Skip to content

Commit a163257

Browse files
GPU: Validate that textures are not bound for both read and write on render passes (#12925)
1 parent ea67133 commit a163257

File tree

2 files changed

+76
-18
lines changed

2 files changed

+76
-18
lines changed

src/gpu/SDL_gpu.c

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,43 @@
5656
}
5757

5858
#define CHECK_RENDERPASS \
59-
if (!((Pass *)render_pass)->in_progress) { \
59+
if (!((RenderPass *)render_pass)->in_progress) { \
6060
SDL_assert_release(!"Render pass not in progress!"); \
6161
return; \
6262
}
6363

64+
#define CHECK_SAMPLER_TEXTURES \
65+
RenderPass *rp = (RenderPass *)render_pass; \
66+
for (Uint32 color_target_index = 0; color_target_index < rp->num_color_targets; color_target_index += 1) { \
67+
for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \
68+
if (rp->color_targets[color_target_index] == texture_sampler_bindings[texture_sampler_index].texture) { \
69+
SDL_assert_release(!"Texture cannot be simultaneously bound as a color target and a sampler!"); \
70+
} \
71+
} \
72+
} \
73+
\
74+
for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \
75+
if (rp->depth_stencil_target != NULL && rp->depth_stencil_target == texture_sampler_bindings[texture_sampler_index].texture) { \
76+
SDL_assert_release(!"Texture cannot be simultaneously bound as a depth stencil target and a sampler!"); \
77+
} \
78+
}
79+
80+
#define CHECK_STORAGE_TEXTURES \
81+
RenderPass *rp = (RenderPass *)render_pass; \
82+
for (Uint32 color_target_index = 0; color_target_index < rp->num_color_targets; color_target_index += 1) { \
83+
for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \
84+
if (rp->color_targets[color_target_index] == storage_textures[texture_sampler_index]) { \
85+
SDL_assert_release(!"Texture cannot be simultaneously bound as a color target and a storage texture!"); \
86+
} \
87+
} \
88+
} \
89+
\
90+
for (Uint32 texture_sampler_index = 0; texture_sampler_index < num_bindings; texture_sampler_index += 1) { \
91+
if (rp->depth_stencil_target != NULL && rp->depth_stencil_target == storage_textures[texture_sampler_index]) { \
92+
SDL_assert_release(!"Texture cannot be simultaneously bound as a depth stencil target and a storage texture!"); \
93+
} \
94+
}
95+
6496
#define CHECK_GRAPHICS_PIPELINE_BOUND \
6597
if (!((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->graphics_pipeline_bound) { \
6698
SDL_assert_release(!"Graphics pipeline not bound!"); \
@@ -137,7 +169,7 @@
137169
((CommandBufferCommonHeader *)command_buffer)->device
138170

139171
#define RENDERPASS_COMMAND_BUFFER \
140-
((Pass *)render_pass)->command_buffer
172+
((RenderPass *)render_pass)->command_buffer
141173

142174
#define RENDERPASS_DEVICE \
143175
((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->device
@@ -1544,6 +1576,13 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
15441576

15451577
commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
15461578
commandBufferHeader->render_pass.in_progress = true;
1579+
for (Uint32 i = 0; i < num_color_targets; i += 1) {
1580+
commandBufferHeader->render_pass.color_targets[i] = color_target_infos[i].texture;
1581+
}
1582+
commandBufferHeader->render_pass.num_color_targets = num_color_targets;
1583+
if (depth_stencil_target_info != NULL) {
1584+
commandBufferHeader->render_pass.depth_stencil_target = depth_stencil_target_info->texture;
1585+
}
15471586
return (SDL_GPURenderPass *)&(commandBufferHeader->render_pass);
15481587
}
15491588

@@ -1717,6 +1756,7 @@ void SDL_BindGPUVertexSamplers(
17171756

17181757
if (RENDERPASS_DEVICE->debug_mode) {
17191758
CHECK_RENDERPASS
1759+
CHECK_SAMPLER_TEXTURES
17201760
}
17211761

17221762
RENDERPASS_DEVICE->BindVertexSamplers(
@@ -1743,6 +1783,7 @@ void SDL_BindGPUVertexStorageTextures(
17431783

17441784
if (RENDERPASS_DEVICE->debug_mode) {
17451785
CHECK_RENDERPASS
1786+
CHECK_STORAGE_TEXTURES
17461787
}
17471788

17481789
RENDERPASS_DEVICE->BindVertexStorageTextures(
@@ -1795,6 +1836,7 @@ void SDL_BindGPUFragmentSamplers(
17951836

17961837
if (RENDERPASS_DEVICE->debug_mode) {
17971838
CHECK_RENDERPASS
1839+
CHECK_SAMPLER_TEXTURES
17981840
}
17991841

18001842
RENDERPASS_DEVICE->BindFragmentSamplers(
@@ -1821,6 +1863,7 @@ void SDL_BindGPUFragmentStorageTextures(
18211863

18221864
if (RENDERPASS_DEVICE->debug_mode) {
18231865
CHECK_RENDERPASS
1866+
CHECK_STORAGE_TEXTURES
18241867
}
18251868

18261869
RENDERPASS_DEVICE->BindFragmentStorageTextures(
@@ -1981,6 +2024,12 @@ void SDL_EndGPURenderPass(
19812024

19822025
commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
19832026
commandBufferCommonHeader->render_pass.in_progress = false;
2027+
for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1)
2028+
{
2029+
commandBufferCommonHeader->render_pass.color_targets[i] = NULL;
2030+
}
2031+
commandBufferCommonHeader->render_pass.num_color_targets = 0;
2032+
commandBufferCommonHeader->render_pass.depth_stencil_target = NULL;
19842033
commandBufferCommonHeader->graphics_pipeline_bound = false;
19852034
}
19862035

src/gpu/SDL_sysgpu.h

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,21 @@
2424
#ifndef SDL_GPU_DRIVER_H
2525
#define SDL_GPU_DRIVER_H
2626

27+
// GraphicsDevice Limits
28+
29+
#define MAX_TEXTURE_SAMPLERS_PER_STAGE 16
30+
#define MAX_STORAGE_TEXTURES_PER_STAGE 8
31+
#define MAX_STORAGE_BUFFERS_PER_STAGE 8
32+
#define MAX_UNIFORM_BUFFERS_PER_STAGE 4
33+
#define MAX_COMPUTE_WRITE_TEXTURES 8
34+
#define MAX_COMPUTE_WRITE_BUFFERS 8
35+
#define UNIFORM_BUFFER_SIZE 32768
36+
#define MAX_VERTEX_BUFFERS 16
37+
#define MAX_VERTEX_ATTRIBUTES 16
38+
#define MAX_COLOR_TARGET_BINDINGS 4
39+
#define MAX_PRESENT_COUNT 16
40+
#define MAX_FRAMES_IN_FLIGHT 3
41+
2742
// Common Structs
2843

2944
typedef struct Pass
@@ -32,10 +47,19 @@ typedef struct Pass
3247
bool in_progress;
3348
} Pass;
3449

50+
typedef struct RenderPass
51+
{
52+
SDL_GPUCommandBuffer *command_buffer;
53+
bool in_progress;
54+
SDL_GPUTexture *color_targets[MAX_COLOR_TARGET_BINDINGS];
55+
Uint32 num_color_targets;
56+
SDL_GPUTexture *depth_stencil_target;
57+
} RenderPass;
58+
3559
typedef struct CommandBufferCommonHeader
3660
{
3761
SDL_GPUDevice *device;
38-
Pass render_pass;
62+
RenderPass render_pass;
3963
bool graphics_pipeline_bound;
4064
Pass compute_pass;
4165
bool compute_pipeline_bound;
@@ -535,21 +559,6 @@ static inline Uint32 BytesPerRow(
535559
return blocksPerRow * SDL_GPUTextureFormatTexelBlockSize(format);
536560
}
537561

538-
// GraphicsDevice Limits
539-
540-
#define MAX_TEXTURE_SAMPLERS_PER_STAGE 16
541-
#define MAX_STORAGE_TEXTURES_PER_STAGE 8
542-
#define MAX_STORAGE_BUFFERS_PER_STAGE 8
543-
#define MAX_UNIFORM_BUFFERS_PER_STAGE 4
544-
#define MAX_COMPUTE_WRITE_TEXTURES 8
545-
#define MAX_COMPUTE_WRITE_BUFFERS 8
546-
#define UNIFORM_BUFFER_SIZE 32768
547-
#define MAX_VERTEX_BUFFERS 16
548-
#define MAX_VERTEX_ATTRIBUTES 16
549-
#define MAX_COLOR_TARGET_BINDINGS 4
550-
#define MAX_PRESENT_COUNT 16
551-
#define MAX_FRAMES_IN_FLIGHT 3
552-
553562
// Internal Macros
554563

555564
#define EXPAND_ARRAY_IF_NEEDED(arr, elementType, newCount, capacity, newCapacity) \

0 commit comments

Comments
 (0)