diff --git a/src/polyrenderer/drawers/screen_triangle.cpp b/src/polyrenderer/drawers/screen_triangle.cpp index e914551c5..561975626 100644 --- a/src/polyrenderer/drawers/screen_triangle.cpp +++ b/src/polyrenderer/drawers/screen_triangle.cpp @@ -54,6 +54,8 @@ static void SortVertices(const TriDrawTriangleArgs *args, ShadedTriVertex **sort void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread) { + using namespace TriScreenDrawerModes; + // Sort vertices by Y position ShadedTriVertex *sortedVertices[3]; SortVertices(args, sortedVertices); @@ -75,8 +77,7 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat // Find start/end X positions for each line covered by the triangle: - int leftEdge[MAXHEIGHT]; - int rightEdge[MAXHEIGHT]; + int16_t edges[MAXHEIGHT * 2]; float longDX = sortedVertices[2]->x - sortedVertices[0]->x; float longDY = sortedVertices[2]->y - sortedVertices[0]->y; @@ -98,8 +99,8 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat x0 = clamp(x0, 0, clipright); x1 = clamp(x1, 0, clipright); - leftEdge[y] = x0; - rightEdge[y] = x1; + edges[y << 1] = x0; + edges[(y << 1) + 1] = x1; shortPos += shortStep; longPos += longStep; @@ -121,64 +122,96 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat x0 = clamp(x0, 0, clipright); x1 = clamp(x1, 0, clipright); - leftEdge[y] = x0; - rightEdge[y] = x1; + edges[y << 1] = x0; + edges[(y << 1) + 1] = x1; shortPos += shortStep; longPos += longStep; } } - // Draw the triangle: + int opt = 0; + if (args->uniforms->DepthTest()) opt |= SWTRI_DepthTest; + /*if (args->uniforms->StencilTest())*/ opt |= SWTRI_StencilTest; + if (args->uniforms->WriteColor()) opt |= SWTRI_WriteColor; + if (args->uniforms->WriteDepth()) opt |= SWTRI_WriteDepth; + if (args->uniforms->WriteStencil()) opt |= SWTRI_WriteStencil; + + TriangleDrawers[opt](args, thread, edges, topY, bottomY); +} - int bmode = (int)args->uniforms->BlendMode(); - auto drawfunc = args->destBgra ? ScreenTriangle::SpanDrawers32[bmode] : ScreenTriangle::SpanDrawers8[bmode]; +template +void DrawTriangle(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread, int16_t *edges, int topY, int bottomY) +{ + using namespace TriScreenDrawerModes; - float stepXW = args->gradientX.W; - float v1X = args->v1->x; - float v1Y = args->v1->y; - float v1W = args->v1->w; + void(*drawfunc)(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); + float stepXW, v1X, v1Y, v1W, posXW; + uint8_t stencilTestValue, stencilWriteValue; + float *zbufferLine; + uint8_t *stencilLine; - bool depthTest = args->uniforms->DepthTest(); - bool stencilTest = true; - bool writeColor = args->uniforms->WriteColor(); - bool writeStencil = args->uniforms->WriteStencil(); - bool writeDepth = args->uniforms->WriteDepth(); - uint8_t stencilTestValue = args->uniforms->StencilTestValue(); - uint8_t stencilWriteValue = args->uniforms->StencilWriteValue(); + if (OptT::Flags & SWTRI_WriteColor) + { + int bmode = (int)args->uniforms->BlendMode(); + drawfunc = args->destBgra ? ScreenTriangle::SpanDrawers32[bmode] : ScreenTriangle::SpanDrawers8[bmode]; + } + + if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth)) + { + stepXW = args->gradientX.W; + v1X = args->v1->x; + v1Y = args->v1->y; + v1W = args->v1->w; + } + + if (OptT::Flags & SWTRI_StencilTest) + stencilTestValue = args->uniforms->StencilTestValue(); + + if (OptT::Flags & SWTRI_WriteStencil) + stencilWriteValue = args->uniforms->StencilWriteValue(); int num_cores = thread->num_cores; for (int y = topY + thread->skipped_by_thread(topY); y < bottomY; y += num_cores) { - int x = leftEdge[y]; - int xend = rightEdge[y]; + int x = edges[y << 1]; + int xend = edges[(y << 1) + 1]; - float *zbufferLine = args->zbuffer + args->stencilpitch * y; - uint8_t *stencilLine = args->stencilbuffer + args->stencilpitch * y; + if ((OptT::Flags & SWTRI_StencilTest) || (OptT::Flags & SWTRI_WriteStencil)) + stencilLine = args->stencilbuffer + args->stencilpitch * y; - float startX = x + (0.5f - v1X); - float startY = y + (0.5f - v1Y); - float posXW = v1W + stepXW * startX + args->gradientY.W * startY + args->depthOffset; + if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth)) + { + zbufferLine = args->zbuffer + args->stencilpitch * y; + + float startX = x + (0.5f - v1X); + float startY = y + (0.5f - v1Y); + posXW = v1W + stepXW * startX + args->gradientY.W * startY + args->depthOffset; + } #ifndef NO_SSE - __m128 mstepXW = _mm_set1_ps(stepXW * 4.0f); - __m128 mfirstStepXW = _mm_setr_ps(0.0f, stepXW, stepXW + stepXW, stepXW + stepXW + stepXW); + __m128 mstepXW, mfirstStepXW; + if ((OptT::Flags & SWTRI_DepthTest) || (OptT::Flags & SWTRI_WriteDepth)) + { + mstepXW = _mm_set1_ps(stepXW * 4.0f); + mfirstStepXW = _mm_setr_ps(0.0f, stepXW, stepXW + stepXW, stepXW + stepXW + stepXW); + } while (x < xend) { int xstart = x; - if (depthTest && stencilTest) + if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) { int xendsse = x + ((xend - x) / 4); __m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW); - while (_mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 15 && + while (x < xendsse && + _mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 15 && stencilLine[x] == stencilTestValue && stencilLine[x + 1] == stencilTestValue && stencilLine[x + 2] == stencilTestValue && - stencilLine[x + 3] == stencilTestValue && - x < xendsse) + stencilLine[x + 3] == stencilTestValue) { - if (writeDepth) + if (OptT::Flags & SWTRI_WriteDepth) _mm_storeu_ps(zbufferLine + x, mposXW); mposXW = _mm_add_ps(mposXW, mstepXW); x += 4; @@ -187,19 +220,19 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat while (zbufferLine[x] <= posXW && stencilLine[x] == stencilTestValue && x < xend) { - if (writeDepth) + if (OptT::Flags & SWTRI_WriteDepth) zbufferLine[x] = posXW; posXW += stepXW; x++; } } - else if (depthTest) + else if (OptT::Flags & SWTRI_DepthTest) { int xendsse = x + ((xend - x) / 4); __m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW); - while (_mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 15 && x < xendsse) + while (x < xendsse && _mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 15) { - if (writeDepth) + if (OptT::Flags & SWTRI_WriteDepth) _mm_storeu_ps(zbufferLine + x, mposXW); mposXW = _mm_add_ps(mposXW, mstepXW); x += 4; @@ -208,14 +241,20 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat while (zbufferLine[x] <= posXW && x < xend) { - if (writeDepth) + if (OptT::Flags & SWTRI_WriteDepth) zbufferLine[x] = posXW; posXW += stepXW; x++; } } - else if (stencilTest) + else if (OptT::Flags & SWTRI_StencilTest) { + int xendsse = x + ((xend - x) / 16); + while (x < xendsse && _mm_movemask_epi8(_mm_cmpeq_epi8(_mm_loadu_si128((const __m128i*)&stencilLine[x]), _mm_set1_epi8(stencilTestValue))) == 0xffff) + { + x += 16; + } + while (stencilLine[x] == stencilTestValue && x < xend) x++; } @@ -226,16 +265,24 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat if (x > xstart) { - if (writeColor) + if (OptT::Flags & SWTRI_WriteColor) drawfunc(y, xstart, x, args, thread); - if (writeStencil) + if (OptT::Flags & SWTRI_WriteStencil) { - for (int i = xstart; i < x; i++) - stencilLine[i] = stencilWriteValue; + int i = xstart; + int xendsse = xstart + ((x - xstart) / 16); + while (i < xendsse) + { + _mm_storeu_si128((__m128i*)&stencilLine[i], _mm_set1_epi8(stencilWriteValue)); + i += 16; + } + + while (i < x) + stencilLine[i++] = stencilWriteValue; } - if (!depthTest && writeDepth) + if (!(OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_WriteDepth)) { for (int i = xstart; i < x; i++) { @@ -245,16 +292,16 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat } } - if (depthTest && stencilTest) + if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) { int xendsse = x + ((xend - x) / 4); __m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW); - while ((_mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 0 || + while (x < xendsse && + (_mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 0 || stencilLine[x] != stencilTestValue || stencilLine[x + 1] != stencilTestValue || stencilLine[x + 2] != stencilTestValue || - stencilLine[x + 3] != stencilTestValue) && - x < xendsse) + stencilLine[x + 3] != stencilTestValue)) { mposXW = _mm_add_ps(mposXW, mstepXW); x += 4; @@ -267,11 +314,11 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat x++; } } - else if (depthTest) + else if (OptT::Flags & SWTRI_DepthTest) { int xendsse = x + ((xend - x) / 4); __m128 mposXW = _mm_add_ps(_mm_set1_ps(posXW), mfirstStepXW); - while (_mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 0 && x < xendsse) + while (x < xendsse && _mm_movemask_ps(_mm_cmple_ps(_mm_loadu_ps(zbufferLine + x), mposXW)) == 0) { mposXW = _mm_add_ps(mposXW, mstepXW); x += 4; @@ -284,11 +331,16 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat x++; } } - else if (stencilTest) + else if (OptT::Flags & SWTRI_StencilTest) { + int xendsse = x + ((xend - x) / 16); + while (x < xendsse && _mm_movemask_epi8(_mm_cmpeq_epi8(_mm_loadu_si128((const __m128i*)&stencilLine[x]), _mm_set1_epi8(stencilTestValue))) == 0) + { + x += 16; + } + while (stencilLine[x] != stencilTestValue && x < xend) { - posXW += stepXW; x++; } } @@ -298,27 +350,27 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat { int xstart = x; - if (depthTest && stencilTest) + if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) { while (zbufferLine[x] <= posXW && stencilLine[x] == stencilTestValue && x < xend) { - if (writeDepth) + if (OptT::Flags & SWTRI_WriteDepth) zbufferLine[x] = posXW; posXW += stepXW; x++; } } - else if (depthTest) + else if (OptT::Flags & SWTRI_DepthTest) { while (zbufferLine[x] <= posXW && x < xend) { - if (writeDepth) + if (OptT::Flags & SWTRI_WriteDepth) zbufferLine[x] = posXW; posXW += stepXW; x++; } } - else if (stencilTest) + else if (OptT::Flags & SWTRI_StencilTest) { while (stencilLine[x] == stencilTestValue && x < xend) x++; @@ -330,16 +382,16 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat if (x > xstart) { - if (writeColor) + if (OptT::Flags & SWTRI_WriteColor) drawfunc(y, xstart, x, args, thread); - if (writeStencil) + if (OptT::Flags & SWTRI_WriteStencil) { for (int i = xstart; i < x; i++) stencilLine[i] = stencilWriteValue; } - if (!depthTest && writeDepth) + if (!(OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_WriteDepth)) { for (int i = xstart; i < x; i++) { @@ -349,7 +401,7 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat } } - if (depthTest && stencilTest) + if ((OptT::Flags & SWTRI_DepthTest) && (OptT::Flags & SWTRI_StencilTest)) { while ((zbufferLine[x] > posXW || stencilLine[x] != stencilTestValue) && x < xend) { @@ -357,7 +409,7 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat x++; } } - else if (depthTest) + else if (OptT::Flags & SWTRI_DepthTest) { while (zbufferLine[x] > posXW && x < xend) { @@ -365,11 +417,10 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat x++; } } - else if (stencilTest) + else if (OptT::Flags & SWTRI_StencilTest) { while (stencilLine[x] != stencilTestValue && x < xend) { - posXW += stepXW; x++; } } @@ -2164,4 +2215,40 @@ void(*ScreenTriangle::RectDrawers32[])(const void *, int, int, int, const RectDr &DrawRect32 }; +void(*ScreenTriangle::TriangleDrawers[])(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread, int16_t *edges, int topY, int bottomY) = +{ + nullptr, + nullptr, + nullptr, + nullptr, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle, + &DrawTriangle +}; + int ScreenTriangle::FuzzStart = 0; diff --git a/src/polyrenderer/drawers/screen_triangle.h b/src/polyrenderer/drawers/screen_triangle.h index dc8809b0d..80fd24ce7 100644 --- a/src/polyrenderer/drawers/screen_triangle.h +++ b/src/polyrenderer/drawers/screen_triangle.h @@ -142,6 +142,8 @@ class ScreenTriangle public: static void Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); + static void(*TriangleDrawers[])(const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread, int16_t *edges, int topY, int bottomY); + static void(*SpanDrawers8[])(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); static void(*SpanDrawers32[])(int y, int x0, int x1, const TriDrawTriangleArgs *args, PolyTriangleThreadData *thread); static void(*RectDrawers8[])(const void *, int, int, int, const RectDrawArgs *, PolyTriangleThreadData *); @@ -216,4 +218,42 @@ namespace TriScreenDrawerModes 11, 6, 6, 11, 15, 6, 6, 11, 15, 18, 21, 6, 6, 6, 6, 11, 6, 6, 11, 6, }; + + enum SWTriangleFlags + { + SWTRI_DepthTest = 1, + SWTRI_StencilTest = 2, + SWTRI_WriteColor = 4, + SWTRI_WriteDepth = 8, + SWTRI_WriteStencil = 16 + }; + + struct TriangleOpt4 { static const int Flags = 4; }; + struct TriangleOpt5 { static const int Flags = 5; }; + struct TriangleOpt6 { static const int Flags = 6; }; + struct TriangleOpt7 { static const int Flags = 7; }; + struct TriangleOpt8 { static const int Flags = 8; }; + struct TriangleOpt9 { static const int Flags = 9; }; + struct TriangleOpt10 { static const int Flags = 10; }; + struct TriangleOpt11 { static const int Flags = 11; }; + struct TriangleOpt12 { static const int Flags = 12; }; + struct TriangleOpt13 { static const int Flags = 13; }; + struct TriangleOpt14 { static const int Flags = 14; }; + struct TriangleOpt15 { static const int Flags = 15; }; + struct TriangleOpt16 { static const int Flags = 16; }; + struct TriangleOpt17 { static const int Flags = 17; }; + struct TriangleOpt18 { static const int Flags = 18; }; + struct TriangleOpt19 { static const int Flags = 19; }; + struct TriangleOpt20 { static const int Flags = 20; }; + struct TriangleOpt21 { static const int Flags = 21; }; + struct TriangleOpt22 { static const int Flags = 22; }; + struct TriangleOpt23 { static const int Flags = 23; }; + struct TriangleOpt24 { static const int Flags = 24; }; + struct TriangleOpt25 { static const int Flags = 25; }; + struct TriangleOpt26 { static const int Flags = 26; }; + struct TriangleOpt27 { static const int Flags = 27; }; + struct TriangleOpt28 { static const int Flags = 28; }; + struct TriangleOpt29 { static const int Flags = 29; }; + struct TriangleOpt30 { static const int Flags = 30; }; + struct TriangleOpt31 { static const int Flags = 31; }; }