1 // Copyright (C) 2018 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 #include "VulkanStream.h"
15
16 #include "IOStream.h"
17
18 #include "common/goldfish_vk_deepcopy.h"
19 #include "common/goldfish_vk_extension_structs.h"
20 #include "common/goldfish_vk_marshaling.h"
21 #include "common/goldfish_vk_reserved_marshaling.h"
22 #include "common/goldfish_vk_testing.h"
23
24 #include "android/base/ArraySize.h"
25 #include "android/base/BumpPool.h"
26
27 #include <gtest/gtest.h>
28 #include <string.h>
29 #include <vulkan.h>
30
31 using android::base::arraySize;
32
33 namespace goldfish_vk {
34
35 class TestStream : public IOStream {
36 public:
37 static constexpr size_t kBufSize = 1024;
TestStream()38 TestStream() : IOStream(kBufSize) { }
39 protected:
40
getDmaForReading(uint64_t guest_paddr)41 void* getDmaForReading(uint64_t guest_paddr) override { return nullptr; }
unlockDma(uint64_t guest_paddr)42 void unlockDma(uint64_t guest_paddr) override { }
43
44 // VulkanStream should never use these functions.
allocBuffer(size_t minSize)45 void* allocBuffer(size_t minSize) override {
46 fprintf(stderr, "%s: FATAL: not intended for use!\n", __func__);
47 abort();
48 }
49
commitBuffer(size_t size)50 int commitBuffer(size_t size) override {
51 fprintf(stderr, "%s: FATAL: not intended for use!\n", __func__);
52 abort();
53 }
54
readRaw(void * buf,size_t * inout_len)55 const unsigned char *readRaw(void *buf, size_t *inout_len) override {
56 fprintf(stderr, "%s: FATAL: not intended for use!\n", __func__);
57 abort();
58 }
59
onSave(android::base::Stream *)60 void onSave(android::base::Stream*) override {
61 fprintf(stderr, "%s: FATAL: not intended for use!\n", __func__);
62 abort();
63
64 }
65
onLoad(android::base::Stream *)66 virtual unsigned char* onLoad(android::base::Stream*) override {
67 fprintf(stderr, "%s: FATAL: not intended for use!\n", __func__);
68 abort();
69 }
70
writeFully(const void * buffer,size_t size)71 int writeFully(const void* buffer, size_t size) override {
72 if (mBuffer.size() < mWriteCursor + size) {
73 mBuffer.resize(mWriteCursor + size);
74 }
75
76 memcpy(mBuffer.data() + mWriteCursor, buffer, size);
77
78 mWriteCursor += size;
79
80 if (mReadCursor == mWriteCursor) {
81 clear();
82 }
83 return 0;
84 }
85
readFully(void * buf,size_t len)86 const unsigned char* readFully(void* buf, size_t len) override {
87 EXPECT_LE(mReadCursor + len, mBuffer.size());
88 memcpy(buf, mBuffer.data() + mReadCursor, len);
89
90 mReadCursor += len;
91
92 if (mReadCursor == mWriteCursor) {
93 clear();
94 }
95 return (unsigned char*)buf;
96 }
97
98 private:
clear()99 void clear() {
100 mBuffer.clear();
101 mReadCursor = 0;
102 mWriteCursor = 0;
103 }
104
105 size_t mReadCursor = 0;
106 size_t mWriteCursor = 0;
107 std::vector<char> mBuffer;
108 };
109
110 // Just see whether the test class is OK
TEST(VulkanStream,Basic)111 TEST(VulkanStream, Basic) {
112 TestStream testStream;
113 VulkanStream stream(&testStream);
114
115 const uint32_t testInt = 6;
116 stream.putBe32(testInt);
117 EXPECT_EQ(testInt, stream.getBe32());
118
119 const std::string testString = "Hello World";
120 stream.putString(testString);
121 EXPECT_EQ(testString, stream.getString());
122 }
123
124 // Try a "basic" Vulkan struct (VkInstanceCreateInfo)
TEST(VulkanStream,testMarshalVulkanStruct)125 TEST(VulkanStream, testMarshalVulkanStruct) {
126 TestStream testStream;
127 VulkanStream stream(&testStream);
128
129 VkApplicationInfo appInfo = {
130 VK_STRUCTURE_TYPE_APPLICATION_INFO,
131 0, // pNext
132 "VulkanStreamTest", // application name
133 6, // application version
134 "VulkanStreamTestEngine", //engine name
135 4, // engine version,
136 VK_API_VERSION_1_0,
137 };
138
139 const char* const layerNames[] = {
140 "layer0",
141 "layer1: test layer",
142 };
143
144 const char* const extensionNames[] = {
145 "VK_KHR_8bit_storage",
146 "VK_KHR_android_surface",
147 "VK_MVK_macos_surface",
148 };
149
150 VkInstanceCreateInfo forMarshaling = {
151 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
152 0, // pNext
153 0, // flags,
154 &appInfo, // pApplicationInfo,
155 arraySize(layerNames),
156 layerNames,
157 arraySize(extensionNames),
158 extensionNames
159 };
160
161 marshal_VkInstanceCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
162
163 VkInstanceCreateInfo forUnmarshaling;
164 memset(&forUnmarshaling, 0x0, sizeof(VkInstanceCreateInfo));
165
166 // Before unmarshaling, these structs should be different.
167 // Test that the generated comparator can detect inequality.
168 int inequalities = 0;
169 checkEqual_VkInstanceCreateInfo(
170 &forMarshaling, &forUnmarshaling, [&inequalities](const char* errMsg) {
171 (void)errMsg;
172 ++inequalities;
173 });
174
175 EXPECT_GT(inequalities, 0);
176
177 unmarshal_VkInstanceCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
178
179 // Check that the strings are equal as well.
180
181 EXPECT_STREQ(
182 forMarshaling.pApplicationInfo->pApplicationName,
183 forUnmarshaling.pApplicationInfo->pApplicationName);
184
185 EXPECT_STREQ(
186 forMarshaling.pApplicationInfo->pEngineName,
187 forUnmarshaling.pApplicationInfo->pEngineName);
188
189 for (size_t i = 0; i < arraySize(layerNames); ++i) {
190 EXPECT_STREQ(
191 forMarshaling.ppEnabledLayerNames[i],
192 forUnmarshaling.ppEnabledLayerNames[i]);
193 }
194
195 for (size_t i = 0; i < arraySize(extensionNames); ++i) {
196 EXPECT_STREQ(
197 forMarshaling.ppEnabledExtensionNames[i],
198 forUnmarshaling.ppEnabledExtensionNames[i]);
199 }
200
201 EXPECT_EQ(forMarshaling.sType, forUnmarshaling.sType);
202 EXPECT_EQ(forMarshaling.pNext, forUnmarshaling.pNext);
203 EXPECT_EQ(forMarshaling.flags, forUnmarshaling.flags);
204 EXPECT_EQ(forMarshaling.pApplicationInfo->sType,
205 forUnmarshaling.pApplicationInfo->sType);
206 EXPECT_EQ(forMarshaling.pApplicationInfo->apiVersion,
207 forUnmarshaling.pApplicationInfo->apiVersion);
208
209 checkEqual_VkInstanceCreateInfo(
210 &forMarshaling, &forUnmarshaling, [](const char* errMsg) {
211 EXPECT_TRUE(false) << errMsg;
212 });
213 }
214
215 // Try a Vulkan struct that has non-ptr structs in it
TEST(VulkanStream,testMarshalVulkanStructWithNonPtrStruct)216 TEST(VulkanStream, testMarshalVulkanStructWithNonPtrStruct) {
217 TestStream testStream;
218 VulkanStream stream(&testStream);
219
220 VkPhysicalDeviceProperties forMarshaling = {
221 VK_API_VERSION_1_0,
222 0,
223 0x8086,
224 0x7800,
225 VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
226 "Intel740",
227 "123456789abcdef",
228 {
229 0x00, // maxImageDimension1D;
230 0x01, // maxImageDimension2D;
231 0x02, // maxImageDimension3D;
232 0x03, // maxImageDimensionCube;
233 0x04, // maxImageArrayLayers;
234 0x05, // maxTexelBufferElements;
235 0x06, // maxUniformBufferRange;
236 0x07, // maxStorageBufferRange;
237 0x08, // maxPushConstantsSize;
238 0x09, // maxMemoryAllocationCount;
239 0x0a, // maxSamplerAllocationCount;
240 0x0b, // bufferImageGranularity;
241 0x0c, // sparseAddressSpaceSize;
242 0x0d, // maxBoundDescriptorSets;
243 0x0e, // maxPerStageDescriptorSamplers;
244 0x0f, // maxPerStageDescriptorUniformBuffers;
245 0x10, // maxPerStageDescriptorStorageBuffers;
246 0x11, // maxPerStageDescriptorSampledImages;
247 0x12, // maxPerStageDescriptorStorageImages;
248 0x13, // maxPerStageDescriptorInputAttachments;
249 0x14, // maxPerStageResources;
250 0x15, // maxDescriptorSetSamplers;
251 0x16, // maxDescriptorSetUniformBuffers;
252 0x17, // maxDescriptorSetUniformBuffersDynamic;
253 0x18, // maxDescriptorSetStorageBuffers;
254 0x19, // maxDescriptorSetStorageBuffersDynamic;
255 0x1a, // maxDescriptorSetSampledImages;
256 0x1b, // maxDescriptorSetStorageImages;
257 0x1c, // maxDescriptorSetInputAttachments;
258 0x1d, // maxVertexInputAttributes;
259 0x1e, // maxVertexInputBindings;
260 0x1f, // maxVertexInputAttributeOffset;
261 0x20, // maxVertexInputBindingStride;
262 0x21, // maxVertexOutputComponents;
263 0x22, // maxTessellationGenerationLevel;
264 0x23, // maxTessellationPatchSize;
265 0x24, // maxTessellationControlPerVertexInputComponents;
266 0x25, // maxTessellationControlPerVertexOutputComponents;
267 0x26, // maxTessellationControlPerPatchOutputComponents;
268 0x27, // maxTessellationControlTotalOutputComponents;
269 0x28, // maxTessellationEvaluationInputComponents;
270 0x29, // maxTessellationEvaluationOutputComponents;
271 0x2a, // maxGeometryShaderInvocations;
272 0x2b, // maxGeometryInputComponents;
273 0x2c, // maxGeometryOutputComponents;
274 0x2d, // maxGeometryOutputVertices;
275 0x2e, // maxGeometryTotalOutputComponents;
276 0x2f, // maxFragmentInputComponents;
277 0x30, // maxFragmentOutputAttachments;
278 0x31, // maxFragmentDualSrcAttachments;
279 0x32, // maxFragmentCombinedOutputResources;
280 0x33, // maxComputeSharedMemorySize;
281 { 0x1, 0x2, 0x3 }, // maxComputeWorkGroupCount[3];
282 0x35, // maxComputeWorkGroupInvocations;
283 { 0x4, 0x5, 0x6 }, // maxComputeWorkGroupSize[3];
284 0x37, // subPixelPrecisionBits;
285 0x38, // subTexelPrecisionBits;
286 0x39, // mipmapPrecisionBits;
287 0x3a, // maxDrawIndexedIndexValue;
288 0x3b, // maxDrawIndirectCount;
289 1.0f, // maxSamplerLodBias;
290 1.0f, // maxSamplerAnisotropy;
291 0x3e, // maxViewports;
292 { 0x7, 0x8 }, // maxViewportDimensions[2];
293 { 0.4f, 0.5f }, // viewportBoundsRange[2];
294 0x41, // viewportSubPixelBits;
295 0x42, // minMemoryMapAlignment;
296 0x43, // minTexelBufferOffsetAlignment;
297 0x44, // minUniformBufferOffsetAlignment;
298 0x45, // minStorageBufferOffsetAlignment;
299 0x46, // minTexelOffset;
300 0x47, // maxTexelOffset;
301 0x48, // minTexelGatherOffset;
302 0x49, // maxTexelGatherOffset;
303 10.0f, // minInterpolationOffset;
304 11.0f, // maxInterpolationOffset;
305 0x4c, // subPixelInterpolationOffsetBits;
306 0x4d, // maxFramebufferWidth;
307 0x4e, // maxFramebufferHeight;
308 0x4f, // maxFramebufferLayers;
309 0x50, // framebufferColorSampleCounts;
310 0x51, // framebufferDepthSampleCounts;
311 0x52, // framebufferStencilSampleCounts;
312 0x53, // framebufferNoAttachmentsSampleCounts;
313 0x54, // maxColorAttachments;
314 0x55, // sampledImageColorSampleCounts;
315 0x56, // sampledImageIntegerSampleCounts;
316 0x57, // sampledImageDepthSampleCounts;
317 0x58, // sampledImageStencilSampleCounts;
318 0x59, // storageImageSampleCounts;
319 0x5a, // maxSampleMaskWords;
320 0x5b, // timestampComputeAndGraphics;
321 100.0f, // timestampPeriod;
322 0x5d, // maxClipDistances;
323 0x5e, // maxCullDistances;
324 0x5f, // maxCombinedClipAndCullDistances;
325 0x60, // discreteQueuePriorities;
326 { 0.0f, 1.0f }, // pointSizeRange[2];
327 { 1.0f, 2.0f }, // lineWidthRange[2];
328 3.0f, // pointSizeGranularity;
329 4.0f, // lineWidthGranularity;
330 0x65, // strictLines;
331 0x66, // standardSampleLocations;
332 0x67, // optimalBufferCopyOffsetAlignment;
333 0x68, // optimalBufferCopyRowPitchAlignment;
334 0x69, // nonCoherentAtomSize;
335 },
336 {
337 0xff, // residencyStandard2DBlockShape;
338 0x00, // residencyStandard2DMultisampleBlockShape;
339 0x11, // residencyStandard3DBlockShape;
340 0x22, // residencyAlignedMipSize;
341 0x33, // residencyNonResidentStrict;
342 },
343 };
344
345 marshal_VkPhysicalDeviceProperties(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
346
347 VkPhysicalDeviceProperties forUnmarshaling;
348 memset(&forUnmarshaling, 0x0, sizeof(VkPhysicalDeviceLimits));
349
350 // Test the autogenerated testing code
351 int inequalities = 0;
352 checkEqual_VkPhysicalDeviceProperties(
353 &forMarshaling, &forUnmarshaling, [&inequalities](const char* errMsg) {
354 (void)errMsg;
355 ++inequalities;
356 });
357
358 EXPECT_GT(inequalities, 0);
359
360 unmarshal_VkPhysicalDeviceProperties(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
361
362 // Test the autogenerated testing code
363 EXPECT_EQ(VK_API_VERSION_1_0, forUnmarshaling.apiVersion);
364 EXPECT_EQ(VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, forUnmarshaling.deviceType);
365 EXPECT_EQ(2.0f, forUnmarshaling.limits.lineWidthRange[1]);
366 EXPECT_EQ(11.0f, forUnmarshaling.limits.maxInterpolationOffset);
367
368 checkEqual_VkPhysicalDeviceProperties(
369 &forMarshaling, &forUnmarshaling, [](const char* errMsg) {
370 EXPECT_TRUE(false) << errMsg;
371 });
372 }
373
374 // Try a Vulkan struct that has ptr fields with count (dynamic arrays)
TEST(VulkanStream,testMarshalVulkanStructWithPtrFields)375 TEST(VulkanStream, testMarshalVulkanStructWithPtrFields) {
376 TestStream testStream;
377 VulkanStream stream(&testStream);
378
379 const uint32_t bindCount = 14;
380
381 std::vector<VkSparseImageMemoryBind> sparseBinds;
382
383 for (uint32_t i = 0; i < bindCount; i++) {
384 VkSparseImageMemoryBind sparseBind = {
385 // VkImageSubresource subresource
386 {
387 VK_IMAGE_ASPECT_COLOR_BIT |
388 VK_IMAGE_ASPECT_DEPTH_BIT,
389 i,
390 i * 2,
391 },
392 // VkOffset3D offset
393 { 1, 2 + (int32_t)i, 3},
394 // VkExtent3D extent
395 { 10, 20 * i, 30},
396 // VkDeviceMemory memory
397 (VkDeviceMemory)(uintptr_t)(0xff - i),
398 // VkDeviceSize memoryOffset
399 0x12345678 + i,
400 // VkSparseMemoryBindFlags flags
401 VK_SPARSE_MEMORY_BIND_METADATA_BIT,
402 };
403
404 sparseBinds.push_back(sparseBind);
405 }
406
407 VkSparseImageMemoryBindInfo forMarshaling = {
408 (VkImage)(uintptr_t)54,
409 bindCount,
410 sparseBinds.data(),
411 };
412
413 marshal_VkSparseImageMemoryBindInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
414
415 VkSparseImageMemoryBindInfo forUnmarshaling = {
416 0, 0, nullptr,
417 };
418
419 unmarshal_VkSparseImageMemoryBindInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
420
421 EXPECT_EQ(bindCount, forUnmarshaling.bindCount);
422 EXPECT_EQ(forMarshaling.image, forUnmarshaling.image);
423
424 // Test some values in there so we know the autogenerated
425 // compare code works.
426 for (uint32_t i = 0; i < bindCount; i++) {
427 EXPECT_EQ(forMarshaling.pBinds[i].memoryOffset,
428 forUnmarshaling.pBinds[i].memoryOffset);
429 EXPECT_EQ(forMarshaling.pBinds[i].memoryOffset,
430 forUnmarshaling.pBinds[i].memoryOffset);
431 EXPECT_EQ(forMarshaling.pBinds[i].subresource.arrayLayer,
432 forUnmarshaling.pBinds[i].subresource.arrayLayer);
433 }
434
435 checkEqual_VkSparseImageMemoryBindInfo(
436 &forMarshaling, &forUnmarshaling, [](const char* errMsg) {
437 EXPECT_TRUE(false) << errMsg;
438 });
439 }
440
441 // Try a Vulkan struct that has ptr fields that are not structs
TEST(VulkanStream,testMarshalVulkanStructWithSimplePtrFields)442 TEST(VulkanStream, testMarshalVulkanStructWithSimplePtrFields) {
443 TestStream testStream;
444 VulkanStream stream(&testStream);
445
446 const uint32_t queueCount = 4;
447
448 std::vector<float> queuePriorities;
449
450 for (uint32_t i = 0; i < queueCount; i++) {
451 queuePriorities.push_back(i * 4.0f);
452 }
453
454 VkDeviceQueueCreateInfo forMarshaling = {
455 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
456 0,
457 0,
458 1,
459 queueCount,
460 queuePriorities.data(),
461 };
462
463 VkDeviceQueueCreateInfo forUnmarshaling = {
464 VK_STRUCTURE_TYPE_APPLICATION_INFO,
465 0,
466 0,
467 0,
468 0,
469 nullptr,
470 };
471
472 marshal_VkDeviceQueueCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
473 unmarshal_VkDeviceQueueCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
474
475 // As always, test the autogenerated tester.
476 for (uint32_t i = 0; i < queueCount; i++) {
477 EXPECT_EQ(forMarshaling.pQueuePriorities[i], forUnmarshaling.pQueuePriorities[i]);
478 }
479
480 checkEqual_VkDeviceQueueCreateInfo(
481 &forMarshaling, &forUnmarshaling, [](const char* errMsg) {
482 EXPECT_TRUE(false) << errMsg;
483 });
484 }
485
486 // Vulkan struct with a void* field that refers to actual data
487 // that needs to get transmitted over
TEST(VulkanStream,testMarshalVulkanStructWithVoidPtrToData)488 TEST(VulkanStream, testMarshalVulkanStructWithVoidPtrToData) {
489 TestStream testStream;
490 VulkanStream stream(&testStream);
491
492 // Not going to validate the map entries---
493 // that's the validation layer's job,
494 // and this is just to make sure values match.
495 const uint32_t numEntries = 5;
496 const size_t dataSize = 54;
497
498 std::vector<VkSpecializationMapEntry> entries(numEntries);
499
500 for (uint32_t i = 0; i < numEntries; i++) {
501 entries[i].constantID = 8 * i + 0;
502 entries[i].offset = 8 * i + 1;
503 entries[i].size = 8 * i + 2;
504 }
505
506 std::vector<uint8_t> data(dataSize);
507
508 for (size_t i = 0; i < dataSize; i++) {
509 data[i] = (uint8_t)i;
510 }
511
512 VkSpecializationInfo forMarshaling = {
513 numEntries,
514 entries.data(),
515 dataSize,
516 data.data(),
517 };
518
519 VkSpecializationInfo forUnmarshaling;
520 memset(&forUnmarshaling, 0x0, sizeof(VkSpecializationInfo));
521
522 int inequalities = 0;
523 checkEqual_VkSpecializationInfo(
524 &forMarshaling, &forUnmarshaling, [&inequalities](const char* errMsg) {
525 ++inequalities;
526 });
527
528 EXPECT_GT(inequalities, 0);
529
530 marshal_VkSpecializationInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
531 unmarshal_VkSpecializationInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
532
533 checkEqual_VkSpecializationInfo(
534 &forMarshaling, &forUnmarshaling, [](const char* errMsg) {
535 EXPECT_TRUE(false) << errMsg;
536 });
537 }
538
539 // Tests that marshal + unmarshal is equivalent to deepcopy.
TEST(VulkanStream,testDeepcopyEquivalence)540 TEST(VulkanStream, testDeepcopyEquivalence) {
541 BumpPool pool;
542 TestStream testStream;
543 VulkanStream stream(&testStream);
544
545 VkApplicationInfo appInfo = {
546 VK_STRUCTURE_TYPE_APPLICATION_INFO,
547 0, // pNext
548 "VulkanStreamTest", // application name
549 6, // application version
550 "VulkanStreamTestEngine", //engine name
551 4, // engine version,
552 VK_API_VERSION_1_0,
553 };
554
555 const char* const layerNames[] = {
556 "layer0",
557 "layer1: test layer",
558 };
559
560 const char* const extensionNames[] = {
561 "VK_KHR_8bit_storage",
562 "VK_KHR_android_surface",
563 "VK_MVK_macos_surface",
564 };
565
566 VkInstanceCreateInfo forMarshaling = {
567 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
568 0, // pNext
569 0, // flags,
570 &appInfo, // pApplicationInfo,
571 arraySize(layerNames),
572 layerNames,
573 arraySize(extensionNames),
574 extensionNames
575 };
576
577 marshal_VkInstanceCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
578
579 VkInstanceCreateInfo forUnmarshaling;
580 VkInstanceCreateInfo forDeepcopy;
581
582 unmarshal_VkInstanceCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
583 deepcopy_VkInstanceCreateInfo(&pool, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling, &forDeepcopy);
584
585 checkEqual_VkInstanceCreateInfo(
586 &forMarshaling, &forUnmarshaling, [](const char* errMsg) {
587 EXPECT_TRUE(false) << errMsg;
588 });
589
590 checkEqual_VkInstanceCreateInfo(
591 &forMarshaling, &forDeepcopy, [](const char* errMsg) {
592 EXPECT_TRUE(false) << errMsg;
593 });
594 }
595
596 // Tests that a struct with an extension struct attached
597 // is properly marshaled/unmarshaled.
TEST(VulkanStream,testStructExtension)598 TEST(VulkanStream, testStructExtension) {
599 BumpPool pool;
600 TestStream testStream;
601 VulkanStream stream(&testStream);
602
603 VkImage image = (VkImage)1;
604 VkBuffer buffer = (VkBuffer)2;
605
606 VkMemoryDedicatedAllocateInfo dedicatedAllocInfo = {
607 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, 0,
608 image, buffer,
609 };
610
611 VkMemoryAllocateInfo forMarshaling = {
612 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
613 &dedicatedAllocInfo,
614 4096,
615 5,
616 };
617
618 marshal_VkMemoryAllocateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
619
620 VkMemoryAllocateInfo forUnmarshaling;
621 unmarshal_VkMemoryAllocateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
622
623 VkMemoryDedicatedAllocateInfo* copiedDedicated =
624 (VkMemoryDedicatedAllocateInfo*)forUnmarshaling.pNext;
625
626 EXPECT_EQ(VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
627 copiedDedicated->sType);
628 EXPECT_EQ(image, copiedDedicated->image);
629 EXPECT_EQ(buffer, copiedDedicated->buffer);
630
631 checkEqual_VkMemoryAllocateInfo(
632 &forMarshaling, &forUnmarshaling, [](const char* errMsg) {
633 EXPECT_TRUE(false) << errMsg;
634 });
635
636 VkMemoryAllocateInfo forDeepcopy;
637 deepcopy_VkMemoryAllocateInfo(&pool, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling, &forDeepcopy);
638
639 copiedDedicated =
640 (VkMemoryDedicatedAllocateInfo*)forDeepcopy.pNext;
641
642 EXPECT_EQ(VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
643 copiedDedicated->sType);
644 EXPECT_EQ(image, copiedDedicated->image);
645 EXPECT_EQ(buffer, copiedDedicated->buffer);
646
647 checkEqual_VkMemoryAllocateInfo(
648 &forMarshaling, &forDeepcopy, [](const char* errMsg) {
649 EXPECT_TRUE(false) << errMsg;
650 });
651 }
652
TEST(VulkanStream,testConflictStructExtensions_marshaling)653 TEST(VulkanStream, testConflictStructExtensions_marshaling) {
654 BumpPool pool;
655 TestStream testStream;
656 VulkanStream stream(&testStream);
657
658 VkStructureType conflictSType0 = static_cast<VkStructureType>(1000218000u);
659 {
660 VkImportColorBufferGOOGLE importColorBuffer = {
661 .sType = conflictSType0,
662 .pNext = nullptr,
663 .colorBuffer = 0xabcd1234,
664 };
665 VkMemoryAllocateInfo forMarshaling = {
666 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
667 .pNext = &importColorBuffer,
668 .allocationSize = 0xcdab,
669 .memoryTypeIndex = 0xabcd,
670 };
671 marshal_VkMemoryAllocateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
672
673 VkMemoryAllocateInfo forUnmarshaling;
674 unmarshal_VkMemoryAllocateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
675 ASSERT_TRUE(forUnmarshaling.pNext);
676 const VkImportColorBufferGOOGLE* ext = reinterpret_cast<const VkImportColorBufferGOOGLE*>(forUnmarshaling.pNext);
677
678 EXPECT_EQ(ext->sType, VK_STRUCTURE_TYPE_IMPORT_COLOR_BUFFER_GOOGLE);
679 EXPECT_EQ(ext->pNext, nullptr);
680 EXPECT_EQ(ext->colorBuffer, importColorBuffer.colorBuffer);
681 }
682 {
683 VkPhysicalDeviceFragmentDensityMapFeaturesEXT densityMapFeatures = {
684 .sType = conflictSType0,
685 .pNext = nullptr,
686 .fragmentDensityMap = true,
687 .fragmentDensityMapDynamic = false,
688 .fragmentDensityMapNonSubsampledImages = true,
689 };
690 VkDeviceCreateInfo forMarshaling = {
691 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
692 .pNext = &densityMapFeatures,
693 };
694 marshal_VkDeviceCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
695
696 VkDeviceCreateInfo forUnmarshaling;
697 unmarshal_VkDeviceCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
698 ASSERT_TRUE(forUnmarshaling.pNext);
699 const VkPhysicalDeviceFragmentDensityMapFeaturesEXT* ext = reinterpret_cast<const VkPhysicalDeviceFragmentDensityMapFeaturesEXT*>(forUnmarshaling.pNext);
700
701 EXPECT_EQ(ext->sType, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT);
702 EXPECT_EQ(ext->pNext, nullptr);
703 EXPECT_EQ(ext->fragmentDensityMap, densityMapFeatures.fragmentDensityMap);
704 EXPECT_EQ(ext->fragmentDensityMapDynamic, densityMapFeatures.fragmentDensityMapDynamic);
705 EXPECT_EQ(ext->fragmentDensityMapNonSubsampledImages, densityMapFeatures.fragmentDensityMapNonSubsampledImages);
706 }
707 }
708
TEST(VulkanStream,testConflictStructExtensions_size)709 TEST(VulkanStream, testConflictStructExtensions_size) {
710 BumpPool pool;
711 TestStream testStream;
712 VulkanStream stream(&testStream);
713
714 VkStructureType conflictSType0 = static_cast<VkStructureType>(1000218000u);
715 {
716 VkImportColorBufferGOOGLE importColorBuffer = {
717 .sType = conflictSType0,
718 .pNext = nullptr,
719 .colorBuffer = 0xabcd1234,
720 };
721 VkMemoryAllocateInfo allocateInfo = {
722 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
723 .pNext = &importColorBuffer,
724 .allocationSize = 0xcdab,
725 .memoryTypeIndex = 0xabcd,
726 };
727
728 size_t size = goldfish_vk_extension_struct_size(allocateInfo.sType, &importColorBuffer);
729 EXPECT_EQ(size, sizeof(VkImportColorBufferGOOGLE));
730 }
731 {
732 VkPhysicalDeviceFragmentDensityMapFeaturesEXT densityMapFeatures = {
733 .sType = conflictSType0,
734 .pNext = nullptr,
735 .fragmentDensityMap = true,
736 .fragmentDensityMapDynamic = false,
737 .fragmentDensityMapNonSubsampledImages = true,
738 };
739 VkDeviceCreateInfo deviceCreateInfo = {
740 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
741 .pNext = &densityMapFeatures,
742 };
743
744 size_t size = goldfish_vk_extension_struct_size(deviceCreateInfo.sType, &densityMapFeatures);
745 EXPECT_EQ(size, sizeof(VkPhysicalDeviceFragmentDensityMapFeaturesEXT));
746 }
747 }
748
749 } // namespace goldfish_vk
750