fix: corregir límite de sprites en SHAPE mode con muchas bolas
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 <noreply@anthropic.com>
This commit is contained in:
@@ -231,8 +231,14 @@ bool Engine::initialize(int width, int height, int zoom, bool fullscreen, AppMod
|
|||||||
success = false;
|
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<GpuSpriteBatch>();
|
sprite_batch_ = std::make_unique<GpuSpriteBatch>();
|
||||||
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;
|
std::cerr << "ERROR: No se pudo crear el sprite batch GPU" << std::endl;
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,12 @@
|
|||||||
// Public interface
|
// Public interface
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool GpuSpriteBatch::init(SDL_GPUDevice* device) {
|
bool GpuSpriteBatch::init(SDL_GPUDevice* device, int max_sprites) {
|
||||||
// Pre-allocate GPU buffers large enough for MAX_SPRITES quads.
|
max_sprites_ = max_sprites;
|
||||||
Uint32 max_verts = static_cast<Uint32>(MAX_SPRITES) * 4;
|
// Pre-allocate GPU buffers large enough for (max_sprites_ + 1) quads.
|
||||||
Uint32 max_indices = static_cast<Uint32>(MAX_SPRITES) * 6;
|
// The +1 reserves a guaranteed slot for the fullscreen overlay.
|
||||||
|
Uint32 max_verts = static_cast<Uint32>(max_sprites_ + 1) * 4;
|
||||||
|
Uint32 max_indices = static_cast<Uint32>(max_sprites_ + 1) * 6;
|
||||||
|
|
||||||
Uint32 vb_size = max_verts * sizeof(GpuVertex);
|
Uint32 vb_size = max_verts * sizeof(GpuVertex);
|
||||||
Uint32 ib_size = max_indices * sizeof(uint32_t);
|
Uint32 ib_size = max_indices * sizeof(uint32_t);
|
||||||
@@ -53,8 +55,8 @@ bool GpuSpriteBatch::init(SDL_GPUDevice* device) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vertices_.reserve(MAX_SPRITES * 4);
|
vertices_.reserve(static_cast<size_t>(max_sprites_ + 1) * 4);
|
||||||
indices_.reserve(MAX_SPRITES * 6);
|
indices_.reserve(static_cast<size_t>(max_sprites_ + 1) * 6);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,8 +131,9 @@ void GpuSpriteBatch::addSprite(float x, float y, float w, float h,
|
|||||||
|
|
||||||
void GpuSpriteBatch::addFullscreenOverlay() {
|
void GpuSpriteBatch::addFullscreenOverlay() {
|
||||||
overlay_index_offset_ = static_cast<int>(indices_.size());
|
overlay_index_offset_ = static_cast<int>(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);
|
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<int>(indices_.size() - before); // 0 si pushQuad falló, 6 si ok
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpuSpriteBatch::uploadBatch(SDL_GPUDevice* device, SDL_GPUCommandBuffer* cmd_buf) {
|
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,
|
void GpuSpriteBatch::pushQuad(float ndx0, float ndy0, float ndx1, float ndy1,
|
||||||
float u0, float v0, float u1, float v1,
|
float u0, float v0, float u1, float v1,
|
||||||
float r, float g, float b, float a) {
|
float r, float g, float b, float a) {
|
||||||
if (vertices_.size() + 4 > static_cast<size_t>(MAX_SPRITES) * 4) return;
|
if (vertices_.size() + 4 > static_cast<size_t>(max_sprites_) * 4) return;
|
||||||
uint32_t vi = static_cast<uint32_t>(vertices_.size());
|
uint32_t vi = static_cast<uint32_t>(vertices_.size());
|
||||||
|
|
||||||
// TL, TR, BR, BL
|
// TL, TR, BR, BL
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ struct GpuVertex {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
class GpuSpriteBatch {
|
class GpuSpriteBatch {
|
||||||
public:
|
public:
|
||||||
// Maximum sprites (background + UI overlay each count as one sprite)
|
// Default maximum sprites (background + UI overlay each count as one sprite)
|
||||||
static constexpr int MAX_SPRITES = 200000;
|
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 destroy(SDL_GPUDevice* device);
|
||||||
|
|
||||||
void beginFrame();
|
void beginFrame();
|
||||||
@@ -83,4 +83,6 @@ private:
|
|||||||
int sprite_index_count_ = 0;
|
int sprite_index_count_ = 0;
|
||||||
int overlay_index_offset_ = 0;
|
int overlay_index_offset_ = 0;
|
||||||
int overlay_index_count_ = 0;
|
int overlay_index_count_ = 0;
|
||||||
|
|
||||||
|
int max_sprites_ = DEFAULT_MAX_SPRITES;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user