Backends: Vulkan, SDLGPU3: remove samplers from RenderState. (#9378)

Revert part of ac261203a5, 9ee3d731b5 (#8866, #8163, #7998, #7988) since we have a better solution.
This commit is contained in:
ocornut
2026-04-22 18:06:17 +02:00
parent 0a811e8ea1
commit 37952fb3b8
5 changed files with 19 additions and 30 deletions

View File

@@ -59,7 +59,10 @@ struct ImGui_ImplSDLGPU3_FrameData
struct ImGui_ImplSDLGPU3_Data
{
ImGui_ImplSDLGPU3_InitInfo InitInfo;
ImGui_ImplSDLGPU3_RenderState* RenderState = nullptr; // == ImGui::GetPlatformIO().Renderer_RenderState during rendering.
// Render state
ImGui_ImplSDLGPU3_RenderState* RenderState = nullptr; // == ImGui::GetPlatformIO().Renderer_RenderState during rendering.
SDL_GPUSampler* CurrentSampler = nullptr;
// Graphics pipeline & shaders
SDL_GPUShader* VertexShader = nullptr;
@@ -89,10 +92,10 @@ static ImGui_ImplSDLGPU3_Data* ImGui_ImplSDLGPU3_GetBackendData()
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLGPU3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
}
static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, ImGui_ImplSDLGPU3_RenderState* render_state, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height)
static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height)
{
ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
render_state->SamplerCurrent = bd->TexSamplerLinear;
bd->CurrentSampler = bd->TexSamplerLinear;
// Bind graphics pipeline
SDL_BindGPUGraphicsPipeline(render_pass, pipeline);
@@ -220,9 +223,9 @@ void ImGui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff
// Draw callbacks
static void ImGui_ImplSDLGPU3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} // Intentionally empty. Used as an identifier for rendering loop to call its code. Simpler to implement this way.
static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); bd->RenderState->SamplerCurrent = bd->TexSamplerLinear; }
static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); bd->RenderState->SamplerCurrent = bd->TexSamplerNearest; }
static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerCustom(const ImDrawList*, const ImDrawCmd* cmd){ ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); bd->RenderState->SamplerCurrent = (SDL_GPUSampler*)cmd->UserCallbackData; }
static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerLinear(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); bd->CurrentSampler = bd->TexSamplerLinear; }
static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerNearest(const ImDrawList*, const ImDrawCmd*) { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); bd->CurrentSampler = bd->TexSamplerNearest; }
static void ImGui_ImplSDLGPU3_DrawCallback_SetSamplerCustom(const ImDrawList*, const ImDrawCmd* cmd){ ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); bd->CurrentSampler = (SDL_GPUSampler*)cmd->UserCallbackData; }
void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline)
{
@@ -246,11 +249,9 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui_ImplSDLGPU3_RenderState render_state;
render_state.Device = bd->InitInfo.Device;
render_state.SamplerLinear = render_state.SamplerCurrent = bd->TexSamplerLinear;
render_state.SamplerNearest = bd->TexSamplerNearest;
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, &render_state, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
// Render command lists
// (Because we merged all buffers into a single one, we maintain our own offset into them)
@@ -265,7 +266,7 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
{
// User callback, registered via ImDrawList::AddCallback()
if (pcmd->UserCallback == ImGui_ImplSDLGPU3_DrawCallback_ResetRenderState)
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, &render_state, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
ImGui_ImplSDLGPU3_SetupRenderState(draw_data, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
else
pcmd->UserCallback(draw_list, pcmd);
}
@@ -294,7 +295,7 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
// Bind DescriptorSet with font or user texture
SDL_GPUTextureSamplerBinding texture_sampler_binding;
texture_sampler_binding.texture = (SDL_GPUTexture*)(intptr_t)pcmd->GetTexID();
texture_sampler_binding.sampler = render_state.SamplerCurrent;
texture_sampler_binding.sampler = bd->CurrentSampler;
SDL_BindGPUFragmentSamplers(render_pass, 0, &texture_sampler_binding, 1);
// Draw

View File

@@ -57,9 +57,6 @@ IMGUI_IMPL_API void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex);
struct ImGui_ImplSDLGPU3_RenderState
{
SDL_GPUDevice* Device;
SDL_GPUSampler* SamplerLinear; // Bilinear filtering sampler
SDL_GPUSampler* SamplerNearest; // Nearest/point filtering sampler
SDL_GPUSampler* SamplerCurrent; // Current sampler (may be changed by callback)
};
#endif // #ifndef IMGUI_DISABLE

View File

@@ -496,10 +496,9 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
buffer_size = buffer_size_aligned;
}
static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, ImGui_ImplVulkan_RenderState* render_state, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkan_FrameRenderBuffers* rb, int fb_width, int fb_height)
static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkan_FrameRenderBuffers* rb, int fb_width, int fb_height)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
render_state->SamplerCurrentDS = bd->SamplerLinearDS;
// Bind pipeline:
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
@@ -531,6 +530,9 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, ImGui_ImplV
constants[2] = -1.0f - draw_data->DisplayPos.x * constants[0]; // Translate
constants[3] = -1.0f - draw_data->DisplayPos.y * constants[1];
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float) * 4, constants);
// Setup sampler
vkCmdBindDescriptorSets(bd->RenderState->CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &bd->SamplerLinearDS, 0, nullptr);
}
// Draw callbacks
@@ -616,12 +618,10 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
render_state.CommandBuffer = command_buffer;
render_state.Pipeline = pipeline;
render_state.PipelineLayout = bd->PipelineLayout;
render_state.SamplerLinearDS = render_state.SamplerCurrentDS = bd->SamplerLinearDS;
render_state.SamplerNearestDS = bd->SamplerNearestDS;
platform_io.Renderer_RenderState = bd->RenderState = &render_state;
// Setup desired Vulkan state
ImGui_ImplVulkan_SetupRenderState(draw_data, &render_state, pipeline, command_buffer, rb, fb_width, fb_height);
ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
@@ -630,7 +630,6 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
// Render command lists
// (Because we merged all buffers into a single one, we maintain our own offset into them)
VkDescriptorSet last_image_view = VK_NULL_HANDLE;
VkDescriptorSet last_sampler = VK_NULL_HANDLE;
int global_vtx_offset = 0;
int global_idx_offset = 0;
for (const ImDrawList* draw_list : draw_data->CmdLists)
@@ -643,8 +642,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
// User callback, registered via ImDrawList::AddCallback()
if (pcmd->UserCallback == ImGui_ImplVulkan_DrawCallback_ResetRenderState)
{
ImGui_ImplVulkan_SetupRenderState(draw_data, &render_state, pipeline, command_buffer, rb, fb_width, fb_height);
last_image_view = last_sampler = VK_NULL_HANDLE;
ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
last_image_view = VK_NULL_HANDLE;
}
else
pcmd->UserCallback(draw_list, pcmd);
@@ -675,10 +674,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
VkDescriptorSet image_view = (VkDescriptorSet)pcmd->GetTexID();
if (image_view != last_image_view)
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, &image_view, 0, nullptr);
if (render_state.SamplerCurrentDS != last_sampler)
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 1, 1, &render_state.SamplerCurrentDS, 0, nullptr);
last_image_view = image_view;
last_sampler = render_state.SamplerCurrentDS;
// Draw
vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);

View File

@@ -173,9 +173,6 @@ struct ImGui_ImplVulkan_RenderState
VkCommandBuffer CommandBuffer;
VkPipeline Pipeline;
VkPipelineLayout PipelineLayout;
VkDescriptorSet SamplerLinearDS; // Bilinear filtering sampler
VkDescriptorSet SamplerNearestDS; // Nearest/point filtering sampler
VkDescriptorSet SamplerCurrentDS; // Current sampler (may be changed by callback)
};
//-------------------------------------------------------------------------

View File

@@ -56,8 +56,6 @@ Breaking Changes:
- Before: ImGui_ImplVulkan_AddTexture(VkSampler, VkImageView, VkImageLayout)
- After: ImGui_ImplVulkan_AddTexture(VkImageView, VkImageLayout)
- Kept inline redirection function that ignores the sampler (will obsolete).
- Vulkan: with the change above it is now possible to change the current Sampler during
rendering, by poking into ImGui_ImplVulkan_RenderState's SamplerCurrentDS. (#914)
Other Changes: