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);
}
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)
void Screen::toggleSupersampling() {
Options::video.supersampling = !Options::video.supersampling;

View File

@@ -59,6 +59,8 @@ class Screen {
void togglePostFX(); // Cambia el estado del PostFX
void toggleSupersampling(); // Activa/desactiva el supersampling global
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
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
#ifndef __APPLE__
#include "core/rendering/sdl3gpu/downscale_frag_spv.h"
#include "core/rendering/sdl3gpu/postfx_frag_spv.h"
#include "core/rendering/sdl3gpu/postfx_vert_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);
}
)";
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)
#endif // __APPLE__
@@ -421,6 +462,83 @@ namespace Rendering {
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;
}
@@ -489,7 +607,7 @@ namespace Rendering {
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) {
SDL_GPUColorTargetInfo upscale_target = {};
upscale_target.texture = scaled_texture_;
@@ -501,7 +619,7 @@ namespace Rendering {
SDL_BindGPUGraphicsPipeline(upass, upscale_pipeline_);
SDL_GPUTextureSamplerBinding ubinding = {};
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_DrawGPUPrimitives(upass, 3, 1, 0, 0);
SDL_EndGPURenderPass(upass);
@@ -523,71 +641,117 @@ namespace Rendering {
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};
// ---- Calcular viewport (dimensiones lógicas del canvas, no de textura GPU) ----
float vx = 0.0F;
float vy = 0.0F;
float vw = 0.0F;
float vh = 0.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);
if (pass != nullptr) {
SDL_BindGPUGraphicsPipeline(pass, pipeline_);
// pixel_scale: subpíxeles por pixel lógico.
// Sin SS: vh/game_height (zoom de ventana).
// 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_),
// no las de la textura GPU (que pueden ser game×3 con supersampling).
// El GPU escala la textura para cubrir el viewport independientemente de su resolución.
float vx = 0.0F;
float vy = 0.0F;
float vw = 0.0F;
float vh = 0.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;
// ---- Determinar si usar el path Lanczos (SS activo + algo seleccionado) ----
const bool USE_LANCZOS = (oversample_ > 1 && downscale_algo_ > 0
&& scaled_texture_ != nullptr
&& postfx_texture_ != nullptr
&& postfx_offscreen_pipeline_ != nullptr
&& downscale_pipeline_ != nullptr);
if (USE_LANCZOS) {
// ---- Pass A: PostFX → postfx_texture_ (full scaled size, sin viewport) ----
SDL_GPUColorTargetInfo postfx_target = {};
postfx_target.texture = postfx_texture_;
postfx_target.load_op = SDL_GPU_LOADOP_CLEAR;
postfx_target.store_op = SDL_GPU_STOREOP_STORE;
postfx_target.clear_color = {.r = 0.0F, .g = 0.0F, .b = 0.0F, .a = 1.0F};
SDL_GPURenderPass* ppass = SDL_BeginGPURenderPass(cmd, &postfx_target, 1, nullptr);
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.
// Sin SS: vh/game_height (zoom de ventana).
// Con SS: ss_factor_ exacto (3, 6, 9...) — la textura scaled tiene exactamente
// ss_factor_ subfilas por fila lógica, múltiplo de 3 garantizado.
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;
// ---- Pass B: Downscale Lanczos → swapchain (con viewport/letterbox) ----
SDL_GPUColorTargetInfo ds_target = {};
ds_target.texture = swapchain;
ds_target.load_op = SDL_GPU_LOADOP_CLEAR;
ds_target.store_op = SDL_GPU_STOREOP_STORE;
ds_target.clear_color = {.r = 0.0F, .g = 0.0F, .b = 0.0F, .a = 1.0F};
// Con SS: leer de scaled_texture_ (ya ampliada); con LINEAR para suavizar
// el escalado final a zooms no-múltiplo-de-OS.
// Sin SS: leer de 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_GPURenderPass* dpass = SDL_BeginGPURenderPass(cmd, &ds_target, 1, nullptr);
if (dpass != nullptr) {
SDL_BindGPUGraphicsPipeline(dpass, downscale_pipeline_);
SDL_GPUViewport vp = {.x = vx, .y = vy, .w = vw, .h = vh, .min_depth = 0.0F, .max_depth = 1.0F};
SDL_SetGPUViewport(dpass, &vp);
SDL_GPUTextureSamplerBinding dbinding = {};
dbinding.texture = postfx_texture_;
dbinding.sampler = sampler_; // NEAREST: el shader Lanczos hace su propia interpolación
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 = {};
binding.texture = input_texture;
binding.sampler = active_sampler;
SDL_BindGPUFragmentSamplers(pass, 0, &binding, 1);
SDL_GPURenderPass* pass = SDL_BeginGPURenderPass(cmd, &color_target, 1, nullptr);
if (pass != nullptr) {
SDL_BindGPUGraphicsPipeline(pass, pipeline_);
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_EndGPURenderPass(pass);
SDL_GPUTextureSamplerBinding binding = {};
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);
@@ -606,10 +770,18 @@ namespace Rendering {
SDL_ReleaseGPUGraphicsPipeline(device_, pipeline_);
pipeline_ = nullptr;
}
if (postfx_offscreen_pipeline_ != nullptr) {
SDL_ReleaseGPUGraphicsPipeline(device_, postfx_offscreen_pipeline_);
postfx_offscreen_pipeline_ = nullptr;
}
if (upscale_pipeline_ != nullptr) {
SDL_ReleaseGPUGraphicsPipeline(device_, upscale_pipeline_);
upscale_pipeline_ = nullptr;
}
if (downscale_pipeline_ != nullptr) {
SDL_ReleaseGPUGraphicsPipeline(device_, downscale_pipeline_);
downscale_pipeline_ = nullptr;
}
if (scene_texture_ != nullptr) {
SDL_ReleaseGPUTexture(device_, scene_texture_);
scene_texture_ = nullptr;
@@ -618,6 +790,10 @@ namespace Rendering {
SDL_ReleaseGPUTexture(device_, scaled_texture_);
scaled_texture_ = nullptr;
}
if (postfx_texture_ != nullptr) {
SDL_ReleaseGPUTexture(device_, postfx_texture_);
postfx_texture_ = nullptr;
}
ss_factor_ = 0;
if (upload_buffer_ != nullptr) {
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
// upload_buffer_ con el factor oversample_ actual. No toca pipelines ni samplers.
@@ -814,6 +998,10 @@ namespace Rendering {
SDL_ReleaseGPUTexture(device_, scaled_texture_);
scaled_texture_ = nullptr;
}
if (postfx_texture_ != nullptr) {
SDL_ReleaseGPUTexture(device_, postfx_texture_);
postfx_texture_ = nullptr;
}
ss_factor_ = 0;
const int W = game_width_ * factor;
@@ -827,17 +1015,25 @@ namespace Rendering {
info.height = static_cast<Uint32>(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 (factor %d): %s",
W,
H,
factor,
SDL_GetError());
W, H, factor, SDL_GetError());
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;
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;
}

View File

@@ -23,6 +23,15 @@ struct PostFXUniforms {
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 {
/**
@@ -64,6 +73,12 @@ namespace Rendering {
// Establece factor de supersampling (1 = off, 3 = 3×SS)
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:
static auto createShaderMSL(SDL_GPUDevice* device,
const char* msl_source,
@@ -87,24 +102,29 @@ namespace Rendering {
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 (win*SS × win*SS), solo con SS
SDL_GPUGraphicsPipeline* pipeline_ = nullptr; // PostFX pass (→ swapchain o → postfx_texture_)
SDL_GPUGraphicsPipeline* postfx_offscreen_pipeline_ = nullptr; // PostFX → postfx_texture_ (B8G8R8A8, solo con Lanczos)
SDL_GPUGraphicsPipeline* upscale_pipeline_ = nullptr; // Upscale pass (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_GPUSampler* sampler_ = nullptr; // NEAREST
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};
int game_width_ = 0; // Dimensiones originales del canvas
int game_width_ = 0; // Dimensiones originales del canvas
int game_height_ = 0;
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 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 downscale_algo_ = 1; // 0 = bilinear legacy, 1 = Lanczos2, 2 = Lanczos3
std::string driver_name_;
bool is_initialized_ = false;
bool vsync_ = true;
bool integer_scale_ = false;
bool linear_upscale_ = false; // Upscale NEAREST (false) o LINEAR (true)
};
} // namespace Rendering

View File

@@ -1,634 +1,59 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <cstddef>
static const uint8_t kupscale_frag_spv[] = {
0x03,
0x02,
0x23,
0x07,
0x00,
0x00,
0x01,
0x00,
0x0b,
0x00,
0x0d,
0x00,
0x14,
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,
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,
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00,
0x14, 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,
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;

View File

@@ -90,6 +90,19 @@ namespace Rendering {
*/
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
* @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.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..."
@@ -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/' \
> "${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
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"
done
echo "Done. Headers updated in ${HEADERS_DIR}/"
echo " postfx_vert_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."