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

Skip to content

Commit 4b532b8

Browse files
committed
Remove VDeleter from uniform buffer chapters
1 parent fa80e74 commit 4b532b8

4 files changed

Lines changed: 325 additions & 330 deletions

File tree

05_Uniform_buffers/00_Descriptor_layout_and_buffer.md

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ All of the descriptor bindings are combined into a single
174174
`pipelineLayout`:
175175

176176
```c++
177-
VDeleter<VkDescriptorSetLayout> descriptorSetLayout{device, vkDestroyDescriptorSetLayout};
178-
VDeleter<VkPipelineLayout> pipelineLayout{device, vkDestroyPipelineLayout};
177+
VkDescriptorSetLayout descriptorSetLayout;
178+
VkPipelineLayout pipelineLayout;
179179
```
180180

181181
We can then create it using `vkCreateDescriptorSetLayout`. This function accepts
@@ -187,7 +187,7 @@ layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
187187
layoutInfo.bindingCount = 1;
188188
layoutInfo.pBindings = &uboLayoutBinding;
189189

190-
if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, descriptorSetLayout.replace()) != VK_SUCCESS) {
190+
if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
191191
throw std::runtime_error("failed to create descriptor set layout!");
192192
}
193193
```
@@ -198,40 +198,50 @@ specified in the pipeline layout object. Modify the `VkPipelineLayoutCreateInfo`
198198
to reference the layout object:
199199

200200
```c++
201-
VkDescriptorSetLayout setLayouts[] = {descriptorSetLayout};
202201
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
203202
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
204203
pipelineLayoutInfo.setLayoutCount = 1;
205-
pipelineLayoutInfo.pSetLayouts = setLayouts;
204+
pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
206205
```
207206

208207
You may be wondering why it's possible to specify multiple descriptor set
209208
layouts here, because a single one already includes all of the bindings. We'll
210209
get back to that in the next chapter, where we'll look into descriptor pools and
211210
descriptor sets.
212211

212+
The descriptor layout should stick around while we may create new graphics
213+
pipelines i.e. until the program ends:
214+
215+
```c++
216+
void cleanup() {
217+
cleanupSwapChain();
218+
219+
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
220+
221+
...
222+
}
223+
```
224+
213225
## Uniform buffer
214226

215227
In the next chapter we'll specify the buffer that contains the UBO data for the
216228
shader, but we need to create this buffer first. We're going to copy new data to
217-
the uniform buffer every frame, so this time the staging buffer actually needs
218-
to stick around.
229+
the uniform buffer every frame, so it doesn't really make any sense to have a
230+
staging buffer. It would just add extra overhead in this case and likely degrade
231+
performance instead of improving it.
219232

220-
Add new class members for `uniformStagingBuffer`, `uniformStagingBufferMemory`,
221-
`uniformBuffer`, and `uniformBufferMemory`:
233+
Add new class members for `uniformBuffer`, and `uniformBufferMemory`:
222234

223235
```c++
224-
VDeleter<VkBuffer> indexBuffer{device, vkDestroyBuffer};
225-
VDeleter<VkDeviceMemory> indexBufferMemory{device, vkFreeMemory};
236+
VkBuffer indexBuffer;
237+
VkDeviceMemory indexBufferMemory;
226238

227-
VDeleter<VkBuffer> uniformStagingBuffer{device, vkDestroyBuffer};
228-
VDeleter<VkDeviceMemory> uniformStagingBufferMemory{device, vkFreeMemory};
229-
VDeleter<VkBuffer> uniformBuffer{device, vkDestroyBuffer};
230-
VDeleter<VkDeviceMemory> uniformBufferMemory{device, vkFreeMemory};
239+
VkBuffer uniformBuffer;
240+
VkDeviceMemory uniformBufferMemory;
231241
```
232242

233243
Similarly, create a new function `createUniformBuffer` that is called after
234-
`createIndexBuffer` and allocates the buffers:
244+
`createIndexBuffer` and allocates the buffer:
235245

236246
```c++
237247
void initVulkan() {
@@ -246,15 +256,31 @@ void initVulkan() {
246256

247257
void createUniformBuffer() {
248258
VkDeviceSize bufferSize = sizeof(UniformBufferObject);
249-
250-
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformStagingBuffer, uniformStagingBufferMemory);
251-
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, uniformBuffer, uniformBufferMemory);
259+
createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffer, uniformBufferMemory);
252260
}
253261
```
254262

255263
We're going to write a separate function that updates the uniform buffer with a
256-
new transformation every frame, so there will be no `vkMapMemory` and
257-
`copyBuffer` operations here.
264+
new transformation every frame, so there will be no `vkMapMemory` here. The
265+
uniform data will be used for all draw calls, so the buffer containing it should
266+
only be destroyed at the end:
267+
268+
```c++
269+
void cleanup() {
270+
cleanupSwapChain();
271+
272+
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
273+
vkDestroyBuffer(device, uniformBuffer, nullptr);
274+
vkFreeMemory(device, uniformBufferMemory, nullptr);
275+
276+
...
277+
}
278+
```
279+
280+
## Updating uniform data
281+
282+
Create a new function `updateUniformBuffer` and add a call to it from the main
283+
loop:
258284

259285
```c++
260286
void mainLoop() {
@@ -266,8 +292,6 @@ void mainLoop() {
266292
}
267293

268294
vkDeviceWaitIdle(device);
269-
270-
glfwDestroyWindow(window);
271295
}
272296

273297
...
@@ -277,10 +301,7 @@ void updateUniformBuffer() {
277301
}
278302
```
279303

280-
## Updating uniform data
281-
282-
Create a new function `updateUniformBuffer` and add a call to it from the main
283-
loop. This function will generate a new transformation every frame to make the
304+
This function will generate a new transformation every frame to make the
284305
geometry spin around. We need to include two new headers to implement this
285306
functionality:
286307

@@ -359,26 +380,23 @@ do this, then the image will be rendered upside down.
359380

360381
All of the transformations are defined now, so we can copy the data in the
361382
uniform buffer object to the uniform buffer. This happens in exactly the same
362-
way as we did for vertex buffers with a staging buffer:
383+
way as we did for vertex buffers, except without a staging buffer:
363384

364385
```c++
365386
void* data;
366-
vkMapMemory(device, uniformStagingBufferMemory, 0, sizeof(ubo), 0, &data);
387+
vkMapMemory(device, uniformBufferMemory, 0, sizeof(ubo), 0, &data);
367388
memcpy(data, &ubo, sizeof(ubo));
368-
vkUnmapMemory(device, uniformStagingBufferMemory);
369-
370-
copyBuffer(uniformStagingBuffer, uniformBuffer, sizeof(ubo));
389+
vkUnmapMemory(device, uniformBufferMemory);
371390
```
372391
373-
Using a staging buffer and final buffer this way is not the most efficient way
374-
to pass frequently changing values to the shader. A more efficient way to pass a
375-
small buffer of data to shaders are *push constants*. We may look at these in a
376-
future chapter.
392+
Using a UBO this way is not the most efficient way to pass frequently changing
393+
values to the shader. A more efficient way to pass a small buffer of data to
394+
shaders are *push constants*. We may look at these in a future chapter.
377395
378396
In the next chapter we'll look at descriptor sets, which will actually bind the
379397
`VkBuffer` to the uniform buffer descriptor so that the shader can access this
380398
transformation data.
381399
382400
[C++ code](/code/descriptor_layout.cpp) /
383401
[Vertex shader](/code/shader_ubo.vert) /
384-
[Fragment shader](/code/shader_ubo.frag)
402+
[Fragment shader](/code/shader_ubo.frag)

05_Uniform_buffers/01_Descriptor_pool_and_sets.md

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,28 @@ the descriptor set after creating it, so we don't need this flag. You can leave
6060
`flags` to its default value of `0`.
6161

6262
```c++
63-
VDeleter<VkDescriptorPool> descriptorPool{device, vkDestroyDescriptorPool};
63+
VkDescriptorPool descriptorPool;
6464

6565
...
6666

67-
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, descriptorPool.replace()) != VK_SUCCESS) {
67+
if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
6868
throw std::runtime_error("failed to create descriptor pool!");
6969
}
7070
```
7171

7272
Add a new class member to store the handle of the descriptor pool and call
73-
`vkCreateDescriptorPool` to create it.
73+
`vkCreateDescriptorPool` to create it. The descriptor pool should be destroyed
74+
only at the end of the program, much like the other drawing related resources:
75+
76+
```c++
77+
void cleanup() {
78+
cleanupSwapChain();
79+
80+
vkDestroyDescriptorPool(device, descriptorPool, nullptr);
81+
82+
...
83+
}
84+
```
7485

7586
## Descriptor set
7687

@@ -109,7 +120,7 @@ Add a class member to hold the descriptor set handle and allocate it with
109120
`vkAllocateDescriptorSets`:
110121
111122
```c++
112-
VDeleter<VkDescriptorPool> descriptorPool{device, vkDestroyDescriptorPool};
123+
VkDescriptorPool descriptorPool;
113124
VkDescriptorSet descriptorSet;
114125
115126
...
@@ -119,7 +130,7 @@ if (vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet) != VK_SUCCESS)
119130
}
120131
```
121132

122-
You don't need to use a deleter for descriptor sets, because they will be
133+
You don't need to explicitly clean up descriptor sets, because they will be
123134
automatically freed when the descriptor pool is destroyed. The call to
124135
`vkAllocateDescriptorSets` will allocate one descriptor set with one uniform
125136
buffer descriptor.
@@ -182,8 +193,8 @@ vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
182193
183194
The updates are applied using `vkUpdateDescriptorSets`. It accepts two kinds of
184195
arrays as parameters: an array of `VkWriteDescriptorSet` and an array of
185-
`VkCopyDescriptorSet`. The latter can be used to copy the configuration of
186-
descriptors, as its name implies.
196+
`VkCopyDescriptorSet`. The latter can be used to copy descriptors to each other,
197+
as its name implies.
187198
188199
## Using a descriptor set
189200

0 commit comments

Comments
 (0)