Select blend function once per triangle

This commit is contained in:
Magnus Norddahl 2019-12-08 14:42:20 +01:00
parent 73c62c5404
commit f7ae955e6a
2 changed files with 62 additions and 36 deletions

View File

@ -272,6 +272,8 @@ public:
uint8_t StencilTestValue = 0; uint8_t StencilTestValue = 0;
uint8_t StencilWriteValue = 0; uint8_t StencilWriteValue = 0;
void (*WriteColorFunc)(int y, int x0, int x1, PolyTriangleThreadData* thread) = nullptr;
private: private:
ShadedTriVertex ShadeVertex(int index); ShadedTriVertex ShadeVertex(int index);
void DrawShadedPoint(const ShadedTriVertex *const* vertex); void DrawShadedPoint(const ShadedTriVertex *const* vertex);

View File

@ -596,20 +596,22 @@ static void BlendColor(int y, int x0, int x1, PolyTriangleThreadData* thread)
} }
#endif #endif
static void WriteColor(int y, int x0, int x1, PolyTriangleThreadData* thread) #ifdef NO_SSE
{ static void BlendColorOpaque(int y, int x0, int x1, PolyTriangleThreadData* thread)
using namespace TriScreenDrawerModes;
FRenderStyle style = thread->RenderStyle;
if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero)
{ {
uint32_t* dest = (uint32_t*)thread->dest; uint32_t* dest = (uint32_t*)thread->dest;
uint32_t* line = dest + y * (ptrdiff_t)thread->dest_pitch; uint32_t* line = dest + y * (ptrdiff_t)thread->dest_pitch;
uint32_t* fragcolor = thread->scanline.FragColor; uint32_t* fragcolor = thread->scanline.FragColor;
if (!thread->AlphaTest) memcpy(line + x0, fragcolor + x0, (x1 - x0) * sizeof(uint32_t));
}
#else
static void BlendColorOpaque(int y, int x0, int x1, PolyTriangleThreadData* thread)
{ {
#if !defined(NO_SSE) uint32_t* dest = (uint32_t*)thread->dest;
uint32_t* line = dest + y * (ptrdiff_t)thread->dest_pitch;
uint32_t* fragcolor = thread->scanline.FragColor;
int ssecount = ((x1 - x0) & ~3); int ssecount = ((x1 - x0) & ~3);
int sseend = x0 + ssecount; int sseend = x0 + ssecount;
@ -623,12 +625,14 @@ static void WriteColor(int y, int x0, int x1, PolyTriangleThreadData* thread)
{ {
line[x] = fragcolor[x]; line[x] = fragcolor[x];
} }
#else
memcpy(line + x0, fragcolor + x0, (x1 - x0) * sizeof(uint32_t));
#endif
} }
else #endif
static void BlendColorOpaqueAlphaTest(int y, int x0, int x1, PolyTriangleThreadData* thread)
{ {
uint32_t* dest = (uint32_t*)thread->dest;
uint32_t* line = dest + y * (ptrdiff_t)thread->dest_pitch;
uint32_t* fragcolor = thread->scanline.FragColor;
uint8_t* discard = thread->scanline.discard; uint8_t* discard = thread->scanline.discard;
for (int x = x0; x < x1; x++) for (int x = x0; x < x1; x++)
{ {
@ -636,17 +640,34 @@ static void WriteColor(int y, int x0, int x1, PolyTriangleThreadData* thread)
line[x] = fragcolor[x]; line[x] = fragcolor[x];
} }
} }
static void SelectWriteColorFunc(PolyTriangleThreadData* thread)
{
void(*writecolorfunc)(int y, int x0, int x1, PolyTriangleThreadData * thread);
FRenderStyle style = thread->RenderStyle;
if (style.BlendOp == STYLEOP_Add && style.SrcAlpha == STYLEALPHA_One && style.DestAlpha == STYLEALPHA_Zero)
{
if (!thread->AlphaTest)
{
writecolorfunc = &BlendColorOpaque;
} }
else else
{ {
writecolorfunc = &BlendColorOpaqueAlphaTest;
}
}
else
{
using namespace TriScreenDrawerModes;
if (!thread->AlphaTest) if (!thread->AlphaTest)
{ {
switch (style.BlendOp) switch (style.BlendOp)
{ {
default: default:
case STYLEOP_Add: BlendColor<BlendColorOpt_Add>(y, x0, x1, thread); break; case STYLEOP_Add: writecolorfunc = &BlendColor<BlendColorOpt_Add>; break;
case STYLEOP_Sub: BlendColor<BlendColorOpt_Sub>(y, x0, x1, thread); break; case STYLEOP_Sub: writecolorfunc = &BlendColor<BlendColorOpt_Sub>; break;
case STYLEOP_RevSub: BlendColor<BlendColorOpt_RevSub>(y, x0, x1, thread); break; case STYLEOP_RevSub: writecolorfunc = &BlendColor<BlendColorOpt_RevSub>; break;
} }
} }
else else
@ -654,12 +675,13 @@ static void WriteColor(int y, int x0, int x1, PolyTriangleThreadData* thread)
switch (style.BlendOp) switch (style.BlendOp)
{ {
default: default:
case STYLEOP_Add: BlendColor<BlendColorOpt_AlphaTest_Add>(y, x0, x1, thread); break; case STYLEOP_Add: writecolorfunc = BlendColor<BlendColorOpt_AlphaTest_Add>; break;
case STYLEOP_Sub: BlendColor<BlendColorOpt_AlphaTest_Sub>(y, x0, x1, thread); break; case STYLEOP_Sub: writecolorfunc = BlendColor<BlendColorOpt_AlphaTest_Sub>; break;
case STYLEOP_RevSub: BlendColor<BlendColorOpt_AlphaTest_RevSub>(y, x0, x1, thread); break; case STYLEOP_RevSub: writecolorfunc = BlendColor<BlendColorOpt_AlphaTest_RevSub>; break;
} }
} }
} }
thread->WriteColorFunc = writecolorfunc;
} }
static void WriteDepth(int y, int x0, int x1, PolyTriangleThreadData* thread) static void WriteDepth(int y, int x0, int x1, PolyTriangleThreadData* thread)
@ -1210,7 +1232,7 @@ static void DrawSpan(int y, int x0, int x1, const TriDrawTriangleArgs* args, Pol
RunShader(x0, x1, thread); RunShader(x0, x1, thread);
if (thread->WriteColor) if (thread->WriteColor)
WriteColor(y, x0, x1, thread); thread->WriteColorFunc(y, x0, x1, thread);
if (thread->WriteDepth) if (thread->WriteDepth)
WriteDepth(y, x0, x1, thread); WriteDepth(y, x0, x1, thread);
if (thread->WriteStencil) if (thread->WriteStencil)
@ -1340,6 +1362,8 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs* args, PolyTriangleThreadDat
if (topY >= bottomY) if (topY >= bottomY)
return; return;
SelectWriteColorFunc(thread);
void(*testfunc)(int y, int x0, int x1, const TriDrawTriangleArgs * args, PolyTriangleThreadData * thread); void(*testfunc)(int y, int x0, int x1, const TriDrawTriangleArgs * args, PolyTriangleThreadData * thread);
int opt = 0; int opt = 0;