diff options
author | Jason Fielder <jason_apple> | 2022-09-22 18:40:45 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2022-09-22 18:43:04 +0300 |
commit | 1514e1a5b7e15ec0c11cd40c2b9389982bd5d00e (patch) | |
tree | 3c7028d7d8e9a96b3047d2e5ad84f0c2276f2530 /source/blender/gpu/shaders | |
parent | 697b447c2069bbbbaa9929aab0ea1f66ef8bf4d0 (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/shaders')
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_3D_polyline_vert_no_geom.glsl | 162 | ||||
-rw-r--r-- | source/blender/gpu/shaders/infos/gpu_shader_3D_polyline_info.hh | 39 |
2 files changed, 201 insertions, 0 deletions
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"); |