From 2b2eb31c67c34bdf89ebbeafdf905a666c4539a6 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sat, 21 Mar 2026 13:31:42 +0100 Subject: [PATCH] treballant en postfx --- CMakeLists.txt | 20 +- source/core/rendering/screen.cpp | 86 +++- source/core/rendering/screen.hpp | 3 + .../core/rendering/sdl3gpu/postfx_frag_spv.h | 5 + .../core/rendering/sdl3gpu/postfx_vert_spv.h | 5 + .../core/rendering/sdl3gpu/sdl3gpu_shader.cpp | 419 ++++++++++++++++++ .../core/rendering/sdl3gpu/sdl3gpu_shader.hpp | 76 ++++ source/core/rendering/shader_backend.hpp | 6 + source/core/rendering/surface.cpp | 13 + source/core/rendering/surface.hpp | 3 + source/game/scene_manager.hpp | 2 +- 11 files changed, 613 insertions(+), 25 deletions(-) create mode 100644 source/core/rendering/sdl3gpu/postfx_frag_spv.h create mode 100644 source/core/rendering/sdl3gpu/postfx_vert_spv.h create mode 100644 source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp create mode 100644 source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f82f3deb..7be65305 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,9 +111,17 @@ set(APP_SOURCES ) # Fuentes del sistema de renderizado -set(RENDERING_SOURCES - source/core/rendering/opengl/opengl_shader.cpp -) +# En macOS usamos SDL3 GPU (Metal), no OpenGL +if(APPLE) + set(RENDERING_SOURCES + source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp + ) +else() + set(RENDERING_SOURCES + source/core/rendering/opengl/opengl_shader.cpp + source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp + ) +endif() # Fuentes de debug (solo en modo Debug) set(DEBUG_SOURCES @@ -161,8 +169,10 @@ elseif(UNIX AND NOT APPLE) target_compile_definitions(${PROJECT_NAME} PRIVATE LINUX_BUILD) endif() -# Configuración común para OpenGL -if(NOT WIN32) +# Configuración común para OpenGL (no requerido en macOS: usamos SDL3 GPU API / Metal) +if(WIN32) + target_link_libraries(${PROJECT_NAME} PRIVATE opengl32) +elseif(NOT APPLE) find_package(OpenGL REQUIRED) if(OPENGL_FOUND) message(STATUS "OpenGL encontrado: ${OPENGL_LIBRARIES}") diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index 3b9906a4..58010bc4 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -10,7 +10,10 @@ #include // Para char_traits, string, operator+, operator== #include "core/input/mouse.hpp" // Para updateCursorVisibility +#ifndef __APPLE__ #include "core/rendering/opengl/opengl_shader.hpp" // Para OpenGLShader +#endif +#include "core/rendering/sdl3gpu/sdl3gpu_shader.hpp" // Para SDL3GPUShader #include "core/rendering/surface.hpp" // Para Surface, readPalFile #include "core/rendering/text.hpp" // Para Text #include "core/resources/resource_cache.hpp" // Para Resource @@ -124,13 +127,16 @@ void Screen::start() { setRendererSurface(nullptr); } void Screen::render() { fps_.increment(); - // Renderiza todos los overlays + // Renderiza todos los overlays (escribe en game_surface_ CPU-side) renderOverlays(); - // Copia la surface a la textura - surfaceToTexture(); + // En el path SDL3GPU, los píxeles se suben directamente desde la Surface. + // En el path SDL_Renderer, primero copiamos la surface a la SDL_Texture. + if (!(Options::video.shaders && shader_backend_ && shader_backend_->isHardwareAccelerated())) { + surfaceToTexture(); + } - // Copia la textura al renderizador + // Copia la textura al renderizador (o hace el present GPU) textureToRenderer(); } @@ -206,7 +212,12 @@ void Screen::renderNotifications() const { // Cambia el estado de los shaders void Screen::toggleShaders() { Options::video.shaders = !Options::video.shaders; - initShaders(); + if (!Options::video.shaders && shader_backend_) { + // Al desactivar shaders, limpiar el backend para liberar el swapchain de GPU + shader_backend_->cleanup(); + } else { + initShaders(); + } } // Actualiza la lógica de la clase (versión nueva con delta_time para escenas migradas) @@ -304,13 +315,42 @@ void Screen::surfaceToTexture() { } } -// Copia la textura al renderizador +// Copia la textura al renderizador (o hace el present GPU) void Screen::textureToRenderer() { SDL_Texture* texture_to_render = Options::video.border.enabled ? border_texture_ : game_texture_; - if (Options::video.shaders && shader_backend_) { + if (Options::video.shaders && shader_backend_ && shader_backend_->isHardwareAccelerated()) { + // ---- SDL3 GPU path: convertir Surface → ARGB → upload → PostFX → present ---- + if (Options::video.border.enabled) { + // El border_surface_ solo tiene el color de borde; hay que componer encima el game_surface_ + const int BORDER_W = static_cast(border_surface_->getWidth()); + const int BORDER_H = static_cast(border_surface_->getHeight()); + pixel_buffer_.resize(static_cast(BORDER_W * BORDER_H)); + border_surface_->toARGBBuffer(pixel_buffer_.data()); + + // Compositar game_surface_ en la posición correcta dentro del buffer + const int GAME_W = static_cast(game_surface_->getWidth()); + const int GAME_H = static_cast(game_surface_->getHeight()); + const int OFF_X = static_cast(game_surface_dstrect_.x); + const int OFF_Y = static_cast(game_surface_dstrect_.y); + std::vector game_pixels(static_cast(GAME_W * GAME_H)); + game_surface_->toARGBBuffer(game_pixels.data()); + for (int y = 0; y < GAME_H; ++y) { + for (int x = 0; x < GAME_W; ++x) { + pixel_buffer_[static_cast(((OFF_Y + y) * BORDER_W) + (OFF_X + x))] = game_pixels[static_cast((y * GAME_W) + x)]; + } + } + shader_backend_->uploadPixels(pixel_buffer_.data(), BORDER_W, BORDER_H); + } else { + const int GAME_W = static_cast(game_surface_->getWidth()); + const int GAME_H = static_cast(game_surface_->getHeight()); + pixel_buffer_.resize(static_cast(GAME_W * GAME_H)); + game_surface_->toARGBBuffer(pixel_buffer_.data()); + shader_backend_->uploadPixels(pixel_buffer_.data(), GAME_W, GAME_H); + } shader_backend_->render(); } else { + // ---- SDL_Renderer path (fallback / no-shader) ---- SDL_SetRenderTarget(renderer_, nullptr); SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF); SDL_RenderClear(renderer_); @@ -437,19 +477,25 @@ void Screen::loadShaders() { // Inicializa los shaders void Screen::initShaders() { -#ifndef __APPLE__ - if (Options::video.shaders) { - loadShaders(); - if (!shader_backend_) { - shader_backend_ = std::make_unique(); - } - shader_backend_->init(window_, Options::video.border.enabled ? border_texture_ : game_texture_, vertex_shader_source_, fragment_shader_source_); - // shader_backend_->init(window_, shaders_texture_, vertex_shader_source_, fragment_shader_source_); + if (!Options::video.shaders) { + return; } + + SDL_Texture* tex = Options::video.border.enabled ? border_texture_ : game_texture_; + +#ifdef __APPLE__ + // macOS: usar SDL3 GPU API (Metal) via SDL3GPUShader + if (!shader_backend_) { + shader_backend_ = std::make_unique(); + } + shader_backend_->init(window_, tex, "", ""); #else - // En macOS, OpenGL está deprecated y rinde mal - // TODO: Implementar backend de Metal para shaders en macOS - std::cout << "WARNING: Shaders no disponibles en macOS (OpenGL deprecated). Usa Metal backend.\n"; + // Win/Linux: usar OpenGL + GLSL + loadShaders(); + if (!shader_backend_) { + shader_backend_ = std::make_unique(); + } + shader_backend_->init(window_, tex, vertex_shader_source_, fragment_shader_source_); #endif } @@ -537,7 +583,9 @@ auto Screen::initSDLVideo() -> bool { const auto WINDOW_WIDTH = Options::video.border.enabled ? Options::game.width + (Options::video.border.width * 2) : Options::game.width; const auto WINDOW_HEIGHT = Options::video.border.enabled ? Options::game.height + (Options::video.border.height * 2) : Options::game.height; #ifdef __APPLE__ - SDL_WindowFlags window_flags = SDL_WINDOW_METAL; + // SDL_WINDOW_METAL no es necesario: SDL3GPU autodetecta Metal via SDL_CreateGPUDevice. + // SDL_Renderer también usará Metal si está disponible (via hint o autoselección). + SDL_WindowFlags window_flags = 0; #elif defined(LINUX_BUILD) // En Linux, SDL_WINDOW_OPENGL puede entrar en conflicto con el backend del renderer; // el hint SDL_HINT_RENDER_DRIVER="opengl" es suficiente para seleccionar OpenGL. diff --git a/source/core/rendering/screen.hpp b/source/core/rendering/screen.hpp index 2a22b2dd..b9468fb2 100644 --- a/source/core/rendering/screen.hpp +++ b/source/core/rendering/screen.hpp @@ -7,6 +7,8 @@ #include // Para string #include // Para vector +#include // Para Uint32 + #include "utils/utils.hpp" // Para Color class Surface; class Text; @@ -155,6 +157,7 @@ class Screen { std::string info_resolution_; // Texto con la información de la pantalla std::string vertex_shader_source_; // Almacena el vertex shader std::string fragment_shader_source_; // Almacena el fragment shader + std::vector pixel_buffer_; // Buffer intermedio para SDL3GPU path (surface → ARGB) #ifdef _DEBUG bool show_debug_info_{true}; // Indica si ha de mostrar la información de debug diff --git a/source/core/rendering/sdl3gpu/postfx_frag_spv.h b/source/core/rendering/sdl3gpu/postfx_frag_spv.h new file mode 100644 index 00000000..812e720d --- /dev/null +++ b/source/core/rendering/sdl3gpu/postfx_frag_spv.h @@ -0,0 +1,5 @@ +#pragma once +#include +#include +static const uint8_t kpostfx_frag_spv[] = { 0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x0b,0x00,0x0d,0x00,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00,0x01,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30,0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x07,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x10,0x00,0x03,0x00,0x04,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0x04,0x00,0x0a,0x00,0x47,0x4c,0x5f,0x47,0x4f,0x4f,0x47,0x4c,0x45,0x5f,0x63,0x70,0x70,0x5f,0x73,0x74,0x79,0x6c,0x65,0x5f,0x6c,0x69,0x6e,0x65,0x5f,0x64,0x69,0x72,0x65,0x63,0x74,0x69,0x76,0x65,0x00,0x00,0x04,0x00,0x08,0x00,0x47,0x4c,0x5f,0x47,0x4f,0x4f,0x47,0x4c,0x45,0x5f,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x5f,0x64,0x69,0x72,0x65,0x63,0x74,0x69,0x76,0x65,0x00,0x05,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x08,0x00,0x00,0x00,0x63,0x61,0x00,0x00,0x05,0x00,0x06,0x00,0x09,0x00,0x00,0x00,0x50,0x6f,0x73,0x74,0x46,0x58,0x55,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x73,0x00,0x00,0x06,0x00,0x08,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x69,0x67,0x6e,0x65,0x74,0x74,0x65,0x5f,0x73,0x74,0x72,0x65,0x6e,0x67,0x74,0x68,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x63,0x68,0x72,0x6f,0x6d,0x61,0x5f,0x73,0x74,0x72,0x65,0x6e,0x67,0x74,0x68,0x00,0x06,0x00,0x08,0x00,0x09,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x73,0x63,0x61,0x6e,0x6c,0x69,0x6e,0x65,0x5f,0x73,0x74,0x72,0x65,0x6e,0x67,0x74,0x68,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x73,0x63,0x72,0x65,0x65,0x6e,0x5f,0x68,0x65,0x69,0x67,0x68,0x74,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x0b,0x00,0x00,0x00,0x75,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0x15,0x00,0x00,0x00,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0x19,0x00,0x00,0x00,0x73,0x63,0x65,0x6e,0x65,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0x1d,0x00,0x00,0x00,0x76,0x5f,0x75,0x76,0x00,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0x3d,0x00,0x00,0x00,0x73,0x63,0x61,0x6e,0x00,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x5d,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x62,0x00,0x00,0x00,0x76,0x69,0x67,0x6e,0x65,0x74,0x74,0x65,0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x77,0x00,0x00,0x00,0x6f,0x75,0x74,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x00,0x47,0x00,0x03,0x00,0x09,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x09,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x0b,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x0b,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x19,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x19,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x1d,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x77,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x21,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x16,0x00,0x03,0x00,0x06,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x1e,0x00,0x06,0x00,0x09,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x0a,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0a,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x0c,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x0c,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x0a,0xd7,0xa3,0x3b,0x17,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x14,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x19,0x00,0x09,0x00,0x16,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x00,0x03,0x00,0x17,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x18,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x1b,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x1c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x1c,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x24,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x24,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x24,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x24,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x24,0x00,0x00,0x00,0x3a,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x9a,0x99,0x59,0x3f,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x9a,0x99,0x19,0x3e,0x20,0x00,0x04,0x00,0x40,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x43,0x00,0x00,0x00,0xdb,0x0f,0x49,0x40,0x2b,0x00,0x04,0x00,0x0c,0x00,0x00,0x00,0x45,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x2b,0x00,0x04,0x00,0x0c,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x52,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x5c,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x2c,0x00,0x05,0x00,0x1b,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x0c,0x00,0x00,0x00,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x76,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x76,0x00,0x00,0x00,0x77,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x36,0x00,0x05,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x05,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x14,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x5c,0x00,0x00,0x00,0x5d,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x62,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0e,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x08,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x17,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x1b,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x50,0x00,0x05,0x00,0x1b,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x1b,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x57,0x00,0x05,0x00,0x13,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x27,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x17,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x1b,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x57,0x00,0x05,0x00,0x13,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x2d,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x17,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x1b,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x50,0x00,0x05,0x00,0x1b,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x1b,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x57,0x00,0x05,0x00,0x13,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x36,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x17,0x00,0x00,0x00,0x37,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x1b,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x57,0x00,0x05,0x00,0x13,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0x37,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x3b,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x3a,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x3c,0x00,0x00,0x00,0x3b,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x40,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x43,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0e,0x00,0x00,0x00,0x46,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x45,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x47,0x00,0x00,0x00,0x46,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x44,0x00,0x00,0x00,0x47,0x00,0x00,0x00,0x0c,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x49,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x49,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x3d,0x00,0x00,0x00,0x4b,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x4d,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0e,0x00,0x00,0x00,0x4f,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x4f,0x00,0x00,0x00,0x0c,0x00,0x08,0x00,0x06,0x00,0x00,0x00,0x51,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x4d,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x53,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x4f,0x00,0x08,0x00,0x52,0x00,0x00,0x00,0x54,0x00,0x00,0x00,0x53,0x00,0x00,0x00,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x8e,0x00,0x05,0x00,0x52,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x54,0x00,0x00,0x00,0x51,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x56,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x56,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x59,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x58,0x00,0x00,0x00,0x59,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x5b,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x5a,0x00,0x00,0x00,0x5b,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x1b,0x00,0x00,0x00,0x5e,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x1b,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x5e,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x5d,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x1b,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0x5d,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x1b,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x5d,0x00,0x00,0x00,0x94,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x63,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x0e,0x00,0x00,0x00,0x67,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x66,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x67,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x83,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x6a,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x62,0x00,0x00,0x00,0x6a,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x6b,0x00,0x00,0x00,0x62,0x00,0x00,0x00,0x0c,0x00,0x08,0x00,0x06,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x6b,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x4f,0x00,0x08,0x00,0x52,0x00,0x00,0x00,0x6e,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x8e,0x00,0x05,0x00,0x52,0x00,0x00,0x00,0x6f,0x00,0x00,0x00,0x6e,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x71,0x00,0x00,0x00,0x6f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x70,0x00,0x00,0x00,0x71,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x72,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x73,0x00,0x00,0x00,0x6f,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x72,0x00,0x00,0x00,0x73,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x74,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x75,0x00,0x00,0x00,0x6f,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x74,0x00,0x00,0x00,0x75,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x77,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00 }; +static const size_t kpostfx_frag_spv_size = 3024; diff --git a/source/core/rendering/sdl3gpu/postfx_vert_spv.h b/source/core/rendering/sdl3gpu/postfx_vert_spv.h new file mode 100644 index 00000000..915e8316 --- /dev/null +++ b/source/core/rendering/sdl3gpu/postfx_vert_spv.h @@ -0,0 +1,5 @@ +#pragma once +#include +#include +static const uint8_t kpostfx_vert_spv[] = { 0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x0b,0x00,0x0d,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00,0x01,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30,0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0x04,0x00,0x0a,0x00,0x47,0x4c,0x5f,0x47,0x4f,0x4f,0x47,0x4c,0x45,0x5f,0x63,0x70,0x70,0x5f,0x73,0x74,0x79,0x6c,0x65,0x5f,0x6c,0x69,0x6e,0x65,0x5f,0x64,0x69,0x72,0x65,0x63,0x74,0x69,0x76,0x65,0x00,0x00,0x04,0x00,0x08,0x00,0x47,0x4c,0x5f,0x47,0x4f,0x4f,0x47,0x4c,0x45,0x5f,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x5f,0x64,0x69,0x72,0x65,0x63,0x74,0x69,0x76,0x65,0x00,0x05,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x0c,0x00,0x00,0x00,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x73,0x00,0x00,0x00,0x05,0x00,0x03,0x00,0x13,0x00,0x00,0x00,0x75,0x76,0x73,0x00,0x05,0x00,0x06,0x00,0x1e,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x65,0x72,0x56,0x65,0x72,0x74,0x65,0x78,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x06,0x00,0x07,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74,0x53,0x69,0x7a,0x65,0x00,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x1e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x67,0x6c,0x5f,0x43,0x6c,0x69,0x70,0x44,0x69,0x73,0x74,0x61,0x6e,0x63,0x65,0x00,0x06,0x00,0x07,0x00,0x1e,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x67,0x6c,0x5f,0x43,0x75,0x6c,0x6c,0x44,0x69,0x73,0x74,0x61,0x6e,0x63,0x65,0x00,0x05,0x00,0x03,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x06,0x00,0x24,0x00,0x00,0x00,0x67,0x6c,0x5f,0x56,0x65,0x72,0x74,0x65,0x78,0x49,0x6e,0x64,0x65,0x78,0x00,0x00,0x05,0x00,0x04,0x00,0x2f,0x00,0x00,0x00,0x76,0x5f,0x75,0x76,0x00,0x00,0x00,0x00,0x47,0x00,0x03,0x00,0x1e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x1e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x1e,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x24,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x2f,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x21,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x16,0x00,0x03,0x00,0x06,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1c,0x00,0x04,0x00,0x0a,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x0b,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x80,0xbf,0x2c,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x2c,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x2c,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x2c,0x00,0x06,0x00,0x0a,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x2c,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x06,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x2c,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x2c,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x2c,0x00,0x06,0x00,0x0a,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x1b,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x04,0x00,0x1d,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x1e,0x00,0x06,0x00,0x1e,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x1f,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x1f,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x21,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x21,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x23,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x23,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x26,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x2c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x2e,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x2e,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x36,0x00,0x05,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x05,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0b,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0b,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x0c,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x13,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x21,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x26,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x06,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x50,0x00,0x07,0x00,0x1b,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x2c,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x2d,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x21,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x26,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x2f,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00 }; +static const size_t kpostfx_vert_spv_size = 1436; diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp new file mode 100644 index 00000000..5fe5e974 --- /dev/null +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp @@ -0,0 +1,419 @@ +#include "core/rendering/sdl3gpu/sdl3gpu_shader.hpp" + +#include + +#include // memcpy, strlen + +#ifndef __APPLE__ +#include "core/rendering/sdl3gpu/postfx_frag_spv.h" +#include "core/rendering/sdl3gpu/postfx_vert_spv.h" +#endif + +#ifdef __APPLE__ +// ============================================================================ +// MSL shaders (Metal Shading Language) — macOS +// ============================================================================ + +// NOLINTBEGIN(readability-identifier-naming) +static const char* POSTFX_VERT_MSL = R"( +#include +using namespace metal; + +struct PostVOut { + float4 pos [[position]]; + float2 uv; +}; + +vertex PostVOut postfx_vs(uint vid [[vertex_id]]) { + const float2 positions[3] = { {-1.0, -1.0}, {3.0, -1.0}, {-1.0, 3.0} }; + const float2 uvs[3] = { { 0.0, 1.0}, {2.0, 1.0}, { 0.0,-1.0} }; + PostVOut out; + out.pos = float4(positions[vid], 0.0, 1.0); + out.uv = uvs[vid]; + return out; +} +)"; + +static const char* POSTFX_FRAG_MSL = R"( +#include +using namespace metal; + +struct PostVOut { + float4 pos [[position]]; + float2 uv; +}; + +struct PostFXUniforms { + float vignette_strength; + float chroma_strength; + float scanline_strength; + float screen_height; +}; + +fragment float4 postfx_fs(PostVOut in [[stage_in]], + texture2d scene [[texture(0)]], + sampler samp [[sampler(0)]], + constant PostFXUniforms& u [[buffer(0)]]) { + float ca = u.chroma_strength * 0.005; + float4 color; + color.r = scene.sample(samp, in.uv + float2( ca, 0.0)).r; + color.g = scene.sample(samp, in.uv).g; + color.b = scene.sample(samp, in.uv - float2( ca, 0.0)).b; + color.a = scene.sample(samp, in.uv).a; + + float scan = 0.85 + 0.15 * sin(in.uv.y * 3.14159265 * u.screen_height); + color.rgb *= mix(1.0, scan, u.scanline_strength); + + float2 d = in.uv - float2(0.5, 0.5); + float vignette = 1.0 - dot(d, d) * u.vignette_strength; + color.rgb *= clamp(vignette, 0.0, 1.0); + + return color; +} +)"; +// NOLINTEND(readability-identifier-naming) + +#endif // __APPLE__ + +namespace Rendering { + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +SDL3GPUShader::~SDL3GPUShader() { + cleanup(); +} + +// --------------------------------------------------------------------------- +// init +// --------------------------------------------------------------------------- +auto SDL3GPUShader::init(SDL_Window* window, + SDL_Texture* texture, + const std::string& /*vertex_source*/, + const std::string& /*fragment_source*/) -> bool { + // Si ya estaba inicializado, limpiar antes de reinicializar (p.ej. al cambiar borde) + if (is_initialized_) { + cleanup(); + } + + window_ = window; + + // Dimensions from the SDL_Texture placeholder + float fw = 0.0F; + float fh = 0.0F; + SDL_GetTextureSize(texture, &fw, &fh); + tex_width_ = static_cast(fw); + tex_height_ = static_cast(fh); + uniforms_.screen_height = fh; + + // ---------------------------------------------------------------- + // 1. Create GPU device + // ---------------------------------------------------------------- +#ifdef __APPLE__ + const SDL_GPUShaderFormat PREFERRED = SDL_GPU_SHADERFORMAT_MSL | SDL_GPU_SHADERFORMAT_METALLIB; +#else + const SDL_GPUShaderFormat PREFERRED = SDL_GPU_SHADERFORMAT_SPIRV; +#endif + device_ = SDL_CreateGPUDevice(PREFERRED, false, nullptr); + if (device_ == nullptr) { + SDL_Log("SDL3GPUShader: SDL_CreateGPUDevice failed: %s", SDL_GetError()); + return false; + } + SDL_Log("SDL3GPUShader: driver = %s", SDL_GetGPUDeviceDriver(device_)); + + // ---------------------------------------------------------------- + // 2. Claim window (GPU device owns the swapchain from now on) + // ---------------------------------------------------------------- + if (!SDL_ClaimWindowForGPUDevice(device_, window_)) { + SDL_Log("SDL3GPUShader: SDL_ClaimWindowForGPUDevice failed: %s", SDL_GetError()); + SDL_DestroyGPUDevice(device_); + device_ = nullptr; + return false; + } + SDL_SetGPUSwapchainParameters(device_, window_, + SDL_GPU_SWAPCHAINCOMPOSITION_SDR, + SDL_GPU_PRESENTMODE_VSYNC); + + // ---------------------------------------------------------------- + // 3. Create scene texture (upload target + sampler source) + // Format: B8G8R8A8_UNORM matches SDL ARGB8888 byte layout on LE + // ---------------------------------------------------------------- + SDL_GPUTextureCreateInfo tex_info = {}; + tex_info.type = SDL_GPU_TEXTURETYPE_2D; + tex_info.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM; + tex_info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER; + tex_info.width = static_cast(tex_width_); + tex_info.height = static_cast(tex_height_); + tex_info.layer_count_or_depth = 1; + tex_info.num_levels = 1; + scene_texture_ = SDL_CreateGPUTexture(device_, &tex_info); + if (scene_texture_ == nullptr) { + SDL_Log("SDL3GPUShader: failed to create scene texture: %s", SDL_GetError()); + cleanup(); + return false; + } + + // ---------------------------------------------------------------- + // 4. Create upload transfer buffer (CPU → GPU, size = w*h*4 bytes) + // ---------------------------------------------------------------- + SDL_GPUTransferBufferCreateInfo tb_info = {}; + tb_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; + tb_info.size = static_cast(tex_width_ * tex_height_ * 4); + upload_buffer_ = SDL_CreateGPUTransferBuffer(device_, &tb_info); + if (upload_buffer_ == nullptr) { + SDL_Log("SDL3GPUShader: failed to create upload buffer: %s", SDL_GetError()); + cleanup(); + return false; + } + + // ---------------------------------------------------------------- + // 5. Create nearest-neighbour sampler (retro pixel art) + // ---------------------------------------------------------------- + SDL_GPUSamplerCreateInfo samp_info = {}; + samp_info.min_filter = SDL_GPU_FILTER_NEAREST; + samp_info.mag_filter = SDL_GPU_FILTER_NEAREST; + samp_info.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST; + samp_info.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + samp_info.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + samp_info.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + sampler_ = SDL_CreateGPUSampler(device_, &samp_info); + if (sampler_ == nullptr) { + SDL_Log("SDL3GPUShader: failed to create sampler: %s", SDL_GetError()); + cleanup(); + return false; + } + + // ---------------------------------------------------------------- + // 6. Create PostFX graphics pipeline + // ---------------------------------------------------------------- + if (!createPipeline()) { + cleanup(); + return false; + } + + is_initialized_ = true; + SDL_Log("SDL3GPUShader: initialized OK (%dx%d)", tex_width_, tex_height_); + return true; +} + +// --------------------------------------------------------------------------- +// createPipeline +// --------------------------------------------------------------------------- +auto SDL3GPUShader::createPipeline() -> bool { + const SDL_GPUTextureFormat SWAPCHAIN_FMT = SDL_GetGPUSwapchainTextureFormat(device_, window_); + +#ifdef __APPLE__ + SDL_GPUShader* vert = createShaderMSL(device_, POSTFX_VERT_MSL, "postfx_vs", + SDL_GPU_SHADERSTAGE_VERTEX, 0, 0); + SDL_GPUShader* frag = createShaderMSL(device_, POSTFX_FRAG_MSL, "postfx_fs", + SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 1); +#else + SDL_GPUShader* vert = createShaderSPIRV(device_, kpostfx_vert_spv, kpostfx_vert_spv_size, + "main", SDL_GPU_SHADERSTAGE_VERTEX, 0, 0); + SDL_GPUShader* frag = createShaderSPIRV(device_, kpostfx_frag_spv, kpostfx_frag_spv_size, + "main", SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 1); +#endif + + if ((vert == nullptr) || (frag == nullptr)) { + SDL_Log("SDL3GPUShader: failed to compile PostFX shaders"); + if (vert != nullptr) { SDL_ReleaseGPUShader(device_, vert); } + if (frag != nullptr) { SDL_ReleaseGPUShader(device_, frag); } + return false; + } + + SDL_GPUColorTargetBlendState no_blend = {}; + no_blend.enable_blend = false; + no_blend.enable_color_write_mask = false; + + SDL_GPUColorTargetDescription color_target = {}; + color_target.format = SWAPCHAIN_FMT; + color_target.blend_state = no_blend; + + SDL_GPUVertexInputState no_input = {}; + + SDL_GPUGraphicsPipelineCreateInfo pipe_info = {}; + pipe_info.vertex_shader = vert; + pipe_info.fragment_shader = frag; + pipe_info.vertex_input_state = no_input; + pipe_info.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST; + pipe_info.target_info.num_color_targets = 1; + pipe_info.target_info.color_target_descriptions = &color_target; + + pipeline_ = SDL_CreateGPUGraphicsPipeline(device_, &pipe_info); + + SDL_ReleaseGPUShader(device_, vert); + SDL_ReleaseGPUShader(device_, frag); + + if (pipeline_ == nullptr) { + SDL_Log("SDL3GPUShader: pipeline creation failed: %s", SDL_GetError()); + return false; + } + return true; +} + +// --------------------------------------------------------------------------- +// uploadPixels — copies ARGB8888 CPU pixels into the GPU transfer buffer +// --------------------------------------------------------------------------- +void SDL3GPUShader::uploadPixels(const Uint32* pixels, int width, int height) { + if (!is_initialized_ || (upload_buffer_ == nullptr)) { return; } + + void* mapped = SDL_MapGPUTransferBuffer(device_, upload_buffer_, false); + if (mapped == nullptr) { + SDL_Log("SDL3GPUShader: SDL_MapGPUTransferBuffer failed: %s", SDL_GetError()); + return; + } + std::memcpy(mapped, pixels, static_cast(width * height * 4)); + SDL_UnmapGPUTransferBuffer(device_, upload_buffer_); +} + +// --------------------------------------------------------------------------- +// render — upload scene texture + PostFX pass → swapchain +// --------------------------------------------------------------------------- +void SDL3GPUShader::render() { + if (!is_initialized_) { return; } + + SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(device_); + if (cmd == nullptr) { + SDL_Log("SDL3GPUShader: SDL_AcquireGPUCommandBuffer failed: %s", SDL_GetError()); + return; + } + + // ---- Copy pass: transfer buffer → scene texture ---- + SDL_GPUCopyPass* copy = SDL_BeginGPUCopyPass(cmd); + if (copy != nullptr) { + SDL_GPUTextureTransferInfo src = {}; + src.transfer_buffer = upload_buffer_; + src.offset = 0; + src.pixels_per_row = static_cast(tex_width_); + src.rows_per_layer = static_cast(tex_height_); + + SDL_GPUTextureRegion dst = {}; + dst.texture = scene_texture_; + dst.w = static_cast(tex_width_); + dst.h = static_cast(tex_height_); + dst.d = 1; + + SDL_UploadToGPUTexture(copy, &src, &dst, false); + SDL_EndGPUCopyPass(copy); + } + + // ---- Acquire swapchain texture ---- + SDL_GPUTexture* swapchain = nullptr; + Uint32 sw = 0; + Uint32 sh = 0; + if (!SDL_AcquireGPUSwapchainTexture(cmd, window_, &swapchain, &sw, &sh)) { + SDL_Log("SDL3GPUShader: SDL_AcquireGPUSwapchainTexture failed: %s", SDL_GetError()); + SDL_SubmitGPUCommandBuffer(cmd); + return; + } + if (swapchain == nullptr) { + // Window minimized — skip frame + SDL_SubmitGPUCommandBuffer(cmd); + return; + } + + // ---- Render pass: PostFX → swapchain ---- + SDL_GPUColorTargetInfo color_target = {}; + color_target.texture = swapchain; + color_target.load_op = SDL_GPU_LOADOP_CLEAR; + color_target.store_op = SDL_GPU_STOREOP_STORE; + color_target.clear_color = {.r = 0.0F, .g = 0.0F, .b = 0.0F, .a = 1.0F}; + + SDL_GPURenderPass* pass = SDL_BeginGPURenderPass(cmd, &color_target, 1, nullptr); + if (pass != nullptr) { + SDL_BindGPUGraphicsPipeline(pass, pipeline_); + + SDL_GPUTextureSamplerBinding binding = {}; + binding.texture = scene_texture_; + binding.sampler = sampler_; + SDL_BindGPUFragmentSamplers(pass, 0, &binding, 1); + + SDL_PushGPUFragmentUniformData(cmd, 0, &uniforms_, sizeof(PostFXUniforms)); + + SDL_DrawGPUPrimitives(pass, 3, 1, 0, 0); + SDL_EndGPURenderPass(pass); + } + + SDL_SubmitGPUCommandBuffer(cmd); +} + +// --------------------------------------------------------------------------- +// cleanup +// --------------------------------------------------------------------------- +void SDL3GPUShader::cleanup() { + is_initialized_ = false; + + if (device_ != nullptr) { + SDL_WaitForGPUIdle(device_); + + if (pipeline_ != nullptr) { + SDL_ReleaseGPUGraphicsPipeline(device_, pipeline_); + pipeline_ = nullptr; + } + if (scene_texture_ != nullptr) { + SDL_ReleaseGPUTexture(device_, scene_texture_); + scene_texture_ = nullptr; + } + if (upload_buffer_ != nullptr) { + SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_); + upload_buffer_ = nullptr; + } + if (sampler_ != nullptr) { + SDL_ReleaseGPUSampler(device_, sampler_); + sampler_ = nullptr; + } + + SDL_ReleaseWindowFromGPUDevice(device_, window_); + SDL_DestroyGPUDevice(device_); + device_ = nullptr; + } + window_ = nullptr; +} + +// --------------------------------------------------------------------------- +// Shader creation helpers +// --------------------------------------------------------------------------- +auto SDL3GPUShader::createShaderMSL(SDL_GPUDevice* device, + const char* msl_source, + const char* entrypoint, + SDL_GPUShaderStage stage, + Uint32 num_samplers, + Uint32 num_uniform_buffers) -> SDL_GPUShader* { + SDL_GPUShaderCreateInfo info = {}; + info.code = reinterpret_cast(msl_source); + info.code_size = std::strlen(msl_source) + 1; + info.entrypoint = entrypoint; + info.format = SDL_GPU_SHADERFORMAT_MSL; + info.stage = stage; + info.num_samplers = num_samplers; + info.num_uniform_buffers = num_uniform_buffers; + SDL_GPUShader* shader = SDL_CreateGPUShader(device, &info); + if (shader == nullptr) { + SDL_Log("SDL3GPUShader: MSL shader '%s' failed: %s", entrypoint, SDL_GetError()); + } + return shader; +} + +auto SDL3GPUShader::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* { + SDL_GPUShaderCreateInfo info = {}; + info.code = spv_code; + info.code_size = spv_size; + info.entrypoint = entrypoint; + info.format = SDL_GPU_SHADERFORMAT_SPIRV; + info.stage = stage; + info.num_samplers = num_samplers; + info.num_uniform_buffers = num_uniform_buffers; + SDL_GPUShader* shader = SDL_CreateGPUShader(device, &info); + if (shader == nullptr) { + SDL_Log("SDL3GPUShader: SPIRV shader '%s' failed: %s", entrypoint, SDL_GetError()); + } + return shader; +} + +} // namespace Rendering diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp new file mode 100644 index 00000000..8c09b333 --- /dev/null +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp @@ -0,0 +1,76 @@ +#pragma once + +#include +#include + +#include "core/rendering/shader_backend.hpp" + +// PostFX uniforms pushed to fragment stage each frame. +// Must match the MSL struct and GLSL uniform block layout. +struct PostFXUniforms { + float vignette_strength; // 0 = none, ~0.8 = subtle + float chroma_strength; // 0 = off, ~0.2 = subtle chromatic aberration + float scanline_strength; // 0 = off, 1 = full + float screen_height; // logical height in pixels (for resolution-independent scanlines) +}; + +namespace Rendering { + +/** + * @brief Backend de shaders usando SDL3 GPU API (Metal en macOS, Vulkan/SPIR-V en Win/Linux) + * + * Reemplaza el backend OpenGL para que los shaders PostFX funcionen en macOS. + * Pipeline: Surface pixels (CPU) → SDL_GPUTransferBuffer → SDL_GPUTexture (scene) + * → PostFX render pass → 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() override; + [[nodiscard]] auto isHardwareAccelerated() const -> bool override { return is_initialized_; } + + // Sube píxeles ARGB8888 desde CPU; llamado antes de render() + void uploadPixels(const Uint32* pixels, int width, int height) override; + + 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; + + SDL_Window* window_ = nullptr; + SDL_GPUDevice* device_ = nullptr; + SDL_GPUGraphicsPipeline* pipeline_ = nullptr; + SDL_GPUTexture* scene_texture_ = nullptr; + SDL_GPUTransferBuffer* upload_buffer_ = nullptr; + SDL_GPUSampler* sampler_ = nullptr; + + PostFXUniforms uniforms_{.vignette_strength = 0.6F, .chroma_strength = 0.15F, .scanline_strength = 0.7F, .screen_height = 192.0F}; + + int tex_width_ = 0; + int tex_height_ = 0; + bool is_initialized_ = false; +}; + +} // namespace Rendering diff --git a/source/core/rendering/shader_backend.hpp b/source/core/rendering/shader_backend.hpp index d75558f4..2a554331 100644 --- a/source/core/rendering/shader_backend.hpp +++ b/source/core/rendering/shader_backend.hpp @@ -46,6 +46,12 @@ class ShaderBackend { */ virtual void cleanup() = 0; + /** + * @brief Sube píxeles ARGB8888 desde la CPU al backend de shaders + * Usado por SDL3GPUShader para evitar pasar por SDL_Texture + */ + virtual void uploadPixels(const Uint32* /*pixels*/, int /*width*/, int /*height*/) {} + /** * @brief Verifica si el backend está usando aceleración por hardware * @return true si usa aceleración (OpenGL/Metal/Vulkan) diff --git a/source/core/rendering/surface.cpp b/source/core/rendering/surface.cpp index d3d9bed5..9b98359d 100644 --- a/source/core/rendering/surface.cpp +++ b/source/core/rendering/surface.cpp @@ -524,6 +524,19 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height } } +// Vuelca los píxeles como ARGB8888 a un buffer externo (sin SDL_Texture ni SDL_Renderer) +void Surface::toARGBBuffer(Uint32* buffer) const { + if (!surface_data_ || (surface_data_->data == nullptr)) { return; } + const int WIDTH = static_cast(surface_data_->width); + const int HEIGHT = static_cast(surface_data_->height); + const Uint8* src = surface_data_->data.get(); + for (int y = 0; y < HEIGHT; ++y) { + for (int x = 0; x < WIDTH; ++x) { + buffer[(y * WIDTH) + x] = palette_[src[(y * WIDTH) + x]]; + } + } +} + // Vuelca la superficie a una textura void Surface::copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture) { if ((renderer == nullptr) || (texture == nullptr) || !surface_data_) { diff --git a/source/core/rendering/surface.hpp b/source/core/rendering/surface.hpp index 4118295c..1a375f52 100644 --- a/source/core/rendering/surface.hpp +++ b/source/core/rendering/surface.hpp @@ -106,6 +106,9 @@ class Surface { auto fadePalette() -> bool; auto fadeSubPalette(Uint32 delay = 0) -> bool; + // Vuelca los píxeles como ARGB8888 a un buffer externo (sin SDL_Texture) + void toARGBBuffer(Uint32* buffer) const; + // Pone un pixel en la SurfaceData void putPixel(int x, int y, Uint8 color); diff --git a/source/game/scene_manager.hpp b/source/game/scene_manager.hpp index d54a8d2c..62e79ae3 100644 --- a/source/game/scene_manager.hpp +++ b/source/game/scene_manager.hpp @@ -34,7 +34,7 @@ enum class Options { // --- Variables de estado globales --- #ifdef _DEBUG -inline Scene current = Scene::ENDING2; // Escena actual +inline Scene current = Scene::GAME; // Escena actual inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual #else inline Scene current = Scene::LOGO; // Escena actual