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
This commit is contained in:
parent
a83f2834c7
commit
9ec20f2ede
Notes:
blender-bot
2023-02-14 11:21:40 +01:00
Referenced by issue #96261, Metal Viewport
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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_fetch_attribute(input_base_vertex_id + 1, pos, vec3);
|
||||
vData[2].pos = vertex_fetch_attribute(input_base_vertex_id + 2, pos, vec3);
|
||||
vData[3].pos = vertex_fetch_attribute(input_base_vertex_id + 3, 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);
|
||||
|
||||
vData[3].frontPosition = point_object_to_ndc(vData[3].pos);
|
||||
vData[3].backPosition = point_object_to_ndc(vData[3].pos + lightDirection * lightDistance);
|
||||
|
||||
/* Geometry shader equivalent path. */
|
||||
vec3 v10 = vData[0].pos - vData[1].pos;
|
||||
vec3 v12 = vData[2].pos - vData[1].pos;
|
||||
vec3 v13 = vData[3].pos - vData[1].pos;
|
||||
vec3 n1 = cross(v12, v10);
|
||||
vec3 n2 = cross(v13, v12);
|
||||
|
||||
#ifdef DEGENERATE_TRIS_WORKAROUND
|
||||
/* Check if area is null. */
|
||||
vec2 faces_area = vec2(len_sqr(n1), len_sqr(n2));
|
||||
bvec2 degen_faces = lessThan(abs(faces_area), vec2(DEGENERATE_TRIS_AREA_THRESHOLD));
|
||||
|
||||
/* Both triangles are degenerate, abort. */
|
||||
if (all(degen_faces)) {
|
||||
DISCARD_VERTEX
|
||||
}
|
||||
#endif
|
||||
|
||||
vec2 facing = vec2(dot(n1, lightDirection), dot(n2, lightDirection));
|
||||
|
||||
/* WATCH: maybe unpredictable in some cases. */
|
||||
bool is_manifold = any(notEqual(vData[0].pos, vData[3].pos));
|
||||
|
||||
bvec2 backface = greaterThan(facing, vec2(0.0));
|
||||
|
||||
#ifdef DEGENERATE_TRIS_WORKAROUND
|
||||
# ifndef DOUBLE_MANIFOLD
|
||||
/* If the mesh is known to be manifold and we don't use double count,
|
||||
* only create an quad if the we encounter a facing geom. */
|
||||
if ((degen_faces.x && backface.y) || (degen_faces.y && backface.x)) {
|
||||
DISCARD_VERTEX
|
||||
}
|
||||
# endif
|
||||
|
||||
/* If one of the 2 triangles is degenerate, replace edge by a non-manifold one. */
|
||||
backface.x = (degen_faces.x) ? !backface.y : backface.x;
|
||||
backface.y = (degen_faces.y) ? !backface.x : backface.y;
|
||||
is_manifold = (any(degen_faces)) ? false : is_manifold;
|
||||
#endif
|
||||
|
||||
/* If both faces face the same direction it's not an outline edge. */
|
||||
if (backface.x == backface.y) {
|
||||
DISCARD_VERTEX
|
||||
}
|
||||
|
||||
/* Output correct output vertex depending on */
|
||||
if (output_vertex_id < 6) {
|
||||
/* Always output if first 6 vertices. */
|
||||
extrude_edge(backface.x, output_vertex_id);
|
||||
}
|
||||
else {
|
||||
#ifdef DOUBLE_MANIFOLD
|
||||
/* If part of double manifold, only output this vertex if correctly contributing */
|
||||
if (is_manifold) {
|
||||
extrude_edge(backface.x, output_vertex_id);
|
||||
}
|
||||
else {
|
||||
DISCARD_VERTEX
|
||||
}
|
||||
#else
|
||||
DISCARD_VERTEX
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -75,9 +75,9 @@ void ShaderCreateInfo::finalize()
|
|||
if (info.early_fragment_test_) {
|
||||
early_fragment_test_ = true;
|
||||
}
|
||||
/* Override depth-write with additional info if this specifies a writing mode
|
||||
* other than the default. */
|
||||
if (info.depth_write_ != DepthWrite::NONE) {
|
||||
/* Modify depth write if has been changed from default.
|
||||
* `UNCHANGED` implies gl_FragDepth is not used at all. */
|
||||
if (info.depth_write_ != DepthWrite::UNCHANGED) {
|
||||
depth_write_ = info.depth_write_;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
/* Workbench shadows.
|
||||
* Note: Updates additional-info used by workbench shadow permutations.
|
||||
* Must be prepared prior to permutation preparation. */
|
||||
workbench_shadow_manifold = workbench_shadow_manifold_no_geom;
|
||||
workbench_shadow_no_manifold = workbench_shadow_no_manifold_no_geom;
|
||||
workbench_shadow_caps = workbench_shadow_caps_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;
|
||||
|
|
|
@ -189,8 +189,8 @@ ENUM_OPERATORS(BuiltinBits, BuiltinBits::USE_DEBUG_PRINT);
|
|||
* https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_conservative_depth.txt
|
||||
*/
|
||||
enum class DepthWrite {
|
||||
/* NONE specified as default to indicate gl_FragDepth is not used. */
|
||||
NONE = 0,
|
||||
/* UNCHANGED specified as default to indicate gl_FragDepth is not used. */
|
||||
UNCHANGED = 0,
|
||||
ANY,
|
||||
GREATER,
|
||||
LESS,
|
||||
|
@ -344,7 +344,7 @@ struct ShaderCreateInfo {
|
|||
/** If true, force the use of the GL shader introspection for resource location. */
|
||||
bool legacy_resource_location_ = false;
|
||||
/** Allow optimization when fragment shader writes to `gl_FragDepth`. */
|
||||
DepthWrite depth_write_ = DepthWrite::NONE;
|
||||
DepthWrite depth_write_ = DepthWrite::UNCHANGED;
|
||||
/** GPU Backend compatibility flag. Temporary requirement until Metal enablement is fully
|
||||
* complete. */
|
||||
bool metal_backend_only_ = false;
|
||||
|
|
|
@ -24,19 +24,19 @@ GPU_SHADER_CREATE_INFO(depth_2d_update_float)
|
|||
.metal_backend_only(true)
|
||||
.fragment_source("depth_2d_update_float_frag.glsl")
|
||||
.additional_info("depth_2d_update_info_base")
|
||||
// .do_static_compilation(true)
|
||||
.do_static_compilation(true)
|
||||
.depth_write(DepthWrite::ANY);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(depth_2d_update_int24)
|
||||
.metal_backend_only(true)
|
||||
.fragment_source("depth_2d_update_int24_frag.glsl")
|
||||
.additional_info("depth_2d_update_info_base")
|
||||
// .do_static_compilation(true)
|
||||
.do_static_compilation(true)
|
||||
.depth_write(DepthWrite::ANY);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(depth_2d_update_int32)
|
||||
.metal_backend_only(true)
|
||||
.fragment_source("depth_2d_update_int32_frag.glsl")
|
||||
.additional_info("depth_2d_update_info_base")
|
||||
// .do_static_compilation(true)
|
||||
.do_static_compilation(true)
|
||||
.depth_write(DepthWrite::ANY);
|
||||
|
|
|
@ -472,21 +472,6 @@ id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_first, uint v_count, uint i_fi
|
|||
this->elem ? @"(indexed)" : @"",
|
||||
active_shader_->get_interface()->get_name()]];
|
||||
}
|
||||
|
||||
/* Ensure Context Render Pipeline State is fully setup and ready to execute the draw. */
|
||||
MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(this->prim_type);
|
||||
if (!ctx->ensure_render_pipeline_state(mtl_prim_type)) {
|
||||
printf("FAILED TO ENSURE RENDER PIPELINE STATE");
|
||||
BLI_assert(false);
|
||||
|
||||
if (G.debug & G_DEBUG_GPU) {
|
||||
[rec popDebugGroup];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
/*** Bind Vertex Buffers and Index Buffers **/
|
||||
|
||||
/* SSBO Vertex Fetch Buffer bindings. */
|
||||
if (uses_ssbo_fetch) {
|
||||
|
||||
|
@ -514,7 +499,7 @@ id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_first, uint v_count, uint i_fi
|
|||
}
|
||||
rps.bind_vertex_buffer(idx_buffer, 0, MTL_SSBO_VERTEX_FETCH_IBO_INDEX);
|
||||
|
||||
/* Ensure all attributes are set */
|
||||
/* Ensure all attributes are set. */
|
||||
active_shader_->ssbo_vertex_fetch_bind_attributes_end(rec);
|
||||
|
||||
/* Bind NULL Buffers for unused vertex data slots. */
|
||||
|
@ -529,7 +514,7 @@ id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_first, uint v_count, uint i_fi
|
|||
/* Flag whether Indexed rendering is used or not. */
|
||||
int &uniform_ssbo_use_indexed = active_shader_->uni_ssbo_uses_indexed_rendering;
|
||||
BLI_assert(uniform_ssbo_use_indexed != -1);
|
||||
int uses_indexed_rendering = (mtl_elem != NULL) ? 1 : 0;
|
||||
int uses_indexed_rendering = (mtl_elem != nullptr) ? 1 : 0;
|
||||
active_shader_->uniform_int(uniform_ssbo_use_indexed, 1, 1, &uses_indexed_rendering);
|
||||
|
||||
/* Set SSBO-fetch-mode status uniforms. */
|
||||
|
@ -547,6 +532,19 @@ id<MTLRenderCommandEncoder> MTLBatch::bind(uint v_first, uint v_count, uint i_fi
|
|||
(const int *)(&v_count));
|
||||
}
|
||||
|
||||
/* Ensure Context Render Pipeline State is fully setup and ready to execute the draw.
|
||||
* This should happen after all other final rendeirng setup is complete. */
|
||||
MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(this->prim_type);
|
||||
if (!ctx->ensure_render_pipeline_state(mtl_prim_type)) {
|
||||
printf("FAILED TO ENSURE RENDER PIPELINE STATE");
|
||||
BLI_assert(false);
|
||||
|
||||
if (G.debug & G_DEBUG_GPU) {
|
||||
[rec popDebugGroup];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* Bind Vertex Buffers. */
|
||||
for (int i = 0; i < num_buffers; i++) {
|
||||
MTLVertBuf *buf_at_index = buffers[i];
|
||||
|
@ -755,6 +753,10 @@ void MTLBatch::draw_advanced(int v_first, int v_count, int i_first, int i_count)
|
|||
mtl_vertex_count_fits_primitive_type(
|
||||
output_num_verts, active_shader_->get_ssbo_vertex_fetch_output_prim_type()),
|
||||
"Output Vertex count is not compatible with the requested output vertex primitive type");
|
||||
|
||||
/* Set depth stencil state (requires knowledge of primitive type). */
|
||||
ctx->ensure_depth_stencil_state(active_shader_->get_ssbo_vertex_fetch_output_prim_type());
|
||||
|
||||
[rec drawPrimitives:active_shader_->get_ssbo_vertex_fetch_output_prim_type()
|
||||
vertexStart:0
|
||||
vertexCount:output_num_verts
|
||||
|
|
|
@ -675,7 +675,7 @@ bool MTLShader::generate_msl_from_glsl(const shader::ShaderCreateInfo *info)
|
|||
|
||||
/* NOTE(Metal): FragDepth output mode specified in create-info 'DepthWrite depth_write_'.
|
||||
* If parsing without create-info, manual extraction will be required. */
|
||||
msl_iface.uses_gl_FragDepth = (info->depth_write_ != DepthWrite::NONE) &&
|
||||
msl_iface.uses_gl_FragDepth = (info->depth_write_ != DepthWrite::UNCHANGED) &&
|
||||
shd_builder_->glsl_fragment_source_.find("gl_FragDepth") !=
|
||||
std::string::npos;
|
||||
msl_iface.depth_write = info->depth_write_;
|
||||
|
|
|
@ -282,27 +282,25 @@ void MTLStateManager::set_stencil_test(const eGPUStencilTest test, const eGPUSte
|
|||
context_, MTLStencilOperationKeep, MTLStencilOperationKeep, MTLStencilOperationReplace);
|
||||
break;
|
||||
case GPU_STENCIL_OP_COUNT_DEPTH_PASS:
|
||||
/* Winding inversed due to flipped Y coordinate system in Metal. */
|
||||
mtl_stencil_set_op_separate(context_,
|
||||
GPU_CULL_FRONT,
|
||||
GPU_CULL_BACK,
|
||||
MTLStencilOperationKeep,
|
||||
MTLStencilOperationKeep,
|
||||
MTLStencilOperationIncrementWrap);
|
||||
mtl_stencil_set_op_separate(context_,
|
||||
GPU_CULL_BACK,
|
||||
GPU_CULL_FRONT,
|
||||
MTLStencilOperationKeep,
|
||||
MTLStencilOperationKeep,
|
||||
MTLStencilOperationDecrementWrap);
|
||||
break;
|
||||
case GPU_STENCIL_OP_COUNT_DEPTH_FAIL:
|
||||
/* Winding inversed due to flipped Y coordinate system in Metal. */
|
||||
mtl_stencil_set_op_separate(context_,
|
||||
GPU_CULL_FRONT,
|
||||
GPU_CULL_BACK,
|
||||
MTLStencilOperationKeep,
|
||||
MTLStencilOperationDecrementWrap,
|
||||
MTLStencilOperationKeep);
|
||||
mtl_stencil_set_op_separate(context_,
|
||||
GPU_CULL_BACK,
|
||||
GPU_CULL_FRONT,
|
||||
MTLStencilOperationKeep,
|
||||
MTLStencilOperationIncrementWrap,
|
||||
MTLStencilOperationKeep);
|
||||
|
|
Loading…
Reference in New Issue