mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Fix] (Espryt): keep the invalid-image placeholder on ANGLE instead of probing an empty unit it faults on
This commit is contained in:
+3
-2
@@ -217,8 +217,9 @@ namespace MobileGL::MG_Config {
|
||||
// MOBILEGL_ESPRYT_INVALID_IMAGE_PLACEHOLDER: DirectGLES binds an image unit GL 4.6 8.26
|
||||
// calls invalid (a level the texture does not have) to a zeroed 1x1 texture of the bind's
|
||||
// shape instead of leaving it empty. The Adreno ES driver answers a load through an EMPTY
|
||||
// unit with alpha 1 where GL says 0; the driver POST measures that and arms this by
|
||||
// itself, so Auto is right everywhere. The placeholder's one texel is real, so a store
|
||||
// unit with alpha 1 where GL says 0, and ANGLE faults on any use of an empty unit; the
|
||||
// driver POST measures the first and Auto arms this on ANGLE without probing, so Auto is
|
||||
// right everywhere. The placeholder's one texel is real, so a store
|
||||
// through such a unit can be read back through the same unit in the same pass - which is
|
||||
// why a healthy driver keeps the empty unit. ForceOn exercises the placeholder on a
|
||||
// healthy driver; ForceOff is the negative control.
|
||||
|
||||
@@ -2871,9 +2871,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
}
|
||||
|
||||
// What such a unit is bound to instead, on a driver whose EMPTY unit is not enough
|
||||
// (GLESCapabilities::EmptyImageUnitsReadNonzero): ES 3.2 8.22 leaves an invalid load's
|
||||
// alpha undefined, and Adreno answers 1 where GL says 0. Elsewhere the unit stays empty,
|
||||
// which is exact. A texel outside
|
||||
// (GLESCapabilities::UseInvalidImagePlaceholder): ES 3.2 8.22 leaves an invalid load's
|
||||
// alpha undefined, Adreno answers 1 where GL says 0, and ANGLE faults outright.
|
||||
// Elsewhere the unit stays empty, which is exact. A texel outside
|
||||
// a level is invalid too, and that Adreno answers (0, 0, 0, 0) with the store dropped - so
|
||||
// the unit gets a 1x1 texture of the shape and format the bind names, cleared to zero each
|
||||
// time it is bound. Only texel (0, 0[, 0]) of it exists; it is private to the unit, so a
|
||||
@@ -2990,7 +2990,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
return;
|
||||
}
|
||||
if (ImageViewNamesNoTexel(view)) {
|
||||
if (!g_GLESCapabilities.EmptyImageUnitsReadNonzero) {
|
||||
if (!g_GLESCapabilities.UseInvalidImagePlaceholder) {
|
||||
g_GLESFuncs.glBindImageTexture(unit, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2125,24 +2125,30 @@ namespace MobileGL::MG_Util::BackendLoader {
|
||||
? "true (the subgroup emulation reads its scratch through atomic loads)"
|
||||
: "false");
|
||||
|
||||
caps.IsAngleRenderer = caps.GLESRendererString.find("ANGLE") != String::npos;
|
||||
|
||||
switch (MG_Config::Features.EsprytInvalidImagePlaceholder) {
|
||||
case MG_Config::QuirkOverride::ForceOn:
|
||||
caps.EmptyImageUnitsReadNonzero = true;
|
||||
caps.UseInvalidImagePlaceholder = true;
|
||||
break;
|
||||
case MG_Config::QuirkOverride::ForceOff:
|
||||
caps.EmptyImageUnitsReadNonzero = false;
|
||||
caps.UseInvalidImagePlaceholder = false;
|
||||
break;
|
||||
case MG_Config::QuirkOverride::Auto:
|
||||
default:
|
||||
caps.EmptyImageUnitsReadNonzero = SelfTest::EmptyImageUnitsReadNonzero(glesFuncs);
|
||||
// ANGLE dereferences a null texture when a dispatch or draw reaches an EMPTY image
|
||||
// unit the program uses, so the probe cannot be run there: its subject variant is
|
||||
// exactly that dispatch, and a crash is no verdict. ANGLE keeps the placeholder
|
||||
// without being asked.
|
||||
caps.UseInvalidImagePlaceholder =
|
||||
caps.IsAngleRenderer || SelfTest::EmptyImageUnitsReadNonzero(glesFuncs);
|
||||
break;
|
||||
}
|
||||
MGLOG_I(" Empty image units read nonzero: %s",
|
||||
caps.EmptyImageUnitsReadNonzero
|
||||
? "true (an invalid image unit is bound to a zeroed placeholder)"
|
||||
: "false");
|
||||
MGLOG_I(" Invalid image units bound to a placeholder: %s",
|
||||
!caps.UseInvalidImagePlaceholder ? "false (an invalid image unit stays empty)"
|
||||
: caps.IsAngleRenderer ? "true (ANGLE faults on a use of an empty image unit)"
|
||||
: "true (empty image units read nonzero)");
|
||||
|
||||
caps.IsAngleRenderer = caps.GLESRendererString.find("ANGLE") != String::npos;
|
||||
caps.IsAngleLlvmpipeRenderer =
|
||||
caps.IsAngleRenderer && caps.GLESRendererString.find("llvmpipe") != String::npos;
|
||||
caps.AvoidSamplerMipmapMinFilter =
|
||||
|
||||
@@ -1329,11 +1329,12 @@ namespace MobileGL {
|
||||
// Adreno). The subgroup emulation then reads its scratch through atomic loads.
|
||||
// Defaults FALSE: never assumed broken on an unmeasured driver.
|
||||
Bool SharedMemoryLoadsGoStale = false;
|
||||
// True when a load through an EMPTY image unit returns a nonzero texel
|
||||
// (SelfTest::EmptyImageUnitsReadNonzero - measured on Adreno: alpha 1). DirectGLES
|
||||
// then binds an invalid unit to a zeroed placeholder instead of leaving it empty.
|
||||
// Defaults FALSE: never assumed broken on an unmeasured driver.
|
||||
Bool EmptyImageUnitsReadNonzero = false;
|
||||
// True when DirectGLES binds an invalid image unit to a zeroed placeholder instead of
|
||||
// leaving it empty: on a driver whose load through an EMPTY unit returns a nonzero
|
||||
// texel (SelfTest::EmptyImageUnitsReadNonzero - measured on Adreno: alpha 1), and on
|
||||
// ANGLE, which faults on a dispatch or draw that reaches an empty unit and so cannot
|
||||
// be probed. Defaults FALSE: never assumed broken on an unmeasured driver.
|
||||
Bool UseInvalidImagePlaceholder = false;
|
||||
Int UniformBufferOffsetAlignment = 256;
|
||||
// Its storage-buffer counterpart, queried separately because it is a separate limit:
|
||||
// Adreno 830 answers 32 for GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT and 64 for
|
||||
|
||||
Reference in New Issue
Block a user