From d1698e980eee889efe0cf5c22eead9aa80142138 Mon Sep 17 00:00:00 2001 From: aglab2 Date: Fri, 27 Dec 2024 12:02:37 +0800 Subject: [PATCH 1/5] Introduce batching engine and shadow batching --- bin/segment2.c | 14 +- include/sm64.h | 33 +++++ src/engine/batch_list.c | 33 +++++ src/engine/batch_list.h | 20 +++ src/engine/graph_node.c | 8 ++ src/engine/graph_node.h | 29 +++- src/game/rendering_graph_node.c | 237 ++++++++++++++++++++++---------- src/game/segment2.h | 1 + src/game/shadow.c | 7 +- 9 files changed, 294 insertions(+), 88 deletions(-) create mode 100644 src/engine/batch_list.c create mode 100644 src/engine/batch_list.h diff --git a/bin/segment2.c b/bin/segment2.c index 55695ccf3c..4d02c2b8cf 100644 --- a/bin/segment2.c +++ b/bin/segment2.c @@ -2769,6 +2769,14 @@ const Gfx dl_shadow_begin[] = { gsSPEndDisplayList(), }; +const Gfx dl_shadow_end[] = { + gsDPPipeSync(), + gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF), + gsSPSetGeometryMode(G_LIGHTING | G_CULL_BACK), + gsDPSetCombineMode(G_CC_SHADE, G_CC_SHADE), + gsSPEndDisplayList(), +}; + #ifdef HD_SHADOWS const Gfx dl_shadow_circle[] = { gsSPDisplayList(dl_shadow_begin), @@ -2810,13 +2818,9 @@ static const Vtx vertex_shadow[] = { }; // 0x02014638 - 0x02014660 -const Gfx dl_shadow_end[] = { +const Gfx dl_shadow_tris[] = { gsSPVertex(vertex_shadow, 4, 0), gsSP2Triangles( 0, 2, 1, 0x0, 1, 2, 3, 0x0), - gsDPPipeSync(), - gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF), - gsSPSetGeometryMode(G_LIGHTING | G_CULL_BACK), - gsDPSetCombineMode(G_CC_SHADE, G_CC_SHADE), gsSPEndDisplayList(), }; diff --git a/include/sm64.h b/include/sm64.h index f9c44cd092..787a3433b8 100644 --- a/include/sm64.h +++ b/include/sm64.h @@ -70,12 +70,45 @@ enum RenderLayers { LAYER_OCCLUDE_SILHOUETTE_OPAQUE, LAYER_OCCLUDE_SILHOUETTE_ALPHA, #endif + LAYER_CLD, LAYER_TRANSPARENT_DECAL, LAYER_TRANSPARENT, LAYER_TRANSPARENT_INTER, LAYER_COUNT }; +enum LayerBatches { + LAYER_OPAQUE_BATCHES_BASE = 0, + LAYER_OPAQUE_CORKBOX = LAYER_OPAQUE_BATCHES_BASE, + LAYER_OPAQUE_BATCHES_COUNT, + + LAYER_ALPHA_BATCHES_BASE = 0, + // coin frames batches, it goes 0, 1, 2, 3, 4, 3, 2, 1 + LAYER_ALPHA_COINS_FIRST = LAYER_ALPHA_BATCHES_BASE, + LAYER_ALPHA_COINS_LAST = LAYER_ALPHA_COINS_FIRST + 4, + LAYER_ALPHA_SMOKE, + LAYER_ALPHA_BATCHES_COUNT, + + LAYER_TRANSPARENT_BATCHES_BASE = 0, + LAYER_TRANSPARENT_SMOKE = LAYER_TRANSPARENT_BATCHES_BASE, + LAYER_TRANSPARENT_MIST, + LAYER_TRANSPARENT_RED_FLAMES_FIRST, + LAYER_TRANSPARENT_RED_FLAMES_LAST = LAYER_TRANSPARENT_RED_FLAMES_FIRST + 7, + LAYER_TRANSPARENT_BLUE_FLAMES_FIRST, + LAYER_TRANSPARENT_BLUE_FLAMES_LAST = LAYER_TRANSPARENT_BLUE_FLAMES_FIRST + 7, + LAYER_TRANSPARENT_BATCHES_COUNT, + + LAYER_TRANSPARENT_DECAL_BATCHES_BASE = 0, + LAYER_TRANSPARENT_DECAL_SHADOW_CIRCLE = LAYER_TRANSPARENT_DECAL_BATCHES_BASE, + LAYER_TRANSPARENT_DECAL_SHADOW_SQUARE, + LAYER_TRANSPARENT_DECAL_BATCHES_COUNT, + + LAYER_CLD_BATCHES_BASE = 0, + LAYER_CLD_SHADOW_CIRCLE = LAYER_CLD_BATCHES_BASE, + LAYER_CLD_SHADOW_SQUARE, + LAYER_CLD_BATCHES_COUNT, +}; + #define LAYER_FIRST LAYER_FORCE #define LAYER_LAST (LAYER_COUNT - 1) diff --git a/src/engine/batch_list.c b/src/engine/batch_list.c new file mode 100644 index 0000000000..36d93c8a3e --- /dev/null +++ b/src/engine/batch_list.c @@ -0,0 +1,33 @@ +#include "batch_list.h" + +#include "game/segment2.h" + +static inline struct BatchArray* batch_array_alloc(struct AllocOnlyPool *pool, int count) +{ + struct BatchArray* batches = alloc_only_pool_alloc(pool, sizeof(struct BatchArray) + count * sizeof(struct Batch)); + batches->count = count; + return batches; +} + +static inline void batch_setup(struct BatchArray* arr, int idx, const void* start, const void* end) +{ + struct Batch* batch = &arr->batches[idx]; + batch->startDl = start; + batch->endDl = end; +} + +struct BatchArray* batch_list_objects_alloc_xlu_decal(struct AllocOnlyPool *pool) +{ + struct BatchArray* arr = batch_array_alloc(pool, LAYER_TRANSPARENT_DECAL_BATCHES_COUNT); + batch_setup(arr, LAYER_TRANSPARENT_DECAL_SHADOW_CIRCLE, dl_shadow_circle, dl_shadow_end); + batch_setup(arr, LAYER_TRANSPARENT_DECAL_SHADOW_SQUARE, dl_shadow_square, dl_shadow_end); + return arr; +} + +struct BatchArray* batch_list_objects_alloc_cld(struct AllocOnlyPool *pool) +{ + struct BatchArray* arr = batch_array_alloc(pool, LAYER_CLD_BATCHES_COUNT); + batch_setup(arr, LAYER_CLD_SHADOW_CIRCLE, dl_shadow_circle, dl_shadow_end); + batch_setup(arr, LAYER_CLD_SHADOW_SQUARE, dl_shadow_square, dl_shadow_end); + return arr; +} diff --git a/src/engine/batch_list.h b/src/engine/batch_list.h new file mode 100644 index 0000000000..6b88c01a1f --- /dev/null +++ b/src/engine/batch_list.h @@ -0,0 +1,20 @@ +#pragma once + +#include "sm64.h" +#include "engine/graph_node.h" + +struct BatchArray* batch_list_objects_alloc_xlu_decal(struct AllocOnlyPool *pool); +struct BatchArray* batch_list_objects_alloc_cld(struct AllocOnlyPool *pool); + +static inline struct BatchArray* batch_list_objects_alloc(struct AllocOnlyPool *pool, enum RenderLayers layer) +{ + switch (layer) + { + case LAYER_TRANSPARENT_DECAL: + return batch_list_objects_alloc_xlu_decal(pool); + case LAYER_CLD: + return batch_list_objects_alloc_cld(pool); + default: + return 0; + } +} diff --git a/src/engine/graph_node.c b/src/engine/graph_node.c index 62fccb8812..95796090fb 100644 --- a/src/engine/graph_node.c +++ b/src/engine/graph_node.c @@ -8,6 +8,7 @@ #include "game/rendering_graph_node.h" #include "game/area.h" #include "geo_layout.h" +#include "batch_list.h" /** * Initialize a geo node with a given type. Sets all links such that there @@ -122,6 +123,13 @@ struct GraphNodeMasterList *init_graph_node_master_list(struct AllocOnlyPool *po if (on) { graphNode->node.flags |= GRAPH_RENDER_Z_BUFFER; + for (int layer = 0; layer < LAYER_COUNT; layer++) { + graphNode->layers[layer].objects = batch_list_objects_alloc(pool, layer); + } + } else { + for (int layer = 0; layer < LAYER_COUNT; layer++) { + graphNode->layers[layer].objects = NULL; + } } } diff --git a/src/engine/graph_node.h b/src/engine/graph_node.h index bccb8f2b3a..5aa917758d 100644 --- a/src/engine/graph_node.h +++ b/src/engine/graph_node.h @@ -140,15 +140,38 @@ struct DisplayListNode { struct DisplayListNode *next; }; +struct DisplayListHead { + struct DisplayListNode* head; + struct DisplayListNode* tail; +}; + +struct Batch { + // filled in when master node is created + const void* startDl; + const void* endDl; + + // filled in rendering of the master list + struct DisplayListHead list; +}; + +struct BatchArray { + int count; + struct Batch batches[0]; +}; + +struct MasterLayer { + struct DisplayListHead list; + struct BatchArray* objects; +}; + /** GraphNode that manages the 8 top-level display lists that will be drawn * Each list has its own render mode, so for example water is drawn in a * different master list than opaque objects. * It also sets the z-buffer on before rendering and off after. */ struct GraphNodeMasterList { - /*0x00*/ struct GraphNode node; - /*0x14*/ struct DisplayListNode *listHeads[LAYER_COUNT]; - /*0x34*/ struct DisplayListNode *listTails[LAYER_COUNT]; + struct GraphNode node; + struct MasterLayer layers[LAYER_COUNT]; }; /** Simply used as a parent to group multiple children. diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index cb0d62cbbe..80897fe869 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -80,7 +80,7 @@ s16 *gCurrAnimData; struct AllocOnlyPool *gDisplayListHeap; /* Rendermode settings for cycle 1 for all 8 or 13 layers. */ -struct RenderModeContainer renderModeTable_1Cycle[2] = { +static const struct RenderModeContainer renderModeTable_1Cycle[2] = { [RENDER_NO_ZB] = { { [LAYER_FORCE] = G_RM_OPA_SURF, [LAYER_OPAQUE] = G_RM_AA_OPA_SURF, @@ -94,6 +94,7 @@ struct RenderModeContainer renderModeTable_1Cycle[2] = { [LAYER_OCCLUDE_SILHOUETTE_OPAQUE] = G_RM_AA_OPA_SURF, [LAYER_OCCLUDE_SILHOUETTE_ALPHA] = G_RM_AA_TEX_EDGE, #endif + [LAYER_CLD] = G_RM_CLD_SURF, [LAYER_TRANSPARENT_DECAL] = G_RM_AA_XLU_SURF, [LAYER_TRANSPARENT] = G_RM_AA_XLU_SURF, [LAYER_TRANSPARENT_INTER] = G_RM_AA_XLU_SURF, @@ -111,13 +112,14 @@ struct RenderModeContainer renderModeTable_1Cycle[2] = { [LAYER_OCCLUDE_SILHOUETTE_OPAQUE] = G_RM_AA_ZB_OPA_SURF, [LAYER_OCCLUDE_SILHOUETTE_ALPHA] = G_RM_AA_ZB_TEX_EDGE, #endif + [LAYER_CLD] = G_RM_ZB_CLD_SURF, [LAYER_TRANSPARENT_DECAL] = G_RM_AA_ZB_XLU_DECAL, [LAYER_TRANSPARENT] = G_RM_AA_ZB_XLU_SURF, [LAYER_TRANSPARENT_INTER] = G_RM_AA_ZB_XLU_INTER, } } }; /* Rendermode settings for cycle 2 for all 13 layers. */ -struct RenderModeContainer renderModeTable_2Cycle[2] = { +static const struct RenderModeContainer renderModeTable_2Cycle[2] = { [RENDER_NO_ZB] = { { [LAYER_FORCE] = G_RM_OPA_SURF2, [LAYER_OPAQUE] = G_RM_AA_OPA_SURF2, @@ -131,6 +133,7 @@ struct RenderModeContainer renderModeTable_2Cycle[2] = { [LAYER_OCCLUDE_SILHOUETTE_OPAQUE] = G_RM_AA_OPA_SURF2, [LAYER_OCCLUDE_SILHOUETTE_ALPHA] = G_RM_AA_TEX_EDGE2, #endif + [LAYER_CLD] = G_RM_CLD_SURF2, [LAYER_TRANSPARENT_DECAL] = G_RM_AA_XLU_SURF2, [LAYER_TRANSPARENT] = G_RM_AA_XLU_SURF2, [LAYER_TRANSPARENT_INTER] = G_RM_AA_XLU_SURF2, @@ -148,6 +151,7 @@ struct RenderModeContainer renderModeTable_2Cycle[2] = { [LAYER_OCCLUDE_SILHOUETTE_OPAQUE] = G_RM_AA_ZB_OPA_SURF2, [LAYER_OCCLUDE_SILHOUETTE_ALPHA] = G_RM_AA_ZB_TEX_EDGE2, #endif + [LAYER_CLD] = G_RM_ZB_CLD_SURF2, [LAYER_TRANSPARENT_DECAL] = G_RM_AA_ZB_XLU_DECAL2, [LAYER_TRANSPARENT] = G_RM_AA_ZB_XLU_SURF2, [LAYER_TRANSPARENT_INTER] = G_RM_AA_ZB_XLU_INTER2, @@ -248,6 +252,83 @@ Mtx identityMatrixWorldScale = {{ 0x00000000, LOWER_FIXED(1.0f) << 0} }}; +static void lists_render(Gfx **ptempGfxHead, struct DisplayListNode* currList) +{ +#define tempGfxHead (*ptempGfxHead) + do { + gSPMatrix(tempGfxHead++, VIRTUAL_TO_PHYSICAL(currList->transform), (G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH)); + gSPDisplayList(tempGfxHead++, currList->displayList); + currList = currList->next; + } while (currList != NULL); +#undef tempGfxHead +} + +static int batches_render(Gfx **ptempGfxHead, struct BatchArray* arr, u32 mode1, u32 mode2) +{ +#define tempGfxHead (*ptempGfxHead) + int amountRendered = 0; + + // Some "fun" display lists before may decide to change the render mode so we need to reset it. + // Notably this happens when env effects that change render mode and do not revert it. + gDPSetRenderMode(tempGfxHead++, mode1, mode2); + + for (int batch = 0; batch < arr->count; batch++) { + struct Batch* batches = &arr->batches[batch]; + if (!batches->list.head) + continue; + + gSPDisplayList(tempGfxHead++, batches->startDl); + amountRendered++; + lists_render(&tempGfxHead, batches->list.head); + gSPDisplayList(tempGfxHead++, batches->endDl); + } +#undef tempGfxHead + + return amountRendered; +} + +static void main_render(Gfx **ptempGfxHead, struct DisplayListNode* currList, u32 mode1, u32 mode2, int phaseIndex) +{ + (void)phaseIndex; +#define tempGfxHead (*ptempGfxHead) +#if defined(DISABLE_AA) || !SILHOUETTE + // Set the render mode for the current layer. + gDPSetRenderMode(tempGfxHead++, mode1, mode2); +#else + if (phaseIndex == RENDER_PHASE_NON_SILHOUETTE) { + // To properly cover the silhouette, disable AA. + // The silhouette model does not have AA due to the hack used to prevent triangle overlap. + gDPSetRenderMode(tempGfxHead++, mode1 & ~IM_RD, mode2 & ~IM_RD); + } else { + // Set the render mode for the current dl. + gDPSetRenderMode(tempGfxHead++, mode1, mode2); + } +#endif + // Iterate through all the displaylists on the current layer. + while (currList != NULL) { + // Add the display list's transformation to the master list. + gSPMatrix(tempGfxHead++, VIRTUAL_TO_PHYSICAL(currList->transform), + (G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH)); +#if SILHOUETTE + if (phaseIndex == RENDER_PHASE_SILHOUETTE) { + // Add the current display list to the master list, with silhouette F3D. + gSPDisplayList(tempGfxHead++, dl_silhouette_begin); + gSPDisplayList(tempGfxHead++, currList->displayList); + gSPDisplayList(tempGfxHead++, dl_silhouette_end); + } else { + // Add the current display list to the master list. + gSPDisplayList(tempGfxHead++, currList->displayList); + } +#else + // Add the current display list to the master list. + gSPDisplayList(tempGfxHead++, currList->displayList); +#endif + // Move to the next DisplayListNode. + currList = currList->next; + } +#undef tempGfxHead +} + /** * Process a master list node. This has been modified, so now it runs twice, for each microcode. * It iterates through the first 5 layers of if the first index using F3DLX2.Rej, then it switches @@ -257,15 +338,14 @@ Mtx identityMatrixWorldScale = {{ */ void geo_process_master_list_sub(struct GraphNodeMasterList *node) { struct RenderPhase *renderPhase; - struct DisplayListNode *currList; s32 currLayer = LAYER_FIRST; s32 startLayer = LAYER_FIRST; s32 endLayer = LAYER_LAST; s32 phaseIndex = RENDER_PHASE_FIRST; s32 enableZBuffer = (node->node.flags & GRAPH_RENDER_Z_BUFFER) != 0; s32 finalPhase = enableZBuffer ? RENDER_PHASE_END : 1; - struct RenderModeContainer *mode1List = &renderModeTable_1Cycle[enableZBuffer]; - struct RenderModeContainer *mode2List = &renderModeTable_2Cycle[enableZBuffer]; + const struct RenderModeContainer *mode1List = &renderModeTable_1Cycle[enableZBuffer]; + const struct RenderModeContainer *mode2List = &renderModeTable_2Cycle[enableZBuffer]; Gfx *tempGfxHead = gDisplayListHead; // Loop through the render phases @@ -284,46 +364,17 @@ void geo_process_master_list_sub(struct GraphNodeMasterList *node) { } // Iterate through the layers on the current render phase. for (currLayer = startLayer; currLayer <= endLayer; currLayer++) { - // Set 'currList' to the first DisplayListNode on the current layer. - currList = node->listHeads[currLayer]; -#if defined(DISABLE_AA) || !SILHOUETTE - // Set the render mode for the current layer. - gDPSetRenderMode(tempGfxHead++, mode1List->modes[currLayer], - mode2List->modes[currLayer]); -#else - if (phaseIndex == RENDER_PHASE_NON_SILHOUETTE) { - // To properly cover the silhouette, disable AA. - // The silhouette model does not have AA due to the hack used to prevent triangle overlap. - gDPSetRenderMode(tempGfxHead++, (mode1List->modes[currLayer] & ~IM_RD), - (mode2List->modes[currLayer] & ~IM_RD)); - } else { - // Set the render mode for the current dl. - gDPSetRenderMode(tempGfxHead++, mode1List->modes[currLayer], - mode2List->modes[currLayer]); - } -#endif - // Iterate through all the displaylists on the current layer. - while (currList != NULL) { - // Add the display list's transformation to the master list. - gSPMatrix(tempGfxHead++, VIRTUAL_TO_PHYSICAL(currList->transform), - (G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH)); -#if SILHOUETTE - if (phaseIndex == RENDER_PHASE_SILHOUETTE) { - // Add the current display list to the master list, with silhouette F3D. - gSPDisplayList(tempGfxHead++, dl_silhouette_begin); - gSPDisplayList(tempGfxHead++, currList->displayList); - gSPDisplayList(tempGfxHead++, dl_silhouette_end); - } else { - // Add the current display list to the master list. - gSPDisplayList(tempGfxHead++, currList->displayList); - } -#else - // Add the current display list to the master list. - gSPDisplayList(tempGfxHead++, currList->displayList); -#endif - // Move to the next DisplayListNode. - currList = currList->next; - } + struct MasterLayer *masterLayer = &node->layers[currLayer]; + u32 mode1 = mode1List->modes[currLayer]; + u32 mode2 = mode2List->modes[currLayer]; + + struct DisplayListNode *currList = masterLayer->list.head; + if (currList) + main_render(&tempGfxHead, currList, mode1, mode2, phaseIndex); + + struct BatchArray *objects = masterLayer->objects; + if (objects) + batches_render(&tempGfxHead, objects, mode1, mode2); } } @@ -342,16 +393,23 @@ void geo_process_master_list_sub(struct GraphNodeMasterList *node) { gDisplayListHead = tempGfxHead; } -/** - * Appends the display list to one of the master lists based on the layer - * parameter. Look at the RenderModeContainer struct to see the corresponding - * render modes of layers. - */ -void geo_append_display_list(void *displayList, s32 layer) { -#ifdef F3DEX_GBI_2 - gSPLookAt(gDisplayListHead++, gCurLookAt); -#endif +static void append_dl(struct DisplayListHead* list, void* dl) +{ + struct DisplayListNode *listNode = alloc_only_pool_alloc(gDisplayListHeap, sizeof(struct DisplayListNode)); + + listNode->transform = gMatStackFixed[gMatStackIndex]; + listNode->displayList = dl; + listNode->next = NULL; + if (list->head == NULL) { + list->head = listNode; + } else { + list->tail->next = listNode; + } + list->tail = listNode; +} + #if SILHOUETTE +static inline int mangle_silhouette_layer(int layer) { if (gCurGraphNodeObject != NULL) { if (gCurGraphNodeObject->node.flags & GRAPH_RENDER_SILHOUETTE) { switch (layer) { @@ -366,21 +424,36 @@ void geo_append_display_list(void *displayList, s32 layer) { } } } -#endif // F3DEX_GBI_2 || SILHOUETTE - if (gCurGraphNodeMasterList != NULL) { - struct DisplayListNode *listNode = - alloc_only_pool_alloc(gDisplayListHeap, sizeof(struct DisplayListNode)); - - listNode->transform = gMatStackFixed[gMatStackIndex]; - listNode->displayList = displayList; - listNode->next = NULL; - if (gCurGraphNodeMasterList->listHeads[layer] == NULL) { - gCurGraphNodeMasterList->listHeads[layer] = listNode; - } else { - gCurGraphNodeMasterList->listTails[layer]->next = listNode; - } - gCurGraphNodeMasterList->listTails[layer] = listNode; - } + + return layer; +} +#else +static inline int mangle_silhouette_layer(int layer) { + return layer; +} +#endif + +/** + * Appends the display list to one of the master lists based on the layer + * parameter. Look at the RenderModeContainer struct to see the corresponding + * render modes of layers. + */ +void geo_append_display_list(void *displayList, s32 layer) { +#ifdef F3DEX_GBI_2 + gSPLookAt(gDisplayListHead++, gCurLookAt); +#endif + layer = mangle_silhouette_layer(layer); + struct MasterLayer* masterLayer = &gCurGraphNodeMasterList->layers[layer]; + append_dl(&masterLayer->list, displayList); +} + +static void geo_append_batched_display_list(void *displayList, enum RenderLayers layer, enum LayerBatches batch) { +#ifdef F3DEX_GBI_2 + gSPLookAt(gDisplayListHead++, gCurLookAt); +#endif + layer = mangle_silhouette_layer(layer); + struct MasterLayer* masterLayer = &gCurGraphNodeMasterList->layers[layer]; + append_dl(&masterLayer->objects->batches[batch].list, displayList); } static void inc_mat_stack() { @@ -400,6 +473,15 @@ static void append_dl_and_return(struct GraphNodeDisplayList *node) { gMatStackIndex--; } +static void batches_clean(struct BatchArray* arr) { + if (!arr) + return; + + for (int batch = 0; batch < arr->count; batch++) { + arr->batches[batch].list.head = NULL; + } +} + /** * Process the master list node. */ @@ -409,7 +491,9 @@ void geo_process_master_list(struct GraphNodeMasterList *node) { if (gCurGraphNodeMasterList == NULL && node->node.children != NULL) { gCurGraphNodeMasterList = node; for (layer = LAYER_FIRST; layer < LAYER_COUNT; layer++) { - node->listHeads[layer] = NULL; + struct MasterLayer* masterLayer = &node->layers[layer]; + masterLayer->list.head = NULL; + batches_clean(masterLayer->objects); } geo_process_node_and_siblings(node->node.children); geo_process_master_list_sub(gCurGraphNodeMasterList); @@ -903,10 +987,15 @@ void geo_process_shadow(struct GraphNodeShadow *node) { gCurrShadow.floorNormal, shadowPos, gCurrShadow.scale, gCurGraphNodeObject->angle[1]); inc_mat_stack(); - geo_append_display_list( - (void *) VIRTUAL_TO_PHYSICAL(shadowList), - gCurrShadow.isDecal ? LAYER_TRANSPARENT_DECAL : LAYER_TRANSPARENT - ); + + s32 layer = gCurrShadow.isDecal ? LAYER_TRANSPARENT_DECAL : LAYER_CLD; + s32 batch; + if (node->shadowType == SHADOW_CIRCLE) { + batch = gCurrShadow.isDecal ? LAYER_TRANSPARENT_DECAL_SHADOW_CIRCLE : LAYER_CLD_SHADOW_CIRCLE; + } else { + batch = gCurrShadow.isDecal ? LAYER_TRANSPARENT_DECAL_SHADOW_SQUARE : LAYER_CLD_SHADOW_SQUARE; + } + geo_append_batched_display_list((void *) VIRTUAL_TO_PHYSICAL(shadowList), layer, batch); gMatStackIndex--; } diff --git a/src/game/segment2.h b/src/game/segment2.h index 239e213958..0ab6867992 100644 --- a/src/game/segment2.h +++ b/src/game/segment2.h @@ -32,6 +32,7 @@ extern Gfx dl_shadow_circle[]; extern Gfx dl_shadow_square[]; extern Gfx dl_shadow_4_verts[]; extern Gfx dl_shadow_end[]; +extern Gfx dl_shadow_tris[]; extern Gfx dl_skybox_begin[]; extern Gfx dl_skybox_tile_tex_settings[]; extern Gfx dl_skybox_end[]; diff --git a/src/game/shadow.c b/src/game/shadow.c index 001b01914e..24b181d054 100644 --- a/src/game/shadow.c +++ b/src/game/shadow.c @@ -169,13 +169,8 @@ void correct_lava_shadow_height(f32 *floorHeight) { * Uses environment alpha for shadow solidity. */ static void add_shadow_to_display_list(Gfx *displayListHead, s8 shadowType) { - if (shadowType == SHADOW_CIRCLE) { - gSPDisplayList(displayListHead++, dl_shadow_circle); - } else { - gSPDisplayList(displayListHead++, dl_shadow_square); - } gDPSetEnvColor(displayListHead++, 255, 255, 255, s->solidity); - gSPDisplayList(displayListHead++, dl_shadow_end); + gSPDisplayList(displayListHead++, dl_shadow_tris); gSPEndDisplayList(displayListHead); } From 9c49eaa6f7849076bf7768080ef9bcd5dc3616dd Mon Sep 17 00:00:00 2001 From: aglab2 Date: Fri, 27 Dec 2024 12:34:14 +0800 Subject: [PATCH 2/5] Rename batch ids for easier readability --- include/sm64.h | 59 +++++++++++++++++---------------- src/engine/batch_list.c | 12 +++---- src/game/rendering_graph_node.c | 6 ++-- 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/include/sm64.h b/include/sm64.h index 787a3433b8..b0663d756a 100644 --- a/include/sm64.h +++ b/include/sm64.h @@ -77,36 +77,39 @@ enum RenderLayers { LAYER_COUNT }; -enum LayerBatches { - LAYER_OPAQUE_BATCHES_BASE = 0, - LAYER_OPAQUE_CORKBOX = LAYER_OPAQUE_BATCHES_BASE, - LAYER_OPAQUE_BATCHES_COUNT, +enum BatchOpaque { + BATCH_OPAQUE_CORKBOX, + BATCH_OPAQUE_COUNT, +}; - LAYER_ALPHA_BATCHES_BASE = 0, +enum BatchAlpha { // coin frames batches, it goes 0, 1, 2, 3, 4, 3, 2, 1 - LAYER_ALPHA_COINS_FIRST = LAYER_ALPHA_BATCHES_BASE, - LAYER_ALPHA_COINS_LAST = LAYER_ALPHA_COINS_FIRST + 4, - LAYER_ALPHA_SMOKE, - LAYER_ALPHA_BATCHES_COUNT, - - LAYER_TRANSPARENT_BATCHES_BASE = 0, - LAYER_TRANSPARENT_SMOKE = LAYER_TRANSPARENT_BATCHES_BASE, - LAYER_TRANSPARENT_MIST, - LAYER_TRANSPARENT_RED_FLAMES_FIRST, - LAYER_TRANSPARENT_RED_FLAMES_LAST = LAYER_TRANSPARENT_RED_FLAMES_FIRST + 7, - LAYER_TRANSPARENT_BLUE_FLAMES_FIRST, - LAYER_TRANSPARENT_BLUE_FLAMES_LAST = LAYER_TRANSPARENT_BLUE_FLAMES_FIRST + 7, - LAYER_TRANSPARENT_BATCHES_COUNT, - - LAYER_TRANSPARENT_DECAL_BATCHES_BASE = 0, - LAYER_TRANSPARENT_DECAL_SHADOW_CIRCLE = LAYER_TRANSPARENT_DECAL_BATCHES_BASE, - LAYER_TRANSPARENT_DECAL_SHADOW_SQUARE, - LAYER_TRANSPARENT_DECAL_BATCHES_COUNT, - - LAYER_CLD_BATCHES_BASE = 0, - LAYER_CLD_SHADOW_CIRCLE = LAYER_CLD_BATCHES_BASE, - LAYER_CLD_SHADOW_SQUARE, - LAYER_CLD_BATCHES_COUNT, + BATCH_ALPHA_COINS_FIRST, + BATCH_ALPHA_COINS_LAST = BATCH_ALPHA_COINS_FIRST + 4, + BATCH_ALPHA_SMOKE, + BATCH_ALPHA_COUNT, +}; + +enum BatchTransparent { + BATCH_TRANSPARENT_SMOKE, + BATCH_TRANSPARENT_MIST, + BATCH_TRANSPARENT_RED_FLAMES_FIRST, + BATCH_TRANSPARENT_RED_FLAMES_LAST = BATCH_TRANSPARENT_RED_FLAMES_FIRST + 7, + BATCH_TRANSPARENT_BLUE_FLAMES_FIRST, + BATCH_TRANSPARENT_BLUE_FLAMES_LAST = BATCH_TRANSPARENT_BLUE_FLAMES_FIRST + 7, + BATCH_TRANSPARENT_COUNT, +}; + +enum BatchTransparentDecal { + BATCH_TRANSPARENT_DECAL_SHADOW_CIRCLE, + BATCH_TRANSPARENT_DECAL_SHADOW_SQUARE, + BATCH_TRANSPARENT_DECAL_COUNT, +}; + +enum BatchCld { + BATCH_CLD_SHADOW_CIRCLE, + BATCH_CLD_SHADOW_SQUARE, + BATCH_CLD_COUNT, }; #define LAYER_FIRST LAYER_FORCE diff --git a/src/engine/batch_list.c b/src/engine/batch_list.c index 36d93c8a3e..5f8c327f1d 100644 --- a/src/engine/batch_list.c +++ b/src/engine/batch_list.c @@ -18,16 +18,16 @@ static inline void batch_setup(struct BatchArray* arr, int idx, const void* star struct BatchArray* batch_list_objects_alloc_xlu_decal(struct AllocOnlyPool *pool) { - struct BatchArray* arr = batch_array_alloc(pool, LAYER_TRANSPARENT_DECAL_BATCHES_COUNT); - batch_setup(arr, LAYER_TRANSPARENT_DECAL_SHADOW_CIRCLE, dl_shadow_circle, dl_shadow_end); - batch_setup(arr, LAYER_TRANSPARENT_DECAL_SHADOW_SQUARE, dl_shadow_square, dl_shadow_end); + struct BatchArray* arr = batch_array_alloc(pool, BATCH_TRANSPARENT_DECAL_COUNT); + batch_setup(arr, BATCH_TRANSPARENT_DECAL_SHADOW_CIRCLE, dl_shadow_circle, dl_shadow_end); + batch_setup(arr, BATCH_TRANSPARENT_DECAL_SHADOW_SQUARE, dl_shadow_square, dl_shadow_end); return arr; } struct BatchArray* batch_list_objects_alloc_cld(struct AllocOnlyPool *pool) { - struct BatchArray* arr = batch_array_alloc(pool, LAYER_CLD_BATCHES_COUNT); - batch_setup(arr, LAYER_CLD_SHADOW_CIRCLE, dl_shadow_circle, dl_shadow_end); - batch_setup(arr, LAYER_CLD_SHADOW_SQUARE, dl_shadow_square, dl_shadow_end); + struct BatchArray* arr = batch_array_alloc(pool, BATCH_CLD_COUNT); + batch_setup(arr, BATCH_CLD_SHADOW_CIRCLE, dl_shadow_circle, dl_shadow_end); + batch_setup(arr, BATCH_CLD_SHADOW_SQUARE, dl_shadow_square, dl_shadow_end); return arr; } diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 80897fe869..c92dc42378 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -447,7 +447,7 @@ void geo_append_display_list(void *displayList, s32 layer) { append_dl(&masterLayer->list, displayList); } -static void geo_append_batched_display_list(void *displayList, enum RenderLayers layer, enum LayerBatches batch) { +static void geo_append_batched_display_list(void *displayList, enum RenderLayers layer, s32 batch) { #ifdef F3DEX_GBI_2 gSPLookAt(gDisplayListHead++, gCurLookAt); #endif @@ -991,9 +991,9 @@ void geo_process_shadow(struct GraphNodeShadow *node) { s32 layer = gCurrShadow.isDecal ? LAYER_TRANSPARENT_DECAL : LAYER_CLD; s32 batch; if (node->shadowType == SHADOW_CIRCLE) { - batch = gCurrShadow.isDecal ? LAYER_TRANSPARENT_DECAL_SHADOW_CIRCLE : LAYER_CLD_SHADOW_CIRCLE; + batch = gCurrShadow.isDecal ? BATCH_TRANSPARENT_DECAL_SHADOW_CIRCLE : BATCH_CLD_SHADOW_CIRCLE; } else { - batch = gCurrShadow.isDecal ? LAYER_TRANSPARENT_DECAL_SHADOW_SQUARE : LAYER_CLD_SHADOW_SQUARE; + batch = gCurrShadow.isDecal ? BATCH_TRANSPARENT_DECAL_SHADOW_SQUARE : BATCH_CLD_SHADOW_SQUARE; } geo_append_batched_display_list((void *) VIRTUAL_TO_PHYSICAL(shadowList), layer, batch); From 1c69014f515997b61cbaa7bddad576620c3fb170 Mon Sep 17 00:00:00 2001 From: aglab2 Date: Fri, 27 Dec 2024 20:04:39 +0800 Subject: [PATCH 3/5] Fixed various nits in shadow batching --- bin/segment2.c | 4 +++- include/sm64.h | 23 ----------------------- src/engine/batch_list.c | 12 ++++-------- src/engine/batch_list.h | 6 ++---- src/engine/graph_node.h | 6 +++--- src/game/rendering_graph_node.c | 14 +++++--------- src/game/shadow.c | 2 +- 7 files changed, 18 insertions(+), 49 deletions(-) diff --git a/bin/segment2.c b/bin/segment2.c index 4d02c2b8cf..0427ff2895 100644 --- a/bin/segment2.c +++ b/bin/segment2.c @@ -2761,10 +2761,12 @@ const Gfx dl_draw_quad_verts_4567[] = { gsSPEndDisplayList(), }; +#define G_CC_SHADOW TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0 + const Gfx dl_shadow_begin[] = { gsDPPipeSync(), gsSPClearGeometryMode(G_LIGHTING | G_CULL_BACK), - gsDPSetCombineMode(G_CC_MODULATEIFADEA, G_CC_MODULATEIFADEA), + gsDPSetCombineMode(G_CC_SHADOW, G_CC_SHADOW), gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON), gsSPEndDisplayList(), }; diff --git a/include/sm64.h b/include/sm64.h index b0663d756a..4f405cb857 100644 --- a/include/sm64.h +++ b/include/sm64.h @@ -77,29 +77,6 @@ enum RenderLayers { LAYER_COUNT }; -enum BatchOpaque { - BATCH_OPAQUE_CORKBOX, - BATCH_OPAQUE_COUNT, -}; - -enum BatchAlpha { - // coin frames batches, it goes 0, 1, 2, 3, 4, 3, 2, 1 - BATCH_ALPHA_COINS_FIRST, - BATCH_ALPHA_COINS_LAST = BATCH_ALPHA_COINS_FIRST + 4, - BATCH_ALPHA_SMOKE, - BATCH_ALPHA_COUNT, -}; - -enum BatchTransparent { - BATCH_TRANSPARENT_SMOKE, - BATCH_TRANSPARENT_MIST, - BATCH_TRANSPARENT_RED_FLAMES_FIRST, - BATCH_TRANSPARENT_RED_FLAMES_LAST = BATCH_TRANSPARENT_RED_FLAMES_FIRST + 7, - BATCH_TRANSPARENT_BLUE_FLAMES_FIRST, - BATCH_TRANSPARENT_BLUE_FLAMES_LAST = BATCH_TRANSPARENT_BLUE_FLAMES_FIRST + 7, - BATCH_TRANSPARENT_COUNT, -}; - enum BatchTransparentDecal { BATCH_TRANSPARENT_DECAL_SHADOW_CIRCLE, BATCH_TRANSPARENT_DECAL_SHADOW_SQUARE, diff --git a/src/engine/batch_list.c b/src/engine/batch_list.c index 5f8c327f1d..f5d5ac7c0c 100644 --- a/src/engine/batch_list.c +++ b/src/engine/batch_list.c @@ -2,30 +2,26 @@ #include "game/segment2.h" -static inline struct BatchArray* batch_array_alloc(struct AllocOnlyPool *pool, int count) -{ +static inline struct BatchArray* batch_array_alloc(struct AllocOnlyPool *pool, int count) { struct BatchArray* batches = alloc_only_pool_alloc(pool, sizeof(struct BatchArray) + count * sizeof(struct Batch)); batches->count = count; return batches; } -static inline void batch_setup(struct BatchArray* arr, int idx, const void* start, const void* end) -{ +static inline void batch_setup(struct BatchArray* arr, int idx, const void* start, const void* end) { struct Batch* batch = &arr->batches[idx]; batch->startDl = start; batch->endDl = end; } -struct BatchArray* batch_list_objects_alloc_xlu_decal(struct AllocOnlyPool *pool) -{ +struct BatchArray* batch_list_objects_alloc_xlu_decal(struct AllocOnlyPool *pool) { struct BatchArray* arr = batch_array_alloc(pool, BATCH_TRANSPARENT_DECAL_COUNT); batch_setup(arr, BATCH_TRANSPARENT_DECAL_SHADOW_CIRCLE, dl_shadow_circle, dl_shadow_end); batch_setup(arr, BATCH_TRANSPARENT_DECAL_SHADOW_SQUARE, dl_shadow_square, dl_shadow_end); return arr; } -struct BatchArray* batch_list_objects_alloc_cld(struct AllocOnlyPool *pool) -{ +struct BatchArray* batch_list_objects_alloc_cld(struct AllocOnlyPool *pool) { struct BatchArray* arr = batch_array_alloc(pool, BATCH_CLD_COUNT); batch_setup(arr, BATCH_CLD_SHADOW_CIRCLE, dl_shadow_circle, dl_shadow_end); batch_setup(arr, BATCH_CLD_SHADOW_SQUARE, dl_shadow_square, dl_shadow_end); diff --git a/src/engine/batch_list.h b/src/engine/batch_list.h index 6b88c01a1f..71fb18cd7c 100644 --- a/src/engine/batch_list.h +++ b/src/engine/batch_list.h @@ -6,10 +6,8 @@ struct BatchArray* batch_list_objects_alloc_xlu_decal(struct AllocOnlyPool *pool); struct BatchArray* batch_list_objects_alloc_cld(struct AllocOnlyPool *pool); -static inline struct BatchArray* batch_list_objects_alloc(struct AllocOnlyPool *pool, enum RenderLayers layer) -{ - switch (layer) - { +static inline struct BatchArray* batch_list_objects_alloc(struct AllocOnlyPool *pool, enum RenderLayers layer) { + switch (layer) { case LAYER_TRANSPARENT_DECAL: return batch_list_objects_alloc_xlu_decal(pool); case LAYER_CLD: diff --git a/src/engine/graph_node.h b/src/engine/graph_node.h index 5aa917758d..6b65784e6f 100644 --- a/src/engine/graph_node.h +++ b/src/engine/graph_node.h @@ -140,7 +140,7 @@ struct DisplayListNode { struct DisplayListNode *next; }; -struct DisplayListHead { +struct DisplayListLinks { struct DisplayListNode* head; struct DisplayListNode* tail; }; @@ -151,7 +151,7 @@ struct Batch { const void* endDl; // filled in rendering of the master list - struct DisplayListHead list; + struct DisplayListLinks list; }; struct BatchArray { @@ -160,7 +160,7 @@ struct BatchArray { }; struct MasterLayer { - struct DisplayListHead list; + struct DisplayListLinks list; struct BatchArray* objects; }; diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index c92dc42378..632dfcea44 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -252,8 +252,7 @@ Mtx identityMatrixWorldScale = {{ 0x00000000, LOWER_FIXED(1.0f) << 0} }}; -static void lists_render(Gfx **ptempGfxHead, struct DisplayListNode* currList) -{ +static void lists_render(Gfx **ptempGfxHead, struct DisplayListNode* currList) { #define tempGfxHead (*ptempGfxHead) do { gSPMatrix(tempGfxHead++, VIRTUAL_TO_PHYSICAL(currList->transform), (G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH)); @@ -263,8 +262,7 @@ static void lists_render(Gfx **ptempGfxHead, struct DisplayListNode* currList) #undef tempGfxHead } -static int batches_render(Gfx **ptempGfxHead, struct BatchArray* arr, u32 mode1, u32 mode2) -{ +static int batches_render(Gfx **ptempGfxHead, struct BatchArray* arr, u32 mode1, u32 mode2) { #define tempGfxHead (*ptempGfxHead) int amountRendered = 0; @@ -287,11 +285,10 @@ static int batches_render(Gfx **ptempGfxHead, struct BatchArray* arr, u32 mode1, return amountRendered; } -static void main_render(Gfx **ptempGfxHead, struct DisplayListNode* currList, u32 mode1, u32 mode2, int phaseIndex) -{ - (void)phaseIndex; +static void main_render(Gfx **ptempGfxHead, struct DisplayListNode* currList, u32 mode1, u32 mode2, int phaseIndex) { #define tempGfxHead (*ptempGfxHead) #if defined(DISABLE_AA) || !SILHOUETTE + (void)phaseIndex; // Set the render mode for the current layer. gDPSetRenderMode(tempGfxHead++, mode1, mode2); #else @@ -393,8 +390,7 @@ void geo_process_master_list_sub(struct GraphNodeMasterList *node) { gDisplayListHead = tempGfxHead; } -static void append_dl(struct DisplayListHead* list, void* dl) -{ +static void append_dl(struct DisplayListLinks* list, void* dl) { struct DisplayListNode *listNode = alloc_only_pool_alloc(gDisplayListHeap, sizeof(struct DisplayListNode)); listNode->transform = gMatStackFixed[gMatStackIndex]; diff --git a/src/game/shadow.c b/src/game/shadow.c index 24b181d054..ee5db71628 100644 --- a/src/game/shadow.c +++ b/src/game/shadow.c @@ -169,7 +169,7 @@ void correct_lava_shadow_height(f32 *floorHeight) { * Uses environment alpha for shadow solidity. */ static void add_shadow_to_display_list(Gfx *displayListHead, s8 shadowType) { - gDPSetEnvColor(displayListHead++, 255, 255, 255, s->solidity); + gDPSetPrimColor(displayListHead++, 0, 0, 255, 255, 255, s->solidity); gSPDisplayList(displayListHead++, dl_shadow_tris); gSPEndDisplayList(displayListHead); } From 582d17e950cea40a0f50ab46632e64eac913ed20 Mon Sep 17 00:00:00 2001 From: aglab2 Date: Fri, 27 Dec 2024 20:43:18 +0800 Subject: [PATCH 4/5] Introduce static asserts to ensure all constant batches are set --- src/engine/batch_list.c | 33 +++++++++++++++++---------------- src/engine/graph_node.h | 9 +++------ src/game/rendering_graph_node.c | 15 ++++++++------- src/game/shadow.c | 6 +++--- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/engine/batch_list.c b/src/engine/batch_list.c index f5d5ac7c0c..5bc9743cc3 100644 --- a/src/engine/batch_list.c +++ b/src/engine/batch_list.c @@ -2,28 +2,29 @@ #include "game/segment2.h" -static inline struct BatchArray* batch_array_alloc(struct AllocOnlyPool *pool, int count) { - struct BatchArray* batches = alloc_only_pool_alloc(pool, sizeof(struct BatchArray) + count * sizeof(struct Batch)); +static const struct BatchDisplayLists DecalBatchesTransparent[] = { + [ BATCH_TRANSPARENT_DECAL_SHADOW_CIRCLE ] = { dl_shadow_circle, dl_shadow_end }, + [ BATCH_TRANSPARENT_DECAL_SHADOW_SQUARE ] = { dl_shadow_square, dl_shadow_end }, +}; +STATIC_ASSERT(BATCH_TRANSPARENT_DECAL_COUNT == sizeof(DecalBatchesTransparent) / sizeof(*DecalBatchesTransparent), "Mismatch in transparent decal batch count"); + +static const struct BatchDisplayLists DecalBatchesCLD[] = { + [ BATCH_CLD_SHADOW_CIRCLE ] = { dl_shadow_circle, dl_shadow_end }, + [ BATCH_CLD_SHADOW_SQUARE ] = { dl_shadow_square, dl_shadow_end }, +}; +STATIC_ASSERT(BATCH_CLD_COUNT == sizeof(DecalBatchesCLD) / sizeof(*DecalBatchesCLD), "Mismatch in CLD batch count"); + +static inline struct BatchArray* batch_array_alloc(struct AllocOnlyPool *pool, int count, const struct BatchDisplayLists* dls) { + struct BatchArray* batches = alloc_only_pool_alloc(pool, sizeof(struct BatchArray) + count * sizeof(struct DisplayListLinks)); batches->count = count; + batches->batchDLs = dls; return batches; } -static inline void batch_setup(struct BatchArray* arr, int idx, const void* start, const void* end) { - struct Batch* batch = &arr->batches[idx]; - batch->startDl = start; - batch->endDl = end; -} - struct BatchArray* batch_list_objects_alloc_xlu_decal(struct AllocOnlyPool *pool) { - struct BatchArray* arr = batch_array_alloc(pool, BATCH_TRANSPARENT_DECAL_COUNT); - batch_setup(arr, BATCH_TRANSPARENT_DECAL_SHADOW_CIRCLE, dl_shadow_circle, dl_shadow_end); - batch_setup(arr, BATCH_TRANSPARENT_DECAL_SHADOW_SQUARE, dl_shadow_square, dl_shadow_end); - return arr; + return batch_array_alloc(pool, BATCH_TRANSPARENT_DECAL_COUNT, DecalBatchesTransparent); } struct BatchArray* batch_list_objects_alloc_cld(struct AllocOnlyPool *pool) { - struct BatchArray* arr = batch_array_alloc(pool, BATCH_CLD_COUNT); - batch_setup(arr, BATCH_CLD_SHADOW_CIRCLE, dl_shadow_circle, dl_shadow_end); - batch_setup(arr, BATCH_CLD_SHADOW_SQUARE, dl_shadow_square, dl_shadow_end); - return arr; + return batch_array_alloc(pool, BATCH_CLD_COUNT, DecalBatchesCLD); } diff --git a/src/engine/graph_node.h b/src/engine/graph_node.h index 6b65784e6f..5387703159 100644 --- a/src/engine/graph_node.h +++ b/src/engine/graph_node.h @@ -145,18 +145,15 @@ struct DisplayListLinks { struct DisplayListNode* tail; }; -struct Batch { - // filled in when master node is created +struct BatchDisplayLists { const void* startDl; const void* endDl; - - // filled in rendering of the master list - struct DisplayListLinks list; }; struct BatchArray { int count; - struct Batch batches[0]; + const struct BatchDisplayLists* batchDLs; + struct DisplayListLinks batches[0]; }; struct MasterLayer { diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 632dfcea44..64bf729973 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -271,14 +271,15 @@ static int batches_render(Gfx **ptempGfxHead, struct BatchArray* arr, u32 mode1, gDPSetRenderMode(tempGfxHead++, mode1, mode2); for (int batch = 0; batch < arr->count; batch++) { - struct Batch* batches = &arr->batches[batch]; - if (!batches->list.head) + struct DisplayListLinks* batchLinks = &arr->batches[batch]; + if (!batchLinks->head) continue; - gSPDisplayList(tempGfxHead++, batches->startDl); + const struct BatchDisplayLists* batchDisplayLists = &arr->batchDLs[batch]; + gSPDisplayList(tempGfxHead++, batchDisplayLists->startDl); amountRendered++; - lists_render(&tempGfxHead, batches->list.head); - gSPDisplayList(tempGfxHead++, batches->endDl); + lists_render(&tempGfxHead, batchLinks->head); + gSPDisplayList(tempGfxHead++, batchDisplayLists->endDl); } #undef tempGfxHead @@ -449,7 +450,7 @@ static void geo_append_batched_display_list(void *displayList, enum RenderLayers #endif layer = mangle_silhouette_layer(layer); struct MasterLayer* masterLayer = &gCurGraphNodeMasterList->layers[layer]; - append_dl(&masterLayer->objects->batches[batch].list, displayList); + append_dl(&masterLayer->objects->batches[batch], displayList); } static void inc_mat_stack() { @@ -474,7 +475,7 @@ static void batches_clean(struct BatchArray* arr) { return; for (int batch = 0; batch < arr->count; batch++) { - arr->batches[batch].list.head = NULL; + arr->batches[batch].head = NULL; } } diff --git a/src/game/shadow.c b/src/game/shadow.c index ee5db71628..b405507958 100644 --- a/src/game/shadow.c +++ b/src/game/shadow.c @@ -168,7 +168,7 @@ void correct_lava_shadow_height(f32 *floorHeight) { * shadowType 0 uses a circle texture, the rest use a square texture. * Uses environment alpha for shadow solidity. */ -static void add_shadow_to_display_list(Gfx *displayListHead, s8 shadowType) { +static void add_shadow_to_display_list(Gfx *displayListHead) { gDPSetPrimColor(displayListHead++, 0, 0, 255, 255, 255, s->solidity); gSPDisplayList(displayListHead++, dl_shadow_tris); gSPEndDisplayList(displayListHead); @@ -348,14 +348,14 @@ Gfx *create_shadow_below_xyz(Vec3f pos, s16 shadowScale, u8 shadowSolidity, s8 s } } - Gfx *displayList = alloc_display_list(4 * sizeof(Gfx)); + Gfx *displayList = alloc_display_list(3 * sizeof(Gfx)); if (displayList == NULL) { return NULL; } // Generate the shadow display list with type and solidity. - add_shadow_to_display_list(displayList, shadowType); + add_shadow_to_display_list(displayList); // Move the shadow position to the floor height. pos[1] = floorHeight; From 4b780f944a82af79fb0504de3098f4a62e32305e Mon Sep 17 00:00:00 2001 From: aglab2 Date: Fri, 27 Dec 2024 22:48:06 +0800 Subject: [PATCH 5/5] Fixed incorrect const batches names --- src/engine/batch_list.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/engine/batch_list.c b/src/engine/batch_list.c index 5bc9743cc3..ead07540bc 100644 --- a/src/engine/batch_list.c +++ b/src/engine/batch_list.c @@ -2,17 +2,17 @@ #include "game/segment2.h" -static const struct BatchDisplayLists DecalBatchesTransparent[] = { +static const struct BatchDisplayLists BatchesTransparentDecal[] = { [ BATCH_TRANSPARENT_DECAL_SHADOW_CIRCLE ] = { dl_shadow_circle, dl_shadow_end }, [ BATCH_TRANSPARENT_DECAL_SHADOW_SQUARE ] = { dl_shadow_square, dl_shadow_end }, }; -STATIC_ASSERT(BATCH_TRANSPARENT_DECAL_COUNT == sizeof(DecalBatchesTransparent) / sizeof(*DecalBatchesTransparent), "Mismatch in transparent decal batch count"); +STATIC_ASSERT(BATCH_TRANSPARENT_DECAL_COUNT == sizeof(BatchesTransparentDecal) / sizeof(*BatchesTransparentDecal), "Mismatch in transparent decal batch count"); -static const struct BatchDisplayLists DecalBatchesCLD[] = { +static const struct BatchDisplayLists BatchesCLD[] = { [ BATCH_CLD_SHADOW_CIRCLE ] = { dl_shadow_circle, dl_shadow_end }, [ BATCH_CLD_SHADOW_SQUARE ] = { dl_shadow_square, dl_shadow_end }, }; -STATIC_ASSERT(BATCH_CLD_COUNT == sizeof(DecalBatchesCLD) / sizeof(*DecalBatchesCLD), "Mismatch in CLD batch count"); +STATIC_ASSERT(BATCH_CLD_COUNT == sizeof(BatchesCLD) / sizeof(*BatchesCLD), "Mismatch in CLD batch count"); static inline struct BatchArray* batch_array_alloc(struct AllocOnlyPool *pool, int count, const struct BatchDisplayLists* dls) { struct BatchArray* batches = alloc_only_pool_alloc(pool, sizeof(struct BatchArray) + count * sizeof(struct DisplayListLinks)); @@ -22,9 +22,9 @@ static inline struct BatchArray* batch_array_alloc(struct AllocOnlyPool *pool, i } struct BatchArray* batch_list_objects_alloc_xlu_decal(struct AllocOnlyPool *pool) { - return batch_array_alloc(pool, BATCH_TRANSPARENT_DECAL_COUNT, DecalBatchesTransparent); + return batch_array_alloc(pool, BATCH_TRANSPARENT_DECAL_COUNT, BatchesTransparentDecal); } struct BatchArray* batch_list_objects_alloc_cld(struct AllocOnlyPool *pool) { - return batch_array_alloc(pool, BATCH_CLD_COUNT, DecalBatchesCLD); + return batch_array_alloc(pool, BATCH_CLD_COUNT, BatchesCLD); }