Split out the shader caches into their own files. The goal is to eventually be able to move the "Managers" to VideoCommon.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1681 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
bfa0ef86b1
commit
6c916151ab
|
@ -285,7 +285,9 @@ public:
|
||||||
void JMP(OpArg arg);
|
void JMP(OpArg arg);
|
||||||
void JMPptr(const OpArg &arg);
|
void JMPptr(const OpArg &arg);
|
||||||
void JMPself(); //infinite loop!
|
void JMPself(); //infinite loop!
|
||||||
|
#ifdef CALL
|
||||||
|
#undef CALL
|
||||||
|
#endif
|
||||||
void CALL(const void *fnptr);
|
void CALL(const void *fnptr);
|
||||||
void CALLptr(OpArg arg);
|
void CALLptr(OpArg arg);
|
||||||
|
|
||||||
|
|
|
@ -792,10 +792,26 @@
|
||||||
RelativePath=".\Src\VertexManager.h"
|
RelativePath=".\Src\VertexManager.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Src\XFStructs.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Src\XFStructs.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Render"
|
Name="Render"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Src\PixelShaderCache.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Src\PixelShaderCache.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Src\PixelShaderManager.cpp"
|
RelativePath=".\Src\PixelShaderManager.cpp"
|
||||||
>
|
>
|
||||||
|
@ -844,6 +860,14 @@
|
||||||
RelativePath=".\Src\TextureMngr.h"
|
RelativePath=".\Src\TextureMngr.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Src\VertexShaderCache.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Src\VertexShaderCache.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Src\VertexShaderManager.cpp"
|
RelativePath=".\Src\VertexShaderManager.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
@ -0,0 +1,223 @@
|
||||||
|
// 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 "Profiler.h"
|
||||||
|
|
||||||
|
#include "GLUtil.h"
|
||||||
|
|
||||||
|
#include <Cg/cg.h>
|
||||||
|
#include <Cg/cgGL.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "Statistics.h"
|
||||||
|
#include "Config.h"
|
||||||
|
#include "ImageWrite.h"
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Render.h"
|
||||||
|
#include "VertexShader.h"
|
||||||
|
#include "PixelShaderCache.h"
|
||||||
|
#include "PixelShaderManager.h"
|
||||||
|
|
||||||
|
static int s_nMaxPixelInstructions;
|
||||||
|
static GLuint s_ColorMatrixProgram = 0;
|
||||||
|
PixelShaderCache::PSCache PixelShaderCache::pshaders;
|
||||||
|
PIXELSHADERUID PixelShaderCache::s_curuid;
|
||||||
|
|
||||||
|
static FRAGMENTSHADER* pShaderLast = NULL;
|
||||||
|
|
||||||
|
void SetPSConstant4f(int const_number, float f1, float f2, float f3, float f4)
|
||||||
|
{
|
||||||
|
glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f1, f2, f3, f4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPSConstant4fv(int const_number, const float *f)
|
||||||
|
{
|
||||||
|
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PixelShaderCache::Init()
|
||||||
|
{
|
||||||
|
GL_REPORT_ERRORD();
|
||||||
|
|
||||||
|
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions);
|
||||||
|
|
||||||
|
int maxinst, maxattribs;
|
||||||
|
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&maxinst);
|
||||||
|
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, (GLint *)&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");
|
||||||
|
glDeleteProgramsARB(1, &s_ColorMatrixProgram);
|
||||||
|
s_ColorMatrixProgram = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PixelShaderCache::Shutdown()
|
||||||
|
{
|
||||||
|
glDeleteProgramsARB(1, &s_ColorMatrixProgram);
|
||||||
|
s_ColorMatrixProgram = 0;
|
||||||
|
PSCache::iterator iter = pshaders.begin();
|
||||||
|
for (; iter != pshaders.end(); iter++)
|
||||||
|
iter->second.Destroy();
|
||||||
|
pshaders.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint PixelShaderCache::GetColorMatrixProgram()
|
||||||
|
{
|
||||||
|
return s_ColorMatrixProgram;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FRAGMENTSHADER* PixelShaderCache::GetShader()
|
||||||
|
{
|
||||||
|
DVSTARTPROFILE();
|
||||||
|
PIXELSHADERUID uid;
|
||||||
|
u32 zbufrender = (Renderer::GetZBufferTarget() && bpmem.zmode.updateenable) ? 1 : 0;
|
||||||
|
u32 zBufRenderToCol0 = Renderer::GetRenderMode() != Renderer::RM_Normal;
|
||||||
|
GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), zbufrender, zBufRenderToCol0);
|
||||||
|
|
||||||
|
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];
|
||||||
|
char *code = GeneratePixelShader(PixelShaderManager::GetTextureMask(),
|
||||||
|
Renderer::GetZBufferTarget() != 0,
|
||||||
|
Renderer::GetRenderMode() != Renderer::RM_Normal);
|
||||||
|
|
||||||
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
|
if (g_Config.iLog & CONF_SAVESHADERS && code) {
|
||||||
|
static int counter = 0;
|
||||||
|
char szTemp[MAX_PATH];
|
||||||
|
sprintf(szTemp, "%s/ps_%04i.txt", g_Config.texDumpPath, counter++);
|
||||||
|
|
||||||
|
SaveData(szTemp, code);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// printf("Compiling pixel shader. size = %i\n", strlen(code));
|
||||||
|
if (!code || !CompilePixelShader(newentry.shader, code)) {
|
||||||
|
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 PixelShaderCache::Cleanup()
|
||||||
|
{
|
||||||
|
PSCache::iterator iter = pshaders.begin();
|
||||||
|
while (iter != pshaders.end()) {
|
||||||
|
PSCacheEntry &entry = iter->second;
|
||||||
|
if (entry.frameCount < frameCount - 400) {
|
||||||
|
entry.Destroy();
|
||||||
|
#ifdef _WIN32
|
||||||
|
iter = pshaders.erase(iter);
|
||||||
|
#else
|
||||||
|
pshaders.erase(iter++); // (this is gcc standard!)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
SETSTAT(stats.numPixelShadersAlive,(int)pshaders.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
|
||||||
|
{
|
||||||
|
char stropt[64];
|
||||||
|
sprintf(stropt, "MaxLocalParams=32,NumInstructionSlots=%d", s_nMaxPixelInstructions);
|
||||||
|
const char* opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
|
||||||
|
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
|
||||||
|
// replace the three characters ARB with ATI. TODO - check whether this is fixed in modern ATI drivers.
|
||||||
|
char* poptions = strstr(pcompiledprog, "ARB_draw_buffers");
|
||||||
|
if (poptions != NULL) {
|
||||||
|
poptions[0] = 'A';
|
||||||
|
poptions[1] = 'T';
|
||||||
|
poptions[2] = 'I';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
// printf("Compiled pixel shader %i\n", ps.glprogid);
|
||||||
|
|
||||||
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
|
ps.strprog = pstrprogram;
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
// 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 <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "BPMemory.h"
|
||||||
|
#include "PixelShader.h"
|
||||||
|
|
||||||
|
struct FRAGMENTSHADER
|
||||||
|
{
|
||||||
|
FRAGMENTSHADER() : glprogid(0) { }
|
||||||
|
GLuint glprogid; // opengl program id
|
||||||
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
|
std::string strprog;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
class PixelShaderCache
|
||||||
|
{
|
||||||
|
struct PSCacheEntry
|
||||||
|
{
|
||||||
|
FRAGMENTSHADER shader;
|
||||||
|
int frameCount;
|
||||||
|
PSCacheEntry() : frameCount(0) {}
|
||||||
|
~PSCacheEntry() {}
|
||||||
|
void Destroy() {
|
||||||
|
// printf("Destroying ps %i\n", shader.glprogid);
|
||||||
|
glDeleteProgramsARB(1, &shader.glprogid);
|
||||||
|
shader.glprogid = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
|
||||||
|
|
||||||
|
static PSCache pshaders;
|
||||||
|
|
||||||
|
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 GLuint GetColorMatrixProgram();
|
||||||
|
};
|
|
@ -15,29 +15,18 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Profiler.h"
|
#include "Profiler.h"
|
||||||
|
|
||||||
#include "GLUtil.h"
|
|
||||||
|
|
||||||
#include <Cg/cg.h>
|
|
||||||
#include <Cg/cgGL.h>
|
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "Statistics.h"
|
#include "Statistics.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "ImageWrite.h"
|
|
||||||
#include "Common.h"
|
|
||||||
#include "Render.h"
|
#include "Render.h"
|
||||||
#include "VertexShader.h"
|
|
||||||
#include "PixelShaderManager.h"
|
#include "PixelShaderManager.h"
|
||||||
|
|
||||||
PixelShaderCache::PSCache PixelShaderCache::pshaders;
|
|
||||||
PIXELSHADERUID PixelShaderCache::s_curuid;
|
|
||||||
|
|
||||||
static FRAGMENTSHADER* pShaderLast = NULL;
|
|
||||||
static int s_nMaxPixelInstructions;
|
|
||||||
static int s_nColorsChanged[2]; // 0 - regular colors, 1 - k colors
|
static int s_nColorsChanged[2]; // 0 - regular colors, 1 - k colors
|
||||||
static int s_nIndTexMtxChanged = 0;
|
static int s_nIndTexMtxChanged = 0;
|
||||||
static bool s_bAlphaChanged;
|
static bool s_bAlphaChanged;
|
||||||
|
@ -57,181 +46,6 @@ static u32 s_texturemask = 0;
|
||||||
static int maptocoord[8]; // indexed by texture map, holds the texcoord associated with the map
|
static int maptocoord[8]; // indexed by texture map, holds the texcoord associated with the map
|
||||||
static u32 maptocoord_mask = 0;
|
static u32 maptocoord_mask = 0;
|
||||||
|
|
||||||
static GLuint s_ColorMatrixProgram = 0;
|
|
||||||
|
|
||||||
void SetPSConstant4f(int const_number, float f1, float f2, float f3, float f4) {
|
|
||||||
glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f1, f2, f3, f4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetPSConstant4fv(int const_number, const float *f) {
|
|
||||||
glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, const_number, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PixelShaderCache::Init()
|
|
||||||
{
|
|
||||||
GL_REPORT_ERRORD();
|
|
||||||
|
|
||||||
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, (GLint *)&s_nMaxPixelInstructions);
|
|
||||||
|
|
||||||
int maxinst, maxattribs;
|
|
||||||
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&maxinst);
|
|
||||||
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, (GLint *)&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");
|
|
||||||
glDeleteProgramsARB(1, &s_ColorMatrixProgram);
|
|
||||||
s_ColorMatrixProgram = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PixelShaderCache::Shutdown()
|
|
||||||
{
|
|
||||||
glDeleteProgramsARB(1, &s_ColorMatrixProgram);
|
|
||||||
s_ColorMatrixProgram = 0;
|
|
||||||
PSCache::iterator iter = pshaders.begin();
|
|
||||||
for (; iter != pshaders.end(); iter++)
|
|
||||||
iter->second.Destroy();
|
|
||||||
pshaders.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
FRAGMENTSHADER* PixelShaderCache::GetShader()
|
|
||||||
{
|
|
||||||
DVSTARTPROFILE();
|
|
||||||
PIXELSHADERUID uid;
|
|
||||||
u32 zbufrender = (Renderer::GetZBufferTarget() && bpmem.zmode.updateenable) ? 1 : 0;
|
|
||||||
u32 zBufRenderToCol0 = Renderer::GetRenderMode() != Renderer::RM_Normal;
|
|
||||||
GetPixelShaderId(uid, s_texturemask, zbufrender, zBufRenderToCol0);
|
|
||||||
|
|
||||||
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];
|
|
||||||
char *code = GeneratePixelShader(s_texturemask,
|
|
||||||
Renderer::GetZBufferTarget() != 0,
|
|
||||||
Renderer::GetRenderMode() != Renderer::RM_Normal);
|
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
|
||||||
if (g_Config.iLog & CONF_SAVESHADERS && code) {
|
|
||||||
static int counter = 0;
|
|
||||||
char szTemp[MAX_PATH];
|
|
||||||
sprintf(szTemp, "%s/ps_%04i.txt", g_Config.texDumpPath, counter++);
|
|
||||||
|
|
||||||
SaveData(szTemp, code);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// printf("Compiling pixel shader. size = %i\n", strlen(code));
|
|
||||||
if (!code || !CompilePixelShader(newentry.shader, code)) {
|
|
||||||
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 PixelShaderCache::Cleanup()
|
|
||||||
{
|
|
||||||
PSCache::iterator iter = pshaders.begin();
|
|
||||||
while (iter != pshaders.end()) {
|
|
||||||
PSCacheEntry &entry = iter->second;
|
|
||||||
if (entry.frameCount < frameCount - 400) {
|
|
||||||
entry.Destroy();
|
|
||||||
#ifdef _WIN32
|
|
||||||
iter = pshaders.erase(iter);
|
|
||||||
#else
|
|
||||||
pshaders.erase(iter++); // (this is gcc standard!)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
SETSTAT(stats.numPixelShadersAlive,(int)pshaders.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
|
|
||||||
{
|
|
||||||
char stropt[64];
|
|
||||||
sprintf(stropt, "MaxLocalParams=32,NumInstructionSlots=%d", s_nMaxPixelInstructions);
|
|
||||||
const char* opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
|
|
||||||
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
|
|
||||||
// replace the three characters ARB with ATI. TODO - check whether this is fixed in modern ATI drivers.
|
|
||||||
char* poptions = strstr(pcompiledprog, "ARB_draw_buffers");
|
|
||||||
if (poptions != NULL) {
|
|
||||||
poptions[0] = 'A';
|
|
||||||
poptions[1] = 'T';
|
|
||||||
poptions[2] = 'I';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
// printf("Compiled pixel shader %i\n", ps.glprogid);
|
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
|
||||||
ps.strprog = pstrprogram;
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PixelShaderManager::Init()
|
void PixelShaderManager::Init()
|
||||||
{
|
{
|
||||||
s_nColorsChanged[0] = s_nColorsChanged[1] = 0;
|
s_nColorsChanged[0] = s_nColorsChanged[1] = 0;
|
||||||
|
@ -531,8 +345,7 @@ void PixelShaderManager::SetColorMatrix(const float* pmatrix, const float* pfCon
|
||||||
SetPSConstant4fv(C_COLORMATRIX+4, pfConstAdd);
|
SetPSConstant4fv(C_COLORMATRIX+4, pfConstAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint PixelShaderManager::GetColorMatrixProgram()
|
u32 PixelShaderManager::GetTextureMask()
|
||||||
{
|
{
|
||||||
return s_ColorMatrixProgram;
|
return s_texturemask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,51 +18,9 @@
|
||||||
#ifndef _PIXELSHADERMANAGER_H
|
#ifndef _PIXELSHADERMANAGER_H
|
||||||
#define _PIXELSHADERMANAGER_H
|
#define _PIXELSHADERMANAGER_H
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "BPMemory.h"
|
#include "BPMemory.h"
|
||||||
#include "PixelShader.h"
|
#include "PixelShader.h"
|
||||||
|
|
||||||
struct FRAGMENTSHADER
|
|
||||||
{
|
|
||||||
FRAGMENTSHADER() : glprogid(0) { }
|
|
||||||
GLuint glprogid; // opengl program id
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
|
||||||
std::string strprog;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
class PixelShaderCache
|
|
||||||
{
|
|
||||||
struct PSCacheEntry
|
|
||||||
{
|
|
||||||
FRAGMENTSHADER shader;
|
|
||||||
int frameCount;
|
|
||||||
PSCacheEntry() : frameCount(0) {}
|
|
||||||
~PSCacheEntry() {}
|
|
||||||
void Destroy() {
|
|
||||||
// printf("Destroying ps %i\n", shader.glprogid);
|
|
||||||
glDeleteProgramsARB(1, &shader.glprogid);
|
|
||||||
shader.glprogid = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::map<PIXELSHADERUID, PSCacheEntry> PSCache;
|
|
||||||
|
|
||||||
static PSCache pshaders;
|
|
||||||
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
void SetPSConstant4f(int const_number, float f1, float f2, float f3, float f4);
|
void SetPSConstant4f(int const_number, float f1, float f2, float f3, float f4);
|
||||||
void SetPSConstant4fv(int const_number, const float *f);
|
void SetPSConstant4fv(int const_number, const float *f);
|
||||||
|
|
||||||
|
@ -96,7 +54,8 @@ public:
|
||||||
static void SetTexDimsChanged(int texmapid);
|
static void SetTexDimsChanged(int texmapid);
|
||||||
|
|
||||||
static void SetColorMatrix(const float* pmatrix, const float* pfConstAdd);
|
static void SetColorMatrix(const float* pmatrix, const float* pfConstAdd);
|
||||||
static GLuint GetColorMatrixProgram();
|
|
||||||
|
static u32 GetTextureMask();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "TextureMngr.h"
|
#include "TextureMngr.h"
|
||||||
#include "rasterfont.h"
|
#include "rasterfont.h"
|
||||||
#include "VertexShader.h"
|
#include "VertexShader.h"
|
||||||
|
#include "PixelShaderCache.h"
|
||||||
#include "PixelShaderManager.h"
|
#include "PixelShaderManager.h"
|
||||||
#include "VertexLoaderManager.h"
|
#include "VertexLoaderManager.h"
|
||||||
#include "VertexLoader.h"
|
#include "VertexLoader.h"
|
||||||
|
|
|
@ -14,7 +14,6 @@ files = [
|
||||||
'Globals.cpp',
|
'Globals.cpp',
|
||||||
'Config.cpp',
|
'Config.cpp',
|
||||||
'memcpy_amd.cpp',
|
'memcpy_amd.cpp',
|
||||||
'PixelShaderManager.cpp',
|
|
||||||
'rasterfont.cpp',
|
'rasterfont.cpp',
|
||||||
'Render.cpp',
|
'Render.cpp',
|
||||||
'TextureMngr.cpp',
|
'TextureMngr.cpp',
|
||||||
|
@ -27,7 +26,10 @@ files = [
|
||||||
'VertexLoader_Position.cpp',
|
'VertexLoader_Position.cpp',
|
||||||
'VertexLoader_TextCoord.cpp',
|
'VertexLoader_TextCoord.cpp',
|
||||||
'VertexLoaderManager.cpp',
|
'VertexLoaderManager.cpp',
|
||||||
|
'PixelShaderManager.cpp',
|
||||||
'VertexShaderManager.cpp',
|
'VertexShaderManager.cpp',
|
||||||
|
'PixelShaderCache.cpp',
|
||||||
|
'VertexShaderCache.cpp',
|
||||||
'TextureConverter.cpp',
|
'TextureConverter.cpp',
|
||||||
'XFB.cpp',
|
'XFB.cpp',
|
||||||
]
|
]
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "TextureConverter.h"
|
#include "TextureConverter.h"
|
||||||
#include "PixelShaderManager.h"
|
#include "PixelShaderCache.h"
|
||||||
#include "VertexShaderManager.h"
|
#include "VertexShaderManager.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "GLUtil.h"
|
#include "GLUtil.h"
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "BPStructs.h"
|
#include "BPStructs.h"
|
||||||
#include "TextureDecoder.h"
|
#include "TextureDecoder.h"
|
||||||
#include "TextureMngr.h"
|
#include "TextureMngr.h"
|
||||||
|
#include "PixelShaderCache.h"
|
||||||
#include "PixelShaderManager.h"
|
#include "PixelShaderManager.h"
|
||||||
#include "VertexShaderManager.h"
|
#include "VertexShaderManager.h"
|
||||||
|
|
||||||
|
@ -578,7 +579,7 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
|
||||||
glViewport(0, 0, w, h);
|
glViewport(0, 0, w, h);
|
||||||
|
|
||||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, PixelShaderManager::GetColorMatrixProgram());
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, PixelShaderCache::GetColorMatrixProgram());
|
||||||
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
|
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
|
||||||
GL_REPORT_ERRORD();
|
GL_REPORT_ERRORD();
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,9 @@
|
||||||
#include "ImageWrite.h"
|
#include "ImageWrite.h"
|
||||||
#include "BPMemory.h"
|
#include "BPMemory.h"
|
||||||
#include "TextureMngr.h"
|
#include "TextureMngr.h"
|
||||||
|
#include "PixelShaderCache.h"
|
||||||
#include "PixelShaderManager.h"
|
#include "PixelShaderManager.h"
|
||||||
|
#include "VertexShaderCache.h"
|
||||||
#include "VertexShaderManager.h"
|
#include "VertexShaderManager.h"
|
||||||
#include "VertexShader.h"
|
#include "VertexShader.h"
|
||||||
#include "VertexLoader.h"
|
#include "VertexLoader.h"
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
// 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 <math.h>
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "Profiler.h"
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Statistics.h"
|
||||||
|
|
||||||
|
#include "GLUtil.h"
|
||||||
|
|
||||||
|
#include <Cg/cg.h>
|
||||||
|
#include <Cg/cgGL.h>
|
||||||
|
|
||||||
|
#include "Render.h"
|
||||||
|
#include "VertexShader.h"
|
||||||
|
#include "VertexShaderManager.h"
|
||||||
|
#include "VertexShaderCache.h"
|
||||||
|
#include "VertexManager.h"
|
||||||
|
#include "VertexLoader.h"
|
||||||
|
#include "XFMemory.h"
|
||||||
|
|
||||||
|
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
||||||
|
|
||||||
|
static VERTEXSHADER *pShaderLast = NULL;
|
||||||
|
static int s_nMaxVertexInstructions;
|
||||||
|
|
||||||
|
void SetVSConstant4f(int const_number, float f1, float f2, float f3, float f4)
|
||||||
|
{
|
||||||
|
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, const_number, f1, f2, f3, f4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetVSConstant4fv(int const_number, const float *f)
|
||||||
|
{
|
||||||
|
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VertexShaderCache::Init()
|
||||||
|
{
|
||||||
|
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexShaderCache::Shutdown()
|
||||||
|
{
|
||||||
|
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); iter++)
|
||||||
|
iter->second.Destroy();
|
||||||
|
vshaders.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
|
||||||
|
{
|
||||||
|
DVSTARTPROFILE();
|
||||||
|
VERTEXSHADERUID uid;
|
||||||
|
u32 zbufrender = (bpmem.ztex2.op == ZTEXTURE_ADD) || Renderer::GetZBufferTarget() != 0;
|
||||||
|
GetVertexShaderId(uid, components, zbufrender);
|
||||||
|
|
||||||
|
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];
|
||||||
|
const char *code = GenerateVertexShader(components, Renderer::GetZBufferTarget() != 0);
|
||||||
|
|
||||||
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
|
if (g_Config.iLog & CONF_SAVESHADERS && code) {
|
||||||
|
static int counter = 0;
|
||||||
|
char szTemp[MAX_PATH];
|
||||||
|
sprintf(szTemp, "%s/vs_%04i.txt", g_Config.texDumpPath, counter++);
|
||||||
|
|
||||||
|
SaveData(szTemp, code);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!code || !VertexShaderCache::CompileVertexShader(entry.shader, code)) {
|
||||||
|
ERROR_LOG("failed to create vertex shader\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Make an entry in the table
|
||||||
|
entry.frameCount = frameCount;
|
||||||
|
pShaderLast = &entry.shader;
|
||||||
|
INCSTAT(stats.numVertexShadersCreated);
|
||||||
|
SETSTAT(stats.numVertexShadersAlive, vshaders.size());
|
||||||
|
return pShaderLast;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexShaderCache::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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SETSTAT(stats.numVertexShadersAlive, vshaders.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
|
||||||
|
{
|
||||||
|
char stropt[64];
|
||||||
|
sprintf(stropt, "MaxLocalParams=256,MaxInstructions=%d", s_nMaxVertexInstructions);
|
||||||
|
const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
|
||||||
|
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);
|
||||||
|
// printf("Compiled vertex shader %i\n", vs.glprogid);
|
||||||
|
|
||||||
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
|
vs.strprog = pstrprogram;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
// 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 <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "BPMemory.h"
|
||||||
|
#include "VertexShader.h"
|
||||||
|
|
||||||
|
struct VERTEXSHADER
|
||||||
|
{
|
||||||
|
VERTEXSHADER() : glprogid(0) {}
|
||||||
|
GLuint glprogid; // opengl program id
|
||||||
|
|
||||||
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
|
std::string strprog;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
class VertexShaderCache
|
||||||
|
{
|
||||||
|
struct VSCacheEntry
|
||||||
|
{
|
||||||
|
VERTEXSHADER shader;
|
||||||
|
int frameCount;
|
||||||
|
VSCacheEntry() : frameCount(0) {}
|
||||||
|
void Destroy() {
|
||||||
|
// printf("Destroying vs %i\n", shader.glprogid);
|
||||||
|
glDeleteProgramsARB(1, &shader.glprogid);
|
||||||
|
shader.glprogid = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
|
||||||
|
|
||||||
|
static VSCache vshaders;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void Init();
|
||||||
|
static void Cleanup();
|
||||||
|
static void Shutdown();
|
||||||
|
|
||||||
|
static VERTEXSHADER* GetShader(u32 components);
|
||||||
|
static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram);
|
||||||
|
};
|
|
@ -15,36 +15,22 @@
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Profiler.h"
|
#include "Profiler.h"
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#include "GLUtil.h"
|
#include <cmath>
|
||||||
|
|
||||||
#include <Cg/cg.h>
|
|
||||||
#include <Cg/cgGL.h>
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "Statistics.h"
|
#include "Statistics.h"
|
||||||
#include "ImageWrite.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#include "Render.h"
|
#include "Render.h"
|
||||||
#include "VertexShader.h"
|
#include "VertexShader.h"
|
||||||
#include "VertexShaderManager.h"
|
#include "VertexShaderManager.h"
|
||||||
#include "VertexManager.h"
|
#include "VertexManager.h"
|
||||||
#include "VertexLoader.h"
|
#include "VertexLoader.h"
|
||||||
#include "BPMemory.h"
|
|
||||||
#include "XFMemory.h"
|
#include "XFMemory.h"
|
||||||
|
|
||||||
VertexShaderCache::VSCache VertexShaderCache::vshaders;
|
|
||||||
|
|
||||||
static VERTEXSHADER *pShaderLast = NULL;
|
|
||||||
|
|
||||||
static float GC_ALIGNED16(g_fProjectionMatrix[16]);
|
|
||||||
|
|
||||||
// Internal Variables
|
|
||||||
static int s_nMaxVertexInstructions;
|
|
||||||
|
|
||||||
static float s_fMaterials[16];
|
static float s_fMaterials[16];
|
||||||
|
|
||||||
// track changes
|
// track changes
|
||||||
|
@ -55,13 +41,6 @@ static int nNormalMatricesChanged[2]; // min,max
|
||||||
static int nPostTransformMatricesChanged[2]; // min,max
|
static int nPostTransformMatricesChanged[2]; // min,max
|
||||||
static int nLightsChanged[2]; // min,max
|
static int nLightsChanged[2]; // min,max
|
||||||
|
|
||||||
void SetVSConstant4f(int const_number, float f1, float f2, float f3, float f4) {
|
|
||||||
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, const_number, f1, f2, f3, f4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetVSConstant4fv(int const_number, const float *f) {
|
|
||||||
glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VertexShaderManager::Init()
|
void VertexShaderManager::Init()
|
||||||
{
|
{
|
||||||
|
@ -77,133 +56,11 @@ void VertexShaderManager::Init()
|
||||||
memset(xfmem, 0, sizeof(xfmem));
|
memset(xfmem, 0, sizeof(xfmem));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexShaderCache::Init()
|
|
||||||
{
|
|
||||||
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VertexShaderCache::Shutdown()
|
|
||||||
{
|
|
||||||
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); iter++)
|
|
||||||
iter->second.Destroy();
|
|
||||||
vshaders.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VertexShaderManager::Shutdown()
|
void VertexShaderManager::Shutdown()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
|
|
||||||
{
|
|
||||||
DVSTARTPROFILE();
|
|
||||||
VERTEXSHADERUID uid;
|
|
||||||
u32 zbufrender = (bpmem.ztex2.op == ZTEXTURE_ADD) || Renderer::GetZBufferTarget() != 0;
|
|
||||||
GetVertexShaderId(uid, components, zbufrender);
|
|
||||||
|
|
||||||
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];
|
|
||||||
const char *code = GenerateVertexShader(components, Renderer::GetZBufferTarget() != 0);
|
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
|
||||||
if (g_Config.iLog & CONF_SAVESHADERS && code) {
|
|
||||||
static int counter = 0;
|
|
||||||
char szTemp[MAX_PATH];
|
|
||||||
sprintf(szTemp, "%s/vs_%04i.txt", g_Config.texDumpPath, counter++);
|
|
||||||
|
|
||||||
SaveData(szTemp, code);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!code || !VertexShaderCache::CompileVertexShader(entry.shader, code)) {
|
|
||||||
ERROR_LOG("failed to create vertex shader\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Make an entry in the table
|
|
||||||
entry.frameCount = frameCount;
|
|
||||||
pShaderLast = &entry.shader;
|
|
||||||
INCSTAT(stats.numVertexShadersCreated);
|
|
||||||
SETSTAT(stats.numVertexShadersAlive, vshaders.size());
|
|
||||||
return pShaderLast;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VertexShaderCache::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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SETSTAT(stats.numVertexShadersAlive, vshaders.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
|
|
||||||
{
|
|
||||||
char stropt[64];
|
|
||||||
sprintf(stropt, "MaxLocalParams=256,MaxInstructions=%d", s_nMaxVertexInstructions);
|
|
||||||
const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
|
|
||||||
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);
|
|
||||||
// printf("Compiled vertex shader %i\n", vs.glprogid);
|
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
|
||||||
vs.strprog = pstrprogram;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// =======================================================================================
|
// =======================================================================================
|
||||||
// Syncs the shader constant buffers with xfmem
|
// Syncs the shader constant buffers with xfmem
|
||||||
// ----------------
|
// ----------------
|
||||||
|
@ -416,6 +273,7 @@ void VertexShaderManager::SetConstants()
|
||||||
|
|
||||||
if (bProjectionChanged) {
|
if (bProjectionChanged) {
|
||||||
bProjectionChanged = false;
|
bProjectionChanged = false;
|
||||||
|
static float GC_ALIGNED16(g_fProjectionMatrix[16]);
|
||||||
|
|
||||||
if (xfregs.rawProjection[6] == 0) {
|
if (xfregs.rawProjection[6] == 0) {
|
||||||
g_fProjectionMatrix[0] = xfregs.rawProjection[0];
|
g_fProjectionMatrix[0] = xfregs.rawProjection[0];
|
||||||
|
@ -616,234 +474,38 @@ void VertexShaderManager::SetProjection(float* _pProjection, int constantIndex)
|
||||||
bProjectionChanged = true;
|
bProjectionChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
float* VertexShaderManager::GetPosNormalMat()
|
void VertexShaderManager::SetMaterialColor(int index, u32 data)
|
||||||
{
|
{
|
||||||
return (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4;
|
// TODO: collapse
|
||||||
}
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
// LoadXFReg 0x10
|
nMaterialsChanged |= 1;
|
||||||
void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
|
s_fMaterials[0] = ((data>>24)&0xFF)/255.0f;
|
||||||
{
|
s_fMaterials[1] = ((data>>16)&0xFF)/255.0f;
|
||||||
u32 address = baseAddress;
|
s_fMaterials[2] = ((data>>8)&0xFF)/255.0f;
|
||||||
for (int i = 0; i < (int)transferSize; i++)
|
s_fMaterials[3] = ((data)&0xFF)/255.0f;
|
||||||
{
|
break;
|
||||||
address = baseAddress + i;
|
case 1:
|
||||||
|
nMaterialsChanged |= 2;
|
||||||
// Setup a Matrix
|
s_fMaterials[4] = ((data>>24)&0xFF)/255.0f;
|
||||||
if (address < 0x1000)
|
s_fMaterials[5] = ((data>>16)&0xFF)/255.0f;
|
||||||
{
|
s_fMaterials[6] = ((data>>8)&0xFF)/255.0f;
|
||||||
VertexManager::Flush();
|
s_fMaterials[7] = ((data)&0xFF)/255.0f;
|
||||||
VertexShaderManager::InvalidateXFRange(address, address + transferSize);
|
break;
|
||||||
//PRIM_LOG("xfmem write: 0x%x-0x%x\n", address, address+transferSize);
|
case 2:
|
||||||
|
nMaterialsChanged |= 4;
|
||||||
u32* p1 = &xfmem[address];
|
s_fMaterials[8] = ((data>>24)&0xFF)/255.0f;
|
||||||
memcpy_gc(p1, &pData[i], transferSize*4);
|
s_fMaterials[9] = ((data>>16)&0xFF)/255.0f;
|
||||||
i += transferSize;
|
s_fMaterials[10] = ((data>>8)&0xFF)/255.0f;
|
||||||
}
|
s_fMaterials[11] = ((data)&0xFF)/255.0f;
|
||||||
else if (address<0x2000)
|
break;
|
||||||
{
|
case 3:
|
||||||
u32 data = pData[i];
|
nMaterialsChanged |= 8;
|
||||||
switch (address)
|
s_fMaterials[12] = ((data>>24)&0xFF)/255.0f;
|
||||||
{
|
s_fMaterials[13] = ((data>>16)&0xFF)/255.0f;
|
||||||
case 0x1000: // error
|
s_fMaterials[14] = ((data>>8)&0xFF)/255.0f;
|
||||||
break;
|
s_fMaterials[15] = ((data)&0xFF)/255.0f;
|
||||||
case 0x1001: // diagnostics
|
break;
|
||||||
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 ((u32)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");
|
|
||||||
VertexShaderManager::SetTexMatrixChangedA(data); //?
|
|
||||||
break;
|
|
||||||
case 0x1019:
|
|
||||||
//_assert_msg_(GX_XF, 0, "XF matrixindex1");
|
|
||||||
VertexShaderManager::SetTexMatrixChangedB(data); //?
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x101a:
|
|
||||||
VertexManager::Flush();
|
|
||||||
VertexShaderManager::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();
|
|
||||||
VertexShaderManager::SetProjection((float*)&pData[i]);
|
|
||||||
i += 7;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case 0x103f: // GXSetNumTexGens
|
|
||||||
if ((u32)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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO - verify that it is correct. Seems to work, though.
|
|
||||||
void 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();
|
|
||||||
VertexShaderManager::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);
|
|
||||||
}
|
}
|
|
@ -18,49 +18,8 @@
|
||||||
#ifndef _VERTEXSHADERMANAGER_H
|
#ifndef _VERTEXSHADERMANAGER_H
|
||||||
#define _VERTEXSHADERMANAGER_H
|
#define _VERTEXSHADERMANAGER_H
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "GLUtil.h"
|
|
||||||
#include "VertexShader.h"
|
#include "VertexShader.h"
|
||||||
|
|
||||||
struct VERTEXSHADER
|
|
||||||
{
|
|
||||||
VERTEXSHADER() : glprogid(0) {}
|
|
||||||
GLuint glprogid; // opengl program id
|
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
|
||||||
std::string strprog;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
class VertexShaderCache
|
|
||||||
{
|
|
||||||
struct VSCacheEntry
|
|
||||||
{
|
|
||||||
VERTEXSHADER shader;
|
|
||||||
int frameCount;
|
|
||||||
VSCacheEntry() : frameCount(0) {}
|
|
||||||
void Destroy() {
|
|
||||||
// printf("Destroying vs %i\n", shader.glprogid);
|
|
||||||
glDeleteProgramsARB(1, &shader.glprogid);
|
|
||||||
shader.glprogid = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::map<VERTEXSHADERUID, VSCacheEntry> VSCache;
|
|
||||||
|
|
||||||
static VSCache vshaders;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void Init();
|
|
||||||
static void Cleanup();
|
|
||||||
static void Shutdown();
|
|
||||||
|
|
||||||
static VERTEXSHADER* GetShader(u32 components);
|
|
||||||
static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram);
|
|
||||||
};
|
|
||||||
|
|
||||||
// The non-API dependent parts.
|
// The non-API dependent parts.
|
||||||
class VertexShaderManager
|
class VertexShaderManager
|
||||||
{
|
{
|
||||||
|
@ -77,8 +36,10 @@ public:
|
||||||
static void InvalidateXFRange(int start, int end);
|
static void InvalidateXFRange(int start, int end);
|
||||||
static void SetTexMatrixChangedA(u32 Value);
|
static void SetTexMatrixChangedA(u32 Value);
|
||||||
static void SetTexMatrixChangedB(u32 Value);
|
static void SetTexMatrixChangedB(u32 Value);
|
||||||
|
static void SetMaterialColor(int index, u32 data);
|
||||||
static float* GetPosNormalMat();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void SetVSConstant4f(int const_number, float f1, float f2, float f3, float f4);
|
||||||
|
void SetVSConstant4fv(int const_number, const float *f);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -38,7 +38,9 @@
|
||||||
#include "VertexLoader.h"
|
#include "VertexLoader.h"
|
||||||
#include "VertexLoaderManager.h"
|
#include "VertexLoaderManager.h"
|
||||||
#include "VertexManager.h"
|
#include "VertexManager.h"
|
||||||
|
#include "PixelShaderCache.h"
|
||||||
#include "PixelShaderManager.h"
|
#include "PixelShaderManager.h"
|
||||||
|
#include "VertexShaderCache.h"
|
||||||
#include "VertexShaderManager.h"
|
#include "VertexShaderManager.h"
|
||||||
#include "XFB.h"
|
#include "XFB.h"
|
||||||
#include "XFBConvert.h"
|
#include "XFBConvert.h"
|
||||||
|
|
Loading…
Reference in New Issue