21
21
// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info.
22
22
23
23
// CHANGELOG
24
+ // 2025-03-30: Made ImGui_ImplSDLGPU3_PrepareDrawData() reuse GPU Transfer Buffers which were unusually slow to recreate every frame. Much faster now.
24
25
// 2025-03-21: Fixed typo in function name Imgui_ImplSDLGPU3_PrepareDrawData() -> ImGui_ImplSDLGPU3_PrepareDrawData().
25
26
// 2025-01-16: Renamed ImGui_ImplSDLGPU3_InitInfo::GpuDevice to Device.
26
27
// 2025-01-09: SDL_GPU: Added the SDL_GPU3 backend.
35
36
// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplSDLGPU3_RenderDrawData()
36
37
struct ImGui_ImplSDLGPU3_FrameData
37
38
{
38
- SDL_GPUBuffer* VertexBuffer = nullptr ;
39
- SDL_GPUBuffer* IndexBuffer = nullptr ;
40
- uint32_t VertexBufferSize = 0 ;
41
- uint32_t IndexBufferSize = 0 ;
39
+ SDL_GPUBuffer* VertexBuffer = nullptr ;
40
+ SDL_GPUTransferBuffer* VertexTransferBuffer = nullptr ;
41
+ uint32_t VertexBufferSize = 0 ;
42
+ SDL_GPUBuffer* IndexBuffer = nullptr ;
43
+ SDL_GPUTransferBuffer* IndexTransferBuffer = nullptr ;
44
+ uint32_t IndexBufferSize = 0 ;
42
45
};
43
46
44
47
struct ImGui_ImplSDLGPU3_Data
@@ -114,14 +117,15 @@ static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGra
114
117
SDL_PushGPUVertexUniformData (command_buffer, 0 , &ubo, sizeof (UBO));
115
118
}
116
119
117
- static void CreateOrResizeBuffer (SDL_GPUBuffer** buffer, uint32_t * old_size, uint32_t new_size, SDL_GPUBufferUsageFlags usage)
120
+ static void CreateOrResizeBuffers (SDL_GPUBuffer** buffer, SDL_GPUTransferBuffer** transferbuffer , uint32_t * old_size, uint32_t new_size, SDL_GPUBufferUsageFlags usage)
118
121
{
119
122
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData ();
120
123
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo ;
121
124
122
- // Even though this is fairly rarely called.
125
+ // FIXME-OPT: Not optimal, but this is fairly rarely called.
123
126
SDL_WaitForGPUIdle (v->Device );
124
127
SDL_ReleaseGPUBuffer (v->Device , *buffer);
128
+ SDL_ReleaseGPUTransferBuffer (v->Device , *transferbuffer);
125
129
126
130
SDL_GPUBufferCreateInfo buffer_info = {};
127
131
buffer_info.usage = usage;
@@ -130,6 +134,12 @@ static void CreateOrResizeBuffer(SDL_GPUBuffer** buffer, uint32_t* old_size, uin
130
134
*buffer = SDL_CreateGPUBuffer (v->Device , &buffer_info);
131
135
*old_size = new_size;
132
136
IM_ASSERT (*buffer != nullptr && " Failed to create GPU Buffer, call SDL_GetError() for more information" );
137
+
138
+ SDL_GPUTransferBufferCreateInfo transferbuffer_info = {};
139
+ transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
140
+ transferbuffer_info.size = new_size;
141
+ *transferbuffer = SDL_CreateGPUTransferBuffer (v->Device , &transferbuffer_info);
142
+ IM_ASSERT (*transferbuffer != nullptr && " Failed to create GPU Transfer Buffer, call SDL_GetError() for more information" );
133
143
}
134
144
135
145
// SDL_GPU doesn't allow copy passes to occur while a render or compute pass is bound!
@@ -150,25 +160,12 @@ void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff
150
160
uint32_t vertex_size = draw_data->TotalVtxCount * sizeof (ImDrawVert);
151
161
uint32_t index_size = draw_data->TotalIdxCount * sizeof (ImDrawIdx);
152
162
if (fd->VertexBuffer == nullptr || fd->VertexBufferSize < vertex_size)
153
- CreateOrResizeBuffer (&fd->VertexBuffer , &fd->VertexBufferSize , vertex_size, SDL_GPU_BUFFERUSAGE_VERTEX);
163
+ CreateOrResizeBuffers (&fd->VertexBuffer , &fd-> VertexTransferBuffer , &fd->VertexBufferSize , vertex_size, SDL_GPU_BUFFERUSAGE_VERTEX);
154
164
if (fd->IndexBuffer == nullptr || fd->IndexBufferSize < index_size)
155
- CreateOrResizeBuffer (&fd->IndexBuffer , &fd->IndexBufferSize , index_size, SDL_GPU_BUFFERUSAGE_INDEX);
156
-
157
- // FIXME: It feels like more code could be shared there.
158
- SDL_GPUTransferBufferCreateInfo vertex_transferbuffer_info = {};
159
- vertex_transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
160
- vertex_transferbuffer_info.size = vertex_size;
161
- SDL_GPUTransferBufferCreateInfo index_transferbuffer_info = {};
162
- index_transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
163
- index_transferbuffer_info.size = index_size;
164
-
165
- SDL_GPUTransferBuffer* vertex_transferbuffer = SDL_CreateGPUTransferBuffer (v->Device , &vertex_transferbuffer_info);
166
- IM_ASSERT (vertex_transferbuffer != nullptr && " Failed to create the vertex transfer buffer, call SDL_GetError() for more information" );
167
- SDL_GPUTransferBuffer* index_transferbuffer = SDL_CreateGPUTransferBuffer (v->Device , &index_transferbuffer_info);
168
- IM_ASSERT (index_transferbuffer != nullptr && " Failed to create the index transfer buffer, call SDL_GetError() for more information" );
169
-
170
- ImDrawVert* vtx_dst = (ImDrawVert*)SDL_MapGPUTransferBuffer (v->Device , vertex_transferbuffer, true );
171
- ImDrawIdx* idx_dst = (ImDrawIdx*)SDL_MapGPUTransferBuffer (v->Device , index_transferbuffer, true );
165
+ CreateOrResizeBuffers (&fd->IndexBuffer , &fd->IndexTransferBuffer , &fd->IndexBufferSize , index_size, SDL_GPU_BUFFERUSAGE_INDEX);
166
+
167
+ ImDrawVert* vtx_dst = (ImDrawVert*)SDL_MapGPUTransferBuffer (v->Device , fd->VertexTransferBuffer , true );
168
+ ImDrawIdx* idx_dst = (ImDrawIdx*)SDL_MapGPUTransferBuffer (v->Device , fd->IndexTransferBuffer , true );
172
169
for (int n = 0 ; n < draw_data->CmdListsCount ; n++)
173
170
{
174
171
const ImDrawList* draw_list = draw_data->CmdLists [n];
@@ -177,15 +174,15 @@ void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff
177
174
vtx_dst += draw_list->VtxBuffer .Size ;
178
175
idx_dst += draw_list->IdxBuffer .Size ;
179
176
}
180
- SDL_UnmapGPUTransferBuffer (v->Device , vertex_transferbuffer );
181
- SDL_UnmapGPUTransferBuffer (v->Device , index_transferbuffer );
177
+ SDL_UnmapGPUTransferBuffer (v->Device , fd-> VertexTransferBuffer );
178
+ SDL_UnmapGPUTransferBuffer (v->Device , fd-> IndexTransferBuffer );
182
179
183
180
SDL_GPUTransferBufferLocation vertex_buffer_location = {};
184
181
vertex_buffer_location.offset = 0 ;
185
- vertex_buffer_location.transfer_buffer = vertex_transferbuffer ;
182
+ vertex_buffer_location.transfer_buffer = fd-> VertexTransferBuffer ;
186
183
SDL_GPUTransferBufferLocation index_buffer_location = {};
187
184
index_buffer_location.offset = 0 ;
188
- index_buffer_location.transfer_buffer = index_transferbuffer ;
185
+ index_buffer_location.transfer_buffer = fd-> IndexTransferBuffer ;
189
186
190
187
SDL_GPUBufferRegion vertex_buffer_region = {};
191
188
vertex_buffer_region.buffer = fd->VertexBuffer ;
@@ -201,8 +198,6 @@ void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff
201
198
SDL_UploadToGPUBuffer (copy_pass, &vertex_buffer_location, &vertex_buffer_region, true );
202
199
SDL_UploadToGPUBuffer (copy_pass, &index_buffer_location, &index_buffer_region, true );
203
200
SDL_EndGPUCopyPass (copy_pass);
204
- SDL_ReleaseGPUTransferBuffer (v->Device , index_transferbuffer);
205
- SDL_ReleaseGPUTransferBuffer (v->Device , vertex_transferbuffer);
206
201
}
207
202
208
203
void ImGui_ImplSDLGPU3_RenderDrawData (ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline)
@@ -547,12 +542,14 @@ void ImGui_ImplSDLGPU3_DestroyFrameData()
547
542
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData ();
548
543
ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo ;
549
544
550
- SDL_ReleaseGPUBuffer (v->Device , bd->MainWindowFrameData .VertexBuffer );
551
- SDL_ReleaseGPUBuffer (v->Device , bd->MainWindowFrameData .IndexBuffer );
552
- bd->MainWindowFrameData .VertexBuffer = nullptr ;
553
- bd->MainWindowFrameData .IndexBuffer = nullptr ;
554
- bd->MainWindowFrameData .VertexBufferSize = 0 ;
555
- bd->MainWindowFrameData .IndexBufferSize = 0 ;
545
+ ImGui_ImplSDLGPU3_FrameData* fd = &bd->MainWindowFrameData ;
546
+ SDL_ReleaseGPUBuffer (v->Device , fd->VertexBuffer );
547
+ SDL_ReleaseGPUBuffer (v->Device , fd->IndexBuffer );
548
+ SDL_ReleaseGPUTransferBuffer (v->Device , fd->VertexTransferBuffer );
549
+ SDL_ReleaseGPUTransferBuffer (v->Device , fd->IndexTransferBuffer );
550
+ fd->VertexBuffer = fd->IndexBuffer = nullptr ;
551
+ fd->VertexTransferBuffer = fd->IndexTransferBuffer = nullptr ;
552
+ fd->VertexBufferSize = fd->IndexBufferSize = 0 ;
556
553
}
557
554
558
555
void ImGui_ImplSDLGPU3_DestroyDeviceObjects ()
0 commit comments