Vulkan 学习笔记 03

本章主要的目标是在imgui界面中显示图片,参考文献在最后有链接。主要的步骤是给需要显示的图片创建descriptor set,在显示图片的时候添加这个descriptor set,并且在最终imgui渲染录制绘制指令时,需要稍微修改运行逻辑,在实际调用vkCmdDrawIndexed时,绑定对应的descriptor set,调用正确的贴图。

            vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);

            VkViewport viewport {};
            viewport.width    = ImGui::GetIO().DisplaySize.x;
            viewport.height   = ImGui::GetIO().DisplaySize.y;
            viewport.minDepth = 0.0f;
            viewport.maxDepth = 1.0f;
            vkCmdSetViewport(command_buffer, 0, 1, &viewport);

            // UI scale and translate via push constants
            m_push_const.scale     = {2.0f / io.DisplaySize.x, 2.0f / io.DisplaySize.y};
            m_push_const.translate = {-1.0f, -1.0f};
            vkCmdPushConstants(command_buffer, m_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(PushConstantBlock), &m_push_const);

            // Render commands
            ImDrawData* main_draw_data = ImGui::GetDrawData();
            int32_t     vertex_offset  = 0;
            int32_t     index_offset   = 0;

            if (main_draw_data->CmdListsCount > 0)
            {
                VkDeviceSize offsets[1] = {0};
                vkCmdBindVertexBuffers(command_buffer, 0, 1, &m_vertex_buffer->buffer, offsets);
                vkCmdBindIndexBuffer(command_buffer, m_index_buffer->buffer, 0, VK_INDEX_TYPE_UINT16);

                for (int32_t i = 0; i < main_draw_data->CmdListsCount; i++)
                {
                    const ImDrawList* cmd_list = main_draw_data->CmdLists[i];
                    for (int32_t j = 0; j < cmd_list->CmdBuffer.Size; j++)
                    {
                        const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[j];
                        VkRect2D         scissorRect;

                        VkDescriptorSet desc_set = (VkDescriptorSet)pcmd->TextureId;
                        if (sizeof(ImTextureID) < sizeof(ImU64))
                        {
                            // We don't support texture switches if ImTextureID hasn't been redefined to be 64-bit.
                            // Do a flaky check that other textures haven't been used.
                            desc_set = m_descriptor_set;
                        }
                        if (desc_set == VK_NULL_HANDLE)
                        {
                            desc_set = m_descriptor_set;
                        }
                        vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 0, 1, &desc_set, 0, nullptr);

                        scissorRect.offset.x      = std::max((int32_t)(pcmd->ClipRect.x), 0);
                        scissorRect.offset.y      = std::max((int32_t)(pcmd->ClipRect.y), 0);
                        scissorRect.extent.width  = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x);
                        scissorRect.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y);
                        vkCmdSetScissor(command_buffer, 0, 1, &scissorRect);

                        vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, index_offset, vertex_offset, 0);
                        index_offset += pcmd->ElemCount;
                    }
                    vertex_offset += cmd_list->VtxBuffer.Size;
                }
            }

result

参考文献
1.Image Loading and Displaying Examples
2.How to render Vulkan’s scene to ImGui window