[Bf-blender-cvs] [bb63b98d1ff] master: Metal: MTLVertBuf implementation and support for texture creation from vertex buffers.
Thomas Dinges
noreply at git.blender.org
Thu Sep 22 17:17:41 CEST 2022
Commit: bb63b98d1ff5acfd24dff9b5e72175f82f5bca26
Author: Thomas Dinges
Date: Thu Sep 22 17:13:07 2022 +0200
Branches: master
https://developer.blender.org/rBbb63b98d1ff5acfd24dff9b5e72175f82f5bca26
Metal: MTLVertBuf implementation and support for texture creation from vertex buffers.
Metal: MTLVertBuf implementation and support for texture creation from vertex buffers.
Authored by Apple: Michael Parkin-White
Reviewed By: fclem
Maniphest Tasks: T96261
Differential Revision: https://developer.blender.org/D15452
===================================================================
M source/blender/gpu/CMakeLists.txt
M source/blender/gpu/metal/mtl_backend.mm
M source/blender/gpu/metal/mtl_texture.hh
M source/blender/gpu/metal/mtl_texture.mm
A source/blender/gpu/metal/mtl_vertex_buffer.hh
A source/blender/gpu/metal/mtl_vertex_buffer.mm
===================================================================
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 8b38c22ae28..18da5169620 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -202,6 +202,7 @@ set(METAL_SRC
metal/mtl_texture.mm
metal/mtl_texture_util.mm
metal/mtl_uniform_buffer.mm
+ metal/mtl_vertex_buffer.mm
metal/mtl_backend.hh
metal/mtl_capabilities.hh
@@ -222,6 +223,7 @@ set(METAL_SRC
metal/mtl_state.hh
metal/mtl_texture.hh
metal/mtl_uniform_buffer.hh
+ metal/mtl_vertex_buffer.hh
)
# Select Backend source based on availability
diff --git a/source/blender/gpu/metal/mtl_backend.mm b/source/blender/gpu/metal/mtl_backend.mm
index 3cd7794f6c9..ec9e8ab4d15 100644
--- a/source/blender/gpu/metal/mtl_backend.mm
+++ b/source/blender/gpu/metal/mtl_backend.mm
@@ -14,6 +14,7 @@
#include "mtl_query.hh"
#include "mtl_shader.hh"
#include "mtl_uniform_buffer.hh"
+#include "mtl_vertex_buffer.hh"
#include "gpu_capabilities_private.hh"
#include "gpu_platform_private.hh"
@@ -94,8 +95,7 @@ StorageBuf *MTLBackend::storagebuf_alloc(int size, GPUUsageType usage, const cha
VertBuf *MTLBackend::vertbuf_alloc()
{
- /* TODO(Metal): Implement MTLVertBuf. */
- return nullptr;
+ return new MTLVertBuf();
}
void MTLBackend::render_begin()
diff --git a/source/blender/gpu/metal/mtl_texture.hh b/source/blender/gpu/metal/mtl_texture.hh
index 766f01d9018..88d09e4e133 100644
--- a/source/blender/gpu/metal/mtl_texture.hh
+++ b/source/blender/gpu/metal/mtl_texture.hh
@@ -200,7 +200,7 @@ class MTLTexture : public Texture {
TEXTURE_VIEW_SWIZZLE_DIRTY = (1 << 0),
TEXTURE_VIEW_MIP_DIRTY = (1 << 1)
};
- id<MTLTexture> mip_swizzle_view_;
+ id<MTLTexture> mip_swizzle_view_ = nil;
char tex_swizzle_mask_[4];
MTLTextureSwizzleChannels mtl_swizzle_mask_;
bool mip_range_dirty_ = false;
@@ -216,7 +216,6 @@ class MTLTexture : public Texture {
/* VBO. */
MTLVertBuf *vert_buffer_;
id<MTLBuffer> vert_buffer_mtl_;
- int vert_buffer_offset_;
/* Core parameters and sub-resources. */
eGPUTextureUsage gpu_image_usage_flags_;
@@ -256,6 +255,14 @@ class MTLTexture : public Texture {
return name_;
}
+ id<MTLBuffer> get_vertex_buffer() const
+ {
+ if (resource_mode_ == MTL_TEXTURE_MODE_VBO) {
+ return vert_buffer_mtl_;
+ }
+ return nil;
+ }
+
protected:
bool init_internal() override;
bool init_internal(GPUVertBuf *vbo) override;
@@ -324,8 +331,6 @@ class MTLTexture : public Texture {
int height);
GPUFrameBuffer *get_blit_framebuffer(uint dst_slice, uint dst_mip);
- MEM_CXX_CLASS_ALLOC_FUNCS("gpu::MTLTexture")
-
/* Texture Update function Utilities. */
/* Metal texture updating does not provide the same range of functionality for type conversion
* and format compatibility as are available in OpenGL. To achieve the same level of
@@ -415,6 +420,8 @@ class MTLTexture : public Texture {
/* fullscreen blit utilities. */
GPUShader *fullscreen_blit_sh_get();
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("MTLTexture")
};
/* Utility */
diff --git a/source/blender/gpu/metal/mtl_texture.mm b/source/blender/gpu/metal/mtl_texture.mm
index 2b7c2333bff..4af46c13751 100644
--- a/source/blender/gpu/metal/mtl_texture.mm
+++ b/source/blender/gpu/metal/mtl_texture.mm
@@ -20,6 +20,7 @@
#include "mtl_context.hh"
#include "mtl_debug.hh"
#include "mtl_texture.hh"
+#include "mtl_vertex_buffer.hh"
#include "GHOST_C-api.h"
@@ -50,7 +51,6 @@ void gpu::MTLTexture::mtl_texture_init()
/* VBO. */
vert_buffer_ = nullptr;
vert_buffer_mtl_ = nil;
- vert_buffer_offset_ = -1;
/* Default Swizzle. */
tex_swizzle_mask_[0] = 'r';
@@ -169,26 +169,39 @@ void gpu::MTLTexture::bake_mip_swizzle_view()
id<MTLTexture> gpu::MTLTexture::get_metal_handle()
{
- /* ensure up to date and baked. */
- this->ensure_baked();
-
/* Verify VBO texture shares same buffer. */
if (resource_mode_ == MTL_TEXTURE_MODE_VBO) {
- int r_offset = -1;
+ id<MTLBuffer> buf = vert_buffer_->get_metal_buffer();
+
+ /* Source vertex buffer has been re-generated, require re-initialisation. */
+ if (buf != vert_buffer_mtl_) {
+ MTL_LOG_INFO(
+ "MTLTexture '%p' using MTL_TEXTURE_MODE_VBO requires re-generation due to updated "
+ "Vertex-Buffer.\n",
+ this);
+ /* Clear state. */
+ this->reset();
+
+ /* Re-initialise. */
+ this->init_internal(wrap(vert_buffer_));
+
+ /* Update for assertion check below. */
+ buf = vert_buffer_->get_metal_buffer();
+ }
- /* TODO(Metal): Fetch buffer from MTLVertBuf when implemented. */
- id<MTLBuffer> buf = nil; /*vert_buffer_->get_metal_buffer(&r_offset);*/
+ /* Ensure buffer is valid.
+ * Fetchvert buffer handle directly in-case it changed above. */
BLI_assert(vert_buffer_mtl_ != nil);
- BLI_assert(buf == vert_buffer_mtl_ && r_offset == vert_buffer_offset_);
-
- UNUSED_VARS(buf);
- UNUSED_VARS_NDEBUG(r_offset);
+ BLI_assert(vert_buffer_->get_metal_buffer() == vert_buffer_mtl_);
}
+ /* ensure up to date and baked. */
+ this->ensure_baked();
+
if (is_baked_) {
/* For explicit texture views, ensure we always return the texture view. */
if (resource_mode_ == MTL_TEXTURE_MODE_TEXTURE_VIEW) {
- BLI_assert(mip_swizzle_view_ && "Texture view should always have a valid handle.");
+ BLI_assert_msg(mip_swizzle_view_, "Texture view should always have a valid handle.");
}
if (mip_swizzle_view_ != nil || texture_view_dirty_flags_) {
@@ -208,7 +221,7 @@ id<MTLTexture> gpu::MTLTexture::get_metal_handle_base()
/* For explicit texture views, always return the texture view. */
if (resource_mode_ == MTL_TEXTURE_MODE_TEXTURE_VIEW) {
- BLI_assert(mip_swizzle_view_ && "Texture view should always have a valid handle.");
+ BLI_assert_msg(mip_swizzle_view_, "Texture view should always have a valid handle.");
if (mip_swizzle_view_ != nil || texture_view_dirty_flags_) {
bake_mip_swizzle_view();
}
@@ -915,7 +928,7 @@ void gpu::MTLTexture::generate_mipmap()
/* Ensure texture is baked. */
this->ensure_baked();
- BLI_assert(is_baked_ && texture_ && "MTLTexture is not valid");
+ BLI_assert_msg(is_baked_ && texture_, "MTLTexture is not valid");
if (mipmaps_ == 1 || mtl_max_mips_ == 1) {
MTL_LOG_WARNING("Call to generate mipmaps on texture with 'mipmaps_=1\n'");
@@ -1231,7 +1244,7 @@ void gpu::MTLTexture::read_internal(int mip,
depth_format_mode = 4;
break;
default:
- BLI_assert(false && "Unhandled depth read format case");
+ BLI_assert_msg(false, "Unhandled depth read format case");
break;
}
}
@@ -1445,11 +1458,85 @@ bool gpu::MTLTexture::init_internal()
bool gpu::MTLTexture::init_internal(GPUVertBuf *vbo)
{
- /* Zero initialize. */
- this->prepare_internal();
+ /* Not a valid vertex buffer format, though verifying texture is not set as such
+ * as this is not supported on Apple Silicon. */
+ BLI_assert_msg(this->format_ != GPU_DEPTH24_STENCIL8,
+ "Apple silicon does not support GPU_DEPTH24_S8");
- /* TODO(Metal): Add implementation for GPU Vert buf. */
- return false;
+ MTLPixelFormat mtl_format = gpu_texture_format_to_metal(this->format_);
+ mtl_max_mips_ = 1;
+ mipmaps_ = 0;
+ this->mip_range_set(0, 0);
+
+ /* Create texture from GPUVertBuf's buffer. */
+ MTLVertBuf *mtl_vbo = static_cast<MTLVertBuf *>(unwrap(vbo));
+ mtl_vbo->bind();
+ mtl_vbo->flag_used();
+
+ /* Get Metal Buffer. */
+ id<MTLBuffer> source_buffer = mtl_vbo->get_metal_buffer();
+ BLI_assert(source_buffer);
+
+ /* Verify size. */
+ if (w_ <= 0) {
+ MTL_LOG_WARNING("Allocating texture buffer of width 0!\n");
+ w_ = 1;
+ }
+
+ /* Verify Texture and vertex buffer alignment. */
+ int bytes_per_pixel = get_mtl_format_bytesize(mtl_format);
+ int bytes_per_row = bytes_per_pixel * w_;
+
+ MTLContext *mtl_ctx = MTLContext::get();
+ uint align_requirement = static_cast<uint>(
+ [mtl_ctx->device minimumLinearTextureAlignmentForPixelFormat:mtl_format]);
+
+ /* Verify per-vertex size aligns with texture size. */
+ const GPUVertFormat *format = GPU_vertbuf_get_format(vbo);
+ BLI_assert(bytes_per_pixel == format->stride &&
+ "Pixel format stride MUST match the texture format stride -- These being different "
+ "is likely caused by Metal's VBO padding to a minimum of 4-bytes per-vertex");
+ UNUSED_VARS_NDEBUG(format);
+
+ /* Create texture descriptor. */
+ BLI_assert(type_ == GPU_TEXTURE_BUFFER);
+ texture_descriptor_ = [[MTLTextureDescriptor alloc] init];
+ texture_descriptor_.pixelFormat = mtl_format;
+ texture_descriptor_.textureType = MTLTextureTypeTextureBuffer;
+ texture_descriptor_.width = w_;
+ texture_descriptor_.height = 1;
+ texture_descriptor_.depth = 1;
+ texture_descriptor_.arrayLength = 1;
+ texture_descriptor_.mipmapLevelCount = mtl_max_mips_;
+ texture_descriptor_.usage =
+ MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite |
+ MTLTextureUsagePixelFormatView; /* TODO(Metal): Optimize usage flags. */
+ texture_descriptor_.storageMode = [source_buffer storageMode];
+ texture_descriptor_.sampleCount = 1;
+ texture_descriptor_.cpuCacheMode = [source_buffer cpuCacheMode];
+ texture_descriptor_.hazardTrackingMode = [source_buffer hazardTrackingMode];
+
+ texture_ = [source_buffer
+ newTextureWithDescriptor:texture_descriptor_
+ offset:0
+ bytesPerRow:ceil_to_multiple_u(bytes_per_row, align_requirement)];
+ aligned_w_ = bytes_per_row / bytes_per_pixel;
+
+ BLI_assert(texture_);
+ texture_.label = [NSString stringWithUTF8String:this->get_name()];
+ is_baked_ = true;
+ is_dirty_ = false;
+ resource_mode_ = MTL_TEXTURE_MODE_VBO;
+
+ /* Track Status. */
+ vert_buffer_ = mtl_vbo;
+ vert_buffer_mtl_ = source_buffer;
+
+ /* Cleanup. */
+ [texture_descriptor_ release];
+ texture_descriptor_ = nullptr;
+
+ return true;
}
bool gpu::MTLTexture::init_internal(const GPUTexture *src, int mip_offset, int layer_offset)
diff --git a/source/blender/gpu/metal/mtl_vertex_buffer.hh b/source/blender/gp
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list