From fd15c7c05dbea90864098e6a532a280121e9fce2 Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Wed, 10 Jun 2026 17:55:17 +0200 Subject: [PATCH 1/2] fix(sortingrenderer): Prevent a crash when exceeding the 16-bit index buffer limit --- .../Source/WWVegas/WW3D2/sortingrenderer.cpp | 97 +++++++++---------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/sortingrenderer.cpp b/Core/Libraries/Source/WWVegas/WW3D2/sortingrenderer.cpp index f64b5da1636..47bb7ef774f 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/sortingrenderer.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/sortingrenderer.cpp @@ -508,51 +508,57 @@ void SortingRendererClass::Flush_Sorting_Pool() Sort(tis, tis + overlapping_polygon_count); -/* ///@todo: Add code to break up rendering into multiple index buffer fills to allow more than 65536/3 triangles. -MW - int total_overlapping_polygon_count = overlapping_polygon_count; - while ( > 0) + // TheSuperHackers @fix stephanmeesters 10/06/2026 + // Split rendering into chunks to prevent a crash when exceeding the 16-bit index buffer limit. + static const unsigned MAX_INDEX_CHUNK = 65535; + unsigned chunkOffset = 0; + while (chunkOffset < overlapping_polygon_count) { - if ((total_overlapping_polygon_count*3) > 65535) - { //overflowed the index buffer, must break into multiple batches - overlapping_polygon_count = 65535/3; + unsigned chunkCount = overlapping_polygon_count - chunkOffset; + if (chunkCount * 3 > MAX_INDEX_CHUNK) { + chunkCount = MAX_INDEX_CHUNK / 3; } - else - overlapping_polygon_count = total_overlapping_polygon_count; - //insert rendering code here!! + DynamicIBAccessClass dyn_ib_access(BUFFER_TYPE_DYNAMIC_DX8,chunkCount*3); + { + DynamicIBAccessClass::WriteLockClass lock(&dyn_ib_access); + ShortVectorIStruct* sorted_polygon_index_array=(ShortVectorIStruct*)lock.Get_Index_Array(); - total_overlapping_polygon_count -= overlapping_polygon_count; - } -*/ - unsigned polygonAllocCount = overlapping_polygon_count; - if ((unsigned)(DynamicIBAccessClass::Get_Default_Index_Count()/3) < DEFAULT_SORTING_POLY_COUNT) - polygonAllocCount = DEFAULT_SORTING_POLY_COUNT; //make sure that we force the DX8 index buffer to maximum size - if (overlapping_polygon_count > polygonAllocCount) - polygonAllocCount = overlapping_polygon_count; - WWASSERT(DEFAULT_SORTING_POLY_COUNT <= 1 || polygonAllocCount <= DEFAULT_SORTING_POLY_COUNT); - - DynamicIBAccessClass dyn_ib_access(BUFFER_TYPE_DYNAMIC_DX8,polygonAllocCount*3); - { - DynamicIBAccessClass::WriteLockClass lock(&dyn_ib_access); - ShortVectorIStruct* sorted_polygon_index_array=(ShortVectorIStruct*)lock.Get_Index_Array(); - - for (unsigned a=0;asorting_state); - DX8Wrapper::Apply_Render_State_Changes(); + DX8Wrapper::Draw_Triangles( + start_index*3, + count_to_render, + state->min_vertex_index, + state->vertex_count); - unsigned count_to_render=1; - unsigned start_index=0; - unsigned node_id=tis[0].idx; - for (unsigned i=1;isorting_state); @@ -561,28 +567,13 @@ void SortingRendererClass::Flush_Sorting_Pool() count_to_render, state->min_vertex_index, state->vertex_count); - - count_to_render=0; - start_index=i; - node_id=tis[i].idx; } - count_to_render++; //keep track of number of polygons of same kind - } - - // Render any remaining polygons... - if (count_to_render) { - SortingNodeStruct* state=overlapping_nodes[node_id]; - Apply_Render_State(state->sorting_state); - DX8Wrapper::Draw_Triangles( - start_index*3, - count_to_render, - state->min_vertex_index, - state->vertex_count); + chunkOffset += chunkCount; } // Release all references and return nodes back to the clean list for the frame... - for (node_id=0;node_id Date: Wed, 10 Jun 2026 22:32:27 +0200 Subject: [PATCH 2/2] Process review comments --- Core/Libraries/Source/WWVegas/WW3D2/sortingrenderer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WW3D2/sortingrenderer.cpp b/Core/Libraries/Source/WWVegas/WW3D2/sortingrenderer.cpp index 47bb7ef774f..c2c89a07bdf 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/sortingrenderer.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/sortingrenderer.cpp @@ -510,7 +510,7 @@ void SortingRendererClass::Flush_Sorting_Pool() // TheSuperHackers @fix stephanmeesters 10/06/2026 // Split rendering into chunks to prevent a crash when exceeding the 16-bit index buffer limit. - static const unsigned MAX_INDEX_CHUNK = 65535; + constexpr const unsigned MAX_INDEX_CHUNK = 65535; unsigned chunkOffset = 0; while (chunkOffset < overlapping_polygon_count) { @@ -518,6 +518,7 @@ void SortingRendererClass::Flush_Sorting_Pool() if (chunkCount * 3 > MAX_INDEX_CHUNK) { chunkCount = MAX_INDEX_CHUNK / 3; } + const unsigned chunkEnd = chunkOffset + chunkCount; DynamicIBAccessClass dyn_ib_access(BUFFER_TYPE_DYNAMIC_DX8,chunkCount*3); { @@ -539,7 +540,7 @@ void SortingRendererClass::Flush_Sorting_Pool() unsigned count_to_render=1; unsigned start_index=0; unsigned node_id=tis[chunkOffset].idx; - for (unsigned i=chunkOffset + 1;isorting_state);