From e1d239150ef2716780a6e4a0121a56b4b2db7744 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Thu, 19 Jan 2023 14:01:28 +0100 Subject: [PATCH] Made polygon building faster by checking ahead of time if we have enough primitive buffer space, instead of checking it per polygon. Also the primitive buffer management is now all done through inline functions. --- memory.c | 32 ++++---------------------------- memory.h | 33 +++++++++++++++++++++++---------- world.c | 18 +++++++++--------- 3 files changed, 36 insertions(+), 47 deletions(-) diff --git a/memory.c b/memory.c index 4777157..c90eb47 100644 --- a/memory.c +++ b/memory.c @@ -1,38 +1,14 @@ #include "common.h" #include "memory.h" -#define PRIMBUFLEN 131072 // TODO: optimize this for a typical scene - static char primbuff[2][PRIMBUFLEN]; // Primitive buffer, just a raw buffer of bytes to use as a pool for primitives -static char *nextpri; -static char *primbuff_bounds; +char *nextprim; +char *primbuf_bounds; u_char* const scratchpad = (char*)0x1F800000; -void *mem_scratch(char **scratch_offset, unsigned short size) -{ -#if _DEBUG - if (*scratch_offset + size > scratchpad + 1024) - return NULL; -#endif - - void *result = *scratch_offset; - *scratch_offset += size; - return result; -} - void mem_prim_reset(int db) { - nextpri = primbuff[db]; - primbuff_bounds = nextpri + PRIMBUFLEN; -} - -void *mem_prim(size_t size) -{ - if (nextpri + size > primbuff_bounds) - return NULL; // TODO: report error - - void *prim = nextpri; - nextpri += size; - return prim; + nextprim = primbuff[db]; + primbuf_bounds = nextprim + PRIMBUFLEN; } diff --git a/memory.h b/memory.h index 4b03443..820c6d1 100644 --- a/memory.h +++ b/memory.h @@ -1,16 +1,12 @@ #ifndef __MEMORY_H__ #define __MEMORY_H__ -extern u_char* const scratchpad; // Starting address of scratchpad memory +#define SCRATCHLEN 1024 +extern u_char* const scratchpad; // Starting address of scratchpad memory, i.e. the 1kB of data cache usable as fast RAM -/** - * @brief Allocate memory in the fast scratchpad RAM buffer. - * - * @param scratch_offset Pointer to a variable holding the current offset position in scratch memory. - * @param size The number of bytes to allocate. Be aware that the scratchpad memory only has 1024 bytes available. - * @return Pointer to the allocated buffer in scratchpad memory. - */ -void *mem_scratch(char **scratch_offset, unsigned short size); +#define PRIMBUFLEN 65536 // TODO: reduce this to what's needed for a typical scene +extern char *nextprim; +extern char *primbuf_bounds; /** * @brief Allocate a single primitive in the primitive buffer. @@ -18,7 +14,24 @@ void *mem_scratch(char **scratch_offset, unsigned short size); * @param size Size of the primitive struct to allocate. * @return Pointer to the allocated struct in memory. */ -void *mem_prim(size_t size); +INLINE void *mem_prim(size_t size) +{ + void *prim = nextprim; + nextprim += size; + return prim; +} + +/** + * @brief Check if it's safe to allocate the given number of primitives of the given size. + * + * @param size The size of each primitive to allocate. + * @param count The number of primitives to allocate. + * @return Whether the number of primitives can be allocated without exceeding the primitive buffer bounds. + */ +INLINE char mem_checkprim(size_t size, u_short count) +{ + return nextprim + size * count < primbuf_bounds; +} void mem_prim_reset(int db); diff --git a/world.c b/world.c index 0386c0f..379a1c5 100644 --- a/world.c +++ b/world.c @@ -53,6 +53,9 @@ static INLINE void drawface_triangle_fan(const ps1bsp_face_t *face, SVECTOR *vec { int p; + if (!mem_checkprim(sizeof(POLY_G3), face->numFaceVertices)) + return; + // Draw the face as a triangle fan u_char maxVert = face->numFaceVertices - 1; for (int vertIdx = 1; vertIdx < maxVert; ++vertIdx) @@ -74,9 +77,6 @@ static INLINE void drawface_triangle_fan(const ps1bsp_face_t *face, SVECTOR *vec // Draw a flat-shaded untextured colored triangle POLY_G3 *poly = (POLY_G3*)mem_prim(sizeof(POLY_G3)); - if (poly == NULL) - break; - setPolyG3(poly); gte_stsxy3_g3(poly); @@ -93,6 +93,9 @@ static INLINE void drawface_triangle_strip(const ps1bsp_face_t *face, SVECTOR *v { int p; + if (!mem_checkprim(sizeof(POLY_G3), face->numFaceVertices)) + return; + // Draw the face as a triangle strip const SVECTOR *v0, *v1, *v2; const SVECTOR *head = vecs; @@ -130,9 +133,6 @@ static INLINE void drawface_triangle_strip(const ps1bsp_face_t *face, SVECTOR *v // Draw a flat-shaded untextured colored triangle POLY_G3 *poly = (POLY_G3*)mem_prim(sizeof(POLY_G3)); - if (poly == NULL) - break; - setPolyG3(poly); gte_stsxy3_g3(poly); @@ -149,6 +149,9 @@ static INLINE void drawface_quad_strip(const ps1bsp_face_t *face, SVECTOR *vecs) { int p; + if (!mem_checkprim(sizeof(POLY_G4), face->numFaceVertices)) + return; + // Draw the face as a quad strip const SVECTOR *v0, *v1, *v2, *v3; const SVECTOR *head = vecs; @@ -180,9 +183,6 @@ static INLINE void drawface_quad_strip(const ps1bsp_face_t *face, SVECTOR *vecs) // Draw a flat-shaded untextured colored quad POLY_G4 *poly = (POLY_G4*)mem_prim(sizeof(POLY_G4)); - if (poly == NULL) - break; - setPolyG4(poly); gte_stsxy0(&poly->x0); gte_stsxy1(&poly->x1);