diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index d14cd5f209..f62ae8801c 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -325,11 +325,11 @@ enum class TextureQueryType : u64 { enum class TextureProcessMode : u64 { None = 0, - LZ = 1, // Unknown, appears to be the same as none. + LZ = 1, // Load LOD of zero. LB = 2, // Load Bias. - LL = 3, // Load LOD (LevelOfDetail) - LBA = 6, // Load Bias. The A is unknown, does not appear to differ with LB - LLA = 7 // Load LOD. The A is unknown, does not appear to differ with LL + LL = 3, // Load LOD. + LBA = 6, // Load Bias. The A is unknown, does not appear to differ with LB. + LLA = 7 // Load LOD. The A is unknown, does not appear to differ with LL. }; enum class TextureMiscMode : u64 { diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 72ff6ac6af..11d1169f09 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -5,7 +5,9 @@ #include #include #include +#include #include +#include #include @@ -717,7 +719,7 @@ private: } std::string GenerateTexture(Operation operation, const std::string& func, - bool is_extra_int = false) { + const std::vector>& extras) { constexpr std::array coord_constructors = {"float", "vec2", "vec3", "vec4"}; const auto meta = std::get_if(&operation.GetMeta()); @@ -738,36 +740,47 @@ private: expr += Visit(operation[i]); const std::size_t next = i + 1; - if (next < count || has_array || has_shadow) + if (next < count) expr += ", "; } if (has_array) { - expr += "float(ftoi(" + Visit(meta->array) + "))"; + expr += ", float(ftoi(" + Visit(meta->array) + "))"; } if (has_shadow) { - if (has_array) - expr += ", "; - expr += Visit(meta->depth_compare); + expr += ", " + Visit(meta->depth_compare); } expr += ')'; - for (const Node extra : meta->extras) { + for (const auto& extra_pair : extras) { + const auto [type, operand] = extra_pair; + if (operand == nullptr) { + continue; + } expr += ", "; - if (is_extra_int) { - if (const auto immediate = std::get_if(extra)) { + + switch (type) { + case Type::Int: + if (const auto immediate = std::get_if(operand)) { // Inline the string as an immediate integer in GLSL (some extra arguments are // required to be constant) expr += std::to_string(static_cast(immediate->GetValue())); } else { - expr += "ftoi(" + Visit(extra) + ')'; + expr += "ftoi(" + Visit(operand) + ')'; } - } else { - expr += Visit(extra); + break; + case Type::Float: + expr += Visit(operand); + break; + default: { + const auto type_int = static_cast(type); + UNIMPLEMENTED_MSG("Unimplemented extra type={}", type_int); + expr += '0'; + break; + } } } - expr += ')'; - return expr; + return expr + ')'; } std::string Assign(Operation operation) { @@ -1146,7 +1159,7 @@ private: const auto meta = std::get_if(&operation.GetMeta()); ASSERT(meta); - std::string expr = GenerateTexture(operation, "texture"); + std::string expr = GenerateTexture(operation, "texture", {{Type::Float, meta->bias}}); if (meta->sampler.IsShadow()) { expr = "vec4(" + expr + ')'; } @@ -1157,7 +1170,7 @@ private: const auto meta = std::get_if(&operation.GetMeta()); ASSERT(meta); - std::string expr = GenerateTexture(operation, "textureLod"); + std::string expr = GenerateTexture(operation, "textureLod", {{Type::Float, meta->lod}}); if (meta->sampler.IsShadow()) { expr = "vec4(" + expr + ')'; } @@ -1168,7 +1181,8 @@ private: const auto meta = std::get_if(&operation.GetMeta()); ASSERT(meta); - return GenerateTexture(operation, "textureGather", !meta->sampler.IsShadow()) + + const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int; + return GenerateTexture(operation, "textureGather", {{type, meta->component}}) + GetSwizzle(meta->element); } @@ -1197,8 +1211,8 @@ private: ASSERT(meta); if (meta->element < 2) { - return "itof(int((" + GenerateTexture(operation, "textureQueryLod") + " * vec2(256))" + - GetSwizzle(meta->element) + "))"; + return "itof(int((" + GenerateTexture(operation, "textureQueryLod", {}) + + " * vec2(256))" + GetSwizzle(meta->element) + "))"; } return "0"; } @@ -1224,9 +1238,9 @@ private: else if (next < count) expr += ", "; } - for (std::size_t i = 0; i < meta->extras.size(); ++i) { + if (meta->lod) { expr += ", "; - expr += CastOperand(Visit(meta->extras.at(i)), Type::Int); + expr += CastOperand(Visit(meta->lod), Type::Int); } expr += ')'; diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp index 50e2d0584f..a99ae19bfd 100644 --- a/src/video_core/shader/decode/texture.cpp +++ b/src/video_core/shader/decode/texture.cpp @@ -119,8 +119,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { coords.push_back(op_a); coords.push_back(op_b); } - std::vector extras; - extras.push_back(Immediate(static_cast(instr.tld4s.component))); + const Node component = Immediate(static_cast(instr.tld4s.component)); const auto& sampler = GetSampler(instr.sampler, TextureType::Texture2D, false, depth_compare); @@ -128,7 +127,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, {}, {}, extras, element}; + MetaTexture meta{sampler, {}, {}, {}, {}, component, element}; values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); } @@ -153,7 +152,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)); SetTemporal(bb, indexer++, value); @@ -203,7 +202,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) { for (u32 element = 0; element < 2; ++element) { auto params = coords; - MetaTexture meta{sampler, {}, {}, {}, element}; + MetaTexture meta{sampler, {}, {}, {}, {}, {}, element}; const Node value = Operation(OperationCode::TextureQueryLod, meta, std::move(params)); SetTemporal(bb, element, value); } @@ -347,25 +346,35 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type, (texture_type == Tegra::Shader::TextureType::TextureCube && is_array && is_shadow)); const OperationCode read_method = - lod_needed && gl_lod_supported ? OperationCode::TextureLod : OperationCode::Texture; + (lod_needed && gl_lod_supported) ? OperationCode::TextureLod : OperationCode::Texture; UNIMPLEMENTED_IF(process_mode != TextureProcessMode::None && !gl_lod_supported); - std::vector extras; + Node bias = {}; + Node lod = {}; if (process_mode != TextureProcessMode::None && gl_lod_supported) { - if (process_mode == TextureProcessMode::LZ) { - extras.push_back(Immediate(0.0f)); - } else { + switch (process_mode) { + case TextureProcessMode::LZ: + lod = Immediate(0.0f); + break; + case TextureProcessMode::LB: // If present, lod or bias are always stored in the register indexed by the gpr20 // field with an offset depending on the usage of the other registers - extras.push_back(GetRegister(instr.gpr20.Value() + bias_offset)); + bias = GetRegister(instr.gpr20.Value() + bias_offset); + break; + case TextureProcessMode::LL: + lod = GetRegister(instr.gpr20.Value() + bias_offset); + break; + default: + UNIMPLEMENTED_MSG("Unimplemented process mode={}", static_cast(process_mode)); + break; } } Node4 values; for (u32 element = 0; element < values.size(); ++element) { auto copy_coords = coords; - MetaTexture meta{sampler, array, depth_compare, extras, element}; + MetaTexture meta{sampler, array, depth_compare, bias, lod, {}, element}; values[element] = Operation(read_method, meta, std::move(copy_coords)); } @@ -462,7 +471,7 @@ Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool de Node4 values; for (u32 element = 0; element < values.size(); ++element) { auto coords_copy = coords; - MetaTexture meta{sampler, GetRegister(array_register), {}, {}, element}; + MetaTexture meta{sampler, GetRegister(array_register), {}, {}, {}, {}, element}; values[element] = Operation(OperationCode::TextureGather, meta, std::move(coords_copy)); } @@ -498,7 +507,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/shader_ir.h b/src/video_core/shader/shader_ir.h index 0548c46f0c..5bc3a39004 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -290,7 +290,9 @@ struct MetaTexture { const Sampler& sampler; Node array{}; Node depth_compare{}; - std::vector extras; + Node bias{}; + Node lod{}; + Node component{}; u32 element{}; };