[Fix] (MG_State, MG_Backend/DirectGLES): join both link phases on the draw and drain paths, and refuse to bind a program whose SPIR-V never arrived

This commit is contained in:
2026-08-10 06:08:30 -04:00
parent 1958934594
commit e02e5caa17
4 changed files with 32 additions and 13 deletions
@@ -2028,7 +2028,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_currentDrawFrontendProgram = nullptr;
g_currentDrawBackendProgram = nullptr;
if (!currentProgram || !currentProgram->GetLinkStatus()) {
// ... || !GetSpirvStatus(): see BackendProgramObjectImpl::SyncToBackend - a
// program whose SPIR-V never arrived is linked but not drawable.
if (!currentProgram || !currentProgram->GetLinkStatus() || !currentProgram->GetSpirvStatus()) {
g_GLESFuncs.glUseProgram(0);
g_lastUsedBackendProgramId = 0;
return;
@@ -2589,7 +2591,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
static void BindCurrentProgramWithResources(
const SharedPtr<MG_State::GLState::ProgramObject>& currentProgram,
const TextureImpl::DrawTextureSyncKeys& keys) {
if (currentProgram && currentProgram->GetLinkStatus()) {
if (currentProgram && currentProgram->GetLinkStatus() && currentProgram->GetSpirvStatus()) {
#ifdef TRACY_ENABLE
ZoneScopedNC("BindCurrentProgram", TRACY_ZONECOLOR_BACKEND);
#endif
@@ -2859,7 +2861,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// is pinned for the duration. Prefers the per-draw stash those preparations wrote.
static PrgramImpl::BackendProgramObjectImpl* GetCurrentBackendProgram() {
const auto& currentProgram = MG_State::pGLContext->GetProgramForDraw();
if (!currentProgram || !currentProgram->GetLinkStatus()) {
if (!currentProgram || !currentProgram->GetLinkStatus() || !currentProgram->GetSpirvStatus()) {
return nullptr;
}
if (PrgramImpl::g_currentDrawFrontendProgram == currentProgram.get()) {
@@ -3017,7 +3019,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
TextureImpl::SyncImageTextureBindings();
PrgramImpl::SyncCurrentProgram(currentProgram);
if (!currentProgram || !currentProgram->GetLinkStatus()) {
if (!currentProgram || !currentProgram->GetLinkStatus() || !currentProgram->GetSpirvStatus()) {
g_GLESFuncs.glUseProgram(0);
PrgramImpl::g_lastUsedBackendProgramId = 0;
return;
+8 -2
View File
@@ -4156,8 +4156,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
return;
}
if (!stateProgramObject->GetLinkStatus()) {
MGLOG_E("Program object is not linked, skipping backend sync. State program ID: %u",
// GetSpirvStatus() as well as GetLinkStatus(): a program whose phase-B job was
// cancelled (teardown) or whose optimizer run failed is fully linked and fully
// queryable, but has no SPIR-V to build a driver program out of. GL cannot retract
// a LINK_STATUS it already reported true, so "linked but not drawable" is the
// answer, and this is where the ES backend expresses it.
if (!stateProgramObject->GetLinkStatus() || !stateProgramObject->GetSpirvStatus()) {
MGLOG_E("Program object is not linked or has no generated SPIR-V, skipping backend sync. State "
"program ID: %u",
stateProgramObject->GetExternalIndex());
return;
}