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:
parent
3d5d205c73
commit
306c3570d1
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -353,9 +357,9 @@ 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.
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -176,9 +177,9 @@ 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()
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -148,9 +152,9 @@ 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()
|
||||||
|
|
Loading…
Reference in New Issue