[MG_Backend] (DirectGLES): clip view mip generation to the view's layer window

glGenerateMipmap's native arm carries BASE_LEVEL/MAX_LEVEL of the view's own
ES name, so the LEVEL axis was already clipped the way the view describes, but
the layer set it writes is every layer of the storage the view aliases. A
generation through a windowed texture view therefore rewrote the owner's layers
outside the window (F1WireScenario
.GenerateMipmapThroughViewKeepsOwnerLevelsAndLayersOutsideItsWindow).

Both arms now read the window and generate the chain with per-layer blits
between the owner's levels MinLevel + L, over layers
[MinLayer, MinLayer + NumLayers), and leave the native call for the shapes it
already gets right: no view, a view whose layer window covers the whole
storage, a multisample view, and aspects the layer blits do not carry. The
record arm reads the window from the sampler view CSO with the same validation
SyncTextureViewToBackendByRecord uses (Fatal{ProtocolCorruption} on a stale or
foreign record); the monolith arm reads the same numbers off the frontend view
object. ScratchFBOImpl gains EnsureDepthAttachmentLayer for the depth-only
aspect.
This commit is contained in:
2026-09-20 18:47:26 -04:00
parent 8ffb87109a
commit 73b37bbe83
3 changed files with 305 additions and 1 deletions
+34 -1
View File
@@ -11427,6 +11427,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
fb.depthTex = 0;
fb.depthTarget = 0;
fb.depthLevel = 0;
fb.depthLayer = -1;
fb.depthHasStencil = false;
fb.attachmentsKnown = true;
}
@@ -11459,6 +11460,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
fb.depthTex = 0;
fb.depthTarget = 0;
fb.depthLevel = 0;
fb.depthLayer = -1;
fb.depthHasStencil = false;
}
} // namespace
@@ -11546,7 +11548,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
RecordNoColor(fb);
}
if (fb.depthTex == tex && fb.depthTarget == texTarget && fb.depthLevel == level &&
fb.depthHasStencil == withStencil) {
fb.depthLayer < 0 && fb.depthHasStencil == withStencil) {
return;
}
if (fb.depthTex != 0) {
@@ -11564,10 +11566,41 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
fb.depthTex = tex;
fb.depthTarget = texTarget;
fb.depthLayer = -1;
fb.depthLevel = level;
fb.depthHasStencil = withStencil;
}
// The layer-point sibling of EnsureColorAttachmentLayer above, for a view's mip chain in
// a depth-only storage owner. depthTarget == 0 is the marker that this point was made
// with glFramebufferTextureLayer, exactly as colorTarget == 0 is on the color side, so a
// later 2D attach to the same level is never deduped against it.
void EnsureDepthAttachmentLayer(ScratchFramebuffer& fb, GLenum fbTarget, Uint tex, GLint level, GLint layer) {
PrepareForUse(fb, fbTarget);
if (fb.colorTex != 0) {
g_GLESFuncs.glFramebufferTexture2D(fbTarget, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
RecordNoColor(fb);
}
if (fb.depthTex == tex && fb.depthTarget == 0 && fb.depthLevel == level && fb.depthLayer == layer &&
!fb.depthHasStencil) {
return;
}
if (fb.depthTex != 0) {
g_GLESFuncs.glFramebufferTexture2D(fbTarget, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
}
DrainPendingGLErrors();
g_GLESFuncs.glFramebufferTextureLayer(fbTarget, GL_DEPTH_ATTACHMENT, tex, level, layer);
if (g_GLESFuncs.glGetError() != GL_NO_ERROR) {
RecordNoDepth(fb);
return;
}
fb.depthTex = tex;
fb.depthTarget = 0;
fb.depthLevel = level;
fb.depthLayer = layer;
fb.depthHasStencil = false;
}
void EnsureNoColorAttachment(ScratchFramebuffer& fb, GLenum fbTarget) {
PrepareForUse(fb, fbTarget);
if (fb.colorTex != 0) {