Dreamcast: Fix V3_VIS clipping case producing wrong output

This commit is contained in:
UnknownShadow200 2025-06-01 07:22:30 +10:00
parent 72eb16bc7b
commit 0b40c37ccd
3 changed files with 70 additions and 73 deletions

View File

@ -787,7 +787,7 @@ void DrawQuads(int count, void* src) {
list->length += (end - beg); list->length += (end - beg);
if (list != direct) return; if (list != direct) return;
SceneListSubmit((Vertex*)list->data, list->length); SubmitCommands((Vertex*)list->data, list->length);
list->length = 0; list->length = 0;
} }
@ -885,7 +885,7 @@ static void SubmitList(struct CommandsList* list) {
if (!list->length || list == direct) return; if (!list->length || list == direct) return;
BeginList(list->list_type); BeginList(list->list_type);
SceneListSubmit((Vertex*)list->data, list->length); SubmitCommands((Vertex*)list->data, list->length);
FinishList(); FinishList();
list->length = 0; list->length = 0;
} }

View File

@ -21,6 +21,6 @@ typedef struct {
uint16_t height; uint16_t height;
} TextureObject; } TextureObject;
void GLDC_NO_INLINE SceneListSubmit(Vertex* v2, int n); void GLDC_NO_INLINE SubmitCommands(Vertex* v3, int n);
#endif // PRIVATE_H #endif // PRIVATE_H

137
third_party/gldc/sh4.c vendored
View File

@ -2,47 +2,43 @@
#include <dc/pvr.h> #include <dc/pvr.h>
#include "gldc.h" #include "gldc.h"
static GLDC_FORCE_INLINE void PushVertex(Vertex* v, volatile Vertex* dst) { #define PushVertex(src, dst) __asm__ volatile ( \
asm volatile ( "fmov.d @%1+, dr0 ! LS, FX = *src, src += 8\n" \
"fmov.d @%0+, dr0\n" // LS, FX = *src, src += 8 "fmov.d @%1+, dr2 ! LS, YW = *src, src += 8\n" \
"fmov.d @%0+, dr2\n" // LS, YW = *src, src += 8 "add #64, %0 ! EX, dst += 64\n" \
"add #32, %1 \n" // EX, dst += 32 "fmul fr3, fr3 ! FE, W = W * W\n" \
"fmul fr3, fr3\n" // FE, W = W * W "fmov.d @%1+, dr4 ! LS, UV = *src, src += 8\n" \
"fmov.d @%0+, dr4\n" // LS, UV = *src, src += 8 "fmov.d @%1+, dr6 ! LS, C? = *src, src += 8\n" \
"fmov.d @%0+, dr6\n" // LS, C? = *src, src += 8 "fsrra fr3 ! FE, W = 1/sqrt(W*W) ~ 1/W\n" \
"fsrra fr3\n" // FE, W = 1/sqrt(W*W) ~ 1/W "fmov.d dr6, @-%0 ! LS, dst -= 8, *dst = C?\n" \
"fmov.d dr6, @-%1\n" // LS, dst -= 8, *dst = C? "fmov.d dr4, @-%0 ! LS, dst -= 8, *dst = UV\n" \
"fmov.d dr4, @-%1\n" // LS, dst -= 8, *dst = UV "fmul fr3, fr2 ! FE, Y = W * Y\n" \
"fmul fr3, fr2\n" // FE, Y = W * Y "add #-32, %1 ! EX, src -= 32\n" \
"add #-32, %0 \n" // EX, src -= 32 "fmov.d dr2, @-%0 ! LS, dst -= 8, *dst = YW\n" \
"fmov.d dr2, @-%1\n" // LS, dst -= 8, *dst = YW "fmul fr3, fr1 ! FE, Y = X * X\n" \
"fmul fr3, fr1\n" // FE, Y = X * X "fmov.d dr0, @-%0 ! LS, dst -= 8, *dst = FX\n" \
"fmov.d dr0, @-%1\n" // LS, dst -= 8, *dst = FX "pref @%0 ! LS, flush store queue\n" \
"pref @%1 \n" // LS, flush store queue : "+r" (dst) \
: : "r" (src) \
: "r" (v), "r" (dst) : "memory", "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7" \
: "memory", "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7"
); );
}
static inline void PushCommand(Vertex* v, volatile Vertex* dst) { #define PushCommand(src, dst) __asm__ volatile ( \
asm volatile ( "fmov.d @%1+, dr0 ! LS, D01 = *src, src += 8\n" \
"add #32, %1 \n" // EX, dst += 32 "fmov.d @%1+, dr2 ! LS, D23 = *src, src += 8\n" \
"fmov.d @%0+, dr0\n" // LS, fr0_fr1 = *src, src += 8 "fmov.d @%1+, dr4 ! LS, D45 = *src, src += 8\n" \
"fmov.d @%0+, dr2\n" // LS, fr2_fr3 = *src, src += 8 "fmov.d @%1+, dr6 ! LS, D67 = *src, src += 8\n" \
"fmov.d @%0+, dr4\n" // LS, fr4_fr5 = *src, src += 8 "add #64, %0 ! EX, dst += 64\n" \
"fmov.d @%0+, dr6\n" // LS, fr6_fr7 = *src, src += 8 "fmov.d dr6, @-%0 ! LS, dst -= 8, *dst = D67\n" \
"fmov.d dr6, @-%1\n" // LS, dst -= 8, *dst = fr6_fr7 "fmov.d dr4, @-%0 ! LS, dst -= 8, *dst = D45\n" \
"fmov.d dr4, @-%1\n" // LS, dst -= 8, *dst = fr4_fr5 "fmov.d dr2, @-%0 ! LS, dst -= 8, *dst = D23\n" \
"fmov.d dr2, @-%1\n" // LS, dst -= 8, *dst = fr2_fr3 "fmov.d dr0, @-%0 ! LS, dst -= 8, *dst = D01\n" \
"fmov.d dr0, @-%1\n" // LS, dst -= 8, *dst = fr0_fr1 "pref @%0 ! LS, flush store queue\n" \
"pref @%1 \n" // LS, flush store queue "add #-32, %1 ! EX, src -= 32\n" \
"add #-32, %0 \n" // EX, src -= 32 : "+r" (dst) \
: : "r" (src) \
: "r" (v), "r" (dst) : "memory", "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7" \
: "memory", "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7"
); );
}
extern void ClipEdge(Vertex* const v1, Vertex* const v2, volatile Vertex* vout, char type); extern void ClipEdge(Vertex* const v1, Vertex* const v2, volatile Vertex* vout, char type);
@ -56,11 +52,12 @@ extern void ClipEdge(Vertex* const v1, Vertex* const v2, volatile Vertex* vout,
extern void ProcessVertexList(Vertex* v3, int n, void* sq_addr); extern void ProcessVertexList(Vertex* v3, int n, void* sq_addr);
void SceneListSubmit(Vertex* v3, int n) { void SubmitCommands(Vertex* v3, int n) {
volatile Vertex* dst = (volatile Vertex*)MEM_AREA_SQ_BASE; volatile Vertex* dst = (volatile Vertex*)MEM_AREA_SQ_BASE;
Vertex* vEnd = v3 + n;
asm volatile ("fschg"); // swap to 64 bit loads/stores asm volatile ("fschg"); // swap to 64 bit loads/stores
for (int i = 0; i < n; i++, v3++) for (; v3 < vEnd; v3++)
{ {
// Preload next vertex into memory // Preload next vertex into memory
__builtin_prefetch(v3 + 1); __builtin_prefetch(v3 + 1);
@ -71,7 +68,7 @@ void SceneListSubmit(Vertex* v3, int n) {
case PVR_CMD_VERTEX: case PVR_CMD_VERTEX:
continue; continue;
default: default:
PushCommand(v3, dst++); PushCommand(v3, dst);
continue; continue;
}; };
@ -84,10 +81,10 @@ void SceneListSubmit(Vertex* v3, int n) {
// Check if all vertices visible // Check if all vertices visible
if (__builtin_expect(mask == (V0_VIS | V1_VIS | V2_VIS | V3_VIS), 1)) { if (__builtin_expect(mask == (V0_VIS | V1_VIS | V2_VIS | V3_VIS), 1)) {
// Triangle strip: {1,2,0} {2,0,3} // Triangle strip: {1,2,0} {2,0,3}
PushVertex(v1, dst++); PushVertex(v1, dst);
PushVertex(v2, dst++); PushVertex(v2, dst);
PushVertex(v0, dst++); PushVertex(v0, dst);
PushVertex(v3, dst++); PushVertex(v3, dst);
continue; continue;
} }
@ -102,7 +99,7 @@ void SceneListSubmit(Vertex* v3, int n) {
// .....A....B... // .....A....B...
// / | // / |
// v3--v2---v1 // v3--v2---v1
PushVertex(v0, dst++); // v0 PushVertex(v0, dst); // v0
ClipEdge(v0, v1, dst++, TYPE_VTX); // B ClipEdge(v0, v1, dst++, TYPE_VTX); // B
ClipEdge(v3, v0, dst++, TYPE_EOS); // A ClipEdge(v3, v0, dst++, TYPE_EOS); // A
break; break;
@ -115,7 +112,7 @@ void SceneListSubmit(Vertex* v3, int n) {
// / | // / |
// v0--v3---v2 // v0--v3---v2
ClipEdge(v0, v1, dst++, TYPE_VTX); // A ClipEdge(v0, v1, dst++, TYPE_VTX); // A
PushVertex(v1, dst++); // v1 PushVertex(v1, dst); // v1
ClipEdge(v1, v2, dst++, TYPE_EOS); // B ClipEdge(v1, v2, dst++, TYPE_EOS); // B
break; break;
@ -127,7 +124,7 @@ void SceneListSubmit(Vertex* v3, int n) {
// / | // / |
// v1--v0---v3 // v1--v0---v3
ClipEdge(v1, v2, dst++, TYPE_VTX); // A ClipEdge(v1, v2, dst++, TYPE_VTX); // A
PushVertex(v2, dst++); // v2 PushVertex(v2, dst); // v2
ClipEdge(v2, v3, dst++, TYPE_EOS); // B ClipEdge(v2, v3, dst++, TYPE_EOS); // B
break; break;
@ -139,8 +136,8 @@ void SceneListSubmit(Vertex* v3, int n) {
// / | // / |
// v2--v1---v0 // v2--v1---v0
ClipEdge(v3, v0, dst++, TYPE_VTX); // B ClipEdge(v3, v0, dst++, TYPE_VTX); // B
ClipEdge(v2, v3, dst++, TYPE_EOS); // A ClipEdge(v2, v3, dst++, TYPE_VTX); // A
PushVertex(v3, dst++); // v3 PushVertex(v3, dst); // v3
break; break;
case V0_VIS | V1_VIS: case V0_VIS | V1_VIS:
@ -149,9 +146,9 @@ void SceneListSubmit(Vertex* v3, int n) {
// ....B..........A... // ....B..........A...
// \ | // \ |
// v3-----v2 // v3-----v2
PushVertex(v1, dst++); // v1 PushVertex(v1, dst); // v1
ClipEdge(v1, v2, dst++, TYPE_VTX); // A ClipEdge(v1, v2, dst++, TYPE_VTX); // A
PushVertex(v0, dst++); // v0 PushVertex(v0, dst); // v0
ClipEdge(v3, v0, dst++, TYPE_EOS); // B ClipEdge(v3, v0, dst++, TYPE_EOS); // B
break; break;
@ -164,8 +161,8 @@ void SceneListSubmit(Vertex* v3, int n) {
// v2-----v1 // v2-----v1
ClipEdge(v0, v1, dst++, TYPE_VTX); // A ClipEdge(v0, v1, dst++, TYPE_VTX); // A
ClipEdge(v2, v3, dst++, TYPE_VTX); // B ClipEdge(v2, v3, dst++, TYPE_VTX); // B
PushVertex(v0, dst++); // v0 PushVertex(v0, dst); // v0
PushVertex(v3, dst++); // v3 PushVertex(v3, dst); // v3
break; break;
case V1_VIS | V2_VIS: case V1_VIS | V2_VIS:
@ -174,8 +171,8 @@ void SceneListSubmit(Vertex* v3, int n) {
// ....B..........A... // ....B..........A...
// \ | // \ |
// v0-----v3 // v0-----v3
PushVertex(v1, dst++); // v1 PushVertex(v1, dst); // v1
PushVertex(v2, dst++); // v2 PushVertex(v2, dst); // v2
ClipEdge(v0, v1, dst++, TYPE_VTX); // B ClipEdge(v0, v1, dst++, TYPE_VTX); // B
ClipEdge(v2, v3, dst++, TYPE_EOS); // A ClipEdge(v2, v3, dst++, TYPE_EOS); // A
break; break;
@ -188,9 +185,9 @@ void SceneListSubmit(Vertex* v3, int n) {
// \ | // \ |
// v1-----v0 // v1-----v0
ClipEdge(v1, v2, dst++, TYPE_VTX); // B ClipEdge(v1, v2, dst++, TYPE_VTX); // B
PushVertex(v2, dst++); // v2 PushVertex(v2, dst); // v2
ClipEdge(v3, v0, dst++, TYPE_VTX); // A ClipEdge(v3, v0, dst++, TYPE_VTX); // A
PushVertex(v3, dst++); // v3 PushVertex(v3, dst); // v3
break; break;
case V0_VIS | V1_VIS | V2_VIS: case V0_VIS | V1_VIS | V2_VIS:
@ -201,9 +198,9 @@ void SceneListSubmit(Vertex* v3, int n) {
// \ | // \ |
// v3 // v3
// v1,v2,v0 v2,v0,A v0,A,B // v1,v2,v0 v2,v0,A v0,A,B
PushVertex(v1, dst++); // v1 PushVertex(v1, dst); // v1
PushVertex(v2, dst++); // v2 PushVertex(v2, dst); // v2
PushVertex(v0, dst++); // v0 PushVertex(v0, dst); // v0
ClipEdge(v2, v3, dst++, TYPE_VTX); // A ClipEdge(v2, v3, dst++, TYPE_VTX); // A
ClipEdge(v3, v0, dst++, TYPE_EOS); // B ClipEdge(v3, v0, dst++, TYPE_EOS); // B
break; break;
@ -217,9 +214,9 @@ void SceneListSubmit(Vertex* v3, int n) {
// v2 // v2
// v0,v1,v3 v1,v3,A v3,A,B // v0,v1,v3 v1,v3,A v3,A,B
v3->flags = PVR_CMD_VERTEX; v3->flags = PVR_CMD_VERTEX;
PushVertex(v0, dst++); // v0 PushVertex(v0, dst); // v0
PushVertex(v1, dst++); // v1 PushVertex(v1, dst); // v1
PushVertex(v3, dst++); // v3 PushVertex(v3, dst); // v3
ClipEdge(v1, v2, dst++, TYPE_VTX); // A ClipEdge(v1, v2, dst++, TYPE_VTX); // A
ClipEdge(v2, v3, dst++, TYPE_EOS); // B ClipEdge(v2, v3, dst++, TYPE_EOS); // B
break; break;
@ -233,9 +230,9 @@ void SceneListSubmit(Vertex* v3, int n) {
// v1 // v1
// v3,v0,v2 v0,v2,A v2,A,B // v3,v0,v2 v0,v2,A v2,A,B
v3->flags = PVR_CMD_VERTEX; v3->flags = PVR_CMD_VERTEX;
PushVertex(v3, dst++); // v3 PushVertex(v3, dst); // v3
PushVertex(v0, dst++); // v0 PushVertex(v0, dst); // v0
PushVertex(v2, dst++); // v2 PushVertex(v2, dst); // v2
ClipEdge(v0, v1, dst++, TYPE_VTX); // A ClipEdge(v0, v1, dst++, TYPE_VTX); // A
ClipEdge(v1, v2, dst++, TYPE_EOS); // B ClipEdge(v1, v2, dst++, TYPE_EOS); // B
break; break;
@ -249,9 +246,9 @@ void SceneListSubmit(Vertex* v3, int n) {
// v0 // v0
// v2,v3,v1 v3,v1,A v1,A,B // v2,v3,v1 v3,v1,A v1,A,B
v3->flags = PVR_CMD_VERTEX; v3->flags = PVR_CMD_VERTEX;
PushVertex(v2, dst++); // v2 PushVertex(v2, dst); // v2
PushVertex(v3, dst++); // v3 PushVertex(v3, dst); // v3
PushVertex(v1, dst++); // v1 PushVertex(v1, dst); // v1
ClipEdge(v3, v0, dst++, TYPE_VTX); // A ClipEdge(v3, v0, dst++, TYPE_VTX); // A
ClipEdge(v0, v1, dst++, TYPE_EOS); // B ClipEdge(v0, v1, dst++, TYPE_EOS); // B
break; break;