| /*------------------------------------------------------------------------- |
| * 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 "deMemory.h" |
| |
| namespace vkt |
| { |
| |
| // Default device utilities |
| |
| using std::vector; |
| using std::string; |
| using namespace vk; |
| |
| 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>& deviceExtensions) |
| { |
| vector<string> enabledExtensions; |
| const char* extensionGroups[] = |
| { |
| "VK_KHR_", |
| "VK_EXT_", |
| "VK_KHX_" |
| }; |
| |
| for (size_t deviceExtNdx = 0; deviceExtNdx < deviceExtensions.size(); deviceExtNdx++) |
| { |
| for (int extGroupNdx = 0; extGroupNdx < DE_LENGTH_OF_ARRAY(extensionGroups); extGroupNdx++) |
| { |
| if (deStringBeginsWith(deviceExtensions[deviceExtNdx].extensionName, extensionGroups[extGroupNdx])) |
| enabledExtensions.push_back(deviceExtensions[deviceExtNdx].extensionName); |
| } |
| } |
| |
| return enabledExtensions; |
| } |
| |
| Move<VkInstance> createInstance (const PlatformInterface& vkp, const vector<string>& enabledExtensions, const tcu::CommandLine& cmdLine) |
| { |
| const bool isValidationEnabled = cmdLine.isValidationEnabled(); |
| vector<string> enabledLayers; |
| |
| 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, enabledLayers, enabledExtensions); |
| } |
| |
| 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 InstanceInterface& vki, |
| VkPhysicalDevice physicalDevice, |
| deUint32 queueIndex, |
| const VkPhysicalDeviceFeatures& enabledFeatures, |
| const vector<string>& enabledExtensions, |
| const tcu::CommandLine& cmdLine) |
| { |
| VkDeviceQueueCreateInfo queueInfo; |
| VkDeviceCreateInfo deviceInfo; |
| vector<string> enabledLayers; |
| vector<const char*> layerPtrs; |
| vector<const char*> extensionPtrs; |
| const float queuePriority = 1.0f; |
| |
| 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(); |
| |
| extensionPtrs.resize(enabledExtensions.size()); |
| |
| for (size_t ndx = 0; ndx < enabledExtensions.size(); ++ndx) |
| extensionPtrs[ndx] = enabledExtensions[ndx].c_str(); |
| |
| queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; |
| queueInfo.pNext = DE_NULL; |
| queueInfo.flags = (VkDeviceQueueCreateFlags)0u; |
| queueInfo.queueFamilyIndex = queueIndex; |
| queueInfo.queueCount = 1u; |
| queueInfo.pQueuePriorities = &queuePriority; |
| |
| deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; |
| deviceInfo.pNext = DE_NULL; |
| deviceInfo.queueCreateInfoCount = 1u; |
| 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; |
| |
| return createDevice(vki, physicalDevice, &deviceInfo); |
| }; |
| |
| 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; } |
| const vector<string>& getInstanceExtensions (void) const { return m_instanceExtensions; } |
| |
| VkPhysicalDevice getPhysicalDevice (void) const { return m_physicalDevice; } |
| const VkPhysicalDeviceFeatures& getDeviceFeatures (void) const { return m_deviceFeatures; } |
| 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 getUniversalQueueFamilyIndex (void) const { return m_universalQueueFamilyIndex; } |
| VkQueue getUniversalQueue (void) const; |
| |
| private: |
| static VkPhysicalDeviceFeatures filterDefaultDeviceFeatures (const VkPhysicalDeviceFeatures& deviceFeatures); |
| |
| const vector<string> m_instanceExtensions; |
| const Unique<VkInstance> m_instance; |
| const InstanceDriver m_instanceInterface; |
| |
| const VkPhysicalDevice m_physicalDevice; |
| |
| const deUint32 m_universalQueueFamilyIndex; |
| const VkPhysicalDeviceFeatures m_deviceFeatures; |
| const VkPhysicalDeviceProperties m_deviceProperties; |
| const vector<string> m_deviceExtensions; |
| |
| const Unique<VkDevice> m_device; |
| const DeviceDriver m_deviceInterface; |
| }; |
| |
| DefaultDevice::DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine) |
| : m_instanceExtensions (filterExtensions(enumerateInstanceExtensionProperties(vkPlatform, DE_NULL))) |
| , m_instance (createInstance(vkPlatform, m_instanceExtensions, cmdLine)) |
| , m_instanceInterface (vkPlatform, *m_instance) |
| , m_physicalDevice (chooseDevice(m_instanceInterface, *m_instance, cmdLine)) |
| , m_universalQueueFamilyIndex (findQueueFamilyIndexWithCaps(m_instanceInterface, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT)) |
| , m_deviceFeatures (filterDefaultDeviceFeatures(getPhysicalDeviceFeatures(m_instanceInterface, m_physicalDevice))) |
| , m_deviceProperties (getPhysicalDeviceProperties(m_instanceInterface, m_physicalDevice)) |
| , m_deviceExtensions (filterExtensions(enumerateDeviceExtensionProperties(m_instanceInterface, m_physicalDevice, DE_NULL))) |
| , m_device (createDefaultDevice(m_instanceInterface, m_physicalDevice, m_universalQueueFamilyIndex, m_deviceFeatures, m_deviceExtensions, cmdLine)) |
| , m_deviceInterface (m_instanceInterface, *m_device) |
| { |
| } |
| |
| DefaultDevice::~DefaultDevice (void) |
| { |
| } |
| |
| VkQueue DefaultDevice::getUniversalQueue (void) const |
| { |
| return getDeviceQueue(m_deviceInterface, *m_device, m_universalQueueFamilyIndex, 0); |
| } |
| |
| VkPhysicalDeviceFeatures DefaultDevice::filterDefaultDeviceFeatures (const VkPhysicalDeviceFeatures& deviceFeatures) |
| { |
| VkPhysicalDeviceFeatures enabledDeviceFeatures = deviceFeatures; |
| |
| // Disable robustness by default, as it has an impact on performance on some HW. |
| enabledDeviceFeatures.robustBufferAccess = false; |
| |
| return enabledDeviceFeatures; |
| } |
| |
| // 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); |
| } |
| |
| // Context |
| |
| Context::Context (tcu::TestContext& testCtx, |
| const vk::PlatformInterface& platformInterface, |
| vk::ProgramCollection<vk::ProgramBinary>& progCollection) |
| : m_testCtx (testCtx) |
| , m_platformInterface (platformInterface) |
| , m_progCollection (progCollection) |
| , m_device (new DefaultDevice(m_platformInterface, testCtx.getCommandLine())) |
| , m_allocator (createAllocator(m_device.get())) |
| { |
| } |
| |
| Context::~Context (void) |
| { |
| } |
| |
| 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(); } |
| const vk::VkPhysicalDeviceFeatures& Context::getDeviceFeatures (void) const { return m_device->getDeviceFeatures(); } |
| 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(); } |
| vk::Allocator& Context::getDefaultAllocator (void) const { return *m_allocator; } |
| |
| // TestCase |
| |
| void TestCase::initPrograms (SourceCollections&) const |
| { |
| } |
| |
| } // vkt |