Commit 978ddc59 by Nicolas Capens Committed by Nicolas Capens

Fixed memory leak associated with TLS.

We used to allocate thread-local memory on each compile. If the compile did not happen on the same thread as ShInitialize, we leaked the thread-local memory. It turns out that there is no need to allocate any thread-local memory. This patch cleans up all the unnecessary junk around TLS. BUG=chromium:181691 Change-Id: I4b67ab23dc856d93424ae51ebf8aaf8966b732e4 Reviewed-on: https://swiftshader-review.googlesource.com/1361Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent ff7f1003
...@@ -36,14 +36,14 @@ inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) { ...@@ -36,14 +36,14 @@ inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) {
// //
// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. // Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
// //
#define POOL_ALLOCATOR_NEW_DELETE(A) \ #define POOL_ALLOCATOR_NEW_DELETE() \
void* operator new(size_t s) { return (A).allocate(s); } \ void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
void* operator new(size_t, void *_Where) { return (_Where); } \ void* operator new(size_t, void *_Where) { return (_Where); } \
void operator delete(void*) { } \ void operator delete(void*) { } \
void operator delete(void *, void *) { } \ void operator delete(void *, void *) { } \
void* operator new[](size_t s) { return (A).allocate(s); } \ void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
void* operator new[](size_t, void *_Where) { return (_Where); } \ void* operator new[](size_t, void *_Where) { return (_Where); } \
void operator delete[](void*) { } \ void operator delete[](void*) { } \
void operator delete[](void *, void *) { } void operator delete[](void *, void *) { }
// //
...@@ -54,7 +54,7 @@ typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TStri ...@@ -54,7 +54,7 @@ typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TStri
typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream; typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
inline TString* NewPoolTString(const char* s) inline TString* NewPoolTString(const char* s)
{ {
void* memory = GlobalPoolAllocator.allocate(sizeof(TString)); void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString));
return new(memory) TString(s); return new(memory) TString(s);
} }
......
...@@ -92,7 +92,7 @@ bool TCompiler::compile(const char* const shaderStrings[], ...@@ -92,7 +92,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
TParseContext parseContext(symbolTable, extensionBehavior, intermediate, TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
shaderType, shaderSpec, compileOptions, true, shaderType, shaderSpec, compileOptions, true,
sourcePath, infoSink); sourcePath, infoSink);
GlobalParseContext = &parseContext; SetGlobalParseContext(&parseContext);
// We preserve symbols at the built-in level from compile-to-compile. // We preserve symbols at the built-in level from compile-to-compile.
// Start pushing the user-defined symbols at global level. // Start pushing the user-defined symbols at global level.
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
class ConstantUnion { class ConstantUnion {
public: public:
POOL_ALLOCATOR_NEW_DELETE();
ConstantUnion() ConstantUnion()
{ {
iConst = 0; iConst = 0;
......
...@@ -10,25 +10,8 @@ ...@@ -10,25 +10,8 @@
#include "compiler/InitializeParseContext.h" #include "compiler/InitializeParseContext.h"
#include "compiler/osinclude.h" #include "compiler/osinclude.h"
OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
bool InitProcess() bool InitProcess()
{ {
if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
//
// Function is re-entrant.
//
return true;
}
ThreadInitializeIndex = OS_AllocTLSIndex();
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
return false;
}
if (!InitializePoolIndex()) { if (!InitializePoolIndex()) {
assert(0 && "InitProcess(): Failed to initalize global pool"); assert(0 && "InitProcess(): Failed to initalize global pool");
return false; return false;
...@@ -39,77 +22,11 @@ bool InitProcess() ...@@ -39,77 +22,11 @@ bool InitProcess()
return false; return false;
} }
return InitThread();
}
bool DetachProcess()
{
bool success = true;
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
return true;
success = DetachThread();
if (!FreeParseContextIndex())
success = false;
FreePoolIndex();
OS_FreeTLSIndex(ThreadInitializeIndex);
ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
return success;
}
bool InitThread()
{
//
// This function is re-entrant
//
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitThread(): Process hasn't been initalised.");
return false;
}
if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
return true;
InitializeGlobalPools();
if (!InitializeGlobalParseContext())
return false;
if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
assert(0 && "InitThread(): Unable to set init flag.");
return false;
}
return true; return true;
} }
bool DetachThread() void DetachProcess()
{ {
bool success = true; FreeParseContextIndex();
FreePoolIndex();
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
return true;
//
// Function is re-entrant and this thread may not have been initalised.
//
if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
assert(0 && "DetachThread(): Unable to clear init flag.");
success = false;
}
if (!FreeParseContext())
success = false;
FreeGlobalPools();
}
return success;
} }
...@@ -7,10 +7,7 @@ ...@@ -7,10 +7,7 @@
#define __INITIALIZEDLL_H #define __INITIALIZEDLL_H
bool InitProcess(); bool InitProcess();
bool DetachProcess(); void DetachProcess();
bool InitThread();
bool DetachThread();
#endif // __INITIALIZEDLL_H #endif // __INITIALIZEDLL_H
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
#ifndef __INITIALIZE_GLOBALS_INCLUDED_ #ifndef __INITIALIZE_GLOBALS_INCLUDED_
#define __INITIALIZE_GLOBALS_INCLUDED_ #define __INITIALIZE_GLOBALS_INCLUDED_
void InitializeGlobalPools();
void FreeGlobalPools();
bool InitializePoolIndex(); bool InitializePoolIndex();
void FreePoolIndex(); void FreePoolIndex();
......
...@@ -12,85 +12,29 @@ OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX; ...@@ -12,85 +12,29 @@ OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
bool InitializeParseContextIndex() bool InitializeParseContextIndex()
{ {
if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) { assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX);
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
return false;
}
//
// Allocate a TLS index.
//
GlobalParseContextIndex = OS_AllocTLSIndex(); GlobalParseContextIndex = OS_AllocTLSIndex();
return GlobalParseContextIndex != OS_INVALID_TLS_INDEX;
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
return false;
}
return true;
} }
bool FreeParseContextIndex() void FreeParseContextIndex()
{ {
OS_TLSIndex tlsiIndex = GlobalParseContextIndex; assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "FreeParseContextIndex(): Parse Context index not initalized");
return false;
}
OS_FreeTLSIndex(GlobalParseContextIndex);
GlobalParseContextIndex = OS_INVALID_TLS_INDEX; GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
return OS_FreeTLSIndex(tlsiIndex);
}
bool InitializeGlobalParseContext()
{
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized");
return false;
}
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
if (lpParseContext != 0) {
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
return false;
}
TThreadParseContext *lpThreadData = new TThreadParseContext();
if (lpThreadData == 0) {
assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
return false;
}
lpThreadData->lpGlobalParseContext = 0;
OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
return true;
} }
bool FreeParseContext() void SetGlobalParseContext(TParseContext* context)
{ {
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
assert(0 && "FreeParseContext(): Parse Context index not initalized"); OS_SetTLSValue(GlobalParseContextIndex, context);
return false;
}
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
if (lpParseContext)
delete lpParseContext;
return true;
} }
TParseContextPointer& GetGlobalParseContext() TParseContext* GetGlobalParseContext()
{ {
// assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
// Minimal error checking for speed return static_cast<TParseContext*>(OS_GetTLSValue(GlobalParseContextIndex));
//
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
return lpParseContext->lpGlobalParseContext;
} }
...@@ -8,19 +8,10 @@ ...@@ -8,19 +8,10 @@
#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_ #define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
bool InitializeParseContextIndex(); bool InitializeParseContextIndex();
bool FreeParseContextIndex(); void FreeParseContextIndex();
bool InitializeGlobalParseContext();
bool FreeParseContext();
struct TParseContext; struct TParseContext;
typedef TParseContext* TParseContextPointer; extern void SetGlobalParseContext(TParseContext* context);
extern TParseContextPointer& GetGlobalParseContext(); extern TParseContext* GetGlobalParseContext();
#define GlobalParseContext GetGlobalParseContext()
typedef struct TThreadParseContextRec
{
TParseContext *lpGlobalParseContext;
} TThreadParseContext;
#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_ #endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
...@@ -16,55 +16,32 @@ ...@@ -16,55 +16,32 @@
OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;
void InitializeGlobalPools()
{
TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
if (globalPools)
return;
TThreadGlobalPools* threadData = new TThreadGlobalPools();
threadData->globalPoolAllocator = 0;
OS_SetTLSValue(PoolIndex, threadData);
}
void FreeGlobalPools()
{
// Release the allocated memory for this thread.
TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
if (!globalPools)
return;
delete globalPools;
}
bool InitializePoolIndex() bool InitializePoolIndex()
{ {
// Allocate a TLS index. assert(PoolIndex == OS_INVALID_TLS_INDEX);
if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
return false;
return true; PoolIndex = OS_AllocTLSIndex();
return PoolIndex != OS_INVALID_TLS_INDEX;
} }
void FreePoolIndex() void FreePoolIndex()
{ {
// Release the TLS index. assert(PoolIndex != OS_INVALID_TLS_INDEX);
OS_FreeTLSIndex(PoolIndex); OS_FreeTLSIndex(PoolIndex);
PoolIndex = OS_INVALID_TLS_INDEX;
} }
TPoolAllocator& GetGlobalPoolAllocator() TPoolAllocator* GetGlobalPoolAllocator()
{ {
TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); assert(PoolIndex != OS_INVALID_TLS_INDEX);
return static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex));
return *threadData->globalPoolAllocator;
} }
void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
{ {
TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); assert(PoolIndex != OS_INVALID_TLS_INDEX);
OS_SetTLSValue(PoolIndex, poolAllocator);
threadData->globalPoolAllocator = poolAllocator;
} }
// //
......
...@@ -219,14 +219,8 @@ private: ...@@ -219,14 +219,8 @@ private:
// different times. But a simple use is to have a global pop // different times. But a simple use is to have a global pop
// with everyone using the same global allocator. // with everyone using the same global allocator.
// //
extern TPoolAllocator& GetGlobalPoolAllocator(); extern TPoolAllocator* GetGlobalPoolAllocator();
extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator); extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
#define GlobalPoolAllocator GetGlobalPoolAllocator()
struct TThreadGlobalPools
{
TPoolAllocator* globalPoolAllocator;
};
// //
// This STL compatible allocator is intended to be used as the allocator // This STL compatible allocator is intended to be used as the allocator
...@@ -253,7 +247,7 @@ public: ...@@ -253,7 +247,7 @@ public:
pointer address(reference x) const { return &x; } pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; }
pool_allocator() : allocator(&GlobalPoolAllocator) { } pool_allocator() : allocator(GetGlobalPoolAllocator()) { }
pool_allocator(TPoolAllocator& a) : allocator(&a) { } pool_allocator(TPoolAllocator& a) : allocator(&a) { }
pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { } pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
......
...@@ -23,10 +23,7 @@ ...@@ -23,10 +23,7 @@
// //
int ShInitialize() int ShInitialize()
{ {
if (!InitProcess()) return InitProcess() ? 1 : 0;
return 0;
return 1;
} }
// //
...@@ -34,9 +31,7 @@ int ShInitialize() ...@@ -34,9 +31,7 @@ int ShInitialize()
// //
int ShFinalize() int ShFinalize()
{ {
if (!DetachProcess()) DetachProcess();
return 0;
return 1; return 1;
} }
...@@ -69,9 +64,6 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) ...@@ -69,9 +64,6 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
const ShBuiltInResources* resources) const ShBuiltInResources* resources)
{ {
if (!InitThread())
return 0;
TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec)); TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec));
TCompiler* compiler = base->getAsCompiler(); TCompiler* compiler = base->getAsCompiler();
if (compiler == 0) if (compiler == 0)
...@@ -110,9 +102,6 @@ int ShCompile( ...@@ -110,9 +102,6 @@ int ShCompile(
const int numStrings, const int numStrings,
int compileOptions) int compileOptions)
{ {
if (!InitThread())
return 0;
if (handle == 0) if (handle == 0)
return 0; return 0;
......
...@@ -40,9 +40,10 @@ ...@@ -40,9 +40,10 @@
// //
class TSymbol { class TSymbol {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TSymbol(const TString *n) : name(n) { } TSymbol(const TString *n) : name(n) { }
virtual ~TSymbol() { /* don't delete name, it's from the pool */ } virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
const TString& getName() const { return *name; } const TString& getName() const { return *name; }
virtual const TString& getMangledName() const { return getName(); } virtual const TString& getMangledName() const { return getName(); }
virtual bool isFunction() const { return false; } virtual bool isFunction() const { return false; }
...@@ -179,7 +180,7 @@ public: ...@@ -179,7 +180,7 @@ public:
typedef const tLevel::value_type tLevelPair; typedef const tLevel::value_type tLevelPair;
typedef std::pair<tLevel::iterator, bool> tInsertResult; typedef std::pair<tLevel::iterator, bool> tInsertResult;
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TSymbolTableLevel() { } TSymbolTableLevel() { }
~TSymbolTableLevel(); ~TSymbolTableLevel();
......
// //
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
#ifndef _TYPES_INCLUDED #ifndef _TYPES_INCLUDED
#define _TYPES_INCLUDED #define _TYPES_INCLUDED
#include "compiler/BaseTypes.h" #include "compiler/BaseTypes.h"
#include "compiler/Common.h" #include "compiler/Common.h"
#include "compiler/debug.h" #include "compiler/debug.h"
#include <algorithm> #include <algorithm>
class TType; class TType;
struct TPublicType; struct TPublicType;
// //
// Need to have association of line numbers to types in a list for building structs. // Need to have association of line numbers to types in a list for building structs.
// //
struct TTypeLine { struct TTypeLine {
TType* type; TType* type;
int line; int line;
}; };
typedef TVector<TTypeLine> TTypeList; typedef TVector<TTypeLine> TTypeList;
inline TTypeList* NewPoolTTypeList() inline TTypeList* NewPoolTTypeList()
{ {
void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList)); void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TTypeList));
return new(memory) TTypeList; return new(memory) TTypeList;
} }
// //
// Base class for things that have a type. // Base class for things that have a type.
// //
class TType class TType
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TType() {} TType() {}
TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) : TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0) maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
{ {
} }
explicit TType(const TPublicType &p); explicit TType(const TPublicType &p);
TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) : TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0) maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0)
{ {
typeName = NewPoolTString(n.c_str()); typeName = NewPoolTString(n.c_str());
} }
TBasicType getBasicType() const { return type; } TBasicType getBasicType() const { return type; }
void setBasicType(TBasicType t) { type = t; } void setBasicType(TBasicType t) { type = t; }
TPrecision getPrecision() const { return precision; } TPrecision getPrecision() const { return precision; }
void setPrecision(TPrecision p) { precision = p; } void setPrecision(TPrecision p) { precision = p; }
TQualifier getQualifier() const { return qualifier; } TQualifier getQualifier() const { return qualifier; }
void setQualifier(TQualifier q) { qualifier = q; } void setQualifier(TQualifier q) { qualifier = q; }
// One-dimensional size of single instance type // One-dimensional size of single instance type
int getNominalSize() const { return size; } int getNominalSize() const { return size; }
void setNominalSize(int s) { size = s; } void setNominalSize(int s) { size = s; }
// Full size of single instance of type // Full size of single instance of type
int getObjectSize() const int getObjectSize() const
{ {
if(isArray()) if(isArray())
{ {
return getElementSize() * std::max(getArraySize(), getMaxArraySize()); return getElementSize() * std::max(getArraySize(), getMaxArraySize());
} }
else else
{ {
return getElementSize(); return getElementSize();
} }
} }
int getElementSize() const int getElementSize() const
{ {
if(getBasicType() == EbtStruct) if(getBasicType() == EbtStruct)
{ {
return getStructSize(); return getStructSize();
} }
else if(matrix) else if(matrix)
{ {
return size * size; return size * size;
} }
else // Vector or scalar else // Vector or scalar
{ {
return size; return size;
} }
} }
int elementRegisterCount() const int elementRegisterCount() const
{ {
TTypeList *structure = getStruct(); TTypeList *structure = getStruct();
if(structure) if(structure)
{ {
int registerCount = 0; int registerCount = 0;
for(size_t i = 0; i < structure->size(); i++) for(size_t i = 0; i < structure->size(); i++)
{ {
registerCount += (*structure)[i].type->totalRegisterCount(); registerCount += (*structure)[i].type->totalRegisterCount();
} }
return registerCount; return registerCount;
} }
else if(isMatrix()) else if(isMatrix())
{ {
return getNominalSize(); return getNominalSize();
} }
else else
{ {
return 1; return 1;
} }
} }
int totalRegisterCount() const int totalRegisterCount() const
{ {
if(array) if(array)
{ {
return arraySize * elementRegisterCount(); return arraySize * elementRegisterCount();
} }
else else
{ {
return elementRegisterCount(); return elementRegisterCount();
} }
} }
bool isMatrix() const { return matrix ? true : false; } bool isMatrix() const { return matrix ? true : false; }
void setMatrix(bool m) { matrix = m; } void setMatrix(bool m) { matrix = m; }
bool isArray() const { return array ? true : false; } bool isArray() const { return array ? true : false; }
int getArraySize() const { return arraySize; } int getArraySize() const { return arraySize; }
void setArraySize(int s) { array = true; arraySize = s; } void setArraySize(int s) { array = true; arraySize = s; }
int getMaxArraySize () const { return maxArraySize; } int getMaxArraySize () const { return maxArraySize; }
void setMaxArraySize (int s) { maxArraySize = s; } void setMaxArraySize (int s) { maxArraySize = s; }
void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; } void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }
void setArrayInformationType(TType* t) { arrayInformationType = t; } void setArrayInformationType(TType* t) { arrayInformationType = t; }
TType* getArrayInformationType() const { return arrayInformationType; } TType* getArrayInformationType() const { return arrayInformationType; }
bool isVector() const { return size > 1 && !matrix; } bool isVector() const { return size > 1 && !matrix; }
bool isScalar() const { return size == 1 && !matrix && !structure; } bool isScalar() const { return size == 1 && !matrix && !structure; }
bool isRegister() const { return !matrix && !structure && !array; } // Fits in a 4-element register bool isRegister() const { return !matrix && !structure && !array; } // Fits in a 4-element register
bool isStruct() const { return structure != 0; } bool isStruct() const { return structure != 0; }
TTypeList* getStruct() const { return structure; } TTypeList* getStruct() const { return structure; }
void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); } void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }
const TString& getTypeName() const const TString& getTypeName() const
{ {
assert(typeName); assert(typeName);
return *typeName; return *typeName;
} }
void setTypeName(const TString& n) void setTypeName(const TString& n)
{ {
typeName = NewPoolTString(n.c_str()); typeName = NewPoolTString(n.c_str());
} }
bool isField() const { return fieldName != 0; } bool isField() const { return fieldName != 0; }
const TString& getFieldName() const const TString& getFieldName() const
{ {
assert(fieldName); assert(fieldName);
return *fieldName; return *fieldName;
} }
void setFieldName(const TString& n) void setFieldName(const TString& n)
{ {
fieldName = NewPoolTString(n.c_str()); fieldName = NewPoolTString(n.c_str());
} }
TString& getMangledName() { TString& getMangledName() {
if (!mangled) { if (!mangled) {
mangled = NewPoolTString(""); mangled = NewPoolTString("");
buildMangledName(*mangled); buildMangledName(*mangled);
*mangled += ';' ; *mangled += ';' ;
} }
return *mangled; return *mangled;
} }
bool sameElementType(const TType& right) const { bool sameElementType(const TType& right) const {
return type == right.type && return type == right.type &&
size == right.size && size == right.size &&
matrix == right.matrix && matrix == right.matrix &&
structure == right.structure; structure == right.structure;
} }
bool operator==(const TType& right) const { bool operator==(const TType& right) const {
return type == right.type && return type == right.type &&
size == right.size && size == right.size &&
matrix == right.matrix && matrix == right.matrix &&
array == right.array && (!array || arraySize == right.arraySize) && array == right.array && (!array || arraySize == right.arraySize) &&
structure == right.structure; structure == right.structure;
// don't check the qualifier, it's not ever what's being sought after // don't check the qualifier, it's not ever what's being sought after
} }
bool operator!=(const TType& right) const { bool operator!=(const TType& right) const {
return !operator==(right); return !operator==(right);
} }
bool operator<(const TType& right) const { bool operator<(const TType& right) const {
if (type != right.type) return type < right.type; if (type != right.type) return type < right.type;
if (size != right.size) return size < right.size; if (size != right.size) return size < right.size;
if (matrix != right.matrix) return matrix < right.matrix; if (matrix != right.matrix) return matrix < right.matrix;
if (array != right.array) return array < right.array; if (array != right.array) return array < right.array;
if (arraySize != right.arraySize) return arraySize < right.arraySize; if (arraySize != right.arraySize) return arraySize < right.arraySize;
if (structure != right.structure) return structure < right.structure; if (structure != right.structure) return structure < right.structure;
return false; return false;
} }
const char* getBasicString() const { return ::getBasicString(type); } const char* getBasicString() const { return ::getBasicString(type); }
const char* getPrecisionString() const { return ::getPrecisionString(precision); } const char* getPrecisionString() const { return ::getPrecisionString(precision); }
const char* getQualifierString() const { return ::getQualifierString(qualifier); } const char* getQualifierString() const { return ::getQualifierString(qualifier); }
TString getCompleteString() const; TString getCompleteString() const;
// If this type is a struct, returns the deepest struct nesting of // If this type is a struct, returns the deepest struct nesting of
// any field in the struct. For example: // any field in the struct. For example:
// struct nesting1 { // struct nesting1 {
// vec4 position; // vec4 position;
// }; // };
// struct nesting2 { // struct nesting2 {
// nesting1 field1; // nesting1 field1;
// vec4 field2; // vec4 field2;
// }; // };
// For type "nesting2", this method would return 2 -- the number // For type "nesting2", this method would return 2 -- the number
// of structures through which indirection must occur to reach the // of structures through which indirection must occur to reach the
// deepest field (nesting2.field1.position). // deepest field (nesting2.field1.position).
int getDeepestStructNesting() const { return deepestStructNesting; } int getDeepestStructNesting() const { return deepestStructNesting; }
bool isStructureContainingArrays() const; bool isStructureContainingArrays() const;
protected: protected:
void buildMangledName(TString&); void buildMangledName(TString&);
int getStructSize() const; int getStructSize() const;
void computeDeepestStructNesting(); void computeDeepestStructNesting();
TBasicType type : 6; TBasicType type : 6;
TPrecision precision; TPrecision precision;
TQualifier qualifier : 7; TQualifier qualifier : 7;
int size : 8; // size of vector or matrix, not size of array int size : 8; // size of vector or matrix, not size of array
unsigned int matrix : 1; unsigned int matrix : 1;
unsigned int array : 1; unsigned int array : 1;
int arraySize; int arraySize;
int maxArraySize; int maxArraySize;
TType* arrayInformationType; TType* arrayInformationType;
TTypeList* structure; // 0 unless this is a struct TTypeList* structure; // 0 unless this is a struct
mutable int structureSize; mutable int structureSize;
int deepestStructNesting; int deepestStructNesting;
TString *fieldName; // for structure field names TString *fieldName; // for structure field names
TString *mangled; TString *mangled;
TString *typeName; // for structure field type name TString *typeName; // for structure field type name
}; };
// //
// This is a workaround for a problem with the yacc stack, It can't have // This is a workaround for a problem with the yacc stack, It can't have
// types that it thinks have non-trivial constructors. It should // types that it thinks have non-trivial constructors. It should
// just be used while recognizing the grammar, not anything else. Pointers // just be used while recognizing the grammar, not anything else. Pointers
// could be used, but also trying to avoid lots of memory management overhead. // could be used, but also trying to avoid lots of memory management overhead.
// //
// Not as bad as it looks, there is no actual assumption that the fields // Not as bad as it looks, there is no actual assumption that the fields
// match up or are name the same or anything like that. // match up or are name the same or anything like that.
// //
struct TPublicType struct TPublicType
{ {
TBasicType type; TBasicType type;
TQualifier qualifier; TQualifier qualifier;
TPrecision precision; TPrecision precision;
int size; // size of vector or matrix, not size of array int size; // size of vector or matrix, not size of array
bool matrix; bool matrix;
bool array; bool array;
int arraySize; int arraySize;
TType* userDef; TType* userDef;
int line; int line;
void setBasic(TBasicType bt, TQualifier q, int ln = 0) void setBasic(TBasicType bt, TQualifier q, int ln = 0)
{ {
type = bt; type = bt;
qualifier = q; qualifier = q;
precision = EbpUndefined; precision = EbpUndefined;
size = 1; size = 1;
matrix = false; matrix = false;
array = false; array = false;
arraySize = 0; arraySize = 0;
userDef = 0; userDef = 0;
line = ln; line = ln;
} }
void setAggregate(int s, bool m = false) void setAggregate(int s, bool m = false)
{ {
size = s; size = s;
matrix = m; matrix = m;
} }
void setArray(bool a, int s = 0) void setArray(bool a, int s = 0)
{ {
array = a; array = a;
arraySize = s; arraySize = s;
} }
bool isStructureContainingArrays() const bool isStructureContainingArrays() const
{ {
if (!userDef) if (!userDef)
{ {
return false; return false;
} }
return userDef->isStructureContainingArrays(); return userDef->isStructureContainingArrays();
} }
}; };
#endif // _TYPES_INCLUDED_ #endif // _TYPES_INCLUDED_
...@@ -435,7 +435,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) ...@@ -435,7 +435,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node)
return true; return true;
bool valid = true; bool valid = true;
TSymbolTable& symbolTable = GlobalParseContext->symbolTable; TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable;
TSymbol* symbol = symbolTable.find(node->getName()); TSymbol* symbol = symbolTable.find(node->getName());
ASSERT(symbol && symbol->isFunction()); ASSERT(symbol && symbol->isFunction());
TFunction* function = static_cast<TFunction*>(symbol); TFunction* function = static_cast<TFunction*>(symbol);
......
...@@ -196,7 +196,7 @@ class TInfoSink; ...@@ -196,7 +196,7 @@ class TInfoSink;
// //
class TIntermNode { class TIntermNode {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TIntermNode() : line(0) {} TIntermNode() : line(0) {}
...@@ -510,8 +510,7 @@ enum Visit ...@@ -510,8 +510,7 @@ enum Visit
class TIntermTraverser class TIntermTraverser
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
preVisit(preVisit), preVisit(preVisit),
inVisit(inVisit), inVisit(inVisit),
......
...@@ -21,7 +21,7 @@ struct TVectorFields { ...@@ -21,7 +21,7 @@ struct TVectorFields {
class TInfoSink; class TInfoSink;
class TIntermediate { class TIntermediate {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TIntermediate(TInfoSink& i) : infoSink(i) { } TIntermediate(TInfoSink& i) : infoSink(i) { }
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc); TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
namespace es2 namespace es2
{ {
bool Shader::compilerInitialized = false;
Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager) Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
{ {
mSource = NULL; mSource = NULL;
...@@ -154,7 +156,11 @@ void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source) ...@@ -154,7 +156,11 @@ void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
TranslatorASM *Shader::createCompiler(ShShaderType type) TranslatorASM *Shader::createCompiler(ShShaderType type)
{ {
ShInitialize(); if(!compilerInitialized)
{
ShInitialize();
compilerInitialized = true;
}
TranslatorASM *assembler = new TranslatorASM(this, type, SH_GLES2_SPEC); TranslatorASM *assembler = new TranslatorASM(this, type, SH_GLES2_SPEC);
...@@ -233,6 +239,7 @@ void Shader::flagForDeletion() ...@@ -233,6 +239,7 @@ void Shader::flagForDeletion()
void Shader::releaseCompiler() void Shader::releaseCompiler()
{ {
ShFinalize(); ShFinalize();
compilerInitialized = false;
} }
GLenum Shader::parseType(const std::string &type) GLenum Shader::parseType(const std::string &type)
......
...@@ -97,6 +97,7 @@ public: ...@@ -97,6 +97,7 @@ public:
static void releaseCompiler(); static void releaseCompiler();
protected: protected:
static bool compilerInitialized;
TranslatorASM *createCompiler(ShShaderType type); TranslatorASM *createCompiler(ShShaderType type);
void clear(); void clear();
......
...@@ -36,14 +36,14 @@ inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) { ...@@ -36,14 +36,14 @@ inline void DecodeSourceLoc(TSourceLoc loc, int* string, int* line) {
// //
// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. // Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
// //
#define POOL_ALLOCATOR_NEW_DELETE(A) \ #define POOL_ALLOCATOR_NEW_DELETE() \
void* operator new(size_t s) { return (A).allocate(s); } \ void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
void* operator new(size_t, void *_Where) { return (_Where); } \ void* operator new(size_t, void *_Where) { return (_Where); } \
void operator delete(void*) { } \ void operator delete(void*) { } \
void operator delete(void *, void *) { } \ void operator delete(void *, void *) { } \
void* operator new[](size_t s) { return (A).allocate(s); } \ void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
void* operator new[](size_t, void *_Where) { return (_Where); } \ void* operator new[](size_t, void *_Where) { return (_Where); } \
void operator delete[](void*) { } \ void operator delete[](void*) { } \
void operator delete[](void *, void *) { } void operator delete[](void *, void *) { }
// //
...@@ -54,7 +54,7 @@ typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TStri ...@@ -54,7 +54,7 @@ typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TStri
typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream; typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
inline TString* NewPoolTString(const char* s) inline TString* NewPoolTString(const char* s)
{ {
void* memory = GlobalPoolAllocator.allocate(sizeof(TString)); void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString));
return new(memory) TString(s); return new(memory) TString(s);
} }
......
...@@ -92,7 +92,7 @@ bool TCompiler::compile(const char* const shaderStrings[], ...@@ -92,7 +92,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
TParseContext parseContext(symbolTable, extensionBehavior, intermediate, TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
shaderType, shaderSpec, compileOptions, true, shaderType, shaderSpec, compileOptions, true,
sourcePath, infoSink); sourcePath, infoSink);
GlobalParseContext = &parseContext; SetGlobalParseContext(&parseContext);
// We preserve symbols at the built-in level from compile-to-compile. // We preserve symbols at the built-in level from compile-to-compile.
// Start pushing the user-defined symbols at global level. // Start pushing the user-defined symbols at global level.
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
class ConstantUnion { class ConstantUnion {
public: public:
POOL_ALLOCATOR_NEW_DELETE();
ConstantUnion() ConstantUnion()
{ {
iConst = 0; iConst = 0;
......
...@@ -10,25 +10,8 @@ ...@@ -10,25 +10,8 @@
#include "compiler/InitializeParseContext.h" #include "compiler/InitializeParseContext.h"
#include "compiler/osinclude.h" #include "compiler/osinclude.h"
OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
bool InitProcess() bool InitProcess()
{ {
if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
//
// Function is re-entrant.
//
return true;
}
ThreadInitializeIndex = OS_AllocTLSIndex();
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
return false;
}
if (!InitializePoolIndex()) { if (!InitializePoolIndex()) {
assert(0 && "InitProcess(): Failed to initalize global pool"); assert(0 && "InitProcess(): Failed to initalize global pool");
return false; return false;
...@@ -39,77 +22,11 @@ bool InitProcess() ...@@ -39,77 +22,11 @@ bool InitProcess()
return false; return false;
} }
return InitThread();
}
bool DetachProcess()
{
bool success = true;
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
return true;
success = DetachThread();
if (!FreeParseContextIndex())
success = false;
FreePoolIndex();
OS_FreeTLSIndex(ThreadInitializeIndex);
ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
return success;
}
bool InitThread()
{
//
// This function is re-entrant
//
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitThread(): Process hasn't been initalised.");
return false;
}
if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
return true;
InitializeGlobalPools();
if (!InitializeGlobalParseContext())
return false;
if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
assert(0 && "InitThread(): Unable to set init flag.");
return false;
}
return true; return true;
} }
bool DetachThread() void DetachProcess()
{ {
bool success = true; FreeParseContextIndex();
FreePoolIndex();
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
return true;
//
// Function is re-entrant and this thread may not have been initalised.
//
if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
assert(0 && "DetachThread(): Unable to clear init flag.");
success = false;
}
if (!FreeParseContext())
success = false;
FreeGlobalPools();
}
return success;
} }
...@@ -7,10 +7,7 @@ ...@@ -7,10 +7,7 @@
#define __INITIALIZEDLL_H #define __INITIALIZEDLL_H
bool InitProcess(); bool InitProcess();
bool DetachProcess(); void DetachProcess();
bool InitThread();
bool DetachThread();
#endif // __INITIALIZEDLL_H #endif // __INITIALIZEDLL_H
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
#ifndef __INITIALIZE_GLOBALS_INCLUDED_ #ifndef __INITIALIZE_GLOBALS_INCLUDED_
#define __INITIALIZE_GLOBALS_INCLUDED_ #define __INITIALIZE_GLOBALS_INCLUDED_
void InitializeGlobalPools();
void FreeGlobalPools();
bool InitializePoolIndex(); bool InitializePoolIndex();
void FreePoolIndex(); void FreePoolIndex();
......
...@@ -12,85 +12,29 @@ OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX; ...@@ -12,85 +12,29 @@ OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
bool InitializeParseContextIndex() bool InitializeParseContextIndex()
{ {
if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) { assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX);
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
return false;
}
//
// Allocate a TLS index.
//
GlobalParseContextIndex = OS_AllocTLSIndex(); GlobalParseContextIndex = OS_AllocTLSIndex();
return GlobalParseContextIndex != OS_INVALID_TLS_INDEX;
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
return false;
}
return true;
} }
bool FreeParseContextIndex() void FreeParseContextIndex()
{ {
OS_TLSIndex tlsiIndex = GlobalParseContextIndex; assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "FreeParseContextIndex(): Parse Context index not initalized");
return false;
}
OS_FreeTLSIndex(GlobalParseContextIndex);
GlobalParseContextIndex = OS_INVALID_TLS_INDEX; GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
return OS_FreeTLSIndex(tlsiIndex);
}
bool InitializeGlobalParseContext()
{
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized");
return false;
}
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
if (lpParseContext != 0) {
assert(0 && "InitializeParseContextIndex(): Parse Context already initalized");
return false;
}
TThreadParseContext *lpThreadData = new TThreadParseContext();
if (lpThreadData == 0) {
assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
return false;
}
lpThreadData->lpGlobalParseContext = 0;
OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
return true;
} }
bool FreeParseContext() void SetGlobalParseContext(TParseContext* context)
{ {
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
assert(0 && "FreeParseContext(): Parse Context index not initalized"); OS_SetTLSValue(GlobalParseContextIndex, context);
return false;
}
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
if (lpParseContext)
delete lpParseContext;
return true;
} }
TParseContextPointer& GetGlobalParseContext() TParseContext* GetGlobalParseContext()
{ {
// assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
// Minimal error checking for speed return static_cast<TParseContext*>(OS_GetTLSValue(GlobalParseContextIndex));
//
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
return lpParseContext->lpGlobalParseContext;
} }
...@@ -8,19 +8,10 @@ ...@@ -8,19 +8,10 @@
#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_ #define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
bool InitializeParseContextIndex(); bool InitializeParseContextIndex();
bool FreeParseContextIndex(); void FreeParseContextIndex();
bool InitializeGlobalParseContext();
bool FreeParseContext();
struct TParseContext; struct TParseContext;
typedef TParseContext* TParseContextPointer; extern void SetGlobalParseContext(TParseContext* context);
extern TParseContextPointer& GetGlobalParseContext(); extern TParseContext* GetGlobalParseContext();
#define GlobalParseContext GetGlobalParseContext()
typedef struct TThreadParseContextRec
{
TParseContext *lpGlobalParseContext;
} TThreadParseContext;
#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_ #endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
...@@ -16,55 +16,32 @@ ...@@ -16,55 +16,32 @@
OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;
void InitializeGlobalPools()
{
TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
if (globalPools)
return;
TThreadGlobalPools* threadData = new TThreadGlobalPools();
threadData->globalPoolAllocator = 0;
OS_SetTLSValue(PoolIndex, threadData);
}
void FreeGlobalPools()
{
// Release the allocated memory for this thread.
TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
if (!globalPools)
return;
delete globalPools;
}
bool InitializePoolIndex() bool InitializePoolIndex()
{ {
// Allocate a TLS index. assert(PoolIndex == OS_INVALID_TLS_INDEX);
if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
return false;
return true; PoolIndex = OS_AllocTLSIndex();
return PoolIndex != OS_INVALID_TLS_INDEX;
} }
void FreePoolIndex() void FreePoolIndex()
{ {
// Release the TLS index. assert(PoolIndex != OS_INVALID_TLS_INDEX);
OS_FreeTLSIndex(PoolIndex); OS_FreeTLSIndex(PoolIndex);
PoolIndex = OS_INVALID_TLS_INDEX;
} }
TPoolAllocator& GetGlobalPoolAllocator() TPoolAllocator* GetGlobalPoolAllocator()
{ {
TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); assert(PoolIndex != OS_INVALID_TLS_INDEX);
return static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex));
return *threadData->globalPoolAllocator;
} }
void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
{ {
TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); assert(PoolIndex != OS_INVALID_TLS_INDEX);
OS_SetTLSValue(PoolIndex, poolAllocator);
threadData->globalPoolAllocator = poolAllocator;
} }
// //
......
...@@ -219,14 +219,8 @@ private: ...@@ -219,14 +219,8 @@ private:
// different times. But a simple use is to have a global pop // different times. But a simple use is to have a global pop
// with everyone using the same global allocator. // with everyone using the same global allocator.
// //
extern TPoolAllocator& GetGlobalPoolAllocator(); extern TPoolAllocator* GetGlobalPoolAllocator();
extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator); extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
#define GlobalPoolAllocator GetGlobalPoolAllocator()
struct TThreadGlobalPools
{
TPoolAllocator* globalPoolAllocator;
};
// //
// This STL compatible allocator is intended to be used as the allocator // This STL compatible allocator is intended to be used as the allocator
...@@ -253,7 +247,7 @@ public: ...@@ -253,7 +247,7 @@ public:
pointer address(reference x) const { return &x; } pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; }
pool_allocator() : allocator(&GlobalPoolAllocator) { } pool_allocator() : allocator(GetGlobalPoolAllocator()) { }
pool_allocator(TPoolAllocator& a) : allocator(&a) { } pool_allocator(TPoolAllocator& a) : allocator(&a) { }
pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { } pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
......
...@@ -23,10 +23,7 @@ ...@@ -23,10 +23,7 @@
// //
int ShInitialize() int ShInitialize()
{ {
if (!InitProcess()) return InitProcess() ? 1 : 0;
return 0;
return 1;
} }
// //
...@@ -34,9 +31,7 @@ int ShInitialize() ...@@ -34,9 +31,7 @@ int ShInitialize()
// //
int ShFinalize() int ShFinalize()
{ {
if (!DetachProcess()) DetachProcess();
return 0;
return 1; return 1;
} }
...@@ -69,9 +64,6 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) ...@@ -69,9 +64,6 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
const ShBuiltInResources* resources) const ShBuiltInResources* resources)
{ {
if (!InitThread())
return 0;
TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec)); TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec));
TCompiler* compiler = base->getAsCompiler(); TCompiler* compiler = base->getAsCompiler();
if (compiler == 0) if (compiler == 0)
...@@ -110,9 +102,6 @@ int ShCompile( ...@@ -110,9 +102,6 @@ int ShCompile(
const int numStrings, const int numStrings,
int compileOptions) int compileOptions)
{ {
if (!InitThread())
return 0;
if (handle == 0) if (handle == 0)
return 0; return 0;
......
...@@ -40,9 +40,10 @@ ...@@ -40,9 +40,10 @@
// //
class TSymbol { class TSymbol {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TSymbol(const TString *n) : name(n) { } TSymbol(const TString *n) : name(n) { }
virtual ~TSymbol() { /* don't delete name, it's from the pool */ } virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
const TString& getName() const { return *name; } const TString& getName() const { return *name; }
virtual const TString& getMangledName() const { return getName(); } virtual const TString& getMangledName() const { return getName(); }
virtual bool isFunction() const { return false; } virtual bool isFunction() const { return false; }
...@@ -179,7 +180,7 @@ public: ...@@ -179,7 +180,7 @@ public:
typedef const tLevel::value_type tLevelPair; typedef const tLevel::value_type tLevelPair;
typedef std::pair<tLevel::iterator, bool> tInsertResult; typedef std::pair<tLevel::iterator, bool> tInsertResult;
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TSymbolTableLevel() { } TSymbolTableLevel() { }
~TSymbolTableLevel(); ~TSymbolTableLevel();
......
// //
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
#ifndef _TYPES_INCLUDED #ifndef _TYPES_INCLUDED
#define _TYPES_INCLUDED #define _TYPES_INCLUDED
#include "compiler/BaseTypes.h" #include "compiler/BaseTypes.h"
#include "compiler/Common.h" #include "compiler/Common.h"
#include "compiler/debug.h" #include "compiler/debug.h"
#include <algorithm> #include <algorithm>
class TType; class TType;
struct TPublicType; struct TPublicType;
// //
// Need to have association of line numbers to types in a list for building structs. // Need to have association of line numbers to types in a list for building structs.
// //
struct TTypeLine { struct TTypeLine {
TType* type; TType* type;
int line; int line;
}; };
typedef TVector<TTypeLine> TTypeList; typedef TVector<TTypeLine> TTypeList;
inline TTypeList* NewPoolTTypeList() inline TTypeList* NewPoolTTypeList()
{ {
void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList)); void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TTypeList));
return new(memory) TTypeList; return new(memory) TTypeList;
} }
// //
// Base class for things that have a type. // Base class for things that have a type.
// //
class TType class TType
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TType() {} TType() {}
TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) : TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0) maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
{ {
} }
explicit TType(const TPublicType &p); explicit TType(const TPublicType &p);
TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) : TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0) maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0)
{ {
typeName = NewPoolTString(n.c_str()); typeName = NewPoolTString(n.c_str());
} }
TBasicType getBasicType() const { return type; } TBasicType getBasicType() const { return type; }
void setBasicType(TBasicType t) { type = t; } void setBasicType(TBasicType t) { type = t; }
TPrecision getPrecision() const { return precision; } TPrecision getPrecision() const { return precision; }
void setPrecision(TPrecision p) { precision = p; } void setPrecision(TPrecision p) { precision = p; }
TQualifier getQualifier() const { return qualifier; } TQualifier getQualifier() const { return qualifier; }
void setQualifier(TQualifier q) { qualifier = q; } void setQualifier(TQualifier q) { qualifier = q; }
// One-dimensional size of single instance type // One-dimensional size of single instance type
int getNominalSize() const { return size; } int getNominalSize() const { return size; }
void setNominalSize(int s) { size = s; } void setNominalSize(int s) { size = s; }
// Full size of single instance of type // Full size of single instance of type
int getObjectSize() const int getObjectSize() const
{ {
if(isArray()) if(isArray())
{ {
return getElementSize() * std::max(getArraySize(), getMaxArraySize()); return getElementSize() * std::max(getArraySize(), getMaxArraySize());
} }
else else
{ {
return getElementSize(); return getElementSize();
} }
} }
int getElementSize() const int getElementSize() const
{ {
if(getBasicType() == EbtStruct) if(getBasicType() == EbtStruct)
{ {
return getStructSize(); return getStructSize();
} }
else if(matrix) else if(matrix)
{ {
return size * size; return size * size;
} }
else // Vector or scalar else // Vector or scalar
{ {
return size; return size;
} }
} }
int elementRegisterCount() const int elementRegisterCount() const
{ {
TTypeList *structure = getStruct(); TTypeList *structure = getStruct();
if(structure) if(structure)
{ {
int registerCount = 0; int registerCount = 0;
for(size_t i = 0; i < structure->size(); i++) for(size_t i = 0; i < structure->size(); i++)
{ {
registerCount += (*structure)[i].type->totalRegisterCount(); registerCount += (*structure)[i].type->totalRegisterCount();
} }
return registerCount; return registerCount;
} }
else if(isMatrix()) else if(isMatrix())
{ {
return getNominalSize(); return getNominalSize();
} }
else else
{ {
return 1; return 1;
} }
} }
int totalRegisterCount() const int totalRegisterCount() const
{ {
if(array) if(array)
{ {
return arraySize * elementRegisterCount(); return arraySize * elementRegisterCount();
} }
else else
{ {
return elementRegisterCount(); return elementRegisterCount();
} }
} }
bool isMatrix() const { return matrix ? true : false; } bool isMatrix() const { return matrix ? true : false; }
void setMatrix(bool m) { matrix = m; } void setMatrix(bool m) { matrix = m; }
bool isArray() const { return array ? true : false; } bool isArray() const { return array ? true : false; }
int getArraySize() const { return arraySize; } int getArraySize() const { return arraySize; }
void setArraySize(int s) { array = true; arraySize = s; } void setArraySize(int s) { array = true; arraySize = s; }
int getMaxArraySize () const { return maxArraySize; } int getMaxArraySize () const { return maxArraySize; }
void setMaxArraySize (int s) { maxArraySize = s; } void setMaxArraySize (int s) { maxArraySize = s; }
void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; } void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; }
void setArrayInformationType(TType* t) { arrayInformationType = t; } void setArrayInformationType(TType* t) { arrayInformationType = t; }
TType* getArrayInformationType() const { return arrayInformationType; } TType* getArrayInformationType() const { return arrayInformationType; }
bool isVector() const { return size > 1 && !matrix; } bool isVector() const { return size > 1 && !matrix; }
bool isScalar() const { return size == 1 && !matrix && !structure; } bool isScalar() const { return size == 1 && !matrix && !structure; }
bool isRegister() const { return !matrix && !structure && !array; } // Fits in a 4-element register bool isRegister() const { return !matrix && !structure && !array; } // Fits in a 4-element register
bool isStruct() const { return structure != 0; } bool isStruct() const { return structure != 0; }
TTypeList* getStruct() const { return structure; } TTypeList* getStruct() const { return structure; }
void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); } void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }
const TString& getTypeName() const const TString& getTypeName() const
{ {
assert(typeName); assert(typeName);
return *typeName; return *typeName;
} }
void setTypeName(const TString& n) void setTypeName(const TString& n)
{ {
typeName = NewPoolTString(n.c_str()); typeName = NewPoolTString(n.c_str());
} }
bool isField() const { return fieldName != 0; } bool isField() const { return fieldName != 0; }
const TString& getFieldName() const const TString& getFieldName() const
{ {
assert(fieldName); assert(fieldName);
return *fieldName; return *fieldName;
} }
void setFieldName(const TString& n) void setFieldName(const TString& n)
{ {
fieldName = NewPoolTString(n.c_str()); fieldName = NewPoolTString(n.c_str());
} }
TString& getMangledName() { TString& getMangledName() {
if (!mangled) { if (!mangled) {
mangled = NewPoolTString(""); mangled = NewPoolTString("");
buildMangledName(*mangled); buildMangledName(*mangled);
*mangled += ';' ; *mangled += ';' ;
} }
return *mangled; return *mangled;
} }
bool sameElementType(const TType& right) const { bool sameElementType(const TType& right) const {
return type == right.type && return type == right.type &&
size == right.size && size == right.size &&
matrix == right.matrix && matrix == right.matrix &&
structure == right.structure; structure == right.structure;
} }
bool operator==(const TType& right) const { bool operator==(const TType& right) const {
return type == right.type && return type == right.type &&
size == right.size && size == right.size &&
matrix == right.matrix && matrix == right.matrix &&
array == right.array && (!array || arraySize == right.arraySize) && array == right.array && (!array || arraySize == right.arraySize) &&
structure == right.structure; structure == right.structure;
// don't check the qualifier, it's not ever what's being sought after // don't check the qualifier, it's not ever what's being sought after
} }
bool operator!=(const TType& right) const { bool operator!=(const TType& right) const {
return !operator==(right); return !operator==(right);
} }
bool operator<(const TType& right) const { bool operator<(const TType& right) const {
if (type != right.type) return type < right.type; if (type != right.type) return type < right.type;
if (size != right.size) return size < right.size; if (size != right.size) return size < right.size;
if (matrix != right.matrix) return matrix < right.matrix; if (matrix != right.matrix) return matrix < right.matrix;
if (array != right.array) return array < right.array; if (array != right.array) return array < right.array;
if (arraySize != right.arraySize) return arraySize < right.arraySize; if (arraySize != right.arraySize) return arraySize < right.arraySize;
if (structure != right.structure) return structure < right.structure; if (structure != right.structure) return structure < right.structure;
return false; return false;
} }
const char* getBasicString() const { return ::getBasicString(type); } const char* getBasicString() const { return ::getBasicString(type); }
const char* getPrecisionString() const { return ::getPrecisionString(precision); } const char* getPrecisionString() const { return ::getPrecisionString(precision); }
const char* getQualifierString() const { return ::getQualifierString(qualifier); } const char* getQualifierString() const { return ::getQualifierString(qualifier); }
TString getCompleteString() const; TString getCompleteString() const;
// If this type is a struct, returns the deepest struct nesting of // If this type is a struct, returns the deepest struct nesting of
// any field in the struct. For example: // any field in the struct. For example:
// struct nesting1 { // struct nesting1 {
// vec4 position; // vec4 position;
// }; // };
// struct nesting2 { // struct nesting2 {
// nesting1 field1; // nesting1 field1;
// vec4 field2; // vec4 field2;
// }; // };
// For type "nesting2", this method would return 2 -- the number // For type "nesting2", this method would return 2 -- the number
// of structures through which indirection must occur to reach the // of structures through which indirection must occur to reach the
// deepest field (nesting2.field1.position). // deepest field (nesting2.field1.position).
int getDeepestStructNesting() const { return deepestStructNesting; } int getDeepestStructNesting() const { return deepestStructNesting; }
bool isStructureContainingArrays() const; bool isStructureContainingArrays() const;
protected: protected:
void buildMangledName(TString&); void buildMangledName(TString&);
int getStructSize() const; int getStructSize() const;
void computeDeepestStructNesting(); void computeDeepestStructNesting();
TBasicType type : 6; TBasicType type : 6;
TPrecision precision; TPrecision precision;
TQualifier qualifier : 7; TQualifier qualifier : 7;
int size : 8; // size of vector or matrix, not size of array int size : 8; // size of vector or matrix, not size of array
unsigned int matrix : 1; unsigned int matrix : 1;
unsigned int array : 1; unsigned int array : 1;
int arraySize; int arraySize;
int maxArraySize; int maxArraySize;
TType* arrayInformationType; TType* arrayInformationType;
TTypeList* structure; // 0 unless this is a struct TTypeList* structure; // 0 unless this is a struct
mutable int structureSize; mutable int structureSize;
int deepestStructNesting; int deepestStructNesting;
TString *fieldName; // for structure field names TString *fieldName; // for structure field names
TString *mangled; TString *mangled;
TString *typeName; // for structure field type name TString *typeName; // for structure field type name
}; };
// //
// This is a workaround for a problem with the yacc stack, It can't have // This is a workaround for a problem with the yacc stack, It can't have
// types that it thinks have non-trivial constructors. It should // types that it thinks have non-trivial constructors. It should
// just be used while recognizing the grammar, not anything else. Pointers // just be used while recognizing the grammar, not anything else. Pointers
// could be used, but also trying to avoid lots of memory management overhead. // could be used, but also trying to avoid lots of memory management overhead.
// //
// Not as bad as it looks, there is no actual assumption that the fields // Not as bad as it looks, there is no actual assumption that the fields
// match up or are name the same or anything like that. // match up or are name the same or anything like that.
// //
struct TPublicType struct TPublicType
{ {
TBasicType type; TBasicType type;
TQualifier qualifier; TQualifier qualifier;
TPrecision precision; TPrecision precision;
int size; // size of vector or matrix, not size of array int size; // size of vector or matrix, not size of array
bool matrix; bool matrix;
bool array; bool array;
int arraySize; int arraySize;
TType* userDef; TType* userDef;
int line; int line;
void setBasic(TBasicType bt, TQualifier q, int ln = 0) void setBasic(TBasicType bt, TQualifier q, int ln = 0)
{ {
type = bt; type = bt;
qualifier = q; qualifier = q;
precision = EbpUndefined; precision = EbpUndefined;
size = 1; size = 1;
matrix = false; matrix = false;
array = false; array = false;
arraySize = 0; arraySize = 0;
userDef = 0; userDef = 0;
line = ln; line = ln;
} }
void setAggregate(int s, bool m = false) void setAggregate(int s, bool m = false)
{ {
size = s; size = s;
matrix = m; matrix = m;
} }
void setArray(bool a, int s = 0) void setArray(bool a, int s = 0)
{ {
array = a; array = a;
arraySize = s; arraySize = s;
} }
bool isStructureContainingArrays() const bool isStructureContainingArrays() const
{ {
if (!userDef) if (!userDef)
{ {
return false; return false;
} }
return userDef->isStructureContainingArrays(); return userDef->isStructureContainingArrays();
} }
}; };
#endif // _TYPES_INCLUDED_ #endif // _TYPES_INCLUDED_
...@@ -435,7 +435,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) ...@@ -435,7 +435,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node)
return true; return true;
bool valid = true; bool valid = true;
TSymbolTable& symbolTable = GlobalParseContext->symbolTable; TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable;
TSymbol* symbol = symbolTable.find(node->getName()); TSymbol* symbol = symbolTable.find(node->getName());
ASSERT(symbol && symbol->isFunction()); ASSERT(symbol && symbol->isFunction());
TFunction* function = static_cast<TFunction*>(symbol); TFunction* function = static_cast<TFunction*>(symbol);
......
...@@ -196,7 +196,7 @@ class TInfoSink; ...@@ -196,7 +196,7 @@ class TInfoSink;
// //
class TIntermNode { class TIntermNode {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TIntermNode() : line(0) {} TIntermNode() : line(0) {}
...@@ -510,8 +510,7 @@ enum Visit ...@@ -510,8 +510,7 @@ enum Visit
class TIntermTraverser class TIntermTraverser
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
preVisit(preVisit), preVisit(preVisit),
inVisit(inVisit), inVisit(inVisit),
......
...@@ -21,7 +21,7 @@ struct TVectorFields { ...@@ -21,7 +21,7 @@ struct TVectorFields {
class TInfoSink; class TInfoSink;
class TIntermediate { class TIntermediate {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE();
TIntermediate(TInfoSink& i) : infoSink(i) { } TIntermediate(TInfoSink& i) : infoSink(i) { }
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc); TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
namespace rad namespace rad
{ {
bool Shader::compilerInitialized = false;
Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager) Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
{ {
mSource = NULL; mSource = NULL;
...@@ -154,7 +156,11 @@ void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source) ...@@ -154,7 +156,11 @@ void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
TranslatorASM *Shader::createCompiler(ShShaderType type) TranslatorASM *Shader::createCompiler(ShShaderType type)
{ {
ShInitialize(); if(!compilerInitialized)
{
ShInitialize();
compilerInitialized = true;
}
TranslatorASM *assembler = new TranslatorASM(this, type, SH_GLES2_SPEC); TranslatorASM *assembler = new TranslatorASM(this, type, SH_GLES2_SPEC);
...@@ -233,6 +239,7 @@ void Shader::flagForDeletion() ...@@ -233,6 +239,7 @@ void Shader::flagForDeletion()
void Shader::releaseCompiler() void Shader::releaseCompiler()
{ {
ShFinalize(); ShFinalize();
compilerInitialized = false;
} }
GLenum Shader::parseType(const std::string &type) GLenum Shader::parseType(const std::string &type)
......
...@@ -97,6 +97,7 @@ public: ...@@ -97,6 +97,7 @@ public:
static void releaseCompiler(); static void releaseCompiler();
protected: protected:
static bool compilerInitialized;
TranslatorASM *createCompiler(ShShaderType type); TranslatorASM *createCompiler(ShShaderType type);
void clear(); void clear();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment