From db2d95627f307e65b5c2450e96b1be8f320c2e96 Mon Sep 17 00:00:00 2001 From: palana Date: Mon, 19 Aug 2013 19:49:25 +0200 Subject: [PATCH] Added shader blob file cache To offset the huge compile time for shaders with complexity similar to the yadif shader --- Source/D3D10Shader.cpp | 128 +++++++++++++++++++++++++++++------------ Source/Main.cpp | 4 ++ 2 files changed, 96 insertions(+), 36 deletions(-) diff --git a/Source/D3D10Shader.cpp b/Source/D3D10Shader.cpp index d3927073..9d5dde26 100644 --- a/Source/D3D10Shader.cpp +++ b/Source/D3D10Shader.cpp @@ -19,7 +19,6 @@ #include "Main.h" - void D3D10Shader::LoadDefaults() { for(UINT i=0; i(GS); LPCSTR lpVSType = d3d10Sys->bDisableCompatibilityMode ? "vs_4_0" : "vs_4_0_level_9_3"; + String cacheFilename = FormattedString(TEXT("%s/shaderCache/%s.blob"), OBSGetAppDataPath(), lpFileName).FindReplace(TEXT("\\"), TEXT("/")); + + List shaderBuffer; + LPVOID shaderData; + SIZE_T shaderDataSize; + ID3D10Blob *errorMessages = NULL, *shaderBlob = NULL; - HRESULT err = D3DX10CompileFromMemory(lpAnsiShader, strlen(lpAnsiShader), lpAnsiFileName, NULL, NULL, "main", lpVSType, D3D10_SHADER_OPTIMIZATION_LEVEL3, 0, NULL, &shaderBlob, &errorMessages, NULL); + + HRESULT err; - Free(lpAnsiFileName); - Free(lpAnsiShader); - - if(FAILED(err)) + if(!OSFileExists(cacheFilename) || OSGetFileModificationTime(lpFileName) > OSGetFileModificationTime(cacheFilename)) { - if(errorMessages) + LPSTR lpAnsiShader = tstr_createUTF8(lpShader); + LPSTR lpAnsiFileName = tstr_createUTF8(lpFileName); + + err = D3DX10CompileFromMemory(lpAnsiShader, strlen(lpAnsiShader), lpAnsiFileName, NULL, NULL, "main", lpVSType, D3D10_SHADER_OPTIMIZATION_LEVEL3, 0, NULL, &shaderBlob, &errorMessages, NULL); + + Free(lpAnsiFileName); + Free(lpAnsiShader); + + if(FAILED(err)) { - if(errorMessages->GetBufferSize()) + if(errorMessages) { - LPSTR lpErrors = (LPSTR)errorMessages->GetBufferPointer(); - Log(TEXT("Error compiling vertex shader '%s':\r\n\r\n%S\r\n"), lpFileName, lpErrors); + if(errorMessages->GetBufferSize()) + { + LPSTR lpErrors = (LPSTR)errorMessages->GetBufferPointer(); + Log(TEXT("Error compiling vertex shader '%s':\r\n\r\n%S\r\n"), lpFileName, lpErrors); + } + + errorMessages->Release(); } - errorMessages->Release(); + CrashError(TEXT("Compilation of vertex shader '%s' failed, result = %08lX"), lpFileName, err); + return NULL; } - CrashError(TEXT("Compilation of vertex shader '%s' failed, result = %08lX"), lpFileName, err); - return NULL; + shaderData = shaderBlob->GetBufferPointer(); + shaderDataSize = shaderBlob->GetBufferSize(); + + CreatePath(GetPathDirectory(cacheFilename)); + XFile cacheFile(cacheFilename, XFILE_WRITE, XFILE_CREATEALWAYS); + cacheFile.Write(shaderData, (DWORD)shaderDataSize); + } + else + { + XFile cacheFile(cacheFilename, XFILE_READ | XFILE_SHARED, XFILE_OPENEXISTING); + shaderBuffer.SetSize((unsigned)cacheFile.GetFileSize()); + cacheFile.Read(shaderBuffer.Array(), shaderBuffer.Num()); + + shaderData = shaderBuffer.Array(); + shaderDataSize = shaderBuffer.Num(); } //----------------------------------------------- @@ -124,7 +151,7 @@ Shader* D3D10VertexShader::CreateVertexShader(CTSTR lpShader, CTSTR lpFileName) ID3D10VertexShader *vShader; ID3D10InputLayout *vShaderLayout; - err = GetD3D()->CreateVertexShader(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), &vShader); + err = GetD3D()->CreateVertexShader(shaderData, shaderDataSize, &vShader); if(FAILED(err)) { CrashError(TEXT("Unable to create vertex shader '%s', result = %08lX"), lpFileName, err); @@ -132,7 +159,7 @@ Shader* D3D10VertexShader::CreateVertexShader(CTSTR lpShader, CTSTR lpFileName) return NULL; } - err = GetD3D()->CreateInputLayout(shaderProcessor.generatedLayout.Array(), shaderProcessor.generatedLayout.Num(), shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), &vShaderLayout); + err = GetD3D()->CreateInputLayout(shaderProcessor.generatedLayout.Array(), shaderProcessor.generatedLayout.Num(), shaderData, shaderDataSize, &vShaderLayout); if(FAILED(err)) { CrashError(TEXT("Unable to create vertex layout for vertex shader '%s', result = %08lX"), lpFileName, err); @@ -141,7 +168,7 @@ Shader* D3D10VertexShader::CreateVertexShader(CTSTR lpShader, CTSTR lpFileName) return NULL; } - shaderBlob->Release(); + SafeRelease(shaderBlob); //----------------------------------------------- @@ -173,40 +200,69 @@ Shader* D3D10PixelShader::CreatePixelShader(CTSTR lpShader, CTSTR lpFileName) //----------------------------------------------- - LPSTR lpAnsiShader = tstr_createUTF8(lpShader); - LPSTR lpAnsiFileName = tstr_createUTF8(lpFileName); - D3D10System *d3d10Sys = static_cast(GS); LPCSTR lpPSType = d3d10Sys->bDisableCompatibilityMode ? "ps_4_0" : "ps_4_0_level_9_3"; + String cacheFilename = FormattedString(TEXT("%s/shaderCache/%s.blob"), OBSGetAppDataPath(), lpFileName).FindReplace(TEXT("\\"), TEXT("/")); + Log(cacheFilename); + + List shaderBuffer; + LPVOID shaderData; + SIZE_T shaderDataSize; + ID3D10Blob *errorMessages = NULL, *shaderBlob = NULL; - HRESULT err = D3DX10CompileFromMemory(lpAnsiShader, strlen(lpAnsiShader), lpAnsiFileName, NULL, NULL, "main", lpPSType, D3D10_SHADER_OPTIMIZATION_LEVEL3, 0, NULL, &shaderBlob, &errorMessages, NULL); + + HRESULT err; - Free(lpAnsiFileName); - Free(lpAnsiShader); - - if(FAILED(err)) + if(!OSFileExists(cacheFilename) || OSGetFileModificationTime(lpFileName) > OSGetFileModificationTime(cacheFilename)) { - if(errorMessages) + LPSTR lpAnsiShader = tstr_createUTF8(lpShader); + LPSTR lpAnsiFileName = tstr_createUTF8(lpFileName); + + err = D3DX10CompileFromMemory(lpAnsiShader, strlen(lpAnsiShader), lpAnsiFileName, NULL, NULL, "main", lpPSType, D3D10_SHADER_OPTIMIZATION_LEVEL3, 0, NULL, &shaderBlob, &errorMessages, NULL); + + Free(lpAnsiFileName); + Free(lpAnsiShader); + + if(FAILED(err)) { - if(errorMessages->GetBufferSize()) + if(errorMessages) { - LPSTR lpErrors = (LPSTR)errorMessages->GetBufferPointer(); - Log(TEXT("Error compiling pixel shader '%s':\r\n\r\n%S\r\n"), lpFileName, lpErrors); + if(errorMessages->GetBufferSize()) + { + LPSTR lpErrors = (LPSTR)errorMessages->GetBufferPointer(); + Log(TEXT("Error compiling pixel shader '%s':\r\n\r\n%S\r\n"), lpFileName, lpErrors); + } + + errorMessages->Release(); } - errorMessages->Release(); + CrashError(TEXT("Compilation of pixel shader '%s' failed, result = %08lX"), lpFileName, err); + return NULL; } - CrashError(TEXT("Compilation of pixel shader '%s' failed, result = %08lX"), lpFileName, err); - return NULL; + shaderData = shaderBlob->GetBufferPointer(); + shaderDataSize = shaderBlob->GetBufferSize(); + + CreatePath(GetPathDirectory(cacheFilename)); + XFile cacheFile(cacheFilename, XFILE_WRITE, XFILE_CREATEALWAYS); + cacheFile.Write(shaderData, (DWORD)shaderDataSize); + } + else + { + XFile cacheFile(cacheFilename, XFILE_READ | XFILE_SHARED, XFILE_OPENEXISTING); + shaderBuffer.SetSize((unsigned)cacheFile.GetFileSize()); + cacheFile.Read(shaderBuffer.Array(), shaderBuffer.Num()); + + shaderData = shaderBuffer.Array(); + shaderDataSize = shaderBuffer.Num(); } //----------------------------------------------- ID3D10PixelShader *pShader; - err = GetD3D()->CreatePixelShader(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), &pShader); + err = GetD3D()->CreatePixelShader(shaderData, shaderDataSize, &pShader); if(FAILED(err)) { CrashError(TEXT("Unable to create pixel shader '%s', result = %08lX"), lpFileName, err); @@ -214,7 +270,7 @@ Shader* D3D10PixelShader::CreatePixelShader(CTSTR lpShader, CTSTR lpFileName) return NULL; } - shaderBlob->Release(); + SafeRelease(shaderBlob); //----------------------------------------------- diff --git a/Source/Main.cpp b/Source/Main.cpp index dce1a609..574cf72a 100644 --- a/Source/Main.cpp +++ b/Source/Main.cpp @@ -511,6 +511,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine if(!OSFileExists(strUpdatePath) && !OSCreateDirectory(strUpdatePath)) CrashError(TEXT("Couldn't create directory '%s'"), strUpdatePath.Array()); + String strShaderCachePath = strAppDataPath + TEXT("\\shaderCache"); + if(!OSFileExists(strShaderCachePath) && !OSCreateDirectory(strShaderCachePath)) + CrashError(TEXT("Coudln't create directory '%s'"), strShaderCachePath.Array()); + LoadGlobalIni(); String strAllocator = GlobalConfig->GetString(TEXT("General"), TEXT("Allocator"));