blob: 472ef0cfaad0179326600ef087783add786f062e [file] [log] [blame]
/*-------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief Device Initialization Tests
*//*--------------------------------------------------------------------*/
#include "vktApiDeviceInitializationTests.hpp"
#include "vktTestCaseUtil.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 "tcuTestLog.hpp"
#include "tcuResultCollector.hpp"
#include "tcuCommandLine.hpp"
#include "deUniquePtr.hpp"
#include "deStringUtil.hpp"
#include <vector>
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 PlatformInterface& platformInterface = context.getPlatformInterface();
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
{
const Unique<VkInstance> instance(createInstance(platformInterface, &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;
context.getPlatformInterface().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;
{
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 (apiVersion.majorNum == 1 && apiVersion.minorNum == 0)
{
if (result == VK_ERROR_INCOMPATIBLE_DRIVER)
{
TCU_CHECK(!gotInstance);
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(gotInstance);
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 PlatformInterface& platformInterface = context.getPlatformInterface();
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
{
const Unique<VkInstance> instance(createInstance(platformInterface, &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 PlatformInterface& platformInterface = context.getPlatformInterface();
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;
{
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_EXTENSION_NOT_PRESENT)
{
TCU_CHECK(!gotInstance);
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 PlatformInterface& platformInterface = context.getPlatformInterface();
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;
};
{
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_EXTENSION_NOT_PRESENT)
failCount++;
TCU_CHECK(!gotInstance);
}
}
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 createDeviceTest (Context& context)
{
const PlatformInterface& platformInterface = context.getPlatformInterface();
const Unique<VkInstance> instance (createDefaultInstance(platformInterface, context.getUsedApiVersion()));
const InstanceDriver instanceDriver (platformInterface, instance.get());
const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance.get(), 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 (createDevice(platformInterface, *instance, instanceDriver, physicalDevice, &deviceCreateInfo));
const DeviceDriver deviceDriver (platformInterface, instance.get(), 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 Unique<VkInstance> instance (createDefaultInstance(platformInterface, context.getUsedApiVersion()));
const InstanceDriver instanceDriver (platformInterface, instance.get());
const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance.get(), 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 = instanceDriver.createDevice(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.get(), 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.get(), 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.get(), 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 Unique<VkInstance> instance (createDefaultInstance(platformInterface, context.getUsedApiVersion()));
const InstanceDriver instanceDriver (platformInterface, instance.get());
const char* enabledExtensions[] = {"VK_UNSUPPORTED_EXTENSION", "THIS_IS_NOT_AN_EXTENSION", "VK_DONT_SUPPORT_ME"};
const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance.get(), 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 = instanceDriver.createDevice(physicalDevice, &deviceCreateInfo, DE_NULL/*pAllocator*/, &device);
const bool gotDevice = !!device;
if (device)
{
const DeviceDriver deviceIface (platformInterface, instance.get(), 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 Unique<VkInstance> instance (createDefaultInstance(platformInterface, context.getUsedApiVersion()));
const InstanceDriver instanceDriver (platformInterface, instance.get());
const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance.get(), 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 (createDevice(platformInterface, *instance, instanceDriver, physicalDevice, &deviceCreateInfo));
const DeviceDriver deviceDriver (platformInterface, instance.get(), 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");
}
tcu::TestStatus createDeviceFeatures2Test (Context& context)
{
const PlatformInterface& vkp = context.getPlatformInterface();
const Unique<VkInstance> instance (createInstanceWithExtension(vkp, context.getUsedApiVersion(), "VK_KHR_get_physical_device_properties2"));
const InstanceDriver vki (vkp, instance.get());
const VkPhysicalDevice physicalDevice = chooseDevice(vki, instance.get(), context.getTestContext().getCommandLine());
const deUint32 queueFamilyIndex = 0;
const deUint32 queueCount = 1;
const deUint32 queueIndex = 0;
const float queuePriority = 1.0f;
const InstanceDriver instanceDriver (vkp, instance.get());
const vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceDriver, 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,
0,
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 (createDevice(vkp, *instance, vki, physicalDevice, &deviceCreateInfo));
const DeviceDriver vkd (vkp, instance.get(), 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(MEMBER) {#MEMBER, DE_OFFSET_OF(VkPhysicalDeviceFeatures, MEMBER)}
tcu::TestStatus createDeviceWithUnsupportedFeaturesTest (Context& context)
{
tcu::TestLog& log = context.getTestContext().getLog();
tcu::ResultCollector resultCollector (log);
const PlatformInterface& platformInterface = context.getPlatformInterface();
const Move<VkInstance> instance (createDefaultInstance(platformInterface, context.getUsedApiVersion()));
const InstanceDriver instanceDriver (platformInterface, instance.get());
const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance.get(), context.getTestContext().getCommandLine());
const deUint32 queueFamilyIndex = 0;
const deUint32 queueCount = 1;
const float queuePriority = 1.0f;
VkPhysicalDeviceFeatures physicalDeviceFeatures;
const vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice);
instanceDriver.getPhysicalDeviceFeatures(physicalDevice, &physicalDeviceFeatures);
static const Feature features[] =
{
FEATURE_ITEM(robustBufferAccess),
FEATURE_ITEM(fullDrawIndexUint32),
FEATURE_ITEM(imageCubeArray),
FEATURE_ITEM(independentBlend),
FEATURE_ITEM(geometryShader),
FEATURE_ITEM(tessellationShader),
FEATURE_ITEM(sampleRateShading),
FEATURE_ITEM(dualSrcBlend),
FEATURE_ITEM(logicOp),
FEATURE_ITEM(multiDrawIndirect),
FEATURE_ITEM(drawIndirectFirstInstance),
FEATURE_ITEM(depthClamp),
FEATURE_ITEM(depthBiasClamp),
FEATURE_ITEM(fillModeNonSolid),
FEATURE_ITEM(depthBounds),
FEATURE_ITEM(wideLines),
FEATURE_ITEM(largePoints),
FEATURE_ITEM(alphaToOne),
FEATURE_ITEM(multiViewport),
FEATURE_ITEM(samplerAnisotropy),
FEATURE_ITEM(textureCompressionETC2),
FEATURE_ITEM(textureCompressionASTC_LDR),
FEATURE_ITEM(textureCompressionBC),
FEATURE_ITEM(occlusionQueryPrecise),
FEATURE_ITEM(pipelineStatisticsQuery),
FEATURE_ITEM(vertexPipelineStoresAndAtomics),
FEATURE_ITEM(fragmentStoresAndAtomics),
FEATURE_ITEM(shaderTessellationAndGeometryPointSize),
FEATURE_ITEM(shaderImageGatherExtended),
FEATURE_ITEM(shaderStorageImageExtendedFormats),
FEATURE_ITEM(shaderStorageImageMultisample),
FEATURE_ITEM(shaderStorageImageReadWithoutFormat),
FEATURE_ITEM(shaderStorageImageWriteWithoutFormat),
FEATURE_ITEM(shaderUniformBufferArrayDynamicIndexing),
FEATURE_ITEM(shaderSampledImageArrayDynamicIndexing),
FEATURE_ITEM(shaderStorageBufferArrayDynamicIndexing),
FEATURE_ITEM(shaderStorageImageArrayDynamicIndexing),
FEATURE_ITEM(shaderClipDistance),
FEATURE_ITEM(shaderCullDistance),
FEATURE_ITEM(shaderFloat64),
FEATURE_ITEM(shaderInt64),
FEATURE_ITEM(shaderInt16),
FEATURE_ITEM(shaderResourceResidency),
FEATURE_ITEM(shaderResourceMinLod),
FEATURE_ITEM(sparseBinding),
FEATURE_ITEM(sparseResidencyBuffer),
FEATURE_ITEM(sparseResidencyImage2D),
FEATURE_ITEM(sparseResidencyImage3D),
FEATURE_ITEM(sparseResidency2Samples),
FEATURE_ITEM(sparseResidency4Samples),
FEATURE_ITEM(sparseResidency8Samples),
FEATURE_ITEM(sparseResidency16Samples),
FEATURE_ITEM(sparseResidencyAliased),
FEATURE_ITEM(variableMultisampleRate),
FEATURE_ITEM(inheritedQueries)
};
const int numFeatures = DE_LENGTH_OF_ARRAY(features);
int numErrors = 0;
for (int featureNdx = 0; featureNdx < numFeatures; featureNdx++)
{
// Test only features that are not supported.
if (*(((VkBool32*)((deUint8*)(&physicalDeviceFeatures) + features[featureNdx].offset))))
continue;
VkPhysicalDeviceFeatures enabledFeatures;
for (int i = 0; i < numFeatures; i++)
*((VkBool32*)((deUint8*)(&enabledFeatures) + features[i].offset)) = (i == featureNdx ? VK_TRUE : VK_FALSE);
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,
0,
DE_NULL,
0,
DE_NULL,
&enabledFeatures
};
VkDevice device;
const VkResult res = instanceDriver.createDevice(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 (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 InstanceDriver instanceDriver (platformInterface, instance);
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 (createDevice(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 InstanceDriver instanceDriver (platformInterface, instance);
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 (createDevice(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");
}
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 = vki.createDevice(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(), "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_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