Metal: Enable object selection support

Porting conservative depth rendering to use non-geometry shader path for
Metal.

Authored by Apple: Michael Parkin-White

Ref T96261

Reviewed By: fclem
Differential Revision: https://developer.blender.org/D16424
This commit is contained in:
Jason Fielder 2022-12-08 21:57:58 +01:00 committed by Clément Foucault
parent 3608af24fd
commit 2744ee2262
Notes: blender-bot 2023-02-14 09:24:53 +01:00
Referenced by issue #96261, Metal Viewport
7 changed files with 128 additions and 2 deletions

View File

@ -553,6 +553,7 @@ set(GLSL_SRC
engines/basic/shaders/basic_conservative_depth_geom.glsl
engines/basic/shaders/basic_depth_vert.glsl
engines/basic/shaders/basic_depth_vert_conservative_no_geom.glsl
engines/basic/shaders/basic_depth_curves_vert.glsl
engines/basic/shaders/basic_depth_pointcloud_vert.glsl
engines/basic/shaders/basic_depth_frag.glsl

View File

@ -7,9 +7,19 @@ void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
vec3 world_pos = pointcloud_get_pos();
vec3 world_pos, world_nor;
float world_radius;
pointcloud_get_pos_nor_radius(world_pos, world_nor, world_radius);
gl_Position = point_world_to_ndc(world_pos);
#ifdef CONSERVATIVE_RASTER
/* Avoid expense of geometry shader by ensuring rastered pointcloud primitive
* covers at least a whole pixel. */
int i = gl_VertexID % 3;
vec2 ofs = (i == 0) ? vec2(-1.0) : ((i == 1) ? vec2(2.0, -1.0) : vec2(-1.0, 2.0));
gl_Position.xy += sizeViewportInv * gl_Position.w * ofs;
#endif
view_clipping_distances(world_pos);
}

View File

@ -0,0 +1,75 @@
#pragma USE_SSBO_VERTEX_FETCH(TriangleList, 3)
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
void main()
{
/* Calculate triangle vertex info. */
int output_triangle_id = gl_VertexID / 3;
int output_triangle_vertex_id = gl_VertexID % 3;
int base_vertex_id = 0;
if (vertex_fetch_get_input_prim_type() == GPU_PRIM_TRIS) {
base_vertex_id = output_triangle_id * 3;
}
else if (vertex_fetch_get_input_prim_type() == GPU_PRIM_TRI_STRIP) {
base_vertex_id = output_triangle_id;
}
/* NOTE: Triangle fan unsupported in Metal. Will be conveted upfront. */
/** Perform vertex shader calculations per input vertex. **/
/* input pos vertex attribute. */
vec3 in_pos[3];
/* Calculated per-vertex world pos. */
vec3 world_pos[3];
/* Output gl_Position per vertex. */
vec3 ndc_pos[3];
/* Geometry shader normalized position. */
vec3 pos[3];
for (int i = 0; i < 3; i++) {
in_pos[0] = vertex_fetch_attribute(base_vertex_id + i, pos, vec3);
world_pos[0] = point_object_to_world(in_pos[i]);
ndc_pos[i] = point_world_to_ndc(world_pos[i]);
pos[i] = ndc_pos[i].xyz / ndc_pos[i].w;
}
/** Geometry Shader equivalent calculation
* In this no_geom mode using SSBO vertex fetch, rather than emitting 3 vertices, the vertex
* shader is invocated 3 times, and output is determined based on vertex ID within a triangle
* 0..2. **/
vec3 plane = normalize(cross(pos[1] - pos[0], pos[2] - pos[0]));
/* Compute NDC bound box. */
vec4 bbox = vec4(min(min(pos[0].xy, pos[1].xy), pos[2].xy),
max(max(pos[0].xy, pos[1].xy), pos[2].xy));
/* Convert to pixel space. */
bbox = (bbox * 0.5 + 0.5) * sizeViewport.xyxy;
/* Detect failure cases where triangles would produce no fragments. */
bvec2 is_subpixel = lessThan(bbox.zw - bbox.xy, vec2(1.0));
/* View aligned triangle. */
const float threshold = 0.00001;
bool is_coplanar = abs(plane.z) < threshold;
/* Determine output position per-vertex in each triangle */
gl_Position = ndc_pos[output_triangle_vertex_id];
if (all(is_subpixel)) {
vec2 ofs = (i == 0) ? vec2(-1.0) : ((i == 1) ? vec2(2.0, -1.0) : vec2(-1.0, 2.0));
/* HACK: Fix cases where the triangle is too small make it cover at least one pixel. */
gl_Position.xy += sizeViewportInv * gl_Position.w * ofs;
}
/* Test if the triangle is almost parallel with the view to avoid precision issues. */
else if (any(is_subpixel) || is_coplanar) {
/* HACK: Fix cases where the triangle is Parallel to the view by deforming it slightly. */
vec2 ofs = (i == 0) ? vec2(-1.0) : ((i == 1) ? vec2(1.0, -1.0) : vec2(1.0));
gl_Position.xy += sizeViewportInv * gl_Position.w * ofs;
}
else {
/* Triangle expansion should happen here, but we decide to not implement it for
* depth precision & performance reasons. */
}
/* Assign vertex shader clipping distances. */
view_clipping_distances(world_pos[output_triangle_vertex_id]);
}

View File

@ -30,6 +30,18 @@ GPU_SHADER_CREATE_INFO(basic_pointcloud)
GPU_SHADER_CREATE_INFO(basic_curves)
.vertex_source("basic_depth_curves_vert.glsl")
.additional_info("draw_hair");
/* Geometry-shader alterantive paths. */
GPU_SHADER_CREATE_INFO(basic_mesh_conservative_no_geom)
.vertex_in(0, Type::VEC3, "pos")
.vertex_source("basic_depth_vert_conservative_no_geom.glsl")
.additional_info("draw_mesh");
GPU_SHADER_CREATE_INFO(basic_pointcloud_conservative_no_geom)
.define("CONSERVATIVE_RASTER")
.vertex_source("basic_depth_pointcloud_vert.glsl")
.additional_info("draw_pointcloud");
/** \} */
/* -------------------------------------------------------------------- */
@ -45,6 +57,7 @@ GPU_SHADER_CREATE_INFO(basic_curves)
#define BASIC_CONSERVATIVE_VARIATIONS(prefix, ...) \
BASIC_CLIPPING_VARIATIONS(prefix##_conservative, "basic_conservative", __VA_ARGS__) \
BASIC_CLIPPING_VARIATIONS(prefix##_conservative_no_geom, __VA_ARGS__) \
BASIC_CLIPPING_VARIATIONS(prefix, __VA_ARGS__)
#define BASIC_OBTYPE_VARIATIONS(prefix, ...) \

View File

@ -45,7 +45,7 @@ void pointcloud_get_pos_and_radius(out vec3 outpos, out float outradius)
}
/* Return world position and normal. */
void pointcloud_get_pos_and_nor(out vec3 outpos, out vec3 outnor)
void pointcloud_get_pos_nor_radius(out vec3 outpos, out vec3 outnor, out float outradius)
{
vec3 p;
float radius;
@ -79,6 +79,17 @@ void pointcloud_get_pos_and_nor(out vec3 outpos, out vec3 outnor)
radius *= 0.01;
outnor = facing_mat * pos_inst;
outpos = p + outnor * radius;
outradius = radius;
}
/* Return world position and normal. */
void pointcloud_get_pos_and_nor(out vec3 outpos, out vec3 outnor)
{
vec3 nor, pos;
float radius;
pointcloud_get_pos_nor_radius(pos, nor, radius);
outpos = pos;
outnor = nor;
}
vec3 pointcloud_get_pos()

View File

@ -343,6 +343,13 @@ void gpu_shader_create_info_init()
overlay_motion_path_line = overlay_motion_path_line_no_geom;
overlay_motion_path_line_clipped = overlay_motion_path_line_clipped_no_geom;
/* Conservative rasterization. */
basic_depth_mesh_conservative = basic_depth_mesh_conservative_no_geom;
basic_depth_mesh_conservative_clipped = basic_depth_mesh_conservative_no_geom_clipped;
basic_depth_pointcloud_conservative = basic_depth_pointcloud_conservative_no_geom;
basic_depth_pointcloud_conservative_clipped =
basic_depth_pointcloud_conservative_no_geom_clipped;
/* Overlay prepass wire. */
overlay_outline_prepass_wire = overlay_outline_prepass_wire_no_geom;

View File

@ -3823,6 +3823,9 @@ void wm_event_do_handlers(bContext *C)
wmWindowManager *wm = CTX_wm_manager(C);
BLI_assert(ED_undo_is_state_valid(C));
/* Begin GPU render boundary - Certain event handlers require GPU usage. */
GPU_render_begin();
/* Update key configuration before handling events. */
WM_keyconfig_update(wm);
WM_gizmoconfig_update(CTX_data_main(C));
@ -3962,6 +3965,7 @@ void wm_event_do_handlers(bContext *C)
/* File-read case. */
if (CTX_wm_window(C) == nullptr) {
wm_event_free_and_remove_from_queue_if_valid(event);
GPU_render_end();
return;
}
@ -4016,6 +4020,7 @@ void wm_event_do_handlers(bContext *C)
/* File-read case (Python), T29489. */
if (CTX_wm_window(C) == nullptr) {
wm_event_free_and_remove_from_queue_if_valid(event);
GPU_render_end();
return;
}
@ -4044,6 +4049,7 @@ void wm_event_do_handlers(bContext *C)
/* File-read case. */
if (CTX_wm_window(C) == nullptr) {
wm_event_free_and_remove_from_queue_if_valid(event);
GPU_render_end();
return;
}
}
@ -4094,6 +4100,9 @@ void wm_event_do_handlers(bContext *C)
/* Update key configuration after handling events. */
WM_keyconfig_update(wm);
WM_gizmoconfig_update(CTX_data_main(C));
/* End GPU render boundary. Certain event handlers require GPU usage. */
GPU_render_end();
}
/** \} */