blob: a70d342f83fe1d3cc72051f1accf720b3df495a0 [file] [log] [blame]
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <gtest/gtest.h>
#include "VulkanStream.h"
#include <string.h>
#include <vulkan.h>
#include "render-utils/IOStream.h"
#include "android/base/ArraySize.h"
#include "android/base/BumpPool.h"
#include "common/goldfish_vk_deepcopy.h"
#include "common/goldfish_vk_extension_structs.h"
#include "common/goldfish_vk_marshaling.h"
#include "common/goldfish_vk_reserved_marshaling.h"
#include "common/goldfish_vk_testing.h"
namespace gfxstream {
namespace vk {
namespace {
using android::base::arraySize;
class TestStream : public IOStream {
public:
static constexpr size_t kBufSize = 1024;
TestStream() : IOStream(kBufSize) {}
protected:
void* getDmaForReading(uint64_t guest_paddr) override { return nullptr; }
void unlockDma(uint64_t guest_paddr) override {}
// VulkanStream should never use these functions.
void* allocBuffer(size_t minSize) override {
fprintf(stderr, "%s: FATAL: not intended for use!\n", __func__);
abort();
}
int commitBuffer(size_t size) override {
fprintf(stderr, "%s: FATAL: not intended for use!\n", __func__);
abort();
}
const unsigned char* readRaw(void* buf, size_t* inout_len) override {
fprintf(stderr, "%s: FATAL: not intended for use!\n", __func__);
abort();
}
void onSave(android::base::Stream*) override {
fprintf(stderr, "%s: FATAL: not intended for use!\n", __func__);
abort();
}
virtual unsigned char* onLoad(android::base::Stream*) override {
fprintf(stderr, "%s: FATAL: not intended for use!\n", __func__);
abort();
}
int writeFully(const void* buffer, size_t size) override {
if (mBuffer.size() < mWriteCursor + size) {
mBuffer.resize(mWriteCursor + size);
}
memcpy(mBuffer.data() + mWriteCursor, buffer, size);
mWriteCursor += size;
if (mReadCursor == mWriteCursor) {
clear();
}
return 0;
}
const unsigned char* readFully(void* buf, size_t len) override {
EXPECT_LE(mReadCursor + len, mBuffer.size());
memcpy(buf, mBuffer.data() + mReadCursor, len);
mReadCursor += len;
if (mReadCursor == mWriteCursor) {
clear();
}
return (unsigned char*)buf;
}
private:
void clear() {
mBuffer.clear();
mReadCursor = 0;
mWriteCursor = 0;
}
size_t mReadCursor = 0;
size_t mWriteCursor = 0;
std::vector<char> mBuffer;
};
// Just see whether the test class is OK
TEST(VulkanStream, Basic) {
TestStream testStream;
VulkanStream stream(&testStream);
const uint32_t testInt = 6;
stream.putBe32(testInt);
EXPECT_EQ(testInt, stream.getBe32());
const std::string testString = "Hello World";
stream.putString(testString);
EXPECT_EQ(testString, stream.getString());
}
// Try a "basic" Vulkan struct (VkInstanceCreateInfo)
TEST(VulkanStream, testMarshalVulkanStruct) {
TestStream testStream;
VulkanStream stream(&testStream);
VkApplicationInfo appInfo = {
VK_STRUCTURE_TYPE_APPLICATION_INFO,
0, // pNext
"VulkanStreamTest", // application name
6, // application version
"VulkanStreamTestEngine", // engine name
4, // engine version,
VK_API_VERSION_1_0,
};
const char* const layerNames[] = {
"layer0",
"layer1: test layer",
};
const char* const extensionNames[] = {
"VK_KHR_8bit_storage",
"VK_KHR_android_surface",
"VK_MVK_macos_surface",
};
VkInstanceCreateInfo forMarshaling = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
0, // pNext
0, // flags,
&appInfo, // pApplicationInfo,
arraySize(layerNames),
layerNames,
arraySize(extensionNames),
extensionNames};
marshal_VkInstanceCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
VkInstanceCreateInfo forUnmarshaling;
memset(&forUnmarshaling, 0x0, sizeof(VkInstanceCreateInfo));
// Before unmarshaling, these structs should be different.
// Test that the generated comparator can detect inequality.
int inequalities = 0;
checkEqual_VkInstanceCreateInfo(&forMarshaling, &forUnmarshaling,
[&inequalities](const char* errMsg) {
(void)errMsg;
++inequalities;
});
EXPECT_GT(inequalities, 0);
unmarshal_VkInstanceCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
// Check that the strings are equal as well.
EXPECT_STREQ(forMarshaling.pApplicationInfo->pApplicationName,
forUnmarshaling.pApplicationInfo->pApplicationName);
EXPECT_STREQ(forMarshaling.pApplicationInfo->pEngineName,
forUnmarshaling.pApplicationInfo->pEngineName);
for (size_t i = 0; i < arraySize(layerNames); ++i) {
EXPECT_STREQ(forMarshaling.ppEnabledLayerNames[i], forUnmarshaling.ppEnabledLayerNames[i]);
}
for (size_t i = 0; i < arraySize(extensionNames); ++i) {
EXPECT_STREQ(forMarshaling.ppEnabledExtensionNames[i],
forUnmarshaling.ppEnabledExtensionNames[i]);
}
EXPECT_EQ(forMarshaling.sType, forUnmarshaling.sType);
EXPECT_EQ(forMarshaling.pNext, forUnmarshaling.pNext);
EXPECT_EQ(forMarshaling.flags, forUnmarshaling.flags);
EXPECT_EQ(forMarshaling.pApplicationInfo->sType, forUnmarshaling.pApplicationInfo->sType);
EXPECT_EQ(forMarshaling.pApplicationInfo->apiVersion,
forUnmarshaling.pApplicationInfo->apiVersion);
checkEqual_VkInstanceCreateInfo(&forMarshaling, &forUnmarshaling,
[](const char* errMsg) { EXPECT_TRUE(false) << errMsg; });
}
// Try a Vulkan struct that has non-ptr structs in it
TEST(VulkanStream, testMarshalVulkanStructWithNonPtrStruct) {
TestStream testStream;
VulkanStream stream(&testStream);
VkPhysicalDeviceProperties forMarshaling = {
VK_API_VERSION_1_0,
0,
0x8086,
0x7800,
VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
"Intel740",
"123456789abcdef",
{
0x00, // maxImageDimension1D;
0x01, // maxImageDimension2D;
0x02, // maxImageDimension3D;
0x03, // maxImageDimensionCube;
0x04, // maxImageArrayLayers;
0x05, // maxTexelBufferElements;
0x06, // maxUniformBufferRange;
0x07, // maxStorageBufferRange;
0x08, // maxPushConstantsSize;
0x09, // maxMemoryAllocationCount;
0x0a, // maxSamplerAllocationCount;
0x0b, // bufferImageGranularity;
0x0c, // sparseAddressSpaceSize;
0x0d, // maxBoundDescriptorSets;
0x0e, // maxPerStageDescriptorSamplers;
0x0f, // maxPerStageDescriptorUniformBuffers;
0x10, // maxPerStageDescriptorStorageBuffers;
0x11, // maxPerStageDescriptorSampledImages;
0x12, // maxPerStageDescriptorStorageImages;
0x13, // maxPerStageDescriptorInputAttachments;
0x14, // maxPerStageResources;
0x15, // maxDescriptorSetSamplers;
0x16, // maxDescriptorSetUniformBuffers;
0x17, // maxDescriptorSetUniformBuffersDynamic;
0x18, // maxDescriptorSetStorageBuffers;
0x19, // maxDescriptorSetStorageBuffersDynamic;
0x1a, // maxDescriptorSetSampledImages;
0x1b, // maxDescriptorSetStorageImages;
0x1c, // maxDescriptorSetInputAttachments;
0x1d, // maxVertexInputAttributes;
0x1e, // maxVertexInputBindings;
0x1f, // maxVertexInputAttributeOffset;
0x20, // maxVertexInputBindingStride;
0x21, // maxVertexOutputComponents;
0x22, // maxTessellationGenerationLevel;
0x23, // maxTessellationPatchSize;
0x24, // maxTessellationControlPerVertexInputComponents;
0x25, // maxTessellationControlPerVertexOutputComponents;
0x26, // maxTessellationControlPerPatchOutputComponents;
0x27, // maxTessellationControlTotalOutputComponents;
0x28, // maxTessellationEvaluationInputComponents;
0x29, // maxTessellationEvaluationOutputComponents;
0x2a, // maxGeometryShaderInvocations;
0x2b, // maxGeometryInputComponents;
0x2c, // maxGeometryOutputComponents;
0x2d, // maxGeometryOutputVertices;
0x2e, // maxGeometryTotalOutputComponents;
0x2f, // maxFragmentInputComponents;
0x30, // maxFragmentOutputAttachments;
0x31, // maxFragmentDualSrcAttachments;
0x32, // maxFragmentCombinedOutputResources;
0x33, // maxComputeSharedMemorySize;
{0x1, 0x2, 0x3}, // maxComputeWorkGroupCount[3];
0x35, // maxComputeWorkGroupInvocations;
{0x4, 0x5, 0x6}, // maxComputeWorkGroupSize[3];
0x37, // subPixelPrecisionBits;
0x38, // subTexelPrecisionBits;
0x39, // mipmapPrecisionBits;
0x3a, // maxDrawIndexedIndexValue;
0x3b, // maxDrawIndirectCount;
1.0f, // maxSamplerLodBias;
1.0f, // maxSamplerAnisotropy;
0x3e, // maxViewports;
{0x7, 0x8}, // maxViewportDimensions[2];
{0.4f, 0.5f}, // viewportBoundsRange[2];
0x41, // viewportSubPixelBits;
0x42, // minMemoryMapAlignment;
0x43, // minTexelBufferOffsetAlignment;
0x44, // minUniformBufferOffsetAlignment;
0x45, // minStorageBufferOffsetAlignment;
0x46, // minTexelOffset;
0x47, // maxTexelOffset;
0x48, // minTexelGatherOffset;
0x49, // maxTexelGatherOffset;
10.0f, // minInterpolationOffset;
11.0f, // maxInterpolationOffset;
0x4c, // subPixelInterpolationOffsetBits;
0x4d, // maxFramebufferWidth;
0x4e, // maxFramebufferHeight;
0x4f, // maxFramebufferLayers;
0x50, // framebufferColorSampleCounts;
0x51, // framebufferDepthSampleCounts;
0x52, // framebufferStencilSampleCounts;
0x53, // framebufferNoAttachmentsSampleCounts;
0x54, // maxColorAttachments;
0x55, // sampledImageColorSampleCounts;
0x56, // sampledImageIntegerSampleCounts;
0x57, // sampledImageDepthSampleCounts;
0x58, // sampledImageStencilSampleCounts;
0x59, // storageImageSampleCounts;
0x5a, // maxSampleMaskWords;
0x5b, // timestampComputeAndGraphics;
100.0f, // timestampPeriod;
0x5d, // maxClipDistances;
0x5e, // maxCullDistances;
0x5f, // maxCombinedClipAndCullDistances;
0x60, // discreteQueuePriorities;
{0.0f, 1.0f}, // pointSizeRange[2];
{1.0f, 2.0f}, // lineWidthRange[2];
3.0f, // pointSizeGranularity;
4.0f, // lineWidthGranularity;
0x65, // strictLines;
0x66, // standardSampleLocations;
0x67, // optimalBufferCopyOffsetAlignment;
0x68, // optimalBufferCopyRowPitchAlignment;
0x69, // nonCoherentAtomSize;
},
{
0xff, // residencyStandard2DBlockShape;
0x00, // residencyStandard2DMultisampleBlockShape;
0x11, // residencyStandard3DBlockShape;
0x22, // residencyAlignedMipSize;
0x33, // residencyNonResidentStrict;
},
};
marshal_VkPhysicalDeviceProperties(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
VkPhysicalDeviceProperties forUnmarshaling;
memset(&forUnmarshaling, 0x0, sizeof(VkPhysicalDeviceLimits));
// Test the autogenerated testing code
int inequalities = 0;
checkEqual_VkPhysicalDeviceProperties(&forMarshaling, &forUnmarshaling,
[&inequalities](const char* errMsg) {
(void)errMsg;
++inequalities;
});
EXPECT_GT(inequalities, 0);
unmarshal_VkPhysicalDeviceProperties(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
// Test the autogenerated testing code
EXPECT_EQ(VK_API_VERSION_1_0, forUnmarshaling.apiVersion);
EXPECT_EQ(VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, forUnmarshaling.deviceType);
EXPECT_EQ(2.0f, forUnmarshaling.limits.lineWidthRange[1]);
EXPECT_EQ(11.0f, forUnmarshaling.limits.maxInterpolationOffset);
checkEqual_VkPhysicalDeviceProperties(&forMarshaling, &forUnmarshaling,
[](const char* errMsg) { EXPECT_TRUE(false) << errMsg; });
}
// Try a Vulkan struct that has ptr fields with count (dynamic arrays)
TEST(VulkanStream, testMarshalVulkanStructWithPtrFields) {
TestStream testStream;
VulkanStream stream(&testStream);
const uint32_t bindCount = 14;
std::vector<VkSparseImageMemoryBind> sparseBinds;
for (uint32_t i = 0; i < bindCount; i++) {
VkSparseImageMemoryBind sparseBind = {
// VkImageSubresource subresource
{
VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT,
i,
i * 2,
},
// VkOffset3D offset
{1, 2 + (int32_t)i, 3},
// VkExtent3D extent
{10, 20 * i, 30},
// VkDeviceMemory memory
(VkDeviceMemory)(uintptr_t)(0xff - i),
// VkDeviceSize memoryOffset
0x12345678 + i,
// VkSparseMemoryBindFlags flags
VK_SPARSE_MEMORY_BIND_METADATA_BIT,
};
sparseBinds.push_back(sparseBind);
}
VkSparseImageMemoryBindInfo forMarshaling = {
(VkImage)(uintptr_t)54,
bindCount,
sparseBinds.data(),
};
marshal_VkSparseImageMemoryBindInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
VkSparseImageMemoryBindInfo forUnmarshaling = {
0,
0,
nullptr,
};
unmarshal_VkSparseImageMemoryBindInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
EXPECT_EQ(bindCount, forUnmarshaling.bindCount);
EXPECT_EQ(forMarshaling.image, forUnmarshaling.image);
// Test some values in there so we know the autogenerated
// compare code works.
for (uint32_t i = 0; i < bindCount; i++) {
EXPECT_EQ(forMarshaling.pBinds[i].memoryOffset, forUnmarshaling.pBinds[i].memoryOffset);
EXPECT_EQ(forMarshaling.pBinds[i].memoryOffset, forUnmarshaling.pBinds[i].memoryOffset);
EXPECT_EQ(forMarshaling.pBinds[i].subresource.arrayLayer,
forUnmarshaling.pBinds[i].subresource.arrayLayer);
}
checkEqual_VkSparseImageMemoryBindInfo(
&forMarshaling, &forUnmarshaling, [](const char* errMsg) { EXPECT_TRUE(false) << errMsg; });
}
// Try a Vulkan struct that has ptr fields that are not structs
TEST(VulkanStream, testMarshalVulkanStructWithSimplePtrFields) {
TestStream testStream;
VulkanStream stream(&testStream);
const uint32_t queueCount = 4;
std::vector<float> queuePriorities;
for (uint32_t i = 0; i < queueCount; i++) {
queuePriorities.push_back(i * 4.0f);
}
VkDeviceQueueCreateInfo forMarshaling = {
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0, 1, queueCount, queuePriorities.data(),
};
VkDeviceQueueCreateInfo forUnmarshaling = {
VK_STRUCTURE_TYPE_APPLICATION_INFO, 0, 0, 0, 0, nullptr,
};
marshal_VkDeviceQueueCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
unmarshal_VkDeviceQueueCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
// As always, test the autogenerated tester.
for (uint32_t i = 0; i < queueCount; i++) {
EXPECT_EQ(forMarshaling.pQueuePriorities[i], forUnmarshaling.pQueuePriorities[i]);
}
checkEqual_VkDeviceQueueCreateInfo(&forMarshaling, &forUnmarshaling,
[](const char* errMsg) { EXPECT_TRUE(false) << errMsg; });
}
// Vulkan struct with a void* field that refers to actual data
// that needs to get transmitted over
TEST(VulkanStream, testMarshalVulkanStructWithVoidPtrToData) {
TestStream testStream;
VulkanStream stream(&testStream);
// Not going to validate the map entries---
// that's the validation layer's job,
// and this is just to make sure values match.
const uint32_t numEntries = 5;
const size_t dataSize = 54;
std::vector<VkSpecializationMapEntry> entries(numEntries);
for (uint32_t i = 0; i < numEntries; i++) {
entries[i].constantID = 8 * i + 0;
entries[i].offset = 8 * i + 1;
entries[i].size = 8 * i + 2;
}
std::vector<uint8_t> data(dataSize);
for (size_t i = 0; i < dataSize; i++) {
data[i] = (uint8_t)i;
}
VkSpecializationInfo forMarshaling = {
numEntries,
entries.data(),
dataSize,
data.data(),
};
VkSpecializationInfo forUnmarshaling;
memset(&forUnmarshaling, 0x0, sizeof(VkSpecializationInfo));
int inequalities = 0;
checkEqual_VkSpecializationInfo(&forMarshaling, &forUnmarshaling,
[&inequalities](const char* errMsg) { ++inequalities; });
EXPECT_GT(inequalities, 0);
marshal_VkSpecializationInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
unmarshal_VkSpecializationInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
checkEqual_VkSpecializationInfo(&forMarshaling, &forUnmarshaling,
[](const char* errMsg) { EXPECT_TRUE(false) << errMsg; });
}
// Tests that marshal + unmarshal is equivalent to deepcopy.
TEST(VulkanStream, testDeepcopyEquivalence) {
BumpPool pool;
TestStream testStream;
VulkanStream stream(&testStream);
VkApplicationInfo appInfo = {
VK_STRUCTURE_TYPE_APPLICATION_INFO,
0, // pNext
"VulkanStreamTest", // application name
6, // application version
"VulkanStreamTestEngine", // engine name
4, // engine version,
VK_API_VERSION_1_0,
};
const char* const layerNames[] = {
"layer0",
"layer1: test layer",
};
const char* const extensionNames[] = {
"VK_KHR_8bit_storage",
"VK_KHR_android_surface",
"VK_MVK_macos_surface",
};
VkInstanceCreateInfo forMarshaling = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
0, // pNext
0, // flags,
&appInfo, // pApplicationInfo,
arraySize(layerNames),
layerNames,
arraySize(extensionNames),
extensionNames};
marshal_VkInstanceCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
VkInstanceCreateInfo forUnmarshaling;
VkInstanceCreateInfo forDeepcopy;
unmarshal_VkInstanceCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
deepcopy_VkInstanceCreateInfo(&pool, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling, &forDeepcopy);
checkEqual_VkInstanceCreateInfo(&forMarshaling, &forUnmarshaling,
[](const char* errMsg) { EXPECT_TRUE(false) << errMsg; });
checkEqual_VkInstanceCreateInfo(&forMarshaling, &forDeepcopy,
[](const char* errMsg) { EXPECT_TRUE(false) << errMsg; });
}
// Tests that a struct with an extension struct attached
// is properly marshaled/unmarshaled.
TEST(VulkanStream, testStructExtension) {
BumpPool pool;
TestStream testStream;
VulkanStream stream(&testStream);
VkImage image = (VkImage)1;
VkBuffer buffer = (VkBuffer)2;
VkMemoryDedicatedAllocateInfo dedicatedAllocInfo = {
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
0,
image,
buffer,
};
VkMemoryAllocateInfo forMarshaling = {
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
&dedicatedAllocInfo,
4096,
5,
};
marshal_VkMemoryAllocateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
VkMemoryAllocateInfo forUnmarshaling;
unmarshal_VkMemoryAllocateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
VkMemoryDedicatedAllocateInfo* copiedDedicated =
(VkMemoryDedicatedAllocateInfo*)forUnmarshaling.pNext;
EXPECT_EQ(VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, copiedDedicated->sType);
EXPECT_EQ(image, copiedDedicated->image);
EXPECT_EQ(buffer, copiedDedicated->buffer);
checkEqual_VkMemoryAllocateInfo(&forMarshaling, &forUnmarshaling,
[](const char* errMsg) { EXPECT_TRUE(false) << errMsg; });
VkMemoryAllocateInfo forDeepcopy;
deepcopy_VkMemoryAllocateInfo(&pool, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling, &forDeepcopy);
copiedDedicated = (VkMemoryDedicatedAllocateInfo*)forDeepcopy.pNext;
EXPECT_EQ(VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, copiedDedicated->sType);
EXPECT_EQ(image, copiedDedicated->image);
EXPECT_EQ(buffer, copiedDedicated->buffer);
checkEqual_VkMemoryAllocateInfo(&forMarshaling, &forDeepcopy,
[](const char* errMsg) { EXPECT_TRUE(false) << errMsg; });
}
TEST(VulkanStream, testConflictStructExtensions_marshaling) {
BumpPool pool;
TestStream testStream;
VulkanStream stream(&testStream);
VkStructureType conflictSType0 = static_cast<VkStructureType>(1000218000u);
{
VkImportColorBufferGOOGLE importColorBuffer = {
.sType = conflictSType0,
.pNext = nullptr,
.colorBuffer = 0xabcd1234,
};
VkMemoryAllocateInfo forMarshaling = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &importColorBuffer,
.allocationSize = 0xcdab,
.memoryTypeIndex = 0xabcd,
};
marshal_VkMemoryAllocateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
VkMemoryAllocateInfo forUnmarshaling;
unmarshal_VkMemoryAllocateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
ASSERT_TRUE(forUnmarshaling.pNext);
const VkImportColorBufferGOOGLE* ext =
reinterpret_cast<const VkImportColorBufferGOOGLE*>(forUnmarshaling.pNext);
EXPECT_EQ(ext->sType, VK_STRUCTURE_TYPE_IMPORT_COLOR_BUFFER_GOOGLE);
EXPECT_EQ(ext->pNext, nullptr);
EXPECT_EQ(ext->colorBuffer, importColorBuffer.colorBuffer);
}
{
VkPhysicalDeviceFragmentDensityMapFeaturesEXT densityMapFeatures = {
.sType = conflictSType0,
.pNext = nullptr,
.fragmentDensityMap = true,
.fragmentDensityMapDynamic = false,
.fragmentDensityMapNonSubsampledImages = true,
};
VkDeviceCreateInfo forMarshaling = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = &densityMapFeatures,
};
marshal_VkDeviceCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forMarshaling);
VkDeviceCreateInfo forUnmarshaling;
unmarshal_VkDeviceCreateInfo(&stream, VK_STRUCTURE_TYPE_MAX_ENUM, &forUnmarshaling);
ASSERT_TRUE(forUnmarshaling.pNext);
const VkPhysicalDeviceFragmentDensityMapFeaturesEXT* ext =
reinterpret_cast<const VkPhysicalDeviceFragmentDensityMapFeaturesEXT*>(
forUnmarshaling.pNext);
EXPECT_EQ(ext->sType, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT);
EXPECT_EQ(ext->pNext, nullptr);
EXPECT_EQ(ext->fragmentDensityMap, densityMapFeatures.fragmentDensityMap);
EXPECT_EQ(ext->fragmentDensityMapDynamic, densityMapFeatures.fragmentDensityMapDynamic);
EXPECT_EQ(ext->fragmentDensityMapNonSubsampledImages,
densityMapFeatures.fragmentDensityMapNonSubsampledImages);
}
}
TEST(VulkanStream, testConflictStructExtensions_size) {
BumpPool pool;
TestStream testStream;
VulkanStream stream(&testStream);
VkStructureType conflictSType0 = static_cast<VkStructureType>(1000218000u);
{
VkImportColorBufferGOOGLE importColorBuffer = {
.sType = conflictSType0,
.pNext = nullptr,
.colorBuffer = 0xabcd1234,
};
VkMemoryAllocateInfo allocateInfo = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &importColorBuffer,
.allocationSize = 0xcdab,
.memoryTypeIndex = 0xabcd,
};
size_t size = goldfish_vk_extension_struct_size(allocateInfo.sType, &importColorBuffer);
EXPECT_EQ(size, sizeof(VkImportColorBufferGOOGLE));
}
{
VkPhysicalDeviceFragmentDensityMapFeaturesEXT densityMapFeatures = {
.sType = conflictSType0,
.pNext = nullptr,
.fragmentDensityMap = true,
.fragmentDensityMapDynamic = false,
.fragmentDensityMapNonSubsampledImages = true,
};
VkDeviceCreateInfo deviceCreateInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = &densityMapFeatures,
};
size_t size =
goldfish_vk_extension_struct_size(deviceCreateInfo.sType, &densityMapFeatures);
EXPECT_EQ(size, sizeof(VkPhysicalDeviceFragmentDensityMapFeaturesEXT));
}
}
} // namespace
} // namespace vk
} // namespace gfxstream