pcsx2/plugins/zerogs/dx/ZeroGSShaders/zerogsshaders.cpp

408 lines
14 KiB
C++

// Builds all possible shader files from ps2hw.fx and stores them in
// a preprocessed database
#include <stdio.h>
#include <windows.h>
#include <d3dx9.h>
#include <assert.h>
#define SAFE_RELEASE(x) { if( (x) != NULL ) { (x)->Release(); x = NULL; } }
#include <map>
#include <vector>
using namespace std;
#include "zerogsshaders.h"
char* srcfilename = "ps2hw.fx";
char* dstfilename = "ps2hw.dat";
DWORD dwFlags = 0;
#ifndef ARRAYSIZE
#define ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
struct SHADERINFO
{
DWORD type; // 1 - ps, 0 - vs
LPD3DXBUFFER pbuf;
};
map<DWORD, SHADERINFO> mapShaders;
class ZeroGSShaderInclude : public ID3DXInclude
{
public:
int context;
int ps2x; // if 0, ps20 only
char* pEffectDir;
STDMETHOD(Open)(D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes)
{
const char* pfilename = pFileName;
char strfile[255];
if( strstr(pFileName, "ps2hw_ctx") != NULL ) {
_snprintf(strfile, 255, "%sps2hw_ctx%d.fx", pEffectDir, context);
pfilename = strfile;
}
// else if( strstr(pFileName, "ps2hw_ps2x") != NULL ) {
// _snprintf(strfile, 255, "%sps2hw_ps2%c.fx", pEffectDir, ps2x?'x':'0');
// pfilename = strfile;
// }
else if( strstr(pFileName, "ps2hw.fx") != NULL ) {
_snprintf(strfile, 255, "%s%s", pEffectDir, pFileName);
pfilename = strfile;
}
FILE* f = fopen(pfilename, "rb");
if( f == NULL )
return E_FAIL;
fseek(f, 0, SEEK_END);
DWORD size = ftell(f);
fseek(f, 0, SEEK_SET);
char* buffer = new char[size+1];
fread(buffer, size, 1, f);
buffer[size] = 0;
*ppData = buffer;
*pBytes = size;
fclose(f);
return S_OK;
}
STDMETHOD(Close)(LPCVOID pData)
{
delete[] (char*)pData;
return S_OK;
}
};
void LoadShader(int index, const char* name, const char* pshader, D3DXMACRO* pmacros, ID3DXInclude* pInclude)
{
LPD3DXBUFFER pShader = NULL, pError = NULL;
HRESULT hr = D3DXCompileShaderFromFile(srcfilename, pmacros, pInclude, name, pshader, dwFlags, &pShader, &pError, NULL);
if( FAILED(hr) )
{
printf("Failed to load %s\n%s\n", name, pError->GetBufferPointer());
SAFE_RELEASE(pShader);
SAFE_RELEASE(pError);
return;
}
SAFE_RELEASE(pError);
if( mapShaders.find(index) != mapShaders.end() ) {
printf("two shaders share the same index %d\n", index);
exit(0);
}
SHADERINFO info;
info.type = name[0] == 'p' ? 0x80000000 : 0;
info.pbuf = pShader;
mapShaders[index] = info;
}
int main(int argc, char** argv)
{
printf("usage: [src] [dst] [opts]\n");
if( argc >= 2 ) srcfilename = argv[1];
if( argc >= 3 ) dstfilename = argv[2];
if( argc >= 4 ) {
dwFlags = atoi(argv[3]);
}
FILE* fsrc = fopen(srcfilename, "r");
if( fsrc == NULL ) {
printf("cannot open %s\n", srcfilename);
return 0;
}
fclose(fsrc);
LoadShader(SH_BITBLTVS, "BitBltVS", "vs_2_0", NULL, NULL);
LoadShader(SH_BITBLTVS|SH_30, "BitBltVS", "vs_3_0", NULL, NULL);
LoadShader(SH_BITBLTPS, "BitBltPS", "ps_2_0", NULL, NULL);
LoadShader(SH_BITBLTDEPTHPS, "BitBltDepthPS", "ps_2_0", NULL, NULL);
LoadShader(SH_BITBLTDEPTHMRTPS, "BitBltDepthMRTPS", "ps_2_0", NULL, NULL);
LoadShader(SH_BITBLTDEPTHTEXPS, "BitBltDepthTexPS", "ps_2_0", NULL, NULL);
LoadShader(SH_BITBLTDEPTHTEXMRTPS, "BitBltDepthTexMRTPS", "ps_2_0", NULL, NULL);
LoadShader(SH_CRTCTARGPS, "CRTCTargPS", "ps_2_0", NULL, NULL);
LoadShader(SH_CRTCPS, "CRTCPS", "ps_2_0", NULL, NULL);
LoadShader(SH_CRTC24PS, "CRTC24PS", "ps_2_0", NULL, NULL);
LoadShader(SH_ZEROPS, "ZeroPS", "ps_2_0", NULL, NULL);
LoadShader(SH_ZEROPS|SH_30, "ZeroPS", "ps_3_0", NULL, NULL);
LoadShader(SH_BASETEXTUREPS, "BaseTexturePS", "ps_2_0", NULL, NULL);
LoadShader(SH_BITBLTAAPS, "BitBltPS", "ps_2_0", NULL, NULL);
LoadShader(SH_CRTCTARGINTERPS, "CRTCTargInterPS", "ps_2_0", NULL, NULL);
LoadShader(SH_CRTCINTERPS, "CRTCInterPS", "ps_2_0", NULL, NULL);
LoadShader(SH_CRTC24INTERPS, "CRTC24InterPS", "ps_2_0", NULL, NULL);
LoadShader(SH_CONVERT16TO32PS, "Convert16to32PS", "ps_2_0", NULL, NULL);
LoadShader(SH_CONVERT32TO16PS, "Convert32to16PS", "ps_2_0", NULL, NULL);
const int vsshaders[4] = { SH_REGULARVS, SH_TEXTUREVS, SH_REGULARFOGVS, SH_TEXTUREFOGVS };
const char* pvsshaders[4] = { "RegularVS", "TextureVS", "RegularFogVS", "TextureFogVS" };
// load the texture shaders
char str[255], strdir[255];
strcpy(strdir, srcfilename);
int i = (int)strlen(strdir);
while(i > 0) {
if( strdir[i-1] == '/' || strdir[i-1] == '\\' )
break;
--i;
}
strdir[i] = 0;
ZeroGSShaderInclude inc;
inc.pEffectDir = strdir;
D3DXMACRO macros[10];
memset(macros, 0, sizeof(macros));
macros[0].Name = "WRITE_DEPTH";
macros[0].Definition = "1";
for(i = 0; i < ARRAYSIZE(vsshaders); ++i) {
for(int vs30 = 0; vs30 < 2; ++vs30 ) {
for(int writedepth = 0; writedepth < 2; ++writedepth ) {
inc.context = 0;
LoadShader(vsshaders[i]|(vs30?SH_30:0)|(writedepth?SH_WRITEDEPTH:0), pvsshaders[i], vs30 ? "vs_3_0" : "vs_2_0", writedepth ? macros : NULL, &inc);
inc.context = 1;
LoadShader(vsshaders[i]|(vs30?SH_30:0)|(writedepth?SH_WRITEDEPTH:0)|SH_CONTEXT1, pvsshaders[i], vs30 ? "vs_3_0" : "vs_2_0", writedepth ? macros : NULL, &inc);
}
}
}
const int psshaders[2] = { SH_REGULARPS, SH_REGULARFOGPS };
const char* ppsshaders[2] = { "RegularPS", "RegularFogPS" };
for(i = 0; i < ARRAYSIZE(psshaders); ++i) {
for(int ps30 = 0; ps30 < 2; ++ps30 ) {
for(int writedepth = 0; writedepth < 2; ++writedepth ) {
LoadShader(psshaders[i]|(ps30?SH_30:0)|(writedepth?SH_WRITEDEPTH:0), ppsshaders[i], ps30 ? "ps_3_0" : "ps_2_0", writedepth ? macros : NULL, NULL);
}
}
}
printf("creating shaders, note that ps2hw_ctx0.fx, and ps2hw_ctx1.fx are required\n");
for(int texwrap = 0; texwrap < NUM_TEXWRAPS; ++texwrap ) {
int macroindex = 0;
memset(macros, 0, sizeof(macros));
if( g_pPsTexWrap[texwrap] != NULL ) {
macros[0].Name = g_pPsTexWrap[texwrap];
macros[0].Definition = "1";
macroindex++;
}
for(int context = 0; context < 2; ++context) {
inc.context = context;
for(int texfilter = 0; texfilter < NUM_FILTERS; ++texfilter) {
for(int fog = 0; fog < 2; ++fog ) {
for(int writedepth = 0; writedepth < 2; ++writedepth ) {
if( writedepth ) {
macros[macroindex].Name = "WRITE_DEPTH";
macros[macroindex].Definition = "1";
macroindex++;
}
else {
macros[macroindex].Name = NULL;
macros[macroindex].Definition = NULL;
}
for(int testaem = 0; testaem < 2; ++testaem ) {
if( testaem ) {
macros[macroindex].Name = "TEST_AEM";
macros[macroindex].Definition = "1";
macroindex++;
}
else {
macros[macroindex].Name = NULL;
macros[macroindex].Definition = NULL;
}
for(int exactcolor = 0; exactcolor < 2; ++exactcolor ) {
if( exactcolor ) {
macros[macroindex].Name = "EXACT_COLOR";
macros[macroindex].Definition = "1";
macroindex++;
}
else {
macros[macroindex].Name = NULL;
macros[macroindex].Definition = NULL;
}
// 32
sprintf(str, "Texture%s%d_32PS", fog?"Fog":"", texfilter);
inc.ps2x = 0;
if( macros[macroindex].Name != NULL )
printf("error[%d] %s: %d %d %d %d!\n", macroindex, macros[macroindex].Name, texfilter, fog, writedepth, testaem);
macros[macroindex].Name = "ACCURATE_DECOMPRESSION";
macros[macroindex].Definition = "1";
if( texfilter == 0 && exactcolor == 0 ) {
LoadShader(GET_SHADER_INDEX(0, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20), str, g_pShaders[SHADER_20], macros, &inc);
}
inc.ps2x = 1;
LoadShader(GET_SHADER_INDEX(0, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20b), str, g_pShaders[SHADER_20b], macros, &inc);
macros[macroindex].Name = NULL;
macros[macroindex].Definition = NULL;
LoadShader(GET_SHADER_INDEX(0, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20a), str, g_pShaders[SHADER_20a], macros, &inc);
LoadShader(GET_SHADER_INDEX(0, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_30), str, g_pShaders[SHADER_30], macros, &inc);
if( texfilter == 0 ) {
// tex32
sprintf(str, "Texture%s%d_tex32PS", fog?"Fog":"", texfilter);
inc.ps2x = 0;
macros[macroindex].Name = "ACCURATE_DECOMPRESSION";
macros[macroindex].Definition = "1";
if( texfilter == 0 && exactcolor == 0 ) {
LoadShader(GET_SHADER_INDEX(1, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20), str, g_pShaders[SHADER_20], macros, &inc);
}
inc.ps2x = 1;
LoadShader(GET_SHADER_INDEX(1, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20b), str, g_pShaders[SHADER_20b], macros, &inc);
macros[macroindex].Name = NULL;
macros[macroindex].Definition = NULL;
LoadShader(GET_SHADER_INDEX(1, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20a), str, g_pShaders[SHADER_20a], macros, &inc);
LoadShader(GET_SHADER_INDEX(1, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_30), str, g_pShaders[SHADER_30], macros, &inc);
// clut32
sprintf(str, "Texture%s%d_clut32PS", fog?"Fog":"", texfilter);
inc.ps2x = 0;
macros[macroindex].Name = "ACCURATE_DECOMPRESSION";
macros[macroindex].Definition = "1";
if( texfilter == 0 && exactcolor == 0 ) {
LoadShader(GET_SHADER_INDEX(2, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20), str, g_pShaders[SHADER_20], macros, &inc);
}
inc.ps2x = 1;
LoadShader(GET_SHADER_INDEX(2, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20b), str, g_pShaders[SHADER_20b], macros, &inc);
macros[macroindex].Name = NULL;
macros[macroindex].Definition = NULL;
LoadShader(GET_SHADER_INDEX(2, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20a), str, g_pShaders[SHADER_20a], macros, &inc);
LoadShader(GET_SHADER_INDEX(2, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_30), str, g_pShaders[SHADER_30], macros, &inc);
// tex32to16
sprintf(str, "Texture%s%d_tex32to16PS", fog?"Fog":"", texfilter);
inc.ps2x = 0;
macros[macroindex].Name = "ACCURATE_DECOMPRESSION";
macros[macroindex].Definition = "1";
if( texfilter == 0 && exactcolor == 0 ) {
LoadShader(GET_SHADER_INDEX(3, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20), str, g_pShaders[SHADER_20], macros, &inc);
}
inc.ps2x = 1;
LoadShader(GET_SHADER_INDEX(3, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20b), str, g_pShaders[SHADER_20b], macros, &inc);
macros[macroindex].Name = NULL;
macros[macroindex].Definition = NULL;
LoadShader(GET_SHADER_INDEX(3, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20a), str, g_pShaders[SHADER_20a], macros, &inc);
LoadShader(GET_SHADER_INDEX(3, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_30), str, g_pShaders[SHADER_30], macros, &inc);
// tex16to8h
sprintf(str, "Texture%s%d_tex16to8hPS", fog?"Fog":"", texfilter);
inc.ps2x = 0;
macros[macroindex].Name = "ACCURATE_DECOMPRESSION";
macros[macroindex].Definition = "1";
inc.ps2x = 1;
LoadShader(GET_SHADER_INDEX(4, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20b), str, g_pShaders[SHADER_20b], macros, &inc);
macros[macroindex].Name = NULL;
macros[macroindex].Definition = NULL;
LoadShader(GET_SHADER_INDEX(4, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_20a), str, g_pShaders[SHADER_20a], macros, &inc);
LoadShader(GET_SHADER_INDEX(4, texfilter, texwrap, fog, writedepth, testaem, exactcolor, context, SHADER_30), str, g_pShaders[SHADER_30], macros, &inc);
}
}
--macroindex;
macros[macroindex].Name = NULL;
macros[macroindex].Definition = NULL;
}
--macroindex;
macros[macroindex].Name = NULL;
macros[macroindex].Definition = NULL;
}
--macroindex;
macros[macroindex].Name = NULL;
macros[macroindex].Definition = NULL;
}
}
}
}
// create the database
FILE* fdst = fopen(dstfilename, "wb");
if( fdst == NULL ) {
printf("failed to open %s\n", dstfilename);
return 0;
}
DWORD num = (DWORD)mapShaders.size();
fwrite(&num, 4, 1, fdst);
i = 0;
DWORD totaloffset = 4+sizeof(SHADERHEADER)*num;
for(map<DWORD, SHADERINFO>::iterator it = mapShaders.begin(); it != mapShaders.end(); ++it, ++i) {
SHADERHEADER h;
h.index = it->first | it->second.type;
h.offset = totaloffset;
h.size = it->second.pbuf->GetBufferSize();
fseek(fdst, 4+i*sizeof(SHADERHEADER), SEEK_SET);
fwrite(&h, sizeof(SHADERHEADER), 1, fdst);
fseek(fdst, totaloffset, SEEK_SET);
fwrite(it->second.pbuf->GetBufferPointer(), it->second.pbuf->GetBufferSize(), 1, fdst);
totaloffset += it->second.pbuf->GetBufferSize();
it->second.pbuf->Release();
}
fclose(fdst);
printf("wrote %s\n", dstfilename);
return 0;
}