mirror of https://github.com/PCSX2/pcsx2.git
628 lines
20 KiB
C++
628 lines
20 KiB
C++
/* ZZ Open GL graphics plugin
|
|
* Copyright (c)2009 zeydlitz@gmail.com
|
|
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2006
|
|
*
|
|
* 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; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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 for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
// ZZogl Shader manipulation functions.
|
|
|
|
//------------------- Includes
|
|
#include "zerogs.h"
|
|
#include "ZeroGSShaders/zerogsshaders.h"
|
|
#include "zpipe.h"
|
|
|
|
// ----------------- Defines
|
|
|
|
using namespace ZeroGS;
|
|
//------------------ Constants
|
|
|
|
// ----------------- Global Variables
|
|
namespace ZeroGS {
|
|
FRAGMENTSHADER ppsBitBlt[2], ppsBitBltDepth, ppsOne;
|
|
FRAGMENTSHADER ppsBaseTexture, ppsConvert16to32, ppsConvert32to16;
|
|
}
|
|
|
|
// Debug variable, store name of the function that call the shader.
|
|
const char* ShaderCallerName = "";
|
|
const char* ShaderHandleName = "";
|
|
|
|
//------------------ Code
|
|
|
|
// Error handler. Setup in ZZogl_Create once.
|
|
void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
|
|
{
|
|
ERROR_LOG("%s->%s: %s\n", ShaderCallerName, ShaderHandleName, cgGetErrorString(err));
|
|
const char* listing = cgGetLastListing(g_cgcontext);
|
|
if (listing != NULL)
|
|
DEBUG_LOG(" last listing: %s\n", listing);
|
|
}
|
|
|
|
// This is helper of cgGLSetParameter4fv, made for debug purpose.
|
|
// Name could be any string. We must use it on compilation time, because erroneus handler does not
|
|
// return name
|
|
void ZZcgSetParameter4fv(CGparameter param, const float* v, const char* name) {
|
|
ShaderHandleName = name;
|
|
cgGLSetParameter4fv(param, v);
|
|
}
|
|
|
|
#define SET_UNIFORMPARAM(var, name) { \
|
|
p = cgGetNamedParameter(pf->prog, name); \
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) \
|
|
pf->var = p; \
|
|
} \
|
|
|
|
void SetupFragmentProgramParameters(FRAGMENTSHADER* pf, int context, int type)
|
|
{
|
|
// uniform parameters
|
|
CGparameter p;
|
|
|
|
p = cgGetNamedParameter(pf->prog, "g_fFogColor");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) {
|
|
cgConnectParameter(g_fparamFogColor, p);
|
|
}
|
|
|
|
SET_UNIFORMPARAM(sOneColor, "g_fOneColor");
|
|
SET_UNIFORMPARAM(sBitBltZ, "g_fBitBltZ");
|
|
SET_UNIFORMPARAM(sInvTexDims, "g_fInvTexDims");
|
|
SET_UNIFORMPARAM(fTexAlpha2, "fTexAlpha2");
|
|
SET_UNIFORMPARAM(fTexOffset, "g_fTexOffset");
|
|
SET_UNIFORMPARAM(fTexDims, "g_fTexDims");
|
|
SET_UNIFORMPARAM(fTexBlock, "g_fTexBlock");
|
|
SET_UNIFORMPARAM(fClampExts, "g_fClampExts");
|
|
SET_UNIFORMPARAM(fTexWrapMode, "TexWrapMode");
|
|
SET_UNIFORMPARAM(fRealTexDims, "g_fRealTexDims");
|
|
SET_UNIFORMPARAM(fTestBlack, "g_fTestBlack");
|
|
SET_UNIFORMPARAM(fPageOffset, "g_fPageOffset");
|
|
SET_UNIFORMPARAM(fTexAlpha, "fTexAlpha");
|
|
|
|
// textures
|
|
p = cgGetNamedParameter(pf->prog, "g_sBlocks");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) {
|
|
cgGLSetTextureParameter(p, ptexBlocks);
|
|
cgGLEnableTextureParameter(p);
|
|
}
|
|
|
|
// cg parameter usage is wrong, so do it manually
|
|
if( type == 3 ) {
|
|
p = cgGetNamedParameter(pf->prog, "g_sConv16to32");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) {
|
|
cgGLSetTextureParameter(p, ptexConv16to32);
|
|
cgGLEnableTextureParameter(p);
|
|
}
|
|
}
|
|
else if( type == 4 ) {
|
|
p = cgGetNamedParameter(pf->prog, "g_sConv32to16");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) {
|
|
cgGLSetTextureParameter(p, ptexConv32to16);
|
|
cgGLEnableTextureParameter(p);
|
|
}
|
|
}
|
|
else {
|
|
p = cgGetNamedParameter(pf->prog, "g_sBilinearBlocks");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) {
|
|
cgGLSetTextureParameter(p, ptexBilinearBlocks);
|
|
cgGLEnableTextureParameter(p);
|
|
}
|
|
}
|
|
|
|
p = cgGetNamedParameter(pf->prog, "g_sMemory");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) {
|
|
//cgGLEnableTextureParameter(p);
|
|
pf->sMemory = p;
|
|
}
|
|
p = cgGetNamedParameter(pf->prog, "g_sSrcFinal");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) {
|
|
//cgGLEnableTextureParameter(p);
|
|
pf->sFinal = p;
|
|
}
|
|
p = cgGetNamedParameter(pf->prog, "g_sBitwiseANDX");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) {
|
|
//cgGLEnableTextureParameter(p);
|
|
pf->sBitwiseANDX = p;
|
|
}
|
|
p = cgGetNamedParameter(pf->prog, "g_sBitwiseANDY");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) {
|
|
//cgGLEnableTextureParameter(p);
|
|
pf->sBitwiseANDY = p;
|
|
}
|
|
p = cgGetNamedParameter(pf->prog, "g_sCLUT");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) {
|
|
//cgGLEnableTextureParameter(p);
|
|
pf->sCLUT = p;
|
|
}
|
|
p = cgGetNamedParameter(pf->prog, "g_sInterlace");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) {
|
|
//cgGLEnableTextureParameter(p);
|
|
pf->sInterlace = p;
|
|
}
|
|
|
|
// set global shader constants
|
|
p = cgGetNamedParameter(pf->prog, "g_fExactColor");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE ) {
|
|
cgGLSetParameter4fv(p, Vector(0.5f, (g_GameSettings&GAME_EXACTCOLOR)?0.9f/256.0f:0.5f/256.0f, 0,1/255.0f));
|
|
}
|
|
|
|
p = cgGetNamedParameter(pf->prog, "g_fBilinear");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE )
|
|
cgGLSetParameter4fv(p, Vector(-0.2f, -0.65f, 0.9f, 1.0f / 32767.0f ));
|
|
|
|
p = cgGetNamedParameter(pf->prog, "g_fZBias");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE )
|
|
cgGLSetParameter4fv(p, Vector(1.0f/256.0f, 1.0004f, 1, 0.5f));
|
|
|
|
p = cgGetNamedParameter(pf->prog, "g_fc0");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE )
|
|
cgGLSetParameter4fv(p, Vector(0,1, 0.001f, 0.5f));
|
|
|
|
p = cgGetNamedParameter(pf->prog, "g_fMult");
|
|
if( p != NULL && cgIsParameterUsed(p, pf->prog) == CG_TRUE )
|
|
cgGLSetParameter4fv(p, Vector(1/1024.0f, 0.2f/1024.0f, 1/128.0f, 1/512.0f));
|
|
}
|
|
|
|
void SetupVertexProgramParameters(CGprogram prog, int context)
|
|
{
|
|
CGparameter p;
|
|
|
|
p = cgGetNamedParameter(prog, "g_fPosXY");
|
|
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE )
|
|
cgConnectParameter(g_vparamPosXY[context], p);
|
|
|
|
// Set Z-test, log or no log;
|
|
if (g_GameSettings&GAME_NOLOGZ) {
|
|
g_vdepth = Vector( 255.0 /256.0f, 255.0/65536.0f, 255.0f/(65535.0f*256.0f), 1.0f/(65536.0f*65536.0f));
|
|
vlogz = Vector( 1.0f, 0.0f, 0.0f, 0.0f);
|
|
}
|
|
else {
|
|
g_vdepth = Vector( 256.0f*65536.0f, 65536.0f, 256.0f, 65536.0f*65536.0f);
|
|
vlogz = Vector( 0.0f, 1.0f, 0.0f, 0.0f);
|
|
}
|
|
|
|
p = cgGetNamedParameter(prog, "g_fZ");
|
|
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) {
|
|
cgGLSetParameter4fv(p, g_vdepth);
|
|
|
|
p = cgGetNamedParameter(prog, "g_fZMin"); // Switch to flat-z when needed
|
|
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) {
|
|
//ERROR_LOG ("Use flat-z\n");
|
|
cgGLSetParameter4fv(p, vlogz);
|
|
}
|
|
else
|
|
ERROR_LOG ("Shader file version is outdated! Only is log-Z possible\n");
|
|
}
|
|
|
|
Vector vnorm = Vector(g_filog32, 0, 0,0);
|
|
p = cgGetNamedParameter(prog, "g_fZNorm");
|
|
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE )
|
|
cgGLSetParameter4fv(p, vnorm);
|
|
|
|
p = cgGetNamedParameter(prog, "g_fBilinear");
|
|
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE )
|
|
cgGLSetParameter4fv(p, Vector(-0.2f, -0.65f, 0.9f, 1.0f / 32767.0f ));
|
|
|
|
p = cgGetNamedParameter(prog, "g_fZBias");
|
|
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE )
|
|
cgGLSetParameter4fv(p, Vector(1.0f/256.0f, 1.0004f, 1, 0.5f));
|
|
|
|
p = cgGetNamedParameter(prog, "g_fc0");
|
|
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE )
|
|
cgGLSetParameter4fv(p, Vector(0,1, 0.001f, 0.5f));
|
|
}
|
|
|
|
#ifndef DEVBUILD
|
|
|
|
#define LOAD_VS(Index, prog) { \
|
|
assert( mapShaderResources.find(Index) != mapShaderResources.end() ); \
|
|
header = mapShaderResources[Index]; \
|
|
assert( (header) != NULL && (header)->index == (Index) ); \
|
|
prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgvProf, NULL, NULL); \
|
|
if( !cgIsProgram(prog) ) { \
|
|
ERROR_LOG("Failed to load vs %d: \n%s\n", Index, cgGetLastListing(g_cgcontext)); \
|
|
return false; \
|
|
} \
|
|
cgGLLoadProgram(prog); \
|
|
if( cgGetError() != CG_NO_ERROR ) ERROR_LOG("failed to load program %d\n", Index); \
|
|
SetupVertexProgramParameters(prog, !!(Index&SH_CONTEXT1)); \
|
|
} \
|
|
|
|
#define LOAD_PS(Index, fragment) { \
|
|
bLoadSuccess = true; \
|
|
assert( mapShaderResources.find(Index) != mapShaderResources.end() ); \
|
|
header = mapShaderResources[Index]; \
|
|
fragment.prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgfProf, NULL, NULL); \
|
|
if( !cgIsProgram(fragment.prog) ) { \
|
|
ERROR_LOG("Failed to load ps %d: \n%s\n", Index, cgGetLastListing(g_cgcontext)); \
|
|
return false; \
|
|
} \
|
|
cgGLLoadProgram(fragment.prog); \
|
|
if( cgGetError() != CG_NO_ERROR ) { \
|
|
ERROR_LOG("failed to load program %d\n", Index); \
|
|
bLoadSuccess = false; \
|
|
} \
|
|
SetupFragmentProgramParameters(&fragment, !!(Index&SH_CONTEXT1), 0); \
|
|
} \
|
|
|
|
bool ZeroGS::LoadEffects()
|
|
{
|
|
assert( s_lpShaderResources != NULL );
|
|
|
|
// process the header
|
|
u32 num = *(u32*)s_lpShaderResources;
|
|
int compressed_size = *(int*)(s_lpShaderResources+4);
|
|
int real_size = *(int*)(s_lpShaderResources+8);
|
|
int out;
|
|
|
|
char* pbuffer = (char*)malloc(real_size);
|
|
inf((char*)s_lpShaderResources+12, &pbuffer[0], compressed_size, real_size, &out);
|
|
assert(out == real_size);
|
|
|
|
s_lpShaderResources = (u8*)pbuffer;
|
|
SHADERHEADER* header = (SHADERHEADER*)s_lpShaderResources;
|
|
|
|
mapShaderResources.clear();
|
|
while(num-- > 0 ) {
|
|
mapShaderResources[header->index] = header;
|
|
++header;
|
|
}
|
|
|
|
// clear the textures
|
|
for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) {
|
|
SAFE_RELEASE_PROG(ppsTexture[i].prog);
|
|
ppsTexture[i].prog = NULL;
|
|
}
|
|
#ifndef _DEBUG
|
|
memset(ppsTexture, 0, sizeof(ppsTexture));
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
// called
|
|
bool ZeroGS::LoadExtraEffects()
|
|
{
|
|
SHADERHEADER* header;
|
|
bool bLoadSuccess = true;
|
|
|
|
const int vsshaders[4] = { SH_REGULARVS, SH_TEXTUREVS, SH_REGULARFOGVS, SH_TEXTUREFOGVS };
|
|
|
|
for(int i = 0; i < 4; ++i) {
|
|
LOAD_VS(vsshaders[i], pvs[2*i]);
|
|
LOAD_VS((vsshaders[i] | SH_CONTEXT1), pvs[2*i+1]);
|
|
//if( conf.mrtdepth ) {
|
|
LOAD_VS((vsshaders[i] | SH_WRITEDEPTH), pvs[2*i+8]);
|
|
LOAD_VS((vsshaders[i] | SH_WRITEDEPTH | SH_CONTEXT1), pvs[2*i+8+1]);
|
|
// }
|
|
// else {
|
|
// pvs[2*i+8] = pvs[2*i+8+1] = NULL;
|
|
// }
|
|
}
|
|
|
|
LOAD_VS(SH_BITBLTVS, pvsBitBlt.prog);
|
|
pvsBitBlt.sBitBltPos = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltPos");
|
|
pvsBitBlt.sBitBltTex = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTex");
|
|
pvsBitBlt.fBitBltTrans = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTrans");
|
|
|
|
LOAD_PS(SH_REGULARPS, ppsRegular[0]);
|
|
LOAD_PS(SH_REGULARFOGPS, ppsRegular[1]);
|
|
|
|
if( conf.mrtdepth ) {
|
|
LOAD_PS(SH_REGULARPS, ppsRegular[2]);
|
|
if( !bLoadSuccess )
|
|
conf.mrtdepth = 0;
|
|
LOAD_PS(SH_REGULARFOGPS, ppsRegular[3]);
|
|
if( !bLoadSuccess )
|
|
conf.mrtdepth = 0;
|
|
}
|
|
|
|
LOAD_PS(SH_BITBLTPS, ppsBitBlt[0]);
|
|
LOAD_PS(SH_BITBLTAAPS, ppsBitBlt[1]);
|
|
if( !bLoadSuccess ) {
|
|
ERROR_LOG("Failed to load BitBltAAPS, using BitBltPS\n");
|
|
LOAD_PS(SH_BITBLTPS, ppsBitBlt[1]);
|
|
}
|
|
LOAD_PS(SH_BITBLTDEPTHPS, ppsBitBltDepth);
|
|
LOAD_PS(SH_CRTCTARGPS, ppsCRTCTarg[0]);
|
|
LOAD_PS(SH_CRTCTARGINTERPS, ppsCRTCTarg[1]);
|
|
|
|
g_bCRTCBilinear = TRUE;
|
|
LOAD_PS(SH_CRTCPS, ppsCRTC[0]);
|
|
if( !bLoadSuccess ) {
|
|
// switch to simpler
|
|
g_bCRTCBilinear = FALSE;
|
|
LOAD_PS(SH_CRTC_NEARESTPS, ppsCRTC[0]);
|
|
LOAD_PS(SH_CRTCINTER_NEARESTPS, ppsCRTC[0]);
|
|
}
|
|
else {
|
|
LOAD_PS(SH_CRTCINTERPS, ppsCRTC[1]);
|
|
}
|
|
|
|
if( !bLoadSuccess )
|
|
ERROR_LOG("Failed to create CRTC shaders\n");
|
|
|
|
LOAD_PS(SH_CRTC24PS, ppsCRTC24[0]);
|
|
LOAD_PS(SH_CRTC24INTERPS, ppsCRTC24[1]);
|
|
LOAD_PS(SH_ZEROPS, ppsOne);
|
|
LOAD_PS(SH_BASETEXTUREPS, ppsBaseTexture);
|
|
LOAD_PS(SH_CONVERT16TO32PS, ppsConvert16to32);
|
|
LOAD_PS(SH_CONVERT32TO16PS, ppsConvert32to16);
|
|
|
|
return true;
|
|
}
|
|
|
|
FRAGMENTSHADER* ZeroGS::LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed)
|
|
{
|
|
int texwrap;
|
|
assert( texfilter < NUM_FILTERS );
|
|
|
|
if(g_nPixelShaderVer&SHADER_REDUCED)
|
|
texfilter = 0;
|
|
assert(!(g_nPixelShaderVer&SHADER_REDUCED) || !exactcolor);
|
|
|
|
if( clamp.wms == clamp.wmt ) {
|
|
switch( clamp.wms ) {
|
|
case 0: texwrap = TEXWRAP_REPEAT; break;
|
|
case 1: texwrap = TEXWRAP_CLAMP; break;
|
|
case 2: texwrap = TEXWRAP_CLAMP; break;
|
|
default: texwrap = TEXWRAP_REGION_REPEAT; break;
|
|
}
|
|
}
|
|
else if( clamp.wms==3||clamp.wmt==3)
|
|
texwrap = TEXWRAP_REGION_REPEAT;
|
|
else
|
|
texwrap = TEXWRAP_REPEAT_CLAMP;
|
|
|
|
int index = GET_SHADER_INDEX(type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, context, 0);
|
|
|
|
assert( index < ARRAY_SIZE(ppsTexture) );
|
|
FRAGMENTSHADER* pf = ppsTexture+index;
|
|
|
|
if( pbFailed != NULL ) *pbFailed = false;
|
|
|
|
if( pf->prog != NULL )
|
|
return pf;
|
|
|
|
if( (g_nPixelShaderVer & SHADER_ACCURATE) && mapShaderResources.find(index+NUM_SHADERS*SHADER_ACCURATE) != mapShaderResources.end() )
|
|
index += NUM_SHADERS*SHADER_ACCURATE;
|
|
|
|
assert( mapShaderResources.find(index) != mapShaderResources.end() );
|
|
SHADERHEADER* header = mapShaderResources[index];
|
|
if( header == NULL )
|
|
ERROR_LOG("%d %d\n", index, g_nPixelShaderVer);
|
|
assert( header != NULL );
|
|
|
|
//DEBUG_LOG("shader:\n%s\n", (char*)(s_lpShaderResources + (header)->offset));
|
|
pf->prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgfProf, NULL, NULL);
|
|
if( pf->prog != NULL && cgIsProgram(pf->prog) && cgGetError() == CG_NO_ERROR ) {
|
|
SetupFragmentProgramParameters(pf, context, type);
|
|
cgGLLoadProgram(pf->prog);
|
|
if( cgGetError() != CG_NO_ERROR ) {
|
|
// cgGLLoadProgram(pf->prog);
|
|
// if( cgGetError() != CG_NO_ERROR ) {
|
|
ERROR_LOG("Failed to load shader %d,%d,%d,%d\n", type, fog, texfilter, 4*clamp.wms+clamp.wmt);
|
|
if( pbFailed != NULL ) *pbFailed = true;
|
|
return pf;
|
|
// }
|
|
}
|
|
return pf;
|
|
}
|
|
|
|
ERROR_LOG("Failed to create shader %d,%d,%d,%d\n", type, fog, texfilter, 4*clamp.wms+clamp.wmt);
|
|
if( pbFailed != NULL ) *pbFailed = true;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#else // not RELEASE_TO_PUBLIC
|
|
|
|
#define LOAD_VS(name, prog, shaderver) { \
|
|
prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, EFFECT_NAME, shaderver, name, args); \
|
|
if( !cgIsProgram(prog) ) { \
|
|
ERROR_LOG("Failed to load vs %s: \n%s\n", name, cgGetLastListing(g_cgcontext)); \
|
|
return false; \
|
|
} \
|
|
cgGLLoadProgram(prog); \
|
|
if( cgGetError() != CG_NO_ERROR ) ERROR_LOG("failed to load program %s\n", name); \
|
|
SetupVertexProgramParameters(prog, args[0]==context1); \
|
|
} \
|
|
|
|
#ifdef _DEBUG
|
|
#define SET_PSFILENAME(frag, name) frag.filename = name
|
|
#else
|
|
#define SET_PSFILENAME(frag, name)
|
|
#endif
|
|
|
|
#define LOAD_PS(name, fragment, shaderver) { \
|
|
bLoadSuccess = true; \
|
|
fragment.prog = cgCreateProgramFromFile(g_cgcontext, CG_SOURCE, EFFECT_NAME, shaderver, name, args); \
|
|
if( !cgIsProgram(fragment.prog) ) { \
|
|
ERROR_LOG("Failed to load ps %s: \n%s\n", name, cgGetLastListing(g_cgcontext)); \
|
|
return false; \
|
|
} \
|
|
cgGLLoadProgram(fragment.prog); \
|
|
if( cgGetError() != CG_NO_ERROR ) { \
|
|
ERROR_LOG("failed to load program %s\n", name); \
|
|
bLoadSuccess = false; \
|
|
} \
|
|
SetupFragmentProgramParameters(&fragment, args[0]==context1, 0); \
|
|
SET_PSFILENAME(fragment, name); \
|
|
} \
|
|
|
|
bool ZeroGS::LoadEffects()
|
|
{
|
|
// clear the textures
|
|
for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) {
|
|
SAFE_RELEASE_PROG(ppsTexture[i].prog);
|
|
}
|
|
|
|
#ifndef _DEBUG
|
|
memset(ppsTexture, 0, sizeof(ppsTexture));
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ZeroGS::LoadExtraEffects()
|
|
{
|
|
const char* args[] = { NULL , NULL, NULL, NULL };
|
|
char context0[255], context1[255];
|
|
sprintf(context0, "-I%sctx0", EFFECT_DIR);
|
|
sprintf(context1, "-I%sctx1", EFFECT_DIR);
|
|
char* write_depth = "-DWRITE_DEPTH";
|
|
bool bLoadSuccess = true;
|
|
|
|
const char* pvsshaders[4] = { "RegularVS", "TextureVS", "RegularFogVS", "TextureFogVS" };
|
|
|
|
for(int i = 0; i < 4; ++i) {
|
|
args[0] = context0;
|
|
args[1] = NULL;
|
|
LOAD_VS(pvsshaders[i], pvs[2*i], cgvProf);
|
|
args[0] = context1;
|
|
LOAD_VS(pvsshaders[i], pvs[2*i+1], cgvProf);
|
|
|
|
//if( conf.mrtdepth ) {
|
|
args[0] = context0;
|
|
args[1] = write_depth;
|
|
LOAD_VS(pvsshaders[i], pvs[2*i+8], cgvProf);
|
|
args[0] = context1;
|
|
LOAD_VS(pvsshaders[i], pvs[2*i+8+1], cgvProf);
|
|
// }
|
|
// else {
|
|
// pvs[2*i+8] = pvs[2*i+8+1] = NULL;
|
|
// }
|
|
}
|
|
|
|
args[0] = context0;
|
|
args[1] = NULL;
|
|
LOAD_VS("BitBltVS", pvsBitBlt.prog, cgvProf);
|
|
pvsBitBlt.sBitBltPos = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltPos");
|
|
pvsBitBlt.sBitBltTex = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTex");
|
|
pvsBitBlt.fBitBltTrans = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTrans");
|
|
|
|
LOAD_PS("RegularPS", ppsRegular[0], cgfProf);
|
|
LOAD_PS("RegularFogPS", ppsRegular[1], cgfProf);
|
|
|
|
if( conf.mrtdepth ) {
|
|
args[0] = context0;
|
|
args[1] = write_depth;
|
|
LOAD_PS("RegularPS", ppsRegular[2], cgfProf);
|
|
if( !bLoadSuccess )
|
|
conf.mrtdepth = 0;
|
|
LOAD_PS("RegularFogPS", ppsRegular[3], cgfProf);
|
|
if( !bLoadSuccess )
|
|
conf.mrtdepth = 0;
|
|
}
|
|
|
|
LOAD_PS("BitBltPS", ppsBitBlt[0], cgfProf);
|
|
LOAD_PS("BitBltAAPS", ppsBitBlt[1], cgfProf);
|
|
if( !bLoadSuccess ) {
|
|
ERROR_LOG("Failed to load BitBltAAPS, using BitBltPS\n");
|
|
LOAD_PS("BitBltPS", ppsBitBlt[1], cgfProf);
|
|
}
|
|
|
|
LOAD_PS("BitBltDepthPS", ppsBitBltDepth, cgfProf);
|
|
LOAD_PS("CRTCTargPS", ppsCRTCTarg[0], cgfProf);
|
|
LOAD_PS("CRTCTargInterPS", ppsCRTCTarg[1], cgfProf);
|
|
|
|
g_bCRTCBilinear = TRUE;
|
|
LOAD_PS("CRTCPS", ppsCRTC[0], cgfProf);
|
|
if( !bLoadSuccess ) {
|
|
// switch to simpler
|
|
g_bCRTCBilinear = FALSE;
|
|
LOAD_PS("CRTCPS_Nearest", ppsCRTC[0], cgfProf);
|
|
LOAD_PS("CRTCInterPS_Nearest", ppsCRTC[0], cgfProf);
|
|
}
|
|
else {
|
|
LOAD_PS("CRTCInterPS", ppsCRTC[1], cgfProf);
|
|
}
|
|
|
|
if( !bLoadSuccess )
|
|
ERROR_LOG("Failed to create CRTC shaders\n");
|
|
|
|
LOAD_PS("CRTC24PS", ppsCRTC24[0], cgfProf); LOAD_PS("CRTC24InterPS", ppsCRTC24[1], cgfProf);
|
|
LOAD_PS("ZeroPS", ppsOne, cgfProf);
|
|
LOAD_PS("BaseTexturePS", ppsBaseTexture, cgfProf);
|
|
LOAD_PS("Convert16to32PS", ppsConvert16to32, cgfProf);
|
|
LOAD_PS("Convert32to16PS", ppsConvert32to16, cgfProf);
|
|
|
|
// if( !conf.mrtdepth ) {
|
|
// ERROR_LOG("Disabling MRT depth writing\n");
|
|
// s_bWriteDepth = FALSE;
|
|
// }
|
|
|
|
return true;
|
|
}
|
|
|
|
FRAGMENTSHADER* ZeroGS::LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed)
|
|
{
|
|
int texwrap;
|
|
|
|
assert( texfilter < NUM_FILTERS );
|
|
//assert( g_nPixelShaderVer == SHADER_30 );
|
|
if( clamp.wms == clamp.wmt ) {
|
|
switch( clamp.wms ) {
|
|
case 0: texwrap = TEXWRAP_REPEAT; break;
|
|
case 1: texwrap = TEXWRAP_CLAMP; break;
|
|
case 2: texwrap = TEXWRAP_CLAMP; break;
|
|
default:
|
|
texwrap = TEXWRAP_REGION_REPEAT; break;
|
|
}
|
|
}
|
|
else if( clamp.wms==3||clamp.wmt==3)
|
|
texwrap = TEXWRAP_REGION_REPEAT;
|
|
else
|
|
texwrap = TEXWRAP_REPEAT_CLAMP;
|
|
|
|
int index = GET_SHADER_INDEX(type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, context, 0);
|
|
|
|
if( pbFailed != NULL ) *pbFailed = false;
|
|
|
|
FRAGMENTSHADER* pf = ppsTexture+index;
|
|
|
|
if( pf->prog != NULL )
|
|
return pf;
|
|
|
|
pf->prog = LoadShaderFromType(EFFECT_DIR, EFFECT_NAME, type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, g_nPixelShaderVer, context);
|
|
|
|
if( pf->prog != NULL ) {
|
|
#ifdef _DEBUG
|
|
char str[255];
|
|
sprintf(str, "Texture%s%d_%sPS", fog?"Fog":"", texfilter, g_pTexTypes[type]);
|
|
pf->filename = str;
|
|
#endif
|
|
SetupFragmentProgramParameters(pf, context, type);
|
|
cgGLLoadProgram(pf->prog);
|
|
if( cgGetError() != CG_NO_ERROR ) {
|
|
// try again
|
|
// cgGLLoadProgram(pf->prog);
|
|
// if( cgGetError() != CG_NO_ERROR ) {
|
|
ERROR_LOG("Failed to load shader %d,%d,%d,%d\n", type, fog, texfilter, 4*clamp.wms+clamp.wmt);
|
|
if( pbFailed != NULL ) *pbFailed = true;
|
|
//assert(0);
|
|
// NULL makes things crash
|
|
return pf;
|
|
// }
|
|
}
|
|
return pf;
|
|
}
|
|
|
|
ERROR_LOG("Failed to create shader %d,%d,%d,%d\n", type, fog, texfilter, 4*clamp.wms+clamp.wmt);
|
|
if( pbFailed != NULL ) *pbFailed = true;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#endif // RELEASE_TO_PUBLIC
|
|
|