[Feat] (DirectGLES): support rectangle textures where the emulation is exact

ES has no rectangle target and no rectangle sampler, so DirectGLES declared
GL_TEXTURE_RECTANGLE unsupported outright: the texture was never synced or bound,
and SPIRV-Cross refused the shader ("Rectangle textures are not supported on
OpenGL ES") which left the whole program unlinkable.

A rectangle texture is a single-level, clamped 2D texture whose only real
difference is that its lookups take non-normalized coordinates. Where every use
takes *integer* texel coordinates - texelFetch, textureSize - that difference
does not exist at all, and the two are the same thing. So:

- A new SPIR-V pass rewrites Dim::Rect image types to Dim::2D before
  transpiling, and restates the rectangle capabilities as Shader. It declines
  any module containing a normalized-coordinate lookup rather than emitting
  something subtly wrong; SPIRV-Cross then rejects that module exactly as
  before, so nothing that used to work changes and nothing new renders wrongly.
- The target maps to GL_TEXTURE_2D for storage, uploads and binding, alongside
  the existing 1D and 1D-array emulation.

Fixes KHR-GL31.texture_size_promotion.functional outright, which takes GL31 to
100% conformance. GL32/GL33 advance past their rectangle cases to a separate
GL_RGB16 multisample issue. No regressions across texture_swizzle, shaders30,
texture_lod_*, framebuffer_blit, packed_depth_stencil, transform_feedback,
clip_distance or draw_buffers; DirectVulkan re-verified unaffected.
This commit is contained in:
BZLZHH
2026-08-02 01:56:22 -04:00
parent 9dff24f3e1
commit 6de38c666c
4 changed files with 112 additions and 7 deletions
@@ -3344,6 +3344,17 @@ namespace MobileGL::MG_Backend::DirectGLES {
effectiveSpirv = &noperspectiveSpirv;
}
// ES has no rectangle sampler, and SPIRV-Cross refuses the whole module rather
// than approximating one. Where every use takes integer texel coordinates a
// rectangle image is indistinguishable from a 2D one, so rewrite the type and let
// it through; the pass declines anything it cannot convert exactly.
Vector<unsigned int> rectLoweredSpirv;
if (MG_Util::ShaderTranspiler::ShaderCompiler::LowerRectImagesForEssl(*effectiveSpirv,
rectLoweredSpirv) &&
!rectLoweredSpirv.empty()) {
effectiveSpirv = &rectLoweredSpirv;
}
MG_Util::ShaderTranspiler::SpvcSession spvcSession(*effectiveSpirv,
MG_Util::ShaderTranspiler::SessionUsageBit::Transpile);
+11 -7
View File
@@ -270,18 +270,21 @@ namespace MobileGL::MG_Backend::DirectGLES {
namespace TextureImpl {
inline Bool IsSupportedTextureTarget(TextureTarget target) {
// Rectangle textures need non-normalized sampling ES cannot express; everything else is
// either native or emulated (1D -> 2D with height 1, 1D array -> 2D array, see
// MapToBackendTextureTarget). SPIRV-Cross already emits the matching ESSL samplers and
// coordinate padding for 1D/1D-array shaders.
return target != TextureTarget::TextureRectangle;
// Every desktop-only target is stored on an ES one; see MapToBackendTextureTarget.
(void)target;
return true;
}
// ES has no 1D targets: 1D textures are stored as 2D (height 1) and 1D arrays as 2D arrays
// (height 1, layers in depth). Must match SPIRV-Cross's ES 1D-as-2D shader emulation.
// ES has none of the desktop-only targets: 1D textures are stored as 2D (height 1), 1D
// arrays as 2D arrays (height 1, layers in depth), and rectangle textures as plain 2D -
// they are single-level and already clamp, so only the non-normalized coordinates differ.
// Must match the shader-side emulation: SPIRV-Cross handles 1D/1D-array itself, and
// ShaderCompiler::LowerRectImagesForEssl rewrites rectangle images (declining any module
// whose lookups are not integer-coordinate, which SPIRV-Cross then still rejects).
inline TextureTarget MapToBackendTextureTarget(TextureTarget target) {
switch (target) {
case TextureTarget::Texture1D:
case TextureTarget::TextureRectangle:
return TextureTarget::Texture2D;
case TextureTarget::Texture1DArray:
return TextureTarget::Texture2DArray;
@@ -297,6 +300,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
inline GLenum ConvertTextureUploadTargetToBackendGLEnum(TextureUploadTarget uploadTarget) {
switch (uploadTarget) {
case TextureUploadTarget::Texture1D:
case TextureUploadTarget::TextureRectangle:
return GL_TEXTURE_2D;
case TextureUploadTarget::Texture1DArray:
return GL_TEXTURE_2D_ARRAY;