mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 05:38:31 +09:00
[Fix] (MG_State, MG_Impl): defer deletion of the program in use
glDeleteProgram on the current program now only flags it: the name (and every glGetProgram* query) stays valid until the program stops being current, at which point UseProgram frees the slot and releases orphaned attached shaders. Previously the name died immediately, so a second glDeleteProgram - as issued by common CTS utility teardown - recorded GL_INVALID_VALUE that poisoned the next test iteration's build (KHR-GL33.clip_distance.functional now passes its build phase). glIsProgram/glIsShader piggyback on the same rule: a flagged name is still a program/shader while it stays GL-visible, which resolves the long-standing FIXMEs there.
This commit is contained in:
@@ -844,19 +844,13 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLboolean IsProgram_State(GLuint program) {
|
GLboolean IsProgram_State(GLuint program) {
|
||||||
/* FIXME: Handle situations that:
|
// Deletion-flagged names stay valid while the object is still GL-visible (program in
|
||||||
* A program object marked for deletion with glDeleteProgram but still in use as part of current
|
// use, shader attached), so name validity is exactly the Is* answer.
|
||||||
* rendering state is still considered a program object and glIsProgram will return GL_TRUE.
|
|
||||||
*/
|
|
||||||
if (program == 0) return GL_FALSE;
|
if (program == 0) return GL_FALSE;
|
||||||
return MG_State::pGLContext->ValidateProgramName(program) ? GL_TRUE : GL_FALSE;
|
return MG_State::pGLContext->ValidateProgramName(program) ? GL_TRUE : GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLboolean IsShader_State(GLuint shader) {
|
GLboolean IsShader_State(GLuint shader) {
|
||||||
/* FIXME: Handle situations that:
|
|
||||||
* A shader object marked for deletion with glDeleteShader but still attached to a program object is still
|
|
||||||
* considered a shader object and glIsShader will return GL_TRUE.
|
|
||||||
*/
|
|
||||||
if (shader == 0) return GL_FALSE;
|
if (shader == 0) return GL_FALSE;
|
||||||
return MG_State::pGLContext->ValidateShaderName(shader) ? GL_TRUE : GL_FALSE;
|
return MG_State::pGLContext->ValidateShaderName(shader) ? GL_TRUE : GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,19 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
if (!CheckIndexAvail(program, m_programObjects)) return; // FIXME: add error reporting here
|
if (!CheckIndexAvail(program, m_programObjects)) return; // FIXME: add error reporting here
|
||||||
auto& programObject = m_programObjects[program];
|
auto& programObject = m_programObjects[program];
|
||||||
if (programObject != nullptr) {
|
if (programObject != nullptr) {
|
||||||
|
programObject->MarkAsDeleted();
|
||||||
|
// A program in use is only FLAGGED: its name (and every program query) stays
|
||||||
|
// valid until it stops being current, at which point UseProgram finishes the job.
|
||||||
|
if (programObject == m_currentProgram) return;
|
||||||
|
DestroyProgramSlot(program);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProgramState::DestroyProgramSlot(const Uint program) {
|
||||||
|
auto& programObject = m_programObjects[program];
|
||||||
// Snapshot the attachments: deleting the program is a detach point for shaders
|
// Snapshot the attachments: deleting the program is a detach point for shaders
|
||||||
// that were flagged with glDeleteShader while still attached.
|
// that were flagged with glDeleteShader while still attached.
|
||||||
const Vector<SharedPtr<ShaderObject>> attachedShaders = programObject->GetAttachedShaders();
|
const Vector<SharedPtr<ShaderObject>> attachedShaders = programObject->GetAttachedShaders();
|
||||||
programObject->MarkAsDeleted();
|
|
||||||
programObject.reset();
|
programObject.reset();
|
||||||
m_programIndexGenerator.Delete(program);
|
m_programIndexGenerator.Delete(program);
|
||||||
for (const auto& shader : attachedShaders) {
|
for (const auto& shader : attachedShaders) {
|
||||||
@@ -42,19 +51,30 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Bool ProgramState::ValidateProgramObject(const Uint program) const {
|
Bool ProgramState::ValidateProgramObject(const Uint program) const {
|
||||||
return CheckIndexAvail(program, m_programObjects) && m_programObjects[program] != nullptr;
|
return CheckIndexAvail(program, m_programObjects) && m_programObjects[program] != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgramState::UseProgram(Uint program) {
|
void ProgramState::UseProgram(Uint program) {
|
||||||
|
const SharedPtr<ProgramObject> previous = m_currentProgram;
|
||||||
|
|
||||||
if (program == 0) m_currentProgram.reset();
|
if (program == 0) m_currentProgram.reset();
|
||||||
|
|
||||||
if (!CheckIndexAvail(program, m_programObjects)) return;
|
if (CheckIndexAvail(program, m_programObjects)) {
|
||||||
m_currentProgram = m_programObjects[program];
|
m_currentProgram = m_programObjects[program];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A deletion flagged while the program was current takes effect the moment it
|
||||||
|
// stops being current.
|
||||||
|
if (previous != nullptr && previous != m_currentProgram && previous->GetDeleteStatus()) {
|
||||||
|
const Uint previousName = previous->GetExternalIndex();
|
||||||
|
if (CheckIndexAvail(previousName, m_programObjects) && m_programObjects[previousName] == previous) {
|
||||||
|
DestroyProgramSlot(previousName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Uint ProgramState::CreateShader(ShaderStage stage) {
|
Uint ProgramState::CreateShader(ShaderStage stage) {
|
||||||
Uint shaderId = 0;
|
Uint shaderId = 0;
|
||||||
m_shaderIndexGenerator.Generate(1, &shaderId);
|
m_shaderIndexGenerator.Generate(1, &shaderId);
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Bool ShaderHasGLVisibleAttachment(const SharedPtr<ShaderObject>& shaderObject) const;
|
Bool ShaderHasGLVisibleAttachment(const SharedPtr<ShaderObject>& shaderObject) const;
|
||||||
|
// Frees the name slot and releases orphaned attached shaders; the immediate half
|
||||||
|
// of glDeleteProgram (deferred while the program is current).
|
||||||
|
void DestroyProgramSlot(Uint program);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static Bool CheckIndexAvail(const SizeT idx, const Vector<T>& vec) {
|
static Bool CheckIndexAvail(const SizeT idx, const Vector<T>& vec) {
|
||||||
|
|||||||
Reference in New Issue
Block a user