Skip to content
Snippets Groups Projects
Commit a558b265 authored by Juan Lopez's avatar Juan Lopez
Browse files

This refactor the StandAlone and WorkList files in order to use more

C++11 features remove the dependencies from OS specific code. Changes:

- Making WorkList class to have its own mutex instead of the OS specific
global one. The new mutex is the one from std library. The OS specific
code is also removed.

- Using the C++11 std library to handle threads in StandAlone
application
and enabling concurrent processing on non-windows platforms.

- converting the global variable Worklist into local variable workList.
parent c7fd73b7
No related branches found
No related tags found
No related merge requests found
......@@ -51,6 +51,8 @@
#include <cctype>
#include <cmath>
#include <array>
#include <memory>
#include <thread>
#include "../glslang/OSDependent/osinclude.h"
......@@ -150,13 +152,6 @@ void ProcessConfigFile()
delete[] config;
}
// 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;
const char* ExecutableName = nullptr;
const char* binaryFileName = nullptr;
......@@ -253,7 +248,7 @@ void ProcessBindingBase(int& argc, char**& argv, std::array<unsigned int, EShLan
//
// Does not return (it exits) if command-line is fatally flawed.
//
void ProcessArguments(int argc, char* argv[])
void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItems, int argc, char* argv[])
{
baseSamplerBinding.fill(0);
baseTextureBinding.fill(0);
......@@ -262,10 +257,7 @@ void ProcessArguments(int argc, char* argv[])
baseSsboBinding.fill(0);
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];
for (int w = 0; w < NumWorkItems; ++w)
Work[w] = 0;
workItems.reserve(argc);
argc--;
argv++;
......@@ -420,9 +412,7 @@ void ProcessArguments(int argc, char* argv[])
Options |= EOptionSuppressInfolog;
break;
case 't':
#ifdef _WIN32
Options |= EOptionMultiThreaded;
#endif
Options |= EOptionMultiThreaded;
break;
case 'v':
Options |= EOptionDumpVersions;
......@@ -440,8 +430,7 @@ void ProcessArguments(int argc, char* argv[])
} else {
std::string name(argv[0]);
if (! SetConfigFile(name)) {
Work[argc] = new glslang::TWorkItem(name);
Worklist.add(Work[argc]);
workItems.push_back(std::unique_ptr<glslang::TWorkItem>(new glslang::TWorkItem(name)));
}
}
}
......@@ -487,15 +476,13 @@ void SetMessageOptions(EShMessages& messages)
//
// Thread entry point, for non-linking asynchronous mode.
//
// Return 0 for failure, 1 for success.
//
unsigned int CompileShaders(void*)
void CompileShaders(glslang::TWorklist& worklist)
{
glslang::TWorkItem* workItem;
while (Worklist.remove(workItem)) {
while (worklist.remove(workItem)) {
ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options);
if (compiler == 0)
return 0;
return;
CompileFile(workItem->name.c_str(), compiler);
......@@ -504,8 +491,6 @@ unsigned int CompileShaders(void*)
ShDestruct(compiler);
}
return 0;
}
// Outputs the given string, but only if it is non-null and non-empty.
......@@ -705,7 +690,7 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
// performance and memory testing, the actual compile/link can be put in
// a loop, independent of processing the work items and file IO.
//
void CompileAndLinkShaderFiles()
void CompileAndLinkShaderFiles(glslang::TWorklist& Worklist)
{
std::vector<ShaderCompUnit> compUnits;
......@@ -747,11 +732,19 @@ void CompileAndLinkShaderFiles()
int C_DECL main(int argc, char* argv[])
{
ProcessArguments(argc, argv);
// array of unique places to leave the shader names and infologs for the asynchronous compiles
std::vector<std::unique_ptr<glslang::TWorkItem>> workItems;
ProcessArguments(workItems, argc, argv);
glslang::TWorklist workList;
std::for_each(workItems.begin(), workItems.end(), [&workList](std::unique_ptr<glslang::TWorkItem>& item) {
assert(item);
workList.add(item.get());
});
if (Options & EOptionDumpConfig) {
printf("%s", glslang::GetDefaultTBuiltInResourceString().c_str());
if (Worklist.empty())
if (workList.empty())
return ESuccess;
}
......@@ -766,11 +759,11 @@ int C_DECL main(int argc, char* argv[])
printf("Khronos Tool ID %d\n", glslang::GetKhronosToolId());
printf("GL_KHR_vulkan_glsl version %d\n", 100);
printf("ARB_GL_gl_spirv version %d\n", 100);
if (Worklist.empty())
if (workList.empty())
return ESuccess;
}
if (Worklist.empty()) {
if (workList.empty()) {
usage();
}
......@@ -784,47 +777,42 @@ int C_DECL main(int argc, char* argv[])
if (Options & EOptionLinkProgram ||
Options & EOptionOutputPreprocessed) {
glslang::InitializeProcess();
CompileAndLinkShaderFiles();
CompileAndLinkShaderFiles(workList);
glslang::FinalizeProcess();
for (int w = 0; w < NumWorkItems; ++w) {
if (Work[w]) {
delete Work[w];
}
}
} else {
ShInitialize();
bool printShaderNames = Worklist.size() > 1;
bool printShaderNames = workList.size() > 1;
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]) {
if (Options & EOptionMultiThreaded)
{
std::array<std::thread, 16> threads;
for (unsigned int t = 0; t < threads.size(); ++t)
{
threads[t] = std::thread(CompileShaders, std::ref(workList));
if (threads[t].get_id() == std::thread::id())
{
printf("Failed to create thread\n");
return EFailThreadCreate;
}
}
glslang::OS_WaitForAllThreads(threads, NumThreads);
std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
} else
CompileShaders(0);
CompileShaders(workList);
// Print out all the resulting infologs
for (int w = 0; w < NumWorkItems; ++w) {
if (Work[w]) {
if (printShaderNames || Work[w]->results.size() > 0)
PutsIfNonEmpty(Work[w]->name.c_str());
PutsIfNonEmpty(Work[w]->results.c_str());
delete Work[w];
for (size_t w = 0; w < workItems.size(); ++w) {
if (workItems[w]) {
if (printShaderNames || workItems[w]->results.size() > 0)
PutsIfNonEmpty(workItems[w]->name.c_str());
PutsIfNonEmpty(workItems[w]->results.c_str());
}
}
ShFinalize();
}
delete[] Work;
if (CompileFailed)
return EFailCompile;
if (LinkFailed)
......
......@@ -36,8 +36,9 @@
#define WORKLIST_H_INCLUDED
#include "../glslang/OSDependent/osinclude.h"
#include <string>
#include <list>
#include <mutex>
#include <string>
namespace glslang {
......@@ -58,24 +59,19 @@ namespace glslang {
void add(TWorkItem* item)
{
GetGlobalLock();
std::lock_guard<std::mutex> guard(mutex);
worklist.push_back(item);
ReleaseGlobalLock();
}
bool remove(TWorkItem*& item)
{
GetGlobalLock();
std::lock_guard<std::mutex> guard(mutex);
if (worklist.empty())
return false;
item = worklist.front();
worklist.pop_front();
ReleaseGlobalLock();
return true;
}
......@@ -90,6 +86,7 @@ namespace glslang {
}
protected:
std::mutex mutex;
std::list<TWorkItem*> worklist;
};
......
......@@ -184,20 +184,6 @@ void ReleaseGlobalLock()
pthread_mutex_unlock(&gMutex);
}
// TODO: non-windows: if we need these on linux, flesh them out
void* OS_CreateThread(TThreadEntrypoint /*entry*/)
{
return 0;
}
void OS_WaitForAllThreads(void* /*threads*/, int /*numThreads*/)
{
}
void OS_Sleep(int /*milliseconds*/)
{
}
void OS_DumpMemoryCounters()
{
}
......
......@@ -131,21 +131,6 @@ unsigned int __stdcall EnterGenericThread (void* entry)
return ((TThreadEntrypoint)entry)(0);
}
void* OS_CreateThread(TThreadEntrypoint entry)
{
return (void*)_beginthreadex(0, 0, EnterGenericThread, (void*)entry, 0, 0);
}
void OS_WaitForAllThreads(void* threads, int numThreads)
{
WaitForMultipleObjects(numThreads, (HANDLE*)threads, true, INFINITE);
}
void OS_Sleep(int milliseconds)
{
Sleep(milliseconds);
}
//#define DUMP_COUNTERS
void OS_DumpMemoryCounters()
......
......@@ -53,11 +53,8 @@ void GetGlobalLock();
void ReleaseGlobalLock();
typedef unsigned int (*TThreadEntrypoint)(void*);
void* OS_CreateThread(TThreadEntrypoint);
void OS_WaitForAllThreads(void* threads, int numThreads);
void OS_CleanupThreadData(void);
void OS_Sleep(int milliseconds);
void OS_DumpMemoryCounters();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment