You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
750 lines
26 KiB
750 lines
26 KiB
// 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 "VulkanStream.h"
|
|
|
|
#include "IOStream.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"
|
|
|
|
#include "android/base/ArraySize.h"
|
|
#include "android/base/BumpPool.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <string.h>
|
|
#include <vulkan.h>
|
|
|
|
using android::base::arraySize;
|
|
|
|
namespace goldfish_vk {
|
|
|
|
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 goldfish_vk
|