// gpu_bloom_pipeline.hpp - Pipeline gráfico per al bloom separable de dues passes.
// © 2026 JailDesigner
//
// El bloom es calcula en dues passes 1D (horizontal i vertical) abans del pase
// final de composite. La mateixa instància de pipeline serveix per a tots dos
// passes; només canvien els uniformes (direction + extract).
//
// Recursos del shader (SDL_gpu set bindings):
//   fragment set=2, binding=0 → sampler2D (input)
//   fragment set=3, binding=0 → uniform buffer (paràmetres del blur)
//
// Per al vertex shader es reutilitza postfx.vert.glsl (fullscreen triangle).

#pragma once

#include <SDL3/SDL_gpu.h>

namespace Rendering::GPU {

    class GpuDevice;

    // Uniform buffer del bloom. Ha de coincidir EXACTAMENT amb shaders/bloom.frag.glsl
    // (std140 — vec2 alineats a 8 bytes; padding a 16).
    struct BloomUniforms {
        float texel_size_x;  // 1.0 / texture_width
        float texel_size_y;  // 1.0 / texture_height
        float direction_x;   // 1.0 per pass H, 0.0 per pass V
        float direction_y;   // 0.0 per pass H, 1.0 per pass V

        float threshold;  // luminància mínima per al high-pass (només si extract>0)
        float extract;    // 1.0 = pass H amb high-pass, 0.0 = pass V (blur pur)
        float sigma;      // amplada de la gaussiana en texels
        float pad_a;      // alineament a 16 bytes
    };

    class GpuBloomPipeline {
       public:
        GpuBloomPipeline() = default;
        ~GpuBloomPipeline();

        GpuBloomPipeline(const GpuBloomPipeline&) = delete;
        auto operator=(const GpuBloomPipeline&) -> GpuBloomPipeline& = delete;
        GpuBloomPipeline(GpuBloomPipeline&&) = delete;
        auto operator=(GpuBloomPipeline&&) -> GpuBloomPipeline& = delete;

        // target_format: format del color target on s'escriu el resultat (bloom
        // texture, idealment el mateix format que l'offscreen per portabilitat).
        [[nodiscard]] auto init(const GpuDevice& device,
            SDL_GPUTextureFormat target_format) -> bool;
        void destroy();

        [[nodiscard]] auto get() const -> SDL_GPUGraphicsPipeline* { return pipeline_; }

       private:
        SDL_GPUDevice* owner_{nullptr};
        SDL_GPUGraphicsPipeline* pipeline_{nullptr};
    };

}  // namespace Rendering::GPU
