From 271a3264f33766524224462537685b6e5c691f9d Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 11 Dec 2019 13:07:30 -0400 Subject: [PATCH 1/4] Shader_Ir: default failed tracks on bindless samplers to null values. --- src/video_core/shader/decode/texture.cpp | 97 ++++++++++++++++++------ src/video_core/shader/shader_ir.h | 4 +- 2 files changed, 77 insertions(+), 24 deletions(-) diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index da8e886df2..67926afcbe 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp @@ -129,7 +129,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { const Node component = Immediate(static_cast(instr.tld4s.component)); const SamplerInfo info{TextureType::Texture2D, false, depth_compare}; - const auto& sampler = GetSampler(instr.sampler, info); + const Sampler& sampler = *GetSampler(instr.sampler, info); Node4 values; for (u32 element = 0; element < values.size(); ++element) { @@ -154,9 +154,17 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { const auto texture_type = instr.txd.texture_type.Value(); const auto coord_count = GetCoordCount(texture_type); - const auto& sampler = is_bindless + const Sampler* sampler = is_bindless ? GetBindlessSampler(base_reg, {{texture_type, false, false}}) : GetSampler(instr.sampler, {{texture_type, false, false}}); + Node4 values; + if (sampler == nullptr) { + for (u32 element = 0; element < values.size(); ++element) { + values[element] = Immediate(0); + } + WriteTexInstructionFloat(bb, instr, values); + break; + } if (is_bindless) { base_reg++; } @@ -170,9 +178,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { derivates.push_back(GetRegister(derivate_reg + derivate + 1)); } - Node4 values; for (u32 element = 0; element < values.size(); ++element) { - MetaTexture meta{sampler, {}, {}, {}, derivates, {}, {}, {}, element}; + MetaTexture meta{*sampler, {}, {}, {}, derivates, {}, {}, {}, element}; values[element] = Operation(OperationCode::TextureGradient, std::move(meta), coords); } @@ -187,9 +194,24 @@ 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. - const auto& sampler = + const Sampler* sampler = is_bindless ? GetBindlessSampler(instr.gpr8) : GetSampler(instr.sampler); + if (sampler == nullptr) { + u32 indexer = 0; + for (u32 element = 0; element < 4; ++element) { + if (!instr.txq.IsComponentEnabled(element)) { + continue; + } + const Node value = Immediate(0); + SetTemporary(bb, indexer++, value); + } + for (u32 i = 0; i < indexer; ++i) { + SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i)); + } + break; + } + u32 indexer = 0; switch (instr.txq.query_type) { case Tegra::Shader::TextureQueryType::Dimension: { @@ -197,7 +219,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { if (!instr.txq.IsComponentEnabled(element)) { continue; } - MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element}; + MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, element}; const Node value = Operation(OperationCode::TextureQueryDimensions, meta, GetRegister(instr.gpr8.Value() + (is_bindless ? 1 : 0))); @@ -223,9 +245,24 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { auto texture_type = instr.tmml.texture_type.Value(); const bool is_array = instr.tmml.array != 0; - const auto& sampler = + const Sampler* sampler = is_bindless ? GetBindlessSampler(instr.gpr20) : GetSampler(instr.sampler); + if (sampler == nullptr) { + u32 indexer = 0; + for (u32 element = 0; element < 2; ++element) { + if (!instr.tmml.IsComponentEnabled(element)) { + continue; + } + const Node value = Immediate(0); + SetTemporary(bb, indexer++, value); + } + for (u32 i = 0; i < indexer; ++i) { + SetRegister(bb, instr.gpr0.Value() + i, GetTemporary(i)); + } + break; + } + std::vector coords; // TODO: Add coordinates for different samplers once other texture types are implemented. @@ -251,7 +288,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { continue; } auto params = coords; - MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, {}, element}; + MetaTexture meta{*sampler, {}, {}, {}, {}, {}, {}, {}, element}; const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); SetTemporary(bb, indexer++, value); } @@ -307,7 +344,7 @@ ShaderIR::SamplerInfo ShaderIR::GetSamplerInfo(std::optional sample sampler->is_buffer != 0}; } -const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, +const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, std::optional sampler_info) { const auto offset = static_cast(sampler.index.Value()); const auto info = GetSamplerInfo(sampler_info, offset); @@ -319,21 +356,24 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, if (it != used_samplers.end()) { ASSERT(!it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && it->IsShadow() == info.is_shadow && it->IsBuffer() == info.is_buffer); - return *it; + return &(*it); } // Otherwise create a new mapping for this sampler const auto next_index = static_cast(used_samplers.size()); - return used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow, + return &used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow, info.is_buffer); } -const Sampler& ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, +const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, std::optional sampler_info) { const Node sampler_register = GetRegister(reg); const auto [base_sampler, buffer, offset] = TrackCbuf(sampler_register, global_code, static_cast(global_code.size())); ASSERT(base_sampler != nullptr); + if (base_sampler == nullptr) { + return nullptr; + } const auto info = GetSamplerInfo(sampler_info, offset, buffer); @@ -346,12 +386,12 @@ const Sampler& ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, if (it != used_samplers.end()) { ASSERT(it->IsBindless() && it->GetType() == info.type && it->IsArray() == info.is_array && it->IsShadow() == info.is_shadow); - return *it; + return &(*it); } // Otherwise create a new mapping for this sampler const auto next_index = static_cast(used_samplers.size()); - return used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array, + return &used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array, info.is_shadow, info.is_buffer); } @@ -438,8 +478,15 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, "This method is not supported."); const SamplerInfo info{texture_type, is_array, is_shadow, false}; - const auto& sampler = + const Sampler* sampler = is_bindless ? GetBindlessSampler(*bindless_reg, info) : GetSampler(instr.sampler, info); + Node4 values; + if (sampler == nullptr) { + for (u32 element = 0; element < values.size(); ++element) { + values[element] = Immediate(0); + } + return values; + } const bool lod_needed = process_mode == TextureProcessMode::LZ || process_mode == TextureProcessMode::LL || @@ -478,10 +525,10 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, } } - Node4 values; + 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}; values[element] = Operation(read_method, meta, std::move(copy_coords)); } @@ -594,8 +641,15 @@ 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 auto& sampler = is_bindless ? GetBindlessSampler(parameter_register++, info) + const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, info) : GetSampler(instr.sampler, info); + Node4 values; + if (sampler == nullptr) { + for (u32 element = 0; element < values.size(); ++element) { + values[element] = Immediate(0); + } + return values; + } std::vector aoffi; if (is_aoffi) { @@ -610,10 +664,9 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de const Node component = is_bindless ? Immediate(static_cast(instr.tld4_b.component)) : Immediate(static_cast(instr.tld4.component)); - Node4 values; for (u32 element = 0; element < values.size(); ++element) { auto coords_copy = coords; - MetaTexture meta{sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component, + MetaTexture meta{*sampler, GetRegister(array_register), dc, aoffi, {}, {}, {}, component, element}; values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); } @@ -642,7 +695,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { // const Node aoffi_register{is_aoffi ? GetRegister(gpr20_cursor++) : nullptr}; // const Node multisample{is_multisample ? GetRegister(gpr20_cursor++) : nullptr}; - const auto& sampler = GetSampler(instr.sampler); + const auto& sampler = *GetSampler(instr.sampler); Node4 values; for (u32 element = 0; element < values.size(); ++element) { @@ -655,7 +708,7 @@ Node4 ShaderIR::GetTldCode(Tegra::Shader::Instruction instr) { } Node4 ShaderIR::GetTldsCode(Instruction instr, TextureType texture_type, bool is_array) { - const auto& sampler = GetSampler(instr.sampler); + const Sampler& sampler = *GetSampler(instr.sampler); const std::size_t type_coord_count = GetCoordCount(texture_type); const bool lod_enabled = instr.tlds.GetTextureProcessMode() == TextureProcessMode::LL; diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 580f84fcbd..8324432ae4 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -313,11 +313,11 @@ private: std::optional buffer = std::nullopt); /// Accesses a texture sampler - const Sampler& GetSampler(const Tegra::Shader::Sampler& sampler, + const Sampler* GetSampler(const Tegra::Shader::Sampler& sampler, 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, std::optional sampler_info = std::nullopt); /// Accesses an image. From 84a158c977c5c87880fac13ad48648e1bda3e079 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 11 Dec 2019 16:10:12 -0400 Subject: [PATCH 2/4] Gl_Shader_compiler: Correct Depth Compare for Texture Gather operations. --- .../renderer_opengl/gl_shader_decompiler.cpp | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index fa7049bbe8..45c2d464f1 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -1076,7 +1076,7 @@ private: } std::string GenerateTexture(Operation operation, const std::string& function_suffix, - const std::vector& extras) { + const std::vector& extras, bool sepparate_dc = false) { constexpr std::array coord_constructors = {"float", "vec2", "vec3", "vec4"}; const auto meta = std::get_if(&operation.GetMeta()); @@ -1091,7 +1091,7 @@ private: expr += "Offset"; } expr += '(' + GetSampler(meta->sampler) + ", "; - expr += coord_constructors.at(count + (has_array ? 1 : 0) + (has_shadow ? 1 : 0) - 1); + expr += coord_constructors.at(count + (has_array ? 1 : 0) + (has_shadow && !sepparate_dc ? 1 : 0) - 1); expr += '('; for (std::size_t i = 0; i < count; ++i) { expr += Visit(operation[i]).AsFloat(); @@ -1104,9 +1104,14 @@ private: expr += ", float(" + Visit(meta->array).AsInt() + ')'; } if (has_shadow) { - expr += ", " + Visit(meta->depth_compare).AsFloat(); + if (sepparate_dc) { + expr += "), " + Visit(meta->depth_compare).AsFloat(); + } else { + expr += ", " + Visit(meta->depth_compare).AsFloat() + ')'; + } + } else { + expr += ')'; } - expr += ')'; for (const auto& variant : extras) { if (const auto argument = std::get_if(&variant)) { @@ -1706,10 +1711,18 @@ private: ASSERT(meta); const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int; - return {GenerateTexture(operation, "Gather", - {TextureAoffi{}, TextureArgument{type, meta->component}}) + - GetSwizzle(meta->element), - Type::Float}; + if (meta->sampler.IsShadow()) { + return {GenerateTexture(operation, "Gather", + {TextureAoffi{}}, true) + + GetSwizzle(meta->element), + Type::Float}; + } else { + return {GenerateTexture(operation, "Gather", + {TextureAoffi{}, TextureArgument{type, meta->component}}, + true) + + GetSwizzle(meta->element), + Type::Float}; + } } Expression TextureQueryDimensions(Operation operation) { From af89723fa3d4ca13fc2ce7be545170d093eb4c31 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 11 Dec 2019 18:12:29 -0400 Subject: [PATCH 3/4] Shader_Ir: Correct TLD4S encoding and implement f16 flag. --- src/video_core/engines/shader_bytecode.h | 3 ++- src/video_core/shader/decode/texture.cpp | 21 ++++++++++++--------- src/video_core/shader/shader_ir.h | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 290d929df1..d6a2cc8b8a 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -1292,6 +1292,7 @@ union Instruction { BitField<50, 1, u64> dc_flag; BitField<51, 1, u64> aoffi_flag; BitField<52, 2, u64> component; + BitField<55, 1, u64> fp16_flag; bool UsesMiscMode(TextureMiscMode mode) const { switch (mode) { @@ -1972,7 +1973,7 @@ private: INST("1101-01---------", Id::TLDS, Type::Texture, "TLDS"), INST("110010----111---", Id::TLD4, Type::Texture, "TLD4"), INST("1101111011111---", Id::TLD4_B, Type::Texture, "TLD4_B"), - INST("1101111100------", Id::TLD4S, Type::Texture, "TLD4S"), + INST("11011111--00----", Id::TLD4S, Type::Texture, "TLD4S"), INST("110111110110----", Id::TMML_B, Type::Texture, "TMML_B"), INST("1101111101011---", Id::TMML, Type::Texture, "TMML"), INST("11011110011110--", Id::TXD_B, Type::Texture, "TXD_B"), diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index 67926afcbe..9aef5ddd55 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp @@ -138,7 +138,11 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); } - WriteTexsInstructionFloat(bb, instr, values, true); + if (instr.tld4s.fp16_flag) { + WriteTexsInstructionHalfFloat(bb, instr, values, true); + } else { + WriteTexsInstructionFloat(bb, instr, values, true); + } break; } case OpCode::Id::TXD_B: @@ -155,8 +159,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { const auto coord_count = GetCoordCount(texture_type); const Sampler* sampler = is_bindless - ? GetBindlessSampler(base_reg, {{texture_type, false, false}}) - : GetSampler(instr.sampler, {{texture_type, false, false}}); + ? GetBindlessSampler(base_reg, {{texture_type, false, false}}) + : GetSampler(instr.sampler, {{texture_type, false, false}}); Node4 values; if (sampler == nullptr) { for (u32 element = 0; element < values.size(); ++element) { @@ -362,7 +366,7 @@ const Sampler* ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler, // Otherwise create a new mapping for this sampler const auto next_index = static_cast(used_samplers.size()); return &used_samplers.emplace_back(next_index, offset, info.type, info.is_array, info.is_shadow, - info.is_buffer); + info.is_buffer); } const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, @@ -392,7 +396,7 @@ const Sampler* ShaderIR::GetBindlessSampler(Tegra::Shader::Register reg, // Otherwise create a new mapping for this sampler const auto next_index = static_cast(used_samplers.size()); return &used_samplers.emplace_back(next_index, offset, buffer, info.type, info.is_array, - info.is_shadow, info.is_buffer); + info.is_shadow, info.is_buffer); } void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) { @@ -435,14 +439,14 @@ void ShaderIR::WriteTexsInstructionFloat(NodeBlock& bb, Instruction instr, const } void ShaderIR::WriteTexsInstructionHalfFloat(NodeBlock& bb, Instruction instr, - const Node4& components) { + const Node4& components, bool ignore_mask) { // TEXS.F16 destionation registers are packed in two registers in pairs (just like any half // float instruction). Node4 values; u32 dest_elem = 0; for (u32 component = 0; component < 4; ++component) { - if (!instr.texs.IsComponentEnabled(component)) + if (!instr.texs.IsComponentEnabled(component) && !ignore_mask) continue; values[dest_elem++] = components[component]; } @@ -525,7 +529,6 @@ 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}; @@ -642,7 +645,7 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de const SamplerInfo info{texture_type, is_array, depth_compare, false}; const Sampler* sampler = is_bindless ? GetBindlessSampler(parameter_register++, info) - : GetSampler(instr.sampler, info); + : GetSampler(instr.sampler, info); Node4 values; if (sampler == nullptr) { for (u32 element = 0; element < values.size(); ++element) { diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 8324432ae4..04ae5f8222 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -338,7 +338,7 @@ private: void WriteTexsInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, const Node4& components, bool ignore_mask = false); void WriteTexsInstructionHalfFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, - const Node4& components); + const Node4& components, bool ignore_mask = false); Node4 GetTexCode(Tegra::Shader::Instruction instr, Tegra::Shader::TextureType texture_type, Tegra::Shader::TextureProcessMode process_mode, bool depth_compare, From c0ee0aa1a8266b0f5c5568cf1af3cb6247156720 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 11 Dec 2019 19:43:43 -0400 Subject: [PATCH 4/4] Shader_IR: Correct TLD4S Depth Compare. --- .../renderer_opengl/gl_shader_decompiler.cpp | 8 ++++---- src/video_core/shader/decode/texture.cpp | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 45c2d464f1..d1ae4be6d7 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -1091,7 +1091,8 @@ private: expr += "Offset"; } expr += '(' + GetSampler(meta->sampler) + ", "; - expr += coord_constructors.at(count + (has_array ? 1 : 0) + (has_shadow && !sepparate_dc ? 1 : 0) - 1); + expr += coord_constructors.at(count + (has_array ? 1 : 0) + + (has_shadow && !sepparate_dc ? 1 : 0) - 1); expr += '('; for (std::size_t i = 0; i < count; ++i) { expr += Visit(operation[i]).AsFloat(); @@ -1712,14 +1713,13 @@ private: const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int; if (meta->sampler.IsShadow()) { - return {GenerateTexture(operation, "Gather", - {TextureAoffi{}}, true) + + return {GenerateTexture(operation, "Gather", {TextureAoffi{}}, true) + GetSwizzle(meta->element), Type::Float}; } else { return {GenerateTexture(operation, "Gather", {TextureAoffi{}, TextureArgument{type, meta->component}}, - true) + + false) + GetSwizzle(meta->element), Type::Float}; } diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index 9aef5ddd55..994c05611b 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp @@ -107,8 +107,8 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { break; } case OpCode::Id::TLD4S: { - UNIMPLEMENTED_IF_MSG(instr.tld4s.UsesMiscMode(TextureMiscMode::AOFFI), - "AOFFI is not implemented"); + const bool uses_aoffi = instr.tld4s.UsesMiscMode(TextureMiscMode::AOFFI); + UNIMPLEMENTED_IF_MSG(uses_aoffi, "AOFFI is not implemented"); const bool depth_compare = instr.tld4s.UsesMiscMode(TextureMiscMode::DC); const Node op_a = GetRegister(instr.gpr8); @@ -116,15 +116,22 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. std::vector coords; + Node dc_reg; if (depth_compare) { // Note: TLD4S coordinate encoding works just like TEXS's const Node op_y = GetRegister(instr.gpr8.Value() + 1); coords.push_back(op_a); coords.push_back(op_y); - coords.push_back(op_b); + dc_reg = uses_aoffi ? GetRegister(instr.gpr20.Value() + 1) : op_b; } else { coords.push_back(op_a); - coords.push_back(op_b); + if (uses_aoffi) { + const Node op_y = GetRegister(instr.gpr8.Value() + 1); + coords.push_back(op_y); + } else { + coords.push_back(op_b); + } + dc_reg = {}; } const Node component = Immediate(static_cast(instr.tld4s.component)); @@ -134,7 +141,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { Node4 values; for (u32 element = 0; element < values.size(); ++element) { auto coords_copy = coords; - MetaTexture meta{sampler, {}, {}, {}, {}, {}, {}, component, element}; + MetaTexture meta{sampler, {}, dc_reg, {}, {}, {}, {}, component, element}; values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); }