#include "gpu_ball_buffer.hpp" #include #include // std::min #include // memcpy auto GpuBallBuffer::init(SDL_GPUDevice* device) -> bool { Uint32 buf_size = static_cast(MAX_BALLS) * sizeof(BallGPUData); // GPU vertex buffer (instance-rate data read by the ball instanced shader) SDL_GPUBufferCreateInfo buf_info = {}; buf_info.usage = SDL_GPU_BUFFERUSAGE_VERTEX; buf_info.size = buf_size; gpu_buf_ = SDL_CreateGPUBuffer(device, &buf_info); if (gpu_buf_ == nullptr) { SDL_Log("GpuBallBuffer: GPU buffer creation failed: %s", SDL_GetError()); return false; } // Transfer buffer (upload staging, cycled every frame) SDL_GPUTransferBufferCreateInfo tb_info = {}; tb_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; tb_info.size = buf_size; transfer_buf_ = SDL_CreateGPUTransferBuffer(device, &tb_info); if (transfer_buf_ == nullptr) { SDL_Log("GpuBallBuffer: transfer buffer creation failed: %s", SDL_GetError()); return false; } SDL_Log("GpuBallBuffer: initialized (capacity %d balls, %.1f MB VRAM)", MAX_BALLS, buf_size / (1024.0f * 1024.0f)); return true; } void GpuBallBuffer::destroy(SDL_GPUDevice* device) { if (device == nullptr) { return; } if (transfer_buf_ != nullptr) { SDL_ReleaseGPUTransferBuffer(device, transfer_buf_); transfer_buf_ = nullptr; } if (gpu_buf_ != nullptr) { SDL_ReleaseGPUBuffer(device, gpu_buf_); gpu_buf_ = nullptr; } count_ = 0; } auto GpuBallBuffer::upload(SDL_GPUDevice* device, SDL_GPUCommandBuffer* cmd, const BallGPUData* data, int count) -> bool { if ((data == nullptr) || count <= 0) { count_ = 0; return false; } count = std::min(count, MAX_BALLS); Uint32 upload_size = static_cast(count) * sizeof(BallGPUData); void* ptr = SDL_MapGPUTransferBuffer(device, transfer_buf_, true /* cycle */); if (ptr == nullptr) { SDL_Log("GpuBallBuffer: transfer buffer map failed: %s", SDL_GetError()); return false; } memcpy(ptr, data, upload_size); SDL_UnmapGPUTransferBuffer(device, transfer_buf_); SDL_GPUCopyPass* copy = SDL_BeginGPUCopyPass(cmd); SDL_GPUTransferBufferLocation src = {transfer_buf_, 0}; SDL_GPUBufferRegion dst = {gpu_buf_, 0, upload_size}; SDL_UploadToGPUBuffer(copy, &src, &dst, true /* cycle */); SDL_EndGPUCopyPass(copy); count_ = count; return true; }