Shader Disk Cache implementation for D3D. Saves generated shaders on disk. Eliminates "freeze jerks" in D3D plugin the _second_ and later times you play something.... not much to do about the first time. The D3D shader compiler is just slow.

Also assorted cleanup around the shader code.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4869 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard
2010-01-17 17:44:09 +00:00
parent f599fdcec5
commit 3e01152793
24 changed files with 551 additions and 265 deletions

View File

@ -78,9 +78,9 @@ void PixelShaderCache::Init()
{
GL_REPORT_ERRORD();
for( int i=0;i<(C_COLORMATRIX+16)*4;i++)
for (int i = 0; i < (C_COLORMATRIX+16) * 4; i++)
lastPSconstants[i/4][i%4] = -100000000.0f;
memset(&last_pixel_shader_uid,0xFF,sizeof(last_pixel_shader_uid));
memset(&last_pixel_shader_uid, 0xFF, sizeof(last_pixel_shader_uid));
s_displayCompileAlert = true;
@ -172,8 +172,7 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
{
DVSTARTPROFILE();
PIXELSHADERUID uid;
u32 dstAlpha = dstAlphaEnable ? 1 : 0;
GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), dstAlpha);
GetPixelShaderId(&uid, PixelShaderManager::GetTextureMask(), dstAlphaEnable ? 1 : 0);
if (uid == last_pixel_shader_uid && pshaders[uid].frameCount == frameCount)
{
return pShaderLast;
@ -194,14 +193,12 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
return pShaderLast;
}
//Make an entry in the table
PSCacheEntry& newentry = pshaders[uid];
newentry.frameCount = frameCount;
pShaderLast = &newentry.shader;
const char *code = GeneratePixelShader(PixelShaderManager::GetTextureMask(),
dstAlphaEnable);
const char *code = GeneratePixelShaderCode(PixelShaderManager::GetTextureMask(),
dstAlphaEnable);
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
@ -218,34 +215,12 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
ERROR_LOG(VIDEO, "failed to create pixel shader");
return NULL;
}
INCSTAT(stats.numPixelShadersCreated);
SETSTAT(stats.numPixelShadersAlive, pshaders.size());
return pShaderLast;
}
void PixelShaderCache::ProgressiveCleanup()
{
/*
PSCache::iterator iter = pshaders.begin();
while (iter != pshaders.end()) {
PSCacheEntry &entry = iter->second;
if (entry.frameCount < frameCount - 400) {
entry.Destroy();
#ifdef _WIN32
iter = pshaders.erase(iter);
#else
pshaders.erase(iter++); // (this is gcc standard!)
#endif
}
else
iter++;
}
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
*/
}
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
{
GLenum err = GL_REPORT_ERROR();
@ -268,7 +243,7 @@ bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrpr
}
// handle warnings
if(cgGetError() != CG_NO_ERROR)
if (cgGetError() != CG_NO_ERROR)
{
WARN_LOG(VIDEO, "Warnings on compile ps %s:", cgGetLastListing(g_cgcontext));
WARN_LOG(VIDEO, pstrprogram);

View File

@ -69,7 +69,6 @@ class PixelShaderCache
public:
static void Init();
static void ProgressiveCleanup();
static void Shutdown();
static FRAGMENTSHADER* GetShader(bool dstAlphaEnable);

View File

@ -1054,10 +1054,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
GL_REPORT_ERRORD();
// Clean out old stuff from caches
// Clean out old stuff from caches. It's not worth it to clean out the shader caches.
DLCache::ProgressiveCleanup();
VertexShaderCache::ProgressiveCleanup();
PixelShaderCache::ProgressiveCleanup();
TextureMngr::ProgressiveCleanup();
frameCount++;

View File

@ -47,7 +47,7 @@ static float GC_ALIGNED16(lastVSconstants[C_FOGPARAMS+8][4]);
void SetVSConstant4f(int const_number, float f1, float f2, float f3, float f4)
{
if( lastVSconstants[const_number][0] != f1 ||
if ( lastVSconstants[const_number][0] != f1 ||
lastVSconstants[const_number][1] != f2 ||
lastVSconstants[const_number][2] != f3 ||
lastVSconstants[const_number][3] != f4)
@ -114,9 +114,9 @@ void SetMultiVSConstant3fv(int const_number, int count, const float *f)
void VertexShaderCache::Init()
{
for( int i=0;i<(C_FOGPARAMS+8)*4;i++)
lastVSconstants[i/4][i%4] = -100000000.0f;
memset(&last_vertex_shader_uid,0xFF,sizeof(last_vertex_shader_uid));
for (int i = 0; i < (C_FOGPARAMS + 8) * 4; i++)
lastVSconstants[i / 4][i % 4] = -100000000.0f;
memset(&last_vertex_shader_uid, 0xFF, sizeof(last_vertex_shader_uid));
s_displayCompileAlert = true;
@ -138,7 +138,7 @@ VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
{
DVSTARTPROFILE();
VERTEXSHADERUID uid;
GetVertexShaderId(uid, components);
GetVertexShaderId(&uid, components);
if (uid == last_vertex_shader_uid && vshaders[uid].frameCount == frameCount)
{
@ -163,7 +163,7 @@ VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
VSCacheEntry& entry = vshaders[uid];
entry.frameCount = frameCount;
pShaderLast = &entry.shader;
const char *code = GenerateVertexShader(components, false);
const char *code = GenerateVertexShaderCode(components, false);
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
@ -185,29 +185,6 @@ VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
return pShaderLast;
}
void VertexShaderCache::ProgressiveCleanup()
{
/*
VSCache::iterator iter = vshaders.begin();
while (iter != vshaders.end()) {
VSCacheEntry &entry = iter->second;
if (entry.frameCount < frameCount - 200) {
entry.Destroy();
#ifdef _WIN32
iter = vshaders.erase(iter);
#else
vshaders.erase(iter++);
#endif
}
else {
++iter;
}
}
SETSTAT(stats.numVertexShadersAlive, vshaders.size());
*/
}
bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
{
// Reset GL error before compiling shaders. Yeah, we need to investigate the causes of these.
@ -232,7 +209,7 @@ bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrpr
return false;
}
if(cgGetError() != CG_NO_ERROR)
if (cgGetError() != CG_NO_ERROR)
{
WARN_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext));
WARN_LOG(VIDEO, pstrprogram);
@ -249,8 +226,7 @@ bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrpr
}
glGenProgramsARB(1, &vs.glprogid);
EnableShader(vs.glprogid);
//glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vs.glprogid);
//CurrentShader = vs.glprogid;
glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
err = GL_REPORT_ERROR();
if (err != GL_NO_ERROR) {
@ -263,13 +239,13 @@ bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrpr
#if defined(_DEBUG) || defined(DEBUGFAST)
vs.strprog = pstrprogram;
#endif
return true;
}
void VertexShaderCache::DisableShader()
{
//if(ShaderEnabled)
//if (ShaderEnabled)
{
CurrentShader = 0;
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
@ -278,9 +254,11 @@ void VertexShaderCache::DisableShader()
}
}
// TODO: Why are these if statements commented out?
void VertexShaderCache::SetCurrentShader(GLuint Shader)
{
//if(ShaderEnabled && CurrentShader != Shader)
//if (ShaderEnabled && CurrentShader != Shader)
{
CurrentShader = Shader;
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
@ -289,13 +267,13 @@ void VertexShaderCache::SetCurrentShader(GLuint Shader)
void VertexShaderCache::EnableShader(GLuint Shader)
{
//if(!ShaderEnabled)
//if (!ShaderEnabled)
{
glEnable(GL_VERTEX_PROGRAM_ARB);
ShaderEnabled= true;
CurrentShader = 0;
}
//if(CurrentShader != Shader)
//if (CurrentShader != Shader)
{
CurrentShader = Shader;
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);

View File

@ -59,7 +59,6 @@ class VertexShaderCache
public:
static void Init();
static void ProgressiveCleanup();
static void Shutdown();
static VERTEXSHADER* GetShader(u32 components);