Fix: Cycles Metal graphics interop not working

It needs an MTLBuffer instead of a raw pointer.
This commit is contained in:
Brecht Van Lommel
2025-05-26 10:47:51 +02:00
parent ef0ccb6854
commit d2f883d8bc
5 changed files with 15 additions and 9 deletions

View File

@@ -633,9 +633,10 @@ GraphicsInteropDevice BlenderDisplayDriver::graphics_interop_get_device()
interop_device.type = GraphicsInteropDevice::VULKAN;
break;
case GPU_BACKEND_METAL:
interop_device.type = GraphicsInteropDevice::METAL;
break;
case GPU_BACKEND_NONE:
case GPU_BACKEND_ANY:
/* Metal not supported yet by Cycles. */
interop_device.type = GraphicsInteropDevice::NONE;
break;
}
@@ -665,9 +666,10 @@ GraphicsInteropBuffer BlenderDisplayDriver::graphics_interop_get_buffer()
interop_buffer.type = GraphicsInteropDevice::VULKAN;
break;
case GPU_BACKEND_METAL:
interop_buffer.type = GraphicsInteropDevice::METAL;
break;
case GPU_BACKEND_NONE:
case GPU_BACKEND_ANY:
/* Metal not supported yet by Cycles. */
interop_buffer.type = GraphicsInteropDevice::NONE;
break;
}

View File

@@ -5,6 +5,8 @@
#ifdef WITH_METAL
# include "device/graphics_interop.h"
# include "device/metal/device_impl.h"
# include "session/display_driver.h"
CCL_NAMESPACE_BEGIN
@@ -34,7 +36,7 @@ class MetalDeviceGraphicsInterop : public DeviceGraphicsInterop {
MetalDevice *device_ = nullptr;
/* Native handle. */
void *buffer_ = nullptr;
MetalDevice::MetalMem mem_;
size_t size_ = 0;
/* The destination was requested to be cleared. */

View File

@@ -22,18 +22,19 @@ void MetalDeviceGraphicsInterop::set_buffer(const GraphicsInteropBuffer &interop
/* Trivial implementation due to unified memory. */
if (interop_buffer.type == GraphicsInteropDevice::METAL) {
need_clear_ |= interop_buffer.need_clear;
buffer_ = reinterpret_cast<void *>(interop_buffer.handle);
mem_.mtlBuffer = reinterpret_cast<id<MTLBuffer>>(interop_buffer.handle);
size_ = interop_buffer.width * interop_buffer.height * sizeof(half4);
}
}
device_ptr MetalDeviceGraphicsInterop::map()
{
if (buffer_ && need_clear_) {
memset(buffer_, 0, size_);
if (mem_.mtlBuffer && need_clear_) {
memset([mem_.mtlBuffer contents], 0, size_);
need_clear_ = false;
}
return device_ptr(buffer_);
return device_ptr(&mem_);
}
void MetalDeviceGraphicsInterop::unmap() {}

View File

@@ -41,7 +41,7 @@ class GraphicsInteropBuffer {
* - OpenGL: pixel buffer object ID.
* - Vulkan on Windows: opaque handle for VkBuffer.
* - Vulkan on Unix: opaque file descriptor for VkBuffer.
* - Metal: pixel buffer unified memory pointer. */
* - Metal: MTLBuffer with unified memory. */
GraphicsInteropDevice::Type type = GraphicsInteropDevice::NONE;
int64_t handle = 0;

View File

@@ -2657,7 +2657,8 @@ GPUPixelBufferNativeHandle MTLPixelBuffer::get_native_handle()
}
/* Just get pointer to unified memory. No need to unmap. */
native_handle.handle = reinterpret_cast<int64_t>(map());
map();
native_handle.handle = reinterpret_cast<int64_t>(buffer_);
native_handle.size = size_;
return native_handle;