Untitled
Anonymous
plain_text
02/02/2026 3:23 PM
8.2 KB
12
Indexable
package main
import "core:fmt"
import "core:mem"
import "core:slice"
import sdl "vendor:sdl3"
Instance_Data :: struct {
model: matrix[4, 4]f32,
}
main :: proc() {
ok: bool
app := new(App)
app_init(app)
defer app_deinit(app)
camera := Camera {
pos = {0, 0, -1},
fov = 60,
near = .1,
far = 100,
aspect = 16 / 9,
}
transforms := [?]Transform {
transform_identity({-1, 0, 0}),
transform_identity({1, 0, 0}),
}
triangle_vertices := [?][4]f32{{-.5, -.5, 0, 1}, {0, .5, 0, 1}, {.5, -.5, 0, 1}}
triangle_indices := [?]u32{0, 1, 2}
triangle_v_size := size_of(triangle_vertices[0]) * len(triangle_vertices)
triangle_i_size := size_of(triangle_indices[0]) * len(triangle_indices)
quad_vertices := [?][4]f32 {
{-.5, -.5, 0, 1},
{-.5, .5, 0, 1},
{.5, .5, 0, 1},
{.5, -.5, 0, 1},
}
// quad_indices := [?]u32{3, 4, 5, 3, 5, 6}
quad_indices := [?]u32{0, 1, 2, 0, 2, 3}
quad_v_size := size_of(quad_vertices[0]) * len(quad_vertices)
quad_i_size := size_of(quad_indices[0]) * len(quad_indices)
v_size := triangle_v_size + quad_v_size
i_size := triangle_i_size + quad_i_size
instances := [?]Instance_Data {
{model = transform_model(transforms[0])},
{model = transform_model(transforms[1])},
}
instance_size := size_of(instances[0]) * len(instances)
commands := []sdl.GPUIndexedIndirectDrawCommand {
{
num_indices = u32(len(triangle_indices)),
num_instances = 1,
first_index = 0,
vertex_offset = 0,
first_instance = 0,
},
{
num_indices = u32(len(quad_indices)),
num_instances = 1,
first_index = u32(len(triangle_indices)),
vertex_offset = len(triangle_vertices),
first_instance = 1,
},
}
commands_size := size_of(commands[0]) * len(commands)
v_buf := sdl.CreateGPUBuffer(
app.device,
{usage = {.GRAPHICS_STORAGE_READ, .VERTEX}, size = u32(v_size)},
)
i_buf := sdl.CreateGPUBuffer(
app.device,
{usage = {.GRAPHICS_STORAGE_READ}, size = u32(instance_size)},
)
idx_buf := sdl.CreateGPUBuffer(app.device, {usage = {.INDEX}, size = u32(i_size)})
command_buf := sdl.CreateGPUBuffer(
app.device,
{usage = {.INDIRECT}, size = u32(commands_size)},
)
t_buf := sdl.CreateGPUTransferBuffer(
app.device,
{usage = .UPLOAD, size = u32(v_size + i_size + instance_size + commands_size)},
)
ptr := transmute([^]u8)sdl.MapGPUTransferBuffer(app.device, t_buf, false)
mem.copy(ptr, &triangle_vertices[0], triangle_v_size)
mem.copy(ptr[triangle_v_size:], &quad_vertices[0], quad_v_size)
instance_offset := triangle_v_size + quad_v_size
mem.copy(ptr[instance_offset:], &instances[0], instance_size)
indices_offset := instance_offset + instance_size
mem.copy(ptr[indices_offset:], &triangle_indices[0], triangle_i_size)
mem.copy(ptr[indices_offset + triangle_i_size:], &quad_indices[0], quad_i_size)
indirect_offset := indices_offset + triangle_i_size + quad_i_size
mem.copy(ptr[indirect_offset:], &commands[0], commands_size)
sdl.UnmapGPUTransferBuffer(app.device, t_buf)
cmd := sdl.AcquireGPUCommandBuffer(app.device)
cp := sdl.BeginGPUCopyPass(cmd)
sdl.UploadToGPUBuffer(
cp,
{transfer_buffer = t_buf},
{buffer = v_buf, size = u32(v_size)},
false,
)
sdl.UploadToGPUBuffer(
cp,
{transfer_buffer = t_buf, offset = u32(instance_offset)},
{buffer = i_buf, size = u32(instance_size)},
false,
)
sdl.UploadToGPUBuffer(
cp,
{transfer_buffer = t_buf, offset = u32(indices_offset)},
{buffer = idx_buf, size = u32(i_size)},
false,
)
sdl.UploadToGPUBuffer(
cp,
{transfer_buffer = t_buf, offset = u32(indirect_offset)},
{buffer = command_buf, size = u32(commands_size)},
false,
)
sdl.EndGPUCopyPass(cp)
ok = sdl.SubmitGPUCommandBuffer(cmd);assert(ok)
sdl.ReleaseGPUTransferBuffer(app.device, t_buf)
ok = sdl.WaitForGPUIdle(app.device);assert(ok)
shaders := load_shader_module(
app.device,
"/home/dosynk/Projects/odin-learning-sdl/out/shaders/unlit_test.spv",
[Stage]u32{.VERTEX = 2, .FRAGMENT = 0},
[Stage]u32{.VERTEX = 0, .FRAGMENT = 0},
[Stage]cstring{.VERTEX = "vertexMain", .FRAGMENT = "fragmentMain"},
context.allocator,
)
defer for shader in shaders do sdl.ReleaseGPUShader(app.device, shader)
info := sdl.GPUGraphicsPipelineCreateInfo {
vertex_shader = shaders[.VERTEX],
fragment_shader = shaders[.FRAGMENT],
primitive_type = .TRIANGLELIST,
target_info = {
num_color_targets = 1,
color_target_descriptions = &sdl.GPUColorTargetDescription {
format = sdl.GetGPUSwapchainTextureFormat(app.device, app.window),
},
},
}
pip := sdl.CreateGPUGraphicsPipeline(app.device, info)
ubo := UBO {
view = camera_get_view(&camera),
proj = camera_get_proj(&camera),
}
renderer := Renderer {
command_buf = command_buf,
static_buf = v_buf,
index_buf = idx_buf,
instance_buf = i_buf,
pip = pip,
commands_number = u32(len(commands)),
uniform_data = &ubo,
}
for app.is_running {
handle_events(app)
handle_rendering(app, &renderer)
}
}
handle_events :: proc(app: ^App) {
evt: sdl.Event
for sdl.PollEvent(&evt) {
#partial switch evt.type {
case .QUIT:
app.is_running = false
case .KEY_DOWN:
if evt.key.scancode == .ESCAPE do app.is_running = false
}
}
}
handle_rendering :: proc(using app: ^App, renderer: ^Renderer) {
ok: bool
cmd := sdl.AcquireGPUCommandBuffer(device);assert(cmd != nil)
swapchain: ^sdl.GPUTexture
ok = sdl.WaitAndAcquireGPUSwapchainTexture(
cmd,
window,
&swapchain,
nil,
nil,
);assert(ok)
info := sdl.GPUColorTargetInfo {
texture = swapchain,
clear_color = {0, 0.5, 0.5, 1},
store_op = .STORE,
load_op = .CLEAR,
}
pass := sdl.BeginGPURenderPass(cmd, &info, 1, nil);assert(pass != nil)
sdl.BindGPUGraphicsPipeline(pass, renderer.pip)
sdl.BindGPUVertexStorageBuffers(pass, 0, &renderer.static_buf, 1)
sdl.BindGPUVertexStorageBuffers(pass, 1, &renderer.instance_buf, 1)
sdl.BindGPUIndexBuffer(pass, {buffer = renderer.index_buf}, ._32BIT)
sdl.PushGPUVertexUniformData(
cmd,
0,
renderer.uniform_data,
size_of(renderer.uniform_data^),
)
sdl.DrawGPUIndexedPrimitivesIndirect(
pass,
renderer.command_buf,
0,
renderer.commands_number,
)
sdl.EndGPURenderPass(pass)
ok = sdl.SubmitGPUCommandBuffer(cmd);assert(ok)
}Editor is loading...
Leave a Comment