1 // Copyright (C) 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <string>
16
17 #include "GfxstreamEnd2EndTestUtils.h"
18 #include "GfxstreamEnd2EndTests.h"
19 #include "gfxstream/RutabagaLayerTestUtils.h"
20
21 namespace gfxstream {
22 namespace tests {
23 namespace {
24
25 using testing::Eq;
26 using testing::Ge;
27 using testing::IsEmpty;
28 using testing::IsNull;
29 using testing::Not;
30 using testing::NotNull;
31
32 class GfxstreamEnd2EndVkSnapshotImageTest : public GfxstreamEnd2EndTest {};
33
TEST_P(GfxstreamEnd2EndVkSnapshotImageTest,PreserveImageHandle)34 TEST_P(GfxstreamEnd2EndVkSnapshotImageTest, PreserveImageHandle) {
35 auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
36 VK_ASSERT(SetUpTypicalVkTestEnvironment());
37
38 const uint32_t width = 32;
39 const uint32_t height = 32;
40
41 const vkhpp::ImageCreateInfo imageCreateInfo = {
42 .pNext = nullptr,
43 .imageType = vkhpp::ImageType::e2D,
44 .extent.width = width,
45 .extent.height = height,
46 .extent.depth = 1,
47 .mipLevels = 1,
48 .arrayLayers = 1,
49 .format = vkhpp::Format::eR8G8B8A8Unorm,
50 .tiling = vkhpp::ImageTiling::eOptimal,
51 .initialLayout = vkhpp::ImageLayout::eUndefined,
52 .usage = vkhpp::ImageUsageFlagBits::eSampled | vkhpp::ImageUsageFlagBits::eTransferDst |
53 vkhpp::ImageUsageFlagBits::eTransferSrc,
54 .sharingMode = vkhpp::SharingMode::eExclusive,
55 .samples = vkhpp::SampleCountFlagBits::e1,
56 };
57 auto image = device->createImageUnique(imageCreateInfo).value;
58
59 vkhpp::MemoryRequirements imageMemoryRequirements{};
60 device->getImageMemoryRequirements(*image, &imageMemoryRequirements);
61
62 const uint32_t imageMemoryIndex = utils::getMemoryType(
63 physicalDevice, imageMemoryRequirements, vkhpp::MemoryPropertyFlagBits::eDeviceLocal);
64 ASSERT_THAT(imageMemoryIndex, Not(Eq(-1)));
65
66 const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
67 .allocationSize = imageMemoryRequirements.size,
68 .memoryTypeIndex = imageMemoryIndex,
69 };
70
71 auto imageMemory = device->allocateMemoryUnique(imageMemoryAllocateInfo).value;
72 ASSERT_THAT(imageMemory, IsValidHandle());
73
74 SnapshotSaveAndLoad();
75
76 ASSERT_THAT(device->bindImageMemory(*image, *imageMemory, 0), IsVkSuccess());
77 }
78
79 // b/346415931
80 // We used to have an issue that the handles mismatch when running more device
81 // create calls. The first device always work but the second might break.
TEST_P(GfxstreamEnd2EndVkSnapshotImageTest,MultipleDevicesPreserveHandles)82 TEST_P(GfxstreamEnd2EndVkSnapshotImageTest, MultipleDevicesPreserveHandles) {
83 auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
84 VK_ASSERT(SetUpTypicalVkTestEnvironment());
85
86 uint32_t graphicsQueueFamilyIndex = -1;
87 {
88 const auto props = physicalDevice.getQueueFamilyProperties();
89 for (uint32_t i = 0; i < props.size(); i++) {
90 const auto& prop = props[i];
91 if (prop.queueFlags & vkhpp::QueueFlagBits::eGraphics) {
92 graphicsQueueFamilyIndex = i;
93 break;
94 }
95 }
96 }
97 ASSERT_THAT(graphicsQueueFamilyIndex, Not(Eq(-1)));
98 const float queuePriority = 1.0f;
99 const vkhpp::DeviceQueueCreateInfo deviceQueueCreateInfo = {
100 .queueFamilyIndex = graphicsQueueFamilyIndex,
101 .queueCount = 1,
102 .pQueuePriorities = &queuePriority,
103 };
104 std::vector<const char*> deviceExtensions = {
105 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME,
106 VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
107 };
108 const vkhpp::DeviceCreateInfo deviceCreateInfo = {
109 .pNext = nullptr,
110 .pQueueCreateInfos = &deviceQueueCreateInfo,
111 .queueCreateInfoCount = 1,
112 .enabledLayerCount = 0,
113 .ppEnabledLayerNames = nullptr,
114 .enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size()),
115 .ppEnabledExtensionNames = deviceExtensions.data(),
116 };
117 auto device2 = physicalDevice.createDeviceUnique(deviceCreateInfo).value;
118 ASSERT_THAT(device2, IsValidHandle());
119
120 const uint32_t width = 32;
121 const uint32_t height = 32;
122
123 const vkhpp::ImageCreateInfo imageCreateInfo = {
124 .pNext = nullptr,
125 .imageType = vkhpp::ImageType::e2D,
126 .extent.width = width,
127 .extent.height = height,
128 .extent.depth = 1,
129 .mipLevels = 1,
130 .arrayLayers = 1,
131 .format = vkhpp::Format::eR8G8B8A8Unorm,
132 .tiling = vkhpp::ImageTiling::eOptimal,
133 .initialLayout = vkhpp::ImageLayout::eUndefined,
134 .usage = vkhpp::ImageUsageFlagBits::eSampled | vkhpp::ImageUsageFlagBits::eTransferDst |
135 vkhpp::ImageUsageFlagBits::eTransferSrc,
136 .sharingMode = vkhpp::SharingMode::eExclusive,
137 .samples = vkhpp::SampleCountFlagBits::e1,
138 };
139 auto image = device->createImageUnique(imageCreateInfo).value;
140
141 vkhpp::MemoryRequirements imageMemoryRequirements{};
142 device->getImageMemoryRequirements(*image, &imageMemoryRequirements);
143
144 const uint32_t imageMemoryIndex = utils::getMemoryType(
145 physicalDevice, imageMemoryRequirements, vkhpp::MemoryPropertyFlagBits::eDeviceLocal);
146 ASSERT_THAT(imageMemoryIndex, Not(Eq(-1)));
147
148 const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
149 .allocationSize = imageMemoryRequirements.size,
150 .memoryTypeIndex = imageMemoryIndex,
151 };
152
153 auto imageMemory = device->allocateMemoryUnique(imageMemoryAllocateInfo).value;
154 ASSERT_THAT(imageMemory, IsValidHandle());
155
156 ASSERT_THAT(device->bindImageMemory(*image, *imageMemory, 0), IsVkSuccess());
157
158 // No device lost on snapshot load.
159 SnapshotSaveAndLoad();
160 }
161
TEST_P(GfxstreamEnd2EndVkSnapshotImageTest,ImageViewDependency)162 TEST_P(GfxstreamEnd2EndVkSnapshotImageTest, ImageViewDependency) {
163 auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
164 VK_ASSERT(SetUpTypicalVkTestEnvironment());
165
166 const uint32_t width = 32;
167 const uint32_t height = 32;
168
169 const vkhpp::ImageCreateInfo imageCreateInfo = {
170 .pNext = nullptr,
171 .imageType = vkhpp::ImageType::e2D,
172 .extent.width = width,
173 .extent.height = height,
174 .extent.depth = 1,
175 .mipLevels = 1,
176 .arrayLayers = 1,
177 .format = vkhpp::Format::eR8G8B8A8Unorm,
178 .tiling = vkhpp::ImageTiling::eOptimal,
179 .initialLayout = vkhpp::ImageLayout::eUndefined,
180 .usage = vkhpp::ImageUsageFlagBits::eSampled | vkhpp::ImageUsageFlagBits::eTransferDst |
181 vkhpp::ImageUsageFlagBits::eTransferSrc,
182 .sharingMode = vkhpp::SharingMode::eExclusive,
183 .samples = vkhpp::SampleCountFlagBits::e1,
184 };
185 auto image = device->createImageUnique(imageCreateInfo).value;
186 ASSERT_THAT(image, IsValidHandle());
187
188 vkhpp::MemoryRequirements imageMemoryRequirements{};
189 device->getImageMemoryRequirements(*image, &imageMemoryRequirements);
190
191 const uint32_t imageMemoryIndex = utils::getMemoryType(
192 physicalDevice, imageMemoryRequirements, vkhpp::MemoryPropertyFlagBits::eDeviceLocal);
193 ASSERT_THAT(imageMemoryIndex, Not(Eq(-1)));
194
195 const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
196 .allocationSize = imageMemoryRequirements.size,
197 .memoryTypeIndex = imageMemoryIndex,
198 };
199
200 auto imageMemory = device->allocateMemoryUnique(imageMemoryAllocateInfo).value;
201 ASSERT_THAT(imageMemory, IsValidHandle());
202
203 ASSERT_THAT(device->bindImageMemory(*image, *imageMemory, 0), IsVkSuccess());
204
205 // b/331677615
206 // Create and delete a buffer handle right before creating image view.
207 // Gfxstream recycle handles. We trick the VkImageView handle to collide with
208 // a destroyed buffer handle and verify there is no bug snapshotting recycled
209 // handles.
210 const vkhpp::BufferCreateInfo bufferCreateInfo = {
211 .size = 1024,
212 .usage = vkhpp::BufferUsageFlagBits::eTransferSrc,
213 };
214 auto buffer = device->createBufferUnique(bufferCreateInfo).value;
215 ASSERT_THAT(buffer, IsValidHandle());
216 buffer.reset();
217
218 const vkhpp::ImageViewCreateInfo imageViewCreateInfo = {
219 .image = *image,
220 .viewType = vkhpp::ImageViewType::e2D,
221 .format = vkhpp::Format::eR8G8B8A8Unorm,
222 .subresourceRange =
223 {
224 .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
225 .baseMipLevel = 0,
226 .levelCount = 1,
227 .baseArrayLayer = 0,
228 .layerCount = 1,
229 },
230 };
231 auto imageView = device->createImageViewUnique(imageViewCreateInfo).value;
232 ASSERT_THAT(imageView, IsValidHandle());
233 // Make sure it doesn't crash on load
234 SnapshotSaveAndLoad();
235 }
236
TEST_P(GfxstreamEnd2EndVkSnapshotImageTest,MultiSampleImage)237 TEST_P(GfxstreamEnd2EndVkSnapshotImageTest, MultiSampleImage) {
238 auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
239 VK_ASSERT(SetUpTypicalVkTestEnvironment());
240
241 const uint32_t width = 32;
242 const uint32_t height = 32;
243
244 const vkhpp::ImageCreateInfo imageCreateInfo = {
245 .pNext = nullptr,
246 .imageType = vkhpp::ImageType::e2D,
247 .extent.width = width,
248 .extent.height = height,
249 .extent.depth = 1,
250 .mipLevels = 1,
251 .arrayLayers = 1,
252 .format = vkhpp::Format::eR8G8B8A8Unorm,
253 .tiling = vkhpp::ImageTiling::eOptimal,
254 .initialLayout = vkhpp::ImageLayout::eUndefined,
255 .usage = vkhpp::ImageUsageFlagBits::eColorAttachment |
256 vkhpp::ImageUsageFlagBits::eTransferDst | vkhpp::ImageUsageFlagBits::eTransferSrc,
257 .sharingMode = vkhpp::SharingMode::eExclusive,
258 .samples = vkhpp::SampleCountFlagBits::e8,
259 };
260 auto image = device->createImageUnique(imageCreateInfo).value;
261 ASSERT_THAT(image, IsValidHandle());
262
263 vkhpp::MemoryRequirements imageMemoryRequirements{};
264 device->getImageMemoryRequirements(*image, &imageMemoryRequirements);
265
266 const uint32_t imageMemoryIndex = utils::getMemoryType(
267 physicalDevice, imageMemoryRequirements, vkhpp::MemoryPropertyFlagBits::eDeviceLocal);
268 ASSERT_THAT(imageMemoryIndex, Not(Eq(-1)));
269
270 const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
271 .allocationSize = imageMemoryRequirements.size,
272 .memoryTypeIndex = imageMemoryIndex,
273 };
274
275 auto imageMemory = device->allocateMemoryUnique(imageMemoryAllocateInfo).value;
276 ASSERT_THAT(imageMemory, IsValidHandle());
277
278 // Make sure it doesn't crash on load
279 SnapshotSaveAndLoad();
280 }
281
TEST_P(GfxstreamEnd2EndVkSnapshotImageTest,ImageViewDependencyWithDedicatedMemory)282 TEST_P(GfxstreamEnd2EndVkSnapshotImageTest, ImageViewDependencyWithDedicatedMemory) {
283 auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
284 VK_ASSERT(SetUpTypicalVkTestEnvironment());
285
286 const uint32_t width = 32;
287 const uint32_t height = 32;
288
289 const vkhpp::ImageCreateInfo imageCreateInfo = {
290 .pNext = nullptr,
291 .imageType = vkhpp::ImageType::e2D,
292 .extent.width = width,
293 .extent.height = height,
294 .extent.depth = 1,
295 .mipLevels = 1,
296 .arrayLayers = 1,
297 .format = vkhpp::Format::eR8G8B8A8Unorm,
298 .tiling = vkhpp::ImageTiling::eOptimal,
299 .initialLayout = vkhpp::ImageLayout::eUndefined,
300 .usage = vkhpp::ImageUsageFlagBits::eSampled | vkhpp::ImageUsageFlagBits::eTransferDst |
301 vkhpp::ImageUsageFlagBits::eTransferSrc,
302 .sharingMode = vkhpp::SharingMode::eExclusive,
303 .samples = vkhpp::SampleCountFlagBits::e1,
304 };
305 auto image = device->createImageUnique(imageCreateInfo).value;
306 ASSERT_THAT(image, IsValidHandle());
307
308 vkhpp::MemoryRequirements imageMemoryRequirements{};
309 device->getImageMemoryRequirements(*image, &imageMemoryRequirements);
310
311 const uint32_t imageMemoryIndex = utils::getMemoryType(
312 physicalDevice, imageMemoryRequirements, vkhpp::MemoryPropertyFlagBits::eDeviceLocal);
313 ASSERT_THAT(imageMemoryIndex, Not(Eq(-1)));
314
315 const vkhpp::MemoryDedicatedAllocateInfo dedicatedAllocateInfo = {
316 .image = *image,
317 };
318
319 const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
320 .pNext = &dedicatedAllocateInfo,
321 .allocationSize = imageMemoryRequirements.size,
322 .memoryTypeIndex = imageMemoryIndex,
323 };
324
325 auto imageMemory = device->allocateMemoryUnique(imageMemoryAllocateInfo).value;
326 ASSERT_THAT(imageMemory, IsValidHandle());
327
328 ASSERT_THAT(device->bindImageMemory(*image, *imageMemory, 0), IsVkSuccess());
329
330 const vkhpp::ImageViewCreateInfo imageViewCreateInfo = {
331 .image = *image,
332 .viewType = vkhpp::ImageViewType::e2D,
333 .format = vkhpp::Format::eR8G8B8A8Unorm,
334 .subresourceRange =
335 {
336 .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
337 .baseMipLevel = 0,
338 .levelCount = 1,
339 .baseArrayLayer = 0,
340 .layerCount = 1,
341 },
342 };
343 auto imageView = device->createImageViewUnique(imageViewCreateInfo).value;
344 ASSERT_THAT(imageView, IsValidHandle());
345 // Make sure it doesn't crash on load
346 SnapshotSaveAndLoad();
347 }
348
TEST_P(GfxstreamEnd2EndVkSnapshotImageTest,ImageContent)349 TEST_P(GfxstreamEnd2EndVkSnapshotImageTest, ImageContent) {
350 static constexpr int kWidth = 256;
351 static constexpr int kHeight = 256;
352 static constexpr vkhpp::DeviceSize kSize = 4 * kWidth * kHeight;
353
354 std::vector<uint8_t> srcBufferContent(kSize);
355 for (size_t i = 0; i < kSize; i++) {
356 srcBufferContent[i] = static_cast<uint8_t>(i & 0xff);
357 }
358 TypicalVkTestEnvironment testEnvironment = VK_ASSERT(SetUpTypicalVkTestEnvironment());
359 auto& instance = testEnvironment.instance;
360 auto& physicalDevice = testEnvironment.physicalDevice;
361 auto& device = testEnvironment.device;
362 auto& queue = testEnvironment.queue;
363 auto queueFamilyIndex = testEnvironment.queueFamilyIndex;
364
365 // Staging buffer
366 const vkhpp::BufferCreateInfo bufferCreateInfo = {
367 .size = static_cast<VkDeviceSize>(kSize),
368 .usage = vkhpp::BufferUsageFlagBits::eTransferSrc,
369 .sharingMode = vkhpp::SharingMode::eExclusive,
370 };
371 auto stagingBuffer = device->createBufferUnique(bufferCreateInfo).value;
372 ASSERT_THAT(stagingBuffer, IsValidHandle());
373
374 vkhpp::MemoryRequirements stagingBufferMemoryRequirements{};
375 device->getBufferMemoryRequirements(*stagingBuffer, &stagingBufferMemoryRequirements);
376
377 const auto stagingBufferMemoryType = utils::getMemoryType(
378 physicalDevice, stagingBufferMemoryRequirements,
379 vkhpp::MemoryPropertyFlagBits::eHostVisible | vkhpp::MemoryPropertyFlagBits::eHostCoherent);
380
381 // Staging memory
382 const vkhpp::MemoryAllocateInfo stagingBufferMemoryAllocateInfo = {
383 .allocationSize = stagingBufferMemoryRequirements.size,
384 .memoryTypeIndex = stagingBufferMemoryType,
385 };
386 auto stagingBufferMemory = device->allocateMemoryUnique(stagingBufferMemoryAllocateInfo).value;
387 ASSERT_THAT(stagingBufferMemory, IsValidHandle());
388 ASSERT_THAT(device->bindBufferMemory(*stagingBuffer, *stagingBufferMemory, 0), IsVkSuccess());
389
390 // Fill memory content
391 void* mapped = nullptr;
392 auto mapResult =
393 device->mapMemory(*stagingBufferMemory, 0, VK_WHOLE_SIZE, vkhpp::MemoryMapFlags{}, &mapped);
394 ASSERT_THAT(mapResult, IsVkSuccess());
395 ASSERT_THAT(mapped, NotNull());
396
397 auto* bytes = reinterpret_cast<uint8_t*>(mapped);
398 std::memcpy(bytes, srcBufferContent.data(), kSize);
399
400 const vkhpp::MappedMemoryRange range = {
401 .memory = *stagingBufferMemory,
402 .offset = 0,
403 .size = kSize,
404 };
405 device->unmapMemory(*stagingBufferMemory);
406
407 // Image
408 const vkhpp::ImageCreateInfo imageCreateInfo = {
409 .pNext = nullptr,
410 .imageType = vkhpp::ImageType::e2D,
411 .extent.width = kWidth,
412 .extent.height = kHeight,
413 .extent.depth = 1,
414 .mipLevels = 1,
415 .arrayLayers = 1,
416 .format = vkhpp::Format::eR8G8B8A8Unorm,
417 .tiling = vkhpp::ImageTiling::eOptimal,
418 .initialLayout = vkhpp::ImageLayout::ePreinitialized,
419 .usage = vkhpp::ImageUsageFlagBits::eTransferDst | vkhpp::ImageUsageFlagBits::eTransferSrc,
420 .sharingMode = vkhpp::SharingMode::eExclusive,
421 .samples = vkhpp::SampleCountFlagBits::e1,
422 };
423 auto image = device->createImageUnique(imageCreateInfo).value;
424 ASSERT_THAT(image, IsValidHandle());
425
426 vkhpp::MemoryRequirements imageMemoryRequirements{};
427 device->getImageMemoryRequirements(*image, &imageMemoryRequirements);
428
429 const uint32_t imageMemoryIndex = utils::getMemoryType(
430 physicalDevice, imageMemoryRequirements, vkhpp::MemoryPropertyFlagBits::eDeviceLocal);
431 ASSERT_THAT(imageMemoryIndex, Not(Eq(-1)));
432
433 const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
434 .allocationSize = imageMemoryRequirements.size,
435 .memoryTypeIndex = imageMemoryIndex,
436 };
437
438 auto imageMemory = device->allocateMemoryUnique(imageMemoryAllocateInfo).value;
439 ASSERT_THAT(imageMemory, IsValidHandle());
440
441 ASSERT_THAT(device->bindImageMemory(*image, *imageMemory, 0), IsVkSuccess());
442
443 // Command buffer
444 const vkhpp::CommandPoolCreateInfo commandPoolCreateInfo = {
445 .queueFamilyIndex = queueFamilyIndex,
446 };
447
448 auto commandPool = device->createCommandPoolUnique(commandPoolCreateInfo).value;
449 ASSERT_THAT(commandPool, IsValidHandle());
450
451 const vkhpp::CommandBufferAllocateInfo commandBufferAllocateInfo = {
452 .level = vkhpp::CommandBufferLevel::ePrimary,
453 .commandPool = *commandPool,
454 .commandBufferCount = 1,
455 };
456 auto commandBuffers = device->allocateCommandBuffersUnique(commandBufferAllocateInfo).value;
457 ASSERT_THAT(commandBuffers, Not(IsEmpty()));
458 auto commandBuffer = std::move(commandBuffers[0]);
459 ASSERT_THAT(commandBuffer, IsValidHandle());
460
461 const vkhpp::CommandBufferBeginInfo commandBufferBeginInfo = {
462 .flags = vkhpp::CommandBufferUsageFlagBits::eOneTimeSubmit,
463 };
464 commandBuffer->begin(commandBufferBeginInfo);
465
466 const vkhpp::ImageMemoryBarrier barrier{
467 .oldLayout = vkhpp::ImageLayout::eUndefined,
468 .newLayout = vkhpp::ImageLayout::eTransferDstOptimal,
469 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
470 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
471 .image = *image,
472 .subresourceRange =
473 {
474 .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
475 .levelCount = 1,
476 .layerCount = 1,
477 },
478 };
479
480 commandBuffer->pipelineBarrier(vkhpp::PipelineStageFlagBits::eAllCommands,
481 vkhpp::PipelineStageFlagBits::eAllCommands,
482 vkhpp::DependencyFlags(), nullptr, nullptr, barrier);
483
484 const vkhpp::BufferImageCopy bufferImageCopy = {
485 .imageSubresource =
486 {
487 .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
488 .layerCount = 1,
489 },
490 .imageExtent =
491 {
492 .width = kWidth,
493 .height = kHeight,
494 .depth = 1,
495 },
496 };
497 commandBuffer->copyBufferToImage(*stagingBuffer, *image,
498 vkhpp::ImageLayout::eTransferDstOptimal, 1, &bufferImageCopy);
499
500 commandBuffer->end();
501
502 auto transferFence = device->createFenceUnique(vkhpp::FenceCreateInfo()).value;
503 ASSERT_THAT(transferFence, IsValidHandle());
504
505 // Execute the command to copy image
506 const vkhpp::SubmitInfo submitInfo = {
507 .commandBufferCount = 1,
508 .pCommandBuffers = &commandBuffer.get(),
509 };
510 queue.submit(submitInfo, *transferFence);
511
512 auto waitResult = device->waitForFences(*transferFence, VK_TRUE, 3000000000L);
513 ASSERT_THAT(waitResult, IsVkSuccess());
514
515 // Snapshot
516 SnapshotSaveAndLoad();
517
518 std::vector<uint8_t> dst(kSize);
519 utils::readImageData(*image, kWidth, kHeight, vkhpp::ImageLayout::eTransferDstOptimal,
520 dst.data(), kSize, testEnvironment);
521
522 for (uint32_t i = 0; i < kSize; ++i) {
523 ASSERT_THAT(dst[i], Eq(srcBufferContent[i]));
524 }
525 }
526
527 INSTANTIATE_TEST_CASE_P(GfxstreamEnd2EndTests, GfxstreamEnd2EndVkSnapshotImageTest,
528 ::testing::ValuesIn({
529 TestParams{
530 .with_gl = false,
531 .with_vk = true,
532 .with_features = {"VulkanSnapshots"},
533 },
534 }),
535 &GetTestName);
536
537 } // namespace
538 } // namespace tests
539 } // namespace gfxstream