From 1e4b6bef6f1b278bdc99170b76f33179a2eff26f Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 3 Jan 2020 18:15:24 -0400 Subject: Shader_IR: Store Bound buffer on Shader Usage --- src/video_core/renderer_opengl/gl_shader_cache.cpp | 4 +++- src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | 12 ++++++++---- src/video_core/renderer_opengl/gl_shader_disk_cache.h | 1 + 3 files changed, 12 insertions(+), 5 deletions(-) (limited to 'src/video_core/renderer_opengl') diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 3c5bdd377..489eb143c 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -214,6 +214,7 @@ std::unique_ptr MakeLocker(Core::System& system, ShaderType s } void FillLocker(ConstBufferLocker& locker, const ShaderDiskCacheUsage& usage) { + locker.SetBoundBuffer(usage.bound_buffer); for (const auto& key : usage.keys) { const auto [buffer, offset] = key.first; locker.InsertKey(buffer, offset, key.second); @@ -418,7 +419,8 @@ bool CachedShader::EnsureValidLockerVariant() { ShaderDiskCacheUsage CachedShader::GetUsage(const ProgramVariant& variant, const ConstBufferLocker& locker) const { - return ShaderDiskCacheUsage{unique_identifier, variant, locker.GetKeys(), + return ShaderDiskCacheUsage{unique_identifier, variant, + locker.GetBoundBuffer(), locker.GetKeys(), locker.GetBoundSamplers(), locker.GetBindlessSamplers()}; } diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp index cf874a09a..1fc204f6f 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp @@ -53,7 +53,7 @@ struct BindlessSamplerKey { Tegra::Engines::SamplerDescriptor sampler{}; }; -constexpr u32 NativeVersion = 11; +constexpr u32 NativeVersion = 12; // Making sure sizes doesn't change by accident static_assert(sizeof(ProgramVariant) == 20); @@ -186,7 +186,8 @@ ShaderDiskCacheOpenGL::LoadTransferable() { u32 num_bound_samplers{}; u32 num_bindless_samplers{}; if (file.ReadArray(&usage.unique_identifier, 1) != 1 || - file.ReadArray(&usage.variant, 1) != 1 || file.ReadArray(&num_keys, 1) != 1 || + file.ReadArray(&usage.variant, 1) != 1 || + file.ReadArray(&usage.bound_buffer, 1) != 1 || file.ReadArray(&num_keys, 1) != 1 || file.ReadArray(&num_bound_samplers, 1) != 1 || file.ReadArray(&num_bindless_samplers, 1) != 1) { LOG_ERROR(Render_OpenGL, error_loading); @@ -281,7 +282,9 @@ ShaderDiskCacheOpenGL::LoadPrecompiledFile(FileUtil::IOFile& file) { u32 num_bindless_samplers{}; ShaderDiskCacheUsage usage; if (!LoadObjectFromPrecompiled(usage.unique_identifier) || - !LoadObjectFromPrecompiled(usage.variant) || !LoadObjectFromPrecompiled(num_keys) || + !LoadObjectFromPrecompiled(usage.variant) || + !LoadObjectFromPrecompiled(usage.bound_buffer) || + !LoadObjectFromPrecompiled(num_keys) || !LoadObjectFromPrecompiled(num_bound_samplers) || !LoadObjectFromPrecompiled(num_bindless_samplers)) { return {}; @@ -393,6 +396,7 @@ void ShaderDiskCacheOpenGL::SaveUsage(const ShaderDiskCacheUsage& usage) { if (file.WriteObject(TransferableEntryKind::Usage) != 1 || file.WriteObject(usage.unique_identifier) != 1 || file.WriteObject(usage.variant) != 1 || + file.WriteObject(usage.bound_buffer) != 1 || file.WriteObject(static_cast(usage.keys.size())) != 1 || file.WriteObject(static_cast(usage.bound_samplers.size())) != 1 || file.WriteObject(static_cast(usage.bindless_samplers.size())) != 1) { @@ -447,7 +451,7 @@ void ShaderDiskCacheOpenGL::SaveDump(const ShaderDiskCacheUsage& usage, GLuint p }; if (!SaveObjectToPrecompiled(usage.unique_identifier) || - !SaveObjectToPrecompiled(usage.variant) || + !SaveObjectToPrecompiled(usage.variant) || !SaveObjectToPrecompiled(usage.bound_buffer) || !SaveObjectToPrecompiled(static_cast(usage.keys.size())) || !SaveObjectToPrecompiled(static_cast(usage.bound_samplers.size())) || !SaveObjectToPrecompiled(static_cast(usage.bindless_samplers.size()))) { diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.h b/src/video_core/renderer_opengl/gl_shader_disk_cache.h index 69a2fbdda..ef2371f6d 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.h @@ -79,6 +79,7 @@ static_assert(std::is_trivially_copyable_v); struct ShaderDiskCacheUsage { u64 unique_identifier{}; ProgramVariant variant; + u32 bound_buffer{}; VideoCommon::Shader::KeyMap keys; VideoCommon::Shader::BoundSamplerMap bound_samplers; VideoCommon::Shader::BindlessSamplerMap bindless_samplers; -- cgit v1.2.3 From 2b02f29a2ddfe40639ea0f855bdf257beca59e65 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 6 Jan 2020 11:43:13 -0400 Subject: GL Backend: Introduce indexed samplers into the GL backend --- src/video_core/renderer_opengl/gl_rasterizer.cpp | 34 +++++++++++++++++----- .../renderer_opengl/gl_shader_decompiler.cpp | 15 ++++++++-- 2 files changed, 39 insertions(+), 10 deletions(-) (limited to 'src/video_core/renderer_opengl') diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c428f06e4..362942e09 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -55,16 +55,20 @@ namespace { template Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, - Tegra::Engines::ShaderType shader_type) { + Tegra::Engines::ShaderType shader_type, + std::size_t index = 0) { if (entry.IsBindless()) { const Tegra::Texture::TextureHandle tex_handle = engine.AccessConstBuffer32(shader_type, entry.GetBuffer(), entry.GetOffset()); return engine.GetTextureInfo(tex_handle); } + const auto& gpu_profile = engine.AccessGuestDriverProfile(); + const u32 offset = + entry.GetOffset() + static_cast(index * gpu_profile.GetTextureHandlerSize()); if constexpr (std::is_same_v) { - return engine.GetStageTexture(shader_type, entry.GetOffset()); + return engine.GetStageTexture(shader_type, offset); } else { - return engine.GetTexture(entry.GetOffset()); + return engine.GetTexture(offset); } } @@ -942,8 +946,15 @@ void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, const Shader& u32 binding = device.GetBaseBindings(stage_index).sampler; for (const auto& entry : shader->GetShaderEntries().samplers) { const auto shader_type = static_cast(stage_index); - const auto texture = GetTextureInfo(maxwell3d, entry, shader_type); - SetupTexture(binding++, texture, entry); + if (!entry.IsIndexed()) { + const auto texture = GetTextureInfo(maxwell3d, entry, shader_type); + SetupTexture(binding++, texture, entry); + } else { + for (std::size_t i = 0; i < entry.Size(); ++i) { + const auto texture = GetTextureInfo(maxwell3d, entry, shader_type, i); + SetupTexture(binding++, texture, entry); + } + } } } @@ -952,8 +963,17 @@ void RasterizerOpenGL::SetupComputeTextures(const Shader& kernel) { const auto& compute = system.GPU().KeplerCompute(); u32 binding = 0; for (const auto& entry : kernel->GetShaderEntries().samplers) { - const auto texture = GetTextureInfo(compute, entry, Tegra::Engines::ShaderType::Compute); - SetupTexture(binding++, texture, entry); + if (!entry.IsIndexed()) { + const auto texture = + GetTextureInfo(compute, entry, Tegra::Engines::ShaderType::Compute); + SetupTexture(binding++, texture, entry); + } else { + for (std::size_t i = 0; i < entry.Size(); ++i) { + const auto texture = + GetTextureInfo(compute, entry, Tegra::Engines::ShaderType::Compute, i); + SetupTexture(binding++, texture, entry); + } + } } } diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 2996aaf08..4b35396f9 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -655,7 +655,8 @@ private: u32 binding = device.GetBaseBindings(stage).sampler; for (const auto& sampler : ir.GetSamplers()) { const std::string name = GetSampler(sampler); - const std::string description = fmt::format("layout (binding = {}) uniform", binding++); + const std::string description = fmt::format("layout (binding = {}) uniform", binding); + binding += sampler.IsIndexed() ? sampler.Size() : 1; std::string sampler_type = [&]() { if (sampler.IsBuffer()) { @@ -682,7 +683,11 @@ private: sampler_type += "Shadow"; } - code.AddLine("{} {} {};", description, sampler_type, name); + if (!sampler.IsIndexed()) { + code.AddLine("{} {} {};", description, sampler_type, name); + } else { + code.AddLine("{} {} {}[{}];", description, sampler_type, name, sampler.Size()); + } } if (!ir.GetSamplers().empty()) { code.AddNewLine(); @@ -1099,7 +1104,11 @@ private: } else if (!meta->ptp.empty()) { expr += "Offsets"; } - expr += '(' + GetSampler(meta->sampler) + ", "; + if (!meta->sampler.IsIndexed()) { + expr += '(' + GetSampler(meta->sampler) + ", "; + } else { + expr += '(' + GetSampler(meta->sampler) + "[0], "; + } expr += coord_constructors.at(count + (has_array ? 1 : 0) + (has_shadow && !separate_dc ? 1 : 0) - 1); expr += '('; -- cgit v1.2.3 From 3c34678627eeb1b48375cf70ec38b72691fedd1e Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 7 Jan 2020 14:53:46 -0400 Subject: Shader_IR: Implement Injectable Custom Variables to the IR. --- .../renderer_opengl/gl_shader_decompiler.cpp | 20 ++++++++++++++++++++ .../renderer_vulkan/vk_shader_decompiler.cpp | 16 ++++++++++++++++ src/video_core/shader/node.h | 17 ++++++++++++++++- src/video_core/shader/shader_ir.cpp | 9 +++++++++ src/video_core/shader/shader_ir.h | 9 +++++++++ 5 files changed, 70 insertions(+), 1 deletion(-) (limited to 'src/video_core/renderer_opengl') diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 4b35396f9..8b413ae9a 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -391,6 +391,7 @@ public: DeclareVertex(); DeclareGeometry(); DeclareRegisters(); + DeclareCustomVariables(); DeclarePredicates(); DeclareLocalMemory(); DeclareInternalFlags(); @@ -503,6 +504,16 @@ private: } } + void DeclareCustomVariables() { + const u32 cv_num = ir.GetCustomVariablesAmount(); + for (u32 i = 0; i < cv_num; ++i) { + code.AddLine("float {} = 0.0f;", GetCustomVariable(i)); + } + if (cv_num > 0) { + code.AddNewLine(); + } + } + void DeclarePredicates() { const auto& predicates = ir.GetPredicates(); for (const auto pred : predicates) { @@ -780,6 +791,11 @@ private: return {GetRegister(index), Type::Float}; } + if (const auto cv = std::get_if(&*node)) { + const u32 index = cv->GetIndex(); + return {GetCustomVariable(index), Type::Float}; + } + if (const auto immediate = std::get_if(&*node)) { const u32 value = immediate->GetValue(); if (value < 10) { @@ -2250,6 +2266,10 @@ private: return GetDeclarationWithSuffix(index, "gpr"); } + std::string GetCustomVariable(u32 index) const { + return GetDeclarationWithSuffix(index, "custom_var"); + } + std::string GetPredicate(Tegra::Shader::Pred pred) const { return GetDeclarationWithSuffix(static_cast(pred), "pred"); } diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index dd6d2ef03..bf797dad3 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -353,6 +353,7 @@ private: DeclareFragment(); DeclareCompute(); DeclareRegisters(); + DeclareCustomVariables(); DeclarePredicates(); DeclareLocalMemory(); DeclareSharedMemory(); @@ -587,6 +588,15 @@ private: } } + void DeclareCustomVariables() { + const u32 cv_num = ir.GetCustomVariablesAmount(); + for (u32 i = 0; i < cv_num; ++i) { + const Id id = OpVariable(t_prv_float, spv::StorageClass::Private, v_float_zero); + Name(id, fmt::format("custom_var_{}", i)); + custom_variables.emplace(i, AddGlobalVariable(id)); + } + } + void DeclarePredicates() { for (const auto pred : ir.GetPredicates()) { const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false); @@ -974,6 +984,11 @@ private: return {OpLoad(t_float, registers.at(index)), Type::Float}; } + if (const auto cv = std::get_if(&*node)) { + const u32 index = cv->GetIndex(); + return {OpLoad(t_float, custom_variables.at(index)), Type::Float}; + } + if (const auto immediate = std::get_if(&*node)) { return {Constant(t_uint, immediate->GetValue()), Type::Uint}; } @@ -2505,6 +2520,7 @@ private: Id out_vertex{}; Id in_vertex{}; std::map registers; + std::map custom_variables; std::map predicates; std::map flow_variables; Id local_memory{}; diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index 2f29b9506..db06767f6 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h @@ -212,6 +212,7 @@ enum class MetaStackClass { class OperationNode; class ConditionalNode; class GprNode; +class CustomVarNode; class ImmediateNode; class InternalFlagNode; class PredicateNode; @@ -223,7 +224,7 @@ class SmemNode; class GmemNode; class CommentNode; -using NodeData = std::variant; using Node = std::shared_ptr; @@ -550,6 +551,20 @@ private: Tegra::Shader::Register index{}; }; +/// A custom variable +class CustomVarNode final { +public: + explicit constexpr CustomVarNode(u32 index) : index{index} {} + + u32 GetIndex() const { + return index; + } + +private: + u32 index{}; +}; + + /// A 32-bits value that represents an immediate value class ImmediateNode final { public: diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index a186e22b2..94972d57f 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -39,6 +39,10 @@ Node ShaderIR::GetRegister(Register reg) { return MakeNode(reg); } +Node ShaderIR::GetCustomVariable(u32 id) { + return MakeNode(id); +} + Node ShaderIR::GetImmediate19(Instruction instr) { return Immediate(instr.alu.GetImm20_19()); } @@ -453,4 +457,9 @@ std::size_t ShaderIR::DeclareAmend(Node new_amend) { return id; } +u32 ShaderIR::NewCustomVariable() { + const u32 id = num_custom_variables++; + return id; +} + } // namespace VideoCommon::Shader diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 121528346..2fe14e815 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -180,6 +180,10 @@ public: return amend_code[index]; } + u32 GetCustomVariablesAmount() const { + return num_custom_variables; + } + private: friend class ASTDecoder; @@ -236,6 +240,8 @@ private: /// Generates a node for a passed register. Node GetRegister(Tegra::Shader::Register reg); + /// Generates a node for a custom variable + Node GetCustomVariable(u32 id); /// Generates a node representing a 19-bit immediate value Node GetImmediate19(Tegra::Shader::Instruction instr); /// Generates a node representing a 32-bit immediate value @@ -403,6 +409,8 @@ private: /// Register new amending code and obtain the reference id. std::size_t DeclareAmend(Node new_amend); + u32 NewCustomVariable(); + const ProgramCode& program_code; const u32 main_offset; const CompilerSettings settings; @@ -418,6 +426,7 @@ private: NodeBlock global_code; ASTManager program_manager{true, true}; std::vector amend_code; + u32 num_custom_variables{}; std::set used_registers; std::set used_predicates; -- cgit v1.2.3 From 7c530e06661d760eb6366724d109468423363072 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 7 Jan 2020 17:45:12 -0400 Subject: Shader_IR: Propagate bindless index into the GL compiler. --- .../renderer_opengl/gl_shader_decompiler.cpp | 2 +- src/video_core/shader/decode/texture.cpp | 40 +++++++++++++--------- src/video_core/shader/node.h | 2 +- src/video_core/shader/shader_ir.h | 5 ++- src/video_core/shader/track.cpp | 29 ++++++++++++++-- 5 files changed, 54 insertions(+), 24 deletions(-) (limited to 'src/video_core/renderer_opengl') diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 8b413ae9a..df681bdcb 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -1123,7 +1123,7 @@ private: if (!meta->sampler.IsIndexed()) { expr += '(' + GetSampler(meta->sampler) + ", "; } else { - expr += '(' + GetSampler(meta->sampler) + "[0], "; + expr += '(' + GetSampler(meta->sampler) + '[' + Visit(meta->index).AsUint() + "], "; } expr += coord_constructors.at(count + (has_array ? 1 : 0) + (has_shadow && !separate_dc ? 1 : 0) - 1); diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index e7c38f5d6..31b09b18c 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp @@ -144,7 +144,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { Node4 values; for (u32 element = 0; element < values.size(); ++element) { auto coords_copy = coords; - MetaTexture meta{sampler, {}, depth_compare, aoffi, {}, {}, {}, {}, component, element}; + MetaTexture meta{sampler, {}, depth_compare, aoffi, {}, {}, + {}, {}, component, element, {}}; values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); } @@ -167,9 +168,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { const auto derivate_reg = instr.gpr20.Value(); const auto texture_type = instr.txd.texture_type.Value(); const auto coord_count = GetCoordCount(texture_type); - + Node index_var{}; const Sampler* sampler = - is_bindless ? GetBindlessSampler(base_reg, {{texture_type, is_array, false}}) + is_bindless ? GetBindlessSampler(base_reg, index_var, {{texture_type, is_array, false}}) : GetSampler(instr.sampler, {{texture_type, is_array, false}}); Node4 values; if (sampler == nullptr) { @@ -200,7 +201,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { } for (u32 element = 0; element < values.size(); ++element) { - MetaTexture meta{*sampler, array_node, {}, {}, {}, derivates, {}, {}, {}, element}; + MetaTexture meta{*sampler, array_node, {}, {}, {}, derivates, {}, {}, {}, element, index_var}; values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); } @@ -215,8 +216,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { // TODO: The new commits on the texture refactor, change the way samplers work. // Sadly, not all texture instructions specify the type of texture their sampler // uses. This must be fixed at a later instance. + Node index_var{}; const Sampler* sampler = - is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler); + is_bindless ? GetBindlessSampler(instr.gpr8, index_var) : GetSampler(instr.sampler); if (sampler == nullptr) { u32 indexer = 0; @@ -240,7 +242,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { if (!instr.txq.IsComponentEnabled(element)) { continue; } - MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element}; + MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element, index_var}; const Node value = Operation(OperationCode::TextureQueryDimensions, meta, GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); @@ -266,8 +268,9 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { auto texture_type = instr.tmml.texture_type.Value(); const bool is_array = instr.tmml.array != 0; + Node index_var{}; const Sampler* sampler = - is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler); + is_bindless ? GetBindlessSampler(instr.gpr20, index_var) : GetSampler(instr.sampler); if (sampler == nullptr) { u32 indexer = 0; @@ -309,7 +312,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { continue; } auto params = coords; - MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element}; + MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, {}, element, index_var}; const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); SetTemporary(bb, indexer++, value); } @@ -386,7 +389,7 @@ const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, info.is_buffer, false); } -const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, +const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, Node& index_var, std::optional sampler_info) { const Node sampler_register = GetRegister(reg); const auto [base_node, tracked_sampler_info] = @@ -421,6 +424,7 @@ const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, } else if (const auto array_sampler_info = std::get_if(&*tracked_sampler_info)) { const u32 base_offset = array_sampler_info->GetBaseOffset() / 4; + index_var = GetCustomVariable(array_sampler_info->GetIndexVar()); const auto info = GetSamplerInfo(sampler_info, base_offset); // If this sampler has already been used, return the existing mapping. @@ -526,8 +530,9 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, "This method is not supported."); const SamplerInfo info{texture_type, is_array, is_shadow, false}; - const Sampler* sampler = - is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info); + Node index_var{}; + const Sampler* sampler = is_bindless ? GetBindlessSampler(*bindless_reg, index_var, info) + : GetSampler(instr.sampler, info); Node4 values; if (sampler == nullptr) { for (u32 element = 0; element < values.size(); ++element) { @@ -575,7 +580,8 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, for (u32 element = 0; element < values.size(); ++element) { auto copy_coords = coords; - MetaTexture meta{*sampler, array, depth_compare, aoffi, {}, {}, bias, lod, {}, element}; + MetaTexture meta{*sampler, array, depth_compare, aoffi, {}, {}, bias, + lod, {}, element, index_var}; values[element] = Operation(read_method, meta, std::move(copy_coords)); } @@ -690,7 +696,8 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de u64 parameter_register = instr.gpr20.Value(); const SamplerInfo info{texture_type, is_array, depth_compare, false}; - const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, info) + Node index_var{}; + const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, index_var, info) : GetSampler(instr.sampler, info); Node4 values; if (sampler == nullptr) { @@ -719,7 +726,8 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de for (u32 element = 0; element < values.size(); ++element) { auto coords_copy = coords; MetaTexture meta{ - *sampler, GetRegister(array_register), dc, aoffi, ptp, {}, {}, {}, component, element}; + *sampler, GetRegister(array_register), dc, aoffi, ptp, {}, {}, {}, component, element, + index_var}; values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); } @@ -752,7 +760,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { Node4 values; for (u32 element = 0; element < values.size(); ++element) { auto coords_copy = coords; - MetaTexture meta{sampler, array_register, {}, {}, {}, {}, {}, lod, {}, element}; + MetaTexture meta{sampler, array_register, {}, {}, {}, {}, {}, lod, {}, element, {}}; values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); } @@ -802,7 +810,7 @@ Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is Node4 values; for (u32 element = 0; element < values.size(); ++element) { auto coords_copy = coords; - MetaTexture meta{sampler, array, {}, {}, {}, {}, {}, lod, {}, element}; + MetaTexture meta{sampler, array, {}, {}, {}, {}, {}, lod, {}, element, {}}; values[element] = Operation(OperationCode::TexelFetch, meta, std::move(coords_copy)); } return values; diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index db06767f6..d75453458 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h @@ -445,6 +445,7 @@ struct MetaTexture { Node lod; Node component{}; u32 element{}; + Node index{}; }; struct MetaImage { @@ -564,7 +565,6 @@ private: u32 index{}; }; - /// A 32-bits value that represents an immediate value class ImmediateNode final { public: diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 2fe14e815..0421dac0c 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -328,7 +328,7 @@ private: std::optional sampler_info = std::nullopt); /// Accesses a texture sampler for a bindless texture. - const Sampler* GetBindlessSampler(Tegra::Shader::Register reg, + const Sampler* GetBindlessSampler(Tegra::Shader::Register reg, Node& index_var, std::optional sampler_info = std::nullopt); /// Accesses an image. @@ -394,8 +394,7 @@ private: std::tuple TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const; - std::tuple TrackSampler(Node tracked, const NodeBlock& code, - s64 cursor) const; + std::tuple TrackSampler(Node tracked, const NodeBlock& code, s64 cursor); std::optional TrackImmediate(Node tracked, const NodeBlock& code, s64 cursor) const; diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp index 69a677394..d449b625e 100644 --- a/src/video_core/shader/track.cpp +++ b/src/video_core/shader/track.cpp @@ -61,8 +61,19 @@ std::optional> DecoupleIndirectRead(const OperationNode& o return std::nullopt; } +bool AmendNodeCv(std::size_t amend_index, Node node) { + if (const auto operation = std::get_if(&*node)) { + operation->SetAmendIndex(amend_index); + return true; + } else if (const auto conditional = std::get_if(&*node)) { + conditional->SetAmendIndex(amend_index); + return true; + } + return false; +} + std::tuple ShaderIR::TrackSampler(Node tracked, const NodeBlock& code, - s64 cursor) const { + s64 cursor) { if (const auto cbuf = std::get_if(&*tracked)) { // Constant buffer found, test if it's an immediate const auto offset = cbuf->GetOffset(); @@ -84,9 +95,21 @@ std::tuple ShaderIR::TrackSampler(Node tracked, const NodeBl } auto [gpr, base_offset] = *pair; const auto offset_inm = std::get_if(&*base_offset); + auto gpu_driver = locker.AccessGuestDriverProfile(); + if (gpu_driver == nullptr) { + return {}; + } + const u32 bindless_cv = NewCustomVariable(); + const Node op = Operation(OperationCode::UDiv, NO_PRECISE, gpr, + Immediate(gpu_driver->GetTextureHandlerSize())); + + const Node cv_node = GetCustomVariable(bindless_cv); + Node amend_op = Operation(OperationCode::Assign, cv_node, std::move(op)); + const std::size_t amend_index = DeclareAmend(amend_op); + AmendNodeCv(amend_index, code[cursor]); // TODO Implement Bindless Index custom variable - auto track = - MakeTrackSampler(cbuf->GetIndex(), offset_inm->GetValue(), 0); + auto track = MakeTrackSampler(cbuf->GetIndex(), + offset_inm->GetValue(), bindless_cv); return {tracked, track}; } return {}; -- cgit v1.2.3 From 37b8504faaeca9aaffd67649f5a026a900743431 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 7 Jan 2020 18:56:03 -0400 Subject: Shader_IR: Correct Custom Variable assignment. --- src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 2 ++ src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src/video_core/renderer_opengl') diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index df681bdcb..2f2bb07a4 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -1336,6 +1336,8 @@ private: const std::string final_offset = fmt::format("({} - {}) >> 2", real, base); target = {fmt::format("{}[{}]", GetGlobalMemory(gmem->GetDescriptor()), final_offset), Type::Uint}; + } else if (const auto cv = std::get_if(&*dest)) { + target = {GetCustomVariable(cv->GetIndex()), Type::Float}; } else { UNREACHABLE_MSG("Assign called without a proper target"); } diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index bf797dad3..130060369 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -1361,6 +1361,8 @@ private: target = {OpAccessChain(t_gmem_float, gmem_buffer, Constant(t_uint, 0), offset), Type::Float}; + } else if (const auto cv = std::get_if(&*dest)) { + target = {custom_variables.at(cv->GetIndex()), Type::Float}; } else { UNIMPLEMENTED(); } -- cgit v1.2.3 From bb8eb15d392d69693f8cda0427669d011e23db97 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 24 Jan 2020 10:44:34 -0400 Subject: Shader_IR: Address feedback. --- src/video_core/guest_driver.h | 1 + .../renderer_opengl/gl_shader_decompiler.cpp | 6 ++--- .../renderer_vulkan/vk_shader_decompiler.cpp | 5 ++-- src/video_core/shader/const_buffer_locker.h | 2 ++ src/video_core/shader/decode.cpp | 31 +++++++++++----------- src/video_core/shader/decode/texture.cpp | 3 ++- src/video_core/shader/node.h | 14 +++++----- src/video_core/shader/shader_ir.cpp | 3 +-- src/video_core/shader/shader_ir.h | 2 +- src/video_core/shader/track.cpp | 9 +++---- 10 files changed, 40 insertions(+), 36 deletions(-) (limited to 'src/video_core/renderer_opengl') diff --git a/src/video_core/guest_driver.h b/src/video_core/guest_driver.h index 0a9a826b6..fc1917347 100644 --- a/src/video_core/guest_driver.h +++ b/src/video_core/guest_driver.h @@ -33,6 +33,7 @@ private: // This goes with Vulkan and OpenGL standards but Nvidia GPUs can easily // use 4 bytes instead. Thus, certain drivers may squish the size. static constexpr u32 default_texture_handler_size = 8; + u32 texture_handler_size = default_texture_handler_size; bool texture_handler_size_deduced = false; }; diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 2f2bb07a4..cb1a5f35c 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -505,11 +505,11 @@ private: } void DeclareCustomVariables() { - const u32 cv_num = ir.GetCustomVariablesAmount(); - for (u32 i = 0; i < cv_num; ++i) { + const u32 num_custom_variables = ir.GetNumCustomVariables(); + for (u32 i = 0; i < num_custom_variables; ++i) { code.AddLine("float {} = 0.0f;", GetCustomVariable(i)); } - if (cv_num > 0) { + if (num_custom_variables > 0) { code.AddNewLine(); } } diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 130060369..36d928fab 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -589,8 +589,8 @@ private: } void DeclareCustomVariables() { - const u32 cv_num = ir.GetCustomVariablesAmount(); - for (u32 i = 0; i < cv_num; ++i) { + const u32 num_custom_variables = ir.GetNumCustomVariables(); + for (u32 i = 0; i < num_custom_variables; ++i) { const Id id = OpVariable(t_prv_float, spv::StorageClass::Private, v_float_zero); Name(id, fmt::format("custom_var_{}", i)); custom_variables.emplace(i, AddGlobalVariable(id)); @@ -1363,6 +1363,7 @@ private: } else if (const auto cv = std::get_if(&*dest)) { target = {custom_variables.at(cv->GetIndex()), Type::Float}; + } else { UNIMPLEMENTED(); } diff --git a/src/video_core/shader/const_buffer_locker.h b/src/video_core/shader/const_buffer_locker.h index fd1bb476a..d3ea11087 100644 --- a/src/video_core/shader/const_buffer_locker.h +++ b/src/video_core/shader/const_buffer_locker.h @@ -77,10 +77,12 @@ public: return bindless_samplers; } + /// Gets bound buffer used on this shader u32 GetBoundBuffer() const { return bound_buffer; } + /// Obtains access to the guest driver's profile. VideoCore::GuestDriverProfile* AccessGuestDriverProfile() const { if (engine) { return &engine->AccessGuestDriverProfile(); diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp index d4a10eee5..6b697ed5d 100644 --- a/src/video_core/shader/decode.cpp +++ b/src/video_core/shader/decode.cpp @@ -35,9 +35,9 @@ constexpr bool IsSchedInstruction(u32 offset, u32 main_offset) { } void DeduceTextureHandlerSize(VideoCore::GuestDriverProfile* gpu_driver, - std::list& used_samplers) { + const std::list& used_samplers) { if (gpu_driver == nullptr) { - LOG_CRITICAL(HW_GPU, "GPU Driver profile has not been created yet"); + LOG_CRITICAL(HW_GPU, "GPU driver profile has not been created yet"); return; } if (gpu_driver->TextureHandlerSizeKnown() || used_samplers.size() <= 1) { @@ -57,9 +57,9 @@ void DeduceTextureHandlerSize(VideoCore::GuestDriverProfile* gpu_driver, } } -std::optional TryDeduceSamplerSize(Sampler& sampler_to_deduce, +std::optional TryDeduceSamplerSize(const Sampler& sampler_to_deduce, VideoCore::GuestDriverProfile* gpu_driver, - std::list& used_samplers) { + const std::list& used_samplers) { if (gpu_driver == nullptr) { LOG_CRITICAL(HW_GPU, "GPU Driver profile has not been created yet"); return std::nullopt; @@ -367,17 +367,18 @@ void ShaderIR::PostDecode() { auto gpu_driver = locker.AccessGuestDriverProfile(); DeduceTextureHandlerSize(gpu_driver, used_samplers); // Deduce Indexed Samplers - if (uses_indexed_samplers) { - for (auto& sampler : used_samplers) { - if (sampler.IsIndexed()) { - auto size = TryDeduceSamplerSize(sampler, gpu_driver, used_samplers); - if (size) { - sampler.SetSize(*size); - } else { - LOG_CRITICAL(HW_GPU, "Failed to deduce size of indexed sampler"); - sampler.SetSize(1); - } - } + if (!uses_indexed_samplers) { + return; + } + for (auto& sampler : used_samplers) { + if (!sampler.IsIndexed()) { + continue; + } + if (const auto size = TryDeduceSamplerSize(sampler, gpu_driver, used_samplers)) { + sampler.SetSize(*size); + } else { + LOG_CRITICAL(HW_GPU, "Failed to deduce size of indexed sampler"); + sampler.SetSize(1); } } } diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index 6da9668fe..d980535b1 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp @@ -201,7 +201,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { } for (u32 element = 0; element < values.size(); ++element) { - MetaTexture meta{*sampler, array_node, {}, {}, {}, derivates, {}, {}, {}, element, index_var}; + MetaTexture meta{*sampler, array_node, {}, {}, {}, derivates, + {}, {}, {}, element, index_var}; values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); } diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index d75453458..53a551d27 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h @@ -291,7 +291,7 @@ public: return size; } - void SetSize(u32 new_size) { + constexpr void SetSize(u32 new_size) { size = new_size; } @@ -315,15 +315,15 @@ public: explicit ArraySamplerNode(u32 index, u32 base_offset, u32 bindless_var) : index{index}, base_offset{base_offset}, bindless_var{bindless_var} {} - u32 GetIndex() const { + constexpr u32 GetIndex() const { return index; } - u32 GetBaseOffset() const { + constexpr u32 GetBaseOffset() const { return base_offset; } - u32 GetIndexVar() const { + constexpr u32 GetIndexVar() const { return bindless_var; } @@ -338,11 +338,11 @@ class BindlessSamplerNode final { public: explicit BindlessSamplerNode(u32 index, u32 offset) : index{index}, offset{offset} {} - u32 GetIndex() const { + constexpr u32 GetIndex() const { return index; } - u32 GetOffset() const { + constexpr u32 GetOffset() const { return offset; } @@ -557,7 +557,7 @@ class CustomVarNode final { public: explicit constexpr CustomVarNode(u32 index) : index{index} {} - u32 GetIndex() const { + constexpr u32 GetIndex() const { return index; } diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 94972d57f..3a5d280a9 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -458,8 +458,7 @@ std::size_t ShaderIR::DeclareAmend(Node new_amend) { } u32 ShaderIR::NewCustomVariable() { - const u32 id = num_custom_variables++; - return id; + return num_custom_variables++; } } // namespace VideoCommon::Shader diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 43672b41c..b0851c3be 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -180,7 +180,7 @@ public: return amend_code[index]; } - u32 GetCustomVariablesAmount() const { + u32 GetNumCustomVariables() const { return num_custom_variables; } diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp index 4db721f69..ea39bca54 100644 --- a/src/video_core/shader/track.cpp +++ b/src/video_core/shader/track.cpp @@ -36,7 +36,6 @@ std::pair FindOperation(const NodeBlock& code, s64 cursor, } return {}; } -} // Anonymous namespace std::optional> DecoupleIndirectRead(const OperationNode& operation) { if (operation.GetCode() != OperationCode::UAdd) { @@ -44,9 +43,7 @@ std::optional> DecoupleIndirectRead(const OperationNode& o } Node gpr{}; Node offset{}; - if (operation.GetOperandsCount() != 2) { - return std::nullopt; - } + ASSERT(operation.GetOperandsCount() == 2); for (std::size_t i = 0; i < operation.GetOperandsCount(); i++) { Node operand = operation[i]; if (std::holds_alternative(*operand)) { @@ -56,7 +53,7 @@ std::optional> DecoupleIndirectRead(const OperationNode& o } } if (offset && gpr) { - return {std::make_pair(gpr, offset)}; + return std::make_pair(gpr, offset); } return std::nullopt; } @@ -72,6 +69,8 @@ bool AmendNodeCv(std::size_t amend_index, Node node) { return false; } +} // Anonymous namespace + std::tuple ShaderIR::TrackBindlessSampler(Node tracked, const NodeBlock& code, s64 cursor) { if (const auto cbuf = std::get_if(&*tracked)) { -- cgit v1.2.3