From e2066298d9ea12bbc440b38a881d09836ceb4891 Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Wed, 19 Mar 2025 11:52:59 +1100 Subject: [PATCH] Renderer: Fix Metal handling of cube textures; assert equal dimensions --- .../metal/rendering_device_driver_metal.mm | 20 +++++++++++++++++-- servers/rendering/rendering_device.cpp | 2 ++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/metal/rendering_device_driver_metal.mm b/drivers/metal/rendering_device_driver_metal.mm index f7ac6121bc8..8f7e6505875 100644 --- a/drivers/metal/rendering_device_driver_metal.mm +++ b/drivers/metal/rendering_device_driver_metal.mm @@ -405,6 +405,15 @@ RDD::TextureID RenderingDeviceDriverMetal::texture_create_from_extension(uint64_ RDD::TextureID RenderingDeviceDriverMetal::texture_create_shared(TextureID p_original_texture, const TextureView &p_view) { id src_texture = rid::get(p_original_texture); + NSUInteger slices = src_texture.arrayLength; + if (src_texture.textureType == MTLTextureTypeCube) { + // Metal expects Cube textures to have a slice count of 6. + slices = 6; + } else if (src_texture.textureType == MTLTextureTypeCubeArray) { + // Metal expects Cube Array textures to have 6 slices per layer. + slices *= 6; + } + #if DEV_ENABLED if (src_texture.sampleCount > 1) { // TODO(sgc): is it ok to create a shared texture from a multi-sample texture? @@ -434,7 +443,7 @@ RDD::TextureID RenderingDeviceDriverMetal::texture_create_shared(TextureID p_ori id obj = [src_texture newTextureViewWithPixelFormat:format textureType:src_texture.textureType levels:NSMakeRange(0, src_texture.mipmapLevelCount) - slices:NSMakeRange(0, src_texture.arrayLength) + slices:NSMakeRange(0, slices) swizzle:swizzle]; ERR_FAIL_NULL_V_MSG(obj, TextureID(), "Unable to create shared texture"); return rid::make(obj); @@ -566,7 +575,14 @@ void RenderingDeviceDriverMetal::texture_get_copyable_layout(TextureID p_texture r_layout->size = get_image_format_required_size(format, sz.width, sz.height, sz.depth, 1, &sbw, &sbh); r_layout->row_pitch = r_layout->size / ((sbh / bh) * sz.depth); r_layout->depth_pitch = r_layout->size / sz.depth; - r_layout->layer_pitch = r_layout->size / obj.arrayLength; + + uint32_t array_length = obj.arrayLength; + if (obj.textureType == MTLTextureTypeCube) { + array_length = 6; + } else if (obj.textureType == MTLTextureTypeCubeArray) { + array_length *= 6; + } + r_layout->layer_pitch = r_layout->size / array_length; } else { CRASH_NOW_MSG("need to calculate layout for shared texture"); } diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 62c5135172d..2ae365d167e 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -912,6 +912,8 @@ RID RenderingDevice::texture_create(const TextureFormat &p_format, const Texture "Number of layers must be equal or greater than 1 for arrays and cubemaps."); ERR_FAIL_COND_V_MSG((format.texture_type == TEXTURE_TYPE_CUBE_ARRAY || format.texture_type == TEXTURE_TYPE_CUBE) && (format.array_layers % 6) != 0, RID(), "Cubemap and cubemap array textures must provide a layer number that is multiple of 6"); + ERR_FAIL_COND_V_MSG(((format.texture_type == TEXTURE_TYPE_CUBE_ARRAY || format.texture_type == TEXTURE_TYPE_CUBE)) && (format.width != format.height), RID(), + "Cubemap and cubemap array textures must have equal width and height."); ERR_FAIL_COND_V_MSG(format.array_layers > driver->limit_get(LIMIT_MAX_TEXTURE_ARRAY_LAYERS), RID(), "Number of layers exceeds device maximum."); } else { format.array_layers = 1;