Swap Chain Recreation & Dynamic Viewports
This commit is contained in:
parent
eb484e22f8
commit
976ff14298
|
@ -48,6 +48,30 @@
|
||||||
"typeinfo": "cpp",
|
"typeinfo": "cpp",
|
||||||
"fstream": "cpp",
|
"fstream": "cpp",
|
||||||
"set": "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()
|
void FirstApp::createPipeline()
|
||||||
{
|
{
|
||||||
auto pipelineConfig =
|
assert(swapChain != nullptr && "Cannot create pipeline before swap chain");
|
||||||
Pipeline::defaultPipelineConfigInfo(swapChain->width(), swapChain->height());
|
assert(pipelineLayout != nullptr && "Cannot create pipeline before pipeline layout");
|
||||||
|
|
||||||
|
PipelineConfigInfo pipelineConfig{};
|
||||||
|
Pipeline::defaultPipelineConfigInfo(pipelineConfig);
|
||||||
|
|
||||||
pipelineConfig.renderPass = swapChain->getRenderPass();
|
pipelineConfig.renderPass = swapChain->getRenderPass();
|
||||||
pipelineConfig.pipelineLayout = pipelineLayout;
|
pipelineConfig.pipelineLayout = pipelineLayout;
|
||||||
|
@ -80,7 +83,22 @@ namespace hk
|
||||||
}
|
}
|
||||||
|
|
||||||
vkDeviceWaitIdle(device.device());
|
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();
|
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)
|
void FirstApp::recordCommandBuffer(int imageIndex)
|
||||||
{
|
{
|
||||||
VkCommandBufferBeginInfo beginInfo{};
|
VkCommandBufferBeginInfo beginInfo{};
|
||||||
|
@ -126,6 +154,17 @@ namespace hk
|
||||||
|
|
||||||
vkCmdBeginRenderPass(commandBuffers[imageIndex], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
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]);
|
pipeline->bind(commandBuffers[imageIndex]);
|
||||||
model->bind(commandBuffers[imageIndex]);
|
model->bind(commandBuffers[imageIndex]);
|
||||||
model->draw(commandBuffers[imageIndex]);
|
model->draw(commandBuffers[imageIndex]);
|
||||||
|
@ -161,7 +200,7 @@ namespace hk
|
||||||
recreateSwapChain();
|
recreateSwapChain();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("failed to present swap chain image!");
|
throw std::runtime_error("failed to present swap chain image!");
|
||||||
|
|
|
@ -31,6 +31,7 @@ namespace hk
|
||||||
void createPipelineLayout();
|
void createPipelineLayout();
|
||||||
void createPipeline();
|
void createPipeline();
|
||||||
void createCommandBuffers();
|
void createCommandBuffers();
|
||||||
|
void freeCommandBuffers();
|
||||||
void drawFrame();
|
void drawFrame();
|
||||||
void recreateSwapChain();
|
void recreateSwapChain();
|
||||||
void recordCommandBuffer(int imageIndex);
|
void recordCommandBuffer(int imageIndex);
|
||||||
|
|
|
@ -31,22 +31,17 @@ namespace hk
|
||||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicPipeline);
|
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.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
configInfo.inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
configInfo.inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
configInfo.inputAssemblyInfo.primitiveRestartEnable = VK_FALSE;
|
configInfo.inputAssemblyInfo.primitiveRestartEnable = VK_FALSE;
|
||||||
|
|
||||||
configInfo.viewport.x = 0.0f;
|
configInfo.viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||||
configInfo.viewport.y = 0.0f;
|
configInfo.viewportInfo.viewportCount = 1;
|
||||||
configInfo.viewport.width = static_cast<float>(width);
|
configInfo.viewportInfo.pViewports = nullptr;
|
||||||
configInfo.viewport.height = static_cast<float>(height);
|
configInfo.viewportInfo.scissorCount = 1;
|
||||||
configInfo.viewport.minDepth = 0.0f;
|
configInfo.viewportInfo.pScissors = nullptr;
|
||||||
configInfo.viewport.maxDepth = 1.0f;
|
|
||||||
|
|
||||||
configInfo.scissor.offset = {0, 0};
|
|
||||||
configInfo.scissor.extent = {width, height};
|
|
||||||
|
|
||||||
configInfo.rasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
configInfo.rasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||||
configInfo.rasterizationInfo.depthClampEnable = VK_FALSE;
|
configInfo.rasterizationInfo.depthClampEnable = VK_FALSE;
|
||||||
|
@ -100,7 +95,11 @@ namespace hk
|
||||||
configInfo.depthStencilInfo.front = {}; // Optional
|
configInfo.depthStencilInfo.front = {}; // Optional
|
||||||
configInfo.depthStencilInfo.back = {}; // 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)
|
std::vector<char> Pipeline::readFile(const std::string &filePath)
|
||||||
|
@ -165,25 +164,18 @@ namespace hk
|
||||||
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
|
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
|
||||||
vertexInputInfo.pVertexBindingDescriptions = bindingDescriptions.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{};
|
VkGraphicsPipelineCreateInfo pipelineInfo{};
|
||||||
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
pipelineInfo.stageCount = 2;
|
pipelineInfo.stageCount = 2;
|
||||||
pipelineInfo.pStages = shaderStages;
|
pipelineInfo.pStages = shaderStages;
|
||||||
pipelineInfo.pVertexInputState = &vertexInputInfo;
|
pipelineInfo.pVertexInputState = &vertexInputInfo;
|
||||||
pipelineInfo.pInputAssemblyState = &configInfo.inputAssemblyInfo;
|
pipelineInfo.pInputAssemblyState = &configInfo.inputAssemblyInfo;
|
||||||
pipelineInfo.pViewportState = &viewportInfo;
|
pipelineInfo.pViewportState = &configInfo.viewportInfo;
|
||||||
pipelineInfo.pRasterizationState = &configInfo.rasterizationInfo;
|
pipelineInfo.pRasterizationState = &configInfo.rasterizationInfo;
|
||||||
pipelineInfo.pMultisampleState = &configInfo.multisampleInfo;
|
pipelineInfo.pMultisampleState = &configInfo.multisampleInfo;
|
||||||
pipelineInfo.pColorBlendState = &configInfo.colorBlendInfo;
|
pipelineInfo.pColorBlendState = &configInfo.colorBlendInfo;
|
||||||
pipelineInfo.pDepthStencilState = &configInfo.depthStencilInfo;
|
pipelineInfo.pDepthStencilState = &configInfo.depthStencilInfo;
|
||||||
pipelineInfo.pDynamicState = nullptr;
|
pipelineInfo.pDynamicState = &configInfo.dynamicStateInfo;
|
||||||
|
|
||||||
pipelineInfo.layout = configInfo.pipelineLayout;
|
pipelineInfo.layout = configInfo.pipelineLayout;
|
||||||
pipelineInfo.renderPass = configInfo.renderPass;
|
pipelineInfo.renderPass = configInfo.renderPass;
|
||||||
|
|
|
@ -10,14 +10,18 @@ namespace hk
|
||||||
{
|
{
|
||||||
struct PipelineConfigInfo
|
struct PipelineConfigInfo
|
||||||
{
|
{
|
||||||
VkViewport viewport;
|
PipelineConfigInfo(const PipelineConfigInfo&) = delete;
|
||||||
VkRect2D scissor;
|
PipelineConfigInfo &operator=(const PipelineConfigInfo&) = delete;
|
||||||
|
|
||||||
|
VkPipelineViewportStateCreateInfo viewportInfo;
|
||||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo;
|
VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo;
|
||||||
VkPipelineRasterizationStateCreateInfo rasterizationInfo;
|
VkPipelineRasterizationStateCreateInfo rasterizationInfo;
|
||||||
VkPipelineMultisampleStateCreateInfo multisampleInfo;
|
VkPipelineMultisampleStateCreateInfo multisampleInfo;
|
||||||
VkPipelineColorBlendAttachmentState colorBlendAttachment;
|
VkPipelineColorBlendAttachmentState colorBlendAttachment;
|
||||||
VkPipelineColorBlendStateCreateInfo colorBlendInfo;
|
VkPipelineColorBlendStateCreateInfo colorBlendInfo;
|
||||||
VkPipelineDepthStencilStateCreateInfo depthStencilInfo;
|
VkPipelineDepthStencilStateCreateInfo depthStencilInfo;
|
||||||
|
std::vector<VkDynamicState> dynamicStateEnables;
|
||||||
|
VkPipelineDynamicStateCreateInfo dynamicStateInfo;
|
||||||
VkPipelineLayout pipelineLayout = nullptr;
|
VkPipelineLayout pipelineLayout = nullptr;
|
||||||
VkRenderPass renderPass = nullptr;
|
VkRenderPass renderPass = nullptr;
|
||||||
uint32_t subpass = 0;
|
uint32_t subpass = 0;
|
||||||
|
@ -38,7 +42,7 @@ namespace hk
|
||||||
|
|
||||||
void bind(VkCommandBuffer commandBuffer);
|
void bind(VkCommandBuffer commandBuffer);
|
||||||
|
|
||||||
static PipelineConfigInfo defaultPipelineConfigInfo(uint32_t width, uint32_t height);
|
static void defaultPipelineConfigInfo(PipelineConfigInfo& configInfo);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::vector<char> readFile(const std::string &filePath);
|
static std::vector<char> readFile(const std::string &filePath);
|
||||||
|
|
|
@ -14,6 +14,19 @@ namespace hk
|
||||||
|
|
||||||
SwapChain::SwapChain(Device &deviceRef, VkExtent2D extent)
|
SwapChain::SwapChain(Device &deviceRef, VkExtent2D extent)
|
||||||
: device{deviceRef}, windowExtent{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();
|
createSwapChain();
|
||||||
createImageViews();
|
createImageViews();
|
||||||
|
@ -179,7 +192,7 @@ namespace hk
|
||||||
createInfo.presentMode = presentMode;
|
createInfo.presentMode = presentMode;
|
||||||
createInfo.clipped = VK_TRUE;
|
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)
|
if (vkCreateSwapchainKHR(device.device(), &createInfo, nullptr, &swapChain) != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
// std lib headers
|
// std lib headers
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@ namespace hk
|
||||||
static constexpr int MAX_FRAMES_IN_FLIGHT = 2;
|
static constexpr int MAX_FRAMES_IN_FLIGHT = 2;
|
||||||
|
|
||||||
SwapChain(Device &deviceRef, VkExtent2D windowExtent);
|
SwapChain(Device &deviceRef, VkExtent2D windowExtent);
|
||||||
|
SwapChain(Device &deviceRef, VkExtent2D windowExtent, std::shared_ptr<SwapChain> previous);
|
||||||
~SwapChain();
|
~SwapChain();
|
||||||
|
|
||||||
SwapChain(const SwapChain &) = delete;
|
SwapChain(const SwapChain &) = delete;
|
||||||
|
@ -42,6 +44,7 @@ namespace hk
|
||||||
VkResult submitCommandBuffers(const VkCommandBuffer *buffers, uint32_t *imageIndex);
|
VkResult submitCommandBuffers(const VkCommandBuffer *buffers, uint32_t *imageIndex);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void init();
|
||||||
void createSwapChain();
|
void createSwapChain();
|
||||||
void createImageViews();
|
void createImageViews();
|
||||||
void createDepthResources();
|
void createDepthResources();
|
||||||
|
@ -72,6 +75,7 @@ namespace hk
|
||||||
VkExtent2D windowExtent;
|
VkExtent2D windowExtent;
|
||||||
|
|
||||||
VkSwapchainKHR swapChain;
|
VkSwapchainKHR swapChain;
|
||||||
|
std::shared_ptr<SwapChain> oldSwapChain;
|
||||||
|
|
||||||
std::vector<VkSemaphore> imageAvailableSemaphores;
|
std::vector<VkSemaphore> imageAvailableSemaphores;
|
||||||
std::vector<VkSemaphore> renderFinishedSemaphores;
|
std::vector<VkSemaphore> renderFinishedSemaphores;
|
||||||
|
|
Loading…
Reference in New Issue