20 FramebufferVK::FramebufferVK(
RenderPass* renderPass, VkImageView imageView) {
21 VkDevice device = VulkanContext::getCurrent()->getDevice()->getHandle();
22 SwapchainData swapchainData = VulkanContext::getCurrent()->getSwapchain()->getSwapchainData();
25 createDepthStencilBuffer();
26 vector<VkImageView> attachments = {imageView, depthStencil.imageView};
29 VkFramebufferCreateInfo createInfo = {};
30 createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
31 createInfo.renderPass = renderPass->
getHandle();
32 createInfo.attachmentCount = attachments.size();
33 createInfo.pAttachments = attachments.data();
34 createInfo.width = swapchainData.
extent.width;
35 createInfo.height = swapchainData.
extent.height;
36 createInfo.layers = 1;
39 if (vkCreateFramebuffer(device, &createInfo,
nullptr, &handle) != VK_SUCCESS) {
40 throw runtime_error(
"Could not create a framebuffer!");
44 FramebufferVK::~FramebufferVK(
void) {
45 VkDevice device = VulkanContext::getCurrent()->getDevice()->getHandle();
48 vkDestroyFramebuffer(device, handle,
nullptr);
51 VkFramebuffer FramebufferVK::getHandle() {
59 void FramebufferVK::createDepthStencilBuffer() {
60 VkPhysicalDevice physicalDevice = VulkanContext::getCurrent()->getPhysicalDevice()->getHandle();
61 VkDevice device = VulkanContext::getCurrent()->getDevice()->getHandle();
62 VkCommandPool commandPool = VulkanContext::getCurrent()->getCommandPool()->getHandle();
63 VkQueue queue = VulkanContext::getCurrent()->getDevice()->getQueues().graphics;
64 SwapchainData swapchainData = VulkanContext::getCurrent()->getSwapchain()->getSwapchainData();
67 depthStencil.format = VK_FORMAT_UNDEFINED;
68 VkImageTiling tiling = VK_IMAGE_TILING_MAX_ENUM;
69 vector<VkFormat> candidates = {VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT};
72 for (uint32_t i = 0; i < candidates.size(); i++) {
73 depthStencil.format = candidates[i];
76 VkFormatProperties formatProperties;
77 vkGetPhysicalDeviceFormatProperties(physicalDevice, depthStencil.format, &formatProperties);
80 if (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
81 tiling = VK_IMAGE_TILING_OPTIMAL;
83 }
else if (formatProperties.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
84 tiling = VK_IMAGE_TILING_LINEAR;
88 if (depthStencil.format == VK_FORMAT_UNDEFINED || tiling == VK_IMAGE_TILING_MAX_ENUM) {
89 throw runtime_error(
"Could not find a supported depth stencil format!");
93 VkImageCreateInfo createInfo = {};
94 createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
95 createInfo.imageType = VK_IMAGE_TYPE_2D;
96 createInfo.format = depthStencil.format;
97 createInfo.extent = {swapchainData.
extent.width, swapchainData.
extent.height, 1};
98 createInfo.mipLevels = 1;
99 createInfo.arrayLayers = 1;
100 createInfo.samples = VK_SAMPLE_COUNT_1_BIT;
101 createInfo.tiling = tiling;
102 createInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
103 createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
104 createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
107 if (vkCreateImage(device, &createInfo,
nullptr, &depthStencil.image) != VK_SUCCESS) {
108 throw runtime_error(
"Could not create a depth stencil image!");
112 VkMemoryRequirements memoryRequirements;
113 vkGetImageMemoryRequirements(device, depthStencil.image, &memoryRequirements);
116 VkPhysicalDeviceMemoryProperties memoryProperties;
117 vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
120 uint32_t memoryTypeIndex = -1;
121 VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
122 for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
123 if ((memoryRequirements.memoryTypeBits & (1 << i)) &&
124 (memoryProperties.memoryTypes[i].propertyFlags & flags) == flags) {
131 VkMemoryAllocateInfo allocateInfo = {};
132 allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
133 allocateInfo.allocationSize = memoryRequirements.size;
134 allocateInfo.memoryTypeIndex = memoryTypeIndex;
137 if (vkAllocateMemory(device, &allocateInfo,
nullptr, &depthStencil.memory) != VK_SUCCESS) {
138 throw runtime_error(
"Could not allocate depth stencil image memory!");
142 vkBindImageMemory(device, depthStencil.image, depthStencil.memory, 0);
145 VkImageViewCreateInfo viewInfo = {};
146 viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
147 viewInfo.image = depthStencil.image;
148 viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
149 viewInfo.format = depthStencil.format;
150 viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
151 viewInfo.subresourceRange.baseMipLevel = 0;
152 viewInfo.subresourceRange.levelCount = 1;
153 viewInfo.subresourceRange.baseArrayLayer = 0;
154 viewInfo.subresourceRange.layerCount = 1;
157 if (vkCreateImageView(device, &viewInfo,
nullptr, &depthStencil.imageView) != VK_SUCCESS) {
158 throw runtime_error(
"Could not create a depth stencil image view!");
162 VkCommandBufferAllocateInfo cmdAllocateInfo = {};
163 cmdAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
164 cmdAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
165 cmdAllocateInfo.commandPool = commandPool;
166 cmdAllocateInfo.commandBufferCount = 1;
169 VkCommandBuffer commandBuffer;
170 vkAllocateCommandBuffers(device, &cmdAllocateInfo, &commandBuffer);
173 VkCommandBufferBeginInfo beginInfo = {};
174 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
175 beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
178 vkBeginCommandBuffer(commandBuffer, &beginInfo);
181 VkImageMemoryBarrier barrier = {};
182 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
183 barrier.srcAccessMask = 0;
184 barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
185 barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
186 barrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
187 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
188 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
189 barrier.image = depthStencil.image;
190 barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
191 barrier.subresourceRange.baseMipLevel = 0;
192 barrier.subresourceRange.levelCount = 1;
193 barrier.subresourceRange.baseArrayLayer = 0;
194 barrier.subresourceRange.layerCount = 1;
197 vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0, 0,
nullptr, 0,
nullptr, 1, &barrier);
200 vkEndCommandBuffer(commandBuffer);
203 VkSubmitInfo submitInfo = {};
204 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
205 submitInfo.commandBufferCount = 1;
206 submitInfo.pCommandBuffers = &commandBuffer;
209 vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
210 vkQueueWaitIdle(queue);
213 vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
VkRenderPass getHandle()
Returns the handle of the render pass.
This struct stores the data of a depth stencil buffer.
Generic namespace for the SimpleGL framework.
VkExtent2D extent
The swapchain extent.
This struct stores relevant swapchain data.
This class wraps a Vulkan render pass.