summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--sdl_gpu_test.c202
1 files changed, 119 insertions, 83 deletions
diff --git a/sdl_gpu_test.c b/sdl_gpu_test.c
index d77e137..8bc6b73 100644
--- a/sdl_gpu_test.c
+++ b/sdl_gpu_test.c
@@ -1,8 +1,9 @@
-/* sdl_gpu_test.c -- -lSDL3 */
+/* sdl_gpu_test.c -- -lSDL3 -lm */
 
 #define SDL_MAIN_USE_CALLBACKS 1
 #include <SDL3/SDL_main.h>
 #include <SDL3/SDL_gpu.h>
+#include <math.h>
 #include <stdio.h>
 #include <err.h>
 
@@ -12,25 +13,36 @@ SDL_GPUGraphicsPipeline *pipeline_fill;
 SDL_GPUBuffer *buf_vert;
 SDL_GPUTransferBuffer *buf_vert_xfer;
 
-float vertices[][2] = {
-	{ 0.5, -0.5 },
-	{ 0.5, 0.5 },
-	{ -0.5, -0.5 },
+typedef struct {
+	float x, y;
+	float u, v;
+} Vertex;
+
+Vertex vertices[] = {
+	{ -1, -1,  0, 0, },
+	{ 0, -1,  1, 0, },
+	{ 0, 0,  1, 1, },
+
+	{ -1, -1,  0, 0, },
+	{ -1, 0,  0, 1, },
+	{ 0, 0,  1, 1, },
+
+	{ 0, 0,  0, 0, },
+	{ 1, 0,  1, 0, },
+	{ 1, 1,  1, 1, },
+
+	{ 0, 0,  0, 0, },
+	{ 0, 1,  0, 1, },
+	{ 1, 1,  1, 1, },
 
-	{ -0.5, -0.5 },
-	{ -0.5, 0.5 },
-	{ 0.5, 0.5 },
 };
 
-SDL_GPUShader* load_shader(
-		SDL_GPUDevice* dev, 
-		const char *path, 
-		SDL_GPUShaderStage stage, 
-		Uint32 samplers, 
-		Uint32 uniformbufs, 
-		Uint32 storagebufs, 
-		Uint32 storagetextures)
-{
+typedef struct {
+	SDL_GPUShaderStage stage;
+	Uint32 n_sampler, n_uniformbuf, n_storagebuf, n_storagetex;
+} ShaderDesc;
+
+SDL_GPUShader* load_shader(SDL_GPUDevice* dev, const char *path, ShaderDesc *desc) {
 	size_t code_size;
 	void *code = SDL_LoadFile(path, &code_size);
 	if (!code) {
@@ -38,24 +50,19 @@ SDL_GPUShader* load_shader(
 		return NULL;
 	}
 
-	SDL_GPUShaderCreateInfo info = {
+	SDL_GPUShader *sh = SDL_CreateGPUShader(dev, &(SDL_GPUShaderCreateInfo) {
 		.code = code,
 		.code_size = code_size,
 		.entrypoint = "main",
 		.format = SDL_GPU_SHADERFORMAT_SPIRV,
-		.stage = stage,
-		.num_samplers = samplers,
-		.num_uniform_buffers = uniformbufs,
-		.num_storage_buffers = storagebufs,
-		.num_storage_textures = storagetextures
-	};
-
-	SDL_GPUShader *sh = SDL_CreateGPUShader(dev, &info);
-	if (!sh) {
-		fprintf(stderr, "failed to create shader: %s\n", SDL_GetError());
-		return NULL;
-	}
-
+		.stage = desc->stage,
+		.num_samplers = desc->n_sampler,
+		.num_uniform_buffers = desc->n_uniformbuf,
+		.num_storage_buffers = desc->n_storagebuf,
+		.num_storage_textures = desc->n_storagetex
+	});
+
+	if (!sh) return NULL;
 	SDL_free(code);
 	return sh;
 }
@@ -73,25 +80,30 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
 	CHECK(gpudev, "failed to create gpu device");
 	CHECK(SDL_ClaimWindowForGPUDevice(gpudev, win), "failed to claim window");
 
-	SDL_GPUShader *shader_vert = load_shader(gpudev, "shader/tri.vert.spv", SDL_GPU_SHADERSTAGE_VERTEX, 0, 0, 0, 0);
+	SDL_GPUShader *shader_vert = load_shader(gpudev, "shader/tri.vert.spv", &(ShaderDesc) {
+			.stage = SDL_GPU_SHADERSTAGE_VERTEX,
+			.n_uniformbuf = 1
+		});
 	CHECK(shader_vert, "load vertex shader");
-	SDL_GPUShader *shader_frag = load_shader(gpudev, "shader/tri.frag.spv", SDL_GPU_SHADERSTAGE_FRAGMENT, 0, 0, 0, 0);
+	SDL_GPUShader *shader_frag = load_shader(gpudev, "shader/tri.frag.spv", &(ShaderDesc) { SDL_GPU_SHADERSTAGE_FRAGMENT });
 	CHECK(shader_frag, "load fragment shader");
 
-	SDL_GPUBufferCreateInfo buf_desc = {
+	buf_vert = SDL_CreateGPUBuffer(gpudev, &(SDL_GPUBufferCreateInfo) {
 		.usage = SDL_GPU_BUFFERUSAGE_VERTEX,
 		.size = sizeof(vertices),
 		.props = 0
-	};
-	buf_vert = SDL_CreateGPUBuffer(gpudev, &buf_desc);
+	});
 	CHECK(buf_vert, "vertex buffer");
 
-	SDL_GPUTransferBufferCreateInfo buf_xfer_desc = {
-		.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
-		.size = sizeof(buf_vert),
-		.props = 0
-	};
-	buf_vert_xfer = SDL_CreateGPUTransferBuffer(gpudev, &buf_xfer_desc);
+	buf_vert_xfer = SDL_CreateGPUTransferBuffer(
+		gpudev,
+		&(SDL_GPUTransferBufferCreateInfo) {
+			.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
+			.size = sizeof(vertices),
+			.props = 0
+		}
+	);
+
 	CHECK(buf_vert_xfer, "vertex transfer buffer");
 
 	void *map = SDL_MapGPUTransferBuffer(gpudev, buf_vert_xfer, false);
@@ -103,27 +115,38 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
 	SDL_GPUCopyPass *copypass = SDL_BeginGPUCopyPass(cmdbuf);
 	CHECK(copypass, "gpu copy pass");
 
-	SDL_GPUTransferBufferLocation src = {
-		.transfer_buffer = buf_vert_xfer,
-		.offset = 0
-	};
-
-	SDL_GPUBufferRegion dest = {
-		.buffer = buf_vert,
-		.offset = 0,
-		.size = sizeof(vertices)
-	};
+	SDL_UploadToGPUBuffer(
+		copypass,
+		&(SDL_GPUTransferBufferLocation) {
+			.transfer_buffer = buf_vert_xfer,
+			.offset = 0
+		},
+		&(SDL_GPUBufferRegion) {
+			.buffer = buf_vert,
+			.offset = 0,
+			.size = sizeof(vertices)
+		},
+		false
+	);
 
-	SDL_UploadToGPUBuffer(copypass, &src, &dest, false);
 	SDL_EndGPUCopyPass(copypass);
 	SDL_SubmitGPUCommandBuffer(cmdbuf);
 	SDL_ReleaseGPUTransferBuffer(gpudev, buf_vert_xfer);
 
-	SDL_GPUGraphicsPipelineCreateInfo pipeline_info = {
+	pipeline_fill = SDL_CreateGPUGraphicsPipeline(gpudev, &(SDL_GPUGraphicsPipelineCreateInfo) {
 		.target_info = {
 			.num_color_targets = 1,
 			.color_target_descriptions = (SDL_GPUColorTargetDescription[]) {{
-				.format = SDL_GetGPUSwapchainTextureFormat(gpudev, win)
+				.format = SDL_GetGPUSwapchainTextureFormat(gpudev, win),
+			       .blend_state = {
+				       .enable_blend = true,
+				       .color_blend_op = SDL_GPU_BLENDOP_ADD,
+				       .alpha_blend_op = SDL_GPU_BLENDOP_ADD,
+				       .src_color_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA,
+				       .dst_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
+				       .src_alpha_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA,
+				       .dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
+			       }
 			}},
 		},
 		.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
@@ -133,25 +156,32 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
 			.num_vertex_buffers = 1,
 			.vertex_buffer_descriptions = &(SDL_GPUVertexBufferDescription) {
 				.slot = 0,
-				.pitch = sizeof(float) * 2,
+				.pitch = sizeof(Vertex),
 				.input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX,
 				.instance_step_rate = 0,
 			},
-			.num_vertex_attributes = 1,
+			.num_vertex_attributes = 2,
 			.vertex_attributes = (SDL_GPUVertexAttribute[]) {
 				{
 					.location = 0,
 					.buffer_slot = 0,
 					.format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2,
 					.offset = 0
+				},
+				{
+					.location = 1,
+					.buffer_slot = 0,
+					.format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2,
+					.offset = sizeof(float) * 2
 				}
 			}
 		},
+		.rasterizer_state = {
+			.fill_mode = SDL_GPU_FILLMODE_FILL
+		},
 		.props = 0
-	};
+	});
 
-	pipeline_info.rasterizer_state.fill_mode = SDL_GPU_FILLMODE_FILL;
-	pipeline_fill = SDL_CreateGPUGraphicsPipeline(gpudev, &pipeline_info);
 	CHECK(pipeline_fill, "graphics pipeline");
 
 	SDL_ReleaseGPUShader(gpudev, shader_frag);
@@ -176,33 +206,39 @@ SDL_AppResult SDL_AppIterate(void *appstate) {
 	(void)appstate;
 
 	SDL_GPUCommandBuffer *cmdbuf = SDL_AcquireGPUCommandBuffer(gpudev);
-	if (!cmdbuf) {
-		fprintf(stderr, "failed to acquire GPU command buffer: %s\n", SDL_GetError());
-		return SDL_APP_FAILURE;
-	}
+	CHECK(cmdbuf, "gpu cmd buffer acquisition");
 
 	SDL_GPUTexture *swapchain;
-	if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, win, &swapchain, NULL, NULL)) {
-		fprintf(stderr, "failed to acquire swapchain texture: %s\n", SDL_GetError());
-		return SDL_APP_FAILURE;
-	}
-
-	if (!swapchain) {
-		fprintf(stderr, "null swapchain texture: %s\n", SDL_GetError());
-		SDL_SubmitGPUCommandBuffer(cmdbuf);
-		return SDL_APP_FAILURE;
-	}
-
-        SDL_GPUColorTargetInfo color_target_info = { 0 };
-        color_target_info.texture = swapchain;
-        color_target_info.clear_color = (SDL_FColor) { 0, 0, 0, 1 }; 
-        color_target_info.load_op = SDL_GPU_LOADOP_CLEAR;
-        color_target_info.store_op = SDL_GPU_STOREOP_STORE;
-
-	SDL_GPURenderPass *render_pass = SDL_BeginGPURenderPass(cmdbuf, &color_target_info, 1, NULL);
+	Uint32 swc_width, swc_height;
+	CHECK(SDL_WaitAndAcquireGPUSwapchainTexture(cmdbuf, win, &swapchain, &swc_width, &swc_height), "swapchain texture acquisition");
+	CHECK(swapchain, "nil swapchain texture");
+
+	float how = (float)swc_height / (float)swc_width;
+	float woh = (float)swc_width / (float)swc_height;
+	float scale = (32 * 2) / fminf(swc_width, swc_height);
+	float scale_x = (swc_height < swc_width ? how : 1) * scale;
+	float scale_y = (swc_height < swc_width ? 1 : woh) * scale;
+	float cam_mat[4][4] = {
+		{ scale_x, 0, 0, 0, },
+		{ 0, scale_y, 0, 0, },
+		{ 0, 0, 1, 0, },
+		{ 0, 0, 0, 1, },
+	};
+	SDL_PushGPUVertexUniformData(cmdbuf, 0, &cam_mat, sizeof(cam_mat));
+	SDL_GPURenderPass *render_pass = SDL_BeginGPURenderPass(
+		cmdbuf,
+		&(SDL_GPUColorTargetInfo) {
+			.texture = swapchain,
+			.clear_color = { 0, 0, 0, 1 },
+			.load_op = SDL_GPU_LOADOP_CLEAR,
+			.store_op = SDL_GPU_STOREOP_STORE,
+		},
+		1,
+		NULL
+	);
         SDL_BindGPUGraphicsPipeline(render_pass, pipeline_fill);
 	SDL_BindGPUVertexBuffers(render_pass, 0, &(SDL_GPUBufferBinding) { .buffer = buf_vert, .offset = 0 }, 1);
-        SDL_DrawGPUPrimitives(render_pass, sizeof(vertices) / (sizeof(float)*2), 1, 0, 0);
+        SDL_DrawGPUPrimitives(render_pass, sizeof(vertices) / sizeof(Vertex), 1, 0, 0);
         SDL_EndGPURenderPass(render_pass);
 
 	SDL_SubmitGPUCommandBuffer(cmdbuf);