summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-08-23 12:04:08 -0400
committerGravatar GitHub2018-08-23 12:04:08 -0400
commit3ed0115e36a8b563aa40b32cd645165e12b1ba81 (patch)
tree37c8529b9f2037dfb2072a248e4d257edc6144d7 /src
parentMerge pull request #1157 from lioncash/vec (diff)
parentgl_rasterizer: Implement stencil test. (diff)
downloadyuzu-3ed0115e36a8b563aa40b32cd645165e12b1ba81.tar.gz
yuzu-3ed0115e36a8b563aa40b32cd645165e12b1ba81.tar.xz
yuzu-3ed0115e36a8b563aa40b32cd645165e12b1ba81.zip
Merge pull request #1153 from bunnei/stencil-clear
gl_rasterizer: Implement partial color clear, stencil clear, and stencil test.
Diffstat (limited to '')
-rw-r--r--src/video_core/engines/maxwell_3d.h70
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp89
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h3
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp53
-rw-r--r--src/video_core/renderer_opengl/gl_state.h18
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h24
6 files changed, 188 insertions, 69 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index d03bc1c0c..92bfda053 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -330,6 +330,17 @@ public:
330 Set = 0x150F, 330 Set = 0x150F,
331 }; 331 };
332 332
333 enum class StencilOp : u32 {
334 Keep = 1,
335 Zero = 2,
336 Replace = 3,
337 Incr = 4,
338 Decr = 5,
339 Invert = 6,
340 IncrWrap = 7,
341 DecrWrap = 8,
342 };
343
333 struct Cull { 344 struct Cull {
334 enum class FrontFace : u32 { 345 enum class FrontFace : u32 {
335 ClockWise = 0x0900, 346 ClockWise = 0x0900,
@@ -508,8 +519,16 @@ public:
508 519
509 float clear_color[4]; 520 float clear_color[4];
510 float clear_depth; 521 float clear_depth;
522 INSERT_PADDING_WORDS(0x3);
523 s32 clear_stencil;
524
525 INSERT_PADDING_WORDS(0x6C);
526
527 s32 stencil_back_func_ref;
528 u32 stencil_back_mask;
529 u32 stencil_back_func_mask;
511 530
512 INSERT_PADDING_WORDS(0x93); 531 INSERT_PADDING_WORDS(0x20);
513 532
514 struct { 533 struct {
515 u32 address_high; 534 u32 address_high;
@@ -573,16 +592,14 @@ public:
573 u32 enable[NumRenderTargets]; 592 u32 enable[NumRenderTargets];
574 } blend; 593 } blend;
575 594
576 struct { 595 u32 stencil_enable;
577 u32 enable; 596 StencilOp stencil_front_op_fail;
578 u32 front_op_fail; 597 StencilOp stencil_front_op_zfail;
579 u32 front_op_zfail; 598 StencilOp stencil_front_op_zpass;
580 u32 front_op_zpass; 599 ComparisonOp stencil_front_func_func;
581 u32 front_func_func; 600 s32 stencil_front_func_ref;
582 u32 front_func_ref; 601 u32 stencil_front_func_mask;
583 u32 front_func_mask; 602 u32 stencil_front_mask;
584 u32 front_mask;
585 } stencil;
586 603
587 INSERT_PADDING_WORDS(0x3); 604 INSERT_PADDING_WORDS(0x3);
588 605
@@ -626,13 +643,11 @@ public:
626 643
627 INSERT_PADDING_WORDS(0x5); 644 INSERT_PADDING_WORDS(0x5);
628 645
629 struct { 646 u32 stencil_two_side_enable;
630 u32 enable; 647 StencilOp stencil_back_op_fail;
631 u32 back_op_fail; 648 StencilOp stencil_back_op_zfail;
632 u32 back_op_zfail; 649 StencilOp stencil_back_op_zpass;
633 u32 back_op_zpass; 650 ComparisonOp stencil_back_func_func;
634 u32 back_func_func;
635 } stencil_two_side;
636 651
637 INSERT_PADDING_WORDS(0x17); 652 INSERT_PADDING_WORDS(0x17);
638 653
@@ -944,6 +959,10 @@ ASSERT_REG_POSITION(viewport, 0x300);
944ASSERT_REG_POSITION(vertex_buffer, 0x35D); 959ASSERT_REG_POSITION(vertex_buffer, 0x35D);
945ASSERT_REG_POSITION(clear_color[0], 0x360); 960ASSERT_REG_POSITION(clear_color[0], 0x360);
946ASSERT_REG_POSITION(clear_depth, 0x364); 961ASSERT_REG_POSITION(clear_depth, 0x364);
962ASSERT_REG_POSITION(clear_stencil, 0x368);
963ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5);
964ASSERT_REG_POSITION(stencil_back_mask, 0x3D6);
965ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7);
947ASSERT_REG_POSITION(zeta, 0x3F8); 966ASSERT_REG_POSITION(zeta, 0x3F8);
948ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458); 967ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458);
949ASSERT_REG_POSITION(rt_control, 0x487); 968ASSERT_REG_POSITION(rt_control, 0x487);
@@ -955,13 +974,24 @@ ASSERT_REG_POSITION(depth_write_enabled, 0x4BA);
955ASSERT_REG_POSITION(d3d_cull_mode, 0x4C2); 974ASSERT_REG_POSITION(d3d_cull_mode, 0x4C2);
956ASSERT_REG_POSITION(depth_test_func, 0x4C3); 975ASSERT_REG_POSITION(depth_test_func, 0x4C3);
957ASSERT_REG_POSITION(blend, 0x4CF); 976ASSERT_REG_POSITION(blend, 0x4CF);
958ASSERT_REG_POSITION(stencil, 0x4E0); 977ASSERT_REG_POSITION(stencil_enable, 0x4E0);
978ASSERT_REG_POSITION(stencil_front_op_fail, 0x4E1);
979ASSERT_REG_POSITION(stencil_front_op_zfail, 0x4E2);
980ASSERT_REG_POSITION(stencil_front_op_zpass, 0x4E3);
981ASSERT_REG_POSITION(stencil_front_func_func, 0x4E4);
982ASSERT_REG_POSITION(stencil_front_func_ref, 0x4E5);
983ASSERT_REG_POSITION(stencil_front_func_mask, 0x4E6);
984ASSERT_REG_POSITION(stencil_front_mask, 0x4E7);
959ASSERT_REG_POSITION(screen_y_control, 0x4EB); 985ASSERT_REG_POSITION(screen_y_control, 0x4EB);
960ASSERT_REG_POSITION(vb_element_base, 0x50D); 986ASSERT_REG_POSITION(vb_element_base, 0x50D);
961ASSERT_REG_POSITION(zeta_enable, 0x54E); 987ASSERT_REG_POSITION(zeta_enable, 0x54E);
962ASSERT_REG_POSITION(tsc, 0x557); 988ASSERT_REG_POSITION(tsc, 0x557);
963ASSERT_REG_POSITION(tic, 0x55D); 989ASSERT_REG_POSITION(tic, 0x55D);
964ASSERT_REG_POSITION(stencil_two_side, 0x565); 990ASSERT_REG_POSITION(stencil_two_side_enable, 0x565);
991ASSERT_REG_POSITION(stencil_back_op_fail, 0x566);
992ASSERT_REG_POSITION(stencil_back_op_zfail, 0x567);
993ASSERT_REG_POSITION(stencil_back_op_zpass, 0x568);
994ASSERT_REG_POSITION(stencil_back_func_func, 0x569);
965ASSERT_REG_POSITION(point_coord_replace, 0x581); 995ASSERT_REG_POSITION(point_coord_replace, 0x581);
966ASSERT_REG_POSITION(code_address, 0x582); 996ASSERT_REG_POSITION(code_address, 0x582);
967ASSERT_REG_POSITION(draw, 0x585); 997ASSERT_REG_POSITION(draw, 0x585);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 516e1b50f..8bfa75b84 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -14,6 +14,7 @@
14#include "common/logging/log.h" 14#include "common/logging/log.h"
15#include "common/math_util.h" 15#include "common/math_util.h"
16#include "common/microprofile.h" 16#include "common/microprofile.h"
17#include "common/scope_exit.h"
17#include "core/core.h" 18#include "core/core.h"
18#include "core/frontend/emu_window.h" 19#include "core/frontend/emu_window.h"
19#include "core/hle/kernel/process.h" 20#include "core/hle/kernel/process.h"
@@ -315,16 +316,14 @@ std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers(bool using_c
315 using_color_fb = false; 316 using_color_fb = false;
316 } 317 }
317 318
318 // TODO(bunnei): Implement this 319 const bool has_stencil = regs.stencil_enable;
319 const bool has_stencil = false;
320
321 const bool write_color_fb = 320 const bool write_color_fb =
322 state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE || 321 state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE ||
323 state.color_mask.blue_enabled == GL_TRUE || state.color_mask.alpha_enabled == GL_TRUE; 322 state.color_mask.blue_enabled == GL_TRUE || state.color_mask.alpha_enabled == GL_TRUE;
324 323
325 const bool write_depth_fb = 324 const bool write_depth_fb =
326 (state.depth.test_enabled && state.depth.write_mask == GL_TRUE) || 325 (state.depth.test_enabled && state.depth.write_mask == GL_TRUE) ||
327 (has_stencil && state.stencil.test_enabled && state.stencil.write_mask != 0); 326 (has_stencil && (state.stencil.front.write_mask || state.stencil.back.write_mask));
328 327
329 Surface color_surface; 328 Surface color_surface;
330 Surface depth_surface; 329 Surface depth_surface;
@@ -364,41 +363,70 @@ std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers(bool using_c
364} 363}
365 364
366void RasterizerOpenGL::Clear() { 365void RasterizerOpenGL::Clear() {
367 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 366 const auto prev_state{state};
367 SCOPE_EXIT({ prev_state.Apply(); });
368 368
369 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
369 bool use_color_fb = false; 370 bool use_color_fb = false;
370 bool use_depth_fb = false; 371 bool use_depth_fb = false;
371 372
372 GLbitfield clear_mask = 0; 373 OpenGLState clear_state;
373 if (regs.clear_buffers.R && regs.clear_buffers.G && regs.clear_buffers.B && 374 clear_state.draw.draw_framebuffer = state.draw.draw_framebuffer;
375 clear_state.color_mask.red_enabled = regs.clear_buffers.R ? GL_TRUE : GL_FALSE;
376 clear_state.color_mask.green_enabled = regs.clear_buffers.G ? GL_TRUE : GL_FALSE;
377 clear_state.color_mask.blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE;
378 clear_state.color_mask.alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
379
380 GLbitfield clear_mask{};
381 if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
374 regs.clear_buffers.A) { 382 regs.clear_buffers.A) {
375 clear_mask |= GL_COLOR_BUFFER_BIT; 383 if (regs.clear_buffers.RT == 0) {
376 use_color_fb = true; 384 // We only support clearing the first color attachment for now
385 clear_mask |= GL_COLOR_BUFFER_BIT;
386 use_color_fb = true;
387 } else {
388 // TODO(subv): Add support for the other color attachments
389 LOG_CRITICAL(HW_GPU, "Clear unimplemented for RT {}", regs.clear_buffers.RT);
390 }
377 } 391 }
378 if (regs.clear_buffers.Z) { 392 if (regs.clear_buffers.Z) {
393 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!");
394 use_depth_fb = true;
379 clear_mask |= GL_DEPTH_BUFFER_BIT; 395 clear_mask |= GL_DEPTH_BUFFER_BIT;
380 use_depth_fb = regs.zeta_enable != 0;
381 396
382 // Always enable the depth write when clearing the depth buffer. The depth write mask is 397 // Always enable the depth write when clearing the depth buffer. The depth write mask is
383 // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true. 398 // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true.
384 state.depth.test_enabled = true; 399 clear_state.depth.test_enabled = true;
385 state.depth.write_mask = GL_TRUE; 400 clear_state.depth.test_func = GL_ALWAYS;
386 state.depth.test_func = GL_ALWAYS; 401 }
387 state.Apply(); 402 if (regs.clear_buffers.S) {
403 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear stencil but buffer is not enabled!");
404 use_depth_fb = true;
405 clear_mask |= GL_STENCIL_BUFFER_BIT;
406 clear_state.stencil.test_enabled = true;
388 } 407 }
389 408
390 if (clear_mask == 0) 409 if (!use_color_fb && !use_depth_fb) {
410 // No color surface nor depth/stencil surface are enabled
391 return; 411 return;
412 }
413
414 if (clear_mask == 0) {
415 // No clear mask is enabled
416 return;
417 }
392 418
393 ScopeAcquireGLContext acquire_context{emu_window}; 419 ScopeAcquireGLContext acquire_context{emu_window};
394 420
395 auto [dirty_color_surface, dirty_depth_surface] = 421 auto [dirty_color_surface, dirty_depth_surface] =
396 ConfigureFramebuffers(use_color_fb, use_depth_fb, false); 422 ConfigureFramebuffers(use_color_fb, use_depth_fb, false);
397 423
398 // TODO(Subv): Support clearing only partial colors. 424 clear_state.Apply();
425
399 glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2], 426 glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2],
400 regs.clear_color[3]); 427 regs.clear_color[3]);
401 glClearDepth(regs.clear_depth); 428 glClearDepth(regs.clear_depth);
429 glClearStencil(regs.clear_stencil);
402 430
403 glClear(clear_mask); 431 glClear(clear_mask);
404 432
@@ -451,6 +479,7 @@ void RasterizerOpenGL::DrawArrays() {
451 ConfigureFramebuffers(true, regs.zeta.Address() != 0 && regs.zeta_enable != 0, true); 479 ConfigureFramebuffers(true, regs.zeta.Address() != 0 && regs.zeta_enable != 0, true);
452 480
453 SyncDepthTestState(); 481 SyncDepthTestState();
482 SyncStencilTestState();
454 SyncBlendState(); 483 SyncBlendState();
455 SyncLogicOpState(); 484 SyncLogicOpState();
456 SyncCullMode(); 485 SyncCullMode();
@@ -841,6 +870,34 @@ void RasterizerOpenGL::SyncDepthTestState() {
841 state.depth.test_func = MaxwellToGL::ComparisonOp(regs.depth_test_func); 870 state.depth.test_func = MaxwellToGL::ComparisonOp(regs.depth_test_func);
842} 871}
843 872
873void RasterizerOpenGL::SyncStencilTestState() {
874 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
875 state.stencil.test_enabled = regs.stencil_enable != 0;
876
877 if (!regs.stencil_enable) {
878 return;
879 }
880
881 // TODO(bunnei): Verify behavior when this is not set
882 ASSERT(regs.stencil_two_side_enable);
883
884 state.stencil.front.test_func = MaxwellToGL::ComparisonOp(regs.stencil_front_func_func);
885 state.stencil.front.test_ref = regs.stencil_front_func_ref;
886 state.stencil.front.test_mask = regs.stencil_front_func_mask;
887 state.stencil.front.action_stencil_fail = MaxwellToGL::StencilOp(regs.stencil_front_op_fail);
888 state.stencil.front.action_depth_fail = MaxwellToGL::StencilOp(regs.stencil_front_op_zfail);
889 state.stencil.front.action_depth_pass = MaxwellToGL::StencilOp(regs.stencil_front_op_zpass);
890 state.stencil.front.write_mask = regs.stencil_front_mask;
891
892 state.stencil.back.test_func = MaxwellToGL::ComparisonOp(regs.stencil_back_func_func);
893 state.stencil.back.test_ref = regs.stencil_back_func_ref;
894 state.stencil.back.test_mask = regs.stencil_back_func_mask;
895 state.stencil.back.action_stencil_fail = MaxwellToGL::StencilOp(regs.stencil_back_op_fail);
896 state.stencil.back.action_depth_fail = MaxwellToGL::StencilOp(regs.stencil_back_op_zfail);
897 state.stencil.back.action_depth_pass = MaxwellToGL::StencilOp(regs.stencil_back_op_zpass);
898 state.stencil.back.write_mask = regs.stencil_back_mask;
899}
900
844void RasterizerOpenGL::SyncBlendState() { 901void RasterizerOpenGL::SyncBlendState() {
845 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 902 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
846 903
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 59b727de0..531b04046 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -141,6 +141,9 @@ private:
141 /// Syncs the depth test state to match the guest state 141 /// Syncs the depth test state to match the guest state
142 void SyncDepthTestState(); 142 void SyncDepthTestState();
143 143
144 /// Syncs the stencil test state to match the guest state
145 void SyncStencilTestState();
146
144 /// Syncs the blend state to match the guest state 147 /// Syncs the blend state to match the guest state
145 void SyncBlendState(); 148 void SyncBlendState();
146 149
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index e1a887d67..60a4defd1 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -27,13 +27,17 @@ OpenGLState::OpenGLState() {
27 color_mask.alpha_enabled = GL_TRUE; 27 color_mask.alpha_enabled = GL_TRUE;
28 28
29 stencil.test_enabled = false; 29 stencil.test_enabled = false;
30 stencil.test_func = GL_ALWAYS; 30 auto reset_stencil = [](auto& config) {
31 stencil.test_ref = 0; 31 config.test_func = GL_ALWAYS;
32 stencil.test_mask = 0xFF; 32 config.test_ref = 0;
33 stencil.write_mask = 0xFF; 33 config.test_mask = 0xFFFFFFFF;
34 stencil.action_depth_fail = GL_KEEP; 34 config.write_mask = 0xFFFFFFFF;
35 stencil.action_depth_pass = GL_KEEP; 35 config.action_depth_fail = GL_KEEP;
36 stencil.action_stencil_fail = GL_KEEP; 36 config.action_depth_pass = GL_KEEP;
37 config.action_stencil_fail = GL_KEEP;
38 };
39 reset_stencil(stencil.front);
40 reset_stencil(stencil.back);
37 41
38 blend.enabled = true; 42 blend.enabled = true;
39 blend.rgb_equation = GL_FUNC_ADD; 43 blend.rgb_equation = GL_FUNC_ADD;
@@ -129,24 +133,23 @@ void OpenGLState::Apply() const {
129 glDisable(GL_STENCIL_TEST); 133 glDisable(GL_STENCIL_TEST);
130 } 134 }
131 } 135 }
132 136 auto config_stencil = [](GLenum face, const auto& config, const auto& prev_config) {
133 if (stencil.test_func != cur_state.stencil.test_func || 137 if (config.test_func != prev_config.test_func || config.test_ref != prev_config.test_ref ||
134 stencil.test_ref != cur_state.stencil.test_ref || 138 config.test_mask != prev_config.test_mask) {
135 stencil.test_mask != cur_state.stencil.test_mask) { 139 glStencilFuncSeparate(face, config.test_func, config.test_ref, config.test_mask);
136 glStencilFunc(stencil.test_func, stencil.test_ref, stencil.test_mask); 140 }
137 } 141 if (config.action_depth_fail != prev_config.action_depth_fail ||
138 142 config.action_depth_pass != prev_config.action_depth_pass ||
139 if (stencil.action_depth_fail != cur_state.stencil.action_depth_fail || 143 config.action_stencil_fail != prev_config.action_stencil_fail) {
140 stencil.action_depth_pass != cur_state.stencil.action_depth_pass || 144 glStencilOpSeparate(face, config.action_stencil_fail, config.action_depth_fail,
141 stencil.action_stencil_fail != cur_state.stencil.action_stencil_fail) { 145 config.action_depth_pass);
142 glStencilOp(stencil.action_stencil_fail, stencil.action_depth_fail, 146 }
143 stencil.action_depth_pass); 147 if (config.write_mask != prev_config.write_mask) {
144 } 148 glStencilMaskSeparate(face, config.write_mask);
145 149 }
146 // Stencil mask 150 };
147 if (stencil.write_mask != cur_state.stencil.write_mask) { 151 config_stencil(GL_FRONT, stencil.front, cur_state.stencil.front);
148 glStencilMask(stencil.write_mask); 152 config_stencil(GL_BACK, stencil.back, cur_state.stencil.back);
149 }
150 153
151 // Blending 154 // Blending
152 if (blend.enabled != cur_state.blend.enabled) { 155 if (blend.enabled != cur_state.blend.enabled) {
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 22b0b1e41..46e96a97d 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -58,14 +58,16 @@ public:
58 } color_mask; // GL_COLOR_WRITEMASK 58 } color_mask; // GL_COLOR_WRITEMASK
59 59
60 struct { 60 struct {
61 bool test_enabled; // GL_STENCIL_TEST 61 bool test_enabled; // GL_STENCIL_TEST
62 GLenum test_func; // GL_STENCIL_FUNC 62 struct {
63 GLint test_ref; // GL_STENCIL_REF 63 GLenum test_func; // GL_STENCIL_FUNC
64 GLuint test_mask; // GL_STENCIL_VALUE_MASK 64 GLint test_ref; // GL_STENCIL_REF
65 GLuint write_mask; // GL_STENCIL_WRITEMASK 65 GLuint test_mask; // GL_STENCIL_VALUE_MASK
66 GLenum action_stencil_fail; // GL_STENCIL_FAIL 66 GLuint write_mask; // GL_STENCIL_WRITEMASK
67 GLenum action_depth_fail; // GL_STENCIL_PASS_DEPTH_FAIL 67 GLenum action_stencil_fail; // GL_STENCIL_FAIL
68 GLenum action_depth_pass; // GL_STENCIL_PASS_DEPTH_PASS 68 GLenum action_depth_fail; // GL_STENCIL_PASS_DEPTH_FAIL
69 GLenum action_depth_pass; // GL_STENCIL_PASS_DEPTH_PASS
70 } front, back;
69 } stencil; 71 } stencil;
70 72
71 struct { 73 struct {
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 0343759a6..67273e164 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -295,6 +295,30 @@ inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
295 return {}; 295 return {};
296} 296}
297 297
298inline GLenum StencilOp(Maxwell::StencilOp stencil) {
299 switch (stencil) {
300 case Maxwell::StencilOp::Keep:
301 return GL_KEEP;
302 case Maxwell::StencilOp::Zero:
303 return GL_ZERO;
304 case Maxwell::StencilOp::Replace:
305 return GL_REPLACE;
306 case Maxwell::StencilOp::Incr:
307 return GL_INCR;
308 case Maxwell::StencilOp::Decr:
309 return GL_DECR;
310 case Maxwell::StencilOp::Invert:
311 return GL_INVERT;
312 case Maxwell::StencilOp::IncrWrap:
313 return GL_INCR_WRAP;
314 case Maxwell::StencilOp::DecrWrap:
315 return GL_DECR_WRAP;
316 }
317 LOG_CRITICAL(Render_OpenGL, "Unimplemented stencil op={}", static_cast<u32>(stencil));
318 UNREACHABLE();
319 return {};
320}
321
298inline GLenum FrontFace(Maxwell::Cull::FrontFace front_face) { 322inline GLenum FrontFace(Maxwell::Cull::FrontFace front_face) {
299 switch (front_face) { 323 switch (front_face) {
300 case Maxwell::Cull::FrontFace::ClockWise: 324 case Maxwell::Cull::FrontFace::ClockWise: