mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 21:28:32 +09:00
[Feat, Test] (MG_Impl, MG_State, MG_Util): opt-in MOBILEGL_ASYNC_OPTIMISTIC_SHADER_STATUS - shader compile status/log answer without joining, latched per compile
This commit is contained in:
@@ -408,6 +408,13 @@ namespace MobileGL::MG_State::GLState {
|
||||
MG_Util::ConvertGLEnumToString(shaderType).c_str());
|
||||
|
||||
if (!compiled.compileStatus) {
|
||||
// The compile log LEADS the quoted source, and that order is load-bearing:
|
||||
// under MOBILEGL_ASYNC_OPTIMISTIC_SHADER_STATUS this string is the
|
||||
// application's ONLY compile diagnostic (the per-shader queries answered
|
||||
// optimistically), and applications read it through a bounded buffer -
|
||||
// Iris uses 32768 bytes - so the actionable text must come before the
|
||||
// potentially-100KB source dump. The full source stays: the device log is
|
||||
// where a failing pack gets debugged from.
|
||||
artifacts.infoLog =
|
||||
std::format("Linking a {} with compilation error, linking will now terminate. Shader error "
|
||||
"log:\n{}\nShader src:\n{}",
|
||||
|
||||
@@ -88,12 +88,19 @@ namespace MobileGL::MG_State::GLState {
|
||||
// another object, THIS object has not pulled its result yet. (An adopted node may
|
||||
// already be terminal - the join then only replays what is left of its diagnostics.)
|
||||
m_compileJoined = false;
|
||||
// A new compile is a new story: whatever the optimistic getters promised about the
|
||||
// previous node does not carry over.
|
||||
m_optimisticAnswerLatched = false;
|
||||
}
|
||||
|
||||
void ShaderObject::DropCompileNode() const {
|
||||
if (!m_compiled) return;
|
||||
m_compiled->ReleaseAdopter();
|
||||
m_compiled.reset();
|
||||
// No node means IsCompileComplete() is trivially true and the truthful answers are
|
||||
// "not compiled"; a stale latch would keep reporting a compile that no longer
|
||||
// exists as GL_TRUE.
|
||||
m_optimisticAnswerLatched = false;
|
||||
}
|
||||
|
||||
void ShaderObject::InvalidateCompiledState() {
|
||||
|
||||
@@ -116,8 +116,10 @@ namespace MobileGL {
|
||||
Bool GetDeleteStatus() const { return m_deleteStatus; }
|
||||
|
||||
// Blocks until a pending compile has published its artifacts. Public for the
|
||||
// sites that must join without reading anything - ProgramObject::Link's
|
||||
// prologue, which needs every attached shader settled before it runs.
|
||||
// sites that must join without reading anything - ProgramState::
|
||||
// JoinAllPendingWork, the glMaxShaderCompilerThreadsKHR(0) path that settles
|
||||
// every outstanding job. glLinkProgram deliberately does NOT come through
|
||||
// here: its prologue takes the nodes unjoined via CompiledNodeForLink().
|
||||
void JoinCompile() const { EnsureCompileJoined(); }
|
||||
|
||||
// True while this object holds the outcome (success OR failure) of a Compile()
|
||||
@@ -141,6 +143,23 @@ namespace MobileGL {
|
||||
// outstanding to wait for.
|
||||
Bool IsCompileComplete() const { return m_compiled == nullptr || m_compiled->IsTerminal(); }
|
||||
|
||||
// MOBILEGL_ASYNC_OPTIMISTIC_SHADER_STATUS's one-story-per-compile memory. The
|
||||
// three optimistic getter sites in GL_Program ask THIS instead of a raw
|
||||
// IsCompileComplete() peek, and the difference is the latch: without it, a job
|
||||
// that settles between two adjacent queries hands the application a torn pair -
|
||||
// an empty info log from the optimistic read, then the real GL_FALSE from the
|
||||
// truthful one - and an application that aborts on that status never reaches
|
||||
// the link join that quotes the real log. So the first optimistic answer
|
||||
// latches: until the next AdoptCompileNode/DropCompileNode this object keeps
|
||||
// answering optimistically even after the job settles, and a real failure
|
||||
// surfaces exactly once, at the link. Returns whether the caller should answer
|
||||
// optimistically; the caller has already checked the quirk is active.
|
||||
Bool TakeOptimisticCompileAnswer() const {
|
||||
if (!m_optimisticAnswerLatched && IsCompileComplete()) return false;
|
||||
m_optimisticAnswerLatched = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// ---- The one and only join gate for compile output (P1 invariant I5) ----
|
||||
// The fast path - no job, or a job whose result this object has already pulled -
|
||||
@@ -231,6 +250,10 @@ namespace MobileGL {
|
||||
// Exactly-once latch for the pull above. Armed with every new job node, set by
|
||||
// the one join that consumes it.
|
||||
mutable Bool m_compileJoined = false;
|
||||
// TakeOptimisticCompileAnswer's memory: this object has answered a compile
|
||||
// query optimistically for the current node. Cleared wherever the node
|
||||
// changes hands (AdoptCompileNode) or goes away (DropCompileNode).
|
||||
mutable Bool m_optimisticAnswerLatched = false;
|
||||
};
|
||||
} // namespace MG_State::GLState
|
||||
} // namespace MobileGL
|
||||
|
||||
Reference in New Issue
Block a user