diff options
| author | 2018-08-20 21:56:06 -0400 | |
|---|---|---|
| committer | 2018-08-20 21:56:06 -0400 | |
| commit | 5aaee2ff8dcb2ce396aa7e8556f61f6a02f2488c (patch) | |
| tree | 9553857817671c4e6cd4931ae94b1919f6a8f412 /src/video_core | |
| parent | Merge pull request #1130 from Subv/tex_2d (diff) | |
| parent | Shaders: Write all the enabled color outputs when a fragment shader exits. (diff) | |
| download | yuzu-5aaee2ff8dcb2ce396aa7e8556f61f6a02f2488c.tar.gz yuzu-5aaee2ff8dcb2ce396aa7e8556f61f6a02f2488c.tar.xz yuzu-5aaee2ff8dcb2ce396aa7e8556f61f6a02f2488c.zip | |
Merge pull request #1106 from Subv/multiple_rendertargets
Shaders: Write all the enabled color outputs when a fragment shader exits.
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 49 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 2 |
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; | |||
| 26 | using Tegra::Shader::SubOp; | 26 | using Tegra::Shader::SubOp; |
| 27 | 27 | ||
| 28 | constexpr u32 PROGRAM_END = MAX_PROGRAM_CODE_LENGTH; | 28 | constexpr u32 PROGRAM_END = MAX_PROGRAM_CODE_LENGTH; |
| 29 | constexpr u32 PROGRAM_HEADER_SIZE = 0x50; | ||
| 29 | 30 | ||
| 30 | class DecompileFail : public std::runtime_error { | 31 | class DecompileFail : public std::runtime_error { |
| 31 | public: | 32 | public: |
| @@ -621,6 +622,23 @@ public: | |||
| 621 | } | 622 | } |
| 622 | 623 | ||
| 623 | private: | 624 | private: |
| 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"( |
| 89 | in vec4 position; | 89 | in vec4 position; |
| 90 | out vec4 color; | 90 | layout(location = 0) out vec4 color[8]; |
| 91 | 91 | ||
| 92 | layout (std140) uniform fs_config { | 92 | layout (std140) uniform fs_config { |
| 93 | vec4 viewport_flip; | 93 | vec4 viewport_flip; |