@@ -158,34 +158,30 @@ class VulkanExample : public VulkanExampleBase
158
158
ktx_uint8_t *ktxTextureData = ktxTexture_GetData (ktxTexture);
159
159
ktx_size_t ktxTextureSize = ktxTexture_GetSize (ktxTexture);
160
160
161
- VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo ();
162
- VkMemoryRequirements memReqs;
163
-
164
- // Create a host-visible staging buffer that contains the raw image data
165
- VkBuffer stagingBuffer;
166
- VkDeviceMemory stagingMemory;
161
+ vks::Buffer sourceData;
167
162
163
+ // Create a host-visible source buffer that contains the raw image data
168
164
VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo ();
169
165
bufferCreateInfo.size = ktxTextureSize;
170
- // This buffer is used as a transfer source for the buffer copy
171
166
bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
172
167
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
168
+ VK_CHECK_RESULT (vkCreateBuffer (device, &bufferCreateInfo, nullptr , &sourceData.buffer ));
173
169
174
- VK_CHECK_RESULT ( vkCreateBuffer (device, &bufferCreateInfo, nullptr , &stagingBuffer));
175
-
176
- // Get memory requirements for the staging buffer (alignment, memory type bits)
177
- vkGetBufferMemoryRequirements (device, stagingBuffer, &memReqs );
170
+ // Get memory requirements for the source buffer (alignment, memory type bits)
171
+ VkMemoryRequirements memReqs;
172
+ vkGetBufferMemoryRequirements (device, sourceData. buffer , &memReqs);
173
+ VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo ( );
178
174
memAllocInfo.allocationSize = memReqs.size ;
179
175
// Get memory type index for a host visible buffer
180
176
memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType (memReqs.memoryTypeBits , VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
181
- VK_CHECK_RESULT (vkAllocateMemory (device, &memAllocInfo, nullptr , &stagingMemory ));
182
- VK_CHECK_RESULT (vkBindBufferMemory (device, stagingBuffer, stagingMemory , 0 ));
177
+ VK_CHECK_RESULT (vkAllocateMemory (device, &memAllocInfo, nullptr , &sourceData. memory ));
178
+ VK_CHECK_RESULT (vkBindBufferMemory (device, sourceData. buffer , sourceData. memory , 0 ));
183
179
184
- // Copy texture data into staging buffer
180
+ // Copy the ktx image data into the source buffer
185
181
uint8_t *data;
186
- VK_CHECK_RESULT (vkMapMemory (device, stagingMemory , 0 , memReqs.size , 0 , (void **)&data));
182
+ VK_CHECK_RESULT (vkMapMemory (device, sourceData. memory , 0 , memReqs.size , 0 , (void **)&data));
187
183
memcpy (data, ktxTextureData, ktxTextureSize);
188
- vkUnmapMemory (device, stagingMemory );
184
+ vkUnmapMemory (device, sourceData. memory );
189
185
190
186
// Create optimal tiled target image
191
187
VkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo ();
@@ -202,25 +198,17 @@ class VulkanExample : public VulkanExampleBase
202
198
imageCreateInfo.arrayLayers = 6 * cubeMapArray.layerCount ;
203
199
// This flag is required for cube map images
204
200
imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
205
-
206
201
VK_CHECK_RESULT (vkCreateImage (device, &imageCreateInfo, nullptr , &cubeMapArray.image ));
207
202
203
+ // Allocate memory for the cube map array image
208
204
vkGetImageMemoryRequirements (device, cubeMapArray.image , &memReqs);
209
-
210
205
memAllocInfo.allocationSize = memReqs.size ;
211
206
memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType (memReqs.memoryTypeBits , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
212
-
213
207
VK_CHECK_RESULT (vkAllocateMemory (device, &memAllocInfo, nullptr , &cubeMapArray.deviceMemory ));
214
208
VK_CHECK_RESULT (vkBindImageMemory (device, cubeMapArray.image , cubeMapArray.deviceMemory , 0 ));
215
209
216
- VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer (VK_COMMAND_BUFFER_LEVEL_PRIMARY, true );
217
-
218
- // Setup buffer copy regions for each face including all of its miplevels
219
- std::vector<VkBufferImageCopy> bufferCopyRegions;
220
- uint32_t offset = 0 ;
221
-
222
- /*
223
- Setup buffer copy regions to copy the data from the ktx file to our image
210
+ /*
211
+ We now copy the parts that make up the cube map array to our image via a command buffer
224
212
Cube map arrays in ktx are stored with a layout like this:
225
213
- Mip Level 0
226
214
- Layer 0 (= Cube map 0)
@@ -242,6 +230,11 @@ class VulkanExample : public VulkanExampleBase
242
230
...
243
231
*/
244
232
233
+ VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer (VK_COMMAND_BUFFER_LEVEL_PRIMARY, true );
234
+
235
+ // Setup buffer copy regions for each face including all of its miplevels
236
+ std::vector<VkBufferImageCopy> bufferCopyRegions;
237
+ uint32_t offset = 0 ;
245
238
for (uint32_t face = 0 ; face < 6 ; face++) {
246
239
for (uint32_t layer = 0 ; layer < ktxTexture->numLayers ; layer++) {
247
240
for (uint32_t level = 0 ; level < ktxTexture->numLevels ; level++) {
@@ -262,39 +255,28 @@ class VulkanExample : public VulkanExampleBase
262
255
}
263
256
}
264
257
265
- // Image barrier for optimal image (target)
266
- // Set initial layout for all array layers (faces) of the optimal (target) tiled texture
267
258
VkImageSubresourceRange subresourceRange = {};
268
259
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
269
260
subresourceRange.baseMipLevel = 0 ;
270
261
subresourceRange.levelCount = cubeMapArray.mipLevels ;
271
262
subresourceRange.layerCount = 6 * cubeMapArray.layerCount ;
272
263
273
- vks::tools::setImageLayout (
274
- copyCmd,
275
- cubeMapArray.image ,
276
- VK_IMAGE_LAYOUT_UNDEFINED,
277
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
278
- subresourceRange);
264
+ // Transition target image to accept the writes from our buffer to image copies
265
+ vks::tools::setImageLayout (copyCmd, cubeMapArray.image , VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceRange);
279
266
280
- // Copy the cube map faces from the staging buffer to the optimal tiled image
267
+ // Copy the cube map array buffer parts from the staging buffer to the optimal tiled image
281
268
vkCmdCopyBufferToImage (
282
269
copyCmd,
283
- stagingBuffer ,
270
+ sourceData. buffer ,
284
271
cubeMapArray.image ,
285
272
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
286
273
static_cast <uint32_t >(bufferCopyRegions.size ()),
287
274
bufferCopyRegions.data ()
288
275
);
289
276
290
- // Change texture image layout to shader read after all faces have been copied
277
+ // Transition image to shader read layout
291
278
cubeMapArray.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
292
- vks::tools::setImageLayout (
293
- copyCmd,
294
- cubeMapArray.image ,
295
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
296
- cubeMapArray.imageLayout ,
297
- subresourceRange);
279
+ vks::tools::setImageLayout (copyCmd, cubeMapArray.image , VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, cubeMapArray.imageLayout , subresourceRange);
298
280
299
281
vulkanDevice->flushCommandBuffer (copyCmd, queue, true );
300
282
@@ -331,8 +313,8 @@ class VulkanExample : public VulkanExampleBase
331
313
VK_CHECK_RESULT (vkCreateImageView (device, &view, nullptr , &cubeMapArray.view ));
332
314
333
315
// Clean up staging resources
334
- vkFreeMemory (device, stagingMemory , nullptr );
335
- vkDestroyBuffer (device, stagingBuffer , nullptr );
316
+ vkFreeMemory (device, sourceData. memory , nullptr );
317
+ vkDestroyBuffer (device, sourceData. buffer , nullptr );
336
318
ktxTexture_Destroy (ktxTexture);
337
319
}
338
320
0 commit comments