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