vk: reformat, cleanup VulkanPlatform.cpp (#8457)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user