summaryrefslogtreecommitdiff
path: root/src/gpu.c
diff options
context:
space:
mode:
authorConnor Thomson <blumatrikz@gmail.com>2026-09-08 18:27:39 -0700
committerConnor Thomson <blumatrikz@gmail.com>2026-09-08 18:27:39 -0700
commitf1ddc12b68b4e4c8087962de25260470e6df2bea (patch)
tree7d0440a6402a9b0ef75ded23fa64b68534255bba /src/gpu.c
parent6025860a61386bf767b29c3ec5fd0d31285f1056 (diff)
Add tuxanci2 files
Diffstat (limited to 'src/gpu.c')
-rw-r--r--src/gpu.c209
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);
+}