softgpu: Fix PixelFuncID size.

Oops, can't use unions in bitfields.  Also improve typesafety.
This commit is contained in:
Unknown W. Brackets 2021-11-21 09:39:14 -08:00
parent be152acf7b
commit 876c8cd368
7 changed files with 103 additions and 54 deletions

View file

@ -127,7 +127,7 @@ static inline bool AlphaTestPassed(const PixelFuncID &pixelID, int alpha) {
if (pixelID.hasAlphaTestMask)
alpha &= gstate.getAlphaTestMask();
switch (GEComparison(pixelID.alphaTestFunc)) {
switch (pixelID.AlphaTestFunc()) {
case GE_COMP_NEVER:
return false;
@ -369,7 +369,7 @@ inline void DrawSinglePixel(int x, int y, int z, int fog, const Vec4<int> &color
if (z < gstate.getDepthRangeMin() || z > gstate.getDepthRangeMax())
return;
if (GEComparison(pixelID.alphaTestFunc) != GE_COMP_ALWAYS && !clearMode)
if (pixelID.AlphaTestFunc() != GE_COMP_ALWAYS && !clearMode)
if (!AlphaTestPassed(pixelID, prim_color.a()))
return;
@ -389,7 +389,7 @@ inline void DrawSinglePixel(int x, int y, int z, int fog, const Vec4<int> &color
// In clear mode, it uses the alpha color as stencil.
u8 stencil = clearMode ? prim_color.a() : GetPixelStencil(fbFormat, x, y);
if (clearMode) {
if (pixelID.depthClear)
if (pixelID.DepthClear())
SetPixelDepth(x, y, z);
} else if (pixelID.stencilTest) {
if (!StencilTestPassed(pixelID, stencil)) {
@ -399,7 +399,7 @@ inline void DrawSinglePixel(int x, int y, int z, int fog, const Vec4<int> &color
}
// Also apply depth at the same time. If disabled, same as passing.
if (pixelID.depthTestFunc != GE_COMP_ALWAYS && !DepthTestPassed(GEComparison(pixelID.depthTestFunc), x, y, z)) {
if (pixelID.DepthTestFunc() != GE_COMP_ALWAYS && !DepthTestPassed(pixelID.DepthTestFunc(), x, y, z)) {
stencil = ApplyStencilOp(fbFormat, GEStencilOp(pixelID.zFail), stencil);
SetPixelStencil(fbFormat, x, y, stencil);
return;
@ -407,7 +407,7 @@ inline void DrawSinglePixel(int x, int y, int z, int fog, const Vec4<int> &color
stencil = ApplyStencilOp(fbFormat, GEStencilOp(pixelID.zPass), stencil);
} else {
if (pixelID.depthTestFunc != GE_COMP_ALWAYS && !DepthTestPassed(GEComparison(pixelID.depthTestFunc), x, y, z)) {
if (pixelID.DepthTestFunc() != GE_COMP_ALWAYS && !DepthTestPassed(pixelID.DepthTestFunc(), x, y, z)) {
return;
}
}
@ -460,7 +460,7 @@ inline void DrawSinglePixel(int x, int y, int z, int fog, const Vec4<int> &color
SingleFunc GetSingleFunc(const PixelFuncID &id) {
if (id.clearMode) {
switch (id.fbFormat) {
switch (id.FBFormat()) {
case GE_FORMAT_565:
return &DrawSinglePixel<true, GE_FORMAT_565>;
case GE_FORMAT_5551:
@ -471,7 +471,7 @@ SingleFunc GetSingleFunc(const PixelFuncID &id) {
return &DrawSinglePixel<true, GE_FORMAT_8888>;
}
}
switch (id.fbFormat) {
switch (id.FBFormat()) {
case GE_FORMAT_565:
return &DrawSinglePixel<false, GE_FORMAT_565>;
case GE_FORMAT_5551:

View file

@ -19,6 +19,9 @@
#include "GPU/Software/FuncId.h"
#include "GPU/GPUState.h"
static_assert(sizeof(SamplerID) == sizeof(SamplerID::fullKey), "Bad sampler ID size");
static_assert(sizeof(PixelFuncID) == sizeof(PixelFuncID::fullKey), "Bad pixel func ID size");
void ComputePixelFuncID(PixelFuncID *id) {
id->fullKey = 0;
@ -32,9 +35,9 @@ void ComputePixelFuncID(PixelFuncID *id) {
id->clearMode = gstate.isModeClear();
if (id->clearMode) {
id->colorClear = gstate.isClearModeColorMask();
id->stencilClear = gstate.isClearModeAlphaMask();
id->depthClear = gstate.isClearModeDepthMask();
id->colorTest = gstate.isClearModeColorMask();
id->stencilTest = gstate.isClearModeAlphaMask();
id->depthWrite = gstate.isClearModeDepthMask();
} else {
id->colorTest = gstate.isColorTestEnabled() && gstate.getColorTestFunction() != GE_COMP_ALWAYS;
if (gstate.isStencilTestEnabled() && gstate.getStencilTestFunction() == GE_COMP_ALWAYS) {
@ -60,7 +63,7 @@ void ComputePixelFuncID(PixelFuncID *id) {
id->depthTestFunc = gstate.isDepthTestEnabled() ? gstate.getDepthTestFunction() : GE_COMP_ALWAYS;
id->alphaTestFunc = gstate.isAlphaTestEnabled() ? gstate.getAlphaTestFunction() : GE_COMP_ALWAYS;
if (id->alphaTestFunc != GE_COMP_ALWAYS) {
if (id->AlphaTestFunc() != GE_COMP_ALWAYS) {
id->alphaTestRef = gstate.getAlphaTestRef() & gstate.getAlphaTestMask();
id->hasAlphaTestMask = gstate.getAlphaTestMask() != 0xFF;
}
@ -88,11 +91,11 @@ std::string DescribePixelFuncID(const PixelFuncID &id) {
std::string desc;
if (id.clearMode) {
desc = "Clear";
if (id.colorClear)
if (id.ColorClear())
desc += "C";
if (id.stencilClear)
if (id.StencilClear())
desc += "S";
if (id.depthClear)
if (id.DepthClear())
desc += "D";
desc += ":";
}
@ -105,15 +108,15 @@ std::string DescribePixelFuncID(const PixelFuncID &id) {
if (id.applyColorWriteMask)
desc += "Msk:";
switch (id.fbFormat) {
switch (id.FBFormat()) {
case GE_FORMAT_565: desc += "5650:"; break;
case GE_FORMAT_5551: desc += "5551:"; break;
case GE_FORMAT_4444: desc += "4444:"; break;
case GE_FORMAT_8888: desc += "8888:"; break;
}
if (id.alphaTestFunc != GE_COMP_ALWAYS) {
switch (GEComparison(id.alphaTestFunc)) {
if (id.AlphaTestFunc() != GE_COMP_ALWAYS) {
switch (id.AlphaTestFunc()) {
case GE_COMP_NEVER: desc += "ANever"; break;
case GE_COMP_ALWAYS: break;
case GE_COMP_EQUAL: desc += "AEQ"; break;
@ -128,8 +131,8 @@ std::string DescribePixelFuncID(const PixelFuncID &id) {
desc += StringFromFormat("%02X:", id.alphaTestRef);
}
if (id.depthTestFunc != GE_COMP_ALWAYS) {
switch (GEComparison(id.depthTestFunc)) {
if (id.DepthTestFunc() != GE_COMP_ALWAYS) {
switch (id.DepthTestFunc()) {
case GE_COMP_NEVER: desc += "ZNever:"; break;
case GE_COMP_ALWAYS: break;
case GE_COMP_EQUAL: desc += "ZEQ:"; break;
@ -147,7 +150,7 @@ std::string DescribePixelFuncID(const PixelFuncID &id) {
desc += "CTest:";
if (id.stencilTest && !id.clearMode) {
switch (GEComparison(id.stencilTestFunc)) {
switch (id.StencilTestFunc()) {
case GE_COMP_NEVER: desc += "SNever"; break;
case GE_COMP_ALWAYS: desc += "SAlways"; break;
case GE_COMP_EQUAL: desc += "SEQ"; break;
@ -162,7 +165,7 @@ std::string DescribePixelFuncID(const PixelFuncID &id) {
desc += StringFromFormat("%02X:", id.stencilTestRef);
}
switch (GEStencilOp(id.sFail)) {
switch (id.SFail()) {
case GE_STENCILOP_KEEP: break;
case GE_STENCILOP_ZERO: desc += "STstF0:"; break;
case GE_STENCILOP_REPLACE: desc += "STstFRpl:"; break;
@ -170,7 +173,7 @@ std::string DescribePixelFuncID(const PixelFuncID &id) {
case GE_STENCILOP_INCR: desc += "STstFInc:"; break;
case GE_STENCILOP_DECR: desc += "STstFDec:"; break;
}
switch (GEStencilOp(id.zFail)) {
switch (id.ZFail()) {
case GE_STENCILOP_KEEP: break;
case GE_STENCILOP_ZERO: desc += "ZTstF0:"; break;
case GE_STENCILOP_REPLACE: desc += "ZTstFRpl:"; break;
@ -178,7 +181,7 @@ std::string DescribePixelFuncID(const PixelFuncID &id) {
case GE_STENCILOP_INCR: desc += "ZTstFInc:"; break;
case GE_STENCILOP_DECR: desc += "ZTstFDec:"; break;
}
switch (GEStencilOp(id.zPass)) {
switch (id.ZPass()) {
case GE_STENCILOP_KEEP: break;
case GE_STENCILOP_ZERO: desc += "ZTstT0:"; break;
case GE_STENCILOP_REPLACE: desc += "ZTstTRpl:"; break;
@ -188,7 +191,7 @@ std::string DescribePixelFuncID(const PixelFuncID &id) {
}
if (id.alphaBlend) {
switch (GEBlendMode(id.alphaBlendEq)) {
switch (id.AlphaBlendEq()) {
case GE_BLENDMODE_MUL_AND_ADD: desc += "BlendAdd<"; break;
case GE_BLENDMODE_MUL_AND_SUBTRACT: desc += "BlendSub<"; break;
case GE_BLENDMODE_MUL_AND_SUBTRACT_REVERSE: desc += "BlendRSub<"; break;
@ -196,7 +199,7 @@ std::string DescribePixelFuncID(const PixelFuncID &id) {
case GE_BLENDMODE_MAX: desc += "BlendMax<"; break;
case GE_BLENDMODE_ABSDIFF: desc += "BlendDiff<"; break;
}
switch (GEBlendSrcFactor(id.alphaBlendSrc)) {
switch (id.AlphaBlendSrc()) {
case GE_SRCBLEND_DSTCOLOR: desc += "DstRGB,"; break;
case GE_SRCBLEND_INVDSTCOLOR: desc += "1-DstRGB,"; break;
case GE_SRCBLEND_SRCALPHA: desc += "SrcA,"; break;
@ -209,7 +212,7 @@ std::string DescribePixelFuncID(const PixelFuncID &id) {
case GE_SRCBLEND_DOUBLEINVDSTALPHA: desc += "1-2*DstA,"; break;
case GE_SRCBLEND_FIXA: desc += "Fix,"; break;
}
switch (GEBlendDstFactor(id.alphaBlendSrc)) {
switch (id.AlphaBlendDst()) {
case GE_DSTBLEND_SRCCOLOR: desc += "SrcRGB>:"; break;
case GE_DSTBLEND_INVSRCCOLOR: desc += "1-SrcRGB>:"; break;
case GE_DSTBLEND_SRCALPHA: desc += "SrcA>:"; break;

View file

@ -31,18 +31,12 @@ struct PixelFuncID {
uint64_t fullKey{};
struct {
bool clearMode : 1;
union {
bool colorTest : 1;
bool colorClear : 1;
};
union {
bool stencilTest : 1;
bool stencilClear : 1;
};
union {
bool depthWrite : 1;
bool depthClear : 1;
};
// Reused as ColorClear.
bool colorTest : 1;
// Reused as StencilClear.
bool stencilTest : 1;
// Reused as DepthClear.
bool depthWrite : 1;
bool applyDepthRange : 1;
// If alpha testing is disabled, set to GE_COMP_ALWAYS.
uint8_t alphaTestFunc : 3;
@ -77,6 +71,50 @@ struct PixelFuncID {
};
};
bool ColorClear() const {
return colorTest;
}
bool StencilClear() const {
return stencilTest;
}
bool DepthClear() const {
return depthWrite;
}
GEComparison AlphaTestFunc() const {
return GEComparison(alphaTestFunc);
}
GEComparison DepthTestFunc() const {
return GEComparison(depthTestFunc);
}
GEComparison StencilTestFunc() const {
return GEComparison(stencilTestFunc);
}
GEBufferFormat FBFormat() const {
return GEBufferFormat(fbFormat);
}
GEBlendMode AlphaBlendEq() const {
return GEBlendMode(alphaBlendEq);
}
GEBlendSrcFactor AlphaBlendSrc() const {
return GEBlendSrcFactor(alphaBlendSrc);
}
GEBlendDstFactor AlphaBlendDst() const {
return GEBlendDstFactor(alphaBlendDst);
}
GEStencilOp SFail() const {
return GEStencilOp(sFail);
}
GEStencilOp ZFail() const {
return GEStencilOp(zFail);
}
GEStencilOp ZPass() const {
return GEStencilOp(zPass);
}
bool operator == (const PixelFuncID &other) const {
return fullKey == other.fullKey;
}
@ -102,6 +140,14 @@ struct SamplerID {
};
};
GETextureFormat TexFmt() const {
return GETextureFormat(texfmt);
}
GEPaletteFormat ClutFmt() const {
return GEPaletteFormat(clutfmt);
}
bool operator == (const SamplerID &other) const {
return fullKey == other.fullKey;
}

View file

@ -467,10 +467,10 @@ static inline Vec3<int> GetDestFactor(GEBlendDstFactor factor, const Vec4<int> &
Vec3<int> AlphaBlendingResult(const PixelFuncID &pixelID, const Vec4<int> &source, const Vec4<int> &dst)
{
// Note: These factors cannot go below 0, but they can go above 255 when doubling.
Vec3<int> srcfactor = GetSourceFactor(GEBlendSrcFactor(pixelID.alphaBlendSrc), source, dst);
Vec3<int> dstfactor = GetDestFactor(GEBlendDstFactor(pixelID.alphaBlendDst), source, dst);
Vec3<int> srcfactor = GetSourceFactor(pixelID.AlphaBlendSrc(), source, dst);
Vec3<int> dstfactor = GetDestFactor(pixelID.AlphaBlendDst(), source, dst);
switch (GEBlendMode(pixelID.alphaBlendEq)) {
switch (pixelID.AlphaBlendEq()) {
case GE_BLENDMODE_MUL_AND_ADD:
{
#if defined(_M_SSE)

View file

@ -133,19 +133,19 @@ void DrawSprite(const VertexData& v0, const VertexData& v1) {
}
if (!pixelID.stencilTest &&
pixelID.depthTestFunc == GE_COMP_ALWAYS &&
pixelID.DepthTestFunc() == GE_COMP_ALWAYS &&
!pixelID.applyLogicOp &&
!pixelID.colorTest &&
!pixelID.dithering &&
// TODO: Safe?
pixelID.alphaTestFunc != GE_COMP_ALWAYS &&
pixelID.AlphaTestFunc() != GE_COMP_ALWAYS &&
pixelID.alphaTestRef == 0 &&
!pixelID.hasAlphaTestMask &&
pixelID.alphaBlend &&
gstate.isTextureAlphaUsed() &&
gstate.getTextureFunction() == GE_TEXFUNC_MODULATE &&
!pixelID.applyColorWriteMask &&
pixelID.fbFormat == GE_FORMAT_5551) {
pixelID.FBFormat() == GE_FORMAT_5551) {
if (isWhite) {
ParallelRangeLoop(&g_threadManager, [=](int y1, int y2) {
int t = t_start + (y1 - pos0.y) * dt;
@ -206,19 +206,19 @@ void DrawSprite(const VertexData& v0, const VertexData& v1) {
if (pos0.x < scissorTL.x) pos0.x = scissorTL.x;
if (pos0.y < scissorTL.y) pos0.y = scissorTL.y;
if (!pixelID.stencilTest &&
pixelID.depthTestFunc == GE_COMP_ALWAYS &&
pixelID.DepthTestFunc() == GE_COMP_ALWAYS &&
!pixelID.applyLogicOp &&
!pixelID.colorTest &&
!pixelID.dithering &&
// TODO: Safe?
pixelID.alphaTestFunc != GE_COMP_ALWAYS &&
pixelID.AlphaTestFunc() != GE_COMP_ALWAYS &&
pixelID.alphaTestRef == 0 &&
!pixelID.hasAlphaTestMask &&
pixelID.alphaBlend &&
gstate.isTextureAlphaUsed() &&
gstate.getTextureFunction() == GE_TEXFUNC_MODULATE &&
!pixelID.applyColorWriteMask &&
pixelID.fbFormat == GE_FORMAT_5551) {
pixelID.FBFormat() == GE_FORMAT_5551) {
if (v1.color0.a() == 0)
return;

View file

@ -133,7 +133,7 @@ void SamplerJitCache::ComputeSamplerID(SamplerID *id_out, bool linear) {
std::string SamplerJitCache::DescribeSamplerID(const SamplerID &id) {
std::string name;
switch ((GETextureFormat)id.texfmt) {
switch (id.TexFmt()) {
case GE_TFMT_5650: name = "5650"; break;
case GE_TFMT_5551: name = "5551"; break;
case GE_TFMT_4444: name = "4444"; break;
@ -146,9 +146,9 @@ std::string SamplerJitCache::DescribeSamplerID(const SamplerID &id) {
case GE_TFMT_DXT3: name = "DXT3"; break;
case GE_TFMT_DXT5: name = "DXT5"; break;
}
switch ((GEPaletteFormat)id.clutfmt) {
switch (id.ClutFmt()) {
case GE_CMODE_16BIT_BGR5650:
switch ((GETextureFormat)id.texfmt) {
switch (id.TexFmt()) {
case GE_TFMT_CLUT4:
case GE_TFMT_CLUT8:
case GE_TFMT_CLUT16:

View file

@ -285,7 +285,7 @@ LinearFunc SamplerJitCache::CompileLinear(const SamplerID &id) {
}
bool SamplerJitCache::Jit_ReadTextureFormat(const SamplerID &id) {
GETextureFormat fmt = (GETextureFormat)id.texfmt;
GETextureFormat fmt = id.TexFmt();
bool success = true;
switch (fmt) {
case GE_TFMT_5650:
@ -547,7 +547,7 @@ bool SamplerJitCache::Jit_GetDXT1Color(const SamplerID &id, int blockSize, int a
}
bool SamplerJitCache::Jit_ApplyDXTAlpha(const SamplerID &id) {
GETextureFormat fmt = (GETextureFormat)id.texfmt;
GETextureFormat fmt = id.TexFmt();
if (fmt == GE_TFMT_DXT3) {
MOVZX(32, 16, tempReg1, MComplex(srcReg, vReg, SCALE_2, 8));
LEA(32, RCX, MScaled(uReg, SCALE_4, 0));
@ -891,7 +891,7 @@ bool SamplerJitCache::Jit_Decode4444() {
}
bool SamplerJitCache::Jit_TransformClutIndex(const SamplerID &id, int bitsPerIndex) {
GEPaletteFormat fmt = (GEPaletteFormat)id.clutfmt;
GEPaletteFormat fmt = id.ClutFmt();
if (!id.hasClutShift && !id.hasClutMask && !id.hasClutOffset) {
// This is simple - just mask if necessary.
if (bitsPerIndex > 8) {
@ -967,7 +967,7 @@ bool SamplerJitCache::Jit_ReadClutColor(const SamplerID &id) {
MOV(PTRBITS, R(tempReg1), ImmPtr(clut));
switch ((GEPaletteFormat)id.clutfmt) {
switch (id.ClutFmt()) {
case GE_CMODE_16BIT_BGR5650:
MOVZX(32, 16, resultReg, MComplex(tempReg1, resultReg, SCALE_2, 0));
return Jit_Decode5650();