feat(shaders): sistema de shaders runtime amb presets externs
- Afegir GpuShaderPreset i ShaderManager per carregar shaders des de data/shaders/ - Implementar preset ntsc-md-rainbows (2 passos: encode + decode MAME NTSC) - Render loop multi-pass per shaders externs (targets intermedis R16G16B16A16_FLOAT) - cycleShader(): cicla OFF→PostFX natius→shaders externs amb tecla X - --shader <nom> per arrancar directament amb un preset extern - CMake auto-descubreix i compila data/shaders/**/*.vert/.frag → .spv - HUD F1 mostra 'Shader: <nom>' quan hi ha shader extern actiu Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
68
source/gpu/shader_manager.cpp
Normal file
68
source/gpu/shader_manager.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "shader_manager.hpp"
|
||||
|
||||
#include <SDL3/SDL_log.h>
|
||||
#include <filesystem>
|
||||
#include <algorithm>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
void ShaderManager::scan(const std::string& root_dir) {
|
||||
root_dir_ = root_dir;
|
||||
names_.clear();
|
||||
dirs_.clear();
|
||||
|
||||
std::error_code ec;
|
||||
for (const auto& entry : fs::directory_iterator(root_dir, ec)) {
|
||||
if (!entry.is_directory()) continue;
|
||||
fs::path ini = entry.path() / "preset.ini";
|
||||
if (!fs::exists(ini)) continue;
|
||||
|
||||
std::string preset_name = entry.path().filename().string();
|
||||
names_.push_back(preset_name);
|
||||
dirs_[preset_name] = entry.path().string();
|
||||
}
|
||||
|
||||
if (ec) {
|
||||
SDL_Log("ShaderManager: scan error on %s: %s", root_dir.c_str(), ec.message().c_str());
|
||||
}
|
||||
|
||||
std::sort(names_.begin(), names_.end());
|
||||
SDL_Log("ShaderManager: found %d preset(s) in %s", (int)names_.size(), root_dir.c_str());
|
||||
}
|
||||
|
||||
GpuShaderPreset* ShaderManager::load(SDL_GPUDevice* device,
|
||||
const std::string& name,
|
||||
SDL_GPUTextureFormat swapchain_fmt,
|
||||
int w, int h) {
|
||||
auto it = loaded_.find(name);
|
||||
if (it != loaded_.end()) return it->second.get();
|
||||
|
||||
auto dir_it = dirs_.find(name);
|
||||
if (dir_it == dirs_.end()) {
|
||||
SDL_Log("ShaderManager: preset '%s' not found", name.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto preset = std::make_unique<GpuShaderPreset>();
|
||||
if (!preset->load(device, dir_it->second, swapchain_fmt, w, h)) {
|
||||
SDL_Log("ShaderManager: failed to load preset '%s'", name.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GpuShaderPreset* raw = preset.get();
|
||||
loaded_[name] = std::move(preset);
|
||||
return raw;
|
||||
}
|
||||
|
||||
void ShaderManager::onResize(SDL_GPUDevice* device, SDL_GPUTextureFormat /*swapchain_fmt*/, int w, int h) {
|
||||
for (auto& [name, preset] : loaded_) {
|
||||
preset->recreateTargets(device, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderManager::destroyAll(SDL_GPUDevice* device) {
|
||||
for (auto& [name, preset] : loaded_) {
|
||||
preset->destroy(device);
|
||||
}
|
||||
loaded_.clear();
|
||||
}
|
||||
Reference in New Issue
Block a user