Skip to content

Commit

Permalink
Merge pull request #3821 from fluffyfreak/threading-modelcompiler
Browse files Browse the repository at this point in the history
Multi-Threading modelcompiler
  • Loading branch information
fluffyfreak committed Sep 26, 2016
2 parents 23cc3cf + dfe9867 commit 80952e4
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ modelcompiler_SOURCES = \
FontCache.cpp \
IniConfig.cpp \
GameConfig.cpp \
JobQueue.cpp \
Lang.cpp \
ModManager.cpp \
NavLights.cpp \
Expand Down
8 changes: 8 additions & 0 deletions src/graphics/TextureBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

namespace Graphics {

//static
SDL_mutex *TextureBuilder::m_textureLock = nullptr;

TextureBuilder::TextureBuilder(const SDLSurfacePtr &surface, TextureSampleMode sampleMode, bool generateMipmaps, bool potExtend, bool forceRGBA, bool compressTextures, bool anisoFiltering) :
m_surface(surface), m_sampleMode(sampleMode), m_generateMipmaps(generateMipmaps), m_potExtend(potExtend), m_forceRGBA(forceRGBA), m_compressTextures(compressTextures), m_anisotropicFiltering(anisoFiltering), m_textureType(TEXTURE_2D), m_prepared(false)
{
Expand All @@ -26,6 +29,11 @@ TextureBuilder::~TextureBuilder()
{
}

void TextureBuilder::Init()
{
m_textureLock = SDL_CreateMutex();
}

// RGBA and RGBpixel format for converting textures
// XXX little-endian. if we ever have a port to a big-endian arch, invert shift and mask
#if SDL_BYTEORDER != SDL_LIL_ENDIAN
Expand Down
8 changes: 7 additions & 1 deletion src/graphics/TextureBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class TextureBuilder {
TextureBuilder(const std::string &filename, TextureSampleMode sampleMode = LINEAR_CLAMP, bool generateMipmaps = false, bool potExtend = false, bool forceRGBA = true, bool compressTextures = true, bool anisoFiltering = true, TextureType textureType = TEXTURE_2D);
~TextureBuilder();

static void Init();

// convenience constructors for common texture types
static TextureBuilder Model(const std::string &filename) {
return TextureBuilder(filename, LINEAR_REPEAT, true, false, false, true, true);
Expand Down Expand Up @@ -49,10 +51,12 @@ class TextureBuilder {
if(m_filename.empty()) {
return CreateTexture(r);
}
SDL_LockMutex(m_textureLock);
Texture *t = r->GetCachedTexture(type, m_filename);
if (t) return t;
if (t) { SDL_UnlockMutex(m_textureLock); return t; }
t = CreateTexture(r);
r->AddCachedTexture(type, m_filename, t);
SDL_UnlockMutex(m_textureLock);
return t;
}

Expand Down Expand Up @@ -88,6 +92,8 @@ class TextureBuilder {

void LoadSurface();
void LoadDDS();

static SDL_mutex *m_textureLock;
};

}
Expand Down
3 changes: 3 additions & 0 deletions src/graphics/opengl/RendererGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "OS.h"
#include "StringF.h"
#include "graphics/Texture.h"
#include "graphics/TextureBuilder.h"
#include "TextureGL.h"
#include "graphics/VertexArray.h"
#include "GLDebug.h"
Expand Down Expand Up @@ -85,6 +86,8 @@ RendererOGL::RendererOGL(WindowSDL *window, const Graphics::Settings &vs)
);
}

TextureBuilder::Init();

m_viewportStack.push(Viewport());

const bool useDXTnTextures = vs.useTextureCompression;
Expand Down
53 changes: 52 additions & 1 deletion src/modelcompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "FileSystem.h"
#include "GameConfig.h"
#include "JobQueue.h"
#include "graphics/dummy/RendererDummy.h"
#include "graphics/Graphics.h"
#include "graphics/Light.h"
Expand All @@ -28,9 +29,36 @@

std::unique_ptr<GameConfig> s_config;
std::unique_ptr<Graphics::Renderer> s_renderer;
std::unique_ptr<AsyncJobQueue> asyncJobQueue;

static const std::string s_dummyPath("");

// fwd decl'
void RunCompiler(const std::string &modelName, const std::string &filepath, const bool bInPlace);

// ********************************************************************************
// Overloaded PureJob class to handle compiling each model
// ********************************************************************************
class CompileJob : public Job
{
public:
CompileJob() {};
CompileJob(const std::string &name, const std::string &path, const bool inPlace)
: m_name(name), m_path(path), m_inPlace(inPlace) {}

virtual void OnRun() override final { RunCompiler(m_name, m_path, m_inPlace); } // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
virtual void OnFinish() override final {}
virtual void OnCancel() override final {}

protected:
std::string m_name;
std::string m_path;
bool m_inPlace;
};

// ********************************************************************************
// functions
// ********************************************************************************
void SetupRenderer()
{
PROFILE_SCOPED()
Expand Down Expand Up @@ -61,6 +89,15 @@ void SetupRenderer()
videoSettings.iconFile = OS::GetIconFilename();
videoSettings.title = "Model Compiler";
s_renderer.reset(Graphics::Init(videoSettings));

// get threads up
Uint32 numThreads = s_config->Int("WorkerThreads");
const int numCores = OS::GetNumCores();
assert(numCores > 0);
if (numThreads == 0)
numThreads = std::max(Uint32(numCores), 1U); // this is a tool, we can use all of the cores for processing unlike Pioneer
asyncJobQueue.reset(new AsyncJobQueue(numThreads));
Output("started %d worker threads\n", numThreads);
}

void RunCompiler(const std::string &modelName, const std::string &filepath, const bool bInPlace)
Expand Down Expand Up @@ -100,6 +137,9 @@ void RunCompiler(const std::string &modelName, const std::string &filepath, cons
}


// ********************************************************************************
// functions
// ********************************************************************************
enum RunMode {
MODE_MODELCOMPILER=0,
MODE_MODELBATCHEXPORT,
Expand Down Expand Up @@ -221,8 +261,19 @@ int main(int argc, char** argv)
}

SetupRenderer();
std::deque<Job::Handle> handles;
for (auto &modelName : list_model) {
RunCompiler(modelName.first, modelName.second, isInPlace);
handles.push_back( asyncJobQueue->Queue(new CompileJob(modelName.first, modelName.second, isInPlace)) );
}

while(true) {
asyncJobQueue->FinishJobs();
bool hasJobs = false;
for(auto &handle : handles)
hasJobs |= handle.HasJob();

if(!hasJobs)
break;
}
break;
}
Expand Down
2 changes: 2 additions & 0 deletions win32/vs2015/modelcompiler.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<ClCompile Include="..\..\src\FileSystem.cpp" />
<ClCompile Include="..\..\src\GameConfig.cpp" />
<ClCompile Include="..\..\src\IniConfig.cpp" />
<ClCompile Include="..\..\src\JobQueue.cpp" />
<ClCompile Include="..\..\src\Lang.cpp" />
<ClCompile Include="..\..\src\modelcompiler.cpp" />
<ClCompile Include="..\..\src\ModManager.cpp" />
Expand All @@ -50,6 +51,7 @@
<ClInclude Include="..\..\src\FileSystem.h" />
<ClInclude Include="..\..\src\GameConfig.h" />
<ClInclude Include="..\..\src\IniConfig.h" />
<ClInclude Include="..\..\src\JobQueue.h" />
<ClInclude Include="..\..\src\Lang.h" />
<ClInclude Include="..\..\src\LangStrings.inc.h" />
<ClInclude Include="..\..\src\libs.h" />
Expand Down
6 changes: 6 additions & 0 deletions win32/vs2015/modelcompiler.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@
<ClCompile Include="..\..\src\win32\TextUtils.cpp">
<Filter>Win32</Filter>
</ClCompile>
<ClCompile Include="..\..\src\JobQueue.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\IniConfig.h">
Expand Down Expand Up @@ -164,5 +167,8 @@
<ClInclude Include="..\..\src\DateTime.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\JobQueue.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

0 comments on commit 80952e4

Please sign in to comment.