From e3495011bfdee7177c8211c2262183c516cecfbb Mon Sep 17 00:00:00 2001 From: RSDuck Date: Sat, 22 Apr 2023 01:00:30 +0200 Subject: [PATCH] take all edge cases into account for XMin/XMax calculation --- src/GPU3D_Compute.cpp | 117 ++++++++++++++---------------------- src/GPU3D_Compute.h | 4 +- src/GPU3D_Compute_shaders.h | 28 ++++++++- src/OpenGLSupport.cpp | 6 -- 4 files changed, 73 insertions(+), 82 deletions(-) diff --git a/src/GPU3D_Compute.cpp b/src/GPU3D_Compute.cpp index 1d1bd831..68d3af07 100644 --- a/src/GPU3D_Compute.cpp +++ b/src/GPU3D_Compute.cpp @@ -307,7 +307,7 @@ void ComputeRenderer::SetupAttrs(SpanSetupY* span, Polygon* poly, int from, int span->TexcoordV1 = poly->Vertices[to]->TexCoords[1]; } -void ComputeRenderer::SetupYSpanDummy(SpanSetupY* span, Polygon* poly, int vertex, int side, s32 positions[10][2]) +void ComputeRenderer::SetupYSpanDummy(RenderPolygon* rp, SpanSetupY* span, Polygon* poly, int vertex, int side, s32 positions[10][2]) { s32 x0 = positions[vertex][0]; if (side) @@ -325,6 +325,17 @@ void ComputeRenderer::SetupYSpanDummy(SpanSetupY* span, Polygon* poly, int verte span->XMax = x0; span->Y0 = span->Y1 = positions[vertex][1]; + if (span->XMin < rp->XMin) + { + rp->XMin = span->XMin; + rp->XMinY = span->Y0; + } + if (span->XMax > rp->XMax) + { + rp->XMax = span->XMax; + rp->XMaxY = span->Y0; + } + span->Increment = 0; span->I0 = span->I1 = span->IRecip = 0; @@ -337,7 +348,7 @@ void ComputeRenderer::SetupYSpanDummy(SpanSetupY* span, Polygon* poly, int verte SetupAttrs(span, poly, vertex, vertex); } -void ComputeRenderer::SetupYSpan(int polynum, SpanSetupY* span, Polygon* poly, int from, int to, u32 y, int side, s32 positions[10][2]) +void ComputeRenderer::SetupYSpan(RenderPolygon* rp, SpanSetupY* span, Polygon* poly, int from, int to, int side, s32 positions[10][2]) { span->X0 = positions[from][0]; span->X1 = positions[to][0]; @@ -346,23 +357,45 @@ void ComputeRenderer::SetupYSpan(int polynum, SpanSetupY* span, Polygon* poly, i SetupAttrs(span, poly, from, to); + s32 minXY, maxXY; bool negative = false; if (span->X1 > span->X0) { span->XMin = span->X0; span->XMax = span->X1-1; + + minXY = span->Y0; + maxXY = span->Y1; } else if (span->X1 < span->X0) { span->XMin = span->X1; span->XMax = span->X0-1; negative = true; + + minXY = span->Y1; + maxXY = span->Y0; } else { span->XMin = span->X0; if (side) span->XMin--; span->XMax = span->XMin; + + // doesn't matter for completely vertical slope + minXY = span->Y0; + maxXY = span->Y0; + } + + if (span->XMin < rp->XMin) + { + rp->XMin = span->XMin; + rp->XMinY = minXY; + } + if (span->XMax > rp->XMax) + { + rp->XMax = span->XMax; + rp->XMaxY = maxXY; } span->IsDummy = false; @@ -1072,18 +1105,15 @@ void ComputeRenderer::RenderFrame() s32 ytop = ScreenHeight, ybot = 0; for (int i = 0; i < polygon->NumVertices; i++) { - scaledPositions[i][0] = (polygon->Vertices[i]->HiresPosition[0] * ScaleFactor) >> 4; - scaledPositions[i][1] = (polygon->Vertices[i]->HiresPosition[1] * ScaleFactor) >> 4; + scaledPositions[i][0] = (polygon->Vertices[i]->FinalPosition[0] * ScaleFactor); + scaledPositions[i][1] = (polygon->Vertices[i]->FinalPosition[1] * ScaleFactor); ytop = std::min(scaledPositions[i][1], ytop); ybot = std::max(scaledPositions[i][1], ybot); } RenderPolygons[i].YTop = ytop; RenderPolygons[i].YBot = ybot; - - s32 minX = scaledPositions[vtop][0]; - s32 minXY = scaledPositions[vtop][1]; - s32 maxX = scaledPositions[vtop][0]; - s32 maxXY = scaledPositions[vtop][1]; + RenderPolygons[i].XMin = ScreenWidth; + RenderPolygons[i].XMax = 0; if (ybot == ytop) { @@ -1101,20 +1131,10 @@ void ComputeRenderer::RenderFrame() assert(numYSpans < MaxYSpanSetups); u32 curSpanL = numYSpans; - SetupYSpanDummy(&YSpanSetups[numYSpans++], polygon, vtop, 0, scaledPositions); + SetupYSpanDummy(&RenderPolygons[i], &YSpanSetups[numYSpans++], polygon, vtop, 0, scaledPositions); assert(numYSpans < MaxYSpanSetups); u32 curSpanR = numYSpans; - SetupYSpanDummy(&YSpanSetups[numYSpans++], polygon, vbot, 1, scaledPositions); - - minX = YSpanSetups[curSpanL].X0; - minXY = YSpanSetups[curSpanL].Y0; - maxX = YSpanSetups[curSpanR].X0; - maxXY = YSpanSetups[curSpanR].Y0; - if (maxX < minX) - { - std::swap(minX, maxX); - std::swap(minXY, maxXY); - } + SetupYSpanDummy(&RenderPolygons[i], &YSpanSetups[numYSpans++], polygon, vbot, 1, scaledPositions); YSpanIndices[numSetupIndices].PolyIdx = i; YSpanIndices[numSetupIndices].SpanIdxL = curSpanL; @@ -1126,10 +1146,10 @@ void ComputeRenderer::RenderFrame() { u32 curSpanL = numYSpans; assert(numYSpans < MaxYSpanSetups); - SetupYSpan(i, &YSpanSetups[numYSpans++], polygon, curVL, nextVL, ytop, 0, scaledPositions); + SetupYSpan(&RenderPolygons[i], &YSpanSetups[numYSpans++], polygon, curVL, nextVL, 0, scaledPositions); u32 curSpanR = numYSpans; assert(numYSpans < MaxYSpanSetups); - SetupYSpan(i, &YSpanSetups[numYSpans++], polygon, curVR, nextVR, ytop, 1, scaledPositions); + SetupYSpan(&RenderPolygons[i], &YSpanSetups[numYSpans++], polygon, curVR, nextVR, 1, scaledPositions); for (u32 y = ytop; y < ybot; y++) { @@ -1152,20 +1172,10 @@ void ComputeRenderer::RenderFrame() } } - if (scaledPositions[curVL][0] < minX) - { - minX = scaledPositions[curVL][0]; - minXY = scaledPositions[curVL][1]; - } - if (scaledPositions[curVL][0] > maxX) - { - maxX = scaledPositions[curVL][0]; - maxXY = scaledPositions[curVL][1]; - } assert(numYSpans < MaxYSpanSetups); curSpanL = numYSpans; - SetupYSpan(i,&YSpanSetups[numYSpans++], polygon, curVL, nextVL, y, 0, scaledPositions); + SetupYSpan(&RenderPolygons[i], &YSpanSetups[numYSpans++], polygon, curVL, nextVL, 0, scaledPositions); } if (y >= scaledPositions[nextVR][1] && curVR != polygon->VBottom) { @@ -1186,20 +1196,9 @@ void ComputeRenderer::RenderFrame() } } - if (scaledPositions[curVR][0] < minX) - { - minX = scaledPositions[curVR][0]; - minXY = scaledPositions[curVR][1]; - } - if (scaledPositions[curVR][0] > maxX) - { - maxX = scaledPositions[curVR][0]; - maxXY = scaledPositions[curVR][1]; - } - assert(numYSpans < MaxYSpanSetups); curSpanR = numYSpans; - SetupYSpan(i,&YSpanSetups[numYSpans++], polygon, curVR, nextVR, y, 1, scaledPositions); + SetupYSpan(&RenderPolygons[i] ,&YSpanSetups[numYSpans++], polygon, curVR, nextVR, 1, scaledPositions); } YSpanIndices[numSetupIndices].PolyIdx = i; @@ -1210,32 +1209,6 @@ void ComputeRenderer::RenderFrame() } } - if (scaledPositions[nextVL][0] < minX) - { - minX = scaledPositions[nextVL][0]; - minXY = scaledPositions[nextVL][1]; - } - if (scaledPositions[nextVL][0] > maxX) - { - maxX = scaledPositions[nextVL][0]; - maxXY = scaledPositions[nextVL][1]; - } - if (scaledPositions[nextVR][0] < minX) - { - minX = scaledPositions[nextVR][0]; - minXY = scaledPositions[nextVR][1]; - } - if (scaledPositions[nextVR][0] > maxX) - { - maxX = scaledPositions[nextVR][0]; - maxXY = scaledPositions[nextVR][1]; - } - - RenderPolygons[i].XMin = minX; - RenderPolygons[i].XMinY = minXY; - RenderPolygons[i].XMax = maxX; - RenderPolygons[i].XMaxY = maxXY; - //printf("polygon min max %d %d | %d %d\n", RenderPolygons[i].XMin, RenderPolygons[i].XMinY, RenderPolygons[i].XMax, RenderPolygons[i].XMaxY); } diff --git a/src/GPU3D_Compute.h b/src/GPU3D_Compute.h index fc1b7c00..721c7a61 100644 --- a/src/GPU3D_Compute.h +++ b/src/GPU3D_Compute.h @@ -230,8 +230,8 @@ private: void DeleteShaders(); void SetupAttrs(SpanSetupY* span, Polygon* poly, int from, int to); - void SetupYSpan(int polynum, SpanSetupY* span, Polygon* poly, int from, int to, u32 y, int side, s32 positions[10][2]); - void SetupYSpanDummy(SpanSetupY* span, Polygon* poly, int vertex, int side, s32 positions[10][2]); + void SetupYSpan(RenderPolygon* rp, SpanSetupY* span, Polygon* poly, int from, int to, int side, s32 positions[10][2]); + void SetupYSpanDummy(RenderPolygon* rp, SpanSetupY* span, Polygon* poly, int vertex, int side, s32 positions[10][2]); bool CompileShader(GLuint& shader, const char* source, const std::initializer_list& defines); }; diff --git a/src/GPU3D_Compute_shaders.h b/src/GPU3D_Compute_shaders.h index eaef76c9..6b63919a 100644 --- a/src/GPU3D_Compute_shaders.h +++ b/src/GPU3D_Compute_shaders.h @@ -208,6 +208,7 @@ buffer TilesBuffer }; #endif +#if defined(DepthBlend) || defined(FinalPass) layout (std430, binding = 5) #ifdef DepthBlend writeonly @@ -221,6 +222,7 @@ buffer RasterResult uint DepthResult[ScreenWidth*ScreenHeight*2]; uint AttrResult[ScreenWidth*ScreenHeight*2]; }; +#endif layout (std140, binding = 0) uniform MetaUniform { @@ -835,6 +837,28 @@ bool BinPolygon(Polygon polygon, ivec2 topLeft, ivec2 botRight) int polygonHeight = polygon.YBot - polygon.YTop; + /* + All (good) polygons are convex. So the following holds true: + + Starting from the top most point where both edges originate + the X coordinate of the left edge will stay the same or falls until + the minimum X-axis coordinate is reached. Then it stays the same or + rises until the point it meets with the right edge. + + The same applies to the right edge, except that it first may rise or stay equal and + after the maximum point may only fall or stay the same. + + This means that for every tile which doesn't contain the point where the direction changes + we can just get the maximum point by sampling the top most and bottom most coordinate + within the tile. + + For a tile which is that the height of the direction change + + As a sidenote another consequence of this design decision is + that malformed polygons aren't binned properly. + + As a note bottom Y is exclusive! + */ int polyInnerTopY = clamp(topLeft.y - polygon.YTop, 0, max(polygonHeight-1, 0)); int polyInnerBotY = clamp(botRight.y - polygon.YTop, 0, max(polygonHeight-1, 0)); @@ -1557,8 +1581,8 @@ void main() // else // color.x = 0U; - //if (gl_LocalInvocationID.x == 7 || gl_LocalInvocationID.y == 7) - //color.x = 0x1F00001FU | 0x40000000U; + //if ((gl_GlobalInvocationID.y % 8) == 7 || (gl_GlobalInvocationID.y % 8) == 7) + // color.x = 0x1F00001FU | 0x40000000U; vec4 result = vec4(bitfieldExtract(color.x, 16, 8), bitfieldExtract(color.x, 8, 8), color.x & 0x3FU, bitfieldExtract(color.x, 24, 8)); result /= vec4(63.0, 63.0, 63.0, 31.0); diff --git a/src/OpenGLSupport.cpp b/src/OpenGLSupport.cpp index 6f6d770b..5b3df9e3 100644 --- a/src/OpenGLSupport.cpp +++ b/src/OpenGLSupport.cpp @@ -24,8 +24,6 @@ using Platform::LogLevel; namespace OpenGL { -#define checkGLError() if (glGetError() != GL_NO_ERROR) printf("error %d\n", __LINE__) - bool CompilerShader(GLuint& id, const char* source, const char* name, const char* type) { int len; @@ -39,12 +37,9 @@ bool CompilerShader(GLuint& id, const char* source, const char* name, const char len = strlen(source); glShaderSource(id, 1, &source, &len); - checkGLError(); glCompileShader(id); - checkGLError(); glGetShaderiv(id, GL_COMPILE_STATUS, &res); - checkGLError(); if (res != GL_TRUE) { glGetShaderiv(id, GL_INFO_LOG_LENGTH, &res); @@ -74,7 +69,6 @@ bool LinkProgram(GLuint& result, GLuint* ids, int numIds) for (int i = 0; i < numIds; i++) { glAttachShader(result, ids[i]); - checkGLError(); } glLinkProgram(result);