mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +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:
@@ -156,6 +156,14 @@ namespace MobileGL::MG_State::GLState {
|
||||
? static_cast<TextureObjectMipmap*>(texture)
|
||||
: nullptr;
|
||||
}
|
||||
// Whether the texture satisfies the mipmap-completeness rules a minification filter
|
||||
// that samples the mip chain imposes (GL 4.6 core 8.17): every level from the base to
|
||||
// the effective max must exist at exactly half the previous one's size. `mipmapped` is
|
||||
// the effective sampler's answer to "does this filter read more than the base level" -
|
||||
// when it is false only base-level completeness matters, which the ordinary
|
||||
// IsComplete() already covers. Sampling an incomplete texture returns (0, 0, 0, 1).
|
||||
Bool IsMipmapCompleteForFilter(const ITextureObject* texture, Bool mipmapped);
|
||||
|
||||
inline const TextureObjectMipmap* AsMipmapTexture(const ITextureObject* texture) {
|
||||
return (texture && texture->GetStorageType() == TextureStorageType::Mipmap)
|
||||
? static_cast<const TextureObjectMipmap*>(texture)
|
||||
|
||||
Reference in New Issue
Block a user