scop
a small 3D object loader
Loading...
Searching...
No Matches
VulkanRender.cpp
Go to the documentation of this file.
1/* ************************************************************************** */
2/* */
3/* ::: :::::::: */
4/* VulkanRender.cpp :+: :+: :+: */
5/* +:+ +:+ +:+ */
6/* By: rbourgea <rbourgea@student.42.fr> +#+ +:+ +#+ */
7/* +#+#+#+#+#+ +#+ */
8/* Created: 2024/01/11 07:20:04 by rbourgea #+# #+# */
9/* Updated: 2024/04/02 22:13:04 by rbourgea ### ########.fr */
10/* */
11/* ************************************************************************** */
12
13#include "VulkanApp.hpp"
14
17
18 for (size_t i = 0; i < swapChainImageViews.size(); i++) {
19 std::array<VkImageView, 3> attachments = {
23 };
24
25 VkFramebufferCreateInfo framebufferInfo{};
26 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
27 framebufferInfo.renderPass = renderPass;
28 framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
29 framebufferInfo.pAttachments = attachments.data();
30 framebufferInfo.width = swapChainExtent.width;
31 framebufferInfo.height = swapChainExtent.height;
32 framebufferInfo.layers = 1;
33
34 if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) {
35 throw std::runtime_error("Failed to create framebuffer !");
36 }
37 }
38}
39
42
43 VkCommandPoolCreateInfo poolInfo{};
44 poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
45 poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
46 poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();
47
48 if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {
49 throw std::runtime_error("Failed to create command pool !");
50 }
51}
52
55
56 VkCommandBufferAllocateInfo allocInfo{};
57 allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
58 allocInfo.commandPool = commandPool;
59 allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
60 allocInfo.commandBufferCount = (uint32_t) commandBuffers.size();
61
62 if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
63 throw std::runtime_error("Failed to allocate command buffers !");
64 }
65}
66
67void VulkanApp::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
68 VkCommandBufferBeginInfo beginInfo{};
69 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
70
71 if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {
72 throw std::runtime_error("Failed to begin recording command buffer !");
73 }
74
75 VkRenderPassBeginInfo renderPassInfo{};
76 renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
77 renderPassInfo.renderPass = renderPass;
78 renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex];
79 renderPassInfo.renderArea.offset = {0, 0};
80 renderPassInfo.renderArea.extent = swapChainExtent;
81
82 std::array<VkClearValue, 2> clearValues{};
83 clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}};
84 clearValues[1].depthStencil = {1.0f, 0};
85
86 renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
87 renderPassInfo.pClearValues = clearValues.data();
88
89 vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
90
91 vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
92
93 VkViewport viewport{};
94 viewport.x = 0.0f;
95 viewport.y = 0.0f;
96 viewport.width = (float) swapChainExtent.width;
97 viewport.height = (float) swapChainExtent.height;
98 viewport.minDepth = 0.0f;
99 viewport.maxDepth = 1.0f;
100 vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
101
102 VkRect2D scissor{};
103 scissor.offset = {0, 0};
104 scissor.extent = swapChainExtent;
105 vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
106
107 VkBuffer vertexBuffers[] = {vertexBuffer};
108 VkDeviceSize offsets[] = {0};
109 vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
110
111 vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT32);
112
113 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[currentFrame], 0, nullptr);
114
115 vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);
116
117 vkCmdEndRenderPass(commandBuffer);
118
119 if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
120 throw std::runtime_error("Failed to record command buffer !");
121 }
122}
123
128
129 VkSemaphoreCreateInfo semaphoreInfo{};
130 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
131
132 VkFenceCreateInfo fenceInfo{};
133 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
134 fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
135
136 for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
137 if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS ||
138 vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS ||
139 vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) {
140
141 throw std::runtime_error("Failed to create synchronization objects for a frame !");
142 }
143 }
144}
145
147 vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
148
149 uint32_t imageIndex;
150 VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
151
152 if (result == VK_ERROR_OUT_OF_DATE_KHR) {
154 return;
155 } else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
156 throw std::runtime_error("Failed to acquire swap chain image !");
157 }
158
160
161 vkResetFences(device, 1, &inFlightFences[currentFrame]);
162
163 vkResetCommandBuffer(commandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0);
165
166 VkSubmitInfo submitInfo{};
167 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
168
169 VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]};
170 VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
171 submitInfo.waitSemaphoreCount = 1;
172 submitInfo.pWaitSemaphores = waitSemaphores;
173 submitInfo.pWaitDstStageMask = waitStages;
174
175 submitInfo.commandBufferCount = 1;
176 submitInfo.pCommandBuffers = &commandBuffers[currentFrame];
177
178 VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]};
179 submitInfo.signalSemaphoreCount = 1;
180 submitInfo.pSignalSemaphores = signalSemaphores;
181
182 if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) {
183 throw std::runtime_error("Failed to submit draw command buffer !");
184 }
185
186 VkPresentInfoKHR presentInfo{};
187 presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
188
189 presentInfo.waitSemaphoreCount = 1;
190 presentInfo.pWaitSemaphores = signalSemaphores;
191
192 VkSwapchainKHR swapChains[] = {swapChain};
193 presentInfo.swapchainCount = 1;
194 presentInfo.pSwapchains = swapChains;
195
196 presentInfo.pImageIndices = &imageIndex;
197
198 vkQueuePresentKHR(presentQueue, &presentInfo);
199
200 if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) {
201 framebufferResized = false;
203 } else if (result != VK_SUCCESS) {
204 throw std::runtime_error("Failed to present swap chain image !");
205 }
206
208}
209
211 VkCommandBufferAllocateInfo allocInfo{};
212 allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
213 allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
214 allocInfo.commandPool = commandPool;
215 allocInfo.commandBufferCount = 1;
216
217 VkCommandBuffer commandBuffer;
218 vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);
219
220 VkCommandBufferBeginInfo beginInfo{};
221 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
222 beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
223
224 vkBeginCommandBuffer(commandBuffer, &beginInfo);
225
226 return commandBuffer;
227}
228
229void VulkanApp::endSingleTimeCommands(VkCommandBuffer commandBuffer) {
230 vkEndCommandBuffer(commandBuffer);
231
232 VkSubmitInfo submitInfo{};
233 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
234 submitInfo.commandBufferCount = 1;
235 submitInfo.pCommandBuffers = &commandBuffer;
236
237 vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
238 vkQueueWaitIdle(graphicsQueue);
239
240 vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
241}
242
244 VkFormat colorFormat = swapChainImageFormat;
245
246 createImage(swapChainExtent.width, swapChainExtent.height, 1, msaaSamples, colorFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, colorImage, colorImageMemory);
247 colorImageView = createImageView(colorImage, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
248}
249
251 VkFormat depthFormat = findDepthFormat();
252
253 createImage(swapChainExtent.width, swapChainExtent.height, 1, msaaSamples, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);
254 depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1);
255}
const int MAX_FRAMES_IN_FLIGHT
Definition VulkanApp.hpp:45
void createCommandPool()
std::vector< uint32_t > indices
void createDepthResources()
VkSampleCountFlagBits msaaSamples
VkDevice device
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device)
void createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkSampleCountFlagBits numSamples, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage &image, VkDeviceMemory &imageMemory)
VkPhysicalDevice physicalDevice
void createColorResources()
VkQueue presentQueue
void drawFrame()
void recreateSwapChain()
std::vector< VkSemaphore > renderFinishedSemaphores
VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags, uint32_t mipLevels)
VkBuffer indexBuffer
VkRenderPass renderPass
VkQueue graphicsQueue
VkDeviceMemory colorImageMemory
std::vector< VkFence > inFlightFences
std::vector< VkCommandBuffer > commandBuffers
VkPipelineLayout pipelineLayout
std::vector< VkFramebuffer > swapChainFramebuffers
VkExtent2D swapChainExtent
VkPipeline graphicsPipeline
std::vector< VkSemaphore > imageAvailableSemaphores
VkImage colorImage
VkBuffer vertexBuffer
bool framebufferResized
VkCommandBuffer beginSingleTimeCommands()
VkImage depthImage
VkDeviceMemory depthImageMemory
VkFormat findDepthFormat()
void createCommandBuffers()
VkCommandPool commandPool
VkImageView colorImageView
std::vector< VkDescriptorSet > descriptorSets
VkImageView depthImageView
void endSingleTimeCommands(VkCommandBuffer commandBuffer)
void createSyncObjects()
void createFramebuffers()
std::vector< VkImageView > swapChainImageViews
void updateUniformBuffer(uint32_t currentImage)
void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex)
VkSwapchainKHR swapChain
VkFormat swapChainImageFormat
size_t currentFrame
std::optional< uint32_t > graphicsFamily
Definition VulkanApp.hpp:68