Dynamic window resizing
This commit is contained in:
BIN
VulkanTest
BIN
VulkanTest
Binary file not shown.
@@ -75,25 +75,18 @@ namespace cve {
|
|||||||
vertexInputInfo.pVertexBindingDescriptions = bindingDescriptions.data();
|
vertexInputInfo.pVertexBindingDescriptions = bindingDescriptions.data();
|
||||||
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
|
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.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;
|
||||||
@@ -123,22 +116,16 @@ namespace cve {
|
|||||||
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
|
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
PipelineConfigInfo CvePipeline::defaultPipelineConfigInfo(uint32_t width, uint32_t height) {
|
void CvePipeline::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;
|
||||||
@@ -192,6 +179,11 @@ namespace cve {
|
|||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,14 +7,18 @@
|
|||||||
|
|
||||||
namespace cve {
|
namespace cve {
|
||||||
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;
|
||||||
@@ -29,7 +33,7 @@ namespace cve {
|
|||||||
CvePipeline& operator=(const CvePipeline&) = delete;
|
CvePipeline& operator=(const CvePipeline&) = delete;
|
||||||
|
|
||||||
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);
|
||||||
|
|||||||
@@ -13,6 +13,18 @@ namespace cve {
|
|||||||
|
|
||||||
CveSwapChain::CveSwapChain(CveDevice &deviceRef, VkExtent2D extent)
|
CveSwapChain::CveSwapChain(CveDevice &deviceRef, VkExtent2D extent)
|
||||||
: device{deviceRef}, windowExtent{extent} {
|
: device{deviceRef}, windowExtent{extent} {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
CveSwapChain::CveSwapChain(CveDevice &deviceRef, VkExtent2D extent, std::shared_ptr<CveSwapChain> previous)
|
||||||
|
: device{deviceRef}, windowExtent{extent}, oldSwapChain{previous} {
|
||||||
|
init();
|
||||||
|
|
||||||
|
// Clean up old swap chain
|
||||||
|
oldSwapChain = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CveSwapChain::init() {
|
||||||
createSwapChain();
|
createSwapChain();
|
||||||
createImageViews();
|
createImageViews();
|
||||||
createRenderPass();
|
createRenderPass();
|
||||||
@@ -162,7 +174,7 @@ void CveSwapChain::createSwapChain() {
|
|||||||
createInfo.presentMode = presentMode;
|
createInfo.presentMode = presentMode;
|
||||||
createInfo.clipped = VK_TRUE;
|
createInfo.clipped = VK_TRUE;
|
||||||
|
|
||||||
createInfo.oldSwapchain = VK_NULL_HANDLE;
|
createInfo.oldSwapchain = oldSwapChain ? oldSwapChain->swapChain : VK_NULL_HANDLE;
|
||||||
|
|
||||||
if (vkCreateSwapchainKHR(device.device(), &createInfo, nullptr, &swapChain) != VK_SUCCESS) {
|
if (vkCreateSwapchainKHR(device.device(), &createInfo, nullptr, &swapChain) != VK_SUCCESS) {
|
||||||
throw std::runtime_error("failed to create swap chain!");
|
throw std::runtime_error("failed to create swap chain!");
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ class CveSwapChain {
|
|||||||
static constexpr int MAX_FRAMES_IN_FLIGHT = 2;
|
static constexpr int MAX_FRAMES_IN_FLIGHT = 2;
|
||||||
|
|
||||||
CveSwapChain(CveDevice &deviceRef, VkExtent2D windowExtent);
|
CveSwapChain(CveDevice &deviceRef, VkExtent2D windowExtent);
|
||||||
|
CveSwapChain(CveDevice &deviceRef, VkExtent2D windowExtent, std::shared_ptr<CveSwapChain> previous);
|
||||||
~CveSwapChain();
|
~CveSwapChain();
|
||||||
|
|
||||||
CveSwapChain(const CveSwapChain &) = delete;
|
CveSwapChain(const CveSwapChain &) = delete;
|
||||||
@@ -39,6 +41,7 @@ class CveSwapChain {
|
|||||||
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();
|
||||||
@@ -69,6 +72,7 @@ class CveSwapChain {
|
|||||||
VkExtent2D windowExtent;
|
VkExtent2D windowExtent;
|
||||||
|
|
||||||
VkSwapchainKHR swapChain;
|
VkSwapchainKHR swapChain;
|
||||||
|
std::shared_ptr<CveSwapChain> oldSwapChain;
|
||||||
|
|
||||||
std::vector<VkSemaphore> imageAvailableSemaphores;
|
std::vector<VkSemaphore> imageAvailableSemaphores;
|
||||||
std::vector<VkSemaphore> renderFinishedSemaphores;
|
std::vector<VkSemaphore> renderFinishedSemaphores;
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ namespace cve {
|
|||||||
|
|
||||||
window = glfwCreateWindow(width, height,
|
window = glfwCreateWindow(width, height,
|
||||||
windowName.c_str(), nullptr, nullptr);
|
windowName.c_str(), nullptr, nullptr);
|
||||||
|
glfwSetWindowUserPointer(window, this);
|
||||||
|
glfwSetFramebufferSizeCallback(window, framebufferResizedCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CveWindow::createWindowSurface(VkInstance instance, VkSurfaceKHR *surface) {
|
void CveWindow::createWindowSurface(VkInstance instance, VkSurfaceKHR *surface) {
|
||||||
@@ -27,4 +29,11 @@ namespace cve {
|
|||||||
throw std::runtime_error("Failed to create window surface");
|
throw std::runtime_error("Failed to create window surface");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CveWindow::framebufferResizedCallback(GLFWwindow *window, int width, int height) {
|
||||||
|
auto cveWindow = reinterpret_cast<CveWindow *>(glfwGetWindowUserPointer(window));
|
||||||
|
cveWindow->framebufferResized = true;
|
||||||
|
cveWindow->width = width;
|
||||||
|
cveWindow->height = height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,17 @@ class CveWindow {
|
|||||||
|
|
||||||
bool shouldClose() { return glfwWindowShouldClose(window); };
|
bool shouldClose() { return glfwWindowShouldClose(window); };
|
||||||
VkExtent2D getExtent() { return { static_cast<uint32_t>(width), static_cast<uint32_t>(height) }; };
|
VkExtent2D getExtent() { return { static_cast<uint32_t>(width), static_cast<uint32_t>(height) }; };
|
||||||
|
bool wasWindowResized() { return framebufferResized; };
|
||||||
|
void resetWindowResizedFlag() { framebufferResized = false; };
|
||||||
|
|
||||||
void createWindowSurface(VkInstance instance, VkSurfaceKHR *surface);
|
void createWindowSurface(VkInstance instance, VkSurfaceKHR *surface);
|
||||||
private:
|
private:
|
||||||
|
static void framebufferResizedCallback(GLFWwindow *window, int width, int height);
|
||||||
void initWindow();
|
void initWindow();
|
||||||
|
|
||||||
const int width;
|
int width;
|
||||||
const int height;
|
int height;
|
||||||
|
bool framebufferResized = false;
|
||||||
|
|
||||||
std::string windowName;
|
std::string windowName;
|
||||||
GLFWwindow *window;
|
GLFWwindow *window;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace cve {
|
|||||||
FirstApp::FirstApp() {
|
FirstApp::FirstApp() {
|
||||||
loadModels();
|
loadModels();
|
||||||
createPipelineLayout();
|
createPipelineLayout();
|
||||||
createPipeline();
|
recreateSwapChain();
|
||||||
createCommandBuffers();
|
createCommandBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,8 +48,12 @@ namespace cve {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FirstApp::createPipeline() {
|
void FirstApp::createPipeline() {
|
||||||
auto pipelineConfig = CvePipeline::defaultPipelineConfigInfo(cveSwapChain.width(), cveSwapChain.height());
|
assert(cveSwapChain != nullptr && "Cannot create pipeline before swap chain");
|
||||||
pipelineConfig.renderPass = cveSwapChain.getRenderPass();
|
assert(pipelineLayout != nullptr && "Cannot create pipeline before pipeline layout");
|
||||||
|
|
||||||
|
PipelineConfigInfo pipelineConfig{};
|
||||||
|
CvePipeline::defaultPipelineConfigInfo(pipelineConfig);
|
||||||
|
pipelineConfig.renderPass = cveSwapChain->getRenderPass();
|
||||||
pipelineConfig.pipelineLayout = pipelineLayout;
|
pipelineConfig.pipelineLayout = pipelineLayout;
|
||||||
cvePipeline = std::make_unique<CvePipeline>(
|
cvePipeline = std::make_unique<CvePipeline>(
|
||||||
cveDevice,
|
cveDevice,
|
||||||
@@ -59,8 +63,31 @@ namespace cve {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FirstApp::recreateSwapChain() {
|
||||||
|
auto extent = cveWindow.getExtent();
|
||||||
|
while (extent.width == 0 || extent.height == 0) {
|
||||||
|
extent = cveWindow.getExtent();
|
||||||
|
glfwWaitEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
vkDeviceWaitIdle(cveDevice.device());
|
||||||
|
|
||||||
|
if (cveSwapChain == nullptr) {
|
||||||
|
cveSwapChain = std::make_unique<CveSwapChain>(cveDevice, extent);
|
||||||
|
} else {
|
||||||
|
cveSwapChain = std::make_unique<CveSwapChain>(cveDevice, extent, std::move(cveSwapChain));
|
||||||
|
if (cveSwapChain->imageCount() != commandBuffers.size()) {
|
||||||
|
freeCommandBuffers();
|
||||||
|
createCommandBuffers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if render pass is compatible
|
||||||
|
createPipeline();
|
||||||
|
}
|
||||||
|
|
||||||
void FirstApp::createCommandBuffers() {
|
void FirstApp::createCommandBuffers() {
|
||||||
commandBuffers.resize(cveSwapChain.imageCount());
|
commandBuffers.resize(cveSwapChain->imageCount());
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo allocInfo{};
|
VkCommandBufferAllocateInfo allocInfo{};
|
||||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
@@ -72,22 +99,29 @@ namespace cve {
|
|||||||
VK_SUCCESS) {
|
VK_SUCCESS) {
|
||||||
throw std::runtime_error("Failed to allocate command buffers");
|
throw std::runtime_error("Failed to allocate command buffers");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i=0; i < commandBuffers.size(); i++) {
|
void FirstApp::freeCommandBuffers() {
|
||||||
|
vkFreeCommandBuffers(cveDevice.device(), cveDevice.getCommandPool(),
|
||||||
|
static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());
|
||||||
|
commandBuffers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FirstApp::recordCommandBuffer(int imageIndex) {
|
||||||
VkCommandBufferBeginInfo beginInfo{};
|
VkCommandBufferBeginInfo beginInfo{};
|
||||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
|
||||||
if (vkBeginCommandBuffer(commandBuffers[i], &beginInfo) != VK_SUCCESS) {
|
if (vkBeginCommandBuffer(commandBuffers[imageIndex], &beginInfo) != VK_SUCCESS) {
|
||||||
throw std::runtime_error("Failed to begin command buffer recording");
|
throw std::runtime_error("Failed to begin command buffer recording");
|
||||||
}
|
}
|
||||||
|
|
||||||
VkRenderPassBeginInfo renderPassInfo{};
|
VkRenderPassBeginInfo renderPassInfo{};
|
||||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
renderPassInfo.renderPass = cveSwapChain.getRenderPass();
|
renderPassInfo.renderPass = cveSwapChain->getRenderPass();
|
||||||
renderPassInfo.framebuffer = cveSwapChain.getFrameBuffer(i);
|
renderPassInfo.framebuffer = cveSwapChain->getFrameBuffer(imageIndex);
|
||||||
|
|
||||||
renderPassInfo.renderArea.offset = {0, 0};
|
renderPassInfo.renderArea.offset = {0, 0};
|
||||||
renderPassInfo.renderArea.extent = cveSwapChain.getSwapChainExtent();
|
renderPassInfo.renderArea.extent = cveSwapChain->getSwapChainExtent();
|
||||||
|
|
||||||
std::array<VkClearValue, 2> clearValues{};
|
std::array<VkClearValue, 2> clearValues{};
|
||||||
clearValues[0].color = {0.1f, 0.1f, 0.1f, 1.0f};
|
clearValues[0].color = {0.1f, 0.1f, 0.1f, 1.0f};
|
||||||
@@ -95,27 +129,48 @@ namespace cve {
|
|||||||
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
|
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
|
||||||
renderPassInfo.pClearValues = clearValues.data();
|
renderPassInfo.pClearValues = clearValues.data();
|
||||||
|
|
||||||
vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(commandBuffers[imageIndex], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
cvePipeline->bind(commandBuffers[i]);
|
VkViewport viewport{};
|
||||||
cveModel->bind(commandBuffers[i]);
|
viewport.x = 0.0f;
|
||||||
cveModel->draw(commandBuffers[i]);
|
viewport.y = 0.0f;
|
||||||
|
viewport.width = static_cast<float>(cveSwapChain->getSwapChainExtent().width);
|
||||||
|
viewport.height = static_cast<float>(cveSwapChain->getSwapChainExtent().height);
|
||||||
|
viewport.minDepth = 0.0f;
|
||||||
|
viewport.maxDepth = 1.0f;
|
||||||
|
VkRect2D scissor{{0, 0}, cveSwapChain->getSwapChainExtent()};
|
||||||
|
vkCmdSetViewport(commandBuffers[imageIndex], 0, 1, &viewport);
|
||||||
|
vkCmdSetScissor(commandBuffers[imageIndex], 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdEndRenderPass(commandBuffers[i]);
|
cvePipeline->bind(commandBuffers[imageIndex]);
|
||||||
if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) {
|
cveModel->bind(commandBuffers[imageIndex]);
|
||||||
|
cveModel->draw(commandBuffers[imageIndex]);
|
||||||
|
|
||||||
|
vkCmdEndRenderPass(commandBuffers[imageIndex]);
|
||||||
|
if (vkEndCommandBuffer(commandBuffers[imageIndex]) != VK_SUCCESS) {
|
||||||
throw std::runtime_error("Failed to record command buffer!");
|
throw std::runtime_error("Failed to record command buffer!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
void FirstApp::drawFrame() {
|
void FirstApp::drawFrame() {
|
||||||
uint32_t imageIndex;
|
uint32_t imageIndex;
|
||||||
auto result = cveSwapChain.acquireNextImage(&imageIndex);
|
auto result = cveSwapChain->acquireNextImage(&imageIndex);
|
||||||
|
|
||||||
|
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||||
|
recreateSwapChain();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
|
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
|
||||||
throw std::runtime_error("Failed to acquire swap chain image!");
|
throw std::runtime_error("Failed to acquire swap chain image!");
|
||||||
}
|
}
|
||||||
|
|
||||||
result = cveSwapChain.submitCommandBuffers(&commandBuffers[imageIndex], &imageIndex);
|
recordCommandBuffer(imageIndex);
|
||||||
|
result = cveSwapChain->submitCommandBuffers(&commandBuffers[imageIndex], &imageIndex);
|
||||||
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || cveWindow.wasWindowResized()) {
|
||||||
|
cveWindow.resetWindowResizedFlag();
|
||||||
|
recreateSwapChain();
|
||||||
|
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!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,11 +27,14 @@ namespace cve {
|
|||||||
void createPipelineLayout();
|
void createPipelineLayout();
|
||||||
void createPipeline();
|
void createPipeline();
|
||||||
void createCommandBuffers();
|
void createCommandBuffers();
|
||||||
|
void freeCommandBuffers();
|
||||||
void drawFrame();
|
void drawFrame();
|
||||||
|
void recreateSwapChain();
|
||||||
|
void recordCommandBuffer(int imageIndex);
|
||||||
|
|
||||||
CveWindow cveWindow{WIDTH, HEIGHT, "Hello Vulkan!"};
|
CveWindow cveWindow{WIDTH, HEIGHT, "Hello Vulkan!"};
|
||||||
CveDevice cveDevice{cveWindow};
|
CveDevice cveDevice{cveWindow};
|
||||||
CveSwapChain cveSwapChain{cveDevice, cveWindow.getExtent()};
|
std::unique_ptr<CveSwapChain> cveSwapChain;
|
||||||
std::unique_ptr<CvePipeline> cvePipeline;
|
std::unique_ptr<CvePipeline> cvePipeline;
|
||||||
VkPipelineLayout pipelineLayout;
|
VkPipelineLayout pipelineLayout;
|
||||||
std::vector<VkCommandBuffer> commandBuffers;
|
std::vector<VkCommandBuffer> commandBuffers;
|
||||||
|
|||||||
Reference in New Issue
Block a user