diff options
| author | 2018-06-03 12:05:38 -0400 | |
|---|---|---|
| committer | 2018-06-03 12:05:38 -0400 | |
| commit | bb9d39b8fe89c7619ffbca2a0a6ecae1eb3f4595 (patch) | |
| tree | d75cdd5f1f50dc9e32e0ca28e167c1680f8f75d8 /src | |
| parent | Merge pull request #495 from bunnei/improve-rro (diff) | |
| parent | gl_shader_decompiler: Implement TEX instruction. (diff) | |
| download | yuzu-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.h | 15 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 45 |
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("}"); |