DRW: Make stencil state clearer and distinct
authorClément Foucault <foucault.clem@gmail.com>
Mon, 17 Jun 2019 13:18:21 +0000 (15:18 +0200)
committerClément Foucault <foucault.clem@gmail.com>
Mon, 17 Jun 2019 14:13:28 +0000 (16:13 +0200)
Write and test states are now separate and need to be explicit.

Also add asserts when trying to write without test enabled.

source/blender/draw/engines/eevee/eevee_materials.c
source/blender/draw/engines/eevee/eevee_subsurface.c
source/blender/draw/engines/workbench/workbench_deferred.c
source/blender/draw/intern/DRW_render.h
source/blender/draw/intern/draw_manager_exec.c

index 5ac4545d223e7ffade18d6cb8d3719ca547648ab..f5f3a7a70e3d7c7b3b410464c22f66f9b06ec460 100644 (file)
@@ -1078,7 +1078,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
 
   {
     DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
 
   {
     DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
-                      DRW_STATE_WRITE_STENCIL);
+                      DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS);
     DRW_PASS_CREATE(psl->sss_pass, state);
     DRW_PASS_CREATE(psl->sss_pass_cull, state | DRW_STATE_CULL_BACK);
     e_data.sss_count = 0;
     DRW_PASS_CREATE(psl->sss_pass, state);
     DRW_PASS_CREATE(psl->sss_pass_cull, state | DRW_STATE_CULL_BACK);
     e_data.sss_count = 0;
index 0e451dc41da6eeb9337fff2391933209ee038d3c..249562395084c7c02f176ec6ac4a044166bbfc2e 100644 (file)
@@ -174,7 +174,7 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
 
     /* Make the opaque refraction pass mask the sss. */
     DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
 
     /* Make the opaque refraction pass mask the sss. */
     DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
-                     DRW_STATE_WRITE_STENCIL;
+                     DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
     DRW_pass_state_set(vedata->psl->refract_pass, state);
     DRW_pass_foreach_shgroup(vedata->psl->refract_pass, &set_shgrp_stencil, NULL);
   }
     DRW_pass_state_set(vedata->psl->refract_pass, state);
     DRW_pass_foreach_shgroup(vedata->psl->refract_pass, &set_shgrp_stencil, NULL);
   }
index 28ac6d0c274372babf500550f52eaf4b5337cbdf..f2f211d1db95eec1d1c0b26884680a7d3da02fd5 100644 (file)
@@ -760,8 +760,10 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
       DRWState depth_fail_state = DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR |
                                   DRW_STATE_BLEND_ADD;
 #else
       DRWState depth_fail_state = DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR |
                                   DRW_STATE_BLEND_ADD;
 #else
-      DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_PASS;
-      DRWState depth_fail_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL;
+      DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_PASS |
+                                  DRW_STATE_STENCIL_ALWAYS;
+      DRWState depth_fail_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL |
+                                  DRW_STATE_STENCIL_ALWAYS;
 #endif
       psl->shadow_depth_pass_pass = DRW_pass_create("Shadow Pass", depth_pass_state);
       psl->shadow_depth_pass_mani_pass = DRW_pass_create("Shadow Pass Mani", depth_pass_state);
 #endif
       psl->shadow_depth_pass_pass = DRW_pass_create("Shadow Pass", depth_pass_state);
       psl->shadow_depth_pass_mani_pass = DRW_pass_create("Shadow Pass Mani", depth_pass_state);
@@ -1246,11 +1248,11 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata)
     DRW_draw_pass(psl->shadow_depth_fail_caps_mani_pass);
 
     if (GHOST_ENABLED(psl)) {
     DRW_draw_pass(psl->shadow_depth_fail_caps_mani_pass);
 
     if (GHOST_ENABLED(psl)) {
-      /* We need to set the stencil buffer to 0 where Ghost objects
+      /* We need to set the stencil buffer to 0 where Ghost objects are
        * else they will get shadow and even badly shadowed. */
        * else they will get shadow and even badly shadowed. */
-      DRW_pass_state_set(psl->ghost_prepass_pass, DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL);
-      DRW_pass_state_set(psl->ghost_prepass_hair_pass,
-                         DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL);
+      DRWState state = DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
+      DRW_pass_state_set(psl->ghost_prepass_pass, state);
+      DRW_pass_state_set(psl->ghost_prepass_hair_pass, state);
 
       DRW_draw_pass(psl->ghost_prepass_pass);
       DRW_draw_pass(psl->ghost_prepass_hair_pass);
 
       DRW_draw_pass(psl->ghost_prepass_pass);
       DRW_draw_pass(psl->ghost_prepass_hair_pass);
@@ -1274,9 +1276,9 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata)
     GPU_framebuffer_bind(dfbl->depth_only_fb);
     GPU_framebuffer_clear_stencil(dfbl->depth_only_fb, 0xFF);
 
     GPU_framebuffer_bind(dfbl->depth_only_fb);
     GPU_framebuffer_clear_stencil(dfbl->depth_only_fb, 0xFF);
 
-    DRW_pass_state_set(psl->ghost_prepass_pass, DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL);
-    DRW_pass_state_set(psl->ghost_prepass_hair_pass,
-                       DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL);
+    DRWState state = DRW_STATE_DEPTH_EQUAL | DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
+    DRW_pass_state_set(psl->ghost_prepass_pass, state);
+    DRW_pass_state_set(psl->ghost_prepass_hair_pass, state);
 
     DRW_draw_pass(psl->ghost_prepass_pass);
     DRW_draw_pass(psl->ghost_prepass_hair_pass);
 
     DRW_draw_pass(psl->ghost_prepass_pass);
     DRW_draw_pass(psl->ghost_prepass_hair_pass);
index 98d4c3bfa5380be5e843f048404f10eb7de39320..d68525e62ae33cda2ab3189d883ab4ae76a9e94f 100644 (file)
@@ -332,26 +332,27 @@ typedef enum {
   DRW_STATE_CULL_BACK = (1 << 11),
   DRW_STATE_CULL_FRONT = (1 << 12),
   /** Stencil test */
   DRW_STATE_CULL_BACK = (1 << 11),
   DRW_STATE_CULL_FRONT = (1 << 12),
   /** Stencil test */
-  DRW_STATE_STENCIL_EQUAL = (1 << 13),
-  DRW_STATE_STENCIL_NEQUAL = (1 << 14),
+  DRW_STATE_STENCIL_ALWAYS = (1 << 13),
+  DRW_STATE_STENCIL_EQUAL = (1 << 14),
+  DRW_STATE_STENCIL_NEQUAL = (1 << 15),
 
   /** Blend state */
 
   /** Blend state */
-  DRW_STATE_BLEND_ADD = (1 << 15),
+  DRW_STATE_BLEND_ADD = (1 << 16),
   /** Same as additive but let alpha accumulate without premult. */
   /** Same as additive but let alpha accumulate without premult. */
-  DRW_STATE_BLEND_ADD_FULL = (1 << 16),
+  DRW_STATE_BLEND_ADD_FULL = (1 << 17),
   /** Standard alpha blending. */
   /** Standard alpha blending. */
-  DRW_STATE_BLEND_ALPHA = (1 << 17),
+  DRW_STATE_BLEND_ALPHA = (1 << 18),
   /** Use that if color is already premult by alpha. */
   /** Use that if color is already premult by alpha. */
-  DRW_STATE_BLEND_ALPHA_PREMUL = (1 << 18),
-  DRW_STATE_BLEND_ALPHA_UNDER_PREMUL = (1 << 19),
-  DRW_STATE_BLEND_OIT = (1 << 20),
-  DRW_STATE_BLEND_MUL = (1 << 21),
-
-  DRW_STATE_CLIP_PLANES = (1 << 22),
-  DRW_STATE_WIRE_SMOOTH = (1 << 23),
-  DRW_STATE_FIRST_VERTEX_CONVENTION = (1 << 24),
+  DRW_STATE_BLEND_ALPHA_PREMUL = (1 << 19),
+  DRW_STATE_BLEND_ALPHA_UNDER_PREMUL = (1 << 20),
+  DRW_STATE_BLEND_OIT = (1 << 21),
+  DRW_STATE_BLEND_MUL = (1 << 22),
+
+  DRW_STATE_CLIP_PLANES = (1 << 23),
+  DRW_STATE_WIRE_SMOOTH = (1 << 24),
+  DRW_STATE_FIRST_VERTEX_CONVENTION = (1 << 25),
   /** DO NOT USE. Assumed always enabled. Only used internally. */
   /** DO NOT USE. Assumed always enabled. Only used internally. */
-  DRW_STATE_PROGRAM_POINT_SIZE = (1 << 25),
+  DRW_STATE_PROGRAM_POINT_SIZE = (1 << 26),
 } DRWState;
 
 #define DRW_STATE_DEFAULT \
 } DRWState;
 
 #define DRW_STATE_DEFAULT \
@@ -359,6 +360,14 @@ typedef enum {
 #define DRW_STATE_RASTERIZER_ENABLED \
   (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_STENCIL | \
    DRW_STATE_WRITE_STENCIL_SHADOW_PASS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL)
 #define DRW_STATE_RASTERIZER_ENABLED \
   (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_STENCIL | \
    DRW_STATE_WRITE_STENCIL_SHADOW_PASS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL)
+#define DRW_STATE_DEPTH_TEST_ENABLED \
+  (DRW_STATE_DEPTH_ALWAYS | DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_LESS_EQUAL | \
+   DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER | DRW_STATE_DEPTH_GREATER_EQUAL)
+#define DRW_STATE_STENCIL_TEST_ENABLED \
+  (DRW_STATE_STENCIL_ALWAYS | DRW_STATE_STENCIL_EQUAL | DRW_STATE_STENCIL_NEQUAL)
+#define DRW_STATE_WRITE_STENCIL_ENABLED \
+  (DRW_STATE_WRITE_STENCIL | DRW_STATE_WRITE_STENCIL_SHADOW_PASS | \
+   DRW_STATE_WRITE_STENCIL_SHADOW_FAIL)
 
 typedef enum {
   DRW_ATTR_INT,
 
 typedef enum {
   DRW_ATTR_INT,
index 85490e2f81d1b2c0d82496dd5d596a7c4d3b1c43..2596570c022914a2f455170a0adb4b89e906de8a 100644 (file)
@@ -79,6 +79,34 @@ void drw_state_set(DRWState state)
     }
   }
 
     }
   }
 
+  /* Stencil Write */
+  {
+    DRWState test;
+    if (CHANGED_ANY_STORE_VAR(DRW_STATE_WRITE_STENCIL_ENABLED, test)) {
+      /* Stencil Write */
+      if (test) {
+        glStencilMask(0xFF);
+        if (test & DRW_STATE_WRITE_STENCIL) {
+          glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+        }
+        else if (test & DRW_STATE_WRITE_STENCIL_SHADOW_PASS) {
+          glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
+          glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
+        }
+        else if (test & DRW_STATE_WRITE_STENCIL_SHADOW_FAIL) {
+          glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
+          glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
+        }
+        else {
+          BLI_assert(0);
+        }
+      }
+      else {
+        glStencilMask(0x00);
+      }
+    }
+  }
+
   /* Color Write */
   {
     int test;
   /* Color Write */
   {
     int test;
@@ -130,10 +158,7 @@ void drw_state_set(DRWState state)
   /* Depth Test */
   {
     DRWState test;
   /* Depth Test */
   {
     DRWState test;
-    if (CHANGED_ANY_STORE_VAR(DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_LESS_EQUAL |
-                                  DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER |
-                                  DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_DEPTH_ALWAYS,
-                              test)) {
+    if (CHANGED_ANY_STORE_VAR(DRW_STATE_DEPTH_TEST_ENABLED, test)) {
       if (test) {
         glEnable(GL_DEPTH_TEST);
 
       if (test) {
         glEnable(GL_DEPTH_TEST);
 
@@ -165,6 +190,20 @@ void drw_state_set(DRWState state)
     }
   }
 
     }
   }
 
+  /* Stencil Test */
+  {
+    int test;
+    if (CHANGED_ANY_STORE_VAR(DRW_STATE_STENCIL_TEST_ENABLED, test)) {
+      DST.stencil_mask = STENCIL_UNDEFINED;
+      if (test) {
+        glEnable(GL_STENCIL_TEST);
+      }
+      else {
+        glDisable(GL_STENCIL_TEST);
+      }
+    }
+  }
+
   /* Wire Width */
   {
     int test;
   /* Wire Width */
   {
     int test;
@@ -264,49 +303,6 @@ void drw_state_set(DRWState state)
     }
   }
 
     }
   }
 
-  /* Stencil */
-  {
-    DRWState test;
-    if (CHANGED_ANY_STORE_VAR(DRW_STATE_WRITE_STENCIL | DRW_STATE_WRITE_STENCIL_SHADOW_PASS |
-                                  DRW_STATE_WRITE_STENCIL_SHADOW_FAIL | DRW_STATE_STENCIL_EQUAL |
-                                  DRW_STATE_STENCIL_NEQUAL,
-                              test)) {
-      if (test) {
-        glEnable(GL_STENCIL_TEST);
-        /* Stencil Write */
-        if ((state & DRW_STATE_WRITE_STENCIL) != 0) {
-          glStencilMask(0xFF);
-          glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-        }
-        else if ((state & DRW_STATE_WRITE_STENCIL_SHADOW_PASS) != 0) {
-          glStencilMask(0xFF);
-          glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
-          glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
-        }
-        else if ((state & DRW_STATE_WRITE_STENCIL_SHADOW_FAIL) != 0) {
-          glStencilMask(0xFF);
-          glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
-          glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
-        }
-        /* Stencil Test */
-        else if ((state & (DRW_STATE_STENCIL_EQUAL | DRW_STATE_STENCIL_NEQUAL)) != 0) {
-          glStencilMask(0x00); /* disable write */
-          DST.stencil_mask = STENCIL_UNDEFINED;
-        }
-        else {
-          BLI_assert(0);
-        }
-      }
-      else {
-        /* disable write & test */
-        DST.stencil_mask = 0;
-        glStencilMask(0x00);
-        glStencilFunc(GL_ALWAYS, 0, 0xFF);
-        glDisable(GL_STENCIL_TEST);
-      }
-    }
-  }
-
   /* Provoking Vertex */
   {
     int test;
   /* Provoking Vertex */
   {
     int test;
@@ -331,11 +327,9 @@ static void drw_stencil_set(uint mask)
 {
   if (DST.stencil_mask != mask) {
     DST.stencil_mask = mask;
 {
   if (DST.stencil_mask != mask) {
     DST.stencil_mask = mask;
-    /* Stencil Write */
-    if ((DST.state & DRW_STATE_WRITE_STENCIL) != 0) {
+    if ((DST.state & DRW_STATE_STENCIL_ALWAYS) != 0) {
       glStencilFunc(GL_ALWAYS, mask, 0xFF);
     }
       glStencilFunc(GL_ALWAYS, mask, 0xFF);
     }
-    /* Stencil Test */
     else if ((DST.state & DRW_STATE_STENCIL_EQUAL) != 0) {
       glStencilFunc(GL_EQUAL, mask, 0xFF);
     }
     else if ((DST.state & DRW_STATE_STENCIL_EQUAL) != 0) {
       glStencilFunc(GL_EQUAL, mask, 0xFF);
     }
@@ -352,6 +346,18 @@ void DRW_state_reset_ex(DRWState state)
   drw_state_set(state);
 }
 
   drw_state_set(state);
 }
 
+static void drw_state_validate(void)
+{
+  /* Cannot write to stencil buffer without stencil test. */
+  if ((DST.state & DRW_STATE_WRITE_STENCIL_ENABLED)) {
+    BLI_assert(DST.state & DRW_STATE_STENCIL_TEST_ENABLED);
+  }
+  /* Cannot write to depth buffer without depth test. */
+  if ((DST.state & DRW_STATE_WRITE_DEPTH)) {
+    BLI_assert(DST.state & DRW_STATE_DEPTH_TEST_ENABLED);
+  }
+}
+
 /**
  * Use with care, intended so selection code can override passes depth settings,
  * which is important for selection to work properly.
 /**
  * Use with care, intended so selection code can override passes depth settings,
  * which is important for selection to work properly.
@@ -980,6 +986,7 @@ static void drw_draw_pass_ex(DRWPass *pass,
   drw_state_set(DST.state | DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR);
 
   drw_state_set(pass->state);
   drw_state_set(DST.state | DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR);
 
   drw_state_set(pass->state);
+  drw_state_validate();
 
   DRW_stats_query_start(pass->name);
 
 
   DRW_stats_query_start(pass->name);