Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Vulkan implementation distinguish the user's render pass to its own created render pass in un-docked windows. #3459

Closed
wants to merge 4 commits into from
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
8 changes: 5 additions & 3 deletions examples/example_glfw_vulkan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ set(IMGUI_DIR ../../)
include_directories(${IMGUI_DIR} ..)

# Libraries
find_library(VULKAN_LIBRARY
NAMES vulkan vulkan-1)
set(LIBRARIES "glfw;${VULKAN_LIBRARY}")
find_package(Vulkan REQUIRED)
#find_library(VULKAN_LIBRARY
#NAMES vulkan vulkan-1)
#set(LIBRARIES "glfw;${VULKAN_LIBRARY}")
set(LIBRARIES "glfw;Vulkan::Vulkan")

# Use vulkan headers from glfw:
include_directories(${GLFW_DIR}/deps)
Expand Down
3 changes: 1 addition & 2 deletions examples/example_glfw_vulkan/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,9 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
create_info.enabledExtensionCount = extensions_count;
create_info.ppEnabledExtensionNames = extensions;

#ifdef IMGUI_VULKAN_DEBUG_REPORT
// Enabling multiple validation layers grouped as LunarG standard validation
const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" };
const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
create_info.enabledLayerCount = 1;
create_info.ppEnabledLayerNames = layers;

Expand Down
224 changes: 143 additions & 81 deletions examples/imgui_impl_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,73 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
p_buffer_size = new_size;
}

static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height)
static VkSampler getFontSampler(VkDevice device, const VkAllocationCallbacks *allocator)
{
if (!g_FontSampler)
{
VkSamplerCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
info.magFilter = VK_FILTER_LINEAR;
info.minFilter = VK_FILTER_LINEAR;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.minLod = -1000;
info.maxLod = 1000;
info.maxAnisotropy = 1.0f;
VkResult err = vkCreateSampler(device, &info, allocator, &g_FontSampler);
check_vk_result(err);
}
return g_FontSampler;
}

static VkDescriptorSetLayout getDescriptorSetLayout(VkDevice device, const VkAllocationCallbacks *allocator) {
if (!g_DescriptorSetLayout) {
VkSampler sampler[1] = {getFontSampler(device, allocator)};
VkDescriptorSetLayoutBinding binding[1] = {};
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
binding[0].descriptorCount = 1;
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
binding[0].pImmutableSamplers = sampler;
VkDescriptorSetLayoutCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
info.bindingCount = 1;
info.pBindings = binding;
VkResult err = vkCreateDescriptorSetLayout(device, &info, allocator, &g_DescriptorSetLayout);
check_vk_result(err);
}
return g_DescriptorSetLayout;
}

static VkPipelineLayout getPipelineLayout(VkDevice device, const VkAllocationCallbacks *allocator)
{

if (!g_PipelineLayout)
{
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
VkPushConstantRange push_constants[1] = {};
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
push_constants[0].offset = sizeof(float) * 0;
push_constants[0].size = sizeof(float) * 4;
VkDescriptorSetLayout set_layout[1] = { getDescriptorSetLayout(device,allocator) };
VkPipelineLayoutCreateInfo layout_info = {};
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_info.setLayoutCount = 1;
layout_info.pSetLayouts = set_layout;
layout_info.pushConstantRangeCount = 1;
layout_info.pPushConstantRanges = push_constants;
VkResult err = vkCreatePipelineLayout(device, &layout_info, allocator, &g_PipelineLayout);
check_vk_result(err);
}
return g_PipelineLayout;
}

static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height)
{
// Bind pipeline and descriptor sets:
{
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline);
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
VkDescriptorSet desc_set[1] = { g_DescriptorSet };
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL);
}
Expand Down Expand Up @@ -327,8 +389,10 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkCommandBu

// Render function
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer)
void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline)
{
if (pipeline == VK_NULL_HANDLE)
pipeline = g_Pipeline;
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
Expand Down Expand Up @@ -391,7 +455,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
}

// Setup desired Vulkan state
ImGui_ImplVulkan_SetupRenderState(draw_data, 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
Expand All @@ -412,7 +476,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplVulkan_SetupRenderState(draw_data, command_buffer, rb, fb_width, fb_height);
ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
else
pcmd->UserCallback(cmd_list, pcmd);
}
Expand Down Expand Up @@ -603,99 +667,49 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
return true;
}

bool ImGui_ImplVulkan_CreateDeviceObjects()
{
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
VkResult err;
struct ShaderModules {
VkShaderModule vert_module;
VkShaderModule frag_module;
};

static ShaderModules ImGui_ImplVulkan_MakeShaderModules(VkDevice device, const VkAllocationCallbacks* allocator) {
VkResult err;
ShaderModules modules;

// Create The Shader Modules:
{
VkShaderModuleCreateInfo vert_info = {};
vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
vert_info.codeSize = sizeof(__glsl_shader_vert_spv);
vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;
err = vkCreateShaderModule(v->Device, &vert_info, v->Allocator, &vert_module);
err = vkCreateShaderModule(device, &vert_info, allocator, &modules.vert_module);
check_vk_result(err);
VkShaderModuleCreateInfo frag_info = {};
frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
frag_info.codeSize = sizeof(__glsl_shader_frag_spv);
frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;
err = vkCreateShaderModule(v->Device, &frag_info, v->Allocator, &frag_module);
check_vk_result(err);
}

if (!g_FontSampler)
{
VkSamplerCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
info.magFilter = VK_FILTER_LINEAR;
info.minFilter = VK_FILTER_LINEAR;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.minLod = -1000;
info.maxLod = 1000;
info.maxAnisotropy = 1.0f;
err = vkCreateSampler(v->Device, &info, v->Allocator, &g_FontSampler);
check_vk_result(err);
}

if (!g_DescriptorSetLayout)
{
VkSampler sampler[1] = {g_FontSampler};
VkDescriptorSetLayoutBinding binding[1] = {};
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
binding[0].descriptorCount = 1;
binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
binding[0].pImmutableSamplers = sampler;
VkDescriptorSetLayoutCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
info.bindingCount = 1;
info.pBindings = binding;
err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &g_DescriptorSetLayout);
check_vk_result(err);
}

// Create Descriptor Set:
{
VkDescriptorSetAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
alloc_info.descriptorPool = v->DescriptorPool;
alloc_info.descriptorSetCount = 1;
alloc_info.pSetLayouts = &g_DescriptorSetLayout;
err = vkAllocateDescriptorSets(v->Device, &alloc_info, &g_DescriptorSet);
check_vk_result(err);
}

if (!g_PipelineLayout)
{
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
VkPushConstantRange push_constants[1] = {};
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
push_constants[0].offset = sizeof(float) * 0;
push_constants[0].size = sizeof(float) * 4;
VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout };
VkPipelineLayoutCreateInfo layout_info = {};
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_info.setLayoutCount = 1;
layout_info.pSetLayouts = set_layout;
layout_info.pushConstantRangeCount = 1;
layout_info.pPushConstantRanges = push_constants;
err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &g_PipelineLayout);
err = vkCreateShaderModule(device, &frag_info, allocator, &modules.frag_module);
check_vk_result(err);
}
return modules;
}

static ShaderModules ImGui_ImplVulkan_GetModules(VkDevice device, const VkAllocationCallbacks* allocator) {
static ShaderModules modules = ImGui_ImplVulkan_MakeShaderModules(device, allocator);
return modules;
}
void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator,
VkPipelineCache pipelineCache, VkRenderPass renderPass,
VkSampleCountFlagBits MSAASamples, VkPipeline *pipeline) {
ShaderModules modules = ImGui_ImplVulkan_GetModules(device, allocator);
VkPipelineShaderStageCreateInfo stage[2] = {};
stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
stage[0].module = vert_module;
stage[0].module = modules.vert_module;
stage[0].pName = "main";
stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
stage[1].module = frag_module;
stage[1].module = modules.frag_module;
stage[1].pName = "main";

VkVertexInputBindingDescription binding_desc[1] = {};
Expand Down Expand Up @@ -741,8 +755,8 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()

VkPipelineMultisampleStateCreateInfo ms_info = {};
ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
if (v->MSAASamples != 0)
ms_info.rasterizationSamples = v->MSAASamples;
if (MSAASamples != 0)
ms_info.rasterizationSamples = MSAASamples;
else
ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;

Expand Down Expand Up @@ -783,10 +797,54 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
info.pDepthStencilState = &depth_info;
info.pColorBlendState = &blend_info;
info.pDynamicState = &dynamic_state;
info.layout = g_PipelineLayout;
info.renderPass = g_RenderPass;
err = vkCreateGraphicsPipelines(v->Device, v->PipelineCache, 1, &info, v->Allocator, &g_Pipeline);
info.layout = getPipelineLayout(device, allocator);
info.renderPass = renderPass;
VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline);
check_vk_result(err);
}

bool ImGui_ImplVulkan_CreateDeviceObjects()
{
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
VkResult err;
VkShaderModule vert_module;
VkShaderModule frag_module;

// Create The Shader Modules:
{
VkShaderModuleCreateInfo vert_info = {};
vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
vert_info.codeSize = sizeof(__glsl_shader_vert_spv);
vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;
err = vkCreateShaderModule(v->Device, &vert_info, v->Allocator, &vert_module);
check_vk_result(err);
VkShaderModuleCreateInfo frag_info = {};
frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
frag_info.codeSize = sizeof(__glsl_shader_frag_spv);
frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;
err = vkCreateShaderModule(v->Device, &frag_info, v->Allocator, &frag_module);
check_vk_result(err);
}

// Create Descriptor Set:
{
VkDescriptorSetLayout set_layout[1] = { getDescriptorSetLayout(v->Device, v->Allocator) };
VkDescriptorSetAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
alloc_info.descriptorPool = v->DescriptorPool;
alloc_info.descriptorSetCount = 1;
alloc_info.pSetLayouts = set_layout;
err = vkAllocateDescriptorSets(v->Device, &alloc_info, &g_DescriptorSet);
check_vk_result(err);
}

if (!g_PipelineLayout)
{
getPipelineLayout(v->Device, v->Allocator);
}

ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache,
g_RenderPass, v->MSAASamples, &g_Pipeline);

vkDestroyShaderModule(v->Device, vert_module, v->Allocator);
vkDestroyShaderModule(v->Device, frag_module, v->Allocator);
Expand Down Expand Up @@ -1054,6 +1112,8 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
wd->ImageCount = 0;
if (wd->RenderPass)
vkDestroyRenderPass(device, wd->RenderPass, allocator);
if (wd->Pipeline)
vkDestroyPipeline(device, wd->Pipeline, allocator);

// If min image count was not specified, request different count of images dependent on selected present mode
if (min_image_count == 0)
Expand Down Expand Up @@ -1149,6 +1209,8 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
info.pDependencies = &dependency;
err = vkCreateRenderPass(device, &info, allocator, &wd->RenderPass);
check_vk_result(err);
ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE,
wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline);
}

// Create The Image Views
Expand Down Expand Up @@ -1385,7 +1447,7 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*)
}
}

ImGui_ImplVulkan_RenderDrawData(viewport->DrawData, fd->CommandBuffer);
ImGui_ImplVulkan_RenderDrawData(viewport->DrawData, fd->CommandBuffer, wd->Pipeline);

{
vkCmdEndRenderPass(fd->CommandBuffer);
Expand Down
3 changes: 2 additions & 1 deletion examples/imgui_impl_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct ImGui_ImplVulkan_InitInfo
IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass);
IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown();
IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame();
IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer);
IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer);
IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects();
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
Expand Down Expand Up @@ -109,6 +109,7 @@ struct ImGui_ImplVulkanH_Window
VkSurfaceFormatKHR SurfaceFormat;
VkPresentModeKHR PresentMode;
VkRenderPass RenderPass;
VkPipeline Pipeline; // The window pipeline uses a different VkRenderPass than the user's
bool ClearEnable;
VkClearValue ClearValue;
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
Expand Down