summaryrefslogtreecommitdiff
path: root/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'main.cpp')
-rw-r--r--main.cpp417
1 files changed, 410 insertions, 7 deletions
diff --git a/main.cpp b/main.cpp
index 07c54a2..61f8a16 100644
--- a/main.cpp
+++ b/main.cpp
@@ -13,6 +13,13 @@
#include <cstdint>
#include <limits>
#include <algorithm>
+#include <fstream>
+
+#ifdef NDEBUG
+ const bool enableValidationLayers = false;
+#else
+ const bool enableValidationLayers = true;
+#endif
const uint32_t WIDTH = 800;
const uint32_t HEIGHT = 600;
@@ -21,11 +28,20 @@ const std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};
-#ifdef NDEBUG
- const bool enableValidationLayers = false;
-#else
- const bool enableValidationLayers = true;
-#endif
+static std::vector<char> readFile(const std::string& filename) {
+ std::ifstream file(filename, std::ios::ate | std::ios::binary);
+
+ if (!file.is_open()) {
+ throw std::runtime_error("failed to open file!");
+ }
+
+ size_t fileSize = (size_t) file.tellg();
+ std::vector<char> buffer(fileSize);
+ file.seekg(0);
+ file.read(buffer.data(), fileSize);
+ file.close();
+ return buffer;
+}
class HelloTriangleApplication {
@@ -62,6 +78,20 @@ private:
std::vector<VkImageView> swapChainImageViews;
+ VkRenderPass renderPass;
+
+ VkPipelineLayout pipelineLayout;
+ VkPipeline graphicsPipeline;
+
+ std::vector<VkFramebuffer> swapChainFramebuffers;
+
+ VkCommandPool commandPool;
+ VkCommandBuffer commandBuffer;
+
+ VkSemaphore imageAvailableSemaphore;
+ VkSemaphore renderFinishedSemaphore;
+ VkFence inFlightFence;
+
void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) {
createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
@@ -88,6 +118,7 @@ private:
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
}
+
void initVulkan() {
createInstance(); // 01 Setup -> Instance
setupDebugMessenger(); // 02 Setup -> Validation Layers
@@ -96,14 +127,332 @@ private:
createLogicalDevice(); // 04 Setup -> Logical Device
createSwapChain(); // 06 Presentation -> Swap Chain
createImageViews(); // 07 Presentation -> Image Views
- createGraphicsPipeline(); // 08 Graphics Pipeline -> Introduction
+ createRenderPass(); // 11 Graphics Pipeline -> RenderPasses
+ createGraphicsPipeline(); // 08 Graphics Pipeline -> Introduction
+ createFramebuffers(); // 12 Drawing -> Framebuffers
+ createCommandPool(); // 13 Drawing -> Commmand Buffers
+ createCommandBuffer(); // --
+ createSyncObjects (); // 14 Drawing -> Rendering
+ }
+ void createSyncObjects() {
+ VkSemaphoreCreateInfo semaphoreInfo{};
+ semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+
+ VkFenceCreateInfo fenceInfo{};
+ fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+
+ if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphore) != VK_SUCCESS ||
+ vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphore) != VK_SUCCESS ||
+ vkCreateFence(device, &fenceInfo, nullptr, &inFlightFence) != VK_SUCCESS) {
+ throw std::runtime_error("failed to create semaphores!");
+ }
+ }
+
+ void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
+
+ VkCommandBufferBeginInfo beginInfo{};
+ beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ beginInfo.flags = 0; // Optional
+ beginInfo.pInheritanceInfo = nullptr; // Optional
+
+ if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {
+ throw std::runtime_error("failed to begin recording command buffer!");
+ }
+
+ VkRenderPassBeginInfo renderPassInfo{};
+ renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ renderPassInfo.renderPass = renderPass;
+ renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex];
+ renderPassInfo.renderArea.offset = {0, 0};
+ renderPassInfo.renderArea.extent = swapChainExtent;
+
+ VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
+ renderPassInfo.clearValueCount = 1;
+ renderPassInfo.pClearValues = &clearColor;
+
+ vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
+ vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
+
+ VkViewport viewport{};
+ viewport.x = 0.0f;
+ viewport.y = 0.0f;
+ viewport.width = static_cast<float>(swapChainExtent.width);
+ viewport.height = static_cast<float>(swapChainExtent.height);
+ viewport.minDepth = 0.0f;
+ viewport.maxDepth = 1.0f;
+ vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
+
+ VkRect2D scissor{};
+ scissor.offset = {0, 0};
+ scissor.extent = swapChainExtent;
+ vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
+
+ vkCmdDraw(commandBuffer, 3, 1, 0, 0);
+ vkCmdEndRenderPass(commandBuffer);
+
+ if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
+ throw std::runtime_error("failed to record command buffer!");
+ }
+ }
+
+ void createCommandBuffer() {
+ VkCommandBufferAllocateInfo allocInfo{};
+ allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ allocInfo.commandPool = commandPool;
+ allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ allocInfo.commandBufferCount = 1;
+
+ if (vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer) != VK_SUCCESS) {
+ throw std::runtime_error("failed to allocate command buffers!");
+ }
+ }
+
+ void createCommandPool() {
+ QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice);
+
+ VkCommandPoolCreateInfo poolInfo{};
+ poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();
+
+ if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {
+ throw std::runtime_error("failed to create command pool!");
+ }
+ }
+
+ void createFramebuffers() {
+ swapChainFramebuffers.resize(swapChainImageViews.size());
+ for (size_t i = 0; i < swapChainImageViews.size(); i++) {
+ VkImageView attachments[] = {
+ swapChainImageViews[i]
+ };
+
+ VkFramebufferCreateInfo framebufferInfo{};
+ framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ framebufferInfo.renderPass = renderPass;
+ framebufferInfo.attachmentCount = 1;
+ framebufferInfo.pAttachments = attachments;
+ framebufferInfo.width = swapChainExtent.width;
+ framebufferInfo.height = swapChainExtent.height;
+ framebufferInfo.layers = 1;
+
+ if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) {
+ throw std::runtime_error("failed to create framebuffer!");
+ }
+ }
+ }
+
+ void createRenderPass() {
+
+ VkAttachmentDescription colorAttachment{};
+ colorAttachment.format = swapChainImageFormat;
+ colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
+ colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+
+ VkAttachmentReference colorAttachmentRef{};
+ colorAttachmentRef.attachment = 0;
+ colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ VkSubpassDescription subpass{};
+ subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass.colorAttachmentCount = 1;
+ subpass.pColorAttachments = &colorAttachmentRef;
+
+ VkSubpassDependency dependency{};
+ dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
+ dependency.dstSubpass = 0;
+ dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependency.srcAccessMask = 0;
+ dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ VkRenderPassCreateInfo renderPassInfo{};
+ renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ renderPassInfo.attachmentCount = 1;
+ renderPassInfo.pAttachments = &colorAttachment;
+ renderPassInfo.subpassCount = 1;
+ renderPassInfo.pSubpasses = &subpass;
+ renderPassInfo.dependencyCount = 1;
+ renderPassInfo.pDependencies = &dependency;
+
+ if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
+ throw std::runtime_error("failed to create render pass!");
+ }
}
void createGraphicsPipeline() {
+ // 09 Graphics Pipeline -> Shader Modules
+ auto vertShaderCode = readFile("shaders/vert.spv");
+ auto fragShaderCode = readFile("shaders/frag.spv");
+ std::cout << vertShaderCode.size() << std::endl;
+ std::cout << fragShaderCode.size() << std::endl;
+ VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
+ VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);
+
+ VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
+ vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
+ vertShaderStageInfo.module = vertShaderModule;
+ vertShaderStageInfo.pName = "main";
+
+ VkPipelineShaderStageCreateInfo fragShaderStageInfo{};
+ fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
+ fragShaderStageInfo.module = fragShaderModule;
+ fragShaderStageInfo.pName = "main";
+
+ VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo};
+
+ // 10 Graphics Pipeline -> Fixed Functions
+ std::vector<VkDynamicState> dynamicStates = {
+ VK_DYNAMIC_STATE_VIEWPORT,
+ VK_DYNAMIC_STATE_SCISSOR
+ };
+
+ VkPipelineDynamicStateCreateInfo dynamicState{};
+ dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
+ dynamicState.pDynamicStates = dynamicStates.data();
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.vertexBindingDescriptionCount = 0;
+ vertexInputInfo.pVertexBindingDescriptions = nullptr; // Optional
+ vertexInputInfo.vertexAttributeDescriptionCount = 0;
+ vertexInputInfo.pVertexAttributeDescriptions = nullptr; // Optional
+
+ VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
+ inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ inputAssembly.primitiveRestartEnable = VK_FALSE;
+
+ VkViewport viewport{};
+ viewport.x = 0.0f;
+ viewport.y = 0.0f;
+ viewport.width = (float) swapChainExtent.width;
+ viewport.height = (float) swapChainExtent.height;
+ viewport.minDepth = 0.0f;
+ viewport.maxDepth = 1.0f;
+
+ VkRect2D scissor{};
+ scissor.offset = {0, 0};
+ scissor.extent = swapChainExtent;
+
+// DYN STATE?
+ VkPipelineViewportStateCreateInfo viewportState{};
+ viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ viewportState.viewportCount = 1;
+ viewportState.scissorCount = 1;
+
+// VkPipelineViewportStateCreateInfo viewportState{};
+// viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+// viewportState.viewportCount = 1;
+// viewportState.pViewports = &viewport;
+// viewportState.scissorCount = 1;
+// viewportState.pScissors = &scissor;
+
+ VkPipelineRasterizationStateCreateInfo rasterizer{};
+ rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rasterizer.depthClampEnable = VK_FALSE;
+ rasterizer.rasterizerDiscardEnable = VK_FALSE;
+ rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
+ rasterizer.lineWidth = 1.0f;
+ rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
+ rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
+
+ rasterizer.depthBiasEnable = VK_FALSE;
+ rasterizer.depthBiasConstantFactor = 0.0f; // Optional
+ rasterizer.depthBiasClamp = 0.0f; // Optional
+ rasterizer.depthBiasSlopeFactor = 0.0f; // Optional
+
+ VkPipelineMultisampleStateCreateInfo multisampling{};
+ multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ multisampling.sampleShadingEnable = VK_FALSE;
+ multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ multisampling.minSampleShading = 1.0f; // Optional
+ multisampling.pSampleMask = nullptr; // Optional
+ multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
+ multisampling.alphaToOneEnable = VK_FALSE; // Optional
+
+ VkPipelineColorBlendAttachmentState colorBlendAttachment{};
+ colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
+ colorBlendAttachment.blendEnable = VK_FALSE;
+ colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // Optional
+ colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
+ colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; // Optional
+ colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // Optional
+ colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
+ colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; // Optional
+
+ VkPipelineColorBlendStateCreateInfo colorBlending{};
+ colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ colorBlending.logicOpEnable = VK_FALSE;
+ colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
+ colorBlending.attachmentCount = 1;
+ colorBlending.pAttachments = &colorBlendAttachment;
+ colorBlending.blendConstants[0] = 0.0f; // Optional
+ colorBlending.blendConstants[1] = 0.0f; // Optional
+ colorBlending.blendConstants[2] = 0.0f; // Optional
+ colorBlending.blendConstants[3] = 0.0f; // Optional
+
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.setLayoutCount = 0; // Optional
+ pipelineLayoutInfo.pSetLayouts = nullptr; // Optional
+ pipelineLayoutInfo.pushConstantRangeCount = 0; // Optional
+ pipelineLayoutInfo.pPushConstantRanges = nullptr; // Optional
+
+ if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
+ throw std::runtime_error("failed to create pipeline layout!");
+ }
+
+ // 12 Graphics Pipeline -> Conclusion
+ VkGraphicsPipelineCreateInfo pipelineInfo{};
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+ pipelineInfo.pInputAssemblyState = &inputAssembly;
+ pipelineInfo.pViewportState = &viewportState;
+ pipelineInfo.pRasterizationState = &rasterizer;
+ pipelineInfo.pMultisampleState = &multisampling;
+ pipelineInfo.pDepthStencilState = nullptr; // Optional
+ pipelineInfo.pColorBlendState = &colorBlending;
+ pipelineInfo.pDynamicState = &dynamicState;
+ pipelineInfo.layout = pipelineLayout;
+ pipelineInfo.renderPass = renderPass;
+ pipelineInfo.subpass = 0;
+ pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional
+ pipelineInfo.basePipelineIndex = -1; // Optional
+
+ if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
+ throw std::runtime_error("failed to create graphics pipeline!");
+ }
+ //
+
+ vkDestroyShaderModule(device, fragShaderModule, nullptr);
+ vkDestroyShaderModule(device, vertShaderModule, nullptr);
+ }
+ VkShaderModule createShaderModule(const std::vector<char>& code) {
+ VkShaderModuleCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ createInfo.codeSize = code.size();
+ createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
+ VkShaderModule shaderModule;
+ if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
+ throw std::runtime_error("failed to create shader module!");
+ }
+ return shaderModule;
}
-
+
void createImageViews() {
swapChainImageViews.resize(swapChainImages.size());
for (size_t i = 0; i < swapChainImages.size(); i++) {
@@ -308,10 +657,64 @@ private:
void mainLoop() {
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
+ drawFrame(); // 14 Drawing -> Rendering
}
}
+ void drawFrame() {
+
+ vkWaitForFences(device, 1, &inFlightFence, VK_TRUE, UINT64_MAX);
+ vkResetFences(device, 1, &inFlightFence);
+ uint32_t imageIndex;
+ vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
+ vkResetCommandBuffer(commandBuffer, 0);
+ recordCommandBuffer(commandBuffer, imageIndex);
+
+ VkSubmitInfo submitInfo{};
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+
+ VkSemaphore waitSemaphores[] = {imageAvailableSemaphore};
+ VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
+ submitInfo.waitSemaphoreCount = 1;
+ submitInfo.pWaitSemaphores = waitSemaphores;
+ submitInfo.pWaitDstStageMask = waitStages;
+
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &commandBuffer;
+
+ VkSemaphore signalSemaphores[] = {renderFinishedSemaphore};
+ submitInfo.signalSemaphoreCount = 1;
+ submitInfo.pSignalSemaphores = signalSemaphores;
+
+ if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFence) != VK_SUCCESS) {
+ throw std::runtime_error("failed to submit draw command buffer!");
+ }
+
+ VkPresentInfoKHR presentInfo{};
+ presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ presentInfo.waitSemaphoreCount = 1;
+ presentInfo.pWaitSemaphores = signalSemaphores;
+
+ VkSwapchainKHR swapChains[] = {swapChain};
+ presentInfo.swapchainCount = 1;
+ presentInfo.pSwapchains = swapChains;
+ presentInfo.pImageIndices = &imageIndex;
+ presentInfo.pResults = nullptr; // Optional
+
+ vkQueuePresentKHR(presentQueue, &presentInfo);
+ }
+
void cleanup() {
+ vkDestroySemaphore(device, imageAvailableSemaphore, nullptr);
+ vkDestroySemaphore(device, renderFinishedSemaphore, nullptr);
+ vkDestroyFence(device, inFlightFence, nullptr);
+ vkDestroyCommandPool(device, commandPool, nullptr);
+ for (auto framebuffer : swapChainFramebuffers) {
+ vkDestroyFramebuffer(device, framebuffer, nullptr);
+ }
+ vkDestroyPipeline(device, graphicsPipeline, nullptr);
+ vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
+ vkDestroyRenderPass(device, renderPass, nullptr);
for (auto imageView : swapChainImageViews) {
vkDestroyImageView(device, imageView, nullptr);
}