summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp72
1 files changed, 43 insertions, 29 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index e771411ef..4e36b6de8 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -750,6 +750,38 @@ private:
750 } 750 }
751 } 751 }
752 752
753 std::string WriteTexsInstruction(const Instruction& instr, const std::string& coord,
754 const std::string& texture) {
755 // Add an extra scope and declare the texture coords inside to prevent
756 // overwriting them in case they are used as outputs of the texs instruction.
757 shader.AddLine('{');
758 ++shader.scope;
759 shader.AddLine(coord);
760
761 // TEXS has two destination registers. RG goes into gpr0+0 and gpr0+1, and BA
762 // goes into gpr28+0 and gpr28+1
763 size_t texs_offset{};
764
765 for (const auto& dest : {instr.gpr0.Value(), instr.gpr28.Value()}) {
766 for (unsigned elem = 0; elem < 2; ++elem) {
767 if (!instr.texs.IsComponentEnabled(elem)) {
768 // Skip disabled components
769 continue;
770 }
771 regs.SetRegisterToFloat(dest, elem + texs_offset, texture, 1, 4, false, elem);
772 }
773
774 if (!instr.texs.HasTwoDestinations()) {
775 // Skip the second destination
776 break;
777 }
778
779 texs_offset += 2;
780 }
781 --shader.scope;
782 shader.AddLine('}');
783 }
784
753 /** 785 /**
754 * Compiles a single instruction from Tegra to GLSL. 786 * Compiles a single instruction from Tegra to GLSL.
755 * @param offset the offset of the Tegra shader instruction. 787 * @param offset the offset of the Tegra shader instruction.
@@ -1348,36 +1380,18 @@ private:
1348 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20); 1380 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
1349 const std::string sampler = GetSampler(instr.sampler); 1381 const std::string sampler = GetSampler(instr.sampler);
1350 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; 1382 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
1351 // Add an extra scope and declare the texture coords inside to prevent
1352 // overwriting them in case they are used as outputs of the texs instruction.
1353 shader.AddLine("{");
1354 ++shader.scope;
1355 shader.AddLine(coord);
1356 const std::string texture = "texture(" + sampler + ", coords)";
1357
1358 // TEXS has two destination registers. RG goes into gpr0+0 and gpr0+1, and BA
1359 // goes into gpr28+0 and gpr28+1
1360 size_t texs_offset{};
1361
1362 for (const auto& dest : {instr.gpr0.Value(), instr.gpr28.Value()}) {
1363 for (unsigned elem = 0; elem < 2; ++elem) {
1364 if (!instr.texs.IsComponentEnabled(elem)) {
1365 // Skip disabled components
1366 continue;
1367 }
1368 regs.SetRegisterToFloat(dest, elem + texs_offset, texture, 1, 4, false,
1369 elem);
1370 }
1371
1372 if (!instr.texs.HasTwoDestinations()) {
1373 // Skip the second destination
1374 break;
1375 }
1376 1383
1377 texs_offset += 2; 1384 const std::string texture = "texture(" + sampler + ", coords)";
1378 } 1385 WriteTexsInstruction(instr, coord, texture);
1379 --shader.scope; 1386 break;
1380 shader.AddLine("}"); 1387 }
1388 case OpCode::Id::TLDS: {
1389 const std::string op_a = regs.GetRegisterAsInteger(instr.gpr8);
1390 const std::string op_b = regs.GetRegisterAsInteger(instr.gpr20);
1391 const std::string sampler = GetSampler(instr.sampler);
1392 const std::string coord = "ivec2 coords = ivec2(" + op_a + ", " + op_b + ");";
1393 const std::string texture = "texelFetch(" + sampler + ", coords, 0)";
1394 WriteTexsInstruction(instr, coord, texture);
1381 break; 1395 break;
1382 } 1396 }
1383 default: { 1397 default: {