diff --git a/Source/Core/Common/Src/LinearDiskCache.h b/Source/Core/Common/Src/LinearDiskCache.h index 7a124aaa7b..6ead5a8b7f 100644 --- a/Source/Core/Common/Src/LinearDiskCache.h +++ b/Source/Core/Common/Src/LinearDiskCache.h @@ -20,6 +20,7 @@ #include "Common.h" #include +#include // Update this to the current SVN revision every time you change shader generation code. // We don't automatically get this from SVN_REV because that would mean regenerating the @@ -43,12 +44,15 @@ enum // value_type[value_size] value; //} -template -class LinearDiskCacheReader -{ -public: - virtual void Read(const K &key, const V *value, u32 value_size) = 0; -}; +// Example reader: +// +//class LinearDiskCacheReader +//{ +//public: +// template +// void operator()(const K& key, u32 value_size, F get_data) const +// {...} +//}; // Dead simple unsorted key-value store with append functionality. // No random read functionality, all reading is done in OpenAndRead. @@ -67,48 +71,45 @@ class LinearDiskCache { public: // return number of read entries - u32 OpenAndRead(const char *filename, LinearDiskCacheReader &reader) + template + u32 OpenAndRead(const char* filename, LinearDiskCacheReader& reader) { - using std::ios_base; + using std::ios; // close any currently opened file Close(); // try opening for reading/writing - m_file.open(filename, ios_base::in | ios_base::out | ios_base::binary | ios_base::app); + m_file.open(filename, ios::in | ios::out | ios::binary | ios::app); if (m_file.is_open() && ValidateHeader()) { // good header, read some key/value pairs u32 num_entries = 0; - K key; - V *value = NULL; u32 value_size; - - while (Read(&value_size)) + K key; + while (Read(&value_size) && Read(&key)) { - delete[] value; - value = new V[value_size]; + std::streamoff const pos = m_file.tellg(); - // read key/value and pass to reader - if (Read(&key) && Read(value, value_size)) - reader.Read(key, value, value_size); - else - break; + // pass key and value_size to reader with callback function to read the data + reader(key, value_size, [this, &value_size](V* data){ Read(data, value_size); }); + + // seek past data (in case reader didn't read it for whatever reason) + m_file.seekg(pos + (value_size * sizeof(V)), ios::beg); ++num_entries; } m_file.clear(); - delete[] value; return num_entries; } // failed to open file for reading or bad header // close and recreate file Close(); - m_file.open(filename, ios_base::out | ios_base::trunc | ios_base::binary); + m_file.open(filename, ios::out | ios::trunc | ios::binary); WriteHeader(); return 0; } diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp index 8a0249d758..d5b1628f11 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp @@ -306,12 +306,16 @@ ID3D11Buffer*const& PixelShaderCache::GetConstantBuffer() } // this class will load the precompiled shaders into our cache -class PixelShaderCacheInserter : public LinearDiskCacheReader +class PixelShaderCacheInserter { public: - void Read(const PIXELSHADERUID &key, const u8 *value, u32 value_size) + template + void operator()(const PIXELSHADERUID& key, u32 value_size, F get_data) const { - PixelShaderCache::InsertByteCode(key, value, value_size); + std::unique_ptr value(new u8[value_size]); + get_data(value.get()); + + PixelShaderCache::InsertByteCode(key, value.get(), value_size); } }; @@ -353,9 +357,9 @@ void PixelShaderCache::Init() char cache_filename[MAX_PATH]; sprintf(cache_filename, "%sdx11-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); - PixelShaderCacheInserter inserter; - g_ps_disk_cache.OpenAndRead(cache_filename, inserter); + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); + + g_ps_disk_cache.OpenAndRead(cache_filename, PixelShaderCacheInserter()); } // ONLY to be used during shutdown. diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp index 9737abe137..0ac6cbb563 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexShaderCache.cpp @@ -68,14 +68,15 @@ ID3D11Buffer*const& VertexShaderCache::GetConstantBuffer() } // this class will load the precompiled shaders into our cache -class VertexShaderCacheInserter : public LinearDiskCacheReader +class VertexShaderCacheInserter { public: - void Read(const VERTEXSHADERUID &key, const u8 *value, u32 value_size) + template + void operator()(const VERTEXSHADERUID& key, u32 value_size, F get_data) const { ID3D10Blob* blob = nullptr; PD3D10CreateBlob(value_size, &blob); - memcpy(blob->GetBufferPointer(), value, value_size); // TODO: i would like to eliminate this memcpy + get_data((u8*)blob->GetBufferPointer()); // read data from file into blob VertexShaderCache::InsertByteCode(key, SharedPtr::FromPtr(blob)); } @@ -176,9 +177,9 @@ void VertexShaderCache::Init() char cache_filename[MAX_PATH]; sprintf(cache_filename, "%sdx11-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); - VertexShaderCacheInserter inserter; - g_vs_disk_cache.OpenAndRead(cache_filename, inserter); + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); + + g_vs_disk_cache.OpenAndRead(cache_filename, VertexShaderCacheInserter()); } void VertexShaderCache::Clear() diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp index 1ac5d5d20f..d34625a60f 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp @@ -66,12 +66,16 @@ static LPDIRECT3DPIXELSHADER9 s_ClearProgram = NULL; static LPDIRECT3DPIXELSHADER9 s_rgba6_to_rgb8 = NULL; static LPDIRECT3DPIXELSHADER9 s_rgb8_to_rgba6 = NULL; -class PixelShaderCacheInserter : public LinearDiskCacheReader +class PixelShaderCacheInserter { public: - void Read(const PIXELSHADERUID &key, const u8 *value, u32 value_size) + template + void operator()(const PIXELSHADERUID& key, u32 value_size, F get_data) const { - PixelShaderCache::InsertByteCode(key, value, value_size, false); + std::unique_ptr value(new u8[value_size]); + get_data(value.get()); + + PixelShaderCache::InsertByteCode(key, value.get(), value_size, false); } }; @@ -281,8 +285,8 @@ void PixelShaderCache::Init() char cache_filename[MAX_PATH]; sprintf(cache_filename, "%sdx9-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); - PixelShaderCacheInserter inserter; - g_ps_disk_cache.OpenAndRead(cache_filename, inserter); + + g_ps_disk_cache.OpenAndRead(cache_filename, PixelShaderCacheInserter()); } // ONLY to be used during shutdown. diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp index 15fd5aab4e..f0ed678ec9 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp @@ -57,12 +57,16 @@ LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetClearVertexShader() } // this class will load the precompiled shaders into our cache -class VertexShaderCacheInserter : public LinearDiskCacheReader +class VertexShaderCacheInserter { public: - void Read(const VERTEXSHADERUID &key, const u8 *value, u32 value_size) + template + void operator()(const VERTEXSHADERUID& key, u32 value_size, F get_data) const { - VertexShaderCache::InsertByteCode(key, value, value_size, false); + std::unique_ptr value(new u8[value_size]); + get_data(value.get()); + + VertexShaderCache::InsertByteCode(key, value.get(), value_size, false); } }; @@ -148,9 +152,9 @@ void VertexShaderCache::Init() char cache_filename[MAX_PATH]; sprintf(cache_filename, "%sdx9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); - VertexShaderCacheInserter inserter; - g_vs_disk_cache.OpenAndRead(cache_filename, inserter); + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); + + g_vs_disk_cache.OpenAndRead(cache_filename, VertexShaderCacheInserter()); } void VertexShaderCache::Clear()