Ensure the shared symbol table levels are read-only to make multi-threading safe. Also removed inadvertent extra copies of the symbol table shared across all stages.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22939 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich
2013-09-06 19:52:57 +00:00
parent 69f4b517c2
commit 38f3b890de
14 changed files with 230 additions and 125 deletions

View File

@@ -55,6 +55,7 @@ enum TOptions {
EOptionRelaxedErrors = 0x008,
EOptionGiveWarnings = 0x010,
EOptionsLinkProgram = 0x020,
EOptionMultiThreaded = 0x040,
};
//
@@ -119,16 +120,29 @@ void GenerateResources(TBuiltInResource& resources)
resources.maxProgramTexelOffset = 7;
}
// thread-safe list of shaders to asynchronously grab and compile
glslang::TWorklist Worklist;
// array of unique places to leave the shader names and infologs for the asynchronous compiles
glslang::TWorkItem **Work = 0;
int NumWorkItems = 0;
int Options = 0;
bool Delay = false;
const char* ExecutableName;
bool ProcessArguments(int argc, char* argv[])
{
ExecutableName = argv[0];
NumWorkItems = argc; // will include some empties where the '-' options were, but it doesn't matter, they'll be 0
Work = new glslang::TWorkItem*[NumWorkItems];
Work[0] = 0;
argc--;
argv++;
for (; argc >= 1; argc--, argv++) {
if (argv[0][0] == '-') {
Work[argc] = 0;
switch (argv[0][1]) {
case 'd':
Delay = true;
@@ -148,11 +162,18 @@ bool ProcessArguments(int argc, char* argv[])
case 's':
Options |= EOptionSuppressInfolog;
break;
case 't':
#ifdef _WIN32
Options |= EOptionMultiThreaded;
#endif
break;
default:
return false;
}
} else
Worklist.add(std::string(argv[0]));
} else {
Work[argc] = new glslang::TWorkItem(std::string(argv[0]));
Worklist.add(Work[argc]);
}
}
if (Worklist.empty())
@@ -168,18 +189,18 @@ unsigned int
#endif
CompileShaders(void*)
{
std::string shaderName;
while (Worklist.remove(shaderName)) {
ShHandle compiler = ShConstructCompiler(FindLanguage(shaderName), Options);
glslang::TWorkItem* workItem;
while (Worklist.remove(workItem)) {
ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options);
if (compiler == 0)
return false;
TBuiltInResource resources;
GenerateResources(resources);
CompileFile(shaderName.c_str(), compiler, Options, &resources);
CompileFile(workItem->name.c_str(), compiler, Options, &resources);
if (! (Options & EOptionSuppressInfolog))
puts(ShGetInfoLog(compiler));
workItem->results = ShGetInfoLog(compiler);
ShDestruct(compiler);
}
@@ -212,13 +233,13 @@ void CompileAndLinkShaders()
//
glslang::TProgram program;
std::string shaderName;
while (Worklist.remove(shaderName)) {
EShLanguage stage = FindLanguage(shaderName);
glslang::TWorkItem* workItem;
while (Worklist.remove(workItem)) {
EShLanguage stage = FindLanguage(workItem->name);
glslang::TShader* shader = new glslang::TShader(stage);
shaders.push_back(shader);
char** shaderStrings = ReadFileData(shaderName.c_str());
char** shaderStrings = ReadFileData(workItem->name.c_str());
if (! shaderStrings) {
usage();
return;
@@ -231,7 +252,7 @@ void CompileAndLinkShaders()
program.addShader(shader);
if (! (Options & EOptionSuppressInfolog)) {
puts(shaderName.c_str());
puts(workItem->name.c_str());
puts(shader->getInfoLog());
puts(shader->getInfoDebugLog());
}
@@ -266,7 +287,7 @@ int C_DECL main(int argc, char* argv[])
// Init for front-end proper
ShInitialize();
// Init for for standalone
// Init for standalone
glslang::InitGlobalLock();
if (! ProcessArguments(argc, argv)) {
@@ -276,29 +297,39 @@ int C_DECL main(int argc, char* argv[])
//
// Two modes:
// 1) linking all arguments together, single-threaded
// 2) independent arguments, can be tackled by multiple asynchronous threads, for testing thread safety
// 1) linking all arguments together, single-threaded, new C++ interface
// 2) independent arguments, can be tackled by multiple asynchronous threads, for testing thread safety, using the old handle interface
//
if (Options & EOptionsLinkProgram)
CompileAndLinkShaders();
else {
bool printShaderNames = Worklist.size() > 1;
// TODO: finish threading, allow external control over number of threads
const int NumThreads = 1;
if (NumThreads > 1) {
void* threads[NumThreads];
for (int t = 0; t < NumThreads; ++t) {
threads[t] = glslang::OS_CreateThread(&CompileShaders);
if (! threads[t]) {
printf("Failed to create thread\n");
return EFailThreadCreate;
if (Options & EOptionMultiThreaded) {
const int NumThreads = 16;
void* threads[NumThreads];
for (int t = 0; t < NumThreads; ++t) {
threads[t] = glslang::OS_CreateThread(&CompileShaders);
if (! threads[t]) {
printf("Failed to create thread\n");
return EFailThreadCreate;
}
}
}
glslang::OS_WaitForAllThreads(threads, NumThreads);
} else {
if (Options & EOptionsLinkProgram) {
CompileAndLinkShaders();
glslang::OS_WaitForAllThreads(threads, NumThreads);
} else {
if (! CompileShaders(0))
compileFailed = true;
}
// Print out all the resulting infologs
for (int w = 0; w < NumWorkItems; ++w) {
if (Work[w]) {
if (printShaderNames)
puts(Work[w]->name.c_str());
puts(Work[w]->results.c_str());
delete Work[w];
}
}
}
if (Delay)
@@ -401,7 +432,7 @@ bool CompileFile(const char *fileName, ShHandle compiler, int Options, const TBu
//
void usage()
{
printf("Usage: standalone [ options ] filename\n"
printf("Usage: glslangValidator [ options ] filename\n"
"Where: filename is a name ending in\n"
" .vert for a vertex shader\n"
" .tesc for a tessellation control shader\n"
@@ -415,8 +446,9 @@ void usage()
"-d: delay exit\n"
"-l: link validation of all input files\n"
"-m: memory leak mode\n"
"-r: relaxed semantic error-checking mode\n"
"-s: silent mode\n"
"-r: relaxed semantic error-checking mode\n");
"-t: multi-threaded mode\n");
}
#ifndef _WIN32

View File

@@ -41,27 +41,36 @@
namespace glslang {
class TWorkItem {
public:
TWorkItem() { }
explicit TWorkItem(const std::string& s) :
name(s) { }
std::string name;
std::string results;
};
class TWorklist {
public:
TWorklist() { }
virtual ~TWorklist() { }
void add(const std::string& s)
void add(TWorkItem* item)
{
GetGlobalLock();
worklist.push_back(s);
worklist.push_back(item);
ReleaseGlobalLock();
}
bool remove(std::string& s)
bool remove(TWorkItem*& item)
{
GetGlobalLock();
if (worklist.empty())
return false;
s = worklist.front();
item = worklist.front();
worklist.pop_front();
ReleaseGlobalLock();
@@ -69,13 +78,18 @@ namespace glslang {
return true;
}
int size()
{
return worklist.size();
}
bool empty()
{
return worklist.empty();
}
protected:
std::list<std::string> worklist;
std::list<TWorkItem*> worklist;
};
} // end namespace glslang