implementat lanzcos en el supersampling

This commit is contained in:
2026-03-27 21:59:14 +01:00
parent c063488e8e
commit 3712f0c8d9
11 changed files with 1890 additions and 13859 deletions

View File

@@ -0,0 +1,48 @@
#version 450
layout(location = 0) in vec2 v_uv;
layout(location = 0) out vec4 out_color;
layout(set = 2, binding = 0) uniform sampler2D source;
layout(set = 3, binding = 0) uniform DownscaleUniforms {
int algorithm; // 0 = Lanczos2 (ventana 2, ±2 taps), 1 = Lanczos3 (ventana 3, ±3 taps)
float pad0;
float pad1;
float pad2;
} u;
// Kernel Lanczos normalizado: sinc(t) * sinc(t/a) para |t| < a, 0 fuera.
float lanczos(float t, float a) {
t = abs(t);
if (t < 0.0001) { return 1.0; }
if (t >= a) { return 0.0; }
const float PI = 3.14159265358979;
float pt = PI * t;
return (a * sin(pt) * sin(pt / a)) / (pt * pt);
}
void main() {
vec2 src_size = vec2(textureSize(source, 0));
// Posición en coordenadas de texel (centros de texel en N+0.5)
vec2 p = v_uv * src_size;
vec2 p_floor = floor(p);
float a = (u.algorithm == 0) ? 2.0 : 3.0;
int win = int(a);
vec4 color = vec4(0.0);
float weight_sum = 0.0;
for (int j = -win; j <= win; j++) {
for (int i = -win; i <= win; i++) {
// Centro del texel (i,j) relativo a p_floor
vec2 tap_center = p_floor + vec2(float(i), float(j)) + 0.5;
vec2 offset = tap_center - p;
float w = lanczos(offset.x, a) * lanczos(offset.y, a);
color += texture(source, tap_center / src_size) * w;
weight_sum += w;
}
}
out_color = (weight_sum > 0.0) ? (color / weight_sum) : vec4(0.0, 0.0, 0.0, 1.0);
}

View File

@@ -528,6 +528,18 @@ auto loadData(const std::string& filepath) -> std::vector<uint8_t> {
return Resource::Helper::loadFile(filepath); return Resource::Helper::loadFile(filepath);
} }
void Screen::setLinearUpscale(bool linear) {
if (shader_backend_ && shader_backend_->isHardwareAccelerated()) {
shader_backend_->setLinearUpscale(linear);
}
}
void Screen::setDownscaleAlgo(int algo) {
if (shader_backend_ && shader_backend_->isHardwareAccelerated()) {
shader_backend_->setDownscaleAlgo(algo);
}
}
// Activa/desactiva el supersampling global (Ctrl+F4) // Activa/desactiva el supersampling global (Ctrl+F4)
void Screen::toggleSupersampling() { void Screen::toggleSupersampling() {
Options::video.supersampling = !Options::video.supersampling; Options::video.supersampling = !Options::video.supersampling;

View File

@@ -59,6 +59,8 @@ class Screen {
void togglePostFX(); // Cambia el estado del PostFX void togglePostFX(); // Cambia el estado del PostFX
void toggleSupersampling(); // Activa/desactiva el supersampling global void toggleSupersampling(); // Activa/desactiva el supersampling global
void reloadPostFX(); // Recarga el shader del preset actual sin toggle void reloadPostFX(); // Recarga el shader del preset actual sin toggle
void setLinearUpscale(bool linear); // Upscale NEAREST (false) o LINEAR (true) en el paso SS
void setDownscaleAlgo(int algo); // 0=bilinear legacy, 1=Lanczos2, 2=Lanczos3
// Surfaces y notificaciones // Surfaces y notificaciones
void setRendererSurface(const std::shared_ptr<Surface>& surface = nullptr); // Establece el renderizador para las surfaces void setRendererSurface(const std::shared_ptr<Surface>& surface = nullptr); // Establece el renderizador para las surfaces

View File

@@ -0,0 +1,360 @@
#pragma once
#include <cstdint>
#include <cstddef>
static const uint8_t kdownscale_frag_spv[] = {
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00,
0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x32, 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, 0x41, 0x00, 0x00, 0x00,
0xa4, 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, 0x06, 0x00,
0x0b, 0x00, 0x00, 0x00, 0x6c, 0x61, 0x6e, 0x63, 0x7a, 0x6f, 0x73, 0x28,
0x66, 0x31, 0x3b, 0x66, 0x31, 0x3b, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
0x09, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
0x0a, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x70, 0x74, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
0x33, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65,
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
0x3f, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
0x41, 0x00, 0x00, 0x00, 0x76, 0x5f, 0x75, 0x76, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x04, 0x00, 0x45, 0x00, 0x00, 0x00, 0x70, 0x5f, 0x66, 0x6c,
0x6f, 0x6f, 0x72, 0x00, 0x05, 0x00, 0x03, 0x00, 0x48, 0x00, 0x00, 0x00,
0x61, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, 0x49, 0x00, 0x00, 0x00,
0x44, 0x6f, 0x77, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x55, 0x6e, 0x69,
0x66, 0x6f, 0x72, 0x6d, 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x6c, 0x67, 0x6f,
0x72, 0x69, 0x74, 0x68, 0x6d, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00,
0x49, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x30,
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x49, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x31, 0x00, 0x00, 0x00, 0x00,
0x06, 0x00, 0x05, 0x00, 0x49, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x70, 0x61, 0x64, 0x32, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
0x4b, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
0x54, 0x00, 0x00, 0x00, 0x77, 0x69, 0x6e, 0x00, 0x05, 0x00, 0x04, 0x00,
0x59, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00,
0x05, 0x00, 0x05, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x77, 0x65, 0x69, 0x67,
0x68, 0x74, 0x5f, 0x73, 0x75, 0x6d, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
0x5c, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
0x67, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
0x72, 0x00, 0x00, 0x00, 0x74, 0x61, 0x70, 0x5f, 0x63, 0x65, 0x6e, 0x74,
0x65, 0x72, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x7d, 0x00, 0x00, 0x00,
0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
0x81, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
0x82, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00,
0x05, 0x00, 0x04, 0x00, 0x87, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61,
0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x8a, 0x00, 0x00, 0x00,
0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
0x8e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00,
0x05, 0x00, 0x05, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x5f,
0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
0x37, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x47, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x41, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
0x49, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x49, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x48, 0x00, 0x05, 0x00, 0x49, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
0x49, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4b, 0x00, 0x00, 0x00,
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
0x4b, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
0x47, 0x00, 0x04, 0x00, 0xa4, 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, 0x21, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x17, 0xb7, 0xd1, 0x38, 0x14, 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x00,
0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x3f, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0xdb, 0x0f, 0x49, 0x40,
0x17, 0x00, 0x04, 0x00, 0x31, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00,
0x34, 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,
0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x04, 0x00, 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
0x39, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x17, 0x00, 0x04, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x06, 0x00, 0x49, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x20, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x49, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00,
0x4b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x20, 0x00, 0x04, 0x00,
0x53, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
0x17, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x07, 0x00,
0x57, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0x15, 0x00, 0x04, 0x00, 0x83, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
0x83, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2b, 0x00, 0x04, 0x00, 0x83, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00,
0x9f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
0xa3, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x04, 0x00, 0xa3, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x07, 0x00, 0x57, 0x00, 0x00, 0x00,
0xaf, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00, 0x15, 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, 0x32, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00,
0x3f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
0x32, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x53, 0x00, 0x00, 0x00,
0x54, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
0x58, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x53, 0x00, 0x00, 0x00,
0x5c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
0x53, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x32, 0x00, 0x00, 0x00,
0x7d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
0x07, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
0x87, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
0x07, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
0xa7, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x35, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
0x64, 0x00, 0x04, 0x00, 0x34, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
0x38, 0x00, 0x00, 0x00, 0x67, 0x00, 0x05, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00,
0x6f, 0x00, 0x04, 0x00, 0x31, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x31, 0x00, 0x00, 0x00,
0x42, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x31, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
0x85, 0x00, 0x05, 0x00, 0x31, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
0x42, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
0x3f, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x31, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x03, 0x00, 0x45, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00,
0x41, 0x00, 0x05, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
0x4b, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x39, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00,
0xaa, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
0x4e, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x06, 0x00,
0x06, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00,
0x50, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
0x48, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
0x6e, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00,
0x55, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00,
0x56, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x59, 0x00, 0x00, 0x00,
0x5a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x5b, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00,
0x5d, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x04, 0x00,
0x39, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x03, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
0xf9, 0x00, 0x02, 0x00, 0x5f, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
0x5f, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00,
0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
0x63, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x63, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
0x5c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00,
0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x05, 0x00,
0x11, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
0x65, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x66, 0x00, 0x00, 0x00,
0x60, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
0x60, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00,
0x68, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x04, 0x00,
0x39, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x03, 0x00, 0x67, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00,
0xf9, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
0x6a, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x6c, 0x00, 0x00, 0x00,
0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
0x6e, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x6e, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
0x67, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00,
0x70, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x05, 0x00,
0x11, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
0x70, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x71, 0x00, 0x00, 0x00,
0x6b, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
0x6b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x31, 0x00, 0x00, 0x00,
0x73, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x39, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00,
0x6f, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00,
0x74, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00,
0x76, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
0x50, 0x00, 0x05, 0x00, 0x31, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
0x75, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00,
0x31, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00,
0x78, 0x00, 0x00, 0x00, 0x50, 0x00, 0x05, 0x00, 0x31, 0x00, 0x00, 0x00,
0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00,
0x81, 0x00, 0x05, 0x00, 0x31, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
0x79, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
0x72, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x31, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x31, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
0x3f, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x31, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x03, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
0x41, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00,
0x7d, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x03, 0x00, 0x82, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
0x48, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x87, 0x00, 0x00, 0x00,
0x88, 0x00, 0x00, 0x00, 0x39, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,
0x89, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00,
0x87, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
0x8c, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00,
0x8c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x8a, 0x00, 0x00, 0x00,
0x8d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
0x8f, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
0x8e, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x39, 0x00, 0x06, 0x00,
0x06, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x8a, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
0x06, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00,
0x90, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x81, 0x00, 0x00, 0x00,
0x91, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x35, 0x00, 0x00, 0x00,
0x92, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x31, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x31, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
0x33, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x31, 0x00, 0x00, 0x00,
0x95, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
0x57, 0x00, 0x05, 0x00, 0x57, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00,
0x92, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00,
0x8e, 0x00, 0x05, 0x00, 0x57, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
0x96, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x57, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
0x81, 0x00, 0x05, 0x00, 0x57, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00,
0x99, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
0x59, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00,
0x5b, 0x00, 0x00, 0x00, 0x81, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
0x9d, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x03, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00,
0xf9, 0x00, 0x02, 0x00, 0x6d, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
0x6d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00,
0x9e, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
0x39, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,
0x9f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x67, 0x00, 0x00, 0x00,
0xa0, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x6a, 0x00, 0x00, 0x00,
0xf8, 0x00, 0x02, 0x00, 0x6c, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
0x62, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x62, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x39, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00,
0x5c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x39, 0x00, 0x00, 0x00,
0xa2, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x03, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00,
0xf9, 0x00, 0x02, 0x00, 0x5f, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
0x61, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
0xa5, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0xba, 0x00, 0x05, 0x00,
0x11, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0xa9, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0xa6, 0x00, 0x00, 0x00,
0xa8, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
0xa8, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00,
0xaa, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00,
0x50, 0x00, 0x07, 0x00, 0x57, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00,
0xab, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00,
0xab, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x57, 0x00, 0x00, 0x00,
0xad, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x03, 0x00, 0xa7, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00,
0xf9, 0x00, 0x02, 0x00, 0xa9, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
0xae, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0xa7, 0x00, 0x00, 0x00,
0xaf, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0xa9, 0x00, 0x00, 0x00,
0xf8, 0x00, 0x02, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x57, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x03, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00,
0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00,
0x06, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00,
0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
0xb8, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00,
0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0xf8, 0x00, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00,
0x15, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x09, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x05, 0x00,
0x11, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x1b, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00,
0x1a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
0x1a, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x00, 0x00,
0xf8, 0x00, 0x02, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x06, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,
0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
0x23, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
0x25, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
0x27, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00,
0x06, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
0x27, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00,
0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
0x28, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
0x2a, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
0x2c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
0x06, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
0x2c, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
0x2e, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
0xfe, 0x00, 0x02, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00
};
static const size_t kdownscale_frag_spv_size = 4248;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@
#include <cstring> // memcpy, strlen #include <cstring> // memcpy, strlen
#ifndef __APPLE__ #ifndef __APPLE__
#include "core/rendering/sdl3gpu/downscale_frag_spv.h"
#include "core/rendering/sdl3gpu/postfx_frag_spv.h" #include "core/rendering/sdl3gpu/postfx_frag_spv.h"
#include "core/rendering/sdl3gpu/postfx_vert_spv.h" #include "core/rendering/sdl3gpu/postfx_vert_spv.h"
#include "core/rendering/sdl3gpu/upscale_frag_spv.h" #include "core/rendering/sdl3gpu/upscale_frag_spv.h"
@@ -187,6 +188,46 @@ fragment float4 upscale_fs(VertOut in [[stage_in]],
return scene.sample(smp, in.uv); return scene.sample(smp, in.uv);
} }
)"; )";
static const char* DOWNSCALE_FRAG_MSL = R"(
#include <metal_stdlib>
using namespace metal;
struct VertOut { float4 pos [[position]]; float2 uv; };
struct DownscaleUniforms { int algorithm; float pad0; float pad1; float pad2; };
static float lanczos_w(float t, float a) {
t = abs(t);
if (t < 0.0001f) { return 1.0f; }
if (t >= a) { return 0.0f; }
const float PI = 3.14159265358979f;
float pt = PI * t;
return (a * sin(pt) * sin(pt / a)) / (pt * pt);
}
fragment float4 downscale_fs(VertOut in [[stage_in]],
texture2d<float> source [[texture(0)]],
sampler smp [[sampler(0)]],
constant DownscaleUniforms& u [[buffer(0)]])
{
float2 src_size = float2(source.get_width(), source.get_height());
float2 p = in.uv * src_size;
float2 p_floor = floor(p);
float a = (u.algorithm == 0) ? 2.0f : 3.0f;
int win = int(a);
float4 color = float4(0.0f);
float weight_sum = 0.0f;
for (int j = -win; j <= win; j++) {
for (int i = -win; i <= win; i++) {
float2 tap_center = p_floor + float2(float(i), float(j)) + 0.5f;
float2 offset = tap_center - p;
float w = lanczos_w(offset.x, a) * lanczos_w(offset.y, a);
color += source.sample(smp, tap_center / src_size) * w;
weight_sum += w;
}
}
return (weight_sum > 0.0f) ? (color / weight_sum) : float4(0.0f, 0.0f, 0.0f, 1.0f);
}
)";
// NOLINTEND(readability-identifier-naming) // NOLINTEND(readability-identifier-naming)
#endif // __APPLE__ #endif // __APPLE__
@@ -421,6 +462,83 @@ namespace Rendering {
return false; return false;
} }
// ---- PostFX offscreen pipeline (scaled_texture_ → postfx_texture_, B8G8R8A8) ----
// Mismos shaders que pipeline_ pero con formato de salida B8G8R8A8_UNORM para textura intermedia.
#ifdef __APPLE__
SDL_GPUShader* ofvert = createShaderMSL(device_, POSTFX_VERT_MSL, "postfx_vs", SDL_GPU_SHADERSTAGE_VERTEX, 0, 0);
SDL_GPUShader* offrag = createShaderMSL(device_, POSTFX_FRAG_MSL, "postfx_fs", SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 1);
#else
SDL_GPUShader* ofvert = createShaderSPIRV(device_, kpostfx_vert_spv, kpostfx_vert_spv_size, "main", SDL_GPU_SHADERSTAGE_VERTEX, 0, 0);
SDL_GPUShader* offrag = createShaderSPIRV(device_, kpostfx_frag_spv, kpostfx_frag_spv_size, "main", SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 1);
#endif
if ((ofvert == nullptr) || (offrag == nullptr)) {
SDL_Log("SDL3GPUShader: failed to compile PostFX offscreen shaders");
if (ofvert != nullptr) { SDL_ReleaseGPUShader(device_, ofvert); }
if (offrag != nullptr) { SDL_ReleaseGPUShader(device_, offrag); }
return false;
}
SDL_GPUColorTargetDescription offscreen_color_target = {};
offscreen_color_target.format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM;
offscreen_color_target.blend_state = no_blend;
SDL_GPUGraphicsPipelineCreateInfo offscreen_pipe_info = {};
offscreen_pipe_info.vertex_shader = ofvert;
offscreen_pipe_info.fragment_shader = offrag;
offscreen_pipe_info.vertex_input_state = no_input;
offscreen_pipe_info.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST;
offscreen_pipe_info.target_info.num_color_targets = 1;
offscreen_pipe_info.target_info.color_target_descriptions = &offscreen_color_target;
postfx_offscreen_pipeline_ = SDL_CreateGPUGraphicsPipeline(device_, &offscreen_pipe_info);
SDL_ReleaseGPUShader(device_, ofvert);
SDL_ReleaseGPUShader(device_, offrag);
if (postfx_offscreen_pipeline_ == nullptr) {
SDL_Log("SDL3GPUShader: PostFX offscreen pipeline creation failed: %s", SDL_GetError());
return false;
}
// ---- Downscale pipeline (postfx_texture_ → swapchain, Lanczos) ----
#ifdef __APPLE__
SDL_GPUShader* dvert = createShaderMSL(device_, POSTFX_VERT_MSL, "postfx_vs", SDL_GPU_SHADERSTAGE_VERTEX, 0, 0);
SDL_GPUShader* dfrag = createShaderMSL(device_, DOWNSCALE_FRAG_MSL, "downscale_fs", SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 1);
#else
SDL_GPUShader* dvert = createShaderSPIRV(device_, kpostfx_vert_spv, kpostfx_vert_spv_size, "main", SDL_GPU_SHADERSTAGE_VERTEX, 0, 0);
SDL_GPUShader* dfrag = createShaderSPIRV(device_, kdownscale_frag_spv, kdownscale_frag_spv_size, "main", SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 1);
#endif
if ((dvert == nullptr) || (dfrag == nullptr)) {
SDL_Log("SDL3GPUShader: failed to compile downscale shaders");
if (dvert != nullptr) { SDL_ReleaseGPUShader(device_, dvert); }
if (dfrag != nullptr) { SDL_ReleaseGPUShader(device_, dfrag); }
return false;
}
SDL_GPUColorTargetDescription downscale_color_target = {};
downscale_color_target.format = SWAPCHAIN_FMT;
downscale_color_target.blend_state = no_blend;
SDL_GPUGraphicsPipelineCreateInfo downscale_pipe_info = {};
downscale_pipe_info.vertex_shader = dvert;
downscale_pipe_info.fragment_shader = dfrag;
downscale_pipe_info.vertex_input_state = no_input;
downscale_pipe_info.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST;
downscale_pipe_info.target_info.num_color_targets = 1;
downscale_pipe_info.target_info.color_target_descriptions = &downscale_color_target;
downscale_pipeline_ = SDL_CreateGPUGraphicsPipeline(device_, &downscale_pipe_info);
SDL_ReleaseGPUShader(device_, dvert);
SDL_ReleaseGPUShader(device_, dfrag);
if (downscale_pipeline_ == nullptr) {
SDL_Log("SDL3GPUShader: downscale pipeline creation failed: %s", SDL_GetError());
return false;
}
return true; return true;
} }
@@ -489,7 +607,7 @@ namespace Rendering {
SDL_EndGPUCopyPass(copy); SDL_EndGPUCopyPass(copy);
} }
// ---- Upscale pass: scene_texture_ (game res) → scaled_texture_ (game × OS) ---- // ---- Upscale pass: scene_texture_ → scaled_texture_ (NEAREST o LINEAR según linear_upscale_) ----
if (oversample_ > 1 && scaled_texture_ != nullptr && upscale_pipeline_ != nullptr) { if (oversample_ > 1 && scaled_texture_ != nullptr && upscale_pipeline_ != nullptr) {
SDL_GPUColorTargetInfo upscale_target = {}; SDL_GPUColorTargetInfo upscale_target = {};
upscale_target.texture = scaled_texture_; upscale_target.texture = scaled_texture_;
@@ -501,7 +619,7 @@ namespace Rendering {
SDL_BindGPUGraphicsPipeline(upass, upscale_pipeline_); SDL_BindGPUGraphicsPipeline(upass, upscale_pipeline_);
SDL_GPUTextureSamplerBinding ubinding = {}; SDL_GPUTextureSamplerBinding ubinding = {};
ubinding.texture = scene_texture_; ubinding.texture = scene_texture_;
ubinding.sampler = sampler_; // NEAREST ubinding.sampler = (linear_upscale_ && linear_sampler_ != nullptr) ? linear_sampler_ : sampler_;
SDL_BindGPUFragmentSamplers(upass, 0, &ubinding, 1); SDL_BindGPUFragmentSamplers(upass, 0, &ubinding, 1);
SDL_DrawGPUPrimitives(upass, 3, 1, 0, 0); SDL_DrawGPUPrimitives(upass, 3, 1, 0, 0);
SDL_EndGPURenderPass(upass); SDL_EndGPURenderPass(upass);
@@ -523,71 +641,117 @@ namespace Rendering {
return; return;
} }
// ---- Render pass: PostFX → swapchain ---- // ---- Calcular viewport (dimensiones lógicas del canvas, no de textura GPU) ----
SDL_GPUColorTargetInfo color_target = {}; float vx = 0.0F;
color_target.texture = swapchain; float vy = 0.0F;
color_target.load_op = SDL_GPU_LOADOP_CLEAR; float vw = 0.0F;
color_target.store_op = SDL_GPU_STOREOP_STORE; float vh = 0.0F;
color_target.clear_color = {.r = 0.0F, .g = 0.0F, .b = 0.0F, .a = 1.0F}; if (integer_scale_) {
const int SCALE = std::max(1, std::min(static_cast<int>(sw) / game_width_, static_cast<int>(sh) / game_height_));
vw = static_cast<float>(game_width_ * SCALE);
vh = static_cast<float>(game_height_ * SCALE);
} else {
const float SCALE = std::min(
static_cast<float>(sw) / static_cast<float>(game_width_),
static_cast<float>(sh) / static_cast<float>(game_height_));
vw = static_cast<float>(game_width_) * SCALE;
vh = static_cast<float>(game_height_) * SCALE;
}
vx = std::floor((static_cast<float>(sw) - vw) * 0.5F);
vy = std::floor((static_cast<float>(sh) - vh) * 0.5F);
SDL_GPURenderPass* pass = SDL_BeginGPURenderPass(cmd, &color_target, 1, nullptr); // pixel_scale: subpíxeles por pixel lógico.
if (pass != nullptr) { // Sin SS: vh/game_height (zoom de ventana).
SDL_BindGPUGraphicsPipeline(pass, pipeline_); // Con SS: ss_factor_ exacto (3, 6, 9...).
uniforms_.pixel_scale = (oversample_ > 1 && ss_factor_ > 0)
? static_cast<float>(ss_factor_)
: ((game_height_ > 0) ? (vh / static_cast<float>(game_height_)) : 1.0F);
uniforms_.time = static_cast<float>(SDL_GetTicks()) / 1000.0F;
uniforms_.oversample = (oversample_ > 1 && ss_factor_ > 0)
? static_cast<float>(ss_factor_)
: 1.0F;
// Calcular viewport usando las dimensiones lógicas del canvas (game_width_/height_), // ---- Determinar si usar el path Lanczos (SS activo + algo seleccionado) ----
// no las de la textura GPU (que pueden ser game×3 con supersampling). const bool USE_LANCZOS = (oversample_ > 1 && downscale_algo_ > 0
// El GPU escala la textura para cubrir el viewport independientemente de su resolución. && scaled_texture_ != nullptr
float vx = 0.0F; && postfx_texture_ != nullptr
float vy = 0.0F; && postfx_offscreen_pipeline_ != nullptr
float vw = 0.0F; && downscale_pipeline_ != nullptr);
float vh = 0.0F;
if (integer_scale_) { if (USE_LANCZOS) {
const int SCALE = std::max(1, std::min(static_cast<int>(sw) / game_width_, static_cast<int>(sh) / game_height_)); // ---- Pass A: PostFX → postfx_texture_ (full scaled size, sin viewport) ----
vw = static_cast<float>(game_width_ * SCALE); SDL_GPUColorTargetInfo postfx_target = {};
vh = static_cast<float>(game_height_ * SCALE); postfx_target.texture = postfx_texture_;
} else { postfx_target.load_op = SDL_GPU_LOADOP_CLEAR;
const float SCALE = std::min( postfx_target.store_op = SDL_GPU_STOREOP_STORE;
static_cast<float>(sw) / static_cast<float>(game_width_), postfx_target.clear_color = {.r = 0.0F, .g = 0.0F, .b = 0.0F, .a = 1.0F};
static_cast<float>(sh) / static_cast<float>(game_height_));
vw = static_cast<float>(game_width_) * SCALE; SDL_GPURenderPass* ppass = SDL_BeginGPURenderPass(cmd, &postfx_target, 1, nullptr);
vh = static_cast<float>(game_height_) * SCALE; if (ppass != nullptr) {
SDL_BindGPUGraphicsPipeline(ppass, postfx_offscreen_pipeline_);
SDL_GPUTextureSamplerBinding pbinding = {};
pbinding.texture = scaled_texture_;
pbinding.sampler = sampler_; // NEAREST: 1:1 pass, efectos calculados analíticamente
SDL_BindGPUFragmentSamplers(ppass, 0, &pbinding, 1);
SDL_PushGPUFragmentUniformData(cmd, 0, &uniforms_, sizeof(PostFXUniforms));
SDL_DrawGPUPrimitives(ppass, 3, 1, 0, 0);
SDL_EndGPURenderPass(ppass);
} }
vx = std::floor((static_cast<float>(sw) - vw) * 0.5F);
vy = std::floor((static_cast<float>(sh) - vh) * 0.5F);
SDL_GPUViewport vp = {.x = vx, .y = vy, .w = vw, .h = vh, .min_depth = 0.0F, .max_depth = 1.0F};
SDL_SetGPUViewport(pass, &vp);
// pixel_scale: subpíxeles de textura por pixel lógico de juego. // ---- Pass B: Downscale Lanczos → swapchain (con viewport/letterbox) ----
// Sin SS: vh/game_height (zoom de ventana). SDL_GPUColorTargetInfo ds_target = {};
// Con SS: ss_factor_ exacto (3, 6, 9...) — la textura scaled tiene exactamente ds_target.texture = swapchain;
// ss_factor_ subfilas por fila lógica, múltiplo de 3 garantizado. ds_target.load_op = SDL_GPU_LOADOP_CLEAR;
uniforms_.pixel_scale = (oversample_ > 1 && ss_factor_ > 0) ds_target.store_op = SDL_GPU_STOREOP_STORE;
? static_cast<float>(ss_factor_) ds_target.clear_color = {.r = 0.0F, .g = 0.0F, .b = 0.0F, .a = 1.0F};
: ((game_height_ > 0) ? (vh / static_cast<float>(game_height_)) : 1.0F);
uniforms_.time = static_cast<float>(SDL_GetTicks()) / 1000.0F;
uniforms_.oversample = (oversample_ > 1 && ss_factor_ > 0)
? static_cast<float>(ss_factor_)
: 1.0F;
// Con SS: leer de scaled_texture_ (ya ampliada); con LINEAR para suavizar SDL_GPURenderPass* dpass = SDL_BeginGPURenderPass(cmd, &ds_target, 1, nullptr);
// el escalado final a zooms no-múltiplo-de-OS. if (dpass != nullptr) {
// Sin SS: leer de scene_texture_ con NEAREST. SDL_BindGPUGraphicsPipeline(dpass, downscale_pipeline_);
SDL_GPUTexture* input_texture = (oversample_ > 1 && scaled_texture_ != nullptr) SDL_GPUViewport vp = {.x = vx, .y = vy, .w = vw, .h = vh, .min_depth = 0.0F, .max_depth = 1.0F};
? scaled_texture_ SDL_SetGPUViewport(dpass, &vp);
: scene_texture_; SDL_GPUTextureSamplerBinding dbinding = {};
SDL_GPUSampler* active_sampler = (oversample_ > 1 && linear_sampler_ != nullptr) dbinding.texture = postfx_texture_;
? linear_sampler_ dbinding.sampler = sampler_; // NEAREST: el shader Lanczos hace su propia interpolación
: sampler_; SDL_BindGPUFragmentSamplers(dpass, 0, &dbinding, 1);
// algorithm: 0=Lanczos2, 1=Lanczos3 (downscale_algo_ es 1-based)
DownscaleUniforms downscale_u = {.algorithm = downscale_algo_ - 1, .pad0 = 0.0F, .pad1 = 0.0F, .pad2 = 0.0F};
SDL_PushGPUFragmentUniformData(cmd, 0, &downscale_u, sizeof(DownscaleUniforms));
SDL_DrawGPUPrimitives(dpass, 3, 1, 0, 0);
SDL_EndGPURenderPass(dpass);
}
} else {
// ---- Render pass: PostFX → swapchain directamente (bilinear, comportamiento original) ----
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_GPUTextureSamplerBinding binding = {}; SDL_GPURenderPass* pass = SDL_BeginGPURenderPass(cmd, &color_target, 1, nullptr);
binding.texture = input_texture; if (pass != nullptr) {
binding.sampler = active_sampler; SDL_BindGPUGraphicsPipeline(pass, pipeline_);
SDL_BindGPUFragmentSamplers(pass, 0, &binding, 1); SDL_GPUViewport vp = {.x = vx, .y = vy, .w = vw, .h = vh, .min_depth = 0.0F, .max_depth = 1.0F};
SDL_SetGPUViewport(pass, &vp);
SDL_PushGPUFragmentUniformData(cmd, 0, &uniforms_, sizeof(PostFXUniforms)); // Con SS: leer de scaled_texture_ con LINEAR; sin SS: scene_texture_ con NEAREST.
SDL_GPUTexture* input_texture = (oversample_ > 1 && scaled_texture_ != nullptr)
? scaled_texture_
: scene_texture_;
SDL_GPUSampler* active_sampler = (oversample_ > 1 && linear_sampler_ != nullptr)
? linear_sampler_
: sampler_;
SDL_DrawGPUPrimitives(pass, 3, 1, 0, 0); SDL_GPUTextureSamplerBinding binding = {};
SDL_EndGPURenderPass(pass); binding.texture = input_texture;
binding.sampler = active_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); SDL_SubmitGPUCommandBuffer(cmd);
@@ -606,10 +770,18 @@ namespace Rendering {
SDL_ReleaseGPUGraphicsPipeline(device_, pipeline_); SDL_ReleaseGPUGraphicsPipeline(device_, pipeline_);
pipeline_ = nullptr; pipeline_ = nullptr;
} }
if (postfx_offscreen_pipeline_ != nullptr) {
SDL_ReleaseGPUGraphicsPipeline(device_, postfx_offscreen_pipeline_);
postfx_offscreen_pipeline_ = nullptr;
}
if (upscale_pipeline_ != nullptr) { if (upscale_pipeline_ != nullptr) {
SDL_ReleaseGPUGraphicsPipeline(device_, upscale_pipeline_); SDL_ReleaseGPUGraphicsPipeline(device_, upscale_pipeline_);
upscale_pipeline_ = nullptr; upscale_pipeline_ = nullptr;
} }
if (downscale_pipeline_ != nullptr) {
SDL_ReleaseGPUGraphicsPipeline(device_, downscale_pipeline_);
downscale_pipeline_ = nullptr;
}
if (scene_texture_ != nullptr) { if (scene_texture_ != nullptr) {
SDL_ReleaseGPUTexture(device_, scene_texture_); SDL_ReleaseGPUTexture(device_, scene_texture_);
scene_texture_ = nullptr; scene_texture_ = nullptr;
@@ -618,6 +790,10 @@ namespace Rendering {
SDL_ReleaseGPUTexture(device_, scaled_texture_); SDL_ReleaseGPUTexture(device_, scaled_texture_);
scaled_texture_ = nullptr; scaled_texture_ = nullptr;
} }
if (postfx_texture_ != nullptr) {
SDL_ReleaseGPUTexture(device_, postfx_texture_);
postfx_texture_ = nullptr;
}
ss_factor_ = 0; ss_factor_ = 0;
if (upload_buffer_ != nullptr) { if (upload_buffer_ != nullptr) {
SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_); SDL_ReleaseGPUTransferBuffer(device_, upload_buffer_);
@@ -734,6 +910,14 @@ namespace Rendering {
} }
} }
void SDL3GPUShader::setLinearUpscale(bool linear) {
linear_upscale_ = linear;
}
void SDL3GPUShader::setDownscaleAlgo(int algo) {
downscale_algo_ = std::max(0, std::min(algo, 2));
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// reinitTexturesAndBuffer — recrea scene_texture_, scaled_texture_ y // reinitTexturesAndBuffer — recrea scene_texture_, scaled_texture_ y
// upload_buffer_ con el factor oversample_ actual. No toca pipelines ni samplers. // upload_buffer_ con el factor oversample_ actual. No toca pipelines ni samplers.
@@ -814,6 +998,10 @@ namespace Rendering {
SDL_ReleaseGPUTexture(device_, scaled_texture_); SDL_ReleaseGPUTexture(device_, scaled_texture_);
scaled_texture_ = nullptr; scaled_texture_ = nullptr;
} }
if (postfx_texture_ != nullptr) {
SDL_ReleaseGPUTexture(device_, postfx_texture_);
postfx_texture_ = nullptr;
}
ss_factor_ = 0; ss_factor_ = 0;
const int W = game_width_ * factor; const int W = game_width_ * factor;
@@ -827,17 +1015,25 @@ namespace Rendering {
info.height = static_cast<Uint32>(H); info.height = static_cast<Uint32>(H);
info.layer_count_or_depth = 1; info.layer_count_or_depth = 1;
info.num_levels = 1; info.num_levels = 1;
scaled_texture_ = SDL_CreateGPUTexture(device_, &info); scaled_texture_ = SDL_CreateGPUTexture(device_, &info);
if (scaled_texture_ == nullptr) { if (scaled_texture_ == nullptr) {
SDL_Log("SDL3GPUShader: failed to create scaled texture %dx%d (factor %d): %s", SDL_Log("SDL3GPUShader: failed to create scaled texture %dx%d (factor %d): %s",
W, W, H, factor, SDL_GetError());
H,
factor,
SDL_GetError());
return false; return false;
} }
postfx_texture_ = SDL_CreateGPUTexture(device_, &info);
if (postfx_texture_ == nullptr) {
SDL_Log("SDL3GPUShader: failed to create postfx texture %dx%d (factor %d): %s",
W, H, factor, SDL_GetError());
SDL_ReleaseGPUTexture(device_, scaled_texture_);
scaled_texture_ = nullptr;
return false;
}
ss_factor_ = factor; ss_factor_ = factor;
SDL_Log("SDL3GPUShader: scaled texture %dx%d (factor %d×)", W, H, factor); SDL_Log("SDL3GPUShader: scaled+postfx textures %dx%d (factor %d×)", W, H, factor);
return true; return true;
} }

View File

@@ -23,6 +23,15 @@ struct PostFXUniforms {
float flicker; // 0 = off, 1 = phosphor flicker ~50 Hz — keep struct at 48 bytes (3 × 16) float flicker; // 0 = off, 1 = phosphor flicker ~50 Hz — keep struct at 48 bytes (3 × 16)
}; };
// Downscale uniforms pushed to the Lanczos downscale fragment stage.
// 1 int + 3 floats = 16 bytes — meets Metal/Vulkan alignment.
struct DownscaleUniforms {
int algorithm; // 0 = Lanczos2 (ventana 2), 1 = Lanczos3 (ventana 3)
float pad0;
float pad1;
float pad2;
};
namespace Rendering { namespace Rendering {
/** /**
@@ -64,6 +73,12 @@ namespace Rendering {
// Establece factor de supersampling (1 = off, 3 = 3×SS) // Establece factor de supersampling (1 = off, 3 = 3×SS)
void setOversample(int factor) override; void setOversample(int factor) override;
// Activa/desactiva interpolación LINEAR en el upscale (false = NEAREST)
void setLinearUpscale(bool linear) override;
// Selecciona algoritmo de downscale: 0=bilinear legacy, 1=Lanczos2, 2=Lanczos3
void setDownscaleAlgo(int algo) override;
private: private:
static auto createShaderMSL(SDL_GPUDevice* device, static auto createShaderMSL(SDL_GPUDevice* device,
const char* msl_source, const char* msl_source,
@@ -87,24 +102,29 @@ namespace Rendering {
SDL_Window* window_ = nullptr; SDL_Window* window_ = nullptr;
SDL_GPUDevice* device_ = nullptr; SDL_GPUDevice* device_ = nullptr;
SDL_GPUGraphicsPipeline* pipeline_ = nullptr; // PostFX pass SDL_GPUGraphicsPipeline* pipeline_ = nullptr; // PostFX pass (→ swapchain o → postfx_texture_)
SDL_GPUGraphicsPipeline* upscale_pipeline_ = nullptr; // Upscale nearest pass (solo con SS) SDL_GPUGraphicsPipeline* postfx_offscreen_pipeline_ = nullptr; // PostFX → postfx_texture_ (B8G8R8A8, solo con Lanczos)
SDL_GPUTexture* scene_texture_ = nullptr; // Canvas del juego (game_width_ × game_height_) SDL_GPUGraphicsPipeline* upscale_pipeline_ = nullptr; // Upscale pass (solo con SS)
SDL_GPUTexture* scaled_texture_ = nullptr; // Render target intermedio (win*SS × win*SS), solo con SS SDL_GPUGraphicsPipeline* downscale_pipeline_ = nullptr; // Lanczos downscale (solo con SS + algo > 0)
SDL_GPUTexture* scene_texture_ = nullptr; // Canvas del juego (game_width_ × game_height_)
SDL_GPUTexture* scaled_texture_ = nullptr; // Upscale target (game×factor), solo con SS
SDL_GPUTexture* postfx_texture_ = nullptr; // PostFX output a resolución escalada, solo con Lanczos
SDL_GPUTransferBuffer* upload_buffer_ = nullptr; SDL_GPUTransferBuffer* upload_buffer_ = nullptr;
SDL_GPUSampler* sampler_ = nullptr; // NEAREST SDL_GPUSampler* sampler_ = nullptr; // NEAREST
SDL_GPUSampler* linear_sampler_ = nullptr; // LINEAR SDL_GPUSampler* linear_sampler_ = nullptr; // LINEAR
PostFXUniforms uniforms_{.vignette_strength = 0.6F, .chroma_strength = 0.15F, .scanline_strength = 0.7F, .screen_height = 192.0F, .pixel_scale = 1.0F, .oversample = 1.0F}; PostFXUniforms uniforms_{.vignette_strength = 0.6F, .chroma_strength = 0.15F, .scanline_strength = 0.7F, .screen_height = 192.0F, .pixel_scale = 1.0F, .oversample = 1.0F};
int game_width_ = 0; // Dimensiones originales del canvas int game_width_ = 0; // Dimensiones originales del canvas
int game_height_ = 0; int game_height_ = 0;
int ss_factor_ = 0; // Factor SS activo (3, 6, 9...) o 0 si SS desactivado int ss_factor_ = 0; // Factor SS activo (3, 6, 9...) o 0 si SS desactivado
int oversample_ = 1; // SS on/off (1 = off, >1 = on) int oversample_ = 1; // SS on/off (1 = off, >1 = on)
int downscale_algo_ = 1; // 0 = bilinear legacy, 1 = Lanczos2, 2 = Lanczos3
std::string driver_name_; std::string driver_name_;
bool is_initialized_ = false; bool is_initialized_ = false;
bool vsync_ = true; bool vsync_ = true;
bool integer_scale_ = false; bool integer_scale_ = false;
bool linear_upscale_ = false; // Upscale NEAREST (false) o LINEAR (true)
}; };
} // namespace Rendering } // namespace Rendering

View File

@@ -1,634 +1,59 @@
#pragma once #pragma once
#include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstddef>
static const uint8_t kupscale_frag_spv[] = { static const uint8_t kupscale_frag_spv[] = {
0x03, 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00,
0x02, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
0x23, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
0x07, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00,
0x01, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
0x0b, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00,
0x0d, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70,
0x00, 0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65,
0x14, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00,
0x00, 0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c,
0x00, 0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69,
0x00, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x05, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x5f,
0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
0x00, 0x0d, 0x00, 0x00, 0x00, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x00, 0x00,
0x11, 0x05, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x76, 0x5f, 0x75, 0x76,
0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
0x02, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
0x00, 0x0d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x47, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00,
0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
0x0b, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00,
0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
0x06, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x01, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x00, 0x00,
0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x47, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x4c, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
0x53, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
0x4c, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2e, 0x17, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
0x73, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
0x74, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
0x64, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x2e, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x34, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
0x35, 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x30, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
0x00, 0x0f, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
0x00, 0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
0x00, 0x0e, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00,
0x0e, 0x38, 0x00, 0x01, 0x00
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,
0x09,
0x00,
0x00,
0x00,
0x11,
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,
0x05,
0x00,
0x09,
0x00,
0x00,
0x00,
0x6f,
0x75,
0x74,
0x5f,
0x63,
0x6f,
0x6c,
0x6f,
0x72,
0x00,
0x00,
0x00,
0x05,
0x00,
0x04,
0x00,
0x0d,
0x00,
0x00,
0x00,
0x73,
0x63,
0x65,
0x6e,
0x65,
0x00,
0x00,
0x00,
0x05,
0x00,
0x04,
0x00,
0x11,
0x00,
0x00,
0x00,
0x76,
0x5f,
0x75,
0x76,
0x00,
0x00,
0x00,
0x00,
0x47,
0x00,
0x04,
0x00,
0x09,
0x00,
0x00,
0x00,
0x1e,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x47,
0x00,
0x04,
0x00,
0x0d,
0x00,
0x00,
0x00,
0x21,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x47,
0x00,
0x04,
0x00,
0x0d,
0x00,
0x00,
0x00,
0x22,
0x00,
0x00,
0x00,
0x02,
0x00,
0x00,
0x00,
0x47,
0x00,
0x04,
0x00,
0x11,
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,
0x04,
0x00,
0x00,
0x00,
0x20,
0x00,
0x04,
0x00,
0x08,
0x00,
0x00,
0x00,
0x03,
0x00,
0x00,
0x00,
0x07,
0x00,
0x00,
0x00,
0x3b,
0x00,
0x04,
0x00,
0x08,
0x00,
0x00,
0x00,
0x09,
0x00,
0x00,
0x00,
0x03,
0x00,
0x00,
0x00,
0x19,
0x00,
0x09,
0x00,
0x0a,
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,
0x0b,
0x00,
0x00,
0x00,
0x0a,
0x00,
0x00,
0x00,
0x20,
0x00,
0x04,
0x00,
0x0c,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x0b,
0x00,
0x00,
0x00,
0x3b,
0x00,
0x04,
0x00,
0x0c,
0x00,
0x00,
0x00,
0x0d,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x17,
0x00,
0x04,
0x00,
0x0f,
0x00,
0x00,
0x00,
0x06,
0x00,
0x00,
0x00,
0x02,
0x00,
0x00,
0x00,
0x20,
0x00,
0x04,
0x00,
0x10,
0x00,
0x00,
0x00,
0x01,
0x00,
0x00,
0x00,
0x0f,
0x00,
0x00,
0x00,
0x3b,
0x00,
0x04,
0x00,
0x10,
0x00,
0x00,
0x00,
0x11,
0x00,
0x00,
0x00,
0x01,
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,
0x3d,
0x00,
0x04,
0x00,
0x0b,
0x00,
0x00,
0x00,
0x0e,
0x00,
0x00,
0x00,
0x0d,
0x00,
0x00,
0x00,
0x3d,
0x00,
0x04,
0x00,
0x0f,
0x00,
0x00,
0x00,
0x12,
0x00,
0x00,
0x00,
0x11,
0x00,
0x00,
0x00,
0x57,
0x00,
0x05,
0x00,
0x07,
0x00,
0x00,
0x00,
0x13,
0x00,
0x00,
0x00,
0x0e,
0x00,
0x00,
0x00,
0x12,
0x00,
0x00,
0x00,
0x3e,
0x00,
0x03,
0x00,
0x09,
0x00,
0x00,
0x00,
0x13,
0x00,
0x00,
0x00,
0xfd,
0x00,
0x01,
0x00,
0x38,
0x00,
0x01,
0x00,
}; };
static const size_t kupscale_frag_spv_size = 628; static const size_t kupscale_frag_spv_size = 628;

View File

@@ -90,6 +90,19 @@ namespace Rendering {
*/ */
virtual void setOversample(int /*factor*/) {} virtual void setOversample(int /*factor*/) {}
/**
* @brief Activa/desactiva interpolación LINEAR en el paso de upscale (SS).
* Por defecto NEAREST (false). Solo tiene efecto con supersampling activo.
*/
virtual void setLinearUpscale(bool /*linear*/) {}
/**
* @brief Selecciona el algoritmo de downscale tras el PostFX (SS activo).
* 0 = bilinear legacy (comportamiento actual, sin textura intermedia),
* 1 = Lanczos2 (ventana 2, ~25 muestras), 2 = Lanczos3 (ventana 3, ~49 muestras).
*/
virtual void setDownscaleAlgo(int /*algo*/) {}
/** /**
* @brief Verifica si el backend está usando aceleración por hardware * @brief Verifica si el backend está usando aceleración por hardware
* @return true si usa aceleración (OpenGL/Metal/Vulkan) * @return true si usa aceleración (OpenGL/Metal/Vulkan)

View File

@@ -20,6 +20,8 @@ echo "Compiling SPIR-V shaders..."
glslc "${SHADERS_DIR}/postfx.vert" -o /tmp/postfx.vert.spv glslc "${SHADERS_DIR}/postfx.vert" -o /tmp/postfx.vert.spv
glslc "${SHADERS_DIR}/postfx.frag" -o /tmp/postfx.frag.spv glslc "${SHADERS_DIR}/postfx.frag" -o /tmp/postfx.frag.spv
glslc "${SHADERS_DIR}/upscale.frag" -o /tmp/upscale.frag.spv
glslc "${SHADERS_DIR}/downscale.frag" -o /tmp/downscale.frag.spv
echo "Generating C++ headers..." echo "Generating C++ headers..."
@@ -33,12 +35,24 @@ xxd -i /tmp/postfx.frag.spv | \
sed 's/unsigned int .*postfx_frag_spv_len/static const size_t kpostfx_frag_spv_size/' \ sed 's/unsigned int .*postfx_frag_spv_len/static const size_t kpostfx_frag_spv_size/' \
> "${HEADERS_DIR}/postfx_frag_spv.h" > "${HEADERS_DIR}/postfx_frag_spv.h"
xxd -i /tmp/upscale.frag.spv | \
sed 's/unsigned char .*upscale_frag_spv\[\]/static const uint8_t kupscale_frag_spv[]/' | \
sed 's/unsigned int .*upscale_frag_spv_len/static const size_t kupscale_frag_spv_size/' \
> "${HEADERS_DIR}/upscale_frag_spv.h"
xxd -i /tmp/downscale.frag.spv | \
sed 's/unsigned char .*downscale_frag_spv\[\]/static const uint8_t kdownscale_frag_spv[]/' | \
sed 's/unsigned int .*downscale_frag_spv_len/static const size_t kdownscale_frag_spv_size/' \
> "${HEADERS_DIR}/downscale_frag_spv.h"
# Prepend required includes to the headers # Prepend required includes to the headers
for f in "${HEADERS_DIR}/postfx_vert_spv.h" "${HEADERS_DIR}/postfx_frag_spv.h"; do for f in "${HEADERS_DIR}/postfx_vert_spv.h" "${HEADERS_DIR}/postfx_frag_spv.h" "${HEADERS_DIR}/upscale_frag_spv.h" "${HEADERS_DIR}/downscale_frag_spv.h"; do
echo -e "#pragma once\n#include <cstdint>\n#include <cstddef>\n$(cat "$f")" > "$f" echo -e "#pragma once\n#include <cstdint>\n#include <cstddef>\n$(cat "$f")" > "$f"
done done
echo "Done. Headers updated in ${HEADERS_DIR}/" echo "Done. Headers updated in ${HEADERS_DIR}/"
echo " postfx_vert_spv.h" echo " postfx_vert_spv.h"
echo " postfx_frag_spv.h" echo " postfx_frag_spv.h"
echo " upscale_frag_spv.h"
echo " downscale_frag_spv.h"
echo "Rebuild the project to use the new shaders." echo "Rebuild the project to use the new shaders."