From 91ccda69efb56fa729c3f4f3209726238f656e29 Mon Sep 17 00:00:00 2001 From: hrydgard Date: Thu, 17 Jul 2008 21:09:18 +0000 Subject: [PATCH] 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 --- Source/Plugins/Plugin_VideoDX9/Src/Utils.h | 2 - .../Plugin_VideoDX9/Src/VertexLoader.cpp | 2 +- .../Plugin_VideoOGL/Plugin_VideoOGL.vcproj | 16 + .../Plugins/Plugin_VideoOGL/Src/BPStructs.cpp | 4 +- .../Plugins/Plugin_VideoOGL/Src/Globals.cpp | 1 - .../Plugin_VideoOGL/Src/OpcodeDecoding.cpp | 2 +- .../Plugin_VideoOGL/Src/PixelShader.cpp | 580 +------------ .../Plugins/Plugin_VideoOGL/Src/PixelShader.h | 139 +--- .../Src/PixelShaderManager.cpp | 567 +++++++++++++ .../Plugin_VideoOGL/Src/PixelShaderManager.h | 145 ++++ Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 2 +- .../Plugin_VideoOGL/Src/TextureMngr.cpp | 4 +- .../Plugin_VideoOGL/Src/VertexLoader.cpp | 4 +- .../Plugin_VideoOGL/Src/VertexShader.cpp | 782 +----------------- .../Plugin_VideoOGL/Src/VertexShader.h | 95 +-- .../Src/VertexShaderManager.cpp | 781 +++++++++++++++++ .../Plugin_VideoOGL/Src/VertexShaderManager.h | 140 ++++ Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 4 +- 18 files changed, 1696 insertions(+), 1574 deletions(-) create mode 100644 Source/Plugins/Plugin_VideoOGL/Src/PixelShaderManager.cpp create mode 100644 Source/Plugins/Plugin_VideoOGL/Src/PixelShaderManager.h create mode 100644 Source/Plugins/Plugin_VideoOGL/Src/VertexShaderManager.cpp create mode 100644 Source/Plugins/Plugin_VideoOGL/Src/VertexShaderManager.h 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 @@ -1301,6 +1301,14 @@ RelativePath=".\Src\PixelShader.h" > + + + + @@ -1349,6 +1357,14 @@ RelativePath=".\Src\VertexShader.h" > + + + + +#include #include -#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= 0 ) { - float fdims[4]; - for(int i = s_nTexDimsChanged[0]; i <= s_nTexDimsChanged[1]; ++i) { - if( s_texturemask & (1<= 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<>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 ) 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<>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 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 + +#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= 0 ) { + float fdims[4]; + for(int i = s_nTexDimsChanged[0]; i <= s_nTexDimsChanged[1]; ++i) { + if( s_texturemask & (1<= 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<>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 ) 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<>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 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 #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<= 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 ///////////// // 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 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 +#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<= 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 + +#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 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;