mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 22:28:32 +09:00
[Fix] (DirectGLES): report distinct depth/stencil framebuffers as unsupported
GL only requires framebuffers whose depth and stencil attachments refer to the
same image; anything else may be answered GL_FRAMEBUFFER_UNSUPPORTED, and both
backends' real targets do exactly that - DirectVulkan cannot form two separate
attachments at all, and the ES drivers behind DirectGLES return UNSUPPORTED for
a separate depth renderbuffer plus stencil renderbuffer.
The frontend already knew how to detect the configuration, but only consulted it
for DirectVulkan. On DirectGLES it answered GL_FRAMEBUFFER_COMPLETE for a
framebuffer the driver had rejected, so every clear and draw against it was
silently dropped and the results read back as zeros - which is what
KHR-GL3x.packed_depth_stencil.verify_mixed_attachments saw. (That test
explicitly tolerates GL_FRAMEBUFFER_UNSUPPORTED; what it cannot survive is being
told the framebuffer works.)
Turned into a backend capability rather than a backend-type check, probed once
at init from a scratch framebuffer the same way the format-capability cache is,
so a driver that does support the configuration keeps using it. Defaults to
supported, leaving any backend that does not set it on the permissive path.
Fixes KHR-GL3{2,3}.packed_depth_stencil.verify_mixed_attachments for both
formats; DirectVulkan re-verified unchanged at 23/25 pass + 2 not-supported.
This commit is contained in:
@@ -324,6 +324,13 @@ namespace MobileGL {
|
|||||||
Float MaxFragmentInterpolationOffset = 0.4375f;
|
Float MaxFragmentInterpolationOffset = 0.4375f;
|
||||||
Int FragmentInterpolationOffsetBits = 4;
|
Int FragmentInterpolationOffsetBits = 4;
|
||||||
Bool SupportsWideLines = false;
|
Bool SupportsWideLines = false;
|
||||||
|
// Whether a framebuffer whose depth and stencil attachments are distinct
|
||||||
|
// images can be rendered to. GL only requires support when both refer to the
|
||||||
|
// same image and lets an implementation answer GL_FRAMEBUFFER_UNSUPPORTED
|
||||||
|
// otherwise, which is what DirectVulkan (one combined attachment) and the
|
||||||
|
// real ES drivers behind DirectGLES both do. Defaults to true so a backend
|
||||||
|
// that never sets it keeps the permissive behaviour.
|
||||||
|
Bool SupportsDistinctDepthStencilAttachments = true;
|
||||||
SizeT MaxShaderStorageBlockSize = 128 * 1024 * 1024;
|
SizeT MaxShaderStorageBlockSize = 128 * 1024 * 1024;
|
||||||
Uint32 SubgroupSize = 0;
|
Uint32 SubgroupSize = 0;
|
||||||
Uint32 SubgroupSupportedStages = 0;
|
Uint32 SubgroupSupportedStages = 0;
|
||||||
|
|||||||
@@ -357,6 +357,42 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
return complete;
|
return complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whether the driver renders to a framebuffer whose depth and stencil come from
|
||||||
|
// two different renderbuffers. GL only requires support when both attachments are
|
||||||
|
// the same image, and ES drivers commonly answer GL_FRAMEBUFFER_UNSUPPORTED here;
|
||||||
|
// reporting COMPLETE from the frontend and then rendering into a framebuffer the
|
||||||
|
// driver refuses leaves the results silently empty.
|
||||||
|
Bool ProbeDistinctDepthStencilAttachments(const MG_External::GLESFunctionsTable& gl) {
|
||||||
|
if (!gl.glGenFramebuffers || !gl.glBindFramebuffer || !gl.glFramebufferRenderbuffer ||
|
||||||
|
!gl.glCheckFramebufferStatus || !gl.glDeleteFramebuffers || !gl.glGenRenderbuffers ||
|
||||||
|
!gl.glBindRenderbuffer || !gl.glRenderbufferStorage || !gl.glDeleteRenderbuffers) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint prevFramebuffer = 0, prevRenderbuffer = 0;
|
||||||
|
gl.glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFramebuffer);
|
||||||
|
gl.glGetIntegerv(GL_RENDERBUFFER_BINDING, &prevRenderbuffer);
|
||||||
|
|
||||||
|
GLuint framebuffer = 0;
|
||||||
|
GLuint renderbuffers[2] = {0, 0};
|
||||||
|
gl.glGenFramebuffers(1, &framebuffer);
|
||||||
|
gl.glGenRenderbuffers(2, renderbuffers);
|
||||||
|
gl.glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[0]);
|
||||||
|
gl.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4);
|
||||||
|
gl.glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[1]);
|
||||||
|
gl.glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 4, 4);
|
||||||
|
gl.glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||||
|
gl.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffers[0]);
|
||||||
|
gl.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderbuffers[1]);
|
||||||
|
const Bool supported = gl.glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
|
||||||
|
|
||||||
|
gl.glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(prevFramebuffer));
|
||||||
|
gl.glBindRenderbuffer(GL_RENDERBUFFER, static_cast<GLuint>(prevRenderbuffer));
|
||||||
|
gl.glDeleteFramebuffers(1, &framebuffer);
|
||||||
|
gl.glDeleteRenderbuffers(2, renderbuffers);
|
||||||
|
return supported;
|
||||||
|
}
|
||||||
|
|
||||||
Bool ProbeFramebufferCompletenessForRenderbuffer(const MG_External::GLESFunctionsTable& gl,
|
Bool ProbeFramebufferCompletenessForRenderbuffer(const MG_External::GLESFunctionsTable& gl,
|
||||||
GLuint renderbuffer,
|
GLuint renderbuffer,
|
||||||
TextureInternalFormat format) {
|
TextureInternalFormat format) {
|
||||||
@@ -1046,6 +1082,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
clampStageImageUniforms(m_GLESCapabilities.MaxFragmentImageUniforms);
|
clampStageImageUniforms(m_GLESCapabilities.MaxFragmentImageUniforms);
|
||||||
m_dynamicParameters.MaxComputeImageUniforms =
|
m_dynamicParameters.MaxComputeImageUniforms =
|
||||||
clampStageImageUniforms(m_GLESCapabilities.MaxComputeImageUniforms);
|
clampStageImageUniforms(m_GLESCapabilities.MaxComputeImageUniforms);
|
||||||
|
m_dynamicParameters.SupportsDistinctDepthStencilAttachments =
|
||||||
|
ProbeDistinctDepthStencilAttachments(DirectGLES::g_GLESFuncs);
|
||||||
m_dynamicParameters.MaxDrawBuffers = m_GLESCapabilities.MaxDrawBuffers;
|
m_dynamicParameters.MaxDrawBuffers = m_GLESCapabilities.MaxDrawBuffers;
|
||||||
m_dynamicParameters.MaxColorAttachments = m_GLESCapabilities.MaxColorAttachments;
|
m_dynamicParameters.MaxColorAttachments = m_GLESCapabilities.MaxColorAttachments;
|
||||||
m_dynamicParameters.MaxClipDistances = m_GLESCapabilities.MaxClipDistances;
|
m_dynamicParameters.MaxClipDistances = m_GLESCapabilities.MaxClipDistances;
|
||||||
|
|||||||
@@ -22,9 +22,21 @@
|
|||||||
|
|
||||||
namespace MobileGL::MG_Impl::GLImpl {
|
namespace MobileGL::MG_Impl::GLImpl {
|
||||||
namespace {
|
namespace {
|
||||||
Bool IsActiveBackendDirectVulkan() {
|
// GL only requires support for framebuffers whose depth and stencil attachments
|
||||||
|
// are the same image; anything else may be reported GL_FRAMEBUFFER_UNSUPPORTED.
|
||||||
|
// DirectVulkan cannot form two separate attachments at all, and the real ES
|
||||||
|
// drivers behind DirectGLES answer UNSUPPORTED for it too - so saying COMPLETE
|
||||||
|
// and then rendering into a framebuffer the driver refuses produced silently
|
||||||
|
// empty results (KHR-GL3x.packed_depth_stencil.verify_mixed_attachments).
|
||||||
|
Bool ActiveBackendRejectsDistinctDepthStencil() {
|
||||||
auto* activeBackend = MG_Backend::pActiveBackendObject.get();
|
auto* activeBackend = MG_Backend::pActiveBackendObject.get();
|
||||||
return activeBackend != nullptr && activeBackend->GetBackendType() == BackendType::DirectVulkan;
|
if (activeBackend == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (activeBackend->GetBackendType() == BackendType::DirectVulkan) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return !activeBackend->GetDynamicParameters().SupportsDistinctDepthStencilAttachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool HasDistinctCompleteDepthStencilTextureAttachments(
|
Bool HasDistinctCompleteDepthStencilTextureAttachments(
|
||||||
@@ -66,7 +78,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
(depthAttachment.IsTexture() || stencilAttachment.IsTexture());
|
(depthAttachment.IsTexture() || stencilAttachment.IsTexture());
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool IsUnsupportedFramebufferForDirectVulkan(
|
Bool HasUnsupportedDistinctDepthStencilAttachments(
|
||||||
const MG_State::GLState::FramebufferObject& framebufferObject) {
|
const MG_State::GLState::FramebufferObject& framebufferObject) {
|
||||||
// TODO: Keep this in sync with DirectVulkan renderbuffer support as color renderbuffer rendering lands.
|
// TODO: Keep this in sync with DirectVulkan renderbuffer support as color renderbuffer rendering lands.
|
||||||
return HasDistinctCompleteDepthStencilTextureAttachments(framebufferObject) ||
|
return HasDistinctCompleteDepthStencilTextureAttachments(framebufferObject) ||
|
||||||
@@ -1631,8 +1643,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
if (HasNonRenderableColorAttachment(*framebufferObject)) {
|
if (HasNonRenderableColorAttachment(*framebufferObject)) {
|
||||||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
if (IsActiveBackendDirectVulkan() &&
|
if (ActiveBackendRejectsDistinctDepthStencil() &&
|
||||||
IsUnsupportedFramebufferForDirectVulkan(*framebufferObject)) {
|
HasUnsupportedDistinctDepthStencilAttachments(*framebufferObject)) {
|
||||||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
return GL_FRAMEBUFFER_COMPLETE;
|
return GL_FRAMEBUFFER_COMPLETE;
|
||||||
@@ -1659,8 +1671,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
if (HasNonRenderableColorAttachment(*framebufferObject)) {
|
if (HasNonRenderableColorAttachment(*framebufferObject)) {
|
||||||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
if (IsActiveBackendDirectVulkan() &&
|
if (ActiveBackendRejectsDistinctDepthStencil() &&
|
||||||
IsUnsupportedFramebufferForDirectVulkan(*framebufferObject)) {
|
HasUnsupportedDistinctDepthStencilAttachments(*framebufferObject)) {
|
||||||
return GL_FRAMEBUFFER_UNSUPPORTED;
|
return GL_FRAMEBUFFER_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
return GL_FRAMEBUFFER_COMPLETE;
|
return GL_FRAMEBUFFER_COMPLETE;
|
||||||
|
|||||||
Reference in New Issue
Block a user