Files
coffee_crisis_arcade_edition/source/rendering/sdl3gpu/sdl3gpu_shader.hpp

155 lines
5.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include <SDL3/SDL.h>
#include <SDL3/SDL_gpu.h>
#include <string>
#include <utility>
#include "rendering/shader_backend.hpp"
// PostFX uniforms pushed to fragment stage each frame.
// 12 floats = 48 bytes — meets Metal/Vulkan 16-byte alignment requirement.
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;
};
// CrtPi uniforms pushed to fragment stage each frame.
// 16 fields = 64 bytes — 4 × 16-byte alignment.
struct CrtPiUniforms {
float scanline_weight;
float scanline_gap_brightness;
float bloom_factor;
float input_gamma;
float output_gamma;
float mask_brightness;
float curvature_x;
float curvature_y;
int mask_type;
int enable_scanlines;
int enable_multisample;
int enable_gamma;
int enable_curvature;
int enable_sharper;
float texture_width;
float texture_height;
};
// Downscale uniforms for Lanczos downscale fragment stage.
// 1 int + 3 floats = 16 bytes.
struct DownscaleUniforms {
int algorithm;
float pad0;
float pad1;
float pad2;
};
namespace Rendering {
/**
* @brief Backend de shaders usando SDL3 GPU API (Metal en macOS, Vulkan/SPIR-V en Win/Linux)
*
* Pipeline: Surface pixels (CPU) → SDL_GPUTransferBuffer → SDL_GPUTexture (scene)
* → [Upscale →] PostFX/CrtPi render pass → [Lanczos downscale →] swapchain → present
*/
class SDL3GPUShader : public ShaderBackend {
public:
SDL3GPUShader() = default;
~SDL3GPUShader() override;
auto init(SDL_Window* window,
SDL_Texture* texture,
const std::string& vertex_source,
const std::string& fragment_source) -> bool override;
void render() override;
void setTextureSize(float width, float height) override {}
void cleanup() final;
void destroy();
[[nodiscard]] auto isHardwareAccelerated() const -> bool override { return is_initialized_; }
[[nodiscard]] auto getDriverName() const -> std::string override { return driver_name_; }
void setPreferredDriver(const std::string& driver) override { preferred_driver_ = driver; }
void uploadPixels(const Uint32* pixels, int width, int height) override;
void setPostFXParams(const PostFXParams& p) override;
void setVSync(bool vsync) override;
void setScaleMode(bool integer_scale) override;
void setOversample(int factor) override;
void setLinearUpscale(bool linear) override;
[[nodiscard]] auto isLinearUpscale() const -> bool override { return linear_upscale_; }
void setDownscaleAlgo(int algo) override;
[[nodiscard]] auto getDownscaleAlgo() const -> int override { return downscale_algo_; }
[[nodiscard]] auto getSsTextureSize() const -> std::pair<int, int> override;
void setActiveShader(ShaderType type) override;
void setCrtPiParams(const CrtPiParams& p) override;
[[nodiscard]] auto getActiveShader() const -> ShaderType override { return active_shader_; }
private:
static auto createShaderMSL(SDL_GPUDevice* device,
const char* msl_source,
const char* entrypoint,
SDL_GPUShaderStage stage,
Uint32 num_samplers,
Uint32 num_uniform_buffers) -> SDL_GPUShader*;
static auto createShaderSPIRV(SDL_GPUDevice* device,
const uint8_t* spv_code,
size_t spv_size,
const char* entrypoint,
SDL_GPUShaderStage stage,
Uint32 num_samplers,
Uint32 num_uniform_buffers) -> SDL_GPUShader*;
auto createPipeline() -> bool;
auto createCrtPiPipeline() -> bool;
auto reinitTexturesAndBuffer() -> bool;
auto recreateScaledTexture(int factor) -> bool;
static auto calcSsFactor(float zoom) -> int;
[[nodiscard]] auto bestPresentMode(bool vsync) const -> SDL_GPUPresentMode;
SDL_Window* window_ = nullptr;
SDL_GPUDevice* device_ = nullptr;
SDL_GPUGraphicsPipeline* pipeline_ = nullptr;
SDL_GPUGraphicsPipeline* crtpi_pipeline_ = nullptr;
SDL_GPUGraphicsPipeline* postfx_offscreen_pipeline_ = nullptr;
SDL_GPUGraphicsPipeline* upscale_pipeline_ = nullptr;
SDL_GPUGraphicsPipeline* downscale_pipeline_ = nullptr;
SDL_GPUTexture* scene_texture_ = nullptr;
SDL_GPUTexture* scaled_texture_ = nullptr;
SDL_GPUTexture* postfx_texture_ = nullptr;
SDL_GPUTransferBuffer* upload_buffer_ = nullptr;
SDL_GPUSampler* sampler_ = nullptr;
SDL_GPUSampler* linear_sampler_ = nullptr;
PostFXUniforms uniforms_{.vignette_strength = 0.6F, .chroma_strength = 0.15F, .scanline_strength = 0.7F, .screen_height = 192.0F, .pixel_scale = 1.0F, .oversample = 1.0F};
CrtPiUniforms crtpi_uniforms_{.scanline_weight = 6.0F, .scanline_gap_brightness = 0.12F, .bloom_factor = 3.5F, .input_gamma = 2.4F, .output_gamma = 2.2F, .mask_brightness = 0.80F, .curvature_x = 0.05F, .curvature_y = 0.10F, .mask_type = 2, .enable_scanlines = 1, .enable_multisample = 1, .enable_gamma = 1};
ShaderType active_shader_ = ShaderType::POSTFX;
int game_width_ = 0;
int game_height_ = 0;
int ss_factor_ = 0;
int oversample_ = 1;
int downscale_algo_ = 1;
std::string driver_name_;
std::string preferred_driver_;
bool is_initialized_ = false;
bool vsync_ = true;
bool integer_scale_ = false;
bool linear_upscale_ = false;
};
} // namespace Rendering