Swap Chain Recreation & Dynamic Viewports
This commit is contained in:
		
							parent
							
								
									eb484e22f8
								
							
						
					
					
						commit
						976ff14298
					
				| 
						 | 
				
			
			@ -48,6 +48,30 @@
 | 
			
		|||
        "typeinfo": "cpp",
 | 
			
		||||
        "fstream": "cpp",
 | 
			
		||||
        "set": "cpp",
 | 
			
		||||
        "unordered_set": "cpp"
 | 
			
		||||
        "unordered_set": "cpp",
 | 
			
		||||
        "csignal": "cpp",
 | 
			
		||||
        "ctime": "cpp",
 | 
			
		||||
        "any": "cpp",
 | 
			
		||||
        "strstream": "cpp",
 | 
			
		||||
        "bitset": "cpp",
 | 
			
		||||
        "chrono": "cpp",
 | 
			
		||||
        "codecvt": "cpp",
 | 
			
		||||
        "complex": "cpp",
 | 
			
		||||
        "condition_variable": "cpp",
 | 
			
		||||
        "list": "cpp",
 | 
			
		||||
        "map": "cpp",
 | 
			
		||||
        "optional": "cpp",
 | 
			
		||||
        "ratio": "cpp",
 | 
			
		||||
        "future": "cpp",
 | 
			
		||||
        "iomanip": "cpp",
 | 
			
		||||
        "mutex": "cpp",
 | 
			
		||||
        "semaphore": "cpp",
 | 
			
		||||
        "sstream": "cpp",
 | 
			
		||||
        "stop_token": "cpp",
 | 
			
		||||
        "thread": "cpp",
 | 
			
		||||
        "cfenv": "cpp",
 | 
			
		||||
        "typeindex": "cpp",
 | 
			
		||||
        "valarray": "cpp",
 | 
			
		||||
        "variant": "cpp"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								VulkanTest
								
								
								
								
							
							
						
						
									
										
											BIN
										
									
								
								VulkanTest
								
								
								
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -58,8 +58,11 @@ namespace hk
 | 
			
		|||
 | 
			
		||||
    void FirstApp::createPipeline()
 | 
			
		||||
    {
 | 
			
		||||
        auto pipelineConfig =
 | 
			
		||||
            Pipeline::defaultPipelineConfigInfo(swapChain->width(), swapChain->height());
 | 
			
		||||
        assert(swapChain != nullptr && "Cannot create pipeline before swap chain");
 | 
			
		||||
        assert(pipelineLayout != nullptr && "Cannot create pipeline before pipeline layout");
 | 
			
		||||
 | 
			
		||||
        PipelineConfigInfo pipelineConfig{};
 | 
			
		||||
        Pipeline::defaultPipelineConfigInfo(pipelineConfig);
 | 
			
		||||
 | 
			
		||||
        pipelineConfig.renderPass = swapChain->getRenderPass();
 | 
			
		||||
        pipelineConfig.pipelineLayout = pipelineLayout;
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +83,22 @@ namespace hk
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        vkDeviceWaitIdle(device.device());
 | 
			
		||||
        swapChain = std::make_unique<SwapChain>(device, extent);
 | 
			
		||||
 | 
			
		||||
        if (swapChain == nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            swapChain = std::make_unique<SwapChain>(device, extent);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            swapChain = std::make_unique<SwapChain>(device, extent, std::move(swapChain));
 | 
			
		||||
            if (swapChain->imageCount() != commandBuffers.size())
 | 
			
		||||
            {
 | 
			
		||||
                freeCommandBuffers();
 | 
			
		||||
                createCommandBuffers();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // if render pass compatible do nothing else
 | 
			
		||||
        createPipeline();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -101,6 +119,16 @@ namespace hk
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void FirstApp::freeCommandBuffers()
 | 
			
		||||
    {
 | 
			
		||||
        vkFreeCommandBuffers(
 | 
			
		||||
            device.device(),
 | 
			
		||||
            device.getCommandPool(),
 | 
			
		||||
            static_cast<float>(commandBuffers.size()),
 | 
			
		||||
            commandBuffers.data());
 | 
			
		||||
        commandBuffers.clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void FirstApp::recordCommandBuffer(int imageIndex)
 | 
			
		||||
    {
 | 
			
		||||
        VkCommandBufferBeginInfo beginInfo{};
 | 
			
		||||
| 
						 | 
				
			
			@ -126,6 +154,17 @@ namespace hk
 | 
			
		|||
 | 
			
		||||
        vkCmdBeginRenderPass(commandBuffers[imageIndex], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
 | 
			
		||||
 | 
			
		||||
        VkViewport viewport{};
 | 
			
		||||
        viewport.x = 0.0f;
 | 
			
		||||
        viewport.y = 0.0f;
 | 
			
		||||
        viewport.width = static_cast<float>(swapChain->getSwapChainExtent().width);
 | 
			
		||||
        viewport.height = static_cast<float>(swapChain->getSwapChainExtent().height);
 | 
			
		||||
        viewport.minDepth = 0.0f;
 | 
			
		||||
        viewport.maxDepth = 1.0f;
 | 
			
		||||
        VkRect2D scissor{{0, 0}, swapChain->getSwapChainExtent()};
 | 
			
		||||
        vkCmdSetViewport(commandBuffers[imageIndex], 0, 1, &viewport);
 | 
			
		||||
        vkCmdSetScissor(commandBuffers[imageIndex], 0, 1, &scissor);
 | 
			
		||||
 | 
			
		||||
        pipeline->bind(commandBuffers[imageIndex]);
 | 
			
		||||
        model->bind(commandBuffers[imageIndex]);
 | 
			
		||||
        model->draw(commandBuffers[imageIndex]);
 | 
			
		||||
| 
						 | 
				
			
			@ -161,7 +200,7 @@ namespace hk
 | 
			
		|||
            recreateSwapChain();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        if (result != VK_SUCCESS)
 | 
			
		||||
        {
 | 
			
		||||
            throw std::runtime_error("failed to present swap chain image!");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,7 @@ namespace hk
 | 
			
		|||
        void createPipelineLayout();
 | 
			
		||||
        void createPipeline();
 | 
			
		||||
        void createCommandBuffers();
 | 
			
		||||
        void freeCommandBuffers();
 | 
			
		||||
        void drawFrame();
 | 
			
		||||
        void recreateSwapChain();
 | 
			
		||||
        void recordCommandBuffer(int imageIndex);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,22 +31,17 @@ namespace hk
 | 
			
		|||
        vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicPipeline);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    PipelineConfigInfo Pipeline::defaultPipelineConfigInfo(uint32_t width, uint32_t height)
 | 
			
		||||
    void Pipeline::defaultPipelineConfigInfo(PipelineConfigInfo& configInfo)
 | 
			
		||||
    {
 | 
			
		||||
        PipelineConfigInfo configInfo{};
 | 
			
		||||
        configInfo.inputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
 | 
			
		||||
        configInfo.inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
 | 
			
		||||
        configInfo.inputAssemblyInfo.primitiveRestartEnable = VK_FALSE;
 | 
			
		||||
 | 
			
		||||
        configInfo.viewport.x = 0.0f;
 | 
			
		||||
        configInfo.viewport.y = 0.0f;
 | 
			
		||||
        configInfo.viewport.width = static_cast<float>(width);
 | 
			
		||||
        configInfo.viewport.height = static_cast<float>(height);
 | 
			
		||||
        configInfo.viewport.minDepth = 0.0f;
 | 
			
		||||
        configInfo.viewport.maxDepth = 1.0f;
 | 
			
		||||
 | 
			
		||||
        configInfo.scissor.offset = {0, 0};
 | 
			
		||||
        configInfo.scissor.extent = {width, height};
 | 
			
		||||
        configInfo.viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
 | 
			
		||||
        configInfo.viewportInfo.viewportCount = 1;
 | 
			
		||||
        configInfo.viewportInfo.pViewports = nullptr;
 | 
			
		||||
        configInfo.viewportInfo.scissorCount = 1;
 | 
			
		||||
        configInfo.viewportInfo.pScissors = nullptr;
 | 
			
		||||
 | 
			
		||||
        configInfo.rasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
 | 
			
		||||
        configInfo.rasterizationInfo.depthClampEnable = VK_FALSE;
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +95,11 @@ namespace hk
 | 
			
		|||
        configInfo.depthStencilInfo.front = {}; // Optional
 | 
			
		||||
        configInfo.depthStencilInfo.back = {};  // Optional
 | 
			
		||||
 | 
			
		||||
        return configInfo;
 | 
			
		||||
        configInfo.dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
 | 
			
		||||
        configInfo.dynamicStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
 | 
			
		||||
        configInfo.dynamicStateInfo.pDynamicStates = configInfo.dynamicStateEnables.data();
 | 
			
		||||
        configInfo.dynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(configInfo.dynamicStateEnables.size());
 | 
			
		||||
        configInfo.dynamicStateInfo.flags = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::vector<char> Pipeline::readFile(const std::string &filePath)
 | 
			
		||||
| 
						 | 
				
			
			@ -165,25 +164,18 @@ namespace hk
 | 
			
		|||
        vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
 | 
			
		||||
        vertexInputInfo.pVertexBindingDescriptions = bindingDescriptions.data();
 | 
			
		||||
 | 
			
		||||
        VkPipelineViewportStateCreateInfo viewportInfo{};
 | 
			
		||||
        viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
 | 
			
		||||
        viewportInfo.viewportCount = 1;
 | 
			
		||||
        viewportInfo.pViewports = &configInfo.viewport;
 | 
			
		||||
        viewportInfo.scissorCount = 1;
 | 
			
		||||
        viewportInfo.pScissors = &configInfo.scissor;
 | 
			
		||||
 | 
			
		||||
        VkGraphicsPipelineCreateInfo pipelineInfo{};
 | 
			
		||||
        pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
 | 
			
		||||
        pipelineInfo.stageCount = 2;
 | 
			
		||||
        pipelineInfo.pStages = shaderStages;
 | 
			
		||||
        pipelineInfo.pVertexInputState = &vertexInputInfo;
 | 
			
		||||
        pipelineInfo.pInputAssemblyState = &configInfo.inputAssemblyInfo;
 | 
			
		||||
        pipelineInfo.pViewportState = &viewportInfo;
 | 
			
		||||
        pipelineInfo.pViewportState = &configInfo.viewportInfo;
 | 
			
		||||
        pipelineInfo.pRasterizationState = &configInfo.rasterizationInfo;
 | 
			
		||||
        pipelineInfo.pMultisampleState = &configInfo.multisampleInfo;
 | 
			
		||||
        pipelineInfo.pColorBlendState = &configInfo.colorBlendInfo;
 | 
			
		||||
        pipelineInfo.pDepthStencilState = &configInfo.depthStencilInfo;
 | 
			
		||||
        pipelineInfo.pDynamicState = nullptr;
 | 
			
		||||
        pipelineInfo.pDynamicState = &configInfo.dynamicStateInfo;
 | 
			
		||||
 | 
			
		||||
        pipelineInfo.layout = configInfo.pipelineLayout;
 | 
			
		||||
        pipelineInfo.renderPass = configInfo.renderPass;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,14 +10,18 @@ namespace hk
 | 
			
		|||
{
 | 
			
		||||
    struct PipelineConfigInfo
 | 
			
		||||
    {
 | 
			
		||||
        VkViewport viewport;
 | 
			
		||||
        VkRect2D scissor;
 | 
			
		||||
        PipelineConfigInfo(const PipelineConfigInfo&) = delete;
 | 
			
		||||
        PipelineConfigInfo &operator=(const PipelineConfigInfo&) = delete;
 | 
			
		||||
        
 | 
			
		||||
        VkPipelineViewportStateCreateInfo viewportInfo;
 | 
			
		||||
        VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo;
 | 
			
		||||
        VkPipelineRasterizationStateCreateInfo rasterizationInfo;
 | 
			
		||||
        VkPipelineMultisampleStateCreateInfo multisampleInfo;
 | 
			
		||||
        VkPipelineColorBlendAttachmentState colorBlendAttachment;
 | 
			
		||||
        VkPipelineColorBlendStateCreateInfo colorBlendInfo;
 | 
			
		||||
        VkPipelineDepthStencilStateCreateInfo depthStencilInfo;
 | 
			
		||||
        std::vector<VkDynamicState> dynamicStateEnables;
 | 
			
		||||
        VkPipelineDynamicStateCreateInfo dynamicStateInfo;
 | 
			
		||||
        VkPipelineLayout pipelineLayout = nullptr;
 | 
			
		||||
        VkRenderPass renderPass = nullptr;
 | 
			
		||||
        uint32_t subpass = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +42,7 @@ namespace hk
 | 
			
		|||
 | 
			
		||||
        void bind(VkCommandBuffer commandBuffer);
 | 
			
		||||
 | 
			
		||||
        static PipelineConfigInfo defaultPipelineConfigInfo(uint32_t width, uint32_t height);
 | 
			
		||||
        static void defaultPipelineConfigInfo(PipelineConfigInfo& configInfo);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        static std::vector<char> readFile(const std::string &filePath);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,19 @@ namespace hk
 | 
			
		|||
 | 
			
		||||
  SwapChain::SwapChain(Device &deviceRef, VkExtent2D extent)
 | 
			
		||||
      : device{deviceRef}, windowExtent{extent}
 | 
			
		||||
  {
 | 
			
		||||
    init();
 | 
			
		||||
  }
 | 
			
		||||
  SwapChain::SwapChain(Device &deviceRef, VkExtent2D extent, std::shared_ptr<SwapChain> previous)
 | 
			
		||||
      : device{deviceRef}, windowExtent{extent}, oldSwapChain{previous}
 | 
			
		||||
  {
 | 
			
		||||
    init();
 | 
			
		||||
 | 
			
		||||
    // clean up old swap chain
 | 
			
		||||
    oldSwapChain = nullptr;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void SwapChain::init()
 | 
			
		||||
  {
 | 
			
		||||
    createSwapChain();
 | 
			
		||||
    createImageViews();
 | 
			
		||||
| 
						 | 
				
			
			@ -179,7 +192,7 @@ namespace hk
 | 
			
		|||
    createInfo.presentMode = presentMode;
 | 
			
		||||
    createInfo.clipped = VK_TRUE;
 | 
			
		||||
 | 
			
		||||
    createInfo.oldSwapchain = VK_NULL_HANDLE;
 | 
			
		||||
    createInfo.oldSwapchain = oldSwapChain == nullptr ? VK_NULL_HANDLE : oldSwapChain->swapChain;
 | 
			
		||||
 | 
			
		||||
    if (vkCreateSwapchainKHR(device.device(), &createInfo, nullptr, &swapChain) != VK_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@
 | 
			
		|||
#include <vulkan/vulkan.h>
 | 
			
		||||
 | 
			
		||||
// std lib headers
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,6 +19,7 @@ namespace hk
 | 
			
		|||
    static constexpr int MAX_FRAMES_IN_FLIGHT = 2;
 | 
			
		||||
 | 
			
		||||
    SwapChain(Device &deviceRef, VkExtent2D windowExtent);
 | 
			
		||||
    SwapChain(Device &deviceRef, VkExtent2D windowExtent, std::shared_ptr<SwapChain> previous);
 | 
			
		||||
    ~SwapChain();
 | 
			
		||||
 | 
			
		||||
    SwapChain(const SwapChain &) = delete;
 | 
			
		||||
| 
						 | 
				
			
			@ -42,6 +44,7 @@ namespace hk
 | 
			
		|||
    VkResult submitCommandBuffers(const VkCommandBuffer *buffers, uint32_t *imageIndex);
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    void init();
 | 
			
		||||
    void createSwapChain();
 | 
			
		||||
    void createImageViews();
 | 
			
		||||
    void createDepthResources();
 | 
			
		||||
| 
						 | 
				
			
			@ -72,6 +75,7 @@ namespace hk
 | 
			
		|||
    VkExtent2D windowExtent;
 | 
			
		||||
 | 
			
		||||
    VkSwapchainKHR swapChain;
 | 
			
		||||
    std::shared_ptr<SwapChain> oldSwapChain;
 | 
			
		||||
 | 
			
		||||
    std::vector<VkSemaphore> imageAvailableSemaphores;
 | 
			
		||||
    std::vector<VkSemaphore> renderFinishedSemaphores;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue