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