summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-08-22 01:05:25 -0400
committerGravatar GitHub2018-08-22 01:05:25 -0400
commit125d7122ac6c369d461d4219aaecfe4563362c01 (patch)
tree19dfc78904b0cced2abfa05aaebd5fa2a8f88a85 /src
parentMerge pull request #1147 from lioncash/warn (diff)
parentGPU: Implemented the logic op functionality of the GPU. (diff)
downloadyuzu-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.h29
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp18
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h3
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp20
-rw-r--r--src/video_core/renderer_opengl/gl_state.h5
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h40
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);
942ASSERT_REG_POSITION(index_array, 0x5F2); 968ASSERT_REG_POSITION(index_array, 0x5F2);
943ASSERT_REG_POSITION(instanced_arrays, 0x620); 969ASSERT_REG_POSITION(instanced_arrays, 0x620);
944ASSERT_REG_POSITION(cull, 0x646); 970ASSERT_REG_POSITION(cull, 0x646);
971ASSERT_REG_POSITION(logic_op, 0x671);
945ASSERT_REG_POSITION(clear_buffers, 0x674); 972ASSERT_REG_POSITION(clear_buffers, 0x674);
946ASSERT_REG_POSITION(query, 0x6C0); 973ASSERT_REG_POSITION(query, 0x6C0);
947ASSERT_REG_POSITION(vertex_array[0], 0x700); 974ASSERT_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
864void 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
320inline 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