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

Skip to content

Commit 17c559c

Browse files
committed
Remove VDeleter from presentation chapters
1 parent 9cf2a2c commit 17c559c

9 files changed

Lines changed: 135 additions & 258 deletions

File tree

03_Drawing_a_triangle/01_Presentation/00_Window_surface.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@ allows you to do that without hacks like creating an invisible window
2323
## Window surface creation
2424

2525
Start by adding a `surface` class member right below the debug callback.
26-
Surfaces are destroyed using the `vkDestroySurfaceKHR` call.
2726

2827
```c++
29-
VDeleter<VkSurfaceKHR> surface{instance, vkDestroySurfaceKHR};
28+
VkSurfaceKHR surface;
3029
```
3130

3231
Although the `VkSurfaceKHR` object and its usage is platform agnostic, its
@@ -101,15 +100,27 @@ implementation of the function very straightforward:
101100

102101
```c++
103102
void createSurface() {
104-
if (glfwCreateWindowSurface(instance, window, nullptr, surface.replace()) != VK_SUCCESS) {
103+
if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) {
105104
throw std::runtime_error("failed to create window surface!");
106105
}
107106
}
108107
```
109108

110109
The parameters are the `VkInstance`, GLFW window pointer, custom allocators and
111110
pointer to `VkSurfaceKHR` variable. It simply passes through the `VkResult` from
112-
the relevant platform call.
111+
the relevant platform call. GLFW doesn't offer a special function for destroying
112+
a surface, but that can easily be done through the original API:
113+
114+
```c++
115+
void cleanup() {
116+
...
117+
vkDestroySurfaceKHR(instance, surface, nullptr);
118+
vkDestroyInstance(instance, nullptr);
119+
...
120+
}
121+
```
122+
123+
Make sure that the surface is destroyed before the instance.
113124
114125
## Querying for presentation support
115126
@@ -200,8 +211,8 @@ for (int queueFamily : uniqueQueueFamilies) {
200211
And modify `VkDeviceCreateInfo` to point to the vector:
201212

202213
```c++
214+
createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
203215
createInfo.pQueueCreateInfos = queueCreateInfos.data();
204-
createInfo.queueCreateInfoCount = (uint32_t) queueCreateInfos.size();
205216
```
206217

207218
If the queue families are the same, then we only need to pass its index once.

03_Drawing_a_triangle/01_Presentation/01_Swap_chain.md

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ Enabling the extension just requires a small change to the logical device
8585
creation structure:
8686

8787
```c++
88-
createInfo.enabledExtensionCount = deviceExtensions.size();
88+
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
8989
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
9090
```
9191

@@ -531,26 +531,32 @@ be specified in this field. This is a complex topic that we'll learn more about
531531
in [a future chapter](!Drawing_a_triangle/Swap_chain_recreation). For now we'll
532532
assume that we'll only ever create one swap chain.
533533

534-
Now add a class member to store the `VkSwapchainKHR` object with a proper
535-
deleter. Make sure to add it after `device` so that it gets cleaned up before
536-
the logical device is.
534+
Now add a class member to store the `VkSwapchainKHR` object:
537535

538536
```c++
539-
VDeleter<VkSwapchainKHR> swapChain{device, vkDestroySwapchainKHR};
537+
VkSwapchainKHR swapChain;
540538
```
541539

542-
Now creating the swap chain is as simple as calling `vkCreateSwapchainKHR`:
540+
Creating the swap chain is now as simple as calling `vkCreateSwapchainKHR`:
543541

544542
```c++
545-
if (vkCreateSwapchainKHR(device, &createInfo, nullptr, swapChain.replace()) != VK_SUCCESS) {
543+
if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) {
546544
throw std::runtime_error("failed to create swap chain!");
547545
}
548546
```
549547

550548
The parameters are the logical device, swap chain creation info, optional custom
551549
allocators and a pointer to the variable to store the handle in. No surprises
552-
there. Now run the application to ensure that the swap chain is created
553-
successfully!
550+
there. It should be cleaned up using `vkDestroySwapchainKHR` before the device:
551+
552+
```c++
553+
void cleanup() {
554+
vkDestroySwapchainKHR(device, swapChain, nullptr);
555+
...
556+
}
557+
```
558+
559+
Now run the application to ensure that the swap chain is created successfully!
554560

555561
Try removing the `createInfo.imageExtent = extent;` line with validation layers
556562
enabled. You'll see that one of the validation layers immediately catches the
@@ -570,7 +576,7 @@ std::vector<VkImage> swapChainImages;
570576

571577
The images were created by the implementation for the swap chain and they will
572578
be automatically cleaned up once the swap chain has been destroyed, therefore we
573-
don't need a deleter here.
579+
don't need to add any cleanup code.
574580

575581
I'm adding the code to retrieve the handles to the end of the `createSwapChain`
576582
function, right after the `vkCreateSwapchainKHR` call. Retrieving them is very
@@ -593,7 +599,7 @@ One last thing, store the format and extent we've chosen for the swap chain
593599
images in member variables. We'll need them in future chapters.
594600
595601
```c++
596-
VDeleter<VkSwapchainKHR> swapChain{device, vkDestroySwapchainKHR};
602+
VkSwapchainKHR swapChain;
597603
std::vector<VkImage> swapChainImages;
598604
VkFormat swapChainImageFormat;
599605
VkExtent2D swapChainExtent;
@@ -605,7 +611,8 @@ swapChainExtent = extent;
605611
```
606612

607613
We now have a set of images that can be drawn onto and can be presented to the
608-
window. The next two chapters will cover how we can set up the images as render
609-
targets and then we start looking into the actual drawing commands!
614+
window. The next chapter will begin to cover how we can set up the images as
615+
render targets and then we start looking into the actual graphics pipeline and
616+
drawing commands!
610617

611618
[C++ code](/code/swap_chain_creation.cpp)

03_Drawing_a_triangle/01_Presentation/02_Image_views.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@ In this chapter we'll write a `createImageViews` function that creates a basic
88
image view for every image in the swap chain so that we can use them as color
99
targets later on.
1010

11-
First add a class member to store the image views in. Unlike the `VkImage`s, the
12-
`VkImageView` objects are created by us so we need to clean them up ourselves
13-
later.
11+
First add a class member to store the image views in:
1412

1513
```c++
16-
std::vector<VDeleter<VkImageView>> swapChainImageViews;
14+
std::vector<VkImageView> swapChainImageViews;
1715
```
1816

1917
Create the `createImageViews` function and call it right after swap chain
@@ -36,21 +34,19 @@ void createImageViews() {
3634
```
3735

3836
The first thing we need to do is resize the list to fit all of the image views
39-
we'll be creating. This is also the place where we'll actually define the
40-
deleter function.
37+
we'll be creating:
4138

4239
```c++
4340
void createImageViews() {
44-
swapChainImageViews.resize(swapChainImages.size(), VDeleter<VkImageView>{device, vkDestroyImageView});
41+
swapChainImageViews.resize(swapChainImages.size());
4542

4643
}
4744
```
4845

49-
The `resize` function initializes all of the list items with the right deleter.
5046
Next, set up the loop that iterates over all of the swap chain images.
5147

5248
```c++
53-
for (uint32_t i = 0; i < swapChainImages.size(); i++) {
49+
for (size_t i = 0; i < swapChainImages.size(); i++) {
5450

5551
}
5652
```
@@ -105,11 +101,24 @@ different layers.
105101
Creating the image view is now a matter of calling `vkCreateImageView`:
106102

107103
```c++
108-
if (vkCreateImageView(device, &createInfo, nullptr, swapChainImageViews[i].replace()) != VK_SUCCESS) {
104+
if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) {
109105
throw std::runtime_error("failed to create image views!");
110106
}
111107
```
112108

109+
Unlike images, the image views were explicitly created by us, so we need to add
110+
a similar loop to destroy them again at the end of the program:
111+
112+
```c++
113+
void cleanup() {
114+
for (size_t i = 0; i < swapChainImageViews.size(); i++) {
115+
vkDestroyImageView(device, swapChainImageViews[i], nullptr);
116+
}
117+
118+
...
119+
}
120+
```
121+
113122
That's it, now run the program to verify that the image views are created
114123
properly and destroyed properly. Checking the latter requires enabling the
115124
validation layers, or putting a print statement in the deleter function.

0 commit comments

Comments
 (0)