Files
aee-arcade/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp
T

103 lines
3.6 KiB
C++

#pragma once
#include <SDL3/SDL.h>
#include <SDL3/SDL_gpu.h>
#include <cstdint>
#include <string>
#include "core/rendering/shader_backend.hpp"
// Uniforms enviats al fragment stage cada frame.
// Han de coincidir amb l'estructura MSL/GLSL (48 bytes, alineats a 16).
struct PostFXUniforms {
float vignette_strength;
float chroma_strength;
float scanline_strength;
float screen_height;
float mask_strength;
float gamma_strength;
float curvature;
float bleeding;
float pixel_scale;
float time;
float oversample;
float flicker;
};
namespace Rendering {
// Backend GPU basat en SDL3 GPU API (Vulkan/SPIR-V a Linux i Windows,
// Metal/MSL a macOS). Pipeline únic: CPU framebuffer → transfer buffer →
// scene texture → PostFX pass → swapchain. Sense supersampling, sense
// CrtPi i sense Lanczos (reservats per a fases següents).
//
// Marcat `final` perquè el destructor crida cleanup() (que és virtual);
// sense final, clang-tidy avisa de dispatch virtual durant destrucció.
class SDL3GPUShader final : public ShaderBackend {
public:
SDL3GPUShader() = default;
~SDL3GPUShader() override;
SDL3GPUShader(const SDL3GPUShader&) = delete;
SDL3GPUShader(SDL3GPUShader&&) = delete;
auto operator=(const SDL3GPUShader&) -> SDL3GPUShader& = delete;
auto operator=(SDL3GPUShader&&) -> SDL3GPUShader& = delete;
auto init(SDL_Window* window, int game_width, int game_height) -> bool override;
void uploadPixels(const std::uint32_t* pixels, int width, int height) override;
void render() override;
void setPostFXParams(const PostFXParams& params) override;
void setVSync(bool vsync) override;
void setPreferredDriver(const std::string& driver) override { preferred_driver_ = driver; }
void cleanup() override;
// Allibera la finestra del device sense destruir el device. Cal cridar-ho
// abans de SDL_DestroyWindow perquè el VkSurface tancat no sobrevisca la
// finestra de Wayland (vkDestroyInstance cridaria Wayland amb surface invàlida).
void releaseWindow();
[[nodiscard]] auto isReady() const -> bool override { return is_ready_; }
[[nodiscard]] auto getDriverName() const -> std::string override { return driver_name_; }
private:
auto createDevice() -> bool;
auto createShaders() -> bool;
auto createPipeline() -> bool;
auto createResources() -> bool;
[[nodiscard]] auto bestPresentMode(bool vsync) const -> SDL_GPUPresentMode;
SDL_Window* window_{nullptr};
SDL_GPUDevice* device_{nullptr};
SDL_GPUShader* vertex_shader_{nullptr};
SDL_GPUShader* fragment_shader_{nullptr};
SDL_GPUGraphicsPipeline* pipeline_{nullptr};
SDL_GPUTexture* scene_texture_{nullptr};
SDL_GPUTransferBuffer* upload_buffer_{nullptr};
SDL_GPUSampler* sampler_{nullptr};
PostFXUniforms uniforms_{
.vignette_strength = 0.0F,
.chroma_strength = 0.0F,
.scanline_strength = 0.0F,
.screen_height = 0.0F,
.mask_strength = 0.0F,
.gamma_strength = 0.0F,
.curvature = 0.0F,
.bleeding = 0.0F,
.pixel_scale = 1.0F,
.time = 0.0F,
.oversample = 1.0F,
.flicker = 0.0F,
};
int game_width_{0};
int game_height_{0};
std::string preferred_driver_;
std::string driver_name_;
bool vsync_{true};
bool is_ready_{false};
};
} // namespace Rendering