import std::io; import sdl3::sdl; import std::io::file; import std::core::mem; const int WINDOW_WIDTH = 1200; const int WINDOW_HEIGHT = 800; const ZString WINDOW_TITLE = "Basic Triangle"; fn GPUShader* load_shader(GPUDevice* device, ZString filename, GPUShaderStage stage, uint sampler_count, uint uniform_buffer_count, uint storage_buffer_count, uint storage_texture_count) { //if(!SDL_GetPathInfo(filename, null)) { // io::eprintf("File (%s) does not exist.\n", filename); // return null; //} if (!file::is_file(filename.str_view())) { io::eprintf("File %s is not a file\n", filename); return null; } ZString entrypoint; GPUShaderFormat backend_formats = sdl::get_gpu_shader_formats(device); GPUShaderFormat format = GPU_SHADERFORMAT_INVALID; if (backend_formats & GPU_SHADERFORMAT_SPIRV) { format = GPU_SHADERFORMAT_SPIRV; entrypoint = "main"; } usz code_size = file::get_size(filename.str_view())!!; char[] code = mem::new_array(char, code_size+1); file::load_buffer(filename.str_view(), code)!!; GPUShaderCreateInfo shader_info = { .code = code.ptr, .code_size = code.len, .entrypoint = entrypoint, .format = format, .stage = stage, .num_samplers = sampler_count, .num_uniform_buffers = uniform_buffer_count, .num_storage_buffers = storage_buffer_count, .num_storage_textures = storage_texture_count }; GPUShader* shader = sdl::create_gpu_shader(device, &shader_info); if (shader == null) { io::eprintf("ERROR: SDL_CreateGPUShader failed: %s\n", sdl::get_error()); mem::free(code); return null; } mem::free(code); return shader; } fn void print_info() { int render_drivers = sdl::get_num_render_drivers(); io::printf("Number of render drivers: %d\n", render_drivers)!!; for (int i = 0; i < render_drivers; i++) { io::printf("Render driver #%d: %s\n", i, sdl::get_render_driver(i))!!; } int video_drivers = sdl::get_num_video_drivers(); io::printf("Number of video drivers: %d\n", video_drivers)!!; for (int i = 0; i < video_drivers; i++) { io::printf("Video driver #%d: %s\n", i, sdl::get_video_driver(i))!!; } io::printf("Current video driver: %s\n", sdl::get_current_video_driver())!!; } fn void handle_event(Event event, bool* quit) { switch (event.type) { case EVENT_QUIT: { *quit = true; } break; case EVENT_KEY_DOWN: { switch (event.key.key) { case K_Q: { *quit = true; } break; case sdl::K_W: { } break; case sdl::K_S: { } break; case sdl::K_D: { } break; } } break; } } fn int main() { sdl::set_hint(sdl::HINT_VIDEO_DRIVER, "wayland"); if (!sdl::init(sdl::INIT_VIDEO)) { io::eprintf("ERROR: SDL_Init failed: %s\n", sdl::get_error()); return 1; } Window* window; window = sdl::create_window(WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_VULKAN); if (window == null) { io::eprintf("ERROR: SDL_CreateWindow failed: %s\n", sdl::get_error()); return 1; } sdl::set_window_position(window, WINDOWPOS_CENTERED, WINDOWPOS_CENTERED); GPUDevice* device = sdl::create_gpu_device(GPU_SHADERFORMAT_SPIRV, true, null); if (device == null) { io::eprintf("ERROR: SDL_CreateGPUDevice failed: %s\n", sdl::get_error()); return 1; } ZString device_driver = sdl::get_gpu_device_driver(device); io::printf("OK: Created device with driver %s\n", device_driver)!!; if (!sdl::claim_window_for_gpu_device(device, window)) { io::eprintf("ERROR: SDL_ClaimWindowForGPUDevice failed: %s\n", sdl::get_error()); return 1; } // Load shaders + create fill/line pipeline GPUShader* shader_vert = load_shader(device, "shaders/compiled/RawTriangle.vert.spv", GPU_SHADERSTAGE_VERTEX, 0, 0, 0, 0); if (shader_vert == null) { io::eprintf("ERROR: LoadShader failed \n"); return 1; } GPUShader* shader_frag = load_shader(device, "shaders/compiled/SolidColor.frag.spv", GPU_SHADERSTAGE_FRAGMENT, 0, 0, 0, 0); if (shader_vert == null) { io::eprintf("ERROR: LoadShader failed \n"); return 1; } GPUGraphicsPipelineCreateInfo pipeline_info = { .target_info = { .num_color_targets = 1, .color_target_descriptions = (GPUColorTargetDescription[]){{ .format = sdl::get_gpu_swapchain_texture_format(device, window) }}, }, .primitive_type = GPU_PRIMITIVETYPE_TRIANGLELIST, .vertex_shader = shader_vert, .fragment_shader = shader_frag, }; GPUGraphicsPipeline* pipeline_fill; GPUGraphicsPipeline* pipeline_line; pipeline_info.rasterizer_state.fill_mode = GPU_FILLMODE_FILL; pipeline_fill = sdl::create_gpu_graphics_pipeline(device, &pipeline_info); if (pipeline_fill == null) { io::eprintf("ERROR: SDL_CreateGPUGraphicsPipeline failed: %s\n", sdl::get_error()); return -1; } pipeline_info.rasterizer_state.fill_mode = GPU_FILLMODE_LINE; pipeline_line = sdl::create_gpu_graphics_pipeline(device, &pipeline_info); if (pipeline_line == null) { io::eprintf("ERROR: SDL_CreateGPUGraphicsPipeline failed: %s\n", sdl::get_error()); return -1; } sdl::release_gpu_shader(device, shader_vert); sdl::release_gpu_shader(device, shader_frag); const FColor COLOR_WHITE = (FColor) { 1.0f, 1.0f, 1.0f, 1.0f }; const FColor COLOR_BLACK = (FColor) { 0.0f, 0.0f, 0.0f, 1.0f }; const FColor COLOR_RED = (FColor) { 1.0f, 0.0f, 0.0f, 1.0f }; const FColor COLOR_GREEN = (FColor) { 0.0f, 1.0f, 0.0f, 1.0f }; const FColor COLOR_BLUE = (FColor) { 0.0f, 0.0f, 1.0f, 1.0f }; const FColor COLOR_CYAN = (FColor) { 0.0f, 1.0f, 1.0f, 1.0f }; const FColor COLOR_YELLOW = (FColor) { 1.0f, 1.0f, 0.0f, 1.0f }; const FColor COLOR_PINK = (FColor) { 1.0f, 0.0f, 1.0f, 1.0f }; print_info(); bool quit = false; while (!quit) { Event event; if (sdl::poll_event(&event)) handle_event(event, &quit); GPUCommandBuffer* cmdbuf = sdl::acquire_gpu_command_buffer(device); if (cmdbuf == null) { io::eprintf("ERROR: SDL_AcquireGPUCommandBuffer failed: %s\n", sdl::get_error()); break; } GPUTexture* swapchain_texture; if (!sdl::wait_and_acquire_gpu_swapchain_texture(cmdbuf, window, &swapchain_texture, null, null)) { io::eprintf("ERROR: SDL_WaitAndAcquireGPUSwapchainTexture failed: %s\n", sdl::get_error()); break; } if (swapchain_texture == null) { io::eprintf("ERROR: swapchain_texture is null\n"); sdl::submit_gpu_command_buffer(cmdbuf); break; } GPUColorTargetInfo color_target_info; color_target_info.texture = swapchain_texture; color_target_info.clear_color = COLOR_BLACK; color_target_info.load_op = GPU_LOADOP_CLEAR; color_target_info.store_op = GPU_STOREOP_STORE; GPURenderPass* render_pass = sdl::begin_gpu_render_pass(cmdbuf, &color_target_info, 1, null); sdl::bind_gpu_graphics_pipeline(render_pass, pipeline_fill); sdl::draw_gpu_primitives(render_pass, 3, 1, 0, 0); sdl::end_gpu_render_pass(render_pass); sdl::submit_gpu_command_buffer(cmdbuf); } sdl::release_gpu_graphics_pipeline(device, pipeline_fill); sdl::release_gpu_graphics_pipeline(device, pipeline_line); sdl::release_window_from_gpu_device(device, window); sdl::destroy_window(window); sdl::destroy_gpu_device(device); sdl::quit(); return 0; }