Path SDL3 GPU amb PostFX passthrough; Screen amb init/shutdown explicit (v0.4.0)

This commit is contained in:
JailDesigner committed 2026-04-18 22:50:04 +02:00
1 parent 0348acb0eb
commit 6c8ef9ff44
18 files changed
+14213 -38

No files matched your search

+50 -17
View File
@@ -6,8 +6,11 @@
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <ranges>
#include "core/rendering/sdl3gpu/sdl3gpu_shader.hpp"
#include "utils/defines.hpp"
namespace {
@@ -39,29 +42,41 @@ auto Screen::get() -> Screen& {
return instance_;
}
Screen::Screen()
: canvas_width_(GameCanvas::WIDTH),
canvas_height_(GameCanvas::HEIGHT),
canvas_(static_cast<std::size_t>(GameCanvas::WIDTH) * static_cast<std::size_t>(GameCanvas::HEIGHT), 0xFF000000U) {
if (!SDL_InitSubSystem(SDL_INIT_VIDEO)) {
std::fprintf(stderr, "SDL_InitSubSystem(VIDEO) failed: %s\n", SDL_GetError());
std::exit(EXIT_FAILURE);
}
// Els recursos SDL (finestra, renderer, textura) es creen a configure().
}
Screen::~Screen() {
destroySdl();
SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
void Screen::configure(const Config& config) {
// Inicialitza el subsistema de vídeo la primera volta; reconfiguracions
// posteriors reutilitzen el subsistema i recreen els recursos SDL.
if (!subsystem_initialized_) {
if (!SDL_InitSubSystem(SDL_INIT_VIDEO)) {
std::fprintf(stderr, "SDL_InitSubSystem(VIDEO) failed: %s\n", SDL_GetError());
std::exit(EXIT_FAILURE);
}
subsystem_initialized_ = true;
canvas_width_ = GameCanvas::WIDTH;
canvas_height_ = GameCanvas::HEIGHT;
canvas_.assign(static_cast<std::size_t>(GameCanvas::WIDTH) * static_cast<std::size_t>(GameCanvas::HEIGHT), 0xFF000000U);
}
destroySdl();
config_ = config;
createSdl();
}
void Screen::shutdown() {
destroySdl();
if (subsystem_initialized_) {
SDL_QuitSubSystem(SDL_INIT_VIDEO);
subsystem_initialized_ = false;
}
}
void Screen::destroySdl() {
// Ordre per a evitar crashes a Wayland/Vulkan durant el teardown:
// 1) Alliberar la finestra del GPU device (destrueix el VkSurface).
// 2) Destruir el GPU device (vkDestroyInstance amb Wayland encara viu).
// 3) Destruir la finestra SDL (tanca la surface de Wayland al final).
if (shader_backend_ != nullptr) {
static_cast<Rendering::SDL3GPUShader*>(shader_backend_.get())->releaseWindow();
}
shader_backend_.reset();
if (game_texture_ != nullptr) {
SDL_DestroyTexture(game_texture_);
game_texture_ = nullptr;
@@ -89,6 +104,19 @@ void Screen::createSdl() {
std::exit(EXIT_FAILURE);
}
// Primer intent: path SDL3 GPU. Si falla, fallback automàtic a SDL_Renderer.
if (config_.gpu_acceleration) {
auto backend = std::make_unique<Rendering::SDL3GPUShader>();
backend->setPreferredDriver(config_.preferred_driver);
backend->setVSync(config_.vsync);
if (backend->init(window_, canvas_width_, canvas_height_)) {
std::cout << "Screen: path GPU actiu (driver: " << backend->getDriverName() << ")\n";
shader_backend_ = std::move(backend);
return;
}
std::cerr << "Screen: GPU no disponible, fallback a SDL_Renderer\n";
}
renderer_ = SDL_CreateRenderer(window_, nullptr);
if (renderer_ == nullptr) {
std::fprintf(stderr, "SDL_CreateRenderer failed: %s\n", SDL_GetError());
@@ -114,8 +142,13 @@ void Screen::clear(std::uint8_t r, std::uint8_t g, std::uint8_t b) {
}
void Screen::present() {
SDL_UpdateTexture(game_texture_, nullptr, canvas_.data(), canvas_width_ * static_cast<int>(sizeof(std::uint32_t)));
if (shader_backend_ != nullptr) {
shader_backend_->uploadPixels(canvas_.data(), canvas_width_, canvas_height_);
shader_backend_->render();
return;
}
SDL_UpdateTexture(game_texture_, nullptr, canvas_.data(), canvas_width_ * static_cast<int>(sizeof(std::uint32_t)));
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
SDL_RenderClear(renderer_);
SDL_RenderTexture(renderer_, game_texture_, nullptr, nullptr);