summaryrefslogtreecommitdiff
path: root/src/contrib/SDL-3.2.20/test/testgpu_spinning_cube.c
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-08-30 16:53:58 -0700
committer3gg <3gg@shellblade.net>2025-08-30 16:53:58 -0700
commit6aaedb813fa11ba0679c3051bc2eb28646b9506c (patch)
tree34acbfc9840e02cb4753e6306ea7ce978bf8b58e /src/contrib/SDL-3.2.20/test/testgpu_spinning_cube.c
parent8f228ade99dd3d4c8da9b78ade1815c9adf85c8f (diff)
Update to SDL3
Diffstat (limited to 'src/contrib/SDL-3.2.20/test/testgpu_spinning_cube.c')
-rw-r--r--src/contrib/SDL-3.2.20/test/testgpu_spinning_cube.c761
1 files changed, 761 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/test/testgpu_spinning_cube.c b/src/contrib/SDL-3.2.20/test/testgpu_spinning_cube.c
new file mode 100644
index 0000000..0eeb034
--- /dev/null
+++ b/src/contrib/SDL-3.2.20/test/testgpu_spinning_cube.c
@@ -0,0 +1,761 @@
1/*
2 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely.
11*/
12
13#include <stdlib.h>
14
15#ifdef __EMSCRIPTEN__
16#include <emscripten/emscripten.h>
17#endif
18
19#include <SDL3/SDL_test_common.h>
20#include <SDL3/SDL_gpu.h>
21#include <SDL3/SDL_main.h>
22
23/* Regenerate the shaders with testgpu/build-shaders.sh */
24#include "testgpu/testgpu_spirv.h"
25#include "testgpu/testgpu_dxil.h"
26#include "testgpu/testgpu_metallib.h"
27
28#define TESTGPU_SUPPORTED_FORMATS (SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXBC | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_METALLIB)
29
30#define CHECK_CREATE(var, thing) { if (!(var)) { SDL_Log("Failed to create %s: %s", thing, SDL_GetError()); quit(2); } }
31
32static Uint32 frames = 0;
33
34typedef struct RenderState
35{
36 SDL_GPUBuffer *buf_vertex;
37 SDL_GPUGraphicsPipeline *pipeline;
38 SDL_GPUSampleCount sample_count;
39} RenderState;
40
41typedef struct WindowState
42{
43 int angle_x, angle_y, angle_z;
44 SDL_GPUTexture *tex_depth, *tex_msaa, *tex_resolve;
45 Uint32 prev_drawablew, prev_drawableh;
46} WindowState;
47
48static SDL_GPUDevice *gpu_device = NULL;
49static RenderState render_state;
50static SDLTest_CommonState *state = NULL;
51static WindowState *window_states = NULL;
52
53static void shutdownGPU(void)
54{
55 if (window_states) {
56 int i;
57 for (i = 0; i < state->num_windows; i++) {
58 WindowState *winstate = &window_states[i];
59 SDL_ReleaseGPUTexture(gpu_device, winstate->tex_depth);
60 SDL_ReleaseGPUTexture(gpu_device, winstate->tex_msaa);
61 SDL_ReleaseGPUTexture(gpu_device, winstate->tex_resolve);
62 SDL_ReleaseWindowFromGPUDevice(gpu_device, state->windows[i]);
63 }
64 SDL_free(window_states);
65 window_states = NULL;
66 }
67
68 SDL_ReleaseGPUBuffer(gpu_device, render_state.buf_vertex);
69 SDL_ReleaseGPUGraphicsPipeline(gpu_device, render_state.pipeline);
70 SDL_DestroyGPUDevice(gpu_device);
71
72 SDL_zero(render_state);
73 gpu_device = NULL;
74}
75
76
77/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
78static void
79quit(int rc)
80{
81 shutdownGPU();
82 SDLTest_CommonQuit(state);
83 exit(rc);
84}
85
86/*
87 * Simulates desktop's glRotatef. The matrix is returned in column-major
88 * order.
89 */
90static void
91rotate_matrix(float angle, float x, float y, float z, float *r)
92{
93 float radians, c, s, c1, u[3], length;
94 int i, j;
95
96 radians = angle * SDL_PI_F / 180.0f;
97
98 c = SDL_cosf(radians);
99 s = SDL_sinf(radians);
100
101 c1 = 1.0f - SDL_cosf(radians);
102
103 length = (float)SDL_sqrt(x * x + y * y + z * z);
104
105 u[0] = x / length;
106 u[1] = y / length;
107 u[2] = z / length;
108
109 for (i = 0; i < 16; i++) {
110 r[i] = 0.0;
111 }
112
113 r[15] = 1.0;
114
115 for (i = 0; i < 3; i++) {
116 r[i * 4 + (i + 1) % 3] = u[(i + 2) % 3] * s;
117 r[i * 4 + (i + 2) % 3] = -u[(i + 1) % 3] * s;
118 }
119
120 for (i = 0; i < 3; i++) {
121 for (j = 0; j < 3; j++) {
122 r[i * 4 + j] += c1 * u[i] * u[j] + (i == j ? c : 0.0f);
123 }
124 }
125}
126
127/*
128 * Simulates gluPerspectiveMatrix
129 */
130static void
131perspective_matrix(float fovy, float aspect, float znear, float zfar, float *r)
132{
133 int i;
134 float f;
135
136 f = 1.0f/SDL_tanf(fovy * 0.5f);
137
138 for (i = 0; i < 16; i++) {
139 r[i] = 0.0;
140 }
141
142 r[0] = f / aspect;
143 r[5] = f;
144 r[10] = (znear + zfar) / (znear - zfar);
145 r[11] = -1.0f;
146 r[14] = (2.0f * znear * zfar) / (znear - zfar);
147 r[15] = 0.0f;
148}
149
150/*
151 * Multiplies lhs by rhs and writes out to r. All matrices are 4x4 and column
152 * major. In-place multiplication is supported.
153 */
154static void
155multiply_matrix(const float *lhs, const float *rhs, float *r)
156{
157 int i, j, k;
158 float tmp[16];
159
160 for (i = 0; i < 4; i++) {
161 for (j = 0; j < 4; j++) {
162 tmp[j * 4 + i] = 0.0;
163
164 for (k = 0; k < 4; k++) {
165 tmp[j * 4 + i] += lhs[k * 4 + i] * rhs[j * 4 + k];
166 }
167 }
168 }
169
170 for (i = 0; i < 16; i++) {
171 r[i] = tmp[i];
172 }
173}
174
175typedef struct VertexData
176{
177 float x, y, z; /* 3D data. Vertex range -0.5..0.5 in all axes. Z -0.5 is near, 0.5 is far. */
178 float red, green, blue; /* intensity 0 to 1 (alpha is always 1). */
179} VertexData;
180
181static const VertexData vertex_data[] = {
182 /* Front face. */
183 /* Bottom left */
184 { -0.5, 0.5, -0.5, 1.0, 0.0, 0.0 }, /* red */
185 { 0.5, -0.5, -0.5, 0.0, 0.0, 1.0 }, /* blue */
186 { -0.5, -0.5, -0.5, 0.0, 1.0, 0.0 }, /* green */
187
188 /* Top right */
189 { -0.5, 0.5, -0.5, 1.0, 0.0, 0.0 }, /* red */
190 { 0.5, 0.5, -0.5, 1.0, 1.0, 0.0 }, /* yellow */
191 { 0.5, -0.5, -0.5, 0.0, 0.0, 1.0 }, /* blue */
192
193 /* Left face */
194 /* Bottom left */
195 { -0.5, 0.5, 0.5, 1.0, 1.0, 1.0 }, /* white */
196 { -0.5, -0.5, -0.5, 0.0, 1.0, 0.0 }, /* green */
197 { -0.5, -0.5, 0.5, 0.0, 1.0, 1.0 }, /* cyan */
198
199 /* Top right */
200 { -0.5, 0.5, 0.5, 1.0, 1.0, 1.0 }, /* white */
201 { -0.5, 0.5, -0.5, 1.0, 0.0, 0.0 }, /* red */
202 { -0.5, -0.5, -0.5, 0.0, 1.0, 0.0 }, /* green */
203
204 /* Top face */
205 /* Bottom left */
206 { -0.5, 0.5, 0.5, 1.0, 1.0, 1.0 }, /* white */
207 { 0.5, 0.5, -0.5, 1.0, 1.0, 0.0 }, /* yellow */
208 { -0.5, 0.5, -0.5, 1.0, 0.0, 0.0 }, /* red */
209
210 /* Top right */
211 { -0.5, 0.5, 0.5, 1.0, 1.0, 1.0 }, /* white */
212 { 0.5, 0.5, 0.5, 0.0, 0.0, 0.0 }, /* black */
213 { 0.5, 0.5, -0.5, 1.0, 1.0, 0.0 }, /* yellow */
214
215 /* Right face */
216 /* Bottom left */
217 { 0.5, 0.5, -0.5, 1.0, 1.0, 0.0 }, /* yellow */
218 { 0.5, -0.5, 0.5, 1.0, 0.0, 1.0 }, /* magenta */
219 { 0.5, -0.5, -0.5, 0.0, 0.0, 1.0 }, /* blue */
220
221 /* Top right */
222 { 0.5, 0.5, -0.5, 1.0, 1.0, 0.0 }, /* yellow */
223 { 0.5, 0.5, 0.5, 0.0, 0.0, 0.0 }, /* black */
224 { 0.5, -0.5, 0.5, 1.0, 0.0, 1.0 }, /* magenta */
225
226 /* Back face */
227 /* Bottom left */
228 { 0.5, 0.5, 0.5, 0.0, 0.0, 0.0 }, /* black */
229 { -0.5, -0.5, 0.5, 0.0, 1.0, 1.0 }, /* cyan */
230 { 0.5, -0.5, 0.5, 1.0, 0.0, 1.0 }, /* magenta */
231
232 /* Top right */
233 { 0.5, 0.5, 0.5, 0.0, 0.0, 0.0 }, /* black */
234 { -0.5, 0.5, 0.5, 1.0, 1.0, 1.0 }, /* white */
235 { -0.5, -0.5, 0.5, 0.0, 1.0, 1.0 }, /* cyan */
236
237 /* Bottom face */
238 /* Bottom left */
239 { -0.5, -0.5, -0.5, 0.0, 1.0, 0.0 }, /* green */
240 { 0.5, -0.5, 0.5, 1.0, 0.0, 1.0 }, /* magenta */
241 { -0.5, -0.5, 0.5, 0.0, 1.0, 1.0 }, /* cyan */
242
243 /* Top right */
244 { -0.5, -0.5, -0.5, 0.0, 1.0, 0.0 }, /* green */
245 { 0.5, -0.5, -0.5, 0.0, 0.0, 1.0 }, /* blue */
246 { 0.5, -0.5, 0.5, 1.0, 0.0, 1.0 } /* magenta */
247};
248
249static SDL_GPUTexture*
250CreateDepthTexture(Uint32 drawablew, Uint32 drawableh)
251{
252 SDL_GPUTextureCreateInfo createinfo;
253 SDL_GPUTexture *result;
254
255 createinfo.type = SDL_GPU_TEXTURETYPE_2D;
256 createinfo.format = SDL_GPU_TEXTUREFORMAT_D16_UNORM;
257 createinfo.width = drawablew;
258 createinfo.height = drawableh;
259 createinfo.layer_count_or_depth = 1;
260 createinfo.num_levels = 1;
261 createinfo.sample_count = render_state.sample_count;
262 createinfo.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
263 createinfo.props = 0;
264
265 result = SDL_CreateGPUTexture(gpu_device, &createinfo);
266 CHECK_CREATE(result, "Depth Texture")
267
268 return result;
269}
270
271static SDL_GPUTexture*
272CreateMSAATexture(Uint32 drawablew, Uint32 drawableh)
273{
274 SDL_GPUTextureCreateInfo createinfo;
275 SDL_GPUTexture *result;
276
277 if (render_state.sample_count == SDL_GPU_SAMPLECOUNT_1) {
278 return NULL;
279 }
280
281 createinfo.type = SDL_GPU_TEXTURETYPE_2D;
282 createinfo.format = SDL_GetGPUSwapchainTextureFormat(gpu_device, state->windows[0]);
283 createinfo.width = drawablew;
284 createinfo.height = drawableh;
285 createinfo.layer_count_or_depth = 1;
286 createinfo.num_levels = 1;
287 createinfo.sample_count = render_state.sample_count;
288 createinfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
289 createinfo.props = 0;
290
291 result = SDL_CreateGPUTexture(gpu_device, &createinfo);
292 CHECK_CREATE(result, "MSAA Texture")
293
294 return result;
295}
296
297static SDL_GPUTexture *
298CreateResolveTexture(Uint32 drawablew, Uint32 drawableh)
299{
300 SDL_GPUTextureCreateInfo createinfo;
301 SDL_GPUTexture *result;
302
303 if (render_state.sample_count == SDL_GPU_SAMPLECOUNT_1) {
304 return NULL;
305 }
306
307 createinfo.type = SDL_GPU_TEXTURETYPE_2D;
308 createinfo.format = SDL_GetGPUSwapchainTextureFormat(gpu_device, state->windows[0]);
309 createinfo.width = drawablew;
310 createinfo.height = drawableh;
311 createinfo.layer_count_or_depth = 1;
312 createinfo.num_levels = 1;
313 createinfo.sample_count = SDL_GPU_SAMPLECOUNT_1;
314 createinfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER;
315 createinfo.props = 0;
316
317 result = SDL_CreateGPUTexture(gpu_device, &createinfo);
318 CHECK_CREATE(result, "Resolve Texture")
319
320 return result;
321}
322
323static void
324Render(SDL_Window *window, const int windownum)
325{
326 WindowState *winstate = &window_states[windownum];
327 SDL_GPUTexture *swapchainTexture;
328 SDL_GPUColorTargetInfo color_target;
329 SDL_GPUDepthStencilTargetInfo depth_target;
330 float matrix_rotate[16], matrix_modelview[16], matrix_perspective[16], matrix_final[16];
331 SDL_GPUCommandBuffer *cmd;
332 SDL_GPURenderPass *pass;
333 SDL_GPUBufferBinding vertex_binding;
334 SDL_GPUBlitInfo blit_info;
335 Uint32 drawablew, drawableh;
336
337 /* Acquire the swapchain texture */
338
339 cmd = SDL_AcquireGPUCommandBuffer(gpu_device);
340 if (!cmd) {
341 SDL_Log("Failed to acquire command buffer :%s", SDL_GetError());
342 quit(2);
343 }
344 if (!SDL_WaitAndAcquireGPUSwapchainTexture(cmd, state->windows[windownum], &swapchainTexture, &drawablew, &drawableh)) {
345 SDL_Log("Failed to acquire swapchain texture: %s", SDL_GetError());
346 quit(2);
347 }
348
349 if (swapchainTexture == NULL) {
350 /* Swapchain is unavailable, cancel work */
351 SDL_CancelGPUCommandBuffer(cmd);
352 return;
353 }
354
355 /*
356 * Do some rotation with Euler angles. It is not a fixed axis as
357 * quaternions would be, but the effect is cool.
358 */
359 rotate_matrix((float)winstate->angle_x, 1.0f, 0.0f, 0.0f, matrix_modelview);
360 rotate_matrix((float)winstate->angle_y, 0.0f, 1.0f, 0.0f, matrix_rotate);
361
362 multiply_matrix(matrix_rotate, matrix_modelview, matrix_modelview);
363
364 rotate_matrix((float)winstate->angle_z, 0.0f, 1.0f, 0.0f, matrix_rotate);
365
366 multiply_matrix(matrix_rotate, matrix_modelview, matrix_modelview);
367
368 /* Pull the camera back from the cube */
369 matrix_modelview[14] -= 2.5f;
370
371 perspective_matrix(45.0f, (float)drawablew/drawableh, 0.01f, 100.0f, matrix_perspective);
372 multiply_matrix(matrix_perspective, matrix_modelview, (float*) &matrix_final);
373
374 winstate->angle_x += 3;
375 winstate->angle_y += 2;
376 winstate->angle_z += 1;
377
378 if(winstate->angle_x >= 360) winstate->angle_x -= 360;
379 if(winstate->angle_x < 0) winstate->angle_x += 360;
380 if(winstate->angle_y >= 360) winstate->angle_y -= 360;
381 if(winstate->angle_y < 0) winstate->angle_y += 360;
382 if(winstate->angle_z >= 360) winstate->angle_z -= 360;
383 if(winstate->angle_z < 0) winstate->angle_z += 360;
384
385 /* Resize the depth buffer if the window size changed */
386
387 if (winstate->prev_drawablew != drawablew || winstate->prev_drawableh != drawableh) {
388 SDL_ReleaseGPUTexture(gpu_device, winstate->tex_depth);
389 SDL_ReleaseGPUTexture(gpu_device, winstate->tex_msaa);
390 SDL_ReleaseGPUTexture(gpu_device, winstate->tex_resolve);
391 winstate->tex_depth = CreateDepthTexture(drawablew, drawableh);
392 winstate->tex_msaa = CreateMSAATexture(drawablew, drawableh);
393 winstate->tex_resolve = CreateResolveTexture(drawablew, drawableh);
394 }
395 winstate->prev_drawablew = drawablew;
396 winstate->prev_drawableh = drawableh;
397
398 /* Set up the pass */
399
400 SDL_zero(color_target);
401 color_target.clear_color.a = 1.0f;
402 if (winstate->tex_msaa) {
403 color_target.load_op = SDL_GPU_LOADOP_CLEAR;
404 color_target.store_op = SDL_GPU_STOREOP_RESOLVE;
405 color_target.texture = winstate->tex_msaa;
406 color_target.resolve_texture = winstate->tex_resolve;
407 color_target.cycle = true;
408 color_target.cycle_resolve_texture = true;
409 } else {
410 color_target.load_op = SDL_GPU_LOADOP_CLEAR;
411 color_target.store_op = SDL_GPU_STOREOP_STORE;
412 color_target.texture = swapchainTexture;
413 }
414
415 SDL_zero(depth_target);
416 depth_target.clear_depth = 1.0f;
417 depth_target.load_op = SDL_GPU_LOADOP_CLEAR;
418 depth_target.store_op = SDL_GPU_STOREOP_DONT_CARE;
419 depth_target.stencil_load_op = SDL_GPU_LOADOP_DONT_CARE;
420 depth_target.stencil_store_op = SDL_GPU_STOREOP_DONT_CARE;
421 depth_target.texture = winstate->tex_depth;
422 depth_target.cycle = true;
423
424 /* Set up the bindings */
425
426 vertex_binding.buffer = render_state.buf_vertex;
427 vertex_binding.offset = 0;
428
429 /* Draw the cube! */
430
431 SDL_PushGPUVertexUniformData(cmd, 0, matrix_final, sizeof(matrix_final));
432
433 pass = SDL_BeginGPURenderPass(cmd, &color_target, 1, &depth_target);
434 SDL_BindGPUGraphicsPipeline(pass, render_state.pipeline);
435 SDL_BindGPUVertexBuffers(pass, 0, &vertex_binding, 1);
436 SDL_DrawGPUPrimitives(pass, 36, 1, 0, 0);
437 SDL_EndGPURenderPass(pass);
438
439 /* Blit MSAA resolve target to swapchain, if needed */
440 if (render_state.sample_count > SDL_GPU_SAMPLECOUNT_1) {
441 SDL_zero(blit_info);
442 blit_info.source.texture = winstate->tex_resolve;
443 blit_info.source.w = drawablew;
444 blit_info.source.h = drawableh;
445
446 blit_info.destination.texture = swapchainTexture;
447 blit_info.destination.w = drawablew;
448 blit_info.destination.h = drawableh;
449
450 blit_info.load_op = SDL_GPU_LOADOP_DONT_CARE;
451 blit_info.filter = SDL_GPU_FILTER_LINEAR;
452
453 SDL_BlitGPUTexture(cmd, &blit_info);
454 }
455
456 /* Submit the command buffer! */
457 SDL_SubmitGPUCommandBuffer(cmd);
458
459 ++frames;
460}
461
462static SDL_GPUShader*
463load_shader(bool is_vertex)
464{
465 SDL_GPUShaderCreateInfo createinfo;
466 createinfo.num_samplers = 0;
467 createinfo.num_storage_buffers = 0;
468 createinfo.num_storage_textures = 0;
469 createinfo.num_uniform_buffers = is_vertex ? 1 : 0;
470 createinfo.props = 0;
471
472 SDL_GPUShaderFormat format = SDL_GetGPUShaderFormats(gpu_device);
473 if (format & SDL_GPU_SHADERFORMAT_DXIL) {
474 createinfo.format = SDL_GPU_SHADERFORMAT_DXIL;
475 createinfo.code = is_vertex ? D3D12_CubeVert : D3D12_CubeFrag;
476 createinfo.code_size = is_vertex ? SDL_arraysize(D3D12_CubeVert) : SDL_arraysize(D3D12_CubeFrag);
477 createinfo.entrypoint = is_vertex ? "VSMain" : "PSMain";
478 } else if (format & SDL_GPU_SHADERFORMAT_METALLIB) {
479 createinfo.format = SDL_GPU_SHADERFORMAT_METALLIB;
480 createinfo.code = is_vertex ? cube_vert_metallib : cube_frag_metallib;
481 createinfo.code_size = is_vertex ? cube_vert_metallib_len : cube_frag_metallib_len;
482 createinfo.entrypoint = is_vertex ? "vs_main" : "fs_main";
483 } else {
484 createinfo.format = SDL_GPU_SHADERFORMAT_SPIRV;
485 createinfo.code = is_vertex ? cube_vert_spv : cube_frag_spv;
486 createinfo.code_size = is_vertex ? cube_vert_spv_len : cube_frag_spv_len;
487 createinfo.entrypoint = "main";
488 }
489
490 createinfo.stage = is_vertex ? SDL_GPU_SHADERSTAGE_VERTEX : SDL_GPU_SHADERSTAGE_FRAGMENT;
491 return SDL_CreateGPUShader(gpu_device, &createinfo);
492}
493
494static void
495init_render_state(int msaa)
496{
497 SDL_GPUCommandBuffer *cmd;
498 SDL_GPUTransferBuffer *buf_transfer;
499 void *map;
500 SDL_GPUTransferBufferLocation buf_location;
501 SDL_GPUBufferRegion dst_region;
502 SDL_GPUCopyPass *copy_pass;
503 SDL_GPUBufferCreateInfo buffer_desc;
504 SDL_GPUTransferBufferCreateInfo transfer_buffer_desc;
505 SDL_GPUGraphicsPipelineCreateInfo pipelinedesc;
506 SDL_GPUColorTargetDescription color_target_desc;
507 Uint32 drawablew, drawableh;
508 SDL_GPUVertexAttribute vertex_attributes[2];
509 SDL_GPUVertexBufferDescription vertex_buffer_desc;
510 SDL_GPUShader *vertex_shader;
511 SDL_GPUShader *fragment_shader;
512 int i;
513
514 gpu_device = SDL_CreateGPUDevice(
515 TESTGPU_SUPPORTED_FORMATS,
516 true,
517 state->gpudriver
518 );
519 CHECK_CREATE(gpu_device, "GPU device");
520
521 /* Claim the windows */
522
523 for (i = 0; i < state->num_windows; i++) {
524 SDL_ClaimWindowForGPUDevice(
525 gpu_device,
526 state->windows[i]
527 );
528 }
529
530 /* Create shaders */
531
532 vertex_shader = load_shader(true);
533 CHECK_CREATE(vertex_shader, "Vertex Shader")
534 fragment_shader = load_shader(false);
535 CHECK_CREATE(fragment_shader, "Fragment Shader")
536
537 /* Create buffers */
538
539 buffer_desc.usage = SDL_GPU_BUFFERUSAGE_VERTEX;
540 buffer_desc.size = sizeof(vertex_data);
541 buffer_desc.props = SDL_CreateProperties();
542 SDL_SetStringProperty(buffer_desc.props, SDL_PROP_GPU_BUFFER_CREATE_NAME_STRING, "космонавт");
543 render_state.buf_vertex = SDL_CreateGPUBuffer(
544 gpu_device,
545 &buffer_desc
546 );
547 CHECK_CREATE(render_state.buf_vertex, "Static vertex buffer")
548 SDL_DestroyProperties(buffer_desc.props);
549
550 transfer_buffer_desc.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
551 transfer_buffer_desc.size = sizeof(vertex_data);
552 transfer_buffer_desc.props = SDL_CreateProperties();
553 SDL_SetStringProperty(transfer_buffer_desc.props, SDL_PROP_GPU_TRANSFERBUFFER_CREATE_NAME_STRING, "Transfer Buffer");
554 buf_transfer = SDL_CreateGPUTransferBuffer(
555 gpu_device,
556 &transfer_buffer_desc
557 );
558 CHECK_CREATE(buf_transfer, "Vertex transfer buffer")
559 SDL_DestroyProperties(transfer_buffer_desc.props);
560
561 /* We just need to upload the static data once. */
562 map = SDL_MapGPUTransferBuffer(gpu_device, buf_transfer, false);
563 SDL_memcpy(map, vertex_data, sizeof(vertex_data));
564 SDL_UnmapGPUTransferBuffer(gpu_device, buf_transfer);
565
566 cmd = SDL_AcquireGPUCommandBuffer(gpu_device);
567 copy_pass = SDL_BeginGPUCopyPass(cmd);
568 buf_location.transfer_buffer = buf_transfer;
569 buf_location.offset = 0;
570 dst_region.buffer = render_state.buf_vertex;
571 dst_region.offset = 0;
572 dst_region.size = sizeof(vertex_data);
573 SDL_UploadToGPUBuffer(copy_pass, &buf_location, &dst_region, false);
574 SDL_EndGPUCopyPass(copy_pass);
575 SDL_SubmitGPUCommandBuffer(cmd);
576
577 SDL_ReleaseGPUTransferBuffer(gpu_device, buf_transfer);
578
579 /* Determine which sample count to use */
580 render_state.sample_count = SDL_GPU_SAMPLECOUNT_1;
581 if (msaa && SDL_GPUTextureSupportsSampleCount(
582 gpu_device,
583 SDL_GetGPUSwapchainTextureFormat(gpu_device, state->windows[0]),
584 SDL_GPU_SAMPLECOUNT_4)) {
585 render_state.sample_count = SDL_GPU_SAMPLECOUNT_4;
586 }
587
588 /* Set up the graphics pipeline */
589
590 SDL_zero(pipelinedesc);
591 SDL_zero(color_target_desc);
592
593 color_target_desc.format = SDL_GetGPUSwapchainTextureFormat(gpu_device, state->windows[0]);
594
595 pipelinedesc.target_info.num_color_targets = 1;
596 pipelinedesc.target_info.color_target_descriptions = &color_target_desc;
597 pipelinedesc.target_info.depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D16_UNORM;
598 pipelinedesc.target_info.has_depth_stencil_target = true;
599
600 pipelinedesc.depth_stencil_state.enable_depth_test = true;
601 pipelinedesc.depth_stencil_state.enable_depth_write = true;
602 pipelinedesc.depth_stencil_state.compare_op = SDL_GPU_COMPAREOP_LESS_OR_EQUAL;
603
604 pipelinedesc.multisample_state.sample_count = render_state.sample_count;
605
606 pipelinedesc.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST;
607
608 pipelinedesc.vertex_shader = vertex_shader;
609 pipelinedesc.fragment_shader = fragment_shader;
610
611 vertex_buffer_desc.slot = 0;
612 vertex_buffer_desc.input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX;
613 vertex_buffer_desc.instance_step_rate = 0;
614 vertex_buffer_desc.pitch = sizeof(VertexData);
615
616 vertex_attributes[0].buffer_slot = 0;
617 vertex_attributes[0].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3;
618 vertex_attributes[0].location = 0;
619 vertex_attributes[0].offset = 0;
620
621 vertex_attributes[1].buffer_slot = 0;
622 vertex_attributes[1].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3;
623 vertex_attributes[1].location = 1;
624 vertex_attributes[1].offset = sizeof(float) * 3;
625
626 pipelinedesc.vertex_input_state.num_vertex_buffers = 1;
627 pipelinedesc.vertex_input_state.vertex_buffer_descriptions = &vertex_buffer_desc;
628 pipelinedesc.vertex_input_state.num_vertex_attributes = 2;
629 pipelinedesc.vertex_input_state.vertex_attributes = (SDL_GPUVertexAttribute*) &vertex_attributes;
630
631 pipelinedesc.props = 0;
632
633 render_state.pipeline = SDL_CreateGPUGraphicsPipeline(gpu_device, &pipelinedesc);
634 CHECK_CREATE(render_state.pipeline, "Render Pipeline")
635
636 /* These are reference-counted; once the pipeline is created, you don't need to keep these. */
637 SDL_ReleaseGPUShader(gpu_device, vertex_shader);
638 SDL_ReleaseGPUShader(gpu_device, fragment_shader);
639
640 /* Set up per-window state */
641
642 window_states = (WindowState *) SDL_calloc(state->num_windows, sizeof (WindowState));
643 if (!window_states) {
644 SDL_Log("Out of memory!");
645 quit(2);
646 }
647
648 for (i = 0; i < state->num_windows; i++) {
649 WindowState *winstate = &window_states[i];
650
651 /* create a depth texture for the window */
652 SDL_GetWindowSizeInPixels(state->windows[i], (int*) &drawablew, (int*) &drawableh);
653 winstate->tex_depth = CreateDepthTexture(drawablew, drawableh);
654 winstate->tex_msaa = CreateMSAATexture(drawablew, drawableh);
655 winstate->tex_resolve = CreateResolveTexture(drawablew, drawableh);
656
657 /* make each window different */
658 winstate->angle_x = (i * 10) % 360;
659 winstate->angle_y = (i * 20) % 360;
660 winstate->angle_z = (i * 30) % 360;
661 }
662}
663
664static int done = 0;
665
666void loop(void)
667{
668 SDL_Event event;
669 int i;
670
671 /* Check for events */
672 while (SDL_PollEvent(&event) && !done) {
673 SDLTest_CommonEvent(state, &event, &done);
674 }
675 if (!done) {
676 for (i = 0; i < state->num_windows; ++i) {
677 Render(state->windows[i], i);
678 }
679 }
680#ifdef __EMSCRIPTEN__
681 else {
682 emscripten_cancel_main_loop();
683 }
684#endif
685}
686
687int
688main(int argc, char *argv[])
689{
690 int msaa;
691 int i;
692 const SDL_DisplayMode *mode;
693 Uint64 then, now;
694
695 /* Initialize params */
696 msaa = 0;
697
698 /* Initialize test framework */
699 state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
700 if (!state) {
701 return 1;
702 }
703 for (i = 1; i < argc;) {
704 int consumed;
705
706 consumed = SDLTest_CommonArg(state, i);
707 if (consumed == 0) {
708 if (SDL_strcasecmp(argv[i], "--msaa") == 0) {
709 ++msaa;
710 consumed = 1;
711 } else {
712 consumed = -1;
713 }
714 }
715 if (consumed < 0) {
716 static const char *options[] = { "[--msaa]", NULL };
717 SDLTest_CommonLogUsage(state, argv[0], options);
718 quit(1);
719 }
720 i += consumed;
721 }
722
723 state->skip_renderer = 1;
724 state->window_flags |= SDL_WINDOW_RESIZABLE;
725
726 if (!SDLTest_CommonInit(state)) {
727 quit(2);
728 return 0;
729 }
730
731 mode = SDL_GetCurrentDisplayMode(SDL_GetDisplayForWindow(state->windows[0]));
732 SDL_Log("Screen bpp: %d", SDL_BITSPERPIXEL(mode->format));
733
734 init_render_state(msaa);
735
736 /* Main render loop */
737 frames = 0;
738 then = SDL_GetTicks();
739 done = 0;
740
741#ifdef __EMSCRIPTEN__
742 emscripten_set_main_loop(loop, 0, 1);
743#else
744 while (!done) {
745 loop();
746 }
747#endif
748
749 /* Print out some timing information */
750 now = SDL_GetTicks();
751 if (now > then) {
752 SDL_Log("%2.2f frames per second",
753 ((double) frames * 1000) / (now - then));
754 }
755#if !defined(__ANDROID__)
756 quit(0);
757#endif
758 return 0;
759}
760
761/* vi: set ts=4 sw=4 expandtab: */