[Bf-blender-cvs] [34051fcc12f] master: EEVEE: Fix volumetric resolve in large scenes.

Jeroen Bakker noreply at git.blender.org
Tue Sep 13 15:05:27 CEST 2022


Commit: 34051fcc12f388375697dcfc6da53e9909058fe1
Author: Jeroen Bakker
Date:   Tue Sep 13 15:03:04 2022 +0200
Branches: master
https://developer.blender.org/rB34051fcc12f388375697dcfc6da53e9909058fe1

EEVEE: Fix volumetric resolve in large scenes.

On NVIDIA volumetric resolve failed for large production scenes.
The result would remove most color from the final render. The cause
seems to be a faulty driver.

This change ported the fragment shader to a compute shader which
would select a different compiler branch and didn't show the error.

===================================================================

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/engines/eevee/eevee_private.h
M	source/blender/draw/engines/eevee/eevee_shaders.c
M	source/blender/draw/engines/eevee/eevee_volumes.c
A	source/blender/draw/engines/eevee/shaders/volumetric_resolve_comp.glsl
M	source/blender/draw/intern/DRW_render.h
M	source/blender/draw/intern/draw_manager_shader.c
M	source/blender/draw/tests/shaders_test.cc

===================================================================

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 32103692421..e6b532ed25a 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -388,6 +388,7 @@ set(GLSL_SRC
   engines/eevee/shaders/volumetric_frag.glsl
   engines/eevee/shaders/volumetric_geom.glsl
   engines/eevee/shaders/volumetric_vert.glsl
+  engines/eevee/shaders/volumetric_resolve_comp.glsl
   engines/eevee/shaders/volumetric_resolve_frag.glsl
   engines/eevee/shaders/volumetric_scatter_frag.glsl
   engines/eevee/shaders/volumetric_integration_frag.glsl
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 8c6d96254ae..573c29b78a1 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -1261,6 +1261,7 @@ struct GPUShader *EEVEE_shaders_volumes_scatter_sh_get(void);
 struct GPUShader *EEVEE_shaders_volumes_scatter_with_lights_sh_get(void);
 struct GPUShader *EEVEE_shaders_volumes_integration_sh_get(void);
 struct GPUShader *EEVEE_shaders_volumes_resolve_sh_get(bool accum);
+struct GPUShader *EEVEE_shaders_volumes_resolve_comp_sh_get(bool float_target);
 struct GPUShader *EEVEE_shaders_volumes_accum_sh_get(void);
 struct GPUShader *EEVEE_shaders_ggx_lut_sh_get(void);
 struct GPUShader *EEVEE_shaders_ggx_refraction_lut_sh_get(void);
diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c
index 04d1168a30d..a7290b3894e 100644
--- a/source/blender/draw/engines/eevee/eevee_shaders.c
+++ b/source/blender/draw/engines/eevee/eevee_shaders.c
@@ -133,6 +133,7 @@ static struct {
   struct GPUShader *scatter_with_lights_sh;
   struct GPUShader *volumetric_integration_sh;
   struct GPUShader *volumetric_resolve_sh[2];
+  struct GPUShader *volumetric_resolve_comp_sh[2];
   struct GPUShader *volumetric_accum_sh;
 
   /* Shader strings */
@@ -261,6 +262,7 @@ extern char datatoc_volumetric_frag_glsl[];
 extern char datatoc_volumetric_geom_glsl[];
 extern char datatoc_volumetric_integration_frag_glsl[];
 extern char datatoc_volumetric_lib_glsl[];
+extern char datatoc_volumetric_resolve_comp_glsl[];
 extern char datatoc_volumetric_resolve_frag_glsl[];
 extern char datatoc_volumetric_scatter_frag_glsl[];
 extern char datatoc_volumetric_vert_glsl[];
@@ -903,6 +905,20 @@ struct GPUShader *EEVEE_shaders_volumes_resolve_sh_get(bool accum)
   return e_data.volumetric_resolve_sh[index];
 }
 
+struct GPUShader *EEVEE_shaders_volumes_resolve_comp_sh_get(bool float_target)
+{
+  const int index = (float_target ? 1 : 0);
+  if (e_data.volumetric_resolve_comp_sh[index] == NULL) {
+    e_data.volumetric_resolve_comp_sh[index] = DRW_shader_create_compute_with_shaderlib(
+        datatoc_volumetric_resolve_comp_glsl,
+        e_data.lib,
+        float_target ? "#define TARGET_IMG_FLOAT\n" SHADER_DEFINES : SHADER_DEFINES,
+        __func__);
+  }
+
+  return e_data.volumetric_resolve_comp_sh[index];
+}
+
 struct GPUShader *EEVEE_shaders_volumes_accum_sh_get()
 {
   if (e_data.volumetric_accum_sh == NULL) {
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 2d96cffb4ba..b2e5a0abe94 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -396,18 +396,37 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
         grp, NULL, USE_VOLUME_OPTI ? 1 : common_data->vol_tex_size[2]);
 
     DRW_PASS_CREATE(psl->volumetric_resolve_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM);
-    grp = DRW_shgroup_create(EEVEE_shaders_volumes_resolve_sh_get(false),
-                             psl->volumetric_resolve_ps);
-    DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter);
-    DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
-    DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
-    DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
-    DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
-    DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
-    DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
-    DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+    if (GPU_compute_shader_support() && GPU_shader_image_load_store_support()) {
+      const bool use_float_target = DRW_state_is_image_render();
+      grp = DRW_shgroup_create(EEVEE_shaders_volumes_resolve_comp_sh_get(use_float_target),
+                               psl->volumetric_resolve_ps);
+      DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter);
+      DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
+      DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
+      DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+      DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+      DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+      DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+      DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+      DRW_shgroup_uniform_image_ref(grp, "target_img", &txl->color);
 
-    DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+      const float *size = DRW_viewport_size_get();
+      DRW_shgroup_call_compute(grp, size[0], size[1], 1);
+    }
+    else {
+      grp = DRW_shgroup_create(EEVEE_shaders_volumes_resolve_sh_get(false),
+                               psl->volumetric_resolve_ps);
+      DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter);
+      DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
+      DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
+      DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+      DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+      DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+      DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+      DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+
+      DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+    }
   }
 }
 
@@ -546,11 +565,16 @@ void EEVEE_volumes_resolve(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
     }
 
     /* Apply for opaque geometry. */
-    GPU_framebuffer_bind(fbl->main_color_fb);
-    DRW_draw_pass(psl->volumetric_resolve_ps);
+    if (GPU_compute_shader_support() && GPU_shader_image_load_store_support()) {
+      DRW_draw_pass(psl->volumetric_resolve_ps);
+    }
+    else {
+      GPU_framebuffer_bind(fbl->main_color_fb);
+      DRW_draw_pass(psl->volumetric_resolve_ps);
 
-    /* Restore. */
-    GPU_framebuffer_bind(fbl->main_fb);
+      /* Restore. */
+      GPU_framebuffer_bind(fbl->main_fb);
+    }
   }
 }
 
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_resolve_comp.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_resolve_comp.glsl
new file mode 100644
index 00000000000..2b0139ff923
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_resolve_comp.glsl
@@ -0,0 +1,38 @@
+
+#pragma BLENDER_REQUIRE(volumetric_lib.glsl)
+
+/* Based on Frosbite Unified Volumetric.
+ * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
+
+/* Step 4 : Apply final integration on top of the scene color. */
+
+uniform sampler2D inSceneDepth;
+
+layout(local_size_x = 1, local_size_y = 1) in;
+
+#ifdef TARGET_IMG_FLOAT
+layout(binding = 0, rgba32f) uniform image2D target_img;
+#else
+layout(binding = 0, rgba16f) uniform image2D target_img;
+#endif
+
+void main()
+{
+  ivec2 co = ivec2(gl_GlobalInvocationID.xy);
+  vec2 uvs = co / vec2(textureSize(inSceneDepth, 0));
+  float scene_depth = texture(inSceneDepth, uvs).r;
+
+  vec3 transmittance, scattering;
+  volumetric_resolve(uvs, scene_depth, transmittance, scattering);
+
+  /* Approximate volume alpha by using a monochromatic transmittance
+   * and adding it to the scene alpha. */
+  float alpha = dot(transmittance, vec3(1.0 / 3.0));
+
+  vec4 color0 = vec4(scattering, 1.0 - alpha);
+  vec4 color1 = vec4(transmittance, alpha);
+
+  vec4 color_in = imageLoad(target_img, co);
+  vec4 color_out = color0 + color1 * color_in;
+  imageStore(target_img, co, color_out);
+}
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 7b80ffd2b88..b49203d85f6 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -207,6 +207,10 @@ struct GPUShader *DRW_shader_create_with_lib_ex(const char *vert,
                                                 const char *lib,
                                                 const char *defines,
                                                 const char *name);
+struct GPUShader *DRW_shader_create_compute_with_shaderlib(const char *comp,
+                                                           const DRWShaderLibrary *lib,
+                                                           const char *defines,
+                                                           const char *name);
 struct GPUShader *DRW_shader_create_with_shaderlib_ex(const char *vert,
                                                       const char *geom,
                                                       const char *frag,
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 4bc3898c5e7..1ada99093c6 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -297,6 +297,18 @@ GPUShader *DRW_shader_create_with_lib_ex(const char *vert,
   return sh;
 }
 
+GPUShader *DRW_shader_create_compute_with_shaderlib(const char *comp,
+                                                    const DRWShaderLibrary *lib,
+               

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list