Atlas - SDL_shaders_gpu.c
Home / ext / SDL / src / render / gpu Lines: 1 | Size: 9584 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2026 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "SDL_internal.h" 22 23#ifdef SDL_VIDEO_RENDER_GPU 24 25#include "SDL_shaders_gpu.h" 26 27// SDL_GPU shader implementation 28 29typedef struct GPU_ShaderModuleSource 30{ 31 const unsigned char *code; 32 unsigned int code_len; 33 SDL_GPUShaderFormat format; 34} GPU_ShaderModuleSource; 35 36#if defined(SDL_GPU_PRIVATE) 37#define IF_PRIVATE(...) __VA_ARGS__ 38#define HAVE_PRIVATE_SHADERS 1 39#include "SDL_render_private_shaders.h" 40#else 41#define IF_PRIVATE(...) 42#define HAVE_PRIVATE_SHADERS 0 43#endif 44 45#if defined(SDL_GPU_VULKAN) && SDL_GPU_VULKAN 46#define IF_VULKAN(...) __VA_ARGS__ 47#define HAVE_SPIRV_SHADERS 1 48#include "shaders/spir-v.h" 49#else 50#define IF_VULKAN(...) 51#define HAVE_SPIRV_SHADERS 0 52#endif 53 54#ifdef SDL_GPU_D3D12 55#define IF_D3D12(...) __VA_ARGS__ 56#define HAVE_DXIL60_SHADERS 1 57#include "shaders/dxil.h" 58#else 59#define IF_D3D12(...) 60#define HAVE_DXIL60_SHADERS 0 61#endif 62 63#ifdef SDL_GPU_METAL 64#define IF_METAL(...) __VA_ARGS__ 65#define HAVE_METAL_SHADERS 1 66#include "shaders/msl.h" 67#else 68#define IF_METAL(...) 69#define HAVE_METAL_SHADERS 0 70#endif 71 72typedef struct GPU_ShaderSources 73{ 74 IF_PRIVATE(GPU_ShaderModuleSource private;) 75 IF_VULKAN(GPU_ShaderModuleSource spirv;) 76 IF_D3D12(GPU_ShaderModuleSource dxil60;) 77 IF_METAL(GPU_ShaderModuleSource msl;) 78 unsigned int num_samplers; 79 unsigned int num_uniform_buffers; 80} GPU_ShaderSources; 81 82#define SHADER_PRIVATE(code) \ 83 IF_PRIVATE(.private = { code, sizeof(code), SDL_GPU_SHADERFORMAT_PRIVATE }, ) 84 85#define SHADER_SPIRV(code) \ 86 IF_VULKAN(.spirv = { code, sizeof(code), SDL_GPU_SHADERFORMAT_SPIRV }, ) 87 88#define SHADER_DXIL60(code) \ 89 IF_D3D12(.dxil60 = { code, sizeof(code), SDL_GPU_SHADERFORMAT_DXIL }, ) 90 91#define SHADER_METAL(code) \ 92 IF_METAL(.msl = { code, sizeof(code), SDL_GPU_SHADERFORMAT_MSL }, ) 93 94// clang-format off 95static const GPU_ShaderSources vert_shader_sources[NUM_VERT_SHADERS] = { 96 [VERT_SHADER_LINEPOINT] = { 97 .num_samplers = 0, 98 .num_uniform_buffers = 1, 99 SHADER_PRIVATE(linepoint_vert_private) 100 SHADER_SPIRV(linepoint_vert_spv) 101 SHADER_DXIL60(linepoint_vert_dxil) 102 SHADER_METAL(linepoint_vert_msl) 103 }, 104 [VERT_SHADER_TRI_COLOR] = { 105 .num_samplers = 0, 106 .num_uniform_buffers = 1, 107 SHADER_PRIVATE(tri_color_vert_private) 108 SHADER_SPIRV(tri_color_vert_spv) 109 SHADER_DXIL60(tri_color_vert_dxil) 110 SHADER_METAL(tri_color_vert_msl) 111 }, 112 [VERT_SHADER_TRI_TEXTURE] = { 113 .num_samplers = 0, 114 .num_uniform_buffers = 1, 115 SHADER_PRIVATE(tri_texture_vert_private) 116 SHADER_SPIRV(tri_texture_vert_spv) 117 SHADER_DXIL60(tri_texture_vert_dxil) 118 SHADER_METAL(tri_texture_vert_msl) 119 }, 120}; 121 122static const GPU_ShaderSources frag_shader_sources[NUM_FRAG_SHADERS] = { 123 [FRAG_SHADER_COLOR] = { 124 .num_samplers = 0, 125 .num_uniform_buffers = 1, 126 SHADER_PRIVATE(color_frag_private) 127 SHADER_SPIRV(color_frag_spv) 128 SHADER_DXIL60(color_frag_dxil) 129 SHADER_METAL(color_frag_msl) 130 }, 131 [FRAG_SHADER_TEXTURE_RGB] = { 132 .num_samplers = 1, 133 .num_uniform_buffers = 1, 134 SHADER_PRIVATE(texture_rgb_frag_private) 135 SHADER_SPIRV(texture_rgb_frag_spv) 136 SHADER_DXIL60(texture_rgb_frag_dxil) 137 SHADER_METAL(texture_rgb_frag_msl) 138 }, 139 [FRAG_SHADER_TEXTURE_RGBA] = { 140 .num_samplers = 1, 141 .num_uniform_buffers = 1, 142 SHADER_PRIVATE(texture_rgba_frag_private) 143 SHADER_SPIRV(texture_rgba_frag_spv) 144 SHADER_DXIL60(texture_rgba_frag_dxil) 145 SHADER_METAL(texture_rgba_frag_msl) 146 }, 147 [FRAG_SHADER_TEXTURE_ADVANCED] = { 148 .num_samplers = 3, 149 .num_uniform_buffers = 1, 150 SHADER_PRIVATE(texture_advanced_frag_private) 151 SHADER_SPIRV(texture_advanced_frag_spv) 152 SHADER_DXIL60(texture_advanced_frag_dxil) 153 SHADER_METAL(texture_advanced_frag_msl) 154 }, 155}; 156// clang-format on 157 158static SDL_GPUShader *CompileShader(const GPU_ShaderSources *sources, SDL_GPUDevice *device, SDL_GPUShaderStage stage) 159{ 160 const GPU_ShaderModuleSource *sms = NULL; 161 SDL_GPUShaderFormat formats = SDL_GetGPUShaderFormats(device); 162 163 if (formats == SDL_GPU_SHADERFORMAT_INVALID) { 164 // SDL_GetGPUShaderFormats already set the error 165 return NULL; 166#if HAVE_PRIVATE_SHADERS 167 } else if (formats & SDL_GPU_SHADERFORMAT_PRIVATE) { 168 sms = &sources->private; 169#endif // HAVE_PRIVATE_SHADERS 170#if HAVE_SPIRV_SHADERS 171 } else if (formats & SDL_GPU_SHADERFORMAT_SPIRV) { 172 sms = &sources->spirv; 173#endif // HAVE_SPIRV_SHADERS 174#if HAVE_DXIL60_SHADERS 175 } else if (formats & SDL_GPU_SHADERFORMAT_DXIL) { 176 sms = &sources->dxil60; 177#endif // HAVE_DXIL60_SHADERS 178#if HAVE_METAL_SHADERS 179 } else if (formats & SDL_GPU_SHADERFORMAT_MSL) { 180 sms = &sources->msl; 181#endif // HAVE_METAL_SHADERS 182 } else { 183 SDL_SetError("Unsupported GPU backend"); 184 return NULL; 185 } 186 187 SDL_GPUShaderCreateInfo sci = { 0 }; 188 sci.code = sms->code; 189 sci.code_size = sms->code_len; 190 sci.format = sms->format; 191 // FIXME not sure if this is correct 192 sci.entrypoint = 193#if HAVE_METAL_SHADERS 194 (sms == &sources->msl) ? "main0" : 195#endif // HAVE_METAL_SHADERS 196 "main"; 197 sci.num_samplers = sources->num_samplers; 198 sci.num_uniform_buffers = sources->num_uniform_buffers; 199 sci.stage = stage; 200 201 return SDL_CreateGPUShader(device, &sci); 202} 203 204bool GPU_InitShaders(GPU_Shaders *shaders, SDL_GPUDevice *device) 205{ 206 for (int i = 0; i < SDL_arraysize(vert_shader_sources); ++i) { 207 shaders->vert_shaders[i] = CompileShader( 208 &vert_shader_sources[i], device, SDL_GPU_SHADERSTAGE_VERTEX); 209 if (shaders->vert_shaders[i] == NULL) { 210 GPU_ReleaseShaders(shaders, device); 211 return false; 212 } 213 } 214 215 for (int i = 0; i < SDL_arraysize(frag_shader_sources); ++i) { 216 if (i == FRAG_SHADER_TEXTURE_CUSTOM) { 217 continue; 218 } 219 shaders->frag_shaders[i] = CompileShader( 220 &frag_shader_sources[i], device, SDL_GPU_SHADERSTAGE_FRAGMENT); 221 if (shaders->frag_shaders[i] == NULL) { 222 GPU_ReleaseShaders(shaders, device); 223 return false; 224 } 225 } 226 227 return true; 228} 229 230void GPU_ReleaseShaders(GPU_Shaders *shaders, SDL_GPUDevice *device) 231{ 232 for (int i = 0; i < SDL_arraysize(shaders->vert_shaders); ++i) { 233 SDL_ReleaseGPUShader(device, shaders->vert_shaders[i]); 234 shaders->vert_shaders[i] = NULL; 235 } 236 237 for (int i = 0; i < SDL_arraysize(shaders->frag_shaders); ++i) { 238 if (i == FRAG_SHADER_TEXTURE_CUSTOM) { 239 continue; 240 } 241 SDL_ReleaseGPUShader(device, shaders->frag_shaders[i]); 242 shaders->frag_shaders[i] = NULL; 243 } 244} 245 246SDL_GPUShader *GPU_GetVertexShader(GPU_Shaders *shaders, GPU_VertexShaderID id) 247{ 248 SDL_assert((unsigned int)id < SDL_arraysize(shaders->vert_shaders)); 249 SDL_GPUShader *shader = shaders->vert_shaders[id]; 250 SDL_assert(shader != NULL); 251 return shader; 252} 253 254SDL_GPUShader *GPU_GetFragmentShader(GPU_Shaders *shaders, GPU_FragmentShaderID id) 255{ 256 SDL_assert((unsigned int)id < SDL_arraysize(shaders->frag_shaders)); 257 SDL_GPUShader *shader = shaders->frag_shaders[id]; 258 SDL_assert(shader != NULL); 259 return shader; 260} 261 262void GPU_FillSupportedShaderFormats(SDL_PropertiesID props) 263{ 264 bool custom_shaders = false; 265 if (SDL_GetBooleanProperty(props, SDL_PROP_RENDERER_CREATE_GPU_SHADERS_SPIRV_BOOLEAN, false)) { 266 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN, HAVE_SPIRV_SHADERS); 267 custom_shaders = true; 268 } 269 if (SDL_GetBooleanProperty(props, SDL_PROP_RENDERER_CREATE_GPU_SHADERS_DXIL_BOOLEAN, false)) { 270 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN, HAVE_DXIL60_SHADERS); 271 custom_shaders = true; 272 } 273 if (SDL_GetBooleanProperty(props, SDL_PROP_RENDERER_CREATE_GPU_SHADERS_MSL_BOOLEAN, false)) { 274 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN, HAVE_METAL_SHADERS); 275 custom_shaders = true; 276 } 277 if (!custom_shaders) { 278 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOLEAN, HAVE_PRIVATE_SHADERS); 279 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN, HAVE_SPIRV_SHADERS); 280 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN, HAVE_DXIL60_SHADERS); 281 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN, HAVE_METAL_SHADERS); 282 } 283} 284 285#endif // SDL_VIDEO_RENDER_GPU 286[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.