From 74d954df1e63c8f8c5919e20b874d9483b2bde7b Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sat, 21 Mar 2026 00:14:28 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20corregir=20l=C3=ADmite=20de=20sprites=20?= =?UTF-8?q?en=20SHAPE=20mode=20con=20muchas=20bolas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GpuSpriteBatch::init() ahora acepta capacidad dinámica para soportar --custom-balls N con N > 200000. El buffer se dimensiona a (N+1) quads, reservando siempre un slot para el overlay. addFullscreenOverlay() calcula overlay_index_count_ desde el delta real de indices_ en lugar de fijarlo a 6 incondicionalmente. Engine calcula la capacidad correcta al init. Co-Authored-By: Claude Sonnet 4.6 --- source/engine.cpp | 8 +++++++- source/gpu/gpu_sprite_batch.cpp | 19 +++++++++++-------- source/gpu/gpu_sprite_batch.hpp | 8 +++++--- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/source/engine.cpp b/source/engine.cpp index c8da655..7a18c45 100644 --- a/source/engine.cpp +++ b/source/engine.cpp @@ -231,8 +231,14 @@ bool Engine::initialize(int width, int height, int zoom, bool fullscreen, AppMod success = false; } + // Calcular capacidad: background (1) + bolas del escenario máximo + overlay (+1 interno en init) + int sprite_capacity = BALL_COUNT_SCENARIOS[DEMO_AUTO_MAX_SCENARIO]; + if (custom_scenario_enabled_ && custom_scenario_balls_ > sprite_capacity) + sprite_capacity = custom_scenario_balls_; + sprite_capacity += 1; // +1 por el background + sprite_batch_ = std::make_unique(); - if (!sprite_batch_->init(gpu_ctx_->device())) { + if (!sprite_batch_->init(gpu_ctx_->device(), sprite_capacity)) { std::cerr << "ERROR: No se pudo crear el sprite batch GPU" << std::endl; success = false; } diff --git a/source/gpu/gpu_sprite_batch.cpp b/source/gpu/gpu_sprite_batch.cpp index ba3348e..e9c9d1c 100644 --- a/source/gpu/gpu_sprite_batch.cpp +++ b/source/gpu/gpu_sprite_batch.cpp @@ -7,10 +7,12 @@ // Public interface // --------------------------------------------------------------------------- -bool GpuSpriteBatch::init(SDL_GPUDevice* device) { - // Pre-allocate GPU buffers large enough for MAX_SPRITES quads. - Uint32 max_verts = static_cast(MAX_SPRITES) * 4; - Uint32 max_indices = static_cast(MAX_SPRITES) * 6; +bool GpuSpriteBatch::init(SDL_GPUDevice* device, int max_sprites) { + max_sprites_ = max_sprites; + // Pre-allocate GPU buffers large enough for (max_sprites_ + 1) quads. + // The +1 reserves a guaranteed slot for the fullscreen overlay. + Uint32 max_verts = static_cast(max_sprites_ + 1) * 4; + Uint32 max_indices = static_cast(max_sprites_ + 1) * 6; Uint32 vb_size = max_verts * sizeof(GpuVertex); Uint32 ib_size = max_indices * sizeof(uint32_t); @@ -53,8 +55,8 @@ bool GpuSpriteBatch::init(SDL_GPUDevice* device) { return false; } - vertices_.reserve(MAX_SPRITES * 4); - indices_.reserve(MAX_SPRITES * 6); + vertices_.reserve(static_cast(max_sprites_ + 1) * 4); + indices_.reserve(static_cast(max_sprites_ + 1) * 6); return true; } @@ -129,8 +131,9 @@ void GpuSpriteBatch::addSprite(float x, float y, float w, float h, void GpuSpriteBatch::addFullscreenOverlay() { overlay_index_offset_ = static_cast(indices_.size()); + size_t before = indices_.size(); pushQuad(-1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); - overlay_index_count_ = 6; + overlay_index_count_ = static_cast(indices_.size() - before); // 0 si pushQuad falló, 6 si ok } bool GpuSpriteBatch::uploadBatch(SDL_GPUDevice* device, SDL_GPUCommandBuffer* cmd_buf) { @@ -179,7 +182,7 @@ void GpuSpriteBatch::toNDC(float px, float py, void GpuSpriteBatch::pushQuad(float ndx0, float ndy0, float ndx1, float ndy1, float u0, float v0, float u1, float v1, float r, float g, float b, float a) { - if (vertices_.size() + 4 > static_cast(MAX_SPRITES) * 4) return; + if (vertices_.size() + 4 > static_cast(max_sprites_) * 4) return; uint32_t vi = static_cast(vertices_.size()); // TL, TR, BR, BL diff --git a/source/gpu/gpu_sprite_batch.hpp b/source/gpu/gpu_sprite_batch.hpp index 56ed788..b92c5e3 100644 --- a/source/gpu/gpu_sprite_batch.hpp +++ b/source/gpu/gpu_sprite_batch.hpp @@ -26,10 +26,10 @@ struct GpuVertex { // ============================================================================ class GpuSpriteBatch { public: - // Maximum sprites (background + UI overlay each count as one sprite) - static constexpr int MAX_SPRITES = 200000; + // Default maximum sprites (background + UI overlay each count as one sprite) + static constexpr int DEFAULT_MAX_SPRITES = 200000; - bool init(SDL_GPUDevice* device); + bool init(SDL_GPUDevice* device, int max_sprites = DEFAULT_MAX_SPRITES); void destroy(SDL_GPUDevice* device); void beginFrame(); @@ -83,4 +83,6 @@ private: int sprite_index_count_ = 0; int overlay_index_offset_ = 0; int overlay_index_count_ = 0; + + int max_sprites_ = DEFAULT_MAX_SPRITES; };