blob: 9cd92f78f6220127d58f82b35bc7ed0b1f118b62 [file] [log] [blame]
/*-------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2015 Google Inc.
*
* 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 Vulkan test case base classes
*//*--------------------------------------------------------------------*/
#include "vktTestCase.hpp"
#include "vkRef.hpp"
#include "vkRefUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkDeviceUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkPlatform.hpp"
#include "vkDebugReportUtil.hpp"
#include "tcuCommandLine.hpp"
#include "tcuTestLog.hpp"
#include "deSTLUtil.hpp"
#include "deMemory.h"
#include <vkrunner/vkrunner.h>
#include <set>
namespace vkt
{
// Default device utilities
using std::vector;
using std::string;
using std::set;
using namespace vk;
namespace
{
vector<string> getValidationLayers (const vector<VkLayerProperties>& supportedLayers)
{
static const char* s_magicLayer = "VK_LAYER_LUNARG_standard_validation";
static const char* s_defaultLayers[] =
{
"VK_LAYER_GOOGLE_threading",
"VK_LAYER_LUNARG_parameter_validation",
"VK_LAYER_LUNARG_device_limits",
"VK_LAYER_LUNARG_object_tracker",
"VK_LAYER_LUNARG_image",
"VK_LAYER_LUNARG_core_validation",
"VK_LAYER_LUNARG_swapchain",
"VK_LAYER_GOOGLE_unique_objects"
};
vector<string> enabledLayers;
if (isLayerSupported(supportedLayers, RequiredLayer(s_magicLayer)))
enabledLayers.push_back(s_magicLayer);
else
{
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_defaultLayers); ++ndx)
{
if (isLayerSupported(supportedLayers, RequiredLayer(s_defaultLayers[ndx])))
enabledLayers.push_back(s_defaultLayers[ndx]);
}
}
return enabledLayers;
}
vector<string> getValidationLayers (const PlatformInterface& vkp)
{
return getValidationLayers(enumerateInstanceLayerProperties(vkp));
}
vector<string> getValidationLayers (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
{
return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice));
}
vector<string> filterExtensions (const vector<VkExtensionProperties>& extensions)
{
vector<string> enabledExtensions;
const char* extensionGroups[] =
{
"VK_KHR_",
"VK_EXT_",
"VK_KHX_"
};
for (size_t extNdx = 0; extNdx < extensions.size(); extNdx++)
{
for (int extGroupNdx = 0; extGroupNdx < DE_LENGTH_OF_ARRAY(extensionGroups); extGroupNdx++)
{
if (deStringBeginsWith(extensions[extNdx].extensionName, extensionGroups[extGroupNdx]))
enabledExtensions.push_back(extensions[extNdx].extensionName);
}
}
return enabledExtensions;
}
vector<string> addExtensions (const vector<string>& a, const vector<const char*>& b)
{
vector<string> res (a);
for (vector<const char*>::const_iterator bIter = b.begin(); bIter != b.end(); ++bIter)
{
if (!de::contains(res.begin(), res.end(), string(*bIter)))
res.push_back(string(*bIter));
}
return res;
}
vector<string> removeExtensions (const vector<string>& a, const vector<const char*>& b)
{
vector<string> res;
set<string> removeExts (b.begin(), b.end());
for (vector<string>::const_iterator aIter = a.begin(); aIter != a.end(); ++aIter)
{
if (!de::contains(removeExts, *aIter))
res.push_back(*aIter);
}
return res;
}
vector<string> addCoreInstanceExtensions (const vector<string>& extensions, deUint32 instanceVersion)
{
vector<const char*> coreExtensions;
getCoreInstanceExtensions(instanceVersion, coreExtensions);
return addExtensions(extensions, coreExtensions);
}
vector<string> addCoreDeviceExtensions(const vector<string>& extensions, deUint32 instanceVersion)
{
vector<const char*> coreExtensions;
getCoreDeviceExtensions(instanceVersion, coreExtensions);
return addExtensions(extensions, coreExtensions);
}
deUint32 getTargetInstanceVersion (const PlatformInterface& vkp)
{
deUint32 version = pack(ApiVersion(1, 0, 0));
if (vkp.enumerateInstanceVersion(&version) != VK_SUCCESS)
TCU_THROW(InternalError, "Enumerate instance version error");
return version;
}
std::pair<deUint32, deUint32> determineDeviceVersions(const PlatformInterface& vkp, deUint32 apiVersion, const tcu::CommandLine& cmdLine)
{
Move<VkInstance> preinstance = createDefaultInstance(vkp, apiVersion);
InstanceDriver preinterface (vkp, preinstance.get());
const vector<VkPhysicalDevice> devices = enumeratePhysicalDevices(preinterface, preinstance.get());
deUint32 lowestDeviceVersion = 0xFFFFFFFFu;
for (deUint32 deviceNdx = 0u; deviceNdx < devices.size(); ++deviceNdx)
{
const VkPhysicalDeviceProperties props = getPhysicalDeviceProperties(preinterface, devices[deviceNdx]);
if (props.apiVersion < lowestDeviceVersion)
lowestDeviceVersion = props.apiVersion;
}
const vk::VkPhysicalDevice choosenDevice = chooseDevice(preinterface, *preinstance, cmdLine);
const VkPhysicalDeviceProperties props = getPhysicalDeviceProperties(preinterface, choosenDevice);
const deUint32 choosenDeviceVersion = props.apiVersion;
return std::make_pair(choosenDeviceVersion, lowestDeviceVersion);
}
Move<VkInstance> createInstance (const PlatformInterface& vkp, deUint32 apiVersion, const vector<string>& enabledExtensions, const tcu::CommandLine& cmdLine)
{
const bool isValidationEnabled = cmdLine.isValidationEnabled();
vector<string> enabledLayers;
// \note Extensions in core are not explicitly enabled even though
// they are in the extension list advertised to tests.
vector<const char*> coreExtensions;
getCoreInstanceExtensions(apiVersion, coreExtensions);
vector<string> nonCoreExtensions (removeExtensions(enabledExtensions, coreExtensions));
if (isValidationEnabled)
{
if (!isDebugReportSupported(vkp))
TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported");
enabledLayers = getValidationLayers(vkp);
if (enabledLayers.empty())
TCU_THROW(NotSupportedError, "No validation layers found");
}
return createDefaultInstance(vkp, apiVersion, enabledLayers, nonCoreExtensions);
}
static deUint32 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
{
const vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice);
for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
{
if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps)
return (deUint32)queueNdx;
}
TCU_THROW(NotSupportedError, "No matching queue found");
}
Move<VkDevice> createDefaultDevice (const PlatformInterface& vkp,
VkInstance instance,
const InstanceInterface& vki,
VkPhysicalDevice physicalDevice,
const deUint32 apiVersion,
deUint32 queueIndex,
deUint32 sparseQueueIndex,
const VkPhysicalDeviceFeatures2& enabledFeatures,
const vector<string>& enabledExtensions,
const tcu::CommandLine& cmdLine)
{
VkDeviceQueueCreateInfo queueInfo[2];
VkDeviceCreateInfo deviceInfo;
vector<string> enabledLayers;
vector<const char*> layerPtrs;
vector<const char*> extensionPtrs;
const float queuePriority = 1.0f;
const deUint32 numQueues = (enabledFeatures.features.sparseBinding && (queueIndex != sparseQueueIndex)) ? 2 : 1;
deMemset(&queueInfo, 0, sizeof(queueInfo));
deMemset(&deviceInfo, 0, sizeof(deviceInfo));
if (cmdLine.isValidationEnabled())
{
enabledLayers = getValidationLayers(vki, physicalDevice);
if (enabledLayers.empty())
TCU_THROW(NotSupportedError, "No validation layers found");
}
layerPtrs.resize(enabledLayers.size());
for (size_t ndx = 0; ndx < enabledLayers.size(); ++ndx)
layerPtrs[ndx] = enabledLayers[ndx].c_str();
// \note Extensions in core are not explicitly enabled even though
// they are in the extension list advertised to tests.
vector<const char*> coreExtensions;
getCoreDeviceExtensions(apiVersion, coreExtensions);
vector<string> nonCoreExtensions(removeExtensions(enabledExtensions, coreExtensions));
extensionPtrs.resize(nonCoreExtensions.size());
for (size_t ndx = 0; ndx < nonCoreExtensions.size(); ++ndx)
extensionPtrs[ndx] = nonCoreExtensions[ndx].c_str();
queueInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueInfo[0].pNext = DE_NULL;
queueInfo[0].flags = (VkDeviceQueueCreateFlags)0u;
queueInfo[0].queueFamilyIndex = queueIndex;
queueInfo[0].queueCount = 1u;
queueInfo[0].pQueuePriorities = &queuePriority;
if (numQueues > 1)
{
queueInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueInfo[1].pNext = DE_NULL;
queueInfo[1].flags = (VkDeviceQueueCreateFlags)0u;
queueInfo[1].queueFamilyIndex = sparseQueueIndex;
queueInfo[1].queueCount = 1u;
queueInfo[1].pQueuePriorities = &queuePriority;
}
// VK_KHR_get_physical_device_properties2 is used if enabledFeatures.pNext != 0
deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
deviceInfo.pNext = enabledFeatures.pNext ? &enabledFeatures : DE_NULL;
deviceInfo.queueCreateInfoCount = numQueues;
deviceInfo.pQueueCreateInfos = queueInfo;
deviceInfo.enabledExtensionCount = (deUint32)extensionPtrs.size();
deviceInfo.ppEnabledExtensionNames = (extensionPtrs.empty() ? DE_NULL : &extensionPtrs[0]);
deviceInfo.enabledLayerCount = (deUint32)layerPtrs.size();
deviceInfo.ppEnabledLayerNames = (layerPtrs.empty() ? DE_NULL : &layerPtrs[0]);
deviceInfo.pEnabledFeatures = enabledFeatures.pNext ? DE_NULL : &enabledFeatures.features;
return createDevice(vkp, instance, vki, physicalDevice, &deviceInfo);
};
bool isPhysicalDeviceFeatures2Supported (const deUint32 version, const vector<string>& instanceExtensions)
{
return isInstanceExtensionSupported(version, instanceExtensions, "VK_KHR_get_physical_device_properties2");
}
class DeviceFeatures
{
public:
VkPhysicalDeviceFeatures2 coreFeatures;
VkPhysicalDeviceSamplerYcbcrConversionFeatures samplerYCbCrConversionFeatures;
VkPhysicalDevice8BitStorageFeaturesKHR eightBitStorageFeatures;
VkPhysicalDevice16BitStorageFeatures sixteenBitStorageFeatures;
VkPhysicalDeviceVariablePointerFeatures variablePointerFeatures;
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertexAttributeDivisorFeatures;
VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptorIndexingFeatures;
VkPhysicalDeviceInlineUniformBlockFeaturesEXT inlineUniformBlockFeatures;
VkPhysicalDeviceVulkanMemoryModelFeaturesKHR vulkanMemoryModelFeatures;
VkPhysicalDeviceShaderAtomicInt64FeaturesKHR shaderAtomicInt64Features;
VkPhysicalDeviceConditionalRenderingFeaturesEXT conditionalRenderingFeatures;
VkPhysicalDeviceScalarBlockLayoutFeaturesEXT scalarBlockLayoutFeatures;
VkPhysicalDeviceFloat16Int8FeaturesKHR float16Int8Features;
DeviceFeatures (const InstanceInterface& vki,
const deUint32 apiVersion,
const VkPhysicalDevice& physicalDevice,
const vector<string>& instanceExtensions,
const vector<string>& deviceExtensions)
{
deMemset(&coreFeatures, 0, sizeof(coreFeatures));
deMemset(&samplerYCbCrConversionFeatures, 0, sizeof(samplerYCbCrConversionFeatures));
deMemset(&eightBitStorageFeatures, 0, sizeof(eightBitStorageFeatures));
deMemset(&sixteenBitStorageFeatures, 0, sizeof(sixteenBitStorageFeatures));
deMemset(&variablePointerFeatures, 0, sizeof(variablePointerFeatures));
deMemset(&descriptorIndexingFeatures, 0, sizeof(descriptorIndexingFeatures));
deMemset(&inlineUniformBlockFeatures, 0, sizeof(inlineUniformBlockFeatures));
deMemset(&float16Int8Features, 0, sizeof(float16Int8Features));
deMemset(&vertexAttributeDivisorFeatures, 0, sizeof(vertexAttributeDivisorFeatures));
deMemset(&descriptorIndexingFeatures, 0, sizeof(descriptorIndexingFeatures));
deMemset(&inlineUniformBlockFeatures, 0, sizeof(inlineUniformBlockFeatures));
deMemset(&vulkanMemoryModelFeatures, 0, sizeof(vulkanMemoryModelFeatures));
deMemset(&shaderAtomicInt64Features, 0, sizeof(shaderAtomicInt64Features));
deMemset(&conditionalRenderingFeatures, 0, sizeof(conditionalRenderingFeatures));
deMemset(&scalarBlockLayoutFeatures, 0, sizeof(scalarBlockLayoutFeatures));
coreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
samplerYCbCrConversionFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
eightBitStorageFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR;
sixteenBitStorageFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR;
variablePointerFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR;
descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
inlineUniformBlockFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT;
float16Int8Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
vertexAttributeDivisorFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
inlineUniformBlockFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT;
vulkanMemoryModelFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR;
shaderAtomicInt64Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR;
conditionalRenderingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT;
scalarBlockLayoutFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT;
vector<VkExtensionProperties> deviceExtensionProperties =
enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);
if (isPhysicalDeviceFeatures2Supported(apiVersion, instanceExtensions))
{
void** nextPtr = &coreFeatures.pNext;
if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_KHR_sampler_ycbcr_conversion"))
{
*nextPtr = &samplerYCbCrConversionFeatures;
nextPtr = &samplerYCbCrConversionFeatures.pNext;
}
if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_KHR_8bit_storage"))
{
*nextPtr = &eightBitStorageFeatures;
nextPtr = &eightBitStorageFeatures.pNext;
}
if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_KHR_16bit_storage"))
{
*nextPtr = &sixteenBitStorageFeatures;
nextPtr = &sixteenBitStorageFeatures.pNext;
}
if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_KHR_variable_pointers"))
{
*nextPtr = &variablePointerFeatures;
nextPtr = &variablePointerFeatures.pNext;
}
if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_EXT_descriptor_indexing"))
{
*nextPtr = &descriptorIndexingFeatures;
nextPtr = &descriptorIndexingFeatures.pNext;
}
if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_EXT_inline_uniform_block"))
{
*nextPtr = &inlineUniformBlockFeatures;
nextPtr = &inlineUniformBlockFeatures.pNext;
}
if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_KHR_shader_float16_int8"))
{
*nextPtr = &float16Int8Features;
nextPtr = &float16Int8Features.pNext;
}
if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_EXT_vertex_attribute_divisor"))
{
*nextPtr = &vertexAttributeDivisorFeatures;
nextPtr = &vertexAttributeDivisorFeatures.pNext;
}
if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_KHR_vulkan_memory_model"))
{
for (size_t i = 0; i < deviceExtensionProperties.size(); ++i)
{
if (deStringEqual(deviceExtensionProperties[i].extensionName, "VK_KHR_vulkan_memory_model"))
{
if (deviceExtensionProperties[i].specVersion == VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION)
{
*nextPtr = &vulkanMemoryModelFeatures;
nextPtr = &vulkanMemoryModelFeatures.pNext;
}
break;
}
}
}
if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_KHR_shader_atomic_int64"))
{
*nextPtr = &shaderAtomicInt64Features;
nextPtr = &shaderAtomicInt64Features.pNext;
}
if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_EXT_conditional_rendering"))
{
*nextPtr = &conditionalRenderingFeatures;
nextPtr = &conditionalRenderingFeatures.pNext;
}
if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_EXT_scalar_block_layout"))
{
*nextPtr = &scalarBlockLayoutFeatures;
nextPtr = &scalarBlockLayoutFeatures.pNext;
}
vki.getPhysicalDeviceFeatures2(physicalDevice, &coreFeatures);
}
else
coreFeatures.features = getPhysicalDeviceFeatures(vki, physicalDevice);
// Disable robustness by default, as it has an impact on performance on some HW.
coreFeatures.features.robustBufferAccess = false;
}
};
} // anonymous
class DefaultDevice
{
public:
DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine);
~DefaultDevice (void);
VkInstance getInstance (void) const { return *m_instance; }
const InstanceInterface& getInstanceInterface (void) const { return m_instanceInterface; }
deUint32 getAvailableInstanceVersion (void) const { return m_availableInstanceVersion; }
const vector<string>& getInstanceExtensions (void) const { return m_instanceExtensions; }
VkPhysicalDevice getPhysicalDevice (void) const { return m_physicalDevice; }
deUint32 getDeviceVersion (void) const { return m_deviceVersion; }
const VkPhysicalDeviceFeatures& getDeviceFeatures (void) const { return m_deviceFeatures.coreFeatures.features; }
const VkPhysicalDeviceFeatures2& getDeviceFeatures2 (void) const { return m_deviceFeatures.coreFeatures; }
const VkPhysicalDeviceSamplerYcbcrConversionFeatures& getSamplerYCbCrConversionFeatures (void) const { return m_deviceFeatures.samplerYCbCrConversionFeatures; }
const VkPhysicalDevice8BitStorageFeaturesKHR& get8BitStorageFeatures (void) const { return m_deviceFeatures.eightBitStorageFeatures; }
const VkPhysicalDevice16BitStorageFeatures& get16BitStorageFeatures (void) const { return m_deviceFeatures.sixteenBitStorageFeatures; }
const VkPhysicalDeviceVariablePointerFeatures& getVariablePointerFeatures (void) const { return m_deviceFeatures.variablePointerFeatures; }
const VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT&getVertexAttributeDivisorFeatures (void) const { return m_deviceFeatures.vertexAttributeDivisorFeatures; }
const VkPhysicalDeviceVulkanMemoryModelFeaturesKHR& getVulkanMemoryModelFeatures (void) const { return m_deviceFeatures.vulkanMemoryModelFeatures; }
const VkPhysicalDeviceShaderAtomicInt64FeaturesKHR& getShaderAtomicInt64Features (void) const { return m_deviceFeatures.shaderAtomicInt64Features; }
const VkPhysicalDeviceConditionalRenderingFeaturesEXT& getConditionalRenderingFeatures (void) const { return m_deviceFeatures.conditionalRenderingFeatures; }
const VkPhysicalDeviceScalarBlockLayoutFeaturesEXT& getScalarBlockLayoutFeatures (void) const { return m_deviceFeatures.scalarBlockLayoutFeatures; }
const VkPhysicalDeviceFloat16Int8FeaturesKHR& getFloat16Int8Features (void) const { return m_deviceFeatures.float16Int8Features; }
VkDevice getDevice (void) const { return *m_device; }
const DeviceInterface& getDeviceInterface (void) const { return m_deviceInterface; }
const VkPhysicalDeviceProperties& getDeviceProperties (void) const { return m_deviceProperties; }
const vector<string>& getDeviceExtensions (void) const { return m_deviceExtensions; }
deUint32 getUsedApiVersion (void) const { return m_usedApiVersion; }
deUint32 getUniversalQueueFamilyIndex (void) const { return m_universalQueueFamilyIndex; }
VkQueue getUniversalQueue (void) const;
deUint32 getSparseQueueFamilyIndex (void) const { return m_sparseQueueFamilyIndex; }
VkQueue getSparseQueue (void) const;
private:
const deUint32 m_availableInstanceVersion;
const std::pair<deUint32, deUint32> m_deviceVersions;
const deUint32 m_usedApiVersion;
const vector<string> m_instanceExtensions;
const Unique<VkInstance> m_instance;
const InstanceDriver m_instanceInterface;
const VkPhysicalDevice m_physicalDevice;
const deUint32 m_deviceVersion;
const vector<string> m_deviceExtensions;
const DeviceFeatures m_deviceFeatures;
const deUint32 m_universalQueueFamilyIndex;
const deUint32 m_sparseQueueFamilyIndex;
const VkPhysicalDeviceProperties m_deviceProperties;
const Unique<VkDevice> m_device;
const DeviceDriver m_deviceInterface;
};
static deUint32 sanitizeApiVersion(deUint32 v)
{
return VK_MAKE_VERSION( VK_VERSION_MAJOR(v), VK_VERSION_MINOR(v), 0 );
}
DefaultDevice::DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine)
: m_availableInstanceVersion (getTargetInstanceVersion(vkPlatform))
, m_deviceVersions (determineDeviceVersions(vkPlatform, m_availableInstanceVersion, cmdLine))
, m_usedApiVersion (sanitizeApiVersion(deMinu32(m_availableInstanceVersion, m_deviceVersions.first)))
, m_instanceExtensions (addCoreInstanceExtensions(filterExtensions(enumerateInstanceExtensionProperties(vkPlatform, DE_NULL)), m_usedApiVersion))
, m_instance (createInstance(vkPlatform, m_usedApiVersion, m_instanceExtensions, cmdLine))
, m_instanceInterface (vkPlatform, *m_instance)
, m_physicalDevice (chooseDevice(m_instanceInterface, *m_instance, cmdLine))
, m_deviceVersion (getPhysicalDeviceProperties(m_instanceInterface, m_physicalDevice).apiVersion)
, m_deviceExtensions (addCoreDeviceExtensions(filterExtensions(enumerateDeviceExtensionProperties(m_instanceInterface, m_physicalDevice, DE_NULL)), m_usedApiVersion))
, m_deviceFeatures (m_instanceInterface, m_usedApiVersion, m_physicalDevice, m_instanceExtensions, m_deviceExtensions)
, m_universalQueueFamilyIndex (findQueueFamilyIndexWithCaps(m_instanceInterface, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT))
, m_sparseQueueFamilyIndex (m_deviceFeatures.coreFeatures.features.sparseBinding ? findQueueFamilyIndexWithCaps(m_instanceInterface, m_physicalDevice, VK_QUEUE_SPARSE_BINDING_BIT) : 0)
, m_deviceProperties (getPhysicalDeviceProperties(m_instanceInterface, m_physicalDevice))
, m_device (createDefaultDevice(vkPlatform, *m_instance, m_instanceInterface, m_physicalDevice, m_usedApiVersion, m_universalQueueFamilyIndex, m_sparseQueueFamilyIndex, m_deviceFeatures.coreFeatures, m_deviceExtensions, cmdLine))
, m_deviceInterface (vkPlatform, *m_instance, *m_device)
{
DE_ASSERT(m_deviceVersions.first == m_deviceVersion);
}
DefaultDevice::~DefaultDevice (void)
{
}
VkQueue DefaultDevice::getUniversalQueue (void) const
{
return getDeviceQueue(m_deviceInterface, *m_device, m_universalQueueFamilyIndex, 0);
}
VkQueue DefaultDevice::getSparseQueue (void) const
{
if (!m_deviceFeatures.coreFeatures.features.sparseBinding)
TCU_THROW(NotSupportedError, "Sparse binding not supported.");
return getDeviceQueue(m_deviceInterface, *m_device, m_sparseQueueFamilyIndex, 0);
}
namespace
{
// Allocator utilities
vk::Allocator* createAllocator (DefaultDevice* device)
{
const VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(device->getInstanceInterface(), device->getPhysicalDevice());
// \todo [2015-07-24 jarkko] support allocator selection/configuration from command line (or compile time)
return new SimpleAllocator(device->getDeviceInterface(), device->getDevice(), memoryProperties);
}
} // anonymous
// Context
void Context::errorCb(const char* message,
void* user_data)
{
Context* context = (Context*) user_data;
context->getTestContext().getLog()
<< tcu::TestLog::Message
<< message
<< "\n"
<< tcu::TestLog::EndMessage;
}
Context::Context (tcu::TestContext& testCtx,
const vk::PlatformInterface& platformInterface,
vk::BinaryCollection& progCollection)
: m_testCtx (testCtx)
, m_platformInterface (platformInterface)
, m_progCollection (progCollection)
, m_device (new DefaultDevice(m_platformInterface, testCtx.getCommandLine()))
, m_allocator (createAllocator(m_device.get()))
{
m_config = vr_config_new();
vr_config_set_user_data(m_config, this);
vr_config_set_error_cb(m_config, errorCb);
m_executor = vr_executor_new(m_config);
vr_executor_set_device(m_executor,
getInstanceProc,
this,
getPhysicalDevice(),
getUniversalQueueFamilyIndex(),
getDevice());
}
Context::~Context (void)
{
vr_config_free(m_config);
vr_executor_free(m_executor);
}
deUint32 Context::getAvailableInstanceVersion (void) const { return m_device->getAvailableInstanceVersion(); }
const vector<string>& Context::getInstanceExtensions (void) const { return m_device->getInstanceExtensions(); }
vk::VkInstance Context::getInstance (void) const { return m_device->getInstance(); }
const vk::InstanceInterface& Context::getInstanceInterface (void) const { return m_device->getInstanceInterface(); }
vk::VkPhysicalDevice Context::getPhysicalDevice (void) const { return m_device->getPhysicalDevice(); }
deUint32 Context::getDeviceVersion (void) const { return m_device->getDeviceVersion(); }
const vk::VkPhysicalDeviceFeatures& Context::getDeviceFeatures (void) const { return m_device->getDeviceFeatures(); }
const vk::VkPhysicalDeviceFeatures2& Context::getDeviceFeatures2 (void) const { return m_device->getDeviceFeatures2(); }
const vk::VkPhysicalDeviceSamplerYcbcrConversionFeatures&
Context::getSamplerYCbCrConversionFeatures
(void) const { return m_device->getSamplerYCbCrConversionFeatures(); }
const vk::VkPhysicalDevice8BitStorageFeaturesKHR&
Context::get8BitStorageFeatures (void) const { return m_device->get8BitStorageFeatures(); }
const vk::VkPhysicalDevice16BitStorageFeatures&
Context::get16BitStorageFeatures (void) const { return m_device->get16BitStorageFeatures(); }
const vk::VkPhysicalDeviceVariablePointerFeatures&
Context::getVariablePointerFeatures (void) const { return m_device->getVariablePointerFeatures(); }
const vk::VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT&
Context::getVertexAttributeDivisorFeatures (void) const { return m_device->getVertexAttributeDivisorFeatures(); }
const vk::VkPhysicalDeviceVulkanMemoryModelFeaturesKHR&
Context::getVulkanMemoryModelFeatures (void) const { return m_device->getVulkanMemoryModelFeatures(); }
const vk::VkPhysicalDeviceShaderAtomicInt64FeaturesKHR&
Context::getShaderAtomicInt64Features (void) const { return m_device->getShaderAtomicInt64Features(); }
const vk::VkPhysicalDeviceConditionalRenderingFeaturesEXT&
Context::getConditionalRenderingFeatures(void) const { return m_device->getConditionalRenderingFeatures(); }
const vk::VkPhysicalDeviceScalarBlockLayoutFeaturesEXT&
Context::getScalarBlockLayoutFeatures (void) const { return m_device->getScalarBlockLayoutFeatures(); }
const vk::VkPhysicalDeviceFloat16Int8FeaturesKHR&
Context::getFloat16Int8Features (void) const { return m_device->getFloat16Int8Features(); }
const vk::VkPhysicalDeviceProperties& Context::getDeviceProperties (void) const { return m_device->getDeviceProperties(); }
const vector<string>& Context::getDeviceExtensions (void) const { return m_device->getDeviceExtensions(); }
vk::VkDevice Context::getDevice (void) const { return m_device->getDevice(); }
const vk::DeviceInterface& Context::getDeviceInterface (void) const { return m_device->getDeviceInterface(); }
deUint32 Context::getUniversalQueueFamilyIndex (void) const { return m_device->getUniversalQueueFamilyIndex(); }
vk::VkQueue Context::getUniversalQueue (void) const { return m_device->getUniversalQueue(); }
deUint32 Context::getSparseQueueFamilyIndex (void) const { return m_device->getSparseQueueFamilyIndex(); }
vk::VkQueue Context::getSparseQueue (void) const { return m_device->getSparseQueue(); }
vk::Allocator& Context::getDefaultAllocator (void) const { return *m_allocator; }
deUint32 Context::getUsedApiVersion (void) const { return m_device->getUsedApiVersion(); }
vr_executor* Context::getExecutor (void) const
{ return m_executor; }
bool Context::contextSupports (const deUint32 majorNum, const deUint32 minorNum, const deUint32 patchNum) const
{ return m_device->getUsedApiVersion() >= VK_MAKE_VERSION(majorNum, minorNum, patchNum); }
bool Context::contextSupports (const ApiVersion version) const
{ return m_device->getUsedApiVersion() >= pack(version); }
bool Context::contextSupports (const deUint32 requiredApiVersionBits) const
{ return m_device->getUsedApiVersion() >= requiredApiVersionBits; }
bool Context::requireDeviceExtension (const std::string& required)
{
if (!isDeviceExtensionSupported(getUsedApiVersion(), getDeviceExtensions(), required))
TCU_THROW(NotSupportedError, required + " is not supported");
return true;
}
bool Context::requireInstanceExtension (const std::string& required)
{
if (!isInstanceExtensionSupported(getUsedApiVersion(), getInstanceExtensions(), required))
TCU_THROW(NotSupportedError, required + " is not supported");
return true;
}
struct DeviceCoreFeaturesTable
{
const char* featureName;
const deUint32 featureArrayIndex;
const deUint32 featureArrayOffset;
};
#define DEVICE_CORE_FEATURE_OFFSET(FEATURE_FIELD_NAME) DE_OFFSET_OF(VkPhysicalDeviceFeatures, FEATURE_FIELD_NAME)
#define DEVICE_CORE_FEATURE_ENTRY(BITNAME, FIELDNAME) { #FIELDNAME, BITNAME, DEVICE_CORE_FEATURE_OFFSET(FIELDNAME) }
const DeviceCoreFeaturesTable deviceCoreFeaturesTable[] =
{
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_ROBUST_BUFFER_ACCESS , robustBufferAccess ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_FULL_DRAW_INDEX_UINT32 , fullDrawIndexUint32 ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY , imageCubeArray ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_INDEPENDENT_BLEND , independentBlend ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_GEOMETRY_SHADER , geometryShader ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_TESSELLATION_SHADER , tessellationShader ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING , sampleRateShading ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_DUAL_SRC_BLEND , dualSrcBlend ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_LOGIC_OP , logicOp ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_MULTI_DRAW_INDIRECT , multiDrawIndirect ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_DRAW_INDIRECT_FIRST_INSTANCE , drawIndirectFirstInstance ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_DEPTH_CLAMP , depthClamp ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_DEPTH_BIAS_CLAMP , depthBiasClamp ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_FILL_MODE_NON_SOLID , fillModeNonSolid ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_DEPTH_BOUNDS , depthBounds ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_WIDE_LINES , wideLines ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_LARGE_POINTS , largePoints ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_ALPHA_TO_ONE , alphaToOne ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_MULTI_VIEWPORT , multiViewport ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SAMPLER_ANISOTROPY , samplerAnisotropy ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_TEXTURE_COMPRESSION_ETC2 , textureCompressionETC2 ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_TEXTURE_COMPRESSION_ASTC_LDR , textureCompressionASTC_LDR ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_TEXTURE_COMPRESSION_BC , textureCompressionBC ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_OCCLUSION_QUERY_PRECISE , occlusionQueryPrecise ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_PIPELINE_STATISTICS_QUERY , pipelineStatisticsQuery ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS , vertexPipelineStoresAndAtomics ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS , fragmentStoresAndAtomics ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE , shaderTessellationAndGeometryPointSize ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_IMAGE_GATHER_EXTENDED , shaderImageGatherExtended ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_EXTENDED_FORMATS , shaderStorageImageExtendedFormats ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_MULTISAMPLE , shaderStorageImageMultisample ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_READ_WITHOUT_FORMAT , shaderStorageImageReadWithoutFormat ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT , shaderStorageImageWriteWithoutFormat ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING , shaderUniformBufferArrayDynamicIndexing ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_SAMPLED_IMAGE_ARRAY_DYNAMIC_INDEXING , shaderSampledImageArrayDynamicIndexing ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING , shaderStorageBufferArrayDynamicIndexing ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_ARRAY_DYNAMIC_INDEXING , shaderStorageImageArrayDynamicIndexing ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_CLIP_DISTANCE , shaderClipDistance ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_CULL_DISTANCE , shaderCullDistance ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_FLOAT64 , shaderFloat64 ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_INT64 , shaderInt64 ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_INT16 , shaderInt16 ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_RESOURCE_RESIDENCY , shaderResourceResidency ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SHADER_RESOURCE_MIN_LOD , shaderResourceMinLod ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_BINDING , sparseBinding ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY_BUFFER , sparseResidencyBuffer ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY_IMAGE2D , sparseResidencyImage2D ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY_IMAGE3D , sparseResidencyImage3D ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY2_SAMPLES , sparseResidency2Samples ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY4_SAMPLES , sparseResidency4Samples ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY8_SAMPLES , sparseResidency8Samples ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY16_SAMPLES , sparseResidency16Samples ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_SPARSE_RESIDENCY_ALIASED , sparseResidencyAliased ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_VARIABLE_MULTISAMPLE_RATE , variableMultisampleRate ),
DEVICE_CORE_FEATURE_ENTRY(DEVICE_CORE_FEATURE_INHERITED_QUERIES , inheritedQueries ),
};
bool Context::requireDeviceCoreFeature (const DeviceCoreFeature requiredFeature)
{
const vk::VkPhysicalDeviceFeatures& featuresAvailable = getDeviceFeatures();
const vk::VkBool32* featuresAvailableArray = (vk::VkBool32*)(&featuresAvailable);
const deUint32 requiredFeatureIndex = static_cast<deUint32>(requiredFeature);
DE_ASSERT(requiredFeatureIndex * sizeof(vk::VkBool32) < sizeof(featuresAvailable));
DE_ASSERT(deviceCoreFeaturesTable[requiredFeatureIndex].featureArrayIndex * sizeof(vk::VkBool32) == deviceCoreFeaturesTable[requiredFeatureIndex].featureArrayOffset);
if (featuresAvailableArray[requiredFeatureIndex] == DE_FALSE)
TCU_THROW(NotSupportedError, "Requested core feature is not supported: " + std::string(deviceCoreFeaturesTable[requiredFeatureIndex].featureName));
return true;
}
void* Context::getInstanceProc (const char* name, void* user_data)
{
Context *context = (Context*) user_data;
return (void*) context->m_platformInterface.getInstanceProcAddr(context->getInstance(), name);
}
// TestCase
void TestCase::initPrograms (SourceCollections&) const
{
}
void TestCase::checkSupport (Context&) const
{
}
} // vkt