Skip to content

Commit

Permalink
Vulkan API version refactors (gfx-rs#4252)
Browse files Browse the repository at this point in the history
  • Loading branch information
teoxoy authored Oct 17, 2023
1 parent c07d889 commit a842019
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 70 deletions.
89 changes: 39 additions & 50 deletions wgpu-hal/src/vulkan/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl PhysicalDeviceFeatures {
///
/// `requested_features` should be the same as what was used to generate `enabled_extensions`.
fn from_extensions_and_requested_features(
effective_api_version: u32,
device_api_version: u32,
enabled_extensions: &[&'static CStr],
requested_features: wgt::Features,
downlevel_flags: wgt::DownlevelFlags,
Expand Down Expand Up @@ -200,7 +200,7 @@ impl PhysicalDeviceFeatures {
} else {
None
},
imageless_framebuffer: if effective_api_version >= vk::API_VERSION_1_2
imageless_framebuffer: if device_api_version >= vk::API_VERSION_1_2
|| enabled_extensions.contains(&vk::KhrImagelessFramebufferFn::name())
{
Some(
Expand All @@ -211,7 +211,7 @@ impl PhysicalDeviceFeatures {
} else {
None
},
timeline_semaphore: if effective_api_version >= vk::API_VERSION_1_2
timeline_semaphore: if device_api_version >= vk::API_VERSION_1_2
|| enabled_extensions.contains(&vk::KhrTimelineSemaphoreFn::name())
{
Some(
Expand All @@ -222,7 +222,7 @@ impl PhysicalDeviceFeatures {
} else {
None
},
image_robustness: if effective_api_version >= vk::API_VERSION_1_3
image_robustness: if device_api_version >= vk::API_VERSION_1_3
|| enabled_extensions.contains(&vk::ExtImageRobustnessFn::name())
{
Some(
Expand All @@ -246,7 +246,7 @@ impl PhysicalDeviceFeatures {
} else {
None
},
multiview: if effective_api_version >= vk::API_VERSION_1_1
multiview: if device_api_version >= vk::API_VERSION_1_1
|| enabled_extensions.contains(&vk::KhrMultiviewFn::name())
{
Some(
Expand Down Expand Up @@ -279,7 +279,7 @@ impl PhysicalDeviceFeatures {
} else {
None
},
zero_initialize_workgroup_memory: if effective_api_version >= vk::API_VERSION_1_3
zero_initialize_workgroup_memory: if device_api_version >= vk::API_VERSION_1_3
|| enabled_extensions.contains(&vk::KhrZeroInitializeWorkgroupMemoryFn::name())
{
Some(
Expand Down Expand Up @@ -526,7 +526,7 @@ impl PhysicalDeviceFeatures {

features.set(
F::BGRA8UNORM_STORAGE,
supports_bgra8unorm_storage(instance, phd, caps.effective_api_version),
supports_bgra8unorm_storage(instance, phd, caps.device_api_version),
);

(features, dl_flags)
Expand All @@ -550,20 +550,12 @@ pub struct PhysicalDeviceCapabilities {
maintenance_3: Option<vk::PhysicalDeviceMaintenance3Properties>,
descriptor_indexing: Option<vk::PhysicalDeviceDescriptorIndexingPropertiesEXT>,
driver: Option<vk::PhysicalDeviceDriverPropertiesKHR>,
/// The effective driver api version supported by the physical device.
/// The device API version.
///
/// The Vulkan specification states the following in the documentation for VkPhysicalDeviceProperties:
/// > The value of apiVersion may be different than the version returned by vkEnumerateInstanceVersion;
/// > either higher or lower. In such cases, the application must not use functionality that exceeds
/// > the version of Vulkan associated with a given object.
/// Which is the version of Vulkan supported for device-level functionality.
///
/// For example, a Vulkan 1.1 instance cannot use functionality added in Vulkan 1.2 even if the physical
/// device supports Vulkan 1.2.
///
/// This means that assuming that the apiVersion provided by VkPhysicalDeviceProperties is the actual
/// version we can use is incorrect. Instead the effective version is the lower of the instance version
/// and physical device version.
effective_api_version: u32,
/// It is associated with a `VkPhysicalDevice` and its children.
device_api_version: u32,
}

// This is safe because the structs have `p_next: *mut c_void`, which we null out/never read.
Expand Down Expand Up @@ -592,7 +584,7 @@ impl PhysicalDeviceCapabilities {
// Require `VK_KHR_swapchain`
extensions.push(vk::KhrSwapchainFn::name());

if self.effective_api_version < vk::API_VERSION_1_1 {
if self.device_api_version < vk::API_VERSION_1_1 {
// Require either `VK_KHR_maintenance1` or `VK_AMD_negative_viewport_height`
if self.supports_extension(vk::KhrMaintenance1Fn::name()) {
extensions.push(vk::KhrMaintenance1Fn::name());
Expand Down Expand Up @@ -620,7 +612,7 @@ impl PhysicalDeviceCapabilities {
}
}

if self.effective_api_version < vk::API_VERSION_1_2 {
if self.device_api_version < vk::API_VERSION_1_2 {
// Optional `VK_KHR_image_format_list`
if self.supports_extension(vk::KhrImageFormatListFn::name()) {
extensions.push(vk::KhrImageFormatListFn::name());
Expand All @@ -630,7 +622,7 @@ impl PhysicalDeviceCapabilities {
if self.supports_extension(vk::KhrImagelessFramebufferFn::name()) {
extensions.push(vk::KhrImagelessFramebufferFn::name());
// Require `VK_KHR_maintenance2` due to it being a dependency
if self.effective_api_version < vk::API_VERSION_1_1 {
if self.device_api_version < vk::API_VERSION_1_1 {
extensions.push(vk::KhrMaintenance2Fn::name());
}
}
Expand All @@ -654,7 +646,7 @@ impl PhysicalDeviceCapabilities {
if requested_features.contains(wgt::Features::SHADER_F16) {
extensions.push(vk::KhrShaderFloat16Int8Fn::name());
// `VK_KHR_16bit_storage` requires `VK_KHR_storage_buffer_storage_class`, however we require that one already
if self.effective_api_version < vk::API_VERSION_1_1 {
if self.device_api_version < vk::API_VERSION_1_1 {
extensions.push(vk::Khr16bitStorageFn::name());
}
}
Expand All @@ -663,7 +655,7 @@ impl PhysicalDeviceCapabilities {
//extensions.push(vk::ExtSamplerFilterMinmaxFn::name());
}

if self.effective_api_version < vk::API_VERSION_1_3 {
if self.device_api_version < vk::API_VERSION_1_3 {
// Optional `VK_EXT_image_robustness`
if self.supports_extension(vk::ExtImageRobustnessFn::name()) {
extensions.push(vk::ExtImageRobustnessFn::name());
Expand Down Expand Up @@ -788,19 +780,22 @@ impl super::InstanceShared {
let mut capabilities = PhysicalDeviceCapabilities::default();
capabilities.supported_extensions =
unsafe { self.raw.enumerate_device_extension_properties(phd).unwrap() };
capabilities.properties = if let Some(ref get_device_properties) =
self.get_physical_device_properties
{
capabilities.properties = unsafe { self.raw.get_physical_device_properties(phd) };
capabilities.device_api_version = capabilities.properties.api_version;

if let Some(ref get_device_properties) = self.get_physical_device_properties {
// Get these now to avoid borrowing conflicts later
let supports_descriptor_indexing = self.driver_api_version >= vk::API_VERSION_1_2
let supports_maintenance3 = capabilities.device_api_version >= vk::API_VERSION_1_1
|| capabilities.supports_extension(vk::KhrMaintenance3Fn::name());
let supports_descriptor_indexing = capabilities.device_api_version
>= vk::API_VERSION_1_2
|| capabilities.supports_extension(vk::ExtDescriptorIndexingFn::name());
let supports_driver_properties = self.driver_api_version >= vk::API_VERSION_1_2
let supports_driver_properties = capabilities.device_api_version
>= vk::API_VERSION_1_2
|| capabilities.supports_extension(vk::KhrDriverPropertiesFn::name());

let mut builder = vk::PhysicalDeviceProperties2KHR::builder();
if self.driver_api_version >= vk::API_VERSION_1_1
|| capabilities.supports_extension(vk::KhrMaintenance3Fn::name())
{
if supports_maintenance3 {
capabilities.maintenance_3 =
Some(vk::PhysicalDeviceMaintenance3Properties::default());
builder = builder.push_next(capabilities.maintenance_3.as_mut().unwrap());
Expand All @@ -824,15 +819,7 @@ impl super::InstanceShared {
unsafe {
get_device_properties.get_physical_device_properties2(phd, &mut properties2);
}
properties2.properties
} else {
unsafe { self.raw.get_physical_device_properties(phd) }
};

// Set the effective api version
capabilities.effective_api_version = self
.driver_api_version
.min(capabilities.properties.api_version);
capabilities
};

Expand All @@ -843,7 +830,7 @@ impl super::InstanceShared {
let mut builder = vk::PhysicalDeviceFeatures2KHR::builder().features(core);

// `VK_KHR_multiview` is promoted to 1.1
if capabilities.effective_api_version >= vk::API_VERSION_1_1
if capabilities.device_api_version >= vk::API_VERSION_1_1
|| capabilities.supports_extension(vk::KhrMultiviewFn::name())
{
let next = features
Expand Down Expand Up @@ -905,7 +892,7 @@ impl super::InstanceShared {
}

// `VK_KHR_zero_initialize_workgroup_memory` is promoted to 1.3
if capabilities.effective_api_version >= vk::API_VERSION_1_3
if capabilities.device_api_version >= vk::API_VERSION_1_3
|| capabilities.supports_extension(vk::KhrZeroInitializeWorkgroupMemoryFn::name())
{
let next = features
Expand Down Expand Up @@ -998,7 +985,7 @@ impl super::Instance {
);
};

if phd_capabilities.effective_api_version == vk::API_VERSION_1_0
if phd_capabilities.device_api_version == vk::API_VERSION_1_0
&& !phd_capabilities.supports_extension(vk::KhrStorageBufferStorageClassFn::name())
{
log::warn!(
Expand All @@ -1009,7 +996,7 @@ impl super::Instance {
}
if !phd_capabilities.supports_extension(vk::AmdNegativeViewportHeightFn::name())
&& !phd_capabilities.supports_extension(vk::KhrMaintenance1Fn::name())
&& phd_capabilities.effective_api_version < vk::API_VERSION_1_1
&& phd_capabilities.device_api_version < vk::API_VERSION_1_1
{
log::warn!(
"viewport Y-flip is not supported, hiding adapter: {}",
Expand All @@ -1030,15 +1017,15 @@ impl super::Instance {
}

let private_caps = super::PrivateCapabilities {
flip_y_requires_shift: phd_capabilities.effective_api_version >= vk::API_VERSION_1_1
flip_y_requires_shift: phd_capabilities.device_api_version >= vk::API_VERSION_1_1
|| phd_capabilities.supports_extension(vk::KhrMaintenance1Fn::name()),
imageless_framebuffers: match phd_features.imageless_framebuffer {
Some(features) => features.imageless_framebuffer == vk::TRUE,
None => phd_features
.imageless_framebuffer
.map_or(false, |ext| ext.imageless_framebuffer != 0),
},
image_view_usage: phd_capabilities.effective_api_version >= vk::API_VERSION_1_1
image_view_usage: phd_capabilities.device_api_version >= vk::API_VERSION_1_1
|| phd_capabilities.supports_extension(vk::KhrMaintenance2Fn::name()),
timeline_semaphores: match phd_features.timeline_semaphore {
Some(features) => features.timeline_semaphore == vk::TRUE,
Expand Down Expand Up @@ -1092,6 +1079,8 @@ impl super::Instance {
.map_or(false, |ext| {
ext.shader_zero_initialize_workgroup_memory == vk::TRUE
}),
image_format_list: phd_capabilities.device_api_version >= vk::API_VERSION_1_2
|| phd_capabilities.supports_extension(vk::KhrImageFormatListFn::name()),
};
let capabilities = crate::Capabilities {
limits: phd_capabilities.to_wgpu_limits(),
Expand Down Expand Up @@ -1165,7 +1154,7 @@ impl super::Adapter {
features: wgt::Features,
) -> PhysicalDeviceFeatures {
PhysicalDeviceFeatures::from_extensions_and_requested_features(
self.phd_capabilities.effective_api_version,
self.phd_capabilities.device_api_version,
enabled_extensions,
features,
self.downlevel_flags,
Expand Down Expand Up @@ -1219,7 +1208,7 @@ impl super::Adapter {
&self.instance.raw,
&raw_device,
)))
} else if self.phd_capabilities.effective_api_version >= vk::API_VERSION_1_2 {
} else if self.phd_capabilities.device_api_version >= vk::API_VERSION_1_2 {
Some(super::ExtensionFn::Promoted)
} else {
None
Expand Down Expand Up @@ -1760,14 +1749,14 @@ fn supports_format(
fn supports_bgra8unorm_storage(
instance: &ash::Instance,
phd: vk::PhysicalDevice,
api_version: u32,
device_api_version: u32,
) -> bool {
// See https://github.com/KhronosGroup/Vulkan-Docs/issues/2027#issuecomment-1380608011

// This check gates the function call and structures used below.
// TODO: check for (`VK_KHR_get_physical_device_properties2` or VK1.1) and (`VK_KHR_format_feature_flags2` or VK1.3).
// Right now we only check for VK1.3.
if api_version < vk::API_VERSION_1_3 {
if device_api_version < vk::API_VERSION_1_3 {
return false;
}

Expand Down
6 changes: 1 addition & 5 deletions wgpu-hal/src/vulkan/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -970,11 +970,7 @@ impl crate::Device<super::Api> for super::Device {
wgt_view_formats = desc.view_formats.clone();
wgt_view_formats.push(desc.format);

if self.shared_instance().driver_api_version >= vk::API_VERSION_1_2
|| self
.enabled_device_extensions()
.contains(&vk::KhrImageFormatListFn::name())
{
if self.shared.private_caps.image_format_list {
vk_view_formats = desc
.view_formats
.iter()
Expand Down
28 changes: 14 additions & 14 deletions wgpu-hal/src/vulkan/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ impl super::InstanceShared {
&self.raw
}

pub fn driver_api_version(&self) -> u32 {
self.driver_api_version
pub fn instance_api_version(&self) -> u32 {
self.instance_api_version
}

pub fn extensions(&self) -> &[&'static CStr] {
Expand All @@ -196,7 +196,7 @@ impl super::Instance {
/// Return a vector of the names of instance extensions actually available
/// on `entry` that wgpu would like to enable.
///
/// The `driver_api_version` argument should be the instance's Vulkan API
/// The `instance_api_version` argument should be the instance's Vulkan API
/// version, as obtained from `vkEnumerateInstanceVersion`. This is the same
/// space of values as the `VK_API_VERSION` constants.
///
Expand All @@ -206,7 +206,7 @@ impl super::Instance {
/// assumes that it has been enabled.
pub fn desired_extensions(
entry: &ash::Entry,
_driver_api_version: u32,
_instance_api_version: u32,
flags: wgt::InstanceFlags,
) -> Result<Vec<&'static CStr>, crate::InstanceError> {
let instance_extensions = entry
Expand Down Expand Up @@ -282,9 +282,9 @@ impl super::Instance {
/// # Safety
///
/// - `raw_instance` must be created from `entry`
/// - `raw_instance` must be created respecting `driver_api_version`, `extensions` and `flags`
/// - `raw_instance` must be created respecting `instance_api_version`, `extensions` and `flags`
/// - `extensions` must be a superset of `desired_extensions()` and must be created from the
/// same entry, driver_api_version and flags.
/// same entry, `instance_api_version`` and flags.
/// - `android_sdk_version` is ignored and can be `0` for all platforms besides Android
///
/// If `debug_utils_user_data` is `Some`, then the validation layer is
Expand All @@ -293,15 +293,15 @@ impl super::Instance {
pub unsafe fn from_raw(
entry: ash::Entry,
raw_instance: ash::Instance,
driver_api_version: u32,
instance_api_version: u32,
android_sdk_version: u32,
debug_utils_user_data: Option<super::DebugUtilsMessengerUserData>,
extensions: Vec<&'static CStr>,
flags: wgt::InstanceFlags,
has_nv_optimus: bool,
drop_guard: Option<crate::DropGuard>,
) -> Result<Self, crate::InstanceError> {
log::info!("Instance version: 0x{:x}", driver_api_version);
log::info!("Instance version: 0x{:x}", instance_api_version);

let debug_utils = if let Some(debug_callback_user_data) = debug_utils_user_data {
if extensions.contains(&ext::DebugUtils::name()) {
Expand Down Expand Up @@ -373,7 +373,7 @@ impl super::Instance {
get_physical_device_properties,
entry,
has_nv_optimus,
driver_api_version,
instance_api_version,
android_sdk_version,
}),
})
Expand Down Expand Up @@ -575,7 +575,7 @@ impl crate::Instance<super::Api> for super::Instance {
let entry = unsafe { ash::Entry::load() }.map_err(|err| {
crate::InstanceError::with_source(String::from("missing Vulkan entry points"), err)
})?;
let driver_api_version = match entry.try_enumerate_instance_version() {
let instance_api_version = match entry.try_enumerate_instance_version() {
// Vulkan 1.1+
Ok(Some(version)) => version,
Ok(None) => vk::API_VERSION_1_0,
Expand All @@ -595,7 +595,7 @@ impl crate::Instance<super::Api> for super::Instance {
.engine_version(2)
.api_version(
// Vulkan 1.0 doesn't like anything but 1.0 passed in here...
if driver_api_version < vk::API_VERSION_1_1 {
if instance_api_version < vk::API_VERSION_1_1 {
vk::API_VERSION_1_0
} else {
// This is the max Vulkan API version supported by `wgpu-hal`.
Expand All @@ -606,11 +606,11 @@ impl crate::Instance<super::Api> for super::Instance {
// - If any were promoted in the new API version and the behavior has changed, we must handle the new behavior in addition to the old behavior.
// - If any were obsoleted in the new API version, we must implement a fallback for the new API version
// - If any are non-KHR-vendored, we must ensure the new behavior is still correct (since backwards-compatibility is not guaranteed).
vk::HEADER_VERSION_COMPLETE
vk::API_VERSION_1_3
},
);

let extensions = Self::desired_extensions(&entry, driver_api_version, desc.flags)?;
let extensions = Self::desired_extensions(&entry, instance_api_version, desc.flags)?;

let instance_layers = entry.enumerate_instance_layer_properties().map_err(|e| {
log::info!("enumerate_instance_layer_properties: {:?}", e);
Expand Down Expand Up @@ -720,7 +720,7 @@ impl crate::Instance<super::Api> for super::Instance {
Self::from_raw(
entry,
vk_instance,
driver_api_version,
instance_api_version,
android_sdk_version,
debug_callback_user_data,
extensions,
Expand Down
Loading

0 comments on commit a842019

Please sign in to comment.