[Bf-blender-cvs] [9ec20f2ede3] master: Metal: Add support for Workbench Shadows.
Jason Fielder
noreply at git.blender.org
Thu Dec 8 23:03:20 CET 2022
Commit: 9ec20f2ede3c894b6c92603002aee11aa6a858a2
Author: Jason Fielder
Date: Thu Dec 8 23:02:52 2022 +0100
Branches: master
https://developer.blender.org/rB9ec20f2ede3c894b6c92603002aee11aa6a858a2
Metal: Add support for Workbench Shadows.
Implementing non-geometry-shader path for rendering stencil shadows,
used by the workbench engine.
Patch also contains a few small modifications to Create-info to ensure
usage of gl_FragDepth is explicitly specified.
This is required for testing of the patch.
Authored by Apple: Michael Parkin-White
Ref T96261
Reviewed By: fclem
Differential Revision: https://developer.blender.org/D16436
===================================================================
M source/blender/draw/CMakeLists.txt
M source/blender/draw/engines/workbench/shaders/infos/workbench_shadow_info.hh
A source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_vert_no_geom.glsl
A source/blender/draw/engines/workbench/shaders/workbench_shadow_vert_no_geom.glsl
M source/blender/gpu/intern/gpu_shader_create_info.cc
M source/blender/gpu/intern/gpu_shader_create_info.hh
M source/blender/gpu/metal/kernels/depth_2d_update_info.hh
M source/blender/gpu/metal/mtl_batch.mm
M source/blender/gpu/metal/mtl_shader_generator.mm
M source/blender/gpu/metal/mtl_state.mm
===================================================================
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index e8a7167eda5..513029bc675 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -477,9 +477,11 @@ set(GLSL_SRC
engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl
engines/workbench/shaders/workbench_prepass_vert.glsl
engines/workbench/shaders/workbench_shadow_caps_geom.glsl
+ engines/workbench/shaders/workbench_shadow_caps_vert_no_geom.glsl
engines/workbench/shaders/workbench_shadow_debug_frag.glsl
engines/workbench/shaders/workbench_shadow_geom.glsl
engines/workbench/shaders/workbench_shadow_vert.glsl
+ engines/workbench/shaders/workbench_shadow_vert_no_geom.glsl
engines/workbench/shaders/workbench_transparent_accum_frag.glsl
engines/workbench/shaders/workbench_transparent_resolve_frag.glsl
engines/workbench/shaders/workbench_volume_frag.glsl
diff --git a/source/blender/draw/engines/workbench/shaders/infos/workbench_shadow_info.hh b/source/blender/draw/engines/workbench/shaders/infos/workbench_shadow_info.hh
index c66e4d61233..3d86ef6e78c 100644
--- a/source/blender/draw/engines/workbench/shaders/infos/workbench_shadow_info.hh
+++ b/source/blender/draw/engines/workbench/shaders/infos/workbench_shadow_info.hh
@@ -13,12 +13,17 @@ GPU_SHADER_INTERFACE_INFO(workbench_shadow_iface, "vData")
GPU_SHADER_CREATE_INFO(workbench_shadow_common)
.vertex_in(0, Type::VEC3, "pos")
- .vertex_out(workbench_shadow_iface)
.push_constant(Type::FLOAT, "lightDistance")
.push_constant(Type::VEC3, "lightDirection")
- .vertex_source("workbench_shadow_vert.glsl")
.additional_info("draw_mesh");
+/* `workbench_shadow_vert.glsl` only used by geometry shader path.
+ * Vertex output iface not needed by non-geometry shader variants,
+ * as only gl_Position is returned. */
+GPU_SHADER_CREATE_INFO(workbench_shadow_common_geom)
+ .vertex_out(workbench_shadow_iface)
+ .vertex_source("workbench_shadow_vert.glsl");
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -26,13 +31,25 @@ GPU_SHADER_CREATE_INFO(workbench_shadow_common)
* \{ */
GPU_SHADER_CREATE_INFO(workbench_shadow_manifold)
+ .additional_info("workbench_shadow_common_geom")
.geometry_layout(PrimitiveIn::LINES_ADJACENCY, PrimitiveOut::TRIANGLE_STRIP, 4, 1)
.geometry_source("workbench_shadow_geom.glsl");
GPU_SHADER_CREATE_INFO(workbench_shadow_no_manifold)
+ .additional_info("workbench_shadow_common_geom")
.geometry_layout(PrimitiveIn::LINES_ADJACENCY, PrimitiveOut::TRIANGLE_STRIP, 4, 2)
.geometry_source("workbench_shadow_geom.glsl");
+GPU_SHADER_CREATE_INFO(workbench_shadow_manifold_no_geom)
+ .vertex_source("workbench_shadow_vert_no_geom.glsl")
+ /* Inject SSBO vertex fetch declaration using 2 output triangles. */
+ .define("VAR_MANIFOLD", "\n#pragma USE_SSBO_VERTEX_FETCH(TriangleList, 6)");
+
+GPU_SHADER_CREATE_INFO(workbench_shadow_no_manifold_no_geom)
+ .vertex_source("workbench_shadow_vert_no_geom.glsl")
+ /* Inject SSBO vertex fetch declaration using 4 output triangles. */
+ .define("VAR_NO_MANIFOLD", "\n#pragma USE_SSBO_VERTEX_FETCH(TriangleList, 12)");
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -40,9 +57,13 @@ GPU_SHADER_CREATE_INFO(workbench_shadow_no_manifold)
* \{ */
GPU_SHADER_CREATE_INFO(workbench_shadow_caps)
+ .additional_info("workbench_shadow_common_geom")
.geometry_layout(PrimitiveIn::TRIANGLES, PrimitiveOut::TRIANGLE_STRIP, 3, 2)
.geometry_source("workbench_shadow_caps_geom.glsl");
+GPU_SHADER_CREATE_INFO(workbench_shadow_caps_no_geom)
+ .vertex_source("workbench_shadow_caps_vert_no_geom.glsl");
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_vert_no_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_vert_no_geom.glsl
new file mode 100644
index 00000000000..8f21b55fa18
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_vert_no_geom.glsl
@@ -0,0 +1,105 @@
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma USE_SSBO_VERTEX_FETCH(TriangleList, 6)
+
+#ifdef DOUBLE_MANIFOLD
+# define vert_len 6 /* Triangle Strip with 6 verts = 4 triangles = 12 verts*/
+# define emit_triangle_count 2
+#else
+# define vert_len 6 /* Triangle Strip with 6 verts = 4 triangles = 12 verts*/
+# define emit_triangle_count 2
+#endif
+
+struct VertexData {
+ vec3 pos; /* local position */
+ vec4 frontPosition; /* final ndc position */
+ vec4 backPosition;
+};
+
+/* Input geometry triangle list. */
+VertexData vData[3] = {};
+
+#define DISCARD_VERTEX \
+ gl_Position = vec4(0.0); \
+ return;
+
+vec4 get_pos(int v, bool backface)
+{
+ return (backface) ? vData[v].backPosition : vData[v].frontPosition;
+}
+
+void emit_cap(const bool front, bool reversed, int triangle_vertex_id)
+{
+ /* Inverse. */
+ ivec2 idx = (reversed) ? ivec2(2, 1) : ivec2(1, 2);
+
+ /* Output position depending on vertex ID. */
+ switch (triangle_vertex_id) {
+ case 0: {
+ gl_Position = (front) ? vData[0].frontPosition : vData[0].backPosition;
+ } break;
+
+ case 1: {
+ gl_Position = (front) ? vData[idx.x].frontPosition : vData[idx.y].backPosition;
+ } break;
+
+ case 2: {
+ gl_Position = (front) ? vData[idx.y].frontPosition : vData[idx.x].backPosition;
+ } break;
+ }
+
+ /* Apply depth bias. Prevents Z-fighting artifacts when fast-math is enabled. */
+ gl_Position.z += 0.00005;
+}
+
+void main()
+{
+ /* Output Data indexing. */
+ int input_prim_index = int(gl_VertexID / 6);
+ int output_vertex_id = gl_VertexID % 6;
+ int output_triangle_id = output_vertex_id / 3;
+
+ /* Source primitive data location derived from output primitive. */
+ int input_base_vertex_id = input_prim_index * 3;
+
+ /* In data is triangles - Should be guaranteed. */
+ /* Read input position data. */
+ vData[0].pos = vertex_fetch_attribute(input_base_vertex_id + 0, pos, vec3);
+ vData[1].pos = vertex_fetch_attribute(input_base_vertex_id + 1, pos, vec3);
+ vData[2].pos = vertex_fetch_attribute(input_base_vertex_id + 2, pos, vec3);
+
+ /* Calculate front/back Positions. */
+ vData[0].frontPosition = point_object_to_ndc(vData[0].pos);
+ vData[0].backPosition = point_object_to_ndc(vData[0].pos + lightDirection * lightDistance);
+
+ vData[1].frontPosition = point_object_to_ndc(vData[1].pos);
+ vData[1].backPosition = point_object_to_ndc(vData[1].pos + lightDirection * lightDistance);
+
+ vData[2].frontPosition = point_object_to_ndc(vData[2].pos);
+ vData[2].backPosition = point_object_to_ndc(vData[2].pos + lightDirection * lightDistance);
+
+ /* Geometry shader equivalent calc. */
+ vec3 v10 = vData[0].pos - vData[1].pos;
+ vec3 v12 = vData[2].pos - vData[1].pos;
+
+ vec3 n = cross(v12, v10);
+ float facing = dot(n, lightDirection);
+
+ bool backface = facing > 0.0;
+
+#ifdef DOUBLE_MANIFOLD
+ /* In case of non manifold geom, we only increase/decrease
+ * the stencil buffer by one but do every faces as they were facing the light. */
+ bool invert = backface;
+ const bool is_manifold = false;
+#else
+ const bool invert = false;
+ const bool is_manifold = true;
+#endif
+
+ if (!is_manifold || !backface) {
+ bool do_front = (output_triangle_id==0)?true:false;
+ emit_cap(do_front, invert, output_vertex_id%3);
+ } else {
+ DISCARD_VERTEX
+ }
+}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert_no_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert_no_geom.glsl
new file mode 100644
index 00000000000..277f85ca457
--- /dev/null
+++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert_no_geom.glsl
@@ -0,0 +1,160 @@
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+
+/* Two variants, split pass, generates either 2 triangles or 6 triangles depending on input
+ * geometry manifold type */
+
+#ifdef DOUBLE_MANIFOLD
+# define vert_len 12 /* Triangle Strip with 6 verts = 4 triangles = 12 verts*/
+# define emit_triangle_count 4
+#else
+# define vert_len 6 /* Triang;e Strip with 4 verts = 2 triangles = 6 verts*/
+# define emit_triangle_count 2
+#endif
+
+#define DEGENERATE_TRIS_WORKAROUND
+#define DEGENERATE_TRIS_AREA_THRESHOLD 4e-15
+
+#define len_sqr(a) dot(a, a)
+
+struct VertexData {
+ vec3 pos; /* local position */
+ vec4 frontPosition; /* final ndc position */
+ vec4 backPosition;
+};
+
+#define DISCARD_VERTEX \
+ gl_Position = vec4(0.0); \
+ return;
+
+/* Extra positions for primary triangle */
+VertexData vData[4];
+
+void extrude_edge(bool invert, int output_vertex_id)
+{
+ /* Reverse order if backfacing the light. */
+ ivec2 idx = (invert) ? ivec2(1, 2) : ivec2(2, 1);
+
+ /* Either outputs first or second quad, depending on double manifold status. */
+ int triangle_vertex_id = output_vertex_id % 6;
+
+ switch (triangle_vertex_id) {
+ case 0:
+ gl_Position = vData[idx.x].frontPosition;
+ break;
+ case 1:
+ case 4:
+ gl_Position = vData[idx.y].frontPosition;
+ break;
+ case 2:
+ case 3:
+ gl_Position = vData[idx.x].backPosition;
+ break;
+ case 5:
+ gl_Position = vData[idx.y].backPosition;
+ break;
+ }
+
+ /* Apply depth bias. Prevents Z-fighting artifacts when fast-math is enabled. */
+ gl_Position.z += 0.00005;
+}
+
+void main()
+{
+ /* Output Data indexing. */
+#ifdef DOUBLE_MANIFOLD
+ int input_prim_index = int(gl_VertexID / 12);
+ int output_vertex_id = gl_VertexID % 12;
+ int output_quad_id = (output_vertex_id >= 6) ? 1 : 0;
+#else
+ int input_prim_index = int(gl_VertexID / 6);
+ int output_vertex_id = gl_VertexID % 6;
+ int output_quad_id = 0;
+#endif
+
+ /* Source primitive data location derived from output primitive. */
+ int input_base_vertex_id = (input_prim_index * 4);
+
+ /* IN DATA is lines_adjacency - Should be guaranteed. */
+ /* Read input position data. */
+ vData[0].pos = vertex_fetch_attribute(input_base_vertex_id + 0, pos, vec3);
+ vData[1].pos = vertex_fetc
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list