[Bf-blender-cvs] [b3464fe152c] master: Metal: Implement suppot for clip plane toggling via GPU_clip_distances.

Jason Fielder noreply at git.blender.org
Tue Dec 20 14:17:16 CET 2022


Commit: b3464fe152ca8a7b50dddf0774e33d24e38fd6b5
Author: Jason Fielder
Date:   Tue Dec 20 14:15:52 2022 +0100
Branches: master
https://developer.blender.org/rBb3464fe152ca8a7b50dddf0774e33d24e38fd6b5

Metal: Implement suppot for clip plane toggling via GPU_clip_distances.

The Metal backend already supports output for the 6 clipping planes via gl_ClipDistances equivalent, however, functionality to toggle clipping plane enablement was missing.

Authored by Apple: Michael Parkin-White

Ref T96261
Depends on D16777

Reviewed By: fclem

Maniphest Tasks: T96261

Differential Revision: https://developer.blender.org/D16813

===================================================================

M	source/blender/draw/engines/eevee/shaders/infos/eevee_legacy_material_info.hh
M	source/blender/gpu/metal/mtl_context.hh
M	source/blender/gpu/metal/mtl_pso_descriptor_state.hh
M	source/blender/gpu/metal/mtl_shader.mm
M	source/blender/gpu/metal/mtl_shader_generator.mm
M	source/blender/gpu/metal/mtl_state.hh
M	source/blender/gpu/metal/mtl_state.mm
M	source/blender/gpu/shaders/metal/mtl_shader_common.msl

===================================================================

diff --git a/source/blender/draw/engines/eevee/shaders/infos/eevee_legacy_material_info.hh b/source/blender/draw/engines/eevee/shaders/infos/eevee_legacy_material_info.hh
index 2d1671ac98d..dd848d6fef9 100644
--- a/source/blender/draw/engines/eevee/shaders/infos/eevee_legacy_material_info.hh
+++ b/source/blender/draw/engines/eevee/shaders/infos/eevee_legacy_material_info.hh
@@ -59,7 +59,9 @@ GPU_SHADER_CREATE_INFO(eevee_legacy_material_surface_vert_common)
     .additional_info("eevee_legacy_material_empty_base")
     .additional_info("draw_resource_id_varying")
     .additional_info("eevee_legacy_common_utiltex_lib")
-    .additional_info("eevee_legacy_closure_eval_surface_lib");
+    .additional_info("eevee_legacy_closure_eval_surface_lib")
+    /* Planar reflections assigns to gl_ClipDistance via surface_vert.glsl. */
+    .define("USE_CLIP_PLANES");
 
 GPU_SHADER_CREATE_INFO(eevee_legacy_material_surface_vert)
     .additional_info("eevee_legacy_material_surface_vert_common")
diff --git a/source/blender/gpu/metal/mtl_context.hh b/source/blender/gpu/metal/mtl_context.hh
index 3656fbdcd19..a26e31aadde 100644
--- a/source/blender/gpu/metal/mtl_context.hh
+++ b/source/blender/gpu/metal/mtl_context.hh
@@ -460,6 +460,9 @@ struct MTLContextGlobalShaderPipelineState {
   /* Render parameters. */
   float point_size = 1.0f;
   float line_width = 1.0f;
+
+  /* Clipping plane enablement. */
+  bool clip_distance_enabled[6] = {false};
 };
 
 /* Command Buffer Manager - Owned by MTLContext.
diff --git a/source/blender/gpu/metal/mtl_pso_descriptor_state.hh b/source/blender/gpu/metal/mtl_pso_descriptor_state.hh
index 8b0d69c6251..1890f6e8ccd 100644
--- a/source/blender/gpu/metal/mtl_pso_descriptor_state.hh
+++ b/source/blender/gpu/metal/mtl_pso_descriptor_state.hh
@@ -174,6 +174,9 @@ struct MTLRenderPipelineStateDescriptor {
   /* Global color write mask as this cannot be specified per attachment. */
   MTLColorWriteMask color_write_mask;
 
+  /* Clip distance enablement. */
+  uchar clipping_plane_enable_mask = 0;
+
   /* Point size required by point primitives. */
   float point_size = 0.0f;
 
@@ -184,6 +187,10 @@ struct MTLRenderPipelineStateDescriptor {
       return false;
     }
 
+    if (clipping_plane_enable_mask != other.clipping_plane_enable_mask) {
+      return false;
+    }
+
     if ((num_color_attachments != other.num_color_attachments) ||
         (depth_attachment_format != other.depth_attachment_format) ||
         (stencil_attachment_format != other.stencil_attachment_format) ||
@@ -243,6 +250,9 @@ struct MTLRenderPipelineStateDescriptor {
     hash |= uint64_t((this->blending_enabled && (this->num_color_attachments > 0)) ? 1 : 0) << 62;
     hash ^= uint64_t(this->point_size);
 
+    /* Clipping plane enablement. */
+    hash ^= uint64_t(clipping_plane_enable_mask) << 20;
+
     return hash;
   }
 
diff --git a/source/blender/gpu/metal/mtl_shader.mm b/source/blender/gpu/metal/mtl_shader.mm
index 747746ea424..496f919d189 100644
--- a/source/blender/gpu/metal/mtl_shader.mm
+++ b/source/blender/gpu/metal/mtl_shader.mm
@@ -654,6 +654,14 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state(
   pipeline_descriptor.src_rgb_blend_factor = ctx->pipeline_state.src_rgb_blend_factor;
   pipeline_descriptor.point_size = ctx->pipeline_state.point_size;
 
+  /* Resolve clipping plane enablement. */
+  pipeline_descriptor.clipping_plane_enable_mask = 0;
+  for (const int plane : IndexRange(6)) {
+    pipeline_descriptor.clipping_plane_enable_mask =
+        pipeline_descriptor.clipping_plane_enable_mask |
+        ((ctx->pipeline_state.clip_distance_enabled[plane]) ? (1 << plane) : 0);
+  }
+
   /* Primitive Type -- Primitive topology class needs to be specified for layered rendering. */
   bool requires_specific_topology_class = uses_mtl_array_index_ ||
                                           prim_type == MTLPrimitiveTopologyClassPoint;
@@ -856,6 +864,29 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state(
                       withName:@"MTL_transform_feedback_buffer_index"];
     }
 
+    /* Clipping planes. */
+    int MTL_clip_distances_enabled = (pipeline_descriptor.clipping_plane_enable_mask > 0) ? 1 : 0;
+
+    /* Only define specialization constant if planes are required.
+     * We guard clip_planes usage on this flag. */
+    [values setConstantValue:&MTL_clip_distances_enabled
+                        type:MTLDataTypeInt
+                    withName:@"MTL_clip_distances_enabled"];
+
+    if (MTL_clip_distances_enabled > 0) {
+      /* Assign individual enablement flags. Only define a flag function constant
+       * if it is used. */
+      for (const int plane : IndexRange(6)) {
+        int plane_enabled = ctx->pipeline_state.clip_distance_enabled[plane] ? 1 : 0;
+        if (plane_enabled) {
+          [values
+              setConstantValue:&plane_enabled
+                          type:MTLDataTypeInt
+                      withName:[NSString stringWithFormat:@"MTL_clip_distance_enabled%d", plane]];
+        }
+      }
+    }
+
     /* gl_PointSize constant. */
     bool null_pointsize = true;
     float MTL_pointsize = pipeline_descriptor.point_size;
diff --git a/source/blender/gpu/metal/mtl_shader_generator.mm b/source/blender/gpu/metal/mtl_shader_generator.mm
index b8c9a28efbd..b938f3fd228 100644
--- a/source/blender/gpu/metal/mtl_shader_generator.mm
+++ b/source/blender/gpu/metal/mtl_shader_generator.mm
@@ -1876,11 +1876,14 @@ std::string MSLGeneratorInterface::generate_msl_vertex_out_struct(ShaderStage sh
     out << "#if defined(USE_CLIP_PLANES) || defined(USE_WORLD_CLIP_PLANES)" << std::endl;
     if (this->clip_distances.size() > 1) {
       /* Output array of clip distances if specified. */
-      out << "\tfloat clipdistance [[clip_distance]] [" << this->clip_distances.size() << "];"
-          << std::endl;
+      out << "\tfloat clipdistance [[clip_distance, "
+             "function_constant(MTL_clip_distances_enabled)]] ["
+          << this->clip_distances.size() << "];" << std::endl;
     }
     else if (this->clip_distances.size() > 0) {
-      out << "\tfloat clipdistance [[clip_distance]];" << std::endl;
+      out << "\tfloat clipdistance [[clip_distance, "
+             "function_constant(MTL_clip_distances_enabled)]];"
+          << std::endl;
     }
     out << "#endif" << std::endl;
   }
@@ -2157,18 +2160,24 @@ std::string MSLGeneratorInterface::generate_msl_vertex_output_population()
         << std::endl;
   }
 
-  /* Output clip-distances. */
-  out << "#if defined(USE_CLIP_PLANES) || defined(USE_WORLD_CLIP_PLANES)" << std::endl;
+  /* Output clip-distances.
+   * Clip distances are only written to if both clipping planes are turned on for the shader,
+   * and the clipping planes are enabled. Enablement is controlled on a per-plane basis
+   * via function constants in the shader pipeline state object (PSO). */
+  out << "#if defined(USE_CLIP_PLANES) || defined(USE_WORLD_CLIP_PLANES)" << std::endl
+      << "if(MTL_clip_distances_enabled) {" << std::endl;
   if (this->clip_distances.size() > 1) {
     for (int cd = 0; cd < this->clip_distances.size(); cd++) {
-      out << "\toutput.clipdistance[" << cd << "] = vertex_shader_instance.gl_ClipDistance_" << cd
-          << ";" << std::endl;
+      /* Default value when clipping is disabled >= 0.0 to ensure primitive is not clipped. */
+      out << "\toutput.clipdistance[" << cd
+          << "] = (is_function_constant_defined(MTL_clip_distance_enabled" << cd
+          << "))?vertex_shader_instance.gl_ClipDistance_" << cd << ":1.0;" << std::endl;
     }
   }
   else if (this->clip_distances.size() > 0) {
     out << "\toutput.clipdistance = vertex_shader_instance.gl_ClipDistance_0;" << std::endl;
   }
-  out << "#endif" << std::endl;
+  out << "}" << std::endl << "#endif" << std::endl;
 
   /* Populate output vertex variables. */
   int output_id = 0;
diff --git a/source/blender/gpu/metal/mtl_state.hh b/source/blender/gpu/metal/mtl_state.hh
index 56114fd313e..bc6c700859d 100644
--- a/source/blender/gpu/metal/mtl_state.hh
+++ b/source/blender/gpu/metal/mtl_state.hh
@@ -80,6 +80,8 @@ class MTLStateManager : public StateManager {
   void mtl_depth_range(float near, float far);
   void mtl_stencil_mask(uint mask);
   void mtl_stencil_set_func(eGPUStencilTest stencil_func, int ref, uint mask);
+  void mtl_clip_plane_enable(uint i);
+  void mtl_clip_plane_disable(uint i);
 
   MEM_CXX_CLASS_ALLOC_FUNCS("MTLStateManager")
 };
diff --git a/source/blender/gpu/metal/mtl_state.mm b/source/blender/gpu/metal/mtl_state.mm
index aeb1ec15de3..95b7e5edc7a 100644
--- a/source/blender/gpu/metal/mtl_state.mm
+++ b/source/blender/gpu/metal/mtl_state.mm
@@ -35,6 +35,12 @@ MTLStateManager::MTLStateManager(MTLContext *ctx) : StateManager()
   /* Force update using default state. */
   current_ = ~state;
   current_mutable_ = ~mutable_state;
+
+  /* Clip distances initial mask forces to 0x111, which exceeds
+   * max clip plane count of 6, so limit to ensure all clipping
+   * planes get disabled. */
+  current_.clip_distances = 6;
+
   set_state(state);
   set_mutable_state(mutable_state);
 }
@@ -52,6 +58,7 @@ void MTLStateManager::force_state()
 {
   /* Little exception for clip distances since they need to keep the old count correct. */
   uint32_t clip_distances = current_.clip_distances;
+  BLI_assert(clip_distances <= 6);
   current_ = ~this->state;
   current_.clip_distances = clip_distances;
   current_mutable_ = ~this->mutable_state;
@@ -329,11 +336,32 @@ void MTLStateManager::set_stencil_mask(const eGPUStencilTest test, const GPUStat
   }
 }
 
+void MTLStateManager::mtl_clip_plane_enable(uint i)
+{
+  BLI_assert(context_);
+  MTLContextGlobalShaderPipelineState &pipeline_state = context_->pipeline_state;
+  pipeline_state.clip_distance_enabled[i] = true;
+  pipeline_state.dirty_flags |= MTL_PIPELINE_STATE_PSO_FLAG;
+}
+
+void MTLStateManager::mtl_clip_plane_disable(uint i)
+{
+  BLI_assert(context_);
+  MTLContextGlobalShaderPipelineState &pipeline_state = context_->pipeline_state;
+  pipeline_state.clip_distance_enabled[i] = false;
+  pipeline_state.dirty_flags |= MTL_PIPELINE_STATE_PSO_FLAG;
+}
+
 void MTLStateManager::set_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list