240 lines
7.9 KiB
Plaintext
240 lines
7.9 KiB
Plaintext
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;
|
|
} |