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. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs
