summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp49
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp2
2 files changed, 45 insertions, 6 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index b7b3fbc17..214a5fa9a 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -26,6 +26,7 @@ using Tegra::Shader::Sampler;
26using Tegra::Shader::SubOp; 26using Tegra::Shader::SubOp;
27 27
28constexpr u32 PROGRAM_END = MAX_PROGRAM_CODE_LENGTH; 28constexpr u32 PROGRAM_END = MAX_PROGRAM_CODE_LENGTH;
29constexpr u32 PROGRAM_HEADER_SIZE = 0x50;
29 30
30class DecompileFail : public std::runtime_error { 31class DecompileFail : public std::runtime_error {
31public: 32public:
@@ -621,6 +622,23 @@ public:
621 } 622 }
622 623
623private: 624private:
625 // Shader program header for a Fragment Shader.
626 struct FragmentHeader {
627 INSERT_PADDING_WORDS(5);
628 INSERT_PADDING_WORDS(13);
629 u32 enabled_color_outputs;
630 union {
631 BitField<0, 1, u32> writes_samplemask;
632 BitField<1, 1, u32> writes_depth;
633 };
634
635 bool IsColorComponentOutputEnabled(u32 render_target, u32 component) const {
636 u32 bit = render_target * 4 + component;
637 return enabled_color_outputs & (1 << bit);
638 }
639 };
640 static_assert(sizeof(FragmentHeader) == PROGRAM_HEADER_SIZE, "FragmentHeader size is wrong");
641
624 /// Gets the Subroutine object corresponding to the specified address. 642 /// Gets the Subroutine object corresponding to the specified address.
625 const Subroutine& GetSubroutine(u32 begin, u32 end) const { 643 const Subroutine& GetSubroutine(u32 begin, u32 end) const {
626 auto iter = subroutines.find(Subroutine{begin, end, suffix}); 644 auto iter = subroutines.find(Subroutine{begin, end, suffix});
@@ -894,6 +912,31 @@ private:
894 shader.AddLine('}'); 912 shader.AddLine('}');
895 } 913 }
896 914
915 /// Writes the output values from a fragment shader to the corresponding GLSL output variables.
916 void EmitFragmentOutputsWrite() {
917 ASSERT(stage == Maxwell3D::Regs::ShaderStage::Fragment);
918 FragmentHeader header;
919 std::memcpy(&header, program_code.data(), PROGRAM_HEADER_SIZE);
920
921 ASSERT_MSG(header.writes_depth == 0, "Depth write is unimplemented");
922 ASSERT_MSG(header.writes_samplemask == 0, "Samplemask write is unimplemented");
923
924 // Write the color outputs using the data in the shader registers, disabled
925 // rendertargets/components are skipped in the register assignment.
926 u32 current_reg = 0;
927 for (u32 render_target = 0; render_target < Maxwell3D::Regs::NumRenderTargets;
928 ++render_target) {
929 // TODO(Subv): Figure out how dual-source blending is configured in the Switch.
930 for (u32 component = 0; component < 4; ++component) {
931 if (header.IsColorComponentOutputEnabled(render_target, component)) {
932 shader.AddLine(fmt::format("color[{}][{}] = {};", render_target, component,
933 regs.GetRegisterAsFloat(current_reg)));
934 ++current_reg;
935 }
936 }
937 }
938 }
939
897 /** 940 /**
898 * Compiles a single instruction from Tegra to GLSL. 941 * Compiles a single instruction from Tegra to GLSL.
899 * @param offset the offset of the Tegra shader instruction. 942 * @param offset the offset of the Tegra shader instruction.
@@ -1969,12 +2012,8 @@ private:
1969 default: { 2012 default: {
1970 switch (opcode->GetId()) { 2013 switch (opcode->GetId()) {
1971 case OpCode::Id::EXIT: { 2014 case OpCode::Id::EXIT: {
1972 // Final color output is currently hardcoded to GPR0-3 for fragment shaders
1973 if (stage == Maxwell3D::Regs::ShaderStage::Fragment) { 2015 if (stage == Maxwell3D::Regs::ShaderStage::Fragment) {
1974 shader.AddLine("color.r = " + regs.GetRegisterAsFloat(0) + ';'); 2016 EmitFragmentOutputsWrite();
1975 shader.AddLine("color.g = " + regs.GetRegisterAsFloat(1) + ';');
1976 shader.AddLine("color.b = " + regs.GetRegisterAsFloat(2) + ';');
1977 shader.AddLine("color.a = " + regs.GetRegisterAsFloat(3) + ';');
1978 } 2017 }
1979 2018
1980 switch (instr.flow.cond) { 2019 switch (instr.flow.cond) {
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 57e0e1726..01c7b9720 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -87,7 +87,7 @@ ProgramResult GenerateFragmentShader(const ShaderSetup& setup, const MaxwellFSCo
87 .get_value_or({}); 87 .get_value_or({});
88 out += R"( 88 out += R"(
89in vec4 position; 89in vec4 position;
90out vec4 color; 90layout(location = 0) out vec4 color[8];
91 91
92layout (std140) uniform fs_config { 92layout (std140) uniform fs_config {
93 vec4 viewport_flip; 93 vec4 viewport_flip;