blob: 05ffbc15ec884b57c6e0a7bf15cca6993d9c4f16 [file] [log] [blame]
/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2020 The Khronos Group Inc.
* Copyright (c) 2020 Google LLC
*
* 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.
*
*//*!
* \file
* \brief VK_EXT_device_memory_report extension tests.
*//*--------------------------------------------------------------------*/
#include "vktMemoryDeviceMemoryReportTests.hpp"
#include "vktCustomInstancesDevices.hpp"
#include "vktExternalMemoryUtil.hpp"
#include "vktTestCaseUtil.hpp"
#include "vkDeviceUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkRefUtil.hpp"
#include "vkTypeUtil.hpp"
#include "tcuCommandLine.hpp"
#include "tcuTestCase.hpp"
#include "tcuTestLog.hpp"
#include "deSharedPtr.hpp"
#include <set>
#include <vector>
#include <limits>
namespace vkt
{
namespace memory
{
namespace
{
#define VK_DESCRIPTOR_TYPE_LAST (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + 1)
using namespace vk;
using namespace vkt::ExternalMemoryUtil;
using de::MovePtr;
using de::SharedPtr;
enum CallbackMarker
{
MARKER_UNKNOWN = 0,
MARKER_ALLOCATE,
MARKER_FREE,
MARKER_IMPORT,
MARKER_UNIMPORT,
MARKER_ALLOCATION_FAILED
};
class CallbackRecorder
{
public:
CallbackRecorder(void): mMarker(MARKER_UNKNOWN) {}
~CallbackRecorder(void) = default;
typedef std::vector<std::pair<VkDeviceMemoryReportCallbackDataEXT, CallbackMarker>>::const_iterator RecordIterator;
RecordIterator getRecordsBegin (void) const
{
return mRecords.begin();
}
RecordIterator getRecordsEnd (void) const
{
return mRecords.end();
}
std::size_t getNumRecords (void) const
{
return mRecords.size();
}
void setCallbackMarker(CallbackMarker marker)
{
mMarker = marker;
}
void callbackInternal (const VkDeviceMemoryReportCallbackDataEXT* pCallbackData)
{
mRecords.emplace_back(*pCallbackData, mMarker);
}
static VKAPI_ATTR void VKAPI_CALL callback (const struct VkDeviceMemoryReportCallbackDataEXT* pCallbackData, void* pUserData)
{
reinterpret_cast<CallbackRecorder*>(pUserData)->callbackInternal(pCallbackData);
}
private:
typedef std::vector<std::pair<VkDeviceMemoryReportCallbackDataEXT, CallbackMarker>> Records;
Records mRecords;
CallbackMarker mMarker;
};
struct Environment
{
const PlatformInterface& vkp;
const InstanceInterface& vki;
VkInstance instance;
VkPhysicalDevice physicalDevice;
const DeviceInterface& vkd;
VkDevice device;
deUint32 queueFamilyIndex;
const BinaryCollection& programBinaries;
const tcu::CommandLine& commandLine;
const CallbackRecorder* recorder;
Environment (const PlatformInterface& vkp_,
const InstanceInterface& vki_,
VkInstance instance_,
VkPhysicalDevice physicalDevice_,
const DeviceInterface& vkd_,
VkDevice device_,
deUint32 queueFamilyIndex_,
const BinaryCollection& programBinaries_,
const tcu::CommandLine& commandLine_,
const CallbackRecorder* recorder_)
: vkp (vkp_)
, vki (vki_)
, instance (instance_)
, physicalDevice (physicalDevice_)
, vkd (vkd_)
, device (device_)
, queueFamilyIndex (queueFamilyIndex_)
, programBinaries (programBinaries_)
, commandLine (commandLine_)
, recorder (recorder_)
{
}
};
template<typename Case>
struct Dependency
{
typename Case::Resources resources;
Unique<typename Case::Type> object;
Dependency (const Environment& env, const typename Case::Parameters& params)
: resources (env, params)
, object (Case::create(env, resources, params))
{}
};
static Move<VkDevice> createDeviceWithMemoryReport (deBool isValidationEnabled,
const PlatformInterface& vkp,
VkInstance instance,
const InstanceInterface& vki,
VkPhysicalDevice physicalDevice,
deUint32 queueFamilyIndex,
const CallbackRecorder* recorder)
{
const deUint32 queueCount = 1;
const float queuePriority = 1.0f;
const char* const enabledExtensions[] = {"VK_EXT_device_memory_report"};
const VkPhysicalDeviceDeviceMemoryReportFeaturesEXT deviceMemoryReportFeatures =
{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT, // VkStructureType sType;
DE_NULL, // void* pNext;
VK_TRUE // VkBool32 deviceMemoryReport;
};
const VkDeviceDeviceMemoryReportCreateInfoEXT deviceMemoryReportCreateInfo =
{
VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT, // VkStructureType sType;
&deviceMemoryReportFeatures, // void* pNext;
(VkDeviceMemoryReportFlagsEXT)0, // VkDeviceMemoryReportFlagsEXT flags;
recorder->callback, // PFN_vkDeviceMemoryReportCallbackEXT pfnUserCallback;
(void*)recorder, // void* pUserData;
};
const VkDeviceQueueCreateInfo queueCreateInfo =
{
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkDeviceQueueCreateFlags)0, // VkDeviceQueueCreateFlags flags;
queueFamilyIndex, // deUint32 queueFamilyIndex;
queueCount, // deUint32 queueCount;
&queuePriority, // const float* pQueuePriorities;
};
const VkDeviceCreateInfo deviceCreateInfo =
{
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
&deviceMemoryReportCreateInfo, // const void* pNext;
(VkDeviceCreateFlags)0, // VkDeviceCreateFlags flags;
queueCount, // uint32_t queueCreateInfoCount;
&queueCreateInfo, // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
0u, // uint32_t enabledLayerCount
DE_NULL, // const char* const* ppEnabledLayerNames
DE_LENGTH_OF_ARRAY(enabledExtensions), // uint32_t enabledExtensionCount
DE_ARRAY_BEGIN(enabledExtensions), // const char* const* ppEnabledExtensionNames
DE_NULL, // const VkPhysicalDeviceFeatures* pEnabledFeatures
};
return createCustomDevice(isValidationEnabled, vkp, instance, vki, physicalDevice, &deviceCreateInfo);
}
struct Device
{
typedef VkDevice Type;
struct Parameters
{
Parameters (void) {}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkDevice> create (const Environment& env, const Resources&, const Parameters&)
{
return createDeviceWithMemoryReport(env.commandLine.isValidationEnabled(), env.vkp, env.instance, env.vki, env.physicalDevice, env.queueFamilyIndex, env.recorder);
}
};
struct DeviceMemory
{
typedef VkDeviceMemory Type;
struct Parameters
{
VkDeviceSize size;
deUint32 memoryTypeIndex;
Parameters (VkDeviceSize size_, deUint32 memoryTypeIndex_)
: size (size_)
, memoryTypeIndex (memoryTypeIndex_)
{
DE_ASSERT(memoryTypeIndex < VK_MAX_MEMORY_TYPES);
}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkDeviceMemory> create (const Environment& env, const Resources&, const Parameters& params)
{
const VkMemoryAllocateInfo memoryAllocateInfo =
{
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
params.size, // VkDeviceSize allocationSize;
params.memoryTypeIndex, // uint32_t memoryTypeIndex;
};
return allocateMemory(env.vkd, env.device, &memoryAllocateInfo);
}
};
DeviceMemory::Parameters getDeviceMemoryParameters (const VkMemoryRequirements& memReqs)
{
return DeviceMemory::Parameters(memReqs.size, deCtz32(memReqs.memoryTypeBits));
}
DeviceMemory::Parameters getDeviceMemoryParameters (const Environment& env, VkImage image)
{
return getDeviceMemoryParameters(getImageMemoryRequirements(env.vkd, env.device, image));
}
DeviceMemory::Parameters getDeviceMemoryParameters (const Environment& env, VkBuffer buffer)
{
return getDeviceMemoryParameters(getBufferMemoryRequirements(env.vkd, env.device, buffer));
}
struct Buffer
{
typedef VkBuffer Type;
struct Parameters
{
VkDeviceSize size;
VkBufferUsageFlags usage;
Parameters (VkDeviceSize size_,
VkBufferUsageFlags usage_)
: size (size_)
, usage (usage_)
{}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkBuffer> create (const Environment& env, const Resources&, const Parameters& params)
{
const VkBufferCreateInfo bufferCreateInfo =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkBufferCreateFlags)0, // VkBufferCreateFlags flags;
params.size, // VkDeviceSize size;
params.usage, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // uint32_t queueFamilyIndexCount;
&env.queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
};
return createBuffer(env.vkd, env.device, &bufferCreateInfo);
}
};
struct BufferView
{
typedef VkBufferView Type;
struct Parameters
{
Buffer::Parameters buffer;
VkFormat format;
VkDeviceSize offset;
VkDeviceSize range;
Parameters (const Buffer::Parameters& buffer_,
VkFormat format_,
VkDeviceSize offset_,
VkDeviceSize range_)
: buffer (buffer_)
, format (format_)
, offset (offset_)
, range (range_)
{}
};
struct Resources
{
Dependency<Buffer> buffer;
Dependency<DeviceMemory> memory;
Resources (const Environment& env, const Parameters& params)
: buffer(env, params.buffer)
, memory(env, getDeviceMemoryParameters(env, *buffer.object))
{
VK_CHECK(env.vkd.bindBufferMemory(env.device, *buffer.object, *memory.object, 0));
}
};
static Move<VkBufferView> create (const Environment& env, const Resources& res, const Parameters& params)
{
const VkBufferViewCreateInfo bufferViewCreateInfo =
{
VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkBufferViewCreateFlags)0, // VkBufferViewCreateFlags flags;
*res.buffer.object, // VkBuffer buffer;
params.format, // VkFormat format;
params.offset, // VkDeviceSize offset;
params.range, // VkDeviceSize range;
};
return createBufferView(env.vkd, env.device, &bufferViewCreateInfo);
}
};
struct Image
{
typedef VkImage Type;
struct Parameters
{
VkImageCreateFlags flags;
VkImageType imageType;
VkFormat format;
VkExtent3D extent;
deUint32 mipLevels;
deUint32 arraySize;
VkSampleCountFlagBits samples;
VkImageTiling tiling;
VkImageUsageFlags usage;
VkImageLayout initialLayout;
Parameters (VkImageCreateFlags flags_,
VkImageType imageType_,
VkFormat format_,
VkExtent3D extent_,
deUint32 mipLevels_,
deUint32 arraySize_,
VkSampleCountFlagBits samples_,
VkImageTiling tiling_,
VkImageUsageFlags usage_,
VkImageLayout initialLayout_)
: flags (flags_)
, imageType (imageType_)
, format (format_)
, extent (extent_)
, mipLevels (mipLevels_)
, arraySize (arraySize_)
, samples (samples_)
, tiling (tiling_)
, usage (usage_)
, initialLayout (initialLayout_)
{}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkImage> create (const Environment& env, const Resources&, const Parameters& params)
{
const VkImageCreateInfo imageCreateInfo =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
params.flags, // VkImageCreateFlags flags;
params.imageType, // VkImageType imageType;
params.format, // VkFormat format;
params.extent, // VkExtent3D extent;
params.mipLevels, // uint32_t mipLevels;
params.arraySize, // uint32_t arrayLayers;
params.samples, // VkSampleCountFlagBits samples;
params.tiling, // VkImageTiling tiling;
params.usage, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // uint32_t queueFamilyIndexCount;
&env.queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
params.initialLayout, // VkImageLayout initialLayout;
};
return createImage(env.vkd, env.device, &imageCreateInfo);
}
};
struct ImageView
{
typedef VkImageView Type;
struct Parameters
{
Image::Parameters image;
VkImageViewType viewType;
VkFormat format;
VkComponentMapping components;
VkImageSubresourceRange subresourceRange;
Parameters (const Image::Parameters& image_,
VkImageViewType viewType_,
VkFormat format_,
VkComponentMapping components_,
VkImageSubresourceRange subresourceRange_)
: image (image_)
, viewType (viewType_)
, format (format_)
, components (components_)
, subresourceRange (subresourceRange_)
{}
};
struct Resources
{
Dependency<Image> image;
Dependency<DeviceMemory> memory;
Resources (const Environment& env, const Parameters& params)
: image (env, params.image)
, memory(env, getDeviceMemoryParameters(env, *image.object))
{
VK_CHECK(env.vkd.bindImageMemory(env.device, *image.object, *memory.object, 0));
}
};
static Move<VkImageView> create (const Environment& env, const Resources& res, const Parameters& params)
{
const VkImageViewCreateInfo imageViewCreateInfo =
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkImageViewCreateFlags)0, // VkImageViewCreateFlags flags;
*res.image.object, // VkImage image;
params.viewType, // VkImageViewType viewType;
params.format, // VkFormat format;
params.components, // VkComponentMapping components;
params.subresourceRange, // VkImageSubresourceRange subresourceRange;
};
return createImageView(env.vkd, env.device, &imageViewCreateInfo);
}
};
struct Semaphore
{
typedef VkSemaphore Type;
struct Parameters
{
VkSemaphoreCreateFlags flags;
Parameters (VkSemaphoreCreateFlags flags_)
: flags(flags_)
{}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkSemaphore> create (const Environment& env, const Resources&, const Parameters& params)
{
const VkSemaphoreCreateInfo semaphoreCreateInfo =
{
VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
params.flags, // VkSemaphoreCreateFlags flags;
};
return createSemaphore(env.vkd, env.device, &semaphoreCreateInfo);
}
};
struct Fence
{
typedef VkFence Type;
struct Parameters
{
VkFenceCreateFlags flags;
Parameters (VkFenceCreateFlags flags_)
: flags(flags_)
{}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkFence> create (const Environment& env, const Resources&, const Parameters& params)
{
const VkFenceCreateInfo fenceCreateInfo =
{
VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
params.flags, // VkFenceCreateFlags flags;
};
return createFence(env.vkd, env.device, &fenceCreateInfo);
}
};
struct Event
{
typedef VkEvent Type;
struct Parameters
{
VkEventCreateFlags flags;
Parameters (VkEventCreateFlags flags_)
: flags(flags_)
{}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkEvent> create (const Environment& env, const Resources&, const Parameters& params)
{
const VkEventCreateInfo eventCreateInfo =
{
VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
params.flags, // VkEventCreateFlags flags;
};
return createEvent(env.vkd, env.device, &eventCreateInfo);
}
};
struct QueryPool
{
typedef VkQueryPool Type;
struct Parameters
{
VkQueryType queryType;
deUint32 entryCount;
VkQueryPipelineStatisticFlags pipelineStatistics;
Parameters (VkQueryType queryType_,
deUint32 entryCount_,
VkQueryPipelineStatisticFlags pipelineStatistics_)
: queryType (queryType_)
, entryCount (entryCount_)
, pipelineStatistics (pipelineStatistics_)
{}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkQueryPool> create (const Environment& env, const Resources&, const Parameters& params)
{
const VkQueryPoolCreateInfo queryPoolCreateInfo =
{
VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkQueryPoolCreateFlags)0, // VkQueryPoolCreateFlags flags;
params.queryType, // VkQueryType queryType;
params.entryCount, // uint32_t queryCount;
params.pipelineStatistics, // VkQueryPipelineStatisticFlags pipelineStatistics;
};
return createQueryPool(env.vkd, env.device, &queryPoolCreateInfo);
}
};
struct ShaderModule
{
typedef VkShaderModule Type;
struct Parameters
{
VkShaderStageFlagBits shaderStage;
std::string binaryName;
Parameters (VkShaderStageFlagBits shaderStage_,
const std::string& binaryName_)
: shaderStage (shaderStage_)
, binaryName (binaryName_)
{}
};
struct Resources
{
const ProgramBinary& binary;
Resources (const Environment& env, const Parameters& params)
: binary(env.programBinaries.get(params.binaryName))
{}
};
static const char* getSource (VkShaderStageFlagBits stage)
{
switch (stage)
{
case VK_SHADER_STAGE_VERTEX_BIT:
return "#version 310 es\n"
"layout(location = 0) in highp vec4 a_position;\n"
"void main () { gl_Position = a_position; }\n";
case VK_SHADER_STAGE_FRAGMENT_BIT:
return "#version 310 es\n"
"layout(location = 0) out mediump vec4 o_color;\n"
"void main () { o_color = vec4(1.0, 0.5, 0.25, 1.0); }";
case VK_SHADER_STAGE_COMPUTE_BIT:
return "#version 310 es\n"
"layout(binding = 0) buffer Input { highp uint dataIn[]; };\n"
"layout(binding = 1) buffer Output { highp uint dataOut[]; };\n"
"void main (void)\n"
"{\n"
" dataOut[gl_GlobalInvocationID.x] = ~dataIn[gl_GlobalInvocationID.x];\n"
"}\n";
default:
DE_FATAL("Not implemented");
return DE_NULL;
}
}
static void initPrograms (SourceCollections& dst, Parameters params)
{
const char* const source = getSource(params.shaderStage);
DE_ASSERT(source);
dst.glslSources.add(params.binaryName)
<< glu::ShaderSource(getGluShaderType(params.shaderStage), source);
}
static Move<VkShaderModule> create (const Environment& env, const Resources& res, const Parameters&)
{
const VkShaderModuleCreateInfo shaderModuleCreateInfo =
{
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkShaderModuleCreateFlags)0, // VkShaderModuleCreateFlags flags;
res.binary.getSize(), // size_t codeSize;
(const deUint32*)res.binary.getBinary(), // const uint32_t* pCode;
};
return createShaderModule(env.vkd, env.device, &shaderModuleCreateInfo);
}
};
struct PipelineCache
{
typedef VkPipelineCache Type;
struct Parameters
{
Parameters (void) {}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkPipelineCache> create (const Environment& env, const Resources&, const Parameters&)
{
const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineCacheCreateFlags)0u, // VkPipelineCacheCreateFlags flags;
0u, // size_t initialDataSize;
DE_NULL, // const void* pInitialData;
};
return createPipelineCache(env.vkd, env.device, &pipelineCacheCreateInfo);
}
};
struct Sampler
{
typedef VkSampler Type;
struct Parameters
{
VkFilter magFilter;
VkFilter minFilter;
VkSamplerMipmapMode mipmapMode;
VkSamplerAddressMode addressModeU;
VkSamplerAddressMode addressModeV;
VkSamplerAddressMode addressModeW;
float mipLodBias;
VkBool32 anisotropyEnable;
float maxAnisotropy;
VkBool32 compareEnable;
VkCompareOp compareOp;
float minLod;
float maxLod;
VkBorderColor borderColor;
VkBool32 unnormalizedCoordinates;
Parameters (void)
: magFilter (VK_FILTER_NEAREST)
, minFilter (VK_FILTER_NEAREST)
, mipmapMode (VK_SAMPLER_MIPMAP_MODE_NEAREST)
, addressModeU (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
, addressModeV (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
, addressModeW (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
, mipLodBias (0.0f)
, anisotropyEnable (VK_FALSE)
, maxAnisotropy (1.0f)
, compareEnable (VK_FALSE)
, compareOp (VK_COMPARE_OP_ALWAYS)
, minLod (-1000.f)
, maxLod (+1000.f)
, borderColor (VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK)
, unnormalizedCoordinates (VK_FALSE)
{}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkSampler> create (const Environment& env, const Resources&, const Parameters& params)
{
const VkSamplerCreateInfo samplerCreateInfo =
{
VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkSamplerCreateFlags)0, // VkSamplerCreateFlags flags;
params.magFilter, // VkFilter magFilter;
params.minFilter, // VkFilter minFilter;
params.mipmapMode, // VkSamplerMipmapMode mipmapMode;
params.addressModeU, // VkSamplerAddressMode addressModeU;
params.addressModeV, // VkSamplerAddressMode addressModeV;
params.addressModeW, // VkSamplerAddressMode addressModeW;
params.mipLodBias, // float mipLodBias;
params.anisotropyEnable, // VkBool32 anisotropyEnable;
params.maxAnisotropy, // float maxAnisotropy;
params.compareEnable, // VkBool32 compareEnable;
params.compareOp, // VkCompareOp compareOp;
params.minLod, // float minLod;
params.maxLod, // float maxLod;
params.borderColor, // VkBorderColor borderColor;
params.unnormalizedCoordinates, // VkBool32 unnormalizedCoordinates;
};
return createSampler(env.vkd, env.device, &samplerCreateInfo);
}
};
struct DescriptorSetLayout
{
typedef VkDescriptorSetLayout Type;
struct Parameters
{
struct Binding
{
deUint32 binding;
VkDescriptorType descriptorType;
deUint32 descriptorCount;
VkShaderStageFlags stageFlags;
bool useImmutableSampler;
Binding (deUint32 binding_,
VkDescriptorType descriptorType_,
deUint32 descriptorCount_,
VkShaderStageFlags stageFlags_,
bool useImmutableSampler_)
: binding (binding_)
, descriptorType (descriptorType_)
, descriptorCount (descriptorCount_)
, stageFlags (stageFlags_)
, useImmutableSampler (useImmutableSampler_)
{}
Binding (void) {}
};
std::vector<Binding> bindings;
Parameters (const std::vector<Binding>& bindings_)
: bindings(bindings_)
{}
static Parameters empty (void)
{
return Parameters(std::vector<Binding>());
}
static Parameters single (deUint32 binding,
VkDescriptorType descriptorType,
deUint32 descriptorCount,
VkShaderStageFlags stageFlags,
bool useImmutableSampler = false)
{
std::vector<Binding> bindings;
bindings.push_back(Binding(binding, descriptorType, descriptorCount, stageFlags, useImmutableSampler));
return Parameters(bindings);
}
};
struct Resources
{
std::vector<VkDescriptorSetLayoutBinding> bindings;
MovePtr<Dependency<Sampler>> immutableSampler;
std::vector<VkSampler> immutableSamplersPtr;
Resources (const Environment& env, const Parameters& params)
{
for (std::vector<Parameters::Binding>::const_iterator cur = params.bindings.begin(); cur != params.bindings.end(); cur++)
{
if (cur->useImmutableSampler && !immutableSampler)
{
immutableSampler = de::newMovePtr<Dependency<Sampler>>(env, Sampler::Parameters());
if (cur->useImmutableSampler && immutableSamplersPtr.size() < (size_t)cur->descriptorCount)
immutableSamplersPtr.resize(cur->descriptorCount, *immutableSampler->object);
}
}
for (std::vector<Parameters::Binding>::const_iterator cur = params.bindings.begin(); cur != params.bindings.end(); cur++)
{
const VkDescriptorSetLayoutBinding binding =
{
cur->binding, // uint32_t binding;
cur->descriptorType, // VkDescriptorType descriptorType;
cur->descriptorCount, // uint32_t descriptorCount;
cur->stageFlags, // VkShaderStageFlags stageFlags;
(cur->useImmutableSampler ? &immutableSamplersPtr[0] : DE_NULL), // const VkSampler* pImmutableSamplers;
};
bindings.push_back(binding);
}
}
};
static Move<VkDescriptorSetLayout> create (const Environment& env, const Resources& res, const Parameters&)
{
const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo =
{
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkDescriptorSetLayoutCreateFlags)0, // VkDescriptorSetLayoutCreateFlags flags;
(deUint32)res.bindings.size(), // uint32_t bindingCount;
(res.bindings.empty() ? DE_NULL : &res.bindings[0]), // const VkDescriptorSetLayoutBinding* pBindings;
};
return createDescriptorSetLayout(env.vkd, env.device, &descriptorSetLayoutCreateInfo);
}
};
struct PipelineLayout
{
typedef VkPipelineLayout Type;
struct Parameters
{
std::vector<DescriptorSetLayout::Parameters> descriptorSetLayouts;
std::vector<VkPushConstantRange> pushConstantRanges;
Parameters (void) {}
static Parameters empty (void)
{
return Parameters();
}
static Parameters singleDescriptorSet (const DescriptorSetLayout::Parameters& descriptorSetLayout)
{
Parameters params;
params.descriptorSetLayouts.push_back(descriptorSetLayout);
return params;
}
};
struct Resources
{
typedef SharedPtr<Dependency<DescriptorSetLayout>> DescriptorSetLayoutDepSp;
typedef std::vector<DescriptorSetLayoutDepSp> DescriptorSetLayouts;
DescriptorSetLayouts descriptorSetLayouts;
std::vector<VkDescriptorSetLayout> pSetLayouts;
Resources (const Environment& env, const Parameters& params)
{
for (std::vector<DescriptorSetLayout::Parameters>::const_iterator dsParams = params.descriptorSetLayouts.begin();
dsParams != params.descriptorSetLayouts.end();
++dsParams)
{
descriptorSetLayouts.push_back(DescriptorSetLayoutDepSp(new Dependency<DescriptorSetLayout>(env, *dsParams)));
pSetLayouts.push_back(*descriptorSetLayouts.back()->object);
}
}
};
static Move<VkPipelineLayout> create (const Environment& env, const Resources& res, const Parameters& params)
{
const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags;
(deUint32)res.pSetLayouts.size(), // uint32_t setLayoutCount;
(res.pSetLayouts.empty() ? DE_NULL : &res.pSetLayouts[0]), // const VkDescriptorSetLayout* pSetLayouts;
(deUint32)params.pushConstantRanges.size(), // uint32_t pushConstantRangeCount;
(params.pushConstantRanges.empty() ? DE_NULL : &params.pushConstantRanges[0]), // const VkPushConstantRange* pPushConstantRanges;
};
return createPipelineLayout(env.vkd, env.device, &pipelineLayoutCreateInfo);
}
};
struct RenderPass
{
typedef VkRenderPass Type;
struct Parameters
{
Parameters (void) {}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkRenderPass> create (const Environment& env, const Resources&, const Parameters&)
{
return makeRenderPass(env.vkd, env.device, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_D16_UNORM,
VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
};
struct GraphicsPipeline
{
typedef VkPipeline Type;
struct Parameters
{
Parameters (void) {}
};
struct Resources
{
Dependency<ShaderModule> vertexShader;
Dependency<ShaderModule> fragmentShader;
Dependency<PipelineLayout> layout;
Dependency<RenderPass> renderPass;
Dependency<PipelineCache> pipelineCache;
Resources (const Environment& env, const Parameters&)
: vertexShader (env, ShaderModule::Parameters(VK_SHADER_STAGE_VERTEX_BIT, "vert"))
, fragmentShader (env, ShaderModule::Parameters(VK_SHADER_STAGE_FRAGMENT_BIT, "frag"))
, layout (env, PipelineLayout::Parameters::singleDescriptorSet(
DescriptorSetLayout::Parameters::single(0u, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u, VK_SHADER_STAGE_FRAGMENT_BIT, true)))
, renderPass (env, RenderPass::Parameters())
, pipelineCache (env, PipelineCache::Parameters())
{}
};
static void initPrograms (SourceCollections& dst, Parameters)
{
ShaderModule::initPrograms(dst, ShaderModule::Parameters(VK_SHADER_STAGE_VERTEX_BIT, "vert"));
ShaderModule::initPrograms(dst, ShaderModule::Parameters(VK_SHADER_STAGE_FRAGMENT_BIT, "frag"));
}
static Move<VkPipeline> create (const Environment& env, const Resources& res, const Parameters&)
{
const VkPipelineShaderStageCreateInfo stages[] =
{
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
*res.vertexShader.object, // VkShaderModule module;
"main", // const char* pName;
DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
},
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
*res.fragmentShader.object, // VkShaderModule module;
"main", // const char* pName;
DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
}
};
const VkVertexInputBindingDescription vertexBindings[] =
{
{
0u, // uint32_t binding;
16u, // uint32_t stride;
VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
}
};
const VkVertexInputAttributeDescription vertexAttribs[] =
{
{
0u, // uint32_t location;
0u, // uint32_t binding;
VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
0u, // uint32_t offset;
}
};
const VkPipelineVertexInputStateCreateInfo vertexInputState =
{
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
DE_LENGTH_OF_ARRAY(vertexBindings), // uint32_t vertexBindingDescriptionCount;
vertexBindings, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
DE_LENGTH_OF_ARRAY(vertexAttribs), // uint32_t vertexAttributeDescriptionCount;
vertexAttribs, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
};
const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
{
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
VK_FALSE, // VkBool32 primitiveRestartEnable;
};
const VkViewport viewport = makeViewport(tcu::UVec2(64));
const VkRect2D scissor = makeRect2D(tcu::UVec2(64));
const VkPipelineViewportStateCreateInfo viewportState =
{
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
1u, // uint32_t viewportCount;
&viewport, // const VkViewport* pViewports;
1u, // uint32_t scissorCount;
&scissor, // const VkRect2D* pScissors;
};
const VkPipelineRasterizationStateCreateInfo rasterState =
{
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
VK_FALSE, // VkBool32 depthClampEnable;
VK_FALSE, // VkBool32 rasterizerDiscardEnable;
VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode;
VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
VK_FALSE, // VkBool32 depthBiasEnable;
0.0f, // float depthBiasConstantFactor;
0.0f, // float depthBiasClamp;
0.0f, // float depthBiasSlopeFactor;
1.0f, // float lineWidth;
};
const VkPipelineMultisampleStateCreateInfo multisampleState =
{
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
VK_FALSE, // VkBool32 sampleShadingEnable;
1.0f, // float minSampleShading;
DE_NULL, // const VkSampleMask* pSampleMask;
VK_FALSE, // VkBool32 alphaToCoverageEnable;
VK_FALSE, // VkBool32 alphaToOneEnable;
};
const VkPipelineDepthStencilStateCreateInfo depthStencilState =
{
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
VK_TRUE, // VkBool32 depthTestEnable;
VK_TRUE, // VkBool32 depthWriteEnable;
VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
VK_FALSE, // VkBool32 depthBoundsTestEnable;
VK_FALSE, // VkBool32 stencilTestEnable;
{
VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
0u, // uint32_t compareMask;
0u, // uint32_t writeMask;
0u, // uint32_t reference;
},
{
VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
0u, // uint32_t compareMask;
0u, // uint32_t writeMask;
0u, // uint32_t reference;
},
0.0f, // float minDepthBounds;
1.0f, // float maxDepthBounds;
};
const VkPipelineColorBlendAttachmentState colorBlendAttState[]=
{
{
VK_FALSE, // VkBool32 blendEnable;
VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, // VkColorComponentFlags colorWriteMask;
}
};
const VkPipelineColorBlendStateCreateInfo colorBlendState =
{
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
VK_FALSE, // VkBool32 logicOpEnable;
VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
DE_LENGTH_OF_ARRAY(colorBlendAttState), // uint32_t attachmentCount;
colorBlendAttState, // const VkPipelineColorBlendAttachmentState* pAttachments;
{ 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
};
const VkGraphicsPipelineCreateInfo pipelineCreateInfo =
{
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
DE_LENGTH_OF_ARRAY(stages), // uint32_t stageCount;
stages, // const VkPipelineShaderStageCreateInfo* pStages;
&vertexInputState, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
&inputAssemblyState, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
&viewportState, // const VkPipelineViewportStateCreateInfo* pViewportState;
&rasterState, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
&multisampleState, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
&depthStencilState, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
&colorBlendState, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
(const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
*res.layout.object, // VkPipelineLayout layout;
*res.renderPass.object, // VkRenderPass renderPass;
0u, // uint32_t subpass;
(VkPipeline)0, // VkPipeline basePipelineHandle;
0, // int32_t basePipelineIndex;
};
return createGraphicsPipeline(env.vkd, env.device, *res.pipelineCache.object, &pipelineCreateInfo);
}
};
struct ComputePipeline
{
typedef VkPipeline Type;
struct Parameters
{
Parameters (void) {}
};
struct Resources
{
Dependency<ShaderModule> shaderModule;
Dependency<PipelineLayout> layout;
Dependency<PipelineCache> pipelineCache;
static DescriptorSetLayout::Parameters getDescriptorSetLayout (void)
{
typedef DescriptorSetLayout::Parameters::Binding Binding;
std::vector<Binding> bindings;
bindings.push_back(Binding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_COMPUTE_BIT, false));
bindings.push_back(Binding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_COMPUTE_BIT, false));
return DescriptorSetLayout::Parameters(bindings);
}
Resources (const Environment& env, const Parameters&)
: shaderModule (env, ShaderModule::Parameters(VK_SHADER_STAGE_COMPUTE_BIT, "comp"))
, layout (env, PipelineLayout::Parameters::singleDescriptorSet(getDescriptorSetLayout()))
, pipelineCache (env, PipelineCache::Parameters())
{}
};
static void initPrograms (SourceCollections& dst, Parameters)
{
ShaderModule::initPrograms(dst, ShaderModule::Parameters(VK_SHADER_STAGE_COMPUTE_BIT, "comp"));
}
static Move<VkPipeline> create (const Environment& env, const Resources& res, const Parameters&)
{
const VkComputePipelineCreateInfo pipelineCreateInfo =
{
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
*res.shaderModule.object, // VkShaderModule module;
"main", // const char* pName;
DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
},
*res.layout.object, // VkPipelineLayout layout;
(VkPipeline)0, // VkPipeline basePipelineHandle;
0u, // int32_t basePipelineIndex;
};
return createComputePipeline(env.vkd, env.device, *res.pipelineCache.object, &pipelineCreateInfo);
}
};
struct DescriptorPool
{
typedef VkDescriptorPool Type;
struct Parameters
{
VkDescriptorPoolCreateFlags flags;
deUint32 maxSets;
std::vector<VkDescriptorPoolSize> poolSizes;
Parameters (VkDescriptorPoolCreateFlags flags_,
deUint32 maxSets_,
const std::vector<VkDescriptorPoolSize>& poolSizes_)
: flags (flags_)
, maxSets (maxSets_)
, poolSizes (poolSizes_)
{}
static Parameters singleType (VkDescriptorPoolCreateFlags flags,
deUint32 maxSets,
VkDescriptorType type,
deUint32 count)
{
std::vector<VkDescriptorPoolSize> poolSizes;
poolSizes.push_back(makeDescriptorPoolSize(type, count));
return Parameters(flags, maxSets, poolSizes);
}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkDescriptorPool> create (const Environment& env, const Resources&, const Parameters& params)
{
const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo =
{
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
params.flags, // VkDescriptorPoolCreateFlags flags;
params.maxSets, // uint32_t maxSets;
(deUint32)params.poolSizes.size(), // uint32_t poolSizeCount;
(params.poolSizes.empty() ? DE_NULL : &params.poolSizes[0]), // const VkDescriptorPoolSize* pPoolSizes;
};
return createDescriptorPool(env.vkd, env.device, &descriptorPoolCreateInfo);
}
};
struct DescriptorSet
{
typedef VkDescriptorSet Type;
struct Parameters
{
DescriptorSetLayout::Parameters descriptorSetLayout;
Parameters (const DescriptorSetLayout::Parameters& descriptorSetLayout_)
: descriptorSetLayout(descriptorSetLayout_)
{}
};
struct Resources
{
Dependency<DescriptorPool> descriptorPool;
Dependency<DescriptorSetLayout> descriptorSetLayout;
static std::vector<VkDescriptorPoolSize> computePoolSizes (const DescriptorSetLayout::Parameters& layout, int maxSets)
{
deUint32 countByType[VK_DESCRIPTOR_TYPE_LAST];
std::vector<VkDescriptorPoolSize> typeCounts;
std::fill(DE_ARRAY_BEGIN(countByType), DE_ARRAY_END(countByType), 0u);
for (std::vector<DescriptorSetLayout::Parameters::Binding>::const_iterator cur = layout.bindings.begin(); cur != layout.bindings.end(); cur++)
{
DE_ASSERT((deUint32)cur->descriptorType < VK_DESCRIPTOR_TYPE_LAST);
countByType[cur->descriptorType] += cur->descriptorCount * maxSets;
}
for (deUint32 type = 0; type < VK_DESCRIPTOR_TYPE_LAST; type++)
{
if (countByType[type] > 0)
typeCounts.push_back(makeDescriptorPoolSize((VkDescriptorType)type, countByType[type]));
}
return typeCounts;
}
Resources (const Environment& env, const Parameters& params)
: descriptorPool (env, DescriptorPool::Parameters(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u, computePoolSizes(params.descriptorSetLayout, 1u)))
, descriptorSetLayout (env, params.descriptorSetLayout)
{
}
};
static Move<VkDescriptorSet> create (const Environment& env, const Resources& res, const Parameters&)
{
const VkDescriptorSetAllocateInfo allocateInfo =
{
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
*res.descriptorPool.object, // VkDescriptorPool descriptorPool;
1u, // uint32_t descriptorSetCount;
&(*res.descriptorSetLayout.object), // const VkDescriptorSetLayout* pSetLayouts;
};
return allocateDescriptorSet(env.vkd, env.device, &allocateInfo);
}
};
struct Framebuffer
{
typedef VkFramebuffer Type;
struct Parameters
{
Parameters (void)
{}
};
struct Resources
{
Dependency<ImageView> colorAttachment;
Dependency<ImageView> depthStencilAttachment;
Dependency<RenderPass> renderPass;
Resources (const Environment& env, const Parameters&)
: colorAttachment (env, ImageView::Parameters(Image::Parameters(0u, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM,
makeExtent3D(256, 256, 1),
1u, 1u,
VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_IMAGE_LAYOUT_UNDEFINED),
VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM,
makeComponentMappingRGBA(),
makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)))
, depthStencilAttachment (env, ImageView::Parameters(Image::Parameters(0u, VK_IMAGE_TYPE_2D, VK_FORMAT_D16_UNORM,
makeExtent3D(256, 256, 1),
1u, 1u,
VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
VK_IMAGE_LAYOUT_UNDEFINED),
VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_D16_UNORM,
makeComponentMappingRGBA(),
makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u)))
, renderPass (env, RenderPass::Parameters())
{}
};
static Move<VkFramebuffer> create (const Environment& env, const Resources& res, const Parameters&)
{
const VkImageView attachments[] =
{
*res.colorAttachment.object,
*res.depthStencilAttachment.object,
};
const VkFramebufferCreateInfo framebufferCreateInfo =
{
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
*res.renderPass.object, // VkRenderPass renderPass;
(deUint32)DE_LENGTH_OF_ARRAY(attachments), // uint32_t attachmentCount;
attachments, // const VkImageView* pAttachments;
256u, // uint32_t width;
256u, // uint32_t height;
1u, // uint32_t layers;
};
return createFramebuffer(env.vkd, env.device, &framebufferCreateInfo);
}
};
struct CommandPool
{
typedef VkCommandPool Type;
struct Parameters
{
VkCommandPoolCreateFlags flags;
Parameters (VkCommandPoolCreateFlags flags_)
: flags(flags_)
{}
};
struct Resources
{
Resources (const Environment&, const Parameters&) {}
};
static Move<VkCommandPool> create (const Environment& env, const Resources&, const Parameters& params)
{
const VkCommandPoolCreateInfo commandPoolCreateInfo =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
params.flags, // VkCommandPoolCreateFlags flags;
env.queueFamilyIndex, // uint32_t queueFamilyIndex;
};
return createCommandPool(env.vkd, env.device, &commandPoolCreateInfo);
}
};
struct CommandBuffer
{
typedef VkCommandBuffer Type;
struct Parameters
{
CommandPool::Parameters commandPool;
VkCommandBufferLevel level;
Parameters (const CommandPool::Parameters& commandPool_,
VkCommandBufferLevel level_)
: commandPool (commandPool_)
, level (level_)
{}
};
struct Resources
{
Dependency<CommandPool> commandPool;
Resources (const Environment& env, const Parameters& params)
: commandPool(env, params.commandPool)
{}
};
static Move<VkCommandBuffer> create (const Environment& env, const Resources& res, const Parameters& params)
{
const VkCommandBufferAllocateInfo allocateInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
*res.commandPool.object, // VkCommandPool commandPool;
params.level, // VkCommandBufferLevel level;
1, // uint32_t commandBufferCount;
};
return allocateCommandBuffer(env.vkd, env.device, &allocateInfo);
}
};
template<typename Object>
struct NamedParameters
{
const char* name;
typename Object::Parameters parameters;
};
template<typename Object>
struct CaseDescription
{
typename FunctionInstance1<typename Object::Parameters>::Function function;
const NamedParameters<Object>* paramsBegin;
const NamedParameters<Object>* paramsEnd;
};
#define CASE_DESC(FUNCTION, CASES) \
{ FUNCTION, DE_ARRAY_BEGIN(CASES), DE_ARRAY_END(CASES) }
struct CaseDescriptions
{
CaseDescription<Device> device;
CaseDescription<DeviceMemory> deviceMemory;
CaseDescription<Buffer> buffer;
CaseDescription<BufferView> bufferView;
CaseDescription<Image> image;
CaseDescription<ImageView> imageView;
CaseDescription<Semaphore> semaphore;
CaseDescription<Event> event;
CaseDescription<Fence> fence;
CaseDescription<QueryPool> queryPool;
CaseDescription<ShaderModule> shaderModule;
CaseDescription<PipelineCache> pipelineCache;
CaseDescription<Sampler> sampler;
CaseDescription<DescriptorSetLayout> descriptorSetLayout;
CaseDescription<PipelineLayout> pipelineLayout;
CaseDescription<RenderPass> renderPass;
CaseDescription<GraphicsPipeline> graphicsPipeline;
CaseDescription<ComputePipeline> computePipeline;
CaseDescription<DescriptorPool> descriptorPool;
CaseDescription<DescriptorSet> descriptorSet;
CaseDescription<Framebuffer> framebuffer;
CaseDescription<CommandPool> commandPool;
CaseDescription<CommandBuffer> commandBuffer;
};
template<typename Object>
static void checkSupport (Context& context, typename Object::Parameters)
{
context.requireDeviceFunctionality("VK_EXT_device_memory_report");
}
template<typename Object>
void addCases (const MovePtr<tcu::TestCaseGroup>& group, const CaseDescription<Object>& cases)
{
for (const NamedParameters<Object>* cur = cases.paramsBegin; cur != cases.paramsEnd; cur++)
{
addFunctionCase(group.get(), cur->name, "", checkSupport<Object>, cases.function, cur->parameters);
}
}
template<typename Object>
void addCasesWithProgs (const MovePtr<tcu::TestCaseGroup>& group, const CaseDescription<Object>& cases)
{
for (const NamedParameters<Object>* cur = cases.paramsBegin; cur != cases.paramsEnd; cur++)
{
addFunctionCaseWithPrograms(group.get(), cur->name, "", checkSupport<Object>, Object::initPrograms, cases.function, cur->parameters);
}
}
tcu::TestCaseGroup* createObjectTestsGroup (tcu::TestContext& testCtx, const char* name, const char* desc, const CaseDescriptions& cases)
{
MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, name, desc));
addCases (group, cases.device);
addCases (group, cases.deviceMemory);
addCases (group, cases.buffer);
addCases (group, cases.bufferView);
addCases (group, cases.image);
addCases (group, cases.imageView);
addCases (group, cases.semaphore);
addCases (group, cases.event);
addCases (group, cases.fence);
addCases (group, cases.queryPool);
addCasesWithProgs (group, cases.shaderModule);
addCases (group, cases.pipelineCache);
addCases (group, cases.sampler);
addCases (group, cases.descriptorSetLayout);
addCases (group, cases.pipelineLayout);
addCases (group, cases.renderPass);
addCasesWithProgs (group, cases.graphicsPipeline);
addCasesWithProgs (group, cases.computePipeline);
addCases (group, cases.descriptorPool);
addCases (group, cases.descriptorSet);
addCases (group, cases.framebuffer);
addCases (group, cases.commandPool);
addCases (group, cases.commandBuffer);
return group.release();
}
static deBool validateCallbackRecords (Context& context, const CallbackRecorder& recorder)
{
tcu::TestLog& log = context.getTestContext().getLog();
const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
const InstanceInterface& vki = context.getInstanceInterface();
const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physicalDevice);
std::set<std::pair<deUint64, deUint64>> memoryObjectSet;
for (auto iter = recorder.getRecordsBegin(); iter != recorder.getRecordsEnd(); iter++)
{
const VkDeviceMemoryReportCallbackDataEXT& record = iter->first;
if ((record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT ||
record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT) &&
record.heapIndex >= memoryProperties.memoryHeapCount)
{
log << tcu::TestLog::Message << "memoryHeapCount: " << memoryProperties.memoryHeapCount << tcu::TestLog::EndMessage;
log << tcu::TestLog::Message << record << tcu::TestLog::EndMessage;
return false;
}
if (record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT)
{
log << tcu::TestLog::Message << "Observed ALLOCATION_FAILED event" << tcu::TestLog::EndMessage;
log << tcu::TestLog::Message << record << tcu::TestLog::EndMessage;
continue;
}
if (record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT ||
record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT)
{
memoryObjectSet.insert(std::make_pair(record.memoryObjectId, record.objectHandle));
continue;
}
if (record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT ||
record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT)
{
const auto objectPair = std::make_pair(record.memoryObjectId, record.objectHandle);
if (!memoryObjectSet.count(objectPair))
{
log << tcu::TestLog::Message << "Unpaired or out-of-order free/unimport event" << tcu::TestLog::EndMessage;
log << tcu::TestLog::Message << record << tcu::TestLog::EndMessage;
return false;
}
memoryObjectSet.erase(objectPair);
}
}
if (!memoryObjectSet.empty())
{
log << tcu::TestLog::Message << "Unpaired alloc/import event" << tcu::TestLog::EndMessage;
return false;
}
return true;
}
struct EnvClone
{
Unique<VkDevice> device;
DeviceDriver vkd;
Environment env;
EnvClone (const Environment& parent)
: device (Device::create(parent, Device::Resources(parent, Device::Parameters()), Device::Parameters()))
, vkd (parent.vkp, parent.instance, *device)
, env (parent.vkp, parent.vki, parent.instance, parent.physicalDevice, vkd, *device, parent.queueFamilyIndex, parent.programBinaries, parent.commandLine, nullptr)
{
}
};
template<typename Object>
tcu::TestStatus createDestroyObjectTest (Context& context, typename Object::Parameters params)
{
CallbackRecorder recorder;
const Environment env (context.getPlatformInterface(),
context.getInstanceInterface(),
context.getInstance(),
context.getPhysicalDevice(),
context.getDeviceInterface(),
context.getDevice(),
context.getUniversalQueueFamilyIndex(),
context.getBinaryCollection(),
context.getTestContext().getCommandLine(),
&recorder);
if (std::is_same<Object, Device>::value)
{
const typename Object::Resources res (env, params);
Unique<typename Object::Type> obj (Object::create(env, res, params));
}
else
{
const EnvClone envWithCustomDevice (env);
const typename Object::Resources res (envWithCustomDevice.env, params);
Unique<typename Object::Type> obj (Object::create(envWithCustomDevice.env, res, params));
}
if (!validateCallbackRecords(context, recorder))
{
return tcu::TestStatus::fail("Invalid device memory report callback");
}
return tcu::TestStatus::pass("Ok");
}
tcu::TestStatus vkDeviceMemoryAllocateAndFreeTest (Context& context)
{
CallbackRecorder recorder;
const PlatformInterface& vkp = context.getPlatformInterface();
const VkInstance instance = context.getInstance();
const InstanceInterface& vki = context.getInstanceInterface();
const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const deBool isValidationEnabled = context.getTestContext().getCommandLine().isValidationEnabled();
const Unique<VkDevice> device (createDeviceWithMemoryReport(isValidationEnabled, vkp, instance, vki, physicalDevice, queueFamilyIndex, &recorder));
const DeviceDriver vkd (vkp, instance, *device);
const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physicalDevice);
const VkDeviceSize testSize = 1024;
const deUint32 testTypeIndex = 0;
const deUint32 testHeapIndex = memoryProperties.memoryTypes[testTypeIndex].heapIndex;
deUint64 objectHandle = 0;
{
recorder.setCallbackMarker(MARKER_ALLOCATE);
VkResult result = VK_SUCCESS;
VkDeviceMemory memory = DE_NULL;
const VkMemoryAllocateInfo memoryAllocateInfo =
{
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
testSize, // VkDeviceSize allocationSize;
testHeapIndex, // uint32_t memoryTypeIndex;
};
result = vkd.allocateMemory(*device, &memoryAllocateInfo, (const VkAllocationCallbacks*)DE_NULL, &memory);
if (result != VK_SUCCESS)
{
return tcu::TestStatus::fail("Unable to allocate " + de::toString(testSize) + " bytes of memory");
}
objectHandle = memory.getInternal();
recorder.setCallbackMarker(MARKER_FREE);
vkd.freeMemory(*device, memory, (const VkAllocationCallbacks*)DE_NULL);
}
recorder.setCallbackMarker(MARKER_UNKNOWN);
deBool allocateEvent = false;
deBool freeEvent = false;
deUint64 memoryObjectId = 0;
for (auto iter = recorder.getRecordsBegin(); iter != recorder.getRecordsEnd(); iter++)
{
const VkDeviceMemoryReportCallbackDataEXT& record = iter->first;
const CallbackMarker marker = iter->second;
if (record.objectHandle == objectHandle && record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT)
{
TCU_CHECK(marker == MARKER_ALLOCATE);
TCU_CHECK(record.objectType == VK_OBJECT_TYPE_DEVICE_MEMORY);
TCU_CHECK(memoryObjectId == 0);
TCU_CHECK(record.memoryObjectId != 0);
TCU_CHECK_MSG(record.size >= testSize, ("record.size=" + de::toString(record.size) + ", testSize=" + de::toString(testSize)).c_str());
TCU_CHECK(record.heapIndex == testHeapIndex);
memoryObjectId = record.memoryObjectId;
allocateEvent = true;
}
else if (record.objectHandle == objectHandle && record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT)
{
TCU_CHECK(marker == MARKER_FREE);
TCU_CHECK_MSG(record.memoryObjectId == memoryObjectId,
("record.memoryObjectId=" + de::toString(record.memoryObjectId) +
", memoryObjectId=" + de::toString(memoryObjectId)).c_str());
freeEvent = true;
}
}
TCU_CHECK(allocateEvent);
TCU_CHECK(freeEvent);
return tcu::TestStatus::pass("Ok");
}
tcu::TestStatus vkDeviceMemoryAllocationFailedTest (Context& context)
{
CallbackRecorder recorder;
const PlatformInterface& vkp = context.getPlatformInterface();
const VkInstance instance = context.getInstance();
const InstanceInterface& vki = context.getInstanceInterface();
const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const deBool isValidationEnabled = context.getTestContext().getCommandLine().isValidationEnabled();
const Unique<VkDevice> device (createDeviceWithMemoryReport(isValidationEnabled, vkp, instance, vki, physicalDevice, queueFamilyIndex, &recorder));
const DeviceDriver vkd (vkp, instance, *device);
const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physicalDevice);
const VkDeviceSize testSize = std::numeric_limits<deUint64>::max();
const deUint32 testTypeIndex = 0;
const deUint32 testHeapIndex = memoryProperties.memoryTypes[testTypeIndex].heapIndex;
{
recorder.setCallbackMarker(MARKER_ALLOCATION_FAILED);
VkResult result = VK_SUCCESS;
VkDeviceMemory memory = DE_NULL;
const VkMemoryAllocateInfo memoryAllocateInfo =
{
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
testSize, // VkDeviceSize allocationSize;
testHeapIndex, // uint32_t memoryTypeIndex;
};
result = vkd.allocateMemory(*device, &memoryAllocateInfo, (const VkAllocationCallbacks*)DE_NULL, &memory);
if (result == VK_SUCCESS)
{
return tcu::TestStatus::fail("Should not be able to allocate UINT64_MAX bytes of memory");
}
recorder.setCallbackMarker(MARKER_UNKNOWN);
}
deBool allocationFailedEvent = false;
for (auto iter = recorder.getRecordsBegin(); iter != recorder.getRecordsEnd(); iter++)
{
const VkDeviceMemoryReportCallbackDataEXT& record = iter->first;
const CallbackMarker marker = iter->second;
if (record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT)
{
TCU_CHECK(marker == MARKER_ALLOCATION_FAILED);
TCU_CHECK(record.objectType == VK_OBJECT_TYPE_DEVICE_MEMORY);
TCU_CHECK_MSG(record.size >= testSize, ("record.size=" + de::toString(record.size) + ", testSize=" + de::toString(testSize)).c_str());
TCU_CHECK(record.heapIndex == testHeapIndex);
allocationFailedEvent = true;
}
}
TCU_CHECK(allocationFailedEvent);
return tcu::TestStatus::pass("Ok");
}
static void checkSupport (Context& context)
{
context.requireDeviceFunctionality("VK_EXT_device_memory_report");
}
tcu::TestCaseGroup* createVkDeviceMemoryTestsGroup (tcu::TestContext& testCtx, const char* name, const char* desc)
{
MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, name, desc));
addFunctionCase(group.get(), "allocate_and_free", "", checkSupport, vkDeviceMemoryAllocateAndFreeTest);
addFunctionCase(group.get(), "allocation_failed", "", checkSupport, vkDeviceMemoryAllocationFailedTest);
return group.release();
}
static void checkSupport (Context& context, VkExternalMemoryHandleTypeFlagBits externalMemoryType)
{
context.requireInstanceFunctionality("VK_KHR_external_memory_capabilities");
context.requireDeviceFunctionality("VK_EXT_device_memory_report");
context.requireDeviceFunctionality("VK_KHR_dedicated_allocation");
context.requireDeviceFunctionality("VK_KHR_get_memory_requirements2");
if (externalMemoryType & (VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT))
{
context.requireDeviceFunctionality("VK_KHR_external_memory_fd");
}
if (externalMemoryType & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
{
context.requireDeviceFunctionality("VK_EXT_external_memory_dma_buf");
}
if (externalMemoryType & (VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT))
{
context.requireDeviceFunctionality("VK_KHR_external_memory_win32");
}
if (externalMemoryType & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
{
context.requireDeviceFunctionality("VK_ANDROID_external_memory_android_hardware_buffer");
}
}
static std::vector<std::string> getInstanceExtensions (const deUint32 instanceVersion)
{
std::vector<std::string> instanceExtensions;
if (!isCoreInstanceExtension(instanceVersion, "VK_KHR_get_physical_device_properties2"))
instanceExtensions.push_back("VK_KHR_get_physical_device_properties2");
if (!isCoreInstanceExtension(instanceVersion, "VK_KHR_external_memory_capabilities"))
instanceExtensions.push_back("VK_KHR_external_memory_capabilities");
return instanceExtensions;
}
static Move<VkDevice> createExternalMemoryDevice (deBool isValidationEnabled,
const PlatformInterface& vkp,
VkInstance instance,
const InstanceInterface& vki,
VkPhysicalDevice physicalDevice,
deUint32 apiVersion,
deUint32 queueFamilyIndex,
VkExternalMemoryHandleTypeFlagBits externalMemoryType,
const CallbackRecorder* recorder)
{
const deUint32 queueCount = 1;
const float queuePriority = 1.0f;
std::vector<const char*> enabledExtensions = {"VK_EXT_device_memory_report"};
if (!isCoreDeviceExtension(apiVersion, "VK_KHR_dedicated_allocation"))
{
enabledExtensions.push_back("VK_KHR_dedicated_allocation");
}
if (!isCoreDeviceExtension(apiVersion, "VK_KHR_get_memory_requirements2"))
{
enabledExtensions.push_back("VK_KHR_get_memory_requirements2");
}
if (externalMemoryType & (VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT))
{
if (!isCoreDeviceExtension(apiVersion, "VK_KHR_external_memory_fd"))
{
enabledExtensions.push_back("VK_KHR_external_memory_fd");
}
}
if (externalMemoryType & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
{
enabledExtensions.push_back("VK_EXT_external_memory_dma_buf");
}
if (externalMemoryType & (VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT |
VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT))
{
enabledExtensions.push_back("VK_KHR_external_memory_win32");
}
if (externalMemoryType & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
{
enabledExtensions.push_back("VK_ANDROID_external_memory_android_hardware_buffer");
enabledExtensions.push_back("VK_EXT_queue_family_foreign");
if (!isCoreDeviceExtension(apiVersion, "VK_KHR_sampler_ycbcr_conversion"))
{
enabledExtensions.push_back("VK_KHR_sampler_ycbcr_conversion");
}
}
const VkPhysicalDeviceDeviceMemoryReportFeaturesEXT deviceMemoryReportFeatures =
{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT, // VkStructureType sType;
DE_NULL, // void* pNext;
VK_TRUE // VkBool32 deviceMemoryReport;
};
const VkDeviceDeviceMemoryReportCreateInfoEXT deviceMemoryReportCreateInfo =
{
VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT, // VkStructureType sType;
&deviceMemoryReportFeatures, // void* pNext;
(VkDeviceMemoryReportFlagsEXT)0, // VkDeviceMemoryReportFlagsEXT flags;
recorder->callback, // PFN_vkDeviceMemoryReportCallbackEXT pfnUserCallback;
(void*)recorder, // void* pUserData;
};
const VkDeviceQueueCreateInfo queueCreateInfo =
{
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkDeviceQueueCreateFlags)0, // VkDeviceQueueCreateFlags flags;
queueFamilyIndex, // deUint32 queueFamilyIndex;
queueCount, // deUint32 queueCount;
&queuePriority, // const float* pQueuePriorities;
};
const VkDeviceCreateInfo deviceCreateInfo =
{
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
&deviceMemoryReportCreateInfo, // const void* pNext;
(VkDeviceCreateFlags)0, // VkDeviceCreateFlags flags;
queueCount, // uint32_t queueCreateInfoCount;
&queueCreateInfo, // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
0u, // uint32_t enabledLayerCount;
DE_NULL, // const char* const* ppEnabledLayerNames;
(deUint32)enabledExtensions.size(), // uint32_t enabledExtensionCount;
enabledExtensions.data(), // const char* const* ppEnabledExtensionNames;
DE_NULL, // const VkPhysicalDeviceFeatures* pEnabledFeatures;
};
return createCustomDevice(isValidationEnabled, vkp, instance, vki, physicalDevice, &deviceCreateInfo);
}
static void checkBufferSupport (const InstanceInterface& vki,
VkPhysicalDevice device,
VkBufferUsageFlags usage,
VkExternalMemoryHandleTypeFlagBits externalMemoryType)
{
const VkPhysicalDeviceExternalBufferInfo info =
{
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO, // VkStructureType sType;
DE_NULL, // void* pNext;
(VkBufferCreateFlags)0, // VkBufferCreateFlags flags;
usage, // VkBufferUsageFlags usage;
externalMemoryType, // VkExternalMemoryHandleTypeFlagBits handleType;
};
VkExternalBufferProperties properties =
{
VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES, // VkStructureType sType;
DE_NULL, // void* pNext;
{ 0u, 0u, 0u }, // VkExternalMemoryProperties externalMemoryProperties;
};
vki.getPhysicalDeviceExternalBufferProperties(device, &info, &properties);
if ((properties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
TCU_THROW(NotSupportedError, "External handle type doesn't support exporting buffer");
if ((properties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
TCU_THROW(NotSupportedError, "External handle type doesn't support importing buffer");
}
tcu::TestStatus testImportAndUnimportExternalMemory (Context& context, VkExternalMemoryHandleTypeFlagBits externalMemoryType)
{
CallbackRecorder recorder;
const PlatformInterface& vkp (context.getPlatformInterface());
const CustomInstance instance (createCustomInstanceWithExtensions(context, getInstanceExtensions(context.getUsedApiVersion())));
const InstanceDriver& vki (instance.getDriver());
const VkPhysicalDevice physicalDevice (chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
const deUint32 queueFamilyIndex (context.getUniversalQueueFamilyIndex());
const Unique<VkDevice> device (createExternalMemoryDevice(context.getTestContext().getCommandLine().isValidationEnabled(),
vkp,
instance,
vki,
physicalDevice,
context.getUsedApiVersion(),
queueFamilyIndex,
externalMemoryType,
&recorder));
const DeviceDriver vkd (vkp, instance, *device);
const VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
const VkDeviceSize bufferSize = 1024;
checkBufferSupport(vki, physicalDevice, usage, externalMemoryType);
const Unique<VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, externalMemoryType, bufferSize, 0u, usage));
const VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
const deUint32 memoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
deUint64 objectHandle = 0;
deUint64 objectHandleA = 0;
deUint64 objectHandleB = 0;
{
recorder.setCallbackMarker(MARKER_ALLOCATE);
const Unique<VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, memoryTypeIndex, externalMemoryType, *buffer));
objectHandle = (*memory).getInternal();
NativeHandle handleA;
getMemoryNative(vkd, *device, *memory, externalMemoryType, handleA);
NativeHandle handleB (handleA);
const Unique<VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, externalMemoryType, bufferSize, 0u, usage));
const Unique<VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, externalMemoryType, bufferSize, 0u, usage));
{
recorder.setCallbackMarker(MARKER_IMPORT);
const Unique<VkDeviceMemory> memoryA (importDedicatedMemory(vkd, *device, *bufferA, requirements, externalMemoryType, memoryTypeIndex, handleA));
const Unique<VkDeviceMemory> memoryB (importDedicatedMemory(vkd, *device, *bufferB, requirements, externalMemoryType, memoryTypeIndex, handleB));
objectHandleA = (*memoryA).getInternal();
objectHandleB = (*memoryB).getInternal();
recorder.setCallbackMarker(MARKER_UNIMPORT);
}
recorder.setCallbackMarker(MARKER_FREE);
}
recorder.setCallbackMarker(MARKER_UNKNOWN);
deBool allocateEvent = false;
deBool freeEvent = false;
deBool importA = false;
deBool importB = false;
deBool unimportA = false;
deBool unimportB = false;
deUint64 memoryObjectId = 0;
for (auto iter = recorder.getRecordsBegin(); iter != recorder.getRecordsEnd(); iter++)
{
const VkDeviceMemoryReportCallbackDataEXT& record = iter->first;
const CallbackMarker marker = iter->second;
if (record.objectHandle == objectHandle && record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT)
{
TCU_CHECK(marker == MARKER_ALLOCATE);
TCU_CHECK(record.objectType == VK_OBJECT_TYPE_DEVICE_MEMORY);
TCU_CHECK(memoryObjectId == 0);
TCU_CHECK(record.memoryObjectId != 0);
TCU_CHECK_MSG(record.size >= requirements.size,
("size: record=" + de::toString(record.size) +
", requirements=" + de::toString(requirements.size)).c_str());
allocateEvent = true;
memoryObjectId = record.memoryObjectId;
}
else if (record.objectHandle == objectHandleA && record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT)
{
TCU_CHECK(marker == MARKER_IMPORT);
TCU_CHECK(record.objectType == VK_OBJECT_TYPE_DEVICE_MEMORY);
TCU_CHECK_MSG(record.size >= requirements.size,
("sizeA: record=" + de::toString(record.size) +
", requirements=" + de::toString(requirements.size)).c_str());
TCU_CHECK_MSG(record.memoryObjectId == memoryObjectId,
("memoryObjectIdA: record=" + de::toString(record.memoryObjectId) +
", original=" + de::toString(memoryObjectId)).c_str());
importA = true;
}
else if (record.objectHandle == objectHandleB && record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT)
{
TCU_CHECK(marker == MARKER_IMPORT);
TCU_CHECK(record.objectType == VK_OBJECT_TYPE_DEVICE_MEMORY);
TCU_CHECK_MSG(record.size >= requirements.size,
("sizeB: record=" + de::toString(record.size) +
", requirements=" + de::toString(requirements.size)).c_str());
TCU_CHECK_MSG(record.memoryObjectId == memoryObjectId,
("memoryObjectIdB: record=" + de::toString(record.memoryObjectId) +
", original=" + de::toString(memoryObjectId)).c_str());
importB = true;
}
else if (record.objectHandle == objectHandleB && record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT)
{
TCU_CHECK(marker == MARKER_UNIMPORT);
TCU_CHECK_MSG(record.memoryObjectId == memoryObjectId,
("memoryObjectIdA: record=" + de::toString(record.memoryObjectId) +
", original=" + de::toString(memoryObjectId)).c_str());
unimportB = true;
}
else if (record.objectHandle == objectHandleA && record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT)
{
TCU_CHECK(marker == MARKER_UNIMPORT);
TCU_CHECK_MSG(record.memoryObjectId == memoryObjectId,
("memoryObjectIdB: record=" + de::toString(record.memoryObjectId) +
", original=" + de::toString(memoryObjectId)).c_str());
unimportA = true;
}
else if (record.objectHandle == objectHandle && record.type == VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT)
{
TCU_CHECK(marker == MARKER_FREE);
TCU_CHECK_MSG(record.memoryObjectId == memoryObjectId,
("memoryObjectId: record=" + de::toString(record.memoryObjectId) +
", original=" + de::toString(memoryObjectId)).c_str());
freeEvent = true;
}
}
TCU_CHECK(allocateEvent);
TCU_CHECK(importA);
TCU_CHECK(importB);
TCU_CHECK(unimportB);
TCU_CHECK(unimportA);
TCU_CHECK(freeEvent);
return tcu::TestStatus::pass("Pass");
}
tcu::TestCaseGroup* createExternalMemoryTestsGroup (tcu::TestContext& testCtx, const char* name, const char* desc)
{
MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, name, desc));
const std::vector<VkExternalMemoryHandleTypeFlagBits> externalMemoryTypes =
{
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
};
for (const auto externalMemoryType : externalMemoryTypes)
{
const std::string testName = std::string("import_and_unimport_") + std::string(externalMemoryTypeToName(externalMemoryType));
addFunctionCase(group.get(), testName.c_str(), "", checkSupport, testImportAndUnimportExternalMemory, externalMemoryType);
}
return group.release();
}
} // anonymous
tcu::TestCaseGroup* createDeviceMemoryReportTests (tcu::TestContext& testCtx)
{
MovePtr<tcu::TestCaseGroup> deviceMemoryReportTests (new tcu::TestCaseGroup(testCtx, "device_memory_report", "Device Memory Report tests"));
const Image::Parameters img1D (0u,
VK_IMAGE_TYPE_1D,
VK_FORMAT_R8G8B8A8_UNORM,
makeExtent3D(256, 1, 1),
1u,
4u,
VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_LAYOUT_UNDEFINED);
const Image::Parameters img2D (0u,
VK_IMAGE_TYPE_2D,
VK_FORMAT_R8G8B8A8_UNORM,
makeExtent3D(64, 64, 1),
1u,
12u,
VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_IMAGE_LAYOUT_UNDEFINED);
const Image::Parameters imgCube (VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
VK_IMAGE_TYPE_2D,
VK_FORMAT_R8G8B8A8_UNORM,
makeExtent3D(64, 64, 1),
1u,
12u,
VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_IMAGE_LAYOUT_UNDEFINED);
const Image::Parameters img3D (0u,
VK_IMAGE_TYPE_3D,
VK_FORMAT_R8G8B8A8_UNORM,
makeExtent3D(64, 64, 4),
1u,
1u,
VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_SAMPLED_BIT,
VK_IMAGE_LAYOUT_UNDEFINED);
const ImageView::Parameters imgView1D (img1D,
VK_IMAGE_VIEW_TYPE_1D,
img1D.format,
makeComponentMappingRGBA(),
makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
const ImageView::Parameters imgView1DArr (img1D,
VK_IMAGE_VIEW_TYPE_1D_ARRAY,
img1D.format,
makeComponentMappingRGBA(),
makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 4u));
const ImageView::Parameters imgView2D (img2D,
VK_IMAGE_VIEW_TYPE_2D,
img2D.format,
makeComponentMappingRGBA(),
makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
const ImageView::Parameters imgView2DArr (img2D,
VK_IMAGE_VIEW_TYPE_2D_ARRAY,
img2D.format,
makeComponentMappingRGBA(),
makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 8u));
const ImageView::Parameters imgViewCube (imgCube,VK_IMAGE_VIEW_TYPE_CUBE,
img2D.format,
makeComponentMappingRGBA(),
makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 6u));
const ImageView::Parameters imgViewCubeArr (imgCube,
VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,
img2D.format,
makeComponentMappingRGBA(),
makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 12u));
const ImageView::Parameters imgView3D (img3D,
VK_IMAGE_VIEW_TYPE_3D,
img3D.format,
makeComponentMappingRGBA(),
makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
const DescriptorSetLayout::Parameters singleUboDescLayout = DescriptorSetLayout::Parameters::single(0u, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, VK_SHADER_STAGE_VERTEX_BIT);
const NamedParameters<Device> s_deviceCases[] =
{
{ "device", Device::Parameters() },
};
static const NamedParameters<DeviceMemory> s_deviceMemCases[] =
{
{ "device_memory_small", DeviceMemory::Parameters(1024, 0u) },
};
static const NamedParameters<Buffer> s_bufferCases[] =
{
{ "buffer_uniform_small", Buffer::Parameters(1024u, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT), },
{ "buffer_uniform_large", Buffer::Parameters(1024u*1024u*16u, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT), },
{ "buffer_storage_small", Buffer::Parameters(1024u, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), },
{ "buffer_storage_large", Buffer::Parameters(1024u*1024u*16u, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), },
};
static const NamedParameters<BufferView> s_bufferViewCases[] =
{
{ "buffer_view_uniform_r8g8b8a8_unorm", BufferView::Parameters(Buffer::Parameters(8192u, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT), VK_FORMAT_R8G8B8A8_UNORM, 0u, 4096u) },
{ "buffer_view_storage_r8g8b8a8_unorm", BufferView::Parameters(Buffer::Parameters(8192u, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), VK_FORMAT_R8G8B8A8_UNORM, 0u, 4096u) },
};
static const NamedParameters<Image> s_imageCases[] =
{
{ "image_1d", img1D },
{ "image_2d", img2D },
{ "image_3d", img3D },
};
static const NamedParameters<ImageView> s_imageViewCases[] =
{
{ "image_view_1d", imgView1D },
{ "image_view_1d_arr", imgView1DArr },
{ "image_view_2d", imgView2D },
{ "image_view_2d_arr", imgView2DArr },
{ "image_view_cube", imgViewCube },
{ "image_view_cube_arr", imgViewCubeArr },
{ "image_view_3d", imgView3D },
};
static const NamedParameters<Semaphore> s_semaphoreCases[] =
{
{ "semaphore", Semaphore::Parameters(0u), }
};
static const NamedParameters<Event> s_eventCases[] =
{
{ "event", Event::Parameters(0u) }
};
static const NamedParameters<Fence> s_fenceCases[] =
{
{ "fence", Fence::Parameters(0u) },
{ "fence_signaled", Fence::Parameters(VK_FENCE_CREATE_SIGNALED_BIT) }
};
static const NamedParameters<QueryPool> s_queryPoolCases[] =
{
{ "query_pool", QueryPool::Parameters(VK_QUERY_TYPE_OCCLUSION, 1u, 0u) }
};
static const NamedParameters<ShaderModule> s_shaderModuleCases[] =
{
{ "shader_module", ShaderModule::Parameters(VK_SHADER_STAGE_COMPUTE_BIT, "test") }
};
static const NamedParameters<PipelineCache> s_pipelineCacheCases[] =
{
{ "pipeline_cache", PipelineCache::Parameters() }
};
static const NamedParameters<Sampler> s_samplerCases[] =
{
{ "sampler", Sampler::Parameters() }
};
static const NamedParameters<DescriptorSetLayout> s_descriptorSetLayoutCases[] =
{
{ "descriptor_set_layout_empty", DescriptorSetLayout::Parameters::empty() },
{ "descriptor_set_layout_single", singleUboDescLayout }
};
static const NamedParameters<PipelineLayout> s_pipelineLayoutCases[] =
{
{ "pipeline_layout_empty", PipelineLayout::Parameters::empty() },
{ "pipeline_layout_single", PipelineLayout::Parameters::singleDescriptorSet(singleUboDescLayout) }
};
static const NamedParameters<RenderPass> s_renderPassCases[] =
{
{ "render_pass", RenderPass::Parameters() }
};
static const NamedParameters<GraphicsPipeline> s_graphicsPipelineCases[] =
{
{ "graphics_pipeline", GraphicsPipeline::Parameters() }
};
static const NamedParameters<ComputePipeline> s_computePipelineCases[] =
{
{ "compute_pipeline", ComputePipeline::Parameters() }
};
static const NamedParameters<DescriptorPool> s_descriptorPoolCases[] =
{
{ "descriptor_pool", DescriptorPool::Parameters::singleType((VkDescriptorPoolCreateFlags)0, 4u, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u) },
{ "descriptor_pool_free_descriptor_set", DescriptorPool::Parameters::singleType(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 4u, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u) }
};
static const NamedParameters<DescriptorSet> s_descriptorSetCases[] =
{
{ "descriptor_set", DescriptorSet::Parameters(singleUboDescLayout) }
};
static const NamedParameters<Framebuffer> s_framebufferCases[] =
{
{ "framebuffer", Framebuffer::Parameters() }
};
static const NamedParameters<CommandPool> s_commandPoolCases[] =
{
{ "command_pool", CommandPool::Parameters((VkCommandPoolCreateFlags)0) },
{ "command_pool_transient", CommandPool::Parameters(VK_COMMAND_POOL_CREATE_TRANSIENT_BIT) }
};
static const NamedParameters<CommandBuffer> s_commandBufferCases[] =
{
{ "command_buffer_primary", CommandBuffer::Parameters(CommandPool::Parameters((VkCommandPoolCreateFlags)0u), VK_COMMAND_BUFFER_LEVEL_PRIMARY) },
{ "command_buffer_secondary", CommandBuffer::Parameters(CommandPool::Parameters((VkCommandPoolCreateFlags)0u), VK_COMMAND_BUFFER_LEVEL_SECONDARY) }
};
const CaseDescriptions s_createDestroyObjectGroup =
{
CASE_DESC(createDestroyObjectTest <Device>, s_deviceCases),
CASE_DESC(createDestroyObjectTest <DeviceMemory>, s_deviceMemCases),
CASE_DESC(createDestroyObjectTest <Buffer>, s_bufferCases),
CASE_DESC(createDestroyObjectTest <BufferView>, s_bufferViewCases),
CASE_DESC(createDestroyObjectTest <Image>, s_imageCases),
CASE_DESC(createDestroyObjectTest <ImageView>, s_imageViewCases),
CASE_DESC(createDestroyObjectTest <Semaphore>, s_semaphoreCases),
CASE_DESC(createDestroyObjectTest <Event>, s_eventCases),
CASE_DESC(createDestroyObjectTest <Fence>, s_fenceCases),
CASE_DESC(createDestroyObjectTest <QueryPool>, s_queryPoolCases),
CASE_DESC(createDestroyObjectTest <ShaderModule>, s_shaderModuleCases),
CASE_DESC(createDestroyObjectTest <PipelineCache>, s_pipelineCacheCases),
CASE_DESC(createDestroyObjectTest <Sampler>, s_samplerCases),
CASE_DESC(createDestroyObjectTest <DescriptorSetLayout>, s_descriptorSetLayoutCases),
CASE_DESC(createDestroyObjectTest <PipelineLayout>, s_pipelineLayoutCases),
CASE_DESC(createDestroyObjectTest <RenderPass>, s_renderPassCases),
CASE_DESC(createDestroyObjectTest <GraphicsPipeline>, s_graphicsPipelineCases),
CASE_DESC(createDestroyObjectTest <ComputePipeline>, s_computePipelineCases),
CASE_DESC(createDestroyObjectTest <DescriptorPool>, s_descriptorPoolCases),
CASE_DESC(createDestroyObjectTest <DescriptorSet>, s_descriptorSetCases),
CASE_DESC(createDestroyObjectTest <Framebuffer>, s_framebufferCases),
CASE_DESC(createDestroyObjectTest <CommandPool>, s_commandPoolCases),
CASE_DESC(createDestroyObjectTest <CommandBuffer>, s_commandBufferCases),
};
deviceMemoryReportTests->addChild(createObjectTestsGroup(testCtx, "create_and_destroy_object", "Check emitted callbacks are properly paired", s_createDestroyObjectGroup));
deviceMemoryReportTests->addChild(createVkDeviceMemoryTestsGroup(testCtx, "vk_device_memory", "Check callbacks are emitted properly for VkDeviceMemory"));
deviceMemoryReportTests->addChild(createExternalMemoryTestsGroup(testCtx, "external_memory", "Check callbacks are emitted properly for external memory"));
return deviceMemoryReportTests.release();
}
} // memory
} // vkt