@@ -148,8 +148,8 @@ as texels and we'll use that name from this point on. Add the following two
148148variables in the ` createTextureImage ` function:
149149
150150``` c++
151- VDeleter< VkImage> stagingImage{device, vkDestroyImage} ;
152- VDeleter< VkDeviceMemory > stagingImageMemory{device, vkFreeMemory} ;
151+ VkImage stagingImage;
152+ VkDeviceMemory stagingImageMemory;
153153```
154154
155155The parameters for an image are specified in a ` VkImageCreateInfo ` struct:
@@ -244,7 +244,7 @@ avoid allocating memory to store large volumes of "air" values. We won't be
244244using it in this tutorial, so leave it to its default value of ` 0 ` .
245245
246246``` c++
247- if (vkCreateImage(device, &imageInfo, nullptr , stagingImage.replace() ) != VK_SUCCESS) {
247+ if (vkCreateImage(device, &imageInfo, nullptr , & stagingImage) != VK_SUCCESS) {
248248 throw std::runtime_error("failed to create image!");
249249}
250250```
@@ -266,7 +266,7 @@ allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
266266allocInfo.allocationSize = memRequirements.size;
267267allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
268268
269- if (vkAllocateMemory(device, &allocInfo, nullptr, stagingImageMemory.replace() ) != VK_SUCCESS) {
269+ if (vkAllocateMemory(device, &allocInfo, nullptr, & stagingImageMemory) != VK_SUCCESS) {
270270 throw std::runtime_error("failed to allocate image memory!");
271271}
272272
@@ -378,7 +378,7 @@ for buffers. Create the function and move the image object creation and memory
378378allocation to it:
379379
380380``` c++
381- void createImage (uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VDeleter< VkImage > & image, VDeleter< VkDeviceMemory > & imageMemory) {
381+ void createImage (uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) {
382382 VkImageCreateInfo imageInfo = {};
383383 imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
384384 imageInfo.imageType = VK_IMAGE_TYPE_2D;
@@ -394,7 +394,7 @@ void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling
394394 imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
395395 imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
396396
397- if (vkCreateImage(device, &imageInfo, nullptr, image.replace() ) != VK_SUCCESS) {
397+ if (vkCreateImage(device, &imageInfo, nullptr, & image) != VK_SUCCESS) {
398398 throw std::runtime_error("failed to create image!");
399399 }
400400
@@ -406,7 +406,7 @@ void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling
406406 allocInfo.allocationSize = memRequirements.size;
407407 allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
408408
409- if (vkAllocateMemory(device, &allocInfo, nullptr, imageMemory.replace() ) != VK_SUCCESS) {
409+ if (vkAllocateMemory(device, &allocInfo, nullptr, & imageMemory) != VK_SUCCESS) {
410410 throw std::runtime_error("failed to allocate image memory!");
411411 }
412412
@@ -430,8 +430,8 @@ void createTextureImage() {
430430 throw std::runtime_error("failed to load texture image!");
431431 }
432432
433- VDeleter< VkImage> stagingImage{device, vkDestroyImage} ;
434- VDeleter< VkDeviceMemory> stagingImageMemory{device, vkFreeMemory} ;
433+ VkImage stagingImage;
434+ VkDeviceMemory stagingImageMemory;
435435 createImage(texWidth, texHeight, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingImage, stagingImageMemory);
436436
437437 VkImageSubresource subresource = {};
@@ -465,10 +465,10 @@ The next step is to create the actual texture image. Define two new class
465465members to hold the handle to the image and its memory:
466466
467467``` c++
468- VDeleter< VkCommandPool> commandPool{device, vkDestroyCommandPool} ;
469- VDeleter< VkImage > textureImage{device, vkDestroyImage} ;
470- VDeleter< VkDeviceMemory > textureImageMemory{device, vkFreeMemory} ;
471- VDeleter< VkBuffer > vertexBuffer{device, vkDestroyBuffer} ;
468+ VkCommandPool commandPool;
469+ VkImage textureImage;
470+ VkDeviceMemory textureImageMemory;
471+ VkBuffer vertexBuffer;
472472```
473473
474474The final texture image can now be created using the same function:
@@ -787,6 +787,32 @@ it's also possible to use a buffer and copy pixels from it using
787787performance on [ some hardware] ( https://developer.nvidia.com/vulkan-memory-management )
788788if you need to update the data in an image often.
789789
790+ ## Cleanup
791+
792+ Finish the ` createTextureImage ` function by cleaning up the staging image and
793+ its memory at the end:
794+
795+ ``` c++
796+ transitionImageLayout (textureImage, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
797+
798+ vkDestroyImage(device, stagingImage, nullptr);
799+ vkFreeMemory(device, stagingImageMemory, nullptr);
800+ }
801+ ```
802+
803+ The main texture image is used until the end of the program:
804+
805+ ```c++
806+ void cleanup() {
807+ cleanupSwapChain();
808+
809+ vkDestroyImage(device, textureImage, nullptr);
810+ vkFreeMemory(device, textureImageMemory, nullptr);
811+
812+ ...
813+ }
814+ ```
815+
790816The image now contains the texture, but we still need a way to access it from
791817the graphics pipeline. We'll work on that in the next chapter.
792818
0 commit comments