mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Perf] (MG_State): drop the parsed ASTs as soon as the SPIR-V job has generated its modules
This commit is contained in:
@@ -90,6 +90,14 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
// the TShader's own intermediate rather than a copy. These used to die when
|
// the TShader's own intermediate rather than a copy. These used to die when
|
||||||
// RunBody() returned, which was safe only because nothing called getIntermediate()
|
// RunBody() returned, which was safe only because nothing called getIntermediate()
|
||||||
// afterwards. GlslangToSpv does exactly that, so phase B has to own them.
|
// afterwards. GlslangToSpv does exactly that, so phase B has to own them.
|
||||||
|
//
|
||||||
|
// MEMORY NOTE: this is the one thing the split makes live LONGER than it used to -
|
||||||
|
// a glslang arena per stage, megabytes for a shaderpack, now alive from the end of
|
||||||
|
// phase A until phase B has generated its SPIR-V instead of dying with the link
|
||||||
|
// body. Phase B clears this vector as soon as GlslangToSpv returns, but a deep
|
||||||
|
// phase-B backlog still holds one arena per queued program. If peak RSS ever
|
||||||
|
// becomes the binding constraint on a pack load, THIS is the field to attack (by
|
||||||
|
// bounding the backlog, or by moving GlslangToSpv back into phase A).
|
||||||
Vector<SharedPtr<glslang::TShader>> shaders;
|
Vector<SharedPtr<glslang::TShader>> shaders;
|
||||||
// GL enum per entry of `in.shaders`, in the same order (GetSpirvBinaryFromProgram
|
// GL enum per entry of `in.shaders`, in the same order (GetSpirvBinaryFromProgram
|
||||||
// walks it to pick the intermediates).
|
// walks it to pick the intermediates).
|
||||||
|
|||||||
@@ -90,7 +90,11 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
} const phaseAReleaser{m_phaseA};
|
} const phaseAReleaser{m_phaseA};
|
||||||
|
|
||||||
if (!m_phaseA) return;
|
if (!m_phaseA) return;
|
||||||
const ProgramLinkTask::SpirvHandoff& handoff = m_phaseA->spirvHandoff;
|
// Non-const: the TShaders are dropped below, the moment GlslangToSpv is finished with
|
||||||
|
// them. This is safe by ownership rather than by locking - phase A is terminal and
|
||||||
|
// therefore immutable to everyone else, the GL-thread join touches only `artifacts`
|
||||||
|
// and `diagnostics`, and this node is the sole reader of the handoff.
|
||||||
|
ProgramLinkTask::SpirvHandoff& handoff = m_phaseA->spirvHandoff;
|
||||||
const Uint externalIndex = m_phaseA->in.externalIndex;
|
const Uint externalIndex = m_phaseA->in.externalIndex;
|
||||||
if (!handoff.ready || !handoff.reflection.program) {
|
if (!handoff.ready || !handoff.reflection.program) {
|
||||||
// Phase A did not reach its tail (it failed the link, or was cancelled mid-body).
|
// Phase A did not reach its tail (it failed the link, or was cancelled mid-body).
|
||||||
@@ -105,6 +109,12 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
|
|
||||||
MGLOG_D("ProgramObject %u: Starting SPIR-V generation", externalIndex);
|
MGLOG_D("ProgramObject %u: Starting SPIR-V generation", externalIndex);
|
||||||
GenerateSpirv(handoff, externalIndex);
|
GenerateSpirv(handoff, externalIndex);
|
||||||
|
// GlslangToSpv was the only consumer of the parsed ASTs, and they are by far the
|
||||||
|
// largest thing this node keeps alive (one glslang arena per stage, megabytes for a
|
||||||
|
// shaderpack). Everything after this point works on the SPIR-V and on the TProgram's
|
||||||
|
// own self-contained reflection pool, so drop them here rather than at the end of the
|
||||||
|
// body - spirv-opt plus routing is ~87% of this node's runtime.
|
||||||
|
handoff.shaders.clear();
|
||||||
|
|
||||||
MGLOG_D("ProgramObject %u: Building global-UBO routing tables", externalIndex);
|
MGLOG_D("ProgramObject %u: Building global-UBO routing tables", externalIndex);
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user