support resize window

This commit is contained in:
hoenking 2024-02-21 15:42:32 +08:00
parent dad6ce7a21
commit eb484e22f8
5 changed files with 82 additions and 36 deletions

Binary file not shown.

View File

@ -10,7 +10,7 @@ namespace hk
{
loadModels();
createPipelineLayout();
createPipeline();
recreateSwapChain();
createCommandBuffers();
}
@ -59,9 +59,9 @@ namespace hk
void FirstApp::createPipeline()
{
auto pipelineConfig =
Pipeline::defaultPipelineConfigInfo(swapChain.width(), swapChain.height());
Pipeline::defaultPipelineConfigInfo(swapChain->width(), swapChain->height());
pipelineConfig.renderPass = swapChain.getRenderPass();
pipelineConfig.renderPass = swapChain->getRenderPass();
pipelineConfig.pipelineLayout = pipelineLayout;
pipeline = std::make_unique<Pipeline>(
device,
@ -70,9 +70,23 @@ namespace hk
pipelineConfig);
}
void FirstApp::recreateSwapChain()
{
auto extent = window.getExtend();
while (extent.width == 0 || extent.height == 0)
{
extent = window.getExtend();
glfwWaitEvents();
}
vkDeviceWaitIdle(device.device());
swapChain = std::make_unique<SwapChain>(device, extent);
createPipeline();
}
void FirstApp::createCommandBuffers()
{
commandBuffers.resize(swapChain.imageCount());
commandBuffers.resize(swapChain->imageCount());
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
@ -85,53 +99,69 @@ namespace hk
{
throw std::runtime_error("failed to allocate command buffers!");
}
for (int i = 0; i < commandBuffers.size(); i++)
}
void FirstApp::recordCommandBuffer(int imageIndex)
{
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
if (vkBeginCommandBuffer(commandBuffers[imageIndex], &beginInfo) != VK_SUCCESS)
{
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
if (vkBeginCommandBuffer(commandBuffers[i], &beginInfo) != VK_SUCCESS)
{
throw std::runtime_error("failed to begin recording command buffer!");
}
throw std::runtime_error("failed to begin recording command buffer!");
}
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = swapChain.getRenderPass();
renderPassInfo.framebuffer = swapChain.getFrameBuffer(i);
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = swapChain->getRenderPass();
renderPassInfo.framebuffer = swapChain->getFrameBuffer(imageIndex);
renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent = swapChain.getSwapChainExtent();
renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent = swapChain->getSwapChainExtent();
std::array<VkClearValue, 2> clearValues{};
clearValues[0].color = {0.1f, 0.1f, 0.1f, 1.0f};
clearValues[1].depthStencil = {1.0f, 0};
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();
std::array<VkClearValue, 2> clearValues{};
clearValues[0].color = {0.1f, 0.1f, 0.1f, 1.0f};
clearValues[1].depthStencil = {1.0f, 0};
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();
vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBeginRenderPass(commandBuffers[imageIndex], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
pipeline->bind(commandBuffers[i]);
model->bind(commandBuffers[i]);
model->draw(commandBuffers[i]);
pipeline->bind(commandBuffers[imageIndex]);
model->bind(commandBuffers[imageIndex]);
model->draw(commandBuffers[imageIndex]);
vkCmdEndRenderPass(commandBuffers[i]);
if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS)
{
throw std::runtime_error("failed to record command buffer!");
}
vkCmdEndRenderPass(commandBuffers[imageIndex]);
if (vkEndCommandBuffer(commandBuffers[imageIndex]) != VK_SUCCESS)
{
throw std::runtime_error("failed to record command buffer!");
}
}
void FirstApp::drawFrame()
{
uint32_t imageIndex;
auto result = swapChain.acquireNextImage(&imageIndex);
auto result = swapChain->acquireNextImage(&imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR)
{
recreateSwapChain();
return;
}
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
{
throw std::runtime_error("failed to acquire swap chain image!");
}
result = swapChain.submitCommandBuffers(&commandBuffers[imageIndex], &imageIndex);
recordCommandBuffer(imageIndex);
result = swapChain->submitCommandBuffers(&commandBuffers[imageIndex], &imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || window.wasWindowResized())
{
window.resetWindowResizedFlag();
recreateSwapChain();
return;
}
if (result != VK_SUCCESS)
{
throw std::runtime_error("failed to present swap chain image!");

View File

@ -32,10 +32,12 @@ namespace hk
void createPipeline();
void createCommandBuffers();
void drawFrame();
void recreateSwapChain();
void recordCommandBuffer(int imageIndex);
Window window{WIDTH, HEIGHT, "Hello Vulkan!"};
Device device{window};
SwapChain swapChain{device, window.getExtend()};
std::unique_ptr<SwapChain> swapChain;
std::unique_ptr<Pipeline> pipeline;
VkPipelineLayout pipelineLayout;
std::vector<VkCommandBuffer> commandBuffers;

View File

@ -32,6 +32,16 @@ namespace hk
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
m_window = glfwCreateWindow(m_width, m_height, m_windowName.c_str(), nullptr, nullptr);
glfwSetWindowUserPointer(m_window, this);
glfwSetFramebufferSizeCallback(m_window, framebufferResizeCallback);
}
void Window::framebufferResizeCallback(GLFWwindow* window, int width, int height)
{
auto hkWindow = reinterpret_cast<Window*>(glfwGetWindowUserPointer(window));
hkWindow->m_framebufferResized = true;
hkWindow->m_width = width;
hkWindow->m_height = height;
}
}

View File

@ -18,14 +18,18 @@ namespace hk
bool shouldClose() { return glfwWindowShouldClose(m_window); }
VkExtent2D getExtend() { return {static_cast<uint32_t>(m_width), static_cast<uint32_t>(m_height)}; }
bool wasWindowResized() { return m_framebufferResized; }
void resetWindowResizedFlag() { m_framebufferResized = false; }
void createWindowSurface(VkInstance instance, VkSurfaceKHR *surface);
private:
static void framebufferResizeCallback(GLFWwindow* window, int width, int height);
void initWindow();
const int m_width;
const int m_height;
int m_width;
int m_height;
bool m_framebufferResized = false;
std::string m_windowName;
GLFWwindow *m_window;