diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp index cb8e03c..3d647ee 100644 --- a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp @@ -273,25 +273,9 @@ namespace Rendering { return false; } - // ---------------------------------------------------------------- - // 3b. Create scaled texture (render target for upscale pass, only with SS) - // ---------------------------------------------------------------- - if (oversample_ > 1) { - SDL_GPUTextureCreateInfo scaled_info = {}; - scaled_info.type = SDL_GPU_TEXTURETYPE_2D; - scaled_info.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM; - scaled_info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COLOR_TARGET; - scaled_info.width = static_cast(game_width_ * oversample_); - scaled_info.height = static_cast(game_height_ * oversample_); - scaled_info.layer_count_or_depth = 1; - scaled_info.num_levels = 1; - scaled_texture_ = SDL_CreateGPUTexture(device_, &scaled_info); - if (scaled_texture_ == nullptr) { - SDL_Log("SDL3GPUShader: failed to create scaled texture: %s", SDL_GetError()); - cleanup(); - return false; - } - } + // scaled_texture_ se creará en el primer render() una vez conocido el tamaño de ventana + scaled_w_ = 0; + scaled_h_ = 0; // ---------------------------------------------------------------- // 4. Create upload transfer buffer (CPU → GPU, always game resolution) @@ -467,6 +451,19 @@ namespace Rendering { void SDL3GPUShader::render() { if (!is_initialized_) { return; } + // Paso 0: si SS activo, verificar si el tamaño de ventana cambió y recrear scaled_texture_ + if (oversample_ > 1) { + int win_w = 0; + int win_h = 0; + SDL_GetWindowSizeInPixels(window_, &win_w, &win_h); + const int NEED_W = win_w * oversample_; + const int NEED_H = win_h * oversample_; + if (NEED_W != scaled_w_ || NEED_H != scaled_h_) { + SDL_WaitForGPUIdle(device_); + recreateScaledTexture(NEED_W, NEED_H); + } + } + SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(device_); if (cmd == nullptr) { SDL_Log("SDL3GPUShader: SDL_AcquireGPUCommandBuffer failed: %s", SDL_GetError()); @@ -561,11 +558,11 @@ namespace Rendering { SDL_SetGPUViewport(pass, &vp); // pixel_scale: subpíxeles de textura por pixel lógico de juego. - // Sin SS: vh/game_height (zoom de ventana = subpíxeles por fila). - // Con SS: la textura entrada al PostFX tiene OS subfilas por fila lógica, - // así que pixel_scale = OS (independiente del zoom de ventana). - uniforms_.pixel_scale = (oversample_ > 1) - ? static_cast(oversample_) + // Sin SS: vh/game_height (zoom de ventana). + // Con SS: scaled_h_/game_height (= win_h*oversample_/game_height), que indica + // cuántas subfilas de la textura intermedia corresponden a cada fila lógica. + uniforms_.pixel_scale = (oversample_ > 1 && game_height_ > 0) + ? (static_cast(scaled_h_) / static_cast(game_height_)) : ((game_height_ > 0) ? (vh / static_cast(game_height_)) : 1.0F); uniforms_.time = static_cast(SDL_GetTicks()) / 1000.0F; uniforms_.oversample = static_cast(oversample_); @@ -619,6 +616,8 @@ namespace Rendering { SDL_ReleaseGPUTexture(device_, scaled_texture_); scaled_texture_ = nullptr; } + scaled_w_ = 0; + scaled_h_ = 0; if (upload_buffer_ != nullptr) { SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_); upload_buffer_ = nullptr; @@ -746,10 +745,14 @@ namespace Rendering { SDL_ReleaseGPUTexture(device_, scene_texture_); scene_texture_ = nullptr; } + // scaled_texture_ se libera aquí; se recreará en el primer render() con las dims de ventana if (scaled_texture_ != nullptr) { SDL_ReleaseGPUTexture(device_, scaled_texture_); scaled_texture_ = nullptr; } + scaled_w_ = 0; + scaled_h_ = 0; + if (upload_buffer_ != nullptr) { SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_); upload_buffer_ = nullptr; @@ -773,25 +776,6 @@ namespace Rendering { return false; } - // scaled_texture_: solo con SS - if (oversample_ > 1) { - SDL_GPUTextureCreateInfo scaled_info = {}; - scaled_info.type = SDL_GPU_TEXTURETYPE_2D; - scaled_info.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM; - scaled_info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COLOR_TARGET; - scaled_info.width = static_cast(game_width_ * oversample_); - scaled_info.height = static_cast(game_height_ * oversample_); - scaled_info.layer_count_or_depth = 1; - scaled_info.num_levels = 1; - scaled_texture_ = SDL_CreateGPUTexture(device_, &scaled_info); - if (scaled_texture_ == nullptr) { - SDL_Log("SDL3GPUShader: reinit — failed to create scaled texture: %s", SDL_GetError()); - SDL_ReleaseGPUTexture(device_, scene_texture_); - scene_texture_ = nullptr; - return false; - } - } - // upload_buffer_: siempre a resolución del juego SDL_GPUTransferBufferCreateInfo tb_info = {}; tb_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; @@ -799,15 +783,44 @@ namespace Rendering { upload_buffer_ = SDL_CreateGPUTransferBuffer(device_, &tb_info); if (upload_buffer_ == nullptr) { SDL_Log("SDL3GPUShader: reinit — failed to create upload buffer: %s", SDL_GetError()); - if (scaled_texture_ != nullptr) { SDL_ReleaseGPUTexture(device_, scaled_texture_); scaled_texture_ = nullptr; } SDL_ReleaseGPUTexture(device_, scene_texture_); scene_texture_ = nullptr; return false; } - SDL_Log("SDL3GPUShader: oversample %d — scene %dx%d, scaled %dx%d", - oversample_, game_width_, game_height_, - game_width_ * oversample_, game_height_ * oversample_); + SDL_Log("SDL3GPUShader: reinit — scene %dx%d, oversample %d (scaled se creará en render)", + game_width_, game_height_, oversample_); + return true; + } + + // --------------------------------------------------------------------------- + // recreateScaledTexture — libera y recrea scaled_texture_ con nuevas dimensiones. + // Llamar solo cuando device_ no esté ejecutando comandos (SDL_WaitForGPUIdle previo). + // --------------------------------------------------------------------------- + auto SDL3GPUShader::recreateScaledTexture(int w, int h) -> bool { + if (scaled_texture_ != nullptr) { + SDL_ReleaseGPUTexture(device_, scaled_texture_); + scaled_texture_ = nullptr; + } + scaled_w_ = 0; + scaled_h_ = 0; + + SDL_GPUTextureCreateInfo info = {}; + info.type = SDL_GPU_TEXTURETYPE_2D; + info.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM; + info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COLOR_TARGET; + info.width = static_cast(w); + info.height = static_cast(h); + info.layer_count_or_depth = 1; + info.num_levels = 1; + scaled_texture_ = SDL_CreateGPUTexture(device_, &info); + if (scaled_texture_ == nullptr) { + SDL_Log("SDL3GPUShader: failed to create scaled texture %dx%d: %s", w, h, SDL_GetError()); + return false; + } + scaled_w_ = w; + scaled_h_ = h; + SDL_Log("SDL3GPUShader: scaled texture %dx%d (oversample %d)", w, h, oversample_); return true; } diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp index 4d7e98d..e7d4302 100644 --- a/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp @@ -80,14 +80,15 @@ namespace Rendering { Uint32 num_uniform_buffers) -> SDL_GPUShader*; auto createPipeline() -> bool; - auto reinitTexturesAndBuffer() -> bool; // Recrea textura y buffer con oversample actual + auto reinitTexturesAndBuffer() -> bool; // Recrea scene_texture_ y upload_buffer_ + auto recreateScaledTexture(int w, int h) -> bool; // Recrea scaled_texture_ con nuevas dims SDL_Window* window_ = nullptr; SDL_GPUDevice* device_ = nullptr; SDL_GPUGraphicsPipeline* pipeline_ = nullptr; // PostFX pass SDL_GPUGraphicsPipeline* upscale_pipeline_ = nullptr; // Upscale nearest pass (solo con SS) - SDL_GPUTexture* scene_texture_ = nullptr; // Canvas del juego (game_width_ × game_height_) - SDL_GPUTexture* scaled_texture_ = nullptr; // Render target intermedio (game × OS), solo con SS + SDL_GPUTexture* scene_texture_ = nullptr; // Canvas del juego (game_width_ × game_height_) + SDL_GPUTexture* scaled_texture_ = nullptr; // Render target intermedio (win*SS × win*SS), solo con SS SDL_GPUTransferBuffer* upload_buffer_ = nullptr; SDL_GPUSampler* sampler_ = nullptr; // NEAREST SDL_GPUSampler* linear_sampler_ = nullptr; // LINEAR @@ -96,6 +97,8 @@ namespace Rendering { int game_width_ = 0; // Dimensiones originales del canvas int game_height_ = 0; + int scaled_w_ = 0; // Dimensiones actuales de scaled_texture_ (win*SS) + int scaled_h_ = 0; int oversample_ = 1; // Factor SS actual (1 o 3) bool is_initialized_ = false; bool vsync_ = true;