Merge branch 'flow/m3te/P0.2' into m3te-plan

This commit is contained in:
swipelab
2026-06-04 18:29:15 +03:00
2 changed files with 71 additions and 3 deletions

BIN
goldens/p0_quad.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

74
main.sx
View File

@@ -22,6 +22,60 @@ g_viewport_h : f32 = 600.0;
g_uikit_plat : *UIKitPlatform = null;
g_metal_gpu : *MetalGPU = null;
// ── Render-path proof (P0.2) ─────────────────────────────────────────────
// Clear to a solid blue, then draw one centered orange quad covering the
// central 50%×50% of the drawable. Geometry is in NDC ([-0.5, 0.5]²) so the
// quad stays screen-size independent across simulator devices, which keeps
// the screenshot golden unambiguous. This is the GPU protocol's
// clear+quad path: an MSL pipeline state plus a 6-vertex (2-triangle)
// buffer, created lazily once the MTLDevice exists.
g_quad_shader : ShaderHandle = 0;
g_quad_vbuf : BufferHandle = 0;
BG_CLEAR :: ClearColor.{ r = 0.10, g = 0.20, b = 0.55, a = 1.0 };
// Vertex layout matches QUAD_MSL's `Vertex`: packed_float2 pos +
// packed_float4 color = 24 bytes. `packed_*` avoids the 16-byte alignment
// padding a plain `float4` would force. 6 vertices = 2 triangles.
QUAD_VERTS : [36]f32 = .[
-0.5, 0.5, 1.0, 0.6, 0.0, 1.0,
0.5, 0.5, 1.0, 0.6, 0.0, 1.0,
-0.5, -0.5, 1.0, 0.6, 0.0, 1.0,
0.5, 0.5, 1.0, 0.6, 0.0, 1.0,
0.5, -0.5, 1.0, 0.6, 0.0, 1.0,
-0.5, -0.5, 1.0, 0.6, 0.0, 1.0,
];
// Pass-through shader: the vertex stage emits NDC positions directly (no
// projection), the fragment stage returns the interpolated vertex color.
// Entry-point names vmain / fmain are what MetalGPU.create_shader looks up.
QUAD_MSL :: #string MSL
#include <metal_stdlib>
using namespace metal;
struct Vertex {
packed_float2 pos;
packed_float4 color;
};
struct RasterizerData {
float4 position [[position]];
float4 color;
};
vertex RasterizerData vmain(uint vid [[vertex_id]],
constant Vertex* vertices [[buffer(0)]]) {
RasterizerData out;
out.position = float4(vertices[vid].pos, 0.0, 1.0);
out.color = float4(vertices[vid].color);
return out;
}
fragment float4 fmain(RasterizerData in [[stage_in]]) {
return in.color;
}
MSL;
frame :: () {
fc := g_plat.begin_frame();
g_viewport_w = fc.viewport_w;
@@ -49,12 +103,26 @@ frame :: () {
} else if g_metal_gpu.pixel_w != g_uikit_plat.pixel_w or g_metal_gpu.pixel_h != g_uikit_plat.pixel_h {
g_metal_gpu.resize(g_uikit_plat.pixel_w, g_uikit_plat.pixel_h);
}
clear : ClearColor = .{ r = 0.12, g = 0.12, b = 0.15, a = 1.0 };
if !g_metal_gpu.begin_frame(clear) { return; }
// Compile the quad pipeline + upload its vertices once. The MTLDevice
// was created eagerly in main(), so both only need a valid device.
if g_quad_shader == 0 {
g_quad_shader = g_metal_gpu.create_shader(QUAD_MSL, "");
if g_quad_shader == 0 { return; }
}
if g_quad_vbuf == 0 {
g_quad_vbuf = g_metal_gpu.create_buffer(size_of([36]f32));
if g_quad_vbuf == 0 { return; }
g_metal_gpu.update_buffer(g_quad_vbuf, xx @QUAD_VERTS, size_of([36]f32));
}
if !g_metal_gpu.begin_frame(BG_CLEAR) { return; }
g_metal_gpu.set_shader(g_quad_shader);
g_metal_gpu.set_vertex_buffer(g_quad_vbuf);
g_metal_gpu.draw_triangles(0, 6);
g_metal_gpu.end_frame(fc.target_present_time);
} else {
glViewport(0, 0, fc.pixel_w, fc.pixel_h);
glClearColor(0.12, 0.12, 0.15, 1.0);
glClearColor(0.10, 0.20, 0.55, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
}
g_plat.end_frame();