diff --git a/src/Layers/xrRender/ShaderResourceTraits.h b/src/Layers/xrRender/ShaderResourceTraits.h index 2194115bd0c..03d41a106d4 100644 --- a/src/Layers/xrRender/ShaderResourceTraits.h +++ b/src/Layers/xrRender/ShaderResourceTraits.h @@ -392,14 +392,13 @@ inline T* CResourceManager::CreateShader(const char* name, const char* filename FS.update_path(cname, "$game_shaders$", cname); file = FS.r_open(cname); } - R_ASSERT2(file, cname); + R_ASSERT3(file, "Shader file doesnt exist:", cname); // Duplicate and zero-terminate const auto size = file->length(); char* const data = (LPSTR)_alloca(size + 1); CopyMemory(data, file->pointer(), size); data[size] = 0; - FS.r_close(file); // Select target LPCSTR c_target = ShaderTypeTraits::GetCompilationTarget(); @@ -417,8 +416,9 @@ inline T* CResourceManager::CreateShader(const char* name, const char* filename #endif // Compile - HRESULT const _hr = GEnv.Render->shader_compile(name, (DWORD const*)data, size, - c_entry, c_target, flags, (void*&)sh); + HRESULT const _hr = GEnv.Render->shader_compile(name, file, c_entry, c_target, flags, (void*&)sh); + + FS.r_close(file); VERIFY(SUCCEEDED(_hr)); diff --git a/src/Layers/xrRenderPC_GL/glResourceManager_Resources.cpp b/src/Layers/xrRenderPC_GL/glResourceManager_Resources.cpp index ff7c5436cc5..091659fb128 100644 --- a/src/Layers/xrRenderPC_GL/glResourceManager_Resources.cpp +++ b/src/Layers/xrRenderPC_GL/glResourceManager_Resources.cpp @@ -208,16 +208,13 @@ SVS* CResourceManager::_CreateVS(LPCSTR _name) FS.update_path(cname, "$game_shaders$", cname); file = FS.r_open(cname); } - u32 const size = file->length(); - char* const data = (LPSTR)_alloca(size + 1); - CopyMemory ( data, file->pointer(), size ); - data[size] = 0; - FS.r_close(file); // Select target _vs->sh = glCreateShader(GL_VERTEX_SHADER); void* _result = &_vs->sh; - HRESULT const _hr = GEnv.Render->shader_compile(name, (DWORD const*)data, size, nullptr, nullptr, NULL, _result); + HRESULT const _hr = GEnv.Render->shader_compile(name, file, nullptr, nullptr, NULL, _result); + + FS.r_close(file); VERIFY(SUCCEEDED(_hr)); @@ -291,16 +288,13 @@ SPS* CResourceManager::_CreatePS(LPCSTR _name) file = FS.r_open(cname); } R_ASSERT2 ( file, cname ); - u32 const size = file->length(); - char* const data = (LPSTR)_alloca(size + 1); - CopyMemory ( data, file->pointer(), size ); - data[size] = 0; - FS.r_close(file); // Select target _ps->sh = glCreateShader(GL_FRAGMENT_SHADER); void* _result = &_ps->sh; - HRESULT const _hr = GEnv.Render->shader_compile(name, (DWORD const*)data, size, nullptr, nullptr, NULL, _result); + HRESULT const _hr = GEnv.Render->shader_compile(name, file, nullptr, nullptr, NULL, _result); + + FS.r_close(file); VERIFY(SUCCEEDED(_hr)); @@ -367,7 +361,7 @@ SGS* CResourceManager::_CreateGS(LPCSTR name) // Select target _gs->sh = glCreateShader(GL_GEOMETRY_SHADER); void* _result = &_gs->sh; - HRESULT const _hr = GEnv.Render->shader_compile(name, (DWORD const*)file->pointer(), file->length(), nullptr, + HRESULT const _hr = GEnv.Render->shader_compile(name, file, nullptr, nullptr, NULL, _result); VERIFY(SUCCEEDED(_hr)); diff --git a/src/Layers/xrRenderPC_GL/rgl.h b/src/Layers/xrRenderPC_GL/rgl.h index d4fa2b8da09..31edb8ef59d 100644 --- a/src/Layers/xrRenderPC_GL/rgl.h +++ b/src/Layers/xrRenderPC_GL/rgl.h @@ -291,8 +291,7 @@ class CRender : public D3DXRenderBase GLuint texture_load(LPCSTR fname, u32& msize, GLenum& ret_desc); HRESULT shader_compile( LPCSTR name, - DWORD const* pSrcData, - UINT SrcDataLen, + IReader* fs, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, diff --git a/src/Layers/xrRenderPC_GL/rgl_shaders.cpp b/src/Layers/xrRenderPC_GL/rgl_shaders.cpp index 9f0c95162c4..cbfafbdb77b 100644 --- a/src/Layers/xrRenderPC_GL/rgl_shaders.cpp +++ b/src/Layers/xrRenderPC_GL/rgl_shaders.cpp @@ -59,7 +59,7 @@ struct SHADER_MACRO char *Define = "#define ", *Name = "\n", *Sep = "\t", *Definition = "\n", *EOL = "\n"; }; -HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcDataLen, LPCSTR pFunctionName, +HRESULT CRender::shader_compile(LPCSTR name, IReader* fs, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, void*& result) { xr_vector source, includes; @@ -77,7 +77,7 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData VERIFY(!Flags); // open included files - load_includes((LPCSTR)pSrcData, SrcDataLen, source, includes); + load_includes((LPCSTR)fs->pointer(), fs->length(), source, includes); char sh_name[MAX_PATH] = ""; u32 len = 0; diff --git a/src/Layers/xrRenderPC_R1/FStaticRender.h b/src/Layers/xrRenderPC_R1/FStaticRender.h index 6f59ba8581d..82f9bbe047b 100644 --- a/src/Layers/xrRenderPC_R1/FStaticRender.h +++ b/src/Layers/xrRenderPC_R1/FStaticRender.h @@ -116,8 +116,8 @@ class CRender : public D3DXRenderBase virtual void level_Unload() override; virtual IDirect3DBaseTexture9* texture_load(LPCSTR fname, u32& msize); - virtual HRESULT shader_compile(LPCSTR name, const DWORD* pSrcData, UINT SrcDataLen, LPCSTR pFunctionName, - LPCSTR pTarget, DWORD Flags, void*& result) override; + virtual HRESULT shader_compile(LPCSTR name, IReader* fs, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, + void*& result) override; // Information virtual void DumpStatistics(class IGameFont& font, class IPerformanceAlert* alert) override; diff --git a/src/Layers/xrRenderPC_R1/FStaticRender_Shaders.cpp b/src/Layers/xrRenderPC_R1/FStaticRender_Shaders.cpp index 336dd22ff76..b72f15f8e36 100644 --- a/src/Layers/xrRenderPC_R1/FStaticRender_Shaders.cpp +++ b/src/Layers/xrRenderPC_R1/FStaticRender_Shaders.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "FStaticRender.h" #include "Layers/xrRender/ShaderResourceTraits.h" +#include "xrCore/FileCRC32.h" template static HRESULT create_shader(LPCSTR const pTarget, DWORD const* buffer, u32 const buffer_size, LPCSTR const file_name, @@ -89,8 +90,7 @@ static inline bool match_shader_id( LPCSTR const debug_shader_id, LPCSTR const full_shader_id, FS_FileSet const& file_set, string_path& result); -HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcDataLen, LPCSTR pFunctionName, - LPCSTR pTarget, DWORD Flags, void*& result) +HRESULT CRender::shader_compile(LPCSTR name, IReader* fs, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, void*& result) { D3DXMACRO defines[128]; int def_it = 0; @@ -177,14 +177,11 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData HRESULT _result = E_FAIL; + char extension[3]; string_path folder_name, folder; - xr_strcpy(folder, "r1\\objects\\r1\\"); - xr_strcat(folder, name); - xr_strcat(folder, "."); - char extension[3]; strncpy_s(extension, pTarget, 2); - xr_strcat(folder, extension); + strconcat(sizeof(folder), folder, "r1\\objects\\r1\\", name, ".", extension); FS.update_path(folder_name, "$game_shaders$", folder); xr_strcat(folder_name, "\\"); @@ -196,12 +193,7 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData if (!match_shader_id(name, sh_name, m_file_set, temp_file_name)) { string_path file; - xr_strcpy(file, "shaders_cache\\r1\\"); - xr_strcat(file, name); - xr_strcat(file, "."); - xr_strcat(file, extension); - xr_strcat(file, "\\"); - xr_strcat(file, sh_name); + strconcat(sizeof(file), file, "shaders_cache\\r1\\", name, ".", extension, "\\", sh_name); FS.update_path(file_name, "$app_data_root$", file); } else @@ -210,15 +202,27 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData xr_strcat(file_name, temp_file_name); } + string_path shadersFolder; + FS.update_path(shadersFolder, "$game_shaders$", GEnv.Render->getShaderPath()); + + u32 fileCrc = 0; + getFileCrc32(fs, shadersFolder, fileCrc); + fs->seek(0); + if (FS.exist(file_name)) { IReader* file = FS.r_open(file_name); if (file->length() > 4) { - u32 crc = file->r_u32(); - u32 crcComp = crc32(file->pointer(), file->elapsed()); - if (crcComp == crc) - _result = create_shader(pTarget, (DWORD*)file->pointer(), file->elapsed(), file_name, result, o.disasm); + u32 savedFileCrc = file->r_u32(); + if (savedFileCrc == fileCrc) + { + u32 savedBytecodeCrc = file->r_u32(); + u32 bytecodeCrc = crc32(file->pointer(), file->elapsed()); + if (bytecodeCrc == savedBytecodeCrc) + _result = + create_shader(pTarget, (DWORD*)file->pointer(), file->elapsed(), file_name, result, o.disasm); + } } file->close(); } @@ -231,14 +235,19 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData LPD3DXCONSTANTTABLE pConstants = nullptr; LPD3DXINCLUDE pInclude = (LPD3DXINCLUDE)&Includer; - _result = D3DXCompileShader((LPCSTR)pSrcData, SrcDataLen, defines, pInclude, pFunctionName, pTarget, + _result = D3DXCompileShader((LPCSTR)fs->pointer(), fs->length(), defines, pInclude, pFunctionName, pTarget, Flags | D3DXSHADER_USE_LEGACY_D3DX9_31_DLL, &pShaderBuf, &pErrorBuf, &pConstants); if (SUCCEEDED(_result)) { IWriter* file = FS.w_open(file_name); + + file->w_u32(fileCrc); + u32 crc = crc32(pShaderBuf->GetBufferPointer(), pShaderBuf->GetBufferSize()); file->w_u32(crc); + file->w(pShaderBuf->GetBufferPointer(), (u32)pShaderBuf->GetBufferSize()); + FS.w_close(file); _result = create_shader(pTarget, (DWORD*)pShaderBuf->GetBufferPointer(), pShaderBuf->GetBufferSize(), diff --git a/src/Layers/xrRenderPC_R2/r2.h b/src/Layers/xrRenderPC_R2/r2.h index 12cb7ac7a08..77926a5067b 100644 --- a/src/Layers/xrRenderPC_R2/r2.h +++ b/src/Layers/xrRenderPC_R2/r2.h @@ -245,8 +245,8 @@ class CRender : public D3DXRenderBase virtual void level_Unload(); virtual IDirect3DBaseTexture9* texture_load(LPCSTR fname, u32& msize); - virtual HRESULT shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcDataLen, LPCSTR pFunctionName, - LPCSTR pTarget, DWORD Flags, void*& result); + virtual HRESULT shader_compile( + LPCSTR name, IReader* fs, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, void*& result); // Information virtual void DumpStatistics(class IGameFont& font, class IPerformanceAlert* alert) override; diff --git a/src/Layers/xrRenderPC_R2/r2_shaders.cpp b/src/Layers/xrRenderPC_R2/r2_shaders.cpp index 5ab560a7a32..22686a4ad07 100644 --- a/src/Layers/xrRenderPC_R2/r2_shaders.cpp +++ b/src/Layers/xrRenderPC_R2/r2_shaders.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "r2.h" #include "Layers/xrRender/ShaderResourceTraits.h" +#include "xrCore/FileCRC32.h" template static HRESULT create_shader(LPCSTR const pTarget, DWORD const* buffer, u32 const buffer_size, LPCSTR const file_name, @@ -87,8 +88,8 @@ class includer : public ID3DXInclude static inline bool match_shader_id( LPCSTR const debug_shader_id, LPCSTR const full_shader_id, FS_FileSet const& file_set, string_path& result); -HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcDataLen, LPCSTR pFunctionName, - LPCSTR pTarget, DWORD Flags, void*& result) +HRESULT CRender::shader_compile( + LPCSTR name, IReader* fs, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, void*& result) { D3DXMACRO defines[128]; int def_it = 0; @@ -439,14 +440,11 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData HRESULT _result = E_FAIL; + char extension[3]; string_path folder_name, folder; - xr_strcpy(folder, "r2\\objects\\r2\\"); - xr_strcat(folder, name); - xr_strcat(folder, "."); - char extension[3]; strncpy_s(extension, pTarget, 2); - xr_strcat(folder, extension); + strconcat(sizeof(folder), folder, "r2\\objects\\r2\\", name, ".", extension); FS.update_path(folder_name, "$game_shaders$", folder); xr_strcat(folder_name, "\\"); @@ -458,12 +456,7 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData if (!match_shader_id(name, sh_name, m_file_set, temp_file_name)) { string_path file; - xr_strcpy(file, "shaders_cache\\r2\\"); - xr_strcat(file, name); - xr_strcat(file, "."); - xr_strcat(file, extension); - xr_strcat(file, "\\"); - xr_strcat(file, sh_name); + strconcat(sizeof(file), file, "shaders_cache\\r2\\", name, ".", extension, "\\", sh_name); FS.update_path(file_name, "$app_data_root$", file); } else @@ -472,15 +465,27 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData xr_strcat(file_name, temp_file_name); } + string_path shadersFolder; + FS.update_path(shadersFolder, "$game_shaders$", GEnv.Render->getShaderPath()); + + u32 fileCrc = 0; + getFileCrc32(fs, shadersFolder, fileCrc); + fs->seek(0); + if (FS.exist(file_name)) { IReader* file = FS.r_open(file_name); if (file->length() > 4) { - u32 crc = file->r_u32(); - u32 crcComp = crc32(file->pointer(), file->elapsed()); - if (crcComp == crc) - _result = create_shader(pTarget, (DWORD*)file->pointer(), file->elapsed(), file_name, result, o.disasm); + u32 savedFileCrc = file->r_u32(); + if (savedFileCrc == fileCrc) + { + u32 savedBytecodeCrc = file->r_u32(); + u32 bytecodeCrc = crc32(file->pointer(), file->elapsed()); + if (bytecodeCrc == savedBytecodeCrc) + _result = + create_shader(pTarget, (DWORD*)file->pointer(), file->elapsed(), file_name, result, o.disasm); + } } file->close(); } @@ -501,14 +506,19 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData LPD3DXCONSTANTTABLE pConstants = nullptr; LPD3DXINCLUDE pInclude = (LPD3DXINCLUDE)&Includer; - _result = D3DXCompileShader((LPCSTR)pSrcData, SrcDataLen, defines, pInclude, pFunctionName, pTarget, + _result = D3DXCompileShader((LPCSTR)fs->pointer(), fs->length(), defines, pInclude, pFunctionName, pTarget, Flags | D3DXSHADER_USE_LEGACY_D3DX9_31_DLL, &pShaderBuf, &pErrorBuf, &pConstants); if (SUCCEEDED(_result)) { IWriter* file = FS.w_open(file_name); + + file->w_u32(fileCrc); + u32 crc = crc32(pShaderBuf->GetBufferPointer(), pShaderBuf->GetBufferSize()); file->w_u32(crc); + file->w(pShaderBuf->GetBufferPointer(), (u32)pShaderBuf->GetBufferSize()); + FS.w_close(file); _result = create_shader(pTarget, (DWORD*)pShaderBuf->GetBufferPointer(), pShaderBuf->GetBufferSize(), diff --git a/src/Layers/xrRenderPC_R3/r3.h b/src/Layers/xrRenderPC_R3/r3.h index 1eb6d515801..baae9923cb1 100644 --- a/src/Layers/xrRenderPC_R3/r3.h +++ b/src/Layers/xrRenderPC_R3/r3.h @@ -283,8 +283,8 @@ class CRender : public D3DXRenderBase virtual void level_Unload(); ID3DBaseTexture* texture_load(LPCSTR fname, u32& msize, bool bStaging = false); - virtual HRESULT shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcDataLen, LPCSTR pFunctionName, - LPCSTR pTarget, DWORD Flags, void*& result); + virtual HRESULT shader_compile( + LPCSTR name, IReader* fs, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, void*& result); // Information virtual void DumpStatistics(class IGameFont& font, class IPerformanceAlert* alert) override; diff --git a/src/Layers/xrRenderPC_R3/r3_shaders.cpp b/src/Layers/xrRenderPC_R3/r3_shaders.cpp index 2b7990682db..63540ed698f 100644 --- a/src/Layers/xrRenderPC_R3/r3_shaders.cpp +++ b/src/Layers/xrRenderPC_R3/r3_shaders.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "r3.h" #include "Layers/xrRender/ShaderResourceTraits.h" +#include "xrCore/FileCRC32.h" template static HRESULT create_shader(LPCSTR const pTarget, DWORD const* buffer, u32 const buffer_size, LPCSTR const file_name, @@ -147,8 +148,7 @@ class includer : public ID3DInclude static inline bool match_shader_id( LPCSTR const debug_shader_id, LPCSTR const full_shader_id, FS_FileSet const& file_set, string_path& result); -HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcDataLen, LPCSTR pFunctionName, - LPCSTR pTarget, DWORD Flags, void*& result) +HRESULT CRender::shader_compile(LPCSTR name, IReader* fs, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, void*& result) { D3D_SHADER_MACRO defines[128]; int def_it = 0; @@ -674,14 +674,11 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData HRESULT _result = E_FAIL; + char extension[3]; string_path folder_name, folder; - xr_strcpy(folder, "r3\\objects\\r3\\"); - xr_strcat(folder, name); - xr_strcat(folder, "."); - char extension[3]; strncpy_s(extension, pTarget, 2); - xr_strcat(folder, extension); + strconcat(sizeof(folder), folder, "r3\\objects\\r3\\", name, ".", extension); FS.update_path(folder_name, "$game_shaders$", folder); xr_strcat(folder_name, "\\"); @@ -693,12 +690,7 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData if (!match_shader_id(name, sh_name, m_file_set, temp_file_name)) { string_path file; - xr_strcpy(file, "shaders_cache\\r3\\"); - xr_strcat(file, name); - xr_strcat(file, "."); - xr_strcat(file, extension); - xr_strcat(file, "\\"); - xr_strcat(file, sh_name); + strconcat(sizeof(file), file, "shaders_cache\\r3\\", name, ".", extension, "\\", sh_name); FS.update_path(file_name, "$app_data_root$", file); } else @@ -707,15 +699,27 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData xr_strcat(file_name, temp_file_name); } + string_path shadersFolder; + FS.update_path(shadersFolder, "$game_shaders$", GEnv.Render->getShaderPath()); + + u32 fileCrc = 0; + getFileCrc32(fs, shadersFolder, fileCrc); + fs->seek(0); + if (FS.exist(file_name)) { IReader* file = FS.r_open(file_name); if (file->length() > 4) { - u32 crc = file->r_u32(); - u32 crcComp = crc32(file->pointer(), file->elapsed()); - if (crcComp == crc) - _result = create_shader(pTarget, (DWORD*)file->pointer(), file->elapsed(), file_name, result, o.disasm); + u32 savedFileCrc = file->r_u32(); + if (savedFileCrc == fileCrc) + { + u32 savedBytecodeCrc = file->r_u32(); + u32 bytecodeCrc = crc32(file->pointer(), file->elapsed()); + if (bytecodeCrc == savedBytecodeCrc) + _result = + create_shader(pTarget, (DWORD*)file->pointer(), file->elapsed(), file_name, result, o.disasm); + } } file->close(); } @@ -725,15 +729,27 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData includer Includer; LPD3DBLOB pShaderBuf = NULL; LPD3DBLOB pErrorBuf = NULL; - _result = D3DCompile( - pSrcData, SrcDataLen, "", defines, &Includer, pFunctionName, pTarget, Flags, 0, &pShaderBuf, &pErrorBuf); + _result = D3DCompile(fs->pointer(), fs->length(), "", defines, &Includer, pFunctionName, pTarget, Flags, 0, + &pShaderBuf, &pErrorBuf); +#if 0 + if (pErrorBuf) + { + std::string shaderErrStr = std::string((const char*)pErrorBuf->GetBufferPointer(), pErrorBuf->GetBufferSize()); + Msg("shader: %s \n %s", name, shaderErrStr.c_str()); + } +#endif if (SUCCEEDED(_result)) { IWriter* file = FS.w_open(file_name); - u32 crc = crc32(pShaderBuf->GetBufferPointer(), pShaderBuf->GetBufferSize()); - file->w_u32(crc); + + file->w_u32(fileCrc); + + u32 bytecodeCrc = crc32(pShaderBuf->GetBufferPointer(), pShaderBuf->GetBufferSize()); + file->w_u32(bytecodeCrc); + file->w(pShaderBuf->GetBufferPointer(), (u32)pShaderBuf->GetBufferSize()); + FS.w_close(file); _result = create_shader(pTarget, (DWORD*)pShaderBuf->GetBufferPointer(), pShaderBuf->GetBufferSize(), diff --git a/src/Layers/xrRenderPC_R4/CSCompiler.cpp b/src/Layers/xrRenderPC_R4/CSCompiler.cpp index f14fde58d05..0411d1e5dcd 100644 --- a/src/Layers/xrRenderPC_R4/CSCompiler.cpp +++ b/src/Layers/xrRenderPC_R4/CSCompiler.cpp @@ -196,7 +196,7 @@ void CSCompiler::compile(const char* name) LPCSTR c_target = "cs_5_0"; LPCSTR c_entry = "main"; - HRESULT const _hr = GEnv.Render->shader_compile(name, (DWORD const*)file->pointer(), file->length(), c_entry, + HRESULT const _hr = GEnv.Render->shader_compile(name, file, c_entry, c_target, D3D10_SHADER_PACK_MATRIX_ROW_MAJOR, (void*&)m_cs); FS.r_close(file); diff --git a/src/Layers/xrRenderPC_R4/r4.h b/src/Layers/xrRenderPC_R4/r4.h index dfbf4c46f5d..2bf37297ea5 100644 --- a/src/Layers/xrRenderPC_R4/r4.h +++ b/src/Layers/xrRenderPC_R4/r4.h @@ -289,8 +289,8 @@ class CRender : public D3DXRenderBase virtual void level_Unload(); ID3DBaseTexture* texture_load(LPCSTR fname, u32& msize, bool bStaging = false); - virtual HRESULT shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcDataLen, LPCSTR pFunctionName, - LPCSTR pTarget, DWORD Flags, void*& result); + virtual HRESULT shader_compile( + LPCSTR name, IReader* fs, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, void*& result); // Information virtual void DumpStatistics(class IGameFont& font, class IPerformanceAlert* alert) override; diff --git a/src/Layers/xrRenderPC_R4/r4_shaders.cpp b/src/Layers/xrRenderPC_R4/r4_shaders.cpp index e47b9261ecc..bca4e6a9f47 100644 --- a/src/Layers/xrRenderPC_R4/r4_shaders.cpp +++ b/src/Layers/xrRenderPC_R4/r4_shaders.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "r4.h" #include "Layers/xrRender/ShaderResourceTraits.h" +#include "xrCore/FileCRC32.h" void CRender::addShaderOption(const char* name, const char* value) { @@ -165,7 +166,7 @@ class includer : public ID3DInclude static inline bool match_shader_id( LPCSTR const debug_shader_id, LPCSTR const full_shader_id, FS_FileSet const& file_set, string_path& result); -HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcDataLen, LPCSTR pFunctionName, +HRESULT CRender::shader_compile(LPCSTR name, IReader* fs, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, void*& result) { D3D_SHADER_MACRO defines[128]; @@ -727,14 +728,11 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData HRESULT _result = E_FAIL; + char extension[3]; string_path folder_name, folder; - xr_strcpy(folder, "r3\\objects\\r4\\"); - xr_strcat(folder, name); - xr_strcat(folder, "."); - char extension[3]; strncpy_s(extension, pTarget, 2); - xr_strcat(folder, extension); + strconcat(sizeof(folder), folder, "r3\\objects\\r4\\", name, ".", extension); FS.update_path(folder_name, "$game_shaders$", folder); xr_strcat(folder_name, "\\"); @@ -746,12 +744,7 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData if (!match_shader_id(name, sh_name, m_file_set, temp_file_name)) { string_path file; - xr_strcpy(file, "shaders_cache\\r4\\"); - xr_strcat(file, name); - xr_strcat(file, "."); - xr_strcat(file, extension); - xr_strcat(file, "\\"); - xr_strcat(file, sh_name); + strconcat(sizeof(file), file, "shaders_cache\\r4\\", name, ".", extension, "\\", sh_name); FS.update_path(file_name, "$app_data_root$", file); } else @@ -760,15 +753,27 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData xr_strcat(file_name, temp_file_name); } + string_path shadersFolder; + FS.update_path(shadersFolder, "$game_shaders$", GEnv.Render->getShaderPath()); + + u32 fileCrc = 0; + getFileCrc32(fs, shadersFolder, fileCrc); + fs->seek(0); + if (FS.exist(file_name)) { IReader* file = FS.r_open(file_name); if (file->length() > 4) { - u32 crc = file->r_u32(); - u32 crcComp = crc32(file->pointer(), file->elapsed()); - if (crcComp == crc) - _result = create_shader(pTarget, (DWORD*)file->pointer(), file->elapsed(), file_name, result, o.disasm); + u32 savedFileCrc = file->r_u32(); + if (savedFileCrc == fileCrc) + { + u32 savedBytecodeCrc = file->r_u32(); + u32 bytecodeCrc = crc32(file->pointer(), file->elapsed()); + if (bytecodeCrc == savedBytecodeCrc) + _result = + create_shader(pTarget, (DWORD*)file->pointer(), file->elapsed(), file_name, result, o.disasm); + } } file->close(); } @@ -778,14 +783,26 @@ HRESULT CRender::shader_compile(LPCSTR name, DWORD const* pSrcData, UINT SrcData includer Includer; LPD3DBLOB pShaderBuf = NULL; LPD3DBLOB pErrorBuf = NULL; - _result = D3DCompile( - pSrcData, SrcDataLen, "", defines, &Includer, pFunctionName, pTarget, Flags, 0, &pShaderBuf, &pErrorBuf); + _result = D3DCompile(fs->pointer(), fs->length(), "", defines, &Includer, pFunctionName, pTarget, Flags, 0, + &pShaderBuf, &pErrorBuf); + +#if 0 + if (pErrorBuf) + { + std::string shaderErrStr = std::string((const char*)pErrorBuf->GetBufferPointer(), pErrorBuf->GetBufferSize()); + Msg("shader: %s \n %s", name, shaderErrStr.c_str()); + } +#endif if (SUCCEEDED(_result)) { IWriter* file = FS.w_open(file_name); - u32 crc = crc32(pShaderBuf->GetBufferPointer(), pShaderBuf->GetBufferSize()); - file->w_u32(crc); + + file->w_u32(fileCrc); + + u32 bytecodeCrc = crc32(pShaderBuf->GetBufferPointer(), pShaderBuf->GetBufferSize()); + file->w_u32(bytecodeCrc); + file->w(pShaderBuf->GetBufferPointer(), (u32)pShaderBuf->GetBufferSize()); FS.w_close(file); diff --git a/src/xrCore/FileCRC32.cpp b/src/xrCore/FileCRC32.cpp new file mode 100644 index 00000000000..e50f7f46733 --- /dev/null +++ b/src/xrCore/FileCRC32.cpp @@ -0,0 +1,31 @@ +#include "stdafx.h" +#include "FileCRC32.h" + +void getFileCrc32(IReader* F, LPCSTR filePath, u32& outCrc, bool parseIncludes) +{ + outCrc = crc32(F->pointer(), F->length(), outCrc); + string4096 str; + if (parseIncludes) + { + while (!F->eof()) + { + F->r_string(str, sizeof str); + _Trim(str); + if (str[0] && _Trim(str)[0] == '#' && strstr(str, "#include")) // handle includes + { + string_path inc_name; + R_ASSERT(filePath && filePath[0]); + if (_GetItem(str, 1, inc_name, '"')) + { + string_path fn; + strconcat(sizeof fn, fn, filePath, inc_name); + const xr_string inc_path = EFS_Utils::ExtractFilePath(fn); + IReader* I = FS.r_open(fn); + R_ASSERT3(I, "Can't find include file:", inc_name); + getFileCrc32(I, inc_path.c_str(), outCrc, true); + FS.r_close(I); + } + } + } + } +} diff --git a/src/xrCore/FileCRC32.h b/src/xrCore/FileCRC32.h new file mode 100644 index 00000000000..c4ac0cb8a7f --- /dev/null +++ b/src/xrCore/FileCRC32.h @@ -0,0 +1,3 @@ +#pragma once + +XRCORE_API void getFileCrc32(IReader* F, LPCSTR filePath, u32& outCrc, bool parseIncludes = true); diff --git a/src/xrCore/xrCore.vcxproj b/src/xrCore/xrCore.vcxproj index ea5504b17b9..41aca4fe250 100644 --- a/src/xrCore/xrCore.vcxproj +++ b/src/xrCore/xrCore.vcxproj @@ -227,6 +227,7 @@ + @@ -329,6 +330,7 @@ + diff --git a/src/xrCore/xrCore.vcxproj.filters b/src/xrCore/xrCore.vcxproj.filters index a6be6bbc62b..ef5ddbf78d1 100644 --- a/src/xrCore/xrCore.vcxproj.filters +++ b/src/xrCore/xrCore.vcxproj.filters @@ -309,6 +309,9 @@ Text + + FS + @@ -677,6 +680,9 @@ Text + + FS + diff --git a/src/xrEngine/Render.h b/src/xrEngine/Render.h index aa573c9496d..04e6474eca5 100644 --- a/src/xrEngine/Render.h +++ b/src/xrEngine/Render.h @@ -288,8 +288,8 @@ class ENGINE_API IRender // virtual IDirect3DBaseTexture9* texture_load (LPCSTR fname, u32& msize) = 0; void shader_option_skinning(s32 mode) { m_skinning = mode; } - virtual HRESULT shader_compile(LPCSTR name, const DWORD* pSrcData, UINT SrcDataLen, LPCSTR pFunctionName, - LPCSTR pTarget, DWORD Flags, void*& result) = 0; + virtual HRESULT shader_compile(LPCSTR name, IReader* fs, LPCSTR pFunctionName, LPCSTR pTarget, DWORD Flags, + void*& result) = 0; // Information virtual void DumpStatistics(IGameFont& font, IPerformanceAlert* alert) = 0;