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

Skip to content

Commit 3272ef7

Browse files
committed
Fix all frames in flight using a single depth buffer
1 parent 5730f69 commit 3272ef7

5 files changed

Lines changed: 85 additions & 76 deletions

File tree

07_Depth_buffering.md

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,12 @@ range of `0.0` to `1.0` using the `GLM_FORCE_DEPTH_ZERO_TO_ONE` definition.
125125

126126
A depth attachment is based on an image, just like the color attachment. The
127127
difference is that the swap chain will not automatically create depth images for
128-
us. We only need a single depth image, because only one draw operation is
129-
running at once. The depth image will again require the trifecta of resources:
130-
image, memory and image view.
128+
us. We need a depth image for every frame that can be in flight simultaneously. In practice it's easiest to juse have one per swap chain image similar to the uniform buffers. The depth images will again require the trifecta of resources: image, memory and image view.
131129

132130
```c++
133-
VkImage depthImage;
134-
VkDeviceMemory depthImageMemory;
135-
VkImageView depthImageView;
131+
std::vector<VkImage> depthImages;
132+
std::vector<VkDeviceMemory> depthImagesMemory;
133+
std::vector<VkImageView> depthImagesView;
136134
```
137135

138136
Create a new function `createDepthResources` to set up these resources:
@@ -264,15 +262,27 @@ bool hasStencilComponent(VkFormat format) {
264262
Call the function to find a depth format from `createDepthResources`:
265263
266264
```c++
267-
VkFormat depthFormat = findDepthFormat();
265+
void createDepthResources() {
266+
VkFormat depthFormat = findDepthFormat();
267+
}
268268
```
269269

270270
We now have all the required information to invoke our `createImage` and
271271
`createImageView` helper functions:
272272

273273
```c++
274-
createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);
275-
depthImageView = createImageView(depthImage, depthFormat);
274+
void createDepthResources() {
275+
VkFormat depthFormat = findDepthFormat();
276+
277+
depthImages.resize(swapChainImages.size());
278+
depthImagesMemory.resize(swapChainImages.size());
279+
depthImagesView.resize(swapChainImages.size());
280+
281+
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
282+
createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImages[i], depthImagesMemory[i]);
283+
depthImagesView[i] = createImageView(depthImages[i], depthFormat);
284+
}
285+
}
276286
```
277287

278288
However, the `createImageView` function currently assumes that the subresource
@@ -292,7 +302,7 @@ Update all calls to this function to use the right aspect:
292302
```c++
293303
swapChainImageViews[i] = createImageView(swapChainImages[i], swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT);
294304
...
295-
depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
305+
depthImagesView[i] = createImageView(depthImages[i], depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
296306
...
297307
textureImageView = createImageView(textureImage, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
298308
```
@@ -305,7 +315,7 @@ render pass like the color attachment, but here I've chosen to use a pipeline
305315
barrier because the transition only needs to happen once:
306316

307317
```c++
308-
transitionImageLayout(depthImage, depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
318+
transitionImageLayout(depthImages[i], depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
309319
```
310320
311321
The undefined layout can be used as initial layout, because there are no
@@ -421,13 +431,12 @@ attachments.
421431
## Framebuffer
422432
423433
The next step is to modify the framebuffer creation to bind the depth image to
424-
the depth attachment. Go to `createFramebuffers` and specify the depth image
425-
view as second attachment:
434+
the depth attachment. Go to `createFramebuffers` and specify the right depth image view as second attachment:
426435
427436
```c++
428437
std::array<VkImageView, 2> attachments = {
429438
swapChainImageViews[i],
430-
depthImageView
439+
depthImagesView[i]
431440
};
432441
433442
VkFramebufferCreateInfo framebufferInfo = {};
@@ -440,10 +449,6 @@ framebufferInfo.height = swapChainExtent.height;
440449
framebufferInfo.layers = 1;
441450
```
442451

443-
The color attachment differs for every swap chain image, but the same depth
444-
image can be used by all of them because only a single subpass is running at the
445-
same time due to our semaphores.
446-
447452
You'll also need to move the call to `createFramebuffers` to make sure that it
448453
is called after the depth image view has actually been created:
449454

@@ -565,9 +570,11 @@ The cleanup operations should happen in the swap chain cleanup function:
565570

566571
```c++
567572
void cleanupSwapChain() {
568-
vkDestroyImageView(device, depthImageView, nullptr);
569-
vkDestroyImage(device, depthImage, nullptr);
570-
vkFreeMemory(device, depthImageMemory, nullptr);
573+
for (size_t i = 0; i < swapChainImages.size(); i++) {
574+
vkDestroyImageView(device, depthImagesView[i], nullptr);
575+
vkDestroyImage(device, depthImages[i], nullptr);
576+
vkFreeMemory(device, depthImagesMemory[i], nullptr);
577+
}
571578

572579
...
573580
}

09_Generating_Mipmaps.md

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,19 @@ void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayo
5555
Update all calls to these functions to use the right values:
5656
5757
```c++
58-
createImage(swapChainExtent.width, swapChainExtent.height, 1, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);
58+
createImage(swapChainExtent.width, swapChainExtent.height, 1, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImages[i], depthImagesMemory[i]);
5959
...
6060
createImage(texWidth, texHeight, mipLevels, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, textureImage, textureImageMemory);
6161
```
6262
```c++
6363
swapChainImageViews[i] = createImageView(swapChainImages[i], swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
6464
...
65-
depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1);
65+
depthImagesView[i] = createImageView(depthImages[i], depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1);
6666
...
6767
textureImageView = createImageView(textureImage, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT, mipLevels);
6868
```
6969
```c++
70-
transitionImageLayout(depthImage, depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1);
70+
transitionImageLayout(depthImages[i], depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1);
7171
...
7272
transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, mipLevels);
7373
```
@@ -346,28 +346,6 @@ These settings will produce this image:
346346

347347
This is how higher mip levels will be used when objects are further away from the camera.
348348

349-
350-
## Conclusion
351-
352-
It has taken a lot of work to get to this point, but now you finally have a good
353-
base for a Vulkan program. The knowledge of the basic principles of Vulkan that
354-
you now possess should be sufficient to start exploring more of the features,
355-
like:
356-
357-
* Push constants
358-
* Instanced rendering
359-
* Dynamic uniforms
360-
* Separate images and sampler descriptors
361-
* Pipeline cache
362-
* Multi-threaded command buffer generation
363-
* Multiple subpasses
364-
* Compute shaders
365-
366-
The current program can be extended in many ways, like adding Blinn-Phong
367-
lighting, post-processing effects and shadow mapping. You should be able to
368-
learn how these effects work from tutorials for other APIs, because despite
369-
Vulkan's explicitness, many concepts still work the same.
370-
371349
[C++ code](/code/28_mipmapping.cpp) /
372350
[Vertex shader](/code/26_shader_depth.vert) /
373351
[Fragment shader](/code/26_shader_depth.frag)

code/26_depth_buffering.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ class HelloTriangleApplication {
165165

166166
VkCommandPool commandPool;
167167

168-
VkImage depthImage;
169-
VkDeviceMemory depthImageMemory;
170-
VkImageView depthImageView;
168+
std::vector<VkImage> depthImages;
169+
std::vector<VkDeviceMemory> depthImagesMemory;
170+
std::vector<VkImageView> depthImagesView;
171171

172172
VkImage textureImage;
173173
VkDeviceMemory textureImageMemory;
@@ -245,9 +245,11 @@ class HelloTriangleApplication {
245245
}
246246

247247
void cleanupSwapChain() {
248-
vkDestroyImageView(device, depthImageView, nullptr);
249-
vkDestroyImage(device, depthImage, nullptr);
250-
vkFreeMemory(device, depthImageMemory, nullptr);
248+
for (size_t i = 0; i < swapChainImages.size(); i++) {
249+
vkDestroyImageView(device, depthImagesView[i], nullptr);
250+
vkDestroyImage(device, depthImages[i], nullptr);
251+
vkFreeMemory(device, depthImagesMemory[i], nullptr);
252+
}
251253

252254
for (auto framebuffer : swapChainFramebuffers) {
253255
vkDestroyFramebuffer(device, framebuffer, nullptr);
@@ -728,7 +730,7 @@ class HelloTriangleApplication {
728730
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
729731
std::array<VkImageView, 2> attachments = {
730732
swapChainImageViews[i],
731-
depthImageView
733+
depthImagesView[i]
732734
};
733735

734736
VkFramebufferCreateInfo framebufferInfo = {};
@@ -761,10 +763,16 @@ class HelloTriangleApplication {
761763
void createDepthResources() {
762764
VkFormat depthFormat = findDepthFormat();
763765

764-
createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);
765-
depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
766+
depthImages.resize(swapChainImages.size());
767+
depthImagesMemory.resize(swapChainImages.size());
768+
depthImagesView.resize(swapChainImages.size());
766769

767-
transitionImageLayout(depthImage, depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
770+
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
771+
createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImages[i], depthImagesMemory[i]);
772+
depthImagesView[i] = createImageView(depthImages[i], depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
773+
774+
transitionImageLayout(depthImages[i], depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
775+
}
768776
}
769777

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

code/27_model_loading.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ class HelloTriangleApplication {
169169

170170
VkCommandPool commandPool;
171171

172-
VkImage depthImage;
173-
VkDeviceMemory depthImageMemory;
174-
VkImageView depthImageView;
172+
std::vector<VkImage> depthImages;
173+
std::vector<VkDeviceMemory> depthImagesMemory;
174+
std::vector<VkImageView> depthImagesView;
175175

176176
VkImage textureImage;
177177
VkDeviceMemory textureImageMemory;
@@ -252,9 +252,11 @@ class HelloTriangleApplication {
252252
}
253253

254254
void cleanupSwapChain() {
255-
vkDestroyImageView(device, depthImageView, nullptr);
256-
vkDestroyImage(device, depthImage, nullptr);
257-
vkFreeMemory(device, depthImageMemory, nullptr);
255+
for (size_t i = 0; i < swapChainImages.size(); i++) {
256+
vkDestroyImageView(device, depthImagesView[i], nullptr);
257+
vkDestroyImage(device, depthImages[i], nullptr);
258+
vkFreeMemory(device, depthImagesMemory[i], nullptr);
259+
}
258260

259261
for (auto framebuffer : swapChainFramebuffers) {
260262
vkDestroyFramebuffer(device, framebuffer, nullptr);
@@ -735,7 +737,7 @@ class HelloTriangleApplication {
735737
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
736738
std::array<VkImageView, 2> attachments = {
737739
swapChainImageViews[i],
738-
depthImageView
740+
depthImagesView[i]
739741
};
740742

741743
VkFramebufferCreateInfo framebufferInfo = {};
@@ -768,10 +770,16 @@ class HelloTriangleApplication {
768770
void createDepthResources() {
769771
VkFormat depthFormat = findDepthFormat();
770772

771-
createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);
772-
depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
773+
depthImages.resize(swapChainImages.size());
774+
depthImagesMemory.resize(swapChainImages.size());
775+
depthImagesView.resize(swapChainImages.size());
773776

774-
transitionImageLayout(depthImage, depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
777+
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
778+
createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImages[i], depthImagesMemory[i]);
779+
depthImagesView[i] = createImageView(depthImages[i], depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
780+
781+
transitionImageLayout(depthImages[i], depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
782+
}
775783
}
776784

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

code/28_mipmapping.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ class HelloTriangleApplication {
169169

170170
VkCommandPool commandPool;
171171

172-
VkImage depthImage;
173-
VkDeviceMemory depthImageMemory;
174-
VkImageView depthImageView;
172+
std::vector<VkImage> depthImages;
173+
std::vector<VkDeviceMemory> depthImagesMemory;
174+
std::vector<VkImageView> depthImagesView;
175175

176176
uint32_t mipLevels;
177177
VkImage textureImage;
@@ -253,9 +253,11 @@ class HelloTriangleApplication {
253253
}
254254

255255
void cleanupSwapChain() {
256-
vkDestroyImageView(device, depthImageView, nullptr);
257-
vkDestroyImage(device, depthImage, nullptr);
258-
vkFreeMemory(device, depthImageMemory, nullptr);
256+
for (size_t i = 0; i < swapChainImages.size(); i++) {
257+
vkDestroyImageView(device, depthImagesView[i], nullptr);
258+
vkDestroyImage(device, depthImages[i], nullptr);
259+
vkFreeMemory(device, depthImagesMemory[i], nullptr);
260+
}
259261

260262
for (auto framebuffer : swapChainFramebuffers) {
261263
vkDestroyFramebuffer(device, framebuffer, nullptr);
@@ -736,7 +738,7 @@ class HelloTriangleApplication {
736738
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
737739
std::array<VkImageView, 2> attachments = {
738740
swapChainImageViews[i],
739-
depthImageView
741+
depthImagesView[i]
740742
};
741743

742744
VkFramebufferCreateInfo framebufferInfo = {};
@@ -769,10 +771,16 @@ class HelloTriangleApplication {
769771
void createDepthResources() {
770772
VkFormat depthFormat = findDepthFormat();
771773

772-
createImage(swapChainExtent.width, swapChainExtent.height, 1, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);
773-
depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1);
774+
depthImages.resize(swapChainImages.size());
775+
depthImagesMemory.resize(swapChainImages.size());
776+
depthImagesView.resize(swapChainImages.size());
774777

775-
transitionImageLayout(depthImage, depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1);
778+
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
779+
createImage(swapChainExtent.width, swapChainExtent.height, 1, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImages[i], depthImagesMemory[i]);
780+
depthImagesView[i] = createImageView(depthImages[i], depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1);
781+
782+
transitionImageLayout(depthImages[i], depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1);
783+
}
776784
}
777785

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

0 commit comments

Comments
 (0)