Enable multithreading in glslang
authorPyry Haulos <phaulos@google.com>
Fri, 11 Nov 2016 00:19:52 +0000 (16:19 -0800)
committerPyry Haulos <phaulos@google.com>
Fri, 11 Nov 2016 17:15:50 +0000 (12:15 -0500)
Glslang is internally synchronized and able to support multithreaded
compilation as long as global lock is implemented.

This change provides 12x speedup in building SPIR-V binaries on a
40-core machine.

Change-Id: I27b8ce22db980c3657ac3ba67b7cec1543859d0d

external/glslang/osinclude.cpp
external/vulkancts/framework/vulkan/vkGlslToSpirV.cpp
external/vulkancts/modules/vulkan/vktBuildPrograms.cpp

index 7ce67f6..cfe01f4 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "deThread.h"
 #include "deThreadLocal.h"
+#include "deMutex.h"
 
 namespace glslang
 {
@@ -56,18 +57,24 @@ void* OS_GetTLSValue (OS_TLSIndex nIndex)
        return deThreadLocal_get((deThreadLocal)nIndex);
 }
 
-// Global lock - not used
+// Global lock
+
+static deMutex s_globalLock = 0;
 
 void InitGlobalLock (void)
 {
+       DE_ASSERT(s_globalLock == 0);
+       s_globalLock = deMutex_create(DE_NULL);
 }
 
 void GetGlobalLock (void)
 {
+       deMutex_lock(s_globalLock);
 }
 
 void ReleaseGlobalLock (void)
 {
+       deMutex_unlock(s_globalLock);
 }
 
 // Threading
index c2740a3..4202ddd 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "vkGlslToSpirV.hpp"
 #include "deArrayUtil.hpp"
-#include "deMutex.hpp"
 #include "deSingleton.h"
 #include "deMemory.h"
 #include "deClock.h"
@@ -66,7 +65,6 @@ EShLanguage getGlslangStage (glu::ShaderType type)
 }
 
 static volatile deSingletonState       s_glslangInitState      = DE_SINGLETON_STATE_NOT_INITIALIZED;
-static de::Mutex                                       s_glslangLock;
 
 void initGlslang (void*)
 {
@@ -223,7 +221,6 @@ bool compileGlslToSpirV (const glu::ProgramSources& program, std::vector<deUint3
        {
                if (!program.sources[shaderType].empty())
                {
-                       const de::ScopedLock    compileLock                     (s_glslangLock);
                        const std::string&              srcText                         = program.sources[shaderType][0];
                        const char*                             srcPtrs[]                       = { srcText.c_str() };
                        const int                               srcLengths[]            = { (int)srcText.size() };
index 5b62570..416ec8e 100644 (file)
@@ -371,8 +371,6 @@ BuildStats buildPrograms (tcu::TestContext& testCtx, const std::string& dstPath,
        de::PoolArray<Program>                          programs                        (&programPool);
 
        {
-               // \todo [2016-09-30 pyry] Use main executor when glslang no longer requires global lock
-               TaskExecutor                                            buildGlslExecutor       (1);
                de::MemPool                                                     tmpPool;
                de::PoolArray<BuildGlslTask>            buildGlslTasks          (&tmpPool);
                de::PoolArray<BuildSpirVAsmTask>        buildSpirvAsmTasks      (&tmpPool);
@@ -400,7 +398,7 @@ BuildStats buildPrograms (tcu::TestContext& testCtx, const std::string& dstPath,
                                        {
                                                programs.pushBack(Program(vk::ProgramIdentifier(casePath, progIter.getName())));
                                                buildGlslTasks.pushBack(BuildGlslTask(progIter.getProgram(), &programs.back()));
-                                               buildGlslExecutor.submit(&buildGlslTasks.back());
+                                               executor.submit(&buildGlslTasks.back());
                                        }
 
                                        for (vk::SpirVAsmCollection::Iterator progIter = sourcePrograms.spirvAsmSources.begin();
@@ -418,7 +416,6 @@ BuildStats buildPrograms (tcu::TestContext& testCtx, const std::string& dstPath,
                }
 
                // Need to wait until tasks completed before freeing task memory
-               buildGlslExecutor.waitForComplete();
                executor.waitForComplete();
        }