Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ad06d6e

Browse files
committed
Update the multisampling chapter to only create one color and depth buffer
1 parent 24d6a2e commit ad06d6e

2 files changed

Lines changed: 53 additions & 73 deletions

File tree

10_Multisampling.md

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -50,29 +50,31 @@ We will now use this function to set the `msaaSamples` variable during the physi
5050

5151
```c++
5252
void pickPhysicalDevice() {
53-
...
54-
if (isDeviceSuitable(device)) {
55-
physicalDevice = device;
56-
msaaSamples = getMaxUsableSampleCount();
57-
break;
58-
}
59-
...
53+
...
54+
for (const auto& device : devices) {
55+
if (isDeviceSuitable(device)) {
56+
physicalDevice = device;
57+
msaaSamples = getMaxUsableSampleCount();
58+
break;
59+
}
60+
}
61+
...
6062
}
6163
```
6264

63-
## Setting up render targets
65+
## Setting up a render target
6466

65-
In MSAA, each pixel is sampled in an offscreen buffer which is then rendered to the screen. These new buffers are slightly different from regular images we've been rendering to - they have to be able to store more than one sample per pixel. Once a multisampled buffer is created, it has to be attached to the default framebuffer (which stores only a single sample per pixel). This is why we have to create additional render targets and modify our current drawing process. Add the following class members:
67+
In MSAA, each pixel is sampled in an offscreen buffer which is then rendered to the screen. This new buffer is slightly different from regular images we've been rendering to - they have to be able to store more than one sample per pixel. Once a multisampled buffer is created, it has to be resolved to the default framebuffer (which stores only a single sample per pixel). This is why we have to create an additional render target and modify our current drawing process. We only need one render target since only one drawing operation is active at a time, just like with the depth buffer. Add the following class members:
6668

6769
```c++
6870
...
69-
std::vector<VkImage> colorImages;
70-
std::vector<VkDeviceMemory> colorImagesMemory;
71-
std::vector<VkImageView> colorImagesView;
71+
VkImage colorImage;
72+
VkDeviceMemory colorImageMemory;
73+
VkImageView colorImageView;
7274
...
7375
```
7476

75-
These new images will have to store the desired number of samples per pixel, so we need to pass this number to `VkImageCreateInfo` during image creation process. Modify the `createImage` function by adding a `numSamples` parameter:
77+
This new image will have to store the desired number of samples per pixel, so we need to pass this number to `VkImageCreateInfo` during the image creation process. Modify the `createImage` function by adding a `numSamples` parameter:
7678

7779
```c++
7880
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) {
@@ -84,27 +86,21 @@ void createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkSampleCo
8486
For now, update all calls to this function using `VK_SAMPLE_COUNT_1_BIT` - we will be replacing this with proper values as we progress with implementation:
8587
8688
```c++
87-
createImage(swapChainExtent.width, swapChainExtent.height, 1, VK_SAMPLE_COUNT_1_BIT, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImages[i], depthImagesMemory[i]);
89+
createImage(swapChainExtent.width, swapChainExtent.height, 1, VK_SAMPLE_COUNT_1_BIT, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);
8890
...
8991
createImage(texWidth, texHeight, mipLevels, VK_SAMPLE_COUNT_1_BIT, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, textureImage, textureImageMemory);
9092
```
9193

92-
We will now create a multisampled color buffer. Same as in case of non-multisampled image, we'll be dealing with dedicated resources for each swapchain image. Add a `createColorResources` function and note that we're using `msaaSamples` here as a function parameter to `createImage`. We're also using only one mip level, since this is enforced by the Vulkan specification in case of images with more than one sample per pixel. Also, this color buffer doesn't need mipmaps since it's not going to be used as a texture:
94+
We will now create a multisampled color buffer. Add a `createColorResources` function and note that we're using `msaaSamples` here as a function parameter to `createImage`. We're also using only one mip level, since this is enforced by the Vulkan specification in case of images with more than one sample per pixel. Also, this color buffer doesn't need mipmaps since it's not going to be used as a texture:
9395

9496
```c++
9597
void createColorResources() {
9698
VkFormat colorFormat = swapChainImageFormat;
9799

98-
colorImages.resize(swapChainImages.size());
99-
colorImagesMemory.resize(swapChainImages.size());
100-
colorImageViews.resize(swapChainImages.size());
100+
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);
101+
colorImageView = createImageView(colorImage, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
101102

102-
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
103-
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, colorImages[i], colorImagesMemory[i]);
104-
colorImageViews[i] = createImageView(colorImages[i], colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
105-
106-
transitionImageLayout(colorImages[i], colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1);
107-
}
103+
transitionImageLayout(colorImage, colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1);
108104
}
109105
```
110106

@@ -141,27 +137,24 @@ Now that we have a multisampled color buffer in place it's time to take care of
141137
142138
```c++
143139
void createDepthResources() {
144-
...
145-
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, depthImages[i], depthImagesMemory[i]);
146-
...
140+
...
141+
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);
142+
...
147143
}
148144
```
149145

150146
We have now created a couple of new Vulkan resources, so let's not forget to release them when necessary:
151147

152148
```c++
153149
void cleanupSwapChain() {
154-
for (size_t i = 0; i < swapChainImages.size(); i++) {
155-
vkDestroyImageView(device, colorImageViews[i], nullptr);
156-
vkDestroyImage(device, colorImages[i], nullptr);
157-
vkFreeMemory(device, colorImagesMemory[i], nullptr);
158-
...
159-
}
150+
vkDestroyImageView(device, colorImageView, nullptr);
151+
vkDestroyImage(device, colorImage, nullptr);
152+
vkFreeMemory(device, colorImageMemory, nullptr);
160153
...
161154
}
162155
```
163156

164-
And update the `recreateSwapChain` so that the new color images can be recreated in the correct resolution when the window is resized:
157+
And update the `recreateSwapChain` so that the new color image can be recreated in the correct resolution when the window is resized:
165158

166159
```c++
167160
void recreateSwapChain() {
@@ -173,7 +166,7 @@ void recreateSwapChain() {
173166
}
174167
```
175168

176-
We made it past the initial MSAA setup, now we need to start using these new resources in our graphics pipeline, framebuffer, render pass and see the results!
169+
We made it past the initial MSAA setup, now we need to start using this new resource in our graphics pipeline, framebuffer, render pass and see the results!
177170

178171
## Adding new attachments
179172

@@ -223,22 +216,22 @@ Set the `pResolveAttachments` subpass struct member to point to the newly create
223216
...
224217
```
225218

226-
Now update render pass info struct with new color attachment:
219+
Now update render pass info struct with the new color attachment:
227220

228221
```c++
229222
...
230223
std::array<VkAttachmentDescription, 3> attachments = {colorAttachment, depthAttachment, colorAttachmentResolve};
231224
...
232225
```
233226
234-
With render pass in place, modify `createFrameBuffers` and add new image view to the list:
227+
With the render pass in place, modify `createFrameBuffers` and add the new image view to the list:
235228
236229
```c++
237230
void createFrameBuffers() {
238231
...
239232
std::array<VkImageView, 3> attachments = {
240-
colorImageViews[i],
241-
depthImagesView[i],
233+
colorImageView,
234+
depthImageView,
242235
swapChainImageViews[i]
243236
};
244237
...

code/29_multisampling.cpp

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,13 @@ class HelloTriangleApplication {
170170

171171
VkCommandPool commandPool;
172172

173-
std::vector<VkImage> colorImages;
174-
std::vector<VkDeviceMemory> colorImagesMemory;
175-
std::vector<VkImageView> colorImageViews;
173+
VkImage colorImage;
174+
VkDeviceMemory colorImageMemory;
175+
VkImageView colorImageView;
176176

177-
std::vector<VkImage> depthImages;
178-
std::vector<VkDeviceMemory> depthImagesMemory;
179-
std::vector<VkImageView> depthImagesView;
177+
VkImage depthImage;
178+
VkDeviceMemory depthImageMemory;
179+
VkImageView depthImageView;
180180

181181
uint32_t mipLevels;
182182
VkImage textureImage;
@@ -259,14 +259,13 @@ class HelloTriangleApplication {
259259
}
260260

261261
void cleanupSwapChain() {
262-
for (size_t i = 0; i < swapChainImages.size(); i++) {
263-
vkDestroyImageView(device, colorImageViews[i], nullptr);
264-
vkDestroyImage(device, colorImages[i], nullptr);
265-
vkFreeMemory(device, colorImagesMemory[i], nullptr);
266-
vkDestroyImageView(device, depthImagesView[i], nullptr);
267-
vkDestroyImage(device, depthImages[i], nullptr);
268-
vkFreeMemory(device, depthImagesMemory[i], nullptr);
269-
}
262+
vkDestroyImageView(device, depthImageView, nullptr);
263+
vkDestroyImage(device, depthImage, nullptr);
264+
vkFreeMemory(device, depthImageMemory, nullptr);
265+
266+
vkDestroyImageView(device, colorImageView, nullptr);
267+
vkDestroyImage(device, colorImage, nullptr);
268+
vkFreeMemory(device, colorImageMemory, nullptr);
270269

271270
for (auto framebuffer : swapChainFramebuffers) {
272271
vkDestroyFramebuffer(device, framebuffer, nullptr);
@@ -764,8 +763,8 @@ class HelloTriangleApplication {
764763

765764
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
766765
std::array<VkImageView, 3> attachments = {
767-
colorImageViews[i],
768-
depthImagesView[i],
766+
colorImageView,
767+
depthImageView,
769768
swapChainImageViews[i]
770769
};
771770

@@ -799,31 +798,19 @@ class HelloTriangleApplication {
799798
void createColorResources() {
800799
VkFormat colorFormat = swapChainImageFormat;
801800

802-
colorImages.resize(swapChainImages.size());
803-
colorImagesMemory.resize(swapChainImages.size());
804-
colorImageViews.resize(swapChainImages.size());
805-
806-
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
807-
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, colorImages[i], colorImagesMemory[i]);
808-
colorImageViews[i] = createImageView(colorImages[i], colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
801+
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);
802+
colorImageView = createImageView(colorImage, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
809803

810-
transitionImageLayout(colorImages[i], colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1);
811-
}
804+
transitionImageLayout(colorImage, colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1);
812805
}
813806

814807
void createDepthResources() {
815808
VkFormat depthFormat = findDepthFormat();
816809

817-
depthImages.resize(swapChainImages.size());
818-
depthImagesMemory.resize(swapChainImages.size());
819-
depthImagesView.resize(swapChainImages.size());
820-
821-
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
822-
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, depthImages[i], depthImagesMemory[i]);
823-
depthImagesView[i] = createImageView(depthImages[i], depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1);
810+
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);
811+
depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1);
824812

825-
transitionImageLayout(depthImages[i], depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1);
826-
}
813+
transitionImageLayout(depthImage, depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1);
827814
}
828815

829816
VkFormat findSupportedFormat(const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) {

0 commit comments

Comments
 (0)