[Fix] (DirectGLES): depth/stencil clear value and readback gaps

Three separate holes, all of them silent, that KHR-GL3x.framebuffer_blit walks
straight into because it clears and reads back depth and stencil directly:

- glClearStencil was frontend-only. The value was recorded in render state and
  never synced, so the real driver kept its default of 0 and every
  glClear(GL_STENCIL_BUFFER_BIT) wrote zeros. glClearColor and glClearDepthf
  were already synced right next to it.

- Stencil readback assumed GL_STENCIL_INDEX works. It is not part of core ES
  (it needs GL_NV_read_stencil) and a driver without it rejects the read
  outright, which left the caller's buffer untouched. Where the attachment is a
  combined depth-stencil buffer the packed GL_DEPTH_STENCIL read carries the
  same bytes in its low octet, so that is now the fallback; the widening to
  GL_UNSIGNED_SHORT/INT moved into the same helper, since even a byte-for-byte
  read needs it.

- Depth readback always went through GL_UNSIGNED_INT. A floating-point depth
  attachment (GL_DEPTH_COMPONENT32F, GL_DEPTH32F_STENCIL8 - the latter is what
  dEQP's own fbo-surface-type wrapper framebuffer picks) rejects that with
  GL_INVALID_OPERATION and only reads back as GL_FLOAT. Try both.

And one format gap behind the same test: GL_DEPTH_COMPONENT32 has no ES
equivalent and was being normalized to the *unsized* GL_DEPTH_COMPONENT base
format, which is not a legal glTexStorage/glRenderbufferStorage internal format
there - the attachment ended up with no storage and the framebuffer read back as
incomplete. GL_DEPTH_COMPONENT32F is the sized ES format that keeps the
requested 32-bit depth footprint; the transfer type follows it to GL_FLOAT.

Takes KHR-GL3x.framebuffer_blit from 0/3 to 2/3 (the remaining
multisampled_to_singlesampled_blit_color_config_test is a separate
single-channel MSAA resolve issue). Note that scissor_blit additionally needs
the suite to run with a depth/stencil config the test agrees with
(--deqp-gl-config-name=rgba8888d24s8): under FBO surfaces the test hardcodes
GL_DEPTH24_STENCIL8 for its own buffers while dEQP's wrapper framebuffer
defaults to GL_DEPTH32F_STENCIL8, and blitting depth between mismatched formats
is a spec error that any conformant driver has to report.
This commit is contained in:
BZLZHH
2026-08-01 13:24:30 -04:00
parent 8269a1786f
commit 8b75628dec
2 changed files with 182 additions and 46 deletions
@@ -66,7 +66,13 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
switch (internalFormat) {
case GL_DEPTH_COMPONENT32:
if (options & PixelFormatNormalizeOptionBit::NoDepthComponent32) {
*outInternalFormat = GL_DEPTH_COMPONENT;
// The unsized GL_DEPTH_COMPONENT base format is not a legal
// glTexStorage/glRenderbufferStorage internal format on ES, which left
// the attachment with no storage at all (KHR-GL3x.framebuffer_blit's
// GL_DEPTH_COMPONENT32 config then read an incomplete framebuffer).
// GL_DEPTH_COMPONENT32F is the sized ES format that keeps the requested
// 32-bit depth footprint.
*outInternalFormat = GL_DEPTH_COMPONENT32F;
break;
}
*outInternalFormat = internalFormat;
@@ -552,7 +558,9 @@ namespace MobileGL::MG_Util::TextureFormatProcessor {
*outType = GL_UNSIGNED_INT;
break;
case GL_DEPTH_COMPONENT32:
*outType = GL_UNSIGNED_INT;
// Follows the internal-format normalization above: ES only accepts
// GL_FLOAT data for a GL_DEPTH_COMPONENT32F store.
*outType = (options & PixelFormatNormalizeOptionBit::NoDepthComponent32) ? GL_FLOAT : GL_UNSIGNED_INT;
break;
case GL_DEPTH_COMPONENT32F:
*outType = GL_FLOAT;