#import "modules/std.sx"; #import "modules/gpu/types.sx"; // GPU is the rendering-API abstraction. Concrete backends live as siblings // of this file: `metal.sx` (iOS, eventually macOS), `vulkan.sx` (Linux/ // Android, plus macOS via MoltenVK), `webgpu.sx` (wasm). The SDL-backed // GL renderer used by the desktop+wasm path stays as-is until those // backends land. GPU :: protocol { // Bind the GPU to a backend-specific render target (e.g. a // CAMetalLayer on iOS). pixel_w/pixel_h are the drawable's pixel // dimensions; call resize when they change. init :: (target: *void, pixel_w: s32, pixel_h: s32) -> bool; shutdown :: (); resize :: (pixel_w: s32, pixel_h: s32); begin_frame :: (clear: ClearColor) -> bool; // target_time is the host clock time at which the drawable should be // presented (units match the platform's CADisplayLink.targetTimestamp // on Apple). Metal forwards it to presentDrawable:atTime: to cap the // pipeline at one frame so the inset slide lands on the same vsync as // UIKit's keyboard view. GL backends ignore it. end_frame :: (target_time: f64); create_shader :: (vsrc: string, fsrc: string) -> ShaderHandle; create_buffer :: (size_bytes: s64) -> BufferHandle; update_buffer :: (buf: BufferHandle, data: *void, size_bytes: s64); // Sub-buffer write at a byte offset. Required for Metal where re-using // the same buffer slice across multiple draws in a single command // encoder is a race: the GPU executes draws asynchronously and reads // shared-storage buffer contents at execution time, so the LAST writer // wins if every flush targets offset 0. Renderers that issue more than // one draw per frame must advance their write offset between flushes. update_buffer_at :: (buf: BufferHandle, data: *void, size_bytes: s64, byte_offset: s64); create_texture :: (w: s32, h: s32, format: TextureFormat, pixels: *void) -> TextureHandle; update_texture_region :: (tex: TextureHandle, x: s32, y: s32, w: s32, h: s32, pixels: *void); // Release a GPU resource. Implementations release the backing object and // null the slot so the handle becomes inert. Calling with handle 0 or // an already-destroyed handle is a no-op. Handles are not re-used; the // backing List entry stays at its index with a null sentinel. destroy_shader :: (sh: ShaderHandle); destroy_buffer :: (buf: BufferHandle); destroy_texture :: (tex: TextureHandle); set_shader :: (sh: ShaderHandle); set_vertex_buffer :: (buf: BufferHandle); set_texture :: (slot: u32, tex: TextureHandle); set_vertex_constants :: (slot: u32, data: *void, size_bytes: s64); set_scissor :: (x: s32, y: s32, w: s32, h: s32); disable_scissor :: (); draw_triangles :: (vertex_offset: s32, vertex_count: s32); }