From 8bb3702af43984be5172da3552db9edb5c52af08 Mon Sep 17 00:00:00 2001 From: Kelsi Davis Date: Sun, 5 Apr 2026 03:25:27 -0700 Subject: [PATCH] perf(rendering): reduce GPU cull buffer and add CPU fallback for overflow Halve MAX_CULL_INSTANCES to 32768 and iterate all instances in render, falling back to CPU frustum culling for any beyond the GPU buffer. --- include/rendering/m2_renderer.hpp | 2 +- src/rendering/m2_renderer.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/rendering/m2_renderer.hpp b/include/rendering/m2_renderer.hpp index 517e42ce..4f9f82e2 100644 --- a/include/rendering/m2_renderer.hpp +++ b/include/rendering/m2_renderer.hpp @@ -478,7 +478,7 @@ private: uint32_t instanceCount; uint32_t _pad[3] = {}; }; - static constexpr uint32_t MAX_CULL_INSTANCES = 65536; + static constexpr uint32_t MAX_CULL_INSTANCES = 32768; VkPipeline cullPipeline_ = VK_NULL_HANDLE; VkPipelineLayout cullPipelineLayout_ = VK_NULL_HANDLE; VkDescriptorSetLayout cullSetLayout_ = VK_NULL_HANDLE; diff --git a/src/rendering/m2_renderer.cpp b/src/rendering/m2_renderer.cpp index c0532787..fd7c6bd4 100644 --- a/src/rendering/m2_renderer.cpp +++ b/src/rendering/m2_renderer.cpp @@ -2680,22 +2680,23 @@ void M2Renderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet, const sortedVisible_.reserve(expectedVisible); } - // GPU frustum culling — build frustum only for CPU fallback path + // GPU frustum culling — build frustum for CPU fallback path and overflow instances Frustum frustum; - if (!gpuCullAvailable) { + { const glm::mat4 vp = camera.getProjectionMatrix() * camera.getViewMatrix(); frustum.extractFromMatrix(vp); } const float maxPossibleDistSq = maxRenderDistanceSq * 4.0f; - for (uint32_t i = 0; i < numInstances; ++i) { + const uint32_t totalInstances = static_cast(instances.size()); + for (uint32_t i = 0; i < totalInstances; ++i) { const auto& instance = instances[i]; - if (gpuCullAvailable) { + if (gpuCullAvailable && i < numInstances) { // GPU already tested flags + distance + frustum if (!visibility[i]) continue; } else { - // CPU fallback: same culling logic as before + // CPU fallback: for non-GPU path or instances beyond cull buffer if (!instance.cachedIsValid || instance.cachedIsSmoke || instance.cachedIsInvisibleTrap) continue; glm::vec3 toCam = instance.position - camPos;