mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Replace the shader uid system with a new one which quasi-automatically generates uids for shaders.
Currently used in the vertex shader only (had to fork lighting shaders for now).
This commit is contained in:
@@ -131,7 +131,7 @@ void GFXDebuggerBase::DumpVertexShader(const char* path)
|
||||
sprintf(filename, "%sdump_vs.txt", path);
|
||||
|
||||
File::CreateEmptyFile(filename);
|
||||
File::WriteStringToFile(true, GenerateVertexShaderCode(g_nativeVertexFmt->m_components, g_ActiveConfig.backend_info.APIType), filename);
|
||||
/// File::WriteStringToFile(true, GenerateVertexShaderCode(g_nativeVertexFmt->m_components, g_ActiveConfig.backend_info.APIType), filename);
|
||||
}
|
||||
|
||||
void GFXDebuggerBase::DumpPixelShaderConstants(const char* path)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,7 @@
|
||||
#ifndef GCOGL_VERTEXSHADER_H
|
||||
#define GCOGL_VERTEXSHADER_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "XFMemory.h"
|
||||
#include "VideoCommon.h"
|
||||
|
||||
@@ -48,71 +49,106 @@
|
||||
#define C_DEPTHPARAMS (C_POSTTRANSFORMMATRICES + 64)
|
||||
#define C_VENVCONST_END (C_DEPTHPARAMS + 4)
|
||||
|
||||
template<bool safe>
|
||||
class _VERTEXSHADERUID
|
||||
// TODO: Need packing?
|
||||
struct uid_data
|
||||
{
|
||||
u32 components;
|
||||
u32 numColorChans : 2;
|
||||
u32 numTexGens : 4;
|
||||
|
||||
struct {
|
||||
u32 projection : 1; // XF_TEXPROJ_X
|
||||
u32 inputform : 2; // XF_TEXINPUT_X
|
||||
u32 texgentype : 3; // XF_TEXGEN_X
|
||||
u32 sourcerow : 5; // XF_SRCGEOM_X
|
||||
u32 embosssourceshift : 3; // what generated texcoord to use
|
||||
u32 embosslightshift : 3; // light index that is used
|
||||
} texMtxInfo[8];
|
||||
struct {
|
||||
u32 index : 6; // base row of dual transform matrix
|
||||
u32 normalize : 1; // normalize before send operation
|
||||
} postMtxInfo[8];
|
||||
struct {
|
||||
u32 enabled : 1;
|
||||
} dualTexTrans;
|
||||
struct {
|
||||
u32 matsource : 1;
|
||||
u32 enablelighting : 1;
|
||||
u32 ambsource : 1;
|
||||
u32 diffusefunc : 2;
|
||||
u32 attnfunc : 2;
|
||||
u32 light_mask : 8;
|
||||
} lit_chans[4];
|
||||
};
|
||||
|
||||
|
||||
class ShaderUid
|
||||
{
|
||||
#define NUM_VSUID_VALUES_SAFE 25
|
||||
public:
|
||||
u32 values[safe ? NUM_VSUID_VALUES_SAFE : 9];
|
||||
|
||||
_VERTEXSHADERUID()
|
||||
ShaderUid()
|
||||
{
|
||||
memset(values, 0, sizeof(values));
|
||||
}
|
||||
|
||||
_VERTEXSHADERUID(const _VERTEXSHADERUID& r)
|
||||
void Write(const char* fmt, ...) {}
|
||||
const char* GetBuffer() { return NULL; }
|
||||
void SetBuffer(char* buffer) { }
|
||||
|
||||
bool operator == (const ShaderUid& obj) const
|
||||
{
|
||||
for (size_t i = 0; i < sizeof(values) / sizeof(u32); ++i)
|
||||
values[i] = r.values[i];
|
||||
return memcmp(this->values, obj.values, sizeof(values)) == 0;
|
||||
}
|
||||
|
||||
int GetNumValues() const
|
||||
// TODO: Store last frame used and order by that? makes much more sense anyway...
|
||||
bool operator < (const ShaderUid& obj) const
|
||||
{
|
||||
if (safe) return NUM_VSUID_VALUES_SAFE;
|
||||
else return (((values[0] >> 23) & 0xf) * 3 + 3) / 4 + 3; // numTexGens*3/4+1
|
||||
}
|
||||
|
||||
bool operator <(const _VERTEXSHADERUID& _Right) const
|
||||
{
|
||||
if (values[0] < _Right.values[0])
|
||||
return true;
|
||||
else if (values[0] > _Right.values[0])
|
||||
return false;
|
||||
int N = GetNumValues();
|
||||
for (int i = 1; i < N; ++i)
|
||||
for (int i = 0; i < 24; ++i)
|
||||
{
|
||||
if (values[i] < _Right.values[i])
|
||||
if (this->values[i] < obj.values[i])
|
||||
return true;
|
||||
else if (values[i] > _Right.values[i])
|
||||
else if (this->values[i] > obj.values[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator ==(const _VERTEXSHADERUID& _Right) const
|
||||
uid_data& GetUidData() { return data; }
|
||||
|
||||
private:
|
||||
union
|
||||
{
|
||||
if (values[0] != _Right.values[0])
|
||||
return false;
|
||||
int N = GetNumValues();
|
||||
for (int i = 1; i < N; ++i)
|
||||
{
|
||||
if (values[i] != _Right.values[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
uid_data data;
|
||||
u32 values[24]; // TODO: Length?
|
||||
};
|
||||
};
|
||||
typedef _VERTEXSHADERUID<false> VERTEXSHADERUID;
|
||||
typedef _VERTEXSHADERUID<true> VERTEXSHADERUIDSAFE;
|
||||
|
||||
class ShaderCode
|
||||
{
|
||||
public:
|
||||
ShaderCode() : buf(NULL), write_ptr(NULL)
|
||||
{
|
||||
|
||||
// components is included in the uid.
|
||||
char* GenerateVSOutputStruct(char* p, u32 components, API_TYPE api_type);
|
||||
const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type);
|
||||
}
|
||||
|
||||
void GetVertexShaderId(VERTEXSHADERUID *uid, u32 components);
|
||||
void GetSafeVertexShaderId(VERTEXSHADERUIDSAFE *uid, u32 components);
|
||||
void Write(const char* fmt, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
va_start(arglist, fmt);
|
||||
write_ptr += vsprintf(write_ptr, fmt, arglist);
|
||||
va_end(arglist);
|
||||
}
|
||||
|
||||
const char* GetBuffer() { return buf; }
|
||||
void SetBuffer(char* buffer) { buf = buffer; write_ptr = buffer; }
|
||||
uid_data& GetUidData() { return *(uid_data*)NULL; }
|
||||
|
||||
private:
|
||||
const char* buf;
|
||||
char* write_ptr;
|
||||
};
|
||||
|
||||
void GenerateShaderUid(ShaderUid& object, u32 components, API_TYPE api_type);
|
||||
void GenerateShaderCode(ShaderCode& object, u32 components, API_TYPE api_type);
|
||||
|
||||
// Used to make sure that our optimized vertex shader IDs don't lose any possible shader code changes
|
||||
void ValidateVertexShaderIDs(API_TYPE api, VERTEXSHADERUIDSAFE old_id, const std::string& old_code, u32 components);
|
||||
|
||||
#endif // GCOGL_VERTEXSHADER_H
|
||||
|
||||
@@ -42,7 +42,7 @@ GLuint VertexShaderCache::CurrentShader;
|
||||
bool VertexShaderCache::ShaderEnabled;
|
||||
|
||||
VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry = NULL;
|
||||
VERTEXSHADERUID VertexShaderCache::last_uid;
|
||||
ShaderUid VertexShaderCache::last_uid;
|
||||
|
||||
static int s_nMaxVertexInstructions;
|
||||
|
||||
@@ -74,14 +74,14 @@ void VertexShaderCache::Shutdown()
|
||||
|
||||
VERTEXSHADER* VertexShaderCache::SetShader(u32 components)
|
||||
{
|
||||
VERTEXSHADERUID uid;
|
||||
GetVertexShaderId(&uid, components);
|
||||
// Possible optimization: Don't always generate the shader uid, but keep track of changes in BPStructs instead
|
||||
ShaderUid uid;
|
||||
GenerateShaderUid(uid, components, API_OPENGL);
|
||||
if (last_entry)
|
||||
{
|
||||
if (uid == last_uid)
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
|
||||
ValidateVertexShaderIDs(API_OPENGL, vshaders[uid].safe_uid, vshaders[uid].shader.strprog, components);
|
||||
return &last_entry->shader;
|
||||
}
|
||||
}
|
||||
@@ -95,15 +95,14 @@ VERTEXSHADER* VertexShaderCache::SetShader(u32 components)
|
||||
last_entry = &entry;
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
|
||||
ValidateVertexShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, components);
|
||||
return &last_entry->shader;
|
||||
}
|
||||
|
||||
// Make an entry in the table
|
||||
VSCacheEntry& entry = vshaders[uid];
|
||||
last_entry = &entry;
|
||||
const char *code = GenerateVertexShaderCode(components, API_OPENGL);
|
||||
GetSafeVertexShaderId(&entry.safe_uid, components);
|
||||
ShaderCode code;
|
||||
GenerateShaderCode(code, components, API_OPENGL);
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
|
||||
@@ -111,11 +110,11 @@ VERTEXSHADER* VertexShaderCache::SetShader(u32 components)
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
|
||||
|
||||
SaveData(szTemp, code);
|
||||
SaveData(szTemp, code.GetBuffer());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!code || !VertexShaderCache::CompileVertexShader(entry.shader, code)) {
|
||||
if (!code.GetBuffer() || !VertexShaderCache::CompileVertexShader(entry.shader, code.GetBuffer())) {
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class VertexShaderCache
|
||||
struct VSCacheEntry
|
||||
{
|
||||
VERTEXSHADER shader;
|
||||
VERTEXSHADERUIDSAFE safe_uid;
|
||||
ShaderUid safe_uid;
|
||||
VSCacheEntry() {}
|
||||
void Destroy() {
|
||||
// printf("Destroying vs %i\n", shader.glprogid);
|
||||
@@ -49,12 +49,12 @@ class VertexShaderCache
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
|
||||
typedef std::map<ShaderUid, VSCacheEntry> VSCache;
|
||||
|
||||
static VSCache vshaders;
|
||||
|
||||
static VSCacheEntry* last_entry;
|
||||
static VERTEXSHADERUID last_uid;
|
||||
static ShaderUid last_uid; // TODO: Use reference instead..
|
||||
|
||||
static GLuint CurrentShader;
|
||||
static bool ShaderEnabled;
|
||||
|
||||
Reference in New Issue
Block a user