[Feat] (DirectGLES, MG_Util): normalize the coordinates of a rectangle lookup

A rectangle texture is emulated on an ES 2D texture, and LowerRectImagesForEssl
rewrites the image type in the SPIR-V to match. That is exact only where the lookup
addresses texels directly, which is why the pass declined any module containing a
lookup that takes normalized coordinates - the whole KHR-GL40.texture_gather 2drect
set among them.

The missing half is one divide: a rectangle lookup's coordinate is in texels and the
2D lookup it becomes wants [0,1], so the coordinate has to be divided by the texture's
size. It goes in on the ESSL the transpiler produces, next to the LOD-bias emulation
that already rewrites lookup arguments there, and reads the size back with
textureSize() rather than plumbing a uniform down - the emulated texture is a real ES
2D texture, so the shader can ask it directly.

Only the forms whose argument 1 is the bare coordinate are rewritten - texture,
textureOffset and the three textureGather flavours, which covers the Dref gathers too
because those carry the compare value in a separate argument. texelFetch is
deliberately left alone: its coordinates are integer texels on both targets. The
SPIR-V pass keeps declining everything else, so a projective lookup or a Dref sample
(where the compare value rides in coord.z) still refuses the module instead of
producing something subtly wrong.

Which samplers were declared rectangle is no longer visible in the transpiled source -
they are plain sampler2D by then - so the names come from the frontend program's
reflection.
This commit is contained in:
BZLZHH
2026-08-04 10:38:01 -04:00
parent f38dbf018d
commit 5437947240
4 changed files with 110 additions and 10 deletions
@@ -397,11 +397,19 @@ namespace MobileGL {
}
} else {
switch (opcode) {
// Everything that takes normalized coordinates. Tracing each one back to
// its image type would let a module mix a normalized 2D lookup with a
// rectangle fetch, but the extra reach is not worth the risk of getting
// the trace wrong: decline the whole module instead.
case spv::Op::OpImageSampleImplicitLod:
// Normalized-coordinate lookups whose ESSL form the backend's
// NormalizeRectSamplerCoordinates post-pass cannot repair: the
// coordinate is either fused with something else in a single argument
// (the Dref sample forms carry the compare value in coord.z) or the
// divide would have to happen after a projective divide. Tracing each
// one back to its image type would let a module mix a normalized 2D
// lookup with a rectangle fetch, but the extra reach is not worth the
// risk of getting the trace wrong: decline the whole module instead.
//
// OpImageSampleImplicitLod, OpImageGather and OpImageDrefGather are
// absent because all three become an ESSL call whose argument 1 is the
// bare texel-space coordinate, which the post-pass divides by the
// texture size.
case spv::Op::OpImageSampleExplicitLod:
case spv::Op::OpImageSampleDrefImplicitLod:
case spv::Op::OpImageSampleDrefExplicitLod:
@@ -409,8 +417,6 @@ namespace MobileGL {
case spv::Op::OpImageSampleProjExplicitLod:
case spv::Op::OpImageSampleProjDrefImplicitLod:
case spv::Op::OpImageSampleProjDrefExplicitLod:
case spv::Op::OpImageGather:
case spv::Op::OpImageDrefGather:
case spv::Op::OpImageSparseSampleImplicitLod:
case spv::Op::OpImageSparseSampleExplicitLod:
case spv::Op::OpImageSparseSampleDrefImplicitLod: