Skip to content

Commit 81608b0

Browse files
authored
Merge pull request #17214 from unknownbrackets/softgpu-alpha
softgpu: Fix over-optimization of alpha test
2 parents a6bf499 + a88b8a1 commit 81608b0

3 files changed

Lines changed: 33 additions & 21 deletions

File tree

GPU/Software/RasterizerRectangle.cpp

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ template <GEBufferFormat fmt, bool alphaBlend>
101101
static inline void DrawSinglePixel(u16 *pixel, const u32 color_in) {
102102
u32 new_color;
103103
// Because of this check, we only support src.a / 1-src.a blending.
104-
// We take advantage of short circuiting by checking the constant (template) value first.
105104
if (!alphaBlend || (color_in >> 24) == 255) {
106105
new_color = color_in & 0xFFFFFF;
107106
} else {
@@ -142,7 +141,7 @@ template <bool alphaBlend>
142141
static inline void DrawSinglePixel32(u32 *pixel, const u32 color_in) {
143142
u32 new_color;
144143
// Because of this check, we only support src.a / 1-src.a blending.
145-
if ((color_in >> 24) == 255 || !alphaBlend) {
144+
if (!alphaBlend || (color_in >> 24) == 255) {
146145
new_color = color_in & 0xFFFFFF;
147146
} else {
148147
const u32 old_color = *pixel;
@@ -231,7 +230,7 @@ static inline Vec4IntResult SOFTRAST_CALL ModulateRGBA(Vec4IntArg prim_in, Vec4I
231230
return ToVec4IntResult(out);
232231
}
233232

234-
template <GEBufferFormat fmt, bool isWhite, bool alphaBlend>
233+
template <GEBufferFormat fmt, bool isWhite, bool alphaBlend, bool alphaTestZero>
235234
static void DrawSpriteTex(const DrawingCoords &pos0, const DrawingCoords &pos1, int s_start, int t_start, int ds, int dt, u32 color0, const RasterizerState &state, Sampler::FetchFunc fetchFunc) {
236235
const u8 *texptr = state.texptr[0];
237236
uint16_t texbufw = state.texbufw[0];
@@ -245,7 +244,7 @@ static void DrawSpriteTex(const DrawingCoords &pos0, const DrawingCoords &pos1,
245244
for (int x = pos0.x; x < pos1.x; x++) {
246245
Vec4<int> tex_color = fetchFunc(s, t, texptr, texbufw, 0, state.samplerID);
247246
if (isWhite) {
248-
if (!alphaBlend || tex_color.a() != 0) {
247+
if (!alphaTestZero || tex_color.a() != 0) {
249248
u32 tex_color32 = tex_color.ToRGBA();
250249
if (fmt == GE_FORMAT_8888)
251250
DrawSinglePixel32<alphaBlend>(pixel32, tex_color32);
@@ -255,7 +254,7 @@ static void DrawSpriteTex(const DrawingCoords &pos0, const DrawingCoords &pos1,
255254
} else {
256255
Vec4<int> prim_color = c0;
257256
prim_color = Vec4<int>(ModulateRGBA(ToVec4IntArg(prim_color), ToVec4IntArg(tex_color), state.samplerID));
258-
if (!alphaBlend || prim_color.a() > 0) {
257+
if (!alphaTestZero || prim_color.a() > 0) {
259258
if (fmt == GE_FORMAT_8888)
260259
DrawSinglePixel32<alphaBlend>(pixel32, prim_color.ToRGBA());
261260
else
@@ -272,27 +271,38 @@ static void DrawSpriteTex(const DrawingCoords &pos0, const DrawingCoords &pos1,
272271
}
273272
}
274273

275-
template <bool isWhite, bool alphaBlend>
274+
template <bool isWhite, bool alphaBlend, bool alphaTestZero>
276275
static void DrawSpriteTex(const DrawingCoords &pos0, const DrawingCoords &pos1, int s_start, int t_start, int ds, int dt, u32 color0, const RasterizerState &state, Sampler::FetchFunc fetchFunc) {
277276
switch (state.pixelID.FBFormat()) {
278277
case GE_FORMAT_565:
279-
DrawSpriteTex<GE_FORMAT_565, isWhite, alphaBlend>(pos0, pos1, s_start, t_start, ds, dt, color0, state, fetchFunc);
278+
DrawSpriteTex<GE_FORMAT_565, isWhite, alphaBlend, alphaTestZero>(pos0, pos1, s_start, t_start, ds, dt, color0, state, fetchFunc);
280279
break;
281280
case GE_FORMAT_5551:
282-
DrawSpriteTex<GE_FORMAT_5551, isWhite, alphaBlend>(pos0, pos1, s_start, t_start, ds, dt, color0, state, fetchFunc);
281+
DrawSpriteTex<GE_FORMAT_5551, isWhite, alphaBlend, alphaTestZero>(pos0, pos1, s_start, t_start, ds, dt, color0, state, fetchFunc);
283282
break;
284283
case GE_FORMAT_4444:
285-
DrawSpriteTex<GE_FORMAT_4444, isWhite, alphaBlend>(pos0, pos1, s_start, t_start, ds, dt, color0, state, fetchFunc);
284+
DrawSpriteTex<GE_FORMAT_4444, isWhite, alphaBlend, alphaTestZero>(pos0, pos1, s_start, t_start, ds, dt, color0, state, fetchFunc);
286285
break;
287286
case GE_FORMAT_8888:
288-
DrawSpriteTex<GE_FORMAT_8888, isWhite, alphaBlend>(pos0, pos1, s_start, t_start, ds, dt, color0, state, fetchFunc);
287+
DrawSpriteTex<GE_FORMAT_8888, isWhite, alphaBlend, alphaTestZero>(pos0, pos1, s_start, t_start, ds, dt, color0, state, fetchFunc);
289288
break;
290289
default:
291290
// Invalid, don't draw anything...
292291
break;
293292
}
294293
}
295294

295+
template <bool isWhite>
296+
static inline void DrawSpriteTex(const DrawingCoords &pos0, const DrawingCoords &pos1, int s_start, int t_start, int ds, int dt, u32 color0, const RasterizerState &state, Sampler::FetchFunc fetchFunc) {
297+
// Standard alpha blending implies skipping alpha zero.
298+
if (state.pixelID.alphaBlend)
299+
DrawSpriteTex<isWhite, true, true>(pos0, pos1, s_start, t_start, ds, dt, color0, state, fetchFunc);
300+
else if (state.pixelID.AlphaTestFunc() != GE_COMP_ALWAYS)
301+
DrawSpriteTex<isWhite, false, true>(pos0, pos1, s_start, t_start, ds, dt, color0, state, fetchFunc);
302+
else
303+
DrawSpriteTex<isWhite, false, false>(pos0, pos1, s_start, t_start, ds, dt, color0, state, fetchFunc);
304+
}
305+
296306
template <GEBufferFormat fmt, bool alphaBlend>
297307
static void DrawSpriteNoTex(const DrawingCoords &pos0, const DrawingCoords &pos1, u32 color0, const RasterizerState &state) {
298308
if (alphaBlend && Vec4<int>::FromRGBA(color0).a() == 0)
@@ -393,15 +403,9 @@ void DrawSprite(const VertexData &v0, const VertexData &v1, const BinCoords &ran
393403

394404
if (UseDrawSinglePixel(pixelID) && (samplerID.TexFunc() == GE_TEXFUNC_MODULATE || samplerID.TexFunc() == GE_TEXFUNC_REPLACE) && samplerID.useTextureAlpha) {
395405
if (isWhite || samplerID.TexFunc() == GE_TEXFUNC_REPLACE) {
396-
if (pixelID.alphaBlend)
397-
DrawSpriteTex<true, true>(pos0, pos1, s_start, t_start, ds, dt, v1.color0, state, fetchFunc);
398-
else
399-
DrawSpriteTex<true, false>(pos0, pos1, s_start, t_start, ds, dt, v1.color0, state, fetchFunc);
406+
DrawSpriteTex<true>(pos0, pos1, s_start, t_start, ds, dt, v1.color0, state, fetchFunc);
400407
} else {
401-
if (pixelID.alphaBlend)
402-
DrawSpriteTex<false, true>(pos0, pos1, s_start, t_start, ds, dt, v1.color0, state, fetchFunc);
403-
else
404-
DrawSpriteTex<false, false>(pos0, pos1, s_start, t_start, ds, dt, v1.color0, state, fetchFunc);
408+
DrawSpriteTex<false>(pos0, pos1, s_start, t_start, ds, dt, v1.color0, state, fetchFunc);
405409
}
406410
} else {
407411
float dsf = ds * (1.0f / (float)(1 << state.samplerID.width0Shift));

headless/HeadlessHost.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,20 @@ void HeadlessHost::SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) {
4242
ScreenshotComparer comparer(pixels, FRAME_STRIDE, FRAME_WIDTH, FRAME_HEIGHT);
4343
double errors = comparer.Compare(comparisonScreenshot_);
4444
if (errors < 0)
45-
SendDebugOutput(comparer.GetError() + "\n");
45+
SendAndCollectOutput(comparer.GetError() + "\n");
4646

4747
if (errors > maxScreenshotError_)
48-
SendDebugOutput(StringFromFormat("Screenshot MSE: %f\n", errors));
48+
SendAndCollectOutput(StringFromFormat("Screenshot MSE: %f\n", errors));
4949

5050
if (errors > maxScreenshotError_ && writeFailureScreenshot_) {
5151
if (comparer.SaveActualBitmap(Path("__testfailure.bmp")))
52-
SendDebugOutput("Actual output written to: __testfailure.bmp\n");
52+
SendAndCollectOutput("Actual output written to: __testfailure.bmp\n");
5353
comparer.SaveVisualComparisonPNG(Path("__testcompare.png"));
5454
}
5555
}
56+
57+
void HeadlessHost::SendAndCollectOutput(const std::string &output) {
58+
SendDebugOutput(output);
59+
if (PSP_CoreParameter().collectDebugOutput)
60+
*PSP_CoreParameter().collectDebugOutput += output;
61+
}

headless/HeadlessHost.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ class HeadlessHost {
6262
virtual void SwapBuffers() {}
6363

6464
protected:
65+
void SendAndCollectOutput(const std::string &output);
66+
6567
Path comparisonScreenshot_;
6668
double maxScreenshotError_ = 0.0;
6769
std::string debugOutputBuffer_;

0 commit comments

Comments
 (0)