Added shader dump option to GL plugin. glScissor is always set, even when copying to EFB. Indirect texturing and alpha blending fixes. Changed determination if texture dimension recalculation is needed - this might break stuff! Let me know if there are issues so it can be tweaked.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@739 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
donkopunchstania 2008-10-02 03:26:08 +00:00
parent f83057262b
commit a1837662a0
8 changed files with 131 additions and 71 deletions

View File

@ -675,10 +675,11 @@ void LoadBPReg(u32 value0)
u32 nRestoreZBufferTarget = Renderer::GetZBufferTarget(); u32 nRestoreZBufferTarget = Renderer::GetZBufferTarget();
glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight()); glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight());
// if copied to texture, set the dimensions to the source copy dims, otherwise, clear the entire buffer
if( PE_copy.copy_to_xfb == 0 ) // Always set the scissor in case it was set by the game and has not been reset
glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom), glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom),
(multirc.right - multirc.left), (multirc.bottom - multirc.top)); (multirc.right - multirc.left), (multirc.bottom - multirc.top));
VertexShaderMngr::SetViewportChanged(); VertexShaderMngr::SetViewportChanged();
// since clear operations use the source rectangle, have to do regular renders (glClear clears the entire buffer) // since clear operations use the source rectangle, have to do regular renders (glClear clears the entire buffer)
@ -724,7 +725,6 @@ void LoadBPReg(u32 value0)
glDrawBuffers(2, s_drawbuffers); glDrawBuffers(2, s_drawbuffers);
} }
if( PE_copy.copy_to_xfb == 0 )
SetScissorRect(); // reset the scissor rect SetScissorRect(); // reset the scissor rect
} }
} }

View File

@ -71,6 +71,7 @@ void Config::Load()
iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0); iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0);
iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0); iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0);
iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0); iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0);
iniFile.Get("Settings", "LogLevel", &iLog, 0);
iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0); iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0);
if(iMultisampleMode == 0) if(iMultisampleMode == 0)
iMultisampleMode = 1; iMultisampleMode = 1;
@ -107,6 +108,7 @@ void Config::Save()
iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel); iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel);
iniFile.Set("Settings", "DumpTextures", bDumpTextures); iniFile.Set("Settings", "DumpTextures", bDumpTextures);
iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors); iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors);
iniFile.Set("Settings", "LogLevel", iLog);
iniFile.Set("Settings", "Multisample", iMultisampleMode); iniFile.Set("Settings", "Multisample", iMultisampleMode);
iniFile.Set("Settings", "TexDumpPath", texDumpPath); iniFile.Set("Settings", "TexDumpPath", texDumpPath);
iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable); iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable);
@ -185,6 +187,17 @@ bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int he
return SaveTGA(filename, width, height, &data[0]); return SaveTGA(filename, width, height, &data[0]);
} }
bool SaveData(const char* filename, const char* data)
{
FILE* f = fopen(filename, "wb");
if (f == NULL)
return false;
fwrite(data, strlen(data), 1, f);
fclose(f);
return true;
}
#ifdef _WIN32 #ifdef _WIN32
// The one for Linux is in Linux/Linux.cpp // The one for Linux is in Linux/Linux.cpp
static HANDLE hConsole = NULL; static HANDLE hConsole = NULL;

View File

@ -117,6 +117,7 @@ extern int frameCount;
#define CONF_PRIMLOG 2 #define CONF_PRIMLOG 2
#define CONF_SAVETEXTURES 4 #define CONF_SAVETEXTURES 4
#define CONF_SAVETARGETS 8 #define CONF_SAVETARGETS 8
#define CONF_SAVESHADERS 16
struct Config struct Config
{ {
@ -226,6 +227,7 @@ void HandleGLError();
void InitLUTs(); void InitLUTs();
bool SaveTGA(const char* filename, int width, int height, void* pdata); bool SaveTGA(const char* filename, int width, int height, void* pdata);
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height); bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height);
bool SaveData(const char* filename, const char* pdata);
#if defined(_MSC_VER) && !defined(__x86_64__) && !defined(_M_X64) #if defined(_MSC_VER) && !defined(__x86_64__) && !defined(_M_X64)
void * memcpy_amd(void *dest, const void *src, size_t n); void * memcpy_amd(void *dest, const void *src, size_t n);

View File

@ -422,6 +422,7 @@ char *GeneratePixelShader(u32 texture_mask, bool has_zbuffer_target, bool bRende
if( !WriteAlphaTest(p) ) { if( !WriteAlphaTest(p) ) {
// alpha test will always fail, so restart the shader and just make it an empty function // alpha test will always fail, so restart the shader and just make it an empty function
p = pmainstart; p = pmainstart;
WRITE(p, "discard;\n");
WRITE(p, "ocol0 = 0;\n"); WRITE(p, "ocol0 = 0;\n");
} }
else { else {
@ -449,7 +450,6 @@ char *GeneratePixelShader(u32 texture_mask, bool has_zbuffer_target, bool bRende
WRITE(p, "ocol1 = frac(float4(256.0f*256.0f, 256.0f, 1.0f, 0.0f) * uv%d.w);\n", ztexcoord); WRITE(p, "ocol1 = frac(float4(256.0f*256.0f, 256.0f, 1.0f, 0.0f) * uv%d.w);\n", ztexcoord);
} }
} }
WRITE(p,"}\n"); WRITE(p,"}\n");
return text; return text;
@ -470,10 +470,25 @@ void WriteStage(char *&p, int n, u32 texture_mask)
bHasIndStage = true; bHasIndStage = true;
int texmap = bpmem.tevorders[n/2].getEnable(n&1) ? bpmem.tevorders[n/2].getTexMap(n&1) : bpmem.tevindref.getTexMap(bpmem.tevind[n].bt); int texmap = bpmem.tevorders[n/2].getEnable(n&1) ? bpmem.tevorders[n/2].getTexMap(n&1) : bpmem.tevindref.getTexMap(bpmem.tevind[n].bt);
if( bpmem.tevind[n].bs != ITBA_OFF ) if( bpmem.tevind[n].bs != ITBA_OFF ) {
// write the bump alpha // write the bump alpha
WRITE(p, "alphabump = %s (indtex%d.%s %s);\n", bpmem.tevind[n].fmt==ITF_8?"":"frac", bpmem.tevind[n].bt,
if( bpmem.tevind[n].fmt == ITF_8 ) {
WRITE(p, "alphabump = indtex%d.%s %s;\n", bpmem.tevind[n].bt,
tevIndAlphaSel[bpmem.tevind[n].bs], tevIndAlphaScale[bpmem.tevind[n].fmt]); tevIndAlphaSel[bpmem.tevind[n].bs], tevIndAlphaScale[bpmem.tevind[n].fmt]);
}
else {
// donkopunchstania: really bad way to do this
// cannot always use fract because fract(1.0) is 0.0 when it needs to be 1.0
// omitting fract seems to work as well
WRITE(p, "if( indtex%d.%s >= 1.0f )\n", bpmem.tevind[n].bt,
tevIndAlphaSel[bpmem.tevind[n].bs]);
WRITE(p, " alphabump = 1.0f;\n");
WRITE(p, "else\n");
WRITE(p, " alphabump = fract ( indtex%d.%s %s );\n", bpmem.tevind[n].bt,
tevIndAlphaSel[bpmem.tevind[n].bs], tevIndAlphaScale[bpmem.tevind[n].fmt]);
}
}
// bias // bias
WRITE(p, "float3 indtevcrd%d = indtex%d;\n", n, bpmem.tevind[n].bt); WRITE(p, "float3 indtevcrd%d = indtex%d;\n", n, bpmem.tevind[n].bt);
@ -757,9 +772,9 @@ void WriteAlphaCompare(char *&p, int num, int comp)
case ALPHACMP_ALWAYS: WRITE(p,"(false)"); break; case ALPHACMP_ALWAYS: WRITE(p,"(false)"); break;
case ALPHACMP_NEVER: WRITE(p,"(true)"); break; case ALPHACMP_NEVER: WRITE(p,"(true)"); break;
case ALPHACMP_LEQUAL: WRITE(p,"(prev.a > %s)",alphaRef[num]); break; case ALPHACMP_LEQUAL: WRITE(p,"(prev.a > %s)",alphaRef[num]); break;
case ALPHACMP_LESS: WRITE(p,"(prev.a >= %s+%f)",alphaRef[num],epsilon*0.5f);break; case ALPHACMP_LESS: WRITE(p,"(prev.a >= %s - %f)",alphaRef[num],epsilon*0.5f);break;
case ALPHACMP_GEQUAL: WRITE(p,"(prev.a < %s)",alphaRef[num]); break; case ALPHACMP_GEQUAL: WRITE(p,"(prev.a < %s)",alphaRef[num]); break;
case ALPHACMP_GREATER: WRITE(p,"(prev.a <= %s - %f)",alphaRef[num],epsilon*0.5f);break; case ALPHACMP_GREATER: WRITE(p,"(prev.a <= %s + %f)",alphaRef[num],epsilon*0.5f);break;
case ALPHACMP_EQUAL: WRITE(p,"(abs(prev.a-%s)>%f)",alphaRef[num],epsilon*2); break; case ALPHACMP_EQUAL: WRITE(p,"(abs(prev.a-%s)>%f)",alphaRef[num],epsilon*2); break;
case ALPHACMP_NEQUAL: WRITE(p,"(abs(prev.a-%s)<%f)",alphaRef[num],epsilon*2); break; case ALPHACMP_NEQUAL: WRITE(p,"(abs(prev.a-%s)<%f)",alphaRef[num],epsilon*2); break;
} }

View File

@ -32,9 +32,10 @@ PixelShaderMngr::PIXELSHADERUID PixelShaderMngr::s_curuid;
static int s_nMaxPixelInstructions; static int s_nMaxPixelInstructions;
static int s_nColorsChanged[2]; // 0 - regular colors, 1 - k colors static int s_nColorsChanged[2]; // 0 - regular colors, 1 - k colors
static int s_nTexDimsChanged[2], s_nIndTexMtxChanged = 0; //min, max static int s_nIndTexMtxChanged = 0;
static bool s_bAlphaChanged, s_bZBiasChanged, s_bIndTexScaleChanged; static bool s_bAlphaChanged, s_bZBiasChanged, s_bIndTexScaleChanged;
static float lastRGBAfull[2][4][4]; static float lastRGBAfull[2][4][4];
static u8 s_nTexDimsChanged;
static u32 lastAlpha = 0; static u32 lastAlpha = 0;
static u32 lastTexDims[8]={0}; static u32 lastTexDims[8]={0};
static u32 lastZBias = 0; static u32 lastZBias = 0;
@ -60,7 +61,7 @@ void PixelShaderMngr::SetPSConstant4fv(int const_number, const float *f) {
void PixelShaderMngr::Init() void PixelShaderMngr::Init()
{ {
s_nColorsChanged[0] = s_nColorsChanged[1] = 0; s_nColorsChanged[0] = s_nColorsChanged[1] = 0;
s_nTexDimsChanged[0] = s_nTexDimsChanged[1] = -1; s_nTexDimsChanged = 0;
s_nIndTexMtxChanged = 15; s_nIndTexMtxChanged = 15;
s_bAlphaChanged = s_bZBiasChanged = s_bIndTexScaleChanged = true; s_bAlphaChanged = s_bZBiasChanged = s_bIndTexScaleChanged = true;
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
@ -133,7 +134,18 @@ FRAGMENTSHADER* PixelShaderMngr::GetShader()
char *code = GeneratePixelShader(s_texturemask, char *code = GeneratePixelShader(s_texturemask,
Renderer::GetZBufferTarget() != 0, Renderer::GetZBufferTarget() != 0,
Renderer::GetRenderMode() != Renderer::RM_Normal); Renderer::GetRenderMode() != Renderer::RM_Normal);
// printf("Compiling pixel shader. size = %i\n", strlen(code));
#ifdef _DEBUG
if( g_Config.iLog & CONF_SAVESHADERS && code ) {
static int counter = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%s/ps_%04i.txt", g_Config.texDumpPath, counter++);
SaveData(szTemp, code);
}
#endif
// printf("Compiling pixel shader. size = %i\n", strlen(code));
if (!code || !CompilePixelShader(newentry.shader, code)) { if (!code || !CompilePixelShader(newentry.shader, code)) {
ERROR_LOG("failed to create pixel shader\n"); ERROR_LOG("failed to create pixel shader\n");
return NULL; return NULL;
@ -243,61 +255,30 @@ void PixelShaderMngr::SetConstants(FRAGMENTSHADER& ps)
int texmap = bpmem.tevorders[i/2].getTexMap(i&1); int texmap = bpmem.tevorders[i/2].getTexMap(i&1);
maptocoord[texmap] = bpmem.tevorders[i/2].getTexCoord(i&1); maptocoord[texmap] = bpmem.tevorders[i/2].getTexCoord(i&1);
newmask |= 1<<texmap; newmask |= 1<<texmap;
SetTexDimsChanged(i); SetTexDimsChanged(texmap);
} }
} }
if( maptocoord_mask != newmask ) { if( maptocoord_mask != newmask ) {
u32 changes = maptocoord_mask ^ newmask; //u32 changes = maptocoord_mask ^ newmask;
for(int i = 0; i < 8; ++i) { for(int i = 0; i < 8; ++i) {
if( changes&(1<<i) ) { if( newmask&(1<<i) ) {
SetTexDimsChanged(i); SetTexDimsChanged(i);
} }
if( !(newmask & (1<<i)) ) { else {
maptocoord[i] = -1; maptocoord[i] = -1;
} }
} }
maptocoord_mask = newmask; maptocoord_mask = newmask;
} }
if( s_nTexDimsChanged[0] >= 0 ) { if( s_nTexDimsChanged ) {
float fdims[4]; for(int i = 0; i < 8; ++i) {
for(int i = s_nTexDimsChanged[0]; i <= s_nTexDimsChanged[1]; ++i) { if( s_nTexDimsChanged & (1<<i) ) {
if( s_texturemask & (1<<i) ) { SetPSTextureDims(i);
if( maptocoord[i] >= 0 ) {
TCoordInfo& tc = bpmem.texcoords[maptocoord[i]];
fdims[0] = (float)(lastTexDims[i]&0xffff);
fdims[1] = (float)((lastTexDims[i]>>16)&0xfff);
fdims[2] = (float)(tc.s.scale_minus_1+1)/(float)(lastTexDims[i]&0xffff);
fdims[3] = (float)(tc.t.scale_minus_1+1)/(float)((lastTexDims[i]>>16)&0xfff);
}
else {
fdims[0] = (float)(lastTexDims[i]&0xffff);
fdims[1] = (float)((lastTexDims[i]>>16)&0xfff);
fdims[2] = 1.0f;
fdims[3] = 1.0f;
} }
} }
else { s_nTexDimsChanged = 0;
if( maptocoord[i] >= 0 ) {
TCoordInfo& tc = bpmem.texcoords[maptocoord[i]];
fdims[0] = (float)(tc.s.scale_minus_1+1)/(float)(lastTexDims[i]&0xffff);
fdims[1] = (float)(tc.t.scale_minus_1+1)/(float)((lastTexDims[i]>>16)&0xfff);
fdims[2] = 1.0f/(float)(tc.s.scale_minus_1+1);
fdims[3] = 1.0f/(float)(tc.t.scale_minus_1+1);
}
else {
fdims[0] = 1.0f;
fdims[1] = 1.0f;
fdims[2] = 1.0f/(float)(lastTexDims[i]&0xffff);
fdims[3] = 1.0f/(float)((lastTexDims[i]>>16)&0xfff);
}
}
PRIM_LOG("texdims%d: %f %f %f %f\n", i, fdims[0], fdims[1], fdims[2], fdims[3]);
SetPSConstant4fv(C_TEXDIMS + i, fdims);
}
s_nTexDimsChanged[0] = s_nTexDimsChanged[1] = -1;
} }
if( s_bAlphaChanged ) { if( s_bAlphaChanged ) {
@ -372,6 +353,45 @@ void PixelShaderMngr::SetConstants(FRAGMENTSHADER& ps)
} }
} }
void PixelShaderMngr::SetPSTextureDims(int texid)
{
float fdims[4];
if( s_texturemask & (1<<texid) ) {
if( maptocoord[texid] >= 0 ) {
TCoordInfo& tc = bpmem.texcoords[maptocoord[texid]];
fdims[0] = (float)(lastTexDims[texid]&0xffff);
fdims[1] = (float)((lastTexDims[texid]>>16)&0xfff);
fdims[2] = (float)(tc.s.scale_minus_1+1)/(float)(lastTexDims[texid]&0xffff);
fdims[3] = (float)(tc.t.scale_minus_1+1)/(float)((lastTexDims[texid]>>16)&0xfff);
}
else {
fdims[0] = (float)(lastTexDims[texid]&0xffff);
fdims[1] = (float)((lastTexDims[texid]>>16)&0xfff);
fdims[2] = 1.0f;
fdims[3] = 1.0f;
}
}
else {
if( maptocoord[texid] >= 0 ) {
TCoordInfo& tc = bpmem.texcoords[maptocoord[texid]];
fdims[0] = (float)(tc.s.scale_minus_1+1)/(float)(lastTexDims[texid]&0xffff);
fdims[1] = (float)(tc.t.scale_minus_1+1)/(float)((lastTexDims[texid]>>16)&0xfff);
fdims[2] = 1.0f/(float)(tc.s.scale_minus_1+1);
fdims[3] = 1.0f/(float)(tc.t.scale_minus_1+1);
}
else {
fdims[0] = 1.0f;
fdims[1] = 1.0f;
fdims[2] = 1.0f/(float)(lastTexDims[texid]&0xffff);
fdims[3] = 1.0f/(float)((lastTexDims[texid]>>16)&0xfff);
}
}
PRIM_LOG("texdims%d: %f %f %f %f\n", texid, fdims[0], fdims[1], fdims[2], fdims[3]);
SetPSConstant4fv(C_TEXDIMS + texid, fdims);
}
void PixelShaderMngr::SetColorChanged(int type, int num) void PixelShaderMngr::SetColorChanged(int type, int num)
{ {
int r=bpmem.tevregs[num].low.a, a=bpmem.tevregs[num].low.b; int r=bpmem.tevregs[num].low.a, a=bpmem.tevregs[num].low.b;
@ -406,13 +426,7 @@ void PixelShaderMngr::SetTexDims(int texmapid, u32 width, u32 height, u32 wraps,
u32 wh = width|(height<<16)|(wraps<<28)|(wrapt<<30); u32 wh = width|(height<<16)|(wraps<<28)|(wrapt<<30);
if( lastTexDims[texmapid] != wh ) { if( lastTexDims[texmapid] != wh ) {
lastTexDims[texmapid] = wh; lastTexDims[texmapid] = wh;
if( s_nTexDimsChanged[0] == -1 ) { s_nTexDimsChanged |= 1<<texmapid;
s_nTexDimsChanged[0] = s_nTexDimsChanged[1] = texmapid;
}
else {
if( s_nTexDimsChanged[0] > texmapid ) s_nTexDimsChanged[0] = texmapid;
else if( s_nTexDimsChanged[1] < texmapid ) s_nTexDimsChanged[1] = texmapid;
}
} }
} }
@ -462,11 +476,11 @@ void PixelShaderMngr::SetZTetureOpChanged()
void PixelShaderMngr::SetTexturesUsed(u32 nonpow2tex) void PixelShaderMngr::SetTexturesUsed(u32 nonpow2tex)
{ {
if( s_texturemask != nonpow2tex ) { if( s_texturemask != nonpow2tex ) {
u32 mask = s_texturemask ^ nonpow2tex;
for(int i = 0; i < 8; ++i) { for(int i = 0; i < 8; ++i) {
if( mask & (0x10101<<i) ) { if( nonpow2tex & (0x10101<<i) ) {
if( s_nTexDimsChanged[0] > i ) s_nTexDimsChanged[0] = i; // this check was previously implicit, but should it be here?
else if( s_nTexDimsChanged[1] < i ) s_nTexDimsChanged[1] = i; if( s_nTexDimsChanged )
s_nTexDimsChanged |= 1<<i;
} }
} }
s_texturemask = nonpow2tex; s_texturemask = nonpow2tex;
@ -475,8 +489,10 @@ void PixelShaderMngr::SetTexturesUsed(u32 nonpow2tex)
void PixelShaderMngr::SetTexDimsChanged(int texmapid) void PixelShaderMngr::SetTexDimsChanged(int texmapid)
{ {
if( s_nTexDimsChanged[0] > texmapid ) s_nTexDimsChanged[0] = texmapid; // this check was previously implicit, but should it be here?
else if( s_nTexDimsChanged[1] < texmapid ) s_nTexDimsChanged[1] = texmapid; if( s_nTexDimsChanged )
s_nTexDimsChanged |= 1<<texmapid;
SetIndTexScaleChanged(); SetIndTexScaleChanged();
} }

View File

@ -115,6 +115,9 @@ class PixelShaderMngr
static void SetPSConstant4f(int const_number, float f1, float f2, float f3, float f4); static void SetPSConstant4f(int const_number, float f1, float f2, float f3, float f4);
static void SetPSConstant4fv(int const_number, const float *f); static void SetPSConstant4fv(int const_number, const float *f);
static void SetPSTextureDims(int texid);
public: public:
static void Init(); static void Init();
static void Cleanup(); static void Cleanup();

View File

@ -100,6 +100,17 @@ VERTEXSHADER* VertexShaderMngr::GetShader(u32 components)
VSCacheEntry& entry = vshaders[uid]; VSCacheEntry& entry = vshaders[uid];
char *code = GenerateVertexShader(components, Renderer::GetZBufferTarget() != 0); char *code = GenerateVertexShader(components, Renderer::GetZBufferTarget() != 0);
#ifdef _DEBUG
if( g_Config.iLog & CONF_SAVESHADERS && code ) {
static int counter = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%s/vs_%04i.txt", g_Config.texDumpPath, counter++);
SaveData(szTemp, code);
}
#endif
if (!code || !VertexShaderMngr::CompileVertexShader(entry.shader, code)) { if (!code || !VertexShaderMngr::CompileVertexShader(entry.shader, code)) {
ERROR_LOG("failed to create vertex shader\n"); ERROR_LOG("failed to create vertex shader\n");
return NULL; return NULL;