|
|
|
|
@@ -84,6 +84,13 @@ FixedCapacityVector<const char*> getEnabledLayers() {
|
|
|
|
|
}
|
|
|
|
|
#endif // FVK_EANBLED(FVK_DEBUG_VALIDATION)
|
|
|
|
|
|
|
|
|
|
template<typename StructA, typename StructB>
|
|
|
|
|
StructA* chainStruct(StructA* structA, StructB* structB) {
|
|
|
|
|
structB->pNext = const_cast<void*>(structA->pNext);
|
|
|
|
|
structA->pNext = (void*) structB;
|
|
|
|
|
return structA;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
|
|
|
|
|
// Print some driver or MoltenVK information if it is available.
|
|
|
|
|
if (vkGetPhysicalDeviceProperties2) {
|
|
|
|
|
@@ -92,8 +99,8 @@ void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
|
|
|
|
|
};
|
|
|
|
|
VkPhysicalDeviceProperties2 physicalDeviceProperties2 = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
|
|
|
|
|
.pNext = &driverProperties,
|
|
|
|
|
};
|
|
|
|
|
chainStruct(&physicalDeviceProperties2, &driverProperties);
|
|
|
|
|
vkGetPhysicalDeviceProperties2(device, &physicalDeviceProperties2);
|
|
|
|
|
FVK_LOGI << "Vulkan device driver: " << driverProperties.driverName << " "
|
|
|
|
|
<< driverProperties.driverInfo << utils::io::endl;
|
|
|
|
|
@@ -194,7 +201,7 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
|
|
|
|
|
#if FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
|
|
|
|
|
VK_EXT_DEBUG_MARKER_EXTENSION_NAME,
|
|
|
|
|
#endif
|
|
|
|
|
// We only support external image for Android for now, but nothing bars us from
|
|
|
|
|
// We only support external image for Android for now, but nothing bars us from
|
|
|
|
|
// supporting other platforms.
|
|
|
|
|
#if defined(__ANDROID__)
|
|
|
|
|
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
|
|
|
|
|
@@ -231,7 +238,9 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
|
|
|
|
|
|
|
|
|
|
VkInstance createInstance(ExtensionSet const& requiredExts) {
|
|
|
|
|
VkInstance instance;
|
|
|
|
|
VkInstanceCreateInfo instanceCreateInfo = {};
|
|
|
|
|
VkInstanceCreateInfo instanceCreateInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
|
|
|
|
};
|
|
|
|
|
bool validationFeaturesSupported = false;
|
|
|
|
|
|
|
|
|
|
#if FVK_ENABLED(FVK_DEBUG_VALIDATION)
|
|
|
|
|
@@ -282,7 +291,6 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
|
|
|
|
|
appInfo.pEngineName = "Filament";
|
|
|
|
|
appInfo.apiVersion
|
|
|
|
|
= VK_MAKE_API_VERSION(0, FVK_REQUIRED_VERSION_MAJOR, FVK_REQUIRED_VERSION_MINOR, 0);
|
|
|
|
|
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
|
|
|
|
instanceCreateInfo.pApplicationInfo = &appInfo;
|
|
|
|
|
instanceCreateInfo.enabledExtensionCount = enabledExtensionCount;
|
|
|
|
|
instanceCreateInfo.ppEnabledExtensionNames = ppEnabledExtensions;
|
|
|
|
|
@@ -290,16 +298,17 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
|
|
|
|
|
instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkValidationFeaturesEXT features = {};
|
|
|
|
|
VkValidationFeaturesEXT features = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
|
|
|
|
|
};
|
|
|
|
|
VkValidationFeatureEnableEXT enables[] = {
|
|
|
|
|
VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
|
|
|
|
|
VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
|
|
|
|
|
VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
|
|
|
|
|
VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
|
|
|
|
|
};
|
|
|
|
|
if (validationFeaturesSupported) {
|
|
|
|
|
features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
|
|
|
|
|
features.enabledValidationFeatureCount = sizeof(enables) / sizeof(enables[0]);
|
|
|
|
|
features.pEnabledValidationFeatures = enables;
|
|
|
|
|
instanceCreateInfo.pNext = &features;
|
|
|
|
|
chainStruct(&instanceCreateInfo, &features);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult result = vkCreateInstance(&instanceCreateInfo, VKALLOC, &instance);
|
|
|
|
|
@@ -310,11 +319,13 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
|
|
|
|
|
|
|
|
|
|
VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
|
|
|
|
|
VkPhysicalDeviceFeatures2 const& features, uint32_t graphicsQueueFamilyIndex,
|
|
|
|
|
uint32_t protectedGraphicsQueueFamilyIndex, ExtensionSet const& deviceExtensions) {
|
|
|
|
|
uint32_t protectedGraphicsQueueFamilyIndex, ExtensionSet const& deviceExtensions,
|
|
|
|
|
bool requestImageView2DOn3DImage) {
|
|
|
|
|
VkDevice device;
|
|
|
|
|
VkDeviceQueueCreateInfo deviceQueueCreateInfo[2] = {};
|
|
|
|
|
const float queuePriority[] = {1.0f};
|
|
|
|
|
VkDeviceCreateInfo deviceCreateInfo = {};
|
|
|
|
|
float queuePriority[] = {1.0f};
|
|
|
|
|
VkDeviceCreateInfo deviceCreateInfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
|
|
|
|
};
|
|
|
|
|
FixedCapacityVector<const char*> requestExtensions;
|
|
|
|
|
requestExtensions.reserve(deviceExtensions.size() + 1);
|
|
|
|
|
|
|
|
|
|
@@ -323,6 +334,7 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
|
|
|
|
|
for (auto const& ext: deviceExtensions) {
|
|
|
|
|
requestExtensions.push_back(ext.data());
|
|
|
|
|
}
|
|
|
|
|
VkDeviceQueueCreateInfo deviceQueueCreateInfo[2] = {};
|
|
|
|
|
deviceQueueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
|
|
|
deviceQueueCreateInfo[0].queueFamilyIndex = graphicsQueueFamilyIndex;
|
|
|
|
|
deviceQueueCreateInfo[0].queueCount = 1;
|
|
|
|
|
@@ -334,7 +346,6 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
|
|
|
|
|
deviceQueueCreateInfo[1].queueCount = 1;
|
|
|
|
|
deviceQueueCreateInfo[1].pQueuePriorities = &queuePriority[0];
|
|
|
|
|
|
|
|
|
|
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
|
|
|
|
bool const hasProtectedQueue = protectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX;
|
|
|
|
|
deviceCreateInfo.queueCreateInfoCount = hasProtectedQueue ? 2 : 1;
|
|
|
|
|
deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfo;
|
|
|
|
|
@@ -353,42 +364,36 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
|
|
|
|
|
deviceCreateInfo.enabledExtensionCount = (uint32_t) requestExtensions.size();
|
|
|
|
|
deviceCreateInfo.ppEnabledExtensionNames = requestExtensions.data();
|
|
|
|
|
|
|
|
|
|
void* pNext = nullptr;
|
|
|
|
|
VkPhysicalDevicePortabilitySubsetFeaturesKHR portability = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.imageViewFormatSwizzle = VK_TRUE,
|
|
|
|
|
.mutableComparisonSamplers = VK_TRUE,
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR,
|
|
|
|
|
.imageViewFormatSwizzle = VK_TRUE,
|
|
|
|
|
.mutableComparisonSamplers = VK_TRUE,
|
|
|
|
|
.imageView2DOn3DImage = requestImageView2DOn3DImage ? VK_TRUE : VK_FALSE,
|
|
|
|
|
};
|
|
|
|
|
if (setContains(deviceExtensions, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) {
|
|
|
|
|
portability.pNext = pNext;
|
|
|
|
|
pNext = &portability;
|
|
|
|
|
chainStruct(&deviceCreateInfo, &portability);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkPhysicalDeviceMultiviewFeaturesKHR multiview = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.multiview = VK_TRUE,
|
|
|
|
|
.multiviewGeometryShader = VK_FALSE,
|
|
|
|
|
.multiviewTessellationShader = VK_FALSE
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.multiview = VK_TRUE,
|
|
|
|
|
.multiviewGeometryShader = VK_FALSE,
|
|
|
|
|
.multiviewTessellationShader = VK_FALSE,
|
|
|
|
|
};
|
|
|
|
|
if (setContains(deviceExtensions, VK_KHR_MULTIVIEW_EXTENSION_NAME)) {
|
|
|
|
|
multiview.pNext = pNext;
|
|
|
|
|
pNext = &multiview;
|
|
|
|
|
chainStruct(&deviceCreateInfo, &multiview);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkPhysicalDeviceProtectedMemoryFeatures protectedMemory = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,
|
|
|
|
|
.protectedMemory = VK_TRUE,
|
|
|
|
|
};
|
|
|
|
|
if (hasProtectedQueue) {
|
|
|
|
|
// Enable protected memory, if requested.
|
|
|
|
|
protectedMemory.protectedMemory = VK_TRUE;
|
|
|
|
|
protectedMemory.pNext = pNext;
|
|
|
|
|
pNext = &protectedMemory;
|
|
|
|
|
chainStruct(&deviceCreateInfo, &protectedMemory);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
deviceCreateInfo.pNext = pNext;
|
|
|
|
|
|
|
|
|
|
VkResult result = vkCreateDevice(physicalDevice, &deviceCreateInfo, VKALLOC, &device);
|
|
|
|
|
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
|
|
|
|
|
<< "vkCreateDevice error=" << static_cast<int32_t>(result);
|
|
|
|
|
@@ -501,7 +506,7 @@ VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
|
|
|
|
|
// Does the device have any command queues that support graphics?
|
|
|
|
|
// In theory, we should also ensure that the device supports presentation of our
|
|
|
|
|
// particular VkSurface, but we don't have a VkSurface yet, so we'll skip this requirement.
|
|
|
|
|
if (identifyGraphicsQueueFamilyIndex(candidateDevice, VK_QUEUE_GRAPHICS_BIT)
|
|
|
|
|
if (identifyGraphicsQueueFamilyIndex(candidateDevice, VK_QUEUE_GRAPHICS_BIT)
|
|
|
|
|
== INVALID_VK_INDEX) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
@@ -721,14 +726,11 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
|
|
|
|
|
VkPhysicalDeviceProtectedMemoryFeatures queryProtectedMemoryFeatures = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,
|
|
|
|
|
};
|
|
|
|
|
// Chain to the pNext linked list
|
|
|
|
|
queryProtectedMemoryFeatures.pNext = context.mPhysicalDeviceFeatures.pNext;
|
|
|
|
|
context.mPhysicalDeviceFeatures.pNext = &queryProtectedMemoryFeatures;
|
|
|
|
|
VkPhysicalDeviceProtectedMemoryProperties protectedMemoryProperties = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES,
|
|
|
|
|
};
|
|
|
|
|
protectedMemoryProperties.pNext = context.mPhysicalDeviceProperties.pNext;
|
|
|
|
|
context.mPhysicalDeviceProperties.pNext = &protectedMemoryProperties;
|
|
|
|
|
chainStruct(&context.mPhysicalDeviceFeatures, &queryProtectedMemoryFeatures);
|
|
|
|
|
chainStruct(&context.mPhysicalDeviceProperties, &protectedMemoryProperties);
|
|
|
|
|
|
|
|
|
|
// Initialize the following fields: physicalDeviceProperties, memoryProperties,
|
|
|
|
|
// physicalDeviceFeatures, graphicsQueueFamilyIndex.
|
|
|
|
|
@@ -738,17 +740,17 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
|
|
|
|
|
|
|
|
|
|
mImpl->mGraphicsQueueFamilyIndex
|
|
|
|
|
= mImpl->mGraphicsQueueFamilyIndex == INVALID_VK_INDEX
|
|
|
|
|
? identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
|
|
|
|
|
? identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
|
|
|
|
|
VK_QUEUE_GRAPHICS_BIT)
|
|
|
|
|
: mImpl->mGraphicsQueueFamilyIndex;
|
|
|
|
|
assert_invariant(mImpl->mGraphicsQueueFamilyIndex != INVALID_VK_INDEX);
|
|
|
|
|
|
|
|
|
|
// We know we need to allocate the protected version of the VK objects
|
|
|
|
|
context.mProtectedMemorySupported =
|
|
|
|
|
context.mProtectedMemorySupported =
|
|
|
|
|
static_cast<bool>(queryProtectedMemoryFeatures.protectedMemory);
|
|
|
|
|
if (context.mProtectedMemorySupported) {
|
|
|
|
|
mImpl->mProtectedGraphicsQueueFamilyIndex
|
|
|
|
|
= identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
|
|
|
|
|
= identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
|
|
|
|
|
(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_PROTECTED_BIT));
|
|
|
|
|
assert_invariant(mImpl->mProtectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX);
|
|
|
|
|
}
|
|
|
|
|
@@ -768,7 +770,7 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
|
|
|
|
|
|
|
|
|
|
// Applying the same logic to the protected queue index (Not sure about shared context and protection)
|
|
|
|
|
mImpl->mProtectedGraphicsQueueIndex
|
|
|
|
|
= mImpl->mProtectedGraphicsQueueIndex == INVALID_VK_INDEX ? 0 :
|
|
|
|
|
= mImpl->mProtectedGraphicsQueueIndex == INVALID_VK_INDEX ? 0 :
|
|
|
|
|
mImpl->mProtectedGraphicsQueueIndex;
|
|
|
|
|
|
|
|
|
|
ExtensionSet deviceExts;
|
|
|
|
|
@@ -785,11 +787,24 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mImpl->mDevice
|
|
|
|
|
= mImpl->mDevice == VK_NULL_HANDLE ? createLogicalDevice(mImpl->mPhysicalDevice,
|
|
|
|
|
context.mPhysicalDeviceFeatures, mImpl->mGraphicsQueueFamilyIndex,
|
|
|
|
|
mImpl->mProtectedGraphicsQueueFamilyIndex, deviceExts)
|
|
|
|
|
: mImpl->mDevice;
|
|
|
|
|
bool requestPortabilitySubsetImageView2DOn3DImage = false;
|
|
|
|
|
if (setContains(deviceExts, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) {
|
|
|
|
|
// We are on a non-conformant vulkan implementation so we need to ascertain if the features
|
|
|
|
|
// we need are available.
|
|
|
|
|
|
|
|
|
|
chainStruct(&context.mPhysicalDeviceFeatures, &context.mPortabilitySubsetFeatures);
|
|
|
|
|
vkGetPhysicalDeviceFeatures2(mImpl->mPhysicalDevice, &context.mPhysicalDeviceFeatures);
|
|
|
|
|
requestPortabilitySubsetImageView2DOn3DImage =
|
|
|
|
|
context.mPortabilitySubsetFeatures.imageView2DOn3DImage == VK_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mImpl->mDevice =
|
|
|
|
|
mImpl->mDevice == VK_NULL_HANDLE
|
|
|
|
|
? createLogicalDevice(mImpl->mPhysicalDevice, context.mPhysicalDeviceFeatures,
|
|
|
|
|
mImpl->mGraphicsQueueFamilyIndex,
|
|
|
|
|
mImpl->mProtectedGraphicsQueueFamilyIndex, deviceExts,
|
|
|
|
|
requestPortabilitySubsetImageView2DOn3DImage)
|
|
|
|
|
: mImpl->mDevice;
|
|
|
|
|
assert_invariant(mImpl->mDevice != VK_NULL_HANDLE);
|
|
|
|
|
|
|
|
|
|
vkGetDeviceQueue(mImpl->mDevice, mImpl->mGraphicsQueueFamilyIndex, mImpl->mGraphicsQueueIndex,
|
|
|
|
|
|