summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-04-10 01:26:15 -0400
committerGravatar bunnei2018-04-17 16:36:38 -0400
commit8b4443c966c1f00ca468f41584b74fe22a4580af (patch)
tree361d7f72d11b7deb442f749f57bb3d35d616c7ac /src
parentgl_shader_decompiler: Use fragment output color for GPR 0-3. (diff)
downloadyuzu-8b4443c966c1f00ca468f41584b74fe22a4580af.tar.gz
yuzu-8b4443c966c1f00ca468f41584b74fe22a4580af.tar.xz
yuzu-8b4443c966c1f00ca468f41584b74fe22a4580af.zip
gl_shader_decompiler: Add support for TEXS instruction.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h19
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp36
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 eff0c35a1..51cf4af9f 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -16,10 +16,6 @@ struct Register {
16 16
17 constexpr Register(u64 value) : value(value) {} 17 constexpr Register(u64 value) : value(value) {}
18 18
19 constexpr u64 GetIndex() const {
20 return value;
21 }
22
23 constexpr operator u64() const { 19 constexpr operator u64() const {
24 return value; 20 return value;
25 } 21 }
@@ -71,6 +67,19 @@ union Attribute {
71 u64 value; 67 u64 value;
72}; 68};
73 69
70union Sampler {
71 Sampler() = default;
72
73 constexpr Sampler(u64 value) : value(value) {}
74
75 enum class Index : u64 {
76 Sampler_0 = 8,
77 };
78
79 BitField<36, 13, Index> index;
80 u64 value;
81};
82
74union Uniform { 83union Uniform {
75 BitField<20, 14, u64> offset; 84 BitField<20, 14, u64> offset;
76 BitField<34, 5, u64> index; 85 BitField<34, 5, u64> index;
@@ -295,7 +304,6 @@ union Instruction {
295 BitField<20, 8, Register> gpr20; 304 BitField<20, 8, Register> gpr20;
296 BitField<20, 7, SubOp> sub_op; 305 BitField<20, 7, SubOp> sub_op;
297 BitField<28, 8, Register> gpr28; 306 BitField<28, 8, Register> gpr28;
298 BitField<36, 13, u64> imm36;
299 BitField<39, 8, Register> gpr39; 307 BitField<39, 8, Register> gpr39;
300 308
301 union { 309 union {
@@ -316,6 +324,7 @@ union Instruction {
316 324
317 Attribute attribute; 325 Attribute attribute;
318 Uniform uniform; 326 Uniform uniform;
327 Sampler sampler;
319 328
320 u64 hex; 329 u64 hex;
321}; 330};
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index ba3aa7dd1..a8f1ac5b5 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;
17using Tegra::Shader::Instruction; 17using Tegra::Shader::Instruction;
18using Tegra::Shader::OpCode; 18using Tegra::Shader::OpCode;
19using Tegra::Shader::Register; 19using Tegra::Shader::Register;
20using Tegra::Shader::Sampler;
20using Tegra::Shader::SubOp; 21using Tegra::Shader::SubOp;
21using Tegra::Shader::Uniform; 22using Tegra::Shader::Uniform;
22 23
@@ -186,13 +187,13 @@ private:
186 } 187 }
187 188
188 /// Generates code representing a temporary (GPR) register. 189 /// Generates code representing a temporary (GPR) register.
189 std::string GetRegister(const Register& reg) { 190 std::string GetRegister(const Register& reg, unsigned elem = 0) {
190 if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg.GetIndex() < 4) { 191 if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg < 4) {
191 // GPRs 0-3 are output color for the fragment shader 192 // GPRs 0-3 are output color for the fragment shader
192 return std::string{"color."} + "rgba"[reg.GetIndex()]; 193 return std::string{"color."} + "rgba"[reg + elem];
193 } 194 }
194 195
195 return *declr_register.insert("register_" + std::to_string(reg)).first; 196 return *declr_register.insert("register_" + std::to_string(reg + elem)).first;
196 } 197 }
197 198
198 /// Generates code representing a uniform (C buffer) register. 199 /// Generates code representing a uniform (C buffer) register.
@@ -201,6 +202,15 @@ private:
201 return 'c' + std::to_string(reg.index) + '[' + std::to_string(reg.offset) + ']'; 202 return 'c' + std::to_string(reg.index) + '[' + std::to_string(reg.offset) + ']';
202 } 203 }
203 204
205 /// Generates code representing a texture sampler.
206 std::string GetSampler(const Sampler& sampler) const {
207 // TODO(Subv): Support more than just texture sampler 0
208 ASSERT_MSG(sampler.index == Sampler::Index::Sampler_0, "unsupported");
209 const unsigned index{static_cast<unsigned>(sampler.index.Value()) -
210 static_cast<unsigned>(Sampler::Index::Sampler_0)};
211 return "tex[" + std::to_string(index) + "]";
212 }
213
204 /** 214 /**
205 * Adds code that calls a subroutine. 215 * Adds code that calls a subroutine.
206 * @param subroutine the subroutine to call. 216 * @param subroutine the subroutine to call.
@@ -245,7 +255,7 @@ private:
245 255
246 switch (OpCode::GetInfo(instr.opcode).type) { 256 switch (OpCode::GetInfo(instr.opcode).type) {
247 case OpCode::Type::Arithmetic: { 257 case OpCode::Type::Arithmetic: {
248 ASSERT(!instr.alu.abs_d); 258 ASSERT_MSG(!instr.alu.abs_d, "unimplemented");
249 259
250 std::string dest = GetRegister(instr.gpr0); 260 std::string dest = GetRegister(instr.gpr0);
251 std::string op_a = instr.alu.negate_a ? "-" : ""; 261 std::string op_a = instr.alu.negate_a ? "-" : "";
@@ -330,15 +340,27 @@ private:
330 340
331 switch (instr.opcode.EffectiveOpCode()) { 341 switch (instr.opcode.EffectiveOpCode()) {
332 case OpCode::Id::LD_A: { 342 case OpCode::Id::LD_A: {
333 ASSERT(instr.attribute.fmt20.size == 0); 343 ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
334 SetDest(instr.attribute.fmt20.element, gpr0, GetInputAttribute(attribute), 1, 4); 344 SetDest(instr.attribute.fmt20.element, gpr0, GetInputAttribute(attribute), 1, 4);
335 break; 345 break;
336 } 346 }
337 case OpCode::Id::ST_A: { 347 case OpCode::Id::ST_A: {
338 ASSERT(instr.attribute.fmt20.size == 0); 348 ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
339 SetDest(instr.attribute.fmt20.element, GetOutputAttribute(attribute), gpr0, 4, 1); 349 SetDest(instr.attribute.fmt20.element, GetOutputAttribute(attribute), gpr0, 4, 1);
340 break; 350 break;
341 } 351 }
352 case OpCode::Id::TEXS: {
353 ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested");
354 const std::string op_a = GetRegister(instr.gpr8);
355 const std::string op_b = GetRegister(instr.gpr20);
356 const std::string sampler = GetSampler(instr.sampler);
357 const std::string coord = "vec2(" + op_a + ", " + op_b + ")";
358 const std::string texture = "texture(" + sampler + ", " + coord + ")";
359 for (unsigned elem = 0; elem < instr.attribute.fmt20.size; ++elem) {
360 SetDest(elem, GetRegister(instr.gpr0, elem), texture, 1, 4);
361 }
362 break;
363 }
342 default: { 364 default: {
343 LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: 0x%02x (%s): 0x%08x", 365 LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: 0x%02x (%s): 0x%08x",
344 static_cast<unsigned>(instr.opcode.EffectiveOpCode()), 366 static_cast<unsigned>(instr.opcode.EffectiveOpCode()),