Fase 7b+c: swap atomico a SDL3 GPU (Vulkan/Metal, sin SDL_Renderer)
El runtime de rendering pasa a SDL3 GPU. SDL_Renderer eliminado por completo del proyecto: SDLManager posee un GpuFrameRenderer y todo el resto del codigo habla con un Rendering::Renderer* opaco (alias del GpuFrameRenderer). Cambios principales: - core/rendering/render_context.hpp: alias central `using Rendering::Renderer = GPU::GpuFrameRenderer;` — punto unico de indireccion entre el juego y el backend de dibujo. - core/rendering/sdl_manager.hpp/cpp: deja de tener SDL_Renderer*; contiene un Rendering::Renderer gpu_renderer_. iniciar() ahora hace GpuDevice::init + pipeline; clear() llama beginFrame; present() llama endFrame. Letterbox se aplica via setViewport tras cada begin del render pass. toggleVSync() usa SDL_SetGPUSwapchainParameters. - core/rendering/line_renderer.hpp/cpp: la firma cambia a `linea(Renderer*, x1,y1,x2,y2, brightness, thickness)`. La implementacion deja de usar SDL_RenderLine: empuja la linea como quad extrudido al batch del GpuFrameRenderer. Se anade un grosor global configurable via setLineThickness (default 1.5 px). Ya no se aplica transform_x/y porque el shader hace logical->NDC y el viewport hace el letterbox. - gpu_frame_renderer: anade setViewport (aplicable mid-frame), setVSync (PRESENTMODE_VSYNC/IMMEDIATE) y applyViewport interno que re-aplica el viewport tras reabrir el render pass en flushBatch. - Sed sweep masivo en 19 archivos: SDL_Renderer* -> Rendering::Renderer* en headers y .cpp de entities, effects, graphics y title. Los archivos solo propagan el puntero — solo line_renderer consume sus metodos. SDL_Renderer queda eliminado del proyecto. Smoke test xvfb: backend Vulkan detectado, binario arranca, carga todos los shapes/audio/title, TitleScene inicializa, termina limpio con "Adeu!". stderr vacio. Validacion visual pendiente en hardware real (xvfb VMware sin 3D no muestra el swapchain Vulkan). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -76,12 +76,56 @@ auto GpuFrameRenderer::beginFrame(float clear_r, float clear_g, float clear_b) -
|
||||
cmd_buffer_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
applyViewport();
|
||||
|
||||
vertices_.clear();
|
||||
indices_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void GpuFrameRenderer::setViewport(float x, float y, float w, float h) {
|
||||
viewport_x_ = x;
|
||||
viewport_y_ = y;
|
||||
viewport_w_ = w;
|
||||
viewport_h_ = h;
|
||||
// Si estamos en medio de un frame, aplicar inmediatamente.
|
||||
if (render_pass_ != nullptr) {
|
||||
applyViewport();
|
||||
}
|
||||
}
|
||||
|
||||
void GpuFrameRenderer::setVSync(bool enabled) {
|
||||
SDL_GPUDevice* dev = device_.get();
|
||||
if (dev == nullptr || device_.window() == nullptr) {
|
||||
return;
|
||||
}
|
||||
const SDL_GPUPresentMode MODE = enabled
|
||||
? SDL_GPU_PRESENTMODE_VSYNC
|
||||
: SDL_GPU_PRESENTMODE_IMMEDIATE;
|
||||
// Composition por defecto: SDR sin HDR.
|
||||
if (!SDL_SetGPUSwapchainParameters(dev, device_.window(),
|
||||
SDL_GPU_SWAPCHAINCOMPOSITION_SDR, MODE)) {
|
||||
std::cerr << "[GpuFrameRenderer] SDL_SetGPUSwapchainParameters: " << SDL_GetError() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void GpuFrameRenderer::applyViewport() {
|
||||
if (render_pass_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (viewport_w_ <= 0.0F || viewport_h_ <= 0.0F) {
|
||||
return; // full window por defecto, no setear nada
|
||||
}
|
||||
SDL_GPUViewport vp{};
|
||||
vp.x = viewport_x_;
|
||||
vp.y = viewport_y_;
|
||||
vp.w = viewport_w_;
|
||||
vp.h = viewport_h_;
|
||||
vp.min_depth = 0.0F;
|
||||
vp.max_depth = 1.0F;
|
||||
SDL_SetGPUViewport(render_pass_, &vp);
|
||||
}
|
||||
|
||||
void GpuFrameRenderer::pushLine(float x1, float y1, float x2, float y2, float thickness,
|
||||
float r, float g, float b, float a) {
|
||||
// Extrusión perpendicular en CPU: por cada línea generamos 4 vértices que
|
||||
@@ -167,6 +211,7 @@ void GpuFrameRenderer::flushBatch() {
|
||||
color_target.load_op = SDL_GPU_LOADOP_LOAD;
|
||||
color_target.store_op = SDL_GPU_STOREOP_STORE;
|
||||
render_pass_ = SDL_BeginGPURenderPass(cmd_buffer_, &color_target, 1, nullptr);
|
||||
applyViewport();
|
||||
|
||||
// Bind pipeline + buffers + uniforms.
|
||||
SDL_BindGPUGraphicsPipeline(render_pass_, pipeline_.get());
|
||||
|
||||
@@ -48,6 +48,13 @@ class GpuFrameRenderer {
|
||||
// endFrame: sube el VBO, ejecuta el draw, cierra render pass y presenta.
|
||||
void endFrame();
|
||||
|
||||
// Viewport en píxeles físicos de la swapchain. Si w<=0 o h<=0, se
|
||||
// usa el tamaño completo de la ventana (sin letterbox).
|
||||
void setViewport(float x, float y, float w, float h);
|
||||
|
||||
// Activa/desactiva VSync. true = SDL_GPU_PRESENTMODE_VSYNC, false = IMMEDIATE.
|
||||
void setVSync(bool enabled);
|
||||
|
||||
// Acceso a internals (necesario para SDLManager y futuros sistemas).
|
||||
[[nodiscard]] auto device() -> GpuDevice& { return device_; }
|
||||
[[nodiscard]] auto isInsideFrame() const -> bool { return cmd_buffer_ != nullptr; }
|
||||
@@ -60,6 +67,12 @@ class GpuFrameRenderer {
|
||||
float logical_w_{1280.0F};
|
||||
float logical_h_{720.0F};
|
||||
|
||||
// Viewport en píxeles físicos. <0 = full window.
|
||||
float viewport_x_{0.0F};
|
||||
float viewport_y_{0.0F};
|
||||
float viewport_w_{-1.0F};
|
||||
float viewport_h_{-1.0F};
|
||||
|
||||
// Batch del frame en curso.
|
||||
std::vector<LineVertex> vertices_;
|
||||
std::vector<uint16_t> indices_;
|
||||
@@ -71,6 +84,7 @@ class GpuFrameRenderer {
|
||||
|
||||
// Helpers internos.
|
||||
void flushBatch();
|
||||
void applyViewport();
|
||||
};
|
||||
|
||||
} // namespace Rendering::GPU
|
||||
|
||||
Reference in New Issue
Block a user