package main import sdl "vendor:sdl3" import "core:math/linalg" import "core:mem" frag_shader_code := #load("shader.spv.frag") vert_shader_code := #load("shader.spv.vert") main :: proc() { ok := sdl.Init({.VIDEO}); assert(ok) sdl.SetLogPriorities(.VERBOSE) window := sdl.CreateWindow("Pain and Suffering and Pleasure", 800, 500, nil) device := sdl.CreateGPUDevice({.SPIRV}, true, nil) ok = sdl.ClaimWindowForGPUDevice(device, window); assert(ok) vert_shader := sdl.CreateGPUShader(device, { code_size = len(vert_shader_code), code = raw_data(vert_shader_code), entrypoint = "main", format = {.SPIRV}, stage = .VERTEX, num_uniform_buffers = 1, }) frag_shader := sdl.CreateGPUShader(device, { code_size = len(frag_shader_code), code = raw_data(frag_shader_code), entrypoint = "main", format = {.SPIRV}, stage = .FRAGMENT, num_uniform_buffers = 0, }) Vec3 :: [3]f32 Vertex_Data :: struct { pos: Vec3, color: sdl.FColor, } size : f32= 1 vertices := []Vertex_Data { { pos = {-size, size, 1}, color = {1,0,0,1} }, {pos = {size, size, 1}, color = {0,1,1,1}}, {pos={-size,-size, 1}, color = {1,0,1,1}}, {pos={size,-size, 1}, color = {1,0,1,1}}, } vertices_byte_size := len(vertices) * size_of(vertices[0]) indicies := []u16 { 0,1,2, 2,1,3 } indices_byte_size := len(indicies) * size_of(indicies[0]) vertex_buf := sdl.CreateGPUBuffer(device, { usage = {.VERTEX}, size = u32(vertices_byte_size), }) index_buf := sdl.CreateGPUBuffer(device, { usage = {.INDEX}, size = u32(vertices_byte_size), }) transfer_buf := sdl.CreateGPUTransferBuffer(device, { usage = .UPLOAD, size = u32(vertices_byte_size + indices_byte_size), }) transfer_mem := transmute([^]byte)sdl.MapGPUTransferBuffer(device, transfer_buf, false) mem.copy(transfer_mem, raw_data(vertices), vertices_byte_size) mem.copy(transfer_mem[vertices_byte_size:], raw_data(indicies), indices_byte_size) sdl.UnmapGPUTransferBuffer(device, transfer_buf) copy_buffer := sdl.AcquireGPUCommandBuffer(device) copy_pass := sdl.BeginGPUCopyPass(copy_buffer) sdl.UploadToGPUBuffer(copy_pass, { transfer_buffer = transfer_buf, }, { buffer = vertex_buf, size = u32(vertices_byte_size), }, false) sdl.UploadToGPUBuffer(copy_pass, { transfer_buffer = transfer_buf, offset = u32(vertices_byte_size) }, { buffer = index_buf, size = u32(indices_byte_size) }, false) sdl.EndGPUCopyPass(copy_pass) ok = sdl.SubmitGPUCommandBuffer(copy_buffer); assert(ok) sdl.ReleaseGPUTransferBuffer(device, transfer_buf) vertex_attrs := []sdl.GPUVertexAttribute { { location = 0, format = .FLOAT3, offset = u32(offset_of(Vertex_Data, pos)), }, { location = 1, format = .FLOAT4, offset = u32(offset_of(Vertex_Data, color)), } } pipeline := sdl.CreateGPUGraphicsPipeline(device, { vertex_shader = vert_shader, fragment_shader = frag_shader, primitive_type = .TRIANGLELIST, vertex_input_state = { num_vertex_buffers = 1, vertex_buffer_descriptions = &(sdl.GPUVertexBufferDescription{ slot = 0, pitch = size_of(Vertex_Data), }), num_vertex_attributes = u32(len(vertex_attrs)), vertex_attributes = raw_data(vertex_attrs), }, target_info = { num_color_targets = 1, color_target_descriptions = &(sdl.GPUColorTargetDescription{ format = sdl.GetGPUSwapchainTextureFormat(device, window) }) } }) defer sdl.ReleaseGPUShader(device, frag_shader) defer sdl.ReleaseGPUShader(device, vert_shader) win_size: [2]i32 ok = sdl.GetWindowSize(window, &win_size.x, &win_size.y); assert(ok) rotation_speed := linalg.to_radians(f32(90)) rotation := f32(0.62) proj := linalg.matrix4_perspective_f32(linalg.to_radians(f32(70)), f32(win_size.x) / f32(win_size.y), 0.0001, 1000) UBO :: struct { mvp: matrix[4,4]f32 } last_ticks := sdl.GetTicks() for { new_ticks := sdl.GetTicks() delta_time := f32(new_ticks - last_ticks) / 1000 last_ticks = new_ticks event: sdl.Event for sdl.PollEvent(&event) { #partial switch(event.type) { case .QUIT: return case .KEY_DOWN: #partial switch(event.key.scancode) { case .ESCAPE: return } } } buffer := sdl.AcquireGPUCommandBuffer(device) texture: ^sdl.GPUTexture ok = sdl.WaitAndAcquireGPUSwapchainTexture(buffer, window, &texture, nil, nil); assert(ok) rotation += rotation_speed * delta_time model_mat := linalg.matrix4_translate_f32({0,0,-5}) * linalg.matrix4_rotate_f32(rotation, {0,1,0}) ubo := UBO {mvp = proj * model_mat} if texture != nil { color_target := sdl.GPUColorTargetInfo{ texture = texture, load_op = .CLEAR, clear_color = {0,0.2,0.4,1}, store_op = .STORE, } render_pass := sdl.BeginGPURenderPass(buffer, &color_target, 1, nil) sdl.BindGPUGraphicsPipeline(render_pass, pipeline) sdl.BindGPUVertexBuffers(render_pass, 0, &(sdl.GPUBufferBinding{ buffer = vertex_buf, }),1) sdl.BindGPUIndexBuffer(render_pass, {buffer = index_buf}, ._16BIT) sdl.PushGPUVertexUniformData(buffer, 0, &ubo, size_of(ubo)) sdl.DrawGPUIndexedPrimitives(render_pass, 6, 1, 0, 0 ,0) sdl.EndGPURenderPass(render_pass) } ok = sdl.SubmitGPUCommandBuffer(buffer); assert(ok) } }