summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2018-06-03 12:05:38 -0400
committerGravatar GitHub2018-06-03 12:05:38 -0400
commitbb9d39b8fe89c7619ffbca2a0a6ecae1eb3f4595 (patch)
treed75cdd5f1f50dc9e32e0ca28e167c1680f8f75d8
parentMerge pull request #495 from bunnei/improve-rro (diff)
parentgl_shader_decompiler: Implement TEX instruction. (diff)
downloadyuzu-bb9d39b8fe89c7619ffbca2a0a6ecae1eb3f4595.tar.gz
yuzu-bb9d39b8fe89c7619ffbca2a0a6ecae1eb3f4595.tar.xz
yuzu-bb9d39b8fe89c7619ffbca2a0a6ecae1eb3f4595.zip
Merge pull request #494 from bunnei/shader-tex
gl_shader_decompiler: Implement TEX, fixes for TEXS.
Diffstat (limited to '')
-rw-r--r--src/video_core/engines/shader_bytecode.h15
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp45
2 files changed, 58 insertions, 2 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 26c891356..fd4e0746e 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -261,6 +261,19 @@ union Instruction {
261 BitField<50, 1, u64> saturate_a; 261 BitField<50, 1, u64> saturate_a;
262 } conversion; 262 } conversion;
263 263
264 union {
265 BitField<31, 4, u64> component_mask;
266
267 bool IsComponentEnabled(size_t component) const {
268 return ((1 << component) & component_mask) != 0;
269 }
270 } tex;
271
272 union {
273 // TODO(bunnei): This is just a guess, needs to be verified
274 BitField<52, 1, u64> enable_g_component;
275 } texs;
276
264 BitField<61, 1, u64> is_b_imm; 277 BitField<61, 1, u64> is_b_imm;
265 BitField<60, 1, u64> is_b_gpr; 278 BitField<60, 1, u64> is_b_gpr;
266 BitField<59, 1, u64> is_c_gpr; 279 BitField<59, 1, u64> is_c_gpr;
@@ -281,6 +294,7 @@ public:
281 KIL, 294 KIL,
282 LD_A, 295 LD_A,
283 ST_A, 296 ST_A,
297 TEX,
284 TEXQ, // Texture Query 298 TEXQ, // Texture Query
285 TEXS, // Texture Fetch with scalar/non-vec4 source/destinations 299 TEXS, // Texture Fetch with scalar/non-vec4 source/destinations
286 TLDS, // Texture Load with scalar/non-vec4 source/destinations 300 TLDS, // Texture Load with scalar/non-vec4 source/destinations
@@ -444,6 +458,7 @@ private:
444 INST("111000110011----", Id::KIL, Type::Flow, "KIL"), 458 INST("111000110011----", Id::KIL, Type::Flow, "KIL"),
445 INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), 459 INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"),
446 INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"), 460 INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"),
461 INST("1100000000111---", Id::TEX, Type::Memory, "TEX"),
447 INST("1101111101001---", Id::TEXQ, Type::Memory, "TEXQ"), 462 INST("1101111101001---", Id::TEXQ, Type::Memory, "TEXQ"),
448 INST("1101100---------", Id::TEXS, Type::Memory, "TEXS"), 463 INST("1101100---------", Id::TEXS, Type::Memory, "TEXS"),
449 INST("1101101---------", Id::TLDS, Type::Memory, "TLDS"), 464 INST("1101101---------", Id::TLDS, Type::Memory, "TLDS"),
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index cb4b68b26..86d880dfc 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -896,6 +896,32 @@ private:
896 instr.gpr0); 896 instr.gpr0);
897 break; 897 break;
898 } 898 }
899 case OpCode::Id::TEX: {
900 ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested");
901 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
902 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
903 const std::string sampler = GetSampler(instr.sampler);
904 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
905 // Add an extra scope and declare the texture coords inside to prevent overwriting
906 // them in case they are used as outputs of the texs instruction.
907 shader.AddLine("{");
908 ++shader.scope;
909 shader.AddLine(coord);
910 const std::string texture = "texture(" + sampler + ", coords)";
911
912 size_t dest_elem{};
913 for (size_t elem = 0; elem < instr.attribute.fmt20.size; ++elem) {
914 if (!instr.tex.IsComponentEnabled(elem)) {
915 // Skip disabled components
916 continue;
917 }
918 regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem);
919 ++dest_elem;
920 }
921 --shader.scope;
922 shader.AddLine("}");
923 break;
924 }
899 case OpCode::Id::TEXS: { 925 case OpCode::Id::TEXS: {
900 ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested"); 926 ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested");
901 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 927 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
@@ -908,8 +934,23 @@ private:
908 ++shader.scope; 934 ++shader.scope;
909 shader.AddLine(coord); 935 shader.AddLine(coord);
910 const std::string texture = "texture(" + sampler + ", coords)"; 936 const std::string texture = "texture(" + sampler + ", coords)";
911 for (unsigned elem = 0; elem < instr.attribute.fmt20.size; ++elem) { 937
912 regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, elem); 938 // TEXS has two destination registers. RG goes into gpr0+0 and gpr0+1, and BA goes
939 // into gpr28+0 and gpr28+1
940 size_t offset{};
941 for (const auto& dest : {instr.gpr0.Value(), instr.gpr28.Value()}) {
942 for (unsigned elem = 0; elem < 2; ++elem) {
943 if (dest + elem >= Register::ZeroIndex) {
944 // Skip invalid register values
945 break;
946 }
947 regs.SetRegisterToFloat(dest, elem + offset, texture, 1, 4, false, elem);
948 if (!instr.texs.enable_g_component) {
949 // Skip the second component
950 break;
951 }
952 }
953 offset += 2;
913 } 954 }
914 --shader.scope; 955 --shader.scope;
915 shader.AddLine("}"); 956 shader.AddLine("}");