Skip to content

Commit

Permalink
ValidationError-ify last remnants (#2269)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rua authored Jul 24, 2023
1 parent 69a0a7a commit 59b53d7
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 168 deletions.
62 changes: 7 additions & 55 deletions vulkano/src/deferred.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,9 @@
use crate::{
device::{Device, DeviceOwned},
instance::InstanceOwnedDebugWrapper,
Requires, RequiresAllOf, RequiresOneOf, VulkanError, VulkanObject,
};
use std::{
error::Error,
fmt::{Display, Formatter},
mem::MaybeUninit,
ptr,
sync::Arc,
Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError, VulkanObject,
};
use std::{mem::MaybeUninit, ptr, sync::Arc};

/// An operation on the host that has been deferred.
///
Expand All @@ -46,20 +40,20 @@ impl DeferredOperation {
///
/// [`khr_deferred_host_operations`]: crate::device::DeviceExtensions::khr_deferred_host_operations
#[inline]
pub fn new(device: Arc<Device>) -> Result<Arc<Self>, DeferredOperationCreateError> {
pub fn new(device: Arc<Device>) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_new(&device)?;

unsafe { Ok(Self::new_unchecked(device)?) }
}

fn validate_new(device: &Device) -> Result<(), DeferredOperationCreateError> {
fn validate_new(device: &Device) -> Result<(), Box<ValidationError>> {
if !device.enabled_extensions().khr_deferred_host_operations {
return Err(DeferredOperationCreateError::RequirementNotMet {
required_for: "`DeferredOperation::new`",
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"khr_deferred_host_operations",
)])]),
});
..Default::default()
}));
}

Ok(())
Expand Down Expand Up @@ -207,48 +201,6 @@ unsafe impl DeviceOwned for DeferredOperation {
}
}

/// Error that can happen when creating a `DeferredOperation`.
#[derive(Clone, Debug)]
pub enum DeferredOperationCreateError {
VulkanError(VulkanError),

RequirementNotMet {
required_for: &'static str,
requires_one_of: RequiresOneOf,
},
}

impl Display for DeferredOperationCreateError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::VulkanError(_) => write!(f, "a runtime error occurred"),
Self::RequirementNotMet {
required_for,
requires_one_of,
} => write!(
f,
"a requirement was not met for: {}; requires one of: {}",
required_for, requires_one_of,
),
}
}
}

impl Error for DeferredOperationCreateError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::VulkanError(err) => Some(err),
_ => None,
}
}
}

impl From<VulkanError> for DeferredOperationCreateError {
fn from(err: VulkanError) -> Self {
Self::VulkanError(err)
}
}

/// The status of the operation after [`join`] returns.
///
/// [`join`]: DeferredOperation::join
Expand Down
192 changes: 79 additions & 113 deletions vulkano/src/swapchain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,14 +336,12 @@ use crate::{
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags, vulkan_bitflags_enum, vulkan_enum},
sync::Sharing,
OomError, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError,
VulkanObject,
Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError, VulkanObject,
};
use parking_lot::Mutex;
use smallvec::SmallVec;
use std::{
error::Error,
fmt::{Debug, Display, Error as FmtError, Formatter},
fmt::Debug,
mem::MaybeUninit,
num::NonZeroU64,
ptr,
Expand Down Expand Up @@ -1380,58 +1378,105 @@ impl Swapchain {
/// either the `release_full_screen_exclusive` is called, or if any of the the other `Swapchain`
/// functions return `FullScreenExclusiveLost`.
#[inline]
pub fn acquire_full_screen_exclusive(&self) -> Result<(), FullScreenExclusiveError> {
if self.full_screen_exclusive != FullScreenExclusive::ApplicationControlled {
return Err(FullScreenExclusiveError::NotApplicationControlled);
pub fn acquire_full_screen_exclusive_mode(&self) -> Result<(), Validated<VulkanError>> {
self.validate_acquire_full_screen_exclusive_mode()?;

unsafe { Ok(self.acquire_full_screen_exclusive_mode_unchecked()?) }
}

fn validate_acquire_full_screen_exclusive_mode(&self) -> Result<(), Box<ValidationError>> {
if *self.is_retired.lock() {
return Err(Box::new(ValidationError {
problem: "this swapchain is retired".into(),
vuids: &["VUID-vkAcquireFullScreenExclusiveModeEXT-swapchain-02674"],
..Default::default()
}));
}

if self.full_screen_exclusive_held.swap(true, Ordering::SeqCst) {
return Err(FullScreenExclusiveError::DoubleAcquire);
if self.full_screen_exclusive != FullScreenExclusive::ApplicationControlled {
return Err(Box::new(ValidationError {
context: "self.full_screen_exclusive()".into(),
problem: "is not `FullScreenExclusive::ApplicationControlled`".into(),
vuids: &["VUID-vkAcquireFullScreenExclusiveModeEXT-swapchain-02675"],
..Default::default()
}));
}

unsafe {
let fns = self.device.fns();
(fns.ext_full_screen_exclusive
.acquire_full_screen_exclusive_mode_ext)(
self.device.handle(), self.handle
)
.result()
.map_err(VulkanError::from)?;
// This must be the last check in this function.
if self
.full_screen_exclusive_held
.swap(true, Ordering::Acquire)
{
return Err(Box::new(ValidationError {
problem: "this swapchain already holds full-screen exclusive access".into(),
vuids: &["VUID-vkAcquireFullScreenExclusiveModeEXT-swapchain-02676"],
..Default::default()
}));
}

Ok(())
}

#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn acquire_full_screen_exclusive_mode_unchecked(&self) -> Result<(), VulkanError> {
self.full_screen_exclusive_held
.store(true, Ordering::Relaxed);

let fns = self.device.fns();
(fns.ext_full_screen_exclusive
.acquire_full_screen_exclusive_mode_ext)(self.device.handle(), self.handle)
.result()
.map_err(VulkanError::from)?;

Ok(())
}

/// Releases full-screen exclusivity.
///
/// The swapchain must have been created with [`FullScreenExclusive::ApplicationControlled`],
/// and must currently hold full-screen exclusivity.
#[inline]
pub fn release_full_screen_exclusive(&self) -> Result<(), FullScreenExclusiveError> {
if self.full_screen_exclusive != FullScreenExclusive::ApplicationControlled {
return Err(FullScreenExclusiveError::NotApplicationControlled);
}
pub fn release_full_screen_exclusive_mode(&self) -> Result<(), Validated<VulkanError>> {
self.validate_release_full_screen_exclusive_mode()?;

if !self
.full_screen_exclusive_held
.swap(false, Ordering::SeqCst)
{
return Err(FullScreenExclusiveError::DoubleRelease);
unsafe { Ok(self.release_full_screen_exclusive_mode_unchecked()?) }
}

fn validate_release_full_screen_exclusive_mode(&self) -> Result<(), Box<ValidationError>> {
if *self.is_retired.lock() {
return Err(Box::new(ValidationError {
problem: "this swapchain is retired".into(),
vuids: &["VUID-vkReleaseFullScreenExclusiveModeEXT-swapchain-02677"],
..Default::default()
}));
}

unsafe {
let fns = self.device.fns();
(fns.ext_full_screen_exclusive
.release_full_screen_exclusive_mode_ext)(
self.device.handle(), self.handle
)
.result()
.map_err(VulkanError::from)?;
if self.full_screen_exclusive != FullScreenExclusive::ApplicationControlled {
return Err(Box::new(ValidationError {
context: "self.full_screen_exclusive()".into(),
problem: "is not `FullScreenExclusive::ApplicationControlled`".into(),
vuids: &["VUID-vkReleaseFullScreenExclusiveModeEXT-swapchain-02678"],
..Default::default()
}));
}

Ok(())
}

#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn release_full_screen_exclusive_mode_unchecked(&self) -> Result<(), VulkanError> {
self.full_screen_exclusive_held
.store(false, Ordering::Release);

let fns = self.device.fns();
(fns.ext_full_screen_exclusive
.release_full_screen_exclusive_mode_ext)(self.device.handle(), self.handle)
.result()
.map_err(VulkanError::from)?;

Ok(())
}

/// `FullScreenExclusive::AppControlled` is not the active full-screen exclusivity mode,
/// then this function will always return false. If true is returned the swapchain
/// is in `FullScreenExclusive::AppControlled` full-screen exclusivity mode and exclusivity
Expand Down Expand Up @@ -2078,82 +2123,3 @@ impl Win32Monitor {
// Winit's `MonitorHandle` is Send on Win32, so this seems safe.
unsafe impl Send for Win32Monitor {}
unsafe impl Sync for Win32Monitor {}

/// Error that can happen when calling `Swapchain::acquire_full_screen_exclusive` or
/// `Swapchain::release_full_screen_exclusive`.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum FullScreenExclusiveError {
/// Not enough memory.
OomError(OomError),

/// Operation could not be completed for driver specific reasons.
InitializationFailed,

/// The surface is no longer accessible and must be recreated.
SurfaceLost,

/// Full-screen exclusivity is already acquired.
DoubleAcquire,

/// Full-screen exclusivity is not currently acquired.
DoubleRelease,

/// The swapchain is not in full-screen exclusive application controlled mode.
NotApplicationControlled,
}

impl Error for FullScreenExclusiveError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
FullScreenExclusiveError::OomError(err) => Some(err),
_ => None,
}
}
}

impl Display for FullScreenExclusiveError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
write!(
f,
"{}",
match self {
FullScreenExclusiveError::OomError(_) => "not enough memory",
FullScreenExclusiveError::SurfaceLost => {
"the surface of this swapchain is no longer valid"
}
FullScreenExclusiveError::InitializationFailed => {
"operation could not be completed for driver specific reasons"
}
FullScreenExclusiveError::DoubleAcquire =>
"full-screen exclusivity is already acquired",
FullScreenExclusiveError::DoubleRelease =>
"full-screen exclusivity is not acquired",
FullScreenExclusiveError::NotApplicationControlled => {
"the swapchain is not in full-screen exclusive application controlled mode"
}
}
)
}
}

impl From<VulkanError> for FullScreenExclusiveError {
fn from(err: VulkanError) -> FullScreenExclusiveError {
match err {
err @ VulkanError::OutOfHostMemory => {
FullScreenExclusiveError::OomError(OomError::from(err))
}
err @ VulkanError::OutOfDeviceMemory => {
FullScreenExclusiveError::OomError(OomError::from(err))
}
VulkanError::SurfaceLost => FullScreenExclusiveError::SurfaceLost,
VulkanError::InitializationFailed => FullScreenExclusiveError::InitializationFailed,
_ => panic!("unexpected error: {:?}", err),
}
}
}

impl From<OomError> for FullScreenExclusiveError {
fn from(err: OomError) -> FullScreenExclusiveError {
FullScreenExclusiveError::OomError(err)
}
}

0 comments on commit 59b53d7

Please # to comment.