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:
parent
3608af24fd
commit
2744ee2262
Notes:
blender-bot
2023-02-14 09:24:53 +01:00
Referenced by issue #96261, Metal Viewport
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
}
|
|
@ -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, ...) \
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
Loading…
Reference in New Issue