Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Fielder <jason_apple>2022-09-22 18:40:45 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-09-22 18:43:04 +0300
commit1514e1a5b7e15ec0c11cd40c2b9389982bd5d00e (patch)
tree3c7028d7d8e9a96b3047d2e5ad84f0c2276f2530 /source/blender/gpu
parent697b447c2069bbbbaa9929aab0ea1f66ef8bf4d0 (diff)
Metal: First set of Geometry Shader alternative implementations using SSBO vertex shader fetch.
These implementations remove dependency on the Geometry pass by instead invoking one vertex shader instance for each expected output vertex, matching what a geometry shader would emit. Each vertex shader instance is then responsible for calculating the same output position based on its vertex_id as the logic would in the geometry shader version. SSBO Vertex fetch enables full random-access into a vertex buffer by binding it as a read-only SSBO. This enables each instance to read neighbouring vertex data to perform contextual calculations as a geometry shader would, for cases where attribute Multiload is not supported. Authored by Apple: Michael Parkin-White Ref T96261 Reviewed By: fclem Differential Revision: https://developer.blender.org/D15901
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/CMakeLists.txt1
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.cc25
-rw-r--r--source/blender/gpu/metal/mtl_shader.mm1
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_polyline_vert_no_geom.glsl162
-rw-r--r--source/blender/gpu/shaders/infos/gpu_shader_3D_polyline_info.hh39
5 files changed, 228 insertions, 0 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 0ce4011b2b4..a322922e86e 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -297,6 +297,7 @@ set(GLSL_SRC
shaders/gpu_shader_3D_polyline_frag.glsl
shaders/gpu_shader_3D_polyline_geom.glsl
shaders/gpu_shader_3D_polyline_vert.glsl
+ shaders/gpu_shader_3D_polyline_vert_no_geom.glsl
shaders/gpu_shader_3D_smooth_color_vert.glsl
shaders/gpu_shader_3D_smooth_color_frag.glsl
shaders/gpu_shader_3D_passthrough_vert.glsl
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.cc b/source/blender/gpu/intern/gpu_shader_create_info.cc
index a18fdcd32df..ff7aa65f03f 100644
--- a/source/blender/gpu/intern/gpu_shader_create_info.cc
+++ b/source/blender/gpu/intern/gpu_shader_create_info.cc
@@ -305,6 +305,31 @@ void gpu_shader_create_info_init()
draw_resource_id_new = draw_resource_id_fallback;
}
+ /* Metal-specific alternatives for Geometry shaders. */
+ if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_METAL)) {
+
+ /* 3D polyline. */
+ gpu_shader_3D_polyline_uniform_color = gpu_shader_3D_polyline_uniform_color_no_geom;
+ gpu_shader_3D_polyline_flat_color = gpu_shader_3D_polyline_flat_color_no_geom;
+ gpu_shader_3D_polyline_smooth_color = gpu_shader_3D_polyline_smooth_color_no_geom;
+ gpu_shader_3D_polyline_uniform_color_clipped =
+ gpu_shader_3D_polyline_uniform_color_clipped_no_geom;
+
+ /* Overlay Edit Mesh. */
+ overlay_edit_mesh_edge = overlay_edit_mesh_edge_no_geom;
+ overlay_edit_mesh_edge_flat = overlay_edit_mesh_edge_flat_no_geom;
+ overlay_edit_mesh_edge_clipped = overlay_edit_mesh_edge_clipped_no_geom;
+ overlay_edit_mesh_edge_flat_clipped = overlay_edit_mesh_edge_flat_clipped_no_geom;
+
+ /* Overlay Armature Shape outline. */
+ overlay_armature_shape_outline = overlay_armature_shape_outline_no_geom;
+ overlay_armature_shape_outline_clipped = overlay_armature_shape_outline_clipped_no_geom;
+
+ /* Overlay Motion Path Line. */
+ overlay_motion_path_line = overlay_motion_path_line_no_geom;
+ overlay_motion_path_line_clipped = overlay_motion_path_line_clipped_no_geom;
+ }
+
for (ShaderCreateInfo *info : g_create_infos->values()) {
if (info->do_static_compilation_) {
info->builtins_ |= gpu_shader_dependency_get_builtins(info->vertex_source_);
diff --git a/source/blender/gpu/metal/mtl_shader.mm b/source/blender/gpu/metal/mtl_shader.mm
index 3b27b60bca0..006d3394378 100644
--- a/source/blender/gpu/metal/mtl_shader.mm
+++ b/source/blender/gpu/metal/mtl_shader.mm
@@ -539,6 +539,7 @@ void MTLShader::push_constant_bindstate_mark_dirty(bool is_dirty)
{
push_constant_modified_ = is_dirty;
}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_polyline_vert_no_geom.glsl b/source/blender/gpu/shaders/gpu_shader_3D_polyline_vert_no_geom.glsl
new file mode 100644
index 00000000000..0ae39dde4c1
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_polyline_vert_no_geom.glsl
@@ -0,0 +1,162 @@
+
+#pragma USE_SSBO_VERTEX_FETCH(TriangleList, 6)
+
+/* Local vars to store results per input vertex. */
+#if !defined(UNIFORM)
+vec4 finalColor_g[2];
+#endif
+
+#ifdef CLIP
+float clip_g[2];
+#endif
+
+#define SMOOTH_WIDTH 1.0
+
+/* Clips point to near clip plane before perspective divide. */
+vec4 clip_line_point_homogeneous_space(vec4 p, vec4 q)
+{
+ if (p.z < -p.w) {
+ /* Just solves p + (q - p) * A; for A when p.z / p.w = -1.0. */
+ float denom = q.z - p.z + q.w - p.w;
+ if (denom == 0.0) {
+ /* No solution. */
+ return p;
+ }
+ float A = (-p.z - p.w) / denom;
+ p = p + (q - p) * A;
+ }
+ return p;
+}
+
+void do_vertex(int index, vec4 pos, vec2 ofs, float flip)
+{
+#if defined(UNIFORM)
+ interp.final_color = color;
+
+#elif defined(FLAT)
+ /* WATCH: Assuming last provoking vertex. */
+ interp.final_color = finalColor_g[index];
+
+#elif defined(SMOOTH)
+ interp.final_color = finalColor_g[index];
+#endif
+
+#ifdef CLIP
+ interp.clip = clip_g[index];
+#endif
+
+ interp.smoothline = flip * (lineWidth + SMOOTH_WIDTH * float(lineSmooth)) * 0.5;
+ gl_Position = pos;
+ gl_Position.xy += flip * ofs * pos.w;
+}
+
+void main()
+{
+ /** Determine output quad primitive structure. */
+ /* Index of the quad primitive. Each quad corresponds to one line in the input primitive. */
+ int quad_id = gl_VertexID / 6;
+
+ /* Determine vertex within the quad (A, B, C)(A, C, D).*/
+ int quad_vertex_id = gl_VertexID % 6;
+
+ uint src_index_a;
+ uint src_index_b;
+ if (vertex_fetch_get_input_prim_type() == GPU_PRIM_LINE_STRIP) {
+ src_index_a = quad_id;
+ src_index_b = quad_id + 1;
+ }
+ else if (vertex_fetch_get_input_prim_type() == GPU_PRIM_LINES) {
+ src_index_a = quad_id * 2;
+ src_index_b = quad_id * 2 + 1;
+ }
+ else if (vertex_fetch_get_input_prim_type() == GPU_PRIM_LINE_LOOP) {
+ src_index_a = quad_id;
+ src_index_b = quad_id + 1;
+ if (quad_id == vertex_fetch_get_input_vert_count() - 1) {
+ src_index_b = 0;
+ }
+ }
+ else {
+ src_index_a = 0;
+ src_index_b = 0;
+ }
+
+ /* Fetch input attributes for line prims -- either provided as vec2 or vec3 -- So we need to
+ * query the type. */
+ vec3 in_pos0, in_pos1;
+ in_pos0 = vec3(0.0);
+ in_pos1 = vec3(0.0);
+ if (vertex_fetch_get_attr_type(pos) == GPU_SHADER_ATTR_TYPE_VEC4) {
+ in_pos0 = vertex_fetch_attribute(src_index_a, pos, vec4).xyz;
+ in_pos1 = vertex_fetch_attribute(src_index_b, pos, vec4).xyz;
+ }
+ else if (vertex_fetch_get_attr_type(pos) == GPU_SHADER_ATTR_TYPE_VEC3) {
+ in_pos0 = vertex_fetch_attribute(src_index_a, pos, vec3);
+ in_pos1 = vertex_fetch_attribute(src_index_b, pos, vec3);
+ }
+ else if (vertex_fetch_get_attr_type(pos) == GPU_SHADER_ATTR_TYPE_VEC2) {
+ in_pos0 = vec3(vertex_fetch_attribute(src_index_a, pos, vec2), 0.0);
+ in_pos1 = vec3(vertex_fetch_attribute(src_index_b, pos, vec2), 0.0);
+ }
+#if !defined(UNIFORM)
+ vec4 in_color0 = vec4(0.0);
+ vec4 in_color1 = vec4(0.0);
+
+ if (vertex_fetch_get_attr_type(color) == GPU_SHADER_ATTR_TYPE_VEC4) {
+ in_color0 = vertex_fetch_attribute(src_index_a, color, vec4);
+ in_color1 = vertex_fetch_attribute(src_index_b, color, vec4);
+ }
+ else if (vertex_fetch_get_attr_type(color) == GPU_SHADER_ATTR_TYPE_VEC3) {
+ in_color0 = vec4(vertex_fetch_attribute(src_index_a, color, vec3), 1.0);
+ in_color1 = vec4(vertex_fetch_attribute(src_index_b, color, vec3), 1.0);
+ }
+ else if (vertex_fetch_get_attr_type(color) == GPU_SHADER_ATTR_TYPE_UCHAR4_NORM) {
+ in_color0 = vec4(vertex_fetch_attribute(src_index_a, color, uchar4)) / vec4(255.0);
+ in_color1 = vec4(vertex_fetch_attribute(src_index_b, color, uchar4)) / vec4(255.0);
+ }
+ else if (vertex_fetch_get_attr_type(color) == GPU_SHADER_ATTR_TYPE_UCHAR3_NORM) {
+ in_color0 = vec4(vec3(vertex_fetch_attribute(src_index_a, color, uchar3)) / vec3(255.0), 1.0);
+ in_color1 = vec4(vec3(vertex_fetch_attribute(src_index_b, color, uchar3)) / vec3(255.0), 1.0);
+ }
+#endif
+
+ /* Calculate Vertex shader for both points in Line. */
+ vec4 out_pos0 = ModelViewProjectionMatrix * vec4(in_pos0, 1.0);
+ vec4 out_pos1 = ModelViewProjectionMatrix * vec4(in_pos1, 1.0);
+#if !defined(UNIFORM)
+ finalColor_g[0] = in_color0;
+ finalColor_g[1] = in_color1;
+#endif
+#ifdef CLIP
+ clip_g[0] = dot(ModelMatrix * vec4(in_pos0, 1.0), ClipPlane);
+ clip_g[1] = dot(ModelMatrix * vec4(in_pos1, 1.0), ClipPlane);
+#endif
+
+ /*** Geometry Shader Alternative. ***/
+ vec4 p0 = clip_line_point_homogeneous_space(out_pos0, out_pos1);
+ vec4 p1 = clip_line_point_homogeneous_space(out_pos1, out_pos0);
+ vec2 e = normalize(((p1.xy / p1.w) - (p0.xy / p0.w)) * viewportSize.xy);
+
+#if 0 /* Hard turn when line direction changes quadrant. */
+ e = abs(e);
+ vec2 ofs = (e.x > e.y) ? vec2(0.0, 1.0 / e.x) : vec2(1.0 / e.y, 0.0);
+#else /* Use perpendicular direction. */
+ vec2 ofs = vec2(-e.y, e.x);
+#endif
+
+ ofs /= viewportSize.xy;
+ ofs *= lineWidth + SMOOTH_WIDTH * float(lineSmooth);
+
+ if (quad_vertex_id == 0) {
+ do_vertex(0, p0, ofs, 1.0);
+ }
+ else if (quad_vertex_id == 1 || quad_vertex_id == 3) {
+ do_vertex(0, p0, ofs, -1.0);
+ }
+ else if (quad_vertex_id == 2 || quad_vertex_id == 5) {
+ do_vertex(1, p1, ofs, 1.0);
+ }
+ else if (quad_vertex_id == 4) {
+ do_vertex(1, p1, ofs, -1.0);
+ }
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/infos/gpu_shader_3D_polyline_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_3D_polyline_info.hh
index 396ee64454c..b486674082e 100644
--- a/source/blender/gpu/shaders/infos/gpu_shader_3D_polyline_info.hh
+++ b/source/blender/gpu/shaders/infos/gpu_shader_3D_polyline_info.hh
@@ -29,12 +29,31 @@ GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline)
.fragment_source("gpu_shader_3D_polyline_frag.glsl")
.additional_info("gpu_srgb_to_framebuffer_space");
+GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_no_geom)
+ .define("SMOOTH_WIDTH", "1.0")
+ .push_constant(Type::MAT4, "ModelViewProjectionMatrix")
+ .push_constant(Type::VEC2, "viewportSize")
+ .push_constant(Type::FLOAT, "lineWidth")
+ .push_constant(Type::BOOL, "lineSmooth")
+ .vertex_in(0, Type::VEC3, "pos")
+ .vertex_out(gpu_shader_3D_polyline_iface)
+ .fragment_out(0, Type::VEC4, "fragColor")
+ .vertex_source("gpu_shader_3D_polyline_vert_no_geom.glsl")
+ .fragment_source("gpu_shader_3D_polyline_frag.glsl")
+ .additional_info("gpu_srgb_to_framebuffer_space");
+
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_uniform_color)
.do_static_compilation(true)
.define("UNIFORM")
.push_constant(Type::VEC4, "color")
.additional_info("gpu_shader_3D_polyline");
+GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_uniform_color_no_geom)
+ .do_static_compilation(true)
+ .define("UNIFORM")
+ .push_constant(Type::VEC4, "color")
+ .additional_info("gpu_shader_3D_polyline_no_geom");
+
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_uniform_color_clipped)
.do_static_compilation(true)
/* TODO(fclem): Put in a UBO to fit the 128byte requirement. */
@@ -43,14 +62,34 @@ GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_uniform_color_clipped)
.define("CLIP")
.additional_info("gpu_shader_3D_polyline_uniform_color");
+GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_uniform_color_clipped_no_geom)
+ .do_static_compilation(true)
+ /* TODO(fclem): Put in an UBO to fit the 128byte requirement. */
+ .push_constant(Type::MAT4, "ModelMatrix")
+ .push_constant(Type::VEC4, "ClipPlane")
+ .define("CLIP")
+ .additional_info("gpu_shader_3D_polyline_uniform_color_no_geom");
+
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_flat_color)
.do_static_compilation(true)
.define("FLAT")
.vertex_in(1, Type::VEC4, "color")
.additional_info("gpu_shader_3D_polyline");
+GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_flat_color_no_geom)
+ .do_static_compilation(true)
+ .define("FLAT")
+ .vertex_in(1, Type::VEC4, "color")
+ .additional_info("gpu_shader_3D_polyline_no_geom");
+
GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_smooth_color)
.do_static_compilation(true)
.define("SMOOTH")
.vertex_in(1, Type::VEC4, "color")
.additional_info("gpu_shader_3D_polyline");
+
+GPU_SHADER_CREATE_INFO(gpu_shader_3D_polyline_smooth_color_no_geom)
+ .do_static_compilation(true)
+ .define("SMOOTH")
+ .vertex_in(1, Type::VEC4, "color")
+ .additional_info("gpu_shader_3D_polyline_no_geom");