Atlas - testgpurender_effects.c

Home / ext / SDL / test Lines: 1 | Size: 10715 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ 14#include <SDL3/SDL.h> 15#include <SDL3/SDL_main.h> 16 17#include "testutils.h" 18 19#include "testgpurender_effects_grayscale.frag.dxil.h" 20#include "testgpurender_effects_grayscale.frag.msl.h" 21#include "testgpurender_effects_grayscale.frag.spv.h" 22#include "testgpurender_effects_CRT.frag.dxil.h" 23#include "testgpurender_effects_CRT.frag.msl.h" 24#include "testgpurender_effects_CRT.frag.spv.h" 25 26/* The window is twice the size of the background */ 27#define WINDOW_WIDTH (408 * 2) 28#define WINDOW_HEIGHT (167 * 2) 29#define NUM_SPRITES 15 30#define MAX_SPEED 1 31 32static SDL_Window *window = NULL; 33static SDL_Renderer *renderer = NULL; 34static SDL_Texture *target = NULL; 35static SDL_GPUDevice *device = NULL; 36static SDL_Texture *background; 37static SDL_Texture *sprite; 38static SDL_FRect positions[NUM_SPRITES]; 39static SDL_FRect velocities[NUM_SPRITES]; 40 41typedef enum 42{ 43 EFFECT_NONE, 44 EFFECT_GRAYSCALE, 45 EFFECT_CRT, 46 NUM_EFFECTS 47} FullscreenEffect; 48 49typedef struct 50{ 51 const char *name; 52 const unsigned char *dxil_shader_source; 53 unsigned int dxil_shader_source_len; 54 const unsigned char *msl_shader_source; 55 unsigned int msl_shader_source_len; 56 const unsigned char *spirv_shader_source; 57 unsigned int spirv_shader_source_len; 58 int num_samplers; 59 int num_uniform_buffers; 60 SDL_GPUShader *shader; 61 SDL_GPURenderState *state; 62} FullscreenEffectData; 63 64typedef struct 65{ 66 float texture_width; 67 float texture_height; 68} CRTEffectUniforms; 69 70static FullscreenEffectData effects[] = { 71 { 72 "NONE", 73 NULL, 74 0, 75 NULL, 76 0, 77 NULL, 78 0, 79 0, 80 0, 81 NULL, 82 NULL 83 }, 84 { 85 "Grayscale", 86 testgpurender_effects_grayscale_frag_dxil, 87 sizeof(testgpurender_effects_grayscale_frag_dxil), 88 testgpurender_effects_grayscale_frag_msl, 89 sizeof(testgpurender_effects_grayscale_frag_msl), 90 testgpurender_effects_grayscale_frag_spv, 91 sizeof(testgpurender_effects_grayscale_frag_spv), 92 1, 93 0, 94 NULL, 95 NULL 96 }, 97 { 98 "CRT monitor", 99 testgpurender_effects_CRT_frag_dxil, 100 sizeof(testgpurender_effects_CRT_frag_dxil), 101 testgpurender_effects_CRT_frag_msl, 102 sizeof(testgpurender_effects_CRT_frag_msl), 103 testgpurender_effects_CRT_frag_spv, 104 sizeof(testgpurender_effects_CRT_frag_spv), 105 1, 106 1, 107 NULL, 108 NULL 109 } 110}; 111SDL_COMPILE_TIME_ASSERT(effects, SDL_arraysize(effects) == NUM_EFFECTS); 112 113static int current_effect = 0; 114 115static void DrawScene(void) 116{ 117 int i; 118 int window_w = WINDOW_WIDTH; 119 int window_h = WINDOW_HEIGHT; 120 SDL_FRect *position, *velocity; 121 122 SDL_RenderTexture(renderer, background, NULL, NULL); 123 124 /* Move the sprite, bounce at the wall, and draw */ 125 for (i = 0; i < NUM_SPRITES; ++i) { 126 position = &positions[i]; 127 velocity = &velocities[i]; 128 position->x += velocity->x; 129 if ((position->x < 0) || (position->x >= (window_w - sprite->w))) { 130 velocity->x = -velocity->x; 131 position->x += velocity->x; 132 } 133 position->y += velocity->y; 134 if ((position->y < 0) || (position->y >= (window_h - sprite->h))) { 135 velocity->y = -velocity->y; 136 position->y += velocity->y; 137 } 138 139 /* Blit the sprite onto the screen */ 140 SDL_RenderTexture(renderer, sprite, NULL, position); 141 } 142} 143 144static bool InitGPURenderState(void) 145{ 146 SDL_GPUShaderFormat formats; 147 SDL_GPUShaderCreateInfo info; 148 SDL_GPURenderStateCreateInfo createinfo; 149 int i; 150 151 device = SDL_GetGPURendererDevice(renderer); 152 if (!device) { 153 SDL_Log("Couldn't get GPU device"); 154 return false; 155 } 156 157 formats = SDL_GetGPUShaderFormats(device); 158 if (formats == SDL_GPU_SHADERFORMAT_INVALID) { 159 SDL_Log("Couldn't get supported shader formats: %s", SDL_GetError()); 160 return false; 161 } 162 163 for (i = 0; i < SDL_arraysize(effects); ++i) { 164 FullscreenEffectData *data = &effects[i]; 165 166 if (i == EFFECT_NONE) { 167 continue; 168 } 169 170 SDL_zero(info); 171 if (formats & SDL_GPU_SHADERFORMAT_SPIRV) { 172 info.format = SDL_GPU_SHADERFORMAT_SPIRV; 173 info.code = data->spirv_shader_source; 174 info.code_size = data->spirv_shader_source_len; 175 } else if (formats & SDL_GPU_SHADERFORMAT_DXIL) { 176 info.format = SDL_GPU_SHADERFORMAT_DXIL; 177 info.code = data->dxil_shader_source; 178 info.code_size = data->dxil_shader_source_len; 179 } else if (formats & SDL_GPU_SHADERFORMAT_MSL) { 180 info.format = SDL_GPU_SHADERFORMAT_MSL; 181 info.code = data->msl_shader_source; 182 info.code_size = data->msl_shader_source_len; 183 } else { 184 SDL_Log("No supported shader format found"); 185 return false; 186 } 187 info.num_samplers = data->num_samplers; 188 info.num_uniform_buffers = data->num_uniform_buffers; 189 info.stage = SDL_GPU_SHADERSTAGE_FRAGMENT; 190 data->shader = SDL_CreateGPUShader(device, &info); 191 if (!data->shader) { 192 SDL_Log("Couldn't create shader: %s", SDL_GetError()); 193 return false; 194 } 195 196 SDL_zero(createinfo); 197 createinfo.fragment_shader = data->shader; 198 data->state = SDL_CreateGPURenderState(renderer, &createinfo); 199 if (!data->state) { 200 SDL_Log("Couldn't create render state: %s", SDL_GetError()); 201 return false; 202 } 203 204 if (i == EFFECT_CRT) { 205 CRTEffectUniforms uniforms; 206 SDL_zero(uniforms); 207 uniforms.texture_width = (float)target->w; 208 uniforms.texture_height = (float)target->h; 209 if (!SDL_SetGPURenderStateFragmentUniforms(data->state, 0, &uniforms, sizeof(uniforms))) { 210 SDL_Log("Couldn't set uniform data: %s", SDL_GetError()); 211 return false; 212 } 213 } 214 } 215 return true; 216} 217 218static void QuitGPURenderState(void) 219{ 220 int i; 221 222 for (i = 0; i < SDL_arraysize(effects); ++i) { 223 FullscreenEffectData *data = &effects[i]; 224 225 if (i == EFFECT_NONE) { 226 continue; 227 } 228 229 SDL_DestroyGPURenderState(data->state); 230 SDL_ReleaseGPUShader(device, data->shader); 231 } 232} 233 234/* This function runs once at startup. */ 235SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) 236{ 237 const char *description = "GPU render effects example"; 238 int i; 239 240 SDL_SetAppMetadata(description, "1.0", "com.example.testgpurender_effects"); 241 242 if (!SDL_Init(SDL_INIT_VIDEO)) { 243 SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); 244 return SDL_APP_FAILURE; 245 } 246 247 window = SDL_CreateWindow(description, WINDOW_WIDTH, WINDOW_HEIGHT, 0); 248 if (!window) { 249 SDL_Log("Couldn't create window: %s", SDL_GetError()); 250 return SDL_APP_FAILURE; 251 } 252 253 renderer = SDL_CreateRenderer(window, SDL_GPU_RENDERER); 254 if (!renderer) { 255 SDL_Log("Couldn't create renderer: %s", SDL_GetError()); 256 return SDL_APP_FAILURE; 257 } 258 SDL_SetRenderVSync(renderer, 1); 259 260 target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, WINDOW_WIDTH, WINDOW_HEIGHT); 261 if (!target) { 262 SDL_Log("Couldn't create target texture: %s", SDL_GetError()); 263 return SDL_APP_FAILURE; 264 } 265 266 background = LoadTexture(renderer, "sample.png", false); 267 if (!background) { 268 SDL_Log("Couldn't create background: %s", SDL_GetError()); 269 return SDL_APP_FAILURE; 270 } 271 272 sprite = LoadTexture(renderer, "icon.png", true); 273 if (!sprite) { 274 SDL_Log("Couldn't create sprite: %s", SDL_GetError()); 275 return SDL_APP_FAILURE; 276 } 277 278 /* Initialize the sprite positions */ 279 for (i = 0; i < NUM_SPRITES; ++i) { 280 positions[i].x = (float)SDL_rand(WINDOW_WIDTH - sprite->w); 281 positions[i].y = (float)SDL_rand(WINDOW_HEIGHT - sprite->h); 282 positions[i].w = (float)sprite->w; 283 positions[i].h = (float)sprite->h; 284 velocities[i].x = 0.0f; 285 velocities[i].y = 0.0f; 286 while (velocities[i].x == 0.f && velocities[i].y == 0.f) { 287 velocities[i].x = (float)(SDL_rand(MAX_SPEED * 2 + 1) - MAX_SPEED); 288 velocities[i].y = (float)(SDL_rand(MAX_SPEED * 2 + 1) - MAX_SPEED); 289 } 290 } 291 292 if (!InitGPURenderState()) { 293 return SDL_APP_FAILURE; 294 } 295 296 return SDL_APP_CONTINUE; /* carry on with the program! */ 297} 298 299/* This function runs when a new event (mouse input, keypresses, etc) occurs. */ 300SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) 301{ 302 if (event->type == SDL_EVENT_QUIT || 303 (event->type == SDL_EVENT_KEY_DOWN && event->key.key == SDLK_ESCAPE)) { 304 return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ 305 } 306 if (event->type == SDL_EVENT_KEY_DOWN) { 307 if (event->key.key == SDLK_SPACE) { 308 current_effect = (current_effect + 1) % NUM_EFFECTS; 309 } 310 } 311 return SDL_APP_CONTINUE; /* carry on with the program! */ 312} 313 314/* This function runs once per frame, and is the heart of the program. */ 315SDL_AppResult SDL_AppIterate(void *appstate) 316{ 317 FullscreenEffectData *effect = &effects[current_effect]; 318 319 /* Draw the scene to the render target */ 320 SDL_SetRenderTarget(renderer, target); 321 DrawScene(); 322 SDL_SetRenderTarget(renderer, NULL); 323 324 /* Display the render target with the fullscreen effect */ 325 SDL_SetGPURenderState(renderer, effect->state); 326 SDL_RenderTexture(renderer, target, NULL, NULL); 327 SDL_SetGPURenderState(renderer, NULL); 328 329 /* Draw some help text */ 330 SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); 331 SDL_RenderDebugTextFormat(renderer, 4.0f, WINDOW_HEIGHT - SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE - 4.0f, 332 "Current effect: %s, press SPACE to cycle", effect->name); 333 334 SDL_RenderPresent(renderer); 335 336 return SDL_APP_CONTINUE; /* carry on with the program! */ 337} 338 339/* This function runs once at shutdown. */ 340void SDL_AppQuit(void *appstate, SDL_AppResult result) 341{ 342 /* SDL will clean up the window/renderer for us. */ 343 QuitGPURenderState(); 344} 345 346
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.