Eliminated a memcpy in DX11's vertex shader disk cache loading. Maybe games will boot faster now, who knows?

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7422 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Jordan Woyak 2011-03-30 10:46:27 +00:00
parent 3d5d205c73
commit 306c3570d1
5 changed files with 59 additions and 45 deletions

View File

@ -20,6 +20,7 @@
#include "Common.h" #include "Common.h"
#include <fstream> #include <fstream>
#include <functional>
// Update this to the current SVN revision every time you change shader generation code. // 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 // 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; // value_type[value_size] value;
//} //}
template <typename K, typename V> // Example reader:
class LinearDiskCacheReader //
{ //class LinearDiskCacheReader
public: //{
virtual void Read(const K &key, const V *value, u32 value_size) = 0; //public:
}; // template <typename F>
// void operator()(const K& key, u32 value_size, F get_data) const
// {...}
//};
// Dead simple unsorted key-value store with append functionality. // Dead simple unsorted key-value store with append functionality.
// No random read functionality, all reading is done in OpenAndRead. // No random read functionality, all reading is done in OpenAndRead.
@ -67,48 +71,45 @@ class LinearDiskCache
{ {
public: public:
// return number of read entries // return number of read entries
u32 OpenAndRead(const char *filename, LinearDiskCacheReader<K, V> &reader) template <typename LinearDiskCacheReader>
u32 OpenAndRead(const char* filename, LinearDiskCacheReader& reader)
{ {
using std::ios_base; using std::ios;
// close any currently opened file // close any currently opened file
Close(); Close();
// try opening for reading/writing // 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()) if (m_file.is_open() && ValidateHeader())
{ {
// good header, read some key/value pairs // good header, read some key/value pairs
u32 num_entries = 0; u32 num_entries = 0;
K key;
V *value = NULL;
u32 value_size; u32 value_size;
K key;
while (Read(&value_size)) while (Read(&value_size) && Read(&key))
{ {
delete[] value; std::streamoff const pos = m_file.tellg();
value = new V[value_size];
// read key/value and pass to reader // pass key and value_size to reader with callback function to read the data
if (Read(&key) && Read(value, value_size)) reader(key, value_size, [this, &value_size](V* data){ Read(data, value_size); });
reader.Read(key, value, value_size);
else // seek past data (in case reader didn't read it for whatever reason)
break; m_file.seekg(pos + (value_size * sizeof(V)), ios::beg);
++num_entries; ++num_entries;
} }
m_file.clear(); m_file.clear();
delete[] value;
return num_entries; return num_entries;
} }
// failed to open file for reading or bad header // failed to open file for reading or bad header
// close and recreate file // close and recreate file
Close(); 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(); WriteHeader();
return 0; return 0;
} }

View File

@ -306,12 +306,16 @@ ID3D11Buffer*const& PixelShaderCache::GetConstantBuffer()
} }
// this class will load the precompiled shaders into our cache // this class will load the precompiled shaders into our cache
class PixelShaderCacheInserter : public LinearDiskCacheReader<PIXELSHADERUID, u8> class PixelShaderCacheInserter
{ {
public: public:
void Read(const PIXELSHADERUID &key, const u8 *value, u32 value_size) template <typename F>
void operator()(const PIXELSHADERUID& key, u32 value_size, F get_data) const
{ {
PixelShaderCache::InsertByteCode(key, value, value_size); std::unique_ptr<u8[]> value(new u8[value_size]);
get_data(value.get());
PixelShaderCache::InsertByteCode(key, value.get(), value_size);
} }
}; };
@ -354,8 +358,8 @@ void PixelShaderCache::Init()
char cache_filename[MAX_PATH]; char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx11-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), sprintf(cache_filename, "%sdx11-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.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. // ONLY to be used during shutdown.

View File

@ -68,14 +68,15 @@ ID3D11Buffer*const& VertexShaderCache::GetConstantBuffer()
} }
// this class will load the precompiled shaders into our cache // this class will load the precompiled shaders into our cache
class VertexShaderCacheInserter : public LinearDiskCacheReader<VERTEXSHADERUID, u8> class VertexShaderCacheInserter
{ {
public: public:
void Read(const VERTEXSHADERUID &key, const u8 *value, u32 value_size) template <typename F>
void operator()(const VERTEXSHADERUID& key, u32 value_size, F get_data) const
{ {
ID3D10Blob* blob = nullptr; ID3D10Blob* blob = nullptr;
PD3D10CreateBlob(value_size, &blob); 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<ID3D10Blob>::FromPtr(blob)); VertexShaderCache::InsertByteCode(key, SharedPtr<ID3D10Blob>::FromPtr(blob));
} }
@ -177,8 +178,8 @@ void VertexShaderCache::Init()
char cache_filename[MAX_PATH]; char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx11-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), sprintf(cache_filename, "%sdx11-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
VertexShaderCacheInserter inserter;
g_vs_disk_cache.OpenAndRead(cache_filename, inserter); g_vs_disk_cache.OpenAndRead(cache_filename, VertexShaderCacheInserter());
} }
void VertexShaderCache::Clear() void VertexShaderCache::Clear()

View File

@ -66,12 +66,16 @@ static LPDIRECT3DPIXELSHADER9 s_ClearProgram = NULL;
static LPDIRECT3DPIXELSHADER9 s_rgba6_to_rgb8 = NULL; static LPDIRECT3DPIXELSHADER9 s_rgba6_to_rgb8 = NULL;
static LPDIRECT3DPIXELSHADER9 s_rgb8_to_rgba6 = NULL; static LPDIRECT3DPIXELSHADER9 s_rgb8_to_rgba6 = NULL;
class PixelShaderCacheInserter : public LinearDiskCacheReader<PIXELSHADERUID, u8> class PixelShaderCacheInserter
{ {
public: public:
void Read(const PIXELSHADERUID &key, const u8 *value, u32 value_size) template <typename F>
void operator()(const PIXELSHADERUID& key, u32 value_size, F get_data) const
{ {
PixelShaderCache::InsertByteCode(key, value, value_size, false); std::unique_ptr<u8[]> 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]; char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx9-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), sprintf(cache_filename, "%sdx9-%s-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.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. // ONLY to be used during shutdown.

View File

@ -57,12 +57,16 @@ LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetClearVertexShader()
} }
// this class will load the precompiled shaders into our cache // this class will load the precompiled shaders into our cache
class VertexShaderCacheInserter : public LinearDiskCacheReader<VERTEXSHADERUID, u8> class VertexShaderCacheInserter
{ {
public: public:
void Read(const VERTEXSHADERUID &key, const u8 *value, u32 value_size) template <typename F>
void operator()(const VERTEXSHADERUID& key, u32 value_size, F get_data) const
{ {
VertexShaderCache::InsertByteCode(key, value, value_size, false); std::unique_ptr<u8[]> value(new u8[value_size]);
get_data(value.get());
VertexShaderCache::InsertByteCode(key, value.get(), value_size, false);
} }
}; };
@ -149,8 +153,8 @@ void VertexShaderCache::Init()
char cache_filename[MAX_PATH]; char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(), sprintf(cache_filename, "%sdx9-%s-vs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
VertexShaderCacheInserter inserter;
g_vs_disk_cache.OpenAndRead(cache_filename, inserter); g_vs_disk_cache.OpenAndRead(cache_filename, VertexShaderCacheInserter());
} }
void VertexShaderCache::Clear() void VertexShaderCache::Clear()