From 30cac2e24b271277d66b42041b0c8a5a95a89f6b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 3 Mar 2017 04:00:47 -0800 Subject: [PATCH] DS GX: Add z-depth sorting --- include/mgba/internal/ds/gx.h | 3 ++- include/mgba/internal/ds/gx/software.h | 7 ++--- src/ds/gx.c | 7 ++--- src/ds/gx/software.c | 36 +++++++++++++++++++------- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/include/mgba/internal/ds/gx.h b/include/mgba/internal/ds/gx.h index 25e9cb242..97c55b594 100644 --- a/include/mgba/internal/ds/gx.h +++ b/include/mgba/internal/ds/gx.h @@ -131,7 +131,7 @@ struct DSGXRenderer { void (*deinit)(struct DSGXRenderer* renderer); void (*invalidateTex)(struct DSGXRenderer* renderer, int slot); - void (*setRAM)(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount); + void (*setRAM)(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount, bool wSort); void (*drawScanline)(struct DSGXRenderer* renderer, int y); void (*getScanline)(struct DSGXRenderer* renderer, int y, color_t** output); @@ -156,6 +156,7 @@ struct DSGX { struct DSGXEntry activeEntries[32]; bool swapBuffers; + bool wSort; int bufferIndex; int vertexIndex; int polygonIndex; diff --git a/include/mgba/internal/ds/gx/software.h b/include/mgba/internal/ds/gx/software.h index 9fe97db1e..3cbfd014e 100644 --- a/include/mgba/internal/ds/gx/software.h +++ b/include/mgba/internal/ds/gx/software.h @@ -22,15 +22,13 @@ struct DSGXSoftwarePolygon { int texFormat; int texW; int texH; - int32_t topY; - int32_t bottomY; - int32_t topZ; }; struct DSGXSoftwareEdge { unsigned polyId; int32_t y0; // 20.12 int32_t x0; // 20.12 + int32_t z0; // 20.12 int32_t w0; // 20.12 uint8_t cr0; uint8_t cg0; @@ -40,6 +38,7 @@ struct DSGXSoftwareEdge { int32_t y1; // 20.12 int32_t x1; // 20.12 + int32_t z1; // 20.12 int32_t w1; // 20.12 uint8_t cr1; uint8_t cg1; @@ -50,6 +49,7 @@ struct DSGXSoftwareEdge { struct DSGXSoftwareEndpoint { int32_t x; // 20.12 + int64_t z; int64_t w; uint8_t cr; uint8_t cg; @@ -78,6 +78,7 @@ struct DSGXSoftwareRenderer { uint16_t depthBuffer[DS_VIDEO_HORIZONTAL_PIXELS]; color_t* scanlineCache; bool flushPending; + bool wSort; struct DSGXVertex* verts; }; diff --git a/src/ds/gx.c b/src/ds/gx.c index f5a5987af..32efaeec1 100644 --- a/src/ds/gx.c +++ b/src/ds/gx.c @@ -17,7 +17,7 @@ static void DSGXDummyRendererInit(struct DSGXRenderer* renderer); static void DSGXDummyRendererReset(struct DSGXRenderer* renderer); static void DSGXDummyRendererDeinit(struct DSGXRenderer* renderer); static void DSGXDummyRendererInvalidateTex(struct DSGXRenderer* renderer, int slot); -static void DSGXDummyRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount); +static void DSGXDummyRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount, bool wSort); static void DSGXDummyRendererDrawScanline(struct DSGXRenderer* renderer, int y); static void DSGXDummyRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output); @@ -877,6 +877,7 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate) break; case DS_GX_CMD_SWAP_BUFFERS: gx->swapBuffers = true; + gx->wSort = entry.params[0] & 2; break; case DS_GX_CMD_VIEWPORT: gx->viewportX1 = (uint8_t) entry.params[0]; @@ -1186,7 +1187,7 @@ uint32_t DSGXWriteRegister32(struct DSGX* gx, uint32_t address, uint32_t value) void DSGXFlush(struct DSGX* gx) { if (gx->swapBuffers) { - gx->renderer->setRAM(gx->renderer, gx->vertexBuffer[gx->bufferIndex], gx->polygonBuffer[gx->bufferIndex], gx->polygonIndex); + gx->renderer->setRAM(gx->renderer, gx->vertexBuffer[gx->bufferIndex], gx->polygonBuffer[gx->bufferIndex], gx->polygonIndex, gx->wSort); gx->swapBuffers = false; gx->bufferIndex ^= 1; gx->vertexIndex = 0; @@ -1220,7 +1221,7 @@ static void DSGXDummyRendererInvalidateTex(struct DSGXRenderer* renderer, int sl // Nothing to do } -static void DSGXDummyRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount) { +static void DSGXDummyRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount, bool wSort) { UNUSED(renderer); UNUSED(verts); UNUSED(polys); diff --git a/src/ds/gx/software.c b/src/ds/gx/software.c index 4d75ee02c..0887f087b 100644 --- a/src/ds/gx/software.c +++ b/src/ds/gx/software.c @@ -18,7 +18,7 @@ static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer); static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer); static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer); static void DSGXSoftwareRendererInvalidateTex(struct DSGXRenderer* renderer, int slot); -static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount); +static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount, bool wSort); static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y); static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output); @@ -165,6 +165,7 @@ static bool _edgeToSpan(struct DSGXSoftwareSpan* span, const struct DSGXSoftware w0 = 0x10000; w1 = 0x10000; span->ep[index].w = w; + span->ep[index].z = (((edge->z1 - edge->z0) * yw) >> 32) + edge->z0; span->ep[index].cr = (((((edge->cr1 * (int64_t) w1 - edge->cr0 * (int64_t) w0) * yw) >> 32) + edge->cr0 * (int64_t) w0) * wRecip) >> 48; span->ep[index].cg = (((((edge->cg1 * (int64_t) w1 - edge->cg0 * (int64_t) w0) * yw) >> 32) + edge->cg0 * (int64_t) w0) * wRecip) >> 48; span->ep[index].cb = (((((edge->cb1 * (int64_t) w1 - edge->cb0 * (int64_t) w0) * yw) >> 32) + edge->cb0 * (int64_t) w0) * wRecip) >> 48; @@ -217,6 +218,8 @@ static void _lerpEndpoint(const struct DSGXSoftwareSpan* span, struct DSGXSoftwa w0 = 0x10000; w1 = 0x10000; + ep->z = (((span->ep[1].z - span->ep[0].z) * xw) >> 32) + span->ep[0].z; + uint64_t r = (((span->ep[1].cr * (int64_t) w1 - span->ep[0].cr * (int64_t) w0) * xw) >> 32) + span->ep[0].cr * (int64_t) w0; uint64_t g = (((span->ep[1].cg * (int64_t) w1 - span->ep[0].cg * (int64_t) w0) * xw) >> 32) + span->ep[0].cg * (int64_t) w0; uint64_t b = (((span->ep[1].cb * (int64_t) w1 - span->ep[0].cb * (int64_t) w0) * xw) >> 32) + span->ep[0].cb * (int64_t) w0; @@ -268,10 +271,11 @@ static void DSGXSoftwareRendererInvalidateTex(struct DSGXRenderer* renderer, int // TODO } -static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount) { +static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSGXVertex* verts, struct DSGXPolygon* polys, unsigned polyCount, bool wSort) { struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer; softwareRenderer->flushPending = true; + softwareRenderer->wSort = wSort; softwareRenderer->verts = verts; DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys); DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges); @@ -309,6 +313,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG if (v0->vy >= v1->vy) { edge->y0 = SCREEN_SIZE - v0->vy; edge->x0 = v0->vx; + edge->z0 = v0->vz; edge->w0 = v0->vw; _expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0); edge->s0 = v0->vs; @@ -316,6 +321,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG edge->y1 = SCREEN_SIZE - v1->vy; edge->x1 = v1->vx; + edge->z1 = v1->vz; edge->w1 = v1->vw; _expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1); edge->s1 = v1->vs; @@ -323,6 +329,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG } else { edge->y0 = SCREEN_SIZE - v1->vy; edge->x0 = v1->vx; + edge->z0 = v1->vz; edge->w0 = v1->vw; _expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0); edge->s0 = v1->vs; @@ -330,6 +337,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG edge->y1 = SCREEN_SIZE - v0->vy; edge->x1 = v0->vx; + edge->z1 = v0->vz; edge->w1 = v0->vw; _expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1); edge->s1 = v0->vs; @@ -345,6 +353,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG if (v0->vy >= v1->vy) { edge->y0 = SCREEN_SIZE - v0->vy; edge->x0 = v0->vx; + edge->z0 = v0->vz; edge->w0 = v0->vw; _expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0); edge->s0 = v0->vs; @@ -352,6 +361,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG edge->y1 = SCREEN_SIZE - v1->vy; edge->x1 = v1->vx; + edge->z1 = v1->vz; edge->w1 = v1->vw; _expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1); edge->s1 = v1->vs; @@ -360,12 +370,14 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG edge->y0 = SCREEN_SIZE - v1->vy; edge->x0 = v1->vx; edge->w0 = v1->vw; + edge->z0 = v1->vz; _expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0); edge->s0 = v1->vs; edge->t0 = v1->vt; edge->y1 = SCREEN_SIZE - v0->vy; edge->x1 = v0->vx; + edge->z1 = v0->vz; edge->w1 = v0->vw; _expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1); edge->s1 = v0->vs; @@ -438,16 +450,22 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int span = DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, nextSpanId - 1); nextSpanX = span->ep[0].x >> 12; } - while (i > (span->ep[0].x >> 12)) { + while (span && i > (span->ep[0].x >> 12)) { if (i <= (span->ep[1].x >> 12)) { _lerpEndpoint(span, &ep, i); color_t color = _lookupColor(&ep, span->poly); - if (scanline[i] == FLAG_UNWRITTEN) { - scanline[i] = color; - } - if (ep.w < depth && color != FLAG_UNWRITTEN) { - depth = ep.w; - scanline[i] = color; + if (color != FLAG_UNWRITTEN) { + if (softwareRenderer->wSort) { + if (ep.w < depth) { + depth = ep.w; + scanline[i] = color; + } + } else { + if (ep.z < depth) { + depth = ep.z; + scanline[i] = color; + } + } } } --nextSpanId;