Optimisations

This commit is contained in:
Luke Benstead 2023-05-11 20:00:13 +01:00
parent cba2fb7ceb
commit e683b8becb
4 changed files with 288 additions and 220 deletions

View File

@ -5,75 +5,123 @@
MAKE_FUNC(POLYMODE)
{
const Vertex* const start = _glSubmissionTargetStart(target);
const VertexExtra* const ve_start = aligned_vector_at(target->extras, 0);
const GLuint vstride = ATTRIB_POINTERS.vertex.stride;
GLuint uvstride = ATTRIB_POINTERS.uv.stride;
GLuint ststride = ATTRIB_POINTERS.st.stride;
GLuint dstride = ATTRIB_POINTERS.colour.stride;
GLuint nstride = ATTRIB_POINTERS.normal.stride;
const GLubyte* pos = (ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG) ? ATTRIB_POINTERS.vertex.ptr + (first * vstride) : NULL;
const GLubyte* uv = (ENABLED_VERTEX_ATTRIBUTES & UV_ENABLED_FLAG) ? ATTRIB_POINTERS.uv.ptr + (first * uvstride) : NULL;
const GLubyte* col = (ENABLED_VERTEX_ATTRIBUTES & DIFFUSE_ENABLED_FLAG) ? ATTRIB_POINTERS.colour.ptr + (first * dstride) : NULL;
const GLubyte* st = (ENABLED_VERTEX_ATTRIBUTES & ST_ENABLED_FLAG) ? ATTRIB_POINTERS.st.ptr + (first * ststride) : NULL;
const GLubyte* n = (ENABLED_VERTEX_ATTRIBUTES & NORMAL_ENABLED_FLAG) ? ATTRIB_POINTERS.normal.ptr + (first * nstride) : NULL;
const float w = 1.0f;
if(!pos) {
static const float w = 1.0f;
if(!(ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG)) {
/* If we don't have vertices, do nothing */
return;
}
if(!col) {
col = (GLubyte*) &U4ONE;
dstride = 0;
/* This is the best value we have. PROCESS_VERTEX_FLAGS needs to operate on quads and tris and so
this need to be divisible by 4 and 3. Even though we should be able to go much higher than this
and still be cache-local, trial and error says otherwise... */
#define BATCH_SIZE 60
GLuint min = 0;
GLuint stride;
const GLubyte* ptr;
Vertex* it;
VertexExtra* ve;
for(int min = 0; min < count; min += BATCH_SIZE) {
const Vertex* start = ((Vertex*) _glSubmissionTargetStart(target)) + min;
const int_fast32_t loop = ((min + BATCH_SIZE) > count) ? count - min : BATCH_SIZE;
const int offset = (first + min);
stride = ATTRIB_POINTERS.vertex.stride;
ptr = ATTRIB_POINTERS.vertex.ptr + (offset * stride);
it = (Vertex*) start;
PREFETCH(ptr);
for(int_fast32_t i = 0; i < loop; ++i, ++it) {
PREFETCH(ptr + stride);
TransformVertex((const float*) ptr, &w, it->xyz, &it->w);
PROCESS_VERTEX_FLAGS(it, min + i);
ptr += stride;
}
if(!uv) {
uv = (GLubyte*) &F2ZERO;
uvstride = 0;
stride = ATTRIB_POINTERS.uv.stride;
ptr = (ENABLED_VERTEX_ATTRIBUTES & UV_ENABLED_FLAG) ? ATTRIB_POINTERS.uv.ptr + ((first + min) * stride) : NULL;
it = (Vertex*) start;
if(ptr) {
PREFETCH(ptr);
for(int_fast32_t i = 0; i < loop; ++i, ++it) {
PREFETCH(ptr + stride);
it->uv[0] = ((float*) ptr)[0];
it->uv[1] = ((float*) ptr)[1];
ptr += stride;
}
} else {
for(int_fast32_t i = 0; i < loop; ++i, ++it) {
it->uv[0] = 0;
it->uv[1] = 0;
}
}
stride = ATTRIB_POINTERS.colour.stride;
ptr = (ENABLED_VERTEX_ATTRIBUTES & DIFFUSE_ENABLED_FLAG) ? ATTRIB_POINTERS.colour.ptr + (offset * stride) : NULL;
it = (Vertex*) start;
if(ptr) {
PREFETCH(ptr);
for(int_fast32_t i = 0; i < loop; ++i, ++it) {
PREFETCH(ptr + stride);
it->bgra[0] = ptr[0];
it->bgra[1] = ptr[1];
it->bgra[2] = ptr[2];
it->bgra[3] = ptr[3];
ptr += stride;
}
} else {
for(int_fast32_t i = 0; i < loop; ++i, ++it) {
*((uint32_t*) it->bgra) = ~0;
}
}
start = aligned_vector_at(target->extras, min);
stride = ATTRIB_POINTERS.st.stride;
ptr = (ENABLED_VERTEX_ATTRIBUTES & ST_ENABLED_FLAG) ? ATTRIB_POINTERS.st.ptr + (offset * stride) : NULL;
ve = (VertexExtra*) start;
if(ptr) {
PREFETCH(ptr);
for(int_fast32_t i = 0; i < loop; ++i, ++ve) {
PREFETCH(ptr + stride);
ve->st[0] = ((float*) ptr)[0];
ve->st[1] = ((float*) ptr)[1];
ptr += stride;
}
} else {
for(int_fast32_t i = 0; i < loop; ++i, ++ve) {
ve->st[0] = 0;
ve->st[1] = 0;
}
}
stride = ATTRIB_POINTERS.normal.stride;
ptr = (ENABLED_VERTEX_ATTRIBUTES & NORMAL_ENABLED_FLAG) ? ATTRIB_POINTERS.normal.ptr + (offset * stride) : NULL;
ve = (VertexExtra*) start;
if(ptr) {
PREFETCH(ptr);
for(int_fast32_t i = 0; i < loop; ++i, ++ve) {
PREFETCH(ptr + stride);
ve->nxyz[0] = ((float*) ptr)[0];
ve->nxyz[1] = ((float*) ptr)[1];
ve->nxyz[2] = ((float*) ptr)[2];
ptr += stride;
}
} else {
for(int_fast32_t i = 0; i < loop; ++i, ++ve) {
ve->nxyz[0] = 0;
ve->nxyz[1] = 0;
ve->nxyz[2] = 0;
}
}
if(!st) {
st = (GLubyte*) &F2ZERO;
ststride = 0;
}
if(!n) {
n = (GLubyte*) &F3Z;
nstride = 0;
}
VertexExtra* ve = (VertexExtra*) ve_start;
Vertex* it = (Vertex*) start;
for(int_fast32_t i = 0; i < count; ++i) {
TransformVertex((const float*) pos, &w, it->xyz, &it->w);
pos += vstride;
PREFETCH(pos);
*((Float2*) it->uv) = *((Float2*) uv);
uv += uvstride;
PREFETCH(uv);
*((uint32_t*) it->bgra) = *((uint32_t*) col);
col += dstride;
PREFETCH(col);
*((Float2*) ve->st) = *((Float2*) st);
st += ststride;
PREFETCH(st);
*((Float3*) ve->nxyz) = *((Float3*) n);
n += nstride;
PREFETCH(n);
PROCESS_VERTEX_FLAGS(it, i);
++it;
++ve;
}
}

View File

@ -95,19 +95,19 @@ void APIENTRY glKosSwapBuffers() {
SceneBegin();
if(OP_LIST.vector.size > 2) {
SceneListBegin(GPU_LIST_OP_POLY);
SceneListSubmit(OP_LIST.vector.data, OP_LIST.vector.size);
SceneListSubmit((Vertex*) OP_LIST.vector.data, OP_LIST.vector.size);
SceneListFinish();
}
if(PT_LIST.vector.size > 2) {
SceneListBegin(GPU_LIST_PT_POLY);
SceneListSubmit(PT_LIST.vector.data, PT_LIST.vector.size);
SceneListSubmit((Vertex*) PT_LIST.vector.data, PT_LIST.vector.size);
SceneListFinish();
}
if(TR_LIST.vector.size > 2) {
SceneListBegin(GPU_LIST_TR_POLY);
SceneListSubmit(TR_LIST.vector.data, TR_LIST.vector.size);
SceneListSubmit((Vertex*) TR_LIST.vector.data, TR_LIST.vector.size);
SceneListFinish();
}
SceneFinish();

View File

@ -5,6 +5,7 @@
#include <stdbool.h>
#include "gl_assert.h"
#include "types.h"
#define MEMSET(dst, v, size) memset((dst), (v), (size))
@ -260,7 +261,7 @@ typedef float Matrix4x4[16];
void SceneBegin();
void SceneListBegin(GPUList list);
void SceneListSubmit(void* src, int n);
void SceneListSubmit(Vertex* v2, int n);
void SceneListFinish();
void SceneFinish();

View File

@ -64,31 +64,26 @@ GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex, const float h) {
}
}
GL_FORCE_INLINE void _glSubmitHeaderOrVertex(volatile uint32_t* d, const Vertex* v) {
#ifndef NDEBUG
gl_assert(!isnan(v->xyz[2]));
gl_assert(!isnan(v->w));
#endif
#if CLIP_DEBUG
fprintf(stderr, "Submitting: %x (%x)\n", v, v->flags);
#endif
volatile uint32_t *sq = SQ_BASE_ADDRESS;
static inline void _glFlushBuffer() {}
static inline void _glPushHeaderOrVertex(Vertex* v) {
uint32_t* s = (uint32_t*) v;
d[0] = *(s++);
d[1] = *(s++);
d[2] = *(s++);
d[3] = *(s++);
d[4] = *(s++);
d[5] = *(s++);
d[6] = *(s++);
d[7] = *(s++);
__asm__("pref @%0" : : "r"(d));
d += 8;
sq[0] = *(s++);
sq[1] = *(s++);
sq[2] = *(s++);
sq[3] = *(s++);
sq[4] = *(s++);
sq[5] = *(s++);
sq[6] = *(s++);
sq[7] = *(s++);
__asm__("pref @%0" : : "r"(sq));
sq += 8;
}
static inline void _glClipEdge(const Vertex* const v1, const Vertex* const v2, Vertex* vout) {
const static float o = 1.0f / 255.0f;
const static float o = 0.003921569f; // 1 / 255
const float d0 = v1->w + v1->xyz[2];
const float d1 = v2->w + v2->xyz[2];
const float t = (fabs(d0) * (1.0f / sqrtf((d1 - d0) * (d1 - d0)))) + 0.000001f;
@ -117,7 +112,7 @@ static volatile uint32_t* PVR_LMMODE0 = (uint32_t*) 0xA05F6884;
static volatile uint32_t *PVR_LMMODE1 = (uint32_t*) 0xA05F6888;
static volatile uint32_t *QACR = (uint32_t*) 0xFF000038;
void SceneListSubmit(void* src, int n) {
void SceneListSubmit(Vertex* v2, int n) {
/* You need at least a header, and 3 vertices to render anything */
if(n < 4) {
return;
@ -134,111 +129,113 @@ void SceneListSubmit(void* src, int n) {
//Set QACR registers
QACR[1] = QACR[0] = 0x11;
volatile uint32_t *sq = SQ_BASE_ADDRESS;
uint32_t clipping_disabled_mask = (_glNearZClippingEnabled()) ? 0 : 0x7;
#if CLIP_DEBUG
Vertex* vertex = (Vertex*) src;
for(int i = 0; i < n; ++i) {
fprintf(stderr, "{%f, %f, %f, %f}, // %x (%x)\n", vertex[i].xyz[0], vertex[i].xyz[1], vertex[i].xyz[2], vertex[i].w, vertex[i].flags, &vertex[i]);
}
fprintf(stderr, "----\n");
#endif
uint8_t counter = 0;
uint8_t __attribute__((aligned(32))) visible_mask = 0;
uint8_t __attribute__((aligned(32))) counter = 0;
Vertex* v2 = (Vertex*) src;
while(n--) {
__builtin_prefetch(v2 + 1);
sq = SQ_BASE_ADDRESS;
for(int i = 0; i < n; ++i, ++v2) {
switch(v2->flags) {
case GPU_CMD_VERTEX_EOL:
if(counter < 2) {
continue;
}
counter = 0;
break;
case GPU_CMD_VERTEX:
if(++counter < 3) {
v2++;
++counter;
if(counter < 3) {
continue;
}
break;
default:
_glSubmitHeaderOrVertex(sq, v2++);
_glPushHeaderOrVertex(v2);
counter = 0;
continue;
}
};
Vertex* const v0 = v2 - 2;
Vertex* const v1 = v2 - 1;
const uint8_t visible_mask = (
visible_mask = (
(v0->xyz[2] > -v0->w) << 0 |
(v1->xyz[2] > -v1->w) << 1 |
(v2->xyz[2] > -v2->w) << 2 |
((v2->flags == GPU_CMD_VERTEX_EOL) << 3) |
clipping_disabled_mask // This forces everything to be marked visible if clipping is disabled
(counter == 0) << 3
);
switch(visible_mask) {
case 0:
break;
case 15: /* All visible, but final vertex in strip */
{
_glPerspectiveDivideVertex(v0, h);
_glSubmitHeaderOrVertex(sq, v0);
_glPushHeaderOrVertex(v0);
Vertex __attribute__((aligned(32))) a = *v1;
_glPerspectiveDivideVertex(&a, h);
_glSubmitHeaderOrVertex(sq, &a);
_glPerspectiveDivideVertex(v1, h);
_glPushHeaderOrVertex(v1);
a = *v2;
_glPerspectiveDivideVertex(&a, h);
_glSubmitHeaderOrVertex(sq, &a);
_glPerspectiveDivideVertex(v2, h);
_glPushHeaderOrVertex(v2);
}
break;
case 7:
/* All visible, push the first vertex and move on */
_glPerspectiveDivideVertex(v0, h);
_glSubmitHeaderOrVertex(sq, v0);
_glPushHeaderOrVertex(v0);
break;
case 9:
/* First vertex was visible, last in strip */
{
Vertex __attribute__((aligned(32))) a, b;
Vertex __attribute__((aligned(32))) scratch[2];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
_glClipEdge(v0, v1, &a);
a.flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v2, v0, &b);
b.flags = GPU_CMD_VERTEX_EOL;
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX_EOL;
_glPerspectiveDivideVertex(v0, h);
_glSubmitHeaderOrVertex(sq, v0);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(&a, h);
_glSubmitHeaderOrVertex(sq, &a);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(&b, h);
_glSubmitHeaderOrVertex(sq, &b);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
}
break;
case 1:
/* First vertex was visible, but not last in strip */
{
Vertex __attribute__((aligned(32))) a, b;
Vertex __attribute__((aligned(32))) scratch[2];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
_glClipEdge(v0, v1, &a);
a.flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v2, v0, &b);
b.flags = GPU_CMD_VERTEX;
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glSubmitHeaderOrVertex(sq, v0);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(&a, h);
_glSubmitHeaderOrVertex(sq, &a);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(&b, h);
_glSubmitHeaderOrVertex(sq, &b);
_glSubmitHeaderOrVertex(sq, &b);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(b);
}
break;
case 10:
@ -246,165 +243,187 @@ void SceneListSubmit(void* src, int n) {
/* Second vertex was visible. In self case we need to create a triangle and produce
two new vertices: 1-2, and 2-3. */
{
Vertex __attribute__((aligned(32))) a;
Vertex __attribute__((aligned(32))) c = *v1;
_glClipEdge(v0, &c, &a);
a.flags = GPU_CMD_VERTEX;
Vertex __attribute__((aligned(32))) scratch[2];
Vertex* a = &scratch[0];
Vertex* c = &scratch[1];
_glPerspectiveDivideVertex(&a, h);
_glSubmitHeaderOrVertex(sq, &a);
memcpy_vertex(c, v1);
_glClipEdge(&c, v2, &a);
a.flags = v2->flags;
_glClipEdge(v0, c, a);
a->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(&c, h);
_glSubmitHeaderOrVertex(sq, &c);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(&a, h);
_glSubmitHeaderOrVertex(sq, &a);
_glClipEdge(c, v2, a);
a->flags = v2->flags;
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
}
break;
case 11:
case 3: /* First and second vertex were visible */
{
Vertex __attribute__((aligned(32))) a, b;
Vertex __attribute__((aligned(32))) c = *v1;
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
_glClipEdge(v2, v0, &b);
b.flags = GPU_CMD_VERTEX;
memcpy_vertex(c, v1);
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glSubmitHeaderOrVertex(sq, v0);
_glPushHeaderOrVertex(v0);
_glClipEdge(v1, v2, &a);
a.flags = v2->flags;
_glClipEdge(v1, v2, a);
a->flags = v2->flags;
_glPerspectiveDivideVertex(&c, h);
_glSubmitHeaderOrVertex(sq, &c);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(&b, h);
_glSubmitHeaderOrVertex(sq, &b);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(&a, h);
_glSubmitHeaderOrVertex(sq, &c);
_glSubmitHeaderOrVertex(sq, &a);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(c);
_glPushHeaderOrVertex(a);
}
break;
case 12:
case 4:
/* Third vertex was visible. */
{
Vertex __attribute__((aligned(32))) a, b;
Vertex __attribute__((aligned(32))) c = *v2;
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
_glClipEdge(v2, v0, &a);
a.flags = GPU_CMD_VERTEX;
memcpy_vertex(c, v2);
_glClipEdge(v1, v2, &b);
b.flags = GPU_CMD_VERTEX;
_glClipEdge(v2, v0, a);
a->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(&a, h);
_glSubmitHeaderOrVertex(sq, &a);
_glClipEdge(v1, v2, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(&b, h);
_glSubmitHeaderOrVertex(sq, &a);
_glSubmitHeaderOrVertex(sq, &b);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(&c, h);
_glSubmitHeaderOrVertex(sq, &c);
if(counter % 2 == 1) {
_glPushHeaderOrVertex(a);
}
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
}
break;
case 13:
{
Vertex __attribute__((aligned(32))) a, b;
Vertex __attribute__((aligned(32))) c = *v2;
c.flags = GPU_CMD_VERTEX;
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
_glClipEdge(v0, v1, &a);
a.flags = GPU_CMD_VERTEX;
memcpy_vertex(c, v2);
c->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, &b);
b.flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glSubmitHeaderOrVertex(sq, v0);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(&a, h);
_glSubmitHeaderOrVertex(sq, &a);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(&c, h);
_glSubmitHeaderOrVertex(sq, &c);
_glPerspectiveDivideVertex(&b, h);
_glSubmitHeaderOrVertex(sq, &b);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
c.flags = GPU_CMD_VERTEX_EOL;
_glSubmitHeaderOrVertex(sq, &c);
c->flags = GPU_CMD_VERTEX_EOL;
_glPushHeaderOrVertex(c);
}
break;
case 5: /* First and third vertex were visible */
{
Vertex __attribute__((aligned(32))) a, b;
Vertex __attribute__((aligned(32))) c = *v2;
c.flags = GPU_CMD_VERTEX;
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
_glClipEdge(v0, v1, &a);
a.flags = GPU_CMD_VERTEX;
memcpy_vertex(c, v2);
c->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, &b);
b.flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glSubmitHeaderOrVertex(sq, v0);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(&a, h);
_glSubmitHeaderOrVertex(sq, &a);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(&c, h);
_glSubmitHeaderOrVertex(sq, &c);
_glPerspectiveDivideVertex(&b, h);
_glSubmitHeaderOrVertex(sq, &b);
_glSubmitHeaderOrVertex(sq, &c);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(c);
}
break;
case 14:
case 6: /* Second and third vertex were visible */
{
Vertex __attribute__((aligned(32))) a, b;
Vertex __attribute__((aligned(32))) c = *v1;
Vertex __attribute__((aligned(32))) scratch[4];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
Vertex* d = &scratch[3];
_glClipEdge(v0, v1, &a);
a.flags = GPU_CMD_VERTEX;
memcpy_vertex(c, v1);
memcpy_vertex(d, v2);
_glClipEdge(v2, v0, &b);
b.flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(&a, h);
_glSubmitHeaderOrVertex(sq, &a);
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(&c, h);
_glSubmitHeaderOrVertex(sq, &c);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(&b, h);
_glSubmitHeaderOrVertex(sq, &b);
_glSubmitHeaderOrVertex(sq, &c);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
c = *v2;
_glPerspectiveDivideVertex(&c, h);
_glSubmitHeaderOrVertex(sq, &c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(d, h);
_glPushHeaderOrVertex(d);
}
break;
default:
break;
}
if(v2->flags == GPU_CMD_VERTEX_EOL) {
counter = 0;
} else {
--counter;
}
v2++;
}
_glFlushBuffer();
}
void SceneListFinish() {