Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 41 additions & 29 deletions backends/imgui_impl_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -495,28 +495,28 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline
}

// Setup viewport:
{
VkViewport viewport;
viewport.x = 0;
viewport.y = 0;
viewport.width = (float)fb_width;
viewport.height = (float)fb_height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
}

VkViewport viewport;
viewport.x = draw_data->OwnerViewport->Pos.x;
viewport.y = draw_data->OwnerViewport->Pos.y;
viewport.width = (float)fb_width;
viewport.height = (float)fb_height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
vkCmdSetViewport(command_buffer, 0, 1, &viewport);


// Setup scale and translation:
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
{
float scale[2];
scale[0] = 2.0f / draw_data->DisplaySize.x;
scale[1] = 2.0f / draw_data->DisplaySize.y;
float translate[2];
translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0];
translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1];
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale);
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate);
float scale_translate[4];
//first two are scale
scale_translate[0] = 2.0f / draw_data->DisplaySize.x;
scale_translate[1] = 2.0f / draw_data->DisplaySize.y;
//second two are translate
scale_translate[2] = -1.0f - draw_data->DisplayPos.x * scale_translate[0];
scale_translate[3] = -1.0f - draw_data->DisplayPos.y * scale_translate[1];
vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float) * 4, scale_translate);
}
}

Expand Down Expand Up @@ -629,23 +629,35 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
else
{
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
ImVec2 scissor_offset{
pcmd->ClipRect.x * clip_scale.x,
pcmd->ClipRect.y * clip_scale.y
};
ImVec2 scissor_extent{
(pcmd->ClipRect.z - clip_off.x) * clip_scale.x,
(pcmd->ClipRect.w - clip_off.y) * clip_scale.y
};

// Clamp to viewport as vkCmdSetScissor() won't accept values that are off bounds
if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are acceptable values, as seen immediately below at line 645, scissor is a position and size, as opposed to a min and max.

if (scissor_offset.x < 0.0f) { scissor_offset.x = 0.0f; }
if (scissor_offset.y < 0.0f) { scissor_offset.y = 0.0f; }
const float scissor_rect_right = scissor_offset.x + scissor_extent.x;
const float scissor_rect_bottom = scissor_offset.y + scissor_offset.y;
if (scissor_rect_right > fb_width) { scissor_extent.x = (float)fb_width - scissor_offset.x; }
if (scissor_rect_bottom > fb_height) { scissor_extent.y = (float)fb_height - scissor_offset.y; }
if(scissor_extent.x <= 0.f || scissor_extent.y <= 0.f){
continue;
}
if(scissor_offset.x >= fb_width || scissor_offset.y >= fb_height){
continue;
}

// Apply scissor/clipping rectangle
VkRect2D scissor;
scissor.offset.x = (int32_t)(clip_min.x);
scissor.offset.y = (int32_t)(clip_min.y);
scissor.extent.width = (uint32_t)(clip_max.x - clip_min.x);
scissor.extent.height = (uint32_t)(clip_max.y - clip_min.y);
scissor.offset.x = (int32_t)(scissor_offset.x);
scissor.offset.y = (int32_t)(scissor_offset.y);
scissor.extent.width = uint32_t(scissor_extent.x);
scissor.extent.height = uint32_t(scissor_extent.y);
vkCmdSetScissor(command_buffer, 0, 1, &scissor);

// Bind DescriptorSet with font or user texture
Expand Down
1 change: 0 additions & 1 deletion imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15816,7 +15816,6 @@ static void ImGui::UpdateViewportsNewFrame()
// FIXME-VIEWPORT: Size is driven by backend/user code for backward-compatibility but we should aim to make this more consistent.
ImGuiViewportP* main_viewport = g.Viewports[0];
main_viewport->Flags = ImGuiViewportFlags_IsPlatformWindow | ImGuiViewportFlags_OwnedByApp;
main_viewport->Pos = ImVec2(0.0f, 0.0f);

@GDBobby GDBobby Mar 28, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

previously, this was a wasted instruction as Pos was initialized as 0 and never changed. now, it would cause the viewport and scissor to be out of sync if left alone.

main_viewport->Size = g.IO.DisplaySize;
main_viewport->FramebufferScale = g.IO.DisplayFramebufferScale;
IM_ASSERT(main_viewport->FramebufferScale.x > 0.0f && main_viewport->FramebufferScale.y > 0.0f);
Expand Down