mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Fix] (MG_Impl, MG_Backend): let the backend that can honour a layered attachment have it
NamedFramebufferTextureLayer declined every attachment but layer zero, on both backends. That was right for DirectVulkan, which maps a GL layer onto a Vulkan array layer with no notion of a 3D depth slice, but wrong for DirectGLES: SyncAttachmentObject already routes a layered upload target to glFramebufferTextureLayer with the attachment's layer passed straight through, and array storage already carries the real layer count into glTexStorage3D. The one backend that could render to the layer was being told it could not. The decision now lives in a DynamicBackendParameters flag, so it is the backend that answers rather than the entry point guessing. DirectGLES sets it when the driver resolved glFramebufferTextureLayer; DirectVulkan leaves it false until VkRenderPassManager tells a depth slice from an array layer. framebuffers_texture_layer_attachment's colour checks now pass on Espryt for 3D, 2D array and 2D multisample array textures - the case still fails there on cube map arrays, which DirectGLES gives no storage at all, and on the depth and stencil halves. No case changes on DirectVulkan, which keeps the old behaviour.
This commit is contained in:
@@ -353,6 +353,12 @@ namespace MobileGL {
|
||||
// real ES drivers behind DirectGLES both do. Defaults to true so a backend
|
||||
// that never sets it keeps the permissive behaviour.
|
||||
Bool SupportsDistinctDepthStencilAttachments = true;
|
||||
// Whether attaching a single layer of a 3D or array texture to a framebuffer actually
|
||||
// renders to that layer. DirectGLES hands the layer straight to
|
||||
// glFramebufferTextureLayer, so it does; DirectVulkan maps a GL layer onto a Vulkan
|
||||
// array layer with no notion of a 3D depth slice, so it does not yet. Defaults to false
|
||||
// so a backend that never sets it gets the conservative answer.
|
||||
Bool SupportsPerLayerFramebufferAttachment = false;
|
||||
SizeT MaxShaderStorageBlockSize = 128 * 1024 * 1024;
|
||||
Uint32 SubgroupSize = 0;
|
||||
Uint32 SubgroupSupportedStages = 0;
|
||||
|
||||
@@ -1109,6 +1109,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
clampStageImageUniforms(m_GLESCapabilities.MaxComputeImageUniforms);
|
||||
m_dynamicParameters.SupportsDistinctDepthStencilAttachments =
|
||||
ProbeDistinctDepthStencilAttachments(DirectGLES::g_GLESFuncs);
|
||||
// SyncAttachmentObject routes a layered upload target to glFramebufferTextureLayer with the
|
||||
// attachment's layer passed through, so this backend really does render to the layer it was
|
||||
// given - provided the driver resolved the entry point at all.
|
||||
m_dynamicParameters.SupportsPerLayerFramebufferAttachment =
|
||||
DirectGLES::g_GLESFuncs.glFramebufferTextureLayer != nullptr;
|
||||
m_dynamicParameters.MaxDrawBuffers = m_GLESCapabilities.MaxDrawBuffers;
|
||||
m_dynamicParameters.MaxColorAttachments = m_GLESCapabilities.MaxColorAttachments;
|
||||
m_dynamicParameters.MaxClipDistances = m_GLESCapabilities.MaxClipDistances;
|
||||
|
||||
@@ -1398,21 +1398,20 @@ 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) {
|
||||
// Everything above is the spec's error set and is answered for every target and every layer
|
||||
// on every backend. Whether the attachment can actually be honoured is a backend question:
|
||||
// DirectGLES hands the layer to glFramebufferTextureLayer and renders to it, while
|
||||
// DirectVulkan maps a GL layer onto a Vulkan array layer with no notion of a 3D depth slice,
|
||||
// so a slice lands outside the image and the renderer asserts on the clear. Letting it
|
||||
// through there would only move the failure downstream, so it is declined instead - layer
|
||||
// zero always works, being the plain first-slice attachment.
|
||||
const Bool backsLayeredAttachment = limits.SupportsPerLayerFramebufferAttachment;
|
||||
// A cube map array additionally has no image shape at all in VkTextureManager, so on that
|
||||
// backend it cannot be an attachment whatever the layer is.
|
||||
const Bool isCubeMapArray = textureObject->GetTarget() == TextureTarget::TextureCubeMapArray;
|
||||
if ((layer != 0 && !backsLayeredAttachment) || (isCubeMapArray && !backsLayeredAttachment)) {
|
||||
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.");
|
||||
__func__, "This backend does not resolve a framebuffer attachment's layer onto its image.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user