treballant en internal resolution
This commit is contained in:
@@ -456,6 +456,11 @@ namespace Rendering {
|
||||
return false;
|
||||
}
|
||||
|
||||
// internal_texture_: si el multiplicador és > 1, es crea ací amb les
|
||||
// dimensions game·N × game·N. No bloqueja si falla — només deixa la
|
||||
// textura a nullptr i el pipeline ometrà la còpia.
|
||||
recreateInternalTexture();
|
||||
|
||||
// scaled_texture_ se creará en el primer render() una vez conocido el zoom de ventana
|
||||
ss_factor_ = 0;
|
||||
|
||||
@@ -812,14 +817,50 @@ namespace Rendering {
|
||||
SDL_EndGPUCopyPass(copy);
|
||||
}
|
||||
|
||||
// ---- Upscale pass: scene_texture_ → scaled_texture_ ----
|
||||
// ---- Internal resolution NN upscale: scene_texture_ → internal_texture_ ----
|
||||
// Multiplicador enter. Si > 1, tot el pipeline downstream veu internal_texture_
|
||||
// com a "scene" (mida game·N × game·N) i els passos següents (SS, PostFX,
|
||||
// Lanczos, letterbox) operen sobre aquesta font més gran. L'objectiu: quan el
|
||||
// filtre final LINEAR estira a finestra, parteix d'una base més gran i es veu
|
||||
// menys borrós. Amb internal_res_ == 1, s'omet el pas (zero overhead).
|
||||
SDL_GPUTexture* source_texture = scene_texture_;
|
||||
int source_width = game_width_;
|
||||
int source_height = game_height_;
|
||||
if (internal_res_ > 1 && internal_texture_ != nullptr && upscale_pipeline_ != nullptr) {
|
||||
SDL_GPUColorTargetInfo internal_target = {};
|
||||
internal_target.texture = internal_texture_;
|
||||
internal_target.load_op = SDL_GPU_LOADOP_DONT_CARE;
|
||||
internal_target.store_op = SDL_GPU_STOREOP_STORE;
|
||||
|
||||
SDL_GPURenderPass* ipass = SDL_BeginGPURenderPass(cmd, &internal_target, 1, nullptr);
|
||||
if (ipass != nullptr) {
|
||||
SDL_BindGPUGraphicsPipeline(ipass, upscale_pipeline_);
|
||||
SDL_GPUTextureSamplerBinding ibinding = {};
|
||||
ibinding.texture = scene_texture_;
|
||||
ibinding.sampler = sampler_; // sempre NEAREST per a la còpia de resolució interna
|
||||
SDL_BindGPUFragmentSamplers(ipass, 0, &ibinding, 1);
|
||||
SDL_DrawGPUPrimitives(ipass, 3, 1, 0, 0);
|
||||
SDL_EndGPURenderPass(ipass);
|
||||
}
|
||||
source_texture = internal_texture_;
|
||||
source_width = game_width_ * internal_res_;
|
||||
source_height = game_height_ * internal_res_;
|
||||
}
|
||||
|
||||
// ---- Upscale pass: source_texture → scaled_texture_ ----
|
||||
// Si 4:3 actiu, l'estirament s'aplica ací directament (320x200 → W*factor × H*factor*1.2)
|
||||
// El filtre s'aplica sempre (texture_filter_linear_), independent de 4:3.
|
||||
// L'effective_scene/height reflecteix la textura real que veuen els shaders.
|
||||
// Sense SS ni stretch: scene_texture_ a game_height_.
|
||||
// Amb SS o stretch: scaled_texture_ a l'alçada escalada (amb o sense 4:3).
|
||||
SDL_GPUTexture* effective_scene = scene_texture_;
|
||||
SDL_GPUTexture* effective_scene = source_texture;
|
||||
// `effective_height` reflecteix l'alçada lògica del frame (per a
|
||||
// scanlines i viewport), no la mida real de la textura. Es manté
|
||||
// a `game_height_` encara que internal_res_ > 1 — el multiplicador
|
||||
// només afecta la resolució física de la font, no l'aspect ni el
|
||||
// nombre de scanlines visibles.
|
||||
int effective_height = game_height_;
|
||||
(void)source_width; // només es fa servir com a context informatiu
|
||||
|
||||
if (oversample_ > 1 && scaled_texture_ != nullptr && upscale_pipeline_ != nullptr) {
|
||||
SDL_GPUColorTargetInfo upscale_target = {};
|
||||
@@ -834,7 +875,7 @@ namespace Rendering {
|
||||
if (upass != nullptr) {
|
||||
SDL_BindGPUGraphicsPipeline(upass, upscale_pipeline_);
|
||||
SDL_GPUTextureSamplerBinding ubinding = {};
|
||||
ubinding.texture = scene_texture_;
|
||||
ubinding.texture = source_texture;
|
||||
ubinding.sampler = (use_linear && linear_sampler_ != nullptr) ? linear_sampler_ : sampler_;
|
||||
SDL_BindGPUFragmentSamplers(upass, 0, &ubinding, 1);
|
||||
SDL_DrawGPUPrimitives(upass, 3, 1, 0, 0);
|
||||
@@ -846,6 +887,7 @@ namespace Rendering {
|
||||
// Sense SS: el viewport s'encarrega de l'estirament geomètric
|
||||
effective_height = static_cast<int>(static_cast<float>(game_height_) * 1.2F);
|
||||
}
|
||||
(void)source_height;
|
||||
|
||||
// ---- Acquire swapchain texture ----
|
||||
SDL_GPUTexture* swapchain = nullptr;
|
||||
@@ -1068,6 +1110,10 @@ namespace Rendering {
|
||||
SDL_ReleaseGPUTexture(device_, scene_texture_);
|
||||
scene_texture_ = nullptr;
|
||||
}
|
||||
if (internal_texture_ != nullptr) {
|
||||
SDL_ReleaseGPUTexture(device_, internal_texture_);
|
||||
internal_texture_ = nullptr;
|
||||
}
|
||||
if (scaled_texture_ != nullptr) {
|
||||
SDL_ReleaseGPUTexture(device_, scaled_texture_);
|
||||
scaled_texture_ = nullptr;
|
||||
@@ -1218,6 +1264,18 @@ namespace Rendering {
|
||||
scaling_mode_ = mode;
|
||||
}
|
||||
|
||||
// setInternalResolution — canvia el multiplicador de resolució interna.
|
||||
// Recrea la textura intermèdia amb les noves dimensions (320·N × 200·N).
|
||||
void SDL3GPUShader::setInternalResolution(int multiplier) {
|
||||
const int NEW = std::max(1, multiplier);
|
||||
if (NEW == internal_res_) return;
|
||||
internal_res_ = NEW;
|
||||
if (is_initialized_ && device_ != nullptr) {
|
||||
SDL_WaitForGPUIdle(device_);
|
||||
recreateInternalTexture();
|
||||
}
|
||||
}
|
||||
|
||||
void SDL3GPUShader::setStretch4_3(bool enabled) {
|
||||
stretch_4_3_ = enabled;
|
||||
if (!is_initialized_ || device_ == nullptr) return;
|
||||
@@ -1263,6 +1321,10 @@ namespace Rendering {
|
||||
SDL_ReleaseGPUTexture(device_, scene_texture_);
|
||||
scene_texture_ = nullptr;
|
||||
}
|
||||
if (internal_texture_ != nullptr) {
|
||||
SDL_ReleaseGPUTexture(device_, internal_texture_);
|
||||
internal_texture_ = nullptr;
|
||||
}
|
||||
// scaled_texture_ se libera aquí; se recreará en el primer render() con el factor correcto
|
||||
if (scaled_texture_ != nullptr) {
|
||||
SDL_ReleaseGPUTexture(device_, scaled_texture_);
|
||||
@@ -1305,10 +1367,15 @@ namespace Rendering {
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_Log("SDL3GPUShader: reinit — scene %dx%d, SS %s (scaled se creará en render)",
|
||||
// Recrea la textura interna si internal_res_ > 1 — manté coherència
|
||||
// en canvis d'SS que passen per reinitTexturesAndBuffer().
|
||||
recreateInternalTexture();
|
||||
|
||||
SDL_Log("SDL3GPUShader: reinit — scene %dx%d, SS %s, internal ×%d (scaled se creará en render)",
|
||||
game_width_,
|
||||
game_height_,
|
||||
oversample_ > 1 ? "on" : "off");
|
||||
oversample_ > 1 ? "on" : "off",
|
||||
internal_res_);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1379,4 +1446,39 @@ namespace Rendering {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// recreateInternalTexture — libera y recrea internal_texture_ para el
|
||||
// multiplicador internal_res_ actual. Si val 1, allibera i queda a nullptr
|
||||
// (el pipeline ometrà la còpia al següent render).
|
||||
// ---------------------------------------------------------------------------
|
||||
auto SDL3GPUShader::recreateInternalTexture() -> bool {
|
||||
if (internal_texture_ != nullptr) {
|
||||
SDL_ReleaseGPUTexture(device_, internal_texture_);
|
||||
internal_texture_ = nullptr;
|
||||
}
|
||||
if (internal_res_ <= 1 || device_ == nullptr) return true;
|
||||
|
||||
const int W = game_width_ * internal_res_;
|
||||
const int H = game_height_ * internal_res_;
|
||||
|
||||
SDL_GPUTextureCreateInfo info = {};
|
||||
info.type = SDL_GPU_TEXTURETYPE_2D;
|
||||
info.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
||||
info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
||||
info.width = static_cast<Uint32>(W);
|
||||
info.height = static_cast<Uint32>(H);
|
||||
info.layer_count_or_depth = 1;
|
||||
info.num_levels = 1;
|
||||
|
||||
internal_texture_ = SDL_CreateGPUTexture(device_, &info);
|
||||
if (internal_texture_ == nullptr) {
|
||||
SDL_Log("SDL3GPUShader: failed to create internal texture %dx%d (×%d): %s",
|
||||
W, H, internal_res_, SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_Log("SDL3GPUShader: internal texture %dx%d (×%d)", W, H, internal_res_);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
Reference in New Issue
Block a user