Atlas - SDL_gpu.c
Home / ext / SDL / src / gpu Lines: 1 | Size: 121597 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 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#include "SDL_sysgpu.h" 23 24// FIXME: This could probably use SDL_ObjectValid 25#define CHECK_DEVICE_MAGIC(device, retval) \ 26 CHECK_PARAM(device == NULL) { \ 27 SDL_SetError("Invalid GPU device"); \ 28 return retval; \ 29 } 30 31#define CHECK_COMMAND_BUFFER \ 32 if (((CommandBufferCommonHeader *)command_buffer)->submitted) { \ 33 SDL_assert_release(!"Command buffer already submitted!"); \ 34 return; \ 35 } 36 37#define CHECK_COMMAND_BUFFER_RETURN_FALSE \ 38 if (((CommandBufferCommonHeader *)command_buffer)->submitted) { \ 39 SDL_assert_release(!"Command buffer already submitted!"); \ 40 return false; \ 41 } 42 43#define CHECK_COMMAND_BUFFER_RETURN_NULL \ 44 if (((CommandBufferCommonHeader *)command_buffer)->submitted) { \ 45 SDL_assert_release(!"Command buffer already submitted!"); \ 46 return NULL; \ 47 } 48 49#define CHECK_ANY_PASS_IN_PROGRESS(msg, retval) \ 50 if ( \ 51 ((CommandBufferCommonHeader *)command_buffer)->render_pass.in_progress || \ 52 ((CommandBufferCommonHeader *)command_buffer)->compute_pass.in_progress || \ 53 ((CommandBufferCommonHeader *)command_buffer)->copy_pass.in_progress) { \ 54 SDL_assert_release(!msg); \ 55 return retval; \ 56 } 57 58#define CHECK_RENDERPASS \ 59 if (!((RenderPass *)render_pass)->in_progress) { \ 60 SDL_assert_release(!"Render pass not in progress!"); \ 61 return; \ 62 } 63 64#if 0 65// The below validation is too aggressive, since there are advanced situations 66// where this is legal. This is being temporarily disabled for further review. 67// See: https://github.com/libsdl-org/SDL/issues/13871 68#define CHECK_SAMPLER_TEXTURES \ 69 RenderPass *rp = (RenderPass *)render_pass; \ 70 for (Uint32 color_target_index = 0; color_target_index < rp->num_color_targets; color_target_index += 1) { \ 71 for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \ 72 if (rp->color_targets[color_target_index] == texture_sampler_bindings[texture_sampler_index].texture) { \ 73 SDL_assert_release(!"Texture cannot be simultaneously bound as a color target and a sampler!"); \ 74 } \ 75 } \ 76 } \ 77 \ 78 for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \ 79 if (rp->depth_stencil_target != NULL && rp->depth_stencil_target == texture_sampler_bindings[texture_sampler_index].texture) { \ 80 SDL_assert_release(!"Texture cannot be simultaneously bound as a depth stencil target and a sampler!"); \ 81 } \ 82 } 83 84#define CHECK_STORAGE_TEXTURES \ 85 RenderPass *rp = (RenderPass *)render_pass; \ 86 for (Uint32 color_target_index = 0; color_target_index < rp->num_color_targets; color_target_index += 1) { \ 87 for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \ 88 if (rp->color_targets[color_target_index] == storage_textures[texture_sampler_index]) { \ 89 SDL_assert_release(!"Texture cannot be simultaneously bound as a color target and a storage texture!"); \ 90 } \ 91 } \ 92 } \ 93 \ 94 for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \ 95 if (rp->depth_stencil_target != NULL && rp->depth_stencil_target == storage_textures[texture_sampler_index]) { \ 96 SDL_assert_release(!"Texture cannot be simultaneously bound as a depth stencil target and a storage texture!"); \ 97 } \ 98 } 99#else 100#define CHECK_SAMPLER_TEXTURES 101#define CHECK_STORAGE_TEXTURES 102#endif 103 104#define CHECK_GRAPHICS_PIPELINE_BOUND \ 105 if (!((RenderPass *)render_pass)->graphics_pipeline) { \ 106 SDL_assert_release(!"Graphics pipeline not bound!"); \ 107 return; \ 108 } 109 110#define CHECK_COMPUTEPASS \ 111 if (!((Pass *)compute_pass)->in_progress) { \ 112 SDL_assert_release(!"Compute pass not in progress!"); \ 113 return; \ 114 } 115 116#define CHECK_COMPUTE_PIPELINE_BOUND \ 117 if (!((ComputePass *)compute_pass)->compute_pipeline) { \ 118 SDL_assert_release(!"Compute pipeline not bound!"); \ 119 return; \ 120 } 121 122#define CHECK_COPYPASS \ 123 if (!((Pass *)copy_pass)->in_progress) { \ 124 SDL_assert_release(!"Copy pass not in progress!"); \ 125 return; \ 126 } 127 128#define CHECK_TEXTUREFORMAT_ENUM_INVALID(enumval, retval) \ 129 if (enumval <= SDL_GPU_TEXTUREFORMAT_INVALID || enumval >= SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE) { \ 130 SDL_assert_release(!"Invalid texture format enum!"); \ 131 return retval; \ 132 } 133 134#define CHECK_VERTEXELEMENTFORMAT_ENUM_INVALID(enumval, retval) \ 135 if (enumval <= SDL_GPU_VERTEXELEMENTFORMAT_INVALID || enumval >= SDL_GPU_VERTEXELEMENTFORMAT_MAX_ENUM_VALUE) { \ 136 SDL_assert_release(!"Invalid vertex format enum!"); \ 137 return retval; \ 138 } 139 140#define CHECK_COMPAREOP_ENUM_INVALID(enumval, retval) \ 141 if (enumval <= SDL_GPU_COMPAREOP_INVALID || enumval >= SDL_GPU_COMPAREOP_MAX_ENUM_VALUE) { \ 142 SDL_assert_release(!"Invalid compare op enum!"); \ 143 return retval; \ 144 } 145 146#define CHECK_STENCILOP_ENUM_INVALID(enumval, retval) \ 147 if (enumval <= SDL_GPU_STENCILOP_INVALID || enumval >= SDL_GPU_STENCILOP_MAX_ENUM_VALUE) { \ 148 SDL_assert_release(!"Invalid stencil op enum!"); \ 149 return retval; \ 150 } 151 152#define CHECK_BLENDOP_ENUM_INVALID(enumval, retval) \ 153 if (enumval <= SDL_GPU_BLENDOP_INVALID || enumval >= SDL_GPU_BLENDOP_MAX_ENUM_VALUE) { \ 154 SDL_assert_release(!"Invalid blend op enum!"); \ 155 return retval; \ 156 } 157 158#define CHECK_BLENDFACTOR_ENUM_INVALID(enumval, retval) \ 159 if (enumval <= SDL_GPU_BLENDFACTOR_INVALID || enumval >= SDL_GPU_BLENDFACTOR_MAX_ENUM_VALUE) { \ 160 SDL_assert_release(!"Invalid blend factor enum!"); \ 161 return retval; \ 162 } 163 164#define CHECK_SWAPCHAINCOMPOSITION_ENUM_INVALID(enumval, retval) \ 165 if (enumval < 0 || enumval >= SDL_GPU_SWAPCHAINCOMPOSITION_MAX_ENUM_VALUE) { \ 166 SDL_assert_release(!"Invalid swapchain composition enum!"); \ 167 return retval; \ 168 } 169 170#define CHECK_PRESENTMODE_ENUM_INVALID(enumval, retval) \ 171 if (enumval < 0 || enumval >= SDL_GPU_PRESENTMODE_MAX_ENUM_VALUE) { \ 172 SDL_assert_release(!"Invalid present mode enum!"); \ 173 return retval; \ 174 } 175 176#define COMMAND_BUFFER_DEVICE \ 177 ((CommandBufferCommonHeader *)command_buffer)->device 178 179#define RENDERPASS_COMMAND_BUFFER \ 180 ((RenderPass *)render_pass)->command_buffer 181 182#define RENDERPASS_DEVICE \ 183 ((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->device 184 185#define RENDERPASS_BOUND_PIPELINE \ 186 ((RenderPass *)render_pass)->graphics_pipeline 187 188#define COMPUTEPASS_COMMAND_BUFFER \ 189 ((Pass *)compute_pass)->command_buffer 190 191#define COMPUTEPASS_DEVICE \ 192 ((CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER)->device 193 194#define COMPUTEPASS_BOUND_PIPELINE \ 195 ((ComputePass *)compute_pass)->compute_pipeline 196 197#define COPYPASS_COMMAND_BUFFER \ 198 ((Pass *)copy_pass)->command_buffer 199 200#define COPYPASS_DEVICE \ 201 ((CommandBufferCommonHeader *)COPYPASS_COMMAND_BUFFER)->device 202 203static bool TextureFormatIsComputeWritable[] = { 204 false, // INVALID 205 false, // A8_UNORM 206 true, // R8_UNORM 207 true, // R8G8_UNORM 208 true, // R8G8B8A8_UNORM 209 true, // R16_UNORM 210 true, // R16G16_UNORM 211 true, // R16G16B16A16_UNORM 212 true, // R10G10B10A2_UNORM 213 false, // B5G6R5_UNORM 214 false, // B5G5R5A1_UNORM 215 false, // B4G4R4A4_UNORM 216 false, // B8G8R8A8_UNORM 217 false, // BC1_UNORM 218 false, // BC2_UNORM 219 false, // BC3_UNORM 220 false, // BC4_UNORM 221 false, // BC5_UNORM 222 false, // BC7_UNORM 223 false, // BC6H_FLOAT 224 false, // BC6H_UFLOAT 225 true, // R8_SNORM 226 true, // R8G8_SNORM 227 true, // R8G8B8A8_SNORM 228 true, // R16_SNORM 229 true, // R16G16_SNORM 230 true, // R16G16B16A16_SNORM 231 true, // R16_FLOAT 232 true, // R16G16_FLOAT 233 true, // R16G16B16A16_FLOAT 234 true, // R32_FLOAT 235 true, // R32G32_FLOAT 236 true, // R32G32B32A32_FLOAT 237 true, // R11G11B10_UFLOAT 238 true, // R8_UINT 239 true, // R8G8_UINT 240 true, // R8G8B8A8_UINT 241 true, // R16_UINT 242 true, // R16G16_UINT 243 true, // R16G16B16A16_UINT 244 true, // R32_UINT 245 true, // R32G32_UINT 246 true, // R32G32B32A32_UINT 247 true, // R8_INT 248 true, // R8G8_INT 249 true, // R8G8B8A8_INT 250 true, // R16_INT 251 true, // R16G16_INT 252 true, // R16G16B16A16_INT 253 true, // R32_INT 254 true, // R32G32_INT 255 true, // R32G32B32A32_INT 256 false, // R8G8B8A8_UNORM_SRGB 257 false, // B8G8R8A8_UNORM_SRGB 258 false, // BC1_UNORM_SRGB 259 false, // BC3_UNORM_SRGB 260 false, // BC3_UNORM_SRGB 261 false, // BC7_UNORM_SRGB 262 false, // D16_UNORM 263 false, // D24_UNORM 264 false, // D32_FLOAT 265 false, // D24_UNORM_S8_UINT 266 false, // D32_FLOAT_S8_UINT 267 false, // ASTC_4x4_UNORM 268 false, // ASTC_5x4_UNORM 269 false, // ASTC_5x5_UNORM 270 false, // ASTC_6x5_UNORM 271 false, // ASTC_6x6_UNORM 272 false, // ASTC_8x5_UNORM 273 false, // ASTC_8x6_UNORM 274 false, // ASTC_8x8_UNORM 275 false, // ASTC_10x5_UNORM 276 false, // ASTC_10x6_UNORM 277 false, // ASTC_10x8_UNORM 278 false, // ASTC_10x10_UNORM 279 false, // ASTC_12x10_UNORM 280 false, // ASTC_12x12_UNORM 281 false, // ASTC_4x4_UNORM_SRGB 282 false, // ASTC_5x4_UNORM_SRGB 283 false, // ASTC_5x5_UNORM_SRGB 284 false, // ASTC_6x5_UNORM_SRGB 285 false, // ASTC_6x6_UNORM_SRGB 286 false, // ASTC_8x5_UNORM_SRGB 287 false, // ASTC_8x6_UNORM_SRGB 288 false, // ASTC_8x8_UNORM_SRGB 289 false, // ASTC_10x5_UNORM_SRGB 290 false, // ASTC_10x6_UNORM_SRGB 291 false, // ASTC_10x8_UNORM_SRGB 292 false, // ASTC_10x10_UNORM_SRGB 293 false, // ASTC_12x10_UNORM_SRGB 294 false, // ASTC_12x12_UNORM_SRGB 295 false, // ASTC_4x4_FLOAT 296 false, // ASTC_5x4_FLOAT 297 false, // ASTC_5x5_FLOAT 298 false, // ASTC_6x5_FLOAT 299 false, // ASTC_6x6_FLOAT 300 false, // ASTC_8x5_FLOAT 301 false, // ASTC_8x6_FLOAT 302 false, // ASTC_8x8_FLOAT 303 false, // ASTC_10x5_FLOAT 304 false, // ASTC_10x6_FLOAT 305 false, // ASTC_10x8_FLOAT 306 false, // ASTC_10x10_FLOAT 307 false, // ASTC_12x10_FLOAT 308 false // ASTC_12x12_FLOAT 309}; 310 311// Drivers 312 313#ifndef SDL_GPU_DISABLED 314static const SDL_GPUBootstrap *backends[] = { 315#ifdef SDL_GPU_PRIVATE 316 &PrivateGPUDriver, 317#endif 318#ifdef SDL_GPU_METAL 319 &MetalDriver, 320#endif 321#ifdef SDL_GPU_D3D12 322 &D3D12Driver, 323#endif 324#ifdef SDL_GPU_VULKAN 325 &VulkanDriver, 326#endif 327 NULL 328}; 329#endif // !SDL_GPU_DISABLED 330 331// Internal Utility Functions 332 333SDL_GPUGraphicsPipeline *SDL_GPU_FetchBlitPipeline( 334 SDL_GPUDevice *device, 335 SDL_GPUTextureType source_texture_type, 336 SDL_GPUTextureFormat destination_format, 337 SDL_GPUShader *blit_vertex_shader, 338 SDL_GPUShader *blit_from_2d_shader, 339 SDL_GPUShader *blit_from_2d_array_shader, 340 SDL_GPUShader *blit_from_3d_shader, 341 SDL_GPUShader *blit_from_cube_shader, 342 SDL_GPUShader *blit_from_cube_array_shader, 343 BlitPipelineCacheEntry **blit_pipelines, 344 Uint32 *blit_pipeline_count, 345 Uint32 *blit_pipeline_capacity) 346{ 347 SDL_GPUGraphicsPipelineCreateInfo blit_pipeline_create_info; 348 SDL_GPUColorTargetDescription color_target_desc; 349 SDL_GPUGraphicsPipeline *pipeline; 350 351 if (blit_pipeline_count == NULL) { 352 // use pre-created, format-agnostic pipelines 353 return (*blit_pipelines)[source_texture_type].pipeline; 354 } 355 356 for (Uint32 i = 0; i < *blit_pipeline_count; i += 1) { 357 if ((*blit_pipelines)[i].type == source_texture_type && (*blit_pipelines)[i].format == destination_format) { 358 return (*blit_pipelines)[i].pipeline; 359 } 360 } 361 362 // No pipeline found, we'll need to make one! 363 SDL_zero(blit_pipeline_create_info); 364 365 SDL_zero(color_target_desc); 366 color_target_desc.blend_state.color_write_mask = 0xF; 367 color_target_desc.format = destination_format; 368 369 blit_pipeline_create_info.target_info.color_target_descriptions = &color_target_desc; 370 blit_pipeline_create_info.target_info.num_color_targets = 1; 371 blit_pipeline_create_info.target_info.depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D16_UNORM; // arbitrary 372 blit_pipeline_create_info.target_info.has_depth_stencil_target = false; 373 374 blit_pipeline_create_info.vertex_shader = blit_vertex_shader; 375 if (source_texture_type == SDL_GPU_TEXTURETYPE_CUBE) { 376 blit_pipeline_create_info.fragment_shader = blit_from_cube_shader; 377 } else if (source_texture_type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) { 378 blit_pipeline_create_info.fragment_shader = blit_from_cube_array_shader; 379 } else if (source_texture_type == SDL_GPU_TEXTURETYPE_2D_ARRAY) { 380 blit_pipeline_create_info.fragment_shader = blit_from_2d_array_shader; 381 } else if (source_texture_type == SDL_GPU_TEXTURETYPE_3D) { 382 blit_pipeline_create_info.fragment_shader = blit_from_3d_shader; 383 } else { 384 blit_pipeline_create_info.fragment_shader = blit_from_2d_shader; 385 } 386 blit_pipeline_create_info.rasterizer_state.enable_depth_clip = device->default_enable_depth_clip; 387 388 blit_pipeline_create_info.multisample_state.sample_count = SDL_GPU_SAMPLECOUNT_1; 389 blit_pipeline_create_info.multisample_state.enable_mask = false; 390 391 blit_pipeline_create_info.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST; 392 393 pipeline = SDL_CreateGPUGraphicsPipeline( 394 device, 395 &blit_pipeline_create_info); 396 397 if (pipeline == NULL) { 398 SDL_SetError("Failed to create GPU pipeline for blit"); 399 return NULL; 400 } 401 402 // Cache the new pipeline 403 EXPAND_ARRAY_IF_NEEDED( 404 (*blit_pipelines), 405 BlitPipelineCacheEntry, 406 *blit_pipeline_count + 1, 407 *blit_pipeline_capacity, 408 *blit_pipeline_capacity * 2); 409 410 (*blit_pipelines)[*blit_pipeline_count].pipeline = pipeline; 411 (*blit_pipelines)[*blit_pipeline_count].type = source_texture_type; 412 (*blit_pipelines)[*blit_pipeline_count].format = destination_format; 413 *blit_pipeline_count += 1; 414 415 return pipeline; 416} 417 418void SDL_GPU_BlitCommon( 419 SDL_GPUCommandBuffer *command_buffer, 420 const SDL_GPUBlitInfo *info, 421 SDL_GPUSampler *blit_linear_sampler, 422 SDL_GPUSampler *blit_nearest_sampler, 423 SDL_GPUShader *blit_vertex_shader, 424 SDL_GPUShader *blit_from_2d_shader, 425 SDL_GPUShader *blit_from_2d_array_shader, 426 SDL_GPUShader *blit_from_3d_shader, 427 SDL_GPUShader *blit_from_cube_shader, 428 SDL_GPUShader *blit_from_cube_array_shader, 429 BlitPipelineCacheEntry **blit_pipelines, 430 Uint32 *blit_pipeline_count, 431 Uint32 *blit_pipeline_capacity) 432{ 433 CommandBufferCommonHeader *cmdbufHeader = (CommandBufferCommonHeader *)command_buffer; 434 SDL_GPURenderPass *render_pass; 435 TextureCommonHeader *src_header = (TextureCommonHeader *)info->source.texture; 436 TextureCommonHeader *dst_header = (TextureCommonHeader *)info->destination.texture; 437 SDL_GPUGraphicsPipeline *blit_pipeline; 438 SDL_GPUColorTargetInfo color_target_info; 439 SDL_GPUViewport viewport; 440 SDL_GPUTextureSamplerBinding texture_sampler_binding; 441 BlitFragmentUniforms blit_fragment_uniforms; 442 Uint32 layer_divisor; 443 444 blit_pipeline = SDL_GPU_FetchBlitPipeline( 445 cmdbufHeader->device, 446 src_header->info.type, 447 dst_header->info.format, 448 blit_vertex_shader, 449 blit_from_2d_shader, 450 blit_from_2d_array_shader, 451 blit_from_3d_shader, 452 blit_from_cube_shader, 453 blit_from_cube_array_shader, 454 blit_pipelines, 455 blit_pipeline_count, 456 blit_pipeline_capacity); 457 458 SDL_assert(blit_pipeline != NULL); 459 460 color_target_info.load_op = info->load_op; 461 color_target_info.clear_color = info->clear_color; 462 color_target_info.store_op = SDL_GPU_STOREOP_STORE; 463 464 color_target_info.texture = info->destination.texture; 465 color_target_info.mip_level = info->destination.mip_level; 466 color_target_info.layer_or_depth_plane = info->destination.layer_or_depth_plane; 467 color_target_info.cycle = info->cycle; 468 469 render_pass = SDL_BeginGPURenderPass( 470 command_buffer, 471 &color_target_info, 472 1, 473 NULL); 474 475 viewport.x = (float)info->destination.x; 476 viewport.y = (float)info->destination.y; 477 viewport.w = (float)info->destination.w; 478 viewport.h = (float)info->destination.h; 479 viewport.min_depth = 0; 480 viewport.max_depth = 1; 481 482 SDL_SetGPUViewport( 483 render_pass, 484 &viewport); 485 486 SDL_BindGPUGraphicsPipeline( 487 render_pass, 488 blit_pipeline); 489 490 texture_sampler_binding.texture = info->source.texture; 491 texture_sampler_binding.sampler = 492 info->filter == SDL_GPU_FILTER_NEAREST ? blit_nearest_sampler : blit_linear_sampler; 493 494 SDL_BindGPUFragmentSamplers( 495 render_pass, 496 0, 497 &texture_sampler_binding, 498 1); 499 500 blit_fragment_uniforms.left = (float)info->source.x / (src_header->info.width >> info->source.mip_level); 501 blit_fragment_uniforms.top = (float)info->source.y / (src_header->info.height >> info->source.mip_level); 502 blit_fragment_uniforms.width = (float)info->source.w / (src_header->info.width >> info->source.mip_level); 503 blit_fragment_uniforms.height = (float)info->source.h / (src_header->info.height >> info->source.mip_level); 504 blit_fragment_uniforms.mip_level = info->source.mip_level; 505 506 layer_divisor = (src_header->info.type == SDL_GPU_TEXTURETYPE_3D) ? src_header->info.layer_count_or_depth : 1; 507 blit_fragment_uniforms.layer_or_depth = (float)info->source.layer_or_depth_plane / layer_divisor; 508 509 if (info->flip_mode & SDL_FLIP_HORIZONTAL) { 510 blit_fragment_uniforms.left += blit_fragment_uniforms.width; 511 blit_fragment_uniforms.width *= -1; 512 } 513 514 if (info->flip_mode & SDL_FLIP_VERTICAL) { 515 blit_fragment_uniforms.top += blit_fragment_uniforms.height; 516 blit_fragment_uniforms.height *= -1; 517 } 518 519 SDL_PushGPUFragmentUniformData( 520 command_buffer, 521 0, 522 &blit_fragment_uniforms, 523 sizeof(blit_fragment_uniforms)); 524 525 SDL_DrawGPUPrimitives(render_pass, 3, 1, 0, 0); 526 SDL_EndGPURenderPass(render_pass); 527} 528 529static void SDL_GPU_CheckGraphicsBindings(SDL_GPURenderPass *render_pass) 530{ 531 RenderPass *rp = (RenderPass *)render_pass; 532 GraphicsPipelineCommonHeader *pipeline = (GraphicsPipelineCommonHeader *)RENDERPASS_BOUND_PIPELINE; 533 for (Uint32 i = 0; i < pipeline->num_vertex_samplers; i += 1) { 534 if (!rp->vertex_sampler_bound[i]) { 535 SDL_assert_release(!"Missing vertex sampler binding!"); 536 } 537 } 538 for (Uint32 i = 0; i < pipeline->num_vertex_storage_textures; i += 1) { 539 if (!rp->vertex_storage_texture_bound[i]) { 540 SDL_assert_release(!"Missing vertex storage texture binding!"); 541 } 542 } 543 for (Uint32 i = 0; i < pipeline->num_vertex_storage_buffers; i += 1) { 544 if (!rp->vertex_storage_buffer_bound[i]) { 545 SDL_assert_release(!"Missing vertex storage buffer binding!"); 546 } 547 } 548 for (Uint32 i = 0; i < pipeline->num_fragment_samplers; i += 1) { 549 if (!rp->fragment_sampler_bound[i]) { 550 SDL_assert_release(!"Missing fragment sampler binding!"); 551 } 552 } 553 for (Uint32 i = 0; i < pipeline->num_fragment_storage_textures; i += 1) { 554 if (!rp->fragment_storage_texture_bound[i]) { 555 SDL_assert_release(!"Missing fragment storage texture binding!"); 556 } 557 } 558 for (Uint32 i = 0; i < pipeline->num_fragment_storage_buffers; i += 1) { 559 if (!rp->fragment_storage_buffer_bound[i]) { 560 SDL_assert_release(!"Missing fragment storage buffer binding!"); 561 } 562 } 563} 564 565static void SDL_GPU_CheckComputeBindings(SDL_GPUComputePass *compute_pass) 566{ 567 ComputePass *cp = (ComputePass *)compute_pass; 568 ComputePipelineCommonHeader *pipeline = (ComputePipelineCommonHeader *)COMPUTEPASS_BOUND_PIPELINE; 569 for (Uint32 i = 0; i < pipeline->numSamplers; i += 1) { 570 if (!cp->sampler_bound[i]) { 571 SDL_assert_release(!"Missing compute sampler binding!"); 572 } 573 } 574 for (Uint32 i = 0; i < pipeline->numReadonlyStorageTextures; i += 1) { 575 if (!cp->read_only_storage_texture_bound[i]) { 576 SDL_assert_release(!"Missing compute readonly storage texture binding!"); 577 } 578 } 579 for (Uint32 i = 0; i < pipeline->numReadonlyStorageBuffers; i += 1) { 580 if (!cp->read_only_storage_buffer_bound[i]) { 581 SDL_assert_release(!"Missing compute readonly storage buffer binding!"); 582 } 583 } 584 for (Uint32 i = 0; i < pipeline->numReadWriteStorageTextures; i += 1) { 585 if (!cp->read_write_storage_texture_bound[i]) { 586 SDL_assert_release(!"Missing compute read-write storage texture binding!"); 587 } 588 } 589 for (Uint32 i = 0; i < pipeline->numReadWriteStorageBuffers; i += 1) { 590 if (!cp->read_write_storage_buffer_bound[i]) { 591 SDL_assert_release(!"Missing compute read-write storage buffer bbinding!"); 592 } 593 } 594} 595 596// Driver Functions 597 598#ifndef SDL_GPU_DISABLED 599static const SDL_GPUBootstrap * SDL_GPUSelectBackend(SDL_PropertiesID props) 600{ 601 Uint32 i; 602 const char *gpudriver; 603 SDL_VideoDevice *_this = SDL_GetVideoDevice(); 604 605 if (_this == NULL) { 606 SDL_SetError("Video subsystem not initialized"); 607 return NULL; 608 } 609 610 gpudriver = SDL_GetHint(SDL_HINT_GPU_DRIVER); 611 if (gpudriver == NULL) { 612 gpudriver = SDL_GetStringProperty(props, SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING, NULL); 613 } 614 615 // Environment/Properties override... 616 if (gpudriver != NULL) { 617 for (i = 0; backends[i]; i += 1) { 618 if (SDL_strcasecmp(gpudriver, backends[i]->name) == 0) { 619 if (backends[i]->PrepareDriver(_this, props)) { 620 return backends[i]; 621 } 622 } 623 } 624 625 SDL_SetError("SDL_HINT_GPU_DRIVER %s unsupported!", gpudriver); 626 return NULL; 627 } 628 629 for (i = 0; backends[i]; i += 1) { 630 if (backends[i]->PrepareDriver(_this, props)) { 631 return backends[i]; 632 } 633 } 634 635 SDL_SetError("No supported SDL_GPU backend found!"); 636 return NULL; 637} 638 639static void SDL_GPU_FillProperties( 640 SDL_PropertiesID props, 641 SDL_GPUShaderFormat format_flags, 642 bool debug_mode, 643 const char *name) 644{ 645 if (format_flags & SDL_GPU_SHADERFORMAT_PRIVATE) { 646 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOLEAN, true); 647 } 648 if (format_flags & SDL_GPU_SHADERFORMAT_SPIRV) { 649 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN, true); 650 } 651 if (format_flags & SDL_GPU_SHADERFORMAT_DXBC) { 652 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOLEAN, true); 653 } 654 if (format_flags & SDL_GPU_SHADERFORMAT_DXIL) { 655 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN, true); 656 } 657 if (format_flags & SDL_GPU_SHADERFORMAT_MSL) { 658 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN, true); 659 } 660 if (format_flags & SDL_GPU_SHADERFORMAT_METALLIB) { 661 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN, true); 662 } 663 SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN, debug_mode); 664 SDL_SetStringProperty(props, SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING, name); 665} 666#endif // SDL_GPU_DISABLED 667 668bool SDL_GPUSupportsShaderFormats( 669 SDL_GPUShaderFormat format_flags, 670 const char *name) 671{ 672#ifndef SDL_GPU_DISABLED 673 bool result; 674 SDL_PropertiesID props = SDL_CreateProperties(); 675 SDL_GPU_FillProperties(props, format_flags, false, name); 676 result = SDL_GPUSupportsProperties(props); 677 SDL_DestroyProperties(props); 678 return result; 679#else 680 SDL_SetError("SDL not built with GPU support"); 681 return false; 682#endif 683} 684 685bool SDL_GPUSupportsProperties(SDL_PropertiesID props) 686{ 687#ifndef SDL_GPU_DISABLED 688 return (SDL_GPUSelectBackend(props) != NULL); 689#else 690 SDL_SetError("SDL not built with GPU support"); 691 return false; 692#endif 693} 694 695SDL_GPUDevice *SDL_CreateGPUDevice( 696 SDL_GPUShaderFormat format_flags, 697 bool debug_mode, 698 const char *name) 699{ 700#ifndef SDL_GPU_DISABLED 701 SDL_GPUDevice *result; 702 SDL_PropertiesID props = SDL_CreateProperties(); 703 SDL_GPU_FillProperties(props, format_flags, debug_mode, name); 704 result = SDL_CreateGPUDeviceWithProperties(props); 705 SDL_DestroyProperties(props); 706 return result; 707#else 708 SDL_SetError("SDL not built with GPU support"); 709 return NULL; 710#endif // SDL_GPU_DISABLED 711} 712 713SDL_GPUDevice *SDL_CreateGPUDeviceWithProperties(SDL_PropertiesID props) 714{ 715#ifndef SDL_GPU_DISABLED 716 bool debug_mode; 717 bool preferLowPower; 718 SDL_GPUDevice *result = NULL; 719 const SDL_GPUBootstrap *selectedBackend; 720 721 selectedBackend = SDL_GPUSelectBackend(props); 722 if (selectedBackend != NULL) { 723 SDL_DebugLogBackend("gpu", selectedBackend->name); 724 debug_mode = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN, true); 725 preferLowPower = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN, false); 726 727 result = selectedBackend->CreateDevice(debug_mode, preferLowPower, props); 728 if (result != NULL) { 729 result->backend = selectedBackend->name; 730 result->debug_mode = debug_mode; 731 if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_FEATURE_DEPTH_CLAMPING_BOOLEAN, true)) { 732 result->default_enable_depth_clip = false; 733 } else { 734 result->default_enable_depth_clip = true; 735 result->validate_feature_depth_clamp_disabled = true; 736 } 737 if (!SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_FEATURE_ANISOTROPY_BOOLEAN, true)) { 738 result->validate_feature_anisotropy_disabled = true; 739 } 740 } 741 } 742 return result; 743#else 744 SDL_SetError("SDL not built with GPU support"); 745 return NULL; 746#endif // SDL_GPU_DISABLED 747} 748 749void SDL_DestroyGPUDevice(SDL_GPUDevice *device) 750{ 751 CHECK_DEVICE_MAGIC(device, ); 752 device->DestroyDevice(device); 753} 754 755int SDL_GetNumGPUDrivers(void) 756{ 757#ifndef SDL_GPU_DISABLED 758 return SDL_arraysize(backends) - 1; 759#else 760 return 0; 761#endif 762} 763 764const char * SDL_GetGPUDriver(int index) 765{ 766 CHECK_PARAM(index < 0 || index >= SDL_GetNumGPUDrivers()) { 767 SDL_InvalidParamError("index"); 768 return NULL; 769 } 770#ifndef SDL_GPU_DISABLED 771 return backends[index]->name; 772#else 773 return NULL; 774#endif 775} 776 777const char * SDL_GetGPUDeviceDriver(SDL_GPUDevice *device) 778{ 779 CHECK_DEVICE_MAGIC(device, NULL); 780 return device->backend; 781} 782 783SDL_GPUShaderFormat SDL_GetGPUShaderFormats(SDL_GPUDevice *device) 784{ 785 CHECK_DEVICE_MAGIC(device, SDL_GPU_SHADERFORMAT_INVALID); 786 return device->shader_formats; 787} 788 789SDL_PropertiesID SDL_GetGPUDeviceProperties(SDL_GPUDevice *device) 790{ 791 CHECK_DEVICE_MAGIC(device, 0); 792 return device->GetDeviceProperties(device); 793} 794 795Uint32 SDL_GPUTextureFormatTexelBlockSize( 796 SDL_GPUTextureFormat format) 797{ 798 switch (format) { 799 case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM: 800 case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB: 801 case SDL_GPU_TEXTUREFORMAT_BC4_R_UNORM: 802 return 8; 803 case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM: 804 case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM: 805 case SDL_GPU_TEXTUREFORMAT_BC5_RG_UNORM: 806 case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM: 807 case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT: 808 case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT: 809 case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB: 810 case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB: 811 case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB: 812 return 16; 813 case SDL_GPU_TEXTUREFORMAT_R8_UNORM: 814 case SDL_GPU_TEXTUREFORMAT_R8_SNORM: 815 case SDL_GPU_TEXTUREFORMAT_A8_UNORM: 816 case SDL_GPU_TEXTUREFORMAT_R8_UINT: 817 case SDL_GPU_TEXTUREFORMAT_R8_INT: 818 return 1; 819 case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM: 820 case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM: 821 case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM: 822 case SDL_GPU_TEXTUREFORMAT_R16_FLOAT: 823 case SDL_GPU_TEXTUREFORMAT_R8G8_SNORM: 824 case SDL_GPU_TEXTUREFORMAT_R8G8_UNORM: 825 case SDL_GPU_TEXTUREFORMAT_R8G8_UINT: 826 case SDL_GPU_TEXTUREFORMAT_R8G8_INT: 827 case SDL_GPU_TEXTUREFORMAT_R16_UNORM: 828 case SDL_GPU_TEXTUREFORMAT_R16_SNORM: 829 case SDL_GPU_TEXTUREFORMAT_R16_UINT: 830 case SDL_GPU_TEXTUREFORMAT_R16_INT: 831 case SDL_GPU_TEXTUREFORMAT_D16_UNORM: 832 return 2; 833 case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM: 834 case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM: 835 case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB: 836 case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB: 837 case SDL_GPU_TEXTUREFORMAT_R32_FLOAT: 838 case SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT: 839 case SDL_GPU_TEXTUREFORMAT_R11G11B10_UFLOAT: 840 case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM: 841 case SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM: 842 case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT: 843 case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_INT: 844 case SDL_GPU_TEXTUREFORMAT_R16G16_UINT: 845 case SDL_GPU_TEXTUREFORMAT_R16G16_INT: 846 case SDL_GPU_TEXTUREFORMAT_R16G16_UNORM: 847 case SDL_GPU_TEXTUREFORMAT_R16G16_SNORM: 848 case SDL_GPU_TEXTUREFORMAT_D24_UNORM: 849 case SDL_GPU_TEXTUREFORMAT_D32_FLOAT: 850 case SDL_GPU_TEXTUREFORMAT_R32_UINT: 851 case SDL_GPU_TEXTUREFORMAT_R32_INT: 852 case SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT: 853 return 4; 854 case SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT: 855 return 5; 856 case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT: 857 case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM: 858 case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_SNORM: 859 case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT: 860 case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_INT: 861 case SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT: 862 case SDL_GPU_TEXTUREFORMAT_R32G32_UINT: 863 case SDL_GPU_TEXTUREFORMAT_R32G32_INT: 864 return 8; 865 case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT: 866 case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_INT: 867 case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_UINT: 868 return 16; 869 case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM: 870 case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM: 871 case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM: 872 case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM: 873 case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM: 874 case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM: 875 case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM: 876 case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM: 877 case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM: 878 case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM: 879 case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM: 880 case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM: 881 case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM: 882 case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM: 883 case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_UNORM_SRGB: 884 case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_UNORM_SRGB: 885 case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_UNORM_SRGB: 886 case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_UNORM_SRGB: 887 case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_UNORM_SRGB: 888 case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_UNORM_SRGB: 889 case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_UNORM_SRGB: 890 case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_UNORM_SRGB: 891 case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_UNORM_SRGB: 892 case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_UNORM_SRGB: 893 case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_UNORM_SRGB: 894 case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_UNORM_SRGB: 895 case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_UNORM_SRGB: 896 case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_UNORM_SRGB: 897 case SDL_GPU_TEXTUREFORMAT_ASTC_4x4_FLOAT: 898 case SDL_GPU_TEXTUREFORMAT_ASTC_5x4_FLOAT: 899 case SDL_GPU_TEXTUREFORMAT_ASTC_5x5_FLOAT: 900 case SDL_GPU_TEXTUREFORMAT_ASTC_6x5_FLOAT: 901 case SDL_GPU_TEXTUREFORMAT_ASTC_6x6_FLOAT: 902 case SDL_GPU_TEXTUREFORMAT_ASTC_8x5_FLOAT: 903 case SDL_GPU_TEXTUREFORMAT_ASTC_8x6_FLOAT: 904 case SDL_GPU_TEXTUREFORMAT_ASTC_8x8_FLOAT: 905 case SDL_GPU_TEXTUREFORMAT_ASTC_10x5_FLOAT: 906 case SDL_GPU_TEXTUREFORMAT_ASTC_10x6_FLOAT: 907 case SDL_GPU_TEXTUREFORMAT_ASTC_10x8_FLOAT: 908 case SDL_GPU_TEXTUREFORMAT_ASTC_10x10_FLOAT: 909 case SDL_GPU_TEXTUREFORMAT_ASTC_12x10_FLOAT: 910 case SDL_GPU_TEXTUREFORMAT_ASTC_12x12_FLOAT: 911 return 16; 912 default: 913 SDL_assert_release(!"Unrecognized TextureFormat!"); 914 return 0; 915 } 916} 917 918bool SDL_GPUTextureSupportsFormat( 919 SDL_GPUDevice *device, 920 SDL_GPUTextureFormat format, 921 SDL_GPUTextureType type, 922 SDL_GPUTextureUsageFlags usage) 923{ 924 CHECK_DEVICE_MAGIC(device, false); 925 926 if (device->debug_mode) { 927 CHECK_TEXTUREFORMAT_ENUM_INVALID(format, false) 928 } 929 930 if ((usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) || 931 (usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE)) { 932 if (!TextureFormatIsComputeWritable[format]) { 933 return false; 934 } 935 } 936 937 return device->SupportsTextureFormat( 938 device->driverData, 939 format, 940 type, 941 usage); 942} 943 944bool SDL_GPUTextureSupportsSampleCount( 945 SDL_GPUDevice *device, 946 SDL_GPUTextureFormat format, 947 SDL_GPUSampleCount sample_count) 948{ 949 CHECK_DEVICE_MAGIC(device, 0); 950 951 if (device->debug_mode) { 952 CHECK_TEXTUREFORMAT_ENUM_INVALID(format, 0) 953 } 954 955 return device->SupportsSampleCount( 956 device->driverData, 957 format, 958 sample_count); 959} 960 961// State Creation 962 963SDL_GPUComputePipeline *SDL_CreateGPUComputePipeline( 964 SDL_GPUDevice *device, 965 const SDL_GPUComputePipelineCreateInfo *createinfo) 966{ 967 CHECK_DEVICE_MAGIC(device, NULL); 968 969 if (createinfo == NULL) { 970 SDL_InvalidParamError("createinfo"); 971 return NULL; 972 } 973 974 if (device->debug_mode) { 975 if (createinfo->format == SDL_GPU_SHADERFORMAT_INVALID) { 976 SDL_assert_release(!"Shader format cannot be INVALID!"); 977 return NULL; 978 } 979 if (!(createinfo->format & device->shader_formats)) { 980 SDL_assert_release(!"Incompatible shader format for GPU backend"); 981 return NULL; 982 } 983 if (createinfo->num_readwrite_storage_textures > MAX_COMPUTE_WRITE_TEXTURES) { 984 SDL_COMPILE_TIME_ASSERT(compute_write_textures, MAX_COMPUTE_WRITE_TEXTURES == 8); 985 SDL_assert_release(!"Compute pipeline write-only texture count cannot be higher than 8!"); 986 return NULL; 987 } 988 if (createinfo->num_readwrite_storage_buffers > MAX_COMPUTE_WRITE_BUFFERS) { 989 SDL_COMPILE_TIME_ASSERT(compute_write_buffers, MAX_COMPUTE_WRITE_BUFFERS == 8); 990 SDL_assert_release(!"Compute pipeline write-only buffer count cannot be higher than 8!"); 991 return NULL; 992 } 993 if (createinfo->num_samplers > MAX_TEXTURE_SAMPLERS_PER_STAGE) { 994 SDL_COMPILE_TIME_ASSERT(compute_texture_samplers, MAX_TEXTURE_SAMPLERS_PER_STAGE == 16); 995 SDL_assert_release(!"Compute pipeline sampler count cannot be higher than 16!"); 996 return NULL; 997 } 998 if (createinfo->num_readonly_storage_textures > MAX_STORAGE_TEXTURES_PER_STAGE) { 999 SDL_COMPILE_TIME_ASSERT(compute_storage_textures, MAX_STORAGE_TEXTURES_PER_STAGE == 8); 1000 SDL_assert_release(!"Compute pipeline readonly storage texture count cannot be higher than 8!"); 1001 return NULL; 1002 } 1003 if (createinfo->num_readonly_storage_buffers > MAX_STORAGE_BUFFERS_PER_STAGE) { 1004 SDL_COMPILE_TIME_ASSERT(compute_storage_buffers, MAX_STORAGE_BUFFERS_PER_STAGE == 8); 1005 SDL_assert_release(!"Compute pipeline readonly storage buffer count cannot be higher than 8!"); 1006 return NULL; 1007 } 1008 if (createinfo->num_uniform_buffers > MAX_UNIFORM_BUFFERS_PER_STAGE) { 1009 SDL_COMPILE_TIME_ASSERT(compute_uniform_buffers, MAX_UNIFORM_BUFFERS_PER_STAGE == 4); 1010 SDL_assert_release(!"Compute pipeline uniform buffer count cannot be higher than 4!"); 1011 return NULL; 1012 } 1013 if (createinfo->threadcount_x == 0 || 1014 createinfo->threadcount_y == 0 || 1015 createinfo->threadcount_z == 0) { 1016 SDL_assert_release(!"Compute pipeline threadCount dimensions must be at least 1!"); 1017 return NULL; 1018 } 1019 } 1020 1021 return device->CreateComputePipeline( 1022 device->driverData, 1023 createinfo); 1024} 1025 1026SDL_GPUGraphicsPipeline *SDL_CreateGPUGraphicsPipeline( 1027 SDL_GPUDevice *device, 1028 const SDL_GPUGraphicsPipelineCreateInfo *graphicsPipelineCreateInfo) 1029{ 1030 CHECK_DEVICE_MAGIC(device, NULL); 1031 1032 CHECK_PARAM(graphicsPipelineCreateInfo == NULL) { 1033 SDL_InvalidParamError("graphicsPipelineCreateInfo"); 1034 return NULL; 1035 } 1036 1037 if (device->debug_mode) { 1038 if (graphicsPipelineCreateInfo->vertex_shader == NULL) { 1039 SDL_assert_release(!"Vertex shader cannot be NULL!"); 1040 return NULL; 1041 } 1042 if (graphicsPipelineCreateInfo->fragment_shader == NULL) { 1043 SDL_assert_release(!"Fragment shader cannot be NULL!"); 1044 return NULL; 1045 } 1046 if (graphicsPipelineCreateInfo->target_info.num_color_targets > 0 && graphicsPipelineCreateInfo->target_info.color_target_descriptions == NULL) { 1047 SDL_assert_release(!"Color target descriptions array pointer cannot be NULL if num_color_targets is greater than zero!"); 1048 return NULL; 1049 } 1050 for (Uint32 i = 0; i < graphicsPipelineCreateInfo->target_info.num_color_targets; i += 1) { 1051 CHECK_TEXTUREFORMAT_ENUM_INVALID(graphicsPipelineCreateInfo->target_info.color_target_descriptions[i].format, NULL); 1052 if (IsDepthFormat(graphicsPipelineCreateInfo->target_info.color_target_descriptions[i].format)) { 1053 SDL_assert_release(!"Color target formats cannot be a depth format!"); 1054 return NULL; 1055 } 1056 if (!SDL_GPUTextureSupportsFormat(device, graphicsPipelineCreateInfo->target_info.color_target_descriptions[i].format, SDL_GPU_TEXTURETYPE_2D, SDL_GPU_TEXTUREUSAGE_COLOR_TARGET)) { 1057 SDL_assert_release(!"Format is not supported for color targets on this device!"); 1058 return NULL; 1059 } 1060 if (graphicsPipelineCreateInfo->target_info.color_target_descriptions[i].blend_state.enable_blend) { 1061 const SDL_GPUColorTargetBlendState *blend_state = &graphicsPipelineCreateInfo->target_info.color_target_descriptions[i].blend_state; 1062 CHECK_BLENDFACTOR_ENUM_INVALID(blend_state->src_color_blendfactor, NULL) 1063 CHECK_BLENDFACTOR_ENUM_INVALID(blend_state->dst_color_blendfactor, NULL) 1064 CHECK_BLENDOP_ENUM_INVALID(blend_state->color_blend_op, NULL) 1065 CHECK_BLENDFACTOR_ENUM_INVALID(blend_state->src_alpha_blendfactor, NULL) 1066 CHECK_BLENDFACTOR_ENUM_INVALID(blend_state->dst_alpha_blendfactor, NULL) 1067 CHECK_BLENDOP_ENUM_INVALID(blend_state->alpha_blend_op, NULL) 1068 1069 // TODO: validate that format support blending? 1070 } 1071 } 1072 if (graphicsPipelineCreateInfo->target_info.has_depth_stencil_target) { 1073 CHECK_TEXTUREFORMAT_ENUM_INVALID(graphicsPipelineCreateInfo->target_info.depth_stencil_format, NULL); 1074 if (!IsDepthFormat(graphicsPipelineCreateInfo->target_info.depth_stencil_format)) { 1075 SDL_assert_release(!"Depth-stencil target format must be a depth format!"); 1076 return NULL; 1077 } 1078 if (!SDL_GPUTextureSupportsFormat(device, graphicsPipelineCreateInfo->target_info.depth_stencil_format, SDL_GPU_TEXTURETYPE_2D, SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET)) { 1079 SDL_assert_release(!"Format is not supported for depth targets on this device!"); 1080 return NULL; 1081 } 1082 } 1083 if (graphicsPipelineCreateInfo->multisample_state.enable_alpha_to_coverage) { 1084 if (graphicsPipelineCreateInfo->target_info.num_color_targets < 1) { 1085 SDL_assert_release(!"Alpha-to-coverage enabled but no color targets present!"); 1086 return NULL; 1087 } 1088 if (!FormatHasAlpha(graphicsPipelineCreateInfo->target_info.color_target_descriptions[0].format)) { 1089 SDL_assert_release(!"Format is not compatible with alpha-to-coverage!"); 1090 return NULL; 1091 } 1092 1093 // TODO: validate that format supports belnding? This is only required on Metal. 1094 } 1095 if (graphicsPipelineCreateInfo->vertex_input_state.num_vertex_buffers > 0 && graphicsPipelineCreateInfo->vertex_input_state.vertex_buffer_descriptions == NULL) { 1096 SDL_assert_release(!"Vertex buffer descriptions array pointer cannot be NULL!"); 1097 return NULL; 1098 } 1099 if (graphicsPipelineCreateInfo->vertex_input_state.num_vertex_buffers > MAX_VERTEX_BUFFERS) { 1100 SDL_COMPILE_TIME_ASSERT(vertex_buffers, MAX_VERTEX_BUFFERS == 16); 1101 SDL_assert_release(!"The number of vertex buffer descriptions in a vertex input state must not exceed 16!"); 1102 return NULL; 1103 } 1104 if (graphicsPipelineCreateInfo->vertex_input_state.num_vertex_attributes > 0 && graphicsPipelineCreateInfo->vertex_input_state.vertex_attributes == NULL) { 1105 SDL_assert_release(!"Vertex attributes array pointer cannot be NULL!"); 1106 return NULL; 1107 } 1108 if (graphicsPipelineCreateInfo->vertex_input_state.num_vertex_attributes > MAX_VERTEX_ATTRIBUTES) { 1109 SDL_COMPILE_TIME_ASSERT(vertex_attributes, MAX_VERTEX_ATTRIBUTES == 16); 1110 SDL_assert_release(!"The number of vertex attributes in a vertex input state must not exceed 16!"); 1111 return NULL; 1112 } 1113 for (Uint32 i = 0; i < graphicsPipelineCreateInfo->vertex_input_state.num_vertex_buffers; i += 1) { 1114 if (graphicsPipelineCreateInfo->vertex_input_state.vertex_buffer_descriptions[i].instance_step_rate != 0) { 1115 SDL_assert_release(!"For all vertex buffer descriptions, instance_step_rate must be 0!"); 1116 return NULL; 1117 } 1118 } 1119 Uint32 locations[MAX_VERTEX_ATTRIBUTES]; 1120 for (Uint32 i = 0; i < graphicsPipelineCreateInfo->vertex_input_state.num_vertex_attributes; i += 1) { 1121 CHECK_VERTEXELEMENTFORMAT_ENUM_INVALID(graphicsPipelineCreateInfo->vertex_input_state.vertex_attributes[i].format, NULL); 1122 1123 locations[i] = graphicsPipelineCreateInfo->vertex_input_state.vertex_attributes[i].location; 1124 for (Uint32 j = 0; j < i; j += 1) { 1125 if (locations[j] == locations[i]) { 1126 SDL_assert_release(!"Each vertex attribute location in a vertex input state must be unique!"); 1127 return NULL; 1128 } 1129 } 1130 } 1131 if (graphicsPipelineCreateInfo->multisample_state.enable_mask) { 1132 SDL_assert_release(!"For multisample states, enable_mask must be false!"); 1133 return NULL; 1134 } 1135 if (graphicsPipelineCreateInfo->multisample_state.sample_mask != 0) { 1136 SDL_assert_release(!"For multisample states, sample_mask must be 0!"); 1137 return NULL; 1138 } 1139 if (graphicsPipelineCreateInfo->depth_stencil_state.enable_depth_test) { 1140 CHECK_COMPAREOP_ENUM_INVALID(graphicsPipelineCreateInfo->depth_stencil_state.compare_op, NULL) 1141 } 1142 if (graphicsPipelineCreateInfo->depth_stencil_state.enable_stencil_test) { 1143 const SDL_GPUStencilOpState *stencil_state = &graphicsPipelineCreateInfo->depth_stencil_state.back_stencil_state; 1144 CHECK_COMPAREOP_ENUM_INVALID(stencil_state->compare_op, NULL) 1145 CHECK_STENCILOP_ENUM_INVALID(stencil_state->fail_op, NULL) 1146 CHECK_STENCILOP_ENUM_INVALID(stencil_state->pass_op, NULL) 1147 CHECK_STENCILOP_ENUM_INVALID(stencil_state->depth_fail_op, NULL) 1148 } 1149 1150 if (device->validate_feature_depth_clamp_disabled && 1151 !graphicsPipelineCreateInfo->rasterizer_state.enable_depth_clip) { 1152 SDL_assert_release(!"Rasterizer state enable_depth_clip must be set to true (FEATURE_DEPTH_CLAMPING disabled)"); 1153 return NULL; 1154 } 1155 } 1156 1157 return device->CreateGraphicsPipeline( 1158 device->driverData, 1159 graphicsPipelineCreateInfo); 1160} 1161 1162SDL_GPUSampler *SDL_CreateGPUSampler( 1163 SDL_GPUDevice *device, 1164 const SDL_GPUSamplerCreateInfo *createinfo) 1165{ 1166 CHECK_DEVICE_MAGIC(device, NULL); 1167 1168 CHECK_PARAM(createinfo == NULL) { 1169 SDL_InvalidParamError("createinfo"); 1170 return NULL; 1171 } 1172 1173 if (device->debug_mode) { 1174 if (device->validate_feature_anisotropy_disabled && 1175 createinfo->enable_anisotropy) { 1176 SDL_assert_release(!"enable_anisotropy must be set to false (FEATURE_ANISOTROPY disabled)"); 1177 return NULL; 1178 } 1179 } 1180 1181 return device->CreateSampler( 1182 device->driverData, 1183 createinfo); 1184} 1185 1186SDL_GPUShader *SDL_CreateGPUShader( 1187 SDL_GPUDevice *device, 1188 const SDL_GPUShaderCreateInfo *createinfo) 1189{ 1190 CHECK_DEVICE_MAGIC(device, NULL); 1191 1192 CHECK_PARAM(createinfo == NULL) { 1193 SDL_InvalidParamError("createinfo"); 1194 return NULL; 1195 } 1196 1197 if (device->debug_mode) { 1198 if (createinfo->format == SDL_GPU_SHADERFORMAT_INVALID) { 1199 SDL_assert_release(!"Shader format cannot be INVALID!"); 1200 return NULL; 1201 } 1202 if (!(createinfo->format & device->shader_formats)) { 1203 SDL_assert_release(!"Incompatible shader format for GPU backend"); 1204 return NULL; 1205 } 1206 if (createinfo->num_samplers > MAX_TEXTURE_SAMPLERS_PER_STAGE) { 1207 SDL_COMPILE_TIME_ASSERT(shader_texture_samplers, MAX_TEXTURE_SAMPLERS_PER_STAGE == 16); 1208 SDL_assert_release(!"Shader sampler count cannot be higher than 16!"); 1209 return NULL; 1210 } 1211 if (createinfo->num_storage_textures > MAX_STORAGE_TEXTURES_PER_STAGE) { 1212 SDL_COMPILE_TIME_ASSERT(shader_storage_textures, MAX_STORAGE_TEXTURES_PER_STAGE == 8); 1213 SDL_assert_release(!"Shader storage texture count cannot be higher than 8!"); 1214 return NULL; 1215 } 1216 if (createinfo->num_storage_buffers > MAX_STORAGE_BUFFERS_PER_STAGE) { 1217 SDL_COMPILE_TIME_ASSERT(shader_storage_buffers, MAX_STORAGE_BUFFERS_PER_STAGE == 8); 1218 SDL_assert_release(!"Shader storage buffer count cannot be higher than 8!"); 1219 return NULL; 1220 } 1221 if (createinfo->num_uniform_buffers > MAX_UNIFORM_BUFFERS_PER_STAGE) { 1222 SDL_COMPILE_TIME_ASSERT(shader_uniform_buffers, MAX_UNIFORM_BUFFERS_PER_STAGE == 4); 1223 SDL_assert_release(!"Shader uniform buffer count cannot be higher than 4!"); 1224 return NULL; 1225 } 1226 } 1227 1228 return device->CreateShader( 1229 device->driverData, 1230 createinfo); 1231} 1232 1233SDL_GPUTexture *SDL_CreateGPUTexture( 1234 SDL_GPUDevice *device, 1235 const SDL_GPUTextureCreateInfo *createinfo) 1236{ 1237 CHECK_DEVICE_MAGIC(device, NULL); 1238 1239 CHECK_PARAM(createinfo == NULL) { 1240 SDL_InvalidParamError("createinfo"); 1241 return NULL; 1242 } 1243 1244 if (device->debug_mode) { 1245 bool failed = false; 1246 1247 const Uint32 MAX_2D_DIMENSION = 16384; 1248 const Uint32 MAX_3D_DIMENSION = 2048; 1249 1250 // Common checks for all texture types 1251 CHECK_TEXTUREFORMAT_ENUM_INVALID(createinfo->format, NULL) 1252 1253 if (createinfo->width <= 0 || createinfo->height <= 0 || createinfo->layer_count_or_depth <= 0) { 1254 SDL_assert_release(!"For any texture: width, height, and layer_count_or_depth must be >= 1"); 1255 failed = true; 1256 } 1257 if (createinfo->num_levels <= 0) { 1258 SDL_assert_release(!"For any texture: num_levels must be >= 1"); 1259 failed = true; 1260 } 1261 if ((createinfo->usage & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ) && (createinfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER)) { 1262 SDL_assert_release(!"For any texture: usage cannot contain both GRAPHICS_STORAGE_READ and SAMPLER"); 1263 failed = true; 1264 } 1265 if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1 && 1266 (createinfo->usage & (SDL_GPU_TEXTUREUSAGE_SAMPLER | 1267 SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ | 1268 SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ | 1269 SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE))) { 1270 SDL_assert_release(!"For multisample textures: usage cannot contain SAMPLER or STORAGE flags"); 1271 failed = true; 1272 } 1273 if (IsDepthFormat(createinfo->format) && (createinfo->usage & ~(SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER))) { 1274 SDL_assert_release(!"For depth textures: usage cannot contain any flags except for DEPTH_STENCIL_TARGET and SAMPLER"); 1275 failed = true; 1276 } 1277 if (IsIntegerFormat(createinfo->format) && (createinfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER)) { 1278 SDL_assert_release(!"For any texture: usage cannot contain SAMPLER for textures with an integer format"); 1279 failed = true; 1280 } 1281 1282 if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE) { 1283 // Cubemap validation 1284 if (createinfo->width != createinfo->height) { 1285 SDL_assert_release(!"For cube textures: width and height must be identical"); 1286 failed = true; 1287 } 1288 if (createinfo->width > MAX_2D_DIMENSION || createinfo->height > MAX_2D_DIMENSION) { 1289 SDL_assert_release(!"For cube textures: width and height must be <= 16384"); 1290 failed = true; 1291 } 1292 if (createinfo->layer_count_or_depth != 6) { 1293 SDL_assert_release(!"For cube textures: layer_count_or_depth must be 6"); 1294 failed = true; 1295 } 1296 if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) { 1297 SDL_assert_release(!"For cube textures: sample_count must be SDL_GPU_SAMPLECOUNT_1"); 1298 failed = true; 1299 } 1300 if (!SDL_GPUTextureSupportsFormat(device, createinfo->format, SDL_GPU_TEXTURETYPE_CUBE, createinfo->usage)) { 1301 SDL_assert_release(!"For cube textures: the format is unsupported for the given usage"); 1302 failed = true; 1303 } 1304 } else if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) { 1305 // Cubemap array validation 1306 if (createinfo->width != createinfo->height) { 1307 SDL_assert_release(!"For cube array textures: width and height must be identical"); 1308 failed = true; 1309 } 1310 if (createinfo->width > MAX_2D_DIMENSION || createinfo->height > MAX_2D_DIMENSION) { 1311 SDL_assert_release(!"For cube array textures: width and height must be <= 16384"); 1312 failed = true; 1313 } 1314 if (createinfo->layer_count_or_depth % 6 != 0) { 1315 SDL_assert_release(!"For cube array textures: layer_count_or_depth must be a multiple of 6"); 1316 failed = true; 1317 } 1318 if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) { 1319 SDL_assert_release(!"For cube array textures: sample_count must be SDL_GPU_SAMPLECOUNT_1"); 1320 failed = true; 1321 } 1322 if (!SDL_GPUTextureSupportsFormat(device, createinfo->format, SDL_GPU_TEXTURETYPE_CUBE_ARRAY, createinfo->usage)) { 1323 SDL_assert_release(!"For cube array textures: the format is unsupported for the given usage"); 1324 failed = true; 1325 } 1326 } else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) { 1327 // 3D Texture Validation 1328 if (createinfo->width > MAX_3D_DIMENSION || createinfo->height > MAX_3D_DIMENSION || createinfo->layer_count_or_depth > MAX_3D_DIMENSION) { 1329 SDL_assert_release(!"For 3D textures: width, height, and layer_count_or_depth must be <= 2048"); 1330 failed = true; 1331 } 1332 if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) { 1333 SDL_assert_release(!"For 3D textures: usage must not contain DEPTH_STENCIL_TARGET"); 1334 failed = true; 1335 } 1336 if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) { 1337 SDL_assert_release(!"For 3D textures: sample_count must be SDL_GPU_SAMPLECOUNT_1"); 1338 failed = true; 1339 } 1340 if (!SDL_GPUTextureSupportsFormat(device, createinfo->format, SDL_GPU_TEXTURETYPE_3D, createinfo->usage)) { 1341 SDL_assert_release(!"For 3D textures: the format is unsupported for the given usage"); 1342 failed = true; 1343 } 1344 } else { 1345 if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) { 1346 // Array Texture Validation 1347 if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) { 1348 SDL_assert_release(!"For array textures: usage must not contain DEPTH_STENCIL_TARGET"); 1349 failed = true; 1350 } 1351 if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) { 1352 SDL_assert_release(!"For array textures: sample_count must be SDL_GPU_SAMPLECOUNT_1"); 1353 failed = true; 1354 } 1355 } 1356 if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1 && createinfo->num_levels > 1) { 1357 SDL_assert_release(!"For 2D multisample textures: num_levels must be 1"); 1358 failed = true; 1359 } 1360 if (!SDL_GPUTextureSupportsFormat(device, createinfo->format, SDL_GPU_TEXTURETYPE_2D, createinfo->usage)) { 1361 SDL_assert_release(!"For 2D textures: the format is unsupported for the given usage"); 1362 failed = true; 1363 } 1364 } 1365 1366 if (failed) { 1367 return NULL; 1368 } 1369 } 1370 1371 return device->CreateTexture( 1372 device->driverData, 1373 createinfo); 1374} 1375 1376SDL_GPUBuffer *SDL_CreateGPUBuffer( 1377 SDL_GPUDevice *device, 1378 const SDL_GPUBufferCreateInfo *createinfo) 1379{ 1380 CHECK_DEVICE_MAGIC(device, NULL); 1381 1382 CHECK_PARAM(createinfo == NULL) { 1383 SDL_InvalidParamError("createinfo"); 1384 return NULL; 1385 } 1386 1387 if (device->debug_mode) { 1388 if (createinfo->size < 4) { 1389 SDL_assert_release(!"Cannot create a buffer with size less than 4 bytes!"); 1390 } 1391 } 1392 1393 const char *debugName = SDL_GetStringProperty(createinfo->props, SDL_PROP_GPU_BUFFER_CREATE_NAME_STRING, NULL); 1394 1395 return device->CreateBuffer( 1396 device->driverData, 1397 createinfo->usage, 1398 createinfo->size, 1399 debugName); 1400} 1401 1402SDL_GPUTransferBuffer *SDL_CreateGPUTransferBuffer( 1403 SDL_GPUDevice *device, 1404 const SDL_GPUTransferBufferCreateInfo *createinfo) 1405{ 1406 CHECK_DEVICE_MAGIC(device, NULL); 1407 1408 CHECK_PARAM(createinfo == NULL) { 1409 SDL_InvalidParamError("createinfo"); 1410 return NULL; 1411 } 1412 1413 const char *debugName = SDL_GetStringProperty(createinfo->props, SDL_PROP_GPU_TRANSFERBUFFER_CREATE_NAME_STRING, NULL); 1414 1415 return device->CreateTransferBuffer( 1416 device->driverData, 1417 createinfo->usage, 1418 createinfo->size, 1419 debugName); 1420} 1421 1422// Debug Naming 1423 1424void SDL_SetGPUBufferName( 1425 SDL_GPUDevice *device, 1426 SDL_GPUBuffer *buffer, 1427 const char *text) 1428{ 1429 CHECK_DEVICE_MAGIC(device, ); 1430 1431 CHECK_PARAM(buffer == NULL) { 1432 SDL_InvalidParamError("buffer"); 1433 return; 1434 } 1435 CHECK_PARAM(text == NULL) { 1436 SDL_InvalidParamError("text"); 1437 } 1438 1439 device->SetBufferName( 1440 device->driverData, 1441 buffer, 1442 text); 1443} 1444 1445void SDL_SetGPUTextureName( 1446 SDL_GPUDevice *device, 1447 SDL_GPUTexture *texture, 1448 const char *text) 1449{ 1450 CHECK_DEVICE_MAGIC(device, ); 1451 1452 CHECK_PARAM(texture == NULL) { 1453 SDL_InvalidParamError("texture"); 1454 return; 1455 } 1456 CHECK_PARAM(text == NULL) { 1457 SDL_InvalidParamError("text"); 1458 } 1459 1460 device->SetTextureName( 1461 device->driverData, 1462 texture, 1463 text); 1464} 1465 1466void SDL_InsertGPUDebugLabel( 1467 SDL_GPUCommandBuffer *command_buffer, 1468 const char *text) 1469{ 1470 CHECK_PARAM(command_buffer == NULL) { 1471 SDL_InvalidParamError("command_buffer"); 1472 return; 1473 } 1474 CHECK_PARAM(text == NULL) { 1475 SDL_InvalidParamError("text"); 1476 return; 1477 } 1478 1479 if (COMMAND_BUFFER_DEVICE->debug_mode) { 1480 CHECK_COMMAND_BUFFER 1481 } 1482 1483 COMMAND_BUFFER_DEVICE->InsertDebugLabel( 1484 command_buffer, 1485 text); 1486} 1487 1488void SDL_PushGPUDebugGroup( 1489 SDL_GPUCommandBuffer *command_buffer, 1490 const char *name) 1491{ 1492 CHECK_PARAM(command_buffer == NULL) { 1493 SDL_InvalidParamError("command_buffer"); 1494 return; 1495 } 1496 CHECK_PARAM(name == NULL) { 1497 SDL_InvalidParamError("name"); 1498 return; 1499 } 1500 1501 if (COMMAND_BUFFER_DEVICE->debug_mode) { 1502 CHECK_COMMAND_BUFFER 1503 } 1504 1505 COMMAND_BUFFER_DEVICE->PushDebugGroup( 1506 command_buffer, 1507 name); 1508} 1509 1510void SDL_PopGPUDebugGroup( 1511 SDL_GPUCommandBuffer *command_buffer) 1512{ 1513 CHECK_PARAM(command_buffer == NULL) { 1514 SDL_InvalidParamError("command_buffer"); 1515 return; 1516 } 1517 1518 if (COMMAND_BUFFER_DEVICE->debug_mode) { 1519 CHECK_COMMAND_BUFFER 1520 } 1521 1522 COMMAND_BUFFER_DEVICE->PopDebugGroup( 1523 command_buffer); 1524} 1525 1526// Disposal 1527 1528void SDL_ReleaseGPUTexture( 1529 SDL_GPUDevice *device, 1530 SDL_GPUTexture *texture) 1531{ 1532 CHECK_DEVICE_MAGIC(device, ); 1533 1534 CHECK_PARAM(texture == NULL) { 1535 return; 1536 } 1537 1538 device->ReleaseTexture( 1539 device->driverData, 1540 texture); 1541} 1542 1543void SDL_ReleaseGPUSampler( 1544 SDL_GPUDevice *device, 1545 SDL_GPUSampler *sampler) 1546{ 1547 CHECK_DEVICE_MAGIC(device, ); 1548 1549 CHECK_PARAM(sampler == NULL) { 1550 return; 1551 } 1552 1553 device->ReleaseSampler( 1554 device->driverData, 1555 sampler); 1556} 1557 1558void SDL_ReleaseGPUBuffer( 1559 SDL_GPUDevice *device, 1560 SDL_GPUBuffer *buffer) 1561{ 1562 CHECK_DEVICE_MAGIC(device, ); 1563 1564 CHECK_PARAM(buffer == NULL) { 1565 return; 1566 } 1567 1568 device->ReleaseBuffer( 1569 device->driverData, 1570 buffer); 1571} 1572 1573void SDL_ReleaseGPUTransferBuffer( 1574 SDL_GPUDevice *device, 1575 SDL_GPUTransferBuffer *transfer_buffer) 1576{ 1577 CHECK_DEVICE_MAGIC(device, ); 1578 1579 CHECK_PARAM(transfer_buffer == NULL) { 1580 return; 1581 } 1582 1583 device->ReleaseTransferBuffer( 1584 device->driverData, 1585 transfer_buffer); 1586} 1587 1588void SDL_ReleaseGPUShader( 1589 SDL_GPUDevice *device, 1590 SDL_GPUShader *shader) 1591{ 1592 CHECK_DEVICE_MAGIC(device, ); 1593 1594 CHECK_PARAM(shader == NULL) { 1595 return; 1596 } 1597 1598 device->ReleaseShader( 1599 device->driverData, 1600 shader); 1601} 1602 1603void SDL_ReleaseGPUComputePipeline( 1604 SDL_GPUDevice *device, 1605 SDL_GPUComputePipeline *compute_pipeline) 1606{ 1607 CHECK_DEVICE_MAGIC(device, ); 1608 1609 CHECK_PARAM(compute_pipeline == NULL) { 1610 return; 1611 } 1612 1613 device->ReleaseComputePipeline( 1614 device->driverData, 1615 compute_pipeline); 1616} 1617 1618void SDL_ReleaseGPUGraphicsPipeline( 1619 SDL_GPUDevice *device, 1620 SDL_GPUGraphicsPipeline *graphics_pipeline) 1621{ 1622 CHECK_DEVICE_MAGIC(device, ); 1623 1624 CHECK_PARAM(graphics_pipeline == NULL) { 1625 return; 1626 } 1627 1628 device->ReleaseGraphicsPipeline( 1629 device->driverData, 1630 graphics_pipeline); 1631} 1632 1633// Command Buffer 1634 1635SDL_GPUCommandBuffer *SDL_AcquireGPUCommandBuffer( 1636 SDL_GPUDevice *device) 1637{ 1638 SDL_GPUCommandBuffer *command_buffer; 1639 CommandBufferCommonHeader *commandBufferHeader; 1640 1641 CHECK_DEVICE_MAGIC(device, NULL); 1642 1643 command_buffer = device->AcquireCommandBuffer( 1644 device->driverData); 1645 1646 if (command_buffer == NULL) { 1647 return NULL; 1648 } 1649 1650 commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; 1651 commandBufferHeader->device = device; 1652 commandBufferHeader->render_pass.command_buffer = command_buffer; 1653 commandBufferHeader->compute_pass.command_buffer = command_buffer; 1654 commandBufferHeader->copy_pass.command_buffer = command_buffer; 1655 1656 if (device->debug_mode) { 1657 commandBufferHeader->render_pass.in_progress = false; 1658 commandBufferHeader->render_pass.graphics_pipeline = NULL; 1659 commandBufferHeader->compute_pass.in_progress = false; 1660 commandBufferHeader->compute_pass.compute_pipeline = NULL; 1661 commandBufferHeader->copy_pass.in_progress = false; 1662 commandBufferHeader->swapchain_texture_acquired = false; 1663 commandBufferHeader->submitted = false; 1664 commandBufferHeader->ignore_render_pass_texture_validation = false; 1665 SDL_zeroa(commandBufferHeader->render_pass.vertex_sampler_bound); 1666 SDL_zeroa(commandBufferHeader->render_pass.vertex_storage_texture_bound); 1667 SDL_zeroa(commandBufferHeader->render_pass.vertex_storage_buffer_bound); 1668 SDL_zeroa(commandBufferHeader->render_pass.fragment_sampler_bound); 1669 SDL_zeroa(commandBufferHeader->render_pass.fragment_storage_texture_bound); 1670 SDL_zeroa(commandBufferHeader->render_pass.fragment_storage_buffer_bound); 1671 SDL_zeroa(commandBufferHeader->compute_pass.sampler_bound); 1672 SDL_zeroa(commandBufferHeader->compute_pass.read_only_storage_texture_bound); 1673 SDL_zeroa(commandBufferHeader->compute_pass.read_only_storage_buffer_bound); 1674 SDL_zeroa(commandBufferHeader->compute_pass.read_write_storage_texture_bound); 1675 SDL_zeroa(commandBufferHeader->compute_pass.read_write_storage_buffer_bound); 1676 } 1677 1678 return command_buffer; 1679} 1680 1681// Uniforms 1682 1683void SDL_PushGPUVertexUniformData( 1684 SDL_GPUCommandBuffer *command_buffer, 1685 Uint32 slot_index, 1686 const void *data, 1687 Uint32 length) 1688{ 1689 CHECK_PARAM(command_buffer == NULL) { 1690 SDL_InvalidParamError("command_buffer"); 1691 return; 1692 } 1693 CHECK_PARAM(data == NULL) { 1694 SDL_InvalidParamError("data"); 1695 return; 1696 } 1697 CHECK_PARAM(slot_index >= MAX_UNIFORM_BUFFERS_PER_STAGE) { 1698 SDL_SetError("slot_index exceeds MAX_UNIFORM_BUFFERS_PER_STAGE"); 1699 return; 1700 } 1701 1702 if (COMMAND_BUFFER_DEVICE->debug_mode) { 1703 CHECK_COMMAND_BUFFER 1704 } 1705 1706 COMMAND_BUFFER_DEVICE->PushVertexUniformData( 1707 command_buffer, 1708 slot_index, 1709 data, 1710 length); 1711} 1712 1713void SDL_PushGPUFragmentUniformData( 1714 SDL_GPUCommandBuffer *command_buffer, 1715 Uint32 slot_index, 1716 const void *data, 1717 Uint32 length) 1718{ 1719 CHECK_PARAM(command_buffer == NULL) { 1720 SDL_InvalidParamError("command_buffer"); 1721 return; 1722 } 1723 CHECK_PARAM(data == NULL) { 1724 SDL_InvalidParamError("data"); 1725 return; 1726 } 1727 CHECK_PARAM(slot_index >= MAX_UNIFORM_BUFFERS_PER_STAGE) { 1728 SDL_SetError("slot_index exceeds MAX_UNIFORM_BUFFERS_PER_STAGE"); 1729 return; 1730 } 1731 1732 if (COMMAND_BUFFER_DEVICE->debug_mode) { 1733 CHECK_COMMAND_BUFFER 1734 } 1735 1736 COMMAND_BUFFER_DEVICE->PushFragmentUniformData( 1737 command_buffer, 1738 slot_index, 1739 data, 1740 length); 1741} 1742 1743void SDL_PushGPUComputeUniformData( 1744 SDL_GPUCommandBuffer *command_buffer, 1745 Uint32 slot_index, 1746 const void *data, 1747 Uint32 length) 1748{ 1749 CHECK_PARAM(command_buffer == NULL) { 1750 SDL_InvalidParamError("command_buffer"); 1751 return; 1752 } 1753 CHECK_PARAM(data == NULL) { 1754 SDL_InvalidParamError("data"); 1755 return; 1756 } 1757 CHECK_PARAM(slot_index >= MAX_UNIFORM_BUFFERS_PER_STAGE) { 1758 SDL_SetError("slot_index exceeds MAX_UNIFORM_BUFFERS_PER_STAGE"); 1759 return; 1760 } 1761 1762 if (COMMAND_BUFFER_DEVICE->debug_mode) { 1763 CHECK_COMMAND_BUFFER 1764 } 1765 1766 COMMAND_BUFFER_DEVICE->PushComputeUniformData( 1767 command_buffer, 1768 slot_index, 1769 data, 1770 length); 1771} 1772 1773// Render Pass 1774 1775SDL_GPURenderPass *SDL_BeginGPURenderPass( 1776 SDL_GPUCommandBuffer *command_buffer, 1777 const SDL_GPUColorTargetInfo *color_target_infos, 1778 Uint32 num_color_targets, 1779 const SDL_GPUDepthStencilTargetInfo *depth_stencil_target_info) 1780{ 1781 CommandBufferCommonHeader *commandBufferHeader; 1782 1783 CHECK_PARAM(command_buffer == NULL) { 1784 SDL_InvalidParamError("command_buffer"); 1785 return NULL; 1786 } 1787 CHECK_PARAM(color_target_infos == NULL && num_color_targets > 0) { 1788 SDL_InvalidParamError("color_target_infos"); 1789 return NULL; 1790 } 1791 1792 CHECK_PARAM(num_color_targets > MAX_COLOR_TARGET_BINDINGS) { 1793 SDL_SetError("num_color_targets exceeds MAX_COLOR_TARGET_BINDINGS"); 1794 return NULL; 1795 } 1796 1797 if (COMMAND_BUFFER_DEVICE->debug_mode) { 1798 CHECK_COMMAND_BUFFER_RETURN_NULL 1799 CHECK_ANY_PASS_IN_PROGRESS("Cannot begin render pass during another pass!", NULL) 1800 1801 for (Uint32 i = 0; i < num_color_targets; i += 1) { 1802 TextureCommonHeader *textureHeader = (TextureCommonHeader *)color_target_infos[i].texture; 1803 1804 if (color_target_infos[i].cycle && color_target_infos[i].load_op == SDL_GPU_LOADOP_LOAD) { 1805 SDL_assert_release(!"Cannot cycle color target when load op is LOAD!"); 1806 return NULL; 1807 } 1808 1809 if (color_target_infos[i].store_op == SDL_GPU_STOREOP_RESOLVE || color_target_infos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) { 1810 if (color_target_infos[i].resolve_texture == NULL) { 1811 SDL_assert_release(!"Store op is RESOLVE or RESOLVE_AND_STORE but resolve_texture is NULL!"); 1812 return NULL; 1813 } else { 1814 TextureCommonHeader *resolveTextureHeader = (TextureCommonHeader *)color_target_infos[i].resolve_texture; 1815 if (textureHeader->info.sample_count == SDL_GPU_SAMPLECOUNT_1) { 1816 SDL_assert_release(!"Store op is RESOLVE or RESOLVE_AND_STORE but texture is not multisample!"); 1817 return NULL; 1818 } 1819 if (resolveTextureHeader->info.sample_count != SDL_GPU_SAMPLECOUNT_1) { 1820 SDL_assert_release(!"Resolve texture must have a sample count of 1!"); 1821 return NULL; 1822 } 1823 if (resolveTextureHeader->info.format != textureHeader->info.format) { 1824 SDL_assert_release(!"Resolve texture must have the same format as its corresponding color target!"); 1825 return NULL; 1826 } 1827 if (resolveTextureHeader->info.type == SDL_GPU_TEXTURETYPE_3D) { 1828 SDL_assert_release(!"Resolve texture must not be of TEXTURETYPE_3D!"); 1829 return NULL; 1830 } 1831 if (!(resolveTextureHeader->info.usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET)) { 1832 SDL_assert_release(!"Resolve texture usage must include COLOR_TARGET!"); 1833 return NULL; 1834 } 1835 } 1836 } 1837 1838 if (color_target_infos[i].layer_or_depth_plane >= textureHeader->info.layer_count_or_depth) { 1839 SDL_assert_release(!"Color target layer index must be less than the texture's layer count!"); 1840 return NULL; 1841 } 1842 1843 if (color_target_infos[i].mip_level >= textureHeader->info.num_levels) { 1844 SDL_assert_release(!"Color target mip level must be less than the texture's level count!"); 1845 return NULL; 1846 } 1847 } 1848 1849 if (depth_stencil_target_info != NULL) { 1850 TextureCommonHeader *textureHeader = (TextureCommonHeader *)depth_stencil_target_info->texture; 1851 if (!(textureHeader->info.usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET)) { 1852 SDL_assert_release(!"Depth target must have been created with the DEPTH_STENCIL_TARGET usage flag!"); 1853 return NULL; 1854 } 1855 1856 if (textureHeader->info.layer_count_or_depth > 255) { 1857 SDL_assert_release(!"Cannot bind a depth texture with more than 255 layers!"); 1858 return NULL; 1859 } 1860 1861 if (depth_stencil_target_info->cycle && (depth_stencil_target_info->load_op == SDL_GPU_LOADOP_LOAD || depth_stencil_target_info->stencil_load_op == SDL_GPU_LOADOP_LOAD)) { 1862 SDL_assert_release(!"Cannot cycle depth target when load op or stencil load op is LOAD!"); 1863 return NULL; 1864 } 1865 1866 if (depth_stencil_target_info->store_op == SDL_GPU_STOREOP_RESOLVE || 1867 depth_stencil_target_info->stencil_store_op == SDL_GPU_STOREOP_RESOLVE || 1868 depth_stencil_target_info->store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE || 1869 depth_stencil_target_info->stencil_store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) { 1870 SDL_assert_release(!"RESOLVE store ops are not supported for depth-stencil targets!"); 1871 return NULL; 1872 } 1873 } 1874 } 1875 1876 COMMAND_BUFFER_DEVICE->BeginRenderPass( 1877 command_buffer, 1878 color_target_infos, 1879 num_color_targets, 1880 depth_stencil_target_info); 1881 1882 commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; 1883 1884 if (COMMAND_BUFFER_DEVICE->debug_mode) { 1885 commandBufferHeader->render_pass.in_progress = true; 1886 for (Uint32 i = 0; i < num_color_targets; i += 1) { 1887 commandBufferHeader->render_pass.color_targets[i] = color_target_infos[i].texture; 1888 } 1889 commandBufferHeader->render_pass.num_color_targets = num_color_targets; 1890 if (depth_stencil_target_info != NULL) { 1891 commandBufferHeader->render_pass.depth_stencil_target = depth_stencil_target_info->texture; 1892 } else { 1893 commandBufferHeader->render_pass.depth_stencil_target = NULL; 1894 } 1895 } 1896 1897 return (SDL_GPURenderPass *)&(commandBufferHeader->render_pass); 1898} 1899 1900void SDL_BindGPUGraphicsPipeline( 1901 SDL_GPURenderPass *render_pass, 1902 SDL_GPUGraphicsPipeline *graphics_pipeline) 1903{ 1904 CHECK_PARAM(render_pass == NULL) { 1905 SDL_InvalidParamError("render_pass"); 1906 return; 1907 } 1908 CHECK_PARAM(graphics_pipeline == NULL) { 1909 SDL_InvalidParamError("graphics_pipeline"); 1910 return; 1911 } 1912 1913 RENDERPASS_DEVICE->BindGraphicsPipeline( 1914 RENDERPASS_COMMAND_BUFFER, 1915 graphics_pipeline); 1916 1917 1918 if (RENDERPASS_DEVICE->debug_mode) { 1919 RENDERPASS_BOUND_PIPELINE = graphics_pipeline; 1920 } 1921} 1922 1923void SDL_SetGPUViewport( 1924 SDL_GPURenderPass *render_pass, 1925 const SDL_GPUViewport *viewport) 1926{ 1927 CHECK_PARAM(render_pass == NULL) { 1928 SDL_InvalidParamError("render_pass"); 1929 return; 1930 } 1931 CHECK_PARAM(viewport == NULL) { 1932 SDL_InvalidParamError("viewport"); 1933 return; 1934 } 1935 1936 if (RENDERPASS_DEVICE->debug_mode) { 1937 CHECK_RENDERPASS 1938 } 1939 1940 RENDERPASS_DEVICE->SetViewport( 1941 RENDERPASS_COMMAND_BUFFER, 1942 viewport); 1943} 1944 1945void SDL_SetGPUScissor( 1946 SDL_GPURenderPass *render_pass, 1947 const SDL_Rect *scissor) 1948{ 1949 CHECK_PARAM(render_pass == NULL) { 1950 SDL_InvalidParamError("render_pass"); 1951 return; 1952 } 1953 CHECK_PARAM(scissor == NULL) { 1954 SDL_InvalidParamError("scissor"); 1955 return; 1956 } 1957 1958 if (RENDERPASS_DEVICE->debug_mode) { 1959 CHECK_RENDERPASS 1960 } 1961 1962 RENDERPASS_DEVICE->SetScissor( 1963 RENDERPASS_COMMAND_BUFFER, 1964 scissor); 1965} 1966 1967void SDL_SetGPUBlendConstants( 1968 SDL_GPURenderPass *render_pass, 1969 SDL_FColor blend_constants) 1970{ 1971 CHECK_PARAM(render_pass == NULL) { 1972 SDL_InvalidParamError("render_pass"); 1973 return; 1974 } 1975 1976 if (RENDERPASS_DEVICE->debug_mode) { 1977 CHECK_RENDERPASS 1978 } 1979 1980 RENDERPASS_DEVICE->SetBlendConstants( 1981 RENDERPASS_COMMAND_BUFFER, 1982 blend_constants); 1983} 1984 1985void SDL_SetGPUStencilReference( 1986 SDL_GPURenderPass *render_pass, 1987 Uint8 reference) 1988{ 1989 CHECK_PARAM(render_pass == NULL) { 1990 SDL_InvalidParamError("render_pass"); 1991 return; 1992 } 1993 1994 if (RENDERPASS_DEVICE->debug_mode) { 1995 CHECK_RENDERPASS 1996 } 1997 1998 RENDERPASS_DEVICE->SetStencilReference( 1999 RENDERPASS_COMMAND_BUFFER, 2000 reference); 2001} 2002 2003void SDL_BindGPUVertexBuffers( 2004 SDL_GPURenderPass *render_pass, 2005 Uint32 first_binding, 2006 const SDL_GPUBufferBinding *bindings, 2007 Uint32 num_bindings) 2008{ 2009 CHECK_PARAM(render_pass == NULL) { 2010 SDL_InvalidParamError("render_pass"); 2011 return; 2012 } 2013 if (bindings == NULL && num_bindings > 0) { 2014 SDL_InvalidParamError("bindings"); 2015 return; 2016 } 2017 2018 if (RENDERPASS_DEVICE->debug_mode) { 2019 CHECK_RENDERPASS 2020 } 2021 2022 RENDERPASS_DEVICE->BindVertexBuffers( 2023 RENDERPASS_COMMAND_BUFFER, 2024 first_binding, 2025 bindings, 2026 num_bindings); 2027} 2028 2029void SDL_BindGPUIndexBuffer( 2030 SDL_GPURenderPass *render_pass, 2031 const SDL_GPUBufferBinding *binding, 2032 SDL_GPUIndexElementSize index_element_size) 2033{ 2034 CHECK_PARAM(render_pass == NULL) { 2035 SDL_InvalidParamError("render_pass"); 2036 return; 2037 } 2038 if (binding == NULL) { 2039 SDL_InvalidParamError("binding"); 2040 return; 2041 } 2042 2043 if (RENDERPASS_DEVICE->debug_mode) { 2044 CHECK_RENDERPASS 2045 } 2046 2047 RENDERPASS_DEVICE->BindIndexBuffer( 2048 RENDERPASS_COMMAND_BUFFER, 2049 binding, 2050 index_element_size); 2051} 2052 2053void SDL_BindGPUVertexSamplers( 2054 SDL_GPURenderPass *render_pass, 2055 Uint32 first_slot, 2056 const SDL_GPUTextureSamplerBinding *texture_sampler_bindings, 2057 Uint32 num_bindings) 2058{ 2059 CHECK_PARAM(render_pass == NULL) { 2060 SDL_InvalidParamError("render_pass"); 2061 return; 2062 } 2063 CHECK_PARAM(texture_sampler_bindings == NULL && num_bindings > 0) { 2064 SDL_InvalidParamError("texture_sampler_bindings"); 2065 return; 2066 } 2067 CHECK_PARAM(first_slot + num_bindings > MAX_TEXTURE_SAMPLERS_PER_STAGE) { 2068 SDL_SetError("first_slot + num_bindings exceeds MAX_TEXTURE_SAMPLERS_PER_STAGE"); 2069 return; 2070 } 2071 2072 if (RENDERPASS_DEVICE->debug_mode) { 2073 CHECK_RENDERPASS 2074 2075 if (!((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->ignore_render_pass_texture_validation) 2076 { 2077 CHECK_SAMPLER_TEXTURES 2078 } 2079 2080 for (Uint32 i = 0; i < num_bindings; i += 1) { 2081 ((RenderPass *)render_pass)->vertex_sampler_bound[first_slot + i] = true; 2082 } 2083 } 2084 2085 RENDERPASS_DEVICE->BindVertexSamplers( 2086 RENDERPASS_COMMAND_BUFFER, 2087 first_slot, 2088 texture_sampler_bindings, 2089 num_bindings); 2090} 2091 2092void SDL_BindGPUVertexStorageTextures( 2093 SDL_GPURenderPass *render_pass, 2094 Uint32 first_slot, 2095 SDL_GPUTexture *const *storage_textures, 2096 Uint32 num_bindings) 2097{ 2098 CHECK_PARAM(render_pass == NULL) { 2099 SDL_InvalidParamError("render_pass"); 2100 return; 2101 } 2102 CHECK_PARAM(storage_textures == NULL && num_bindings > 0) { 2103 SDL_InvalidParamError("storage_textures"); 2104 return; 2105 } 2106 CHECK_PARAM(first_slot + num_bindings > MAX_STORAGE_TEXTURES_PER_STAGE) { 2107 SDL_SetError("first_slot + num_bindings exceeds MAX_STORAGE_TEXTURES_PER_STAGE"); 2108 return; 2109 } 2110 2111 if (RENDERPASS_DEVICE->debug_mode) { 2112 CHECK_RENDERPASS 2113 CHECK_STORAGE_TEXTURES 2114 2115 for (Uint32 i = 0; i < num_bindings; i += 1) { 2116 ((RenderPass *)render_pass)->vertex_storage_texture_bound[first_slot + i] = true; 2117 } 2118 } 2119 2120 RENDERPASS_DEVICE->BindVertexStorageTextures( 2121 RENDERPASS_COMMAND_BUFFER, 2122 first_slot, 2123 storage_textures, 2124 num_bindings); 2125} 2126 2127void SDL_BindGPUVertexStorageBuffers( 2128 SDL_GPURenderPass *render_pass, 2129 Uint32 first_slot, 2130 SDL_GPUBuffer *const *storage_buffers, 2131 Uint32 num_bindings) 2132{ 2133 CHECK_PARAM(render_pass == NULL) { 2134 SDL_InvalidParamError("render_pass"); 2135 return; 2136 } 2137 CHECK_PARAM(storage_buffers == NULL && num_bindings > 0) { 2138 SDL_InvalidParamError("storage_buffers"); 2139 return; 2140 } 2141 CHECK_PARAM(first_slot + num_bindings > MAX_STORAGE_BUFFERS_PER_STAGE) { 2142 SDL_SetError("first_slot + num_bindings exceeds MAX_STORAGE_BUFFERS_PER_STAGE"); 2143 return; 2144 } 2145 2146 if (RENDERPASS_DEVICE->debug_mode) { 2147 CHECK_RENDERPASS 2148 2149 for (Uint32 i = 0; i < num_bindings; i += 1) { 2150 ((RenderPass *)render_pass)->vertex_storage_buffer_bound[first_slot + i] = true; 2151 } 2152 } 2153 2154 RENDERPASS_DEVICE->BindVertexStorageBuffers( 2155 RENDERPASS_COMMAND_BUFFER, 2156 first_slot, 2157 storage_buffers, 2158 num_bindings); 2159} 2160 2161void SDL_BindGPUFragmentSamplers( 2162 SDL_GPURenderPass *render_pass, 2163 Uint32 first_slot, 2164 const SDL_GPUTextureSamplerBinding *texture_sampler_bindings, 2165 Uint32 num_bindings) 2166{ 2167 CHECK_PARAM(render_pass == NULL) { 2168 SDL_InvalidParamError("render_pass"); 2169 return; 2170 } 2171 CHECK_PARAM(texture_sampler_bindings == NULL && num_bindings > 0) { 2172 SDL_InvalidParamError("texture_sampler_bindings"); 2173 return; 2174 } 2175 CHECK_PARAM(first_slot + num_bindings > MAX_TEXTURE_SAMPLERS_PER_STAGE) { 2176 SDL_SetError("first_slot + num_bindings exceeds MAX_TEXTURE_SAMPLERS_PER_STAGE"); 2177 return; 2178 } 2179 2180 if (RENDERPASS_DEVICE->debug_mode) { 2181 CHECK_RENDERPASS 2182 2183 if (!((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->ignore_render_pass_texture_validation) { 2184 CHECK_SAMPLER_TEXTURES 2185 } 2186 2187 for (Uint32 i = 0; i < num_bindings; i += 1) { 2188 ((RenderPass *)render_pass)->fragment_sampler_bound[first_slot + i] = true; 2189 } 2190 } 2191 2192 RENDERPASS_DEVICE->BindFragmentSamplers( 2193 RENDERPASS_COMMAND_BUFFER, 2194 first_slot, 2195 texture_sampler_bindings, 2196 num_bindings); 2197} 2198 2199void SDL_BindGPUFragmentStorageTextures( 2200 SDL_GPURenderPass *render_pass, 2201 Uint32 first_slot, 2202 SDL_GPUTexture *const *storage_textures, 2203 Uint32 num_bindings) 2204{ 2205 CHECK_PARAM(render_pass == NULL) { 2206 SDL_InvalidParamError("render_pass"); 2207 return; 2208 } 2209 CHECK_PARAM(storage_textures == NULL && num_bindings > 0) { 2210 SDL_InvalidParamError("storage_textures"); 2211 return; 2212 } 2213 CHECK_PARAM(first_slot + num_bindings > MAX_STORAGE_TEXTURES_PER_STAGE) { 2214 SDL_SetError("first_slot + num_bindings exceeds MAX_STORAGE_TEXTURES_PER_STAGE"); 2215 return; 2216 } 2217 2218 if (RENDERPASS_DEVICE->debug_mode) { 2219 CHECK_RENDERPASS 2220 CHECK_STORAGE_TEXTURES 2221 2222 for (Uint32 i = 0; i < num_bindings; i += 1) { 2223 ((RenderPass *)render_pass)->fragment_storage_texture_bound[first_slot + i] = true; 2224 } 2225 } 2226 2227 RENDERPASS_DEVICE->BindFragmentStorageTextures( 2228 RENDERPASS_COMMAND_BUFFER, 2229 first_slot, 2230 storage_textures, 2231 num_bindings); 2232} 2233 2234void SDL_BindGPUFragmentStorageBuffers( 2235 SDL_GPURenderPass *render_pass, 2236 Uint32 first_slot, 2237 SDL_GPUBuffer *const *storage_buffers, 2238 Uint32 num_bindings) 2239{ 2240 CHECK_PARAM(render_pass == NULL) { 2241 SDL_InvalidParamError("render_pass"); 2242 return; 2243 } 2244 CHECK_PARAM(storage_buffers == NULL && num_bindings > 0) { 2245 SDL_InvalidParamError("storage_buffers"); 2246 return; 2247 } 2248 CHECK_PARAM(first_slot + num_bindings > MAX_STORAGE_BUFFERS_PER_STAGE) { 2249 SDL_SetError("first_slot + num_bindings exceeds MAX_STORAGE_BUFFERS_PER_STAGE"); 2250 return; 2251 } 2252 2253 if (RENDERPASS_DEVICE->debug_mode) { 2254 CHECK_RENDERPASS 2255 2256 for (Uint32 i = 0; i < num_bindings; i += 1) { 2257 ((RenderPass *)render_pass)->fragment_storage_buffer_bound[first_slot + i] = true; 2258 } 2259 } 2260 2261 RENDERPASS_DEVICE->BindFragmentStorageBuffers( 2262 RENDERPASS_COMMAND_BUFFER, 2263 first_slot, 2264 storage_buffers, 2265 num_bindings); 2266} 2267 2268void SDL_DrawGPUIndexedPrimitives( 2269 SDL_GPURenderPass *render_pass, 2270 Uint32 num_indices, 2271 Uint32 num_instances, 2272 Uint32 first_index, 2273 Sint32 vertex_offset, 2274 Uint32 first_instance) 2275{ 2276 CHECK_PARAM(render_pass == NULL) { 2277 SDL_InvalidParamError("render_pass"); 2278 return; 2279 } 2280 2281 if (RENDERPASS_DEVICE->debug_mode) { 2282 CHECK_RENDERPASS 2283 CHECK_GRAPHICS_PIPELINE_BOUND 2284 SDL_GPU_CheckGraphicsBindings(render_pass); 2285 } 2286 2287 RENDERPASS_DEVICE->DrawIndexedPrimitives( 2288 RENDERPASS_COMMAND_BUFFER, 2289 num_indices, 2290 num_instances, 2291 first_index, 2292 vertex_offset, 2293 first_instance); 2294} 2295 2296void SDL_DrawGPUPrimitives( 2297 SDL_GPURenderPass *render_pass, 2298 Uint32 num_vertices, 2299 Uint32 num_instances, 2300 Uint32 first_vertex, 2301 Uint32 first_instance) 2302{ 2303 CHECK_PARAM(render_pass == NULL) { 2304 SDL_InvalidParamError("render_pass"); 2305 return; 2306 } 2307 2308 if (RENDERPASS_DEVICE->debug_mode) { 2309 CHECK_RENDERPASS 2310 CHECK_GRAPHICS_PIPELINE_BOUND 2311 SDL_GPU_CheckGraphicsBindings(render_pass); 2312 } 2313 2314 RENDERPASS_DEVICE->DrawPrimitives( 2315 RENDERPASS_COMMAND_BUFFER, 2316 num_vertices, 2317 num_instances, 2318 first_vertex, 2319 first_instance); 2320} 2321 2322void SDL_DrawGPUPrimitivesIndirect( 2323 SDL_GPURenderPass *render_pass, 2324 SDL_GPUBuffer *buffer, 2325 Uint32 offset, 2326 Uint32 draw_count) 2327{ 2328 CHECK_PARAM(render_pass == NULL) { 2329 SDL_InvalidParamError("render_pass"); 2330 return; 2331 } 2332 CHECK_PARAM(buffer == NULL) { 2333 SDL_InvalidParamError("buffer"); 2334 return; 2335 } 2336 2337 if (RENDERPASS_DEVICE->debug_mode) { 2338 CHECK_RENDERPASS 2339 CHECK_GRAPHICS_PIPELINE_BOUND 2340 SDL_GPU_CheckGraphicsBindings(render_pass); 2341 } 2342 2343 RENDERPASS_DEVICE->DrawPrimitivesIndirect( 2344 RENDERPASS_COMMAND_BUFFER, 2345 buffer, 2346 offset, 2347 draw_count); 2348} 2349 2350void SDL_DrawGPUIndexedPrimitivesIndirect( 2351 SDL_GPURenderPass *render_pass, 2352 SDL_GPUBuffer *buffer, 2353 Uint32 offset, 2354 Uint32 draw_count) 2355{ 2356 CHECK_PARAM(render_pass == NULL) { 2357 SDL_InvalidParamError("render_pass"); 2358 return; 2359 } 2360 CHECK_PARAM(buffer == NULL) { 2361 SDL_InvalidParamError("buffer"); 2362 return; 2363 } 2364 2365 if (RENDERPASS_DEVICE->debug_mode) { 2366 CHECK_RENDERPASS 2367 CHECK_GRAPHICS_PIPELINE_BOUND 2368 SDL_GPU_CheckGraphicsBindings(render_pass); 2369 } 2370 2371 RENDERPASS_DEVICE->DrawIndexedPrimitivesIndirect( 2372 RENDERPASS_COMMAND_BUFFER, 2373 buffer, 2374 offset, 2375 draw_count); 2376} 2377 2378void SDL_EndGPURenderPass( 2379 SDL_GPURenderPass *render_pass) 2380{ 2381 CHECK_PARAM(render_pass == NULL) { 2382 SDL_InvalidParamError("render_pass"); 2383 return; 2384 } 2385 2386 CommandBufferCommonHeader *commandBufferCommonHeader; 2387 commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER; 2388 2389 if (RENDERPASS_DEVICE->debug_mode) { 2390 CHECK_RENDERPASS 2391 } 2392 2393 RENDERPASS_DEVICE->EndRenderPass( 2394 RENDERPASS_COMMAND_BUFFER); 2395 2396 if (RENDERPASS_DEVICE->debug_mode) { 2397 commandBufferCommonHeader->render_pass.in_progress = false; 2398 for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) 2399 { 2400 commandBufferCommonHeader->render_pass.color_targets[i] = NULL; 2401 } 2402 commandBufferCommonHeader->render_pass.num_color_targets = 0; 2403 commandBufferCommonHeader->render_pass.depth_stencil_target = NULL; 2404 commandBufferCommonHeader->render_pass.graphics_pipeline = NULL; 2405 SDL_zeroa(commandBufferCommonHeader->render_pass.vertex_sampler_bound); 2406 SDL_zeroa(commandBufferCommonHeader->render_pass.vertex_storage_texture_bound); 2407 SDL_zeroa(commandBufferCommonHeader->render_pass.vertex_storage_buffer_bound); 2408 SDL_zeroa(commandBufferCommonHeader->render_pass.fragment_sampler_bound); 2409 SDL_zeroa(commandBufferCommonHeader->render_pass.fragment_storage_texture_bound); 2410 SDL_zeroa(commandBufferCommonHeader->render_pass.fragment_storage_buffer_bound); 2411 } 2412} 2413 2414// Compute Pass 2415 2416SDL_GPUComputePass *SDL_BeginGPUComputePass( 2417 SDL_GPUCommandBuffer *command_buffer, 2418 const SDL_GPUStorageTextureReadWriteBinding *storage_texture_bindings, 2419 Uint32 num_storage_texture_bindings, 2420 const SDL_GPUStorageBufferReadWriteBinding *storage_buffer_bindings, 2421 Uint32 num_storage_buffer_bindings) 2422{ 2423 CommandBufferCommonHeader *commandBufferHeader; 2424 2425 CHECK_PARAM(command_buffer == NULL) { 2426 SDL_InvalidParamError("command_buffer"); 2427 return NULL; 2428 } 2429 CHECK_PARAM(storage_texture_bindings == NULL && num_storage_texture_bindings > 0) { 2430 SDL_InvalidParamError("storage_texture_bindings"); 2431 return NULL; 2432 } 2433 CHECK_PARAM(storage_buffer_bindings == NULL && num_storage_buffer_bindings > 0) { 2434 SDL_InvalidParamError("storage_buffer_bindings"); 2435 return NULL; 2436 } 2437 CHECK_PARAM(num_storage_texture_bindings > MAX_COMPUTE_WRITE_TEXTURES) { 2438 SDL_InvalidParamError("num_storage_texture_bindings"); 2439 return NULL; 2440 } 2441 CHECK_PARAM(num_storage_buffer_bindings > MAX_COMPUTE_WRITE_BUFFERS) { 2442 SDL_InvalidParamError("num_storage_buffer_bindings"); 2443 return NULL; 2444 } 2445 2446 if (COMMAND_BUFFER_DEVICE->debug_mode) { 2447 CHECK_COMMAND_BUFFER_RETURN_NULL 2448 CHECK_ANY_PASS_IN_PROGRESS("Cannot begin compute pass during another pass!", NULL) 2449 2450 for (Uint32 i = 0; i < num_storage_texture_bindings; i += 1) { 2451 TextureCommonHeader *header = (TextureCommonHeader *)storage_texture_bindings[i].texture; 2452 if (!(header->info.usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) && !(header->info.usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE)) { 2453 SDL_assert_release(!"Texture must be created with COMPUTE_STORAGE_WRITE or COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE flag"); 2454 return NULL; 2455 } 2456 2457 if (storage_texture_bindings[i].layer >= header->info.layer_count_or_depth) { 2458 SDL_assert_release(!"Storage texture layer index must be less than the texture's layer count!"); 2459 return NULL; 2460 } 2461 2462 if (storage_texture_bindings[i].mip_level >= header->info.num_levels) { 2463 SDL_assert_release(!"Storage texture mip level must be less than the texture's level count!"); 2464 return NULL; 2465 } 2466 } 2467 2468 // TODO: validate buffer usage? 2469 } 2470 2471 COMMAND_BUFFER_DEVICE->BeginComputePass( 2472 command_buffer, 2473 storage_texture_bindings, 2474 num_storage_texture_bindings, 2475 storage_buffer_bindings, 2476 num_storage_buffer_bindings); 2477 2478 commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; 2479 2480 if (COMMAND_BUFFER_DEVICE->debug_mode) { 2481 commandBufferHeader->compute_pass.in_progress = true; 2482 2483 for (Uint32 i = 0; i < num_storage_texture_bindings; i += 1) { 2484 commandBufferHeader->compute_pass.read_write_storage_texture_bound[i] = true; 2485 } 2486 2487 for (Uint32 i = 0; i < num_storage_buffer_bindings; i += 1) { 2488 commandBufferHeader->compute_pass.read_write_storage_buffer_bound[i] = true; 2489 } 2490 } 2491 2492 return (SDL_GPUComputePass *)&(commandBufferHeader->compute_pass); 2493} 2494 2495void SDL_BindGPUComputePipeline( 2496 SDL_GPUComputePass *compute_pass, 2497 SDL_GPUComputePipeline *compute_pipeline) 2498{ 2499 CHECK_PARAM(compute_pass == NULL) { 2500 SDL_InvalidParamError("compute_pass"); 2501 return; 2502 } 2503 CHECK_PARAM(compute_pipeline == NULL) { 2504 SDL_InvalidParamError("compute_pipeline"); 2505 return; 2506 } 2507 2508 if (COMPUTEPASS_DEVICE->debug_mode) { 2509 CHECK_COMPUTEPASS 2510 } 2511 2512 COMPUTEPASS_DEVICE->BindComputePipeline( 2513 COMPUTEPASS_COMMAND_BUFFER, 2514 compute_pipeline); 2515 2516 2517 if (COMPUTEPASS_DEVICE->debug_mode) { 2518 COMPUTEPASS_BOUND_PIPELINE = compute_pipeline; 2519 } 2520} 2521 2522void SDL_BindGPUComputeSamplers( 2523 SDL_GPUComputePass *compute_pass, 2524 Uint32 first_slot, 2525 const SDL_GPUTextureSamplerBinding *texture_sampler_bindings, 2526 Uint32 num_bindings) 2527{ 2528 CHECK_PARAM(compute_pass == NULL) { 2529 SDL_InvalidParamError("compute_pass"); 2530 return; 2531 } 2532 CHECK_PARAM(texture_sampler_bindings == NULL && num_bindings > 0) { 2533 SDL_InvalidParamError("texture_sampler_bindings"); 2534 return; 2535 } 2536 CHECK_PARAM(first_slot + num_bindings > MAX_TEXTURE_SAMPLERS_PER_STAGE) { 2537 SDL_SetError("first_slot + num_bindings exceeds MAX_TEXTURE_SAMPLERS_PER_STAGE"); 2538 return; 2539 } 2540 2541 if (COMPUTEPASS_DEVICE->debug_mode) { 2542 CHECK_COMPUTEPASS 2543 2544 for (Uint32 i = 0; i < num_bindings; i += 1) { 2545 ((ComputePass *)compute_pass)->sampler_bound[first_slot + i] = true; 2546 } 2547 } 2548 2549 COMPUTEPASS_DEVICE->BindComputeSamplers( 2550 COMPUTEPASS_COMMAND_BUFFER, 2551 first_slot, 2552 texture_sampler_bindings, 2553 num_bindings); 2554} 2555 2556void SDL_BindGPUComputeStorageTextures( 2557 SDL_GPUComputePass *compute_pass, 2558 Uint32 first_slot, 2559 SDL_GPUTexture *const *storage_textures, 2560 Uint32 num_bindings) 2561{ 2562 CHECK_PARAM(compute_pass == NULL) { 2563 SDL_InvalidParamError("compute_pass"); 2564 return; 2565 } 2566 CHECK_PARAM(storage_textures == NULL && num_bindings > 0) { 2567 SDL_InvalidParamError("storage_textures"); 2568 return; 2569 } 2570 CHECK_PARAM(first_slot + num_bindings > MAX_STORAGE_TEXTURES_PER_STAGE) { 2571 SDL_SetError("first_slot + num_bindings exceeds MAX_STORAGE_TEXTURES_PER_STAGE"); 2572 return; 2573 } 2574 2575 if (COMPUTEPASS_DEVICE->debug_mode) { 2576 CHECK_COMPUTEPASS 2577 2578 for (Uint32 i = 0; i < num_bindings; i += 1) { 2579 ((ComputePass *)compute_pass)->read_only_storage_texture_bound[first_slot + i] = true; 2580 } 2581 } 2582 2583 COMPUTEPASS_DEVICE->BindComputeStorageTextures( 2584 COMPUTEPASS_COMMAND_BUFFER, 2585 first_slot, 2586 storage_textures, 2587 num_bindings); 2588} 2589 2590void SDL_BindGPUComputeStorageBuffers( 2591 SDL_GPUComputePass *compute_pass, 2592 Uint32 first_slot, 2593 SDL_GPUBuffer *const *storage_buffers, 2594 Uint32 num_bindings) 2595{ 2596 CHECK_PARAM(compute_pass == NULL) { 2597 SDL_InvalidParamError("compute_pass"); 2598 return; 2599 } 2600 CHECK_PARAM(storage_buffers == NULL && num_bindings > 0) { 2601 SDL_InvalidParamError("storage_buffers"); 2602 return; 2603 } 2604 CHECK_PARAM(first_slot + num_bindings > MAX_STORAGE_BUFFERS_PER_STAGE) { 2605 SDL_SetError("first_slot + num_bindings exceeds MAX_STORAGE_BUFFERS_PER_STAGE"); 2606 return; 2607 } 2608 2609 if (COMPUTEPASS_DEVICE->debug_mode) { 2610 CHECK_COMPUTEPASS 2611 2612 for (Uint32 i = 0; i < num_bindings; i += 1) { 2613 ((ComputePass *)compute_pass)->read_only_storage_buffer_bound[first_slot + i] = true; 2614 } 2615 } 2616 2617 COMPUTEPASS_DEVICE->BindComputeStorageBuffers( 2618 COMPUTEPASS_COMMAND_BUFFER, 2619 first_slot, 2620 storage_buffers, 2621 num_bindings); 2622} 2623 2624void SDL_DispatchGPUCompute( 2625 SDL_GPUComputePass *compute_pass, 2626 Uint32 groupcount_x, 2627 Uint32 groupcount_y, 2628 Uint32 groupcount_z) 2629{ 2630 CHECK_PARAM(compute_pass == NULL) { 2631 SDL_InvalidParamError("compute_pass"); 2632 return; 2633 } 2634 2635 if (COMPUTEPASS_DEVICE->debug_mode) { 2636 CHECK_COMPUTEPASS 2637 CHECK_COMPUTE_PIPELINE_BOUND 2638 SDL_GPU_CheckComputeBindings(compute_pass); 2639 } 2640 2641 COMPUTEPASS_DEVICE->DispatchCompute( 2642 COMPUTEPASS_COMMAND_BUFFER, 2643 groupcount_x, 2644 groupcount_y, 2645 groupcount_z); 2646} 2647 2648void SDL_DispatchGPUComputeIndirect( 2649 SDL_GPUComputePass *compute_pass, 2650 SDL_GPUBuffer *buffer, 2651 Uint32 offset) 2652{ 2653 CHECK_PARAM(compute_pass == NULL) { 2654 SDL_InvalidParamError("compute_pass"); 2655 return; 2656 } 2657 2658 if (COMPUTEPASS_DEVICE->debug_mode) { 2659 CHECK_COMPUTEPASS 2660 CHECK_COMPUTE_PIPELINE_BOUND 2661 SDL_GPU_CheckComputeBindings(compute_pass); 2662 } 2663 2664 COMPUTEPASS_DEVICE->DispatchComputeIndirect( 2665 COMPUTEPASS_COMMAND_BUFFER, 2666 buffer, 2667 offset); 2668} 2669 2670void SDL_EndGPUComputePass( 2671 SDL_GPUComputePass *compute_pass) 2672{ 2673 CommandBufferCommonHeader *commandBufferCommonHeader; 2674 2675 CHECK_PARAM(compute_pass == NULL) { 2676 SDL_InvalidParamError("compute_pass"); 2677 return; 2678 } 2679 2680 if (COMPUTEPASS_DEVICE->debug_mode) { 2681 CHECK_COMPUTEPASS 2682 } 2683 2684 COMPUTEPASS_DEVICE->EndComputePass( 2685 COMPUTEPASS_COMMAND_BUFFER); 2686 2687 if (COMPUTEPASS_DEVICE->debug_mode) { 2688 commandBufferCommonHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER; 2689 commandBufferCommonHeader->compute_pass.in_progress = false; 2690 commandBufferCommonHeader->compute_pass.compute_pipeline = NULL; 2691 SDL_zeroa(commandBufferCommonHeader->compute_pass.sampler_bound); 2692 SDL_zeroa(commandBufferCommonHeader->compute_pass.read_only_storage_texture_bound); 2693 SDL_zeroa(commandBufferCommonHeader->compute_pass.read_only_storage_buffer_bound); 2694 SDL_zeroa(commandBufferCommonHeader->compute_pass.read_write_storage_texture_bound); 2695 SDL_zeroa(commandBufferCommonHeader->compute_pass.read_write_storage_buffer_bound); 2696 } 2697} 2698 2699// TransferBuffer Data 2700 2701void *SDL_MapGPUTransferBuffer( 2702 SDL_GPUDevice *device, 2703 SDL_GPUTransferBuffer *transfer_buffer, 2704 bool cycle) 2705{ 2706 CHECK_DEVICE_MAGIC(device, NULL); 2707 2708 CHECK_PARAM(transfer_buffer == NULL) { 2709 SDL_InvalidParamError("transfer_buffer"); 2710 return NULL; 2711 } 2712 2713 return device->MapTransferBuffer( 2714 device->driverData, 2715 transfer_buffer, 2716 cycle); 2717} 2718 2719void SDL_UnmapGPUTransferBuffer( 2720 SDL_GPUDevice *device, 2721 SDL_GPUTransferBuffer *transfer_buffer) 2722{ 2723 CHECK_DEVICE_MAGIC(device, ); 2724 2725 CHECK_PARAM(transfer_buffer == NULL) { 2726 SDL_InvalidParamError("transfer_buffer"); 2727 return; 2728 } 2729 2730 device->UnmapTransferBuffer( 2731 device->driverData, 2732 transfer_buffer); 2733} 2734 2735// Copy Pass 2736 2737SDL_GPUCopyPass *SDL_BeginGPUCopyPass( 2738 SDL_GPUCommandBuffer *command_buffer) 2739{ 2740 CommandBufferCommonHeader *commandBufferHeader; 2741 2742 CHECK_PARAM(command_buffer == NULL) { 2743 SDL_InvalidParamError("command_buffer"); 2744 return NULL; 2745 } 2746 2747 if (COMMAND_BUFFER_DEVICE->debug_mode) { 2748 CHECK_COMMAND_BUFFER_RETURN_NULL 2749 CHECK_ANY_PASS_IN_PROGRESS("Cannot begin copy pass during another pass!", NULL) 2750 } 2751 2752 COMMAND_BUFFER_DEVICE->BeginCopyPass( 2753 command_buffer); 2754 2755 commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; 2756 2757 if (COMMAND_BUFFER_DEVICE->debug_mode) { 2758 commandBufferHeader->copy_pass.in_progress = true; 2759 } 2760 2761 return (SDL_GPUCopyPass *)&(commandBufferHeader->copy_pass); 2762} 2763 2764void SDL_UploadToGPUTexture( 2765 SDL_GPUCopyPass *copy_pass, 2766 const SDL_GPUTextureTransferInfo *source, 2767 const SDL_GPUTextureRegion *destination, 2768 bool cycle) 2769{ 2770 CHECK_PARAM(copy_pass == NULL) { 2771 SDL_InvalidParamError("copy_pass"); 2772 return; 2773 } 2774 CHECK_PARAM(source == NULL) { 2775 SDL_InvalidParamError("source"); 2776 return; 2777 } 2778 if (destination == NULL) { 2779 SDL_InvalidParamError("destination"); 2780 return; 2781 } 2782 2783 if (COPYPASS_DEVICE->debug_mode) { 2784 CHECK_COPYPASS 2785 if (source->transfer_buffer == NULL) { 2786 SDL_assert_release(!"Source transfer buffer cannot be NULL!"); 2787 return; 2788 } 2789 if (destination->texture == NULL) { 2790 SDL_assert_release(!"Destination texture cannot be NULL!"); 2791 return; 2792 } 2793 } 2794 2795 COPYPASS_DEVICE->UploadToTexture( 2796 COPYPASS_COMMAND_BUFFER, 2797 source, 2798 destination, 2799 cycle); 2800} 2801 2802void SDL_UploadToGPUBuffer( 2803 SDL_GPUCopyPass *copy_pass, 2804 const SDL_GPUTransferBufferLocation *source, 2805 const SDL_GPUBufferRegion *destination, 2806 bool cycle) 2807{ 2808 CHECK_PARAM(copy_pass == NULL) { 2809 SDL_InvalidParamError("copy_pass"); 2810 return; 2811 } 2812 CHECK_PARAM(source == NULL) { 2813 SDL_InvalidParamError("source"); 2814 return; 2815 } 2816 CHECK_PARAM(destination == NULL) { 2817 SDL_InvalidParamError("destination"); 2818 return; 2819 } 2820 2821 if (COPYPASS_DEVICE->debug_mode) { 2822 CHECK_COPYPASS 2823 if (source->transfer_buffer == NULL) { 2824 SDL_assert_release(!"Source transfer buffer cannot be NULL!"); 2825 return; 2826 } 2827 if (destination->buffer == NULL) { 2828 SDL_assert_release(!"Destination buffer cannot be NULL!"); 2829 return; 2830 } 2831 } 2832 2833 COPYPASS_DEVICE->UploadToBuffer( 2834 COPYPASS_COMMAND_BUFFER, 2835 source, 2836 destination, 2837 cycle); 2838} 2839 2840void SDL_CopyGPUTextureToTexture( 2841 SDL_GPUCopyPass *copy_pass, 2842 const SDL_GPUTextureLocation *source, 2843 const SDL_GPUTextureLocation *destination, 2844 Uint32 w, 2845 Uint32 h, 2846 Uint32 d, 2847 bool cycle) 2848{ 2849 CHECK_PARAM(copy_pass == NULL) { 2850 SDL_InvalidParamError("copy_pass"); 2851 return; 2852 } 2853 CHECK_PARAM(source == NULL) { 2854 SDL_InvalidParamError("source"); 2855 return; 2856 } 2857 CHECK_PARAM(destination == NULL) { 2858 SDL_InvalidParamError("destination"); 2859 return; 2860 } 2861 2862 if (COPYPASS_DEVICE->debug_mode) { 2863 CHECK_COPYPASS 2864 if (source->texture == NULL) { 2865 SDL_assert_release(!"Source texture cannot be NULL!"); 2866 return; 2867 } 2868 if (destination->texture == NULL) { 2869 SDL_assert_release(!"Destination texture cannot be NULL!"); 2870 return; 2871 } 2872 2873 TextureCommonHeader *srcHeader = (TextureCommonHeader *)source->texture; 2874 TextureCommonHeader *dstHeader = (TextureCommonHeader *)destination->texture; 2875 if (srcHeader->info.format != dstHeader->info.format) { 2876 SDL_assert_release(!"Source and destination textures must have the same format!"); 2877 return; 2878 } 2879 } 2880 2881 COPYPASS_DEVICE->CopyTextureToTexture( 2882 COPYPASS_COMMAND_BUFFER, 2883 source, 2884 destination, 2885 w, 2886 h, 2887 d, 2888 cycle); 2889} 2890 2891void SDL_CopyGPUBufferToBuffer( 2892 SDL_GPUCopyPass *copy_pass, 2893 const SDL_GPUBufferLocation *source, 2894 const SDL_GPUBufferLocation *destination, 2895 Uint32 size, 2896 bool cycle) 2897{ 2898 CHECK_PARAM(copy_pass == NULL) { 2899 SDL_InvalidParamError("copy_pass"); 2900 return; 2901 } 2902 CHECK_PARAM(source == NULL) { 2903 SDL_InvalidParamError("source"); 2904 return; 2905 } 2906 CHECK_PARAM(destination == NULL) { 2907 SDL_InvalidParamError("destination"); 2908 return; 2909 } 2910 2911 if (COPYPASS_DEVICE->debug_mode) { 2912 CHECK_COPYPASS 2913 if (source->buffer == NULL) { 2914 SDL_assert_release(!"Source buffer cannot be NULL!"); 2915 return; 2916 } 2917 if (destination->buffer == NULL) { 2918 SDL_assert_release(!"Destination buffer cannot be NULL!"); 2919 return; 2920 } 2921 } 2922 2923 COPYPASS_DEVICE->CopyBufferToBuffer( 2924 COPYPASS_COMMAND_BUFFER, 2925 source, 2926 destination, 2927 size, 2928 cycle); 2929} 2930 2931void SDL_DownloadFromGPUTexture( 2932 SDL_GPUCopyPass *copy_pass, 2933 const SDL_GPUTextureRegion *source, 2934 const SDL_GPUTextureTransferInfo *destination) 2935{ 2936 CHECK_PARAM(copy_pass == NULL) { 2937 SDL_InvalidParamError("copy_pass"); 2938 return; 2939 } 2940 CHECK_PARAM(source == NULL) { 2941 SDL_InvalidParamError("source"); 2942 return; 2943 } 2944 CHECK_PARAM(destination == NULL) { 2945 SDL_InvalidParamError("destination"); 2946 return; 2947 } 2948 2949 if (COPYPASS_DEVICE->debug_mode) { 2950 CHECK_COPYPASS 2951 if (source->texture == NULL) { 2952 SDL_assert_release(!"Source texture cannot be NULL!"); 2953 return; 2954 } 2955 if (destination->transfer_buffer == NULL) { 2956 SDL_assert_release(!"Destination transfer buffer cannot be NULL!"); 2957 return; 2958 } 2959 } 2960 2961 COPYPASS_DEVICE->DownloadFromTexture( 2962 COPYPASS_COMMAND_BUFFER, 2963 source, 2964 destination); 2965} 2966 2967void SDL_DownloadFromGPUBuffer( 2968 SDL_GPUCopyPass *copy_pass, 2969 const SDL_GPUBufferRegion *source, 2970 const SDL_GPUTransferBufferLocation *destination) 2971{ 2972 CHECK_PARAM(copy_pass == NULL) { 2973 SDL_InvalidParamError("copy_pass"); 2974 return; 2975 } 2976 CHECK_PARAM(source == NULL) { 2977 SDL_InvalidParamError("source"); 2978 return; 2979 } 2980 CHECK_PARAM(destination == NULL) { 2981 SDL_InvalidParamError("destination"); 2982 return; 2983 } 2984 2985 if (COPYPASS_DEVICE->debug_mode) { 2986 CHECK_COPYPASS 2987 if (source->buffer == NULL) { 2988 SDL_assert_release(!"Source buffer cannot be NULL!"); 2989 return; 2990 } 2991 if (destination->transfer_buffer == NULL) { 2992 SDL_assert_release(!"Destination transfer buffer cannot be NULL!"); 2993 return; 2994 } 2995 } 2996 2997 COPYPASS_DEVICE->DownloadFromBuffer( 2998 COPYPASS_COMMAND_BUFFER, 2999 source, 3000 destination); 3001} 3002 3003void SDL_EndGPUCopyPass( 3004 SDL_GPUCopyPass *copy_pass) 3005{ 3006 CHECK_PARAM(copy_pass == NULL) { 3007 SDL_InvalidParamError("copy_pass"); 3008 return; 3009 } 3010 3011 if (COPYPASS_DEVICE->debug_mode) { 3012 CHECK_COPYPASS 3013 } 3014 3015 COPYPASS_DEVICE->EndCopyPass( 3016 COPYPASS_COMMAND_BUFFER); 3017 3018 if (COPYPASS_DEVICE->debug_mode) { 3019 ((CommandBufferCommonHeader *)COPYPASS_COMMAND_BUFFER)->copy_pass.in_progress = false; 3020 } 3021} 3022 3023void SDL_GenerateMipmapsForGPUTexture( 3024 SDL_GPUCommandBuffer *command_buffer, 3025 SDL_GPUTexture *texture) 3026{ 3027 CHECK_PARAM(command_buffer == NULL) { 3028 SDL_InvalidParamError("command_buffer"); 3029 return; 3030 } 3031 CHECK_PARAM(texture == NULL) { 3032 SDL_InvalidParamError("texture"); 3033 return; 3034 } 3035 3036 if (COMMAND_BUFFER_DEVICE->debug_mode) { 3037 CHECK_COMMAND_BUFFER 3038 CHECK_ANY_PASS_IN_PROGRESS("Cannot generate mipmaps during a pass!", ) 3039 3040 TextureCommonHeader *header = (TextureCommonHeader *)texture; 3041 if (header->info.num_levels <= 1) { 3042 SDL_assert_release(!"Cannot generate mipmaps for texture with num_levels <= 1!"); 3043 return; 3044 } 3045 3046 if (!(header->info.usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) || !(header->info.usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET)) { 3047 SDL_assert_release(!"GenerateMipmaps texture must be created with SAMPLER and COLOR_TARGET usage flags!"); 3048 return; 3049 } 3050 3051 CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; 3052 commandBufferHeader->ignore_render_pass_texture_validation = true; 3053 } 3054 3055 COMMAND_BUFFER_DEVICE->GenerateMipmaps( 3056 command_buffer, 3057 texture); 3058 3059 if (COMMAND_BUFFER_DEVICE->debug_mode) { 3060 CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; 3061 commandBufferHeader->ignore_render_pass_texture_validation = false; 3062 } 3063} 3064 3065void SDL_BlitGPUTexture( 3066 SDL_GPUCommandBuffer *command_buffer, 3067 const SDL_GPUBlitInfo *info) 3068{ 3069 CHECK_PARAM(command_buffer == NULL) { 3070 SDL_InvalidParamError("command_buffer"); 3071 return; 3072 } 3073 CHECK_PARAM(info == NULL) { 3074 SDL_InvalidParamError("info"); 3075 return; 3076 } 3077 3078 if (COMMAND_BUFFER_DEVICE->debug_mode) { 3079 CHECK_COMMAND_BUFFER 3080 CHECK_ANY_PASS_IN_PROGRESS("Cannot blit during a pass!", ) 3081 3082 // Validation 3083 bool failed = false; 3084 TextureCommonHeader *srcHeader = (TextureCommonHeader *)info->source.texture; 3085 TextureCommonHeader *dstHeader = (TextureCommonHeader *)info->destination.texture; 3086 3087 if (srcHeader == NULL) { 3088 SDL_assert_release(!"Blit source texture must be non-NULL"); 3089 return; // attempting to proceed will crash 3090 } 3091 if (dstHeader == NULL) { 3092 SDL_assert_release(!"Blit destination texture must be non-NULL"); 3093 return; // attempting to proceed will crash 3094 } 3095 if (srcHeader->info.sample_count != SDL_GPU_SAMPLECOUNT_1) { 3096 SDL_assert_release(!"Blit source texture must have a sample count of 1"); 3097 failed = true; 3098 } 3099 if ((srcHeader->info.usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) == 0) { 3100 SDL_assert_release(!"Blit source texture must be created with the SAMPLER usage flag"); 3101 failed = true; 3102 } 3103 if ((dstHeader->info.usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) == 0) { 3104 SDL_assert_release(!"Blit destination texture must be created with the COLOR_TARGET usage flag"); 3105 failed = true; 3106 } 3107 if (IsDepthFormat(srcHeader->info.format)) { 3108 SDL_assert_release(!"Blit source texture cannot have a depth format"); 3109 failed = true; 3110 } 3111 if (info->source.w == 0 || info->source.h == 0 || info->destination.w == 0 || info->destination.h == 0) { 3112 SDL_assert_release(!"Blit source/destination regions must have non-zero width, height, and depth"); 3113 failed = true; 3114 } 3115 3116 if (failed) { 3117 return; 3118 } 3119 } 3120 3121 COMMAND_BUFFER_DEVICE->Blit( 3122 command_buffer, 3123 info); 3124} 3125 3126// Submission/Presentation 3127 3128bool SDL_WindowSupportsGPUSwapchainComposition( 3129 SDL_GPUDevice *device, 3130 SDL_Window *window, 3131 SDL_GPUSwapchainComposition swapchain_composition) 3132{ 3133 CHECK_DEVICE_MAGIC(device, false); 3134 3135 CHECK_PARAM(window == NULL) { 3136 SDL_InvalidParamError("window"); 3137 return false; 3138 } 3139 3140 if (device->debug_mode) { 3141 CHECK_SWAPCHAINCOMPOSITION_ENUM_INVALID(swapchain_composition, false) 3142 } 3143 3144 return device->SupportsSwapchainComposition( 3145 device->driverData, 3146 window, 3147 swapchain_composition); 3148} 3149 3150bool SDL_WindowSupportsGPUPresentMode( 3151 SDL_GPUDevice *device, 3152 SDL_Window *window, 3153 SDL_GPUPresentMode present_mode) 3154{ 3155 CHECK_DEVICE_MAGIC(device, false); 3156 3157 CHECK_PARAM(window == NULL) { 3158 SDL_InvalidParamError("window"); 3159 return false; 3160 } 3161 3162 if (device->debug_mode) { 3163 CHECK_PRESENTMODE_ENUM_INVALID(present_mode, false) 3164 } 3165 3166 return device->SupportsPresentMode( 3167 device->driverData, 3168 window, 3169 present_mode); 3170} 3171 3172bool SDL_ClaimWindowForGPUDevice( 3173 SDL_GPUDevice *device, 3174 SDL_Window *window) 3175{ 3176 CHECK_DEVICE_MAGIC(device, false); 3177 3178 CHECK_PARAM(window == NULL) { 3179 return SDL_InvalidParamError("window"); 3180 } 3181 3182 if ((window->flags & SDL_WINDOW_TRANSPARENT) != 0) { 3183 return SDL_SetError("The GPU API doesn't support transparent windows"); 3184 } 3185 3186 return device->ClaimWindow( 3187 device->driverData, 3188 window); 3189} 3190 3191void SDL_ReleaseWindowFromGPUDevice( 3192 SDL_GPUDevice *device, 3193 SDL_Window *window) 3194{ 3195 CHECK_DEVICE_MAGIC(device, ); 3196 3197 CHECK_PARAM(window == NULL) { 3198 SDL_InvalidParamError("window"); 3199 return; 3200 } 3201 3202 device->ReleaseWindow( 3203 device->driverData, 3204 window); 3205} 3206 3207bool SDL_SetGPUSwapchainParameters( 3208 SDL_GPUDevice *device, 3209 SDL_Window *window, 3210 SDL_GPUSwapchainComposition swapchain_composition, 3211 SDL_GPUPresentMode present_mode) 3212{ 3213 CHECK_DEVICE_MAGIC(device, false); 3214 3215 CHECK_PARAM(window == NULL) { 3216 SDL_InvalidParamError("window"); 3217 return false; 3218 } 3219 3220 if (device->debug_mode) { 3221 CHECK_SWAPCHAINCOMPOSITION_ENUM_INVALID(swapchain_composition, false) 3222 CHECK_PRESENTMODE_ENUM_INVALID(present_mode, false) 3223 } 3224 3225 return device->SetSwapchainParameters( 3226 device->driverData, 3227 window, 3228 swapchain_composition, 3229 present_mode); 3230} 3231 3232bool SDL_SetGPUAllowedFramesInFlight( 3233 SDL_GPUDevice *device, 3234 Uint32 allowed_frames_in_flight) 3235{ 3236 CHECK_DEVICE_MAGIC(device, false); 3237 3238 if (device->debug_mode) { 3239 if (allowed_frames_in_flight < 1 || allowed_frames_in_flight > 3) 3240 { 3241 SDL_COMPILE_TIME_ASSERT(max_frames_in_flight, MAX_FRAMES_IN_FLIGHT == 3); 3242 SDL_assert_release(!"allowed_frames_in_flight value must be between 1 and 3!"); 3243 } 3244 } 3245 3246 allowed_frames_in_flight = SDL_clamp(allowed_frames_in_flight, 1, 3); 3247 return device->SetAllowedFramesInFlight( 3248 device->driverData, 3249 allowed_frames_in_flight); 3250} 3251 3252SDL_GPUTextureFormat SDL_GetGPUSwapchainTextureFormat( 3253 SDL_GPUDevice *device, 3254 SDL_Window *window) 3255{ 3256 CHECK_DEVICE_MAGIC(device, SDL_GPU_TEXTUREFORMAT_INVALID); 3257 3258 CHECK_PARAM(window == NULL) { 3259 SDL_InvalidParamError("window"); 3260 return SDL_GPU_TEXTUREFORMAT_INVALID; 3261 } 3262 3263 return device->GetSwapchainTextureFormat( 3264 device->driverData, 3265 window); 3266} 3267 3268bool SDL_AcquireGPUSwapchainTexture( 3269 SDL_GPUCommandBuffer *command_buffer, 3270 SDL_Window *window, 3271 SDL_GPUTexture **swapchain_texture, 3272 Uint32 *swapchain_texture_width, 3273 Uint32 *swapchain_texture_height) 3274{ 3275 CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; 3276 3277 CHECK_PARAM(command_buffer == NULL) { 3278 return SDL_InvalidParamError("command_buffer"); 3279 } 3280 CHECK_PARAM(window == NULL) { 3281 return SDL_InvalidParamError("window"); 3282 } 3283 CHECK_PARAM(swapchain_texture == NULL) { 3284 return SDL_InvalidParamError("swapchain_texture"); 3285 } 3286 3287 if (COMMAND_BUFFER_DEVICE->debug_mode) { 3288 CHECK_COMMAND_BUFFER_RETURN_FALSE 3289 CHECK_ANY_PASS_IN_PROGRESS("Cannot acquire a swapchain texture during a pass!", false) 3290 } 3291 3292 bool result = COMMAND_BUFFER_DEVICE->AcquireSwapchainTexture( 3293 command_buffer, 3294 window, 3295 swapchain_texture, 3296 swapchain_texture_width, 3297 swapchain_texture_height); 3298 3299 if (*swapchain_texture != NULL){ 3300 commandBufferHeader->swapchain_texture_acquired = true; 3301 } 3302 3303 return result; 3304} 3305 3306bool SDL_WaitForGPUSwapchain( 3307 SDL_GPUDevice *device, 3308 SDL_Window *window) 3309{ 3310 CHECK_DEVICE_MAGIC(device, false); 3311 3312 CHECK_PARAM(window == NULL) { 3313 return SDL_InvalidParamError("window"); 3314 } 3315 3316 return device->WaitForSwapchain( 3317 device->driverData, 3318 window); 3319} 3320 3321bool SDL_WaitAndAcquireGPUSwapchainTexture( 3322 SDL_GPUCommandBuffer *command_buffer, 3323 SDL_Window *window, 3324 SDL_GPUTexture **swapchain_texture, 3325 Uint32 *swapchain_texture_width, 3326 Uint32 *swapchain_texture_height) 3327{ 3328 CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; 3329 3330 CHECK_PARAM(command_buffer == NULL) { 3331 return SDL_InvalidParamError("command_buffer"); 3332 } 3333 CHECK_PARAM(window == NULL) { 3334 return SDL_InvalidParamError("window"); 3335 } 3336 CHECK_PARAM(swapchain_texture == NULL) { 3337 return SDL_InvalidParamError("swapchain_texture"); 3338 } 3339 3340 if (COMMAND_BUFFER_DEVICE->debug_mode) { 3341 CHECK_COMMAND_BUFFER_RETURN_FALSE 3342 CHECK_ANY_PASS_IN_PROGRESS("Cannot acquire a swapchain texture during a pass!", false) 3343 } 3344 3345 bool result = COMMAND_BUFFER_DEVICE->WaitAndAcquireSwapchainTexture( 3346 command_buffer, 3347 window, 3348 swapchain_texture, 3349 swapchain_texture_width, 3350 swapchain_texture_height); 3351 3352 if (*swapchain_texture != NULL){ 3353 commandBufferHeader->swapchain_texture_acquired = true; 3354 } 3355 3356 return result; 3357} 3358 3359bool SDL_SubmitGPUCommandBuffer( 3360 SDL_GPUCommandBuffer *command_buffer) 3361{ 3362 CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; 3363 3364 CHECK_PARAM(command_buffer == NULL) { 3365 SDL_InvalidParamError("command_buffer"); 3366 return false; 3367 } 3368 3369 if (COMMAND_BUFFER_DEVICE->debug_mode) { 3370 CHECK_COMMAND_BUFFER_RETURN_FALSE 3371 if ( 3372 commandBufferHeader->render_pass.in_progress || 3373 commandBufferHeader->compute_pass.in_progress || 3374 commandBufferHeader->copy_pass.in_progress) { 3375 SDL_assert_release(!"Cannot submit command buffer while a pass is in progress!"); 3376 return false; 3377 } 3378 } 3379 3380 commandBufferHeader->submitted = true; 3381 3382 return COMMAND_BUFFER_DEVICE->Submit( 3383 command_buffer); 3384} 3385 3386SDL_GPUFence *SDL_SubmitGPUCommandBufferAndAcquireFence( 3387 SDL_GPUCommandBuffer *command_buffer) 3388{ 3389 CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; 3390 3391 CHECK_PARAM(command_buffer == NULL) { 3392 SDL_InvalidParamError("command_buffer"); 3393 return NULL; 3394 } 3395 3396 if (COMMAND_BUFFER_DEVICE->debug_mode) { 3397 CHECK_COMMAND_BUFFER_RETURN_NULL 3398 if ( 3399 commandBufferHeader->render_pass.in_progress || 3400 commandBufferHeader->compute_pass.in_progress || 3401 commandBufferHeader->copy_pass.in_progress) { 3402 SDL_assert_release(!"Cannot submit command buffer while a pass is in progress!"); 3403 return NULL; 3404 } 3405 } 3406 3407 commandBufferHeader->submitted = true; 3408 3409 return COMMAND_BUFFER_DEVICE->SubmitAndAcquireFence( 3410 command_buffer); 3411} 3412 3413bool SDL_CancelGPUCommandBuffer( 3414 SDL_GPUCommandBuffer *command_buffer) 3415{ 3416 CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; 3417 3418 CHECK_PARAM(command_buffer == NULL) { 3419 SDL_InvalidParamError("command_buffer"); 3420 return false; 3421 } 3422 3423 if (COMMAND_BUFFER_DEVICE->debug_mode) { 3424 if (commandBufferHeader->swapchain_texture_acquired) { 3425 SDL_assert_release(!"Cannot cancel command buffer after a swapchain texture has been acquired!"); 3426 return false; 3427 } 3428 } 3429 3430 return COMMAND_BUFFER_DEVICE->Cancel( 3431 command_buffer); 3432} 3433 3434bool SDL_WaitForGPUIdle( 3435 SDL_GPUDevice *device) 3436{ 3437 CHECK_DEVICE_MAGIC(device, false); 3438 3439 return device->Wait( 3440 device->driverData); 3441} 3442 3443bool SDL_WaitForGPUFences( 3444 SDL_GPUDevice *device, 3445 bool wait_all, 3446 SDL_GPUFence *const *fences, 3447 Uint32 num_fences) 3448{ 3449 CHECK_DEVICE_MAGIC(device, false); 3450 3451 CHECK_PARAM(fences == NULL && num_fences > 0) { 3452 SDL_InvalidParamError("fences"); 3453 return false; 3454 } 3455 3456 return device->WaitForFences( 3457 device->driverData, 3458 wait_all, 3459 fences, 3460 num_fences); 3461} 3462 3463bool SDL_QueryGPUFence( 3464 SDL_GPUDevice *device, 3465 SDL_GPUFence *fence) 3466{ 3467 CHECK_DEVICE_MAGIC(device, false); 3468 3469 CHECK_PARAM(fence == NULL) { 3470 SDL_InvalidParamError("fence"); 3471 return false; 3472 } 3473 3474 return device->QueryFence( 3475 device->driverData, 3476 fence); 3477} 3478 3479void SDL_ReleaseGPUFence( 3480 SDL_GPUDevice *device, 3481 SDL_GPUFence *fence) 3482{ 3483 CHECK_DEVICE_MAGIC(device, ); 3484 3485 CHECK_PARAM(fence == NULL) { 3486 return; 3487 } 3488 3489 device->ReleaseFence( 3490 device->driverData, 3491 fence); 3492} 3493 3494Uint32 SDL_CalculateGPUTextureFormatSize( 3495 SDL_GPUTextureFormat format, 3496 Uint32 width, 3497 Uint32 height, 3498 Uint32 depth_or_layer_count) 3499{ 3500 Uint32 blockWidth = SDL_max(Texture_GetBlockWidth(format), 1); 3501 Uint32 blockHeight = SDL_max(Texture_GetBlockHeight(format), 1); 3502 Uint32 blocksPerRow = (width + blockWidth - 1) / blockWidth; 3503 Uint32 blocksPerColumn = (height + blockHeight - 1) / blockHeight; 3504 return depth_or_layer_count * blocksPerRow * blocksPerColumn * SDL_GPUTextureFormatTexelBlockSize(format); 3505} 3506 3507SDL_PixelFormat SDL_GetPixelFormatFromGPUTextureFormat(SDL_GPUTextureFormat format) 3508{ 3509 switch (format) { 3510 case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM: 3511 return SDL_PIXELFORMAT_BGRA4444; 3512 case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM: 3513 return SDL_PIXELFORMAT_BGR565; 3514 case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM: 3515 return SDL_PIXELFORMAT_BGRA5551; 3516 case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT: 3517 return SDL_PIXELFORMAT_RGBA32; 3518 case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM: 3519 return SDL_PIXELFORMAT_RGBA32; 3520 case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM: 3521 return SDL_PIXELFORMAT_RGBA32; 3522 case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB: 3523 return SDL_PIXELFORMAT_RGBA32; 3524 case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM: 3525 return SDL_PIXELFORMAT_BGRA32; 3526 case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB: 3527 return SDL_PIXELFORMAT_BGRA32; 3528 case SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM: 3529 return SDL_PIXELFORMAT_ABGR2101010; 3530 case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT: 3531 return SDL_PIXELFORMAT_RGBA64; 3532 case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM: 3533 return SDL_PIXELFORMAT_RGBA64; 3534 case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT: 3535 return SDL_PIXELFORMAT_RGBA64_FLOAT; 3536 case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT: 3537 return SDL_PIXELFORMAT_RGBA128_FLOAT; 3538 default: 3539 return SDL_PIXELFORMAT_UNKNOWN; 3540 } 3541} 3542 3543SDL_GPUTextureFormat SDL_GetGPUTextureFormatFromPixelFormat(SDL_PixelFormat format) 3544{ 3545 switch (format) { 3546 case SDL_PIXELFORMAT_BGRA4444: 3547 return SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM; 3548 case SDL_PIXELFORMAT_BGR565: 3549 return SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM; 3550 case SDL_PIXELFORMAT_BGRA5551: 3551 return SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM; 3552 case SDL_PIXELFORMAT_BGRA32: 3553 case SDL_PIXELFORMAT_BGRX32: 3554 return SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM; 3555 case SDL_PIXELFORMAT_RGBA32: 3556 case SDL_PIXELFORMAT_RGBX32: 3557 return SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; 3558 case SDL_PIXELFORMAT_ABGR2101010: 3559 return SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM; 3560 case SDL_PIXELFORMAT_RGBA64: 3561 return SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM; 3562 case SDL_PIXELFORMAT_RGBA64_FLOAT: 3563 return SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT; 3564 case SDL_PIXELFORMAT_RGBA128_FLOAT: 3565 return SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT; 3566 default: 3567 return SDL_GPU_TEXTUREFORMAT_INVALID; 3568 } 3569} 3570[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.