mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Fix] (MG_Impl, MG_Backend): stop the new layer attachment from reaching backends that cannot back it
Implementing NamedFramebufferTextureLayer made layered attachments reachable for the first time, and direct_state_access.framebuffers_texture_layer_attachment went from Fail to Crash on DirectVulkan. Two separate gaps sat behind it, both of them asserted on rather than reported: - The renderer resolves an attachment's GL layer straight onto a Vulkan array layer. A 3D texture's z-slice therefore lands outside its image, which has one array layer by construction, and the array texture objects are still the one-image stubs in TextureObjectStubs.h, so their image has a single layer whatever GL believes. MaterializePendingClearForTexture tripped over a clear whose layer span was outside the image it was given. - A cube map array has no image shape in VkTextureManager at all, so SyncTextureAndGetDescriptor returns null for it. NamedFramebufferTextureLayer now answers the full error set for every target and layer - which is what took the two error cases green - and then declines to attach anything but layer zero of a non-cube-array texture, through the same RecordUnsupportedFramebufferTextureAttachmentError the by-target entry point already uses. Layer zero of the other targets is the plain first-slice attachment glFramebufferTextureLayer already backs, so it still goes through. SyncTextureResource's assertion on an unsupported texture shape is also gone: it is a gap in this backend's coverage, not a broken invariant, and the code below it already handles the failure by declining the sync. It logs a warning instead. framebuffers_texture_layer_attachment goes back to Fail on DirectVulkan rather than Crash; no case changes in either direction beyond that.
This commit is contained in:
@@ -1497,15 +1497,17 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
: (mipLevels > 1 ? std::max(mipLevels, ComputeFullMipLevelCount(texelSize)) : 1u);
|
||||
TextureShapeInfo shapeInfo{};
|
||||
const Bool supportedShape = TryResolveTextureShapeInfo(texture, uploadTarget, texelSize, shapeInfo);
|
||||
MOBILEGL_ASSERT(supportedShape,
|
||||
"SyncTextureResource: unsupported uploadTarget=%s textureTarget=%s textureId=%d size=(%d,%d,%d) "
|
||||
"mipLevels=%u vkViewType=%d",
|
||||
MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(),
|
||||
MG_Util::ConvertTextureTargetToString(texture.GetTarget()).c_str(),
|
||||
texture.GetExternalIndex(), texelSize.x(), texelSize.y(), texelSize.z(), mipLevels,
|
||||
static_cast<Int>(MG_Util::ConvertTextureUploadTargetToVkEnum(uploadTarget)));
|
||||
if (!supportedShape) {
|
||||
MGLOG_D("%s: not Texture2D, unsupported", __func__);
|
||||
// A gap in this backend's coverage, not a broken invariant: the GL front end accepts
|
||||
// targets this manager has no Vulkan image shape for yet (cube map arrays above all).
|
||||
// Declining the sync leaves the texture unbacked - wrong, but recoverable - where an
|
||||
// assertion would take the whole process down instead.
|
||||
MGLOG_W("SyncTextureResource: unsupported uploadTarget=%s textureTarget=%s textureId=%d size=(%d,%d,%d) "
|
||||
"mipLevels=%u vkViewType=%d",
|
||||
MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(),
|
||||
MG_Util::ConvertTextureTargetToString(texture.GetTarget()).c_str(), texture.GetExternalIndex(),
|
||||
texelSize.x(), texelSize.y(), texelSize.z(), mipLevels,
|
||||
static_cast<Int>(MG_Util::ConvertTextureUploadTargetToVkEnum(uploadTarget)));
|
||||
return false;
|
||||
}
|
||||
VkSampleCountFlagBits resolvedSampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
@@ -1398,6 +1398,24 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
return;
|
||||
}
|
||||
|
||||
// Everything above is the spec's error set and is answered for every target and every
|
||||
// layer. Actually attaching a layer other than the first is a different matter: no backend
|
||||
// resolves a GL layer onto its image yet. The Vulkan renderer treats the layer as an array
|
||||
// slice - so a 3D texture's z-slice lands outside its single-array-layer image - and the
|
||||
// array texture objects are still the one-image stubs in TextureObjectStubs.h, whose image
|
||||
// has one layer whatever GL thinks. Letting the attachment through only moves the failure
|
||||
// downstream into a clear whose layer span is outside the image; declining keeps it a
|
||||
// reported error. Layer zero is the plain first-slice attachment the by-target
|
||||
// glFramebufferTextureLayer already backs, so it goes through.
|
||||
// A cube map array has no Vulkan image shape at all (TryResolveTextureShapeInfo), so it
|
||||
// cannot be an attachment on that backend whatever the layer is.
|
||||
if (layer != 0 || textureObject->GetTarget() == TextureTarget::TextureCubeMapArray) {
|
||||
RecordUnsupportedFramebufferTextureAttachmentError(
|
||||
__func__, "Attaching a layer other than the first, or any layer of a cube map array, is not "
|
||||
"represented by the current framebuffer attachment model.");
|
||||
return;
|
||||
}
|
||||
|
||||
framebufferObject->AttachTexture(attachmentType, textureObject, textureUploadTarget, level, layer,
|
||||
/*layered=*/false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user