diff options
| author | hrydgard <hrydgard@gmail.com> | 2008-07-17 21:09:18 +0000 |
|---|---|---|
| committer | hrydgard <hrydgard@gmail.com> | 2008-07-17 21:09:18 +0000 |
| commit | 91ccda69efb56fa729c3f4f3209726238f656e29 (patch) | |
| tree | 91943fd8ad3dae28475ee952da7e454288cbe0c1 /Source | |
| parent | af0e52554e1f367633c849a580cce155a8f06605 (diff) | |
Split a couple of huge files up, to make them easier to handle.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@24 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source')
18 files changed, 1696 insertions, 1574 deletions
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Utils.h b/Source/Plugins/Plugin_VideoDX9/Src/Utils.h index ae5c242734..87159c3b38 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Utils.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/Utils.h @@ -1,7 +1,6 @@ #ifndef _UTILS_H
#define _UTILS_H
-
#include "Common.h"
#include "main.h"
@@ -17,7 +16,6 @@ extern float luts8tosfloat[256]; LRESULT CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void InitLUTs();
-
//#define RAM_MASK 0x1FFFFFF
inline u8 *Memory_GetPtr(u32 _uAddress)
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexLoader.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexLoader.cpp index a3f9415c42..8faef5e046 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexLoader.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexLoader.cpp @@ -35,7 +35,7 @@ int ComputeVertexSize(u32 comp) size += 4;
if (comp & VB_HAS_NRM0)
size += 4;
- if (comp & (VB_HAS_NRM1|VB_HAS_NRM2)) //combine into single check for speed
+ if (comp & (VB_HAS_NRM1 | VB_HAS_NRM2)) //combine into single check for speed
size += 8;
if (comp & VB_HAS_COL0)
size += 4;
diff --git a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcproj b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcproj index 6b864f1861..2b1bf09687 100644 --- a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcproj +++ b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcproj @@ -1302,6 +1302,14 @@ >
</File>
<File
+ RelativePath=".\Src\PixelShaderManager.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Src\PixelShaderManager.h"
+ >
+ </File>
+ <File
RelativePath=".\Src\rasterfont.cpp"
>
<FileConfiguration
@@ -1349,6 +1357,14 @@ RelativePath=".\Src\VertexShader.h"
>
</File>
+ <File
+ RelativePath=".\Src\VertexShaderManager.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Src\VertexShaderManager.h"
+ >
+ </File>
</Filter>
<File
RelativePath=".\Src\Fifo.cpp"
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/BPStructs.cpp b/Source/Plugins/Plugin_VideoOGL/Src/BPStructs.cpp index 90f4d75791..b0a5e08d21 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/BPStructs.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/BPStructs.cpp @@ -23,8 +23,8 @@ #include "OpcodeDecoding.h"
#include "TextureMngr.h"
#include "TextureDecoder.h"
-#include "VertexShader.h"
-#include "PixelShader.h"
+#include "VertexShaderManager.h"
+#include "PixelShaderManager.h"
#define BPMEM_GENMODE 0x00
#define BPMEM_IND_MTX 0x06
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Globals.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Globals.cpp index 49f5f9e6ef..b21bd476c5 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Globals.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Globals.cpp @@ -116,7 +116,6 @@ void Config::Save() iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
- iniFile.Set("Settings", "OverlayStats", bOverlayStats);
iniFile.Set("Settings", "Postprocess", iPostprocessEffect);
iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel);
iniFile.Set("Settings", "DumpTextures", bDumpTextures);
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/OpcodeDecoding.cpp b/Source/Plugins/Plugin_VideoOGL/Src/OpcodeDecoding.cpp index e281f4a7f1..5741bc5c3d 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/OpcodeDecoding.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/OpcodeDecoding.cpp @@ -27,7 +27,7 @@ #include "Globals.h"
#include "OpcodeDecoding.h"
#include "VertexLoader.h"
-#include "VertexShader.h"
+#include "VertexShaderManager.h"
#include "TextureMngr.h"
#include "BPStructs.h"
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShader.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PixelShader.cpp index e1d5b990f0..62549a7234 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShader.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShader.cpp @@ -16,494 +16,12 @@ // http://code.google.com/p/dolphin-emu/
#include "Globals.h"
-#include <math.h>
+#include <cmath>
#include <assert.h>
-#include "VertexShader.h"
#include "PixelShader.h"
-
-#define I_COLORS "color"
-#define I_KCOLORS "k"
-#define I_ALPHA "alphaRef"
-#define I_TEXDIMS "texdim"
-#define I_ZBIAS "czbias"
-#define I_INDTEXSCALE "cindscale"
-#define I_INDTEXMTX "cindmtx"
-
-#define C_COLORS 0
-#define C_KCOLORS (C_COLORS+4)
-#define C_ALPHA (C_KCOLORS+4)
-#define C_TEXDIMS (C_ALPHA+1)
-#define C_ZBIAS (C_TEXDIMS+8)
-#define C_INDTEXSCALE (C_ZBIAS+2)
-#define C_INDTEXMTX (C_INDTEXSCALE+2)
-#define C_ENVCONST_END (C_INDTEXMTX+6)
-
-#define C_COLORMATRIX (C_INDTEXMTX+6)
-
-
-void WriteStage(char *&p, int n);
-void WrapNonPow2Tex(char* &p, const char* var, int texmap);
-void WriteAlphaCompare(char *&p, int num, int comp);
-bool WriteAlphaTest(char *&p);
-
-PixelShaderMngr::PSCache PixelShaderMngr::pshaders;
-FRAGMENTSHADER* PixelShaderMngr::pShaderLast = NULL;
-PixelShaderMngr::PIXELSHADERUID PixelShaderMngr::s_curuid;
-
-static int s_nMaxPixelInstructions;
-static int s_nColorsChanged[2]; // 0 - regular colors, 1 - k colors
-static int s_nTexDimsChanged[2], s_nIndTexMtxChanged = 0; //min, max
-static bool s_bAlphaChanged, s_bZBiasChanged, s_bIndTexScaleChanged;
-static float lastRGBAfull[2][4][4] = {0};
-static u32 lastAlpha = 0;
-static u32 lastTexDims[8]={0};
-static u32 lastZBias = 0;
-
-// lower byte describes if a texture is nonpow2 or pow2
-// next byte describes whether the repeat wrap mode is enabled for the s channel
-// next byte is for t channel
-static u32 s_texturemask = 0;
-
-static int maptocoord[8]; // indexed by texture map, holds the texcoord associated with the map
-static u32 maptocoord_mask=0;
-
-static GLuint s_ColorMatrixProgram=0;
-
-void PixelShaderMngr::Init()
-{
- s_nColorsChanged[0] = s_nColorsChanged[1] = 0;
- s_nTexDimsChanged[0] = s_nTexDimsChanged[1] = -1;
- s_nIndTexMtxChanged = 15;
- s_bAlphaChanged = s_bZBiasChanged = s_bIndTexScaleChanged = true;
- GL_REPORT_ERRORD();
- for(int i = 0; i < 8; ++i) maptocoord[i] = -1;
- maptocoord_mask = 0;
- memset(lastRGBAfull, 0, sizeof(lastRGBAfull));
-
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, &s_nMaxPixelInstructions);
-
- int maxinst, maxattribs;
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &maxinst);
- glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, &maxattribs);
- ERROR_LOG("pixel max_alu=%d, max_inst=%d, max_attrib=%d\n", s_nMaxPixelInstructions, maxinst, maxattribs);
-
- char pmatrixprog[1024];
- sprintf(pmatrixprog, "!!ARBfp1.0"
- "TEMP R0;\n"
- "TEMP R1;\n"
- "TEX R0, fragment.texcoord[0], texture[0], RECT;\n"
- "DP4 R1.w, R0, program.env[%d];\n"
- "DP4 R1.z, R0, program.env[%d];\n"
- "DP4 R1.x, R0, program.env[%d];\n"
- "DP4 R1.y, R0, program.env[%d];\n"
- "ADD result.color, R1, program.env[%d];\n"
- "END\n", C_COLORMATRIX+3, C_COLORMATRIX+2, C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+4);
- glGenProgramsARB( 1, &s_ColorMatrixProgram );
- glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, s_ColorMatrixProgram );
-
- glProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog);
-
- GLenum err=GL_NO_ERROR;
- GL_REPORT_ERROR();
- if( err != GL_NO_ERROR ) {
- ERROR_LOG("Failed to create color matrix fragment program\n");
-
- SAFE_RELEASE_PROG(s_ColorMatrixProgram);
- }
-}
-
-void PixelShaderMngr::Shutdown()
-{
- SAFE_RELEASE_PROG(s_ColorMatrixProgram);
- PSCache::iterator iter = pshaders.begin();
- for (;iter!=pshaders.end();iter++)
- iter->second.Destroy();
- pshaders.clear();
-}
-
-FRAGMENTSHADER* PixelShaderMngr::GetShader()
-{
- DVSTARTPROFILE();
- PIXELSHADERUID uid;
- GetPixelShaderId(uid);
-
- PSCache::iterator iter = pshaders.find(uid);
-
- if (iter != pshaders.end()) {
- iter->second.frameCount=frameCount;
- PSCacheEntry &entry = iter->second;
- if (&entry.shader != pShaderLast)
- {
- pShaderLast = &entry.shader;
- }
- return pShaderLast;
- }
-
- PSCacheEntry& newentry = pshaders[uid];
-
- if (!GeneratePixelShader(newentry.shader)) {
- ERROR_LOG("failed to create pixel shader\n");
- return NULL;
- }
-
- //Make an entry in the table
- newentry.frameCount=frameCount;
-
- pShaderLast = &newentry.shader;
- INCSTAT(stats.numPixelShadersCreated);
- SETSTAT(stats.numPixelShadersAlive, pshaders.size());
- return pShaderLast;
-}
-
-void PixelShaderMngr::Cleanup()
-{
- PSCache::iterator iter = pshaders.begin();
- while(iter != pshaders.end()) {
- PSCacheEntry &entry = iter->second;
- if (entry.frameCount<frameCount-200) {
- 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 PixelShaderMngr::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
-{
- CGerror cgerr = cgGetError();
-
- char stropt[64];
- sprintf(stropt, "MaxLocalParams=32,NumInstructionSlots=%d", s_nMaxPixelInstructions);
-#ifdef _WIN32
- const char* opts[] = {"-profileopts",stropt,"-O2","-q",NULL};
-#else
- const char* opts[] = {"-profileopts",stropt,"-q",NULL};
-#endif
- CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);
- if (!cgIsProgram(tempprog) || cgGetError() != CG_NO_ERROR) {
- ERROR_LOG("Failed to create ps %s:\n", cgGetLastListing(g_cgcontext));
- ERROR_LOG(pstrprogram);
- return false;
- }
-
- char* pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
- char* plocal = strstr(pcompiledprog, "program.local");
- while( plocal != NULL ) {
- const char* penv = " program.env";
- memcpy(plocal, penv, 13);
- plocal = strstr(plocal+13, "program.local");
- }
-
- if( Renderer::IsUsingATIDrawBuffers() ) {
- // sometimes compilation can use ARB_draw_buffers, which would fail for ATI cards
- char* poptions = strstr(pcompiledprog, "ARB_draw_buffers");
- if( poptions != NULL ) {
- poptions[0] = 'A';
- poptions[1] = 'T';
- poptions[2] = 'I';
- }
- }
-
- //ERROR_LOG(pcompiledprog);
- //ERROR_LOG(pstrprogram);
-
- glGenProgramsARB( 1, &ps.glprogid );
- glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, ps.glprogid );
- glProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
-
- GLenum err = GL_NO_ERROR;
- GL_REPORT_ERROR();
- if( err != GL_NO_ERROR ) {
- ERROR_LOG(pstrprogram);
- ERROR_LOG(pcompiledprog);
- }
-
- cgDestroyProgram(tempprog);
-
-#ifdef _DEBUG
- ps.strprog = pstrprogram;
-#endif
- return true;
-}
-
-void PixelShaderMngr::SetConstants(FRAGMENTSHADER& ps)
-{
- for(int i = 0; i < 2; ++i) {
- if( s_nColorsChanged[i] ) {
-
- int baseind = i?C_KCOLORS:C_COLORS;
- for(int j = 0; j < 4; ++j) {
- if( s_nColorsChanged[i] & (1<<j) ) {
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, baseind+j, &lastRGBAfull[i][j][0]);
- }
- }
- s_nColorsChanged[i] = 0;
- }
- }
-
- u32 newmask = 0;
- for(u32 i = 0; i < bpmem.genMode.numtevstages+1; ++i) {
- if( bpmem.tevorders[i/2].getEnable(i&1) ) {
- int texmap = bpmem.tevorders[i/2].getTexMap(i&1);
- maptocoord[texmap] = bpmem.tevorders[i/2].getTexCoord(i&1);
- newmask |= 1<<texmap;
- SetTexDimsChanged(i);
- }
- }
-
- if( maptocoord_mask != newmask ) {
- u32 changes = maptocoord_mask ^ newmask;
- for(int i = 0; i < 8; ++i) {
- if( changes&(1<<i) ) {
- SetTexDimsChanged(i);
- }
- if( !(newmask & (1<<i)) ) {
- maptocoord[i] = -1;
- }
- }
- maptocoord_mask = newmask;
- }
-
- if( s_nTexDimsChanged[0] >= 0 ) {
- float fdims[4];
- for(int i = s_nTexDimsChanged[0]; i <= s_nTexDimsChanged[1]; ++i) {
- if( s_texturemask & (1<<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 {
- 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]);
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_TEXDIMS+i, fdims);
- }
- s_nTexDimsChanged[0] = s_nTexDimsChanged[1] = -1;
- }
-
- if( s_bAlphaChanged ) {
- glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, C_ALPHA, (lastAlpha&0xff)/255.0f, ((lastAlpha>>8)&0xff)/255.0f, 0, ((lastAlpha>>16)&0xff)/255.0f);
- }
-
- if( s_bZBiasChanged ) {
- u32 bits;
- float ffrac = 255.0f/256.0f;
- float ftemp[4];
- switch(bpmem.ztex2.type) {
- case 0:
- bits = 8;
- ftemp[0] = ffrac/(256.0f*256.0f); ftemp[1] = ffrac/256.0f; ftemp[2] = ffrac; ftemp[3] = 0;
- break;
- case 1:
- bits = 16;
- ftemp[0] = 0; ftemp[1] = ffrac/(256.0f*256.0f); ftemp[2] = ffrac/256.0f; ftemp[3] = ffrac;
- break;
- case 2:
- bits = 24;
- ftemp[0] = ffrac/(256.0f*256.0f); ftemp[1] = ffrac/256.0f; ftemp[2] = ffrac; ftemp[3] = 0;
- break;
- }
- //ERROR_LOG("pixel=%x,%x, bias=%x\n", bpmem.zcontrol.pixel_format, bpmem.ztex2.type, lastZBias);
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_ZBIAS, ftemp);
- glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, C_ZBIAS+1, 0, 0, 0, (float)( (((int)lastZBias<<8)>>8))/16777216.0f);
- }
-
- // indirect incoming texture scales, update all!
- if( s_bIndTexScaleChanged ) {
- float f[8];
-
- for(u32 i = 0; i < bpmem.genMode.numindstages; ++i) {
- int srctexmap = bpmem.tevindref.getTexMap(i);
- int texcoord = bpmem.tevindref.getTexCoord(i);
- TCoordInfo& tc = bpmem.texcoords[texcoord];
-
- f[2*i] = bpmem.texscale[i/2].getScaleS(i&1) * (float)(tc.s.scale_minus_1+1) / (float)(lastTexDims[srctexmap]&0xffff);
- f[2*i+1] = bpmem.texscale[i/2].getScaleT(i&1) * (float)(tc.t.scale_minus_1+1) / (float)((lastTexDims[srctexmap]>>16)&0xfff);
-
- PRIM_LOG("tex indscale%d: %f %f\n", i, f[2*i], f[2*i+1]);
- }
-
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_INDTEXSCALE, f);
-
- if( bpmem.genMode.numindstages > 2 )
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_INDTEXSCALE+1, &f[4]);
-
- s_bIndTexScaleChanged = false;
- }
-
- if( s_nIndTexMtxChanged ) {
- for(int i = 0; i < 3; ++i) {
- if( s_nIndTexMtxChanged & (1<<i) ) {
- int scale = ((u32)bpmem.indmtx[i].col0.s0<<0)|((u32)bpmem.indmtx[i].col1.s1<<2)|((u32)bpmem.indmtx[i].col2.s2<<4);
- float fscale = powf(2.0f,(float)(scale-17)) / 1024.0f;
-
- // xyz - static matrix
- //TODO w - dynamic matrix scale / 256...... somehow / 4 works better
- glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, C_INDTEXMTX+2*i,
- bpmem.indmtx[i].col0.ma * fscale, bpmem.indmtx[i].col1.mc * fscale, bpmem.indmtx[i].col2.me * fscale, fscale * 256.0f);
- glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, C_INDTEXMTX+2*i+1,
- bpmem.indmtx[i].col0.mb * fscale, bpmem.indmtx[i].col1.md * fscale, bpmem.indmtx[i].col2.mf * fscale, fscale * 256.0f);
-
- PRIM_LOG("indmtx%d: scale=%f, mat=(%f %f %f; %f %f %f)\n", i,
- 1024.0f*fscale, bpmem.indmtx[i].col0.ma * fscale, bpmem.indmtx[i].col1.mc * fscale, bpmem.indmtx[i].col2.me * fscale,
- bpmem.indmtx[i].col0.mb * fscale, bpmem.indmtx[i].col1.md * fscale, bpmem.indmtx[i].col2.mf * fscale, fscale);
- }
- }
- s_nIndTexMtxChanged = 0;
- }
-}
-
-void PixelShaderMngr::SetColorChanged(int type, int num)
-{
- int r=bpmem.tevregs[num].low.a, a=bpmem.tevregs[num].low.b;
- int b=bpmem.tevregs[num].high.a, g=bpmem.tevregs[num].high.b;
- float* pf = &lastRGBAfull[type][num][0];
- pf[0] = (float)r/255.0f;
- pf[1] = (float)g/255.0f;
- pf[2] = (float)b/255.0f;
- pf[3] = (float)a/255.0f;
- s_nColorsChanged[type] |= 1 << num;
- PRIM_LOG("pixel %scolor%d: %f %f %f %f\n", type?"k":"", num, pf[0], pf[1], pf[2], pf[3]);
-}
-
-void PixelShaderMngr::SetAlpha(const AlphaFunc& alpha)
-{
- if( (alpha.hex&0xffff) != lastAlpha ) {
- lastAlpha = (lastAlpha&~0xffff)|(alpha.hex&0xffff);
- s_bAlphaChanged = true;
- }
-}
-
-void PixelShaderMngr::SetDestAlpha(const ConstantAlpha& alpha)
-{
- if( alpha.alpha != (lastAlpha>>16) ) {
- lastAlpha = (lastAlpha&~0xff0000)|((alpha.hex&0xff)<<16);
- s_bAlphaChanged = true;
- }
-}
-
-void PixelShaderMngr::SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt)
-{
- u32 wh = width|(height<<16)|(wraps<<28)|(wrapt<<30);
- if( lastTexDims[texmapid] != wh ) {
- lastTexDims[texmapid] = wh;
- if( s_nTexDimsChanged[0] == -1 ) {
- 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;
- }
- }
-}
-
-void PixelShaderMngr::SetZTetureBias(u32 bias)
-{
- if( lastZBias != bias ) {
- s_bZBiasChanged = true;
- lastZBias = bias;
- }
-}
-
-void PixelShaderMngr::SetIndTexScaleChanged()
-{
- s_bIndTexScaleChanged = true;
-}
-
-void PixelShaderMngr::SetIndMatrixChanged(int matrixidx)
-{
- s_nIndTexMtxChanged |= 1 << matrixidx;
-}
-
-void PixelShaderMngr::SetGenModeChanged()
-{
-}
-
-void PixelShaderMngr::SetTevCombinerChanged(int id)
-{
-}
-
-void PixelShaderMngr::SetTevKSelChanged(int id)
-{
-}
-
-void PixelShaderMngr::SetTevOrderChanged(int id)
-{
-}
-
-void PixelShaderMngr::SetTevIndirectChanged(int id)
-{
-}
-
-void PixelShaderMngr::SetZTetureOpChanged()
-{
- s_bZBiasChanged = true;
-}
-
-void PixelShaderMngr::SetTexturesUsed(u32 nonpow2tex)
-{
- if( s_texturemask != nonpow2tex ) {
- u32 mask = s_texturemask ^ nonpow2tex;
- for(int i = 0; i < 8; ++i) {
- if( mask & (0x10101<<i) ) {
- if( s_nTexDimsChanged[0] > i ) s_nTexDimsChanged[0] = i;
- else if( s_nTexDimsChanged[1] < i ) s_nTexDimsChanged[1] = i;
- }
- }
- s_texturemask = nonpow2tex;
- }
-}
-
-void PixelShaderMngr::SetTexDimsChanged(int texmapid)
-{
- if( s_nTexDimsChanged[0] > texmapid ) s_nTexDimsChanged[0] = texmapid;
- else if( s_nTexDimsChanged[1] < texmapid ) s_nTexDimsChanged[1] = texmapid;
- SetIndTexScaleChanged();
-}
-
-void PixelShaderMngr::SetColorMatrix(const float* pmatrix, const float* pfConstAdd)
-{
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_COLORMATRIX, pmatrix);
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_COLORMATRIX+1, pmatrix+4);
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_COLORMATRIX+2, pmatrix+8);
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_COLORMATRIX+3, pmatrix+12);
- glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_COLORMATRIX+4, pfConstAdd);
-}
-
-GLuint PixelShaderMngr::GetColorMatrixProgram()
-{
- return s_ColorMatrixProgram;
-}
+#include "VertexShader.h" // for texture projection mode
+#include "PixelShaderManager.h"
// old tev->pixelshader notes
//
@@ -513,6 +31,12 @@ GLuint PixelShaderMngr::GetColorMatrixProgram() // according to GXTevColorArg table above
// output is given by .outreg
// tevtemp is set according to swapmodetables and
+
+void WriteStage(char *&p, int n);
+void WrapNonPow2Tex(char* &p, const char* var, int texmap);
+void WriteAlphaCompare(char *&p, int num, int comp);
+bool WriteAlphaTest(char *&p);
+
const float epsilon = 1.0f/255.0f;
const char *tevKSelTableC[] = // KCSEL
@@ -719,90 +243,6 @@ const char* tevIndBiasAdd[] = {"-128.0f", "1.0f", "1.0f", "1.0f" }; // indexed b const char* tevIndWrapStart[] = {"0", "256", "128", "64", "32", "16", "0.001" };
const char* tevIndFmtScale[] = {"255.0f", "31.0f", "15.0f", "8.0f" };
-void PixelShaderMngr::GetPixelShaderId(PixelShaderMngr::PIXELSHADERUID& uid)
-{
- u32 projtexcoords = 0;
- for (u32 i = 0; i < bpmem.genMode.numtevstages+1; i++) {
- if( bpmem.tevorders[i/2].getEnable(i&1) ) {
- int texcoord = bpmem.tevorders[i/2].getTexCoord(i&1);
- if( xfregs.texcoords[texcoord].texmtxinfo.projection )
- projtexcoords |= 1<<texcoord;
- }
- }
-
- u32 zbufrender = (Renderer::GetZBufferTarget()&&bpmem.zmode.updateenable)?1:0;
- u32 zBufRenderToCol0 = Renderer::GetRenderMode()!=Renderer::RM_Normal;
- uid.values[0] = (u32)bpmem.genMode.numtevstages|((u32)bpmem.genMode.numindstages<<4)|((u32)bpmem.genMode.numtexgens<<7)
- |((u32)bpmem.dstalpha.enable<<11)|((u32)((bpmem.alphaFunc.hex>>16)&0xff)<<12)|(projtexcoords<<20)|((u32)bpmem.ztex2.op<<28)
- |(zbufrender<<30)|(zBufRenderToCol0<<31);
-
- s_curuid.values[0] = (s_curuid.values[0]&~0x0ff00000)|(projtexcoords<<20);
-
- // swap table
- for(int i = 0; i < 8; i += 2)
- ((u8*)&uid.values[1])[i/2] = (bpmem.tevksel[i].hex&0xf)|((bpmem.tevksel[i+1].hex&0xf)<<4);
-
- uid.values[2] = s_texturemask;
- int hdr = 3;
-
- u32* pcurvalue = &uid.values[hdr];
- for(u32 i = 0; i < bpmem.genMode.numtevstages+1; ++i) {
- TevStageCombiner::ColorCombiner &cc = bpmem.combiners[i].colorC;
- TevStageCombiner::AlphaCombiner &ac = bpmem.combiners[i].alphaC;
-
- u32 val0 = cc.hex&0xffffff;
- u32 val1 = ac.hex&0xffffff;
- val0 |= bpmem.tevksel[i/2].getKC(i&1)<<24;
- val1 |= bpmem.tevksel[i/2].getKA(i&1)<<24;
-
- pcurvalue[0] = val0;
- pcurvalue[1] = val1;
- pcurvalue+=2;
- }
-
- for(u32 i = 0; i < (bpmem.genMode.numtevstages+1)/2; ++i) {
- u32 val0, val1;
- if( bpmem.tevorders[i].hex&0x40 ) val0 = bpmem.tevorders[i].hex&0x3ff;
- else val0 = bpmem.tevorders[i].hex&0x380;
- if( bpmem.tevorders[i].hex&0x40000 ) val1 = (bpmem.tevorders[i].hex&0x3ff000)>>12;
- else val1 = (bpmem.tevorders[i].hex&0x380000)>>12;
-
- switch(i % 3) {
- case 0: pcurvalue[0] = val0|(val1<<10); break;
- case 1: pcurvalue[0] |= val0<<20; pcurvalue[1] = val1; pcurvalue++; break;
- case 2: pcurvalue[1] |= (val0<<10)|(val1<<20); pcurvalue++; break;
- }
- }
-
- if( (bpmem.genMode.numtevstages+1)&1 ) { // odd
- u32 val0;
- if( bpmem.tevorders[bpmem.genMode.numtevstages/2].hex&0x40 ) val0 = bpmem.tevorders[bpmem.genMode.numtevstages/2].hex&0x3ff;
- else val0 = bpmem.tevorders[bpmem.genMode.numtevstages/2].hex&0x380;
-
- switch(bpmem.genMode.numtevstages % 3) {
- case 0: pcurvalue[0] = val0; break;
- case 1: pcurvalue[0] |= val0<<20; break;
- case 2: pcurvalue[1] |= (val0<<10); pcurvalue++; break;
- }
- }
-
- if( (bpmem.genMode.numtevstages % 3) != 2 )
- ++pcurvalue;
-
- uid.tevstages = (u32)(pcurvalue-&uid.values[0]-hdr);
-
- for(u32 i = 0; i < bpmem.genMode.numindstages; ++i) {
- u32 val = bpmem.tevind[i].hex&0x1fffff; // 21 bits
- switch(i%3) {
- case 0: pcurvalue[0] = val; break;
- case 1: pcurvalue[0] |= val<<21; pcurvalue[1] = val>>11; ++pcurvalue; break;
- case 2: pcurvalue[0] |= val<<10; ++pcurvalue; break;
- }
- }
-
- uid.indstages = (u32)(pcurvalue-&uid.values[0]-2-uid.tevstages);
-}
-
#define WRITE p+=sprintf
const char *swapColors = "rgba";
@@ -822,7 +262,7 @@ void BuildSwapModeTable() }
static char text[16384];
-bool PixelShaderMngr::GeneratePixelShader(FRAGMENTSHADER& ps)
+bool GeneratePixelShader(FRAGMENTSHADER& ps)
{
DVSTARTPROFILE();
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShader.h b/Source/Plugins/Plugin_VideoOGL/Src/PixelShader.h index f41c0203b4..51333825cf 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShader.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShader.h @@ -21,6 +21,25 @@ #include "Render.h"
#include "BPStructs.h"
+#define I_COLORS "color"
+#define I_KCOLORS "k"
+#define I_ALPHA "alphaRef"
+#define I_TEXDIMS "texdim"
+#define I_ZBIAS "czbias"
+#define I_INDTEXSCALE "cindscale"
+#define I_INDTEXMTX "cindmtx"
+
+#define C_COLORS 0
+#define C_KCOLORS (C_COLORS+4)
+#define C_ALPHA (C_KCOLORS+4)
+#define C_TEXDIMS (C_ALPHA+1)
+#define C_ZBIAS (C_TEXDIMS+8)
+#define C_INDTEXSCALE (C_ZBIAS+2)
+#define C_INDTEXMTX (C_INDTEXSCALE+2)
+#define C_ENVCONST_END (C_INDTEXMTX+6)
+
+#define C_COLORMATRIX (C_INDTEXMTX+6)
+
struct FRAGMENTSHADER
{
FRAGMENTSHADER() : glprogid(0) { }
@@ -31,124 +50,6 @@ struct FRAGMENTSHADER #endif
};
-class PixelShaderMngr
-{
- class PIXELSHADERUID
- {
- public:
- PIXELSHADERUID() { values = new u32[3+32+6+11]; tevstages = indstages = 0; }
- ~PIXELSHADERUID() { delete[] values; }
- PIXELSHADERUID(const PIXELSHADERUID& r)
- {
- values = new u32[4+32+6+11];
- tevstages = r.tevstages; indstages = r.indstages;
- int N = tevstages + indstages + 3;
- _assert_(N <= 4+32+6+11);
- for(int i = 0; i < N; ++i)
- values[i] = r.values[i];
- }
-
- bool operator <(const PIXELSHADERUID& _Right) const
- {
- if( values[0] < _Right.values[0] )
- return true;
- else if( values[0] > _Right.values[0] )
- return false;
-
- int N = tevstages + 3; // numTevStages*3/2+1
- int i = 1;
- for(; i < N; ++i) {
- if( values[i] < _Right.values[i] )
- return true;
- else if( values[i] > _Right.values[i] )
- return false;
- }
-
- N += indstages;
- for(; i < N; ++i) {
- if( values[i] < _Right.values[i] )
- return true;
- else if( values[i] > _Right.values[i] )
- return false;
- }
-
- return false;
- }
-
- bool operator ==(const PIXELSHADERUID& _Right) const
- {
- if( values[0] != _Right.values[0] )
- return false;
-
- int N = tevstages + 3; // numTevStages*3/2+1
- int i = 1;
- for(; i < N; ++i) {
- if( values[i] != _Right.values[i] )
- return false;
- }
-
- N += indstages;
- for(; i < N; ++i) {
- if( values[i] != _Right.values[i] )
- return false;
- }
-
- return true;
- }
-
- u32* values;
- u16 tevstages, indstages;
- };
-
- struct PSCacheEntry
- {
- FRAGMENTSHADER shader;
- int frameCount;
- PSCacheEntry() : frameCount(0) {}
- ~PSCacheEntry() {}
- void Destroy() {
- glDeleteProgramsARB(1, &shader.glprogid);
- }
- };
-
- typedef std::map<PIXELSHADERUID,PSCacheEntry> PSCache;
-
- static FRAGMENTSHADER* pShaderLast; // last used shader
- static PSCache pshaders;
-
- static bool GeneratePixelShader(FRAGMENTSHADER& ps);
- static void GetPixelShaderId(PIXELSHADERUID&);
- static PIXELSHADERUID s_curuid; // the current pixel shader uid (progressively changed as memory is written)
-
-public:
- static void Init();
- static void Cleanup();
- static void Shutdown();
- static FRAGMENTSHADER* GetShader();
- static bool CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram);
-
- static void SetConstants(FRAGMENTSHADER& ps); // sets pixel shader constants
-
- // constant management, should be called after memory is committed
- static void SetColorChanged(int type, int index);
- static void SetAlpha(const AlphaFunc& alpha);
- static void SetDestAlpha(const ConstantAlpha& alpha);
- static void SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt);
- static void SetZTetureBias(u32 bias);
- static void SetIndTexScaleChanged();
- static void SetIndMatrixChanged(int matrixidx);
-
- static void SetGenModeChanged();
- static void SetTevCombinerChanged(int id);
- static void SetTevKSelChanged(int id);
- static void SetTevOrderChanged(int id);
- static void SetTevIndirectChanged(int id);
- static void SetZTetureOpChanged();
- static void SetTexturesUsed(u32 nonpow2tex);
- static void SetTexDimsChanged(int texmapid);
-
- static void SetColorMatrix(const float* pmatrix, const float* pfConstAdd);
- static GLuint GetColorMatrixProgram();
-};
+bool GeneratePixelShader(FRAGMENTSHADER& ps);
#endif
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderManager.cpp new file mode 100644 index 0000000000..6351a16c7e --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderManager.cpp @@ -0,0 +1,567 @@ +// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Globals.h"
+
+#include <cmath>
+
+#include "Common.h"
+#include "VertexShader.h"
+#include "PixelShaderManager.h"
+#include "PixelShader.h"
+
+PixelShaderMngr::PSCache PixelShaderMngr::pshaders;
+FRAGMENTSHADER* PixelShaderMngr::pShaderLast = NULL;
+PixelShaderMngr::PIXELSHADERUID PixelShaderMngr::s_curuid;
+
+static int s_nMaxPixelInstructions;
+static int s_nColorsChanged[2]; // 0 - regular colors, 1 - k colors
+static int s_nTexDimsChanged[2], s_nIndTexMtxChanged = 0; //min, max
+static bool s_bAlphaChanged, s_bZBiasChanged, s_bIndTexScaleChanged;
+static float lastRGBAfull[2][4][4] = {0};
+static u32 lastAlpha = 0;
+static u32 lastTexDims[8]={0};
+static u32 lastZBias = 0;
+
+// lower byte describes if a texture is nonpow2 or pow2
+// next byte describes whether the repeat wrap mode is enabled for the s channel
+// next byte is for t channel
+u32 s_texturemask = 0;
+
+static int maptocoord[8]; // indexed by texture map, holds the texcoord associated with the map
+static u32 maptocoord_mask=0;
+
+static GLuint s_ColorMatrixProgram=0;
+
+void PixelShaderMngr::Init()
+{
+ s_nColorsChanged[0] = s_nColorsChanged[1] = 0;
+ s_nTexDimsChanged[0] = s_nTexDimsChanged[1] = -1;
+ s_nIndTexMtxChanged = 15;
+ s_bAlphaChanged = s_bZBiasChanged = s_bIndTexScaleChanged = true;
+ GL_REPORT_ERRORD();
+ for(int i = 0; i < 8; ++i) maptocoord[i] = -1;
+ maptocoord_mask = 0;
+ memset(lastRGBAfull, 0, sizeof(lastRGBAfull));
+
+ glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, &s_nMaxPixelInstructions);
+
+ int maxinst, maxattribs;
+ glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &maxinst);
+ glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, &maxattribs);
+ ERROR_LOG("pixel max_alu=%d, max_inst=%d, max_attrib=%d\n", s_nMaxPixelInstructions, maxinst, maxattribs);
+
+ char pmatrixprog[1024];
+ sprintf(pmatrixprog, "!!ARBfp1.0"
+ "TEMP R0;\n"
+ "TEMP R1;\n"
+ "TEX R0, fragment.texcoord[0], texture[0], RECT;\n"
+ "DP4 R1.w, R0, program.env[%d];\n"
+ "DP4 R1.z, R0, program.env[%d];\n"
+ "DP4 R1.x, R0, program.env[%d];\n"
+ "DP4 R1.y, R0, program.env[%d];\n"
+ "ADD result.color, R1, program.env[%d];\n"
+ "END\n", C_COLORMATRIX+3, C_COLORMATRIX+2, C_COLORMATRIX, C_COLORMATRIX+1, C_COLORMATRIX+4);
+ glGenProgramsARB( 1, &s_ColorMatrixProgram );
+ glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, s_ColorMatrixProgram );
+
+ glProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pmatrixprog), pmatrixprog);
+
+ GLenum err=GL_NO_ERROR;
+ GL_REPORT_ERROR();
+ if( err != GL_NO_ERROR ) {
+ ERROR_LOG("Failed to create color matrix fragment program\n");
+
+ SAFE_RELEASE_PROG(s_ColorMatrixProgram);
+ }
+}
+
+void PixelShaderMngr::Shutdown()
+{
+ SAFE_RELEASE_PROG(s_ColorMatrixProgram);
+ PSCache::iterator iter = pshaders.begin();
+ for (;iter!=pshaders.end();iter++)
+ iter->second.Destroy();
+ pshaders.clear();
+}
+
+FRAGMENTSHADER* PixelShaderMngr::GetShader()
+{
+ DVSTARTPROFILE();
+ PIXELSHADERUID uid;
+ GetPixelShaderId(uid);
+
+ PSCache::iterator iter = pshaders.find(uid);
+
+ if (iter != pshaders.end()) {
+ iter->second.frameCount=frameCount;
+ PSCacheEntry &entry = iter->second;
+ if (&entry.shader != pShaderLast)
+ {
+ pShaderLast = &entry.shader;
+ }
+ return pShaderLast;
+ }
+
+ PSCacheEntry& newentry = pshaders[uid];
+
+ if (!GeneratePixelShader(newentry.shader)) {
+ ERROR_LOG("failed to create pixel shader\n");
+ return NULL;
+ }
+
+ //Make an entry in the table
+ newentry.frameCount=frameCount;
+
+ pShaderLast = &newentry.shader;
+ INCSTAT(stats.numPixelShadersCreated);
+ SETSTAT(stats.numPixelShadersAlive, pshaders.size());
+ return pShaderLast;
+}
+
+void PixelShaderMngr::Cleanup()
+{
+ PSCache::iterator iter = pshaders.begin();
+ while(iter != pshaders.end()) {
+ PSCacheEntry &entry = iter->second;
+ if (entry.frameCount<frameCount-200) {
+ 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 PixelShaderMngr::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
+{
+ CGerror cgerr = cgGetError();
+
+ char stropt[64];
+ sprintf(stropt, "MaxLocalParams=32,NumInstructionSlots=%d", s_nMaxPixelInstructions);
+#ifdef _WIN32
+ const char* opts[] = {"-profileopts",stropt,"-O2","-q",NULL};
+#else
+ const char* opts[] = {"-profileopts",stropt,"-q",NULL};
+#endif
+ CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);
+ if (!cgIsProgram(tempprog) || cgGetError() != CG_NO_ERROR) {
+ ERROR_LOG("Failed to create ps %s:\n", cgGetLastListing(g_cgcontext));
+ ERROR_LOG(pstrprogram);
+ return false;
+ }
+
+ char* pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
+ char* plocal = strstr(pcompiledprog, "program.local");
+ while( plocal != NULL ) {
+ const char* penv = " program.env";
+ memcpy(plocal, penv, 13);
+ plocal = strstr(plocal+13, "program.local");
+ }
+
+ if( Renderer::IsUsingATIDrawBuffers() ) {
+ // sometimes compilation can use ARB_draw_buffers, which would fail for ATI cards
+ char* poptions = strstr(pcompiledprog, "ARB_draw_buffers");
+ if( poptions != NULL ) {
+ poptions[0] = 'A';
+ poptions[1] = 'T';
+ poptions[2] = 'I';
+ }
+ }
+
+ //ERROR_LOG(pcompiledprog);
+ //ERROR_LOG(pstrprogram);
+
+ glGenProgramsARB( 1, &ps.glprogid );
+ glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, ps.glprogid );
+ glProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
+
+ GLenum err = GL_NO_ERROR;
+ GL_REPORT_ERROR();
+ if( err != GL_NO_ERROR ) {
+ ERROR_LOG(pstrprogram);
+ ERROR_LOG(pcompiledprog);
+ }
+
+ cgDestroyProgram(tempprog);
+
+#ifdef _DEBUG
+ ps.strprog = pstrprogram;
+#endif
+ return true;
+}
+
+void PixelShaderMngr::SetConstants(FRAGMENTSHADER& ps)
+{
+ for(int i = 0; i < 2; ++i) {
+ if( s_nColorsChanged[i] ) {
+
+ int baseind = i?C_KCOLORS:C_COLORS;
+ for(int j = 0; j < 4; ++j) {
+ if( s_nColorsChanged[i] & (1<<j) ) {
+ glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, baseind+j, &lastRGBAfull[i][j][0]);
+ }
+ }
+ s_nColorsChanged[i] = 0;
+ }
+ }
+
+ u32 newmask = 0;
+ for(u32 i = 0; i < bpmem.genMode.numtevstages+1; ++i) {
+ if( bpmem.tevorders[i/2].getEnable(i&1) ) {
+ int texmap = bpmem.tevorders[i/2].getTexMap(i&1);
+ maptocoord[texmap] = bpmem.tevorders[i/2].getTexCoord(i&1);
+ newmask |= 1<<texmap;
+ SetTexDimsChanged(i);
+ }
+ }
+
+ if( maptocoord_mask != newmask ) {
+ u32 changes = maptocoord_mask ^ newmask;
+ for(int i = 0; i < 8; ++i) {
+ if( changes&(1<<i) ) {
+ SetTexDimsChanged(i);
+ }
+ if( !(newmask & (1<<i)) ) {
+ maptocoord[i] = -1;
+ }
+ }
+ maptocoord_mask = newmask;
+ }
+
+ if( s_nTexDimsChanged[0] >= 0 ) {
+ float fdims[4];
+ for(int i = s_nTexDimsChanged[0]; i <= s_nTexDimsChanged[1]; ++i) {
+ if( s_texturemask & (1<<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 {
+ 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]);
+ glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_TEXDIMS+i, fdims);
+ }
+ s_nTexDimsChanged[0] = s_nTexDimsChanged[1] = -1;
+ }
+
+ if( s_bAlphaChanged ) {
+ glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, C_ALPHA, (lastAlpha&0xff)/255.0f, ((lastAlpha>>8)&0xff)/255.0f, 0, ((lastAlpha>>16)&0xff)/255.0f);
+ }
+
+ if( s_bZBiasChanged ) {
+ u32 bits;
+ float ffrac = 255.0f/256.0f;
+ float ftemp[4];
+ switch(bpmem.ztex2.type) {
+ case 0:
+ bits = 8;
+ ftemp[0] = ffrac/(256.0f*256.0f); ftemp[1] = ffrac/256.0f; ftemp[2] = ffrac; ftemp[3] = 0;
+ break;
+ case 1:
+ bits = 16;
+ ftemp[0] = 0; ftemp[1] = ffrac/(256.0f*256.0f); ftemp[2] = ffrac/256.0f; ftemp[3] = ffrac;
+ break;
+ case 2:
+ bits = 24;
+ ftemp[0] = ffrac/(256.0f*256.0f); ftemp[1] = ffrac/256.0f; ftemp[2] = ffrac; ftemp[3] = 0;
+ break;
+ }
+ //ERROR_LOG("pixel=%x,%x, bias=%x\n", bpmem.zcontrol.pixel_format, bpmem.ztex2.type, lastZBias);
+ glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_ZBIAS, ftemp);
+ glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, C_ZBIAS+1, 0, 0, 0, (float)( (((int)lastZBias<<8)>>8))/16777216.0f);
+ }
+
+ // indirect incoming texture scales, update all!
+ if( s_bIndTexScaleChanged ) {
+ float f[8];
+
+ for(u32 i = 0; i < bpmem.genMode.numindstages; ++i) {
+ int srctexmap = bpmem.tevindref.getTexMap(i);
+ int texcoord = bpmem.tevindref.getTexCoord(i);
+ TCoordInfo& tc = bpmem.texcoords[texcoord];
+
+ f[2*i] = bpmem.texscale[i/2].getScaleS(i&1) * (float)(tc.s.scale_minus_1+1) / (float)(lastTexDims[srctexmap]&0xffff);
+ f[2*i+1] = bpmem.texscale[i/2].getScaleT(i&1) * (float)(tc.t.scale_minus_1+1) / (float)((lastTexDims[srctexmap]>>16)&0xfff);
+
+ PRIM_LOG("tex indscale%d: %f %f\n", i, f[2*i], f[2*i+1]);
+ }
+
+ glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_INDTEXSCALE, f);
+
+ if( bpmem.genMode.numindstages > 2 )
+ glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_INDTEXSCALE+1, &f[4]);
+
+ s_bIndTexScaleChanged = false;
+ }
+
+ if( s_nIndTexMtxChanged ) {
+ for(int i = 0; i < 3; ++i) {
+ if( s_nIndTexMtxChanged & (1<<i) ) {
+ int scale = ((u32)bpmem.indmtx[i].col0.s0<<0)|((u32)bpmem.indmtx[i].col1.s1<<2)|((u32)bpmem.indmtx[i].col2.s2<<4);
+ float fscale = powf(2.0f,(float)(scale-17)) / 1024.0f;
+
+ // xyz - static matrix
+ //TODO w - dynamic matrix scale / 256...... somehow / 4 works better
+ glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, C_INDTEXMTX+2*i,
+ bpmem.indmtx[i].col0.ma * fscale, bpmem.indmtx[i].col1.mc * fscale, bpmem.indmtx[i].col2.me * fscale, fscale * 256.0f);
+ glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, C_INDTEXMTX+2*i+1,
+ bpmem.indmtx[i].col0.mb * fscale, bpmem.indmtx[i].col1.md * fscale, bpmem.indmtx[i].col2.mf * fscale, fscale * 256.0f);
+
+ PRIM_LOG("indmtx%d: scale=%f, mat=(%f %f %f; %f %f %f)\n", i,
+ 1024.0f*fscale, bpmem.indmtx[i].col0.ma * fscale, bpmem.indmtx[i].col1.mc * fscale, bpmem.indmtx[i].col2.me * fscale,
+ bpmem.indmtx[i].col0.mb * fscale, bpmem.indmtx[i].col1.md * fscale, bpmem.indmtx[i].col2.mf * fscale, fscale);
+ }
+ }
+ s_nIndTexMtxChanged = 0;
+ }
+}
+
+void PixelShaderMngr::SetColorChanged(int type, int num)
+{
+ int r=bpmem.tevregs[num].low.a, a=bpmem.tevregs[num].low.b;
+ int b=bpmem.tevregs[num].high.a, g=bpmem.tevregs[num].high.b;
+ float* pf = &lastRGBAfull[type][num][0];
+ pf[0] = (float)r/255.0f;
+ pf[1] = (float)g/255.0f;
+ pf[2] = (float)b/255.0f;
+ pf[3] = (float)a/255.0f;
+ s_nColorsChanged[type] |= 1 << num;
+ PRIM_LOG("pixel %scolor%d: %f %f %f %f\n", type?"k":"", num, pf[0], pf[1], pf[2], pf[3]);
+}
+
+void PixelShaderMngr::SetAlpha(const AlphaFunc& alpha)
+{
+ if( (alpha.hex&0xffff) != lastAlpha ) {
+ lastAlpha = (lastAlpha&~0xffff)|(alpha.hex&0xffff);
+ s_bAlphaChanged = true;
+ }
+}
+
+void PixelShaderMngr::SetDestAlpha(const ConstantAlpha& alpha)
+{
+ if( alpha.alpha != (lastAlpha>>16) ) {
+ lastAlpha = (lastAlpha&~0xff0000)|((alpha.hex&0xff)<<16);
+ s_bAlphaChanged = true;
+ }
+}
+
+void PixelShaderMngr::SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt)
+{
+ u32 wh = width|(height<<16)|(wraps<<28)|(wrapt<<30);
+ if( lastTexDims[texmapid] != wh ) {
+ lastTexDims[texmapid] = wh;
+ if( s_nTexDimsChanged[0] == -1 ) {
+ 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;
+ }
+ }
+}
+
+void PixelShaderMngr::SetZTetureBias(u32 bias)
+{
+ if( lastZBias != bias ) {
+ s_bZBiasChanged = true;
+ lastZBias = bias;
+ }
+}
+
+void PixelShaderMngr::SetIndTexScaleChanged()
+{
+ s_bIndTexScaleChanged = true;
+}
+
+void PixelShaderMngr::SetIndMatrixChanged(int matrixidx)
+{
+ s_nIndTexMtxChanged |= 1 << matrixidx;
+}
+
+void PixelShaderMngr::SetGenModeChanged()
+{
+}
+
+void PixelShaderMngr::SetTevCombinerChanged(int id)
+{
+}
+
+void PixelShaderMngr::SetTevKSelChanged(int id)
+{
+}
+
+void PixelShaderMngr::SetTevOrderChanged(int id)
+{
+}
+
+void PixelShaderMngr::SetTevIndirectChanged(int id)
+{
+}
+
+void PixelShaderMngr::SetZTetureOpChanged()
+{
+ s_bZBiasChanged = true;
+}
+
+void PixelShaderMngr::SetTexturesUsed(u32 nonpow2tex)
+{
+ if( s_texturemask != nonpow2tex ) {
+ u32 mask = s_texturemask ^ nonpow2tex;
+ for(int i = 0; i < 8; ++i) {
+ if( mask & (0x10101<<i) ) {
+ if( s_nTexDimsChanged[0] > i ) s_nTexDimsChanged[0] = i;
+ else if( s_nTexDimsChanged[1] < i ) s_nTexDimsChanged[1] = i;
+ }
+ }
+ s_texturemask = nonpow2tex;
+ }
+}
+
+void PixelShaderMngr::SetTexDimsChanged(int texmapid)
+{
+ if( s_nTexDimsChanged[0] > texmapid ) s_nTexDimsChanged[0] = texmapid;
+ else if( s_nTexDimsChanged[1] < texmapid ) s_nTexDimsChanged[1] = texmapid;
+ SetIndTexScaleChanged();
+}
+
+void PixelShaderMngr::SetColorMatrix(const float* pmatrix, const float* pfConstAdd)
+{
+ glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_COLORMATRIX, pmatrix);
+ glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_COLORMATRIX+1, pmatrix+4);
+ glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_COLORMATRIX+2, pmatrix+8);
+ glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_COLORMATRIX+3, pmatrix+12);
+ glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, C_COLORMATRIX+4, pfConstAdd);
+}
+
+GLuint PixelShaderMngr::GetColorMatrixProgram()
+{
+ return s_ColorMatrixProgram;
+}
+
+void PixelShaderMngr::GetPixelShaderId(PixelShaderMngr::PIXELSHADERUID& uid)
+{
+ u32 projtexcoords = 0;
+ for (u32 i = 0; i < bpmem.genMode.numtevstages+1; i++) {
+ if( bpmem.tevorders[i/2].getEnable(i&1) ) {
+ int texcoord = bpmem.tevorders[i/2].getTexCoord(i&1);
+ if( xfregs.texcoords[texcoord].texmtxinfo.projection )
+ projtexcoords |= 1<<texcoord;
+ }
+ }
+
+ u32 zbufrender = (Renderer::GetZBufferTarget()&&bpmem.zmode.updateenable)?1:0;
+ u32 zBufRenderToCol0 = Renderer::GetRenderMode()!=Renderer::RM_Normal;
+ uid.values[0] = (u32)bpmem.genMode.numtevstages|((u32)bpmem.genMode.numindstages<<4)|((u32)bpmem.genMode.numtexgens<<7)
+ |((u32)bpmem.dstalpha.enable<<11)|((u32)((bpmem.alphaFunc.hex>>16)&0xff)<<12)|(projtexcoords<<20)|((u32)bpmem.ztex2.op<<28)
+ |(zbufrender<<30)|(zBufRenderToCol0<<31);
+
+ s_curuid.values[0] = (s_curuid.values[0]&~0x0ff00000)|(projtexcoords<<20);
+
+ // swap table
+ for(int i = 0; i < 8; i += 2)
+ ((u8*)&uid.values[1])[i/2] = (bpmem.tevksel[i].hex&0xf)|((bpmem.tevksel[i+1].hex&0xf)<<4);
+
+ uid.values[2] = s_texturemask;
+ int hdr = 3;
+
+ u32* pcurvalue = &uid.values[hdr];
+ for(u32 i = 0; i < bpmem.genMode.numtevstages+1; ++i) {
+ TevStageCombiner::ColorCombiner &cc = bpmem.combiners[i].colorC;
+ TevStageCombiner::AlphaCombiner &ac = bpmem.combiners[i].alphaC;
+
+ u32 val0 = cc.hex&0xffffff;
+ u32 val1 = ac.hex&0xffffff;
+ val0 |= bpmem.tevksel[i/2].getKC(i&1)<<24;
+ val1 |= bpmem.tevksel[i/2].getKA(i&1)<<24;
+
+ pcurvalue[0] = val0;
+ pcurvalue[1] = val1;
+ pcurvalue+=2;
+ }
+
+ for(u32 i = 0; i < (bpmem.genMode.numtevstages+1)/2; ++i) {
+ u32 val0, val1;
+ if( bpmem.tevorders[i].hex&0x40 ) val0 = bpmem.tevorders[i].hex&0x3ff;
+ else val0 = bpmem.tevorders[i].hex&0x380;
+ if( bpmem.tevorders[i].hex&0x40000 ) val1 = (bpmem.tevorders[i].hex&0x3ff000)>>12;
+ else val1 = (bpmem.tevorders[i].hex&0x380000)>>12;
+
+ switch(i % 3) {
+ case 0: pcurvalue[0] = val0|(val1<<10); break;
+ case 1: pcurvalue[0] |= val0<<20; pcurvalue[1] = val1; pcurvalue++; break;
+ case 2: pcurvalue[1] |= (val0<<10)|(val1<<20); pcurvalue++; break;
+ }
+ }
+
+ if( (bpmem.genMode.numtevstages+1)&1 ) { // odd
+ u32 val0;
+ if( bpmem.tevorders[bpmem.genMode.numtevstages/2].hex&0x40 ) val0 = bpmem.tevorders[bpmem.genMode.numtevstages/2].hex&0x3ff;
+ else val0 = bpmem.tevorders[bpmem.genMode.numtevstages/2].hex&0x380;
+
+ switch(bpmem.genMode.numtevstages % 3) {
+ case 0: pcurvalue[0] = val0; break;
+ case 1: pcurvalue[0] |= val0<<20; break;
+ case 2: pcurvalue[1] |= (val0<<10); pcurvalue++; break;
+ }
+ }
+
+ if( (bpmem.genMode.numtevstages % 3) != 2 )
+ ++pcurvalue;
+
+ uid.tevstages = (u32)(pcurvalue-&uid.values[0]-hdr);
+
+ for(u32 i = 0; i < bpmem.genMode.numindstages; ++i) {
+ u32 val = bpmem.tevind[i].hex&0x1fffff; // 21 bits
+ switch(i%3) {
+ case 0: pcurvalue[0] = val; break;
+ case 1: pcurvalue[0] |= val<<21; pcurvalue[1] = val>>11; ++pcurvalue; break;
+ case 2: pcurvalue[0] |= val<<10; ++pcurvalue; break;
+ }
+ }
+
+ uid.indstages = (u32)(pcurvalue-&uid.values[0]-2-uid.tevstages);
+}
\ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderManager.h b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderManager.h new file mode 100644 index 0000000000..174996365b --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderManager.h @@ -0,0 +1,145 @@ +// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef _PIXELSHADERMANAGER_H
+#define _PIXELSHADERMANAGER_H
+
+#include "PixelShader.h"
+
+extern u32 s_texturemask;
+
+class PixelShaderMngr
+{
+ class PIXELSHADERUID
+ {
+ public:
+ PIXELSHADERUID() { values = new u32[3+32+6+11]; tevstages = indstages = 0; }
+ ~PIXELSHADERUID() { delete[] values; }
+ PIXELSHADERUID(const PIXELSHADERUID& r)
+ {
+ values = new u32[4+32+6+11];
+ tevstages = r.tevstages; indstages = r.indstages;
+ int N = tevstages + indstages + 3;
+ _assert_(N <= 4+32+6+11);
+ for(int i = 0; i < N; ++i)
+ values[i] = r.values[i];
+ }
+
+ bool operator <(const PIXELSHADERUID& _Right) const
+ {
+ if( values[0] < _Right.values[0] )
+ return true;
+ else if( values[0] > _Right.values[0] )
+ return false;
+
+ int N = tevstages + 3; // numTevStages*3/2+1
+ int i = 1;
+ for(; i < N; ++i) {
+ if( values[i] < _Right.values[i] )
+ return true;
+ else if( values[i] > _Right.values[i] )
+ return false;
+ }
+
+ N += indstages;
+ for(; i < N; ++i) {
+ if( values[i] < _Right.values[i] )
+ return true;
+ else if( values[i] > _Right.values[i] )
+ return false;
+ }
+
+ return false;
+ }
+
+ bool operator ==(const PIXELSHADERUID& _Right) const
+ {
+ if( values[0] != _Right.values[0] )
+ return false;
+
+ int N = tevstages + 3; // numTevStages*3/2+1
+ int i = 1;
+ for(; i < N; ++i) {
+ if( values[i] != _Right.values[i] )
+ return false;
+ }
+
+ N += indstages;
+ for(; i < N; ++i) {
+ if( values[i] != _Right.values[i] )
+ return false;
+ }
+
+ return true;
+ }
+
+ u32* values;
+ u16 tevstages, indstages;
+ };
+
+ struct PSCacheEntry
+ {
+ FRAGMENTSHADER shader;
+ int frameCount;
+ PSCacheEntry() : frameCount(0) {}
+ ~PSCacheEntry() {}
+ void Destroy() {
+ glDeleteProgramsARB(1, &shader.glprogid);
+ }
+ };
+
+ typedef std::map<PIXELSHADERUID,PSCacheEntry> PSCache;
+
+ static FRAGMENTSHADER* pShaderLast; // last used shader
+ static PSCache pshaders;
+
+ static void GetPixelShaderId(PIXELSHADERUID&);
+ static PIXELSHADERUID s_curuid; // the current pixel shader uid (progressively changed as memory is written)
+
+public:
+ static void Init();
+ static void Cleanup();
+ static void Shutdown();
+ static FRAGMENTSHADER* GetShader();
+ static bool CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram);
+
+ static void SetConstants(FRAGMENTSHADER& ps); // sets pixel shader constants
+
+ // constant management, should be called after memory is committed
+ static void SetColorChanged(int type, int index);
+ static void SetAlpha(const AlphaFunc& alpha);
+ static void SetDestAlpha(const ConstantAlpha& alpha);
+ static void SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt);
+ static void SetZTetureBias(u32 bias);
+ static void SetIndTexScaleChanged();
+ static void SetIndMatrixChanged(int matrixidx);
+
+ static void SetGenModeChanged();
+ static void SetTevCombinerChanged(int id);
+ static void SetTevKSelChanged(int id);
+ static void SetTevOrderChanged(int id);
+ static void SetTevIndirectChanged(int id);
+ static void SetZTetureOpChanged();
+ static void SetTexturesUsed(u32 nonpow2tex);
+ static void SetTexDimsChanged(int texmapid);
+
+ static void SetColorMatrix(const float* pmatrix, const float* pfConstAdd);
+ static GLuint GetColorMatrixProgram();
+};
+
+
+#endif
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 707b249590..515a460694 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -25,7 +25,7 @@ #include "TextureMngr.h"
#include "rasterfont.h"
#include "VertexShader.h"
-#include "PixelShader.h"
+#include "PixelShaderManager.h"
#include "VertexLoader.h"
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp index 3525c310a3..e3a177927f 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp @@ -27,8 +27,8 @@ #include "BPStructs.h"
#include "TextureDecoder.h"
#include "TextureMngr.h"
-#include "PixelShader.h"
-#include "VertexShader.h"
+#include "PixelShaderManager.h"
+#include "VertexShaderManager.h"
u8 *TextureMngr::temp = NULL;
TextureMngr::TexCache TextureMngr::textures;
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.cpp index 3967618883..5e256c7560 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexLoader.cpp @@ -25,8 +25,8 @@ #include "BPStructs.h"
#include "DataReader.h"
-#include "VertexShader.h"
-#include "PixelShader.h"
+#include "VertexShaderManager.h"
+#include "PixelShaderManager.h"
#include "TextureMngr.h"
#include "MemoryUtil.h"
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShader.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexShader.cpp index f181549440..646f6d3768 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexShader.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexShader.cpp @@ -20,790 +20,18 @@ #include <math.h>
#include "Render.h"
#include "VertexShader.h"
+#include "VertexShaderManager.h"
#include "BPStructs.h"
#include "VertexLoader.h"
-// shader variables
-#define I_POSNORMALMATRIX "cpnmtx"
-#define I_PROJECTION "cproj"
-#define I_MATERIALS "cmtrl"
-#define I_LIGHTS "clights"
-#define I_TEXMATRICES "ctexmtx"
-#define I_TRANSFORMMATRICES "ctrmtx"
-#define I_NORMALMATRICES "cnmtx"
-#define I_POSTTRANSFORMMATRICES "cpostmtx"
-#define I_FOGPARAMS "cfog"
-
-#define C_POSNORMALMATRIX 0
-#define C_PROJECTION (C_POSNORMALMATRIX+6)
-#define C_MATERIALS (C_PROJECTION+4)
-#define C_LIGHTS (C_MATERIALS+4)
-#define C_TEXMATRICES (C_LIGHTS+40)
-#define C_TRANSFORMMATRICES (C_TEXMATRICES+24)
-#define C_NORMALMATRICES (C_TRANSFORMMATRICES+64)
-#define C_POSTTRANSFORMMATRICES (C_NORMALMATRICES+32)
-#define C_FOGPARAMS (C_POSTTRANSFORMMATRICES+64)
-
-VertexShaderMngr::VSCache VertexShaderMngr::vshaders;
-VERTEXSHADER* VertexShaderMngr::pShaderLast = NULL;
-TMatrixIndexA VertexShaderMngr::MatrixIndexA;
-TMatrixIndexB VertexShaderMngr::MatrixIndexB;
-float VertexShaderMngr::rawViewport[6] = {0};
-float VertexShaderMngr::rawProjection[7] = {0};
-float GC_ALIGNED16(g_fProjectionMatrix[16]);
-
-static int s_nMaxVertexInstructions;
-
-////////////////////////
-// Internal Variables //
-////////////////////////
-XFRegisters xfregs;
-static u32 xfmem[XFMEM_SIZE];
-static float s_fMaterials[16];
-
-// track changes
-static bool bTexMatricesChanged[2], bPosNormalMatrixChanged, bProjectionChanged, bViewportChanged;
-int nMaterialsChanged;
-static int nTransformMatricesChanged[2]; // min,max
-static int nNormalMatricesChanged[2]; // min,max
-static int nPostTransformMatricesChanged[2]; // min,max
-static int nLightsChanged[2]; // min,max
-
-void VertexShaderMngr::Init()
-{
- nTransformMatricesChanged[0] = nTransformMatricesChanged[1] = -1;
- nNormalMatricesChanged[0] = nNormalMatricesChanged[1] = -1;
- nPostTransformMatricesChanged[0] = nPostTransformMatricesChanged[1] = -1;
- nLightsChanged[0] = nLightsChanged[1] = -1;
- bTexMatricesChanged[0] = bTexMatricesChanged[1] = false;
- bPosNormalMatrixChanged = bProjectionChanged = bViewportChanged = false;
- nMaterialsChanged = 0;
-
- memset(&xfregs, 0, sizeof(xfregs));
- memset(xfmem, 0, sizeof(xfmem));
-
- glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &s_nMaxVertexInstructions);
-}
-
-void VertexShaderMngr::Shutdown()
-{
- VSCache::iterator iter = vshaders.begin();
- for (;iter!=vshaders.end();iter++)
- iter->second.Destroy();
- vshaders.clear();
-}
-
-VERTEXSHADER* VertexShaderMngr::GetShader(u32 components)
-{
- DVSTARTPROFILE();
- VERTEXSHADERUID uid;
- GetVertexShaderId(uid, components);
-
- VSCache::iterator iter = vshaders.find(uid);
-
- if (iter != vshaders.end()) {
- iter->second.frameCount=frameCount;
- VSCacheEntry &entry = iter->second;
- if (&entry.shader != pShaderLast) {
- pShaderLast = &entry.shader;
- }
- return pShaderLast;
- }
-
- VSCacheEntry& entry = vshaders[uid];
-
- if (!GenerateVertexShader(entry.shader, components)) {
- ERROR_LOG("failed to create vertex shader\n");
- }
-
- //Make an entry in the table
- entry.frameCount=frameCount;
-
- pShaderLast = &entry.shader;
- INCSTAT(stats.numVertexShadersCreated);
- SETSTAT(stats.numVertexShadersAlive,vshaders.size());
- return pShaderLast;
-}
-
-void VertexShaderMngr::Cleanup()
-{
- 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;
- }
- }
-
-// static int frame = 0;
-// if( frame++ > 30 ) {
-// VSCache::iterator iter=vshaders.begin();
-// while(iter!=vshaders.end()) {
-// iter->second.Destroy();
-// ++iter;
-// }
-// vshaders.clear();
-// }
-
- SETSTAT(stats.numPixelShadersAlive,vshaders.size());
-}
-
-bool VertexShaderMngr::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
-{
- char stropt[64];
- sprintf(stropt, "MaxLocalParams=256,MaxInstructions=%d", s_nMaxVertexInstructions);
-#ifdef _WIN32
- const char* opts[] = {"-profileopts",stropt,"-O2", "-q", NULL};
-#else
- const char* opts[] = {"-profileopts",stropt,"-q", NULL};
-#endif
- CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgvProf, "main", opts);
- if (!cgIsProgram(tempprog) || cgGetError() != CG_NO_ERROR) {
- ERROR_LOG("Failed to load vs %s:\n", cgGetLastListing(g_cgcontext));
- ERROR_LOG(pstrprogram);
- return false;
- }
-
- //ERROR_LOG(pstrprogram);
- //ERROR_LOG("id: %d\n", g_Config.iSaveTargetId);
-
- char* pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
- char* plocal = strstr(pcompiledprog, "program.local");
-
- while( plocal != NULL ) {
- const char* penv = " program.env";
- memcpy(plocal, penv, 13);
- plocal = strstr(plocal+13, "program.local");
- }
-
- glGenProgramsARB( 1, &vs.glprogid );
- glBindProgramARB( GL_VERTEX_PROGRAM_ARB, vs.glprogid );
- glProgramStringARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
-
- GLenum err = GL_NO_ERROR;
- GL_REPORT_ERROR();
- if( err != GL_NO_ERROR ) {
- ERROR_LOG(pstrprogram);
- ERROR_LOG(pcompiledprog);
- }
-
- cgDestroyProgram(tempprog);
-
-#ifdef _DEBUG
- vs.strprog = pstrprogram;
-#endif
-
- return true;
-}
-
-// TODO: this array is misdeclared. Why teh f** does it go through the compilers?
-const u16 s_mtrltable[16][2] = {0, 0, 0, 1, 1, 1, 0, 2,
- 2, 1, 0, 3, 1, 2, 0, 3,
- 3, 1, 0, 4, 1, 3, 0, 4,
- 2, 2, 0, 4, 1, 3, 0, 4};
-
-/// syncs the shader constant buffers with xfmem
-void VertexShaderMngr::SetConstants(VERTEXSHADER& vs)
-{
- //nTransformMatricesChanged[0] = 0; nTransformMatricesChanged[1] = 256;
- //nNormalMatricesChanged[0] = 0; nNormalMatricesChanged[1] = 96;
- //nPostTransformMatricesChanged[0] = 0; nPostTransformMatricesChanged[1] = 256;
- //nLightsChanged[0] = 0; nLightsChanged[1] = 0x80;
- //bPosNormalMatrixChanged = true;
- //bTexMatricesChanged[0] = bTexMatricesChanged[1] = true;
- //bProjectionChanged = true;
-// bPosNormalMatrixChanged = bTexMatricesChanged[0] = bTexMatricesChanged[1] = true;
-// nMaterialsChanged = 15;
-
- if (nTransformMatricesChanged[0] >= 0) {
- int startn = nTransformMatricesChanged[0]/4;
- int endn = (nTransformMatricesChanged[1]+3)/4;
- const float* pstart = (const float*)&xfmem[startn*4];
- for(int i = startn; i < endn; ++i, pstart += 4)
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TRANSFORMMATRICES+i, pstart);
- nTransformMatricesChanged[0] = nTransformMatricesChanged[1] = -1;
- }
- if (nNormalMatricesChanged[0] >= 0) {
- int startn = nNormalMatricesChanged[0]/3;
- int endn = (nNormalMatricesChanged[1]+2)/3;
- const float* pnstart = (const float*)&xfmem[XFMEM_NORMALMATRICES+3*startn];
-
- for(int i = startn; i < endn; ++i, pnstart += 3)
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_NORMALMATRICES+i, pnstart);
-
- nNormalMatricesChanged[0] = nNormalMatricesChanged[1] = -1;
- }
-
- if (nPostTransformMatricesChanged[0] >= 0) {
- int startn = nPostTransformMatricesChanged[0]/4;
- int endn = (nPostTransformMatricesChanged[1]+3)/4;
- const float* pstart = (const float*)&xfmem[XFMEM_POSTMATRICES+startn*4];
- for(int i = startn; i < endn; ++i, pstart += 4)
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSTTRANSFORMMATRICES+i, pstart);
- }
-
- if (nLightsChanged[0] >= 0) {
- // lights don't have a 1 to 1 mapping, the color component needs to be converted to 4 floats
- int istart = nLightsChanged[0]/0x10;
- int iend = (nLightsChanged[1]+15)/0x10;
- const float* xfmemptr = (const float*)&xfmem[0x10*istart+XFMEM_LIGHTS];
-
- for(int i = istart; i < iend; ++i) {
- u32 color = *(const u32*)(xfmemptr+3);
- glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, C_LIGHTS+5*i,
- ((color>>24)&0xFF)/255.0f, ((color>>16)&0xFF)/255.0f, ((color>>8)&0xFF)/255.0f, ((color)&0xFF)/255.0f);
- xfmemptr += 4;
- for(int j = 0; j < 4; ++j, xfmemptr += 3) {
- if( j == 1 && fabs(xfmemptr[0]) < 0.00001f && fabs(xfmemptr[1]) < 0.00001f && fabs(xfmemptr[2]) < 0.00001f) {
- // dist atten, make sure not equal to 0!!!
- glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, C_LIGHTS+5*i+j+1, 0.00001f, xfmemptr[1], xfmemptr[2], 0);
- }
- else
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_LIGHTS+5*i+j+1, xfmemptr);
- }
- }
-
- nLightsChanged[0] = nLightsChanged[1] = -1;
- }
-
- if (nMaterialsChanged) {
- for(int i = 0; i < 4; ++i) {
- if( nMaterialsChanged&(1<<i) )
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_MATERIALS+i, &s_fMaterials[4*i]);
- }
- nMaterialsChanged = 0;
- }
-
- if (bPosNormalMatrixChanged) {
- bPosNormalMatrixChanged = false;
-
- float* pos = (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4;
- float* norm = (float*)xfmem + XFMEM_NORMALMATRICES + 3 * (MatrixIndexA.PosNormalMtxIdx & 31);
-
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSNORMALMATRIX, pos);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSNORMALMATRIX+1, pos+4);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSNORMALMATRIX+2, pos+8);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSNORMALMATRIX+3, norm);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSNORMALMATRIX+4, norm+3);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSNORMALMATRIX+5, norm+6);
- }
-
- if (bTexMatricesChanged[0]) {
- bTexMatricesChanged[0] = false;
-
- float* fptrs[] = {(float*)xfmem + MatrixIndexA.Tex0MtxIdx * 4, (float*)xfmem + MatrixIndexA.Tex1MtxIdx * 4,
- (float*)xfmem + MatrixIndexA.Tex2MtxIdx * 4, (float*)xfmem + MatrixIndexA.Tex3MtxIdx * 4 };
-
- for(int i = 0; i < 4; ++i) {
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TEXMATRICES+3*i, fptrs[i]);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TEXMATRICES+3*i+1, fptrs[i]+4);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TEXMATRICES+3*i+2, fptrs[i]+8);
- }
- }
-
- if (bTexMatricesChanged[1]) {
- bTexMatricesChanged[1] = false;
-
- float* fptrs[] = {(float*)xfmem + MatrixIndexB.Tex4MtxIdx * 4, (float*)xfmem + MatrixIndexB.Tex5MtxIdx * 4,
- (float*)xfmem + MatrixIndexB.Tex6MtxIdx * 4, (float*)xfmem + MatrixIndexB.Tex7MtxIdx * 4 };
-
- for(int i = 0; i < 4; ++i) {
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TEXMATRICES+3*i+12, fptrs[i]);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TEXMATRICES+3*i+12+1, fptrs[i]+4);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TEXMATRICES+3*i+12+2, fptrs[i]+8);
- }
- }
-
- if (bViewportChanged) {
- bViewportChanged = false;
-
- // reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
- // [0] = width/2
- // [1] = height/2
- // [2] = 16777215 * (farz-nearz)
- // [3] = xorig + width/2 + 342
- // [4] = yorig + height/2 + 342
- // [5] = 16777215 * farz
- INFO_LOG("view: topleft=(%f,%f), wh=(%f,%f), z=(%f,%f)\n",rawViewport[3]-rawViewport[0]-342,rawViewport[4]+rawViewport[1]-342,
- 2 * rawViewport[0], 2 * rawViewport[1], (rawViewport[5]-rawViewport[2])/16777215.0f, rawViewport[5]/16777215.0f);
- glViewport((int)(rawViewport[3]-rawViewport[0]-342)<<g_AAx,Renderer::GetTargetHeight()-((int)(rawViewport[4]-rawViewport[1]-342)<<g_AAy), abs((int)(2 * rawViewport[0])), abs((int)(2 * rawViewport[1])));
- glDepthRange((rawViewport[5]-rawViewport[2])/16777215.0f, rawViewport[5]/16777215.0f);
- }
-
- if (bProjectionChanged) {
- bProjectionChanged = false;
-
- if (rawProjection[6] == 0) {
- g_fProjectionMatrix[0] = rawProjection[0];
- g_fProjectionMatrix[1] = 0.0f;
- g_fProjectionMatrix[2] = rawProjection[1];
- g_fProjectionMatrix[3] = 0;//-0.5f/Renderer::GetTargetWidth();
-
- g_fProjectionMatrix[4] = 0.0f;
- g_fProjectionMatrix[5] = rawProjection[2];
- g_fProjectionMatrix[6] = rawProjection[3];
- g_fProjectionMatrix[7] = 0;//+0.5f/Renderer::GetTargetHeight();
-
- g_fProjectionMatrix[8] = 0.0f;
- g_fProjectionMatrix[9] = 0.0f;
- g_fProjectionMatrix[10] = -(1-rawProjection[4]);
- g_fProjectionMatrix[11] = rawProjection[5];
-
- g_fProjectionMatrix[12] = 0.0f;
- g_fProjectionMatrix[13] = 0.0f;
- g_fProjectionMatrix[14] = -1.0f;
- g_fProjectionMatrix[15] = 0.0f;
- }
- else {
- g_fProjectionMatrix[0] = rawProjection[0];
- g_fProjectionMatrix[1] = 0.0f;
- g_fProjectionMatrix[2] = 0.0f;
- g_fProjectionMatrix[3] = rawProjection[1];
-
- g_fProjectionMatrix[4] = 0.0f;
- g_fProjectionMatrix[5] = rawProjection[2];
- g_fProjectionMatrix[6] = 0.0f;
- g_fProjectionMatrix[7] = rawProjection[3];
-
- g_fProjectionMatrix[8] = 0.0f;
- g_fProjectionMatrix[9] = 0.0f;
- g_fProjectionMatrix[10] = rawProjection[4];
- g_fProjectionMatrix[11] = -(-1 - rawProjection[5]);
-
- g_fProjectionMatrix[12] = 0;
- g_fProjectionMatrix[13] = 0;
- g_fProjectionMatrix[14] = 0.0f;
- g_fProjectionMatrix[15] = 1.0f;
- }
-
- PRIM_LOG("Projection: %f %f %f %f %f %f\n",rawProjection[0], rawProjection[1], rawProjection[2], rawProjection[3], rawProjection[4], rawProjection[5]);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_PROJECTION, &g_fProjectionMatrix[0]);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_PROJECTION+1, &g_fProjectionMatrix[4]);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_PROJECTION+2, &g_fProjectionMatrix[8]);
- glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_PROJECTION+3, &g_fProjectionMatrix[12]);
- }
-}
-
-void VertexShaderMngr::InvalidateXFRange(int start, int end)
-{
- if( ((u32)start >= MatrixIndexA.PosNormalMtxIdx*4 && (u32)start < MatrixIndexA.PosNormalMtxIdx*4+12) ||
- ((u32)start >= XFMEM_NORMALMATRICES+(MatrixIndexA.PosNormalMtxIdx&31)*3 && (u32)start < XFMEM_NORMALMATRICES+(MatrixIndexA.PosNormalMtxIdx&31)*3+9) ) {
- bPosNormalMatrixChanged = true;
- }
-
- if (((u32)start >= MatrixIndexA.Tex0MtxIdx*4 && (u32)start < MatrixIndexA.Tex0MtxIdx*4+12) ||
- ((u32)start >= MatrixIndexA.Tex1MtxIdx*4 && (u32)start < MatrixIndexA.Tex1MtxIdx*4+12) ||
- ((u32)start >= MatrixIndexA.Tex2MtxIdx*4 && (u32)start < MatrixIndexA.Tex2MtxIdx*4+12) ||
- ((u32)start >= MatrixIndexA.Tex3MtxIdx*4 && (u32)start < MatrixIndexA.Tex3MtxIdx*4+12)) {
- bTexMatricesChanged[0] = true;
- }
-
- if (((u32)start >= MatrixIndexB.Tex4MtxIdx*4 && (u32)start < MatrixIndexB.Tex4MtxIdx*4+12) ||
- ((u32)start >= MatrixIndexB.Tex5MtxIdx*4 && (u32)start < MatrixIndexB.Tex5MtxIdx*4+12) ||
- ((u32)start >= MatrixIndexB.Tex6MtxIdx*4 && (u32)start < MatrixIndexB.Tex6MtxIdx*4+12) ||
- ((u32)start >= MatrixIndexB.Tex7MtxIdx*4 && (u32)start < MatrixIndexB.Tex7MtxIdx*4+12)) {
- bTexMatricesChanged[1] = true;
- }
-
- if (start < XFMEM_POSMATRICES_END ) {
- if (nTransformMatricesChanged[0] == -1) {
- nTransformMatricesChanged[0] = start;
- nTransformMatricesChanged[1] = end>XFMEM_POSMATRICES_END?XFMEM_POSMATRICES_END:end;
- }
- else {
- if (nTransformMatricesChanged[0] > start) nTransformMatricesChanged[0] = start;
- if (nTransformMatricesChanged[1] < end) nTransformMatricesChanged[1] = end>XFMEM_POSMATRICES_END?XFMEM_POSMATRICES_END:end;
- }
- }
-
- if (start < XFMEM_NORMALMATRICES_END && end > XFMEM_NORMALMATRICES ) {
- int _start = start < XFMEM_NORMALMATRICES ? 0 : start-XFMEM_NORMALMATRICES;
- int _end = end < XFMEM_NORMALMATRICES_END ? end-XFMEM_NORMALMATRICES : XFMEM_NORMALMATRICES_END-XFMEM_NORMALMATRICES;
-
- if (nNormalMatricesChanged[0] == -1 ) {
- nNormalMatricesChanged[0] = _start;
- nNormalMatricesChanged[1] = _end;
- }
- else {
- if (nNormalMatricesChanged[0] > _start) nNormalMatricesChanged[0] = _start;
- if (nNormalMatricesChanged[1] < _end) nNormalMatricesChanged[1] = _end;
- }
- }
-
- if (start < XFMEM_POSTMATRICES_END && end > XFMEM_POSTMATRICES ) {
- int _start = start < XFMEM_POSTMATRICES ? XFMEM_POSTMATRICES : start-XFMEM_POSTMATRICES;
- int _end = end < XFMEM_POSTMATRICES_END ? end-XFMEM_POSTMATRICES : XFMEM_POSTMATRICES_END-XFMEM_POSTMATRICES;
-
- if (nPostTransformMatricesChanged[0] == -1 ) {
- nPostTransformMatricesChanged[0] = _start;
- nPostTransformMatricesChanged[1] = _end;
- }
- else {
- if (nPostTransformMatricesChanged[0] > _start) nPostTransformMatricesChanged[0] = _start;
- if (nPostTransformMatricesChanged[1] < _end) nPostTransformMatricesChanged[1] = _end;
- }
- }
-
- if (start < XFMEM_LIGHTS_END && end > XFMEM_LIGHTS) {
- int _start = start < XFMEM_LIGHTS ? XFMEM_LIGHTS : start-XFMEM_LIGHTS;
- int _end = end < XFMEM_LIGHTS_END ? end-XFMEM_LIGHTS : XFMEM_LIGHTS_END-XFMEM_LIGHTS;
-
- if (nLightsChanged[0] == -1 ) {
- nLightsChanged[0] = _start;
- nLightsChanged[1] = _end;
- }
- else {
- if (nLightsChanged[0] > _start) nLightsChanged[0] = _start;
- if (nLightsChanged[1] < _end) nLightsChanged[1] = _end;
- }
- }
-}
-
-void VertexShaderMngr::SetTexMatrixChangedA(u32 Value)
-{
- if (MatrixIndexA.Hex != Value) {
- VertexManager::Flush();
- if (MatrixIndexA.PosNormalMtxIdx != (Value&0x3f))
- bPosNormalMatrixChanged = true;
- bTexMatricesChanged[0] = true;
- MatrixIndexA.Hex = Value;
- }
-}
-
-void VertexShaderMngr::SetTexMatrixChangedB(u32 Value)
-{
- if (MatrixIndexB.Hex != Value) {
- VertexManager::Flush();
- bTexMatricesChanged[1] = true;
- MatrixIndexB.Hex = Value;
- }
-}
-
-void VertexShaderMngr::SetViewport(float* _Viewport)
-{
- // check for paper mario
- for (size_t i = 0; i < ARRAYSIZE(rawViewport); ++i) {
- if( *(u32*)(_Viewport + i) == 0x7f800000 )
- return; // invalid number
- }
-
- memcpy(rawViewport, _Viewport, sizeof(rawViewport));
- bViewportChanged = true;
-}
-
-void VertexShaderMngr::SetViewportChanged()
-{
- bViewportChanged = true;
-}
-
-void VertexShaderMngr::SetProjection(float* _pProjection, int constantIndex)
-{
- memcpy(rawProjection, _pProjection, sizeof(rawProjection));
- bProjectionChanged = true;
-}
-
-size_t VertexShaderMngr::SaveLoadState(char *ptr, BOOL save)
-{
- BEGINSAVELOAD;
-
- SAVELOAD(&xfregs,sizeof(xfregs));
- SAVELOAD(xfmem,XFMEM_SIZE*sizeof(u32));
- SAVELOAD(rawViewport,sizeof(rawViewport));
- SAVELOAD(rawProjection,sizeof(rawProjection));
- SAVELOAD(&MatrixIndexA,sizeof(TMatrixIndexA));
- SAVELOAD(&MatrixIndexB,sizeof(TMatrixIndexB));
-
- if (!save) {
- // invalidate all
- InvalidateXFRange(0,0x1000);
- }
-
- ENDSAVELOAD;
-}
-
-// LoadXFReg 0x10
-void VertexShaderMngr::LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
-{
-
- u32 address = baseAddress;
- for (int i=0; i<(int)transferSize; i++)
- {
- address = baseAddress + i;
-
- // Setup a Matrix
- if (address < 0x1000)
- {
- VertexManager::Flush();
- InvalidateXFRange(address, address+transferSize);
- //PRIM_LOG("xfmem write: 0x%x-0x%x\n", address, address+transferSize);
-
- u32* p1 = &xfmem[address];
- memcpy_gc(p1, &pData[i], transferSize*4);
- i += transferSize;
- }
- else if (address<0x2000)
- {
- u32 data = pData[i];
- switch (address)
- {
- case 0x1000: // error
- break;
- case 0x1001: // diagnostics
- break;
- case 0x1002: // internal state 0
- break;
- case 0x1003: // internal state 1
- break;
- case 0x1004: // xf_clock
- break;
- case 0x1005: // clipdisable
- if (data & 1) { // disable clipping detection
- }
- if (data & 2) { // disable trivial rejection
- }
- if (data & 4) { // disable cpoly clipping acceleration
- }
- break;
- case 0x1006: //SetGPMetric
- break;
- case 0x1008: //__GXXfVtxSpecs, wrote 0004
- xfregs.hostinfo = *(INVTXSPEC*)&data;
- break;
- case 0x1009: //GXSetNumChans (no)
- if (xfregs.nNumChans != (data&3) ) {
- VertexManager::Flush();
- xfregs.nNumChans = data&3;
- }
- break;
- case 0x100a: //GXSetChanAmbientcolor
- if (xfregs.colChans[0].ambColor != data) {
- VertexManager::Flush();
- nMaterialsChanged |= 1;
- xfregs.colChans[0].ambColor = data;
- s_fMaterials[0] = ((data>>24)&0xFF)/255.0f;
- s_fMaterials[1] = ((data>>16)&0xFF)/255.0f;
- s_fMaterials[2] = ((data>>8)&0xFF)/255.0f;
- s_fMaterials[3] = ((data)&0xFF)/255.0f;
- }
- break;
- case 0x100b: //GXSetChanAmbientcolor
- if (xfregs.colChans[1].ambColor != data) {
- VertexManager::Flush();
- nMaterialsChanged |= 2;
- xfregs.colChans[1].ambColor = data;
- s_fMaterials[4] = ((data>>24)&0xFF)/255.0f;
- s_fMaterials[5] = ((data>>16)&0xFF)/255.0f;
- s_fMaterials[6] = ((data>>8)&0xFF)/255.0f;
- s_fMaterials[7] = ((data)&0xFF)/255.0f;
- }
- break;
- case 0x100c: //GXSetChanMatcolor (rgba)
- if (xfregs.colChans[0].matColor != data) {
- VertexManager::Flush();
- nMaterialsChanged |= 4;
- xfregs.colChans[0].matColor = data;
- s_fMaterials[8] = ((data>>24)&0xFF)/255.0f;
- s_fMaterials[9] = ((data>>16)&0xFF)/255.0f;
- s_fMaterials[10] = ((data>>8)&0xFF)/255.0f;
- s_fMaterials[11] = ((data)&0xFF)/255.0f;
- }
- break;
- case 0x100d: //GXSetChanMatcolor (rgba)
- if (xfregs.colChans[1].matColor != data) {
- VertexManager::Flush();
- nMaterialsChanged |= 8;
- xfregs.colChans[1].matColor = data;
- s_fMaterials[12] = ((data>>24)&0xFF)/255.0f;
- s_fMaterials[13] = ((data>>16)&0xFF)/255.0f;
- s_fMaterials[14] = ((data>>8)&0xFF)/255.0f;
- s_fMaterials[15] = ((data)&0xFF)/255.0f;
- }
- break;
-
- case 0x100e: // color0
- if (xfregs.colChans[0].color.hex != (data&0x7fff) ) {
- VertexManager::Flush();
- xfregs.colChans[0].color.hex = data;
- }
- break;
- case 0x100f: // color1
- if (xfregs.colChans[1].color.hex != (data&0x7fff) ) {
- VertexManager::Flush();
- xfregs.colChans[1].color.hex = data;
- }
- break;
- case 0x1010: // alpha0
- if (xfregs.colChans[0].alpha.hex != (data&0x7fff) ) {
- VertexManager::Flush();
- xfregs.colChans[0].alpha.hex = data;
- }
- break;
- case 0x1011: // alpha1
- if (xfregs.colChans[1].alpha.hex != (data&0x7fff) ) {
- VertexManager::Flush();
- xfregs.colChans[1].alpha.hex = data;
- }
- break;
- case 0x1012: // dual tex transform
- if (xfregs.bEnableDualTexTransform != (data&1)) {
- VertexManager::Flush();
- xfregs.bEnableDualTexTransform = data&1;
- }
- break;
-
- case 0x1013:
- case 0x1014:
- case 0x1015:
- case 0x1016:
- case 0x1017:
- DEBUG_LOG("xf addr: %x=%x\n", address, data);
- break;
- case 0x1018:
- //_assert_msg_(GX_XF, 0, "XF matrixindex0");
- VertexShaderMngr::SetTexMatrixChangedA(data); //?
- break;
- case 0x1019:
- //_assert_msg_(GX_XF, 0, "XF matrixindex1");
- VertexShaderMngr::SetTexMatrixChangedB(data); //?
- break;
-
- case 0x101a:
- VertexManager::Flush();
- VertexShaderMngr::SetViewport((float*)&pData[i]);
- i += 6;
- break;
-
- case 0x101c: // paper mario writes 16777216.0f, 1677721.75
- break;
- case 0x101f: // paper mario writes 16777216.0f, 5033165.0f
- break;
-
- case 0x1020:
- VertexManager::Flush();
- VertexShaderMngr::SetProjection((float*)&pData[i]);
- i += 7;
- return;
-
- case 0x103f: // GXSetNumTexGens
- if (xfregs.numTexGens != data) {
- VertexManager::Flush();
- xfregs.numTexGens = data;
- }
- break;
-
- case 0x1040: xfregs.texcoords[0].texmtxinfo.hex = data; break;
- case 0x1041: xfregs.texcoords[1].texmtxinfo.hex = data; break;
- case 0x1042: xfregs.texcoords[2].texmtxinfo.hex = data; break;
- case 0x1043: xfregs.texcoords[3].texmtxinfo.hex = data; break;
- case 0x1044: xfregs.texcoords[4].texmtxinfo.hex = data; break;
- case 0x1045: xfregs.texcoords[5].texmtxinfo.hex = data; break;
- case 0x1046: xfregs.texcoords[6].texmtxinfo.hex = data; break;
- case 0x1047: xfregs.texcoords[7].texmtxinfo.hex = data; break;
-
- case 0x1048:
- case 0x1049:
- case 0x104a:
- case 0x104b:
- case 0x104c:
- case 0x104d:
- case 0x104e:
- case 0x104f:
- DEBUG_LOG("xf addr: %x=%x\n", address, data);
- break;
- case 0x1050: xfregs.texcoords[0].postmtxinfo.hex = data; break;
- case 0x1051: xfregs.texcoords[1].postmtxinfo.hex = data; break;
- case 0x1052: xfregs.texcoords[2].postmtxinfo.hex = data; break;
- case 0x1053: xfregs.texcoords[3].postmtxinfo.hex = data; break;
- case 0x1054: xfregs.texcoords[4].postmtxinfo.hex = data; break;
- case 0x1055: xfregs.texcoords[5].postmtxinfo.hex = data; break;
- case 0x1056: xfregs.texcoords[6].postmtxinfo.hex = data; break;
- case 0x1057: xfregs.texcoords[7].postmtxinfo.hex = data; break;
-
- default:
- DEBUG_LOG("xf addr: %x=%x\n", address, data);
- break;
- }
- }
- else if (address>=0x4000)
- {
- // MessageBox(NULL, "1", "1", MB_OK);
- //4010 __GXSetGenMode
- }
- }
-}
-
-// Check docs for this sucker...
-void VertexShaderMngr::LoadIndexedXF(u32 val, int array)
-{
- int index = val>>16;
- int address = val&0xFFF; //check mask
- int size = ((val>>12)&0xF)+1;
- //load stuff from array to address in xf mem
-
- VertexManager::Flush();
- InvalidateXFRange(address, address+size);
- //PRIM_LOG("xfmem iwrite: 0x%x-0x%x\n", address, address+size);
-
- for (int i = 0; i < size; i++)
- xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4);
-}
-
-float* VertexShaderMngr::GetPosNormalMat()
-{
- return (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4;
-}
-
-void VertexShaderMngr::GetVertexShaderId(VERTEXSHADERUID& id, u32 components)
-{
- u32 zbufrender = (bpmem.ztex2.op==ZTEXTURE_ADD)||Renderer::GetZBufferTarget()!=0;
- id.values[0] = components|(xfregs.numTexGens<<23)|(xfregs.nNumChans<<27)|((u32)xfregs.bEnableDualTexTransform<<29)|(zbufrender<<30);
-
- for(int i = 0; i < 2; ++i) {
- id.values[1+i] = xfregs.colChans[i].color.enablelighting?(u32)xfregs.colChans[i].color.hex:(u32)xfregs.colChans[i].color.matsource;
- id.values[1+i] |= (xfregs.colChans[i].alpha.enablelighting?(u32)xfregs.colChans[i].alpha.hex:(u32)xfregs.colChans[i].alpha.matsource)<<15;
- }
- // fog
- id.values[1] |= (((u32)bpmem.fog.c_proj_fsel.fsel&3)<<30);
- id.values[2] |= (((u32)bpmem.fog.c_proj_fsel.fsel>>2)<<30);
-
- u32* pcurvalue = &id.values[3];
-
- for(int i = 0; i < xfregs.numTexGens; ++i) {
- TexMtxInfo tinfo = xfregs.texcoords[i].texmtxinfo;
- if( tinfo.texgentype != XF_TEXGEN_EMBOSS_MAP )
- tinfo.hex &= 0x7ff;
- if( tinfo.texgentype != XF_TEXGEN_REGULAR )
- tinfo.projection = 0;
-
- u32 val = ((tinfo.hex>>1)&0x1ffff);
- if( xfregs.bEnableDualTexTransform && tinfo.texgentype == XF_TEXGEN_REGULAR ) {
- // rewrite normalization and post index
- val |= ((u32)xfregs.texcoords[i].postmtxinfo.index<<17)|((u32)xfregs.texcoords[i].postmtxinfo.normalize<<23);
- }
-
- switch(i & 3) {
- case 0: pcurvalue[0] |= val; break;
- case 1: pcurvalue[0] |= val<<24; pcurvalue[1] = val>>8; ++pcurvalue; break;
- case 2: pcurvalue[0] |= val<<16; pcurvalue[1] = val>>16; ++pcurvalue; break;
- case 3: pcurvalue[0] |= val<<8; ++pcurvalue; break;
- }
- }
-}
-
static char text[16384];
#define WRITE p+=sprintf
#define LIGHTS_POS ""
-bool VertexShaderMngr::GenerateVertexShader(VERTEXSHADER& vs, u32 components)
+char* GenerateLightShader(char* p, int index, const LitChannel& chan, const char* dest, int coloralpha);
+
+bool GenerateVertexShader(VERTEXSHADER& vs, u32 components)
{
DVSTARTPROFILE();
@@ -1180,7 +408,7 @@ bool VertexShaderMngr::GenerateVertexShader(VERTEXSHADER& vs, u32 components) }
// coloralpha - 1 if color, 2 if alpha
-char* VertexShaderMngr::GenerateLightShader(char* p, int index, const LitChannel& chan, const char* dest, int coloralpha)
+char* GenerateLightShader(char* p, int index, const LitChannel& chan, const char* dest, int coloralpha)
{
const char* swizzle = "xyzw";
if( coloralpha == 1 ) swizzle = "xyz";
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShader.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexShader.h index d3f3f79255..1207eaec02 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexShader.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexShader.h @@ -18,7 +18,6 @@ #ifndef GCOGL_VERTEXSHADER_H
#define GCOGL_VERTEXSHADER_H
-#include <map>
/////////////
// Lighting
@@ -226,99 +225,7 @@ struct VERTEXSHADER #endif
};
-class VertexShaderMngr
-{
- struct VSCacheEntry
- {
- VERTEXSHADER shader;
- int frameCount;
- VSCacheEntry() : frameCount(0) {}
- void Destroy() {
- SAFE_RELEASE_PROG(shader.glprogid);
- }
- };
-
- class VERTEXSHADERUID
- {
- public:
- VERTEXSHADERUID() {}
- VERTEXSHADERUID(const VERTEXSHADERUID& r) {
- for(size_t i = 0; i < sizeof(values) / sizeof(u32); ++i)
- values[i] = r.values[i];
- }
-
- 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 = (((values[0]>>23)&0xf)*3+3)/4 + 3; // numTexGens*3/4+1
- for(int i = 1; i < N; ++i) {
- if( values[i] < _Right.values[i] )
- return true;
- else if( values[i] > _Right.values[i] )
- return false;
- }
-
- return false;
- }
-
- bool operator==(const VERTEXSHADERUID& _Right) const
- {
- if( values[0] != _Right.values[0] )
- return false;
-
- int N = (((values[0]>>23)&0xf)*3+3)/4 + 3; // numTexGens*3/4+1
- for(int i = 1; i < N; ++i) {
- if( values[i] != _Right.values[i] )
- return false;
- }
-
- return true;
- }
-
- u32 values[9];
- };
-
- typedef std::map<VERTEXSHADERUID,VSCacheEntry> VSCache;
-
- static VSCache vshaders;
- static VERTEXSHADER* pShaderLast;
- static TMatrixIndexA MatrixIndexA;
- static TMatrixIndexB MatrixIndexB;
-
- static void GetVertexShaderId(VERTEXSHADERUID& uid, u32 components);
- static bool GenerateVertexShader(VERTEXSHADER& vs, u32 components);
- static char* GenerateLightShader(char* p, int index, const LitChannel& chan, const char* dest, int coloralpha);
-
-public:
- static void Init();
- static void Cleanup();
- static void Shutdown();
- static VERTEXSHADER* GetShader(u32 components);
- static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram);
-
- // constant management
- static void SetConstants(VERTEXSHADER& vs);
-
- static void SetViewport(float* _Viewport);
- static void SetViewportChanged();
- static void SetProjection(float* _pProjection, int constantIndex = -1);
- static void InvalidateXFRange(int start, int end);
- static void SetTexMatrixChangedA(u32 Value);
- static void SetTexMatrixChangedB(u32 Value);
-
- static size_t SaveLoadState(char *ptr, BOOL save);
- static void LoadXFReg(u32 transferSize, u32 address, u32 *pData);
- static void LoadIndexedXF(u32 val, int array);
-
- static float* GetPosNormalMat();
-
- static float rawViewport[6];
- static float rawProjection[7];
-};
+bool GenerateVertexShader(VERTEXSHADER& vs, u32 components);
extern XFRegisters xfregs;
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderManager.cpp new file mode 100644 index 0000000000..4efe09fbf7 --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderManager.cpp @@ -0,0 +1,781 @@ +// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+
+
+#include "Globals.h"
+#include <math.h>
+#include "Render.h"
+#include "VertexShader.h"
+#include "VertexShaderManager.h"
+#include "BPStructs.h"
+#include "VertexLoader.h"
+
+
+VertexShaderMngr::VSCache VertexShaderMngr::vshaders;
+VERTEXSHADER* VertexShaderMngr::pShaderLast = NULL;
+TMatrixIndexA VertexShaderMngr::MatrixIndexA;
+TMatrixIndexB VertexShaderMngr::MatrixIndexB;
+float VertexShaderMngr::rawViewport[6] = {0};
+float VertexShaderMngr::rawProjection[7] = {0};
+float GC_ALIGNED16(g_fProjectionMatrix[16]);
+
+static int s_nMaxVertexInstructions;
+
+////////////////////////
+// Internal Variables //
+////////////////////////
+XFRegisters xfregs;
+static u32 xfmem[XFMEM_SIZE];
+static float s_fMaterials[16];
+
+// track changes
+static bool bTexMatricesChanged[2], bPosNormalMatrixChanged, bProjectionChanged, bViewportChanged;
+int nMaterialsChanged;
+static int nTransformMatricesChanged[2]; // min,max
+static int nNormalMatricesChanged[2]; // min,max
+static int nPostTransformMatricesChanged[2]; // min,max
+static int nLightsChanged[2]; // min,max
+
+void VertexShaderMngr::Init()
+{
+ nTransformMatricesChanged[0] = nTransformMatricesChanged[1] = -1;
+ nNormalMatricesChanged[0] = nNormalMatricesChanged[1] = -1;
+ nPostTransformMatricesChanged[0] = nPostTransformMatricesChanged[1] = -1;
+ nLightsChanged[0] = nLightsChanged[1] = -1;
+ bTexMatricesChanged[0] = bTexMatricesChanged[1] = false;
+ bPosNormalMatrixChanged = bProjectionChanged = bViewportChanged = false;
+ nMaterialsChanged = 0;
+
+ memset(&xfregs, 0, sizeof(xfregs));
+ memset(xfmem, 0, sizeof(xfmem));
+
+ glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &s_nMaxVertexInstructions);
+}
+
+void VertexShaderMngr::Shutdown()
+{
+ VSCache::iterator iter = vshaders.begin();
+ for (;iter!=vshaders.end();iter++)
+ iter->second.Destroy();
+ vshaders.clear();
+}
+
+VERTEXSHADER* VertexShaderMngr::GetShader(u32 components)
+{
+ DVSTARTPROFILE();
+ VERTEXSHADERUID uid;
+ GetVertexShaderId(uid, components);
+
+ VSCache::iterator iter = vshaders.find(uid);
+
+ if (iter != vshaders.end()) {
+ iter->second.frameCount=frameCount;
+ VSCacheEntry &entry = iter->second;
+ if (&entry.shader != pShaderLast) {
+ pShaderLast = &entry.shader;
+ }
+ return pShaderLast;
+ }
+
+ VSCacheEntry& entry = vshaders[uid];
+
+ if (!GenerateVertexShader(entry.shader, components)) {
+ ERROR_LOG("failed to create vertex shader\n");
+ }
+
+ //Make an entry in the table
+ entry.frameCount=frameCount;
+
+ pShaderLast = &entry.shader;
+ INCSTAT(stats.numVertexShadersCreated);
+ SETSTAT(stats.numVertexShadersAlive,vshaders.size());
+ return pShaderLast;
+}
+
+void VertexShaderMngr::Cleanup()
+{
+ 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;
+ }
+ }
+
+// static int frame = 0;
+// if( frame++ > 30 ) {
+// VSCache::iterator iter=vshaders.begin();
+// while(iter!=vshaders.end()) {
+// iter->second.Destroy();
+// ++iter;
+// }
+// vshaders.clear();
+// }
+
+ SETSTAT(stats.numPixelShadersAlive,vshaders.size());
+}
+
+bool VertexShaderMngr::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
+{
+ char stropt[64];
+ sprintf(stropt, "MaxLocalParams=256,MaxInstructions=%d", s_nMaxVertexInstructions);
+#ifdef _WIN32
+ const char* opts[] = {"-profileopts",stropt,"-O2", "-q", NULL};
+#else
+ const char* opts[] = {"-profileopts",stropt,"-q", NULL};
+#endif
+ CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgvProf, "main", opts);
+ if (!cgIsProgram(tempprog) || cgGetError() != CG_NO_ERROR) {
+ ERROR_LOG("Failed to load vs %s:\n", cgGetLastListing(g_cgcontext));
+ ERROR_LOG(pstrprogram);
+ return false;
+ }
+
+ //ERROR_LOG(pstrprogram);
+ //ERROR_LOG("id: %d\n", g_Config.iSaveTargetId);
+
+ char* pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
+ char* plocal = strstr(pcompiledprog, "program.local");
+
+ while( plocal != NULL ) {
+ const char* penv = " program.env";
+ memcpy(plocal, penv, 13);
+ plocal = strstr(plocal+13, "program.local");
+ }
+
+ glGenProgramsARB( 1, &vs.glprogid );
+ glBindProgramARB( GL_VERTEX_PROGRAM_ARB, vs.glprogid );
+ glProgramStringARB( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
+
+ GLenum err = GL_NO_ERROR;
+ GL_REPORT_ERROR();
+ if( err != GL_NO_ERROR ) {
+ ERROR_LOG(pstrprogram);
+ ERROR_LOG(pcompiledprog);
+ }
+
+ cgDestroyProgram(tempprog);
+
+#ifdef _DEBUG
+ vs.strprog = pstrprogram;
+#endif
+
+ return true;
+}
+
+// TODO: this array is misdeclared. Why teh f** does it go through the compilers?
+const u16 s_mtrltable[16][2] = {0, 0, 0, 1, 1, 1, 0, 2,
+ 2, 1, 0, 3, 1, 2, 0, 3,
+ 3, 1, 0, 4, 1, 3, 0, 4,
+ 2, 2, 0, 4, 1, 3, 0, 4};
+
+/// syncs the shader constant buffers with xfmem
+void VertexShaderMngr::SetConstants(VERTEXSHADER& vs)
+{
+ //nTransformMatricesChanged[0] = 0; nTransformMatricesChanged[1] = 256;
+ //nNormalMatricesChanged[0] = 0; nNormalMatricesChanged[1] = 96;
+ //nPostTransformMatricesChanged[0] = 0; nPostTransformMatricesChanged[1] = 256;
+ //nLightsChanged[0] = 0; nLightsChanged[1] = 0x80;
+ //bPosNormalMatrixChanged = true;
+ //bTexMatricesChanged[0] = bTexMatricesChanged[1] = true;
+ //bProjectionChanged = true;
+// bPosNormalMatrixChanged = bTexMatricesChanged[0] = bTexMatricesChanged[1] = true;
+// nMaterialsChanged = 15;
+
+ if (nTransformMatricesChanged[0] >= 0) {
+ int startn = nTransformMatricesChanged[0]/4;
+ int endn = (nTransformMatricesChanged[1]+3)/4;
+ const float* pstart = (const float*)&xfmem[startn*4];
+ for(int i = startn; i < endn; ++i, pstart += 4)
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TRANSFORMMATRICES+i, pstart);
+ nTransformMatricesChanged[0] = nTransformMatricesChanged[1] = -1;
+ }
+ if (nNormalMatricesChanged[0] >= 0) {
+ int startn = nNormalMatricesChanged[0]/3;
+ int endn = (nNormalMatricesChanged[1]+2)/3;
+ const float* pnstart = (const float*)&xfmem[XFMEM_NORMALMATRICES+3*startn];
+
+ for(int i = startn; i < endn; ++i, pnstart += 3)
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_NORMALMATRICES+i, pnstart);
+
+ nNormalMatricesChanged[0] = nNormalMatricesChanged[1] = -1;
+ }
+
+ if (nPostTransformMatricesChanged[0] >= 0) {
+ int startn = nPostTransformMatricesChanged[0]/4;
+ int endn = (nPostTransformMatricesChanged[1]+3)/4;
+ const float* pstart = (const float*)&xfmem[XFMEM_POSTMATRICES+startn*4];
+ for(int i = startn; i < endn; ++i, pstart += 4)
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSTTRANSFORMMATRICES+i, pstart);
+ }
+
+ if (nLightsChanged[0] >= 0) {
+ // lights don't have a 1 to 1 mapping, the color component needs to be converted to 4 floats
+ int istart = nLightsChanged[0]/0x10;
+ int iend = (nLightsChanged[1]+15)/0x10;
+ const float* xfmemptr = (const float*)&xfmem[0x10*istart+XFMEM_LIGHTS];
+
+ for(int i = istart; i < iend; ++i) {
+ u32 color = *(const u32*)(xfmemptr+3);
+ glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, C_LIGHTS+5*i,
+ ((color>>24)&0xFF)/255.0f, ((color>>16)&0xFF)/255.0f, ((color>>8)&0xFF)/255.0f, ((color)&0xFF)/255.0f);
+ xfmemptr += 4;
+ for(int j = 0; j < 4; ++j, xfmemptr += 3) {
+ if( j == 1 && fabs(xfmemptr[0]) < 0.00001f && fabs(xfmemptr[1]) < 0.00001f && fabs(xfmemptr[2]) < 0.00001f) {
+ // dist atten, make sure not equal to 0!!!
+ glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, C_LIGHTS+5*i+j+1, 0.00001f, xfmemptr[1], xfmemptr[2], 0);
+ }
+ else
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_LIGHTS+5*i+j+1, xfmemptr);
+ }
+ }
+
+ nLightsChanged[0] = nLightsChanged[1] = -1;
+ }
+
+ if (nMaterialsChanged) {
+ for(int i = 0; i < 4; ++i) {
+ if( nMaterialsChanged&(1<<i) )
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_MATERIALS+i, &s_fMaterials[4*i]);
+ }
+ nMaterialsChanged = 0;
+ }
+
+ if (bPosNormalMatrixChanged) {
+ bPosNormalMatrixChanged = false;
+
+ float* pos = (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4;
+ float* norm = (float*)xfmem + XFMEM_NORMALMATRICES + 3 * (MatrixIndexA.PosNormalMtxIdx & 31);
+
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSNORMALMATRIX, pos);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSNORMALMATRIX+1, pos+4);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSNORMALMATRIX+2, pos+8);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSNORMALMATRIX+3, norm);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSNORMALMATRIX+4, norm+3);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_POSNORMALMATRIX+5, norm+6);
+ }
+
+ if (bTexMatricesChanged[0]) {
+ bTexMatricesChanged[0] = false;
+
+ float* fptrs[] = {(float*)xfmem + MatrixIndexA.Tex0MtxIdx * 4, (float*)xfmem + MatrixIndexA.Tex1MtxIdx * 4,
+ (float*)xfmem + MatrixIndexA.Tex2MtxIdx * 4, (float*)xfmem + MatrixIndexA.Tex3MtxIdx * 4 };
+
+ for(int i = 0; i < 4; ++i) {
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TEXMATRICES+3*i, fptrs[i]);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TEXMATRICES+3*i+1, fptrs[i]+4);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TEXMATRICES+3*i+2, fptrs[i]+8);
+ }
+ }
+
+ if (bTexMatricesChanged[1]) {
+ bTexMatricesChanged[1] = false;
+
+ float* fptrs[] = {(float*)xfmem + MatrixIndexB.Tex4MtxIdx * 4, (float*)xfmem + MatrixIndexB.Tex5MtxIdx * 4,
+ (float*)xfmem + MatrixIndexB.Tex6MtxIdx * 4, (float*)xfmem + MatrixIndexB.Tex7MtxIdx * 4 };
+
+ for(int i = 0; i < 4; ++i) {
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TEXMATRICES+3*i+12, fptrs[i]);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TEXMATRICES+3*i+12+1, fptrs[i]+4);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_TEXMATRICES+3*i+12+2, fptrs[i]+8);
+ }
+ }
+
+ if (bViewportChanged) {
+ bViewportChanged = false;
+
+ // reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
+ // [0] = width/2
+ // [1] = height/2
+ // [2] = 16777215 * (farz-nearz)
+ // [3] = xorig + width/2 + 342
+ // [4] = yorig + height/2 + 342
+ // [5] = 16777215 * farz
+ INFO_LOG("view: topleft=(%f,%f), wh=(%f,%f), z=(%f,%f)\n",rawViewport[3]-rawViewport[0]-342,rawViewport[4]+rawViewport[1]-342,
+ 2 * rawViewport[0], 2 * rawViewport[1], (rawViewport[5]-rawViewport[2])/16777215.0f, rawViewport[5]/16777215.0f);
+ glViewport((int)(rawViewport[3]-rawViewport[0]-342)<<g_AAx,Renderer::GetTargetHeight()-((int)(rawViewport[4]-rawViewport[1]-342)<<g_AAy), abs((int)(2 * rawViewport[0])), abs((int)(2 * rawViewport[1])));
+ glDepthRange((rawViewport[5]-rawViewport[2])/16777215.0f, rawViewport[5]/16777215.0f);
+ }
+
+ if (bProjectionChanged) {
+ bProjectionChanged = false;
+
+ if (rawProjection[6] == 0) {
+ g_fProjectionMatrix[0] = rawProjection[0];
+ g_fProjectionMatrix[1] = 0.0f;
+ g_fProjectionMatrix[2] = rawProjection[1];
+ g_fProjectionMatrix[3] = 0;//-0.5f/Renderer::GetTargetWidth();
+
+ g_fProjectionMatrix[4] = 0.0f;
+ g_fProjectionMatrix[5] = rawProjection[2];
+ g_fProjectionMatrix[6] = rawProjection[3];
+ g_fProjectionMatrix[7] = 0;//+0.5f/Renderer::GetTargetHeight();
+
+ g_fProjectionMatrix[8] = 0.0f;
+ g_fProjectionMatrix[9] = 0.0f;
+ g_fProjectionMatrix[10] = -(1-rawProjection[4]);
+ g_fProjectionMatrix[11] = rawProjection[5];
+
+ g_fProjectionMatrix[12] = 0.0f;
+ g_fProjectionMatrix[13] = 0.0f;
+ g_fProjectionMatrix[14] = -1.0f;
+ g_fProjectionMatrix[15] = 0.0f;
+ }
+ else {
+ g_fProjectionMatrix[0] = rawProjection[0];
+ g_fProjectionMatrix[1] = 0.0f;
+ g_fProjectionMatrix[2] = 0.0f;
+ g_fProjectionMatrix[3] = rawProjection[1];
+
+ g_fProjectionMatrix[4] = 0.0f;
+ g_fProjectionMatrix[5] = rawProjection[2];
+ g_fProjectionMatrix[6] = 0.0f;
+ g_fProjectionMatrix[7] = rawProjection[3];
+
+ g_fProjectionMatrix[8] = 0.0f;
+ g_fProjectionMatrix[9] = 0.0f;
+ g_fProjectionMatrix[10] = rawProjection[4];
+ g_fProjectionMatrix[11] = -(-1 - rawProjection[5]);
+
+ g_fProjectionMatrix[12] = 0;
+ g_fProjectionMatrix[13] = 0;
+ g_fProjectionMatrix[14] = 0.0f;
+ g_fProjectionMatrix[15] = 1.0f;
+ }
+
+ PRIM_LOG("Projection: %f %f %f %f %f %f\n",rawProjection[0], rawProjection[1], rawProjection[2], rawProjection[3], rawProjection[4], rawProjection[5]);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_PROJECTION, &g_fProjectionMatrix[0]);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_PROJECTION+1, &g_fProjectionMatrix[4]);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_PROJECTION+2, &g_fProjectionMatrix[8]);
+ glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, C_PROJECTION+3, &g_fProjectionMatrix[12]);
+ }
+}
+
+void VertexShaderMngr::InvalidateXFRange(int start, int end)
+{
+ if( ((u32)start >= MatrixIndexA.PosNormalMtxIdx*4 && (u32)start < MatrixIndexA.PosNormalMtxIdx*4+12) ||
+ ((u32)start >= XFMEM_NORMALMATRICES+(MatrixIndexA.PosNormalMtxIdx&31)*3 && (u32)start < XFMEM_NORMALMATRICES+(MatrixIndexA.PosNormalMtxIdx&31)*3+9) ) {
+ bPosNormalMatrixChanged = true;
+ }
+
+ if (((u32)start >= MatrixIndexA.Tex0MtxIdx*4 && (u32)start < MatrixIndexA.Tex0MtxIdx*4+12) ||
+ ((u32)start >= MatrixIndexA.Tex1MtxIdx*4 && (u32)start < MatrixIndexA.Tex1MtxIdx*4+12) ||
+ ((u32)start >= MatrixIndexA.Tex2MtxIdx*4 && (u32)start < MatrixIndexA.Tex2MtxIdx*4+12) ||
+ ((u32)start >= MatrixIndexA.Tex3MtxIdx*4 && (u32)start < MatrixIndexA.Tex3MtxIdx*4+12)) {
+ bTexMatricesChanged[0] = true;
+ }
+
+ if (((u32)start >= MatrixIndexB.Tex4MtxIdx*4 && (u32)start < MatrixIndexB.Tex4MtxIdx*4+12) ||
+ ((u32)start >= MatrixIndexB.Tex5MtxIdx*4 && (u32)start < MatrixIndexB.Tex5MtxIdx*4+12) ||
+ ((u32)start >= MatrixIndexB.Tex6MtxIdx*4 && (u32)start < MatrixIndexB.Tex6MtxIdx*4+12) ||
+ ((u32)start >= MatrixIndexB.Tex7MtxIdx*4 && (u32)start < MatrixIndexB.Tex7MtxIdx*4+12)) {
+ bTexMatricesChanged[1] = true;
+ }
+
+ if (start < XFMEM_POSMATRICES_END ) {
+ if (nTransformMatricesChanged[0] == -1) {
+ nTransformMatricesChanged[0] = start;
+ nTransformMatricesChanged[1] = end>XFMEM_POSMATRICES_END?XFMEM_POSMATRICES_END:end;
+ }
+ else {
+ if (nTransformMatricesChanged[0] > start) nTransformMatricesChanged[0] = start;
+ if (nTransformMatricesChanged[1] < end) nTransformMatricesChanged[1] = end>XFMEM_POSMATRICES_END?XFMEM_POSMATRICES_END:end;
+ }
+ }
+
+ if (start < XFMEM_NORMALMATRICES_END && end > XFMEM_NORMALMATRICES ) {
+ int _start = start < XFMEM_NORMALMATRICES ? 0 : start-XFMEM_NORMALMATRICES;
+ int _end = end < XFMEM_NORMALMATRICES_END ? end-XFMEM_NORMALMATRICES : XFMEM_NORMALMATRICES_END-XFMEM_NORMALMATRICES;
+
+ if (nNormalMatricesChanged[0] == -1 ) {
+ nNormalMatricesChanged[0] = _start;
+ nNormalMatricesChanged[1] = _end;
+ }
+ else {
+ if (nNormalMatricesChanged[0] > _start) nNormalMatricesChanged[0] = _start;
+ if (nNormalMatricesChanged[1] < _end) nNormalMatricesChanged[1] = _end;
+ }
+ }
+
+ if (start < XFMEM_POSTMATRICES_END && end > XFMEM_POSTMATRICES ) {
+ int _start = start < XFMEM_POSTMATRICES ? XFMEM_POSTMATRICES : start-XFMEM_POSTMATRICES;
+ int _end = end < XFMEM_POSTMATRICES_END ? end-XFMEM_POSTMATRICES : XFMEM_POSTMATRICES_END-XFMEM_POSTMATRICES;
+
+ if (nPostTransformMatricesChanged[0] == -1 ) {
+ nPostTransformMatricesChanged[0] = _start;
+ nPostTransformMatricesChanged[1] = _end;
+ }
+ else {
+ if (nPostTransformMatricesChanged[0] > _start) nPostTransformMatricesChanged[0] = _start;
+ if (nPostTransformMatricesChanged[1] < _end) nPostTransformMatricesChanged[1] = _end;
+ }
+ }
+
+ if (start < XFMEM_LIGHTS_END && end > XFMEM_LIGHTS) {
+ int _start = start < XFMEM_LIGHTS ? XFMEM_LIGHTS : start-XFMEM_LIGHTS;
+ int _end = end < XFMEM_LIGHTS_END ? end-XFMEM_LIGHTS : XFMEM_LIGHTS_END-XFMEM_LIGHTS;
+
+ if (nLightsChanged[0] == -1 ) {
+ nLightsChanged[0] = _start;
+ nLightsChanged[1] = _end;
+ }
+ else {
+ if (nLightsChanged[0] > _start) nLightsChanged[0] = _start;
+ if (nLightsChanged[1] < _end) nLightsChanged[1] = _end;
+ }
+ }
+}
+
+void VertexShaderMngr::SetTexMatrixChangedA(u32 Value)
+{
+ if (MatrixIndexA.Hex != Value) {
+ VertexManager::Flush();
+ if (MatrixIndexA.PosNormalMtxIdx != (Value&0x3f))
+ bPosNormalMatrixChanged = true;
+ bTexMatricesChanged[0] = true;
+ MatrixIndexA.Hex = Value;
+ }
+}
+
+void VertexShaderMngr::SetTexMatrixChangedB(u32 Value)
+{
+ if (MatrixIndexB.Hex != Value) {
+ VertexManager::Flush();
+ bTexMatricesChanged[1] = true;
+ MatrixIndexB.Hex = Value;
+ }
+}
+
+void VertexShaderMngr::SetViewport(float* _Viewport)
+{
+ // check for paper mario
+ for (size_t i = 0; i < ARRAYSIZE(rawViewport); ++i) {
+ if( *(u32*)(_Viewport + i) == 0x7f800000 )
+ return; // invalid number
+ }
+
+ memcpy(rawViewport, _Viewport, sizeof(rawViewport));
+ bViewportChanged = true;
+}
+
+void VertexShaderMngr::SetViewportChanged()
+{
+ bViewportChanged = true;
+}
+
+void VertexShaderMngr::SetProjection(float* _pProjection, int constantIndex)
+{
+ memcpy(rawProjection, _pProjection, sizeof(rawProjection));
+ bProjectionChanged = true;
+}
+
+size_t VertexShaderMngr::SaveLoadState(char *ptr, BOOL save)
+{
+ BEGINSAVELOAD;
+
+ SAVELOAD(&xfregs,sizeof(xfregs));
+ SAVELOAD(xfmem,XFMEM_SIZE*sizeof(u32));
+ SAVELOAD(rawViewport,sizeof(rawViewport));
+ SAVELOAD(rawProjection,sizeof(rawProjection));
+ SAVELOAD(&MatrixIndexA,sizeof(TMatrixIndexA));
+ SAVELOAD(&MatrixIndexB,sizeof(TMatrixIndexB));
+
+ if (!save) {
+ // invalidate all
+ InvalidateXFRange(0,0x1000);
+ }
+
+ ENDSAVELOAD;
+}
+
+// LoadXFReg 0x10
+void VertexShaderMngr::LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
+{
+
+ u32 address = baseAddress;
+ for (int i=0; i<(int)transferSize; i++)
+ {
+ address = baseAddress + i;
+
+ // Setup a Matrix
+ if (address < 0x1000)
+ {
+ VertexManager::Flush();
+ InvalidateXFRange(address, address+transferSize);
+ //PRIM_LOG("xfmem write: 0x%x-0x%x\n", address, address+transferSize);
+
+ u32* p1 = &xfmem[address];
+ memcpy_gc(p1, &pData[i], transferSize*4);
+ i += transferSize;
+ }
+ else if (address<0x2000)
+ {
+ u32 data = pData[i];
+ switch (address)
+ {
+ case 0x1000: // error
+ break;
+ case 0x1001: // diagnostics
+ break;
+ case 0x1002: // internal state 0
+ break;
+ case 0x1003: // internal state 1
+ break;
+ case 0x1004: // xf_clock
+ break;
+ case 0x1005: // clipdisable
+ if (data & 1) { // disable clipping detection
+ }
+ if (data & 2) { // disable trivial rejection
+ }
+ if (data & 4) { // disable cpoly clipping acceleration
+ }
+ break;
+ case 0x1006: //SetGPMetric
+ break;
+ case 0x1008: //__GXXfVtxSpecs, wrote 0004
+ xfregs.hostinfo = *(INVTXSPEC*)&data;
+ break;
+ case 0x1009: //GXSetNumChans (no)
+ if (xfregs.nNumChans != (data&3) ) {
+ VertexManager::Flush();
+ xfregs.nNumChans = data&3;
+ }
+ break;
+ case 0x100a: //GXSetChanAmbientcolor
+ if (xfregs.colChans[0].ambColor != data) {
+ VertexManager::Flush();
+ nMaterialsChanged |= 1;
+ xfregs.colChans[0].ambColor = data;
+ s_fMaterials[0] = ((data>>24)&0xFF)/255.0f;
+ s_fMaterials[1] = ((data>>16)&0xFF)/255.0f;
+ s_fMaterials[2] = ((data>>8)&0xFF)/255.0f;
+ s_fMaterials[3] = ((data)&0xFF)/255.0f;
+ }
+ break;
+ case 0x100b: //GXSetChanAmbientcolor
+ if (xfregs.colChans[1].ambColor != data) {
+ VertexManager::Flush();
+ nMaterialsChanged |= 2;
+ xfregs.colChans[1].ambColor = data;
+ s_fMaterials[4] = ((data>>24)&0xFF)/255.0f;
+ s_fMaterials[5] = ((data>>16)&0xFF)/255.0f;
+ s_fMaterials[6] = ((data>>8)&0xFF)/255.0f;
+ s_fMaterials[7] = ((data)&0xFF)/255.0f;
+ }
+ break;
+ case 0x100c: //GXSetChanMatcolor (rgba)
+ if (xfregs.colChans[0].matColor != data) {
+ VertexManager::Flush();
+ nMaterialsChanged |= 4;
+ xfregs.colChans[0].matColor = data;
+ s_fMaterials[8] = ((data>>24)&0xFF)/255.0f;
+ s_fMaterials[9] = ((data>>16)&0xFF)/255.0f;
+ s_fMaterials[10] = ((data>>8)&0xFF)/255.0f;
+ s_fMaterials[11] = ((data)&0xFF)/255.0f;
+ }
+ break;
+ case 0x100d: //GXSetChanMatcolor (rgba)
+ if (xfregs.colChans[1].matColor != data) {
+ VertexManager::Flush();
+ nMaterialsChanged |= 8;
+ xfregs.colChans[1].matColor = data;
+ s_fMaterials[12] = ((data>>24)&0xFF)/255.0f;
+ s_fMaterials[13] = ((data>>16)&0xFF)/255.0f;
+ s_fMaterials[14] = ((data>>8)&0xFF)/255.0f;
+ s_fMaterials[15] = ((data)&0xFF)/255.0f;
+ }
+ break;
+
+ case 0x100e: // color0
+ if (xfregs.colChans[0].color.hex != (data&0x7fff) ) {
+ VertexManager::Flush();
+ xfregs.colChans[0].color.hex = data;
+ }
+ break;
+ case 0x100f: // color1
+ if (xfregs.colChans[1].color.hex != (data&0x7fff) ) {
+ VertexManager::Flush();
+ xfregs.colChans[1].color.hex = data;
+ }
+ break;
+ case 0x1010: // alpha0
+ if (xfregs.colChans[0].alpha.hex != (data&0x7fff) ) {
+ VertexManager::Flush();
+ xfregs.colChans[0].alpha.hex = data;
+ }
+ break;
+ case 0x1011: // alpha1
+ if (xfregs.colChans[1].alpha.hex != (data&0x7fff) ) {
+ VertexManager::Flush();
+ xfregs.colChans[1].alpha.hex = data;
+ }
+ break;
+ case 0x1012: // dual tex transform
+ if (xfregs.bEnableDualTexTransform != (data&1)) {
+ VertexManager::Flush();
+ xfregs.bEnableDualTexTransform = data&1;
+ }
+ break;
+
+ case 0x1013:
+ case 0x1014:
+ case 0x1015:
+ case 0x1016:
+ case 0x1017:
+ DEBUG_LOG("xf addr: %x=%x\n", address, data);
+ break;
+ case 0x1018:
+ //_assert_msg_(GX_XF, 0, "XF matrixindex0");
+ VertexShaderMngr::SetTexMatrixChangedA(data); //?
+ break;
+ case 0x1019:
+ //_assert_msg_(GX_XF, 0, "XF matrixindex1");
+ VertexShaderMngr::SetTexMatrixChangedB(data); //?
+ break;
+
+ case 0x101a:
+ VertexManager::Flush();
+ VertexShaderMngr::SetViewport((float*)&pData[i]);
+ i += 6;
+ break;
+
+ case 0x101c: // paper mario writes 16777216.0f, 1677721.75
+ break;
+ case 0x101f: // paper mario writes 16777216.0f, 5033165.0f
+ break;
+
+ case 0x1020:
+ VertexManager::Flush();
+ VertexShaderMngr::SetProjection((float*)&pData[i]);
+ i += 7;
+ return;
+
+ case 0x103f: // GXSetNumTexGens
+ if (xfregs.numTexGens != data) {
+ VertexManager::Flush();
+ xfregs.numTexGens = data;
+ }
+ break;
+
+ case 0x1040: xfregs.texcoords[0].texmtxinfo.hex = data; break;
+ case 0x1041: xfregs.texcoords[1].texmtxinfo.hex = data; break;
+ case 0x1042: xfregs.texcoords[2].texmtxinfo.hex = data; break;
+ case 0x1043: xfregs.texcoords[3].texmtxinfo.hex = data; break;
+ case 0x1044: xfregs.texcoords[4].texmtxinfo.hex = data; break;
+ case 0x1045: xfregs.texcoords[5].texmtxinfo.hex = data; break;
+ case 0x1046: xfregs.texcoords[6].texmtxinfo.hex = data; break;
+ case 0x1047: xfregs.texcoords[7].texmtxinfo.hex = data; break;
+
+ case 0x1048:
+ case 0x1049:
+ case 0x104a:
+ case 0x104b:
+ case 0x104c:
+ case 0x104d:
+ case 0x104e:
+ case 0x104f:
+ DEBUG_LOG("xf addr: %x=%x\n", address, data);
+ break;
+ case 0x1050: xfregs.texcoords[0].postmtxinfo.hex = data; break;
+ case 0x1051: xfregs.texcoords[1].postmtxinfo.hex = data; break;
+ case 0x1052: xfregs.texcoords[2].postmtxinfo.hex = data; break;
+ case 0x1053: xfregs.texcoords[3].postmtxinfo.hex = data; break;
+ case 0x1054: xfregs.texcoords[4].postmtxinfo.hex = data; break;
+ case 0x1055: xfregs.texcoords[5].postmtxinfo.hex = data; break;
+ case 0x1056: xfregs.texcoords[6].postmtxinfo.hex = data; break;
+ case 0x1057: xfregs.texcoords[7].postmtxinfo.hex = data; break;
+
+ default:
+ DEBUG_LOG("xf addr: %x=%x\n", address, data);
+ break;
+ }
+ }
+ else if (address>=0x4000)
+ {
+ // MessageBox(NULL, "1", "1", MB_OK);
+ //4010 __GXSetGenMode
+ }
+ }
+}
+
+// Check docs for this sucker...
+void VertexShaderMngr::LoadIndexedXF(u32 val, int array)
+{
+ int index = val>>16;
+ int address = val&0xFFF; //check mask
+ int size = ((val>>12)&0xF)+1;
+ //load stuff from array to address in xf mem
+
+ VertexManager::Flush();
+ InvalidateXFRange(address, address+size);
+ //PRIM_LOG("xfmem iwrite: 0x%x-0x%x\n", address, address+size);
+
+ for (int i = 0; i < size; i++)
+ xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4);
+}
+
+float* VertexShaderMngr::GetPosNormalMat()
+{
+ return (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4;
+}
+
+void VertexShaderMngr::GetVertexShaderId(VERTEXSHADERUID& id, u32 components)
+{
+ u32 zbufrender = (bpmem.ztex2.op==ZTEXTURE_ADD)||Renderer::GetZBufferTarget()!=0;
+ id.values[0] = components|(xfregs.numTexGens<<23)|(xfregs.nNumChans<<27)|((u32)xfregs.bEnableDualTexTransform<<29)|(zbufrender<<30);
+
+ for(int i = 0; i < 2; ++i) {
+ id.values[1+i] = xfregs.colChans[i].color.enablelighting?(u32)xfregs.colChans[i].color.hex:(u32)xfregs.colChans[i].color.matsource;
+ id.values[1+i] |= (xfregs.colChans[i].alpha.enablelighting?(u32)xfregs.colChans[i].alpha.hex:(u32)xfregs.colChans[i].alpha.matsource)<<15;
+ }
+ // fog
+ id.values[1] |= (((u32)bpmem.fog.c_proj_fsel.fsel&3)<<30);
+ id.values[2] |= (((u32)bpmem.fog.c_proj_fsel.fsel>>2)<<30);
+
+ u32* pcurvalue = &id.values[3];
+
+ for(int i = 0; i < xfregs.numTexGens; ++i) {
+ TexMtxInfo tinfo = xfregs.texcoords[i].texmtxinfo;
+ if( tinfo.texgentype != XF_TEXGEN_EMBOSS_MAP )
+ tinfo.hex &= 0x7ff;
+ if( tinfo.texgentype != XF_TEXGEN_REGULAR )
+ tinfo.projection = 0;
+
+ u32 val = ((tinfo.hex>>1)&0x1ffff);
+ if( xfregs.bEnableDualTexTransform && tinfo.texgentype == XF_TEXGEN_REGULAR ) {
+ // rewrite normalization and post index
+ val |= ((u32)xfregs.texcoords[i].postmtxinfo.index<<17)|((u32)xfregs.texcoords[i].postmtxinfo.normalize<<23);
+ }
+
+ switch(i & 3) {
+ case 0: pcurvalue[0] |= val; break;
+ case 1: pcurvalue[0] |= val<<24; pcurvalue[1] = val>>8; ++pcurvalue; break;
+ case 2: pcurvalue[0] |= val<<16; pcurvalue[1] = val>>16; ++pcurvalue; break;
+ case 3: pcurvalue[0] |= val<<8; ++pcurvalue; break;
+ }
+ }
+}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderManager.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderManager.h new file mode 100644 index 0000000000..1a6cd370fc --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderManager.h @@ -0,0 +1,140 @@ +// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef _VERTEXSHADERMANAGER_H
+#define _VERTEXSHADERMANAGER_H
+
+#include <map>
+
+#include "VertexShader.h"
+
+// shader variables
+#define I_POSNORMALMATRIX "cpnmtx"
+#define I_PROJECTION "cproj"
+#define I_MATERIALS "cmtrl"
+#define I_LIGHTS "clights"
+#define I_TEXMATRICES "ctexmtx"
+#define I_TRANSFORMMATRICES "ctrmtx"
+#define I_NORMALMATRICES "cnmtx"
+#define I_POSTTRANSFORMMATRICES "cpostmtx"
+#define I_FOGPARAMS "cfog"
+
+#define C_POSNORMALMATRIX 0
+#define C_PROJECTION (C_POSNORMALMATRIX+6)
+#define C_MATERIALS (C_PROJECTION+4)
+#define C_LIGHTS (C_MATERIALS+4)
+#define C_TEXMATRICES (C_LIGHTS+40)
+#define C_TRANSFORMMATRICES (C_TEXMATRICES+24)
+#define C_NORMALMATRICES (C_TRANSFORMMATRICES+64)
+#define C_POSTTRANSFORMMATRICES (C_NORMALMATRICES+32)
+#define C_FOGPARAMS (C_POSTTRANSFORMMATRICES+64)
+
+
+class VertexShaderMngr
+{
+ struct VSCacheEntry
+ {
+ VERTEXSHADER shader;
+ int frameCount;
+ VSCacheEntry() : frameCount(0) {}
+ void Destroy() {
+ SAFE_RELEASE_PROG(shader.glprogid);
+ }
+ };
+
+ class VERTEXSHADERUID
+ {
+ public:
+ VERTEXSHADERUID() {}
+ VERTEXSHADERUID(const VERTEXSHADERUID& r) {
+ for(size_t i = 0; i < sizeof(values) / sizeof(u32); ++i)
+ values[i] = r.values[i];
+ }
+
+ 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 = (((values[0]>>23)&0xf)*3+3)/4 + 3; // numTexGens*3/4+1
+ for(int i = 1; i < N; ++i) {
+ if( values[i] < _Right.values[i] )
+ return true;
+ else if( values[i] > _Right.values[i] )
+ return false;
+ }
+
+ return false;
+ }
+
+ bool operator==(const VERTEXSHADERUID& _Right) const
+ {
+ if( values[0] != _Right.values[0] )
+ return false;
+
+ int N = (((values[0]>>23)&0xf)*3+3)/4 + 3; // numTexGens*3/4+1
+ for(int i = 1; i < N; ++i) {
+ if( values[i] != _Right.values[i] )
+ return false;
+ }
+
+ return true;
+ }
+
+ u32 values[9];
+ };
+
+ typedef std::map<VERTEXSHADERUID,VSCacheEntry> VSCache;
+
+ static VSCache vshaders;
+ static VERTEXSHADER* pShaderLast;
+ static TMatrixIndexA MatrixIndexA;
+ static TMatrixIndexB MatrixIndexB;
+
+ static void GetVertexShaderId(VERTEXSHADERUID& uid, u32 components);
+
+public:
+ static void Init();
+ static void Cleanup();
+ static void Shutdown();
+ static VERTEXSHADER* GetShader(u32 components);
+ static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram);
+
+ // constant management
+ static void SetConstants(VERTEXSHADER& vs);
+
+ static void SetViewport(float* _Viewport);
+ static void SetViewportChanged();
+ static void SetProjection(float* _pProjection, int constantIndex = -1);
+ static void InvalidateXFRange(int start, int end);
+ static void SetTexMatrixChangedA(u32 Value);
+ static void SetTexMatrixChangedB(u32 Value);
+
+ static size_t SaveLoadState(char *ptr, BOOL save);
+ static void LoadXFReg(u32 transferSize, u32 address, u32 *pData);
+ static void LoadIndexedXF(u32 val, int array);
+
+ static float* GetPosNormalMat();
+
+ static float rawViewport[6];
+ static float rawProjection[7];
+};
+
+
+#endif
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index 7a53dd2c92..36b8804eb3 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -30,8 +30,8 @@ #include "EmuWindow.h"
#endif
#include "VertexLoader.h"
-#include "VertexShader.h"
-#include "PixelShader.h"
+#include "PixelShaderManager.h"
+#include "VertexShaderManager.h"
HINSTANCE g_hInstance = NULL;
|
