Revert the recent zcomploc changes including the Graphic_Fixes merge.
Reason: - It's wrong, zcomploc can't be emulated perfectly in HW backends without severely impacting performance. - It provides virtually no advantages over the previous hack while introducing lots of code. - There is a better alternative: If people insist on having some sort of valid zcomploc emulation, I suggest rendering each primitive separately while using a _clean_ dual-pass approach to emulate zcomploc. This reverts commit0efd4e5c29
. This reverts commitb4ec836aca
. This reverts commitbb4c9e2205
. This reverts commit146b02615c
.
This commit is contained in:
parent
6e02ad55bc
commit
08a9c66037
|
@ -24,7 +24,7 @@
|
|||
// Increment this every time you change shader generation code.
|
||||
enum
|
||||
{
|
||||
LINEAR_DISKCACHE_VER = 6979
|
||||
LINEAR_DISKCACHE_VER = 6975
|
||||
};
|
||||
|
||||
// On disk format:
|
||||
|
|
|
@ -103,21 +103,21 @@ void GFXDebuggerBase::DumpPixelShader(const char* path)
|
|||
if (!useDstAlpha)
|
||||
{
|
||||
output = "Destination alpha disabled:\n";
|
||||
output += GeneratePixelShaderCode(PSGRENDER_NORMAL, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
|
||||
output += GeneratePixelShaderCode(DSTALPHA_NONE, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
|
||||
{
|
||||
output = "Using dual source blending for destination alpha:\n";
|
||||
output += GeneratePixelShaderCode(PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
|
||||
output += GeneratePixelShaderCode(DSTALPHA_DUAL_SOURCE_BLEND, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
|
||||
}
|
||||
else
|
||||
{
|
||||
output = "Using two passes for emulating destination alpha:\n";
|
||||
output += GeneratePixelShaderCode(PSGRENDER_NORMAL, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
|
||||
output += GeneratePixelShaderCode(DSTALPHA_NONE, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
|
||||
output += "\n\nDestination alpha pass shader:\n";
|
||||
output += GeneratePixelShaderCode(PSGRENDER_DSTALPHA_ALPHA_PASS, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
|
||||
output += GeneratePixelShaderCode(DSTALPHA_ALPHA_PASS, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
#include "BPMemory.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "PixelShaderManager.h"
|
||||
|
||||
static int AlphaPreTest();
|
||||
|
||||
static void StageHash(int stage, u32* out)
|
||||
{
|
||||
|
@ -101,25 +102,26 @@ static void StageHash(int stage, u32* out)
|
|||
// a unique identifier, basically containing all the bits. Yup, it's a lot ....
|
||||
// It would likely be a lot more efficient to build this incrementally as the attributes
|
||||
// are set...
|
||||
void GetPixelShaderId(PIXELSHADERUID *uid, PSGRENDER_MODE PSGRenderMode, u32 components)
|
||||
void GetPixelShaderId(PIXELSHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 components)
|
||||
{
|
||||
memset(uid->values, 0, sizeof(uid->values));
|
||||
uid->values[0] |= bpmem.genMode.numtevstages; // 4
|
||||
uid->values[0] |= bpmem.genMode.numtexgens << 4; // 4
|
||||
uid->values[0] |= ((u32)PSGRenderMode) << 8; // 2
|
||||
bool PixelLightingEnabled = g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting;
|
||||
bool DepthTextureEnable = (bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.zcomploc && (bpmem.zmode.testenable || bpmem.zmode.updateenable));
|
||||
bool MustWriteToDepth = DepthTextureEnable || g_ActiveConfig.bEnablePerPixelDepth;
|
||||
bool ZCompLocEnabled = bpmem.zcontrol.zcomploc && bpmem.zmode.updateenable;
|
||||
uid->values[0] |= dstAlphaMode << 8; // 2
|
||||
|
||||
bool DepthTextureEnable = (bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.zcomploc && bpmem.zmode.testenable && bpmem.zmode.updateenable) || g_ActiveConfig.bEnablePerPixelDepth;
|
||||
|
||||
uid->values[0] |= DepthTextureEnable << 10; // 1
|
||||
uid->values[0] |= MustWriteToDepth << 11; // 1
|
||||
uid->values[0] |= PixelLightingEnabled << 12; // 1
|
||||
if (!PixelLightingEnabled) uid->values[0] |= xfregs.numTexGen.numTexGens << 13; // 4
|
||||
ALPHA_PRETEST_RESULT alphaPreTest = PixelShaderManager::AlphaPreTest();
|
||||
uid->values[0] |= ((u32)alphaPreTest) << 17; // 2
|
||||
uid->values[0] |= ZCompLocEnabled << 18; // 2
|
||||
if (((alphaPreTest == ALPHAPT_ALWAYSFAIL) || (alphaPreTest == ALPHAPT_ALWAYSPASS && PSGRenderMode == PSGRENDER_DSTALPHA_ALPHA_PASS)) && !DepthTextureEnable)
|
||||
|
||||
bool enablePL = g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting;
|
||||
uid->values[0] |= enablePL << 11; // 1
|
||||
|
||||
if (!enablePL) uid->values[0] |= xfregs.numTexGen.numTexGens << 12; // 4
|
||||
u32 alphaPreTest = AlphaPreTest()+1;
|
||||
|
||||
uid->values[0] |= alphaPreTest << 16; // 2
|
||||
|
||||
if (alphaPreTest == 1 || (alphaPreTest && !DepthTextureEnable && dstAlphaMode == DSTALPHA_ALPHA_PASS))
|
||||
{
|
||||
// Courtesy of PreAlphaTest, we're done already ;)
|
||||
// NOTE: The comment header of generated shaders depends on the value of bpmem.genmode.numindstages.. shouldnt really bother about that though.
|
||||
|
@ -129,13 +131,13 @@ void GetPixelShaderId(PIXELSHADERUID *uid, PSGRENDER_MODE PSGRenderMode, u32 com
|
|||
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numtexgens; ++i)
|
||||
{
|
||||
if (19+i < 32)
|
||||
uid->values[0] |= xfregs.texMtxInfo[i].projection << (19+i); // 1
|
||||
if (18+i < 32)
|
||||
uid->values[0] |= xfregs.texMtxInfo[i].projection << (18+i); // 1
|
||||
else
|
||||
uid->values[1] |= xfregs.texMtxInfo[i].projection << (i - 13); // 1
|
||||
uid->values[1] |= xfregs.texMtxInfo[i].projection << (i - 14); // 1
|
||||
}
|
||||
|
||||
uid->values[1] = bpmem.genMode.numindstages << 3; // 3
|
||||
uid->values[1] = bpmem.genMode.numindstages << 2; // 3
|
||||
u32 indirectStagesUsed = 0;
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numindstages; ++i)
|
||||
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
|
||||
|
@ -143,13 +145,13 @@ void GetPixelShaderId(PIXELSHADERUID *uid, PSGRENDER_MODE PSGRenderMode, u32 com
|
|||
|
||||
assert(indirectStagesUsed == (indirectStagesUsed & 0xF));
|
||||
|
||||
uid->values[1] |= indirectStagesUsed << 6; // 4;
|
||||
uid->values[1] |= indirectStagesUsed << 5; // 4;
|
||||
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numindstages; ++i)
|
||||
{
|
||||
if (indirectStagesUsed & (1 << i))
|
||||
{
|
||||
uid->values[1] |= (bpmem.tevindref.getTexCoord(i) < bpmem.genMode.numtexgens) << (10 + 3*i); // 1
|
||||
uid->values[1] |= (bpmem.tevindref.getTexCoord(i) < bpmem.genMode.numtexgens) << (9 + 3*i); // 1
|
||||
if (bpmem.tevindref.getTexCoord(i) < bpmem.genMode.numtexgens)
|
||||
uid->values[1] |= bpmem.tevindref.getTexCoord(i) << (10 + 3*i); // 2
|
||||
}
|
||||
|
@ -178,7 +180,7 @@ void GetPixelShaderId(PIXELSHADERUID *uid, PSGRENDER_MODE PSGRenderMode, u32 com
|
|||
}
|
||||
}
|
||||
|
||||
if (PSGRenderMode != PSGRENDER_DSTALPHA_ALPHA_PASS)
|
||||
if (dstAlphaMode != DSTALPHA_ALPHA_PASS)
|
||||
{
|
||||
if (bpmem.fog.c_proj_fsel.fsel != 0)
|
||||
{
|
||||
|
@ -188,7 +190,7 @@ void GetPixelShaderId(PIXELSHADERUID *uid, PSGRENDER_MODE PSGRenderMode, u32 com
|
|||
}
|
||||
|
||||
++ptr;
|
||||
if (PixelLightingEnabled)
|
||||
if (enablePL)
|
||||
{
|
||||
ptr += GetLightingShaderId(ptr);
|
||||
*ptr++ = components;
|
||||
|
@ -197,26 +199,20 @@ void GetPixelShaderId(PIXELSHADERUID *uid, PSGRENDER_MODE PSGRenderMode, u32 com
|
|||
uid->num_values = ptr - uid->values;
|
||||
}
|
||||
|
||||
void GetSafePixelShaderId(PIXELSHADERUIDSAFE *uid, PSGRENDER_MODE PSGRenderMode, u32 components)
|
||||
void GetSafePixelShaderId(PIXELSHADERUIDSAFE *uid, DSTALPHA_MODE dstAlphaMode, u32 components)
|
||||
{
|
||||
memset(uid->values, 0, sizeof(uid->values));
|
||||
bool PixelLightingEnabled = g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting;
|
||||
bool DepthTextureEnable = (bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.zcomploc && (bpmem.zmode.testenable || bpmem.zmode.updateenable));
|
||||
bool MustWriteToDepth = DepthTextureEnable || g_ActiveConfig.bEnablePerPixelDepth;
|
||||
bool ZCompLocEnabled = bpmem.zcontrol.zcomploc && bpmem.zmode.updateenable;
|
||||
u32* ptr = uid->values;
|
||||
*ptr++ = ((u32)PSGRenderMode); // 0
|
||||
*ptr++ = dstAlphaMode; // 0
|
||||
*ptr++ = bpmem.genMode.hex; // 1
|
||||
*ptr++ = bpmem.ztex2.hex; // 2
|
||||
*ptr++ = bpmem.zcontrol.hex; // 3
|
||||
*ptr++ = bpmem.zmode.hex; // 4
|
||||
*ptr++ = MustWriteToDepth; // 5
|
||||
*ptr++ = PixelLightingEnabled; // 6
|
||||
*ptr++ = g_ActiveConfig.bEnablePerPixelDepth; // 5
|
||||
*ptr++ = g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting; // 6
|
||||
*ptr++ = xfregs.numTexGen.hex; // 7
|
||||
*ptr++ = DepthTextureEnable; // 8
|
||||
*ptr++ = ZCompLocEnabled; // 9
|
||||
|
||||
if (PixelLightingEnabled)
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
*ptr++ = xfregs.color[0].hex;
|
||||
*ptr++ = xfregs.alpha[0].hex;
|
||||
|
@ -226,43 +222,43 @@ void GetSafePixelShaderId(PIXELSHADERUIDSAFE *uid, PSGRENDER_MODE PSGRenderMode,
|
|||
}
|
||||
|
||||
for (unsigned int i = 0; i < 8; ++i)
|
||||
*ptr++ = xfregs.texMtxInfo[i].hex; // 9-17
|
||||
*ptr++ = xfregs.texMtxInfo[i].hex; // 8-15
|
||||
|
||||
for (unsigned int i = 0; i < 16; ++i)
|
||||
*ptr++ = bpmem.tevind[i].hex; // 18-33
|
||||
*ptr++ = bpmem.tevind[i].hex; // 16-31
|
||||
|
||||
*ptr++ = bpmem.tevindref.hex; // 34
|
||||
*ptr++ = bpmem.tevindref.hex; // 32
|
||||
|
||||
for (int i = 0; i < bpmem.genMode.numtevstages+1; ++i) // up to 16 times
|
||||
{
|
||||
*ptr++ = bpmem.combiners[i].colorC.hex; // 35+5*i
|
||||
*ptr++ = bpmem.combiners[i].alphaC.hex; // 36+5*i
|
||||
*ptr++ = bpmem.tevind[i].hex; // 37+5*i
|
||||
*ptr++ = bpmem.tevksel[i/2].hex; // 38+5*i
|
||||
*ptr++ = bpmem.tevorders[i/2].hex; // 39+5*i
|
||||
*ptr++ = bpmem.combiners[i].colorC.hex; // 33+5*i
|
||||
*ptr++ = bpmem.combiners[i].alphaC.hex; // 34+5*i
|
||||
*ptr++ = bpmem.tevind[i].hex; // 35+5*i
|
||||
*ptr++ = bpmem.tevksel[i/2].hex; // 36+5*i
|
||||
*ptr++ = bpmem.tevorders[i/2].hex; // 37+5*i
|
||||
}
|
||||
|
||||
ptr = &uid->values[115];
|
||||
ptr = &uid->values[113];
|
||||
|
||||
*ptr++ = bpmem.alphaFunc.hex; // 116
|
||||
*ptr++ = bpmem.alphaFunc.hex; // 113
|
||||
|
||||
*ptr++ = bpmem.fog.c_proj_fsel.hex; // 117
|
||||
*ptr++ = bpmem.fogRange.Base.hex; // 118
|
||||
*ptr++ = bpmem.fog.c_proj_fsel.hex; // 114
|
||||
*ptr++ = bpmem.fogRange.Base.hex; // 115
|
||||
|
||||
_assert_((ptr - uid->values) == uid->GetNumValues());
|
||||
}
|
||||
|
||||
void ValidatePixelShaderIDs(API_TYPE api, PIXELSHADERUIDSAFE old_id, const std::string& old_code, PSGRENDER_MODE PSGRenderMode, u32 components)
|
||||
void ValidatePixelShaderIDs(API_TYPE api, PIXELSHADERUIDSAFE old_id, const std::string& old_code, DSTALPHA_MODE dstAlphaMode, u32 components)
|
||||
{
|
||||
if (!g_ActiveConfig.bEnableShaderDebugging)
|
||||
return;
|
||||
|
||||
PIXELSHADERUIDSAFE new_id;
|
||||
GetSafePixelShaderId(&new_id, PSGRenderMode, components);
|
||||
GetSafePixelShaderId(&new_id, dstAlphaMode, components);
|
||||
|
||||
if (!(old_id == new_id))
|
||||
{
|
||||
std::string new_code(GeneratePixelShaderCode(PSGRenderMode, api, components));
|
||||
std::string new_code(GeneratePixelShaderCode(dstAlphaMode, api, components));
|
||||
if (old_code != new_code)
|
||||
{
|
||||
_assert_(old_id.GetNumValues() == new_id.GetNumValues());
|
||||
|
@ -303,7 +299,7 @@ void ValidatePixelShaderIDs(API_TYPE api, PIXELSHADERUIDSAFE old_id, const std::
|
|||
static void WriteStage(char *&p, int n, API_TYPE ApiType);
|
||||
static void SampleTexture(char *&p, const char *destination, const char *texcoords, const char *texswap, int texmap, API_TYPE ApiType);
|
||||
// static void WriteAlphaCompare(char *&p, int num, int comp);
|
||||
static void WriteAlphaTest(char *&p, API_TYPE ApiType,PSGRENDER_MODE PSGRenderMode);
|
||||
static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode);
|
||||
static void WriteFog(char *&p);
|
||||
|
||||
static const char *tevKSelTableC[] = // KCSEL
|
||||
|
@ -489,10 +485,7 @@ static const char *tevIndFmtScale[] = {"255.0f", "31.0f", "15.0f", "7.0f" };
|
|||
static char swapModeTable[4][5];
|
||||
|
||||
static char text[16384];
|
||||
static bool PixelLightingEnabled;
|
||||
static bool DepthTextureEnable;
|
||||
static bool MustWriteToDepth;
|
||||
static bool ZCompLocEnabled;
|
||||
|
||||
static void BuildSwapModeTable()
|
||||
{
|
||||
|
@ -507,7 +500,7 @@ static void BuildSwapModeTable()
|
|||
}
|
||||
}
|
||||
|
||||
const char *GeneratePixelShaderCode(PSGRENDER_MODE PSGRenderMode, API_TYPE ApiType, u32 components)
|
||||
const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components)
|
||||
{
|
||||
setlocale(LC_NUMERIC, "C"); // Reset locale for compilation
|
||||
text[sizeof(text) - 1] = 0x7C; // canary
|
||||
|
@ -530,10 +523,7 @@ const char *GeneratePixelShaderCode(PSGRENDER_MODE PSGRenderMode, API_TYPE ApiTy
|
|||
nIndirectStagesUsed |= 1 << bpmem.tevind[i].bt;
|
||||
}
|
||||
}
|
||||
PixelLightingEnabled = g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting;
|
||||
DepthTextureEnable = (bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.zcomploc && (bpmem.zmode.testenable || bpmem.zmode.updateenable));
|
||||
MustWriteToDepth = DepthTextureEnable || g_ActiveConfig.bEnablePerPixelDepth;
|
||||
ZCompLocEnabled = bpmem.zcontrol.zcomploc && bpmem.zmode.updateenable;
|
||||
DepthTextureEnable = (bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.zcomploc && bpmem.zmode.testenable && bpmem.zmode.updateenable) || g_ActiveConfig.bEnablePerPixelDepth ;
|
||||
// Declare samplers
|
||||
|
||||
if(ApiType != API_D3D11)
|
||||
|
@ -575,7 +565,7 @@ const char *GeneratePixelShaderCode(PSGRENDER_MODE PSGRenderMode, API_TYPE ApiTy
|
|||
WRITE(p, "uniform float4 " I_INDTEXMTX"[6] : register(c%d);\n", C_INDTEXMTX);
|
||||
WRITE(p, "uniform float4 " I_FOG"[3] : register(c%d);\n", C_FOG);
|
||||
|
||||
if(PixelLightingEnabled)
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
WRITE(p,"typedef struct { float4 col; float4 cosatt; float4 distatt; float4 pos; float4 dir; } Light;\n");
|
||||
WRITE(p,"typedef struct { Light lights[8]; } s_" I_PLIGHTS";\n");
|
||||
|
@ -588,15 +578,15 @@ const char *GeneratePixelShaderCode(PSGRENDER_MODE PSGRenderMode, API_TYPE ApiTy
|
|||
if(ApiType != API_D3D11)
|
||||
{
|
||||
WRITE(p, " out float4 ocol0 : COLOR0,%s%s\n in float4 rawpos : %s,\n",
|
||||
PSGRenderMode == PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : COLOR1," : "",
|
||||
MustWriteToDepth ? "\n out float depth : DEPTH," : "",
|
||||
dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : COLOR1," : "",
|
||||
DepthTextureEnable ? "\n out float depth : DEPTH," : "",
|
||||
ApiType & API_OPENGL ? "WPOS" : ApiType & API_D3D9_SM20 ? "POSITION" : "VPOS");
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(p, " out float4 ocol0 : SV_Target0,%s%s\n in float4 rawpos : SV_Position,\n",
|
||||
PSGRenderMode == PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : SV_Target1," : "",
|
||||
MustWriteToDepth ? "\n out float depth : SV_Depth," : "");
|
||||
dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : SV_Target1," : "",
|
||||
DepthTextureEnable ? "\n out float depth : SV_Depth," : "");
|
||||
}
|
||||
|
||||
WRITE(p, " in float4 colors_0 : COLOR0,\n");
|
||||
|
@ -608,70 +598,46 @@ const char *GeneratePixelShaderCode(PSGRENDER_MODE PSGRenderMode, API_TYPE ApiTy
|
|||
for (int i = 0; i < numTexgen; ++i)
|
||||
WRITE(p, ",\n in float3 uv%d : TEXCOORD%d", i, i);
|
||||
WRITE(p, ",\n in float4 clipPos : TEXCOORD%d", numTexgen);
|
||||
if(PixelLightingEnabled)
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
WRITE(p, ",\n in float4 Normal : TEXCOORD%d", numTexgen + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// wpos is in w of first 4 texcoords
|
||||
if(PixelLightingEnabled)
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
for (int i = 0; i < (numTexgen + 1); ++i)
|
||||
for (int i = 0; i < 8; ++i)
|
||||
WRITE(p, ",\n in float4 uv%d : TEXCOORD%d", i, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < numTexgen; ++i)
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
WRITE(p, ",\n in float%d uv%d : TEXCOORD%d", i < 4 ? 4 : 3 , i, i);
|
||||
}
|
||||
}
|
||||
WRITE(p, " ) {\n");
|
||||
if((bpmem.fog.c_proj_fsel.fsel != 0) || MustWriteToDepth)
|
||||
{
|
||||
// the screen space depth value = far z + (clip z / clip w) * z range
|
||||
if (numTexgen < 7)
|
||||
WRITE(p, "float zCoord = " I_ZBIAS "[1].x + (clipPos.z / clipPos.w) * " I_ZBIAS "[1].y;\n");
|
||||
else
|
||||
WRITE(p, "float zCoord = " I_ZBIAS "[1].x + (uv2.w / uv3.w) * " I_ZBIAS "[1].y;\n");
|
||||
}
|
||||
|
||||
char* pmainstart = p;
|
||||
if(PSGRenderMode == PSGRENDER_ZCOMPLOC && !DepthTextureEnable)
|
||||
int Pretest = AlphaPreTest();
|
||||
if(Pretest >= 0 && !DepthTextureEnable)
|
||||
{
|
||||
// Within ZCompLoc pass, make this an empty function
|
||||
if (!Pretest)
|
||||
{
|
||||
// alpha test will always fail, so restart the shader and just make it an empty function
|
||||
WRITE(p, "ocol0 = 0;\n");
|
||||
// only write to depth if shader Mode requires it
|
||||
if(MustWriteToDepth)
|
||||
WRITE(p, "depth = zCoord;\n");
|
||||
WRITE(p, "}\n");
|
||||
return text;
|
||||
}
|
||||
ALPHA_PRETEST_RESULT Pretest = PixelShaderManager::AlphaPreTest();
|
||||
// Test if we can predict the alpha test result or if we are in depth only mode
|
||||
if((Pretest != ALPHAPT_UNDEFINED) && !DepthTextureEnable)
|
||||
{
|
||||
if (Pretest == ALPHAPT_ALWAYSFAIL)
|
||||
{
|
||||
// alpha test will always fail, just make this an empty function
|
||||
WRITE(p, "ocol0 = 0;\n");
|
||||
// only write to depth if the shader mode requires it
|
||||
if(MustWriteToDepth)
|
||||
WRITE(p, "depth = zCoord;\n");
|
||||
// if we are in dual source blend mode initialize the secondary color o the shader will fail
|
||||
if(PSGRenderMode == PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND)
|
||||
if(DepthTextureEnable)
|
||||
WRITE(p, "depth = 1.f;\n");
|
||||
if(dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
|
||||
WRITE(p, "ocol1 = 0;\n");
|
||||
WRITE(p, "discard;\n");
|
||||
if(ApiType != API_D3D11)
|
||||
WRITE(p, "return;\n");
|
||||
}
|
||||
else if (PSGRenderMode == PSGRENDER_DSTALPHA_ALPHA_PASS)
|
||||
else if (dstAlphaMode == DSTALPHA_ALPHA_PASS)
|
||||
{
|
||||
//write constant alpha value
|
||||
WRITE(p, " ocol0 = " I_ALPHA"[0].aaaa;\n");
|
||||
// only write to depth if the shader mode requires it
|
||||
if(MustWriteToDepth)
|
||||
WRITE(p, "depth = zCoord;\n");
|
||||
}
|
||||
if((Pretest == ALPHAPT_ALWAYSFAIL) || (PSGRenderMode == PSGRENDER_DSTALPHA_ALPHA_PASS))
|
||||
if(!Pretest || dstAlphaMode == DSTALPHA_ALPHA_PASS)
|
||||
{
|
||||
WRITE(p, "}\n");
|
||||
return text;
|
||||
|
@ -687,9 +653,9 @@ const char *GeneratePixelShaderCode(PSGRENDER_MODE PSGRenderMode, API_TYPE ApiTy
|
|||
" float4 cc2=float4(0.0f,0.0f,0.0f,0.0f), cprev=float4(0.0f,0.0f,0.0f,0.0f);\n"
|
||||
" float4 crastemp=float4(0.0f,0.0f,0.0f,0.0f),ckonsttemp=float4(0.0f,0.0f,0.0f,0.0f);\n\n");
|
||||
|
||||
if(PixelLightingEnabled)
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
if (numTexgen < 7)
|
||||
if (xfregs.numTexGen.numTexGens < 7)
|
||||
{
|
||||
WRITE(p,"float3 _norm0 = normalize(Normal.xyz);\n\n");
|
||||
WRITE(p,"float3 pos = float3(clipPos.x,clipPos.y,Normal.w);\n");
|
||||
|
@ -764,10 +730,21 @@ const char *GeneratePixelShaderCode(PSGRENDER_MODE PSGRenderMode, API_TYPE ApiTy
|
|||
// emulation of unsigned 8 overflow when casting
|
||||
WRITE(p, "prev = frac(4.0f + prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");
|
||||
|
||||
if (MustWriteToDepth)
|
||||
if(Pretest == -1)
|
||||
{
|
||||
WriteAlphaTest(p, ApiType, dstAlphaMode);
|
||||
}
|
||||
|
||||
if((bpmem.fog.c_proj_fsel.fsel != 0) || DepthTextureEnable)
|
||||
{
|
||||
// the screen space depth value = far z + (clip z / clip w) * z range
|
||||
WRITE(p, "float zCoord = " I_ZBIAS"[1].x + (clipPos.z / clipPos.w) * " I_ZBIAS"[1].y;\n");
|
||||
}
|
||||
|
||||
if (DepthTextureEnable)
|
||||
{
|
||||
// use the texture input of the last texture stage (textemp), hopefully this has been read and is in correct format...
|
||||
if (DepthTextureEnable)
|
||||
if (bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.zcomploc && bpmem.zmode.testenable && bpmem.zmode.updateenable)
|
||||
{
|
||||
if (bpmem.ztex2.op == ZTEXTURE_ADD)
|
||||
WRITE(p, "zCoord = dot(" I_ZBIAS"[0].xyzw, textemp.xyzw) + " I_ZBIAS"[1].w + zCoord;\n");
|
||||
|
@ -782,7 +759,7 @@ const char *GeneratePixelShaderCode(PSGRENDER_MODE PSGRenderMode, API_TYPE ApiTy
|
|||
WRITE(p, "depth = zCoord;\n");
|
||||
}
|
||||
|
||||
if (PSGRenderMode == PSGRENDER_DSTALPHA_ALPHA_PASS)
|
||||
if (dstAlphaMode == DSTALPHA_ALPHA_PASS)
|
||||
WRITE(p, " ocol0 = float4(prev.rgb, " I_ALPHA"[0].a);\n");
|
||||
else
|
||||
{
|
||||
|
@ -792,7 +769,7 @@ const char *GeneratePixelShaderCode(PSGRENDER_MODE PSGRenderMode, API_TYPE ApiTy
|
|||
|
||||
// On D3D11, use dual-source color blending to perform dst alpha in a
|
||||
// single pass
|
||||
if (PSGRenderMode == PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND)
|
||||
if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
|
||||
{
|
||||
// Colors will be blended against the alpha from ocol1...
|
||||
WRITE(p, " ocol1 = ocol0;\n");
|
||||
|
@ -800,18 +777,6 @@ const char *GeneratePixelShaderCode(PSGRENDER_MODE PSGRenderMode, API_TYPE ApiTy
|
|||
WRITE(p, " ocol0.a = " I_ALPHA"[0].a;\n");
|
||||
}
|
||||
|
||||
// Alpha test could fail here if depth texture is enabled
|
||||
if (Pretest == ALPHAPT_ALWAYSFAIL)
|
||||
{
|
||||
WRITE(p, "discard;\n");
|
||||
if(ApiType != API_D3D11)
|
||||
WRITE(p, "return;\n");
|
||||
}
|
||||
else if(Pretest == ALPHAPT_UNDEFINED)
|
||||
{
|
||||
WriteAlphaTest(p, ApiType, PSGRenderMode);
|
||||
}
|
||||
|
||||
WRITE(p, "}\n");
|
||||
if (text[sizeof(text) - 1] != 0x7C)
|
||||
PanicAlert("PixelShader generator - buffer too small, canary has been eaten!");
|
||||
|
@ -1146,21 +1111,6 @@ static const char *tevAlphaFuncsTable[] =
|
|||
"(true)" //ALPHACMP_ALWAYS 7
|
||||
};
|
||||
|
||||
// THPS3 does not calculate ZCompLoc correctly if there is a margin
|
||||
// of error included. This table removes that margin for ALPHACMP_LESS
|
||||
// and ALPHACMP_GREATER. The other functions are to be confirmed.
|
||||
static const char *tevAlphaFuncsTableZCompLoc[] =
|
||||
{
|
||||
"(false)", //ALPHACMP_NEVER 0
|
||||
"(prev.a <= %s)", //ALPHACMP_LESS 1
|
||||
"(abs( prev.a - %s ) < (0.5f/255.0f))", //ALPHACMP_EQUAL 2
|
||||
"(prev.a < %s + (0.25f/255.0f))", //ALPHACMP_LEQUAL 3
|
||||
"(prev.a >= %s)", //ALPHACMP_GREATER 4
|
||||
"(abs( prev.a - %s ) >= (0.5f/255.0f))", //ALPHACMP_NEQUAL 5
|
||||
"(prev.a > %s - (0.25f/255.0f))", //ALPHACMP_GEQUAL 6
|
||||
"(true)" //ALPHACMP_ALWAYS 7
|
||||
};
|
||||
|
||||
static const char *tevAlphaFunclogicTable[] =
|
||||
{
|
||||
" && ", // and
|
||||
|
@ -1168,8 +1118,41 @@ static const char *tevAlphaFunclogicTable[] =
|
|||
" != ", // xor
|
||||
" == " // xnor
|
||||
};
|
||||
static int AlphaPreTest()
|
||||
{
|
||||
u32 op = bpmem.alphaFunc.logic;
|
||||
u32 comp[2] = {bpmem.alphaFunc.comp0, bpmem.alphaFunc.comp1};
|
||||
|
||||
static void WriteAlphaTest(char *&p, API_TYPE ApiType,PSGRENDER_MODE PSGRenderMode)
|
||||
// First kill all the simple cases
|
||||
switch(op)
|
||||
{
|
||||
case 0: // AND
|
||||
if (comp[0] == ALPHACMP_ALWAYS && comp[1] == ALPHACMP_ALWAYS) return true;
|
||||
if (comp[0] == ALPHACMP_NEVER || comp[1] == ALPHACMP_NEVER) return false;
|
||||
break;
|
||||
case 1: // OR
|
||||
if (comp[0] == ALPHACMP_ALWAYS || comp[1] == ALPHACMP_ALWAYS) return true;
|
||||
if (comp[0] == ALPHACMP_NEVER && comp[1] == ALPHACMP_NEVER)return false;
|
||||
break;
|
||||
case 2: // XOR
|
||||
if ((comp[0] == ALPHACMP_ALWAYS && comp[1] == ALPHACMP_NEVER) || (comp[0] == ALPHACMP_NEVER && comp[1] == ALPHACMP_ALWAYS))
|
||||
return true;
|
||||
if ((comp[0] == ALPHACMP_ALWAYS && comp[1] == ALPHACMP_ALWAYS) || (comp[0] == ALPHACMP_NEVER && comp[1] == ALPHACMP_NEVER))
|
||||
return false;
|
||||
break;
|
||||
case 3: // XNOR
|
||||
if ((comp[0] == ALPHACMP_ALWAYS && comp[1] == ALPHACMP_NEVER) || (comp[0] == ALPHACMP_NEVER && comp[1] == ALPHACMP_ALWAYS))
|
||||
return false;
|
||||
if ((comp[0] == ALPHACMP_ALWAYS && comp[1] == ALPHACMP_ALWAYS) || (comp[0] == ALPHACMP_NEVER && comp[1] == ALPHACMP_NEVER))
|
||||
return true;
|
||||
break;
|
||||
default: PanicAlert("bad logic for alpha test? %08x", op);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void WriteAlphaTest(char *&p, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode)
|
||||
{
|
||||
static const char *alphaRef[2] =
|
||||
{
|
||||
|
@ -1181,28 +1164,38 @@ static void WriteAlphaTest(char *&p, API_TYPE ApiType,PSGRENDER_MODE PSGRenderMo
|
|||
WRITE(p, "if(!( ");
|
||||
|
||||
int compindex = bpmem.alphaFunc.comp0 % 8;
|
||||
|
||||
// Lookup the first component from the alpha function table
|
||||
WRITE(p, ZCompLocEnabled ? tevAlphaFuncsTableZCompLoc[compindex] : tevAlphaFuncsTable[compindex], alphaRef[0]);
|
||||
WRITE(p, tevAlphaFuncsTable[compindex],alphaRef[0]);//lookup the first component from the alpha function table
|
||||
|
||||
WRITE(p, "%s", tevAlphaFunclogicTable[bpmem.alphaFunc.logic % 4]);//lookup the logic op
|
||||
|
||||
compindex = bpmem.alphaFunc.comp1 % 8;
|
||||
|
||||
// Lookup the second component from the alpha function table
|
||||
WRITE(p, ZCompLocEnabled ? tevAlphaFuncsTableZCompLoc[compindex] : tevAlphaFuncsTable[compindex], alphaRef[1]);
|
||||
WRITE(p, tevAlphaFuncsTable[compindex],alphaRef[1]);//lookup the second component from the alpha function table
|
||||
WRITE(p, ")) {\n");
|
||||
|
||||
// ZCompLoc is a way to control whether depth test is done before
|
||||
WRITE(p, "ocol0 = 0;\n");
|
||||
if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
|
||||
WRITE(p, "ocol1 = 0;\n");
|
||||
if (DepthTextureEnable)
|
||||
WRITE(p, "depth = 1.f;\n");
|
||||
|
||||
// HAXX: zcomploc is a way to control whether depth test is done before
|
||||
// or after texturing and alpha test. PC GPU does depth test before texturing ONLY if depth value is
|
||||
// not updated during shader execution.
|
||||
// 1 - if ZCompLoc is enabled make a first pass, with color channel write disabled updating only
|
||||
// We implement "depth test before texturing" by discarding the fragment
|
||||
// when the alpha test fail. This is not a correct implementation because
|
||||
// even if the depth test fails the fragment could be alpha blended.
|
||||
// this implemnetation is a trick to keep speed.
|
||||
// the correct, but slow, way to implement a correct zComploc is :
|
||||
// 1 - if zcomplock is enebled make a first pass, with color channel write disabled updating only
|
||||
// depth channel.
|
||||
// 2 - in the next pass disable depth chanel update, but proccess the color data normally
|
||||
// this way is the only CORRECT way to emulate perfectly the ZCompLoc behaviour
|
||||
// this way is the only CORRECT way to emulate perfectly the zcomplock behaviour
|
||||
if (!(bpmem.zcontrol.zcomploc && bpmem.zmode.updateenable))
|
||||
{
|
||||
WRITE(p, "discard;\n");
|
||||
if (ApiType != API_D3D11)
|
||||
WRITE(p, "return;\n");
|
||||
}
|
||||
|
||||
WRITE(p, "}\n");
|
||||
|
||||
|
|
|
@ -105,28 +105,20 @@ public:
|
|||
typedef _PIXELSHADERUID<false> PIXELSHADERUID;
|
||||
typedef _PIXELSHADERUID<true> PIXELSHADERUIDSAFE;
|
||||
|
||||
// Different ways to achieve rendering
|
||||
enum PSGRENDER_MODE
|
||||
// Different ways to achieve rendering with destination alpha
|
||||
enum DSTALPHA_MODE
|
||||
{
|
||||
PSGRENDER_NORMAL, // Render normally, without destination alpha
|
||||
PSGRENDER_DSTALPHA_ALPHA_PASS, // Render normally first, then render again for alpha
|
||||
PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND, // Use dual-source blending
|
||||
PSGRENDER_ZCOMPLOC //Render to Depth Channel only with no depth dextures enabled
|
||||
DSTALPHA_NONE, // Render normally, without destination alpha
|
||||
DSTALPHA_ALPHA_PASS, // Render normally first, then render again for alpha
|
||||
DSTALPHA_DUAL_SOURCE_BLEND // Use dual-source blending
|
||||
};
|
||||
|
||||
enum ALPHA_PRETEST_RESULT
|
||||
{
|
||||
ALPHAPT_UNDEFINED, // AlphaTest Result is not defined
|
||||
ALPHAPT_ALWAYSFAIL, // Alpha test alway Fail
|
||||
ALPHAPT_ALWAYSPASS // Alpha test alway Pass
|
||||
};
|
||||
const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components);
|
||||
|
||||
const char *GeneratePixelShaderCode(PSGRENDER_MODE PSGRenderMode, API_TYPE ApiType, u32 components);
|
||||
|
||||
void GetPixelShaderId(PIXELSHADERUID *uid, PSGRENDER_MODE PSGRenderMode, u32 components);
|
||||
void GetSafePixelShaderId(PIXELSHADERUIDSAFE *uid, PSGRENDER_MODE PSGRenderMode, u32 components);
|
||||
void GetPixelShaderId(PIXELSHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 components);
|
||||
void GetSafePixelShaderId(PIXELSHADERUIDSAFE *uid, DSTALPHA_MODE dstAlphaMode, u32 components);
|
||||
|
||||
// Used to make sure that our optimized pixel shader IDs don't lose any possible shader code changes
|
||||
void ValidatePixelShaderIDs(API_TYPE api, PIXELSHADERUIDSAFE old_id, const std::string& old_code, PSGRENDER_MODE PSGRenderMode, u32 components);
|
||||
void ValidatePixelShaderIDs(API_TYPE api, PIXELSHADERUIDSAFE old_id, const std::string& old_code, DSTALPHA_MODE dstAlphaMode, u32 components);
|
||||
|
||||
#endif // GCOGL_PIXELSHADER_H
|
||||
|
|
|
@ -466,39 +466,6 @@ void PixelShaderManager::SetMaterialColorChanged(int index)
|
|||
nMaterialsChanged |= (1 << index);
|
||||
}
|
||||
|
||||
ALPHA_PRETEST_RESULT PixelShaderManager::AlphaPreTest()
|
||||
{
|
||||
u32 op = bpmem.alphaFunc.logic;
|
||||
u32 comp[2] = {bpmem.alphaFunc.comp0, bpmem.alphaFunc.comp1};
|
||||
|
||||
// First kill all the simple cases
|
||||
switch(op)
|
||||
{
|
||||
case 0: // AND
|
||||
if (comp[0] == ALPHACMP_ALWAYS && comp[1] == ALPHACMP_ALWAYS) return ALPHAPT_ALWAYSPASS;
|
||||
if (comp[0] == ALPHACMP_NEVER || comp[1] == ALPHACMP_NEVER) return ALPHAPT_ALWAYSFAIL;
|
||||
break;
|
||||
case 1: // OR
|
||||
if (comp[0] == ALPHACMP_ALWAYS || comp[1] == ALPHACMP_ALWAYS) return ALPHAPT_ALWAYSPASS;
|
||||
if (comp[0] == ALPHACMP_NEVER && comp[1] == ALPHACMP_NEVER)return ALPHAPT_ALWAYSFAIL;
|
||||
break;
|
||||
case 2: // XOR
|
||||
if ((comp[0] == ALPHACMP_ALWAYS && comp[1] == ALPHACMP_NEVER) || (comp[0] == ALPHACMP_NEVER && comp[1] == ALPHACMP_ALWAYS))
|
||||
return ALPHAPT_ALWAYSPASS;
|
||||
if ((comp[0] == ALPHACMP_ALWAYS && comp[1] == ALPHACMP_ALWAYS) || (comp[0] == ALPHACMP_NEVER && comp[1] == ALPHACMP_NEVER))
|
||||
return ALPHAPT_ALWAYSFAIL;
|
||||
break;
|
||||
case 3: // XNOR
|
||||
if ((comp[0] == ALPHACMP_ALWAYS && comp[1] == ALPHACMP_NEVER) || (comp[0] == ALPHACMP_NEVER && comp[1] == ALPHACMP_ALWAYS))
|
||||
return ALPHAPT_ALWAYSFAIL;
|
||||
if ((comp[0] == ALPHACMP_ALWAYS && comp[1] == ALPHACMP_ALWAYS) || (comp[0] == ALPHACMP_NEVER && comp[1] == ALPHACMP_NEVER))
|
||||
return ALPHAPT_ALWAYSPASS;
|
||||
break;
|
||||
default: PanicAlert("bad logic for alpha test? %08x", op);
|
||||
}
|
||||
return ALPHAPT_UNDEFINED;
|
||||
}
|
||||
|
||||
void PixelShaderManager::DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(lastRGBAfull);
|
||||
|
|
|
@ -54,7 +54,6 @@ public:
|
|||
static void SetColorMatrix(const float* pmatrix);
|
||||
static void InvalidateXFRange(int start, int end);
|
||||
static void SetMaterialColorChanged(int index);
|
||||
static ALPHA_PRETEST_RESULT AlphaPreTest();
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -43,11 +43,6 @@ extern int OSDChoice, OSDTime;
|
|||
|
||||
extern bool bLastFrameDumped;
|
||||
|
||||
#define RSM_None 0
|
||||
#define RSM_Multipass 1
|
||||
#define RSM_Zcomploc 2
|
||||
#define RSM_UseDstAlpha 4
|
||||
|
||||
// Renderer really isn't a very good name for this class - it's more like "Misc".
|
||||
// The long term goal is to get rid of this class and replace it with others that make
|
||||
// more sense.
|
||||
|
@ -68,7 +63,7 @@ public:
|
|||
virtual void SetSamplerState(int stage,int texindex) = 0;
|
||||
virtual void SetInterlacingMode() = 0;
|
||||
|
||||
virtual void ApplyState(u32 mode) = 0;
|
||||
virtual void ApplyState(bool bUseDstAlpha) = 0;
|
||||
virtual void RestoreState() = 0;
|
||||
|
||||
// Ideal internal resolution - determined by display resolution (automatic scaling) and/or a multiple of the native EFB resolution
|
||||
|
|
|
@ -459,10 +459,10 @@ void PixelShaderCache::Shutdown()
|
|||
g_ps_disk_cache.Close();
|
||||
}
|
||||
|
||||
bool PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 components)
|
||||
bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
|
||||
{
|
||||
PIXELSHADERUID uid;
|
||||
GetPixelShaderId(&uid, PSGRenderMode, components);
|
||||
GetPixelShaderId(&uid, dstAlphaMode, components);
|
||||
|
||||
// Check if the shader is already set
|
||||
if (last_entry)
|
||||
|
@ -470,7 +470,7 @@ bool PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 components)
|
|||
if (uid == last_uid)
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true);
|
||||
ValidatePixelShaderIDs(API_D3D11, last_entry->safe_uid, last_entry->code, PSGRenderMode, components);
|
||||
ValidatePixelShaderIDs(API_D3D11, last_entry->safe_uid, last_entry->code, dstAlphaMode, components);
|
||||
return (last_entry->shader != NULL);
|
||||
}
|
||||
}
|
||||
|
@ -486,12 +486,12 @@ bool PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 components)
|
|||
last_entry = &entry;
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true);
|
||||
ValidatePixelShaderIDs(API_D3D11, entry.safe_uid, entry.code, PSGRenderMode, components);
|
||||
ValidatePixelShaderIDs(API_D3D11, entry.safe_uid, entry.code, dstAlphaMode, components);
|
||||
return (entry.shader != NULL);
|
||||
}
|
||||
|
||||
// Need to compile a new shader
|
||||
const char* code = GeneratePixelShaderCode(PSGRenderMode, API_D3D11, components);
|
||||
const char* code = GeneratePixelShaderCode(dstAlphaMode, API_D3D11, components);
|
||||
|
||||
D3DBlob* pbytecode;
|
||||
if (!D3D::CompilePixelShader(code, (unsigned int)strlen(code), &pbytecode))
|
||||
|
@ -509,7 +509,7 @@ bool PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 components)
|
|||
if (g_ActiveConfig.bEnableShaderDebugging && success)
|
||||
{
|
||||
PixelShaders[uid].code = code;
|
||||
GetSafePixelShaderId(&PixelShaders[uid].safe_uid, PSGRenderMode, components);
|
||||
GetSafePixelShaderId(&PixelShaders[uid].safe_uid, dstAlphaMode, components);
|
||||
}
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
enum PSGRENDER_MODE;
|
||||
enum DSTALPHA_MODE;
|
||||
|
||||
namespace DX11
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
static void Init();
|
||||
static void Clear();
|
||||
static void Shutdown();
|
||||
static bool SetShader(PSGRENDER_MODE PSGRenderMode, u32 components); // TODO: Should be renamed to LoadShader
|
||||
static bool SetShader(DSTALPHA_MODE dstAlphaMode, u32 components); // TODO: Should be renamed to LoadShader
|
||||
static bool InsertByteCode(const PIXELSHADERUID &uid, const void* bytecode, unsigned int bytecodelen);
|
||||
|
||||
static ID3D11PixelShader* GetActiveShader() { return last_entry->shader; }
|
||||
|
|
|
@ -1224,11 +1224,11 @@ void Renderer::RestoreAPIState()
|
|||
BPFunctions::SetScissor();
|
||||
}
|
||||
|
||||
void Renderer::ApplyState(u32 mode)
|
||||
void Renderer::ApplyState(bool bUseDstAlpha)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (mode & RSM_UseDstAlpha)
|
||||
if (bUseDstAlpha)
|
||||
{
|
||||
// Colors should blend against SRC1_ALPHA
|
||||
if (gx_state.blenddc.RenderTarget[0].SrcBlend == D3D11_BLEND_SRC_ALPHA)
|
||||
|
@ -1288,7 +1288,7 @@ void Renderer::ApplyState(u32 mode)
|
|||
|
||||
D3D::stateman->Apply();
|
||||
|
||||
if (mode & RSM_UseDstAlpha)
|
||||
if (bUseDstAlpha)
|
||||
{
|
||||
// restore actual state
|
||||
SetBlendMode(false);
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
void SetInterlacingMode();
|
||||
|
||||
// TODO: Fix confusing names (see ResetAPIState and RestoreAPIState)
|
||||
void ApplyState(u32 mode);
|
||||
void ApplyState(bool bUseDstAlpha);
|
||||
void RestoreState();
|
||||
|
||||
void ApplyCullDisable();
|
||||
|
|
|
@ -249,7 +249,7 @@ void VertexManager::vFlush()
|
|||
bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||
|
||||
if (!PixelShaderCache::SetShader(
|
||||
useDstAlpha ? PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND : PSGRENDER_NORMAL,
|
||||
useDstAlpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE,
|
||||
g_nativeVertexFmt->m_components))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
|
||||
|
@ -264,7 +264,7 @@ void VertexManager::vFlush()
|
|||
unsigned int stride = g_nativeVertexFmt->GetVertexStride();
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
|
||||
g_renderer->ApplyState(useDstAlpha ? RSM_UseDstAlpha : RSM_None);
|
||||
g_renderer->ApplyState(useDstAlpha);
|
||||
LoadBuffers();
|
||||
Draw(stride);
|
||||
|
||||
|
|
|
@ -330,11 +330,11 @@ void PixelShaderCache::Shutdown()
|
|||
unique_shaders.clear();
|
||||
}
|
||||
|
||||
bool PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 components)
|
||||
bool PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
|
||||
{
|
||||
const API_TYPE api = ((D3D::GetCaps().PixelShaderVersion >> 8) & 0xFF) < 3 ? API_D3D9_SM20 : API_D3D9_SM30;
|
||||
PIXELSHADERUID uid;
|
||||
GetPixelShaderId(&uid, PSGRenderMode, components);
|
||||
GetPixelShaderId(&uid, dstAlphaMode, components);
|
||||
|
||||
// Check if the shader is already set
|
||||
if (last_entry)
|
||||
|
@ -342,7 +342,7 @@ bool PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 components)
|
|||
if (uid == last_uid)
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
ValidatePixelShaderIDs(api, last_entry->safe_uid, last_entry->code, PSGRenderMode, components);
|
||||
ValidatePixelShaderIDs(api, last_entry->safe_uid, last_entry->code, dstAlphaMode, components);
|
||||
return last_entry->shader != NULL;
|
||||
}
|
||||
}
|
||||
|
@ -359,13 +359,13 @@ bool PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 components)
|
|||
|
||||
if (entry.shader) D3D::SetPixelShader(entry.shader);
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
ValidatePixelShaderIDs(api, entry.safe_uid, entry.code, PSGRenderMode, components);
|
||||
ValidatePixelShaderIDs(api, entry.safe_uid, entry.code, dstAlphaMode, components);
|
||||
return (entry.shader != NULL);
|
||||
}
|
||||
|
||||
|
||||
// Need to compile a new shader
|
||||
const char *code = GeneratePixelShaderCode(PSGRenderMode, api, components);
|
||||
const char *code = GeneratePixelShaderCode(dstAlphaMode, api, components);
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging)
|
||||
{
|
||||
|
@ -401,7 +401,7 @@ bool PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 components)
|
|||
if (g_ActiveConfig.bEnableShaderDebugging && success)
|
||||
{
|
||||
PixelShaders[uid].code = code;
|
||||
GetSafePixelShaderId(&PixelShaders[uid].safe_uid, PSGRenderMode, components);
|
||||
GetSafePixelShaderId(&PixelShaders[uid].safe_uid, dstAlphaMode, components);
|
||||
}
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
|
|
|
@ -63,7 +63,7 @@ private:
|
|||
public:
|
||||
static void Init();
|
||||
static void Shutdown();
|
||||
static bool SetShader(PSGRENDER_MODE PSGRenderMode, u32 componets);
|
||||
static bool SetShader(DSTALPHA_MODE dstAlphaMode, u32 componets);
|
||||
static bool InsertByteCode(const PIXELSHADERUID &uid, const u8 *bytecode, int bytecodelen, bool activate);
|
||||
static LPDIRECT3DPIXELSHADER9 GetColorMatrixProgram(int SSAAMode);
|
||||
static LPDIRECT3DPIXELSHADER9 GetColorCopyProgram(int SSAAMode);
|
||||
|
|
|
@ -247,7 +247,6 @@ void TeardownDeviceObjects()
|
|||
// Init functions
|
||||
Renderer::Renderer()
|
||||
{
|
||||
Renderer::LastMode = RSM_None;
|
||||
st = new char[32768];
|
||||
|
||||
int fullScreenRes, x, y, w_temp, h_temp;
|
||||
|
@ -1202,49 +1201,20 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
|||
XFBWrited = false;
|
||||
}
|
||||
|
||||
void Renderer::ApplyState(u32 mode)
|
||||
void Renderer::ApplyState(bool bUseDstAlpha)
|
||||
{
|
||||
if(mode & RSM_Zcomploc)
|
||||
{
|
||||
D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, 0);
|
||||
}
|
||||
|
||||
if(mode & RSM_Multipass)
|
||||
{
|
||||
D3D::ChangeRenderState(D3DRS_ZENABLE, TRUE);
|
||||
D3D::ChangeRenderState(D3DRS_ZWRITEENABLE, false);
|
||||
D3D::ChangeRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
|
||||
}
|
||||
|
||||
if (mode & RSM_UseDstAlpha)
|
||||
if (bUseDstAlpha)
|
||||
{
|
||||
D3D::ChangeRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA);
|
||||
D3D::ChangeRenderState(D3DRS_ALPHABLENDENABLE, false);
|
||||
}
|
||||
Renderer::LastMode |= mode;
|
||||
}
|
||||
|
||||
void Renderer::RestoreState()
|
||||
{
|
||||
if(Renderer::LastMode & RSM_Zcomploc)
|
||||
{
|
||||
D3D::RefreshRenderState(D3DRS_COLORWRITEENABLE);
|
||||
}
|
||||
|
||||
if(Renderer::LastMode & RSM_Multipass)
|
||||
{
|
||||
D3D::RefreshRenderState(D3DRS_ALPHABLENDENABLE);
|
||||
D3D::RefreshRenderState(D3DRS_ZENABLE);
|
||||
D3D::RefreshRenderState(D3DRS_ZWRITEENABLE);
|
||||
D3D::RefreshRenderState(D3DRS_ZFUNC);
|
||||
}
|
||||
|
||||
if(Renderer::LastMode & RSM_UseDstAlpha)
|
||||
{
|
||||
D3D::RefreshRenderState(D3DRS_COLORWRITEENABLE);
|
||||
D3D::RefreshRenderState(D3DRS_ALPHABLENDENABLE);
|
||||
}
|
||||
Renderer::LastMode = RSM_None;
|
||||
|
||||
// TODO: Enable this code. Caused glitches for me however (neobrain)
|
||||
// for (unsigned int i = 0; i < 8; ++i)
|
||||
// D3D::dev->SetTexture(i, NULL);
|
||||
|
|
|
@ -9,8 +9,6 @@ namespace DX9
|
|||
|
||||
class Renderer : public ::Renderer
|
||||
{
|
||||
private:
|
||||
u32 LastMode;
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
@ -26,7 +24,7 @@ public:
|
|||
void SetSamplerState(int stage,int texindex);
|
||||
void SetInterlacingMode();
|
||||
|
||||
void ApplyState(u32 mode);
|
||||
void ApplyState(bool bUseDstAlpha);
|
||||
void RestoreState();
|
||||
|
||||
void RenderText(const char* pstr, int left, int top, u32 color);
|
||||
|
|
|
@ -154,7 +154,7 @@ void VertexManager::vFlush()
|
|||
VertexShaderManager::SetConstants();
|
||||
PixelShaderManager::SetConstants();
|
||||
|
||||
if (!PixelShaderCache::SetShader(PSGRENDER_NORMAL,g_nativeVertexFmt->m_components))
|
||||
if (!PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
|
||||
goto shader_fail;
|
||||
|
@ -175,27 +175,14 @@ void VertexManager::vFlush()
|
|||
bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||
if (useDstAlpha)
|
||||
{
|
||||
if (!PixelShaderCache::SetShader(PSGRENDER_DSTALPHA_ALPHA_PASS, g_nativeVertexFmt->m_components))
|
||||
DWORD write = 0;
|
||||
if (!PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS, g_nativeVertexFmt->m_components))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
|
||||
goto shader_fail;
|
||||
}
|
||||
// update alpha only
|
||||
g_renderer->ApplyState(RSM_UseDstAlpha | (bpmem.zmode.updateenable ? RSM_Multipass : RSM_None));
|
||||
Draw(stride);
|
||||
g_renderer->RestoreState();
|
||||
}
|
||||
|
||||
bool useZcomploc = bpmem.zcontrol.zcomploc && bpmem.zmode.updateenable;
|
||||
if (useZcomploc && PixelShaderManager::AlphaPreTest() == ALPHAPT_UNDEFINED)
|
||||
{
|
||||
if (!PixelShaderCache::SetShader(PSGRENDER_ZCOMPLOC, g_nativeVertexFmt->m_components))
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR,true,{printf("Fail to set pixel shader\n");});
|
||||
goto shader_fail;
|
||||
}
|
||||
// update Depth only
|
||||
g_renderer->ApplyState(RSM_Zcomploc);
|
||||
g_renderer->ApplyState(true);
|
||||
Draw(stride);
|
||||
g_renderer->RestoreState();
|
||||
}
|
||||
|
|
|
@ -181,10 +181,10 @@ void PixelShaderCache::Shutdown()
|
|||
PixelShaders.clear();
|
||||
}
|
||||
|
||||
FRAGMENTSHADER* PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 components)
|
||||
FRAGMENTSHADER* PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components)
|
||||
{
|
||||
PIXELSHADERUID uid;
|
||||
GetPixelShaderId(&uid, PSGRenderMode, components);
|
||||
GetPixelShaderId(&uid, dstAlphaMode, components);
|
||||
|
||||
// Check if the shader is already set
|
||||
if (last_entry)
|
||||
|
@ -192,7 +192,7 @@ FRAGMENTSHADER* PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 co
|
|||
if (uid == last_uid)
|
||||
{
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
ValidatePixelShaderIDs(API_OPENGL, last_entry->safe_uid, last_entry->shader.strprog, PSGRenderMode, components);
|
||||
ValidatePixelShaderIDs(API_OPENGL, last_entry->safe_uid, last_entry->shader.strprog, dstAlphaMode, components);
|
||||
return &last_entry->shader;
|
||||
}
|
||||
}
|
||||
|
@ -206,18 +206,18 @@ FRAGMENTSHADER* PixelShaderCache::SetShader(PSGRENDER_MODE PSGRenderMode, u32 co
|
|||
last_entry = &entry;
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
|
||||
ValidatePixelShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, PSGRenderMode, components);
|
||||
ValidatePixelShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, dstAlphaMode, components);
|
||||
return &last_entry->shader;
|
||||
}
|
||||
|
||||
// Make an entry in the table
|
||||
PSCacheEntry& newentry = PixelShaders[uid];
|
||||
last_entry = &newentry;
|
||||
const char *code = GeneratePixelShaderCode(PSGRenderMode, API_OPENGL, components);
|
||||
const char *code = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components);
|
||||
|
||||
if (g_ActiveConfig.bEnableShaderDebugging && code)
|
||||
{
|
||||
GetSafePixelShaderId(&newentry.safe_uid, PSGRenderMode, components);
|
||||
GetSafePixelShaderId(&newentry.safe_uid, dstAlphaMode, components);
|
||||
newentry.shader.strprog = code;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
static void Init();
|
||||
static void Shutdown();
|
||||
|
||||
static FRAGMENTSHADER* SetShader(PSGRENDER_MODE PSGRenderMode, u32 components);
|
||||
static FRAGMENTSHADER* SetShader(DSTALPHA_MODE dstAlphaMode, u32 components);
|
||||
static bool CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram);
|
||||
|
||||
static GLuint GetColorMatrixProgram();
|
||||
|
|
|
@ -245,7 +245,6 @@ int GetNumMSAACoverageSamples(int MSAAMode)
|
|||
// Init functions
|
||||
Renderer::Renderer()
|
||||
{
|
||||
Renderer::LastMode = RSM_None;
|
||||
OSDInternalW = 0;
|
||||
OSDInternalH = 0;
|
||||
|
||||
|
@ -516,49 +515,6 @@ Renderer::~Renderer()
|
|||
delete g_framebuffer_manager;
|
||||
}
|
||||
|
||||
void Renderer::ApplyState(u32 mode)
|
||||
{
|
||||
if(mode & RSM_Zcomploc)
|
||||
{
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
}
|
||||
|
||||
if(mode & RSM_Multipass)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
glDepthFunc(GL_EQUAL);
|
||||
}
|
||||
|
||||
if (mode & RSM_UseDstAlpha)
|
||||
{
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
Renderer::LastMode |= mode;
|
||||
}
|
||||
|
||||
void Renderer::RestoreState()
|
||||
{
|
||||
if(Renderer::LastMode & RSM_Zcomploc)
|
||||
{
|
||||
SetColorMask();
|
||||
}
|
||||
|
||||
if(Renderer::LastMode & RSM_Multipass)
|
||||
{
|
||||
SetDepthMode();
|
||||
}
|
||||
|
||||
if (Renderer::LastMode & RSM_UseDstAlpha)
|
||||
{
|
||||
SetColorMask();
|
||||
if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract)
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
Renderer::LastMode = RSM_None;
|
||||
}
|
||||
|
||||
// Create On-Screen-Messages
|
||||
void Renderer::DrawDebugInfo()
|
||||
{
|
||||
|
|
|
@ -11,8 +11,6 @@ void ClearEFBCache();
|
|||
|
||||
class Renderer : public ::Renderer
|
||||
{
|
||||
private:
|
||||
u32 LastMode;
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
|
@ -29,8 +27,8 @@ public:
|
|||
void SetInterlacingMode();
|
||||
|
||||
// TODO: Implement and use these
|
||||
void ApplyState(u32 mode);
|
||||
void RestoreState();
|
||||
void ApplyState(bool bUseDstAlpha) {}
|
||||
void RestoreState() {}
|
||||
|
||||
void RenderText(const char* pstr, int left, int top, u32 color);
|
||||
void DrawDebugInfo();
|
||||
|
|
|
@ -187,21 +187,21 @@ void VertexManager::vFlush()
|
|||
// If host supports GL_ARB_blend_func_extended, we can do dst alpha in
|
||||
// the same pass as regular rendering.
|
||||
g_renderer->SetBlendMode(true);
|
||||
ps = PixelShaderCache::SetShader(PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components);
|
||||
ps = PixelShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_renderer->SetBlendMode(true);
|
||||
ps = PixelShaderCache::SetShader(PSGRENDER_NORMAL,g_nativeVertexFmt->m_components);
|
||||
ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ps = PixelShaderCache::SetShader(PSGRENDER_NORMAL,g_nativeVertexFmt->m_components);
|
||||
ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
|
||||
}
|
||||
#else
|
||||
bool dualSourcePossible = false;
|
||||
FRAGMENTSHADER* ps = PixelShaderCache::SetShader(PSGRENDER_NORMAL,g_nativeVertexFmt->m_components);
|
||||
FRAGMENTSHADER* ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components);
|
||||
#endif
|
||||
VERTEXSHADER* vs = VertexShaderCache::SetShader(g_nativeVertexFmt->m_components);
|
||||
if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid); // Lego Star Wars crashes here.
|
||||
|
@ -212,22 +212,20 @@ void VertexManager::vFlush()
|
|||
// run through vertex groups again to set alpha
|
||||
if (useDstAlpha && !dualSourcePossible)
|
||||
{
|
||||
ps = PixelShaderCache::SetShader(PSGRENDER_DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components);
|
||||
ps = PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components);
|
||||
if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid);
|
||||
|
||||
g_renderer->ApplyState(RSM_UseDstAlpha | (bpmem.zmode.updateenable ? RSM_Multipass : RSM_None));
|
||||
Draw();
|
||||
g_renderer->RestoreState();
|
||||
}
|
||||
bool useZcomploc = bpmem.zcontrol.zcomploc && bpmem.zmode.updateenable;
|
||||
if (useZcomploc && PixelShaderManager::AlphaPreTest() == ALPHAPT_UNDEFINED)
|
||||
{
|
||||
ps = PixelShaderCache::SetShader(PSGRENDER_ZCOMPLOC,g_nativeVertexFmt->m_components);
|
||||
if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid);
|
||||
// only update alpha
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
g_renderer->ApplyState(RSM_Zcomploc);
|
||||
Draw();
|
||||
g_renderer->RestoreState();
|
||||
// restore color mask
|
||||
g_renderer->SetColorMask();
|
||||
|
||||
if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract)
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_FLUSH, true);
|
||||
|
||||
|
|
Loading…
Reference in New Issue