vk: reformat, cleanup VulkanPlatform.cpp (#8457)

This commit is contained in:
Powei Feng
2025-02-19 16:50:37 -08:00
committed by GitHub
parent 62b8a60527
commit d60e44d989

View File

@@ -45,7 +45,7 @@ namespace filament::backend {
namespace {
constexpr uint32_t const INVALID_VK_INDEX = 0xFFFFFFFF;
constexpr uint32_t INVALID_VK_INDEX = 0xFFFFFFFF;
using ExtensionSet = VulkanPlatform::ExtensionSet;
@@ -56,25 +56,25 @@ inline bool setContains(ExtensionSet const& set, utils::CString const& extension
#if FVK_ENABLED(FVK_DEBUG_VALIDATION)
// These strings need to be allocated outside a function stack
const std::string_view DESIRED_LAYERS[] = {
"VK_LAYER_KHRONOS_validation",
"VK_LAYER_KHRONOS_validation",
#if FVK_ENABLED(FVK_DEBUG_DUMP_API)
"VK_LAYER_LUNARG_api_dump",
"VK_LAYER_LUNARG_api_dump",
#endif
#if defined(ENABLE_RENDERDOC)
"VK_LAYER_RENDERDOC_Capture",
"VK_LAYER_RENDERDOC_Capture",
#endif
};
FixedCapacityVector<const char*> getEnabledLayers() {
constexpr size_t kMaxEnabledLayersCount = sizeof(DESIRED_LAYERS) / sizeof(DESIRED_LAYERS[0]);
const FixedCapacityVector<VkLayerProperties> availableLayers
FixedCapacityVector<VkLayerProperties> const availableLayers
= fvkutils::enumerate(vkEnumerateInstanceLayerProperties);
auto enabledLayers = FixedCapacityVector<const char*>::with_capacity(kMaxEnabledLayersCount);
for (auto const& desired: DESIRED_LAYERS) {
for (const VkLayerProperties& layer: availableLayers) {
const std::string_view availableLayer(layer.layerName);
for (VkLayerProperties const& layer: availableLayers) {
std::string_view const availableLayer(layer.layerName);
if (availableLayer == desired) {
enabledLayers.push_back(desired.data());
break;
@@ -127,13 +127,13 @@ void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
// Since we don't have any vendor-specific workarounds yet, there's no need to make this
// mapping in code. The "deviceName" string informally reveals the marketing name for the
// GPU. (e.g., Quadro)
const uint32_t driverVersion = deviceProperties.driverVersion;
const uint32_t vendorID = deviceProperties.vendorID;
const uint32_t deviceID = deviceProperties.deviceID;
const int major = VK_VERSION_MAJOR(deviceProperties.apiVersion);
const int minor = VK_VERSION_MINOR(deviceProperties.apiVersion);
uint32_t const driverVersion = deviceProperties.driverVersion;
uint32_t const vendorID = deviceProperties.vendorID;
uint32_t const deviceID = deviceProperties.deviceID;
int const major = VK_VERSION_MAJOR(deviceProperties.apiVersion);
int const minor = VK_VERSION_MINOR(deviceProperties.apiVersion);
const FixedCapacityVector<VkPhysicalDevice> physicalDevices
FixedCapacityVector<VkPhysicalDevice> const physicalDevices
= fvkutils::enumerate(vkEnumeratePhysicalDevices, instance);
FVK_LOGI << "Selected physical device '" << deviceProperties.deviceName << "' from "
@@ -148,8 +148,8 @@ void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
void printDepthFormats(VkPhysicalDevice device) {
// For diagnostic purposes, print useful information about available depth formats.
// Note that Vulkan is more constrained than OpenGL ES 3.1 in this area.
const VkFormatFeatureFlags required = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
constexpr VkFormatFeatureFlags required =
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
FVK_LOGI << "Sampleable depth formats: ";
for (VkFormat format : fvkutils::ALL_VK_FORMATS) {
VkFormatProperties props;
@@ -168,11 +168,13 @@ ExtensionSet getInstanceExtensions(ExtensionSet const& externallyRequiredExts =
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
// Request these if available.
// Request these if available.
#if FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
#endif
#if defined(__APPLE__)
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
#endif
#if FVK_ENABLED(FVK_DEBUG_VALIDATION)
VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
@@ -182,8 +184,8 @@ ExtensionSet getInstanceExtensions(ExtensionSet const& externallyRequiredExts =
FixedCapacityVector<VkExtensionProperties> const availableExts =
fvkutils::enumerate(vkEnumerateInstanceExtensionProperties,
static_cast<char const*>(nullptr) /* pLayerName */);
for (auto const& extProps: availableExts) {
utils::CString name { extProps.extensionName };
for (auto const& extension: availableExts) {
utils::CString name { extension.extensionName };
// To workaround an Adreno bug where the extension name could be of 0 length.
if (name.size() == 0) {
@@ -200,22 +202,24 @@ ExtensionSet getInstanceExtensions(ExtensionSet const& externallyRequiredExts =
ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
ExtensionSet const TARGET_EXTS = {
#if FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
VK_EXT_DEBUG_MARKER_EXTENSION_NAME,
VK_EXT_DEBUG_MARKER_EXTENSION_NAME,
#endif
// We only support external image for Android for now, but nothing bars us from
// supporting other platforms.
// 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,
VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
#endif
VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
VK_KHR_MAINTENANCE2_EXTENSION_NAME,
VK_KHR_MAINTENANCE3_EXTENSION_NAME,
VK_KHR_MULTIVIEW_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
#endif
// MoltenVk is the only non-conformant implementation we're interested in.
#if defined(__APPLE__)
VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,
#endif
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
VK_KHR_MAINTENANCE2_EXTENSION_NAME,
VK_KHR_MAINTENANCE3_EXTENSION_NAME,
VK_KHR_MULTIVIEW_EXTENSION_NAME,
};
ExtensionSet exts;
// Identify supported physical device extensions
@@ -238,9 +242,18 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
}
VkInstance createInstance(ExtensionSet const& requiredExts) {
// Create the Vulkan instance.
VkApplicationInfo appInfo = {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pEngineName = "Filament",
.apiVersion =
VK_MAKE_API_VERSION(0, FVK_REQUIRED_VERSION_MAJOR, FVK_REQUIRED_VERSION_MINOR, 0),
};
VkInstance instance;
VkInstanceCreateInfo instanceCreateInfo = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pApplicationInfo = &appInfo,
};
bool validationFeaturesSupported = false;
@@ -271,10 +284,10 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
}
#endif // FVK_ENABLED(FVK_DEBUG_VALIDATION)
// The Platform class can require 1 or 2 instance extensions, plus we'll request at most 5
// instance extensions here in the common code. So that's a max of 7.
static constexpr uint32_t MAX_INSTANCE_EXTENSION_COUNT = 8;
const char* ppEnabledExtensions[MAX_INSTANCE_EXTENSION_COUNT];
// The Platform class can require 1 or 2 instance extensions, plus we'll request at most 6
// instance extensions here in the common code. So that's a max of 8.
constexpr uint32_t MAX_INSTANCE_EXTENSION_COUNT = 8;
char const* ppEnabledExtensions[MAX_INSTANCE_EXTENSION_COUNT];
uint32_t enabledExtensionCount = 0;
if (validationFeaturesSupported) {
@@ -286,29 +299,23 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
ppEnabledExtensions[enabledExtensionCount++] = requiredExt.data();
}
// Create the Vulkan instance.
VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pEngineName = "Filament";
appInfo.apiVersion
= VK_MAKE_API_VERSION(0, FVK_REQUIRED_VERSION_MAJOR, FVK_REQUIRED_VERSION_MINOR, 0);
instanceCreateInfo.pApplicationInfo = &appInfo;
instanceCreateInfo.enabledExtensionCount = enabledExtensionCount;
instanceCreateInfo.ppEnabledExtensionNames = ppEnabledExtensions;
if (setContains(requiredExts, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) {
instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
}
VkValidationFeaturesEXT features = {
.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
};
// Validation features
VkValidationFeatureEnableEXT enables[] = {
VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
};
VkValidationFeaturesEXT features = {
.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
.enabledValidationFeatureCount = sizeof(enables) / sizeof(enables[0]),
.pEnabledValidationFeatures = enables,
};
if (validationFeaturesSupported) {
features.enabledValidationFeatureCount = sizeof(enables) / sizeof(enables[0]);
features.pEnabledValidationFeatures = enables;
chainStruct(&instanceCreateInfo, &features);
}
@@ -336,16 +343,15 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
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;
deviceQueueCreateInfo[0].pQueuePriorities = &queuePriority[0];
deviceQueueCreateInfo[0] = {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.queueFamilyIndex = graphicsQueueFamilyIndex,
.queueCount = 1,
.pQueuePriorities = &queuePriority[0],
};
// Protected queue
deviceQueueCreateInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
deviceQueueCreateInfo[1] = deviceQueueCreateInfo[0];
deviceQueueCreateInfo[1].flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
deviceQueueCreateInfo[1].queueFamilyIndex = protectedGraphicsQueueFamilyIndex;
deviceQueueCreateInfo[1].queueCount = 1;
deviceQueueCreateInfo[1].pQueuePriorities = &queuePriority[0];
bool const hasProtectedQueue = protectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX;
deviceCreateInfo.queueCreateInfoCount = hasProtectedQueue ? 2 : 1;
@@ -354,21 +360,21 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
// We could simply enable all supported features, but since that may have performance
// consequences let's just enable the features we need.
VkPhysicalDeviceFeatures enabledFeatures{
.depthClamp = features.features.depthClamp,
.samplerAnisotropy = features.features.samplerAnisotropy,
.textureCompressionETC2 = features.features.textureCompressionETC2,
.textureCompressionBC = features.features.textureCompressionBC,
.shaderClipDistance = features.features.shaderClipDistance,
.depthClamp = features.features.depthClamp,
.samplerAnisotropy = features.features.samplerAnisotropy,
.textureCompressionETC2 = features.features.textureCompressionETC2,
.textureCompressionBC = features.features.textureCompressionBC,
.shaderClipDistance = features.features.shaderClipDistance,
};
deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
deviceCreateInfo.enabledExtensionCount = (uint32_t) requestExtensions.size();
deviceCreateInfo.ppEnabledExtensionNames = requestExtensions.data();
VkPhysicalDevicePortabilitySubsetFeaturesKHR portability = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR,
.imageViewFormatSwizzle = VK_TRUE,
.imageView2DOn3DImage = requestImageView2DOn3DImage ? VK_TRUE : VK_FALSE,
.imageView2DOn3DImage = requestImageView2DOn3DImage ? VK_TRUE : VK_FALSE,
.mutableComparisonSamplers = VK_TRUE,
};
if (setContains(deviceExtensions, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) {
@@ -404,7 +410,8 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
// This method is used to enable/disable extensions based on external factors (i.e.
// driver/device workarounds).
std::tuple<ExtensionSet, ExtensionSet> pruneExtensions(VkPhysicalDevice device,
ExtensionSet const& instExts, ExtensionSet const& deviceExts) {
Platform::DriverConfig const& driverConfig, ExtensionSet const& instExts,
ExtensionSet const& deviceExts) noexcept {
ExtensionSet newInstExts = instExts;
ExtensionSet newDeviceExts = deviceExts;
@@ -424,6 +431,10 @@ std::tuple<ExtensionSet, ExtensionSet> pruneExtensions(VkPhysicalDevice device,
}
#endif
if (driverConfig.stereoscopicType != StereoscopicType::MULTIVIEW) {
newDeviceExts.erase(VK_KHR_MULTIVIEW_EXTENSION_NAME);
}
return std::tuple(newInstExts, newDeviceExts);
}
@@ -457,22 +468,17 @@ uint32_t identifyGraphicsQueueFamilyIndex(VkPhysicalDevice physicalDevice, VkQue
// Enum based on:
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceType.html
inline int deviceTypeOrder(VkPhysicalDeviceType deviceType) {
switch (deviceType) {
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
return 5;
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
return 4;
case VK_PHYSICAL_DEVICE_TYPE_CPU:
return 3;
case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
return 2;
case VK_PHYSICAL_DEVICE_TYPE_OTHER:
return 1;
default:
FVK_LOGW << "deviceTypeOrder: Unexpected deviceType: " << deviceType
<< utils::io::endl;
return -1;
constexpr std::array<VkPhysicalDeviceType, 5> TYPES = {
VK_PHYSICAL_DEVICE_TYPE_OTHER,
VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,
VK_PHYSICAL_DEVICE_TYPE_CPU,
VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,
};
if (auto itr = std::find(TYPES.begin(), TYPES.end(), deviceType); itr != TYPES.end()) {
return std::distance(TYPES.begin(), itr);
}
return -1;
}
VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
@@ -515,20 +521,19 @@ VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
FixedCapacityVector<VkExtensionProperties> const extensions
= fvkutils::enumerate(vkEnumerateDeviceExtensionProperties,
candidateDevice, static_cast<char const*>(nullptr) /* pLayerName */);
bool supportsSwapchain = false;
for (auto const& extension: extensions) {
if (!strcmp(extension.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
supportsSwapchain = true;
break;
}
}
bool const supportsSwapchain =
std::any_of(extensions.begin(), extensions.end(), [](auto const& ext) {
return !strcmp(ext.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
});
if (!supportsSwapchain) {
continue;
}
deviceList[deviceInd].device = candidateDevice;
deviceList[deviceInd].deviceType = targetDeviceProperties.deviceType;
deviceList[deviceInd].index = deviceInd;
deviceList[deviceInd].name = targetDeviceProperties.deviceName;
deviceList[deviceInd] = {
.device = candidateDevice,
.deviceType = targetDeviceProperties.deviceType,
.index = (int8_t) deviceInd,
.name = targetDeviceProperties.deviceName,
};
}
FILAMENT_CHECK_PRECONDITION(gpuPreference.index < static_cast<int32_t>(deviceList.size()))
@@ -569,7 +574,7 @@ fvkutils::VkFormatList findAttachmentDepthStencilFormats(VkPhysicalDevice device
VkFormatFeatureFlags const features = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
// The ordering here indicates the preference of choosing depth+stencil format.
VkFormat const formats[] = {
constexpr VkFormat formats[] = {
VK_FORMAT_D32_SFLOAT,
VK_FORMAT_X8_D24_UNORM_PACK32,
@@ -591,7 +596,7 @@ fvkutils::VkFormatList findAttachmentDepthStencilFormats(VkPhysicalDevice device
fvkutils::VkFormatList findBlittableDepthStencilFormats(VkPhysicalDevice device) {
std::vector<VkFormat> selectedFormats;
VkFormatFeatureFlags const required = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |
constexpr VkFormatFeatureFlags required = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
for (VkFormat format : fvkutils::ALL_VK_FORMATS) {
if (fvkutils::isVkDepthFormat(format)) {
@@ -651,7 +656,7 @@ void VulkanPlatform::terminate() {
// This is the main entry point for context creation.
Driver* VulkanPlatform::createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept {
Platform::DriverConfig const& driverConfig) noexcept {
// Load Vulkan entry points.
FILAMENT_CHECK_POSTCONDITION(bluevk::initialize()) << "BlueVK is unable to load entry points.";
@@ -679,7 +684,6 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
}
VulkanContext context;
ExtensionSet instExts;
// If using a shared context, we do not assume any extensions.
if (!mImpl->mSharedContext) {
@@ -704,9 +708,9 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
instExts.merge(getRequiredInstanceExtensions());
}
mImpl->mInstance
= mImpl->mInstance == VK_NULL_HANDLE ? createInstance(instExts) : mImpl->mInstance;
if (mImpl->mInstance == VK_NULL_HANDLE) {
mImpl->mInstance = createInstance(instExts);
}
assert_invariant(mImpl->mInstance != VK_NULL_HANDLE);
bluevk::bindInstance(mImpl->mInstance);
@@ -716,9 +720,9 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
FILAMENT_CHECK_PRECONDITION(!(hasGPUPreference && sharedContext))
<< "Cannot both share context and indicate GPU preference";
mImpl->mPhysicalDevice = mImpl->mPhysicalDevice == VK_NULL_HANDLE
? selectPhysicalDevice(mImpl->mInstance, pref)
: mImpl->mPhysicalDevice;
if (mImpl->mPhysicalDevice == VK_NULL_HANDLE) {
mImpl->mPhysicalDevice = selectPhysicalDevice(mImpl->mInstance, pref);
}
assert_invariant(mImpl->mPhysicalDevice != VK_NULL_HANDLE);
printDeviceInfo(mImpl->mInstance, mImpl->mPhysicalDevice);
@@ -732,59 +736,52 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
chainStruct(&context.mPhysicalDeviceFeatures, &queryProtectedMemoryFeatures);
chainStruct(&context.mPhysicalDeviceProperties, &protectedMemoryProperties);
// We know we need to allocate the protected version of the VK objects
context.mProtectedMemorySupported =
static_cast<bool>(queryProtectedMemoryFeatures.protectedMemory);
// Initialize the following fields: physicalDeviceProperties, memoryProperties,
// physicalDeviceFeatures, graphicsQueueFamilyIndex.
vkGetPhysicalDeviceProperties2(mImpl->mPhysicalDevice, &context.mPhysicalDeviceProperties);
vkGetPhysicalDeviceFeatures2(mImpl->mPhysicalDevice, &context.mPhysicalDeviceFeatures);
vkGetPhysicalDeviceMemoryProperties(mImpl->mPhysicalDevice, &context.mMemoryProperties);
mImpl->mGraphicsQueueFamilyIndex
= mImpl->mGraphicsQueueFamilyIndex == INVALID_VK_INDEX
? 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 =
static_cast<bool>(queryProtectedMemoryFeatures.protectedMemory);
if (context.mProtectedMemorySupported) {
mImpl->mProtectedGraphicsQueueFamilyIndex
= identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_PROTECTED_BIT));
assert_invariant(mImpl->mProtectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX);
}
// Only enable shaderClipDistance if we are doing instanced stereoscopic rendering.
if (context.mPhysicalDeviceFeatures.features.shaderClipDistance == VK_TRUE
&& driverConfig.stereoscopicType != StereoscopicType::INSTANCED) {
context.mPhysicalDeviceFeatures.features.shaderClipDistance = VK_FALSE;
if (mImpl->mGraphicsQueueFamilyIndex == INVALID_VK_INDEX) {
mImpl->mGraphicsQueueFamilyIndex =
identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice, VK_QUEUE_GRAPHICS_BIT);
}
// At this point, we should have a family index that points to a family that has > 0 queues for
// graphics. In which case, we will allocate one queue for all of Filament (and assumes at least
// one has been allocated by the client if context was shared). If the index of the target queue
// within the family hasn't been provided by the client, we assume it to be 0.
mImpl->mGraphicsQueueIndex
= mImpl->mGraphicsQueueIndex == INVALID_VK_INDEX ? 0 : mImpl->mGraphicsQueueIndex;
if (mImpl->mGraphicsQueueIndex == INVALID_VK_INDEX) {
mImpl->mGraphicsQueueIndex = 0;
}
// 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;
if (context.mProtectedMemorySupported) {
mImpl->mProtectedGraphicsQueueFamilyIndex = identifyGraphicsQueueFamilyIndex(
mImpl->mPhysicalDevice, (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_PROTECTED_BIT));
// Applying the same logic to the protected queue index (Not sure about shared context and
// protection)
if (mImpl->mProtectedGraphicsQueueIndex == INVALID_VK_INDEX) {
mImpl->mProtectedGraphicsQueueIndex = 0;
}
}
// Only enable shaderClipDistance if we are doing instanced stereoscopic rendering.
if (driverConfig.stereoscopicType != StereoscopicType::INSTANCED) {
context.mPhysicalDeviceFeatures.features.shaderClipDistance = VK_FALSE;
}
ExtensionSet deviceExts;
// If using a shared context, we do not assume any extensions.
if (!mImpl->mSharedContext) {
deviceExts = getDeviceExtensions(mImpl->mPhysicalDevice);
auto [prunedInstExts, prunedDeviceExts]
= pruneExtensions(mImpl->mPhysicalDevice, instExts, deviceExts);
auto [prunedInstExts, prunedDeviceExts] =
pruneExtensions(mImpl->mPhysicalDevice, driverConfig, instExts, deviceExts);
instExts = prunedInstExts;
deviceExts = prunedDeviceExts;
if (driverConfig.stereoscopicType != StereoscopicType::MULTIVIEW) {
deviceExts.erase(VK_KHR_MULTIVIEW_EXTENSION_NAME);
}
}
bool requestPortabilitySubsetImageView2DOn3DImage = false;
@@ -797,26 +794,32 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
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;
if (mImpl->mDevice == VK_NULL_HANDLE) {
mImpl->mDevice =
createLogicalDevice(mImpl->mPhysicalDevice, context.mPhysicalDeviceFeatures,
mImpl->mGraphicsQueueFamilyIndex, mImpl->mProtectedGraphicsQueueFamilyIndex,
deviceExts, requestPortabilitySubsetImageView2DOn3DImage);
}
assert_invariant(mImpl->mDevice != VK_NULL_HANDLE);
assert_invariant(mImpl->mGraphicsQueueFamilyIndex != INVALID_VK_INDEX);
assert_invariant(mImpl->mGraphicsQueueIndex != INVALID_VK_INDEX);
vkGetDeviceQueue(mImpl->mDevice, mImpl->mGraphicsQueueFamilyIndex, mImpl->mGraphicsQueueIndex,
&mImpl->mGraphicsQueue);
assert_invariant(mImpl->mGraphicsQueue != VK_NULL_HANDLE);
if (context.mProtectedMemorySupported) {
VkDeviceQueueInfo2 info = {};
info.queueFamilyIndex = mImpl->mProtectedGraphicsQueueFamilyIndex;
info.queueIndex = mImpl->mProtectedGraphicsQueueIndex;
info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2;
info.flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
assert_invariant(mImpl->mProtectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX);
assert_invariant(mImpl->mProtectedGraphicsQueueIndex != INVALID_VK_INDEX);
VkDeviceQueueInfo2 info = {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,
.flags = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT,
.queueFamilyIndex = mImpl->mProtectedGraphicsQueueFamilyIndex,
.queueIndex = mImpl->mProtectedGraphicsQueueIndex,
};
vkGetDeviceQueue2(mImpl->mDevice, &info, &mImpl->mProtectedGraphicsQueue);
assert_invariant(mImpl->mProtectedGraphicsQueue != VK_NULL_HANDLE);
}
// Store the extension support in the context
@@ -832,16 +835,14 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
}
// Check the availability of lazily allocated memory
{
context.mLazilyAllocatedMemorySupported = false;
const uint32_t typeCount = context.mMemoryProperties.memoryTypeCount;
for(uint32_t i = 0; i < typeCount; ++i) {
const VkMemoryType type = context.mMemoryProperties.memoryTypes[i];
if (type.propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
context.mLazilyAllocatedMemorySupported = true;
assert_invariant(type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
break;
}
context.mLazilyAllocatedMemorySupported = false;
for (uint32_t i = 0, typeCount = context.mMemoryProperties.memoryTypeCount; i < typeCount;
++i) {
VkMemoryType const type = context.mMemoryProperties.memoryTypes[i];
if (type.propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
context.mLazilyAllocatedMemorySupported = true;
assert_invariant(type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
break;
}
}