DS GX: Add z-depth sorting

This commit is contained in:
Vicki Pfau 2017-03-03 04:00:47 -08:00
parent c5157bda7f
commit 30cac2e24b
4 changed files with 37 additions and 16 deletions

View File

@ -131,7 +131,7 @@ struct DSGXRenderer {
void (*deinit)(struct DSGXRenderer* renderer); void (*deinit)(struct DSGXRenderer* renderer);
void (*invalidateTex)(struct DSGXRenderer* renderer, int slot); 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 (*drawScanline)(struct DSGXRenderer* renderer, int y);
void (*getScanline)(struct DSGXRenderer* renderer, int y, color_t** output); void (*getScanline)(struct DSGXRenderer* renderer, int y, color_t** output);
@ -156,6 +156,7 @@ struct DSGX {
struct DSGXEntry activeEntries[32]; struct DSGXEntry activeEntries[32];
bool swapBuffers; bool swapBuffers;
bool wSort;
int bufferIndex; int bufferIndex;
int vertexIndex; int vertexIndex;
int polygonIndex; int polygonIndex;

View File

@ -22,15 +22,13 @@ struct DSGXSoftwarePolygon {
int texFormat; int texFormat;
int texW; int texW;
int texH; int texH;
int32_t topY;
int32_t bottomY;
int32_t topZ;
}; };
struct DSGXSoftwareEdge { struct DSGXSoftwareEdge {
unsigned polyId; unsigned polyId;
int32_t y0; // 20.12 int32_t y0; // 20.12
int32_t x0; // 20.12 int32_t x0; // 20.12
int32_t z0; // 20.12
int32_t w0; // 20.12 int32_t w0; // 20.12
uint8_t cr0; uint8_t cr0;
uint8_t cg0; uint8_t cg0;
@ -40,6 +38,7 @@ struct DSGXSoftwareEdge {
int32_t y1; // 20.12 int32_t y1; // 20.12
int32_t x1; // 20.12 int32_t x1; // 20.12
int32_t z1; // 20.12
int32_t w1; // 20.12 int32_t w1; // 20.12
uint8_t cr1; uint8_t cr1;
uint8_t cg1; uint8_t cg1;
@ -50,6 +49,7 @@ struct DSGXSoftwareEdge {
struct DSGXSoftwareEndpoint { struct DSGXSoftwareEndpoint {
int32_t x; // 20.12 int32_t x; // 20.12
int64_t z;
int64_t w; int64_t w;
uint8_t cr; uint8_t cr;
uint8_t cg; uint8_t cg;
@ -78,6 +78,7 @@ struct DSGXSoftwareRenderer {
uint16_t depthBuffer[DS_VIDEO_HORIZONTAL_PIXELS]; uint16_t depthBuffer[DS_VIDEO_HORIZONTAL_PIXELS];
color_t* scanlineCache; color_t* scanlineCache;
bool flushPending; bool flushPending;
bool wSort;
struct DSGXVertex* verts; struct DSGXVertex* verts;
}; };

View File

@ -17,7 +17,7 @@ static void DSGXDummyRendererInit(struct DSGXRenderer* renderer);
static void DSGXDummyRendererReset(struct DSGXRenderer* renderer); static void DSGXDummyRendererReset(struct DSGXRenderer* renderer);
static void DSGXDummyRendererDeinit(struct DSGXRenderer* renderer); static void DSGXDummyRendererDeinit(struct DSGXRenderer* renderer);
static void DSGXDummyRendererInvalidateTex(struct DSGXRenderer* renderer, int slot); 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 DSGXDummyRendererDrawScanline(struct DSGXRenderer* renderer, int y);
static void DSGXDummyRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output); 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; break;
case DS_GX_CMD_SWAP_BUFFERS: case DS_GX_CMD_SWAP_BUFFERS:
gx->swapBuffers = true; gx->swapBuffers = true;
gx->wSort = entry.params[0] & 2;
break; break;
case DS_GX_CMD_VIEWPORT: case DS_GX_CMD_VIEWPORT:
gx->viewportX1 = (uint8_t) entry.params[0]; 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) { void DSGXFlush(struct DSGX* gx) {
if (gx->swapBuffers) { 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->swapBuffers = false;
gx->bufferIndex ^= 1; gx->bufferIndex ^= 1;
gx->vertexIndex = 0; gx->vertexIndex = 0;
@ -1220,7 +1221,7 @@ static void DSGXDummyRendererInvalidateTex(struct DSGXRenderer* renderer, int sl
// Nothing to do // 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(renderer);
UNUSED(verts); UNUSED(verts);
UNUSED(polys); UNUSED(polys);

View File

@ -18,7 +18,7 @@ static void DSGXSoftwareRendererInit(struct DSGXRenderer* renderer);
static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer); static void DSGXSoftwareRendererReset(struct DSGXRenderer* renderer);
static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer); static void DSGXSoftwareRendererDeinit(struct DSGXRenderer* renderer);
static void DSGXSoftwareRendererInvalidateTex(struct DSGXRenderer* renderer, int slot); 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 DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int y);
static void DSGXSoftwareRendererGetScanline(struct DSGXRenderer* renderer, int y, color_t** output); 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; w0 = 0x10000;
w1 = 0x10000; w1 = 0x10000;
span->ep[index].w = w; 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].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].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; 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; w0 = 0x10000;
w1 = 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 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 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; 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 // 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; struct DSGXSoftwareRenderer* softwareRenderer = (struct DSGXSoftwareRenderer*) renderer;
softwareRenderer->flushPending = true; softwareRenderer->flushPending = true;
softwareRenderer->wSort = wSort;
softwareRenderer->verts = verts; softwareRenderer->verts = verts;
DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys); DSGXSoftwarePolygonListClear(&softwareRenderer->activePolys);
DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges); DSGXSoftwareEdgeListClear(&softwareRenderer->activeEdges);
@ -309,6 +313,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG
if (v0->vy >= v1->vy) { if (v0->vy >= v1->vy) {
edge->y0 = SCREEN_SIZE - v0->vy; edge->y0 = SCREEN_SIZE - v0->vy;
edge->x0 = v0->vx; edge->x0 = v0->vx;
edge->z0 = v0->vz;
edge->w0 = v0->vw; edge->w0 = v0->vw;
_expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0); _expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0);
edge->s0 = v0->vs; edge->s0 = v0->vs;
@ -316,6 +321,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG
edge->y1 = SCREEN_SIZE - v1->vy; edge->y1 = SCREEN_SIZE - v1->vy;
edge->x1 = v1->vx; edge->x1 = v1->vx;
edge->z1 = v1->vz;
edge->w1 = v1->vw; edge->w1 = v1->vw;
_expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1); _expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1);
edge->s1 = v1->vs; edge->s1 = v1->vs;
@ -323,6 +329,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG
} else { } else {
edge->y0 = SCREEN_SIZE - v1->vy; edge->y0 = SCREEN_SIZE - v1->vy;
edge->x0 = v1->vx; edge->x0 = v1->vx;
edge->z0 = v1->vz;
edge->w0 = v1->vw; edge->w0 = v1->vw;
_expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0); _expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0);
edge->s0 = v1->vs; edge->s0 = v1->vs;
@ -330,6 +337,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG
edge->y1 = SCREEN_SIZE - v0->vy; edge->y1 = SCREEN_SIZE - v0->vy;
edge->x1 = v0->vx; edge->x1 = v0->vx;
edge->z1 = v0->vz;
edge->w1 = v0->vw; edge->w1 = v0->vw;
_expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1); _expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1);
edge->s1 = v0->vs; edge->s1 = v0->vs;
@ -345,6 +353,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG
if (v0->vy >= v1->vy) { if (v0->vy >= v1->vy) {
edge->y0 = SCREEN_SIZE - v0->vy; edge->y0 = SCREEN_SIZE - v0->vy;
edge->x0 = v0->vx; edge->x0 = v0->vx;
edge->z0 = v0->vz;
edge->w0 = v0->vw; edge->w0 = v0->vw;
_expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0); _expandColor(v0->color, &edge->cr0, &edge->cg0, &edge->cb0);
edge->s0 = v0->vs; edge->s0 = v0->vs;
@ -352,6 +361,7 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG
edge->y1 = SCREEN_SIZE - v1->vy; edge->y1 = SCREEN_SIZE - v1->vy;
edge->x1 = v1->vx; edge->x1 = v1->vx;
edge->z1 = v1->vz;
edge->w1 = v1->vw; edge->w1 = v1->vw;
_expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1); _expandColor(v1->color, &edge->cr1, &edge->cg1, &edge->cb1);
edge->s1 = v1->vs; edge->s1 = v1->vs;
@ -360,12 +370,14 @@ static void DSGXSoftwareRendererSetRAM(struct DSGXRenderer* renderer, struct DSG
edge->y0 = SCREEN_SIZE - v1->vy; edge->y0 = SCREEN_SIZE - v1->vy;
edge->x0 = v1->vx; edge->x0 = v1->vx;
edge->w0 = v1->vw; edge->w0 = v1->vw;
edge->z0 = v1->vz;
_expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0); _expandColor(v1->color, &edge->cr0, &edge->cg0, &edge->cb0);
edge->s0 = v1->vs; edge->s0 = v1->vs;
edge->t0 = v1->vt; edge->t0 = v1->vt;
edge->y1 = SCREEN_SIZE - v0->vy; edge->y1 = SCREEN_SIZE - v0->vy;
edge->x1 = v0->vx; edge->x1 = v0->vx;
edge->z1 = v0->vz;
edge->w1 = v0->vw; edge->w1 = v0->vw;
_expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1); _expandColor(v0->color, &edge->cr1, &edge->cg1, &edge->cb1);
edge->s1 = v0->vs; edge->s1 = v0->vs;
@ -438,17 +450,23 @@ static void DSGXSoftwareRendererDrawScanline(struct DSGXRenderer* renderer, int
span = DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, nextSpanId - 1); span = DSGXSoftwareSpanListGetPointer(&softwareRenderer->activeSpans, nextSpanId - 1);
nextSpanX = span->ep[0].x >> 12; 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)) { if (i <= (span->ep[1].x >> 12)) {
_lerpEndpoint(span, &ep, i); _lerpEndpoint(span, &ep, i);
color_t color = _lookupColor(&ep, span->poly); color_t color = _lookupColor(&ep, span->poly);
if (scanline[i] == FLAG_UNWRITTEN) { if (color != FLAG_UNWRITTEN) {
scanline[i] = color; if (softwareRenderer->wSort) {
} if (ep.w < depth) {
if (ep.w < depth && color != FLAG_UNWRITTEN) {
depth = ep.w; depth = ep.w;
scanline[i] = color; scanline[i] = color;
} }
} else {
if (ep.z < depth) {
depth = ep.z;
scanline[i] = color;
}
}
}
} }
--nextSpanId; --nextSpanId;
if (!nextSpanId) { if (!nextSpanId) {