fix: quick port to c3 0.8.2

This commit is contained in:
Alessandro Mauri 2026-07-25 13:04:23 +02:00
parent 73619fe6c5
commit cd371b5ee7
2 changed files with 102 additions and 102 deletions

View File

@ -1,7 +1,7 @@
module ugui::sdl3::ren; module ugui::sdl3::ren;
import std::io; import std::io;
import std::ascii; import std::core::ascii;
import ugui; import ugui;
import sdl3; import sdl3;
@ -13,7 +13,7 @@ fn bool? Ctx.handle_events(&ctx)
bool quit = false; bool quit = false;
ugui::ModKeys mod_set, mod_reset; ugui::ModKeys mod_set, mod_reset;
ugui::MouseButtons btn; ugui::MouseButtons btn;
sdl3::Event e; sdl3::SdlEvent e;
while (sdl3::pollEvent(&e)) { while (sdl3::pollEvent(&e)) {
switch (e.type) { switch (e.type) {
@ -28,18 +28,18 @@ fn bool? Ctx.handle_events(&ctx)
bool down = e.type == KEY_DOWN; bool down = e.type == KEY_DOWN;
switch (e.key.key) { switch (e.key.key) {
case sdl3::KEY_RCTRL: mod_set.rctrl = down; mod_reset.rctrl = !down; case KEY_RCTRL: mod_set.rctrl = down; mod_reset.rctrl = !down;
case sdl3::KEY_LCTRL: mod_set.lctrl = down; mod_reset.lctrl = !down; case KEY_LCTRL: mod_set.lctrl = down; mod_reset.lctrl = !down;
case sdl3::KEY_RSHIFT: mod_set.rshift = down; mod_reset.rshift = !down; case KEY_RSHIFT: mod_set.rshift = down; mod_reset.rshift = !down;
case sdl3::KEY_LSHIFT: mod_set.lshift = down; mod_reset.lshift = !down; case KEY_LSHIFT: mod_set.lshift = down; mod_reset.lshift = !down;
case sdl3::KEY_BACKSPACE: mod_set.bkspc = down; mod_reset.bkspc = !down; case KEY_BACKSPACE: mod_set.bkspc = down; mod_reset.bkspc = !down;
case sdl3::KEY_DELETE: mod_set.del = down; mod_reset.del = !down; case KEY_DELETE: mod_set.del = down; mod_reset.del = !down;
case sdl3::KEY_HOME: mod_set.home = down; mod_reset.home = !down; case KEY_HOME: mod_set.home = down; mod_reset.home = !down;
case sdl3::KEY_END: mod_set.end = down; mod_reset.end = !down; case KEY_END: mod_set.end = down; mod_reset.end = !down;
case sdl3::KEY_UP: mod_set.up = down; mod_reset.up = !down; case KEY_UP: mod_set.up = down; mod_reset.up = !down;
case sdl3::KEY_DOWN: mod_set.down = down; mod_reset.down = !down; case KEY_DOWN: mod_set.down = down; mod_reset.down = !down;
case sdl3::KEY_LEFT: mod_set.left = down; mod_reset.left = !down; case KEY_LEFT: mod_set.left = down; mod_reset.left = !down;
case sdl3::KEY_RIGHT: mod_set.right = down; mod_reset.right = !down; case KEY_RIGHT: mod_set.right = down; mod_reset.right = !down;
} }
ctx.input_mod_keys(mod_set, true); ctx.input_mod_keys(mod_set, true);
ctx.input_mod_keys(mod_reset, false); ctx.input_mod_keys(mod_reset, false);
@ -49,12 +49,12 @@ fn bool? Ctx.handle_events(&ctx)
// do manual text input, bummer // do manual text input, bummer
ModKeys mod = ctx.get_mod(); ModKeys mod = ctx.get_mod();
if (e.type == KEY_DOWN && (mod.lctrl || mod.rctrl)) { if (e.type == KEY_DOWN && (mod.lctrl || mod.rctrl)) {
if (ascii::is_alnum_m((uint)e.key.key)) { if (ascii::is_alnum((char)e.key.key)) {
ctx.input_char((char)e.key.key); ctx.input_char((char)e.key.key);
} }
} }
if (e.type == KEY_DOWN && e.key.key == sdl3::KEY_RETURN) ctx.input_char('\n'); if (e.type == KEY_DOWN && e.key.key == KEY_RETURN) ctx.input_char('\n');
case TEXT_INPUT: case TEXT_INPUT:
ctx.input_text_utf8(((ZString)e.text.text).str_view()); ctx.input_text_utf8(((ZString)e.text.text).str_view());
@ -70,13 +70,13 @@ fn bool? Ctx.handle_events(&ctx)
ctx.input_mouse_wheel((short)e.wheel.integer_x, (short)e.wheel.integer_y); ctx.input_mouse_wheel((short)e.wheel.integer_x, (short)e.wheel.integer_y);
case MOUSE_BUTTON_DOWN: nextcase; case MOUSE_BUTTON_DOWN: nextcase;
case MOUSE_BUTTON_UP: case MOUSE_BUTTON_UP:
sdl3::MouseButtonFlags mb = sdl3::getMouseState(null, null); sdl3::SdlMouseButtonFlags mb = sdl3::getMouseState(null, null);
btn = { btn = {
.btn_left = !!(mb & sdl3::BUTTON_LMASK), .btn_left = !!(mb & LMASK),
.btn_right = !!(mb & sdl3::BUTTON_RMASK), .btn_right = !!(mb & RMASK),
.btn_middle = !!(mb & sdl3::BUTTON_MMASK), .btn_middle = !!(mb & MMASK),
.btn_4 = !!(mb & sdl3::BUTTON_X1MASK), .btn_4 = !!(mb & X1MASK),
.btn_5 = !!(mb & sdl3::BUTTON_X2MASK), .btn_5 = !!(mb & X2MASK),
}; };
ctx.input_mouse_button(btn); ctx.input_mouse_button(btn);
//case POLL_SENTINEL: break; //case POLL_SENTINEL: break;
@ -88,10 +88,10 @@ fn bool? Ctx.handle_events(&ctx)
return quit; return quit;
} }
fn void pre(sdl3::Window* win) => sdl3::startTextInput(win); fn void pre(sdl3::SdlWindow* win) => sdl3::startTextInput(win);
// TODO: this has to be a function of Ctx if we want to set the fps internally // TODO: this has to be a function of Ctx if we want to set the fps internally
fn void wait_events(uint timeout_ms = 0) fn void wait_events(int timeout_ms = 0)
{ {
sdl3::waitEventTimeout(null, timeout_ms); sdl3::waitEventTimeout(null, timeout_ms);
} }

View File

@ -83,30 +83,30 @@ struct ViewsizeUniform @align(16) {
} }
struct Shader { struct Shader {
sdl3::GPUShader* frag; sdl3::SdlGPUShader* frag;
sdl3::GPUShader* vert; sdl3::SdlGPUShader* vert;
ugui::Id id; ugui::Id id;
} }
struct Pipeline { struct Pipeline {
sdl3::GPUGraphicsPipeline* pipeline; sdl3::SdlGPUGraphicsPipeline* pipeline;
ugui::Id id; ugui::Id id;
} }
struct Texture { struct Texture {
sdl3::GPUTexture* texture; sdl3::SdlGPUTexture* texture;
sdl3::GPUSampler* sampler; sdl3::SdlGPUSampler* sampler;
ushort width, height; ushort width, height;
ugui::Id id; ugui::Id id;
} }
// The GPU buffers that contain quad info, the size is determined by MAX_QUAD_BATCH // The GPU buffers that contain quad info, the size is determined by MAX_QUAD_BATCH
struct QuadBuffer { struct QuadBuffer {
sdl3::GPUBuffer* vert_buf; // on-gpu vertex buffer sdl3::SdlGPUBuffer* vert_buf; // on-gpu vertex buffer
sdl3::GPUBuffer* idx_buf; // on-gpu index buffer sdl3::SdlGPUBuffer* idx_buf; // on-gpu index buffer
sdl3::GPUBuffer* attr_buf; // on-gpu quad attribute buffer sdl3::SdlGPUBuffer* attr_buf; // on-gpu quad attribute buffer
sdl3::GPUTransferBuffer* attr_ts; sdl3::SdlGPUTransferBuffer* attr_ts;
QuadAttributes[] attr_ts_mapped; QuadAttributes[] attr_ts_mapped;
@ -121,11 +121,11 @@ alias PipelineList = IdList{Pipeline};
alias TextureList = IdList{Texture}; alias TextureList = IdList{Texture};
struct Renderer { struct Renderer {
sdl3::Window* win; sdl3::SdlWindow* win;
sdl3::GPUDevice* gpu; sdl3::SdlGPUDevice* gpu;
sdl3::GPURenderPass* render_pass; sdl3::SdlGPURenderPass* render_pass;
sdl3::GPUTexture* swapchain_texture; sdl3::SdlGPUTexture* swapchain_texture;
sdl3::GPUCommandBuffer* render_cmdbuf; sdl3::SdlGPUCommandBuffer* render_cmdbuf;
QuadBuffer quad_buffer; QuadBuffer quad_buffer;
ShaderList shaders; ShaderList shaders;
@ -178,7 +178,7 @@ $endif
} }
// create the window // create the window
self.win = sdl3::createWindow(title, width, height, {.resizable=true, .vulkan=true}); self.win = sdl3::createWindow(title, (int)width, (int)height, {.resizable=true, .vulkan=true});
if (self.win == null) { if (self.win == null) {
unreachable("sdl error: %s", sdl3::getError()); unreachable("sdl error: %s", sdl3::getError());
} }
@ -194,7 +194,7 @@ $endif
} }
// set swapchain parameters, like vsync // set swapchain parameters, like vsync
GPUPresentMode present_mode = vsync ? VSYNC : IMMEDIATE; SdlGPUPresentMode present_mode = vsync ? VSYNC : IMMEDIATE;
sdl3::setGPUSwapchainParameters(self.gpu, self.win, SDR, present_mode); sdl3::setGPUSwapchainParameters(self.gpu, self.win, SDR, present_mode);
// //
@ -206,29 +206,29 @@ $endif
// create the vertex and index buffer on the gpu // create the vertex and index buffer on the gpu
qb.vert_buf = sdl3::createGPUBuffer(self.gpu, qb.vert_buf = sdl3::createGPUBuffer(self.gpu,
&&(GPUBufferCreateInfo){.usage.vertex = true, .size = Quad.vertices.sizeof} &&(SdlGPUBufferCreateInfo){.usage.vertex = true, .size = $reflect(Quad.vertices).size}
); );
if (qb.vert_buf == null) { if (qb.vert_buf == null) {
unreachable("failed to initialize quad buffer (vertex): %s", sdl3::getError()); unreachable("failed to initialize quad buffer (vertex): %s", sdl3::getError());
} }
qb.idx_buf = sdl3::createGPUBuffer(self.gpu, qb.idx_buf = sdl3::createGPUBuffer(self.gpu,
&&(GPUBufferCreateInfo){.usage.index = true, .size = Quad.indices.sizeof} &&(SdlGPUBufferCreateInfo){.usage.index = true, .size = $reflect(Quad.indices).size}
); );
if (qb.idx_buf == null) { if (qb.idx_buf == null) {
unreachable("failed to initialize quad buffer (index): %s", sdl3::getError()); unreachable("failed to initialize quad buffer (index): %s", sdl3::getError());
} }
qb.attr_buf = sdl3::createGPUBuffer(self.gpu, qb.attr_buf = sdl3::createGPUBuffer(self.gpu,
&&(GPUBufferCreateInfo){.usage.vertex = true, .size = QuadAttributes.sizeof * MAX_QUAD_BATCH} &&(SdlGPUBufferCreateInfo){.usage.vertex = true, .size = QuadAttributes::size * MAX_QUAD_BATCH}
); );
if (qb.attr_buf == null) { if (qb.attr_buf == null) {
unreachable("failed to initialize quad buffer (index): %s", sdl3::getError()); unreachable("failed to initialize quad buffer (index): %s", sdl3::getError());
} }
// upload the quad mesh // upload the quad mesh
GPUTransferBuffer *ts = sdl3::createGPUTransferBuffer(self.gpu, SdlGPUTransferBuffer *ts = sdl3::createGPUTransferBuffer(self.gpu,
&&(GPUTransferBufferCreateInfo){.usage = UPLOAD, .size = Quad.sizeof} &&(SdlGPUTransferBufferCreateInfo){.usage = UPLOAD, .size = Quad::size}
); );
if (ts == null) { if (ts == null) {
unreachable("failed to create gpu transfer buffer: %s", sdl3::getError()); unreachable("failed to create gpu transfer buffer: %s", sdl3::getError());
@ -262,22 +262,22 @@ $endif
sdl3::unmapGPUTransferBuffer(self.gpu, ts); sdl3::unmapGPUTransferBuffer(self.gpu, ts);
GPUCommandBuffer* cmd = sdl3::acquireGPUCommandBuffer(self.gpu); SdlGPUCommandBuffer* cmd = sdl3::acquireGPUCommandBuffer(self.gpu);
if (cmd == null) { if (cmd == null) {
unreachable("failed to upload quad at acquiring command buffer: %s", sdl3::getError()); unreachable("failed to upload quad at acquiring command buffer: %s", sdl3::getError());
} }
GPUCopyPass* cpy = sdl3::beginGPUCopyPass(cmd); SdlGPUCopyPass* cpy = sdl3::beginGPUCopyPass(cmd);
// upload vertices // upload vertices
sdl3::uploadToGPUBuffer(cpy, sdl3::uploadToGPUBuffer(cpy,
&&(GPUTransferBufferLocation){.transfer_buffer = ts, .offset = Quad.vertices.offsetof}, &&(SdlGPUTransferBufferLocation){.transfer_buffer = ts, .offset = $reflect(Quad.vertices).offset},
&&(GPUBufferRegion){.buffer = qb.vert_buf, .offset = 0, .size = Quad.vertices.sizeof}, &&(SdlGPUBufferRegion){.buffer = qb.vert_buf, .offset = 0, .size = $reflect(Quad.vertices).size},
false false
); );
// upload indices // upload indices
sdl3::uploadToGPUBuffer(cpy, sdl3::uploadToGPUBuffer(cpy,
&&(GPUTransferBufferLocation){.transfer_buffer = ts, .offset = Quad.indices.offsetof}, &&(SdlGPUTransferBufferLocation){.transfer_buffer = ts, .offset = $reflect(Quad.indices).offset},
&&(GPUBufferRegion){.buffer = qb.idx_buf, .offset = 0, .size = Quad.indices.sizeof}, &&(SdlGPUBufferRegion){.buffer = qb.idx_buf, .offset = 0, .size = $reflect(Quad.indices).size},
false false
); );
@ -290,7 +290,7 @@ $endif
// create and map the quad attributes transfer buffer // create and map the quad attributes transfer buffer
qb.attr_ts = sdl3::createGPUTransferBuffer(self.gpu, qb.attr_ts = sdl3::createGPUTransferBuffer(self.gpu,
&&(GPUTransferBufferCreateInfo){.usage = UPLOAD, .size = QuadAttributes.sizeof * MAX_QUAD_BATCH} &&(SdlGPUTransferBufferCreateInfo){.usage = UPLOAD, .size = QuadAttributes::size * MAX_QUAD_BATCH}
); );
if (qb.attr_ts == null) { if (qb.attr_ts == null) {
unreachable("failed to create gpu transfer buffer: %s", sdl3::getError()); unreachable("failed to create gpu transfer buffer: %s", sdl3::getError());
@ -346,7 +346,7 @@ fn void Renderer.free(&self)
fn void Renderer.resize_window(&self, uint width, uint height) fn void Renderer.resize_window(&self, uint width, uint height)
{ {
sdl3::setWindowSize(self.win, width, height); sdl3::setWindowSize(self.win, (int)width, (int)height);
} }
@ -375,7 +375,7 @@ fn void Renderer.load_spirv_shader_from_mem(&self, String name, char[] vert_code
if (vert_code.len > 0) { if (vert_code.len > 0) {
// FIXME: these should be passed by parameter and/or automatically determined by parsing // FIXME: these should be passed by parameter and/or automatically determined by parsing
// the shader code // the shader code
GPUShaderCreateInfo shader_info = { SdlGPUShaderCreateInfo shader_info = {
.code = vert_code.ptr, .code = vert_code.ptr,
.code_size = vert_code.len, .code_size = vert_code.len,
.entrypoint = "main", .entrypoint = "main",
@ -396,7 +396,7 @@ fn void Renderer.load_spirv_shader_from_mem(&self, String name, char[] vert_code
if (frag_code.len > 0) { if (frag_code.len > 0) {
// FIXME: these should be passed by parameter and/or automatically determined by parsing // FIXME: these should be passed by parameter and/or automatically determined by parsing
// the shader code // the shader code
GPUShaderCreateInfo shader_info = { SdlGPUShaderCreateInfo shader_info = {
.code = frag_code.ptr, .code = frag_code.ptr,
.code_size = frag_code.len, .code_size = frag_code.len,
.entrypoint = "main", .entrypoint = "main",
@ -429,7 +429,7 @@ fn void Renderer.load_spirv_shader_from_file(&self, String name, String vert_pat
char[] frag_code; char[] frag_code;
// create vertex shader // create vertex shader
usz size = file::get_size(vert_path)!!; sz size = file::get_size(vert_path)!!;
vert_code = mem::new_array(char, size + size%4); vert_code = mem::new_array(char, size + size%4);
file::load_buffer(vert_path, vert_code)!!; file::load_buffer(vert_path, vert_code)!!;
defer mem::free(vert_code); defer mem::free(vert_code);
@ -451,7 +451,7 @@ fn void Renderer.load_spirv_shader_from_file(&self, String name, String vert_pat
// this describes what we want to draw, since for drawing different things we have to change // this describes what we want to draw, since for drawing different things we have to change
// the GPUPrimitiveType and GPURasterizerState for the pipeline. // the GPUPrimitiveType and GPURasterizerState for the pipeline.
enum PipelineType : (GPUPrimitiveType primitive_type, GPURasterizerState raster_state) { enum PipelineType : (SdlGPUPrimitiveType primitive_type, SdlGPURasterizerState raster_state) {
RECT {TRIANGLELIST, {.fill_mode = FILL, .cull_mode = NONE, .front_face = COUNTER_CLOCKWISE}}, RECT {TRIANGLELIST, {.fill_mode = FILL, .cull_mode = NONE, .front_face = COUNTER_CLOCKWISE}},
SPRITE {TRIANGLELIST, {.fill_mode = FILL, .cull_mode = NONE, .front_face = COUNTER_CLOCKWISE}}, SPRITE {TRIANGLELIST, {.fill_mode = FILL, .cull_mode = NONE, .front_face = COUNTER_CLOCKWISE}},
LINE {LINELIST, {.fill_mode = LINE, .cull_mode = NONE, .front_face = COUNTER_CLOCKWISE}}, LINE {LINELIST, {.fill_mode = LINE, .cull_mode = NONE, .front_face = COUNTER_CLOCKWISE}},
@ -467,7 +467,7 @@ fn void Renderer.create_pipeline(&self, String shader_name, PipelineType type)
unreachable("error in creating pipeline: no shader named %s", shader_name); unreachable("error in creating pipeline: no shader named %s", shader_name);
} }
GPUGraphicsPipelineCreateInfo ci = { SdlGPUGraphicsPipelineCreateInfo ci = {
.vertex_shader = s.vert, .vertex_shader = s.vert,
.fragment_shader = s.frag, .fragment_shader = s.frag,
// This structure specifies how the vertex buffer looks in memory, what it contains // This structure specifies how the vertex buffer looks in memory, what it contains
@ -476,21 +476,21 @@ fn void Renderer.create_pipeline(&self, String shader_name, PipelineType type)
// is represented by two floats, the color as 32 bit rgba and the uv also as intgers. // is represented by two floats, the color as 32 bit rgba and the uv also as intgers.
.vertex_input_state = { .vertex_input_state = {
// the description of each vertex buffer, for now I use only one buffer // the description of each vertex buffer, for now I use only one buffer
.vertex_buffer_descriptions = (GPUVertexBufferDescription[]){ .vertex_buffer_descriptions = (SdlGPUVertexBufferDescription[]){
{ // first slot, per-vertex attributes { // first slot, per-vertex attributes
.slot = 0, .slot = 0,
.pitch = Vertex.sizeof, .pitch = Vertex::size,
.input_rate = VERTEX, .input_rate = VERTEX,
}, },
{ // second slot, per-instance attributes { // second slot, per-instance attributes
.slot = 1, .slot = 1,
.pitch = QuadAttributes.sizeof, .pitch = QuadAttributes::size,
.input_rate = INSTANCE, .input_rate = INSTANCE,
} }
}, },
.num_vertex_buffers = 2, .num_vertex_buffers = 2,
// the description of each vertex, quad and bindings // the description of each vertex, quad and bindings
.vertex_attributes = (GPUVertexAttribute[]){ .vertex_attributes = (SdlGPUVertexAttribute[]){
{ // at location zero there is the position of the vertex { // at location zero there is the position of the vertex
.location = 0, .location = 0,
.buffer_slot = 0, // buffer slot zero so per-vertex .buffer_slot = 0, // buffer slot zero so per-vertex
@ -501,25 +501,25 @@ fn void Renderer.create_pipeline(&self, String shader_name, PipelineType type)
.location = 1, .location = 1,
.buffer_slot = 1, // buffer slot one so per-instance .buffer_slot = 1, // buffer slot one so per-instance
.format = SHORT4, // x,y,w,h .format = SHORT4, // x,y,w,h
.offset = QuadAttributes.pos.offsetof, .offset = $reflect(QuadAttributes.pos).offset,
}, },
{ // at location two there are the per-quad uv coordinates { // at location two there are the per-quad uv coordinates
.location = 2, .location = 2,
.buffer_slot = 1, .buffer_slot = 1,
.format = SHORT4, .format = SHORT4,
.offset = QuadAttributes.uv.offsetof, .offset = $reflect(QuadAttributes.uv).offset,
}, },
{ // at location three there is the quad color { // at location three there is the quad color
.location = 3, .location = 3,
.buffer_slot = 1, .buffer_slot = 1,
.format = UBYTE4, .format = UBYTE4,
.offset = QuadAttributes.color.offsetof, .offset = $reflect(QuadAttributes.color).offset,
}, },
{ // at location four there is the quad type { // at location four there is the quad type
.location = 4, .location = 4,
.buffer_slot = 1, .buffer_slot = 1,
.format = UINT, .format = UINT,
.offset = QuadAttributes.type.offsetof, .offset = $reflect(QuadAttributes.type).offset,
} }
}, },
.num_vertex_attributes = 5, .num_vertex_attributes = 5,
@ -531,7 +531,7 @@ fn void Renderer.create_pipeline(&self, String shader_name, PipelineType type)
.multisample_state = {}, // no multisampling, all zeroes .multisample_state = {}, // no multisampling, all zeroes
.depth_stencil_state = {}, // no stencil test, all zeroes .depth_stencil_state = {}, // no stencil test, all zeroes
.target_info = { // the target (texture) description .target_info = { // the target (texture) description
.color_target_descriptions = (GPUColorTargetDescription[]){{ .color_target_descriptions = (SdlGPUColorTargetDescription[]){{
// rendering happens to the window, so get it's format // rendering happens to the window, so get it's format
.format = sdl3::getGPUSwapchainTextureFormat(self.gpu, self.win), .format = sdl3::getGPUSwapchainTextureFormat(self.gpu, self.win),
.blend_state = { .blend_state = {
@ -560,7 +560,7 @@ fn void Renderer.create_pipeline(&self, String shader_name, PipelineType type)
}; };
if (p.pipeline == null) { if (p.pipeline == null) {
unreachable("failed to create pipeline (shaders: %s, type: %s): %s", shader_name, type.nameof, sdl3::getError()); unreachable("failed to create pipeline (shaders: %s, type: %s): %s", shader_name, TextureType::names[type], sdl3::getError());
} }
self.pipelines.push(p); self.pipelines.push(p);
@ -574,7 +574,7 @@ fn void Renderer.create_pipeline(&self, String shader_name, PipelineType type)
// NOTE: with TEXTUREUSAGE_SAMPLER the texture format cannot be intger _UINT so it has to be nermalized // NOTE: with TEXTUREUSAGE_SAMPLER the texture format cannot be intger _UINT so it has to be nermalized
enum TextureType : (GPUTextureFormat format) { enum TextureType : (SdlGPUTextureFormat format) {
FULL_COLOR {R8G8B8A8_UNORM}, FULL_COLOR {R8G8B8A8_UNORM},
JUST_ALPHA {R8_UNORM} JUST_ALPHA {R8_UNORM}
} }
@ -583,7 +583,7 @@ enum TextureType : (GPUTextureFormat format) {
// This macro wraps new_texture_by_id() by accepting either a name or an id directly // This macro wraps new_texture_by_id() by accepting either a name or an id directly
macro void Renderer.new_texture(&self, name_or_id, TextureType type, char[] pixels, uint width, uint height) macro void Renderer.new_texture(&self, name_or_id, TextureType type, char[] pixels, uint width, uint height)
{ {
$switch $typeof(name_or_id): $switch $Typeof(name_or_id):
$case uint: return self.new_texture_by_id(id, type, pixels, width, height); $case uint: return self.new_texture_by_id(id, type, pixels, width, height);
$case String: return self.new_texture_by_id(name_or_id.hash(), type, pixels, width, height); $case String: return self.new_texture_by_id(name_or_id.hash(), type, pixels, width, height);
$default: unreachable("texture must have a name (String) or an id (uint)"); $default: unreachable("texture must have a name (String) or an id (uint)");
@ -594,7 +594,7 @@ macro void Renderer.new_texture(&self, name_or_id, TextureType type, char[] pixe
// This macro wraps update_texture_by_id() by accepting either a name or an id directly // This macro wraps update_texture_by_id() by accepting either a name or an id directly
macro void Renderer.update_texture(&self, name_or_id, char[] pixels, uint width, uint height, uint x = 0, uint y = 0) macro void Renderer.update_texture(&self, name_or_id, char[] pixels, uint width, uint height, uint x = 0, uint y = 0)
{ {
$switch $typeof(name_or_id): $switch $Typeof(name_or_id):
$case uint: return self.update_texture_by_id(name_or_id, pixels, width, height, x, y); $case uint: return self.update_texture_by_id(name_or_id, pixels, width, height, x, y);
$case String: return self.update_texture_by_id(name_or_id.hash(), pixels, width, height, x, y); $case String: return self.update_texture_by_id(name_or_id.hash(), pixels, width, height, x, y);
$default: unreachable("texture must have a name (String) or an id (uint)"); $default: unreachable("texture must have a name (String) or an id (uint)");
@ -608,7 +608,7 @@ macro void Renderer.update_texture(&self, name_or_id, char[] pixels, uint width,
fn void Renderer.new_texture_by_id(&self, Id id, TextureType type, char[] pixels, uint width, uint height) fn void Renderer.new_texture_by_id(&self, Id id, TextureType type, char[] pixels, uint width, uint height)
{ {
// the texture description // the texture description
GPUTextureCreateInfo tci = { SdlGPUTextureCreateInfo tci = {
.type = T2D, .type = T2D,
.format = type.format, .format = type.format,
// all textures are used with samplers, which means read-only textures that contain data to be sampled // all textures are used with samplers, which means read-only textures that contain data to be sampled
@ -620,13 +620,13 @@ fn void Renderer.new_texture_by_id(&self, Id id, TextureType type, char[] pixels
// .sample_count not used since the texture is not a render target // .sample_count not used since the texture is not a render target
}; };
GPUTexture* texture = sdl3::createGPUTexture(self.gpu, &tci); SdlGPUTexture* texture = sdl3::createGPUTexture(self.gpu, &tci);
if (texture == null) { if (texture == null) {
unreachable("failed to create texture (id: %s, type: %s): %s", id, type.nameof, sdl3::getError()); unreachable("failed to create texture (id: %s, type: %s): %s", id, TextureType::names[type], sdl3::getError());
} }
// the sampler description, how the texture should be sampled // the sampler description, how the texture should be sampled
GPUSamplerCreateInfo sci = { SdlGPUSamplerCreateInfo sci = {
.min_filter = LINEAR, // linear interpolation for textures .min_filter = LINEAR, // linear interpolation for textures
.mag_filter = LINEAR, .mag_filter = LINEAR,
.mipmap_mode = NEAREST, .mipmap_mode = NEAREST,
@ -636,9 +636,9 @@ fn void Renderer.new_texture_by_id(&self, Id id, TextureType type, char[] pixels
// everything else is not used and not needed // everything else is not used and not needed
}; };
GPUSampler* sampler = sdl3::createGPUSampler(self.gpu, &sci); SdlGPUSampler* sampler = sdl3::createGPUSampler(self.gpu, &sci);
if (sampler == null) { if (sampler == null) {
unreachable("failed to create sampler (texture id: %s, type: %s): %s", id, type.nameof, sdl3::getError()); unreachable("failed to create sampler (texture id: %s, type: %s): %s", id, TextureType::names[type], sdl3::getError());
} }
Texture t = { Texture t = {
@ -663,7 +663,7 @@ fn void Renderer.update_texture_by_id(&self, Id id, char[] pixels, uint width, u
if (t == null || t.texture == null) { if (t == null || t.texture == null) {
unreachable("failed updating texture: no texture with id %s", id); unreachable("failed updating texture: no texture with id %s", id);
} }
GPUTexture* texture = t.texture; SdlGPUTexture* texture = t.texture;
// FIXME: do a better job at validating the copy // FIXME: do a better job at validating the copy
if (x > t.width || y > t.height) { if (x > t.width || y > t.height) {
@ -671,17 +671,17 @@ fn void Renderer.update_texture_by_id(&self, Id id, char[] pixels, uint width, u
} }
// upload image data // upload image data
GPUCommandBuffer* cmdbuf = sdl3::acquireGPUCommandBuffer(self.gpu); SdlGPUCommandBuffer* cmdbuf = sdl3::acquireGPUCommandBuffer(self.gpu);
if (cmdbuf == null) { if (cmdbuf == null) {
unreachable("failed to upload texture data at acquiring command buffer: %s", sdl3::getError()); unreachable("failed to upload texture data at acquiring command buffer: %s", sdl3::getError());
} }
GPUCopyPass* copypass = sdl3::beginGPUCopyPass(cmdbuf); SdlGPUCopyPass* copypass = sdl3::beginGPUCopyPass(cmdbuf);
if (copypass == null) { if (copypass == null) {
unreachable("failed to upload texture data at beginning copy pass: %s", sdl3::getError()); unreachable("failed to upload texture data at beginning copy pass: %s", sdl3::getError());
} }
GPUTransferBuffer* buf = sdl3::createGPUTransferBuffer(self.gpu, SdlGPUTransferBuffer* buf = sdl3::createGPUTransferBuffer(self.gpu,
&&(GPUTransferBufferCreateInfo){.usage = UPLOAD, .size = pixels.len} &&(SdlGPUTransferBufferCreateInfo){.usage = UPLOAD, .size = pixels.len}
); );
if (buf == null) { if (buf == null) {
unreachable("failed to upload texture data at creating the transfer buffer: %s", sdl3::getError()); unreachable("failed to upload texture data at creating the transfer buffer: %s", sdl3::getError());
@ -697,8 +697,8 @@ fn void Renderer.update_texture_by_id(&self, Id id, char[] pixels, uint width, u
// upload the data to gpu memory // upload the data to gpu memory
sdl3::uploadToGPUTexture(copypass, sdl3::uploadToGPUTexture(copypass,
&&(GPUTextureTransferInfo){.transfer_buffer = buf, .offset = 0}, &&(SdlGPUTextureTransferInfo){.transfer_buffer = buf, .offset = 0},
&&(GPUTextureRegion){.texture = texture, .x = x, .y = y, .w = width, .h = height, .d = 1}, &&(SdlGPUTextureRegion){.texture = texture, .x = x, .y = y, .w = width, .h = height, .d = 1},
false false
); );
@ -735,7 +735,7 @@ fn bool Renderer.push_quad(&self, short x, short y, short w, short h, uint color
{ {
QuadAttributes qa = { QuadAttributes qa = {
.pos = {.x = x, .y = y, .w = w, .h = h}, .pos = {.x = x, .y = y, .w = w, .h = h},
.uv = {.u = radius, .v = radius}, .uv = {.u = (short)radius, .v = (short)radius},
.color = color, .color = color,
.type = type .type = type
}; };
@ -768,16 +768,16 @@ fn void Renderer.upload_quads(&self)
{ {
QuadBuffer* qb = &self.quad_buffer; QuadBuffer* qb = &self.quad_buffer;
GPUCommandBuffer* cmd = sdl3::acquireGPUCommandBuffer(self.gpu); SdlGPUCommandBuffer* cmd = sdl3::acquireGPUCommandBuffer(self.gpu);
if (cmd == null) { if (cmd == null) {
unreachable("failed to upload quad at acquiring command buffer: %s", sdl3::getError()); unreachable("failed to upload quad at acquiring command buffer: %s", sdl3::getError());
} }
GPUCopyPass* cpy = sdl3::beginGPUCopyPass(cmd); SdlGPUCopyPass* cpy = sdl3::beginGPUCopyPass(cmd);
// upload quad attributes // upload quad attributes
sdl3::uploadToGPUBuffer(cpy, sdl3::uploadToGPUBuffer(cpy,
&&(GPUTransferBufferLocation){.transfer_buffer = qb.attr_ts, .offset = 0}, &&(SdlGPUTransferBufferLocation){.transfer_buffer = qb.attr_ts, .offset = 0},
&&(GPUBufferRegion){.buffer = qb.attr_buf, .offset = 0, .size = QuadAttributes.sizeof * qb.count}, &&(SdlGPUBufferRegion){.buffer = qb.attr_buf, .offset = 0, .size = QuadAttributes::size * (uint)qb.count},
false false
); );
@ -794,16 +794,16 @@ fn void Renderer.draw_quads(&self, uint off, uint count)
QuadBuffer* qb = &self.quad_buffer; QuadBuffer* qb = &self.quad_buffer;
// too many quads to draw // too many quads to draw
if (off >= qb.count || count > qb.count - off) { if (off >= (uint)qb.count || count > (uint)qb.count - off) {
unreachable("too many quads, have %d, requested %d, offset %d", qb.count, count, off); unreachable("too many quads, have %d, requested %d, offset %d", qb.count, count, off);
} }
sdl3::bindGPUVertexBuffers(self.render_pass, 0, sdl3::bindGPUVertexBuffers(self.render_pass, 0,
(GPUBufferBinding[]){ (SdlGPUBufferBinding[]){
{.buffer = qb.vert_buf, .offset = 0}, {.buffer = qb.vert_buf, .offset = 0},
{.buffer = qb.attr_buf, .offset = 0}, {.buffer = qb.attr_buf, .offset = 0},
}, 2); }, 2);
sdl3::bindGPUIndexBuffer(self.render_pass, &&(GPUBufferBinding){.buffer = qb.idx_buf, .offset = 0}, BIT16); sdl3::bindGPUIndexBuffer(self.render_pass, &&(SdlGPUBufferBinding){.buffer = qb.idx_buf, .offset = 0}, BIT16);
sdl3::drawGPUIndexedPrimitives(self.render_pass, 6, count, 0, 0, off); sdl3::drawGPUIndexedPrimitives(self.render_pass, 6, count, 0, 0, off);
} }
@ -823,12 +823,12 @@ fn void Renderer.begin_render(&self, bool clear_screen)
// TODO: maybe make this configurable and/or add more things // TODO: maybe make this configurable and/or add more things
ViewsizeUniform v; ViewsizeUniform v;
self.get_window_size(&v.w, &v.h); self.get_window_size(&v.w, &v.h);
sdl3::pushGPUVertexUniformData(self.render_cmdbuf, 0, &v, ViewsizeUniform.sizeof); sdl3::pushGPUVertexUniformData(self.render_cmdbuf, 0, &v, ViewsizeUniform::size);
sdl3::pushGPUFragmentUniformData(self.render_cmdbuf, 0, &v, ViewsizeUniform.sizeof); sdl3::pushGPUFragmentUniformData(self.render_cmdbuf, 0, &v, ViewsizeUniform::size);
if (clear_screen) { if (clear_screen) {
GPURenderPass* pass = sdl3::beginGPURenderPass(self.render_cmdbuf, SdlGPURenderPass* pass = sdl3::beginGPURenderPass(self.render_cmdbuf,
&&(GPUColorTargetInfo){ &&(SdlGPUColorTargetInfo){
.texture = self.swapchain_texture, .texture = self.swapchain_texture,
.mip_level = 0, .mip_level = 0,
.layer_or_depth_plane = 0, .layer_or_depth_plane = 0,
@ -863,7 +863,7 @@ fn void Renderer.end_render(&self)
fn void Renderer.start_render_pass(&self, String pipeline_name) fn void Renderer.start_render_pass(&self, String pipeline_name)
{ {
self.render_pass = sdl3::beginGPURenderPass(self.render_cmdbuf, self.render_pass = sdl3::beginGPURenderPass(self.render_cmdbuf,
&&(GPUColorTargetInfo){ &&(SdlGPUColorTargetInfo){
.texture = self.swapchain_texture, .texture = self.swapchain_texture,
.mip_level = 0, .mip_level = 0,
.layer_or_depth_plane = 0, .layer_or_depth_plane = 0,
@ -884,7 +884,7 @@ fn void Renderer.start_render_pass(&self, String pipeline_name)
unreachable("render pass creation went wrong: %s", sdl3::getError()); unreachable("render pass creation went wrong: %s", sdl3::getError());
} }
sdl3::GPUGraphicsPipeline* p; sdl3::SdlGPUGraphicsPipeline* p;
p = self.pipelines.get_from_name(pipeline_name).pipeline; p = self.pipelines.get_from_name(pipeline_name).pipeline;
if (p == null) { if (p == null) {
unreachable("no pipeline"); unreachable("no pipeline");
@ -909,7 +909,7 @@ fn void Renderer.bind_textures(&self, String... texture_names)
unreachable("texture '%s' was not registered", name); unreachable("texture '%s' was not registered", name);
} }
sdl3::bindGPUFragmentSamplers(self.render_pass, (uint)idx, sdl3::bindGPUFragmentSamplers(self.render_pass, (uint)idx,
(GPUTextureSamplerBinding[]){{.texture = tx.texture, .sampler = tx.sampler}}, 1 (SdlGPUTextureSamplerBinding[]){{.texture = tx.texture, .sampler = tx.sampler}}, 1
); );
} }
} }
@ -924,7 +924,7 @@ fn void Renderer.bind_textures_id(&self, ugui::Id... texture_ids)
unreachable("texture [%d] was not registered", id); unreachable("texture [%d] was not registered", id);
} }
sdl3::bindGPUFragmentSamplers(self.render_pass, (uint)idx, sdl3::bindGPUFragmentSamplers(self.render_pass, (uint)idx,
(GPUTextureSamplerBinding[]){{.texture = tx.texture, .sampler = tx.sampler}}, 1 (SdlGPUTextureSamplerBinding[]){{.texture = tx.texture, .sampler = tx.sampler}}, 1
); );
} }
} }
@ -935,7 +935,7 @@ fn void Renderer.set_scissor(&self, int x, int y, int w, int h)
// in vulkan scissor size must be positive, clamp to zero // in vulkan scissor size must be positive, clamp to zero
w = max(w, 0); w = max(w, 0);
h = max(h, 0); h = max(h, 0);
sdl3::setGPUScissor(self.render_pass, &&(sdl3::Rect){x,y,w,h}); sdl3::setGPUScissor(self.render_pass, &&(sdl3::SdlRect){x,y,w,h});
} }
fn void Renderer.reset_scissor(&self) fn void Renderer.reset_scissor(&self)
@ -1010,7 +1010,7 @@ fn void Renderer.render_ugui(&self, CmdQueue* queue)
// TODO: verify the correct type // TODO: verify the correct type
CmdUpdateAtlas u = cmd.update_atlas; CmdUpdateAtlas u = cmd.update_atlas;
char[] pixels = u.raw_buffer[..u.width*u.height*u.bpp]; char[] pixels = u.raw_buffer[..u.width*u.height*u.bpp];
self.update_texture(u.id, pixels, u.width, u.height); self.update_texture(u.id, pixels, (uint)u.width, (uint)u.height);
case CMD_SCISSOR: case CMD_SCISSOR:
ugui::Rect s = cmd.scissor.rect; ugui::Rect s = cmd.scissor.rect;
if (s.x == 0 && s.y == 0 && s.w == 0 && s.h == 0) { if (s.x == 0 && s.y == 0 && s.w == 0 && s.h == 0) {