| /*------------------------------------------------------------------------- |
| * 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 Device Initialization Tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktApiDeviceInitializationTests.hpp" |
| #include "vktTestCaseUtil.hpp" |
| #include "vktCustomInstancesDevices.hpp" |
| |
| #include "vkDefs.hpp" |
| #include "vkPlatform.hpp" |
| #include "vkStrUtil.hpp" |
| #include "vkRef.hpp" |
| #include "vkRefUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkMemUtil.hpp" |
| #include "vkDeviceUtil.hpp" |
| #include "vkApiVersion.hpp" |
| #include "vkAllocationCallbackUtil.hpp" |
| #include "vkDeviceFeatures.hpp" |
| |
| #include "tcuTestLog.hpp" |
| #include "tcuResultCollector.hpp" |
| #include "tcuCommandLine.hpp" |
| |
| #include "deUniquePtr.hpp" |
| #include "deStringUtil.hpp" |
| |
| #include <vector> |
| #include <set> |
| |
| namespace vkt |
| { |
| namespace api |
| { |
| |
| namespace |
| { |
| |
| using namespace vk; |
| using namespace std; |
| using std::vector; |
| using tcu::TestLog; |
| |
| tcu::TestStatus createInstanceTest (Context& context) |
| { |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| tcu::ResultCollector resultCollector (log); |
| const char* appNames[] = { "appName", DE_NULL, "", "app, name", "app(\"name\"", "app~!@#$%^&*()_+name", "app\nName", "app\r\nName" }; |
| const char* engineNames[] = { "engineName", DE_NULL, "", "engine. name", "engine\"(name)", "eng~!@#$%^&*()_+name", "engine\nName", "engine\r\nName" }; |
| const int patchNumbers[] = { 0, 1, 2, 3, 4, 5, 13, 4094, 4095 }; |
| const deUint32 appVersions[] = { 0, 1, (deUint32)-1 }; |
| const deUint32 engineVersions[] = { 0, 1, (deUint32)-1 }; |
| const deUint32 apiVersion = context.getUsedApiVersion(); |
| vector<VkApplicationInfo> appInfos; |
| |
| // test over appName |
| for (int appNameNdx = 0; appNameNdx < DE_LENGTH_OF_ARRAY(appNames); appNameNdx++) |
| { |
| const VkApplicationInfo appInfo = |
| { |
| VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| appNames[appNameNdx], // const char* pAppName; |
| 0u, // deUint32 appVersion; |
| "engineName", // const char* pEngineName; |
| 0u, // deUint32 engineVersion; |
| apiVersion, // deUint32 apiVersion; |
| }; |
| |
| appInfos.push_back(appInfo); |
| } |
| |
| // test over engineName |
| for (int engineNameNdx = 0; engineNameNdx < DE_LENGTH_OF_ARRAY(engineNames); engineNameNdx++) |
| { |
| const VkApplicationInfo appInfo = |
| { |
| VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| "appName", // const char* pAppName; |
| 0u, // deUint32 appVersion; |
| engineNames[engineNameNdx], // const char* pEngineName; |
| 0u, // deUint32 engineVersion; |
| apiVersion, // deUint32 apiVersion; |
| }; |
| |
| appInfos.push_back(appInfo); |
| } |
| |
| // test over appVersion |
| for (int appVersionNdx = 0; appVersionNdx < DE_LENGTH_OF_ARRAY(appVersions); appVersionNdx++) |
| { |
| const VkApplicationInfo appInfo = |
| { |
| VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| "appName", // const char* pAppName; |
| appVersions[appVersionNdx], // deUint32 appVersion; |
| "engineName", // const char* pEngineName; |
| 0u, // deUint32 engineVersion; |
| apiVersion, // deUint32 apiVersion; |
| }; |
| |
| appInfos.push_back(appInfo); |
| } |
| |
| // test over engineVersion |
| for (int engineVersionNdx = 0; engineVersionNdx < DE_LENGTH_OF_ARRAY(engineVersions); engineVersionNdx++) |
| { |
| const VkApplicationInfo appInfo = |
| { |
| VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| "appName", // const char* pAppName; |
| 0u, // deUint32 appVersion; |
| "engineName", // const char* pEngineName; |
| engineVersions[engineVersionNdx], // deUint32 engineVersion; |
| apiVersion, // deUint32 apiVersion; |
| }; |
| |
| appInfos.push_back(appInfo); |
| } |
| const deUint32 manjorNum = unpackVersion(apiVersion).majorNum; |
| const deUint32 minorNum = unpackVersion(apiVersion).minorNum; |
| |
| // patch component of api version checking (should be ignored by implementation) |
| for (int patchVersion = 0; patchVersion < DE_LENGTH_OF_ARRAY(patchNumbers); patchVersion++) |
| { |
| const VkApplicationInfo appInfo = |
| { |
| VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| "appName", // const char* pAppName; |
| 0u, // deUint32 appVersion; |
| "engineName", // const char* pEngineName; |
| 0u, // deUint32 engineVersion; |
| VK_MAKE_VERSION(manjorNum, minorNum, patchNumbers[patchVersion]), // deUint32 apiVersion; |
| }; |
| |
| appInfos.push_back(appInfo); |
| } |
| |
| // test when apiVersion is 0 |
| { |
| const VkApplicationInfo appInfo = |
| { |
| VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| "appName", // const char* pAppName; |
| 0u, // deUint32 appVersion; |
| "engineName", // const char* pEngineName; |
| 0u, // deUint32 engineVersion; |
| 0u, // deUint32 apiVersion; |
| }; |
| |
| appInfos.push_back(appInfo); |
| } |
| |
| // run the tests! |
| for (size_t appInfoNdx = 0; appInfoNdx < appInfos.size(); ++appInfoNdx) |
| { |
| const VkApplicationInfo& appInfo = appInfos[appInfoNdx]; |
| const VkInstanceCreateInfo instanceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkInstanceCreateFlags)0u, // VkInstanceCreateFlags flags; |
| &appInfo, // const VkApplicationInfo* pAppInfo; |
| 0u, // deUint32 layerCount; |
| DE_NULL, // const char*const* ppEnabledLayernames; |
| 0u, // deUint32 extensionCount; |
| DE_NULL, // const char*const* ppEnabledExtensionNames; |
| }; |
| |
| log << TestLog::Message << "Creating instance with appInfo: " << appInfo << TestLog::EndMessage; |
| |
| try |
| { |
| CustomInstance instance = createCustomInstanceFromInfo(context, &instanceCreateInfo); |
| log << TestLog::Message << "Succeeded" << TestLog::EndMessage; |
| } |
| catch (const vk::Error& err) |
| { |
| resultCollector.fail("Failed, Error code: " + de::toString(err.getMessage())); |
| } |
| } |
| |
| return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage()); |
| } |
| |
| tcu::TestStatus createInstanceWithInvalidApiVersionTest (Context& context) |
| { |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| tcu::ResultCollector resultCollector (log); |
| const PlatformInterface& platformInterface = context.getPlatformInterface(); |
| |
| deUint32 instanceApiVersion = 0u; |
| platformInterface.enumerateInstanceVersion(&instanceApiVersion); |
| |
| const ApiVersion apiVersion = unpackVersion(instanceApiVersion); |
| |
| const deUint32 invalidMajorVersion = (1 << 10) - 1; |
| const deUint32 invalidMinorVersion = (1 << 10) - 1; |
| vector<ApiVersion> invalidApiVersions; |
| |
| invalidApiVersions.push_back(ApiVersion(invalidMajorVersion, apiVersion.minorNum, apiVersion.patchNum)); |
| invalidApiVersions.push_back(ApiVersion(apiVersion.majorNum, invalidMinorVersion, apiVersion.patchNum)); |
| |
| for (size_t apiVersionNdx = 0; apiVersionNdx < invalidApiVersions.size(); apiVersionNdx++) |
| { |
| const VkApplicationInfo appInfo = |
| { |
| VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| "appName", // const char* pAppName; |
| 0u, // deUint32 appVersion; |
| "engineName", // const char* pEngineName; |
| 0u, // deUint32 engineVersion; |
| pack(invalidApiVersions[apiVersionNdx]), // deUint32 apiVersion; |
| }; |
| const VkInstanceCreateInfo instanceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkInstanceCreateFlags)0u, // VkInstanceCreateFlags flags; |
| &appInfo, // const VkApplicationInfo* pAppInfo; |
| 0u, // deUint32 layerCount; |
| DE_NULL, // const char*const* ppEnabledLayernames; |
| 0u, // deUint32 extensionCount; |
| DE_NULL, // const char*const* ppEnabledExtensionNames; |
| }; |
| |
| log << TestLog::Message |
| << "API version reported by enumerateInstanceVersion: " << apiVersion |
| << ", api version used to create instance: " << invalidApiVersions[apiVersionNdx] |
| << TestLog::EndMessage; |
| |
| { |
| UncheckedInstance instance; |
| const VkResult result = createUncheckedInstance(context, &instanceCreateInfo, DE_NULL, &instance); |
| |
| if (apiVersion.majorNum == 1 && apiVersion.minorNum == 0) |
| { |
| if (result == VK_ERROR_INCOMPATIBLE_DRIVER) |
| { |
| TCU_CHECK(!static_cast<bool>(instance)); |
| log << TestLog::Message << "Pass, instance creation with invalid apiVersion is rejected" << TestLog::EndMessage; |
| } |
| else |
| resultCollector.fail("Fail, instance creation with invalid apiVersion is not rejected"); |
| } |
| else if (apiVersion.majorNum == 1 && apiVersion.minorNum >= 1) |
| { |
| if (result == VK_SUCCESS) |
| { |
| TCU_CHECK(static_cast<bool>(instance)); |
| log << TestLog::Message << "Pass, instance creation with nonstandard apiVersion succeeds for Vulkan 1.1" << TestLog::EndMessage; |
| } |
| else if (result == VK_ERROR_INCOMPATIBLE_DRIVER) |
| { |
| resultCollector.fail("Fail, In Vulkan 1.1 instance creation must not return VK_ERROR_INCOMPATIBLE_DRIVER."); |
| } |
| else |
| { |
| std::ostringstream message; |
| message << "Fail, createInstance failed with " << result; |
| resultCollector.fail(message.str().c_str()); |
| } |
| } |
| } |
| } |
| |
| return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage()); |
| } |
| |
| tcu::TestStatus createInstanceWithNullApplicationInfoTest (Context& context) |
| { |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| tcu::ResultCollector resultCollector (log); |
| |
| const VkInstanceCreateInfo instanceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkInstanceCreateFlags)0u, // VkInstanceCreateFlags flags; |
| DE_NULL, // const VkApplicationInfo* pAppInfo; |
| 0u, // deUint32 layerCount; |
| DE_NULL, // const char*const* ppEnabledLayernames; |
| 0u, // deUint32 extensionCount; |
| DE_NULL, // const char*const* ppEnabledExtensionNames; |
| }; |
| |
| log << TestLog::Message << "Creating instance with NULL pApplicationInfo" << TestLog::EndMessage; |
| |
| try |
| { |
| CustomInstance instance = createCustomInstanceFromInfo(context, &instanceCreateInfo); |
| log << TestLog::Message << "Succeeded" << TestLog::EndMessage; |
| } |
| catch (const vk::Error& err) |
| { |
| resultCollector.fail("Failed, Error code: " + de::toString(err.getMessage())); |
| } |
| |
| return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage()); |
| } |
| |
| tcu::TestStatus createInstanceWithUnsupportedExtensionsTest (Context& context) |
| { |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| const char* enabledExtensions[] = {"VK_UNSUPPORTED_EXTENSION", "THIS_IS_NOT_AN_EXTENSION"}; |
| const deUint32 apiVersion = context.getUsedApiVersion(); |
| const VkApplicationInfo appInfo = |
| { |
| VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| "appName", // const char* pAppName; |
| 0u, // deUint32 appVersion; |
| "engineName", // const char* pEngineName; |
| 0u, // deUint32 engineVersion; |
| apiVersion, // deUint32 apiVersion; |
| }; |
| |
| const VkInstanceCreateInfo instanceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkInstanceCreateFlags)0u, // VkInstanceCreateFlags flags; |
| &appInfo, // const VkApplicationInfo* pAppInfo; |
| 0u, // deUint32 layerCount; |
| DE_NULL, // const char*const* ppEnabledLayernames; |
| DE_LENGTH_OF_ARRAY(enabledExtensions), // deUint32 extensionCount; |
| enabledExtensions, // const char*const* ppEnabledExtensionNames; |
| }; |
| |
| log << TestLog::Message << "Enabled extensions are: " << TestLog::EndMessage; |
| |
| for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(enabledExtensions); ndx++) |
| log << TestLog::Message << enabledExtensions[ndx] << TestLog::EndMessage; |
| |
| { |
| UncheckedInstance instance; |
| const VkResult result = createUncheckedInstance(context, &instanceCreateInfo, DE_NULL, &instance); |
| |
| if (result == VK_ERROR_EXTENSION_NOT_PRESENT) |
| { |
| TCU_CHECK(!static_cast<bool>(instance)); |
| return tcu::TestStatus::pass("Pass, creating instance with unsupported extension was rejected."); |
| } |
| else |
| return tcu::TestStatus::fail("Fail, creating instance with unsupported extensions succeeded."); |
| } |
| } |
| |
| enum |
| { |
| UTF8ABUSE_LONGNAME = 0, |
| UTF8ABUSE_BADNAMES, |
| UTF8ABUSE_OVERLONGNUL, |
| UTF8ABUSE_OVERLONG, |
| UTF8ABUSE_ZALGO, |
| UTF8ABUSE_CHINESE, |
| UTF8ABUSE_EMPTY, |
| UTF8ABUSE_MAX |
| }; |
| |
| string getUTF8AbuseString (int index) |
| { |
| switch (index) |
| { |
| case UTF8ABUSE_LONGNAME: |
| // Generate a long name. |
| { |
| std::string longname; |
| longname.resize(65535, 'k'); |
| return longname; |
| } |
| |
| case UTF8ABUSE_BADNAMES: |
| // Various illegal code points in utf-8 |
| return string( |
| "Illegal bytes in UTF-8: " |
| "\xc0 \xc1 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb \xfc \xfd \xfe \xff" |
| "illegal surrogates: \xed\xad\xbf \xed\xbe\x80"); |
| |
| case UTF8ABUSE_OVERLONGNUL: |
| // Zero encoded as overlong, not exactly legal but often supported to differentiate from terminating zero |
| return string("UTF-8 encoded nul \xC0\x80 (should not end name)"); |
| |
| case UTF8ABUSE_OVERLONG: |
| // Some overlong encodings |
| return string( |
| "UTF-8 overlong \xF0\x82\x82\xAC \xfc\x83\xbf\xbf\xbf\xbf \xf8\x87\xbf\xbf\xbf " |
| "\xf0\x8f\xbf\xbf"); |
| |
| case UTF8ABUSE_ZALGO: |
| // Internet "zalgo" meme "bleeding text" |
| return string( |
| "\x56\xcc\xb5\xcc\x85\xcc\x94\xcc\x88\xcd\x8a\xcc\x91\xcc\x88\xcd\x91\xcc\x83\xcd\x82" |
| "\xcc\x83\xcd\x90\xcc\x8a\xcc\x92\xcc\x92\xcd\x8b\xcc\x94\xcd\x9d\xcc\x98\xcc\xab\xcc" |
| "\xae\xcc\xa9\xcc\xad\xcc\x97\xcc\xb0\x75\xcc\xb6\xcc\xbe\xcc\x80\xcc\x82\xcc\x84\xcd" |
| "\x84\xcc\x90\xcd\x86\xcc\x9a\xcd\x84\xcc\x9b\xcd\x86\xcd\x92\xcc\x9a\xcd\x99\xcd\x99" |
| "\xcc\xbb\xcc\x98\xcd\x8e\xcd\x88\xcd\x9a\xcc\xa6\xcc\x9c\xcc\xab\xcc\x99\xcd\x94\xcd" |
| "\x99\xcd\x95\xcc\xa5\xcc\xab\xcd\x89\x6c\xcc\xb8\xcc\x8e\xcc\x8b\xcc\x8b\xcc\x9a\xcc" |
| "\x8e\xcd\x9d\xcc\x80\xcc\xa1\xcc\xad\xcd\x9c\xcc\xba\xcc\x96\xcc\xb3\xcc\xa2\xcd\x8e" |
| "\xcc\xa2\xcd\x96\x6b\xcc\xb8\xcc\x84\xcd\x81\xcc\xbf\xcc\x8d\xcc\x89\xcc\x85\xcc\x92" |
| "\xcc\x84\xcc\x90\xcd\x81\xcc\x93\xcd\x90\xcd\x92\xcd\x9d\xcc\x84\xcd\x98\xcd\x9d\xcd" |
| "\xa0\xcd\x91\xcc\x94\xcc\xb9\xcd\x93\xcc\xa5\xcd\x87\xcc\xad\xcc\xa7\xcd\x96\xcd\x99" |
| "\xcc\x9d\xcc\xbc\xcd\x96\xcd\x93\xcc\x9d\xcc\x99\xcc\xa8\xcc\xb1\xcd\x85\xcc\xba\xcc" |
| "\xa7\x61\xcc\xb8\xcc\x8e\xcc\x81\xcd\x90\xcd\x84\xcd\x8c\xcc\x8c\xcc\x85\xcd\x86\xcc" |
| "\x84\xcd\x84\xcc\x90\xcc\x84\xcc\x8d\xcd\x99\xcd\x8d\xcc\xb0\xcc\xa3\xcc\xa6\xcd\x89" |
| "\xcd\x8d\xcd\x87\xcc\x98\xcd\x8d\xcc\xa4\xcd\x9a\xcd\x8e\xcc\xab\xcc\xb9\xcc\xac\xcc" |
| "\xa2\xcd\x87\xcc\xa0\xcc\xb3\xcd\x89\xcc\xb9\xcc\xa7\xcc\xa6\xcd\x89\xcd\x95\x6e\xcc" |
| "\xb8\xcd\x8a\xcc\x8a\xcd\x82\xcc\x9b\xcd\x81\xcd\x90\xcc\x85\xcc\x9b\xcd\x80\xcd\x91" |
| "\xcd\x9b\xcc\x81\xcd\x81\xcc\x9a\xcc\xb3\xcd\x9c\xcc\x9e\xcc\x9d\xcd\x99\xcc\xa2\xcd" |
| "\x93\xcd\x96\xcc\x97\xff"); |
| |
| case UTF8ABUSE_CHINESE: |
| // Some Chinese glyphs. |
| // "English equivalent: The devil is in the details", https://en.wikiquote.org/wiki/Chinese_proverbs |
| return string( |
| "\xe8\xaf\xbb\xe4\xb9\xa6\xe9\xa1\xbb\xe7\x94\xa8\xe6\x84\x8f\xef\xbc\x8c\xe4\xb8\x80" |
| "\xe5\xad\x97\xe5\x80\xbc\xe5\x8d\x83\xe9\x87\x91\x20"); |
| |
| default: |
| DE_ASSERT(index == UTF8ABUSE_EMPTY); |
| // Also try an empty string. |
| return string(""); |
| } |
| } |
| |
| tcu::TestStatus createInstanceWithExtensionNameAbuseTest (Context& context) |
| { |
| const char* extensionList[1] = { 0 }; |
| const deUint32 apiVersion = context.getUsedApiVersion(); |
| deUint32 failCount = 0; |
| |
| for (int i = 0; i < UTF8ABUSE_MAX; i++) |
| { |
| string abuseString = getUTF8AbuseString(i); |
| extensionList[0] = abuseString.c_str(); |
| |
| const VkApplicationInfo appInfo = |
| { |
| VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| "appName", // const char* pAppName; |
| 0u, // deUint32 appVersion; |
| "engineName", // const char* pEngineName; |
| 0u, // deUint32 engineVersion; |
| apiVersion, // deUint32 apiVersion; |
| }; |
| |
| const VkInstanceCreateInfo instanceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkInstanceCreateFlags)0u, // VkInstanceCreateFlags flags; |
| &appInfo, // const VkApplicationInfo* pAppInfo; |
| 0u, // deUint32 layerCount; |
| DE_NULL, // const char*const* ppEnabledLayernames; |
| 1u, // deUint32 extensionCount; |
| extensionList, // const char*const* ppEnabledExtensionNames; |
| }; |
| |
| { |
| UncheckedInstance instance; |
| const VkResult result = createUncheckedInstance(context, &instanceCreateInfo, DE_NULL, &instance); |
| |
| if (result != VK_ERROR_EXTENSION_NOT_PRESENT) |
| failCount++; |
| |
| TCU_CHECK(!static_cast<bool>(instance)); |
| } |
| } |
| |
| if (failCount > 0) |
| return tcu::TestStatus::fail("Fail, creating instances with unsupported extensions succeeded."); |
| |
| return tcu::TestStatus::pass("Pass, creating instances with unsupported extensions were rejected."); |
| } |
| |
| tcu::TestStatus createInstanceWithLayerNameAbuseTest (Context& context) |
| { |
| const PlatformInterface& platformInterface = context.getPlatformInterface(); |
| const char* layerList[1] = { 0 }; |
| const deUint32 apiVersion = context.getUsedApiVersion(); |
| deUint32 failCount = 0; |
| |
| for (int i = 0; i < UTF8ABUSE_MAX; i++) |
| { |
| string abuseString = getUTF8AbuseString(i); |
| layerList[0] = abuseString.c_str(); |
| |
| const VkApplicationInfo appInfo = |
| { |
| VK_STRUCTURE_TYPE_APPLICATION_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| "appName", // const char* pAppName; |
| 0u, // deUint32 appVersion; |
| "engineName", // const char* pEngineName; |
| 0u, // deUint32 engineVersion; |
| apiVersion, // deUint32 apiVersion; |
| }; |
| |
| const VkInstanceCreateInfo instanceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkInstanceCreateFlags)0u, // VkInstanceCreateFlags flags; |
| &appInfo, // const VkApplicationInfo* pAppInfo; |
| 1u, // deUint32 layerCount; |
| layerList, // const char*const* ppEnabledLayernames; |
| 0u, // deUint32 extensionCount; |
| DE_NULL, // const char*const* ppEnabledExtensionNames; |
| }; |
| |
| { |
| VkInstance instance = (VkInstance)0; |
| const VkResult result = platformInterface.createInstance(&instanceCreateInfo, DE_NULL/*pAllocator*/, &instance); |
| const bool gotInstance = !!instance; |
| |
| if (instance) |
| { |
| const InstanceDriver instanceIface(platformInterface, instance); |
| instanceIface.destroyInstance(instance, DE_NULL/*pAllocator*/); |
| } |
| |
| if (result != VK_ERROR_LAYER_NOT_PRESENT) |
| failCount++; |
| |
| TCU_CHECK(!gotInstance); |
| } |
| } |
| |
| if (failCount > 0) |
| return tcu::TestStatus::fail("Fail, creating instances with unsupported layers succeeded."); |
| |
| return tcu::TestStatus::pass("Pass, creating instances with unsupported layers were rejected."); |
| } |
| |
| tcu::TestStatus enumerateDevicesAllocLeakTest(Context& context) |
| { |
| // enumeratePhysicalDevices uses instance-provided allocator |
| // and this test checks if all alocated memory is freed |
| |
| typedef AllocationCallbackRecorder::RecordIterator RecordIterator; |
| |
| DeterministicFailAllocator objAllocator (getSystemAllocator(), DeterministicFailAllocator::MODE_DO_NOT_COUNT, 0); |
| AllocationCallbackRecorder recorder (objAllocator.getCallbacks(), 128); |
| const auto instance = createCustomInstanceFromContext(context, recorder.getCallbacks(), true); |
| const auto& vki = instance.getDriver(); |
| vector<VkPhysicalDevice> devices (enumeratePhysicalDevices(vki, instance)); |
| RecordIterator recordToCheck (recorder.getRecordsEnd()); |
| |
| try |
| { |
| devices = enumeratePhysicalDevices(vki, instance); |
| } |
| catch (const vk::OutOfMemoryError& e) |
| { |
| if (e.getError() != VK_ERROR_OUT_OF_HOST_MEMORY) |
| return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Got out of memory error - leaks in enumeratePhysicalDevices not tested."); |
| } |
| |
| // make sure that same number of allocations and frees was done |
| deInt32 allocationRecords (0); |
| RecordIterator lastRecordToCheck (recorder.getRecordsEnd()); |
| while (recordToCheck != lastRecordToCheck) |
| { |
| const AllocationCallbackRecord& record = *recordToCheck; |
| switch (record.type) |
| { |
| case AllocationCallbackRecord::TYPE_ALLOCATION: |
| ++allocationRecords; |
| break; |
| case AllocationCallbackRecord::TYPE_FREE: |
| if (record.data.free.mem != DE_NULL) |
| --allocationRecords; |
| break; |
| default: |
| break; |
| } |
| ++recordToCheck; |
| } |
| |
| if (allocationRecords) |
| return tcu::TestStatus::fail("enumeratePhysicalDevices leaked memory"); |
| return tcu::TestStatus::pass("Ok"); |
| } |
| |
| tcu::TestStatus createDeviceTest (Context& context) |
| { |
| const PlatformInterface& platformInterface = context.getPlatformInterface(); |
| const CustomInstance instance (createCustomInstanceFromContext(context)); |
| const InstanceDriver& instanceDriver (instance.getDriver()); |
| const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine()); |
| const deUint32 queueFamilyIndex = 0; |
| const deUint32 queueCount = 1; |
| const deUint32 queueIndex = 0; |
| const float queuePriority = 1.0f; |
| |
| const vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice); |
| |
| const VkDeviceQueueCreateInfo deviceQueueCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, |
| DE_NULL, |
| (VkDeviceQueueCreateFlags)0u, |
| queueFamilyIndex, //queueFamilyIndex; |
| queueCount, //queueCount; |
| &queuePriority, //pQueuePriorities; |
| }; |
| |
| const VkDeviceCreateInfo deviceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType; |
| DE_NULL, //pNext; |
| (VkDeviceCreateFlags)0u, |
| 1, //queueRecordCount; |
| &deviceQueueCreateInfo, //pRequestedQueues; |
| 0, //layerCount; |
| DE_NULL, //ppEnabledLayerNames; |
| 0, //extensionCount; |
| DE_NULL, //ppEnabledExtensionNames; |
| DE_NULL, //pEnabledFeatures; |
| }; |
| |
| const Unique<VkDevice> device (createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), platformInterface, instance, instanceDriver, physicalDevice, &deviceCreateInfo)); |
| const DeviceDriver deviceDriver (platformInterface, instance, device.get()); |
| const VkQueue queue = getDeviceQueue(deviceDriver, *device, queueFamilyIndex, queueIndex); |
| |
| VK_CHECK(deviceDriver.queueWaitIdle(queue)); |
| |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| tcu::TestStatus createMultipleDevicesTest (Context& context) |
| { |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| tcu::ResultCollector resultCollector (log); |
| const int numDevices = 5; |
| const PlatformInterface& platformInterface = context.getPlatformInterface(); |
| const CustomInstance instance (createCustomInstanceFromContext(context)); |
| const InstanceDriver& instanceDriver (instance.getDriver()); |
| const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine()); |
| const vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice); |
| const deUint32 queueFamilyIndex = 0; |
| const deUint32 queueCount = 1; |
| const deUint32 queueIndex = 0; |
| const float queuePriority = 1.0f; |
| const VkDeviceQueueCreateInfo deviceQueueCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, |
| DE_NULL, |
| (VkDeviceQueueCreateFlags)0u, //flags; |
| queueFamilyIndex, //queueFamilyIndex; |
| queueCount, //queueCount; |
| &queuePriority, //pQueuePriorities; |
| }; |
| |
| const VkDeviceCreateInfo deviceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType; |
| DE_NULL, //pNext; |
| (VkDeviceCreateFlags)0u, |
| 1, //queueRecordCount; |
| &deviceQueueCreateInfo, //pRequestedQueues; |
| 0, //layerCount; |
| DE_NULL, //ppEnabledLayerNames; |
| 0, //extensionCount; |
| DE_NULL, //ppEnabledExtensionNames; |
| DE_NULL, //pEnabledFeatures; |
| }; |
| |
| vector<VkDevice> devices(numDevices, (VkDevice)DE_NULL); |
| |
| try |
| { |
| for (int deviceNdx = 0; deviceNdx < numDevices; deviceNdx++) |
| { |
| const VkResult result = createUncheckedDevice(context.getTestContext().getCommandLine().isValidationEnabled(), instanceDriver, physicalDevice, &deviceCreateInfo, DE_NULL/*pAllocator*/, &devices[deviceNdx]); |
| |
| if (result != VK_SUCCESS) |
| { |
| resultCollector.fail("Failed to create Device No." + de::toString(deviceNdx) + ", Error Code: " + de::toString(result)); |
| break; |
| } |
| |
| { |
| const DeviceDriver deviceDriver (platformInterface, instance, devices[deviceNdx]); |
| const VkQueue queue = getDeviceQueue(deviceDriver, devices[deviceNdx], queueFamilyIndex, queueIndex); |
| |
| VK_CHECK(deviceDriver.queueWaitIdle(queue)); |
| } |
| } |
| } |
| catch (const vk::Error& error) |
| { |
| resultCollector.fail(de::toString(error.getError())); |
| } |
| catch (...) |
| { |
| for (int deviceNdx = (int)devices.size()-1; deviceNdx >= 0; deviceNdx--) |
| { |
| if (devices[deviceNdx] != (VkDevice)DE_NULL) |
| { |
| DeviceDriver deviceDriver(platformInterface, instance, devices[deviceNdx]); |
| deviceDriver.destroyDevice(devices[deviceNdx], DE_NULL/*pAllocator*/); |
| } |
| } |
| |
| throw; |
| } |
| |
| for (int deviceNdx = (int)devices.size()-1; deviceNdx >= 0; deviceNdx--) |
| { |
| if (devices[deviceNdx] != (VkDevice)DE_NULL) |
| { |
| DeviceDriver deviceDriver(platformInterface, instance, devices[deviceNdx]); |
| deviceDriver.destroyDevice(devices[deviceNdx], DE_NULL/*pAllocator*/); |
| } |
| } |
| |
| return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage()); |
| } |
| |
| tcu::TestStatus createDeviceWithUnsupportedExtensionsTest (Context& context) |
| { |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| const PlatformInterface& platformInterface = context.getPlatformInterface(); |
| const CustomInstance instance (createCustomInstanceFromContext(context, DE_NULL, false)); |
| const InstanceDriver& instanceDriver (instance.getDriver()); |
| const char* enabledExtensions[] = {"VK_UNSUPPORTED_EXTENSION", "THIS_IS_NOT_AN_EXTENSION", "VK_DONT_SUPPORT_ME"}; |
| const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine()); |
| const float queuePriority = 1.0f; |
| const VkDeviceQueueCreateInfo deviceQueueCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, |
| DE_NULL, |
| (VkDeviceQueueCreateFlags)0u, |
| 0, //queueFamilyIndex; |
| 1, //queueCount; |
| &queuePriority, //pQueuePriorities; |
| }; |
| |
| const VkDeviceCreateInfo deviceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType; |
| DE_NULL, //pNext; |
| (VkDeviceCreateFlags)0u, |
| 1, //queueRecordCount; |
| &deviceQueueCreateInfo, //pRequestedQueues; |
| 0, //layerCount; |
| DE_NULL, //ppEnabledLayerNames; |
| DE_LENGTH_OF_ARRAY(enabledExtensions), //extensionCount; |
| enabledExtensions, //ppEnabledExtensionNames; |
| DE_NULL, //pEnabledFeatures; |
| }; |
| |
| log << TestLog::Message << "Enabled extensions are: " << TestLog::EndMessage; |
| |
| for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(enabledExtensions); ndx++) |
| log << TestLog::Message << enabledExtensions[ndx] << TestLog::EndMessage; |
| |
| { |
| VkDevice device = (VkDevice)0; |
| const VkResult result = createUncheckedDevice(context.getTestContext().getCommandLine().isValidationEnabled(), instanceDriver, physicalDevice, &deviceCreateInfo, DE_NULL/*pAllocator*/, &device); |
| const bool gotDevice = !!device; |
| |
| if (device) |
| { |
| const DeviceDriver deviceIface (platformInterface, instance, device); |
| deviceIface.destroyDevice(device, DE_NULL/*pAllocator*/); |
| } |
| |
| if (result == VK_ERROR_EXTENSION_NOT_PRESENT) |
| { |
| TCU_CHECK(!gotDevice); |
| return tcu::TestStatus::pass("Pass, create device with unsupported extension is rejected."); |
| } |
| else |
| return tcu::TestStatus::fail("Fail, create device with unsupported extension but succeed."); |
| } |
| } |
| |
| deUint32 getGlobalMaxQueueCount(const vector<VkQueueFamilyProperties>& queueFamilyProperties) |
| { |
| deUint32 maxQueueCount = 0; |
| |
| for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < (deUint32)queueFamilyProperties.size(); queueFamilyNdx++) |
| { |
| maxQueueCount = de::max(maxQueueCount, queueFamilyProperties[queueFamilyNdx].queueCount); |
| } |
| |
| return maxQueueCount; |
| } |
| |
| tcu::TestStatus createDeviceWithVariousQueueCountsTest (Context& context) |
| { |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| const int queueCountDiff = 1; |
| const PlatformInterface& platformInterface = context.getPlatformInterface(); |
| const CustomInstance instance (createCustomInstanceFromContext(context)); |
| const InstanceDriver& instanceDriver (instance.getDriver()); |
| const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine()); |
| const vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice); |
| const vector<float> queuePriorities (getGlobalMaxQueueCount(queueFamilyProperties), 1.0f); |
| vector<VkDeviceQueueCreateInfo> deviceQueueCreateInfos; |
| |
| for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < (deUint32)queueFamilyProperties.size(); queueFamilyNdx++) |
| { |
| const deUint32 maxQueueCount = queueFamilyProperties[queueFamilyNdx].queueCount; |
| |
| for (deUint32 queueCount = 1; queueCount <= maxQueueCount; queueCount += queueCountDiff) |
| { |
| const VkDeviceQueueCreateInfo queueCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, |
| DE_NULL, |
| (VkDeviceQueueCreateFlags)0u, |
| queueFamilyNdx, |
| queueCount, |
| queuePriorities.data() |
| }; |
| |
| deviceQueueCreateInfos.push_back(queueCreateInfo); |
| } |
| } |
| |
| for (size_t testNdx = 0; testNdx < deviceQueueCreateInfos.size(); testNdx++) |
| { |
| const VkDeviceQueueCreateInfo& queueCreateInfo = deviceQueueCreateInfos[testNdx]; |
| const VkDeviceCreateInfo deviceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType; |
| DE_NULL, //pNext; |
| (VkDeviceCreateFlags)0u, |
| 1, //queueRecordCount; |
| &queueCreateInfo, //pRequestedQueues; |
| 0, //layerCount; |
| DE_NULL, //ppEnabledLayerNames; |
| 0, //extensionCount; |
| DE_NULL, //ppEnabledExtensionNames; |
| DE_NULL, //pEnabledFeatures; |
| }; |
| |
| const Unique<VkDevice> device (createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), platformInterface, instance, instanceDriver, physicalDevice, &deviceCreateInfo)); |
| const DeviceDriver deviceDriver (platformInterface, instance, device.get()); |
| const deUint32 queueFamilyIndex = deviceCreateInfo.pQueueCreateInfos->queueFamilyIndex; |
| const deUint32 queueCount = deviceCreateInfo.pQueueCreateInfos->queueCount; |
| |
| for (deUint32 queueIndex = 0; queueIndex < queueCount; queueIndex++) |
| { |
| const VkQueue queue = getDeviceQueue(deviceDriver, *device, queueFamilyIndex, queueIndex); |
| VkResult result; |
| |
| TCU_CHECK(!!queue); |
| |
| result = deviceDriver.queueWaitIdle(queue); |
| if (result != VK_SUCCESS) |
| { |
| log << TestLog::Message |
| << "vkQueueWaitIdle failed" |
| << ", queueIndex = " << queueIndex |
| << ", queueCreateInfo " << queueCreateInfo |
| << ", Error Code: " << result |
| << TestLog::EndMessage; |
| return tcu::TestStatus::fail("Fail"); |
| } |
| } |
| } |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| void checkGlobalPrioritySupport (Context& context) |
| { |
| context.requireDeviceFunctionality("VK_EXT_global_priority"); |
| } |
| |
| tcu::TestStatus createDeviceWithGlobalPriorityTest (Context& context) |
| { |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| const PlatformInterface& platformInterface = context.getPlatformInterface(); |
| const CustomInstance instance (createCustomInstanceFromContext(context)); |
| const InstanceDriver& instanceDriver (instance.getDriver()); |
| const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine()); |
| const vector<float> queuePriorities (1, 1.0f); |
| const VkQueueGlobalPriorityEXT globalPriorities[] = { VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT, VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT, VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT, VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT }; |
| |
| for (VkQueueGlobalPriorityEXT globalPriority : globalPriorities) |
| { |
| const VkDeviceQueueGlobalPriorityCreateInfoEXT queueGlobalPriority = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT, //sType; |
| DE_NULL, //pNext; |
| globalPriority //globalPriority; |
| }; |
| |
| const VkDeviceQueueCreateInfo queueCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //sType; |
| &queueGlobalPriority, //pNext; |
| (VkDeviceQueueCreateFlags)0u, //flags; |
| 0, //queueFamilyIndex; |
| 1, //queueCount; |
| queuePriorities.data() //pQueuePriorities; |
| }; |
| |
| const VkDeviceCreateInfo deviceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType; |
| DE_NULL, //pNext; |
| (VkDeviceCreateFlags)0u, //flags; |
| 1, //queueRecordCount; |
| &queueCreateInfo, //pRequestedQueues; |
| 0, //layerCount; |
| DE_NULL, //ppEnabledLayerNames; |
| 0, //extensionCount; |
| DE_NULL, //ppEnabledExtensionNames; |
| DE_NULL, //pEnabledFeatures; |
| }; |
| |
| const bool mayBeDenied = globalPriority > VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT; |
| |
| try |
| { |
| const Unique<VkDevice> device (createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), platformInterface, instance, instanceDriver, physicalDevice, &deviceCreateInfo)); |
| const DeviceDriver deviceDriver (platformInterface, instance, device.get()); |
| const deUint32 queueFamilyIndex = deviceCreateInfo.pQueueCreateInfos->queueFamilyIndex; |
| const VkQueue queue = getDeviceQueue(deviceDriver, *device, queueFamilyIndex, 0); |
| VkResult result; |
| |
| TCU_CHECK(!!queue); |
| |
| result = deviceDriver.queueWaitIdle(queue); |
| if (result == VK_ERROR_NOT_PERMITTED_EXT && mayBeDenied) |
| { |
| continue; |
| } |
| |
| if (result != VK_SUCCESS) |
| { |
| log << TestLog::Message |
| << "vkQueueWaitIdle failed" |
| << ", globalPriority = " << globalPriority |
| << ", queueCreateInfo " << queueCreateInfo |
| << ", Error Code: " << result |
| << TestLog::EndMessage; |
| return tcu::TestStatus::fail("Fail"); |
| } |
| } |
| catch (const Error& error) |
| { |
| if (error.getError() == VK_ERROR_NOT_PERMITTED_EXT && mayBeDenied) |
| { |
| continue; |
| } |
| else |
| { |
| log << TestLog::Message |
| << "exception thrown " << error.getMessage() |
| << ", globalPriority = " << globalPriority |
| << ", queueCreateInfo " << queueCreateInfo |
| << ", Error Code: " << error.getError() |
| << TestLog::EndMessage; |
| return tcu::TestStatus::fail("Fail"); |
| } |
| } |
| } |
| |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| void checkGlobalPriorityQuerySupport (Context& context) |
| { |
| context.requireDeviceFunctionality("VK_EXT_global_priority_query"); |
| } |
| |
| deBool isValidGlobalPriority(VkQueueGlobalPriorityEXT priority) |
| { |
| switch (priority) { |
| case VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT: |
| case VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT: |
| case VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT: |
| case VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT: |
| return DE_TRUE; |
| default: |
| return DE_FALSE; |
| } |
| } |
| |
| void checkGlobalPriorityProperties(const VkQueueFamilyGlobalPriorityPropertiesEXT& properties) |
| { |
| TCU_CHECK(properties.priorityCount > 0); |
| TCU_CHECK(properties.priorityCount <= VK_MAX_GLOBAL_PRIORITY_SIZE_EXT); |
| TCU_CHECK(isValidGlobalPriority(properties.priorities[0])); |
| |
| for (deUint32 ndx = 1; ndx < properties.priorityCount; ndx++) |
| { |
| TCU_CHECK(isValidGlobalPriority(properties.priorities[ndx])); |
| TCU_CHECK(properties.priorities[ndx] == (properties.priorities[ndx - 1] << 1)); |
| } |
| } |
| |
| tcu::TestStatus createDeviceWithQueriedGlobalPriorityTest (Context& context) |
| { |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| const PlatformInterface& platformInterface = context.getPlatformInterface(); |
| const CustomInstance instance (createCustomInstanceFromContext(context)); |
| const InstanceDriver& instanceDriver (instance.getDriver()); |
| const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine()); |
| const VkQueueGlobalPriorityEXT globalPriorities[] = { VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT, VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT, VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT, VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT }; |
| const vector<float> queuePriorities (1, 1.0f); |
| std::vector<const char*> enabledExtensions = {"VK_EXT_global_priority", "VK_EXT_global_priority_query"}; |
| deUint32 queueFamilyPropertyCount = ~0u; |
| |
| instanceDriver.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertyCount, DE_NULL); |
| TCU_CHECK(queueFamilyPropertyCount > 0); |
| |
| std::vector<VkQueueFamilyProperties2> queueFamilyProperties2 (queueFamilyPropertyCount); |
| std::vector<VkQueueFamilyGlobalPriorityPropertiesEXT> globalPriorityProperties (queueFamilyPropertyCount); |
| |
| for (deUint32 ndx = 0; ndx < queueFamilyPropertyCount; ndx++) |
| { |
| globalPriorityProperties[ndx].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT; |
| globalPriorityProperties[ndx].pNext = DE_NULL; |
| queueFamilyProperties2[ndx].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; |
| queueFamilyProperties2[ndx].pNext = &globalPriorityProperties[ndx]; |
| } |
| |
| instanceDriver.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertyCount, queueFamilyProperties2.data()); |
| TCU_CHECK((size_t)queueFamilyPropertyCount == queueFamilyProperties2.size()); |
| |
| if (!context.contextSupports(vk::ApiVersion(1, 1, 0))) |
| { |
| enabledExtensions.emplace_back("VK_KHR_get_physical_device_properties2"); |
| } |
| |
| for (deUint32 ndx = 0; ndx < queueFamilyPropertyCount; ndx++) |
| { |
| checkGlobalPriorityProperties(globalPriorityProperties[ndx]); |
| |
| for (VkQueueGlobalPriorityEXT globalPriority : globalPriorities) |
| { |
| const VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT globalPriorityQueryFeatures = |
| { |
| VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT, //sType; |
| DE_NULL, //pNext; |
| VK_TRUE //globalPriorityQuery; |
| }; |
| const VkDeviceQueueGlobalPriorityCreateInfoEXT queueGlobalPriorityCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT, //sType; |
| DE_NULL, //pNext; |
| globalPriority, //globalPriority; |
| }; |
| const VkDeviceQueueCreateInfo queueCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //sType; |
| &queueGlobalPriorityCreateInfo, //pNext; |
| (VkDeviceQueueCreateFlags)0u, //flags; |
| ndx, //queueFamilyIndex; |
| 1, //queueCount; |
| queuePriorities.data() //pQueuePriorities; |
| }; |
| const VkDeviceCreateInfo deviceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType; |
| &globalPriorityQueryFeatures, //pNext; |
| (VkDeviceCreateFlags)0u, //flags; |
| 1, //queueRecordCount; |
| &queueCreateInfo, //pRequestedQueues; |
| 0, //layerCount; |
| DE_NULL, //ppEnabledLayerNames; |
| (deUint32)enabledExtensions.size(), //extensionCount; |
| enabledExtensions.data(), //ppEnabledExtensionNames; |
| DE_NULL, //pEnabledFeatures; |
| }; |
| const bool mayBeDenied = globalPriority > VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT; |
| const bool mustFail = globalPriority < globalPriorityProperties[ndx].priorities[0] || globalPriority > globalPriorityProperties[ndx].priorities[globalPriorityProperties[ndx].priorityCount - 1]; |
| |
| try |
| { |
| const Unique<VkDevice> device (createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), platformInterface, instance, instanceDriver, physicalDevice, &deviceCreateInfo)); |
| const DeviceDriver deviceDriver (platformInterface, instance, device.get()); |
| const VkQueue queue = getDeviceQueue(deviceDriver, *device, ndx, 0); |
| |
| TCU_CHECK(!!queue); |
| |
| if (mustFail) |
| { |
| log << TestLog::Message |
| << "device creation must fail but not" |
| << ", globalPriority = " << globalPriority |
| << ", queueCreateInfo " << queueCreateInfo |
| << TestLog::EndMessage; |
| return tcu::TestStatus::fail("Fail"); |
| } |
| } |
| catch (const Error& error) |
| { |
| if (mustFail || (error.getError() == VK_ERROR_NOT_PERMITTED_EXT && mayBeDenied)) |
| { |
| continue; |
| } |
| else |
| { |
| log << TestLog::Message |
| << "exception thrown " << error.getMessage() |
| << ", globalPriority = " << globalPriority |
| << ", queueCreateInfo " << queueCreateInfo |
| << ", Error Code: " << error.getError() |
| << TestLog::EndMessage; |
| return tcu::TestStatus::fail("Fail"); |
| } |
| } |
| } |
| } |
| |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| tcu::TestStatus createDeviceFeatures2Test (Context& context) |
| { |
| const PlatformInterface& vkp = context.getPlatformInterface(); |
| const CustomInstance instance (createCustomInstanceWithExtension(context, "VK_KHR_get_physical_device_properties2")); |
| const InstanceDriver& vki (instance.getDriver()); |
| const VkPhysicalDevice physicalDevice = chooseDevice(vki, instance, context.getTestContext().getCommandLine()); |
| const deUint32 queueFamilyIndex = 0; |
| const deUint32 queueCount = 1; |
| const deUint32 queueIndex = 0; |
| const float queuePriority = 1.0f; |
| const vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice); |
| |
| VkPhysicalDeviceFeatures2 enabledFeatures; |
| const VkDeviceQueueCreateInfo deviceQueueCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, |
| DE_NULL, |
| (VkDeviceQueueCreateFlags)0u, |
| queueFamilyIndex, |
| queueCount, |
| &queuePriority, |
| }; |
| |
| const VkDeviceCreateInfo deviceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, |
| &enabledFeatures, |
| (VkDeviceCreateFlags)0u, |
| 1, |
| &deviceQueueCreateInfo, |
| 0u, |
| DE_NULL, |
| 0, |
| DE_NULL, |
| DE_NULL, |
| }; |
| |
| // Populate enabledFeatures |
| enabledFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; |
| enabledFeatures.pNext = DE_NULL; |
| |
| vki.getPhysicalDeviceFeatures2(physicalDevice, &enabledFeatures); |
| |
| { |
| const Unique<VkDevice> device (createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo)); |
| const DeviceDriver vkd (vkp, instance, device.get()); |
| const VkQueue queue = getDeviceQueue(vkd, *device, queueFamilyIndex, queueIndex); |
| |
| VK_CHECK(vkd.queueWaitIdle(queue)); |
| } |
| |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| struct Feature |
| { |
| const char* name; |
| size_t offset; |
| }; |
| |
| #define FEATURE_ITEM(STRUCT, MEMBER) {#MEMBER, DE_OFFSET_OF(STRUCT, MEMBER)} |
| // This macro is used to avoid the "out of array bounds" compiler warnings/errors in the checkFeatures function. |
| #define SAFE_OFFSET(LIMITING_STRUCT, STRUCT, MEMBER) std::min(static_cast<deUint32>(sizeof(LIMITING_STRUCT) - sizeof(VkBool32)), DE_OFFSET_OF(STRUCT, MEMBER)) |
| |
| template<typename StructType> |
| void checkFeatures (const PlatformInterface& vkp, const VkInstance& instance, const InstanceDriver& instanceDriver, const VkPhysicalDevice physicalDevice, int numFeatures, const Feature features[], const StructType* supportedFeatures, const deUint32 queueFamilyIndex, const deUint32 queueCount, const float queuePriority, int& numErrors, tcu::ResultCollector& resultCollector, const vector<const char*>* extensionNames, const VkPhysicalDeviceFeatures& defaultPhysicalDeviceFeatures) |
| { |
| struct StructureBase |
| { |
| VkStructureType sType; |
| void* pNext; |
| }; |
| |
| for (int featureNdx = 0; featureNdx < numFeatures; featureNdx++) |
| { |
| // Test only features that are not supported. |
| if (*(((VkBool32*)((deUint8*)(supportedFeatures) + features[featureNdx].offset)))) |
| continue; |
| |
| StructType structCopy; |
| deMemset(&structCopy, 0, sizeof(StructType)); |
| |
| auto* structBase = reinterpret_cast<StructureBase*>(&structCopy); |
| VkStructureType structureType = reinterpret_cast<const StructureBase*>(supportedFeatures)->sType; |
| structBase->sType = structureType; |
| structBase->pNext = DE_NULL; |
| |
| VkPhysicalDeviceFeatures physicalDeviceFeaturesCopy = defaultPhysicalDeviceFeatures; |
| |
| // Some features require that other feature(s) are also enabled. |
| |
| // If rayTracingPipelineShaderGroupHandleCaptureReplayMixed is VK_TRUE, rayTracingPipelineShaderGroupHandleCaptureReplay must also be VK_TRUE. |
| if (structureType == vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR && |
| features[featureNdx].offset == DE_OFFSET_OF(VkPhysicalDeviceRayTracingPipelineFeaturesKHR, rayTracingPipelineShaderGroupHandleCaptureReplayMixed)) |
| { |
| DE_ASSERT((std::is_same<VkPhysicalDeviceRayTracingPipelineFeaturesKHR, StructType>::value)); |
| auto* memberPtr = reinterpret_cast<VkBool32*>(reinterpret_cast<deUint8*>(&structCopy) + SAFE_OFFSET(StructType, VkPhysicalDeviceRayTracingPipelineFeaturesKHR, rayTracingPipelineShaderGroupHandleCaptureReplay)); |
| *memberPtr = VK_TRUE; |
| } |
| else if (structureType == vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES) |
| { |
| DE_ASSERT((std::is_same<VkPhysicalDeviceVulkan11Features, StructType>::value)); |
| // If multiviewGeometryShader is enabled then multiview must also be enabled. |
| // If multiviewTessellationShader is enabled then multiview must also be enabled. |
| if (features[featureNdx].offset == DE_OFFSET_OF(VkPhysicalDeviceVulkan11Features, multiviewGeometryShader) || |
| features[featureNdx].offset == DE_OFFSET_OF(VkPhysicalDeviceVulkan11Features, multiviewTessellationShader)) |
| { |
| auto* memberPtr = reinterpret_cast<VkBool32*>(reinterpret_cast<deUint8*>(&structCopy) + SAFE_OFFSET(StructType, VkPhysicalDeviceVulkan11Features, multiview)); |
| *memberPtr = VK_TRUE; |
| } |
| |
| // If variablePointers is enabled then variablePointersStorageBuffer must also be enabled. |
| if (features[featureNdx].offset == DE_OFFSET_OF(VkPhysicalDeviceVulkan11Features, variablePointers)) |
| { |
| auto* memberPtr = reinterpret_cast<VkBool32*>(reinterpret_cast<deUint8*>(&structCopy) + SAFE_OFFSET(StructType, VkPhysicalDeviceVulkan11Features, variablePointersStorageBuffer)); |
| *memberPtr = VK_TRUE; |
| } |
| } |
| else if (structureType == vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES) |
| { |
| DE_ASSERT((std::is_same<VkPhysicalDeviceMultiviewFeatures, StructType>::value)); |
| // If multiviewGeometryShader is enabled then multiview must also be enabled. |
| // If multiviewTessellationShader is enabled then multiview must also be enabled. |
| if (features[featureNdx].offset == DE_OFFSET_OF(VkPhysicalDeviceMultiviewFeatures, multiviewGeometryShader) || |
| features[featureNdx].offset == DE_OFFSET_OF(VkPhysicalDeviceMultiviewFeatures, multiviewTessellationShader)) |
| { |
| auto* memberPtr = reinterpret_cast<VkBool32*>(reinterpret_cast<deUint8*>(&structCopy) + SAFE_OFFSET(StructType, VkPhysicalDeviceMultiviewFeatures, multiview)); |
| *memberPtr = VK_TRUE; |
| } |
| } |
| else if (structureType == vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT) |
| { |
| DE_ASSERT((std::is_same<VkPhysicalDeviceRobustness2FeaturesEXT, StructType>::value)); |
| // If robustBufferAccess2 is enabled then robustBufferAccess must also be enabled. |
| if (features[featureNdx].offset == DE_OFFSET_OF(VkPhysicalDeviceRobustness2FeaturesEXT, robustBufferAccess2)) |
| { |
| physicalDeviceFeaturesCopy.robustBufferAccess = true; |
| } |
| } |
| else if (structureType == vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT) |
| { |
| DE_ASSERT((std::is_same<VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT, StructType>::value)); |
| // If sparseImageInt64Atomics is enabled, shaderImageInt64Atomics must be enabled. |
| if (features[featureNdx].offset == DE_OFFSET_OF(VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT, sparseImageInt64Atomics)) |
| { |
| auto* memberPtr = reinterpret_cast<VkBool32*>(reinterpret_cast<deUint8*>(&structCopy) + SAFE_OFFSET(StructType, VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT, shaderImageInt64Atomics)); |
| *memberPtr = VK_TRUE; |
| } |
| } |
| else if (structureType == vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT) |
| { |
| DE_ASSERT((std::is_same<VkPhysicalDeviceShaderAtomicFloatFeaturesEXT, StructType>::value)); |
| // If sparseImageFloat32Atomics is enabled, shaderImageFloat32Atomics must be enabled. |
| if (features[featureNdx].offset == |
| DE_OFFSET_OF(VkPhysicalDeviceShaderAtomicFloatFeaturesEXT, sparseImageFloat32Atomics)) { |
| auto *memberPtr = reinterpret_cast<VkBool32 *>(reinterpret_cast<deUint8 *>(&structCopy) + SAFE_OFFSET(StructType, VkPhysicalDeviceShaderAtomicFloatFeaturesEXT, shaderImageFloat32Atomics)); |
| *memberPtr = VK_TRUE; |
| } |
| |
| // If sparseImageFloat32AtomicAdd is enabled, shaderImageFloat32AtomicAdd must be enabled. |
| if (features[featureNdx].offset == |
| DE_OFFSET_OF(VkPhysicalDeviceShaderAtomicFloatFeaturesEXT, sparseImageFloat32AtomicAdd)) { |
| auto *memberPtr = reinterpret_cast<VkBool32 *>(reinterpret_cast<deUint8 *>(&structCopy) + SAFE_OFFSET(StructType, VkPhysicalDeviceShaderAtomicFloatFeaturesEXT, shaderImageFloat32AtomicAdd)); |
| *memberPtr = VK_TRUE; |
| } |
| } |
| else if (structureType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT) |
| { |
| DE_ASSERT((std::is_same<VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT, StructType>::value)); |
| // If sparseImageFloat32AtomicMinMax is enabled, shaderImageFloat32AtomicMinMax must be enabled. |
| if (features[featureNdx].offset == DE_OFFSET_OF(VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT, sparseImageFloat32AtomicMinMax)) |
| { |
| auto* memberPtr = reinterpret_cast<VkBool32*>(reinterpret_cast<deUint8*>(&structCopy) + SAFE_OFFSET(StructType, VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT, shaderImageFloat32AtomicMinMax)); |
| *memberPtr = VK_TRUE; |
| } |
| } |
| |
| // Enable the feature we're testing. |
| *reinterpret_cast<VkBool32*>(reinterpret_cast<deUint8*>(&structCopy) + features[featureNdx].offset) = VK_TRUE; |
| |
| const VkDeviceQueueCreateInfo deviceQueueCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (VkDeviceQueueCreateFlags)0u, // flags |
| queueFamilyIndex, // queueFamilyIndex |
| queueCount, // queueCount |
| &queuePriority // pQueuePriorities |
| }; |
| const VkPhysicalDeviceFeatures2 deviceFeatures2 = |
| { |
| VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, // sType |
| &structCopy, // pNext |
| physicalDeviceFeaturesCopy // features |
| }; |
| const VkDeviceCreateInfo deviceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType |
| &deviceFeatures2, // pNext |
| (VkDeviceCreateFlags)0u, // flags |
| 1, // queueCreateInfoCount |
| &deviceQueueCreateInfo, // pQueueCreateInfos |
| 0u, // enabledLayerCount |
| DE_NULL, // ppEnabledLayerNames |
| static_cast<deUint32>(extensionNames == DE_NULL ? 0 : extensionNames->size()), // enabledExtensionCount |
| extensionNames == DE_NULL ? DE_NULL : extensionNames->data(), // ppEnabledExtensionNames |
| DE_NULL // pEnabledFeatures |
| }; |
| |
| VkDevice device = (VkDevice)DE_NULL; |
| const VkResult res = createUncheckedDevice(false, instanceDriver, physicalDevice, &deviceCreateInfo, DE_NULL, &device); |
| |
| if (res != VK_ERROR_FEATURE_NOT_PRESENT) |
| { |
| numErrors++; |
| resultCollector.fail("Not returning VK_ERROR_FEATURE_NOT_PRESENT when creating device with feature " |
| + de::toString(features[featureNdx].name) + ", which was reported as unsupported."); |
| } |
| if (device != (VkDevice)DE_NULL) |
| { |
| DeviceDriver deviceDriver(vkp, instance, device); |
| deviceDriver.destroyDevice(device, DE_NULL); |
| } |
| } |
| } |
| |
| vector<string> removeExtensions (const vector<string>& a, const vector<const char*>& b) |
| { |
| vector<string> res; |
| set<string> removeExts (b.begin(), b.end()); |
| |
| for (const auto & aIter : a) |
| { |
| if (!de::contains(removeExts, aIter)) |
| res.push_back(aIter); |
| } |
| |
| return res; |
| } |
| |
| tcu::TestStatus createDeviceWithUnsupportedFeaturesTest (Context& context) |
| { |
| const PlatformInterface& vkp = context.getPlatformInterface(); |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| tcu::ResultCollector resultCollector (log); |
| const CustomInstance instance (createCustomInstanceWithExtensions(context, context.getInstanceExtensions(), DE_NULL, true)); |
| const InstanceDriver& instanceDriver (instance.getDriver()); |
| const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine()); |
| const deUint32 queueFamilyIndex = 0; |
| const deUint32 queueCount = 1; |
| const float queuePriority = 1.0f; |
| const DeviceFeatures deviceFeaturesAll (context.getInstanceInterface(), context.getUsedApiVersion(), physicalDevice, context.getInstanceExtensions(), context.getDeviceExtensions(), DE_TRUE); |
| const VkPhysicalDeviceFeatures2 deviceFeatures2 = deviceFeaturesAll.getCoreFeatures2(); |
| const VkPhysicalDeviceFeatures deviceFeatures = deviceFeatures2.features; |
| const vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice); |
| int numErrors = 0; |
| |
| // Test features listed in VkPhysicalDeviceFeatures structure |
| { |
| static const Feature features[] = |
| { |
| // robustBufferAccess is removed, because it's always supported. |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, fullDrawIndexUint32), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, imageCubeArray), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, independentBlend), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, geometryShader), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, tessellationShader), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, sampleRateShading), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, dualSrcBlend), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, logicOp), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, multiDrawIndirect), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, drawIndirectFirstInstance), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, depthClamp), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, depthBiasClamp), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, fillModeNonSolid), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, depthBounds), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, wideLines), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, largePoints), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, alphaToOne), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, multiViewport), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, samplerAnisotropy), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, textureCompressionETC2), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, textureCompressionASTC_LDR), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, textureCompressionBC), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, occlusionQueryPrecise), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, pipelineStatisticsQuery), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, vertexPipelineStoresAndAtomics), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, fragmentStoresAndAtomics), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderTessellationAndGeometryPointSize), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderImageGatherExtended), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderStorageImageExtendedFormats), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderStorageImageMultisample), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderStorageImageReadWithoutFormat), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderStorageImageWriteWithoutFormat), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderUniformBufferArrayDynamicIndexing), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderSampledImageArrayDynamicIndexing), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderStorageBufferArrayDynamicIndexing), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderStorageImageArrayDynamicIndexing), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderClipDistance), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderCullDistance), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderFloat64), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderInt64), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderInt16), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderResourceResidency), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, shaderResourceMinLod), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, sparseBinding), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, sparseResidencyBuffer), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, sparseResidencyImage2D), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, sparseResidencyImage3D), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, sparseResidency2Samples), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, sparseResidency4Samples), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, sparseResidency8Samples), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, sparseResidency16Samples), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, sparseResidencyAliased), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, variableMultisampleRate), |
| FEATURE_ITEM(VkPhysicalDeviceFeatures, inheritedQueries) |
| }; |
| |
| for (const auto& feature : features) |
| { |
| // Test only features that are not supported. |
| if (*(((VkBool32*)((deUint8*)(&deviceFeatures) + feature.offset)))) |
| continue; |
| |
| VkPhysicalDeviceFeatures enabledFeatures = deviceFeatures; |
| *((VkBool32*)((deUint8*)(&enabledFeatures) + feature.offset)) = VK_TRUE; |
| |
| const VkDeviceQueueCreateInfo deviceQueueCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, |
| DE_NULL, |
| (VkDeviceQueueCreateFlags)0u, |
| queueFamilyIndex, |
| queueCount, |
| &queuePriority |
| }; |
| const VkDeviceCreateInfo deviceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, |
| DE_NULL, |
| (VkDeviceCreateFlags)0u, |
| 1, |
| &deviceQueueCreateInfo, |
| 0u, |
| DE_NULL, |
| 0, |
| DE_NULL, |
| &enabledFeatures |
| }; |
| |
| VkDevice device = DE_NULL; |
| const VkResult res = createUncheckedDevice(false, instanceDriver, physicalDevice, &deviceCreateInfo, DE_NULL, &device); |
| |
| if (res != VK_ERROR_FEATURE_NOT_PRESENT) |
| { |
| numErrors++; |
| resultCollector.fail("Not returning VK_ERROR_FEATURE_NOT_PRESENT when creating device with feature " |
| + de::toString(feature.name) + ", which was reported as unsupported."); |
| } |
| |
| if (device != DE_NULL) |
| { |
| DeviceDriver deviceDriver(vkp, instance, device); |
| deviceDriver.destroyDevice(device, DE_NULL); |
| } |
| } |
| } |
| |
| VkPhysicalDeviceFeatures emptyDeviceFeatures; |
| deMemset(&emptyDeviceFeatures, 0, sizeof(emptyDeviceFeatures)); |
| |
| // Only non-core extensions will be used when creating the device. |
| vector<const char*> coreExtensions; |
| getCoreDeviceExtensions(context.getUsedApiVersion(), coreExtensions); |
| vector<string> nonCoreExtensions(removeExtensions(context.getDeviceExtensions(), coreExtensions)); |
| |
| vector<const char*> extensionNames; |
| extensionNames.reserve(nonCoreExtensions.size()); |
| for (const string& extension : nonCoreExtensions) |
| extensionNames.push_back(extension.c_str()); |
| |
| // Test features provided by extensions and Vulkan 1.1 and 1.2. |
| |
| #include "vkDeviceFeatureTest.inl" |
| |
| if (numErrors > 1) |
| return tcu::TestStatus(resultCollector.getResult(), "Enabling " + de::toString(numErrors) + " unsupported features didn't return VK_ERROR_FEATURE_NOT_PRESENT."); |
| else |
| return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage()); |
| } |
| |
| tcu::TestStatus createDeviceQueue2Test (Context& context) |
| { |
| if (!context.contextSupports(vk::ApiVersion(1, 1, 0))) |
| TCU_THROW(NotSupportedError, "Vulkan 1.1 is not supported"); |
| |
| const PlatformInterface& platformInterface = context.getPlatformInterface(); |
| const VkInstance instance = context.getInstance(); |
| const InstanceInterface& instanceDriver = context.getInstanceInterface(); |
| const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| const deUint32 queueCount = 1; |
| const deUint32 queueIndex = 0; |
| const float queuePriority = 1.0f; |
| |
| VkPhysicalDeviceProtectedMemoryFeatures protectedMemoryFeature = |
| { |
| VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES, // VkStructureType sType; |
| DE_NULL, // void* pNext; |
| VK_FALSE // VkBool32 protectedMemory; |
| }; |
| |
| VkPhysicalDeviceFeatures2 features2; |
| deMemset(&features2, 0, sizeof(features2)); |
| features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; |
| features2.pNext = &protectedMemoryFeature; |
| |
| instanceDriver.getPhysicalDeviceFeatures2(physicalDevice, &features2); |
| if (protectedMemoryFeature.protectedMemory == VK_FALSE) |
| TCU_THROW(NotSupportedError, "Protected memory feature is not supported"); |
| |
| const VkDeviceQueueCreateInfo deviceQueueCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT, // VkDeviceQueueCreateFlags flags; |
| queueFamilyIndex, // deUint32 queueFamilyIndex; |
| queueCount, // deUint32 queueCount; |
| &queuePriority, // const float* pQueuePriorities; |
| }; |
| const VkDeviceCreateInfo deviceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType; |
| &features2, // const void* pNext; |
| (VkDeviceCreateFlags)0u, // VkDeviceCreateFlags flags; |
| 1, // deUint32 queueCreateInfoCount; |
| &deviceQueueCreateInfo, // const VkDeviceQueueCreateInfo* pQueueCreateInfos; |
| 0, // deUint32 enabledLayerCount; |
| DE_NULL, // const char* const* ppEnabledLayerNames; |
| 0, // deUint32 enabledExtensionCount; |
| DE_NULL, // const char* const* ppEnabledExtensionNames; |
| DE_NULL, // const VkPhysicalDeviceFeatures* pEnabledFeatures; |
| }; |
| |
| const VkDeviceQueueInfo2 deviceQueueInfo2 = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT, // VkDeviceQueueCreateFlags flags; |
| queueFamilyIndex, // deUint32 queueFamilyIndex; |
| queueIndex, // deUint32 queueIndex; |
| }; |
| |
| { |
| const Unique<VkDevice> device (createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), platformInterface, instance, instanceDriver, physicalDevice, &deviceCreateInfo)); |
| const DeviceDriver deviceDriver (platformInterface, instance, device.get()); |
| const VkQueue queue2 = getDeviceQueue2(deviceDriver, *device, &deviceQueueInfo2); |
| |
| VK_CHECK(deviceDriver.queueWaitIdle(queue2)); |
| } |
| |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| tcu::TestStatus createDeviceQueue2UnmatchedFlagsTest (Context& context) |
| { |
| if (!context.contextSupports(vk::ApiVersion(1, 1, 0))) |
| TCU_THROW(NotSupportedError, "Vulkan 1.1 is not supported"); |
| |
| const PlatformInterface& platformInterface = context.getPlatformInterface(); |
| const VkInstance instance = context.getInstance(); |
| const InstanceInterface& instanceDriver = context.getInstanceInterface(); |
| const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); |
| |
| // Check if VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT flag can be used. |
| { |
| VkPhysicalDeviceProtectedMemoryFeatures protectedFeatures; |
| protectedFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES; |
| protectedFeatures.pNext = DE_NULL; |
| |
| VkPhysicalDeviceFeatures2 deviceFeatures; |
| deviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; |
| deviceFeatures.pNext = &protectedFeatures; |
| |
| instanceDriver.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures); |
| if (!protectedFeatures.protectedMemory) |
| { |
| TCU_THROW(NotSupportedError, "protectedMemory feature is not supported, no queue creation flags available"); |
| } |
| } |
| |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| const deUint32 queueCount = 1; |
| const deUint32 queueIndex = 0; |
| const float queuePriority = 1.0f; |
| const VkDeviceQueueCreateInfo deviceQueueCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags; |
| queueFamilyIndex, // deUint32 queueFamilyIndex; |
| queueCount, // deUint32 queueCount; |
| &queuePriority, // const float* pQueuePriorities; |
| }; |
| VkPhysicalDeviceProtectedMemoryFeatures protectedFeatures = |
| { |
| VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES, // VkStructureType sType; |
| DE_NULL, // void* pNext; |
| VK_TRUE // VkBool32 protectedMemory; |
| }; |
| |
| VkPhysicalDeviceFeatures emptyDeviceFeatures; |
| deMemset(&emptyDeviceFeatures, 0, sizeof(emptyDeviceFeatures)); |
| |
| const VkPhysicalDeviceFeatures2 deviceFeatures = |
| { |
| VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, // VkStructureType sType; |
| &protectedFeatures, // void* pNext; |
| emptyDeviceFeatures // VkPhysicalDeviceFeatures features; |
| }; |
| |
| const VkDeviceCreateInfo deviceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType; |
| &deviceFeatures, // const void* pNext; |
| (VkDeviceCreateFlags)0u, // VkDeviceCreateFlags flags; |
| 1, // deUint32 queueCreateInfoCount; |
| &deviceQueueCreateInfo, // const VkDeviceQueueCreateInfo* pQueueCreateInfos; |
| 0, // deUint32 enabledLayerCount; |
| DE_NULL, // const char* const* ppEnabledLayerNames; |
| 0, // deUint32 enabledExtensionCount; |
| DE_NULL, // const char* const* ppEnabledExtensionNames; |
| DE_NULL, // const VkPhysicalDeviceFeatures* pEnabledFeatures; |
| }; |
| |
| const VkDeviceQueueInfo2 deviceQueueInfo2 = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT, // VkDeviceQueueCreateFlags flags; |
| queueFamilyIndex, // deUint32 queueFamilyIndex; |
| queueIndex, // deUint32 queueIndex; |
| }; |
| |
| { |
| const Unique<VkDevice> device (createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), platformInterface, instance, instanceDriver, physicalDevice, &deviceCreateInfo)); |
| const DeviceDriver deviceDriver (platformInterface, instance, device.get()); |
| const VkQueue queue2 = getDeviceQueue2(deviceDriver, *device, &deviceQueueInfo2); |
| |
| if (queue2 != DE_NULL) |
| return tcu::TestStatus::fail("Fail, getDeviceQueue2 should return VK_NULL_HANDLE when flags in VkDeviceQueueCreateInfo and VkDeviceQueueInfo2 are different."); |
| |
| const VkQueue queue = getDeviceQueue(deviceDriver, *device, queueFamilyIndex, queueIndex); |
| |
| VK_CHECK(deviceDriver.queueWaitIdle(queue)); |
| } |
| |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| // Allocation tracking utilities |
| struct AllocTrack |
| { |
| bool active; |
| bool wasAllocated; |
| void* alignedStartAddress; |
| char* actualStartAddress; |
| size_t requestedSizeBytes; |
| size_t actualSizeBytes; |
| VkSystemAllocationScope allocScope; |
| deUint64 userData; |
| |
| AllocTrack() |
| : active (false) |
| , wasAllocated (false) |
| , alignedStartAddress (DE_NULL) |
| , actualStartAddress (DE_NULL) |
| , requestedSizeBytes (0) |
| , actualSizeBytes (0) |
| , allocScope (VK_SYSTEM_ALLOCATION_SCOPE_COMMAND) |
| , userData(0) {} |
| }; |
| |
| // Global vector to track allocations. This will be resized before each test and emptied after |
| // However, we have to globally define it so the allocation callback functions work properly |
| std::vector<AllocTrack> g_allocatedVector; |
| bool g_intentionalFailEnabled = false; |
| deUint32 g_intenionalFailIndex = 0; |
| deUint32 g_intenionalFailCount = 0; |
| size_t g_allocationsCount = 0; |
| |
| void freeAllocTracker (void) |
| { |
| g_allocatedVector.clear(); |
| g_allocationsCount = 0; |
| } |
| |
| void initAllocTracker (size_t size, deUint32 intentionalFailIndex = (deUint32)~0) |
| { |
| if (g_allocatedVector.size() > 0) |
| freeAllocTracker(); |
| |
| g_allocatedVector.resize(size); |
| |
| if (intentionalFailIndex != (deUint32)~0) |
| { |
| g_intentionalFailEnabled = true; |
| g_intenionalFailIndex = intentionalFailIndex; |
| g_intenionalFailCount = 0; |
| } |
| else |
| { |
| g_intentionalFailEnabled = false; |
| g_intenionalFailIndex = 0; |
| g_intenionalFailCount = 0; |
| } |
| |
| g_allocationsCount = 0; |
| } |
| |
| bool isAllocTrackerEmpty () |
| { |
| bool success = true; |
| bool wasAllocated = false; |
| |
| for (deUint32 vectorIdx = 0; vectorIdx < g_allocatedVector.size(); vectorIdx++) |
| { |
| if (g_allocatedVector[vectorIdx].active) |
| success = false; |
| else if (!wasAllocated && g_allocatedVector[vectorIdx].wasAllocated) |
| wasAllocated = true; |
| } |
| |
| if (!g_intentionalFailEnabled && !wasAllocated) |
| success = false; |
| |
| return success; |
| } |
| |
| VKAPI_ATTR void *VKAPI_CALL allocCallbackFunc (void *pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) |
| { |
| if (g_intentionalFailEnabled) |
| if (++g_intenionalFailCount >= g_intenionalFailIndex) |
| return DE_NULL; |
| |
| for (deUint32 vectorIdx = 0; vectorIdx < g_allocatedVector.size(); vectorIdx++) |
| { |
| if (!g_allocatedVector[vectorIdx].active) |
| { |
| g_allocatedVector[vectorIdx].requestedSizeBytes = size; |
| g_allocatedVector[vectorIdx].actualSizeBytes = size + (alignment - 1); |
| g_allocatedVector[vectorIdx].alignedStartAddress = DE_NULL; |
| g_allocatedVector[vectorIdx].actualStartAddress = new char[g_allocatedVector[vectorIdx].actualSizeBytes]; |
| |
| if (g_allocatedVector[vectorIdx].actualStartAddress != DE_NULL) |
| { |
| deUint64 addr = (deUint64)g_allocatedVector[vectorIdx].actualStartAddress; |
| addr += (alignment - 1); |
| addr &= ~(alignment - 1); |
| g_allocatedVector[vectorIdx].alignedStartAddress = (void *)addr; |
| g_allocatedVector[vectorIdx].allocScope = allocationScope; |
| g_allocatedVector[vectorIdx].userData = (deUint64)pUserData; |
| g_allocatedVector[vectorIdx].active = true; |
| g_allocatedVector[vectorIdx].wasAllocated = true; |
| } |
| |
| g_allocationsCount++; |
| return g_allocatedVector[vectorIdx].alignedStartAddress; |
| } |
| } |
| return DE_NULL; |
| } |
| |
| VKAPI_ATTR void VKAPI_CALL freeCallbackFunc (void *pUserData, void *pMemory) |
| { |
| DE_UNREF(pUserData); |
| |
| for (deUint32 vectorIdx = 0; vectorIdx < g_allocatedVector.size(); vectorIdx++) |
| { |
| if (g_allocatedVector[vectorIdx].active && g_allocatedVector[vectorIdx].alignedStartAddress == pMemory) |
| { |
| delete[] g_allocatedVector[vectorIdx].actualStartAddress; |
| g_allocatedVector[vectorIdx].active = false; |
| break; |
| } |
| } |
| } |
| |
| VKAPI_ATTR void *VKAPI_CALL reallocCallbackFunc (void *pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) |
| { |
| if (pOriginal != DE_NULL) |
| { |
| for (deUint32 vectorIdx = 0; vectorIdx < g_allocatedVector.size(); vectorIdx++) |
| { |
| if (g_allocatedVector[vectorIdx].active && g_allocatedVector[vectorIdx].alignedStartAddress == pOriginal) |
| { |
| if (size == 0) |
| { |
| freeCallbackFunc(pUserData, pOriginal); |
| return DE_NULL; |
| } |
| else if (size < g_allocatedVector[vectorIdx].requestedSizeBytes) |
| return pOriginal; |
| else |
| { |
| void *pNew = allocCallbackFunc(pUserData, size, alignment, allocationScope); |
| |
| if (pNew != DE_NULL) |
| { |
| size_t copySize = size; |
| |
| if (g_allocatedVector[vectorIdx].requestedSizeBytes < size) |
| copySize = g_allocatedVector[vectorIdx].requestedSizeBytes; |
| |
| memcpy(pNew, pOriginal, copySize); |
| freeCallbackFunc(pUserData, pOriginal); |
| } |
| return pNew; |
| } |
| } |
| } |
| return DE_NULL; |
| } |
| else |
| return allocCallbackFunc(pUserData, size, alignment, allocationScope); |
| } |
| |
| tcu::TestStatus createInstanceDeviceIntentionalAllocFail (Context& context) |
| { |
| const PlatformInterface& vkp = context.getPlatformInterface(); |
| const deUint32 chosenDevice = context.getTestContext().getCommandLine().getVKDeviceId() - 1; |
| VkInstance instance = DE_NULL; |
| VkDevice device = DE_NULL; |
| deUint32 physicalDeviceCount = 0; |
| deUint32 queueFamilyCount = 0; |
| deUint32 queueFamilyIndex = 0; |
| const float queuePriority = 0.0f; |
| const VkAllocationCallbacks allocationCallbacks = |
| { |
| DE_NULL, // userData |
| allocCallbackFunc, // pfnAllocation |
| reallocCallbackFunc, // pfnReallocation |
| freeCallbackFunc, // pfnFree |
| DE_NULL, // pfnInternalAllocation |
| DE_NULL // pfnInternalFree |
| }; |
| const VkApplicationInfo appInfo = |
| { |
| VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType |
| DE_NULL, // pNext |
| "appName", // pApplicationName |
| 0u, // applicationVersion |
| "engineName", // pEngineName |
| 0u, // engineVersion |
| VK_API_VERSION_1_0 // apiVersion |
| }; |
| |
| const VkInstanceCreateInfo instanceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (VkInstanceCreateFlags)0u, // flags |
| &appInfo, // pApplicationInfo |
| 0u, // enabledLayerCount |
| DE_NULL, // ppEnabledLayerNames |
| 0u, // enabledExtensionCount |
| DE_NULL // ppEnabledExtensionNames |
| }; |
| |
| deUint32 failIndex = 0; |
| VkResult result = VK_SUCCESS; |
| size_t max_allowed_alloc = 0; |
| |
| do |
| { |
| if (max_allowed_alloc == 0) |
| { |
| if (result != VK_SUCCESS) |
| return tcu::TestStatus::fail("Could not create instance and device"); |
| |
| initAllocTracker(99999); |
| } |
| else |
| { |
| initAllocTracker(max_allowed_alloc, failIndex++); |
| |
| if (failIndex >= static_cast<deUint32>(max_allowed_alloc)) |
| return tcu::TestStatus::fail("Out of retries, could not create instance and device"); |
| } |
| |
| // if the number of allocations the driver makes is large, we may end up |
| // taking more than the watchdog timeout. touch here to avoid spurious |
| // failures. |
| if (failIndex % 128 == 0) |
| context.getTestContext().touchWatchdog(); |
| |
| result = vkp.createInstance(&instanceCreateInfo, &allocationCallbacks, &instance); |
| |
| if (result == VK_ERROR_OUT_OF_HOST_MEMORY) |
| { |
| if (!isAllocTrackerEmpty()) |
| return tcu::TestStatus::fail("Allocations still remain, failed on index " + de::toString(failIndex)); |
| |
| freeAllocTracker(); |
| continue; |
| } |
| else if (result != VK_SUCCESS) |
| return tcu::TestStatus::fail("createInstance returned " + de::toString(result)); |
| |
| const InstanceDriver instanceDriver (vkp, instance); |
| const InstanceInterface& vki (instanceDriver); |
| |
| result = vki.enumeratePhysicalDevices(instance, &physicalDeviceCount, DE_NULL); |
| |
| if (result == VK_ERROR_OUT_OF_HOST_MEMORY) |
| { |
| vki.destroyInstance(instance, &allocationCallbacks); |
| |
| if (!isAllocTrackerEmpty()) |
| return tcu::TestStatus::fail("Allocations still remain, failed on index " + de::toString(failIndex)); |
| |
| freeAllocTracker(); |
| continue; |
| } |
| else if (result != VK_SUCCESS) |
| return tcu::TestStatus::fail("enumeratePhysicalDevices returned " + de::toString(result)); |
| |
| vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount); |
| |
| result = vki.enumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data()); |
| |
| if (result == VK_ERROR_OUT_OF_HOST_MEMORY) |
| { |
| vki.destroyInstance(instance, &allocationCallbacks); |
| |
| if (!isAllocTrackerEmpty()) |
| return tcu::TestStatus::fail("Allocations still remain, failed on index " + de::toString(failIndex)); |
| |
| freeAllocTracker(); |
| continue; |
| } |
| else if (result != VK_SUCCESS) |
| return tcu::TestStatus::fail("enumeratePhysicalDevices returned " + de::toString(result)); |
| |
| vki.getPhysicalDeviceQueueFamilyProperties(physicalDevices[chosenDevice], &queueFamilyCount, DE_NULL); |
| |
| if (queueFamilyCount == 0u) |
| return tcu::TestStatus::fail("getPhysicalDeviceQueueFamilyProperties returned zero queue families"); |
| |
| vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount); |
| |
| vki.getPhysicalDeviceQueueFamilyProperties(physicalDevices[chosenDevice], &queueFamilyCount, queueFamilies.data()); |
| |
| if (queueFamilyCount == 0u) |
| return tcu::TestStatus::fail("getPhysicalDeviceQueueFamilyProperties returned zero queue families"); |
| |
| for (deUint32 i = 0; i < queueFamilyCount; i++) |
| { |
| if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) |
| { |
| queueFamilyIndex = i; |
| break; |
| } |
| } |
| |
| const VkDeviceQueueCreateInfo deviceQueueCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (VkDeviceQueueCreateFlags)0u, // flags |
| queueFamilyIndex, // queueFamilyIndex |
| 1u, // queueCount |
| &queuePriority // pQueuePriorities |
| }; |
| |
| const VkDeviceCreateInfo deviceCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType |
| DE_NULL, // pNext |
| (VkDeviceCreateFlags)0u, // flags |
| 1u, // queueCreateInfoCount |
| &deviceQueueCreateInfo, // pQueueCreateInfos |
| 0u, // enabledLayerCount |
| DE_NULL, // ppEnabledLayerNames |
| 0u, // enabledExtensionCount |
| DE_NULL, // ppEnabledExtensionNames |
| DE_NULL // pEnabledFeatures |
| }; |
| |
| result = createUncheckedDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vki, physicalDevices[chosenDevice], &deviceCreateInfo, &allocationCallbacks, &device); |
| |
| if (result == VK_ERROR_OUT_OF_HOST_MEMORY) |
| { |
| vki.destroyInstance(instance, &allocationCallbacks); |
| |
| if (!isAllocTrackerEmpty()) |
| return tcu::TestStatus::fail("Allocations still remain, failed on index " + de::toString(failIndex)); |
| |
| freeAllocTracker(); |
| continue; |
| } |
| else if (result != VK_SUCCESS) |
| return tcu::TestStatus::fail("VkCreateDevice returned " + de::toString(result)); |
| |
| DeviceDriver(vkp, instance, device).destroyDevice(device, &allocationCallbacks); |
| vki.destroyInstance(instance, &allocationCallbacks); |
| if (max_allowed_alloc == 0) |
| { |
| max_allowed_alloc = g_allocationsCount + 100; |
| result = VK_ERROR_OUT_OF_HOST_MEMORY; |
| } |
| freeAllocTracker(); |
| } |
| while (result == VK_ERROR_OUT_OF_HOST_MEMORY); |
| |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| } // anonymous |
| |
| tcu::TestCaseGroup* createDeviceInitializationTests (tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> deviceInitializationTests (new tcu::TestCaseGroup(testCtx, "device_init", "Device Initialization Tests")); |
| |
| addFunctionCase(deviceInitializationTests.get(), "create_instance_name_version", "", createInstanceTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_instance_invalid_api_version", "", createInstanceWithInvalidApiVersionTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_instance_null_appinfo", "", createInstanceWithNullApplicationInfoTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_instance_unsupported_extensions", "", createInstanceWithUnsupportedExtensionsTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_instance_extension_name_abuse", "", createInstanceWithExtensionNameAbuseTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_instance_layer_name_abuse", "", createInstanceWithLayerNameAbuseTest); |
| addFunctionCase(deviceInitializationTests.get(), "enumerate_devices_alloc_leak", "", enumerateDevicesAllocLeakTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_device", "", createDeviceTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_multiple_devices", "", createMultipleDevicesTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_device_unsupported_extensions", "", createDeviceWithUnsupportedExtensionsTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_device_various_queue_counts", "", createDeviceWithVariousQueueCountsTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_device_global_priority", "", checkGlobalPrioritySupport, createDeviceWithGlobalPriorityTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_device_global_priority_query", "", checkGlobalPriorityQuerySupport, createDeviceWithQueriedGlobalPriorityTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_device_features2", "", createDeviceFeatures2Test); |
| addFunctionCase(deviceInitializationTests.get(), "create_device_unsupported_features", "", createDeviceWithUnsupportedFeaturesTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_device_queue2", "", createDeviceQueue2Test); |
| addFunctionCase(deviceInitializationTests.get(), "create_device_queue2_unmatched_flags", "", createDeviceQueue2UnmatchedFlagsTest); |
| addFunctionCase(deviceInitializationTests.get(), "create_instance_device_intentional_alloc_fail", "", createInstanceDeviceIntentionalAllocFail); |
| |
| return deviceInitializationTests.release(); |
| } |
| |
| } // api |
| } // vkt |