feat(gpu): suport Metal/MSL a macOS i shaders SPIR-V embedits
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
// line_frag.msl.h - Metal Shading Language del fragment shader de línies
|
||||
// © 2026 JailDesigner
|
||||
//
|
||||
// IMPORTANT: mantenir sincronitzat a mà amb shaders/line.frag.glsl. SDL3 GPU
|
||||
// compila aquest string MSL en runtime; no hi ha generador automàtic.
|
||||
//
|
||||
// Aplica antialias geomètric via smoothstep sobre edge_dist (±1 als laterals,
|
||||
// 0 al centre del quad). Sense uniforms ni samplers.
|
||||
|
||||
#pragma once
|
||||
#ifdef __APPLE__
|
||||
|
||||
namespace Rendering::GPU::Msl {
|
||||
|
||||
inline constexpr const char* LINE_FRAG_MSL = R"(
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
struct VOut {
|
||||
float4 pos [[position]];
|
||||
float4 color;
|
||||
float edge_dist;
|
||||
};
|
||||
|
||||
fragment float4 line_fs(VOut in [[stage_in]]) {
|
||||
float d = abs(in.edge_dist);
|
||||
float alpha = 1.0 - smoothstep(0.7, 1.0, d);
|
||||
return float4(in.color.rgb, in.color.a * alpha);
|
||||
}
|
||||
)";
|
||||
|
||||
} // namespace Rendering::GPU::Msl
|
||||
|
||||
#endif // __APPLE__
|
||||
@@ -0,0 +1,54 @@
|
||||
// line_vert.msl.h - Metal Shading Language del vertex shader de línies
|
||||
// © 2026 JailDesigner
|
||||
//
|
||||
// IMPORTANT: mantenir sincronitzat a mà amb shaders/line.vert.glsl. SDL3 GPU
|
||||
// compila aquest string MSL en runtime; no hi ha generador automàtic. Qualsevol
|
||||
// canvi al UBO o al layout de vèrtex cal replicar-lo ací al mateix commit.
|
||||
//
|
||||
// Mapping SDL3 GPU → Metal (segons src/gpu/metal/SDL_gpu_metal.m upstream):
|
||||
// - Vertex buffers d'usuari: [[buffer(14 + slot)]] (METAL_FIRST_VERTEX_BUFFER_SLOT=14).
|
||||
// A través de [[stage_in]] amb [[attribute(N)]], Metal resol automàticament
|
||||
// a partir del MTLVertexDescriptor del pipeline state (transparent al MSL).
|
||||
// - Vertex UBO slot 0 SDL → [[buffer(0)]] MSL (sense offset).
|
||||
|
||||
#pragma once
|
||||
#ifdef __APPLE__
|
||||
|
||||
namespace Rendering::GPU::Msl {
|
||||
|
||||
inline constexpr const char* LINE_VERT_MSL = R"(
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
struct VIn {
|
||||
float2 in_position [[attribute(0)]];
|
||||
float4 in_color [[attribute(1)]];
|
||||
float in_edge_dist[[attribute(2)]];
|
||||
};
|
||||
|
||||
struct VOut {
|
||||
float4 pos [[position]];
|
||||
float4 color;
|
||||
float edge_dist;
|
||||
};
|
||||
|
||||
struct LineUBO {
|
||||
float2 viewport_size;
|
||||
float2 _padding;
|
||||
};
|
||||
|
||||
vertex VOut line_vs(VIn in [[stage_in]],
|
||||
constant LineUBO& ubo [[buffer(0)]]) {
|
||||
float2 ndc = (in.in_position / ubo.viewport_size) * 2.0 - 1.0;
|
||||
ndc.y = -ndc.y;
|
||||
VOut out;
|
||||
out.pos = float4(ndc, 0.0, 1.0);
|
||||
out.color = in.in_color;
|
||||
out.edge_dist = in.in_edge_dist;
|
||||
return out;
|
||||
}
|
||||
)";
|
||||
|
||||
} // namespace Rendering::GPU::Msl
|
||||
|
||||
#endif // __APPLE__
|
||||
@@ -0,0 +1,90 @@
|
||||
// postfx_frag.msl.h - Metal Shading Language del fragment shader del postpro
|
||||
// © 2026 JailDesigner
|
||||
//
|
||||
// IMPORTANT: mantenir sincronitzat a mà amb shaders/postfx.frag.glsl. SDL3 GPU
|
||||
// compila aquest string MSL en runtime; no hi ha generador automàtic. Qualsevol
|
||||
// canvi al struct PostFxUniforms (gpu_postfx_pipeline.hpp), al GLSL o al MSL
|
||||
// cal replicar-lo a totes tres al mateix commit.
|
||||
//
|
||||
// Composició final: bloom 5×5 amb high-pass, flicker sinusoidal global,
|
||||
// background pulse sumat. Recursos:
|
||||
// - texture2d<float> scene [[texture(0)]] + sampler [[sampler(0)]]
|
||||
// - constant PostFxUBO& ubo [[buffer(0)]] (slot 0 SDL → buffer(0) MSL)
|
||||
//
|
||||
// L'struct PostFxUBO té layout idèntic a PostFxUniforms (5×vec4 = 80 bytes).
|
||||
|
||||
#pragma once
|
||||
#ifdef __APPLE__
|
||||
|
||||
namespace Rendering::GPU::Msl {
|
||||
|
||||
inline constexpr const char* POSTFX_FRAG_MSL = R"(
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
struct PostVOut {
|
||||
float4 pos [[position]];
|
||||
float2 uv;
|
||||
};
|
||||
|
||||
struct PostFxUBO {
|
||||
float time;
|
||||
float bloom_intensity;
|
||||
float bloom_threshold;
|
||||
float bloom_radius_px;
|
||||
|
||||
float flicker_amplitude;
|
||||
float flicker_frequency_hz;
|
||||
float background_pulse_freq_hz;
|
||||
float pad_a;
|
||||
|
||||
float4 background_min;
|
||||
float4 background_max;
|
||||
|
||||
float2 texel_size;
|
||||
float2 pad_b;
|
||||
};
|
||||
|
||||
constant float TAU = 6.28318530718;
|
||||
|
||||
fragment float4 postfx_fs(PostVOut in [[stage_in]],
|
||||
texture2d<float> scene [[texture(0)]],
|
||||
sampler samp [[sampler(0)]],
|
||||
constant PostFxUBO& ubo [[buffer(0)]]) {
|
||||
// === BLOOM ===
|
||||
float3 src = scene.sample(samp, in.uv).rgb;
|
||||
float3 bloom = float3(0.0);
|
||||
float total_weight = 0.0;
|
||||
for (int dy = -2; dy <= 2; ++dy) {
|
||||
for (int dx = -2; dx <= 2; ++dx) {
|
||||
float2 offset = float2(float(dx), float(dy)) * ubo.texel_size * ubo.bloom_radius_px;
|
||||
float3 c = scene.sample(samp, in.uv + offset).rgb;
|
||||
float luma = max(c.r, max(c.g, c.b));
|
||||
float high_pass = max(0.0, luma - ubo.bloom_threshold);
|
||||
float w = exp(-float(dx * dx + dy * dy) / 4.0);
|
||||
bloom += c * high_pass * w;
|
||||
total_weight += w;
|
||||
}
|
||||
}
|
||||
if (total_weight > 0.0) {
|
||||
bloom /= total_weight;
|
||||
}
|
||||
bloom *= ubo.bloom_intensity;
|
||||
|
||||
// === FLICKER ===
|
||||
float pulse = (sin(ubo.time * ubo.flicker_frequency_hz * TAU) * 0.5) + 0.5;
|
||||
float flicker = 1.0 - (ubo.flicker_amplitude * (1.0 - pulse));
|
||||
|
||||
// === BACKGROUND PULSE ===
|
||||
float bg_pulse = (sin(ubo.time * ubo.background_pulse_freq_hz * TAU) * 0.5) + 0.5;
|
||||
float3 background = mix(ubo.background_min.rgb, ubo.background_max.rgb, bg_pulse);
|
||||
|
||||
// === COMPOSICIÓ ===
|
||||
float3 lines_and_glow = (src + bloom) * flicker;
|
||||
return float4(background + lines_and_glow, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
} // namespace Rendering::GPU::Msl
|
||||
|
||||
#endif // __APPLE__
|
||||
@@ -0,0 +1,38 @@
|
||||
// postfx_vert.msl.h - Metal Shading Language del vertex shader del postpro
|
||||
// © 2026 JailDesigner
|
||||
//
|
||||
// IMPORTANT: mantenir sincronitzat a mà amb shaders/postfx.vert.glsl. SDL3 GPU
|
||||
// compila aquest string MSL en runtime; no hi ha generador automàtic.
|
||||
//
|
||||
// Fullscreen triangle: 3 vèrtexs en (-1,-1), (3,-1), (-1,3) generats per
|
||||
// [[vertex_id]]. UV.y invertida per compensar la diferència de convenció
|
||||
// entre clip-space del line shader (Y-flip) i el mostreig SDL_gpu (origen
|
||||
// top-left). Sense uniforms ni vertex buffers (DrawPrimitives vertex_count=3).
|
||||
|
||||
#pragma once
|
||||
#ifdef __APPLE__
|
||||
|
||||
namespace Rendering::GPU::Msl {
|
||||
|
||||
inline constexpr const char* POSTFX_VERT_MSL = R"(
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
struct PostVOut {
|
||||
float4 pos [[position]];
|
||||
float2 uv;
|
||||
};
|
||||
|
||||
vertex PostVOut postfx_vs(uint vid [[vertex_id]]) {
|
||||
const float2 positions[3] = { {-1.0, -1.0}, { 3.0, -1.0}, {-1.0, 3.0} };
|
||||
const float2 uvs[3] = { { 0.0, 1.0}, { 2.0, 1.0}, { 0.0, -1.0} };
|
||||
PostVOut out;
|
||||
out.pos = float4(positions[vid], 0.0, 1.0);
|
||||
out.uv = uvs[vid];
|
||||
return out;
|
||||
}
|
||||
)";
|
||||
|
||||
} // namespace Rendering::GPU::Msl
|
||||
|
||||
#endif // __APPLE__
|
||||
Reference in New Issue
Block a user