diff options
| author | Connor Thomson <blumatrikz@gmail.com> | 2026-09-08 18:27:39 -0700 |
|---|---|---|
| committer | Connor Thomson <blumatrikz@gmail.com> | 2026-09-08 18:27:39 -0700 |
| commit | f1ddc12b68b4e4c8087962de25260470e6df2bea (patch) | |
| tree | 7d0440a6402a9b0ef75ded23fa64b68534255bba /src/gpu.c | |
| parent | 6025860a61386bf767b29c3ec5fd0d31285f1056 (diff) | |
Add tuxanci2 files
Diffstat (limited to 'src/gpu.c')
| -rw-r--r-- | src/gpu.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/src/gpu.c b/src/gpu.c new file mode 100644 index 0000000..9d4bd9d --- /dev/null +++ b/src/gpu.c @@ -0,0 +1,209 @@ +/* + * Tuxánci 2 - A first person shooter + * Copyright (C) 2007-2011 Tuxánci Development Team + * Copyright (C) 2025-2026 Connor Thomson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include "ta_sdl.h" +#include "window.h" +#include "files.h" +#include "text.h" +#include "logging.h" +#include "screen.h" + +#define SPIRV_ENTRY_POINT "main" + +SDL_GPUDevice *ta_gpu_device; +SDL_GPUGraphicsPipeline *ta_gpu_text_pipeline; +SDL_GPUTexture *ta_gpu_text_texture; +SDL_GPUSampler *ta_gpu_text_sampler; +Uint32 ta_gpu_text_texture_width; +Uint32 ta_gpu_text_texture_height; +static SDL_GPUTexture *ta_gpu_msaa_texture; +static SDL_GPUTexture *ta_gpu_depth_texture; +SDL_GPUSampleCount ta_gpu_sample_count = SDL_GPU_SAMPLECOUNT_8; +SDL_GPUTextureFormat ta_gpu_swapchain_format; +static Uint32 ta_gpu_msaa_texture_width; +static Uint32 ta_gpu_msaa_texture_height; +static SDL_GPUCommandBuffer *ta_gpu_command_buffer; +static SDL_GPUTexture *ta_gpu_swapchain_texture; + +static void ta_gpu_resize_msaa_texture(SDL_GPUTextureFormat format) { + if (ta_gpu_msaa_texture_width == (Uint32)ta_window_width && + ta_gpu_msaa_texture_height == (Uint32)ta_window_height && + ta_gpu_msaa_texture) { + return; + } + + SDL_ReleaseGPUTexture(ta_gpu_device, ta_gpu_msaa_texture); + SDL_ReleaseGPUTexture(ta_gpu_device, ta_gpu_depth_texture); + ta_gpu_msaa_texture = NULL; + ta_gpu_depth_texture = NULL; + + SDL_GPUTextureCreateInfo texture_info = { + .type = SDL_GPU_TEXTURETYPE_2D, + .format = format, + .usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET, + .width = (Uint32)ta_window_width, + .height = (Uint32)ta_window_height, + .layer_count_or_depth = 1, + .num_levels = 1, + .sample_count = ta_gpu_sample_count, + }; + ta_gpu_msaa_texture = ta_sdl_create_gpu_texture(ta_gpu_device, &texture_info); + texture_info.format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT; + texture_info.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET; + ta_gpu_depth_texture = ta_sdl_create_gpu_texture(ta_gpu_device, &texture_info); + ta_gpu_msaa_texture_width = (Uint32)ta_window_width; + ta_gpu_msaa_texture_height = (Uint32)ta_window_height; +} + +static SDL_GPUShader *ta_gpu_load_shader(SDL_GPUDevice *device, const void *code, size_t code_size, SDL_GPUShaderStage stage, Uint32 num_samplers, Uint32 num_uniform_buffers) { + SDL_GPUShaderCreateInfo info = { + .code = code, + .code_size = code_size, + .entrypoint = SPIRV_ENTRY_POINT, + .format = SDL_GPU_SHADERFORMAT_SPIRV, + .stage = stage, + .num_samplers = num_samplers, + .num_uniform_buffers = num_uniform_buffers, + }; + + SDL_GPUShader *shader = ta_sdl_create_gpu_shader(device, &info); + return shader; +} + +void ta_gpu_init(void) { + ta_gpu_device = ta_sdl_create_gpu_device(); + + ta_sdl_claim_window_for_gpu_device(ta_gpu_device, ta_window); + + ta_gpu_swapchain_format = SDL_GetGPUSwapchainTextureFormat(ta_gpu_device, ta_window); + ta_gpu_resize_msaa_texture(ta_gpu_swapchain_format); + + SDL_GPUShader *vertex_shader = ta_gpu_load_shader( + ta_gpu_device, + file_text_vert_slang_spv_start, + file_text_vert_slang_spv_size, + SDL_GPU_SHADERSTAGE_VERTEX, + 0, + 1 + ); + SDL_GPUShader *fragment_shader = ta_gpu_load_shader( + ta_gpu_device, + file_text_frag_slang_spv_start, + file_text_frag_slang_spv_size, + SDL_GPU_SHADERSTAGE_FRAGMENT, + 1, + 0 + ); + + SDL_GPUColorTargetDescription color_target = { + .format = ta_gpu_swapchain_format, + .blend_state = { + .src_color_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA, + .dst_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, + .color_blend_op = SDL_GPU_BLENDOP_ADD, + .src_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE, + .dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, + .alpha_blend_op = SDL_GPU_BLENDOP_ADD, + .enable_blend = true, + }, + }; + SDL_GPUGraphicsPipelineCreateInfo pipeline_info = { + .vertex_shader = vertex_shader, + .fragment_shader = fragment_shader, + .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, + .target_info = { + .num_color_targets = 1, + .color_target_descriptions = &color_target, + }, + .multisample_state = { + .sample_count = ta_gpu_sample_count, + }, + }; + ta_gpu_text_pipeline = ta_sdl_create_gpu_graphics_pipeline(ta_gpu_device, &pipeline_info); + SDL_ReleaseGPUShader(ta_gpu_device, vertex_shader); + SDL_ReleaseGPUShader(ta_gpu_device, fragment_shader); + + SDL_GPUSamplerCreateInfo sampler_info = { + .min_filter = SDL_GPU_FILTER_LINEAR, + .mag_filter = SDL_GPU_FILTER_LINEAR, + .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, + .address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, + .address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, + .address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE, + }; + ta_gpu_text_sampler = ta_sdl_create_gpu_sampler(ta_gpu_device, &sampler_info); +} + +void ta_gpu_start_frame(void) { + ta_gpu_command_buffer = ta_sdl_acquire_gpu_command_buffer(ta_gpu_device); + ta_gpu_swapchain_texture = NULL; + ta_gpu_swapchain_format = SDL_GetGPUSwapchainTextureFormat(ta_gpu_device, ta_window); + + ta_sdl_wait_and_acquire_gpu_swapchain_texture(ta_gpu_command_buffer, ta_window, &ta_gpu_swapchain_texture); + if (ta_gpu_swapchain_texture) { + ta_gpu_resize_msaa_texture(ta_gpu_swapchain_format); + } +} + +void ta_gpu_end_frame(void) { + if (ta_gpu_swapchain_texture) { + ta_gpu_upload_text(ta_gpu_command_buffer); + ta_screen_upload(ta_gpu_command_buffer); + + float red = 0.0f; + float green = 0.0f; + float blue = 0.0f; + float alpha = 1.0f; + + SDL_GPUColorTargetInfo color_target = { + .texture = ta_gpu_msaa_texture, + .load_op = SDL_GPU_LOADOP_CLEAR, + .store_op = SDL_GPU_STOREOP_RESOLVE, + .resolve_texture = ta_gpu_swapchain_texture, + .clear_color = { + red, + green, + blue, + alpha + }, + }; + + SDL_GPUDepthStencilTargetInfo depth_target = { + .texture = ta_gpu_depth_texture, + .clear_depth = 1.0f, + .load_op = SDL_GPU_LOADOP_CLEAR, + .store_op = SDL_GPU_STOREOP_DONT_CARE, + .stencil_load_op = SDL_GPU_LOADOP_DONT_CARE, + .stencil_store_op = SDL_GPU_STOREOP_DONT_CARE, + }; + SDL_GPURenderPass *render_pass = ta_sdl_begin_gpu_render_pass( + ta_gpu_command_buffer, + &color_target, + 1, + &depth_target + ); + + ta_text_render(ta_gpu_command_buffer, render_pass); + ta_screen_render(ta_gpu_command_buffer, render_pass); + SDL_EndGPURenderPass(render_pass); + } + + ta_sdl_submit_gpu_command_buffer(ta_gpu_command_buffer); +} |