From 8b4443c966c1f00ca468f41584b74fe22a4580af Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 10 Apr 2018 01:26:15 -0400 Subject: [PATCH] gl_shader_decompiler: Add support for TEXS instruction. --- src/video_core/engines/shader_bytecode.h | 19 +++++++--- .../renderer_opengl/gl_shader_decompiler.cpp | 36 +++++++++++++++---- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index eff0c35a15..51cf4af9f6 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -16,10 +16,6 @@ struct Register { constexpr Register(u64 value) : value(value) {} - constexpr u64 GetIndex() const { - return value; - } - constexpr operator u64() const { return value; } @@ -71,6 +67,19 @@ union Attribute { u64 value; }; +union Sampler { + Sampler() = default; + + constexpr Sampler(u64 value) : value(value) {} + + enum class Index : u64 { + Sampler_0 = 8, + }; + + BitField<36, 13, Index> index; + u64 value; +}; + union Uniform { BitField<20, 14, u64> offset; BitField<34, 5, u64> index; @@ -295,7 +304,6 @@ union Instruction { BitField<20, 8, Register> gpr20; BitField<20, 7, SubOp> sub_op; BitField<28, 8, Register> gpr28; - BitField<36, 13, u64> imm36; BitField<39, 8, Register> gpr39; union { @@ -316,6 +324,7 @@ union Instruction { Attribute attribute; Uniform uniform; + Sampler sampler; u64 hex; }; diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index ba3aa7dd17..a8f1ac5b56 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -17,6 +17,7 @@ using Tegra::Shader::Attribute; using Tegra::Shader::Instruction; using Tegra::Shader::OpCode; using Tegra::Shader::Register; +using Tegra::Shader::Sampler; using Tegra::Shader::SubOp; using Tegra::Shader::Uniform; @@ -186,13 +187,13 @@ private: } /// Generates code representing a temporary (GPR) register. - std::string GetRegister(const Register& reg) { - if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg.GetIndex() < 4) { + std::string GetRegister(const Register& reg, unsigned elem = 0) { + if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg < 4) { // GPRs 0-3 are output color for the fragment shader - return std::string{"color."} + "rgba"[reg.GetIndex()]; + return std::string{"color."} + "rgba"[reg + elem]; } - return *declr_register.insert("register_" + std::to_string(reg)).first; + return *declr_register.insert("register_" + std::to_string(reg + elem)).first; } /// Generates code representing a uniform (C buffer) register. @@ -201,6 +202,15 @@ private: return 'c' + std::to_string(reg.index) + '[' + std::to_string(reg.offset) + ']'; } + /// Generates code representing a texture sampler. + std::string GetSampler(const Sampler& sampler) const { + // TODO(Subv): Support more than just texture sampler 0 + ASSERT_MSG(sampler.index == Sampler::Index::Sampler_0, "unsupported"); + const unsigned index{static_cast(sampler.index.Value()) - + static_cast(Sampler::Index::Sampler_0)}; + return "tex[" + std::to_string(index) + "]"; + } + /** * Adds code that calls a subroutine. * @param subroutine the subroutine to call. @@ -245,7 +255,7 @@ private: switch (OpCode::GetInfo(instr.opcode).type) { case OpCode::Type::Arithmetic: { - ASSERT(!instr.alu.abs_d); + ASSERT_MSG(!instr.alu.abs_d, "unimplemented"); std::string dest = GetRegister(instr.gpr0); std::string op_a = instr.alu.negate_a ? "-" : ""; @@ -330,15 +340,27 @@ private: switch (instr.opcode.EffectiveOpCode()) { case OpCode::Id::LD_A: { - ASSERT(instr.attribute.fmt20.size == 0); + ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested"); SetDest(instr.attribute.fmt20.element, gpr0, GetInputAttribute(attribute), 1, 4); break; } case OpCode::Id::ST_A: { - ASSERT(instr.attribute.fmt20.size == 0); + ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested"); SetDest(instr.attribute.fmt20.element, GetOutputAttribute(attribute), gpr0, 4, 1); break; } + case OpCode::Id::TEXS: { + ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested"); + const std::string op_a = GetRegister(instr.gpr8); + const std::string op_b = GetRegister(instr.gpr20); + const std::string sampler = GetSampler(instr.sampler); + const std::string coord = "vec2(" + op_a + ", " + op_b + ")"; + const std::string texture = "texture(" + sampler + ", " + coord + ")"; + for (unsigned elem = 0; elem < instr.attribute.fmt20.size; ++elem) { + SetDest(elem, GetRegister(instr.gpr0, elem), texture, 1, 4); + } + break; + } default: { LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: 0x%02x (%s): 0x%08x", static_cast(instr.opcode.EffectiveOpCode()),