diff options
| author | 2018-08-22 01:05:25 -0400 | |
|---|---|---|
| committer | 2018-08-22 01:05:25 -0400 | |
| commit | 125d7122ac6c369d461d4219aaecfe4563362c01 (patch) | |
| tree | 19dfc78904b0cced2abfa05aaebd5fa2a8f88a85 /src | |
| parent | Merge pull request #1147 from lioncash/warn (diff) | |
| parent | GPU: Implemented the logic op functionality of the GPU. (diff) | |
| download | yuzu-125d7122ac6c369d461d4219aaecfe4563362c01.tar.gz yuzu-125d7122ac6c369d461d4219aaecfe4563362c01.tar.xz yuzu-125d7122ac6c369d461d4219aaecfe4563362c01.zip | |
Merge pull request #1124 from Subv/logic_ops
GPU: Implemented logic ops.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 29 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 18 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 20 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/maxwell_to_gl.h | 40 |
6 files changed, 108 insertions, 7 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 3c869d3a1..d03bc1c0c 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -311,6 +311,25 @@ public: | |||
| 311 | AlwaysOld = 8, | 311 | AlwaysOld = 8, |
| 312 | }; | 312 | }; |
| 313 | 313 | ||
| 314 | enum class LogicOperation : u32 { | ||
| 315 | Clear = 0x1500, | ||
| 316 | And = 0x1501, | ||
| 317 | AndReverse = 0x1502, | ||
| 318 | Copy = 0x1503, | ||
| 319 | AndInverted = 0x1504, | ||
| 320 | NoOp = 0x1505, | ||
| 321 | Xor = 0x1506, | ||
| 322 | Or = 0x1507, | ||
| 323 | Nor = 0x1508, | ||
| 324 | Equiv = 0x1509, | ||
| 325 | Invert = 0x150A, | ||
| 326 | OrReverse = 0x150B, | ||
| 327 | CopyInverted = 0x150C, | ||
| 328 | OrInverted = 0x150D, | ||
| 329 | Nand = 0x150E, | ||
| 330 | Set = 0x150F, | ||
| 331 | }; | ||
| 332 | |||
| 314 | struct Cull { | 333 | struct Cull { |
| 315 | enum class FrontFace : u32 { | 334 | enum class FrontFace : u32 { |
| 316 | ClockWise = 0x0900, | 335 | ClockWise = 0x0900, |
| @@ -695,7 +714,14 @@ public: | |||
| 695 | 714 | ||
| 696 | Cull cull; | 715 | Cull cull; |
| 697 | 716 | ||
| 698 | INSERT_PADDING_WORDS(0x2B); | 717 | INSERT_PADDING_WORDS(0x28); |
| 718 | |||
| 719 | struct { | ||
| 720 | u32 enable; | ||
| 721 | LogicOperation operation; | ||
| 722 | } logic_op; | ||
| 723 | |||
| 724 | INSERT_PADDING_WORDS(0x1); | ||
| 699 | 725 | ||
| 700 | union { | 726 | union { |
| 701 | u32 raw; | 727 | u32 raw; |
| @@ -942,6 +968,7 @@ ASSERT_REG_POSITION(draw, 0x585); | |||
| 942 | ASSERT_REG_POSITION(index_array, 0x5F2); | 968 | ASSERT_REG_POSITION(index_array, 0x5F2); |
| 943 | ASSERT_REG_POSITION(instanced_arrays, 0x620); | 969 | ASSERT_REG_POSITION(instanced_arrays, 0x620); |
| 944 | ASSERT_REG_POSITION(cull, 0x646); | 970 | ASSERT_REG_POSITION(cull, 0x646); |
| 971 | ASSERT_REG_POSITION(logic_op, 0x671); | ||
| 945 | ASSERT_REG_POSITION(clear_buffers, 0x674); | 972 | ASSERT_REG_POSITION(clear_buffers, 0x674); |
| 946 | ASSERT_REG_POSITION(query, 0x6C0); | 973 | ASSERT_REG_POSITION(query, 0x6C0); |
| 947 | ASSERT_REG_POSITION(vertex_array[0], 0x700); | 974 | ASSERT_REG_POSITION(vertex_array[0], 0x700); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index b653bb479..35056d9bd 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -450,6 +450,7 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 450 | 450 | ||
| 451 | SyncDepthTestState(); | 451 | SyncDepthTestState(); |
| 452 | SyncBlendState(); | 452 | SyncBlendState(); |
| 453 | SyncLogicOpState(); | ||
| 453 | SyncCullMode(); | 454 | SyncCullMode(); |
| 454 | 455 | ||
| 455 | // TODO(bunnei): Sync framebuffer_scale uniform here | 456 | // TODO(bunnei): Sync framebuffer_scale uniform here |
| @@ -847,6 +848,9 @@ void RasterizerOpenGL::SyncBlendState() { | |||
| 847 | if (!state.blend.enabled) | 848 | if (!state.blend.enabled) |
| 848 | return; | 849 | return; |
| 849 | 850 | ||
| 851 | ASSERT_MSG(regs.logic_op.enable == 0, | ||
| 852 | "Blending and logic op can't be enabled at the same time."); | ||
| 853 | |||
| 850 | ASSERT_MSG(regs.independent_blend_enable == 1, "Only independent blending is implemented"); | 854 | ASSERT_MSG(regs.independent_blend_enable == 1, "Only independent blending is implemented"); |
| 851 | ASSERT_MSG(!regs.independent_blend[0].separate_alpha, "Unimplemented"); | 855 | ASSERT_MSG(!regs.independent_blend[0].separate_alpha, "Unimplemented"); |
| 852 | state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_rgb); | 856 | state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.independent_blend[0].equation_rgb); |
| @@ -856,3 +860,17 @@ void RasterizerOpenGL::SyncBlendState() { | |||
| 856 | state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_a); | 860 | state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_source_a); |
| 857 | state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_a); | 861 | state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.independent_blend[0].factor_dest_a); |
| 858 | } | 862 | } |
| 863 | |||
| 864 | void RasterizerOpenGL::SyncLogicOpState() { | ||
| 865 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | ||
| 866 | |||
| 867 | // TODO(Subv): Support more than just render target 0. | ||
| 868 | state.logic_op.enabled = regs.logic_op.enable != 0; | ||
| 869 | |||
| 870 | if (!state.logic_op.enabled) | ||
| 871 | return; | ||
| 872 | |||
| 873 | ASSERT_MSG(regs.blend.enable == 0, "Blending and logic op can't be enabled at the same time."); | ||
| 874 | |||
| 875 | state.logic_op.operation = MaxwellToGL::LogicOp(regs.logic_op.operation); | ||
| 876 | } | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 394fc59f1..f40e70bf4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -142,6 +142,9 @@ private: | |||
| 142 | /// Syncs the blend state to match the guest state | 142 | /// Syncs the blend state to match the guest state |
| 143 | void SyncBlendState(); | 143 | void SyncBlendState(); |
| 144 | 144 | ||
| 145 | /// Syncs the LogicOp state to match the guest state | ||
| 146 | void SyncLogicOpState(); | ||
| 147 | |||
| 145 | bool has_ARB_direct_state_access = false; | 148 | bool has_ARB_direct_state_access = false; |
| 146 | bool has_ARB_separate_shader_objects = false; | 149 | bool has_ARB_separate_shader_objects = false; |
| 147 | bool has_ARB_vertex_attrib_binding = false; | 150 | bool has_ARB_vertex_attrib_binding = false; |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 1d1975179..13399ceb8 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -45,7 +45,8 @@ OpenGLState::OpenGLState() { | |||
| 45 | blend.color.blue = 0.0f; | 45 | blend.color.blue = 0.0f; |
| 46 | blend.color.alpha = 0.0f; | 46 | blend.color.alpha = 0.0f; |
| 47 | 47 | ||
| 48 | logic_op = GL_COPY; | 48 | logic_op.enabled = false; |
| 49 | logic_op.operation = GL_COPY; | ||
| 49 | 50 | ||
| 50 | for (auto& texture_unit : texture_units) { | 51 | for (auto& texture_unit : texture_units) { |
| 51 | texture_unit.Reset(); | 52 | texture_unit.Reset(); |
| @@ -148,11 +149,10 @@ void OpenGLState::Apply() const { | |||
| 148 | // Blending | 149 | // Blending |
| 149 | if (blend.enabled != cur_state.blend.enabled) { | 150 | if (blend.enabled != cur_state.blend.enabled) { |
| 150 | if (blend.enabled) { | 151 | if (blend.enabled) { |
| 152 | ASSERT(!logic_op.enabled); | ||
| 151 | glEnable(GL_BLEND); | 153 | glEnable(GL_BLEND); |
| 152 | glDisable(GL_COLOR_LOGIC_OP); | ||
| 153 | } else { | 154 | } else { |
| 154 | glDisable(GL_BLEND); | 155 | glDisable(GL_BLEND); |
| 155 | glEnable(GL_COLOR_LOGIC_OP); | ||
| 156 | } | 156 | } |
| 157 | } | 157 | } |
| 158 | 158 | ||
| @@ -176,8 +176,18 @@ void OpenGLState::Apply() const { | |||
| 176 | glBlendEquationSeparate(blend.rgb_equation, blend.a_equation); | 176 | glBlendEquationSeparate(blend.rgb_equation, blend.a_equation); |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | if (logic_op != cur_state.logic_op) { | 179 | // Logic Operation |
| 180 | glLogicOp(logic_op); | 180 | if (logic_op.enabled != cur_state.logic_op.enabled) { |
| 181 | if (logic_op.enabled) { | ||
| 182 | ASSERT(!blend.enabled); | ||
| 183 | glEnable(GL_COLOR_LOGIC_OP); | ||
| 184 | } else { | ||
| 185 | glDisable(GL_COLOR_LOGIC_OP); | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | if (logic_op.operation != cur_state.logic_op.operation) { | ||
| 190 | glLogicOp(logic_op.operation); | ||
| 181 | } | 191 | } |
| 182 | 192 | ||
| 183 | // Textures | 193 | // Textures |
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index bdb02ba25..219b65a8a 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -83,7 +83,10 @@ public: | |||
| 83 | } color; // GL_BLEND_COLOR | 83 | } color; // GL_BLEND_COLOR |
| 84 | } blend; | 84 | } blend; |
| 85 | 85 | ||
| 86 | GLenum logic_op; // GL_LOGIC_OP_MODE | 86 | struct { |
| 87 | bool enabled; // GL_LOGIC_OP_MODE | ||
| 88 | GLenum operation; | ||
| 89 | } logic_op; | ||
| 87 | 90 | ||
| 88 | // 3 texture units - one for each that is used in PICA fragment shader emulation | 91 | // 3 texture units - one for each that is used in PICA fragment shader emulation |
| 89 | struct TextureUnit { | 92 | struct TextureUnit { |
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index 5d91a0c2f..ff2f7b8b6 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h | |||
| @@ -317,4 +317,44 @@ inline GLenum CullFace(Maxwell::Cull::CullFace cull_face) { | |||
| 317 | return {}; | 317 | return {}; |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | inline GLenum LogicOp(Maxwell::LogicOperation operation) { | ||
| 321 | switch (operation) { | ||
| 322 | case Maxwell::LogicOperation::Clear: | ||
| 323 | return GL_CLEAR; | ||
| 324 | case Maxwell::LogicOperation::And: | ||
| 325 | return GL_AND; | ||
| 326 | case Maxwell::LogicOperation::AndReverse: | ||
| 327 | return GL_AND_REVERSE; | ||
| 328 | case Maxwell::LogicOperation::Copy: | ||
| 329 | return GL_COPY; | ||
| 330 | case Maxwell::LogicOperation::AndInverted: | ||
| 331 | return GL_AND_INVERTED; | ||
| 332 | case Maxwell::LogicOperation::NoOp: | ||
| 333 | return GL_NOOP; | ||
| 334 | case Maxwell::LogicOperation::Xor: | ||
| 335 | return GL_XOR; | ||
| 336 | case Maxwell::LogicOperation::Or: | ||
| 337 | return GL_OR; | ||
| 338 | case Maxwell::LogicOperation::Nor: | ||
| 339 | return GL_NOR; | ||
| 340 | case Maxwell::LogicOperation::Equiv: | ||
| 341 | return GL_EQUIV; | ||
| 342 | case Maxwell::LogicOperation::Invert: | ||
| 343 | return GL_INVERT; | ||
| 344 | case Maxwell::LogicOperation::OrReverse: | ||
| 345 | return GL_OR_REVERSE; | ||
| 346 | case Maxwell::LogicOperation::CopyInverted: | ||
| 347 | return GL_COPY_INVERTED; | ||
| 348 | case Maxwell::LogicOperation::OrInverted: | ||
| 349 | return GL_OR_INVERTED; | ||
| 350 | case Maxwell::LogicOperation::Nand: | ||
| 351 | return GL_NAND; | ||
| 352 | case Maxwell::LogicOperation::Set: | ||
| 353 | return GL_SET; | ||
| 354 | } | ||
| 355 | LOG_CRITICAL(Render_OpenGL, "Unimplemented logic operation={}", static_cast<u32>(operation)); | ||
| 356 | UNREACHABLE(); | ||
| 357 | return {}; | ||
| 358 | } | ||
| 359 | |||
| 320 | } // namespace MaxwellToGL | 360 | } // namespace MaxwellToGL |