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
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
index 3b26488..8203ad5 100644
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -55,6 +55,7 @@
EOptionRelaxedErrors = 0x008,
EOptionGiveWarnings = 0x010,
EOptionsLinkProgram = 0x020,
+ EOptionMultiThreaded = 0x040,
};
//
@@ -119,16 +120,29 @@
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 @@
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 @@
#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 @@
//
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 @@
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 @@
// Init for front-end proper
ShInitialize();
- // Init for for standalone
+ // Init for standalone
glslang::InitGlobalLock();
if (! ProcessArguments(argc, argv)) {
@@ -276,29 +297,39 @@
//
// 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 @@
//
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 @@
"-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