summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp82
1 files changed, 48 insertions, 34 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 02ed86e5a..f4ad42335 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -6,6 +6,9 @@
#include <set>
#include <string>
#include <string_view>
+
+#include <fmt/format.h>
+
#include "common/assert.h"
#include "common/common_types.h"
#include "video_core/engines/shader_bytecode.h"
@@ -753,6 +756,38 @@ private:
}
}
+ std::string WriteTexsInstruction(const Instruction& instr, const std::string& coord,
+ const std::string& texture) {
+ // Add an extra scope and declare the texture coords inside to prevent
+ // overwriting them in case they are used as outputs of the texs instruction.
+ shader.AddLine('{');
+ ++shader.scope;
+ shader.AddLine(coord);
+
+ // TEXS has two destination registers. RG goes into gpr0+0 and gpr0+1, and BA
+ // goes into gpr28+0 and gpr28+1
+ size_t texs_offset{};
+
+ for (const auto& dest : {instr.gpr0.Value(), instr.gpr28.Value()}) {
+ for (unsigned elem = 0; elem < 2; ++elem) {
+ if (!instr.texs.IsComponentEnabled(elem)) {
+ // Skip disabled components
+ continue;
+ }
+ regs.SetRegisterToFloat(dest, elem + texs_offset, texture, 1, 4, false, elem);
+ }
+
+ if (!instr.texs.HasTwoDestinations()) {
+ // Skip the second destination
+ break;
+ }
+
+ texs_offset += 2;
+ }
+ --shader.scope;
+ shader.AddLine('}');
+ }
+
/**
* Compiles a single instruction from Tegra to GLSL.
* @param offset the offset of the Tegra shader instruction.
@@ -1351,36 +1386,18 @@ private:
const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
const std::string sampler = GetSampler(instr.sampler);
const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
- // Add an extra scope and declare the texture coords inside to prevent
- // overwriting them in case they are used as outputs of the texs instruction.
- shader.AddLine("{");
- ++shader.scope;
- shader.AddLine(coord);
- const std::string texture = "texture(" + sampler + ", coords)";
-
- // TEXS has two destination registers. RG goes into gpr0+0 and gpr0+1, and BA
- // goes into gpr28+0 and gpr28+1
- size_t texs_offset{};
-
- for (const auto& dest : {instr.gpr0.Value(), instr.gpr28.Value()}) {
- for (unsigned elem = 0; elem < 2; ++elem) {
- if (!instr.texs.IsComponentEnabled(elem)) {
- // Skip disabled components
- continue;
- }
- regs.SetRegisterToFloat(dest, elem + texs_offset, texture, 1, 4, false,
- elem);
- }
-
- if (!instr.texs.HasTwoDestinations()) {
- // Skip the second destination
- break;
- }
- texs_offset += 2;
- }
- --shader.scope;
- shader.AddLine("}");
+ const std::string texture = "texture(" + sampler + ", coords)";
+ WriteTexsInstruction(instr, coord, texture);
+ break;
+ }
+ case OpCode::Id::TLDS: {
+ const std::string op_a = regs.GetRegisterAsInteger(instr.gpr8);
+ const std::string op_b = regs.GetRegisterAsInteger(instr.gpr20);
+ const std::string sampler = GetSampler(instr.sampler);
+ const std::string coord = "ivec2 coords = ivec2(" + op_a + ", " + op_b + ");";
+ const std::string texture = "texelFetch(" + sampler + ", coords, 0)";
+ WriteTexsInstruction(instr, coord, texture);
break;
}
default: {
@@ -1780,11 +1797,8 @@ private:
}; // namespace Decompiler
std::string GetCommonDeclarations() {
- std::string declarations;
- declarations += "#define MAX_CONSTBUFFER_ELEMENTS " +
- std::to_string(RasterizerOpenGL::MaxConstbufferSize / (sizeof(GLvec4)));
- declarations += '\n';
- return declarations;
+ return fmt::format("#define MAX_CONSTBUFFER_ELEMENTS {}\n",
+ RasterizerOpenGL::MaxConstbufferSize / sizeof(GLvec4));
}
boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset,