[Bf-blender-cvs] [073139e3294] master: Metal: MTLState module implementation.

Jason Fielder noreply at git.blender.org
Thu May 12 20:50:38 CEST 2022


Commit: 073139e32943b863828474ca70bbdfc258520769
Author: Jason Fielder
Date:   Thu May 12 20:49:09 2022 +0200
Branches: master
https://developer.blender.org/rB073139e32943b863828474ca70bbdfc258520769

Metal: MTLState module implementation.

MTLState module implementation and supporting functionality in MTLContext for state tracking, texture binding and sampler state caching.

Ref T96261

Reviewed By: fclem

Maniphest Tasks: T96261

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

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

M	source/blender/gpu/CMakeLists.txt
A	source/blender/gpu/GPU_common_types.h
M	source/blender/gpu/GPU_state.h
M	source/blender/gpu/metal/mtl_context.hh
M	source/blender/gpu/metal/mtl_context.mm
A	source/blender/gpu/metal/mtl_state.hh
A	source/blender/gpu/metal/mtl_state.mm
M	source/blender/gpu/metal/mtl_texture.hh

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

diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 6ed2c083a6b..f963d0e3b39 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -85,6 +85,7 @@ set(SRC
   GPU_buffers.h
   GPU_capabilities.h
   GPU_common.h
+  GPU_common_types.h
   GPU_compute.h
   GPU_context.h
   GPU_debug.h
@@ -189,6 +190,7 @@ set(METAL_SRC
   metal/mtl_backend.mm
   metal/mtl_context.mm
   metal/mtl_debug.mm
+  metal/mtl_state.mm
   metal/mtl_texture.mm
   metal/mtl_texture_util.mm
 
@@ -197,6 +199,7 @@ set(METAL_SRC
   metal/mtl_common.hh
   metal/mtl_context.hh
   metal/mtl_debug.hh
+  metal/mtl_state.hh
   metal/mtl_texture.hh
 )
 
diff --git a/source/blender/gpu/GPU_common_types.h b/source/blender/gpu/GPU_common_types.h
new file mode 100644
index 00000000000..e08143c2449
--- /dev/null
+++ b/source/blender/gpu/GPU_common_types.h
@@ -0,0 +1,18 @@
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum eGPUFrontFace {
+  GPU_CLOCKWISE,
+  GPU_COUNTERCLOCKWISE,
+} eGPUFrontFace;
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/source/blender/gpu/GPU_state.h b/source/blender/gpu/GPU_state.h
index 99b60351dcc..7641b50fe24 100644
--- a/source/blender/gpu/GPU_state.h
+++ b/source/blender/gpu/GPU_state.h
@@ -35,6 +35,18 @@ typedef enum eGPUBarrier {
 
 ENUM_OPERATORS(eGPUBarrier, GPU_BARRIER_ELEMENT_ARRAY)
 
+/* Note: For Metal and Vulkan only. TODO(Metal): Update barrier calls to use stage flags. */
+typedef enum eGPUStageBarrierBits {
+  GPU_BARRIER_STAGE_VERTEX = (1 << 0),
+  GPU_BARRIER_STAGE_FRAGMENT = (1 << 1),
+  GPU_BARRIER_STAGE_COMPUTE = (1 << 2),
+  GPU_BARRIER_STAGE_ANY_GRAPHICS = (GPU_BARRIER_STAGE_VERTEX | GPU_BARRIER_STAGE_FRAGMENT),
+  GPU_BARRIER_STAGE_ANY = (GPU_BARRIER_STAGE_VERTEX | GPU_BARRIER_STAGE_FRAGMENT |
+                           GPU_BARRIER_STAGE_COMPUTE),
+} eGPUStageBarrierBits;
+
+ENUM_OPERATORS(eGPUStageBarrierBits, GPU_BARRIER_STAGE_COMPUTE)
+
 /**
  * Defines the fixed pipeline blending equation.
  * SRC is the output color from the shader.
diff --git a/source/blender/gpu/metal/mtl_context.hh b/source/blender/gpu/metal/mtl_context.hh
index aa198482291..938ea8edc13 100644
--- a/source/blender/gpu/metal/mtl_context.hh
+++ b/source/blender/gpu/metal/mtl_context.hh
@@ -7,8 +7,10 @@
 
 #include "gpu_context_private.hh"
 
+#include "GPU_common_types.h"
 #include "GPU_context.h"
 
+#include "mtl_capabilities.hh"
 #include "mtl_texture.hh"
 
 #include <Cocoa/Cocoa.h>
@@ -21,6 +23,112 @@
 
 namespace blender::gpu {
 
+class MTLShader;
+class MTLUniformBuf;
+class MTLBuffer;
+
+/* Depth Stencil State */
+typedef struct MTLContextDepthStencilState {
+
+  /* Depth State. */
+  bool depth_write_enable;
+  bool depth_test_enabled;
+  float depth_range_near;
+  float depth_range_far;
+  MTLCompareFunction depth_function;
+  float depth_bias;
+  float depth_slope_scale;
+  bool depth_bias_enabled_for_points;
+  bool depth_bias_enabled_for_lines;
+  bool depth_bias_enabled_for_tris;
+
+  /* Stencil State. */
+  bool stencil_test_enabled;
+  unsigned int stencil_read_mask;
+  unsigned int stencil_write_mask;
+  unsigned int stencil_ref;
+  MTLCompareFunction stencil_func;
+
+  MTLStencilOperation stencil_op_front_stencil_fail;
+  MTLStencilOperation stencil_op_front_depth_fail;
+  MTLStencilOperation stencil_op_front_depthstencil_pass;
+
+  MTLStencilOperation stencil_op_back_stencil_fail;
+  MTLStencilOperation stencil_op_back_depth_fail;
+  MTLStencilOperation stencil_op_back_depthstencil_pass;
+
+  /* Framebuffer State -- We need to mark this, incase stencil state remains unchanged,
+   * but attachment state has changed. */
+  bool has_depth_target;
+  bool has_stencil_target;
+
+  /* TODO(Metal): Consider optimising this function using memcmp.
+   * Un-used, but differing, stencil state leads to over-generation
+   * of state objects when doing trivial compare.  */
+  inline bool operator==(const MTLContextDepthStencilState &other) const
+  {
+    bool depth_state_equality = (has_depth_target == other.has_depth_target &&
+                                 depth_write_enable == other.depth_write_enable &&
+                                 depth_test_enabled == other.depth_test_enabled &&
+                                 depth_function == other.depth_function);
+
+    bool stencil_state_equality = true;
+    if (has_stencil_target) {
+      stencil_state_equality =
+          (has_stencil_target == other.has_stencil_target &&
+           stencil_test_enabled == other.stencil_test_enabled &&
+           stencil_op_front_stencil_fail == other.stencil_op_front_stencil_fail &&
+           stencil_op_front_depth_fail == other.stencil_op_front_depth_fail &&
+           stencil_op_front_depthstencil_pass == other.stencil_op_front_depthstencil_pass &&
+           stencil_op_back_stencil_fail == other.stencil_op_back_stencil_fail &&
+           stencil_op_back_depth_fail == other.stencil_op_back_depth_fail &&
+           stencil_op_back_depthstencil_pass == other.stencil_op_back_depthstencil_pass &&
+           stencil_func == other.stencil_func && stencil_read_mask == other.stencil_read_mask &&
+           stencil_write_mask == other.stencil_write_mask);
+    }
+
+    return depth_state_equality && stencil_state_equality;
+  }
+
+  /* Depth stencil state will get hashed in order to prepare
+   * MTLDepthStencilState objects. The hash should comprise of
+   * all elements which fill the MTLDepthStencilDescriptor.
+   * These are bound when [rec setDepthStencilState:...] is called.
+   * Depth bias and stencil reference value are set dynamically on the RenderCommandEncoder:
+   *  - setStencilReferenceValue:
+   *  - setDepthBias:slopeScale:clamp:
+   */
+  inline std::size_t hash() const
+  {
+    std::size_t boolean_bitmask = (this->depth_write_enable ? 1 : 0) |
+                                  ((this->depth_test_enabled ? 1 : 0) << 1) |
+                                  ((this->depth_bias_enabled_for_points ? 1 : 0) << 2) |
+                                  ((this->depth_bias_enabled_for_lines ? 1 : 0) << 3) |
+                                  ((this->depth_bias_enabled_for_tris ? 1 : 0) << 4) |
+                                  ((this->stencil_test_enabled ? 1 : 0) << 5) |
+                                  ((this->has_depth_target ? 1 : 0) << 6) |
+                                  ((this->has_stencil_target ? 1 : 0) << 7);
+
+    std::size_t stencilop_bitmask = ((std::size_t)this->stencil_op_front_stencil_fail) |
+                                    ((std::size_t)this->stencil_op_front_depth_fail << 3) |
+                                    ((std::size_t)this->stencil_op_front_depthstencil_pass << 6) |
+                                    ((std::size_t)this->stencil_op_back_stencil_fail << 9) |
+                                    ((std::size_t)this->stencil_op_back_depth_fail << 12) |
+                                    ((std::size_t)this->stencil_op_back_depthstencil_pass << 15);
+
+    std::size_t main_hash = (std::size_t)this->depth_function;
+    if (this->has_stencil_target) {
+      main_hash += (std::size_t)(this->stencil_read_mask & 0xFF) << 8;
+      main_hash += (std::size_t)(this->stencil_write_mask & 0xFF) << 16;
+    }
+    main_hash ^= (std::size_t)this->stencil_func << 16;
+    main_hash ^= stencilop_bitmask;
+
+    std::size_t final_hash = (main_hash << 8) | boolean_bitmask;
+    return final_hash;
+  }
+} MTLContextDepthStencilState;
+
 typedef struct MTLContextTextureUtils {
 
   /* Depth Update Utilities */
@@ -108,11 +216,149 @@ typedef struct MTLContextTextureUtils {
 
 } MTLContextTextureUtils;
 
+/* Structs containing information on current binding state for textures and samplers. */
+typedef struct MTLTextureBinding {
+  bool used;
+
+  /* Same value as index in bindings array. */
+  unsigned int texture_slot_index;
+  gpu::MTLTexture *texture_resource;
+
+} MTLTextureBinding;
+
+typedef struct MTLSamplerBinding {
+  bool used;
+  MTLSamplerState state;
+
+  bool operator==(MTLSamplerBinding const &other) const
+  {
+    return (used == other.used && state == other.state);
+  }
+} MTLSamplerBinding;
+
+/* Combined sampler state configuration for Argument Buffer caching. */
+struct MTLSamplerArray {
+  unsigned int num_samplers;
+  /* MTLSamplerState permutations between 0..256 - slightly more than a byte. */
+  MTLSamplerState mtl_sampler_flags[MTL_MAX_TEXTURE_SLOTS];
+  id<MTLSamplerState> mtl_sampler[MTL_MAX_TEXTURE_SLOTS];
+
+  inline bool operator==(const MTLSamplerArray &other) const
+  {
+    if (this->num_samplers != other.num_samplers) {
+      return false;
+    }
+    return (memcmp(this->mtl_sampler_flags,
+                   other.mtl_sampler_flags,
+                   sizeof(MTLSamplerState) * this->num_samplers) == 0);
+  }
+
+  inline uint32_t hash() const
+  {
+    uint32_t hash = this->num_samplers;
+    for (int i = 0; i < this->num_samplers; i++) {
+      hash ^= (uint32_t)this->mtl_sampler_flags[i] << (i % 3);
+    }
+    return hash;
+  }
+};
+
+typedef enum MTLPipelineStateDirtyFlag {
+  MTL_PIPELINE_STATE_NULL_FLAG = 0,
+  /* Whether we need to call setViewport. */
+  MTL_PIPELINE_STATE_VIEWPORT_FLAG = (1 << 0),
+  /* Whether we need to call setScissor.*/
+  MTL_PIPELINE_STATE_SCISSOR_FLAG = (1 << 1),
+  /* Whether we need to update/rebind active depth stencil state. */
+  MTL_PIPELINE_STATE_DEPTHSTENCIL_FLAG = (1 << 2),
+  /* Whether we need to update/rebind active PSO. */
+  MTL_PIPELINE_STATE_PSO_FLAG = (1 << 3),
+  /* Whether we need to update the frontFacingWinding state. */
+  MTL_PIPELINE_STATE_FRONT_FACING_FLAG = (1 << 4),
+  /* Whether we need to update the culling state. */
+  MTL_PIPELINE_STATE_CULLMODE_FLAG = (1 << 5),
+  /* Full pipeline state needs applying. Occurs when beginning a new render pass. */
+  MTL_PIPELINE_STATE_ALL_FLAG =
+      (MTL_PIPELINE_STATE_VIEWPORT_FLAG | MTL_PIPELINE_STATE_SCISSOR_FLAG |
+       MTL_PIPELINE_STATE_DEPTHSTENCIL_FLAG | MTL_PIPELINE_STATE_PSO_FLAG |
+       MTL_PIPELINE_STATE_FRONT_FACING_FLAG | MTL_PIPELINE_STATE_CULLMODE_FLAG)
+} MTLPipelineStateDirtyFlag;
+
+/* Ignore full flag bit-mask `MTL_PIPELINE_STATE

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list