mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-13 14:48:32 +09:00
[Fix] (MG_State, DirectGLES): sample a mipmap-incomplete texture as black
A minification filter that reads the mip chain requires every level from the base down to hold exactly half the previous one's size; a texture that does not is incomplete and every lookup on it returns (0, 0, 0, 1) (GL 4.6 core 8.17). Nothing checked it. The ES driver cannot catch this on MobileGL's behalf, which is why it has to be a frontend rule here: the backend texture is immutable storage allocated from the level set as it stood, so a level the application later redefined at a different size never reaches the driver at all, and the ES texture stays complete. That is exactly what KHR-GL40.texture_gather.incomplete-texture does - it redefines level 1 of a complete chain as 1x1 - and it read the original contents back. The check runs where the sampling bindings are established, and an incomplete texture simply leaves its native target unbound: an unbound ES target samples as (0, 0, 0, 1), which is the answer GL asks for, with no scratch texture to keep around. An array texture's layer count is not one of the dimensions that halves, so the comparison only shrinks the components that belong to the image itself - getting that wrong turned eight *-2darray cases black.
This commit is contained in:
@@ -1613,6 +1613,20 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
const GLenum targetGL = TextureImpl::ConvertTextureTargetToBackendGLEnum(target);
|
||||
|
||||
// A texture whose mip chain does not satisfy the filter's completeness
|
||||
// rules samples as (0, 0, 0, 1). The ES driver cannot work that out for
|
||||
// itself here: the backend texture is immutable storage, so a level the
|
||||
// application redefined at the wrong size never reached it. Leaving the
|
||||
// native target unbound produces exactly the incomplete-texture result.
|
||||
const auto& effectiveSampler = textureUnit.GetSamplerObject()
|
||||
? textureUnit.GetSamplerObject()
|
||||
: textureObject->GetSamplerObject();
|
||||
const Bool mipmappedFilter =
|
||||
effectiveSampler && effectiveSampler->GetMipmapMode() != SamplerMipmapMode::None;
|
||||
if (!MG_State::GLState::IsMipmapCompleteForFilter(textureObject.get(), mipmappedFilter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Bind texture object
|
||||
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject.get());
|
||||
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) continue;
|
||||
|
||||
Reference in New Issue
Block a user