From 30eb0949c7d52c36f820fff20ba8fff2577e10ce Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 24 Jan 2025 17:08:10 +1100 Subject: [PATCH] Saturn: Implement primitive Z sorting --- src/Graphics_Saturn.c | 76 ++++++++++++++++++++++++++++++++++--------- src/_GraphicsBase.h | 5 ++- 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/Graphics_Saturn.c b/src/Graphics_Saturn.c index db40954fb..86b23aae4 100644 --- a/src/Graphics_Saturn.c +++ b/src/Graphics_Saturn.c @@ -10,10 +10,17 @@ #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 224 #define CMDS_COUNT 400 +#define HDR_CMDS 2 + +static struct { + vdp1_cmdt_t hdrs[HDR_CMDS]; + vdp1_cmdt_t list[CMDS_COUNT]; + vdp1_cmdt_t extra[1]; // extra room for 'end' command if needed +} cmds; +static uint16_t z_table[CMDS_COUNT]; +static int cmds_count, cmds_3DCount; static PackedCol clear_color; -static vdp1_cmdt_t cmdts_all[CMDS_COUNT]; -static int cmdts_count; static vdp1_vram_partitions_t _vdp1_vram_partitions; static void* tex_vram_addr; static void* tex_vram_cur; @@ -30,10 +37,11 @@ static CC_NOINLINE NextPrimitive_nomem(void) { return NULL; } -static vdp1_cmdt_t* NextPrimitive(void) { - if (cmdts_count >= CMDS_COUNT) return NextPrimitive_nomem(); +static vdp1_cmdt_t* NextPrimitive(uint16_t z) { + if (cmds_count >= CMDS_COUNT) return NextPrimitive_nomem(); - return &cmdts_all[cmdts_count++]; + z_table[cmds_count] = UInt16_MaxValue - z; + return &cmds.list[cmds_count++]; } static const vdp1_cmdt_draw_mode_t color_draw_mode = { @@ -502,7 +510,7 @@ static void DrawColouredQuads2D(int verticesCount, int startVertex) { points[3].x = Coloured2D_X(v[3].x); points[3].y = Coloured2D_Y(v[3].y); rgb1555_t color; color.raw = v->Col; - vdp1_cmdt_t* cmd = NextPrimitive(); + vdp1_cmdt_t* cmd = NextPrimitive(0); if (!cmd) return; vdp1_cmdt_polygon_set(cmd); @@ -526,7 +534,7 @@ static void DrawTexturedQuads2D(int verticesCount, int startVertex) { points[2].x = Textured2D_X(v[2].x); points[2].y = Textured2D_Y(v[2].y); points[3].x = Textured2D_X(v[3].x); points[3].y = Textured2D_Y(v[3].y); - vdp1_cmdt_t* cmd = NextPrimitive(); + vdp1_cmdt_t* cmd = NextPrimitive(0); if (!cmd) return; vdp1_cmdt_distorted_sprite_set(cmd); @@ -558,8 +566,9 @@ static void DrawColouredQuads3D(int verticesCount, int startVertex) { points[2].x = coords[2].x; points[2].y = coords[2].y; points[3].x = coords[3].x; points[3].y = coords[3].y; + int z = (coords[0].z + coords[1].z + coords[2].z + coords[3].z) >> 2; rgb1555_t color; color.raw = v->Col; - vdp1_cmdt_t* cmd = NextPrimitive(); + vdp1_cmdt_t* cmd = NextPrimitive(z); if (!cmd) return; vdp1_cmdt_polygon_set(cmd); @@ -588,7 +597,8 @@ static void DrawTexturedQuads3D(int verticesCount, int startVertex) { points[2].x = coords[2].x; points[2].y = coords[2].y; points[3].x = coords[3].x; points[3].y = coords[3].y; - vdp1_cmdt_t* cmd = NextPrimitive(); + int z = (coords[0].z + coords[1].z + coords[2].z + coords[3].z) >> 2; + vdp1_cmdt_t* cmd = NextPrimitive(z); if (!cmd) return; vdp1_cmdt_distorted_sprite_set(cmd); @@ -638,32 +648,55 @@ cc_bool Gfx_GetUIOptions(struct MenuOptionsScreen* s) { return false; } void Gfx_BeginFrame(void) { //Platform_LogConst("FRAME BEG"); - cmdts_count = 0; + cmds_count = 0; + cmds_3DCount = 0; static const int16_vec2_t system_clip_coord = { SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1 }; static const int16_vec2_t local_coord_center = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 }; - vdp1_cmdt_t* cmd; - cmd = NextPrimitive(); + cmd = &cmds.hdrs[0]; vdp1_cmdt_system_clip_coord_set(cmd); vdp1_cmdt_vtx_system_clip_coord_set(cmd, system_clip_coord); - cmd = NextPrimitive(); + cmd = &cmds.hdrs[1]; vdp1_cmdt_local_coord_set(cmd); vdp1_cmdt_vtx_local_coord_set(cmd, local_coord_center); } +static void SortCommands(int left, int right) { + vdp1_cmdt_t* values = cmds.list, value; + uint16_t* keys = z_table, key; + + while (left < right) { + int i = left, j = right; + int pivot = keys[(i + j) >> 1]; + + /* partition the list */ + while (i <= j) { + while (pivot > keys[i]) i++; + while (pivot < keys[j]) j--; + QuickSort_Swap_KV_Maybe(); + } + /* recurse into the smaller subset */ + QuickSort_Recurse(SortCommands) + } +} + void Gfx_EndFrame(void) { //Platform_LogConst("FRAME END"); vdp1_cmdt_t* cmd; - cmd = NextPrimitive(); + // TODO optimise Z sorting for 3D polygons + if (cmds_3DCount) SortCommands(0, cmds_3DCount - 1); + + cmd = NextPrimitive(UInt16_MaxValue); + if (!cmd) { cmd = &cmds.extra[0]; cmds_count++; } vdp1_cmdt_end_set(cmd); vdp1_cmdt_list_t cmdt_list; - cmdt_list.cmdts = cmdts_all; - cmdt_list.count = cmdts_count; + cmdt_list.cmdts = cmds.hdrs; + cmdt_list.count = HDR_CMDS + cmds_count; vdp1_sync_cmdt_list_put(&cmdt_list, 0); vdp1_sync_render(); @@ -689,4 +722,15 @@ void Gfx_GetApiInfo(cc_string* info) { } cc_bool Gfx_TryRestoreContext(void) { return true; } + +void Gfx_Begin2D(int width, int height) { + Gfx_SetAlphaBlending(true); + gfx_rendering2D = true; + cmds_3DCount = cmds_count; +} + +void Gfx_End2D(void) { + Gfx_SetAlphaBlending(false); + gfx_rendering2D = false; +} #endif diff --git a/src/_GraphicsBase.h b/src/_GraphicsBase.h index a09d56ed5..b509411a2 100644 --- a/src/_GraphicsBase.h +++ b/src/_GraphicsBase.h @@ -237,8 +237,11 @@ void Gfx_Make2DQuad(const struct Texture* tex, PackedCol color, struct VertexTex *vertices = v; } -#ifndef CC_BUILD_PS1 +#if defined CC_BUILD_PS1 || defined CC_BUILD_SATURN + /* These GFX backends have specialised implementations */ +#else static cc_bool gfx_hadFog; + void Gfx_Begin2D(int width, int height) { struct Matrix ortho; /* intentionally biased more towards positive Z to reduce 2D clipping issues on the DS */