SimpleGL  1.1.0
A framework for platform independent rendering
framebuffer.cpp
Go to the documentation of this file.
1 
9 
10 #include <stdexcept>
11 #include <vector>
12 
15 
16 using namespace std;
17 
18 namespace sgl {
19 
20  FramebufferVK::FramebufferVK(RenderPass* renderPass, VkImageView imageView) {
21  VkDevice device = VulkanContext::getCurrent()->getDevice()->getHandle();
22  SwapchainData swapchainData = VulkanContext::getCurrent()->getSwapchain()->getSwapchainData();
23 
24  /* Create depth stencil buffer */
25  createDepthStencilBuffer();
26  vector<VkImageView> attachments = {imageView, depthStencil.imageView};
27 
28  /* Initialize a framebuffer create info */
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;
37 
38  /* Create the framebuffer */
39  if (vkCreateFramebuffer(device, &createInfo, nullptr, &handle) != VK_SUCCESS) {
40  throw runtime_error("Could not create a framebuffer!");
41  }
42  }
43 
44  FramebufferVK::~FramebufferVK(void) {
45  VkDevice device = VulkanContext::getCurrent()->getDevice()->getHandle();
46 
47  /* Destroy the framebuffer */
48  vkDestroyFramebuffer(device, handle, nullptr);
49  }
50 
51  VkFramebuffer FramebufferVK::getHandle() {
52  return handle;
53  }
54 
55  DepthStencilBuffer FramebufferVK::getDepthStencilBuffer() {
56  return depthStencil;
57  }
58 
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();
65 
66  /* Initialize format candidates */
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};
70 
71  /* Find a supported format */
72  for (uint32_t i = 0; i < candidates.size(); i++) {
73  depthStencil.format = candidates[i];
74 
75  /* Get physical device format properties */
76  VkFormatProperties formatProperties;
77  vkGetPhysicalDeviceFormatProperties(physicalDevice, depthStencil.format, &formatProperties);
78 
79  /* Determine image tiling arrangement */
80  if (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
81  tiling = VK_IMAGE_TILING_OPTIMAL;
82  break;
83  } else if (formatProperties.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
84  tiling = VK_IMAGE_TILING_LINEAR;
85  break;
86  }
87  }
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!");
90  }
91 
92  /* Initialize a image create info */
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;
105 
106  /* Create the image */
107  if (vkCreateImage(device, &createInfo, nullptr, &depthStencil.image) != VK_SUCCESS) {
108  throw runtime_error("Could not create a depth stencil image!");
109  }
110 
111  /* Get memory requirements */
112  VkMemoryRequirements memoryRequirements;
113  vkGetImageMemoryRequirements(device, depthStencil.image, &memoryRequirements);
114 
115  /* Get the device memory properties */
116  VkPhysicalDeviceMemoryProperties memoryProperties;
117  vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
118 
119  /* Determine memory type index */
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) {
125  memoryTypeIndex = i;
126  break;
127  }
128  }
129 
130  /* Initialize a memory allocate info */
131  VkMemoryAllocateInfo allocateInfo = {};
132  allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
133  allocateInfo.allocationSize = memoryRequirements.size;
134  allocateInfo.memoryTypeIndex = memoryTypeIndex;
135 
136  /* Allocate the texture image memory */
137  if (vkAllocateMemory(device, &allocateInfo, nullptr, &depthStencil.memory) != VK_SUCCESS) {
138  throw runtime_error("Could not allocate depth stencil image memory!");
139  }
140 
141  /* Bind the texture image memory */
142  vkBindImageMemory(device, depthStencil.image, depthStencil.memory, 0);
143 
144  /* Initialize a image view create info */
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;
155 
156  /* Create the image view */
157  if (vkCreateImageView(device, &viewInfo, nullptr, &depthStencil.imageView) != VK_SUCCESS) {
158  throw runtime_error("Could not create a depth stencil image view!");
159  }
160 
161  /* Initialize a command buffer allocate info */
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;
167 
168  /* Allocate a temporary command buffer */
169  VkCommandBuffer commandBuffer;
170  vkAllocateCommandBuffers(device, &cmdAllocateInfo, &commandBuffer);
171 
172  /* Initialize a command buffer begin info */
173  VkCommandBufferBeginInfo beginInfo = {};
174  beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
175  beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
176 
177  /* Begin recording */
178  vkBeginCommandBuffer(commandBuffer, &beginInfo);
179 
180  /* Initialize a image memory barrier */
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;
195 
196  /* Pipeline barrier */
197  vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
198 
199  /* End recording */
200  vkEndCommandBuffer(commandBuffer);
201 
202  /* Initialize a submit info */
203  VkSubmitInfo submitInfo = {};
204  submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
205  submitInfo.commandBufferCount = 1;
206  submitInfo.pCommandBuffers = &commandBuffer;
207 
208  /* Submit the command */
209  vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
210  vkQueueWaitIdle(queue);
211 
212  /* Free the temporary command buffer */
213  vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
214  }
215 }
VkRenderPass getHandle()
Returns the handle of the render pass.
This struct stores the data of a depth stencil buffer.
Definition: framebuffer.hpp:24
Generic namespace for the SimpleGL framework.
Definition: application.hpp:18
VkExtent2D extent
The swapchain extent.
Definition: swapchain.hpp:40
This struct stores relevant swapchain data.
Definition: swapchain.hpp:28
This class wraps a Vulkan render pass.
Definition: render_pass.hpp:22