[Bf-blender-cvs] [309ea314858] master: Metal: Initial Implementation of Metal Backend for GPU Module.

Jason Fielder noreply at git.blender.org
Tue Mar 22 12:55:43 CET 2022


Commit: 309ea314858a9b7892ea2c8a6fe55ab2a1028697
Author: Jason Fielder
Date:   Tue Mar 22 12:38:28 2022 +0100
Branches: master
https://developer.blender.org/rB309ea314858a9b7892ea2c8a6fe55ab2a1028697

Metal: Initial Implementation of Metal Backend for GPU Module.

Adding WITH_METAL option to CMAKE to guard compilation for macOS only. Implemented stub METALBackend to mirror GPUBackend interface and added capabilities initialisation, along with API initialisation paths.

Global rendering coordination commands added to backend with GPU_render_begin and GPU_render_end() commands globally wrapping GPU work. This is required for Metal to ensure temporary resources are generated within an NSAutoReleasePool and freed accordingly.

Authored by Apple: Michael Parkin-White, Vil Harvey, Marco Giordano, Michael Jones, Morteza Mostajabodaveh, Jason Fielder

Ref T96261

Reviewed By: fclem

Maniphest Tasks: T96261

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

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

M	CMakeLists.txt
M	source/blender/gpu/CMakeLists.txt
M	source/blender/gpu/GPU_context.h
M	source/blender/gpu/GPU_platform.h
M	source/blender/gpu/intern/gpu_backend.hh
M	source/blender/gpu/intern/gpu_capabilities_private.hh
M	source/blender/gpu/intern/gpu_context.cc
M	source/blender/gpu/intern/gpu_platform.cc
M	source/blender/gpu/intern/gpu_platform_private.hh
A	source/blender/gpu/metal/mtl_backend.hh
A	source/blender/gpu/metal/mtl_backend.mm
A	source/blender/gpu/metal/mtl_capabilities.hh
M	source/blender/gpu/opengl/gl_backend.cc
M	source/blender/gpu/opengl/gl_backend.hh
M	source/blender/windowmanager/intern/wm_draw.c

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

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 04cedcc6722..d31a0c4a63d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -531,6 +531,19 @@ mark_as_advanced(
   WITH_GPU_SHADER_BUILDER
 )
 
+# Metal
+
+if (APPLE)
+  option(WITH_METAL_BACKEND "Use Metal for graphics instead of (or as well as) OpenGL on macOS." OFF)
+  mark_as_advanced(WITH_METAL_BACKEND)
+else()
+  set(WITH_METAL_BACKEND OFF)
+endif()
+
+if (WITH_METAL_BACKEND)
+  set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE)
+endif()
+
 if(WIN32)
   option(WITH_GL_ANGLE "Link with the ANGLE library, an OpenGL ES 2.0 implementation based on Direct3D, instead of the system OpenGL library." OFF)
   mark_as_advanced(WITH_GL_ANGLE)
@@ -1274,6 +1287,16 @@ else()
   list(APPEND GL_DEFINITIONS -DWITH_GL_PROFILE_CORE)
 endif()
 
+#-----------------------------------------------------------------------------
+# Configure Metal.
+if (WITH_METAL_BACKEND)
+  add_definitions(-DWITH_METAL_BACKEND)
+
+  # No need to add frameworks here, all the ones we need for Metal and
+  # Metal-OpenGL Interop are already being added by
+  # build_files/cmake/platform/platform_apple.cmake
+endif()
+
 #-----------------------------------------------------------------------------
 # Configure OpenMP.
 if(WITH_OPENMP)
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 45e614991ca..6c795aba560 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -5,7 +5,7 @@
 # to more easily highlight codepadths in other libraries that need to be refactored,
 # bf_gpu is allowed to have opengl regardless of this option.
 
-if(NOT WITH_OPENGL)
+if(NOT WITH_OPENGL AND NOT WITH_METAL_BACKEND)
   add_definitions(-DWITH_OPENGL)
 endif()
 
@@ -13,6 +13,7 @@ set(INC
   .
   intern
   opengl
+  metal
   ../blenkernel
   ../blenlib
   ../bmesh
@@ -78,27 +79,6 @@ set(SRC
   intern/gpu_vertex_format.cc
   intern/gpu_viewport.c
 
-  opengl/gl_backend.cc
-  opengl/gl_batch.cc
-  opengl/gl_compute.cc
-  opengl/gl_context.cc
-  opengl/gl_debug.cc
-  opengl/gl_debug_layer.cc
-  opengl/gl_drawlist.cc
-  opengl/gl_framebuffer.cc
-  opengl/gl_immediate.cc
-  opengl/gl_index_buffer.cc
-  opengl/gl_query.cc
-  opengl/gl_shader.cc
-  opengl/gl_shader_interface.cc
-  opengl/gl_shader_log.cc
-  opengl/gl_state.cc
-  opengl/gl_storage_buffer.cc
-  opengl/gl_texture.cc
-  opengl/gl_uniform_buffer.cc
-  opengl/gl_vertex_array.cc
-  opengl/gl_vertex_buffer.cc
-
   GPU_batch.h
   GPU_batch_presets.h
   GPU_batch_utils.h
@@ -157,6 +137,30 @@ set(SRC
   intern/gpu_uniform_buffer_private.hh
   intern/gpu_vertex_buffer_private.hh
   intern/gpu_vertex_format_private.h
+)
+
+set(OPENGL_SRC
+
+  opengl/gl_backend.cc
+  opengl/gl_batch.cc
+  opengl/gl_compute.cc
+  opengl/gl_context.cc
+  opengl/gl_debug.cc
+  opengl/gl_debug_layer.cc
+  opengl/gl_drawlist.cc
+  opengl/gl_framebuffer.cc
+  opengl/gl_immediate.cc
+  opengl/gl_index_buffer.cc
+  opengl/gl_query.cc
+  opengl/gl_shader.cc
+  opengl/gl_shader_interface.cc
+  opengl/gl_shader_log.cc
+  opengl/gl_state.cc
+  opengl/gl_storage_buffer.cc
+  opengl/gl_texture.cc
+  opengl/gl_uniform_buffer.cc
+  opengl/gl_vertex_array.cc
+  opengl/gl_vertex_buffer.cc
 
   opengl/gl_backend.hh
   opengl/gl_batch.hh
@@ -178,6 +182,22 @@ set(SRC
   opengl/gl_vertex_buffer.hh
 )
 
+set(METAL_SRC
+  metal/mtl_backend.mm
+
+  metal/mtl_backend.hh
+  metal/mtl_capabilities.hh
+)
+
+# Select Backend source based on availability
+if(WITH_OPENGL)
+  list(APPEND SRC ${OPENGL_SRC})
+endif()
+
+if(WITH_METAL_BACKEND)
+  list(APPEND SRC ${METAL_SRC})
+endif()
+
 set(LIB
   ${BLENDER_GL_LIBRARIES}
 )
diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h
index 85433913456..453c117501d 100644
--- a/source/blender/gpu/GPU_context.h
+++ b/source/blender/gpu/GPU_context.h
@@ -11,18 +11,15 @@
 
 #include "GPU_batch.h"
 #include "GPU_common.h"
+#include "GPU_platform.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef enum eGPUBackendType {
-  GPU_BACKEND_NONE = 0,
-  GPU_BACKEND_OPENGL,
-} eGPUBackendType;
-
 void GPU_backend_init(eGPUBackendType backend);
 void GPU_backend_exit(void);
+bool GPU_backend_supported(eGPUBackendType type);
 
 eGPUBackendType GPU_backend_get_type(void);
 
@@ -49,6 +46,13 @@ GPUContext *GPU_context_active_get(void);
 void GPU_context_main_lock(void);
 void GPU_context_main_unlock(void);
 
+/* GPU Begin/end work blocks */
+void GPU_render_begin();
+void GPU_render_end();
+
+/* For operations which need to run exactly once per frame -- even if there are no render updates. */
+void GPU_render_step();
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/gpu/GPU_platform.h b/source/blender/gpu/GPU_platform.h
index d5a0fcfa921..bd20d0c7db1 100644
--- a/source/blender/gpu/GPU_platform.h
+++ b/source/blender/gpu/GPU_platform.h
@@ -12,6 +12,13 @@
 
 /* GPU platform support */
 
+typedef enum eGPUBackendType {
+  GPU_BACKEND_NONE = 0,
+  GPU_BACKEND_OPENGL = 1 << 0,
+  GPU_BACKEND_METAL = 1 << 1,
+  GPU_BACKEND_ANY = 0xFFFFFFFFu
+} eGPUBackendType;
+
 /* GPU Types */
 typedef enum eGPUDeviceType {
   GPU_DEVICE_NVIDIA = (1 << 0),
@@ -51,8 +58,10 @@ extern "C" {
 #endif
 
 /* GPU Types */
-
+/* TODO: Verify all use-cases of GPU_type_matches to determine which graphics API it should apply to, and replace
+ * with `GPU_type_matches_ex` where appropriate. */
 bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver);
+bool GPU_type_matches_ex(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver, eGPUBackendType backend);
 
 eGPUSupportLevel GPU_platform_support_level(void);
 const char *GPU_platform_vendor(void);
diff --git a/source/blender/gpu/intern/gpu_backend.hh b/source/blender/gpu/intern/gpu_backend.hh
index ad906c74980..6e07e6c3229 100644
--- a/source/blender/gpu/intern/gpu_backend.hh
+++ b/source/blender/gpu/intern/gpu_backend.hh
@@ -49,6 +49,12 @@ class GPUBackend {
   virtual UniformBuf *uniformbuf_alloc(int size, const char *name) = 0;
   virtual StorageBuf *storagebuf_alloc(int size, GPUUsageType usage, const char *name) = 0;
   virtual VertBuf *vertbuf_alloc() = 0;
+
+  /* Render Frame Coordination --
+   * Used for performing per-frame actions globally */
+  virtual void render_begin() = 0;
+  virtual void render_end() = 0;
+  virtual void render_step() = 0;
 };
 
 }  // namespace gpu
diff --git a/source/blender/gpu/intern/gpu_capabilities_private.hh b/source/blender/gpu/intern/gpu_capabilities_private.hh
index d645d82a879..4a951eb8458 100644
--- a/source/blender/gpu/intern/gpu_capabilities_private.hh
+++ b/source/blender/gpu/intern/gpu_capabilities_private.hh
@@ -20,11 +20,13 @@ namespace blender::gpu {
  */
 struct GPUCapabilities {
   int max_texture_size = 0;
+  int max_texture_3d_size = 0;
   int max_texture_layers = 0;
   int max_textures = 0;
   int max_textures_vert = 0;
   int max_textures_geom = 0;
   int max_textures_frag = 0;
+  int max_samplers = 0;
   int max_work_group_count[3] = {0, 0, 0};
   int max_work_group_size[3] = {0, 0, 0};
   int max_uniforms_vert = 0;
@@ -41,6 +43,8 @@ struct GPUCapabilities {
   bool compute_shader_support = false;
   bool shader_storage_buffer_objects_support = false;
   bool shader_image_load_store_support = false;
+  bool transform_feedback_support = false;
+
   /* OpenGL related workarounds. */
   bool mip_render_workaround = false;
   bool depth_blitting_workaround = false;
@@ -48,6 +52,10 @@ struct GPUCapabilities {
   bool broken_amd_driver = false;
   bool use_hq_normals_workaround = false;
   /* Vulkan related workarounds. */
+
+  /* Metal related workarounds. */
+  /* Minimum per-vertex stride in bytes (For a vertex buffer). */
+  int minimum_per_vertex_stride = 1;
 };
 
 extern GPUCapabilities GCaps;
diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc
index 60e95e09a99..5b40d3850a5 100644
--- a/source/blender/gpu/intern/gpu_context.cc
+++ b/source/blender/gpu/intern/gpu_context.cc
@@ -13,7 +13,9 @@
  */
 
 /* TODO: Create cmake option. */
-#define WITH_OPENGL_BACKEND 1
+#if WITH_OPENGL
+  #define WITH_OPENGL_BACKEND 1
+#endif
 
 #include "BLI_assert.h"
 #include "BLI_utildefines.h"
@@ -32,6 +34,9 @@
 #  include "gl_backend.hh"
 #  include "gl_context.hh"
 #endif
+#ifdef WITH_METAL_BACKEND
+#  include "mtl_backend.hh"
+#endif
 
 #include <mutex>
 #include <vector>
@@ -140,21 +145,73 @@ void GPU_context_main_unlock()
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name  GPU Begin/end work blocks
+ *
+ * Used to explicitly define a per-frame block within which GPU work will happen.
+ * Used for global autoreleasepool flushing in Metal
+ * \{ */
+
+void GPU_render_begin() {
+  GPUBackend* backend = GPUBackend::get();
+  BLI_assert(backend);
+  backend->render_begin();
+}
+void GPU_render_end() {
+  GPUBackend* backend = GPUBackend::get();
+  BLI_assert(backend);
+  backend->render_end();
+}
+void GPU_render_step() {
+  GPUBackend* backend = GPUBackend::get();
+  BLI_assert(backend);
+  backend->render_step();
+}
+
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name Backend selection
  * \{ */
 
 static GPUBackend *g_backend;
 
+bool GPU_backend_supported(eGPUBackendType type)
+{
+  switch (type) {
+    case GPU_BACKEND_OPENGL:
+#ifdef WITH_OPENGL_BACKEND
+      return true;
+#else
+      return false;
+#endif
+    case GPU_BACKEND_METAL:
+#ifdef WITH_METAL_BACKEND
+      return MTLBackend::metal_is_supported();
+#else
+      return false;
+#endif
+    default:
+      BLI_assert(false && "No backend specified");
+      return false;
+  }
+}
+
 void GPU_backend_init(eGPUBackendType backend_type)
 {
   BLI_assert(g_backend == nullptr);
+  BLI_assert(GPU_backend_supported(backend_type));
 
   switch (backend_type) {
-#if WITH_OPENGL_BACKEND
+#ifdef WITH_OPENGL_BACKEND
     case GPU_BACKEND_OPENGL:
       g_backend = new GLBackend;
       break;
+#endif
+#ifdef WITH_METAL_BACKEND
+    case GPU_BACKEND_METAL:
+      g_backend = new MTLBackend;
+      break;
 #endif
     default:
       BLI_assert(0);
@@ -172,9 +229,18 @@ void GPU_backend_exit()
 
 eGP

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list