From a5ea9c63f72c0ecf5937a8b33a2e18160c79814a Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Tue, 13 Aug 2013 00:58:49 +0000 Subject: [PATCH] Dynamically allocate symbol table containers, so timing of clean up can be more easily controlled WRT memory pool cleanup. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22681 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- BuildLinux.sh | 5 ++- glslang/MachineIndependent/ShaderLang.cpp | 55 ++++++++++++----------- glslang/MachineIndependent/SymbolTable.h | 38 ++++++++-------- 3 files changed, 51 insertions(+), 47 deletions(-) diff --git a/BuildLinux.sh b/BuildLinux.sh index fb7644380..ac85720d3 100755 --- a/BuildLinux.sh +++ b/BuildLinux.sh @@ -1,12 +1,13 @@ #! /bin/bash -rm -f StandAlone/StandAlone +rm -f StandAlone/glsangValidator +rm -f glslang/MachineIndependent/lib/libglslang.so # build the StandAlone app and all it's dependencies make -C StandAlone # so we can find the shared library -LD_LIBRARY_PATH=`pwd`/glslang/MachineIndependent/lib:${LD_LIBRARY_PATH} +LD_LIBRARY_PATH=`pwd`/glslang/MachineIndependent/lib export LD_LIBRARY_PATH # run using test data diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 7bdae0968..0d1c9ccfe 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -109,8 +109,6 @@ bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profil parseContext.scanContext = &scanContext; parseContext.ppContext = &ppContext; - assert(symbolTable.isEmpty() || symbolTable.atSharedBuiltInLevel()); - // // Parse the built-ins. This should only happen once per // language symbol table when no 'resources' are passed in. @@ -140,29 +138,29 @@ bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profil // // To call for per-stage initialization, with the common table already complete. // -void InitializeSymbolTable(TBuiltIns& builtIns, int version, EProfile profile, EShLanguage language, TInfoSink& infoSink, TSymbolTable* commonTable, TSymbolTable* symbolTables) +void InitializeSymbolTable(TBuiltIns& builtIns, int version, EProfile profile, EShLanguage language, TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables) { int commonIndex = EPcGeneral; if (profile == EEsProfile && language == EShLangFragment) commonIndex = EPcFragment; - symbolTables[language].adoptLevels(commonTable[commonIndex]); - InitializeSymbolTable(builtIns.getStageString(language), version, profile, language, infoSink, symbolTables[language]); - IdentifyBuiltIns(version, profile, language, symbolTables[language]); + (*symbolTables[language]).adoptLevels(*commonTable[commonIndex]); + InitializeSymbolTable(builtIns.getStageString(language), version, profile, language, infoSink, *symbolTables[language]); + IdentifyBuiltIns(version, profile, language, *symbolTables[language]); if (profile == EEsProfile) - symbolTables[language].setNoBuiltInRedeclarations(); + (*symbolTables[language]).setNoBuiltInRedeclarations(); } -bool GenerateBuiltInSymbolTable(TInfoSink& infoSink, TSymbolTable* commonTable, TSymbolTable* symbolTables, int version, EProfile profile) +bool GenerateBuiltInSymbolTable(TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables, int version, EProfile profile) { TBuiltIns builtIns; builtIns.initialize(version, profile); // do the common table - InitializeSymbolTable(builtIns.getCommonString(), version, profile, EShLangVertex, infoSink, commonTable[EPcGeneral]); + InitializeSymbolTable(builtIns.getCommonString(), version, profile, EShLangVertex, infoSink, *commonTable[EPcGeneral]); if (profile == EEsProfile) - InitializeSymbolTable(builtIns.getCommonString(), version, profile, EShLangFragment, infoSink, commonTable[EPcFragment]); + InitializeSymbolTable(builtIns.getCommonString(), version, profile, EShLangFragment, infoSink, *commonTable[EPcFragment]); // do the per-stage tables InitializeSymbolTable(builtIns, version, profile, EShLangVertex, infoSink, commonTable, symbolTables); @@ -222,9 +220,15 @@ void SetupBuiltinSymbolTable(int version, EProfile profile) TPoolAllocator* builtInPoolAllocator = new TPoolAllocator(); SetThreadPoolAllocator(*builtInPoolAllocator); + // Dynamically allocate the symbol tables so we can control when they are deallocated WRT the pool. + TSymbolTable* commonTable[EPcCount]; + TSymbolTable* stageTables[EShLangCount]; + for (int precClass = 0; precClass < EPcCount; ++precClass) + commonTable[precClass] = new TSymbolTable; + for (int stage = 0; stage < EShLangCount; ++stage) + stageTables[stage] = new TSymbolTable; + // Generate the local symbol tables using the new pool - TSymbolTable commonTable[2]; - TSymbolTable stageTables[EShLangCount]; GenerateBuiltInSymbolTable(infoSink, commonTable, stageTables, version, profile); // Switch to the process-global pool @@ -232,23 +236,23 @@ void SetupBuiltinSymbolTable(int version, EProfile profile) // Copy the local symbol tables from the new pool to the global tables using the process-global pool for (int precClass = 0; precClass < EPcCount; ++precClass) { - if (! commonTable[precClass].isEmpty()) { + if (! commonTable[precClass]->isEmpty()) { CommonSymbolTable[versionIndex][profile][precClass] = new TSymbolTable; - CommonSymbolTable[versionIndex][profile][precClass]->copyTable(commonTable[precClass]); + CommonSymbolTable[versionIndex][profile][precClass]->copyTable(*commonTable[precClass]); } } for (int stage = 0; stage < EShLangCount; ++stage) { - if (! stageTables[stage].isEmpty()) { + if (! stageTables[stage]->isEmpty()) { SharedSymbolTables[versionIndex][profile][stage] = new TSymbolTable; - SharedSymbolTables[versionIndex][profile][stage]->copyTable(stageTables[stage]); + SharedSymbolTables[versionIndex][profile][stage]->copyTable(*stageTables[stage]); } } - // Explicitly clean up the local tables before deleting the pool they used and before releasing the lock. + // Clean up the local tables before deleting the pool they used. for (int precClass = 0; precClass < EPcCount; ++precClass) - commonTable[precClass].~TSymbolTable(); + delete commonTable[precClass]; for (int stage = 0; stage < EShLangCount; ++stage) - stageTables[stage].~TSymbolTable(); + delete stageTables[stage]; delete builtInPoolAllocator; SetThreadPoolAllocator(savedGPA); @@ -458,7 +462,10 @@ int ShCompile( TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)] [profile] [compiler->getLanguage()]; - TSymbolTable symbolTable; + + // Dynamically allocate the symbol table so we can control when it is deallocated WRT the pool. + TSymbolTable* symbolTableMemory = new TSymbolTable; + TSymbolTable& symbolTable = *symbolTableMemory; if (cachedTable) symbolTable.adoptLevels(*cachedTable); @@ -531,12 +538,8 @@ int ShCompile( intermediate.remove(parseContext.treeRoot); - // - // Ensure symbol table is returned to the built-in level, - // throwing away all but the built-ins. - // - while (! symbolTable.atSharedBuiltInLevel()) - symbolTable.pop(0); + // Clean up the symbol table before deallocating the pool memory it used. + delete symbolTableMemory; // // Throw away all the temporary memory used by the compilation process. diff --git a/glslang/MachineIndependent/SymbolTable.h b/glslang/MachineIndependent/SymbolTable.h index 4bfae1851..d80721394 100644 --- a/glslang/MachineIndependent/SymbolTable.h +++ b/glslang/MachineIndependent/SymbolTable.h @@ -373,19 +373,13 @@ public: } ~TSymbolTable() { + // this can be called explicitly; safest to code it so it can be called multiple times + // don't deallocate levels passed in from elsewhere while (table.size() > adoptedLevels) pop(0); } - // - // While level adopting is generic, the methods below enact a the following - // convention for levels: - // 0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables - // 1: per-stage built-ins, shared across all compiles, but a different copy per stage - // 2: built-ins specific to a compile, like resources that are context-dependent - // 3: user-shader globals - // void adoptLevels(TSymbolTable& symTable) { for (unsigned int level = 0; level < symTable.table.size(); ++level) { @@ -395,11 +389,21 @@ public: uniqueId = symTable.uniqueId; noBuiltInRedeclarations = symTable.noBuiltInRedeclarations; } + + // + // While level adopting is generic, the methods below enact a the following + // convention for levels: + // 0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables + // 1: per-stage built-ins, shared across all compiles, but a different copy per stage + // 2: built-ins specific to a compile, like resources that are context-dependent + // 3: user-shader globals + // +protected: + static const int globalLevel = 3; +public: bool isEmpty() { return table.size() == 0; } - bool atBuiltInLevel() { return atSharedBuiltInLevel() || atDynamicBuiltInLevel(); } - bool atSharedBuiltInLevel() { return table.size() <= 2; } - bool atDynamicBuiltInLevel() { return table.size() == 3; } - bool atGlobalLevel() { return table.size() <= 4; } + bool atBuiltInLevel() { return table.size() <= globalLevel; } // exclude user globals + bool atGlobalLevel() { return table.size() <= globalLevel + 1; } // include user globals void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; } @@ -411,7 +415,7 @@ public: void pop(TPrecisionQualifier *p) { table[currentLevel()]->getPreviousDefaultPrecisions(p); - delete table[currentLevel()]; + delete table.back(); table.pop_back(); } @@ -453,12 +457,8 @@ public: void relateToOperator(const char* name, TOperator op) { - for (unsigned int level = 0; level < table.size(); ++level) { - if (atSharedBuiltInLevel()) - table[level]->relateToOperator(name, op); - else - break; - } + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->relateToOperator(name, op); } int getMaxSymbolId() { return uniqueId; } -- GitLab