mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 00:04:15 +00:00
The deed (#2016)
This commit is contained in:
parent
7e3515e6eb
commit
b8d7cc3241
@ -290,14 +290,12 @@ pub enum Error {
|
||||
}
|
||||
|
||||
impl From<IoError> for Error {
|
||||
#[inline]
|
||||
fn from(err: IoError) -> Error {
|
||||
Error::IoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SpirvError> for Error {
|
||||
#[inline]
|
||||
fn from(err: SpirvError) -> Error {
|
||||
Error::SpirvError(err)
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ pub struct VulkanoConfig {
|
||||
}
|
||||
|
||||
impl Default for VulkanoConfig {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
let device_extensions = DeviceExtensions {
|
||||
khr_swapchain: true,
|
||||
@ -88,7 +89,7 @@ impl Default for VulkanoConfig {
|
||||
/// in the creation of [`VulkanoWindowRenderer`](crate::renderer::VulkanoWindowRenderer) through
|
||||
/// [`VulkanoWindows`](crate::window::VulkanoWindows).
|
||||
///
|
||||
/// ## Example
|
||||
/// ## Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano_util::context::{VulkanoConfig, VulkanoContext};
|
||||
@ -107,6 +108,7 @@ pub struct VulkanoContext {
|
||||
}
|
||||
|
||||
impl Default for VulkanoContext {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
VulkanoContext::new(VulkanoConfig::default())
|
||||
}
|
||||
@ -245,16 +247,19 @@ impl VulkanoContext {
|
||||
}
|
||||
|
||||
/// Returns the name of the device.
|
||||
#[inline]
|
||||
pub fn device_name(&self) -> &str {
|
||||
&self.device.physical_device().properties().device_name
|
||||
}
|
||||
|
||||
/// Returns the type of the device.
|
||||
#[inline]
|
||||
pub fn device_type(&self) -> PhysicalDeviceType {
|
||||
self.device.physical_device().properties().device_type
|
||||
}
|
||||
|
||||
/// Returns the maximum memory allocation of the device.
|
||||
#[inline]
|
||||
pub fn max_memory(&self) -> u32 {
|
||||
self.device
|
||||
.physical_device()
|
||||
@ -263,16 +268,19 @@ impl VulkanoContext {
|
||||
}
|
||||
|
||||
/// Returns the instance.
|
||||
#[inline]
|
||||
pub fn instance(&self) -> &Arc<Instance> {
|
||||
&self.instance
|
||||
}
|
||||
|
||||
/// Returns the device.
|
||||
#[inline]
|
||||
pub fn device(&self) -> &Arc<Device> {
|
||||
&self.device
|
||||
}
|
||||
|
||||
/// Returns the graphics queue.
|
||||
#[inline]
|
||||
pub fn graphics_queue(&self) -> &Arc<Queue> {
|
||||
&self.graphics_queue
|
||||
}
|
||||
@ -280,6 +288,7 @@ impl VulkanoContext {
|
||||
/// Returns the compute queue.
|
||||
///
|
||||
/// Depending on your device, this might be the same as graphics queue.
|
||||
#[inline]
|
||||
pub fn compute_queue(&self) -> &Arc<Queue> {
|
||||
&self.compute_queue
|
||||
}
|
||||
|
@ -33,11 +33,11 @@ pub type DeviceImageView = Arc<ImageView<StorageImage>>;
|
||||
/// Most common image format
|
||||
pub const DEFAULT_IMAGE_FORMAT: Format = Format::R8G8B8A8_UNORM;
|
||||
|
||||
/// A window renderer struct holding the winit window surface and functionality for organizing your render
|
||||
/// between frames.
|
||||
/// A window renderer struct holding the winit window surface and functionality for organizing your
|
||||
/// render between frames.
|
||||
///
|
||||
/// Begin rendering with [`VulkanoWindowRenderer::acquire`] and finish with [`VulkanoWindowRenderer::present`].
|
||||
/// Between those, you should execute your command buffers.
|
||||
/// Begin rendering with [`VulkanoWindowRenderer::acquire`] and finish with
|
||||
/// [`VulkanoWindowRenderer::present`]. Between those, you should execute your command buffers.
|
||||
///
|
||||
/// The intended usage of this struct is through [`crate::window::VulkanoWindows`].
|
||||
pub struct VulkanoWindowRenderer {
|
||||
@ -56,8 +56,9 @@ pub struct VulkanoWindowRenderer {
|
||||
}
|
||||
|
||||
impl VulkanoWindowRenderer {
|
||||
/// Creates a new [`VulkanoWindowRenderer`] which is used to orchestrate your rendering with Vulkano.
|
||||
/// Pass [`WindowDescriptor`] and optionally a function modifying the [`SwapchainCreateInfo`](vulkano::swapchain::SwapchainCreateInfo) parameters.
|
||||
/// Creates a new [`VulkanoWindowRenderer`] which is used to orchestrate your rendering with
|
||||
/// Vulkano. Pass [`WindowDescriptor`] and optionally a function modifying the
|
||||
/// [`SwapchainCreateInfo`](vulkano::swapchain::SwapchainCreateInfo) parameters.
|
||||
pub fn new(
|
||||
vulkano_context: &VulkanoContext,
|
||||
window: winit::window::Window,
|
||||
@ -142,6 +143,7 @@ impl VulkanoWindowRenderer {
|
||||
}
|
||||
|
||||
/// Set window renderer present mode. This triggers a swapchain recreation.
|
||||
#[inline]
|
||||
pub fn set_present_mode(&mut self, present_mode: vulkano::swapchain::PresentMode) {
|
||||
if self.present_mode != present_mode {
|
||||
self.present_mode = present_mode;
|
||||
@ -149,55 +151,65 @@ impl VulkanoWindowRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return swapchain image format
|
||||
/// Return swapchain image format.
|
||||
#[inline]
|
||||
pub fn swapchain_format(&self) -> Format {
|
||||
self.final_views[self.image_index as usize]
|
||||
.format()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Returns the index of last swapchain image that is the next render target
|
||||
/// Returns the index of last swapchain image that is the next render target.
|
||||
#[inline]
|
||||
pub fn image_index(&self) -> u32 {
|
||||
self.image_index
|
||||
}
|
||||
|
||||
/// Graphics queue of this window. You also can access this through [`VulkanoContext`]
|
||||
/// Graphics queue of this window. You also can access this through [`VulkanoContext`].
|
||||
#[inline]
|
||||
pub fn graphics_queue(&self) -> Arc<Queue> {
|
||||
self.graphics_queue.clone()
|
||||
}
|
||||
|
||||
/// Compute queue of this window. You can also access this through [`VulkanoContext`]
|
||||
/// Compute queue of this window. You can also access this through [`VulkanoContext`].
|
||||
#[inline]
|
||||
pub fn compute_queue(&self) -> Arc<Queue> {
|
||||
self.compute_queue.clone()
|
||||
}
|
||||
|
||||
/// Render target surface
|
||||
/// Render target surface.
|
||||
#[inline]
|
||||
pub fn surface(&self) -> Arc<Surface<Window>> {
|
||||
self.surface.clone()
|
||||
}
|
||||
|
||||
/// Winit window (you can manipulate window through this).
|
||||
#[inline]
|
||||
pub fn window(&self) -> &Window {
|
||||
self.surface.window()
|
||||
}
|
||||
|
||||
/// Size of the physical window
|
||||
/// Size of the physical window.
|
||||
#[inline]
|
||||
pub fn window_size(&self) -> [f32; 2] {
|
||||
let size = self.window().inner_size();
|
||||
[size.width as f32, size.height as f32]
|
||||
}
|
||||
|
||||
/// Size of the final swapchain image (surface)
|
||||
/// Size of the final swapchain image (surface).
|
||||
#[inline]
|
||||
pub fn swapchain_image_size(&self) -> [u32; 2] {
|
||||
self.final_views[0].image().dimensions().width_height()
|
||||
}
|
||||
|
||||
/// Return the current swapchain image view
|
||||
/// Return the current swapchain image view.
|
||||
#[inline]
|
||||
pub fn swapchain_image_view(&self) -> SwapchainImageView {
|
||||
self.final_views[self.image_index as usize].clone()
|
||||
}
|
||||
|
||||
/// Return scale factor accounted window size
|
||||
/// Return scale factor accounted window size.
|
||||
#[inline]
|
||||
pub fn resolution(&self) -> [f32; 2] {
|
||||
let size = self.window().inner_size();
|
||||
let scale_factor = self.window().scale_factor();
|
||||
@ -207,17 +219,21 @@ impl VulkanoWindowRenderer {
|
||||
]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn aspect_ratio(&self) -> f32 {
|
||||
let dims = self.window_size();
|
||||
dims[0] / dims[1]
|
||||
}
|
||||
|
||||
/// Resize swapchain and camera view images at the beginning of next frame based on window dimensions
|
||||
/// Resize swapchain and camera view images at the beginning of next frame based on window
|
||||
/// dimensions.
|
||||
#[inline]
|
||||
pub fn resize(&mut self) {
|
||||
self.recreate_swapchain = true;
|
||||
}
|
||||
|
||||
/// Add interim image view that resizes with window
|
||||
/// Add interim image view that resizes with window.
|
||||
#[inline]
|
||||
pub fn add_additional_image_view(&mut self, key: usize, format: Format, usage: ImageUsage) {
|
||||
let size = self.swapchain_image_size();
|
||||
let image = StorageImage::general_purpose_image_view(
|
||||
@ -230,20 +246,24 @@ impl VulkanoWindowRenderer {
|
||||
self.additional_image_views.insert(key, image);
|
||||
}
|
||||
|
||||
/// Get additional image view by key
|
||||
/// Get additional image view by key.
|
||||
#[inline]
|
||||
pub fn get_additional_image_view(&mut self, key: usize) -> DeviceImageView {
|
||||
self.additional_image_views.get(&key).unwrap().clone()
|
||||
}
|
||||
|
||||
/// Remove additional image by key
|
||||
/// Remove additional image by key.
|
||||
#[inline]
|
||||
pub fn remove_additional_image_view(&mut self, key: usize) {
|
||||
self.additional_image_views.remove(&key);
|
||||
}
|
||||
|
||||
/// Begin your rendering by calling `acquire`.
|
||||
/// Returns a [`GpuFuture`](vulkano::sync::GpuFuture) representing the time after which the swapchain image has been acquired
|
||||
/// and previous frame ended.
|
||||
/// Execute your command buffers after calling this function and finish rendering by calling [`VulkanoWindowRenderer::present`].
|
||||
/// Returns a [`GpuFuture`](vulkano::sync::GpuFuture) representing the time after which the
|
||||
/// swapchain image has been acquired and previous frame ended.
|
||||
/// Execute your command buffers after calling this function and finish rendering by calling
|
||||
/// [`VulkanoWindowRenderer::present`].
|
||||
#[inline]
|
||||
pub fn acquire(&mut self) -> std::result::Result<Box<dyn GpuFuture>, AcquireError> {
|
||||
// Recreate swap chain if needed (when resizing of window occurs or swapchain is outdated)
|
||||
// Also resize render views if needed
|
||||
@ -272,10 +292,13 @@ impl VulkanoWindowRenderer {
|
||||
Ok(future.boxed())
|
||||
}
|
||||
|
||||
/// Finishes rendering by presenting the swapchain. Pass your last future as an input to this function.
|
||||
/// Finishes rendering by presenting the swapchain. Pass your last future as an input to this
|
||||
/// function.
|
||||
///
|
||||
/// Depending on your implementation, you may want to wait on your future. For example, a compute shader
|
||||
/// dispatch using an image that's being later drawn should probably be waited on.
|
||||
/// Depending on your implementation, you may want to wait on your future. For example, a
|
||||
/// compute shader dispatch using an image that's being later drawn should probably be waited
|
||||
/// on.
|
||||
#[inline]
|
||||
pub fn present(&mut self, after_future: Box<dyn GpuFuture>, wait_future: bool) {
|
||||
let future = after_future
|
||||
.then_swapchain_present(
|
||||
@ -313,7 +336,7 @@ impl VulkanoWindowRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Recreates swapchain images and image views which follow the window size
|
||||
/// Recreates swapchain images and image views which follow the window size.
|
||||
fn recreate_swapchain_and_views(&mut self) {
|
||||
let dimensions: [u32; 2] = self.window().inner_size().into();
|
||||
let (new_swapchain, new_images) = match self.swapchain.recreate(SwapchainCreateInfo {
|
||||
|
@ -20,22 +20,25 @@ use winit::{
|
||||
window::{CursorGrabMode, WindowId},
|
||||
};
|
||||
|
||||
/// A struct organizing windows and their corresponding renderers. This makes it easy to handle multiple windows.
|
||||
/// A struct organizing windows and their corresponding renderers. This makes it easy to handle
|
||||
/// multiple windows.
|
||||
///
|
||||
/// ## Example
|
||||
///```
|
||||
/// ## Examples
|
||||
///
|
||||
/// ```
|
||||
/// use vulkano_util::context::{VulkanoConfig, VulkanoContext};
|
||||
/// use winit::event_loop::EventLoop;
|
||||
/// use vulkano_util::window::VulkanoWindows;
|
||||
///
|
||||
/// #[test]
|
||||
/// fn test() {
|
||||
/// let context = VulkanoContext::new(VulkanoConfig::default());
|
||||
/// let event_loop = EventLoop::new();
|
||||
/// let mut vulkano_windows = VulkanoWindows::default();
|
||||
/// let _id1 = vulkano_windows.create_window(&event_loop, &context, &Default::default(), |_| {});
|
||||
/// let _id2 = vulkano_windows.create_window(&event_loop, &context, &Default::default(), |_| {});
|
||||
/// // You should now have two windows
|
||||
/// let context = VulkanoContext::new(VulkanoConfig::default());
|
||||
/// let event_loop = EventLoop::new();
|
||||
/// let mut vulkano_windows = VulkanoWindows::default();
|
||||
/// let _id1 = vulkano_windows.create_window(&event_loop, &context, &Default::default(), |_| {});
|
||||
/// let _id2 = vulkano_windows.create_window(&event_loop, &context, &Default::default(), |_| {});
|
||||
///
|
||||
/// // You should now have two windows.
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Default)]
|
||||
@ -45,8 +48,8 @@ pub struct VulkanoWindows {
|
||||
}
|
||||
|
||||
impl VulkanoWindows {
|
||||
/// Creates a winit window with [`VulkanoWindowRenderer`] based on the given [`WindowDescriptor`]
|
||||
/// input and swapchain creation modifications
|
||||
/// Creates a winit window with [`VulkanoWindowRenderer`] based on the given
|
||||
/// [`WindowDescriptor`] input and swapchain creation modifications.
|
||||
pub fn create_window(
|
||||
&mut self,
|
||||
event_loop: &winit::event_loop::EventLoopWindowTarget<()>,
|
||||
@ -171,7 +174,8 @@ impl VulkanoWindows {
|
||||
id
|
||||
}
|
||||
|
||||
/// Get a mutable reference to the primary window's renderer
|
||||
/// Get a mutable reference to the primary window's renderer.
|
||||
#[inline]
|
||||
pub fn get_primary_renderer_mut(&mut self) -> Option<&mut VulkanoWindowRenderer> {
|
||||
if self.primary.is_some() {
|
||||
self.get_renderer_mut(self.primary.unwrap())
|
||||
@ -180,7 +184,8 @@ impl VulkanoWindows {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a reference to the primary window's renderer
|
||||
/// Get a reference to the primary window's renderer.
|
||||
#[inline]
|
||||
pub fn get_primary_renderer(&self) -> Option<&VulkanoWindowRenderer> {
|
||||
if self.primary.is_some() {
|
||||
self.get_renderer(self.primary.unwrap())
|
||||
@ -189,7 +194,8 @@ impl VulkanoWindows {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a reference to the primary winit window
|
||||
/// Get a reference to the primary winit window.
|
||||
#[inline]
|
||||
pub fn get_primary_window(&self) -> Option<&winit::window::Window> {
|
||||
if self.primary.is_some() {
|
||||
self.get_window(self.primary.unwrap())
|
||||
@ -198,7 +204,8 @@ impl VulkanoWindows {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a mutable reference to the renderer by winit window id
|
||||
/// Get a mutable reference to the renderer by winit window id.
|
||||
#[inline]
|
||||
pub fn get_renderer_mut(
|
||||
&mut self,
|
||||
id: winit::window::WindowId,
|
||||
@ -206,22 +213,26 @@ impl VulkanoWindows {
|
||||
self.windows.get_mut(&id)
|
||||
}
|
||||
|
||||
/// Get a reference to the renderer by winit window id
|
||||
/// Get a reference to the renderer by winit window id.
|
||||
#[inline]
|
||||
pub fn get_renderer(&self, id: winit::window::WindowId) -> Option<&VulkanoWindowRenderer> {
|
||||
self.windows.get(&id)
|
||||
}
|
||||
|
||||
/// Get a reference to the winit window by winit window id
|
||||
/// Get a reference to the winit window by winit window id.
|
||||
#[inline]
|
||||
pub fn get_window(&self, id: winit::window::WindowId) -> Option<&winit::window::Window> {
|
||||
self.windows.get(&id).map(|v_window| v_window.window())
|
||||
}
|
||||
|
||||
/// Return primary window id
|
||||
/// Return primary window id.
|
||||
#[inline]
|
||||
pub fn primary_window_id(&self) -> Option<winit::window::WindowId> {
|
||||
self.primary
|
||||
}
|
||||
|
||||
/// Remove renderer by window id
|
||||
/// Remove renderer by window id.
|
||||
#[inline]
|
||||
pub fn remove_renderer(&mut self, id: winit::window::WindowId) {
|
||||
self.windows.remove(&id);
|
||||
if let Some(primary) = self.primary {
|
||||
@ -231,12 +242,14 @@ impl VulkanoWindows {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return iterator over window renderers
|
||||
/// Return iterator over window renderers.
|
||||
#[inline]
|
||||
pub fn iter(&self) -> Iter<'_, WindowId, VulkanoWindowRenderer> {
|
||||
self.windows.iter()
|
||||
}
|
||||
|
||||
/// Return iterator over mutable window renderers
|
||||
/// Return iterator over mutable window renderers.
|
||||
#[inline]
|
||||
pub fn iter_mut(&mut self) -> IterMut<'_, WindowId, VulkanoWindowRenderer> {
|
||||
self.windows.iter_mut()
|
||||
}
|
||||
@ -301,7 +314,8 @@ pub enum WindowMode {
|
||||
BorderlessFullscreen,
|
||||
/// Creates a fullscreen window that will render at desktop resolution.
|
||||
///
|
||||
/// The app will use the closest supported size from the given size and scale it to fit the screen.
|
||||
/// The app will use the closest supported size from the given size and scale it to fit the
|
||||
/// screen.
|
||||
SizedFullscreen,
|
||||
/// Creates a fullscreen window that uses the maximum supported size.
|
||||
Fullscreen,
|
||||
@ -328,7 +342,8 @@ pub struct WindowDescriptor {
|
||||
///
|
||||
/// If there are some scaling problems on X11 try to set this option to `Some(1.0)`.
|
||||
pub scale_factor_override: Option<f64>,
|
||||
/// Sets the title that displays on the window top bar, on the system task bar and other OS specific places.
|
||||
/// Sets the title that displays on the window top bar, on the system task bar and other OS
|
||||
/// specific places.
|
||||
pub title: String,
|
||||
/// The window's [`PresentMode`].
|
||||
///
|
||||
@ -349,6 +364,7 @@ pub struct WindowDescriptor {
|
||||
}
|
||||
|
||||
impl Default for WindowDescriptor {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
WindowDescriptor {
|
||||
title: "Vulkano App".to_string(),
|
||||
@ -384,6 +400,7 @@ pub struct WindowResizeConstraints {
|
||||
}
|
||||
|
||||
impl Default for WindowResizeConstraints {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
min_width: 180.,
|
||||
|
@ -36,7 +36,6 @@ pub fn required_extensions(library: &VulkanLibrary) -> InstanceExtensions {
|
||||
|
||||
/// Create a surface from a Winit window or a reference to it. The surface takes `W` to prevent it
|
||||
/// from being dropped before the surface.
|
||||
#[inline]
|
||||
pub fn create_surface_from_winit<W>(
|
||||
window: W,
|
||||
instance: Arc<Instance>,
|
||||
@ -56,13 +55,13 @@ pub trait VkSurfaceBuild<E> {
|
||||
}
|
||||
|
||||
impl<E> VkSurfaceBuild<E> for WindowBuilder {
|
||||
#[inline]
|
||||
fn build_vk_surface(
|
||||
self,
|
||||
event_loop: &EventLoopWindowTarget<E>,
|
||||
instance: Arc<Instance>,
|
||||
) -> Result<Arc<Surface<Window>>, CreationError> {
|
||||
let window = self.build(event_loop)?;
|
||||
|
||||
Ok(create_surface_from_winit(window, instance)?)
|
||||
}
|
||||
}
|
||||
@ -77,22 +76,20 @@ pub enum CreationError {
|
||||
}
|
||||
|
||||
impl Error for CreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
CreationError::SurfaceCreationError(ref err) => Some(err),
|
||||
CreationError::WindowCreationError(ref err) => Some(err),
|
||||
match self {
|
||||
CreationError::SurfaceCreationError(err) => Some(err),
|
||||
CreationError::WindowCreationError(err) => Some(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for CreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
match self {
|
||||
CreationError::SurfaceCreationError(_) => "error while creating the surface",
|
||||
CreationError::WindowCreationError(_) => "error while creating the window",
|
||||
}
|
||||
@ -101,21 +98,18 @@ impl Display for CreationError {
|
||||
}
|
||||
|
||||
impl From<SurfaceCreationError> for CreationError {
|
||||
#[inline]
|
||||
fn from(err: SurfaceCreationError) -> CreationError {
|
||||
CreationError::SurfaceCreationError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WindowCreationError> for CreationError {
|
||||
#[inline]
|
||||
fn from(err: WindowCreationError) -> CreationError {
|
||||
CreationError::WindowCreationError(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[inline]
|
||||
unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
|
||||
instance: Arc<Instance>,
|
||||
win: W,
|
||||
@ -243,7 +237,6 @@ unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[inline]
|
||||
unsafe fn winit_to_surface<W: SafeBorrow<Window>>(
|
||||
instance: Arc<Instance>,
|
||||
win: W,
|
||||
|
@ -287,20 +287,20 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream {
|
||||
/// Note that the `robust_buffer_access` is guaranteed to be supported by all Vulkan
|
||||
/// implementations.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use vulkano::device::Features;
|
||||
/// # let physical_device: vulkano::device::physical::PhysicalDevice = return;
|
||||
/// let minimal_features = Features {
|
||||
/// geometry_shader: true,
|
||||
/// .. Features::empty()
|
||||
/// ..Features::empty()
|
||||
/// };
|
||||
///
|
||||
/// let optimal_features = vulkano::device::Features {
|
||||
/// geometry_shader: true,
|
||||
/// tessellation_shader: true,
|
||||
/// .. Features::empty()
|
||||
/// ..Features::empty()
|
||||
/// };
|
||||
///
|
||||
/// if !physical_device.supported_features().is_superset_of(&minimal_features) {
|
||||
@ -310,7 +310,6 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream {
|
||||
/// assert!(optimal_features.is_superset_of(&minimal_features));
|
||||
/// let features_to_request = optimal_features.intersection(physical_device.supported_features());
|
||||
/// ```
|
||||
///
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Features {
|
||||
#(#struct_items)*
|
||||
@ -325,7 +324,8 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream {
|
||||
}
|
||||
|
||||
impl Features {
|
||||
/// Checks enabled features against the device version, device extensions and each other.
|
||||
/// Checks enabled features against the device version, device extensions and each
|
||||
/// other.
|
||||
pub(super) fn check_requirements(
|
||||
&self,
|
||||
supported: &Features,
|
||||
|
@ -573,7 +573,7 @@ fn formats_output(members: &[FormatMember]) -> TokenStream {
|
||||
///
|
||||
/// Note: for 16-bit floating point values, you need to import the [`half::f16`] type.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #[macro_use] extern crate vulkano;
|
||||
|
@ -384,7 +384,7 @@ fn bit_enum_output(enums: &[(Ident, Vec<KindEnumMember>)]) -> TokenStream {
|
||||
);
|
||||
|
||||
quote! {
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct #name {
|
||||
#(#members_items)*
|
||||
@ -524,7 +524,8 @@ fn value_enum_output(enums: &[(Ident, Vec<KindEnumMember>)]) -> TokenStream {
|
||||
|
||||
let derives = match name_string.as_str() {
|
||||
"ExecutionModel" => quote! { #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] },
|
||||
_ => quote! { #[derive(Clone, Debug, PartialEq, Eq)] },
|
||||
"Decoration" => quote! { #[derive(Clone, Debug, PartialEq, Eq)] },
|
||||
_ => quote! { #[derive(Clone, Copy, Debug, PartialEq, Eq)] },
|
||||
};
|
||||
|
||||
quote! {
|
||||
|
@ -110,7 +110,6 @@ where
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `T` has zero size.
|
||||
#[inline]
|
||||
pub unsafe fn uninitialized(
|
||||
device: Arc<Device>,
|
||||
usage: BufferUsage,
|
||||
@ -173,7 +172,6 @@ where
|
||||
///
|
||||
/// - Panics if `T` has zero size.
|
||||
/// - Panics if `len` is zero.
|
||||
#[inline]
|
||||
pub unsafe fn uninitialized_array(
|
||||
device: Arc<Device>,
|
||||
len: DeviceSize,
|
||||
@ -274,7 +272,6 @@ where
|
||||
T: BufferContents + ?Sized,
|
||||
{
|
||||
/// Returns the queue families this buffer can be used on.
|
||||
#[inline]
|
||||
pub fn queue_family_indices(&self) -> &[u32] {
|
||||
&self.queue_family_indices
|
||||
}
|
||||
@ -294,7 +291,6 @@ where
|
||||
/// After this function successfully locks the buffer, any attempt to submit a command buffer
|
||||
/// that uses it in exclusive mode will fail. You can still submit this buffer for non-exclusive
|
||||
/// accesses (ie. reads).
|
||||
#[inline]
|
||||
pub fn read(&self) -> Result<ReadLock<'_, T, A>, ReadLockError> {
|
||||
let mut state = self.inner.state();
|
||||
let buffer_range = self.inner().offset..self.inner().offset + self.size();
|
||||
@ -335,7 +331,6 @@ where
|
||||
///
|
||||
/// After this function successfully locks the buffer, any attempt to submit a command buffer
|
||||
/// that uses it and any attempt to call `read()` will return an error.
|
||||
#[inline]
|
||||
pub fn write(&self) -> Result<WriteLock<'_, T, A>, WriteLockError> {
|
||||
let mut state = self.inner.state();
|
||||
let buffer_range = self.inner().offset..self.inner().offset + self.size();
|
||||
@ -370,7 +365,6 @@ where
|
||||
T: BufferContents + ?Sized,
|
||||
A: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> BufferInner<'_> {
|
||||
BufferInner {
|
||||
buffer: &self.inner,
|
||||
@ -378,7 +372,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size(&self) -> DeviceSize {
|
||||
self.inner.size()
|
||||
}
|
||||
@ -389,7 +382,6 @@ where
|
||||
T: BufferContents + ?Sized,
|
||||
A: Send + Sync + 'static,
|
||||
{
|
||||
#[inline]
|
||||
fn as_buffer_access_object(&self) -> Arc<dyn BufferAccess> {
|
||||
self.clone()
|
||||
}
|
||||
@ -407,7 +399,6 @@ unsafe impl<T, A> DeviceOwned for CpuAccessibleBuffer<T, A>
|
||||
where
|
||||
T: BufferContents + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.inner.device()
|
||||
}
|
||||
@ -418,7 +409,6 @@ where
|
||||
T: BufferContents + ?Sized,
|
||||
A: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner() == other.inner() && self.size() == other.size()
|
||||
}
|
||||
@ -436,7 +426,6 @@ where
|
||||
T: BufferContents + ?Sized,
|
||||
A: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().hash(state);
|
||||
self.size().hash(state);
|
||||
@ -463,7 +452,6 @@ where
|
||||
T: BufferContents + ?Sized + 'a,
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let mut state = self.inner.inner.state();
|
||||
@ -479,7 +467,6 @@ where
|
||||
{
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &T {
|
||||
self.data
|
||||
}
|
||||
@ -506,7 +493,6 @@ where
|
||||
T: BufferContents + ?Sized + 'a,
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.inner
|
||||
@ -529,7 +515,6 @@ where
|
||||
{
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &T {
|
||||
self.data
|
||||
}
|
||||
@ -540,7 +525,6 @@ where
|
||||
T: BufferContents + ?Sized + 'a,
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
self.data
|
||||
}
|
||||
@ -558,7 +542,6 @@ pub enum ReadLockError {
|
||||
impl Error for ReadLockError {}
|
||||
|
||||
impl Display for ReadLockError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
@ -587,7 +570,6 @@ pub enum WriteLockError {
|
||||
impl Error for WriteLockError {}
|
||||
|
||||
impl Display for WriteLockError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
|
@ -59,17 +59,19 @@ use std::{
|
||||
///
|
||||
/// # Usage
|
||||
///
|
||||
/// Since a `DeviceLocalBuffer` can only be directly accessed by the GPU, data cannot be transfered between
|
||||
/// the host process and the buffer alone. One must use additional buffers which are accessible to the CPU as
|
||||
/// staging areas, then use command buffers to execute the necessary data transfers.
|
||||
/// Since a `DeviceLocalBuffer` can only be directly accessed by the GPU, data cannot be transfered
|
||||
/// between the host process and the buffer alone. One must use additional buffers which are
|
||||
/// accessible to the CPU as staging areas, then use command buffers to execute the necessary data
|
||||
/// transfers.
|
||||
///
|
||||
/// Despite this, if one knows in advance that a buffer will not need to be frequently accessed by the host,
|
||||
/// then there may be significant performance gains by using a `DeviceLocalBuffer` over a buffer type which
|
||||
/// allows host access.
|
||||
/// Despite this, if one knows in advance that a buffer will not need to be frequently accessed by
|
||||
/// the host, then there may be significant performance gains by using a `DeviceLocalBuffer` over a
|
||||
/// buffer type which allows host access.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// The following example outlines the general strategy one may take when initializing a `DeviceLocalBuffer`.
|
||||
/// The following example outlines the general strategy one may take when initializing a
|
||||
/// `DeviceLocalBuffer`.
|
||||
///
|
||||
/// ```
|
||||
/// use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, DeviceLocalBuffer};
|
||||
@ -111,21 +113,20 @@ use std::{
|
||||
/// )
|
||||
/// .unwrap();
|
||||
/// cbb.copy_buffer(CopyBufferInfo::buffers(
|
||||
/// temporary_accessible_buffer,
|
||||
/// device_local_buffer.clone(),
|
||||
/// ))
|
||||
/// .unwrap();
|
||||
/// temporary_accessible_buffer,
|
||||
/// device_local_buffer.clone(),
|
||||
/// ))
|
||||
/// .unwrap();
|
||||
/// let cb = cbb.build().unwrap();
|
||||
///
|
||||
/// // Execute copy command and wait for completion before proceeding.
|
||||
/// cb.execute(queue.clone())
|
||||
/// .unwrap()
|
||||
/// .then_signal_fence_and_flush()
|
||||
/// .unwrap()
|
||||
/// .wait(None /* timeout */)
|
||||
/// .unwrap()
|
||||
/// .unwrap()
|
||||
/// .then_signal_fence_and_flush()
|
||||
/// .unwrap()
|
||||
/// .wait(None /* timeout */)
|
||||
/// .unwrap()
|
||||
/// ```
|
||||
///
|
||||
#[derive(Debug)]
|
||||
pub struct DeviceLocalBuffer<T, A = PotentialDedicatedAllocation<StandardMemoryPoolAlloc>>
|
||||
where
|
||||
@ -153,7 +154,6 @@ where
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `T` has zero size.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
device: Arc<Device>,
|
||||
usage: BufferUsage,
|
||||
@ -180,9 +180,9 @@ where
|
||||
/// Builds a `DeviceLocalBuffer` that copies its data from another buffer.
|
||||
///
|
||||
/// This function returns two objects: the newly-created buffer, and a future representing
|
||||
/// the initial upload operation. In order to be allowed to use the `DeviceLocalBuffer`, you must
|
||||
/// either submit your operation after this future, or execute this future and wait for it to
|
||||
/// be finished before submitting your own operation.
|
||||
/// the initial upload operation. In order to be allowed to use the `DeviceLocalBuffer`, you
|
||||
/// must either submit your operation after this future, or execute this future and wait for it
|
||||
/// to be finished before submitting your own operation.
|
||||
pub fn from_buffer<B>(
|
||||
source: Arc<B>,
|
||||
usage: BufferUsage,
|
||||
@ -242,9 +242,9 @@ where
|
||||
/// submits the command buffer as a future.
|
||||
///
|
||||
/// This function returns two objects: the newly-created buffer, and a future representing
|
||||
/// the initial upload operation. In order to be allowed to use the `DeviceLocalBuffer`, you must
|
||||
/// either submit your operation after this future, or execute this future and wait for it to
|
||||
/// be finished before submitting your own operation.
|
||||
/// the initial upload operation. In order to be allowed to use the `DeviceLocalBuffer`, you
|
||||
/// must either submit your operation after this future, or execute this future and wait for it
|
||||
/// to be finished before submitting your own operation.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@ -316,7 +316,6 @@ where
|
||||
///
|
||||
/// - Panics if `T` has zero size.
|
||||
/// - Panics if `len` is zero.
|
||||
#[inline]
|
||||
pub fn array(
|
||||
device: Arc<Device>,
|
||||
len: DeviceSize,
|
||||
@ -453,6 +452,7 @@ where
|
||||
}
|
||||
};
|
||||
let mem_reqs = buffer.memory_requirements();
|
||||
|
||||
Ok((buffer, mem_reqs))
|
||||
}
|
||||
|
||||
@ -471,7 +471,6 @@ where
|
||||
T: BufferContents + ?Sized,
|
||||
{
|
||||
/// Returns the queue families this buffer can be used on.
|
||||
#[inline]
|
||||
pub fn queue_family_indices(&self) -> &[u32] {
|
||||
&self.queue_family_indices
|
||||
}
|
||||
@ -481,7 +480,6 @@ unsafe impl<T, A> DeviceOwned for DeviceLocalBuffer<T, A>
|
||||
where
|
||||
T: BufferContents + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.inner.device()
|
||||
}
|
||||
@ -492,7 +490,6 @@ where
|
||||
T: BufferContents + ?Sized,
|
||||
A: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> BufferInner<'_> {
|
||||
BufferInner {
|
||||
buffer: &self.inner,
|
||||
@ -500,7 +497,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size(&self) -> DeviceSize {
|
||||
self.inner.size()
|
||||
}
|
||||
@ -511,7 +507,6 @@ where
|
||||
T: BufferContents + ?Sized,
|
||||
A: Send + Sync + 'static,
|
||||
{
|
||||
#[inline]
|
||||
fn as_buffer_access_object(&self) -> Arc<dyn BufferAccess> {
|
||||
self.clone()
|
||||
}
|
||||
@ -530,7 +525,6 @@ where
|
||||
T: BufferContents + ?Sized,
|
||||
A: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner() == other.inner() && self.size() == other.size()
|
||||
}
|
||||
@ -548,7 +542,6 @@ where
|
||||
T: BufferContents + ?Sized,
|
||||
A: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().hash(state);
|
||||
self.size().hash(state);
|
||||
@ -562,7 +555,6 @@ pub enum DeviceLocalBufferCreationError {
|
||||
}
|
||||
|
||||
impl Error for DeviceLocalBufferCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::DeviceMemoryAllocationError(err) => Some(err),
|
||||
@ -572,7 +564,6 @@ impl Error for DeviceLocalBufferCreationError {
|
||||
}
|
||||
|
||||
impl Display for DeviceLocalBufferCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::DeviceMemoryAllocationError(err) => err.fmt(f),
|
||||
@ -582,14 +573,12 @@ impl Display for DeviceLocalBufferCreationError {
|
||||
}
|
||||
|
||||
impl From<DeviceMemoryError> for DeviceLocalBufferCreationError {
|
||||
#[inline]
|
||||
fn from(e: DeviceMemoryError) -> Self {
|
||||
Self::DeviceMemoryAllocationError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CommandBufferBeginError> for DeviceLocalBufferCreationError {
|
||||
#[inline]
|
||||
fn from(e: CommandBufferBeginError) -> Self {
|
||||
Self::CommandBufferBeginError(e)
|
||||
}
|
||||
|
@ -125,22 +125,18 @@ unsafe impl<T> BufferContents for T
|
||||
where
|
||||
T: Pod + Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn as_bytes(&self) -> &[u8] {
|
||||
bytes_of(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_bytes(bytes: &[u8]) -> Result<&T, PodCastError> {
|
||||
try_from_bytes(bytes)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_bytes_mut(bytes: &mut [u8]) -> Result<&mut T, PodCastError> {
|
||||
try_from_bytes_mut(bytes)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_of_element() -> DeviceSize {
|
||||
1
|
||||
}
|
||||
@ -150,22 +146,18 @@ unsafe impl<T> BufferContents for [T]
|
||||
where
|
||||
T: Pod + Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn as_bytes(&self) -> &[u8] {
|
||||
cast_slice(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_bytes(bytes: &[u8]) -> Result<&[T], PodCastError> {
|
||||
try_cast_slice(bytes)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_bytes_mut(bytes: &mut [u8]) -> Result<&mut [T], PodCastError> {
|
||||
try_cast_slice_mut(bytes)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_of_element() -> DeviceSize {
|
||||
size_of::<T>() as DeviceSize
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ use std::{
|
||||
///
|
||||
/// This object doesn't correspond to any Vulkan object. It exists for API convenience.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// Creating a slice:
|
||||
///
|
||||
@ -41,7 +41,7 @@ use std::{
|
||||
/// # let buffer: std::sync::Arc<vulkano::buffer::DeviceLocalBuffer<[u8]>> = return;
|
||||
/// let _slice = BufferSlice::from(&buffer).slice(12 .. 14).unwrap();
|
||||
/// ```
|
||||
///
|
||||
#[derive(Debug)]
|
||||
pub struct BufferSlice<T: ?Sized, B> {
|
||||
marker: PhantomData<T>,
|
||||
resource: Arc<B>,
|
||||
@ -51,7 +51,6 @@ pub struct BufferSlice<T: ?Sized, B> {
|
||||
|
||||
// We need to implement `Clone` manually, otherwise the derive adds a `T: Clone` requirement.
|
||||
impl<T: ?Sized, B> Clone for BufferSlice<T, B> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
BufferSlice {
|
||||
marker: PhantomData,
|
||||
@ -63,7 +62,6 @@ impl<T: ?Sized, B> Clone for BufferSlice<T, B> {
|
||||
}
|
||||
|
||||
impl<T: ?Sized, B> BufferSlice<T, B> {
|
||||
#[inline]
|
||||
pub fn from_typed_buffer_access(r: Arc<B>) -> Arc<BufferSlice<T, B>>
|
||||
where
|
||||
B: TypedBufferAccess<Content = T>,
|
||||
@ -84,13 +82,11 @@ impl<T: ?Sized, B> BufferSlice<T, B> {
|
||||
}
|
||||
|
||||
/// Returns the offset of that slice within the buffer.
|
||||
#[inline]
|
||||
pub fn offset(&self) -> DeviceSize {
|
||||
self.offset
|
||||
}
|
||||
|
||||
/// Returns the size of that slice in bytes.
|
||||
#[inline]
|
||||
pub fn size(&self) -> DeviceSize {
|
||||
self.size
|
||||
}
|
||||
@ -100,7 +96,7 @@ impl<T: ?Sized, B> BufferSlice<T, B> {
|
||||
/// This method builds an object that represents a slice of the buffer. No actual operation
|
||||
/// is performed.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// TODO
|
||||
///
|
||||
@ -111,7 +107,6 @@ impl<T: ?Sized, B> BufferSlice<T, B> {
|
||||
///
|
||||
/// You **must** return a reference to an element from the parameter. The closure **must not**
|
||||
/// panic.
|
||||
#[inline]
|
||||
pub unsafe fn slice_custom<F, R: ?Sized>(&self, f: F) -> Arc<BufferSlice<R, B>>
|
||||
where
|
||||
F: for<'r> FnOnce(&'r T) -> &'r R, // TODO: bounds on R
|
||||
@ -136,7 +131,7 @@ impl<T: ?Sized, B> BufferSlice<T, B> {
|
||||
/// useful when you have a buffer with various types of data and want to create a typed slice
|
||||
/// of a region that contains a single type of data.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use std::sync::Arc;
|
||||
@ -153,7 +148,6 @@ impl<T: ?Sized, B> BufferSlice<T, B> {
|
||||
///
|
||||
/// Correct `offset` and `size` must be ensured before using this `BufferSlice` on the device.
|
||||
/// See `BufferSlice::slice` for adjusting these properties.
|
||||
#[inline]
|
||||
pub unsafe fn reinterpret<R: ?Sized>(&self) -> Arc<BufferSlice<R, B>> {
|
||||
Arc::new(BufferSlice {
|
||||
marker: PhantomData,
|
||||
@ -166,7 +160,6 @@ impl<T: ?Sized, B> BufferSlice<T, B> {
|
||||
|
||||
impl<T, B> BufferSlice<[T], B> {
|
||||
/// Returns the number of elements in this slice.
|
||||
#[inline]
|
||||
pub fn len(&self) -> DeviceSize {
|
||||
debug_assert_eq!(self.size() % size_of::<T>() as DeviceSize, 0);
|
||||
self.size() / size_of::<T>() as DeviceSize
|
||||
@ -175,7 +168,6 @@ impl<T, B> BufferSlice<[T], B> {
|
||||
/// Reduces the slice to just one element of the array.
|
||||
///
|
||||
/// Returns `None` if out of range.
|
||||
#[inline]
|
||||
pub fn index(&self, index: DeviceSize) -> Option<Arc<BufferSlice<T, B>>> {
|
||||
if index >= self.len() {
|
||||
return None;
|
||||
@ -192,7 +184,6 @@ impl<T, B> BufferSlice<[T], B> {
|
||||
/// Reduces the slice to just a range of the array.
|
||||
///
|
||||
/// Returns `None` if out of range.
|
||||
#[inline]
|
||||
pub fn slice(&self, range: Range<DeviceSize>) -> Option<Arc<BufferSlice<[T], B>>> {
|
||||
if range.end > self.len() {
|
||||
return None;
|
||||
@ -212,7 +203,6 @@ where
|
||||
B: BufferAccess,
|
||||
T: Send + Sync + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> BufferInner<'_> {
|
||||
let inner = self.resource.inner();
|
||||
BufferInner {
|
||||
@ -221,7 +211,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size(&self) -> DeviceSize {
|
||||
self.size
|
||||
}
|
||||
@ -232,7 +221,6 @@ where
|
||||
B: BufferAccess + 'static,
|
||||
T: Send + Sync + ?Sized + 'static,
|
||||
{
|
||||
#[inline]
|
||||
fn as_buffer_access_object(&self) -> Arc<dyn BufferAccess> {
|
||||
self.clone()
|
||||
}
|
||||
@ -250,14 +238,12 @@ unsafe impl<T: ?Sized, B> DeviceOwned for BufferSlice<T, B>
|
||||
where
|
||||
B: DeviceOwned,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.resource.device()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, B> From<BufferSlice<T, B>> for BufferSlice<[T], B> {
|
||||
#[inline]
|
||||
fn from(r: BufferSlice<T, B>) -> BufferSlice<[T], B> {
|
||||
BufferSlice {
|
||||
marker: PhantomData,
|
||||
@ -273,7 +259,6 @@ where
|
||||
T: Send + Sync,
|
||||
B: BufferAccess,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner() == other.inner() && self.size() == other.size()
|
||||
}
|
||||
@ -291,7 +276,6 @@ where
|
||||
T: Send + Sync,
|
||||
B: BufferAccess,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().hash(state);
|
||||
self.size().hash(state);
|
||||
|
@ -279,6 +279,7 @@ impl UnsafeBuffer {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
handle: ash::vk::Buffer,
|
||||
@ -307,7 +308,6 @@ impl UnsafeBuffer {
|
||||
|
||||
/// Returns the memory requirements for this buffer.
|
||||
pub fn memory_requirements(&self) -> MemoryRequirements {
|
||||
#[inline]
|
||||
fn align(val: DeviceSize, al: DeviceSize) -> DeviceSize {
|
||||
al * (1 + (val - 1) / al)
|
||||
}
|
||||
@ -443,6 +443,7 @@ impl UnsafeBuffer {
|
||||
)
|
||||
.result()
|
||||
.map_err(VulkanError::from)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -511,7 +512,6 @@ impl PartialEq for UnsafeBuffer {
|
||||
impl Eq for UnsafeBuffer {}
|
||||
|
||||
impl Hash for UnsafeBuffer {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device.hash(state);
|
||||
@ -590,17 +590,15 @@ pub enum BufferCreationError {
|
||||
}
|
||||
|
||||
impl Error for BufferCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
BufferCreationError::AllocError(ref err) => Some(err),
|
||||
match self {
|
||||
BufferCreationError::AllocError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for BufferCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::AllocError(_) => write!(f, "allocating memory failed"),
|
||||
@ -614,24 +612,24 @@ impl Display for BufferCreationError {
|
||||
),
|
||||
Self::MaxBufferSizeExceeded { .. } => write!(
|
||||
f,
|
||||
"the specified size exceeded the value of the `max_buffer_size` limit"
|
||||
"the specified size exceeded the value of the `max_buffer_size` limit",
|
||||
),
|
||||
Self::SharingQueueFamilyIndexOutOfRange { .. } => write!(
|
||||
f,
|
||||
"the sharing mode was set to `Concurrent`, but one of the specified queue family \
|
||||
indices was out of range",
|
||||
),
|
||||
Self::SharingQueueFamilyIndexOutOfRange { .. } => {
|
||||
write!(f, "the sharing mode was set to `Concurrent`, but one of the specified queue family indices was out of range")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for BufferCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> BufferCreationError {
|
||||
BufferCreationError::AllocError(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for BufferCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> BufferCreationError {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => {
|
||||
@ -646,7 +644,6 @@ impl From<VulkanError> for BufferCreationError {
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for BufferCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -49,7 +49,6 @@ pub unsafe trait BufferAccess: DeviceOwned + Send + Sync {
|
||||
///
|
||||
/// This method can be used when you want to perform an operation on some part of the buffer
|
||||
/// and not on the whole buffer.
|
||||
#[inline]
|
||||
fn slice<T>(self: &Arc<Self>, range: Range<DeviceSize>) -> Option<Arc<BufferSlice<[T], Self>>>
|
||||
where
|
||||
Self: Sized + TypedBufferAccess<Content = [T]>,
|
||||
@ -61,7 +60,6 @@ pub unsafe trait BufferAccess: DeviceOwned + Send + Sync {
|
||||
///
|
||||
/// This method can be used when you want to perform an operation on a specific element of the
|
||||
/// buffer and not on the whole buffer.
|
||||
#[inline]
|
||||
fn index<T>(self: &Arc<Self>, index: DeviceSize) -> Option<Arc<BufferSlice<T, Self>>>
|
||||
where
|
||||
Self: Sized + TypedBufferAccess<Content = [T]>,
|
||||
@ -121,6 +119,7 @@ pub trait BufferAccessObject {
|
||||
}
|
||||
|
||||
impl BufferAccessObject for Arc<dyn BufferAccess> {
|
||||
#[inline]
|
||||
fn as_buffer_access_object(&self) -> Arc<dyn BufferAccess> {
|
||||
self.clone()
|
||||
}
|
||||
@ -141,12 +140,10 @@ where
|
||||
T: SafeDeref + Send + Sync,
|
||||
T::Target: BufferAccess,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> BufferInner<'_> {
|
||||
(**self).inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size(&self) -> DeviceSize {
|
||||
(**self).size()
|
||||
}
|
||||
@ -192,7 +189,6 @@ impl PartialEq for dyn BufferAccess {
|
||||
impl Eq for dyn BufferAccess {}
|
||||
|
||||
impl Hash for dyn BufferAccess {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().hash(state);
|
||||
self.size().hash(state);
|
||||
@ -213,7 +209,6 @@ pub enum BufferDeviceAddressError {
|
||||
impl Error for BufferDeviceAddressError {}
|
||||
|
||||
impl Display for BufferDeviceAddressError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::RequirementNotMet {
|
||||
@ -224,7 +219,6 @@ impl Display for BufferDeviceAddressError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::BufferMissingUsage => write!(
|
||||
f,
|
||||
"the device address usage flag was not set on this buffer",
|
||||
|
@ -15,7 +15,7 @@
|
||||
//! In order to create a view from a buffer, the buffer must have been created with either the
|
||||
//! `uniform_texel_buffer` or the `storage_texel_buffer` usage.
|
||||
//!
|
||||
//! # Example
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```
|
||||
//! # use std::sync::Arc;
|
||||
@ -235,7 +235,6 @@ where
|
||||
}
|
||||
|
||||
/// Returns the buffer associated to this view.
|
||||
#[inline]
|
||||
pub fn buffer(&self) -> &Arc<B> {
|
||||
&self.buffer
|
||||
}
|
||||
@ -245,7 +244,6 @@ impl<B> Drop for BufferView<B>
|
||||
where
|
||||
B: BufferAccess + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let fns = self.buffer.inner().buffer.device().fns();
|
||||
@ -264,7 +262,6 @@ where
|
||||
{
|
||||
type Object = ash::vk::BufferView;
|
||||
|
||||
#[inline]
|
||||
fn internal_object(&self) -> ash::vk::BufferView {
|
||||
self.handle
|
||||
}
|
||||
@ -274,7 +271,6 @@ unsafe impl<B> DeviceOwned for BufferView<B>
|
||||
where
|
||||
B: BufferAccess + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.buffer.device()
|
||||
}
|
||||
@ -284,7 +280,6 @@ impl<B> PartialEq for BufferView<B>
|
||||
where
|
||||
B: BufferAccess + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.handle == other.handle && self.device() == other.device()
|
||||
}
|
||||
@ -296,7 +291,6 @@ impl<B> Hash for BufferView<B>
|
||||
where
|
||||
B: BufferAccess + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -359,24 +353,18 @@ pub enum BufferViewCreationError {
|
||||
}
|
||||
|
||||
impl Error for BufferViewCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
BufferViewCreationError::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
BufferViewCreationError::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for BufferViewCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::OomError(_) => write!(
|
||||
f,
|
||||
"out of memory when creating buffer view",
|
||||
),
|
||||
|
||||
Self::OomError(_) => write!(f, "out of memory when creating buffer view"),
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -385,10 +373,10 @@ impl Display for BufferViewCreationError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::BufferMissingUsage => write!(
|
||||
f,
|
||||
"the buffer was not created with one of the `storage_texel_buffer` or `uniform_texel_buffer` usages",
|
||||
"the buffer was not created with one of the `storage_texel_buffer` or \
|
||||
`uniform_texel_buffer` usages",
|
||||
),
|
||||
Self::OffsetNotAligned { .. } => write!(
|
||||
f,
|
||||
@ -398,34 +386,29 @@ impl Display for BufferViewCreationError {
|
||||
f,
|
||||
"the range within the buffer is not a multiple of the required alignment",
|
||||
),
|
||||
Self::UnsupportedFormat => write!(
|
||||
f,
|
||||
"the requested format is not supported for this usage",
|
||||
),
|
||||
Self::MaxTexelBufferElementsExceeded => write!(
|
||||
f,
|
||||
"the `max_texel_buffer_elements` limit has been exceeded",
|
||||
),
|
||||
Self::UnsupportedFormat => {
|
||||
write!(f, "the requested format is not supported for this usage")
|
||||
}
|
||||
Self::MaxTexelBufferElementsExceeded => {
|
||||
write!(f, "the `max_texel_buffer_elements` limit has been exceeded")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for BufferViewCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for BufferViewCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
OomError::from(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for BufferViewCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
@ -455,22 +438,18 @@ where
|
||||
B: BufferAccess + ?Sized + 'static,
|
||||
Arc<B>: BufferAccessObject,
|
||||
{
|
||||
#[inline]
|
||||
fn buffer(&self) -> Arc<dyn BufferAccess> {
|
||||
self.buffer.as_buffer_access_object()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn format(&self) -> Option<Format> {
|
||||
self.format
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn format_features(&self) -> &FormatFeatures {
|
||||
&self.format_features
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn range(&self) -> Range<DeviceSize> {
|
||||
self.range.clone()
|
||||
}
|
||||
@ -486,7 +465,6 @@ impl PartialEq for dyn BufferViewAbstract {
|
||||
impl Eq for dyn BufferViewAbstract {}
|
||||
|
||||
impl Hash for dyn BufferViewAbstract {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.internal_object().hash(state);
|
||||
self.device().hash(state);
|
||||
|
@ -83,14 +83,12 @@ pub(super) enum RenderPassStateType {
|
||||
}
|
||||
|
||||
impl From<BeginRenderPassState> for RenderPassStateType {
|
||||
#[inline]
|
||||
fn from(val: BeginRenderPassState) -> Self {
|
||||
Self::BeginRenderPass(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BeginRenderingState> for RenderPassStateType {
|
||||
#[inline]
|
||||
fn from(val: BeginRenderingState) -> Self {
|
||||
Self::BeginRendering(val)
|
||||
}
|
||||
@ -532,21 +530,18 @@ pub enum CommandBufferBeginError {
|
||||
}
|
||||
|
||||
impl Error for CommandBufferBeginError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for CommandBufferBeginError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -555,7 +550,6 @@ impl Display for CommandBufferBeginError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::ColorAttachmentFormatUsageNotSupported { attachment_index } => write!(
|
||||
f,
|
||||
"color attachment {} has a format that does not support that usage",
|
||||
@ -570,10 +564,10 @@ impl Display for CommandBufferBeginError {
|
||||
"the depth and stencil attachments have different formats",
|
||||
),
|
||||
Self::FramebufferNotCompatible => {
|
||||
write!(f, "the framebuffer is not compatible with the render pass",)
|
||||
write!(f, "the framebuffer is not compatible with the render pass")
|
||||
}
|
||||
Self::MaxMultiviewViewCountExceeded { .. } => {
|
||||
write!(f, "the `max_multiview_view_count` limit has been exceeded",)
|
||||
write!(f, "the `max_multiview_view_count` limit has been exceeded")
|
||||
}
|
||||
Self::StencilAttachmentFormatUsageNotSupported => write!(
|
||||
f,
|
||||
@ -584,14 +578,12 @@ impl Display for CommandBufferBeginError {
|
||||
}
|
||||
|
||||
impl From<OomError> for CommandBufferBeginError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for CommandBufferBeginError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
@ -605,7 +597,6 @@ where
|
||||
P: CommandPoolBuilderAlloc,
|
||||
{
|
||||
/// Builds the command buffer.
|
||||
#[inline]
|
||||
pub fn build(self) -> Result<PrimaryAutoCommandBuffer<P::Alloc>, BuildError> {
|
||||
if self.render_pass_state.is_some() {
|
||||
return Err(BuildError::RenderPassActive);
|
||||
@ -638,7 +629,6 @@ where
|
||||
P: CommandPoolBuilderAlloc,
|
||||
{
|
||||
/// Builds the command buffer.
|
||||
#[inline]
|
||||
pub fn build(self) -> Result<SecondaryAutoCommandBuffer<P::Alloc>, BuildError> {
|
||||
if !self.query_state.is_empty() {
|
||||
return Err(BuildError::QueryActive);
|
||||
@ -676,7 +666,6 @@ pub enum BuildError {
|
||||
}
|
||||
|
||||
impl Error for BuildError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
@ -698,27 +687,23 @@ impl Display for BuildError {
|
||||
}
|
||||
|
||||
impl From<OomError> for BuildError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
#[inline]
|
||||
pub(super) fn queue_family_properties(&self) -> &QueueFamilyProperties {
|
||||
&self.device().physical_device().queue_family_properties()[self.queue_family_index as usize]
|
||||
}
|
||||
|
||||
/// Returns the binding/setting state.
|
||||
#[inline]
|
||||
pub fn state(&self) -> CommandBufferState<'_> {
|
||||
self.inner.state()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<L, P> DeviceOwned for AutoCommandBufferBuilder<L, P> {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.inner.device()
|
||||
}
|
||||
@ -733,7 +718,6 @@ pub struct PrimaryAutoCommandBuffer<P = StandardCommandPoolAlloc> {
|
||||
}
|
||||
|
||||
unsafe impl<P> DeviceOwned for PrimaryAutoCommandBuffer<P> {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.inner.device()
|
||||
}
|
||||
@ -743,12 +727,10 @@ unsafe impl<P> PrimaryCommandBuffer for PrimaryAutoCommandBuffer<P>
|
||||
where
|
||||
P: CommandPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> &UnsafeCommandBuffer {
|
||||
self.inner.as_ref()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lock_submit(
|
||||
&self,
|
||||
future: &dyn GpuFuture,
|
||||
@ -793,7 +775,6 @@ where
|
||||
Err(err)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unlock(&self) {
|
||||
// Because of panic safety, we unlock the inner command buffer first.
|
||||
self.inner.unlock();
|
||||
@ -812,7 +793,6 @@ where
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_buffer_access(
|
||||
&self,
|
||||
buffer: &UnsafeBuffer,
|
||||
@ -824,7 +804,6 @@ where
|
||||
.check_buffer_access(buffer, range, exclusive, queue)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_image_access(
|
||||
&self,
|
||||
image: &UnsafeImage,
|
||||
@ -848,7 +827,6 @@ pub struct SecondaryAutoCommandBuffer<P = StandardCommandPoolAlloc> {
|
||||
}
|
||||
|
||||
unsafe impl<P> DeviceOwned for SecondaryAutoCommandBuffer<P> {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.inner.device()
|
||||
}
|
||||
@ -858,12 +836,10 @@ unsafe impl<P> SecondaryCommandBuffer for SecondaryAutoCommandBuffer<P>
|
||||
where
|
||||
P: CommandPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> &UnsafeCommandBuffer {
|
||||
self.inner.as_ref()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lock_record(&self) -> Result<(), CommandBufferExecError> {
|
||||
match self.submit_state {
|
||||
SubmitState::OneTime {
|
||||
@ -886,7 +862,6 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unlock(&self) {
|
||||
match self.submit_state {
|
||||
SubmitState::OneTime {
|
||||
@ -902,17 +877,14 @@ where
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inheritance_info(&self) -> &CommandBufferInheritanceInfo {
|
||||
&self.inheritance_info
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_buffers(&self) -> usize {
|
||||
self.inner.num_buffers()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn buffer(
|
||||
&self,
|
||||
index: usize,
|
||||
@ -924,12 +896,10 @@ where
|
||||
self.inner.buffer(index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_images(&self) -> usize {
|
||||
self.inner.num_images()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn image(
|
||||
&self,
|
||||
index: usize,
|
||||
|
@ -703,7 +703,6 @@ impl SyncCommandBufferBuilder {
|
||||
}
|
||||
|
||||
/// Calls `vkCmdPushConstants` on the builder.
|
||||
#[inline]
|
||||
pub unsafe fn push_constants<D>(
|
||||
&mut self,
|
||||
pipeline_layout: Arc<PipelineLayout>,
|
||||
@ -838,7 +837,6 @@ pub struct SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
||||
|
||||
impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> {
|
||||
/// Adds a descriptor set to the list.
|
||||
#[inline]
|
||||
pub fn add(&mut self, descriptor_set: impl Into<DescriptorSetWithOffsets>) {
|
||||
self.descriptor_sets.push(descriptor_set.into());
|
||||
}
|
||||
@ -1069,7 +1067,6 @@ impl UnsafeCommandBufferBuilder {
|
||||
}
|
||||
|
||||
/// Calls `vkCmdPushConstants` on the builder.
|
||||
#[inline]
|
||||
pub unsafe fn push_constants<D>(
|
||||
&mut self,
|
||||
pipeline_layout: &PipelineLayout,
|
||||
@ -1101,7 +1098,6 @@ impl UnsafeCommandBufferBuilder {
|
||||
/// Calls `vkCmdPushDescriptorSetKHR` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn push_descriptor_set<'a>(
|
||||
&mut self,
|
||||
pipeline_bind_point: PipelineBindPoint,
|
||||
@ -1162,6 +1158,7 @@ impl UnsafeCommandBufferBuilder {
|
||||
}
|
||||
|
||||
/// Prototype for a `vkCmdBindVertexBuffers`.
|
||||
#[derive(Debug)]
|
||||
pub struct UnsafeCommandBufferBuilderBindVertexBuffer {
|
||||
// Raw handles of the buffers to bind.
|
||||
pub raw_buffers: SmallVec<[ash::vk::Buffer; 4]>,
|
||||
@ -1267,7 +1264,6 @@ impl error::Error for BindPushError {
|
||||
}
|
||||
|
||||
impl Display for BindPushError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::RequirementNotMet {
|
||||
@ -1278,83 +1274,78 @@ impl Display for BindPushError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::DescriptorSetUpdateError(_) => write!(
|
||||
f,
|
||||
"a DescriptorSetUpdateError",
|
||||
),
|
||||
|
||||
Self::DescriptorSetUpdateError(_) => write!(f, "a DescriptorSetUpdateError"),
|
||||
Self::DescriptorSetNotCompatible { set_num } => write!(
|
||||
f,
|
||||
"the element of `descriptor_sets` being bound to slot {} is not compatible with the corresponding slot in `pipeline_layout`",
|
||||
"the element of `descriptor_sets` being bound to slot {} is not compatible with \
|
||||
the corresponding slot in `pipeline_layout`",
|
||||
set_num,
|
||||
),
|
||||
Self::DescriptorSetNotPush { set_num } => write!(
|
||||
f,
|
||||
"the descriptor set number being pushed ({}) is not defined for push descriptor sets in the pipeline layout",
|
||||
"the descriptor set number being pushed ({}) is not defined for push descriptor \
|
||||
sets in the pipeline layout",
|
||||
set_num,
|
||||
),
|
||||
Self::DescriptorSetOutOfRange { set_num, pipeline_layout_set_count } => write!(
|
||||
Self::DescriptorSetOutOfRange {
|
||||
set_num,
|
||||
pipeline_layout_set_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the highest descriptor set slot being bound ({}) is greater than the number of sets in `pipeline_layout` ({})",
|
||||
"the highest descriptor set slot being bound ({}) is greater than the number of \
|
||||
sets in `pipeline_layout` ({})",
|
||||
set_num, pipeline_layout_set_count,
|
||||
),
|
||||
Self::IndexBufferMissingUsage => write!(
|
||||
f,
|
||||
"an index buffer is missing the `index_buffer` usage",
|
||||
),
|
||||
Self::MaxVertexInputBindingsExceeded { .. } => write!(
|
||||
f,
|
||||
"the `max_vertex_input_bindings` limit has been exceeded",
|
||||
),
|
||||
Self::NotSupportedByQueueFamily => write!(
|
||||
f,
|
||||
"the queue family doesn't allow this operation",
|
||||
),
|
||||
Self::IndexBufferMissingUsage => {
|
||||
write!(f, "an index buffer is missing the `index_buffer` usage")
|
||||
}
|
||||
Self::MaxVertexInputBindingsExceeded { .. } => {
|
||||
write!(f, "the `max_vertex_input_bindings` limit has been exceeded")
|
||||
}
|
||||
Self::NotSupportedByQueueFamily => {
|
||||
write!(f, "the queue family doesn't allow this operation")
|
||||
}
|
||||
Self::PreviousPipelineColorAttachmentFormatMismatch => write!(
|
||||
f,
|
||||
"the newly set pipeline has color attachment formats that do not match the previously used pipeline",
|
||||
"the newly set pipeline has color attachment formats that do not match the \
|
||||
previously used pipeline",
|
||||
),
|
||||
Self::PreviousPipelineDepthAttachmentFormatMismatch => write!(
|
||||
f,
|
||||
"the newly set pipeline has a depth attachment format that does not match the previously used pipeline",
|
||||
"the newly set pipeline has a depth attachment format that does not match the \
|
||||
previously used pipeline",
|
||||
),
|
||||
Self::PreviousPipelineStencilAttachmentFormatMismatch => write!(
|
||||
f,
|
||||
"the newly set pipeline has a stencil attachment format that does not match the previously used pipeline"
|
||||
"the newly set pipeline has a stencil attachment format that does not match the \
|
||||
previously used pipeline",
|
||||
),
|
||||
Self::PushConstantsDataOutOfRange {
|
||||
offset,
|
||||
} => write!(
|
||||
Self::PushConstantsDataOutOfRange { offset } => write!(
|
||||
f,
|
||||
"the push constants data to be written at offset {} is not included in any push constant range of the pipeline layout",
|
||||
"the push constants data to be written at offset {} is not included in any push \
|
||||
constant range of the pipeline layout",
|
||||
offset,
|
||||
),
|
||||
Self::PushConstantsOffsetNotAligned => write!(
|
||||
f,
|
||||
"the push constants offset is not a multiple of 4",
|
||||
),
|
||||
Self::PushConstantsSizeNotAligned => write!(
|
||||
f,
|
||||
"the push constants size is not a multiple of 4",
|
||||
),
|
||||
Self::VertexBufferMissingUsage => write!(
|
||||
f,
|
||||
"a vertex buffer is missing the `vertex_buffer` usage",
|
||||
),
|
||||
Self::PushConstantsOffsetNotAligned => {
|
||||
write!(f, "the push constants offset is not a multiple of 4")
|
||||
}
|
||||
Self::PushConstantsSizeNotAligned => {
|
||||
write!(f, "the push constants size is not a multiple of 4")
|
||||
}
|
||||
Self::VertexBufferMissingUsage => {
|
||||
write!(f, "a vertex buffer is missing the `vertex_buffer` usage")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DescriptorSetUpdateError> for BindPushError {
|
||||
#[inline]
|
||||
fn from(err: DescriptorSetUpdateError) -> Self {
|
||||
Self::DescriptorSetUpdateError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for BindPushError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -30,7 +30,6 @@ use std::{
|
||||
/// instance.
|
||||
impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// Opens a command buffer debug label region.
|
||||
#[inline]
|
||||
pub fn begin_debug_utils_label(
|
||||
&mut self,
|
||||
mut label_info: DebugUtilsLabel,
|
||||
@ -82,7 +81,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// - When submitting the command buffer, there must be an outstanding command buffer label
|
||||
/// region begun with `begin_debug_utils_label` in the queue, either within this command
|
||||
/// buffer or a previously submitted one.
|
||||
#[inline]
|
||||
pub unsafe fn end_debug_utils_label(&mut self) -> Result<&mut Self, DebugUtilsError> {
|
||||
self.validate_end_debug_utils_label()?;
|
||||
|
||||
@ -126,7 +124,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
}
|
||||
|
||||
/// Inserts a command buffer debug label.
|
||||
#[inline]
|
||||
pub fn insert_debug_utils_label(
|
||||
&mut self,
|
||||
mut label_info: DebugUtilsLabel,
|
||||
@ -323,7 +320,6 @@ pub enum DebugUtilsError {
|
||||
impl Error for DebugUtilsError {}
|
||||
|
||||
impl Display for DebugUtilsError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::RequirementNotMet {
|
||||
@ -334,7 +330,6 @@ impl Display for DebugUtilsError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::NotSupportedByQueueFamily => {
|
||||
write!(f, "the queue family doesn't allow this operation")
|
||||
}
|
||||
|
@ -96,7 +96,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
/// - If there is a graphics pipeline with color blend state bound, `enables.len()` must equal
|
||||
/// - [`attachments.len()`](crate::pipeline::graphics::color_blend::ColorBlendState::attachments).
|
||||
#[inline]
|
||||
pub fn set_color_write_enable<I>(&mut self, enables: I) -> &mut Self
|
||||
where
|
||||
I: IntoIterator<Item = bool>,
|
||||
@ -166,7 +165,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
|
||||
/// not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
#[inline]
|
||||
pub fn set_cull_mode(&mut self, cull_mode: CullMode) -> &mut Self {
|
||||
self.validate_set_cull_mode(cull_mode).unwrap();
|
||||
|
||||
@ -215,7 +213,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
/// - If the [`depth_bias_clamp`](crate::device::Features::depth_bias_clamp)
|
||||
/// feature is not enabled on the device, panics if `clamp` is not 0.0.
|
||||
#[inline]
|
||||
pub fn set_depth_bias(
|
||||
&mut self,
|
||||
constant_factor: f32,
|
||||
@ -271,7 +268,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`extended_dynamic_state2`](crate::device::Features::extended_dynamic_state2) feature is
|
||||
/// not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
#[inline]
|
||||
pub fn set_depth_bias_enable(&mut self, enable: bool) -> &mut Self {
|
||||
self.validate_set_depth_bias_enable(enable).unwrap();
|
||||
|
||||
@ -371,7 +367,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
|
||||
/// not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
#[inline]
|
||||
pub fn set_depth_bounds_test_enable(&mut self, enable: bool) -> &mut Self {
|
||||
self.validate_set_depth_bounds_test_enable(enable).unwrap();
|
||||
|
||||
@ -421,7 +416,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
|
||||
/// not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
#[inline]
|
||||
pub fn set_depth_compare_op(&mut self, compare_op: CompareOp) -> &mut Self {
|
||||
self.validate_set_depth_compare_op(compare_op).unwrap();
|
||||
|
||||
@ -474,7 +468,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
|
||||
/// not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
#[inline]
|
||||
pub fn set_depth_test_enable(&mut self, enable: bool) -> &mut Self {
|
||||
self.validate_set_depth_test_enable(enable).unwrap();
|
||||
|
||||
@ -521,7 +514,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
|
||||
/// not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
#[inline]
|
||||
pub fn set_depth_write_enable(&mut self, enable: bool) -> &mut Self {
|
||||
self.validate_set_depth_write_enable(enable).unwrap();
|
||||
|
||||
@ -644,7 +636,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
|
||||
/// not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
#[inline]
|
||||
pub fn set_front_face(&mut self, face: FrontFace) -> &mut Self {
|
||||
self.validate_set_front_face(face).unwrap();
|
||||
|
||||
@ -694,7 +685,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// extension is not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
/// - Panics if `factor` is not between 1 and 256 inclusive.
|
||||
#[inline]
|
||||
pub fn set_line_stipple(&mut self, factor: u32, pattern: u16) -> &mut Self {
|
||||
self.validate_set_line_stipple(factor, pattern).unwrap();
|
||||
|
||||
@ -788,7 +778,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`extended_dynamic_state2_logic_op`](crate::device::Features::extended_dynamic_state2_logic_op)
|
||||
/// feature is not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
#[inline]
|
||||
pub fn set_logic_op(&mut self, logic_op: LogicOp) -> &mut Self {
|
||||
self.validate_set_logic_op(logic_op).unwrap();
|
||||
|
||||
@ -843,7 +832,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// - Panics if `num` is greater than the
|
||||
/// [`max_tessellation_patch_size`](crate::device::Properties::max_tessellation_patch_size)
|
||||
/// property of the device.
|
||||
#[inline]
|
||||
pub fn set_patch_control_points(&mut self, num: u32) -> &mut Self {
|
||||
self.validate_set_patch_control_points(num).unwrap();
|
||||
|
||||
@ -912,7 +900,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`extended_dynamic_state2`](crate::device::Features::extended_dynamic_state2) feature is
|
||||
/// not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
#[inline]
|
||||
pub fn set_primitive_restart_enable(&mut self, enable: bool) -> &mut Self {
|
||||
self.validate_set_primitive_restart_enable(enable).unwrap();
|
||||
|
||||
@ -966,7 +953,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// enabled, panics if `topology` is a `WithAdjacency` topology.
|
||||
/// - If the [`tessellation_shader`](crate::device::Features::tessellation_shader) feature is
|
||||
/// not enabled, panics if `topology` is `PatchList`.
|
||||
#[inline]
|
||||
pub fn set_primitive_topology(&mut self, topology: PrimitiveTopology) -> &mut Self {
|
||||
self.validate_set_primitive_topology(topology).unwrap();
|
||||
|
||||
@ -1051,7 +1037,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`extended_dynamic_state2`](crate::device::Features::extended_dynamic_state2) feature is
|
||||
/// not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
#[inline]
|
||||
pub fn set_rasterizer_discard_enable(&mut self, enable: bool) -> &mut Self {
|
||||
self.validate_set_rasterizer_discard_enable(enable).unwrap();
|
||||
|
||||
@ -1181,7 +1166,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`max_viewports`](crate::device::Properties::max_viewports) device property.
|
||||
/// - If the [`multi_viewport`](crate::device::Features::multi_viewport) feature is not enabled,
|
||||
/// panics if more than 1 scissor is provided.
|
||||
#[inline]
|
||||
pub fn set_scissor_with_count(
|
||||
&mut self,
|
||||
scissors: impl IntoIterator<Item = Scissor>,
|
||||
@ -1295,7 +1279,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
|
||||
/// not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
#[inline]
|
||||
pub fn set_stencil_op(
|
||||
&mut self,
|
||||
faces: StencilFaces,
|
||||
@ -1410,7 +1393,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
|
||||
/// not enabled on the device.
|
||||
/// - Panics if the currently bound graphics pipeline already contains this state internally.
|
||||
#[inline]
|
||||
pub fn set_stencil_test_enable(&mut self, enable: bool) -> &mut Self {
|
||||
self.validate_set_stencil_test_enable(enable).unwrap();
|
||||
|
||||
@ -1575,7 +1557,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// [`max_viewports`](crate::device::Properties::max_viewports) device property.
|
||||
/// - If the [`multi_viewport`](crate::device::Features::multi_viewport) feature is not enabled,
|
||||
/// panics if more than 1 viewport is provided.
|
||||
#[inline]
|
||||
pub fn set_viewport_with_count(
|
||||
&mut self,
|
||||
viewports: impl IntoIterator<Item = Viewport>,
|
||||
@ -1665,7 +1646,6 @@ impl SyncCommandBufferBuilder {
|
||||
/// Calls `vkCmdSetColorWriteEnableEXT` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn set_color_write_enable(&mut self, enables: impl IntoIterator<Item = bool>) {
|
||||
struct Cmd<I> {
|
||||
enables: Mutex<Option<I>>,
|
||||
@ -1874,7 +1854,6 @@ impl SyncCommandBufferBuilder {
|
||||
/// Calls `vkCmdSetDiscardRectangle` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn set_discard_rectangle(
|
||||
&mut self,
|
||||
first_rectangle: u32,
|
||||
@ -2260,7 +2239,6 @@ impl SyncCommandBufferBuilder {
|
||||
/// Calls `vkCmdSetScissor` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn set_scissor(
|
||||
&mut self,
|
||||
first_scissor: u32,
|
||||
@ -2297,7 +2275,6 @@ impl SyncCommandBufferBuilder {
|
||||
/// Calls `vkCmdSetScissorWithCountEXT` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn set_scissor_with_count(&mut self, scissors: impl IntoIterator<Item = Scissor>) {
|
||||
struct Cmd {
|
||||
scissors: Mutex<SmallVec<[Scissor; 2]>>,
|
||||
@ -2323,7 +2300,6 @@ impl SyncCommandBufferBuilder {
|
||||
/// Calls `vkCmdSetViewport` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn set_viewport(
|
||||
&mut self,
|
||||
first_viewport: u32,
|
||||
@ -2360,7 +2336,6 @@ impl SyncCommandBufferBuilder {
|
||||
/// Calls `vkCmdSetViewportWithCountEXT` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn set_viewport_with_count(
|
||||
&mut self,
|
||||
viewports: impl IntoIterator<Item = Viewport>,
|
||||
@ -2398,7 +2373,6 @@ impl UnsafeCommandBufferBuilder {
|
||||
/// Calls `vkCmdSetColorWriteEnableEXT` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn set_color_write_enable(&mut self, enables: impl IntoIterator<Item = bool>) {
|
||||
debug_assert!(self.device.enabled_extensions().ext_color_write_enable);
|
||||
|
||||
@ -2522,7 +2496,6 @@ impl UnsafeCommandBufferBuilder {
|
||||
/// Calls `vkCmdSetDiscardRectangleEXT` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn set_discard_rectangle(
|
||||
&mut self,
|
||||
first_rectangle: u32,
|
||||
@ -2722,7 +2695,6 @@ impl UnsafeCommandBufferBuilder {
|
||||
/// Calls `vkCmdSetScissor` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn set_scissor(
|
||||
&mut self,
|
||||
first_scissor: u32,
|
||||
@ -2748,7 +2720,6 @@ impl UnsafeCommandBufferBuilder {
|
||||
/// Calls `vkCmdSetScissorWithCountEXT` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn set_scissor_with_count(&mut self, scissors: impl IntoIterator<Item = Scissor>) {
|
||||
let scissors = scissors
|
||||
.into_iter()
|
||||
@ -2780,7 +2751,6 @@ impl UnsafeCommandBufferBuilder {
|
||||
/// Calls `vkCmdSetViewport` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn set_viewport(
|
||||
&mut self,
|
||||
first_viewport: u32,
|
||||
@ -2806,7 +2776,6 @@ impl UnsafeCommandBufferBuilder {
|
||||
/// Calls `vkCmdSetViewportWithCountEXT` on the builder.
|
||||
///
|
||||
/// If the list is empty then the command is automatically ignored.
|
||||
#[inline]
|
||||
pub unsafe fn set_viewport_with_count(
|
||||
&mut self,
|
||||
viewports: impl IntoIterator<Item = Viewport>,
|
||||
@ -2880,7 +2849,6 @@ enum SetDynamicStateError {
|
||||
impl Error for SetDynamicStateError {}
|
||||
|
||||
impl Display for SetDynamicStateError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::RequirementNotMet {
|
||||
@ -2891,45 +2859,42 @@ impl Display for SetDynamicStateError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::FactorOutOfRange => write!(
|
||||
f,
|
||||
"the provided `factor` is not between 1 and 256 inclusive",
|
||||
),
|
||||
Self::MaxDiscardRectanglesExceeded { .. } => write!(
|
||||
f,
|
||||
"the `max_discard_rectangles` limit has been exceeded",
|
||||
),
|
||||
Self::MaxDiscardRectanglesExceeded { .. } => {
|
||||
write!(f, "the `max_discard_rectangles` limit has been exceeded")
|
||||
}
|
||||
Self::MaxTessellationPatchSizeExceeded { .. } => write!(
|
||||
f,
|
||||
"the `max_tessellation_patch_size` limit has been exceeded",
|
||||
),
|
||||
Self::MaxViewportsExceeded { .. } => write!(
|
||||
f,
|
||||
"the `max_viewports` limit has been exceeded",
|
||||
),
|
||||
Self::NotSupportedByQueueFamily => write!(
|
||||
f,
|
||||
"the queue family doesn't allow this operation",
|
||||
),
|
||||
Self::MaxViewportsExceeded { .. } => {
|
||||
write!(f, "the `max_viewports` limit has been exceeded")
|
||||
}
|
||||
Self::NotSupportedByQueueFamily => {
|
||||
write!(f, "the queue family doesn't allow this operation")
|
||||
}
|
||||
Self::PipelineColorBlendAttachmentCountMismatch {
|
||||
provided_count,
|
||||
required_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the provided item count ({}) is different from the number of attachments in the color blend state of the currently bound pipeline ({})",
|
||||
"the provided item count ({}) is different from the number of attachments in the \
|
||||
color blend state of the currently bound pipeline ({})",
|
||||
provided_count, required_count,
|
||||
),
|
||||
Self::PipelineHasFixedState => write!(
|
||||
f,
|
||||
"the currently bound pipeline contains this state as internally fixed state, which cannot be overridden with dynamic state",
|
||||
"the currently bound pipeline contains this state as internally fixed state, which \
|
||||
cannot be overridden with dynamic state",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for SetDynamicStateError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -61,10 +61,9 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// If `layer_count` is greater than 1, the blit will happen between each individual layer as
|
||||
/// if they were separate images.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the source or the destination was not created with `device`.
|
||||
#[inline]
|
||||
pub fn blit_image(&mut self, blit_image_info: BlitImageInfo) -> Result<&mut Self, CopyError> {
|
||||
self.validate_blit_image(&blit_image_info)?;
|
||||
|
||||
@ -561,7 +560,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
}
|
||||
|
||||
/// Clears a color image with a specific value.
|
||||
#[inline]
|
||||
pub fn clear_color_image(
|
||||
&mut self,
|
||||
clear_info: ClearColorImageInfo,
|
||||
@ -714,7 +712,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
}
|
||||
|
||||
/// Clears a depth/stencil image with a specific value.
|
||||
#[inline]
|
||||
pub fn clear_depth_stencil_image(
|
||||
&mut self,
|
||||
clear_info: ClearDepthStencilImageInfo,
|
||||
@ -889,7 +886,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
///
|
||||
/// - Panics if `src_image` or `dst_image` were not created from the same device
|
||||
/// as `self`.
|
||||
#[inline]
|
||||
pub fn resolve_image(
|
||||
&mut self,
|
||||
resolve_image_info: ResolveImageInfo,
|
||||
@ -1271,6 +1267,7 @@ impl SyncCommandBufferBuilder {
|
||||
///
|
||||
/// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid
|
||||
/// usage of the command anyway.
|
||||
#[inline]
|
||||
pub unsafe fn clear_color_image(
|
||||
&mut self,
|
||||
clear_info: ClearColorImageInfo,
|
||||
@ -1341,6 +1338,7 @@ impl SyncCommandBufferBuilder {
|
||||
///
|
||||
/// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid
|
||||
/// usage of the command anyway.
|
||||
#[inline]
|
||||
pub unsafe fn clear_depth_stencil_image(
|
||||
&mut self,
|
||||
clear_info: ClearDepthStencilImageInfo,
|
||||
@ -1678,6 +1676,7 @@ impl UnsafeCommandBufferBuilder {
|
||||
///
|
||||
/// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid
|
||||
/// usage of the command anyway.
|
||||
#[inline]
|
||||
pub unsafe fn clear_color_image(&mut self, clear_info: &ClearColorImageInfo) {
|
||||
let &ClearColorImageInfo {
|
||||
ref image,
|
||||
@ -1713,6 +1712,7 @@ impl UnsafeCommandBufferBuilder {
|
||||
///
|
||||
/// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid
|
||||
/// usage of the command anyway.
|
||||
#[inline]
|
||||
pub unsafe fn clear_depth_stencil_image(&mut self, clear_info: &ClearDepthStencilImageInfo) {
|
||||
let &ClearDepthStencilImageInfo {
|
||||
ref image,
|
||||
|
@ -124,7 +124,8 @@ pub enum CopyError {
|
||||
max: DeviceSize,
|
||||
},
|
||||
|
||||
/// Depth/stencil images are not supported by the queue family of this command buffer; a graphics queue family is required.
|
||||
/// Depth/stencil images are not supported by the queue family of this command buffer; a
|
||||
/// graphics queue family is required.
|
||||
DepthStencilNotSupportedByQueueFamily,
|
||||
|
||||
/// The image extent of a region is not a multiple of the required image alignment.
|
||||
@ -275,7 +276,6 @@ pub enum CopyError {
|
||||
}
|
||||
|
||||
impl Error for CopyError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::SyncCommandBufferBuilderError(err) => Some(err),
|
||||
@ -285,11 +285,9 @@ impl Error for CopyError {
|
||||
}
|
||||
|
||||
impl Display for CopyError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -298,21 +296,20 @@ impl Display for CopyError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::ForbiddenInsideRenderPass => {
|
||||
write!(f, "operation forbidden inside of a render pass")
|
||||
}
|
||||
Self::NotSupportedByQueueFamily => {
|
||||
write!(f, "the queue family doesn't allow this operation")
|
||||
}
|
||||
|
||||
Self::ArrayLayerCountMismatch {
|
||||
region_index,
|
||||
src_layer_count,
|
||||
dst_layer_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the array layer counts of the source and destination subresource ranges of region {} do not match (source: {}; destination: {})",
|
||||
"the array layer counts of the source and destination subresource ranges of region \
|
||||
{} do not match (source: {}; destination: {})",
|
||||
region_index, src_layer_count, dst_layer_count,
|
||||
),
|
||||
Self::ArrayLayersOutOfRange {
|
||||
@ -322,7 +319,8 @@ impl Display for CopyError {
|
||||
image_array_layers,
|
||||
} => write!(
|
||||
f,
|
||||
"the end of the range of accessed array layers ({}) of the {} subresource range of region {} is greater than the number of array layers in the {} image ({})",
|
||||
"the end of the range of accessed array layers ({}) of the {} subresource range of \
|
||||
region {} is greater than the number of array layers in the {} image ({})",
|
||||
array_layers_range_end, resource, region_index, resource, image_array_layers,
|
||||
),
|
||||
Self::AspectsMismatch {
|
||||
@ -331,7 +329,8 @@ impl Display for CopyError {
|
||||
dst_aspects,
|
||||
} => write!(
|
||||
f,
|
||||
"the aspects of the source and destination subresource ranges of region {} do not match (source: {:?}; destination: {:?})",
|
||||
"the aspects of the source and destination subresource ranges of region {} do not \
|
||||
match (source: {:?}; destination: {:?})",
|
||||
region_index, src_aspects, dst_aspects,
|
||||
),
|
||||
Self::AspectsNotAllowed {
|
||||
@ -341,7 +340,8 @@ impl Display for CopyError {
|
||||
allowed_aspects,
|
||||
} => write!(
|
||||
f,
|
||||
"the aspects ({:?}) of the {} subresource range of region {} contain aspects that are not present in the {} image, or that are not allowed ({:?})",
|
||||
"the aspects ({:?}) of the {} subresource range of region {} contain aspects that \
|
||||
are not present in the {} image, or that are not allowed ({:?})",
|
||||
aspects, resource, region_index, resource, allowed_aspects,
|
||||
),
|
||||
Self::BufferImageHeightNotAligned {
|
||||
@ -351,7 +351,8 @@ impl Display for CopyError {
|
||||
required_alignment,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} buffer image height ({}) of region {} is not a multiple of the required {} buffer alignment ({})",
|
||||
"the {} buffer image height ({}) of region {} is not a multiple of the required {} \
|
||||
buffer alignment ({})",
|
||||
resource, image_height, region_index, resource, required_alignment,
|
||||
),
|
||||
Self::BufferRowLengthTooLarge {
|
||||
@ -360,7 +361,8 @@ impl Display for CopyError {
|
||||
buffer_row_length,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} buffer row length ({}) of region {} specifies a row of texels that is greater than 0x7FFFFFFF bytes in size",
|
||||
"the {} buffer row length ({}) of region {} specifies a row of texels that is \
|
||||
greater than 0x7FFFFFFF bytes in size",
|
||||
resource, buffer_row_length, region_index,
|
||||
),
|
||||
Self::BufferImageHeightTooSmall {
|
||||
@ -370,7 +372,8 @@ impl Display for CopyError {
|
||||
min,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} buffer image height ({}) of region {} is smaller than the {} image extent height ({})",
|
||||
"the {} buffer image height ({}) of region {} is smaller than the {} image extent \
|
||||
height ({})",
|
||||
resource, image_height, region_index, resource, min,
|
||||
),
|
||||
Self::BufferRowLengthNotAligned {
|
||||
@ -380,7 +383,8 @@ impl Display for CopyError {
|
||||
required_alignment,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} buffer row length ({}) of region {} is not a multiple of the required {} buffer alignment ({})",
|
||||
"the {} buffer row length ({}) of region {} is not a multiple of the required {} \
|
||||
buffer alignment ({})",
|
||||
resource, row_length, region_index, resource, required_alignment,
|
||||
),
|
||||
Self::BufferRowLengthTooSmall {
|
||||
@ -390,20 +394,19 @@ impl Display for CopyError {
|
||||
min,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} buffer row length length ({}) of region {} is smaller than the {} image extent width ({})",
|
||||
"the {} buffer row length length ({}) of region {} is smaller than the {} image \
|
||||
extent width ({})",
|
||||
resource, row_length, region_index, resource, min,
|
||||
),
|
||||
Self::DataTooLarge {
|
||||
size,
|
||||
max,
|
||||
} => write!(
|
||||
Self::DataTooLarge { size, max } => write!(
|
||||
f,
|
||||
"the provided data has a size ({}) greater than the maximum allowed ({})",
|
||||
size, max,
|
||||
),
|
||||
Self::DepthStencilNotSupportedByQueueFamily => write!(
|
||||
f,
|
||||
"depth/stencil images are not supported by the queue family of this command buffer; a graphics queue family is required",
|
||||
"depth/stencil images are not supported by the queue family of this command \
|
||||
buffer; a graphics queue family is required",
|
||||
),
|
||||
Self::ExtentNotAlignedForImage {
|
||||
resource,
|
||||
@ -412,21 +415,19 @@ impl Display for CopyError {
|
||||
required_alignment,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} image extent ({:?}) of region {} is not a multiple of the required {} image alignment ({:?})",
|
||||
"the {} image extent ({:?}) of region {} is not a multiple of the required {} \
|
||||
image alignment ({:?})",
|
||||
resource, extent, region_index, resource, required_alignment,
|
||||
),
|
||||
Self::FilterNotSupportedForImageType => write!(
|
||||
f,
|
||||
"the chosen filter is not supported for the source image type"
|
||||
"the chosen filter is not supported for the source image type",
|
||||
),
|
||||
Self::FilterNotSupportedByFormat => write!(
|
||||
f,
|
||||
"the chosen filter is not supported by the format of the source image"
|
||||
"the chosen filter is not supported by the format of the source image",
|
||||
),
|
||||
Self::FormatNotSupported {
|
||||
resource,
|
||||
format,
|
||||
} => write!(
|
||||
Self::FormatNotSupported { resource, format } => write!(
|
||||
f,
|
||||
"the format of the {} image ({:?}) is not supported for this operation",
|
||||
resource, format,
|
||||
@ -436,7 +437,8 @@ impl Display for CopyError {
|
||||
dst_format,
|
||||
} => write!(
|
||||
f,
|
||||
"the format of the source image ({:?}) does not match the format of the destination image ({:?})",
|
||||
"the format of the source image ({:?}) does not match the format of the \
|
||||
destination image ({:?})",
|
||||
src_format, dst_format,
|
||||
),
|
||||
Self::FormatsNotCompatible {
|
||||
@ -444,7 +446,8 @@ impl Display for CopyError {
|
||||
dst_format,
|
||||
} => write!(
|
||||
f,
|
||||
"the format of the source image subresource ({:?}) is not compatible with the format of the destination image subresource ({:?})",
|
||||
"the format of the source image subresource ({:?}) is not compatible with the \
|
||||
format of the destination image subresource ({:?})",
|
||||
src_format, dst_format,
|
||||
),
|
||||
Self::ImageLayoutInvalid {
|
||||
@ -462,7 +465,8 @@ impl Display for CopyError {
|
||||
image_mip_levels,
|
||||
} => write!(
|
||||
f,
|
||||
"the end of the range of accessed mip levels ({}) of the {} subresource range of region {} is not less than the number of mip levels in the {} image ({})",
|
||||
"the end of the range of accessed mip levels ({}) of the {} subresource range of \
|
||||
region {} is not less than the number of mip levels in the {} image ({})",
|
||||
mip_levels_range_end, resource, region_index, resource, image_mip_levels,
|
||||
),
|
||||
Self::MissingFormatFeature {
|
||||
@ -484,7 +488,8 @@ impl Display for CopyError {
|
||||
aspects,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} subresource range of region {} specifies multiple aspects ({:?}), but only one aspect can be selected for the {} image",
|
||||
"the {} subresource range of region {} specifies multiple aspects ({:?}), but only \
|
||||
one aspect can be selected for the {} image",
|
||||
resource, region_index, aspects, resource,
|
||||
),
|
||||
Self::OffsetNotAlignedForBuffer {
|
||||
@ -494,7 +499,8 @@ impl Display for CopyError {
|
||||
required_alignment,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} buffer offset ({}) of region {} is not a multiple of the required {} buffer alignment ({})",
|
||||
"the {} buffer offset ({}) of region {} is not a multiple of the required {} \
|
||||
buffer alignment ({})",
|
||||
resource, offset, region_index, resource, required_alignment,
|
||||
),
|
||||
Self::OffsetNotAlignedForImage {
|
||||
@ -504,7 +510,8 @@ impl Display for CopyError {
|
||||
required_alignment,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} image offset ({:?}) of region {} is not a multiple of the required {} image alignment ({:?})",
|
||||
"the {} image offset ({:?}) of region {} is not a multiple of the required {} \
|
||||
image alignment ({:?})",
|
||||
resource, offset, region_index, resource, required_alignment,
|
||||
),
|
||||
Self::OffsetsInvalidForImageType {
|
||||
@ -513,7 +520,8 @@ impl Display for CopyError {
|
||||
offsets,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} image offsets ({:?}) of region {} are not the values required for that axis ([0, 1]) for the type of the {} image",
|
||||
"the {} image offsets ({:?}) of region {} are not the values required for that \
|
||||
axis ([0, 1]) for the type of the {} image",
|
||||
resource, offsets, region_index, resource,
|
||||
),
|
||||
Self::OverlappingRegions {
|
||||
@ -531,7 +539,9 @@ impl Display for CopyError {
|
||||
dst_image_layout,
|
||||
} => write!(
|
||||
f,
|
||||
"the source subresources of region {} overlap with the destination subresources of region {}, but the source image layout ({:?}) does not equal the destination image layout ({:?})",
|
||||
"the source subresources of region {} overlap with the destination subresources of \
|
||||
region {}, but the source image layout ({:?}) does not equal the destination image \
|
||||
layout ({:?})",
|
||||
src_region_index, dst_region_index, src_image_layout, dst_image_layout,
|
||||
),
|
||||
Self::RegionOutOfBufferBounds {
|
||||
@ -541,7 +551,8 @@ impl Display for CopyError {
|
||||
buffer_size,
|
||||
} => write!(
|
||||
f,
|
||||
"the end of the range of accessed {} byte offsets ({}) of region {} is greater than the size of the {} buffer ({})",
|
||||
"the end of the range of accessed {} byte offsets ({}) of region {} is greater \
|
||||
than the size of the {} buffer ({})",
|
||||
resource, offset_range_end, region_index, resource, buffer_size,
|
||||
),
|
||||
Self::RegionOutOfImageBounds {
|
||||
@ -551,7 +562,8 @@ impl Display for CopyError {
|
||||
subresource_extent,
|
||||
} => write!(
|
||||
f,
|
||||
"the end of the range of accessed {} texel offsets ({:?}) of region {} is greater than the extent of the selected subresource of the {} image ({:?})",
|
||||
"the end of the range of accessed {} texel offsets ({:?}) of region {} is greater \
|
||||
than the extent of the selected subresource of the {} image ({:?})",
|
||||
resource, offset_range_end, region_index, resource, subresource_extent,
|
||||
),
|
||||
Self::SampleCountInvalid {
|
||||
@ -560,7 +572,8 @@ impl Display for CopyError {
|
||||
allowed_sample_counts,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} image has a sample count ({:?}) that is not valid for this operation ({:?})",
|
||||
"the {} image has a sample count ({:?}) that is not valid for this operation \
|
||||
({:?})",
|
||||
resource, sample_count, allowed_sample_counts,
|
||||
),
|
||||
Self::SampleCountMismatch {
|
||||
@ -568,7 +581,8 @@ impl Display for CopyError {
|
||||
dst_sample_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the source image has a different sample count ({:?}) than the destination image ({:?})",
|
||||
"the source image has a different sample count ({:?}) than the destination image \
|
||||
({:?})",
|
||||
src_sample_count, dst_sample_count,
|
||||
),
|
||||
Self::SizeNotAlignedForBuffer {
|
||||
@ -578,7 +592,8 @@ impl Display for CopyError {
|
||||
required_alignment,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} buffer size ({}) of region {} is not a multiple of the required {} buffer alignment ({})",
|
||||
"the {} buffer size ({}) of region {} is not a multiple of the required {} buffer \
|
||||
alignment ({})",
|
||||
resource, size, region_index, resource, required_alignment,
|
||||
),
|
||||
}
|
||||
@ -586,14 +601,12 @@ impl Display for CopyError {
|
||||
}
|
||||
|
||||
impl From<SyncCommandBufferBuilderError> for CopyError {
|
||||
#[inline]
|
||||
fn from(err: SyncCommandBufferBuilderError) -> Self {
|
||||
Self::SyncCommandBufferBuilderError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for CopyError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
@ -610,7 +623,6 @@ pub enum CopyErrorResource {
|
||||
}
|
||||
|
||||
impl Display for CopyErrorResource {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::Source => write!(f, "source"),
|
||||
|
@ -55,7 +55,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// A compute pipeline must have been bound using
|
||||
/// [`bind_pipeline_compute`](Self::bind_pipeline_compute). Any resources used by the compute
|
||||
/// pipeline, such as descriptor sets, must have been set beforehand.
|
||||
#[inline]
|
||||
pub fn dispatch(
|
||||
&mut self,
|
||||
group_counts: [u32; 3],
|
||||
@ -116,7 +115,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// A compute pipeline must have been bound using
|
||||
/// [`bind_pipeline_compute`](Self::bind_pipeline_compute). Any resources used by the compute
|
||||
/// pipeline, such as descriptor sets, must have been set beforehand.
|
||||
#[inline]
|
||||
pub fn dispatch_indirect<Inb>(
|
||||
&mut self,
|
||||
indirect_buffer: Arc<Inb>,
|
||||
@ -173,7 +171,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// pipeline, such as descriptor sets, vertex buffers and dynamic state, must have been set
|
||||
/// beforehand. If the bound graphics pipeline uses vertex buffers, then the provided vertex and
|
||||
/// instance ranges must be in range of the bound vertex buffers.
|
||||
#[inline]
|
||||
pub fn draw(
|
||||
&mut self,
|
||||
vertex_count: u32,
|
||||
@ -244,7 +241,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// beforehand. If the bound graphics pipeline uses vertex buffers, then the vertex and instance
|
||||
/// ranges of each `DrawIndirectCommand` in the indirect buffer must be in range of the bound
|
||||
/// vertex buffers.
|
||||
#[inline]
|
||||
pub fn draw_indirect<Inb>(
|
||||
&mut self,
|
||||
indirect_buffer: Arc<Inb>,
|
||||
@ -342,7 +338,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// beforehand. If the bound graphics pipeline uses vertex buffers, then the provided instance
|
||||
/// range must be in range of the bound vertex buffers. The vertex indices in the index buffer
|
||||
/// must be in range of the bound vertex buffers.
|
||||
#[inline]
|
||||
pub fn draw_indexed(
|
||||
&mut self,
|
||||
index_count: u32,
|
||||
@ -435,7 +430,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// beforehand. If the bound graphics pipeline uses vertex buffers, then the instance ranges of
|
||||
/// each `DrawIndexedIndirectCommand` in the indirect buffer must be in range of the bound
|
||||
/// vertex buffers.
|
||||
#[inline]
|
||||
pub fn draw_indexed_indirect<Inb>(
|
||||
&mut self,
|
||||
indirect_buffer: Arc<Inb>,
|
||||
@ -2345,7 +2339,8 @@ pub enum PipelineExecutionError {
|
||||
/// An indexed draw command was recorded, but no index buffer was bound.
|
||||
IndexBufferNotBound,
|
||||
|
||||
/// The highest index to be drawn exceeds the available number of indices in the bound index buffer.
|
||||
/// The highest index to be drawn exceeds the available number of indices in the bound index
|
||||
/// buffer.
|
||||
IndexBufferRangeOutOfBounds {
|
||||
highest_index: u32,
|
||||
max_index_count: u32,
|
||||
@ -2459,7 +2454,6 @@ pub enum PipelineExecutionError {
|
||||
}
|
||||
|
||||
impl Error for PipelineExecutionError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::SyncCommandBufferBuilderError(err) => Some(err),
|
||||
@ -2470,11 +2464,9 @@ impl Error for PipelineExecutionError {
|
||||
}
|
||||
|
||||
impl Display for PipelineExecutionError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -2483,17 +2475,21 @@ impl Display for PipelineExecutionError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::DescriptorResourceInvalid { set_num, binding_num, index, .. } => write!(
|
||||
f,
|
||||
"the resource bound to descriptor set {} binding {} at index {} is not compatible with the requirements of the pipeline and shaders",
|
||||
set_num, binding_num, index,
|
||||
),
|
||||
Self::DescriptorSetNotBound {
|
||||
Self::DescriptorResourceInvalid {
|
||||
set_num,
|
||||
binding_num,
|
||||
index,
|
||||
..
|
||||
} => write!(
|
||||
f,
|
||||
"the pipeline layout requires a descriptor set bound to set number {}, but none was bound",
|
||||
"the resource bound to descriptor set {} binding {} at index {} is not compatible \
|
||||
with the requirements of the pipeline and shaders",
|
||||
set_num, binding_num, index,
|
||||
),
|
||||
Self::DescriptorSetNotBound { set_num } => write!(
|
||||
f,
|
||||
"the pipeline layout requires a descriptor set bound to set number {}, but none \
|
||||
was bound",
|
||||
set_num,
|
||||
),
|
||||
Self::DynamicColorWriteEnableNotEnoughValues {
|
||||
@ -2501,23 +2497,24 @@ impl Display for PipelineExecutionError {
|
||||
attachment_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the bound pipeline uses a dynamic color write enable setting, but the number of provided enable values ({}) is less than the number of attachments in the current render subpass ({})",
|
||||
color_write_enable_count,
|
||||
attachment_count,
|
||||
"the bound pipeline uses a dynamic color write enable setting, but the number of \
|
||||
provided enable values ({}) is less than the number of attachments in the current \
|
||||
render subpass ({})",
|
||||
color_write_enable_count, attachment_count,
|
||||
),
|
||||
Self::DynamicPrimitiveTopologyClassMismatch {
|
||||
provided_class,
|
||||
required_class,
|
||||
} => write!(
|
||||
f,
|
||||
"The bound pipeline uses a dynamic primitive topology, but the provided topology is of a different topology class ({:?}) than what the pipeline requires ({:?})",
|
||||
"The bound pipeline uses a dynamic primitive topology, but the provided topology \
|
||||
is of a different topology class ({:?}) than what the pipeline requires ({:?})",
|
||||
provided_class, required_class,
|
||||
),
|
||||
Self::DynamicPrimitiveTopologyInvalid {
|
||||
topology,
|
||||
} => write!(
|
||||
Self::DynamicPrimitiveTopologyInvalid { topology } => write!(
|
||||
f,
|
||||
"the bound pipeline uses a dynamic primitive topology, but the provided topology ({:?}) is not compatible with the shader stages in the pipeline",
|
||||
"the bound pipeline uses a dynamic primitive topology, but the provided topology \
|
||||
({:?}) is not compatible with the shader stages in the pipeline",
|
||||
topology,
|
||||
),
|
||||
Self::DynamicStateNotSet { dynamic_state } => write!(
|
||||
@ -2530,18 +2527,16 @@ impl Display for PipelineExecutionError {
|
||||
scissor_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the bound pipeline uses a dynamic scissor and/or viewport count, but the scissor count ({}) does not match the viewport count ({})",
|
||||
scissor_count,
|
||||
viewport_count,
|
||||
),
|
||||
Self::ForbiddenInsideRenderPass => write!(
|
||||
f,
|
||||
"operation forbidden inside a render pass",
|
||||
),
|
||||
Self::ForbiddenOutsideRenderPass => write!(
|
||||
f,
|
||||
"operation forbidden outside a render pass",
|
||||
"the bound pipeline uses a dynamic scissor and/or viewport count, but the scissor \
|
||||
count ({}) does not match the viewport count ({})",
|
||||
scissor_count, viewport_count,
|
||||
),
|
||||
Self::ForbiddenInsideRenderPass => {
|
||||
write!(f, "operation forbidden inside a render pass")
|
||||
}
|
||||
Self::ForbiddenOutsideRenderPass => {
|
||||
write!(f, "operation forbidden outside a render pass")
|
||||
}
|
||||
Self::ForbiddenWithSubpassContents { subpass_contents } => write!(
|
||||
f,
|
||||
"operation forbidden inside a render subpass with contents {:?}",
|
||||
@ -2556,9 +2551,9 @@ impl Display for PipelineExecutionError {
|
||||
max_index_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the highest index to be drawn ({}) exceeds the available number of indices in the bound index buffer ({})",
|
||||
highest_index,
|
||||
max_index_count,
|
||||
"the highest index to be drawn ({}) exceeds the available number of indices in the \
|
||||
bound index buffer ({})",
|
||||
highest_index, max_index_count,
|
||||
),
|
||||
Self::IndirectBufferMissingUsage => write!(
|
||||
f,
|
||||
@ -2568,24 +2563,23 @@ impl Display for PipelineExecutionError {
|
||||
f,
|
||||
"the `max_compute_work_group_count` limit has been exceeded",
|
||||
),
|
||||
Self::MaxDrawIndirectCountExceeded { .. } => write!(
|
||||
f,
|
||||
"the `max_draw_indirect_count` limit has been exceeded",
|
||||
),
|
||||
Self::MaxDrawIndirectCountExceeded { .. } => {
|
||||
write!(f, "the `max_draw_indirect_count` limit has been exceeded")
|
||||
}
|
||||
Self::MaxMultiviewInstanceIndexExceeded { .. } => write!(
|
||||
f,
|
||||
"the `max_multiview_instance_index` limit has been exceeded",
|
||||
),
|
||||
Self::NotSupportedByQueueFamily => write!(
|
||||
f,
|
||||
"the queue family doesn't allow this operation",
|
||||
),
|
||||
Self::NotSupportedByQueueFamily => {
|
||||
write!(f, "the queue family doesn't allow this operation")
|
||||
}
|
||||
Self::PipelineColorAttachmentCountMismatch {
|
||||
pipeline_count,
|
||||
required_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the color attachment count in the bound pipeline ({}) does not match the count of the current render pass ({})",
|
||||
"the color attachment count in the bound pipeline ({}) does not match the count of \
|
||||
the current render pass ({})",
|
||||
pipeline_count, required_count,
|
||||
),
|
||||
Self::PipelineColorAttachmentFormatMismatch {
|
||||
@ -2594,7 +2588,8 @@ impl Display for PipelineExecutionError {
|
||||
required_format,
|
||||
} => write!(
|
||||
f,
|
||||
"the format of color attachment {} in the bound pipeline ({:?}) does not match the format of the corresponding color attachment in the current render pass ({:?})",
|
||||
"the format of color attachment {} in the bound pipeline ({:?}) does not match the \
|
||||
format of the corresponding color attachment in the current render pass ({:?})",
|
||||
color_attachment_index, pipeline_format, required_format,
|
||||
),
|
||||
Self::PipelineDepthAttachmentFormatMismatch {
|
||||
@ -2602,12 +2597,14 @@ impl Display for PipelineExecutionError {
|
||||
required_format,
|
||||
} => write!(
|
||||
f,
|
||||
"the format of the depth attachment in the bound pipeline ({:?}) does not match the format of the depth attachment in the current render pass ({:?})",
|
||||
"the format of the depth attachment in the bound pipeline ({:?}) does not match \
|
||||
the format of the depth attachment in the current render pass ({:?})",
|
||||
pipeline_format, required_format,
|
||||
),
|
||||
Self::PipelineLayoutNotCompatible => write!(
|
||||
f,
|
||||
"the bound pipeline is not compatible with the layout used to bind the descriptor sets",
|
||||
"the bound pipeline is not compatible with the layout used to bind the descriptor \
|
||||
sets",
|
||||
),
|
||||
Self::PipelineNotBound => write!(
|
||||
f,
|
||||
@ -2615,27 +2612,27 @@ impl Display for PipelineExecutionError {
|
||||
),
|
||||
Self::PipelineRenderPassNotCompatible => write!(
|
||||
f,
|
||||
"the bound graphics pipeline uses a render pass that is not compatible with the currently active render pass",
|
||||
"the bound graphics pipeline uses a render pass that is not compatible with the \
|
||||
currently active render pass",
|
||||
),
|
||||
Self::PipelineRenderPassTypeMismatch => write!(
|
||||
f,
|
||||
"the bound graphics pipeline uses a render pass of a different type than the currently active render pass",
|
||||
"the bound graphics pipeline uses a render pass of a different type than the \
|
||||
currently active render pass",
|
||||
),
|
||||
Self::PipelineSubpassMismatch {
|
||||
pipeline,
|
||||
current,
|
||||
} => write!(
|
||||
Self::PipelineSubpassMismatch { pipeline, current } => write!(
|
||||
f,
|
||||
"the bound graphics pipeline uses a render subpass index ({}) that doesn't match the currently active subpass index ({})",
|
||||
pipeline,
|
||||
current,
|
||||
"the bound graphics pipeline uses a render subpass index ({}) that doesn't match \
|
||||
the currently active subpass index ({})",
|
||||
pipeline, current,
|
||||
),
|
||||
Self::PipelineStencilAttachmentFormatMismatch {
|
||||
pipeline_format,
|
||||
required_format,
|
||||
} => write!(
|
||||
f,
|
||||
"the format of the stencil attachment in the bound pipeline ({:?}) does not match the format of the stencil attachment in the current render pass ({:?})",
|
||||
"the format of the stencil attachment in the bound pipeline ({:?}) does not match \
|
||||
the format of the stencil attachment in the current render pass ({:?})",
|
||||
pipeline_format, required_format,
|
||||
),
|
||||
Self::PipelineViewMaskMismatch {
|
||||
@ -2643,7 +2640,8 @@ impl Display for PipelineExecutionError {
|
||||
required_view_mask,
|
||||
} => write!(
|
||||
f,
|
||||
"the view mask of the bound pipeline ({}) does not match the view mask of the current render pass ({})",
|
||||
"the view mask of the bound pipeline ({}) does not match the view mask of the \
|
||||
current render pass ({})",
|
||||
pipeline_view_mask, required_view_mask,
|
||||
),
|
||||
Self::PushConstantsNotCompatible => write!(
|
||||
@ -2654,11 +2652,10 @@ impl Display for PipelineExecutionError {
|
||||
f,
|
||||
"not all push constants used by the pipeline have been set",
|
||||
),
|
||||
Self::VertexBufferNotBound {
|
||||
binding_num,
|
||||
} => write!(
|
||||
Self::VertexBufferNotBound { binding_num } => write!(
|
||||
f,
|
||||
"the bound graphics pipeline requires a vertex buffer bound to binding number {}, but none was bound",
|
||||
"the bound graphics pipeline requires a vertex buffer bound to binding number {}, \
|
||||
but none was bound",
|
||||
binding_num,
|
||||
),
|
||||
Self::VertexBufferInstanceRangeOutOfBounds {
|
||||
@ -2666,7 +2663,8 @@ impl Display for PipelineExecutionError {
|
||||
instances_in_buffers,
|
||||
} => write!(
|
||||
f,
|
||||
"the number of instances to be drawn ({}) exceeds the available number of instances in the bound vertex buffers ({}) used by the pipeline",
|
||||
"the number of instances to be drawn ({}) exceeds the available number of \
|
||||
instances in the bound vertex buffers ({}) used by the pipeline",
|
||||
instances_needed, instances_in_buffers,
|
||||
),
|
||||
Self::VertexBufferVertexRangeOutOfBounds {
|
||||
@ -2674,7 +2672,8 @@ impl Display for PipelineExecutionError {
|
||||
vertices_in_buffers,
|
||||
} => write!(
|
||||
f,
|
||||
"the number of vertices to be drawn ({}) exceeds the available number of vertices in the bound vertex buffers ({}) used by the pipeline",
|
||||
"the number of vertices to be drawn ({}) exceeds the available number of vertices \
|
||||
in the bound vertex buffers ({}) used by the pipeline",
|
||||
vertices_needed, vertices_in_buffers,
|
||||
),
|
||||
}
|
||||
@ -2682,7 +2681,6 @@ impl Display for PipelineExecutionError {
|
||||
}
|
||||
|
||||
impl From<SyncCommandBufferBuilderError> for PipelineExecutionError {
|
||||
#[inline]
|
||||
fn from(err: SyncCommandBufferBuilderError) -> Self {
|
||||
Self::SyncCommandBufferBuilderError(err)
|
||||
}
|
||||
@ -2734,40 +2732,41 @@ impl Error for DescriptorResourceInvalidError {
|
||||
}
|
||||
|
||||
impl Display for DescriptorResourceInvalidError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::ImageViewFormatMismatch { provided, required } => write!(
|
||||
f,
|
||||
"the format of the bound image view ({:?}) does not match what the pipeline requires ({:?})",
|
||||
provided, required
|
||||
"the format of the bound image view ({:?}) does not match what the pipeline \
|
||||
requires ({:?})",
|
||||
provided, required,
|
||||
),
|
||||
Self::ImageViewMultisampledMismatch { provided, required } => write!(
|
||||
f,
|
||||
"the multisampling of the bound image ({}) does not match what the pipeline requires ({})",
|
||||
"the multisampling of the bound image ({}) does not match what the pipeline \
|
||||
requires ({})",
|
||||
provided, required,
|
||||
),
|
||||
Self::ImageViewScalarTypeMismatch { provided, required } => write!(
|
||||
f,
|
||||
"the scalar type of the format and aspect of the bound image view ({:?}) does not match what the pipeline requires ({:?})",
|
||||
"the scalar type of the format and aspect of the bound image view ({:?}) does not \
|
||||
match what the pipeline requires ({:?})",
|
||||
provided, required,
|
||||
),
|
||||
Self::ImageViewTypeMismatch { provided, required } => write!(
|
||||
f,
|
||||
"the image view type of the bound image view ({:?}) does not match what the pipeline requires ({:?})",
|
||||
"the image view type of the bound image view ({:?}) does not match what the \
|
||||
pipeline requires ({:?})",
|
||||
provided, required,
|
||||
),
|
||||
Self::Missing => write!(
|
||||
f,
|
||||
"no resource was bound",
|
||||
),
|
||||
Self::Missing => write!(f, "no resource was bound"),
|
||||
Self::SamplerImageViewIncompatible { .. } => write!(
|
||||
f,
|
||||
"the bound sampler samples an image view that is not compatible with that sampler",
|
||||
),
|
||||
Self::SamplerCompareMismatch { provided, required } => write!(
|
||||
f,
|
||||
"the depth comparison state of the bound sampler ({}) does not match what the pipeline requires ({})",
|
||||
"the depth comparison state of the bound sampler ({}) does not match what the \
|
||||
pipeline requires ({})",
|
||||
provided, required,
|
||||
),
|
||||
Self::SamplerUnnormalizedCoordinatesNotAllowed => write!(
|
||||
@ -2784,11 +2783,13 @@ impl Display for DescriptorResourceInvalidError {
|
||||
),
|
||||
Self::StorageReadWithoutFormatNotSupported => write!(
|
||||
f,
|
||||
"the bound image view or buffer view does not support the `storage_read_without_format` format feature",
|
||||
"the bound image view or buffer view does not support the \
|
||||
`storage_read_without_format` format feature",
|
||||
),
|
||||
Self::StorageWriteWithoutFormatNotSupported => write!(
|
||||
f,
|
||||
"the bound image view or buffer view does not support the `storage_write_without_format` format feature",
|
||||
"the bound image view or buffer view does not support the \
|
||||
`storage_write_without_format` format feature",
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,9 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// The query will be active until [`end_query`](Self::end_query) is called for the same query.
|
||||
///
|
||||
/// # Safety
|
||||
/// The query must be unavailable, ensured by calling [`reset_query_pool`](Self::reset_query_pool).
|
||||
///
|
||||
/// The query must be unavailable, ensured by calling
|
||||
/// [`reset_query_pool`](Self::reset_query_pool).
|
||||
pub unsafe fn begin_query(
|
||||
&mut self,
|
||||
query_pool: Arc<QueryPool>,
|
||||
@ -211,7 +213,9 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// Writes a timestamp to a timestamp query.
|
||||
///
|
||||
/// # Safety
|
||||
/// The query must be unavailable, ensured by calling [`reset_query_pool`](Self::reset_query_pool).
|
||||
///
|
||||
/// The query must be unavailable, ensured by calling
|
||||
/// [`reset_query_pool`](Self::reset_query_pool).
|
||||
pub unsafe fn write_timestamp(
|
||||
&mut self,
|
||||
query_pool: Arc<QueryPool>,
|
||||
@ -704,7 +708,6 @@ impl UnsafeCommandBufferBuilder {
|
||||
}
|
||||
|
||||
/// Calls `vkCmdCopyQueryPoolResults` on the builder.
|
||||
#[inline]
|
||||
pub unsafe fn copy_query_pool_results<D, T>(
|
||||
&mut self,
|
||||
queries: QueriesRange<'_>,
|
||||
@ -805,14 +808,9 @@ pub enum QueryError {
|
||||
impl Error for QueryError {}
|
||||
|
||||
impl Display for QueryError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
Self::SyncCommandBufferBuilderError(_) => write!(
|
||||
f,
|
||||
"a SyncCommandBufferBuilderError",
|
||||
),
|
||||
|
||||
match self {
|
||||
Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"),
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -821,7 +819,6 @@ impl Display for QueryError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::BufferTooSmall { .. } => {
|
||||
write!(f, "the buffer is too small for the copy operation")
|
||||
}
|
||||
@ -846,7 +843,8 @@ impl Display for QueryError {
|
||||
Self::OutOfRange => write!(f, "the provided query index is not valid for this pool"),
|
||||
Self::OutOfRangeMultiview => write!(
|
||||
f,
|
||||
"the provided query index plus the number of views in the current render subpass is greater than the number of queries in the pool",
|
||||
"the provided query index plus the number of views in the current render subpass \
|
||||
is greater than the number of queries in the pool",
|
||||
),
|
||||
Self::QueryIsActive => write!(
|
||||
f,
|
||||
@ -861,14 +859,12 @@ impl Display for QueryError {
|
||||
}
|
||||
|
||||
impl From<SyncCommandBufferBuilderError> for QueryError {
|
||||
#[inline]
|
||||
fn from(err: SyncCommandBufferBuilderError) -> Self {
|
||||
Self::SyncCommandBufferBuilderError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for QueryError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -50,7 +50,6 @@ where
|
||||
///
|
||||
/// `contents` specifies what kinds of commands will be recorded in the render pass, either
|
||||
/// draw commands or executions of secondary command buffers.
|
||||
#[inline]
|
||||
pub fn begin_render_pass(
|
||||
&mut self,
|
||||
mut render_pass_begin_info: RenderPassBeginInfo,
|
||||
@ -59,14 +58,14 @@ where
|
||||
self.validate_begin_render_pass(&mut render_pass_begin_info, contents)?;
|
||||
|
||||
unsafe {
|
||||
let &RenderPassBeginInfo {
|
||||
let RenderPassBeginInfo {
|
||||
ref render_pass,
|
||||
ref framebuffer,
|
||||
render_area_offset,
|
||||
render_area_extent,
|
||||
clear_values: _,
|
||||
_ne: _,
|
||||
} = &render_pass_begin_info;
|
||||
} = render_pass_begin_info;
|
||||
|
||||
let subpass = render_pass.clone().first_subpass();
|
||||
let view_mask = subpass.subpass_desc().view_mask;
|
||||
@ -85,8 +84,8 @@ where
|
||||
|
||||
self.inner
|
||||
.begin_render_pass(render_pass_begin_info, contents)?;
|
||||
|
||||
self.render_pass_state = Some(render_pass_state);
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
@ -113,12 +112,12 @@ where
|
||||
return Err(RenderPassError::ForbiddenInsideRenderPass);
|
||||
}
|
||||
|
||||
let &mut RenderPassBeginInfo {
|
||||
ref render_pass,
|
||||
ref framebuffer,
|
||||
let RenderPassBeginInfo {
|
||||
render_pass,
|
||||
framebuffer,
|
||||
render_area_offset,
|
||||
render_area_extent,
|
||||
ref clear_values,
|
||||
clear_values,
|
||||
_ne: _,
|
||||
} = render_pass_begin_info;
|
||||
|
||||
@ -208,12 +207,12 @@ where
|
||||
}
|
||||
|
||||
for subpass_desc in render_pass.subpasses() {
|
||||
let &SubpassDescription {
|
||||
let SubpassDescription {
|
||||
view_mask: _,
|
||||
ref input_attachments,
|
||||
ref color_attachments,
|
||||
ref resolve_attachments,
|
||||
ref depth_stencil_attachment,
|
||||
input_attachments,
|
||||
color_attachments,
|
||||
resolve_attachments,
|
||||
depth_stencil_attachment,
|
||||
preserve_attachments: _,
|
||||
_ne: _,
|
||||
} = subpass_desc;
|
||||
@ -288,7 +287,7 @@ where
|
||||
}
|
||||
|
||||
// VUID-VkRenderPassBeginInfo-clearValueCount-04962
|
||||
for (attachment_index, (attachment_desc, &clear_value)) in render_pass
|
||||
for (attachment_index, (attachment_desc, &mut clear_value)) in render_pass
|
||||
.attachments()
|
||||
.iter()
|
||||
.zip(clear_values)
|
||||
@ -396,7 +395,6 @@ where
|
||||
}
|
||||
|
||||
/// Advances to the next subpass of the render pass previously begun with `begin_render_pass`.
|
||||
#[inline]
|
||||
pub fn next_subpass(
|
||||
&mut self,
|
||||
contents: SubpassContents,
|
||||
@ -472,7 +470,6 @@ where
|
||||
/// Ends the render pass previously begun with `begin_render_pass`.
|
||||
///
|
||||
/// This must be called after you went through all the subpasses.
|
||||
#[inline]
|
||||
pub fn end_render_pass(&mut self) -> Result<&mut Self, RenderPassError> {
|
||||
self.validate_end_render_pass()?;
|
||||
|
||||
@ -538,7 +535,7 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
mut rendering_info: RenderingInfo,
|
||||
) -> Result<&mut Self, RenderPassError> {
|
||||
{
|
||||
let &mut RenderingInfo {
|
||||
let RenderingInfo {
|
||||
render_area_offset,
|
||||
ref mut render_area_extent,
|
||||
ref mut layer_count,
|
||||
@ -548,7 +545,7 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
ref stencil_attachment,
|
||||
contents: _,
|
||||
_ne: _,
|
||||
} = &mut rendering_info;
|
||||
} = rendering_info;
|
||||
|
||||
let auto_extent = render_area_extent[0] == 0 || render_area_extent[1] == 0;
|
||||
let auto_layers = *layer_count == 0;
|
||||
@ -622,7 +619,7 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
self.validate_begin_rendering(&mut rendering_info)?;
|
||||
|
||||
unsafe {
|
||||
let &RenderingInfo {
|
||||
let RenderingInfo {
|
||||
render_area_offset,
|
||||
render_area_extent,
|
||||
layer_count: _,
|
||||
@ -632,7 +629,7 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
ref stencil_attachment,
|
||||
contents,
|
||||
_ne: _,
|
||||
} = &rendering_info;
|
||||
} = rendering_info;
|
||||
|
||||
let render_pass_state = RenderPassState {
|
||||
contents,
|
||||
@ -765,10 +762,10 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
})
|
||||
{
|
||||
let attachment_index = attachment_index as u32;
|
||||
let &RenderingAttachmentInfo {
|
||||
ref image_view,
|
||||
let RenderingAttachmentInfo {
|
||||
image_view,
|
||||
image_layout,
|
||||
ref resolve_info,
|
||||
resolve_info,
|
||||
load_op,
|
||||
store_op,
|
||||
clear_value: _,
|
||||
@ -920,10 +917,10 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
}
|
||||
|
||||
if let Some(attachment_info) = depth_attachment {
|
||||
let &RenderingAttachmentInfo {
|
||||
ref image_view,
|
||||
let RenderingAttachmentInfo {
|
||||
image_view,
|
||||
image_layout,
|
||||
ref resolve_info,
|
||||
resolve_info,
|
||||
load_op,
|
||||
store_op,
|
||||
clear_value: _,
|
||||
@ -1047,10 +1044,10 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
}
|
||||
|
||||
if let Some(attachment_info) = stencil_attachment {
|
||||
let &RenderingAttachmentInfo {
|
||||
ref image_view,
|
||||
let RenderingAttachmentInfo {
|
||||
image_view,
|
||||
image_layout,
|
||||
ref resolve_info,
|
||||
resolve_info,
|
||||
load_op,
|
||||
store_op,
|
||||
clear_value: _,
|
||||
@ -1537,9 +1534,9 @@ impl SyncCommandBufferBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
let &RenderPassBeginInfo {
|
||||
ref render_pass,
|
||||
ref framebuffer,
|
||||
let RenderPassBeginInfo {
|
||||
render_pass,
|
||||
framebuffer,
|
||||
render_area_offset: _,
|
||||
render_area_extent: _,
|
||||
clear_values: _,
|
||||
@ -1658,14 +1655,14 @@ impl SyncCommandBufferBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
let &RenderingInfo {
|
||||
let RenderingInfo {
|
||||
render_area_offset: _,
|
||||
render_area_extent: _,
|
||||
layer_count: _,
|
||||
view_mask: _,
|
||||
ref color_attachments,
|
||||
ref depth_attachment,
|
||||
ref stencil_attachment,
|
||||
color_attachments,
|
||||
depth_attachment,
|
||||
stencil_attachment,
|
||||
contents: _,
|
||||
_ne,
|
||||
} = &rendering_info;
|
||||
@ -2076,6 +2073,7 @@ impl UnsafeCommandBufferBuilder {
|
||||
}
|
||||
|
||||
/// Calls `vkCmdBeginRendering` on the builder.
|
||||
#[inline]
|
||||
pub unsafe fn begin_rendering(&mut self, rendering_info: &RenderingInfo) {
|
||||
let &RenderingInfo {
|
||||
render_area_offset,
|
||||
@ -2178,6 +2176,7 @@ impl UnsafeCommandBufferBuilder {
|
||||
}
|
||||
|
||||
/// Calls `vkCmdEndRendering` on the builder.
|
||||
#[inline]
|
||||
pub unsafe fn end_rendering(&mut self) {
|
||||
let fns = self.device.fns();
|
||||
|
||||
@ -2193,7 +2192,6 @@ impl UnsafeCommandBufferBuilder {
|
||||
///
|
||||
/// Does nothing if the list of attachments or the list of rects is empty, as it would be a
|
||||
/// no-op and isn't a valid usage of the command anyway.
|
||||
#[inline]
|
||||
pub unsafe fn clear_attachments(
|
||||
&mut self,
|
||||
attachments: impl IntoIterator<Item = ClearAttachment>,
|
||||
@ -2490,7 +2488,9 @@ impl RenderingAttachmentResolveInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear attachment type, used in [`clear_attachments`](crate::command_buffer::AutoCommandBufferBuilder::clear_attachments) command.
|
||||
/// Clear attachment type, used in [`clear_attachments`] command.
|
||||
///
|
||||
/// [`clear_attachments`]: crate::command_buffer::AutoCommandBufferBuilder::clear_attachments
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ClearAttachment {
|
||||
/// Clear the color attachment at the specified index, with the specified clear value.
|
||||
@ -2510,6 +2510,7 @@ pub enum ClearAttachment {
|
||||
}
|
||||
|
||||
impl From<ClearAttachment> for ash::vk::ClearAttachment {
|
||||
#[inline]
|
||||
fn from(v: ClearAttachment) -> Self {
|
||||
match v {
|
||||
ClearAttachment::Color {
|
||||
@ -2550,7 +2551,9 @@ impl From<ClearAttachment> for ash::vk::ClearAttachment {
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies the clear region for the [`clear_attachments`](crate::command_buffer::AutoCommandBufferBuilder::clear_attachments) command.
|
||||
/// Specifies the clear region for the [`clear_attachments`] command.
|
||||
///
|
||||
/// [`clear_attachments`]: crate::command_buffer::AutoCommandBufferBuilder::clear_attachments
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ClearRect {
|
||||
/// The rectangle offset.
|
||||
@ -2656,7 +2659,8 @@ pub enum RenderPassError {
|
||||
attachment_index: u32,
|
||||
},
|
||||
|
||||
/// The contents `SubpassContents::SecondaryCommandBuffers` is not allowed inside a secondary command buffer.
|
||||
/// The contents `SubpassContents::SecondaryCommandBuffers` is not allowed inside a secondary
|
||||
/// command buffer.
|
||||
ContentsForbiddenInSecondaryCommandBuffer,
|
||||
|
||||
/// The depth attachment has a format that does not support that usage.
|
||||
@ -2816,7 +2820,6 @@ pub enum RenderPassError {
|
||||
}
|
||||
|
||||
impl Error for RenderPassError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::SyncCommandBufferBuilderError(err) => Some(err),
|
||||
@ -2826,11 +2829,9 @@ impl Error for RenderPassError {
|
||||
}
|
||||
|
||||
impl Display for RenderPassError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -2839,32 +2840,35 @@ impl Display for RenderPassError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::AttachmentImageMissingUsage { attachment_index, usage } => write!(
|
||||
Self::AttachmentImageMissingUsage {
|
||||
attachment_index,
|
||||
usage,
|
||||
} => write!(
|
||||
f,
|
||||
"the framebuffer image attached to attachment index {} did not have the required usage {} enabled",
|
||||
"the framebuffer image attached to attachment index {} did not have the required \
|
||||
usage {} enabled",
|
||||
attachment_index, usage,
|
||||
),
|
||||
Self::AutoExtentAttachmentsEmpty => write!(
|
||||
f,
|
||||
"one of the elements of `render_pass_extent` is zero, but no attachment images were given to calculate the extent from",
|
||||
"one of the elements of `render_pass_extent` is zero, but no attachment images \
|
||||
were given to calculate the extent from",
|
||||
),
|
||||
Self::AutoLayersAttachmentsEmpty => write!(
|
||||
f,
|
||||
"`layer_count` is zero, but no attachment images were given to calculate the number of layers from",
|
||||
"`layer_count` is zero, but no attachment images were given to calculate the \
|
||||
number of layers from",
|
||||
),
|
||||
Self::ClearAttachmentNotCompatible {
|
||||
clear_attachment,
|
||||
attachment_format,
|
||||
} => write!(
|
||||
f,
|
||||
"a clear attachment value ({:?}) is not compatible with the attachment's format ({:?})",
|
||||
clear_attachment,
|
||||
attachment_format,
|
||||
"a clear attachment value ({:?}) is not compatible with the attachment's format \
|
||||
({:?})",
|
||||
clear_attachment, attachment_format,
|
||||
),
|
||||
Self::ClearValueMissing {
|
||||
attachment_index,
|
||||
} => write!(
|
||||
Self::ClearValueMissing { attachment_index } => write!(
|
||||
f,
|
||||
"a clear value for render pass attachment {} is missing",
|
||||
attachment_index,
|
||||
@ -2875,7 +2879,8 @@ impl Display for RenderPassError {
|
||||
attachment_format,
|
||||
} => write!(
|
||||
f,
|
||||
"a clear value ({:?}) provided for render pass attachment {} is not compatible with the attachment's format ({:?})",
|
||||
"a clear value ({:?}) provided for render pass attachment {} is not compatible \
|
||||
with the attachment's format ({:?})",
|
||||
clear_value, attachment_index, attachment_format,
|
||||
),
|
||||
Self::ColorAttachmentIndexOutOfRange {
|
||||
@ -2883,84 +2888,74 @@ impl Display for RenderPassError {
|
||||
num_color_attachments,
|
||||
} => write!(
|
||||
f,
|
||||
"an attachment clear value specifies a `color_attachment` index {} that is not less than the number of color attachments in the subpass ({})",
|
||||
"an attachment clear value specifies a `color_attachment` index {} that is not \
|
||||
less than the number of color attachments in the subpass ({})",
|
||||
color_attachment_index, num_color_attachments,
|
||||
),
|
||||
Self::ColorAttachmentLayoutInvalid {
|
||||
attachment_index,
|
||||
} => write!(
|
||||
Self::ColorAttachmentLayoutInvalid { attachment_index } => write!(
|
||||
f,
|
||||
"color attachment {} has a layout that is not supported",
|
||||
attachment_index,
|
||||
),
|
||||
Self::ColorAttachmentMissingUsage {
|
||||
attachment_index,
|
||||
} => write!(
|
||||
Self::ColorAttachmentMissingUsage { attachment_index } => write!(
|
||||
f,
|
||||
"color attachment {} is missing the `color_attachment` usage",
|
||||
attachment_index,
|
||||
),
|
||||
Self::ColorAttachmentResolveFormatMismatch {
|
||||
attachment_index,
|
||||
} => write!(
|
||||
Self::ColorAttachmentResolveFormatMismatch { attachment_index } => write!(
|
||||
f,
|
||||
"color attachment {} has a `format` value different from the corresponding color attachment",
|
||||
"color attachment {} has a `format` value different from the corresponding color \
|
||||
attachment",
|
||||
attachment_index,
|
||||
),
|
||||
Self::ColorAttachmentResolveLayoutInvalid {
|
||||
attachment_index,
|
||||
} => write!(
|
||||
Self::ColorAttachmentResolveLayoutInvalid { attachment_index } => write!(
|
||||
f,
|
||||
"color resolve attachment {} has a layout that is not supported",
|
||||
attachment_index,
|
||||
),
|
||||
Self::ColorAttachmentResolveModeNotSupported {
|
||||
attachment_index,
|
||||
} => write!(
|
||||
Self::ColorAttachmentResolveModeNotSupported { attachment_index } => write!(
|
||||
f,
|
||||
"color resolve attachment {} has a resolve mode that is not supported",
|
||||
attachment_index,
|
||||
),
|
||||
Self::ColorAttachmentResolveMultisampled {
|
||||
attachment_index,
|
||||
} => write!(
|
||||
Self::ColorAttachmentResolveMultisampled { attachment_index } => write!(
|
||||
f,
|
||||
"color resolve attachment {} has a `samples` value other than `SampleCount::Sample1`",
|
||||
"color resolve attachment {} has a `samples` value other than \
|
||||
`SampleCount::Sample1`",
|
||||
attachment_index,
|
||||
),
|
||||
Self::ColorAttachmentSamplesMismatch {
|
||||
attachment_index,
|
||||
} => write!(
|
||||
Self::ColorAttachmentSamplesMismatch { attachment_index } => write!(
|
||||
f,
|
||||
"color attachment {} has a `samples` value that is different from the first color attachment",
|
||||
"color attachment {} has a `samples` value that is different from the first color \
|
||||
attachment",
|
||||
attachment_index,
|
||||
),
|
||||
Self::ColorAttachmentWithResolveNotMultisampled {
|
||||
attachment_index,
|
||||
} => write!(
|
||||
Self::ColorAttachmentWithResolveNotMultisampled { attachment_index } => write!(
|
||||
f,
|
||||
"color attachment {} with a resolve attachment has a `samples` value of `SampleCount::Sample1`",
|
||||
"color attachment {} with a resolve attachment has a `samples` value of \
|
||||
`SampleCount::Sample1`",
|
||||
attachment_index,
|
||||
),
|
||||
Self::ContentsForbiddenInSecondaryCommandBuffer => write!(
|
||||
f,
|
||||
"the contents `SubpassContents::SecondaryCommandBuffers` is not allowed inside a secondary command buffer",
|
||||
"the contents `SubpassContents::SecondaryCommandBuffers` is not allowed inside a \
|
||||
secondary command buffer",
|
||||
),
|
||||
Self::DepthAttachmentFormatUsageNotSupported => write!(
|
||||
f,
|
||||
"the depth attachment has a format that does not support that usage",
|
||||
),
|
||||
Self::DepthAttachmentLayoutInvalid => write!(
|
||||
f,
|
||||
"the depth attachment has a layout that is not supported",
|
||||
),
|
||||
Self::DepthAttachmentLayoutInvalid => {
|
||||
write!(f, "the depth attachment has a layout that is not supported")
|
||||
}
|
||||
Self::DepthAttachmentMissingUsage => write!(
|
||||
f,
|
||||
"the depth attachment is missing the `depth_stencil_attachment` usage",
|
||||
),
|
||||
Self::DepthAttachmentResolveFormatMismatch => write!(
|
||||
f,
|
||||
"the depth resolve attachment has a `format` value different from the corresponding depth attachment",
|
||||
"the depth resolve attachment has a `format` value different from the \
|
||||
corresponding depth attachment",
|
||||
),
|
||||
Self::DepthAttachmentResolveLayoutInvalid => write!(
|
||||
f,
|
||||
@ -2972,15 +2967,18 @@ impl Display for RenderPassError {
|
||||
),
|
||||
Self::DepthAttachmentResolveMultisampled => write!(
|
||||
f,
|
||||
"the depth resolve attachment has a `samples` value other than `SampleCount::Sample1`",
|
||||
"the depth resolve attachment has a `samples` value other than \
|
||||
`SampleCount::Sample1`",
|
||||
),
|
||||
Self::DepthAttachmentSamplesMismatch => write!(
|
||||
f,
|
||||
"the depth attachment has a `samples` value that is different from the first color attachment",
|
||||
"the depth attachment has a `samples` value that is different from the first color \
|
||||
attachment",
|
||||
),
|
||||
Self::DepthAttachmentWithResolveNotMultisampled => write!(
|
||||
f,
|
||||
"the depth attachment has a resolve attachment and has a `samples` value of `SampleCount::Sample1`",
|
||||
"the depth attachment has a resolve attachment and has a `samples` value of \
|
||||
`SampleCount::Sample1`",
|
||||
),
|
||||
Self::DepthStencilAttachmentImageViewMismatch => write!(
|
||||
f,
|
||||
@ -3002,45 +3000,49 @@ impl Display for RenderPassError {
|
||||
}
|
||||
Self::ForbiddenWithBeginRendering => write!(
|
||||
f,
|
||||
"operation forbidden inside a render pass instance that was begun with `begin_rendering`",
|
||||
"operation forbidden inside a render pass instance that was begun with \
|
||||
`begin_rendering`",
|
||||
),
|
||||
Self::ForbiddenWithBeginRenderPass => write!(
|
||||
f,
|
||||
"operation forbidden inside a render pass instance that was begun with `begin_render_pass`",
|
||||
"operation forbidden inside a render pass instance that was begun with \
|
||||
`begin_render_pass`",
|
||||
),
|
||||
Self::ForbiddenWithInheritedRenderPass => write!(
|
||||
f,
|
||||
"operation forbidden inside a render pass instance that is inherited by a secondary command buffer",
|
||||
"operation forbidden inside a render pass instance that is inherited by a \
|
||||
secondary command buffer",
|
||||
),
|
||||
Self::ForbiddenWithSubpassContents { contents: subpass_contents } => write!(
|
||||
Self::ForbiddenWithSubpassContents {
|
||||
contents: subpass_contents,
|
||||
} => write!(
|
||||
f,
|
||||
"operation forbidden inside a render subpass with contents {:?}",
|
||||
subpass_contents,
|
||||
),
|
||||
Self::FramebufferNotCompatible => write!(
|
||||
f,
|
||||
"the framebuffer is not compatible with the render pass",
|
||||
),
|
||||
Self::FramebufferNotCompatible => {
|
||||
write!(f, "the framebuffer is not compatible with the render pass")
|
||||
}
|
||||
Self::MaxColorAttachmentsExceeded { .. } => {
|
||||
write!(f, "the `max_color_attachments` limit has been exceeded",)
|
||||
write!(f, "the `max_color_attachments` limit has been exceeded")
|
||||
}
|
||||
Self::MaxMultiviewViewCountExceeded { .. } => {
|
||||
write!(f, "the `max_multiview_view_count` limit has been exceeded",)
|
||||
},
|
||||
write!(f, "the `max_multiview_view_count` limit has been exceeded")
|
||||
}
|
||||
Self::MultiviewLayersInvalid => write!(
|
||||
f,
|
||||
"the render pass uses multiview, but `layer_count` was not 0 or 1",
|
||||
),
|
||||
Self::MultiviewRectArrayLayersInvalid { rect_index } => write!(
|
||||
f,
|
||||
"the render pass uses multiview, and in clear rectangle index {}, `array_layers` was not `0..1`",
|
||||
"the render pass uses multiview, and in clear rectangle index {}, `array_layers` \
|
||||
was not `0..1`",
|
||||
rect_index,
|
||||
),
|
||||
Self::NoSubpassesRemaining {
|
||||
current_subpass,
|
||||
} => write!(
|
||||
Self::NoSubpassesRemaining { current_subpass } => write!(
|
||||
f,
|
||||
"tried to advance to the next subpass after subpass {}, but there are no subpasses remaining in the render pass",
|
||||
"tried to advance to the next subpass after subpass {}, but there are no subpasses \
|
||||
remaining in the render pass",
|
||||
current_subpass,
|
||||
),
|
||||
Self::NotSupportedByQueueFamily => {
|
||||
@ -3048,7 +3050,7 @@ impl Display for RenderPassError {
|
||||
}
|
||||
Self::QueryIsActive => write!(
|
||||
f,
|
||||
"a query is active that conflicts with the current operation"
|
||||
"a query is active that conflicts with the current operation",
|
||||
),
|
||||
Self::RectArrayLayersEmpty { rect_index } => write!(
|
||||
f,
|
||||
@ -3057,17 +3059,17 @@ impl Display for RenderPassError {
|
||||
),
|
||||
Self::RectArrayLayersOutOfBounds { rect_index } => write!(
|
||||
f,
|
||||
"clear rectangle index {} `array_layers` is outside the range of layers of the attachments",
|
||||
rect_index,
|
||||
),
|
||||
Self::RectExtentZero { rect_index } => write!(
|
||||
f,
|
||||
"clear rectangle index {} `extent` is zero",
|
||||
"clear rectangle index {} `array_layers` is outside the range of layers of the \
|
||||
attachments",
|
||||
rect_index,
|
||||
),
|
||||
Self::RectExtentZero { rect_index } => {
|
||||
write!(f, "clear rectangle index {} `extent` is zero", rect_index)
|
||||
}
|
||||
Self::RectOutOfBounds { rect_index } => write!(
|
||||
f,
|
||||
"clear rectangle index {} `offset` and `extent` are outside the render area of the render pass instance",
|
||||
"clear rectangle index {} `offset` and `extent` are outside the render area of the \
|
||||
render pass instance",
|
||||
rect_index,
|
||||
),
|
||||
Self::RenderAreaOutOfBounds => write!(
|
||||
@ -3088,7 +3090,8 @@ impl Display for RenderPassError {
|
||||
),
|
||||
Self::StencilAttachmentResolveFormatMismatch => write!(
|
||||
f,
|
||||
"the stencil resolve attachment has a `format` value different from the corresponding stencil attachment",
|
||||
"the stencil resolve attachment has a `format` value different from the \
|
||||
corresponding stencil attachment",
|
||||
),
|
||||
Self::StencilAttachmentResolveLayoutInvalid => write!(
|
||||
f,
|
||||
@ -3100,22 +3103,26 @@ impl Display for RenderPassError {
|
||||
),
|
||||
Self::StencilAttachmentResolveMultisampled => write!(
|
||||
f,
|
||||
"the stencil resolve attachment has a `samples` value other than `SampleCount::Sample1`",
|
||||
"the stencil resolve attachment has a `samples` value other than \
|
||||
`SampleCount::Sample1`",
|
||||
),
|
||||
Self::StencilAttachmentSamplesMismatch => write!(
|
||||
f,
|
||||
"the stencil attachment has a `samples` value that is different from the first color attachment",
|
||||
"the stencil attachment has a `samples` value that is different from the first \
|
||||
color attachment",
|
||||
),
|
||||
Self::StencilAttachmentWithResolveNotMultisampled => write!(
|
||||
f,
|
||||
"the stencil attachment has a resolve attachment and has a `samples` value of `SampleCount::Sample1`",
|
||||
"the stencil attachment has a resolve attachment and has a `samples` value of \
|
||||
`SampleCount::Sample1`",
|
||||
),
|
||||
Self::SubpassesRemaining {
|
||||
current_subpass,
|
||||
remaining_subpasses,
|
||||
} => write!(
|
||||
f,
|
||||
"tried to end a render pass at subpass {}, with {} subpasses still remaining in the render pass",
|
||||
"tried to end a render pass at subpass {}, with {} subpasses still remaining in \
|
||||
the render pass",
|
||||
current_subpass, remaining_subpasses,
|
||||
),
|
||||
}
|
||||
@ -3123,14 +3130,12 @@ impl Display for RenderPassError {
|
||||
}
|
||||
|
||||
impl From<SyncCommandBufferBuilderError> for RenderPassError {
|
||||
#[inline]
|
||||
fn from(err: SyncCommandBufferBuilderError) -> Self {
|
||||
Self::SyncCommandBufferBuilderError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for RenderPassError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -59,7 +59,8 @@ where
|
||||
// Secondary command buffer could leave the primary in any state.
|
||||
self.inner.reset_state();
|
||||
|
||||
// If the secondary is non-concurrent or one-time use, that restricts the primary as well.
|
||||
// If the secondary is non-concurrent or one-time use, that restricts the primary as
|
||||
// well.
|
||||
self.usage = std::cmp::min(self.usage, secondary_usage);
|
||||
}
|
||||
|
||||
@ -96,7 +97,8 @@ where
|
||||
// Secondary command buffer could leave the primary in any state.
|
||||
self.inner.reset_state();
|
||||
|
||||
// If the secondary is non-concurrent or one-time use, that restricts the primary as well.
|
||||
// If the secondary is non-concurrent or one-time use, that restricts the primary as
|
||||
// well.
|
||||
self.usage = std::cmp::min(self.usage, secondary_usage);
|
||||
}
|
||||
|
||||
@ -411,7 +413,6 @@ pub struct SyncCommandBufferBuilderExecuteCommands<'a> {
|
||||
|
||||
impl<'a> SyncCommandBufferBuilderExecuteCommands<'a> {
|
||||
/// Adds a command buffer to the list.
|
||||
#[inline]
|
||||
pub fn add(&mut self, command_buffer: impl SecondaryCommandBuffer + 'static) {
|
||||
self.inner.push(Box::new(command_buffer));
|
||||
}
|
||||
@ -541,7 +542,6 @@ impl UnsafeCommandBufferBuilderExecuteCommands {
|
||||
}
|
||||
|
||||
/// Adds a command buffer to the list.
|
||||
#[inline]
|
||||
pub fn add(&mut self, cb: &(impl SecondaryCommandBuffer + ?Sized)) {
|
||||
// TODO: debug assert that it is a secondary command buffer?
|
||||
self.raw_cbs.push(cb.inner().internal_object());
|
||||
@ -694,7 +694,6 @@ pub enum ExecuteCommandsError {
|
||||
}
|
||||
|
||||
impl Error for ExecuteCommandsError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::SyncCommandBufferBuilderError(err) => Some(err),
|
||||
@ -704,11 +703,9 @@ impl Error for ExecuteCommandsError {
|
||||
}
|
||||
|
||||
impl Display for ExecuteCommandsError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -717,8 +714,9 @@ impl Display for ExecuteCommandsError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::ForbiddenWithSubpassContents { contents: subpass_contents } => write!(
|
||||
Self::ForbiddenWithSubpassContents {
|
||||
contents: subpass_contents,
|
||||
} => write!(
|
||||
f,
|
||||
"operation forbidden inside a render subpass with contents {:?}",
|
||||
subpass_contents,
|
||||
@ -730,7 +728,8 @@ impl Display for ExecuteCommandsError {
|
||||
command_buffer_index,
|
||||
} => write!(
|
||||
f,
|
||||
"a render pass is active, but command buffer {} does not contain occlusion query inheritance info",
|
||||
"a render pass is active, but command buffer {} does not contain occlusion query \
|
||||
inheritance info",
|
||||
command_buffer_index,
|
||||
),
|
||||
Self::OcclusionQueryFlagsNotSuperset {
|
||||
@ -739,7 +738,8 @@ impl Display for ExecuteCommandsError {
|
||||
inherited_flags,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited occlusion query control flags ({:?}) of command buffer {} are not a superset of the currently active flags ({:?})",
|
||||
"the inherited occlusion query control flags ({:?}) of command buffer {} are not a \
|
||||
superset of the currently active flags ({:?})",
|
||||
inherited_flags, command_buffer_index, required_flags,
|
||||
),
|
||||
Self::PipelineStatisticsQueryFlagsNotSuperset {
|
||||
@ -748,7 +748,8 @@ impl Display for ExecuteCommandsError {
|
||||
inherited_flags,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited pipeline statistics query flags ({:?}) of command buffer {} are not a superset of the currently active flags ({:?})",
|
||||
"the inherited pipeline statistics query flags ({:?}) of command buffer {} are not \
|
||||
a superset of the currently active flags ({:?})",
|
||||
inherited_flags, command_buffer_index, required_flags,
|
||||
),
|
||||
Self::RenderPassColorAttachmentCountMismatch {
|
||||
@ -757,10 +758,9 @@ impl Display for ExecuteCommandsError {
|
||||
inherited_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited color attachment count ({}) of command buffer {} does not match the current attachment count ({})",
|
||||
inherited_count,
|
||||
command_buffer_index,
|
||||
required_count,
|
||||
"the inherited color attachment count ({}) of command buffer {} does not match the \
|
||||
current attachment count ({})",
|
||||
inherited_count, command_buffer_index, required_count,
|
||||
),
|
||||
Self::RenderPassColorAttachmentFormatMismatch {
|
||||
command_buffer_index,
|
||||
@ -769,11 +769,9 @@ impl Display for ExecuteCommandsError {
|
||||
inherited_format,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited format ({:?}) of color attachment {} of command buffer {} does not match the current attachment format ({:?})",
|
||||
inherited_format,
|
||||
color_attachment_index,
|
||||
command_buffer_index,
|
||||
required_format,
|
||||
"the inherited format ({:?}) of color attachment {} of command buffer {} does not \
|
||||
match the current attachment format ({:?})",
|
||||
inherited_format, color_attachment_index, command_buffer_index, required_format,
|
||||
),
|
||||
Self::RenderPassColorAttachmentSamplesMismatch {
|
||||
command_buffer_index,
|
||||
@ -782,11 +780,9 @@ impl Display for ExecuteCommandsError {
|
||||
inherited_samples,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited sample count ({:?}) of color attachment {} of command buffer {} does not match the current attachment sample count ({:?})",
|
||||
inherited_samples,
|
||||
color_attachment_index,
|
||||
command_buffer_index,
|
||||
required_samples,
|
||||
"the inherited sample count ({:?}) of color attachment {} of command buffer {} \
|
||||
does not match the current attachment sample count ({:?})",
|
||||
inherited_samples, color_attachment_index, command_buffer_index, required_samples,
|
||||
),
|
||||
Self::RenderPassDepthAttachmentFormatMismatch {
|
||||
command_buffer_index,
|
||||
@ -794,10 +790,9 @@ impl Display for ExecuteCommandsError {
|
||||
inherited_format,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited format ({:?}) of the depth attachment of command buffer {} does not match the current attachment format ({:?})",
|
||||
inherited_format,
|
||||
command_buffer_index,
|
||||
required_format,
|
||||
"the inherited format ({:?}) of the depth attachment of command buffer {} does not \
|
||||
match the current attachment format ({:?})",
|
||||
inherited_format, command_buffer_index, required_format,
|
||||
),
|
||||
Self::RenderPassDepthAttachmentSamplesMismatch {
|
||||
command_buffer_index,
|
||||
@ -805,37 +800,40 @@ impl Display for ExecuteCommandsError {
|
||||
inherited_samples,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited sample count ({:?}) of the depth attachment of command buffer {} does not match the current attachment sample count ({:?})",
|
||||
inherited_samples,
|
||||
command_buffer_index,
|
||||
required_samples,
|
||||
"the inherited sample count ({:?}) of the depth attachment of command buffer {} \
|
||||
does not match the current attachment sample count ({:?})",
|
||||
inherited_samples, command_buffer_index, required_samples,
|
||||
),
|
||||
Self::RenderPassFramebufferMismatch {
|
||||
command_buffer_index,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited framebuffer of command buffer {} does not match the current framebuffer",
|
||||
"the inherited framebuffer of command buffer {} does not match the current \
|
||||
framebuffer",
|
||||
command_buffer_index,
|
||||
),
|
||||
Self::RenderPassInheritanceRequired {
|
||||
command_buffer_index,
|
||||
} => write!(
|
||||
f,
|
||||
"a render pass is active, but command buffer {} does not contain render pass inheritance info",
|
||||
"a render pass is active, but command buffer {} does not contain render pass \
|
||||
inheritance info",
|
||||
command_buffer_index,
|
||||
),
|
||||
Self::RenderPassInheritanceForbidden {
|
||||
command_buffer_index,
|
||||
} => write!(
|
||||
f,
|
||||
"a render pass is not active, but command buffer {} contains render pass inheritance info",
|
||||
"a render pass is not active, but command buffer {} contains render pass \
|
||||
inheritance info",
|
||||
command_buffer_index,
|
||||
),
|
||||
Self::RenderPassNotCompatible {
|
||||
command_buffer_index,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited render pass of command buffer {} is not compatible with the current render pass",
|
||||
"the inherited render pass of command buffer {} is not compatible with the current \
|
||||
render pass",
|
||||
command_buffer_index,
|
||||
),
|
||||
Self::RenderPassStencilAttachmentFormatMismatch {
|
||||
@ -844,10 +842,9 @@ impl Display for ExecuteCommandsError {
|
||||
inherited_format,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited format ({:?}) of the stencil attachment of command buffer {} does not match the current attachment format ({:?})",
|
||||
inherited_format,
|
||||
command_buffer_index,
|
||||
required_format,
|
||||
"the inherited format ({:?}) of the stencil attachment of command buffer {} does \
|
||||
not match the current attachment format ({:?})",
|
||||
inherited_format, command_buffer_index, required_format,
|
||||
),
|
||||
Self::RenderPassStencilAttachmentSamplesMismatch {
|
||||
command_buffer_index,
|
||||
@ -855,10 +852,9 @@ impl Display for ExecuteCommandsError {
|
||||
inherited_samples,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited sample count ({:?}) of the stencil attachment of command buffer {} does not match the current attachment sample count ({:?})",
|
||||
inherited_samples,
|
||||
command_buffer_index,
|
||||
required_samples,
|
||||
"the inherited sample count ({:?}) of the stencil attachment of command buffer {} \
|
||||
does not match the current attachment sample count ({:?})",
|
||||
inherited_samples, command_buffer_index, required_samples,
|
||||
),
|
||||
Self::RenderPassSubpassMismatch {
|
||||
command_buffer_index,
|
||||
@ -866,10 +862,9 @@ impl Display for ExecuteCommandsError {
|
||||
inherited_subpass,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited subpass index ({}) of command buffer {} does not match the current subpass index ({})",
|
||||
inherited_subpass,
|
||||
command_buffer_index,
|
||||
required_subpass,
|
||||
"the inherited subpass index ({}) of command buffer {} does not match the current \
|
||||
subpass index ({})",
|
||||
inherited_subpass, command_buffer_index, required_subpass,
|
||||
),
|
||||
Self::RenderPassTypeMismatch {
|
||||
command_buffer_index,
|
||||
@ -884,17 +879,15 @@ impl Display for ExecuteCommandsError {
|
||||
inherited_view_mask,
|
||||
} => write!(
|
||||
f,
|
||||
"the inherited view mask ({}) of command buffer {} does not match the current view mask ({})",
|
||||
inherited_view_mask,
|
||||
command_buffer_index,
|
||||
required_view_mask,
|
||||
"the inherited view mask ({}) of command buffer {} does not match the current view \
|
||||
mask ({})",
|
||||
inherited_view_mask, command_buffer_index, required_view_mask,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SyncCommandBufferBuilderError> for ExecuteCommandsError {
|
||||
#[inline]
|
||||
fn from(err: SyncCommandBufferBuilderError) -> Self {
|
||||
Self::SyncCommandBufferBuilderError(err)
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
///
|
||||
/// - Panics if `src_buffer` or `dst_buffer` were not created from the same device
|
||||
/// as `self`.
|
||||
#[inline]
|
||||
pub fn copy_buffer(
|
||||
&mut self,
|
||||
copy_buffer_info: impl Into<CopyBufferInfo>,
|
||||
@ -192,7 +191,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
///
|
||||
/// - Panics if `src_image` or `dst_image` were not created from the same device
|
||||
/// as `self`.
|
||||
#[inline]
|
||||
pub fn copy_image(&mut self, copy_image_info: CopyImageInfo) -> Result<&mut Self, CopyError> {
|
||||
self.validate_copy_image(©_image_info)?;
|
||||
|
||||
@ -872,7 +870,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
}
|
||||
|
||||
/// Copies from a buffer to an image.
|
||||
#[inline]
|
||||
pub fn copy_buffer_to_image(
|
||||
&mut self,
|
||||
copy_buffer_to_image_info: CopyBufferToImageInfo,
|
||||
@ -1304,7 +1301,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
}
|
||||
|
||||
/// Copies from an image to a buffer.
|
||||
#[inline]
|
||||
pub fn copy_image_to_buffer(
|
||||
&mut self,
|
||||
copy_image_to_buffer_info: CopyImageToBufferInfo,
|
||||
@ -1736,7 +1732,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `dst_buffer` was not created from the same device as `self`.
|
||||
#[inline]
|
||||
pub fn fill_buffer(
|
||||
&mut self,
|
||||
fill_buffer_info: FillBufferInfo,
|
||||
@ -1840,7 +1835,6 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `dst_buffer` was not created from the same device as `self`.
|
||||
#[inline]
|
||||
pub fn update_buffer<B, D, Dd>(
|
||||
&mut self,
|
||||
data: Dd,
|
||||
@ -2410,7 +2404,6 @@ impl SyncCommandBufferBuilder {
|
||||
}
|
||||
|
||||
/// Calls `vkCmdUpdateBuffer` on the builder.
|
||||
#[inline]
|
||||
pub unsafe fn update_buffer<D, Dd>(
|
||||
&mut self,
|
||||
data: Dd,
|
||||
@ -2998,7 +2991,6 @@ impl UnsafeCommandBufferBuilder {
|
||||
}
|
||||
|
||||
/// Calls `vkCmdUpdateBuffer` on the builder.
|
||||
#[inline]
|
||||
pub unsafe fn update_buffer<D>(
|
||||
&mut self,
|
||||
data: &D,
|
||||
@ -3098,7 +3090,6 @@ where
|
||||
D: TypedBufferAccess<Content = [T]>,
|
||||
{
|
||||
/// Returns a `CopyBufferInfoTyped` with the specified `src_buffer` and `dst_buffer`.
|
||||
#[inline]
|
||||
pub fn buffers(src_buffer: Arc<S>, dst_buffer: Arc<D>) -> Self {
|
||||
let region = BufferCopy {
|
||||
size: min(src_buffer.len(), dst_buffer.len()),
|
||||
@ -3119,7 +3110,6 @@ where
|
||||
S: TypedBufferAccess<Content = [T]> + 'static,
|
||||
D: TypedBufferAccess<Content = [T]> + 'static,
|
||||
{
|
||||
#[inline]
|
||||
fn from(typed: CopyBufferInfoTyped<S, D, T>) -> Self {
|
||||
let CopyBufferInfoTyped {
|
||||
src_buffer,
|
||||
|
@ -48,12 +48,13 @@ mod sys;
|
||||
/// free the command buffer, reset the command buffer, or add it to a pool so that it gets reused.
|
||||
/// If the implementation frees or resets the command buffer, it must not forget that this
|
||||
/// operation must lock the pool.
|
||||
///
|
||||
pub unsafe trait CommandPool: DeviceOwned {
|
||||
/// See `alloc()`.
|
||||
type Iter: Iterator<Item = Self::Builder>;
|
||||
|
||||
/// Represents a command buffer that has been allocated and that is currently being built.
|
||||
type Builder: CommandPoolBuilderAlloc<Alloc = Self::Alloc>;
|
||||
|
||||
/// Represents a command buffer that has been allocated and that is pending execution or is
|
||||
/// being executed.
|
||||
type Alloc: CommandPoolAlloc;
|
||||
@ -76,7 +77,6 @@ pub unsafe trait CommandPool: DeviceOwned {
|
||||
/// # Safety
|
||||
///
|
||||
/// See `CommandPool` for information about safety.
|
||||
///
|
||||
pub unsafe trait CommandPoolBuilderAlloc: DeviceOwned {
|
||||
/// Return type of `into_alloc`.
|
||||
type Alloc: CommandPoolAlloc;
|
||||
@ -96,7 +96,6 @@ pub unsafe trait CommandPoolBuilderAlloc: DeviceOwned {
|
||||
/// # Safety
|
||||
///
|
||||
/// See `CommandPool` for information about safety.
|
||||
///
|
||||
pub unsafe trait CommandPoolAlloc: DeviceOwned + Send + Sync {
|
||||
/// Returns the internal object that contains the command buffer.
|
||||
fn inner(&self) -> &UnsafeCommandPoolAlloc;
|
||||
|
@ -77,6 +77,7 @@ unsafe impl CommandPool for Arc<StandardCommandPool> {
|
||||
type Builder = StandardCommandPoolBuilder;
|
||||
type Alloc = StandardCommandPoolAlloc;
|
||||
|
||||
#[inline]
|
||||
fn allocate(
|
||||
&self,
|
||||
level: CommandBufferLevel,
|
||||
@ -212,6 +213,7 @@ unsafe impl DeviceOwned for StandardCommandPoolAlloc {
|
||||
}
|
||||
|
||||
impl Drop for StandardCommandPoolAlloc {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
// Safe because `self.cmd` is wrapped in a `ManuallyDrop`.
|
||||
let cmd: UnsafeCommandPoolAlloc = unsafe { ptr::read(&*self.cmd) };
|
||||
|
@ -78,6 +78,7 @@ impl UnsafeCommandPool {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
handle: ash::vk::CommandPool,
|
||||
@ -175,6 +176,7 @@ impl UnsafeCommandPool {
|
||||
/// # Safety
|
||||
///
|
||||
/// - The command buffers allocated from this pool jump to the initial state.
|
||||
#[inline]
|
||||
pub unsafe fn reset(&self, release_resources: bool) -> Result<(), OomError> {
|
||||
let flags = if release_resources {
|
||||
ash::vk::CommandPoolResetFlags::RELEASE_RESOURCES
|
||||
@ -186,10 +188,12 @@ impl UnsafeCommandPool {
|
||||
(fns.v1_0.reset_command_pool)(self.device.internal_object(), self.handle, flags)
|
||||
.result()
|
||||
.map_err(VulkanError::from)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Allocates command buffers.
|
||||
#[inline]
|
||||
pub fn allocate_command_buffers(
|
||||
&self,
|
||||
allocate_info: CommandBufferAllocateInfo,
|
||||
@ -269,6 +273,7 @@ impl UnsafeCommandPool {
|
||||
/// enabled on the device. Otherwise an error is returned.
|
||||
/// Since this operation is purely an optimization it is legitimate to call this function and
|
||||
/// simply ignore any possible error.
|
||||
#[inline]
|
||||
pub fn trim(&self) -> Result<(), CommandPoolTrimError> {
|
||||
if !(self.device.api_version() >= Version::V1_1
|
||||
|| self.device.enabled_extensions().khr_maintenance1)
|
||||
@ -351,7 +356,6 @@ impl PartialEq for UnsafeCommandPool {
|
||||
impl Eq for UnsafeCommandPool {}
|
||||
|
||||
impl Hash for UnsafeCommandPool {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -373,26 +377,25 @@ pub enum UnsafeCommandPoolCreationError {
|
||||
}
|
||||
|
||||
impl Error for UnsafeCommandPoolCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for UnsafeCommandPoolCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory",),
|
||||
Self::QueueFamilyIndexOutOfRange {
|
||||
queue_family_index,
|
||||
queue_family_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the provided `queue_family_index` ({}) was not less than the number of queue families in the physical device ({})",
|
||||
"the provided `queue_family_index` ({}) was not less than the number of queue \
|
||||
families in the physical device ({})",
|
||||
queue_family_index, queue_family_count,
|
||||
),
|
||||
}
|
||||
@ -400,7 +403,6 @@ impl Display for UnsafeCommandPoolCreationError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for UnsafeCommandPoolCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)),
|
||||
@ -513,7 +515,6 @@ impl PartialEq for UnsafeCommandPoolAlloc {
|
||||
impl Eq for UnsafeCommandPoolAlloc {}
|
||||
|
||||
impl Hash for UnsafeCommandPoolAlloc {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -532,7 +533,6 @@ pub enum CommandPoolTrimError {
|
||||
impl Error for CommandPoolTrimError {}
|
||||
|
||||
impl Display for CommandPoolTrimError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::RequirementNotMet {
|
||||
@ -548,7 +548,6 @@ impl Display for CommandPoolTrimError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for CommandPoolTrimError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> CommandPoolTrimError {
|
||||
panic!("unexpected error: {:?}", err)
|
||||
}
|
||||
|
@ -119,6 +119,7 @@ impl SyncCommandBufferBuilder {
|
||||
/// # Safety
|
||||
///
|
||||
/// See `UnsafeCommandBufferBuilder::new()`.
|
||||
#[inline]
|
||||
pub unsafe fn new(
|
||||
pool_alloc: &UnsafeCommandPoolAlloc,
|
||||
begin_info: CommandBufferBeginInfo,
|
||||
@ -131,8 +132,8 @@ impl SyncCommandBufferBuilder {
|
||||
.unwrap()
|
||||
.render_pass
|
||||
.is_some();
|
||||
|
||||
let inner = UnsafeCommandBufferBuilder::new(pool_alloc, begin_info)?;
|
||||
|
||||
Ok(SyncCommandBufferBuilder::from_unsafe_cmd(
|
||||
inner,
|
||||
level,
|
||||
@ -346,18 +347,17 @@ impl SyncCommandBufferBuilder {
|
||||
None
|
||||
}
|
||||
|
||||
// Adds a command to be processed by the builder.
|
||||
//
|
||||
// The `resources` argument should contain each buffer or image used by the command.
|
||||
// The function will take care of handling the pipeline barrier or flushing.
|
||||
//
|
||||
// - The index of the resource within the `resources` slice maps to the resource accessed
|
||||
// through `Command::buffer(..)` or `Command::image(..)`.
|
||||
// - `PipelineMemoryAccess` must match the way the resource has been used.
|
||||
// - `start_layout` and `end_layout` designate the image layout that the image is expected to be
|
||||
// in when the command starts, and the image layout that the image will be transitioned to
|
||||
// during the command. When it comes to buffers, you should pass `Undefined` for both.
|
||||
#[inline]
|
||||
/// Adds a command to be processed by the builder.
|
||||
///
|
||||
/// The `resources` argument should contain each buffer or image used by the command.
|
||||
/// The function will take care of handling the pipeline barrier or flushing.
|
||||
///
|
||||
/// - The index of the resource within the `resources` slice maps to the resource accessed
|
||||
/// through `Command::buffer(..)` or `Command::image(..)`.
|
||||
/// - `PipelineMemoryAccess` must match the way the resource has been used.
|
||||
/// - `start_layout` and `end_layout` designate the image layout that the image is expected to
|
||||
/// be in when the command starts, and the image layout that the image will be transitioned to
|
||||
/// during the command. When it comes to buffers, you should pass `Undefined` for both.
|
||||
pub(in crate::command_buffer) fn add_resource(
|
||||
&mut self,
|
||||
resource: (Cow<'static, str>, Resource),
|
||||
@ -610,26 +610,30 @@ impl SyncCommandBufferBuilder {
|
||||
// We can't transition to `Preinitialized`,
|
||||
// so all we can do here is error out.
|
||||
// TODO: put this in find_image_conflict instead?
|
||||
panic!("Command requires Preinitialized layout, but the initial layout of the image is not Preinitialized");
|
||||
panic!(
|
||||
"Command requires Preinitialized layout, but the \
|
||||
initial layout of the image is not Preinitialized"
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
// Insert a layout transition.
|
||||
|
||||
// A layout transition is a write, so if we perform one, we need
|
||||
// exclusive access.
|
||||
// A layout transition is a write, so if we perform one, we
|
||||
// need exclusive access.
|
||||
state.memory.exclusive = true; // TODO: is this correct?
|
||||
state.exclusive_any = true;
|
||||
|
||||
// Note that we transition from `bottom_of_pipe`, which means that we
|
||||
// wait for all the previous commands to be entirely finished. This is
|
||||
// suboptimal, but:
|
||||
//
|
||||
// - If we're at the start of the command buffer we have no choice anyway,
|
||||
// because we have no knowledge about what comes before.
|
||||
// - If we're in the middle of the command buffer, this pipeline is going
|
||||
// to be merged with an existing barrier. While it may still be
|
||||
// suboptimal in some cases, in the general situation it will be ok.
|
||||
// Note that we transition from `bottom_of_pipe`, which
|
||||
// means that we wait for all the previous commands to be
|
||||
// entirely finished. This is suboptimal, but:
|
||||
//
|
||||
// - If we're at the start of the command buffer we have no
|
||||
// choice anyway, because we have no knowledge about what
|
||||
// comes before.
|
||||
// - If we're in the middle of the command buffer, this
|
||||
// pipeline is going to be merged with an existing
|
||||
// barrier. While it may still be suboptimal in some
|
||||
// cases, in the general situation it will be ok.
|
||||
self.pending_barrier.image_memory_barriers.push(
|
||||
ImageMemoryBarrier {
|
||||
source_stages: PipelineStages {
|
||||
@ -862,7 +866,6 @@ unsafe impl DeviceOwned for SyncCommandBufferBuilder {
|
||||
}
|
||||
|
||||
impl Debug for SyncCommandBufferBuilder {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
Debug::fmt(&self.inner, f)
|
||||
}
|
||||
@ -885,7 +888,6 @@ pub enum SyncCommandBufferBuilderError {
|
||||
impl Error for SyncCommandBufferBuilderError {}
|
||||
|
||||
impl Display for SyncCommandBufferBuilderError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
SyncCommandBufferBuilderError::Conflict { .. } => write!(f, "unsolvable conflict"),
|
||||
@ -895,7 +897,6 @@ impl Display for SyncCommandBufferBuilderError {
|
||||
}
|
||||
|
||||
impl From<CommandBufferExecError> for SyncCommandBufferBuilderError {
|
||||
#[inline]
|
||||
fn from(val: CommandBufferExecError) -> Self {
|
||||
SyncCommandBufferBuilderError::ExecError(val)
|
||||
}
|
||||
@ -1101,6 +1102,7 @@ pub enum SetOrPush {
|
||||
}
|
||||
|
||||
impl SetOrPush {
|
||||
#[inline]
|
||||
pub fn resources(&self) -> &DescriptorSetResources {
|
||||
match self {
|
||||
Self::Set(set) => set.as_ref().0.resources(),
|
||||
@ -1304,7 +1306,8 @@ impl<'a> CommandBufferState<'a> {
|
||||
self.current_state.rasterizer_discard_enable
|
||||
}
|
||||
|
||||
/// Returns the current scissor for a given viewport slot, or `None` if nothing has been set yet.
|
||||
/// Returns the current scissor for a given viewport slot, or `None` if nothing has been set
|
||||
/// yet.
|
||||
#[inline]
|
||||
pub fn scissor(&self, num: u32) -> Option<&'a Scissor> {
|
||||
self.current_state.scissor.get(&num)
|
||||
@ -1349,7 +1352,8 @@ impl<'a> CommandBufferState<'a> {
|
||||
self.current_state.stencil_write_mask
|
||||
}
|
||||
|
||||
/// Returns the current viewport for a given viewport slot, or `None` if nothing has been set yet.
|
||||
/// Returns the current viewport for a given viewport slot, or `None` if nothing has been set
|
||||
/// yet.
|
||||
#[inline]
|
||||
pub fn viewport(&self, num: u32) -> Option<&'a Viewport> {
|
||||
self.current_state.viewport.get(&num)
|
||||
|
@ -131,6 +131,7 @@ impl SyncCommandBuffer {
|
||||
/// Tries to lock the resources used by the command buffer.
|
||||
///
|
||||
/// > **Note**: You should call this in the implementation of the `CommandBuffer` trait.
|
||||
#[inline]
|
||||
pub fn lock_submit(
|
||||
&self,
|
||||
future: &dyn GpuFuture,
|
||||
@ -281,7 +282,7 @@ impl SyncCommandBuffer {
|
||||
/// # Safety
|
||||
///
|
||||
/// The command buffer must have been successfully locked with `lock_submit()`.
|
||||
///
|
||||
#[inline]
|
||||
pub unsafe fn unlock(&self) {
|
||||
for (buffer, range_map) in &self.buffers2 {
|
||||
let mut buffer_state = buffer.state();
|
||||
|
@ -50,6 +50,7 @@ impl UnsafeCommandBufferBuilder {
|
||||
///
|
||||
/// - `pool_alloc` must outlive the returned builder and its created command buffer.
|
||||
/// - `kind` must match how `pool_alloc` was created.
|
||||
#[inline]
|
||||
pub unsafe fn new(
|
||||
pool_alloc: &UnsafeCommandPoolAlloc,
|
||||
begin_info: CommandBufferBeginInfo,
|
||||
|
@ -68,9 +68,9 @@ pub unsafe trait PrimaryCommandBuffer: DeviceOwned + Send + Sync {
|
||||
///
|
||||
/// > **Note**: This is just a shortcut for `execute_after(vulkano::sync::now(), queue)`.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the device of the command buffer is not the same as the device of the future.
|
||||
/// - Panics if the device of the command buffer is not the same as the device of the future.
|
||||
#[inline]
|
||||
fn execute(
|
||||
self,
|
||||
@ -102,10 +102,9 @@ pub unsafe trait PrimaryCommandBuffer: DeviceOwned + Send + Sync {
|
||||
/// `std::mem::forget` on that object and "unlock" these resources. For more information about
|
||||
/// this problem, search the web for "rust thread scoped leakpocalypse".
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the device of the command buffer is not the same as the device of the future.
|
||||
#[inline]
|
||||
/// - Panics if the device of the command buffer is not the same as the device of the future.
|
||||
fn execute_after<F>(
|
||||
self,
|
||||
future: F,
|
||||
@ -164,12 +163,10 @@ where
|
||||
T: SafeDeref + Send + Sync,
|
||||
T::Target: PrimaryCommandBuffer,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> &UnsafeCommandBuffer {
|
||||
(**self).inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lock_submit(
|
||||
&self,
|
||||
future: &dyn GpuFuture,
|
||||
@ -178,12 +175,10 @@ where
|
||||
(**self).lock_submit(future, queue)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unlock(&self) {
|
||||
(**self).unlock();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_buffer_access(
|
||||
&self,
|
||||
buffer: &UnsafeBuffer,
|
||||
@ -194,7 +189,6 @@ where
|
||||
(**self).check_buffer_access(buffer, range, exclusive, queue)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_image_access(
|
||||
&self,
|
||||
image: &UnsafeImage,
|
||||
@ -266,32 +260,26 @@ where
|
||||
T: SafeDeref + Send + Sync,
|
||||
T::Target: SecondaryCommandBuffer,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> &UnsafeCommandBuffer {
|
||||
(**self).inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lock_record(&self) -> Result<(), CommandBufferExecError> {
|
||||
(**self).lock_record()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unlock(&self) {
|
||||
(**self).unlock();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inheritance_info(&self) -> &CommandBufferInheritanceInfo {
|
||||
(**self).inheritance_info()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_buffers(&self) -> usize {
|
||||
(**self).num_buffers()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn buffer(
|
||||
&self,
|
||||
index: usize,
|
||||
@ -303,12 +291,10 @@ where
|
||||
(**self).buffer(index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_images(&self) -> usize {
|
||||
(**self).num_images()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn image(
|
||||
&self,
|
||||
index: usize,
|
||||
@ -325,6 +311,7 @@ where
|
||||
|
||||
/// Represents a command buffer being executed by the GPU and the moment when the execution
|
||||
/// finishes.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "Dropping this object will immediately block the thread until the GPU has finished processing the submission"]
|
||||
pub struct CommandBufferExecFuture<F>
|
||||
where
|
||||
@ -399,7 +386,6 @@ unsafe impl<F> GpuFuture for CommandBufferExecFuture<F>
|
||||
where
|
||||
F: GpuFuture,
|
||||
{
|
||||
#[inline]
|
||||
fn cleanup_finished(&mut self) {
|
||||
self.previous.cleanup_finished();
|
||||
}
|
||||
@ -412,7 +398,6 @@ where
|
||||
self.build_submission_impl()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&self) -> Result<(), FlushError> {
|
||||
unsafe {
|
||||
let mut submitted = self.submitted.lock();
|
||||
@ -436,23 +421,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn signal_finished(&self) {
|
||||
self.finished.store(true, Ordering::SeqCst);
|
||||
self.previous.signal_finished();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue_change_allowed(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue(&self) -> Option<Arc<Queue>> {
|
||||
Some(self.queue.clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_buffer_access(
|
||||
&self,
|
||||
buffer: &UnsafeBuffer,
|
||||
@ -472,7 +453,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_image_access(
|
||||
&self,
|
||||
image: &UnsafeImage,
|
||||
@ -511,7 +491,6 @@ unsafe impl<F> DeviceOwned for CommandBufferExecFuture<F>
|
||||
where
|
||||
F: GpuFuture,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.command_buffer.device()
|
||||
}
|
||||
@ -556,32 +535,30 @@ pub enum CommandBufferExecError {
|
||||
}
|
||||
|
||||
impl Error for CommandBufferExecError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
CommandBufferExecError::AccessError { ref error, .. } => Some(error),
|
||||
match self {
|
||||
CommandBufferExecError::AccessError { error, .. } => Some(error),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for CommandBufferExecError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
match self {
|
||||
CommandBufferExecError::AccessError { .. } =>
|
||||
"access to a resource has been denied",
|
||||
CommandBufferExecError::OneTimeSubmitAlreadySubmitted => {
|
||||
"the command buffer or one of the secondary command buffers it executes was \
|
||||
created with the \"one time submit\" flag, but has already been submitted in \
|
||||
the past"
|
||||
created with the \"one time submit\" flag, but has already been submitted in \
|
||||
the past"
|
||||
}
|
||||
CommandBufferExecError::ExclusiveAlreadyInUse => {
|
||||
"the command buffer or one of the secondary command buffers it executes is \
|
||||
already in use was not created with the \"concurrent\" flag"
|
||||
already in use was not created with the \"concurrent\" flag"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -25,7 +25,6 @@ unsafe impl<T> DescriptorSetsCollection for T
|
||||
where
|
||||
T: Into<DescriptorSetWithOffsets>,
|
||||
{
|
||||
#[inline]
|
||||
fn into_vec(self) -> Vec<DescriptorSetWithOffsets> {
|
||||
vec![self.into()]
|
||||
}
|
||||
@ -35,7 +34,6 @@ unsafe impl<T> DescriptorSetsCollection for Vec<T>
|
||||
where
|
||||
T: Into<DescriptorSetWithOffsets>,
|
||||
{
|
||||
#[inline]
|
||||
fn into_vec(self) -> Vec<DescriptorSetWithOffsets> {
|
||||
self.into_iter().map(|x| x.into()).collect()
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ pub struct DescriptorSetLayout {
|
||||
|
||||
impl DescriptorSetLayout {
|
||||
/// Creates a new `DescriptorSetLayout`.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
device: Arc<Device>,
|
||||
mut create_info: DescriptorSetLayoutCreateInfo,
|
||||
@ -73,6 +74,7 @@ impl DescriptorSetLayout {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
handle: ash::vk::DescriptorSetLayout,
|
||||
@ -461,7 +463,6 @@ impl PartialEq for DescriptorSetLayout {
|
||||
impl Eq for DescriptorSetLayout {}
|
||||
|
||||
impl Hash for DescriptorSetLayout {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -520,13 +521,11 @@ impl From<VulkanError> for DescriptorSetLayoutCreationError {
|
||||
impl Error for DescriptorSetLayoutCreationError {}
|
||||
|
||||
impl Display for DescriptorSetLayoutCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
match self {
|
||||
Self::OomError(_) => {
|
||||
write!(f, "out of memory")
|
||||
}
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -535,15 +534,20 @@ impl Display for DescriptorSetLayoutCreationError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::ImmutableSamplersCountMismatch { binding_num, sampler_count, descriptor_count } => write!(
|
||||
Self::ImmutableSamplersCountMismatch {
|
||||
binding_num,
|
||||
sampler_count,
|
||||
descriptor_count,
|
||||
} => write!(
|
||||
f,
|
||||
"binding {} includes immutable samplers but their number ({}) differs from `descriptor_count` ({})",
|
||||
"binding {} includes immutable samplers but their number ({}) differs from \
|
||||
`descriptor_count` ({})",
|
||||
binding_num, sampler_count, descriptor_count,
|
||||
),
|
||||
Self::ImmutableSamplersDescriptorTypeIncompatible { binding_num } => write!(
|
||||
f,
|
||||
"binding {} includes immutable samplers but it has an incompatible `descriptor_type`",
|
||||
"binding {} includes immutable samplers but it has an incompatible \
|
||||
`descriptor_type`",
|
||||
binding_num,
|
||||
),
|
||||
Self::MaxPushDescriptorsExceeded {
|
||||
@ -551,27 +555,35 @@ impl Display for DescriptorSetLayoutCreationError {
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"more descriptors were provided in all bindings ({}) than the `max_push_descriptors` limit ({})",
|
||||
"more descriptors were provided in all bindings ({}) than the \
|
||||
`max_push_descriptors` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::PushDescriptorDescriptorTypeIncompatible { binding_num } => write!(
|
||||
f,
|
||||
"`push_descriptor` is enabled, but binding {} has an incompatible `descriptor_type`",
|
||||
"`push_descriptor` is enabled, but binding {} has an incompatible \
|
||||
`descriptor_type`",
|
||||
binding_num,
|
||||
),
|
||||
Self::PushDescriptorVariableDescriptorCount { binding_num } => write!(
|
||||
f,
|
||||
"`push_descriptor` is enabled, but binding {} has `variable_descriptor_count` enabled",
|
||||
"`push_descriptor` is enabled, but binding {} has `variable_descriptor_count` \
|
||||
enabled",
|
||||
binding_num,
|
||||
),
|
||||
Self::VariableDescriptorCountBindingNotHighest { binding_num, highest_binding_num } => write!(
|
||||
Self::VariableDescriptorCountBindingNotHighest {
|
||||
binding_num,
|
||||
highest_binding_num,
|
||||
} => write!(
|
||||
f,
|
||||
"binding {} has `variable_descriptor_count` enabled, but it is not the highest-numbered binding ({})",
|
||||
"binding {} has `variable_descriptor_count` enabled, but it is not the \
|
||||
highest-numbered binding ({})",
|
||||
binding_num, highest_binding_num,
|
||||
),
|
||||
Self::VariableDescriptorCountDescriptorTypeIncompatible { binding_num } => write!(
|
||||
f,
|
||||
"binding {} has `variable_descriptor_count` enabled, but it has an incompatible `descriptor_type`",
|
||||
"binding {} has `variable_descriptor_count` enabled, but it has an incompatible \
|
||||
`descriptor_type`",
|
||||
binding_num,
|
||||
),
|
||||
}
|
||||
@ -579,7 +591,6 @@ impl Display for DescriptorSetLayoutCreationError {
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for DescriptorSetLayoutCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
@ -633,7 +644,6 @@ impl Default for DescriptorSetLayoutCreateInfo {
|
||||
impl DescriptorSetLayoutCreateInfo {
|
||||
/// Builds a list of `DescriptorSetLayoutCreateInfo` from an iterator of `DescriptorRequirement`
|
||||
/// originating from a shader.
|
||||
#[inline]
|
||||
pub fn from_requirements<'a>(
|
||||
descriptor_requirements: impl IntoIterator<Item = ((u32, u32), &'a DescriptorRequirements)>,
|
||||
) -> Vec<Self> {
|
||||
@ -671,16 +681,17 @@ pub struct DescriptorSetLayoutBinding {
|
||||
|
||||
/// Whether the binding has a variable number of descriptors.
|
||||
///
|
||||
/// If set to `true`, the
|
||||
/// [`descriptor_binding_variable_descriptor_count`](crate::device::Features::descriptor_binding_variable_descriptor_count)
|
||||
/// feature must be enabled. The value of `descriptor_count` specifies the maximum number of
|
||||
/// descriptors allowed.
|
||||
/// If set to `true`, the [`descriptor_binding_variable_descriptor_count`] feature must be
|
||||
/// enabled. The value of `descriptor_count` specifies the maximum number of descriptors
|
||||
/// allowed.
|
||||
///
|
||||
/// There may only be one binding with a variable count in a descriptor set, and it must be the
|
||||
/// binding with the highest binding number. The `descriptor_type` must not be
|
||||
/// [`DescriptorType::UniformBufferDynamic`] or [`DescriptorType::StorageBufferDynamic`].
|
||||
///
|
||||
/// The default value is `false`.
|
||||
///
|
||||
/// [`descriptor_binding_variable_descriptor_count`]: crate::device::Features::descriptor_binding_variable_descriptor_count
|
||||
pub variable_descriptor_count: bool,
|
||||
|
||||
/// Which shader stages are going to access the descriptors in this binding.
|
||||
@ -768,6 +779,7 @@ impl DescriptorSetLayoutBinding {
|
||||
}
|
||||
|
||||
impl From<&DescriptorRequirements> for DescriptorSetLayoutBinding {
|
||||
#[inline]
|
||||
fn from(reqs: &DescriptorRequirements) -> Self {
|
||||
Self {
|
||||
descriptor_type: reqs.descriptor_types[0],
|
||||
@ -802,18 +814,17 @@ pub enum DescriptorRequirementsNotMet {
|
||||
impl Error for DescriptorRequirementsNotMet {}
|
||||
|
||||
impl Display for DescriptorRequirementsNotMet {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::DescriptorType { required, obtained } => write!(
|
||||
f,
|
||||
"the descriptor's type ({:?}) is not one of those required ({:?})",
|
||||
obtained, required
|
||||
obtained, required,
|
||||
),
|
||||
Self::DescriptorCount { required, obtained } => write!(
|
||||
f,
|
||||
"the descriptor count ({}) is less than what is required ({})",
|
||||
obtained, required
|
||||
obtained, required,
|
||||
),
|
||||
Self::ShaderStages { .. } => write!(
|
||||
f,
|
||||
|
@ -22,7 +22,7 @@
|
||||
//! that are often used together in the same set so that you can keep the same set binding through
|
||||
//! multiple draws.
|
||||
//!
|
||||
//! # Example
|
||||
//! # Examples
|
||||
//!
|
||||
//! > **Note**: This section describes the simple way to bind resources. There are more optimized
|
||||
//! > ways.
|
||||
@ -143,7 +143,6 @@ impl PartialEq for dyn DescriptorSet {
|
||||
impl Eq for dyn DescriptorSet {}
|
||||
|
||||
impl Hash for dyn DescriptorSet {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().internal_object().hash(state);
|
||||
self.device().hash(state);
|
||||
@ -164,14 +163,16 @@ impl DescriptorSetInner {
|
||||
) -> Result<Self, DescriptorSetUpdateError> {
|
||||
assert!(
|
||||
!layout.push_descriptor(),
|
||||
"the provided descriptor set layout is for push descriptors, and cannot be used to build a descriptor set object"
|
||||
"the provided descriptor set layout is for push descriptors, and cannot be used to \
|
||||
build a descriptor set object",
|
||||
);
|
||||
|
||||
let max_count = layout.variable_descriptor_count();
|
||||
|
||||
assert!(
|
||||
variable_descriptor_count <= max_count,
|
||||
"the provided variable_descriptor_count ({}) is greater than the maximum number of variable count descriptors in the layout ({})",
|
||||
"the provided variable_descriptor_count ({}) is greater than the maximum number of \
|
||||
variable count descriptors in the layout ({})",
|
||||
variable_descriptor_count,
|
||||
max_count,
|
||||
);
|
||||
@ -247,6 +248,7 @@ pub struct DescriptorSetResources {
|
||||
impl DescriptorSetResources {
|
||||
/// Creates a new `DescriptorSetResources` matching the provided descriptor set layout, and
|
||||
/// all descriptors set to `None`.
|
||||
#[inline]
|
||||
pub fn new(layout: &DescriptorSetLayout, variable_descriptor_count: u32) -> Self {
|
||||
assert!(variable_descriptor_count <= layout.variable_descriptor_count());
|
||||
|
||||
@ -309,6 +311,7 @@ impl DescriptorSetResources {
|
||||
///
|
||||
/// - Panics if the binding number of a write does not exist in the resources.
|
||||
/// - See also [`DescriptorBindingResources::update`].
|
||||
#[inline]
|
||||
pub fn update(&mut self, write: &WriteDescriptorSet) {
|
||||
self.binding_resources
|
||||
.get_mut(&write.binding())
|
||||
@ -344,6 +347,7 @@ impl DescriptorBindingResources {
|
||||
///
|
||||
/// - Panics if the resource types do not match.
|
||||
/// - Panics if the write goes out of bounds.
|
||||
#[inline]
|
||||
pub fn update(&mut self, write: &WriteDescriptorSet) {
|
||||
fn write_resources<T: Clone>(first: usize, resources: &mut [Option<T>], elements: &[T]) {
|
||||
resources
|
||||
@ -406,7 +410,6 @@ pub struct DescriptorSetWithOffsets {
|
||||
}
|
||||
|
||||
impl DescriptorSetWithOffsets {
|
||||
#[inline]
|
||||
pub fn new(
|
||||
descriptor_set: Arc<dyn DescriptorSet>,
|
||||
dynamic_offsets: impl IntoIterator<Item = u32>,
|
||||
@ -428,9 +431,10 @@ impl DescriptorSetWithOffsets {
|
||||
if dynamic_offsets.len() > dynamic_offset_index {
|
||||
assert!(
|
||||
dynamic_offsets[dynamic_offset_index] % min_storage_off_align == 0,
|
||||
"Dynamic storage buffer offset must be a multiple of min_storage_buffer_offset_alignment: got {}, expected a multiple of {}",
|
||||
"Dynamic storage buffer offset must be a multiple of \
|
||||
min_storage_buffer_offset_alignment: got {}, expected a multiple of {}",
|
||||
dynamic_offsets[dynamic_offset_index],
|
||||
min_storage_off_align
|
||||
min_storage_off_align,
|
||||
);
|
||||
}
|
||||
dynamic_offset_index += 1;
|
||||
@ -440,9 +444,10 @@ impl DescriptorSetWithOffsets {
|
||||
if dynamic_offsets.len() > dynamic_offset_index {
|
||||
assert!(
|
||||
dynamic_offsets[dynamic_offset_index] % min_uniform_off_align == 0,
|
||||
"Dynamic uniform buffer offset must be a multiple of min_uniform_buffer_offset_alignment: got {}, expected a multiple of {}",
|
||||
"Dynamic uniform buffer offset must be a multiple of \
|
||||
min_uniform_buffer_offset_alignment: got {}, expected a multiple of {}",
|
||||
dynamic_offsets[dynamic_offset_index],
|
||||
min_uniform_off_align
|
||||
min_uniform_off_align,
|
||||
);
|
||||
}
|
||||
dynamic_offset_index += 1;
|
||||
@ -455,13 +460,13 @@ impl DescriptorSetWithOffsets {
|
||||
dynamic_offsets.len() >= dynamic_offset_index,
|
||||
"Too few dynamic offsets: got {}, expected {}",
|
||||
dynamic_offsets.len(),
|
||||
dynamic_offset_index
|
||||
dynamic_offset_index,
|
||||
);
|
||||
assert!(
|
||||
dynamic_offsets.len() <= dynamic_offset_index,
|
||||
"Too many dynamic offsets: got {}, expected {}",
|
||||
dynamic_offsets.len(),
|
||||
dynamic_offset_index
|
||||
dynamic_offset_index,
|
||||
);
|
||||
|
||||
DescriptorSetWithOffsets {
|
||||
@ -485,7 +490,6 @@ impl<S> From<Arc<S>> for DescriptorSetWithOffsets
|
||||
where
|
||||
S: DescriptorSet + 'static,
|
||||
{
|
||||
#[inline]
|
||||
fn from(descriptor_set: Arc<S>) -> Self {
|
||||
DescriptorSetWithOffsets::new(descriptor_set, std::iter::empty())
|
||||
}
|
||||
@ -498,7 +502,6 @@ pub enum DescriptorSetCreationError {
|
||||
}
|
||||
|
||||
impl Error for DescriptorSetCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::DescriptorSetUpdateError(err) => Some(err),
|
||||
@ -508,7 +511,6 @@ impl Error for DescriptorSetCreationError {
|
||||
}
|
||||
|
||||
impl Display for DescriptorSetCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::DescriptorSetUpdateError(_) => {
|
||||
@ -520,14 +522,12 @@ impl Display for DescriptorSetCreationError {
|
||||
}
|
||||
|
||||
impl From<DescriptorSetUpdateError> for DescriptorSetCreationError {
|
||||
#[inline]
|
||||
fn from(err: DescriptorSetUpdateError) -> Self {
|
||||
Self::DescriptorSetUpdateError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for DescriptorSetCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
//! > actual allocation, you can skip this allocation and make it acceptable to use a persistent
|
||||
//! > descriptor set in performance-critical paths..
|
||||
//!
|
||||
//! # Example
|
||||
//! # Examples
|
||||
//! TODO:
|
||||
|
||||
use crate::{
|
||||
@ -124,17 +124,14 @@ unsafe impl<P> DescriptorSet for PersistentDescriptorSet<P>
|
||||
where
|
||||
P: DescriptorPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> &UnsafeDescriptorSet {
|
||||
self.alloc.inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn layout(&self) -> &Arc<DescriptorSetLayout> {
|
||||
self.inner.layout()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn resources(&self) -> &DescriptorSetResources {
|
||||
self.inner.resources()
|
||||
}
|
||||
@ -144,7 +141,6 @@ unsafe impl<P> DeviceOwned for PersistentDescriptorSet<P>
|
||||
where
|
||||
P: DescriptorPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.inner.layout().device()
|
||||
}
|
||||
@ -154,7 +150,6 @@ impl<P> PartialEq for PersistentDescriptorSet<P>
|
||||
where
|
||||
P: DescriptorPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner().internal_object() == other.inner().internal_object()
|
||||
&& self.device() == other.device()
|
||||
@ -167,7 +162,6 @@ impl<P> Hash for PersistentDescriptorSet<P>
|
||||
where
|
||||
P: DescriptorPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().internal_object().hash(state);
|
||||
self.device().hash(state);
|
||||
|
@ -41,6 +41,7 @@ enum Pool {
|
||||
|
||||
impl StandardDescriptorPool {
|
||||
/// Builds a new `StandardDescriptorPool`.
|
||||
#[inline]
|
||||
pub fn new(device: Arc<Device>) -> StandardDescriptorPool {
|
||||
StandardDescriptorPool {
|
||||
device,
|
||||
@ -52,6 +53,7 @@ impl StandardDescriptorPool {
|
||||
unsafe impl DescriptorPool for StandardDescriptorPool {
|
||||
type Alloc = StandardDescriptorPoolAlloc;
|
||||
|
||||
#[inline]
|
||||
fn allocate(
|
||||
&mut self,
|
||||
layout: &Arc<DescriptorSetLayout>,
|
||||
|
@ -124,6 +124,7 @@ impl UnsafeDescriptorPool {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
handle: ash::vk::DescriptorPool,
|
||||
@ -170,7 +171,7 @@ impl UnsafeDescriptorPool {
|
||||
/// The `FragmentedPool` errors often can't be prevented. If the function returns this error,
|
||||
/// you should just create a new pool.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if one of the layouts wasn't created with the same device as the pool.
|
||||
///
|
||||
@ -182,7 +183,6 @@ impl UnsafeDescriptorPool {
|
||||
/// - The total number of descriptor sets allocated from the pool must not overflow the pool.
|
||||
/// - You must ensure that the allocated descriptor sets are no longer in use when the pool
|
||||
/// is destroyed, as destroying the pool is equivalent to freeing all the sets.
|
||||
///
|
||||
pub unsafe fn allocate_descriptor_sets<'a>(
|
||||
&mut self,
|
||||
allocate_info: impl IntoIterator<Item = DescriptorSetAllocateInfo<'a>>,
|
||||
@ -281,7 +281,6 @@ impl UnsafeDescriptorPool {
|
||||
/// - The descriptor sets must have been allocated from the pool.
|
||||
/// - The descriptor sets must not be free'd twice.
|
||||
/// - The descriptor sets must not be in use by the GPU.
|
||||
///
|
||||
pub unsafe fn free_descriptor_sets(
|
||||
&mut self,
|
||||
descriptor_sets: impl IntoIterator<Item = UnsafeDescriptorSet>,
|
||||
@ -308,6 +307,7 @@ impl UnsafeDescriptorPool {
|
||||
/// Resets the pool.
|
||||
///
|
||||
/// This destroys all descriptor sets and empties the pool.
|
||||
#[inline]
|
||||
pub unsafe fn reset(&mut self) -> Result<(), OomError> {
|
||||
let fns = self.device.fns();
|
||||
(fns.v1_0.reset_descriptor_pool)(
|
||||
@ -317,6 +317,7 @@ impl UnsafeDescriptorPool {
|
||||
)
|
||||
.result()
|
||||
.map_err(VulkanError::from)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -361,7 +362,6 @@ impl PartialEq for UnsafeDescriptorPool {
|
||||
impl Eq for UnsafeDescriptorPool {}
|
||||
|
||||
impl Hash for UnsafeDescriptorPool {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -429,12 +429,11 @@ pub enum DescriptorPoolAllocError {
|
||||
impl Error for DescriptorPoolAllocError {}
|
||||
|
||||
impl Display for DescriptorPoolAllocError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
match self {
|
||||
DescriptorPoolAllocError::OutOfHostMemory => "no memory available on the host",
|
||||
DescriptorPoolAllocError::OutOfDeviceMemory => {
|
||||
"no memory available on the graphical device"
|
||||
|
@ -60,6 +60,7 @@ impl SingleLayoutDescSetPool {
|
||||
/// - Panics if the provided `layout` is for push descriptors rather than regular descriptor
|
||||
/// sets.
|
||||
/// - Panics if the provided `layout` has a binding with a variable descriptor count.
|
||||
#[inline]
|
||||
pub fn new(layout: Arc<DescriptorSetLayout>) -> Result<Self, OomError> {
|
||||
assert!(
|
||||
!layout.push_descriptor(),
|
||||
@ -81,7 +82,6 @@ impl SingleLayoutDescSetPool {
|
||||
|
||||
/// Returns a new descriptor set, either by creating a new one or returning an existing one
|
||||
/// from the internal reserve.
|
||||
#[inline]
|
||||
pub fn next(
|
||||
&mut self,
|
||||
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
|
||||
@ -186,12 +186,10 @@ pub(crate) struct SingleLayoutPoolAlloc {
|
||||
}
|
||||
|
||||
impl DescriptorPoolAlloc for SingleLayoutPoolAlloc {
|
||||
#[inline]
|
||||
fn inner(&self) -> &UnsafeDescriptorSet {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inner_mut(&mut self) -> &mut UnsafeDescriptorSet {
|
||||
&mut self.inner
|
||||
}
|
||||
@ -245,7 +243,6 @@ impl PartialEq for SingleLayoutDescSet {
|
||||
impl Eq for SingleLayoutDescSet {}
|
||||
|
||||
impl Hash for SingleLayoutDescSet {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().internal_object().hash(state);
|
||||
self.device().hash(state);
|
||||
@ -279,6 +276,7 @@ impl SingleLayoutVariableDescSetPool {
|
||||
///
|
||||
/// - Panics if the provided `layout` is for push descriptors rather than regular descriptor
|
||||
/// sets.
|
||||
#[inline]
|
||||
pub fn new(layout: Arc<DescriptorSetLayout>) -> Result<Self, OomError> {
|
||||
assert!(
|
||||
!layout.push_descriptor(),
|
||||
@ -301,7 +299,6 @@ impl SingleLayoutVariableDescSetPool {
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the provided `variable_descriptor_count` exceeds the maximum for the layout.
|
||||
#[inline]
|
||||
pub fn next(
|
||||
&mut self,
|
||||
variable_descriptor_count: u32,
|
||||
@ -440,12 +437,10 @@ unsafe impl Send for SingleLayoutVariablePoolAlloc {}
|
||||
unsafe impl Sync for SingleLayoutVariablePoolAlloc {}
|
||||
|
||||
impl DescriptorPoolAlloc for SingleLayoutVariablePoolAlloc {
|
||||
#[inline]
|
||||
fn inner(&self) -> &UnsafeDescriptorSet {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inner_mut(&mut self) -> &mut UnsafeDescriptorSet {
|
||||
&mut self.inner
|
||||
}
|
||||
@ -492,7 +487,6 @@ impl PartialEq for SingleLayoutVariableDescSet {
|
||||
impl Eq for SingleLayoutVariableDescSet {}
|
||||
|
||||
impl Hash for SingleLayoutVariableDescSet {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().internal_object().hash(state);
|
||||
self.device().hash(state);
|
||||
|
@ -48,7 +48,6 @@ impl UnsafeDescriptorSet {
|
||||
/// - Updating a descriptor set obeys synchronization rules that aren't checked here. Once a
|
||||
/// command buffer contains a pointer/reference to a descriptor set, it is illegal to write
|
||||
/// to it.
|
||||
///
|
||||
pub unsafe fn write<'a>(
|
||||
&mut self,
|
||||
layout: &DescriptorSetLayout,
|
||||
|
@ -72,7 +72,6 @@ impl WriteDescriptorSet {
|
||||
}
|
||||
|
||||
/// Write a number of consecutive buffer elements.
|
||||
#[inline]
|
||||
pub fn buffer_array(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
@ -94,7 +93,6 @@ impl WriteDescriptorSet {
|
||||
}
|
||||
|
||||
/// Write a number of consecutive buffer view elements.
|
||||
#[inline]
|
||||
pub fn buffer_view_array(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
@ -116,7 +114,6 @@ impl WriteDescriptorSet {
|
||||
}
|
||||
|
||||
/// Write a number of consecutive image view elements.
|
||||
#[inline]
|
||||
pub fn image_view_array(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
@ -142,7 +139,6 @@ impl WriteDescriptorSet {
|
||||
}
|
||||
|
||||
/// Write a number of consecutive image view and sampler elements.
|
||||
#[inline]
|
||||
pub fn image_view_sampler_array(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
@ -164,7 +160,6 @@ impl WriteDescriptorSet {
|
||||
}
|
||||
|
||||
/// Write a number of consecutive sampler elements.
|
||||
#[inline]
|
||||
pub fn sampler_array(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
@ -949,7 +944,6 @@ impl Error for DescriptorSetUpdateError {
|
||||
}
|
||||
|
||||
impl Display for DescriptorSetUpdateError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::ArrayIndexOutOfBounds {
|
||||
@ -958,66 +952,75 @@ impl Display for DescriptorSetUpdateError {
|
||||
written_count,
|
||||
} => write!(
|
||||
f,
|
||||
"tried to write up to element {} to binding {}, but only {} descriptors are available",
|
||||
"tried to write up to element {} to binding {}, but only {} descriptors are \
|
||||
available",
|
||||
written_count, binding, available_count,
|
||||
),
|
||||
Self::ImageView2dFrom3d { binding, index } => write!(
|
||||
f,
|
||||
"tried to write an image view to binding {} index {} with a 2D type and a 3D underlying image",
|
||||
"tried to write an image view to binding {} index {} with a 2D type and a 3D \
|
||||
underlying image",
|
||||
binding, index,
|
||||
),
|
||||
Self::ImageViewDepthAndStencil { binding, index } => write!(
|
||||
f,
|
||||
"tried to write an image view to binding {} index {} that has both the `depth` and `stencil` aspects",
|
||||
"tried to write an image view to binding {} index {} that has both the `depth` and \
|
||||
`stencil` aspects",
|
||||
binding, index,
|
||||
),
|
||||
Self::ImageViewHasSamplerYcbcrConversion { binding, index } => write!(
|
||||
f,
|
||||
"tried to write an image view to binding {} index {} with an attached sampler YCbCr conversion to binding that does not support it",
|
||||
"tried to write an image view to binding {} index {} with an attached sampler \
|
||||
YCbCr conversion to binding that does not support it",
|
||||
binding, index,
|
||||
),
|
||||
Self::ImageViewIsArrayed { binding, index } => write!(
|
||||
f,
|
||||
"tried to write an image view of an arrayed type to binding {} index {}, but this binding has a descriptor type that does not support arrayed image views",
|
||||
"tried to write an image view of an arrayed type to binding {} index {}, but this \
|
||||
binding has a descriptor type that does not support arrayed image views",
|
||||
binding, index,
|
||||
),
|
||||
Self::ImageViewIncompatibleSampler { binding, index, .. } => write!(
|
||||
f,
|
||||
"tried to write an image view to binding {} index {}, that was not compatible with the sampler that was provided as part of the update or immutably in the layout",
|
||||
"tried to write an image view to binding {} index {}, that was not compatible with \
|
||||
the sampler that was provided as part of the update or immutably in the layout",
|
||||
binding, index,
|
||||
),
|
||||
Self::ImageViewNotIdentitySwizzled { binding, index } => write!(
|
||||
f,
|
||||
"tried to write an image view with non-identity swizzling to binding {} index {}, but this binding has a descriptor type that requires it to be identity swizzled",
|
||||
"tried to write an image view with non-identity swizzling to binding {} index {}, \
|
||||
but this binding has a descriptor type that requires it to be identity swizzled",
|
||||
binding, index,
|
||||
),
|
||||
Self::IncompatibleDescriptorType { binding } => write!(
|
||||
f,
|
||||
"tried to write a resource to binding {} whose type was not compatible with the descriptor type",
|
||||
binding,
|
||||
),
|
||||
Self::InvalidBinding { binding } => write!(
|
||||
f,
|
||||
"tried to write to a nonexistent binding {}",
|
||||
"tried to write a resource to binding {} whose type was not compatible with the \
|
||||
descriptor type",
|
||||
binding,
|
||||
),
|
||||
Self::InvalidBinding { binding } => {
|
||||
write!(f, "tried to write to a nonexistent binding {}", binding,)
|
||||
}
|
||||
Self::MissingUsage {
|
||||
binding,
|
||||
index,
|
||||
usage,
|
||||
} => write!(
|
||||
f,
|
||||
"tried to write a resource to binding {} index {} that did not have the required usage {} enabled",
|
||||
"tried to write a resource to binding {} index {} that did not have the required \
|
||||
usage {} enabled",
|
||||
binding, index, usage,
|
||||
),
|
||||
Self::SamplerHasSamplerYcbcrConversion { binding, index } => write!(
|
||||
f,
|
||||
"tried to write a sampler to binding {} index {} that has an attached sampler YCbCr conversion",
|
||||
"tried to write a sampler to binding {} index {} that has an attached sampler \
|
||||
YCbCr conversion",
|
||||
binding, index,
|
||||
),
|
||||
Self::SamplerIsImmutable { binding } => write!(
|
||||
f,
|
||||
"tried to write a sampler to binding {}, which already contains immutable samplers in the descriptor set layout",
|
||||
"tried to write a sampler to binding {}, which already contains immutable samplers \
|
||||
in the descriptor set layout",
|
||||
binding,
|
||||
),
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ pub struct FeatureRestrictionError {
|
||||
impl Error for FeatureRestrictionError {}
|
||||
|
||||
impl Display for FeatureRestrictionError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
@ -50,7 +49,6 @@ pub enum FeatureRestriction {
|
||||
}
|
||||
|
||||
impl Display for FeatureRestriction {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
FeatureRestriction::NotSupported => {
|
||||
|
@ -611,6 +611,7 @@ impl Device {
|
||||
///
|
||||
/// - `file` must be a handle to external memory that was created outside the Vulkan API.
|
||||
#[cfg_attr(not(unix), allow(unused_variables))]
|
||||
#[inline]
|
||||
pub unsafe fn memory_fd_properties(
|
||||
&self,
|
||||
handle_type: ExternalMemoryHandleType,
|
||||
@ -694,12 +695,13 @@ impl Device {
|
||||
/// This function is not thread-safe. You must not submit anything to any of the queue
|
||||
/// of the device (either explicitly or implicitly, for example with a future's destructor)
|
||||
/// while this function is waiting.
|
||||
///
|
||||
#[inline]
|
||||
pub unsafe fn wait_idle(&self) -> Result<(), OomError> {
|
||||
let fns = self.fns();
|
||||
(fns.v1_0.device_wait_idle)(self.handle)
|
||||
.result()
|
||||
.map_err(VulkanError::from)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -743,7 +745,6 @@ impl PartialEq for Device {
|
||||
impl Eq for Device {}
|
||||
|
||||
impl Hash for Device {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.physical_device.hash(state);
|
||||
@ -781,15 +782,12 @@ pub enum DeviceCreationError {
|
||||
impl Error for DeviceCreationError {}
|
||||
|
||||
impl Display for DeviceCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
Self::InitializationFailed => {
|
||||
write!(
|
||||
f,
|
||||
"failed to create the device for an implementation-specific reason"
|
||||
)
|
||||
}
|
||||
match self {
|
||||
Self::InitializationFailed => write!(
|
||||
f,
|
||||
"failed to create the device for an implementation-specific reason",
|
||||
),
|
||||
Self::OutOfHostMemory => write!(f, "no memory available on the host"),
|
||||
Self::OutOfDeviceMemory => {
|
||||
write!(f, "no memory available on the graphical device")
|
||||
@ -798,24 +796,23 @@ impl Display for DeviceCreationError {
|
||||
Self::TooManyQueuesForFamily => {
|
||||
write!(f, "tried to create too many queues for a given family")
|
||||
}
|
||||
Self::FeatureNotPresent => {
|
||||
write!(
|
||||
f,
|
||||
"some of the requested features are unsupported by the physical device"
|
||||
)
|
||||
}
|
||||
Self::PriorityOutOfRange => {
|
||||
write!(
|
||||
f,
|
||||
"the priority of one of the queues is out of the [0.0; 1.0] range"
|
||||
)
|
||||
}
|
||||
Self::ExtensionNotPresent => {
|
||||
write!(f,"some of the requested device extensions are not supported by the physical device")
|
||||
}
|
||||
Self::TooManyObjects => {
|
||||
write!(f,"you have reached the limit to the number of devices that can be created from the same physical device")
|
||||
}
|
||||
Self::FeatureNotPresent => write!(
|
||||
f,
|
||||
"some of the requested features are unsupported by the physical device",
|
||||
),
|
||||
Self::PriorityOutOfRange => write!(
|
||||
f,
|
||||
"the priority of one of the queues is out of the [0.0; 1.0] range",
|
||||
),
|
||||
Self::ExtensionNotPresent => write!(
|
||||
f,
|
||||
"some of the requested device extensions are not supported by the physical device",
|
||||
),
|
||||
Self::TooManyObjects => write!(
|
||||
f,
|
||||
"you have reached the limit to the number of devices that can be created from the \
|
||||
same physical device",
|
||||
),
|
||||
Self::ExtensionRestrictionNotMet(err) => err.fmt(f),
|
||||
Self::FeatureRestrictionNotMet(err) => err.fmt(f),
|
||||
}
|
||||
@ -823,7 +820,6 @@ impl Display for DeviceCreationError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for DeviceCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
VulkanError::InitializationFailed => Self::InitializationFailed,
|
||||
@ -839,14 +835,12 @@ impl From<VulkanError> for DeviceCreationError {
|
||||
}
|
||||
|
||||
impl From<ExtensionRestrictionError> for DeviceCreationError {
|
||||
#[inline]
|
||||
fn from(err: ExtensionRestrictionError) -> Self {
|
||||
Self::ExtensionRestrictionNotMet(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FeatureRestrictionError> for DeviceCreationError {
|
||||
#[inline]
|
||||
fn from(err: FeatureRestrictionError) -> Self {
|
||||
Self::FeatureRestrictionNotMet(err)
|
||||
}
|
||||
@ -922,7 +916,6 @@ impl Default for QueueCreateInfo {
|
||||
/// # Safety
|
||||
///
|
||||
/// - `device()` must return the correct device.
|
||||
///
|
||||
pub unsafe trait DeviceOwned {
|
||||
/// Returns the device that owns `Self`.
|
||||
fn device(&self) -> &Arc<Device>;
|
||||
@ -933,7 +926,6 @@ where
|
||||
T: Deref,
|
||||
T::Target: DeviceOwned,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
(**self).device()
|
||||
}
|
||||
@ -971,11 +963,9 @@ pub enum MemoryFdPropertiesError {
|
||||
impl Error for MemoryFdPropertiesError {}
|
||||
|
||||
impl Display for MemoryFdPropertiesError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
match self {
|
||||
Self::OutOfHostMemory => write!(f, "no memory available on the host"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -984,7 +974,6 @@ impl Display for MemoryFdPropertiesError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::InvalidExternalHandle => {
|
||||
write!(f, "the provided external handle was not valid")
|
||||
}
|
||||
@ -1000,7 +989,6 @@ impl Display for MemoryFdPropertiesError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for MemoryFdPropertiesError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
VulkanError::OutOfHostMemory => Self::OutOfHostMemory,
|
||||
@ -1011,7 +999,6 @@ impl From<VulkanError> for MemoryFdPropertiesError {
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for MemoryFdPropertiesError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -42,7 +42,7 @@ use std::{
|
||||
|
||||
/// Represents one of the available physical devices on this machine.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use vulkano::{
|
||||
@ -465,6 +465,7 @@ impl PhysicalDevice {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn directfb_presentation_support_unchecked<D>(
|
||||
&self,
|
||||
queue_family_index: u32,
|
||||
@ -481,12 +482,13 @@ impl PhysicalDevice {
|
||||
|
||||
/// Retrieves the external memory properties supported for buffers with a given configuration.
|
||||
///
|
||||
/// Instance API version must be at least 1.1, or the
|
||||
/// [`khr_external_memory_capabilities`](crate::instance::InstanceExtensions::khr_external_memory_capabilities)
|
||||
/// Instance API version must be at least 1.1, or the [`khr_external_memory_capabilities`]
|
||||
/// extension must be enabled on the instance.
|
||||
///
|
||||
/// The results of this function are cached, so that future calls with the same arguments
|
||||
/// do not need to make a call to the Vulkan API again.
|
||||
///
|
||||
/// [`khr_external_memory_capabilities`]: crate::instance::InstanceExtensions::khr_external_memory_capabilities
|
||||
#[inline]
|
||||
pub fn external_buffer_properties(
|
||||
&self,
|
||||
@ -537,6 +539,7 @@ impl PhysicalDevice {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn external_buffer_properties_unchecked(
|
||||
&self,
|
||||
info: ExternalBufferInfo,
|
||||
@ -592,12 +595,13 @@ impl PhysicalDevice {
|
||||
/// Retrieves the external handle properties supported for fences with a given
|
||||
/// configuration.
|
||||
///
|
||||
/// The instance API version must be at least 1.1, or the
|
||||
/// [`khr_external_fence_capabilities`](crate::instance::InstanceExtensions::khr_external_fence_capabilities)
|
||||
/// The instance API version must be at least 1.1, or the [`khr_external_fence_capabilities`]
|
||||
/// extension must be enabled on the instance.
|
||||
///
|
||||
/// The results of this function are cached, so that future calls with the same arguments
|
||||
/// do not need to make a call to the Vulkan API again.
|
||||
///
|
||||
/// [`khr_external_fence_capabilities`]: crate::instance::InstanceExtensions::khr_external_fence_capabilities
|
||||
#[inline]
|
||||
pub fn external_fence_properties(
|
||||
&self,
|
||||
@ -640,6 +644,7 @@ impl PhysicalDevice {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn external_fence_properties_unchecked(
|
||||
&self,
|
||||
info: ExternalFenceInfo,
|
||||
@ -699,11 +704,12 @@ impl PhysicalDevice {
|
||||
/// configuration.
|
||||
///
|
||||
/// The instance API version must be at least 1.1, or the
|
||||
/// [`khr_external_semaphore_capabilities`](crate::instance::InstanceExtensions::khr_external_semaphore_capabilities)
|
||||
/// extension must be enabled on the instance.
|
||||
/// [`khr_external_semaphore_capabilities`] extension must be enabled on the instance.
|
||||
///
|
||||
/// The results of this function are cached, so that future calls with the same arguments
|
||||
/// do not need to make a call to the Vulkan API again.
|
||||
///
|
||||
/// [`khr_external_semaphore_capabilities`]: crate::instance::InstanceExtensions::khr_external_semaphore_capabilities
|
||||
#[inline]
|
||||
pub fn external_semaphore_properties(
|
||||
&self,
|
||||
@ -746,6 +752,7 @@ impl PhysicalDevice {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn external_semaphore_properties_unchecked(
|
||||
&self,
|
||||
info: ExternalSemaphoreInfo,
|
||||
@ -827,6 +834,7 @@ impl PhysicalDevice {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn format_properties_unchecked(&self, format: Format) -> FormatProperties {
|
||||
self.format_properties.get_or_insert(format, |&format| {
|
||||
let mut format_properties2 = ash::vk::FormatProperties2::default();
|
||||
@ -913,6 +921,7 @@ impl PhysicalDevice {
|
||||
unsafe { Ok(self.image_format_properties_unchecked(image_format_info)?) }
|
||||
}
|
||||
|
||||
// FIXME: Shouldn't this be private?
|
||||
pub fn validate_image_format_properties(
|
||||
&self,
|
||||
image_format_info: &ImageFormatInfo,
|
||||
@ -1019,6 +1028,7 @@ impl PhysicalDevice {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn image_format_properties_unchecked(
|
||||
&self,
|
||||
mut image_format_info: ImageFormatInfo,
|
||||
@ -1200,7 +1210,6 @@ impl PhysicalDevice {
|
||||
/// # Safety
|
||||
///
|
||||
/// - `window` must be a valid QNX Screen `_screen_window` handle.
|
||||
#[inline]
|
||||
pub unsafe fn qnx_screen_presentation_support<W>(
|
||||
&self,
|
||||
queue_family_index: u32,
|
||||
@ -1313,6 +1322,7 @@ impl PhysicalDevice {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn sparse_image_format_properties_unchecked(
|
||||
&self,
|
||||
format_info: SparseImageFormatInfo,
|
||||
@ -1465,10 +1475,9 @@ impl PhysicalDevice {
|
||||
/// The results of this function are cached, so that future calls with the same arguments
|
||||
/// do not need to make a call to the Vulkan API again.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the physical device and the surface don't belong to the same instance.
|
||||
#[inline]
|
||||
pub fn surface_capabilities<W>(
|
||||
&self,
|
||||
surface: &Surface<W>,
|
||||
@ -1700,10 +1709,9 @@ impl PhysicalDevice {
|
||||
/// The results of this function are cached, so that future calls with the same arguments
|
||||
/// do not need to make a call to the Vulkan API again.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the physical device and the surface don't belong to the same instance.
|
||||
#[inline]
|
||||
pub fn surface_formats<W>(
|
||||
&self,
|
||||
surface: &Surface<W>,
|
||||
@ -1928,10 +1936,9 @@ impl PhysicalDevice {
|
||||
/// The results of this function are cached, so that future calls with the same arguments
|
||||
/// do not need to make a call to the Vulkan API again.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the physical device and the surface don't belong to the same instance.
|
||||
#[inline]
|
||||
pub fn surface_present_modes<W>(
|
||||
&self,
|
||||
surface: &Surface<W>,
|
||||
@ -2116,6 +2123,7 @@ impl PhysicalDevice {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn tool_properties_unchecked(&self) -> Result<Vec<ToolProperties>, VulkanError> {
|
||||
let fns = self.instance.fns();
|
||||
|
||||
@ -2190,13 +2198,12 @@ impl PhysicalDevice {
|
||||
}
|
||||
}
|
||||
|
||||
/// Queries whether the physical device supports presenting to Wayland surfaces from queues of the
|
||||
/// given queue family.
|
||||
/// Queries whether the physical device supports presenting to Wayland surfaces from queues of
|
||||
/// the given queue family.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `display` must be a valid Wayland `wl_display` handle.
|
||||
#[inline]
|
||||
pub unsafe fn wayland_presentation_support<D>(
|
||||
&self,
|
||||
queue_family_index: u32,
|
||||
@ -2289,6 +2296,7 @@ impl PhysicalDevice {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn win32_presentation_support_unchecked(&self, queue_family_index: u32) -> bool {
|
||||
let fns = self.instance.fns();
|
||||
(fns.khr_win32_surface
|
||||
@ -2303,7 +2311,6 @@ impl PhysicalDevice {
|
||||
/// # Safety
|
||||
///
|
||||
/// - `connection` must be a valid X11 `xcb_connection_t` handle.
|
||||
#[inline]
|
||||
pub unsafe fn xcb_presentation_support<C>(
|
||||
&self,
|
||||
queue_family_index: u32,
|
||||
@ -2368,7 +2375,6 @@ impl PhysicalDevice {
|
||||
/// # Safety
|
||||
///
|
||||
/// - `display` must be a valid Xlib `Display` handle.
|
||||
#[inline]
|
||||
pub unsafe fn xlib_presentation_support<D>(
|
||||
&self,
|
||||
queue_family_index: u32,
|
||||
@ -2447,7 +2453,6 @@ impl PartialEq for PhysicalDevice {
|
||||
impl Eq for PhysicalDevice {}
|
||||
|
||||
impl Hash for PhysicalDevice {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.instance.hash(state);
|
||||
@ -2504,14 +2509,15 @@ impl From<ash::vk::ConformanceVersion> for ConformanceVersion {
|
||||
}
|
||||
|
||||
impl Debug for ConformanceVersion {
|
||||
fn fmt(&self, formatter: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ConformanceVersion {
|
||||
fn fmt(&self, formatter: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
Debug::fmt(self, formatter)
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
Debug::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2716,24 +2722,18 @@ pub enum PhysicalDeviceError {
|
||||
}
|
||||
|
||||
impl Error for PhysicalDeviceError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::VulkanError(ref err) => Some(err),
|
||||
match self {
|
||||
Self::VulkanError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PhysicalDeviceError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::VulkanError(_) => write!(
|
||||
f,
|
||||
"a runtime error occurred",
|
||||
),
|
||||
|
||||
Self::VulkanError(_) => write!(f, "a runtime error occurred"),
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -2742,17 +2742,18 @@ impl Display for PhysicalDeviceError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::NotSupported => write!(
|
||||
f,
|
||||
"the given `SurfaceInfo` values are not supported for the surface by the physical device",
|
||||
"the given `SurfaceInfo` values are not supported for the surface by the physical \
|
||||
device",
|
||||
),
|
||||
Self::QueueFamilyIndexOutOfRange {
|
||||
queue_family_index,
|
||||
queue_family_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the provided `queue_family_index` ({}) was not less than the number of queue families in the physical device ({})",
|
||||
"the provided `queue_family_index` ({}) was not less than the number of queue \
|
||||
families in the physical device ({})",
|
||||
queue_family_index, queue_family_count,
|
||||
),
|
||||
Self::SurfaceNotSupported => write!(
|
||||
@ -2764,14 +2765,12 @@ impl Display for PhysicalDeviceError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for PhysicalDeviceError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
Self::VulkanError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for PhysicalDeviceError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -47,6 +47,7 @@ pub struct Queue {
|
||||
}
|
||||
|
||||
impl Queue {
|
||||
// TODO: Make public
|
||||
#[inline]
|
||||
pub(super) fn from_handle(
|
||||
device: Arc<Device>,
|
||||
@ -110,12 +111,14 @@ unsafe impl VulkanObject for Queue {
|
||||
}
|
||||
|
||||
unsafe impl DeviceOwned for Queue {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
&self.device
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Queue {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
&& self.queue_family_index == other.queue_family_index
|
||||
@ -126,7 +129,6 @@ impl PartialEq for Queue {
|
||||
impl Eq for Queue {}
|
||||
|
||||
impl Hash for Queue {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.id.hash(state);
|
||||
self.queue_family_index.hash(state);
|
||||
@ -158,7 +160,6 @@ impl<'a> QueueGuard<'a> {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn bind_sparse_unchecked(
|
||||
&mut self,
|
||||
bind_infos: impl IntoIterator<Item = BindSparseInfo>,
|
||||
@ -449,15 +450,16 @@ impl<'a> QueueGuard<'a> {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn present_unchecked(
|
||||
&mut self,
|
||||
present_info: PresentInfo,
|
||||
) -> impl ExactSizeIterator<Item = Result<bool, VulkanError>> {
|
||||
let &PresentInfo {
|
||||
let PresentInfo {
|
||||
ref wait_semaphores,
|
||||
ref swapchain_infos,
|
||||
_ne: _,
|
||||
} = &present_info;
|
||||
} = present_info;
|
||||
|
||||
let wait_semaphores_vk: SmallVec<[_; 4]> = wait_semaphores
|
||||
.iter()
|
||||
@ -573,7 +575,6 @@ impl<'a> QueueGuard<'a> {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn submit_unchecked(
|
||||
&mut self,
|
||||
submit_infos: impl IntoIterator<Item = SubmitInfo>,
|
||||
@ -842,8 +843,9 @@ impl<'a> QueueGuard<'a> {
|
||||
|
||||
/// Opens a queue debug label region.
|
||||
///
|
||||
/// The [`ext_debug_utils`](crate::instance::InstanceExtensions::ext_debug_utils) must be
|
||||
/// enabled on the instance.
|
||||
/// The [`ext_debug_utils`] extension must be enabled on the instance.
|
||||
///
|
||||
/// [`ext_debug_utils`]: crate::instance::InstanceExtensions::ext_debug_utils
|
||||
#[inline]
|
||||
pub fn begin_debug_utils_label(
|
||||
&mut self,
|
||||
@ -881,6 +883,7 @@ impl<'a> QueueGuard<'a> {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn begin_debug_utils_label_unchecked(&mut self, label_info: DebugUtilsLabel) {
|
||||
let DebugUtilsLabel {
|
||||
label_name,
|
||||
@ -911,8 +914,8 @@ impl<'a> QueueGuard<'a> {
|
||||
#[inline]
|
||||
pub unsafe fn end_debug_utils_label(&mut self) -> Result<(), QueueError> {
|
||||
self.validate_end_debug_utils_label()?;
|
||||
|
||||
self.end_debug_utils_label_unchecked();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -940,6 +943,7 @@ impl<'a> QueueGuard<'a> {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn end_debug_utils_label_unchecked(&mut self) {
|
||||
let fns = self.queue.device.instance().fns();
|
||||
(fns.ext_debug_utils.queue_end_debug_utils_label_ext)(self.queue.handle);
|
||||
@ -986,6 +990,7 @@ impl<'a> QueueGuard<'a> {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn insert_debug_utils_label_unchecked(&mut self, label_info: DebugUtilsLabel) {
|
||||
let DebugUtilsLabel {
|
||||
label_name,
|
||||
@ -1106,11 +1111,9 @@ impl Error for QueueError {
|
||||
}
|
||||
|
||||
impl Display for QueueError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::VulkanError(_) => write!(f, "a runtime error occurred",),
|
||||
|
||||
Self::VulkanError(_) => write!(f, "a runtime error occurred"),
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -1124,14 +1127,12 @@ impl Display for QueueError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for QueueError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
Self::VulkanError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for QueueError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -50,7 +50,6 @@ pub struct ExtensionRestrictionError {
|
||||
impl Error for ExtensionRestrictionError {}
|
||||
|
||||
impl Display for ExtensionRestrictionError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
@ -73,7 +72,6 @@ pub enum ExtensionRestriction {
|
||||
}
|
||||
|
||||
impl Display for ExtensionRestriction {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
ExtensionRestriction::NotSupported => {
|
||||
|
@ -173,6 +173,7 @@ impl From<Format> for ash::vk::Format {
|
||||
|
||||
// https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap46.html#spirvenv-image-formats
|
||||
impl From<ImageFormat> for Option<Format> {
|
||||
#[inline]
|
||||
fn from(val: ImageFormat) -> Self {
|
||||
match val {
|
||||
ImageFormat::Unknown => None,
|
||||
@ -252,6 +253,7 @@ pub enum ChromaSampling {
|
||||
}
|
||||
|
||||
impl ChromaSampling {
|
||||
#[inline]
|
||||
pub fn subsampled_extent(&self, mut extent: [u32; 3]) -> [u32; 3] {
|
||||
match self {
|
||||
ChromaSampling::Mode444 => (),
|
||||
|
@ -114,6 +114,7 @@ vulkan_bitflags! {
|
||||
}
|
||||
|
||||
impl ImageAspects {
|
||||
#[inline]
|
||||
pub fn iter(&self) -> impl Iterator<Item = ImageAspect> {
|
||||
let Self {
|
||||
color,
|
||||
@ -147,6 +148,7 @@ impl ImageAspects {
|
||||
}
|
||||
|
||||
impl From<ImageAspect> for ImageAspects {
|
||||
#[inline]
|
||||
fn from(aspect: ImageAspect) -> Self {
|
||||
let mut result = Self::empty();
|
||||
|
||||
|
@ -548,15 +548,17 @@ impl AttachmentImage {
|
||||
}))
|
||||
}
|
||||
|
||||
/// Exports posix file descriptor for the allocated memory
|
||||
/// requires `khr_external_memory_fd` and `khr_external_memory` extensions to be loaded.
|
||||
/// Exports posix file descriptor for the allocated memory.
|
||||
/// Requires `khr_external_memory_fd` and `khr_external_memory` extensions to be loaded.
|
||||
#[inline]
|
||||
pub fn export_posix_fd(&self) -> Result<File, DeviceMemoryError> {
|
||||
self.memory
|
||||
.memory()
|
||||
.export_fd(ExternalMemoryHandleType::OpaqueFd)
|
||||
}
|
||||
|
||||
/// Return the size of the allocated memory (used for e.g. with cuda)
|
||||
/// Return the size of the allocated memory (used e.g. with cuda).
|
||||
#[inline]
|
||||
pub fn mem_size(&self) -> DeviceSize {
|
||||
self.memory.memory().allocation_size()
|
||||
}
|
||||
@ -566,7 +568,6 @@ unsafe impl<A> ImageAccess for AttachmentImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> ImageInner<'_> {
|
||||
ImageInner {
|
||||
image: &self.image,
|
||||
@ -577,17 +578,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initial_layout_requirement(&self) -> ImageLayout {
|
||||
self.attachment_layout
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn final_layout_requirement(&self) -> ImageLayout {
|
||||
self.attachment_layout
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
|
||||
Some(ImageDescriptorLayouts {
|
||||
storage_image: ImageLayout::General,
|
||||
@ -597,12 +595,10 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn layout_initialized(&self) {
|
||||
self.initialized.store(true, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_layout_initialized(&self) -> bool {
|
||||
self.initialized.load(Ordering::SeqCst)
|
||||
}
|
||||
@ -618,7 +614,6 @@ unsafe impl<P, A> ImageContent<P> for AttachmentImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn matches_format(&self) -> bool {
|
||||
true // FIXME:
|
||||
}
|
||||
@ -628,7 +623,6 @@ impl<A> PartialEq for AttachmentImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner() == other.inner()
|
||||
}
|
||||
@ -640,7 +634,6 @@ impl<A> Hash for AttachmentImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().hash(state);
|
||||
}
|
||||
|
@ -99,7 +99,6 @@ fn generate_mipmaps<L>(
|
||||
|
||||
impl ImmutableImage {
|
||||
#[deprecated(note = "use ImmutableImage::uninitialized instead")]
|
||||
#[inline]
|
||||
pub fn new(
|
||||
device: Arc<Device>,
|
||||
dimensions: ImageDimensions,
|
||||
@ -117,7 +116,6 @@ impl ImmutableImage {
|
||||
}
|
||||
|
||||
#[deprecated(note = "use ImmutableImage::uninitialized instead")]
|
||||
#[inline]
|
||||
pub fn with_mipmaps(
|
||||
device: Arc<Device>,
|
||||
dimensions: ImageDimensions,
|
||||
@ -149,7 +147,8 @@ impl ImmutableImage {
|
||||
|
||||
/// Builds an uninitialized immutable image.
|
||||
///
|
||||
/// Returns two things: the image, and a special access that should be used for the initial upload to the image.
|
||||
/// Returns two things: the image, and a special access that should be used for the initial
|
||||
/// upload to the image.
|
||||
pub fn uninitialized(
|
||||
device: Arc<Device>,
|
||||
dimensions: ImageDimensions,
|
||||
@ -222,7 +221,6 @@ impl ImmutableImage {
|
||||
}
|
||||
|
||||
/// Construct an ImmutableImage from the contents of `iter`.
|
||||
#[inline]
|
||||
pub fn from_iter<Px, I>(
|
||||
iter: I,
|
||||
dimensions: ImageDimensions,
|
||||
@ -318,7 +316,6 @@ unsafe impl<A> ImageAccess for ImmutableImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> ImageInner<'_> {
|
||||
ImageInner {
|
||||
image: &self.image,
|
||||
@ -329,22 +326,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_layout_initialized(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initial_layout_requirement(&self) -> ImageLayout {
|
||||
self.layout
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn final_layout_requirement(&self) -> ImageLayout {
|
||||
self.layout
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
|
||||
Some(ImageDescriptorLayouts {
|
||||
storage_image: ImageLayout::General,
|
||||
@ -359,7 +352,6 @@ unsafe impl<P, A> ImageContent<P> for ImmutableImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn matches_format(&self) -> bool {
|
||||
true // FIXME:
|
||||
}
|
||||
@ -369,7 +361,6 @@ impl<A> PartialEq for ImmutableImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner() == other.inner()
|
||||
}
|
||||
@ -381,7 +372,6 @@ impl<A> Hash for ImmutableImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().hash(state);
|
||||
}
|
||||
@ -402,22 +392,18 @@ unsafe impl<A> ImageAccess for ImmutableImageInitialization<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> ImageInner<'_> {
|
||||
self.image.inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initial_layout_requirement(&self) -> ImageLayout {
|
||||
ImageLayout::Undefined
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn final_layout_requirement(&self) -> ImageLayout {
|
||||
self.image.layout
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
|
||||
None
|
||||
}
|
||||
@ -427,7 +413,6 @@ impl<A> PartialEq for ImmutableImageInitialization<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner() == other.inner()
|
||||
}
|
||||
@ -439,7 +424,6 @@ impl<A> Hash for ImmutableImageInitialization<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().hash(state);
|
||||
}
|
||||
@ -453,7 +437,6 @@ pub enum ImmutableImageCreationError {
|
||||
}
|
||||
|
||||
impl Error for ImmutableImageCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::ImageCreationError(err) => Some(err),
|
||||
@ -464,7 +447,6 @@ impl Error for ImmutableImageCreationError {
|
||||
}
|
||||
|
||||
impl Display for ImmutableImageCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::ImageCreationError(err) => err.fmt(f),
|
||||
@ -475,28 +457,24 @@ impl Display for ImmutableImageCreationError {
|
||||
}
|
||||
|
||||
impl From<ImageCreationError> for ImmutableImageCreationError {
|
||||
#[inline]
|
||||
fn from(err: ImageCreationError) -> Self {
|
||||
Self::ImageCreationError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DeviceMemoryError> for ImmutableImageCreationError {
|
||||
#[inline]
|
||||
fn from(err: DeviceMemoryError) -> Self {
|
||||
Self::DeviceMemoryAllocationError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for ImmutableImageCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::DeviceMemoryAllocationError(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CommandBufferBeginError> for ImmutableImageCreationError {
|
||||
#[inline]
|
||||
fn from(err: CommandBufferBeginError) -> Self {
|
||||
Self::CommandBufferBeginError(err)
|
||||
}
|
||||
|
@ -12,27 +12,28 @@ use crate::{descriptor_set::layout::DescriptorType, macros::vulkan_enum};
|
||||
vulkan_enum! {
|
||||
/// In-memory layout of the pixel data of an image.
|
||||
///
|
||||
/// The pixel data of a Vulkan image is arranged in a particular way, which is called its *layout*.
|
||||
/// Each image subresource (mipmap level and array layer) in an image can have a different layout,
|
||||
/// but usually the whole image has its data in the same layout. Layouts are abstract in the sense
|
||||
/// that the user does not know the specific details of each layout; the device driver is free to
|
||||
/// implement each layout in the way it sees fit.
|
||||
/// The pixel data of a Vulkan image is arranged in a particular way, which is called its
|
||||
/// *layout*. Each image subresource (mipmap level and array layer) in an image can have a
|
||||
/// different layout, but usually the whole image has its data in the same layout. Layouts are
|
||||
/// abstract in the sense that the user does not know the specific details of each layout; the
|
||||
/// device driver is free to implement each layout in the way it sees fit.
|
||||
///
|
||||
/// The layout of a newly created image is either `Undefined` or `Preinitialized`. Every operation
|
||||
/// that can be performed on an image is only possible with specific layouts, so before the
|
||||
/// operation is performed, the user must perform a *layout transition* on the image. This
|
||||
/// rearranges the pixel data from one layout into another. Layout transitions are performed as part
|
||||
/// of pipeline barriers in a command buffer.
|
||||
/// The layout of a newly created image is either `Undefined` or `Preinitialized`. Every
|
||||
/// operation that can be performed on an image is only possible with specific layouts, so
|
||||
/// before the operation is performed, the user must perform a *layout transition* on the
|
||||
/// image. This rearranges the pixel data from one layout into another. Layout transitions are
|
||||
/// performed as part of pipeline barriers in a command buffer.
|
||||
///
|
||||
/// The `General` layout is compatible with any operation, so layout transitions are never needed.
|
||||
/// However, the other layouts, while more restricted, are usually better optimised for a particular
|
||||
/// type of operation than `General`, so they are usually preferred.
|
||||
/// The `General` layout is compatible with any operation, so layout transitions are never
|
||||
/// needed. However, the other layouts, while more restricted, are usually better optimised for
|
||||
/// a particular type of operation than `General`, so they are usually preferred.
|
||||
///
|
||||
/// Vulkan does not keep track of layouts itself, so it is the responsibility of the user to keep
|
||||
/// track of this information. When performing a layout transition, the previous layout must be
|
||||
/// specified as well. Some operations allow for different layouts, but require the user to specify
|
||||
/// which one. Vulkano helps with this by providing sensible defaults, automatically tracking the
|
||||
/// layout of each image when creating a command buffer, and adding layout transitions where needed.
|
||||
/// Vulkan does not keep track of layouts itself, so it is the responsibility of the user to
|
||||
/// keep track of this information. When performing a layout transition, the previous layout
|
||||
/// must be specified as well. Some operations allow for different layouts, but require the
|
||||
/// user to specify which one. Vulkano helps with this by providing sensible defaults,
|
||||
/// automatically tracking the layout of each image when creating a command buffer, and adding
|
||||
/// layout transitions where needed.
|
||||
#[non_exhaustive]
|
||||
ImageLayout = ImageLayout(i32);
|
||||
|
||||
@ -73,15 +74,15 @@ vulkan_enum! {
|
||||
/// tiling, optimal tiling gives undefined results.
|
||||
Preinitialized = PREINITIALIZED,
|
||||
|
||||
// A combination of `DepthStencilReadOnlyOptimal` for the depth aspect of the image,
|
||||
// and `DepthStencilAttachmentOptimal` for the stencil aspect of the image.
|
||||
/// A combination of `DepthStencilReadOnlyOptimal` for the depth aspect of the image,
|
||||
/// and `DepthStencilAttachmentOptimal` for the stencil aspect of the image.
|
||||
DepthReadOnlyStencilAttachmentOptimal = DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL {
|
||||
api_version: V1_1,
|
||||
device_extensions: [khr_maintenance2],
|
||||
},
|
||||
|
||||
// A combination of `DepthStencilAttachmentOptimal` for the depth aspect of the image,
|
||||
// and `DepthStencilReadOnlyOptimal` for the stencil aspect of the image.
|
||||
/// A combination of `DepthStencilAttachmentOptimal` for the depth aspect of the image,
|
||||
/// and `DepthStencilReadOnlyOptimal` for the stencil aspect of the image.
|
||||
DepthAttachmentStencilReadOnlyOptimal = DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL {
|
||||
api_version: V1_1,
|
||||
device_extensions: [khr_maintenance2],
|
||||
|
@ -379,7 +379,7 @@ impl ImageDimensions {
|
||||
///
|
||||
/// The returned value is always at least 1.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use vulkano::image::ImageDimensions;
|
||||
@ -392,7 +392,6 @@ impl ImageDimensions {
|
||||
///
|
||||
/// assert_eq!(dims.max_mip_levels(), 6);
|
||||
/// ```
|
||||
///
|
||||
#[inline]
|
||||
pub fn max_mip_levels(&self) -> u32 {
|
||||
// This calculates `log2(max(width, height, depth)) + 1` using fast integer operations.
|
||||
@ -413,7 +412,7 @@ impl ImageDimensions {
|
||||
///
|
||||
/// Returns `None` if `level` is superior or equal to `max_mip_levels()`.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use vulkano::image::ImageDimensions;
|
||||
@ -443,11 +442,11 @@ impl ImageDimensions {
|
||||
/// assert_eq!(dims.mip_level_dimensions(11), None);
|
||||
/// ```
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// In debug mode, Panics if `width`, `height` or `depth` is equal to 0. In release, returns
|
||||
/// an unspecified value.
|
||||
/// # Panics
|
||||
///
|
||||
/// - In debug mode, panics if `width`, `height` or `depth` is equal to 0. In release, returns
|
||||
/// an unspecified value.
|
||||
#[inline]
|
||||
pub fn mip_level_dimensions(&self, level: u32) -> Option<ImageDimensions> {
|
||||
if level == 0 {
|
||||
return Some(*self);
|
||||
@ -520,6 +519,7 @@ pub struct ImageSubresourceLayers {
|
||||
}
|
||||
|
||||
impl From<ImageSubresourceLayers> for ash::vk::ImageSubresourceLayers {
|
||||
#[inline]
|
||||
fn from(val: ImageSubresourceLayers) -> Self {
|
||||
Self {
|
||||
aspect_mask: val.aspects.into(),
|
||||
|
@ -52,7 +52,6 @@ where
|
||||
|
||||
impl StorageImage {
|
||||
/// Creates a new image with the given dimensions and format.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
device: Arc<Device>,
|
||||
dimensions: ImageDimensions,
|
||||
@ -206,6 +205,7 @@ impl StorageImage {
|
||||
}
|
||||
|
||||
/// Allows the creation of a simple 2D general purpose image view from `StorageImage`.
|
||||
#[inline]
|
||||
pub fn general_purpose_image_view(
|
||||
queue: Arc<Queue>,
|
||||
size: [u32; 2],
|
||||
@ -226,6 +226,7 @@ impl StorageImage {
|
||||
flags,
|
||||
Some(queue.queue_family_index()),
|
||||
);
|
||||
|
||||
match image_result {
|
||||
Ok(image) => {
|
||||
let image_view = ImageView::new_default(image);
|
||||
@ -238,15 +239,17 @@ impl StorageImage {
|
||||
}
|
||||
}
|
||||
|
||||
/// Exports posix file descriptor for the allocated memory
|
||||
/// requires `khr_external_memory_fd` and `khr_external_memory` extensions to be loaded.
|
||||
/// Exports posix file descriptor for the allocated memory.
|
||||
/// Requires `khr_external_memory_fd` and `khr_external_memory` extensions to be loaded.
|
||||
#[inline]
|
||||
pub fn export_posix_fd(&self) -> Result<File, DeviceMemoryError> {
|
||||
self.memory
|
||||
.memory()
|
||||
.export_fd(ExternalMemoryHandleType::OpaqueFd)
|
||||
}
|
||||
|
||||
/// Return the size of the allocated memory (used for e.g. with cuda)
|
||||
/// Return the size of the allocated memory (used e.g. with cuda).
|
||||
#[inline]
|
||||
pub fn mem_size(&self) -> DeviceSize {
|
||||
self.memory.memory().allocation_size()
|
||||
}
|
||||
@ -265,7 +268,6 @@ unsafe impl<A> ImageAccess for StorageImage<A>
|
||||
where
|
||||
A: MemoryPool,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> ImageInner<'_> {
|
||||
ImageInner {
|
||||
image: &self.image,
|
||||
@ -276,17 +278,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initial_layout_requirement(&self) -> ImageLayout {
|
||||
ImageLayout::General
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn final_layout_requirement(&self) -> ImageLayout {
|
||||
ImageLayout::General
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
|
||||
Some(ImageDescriptorLayouts {
|
||||
storage_image: ImageLayout::General,
|
||||
@ -301,7 +300,6 @@ unsafe impl<P, A> ImageContent<P> for StorageImage<A>
|
||||
where
|
||||
A: MemoryPool,
|
||||
{
|
||||
#[inline]
|
||||
fn matches_format(&self) -> bool {
|
||||
true // FIXME:
|
||||
}
|
||||
@ -311,7 +309,6 @@ impl<A> PartialEq for StorageImage<A>
|
||||
where
|
||||
A: MemoryPool,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner() == other.inner()
|
||||
}
|
||||
@ -323,7 +320,6 @@ impl<A> Hash for StorageImage<A>
|
||||
where
|
||||
A: MemoryPool,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().hash(state);
|
||||
}
|
||||
|
@ -55,22 +55,18 @@ where
|
||||
}
|
||||
|
||||
/// Returns the swapchain this image belongs to.
|
||||
#[inline]
|
||||
pub fn swapchain(&self) -> &Arc<Swapchain<W>> {
|
||||
&self.swapchain
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn my_image(&self) -> ImageInner<'_> {
|
||||
self.swapchain.raw_image(self.image_index).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn layout_initialized(&self) {
|
||||
self.swapchain.image_layout_initialized(self.image_index);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_layout_initialized(&self) -> bool {
|
||||
self.swapchain.is_image_layout_initialized(self.image_index)
|
||||
}
|
||||
@ -86,22 +82,18 @@ unsafe impl<W> ImageAccess for SwapchainImage<W>
|
||||
where
|
||||
W: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> ImageInner<'_> {
|
||||
self.my_image()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initial_layout_requirement(&self) -> ImageLayout {
|
||||
ImageLayout::PresentSrc
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn final_layout_requirement(&self) -> ImageLayout {
|
||||
ImageLayout::PresentSrc
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
|
||||
Some(ImageDescriptorLayouts {
|
||||
storage_image: ImageLayout::General,
|
||||
@ -111,12 +103,10 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn layout_initialized(&self) {
|
||||
self.layout_initialized();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_layout_initialized(&self) -> bool {
|
||||
self.is_layout_initialized()
|
||||
}
|
||||
@ -126,7 +116,6 @@ unsafe impl<P, W> ImageContent<P> for SwapchainImage<W>
|
||||
where
|
||||
W: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn matches_format(&self) -> bool {
|
||||
true // FIXME:
|
||||
}
|
||||
@ -136,7 +125,6 @@ impl<W> PartialEq for SwapchainImage<W>
|
||||
where
|
||||
W: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner() == other.inner()
|
||||
}
|
||||
@ -148,7 +136,6 @@ impl<W> Hash for SwapchainImage<W>
|
||||
where
|
||||
W: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().hash(state);
|
||||
}
|
||||
|
@ -802,6 +802,7 @@ impl UnsafeImage {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn new_unchecked(
|
||||
device: Arc<Device>,
|
||||
create_info: UnsafeImageCreateInfo,
|
||||
@ -932,6 +933,7 @@ impl UnsafeImage {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
handle: ash::vk::Image,
|
||||
@ -1079,6 +1081,7 @@ impl UnsafeImage {
|
||||
}
|
||||
|
||||
/// Returns the memory requirements for this image.
|
||||
#[inline]
|
||||
pub fn memory_requirements(&self) -> MemoryRequirements {
|
||||
let image_memory_requirements_info2 = ash::vk::ImageMemoryRequirementsInfo2 {
|
||||
image: self.handle,
|
||||
@ -1139,6 +1142,7 @@ impl UnsafeImage {
|
||||
}
|
||||
|
||||
/// Returns the sparse memory requirements for this image.
|
||||
#[inline]
|
||||
pub fn sparse_memory_requirements(&self) -> Vec<SparseImageMemoryRequirements> {
|
||||
let device = &self.device;
|
||||
|
||||
@ -1317,6 +1321,7 @@ impl UnsafeImage {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn bind_memory(
|
||||
&self,
|
||||
memory: &DeviceMemory,
|
||||
@ -1347,10 +1352,10 @@ impl UnsafeImage {
|
||||
)
|
||||
.result()
|
||||
.map_err(VulkanError::from)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn range_size(&self) -> DeviceSize {
|
||||
self.range_size
|
||||
}
|
||||
@ -1360,7 +1365,6 @@ impl UnsafeImage {
|
||||
/// In ranges, the subresources are "flattened" to `DeviceSize`, where each index in the range
|
||||
/// is a single array layer. The layers are arranged hierarchically: aspects at the top level,
|
||||
/// with the mip levels in that aspect, and the array layers in that mip level.
|
||||
#[inline]
|
||||
pub(crate) fn iter_ranges(
|
||||
&self,
|
||||
subresource_range: ImageSubresourceRange,
|
||||
@ -1383,7 +1387,6 @@ impl UnsafeImage {
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn range_to_subresources(
|
||||
&self,
|
||||
mut range: Range<DeviceSize>,
|
||||
@ -1450,7 +1453,6 @@ impl UnsafeImage {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn state(&self) -> MutexGuard<'_, ImageState> {
|
||||
self.state.lock()
|
||||
}
|
||||
@ -1596,7 +1598,7 @@ impl UnsafeImage {
|
||||
/// Note that while Vulkan allows querying the array layers other than 0, it is redundant as
|
||||
/// you can easily calculate the position of any layer.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the mipmap level is out of range.
|
||||
///
|
||||
@ -1612,7 +1614,7 @@ impl UnsafeImage {
|
||||
|
||||
/// Same as `color_linear_layout`, except that it retrieves the depth component of the image.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the mipmap level is out of range.
|
||||
///
|
||||
@ -1628,7 +1630,7 @@ impl UnsafeImage {
|
||||
|
||||
/// Same as `color_linear_layout`, except that it retrieves the stencil component of the image.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the mipmap level is out of range.
|
||||
///
|
||||
@ -1645,7 +1647,7 @@ impl UnsafeImage {
|
||||
/// Same as `color_linear_layout`, except that it retrieves layout for the requested YCbCr
|
||||
/// component too if the format is a YCbCr format.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if plane aspect is out of range.
|
||||
/// - Panics if the aspect is not a color or planar aspect.
|
||||
@ -1724,6 +1726,7 @@ unsafe impl VulkanObject for UnsafeImage {
|
||||
}
|
||||
|
||||
unsafe impl DeviceOwned for UnsafeImage {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
&self.device
|
||||
}
|
||||
@ -1739,7 +1742,6 @@ impl PartialEq for UnsafeImage {
|
||||
impl Eq for UnsafeImage {}
|
||||
|
||||
impl Hash for UnsafeImage {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -1851,6 +1853,7 @@ pub struct UnsafeImageCreateInfo {
|
||||
}
|
||||
|
||||
impl Default for UnsafeImageCreateInfo {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
dimensions: ImageDimensions::Dim2d {
|
||||
@ -1997,21 +2000,18 @@ pub enum ImageCreationError {
|
||||
}
|
||||
|
||||
impl Error for ImageCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
ImageCreationError::AllocError(ref err) => Some(err),
|
||||
match self {
|
||||
ImageCreationError::AllocError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ImageCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::AllocError(_) => write!(f, "allocating memory failed"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -2020,139 +2020,133 @@ impl Display for ImageCreationError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::Array2dCompatibleNot3d => {
|
||||
write!(
|
||||
f,
|
||||
"the array_2d_compatible flag was enabled, but the image type was not 3D"
|
||||
)
|
||||
}
|
||||
Self::BlockTexelViewCompatibleNotCompressed => {
|
||||
write!(f, "the block_texel_view_compatible flag was enabled, but the given format was not compressed")
|
||||
}
|
||||
Self::CubeCompatibleNot2d => {
|
||||
write!(
|
||||
f,
|
||||
"the cube_compatible flag was enabled, but the image type was not 2D"
|
||||
)
|
||||
}
|
||||
Self::CubeCompatibleNotEnoughArrayLayers => {
|
||||
write!(f, "the cube_compatible flag was enabled, but the number of array layers was less than 6")
|
||||
}
|
||||
Self::CubeCompatibleNotSquare => {
|
||||
write!(f, "the cube_compatible flag was enabled, but the image dimensions were not square")
|
||||
}
|
||||
Self::CubeCompatibleMultisampling => {
|
||||
write!(
|
||||
f,
|
||||
"the cube_compatible flag was enabled together with multisampling"
|
||||
)
|
||||
}
|
||||
Self::ExternalMemoryInvalidInitialLayout => {
|
||||
write!(f, "one or more external memory handle types were provided, but the initial layout was not `Undefined`")
|
||||
}
|
||||
Self::Array2dCompatibleNot3d => write!(
|
||||
f,
|
||||
"the array_2d_compatible flag was enabled, but the image type was not 3D",
|
||||
),
|
||||
Self::BlockTexelViewCompatibleNotCompressed => write!(
|
||||
f,
|
||||
"the block_texel_view_compatible flag was enabled, but the given format was not \
|
||||
compressed",
|
||||
),
|
||||
Self::CubeCompatibleNot2d => write!(
|
||||
f,
|
||||
"the cube_compatible flag was enabled, but the image type was not 2D",
|
||||
),
|
||||
Self::CubeCompatibleNotEnoughArrayLayers => write!(
|
||||
f,
|
||||
"the cube_compatible flag was enabled, but the number of array layers was less \
|
||||
than 6",
|
||||
),
|
||||
Self::CubeCompatibleNotSquare => write!(
|
||||
f,
|
||||
"the cube_compatible flag was enabled, but the image dimensions were not square",
|
||||
),
|
||||
Self::CubeCompatibleMultisampling => write!(
|
||||
f,
|
||||
"the cube_compatible flag was enabled together with multisampling",
|
||||
),
|
||||
Self::ExternalMemoryInvalidInitialLayout => write!(
|
||||
f,
|
||||
"one or more external memory handle types were provided, but the initial layout \
|
||||
was not `Undefined`",
|
||||
),
|
||||
Self::FormatNotSupported => {
|
||||
write!(f, "the given format was not supported by the device")
|
||||
}
|
||||
Self::FormatUsageNotSupported { .. } => {
|
||||
write!(
|
||||
f,
|
||||
"a requested usage flag was not supported by the given format"
|
||||
)
|
||||
}
|
||||
Self::ImageFormatPropertiesNotSupported => {
|
||||
write!(f, "the image configuration as queried through the `image_format_properties` function was not supported by the device")
|
||||
}
|
||||
Self::MaxArrayLayersExceeded { .. } => {
|
||||
write!(f, "the number of array layers exceeds the maximum supported by the device for this image configuration")
|
||||
}
|
||||
Self::MaxDimensionsExceeded { .. } => {
|
||||
write!(f, "the specified dimensions exceed the maximum supported by the device for this image configuration")
|
||||
}
|
||||
Self::MaxFramebufferDimensionsExceeded { .. } => {
|
||||
write!(f, "the usage included one of the attachment types, and the specified width and height exceeded the `max_framebuffer_width` or `max_framebuffer_height` limits")
|
||||
}
|
||||
Self::MaxMipLevelsExceeded { .. } => {
|
||||
write!(
|
||||
f,
|
||||
"the maximum number of mip levels for the given dimensions has been exceeded"
|
||||
)
|
||||
}
|
||||
Self::MultisampleCubeCompatible => {
|
||||
write!(
|
||||
f,
|
||||
"multisampling was enabled, and the `cube_compatible` flag was set"
|
||||
)
|
||||
}
|
||||
Self::FormatUsageNotSupported { .. } => write!(
|
||||
f,
|
||||
"a requested usage flag was not supported by the given format",
|
||||
),
|
||||
Self::ImageFormatPropertiesNotSupported => write!(
|
||||
f,
|
||||
"the image configuration as queried through the `image_format_properties` function \
|
||||
was not supported by the device",
|
||||
),
|
||||
Self::MaxArrayLayersExceeded { .. } => write!(
|
||||
f,
|
||||
"the number of array layers exceeds the maximum supported by the device for this \
|
||||
image configuration",
|
||||
),
|
||||
Self::MaxDimensionsExceeded { .. } => write!(
|
||||
f,
|
||||
"the specified dimensions exceed the maximum supported by the device for this \
|
||||
image configuration",
|
||||
),
|
||||
Self::MaxFramebufferDimensionsExceeded { .. } => write!(
|
||||
f,
|
||||
"the usage included one of the attachment types, and the specified width and \
|
||||
height exceeded the `max_framebuffer_width` or `max_framebuffer_height` limits",
|
||||
),
|
||||
Self::MaxMipLevelsExceeded { .. } => write!(
|
||||
f,
|
||||
"the maximum number of mip levels for the given dimensions has been exceeded",
|
||||
),
|
||||
Self::MultisampleCubeCompatible => write!(
|
||||
f,
|
||||
"multisampling was enabled, and the `cube_compatible` flag was set",
|
||||
),
|
||||
Self::MultisampleLinearTiling => {
|
||||
write!(f, "multisampling was enabled, and tiling was `Linear`")
|
||||
}
|
||||
Self::MultisampleMultipleMipLevels => {
|
||||
write!(
|
||||
f,
|
||||
"multisampling was enabled, and multiple mip levels were specified"
|
||||
)
|
||||
}
|
||||
Self::MultisampleNot2d => {
|
||||
write!(
|
||||
f,
|
||||
"multisampling was enabled, but the image type was not 2D"
|
||||
)
|
||||
}
|
||||
Self::SampleCountNotSupported { .. } => {
|
||||
write!(
|
||||
f,
|
||||
"the sample count is not supported by the device for this image configuration"
|
||||
)
|
||||
}
|
||||
Self::SharingQueueFamilyIndexOutOfRange { .. } => {
|
||||
write!(f, "the sharing mode was set to `Concurrent`, but one of the specified queue family indices was out of range")
|
||||
}
|
||||
Self::MultisampleMultipleMipLevels => write!(
|
||||
f,
|
||||
"multisampling was enabled, and multiple mip levels were specified",
|
||||
),
|
||||
Self::MultisampleNot2d => write!(
|
||||
f,
|
||||
"multisampling was enabled, but the image type was not 2D",
|
||||
),
|
||||
Self::SampleCountNotSupported { .. } => write!(
|
||||
f,
|
||||
"the sample count is not supported by the device for this image configuration",
|
||||
),
|
||||
Self::SharingQueueFamilyIndexOutOfRange { .. } => write!(
|
||||
f,
|
||||
"the sharing mode was set to `Concurrent`, but one of the specified queue family \
|
||||
indices was out of range",
|
||||
),
|
||||
Self::StencilUsageMismatch {
|
||||
usage: _,
|
||||
stencil_usage: _,
|
||||
} => write!(
|
||||
f,
|
||||
"the provided `usage` and `stencil_usage` have different values for `depth_stencil_attachment` or `transient_attachment`",
|
||||
"the provided `usage` and `stencil_usage` have different values for \
|
||||
`depth_stencil_attachment` or `transient_attachment`",
|
||||
),
|
||||
Self::YcbcrFormatInvalidDimensions => write!(
|
||||
f,
|
||||
"a YCbCr format was given, but the specified width and/or height was not a \
|
||||
multiple of 2 as required by the format's chroma subsampling",
|
||||
),
|
||||
Self::YcbcrFormatMultipleMipLevels => write!(
|
||||
f,
|
||||
"a YCbCr format was given, and multiple mip levels were specified",
|
||||
),
|
||||
Self::YcbcrFormatInvalidDimensions => {
|
||||
write!(f, "a YCbCr format was given, but the specified width and/or height was not a multiple of 2 as required by the format's chroma subsampling")
|
||||
}
|
||||
Self::YcbcrFormatMultipleMipLevels => {
|
||||
write!(
|
||||
f,
|
||||
"a YCbCr format was given, and multiple mip levels were specified"
|
||||
)
|
||||
}
|
||||
Self::YcbcrFormatMultisampling => {
|
||||
write!(f, "a YCbCr format was given, and multisampling was enabled")
|
||||
}
|
||||
Self::YcbcrFormatNot2d => {
|
||||
write!(f, "a YCbCr format was given, but the image type was not 2D")
|
||||
}
|
||||
Self::DirectImageViewCreationFailed(e) => {
|
||||
write!(f, "Image view creation failed {}", e)
|
||||
}
|
||||
Self::DirectImageViewCreationFailed(e) => write!(f, "Image view creation failed {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for ImageCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::AllocError(DeviceMemoryError::OomError(err))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DeviceMemoryError> for ImageCreationError {
|
||||
#[inline]
|
||||
fn from(err: DeviceMemoryError) -> Self {
|
||||
Self::AllocError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for ImageCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => Self::AllocError(err.into()),
|
||||
@ -2163,7 +2157,6 @@ impl From<VulkanError> for ImageCreationError {
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for ImageCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -247,7 +247,6 @@ impl PartialEq for dyn ImageAccess {
|
||||
impl Eq for dyn ImageAccess {}
|
||||
|
||||
impl Hash for dyn ImageAccess {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().hash(state);
|
||||
}
|
||||
@ -274,12 +273,10 @@ unsafe impl<I> ImageAccess for ImageAccessFromUndefinedLayout<I>
|
||||
where
|
||||
I: ImageAccess,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> ImageInner<'_> {
|
||||
self.image.inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initial_layout_requirement(&self) -> ImageLayout {
|
||||
if self.preinitialized {
|
||||
ImageLayout::Preinitialized
|
||||
@ -288,12 +285,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn final_layout_requirement(&self) -> ImageLayout {
|
||||
self.image.final_layout_requirement()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
|
||||
self.image.descriptor_layouts()
|
||||
}
|
||||
@ -303,7 +298,6 @@ impl<I> PartialEq for ImageAccessFromUndefinedLayout<I>
|
||||
where
|
||||
I: ImageAccess,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.inner() == other.inner()
|
||||
}
|
||||
@ -315,7 +309,6 @@ impl<I> Hash for ImageAccessFromUndefinedLayout<I>
|
||||
where
|
||||
I: ImageAccess,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.inner().hash(state);
|
||||
}
|
||||
@ -331,32 +324,26 @@ where
|
||||
T: SafeDeref + Send + Sync,
|
||||
T::Target: ImageAccess,
|
||||
{
|
||||
#[inline]
|
||||
fn inner(&self) -> ImageInner<'_> {
|
||||
(**self).inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initial_layout_requirement(&self) -> ImageLayout {
|
||||
(**self).initial_layout_requirement()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn final_layout_requirement(&self) -> ImageLayout {
|
||||
(**self).final_layout_requirement()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
|
||||
(**self).descriptor_layouts()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn layout_initialized(&self) {
|
||||
(**self).layout_initialized();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_layout_initialized(&self) -> bool {
|
||||
(**self).is_layout_initialized()
|
||||
}
|
||||
|
@ -69,7 +69,6 @@ where
|
||||
/// `stencil`, `plane0`, `plane1` or `plane2`.
|
||||
/// - Panics if `create_info.aspects` contains more more than one aspect, unless `depth` and
|
||||
/// `stencil` are the only aspects selected.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
image: Arc<I>,
|
||||
create_info: ImageViewCreateInfo,
|
||||
@ -468,7 +467,6 @@ where
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn new_unchecked(
|
||||
image: Arc<I>,
|
||||
create_info: ImageViewCreateInfo,
|
||||
@ -557,7 +555,6 @@ where
|
||||
|
||||
/// Creates a default `ImageView`. Equivalent to
|
||||
/// `ImageView::new(image, ImageViewCreateInfo::from_image(image))`.
|
||||
#[inline]
|
||||
pub fn new_default(image: Arc<I>) -> Result<Arc<ImageView<I>>, ImageViewCreationError> {
|
||||
let create_info = ImageViewCreateInfo::from_image(&image);
|
||||
Self::new(image, create_info)
|
||||
@ -569,7 +566,6 @@ where
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `image`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
image: Arc<I>,
|
||||
handle: ash::vk::ImageView,
|
||||
@ -653,7 +649,6 @@ where
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkImageViewCreateInfo.html#_description
|
||||
#[inline]
|
||||
fn get_default_usage(aspects: ImageAspects, image: &UnsafeImage) -> ImageUsage {
|
||||
let has_stencil_aspect = aspects.stencil;
|
||||
let has_non_stencil_aspect = !(ImageAspects {
|
||||
@ -674,7 +669,6 @@ where
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/chap12.html#resources-image-view-format-features
|
||||
#[inline]
|
||||
unsafe fn get_format_features(format: Format, image: &UnsafeImage) -> FormatFeatures {
|
||||
let device = image.device();
|
||||
|
||||
@ -712,7 +706,6 @@ where
|
||||
}
|
||||
|
||||
/// Returns the wrapped image that this image view was created from.
|
||||
#[inline]
|
||||
pub fn image(&self) -> &Arc<I> {
|
||||
&self.image
|
||||
}
|
||||
@ -722,7 +715,6 @@ impl<I> Drop for ImageView<I>
|
||||
where
|
||||
I: ImageAccess + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let device = self.device();
|
||||
@ -738,7 +730,6 @@ where
|
||||
{
|
||||
type Object = ash::vk::ImageView;
|
||||
|
||||
#[inline]
|
||||
fn internal_object(&self) -> ash::vk::ImageView {
|
||||
self.handle
|
||||
}
|
||||
@ -748,7 +739,6 @@ unsafe impl<I> DeviceOwned for ImageView<I>
|
||||
where
|
||||
I: ImageAccess + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.image.inner().image.device()
|
||||
}
|
||||
@ -758,7 +748,6 @@ impl<I> PartialEq for ImageView<I>
|
||||
where
|
||||
I: ImageAccess + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.handle == other.handle && self.device() == other.device()
|
||||
}
|
||||
@ -770,7 +759,6 @@ impl<I> Hash for ImageView<I>
|
||||
where
|
||||
I: ImageAccess + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -981,24 +969,18 @@ pub enum ImageViewCreationError {
|
||||
}
|
||||
|
||||
impl Error for ImageViewCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
ImageViewCreationError::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
ImageViewCreationError::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ImageViewCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::OomError(_) => write!(
|
||||
f,
|
||||
"allocating memory failed",
|
||||
),
|
||||
|
||||
Self::OomError(_) => write!(f, "allocating memory failed",),
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -1007,10 +989,10 @@ impl Display for ImageViewCreationError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::Array2dCompatibleMultipleMipLevels => write!(
|
||||
f,
|
||||
"a 2D image view was requested from a 3D image, but a range of multiple mip levels was specified",
|
||||
"a 2D image view was requested from a 3D image, but a range of multiple mip levels \
|
||||
was specified",
|
||||
),
|
||||
Self::ArrayLayersOutOfRange { .. } => write!(
|
||||
f,
|
||||
@ -1018,35 +1000,37 @@ impl Display for ImageViewCreationError {
|
||||
),
|
||||
Self::BlockTexelViewCompatibleMultipleArrayLayers => write!(
|
||||
f,
|
||||
"the image has the `block_texel_view_compatible` flag, but a range of multiple array layers was specified",
|
||||
"the image has the `block_texel_view_compatible` flag, but a range of multiple \
|
||||
array layers was specified",
|
||||
),
|
||||
Self::BlockTexelViewCompatibleMultipleMipLevels => write!(
|
||||
f,
|
||||
"the image has the `block_texel_view_compatible` flag, but a range of multiple mip levels was specified",
|
||||
"the image has the `block_texel_view_compatible` flag, but a range of multiple mip \
|
||||
levels was specified",
|
||||
),
|
||||
Self::BlockTexelViewCompatibleUncompressedIs3d => write!(
|
||||
f,
|
||||
"the image has the `block_texel_view_compatible` flag, and an uncompressed format was requested, and the image view type was `Dim3d`",
|
||||
"the image has the `block_texel_view_compatible` flag, and an uncompressed format \
|
||||
was requested, and the image view type was `Dim3d`",
|
||||
),
|
||||
Self::FormatChromaSubsamplingInvalidImageDimensions => write!(
|
||||
f,
|
||||
"the requested format has chroma subsampling, but the width and/or height of the image was not a multiple of 2",
|
||||
),
|
||||
Self::FormatNotCompatible => write!(
|
||||
f,
|
||||
"the requested format was not compatible with the image",
|
||||
),
|
||||
Self::FormatNotSupported => write!(
|
||||
f,
|
||||
"the given format was not supported by the device"
|
||||
"the requested format has chroma subsampling, but the width and/or height of the \
|
||||
image was not a multiple of 2",
|
||||
),
|
||||
Self::FormatNotCompatible => {
|
||||
write!(f, "the requested format was not compatible with the image")
|
||||
}
|
||||
Self::FormatNotSupported => {
|
||||
write!(f, "the given format was not supported by the device")
|
||||
}
|
||||
Self::FormatRequiresSamplerYcbcrConversion { .. } => write!(
|
||||
f,
|
||||
"the format requires a sampler YCbCr conversion, but none was provided",
|
||||
),
|
||||
Self::FormatUsageNotSupported { .. } => write!(
|
||||
f,
|
||||
"a requested usage flag was not supported by the given format"
|
||||
"a requested usage flag was not supported by the given format",
|
||||
),
|
||||
Self::ImageAspectsNotCompatible { .. } => write!(
|
||||
f,
|
||||
@ -1058,11 +1042,13 @@ impl Display for ImageViewCreationError {
|
||||
),
|
||||
Self::ImageNotArray2dCompatible => write!(
|
||||
f,
|
||||
"a 2D image view was requested from a 3D image, but the image was not created with the `array_2d_compatible` flag",
|
||||
"a 2D image view was requested from a 3D image, but the image was not created with \
|
||||
the `array_2d_compatible` flag",
|
||||
),
|
||||
Self::ImageNotCubeCompatible => write!(
|
||||
f,
|
||||
"a cube image view type was requested, but the image was not created with the `cube_compatible` flag",
|
||||
"a cube image view type was requested, but the image was not created with the \
|
||||
`cube_compatible` flag",
|
||||
),
|
||||
Self::ImageTypeNotCompatible => write!(
|
||||
f,
|
||||
@ -1078,23 +1064,28 @@ impl Display for ImageViewCreationError {
|
||||
),
|
||||
Self::MultisamplingNot2d => write!(
|
||||
f,
|
||||
"the image has multisampling enabled, but the image view type was not `Dim2d` or `Dim2dArray`",
|
||||
"the image has multisampling enabled, but the image view type was not `Dim2d` or \
|
||||
`Dim2dArray`",
|
||||
),
|
||||
Self::SamplerYcbcrConversionComponentMappingNotIdentity { .. } => write!(
|
||||
f,
|
||||
"sampler YCbCr conversion was enabled, but `component_mapping` was not the identity mapping",
|
||||
"sampler YCbCr conversion was enabled, but `component_mapping` was not the \
|
||||
identity mapping",
|
||||
),
|
||||
Self::TypeCubeArrayNotMultipleOf6ArrayLayers => write!(
|
||||
f,
|
||||
"the `CubeArray` image view type was specified, but the range of array layers did not have a size that is a multiple 6"
|
||||
"the `CubeArray` image view type was specified, but the range of array layers did \
|
||||
not have a size that is a multiple 6",
|
||||
),
|
||||
Self::TypeCubeNot6ArrayLayers => write!(
|
||||
f,
|
||||
"the `Cube` image view type was specified, but the range of array layers did not have a size of 6"
|
||||
"the `Cube` image view type was specified, but the range of array layers did not \
|
||||
have a size of 6",
|
||||
),
|
||||
Self::TypeNonArrayedMultipleArrayLayers => write!(
|
||||
f,
|
||||
"a non-arrayed image view type was specified, but a range of multiple array layers was specified"
|
||||
"a non-arrayed image view type was specified, but a range of multiple array layers \
|
||||
was specified",
|
||||
),
|
||||
Self::UsageNotSupportedByImage {
|
||||
usage: _,
|
||||
@ -1108,14 +1099,12 @@ impl Display for ImageViewCreationError {
|
||||
}
|
||||
|
||||
impl From<OomError> for ImageViewCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> ImageViewCreationError {
|
||||
ImageViewCreationError::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for ImageViewCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> ImageViewCreationError {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => OomError::from(err).into(),
|
||||
@ -1126,7 +1115,6 @@ impl From<VulkanError> for ImageViewCreationError {
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for ImageViewCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
@ -1202,6 +1190,7 @@ pub unsafe trait ImageViewAbstract:
|
||||
fn component_mapping(&self) -> ComponentMapping;
|
||||
|
||||
/// Returns the dimensions of this view.
|
||||
#[inline]
|
||||
fn dimensions(&self) -> ImageDimensions {
|
||||
let subresource_range = self.subresource_range();
|
||||
let array_layers =
|
||||
@ -1262,52 +1251,42 @@ unsafe impl<I> ImageViewAbstract for ImageView<I>
|
||||
where
|
||||
I: ImageAccess + Debug + 'static,
|
||||
{
|
||||
#[inline]
|
||||
fn image(&self) -> Arc<dyn ImageAccess> {
|
||||
self.image.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn component_mapping(&self) -> ComponentMapping {
|
||||
self.component_mapping
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn filter_cubic(&self) -> bool {
|
||||
self.filter_cubic
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn filter_cubic_minmax(&self) -> bool {
|
||||
self.filter_cubic_minmax
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn format(&self) -> Option<Format> {
|
||||
self.format
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn format_features(&self) -> &FormatFeatures {
|
||||
&self.format_features
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sampler_ycbcr_conversion(&self) -> Option<&Arc<SamplerYcbcrConversion>> {
|
||||
self.sampler_ycbcr_conversion.as_ref()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn subresource_range(&self) -> &ImageSubresourceRange {
|
||||
&self.subresource_range
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn usage(&self) -> &ImageUsage {
|
||||
&self.usage
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn view_type(&self) -> ImageViewType {
|
||||
self.view_type
|
||||
}
|
||||
@ -1375,7 +1354,6 @@ impl PartialEq for dyn ImageViewAbstract {
|
||||
impl Eq for dyn ImageViewAbstract {}
|
||||
|
||||
impl Hash for dyn ImageViewAbstract {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.internal_object().hash(state);
|
||||
self.device().hash(state);
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! Note that the vulkano library can also emit messages to warn you about performance issues.
|
||||
//! TODO: ^ that's not the case yet, need to choose whether we keep this idea
|
||||
//!
|
||||
//! # Example
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```
|
||||
//! # use vulkano::instance::Instance;
|
||||
@ -40,7 +40,6 @@
|
||||
//! Note that you must keep the `_callback` object alive for as long as you want your callback to
|
||||
//! be callable. If you don't store the return value of `DebugUtilsMessenger`'s constructor in a
|
||||
//! variable, it will be immediately destroyed and your callback will not work.
|
||||
//!
|
||||
|
||||
use super::Instance;
|
||||
use crate::{macros::vulkan_bitflags, RequirementNotMet, RequiresOneOf, VulkanError, VulkanObject};
|
||||
@ -254,7 +253,6 @@ pub enum DebugUtilsMessengerCreationError {
|
||||
impl Error for DebugUtilsMessengerCreationError {}
|
||||
|
||||
impl Display for DebugUtilsMessengerCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::RequirementNotMet {
|
||||
@ -270,14 +268,12 @@ impl Display for DebugUtilsMessengerCreationError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for DebugUtilsMessengerCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> DebugUtilsMessengerCreationError {
|
||||
panic!("unexpected error: {:?}", err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for DebugUtilsMessengerCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -22,7 +22,7 @@ impl LayerProperties {
|
||||
/// If you want to enable this layer on an instance, you need to pass this value to
|
||||
/// `Instance::new`.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::VulkanLibrary;
|
||||
@ -46,7 +46,7 @@ impl LayerProperties {
|
||||
///
|
||||
/// This description is chosen by the layer itself.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::VulkanLibrary;
|
||||
@ -68,7 +68,7 @@ impl LayerProperties {
|
||||
|
||||
/// Returns the version of Vulkan supported by this layer.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::{Version, VulkanLibrary};
|
||||
@ -90,7 +90,7 @@ impl LayerProperties {
|
||||
///
|
||||
/// The number is chosen by the layer itself. It can be used for bug reports for example.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::VulkanLibrary;
|
||||
|
@ -202,7 +202,7 @@ mod layers;
|
||||
/// > `export VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_api_dump` on Linux if you installed the Vulkan SDK
|
||||
/// > will print the list of raw Vulkan function calls.
|
||||
///
|
||||
/// ## Example
|
||||
/// ## Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use std::{sync::Arc, error::Error};
|
||||
@ -506,7 +506,7 @@ impl Instance {
|
||||
|
||||
/// Returns an iterator that enumerates the physical devices available.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use vulkano::{
|
||||
@ -589,7 +589,6 @@ impl PartialEq for Instance {
|
||||
impl Eq for Instance {}
|
||||
|
||||
impl Hash for Instance {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
}
|
||||
@ -745,17 +744,15 @@ pub enum InstanceCreationError {
|
||||
}
|
||||
|
||||
impl Error for InstanceCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for InstanceCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
@ -764,7 +761,6 @@ impl Display for InstanceCreationError {
|
||||
Self::ExtensionNotPresent => write!(f, "extension not present"),
|
||||
Self::IncompatibleDriver => write!(f, "incompatible driver"),
|
||||
Self::ExtensionRestrictionNotMet(err) => Display::fmt(err, f),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -778,21 +774,18 @@ impl Display for InstanceCreationError {
|
||||
}
|
||||
|
||||
impl From<OomError> for InstanceCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ExtensionRestrictionError> for InstanceCreationError {
|
||||
#[inline]
|
||||
fn from(err: ExtensionRestrictionError) -> Self {
|
||||
Self::ExtensionRestrictionNotMet(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for InstanceCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)),
|
||||
|
@ -151,12 +151,11 @@ pub enum OomError {
|
||||
impl Error for OomError {}
|
||||
|
||||
impl Display for OomError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
match self {
|
||||
OomError::OutOfHostMemory => "no memory available on the host",
|
||||
OomError::OutOfDeviceMemory => "no memory available on the graphical device",
|
||||
}
|
||||
@ -165,7 +164,6 @@ impl Display for OomError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for OomError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> OomError {
|
||||
match err {
|
||||
VulkanError::OutOfHostMemory => OomError::OutOfHostMemory,
|
||||
@ -182,117 +180,79 @@ impl Error for VulkanError {}
|
||||
|
||||
impl Display for VulkanError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
VulkanError::OutOfHostMemory => write!(
|
||||
f,
|
||||
"A host memory allocation has failed.",
|
||||
),
|
||||
VulkanError::OutOfDeviceMemory => write!(
|
||||
f,
|
||||
"A device memory allocation has failed.",
|
||||
),
|
||||
VulkanError::InitializationFailed => write!(
|
||||
f,
|
||||
"Initialization of an object could not be completed for implementation-specific reasons.",
|
||||
),
|
||||
VulkanError::DeviceLost => write!(
|
||||
f,
|
||||
"The logical or physical device has been lost.",
|
||||
),
|
||||
VulkanError::MemoryMapFailed => write!(
|
||||
f,
|
||||
"Mapping of a memory object has failed.",
|
||||
),
|
||||
VulkanError::LayerNotPresent => write!(
|
||||
f,
|
||||
"A requested layer is not present or could not be loaded.",
|
||||
),
|
||||
VulkanError::ExtensionNotPresent => write!(
|
||||
f,
|
||||
"A requested extension is not supported.",
|
||||
),
|
||||
VulkanError::FeatureNotPresent => write!(
|
||||
f,
|
||||
"A requested feature is not supported.",
|
||||
),
|
||||
VulkanError::IncompatibleDriver => write!(
|
||||
f,
|
||||
"The requested version of Vulkan is not supported by the driver or is otherwise incompatible for implementation-specific reasons.",
|
||||
),
|
||||
VulkanError::TooManyObjects => write!(
|
||||
f,
|
||||
"Too many objects of the type have already been created.",
|
||||
),
|
||||
VulkanError::FormatNotSupported => write!(
|
||||
f,
|
||||
"A requested format is not supported on this device.",
|
||||
),
|
||||
VulkanError::FragmentedPool => write!(
|
||||
f,
|
||||
"A pool allocation has failed due to fragmentation of the pool's memory.",
|
||||
),
|
||||
VulkanError::Unknown => write!(
|
||||
f,
|
||||
"An unknown error has occurred; either the application has provided invalid input, or an implementation failure has occurred.",
|
||||
),
|
||||
VulkanError::OutOfPoolMemory => write!(
|
||||
f,
|
||||
"A pool memory allocation has failed.",
|
||||
),
|
||||
VulkanError::InvalidExternalHandle => write!(
|
||||
f,
|
||||
"An external handle is not a valid handle of the specified type.",
|
||||
),
|
||||
VulkanError::Fragmentation => write!(
|
||||
f,
|
||||
"A descriptor pool creation has failed due to fragmentation.",
|
||||
),
|
||||
VulkanError::InvalidOpaqueCaptureAddress => write!(
|
||||
f,
|
||||
"A buffer creation or memory allocation failed because the requested address is not available. A shader group handle assignment failed because the requested shader group handle information is no longer valid.",
|
||||
),
|
||||
VulkanError::IncompatibleDisplay => write!(
|
||||
f,
|
||||
"The display used by a swapchain does not use the same presentable image layout, or is incompatible in a way that prevents sharing an image.",
|
||||
),
|
||||
VulkanError::NotPermitted => write!(
|
||||
f,
|
||||
"A requested operation was not permitted.",
|
||||
),
|
||||
VulkanError::SurfaceLost => write!(
|
||||
f,
|
||||
"A surface is no longer available.",
|
||||
),
|
||||
VulkanError::NativeWindowInUse => write!(
|
||||
f,
|
||||
"The requested window is already in use by Vulkan or another API in a manner which prevents it from being used again.",
|
||||
),
|
||||
VulkanError::OutOfDate => write!(
|
||||
f,
|
||||
"A surface has changed in such a way that it is no longer compatible with the swapchain, and further presentation requests using the swapchain will fail.",
|
||||
),
|
||||
VulkanError::ValidationFailed => write!(
|
||||
f,
|
||||
"Validation failed.",
|
||||
),
|
||||
VulkanError::FullScreenExclusiveModeLost => write!(
|
||||
f,
|
||||
"An operation on a swapchain created with application controlled full-screen access failed as it did not have exclusive full-screen access.",
|
||||
),
|
||||
VulkanError::InvalidDrmFormatModifierPlaneLayout => write!(
|
||||
f,
|
||||
"The requested DRM format modifier plane layout is invalid.",
|
||||
),
|
||||
VulkanError::InvalidShader => write!(
|
||||
f,
|
||||
"One or more shaders failed to compile or link.",
|
||||
),
|
||||
VulkanError::Unnamed(result) => write!(
|
||||
f,
|
||||
"Unnamed error, VkResult value {}",
|
||||
result.as_raw(),
|
||||
),
|
||||
}
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
VulkanError::OutOfHostMemory => "a host memory allocation has failed",
|
||||
VulkanError::OutOfDeviceMemory => "a device memory allocation has failed",
|
||||
VulkanError::InitializationFailed => {
|
||||
"initialization of an object could not be completed for \
|
||||
implementation-specific reasons"
|
||||
}
|
||||
VulkanError::DeviceLost => "the logical or physical device has been lost",
|
||||
VulkanError::MemoryMapFailed => "mapping of a memory object has failed",
|
||||
VulkanError::LayerNotPresent => {
|
||||
"a requested layer is not present or could not be loaded"
|
||||
}
|
||||
VulkanError::ExtensionNotPresent => "a requested extension is not supported",
|
||||
VulkanError::FeatureNotPresent => "a requested feature is not supported",
|
||||
VulkanError::IncompatibleDriver => {
|
||||
"the requested version of Vulkan is not supported by the driver or is \
|
||||
otherwise incompatible for implementation-specific reasons"
|
||||
}
|
||||
VulkanError::TooManyObjects => {
|
||||
"too many objects of the type have already been created"
|
||||
}
|
||||
VulkanError::FormatNotSupported => {
|
||||
"a requested format is not supported on this device"
|
||||
}
|
||||
VulkanError::FragmentedPool => {
|
||||
"a pool allocation has failed due to fragmentation of the pool's memory"
|
||||
}
|
||||
VulkanError::Unknown => {
|
||||
"an unknown error has occurred; either the application has provided invalid \
|
||||
input, or an implementation failure has occurred"
|
||||
}
|
||||
VulkanError::OutOfPoolMemory => "a pool memory allocation has failed",
|
||||
VulkanError::InvalidExternalHandle => {
|
||||
"an external handle is not a valid handle of the specified type"
|
||||
}
|
||||
VulkanError::Fragmentation => {
|
||||
"a descriptor pool creation has failed due to fragmentation"
|
||||
}
|
||||
VulkanError::InvalidOpaqueCaptureAddress => {
|
||||
"a buffer creation or memory allocation failed because the requested address \
|
||||
is not available. A shader group handle assignment failed because the \
|
||||
requested shader group handle information is no longer valid"
|
||||
}
|
||||
VulkanError::IncompatibleDisplay => {
|
||||
"the display used by a swapchain does not use the same presentable image \
|
||||
layout, or is incompatible in a way that prevents sharing an image"
|
||||
}
|
||||
VulkanError::NotPermitted => "a requested operation was not permitted",
|
||||
VulkanError::SurfaceLost => "a surface is no longer available",
|
||||
VulkanError::NativeWindowInUse => {
|
||||
"the requested window is already in use by Vulkan or another API in a manner \
|
||||
which prevents it from being used again"
|
||||
}
|
||||
VulkanError::OutOfDate => {
|
||||
"a surface has changed in such a way that it is no longer compatible with the \
|
||||
swapchain, and further presentation requests using the swapchain will fail"
|
||||
}
|
||||
VulkanError::ValidationFailed => "validation failed",
|
||||
VulkanError::FullScreenExclusiveModeLost => {
|
||||
"an operation on a swapchain created with application controlled full-screen \
|
||||
access failed as it did not have exclusive full-screen access"
|
||||
}
|
||||
VulkanError::InvalidDrmFormatModifierPlaneLayout => {
|
||||
"the requested DRM format modifier plane layout is invalid"
|
||||
}
|
||||
VulkanError::InvalidShader => "one or more shaders failed to compile or link",
|
||||
VulkanError::Unnamed(result) =>
|
||||
return write!(f, "unnamed error, VkResult value {}", result.as_raw()),
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,7 +275,6 @@ pub struct RequiresOneOf {
|
||||
|
||||
impl RequiresOneOf {
|
||||
/// Returns whether there is more than one possible requirement.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.api_version.map_or(0, |_| 1)
|
||||
+ self.features.len()
|
||||
@ -325,7 +284,6 @@ impl RequiresOneOf {
|
||||
}
|
||||
|
||||
impl Display for RequiresOneOf {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
let mut members_written = 0;
|
||||
|
||||
|
@ -53,6 +53,7 @@ impl VulkanLibrary {
|
||||
#[allow(non_snake_case)]
|
||||
fn def_loader_impl() -> Result<Box<dyn Loader>, LoadingError> {
|
||||
let loader = crate::statically_linked_vulkan_loader!();
|
||||
|
||||
Ok(Box::new(loader))
|
||||
}
|
||||
|
||||
@ -177,6 +178,7 @@ impl VulkanLibrary {
|
||||
}
|
||||
|
||||
/// Returns the highest Vulkan version that is supported for instances.
|
||||
#[inline]
|
||||
pub fn api_version(&self) -> Version {
|
||||
self.api_version
|
||||
}
|
||||
@ -205,7 +207,7 @@ impl VulkanLibrary {
|
||||
/// > here is no longer available when you create the `Instance`. This will lead to an error
|
||||
/// > when calling `Instance::new`.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::VulkanLibrary;
|
||||
@ -315,7 +317,6 @@ where
|
||||
T: SafeDeref + Send + Sync,
|
||||
T::Target: Loader,
|
||||
{
|
||||
#[inline]
|
||||
unsafe fn get_instance_proc_addr(
|
||||
&self,
|
||||
instance: ash::vk::Instance,
|
||||
@ -326,7 +327,6 @@ where
|
||||
}
|
||||
|
||||
impl Debug for dyn Loader {
|
||||
#[inline]
|
||||
fn fmt(&self, _f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
Ok(())
|
||||
}
|
||||
@ -416,23 +416,21 @@ pub enum LoadingError {
|
||||
}
|
||||
|
||||
impl Error for LoadingError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
//Self::LibraryLoadFailure(ref err) => Some(err),
|
||||
Self::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
//Self::LibraryLoadFailure(err) => Some(err),
|
||||
Self::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for LoadingError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
match self {
|
||||
Self::LibraryLoadFailure(_) => "failed to load the Vulkan shared library",
|
||||
Self::OomError(_) => "not enough memory available",
|
||||
}
|
||||
@ -441,7 +439,6 @@ impl Display for LoadingError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for LoadingError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)),
|
||||
|
@ -29,7 +29,7 @@ use std::{
|
||||
///
|
||||
/// The destructor of `DeviceMemory` automatically frees the memory.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use vulkano::memory::{DeviceMemory, MemoryAllocateInfo};
|
||||
@ -547,6 +547,7 @@ impl DeviceMemory {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn commitment_unchecked(&self) -> DeviceSize {
|
||||
let mut output: DeviceSize = 0;
|
||||
|
||||
@ -562,7 +563,7 @@ impl DeviceMemory {
|
||||
|
||||
/// Exports the device memory into a Unix file descriptor. The caller owns the returned `File`.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the user requests an invalid handle type for this device memory object.
|
||||
#[inline]
|
||||
@ -617,6 +618,7 @@ impl DeviceMemory {
|
||||
};
|
||||
|
||||
let file = unsafe { std::fs::File::from_raw_fd(fd) };
|
||||
|
||||
Ok(file)
|
||||
}
|
||||
}
|
||||
@ -660,7 +662,6 @@ impl PartialEq for DeviceMemory {
|
||||
impl Eq for DeviceMemory {}
|
||||
|
||||
impl Hash for DeviceMemory {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device.hash(state);
|
||||
@ -709,6 +710,7 @@ impl Default for MemoryAllocateInfo<'static> {
|
||||
|
||||
impl<'d> MemoryAllocateInfo<'d> {
|
||||
/// Returns a `MemoryAllocateInfo` with the specified `dedicated_allocation`.
|
||||
#[inline]
|
||||
pub fn dedicated_allocation(dedicated_allocation: DedicatedAllocation<'d>) -> Self {
|
||||
Self {
|
||||
allocation_size: 0,
|
||||
@ -748,6 +750,7 @@ pub enum MemoryImportInfo {
|
||||
handle_type: ExternalMemoryHandleType,
|
||||
file: File,
|
||||
},
|
||||
|
||||
/// Import memory from a Windows handle.
|
||||
///
|
||||
/// `handle_type` must be either [`ExternalMemoryHandleType::OpaqueWin32`] or
|
||||
@ -777,8 +780,8 @@ vulkan_enum! {
|
||||
/// Describes a handle type used for Vulkan external memory apis. This is **not** just a
|
||||
/// suggestion. Check out vkExternalMemoryHandleTypeFlagBits in the Vulkan spec.
|
||||
///
|
||||
/// If you specify an handle type that doesnt make sense (for example, using a dma-buf handle type
|
||||
/// on Windows) when using this handle, a panic will happen.
|
||||
/// If you specify an handle type that doesnt make sense (for example, using a dma-buf handle
|
||||
/// type on Windows) when using this handle, a panic will happen.
|
||||
#[non_exhaustive]
|
||||
ExternalMemoryHandleType = ExternalMemoryHandleTypeFlags(u32);
|
||||
|
||||
@ -1000,26 +1003,23 @@ pub enum DeviceMemoryError {
|
||||
}
|
||||
|
||||
impl Error for DeviceMemoryError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
Self::MemoryMapError(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
Self::MemoryMapError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for DeviceMemoryError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
Self::TooManyObjects => {
|
||||
write!(f, "the maximum number of allocations has been exceeded")
|
||||
}
|
||||
Self::MemoryMapError(_) => write!(f, "error occurred when mapping the memory"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -1028,22 +1028,25 @@ impl Display for DeviceMemoryError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::DedicatedAllocationSizeMismatch { allocation_size, required_size } => write!(
|
||||
f,
|
||||
"`dedicated_allocation` was `Some`, but the provided `allocation_size` ({}) was different from the required size of the buffer or image ({})",
|
||||
allocation_size, required_size,
|
||||
),
|
||||
Self::HandleTypeNotSupported {
|
||||
handle_type,
|
||||
Self::DedicatedAllocationSizeMismatch {
|
||||
allocation_size,
|
||||
required_size,
|
||||
} => write!(
|
||||
f,
|
||||
"the requested export handle type ({:?}) is not supported for this operation, or was not provided in `export_handle_types` when allocating the memory",
|
||||
"`dedicated_allocation` was `Some`, but the provided `allocation_size` ({}) was \
|
||||
different from the required size of the buffer or image ({})",
|
||||
allocation_size, required_size,
|
||||
),
|
||||
Self::HandleTypeNotSupported { handle_type } => write!(
|
||||
f,
|
||||
"the requested export handle type ({:?}) is not supported for this operation, or \
|
||||
was not provided in `export_handle_types` when allocating the memory",
|
||||
handle_type,
|
||||
),
|
||||
Self::ImportFdHandleTypeNotSupported { handle_type } => write!(
|
||||
f,
|
||||
"the provided `MemoryImportInfo::Fd::handle_type` ({:?}) is not supported for file descriptors",
|
||||
"the provided `MemoryImportInfo::Fd::handle_type` ({:?}) is not supported for file \
|
||||
descriptors",
|
||||
handle_type,
|
||||
),
|
||||
Self::ImportWin32HandleTypeNotSupported { handle_type } => write!(
|
||||
@ -1051,19 +1054,28 @@ impl Display for DeviceMemoryError {
|
||||
"the provided `MemoryImportInfo::Win32::handle_type` ({:?}) is not supported",
|
||||
handle_type,
|
||||
),
|
||||
Self::MemoryTypeHeapSizeExceeded { allocation_size, heap_size } => write!(
|
||||
Self::MemoryTypeHeapSizeExceeded {
|
||||
allocation_size,
|
||||
heap_size,
|
||||
} => write!(
|
||||
f,
|
||||
"the provided `allocation_size` ({}) was greater than the memory type's heap size ({})",
|
||||
"the provided `allocation_size` ({}) was greater than the memory type's heap size \
|
||||
({})",
|
||||
allocation_size, heap_size,
|
||||
),
|
||||
Self::MemoryTypeIndexOutOfRange { memory_type_index, memory_type_count } => write!(
|
||||
Self::MemoryTypeIndexOutOfRange {
|
||||
memory_type_index,
|
||||
memory_type_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the provided `memory_type_index` ({}) was not less than the number of memory types in the physical device ({})",
|
||||
"the provided `memory_type_index` ({}) was not less than the number of memory \
|
||||
types in the physical device ({})",
|
||||
memory_type_index, memory_type_count,
|
||||
),
|
||||
Self::NotLazilyAllocated => write!(
|
||||
f,
|
||||
"the memory type from which this memory was allocated does not have the `lazily_allocated` flag set",
|
||||
"the memory type from which this memory was allocated does not have the \
|
||||
`lazily_allocated` flag set",
|
||||
),
|
||||
|
||||
Self::SpecViolation(u) => {
|
||||
@ -1077,7 +1089,6 @@ impl Display for DeviceMemoryError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for DeviceMemoryError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
e @ VulkanError::OutOfHostMemory | e @ VulkanError::OutOfDeviceMemory => {
|
||||
@ -1090,21 +1101,18 @@ impl From<VulkanError> for DeviceMemoryError {
|
||||
}
|
||||
|
||||
impl From<OomError> for DeviceMemoryError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MemoryMapError> for DeviceMemoryError {
|
||||
#[inline]
|
||||
fn from(err: MemoryMapError) -> Self {
|
||||
Self::MemoryMapError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for DeviceMemoryError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
@ -1118,7 +1126,7 @@ impl From<RequirementNotMet> for DeviceMemoryError {
|
||||
/// In order to access the contents of the allocated memory, you can use the `read` and `write`
|
||||
/// methods.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use vulkano::memory::{DeviceMemory, MappedDeviceMemory, MemoryAllocateInfo};
|
||||
@ -1132,7 +1140,7 @@ impl From<RequirementNotMet> for DeviceMemoryError {
|
||||
/// .iter()
|
||||
/// .position(|t| t.property_flags.host_visible)
|
||||
/// .map(|i| i as u32)
|
||||
/// .unwrap(); // Vk specs guarantee that this can't fail
|
||||
/// .unwrap(); // Vk specs guarantee that this can't fail
|
||||
///
|
||||
/// // Allocates 1KB of memory.
|
||||
/// let memory = DeviceMemory::allocate(
|
||||
@ -1142,7 +1150,8 @@ impl From<RequirementNotMet> for DeviceMemoryError {
|
||||
/// memory_type_index,
|
||||
/// ..Default::default()
|
||||
/// },
|
||||
/// ).unwrap();
|
||||
/// )
|
||||
/// .unwrap();
|
||||
/// let mapped_memory = MappedDeviceMemory::new(memory, 0..1024).unwrap();
|
||||
///
|
||||
/// // Get access to the content.
|
||||
@ -1167,7 +1176,6 @@ pub struct MappedDeviceMemory {
|
||||
//
|
||||
// Vulkan specs, documentation of `vkFreeMemory`:
|
||||
// > If a memory object is mapped at the time it is freed, it is implicitly unmapped.
|
||||
//
|
||||
|
||||
impl MappedDeviceMemory {
|
||||
/// Maps a range of memory to be accessed by the CPU.
|
||||
@ -1248,6 +1256,7 @@ impl MappedDeviceMemory {
|
||||
}
|
||||
|
||||
/// Unmaps the memory. It will no longer be accessible from the CPU.
|
||||
#[inline]
|
||||
pub fn unmap(self) -> DeviceMemory {
|
||||
unsafe {
|
||||
let device = self.memory.device();
|
||||
@ -1278,6 +1287,7 @@ impl MappedDeviceMemory {
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `range` is empty.
|
||||
#[inline]
|
||||
pub unsafe fn invalidate_range(&self, range: Range<DeviceSize>) -> Result<(), MemoryMapError> {
|
||||
if self.coherent {
|
||||
return Ok(());
|
||||
@ -1327,6 +1337,7 @@ impl MappedDeviceMemory {
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `range` is empty.
|
||||
#[inline]
|
||||
pub unsafe fn flush_range(&self, range: Range<DeviceSize>) -> Result<(), MemoryMapError> {
|
||||
self.check_range(range.clone())?;
|
||||
|
||||
@ -1370,6 +1381,7 @@ impl MappedDeviceMemory {
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `range` is empty.
|
||||
#[inline]
|
||||
pub unsafe fn read(&self, range: Range<DeviceSize>) -> Result<&[u8], MemoryMapError> {
|
||||
self.check_range(range.clone())?;
|
||||
|
||||
@ -1399,6 +1411,7 @@ impl MappedDeviceMemory {
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `range` is empty.
|
||||
#[inline]
|
||||
pub unsafe fn write(&self, range: Range<DeviceSize>) -> Result<&mut [u8], MemoryMapError> {
|
||||
self.check_range(range.clone())?;
|
||||
|
||||
@ -1491,41 +1504,42 @@ pub enum MemoryMapError {
|
||||
}
|
||||
|
||||
impl Error for MemoryMapError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for MemoryMapError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
Self::MemoryMapFailed => write!(f, "memory map failed"),
|
||||
Self::NotHostVisible => write!(
|
||||
Self::NotHostVisible => {
|
||||
write!(f, "tried to map memory whose type is not host-visible")
|
||||
}
|
||||
Self::OutOfRange {
|
||||
provided_range,
|
||||
allowed_range,
|
||||
} => write!(
|
||||
f,
|
||||
"tried to map memory whose type is not host-visible",
|
||||
),
|
||||
Self::OutOfRange { ref provided_range, ref allowed_range } => write!(
|
||||
f,
|
||||
"the specified `range` ({:?}) was not contained within the allocated or mapped memory range ({:?})",
|
||||
"the specified `range` ({:?}) was not contained within the allocated or mapped \
|
||||
memory range ({:?})",
|
||||
provided_range, allowed_range,
|
||||
),
|
||||
Self::RangeNotAlignedToAtomSize { ref range, atom_size } => write!(
|
||||
Self::RangeNotAlignedToAtomSize { range, atom_size } => write!(
|
||||
f,
|
||||
"the memory is not host-coherent, and the specified `range` bounds ({:?}) are not a multiple of the `non_coherent_atom_size` device property ({})",
|
||||
"the memory is not host-coherent, and the specified `range` bounds ({:?}) are not \
|
||||
a multiple of the `non_coherent_atom_size` device property ({})",
|
||||
range, atom_size,
|
||||
)
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for MemoryMapError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
e @ VulkanError::OutOfHostMemory | e @ VulkanError::OutOfDeviceMemory => {
|
||||
@ -1538,7 +1552,6 @@ impl From<VulkanError> for MemoryMapError {
|
||||
}
|
||||
|
||||
impl From<OomError> for MemoryMapError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ impl PipelineCache {
|
||||
/// implementation. Therefore you can easily crash your application or the system by passing
|
||||
/// wrong data. Hence why this function is unsafe.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// This example loads a cache from a file, if it exists.
|
||||
/// See [`get_data`](#method.get_data) for how to store the data in a file.
|
||||
@ -61,8 +61,12 @@ impl PipelineCache {
|
||||
/// let mut data = Vec::new();
|
||||
/// if let Ok(_) = file.read_to_end(&mut data) {
|
||||
/// Some(data)
|
||||
/// } else { None }
|
||||
/// } else { None }
|
||||
/// } else {
|
||||
/// None
|
||||
/// }
|
||||
/// } else {
|
||||
/// None
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// let cache = if let Some(data) = data {
|
||||
@ -82,7 +86,7 @@ impl PipelineCache {
|
||||
|
||||
/// Builds a new empty pipeline cache.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use std::sync::Arc;
|
||||
@ -135,7 +139,7 @@ impl PipelineCache {
|
||||
///
|
||||
/// It is `self` that is modified here. The pipeline caches passed as parameter are untouched.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `self` is included in the list of other pipelines.
|
||||
///
|
||||
@ -173,7 +177,7 @@ impl PipelineCache {
|
||||
///
|
||||
/// This data can be stored and then reloaded and passed to `PipelineCache::with_data`.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// This example stores the data of a pipeline cache on the disk.
|
||||
/// See [`with_data`](#method.with_data) for how to reload it.
|
||||
@ -197,6 +201,7 @@ impl PipelineCache {
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn get_data(&self) -> Result<Vec<u8>, OomError> {
|
||||
let fns = self.device.fns();
|
||||
|
||||
|
@ -273,7 +273,6 @@ impl Pipeline for ComputePipeline {
|
||||
}
|
||||
|
||||
impl Debug for ComputePipeline {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(f, "<Vulkan compute pipeline {:?}>", self.handle)
|
||||
}
|
||||
@ -330,25 +329,23 @@ pub enum ComputePipelineCreationError {
|
||||
}
|
||||
|
||||
impl Error for ComputePipelineCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
Self::DescriptorSetLayoutCreationError(ref err) => Some(err),
|
||||
Self::PipelineLayoutCreationError(ref err) => Some(err),
|
||||
Self::IncompatiblePipelineLayout(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
Self::DescriptorSetLayoutCreationError(err) => Some(err),
|
||||
Self::PipelineLayoutCreationError(err) => Some(err),
|
||||
Self::IncompatiblePipelineLayout(err) => Some(err),
|
||||
Self::IncompatibleSpecializationConstants => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ComputePipelineCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
match self {
|
||||
ComputePipelineCreationError::OomError(_) => "not enough memory available",
|
||||
ComputePipelineCreationError::DescriptorSetLayoutCreationError(_) => {
|
||||
"error while creating a descriptor set layout object"
|
||||
@ -360,7 +357,8 @@ impl Display for ComputePipelineCreationError {
|
||||
"the pipeline layout is not compatible with what the shader expects"
|
||||
}
|
||||
ComputePipelineCreationError::IncompatibleSpecializationConstants => {
|
||||
"the provided specialization constants are not compatible with what the shader expects"
|
||||
"the provided specialization constants are not compatible with what the shader \
|
||||
expects"
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -368,35 +366,30 @@ impl Display for ComputePipelineCreationError {
|
||||
}
|
||||
|
||||
impl From<OomError> for ComputePipelineCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> ComputePipelineCreationError {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DescriptorSetLayoutCreationError> for ComputePipelineCreationError {
|
||||
#[inline]
|
||||
fn from(err: DescriptorSetLayoutCreationError) -> Self {
|
||||
Self::DescriptorSetLayoutCreationError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PipelineLayoutCreationError> for ComputePipelineCreationError {
|
||||
#[inline]
|
||||
fn from(err: PipelineLayoutCreationError) -> Self {
|
||||
Self::PipelineLayoutCreationError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PipelineLayoutSupersetError> for ComputePipelineCreationError {
|
||||
#[inline]
|
||||
fn from(err: PipelineLayoutSupersetError) -> Self {
|
||||
Self::IncompatiblePipelineLayout(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for ComputePipelineCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> ComputePipelineCreationError {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)),
|
||||
|
@ -151,6 +151,7 @@ where
|
||||
Fss: SpecializationConstants,
|
||||
{
|
||||
/// Builds the graphics pipeline, using an inferred a pipeline layout.
|
||||
#[inline]
|
||||
pub fn build(
|
||||
self,
|
||||
device: Arc<Device>,
|
||||
@ -264,6 +265,7 @@ where
|
||||
/// Does the same as `build`, except that `build` automatically builds the pipeline layout
|
||||
/// object corresponding to the union of your shaders while this function allows you to specify
|
||||
/// the pipeline layout.
|
||||
#[inline]
|
||||
pub fn with_pipeline_layout(
|
||||
mut self,
|
||||
device: Arc<Device>,
|
||||
@ -293,12 +295,12 @@ where
|
||||
}
|
||||
|
||||
let has = {
|
||||
let &Self {
|
||||
ref render_pass,
|
||||
let Self {
|
||||
render_pass,
|
||||
cache: _,
|
||||
|
||||
ref vertex_shader,
|
||||
ref tessellation_shaders,
|
||||
vertex_shader,
|
||||
tessellation_shaders,
|
||||
geometry_shader: _,
|
||||
fragment_shader: _,
|
||||
|
||||
@ -307,7 +309,7 @@ where
|
||||
tessellation_state: _,
|
||||
viewport_state: _,
|
||||
discard_rectangle_state: _,
|
||||
ref rasterization_state,
|
||||
rasterization_state,
|
||||
multisample_state: _,
|
||||
depth_stencil_state: _,
|
||||
color_blend_state: _,
|
||||
@ -423,24 +425,24 @@ where
|
||||
let physical_device = device.physical_device();
|
||||
let properties = physical_device.properties();
|
||||
|
||||
let &Self {
|
||||
ref render_pass,
|
||||
let Self {
|
||||
render_pass,
|
||||
cache: _,
|
||||
|
||||
ref vertex_shader,
|
||||
ref tessellation_shaders,
|
||||
ref geometry_shader,
|
||||
ref fragment_shader,
|
||||
vertex_shader,
|
||||
tessellation_shaders,
|
||||
geometry_shader,
|
||||
fragment_shader,
|
||||
|
||||
vertex_input_state: _,
|
||||
ref input_assembly_state,
|
||||
ref tessellation_state,
|
||||
ref viewport_state,
|
||||
ref discard_rectangle_state,
|
||||
ref rasterization_state,
|
||||
ref multisample_state,
|
||||
ref depth_stencil_state,
|
||||
ref color_blend_state,
|
||||
input_assembly_state,
|
||||
tessellation_state,
|
||||
viewport_state,
|
||||
discard_rectangle_state,
|
||||
rasterization_state,
|
||||
multisample_state,
|
||||
depth_stencil_state,
|
||||
color_blend_state,
|
||||
} = self;
|
||||
|
||||
let render_pass = render_pass.as_ref().expect("Missing render pass");
|
||||
@ -595,9 +597,9 @@ where
|
||||
// Vertex input state
|
||||
// VUID-VkGraphicsPipelineCreateInfo-pVertexInputState-04910
|
||||
{
|
||||
let &VertexInputState {
|
||||
ref bindings,
|
||||
ref attributes,
|
||||
let VertexInputState {
|
||||
bindings,
|
||||
attributes,
|
||||
} = vertex_input_state;
|
||||
|
||||
// VUID-VkPipelineVertexInputStateCreateInfo-vertexBindingDescriptionCount-00613
|
||||
@ -1406,18 +1408,15 @@ where
|
||||
|
||||
// Discard rectangle state
|
||||
{
|
||||
let &DiscardRectangleState {
|
||||
mode,
|
||||
ref rectangles,
|
||||
} = discard_rectangle_state;
|
||||
let DiscardRectangleState { mode, rectangles } = discard_rectangle_state;
|
||||
|
||||
if device.enabled_extensions().ext_discard_rectangles {
|
||||
// VUID-VkPipelineDiscardRectangleStateCreateInfoEXT-discardRectangleMode-parameter
|
||||
mode.validate_device(device)?;
|
||||
|
||||
let discard_rectangle_count = match *rectangles {
|
||||
PartialStateMode::Dynamic(count) => count,
|
||||
PartialStateMode::Fixed(ref rectangles) => rectangles.len() as u32,
|
||||
let discard_rectangle_count = match rectangles {
|
||||
PartialStateMode::Dynamic(count) => *count,
|
||||
PartialStateMode::Fixed(rectangles) => rectangles.len() as u32,
|
||||
};
|
||||
|
||||
// VUID-VkPipelineDiscardRectangleStateCreateInfoEXT-discardRectangleCount-00582
|
||||
@ -1430,9 +1429,9 @@ where
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let error = match *rectangles {
|
||||
let error = match rectangles {
|
||||
PartialStateMode::Dynamic(_) => true,
|
||||
PartialStateMode::Fixed(ref rectangles) => !rectangles.is_empty(),
|
||||
PartialStateMode::Fixed(rectangles) => !rectangles.is_empty(),
|
||||
};
|
||||
|
||||
if error {
|
||||
@ -1503,8 +1502,8 @@ where
|
||||
// VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-00750
|
||||
// VUID-VkGraphicsPipelineCreateInfo-pViewportState-04892
|
||||
if has.viewport_state {
|
||||
let (viewport_count, scissor_count) = match *viewport_state {
|
||||
ViewportState::Fixed { ref data } => {
|
||||
let (viewport_count, scissor_count) = match viewport_state {
|
||||
ViewportState::Fixed { data } => {
|
||||
let count = data.len() as u32;
|
||||
assert!(count != 0); // TODO: return error?
|
||||
|
||||
@ -1533,7 +1532,7 @@ where
|
||||
(count, count)
|
||||
}
|
||||
ViewportState::FixedViewport {
|
||||
ref viewports,
|
||||
viewports,
|
||||
scissor_count_dynamic,
|
||||
} => {
|
||||
let viewport_count = viewports.len() as u32;
|
||||
@ -1560,7 +1559,7 @@ where
|
||||
}
|
||||
|
||||
// VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136
|
||||
let scissor_count = if scissor_count_dynamic {
|
||||
let scissor_count = if *scissor_count_dynamic {
|
||||
if !(device.api_version() >= Version::V1_3
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
@ -1583,7 +1582,7 @@ where
|
||||
(viewport_count, scissor_count)
|
||||
}
|
||||
ViewportState::FixedScissor {
|
||||
ref scissors,
|
||||
scissors,
|
||||
viewport_count_dynamic,
|
||||
} => {
|
||||
let scissor_count = scissors.len() as u32;
|
||||
@ -1592,7 +1591,7 @@ where
|
||||
assert!(scissor_count != 0); // TODO: return error?
|
||||
|
||||
// VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135
|
||||
let viewport_count = if viewport_count_dynamic {
|
||||
let viewport_count = if *viewport_count_dynamic {
|
||||
if !(device.api_version() >= Version::V1_3
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
@ -1618,7 +1617,7 @@ where
|
||||
|
||||
(viewport_count, scissor_count)
|
||||
}
|
||||
ViewportState::Dynamic {
|
||||
&ViewportState::Dynamic {
|
||||
count,
|
||||
viewport_count_dynamic,
|
||||
scissor_count_dynamic,
|
||||
@ -1764,10 +1763,10 @@ where
|
||||
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06053
|
||||
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06590
|
||||
if has.depth_stencil_state {
|
||||
let &DepthStencilState {
|
||||
ref depth,
|
||||
ref depth_bounds,
|
||||
ref stencil,
|
||||
let DepthStencilState {
|
||||
depth,
|
||||
depth_bounds,
|
||||
stencil,
|
||||
} = depth_stencil_state;
|
||||
|
||||
if let Some(depth_state) = depth {
|
||||
@ -1860,9 +1859,9 @@ where
|
||||
}
|
||||
|
||||
if let Some(depth_bounds_state) = depth_bounds {
|
||||
let &DepthBoundsState {
|
||||
let DepthBoundsState {
|
||||
enable_dynamic,
|
||||
ref bounds,
|
||||
bounds,
|
||||
} = depth_bounds_state;
|
||||
|
||||
// VUID-VkPipelineDepthStencilStateCreateInfo-depthBoundsTestEnable-00598
|
||||
@ -1877,7 +1876,7 @@ where
|
||||
}
|
||||
|
||||
// VUID?
|
||||
if enable_dynamic
|
||||
if *enable_dynamic
|
||||
&& !(device.api_version() >= Version::V1_3
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
@ -1909,10 +1908,10 @@ where
|
||||
}
|
||||
|
||||
if let Some(stencil_state) = stencil {
|
||||
let &StencilState {
|
||||
let StencilState {
|
||||
enable_dynamic,
|
||||
ref front,
|
||||
ref back,
|
||||
front,
|
||||
back,
|
||||
} = stencil_state;
|
||||
|
||||
let has_stencil_attachment = match render_pass {
|
||||
@ -1927,7 +1926,7 @@ where
|
||||
}
|
||||
|
||||
// VUID?
|
||||
if enable_dynamic
|
||||
if *enable_dynamic
|
||||
&& !(device.api_version() >= Version::V1_3
|
||||
|| device.enabled_features().extended_dynamic_state)
|
||||
{
|
||||
@ -2089,9 +2088,9 @@ where
|
||||
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06044
|
||||
// VUID-VkGraphicsPipelineCreateInfo-renderPass-06054
|
||||
if has.color_blend_state {
|
||||
let &ColorBlendState {
|
||||
let ColorBlendState {
|
||||
logic_op,
|
||||
ref attachments,
|
||||
attachments,
|
||||
blend_constants: _,
|
||||
} = color_blend_state;
|
||||
|
||||
@ -2446,9 +2445,9 @@ where
|
||||
{
|
||||
dynamic_state.insert(DynamicState::VertexInput, false);
|
||||
|
||||
let &VertexInputState {
|
||||
ref bindings,
|
||||
ref attributes,
|
||||
let VertexInputState {
|
||||
bindings,
|
||||
attributes,
|
||||
} = vertex_input_state;
|
||||
|
||||
vertex_binding_descriptions_vk.extend(bindings.iter().map(
|
||||
@ -2865,27 +2864,26 @@ where
|
||||
|
||||
// Discard rectangle state
|
||||
if device.enabled_extensions().ext_discard_rectangles {
|
||||
let &DiscardRectangleState {
|
||||
mode,
|
||||
ref rectangles,
|
||||
} = discard_rectangle_state;
|
||||
let DiscardRectangleState { mode, rectangles } = discard_rectangle_state;
|
||||
|
||||
let discard_rectangle_count = match *rectangles {
|
||||
PartialStateMode::Fixed(ref rectangles) => {
|
||||
let discard_rectangle_count = match rectangles {
|
||||
PartialStateMode::Fixed(rectangles) => {
|
||||
dynamic_state.insert(DynamicState::DiscardRectangle, false);
|
||||
discard_rectangles.extend(rectangles.iter().map(|&rect| rect.into()));
|
||||
|
||||
discard_rectangles.len() as u32
|
||||
}
|
||||
PartialStateMode::Dynamic(count) => {
|
||||
dynamic_state.insert(DynamicState::DiscardRectangle, true);
|
||||
count
|
||||
|
||||
*count
|
||||
}
|
||||
};
|
||||
|
||||
let _ = discard_rectangle_state_vk.insert(
|
||||
ash::vk::PipelineDiscardRectangleStateCreateInfoEXT {
|
||||
flags: ash::vk::PipelineDiscardRectangleStateCreateFlagsEXT::empty(),
|
||||
discard_rectangle_mode: mode.into(),
|
||||
discard_rectangle_mode: (*mode).into(),
|
||||
discard_rectangle_count,
|
||||
p_discard_rectangles: discard_rectangles.as_ptr(),
|
||||
..Default::default()
|
||||
@ -2920,8 +2918,8 @@ where
|
||||
|
||||
// Viewport state
|
||||
if has.viewport_state {
|
||||
let (viewport_count, scissor_count) = match *viewport_state {
|
||||
ViewportState::Fixed { ref data } => {
|
||||
let (viewport_count, scissor_count) = match viewport_state {
|
||||
ViewportState::Fixed { data } => {
|
||||
let count = data.len() as u32;
|
||||
viewports_vk.extend(data.iter().map(|e| e.0.clone().into()));
|
||||
dynamic_state.insert(DynamicState::Viewport, false);
|
||||
@ -2934,7 +2932,7 @@ where
|
||||
(count, count)
|
||||
}
|
||||
ViewportState::FixedViewport {
|
||||
ref viewports,
|
||||
viewports,
|
||||
scissor_count_dynamic,
|
||||
} => {
|
||||
let viewport_count = viewports.len() as u32;
|
||||
@ -2942,7 +2940,7 @@ where
|
||||
dynamic_state.insert(DynamicState::Viewport, false);
|
||||
dynamic_state.insert(DynamicState::ViewportWithCount, false);
|
||||
|
||||
let scissor_count = if scissor_count_dynamic {
|
||||
let scissor_count = if *scissor_count_dynamic {
|
||||
dynamic_state.insert(DynamicState::Scissor, false);
|
||||
dynamic_state.insert(DynamicState::ScissorWithCount, true);
|
||||
0
|
||||
@ -2955,15 +2953,15 @@ where
|
||||
(viewport_count, scissor_count)
|
||||
}
|
||||
ViewportState::FixedScissor {
|
||||
ref scissors,
|
||||
scissors,
|
||||
viewport_count_dynamic,
|
||||
} => {
|
||||
let scissor_count = scissors.len() as u32;
|
||||
scissors_vk.extend(scissors.iter().map(|e| (*e).into()));
|
||||
scissors_vk.extend(scissors.iter().map(|&e| e.into()));
|
||||
dynamic_state.insert(DynamicState::Scissor, false);
|
||||
dynamic_state.insert(DynamicState::ScissorWithCount, false);
|
||||
|
||||
let viewport_count = if viewport_count_dynamic {
|
||||
let viewport_count = if *viewport_count_dynamic {
|
||||
dynamic_state.insert(DynamicState::Viewport, false);
|
||||
dynamic_state.insert(DynamicState::ViewportWithCount, true);
|
||||
0
|
||||
@ -2975,7 +2973,7 @@ where
|
||||
|
||||
(viewport_count, scissor_count)
|
||||
}
|
||||
ViewportState::Dynamic {
|
||||
&ViewportState::Dynamic {
|
||||
count,
|
||||
viewport_count_dynamic,
|
||||
scissor_count_dynamic,
|
||||
@ -2983,19 +2981,23 @@ where
|
||||
let viewport_count = if viewport_count_dynamic {
|
||||
dynamic_state.insert(DynamicState::Viewport, false);
|
||||
dynamic_state.insert(DynamicState::ViewportWithCount, true);
|
||||
|
||||
0
|
||||
} else {
|
||||
dynamic_state.insert(DynamicState::Viewport, true);
|
||||
dynamic_state.insert(DynamicState::ViewportWithCount, false);
|
||||
|
||||
count
|
||||
};
|
||||
let scissor_count = if scissor_count_dynamic {
|
||||
dynamic_state.insert(DynamicState::Scissor, false);
|
||||
dynamic_state.insert(DynamicState::ScissorWithCount, true);
|
||||
|
||||
0
|
||||
} else {
|
||||
dynamic_state.insert(DynamicState::Scissor, true);
|
||||
dynamic_state.insert(DynamicState::ScissorWithCount, false);
|
||||
|
||||
count
|
||||
};
|
||||
|
||||
@ -3071,10 +3073,10 @@ where
|
||||
|
||||
// Depth/stencil state
|
||||
if has.depth_stencil_state {
|
||||
let &DepthStencilState {
|
||||
ref depth,
|
||||
ref depth_bounds,
|
||||
ref stencil,
|
||||
let DepthStencilState {
|
||||
depth,
|
||||
depth_bounds,
|
||||
stencil,
|
||||
} = depth_stencil_state;
|
||||
|
||||
let (depth_test_enable, depth_write_enable, depth_compare_op) =
|
||||
@ -3120,12 +3122,12 @@ where
|
||||
|
||||
let (depth_bounds_test_enable, min_depth_bounds, max_depth_bounds) =
|
||||
if let Some(depth_bounds_state) = depth_bounds {
|
||||
let &DepthBoundsState {
|
||||
let DepthBoundsState {
|
||||
enable_dynamic,
|
||||
ref bounds,
|
||||
bounds,
|
||||
} = depth_bounds_state;
|
||||
|
||||
if enable_dynamic {
|
||||
if *enable_dynamic {
|
||||
dynamic_state.insert(DynamicState::DepthBoundsTestEnable, true);
|
||||
} else {
|
||||
dynamic_state.insert(DynamicState::DepthBoundsTestEnable, false);
|
||||
@ -3148,13 +3150,13 @@ where
|
||||
};
|
||||
|
||||
let (stencil_test_enable, front, back) = if let Some(stencil_state) = stencil {
|
||||
let &StencilState {
|
||||
let StencilState {
|
||||
enable_dynamic,
|
||||
ref front,
|
||||
ref back,
|
||||
front,
|
||||
back,
|
||||
} = stencil_state;
|
||||
|
||||
if enable_dynamic {
|
||||
if *enable_dynamic {
|
||||
dynamic_state.insert(DynamicState::StencilTestEnable, true);
|
||||
} else {
|
||||
dynamic_state.insert(DynamicState::StencilTestEnable, false);
|
||||
@ -3501,6 +3503,7 @@ where
|
||||
)
|
||||
.result()
|
||||
.map_err(VulkanError::from)?;
|
||||
|
||||
output.assume_init()
|
||||
};
|
||||
|
||||
@ -3530,7 +3533,6 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
|
||||
/// Sets the vertex shader to use.
|
||||
// TODO: correct specialization constants
|
||||
#[inline]
|
||||
pub fn vertex_shader<'vs2, Vss2>(
|
||||
self,
|
||||
shader: EntryPoint<'vs2>,
|
||||
@ -3562,7 +3564,6 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
|
||||
/// Sets the tessellation shaders to use.
|
||||
// TODO: correct specialization constants
|
||||
#[inline]
|
||||
pub fn tessellation_shaders<'tcs2, 'tes2, Tcss2, Tess2>(
|
||||
self,
|
||||
control_shader: EntryPoint<'tcs2>,
|
||||
@ -3600,7 +3601,6 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
|
||||
/// Sets the geometry shader to use.
|
||||
// TODO: correct specialization constants
|
||||
#[inline]
|
||||
pub fn geometry_shader<'gs2, Gss2>(
|
||||
self,
|
||||
shader: EntryPoint<'gs2>,
|
||||
@ -3634,7 +3634,6 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
///
|
||||
/// The fragment shader is run once for each pixel that is covered by each primitive.
|
||||
// TODO: correct specialization constants
|
||||
#[inline]
|
||||
pub fn fragment_shader<'fs2, Fss2>(
|
||||
self,
|
||||
shader: EntryPoint<'fs2>,
|
||||
@ -3667,7 +3666,6 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
/// Sets the vertex input state.
|
||||
///
|
||||
/// The default value is [`VertexInputState::default()`].
|
||||
#[inline]
|
||||
pub fn vertex_input_state<T>(
|
||||
self,
|
||||
vertex_input_state: T,
|
||||
@ -3793,7 +3791,6 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
/// You will most likely need to explicitly specify the template parameter to the type of a
|
||||
/// vertex.
|
||||
#[deprecated(since = "0.27.0", note = "Use `vertex_input_state` instead")]
|
||||
#[inline]
|
||||
pub fn vertex_input_single_buffer<V: Vertex>(
|
||||
self,
|
||||
) -> GraphicsPipelineBuilder<
|
||||
@ -3942,7 +3939,6 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
/// Sets the viewports to some value, and the scissor boxes to boxes that always cover the
|
||||
/// whole viewport.
|
||||
#[deprecated(since = "0.27.0", note = "Use `viewport_state` instead")]
|
||||
#[inline]
|
||||
pub fn viewports<I>(self, viewports: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = Viewport>,
|
||||
@ -3952,7 +3948,6 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
|
||||
/// Sets the characteristics of viewports and scissor boxes in advance.
|
||||
#[deprecated(since = "0.27.0", note = "Use `viewport_state` instead")]
|
||||
#[inline]
|
||||
pub fn viewports_scissors<I>(mut self, viewports: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = (Viewport, Scissor)>,
|
||||
@ -3966,7 +3961,6 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
/// Sets the scissor boxes to some values, and viewports to dynamic. The viewports will
|
||||
/// need to be set before drawing.
|
||||
#[deprecated(since = "0.27.0", note = "Use `viewport_state` instead")]
|
||||
#[inline]
|
||||
pub fn viewports_dynamic_scissors_fixed<I>(mut self, scissors: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = Scissor>,
|
||||
@ -3993,7 +3987,6 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
/// Sets the viewports to some values, and scissor boxes to dynamic. The scissor boxes will
|
||||
/// need to be set before drawing.
|
||||
#[deprecated(since = "0.27.0", note = "Use `viewport_state` instead")]
|
||||
#[inline]
|
||||
pub fn viewports_fixed_scissors_dynamic<I>(mut self, viewports: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = Viewport>,
|
||||
@ -4152,10 +4145,9 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
///
|
||||
/// Sample shading is disabled by default.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `min_fract` is not between 0.0 and 1.0.
|
||||
///
|
||||
#[deprecated(since = "0.27.0", note = "Use `multisample_state` instead")]
|
||||
#[inline]
|
||||
pub fn sample_shading_enabled(mut self, min_fract: f32) -> Self {
|
||||
@ -4256,7 +4248,6 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
}
|
||||
|
||||
#[deprecated(since = "0.27.0", note = "Use `color_blend_state` instead")]
|
||||
#[inline]
|
||||
pub fn blend_individual<I>(mut self, blend: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = AttachmentBlend>,
|
||||
@ -4336,7 +4327,6 @@ impl<'vs, 'tcs, 'tes, 'gs, 'fs, Vdef, Vss, Tcss, Tess, Gss, Fss>
|
||||
}
|
||||
|
||||
/// Sets the render pass subpass to use.
|
||||
#[inline]
|
||||
pub fn render_pass(self, render_pass: impl Into<PipelineRenderPassType>) -> Self {
|
||||
GraphicsPipelineBuilder {
|
||||
render_pass: Some(render_pass.into()),
|
||||
|
@ -197,23 +197,21 @@ pub enum GraphicsPipelineCreationError {
|
||||
}
|
||||
|
||||
impl Error for GraphicsPipelineCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
Self::PipelineLayoutCreationError(ref err) => Some(err),
|
||||
Self::IncompatiblePipelineLayout(ref err) => Some(err),
|
||||
Self::ShaderStagesMismatch(ref err) => Some(err),
|
||||
Self::IncompatibleVertexDefinition(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
Self::PipelineLayoutCreationError(err) => Some(err),
|
||||
Self::IncompatiblePipelineLayout(err) => Some(err),
|
||||
Self::ShaderStagesMismatch(err) => Some(err),
|
||||
Self::IncompatibleVertexDefinition(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for GraphicsPipelineCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
match self {
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -222,7 +220,6 @@ impl Display for GraphicsPipelineCreationError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::ColorAttachmentFormatBlendNotSupported { attachment_index } => write!(
|
||||
f,
|
||||
"color attachment {} has a format that does not support blending",
|
||||
@ -243,7 +240,8 @@ impl Display for GraphicsPipelineCreationError {
|
||||
),
|
||||
Self::FragmentShaderRenderPassIncompatible => write!(
|
||||
f,
|
||||
"the output of the fragment shader is not compatible with what the render pass subpass expects",
|
||||
"the output of the fragment shader is not compatible with what the render pass \
|
||||
subpass expects",
|
||||
),
|
||||
Self::IncompatiblePipelineLayout(_) => write!(
|
||||
f,
|
||||
@ -251,7 +249,8 @@ impl Display for GraphicsPipelineCreationError {
|
||||
),
|
||||
Self::IncompatibleSpecializationConstants => write!(
|
||||
f,
|
||||
"the provided specialization constants are not compatible with what the shader expects",
|
||||
"the provided specialization constants are not compatible with what the shader \
|
||||
expects",
|
||||
),
|
||||
Self::IncompatibleVertexDefinition(_) => write!(
|
||||
f,
|
||||
@ -259,19 +258,21 @@ impl Display for GraphicsPipelineCreationError {
|
||||
),
|
||||
Self::InvalidPrimitiveTopology => write!(
|
||||
f,
|
||||
"trying to use a patch list without a tessellation shader, or a non-patch-list with a tessellation shader",
|
||||
"trying to use a patch list without a tessellation shader, or a non-patch-list \
|
||||
with a tessellation shader",
|
||||
),
|
||||
Self::InvalidNumPatchControlPoints => write!(
|
||||
f,
|
||||
"patch_control_points was not greater than 0 and less than or equal to the max_tessellation_patch_size limit",
|
||||
"patch_control_points was not greater than 0 and less than or equal to the \
|
||||
max_tessellation_patch_size limit",
|
||||
),
|
||||
Self::MaxDiscardRectanglesExceeded { .. } => write!(
|
||||
f,
|
||||
"the maximum number of discard rectangles has been exceeded",
|
||||
),
|
||||
Self::MaxMultiviewViewCountExceeded { .. } => {
|
||||
write!(f, "the `max_multiview_view_count` limit has been exceeded",)
|
||||
},
|
||||
write!(f, "the `max_multiview_view_count` limit has been exceeded")
|
||||
}
|
||||
Self::MaxVertexAttribDivisorExceeded { .. } => write!(
|
||||
f,
|
||||
"the maximum value for the instance rate divisor has been exceeded",
|
||||
@ -284,29 +285,29 @@ impl Display for GraphicsPipelineCreationError {
|
||||
f,
|
||||
"the maximum offset for a vertex attribute has been exceeded",
|
||||
),
|
||||
Self::MaxVertexInputBindingsExceeded { .. } => write!(
|
||||
f,
|
||||
"the maximum number of vertex sources has been exceeded",
|
||||
),
|
||||
Self::MaxVertexInputBindingsExceeded { .. } => {
|
||||
write!(f, "the maximum number of vertex sources has been exceeded")
|
||||
}
|
||||
Self::MaxVertexInputBindingStrideExceeded { .. } => write!(
|
||||
f,
|
||||
"the maximum stride value for vertex input (ie. the distance between two vertex elements) has been exceeded",
|
||||
),
|
||||
Self::MaxViewportsExceeded { .. } => write!(
|
||||
f,
|
||||
"the maximum number of viewports has been exceeded",
|
||||
),
|
||||
Self::MaxViewportDimensionsExceeded => write!(
|
||||
f,
|
||||
"the maximum dimensions of viewports has been exceeded",
|
||||
"the maximum stride value for vertex input (ie. the distance between two vertex \
|
||||
elements) has been exceeded",
|
||||
),
|
||||
Self::MaxViewportsExceeded { .. } => {
|
||||
write!(f, "the maximum number of viewports has been exceeded")
|
||||
}
|
||||
Self::MaxViewportDimensionsExceeded => {
|
||||
write!(f, "the maximum dimensions of viewports has been exceeded")
|
||||
}
|
||||
Self::MismatchBlendingAttachmentsCount => write!(
|
||||
f,
|
||||
"the number of attachments specified in the blending does not match the number of attachments in the subpass",
|
||||
"the number of attachments specified in the blending does not match the number of \
|
||||
attachments in the subpass",
|
||||
),
|
||||
Self::MultisampleRasterizationSamplesMismatch => write!(
|
||||
f,
|
||||
"the provided `rasterization_samples` does not match the number of samples of the render subpass",
|
||||
"the provided `rasterization_samples` does not match the number of samples of the \
|
||||
render subpass",
|
||||
),
|
||||
Self::NoDepthAttachment => write!(
|
||||
f,
|
||||
@ -316,30 +317,25 @@ impl Display for GraphicsPipelineCreationError {
|
||||
f,
|
||||
"the stencil attachment of the render pass does not match the stencil test",
|
||||
),
|
||||
Self::OomError(_) => write!(
|
||||
f,
|
||||
"not enough memory available",
|
||||
),
|
||||
Self::DescriptorSetLayoutCreationError(_) => write!(
|
||||
f,
|
||||
"error while creating a descriptor set layout object",
|
||||
),
|
||||
Self::PipelineLayoutCreationError(_) => write!(
|
||||
f,
|
||||
"error while creating the pipeline layout object",
|
||||
),
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
Self::DescriptorSetLayoutCreationError(_) => {
|
||||
write!(f, "error while creating a descriptor set layout object")
|
||||
}
|
||||
Self::PipelineLayoutCreationError(_) => {
|
||||
write!(f, "error while creating the pipeline layout object")
|
||||
}
|
||||
Self::ShaderStagesMismatch(_) => write!(
|
||||
f,
|
||||
"the output interface of one shader and the input interface of the next shader do not match",
|
||||
"the output interface of one shader and the input interface of the next shader do \
|
||||
not match",
|
||||
),
|
||||
Self::StencilAttachmentFormatUsageNotSupported => write!(
|
||||
f,
|
||||
"the stencil attachment has a format that does not support that usage",
|
||||
),
|
||||
Self::StrictLinesNotSupported => write!(
|
||||
f,
|
||||
"the strict_lines device property was false",
|
||||
),
|
||||
Self::StrictLinesNotSupported => {
|
||||
write!(f, "the strict_lines device property was false")
|
||||
}
|
||||
Self::TopologyNotMatchingGeometryShader => write!(
|
||||
f,
|
||||
"the primitives topology does not match what the geometry shader expects",
|
||||
@ -350,77 +346,69 @@ impl Display for GraphicsPipelineCreationError {
|
||||
attribute_type,
|
||||
} => write!(
|
||||
f,
|
||||
"the type of the shader input variable at location {} ({:?}) is not compatible with the format of the corresponding vertex input attribute ({:?})",
|
||||
"the type of the shader input variable at location {} ({:?}) is not compatible \
|
||||
with the format of the corresponding vertex input attribute ({:?})",
|
||||
location, shader_type, attribute_type,
|
||||
),
|
||||
Self::VertexInputAttributeInvalidBinding { location, binding } => write!(
|
||||
f,
|
||||
"the binding number {} specified by vertex input attribute location {} does not exist in the provided list of binding descriptions",
|
||||
"the binding number {} specified by vertex input attribute location {} does not \
|
||||
exist in the provided list of binding descriptions",
|
||||
binding, location,
|
||||
),
|
||||
Self::VertexInputAttributeMissing { location } => write!(
|
||||
f,
|
||||
"the vertex shader expects an input variable at location {}, but no vertex input attribute exists for that location",
|
||||
"the vertex shader expects an input variable at location {}, but no vertex input \
|
||||
attribute exists for that location",
|
||||
location,
|
||||
),
|
||||
Self::VertexInputAttributeUnsupportedFormat { location, format } => write!(
|
||||
f,
|
||||
"the format {:?} specified by vertex input attribute location {} is not supported for vertex buffers",
|
||||
"the format {:?} specified by vertex input attribute location {} is not supported \
|
||||
for vertex buffers",
|
||||
format, location,
|
||||
),
|
||||
Self::ViewportBoundsExceeded => write!(
|
||||
f,
|
||||
"the minimum or maximum bounds of viewports have been exceeded",
|
||||
),
|
||||
Self::WrongShaderType => write!(
|
||||
f,
|
||||
"the wrong type of shader has been passed",
|
||||
),
|
||||
Self::WrongStencilState => write!(
|
||||
f,
|
||||
"the requested stencil test is invalid",
|
||||
),
|
||||
Self::WrongShaderType => write!(f, "the wrong type of shader has been passed"),
|
||||
Self::WrongStencilState => write!(f, "the requested stencil test is invalid"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for GraphicsPipelineCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> GraphicsPipelineCreationError {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DescriptorSetLayoutCreationError> for GraphicsPipelineCreationError {
|
||||
#[inline]
|
||||
fn from(err: DescriptorSetLayoutCreationError) -> Self {
|
||||
Self::DescriptorSetLayoutCreationError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PipelineLayoutCreationError> for GraphicsPipelineCreationError {
|
||||
#[inline]
|
||||
fn from(err: PipelineLayoutCreationError) -> Self {
|
||||
Self::PipelineLayoutCreationError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PipelineLayoutSupersetError> for GraphicsPipelineCreationError {
|
||||
#[inline]
|
||||
fn from(err: PipelineLayoutSupersetError) -> Self {
|
||||
Self::IncompatiblePipelineLayout(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IncompatibleVertexDefinitionError> for GraphicsPipelineCreationError {
|
||||
#[inline]
|
||||
fn from(err: IncompatibleVertexDefinitionError) -> Self {
|
||||
Self::IncompatibleVertexDefinition(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for GraphicsPipelineCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)),
|
||||
@ -431,7 +419,6 @@ impl From<VulkanError> for GraphicsPipelineCreationError {
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for GraphicsPipelineCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -183,7 +183,6 @@ pub enum PrimitiveTopologyClass {
|
||||
|
||||
impl PrimitiveTopologyClass {
|
||||
/// Returns a representative example of this topology class.
|
||||
#[inline]
|
||||
pub(crate) fn example(&self) -> PrimitiveTopology {
|
||||
match self {
|
||||
Self::Point => PrimitiveTopology::PointList,
|
||||
|
@ -123,6 +123,7 @@ pub struct GraphicsPipeline {
|
||||
impl GraphicsPipeline {
|
||||
/// Starts the building process of a graphics pipeline. Returns a builder object that you can
|
||||
/// fill with the various parameters.
|
||||
#[inline]
|
||||
pub fn start() -> GraphicsPipelineBuilder<
|
||||
'static,
|
||||
'static,
|
||||
@ -155,7 +156,8 @@ impl GraphicsPipeline {
|
||||
///
|
||||
/// `None` is returned if the pipeline does not contain this shader.
|
||||
///
|
||||
/// Compatibility note: `()` is temporary, it will be replaced with something else in the future.
|
||||
/// Compatibility note: `()` is temporary, it will be replaced with something else in the
|
||||
/// future.
|
||||
// TODO: ^ implement and make this public
|
||||
#[inline]
|
||||
pub(crate) fn shader(&self, stage: ShaderStage) -> Option<()> {
|
||||
@ -230,11 +232,13 @@ impl GraphicsPipeline {
|
||||
///
|
||||
/// `None` is returned if the pipeline does not contain this state. Previously set dynamic
|
||||
/// state is not disturbed when binding it.
|
||||
#[inline]
|
||||
pub fn dynamic_state(&self, state: DynamicState) -> Option<bool> {
|
||||
self.dynamic_state.get(&state).copied()
|
||||
}
|
||||
|
||||
/// Returns all potentially dynamic states in the pipeline, and whether they are dynamic or not.
|
||||
#[inline]
|
||||
pub fn dynamic_states(&self) -> impl ExactSizeIterator<Item = (DynamicState, bool)> + '_ {
|
||||
self.dynamic_state.iter().map(|(k, v)| (*k, *v))
|
||||
}
|
||||
@ -265,7 +269,6 @@ unsafe impl DeviceOwned for GraphicsPipeline {
|
||||
}
|
||||
|
||||
impl Debug for GraphicsPipeline {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(f, "<Vulkan graphics pipeline {:?}>", self.handle)
|
||||
}
|
||||
@ -300,7 +303,6 @@ impl PartialEq for GraphicsPipeline {
|
||||
impl Eq for GraphicsPipeline {}
|
||||
|
||||
impl Hash for GraphicsPipeline {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device.hash(state);
|
||||
|
@ -298,6 +298,7 @@ vulkan_enum! {
|
||||
|
||||
impl Default for LineRasterizationMode {
|
||||
/// Returns `LineRasterizationMode::Default`.
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::Default
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ impl TessellationState {
|
||||
}
|
||||
|
||||
/// Sets the number of patch control points to dynamic.
|
||||
#[inline]
|
||||
pub fn patch_control_points_dynamic(mut self) -> Self {
|
||||
self.patch_control_points = StateMode::Dynamic;
|
||||
self
|
||||
|
@ -43,7 +43,6 @@ impl Debug for VertexBuffer {
|
||||
}
|
||||
|
||||
impl From<VertexBuffer> for VertexInputBindingDescription {
|
||||
#[inline]
|
||||
fn from(val: VertexBuffer) -> Self {
|
||||
Self {
|
||||
stride: val.stride,
|
||||
@ -54,6 +53,7 @@ impl From<VertexBuffer> for VertexInputBindingDescription {
|
||||
|
||||
impl BuffersDefinition {
|
||||
/// Constructs a new definition.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
BuffersDefinition(Vec::new())
|
||||
}
|
||||
@ -65,6 +65,7 @@ impl BuffersDefinition {
|
||||
stride: mem::size_of::<V>() as u32,
|
||||
input_rate: VertexInputRate::Vertex,
|
||||
});
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
@ -75,31 +76,34 @@ impl BuffersDefinition {
|
||||
stride: mem::size_of::<V>() as u32,
|
||||
input_rate: VertexInputRate::Instance { divisor: 1 },
|
||||
});
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a new instance buffer containing elements of type `V` to the definition, with the
|
||||
/// specified input rate divisor.
|
||||
///
|
||||
/// This requires the
|
||||
/// [`vertex_attribute_instance_rate_divisor`](crate::device::Features::vertex_attribute_instance_rate_divisor)
|
||||
/// feature has been enabled on the device, unless `divisor` is 1.
|
||||
/// This requires the [`vertex_attribute_instance_rate_divisor`] feature has been enabled on
|
||||
/// the device, unless `divisor` is 1.
|
||||
///
|
||||
/// `divisor` can be 0 if the
|
||||
/// [`vertex_attribute_instance_rate_zero_divisor`](crate::device::Features::vertex_attribute_instance_rate_zero_divisor)
|
||||
/// feature is also enabled. This means that every vertex will use the same vertex and instance
|
||||
/// data.
|
||||
/// `divisor` can be 0 if the [`vertex_attribute_instance_rate_zero_divisor`] feature is also
|
||||
/// enabled. This means that every vertex will use the same vertex and instance data.
|
||||
///
|
||||
/// [`vertex_attribute_instance_rate_divisor`]: crate::device::Features::vertex_attribute_instance_rate_divisor
|
||||
/// [`vertex_attribute_instance_rate_zero_divisor`]: crate::device::Features::vertex_attribute_instance_rate_zero_divisor
|
||||
pub fn instance_with_divisor<V: Vertex>(mut self, divisor: u32) -> Self {
|
||||
self.0.push(VertexBuffer {
|
||||
info_fn: V::member,
|
||||
stride: mem::size_of::<V>() as u32,
|
||||
input_rate: VertexInputRate::Instance { divisor },
|
||||
});
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl VertexDefinition for BuffersDefinition {
|
||||
#[inline]
|
||||
fn definition(
|
||||
&self,
|
||||
interface: &ShaderInterface,
|
||||
|
@ -25,14 +25,12 @@ impl VertexBuffersCollection for () {
|
||||
}
|
||||
|
||||
impl<T: BufferAccessObject> VertexBuffersCollection for T {
|
||||
#[inline]
|
||||
fn into_vec(self) -> Vec<Arc<dyn BufferAccess>> {
|
||||
vec![self.as_buffer_access_object()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BufferAccessObject> VertexBuffersCollection for Vec<T> {
|
||||
#[inline]
|
||||
fn into_vec(self) -> Vec<Arc<dyn BufferAccess>> {
|
||||
self.into_iter()
|
||||
.map(|src| src.as_buffer_access_object())
|
||||
@ -41,7 +39,6 @@ impl<T: BufferAccessObject> VertexBuffersCollection for Vec<T> {
|
||||
}
|
||||
|
||||
impl<T: BufferAccessObject, const N: usize> VertexBuffersCollection for [T; N] {
|
||||
#[inline]
|
||||
fn into_vec(self) -> Vec<Arc<dyn BufferAccess>> {
|
||||
self.into_iter()
|
||||
.map(|src| src.as_buffer_access_object())
|
||||
|
@ -17,7 +17,7 @@
|
||||
//! The `Vertex` trait is unsafe, but can be implemented on a struct with the `impl_vertex!`
|
||||
//! macro.
|
||||
//!
|
||||
//! # Example
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```ignore // TODO:
|
||||
//! # #[macro_use] extern crate vulkano
|
||||
@ -40,11 +40,11 @@
|
||||
//!
|
||||
//! let usage = BufferUsage {
|
||||
//! vertex_buffer: true,
|
||||
//! .. BufferUsage::empty()
|
||||
//! ..BufferUsage::empty()
|
||||
//! };
|
||||
//!
|
||||
//! let vertex_buffer = BufferAccess::<[Vertex], _>::array(&device, 128, &usage, HostVisible, &queue)
|
||||
//! .expect("failed to create buffer");
|
||||
//! .expect("failed to create buffer");
|
||||
//!
|
||||
//! // TODO: finish example
|
||||
//! # }
|
||||
@ -103,11 +103,10 @@ pub enum IncompatibleVertexDefinitionError {
|
||||
impl Error for IncompatibleVertexDefinitionError {}
|
||||
|
||||
impl Display for IncompatibleVertexDefinitionError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
match self {
|
||||
IncompatibleVertexDefinitionError::MissingAttribute { .. } => {
|
||||
write!(f, "an attribute is missing",)
|
||||
write!(f, "an attribute is missing")
|
||||
}
|
||||
IncompatibleVertexDefinitionError::FormatMismatch { .. } => {
|
||||
write!(f, "the format of an attribute does not match")
|
||||
|
@ -10,21 +10,20 @@
|
||||
use crate::pipeline::graphics::vertex_input::VertexMemberTy;
|
||||
|
||||
/// Implements the `Vertex` trait on a struct.
|
||||
///# Example
|
||||
///
|
||||
///```
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use bytemuck::{Zeroable, Pod};
|
||||
/// #[repr(C)]
|
||||
/// #[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||
/// struct Vertex{
|
||||
/// position: [f32; 3],
|
||||
/// color: [f32; 4],
|
||||
/// }
|
||||
///
|
||||
///#[repr(C)]
|
||||
///#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
|
||||
///struct Vertex{
|
||||
/// position: [f32; 3],
|
||||
/// color: [f32; 4]
|
||||
///}
|
||||
///
|
||||
///vulkano::impl_vertex!(Vertex, position, color);
|
||||
///
|
||||
///```
|
||||
/// vulkano::impl_vertex!(Vertex, position, color);
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! impl_vertex {
|
||||
($out:ty $(, $member:ident)*) => (
|
||||
@ -128,7 +127,6 @@ unsafe impl<T> VertexMember for (T,)
|
||||
where
|
||||
T: VertexMember,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
<T as VertexMember>::format()
|
||||
}
|
||||
@ -138,7 +136,6 @@ unsafe impl<T> VertexMember for (T, T)
|
||||
where
|
||||
T: VertexMember,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
let (ty, sz) = <T as VertexMember>::format();
|
||||
(ty, sz * 2)
|
||||
@ -149,7 +146,6 @@ unsafe impl<T> VertexMember for (T, T, T)
|
||||
where
|
||||
T: VertexMember,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
let (ty, sz) = <T as VertexMember>::format();
|
||||
(ty, sz * 3)
|
||||
@ -160,7 +156,6 @@ unsafe impl<T> VertexMember for (T, T, T, T)
|
||||
where
|
||||
T: VertexMember,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
let (ty, sz) = <T as VertexMember>::format();
|
||||
(ty, sz * 4)
|
||||
@ -172,7 +167,6 @@ unsafe impl<T> VertexMember for nalgebra::Vector1<T>
|
||||
where
|
||||
T: VertexMember,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
<T as VertexMember>::format()
|
||||
}
|
||||
@ -183,7 +177,6 @@ unsafe impl<T> VertexMember for nalgebra::Vector2<T>
|
||||
where
|
||||
T: VertexMember,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
let (ty, sz) = <T as VertexMember>::format();
|
||||
(ty, sz * 2)
|
||||
@ -195,7 +188,6 @@ unsafe impl<T> VertexMember for nalgebra::Vector3<T>
|
||||
where
|
||||
T: VertexMember,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
let (ty, sz) = <T as VertexMember>::format();
|
||||
(ty, sz * 3)
|
||||
@ -207,7 +199,6 @@ unsafe impl<T> VertexMember for nalgebra::Vector4<T>
|
||||
where
|
||||
T: VertexMember,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
let (ty, sz) = <T as VertexMember>::format();
|
||||
(ty, sz * 4)
|
||||
@ -219,7 +210,6 @@ unsafe impl<T> VertexMember for nalgebra::Point1<T>
|
||||
where
|
||||
T: VertexMember + nalgebra::Scalar,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
<T as VertexMember>::format()
|
||||
}
|
||||
@ -230,7 +220,6 @@ unsafe impl<T> VertexMember for nalgebra::Point2<T>
|
||||
where
|
||||
T: VertexMember + nalgebra::Scalar,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
let (ty, sz) = <T as VertexMember>::format();
|
||||
(ty, sz * 2)
|
||||
@ -242,7 +231,6 @@ unsafe impl<T> VertexMember for nalgebra::Point3<T>
|
||||
where
|
||||
T: VertexMember + nalgebra::Scalar,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
let (ty, sz) = <T as VertexMember>::format();
|
||||
(ty, sz * 3)
|
||||
@ -254,7 +242,6 @@ unsafe impl<T> VertexMember for nalgebra::Point4<T>
|
||||
where
|
||||
T: VertexMember + nalgebra::Scalar,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
let (ty, sz) = <T as VertexMember>::format();
|
||||
(ty, sz * 4)
|
||||
@ -267,7 +254,6 @@ macro_rules! impl_vm_array {
|
||||
where
|
||||
T: VertexMember,
|
||||
{
|
||||
#[inline]
|
||||
fn format() -> (VertexMemberTy, usize) {
|
||||
let (ty, sz) = <T as VertexMember>::format();
|
||||
(ty, sz * $sz)
|
||||
|
@ -143,7 +143,6 @@ impl VertexInputState {
|
||||
}
|
||||
|
||||
/// Sets all bindings.
|
||||
#[inline]
|
||||
pub fn bindings(
|
||||
mut self,
|
||||
bindings: impl IntoIterator<Item = (u32, VertexInputBindingDescription)>,
|
||||
@ -164,7 +163,6 @@ impl VertexInputState {
|
||||
}
|
||||
|
||||
/// Sets all attributes.
|
||||
#[inline]
|
||||
pub fn attributes(
|
||||
mut self,
|
||||
attributes: impl IntoIterator<Item = (u32, VertexInputAttributeDescription)>,
|
||||
@ -208,14 +206,14 @@ pub enum VertexInputRate {
|
||||
/// Each element of the source corresponds to an instance.
|
||||
///
|
||||
/// `divisor` indicates how many consecutive instances will use the same instance buffer data.
|
||||
/// This value must be 1, unless the
|
||||
/// [`vertex_attribute_instance_rate_divisor`](crate::device::Features::vertex_attribute_instance_rate_divisor)
|
||||
/// feature has been enabled on the device.
|
||||
/// This value must be 1, unless the [`vertex_attribute_instance_rate_divisor`] feature has
|
||||
/// been enabled on the device.
|
||||
///
|
||||
/// `divisor` can be 0 if the
|
||||
/// [`vertex_attribute_instance_rate_zero_divisor`](crate::device::Features::vertex_attribute_instance_rate_zero_divisor)
|
||||
/// feature is also enabled. This means that every vertex will use the same vertex and instance
|
||||
/// data.
|
||||
/// `divisor` can be 0 if the [`vertex_attribute_instance_rate_zero_divisor`] feature is also
|
||||
/// enabled. This means that every vertex will use the same vertex and instance data.
|
||||
///
|
||||
/// [`vertex_attribute_instance_rate_divisor`]: crate::device::Features::vertex_attribute_instance_rate_divisor
|
||||
/// [`vertex_attribute_instance_rate_zero_divisor`]: crate::device::Features::vertex_attribute_instance_rate_zero_divisor
|
||||
Instance { divisor: u32 },
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,6 @@ impl ViewportState {
|
||||
}
|
||||
|
||||
/// Creates a `ViewportState` with fixed state from the given viewports and scissors.
|
||||
#[inline]
|
||||
pub fn viewport_fixed_scissor_fixed(
|
||||
data: impl IntoIterator<Item = (Viewport, Scissor)>,
|
||||
) -> Self {
|
||||
@ -131,7 +130,6 @@ impl ViewportState {
|
||||
|
||||
/// Creates a `ViewportState` with fixed state from the given viewports, and matching scissors
|
||||
/// that cover the whole viewport.
|
||||
#[inline]
|
||||
pub fn viewport_fixed_scissor_irrelevant(data: impl IntoIterator<Item = Viewport>) -> Self {
|
||||
Self::Fixed {
|
||||
data: data
|
||||
@ -174,6 +172,7 @@ impl ViewportState {
|
||||
/// Returns the number of viewports and scissors.
|
||||
///
|
||||
/// `None` is returned if both `viewport_count_dynamic` and `scissor_count_dynamic` are `true`.
|
||||
#[inline]
|
||||
pub fn count(&self) -> Option<u32> {
|
||||
Some(match *self {
|
||||
ViewportState::Fixed { ref data } => data.len() as u32,
|
||||
|
@ -531,6 +531,7 @@ impl PipelineLayout {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
handle: ash::vk::PipelineLayout,
|
||||
@ -587,6 +588,7 @@ impl PipelineLayout {
|
||||
}
|
||||
|
||||
/// Returns whether `self` is compatible with `other` for the given number of sets.
|
||||
#[inline]
|
||||
pub fn is_compatible_with(&self, other: &PipelineLayout, num_sets: u32) -> bool {
|
||||
let num_sets = num_sets as usize;
|
||||
assert!(num_sets >= self.set_layouts.len());
|
||||
@ -680,6 +682,7 @@ impl Drop for PipelineLayout {
|
||||
unsafe impl VulkanObject for PipelineLayout {
|
||||
type Object = ash::vk::PipelineLayout;
|
||||
|
||||
#[inline]
|
||||
fn internal_object(&self) -> Self::Object {
|
||||
self.handle
|
||||
}
|
||||
@ -702,7 +705,6 @@ impl PartialEq for PipelineLayout {
|
||||
impl Eq for PipelineLayout {}
|
||||
|
||||
impl Hash for PipelineLayout {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -822,21 +824,18 @@ pub enum PipelineLayoutCreationError {
|
||||
}
|
||||
|
||||
impl Error for PipelineLayoutCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PipelineLayoutCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -845,90 +844,167 @@ impl Display for PipelineLayoutCreationError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::MaxBoundDescriptorSetsExceeded { provided, max_supported } => write!(
|
||||
Self::MaxBoundDescriptorSetsExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the number of elements in `set_layouts` ({}) is greater than the `max_bound_descriptor_sets` limit ({})",
|
||||
"the number of elements in `set_layouts` ({}) is greater than the \
|
||||
`max_bound_descriptor_sets` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxDescriptorSetSamplersExceeded { provided, max_supported } => write!(
|
||||
Self::MaxDescriptorSetSamplersExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::Sampler` and `DescriptorType::CombinedImageSampler` descriptors ({}) than the `max_descriptor_set_samplers` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::Sampler` and \
|
||||
`DescriptorType::CombinedImageSampler` descriptors ({}) than the \
|
||||
`max_descriptor_set_samplers` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxDescriptorSetUniformBuffersExceeded { provided, max_supported } => write!(
|
||||
Self::MaxDescriptorSetUniformBuffersExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::UniformBuffer` descriptors ({}) than the `max_descriptor_set_uniform_buffers` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::UniformBuffer` descriptors ({}) \
|
||||
than the `max_descriptor_set_uniform_buffers` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxDescriptorSetUniformBuffersDynamicExceeded { provided, max_supported } => write!(
|
||||
Self::MaxDescriptorSetUniformBuffersDynamicExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::UniformBufferDynamic` descriptors ({}) than the `max_descriptor_set_uniform_buffers_dynamic` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::UniformBufferDynamic` descriptors \
|
||||
({}) than the `max_descriptor_set_uniform_buffers_dynamic` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxDescriptorSetStorageBuffersExceeded { provided, max_supported } => write!(
|
||||
Self::MaxDescriptorSetStorageBuffersExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::StorageBuffer` descriptors ({}) than the `max_descriptor_set_storage_buffers` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::StorageBuffer` descriptors ({}) \
|
||||
than the `max_descriptor_set_storage_buffers` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxDescriptorSetStorageBuffersDynamicExceeded { provided, max_supported } => write!(
|
||||
Self::MaxDescriptorSetStorageBuffersDynamicExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::StorageBufferDynamic` descriptors ({}) than the `max_descriptor_set_storage_buffers_dynamic` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::StorageBufferDynamic` descriptors \
|
||||
({}) than the `max_descriptor_set_storage_buffers_dynamic` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxDescriptorSetSampledImagesExceeded { provided, max_supported } => write!(
|
||||
Self::MaxDescriptorSetSampledImagesExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::SampledImage`, `DescriptorType::CombinedImageSampler` and `DescriptorType::UniformTexelBuffer` descriptors ({}) than the `max_descriptor_set_sampled_images` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::SampledImage`, \
|
||||
`DescriptorType::CombinedImageSampler` and `DescriptorType::UniformTexelBuffer` \
|
||||
descriptors ({}) than the `max_descriptor_set_sampled_images` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxDescriptorSetStorageImagesExceeded { provided, max_supported } => write!(
|
||||
Self::MaxDescriptorSetStorageImagesExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::StorageImage` and `DescriptorType::StorageTexelBuffer` descriptors ({}) than the `max_descriptor_set_storage_images` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::StorageImage` and \
|
||||
`DescriptorType::StorageTexelBuffer` descriptors ({}) than the \
|
||||
`max_descriptor_set_storage_images` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxDescriptorSetInputAttachmentsExceeded { provided, max_supported } => write!(
|
||||
Self::MaxDescriptorSetInputAttachmentsExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::InputAttachment` descriptors ({}) than the `max_descriptor_set_input_attachments` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::InputAttachment` descriptors ({}) \
|
||||
than the `max_descriptor_set_input_attachments` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxPerStageResourcesExceeded { provided, max_supported } => write!(
|
||||
Self::MaxPerStageResourcesExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more bound resources ({}) in a single stage than the `max_per_stage_resources` limit ({})",
|
||||
"the `set_layouts` contain more bound resources ({}) in a single stage than the \
|
||||
`max_per_stage_resources` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxPerStageDescriptorSamplersExceeded { provided, max_supported } => write!(
|
||||
Self::MaxPerStageDescriptorSamplersExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::Sampler` and `DescriptorType::CombinedImageSampler` descriptors ({}) in a single stage than the `max_per_stage_descriptor_set_samplers` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::Sampler` and \
|
||||
`DescriptorType::CombinedImageSampler` descriptors ({}) in a single stage than the \
|
||||
`max_per_stage_descriptor_set_samplers` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxPerStageDescriptorUniformBuffersExceeded { provided, max_supported } => write!(
|
||||
Self::MaxPerStageDescriptorUniformBuffersExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::UniformBuffer` and `DescriptorType::UniformBufferDynamic` descriptors ({}) in a single stage than the `max_per_stage_descriptor_set_uniform_buffers` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::UniformBuffer` and \
|
||||
`DescriptorType::UniformBufferDynamic` descriptors ({}) in a single stage than the \
|
||||
`max_per_stage_descriptor_set_uniform_buffers` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxPerStageDescriptorStorageBuffersExceeded { provided, max_supported } => write!(
|
||||
Self::MaxPerStageDescriptorStorageBuffersExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::StorageBuffer` and `DescriptorType::StorageBufferDynamic` descriptors ({}) in a single stage than the `max_per_stage_descriptor_set_storage_buffers` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::StorageBuffer` and \
|
||||
`DescriptorType::StorageBufferDynamic` descriptors ({}) in a single stage than the \
|
||||
`max_per_stage_descriptor_set_storage_buffers` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxPerStageDescriptorSampledImagesExceeded { provided, max_supported } => write!(
|
||||
Self::MaxPerStageDescriptorSampledImagesExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::SampledImage`, `DescriptorType::CombinedImageSampler` and `DescriptorType::UniformTexelBuffer` descriptors ({}) in a single stage than the `max_per_stage_descriptor_set_sampled_images` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::SampledImage`, \
|
||||
`DescriptorType::CombinedImageSampler` and `DescriptorType::UniformTexelBuffer` \
|
||||
descriptors ({}) in a single stage than the \
|
||||
`max_per_stage_descriptor_set_sampled_images` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxPerStageDescriptorStorageImagesExceeded { provided, max_supported } => write!(
|
||||
Self::MaxPerStageDescriptorStorageImagesExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::StorageImage` and `DescriptorType::StorageTexelBuffer` descriptors ({}) in a single stage than the `max_per_stage_descriptor_set_storage_images` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::StorageImage` and \
|
||||
`DescriptorType::StorageTexelBuffer` descriptors ({}) in a single stage than the \
|
||||
`max_per_stage_descriptor_set_storage_images` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxPerStageDescriptorInputAttachmentsExceeded { provided, max_supported } => write!(
|
||||
Self::MaxPerStageDescriptorInputAttachmentsExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the `set_layouts` contain more `DescriptorType::InputAttachment` descriptors ({}) in a single stage than the `max_per_stage_descriptor_set_input_attachments` limit ({})",
|
||||
"the `set_layouts` contain more `DescriptorType::InputAttachment` descriptors ({}) \
|
||||
in a single stage than the `max_per_stage_descriptor_set_input_attachments` limit \
|
||||
({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::MaxPushConstantsSizeExceeded { provided, max_supported } => write!(
|
||||
Self::MaxPushConstantsSizeExceeded {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"an element in `push_constant_ranges` has an `offset + size` ({}) greater than the `max_push_constants_size` limit ({})",
|
||||
"an element in `push_constant_ranges` has an `offset + size` ({}) greater than the \
|
||||
`max_push_constants_size` limit ({})",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::PushConstantRangesStageMultiple => write!(
|
||||
@ -937,21 +1013,19 @@ impl Display for PipelineLayoutCreationError {
|
||||
),
|
||||
Self::SetLayoutsPushDescriptorMultiple => write!(
|
||||
f,
|
||||
"multiple elements of `set_layouts` have `push_descriptor` enabled"
|
||||
"multiple elements of `set_layouts` have `push_descriptor` enabled",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for PipelineLayoutCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> PipelineLayoutCreationError {
|
||||
PipelineLayoutCreationError::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for PipelineLayoutCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> PipelineLayoutCreationError {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => {
|
||||
@ -966,7 +1040,6 @@ impl From<VulkanError> for PipelineLayoutCreationError {
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for PipelineLayoutCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
@ -994,55 +1067,53 @@ pub enum PipelineLayoutSupersetError {
|
||||
}
|
||||
|
||||
impl Error for PipelineLayoutSupersetError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
PipelineLayoutSupersetError::DescriptorRequirementsNotMet { ref error, .. } => {
|
||||
Some(error)
|
||||
}
|
||||
match self {
|
||||
PipelineLayoutSupersetError::DescriptorRequirementsNotMet { error, .. } => Some(error),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PipelineLayoutSupersetError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
PipelineLayoutSupersetError::DescriptorRequirementsNotMet { set_num, binding_num, .. } => write!(
|
||||
PipelineLayoutSupersetError::DescriptorRequirementsNotMet {
|
||||
set_num,
|
||||
binding_num,
|
||||
..
|
||||
} => write!(
|
||||
f,
|
||||
"the descriptor at set {} binding {} does not meet the requirements",
|
||||
set_num, binding_num
|
||||
set_num, binding_num,
|
||||
),
|
||||
PipelineLayoutSupersetError::DescriptorMissing {
|
||||
set_num,
|
||||
binding_num,
|
||||
} => write!(
|
||||
f,
|
||||
"a descriptor at set {} binding {} is required by the shaders, but is missing from the pipeline layout",
|
||||
set_num, binding_num
|
||||
"a descriptor at set {} binding {} is required by the shaders, but is missing from \
|
||||
the pipeline layout",
|
||||
set_num, binding_num,
|
||||
),
|
||||
PipelineLayoutSupersetError::PushConstantRange {
|
||||
first_range,
|
||||
second_range,
|
||||
} => {
|
||||
writeln!(
|
||||
f,
|
||||
"our range did not completely encompass the other range"
|
||||
)?;
|
||||
writeln!(f, "our range did not completely encompass the other range")?;
|
||||
writeln!(f, " our stages: {:?}", first_range.stages)?;
|
||||
writeln!(
|
||||
f,
|
||||
" our range: {} - {}",
|
||||
first_range.offset,
|
||||
first_range.offset + first_range.size
|
||||
first_range.offset + first_range.size,
|
||||
)?;
|
||||
writeln!(f, " other stages: {:?}", second_range.stages)?;
|
||||
write!(
|
||||
f,
|
||||
" other range: {} - {}",
|
||||
second_range.offset,
|
||||
second_range.offset + second_range.size
|
||||
second_range.offset + second_range.size,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +269,6 @@ pub enum StateMode<F> {
|
||||
}
|
||||
|
||||
impl<T> From<Option<T>> for StateMode<T> {
|
||||
#[inline]
|
||||
fn from(val: Option<T>) -> Self {
|
||||
match val {
|
||||
Some(x) => StateMode::Fixed(x),
|
||||
@ -279,7 +278,6 @@ impl<T> From<Option<T>> for StateMode<T> {
|
||||
}
|
||||
|
||||
impl<T> From<StateMode<T>> for Option<T> {
|
||||
#[inline]
|
||||
fn from(val: StateMode<T>) -> Self {
|
||||
match val {
|
||||
StateMode::Fixed(x) => Some(x),
|
||||
|
@ -110,6 +110,7 @@ impl QueryPool {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
handle: ash::vk::QueryPool,
|
||||
@ -120,6 +121,7 @@ impl QueryPool {
|
||||
query_count,
|
||||
_ne: _,
|
||||
} = create_info;
|
||||
|
||||
Arc::new(QueryPool {
|
||||
handle,
|
||||
device,
|
||||
@ -152,9 +154,9 @@ impl QueryPool {
|
||||
|
||||
/// Returns a reference to a range of queries, or `None` if out of range.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the range is empty.
|
||||
/// - Panics if the range is empty.
|
||||
#[inline]
|
||||
pub fn queries_range(&self, range: Range<u32>) -> Option<QueriesRange<'_>> {
|
||||
assert!(!range.is_empty());
|
||||
@ -203,7 +205,6 @@ impl PartialEq for QueryPool {
|
||||
impl Eq for QueryPool {}
|
||||
|
||||
impl Hash for QueryPool {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -248,17 +249,15 @@ pub enum QueryPoolCreationError {
|
||||
}
|
||||
|
||||
impl Error for QueryPoolCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
QueryPoolCreationError::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
QueryPoolCreationError::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for QueryPoolCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
@ -267,7 +266,7 @@ impl Display for QueryPoolCreationError {
|
||||
QueryPoolCreationError::OomError(_) => "not enough memory available",
|
||||
QueryPoolCreationError::PipelineStatisticsQueryFeatureNotEnabled => {
|
||||
"a pipeline statistics pool was requested but the corresponding feature \
|
||||
wasn't enabled"
|
||||
wasn't enabled"
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -275,14 +274,12 @@ impl Display for QueryPoolCreationError {
|
||||
}
|
||||
|
||||
impl From<OomError> for QueryPoolCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> QueryPoolCreationError {
|
||||
QueryPoolCreationError::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for QueryPoolCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> QueryPoolCreationError {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => {
|
||||
@ -352,6 +349,7 @@ impl<'a> QueriesRange<'a> {
|
||||
/// is returned if some results were not yet available; these will not be written to the buffer.
|
||||
///
|
||||
/// See also [`copy_query_pool_results`](crate::command_buffer::AutoCommandBufferBuilder::copy_query_pool_results).
|
||||
#[inline]
|
||||
pub fn get_results<T>(
|
||||
&self,
|
||||
destination: &mut [T],
|
||||
@ -461,22 +459,19 @@ pub enum GetResultsError {
|
||||
}
|
||||
|
||||
impl Error for GetResultsError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for GetResultsError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
Self::DeviceLost => write!(f, "the connection to the device has been lost"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -485,7 +480,6 @@ impl Display for GetResultsError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::BufferTooSmall { .. } => write!(f, "the buffer is too small for the operation"),
|
||||
Self::InvalidFlags => write!(
|
||||
f,
|
||||
@ -496,7 +490,6 @@ impl Display for GetResultsError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for GetResultsError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
VulkanError::OutOfHostMemory | VulkanError::OutOfDeviceMemory => {
|
||||
@ -509,14 +502,12 @@ impl From<VulkanError> for GetResultsError {
|
||||
}
|
||||
|
||||
impl From<OomError> for GetResultsError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for GetResultsError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -37,6 +37,7 @@ where
|
||||
V: Eq + Clone,
|
||||
{
|
||||
/// Makes a new empty `RangeMap`.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
RangeMap {
|
||||
btm: BTreeMap::new(),
|
||||
@ -45,12 +46,14 @@ where
|
||||
|
||||
/// Returns a reference to the value corresponding to the given key,
|
||||
/// if the key is covered by any range in the map.
|
||||
#[inline]
|
||||
pub fn get(&self, key: &K) -> Option<&V> {
|
||||
self.get_key_value(key).map(|(_range, value)| value)
|
||||
}
|
||||
|
||||
/// Returns the range-value pair (as a pair of references) corresponding
|
||||
/// to the given key, if the key is covered by any range in the map.
|
||||
#[inline]
|
||||
pub fn get_key_value(&self, key: &K) -> Option<(&Range<K>, &V)> {
|
||||
// The only stored range that could contain the given key is the
|
||||
// last stored range whose start is less than or equal to this key.
|
||||
@ -68,6 +71,7 @@ where
|
||||
}
|
||||
|
||||
/// Returns `true` if any range in the map covers the specified key.
|
||||
#[inline]
|
||||
pub fn contains_key(&self, key: &K) -> bool {
|
||||
self.get(key).is_some()
|
||||
}
|
||||
@ -88,6 +92,7 @@ where
|
||||
/// ordered by key range.
|
||||
///
|
||||
/// The iterator element type is `(&'a Range<K>, &'a V)`.
|
||||
#[inline]
|
||||
pub fn iter(&self) -> Iter<'_, K, V> {
|
||||
Iter {
|
||||
inner: self.btm.iter(),
|
||||
@ -98,6 +103,7 @@ where
|
||||
/// ordered by key range.
|
||||
///
|
||||
/// The iterator element type is `(&'a Range<K>, &'a mut V)`.
|
||||
#[inline]
|
||||
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
|
||||
IterMut {
|
||||
inner: self.btm.iter_mut(),
|
||||
@ -767,6 +773,7 @@ pub struct RangeStartWrapper<T> {
|
||||
}
|
||||
|
||||
impl<T> RangeStartWrapper<T> {
|
||||
#[inline]
|
||||
pub fn new(range: Range<T>) -> RangeStartWrapper<T> {
|
||||
RangeStartWrapper { range }
|
||||
}
|
||||
|
@ -1577,21 +1577,18 @@ pub enum RenderPassCreationError {
|
||||
}
|
||||
|
||||
impl Error for RenderPassCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
RenderPassCreationError::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
RenderPassCreationError::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RenderPassCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available",),
|
||||
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -1600,63 +1597,88 @@ impl Display for RenderPassCreationError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::AttachmentFirstUseLoadOpInvalid { attachment, first_use_subpass } => write!(
|
||||
Self::AttachmentFirstUseLoadOpInvalid {
|
||||
attachment,
|
||||
first_use_subpass,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment {} is first used in the render pass in subpass {} with a read-only layout or as an input attachment, but its `load_op` or `stencil_load_op` is `LoadOp::Clear`",
|
||||
"attachment {} is first used in the render pass in subpass {} with a read-only \
|
||||
layout or as an input attachment, but its `load_op` or `stencil_load_op` is \
|
||||
`LoadOp::Clear`",
|
||||
attachment, first_use_subpass,
|
||||
),
|
||||
Self::AttachmentLayoutInvalid { attachment } => write!(
|
||||
f,
|
||||
"attachment {} has an `initial_layout` or `final_layout` value that is invalid for the provided `format`",
|
||||
"attachment {} has an `initial_layout` or `final_layout` value that is invalid for \
|
||||
the provided `format`",
|
||||
attachment,
|
||||
),
|
||||
Self::CorrelatedViewMasksMultiviewNotEnabled => write!(
|
||||
f,
|
||||
"correlated view masks were included, but multiview is not enabled on the render pass",
|
||||
"correlated view masks were included, but multiview is not enabled on the render \
|
||||
pass",
|
||||
),
|
||||
Self::CorrelatedViewMasksOverlapping => write!(
|
||||
f,
|
||||
"the provided correlated view masks contain a bit that is set in more than one element",
|
||||
"the provided correlated view masks contain a bit that is set in more than one \
|
||||
element",
|
||||
),
|
||||
Self::DependencyAccessNotSupportedByStages { dependency } => write!(
|
||||
f,
|
||||
"subpass dependency {} specified an access type that was not supported by the given stages",
|
||||
dependency,
|
||||
),
|
||||
Self::DependencySelfDependencyFramebufferStagesWithoutByRegion { dependency } => write!(
|
||||
f,
|
||||
"subpass dependency {} specifies a subpass self-dependency and includes framebuffer stages in both `source_stages` and `destination_stages`, but the `by_region` dependency was not enabled",
|
||||
dependency,
|
||||
),
|
||||
Self::DependencySelfDependencySourceStageAfterDestinationStage { dependency } => write!(
|
||||
f,
|
||||
"subpass dependency {} specifies a subpass self-dependency and includes non-framebuffer stages, but the latest stage in `source_stages` is after the earliest stage in `destination_stages`",
|
||||
"subpass dependency {} specified an access type that was not supported by the \
|
||||
given stages",
|
||||
dependency,
|
||||
),
|
||||
Self::DependencySelfDependencyFramebufferStagesWithoutByRegion { dependency } => {
|
||||
write!(
|
||||
f,
|
||||
"subpass dependency {} specifies a subpass self-dependency and includes \
|
||||
framebuffer stages in both `source_stages` and `destination_stages`, but the \
|
||||
`by_region` dependency was not enabled",
|
||||
dependency,
|
||||
)
|
||||
}
|
||||
Self::DependencySelfDependencySourceStageAfterDestinationStage { dependency } => {
|
||||
write!(
|
||||
f,
|
||||
"subpass dependency {} specifies a subpass self-dependency and includes \
|
||||
non-framebuffer stages, but the latest stage in `source_stages` is after the \
|
||||
earliest stage in `destination_stages`",
|
||||
dependency,
|
||||
)
|
||||
}
|
||||
Self::DependencySelfDependencyViewLocalNonzeroOffset { dependency } => write!(
|
||||
f,
|
||||
"subpass dependency {} specifies a subpass self-dependency and has the `view_local` dependency enabled, but the inner offset value was not 0",
|
||||
"subpass dependency {} specifies a subpass self-dependency and has the \
|
||||
`view_local` dependency enabled, but the inner offset value was not 0",
|
||||
dependency,
|
||||
),
|
||||
Self::DependencySelfDependencyViewMaskMultiple { dependency, subpass } => write!(
|
||||
Self::DependencySelfDependencyViewMaskMultiple {
|
||||
dependency,
|
||||
subpass,
|
||||
} => write!(
|
||||
f,
|
||||
"subpass dependency {} specifies a subpass self-dependency without the `view_local` dependency, but the referenced subpass {} has more than one bit set in its `view_mask`",
|
||||
"subpass dependency {} specifies a subpass self-dependency without the \
|
||||
`view_local` dependency, but the referenced subpass {} has more than one bit set \
|
||||
in its `view_mask`",
|
||||
dependency, subpass,
|
||||
),
|
||||
Self::DependencySourceSubpassAfterDestinationSubpass { dependency } => write!(
|
||||
f,
|
||||
"subpass dependency {} has a `source_subpass` that is later than the `destination_subpass`",
|
||||
"subpass dependency {} has a `source_subpass` that is later than the \
|
||||
`destination_subpass`",
|
||||
dependency,
|
||||
),
|
||||
Self::DependencyStageNotSupported { dependency } => write!(
|
||||
f,
|
||||
"subpass dependency {} has a bit set in the `source_stages` or `destination_stages` that is not supported for graphics pipelines",
|
||||
"subpass dependency {} has a bit set in the `source_stages` or \
|
||||
`destination_stages` that is not supported for graphics pipelines",
|
||||
dependency,
|
||||
),
|
||||
Self::DependencyBothSubpassesExternal { dependency } => write!(
|
||||
f,
|
||||
"subpass dependency {} has both `source_subpass` and `destination_subpass` set to `None`",
|
||||
"subpass dependency {} has both `source_subpass` and `destination_subpass` set to \
|
||||
`None`",
|
||||
dependency,
|
||||
),
|
||||
Self::DependencySubpassOutOfRange {
|
||||
@ -1664,25 +1686,35 @@ impl Display for RenderPassCreationError {
|
||||
subpass,
|
||||
} => write!(
|
||||
f,
|
||||
"the subpass index {} in subpass dependency {} is not less than the number of subpasses in the render pass",
|
||||
"the subpass index {} in subpass dependency {} is not less than the number of \
|
||||
subpasses in the render pass",
|
||||
subpass, dependency,
|
||||
),
|
||||
Self::DependencyViewLocalExternalDependency { dependency } => write!(
|
||||
f,
|
||||
"subpass dependency {} has the `view_local` dependency enabled, but `source_subpass` or `destination_subpass` were set to `None`",
|
||||
"subpass dependency {} has the `view_local` dependency enabled, but \
|
||||
`source_subpass` or `destination_subpass` were set to `None`",
|
||||
dependency,
|
||||
),
|
||||
Self::DependencyViewLocalMultiviewNotEnabled { dependency } => write!(
|
||||
f,
|
||||
"subpass dependency {} has the `view_local` dependency enabled, but multiview is not enabled on the render pass",
|
||||
"subpass dependency {} has the `view_local` dependency enabled, but multiview is \
|
||||
not enabled on the render pass",
|
||||
dependency,
|
||||
),
|
||||
Self::SubpassAttachmentAspectsNotEmpty { subpass, attachment } => write!(
|
||||
Self::SubpassAttachmentAspectsNotEmpty {
|
||||
subpass,
|
||||
attachment,
|
||||
} => write!(
|
||||
f,
|
||||
"a reference to attachment {} used other than as an input attachment in subpass {} has one or more aspects selected",
|
||||
"a reference to attachment {} used other than as an input attachment in subpass {} \
|
||||
has one or more aspects selected",
|
||||
attachment, subpass,
|
||||
),
|
||||
Self::SubpassAttachmentLayoutMismatch { subpass, attachment } => write!(
|
||||
Self::SubpassAttachmentLayoutMismatch {
|
||||
subpass,
|
||||
attachment,
|
||||
} => write!(
|
||||
f,
|
||||
"the layouts of all uses of attachment {} in subpass {} do not match.",
|
||||
attachment, subpass,
|
||||
@ -1693,27 +1725,45 @@ impl Display for RenderPassCreationError {
|
||||
usage,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment {} used as {} attachment in subpass {} has a layout that is not supported for that usage",
|
||||
"attachment {} used as {} attachment in subpass {} has a layout that is not \
|
||||
supported for that usage",
|
||||
attachment, usage, subpass,
|
||||
),
|
||||
Self::SubpassAttachmentOutOfRange { subpass, attachment } => write!(
|
||||
Self::SubpassAttachmentOutOfRange {
|
||||
subpass,
|
||||
attachment,
|
||||
} => write!(
|
||||
f,
|
||||
"the attachment index {} in subpass {} is not less than the number of attachments in the render pass",
|
||||
"the attachment index {} in subpass {} is not less than the number of attachments \
|
||||
in the render pass",
|
||||
attachment, subpass,
|
||||
),
|
||||
Self::SubpassAttachmentUsageColorDepthStencil { subpass, attachment } => write!(
|
||||
Self::SubpassAttachmentUsageColorDepthStencil {
|
||||
subpass,
|
||||
attachment,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment {} is used as both a color attachment and a depth/stencil attachment in subpass {}",
|
||||
"attachment {} is used as both a color attachment and a depth/stencil attachment \
|
||||
in subpass {}",
|
||||
attachment, subpass,
|
||||
),
|
||||
Self::SubpassAttachmentFormatUsageNotSupported { subpass, attachment, usage, } => write!(
|
||||
Self::SubpassAttachmentFormatUsageNotSupported {
|
||||
subpass,
|
||||
attachment,
|
||||
usage,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment {} used as {} attachment in subpass {} has a format that does not support that usage",
|
||||
"attachment {} used as {} attachment in subpass {} has a format that does not \
|
||||
support that usage",
|
||||
attachment, usage, subpass,
|
||||
),
|
||||
Self::SubpassColorAttachmentWithResolveNotMultisampled { subpass, attachment } => write!(
|
||||
Self::SubpassColorAttachmentWithResolveNotMultisampled {
|
||||
subpass,
|
||||
attachment,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment {} used as a color attachment in subpass {} with resolve attachments has a `samples` value of `SampleCount::Sample1`",
|
||||
"attachment {} used as a color attachment in subpass {} with resolve attachments \
|
||||
has a `samples` value of `SampleCount::Sample1`",
|
||||
attachment, subpass,
|
||||
),
|
||||
Self::SubpassColorDepthStencilAttachmentSamplesMismatch {
|
||||
@ -1723,37 +1773,49 @@ impl Display for RenderPassCreationError {
|
||||
first_samples,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment {} used as a color or depth/stencil attachment in subpass {} has a `samples` value {:?} that is different from the first color attachment ({:?})",
|
||||
"attachment {} used as a color or depth/stencil attachment in subpass {} has a \
|
||||
`samples` value {:?} that is different from the first color attachment ({:?})",
|
||||
attachment, subpass, samples, first_samples,
|
||||
),
|
||||
Self::SubpassInputAttachmentAspectsNotCompatible { subpass, attachment } => write!(
|
||||
Self::SubpassInputAttachmentAspectsNotCompatible {
|
||||
subpass,
|
||||
attachment,
|
||||
} => write!(
|
||||
f,
|
||||
"a reference to attachment {} used as an input attachment in subpass {} selects aspects that are not present in the format of the attachment",
|
||||
"a reference to attachment {} used as an input attachment in subpass {} selects \
|
||||
aspects that are not present in the format of the attachment",
|
||||
attachment, subpass,
|
||||
),
|
||||
Self::SubpassMaxColorAttachmentsExceeded { .. } => {
|
||||
write!(f, "the `max_color_attachments` limit has been exceeded",)
|
||||
write!(f, "the `max_color_attachments` limit has been exceeded")
|
||||
}
|
||||
Self::SubpassMaxMultiviewViewCountExceeded { .. } => {
|
||||
write!(f, "the `max_multiview_view_count` limit has been exceeded for a subpass",)
|
||||
},
|
||||
Self::SubpassMaxMultiviewViewCountExceeded { .. } => write!(
|
||||
f,
|
||||
"the `max_multiview_view_count` limit has been exceeded for a subpass",
|
||||
),
|
||||
Self::SubpassMultiviewMismatch {
|
||||
subpass,
|
||||
multiview,
|
||||
first_subpass_multiview,
|
||||
} => write!(
|
||||
f,
|
||||
"the multiview state (whether `view_mask` is nonzero) of subpass {} is {}, which is different from the first subpass ({})",
|
||||
"the multiview state (whether `view_mask` is nonzero) of subpass {} is {}, which \
|
||||
is different from the first subpass ({})",
|
||||
subpass, multiview, first_subpass_multiview,
|
||||
),
|
||||
Self::SubpassPreserveAttachmentUsedElsewhere { subpass, attachment } => write!(
|
||||
Self::SubpassPreserveAttachmentUsedElsewhere {
|
||||
subpass,
|
||||
attachment,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment {} marked as a preserve attachment in subpass {} is also used as an attachment in that subpass",
|
||||
"attachment {} marked as a preserve attachment in subpass {} is also used as an \
|
||||
attachment in that subpass",
|
||||
attachment, subpass,
|
||||
),
|
||||
Self::SubpassResolveAttachmentsColorAttachmentsLenMismatch { subpass } => write!(
|
||||
f,
|
||||
"the `resolve_attachments` field of subpass {} was not empty, but its length did not match the length of `color_attachments`",
|
||||
"the `resolve_attachments` field of subpass {} was not empty, but its length did \
|
||||
not match the length of `color_attachments`",
|
||||
subpass,
|
||||
),
|
||||
Self::SubpassResolveAttachmentFormatMismatch {
|
||||
@ -1762,17 +1824,23 @@ impl Display for RenderPassCreationError {
|
||||
color_attachment,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment {} used as a resolve attachment in subpass {} has a `format` value different from the corresponding color attachment {}",
|
||||
"attachment {} used as a resolve attachment in subpass {} has a `format` value \
|
||||
different from the corresponding color attachment {}",
|
||||
subpass, resolve_attachment, color_attachment,
|
||||
),
|
||||
Self::SubpassResolveAttachmentMultisampled { subpass, attachment } => write!(
|
||||
Self::SubpassResolveAttachmentMultisampled {
|
||||
subpass,
|
||||
attachment,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment {} used as a resolve attachment in subpass {} has a `samples` value other than `SampleCount::Sample1`",
|
||||
"attachment {} used as a resolve attachment in subpass {} has a `samples` value \
|
||||
other than `SampleCount::Sample1`",
|
||||
attachment, subpass,
|
||||
),
|
||||
Self::SubpassResolveAttachmentWithoutColorAttachment { subpass } => write!(
|
||||
f,
|
||||
"a resolve attachment in subpass {} is `Some`, but the corresponding color attachment is `None`",
|
||||
"a resolve attachment in subpass {} is `Some`, but the corresponding color \
|
||||
attachment is `None`",
|
||||
subpass,
|
||||
),
|
||||
}
|
||||
@ -1780,14 +1848,12 @@ impl Display for RenderPassCreationError {
|
||||
}
|
||||
|
||||
impl From<OomError> for RenderPassCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> RenderPassCreationError {
|
||||
RenderPassCreationError::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for RenderPassCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> RenderPassCreationError {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => {
|
||||
@ -1802,7 +1868,6 @@ impl From<VulkanError> for RenderPassCreationError {
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for RenderPassCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -336,6 +336,7 @@ impl Framebuffer {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `render_pass`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
render_pass: Arc<RenderPass>,
|
||||
handle: ash::vk::Framebuffer,
|
||||
@ -431,7 +432,6 @@ impl PartialEq for Framebuffer {
|
||||
impl Eq for Framebuffer {}
|
||||
|
||||
impl Hash for Framebuffer {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -588,33 +588,28 @@ pub enum FramebufferCreationError {
|
||||
}
|
||||
|
||||
impl From<OomError> for FramebufferCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for FramebufferCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FramebufferCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
Self::OomError(_) => write!(
|
||||
f,
|
||||
"no memory available",
|
||||
),
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "no memory available",),
|
||||
Self::Attachment2dArrayCompatibleDepthStencil { attachment } => write!(
|
||||
f,
|
||||
"attachment image {} is a 2D image view created from a 3D image, and has a depth/stencil format",
|
||||
"attachment image {} is a 2D image view created from a 3D image, and has a \
|
||||
depth/stencil format",
|
||||
attachment,
|
||||
),
|
||||
Self::AttachmentComponentMappingNotIdentity { attachment } => write!(
|
||||
@ -632,7 +627,8 @@ impl Display for FramebufferCreationError {
|
||||
min,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment image {} has an extent ({:?}) smaller than the provided `extent` ({:?})",
|
||||
"attachment image {} has an extent ({:?}) smaller than the provided `extent` \
|
||||
({:?})",
|
||||
attachment, provided, min,
|
||||
),
|
||||
Self::AttachmentFormatMismatch {
|
||||
@ -641,24 +637,19 @@ impl Display for FramebufferCreationError {
|
||||
required,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment image {} has a `format` ({:?}) different from what the render pass requires ({:?})",
|
||||
"attachment image {} has a `format` ({:?}) different from what the render pass \
|
||||
requires ({:?})",
|
||||
attachment, provided, required,
|
||||
),
|
||||
Self::AttachmentMissingUsage {
|
||||
attachment,
|
||||
usage,
|
||||
} => write!(
|
||||
Self::AttachmentMissingUsage { attachment, usage } => write!(
|
||||
f,
|
||||
"attachment image {} is missing usage `{}` that the render pass requires it to have",
|
||||
"attachment image {} is missing usage `{}` that the render pass requires it to \
|
||||
have",
|
||||
attachment, usage,
|
||||
),
|
||||
Self::AttachmentMultipleMipLevels {
|
||||
attachment,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment image {} has multiple mip levels",
|
||||
attachment,
|
||||
),
|
||||
Self::AttachmentMultipleMipLevels { attachment } => {
|
||||
write!(f, "attachment image {} has multiple mip levels", attachment)
|
||||
}
|
||||
Self::AttachmentNotEnoughLayers {
|
||||
attachment,
|
||||
provided,
|
||||
@ -674,27 +665,29 @@ impl Display for FramebufferCreationError {
|
||||
required,
|
||||
} => write!(
|
||||
f,
|
||||
"attachment image {} has a `samples` ({:?}) different from what the render pass requires ({:?})",
|
||||
"attachment image {} has a `samples` ({:?}) different from what the render pass \
|
||||
requires ({:?})",
|
||||
attachment, provided, required,
|
||||
),
|
||||
Self::AttachmentViewType3d {
|
||||
attachment,
|
||||
} => write!(
|
||||
Self::AttachmentViewType3d { attachment } => write!(
|
||||
f,
|
||||
"attachment image {} has a `ty` of `ImageViewType::Dim3d`",
|
||||
attachment,
|
||||
),
|
||||
Self::AutoExtentAttachmentsEmpty => write!(
|
||||
f,
|
||||
"one of the elements of `extent` is zero, but no attachment images were given to calculate the extent from",
|
||||
"one of the elements of `extent` is zero, but no attachment images were given to \
|
||||
calculate the extent from",
|
||||
),
|
||||
Self::AutoLayersAttachmentsEmpty => write!(
|
||||
f,
|
||||
"`layers` is zero, but no attachment images were given to calculate the number of layers from",
|
||||
"`layers` is zero, but no attachment images were given to calculate the number of \
|
||||
layers from",
|
||||
),
|
||||
Self::MaxFramebufferExtentExceeded { provided, max } => write!(
|
||||
f,
|
||||
"the provided `extent` ({:?}) exceeds the `max_framebuffer_width` or `max_framebuffer_height` limits ({:?})",
|
||||
"the provided `extent` ({:?}) exceeds the `max_framebuffer_width` or \
|
||||
`max_framebuffer_height` limits ({:?})",
|
||||
provided, max,
|
||||
),
|
||||
Self::MaxFramebufferLayersExceeded { provided, max } => write!(
|
||||
@ -708,7 +701,8 @@ impl Display for FramebufferCreationError {
|
||||
min,
|
||||
} => write!(
|
||||
f,
|
||||
"the render pass has multiview enabled, and attachment image {} has less layers ({}) than the number of views in the render pass ({})",
|
||||
"the render pass has multiview enabled, and attachment image {} has less layers \
|
||||
({}) than the number of views in the render pass ({})",
|
||||
attachment, provided, min,
|
||||
),
|
||||
Self::MultiviewLayersInvalid => write!(
|
||||
@ -720,7 +714,6 @@ impl Display for FramebufferCreationError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for FramebufferCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
Self::from(OomError::from(err))
|
||||
}
|
||||
|
@ -198,6 +198,7 @@ impl RenderPass {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
handle: ash::vk::RenderPass,
|
||||
@ -399,21 +400,21 @@ impl RenderPass {
|
||||
if !(subpasses1.iter())
|
||||
.zip(subpasses2.iter())
|
||||
.all(|(subpass1, subpass2)| {
|
||||
let &SubpassDescription {
|
||||
let SubpassDescription {
|
||||
view_mask: view_mask1,
|
||||
input_attachments: ref input_attachments1,
|
||||
color_attachments: ref color_attachments1,
|
||||
resolve_attachments: ref resolve_attachments1,
|
||||
depth_stencil_attachment: ref depth_stencil_attachment1,
|
||||
input_attachments: input_attachments1,
|
||||
color_attachments: color_attachments1,
|
||||
resolve_attachments: resolve_attachments1,
|
||||
depth_stencil_attachment: depth_stencil_attachment1,
|
||||
preserve_attachments: _,
|
||||
_ne: _,
|
||||
} = subpass1;
|
||||
let &SubpassDescription {
|
||||
let SubpassDescription {
|
||||
view_mask: view_mask2,
|
||||
input_attachments: ref input_attachments2,
|
||||
color_attachments: ref color_attachments2,
|
||||
resolve_attachments: ref resolve_attachments2,
|
||||
depth_stencil_attachment: ref depth_stencil_attachment2,
|
||||
input_attachments: input_attachments2,
|
||||
color_attachments: color_attachments2,
|
||||
resolve_attachments: resolve_attachments2,
|
||||
depth_stencil_attachment: depth_stencil_attachment2,
|
||||
preserve_attachments: _,
|
||||
_ne: _,
|
||||
} = subpass2;
|
||||
@ -546,7 +547,6 @@ impl PartialEq for RenderPass {
|
||||
impl Eq for RenderPass {}
|
||||
|
||||
impl Hash for RenderPass {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device.hash(state);
|
||||
@ -727,6 +727,7 @@ impl Subpass {
|
||||
|
||||
/// Returns `true` if this subpass is compatible with the fragment output definition.
|
||||
// TODO: return proper error
|
||||
#[inline]
|
||||
pub fn is_compatible_with(&self, shader_interface: &ShaderInterface) -> bool {
|
||||
self.render_pass
|
||||
.is_compatible_with_shader(self.subpass_id, shader_interface)
|
||||
|
@ -448,6 +448,7 @@ impl Sampler {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
handle: ash::vk::Sampler,
|
||||
@ -752,7 +753,6 @@ impl PartialEq for Sampler {
|
||||
impl Eq for Sampler {}
|
||||
|
||||
impl Hash for Sampler {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -854,22 +854,19 @@ pub enum SamplerCreationError {
|
||||
}
|
||||
|
||||
impl Error for SamplerCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
SamplerCreationError::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
SamplerCreationError::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SamplerCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
Self::TooManyObjects => write!(f, "too many simultaneous sampler objects",),
|
||||
|
||||
Self::TooManyObjects => write!(f, "too many simultaneous sampler objects"),
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -878,61 +875,77 @@ impl Display for SamplerCreationError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::AnisotropyInvalidFilter { .. } => write!(f, "anisotropy was enabled with an invalid filter"),
|
||||
Self::CompareInvalidReductionMode { .. } => write!(f, "depth comparison was enabled with an invalid reduction mode"),
|
||||
Self::AnisotropyInvalidFilter { .. } => {
|
||||
write!(f, "anisotropy was enabled with an invalid filter")
|
||||
}
|
||||
Self::CompareInvalidReductionMode { .. } => write!(
|
||||
f,
|
||||
"depth comparison was enabled with an invalid reduction mode",
|
||||
),
|
||||
Self::MaxSamplerAnisotropyExceeded { .. } => {
|
||||
write!(f, "max_sampler_anisotropy limit exceeded")
|
||||
}
|
||||
Self::MaxSamplerLodBiasExceeded { .. } => write!(f, "mip lod bias limit exceeded"),
|
||||
Self::SamplerYcbcrConversionAnisotropyEnabled => write!(
|
||||
f,
|
||||
"sampler YCbCr conversion was enabled together with anisotropy"
|
||||
"sampler YCbCr conversion was enabled together with anisotropy",
|
||||
),
|
||||
Self::SamplerYcbcrConversionChromaFilterMismatch { .. } => write!(
|
||||
f,
|
||||
"sampler YCbCr conversion was enabled, and its format does not support
|
||||
`sampled_image_ycbcr_conversion_separate_reconstruction_filter`, but `mag_filter`
|
||||
or `min_filter` did not match the conversion's `chroma_filter`",
|
||||
),
|
||||
Self::SamplerYcbcrConversionInvalidAddressMode { .. } => write!(
|
||||
f,
|
||||
"sampler YCbCr conversion was enabled, but the address mode for u, v or w was
|
||||
something other than `ClampToEdge`",
|
||||
),
|
||||
Self::SamplerYcbcrConversionInvalidReductionMode { .. } => write!(
|
||||
f,
|
||||
"sampler YCbCr conversion was enabled, but the reduction mode was something other \
|
||||
than `WeightedAverage`",
|
||||
),
|
||||
Self::SamplerYcbcrConversionChromaFilterMismatch { .. } => write!(f, "sampler YCbCr conversion was enabled, and its format does not support `sampled_image_ycbcr_conversion_separate_reconstruction_filter`, but `mag_filter` or `min_filter` did not match the conversion's `chroma_filter`"),
|
||||
Self::SamplerYcbcrConversionInvalidAddressMode { .. } => write!(f, "sampler YCbCr conversion was enabled, but the address mode for u, v or w was something other than `ClampToEdge`"),
|
||||
Self::SamplerYcbcrConversionInvalidReductionMode { .. } => write!(f, "sampler YCbCr conversion was enabled, but the reduction mode was something other than `WeightedAverage`"),
|
||||
Self::SamplerYcbcrConversionUnnormalizedCoordinatesEnabled => write!(
|
||||
f,
|
||||
"sampler YCbCr conversion was enabled together with unnormalized coordinates"
|
||||
"sampler YCbCr conversion was enabled together with unnormalized coordinates",
|
||||
),
|
||||
Self::UnnormalizedCoordinatesAnisotropyEnabled => write!(
|
||||
f,
|
||||
"unnormalized coordinates were enabled together with anisotropy"
|
||||
"unnormalized coordinates were enabled together with anisotropy",
|
||||
),
|
||||
Self::UnnormalizedCoordinatesCompareEnabled => write!(
|
||||
f,
|
||||
"unnormalized coordinates were enabled together with depth comparison"
|
||||
"unnormalized coordinates were enabled together with depth comparison",
|
||||
),
|
||||
Self::UnnormalizedCoordinatesFiltersNotEqual { .. } => write!(
|
||||
f,
|
||||
"unnormalized coordinates were enabled, but the min and mag filters were not equal"
|
||||
"unnormalized coordinates were enabled, but the min and mag filters were not equal",
|
||||
),
|
||||
Self::UnnormalizedCoordinatesInvalidAddressMode { .. } => write!(
|
||||
f,
|
||||
"unnormalized coordinates were enabled, but the address mode for u or v was something other than `ClampToEdge` or `ClampToBorder`"
|
||||
"unnormalized coordinates were enabled, but the address mode for u or v was \
|
||||
something other than `ClampToEdge` or `ClampToBorder`",
|
||||
),
|
||||
Self::UnnormalizedCoordinatesInvalidMipmapMode { .. } => write!(
|
||||
f,
|
||||
"unnormalized coordinates were enabled, but the mipmap mode was not `Nearest`"
|
||||
"unnormalized coordinates were enabled, but the mipmap mode was not `Nearest`",
|
||||
),
|
||||
Self::UnnormalizedCoordinatesNonzeroLod { .. } => write!(
|
||||
f,
|
||||
"unnormalized coordinates were enabled, but the LOD range was not zero"
|
||||
"unnormalized coordinates were enabled, but the LOD range was not zero",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for SamplerCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for SamplerCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)),
|
||||
@ -944,7 +957,6 @@ impl From<VulkanError> for SamplerCreationError {
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for SamplerCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
@ -1084,6 +1096,7 @@ pub struct SamplerCreateInfo {
|
||||
}
|
||||
|
||||
impl Default for SamplerCreateInfo {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mag_filter: Filter::Nearest,
|
||||
@ -1475,16 +1488,55 @@ impl Error for SamplerImageViewIncompatibleError {}
|
||||
impl Display for SamplerImageViewIncompatibleError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::BorderColorFormatNotCompatible => write!(f, "the sampler has a border color with a numeric type different from the image view"),
|
||||
Self::BorderColorOpaqueBlackNotIdentitySwizzled => write!(f, "the sampler has an opaque black border color, but the image view is not identity swizzled"),
|
||||
Self::DepthComparisonNotSupported => write!(f, "the sampler has depth comparison enabled, but this is not supported by the image view"),
|
||||
Self::DepthComparisonWrongAspect => write!(f, "the sampler has depth comparison enabled, but the image view does not select the `depth` aspect"),
|
||||
Self::FilterLinearNotSupported => write!(f, "the sampler uses a linear filter, but this is not supported by the image view's format features"),
|
||||
Self::FilterCubicNotSupported => write!(f, "the sampler uses a cubic filter, but this is not supported by the image view's format features"),
|
||||
Self::FilterCubicMinmaxNotSupported => write!(f, "the sampler uses a cubic filter with a `Min` or `Max` reduction mode, but this is not supported by the image view's format features"),
|
||||
Self::MipmapModeLinearNotSupported => write!(f, "the sampler uses a linear mipmap mode, but this is not supported by the image view's format features"),
|
||||
Self::UnnormalizedCoordinatesMultipleMipLevels => write!(f, "the sampler uses unnormalized coordinates, but the image view has multiple mip levels"),
|
||||
Self::UnnormalizedCoordinatesViewTypeNotCompatible => write!(f, "the sampler uses unnormalized coordinates, but the image view has a type other than `Dim1d` or `Dim2d`"),
|
||||
Self::BorderColorFormatNotCompatible => write!(
|
||||
f,
|
||||
"the sampler has a border color with a numeric type different from the image view",
|
||||
),
|
||||
Self::BorderColorOpaqueBlackNotIdentitySwizzled => write!(
|
||||
f,
|
||||
"the sampler has an opaque black border color, but the image view is not identity \
|
||||
swizzled",
|
||||
),
|
||||
Self::DepthComparisonNotSupported => write!(
|
||||
f,
|
||||
"the sampler has depth comparison enabled, but this is not supported by the image \
|
||||
view",
|
||||
),
|
||||
Self::DepthComparisonWrongAspect => write!(
|
||||
f,
|
||||
"the sampler has depth comparison enabled, but the image view does not select the \
|
||||
`depth` aspect",
|
||||
),
|
||||
Self::FilterLinearNotSupported => write!(
|
||||
f,
|
||||
"the sampler uses a linear filter, but this is not supported by the image view's \
|
||||
format features",
|
||||
),
|
||||
Self::FilterCubicNotSupported => write!(
|
||||
f,
|
||||
"the sampler uses a cubic filter, but this is not supported by the image view's \
|
||||
format features",
|
||||
),
|
||||
Self::FilterCubicMinmaxNotSupported => write!(
|
||||
f,
|
||||
"the sampler uses a cubic filter with a `Min` or `Max` reduction mode, but this is \
|
||||
not supported by the image view's format features",
|
||||
),
|
||||
Self::MipmapModeLinearNotSupported => write!(
|
||||
f,
|
||||
"the sampler uses a linear mipmap mode, but this is not supported by the image \
|
||||
view's format features",
|
||||
),
|
||||
Self::UnnormalizedCoordinatesMultipleMipLevels => write!(
|
||||
f,
|
||||
"the sampler uses unnormalized coordinates, but the image view has multiple mip \
|
||||
levels",
|
||||
),
|
||||
Self::UnnormalizedCoordinatesViewTypeNotCompatible => write!(
|
||||
f,
|
||||
"the sampler uses unnormalized coordinates, but the image view has a type other \
|
||||
than `Dim1d` or `Dim2d`",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -362,6 +362,7 @@ impl SamplerYcbcrConversion {
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
/// - `create_info.format` must be `Some`.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
handle: ash::vk::SamplerYcbcrConversion,
|
||||
@ -377,6 +378,7 @@ impl SamplerYcbcrConversion {
|
||||
force_explicit_reconstruction,
|
||||
_ne: _,
|
||||
} = create_info;
|
||||
|
||||
Arc::new(SamplerYcbcrConversion {
|
||||
handle,
|
||||
device,
|
||||
@ -506,7 +508,6 @@ impl PartialEq for SamplerYcbcrConversion {
|
||||
impl Eq for SamplerYcbcrConversion {}
|
||||
|
||||
impl Hash for SamplerYcbcrConversion {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -557,21 +558,18 @@ pub enum SamplerYcbcrConversionCreationError {
|
||||
}
|
||||
|
||||
impl Error for SamplerYcbcrConversionCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
SamplerYcbcrConversionCreationError::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
SamplerYcbcrConversionCreationError::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SamplerYcbcrConversionCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -580,7 +578,6 @@ impl Display for SamplerYcbcrConversionCreationError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::CubicFilterNotSupported => {
|
||||
write!(f, "the `Cubic` filter was specified")
|
||||
}
|
||||
@ -596,43 +593,37 @@ impl Display for SamplerYcbcrConversionCreationError {
|
||||
Self::FormatChromaOffsetNotSupported => {
|
||||
write!(f, "the format does not support the chosen chroma offsets")
|
||||
}
|
||||
Self::FormatInvalidComponentMapping => {
|
||||
write!(
|
||||
f,
|
||||
"the component mapping was not valid for use with the chosen format"
|
||||
)
|
||||
}
|
||||
Self::FormatForceExplicitReconstructionNotSupported => {
|
||||
write!(
|
||||
f,
|
||||
"the format does not support `force_explicit_reconstruction`"
|
||||
)
|
||||
}
|
||||
Self::FormatInvalidComponentMapping => write!(
|
||||
f,
|
||||
"the component mapping was not valid for use with the chosen format",
|
||||
),
|
||||
Self::FormatForceExplicitReconstructionNotSupported => write!(
|
||||
f,
|
||||
"the format does not support `force_explicit_reconstruction`",
|
||||
),
|
||||
Self::FormatLinearFilterNotSupported => {
|
||||
write!(f, "the format does not support the `Linear` filter")
|
||||
}
|
||||
Self::YcbcrModelInvalidComponentMapping => {
|
||||
write!(
|
||||
f,
|
||||
"the component mapping was not valid for use with the chosen YCbCr model"
|
||||
)
|
||||
}
|
||||
Self::YcbcrRangeFormatNotEnoughBits => {
|
||||
write!(f, "for the chosen `ycbcr_range`, the R, G or B components being read from the `format` do not have the minimum number of required bits")
|
||||
}
|
||||
Self::YcbcrModelInvalidComponentMapping => write!(
|
||||
f,
|
||||
"the component mapping was not valid for use with the chosen YCbCr model",
|
||||
),
|
||||
Self::YcbcrRangeFormatNotEnoughBits => write!(
|
||||
f,
|
||||
"for the chosen `ycbcr_range`, the R, G or B components being read from the \
|
||||
`format` do not have the minimum number of required bits",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for SamplerYcbcrConversionCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> SamplerYcbcrConversionCreationError {
|
||||
SamplerYcbcrConversionCreationError::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for SamplerYcbcrConversionCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> SamplerYcbcrConversionCreationError {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => {
|
||||
@ -647,7 +638,6 @@ impl From<VulkanError> for SamplerYcbcrConversionCreationError {
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for SamplerYcbcrConversionCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -63,6 +63,7 @@ impl ShaderModule {
|
||||
/// # Safety
|
||||
///
|
||||
/// - The SPIR-V code is not validated beyond the minimum needed to extract the information.
|
||||
#[inline]
|
||||
pub unsafe fn from_words(
|
||||
device: Arc<Device>,
|
||||
words: &[u32],
|
||||
@ -84,11 +85,13 @@ impl ShaderModule {
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the length of `bytes` is not a multiple of 4.
|
||||
#[inline]
|
||||
pub unsafe fn from_bytes(
|
||||
device: Arc<Device>,
|
||||
bytes: &[u8],
|
||||
) -> Result<Arc<ShaderModule>, ShaderCreationError> {
|
||||
assert!((bytes.len() % 4) == 0);
|
||||
|
||||
Self::from_words(
|
||||
device,
|
||||
std::slice::from_raw_parts(
|
||||
@ -204,6 +207,7 @@ impl ShaderModule {
|
||||
entry_points: impl IntoIterator<Item = (String, ExecutionModel, EntryPointInfo)>,
|
||||
) -> Result<Arc<ShaderModule>, ShaderCreationError> {
|
||||
assert!((bytes.len() % 4) == 0);
|
||||
|
||||
Self::from_words_with_data(
|
||||
device,
|
||||
std::slice::from_raw_parts(
|
||||
@ -220,6 +224,7 @@ impl ShaderModule {
|
||||
/// Returns information about the entry point with the provided name. Returns `None` if no entry
|
||||
/// point with that name exists in the shader module or if multiple entry points with the same
|
||||
/// name exist.
|
||||
#[inline]
|
||||
pub fn entry_point<'a>(&'a self, name: &str) -> Option<EntryPoint<'a>> {
|
||||
self.entry_points.get(name).and_then(|infos| {
|
||||
if infos.len() == 1 {
|
||||
@ -234,8 +239,9 @@ impl ShaderModule {
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns information about the entry point with the provided name and execution model. Returns
|
||||
/// `None` if no entry and execution model exists in the shader module.
|
||||
/// Returns information about the entry point with the provided name and execution model.
|
||||
/// Returns `None` if no entry and execution model exists in the shader module.
|
||||
#[inline]
|
||||
pub fn entry_point_with_execution<'a>(
|
||||
&'a self,
|
||||
name: &str,
|
||||
@ -294,7 +300,6 @@ pub enum ShaderCreationError {
|
||||
}
|
||||
|
||||
impl Error for ShaderCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
@ -604,6 +609,7 @@ pub struct DescriptorIdentifier {
|
||||
impl DescriptorRequirements {
|
||||
/// Produces the intersection of two descriptor requirements, so that the requirements of both
|
||||
/// are satisfied. An error is returned if the requirements conflict.
|
||||
#[inline]
|
||||
pub fn intersection(&self, other: &Self) -> Result<Self, DescriptorRequirementsIncompatible> {
|
||||
let descriptor_types: Vec<_> = self
|
||||
.descriptor_types
|
||||
@ -731,7 +737,7 @@ pub struct SpecializationConstantRequirements {
|
||||
///
|
||||
/// This trait is implemented on `()` for shaders that don't have any specialization constant.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use vulkano::shader::SpecializationConstants;
|
||||
@ -774,7 +780,6 @@ pub struct SpecializationConstantRequirements {
|
||||
/// - The `SpecializationMapEntry` returned must contain valid offsets and sizes.
|
||||
/// - The size of each `SpecializationMapEntry` must match the size of the corresponding constant
|
||||
/// (`4` for booleans).
|
||||
///
|
||||
pub unsafe trait SpecializationConstants {
|
||||
/// Returns descriptors of the struct's layout.
|
||||
fn descriptors() -> &'static [SpecializationMapEntry];
|
||||
@ -840,6 +845,7 @@ impl ShaderInterface {
|
||||
}
|
||||
|
||||
/// Creates a description of an empty shader interface.
|
||||
#[inline]
|
||||
pub const fn empty() -> ShaderInterface {
|
||||
ShaderInterface {
|
||||
elements: Vec::new(),
|
||||
@ -855,6 +861,7 @@ impl ShaderInterface {
|
||||
/// Checks whether the interface is potentially compatible with another one.
|
||||
///
|
||||
/// Returns `Ok` if the two interfaces are compatible.
|
||||
#[inline]
|
||||
pub fn matches(&self, other: &ShaderInterface) -> Result<(), ShaderInterfaceMismatchError> {
|
||||
if self.elements().len() != other.elements().len() {
|
||||
return Err(ShaderInterfaceMismatchError::ElementsCountMismatch {
|
||||
@ -977,6 +984,7 @@ pub enum ShaderScalarType {
|
||||
|
||||
// https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap43.html#formats-numericformat
|
||||
impl From<NumericType> for ShaderScalarType {
|
||||
#[inline]
|
||||
fn from(val: NumericType) -> Self {
|
||||
match val {
|
||||
NumericType::SFLOAT => Self::Float,
|
||||
@ -1023,12 +1031,11 @@ pub enum ShaderInterfaceMismatchError {
|
||||
impl Error for ShaderInterfaceMismatchError {}
|
||||
|
||||
impl Display for ShaderInterfaceMismatchError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
match self {
|
||||
ShaderInterfaceMismatchError::ElementsCountMismatch { .. } => {
|
||||
"the number of elements mismatches"
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ use ahash::{HashMap, HashSet};
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// Returns an iterator of the capabilities used by `spirv`.
|
||||
#[inline]
|
||||
pub fn spirv_capabilities(spirv: &Spirv) -> impl Iterator<Item = &Capability> {
|
||||
spirv
|
||||
.iter_capability()
|
||||
@ -39,6 +40,7 @@ pub fn spirv_capabilities(spirv: &Spirv) -> impl Iterator<Item = &Capability> {
|
||||
}
|
||||
|
||||
/// Returns an iterator of the extensions used by `spirv`.
|
||||
#[inline]
|
||||
pub fn spirv_extensions(spirv: &Spirv) -> impl Iterator<Item = &str> {
|
||||
spirv
|
||||
.iter_extension()
|
||||
@ -49,6 +51,7 @@ pub fn spirv_extensions(spirv: &Spirv) -> impl Iterator<Item = &str> {
|
||||
}
|
||||
|
||||
/// Returns an iterator over all entry points in `spirv`, with information about the entry point.
|
||||
#[inline]
|
||||
pub fn entry_points(
|
||||
spirv: &Spirv,
|
||||
) -> impl Iterator<Item = (String, ExecutionModel, EntryPointInfo)> + '_ {
|
||||
@ -56,13 +59,13 @@ pub fn entry_points(
|
||||
|
||||
spirv.iter_entry_point().filter_map(move |instruction| {
|
||||
let (execution_model, function_id, entry_point_name, interface) = match instruction {
|
||||
&Instruction::EntryPoint {
|
||||
ref execution_model,
|
||||
Instruction::EntryPoint {
|
||||
execution_model,
|
||||
entry_point,
|
||||
ref name,
|
||||
ref interface,
|
||||
name,
|
||||
interface,
|
||||
..
|
||||
} => (execution_model, entry_point, name, interface),
|
||||
} => (execution_model, *entry_point, name, interface),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
@ -210,7 +213,6 @@ fn inspect_entry_point(
|
||||
spirv: &Spirv,
|
||||
entry_point: Id,
|
||||
) -> HashMap<(u32, u32), DescriptorRequirements> {
|
||||
#[inline]
|
||||
fn instruction_chain<'a, const N: usize>(
|
||||
result: &'a mut HashMap<Id, DescriptorVariable>,
|
||||
global: &HashMap<Id, DescriptorVariable>,
|
||||
@ -226,8 +228,8 @@ fn inspect_entry_point(
|
||||
return Some((variable, Some(0)));
|
||||
}
|
||||
|
||||
let (id, indexes) = match spirv.id(id).instruction() {
|
||||
&Instruction::AccessChain {
|
||||
let (id, indexes) = match *spirv.id(id).instruction() {
|
||||
Instruction::AccessChain {
|
||||
base, ref indexes, ..
|
||||
} => (base, indexes),
|
||||
_ => return None,
|
||||
@ -237,8 +239,8 @@ fn inspect_entry_point(
|
||||
// Variable was accessed with an access chain.
|
||||
// Retrieve index from instruction if it's a constant value.
|
||||
// TODO: handle a `None` index too?
|
||||
let index = match spirv.id(*indexes.first().unwrap()).instruction() {
|
||||
&Instruction::Constant { ref value, .. } => Some(value[0]),
|
||||
let index = match *spirv.id(*indexes.first().unwrap()).instruction() {
|
||||
Instruction::Constant { ref value, .. } => Some(value[0]),
|
||||
_ => None,
|
||||
};
|
||||
let variable = result.entry(id).or_insert_with(|| variable.clone());
|
||||
@ -248,26 +250,23 @@ fn inspect_entry_point(
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inst_image_texel_pointer(spirv: &Spirv, id: Id) -> Option<Id> {
|
||||
match spirv.id(id).instruction() {
|
||||
&Instruction::ImageTexelPointer { image, .. } => Some(image),
|
||||
match *spirv.id(id).instruction() {
|
||||
Instruction::ImageTexelPointer { image, .. } => Some(image),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inst_load(spirv: &Spirv, id: Id) -> Option<Id> {
|
||||
match spirv.id(id).instruction() {
|
||||
&Instruction::Load { pointer, .. } => Some(pointer),
|
||||
match *spirv.id(id).instruction() {
|
||||
Instruction::Load { pointer, .. } => Some(pointer),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inst_sampled_image(spirv: &Spirv, id: Id) -> Option<Id> {
|
||||
match spirv.id(id).instruction() {
|
||||
&Instruction::SampledImage { sampler, .. } => Some(sampler),
|
||||
match *spirv.id(id).instruction() {
|
||||
Instruction::SampledImage { sampler, .. } => Some(sampler),
|
||||
_ => Some(id),
|
||||
}
|
||||
}
|
||||
@ -283,15 +282,15 @@ fn inspect_entry_point(
|
||||
let mut in_function = false;
|
||||
for instruction in spirv.instructions() {
|
||||
if !in_function {
|
||||
match instruction {
|
||||
Instruction::Function { result_id, .. } if result_id == &function => {
|
||||
match *instruction {
|
||||
Instruction::Function { result_id, .. } if result_id == function => {
|
||||
in_function = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
match instruction {
|
||||
&Instruction::AtomicLoad { pointer, .. } => {
|
||||
match *instruction {
|
||||
Instruction::AtomicLoad { pointer, .. } => {
|
||||
// Storage buffer
|
||||
instruction_chain(result, global, spirv, [], pointer);
|
||||
|
||||
@ -307,26 +306,26 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::AtomicStore { pointer, .. }
|
||||
| &Instruction::AtomicExchange { pointer, .. }
|
||||
| &Instruction::AtomicCompareExchange { pointer, .. }
|
||||
| &Instruction::AtomicCompareExchangeWeak { pointer, .. }
|
||||
| &Instruction::AtomicIIncrement { pointer, .. }
|
||||
| &Instruction::AtomicIDecrement { pointer, .. }
|
||||
| &Instruction::AtomicIAdd { pointer, .. }
|
||||
| &Instruction::AtomicISub { pointer, .. }
|
||||
| &Instruction::AtomicSMin { pointer, .. }
|
||||
| &Instruction::AtomicUMin { pointer, .. }
|
||||
| &Instruction::AtomicSMax { pointer, .. }
|
||||
| &Instruction::AtomicUMax { pointer, .. }
|
||||
| &Instruction::AtomicAnd { pointer, .. }
|
||||
| &Instruction::AtomicOr { pointer, .. }
|
||||
| &Instruction::AtomicXor { pointer, .. }
|
||||
| &Instruction::AtomicFlagTestAndSet { pointer, .. }
|
||||
| &Instruction::AtomicFlagClear { pointer, .. }
|
||||
| &Instruction::AtomicFMinEXT { pointer, .. }
|
||||
| &Instruction::AtomicFMaxEXT { pointer, .. }
|
||||
| &Instruction::AtomicFAddEXT { pointer, .. } => {
|
||||
Instruction::AtomicStore { pointer, .. }
|
||||
| Instruction::AtomicExchange { pointer, .. }
|
||||
| Instruction::AtomicCompareExchange { pointer, .. }
|
||||
| Instruction::AtomicCompareExchangeWeak { pointer, .. }
|
||||
| Instruction::AtomicIIncrement { pointer, .. }
|
||||
| Instruction::AtomicIDecrement { pointer, .. }
|
||||
| Instruction::AtomicIAdd { pointer, .. }
|
||||
| Instruction::AtomicISub { pointer, .. }
|
||||
| Instruction::AtomicSMin { pointer, .. }
|
||||
| Instruction::AtomicUMin { pointer, .. }
|
||||
| Instruction::AtomicSMax { pointer, .. }
|
||||
| Instruction::AtomicUMax { pointer, .. }
|
||||
| Instruction::AtomicAnd { pointer, .. }
|
||||
| Instruction::AtomicOr { pointer, .. }
|
||||
| Instruction::AtomicXor { pointer, .. }
|
||||
| Instruction::AtomicFlagTestAndSet { pointer, .. }
|
||||
| Instruction::AtomicFlagClear { pointer, .. }
|
||||
| Instruction::AtomicFMinEXT { pointer, .. }
|
||||
| Instruction::AtomicFMaxEXT { pointer, .. }
|
||||
| Instruction::AtomicFAddEXT { pointer, .. } => {
|
||||
// Storage buffer
|
||||
if let Some((variable, Some(index))) =
|
||||
instruction_chain(result, global, spirv, [], pointer)
|
||||
@ -347,16 +346,16 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::CopyMemory { target, source, .. } => {
|
||||
Instruction::CopyMemory { target, source, .. } => {
|
||||
instruction_chain(result, global, spirv, [], target);
|
||||
instruction_chain(result, global, spirv, [], source);
|
||||
}
|
||||
|
||||
&Instruction::CopyObject { operand, .. } => {
|
||||
Instruction::CopyObject { operand, .. } => {
|
||||
instruction_chain(result, global, spirv, [], operand);
|
||||
}
|
||||
|
||||
&Instruction::ExtInst { ref operands, .. } => {
|
||||
Instruction::ExtInst { ref operands, .. } => {
|
||||
// We don't know which extended instructions take pointers,
|
||||
// so we must interpret every operand as a pointer.
|
||||
for &operand in operands {
|
||||
@ -364,7 +363,7 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::FunctionCall {
|
||||
Instruction::FunctionCall {
|
||||
function,
|
||||
ref arguments,
|
||||
..
|
||||
@ -386,16 +385,16 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::FunctionEnd => return,
|
||||
Instruction::FunctionEnd => return,
|
||||
|
||||
&Instruction::ImageGather {
|
||||
Instruction::ImageGather {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
}
|
||||
| &Instruction::ImageSparseGather {
|
||||
| Instruction::ImageSparseGather {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
} => {
|
||||
if let Some((variable, Some(index))) = instruction_chain(
|
||||
@ -420,8 +419,8 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::ImageDrefGather { sampled_image, .. }
|
||||
| &Instruction::ImageSparseDrefGather { sampled_image, .. } => {
|
||||
Instruction::ImageDrefGather { sampled_image, .. }
|
||||
| Instruction::ImageSparseDrefGather { sampled_image, .. } => {
|
||||
if let Some((variable, Some(index))) = instruction_chain(
|
||||
result,
|
||||
global,
|
||||
@ -437,24 +436,24 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::ImageSampleImplicitLod {
|
||||
Instruction::ImageSampleImplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
}
|
||||
| &Instruction::ImageSampleProjImplicitLod {
|
||||
| Instruction::ImageSampleProjImplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
}
|
||||
| &Instruction::ImageSparseSampleProjImplicitLod {
|
||||
| Instruction::ImageSparseSampleProjImplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
}
|
||||
| &Instruction::ImageSparseSampleImplicitLod {
|
||||
| Instruction::ImageSparseSampleImplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
} => {
|
||||
if let Some((variable, Some(index))) = instruction_chain(
|
||||
@ -478,14 +477,14 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::ImageSampleProjExplicitLod {
|
||||
Instruction::ImageSampleProjExplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
}
|
||||
| &Instruction::ImageSparseSampleProjExplicitLod {
|
||||
| Instruction::ImageSparseSampleProjExplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
} => {
|
||||
if let Some((variable, Some(index))) = instruction_chain(
|
||||
@ -508,24 +507,24 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::ImageSampleDrefImplicitLod {
|
||||
Instruction::ImageSampleDrefImplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
}
|
||||
| &Instruction::ImageSampleProjDrefImplicitLod {
|
||||
| Instruction::ImageSampleProjDrefImplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
}
|
||||
| &Instruction::ImageSparseSampleDrefImplicitLod {
|
||||
| Instruction::ImageSparseSampleDrefImplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
}
|
||||
| &Instruction::ImageSparseSampleProjDrefImplicitLod {
|
||||
| Instruction::ImageSparseSampleProjDrefImplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
} => {
|
||||
if let Some((variable, Some(index))) = instruction_chain(
|
||||
@ -550,24 +549,24 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::ImageSampleDrefExplicitLod {
|
||||
Instruction::ImageSampleDrefExplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
}
|
||||
| &Instruction::ImageSampleProjDrefExplicitLod {
|
||||
| Instruction::ImageSampleProjDrefExplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
}
|
||||
| &Instruction::ImageSparseSampleDrefExplicitLod {
|
||||
| Instruction::ImageSparseSampleDrefExplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
}
|
||||
| &Instruction::ImageSparseSampleProjDrefExplicitLod {
|
||||
| Instruction::ImageSparseSampleProjDrefExplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
} => {
|
||||
if let Some((variable, Some(index))) = instruction_chain(
|
||||
@ -591,14 +590,14 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::ImageSampleExplicitLod {
|
||||
Instruction::ImageSampleExplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
}
|
||||
| &Instruction::ImageSparseSampleExplicitLod {
|
||||
| Instruction::ImageSparseSampleExplicitLod {
|
||||
sampled_image,
|
||||
ref image_operands,
|
||||
image_operands,
|
||||
..
|
||||
} => {
|
||||
if let Some((variable, Some(index))) = instruction_chain(
|
||||
@ -626,11 +625,11 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::ImageTexelPointer { image, .. } => {
|
||||
Instruction::ImageTexelPointer { image, .. } => {
|
||||
instruction_chain(result, global, spirv, [], image);
|
||||
}
|
||||
|
||||
&Instruction::ImageRead { image, .. } => {
|
||||
Instruction::ImageRead { image, .. } => {
|
||||
if let Some((variable, Some(index))) =
|
||||
instruction_chain(result, global, spirv, [inst_load], image)
|
||||
{
|
||||
@ -638,7 +637,7 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::ImageWrite { image, .. } => {
|
||||
Instruction::ImageWrite { image, .. } => {
|
||||
if let Some((variable, Some(index))) =
|
||||
instruction_chain(result, global, spirv, [inst_load], image)
|
||||
{
|
||||
@ -646,11 +645,11 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::Load { pointer, .. } => {
|
||||
Instruction::Load { pointer, .. } => {
|
||||
instruction_chain(result, global, spirv, [], pointer);
|
||||
}
|
||||
|
||||
&Instruction::SampledImage { image, sampler, .. } => {
|
||||
Instruction::SampledImage { image, sampler, .. } => {
|
||||
let identifier =
|
||||
match instruction_chain(result, global, spirv, [inst_load], image) {
|
||||
Some((variable, Some(index))) => DescriptorIdentifier {
|
||||
@ -673,7 +672,7 @@ fn inspect_entry_point(
|
||||
}
|
||||
}
|
||||
|
||||
&Instruction::Store { pointer, .. } => {
|
||||
Instruction::Store { pointer, .. } => {
|
||||
if let Some((variable, Some(index))) =
|
||||
instruction_chain(result, global, spirv, [], pointer)
|
||||
{
|
||||
@ -696,6 +695,7 @@ fn inspect_entry_point(
|
||||
spirv,
|
||||
entry_point,
|
||||
);
|
||||
|
||||
result
|
||||
.into_iter()
|
||||
.map(|(_, variable)| ((variable.set, variable.binding), variable.reqs))
|
||||
@ -714,15 +714,15 @@ fn descriptor_requirements_of(spirv: &Spirv, variable_id: Id) -> DescriptorVaria
|
||||
};
|
||||
|
||||
let (mut next_type_id, is_storage_buffer) = {
|
||||
let variable_type_id = match variable_id_info.instruction() {
|
||||
Instruction::Variable { result_type_id, .. } => *result_type_id,
|
||||
let variable_type_id = match *variable_id_info.instruction() {
|
||||
Instruction::Variable { result_type_id, .. } => result_type_id,
|
||||
_ => panic!("Id {} is not a variable", variable_id),
|
||||
};
|
||||
|
||||
match spirv.id(variable_type_id).instruction() {
|
||||
match *spirv.id(variable_type_id).instruction() {
|
||||
Instruction::TypePointer {
|
||||
ty, storage_class, ..
|
||||
} => (Some(*ty), *storage_class == StorageClass::StorageBuffer),
|
||||
} => (Some(ty), storage_class == StorageClass::StorageBuffer),
|
||||
_ => panic!(
|
||||
"Variable {} result_type_id does not refer to a TypePointer instruction",
|
||||
variable_id
|
||||
@ -733,7 +733,7 @@ fn descriptor_requirements_of(spirv: &Spirv, variable_id: Id) -> DescriptorVaria
|
||||
while let Some(id) = next_type_id {
|
||||
let id_info = spirv.id(id);
|
||||
|
||||
next_type_id = match id_info.instruction() {
|
||||
next_type_id = match *id_info.instruction() {
|
||||
Instruction::TypeStruct { .. } => {
|
||||
let decoration_block = id_info.iter_decoration().any(|instruction| {
|
||||
matches!(
|
||||
@ -757,7 +757,8 @@ fn descriptor_requirements_of(spirv: &Spirv, variable_id: Id) -> DescriptorVaria
|
||||
|
||||
assert!(
|
||||
decoration_block ^ decoration_buffer_block,
|
||||
"Structs in shader interface are expected to be decorated with one of Block or BufferBlock"
|
||||
"Structs in shader interface are expected to be decorated with one of Block or \
|
||||
BufferBlock",
|
||||
);
|
||||
|
||||
if decoration_buffer_block || decoration_block && is_storage_buffer {
|
||||
@ -775,16 +776,20 @@ fn descriptor_requirements_of(spirv: &Spirv, variable_id: Id) -> DescriptorVaria
|
||||
None
|
||||
}
|
||||
|
||||
&Instruction::TypeImage {
|
||||
Instruction::TypeImage {
|
||||
sampled_type,
|
||||
ref dim,
|
||||
dim,
|
||||
arrayed,
|
||||
ms,
|
||||
sampled,
|
||||
ref image_format,
|
||||
image_format,
|
||||
..
|
||||
} => {
|
||||
assert!(sampled != 0, "Vulkan requires that variables of type OpTypeImage have a Sampled operand of 1 or 2");
|
||||
assert!(
|
||||
sampled != 0,
|
||||
"Vulkan requires that variables of type OpTypeImage have a Sampled operand of \
|
||||
1 or 2",
|
||||
);
|
||||
reqs.image_format = image_format.clone().into();
|
||||
reqs.image_multisampled = ms != 0;
|
||||
reqs.image_scalar_type = Some(match *spirv.id(sampled_type).instruction() {
|
||||
@ -809,7 +814,7 @@ fn descriptor_requirements_of(spirv: &Spirv, variable_id: Id) -> DescriptorVaria
|
||||
Dim::SubpassData => {
|
||||
assert!(
|
||||
reqs.image_format.is_none(),
|
||||
"If Dim is SubpassData, Image Format must be Unknown"
|
||||
"If Dim is SubpassData, Image Format must be Unknown",
|
||||
);
|
||||
assert!(sampled == 2, "If Dim is SubpassData, Sampled must be 2");
|
||||
assert!(arrayed == 0, "If Dim is SubpassData, Arrayed must be 0");
|
||||
@ -854,23 +859,25 @@ fn descriptor_requirements_of(spirv: &Spirv, variable_id: Id) -> DescriptorVaria
|
||||
None
|
||||
}
|
||||
|
||||
&Instruction::TypeSampler { .. } => {
|
||||
Instruction::TypeSampler { .. } => {
|
||||
reqs.descriptor_types = vec![DescriptorType::Sampler];
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
&Instruction::TypeSampledImage { image_type, .. } => {
|
||||
Instruction::TypeSampledImage { image_type, .. } => {
|
||||
reqs.descriptor_types = vec![DescriptorType::CombinedImageSampler];
|
||||
|
||||
Some(image_type)
|
||||
}
|
||||
|
||||
&Instruction::TypeArray {
|
||||
Instruction::TypeArray {
|
||||
element_type,
|
||||
length,
|
||||
..
|
||||
} => {
|
||||
let len = match spirv.id(length).instruction() {
|
||||
&Instruction::Constant { ref value, .. } => {
|
||||
Instruction::Constant { value, .. } => {
|
||||
value.iter().rev().fold(0, |a, &b| (a << 32) | b as u64)
|
||||
}
|
||||
_ => panic!("failed to find array length"),
|
||||
@ -883,23 +890,28 @@ fn descriptor_requirements_of(spirv: &Spirv, variable_id: Id) -> DescriptorVaria
|
||||
Some(element_type)
|
||||
}
|
||||
|
||||
&Instruction::TypeRuntimeArray { element_type, .. } => {
|
||||
Instruction::TypeRuntimeArray { element_type, .. } => {
|
||||
reqs.descriptor_count = None;
|
||||
|
||||
Some(element_type)
|
||||
}
|
||||
|
||||
&Instruction::TypeAccelerationStructureKHR { .. } => None, // FIXME temporary workaround
|
||||
Instruction::TypeAccelerationStructureKHR { .. } => None, // FIXME temporary workaround
|
||||
|
||||
_ => {
|
||||
let name = variable_id_info
|
||||
.iter_name()
|
||||
.find_map(|instruction| match instruction {
|
||||
Instruction::Name { name, .. } => Some(name.as_str()),
|
||||
.find_map(|instruction| match *instruction {
|
||||
Instruction::Name { ref name, .. } => Some(name.as_str()),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or("__unnamed");
|
||||
|
||||
panic!("Couldn't find relevant type for global variable `{}` (id {}, maybe unimplemented)", name, variable_id);
|
||||
panic!(
|
||||
"Couldn't find relevant type for global variable `{}` (id {}, maybe \
|
||||
unimplemented)",
|
||||
name, variable_id,
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -907,21 +919,21 @@ fn descriptor_requirements_of(spirv: &Spirv, variable_id: Id) -> DescriptorVaria
|
||||
DescriptorVariable {
|
||||
set: variable_id_info
|
||||
.iter_decoration()
|
||||
.find_map(|instruction| match instruction {
|
||||
.find_map(|instruction| match *instruction {
|
||||
Instruction::Decorate {
|
||||
decoration: Decoration::DescriptorSet { descriptor_set },
|
||||
..
|
||||
} => Some(*descriptor_set),
|
||||
} => Some(descriptor_set),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap(),
|
||||
binding: variable_id_info
|
||||
.iter_decoration()
|
||||
.find_map(|instruction| match instruction {
|
||||
.find_map(|instruction| match *instruction {
|
||||
Instruction::Decorate {
|
||||
decoration: Decoration::Binding { binding_point },
|
||||
..
|
||||
} => Some(*binding_point),
|
||||
} => Some(binding_point),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap(),
|
||||
@ -933,8 +945,8 @@ fn descriptor_requirements_of(spirv: &Spirv, variable_id: Id) -> DescriptorVaria
|
||||
fn push_constant_requirements(spirv: &Spirv, stage: ShaderStage) -> Option<PushConstantRange> {
|
||||
spirv
|
||||
.iter_global()
|
||||
.find_map(|instruction| match instruction {
|
||||
&Instruction::TypePointer {
|
||||
.find_map(|instruction| match *instruction {
|
||||
Instruction::TypePointer {
|
||||
ty,
|
||||
storage_class: StorageClass::PushConstant,
|
||||
..
|
||||
@ -947,6 +959,7 @@ fn push_constant_requirements(spirv: &Spirv, stage: ShaderStage) -> Option<PushC
|
||||
let start = offset_of_struct(spirv, ty);
|
||||
let end =
|
||||
size_of_type(spirv, ty).expect("Found runtime-sized push constants") as u32;
|
||||
|
||||
Some(PushConstantRange {
|
||||
stages: stage.into(),
|
||||
offset: start,
|
||||
@ -964,39 +977,39 @@ fn specialization_constant_requirements(
|
||||
spirv
|
||||
.iter_global()
|
||||
.filter_map(|instruction| {
|
||||
match instruction {
|
||||
&Instruction::SpecConstantTrue {
|
||||
match *instruction {
|
||||
Instruction::SpecConstantTrue {
|
||||
result_type_id,
|
||||
result_id,
|
||||
}
|
||||
| &Instruction::SpecConstantFalse {
|
||||
| Instruction::SpecConstantFalse {
|
||||
result_type_id,
|
||||
result_id,
|
||||
}
|
||||
| &Instruction::SpecConstant {
|
||||
| Instruction::SpecConstant {
|
||||
result_type_id,
|
||||
result_id,
|
||||
..
|
||||
}
|
||||
| &Instruction::SpecConstantComposite {
|
||||
| Instruction::SpecConstantComposite {
|
||||
result_type_id,
|
||||
result_id,
|
||||
..
|
||||
} => spirv
|
||||
.id(result_id)
|
||||
.iter_decoration()
|
||||
.find_map(|instruction| match instruction {
|
||||
.find_map(|instruction| match *instruction {
|
||||
Instruction::Decorate {
|
||||
decoration:
|
||||
Decoration::SpecId {
|
||||
specialization_constant_id,
|
||||
},
|
||||
..
|
||||
} => Some(*specialization_constant_id),
|
||||
} => Some(specialization_constant_id),
|
||||
_ => None,
|
||||
})
|
||||
.map(|constant_id| {
|
||||
let size = match spirv.id(result_type_id).instruction() {
|
||||
let size = match *spirv.id(result_type_id).instruction() {
|
||||
Instruction::TypeBool { .. } => {
|
||||
// Translate bool to Bool32
|
||||
std::mem::size_of::<ash::vk::Bool32>() as DeviceSize
|
||||
@ -1022,13 +1035,13 @@ fn shader_interface(
|
||||
let elements: Vec<_> = interface
|
||||
.iter()
|
||||
.filter_map(|&id| {
|
||||
let (result_type_id, result_id) = match spirv.id(id).instruction() {
|
||||
&Instruction::Variable {
|
||||
let (result_type_id, result_id) = match *spirv.id(id).instruction() {
|
||||
Instruction::Variable {
|
||||
result_type_id,
|
||||
result_id,
|
||||
ref storage_class,
|
||||
storage_class,
|
||||
..
|
||||
} if storage_class == &filter_storage_class => (result_type_id, result_id),
|
||||
} if storage_class == filter_storage_class => (result_type_id, result_id),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
@ -1040,18 +1053,18 @@ fn shader_interface(
|
||||
|
||||
let name = id_info
|
||||
.iter_name()
|
||||
.find_map(|instruction| match instruction {
|
||||
Instruction::Name { name, .. } => Some(Cow::Owned(name.to_owned())),
|
||||
.find_map(|instruction| match *instruction {
|
||||
Instruction::Name { ref name, .. } => Some(Cow::Owned(name.clone())),
|
||||
_ => None,
|
||||
});
|
||||
|
||||
let location = id_info
|
||||
.iter_decoration()
|
||||
.find_map(|instruction| match instruction {
|
||||
.find_map(|instruction| match *instruction {
|
||||
Instruction::Decorate {
|
||||
decoration: Decoration::Location { location },
|
||||
..
|
||||
} => Some(*location),
|
||||
} => Some(location),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
@ -1062,17 +1075,18 @@ fn shader_interface(
|
||||
});
|
||||
let component = id_info
|
||||
.iter_decoration()
|
||||
.find_map(|instruction| match instruction {
|
||||
.find_map(|instruction| match *instruction {
|
||||
Instruction::Decorate {
|
||||
decoration: Decoration::Component { component },
|
||||
..
|
||||
} => Some(*component),
|
||||
} => Some(component),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or(0);
|
||||
|
||||
let ty = shader_interface_type_of(spirv, result_type_id, ignore_first_array);
|
||||
assert!(ty.num_elements >= 1);
|
||||
|
||||
Some(ShaderInterfaceEntry {
|
||||
location,
|
||||
component,
|
||||
@ -1111,21 +1125,21 @@ fn shader_interface(
|
||||
fn size_of_type(spirv: &Spirv, id: Id) -> Option<DeviceSize> {
|
||||
let id_info = spirv.id(id);
|
||||
|
||||
match id_info.instruction() {
|
||||
match *id_info.instruction() {
|
||||
Instruction::TypeBool { .. } => {
|
||||
panic!("Can't put booleans in structs")
|
||||
}
|
||||
Instruction::TypeInt { width, .. } | Instruction::TypeFloat { width, .. } => {
|
||||
assert!(width % 8 == 0);
|
||||
Some(*width as DeviceSize / 8)
|
||||
Some(width as DeviceSize / 8)
|
||||
}
|
||||
&Instruction::TypeVector {
|
||||
Instruction::TypeVector {
|
||||
component_type,
|
||||
component_count,
|
||||
..
|
||||
} => size_of_type(spirv, component_type)
|
||||
.map(|component_size| component_size * component_count as DeviceSize),
|
||||
&Instruction::TypeMatrix {
|
||||
Instruction::TypeMatrix {
|
||||
column_type,
|
||||
column_count,
|
||||
..
|
||||
@ -1134,19 +1148,19 @@ fn size_of_type(spirv: &Spirv, id: Id) -> Option<DeviceSize> {
|
||||
size_of_type(spirv, column_type)
|
||||
.map(|column_size| column_size * column_count as DeviceSize)
|
||||
}
|
||||
&Instruction::TypeArray { length, .. } => {
|
||||
Instruction::TypeArray { length, .. } => {
|
||||
let stride = id_info
|
||||
.iter_decoration()
|
||||
.find_map(|instruction| match instruction {
|
||||
.find_map(|instruction| match *instruction {
|
||||
Instruction::Decorate {
|
||||
decoration: Decoration::ArrayStride { array_stride },
|
||||
..
|
||||
} => Some(*array_stride),
|
||||
} => Some(array_stride),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap();
|
||||
let length = match spirv.id(length).instruction() {
|
||||
&Instruction::Constant { ref value, .. } => Some(
|
||||
Instruction::Constant { value, .. } => Some(
|
||||
value
|
||||
.iter()
|
||||
.rev()
|
||||
@ -1159,7 +1173,9 @@ fn size_of_type(spirv: &Spirv, id: Id) -> Option<DeviceSize> {
|
||||
Some(stride as DeviceSize * length)
|
||||
}
|
||||
Instruction::TypeRuntimeArray { .. } => None,
|
||||
Instruction::TypeStruct { member_types, .. } => {
|
||||
Instruction::TypeStruct {
|
||||
ref member_types, ..
|
||||
} => {
|
||||
let mut end_of_struct = 0;
|
||||
|
||||
for (&member, member_info) in member_types.iter().zip(id_info.iter_members()) {
|
||||
@ -1181,11 +1197,11 @@ fn size_of_type(spirv: &Spirv, id: Id) -> Option<DeviceSize> {
|
||||
let offset =
|
||||
member_info
|
||||
.iter_decoration()
|
||||
.find_map(|instruction| match instruction {
|
||||
.find_map(|instruction| match *instruction {
|
||||
Instruction::MemberDecorate {
|
||||
decoration: Decoration::Offset { byte_offset },
|
||||
..
|
||||
} => Some(*byte_offset),
|
||||
} => Some(byte_offset),
|
||||
_ => None,
|
||||
})?;
|
||||
let size = size_of_type(spirv, member)?;
|
||||
@ -1206,11 +1222,11 @@ fn offset_of_struct(spirv: &Spirv, id: Id) -> u32 {
|
||||
.filter_map(|member_info| {
|
||||
member_info
|
||||
.iter_decoration()
|
||||
.find_map(|instruction| match instruction {
|
||||
.find_map(|instruction| match *instruction {
|
||||
Instruction::MemberDecorate {
|
||||
decoration: Decoration::Offset { byte_offset },
|
||||
..
|
||||
} => Some(*byte_offset),
|
||||
} => Some(byte_offset),
|
||||
_ => None,
|
||||
})
|
||||
})
|
||||
@ -1293,15 +1309,14 @@ fn shader_interface_type_of(
|
||||
let num_elements = spirv
|
||||
.instructions()
|
||||
.iter()
|
||||
.filter_map(|e| match e {
|
||||
&Instruction::Constant {
|
||||
.find_map(|instruction| match *instruction {
|
||||
Instruction::Constant {
|
||||
result_id,
|
||||
ref value,
|
||||
..
|
||||
} if result_id == length => Some(value.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.next()
|
||||
.expect("failed to find array length")
|
||||
.iter()
|
||||
.rev()
|
||||
@ -1351,25 +1366,19 @@ fn is_builtin(spirv: &Spirv, id: Id) -> bool {
|
||||
}
|
||||
|
||||
match id_info.instruction() {
|
||||
Instruction::Variable { result_type_id, .. } => {
|
||||
return is_builtin(spirv, *result_type_id);
|
||||
Instruction::Variable {
|
||||
result_type_id: ty, ..
|
||||
}
|
||||
Instruction::TypeArray { element_type, .. } => {
|
||||
return is_builtin(spirv, *element_type);
|
||||
| Instruction::TypeArray {
|
||||
element_type: ty, ..
|
||||
}
|
||||
Instruction::TypeRuntimeArray { element_type, .. } => {
|
||||
return is_builtin(spirv, *element_type);
|
||||
| Instruction::TypeRuntimeArray {
|
||||
element_type: ty, ..
|
||||
}
|
||||
| Instruction::TypePointer { ty, .. } => is_builtin(spirv, *ty),
|
||||
Instruction::TypeStruct { member_types, .. } => {
|
||||
if member_types.iter().any(|ty| is_builtin(spirv, *ty)) {
|
||||
return true;
|
||||
}
|
||||
member_types.iter().any(|ty| is_builtin(spirv, *ty))
|
||||
}
|
||||
Instruction::TypePointer { ty, .. } => {
|
||||
return is_builtin(spirv, *ty);
|
||||
}
|
||||
_ => (),
|
||||
_ => false,
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
@ -571,6 +571,7 @@ impl From<Id> for u32 {
|
||||
}
|
||||
|
||||
impl Display for Id {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(f, "%{}", self.0)
|
||||
}
|
||||
@ -588,7 +589,6 @@ impl<'a> InstructionReader<'a> {
|
||||
/// Constructs a new reader from a slice of words for a single instruction, including the opcode
|
||||
/// word. `instruction` is the number of the instruction currently being read, and is used for
|
||||
/// error reporting.
|
||||
#[inline]
|
||||
fn new(words: &'a [u32], instruction: usize) -> Self {
|
||||
debug_assert!(!words.is_empty());
|
||||
Self {
|
||||
@ -599,13 +599,11 @@ impl<'a> InstructionReader<'a> {
|
||||
}
|
||||
|
||||
/// Returns whether the reader has reached the end of the current instruction.
|
||||
#[inline]
|
||||
fn is_empty(&self) -> bool {
|
||||
self.next_word >= self.words.len()
|
||||
}
|
||||
|
||||
/// Converts the `ParseErrors` enum to the `ParseError` struct, adding contextual information.
|
||||
#[inline]
|
||||
fn map_err(&self, error: ParseErrors) -> ParseError {
|
||||
ParseError {
|
||||
instruction: self.instruction,
|
||||
@ -616,7 +614,6 @@ impl<'a> InstructionReader<'a> {
|
||||
}
|
||||
|
||||
/// Returns the next word in the sequence.
|
||||
#[inline]
|
||||
fn next_u32(&mut self) -> Result<u32, ParseError> {
|
||||
let word = *self.words.get(self.next_word).ok_or(ParseError {
|
||||
instruction: self.instruction,
|
||||
@ -625,6 +622,7 @@ impl<'a> InstructionReader<'a> {
|
||||
words: self.words.to_owned(),
|
||||
})?;
|
||||
self.next_word += 1;
|
||||
|
||||
Ok(word)
|
||||
}
|
||||
|
||||
@ -653,7 +651,6 @@ impl<'a> InstructionReader<'a> {
|
||||
}
|
||||
|
||||
/// Reads all remaining words.
|
||||
#[inline]
|
||||
fn remainder(&mut self) -> Vec<u32> {
|
||||
let vec = self.words[self.next_word..].to_owned();
|
||||
self.next_word = self.words.len();
|
||||
@ -686,13 +683,12 @@ pub enum SpirvError {
|
||||
}
|
||||
|
||||
impl Display for SpirvError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::BadLayout { index } => write!(
|
||||
f,
|
||||
"the instruction at index {} does not follow the logical layout of a module",
|
||||
index
|
||||
index,
|
||||
),
|
||||
Self::DuplicateId {
|
||||
id,
|
||||
@ -701,10 +697,19 @@ impl Display for SpirvError {
|
||||
} => write!(
|
||||
f,
|
||||
"id {} is assigned more than once, by instructions {} and {}",
|
||||
id, first_index, second_index
|
||||
id, first_index, second_index,
|
||||
),
|
||||
Self::GroupDecorateNotGroup { index } => write!(
|
||||
f,
|
||||
"a GroupDecorate or GroupMemberDecorate instruction at index {} referred to an Id \
|
||||
that was not a DecorationGroup",
|
||||
index,
|
||||
),
|
||||
Self::IdOutOfBounds { id, bound, index } => write!(
|
||||
f,
|
||||
"id {}, assigned at instruction {}, is not below the maximum bound {}",
|
||||
id, index, bound,
|
||||
),
|
||||
Self::GroupDecorateNotGroup { index } => write!(f, "a GroupDecorate or GroupMemberDecorate instruction at index {} referred to an Id that was not a DecorationGroup", index),
|
||||
Self::IdOutOfBounds { id, bound, index, } => write!(f, "id {}, assigned at instruction {}, is not below the maximum bound {}", id, index, bound),
|
||||
Self::InvalidHeader => write!(f, "the SPIR-V module header is invalid"),
|
||||
Self::MemoryModelInvalid => {
|
||||
write!(f, "the MemoryModel instruction is not present exactly once")
|
||||
@ -715,7 +720,6 @@ impl Display for SpirvError {
|
||||
}
|
||||
|
||||
impl Error for SpirvError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::ParseError(err) => Some(err),
|
||||
@ -725,7 +729,6 @@ impl Error for SpirvError {
|
||||
}
|
||||
|
||||
impl From<ParseError> for SpirvError {
|
||||
#[inline]
|
||||
fn from(err: ParseError) -> Self {
|
||||
Self::ParseError(err)
|
||||
}
|
||||
@ -745,12 +748,11 @@ pub struct ParseError {
|
||||
}
|
||||
|
||||
impl Display for ParseError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"at instruction {}, word {}: {}",
|
||||
self.instruction, self.word, self.error
|
||||
self.instruction, self.word, self.error,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -770,16 +772,23 @@ pub enum ParseErrors {
|
||||
}
|
||||
|
||||
impl Display for ParseErrors {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::FromUtf8Error(_) => write!(f, "invalid UTF-8 in string literal"),
|
||||
Self::LeftoverOperands => write!(f, "unparsed operands remaining"),
|
||||
Self::MissingOperands => write!(f, "the instruction and its operands require more words than are present in the instruction"),
|
||||
Self::MissingOperands => write!(
|
||||
f,
|
||||
"the instruction and its operands require more words than are present in the \
|
||||
instruction",
|
||||
),
|
||||
Self::UnexpectedEOF => write!(f, "encountered unexpected end of file"),
|
||||
Self::UnknownEnumerant(ty, enumerant) => write!(f, "invalid enumerant {} for enum {}", enumerant, ty),
|
||||
Self::UnknownEnumerant(ty, enumerant) => {
|
||||
write!(f, "invalid enumerant {} for enum {}", enumerant, ty)
|
||||
}
|
||||
Self::UnknownOpcode(opcode) => write!(f, "invalid instruction opcode {}", opcode),
|
||||
Self::UnknownSpecConstantOpcode(opcode) => write!(f, "invalid spec constant instruction opcode {}", opcode),
|
||||
Self::UnknownSpecConstantOpcode(opcode) => {
|
||||
write!(f, "invalid spec constant instruction opcode {}", opcode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,10 +142,9 @@ impl DisplayPlane {
|
||||
|
||||
/// Enumerates all the display planes that are available on a given physical device.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the device or host ran out of memory.
|
||||
///
|
||||
// TODO: move iterator creation here from raw constructor?
|
||||
#[inline]
|
||||
pub fn enumerate(physical_device: Arc<PhysicalDevice>) -> IntoIter<DisplayPlane> {
|
||||
@ -235,10 +234,9 @@ impl Display {
|
||||
|
||||
/// Enumerates all the displays that are available on a given physical device.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the device or host ran out of memory.
|
||||
///
|
||||
// TODO: move iterator creation here from raw constructor?
|
||||
#[inline]
|
||||
pub fn enumerate(physical_device: Arc<PhysicalDevice>) -> IntoIter<Display> {
|
||||
@ -344,10 +342,9 @@ impl Display {
|
||||
|
||||
/// Returns a list of all modes available on this display.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the device or host ran out of memory.
|
||||
///
|
||||
// TODO: move iterator creation here from display_modes_raw?
|
||||
#[inline]
|
||||
pub fn display_modes(&self) -> IntoIter<DisplayMode> {
|
||||
|
@ -51,7 +51,7 @@
|
||||
//! may be able to do this for you, if you pass it ownership of your Window (or a
|
||||
//! reference-counting container for it).
|
||||
//!
|
||||
//! ### Example
|
||||
//! ### Examples
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::ptr;
|
||||
@ -88,9 +88,9 @@
|
||||
//! # }
|
||||
//! #
|
||||
//! # fn build_window() -> Arc<Window> { Arc::new(Window(ptr::null())) }
|
||||
//! let window = build_window(); // Third-party function, not provided by vulkano
|
||||
//! let window = build_window(); // Third-party function, not provided by vulkano
|
||||
//! let _surface = unsafe {
|
||||
//! let hinstance: *const () = ptr::null(); // Windows-specific object
|
||||
//! let hinstance: *const () = ptr::null(); // Windows-specific object
|
||||
//! Surface::from_win32(instance.clone(), hinstance, window.hwnd(), Arc::clone(&window)).unwrap()
|
||||
//! };
|
||||
//! ```
|
||||
@ -194,31 +194,31 @@
|
||||
//!
|
||||
//! // Create the swapchain and its images.
|
||||
//! let (swapchain, images) = Swapchain::new(
|
||||
//! // Create the swapchain in this `device`'s memory.
|
||||
//! device,
|
||||
//! // The surface where the images will be presented.
|
||||
//! surface,
|
||||
//! // The creation parameters.
|
||||
//! SwapchainCreateInfo {
|
||||
//! // How many images to use in the swapchain.
|
||||
//! min_image_count,
|
||||
//! // The format of the images.
|
||||
//! image_format: Some(image_format),
|
||||
//! // The size of each image.
|
||||
//! image_extent,
|
||||
//! // What the images are going to be used for.
|
||||
//! image_usage,
|
||||
//! // What transformation to use with the surface.
|
||||
//! pre_transform,
|
||||
//! // How to handle the alpha channel.
|
||||
//! composite_alpha,
|
||||
//! // How to present images.
|
||||
//! present_mode,
|
||||
//! // How to handle full-screen exclusivity
|
||||
//! full_screen_exclusive,
|
||||
//! ..Default::default()
|
||||
//! }
|
||||
//! )?;
|
||||
//! // Create the swapchain in this `device`'s memory.
|
||||
//! device,
|
||||
//! // The surface where the images will be presented.
|
||||
//! surface,
|
||||
//! // The creation parameters.
|
||||
//! SwapchainCreateInfo {
|
||||
//! // How many images to use in the swapchain.
|
||||
//! min_image_count,
|
||||
//! // The format of the images.
|
||||
//! image_format: Some(image_format),
|
||||
//! // The size of each image.
|
||||
//! image_extent,
|
||||
//! // What the images are going to be used for.
|
||||
//! image_usage,
|
||||
//! // What transformation to use with the surface.
|
||||
//! pre_transform,
|
||||
//! // How to handle the alpha channel.
|
||||
//! composite_alpha,
|
||||
//! // How to present images.
|
||||
//! present_mode,
|
||||
//! // How to handle full-screen exclusivity
|
||||
//! full_screen_exclusive,
|
||||
//! ..Default::default()
|
||||
//! }
|
||||
//! )?;
|
||||
//!
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
@ -256,12 +256,14 @@
|
||||
//! // The command_buffer contains the draw commands that modify the framebuffer
|
||||
//! // constructed from images[image_index]
|
||||
//! acquire_future
|
||||
//! .then_execute(queue.clone(), command_buffer).unwrap()
|
||||
//! .then_execute(queue.clone(), command_buffer)
|
||||
//! .unwrap()
|
||||
//! .then_swapchain_present(
|
||||
//! queue.clone(),
|
||||
//! SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
|
||||
//! )
|
||||
//! .then_signal_fence_and_flush().unwrap();
|
||||
//! .then_signal_fence_and_flush()
|
||||
//! .unwrap();
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
@ -276,7 +278,6 @@
|
||||
//! rendering, you will need to *recreate* the swapchain by creating a new swapchain and passing
|
||||
//! as last parameter the old swapchain.
|
||||
//!
|
||||
//!
|
||||
//! ```
|
||||
//! use vulkano::swapchain;
|
||||
//! use vulkano::swapchain::{AcquireError, SwapchainCreateInfo, SwapchainPresentInfo};
|
||||
@ -303,7 +304,7 @@
|
||||
//! let (image_index, suboptimal, acq_future) = match swapchain::acquire_next_image(swapchain.clone(), None) {
|
||||
//! Ok(r) => r,
|
||||
//! Err(AcquireError::OutOfDate) => { recreate_swapchain = true; continue; },
|
||||
//! Err(err) => panic!("{:?}", err)
|
||||
//! Err(err) => panic!("{:?}", err),
|
||||
//! };
|
||||
//!
|
||||
//! // ...
|
||||
@ -314,14 +315,14 @@
|
||||
//! queue.clone(),
|
||||
//! SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
|
||||
//! )
|
||||
//! .then_signal_fence_and_flush().unwrap(); // TODO: PresentError?
|
||||
//! .then_signal_fence_and_flush()
|
||||
//! .unwrap(); // TODO: PresentError?
|
||||
//!
|
||||
//! if suboptimal {
|
||||
//! recreate_swapchain = true;
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
|
||||
pub use self::{
|
||||
surface::{
|
||||
@ -448,10 +449,12 @@ pub struct RectangleLayer {
|
||||
|
||||
impl RectangleLayer {
|
||||
/// Returns true if this rectangle layer is compatible with swapchain.
|
||||
#[inline]
|
||||
pub fn is_compatible_with(&self, swapchain: &dyn SwapchainAbstract) -> bool {
|
||||
// FIXME negative offset is not disallowed by spec, but semantically should not be possible
|
||||
debug_assert!(self.offset[0] >= 0);
|
||||
debug_assert!(self.offset[1] >= 0);
|
||||
|
||||
self.offset[0] as u32 + self.extent[0] <= swapchain.image_extent()[0]
|
||||
&& self.offset[1] as u32 + self.extent[1] <= swapchain.image_extent()[1]
|
||||
&& self.layer < swapchain.image_array_layers()
|
||||
|
@ -67,7 +67,6 @@ impl<W> Surface<W> {
|
||||
/// - `handle` must have been created from `api`.
|
||||
/// - The window object that `handle` was created from must outlive the created `Surface`.
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
instance: Arc<Instance>,
|
||||
handle: ash::vk::SurfaceKHR,
|
||||
@ -95,7 +94,6 @@ impl<W> Surface<W> {
|
||||
///
|
||||
/// Presenting to a headless surface does nothing, so this is mostly useless in itself. However,
|
||||
/// it may be useful for testing, and it is available for future extensions to layer on top of.
|
||||
#[inline]
|
||||
pub fn headless(instance: Arc<Instance>, win: W) -> Result<Arc<Self>, SurfaceCreationError> {
|
||||
Self::validate_headless(&instance)?;
|
||||
|
||||
@ -159,11 +157,10 @@ impl<W> Surface<W> {
|
||||
|
||||
/// Creates a `Surface` from a `DisplayPlane`.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `display_mode` and `plane` don't belong to the same physical device.
|
||||
/// - Panics if `plane` doesn't support the display of `display_mode`.
|
||||
#[inline]
|
||||
pub fn from_display_plane(
|
||||
display_mode: &DisplayMode,
|
||||
plane: &DisplayPlane,
|
||||
@ -263,7 +260,6 @@ impl<W> Surface<W> {
|
||||
/// - `window` must be a valid Android `ANativeWindow` handle.
|
||||
/// - The object referred to by `window` must outlive the created `Surface`.
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
#[inline]
|
||||
pub unsafe fn from_android<T>(
|
||||
instance: Arc<Instance>,
|
||||
window: *const T,
|
||||
@ -345,7 +341,6 @@ impl<W> Surface<W> {
|
||||
/// - `surface` must be a valid DirectFB `IDirectFBSurface` handle.
|
||||
/// - The object referred to by `dfb` and `surface` must outlive the created `Surface`.
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
#[inline]
|
||||
pub unsafe fn from_directfb<D, S>(
|
||||
instance: Arc<Instance>,
|
||||
dfb: *const D,
|
||||
@ -433,7 +428,6 @@ impl<W> Surface<W> {
|
||||
/// - `image_pipe_handle` must be a valid Fuchsia `zx_handle_t` handle.
|
||||
/// - The object referred to by `image_pipe_handle` must outlive the created `Surface`.
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
#[inline]
|
||||
pub unsafe fn from_fuchsia_image_pipe(
|
||||
instance: Arc<Instance>,
|
||||
image_pipe_handle: ash::vk::zx_handle_t,
|
||||
@ -519,7 +513,6 @@ impl<W> Surface<W> {
|
||||
/// - `stream_descriptor` must be a valid Google Games Platform `GgpStreamDescriptor` handle.
|
||||
/// - The object referred to by `stream_descriptor` must outlive the created `Surface`.
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
#[inline]
|
||||
pub unsafe fn from_ggp_stream_descriptor(
|
||||
instance: Arc<Instance>,
|
||||
stream_descriptor: ash::vk::GgpStreamDescriptor,
|
||||
@ -607,7 +600,6 @@ impl<W> Surface<W> {
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
/// - The `UIView` must be backed by a `CALayer` instance of type `CAMetalLayer`.
|
||||
#[cfg(target_os = "ios")]
|
||||
#[inline]
|
||||
pub unsafe fn from_ios(
|
||||
instance: Arc<Instance>,
|
||||
metal_layer: IOSMetalLayer,
|
||||
@ -694,7 +686,6 @@ impl<W> Surface<W> {
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
/// - The `NSView` must be backed by a `CALayer` instance of type `CAMetalLayer`.
|
||||
#[cfg(target_os = "macos")]
|
||||
#[inline]
|
||||
pub unsafe fn from_mac_os<T>(
|
||||
instance: Arc<Instance>,
|
||||
view: *const T,
|
||||
@ -780,7 +771,6 @@ impl<W> Surface<W> {
|
||||
/// - `layer` must be a valid Metal `CAMetalLayer` handle.
|
||||
/// - The object referred to by `layer` must outlive the created `Surface`.
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
#[inline]
|
||||
pub unsafe fn from_metal<T>(
|
||||
instance: Arc<Instance>,
|
||||
layer: *const T,
|
||||
@ -859,7 +849,6 @@ impl<W> Surface<W> {
|
||||
/// - `window` must be a valid QNX Screen `_screen_window` handle.
|
||||
/// - The object referred to by `window` must outlive the created `Surface`.
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
#[inline]
|
||||
pub unsafe fn from_qnx_screen<T, U>(
|
||||
instance: Arc<Instance>,
|
||||
context: *const T,
|
||||
@ -949,7 +938,6 @@ impl<W> Surface<W> {
|
||||
/// - `window` must be a valid `nn::vi::NativeWindowHandle` handle.
|
||||
/// - The object referred to by `window` must outlive the created `Surface`.
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
#[inline]
|
||||
pub unsafe fn from_vi<T>(
|
||||
instance: Arc<Instance>,
|
||||
window: *const T,
|
||||
@ -1033,7 +1021,6 @@ impl<W> Surface<W> {
|
||||
/// - `surface` must be a valid Wayland `wl_surface` handle.
|
||||
/// - The objects referred to by `display` and `surface` must outlive the created `Surface`.
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
#[inline]
|
||||
pub unsafe fn from_wayland<D, S>(
|
||||
instance: Arc<Instance>,
|
||||
display: *const D,
|
||||
@ -1126,7 +1113,6 @@ impl<W> Surface<W> {
|
||||
/// - `hwnd` must be a valid Win32 `HWND` handle.
|
||||
/// - The objects referred to by `hwnd` and `hinstance` must outlive the created `Surface`.
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
#[inline]
|
||||
pub unsafe fn from_win32<T, U>(
|
||||
instance: Arc<Instance>,
|
||||
hinstance: *const T,
|
||||
@ -1217,7 +1203,6 @@ impl<W> Surface<W> {
|
||||
/// - `window` must be a valid X11 `xcb_window_t` handle.
|
||||
/// - The objects referred to by `connection` and `window` must outlive the created `Surface`.
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
#[inline]
|
||||
pub unsafe fn from_xcb<C>(
|
||||
instance: Arc<Instance>,
|
||||
connection: *const C,
|
||||
@ -1308,7 +1293,6 @@ impl<W> Surface<W> {
|
||||
/// - `window` must be a valid Xlib `Window` handle.
|
||||
/// - The objects referred to by `display` and `window` must outlive the created `Surface`.
|
||||
/// The `win` parameter can be used to ensure this.
|
||||
#[inline]
|
||||
pub unsafe fn from_xlib<D>(
|
||||
instance: Arc<Instance>,
|
||||
display: *const D,
|
||||
@ -1390,19 +1374,16 @@ impl<W> Surface<W> {
|
||||
}
|
||||
|
||||
/// Returns the instance this surface was created with.
|
||||
#[inline]
|
||||
pub fn instance(&self) -> &Arc<Instance> {
|
||||
&self.instance
|
||||
}
|
||||
|
||||
/// Returns the windowing API that was used to construct the surface.
|
||||
#[inline]
|
||||
pub fn api(&self) -> SurfaceApi {
|
||||
self.api
|
||||
}
|
||||
|
||||
/// Returns a reference to the `W` type parameter that was passed when creating the surface.
|
||||
#[inline]
|
||||
pub fn window(&self) -> &W {
|
||||
&self.window
|
||||
}
|
||||
@ -1415,7 +1396,6 @@ impl<W> Surface<W> {
|
||||
/// its sublayers are not automatically resized, and we must resize
|
||||
/// it here.
|
||||
#[cfg(target_os = "ios")]
|
||||
#[inline]
|
||||
pub unsafe fn update_ios_sublayer_on_resize(&self) {
|
||||
use core_graphics_types::geometry::CGRect;
|
||||
let class = class!(CAMetalLayer);
|
||||
@ -1427,7 +1407,6 @@ impl<W> Surface<W> {
|
||||
}
|
||||
|
||||
impl<W> Drop for Surface<W> {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let fns = self.instance.fns();
|
||||
@ -1443,14 +1422,12 @@ impl<W> Drop for Surface<W> {
|
||||
unsafe impl<W> VulkanObject for Surface<W> {
|
||||
type Object = ash::vk::SurfaceKHR;
|
||||
|
||||
#[inline]
|
||||
fn internal_object(&self) -> ash::vk::SurfaceKHR {
|
||||
self.handle
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> Debug for Surface<W> {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
let Self {
|
||||
handle,
|
||||
@ -1472,7 +1449,6 @@ impl<W> Debug for Surface<W> {
|
||||
}
|
||||
|
||||
impl<W> PartialEq for Surface<W> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.handle == other.handle && self.instance() == other.instance()
|
||||
}
|
||||
@ -1481,7 +1457,6 @@ impl<W> PartialEq for Surface<W> {
|
||||
impl<W> Eq for Surface<W> {}
|
||||
|
||||
impl<W> Hash for Surface<W> {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.instance().hash(state);
|
||||
@ -1489,7 +1464,6 @@ impl<W> Hash for Surface<W> {
|
||||
}
|
||||
|
||||
unsafe impl<W> SurfaceSwapchainLock for Surface<W> {
|
||||
#[inline]
|
||||
fn flag(&self) -> &AtomicBool {
|
||||
&self.has_swapchain
|
||||
}
|
||||
@ -1508,7 +1482,6 @@ pub enum SurfaceCreationError {
|
||||
}
|
||||
|
||||
impl Error for SurfaceCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
SurfaceCreationError::OomError(err) => Some(err),
|
||||
@ -1518,11 +1491,9 @@ impl Error for SurfaceCreationError {
|
||||
}
|
||||
|
||||
impl Display for SurfaceCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
SurfaceCreationError::OomError(_) => write!(f, "not enough memory available"),
|
||||
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -1536,14 +1507,12 @@ impl Display for SurfaceCreationError {
|
||||
}
|
||||
|
||||
impl From<OomError> for SurfaceCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> SurfaceCreationError {
|
||||
SurfaceCreationError::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for SurfaceCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> SurfaceCreationError {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => {
|
||||
@ -1805,83 +1774,87 @@ vulkan_enum! {
|
||||
///
|
||||
/// ## What is a color space?
|
||||
///
|
||||
/// Each pixel of a monitor is made of three components: one red, one green, and one blue. In the
|
||||
/// past, computers would simply send to the monitor the intensity of each of the three components.
|
||||
/// Each pixel of a monitor is made of three components: one red, one green, and one blue. In
|
||||
/// the past, computers would simply send to the monitor the intensity of each of the three
|
||||
/// components.
|
||||
///
|
||||
/// This proved to be problematic, because depending on the brand of the monitor the colors would
|
||||
/// not exactly be the same. For example on some monitors, a value of `[1.0, 0.0, 0.0]` would be a
|
||||
/// This proved to be problematic, because depending on the brand of the monitor the colors
|
||||
/// would not exactly be the same. For example on some monitors, a value of `[1.0, 0.0, 0.0]`
|
||||
/// would be a
|
||||
/// bit more orange than on others.
|
||||
///
|
||||
/// In order to standardize this, there exist what are called *color spaces*: sRGB, AdobeRGB,
|
||||
/// DCI-P3, scRGB, etc. When you manipulate RGB values in a specific color space, these values have
|
||||
/// a precise absolute meaning in terms of color, that is the same across all systems and monitors.
|
||||
/// DCI-P3, scRGB, etc. When you manipulate RGB values in a specific color space, these values
|
||||
/// have a precise absolute meaning in terms of color, that is the same across all systems and
|
||||
/// monitors.
|
||||
///
|
||||
/// > **Note**: Color spaces are orthogonal to concept of RGB. *RGB* only indicates what is the
|
||||
/// > representation of the data, but not how it is interpreted. You can think of this a bit like
|
||||
/// > text encoding. An *RGB* value is a like a byte, in other words it is the medium by which
|
||||
/// > values are communicated, and a *color space* is like a text encoding (eg. UTF-8), in other
|
||||
/// > words it is the way the value should be interpreted.
|
||||
/// > representation of the data, but not how it is interpreted. You can think of this a bit
|
||||
/// > like text encoding. An *RGB* value is a like a byte, in other words it is the medium by
|
||||
/// > which values are communicated, and a *color space* is like a text encoding (eg. UTF-8),
|
||||
/// > in other words it is the way the value should be interpreted.
|
||||
///
|
||||
/// The most commonly used color space today is sRGB. Most monitors today use this color space,
|
||||
/// and most images files are encoded in this color space.
|
||||
///
|
||||
/// ## Pixel formats and linear vs non-linear
|
||||
///
|
||||
/// In Vulkan all images have a specific format in which the data is stored. The data of an image
|
||||
/// consists of pixels in RGB but contains no information about the color space (or lack thereof)
|
||||
/// of these pixels. You are free to store them in whatever color space you want.
|
||||
/// In Vulkan all images have a specific format in which the data is stored. The data of an
|
||||
/// image consists of pixels in RGB but contains no information about the color space (or lack
|
||||
/// thereof) of these pixels. You are free to store them in whatever color space you want.
|
||||
///
|
||||
/// But one big practical problem with color spaces is that they are sometimes not linear, and in
|
||||
/// particular the popular sRGB color space is not linear. In a non-linear color space, a value of
|
||||
/// `[0.6, 0.6, 0.6]` for example is **not** twice as bright as a value of `[0.3, 0.3, 0.3]`. This
|
||||
/// is problematic, because operations such as taking the average of two colors or calculating the
|
||||
/// lighting of a texture with a dot product are mathematically incorrect and will produce
|
||||
/// incorrect colors.
|
||||
/// But one big practical problem with color spaces is that they are sometimes not linear, and
|
||||
/// in particular the popular sRGB color space is not linear. In a non-linear color space, a
|
||||
/// value of `[0.6, 0.6, 0.6]` for example is **not** twice as bright as a value of `[0.3, 0.3,
|
||||
/// 0.3]`. This is problematic, because operations such as taking the average of two colors or
|
||||
/// calculating the lighting of a texture with a dot product are mathematically incorrect and
|
||||
/// will produce incorrect colors.
|
||||
///
|
||||
/// > **Note**: If the texture format has an alpha component, it is not affected by the color space
|
||||
/// > and always behaves linearly.
|
||||
/// > **Note**: If the texture format has an alpha component, it is not affected by the color
|
||||
/// > space and always behaves linearly.
|
||||
///
|
||||
/// In order to solve this Vulkan also provides image formats with the `Srgb` suffix, which are
|
||||
/// expected to contain RGB data in the sRGB color space. When you sample an image with such a
|
||||
/// format from a shader, the implementation will automatically turn the pixel values into a linear
|
||||
/// color space that is suitable for linear operations (such as additions or multiplications).
|
||||
/// When you write to a framebuffer attachment with such a format, the implementation will
|
||||
/// automatically perform the opposite conversion. These conversions are most of the time performed
|
||||
/// by the hardware and incur no additional cost.
|
||||
/// format from a shader, the implementation will automatically turn the pixel values into a
|
||||
/// linear color space that is suitable for linear operations (such as additions or
|
||||
/// multiplications). When you write to a framebuffer attachment with such a format, the
|
||||
/// implementation will automatically perform the opposite conversion. These conversions are
|
||||
/// most of the time performed by the hardware and incur no additional cost.
|
||||
///
|
||||
/// ## Color space of the swapchain
|
||||
///
|
||||
/// The color space that you specify when you create a swapchain is how the implementation will
|
||||
/// interpret the raw data inside of the image.
|
||||
///
|
||||
/// > **Note**: The implementation can choose to send the data in the swapchain image directly to
|
||||
/// > the monitor, but it can also choose to write it in an intermediary buffer that is then read
|
||||
/// > by the operating system or windowing system. Therefore the color space that the
|
||||
/// > **Note**: The implementation can choose to send the data in the swapchain image directly
|
||||
/// > to the monitor, but it can also choose to write it in an intermediary buffer that is then
|
||||
/// > read by the operating system or windowing system. Therefore the color space that the
|
||||
/// > implementation supports is not necessarily the same as the one supported by the monitor.
|
||||
///
|
||||
/// It is *your* job to ensure that the data in the swapchain image is in the color space
|
||||
/// that is specified here, otherwise colors will be incorrect.
|
||||
/// The implementation will never perform any additional automatic conversion after the colors have
|
||||
/// been written to the swapchain image.
|
||||
/// that is specified here, otherwise colors will be incorrect. The implementation will never
|
||||
/// perform any additional automatic conversion after the colors have been written to the
|
||||
/// swapchain image.
|
||||
///
|
||||
/// # How do I handle this correctly?
|
||||
///
|
||||
/// The easiest way to handle color spaces in a cross-platform program is:
|
||||
///
|
||||
/// - Always request the `SrgbNonLinear` color space when creating the swapchain.
|
||||
/// - Make sure that all your image files use the sRGB color space, and load them in images whose
|
||||
/// format has the `Srgb` suffix. Only use non-sRGB image formats for intermediary computations
|
||||
/// or to store non-color data.
|
||||
/// - Make sure that all your image files use the sRGB color space, and load them in images
|
||||
/// whose format has the `Srgb` suffix. Only use non-sRGB image formats for intermediary
|
||||
/// computations or to store non-color data.
|
||||
/// - Swapchain images should have a format with the `Srgb` suffix.
|
||||
///
|
||||
/// > **Note**: Lots of developers are confused by color spaces. You can sometimes find articles
|
||||
/// > talking about gamma correction and suggestion to put your colors to the power 2.2 for
|
||||
/// > example. These are all hacks and you should use the sRGB pixel formats instead.
|
||||
///
|
||||
/// If you follow these three rules, then everything should render the same way on all platforms.
|
||||
/// If you follow these three rules, then everything should render the same way on all
|
||||
/// platforms.
|
||||
///
|
||||
/// Additionally you can try detect whether the implementation supports any additional color space
|
||||
/// and perform a manual conversion to that color space from inside your shader.
|
||||
/// Additionally you can try detect whether the implementation supports any additional color
|
||||
/// space and perform a manual conversion to that color space from inside your shader.
|
||||
#[non_exhaustive]
|
||||
ColorSpace = ColorSpaceKHR(i32);
|
||||
|
||||
@ -1964,10 +1937,10 @@ vulkan_enum! {
|
||||
},
|
||||
}
|
||||
|
||||
/// Parameters for
|
||||
/// [`PhysicalDevice::surface_capabilities`](crate::device::physical::PhysicalDevice::surface_capabilities)
|
||||
/// and
|
||||
/// [`PhysicalDevice::surface_formats`](crate::device::physical::PhysicalDevice::surface_formats).
|
||||
/// Parameters for [`PhysicalDevice::surface_capabilities`] and [`PhysicalDevice::surface_formats`].
|
||||
///
|
||||
/// [`PhysicalDevice::surface_capabilities`]: crate::device::physical::PhysicalDevice::surface_capabilities
|
||||
/// [`PhysicalDevice::surface_formats`]: crate::device::physical::PhysicalDevice::surface_formats
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct SurfaceInfo {
|
||||
pub full_screen_exclusive: FullScreenExclusive,
|
||||
@ -2004,6 +1977,7 @@ pub struct IOSMetalLayer {
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
impl IOSMetalLayer {
|
||||
#[inline]
|
||||
pub fn new(main_layer: *mut Object, render_layer: *mut Object) -> Self {
|
||||
Self {
|
||||
main_layer: LayerHandle(main_layer),
|
||||
|
@ -71,8 +71,9 @@ pub struct Swapchain<W> {
|
||||
// The images of this swapchain.
|
||||
images: Vec<ImageEntry>,
|
||||
|
||||
// If true, that means we have tried to use this swapchain to recreate a new swapchain. The current
|
||||
// swapchain can no longer be used for anything except presenting already-acquired images.
|
||||
// If true, that means we have tried to use this swapchain to recreate a new swapchain. The
|
||||
// current swapchain can no longer be used for anything except presenting already-acquired
|
||||
// images.
|
||||
//
|
||||
// We use a `Mutex` instead of an `AtomicBool` because we want to keep that locked while
|
||||
// we acquire the image.
|
||||
@ -177,7 +178,6 @@ where
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `create_info.usage` is empty.
|
||||
#[inline]
|
||||
pub fn recreate(
|
||||
self: &Arc<Self>,
|
||||
mut create_info: SwapchainCreateInfo,
|
||||
@ -726,7 +726,6 @@ where
|
||||
}
|
||||
|
||||
/// Returns the creation parameters of the swapchain.
|
||||
#[inline]
|
||||
pub fn create_info(&self) -> SwapchainCreateInfo {
|
||||
SwapchainCreateInfo {
|
||||
min_image_count: self.min_image_count,
|
||||
@ -747,37 +746,31 @@ where
|
||||
}
|
||||
|
||||
/// Returns the saved Surface, from the Swapchain creation.
|
||||
#[inline]
|
||||
pub fn surface(&self) -> &Arc<Surface<W>> {
|
||||
&self.surface
|
||||
}
|
||||
|
||||
/// Returns the pre-transform that was passed when creating the swapchain.
|
||||
#[inline]
|
||||
pub fn pre_transform(&self) -> SurfaceTransform {
|
||||
self.pre_transform
|
||||
}
|
||||
|
||||
/// Returns the alpha mode that was passed when creating the swapchain.
|
||||
#[inline]
|
||||
pub fn composite_alpha(&self) -> CompositeAlpha {
|
||||
self.composite_alpha
|
||||
}
|
||||
|
||||
/// Returns the present mode that was passed when creating the swapchain.
|
||||
#[inline]
|
||||
pub fn present_mode(&self) -> PresentMode {
|
||||
self.present_mode
|
||||
}
|
||||
|
||||
/// Returns the value of `clipped` that was passed when creating the swapchain.
|
||||
#[inline]
|
||||
pub fn clipped(&self) -> bool {
|
||||
self.clipped
|
||||
}
|
||||
|
||||
/// Returns the value of 'full_screen_exclusive` that was passed when creating the swapchain.
|
||||
#[inline]
|
||||
pub fn full_screen_exclusive(&self) -> FullScreenExclusive {
|
||||
self.full_screen_exclusive
|
||||
}
|
||||
@ -875,7 +868,6 @@ where
|
||||
}
|
||||
|
||||
impl<W> Drop for Swapchain<W> {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let fns = self.device.fns();
|
||||
@ -892,7 +884,6 @@ impl<W> Drop for Swapchain<W> {
|
||||
unsafe impl<W> VulkanObject for Swapchain<W> {
|
||||
type Object = ash::vk::SwapchainKHR;
|
||||
|
||||
#[inline]
|
||||
fn internal_object(&self) -> ash::vk::SwapchainKHR {
|
||||
self.handle
|
||||
}
|
||||
@ -905,7 +896,6 @@ unsafe impl<W> DeviceOwned for Swapchain<W> {
|
||||
}
|
||||
|
||||
impl<W> PartialEq for Swapchain<W> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.handle == other.handle && self.device() == other.device()
|
||||
}
|
||||
@ -914,7 +904,6 @@ impl<W> PartialEq for Swapchain<W> {
|
||||
impl<W> Eq for Swapchain<W> {}
|
||||
|
||||
impl<W> Hash for Swapchain<W> {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -922,7 +911,6 @@ impl<W> Hash for Swapchain<W> {
|
||||
}
|
||||
|
||||
impl<W> Debug for Swapchain<W> {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
let Self {
|
||||
handle,
|
||||
@ -1005,7 +993,6 @@ unsafe impl<W> SwapchainAbstract for Swapchain<W>
|
||||
where
|
||||
W: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn raw_image(&self, image_index: u32) -> Option<ImageInner<'_>> {
|
||||
self.images.get(image_index as usize).map(|i| ImageInner {
|
||||
image: &i.image,
|
||||
@ -1016,37 +1003,30 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn image_count(&self) -> u32 {
|
||||
self.images.len() as u32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn image_format(&self) -> Format {
|
||||
self.image_format
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn image_color_space(&self) -> ColorSpace {
|
||||
self.image_color_space
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn image_extent(&self) -> [u32; 2] {
|
||||
self.image_extent
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn image_array_layers(&self) -> u32 {
|
||||
self.image_array_layers
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn full_screen_exclusive_held(&self) -> &AtomicBool {
|
||||
&self.full_screen_exclusive_held
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn try_claim_present_id(&self, present_id: NonZeroU64) -> bool {
|
||||
let present_id = u64::from(present_id);
|
||||
self.prev_present_id.fetch_max(present_id, Ordering::SeqCst) < present_id
|
||||
@ -1063,7 +1043,6 @@ impl PartialEq for dyn SwapchainAbstract {
|
||||
impl Eq for dyn SwapchainAbstract {}
|
||||
|
||||
impl Hash for dyn SwapchainAbstract {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.internal_object().hash(state);
|
||||
self.device().hash(state);
|
||||
@ -1221,10 +1200,7 @@ pub enum SwapchainCreationError {
|
||||
|
||||
/// The provided `image_array_layers` is greater than what is supported by the surface for this
|
||||
/// device.
|
||||
ImageArrayLayersNotSupported {
|
||||
provided: u32,
|
||||
max_supported: u32,
|
||||
},
|
||||
ImageArrayLayersNotSupported { provided: u32, max_supported: u32 },
|
||||
|
||||
/// The provided `image_extent` is not within the range supported by the surface for this
|
||||
/// device.
|
||||
@ -1276,7 +1252,7 @@ pub enum SwapchainCreationError {
|
||||
supported: SupportedSurfaceTransforms,
|
||||
},
|
||||
|
||||
// The provided `surface` is not supported by any of the device's queue families.
|
||||
/// The provided `surface` is not supported by any of the device's queue families.
|
||||
SurfaceNotSupported,
|
||||
|
||||
/// The swapchain has already been used to create a new one.
|
||||
@ -1287,29 +1263,26 @@ pub enum SwapchainCreationError {
|
||||
}
|
||||
|
||||
impl Error for SwapchainCreationError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SwapchainCreationError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available",),
|
||||
Self::DeviceLost => write!(f, "the device was lost",),
|
||||
Self::SurfaceLost => write!(f, "the surface was lost",),
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
Self::DeviceLost => write!(f, "the device was lost"),
|
||||
Self::SurfaceLost => write!(f, "the surface was lost"),
|
||||
Self::SurfaceInUse => {
|
||||
write!(f, "the surface is already used by another swapchain",)
|
||||
write!(f, "the surface is already used by another swapchain")
|
||||
}
|
||||
Self::NativeWindowInUse => {
|
||||
write!(f, "the window is already in use by another API")
|
||||
}
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -1318,23 +1291,32 @@ impl Display for SwapchainCreationError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::CompositeAlphaNotSupported { .. } => write!(
|
||||
f,
|
||||
"the provided `composite_alpha` is not supported by the surface for this device",
|
||||
),
|
||||
Self::FormatColorSpaceNotSupported => write!(
|
||||
f,
|
||||
"the provided `format` and `color_space` are not supported by the surface for this device",
|
||||
"the provided `format` and `color_space` are not supported by the surface for this \
|
||||
device",
|
||||
),
|
||||
Self::ImageArrayLayersNotSupported { provided, max_supported } => write!(
|
||||
Self::ImageArrayLayersNotSupported {
|
||||
provided,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the provided `image_array_layers` ({}) is greater than what is supported ({}) by the surface for this device",
|
||||
"the provided `image_array_layers` ({}) is greater than what is supported ({}) by \
|
||||
the surface for this device",
|
||||
provided, max_supported,
|
||||
),
|
||||
Self::ImageExtentNotSupported { provided, min_supported, max_supported } => write!(
|
||||
Self::ImageExtentNotSupported {
|
||||
provided,
|
||||
min_supported,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the provided `image_extent` ({:?}) is not within the range (min: {:?}, max: {:?}) supported by the surface for this device",
|
||||
"the provided `image_extent` ({:?}) is not within the range (min: {:?}, max: {:?}) \
|
||||
supported by the surface for this device",
|
||||
provided, min_supported, max_supported,
|
||||
),
|
||||
Self::ImageExtentZeroLengthDimensions => write!(
|
||||
@ -1343,20 +1325,31 @@ impl Display for SwapchainCreationError {
|
||||
),
|
||||
Self::ImageFormatPropertiesNotSupported => write!(
|
||||
f,
|
||||
"the provided image parameters are not supported as queried from `image_format_properties`",
|
||||
"the provided image parameters are not supported as queried from \
|
||||
`image_format_properties`",
|
||||
),
|
||||
Self::ImageSharingQueueFamilyIndexOutOfRange { queue_family_index, queue_family_count: _ } => write!(
|
||||
Self::ImageSharingQueueFamilyIndexOutOfRange {
|
||||
queue_family_index,
|
||||
queue_family_count: _,
|
||||
} => write!(
|
||||
f,
|
||||
"the provided `image_sharing` was set to `Concurrent`, but one of the specified queue family indices ({}) was out of range",
|
||||
"the provided `image_sharing` was set to `Concurrent`, but one of the specified \
|
||||
queue family indices ({}) was out of range",
|
||||
queue_family_index,
|
||||
),
|
||||
Self::ImageUsageNotSupported { .. } => write!(
|
||||
f,
|
||||
"the provided `image_usage` has fields set that are not supported by the surface for this device",
|
||||
"the provided `image_usage` has fields set that are not supported by the surface \
|
||||
for this device",
|
||||
),
|
||||
Self::MinImageCountNotSupported { provided, min_supported, max_supported } => write!(
|
||||
Self::MinImageCountNotSupported {
|
||||
provided,
|
||||
min_supported,
|
||||
max_supported,
|
||||
} => write!(
|
||||
f,
|
||||
"the provided `min_image_count` ({}) is not within the range (min: {}, max: {:?}) supported by the surface for this device",
|
||||
"the provided `min_image_count` ({}) is not within the range (min: {}, max: {:?}) \
|
||||
supported by the surface for this device",
|
||||
provided, min_supported, max_supported,
|
||||
),
|
||||
Self::PresentModeNotSupported => write!(
|
||||
@ -1371,10 +1364,9 @@ impl Display for SwapchainCreationError {
|
||||
f,
|
||||
"the provided `surface` is not supported by any of the device's queue families",
|
||||
),
|
||||
Self::SwapchainAlreadyRetired => write!(
|
||||
f,
|
||||
"the swapchain has already been used to create a new one",
|
||||
),
|
||||
Self::SwapchainAlreadyRetired => {
|
||||
write!(f, "the swapchain has already been used to create a new one")
|
||||
}
|
||||
Self::Win32MonitorInvalid => write!(
|
||||
f,
|
||||
"the `win32_monitor` value was `Some` when it must be `None` or vice-versa",
|
||||
@ -1384,7 +1376,6 @@ impl Display for SwapchainCreationError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for SwapchainCreationError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> SwapchainCreationError {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)),
|
||||
@ -1398,14 +1389,12 @@ impl From<VulkanError> for SwapchainCreationError {
|
||||
}
|
||||
|
||||
impl From<OomError> for SwapchainCreationError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> SwapchainCreationError {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for SwapchainCreationError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
@ -1449,7 +1438,6 @@ impl Win32Monitor {
|
||||
/// # Safety
|
||||
///
|
||||
/// - `hmonitor` must be a valid handle as returned by the Win32 API.
|
||||
#[inline]
|
||||
pub unsafe fn new<T>(hmonitor: *const T) -> Self {
|
||||
Self(hmonitor as _)
|
||||
}
|
||||
@ -1483,22 +1471,20 @@ pub enum FullScreenExclusiveError {
|
||||
}
|
||||
|
||||
impl Error for FullScreenExclusiveError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
FullScreenExclusiveError::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
FullScreenExclusiveError::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FullScreenExclusiveError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
match self {
|
||||
FullScreenExclusiveError::OomError(_) => "not enough memory",
|
||||
FullScreenExclusiveError::SurfaceLost => {
|
||||
"the surface of this swapchain is no longer valid"
|
||||
@ -1519,7 +1505,6 @@ impl Display for FullScreenExclusiveError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for FullScreenExclusiveError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> FullScreenExclusiveError {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => {
|
||||
@ -1536,7 +1521,6 @@ impl From<VulkanError> for FullScreenExclusiveError {
|
||||
}
|
||||
|
||||
impl From<OomError> for FullScreenExclusiveError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> FullScreenExclusiveError {
|
||||
FullScreenExclusiveError::OomError(err)
|
||||
}
|
||||
@ -1600,8 +1584,7 @@ pub fn acquire_next_image<W>(
|
||||
|
||||
/// Presents an image on the screen.
|
||||
///
|
||||
/// The actual behavior depends on the present mode that you passed when creating the
|
||||
/// swapchain.
|
||||
/// The actual behavior depends on the present mode that you passed when creating the swapchain.
|
||||
pub fn present<F>(
|
||||
before: F,
|
||||
queue: Arc<Queue>,
|
||||
@ -1628,10 +1611,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait for an image to be presented to the user. Must be used with a `present_id` given to `present_with_id`.
|
||||
/// Wait for an image to be presented to the user. Must be used with a `present_id` given to
|
||||
/// `present_with_id`.
|
||||
///
|
||||
/// Returns a bool to represent if the presentation was suboptimal. In this case the swapchain is still
|
||||
/// usable, but the swapchain should be recreated as the Surface's properties no longer match the swapchain.
|
||||
/// Returns a bool to represent if the presentation was suboptimal. In this case the swapchain is
|
||||
/// still usable, but the swapchain should be recreated as the Surface's properties no longer match
|
||||
/// the swapchain.
|
||||
pub fn wait_for_present<W>(
|
||||
swapchain: Arc<Swapchain<W>>,
|
||||
present_id: u64,
|
||||
@ -1704,13 +1689,11 @@ pub struct SwapchainAcquireFuture<W> {
|
||||
|
||||
impl<W> SwapchainAcquireFuture<W> {
|
||||
/// Returns the index of the image in the list of images returned when creating the swapchain.
|
||||
#[inline]
|
||||
pub fn image_index(&self) -> u32 {
|
||||
self.image_index
|
||||
}
|
||||
|
||||
/// Returns the corresponding swapchain.
|
||||
#[inline]
|
||||
pub fn swapchain(&self) -> &Arc<Swapchain<W>> {
|
||||
&self.swapchain
|
||||
}
|
||||
@ -1720,10 +1703,8 @@ unsafe impl<W> GpuFuture for SwapchainAcquireFuture<W>
|
||||
where
|
||||
W: Send + Sync,
|
||||
{
|
||||
#[inline]
|
||||
fn cleanup_finished(&mut self) {}
|
||||
|
||||
#[inline]
|
||||
unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
|
||||
if let Some(ref semaphore) = self.semaphore {
|
||||
let sem = smallvec![semaphore.clone()];
|
||||
@ -1733,27 +1714,22 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&self) -> Result<(), FlushError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn signal_finished(&self) {
|
||||
self.finished.store(true, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue_change_allowed(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue(&self) -> Option<Arc<Queue>> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_buffer_access(
|
||||
&self,
|
||||
_buffer: &UnsafeBuffer,
|
||||
@ -1764,7 +1740,6 @@ where
|
||||
Err(AccessCheckError::Unknown)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_image_access(
|
||||
&self,
|
||||
image: &UnsafeImage,
|
||||
@ -1833,7 +1808,6 @@ impl<W> Drop for SwapchainAcquireFuture<W> {
|
||||
}
|
||||
|
||||
unsafe impl<W> DeviceOwned for SwapchainAcquireFuture<W> {
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
&self.swapchain.device
|
||||
}
|
||||
@ -1871,22 +1845,20 @@ pub enum AcquireError {
|
||||
}
|
||||
|
||||
impl Error for AcquireError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
AcquireError::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
AcquireError::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AcquireError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
match self {
|
||||
AcquireError::OomError(_) => "not enough memory",
|
||||
AcquireError::DeviceLost => "the connection to the device has been lost",
|
||||
AcquireError::Timeout => "no image is available for acquiring yet",
|
||||
@ -1915,14 +1887,12 @@ impl From<SemaphoreError> for AcquireError {
|
||||
}
|
||||
|
||||
impl From<OomError> for AcquireError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> AcquireError {
|
||||
AcquireError::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for AcquireError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> AcquireError {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => AcquireError::OomError(OomError::from(err)),
|
||||
@ -1970,19 +1940,17 @@ pub enum PresentWaitError {
|
||||
}
|
||||
|
||||
impl Error for PresentWaitError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PresentWaitError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match *self {
|
||||
match self {
|
||||
Self::OomError(e) => write!(f, "{}", e),
|
||||
Self::DeviceLost => write!(f, "the connection to the device has been lost"),
|
||||
Self::Timeout => write!(f, "no image is available for acquiring yet"),
|
||||
@ -2005,14 +1973,12 @@ impl Display for PresentWaitError {
|
||||
}
|
||||
|
||||
impl From<OomError> for PresentWaitError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> PresentWaitError {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for PresentWaitError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
@ -2022,7 +1988,6 @@ impl From<RequirementNotMet> for PresentWaitError {
|
||||
}
|
||||
|
||||
impl From<VulkanError> for PresentWaitError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> PresentWaitError {
|
||||
match err {
|
||||
err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)),
|
||||
@ -2058,13 +2023,11 @@ where
|
||||
P: GpuFuture,
|
||||
{
|
||||
/// Returns the index of the image in the list of images returned when creating the swapchain.
|
||||
#[inline]
|
||||
pub fn image_id(&self) -> u32 {
|
||||
self.swapchain_info.image_index
|
||||
}
|
||||
|
||||
/// Returns the corresponding swapchain.
|
||||
#[inline]
|
||||
pub fn swapchain(&self) -> &Arc<dyn SwapchainAbstract> {
|
||||
&self.swapchain_info.swapchain
|
||||
}
|
||||
@ -2074,12 +2037,10 @@ unsafe impl<P> GpuFuture for PresentFuture<P>
|
||||
where
|
||||
P: GpuFuture,
|
||||
{
|
||||
#[inline]
|
||||
fn cleanup_finished(&mut self) {
|
||||
self.previous.cleanup_finished();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
|
||||
if self.flushed.load(Ordering::SeqCst) {
|
||||
return Ok(SubmitAnyBuilder::Empty);
|
||||
@ -2148,7 +2109,6 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&self) -> Result<(), FlushError> {
|
||||
unsafe {
|
||||
// If `flushed` already contains `true`, then `build_submission` will return `Empty`.
|
||||
@ -2194,19 +2154,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn signal_finished(&self) {
|
||||
self.flushed.store(true, Ordering::SeqCst);
|
||||
self.finished.store(true, Ordering::SeqCst);
|
||||
self.previous.signal_finished();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue_change_allowed(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue(&self) -> Option<Arc<Queue>> {
|
||||
debug_assert!(match self.previous.queue() {
|
||||
None => true,
|
||||
@ -2216,7 +2173,6 @@ where
|
||||
Some(self.queue.clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_buffer_access(
|
||||
&self,
|
||||
buffer: &UnsafeBuffer,
|
||||
@ -2228,7 +2184,6 @@ where
|
||||
.check_buffer_access(buffer, range, exclusive, queue)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_image_access(
|
||||
&self,
|
||||
image: &UnsafeImage,
|
||||
@ -2281,7 +2236,6 @@ unsafe impl<P> DeviceOwned for PresentFuture<P>
|
||||
where
|
||||
P: GpuFuture,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.queue.device()
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ pub struct Event {
|
||||
|
||||
impl Event {
|
||||
/// Creates a new `Event`.
|
||||
#[inline]
|
||||
pub fn new(device: Arc<Device>, _create_info: EventCreateInfo) -> Result<Event, OomError> {
|
||||
let create_info = ash::vk::EventCreateInfo {
|
||||
flags: ash::vk::EventCreateFlags::empty(),
|
||||
@ -66,6 +67,7 @@ impl Event {
|
||||
///
|
||||
/// For most applications, using the event pool should be preferred,
|
||||
/// in order to avoid creating new events every frame.
|
||||
#[inline]
|
||||
pub fn from_pool(device: Arc<Device>) -> Result<Event, OomError> {
|
||||
let handle = device.event_pool().lock().pop();
|
||||
let event = match handle {
|
||||
@ -100,6 +102,7 @@ impl Event {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
handle: ash::vk::Event,
|
||||
@ -142,10 +145,9 @@ impl Event {
|
||||
///
|
||||
/// If a command buffer is waiting on this event, it is then unblocked.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the device or host ran out of memory.
|
||||
///
|
||||
#[inline]
|
||||
pub fn set(&mut self) {
|
||||
self.set_raw().unwrap();
|
||||
@ -165,10 +167,9 @@ impl Event {
|
||||
|
||||
/// Changes the `Event` to the unsignaled state.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the device or host ran out of memory.
|
||||
///
|
||||
#[inline]
|
||||
pub fn reset(&mut self) {
|
||||
self.reset_raw().unwrap();
|
||||
@ -216,7 +217,6 @@ impl PartialEq for Event {
|
||||
impl Eq for Event {}
|
||||
|
||||
impl Hash for Event {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -230,6 +230,7 @@ pub struct EventCreateInfo {
|
||||
}
|
||||
|
||||
impl Default for EventCreateInfo {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
_ne: crate::NonExhaustive(()),
|
||||
|
@ -103,6 +103,7 @@ impl Fence {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn new_unchecked(
|
||||
device: Arc<Device>,
|
||||
create_info: FenceCreateInfo,
|
||||
@ -148,6 +149,7 @@ impl Fence {
|
||||
)
|
||||
.result()
|
||||
.map_err(VulkanError::from)?;
|
||||
|
||||
output.assume_init()
|
||||
};
|
||||
|
||||
@ -171,6 +173,7 @@ impl Fence {
|
||||
///
|
||||
/// For most applications, using the fence pool should be preferred,
|
||||
/// in order to avoid creating new fences every frame.
|
||||
#[inline]
|
||||
pub fn from_pool(device: Arc<Device>) -> Result<Fence, FenceError> {
|
||||
let handle = device.fence_pool().lock().pop();
|
||||
let fence = match handle {
|
||||
@ -210,6 +213,7 @@ impl Fence {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
handle: ash::vk::Fence,
|
||||
@ -236,6 +240,7 @@ impl Fence {
|
||||
}
|
||||
|
||||
/// Returns true if the fence is signaled.
|
||||
#[inline]
|
||||
pub fn is_signaled(&self) -> Result<bool, OomError> {
|
||||
let queue_to_signal = {
|
||||
let mut state = self.lock();
|
||||
@ -322,10 +327,9 @@ impl Fence {
|
||||
|
||||
/// Waits for multiple fences at once.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if not all fences belong to the same device.
|
||||
#[inline]
|
||||
/// - Panics if not all fences belong to the same device.
|
||||
pub fn multi_wait<'a>(
|
||||
fences: impl IntoIterator<Item = &'a Fence>,
|
||||
timeout: Option<Duration>,
|
||||
@ -442,8 +446,10 @@ impl Fence {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn reset_unchecked(&self) -> Result<(), VulkanError> {
|
||||
let mut state = self.state.lock();
|
||||
|
||||
self.reset_unchecked_locked(&mut state)
|
||||
}
|
||||
|
||||
@ -462,10 +468,9 @@ impl Fence {
|
||||
///
|
||||
/// The fences must not be in use by a queue operation.
|
||||
///
|
||||
/// # Panic
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if not all fences belong to the same device.
|
||||
#[inline]
|
||||
pub fn multi_reset<'a>(fences: impl IntoIterator<Item = &'a Fence>) -> Result<(), FenceError> {
|
||||
let (fences, mut states): (SmallVec<[_; 8]>, SmallVec<[_; 8]>) = fences
|
||||
.into_iter()
|
||||
@ -503,7 +508,6 @@ impl Fence {
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
#[inline]
|
||||
pub unsafe fn multi_reset_unchecked<'a>(
|
||||
fences: impl IntoIterator<Item = &'a Fence>,
|
||||
) -> Result<(), VulkanError> {
|
||||
@ -514,6 +518,7 @@ impl Fence {
|
||||
(fence, state)
|
||||
})
|
||||
.unzip();
|
||||
|
||||
Self::multi_reset_unchecked_locked(&fences, &mut states)
|
||||
}
|
||||
|
||||
@ -544,7 +549,6 @@ impl Fence {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn lock(&self) -> MutexGuard<'_, FenceState> {
|
||||
self.state.lock()
|
||||
}
|
||||
@ -591,7 +595,6 @@ impl PartialEq for Fence {
|
||||
impl Eq for Fence {}
|
||||
|
||||
impl Hash for Fence {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.handle.hash(state);
|
||||
self.device().hash(state);
|
||||
@ -607,17 +610,14 @@ pub struct FenceState {
|
||||
impl FenceState {
|
||||
/// If the fence is already signaled, or it's unsignaled but there's no queue that
|
||||
/// could signal it, returns the currently known value.
|
||||
#[inline]
|
||||
pub(crate) fn status(&self) -> Option<bool> {
|
||||
(self.is_signaled || self.in_use_by.is_none()).then_some(self.is_signaled)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn is_in_use(&self) -> bool {
|
||||
self.in_use_by.is_some()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn add_to_queue(&mut self, queue: &Arc<Queue>) {
|
||||
self.is_signaled = false;
|
||||
self.in_use_by = Some(Arc::downgrade(queue));
|
||||
@ -625,20 +625,17 @@ impl FenceState {
|
||||
|
||||
/// Called when a fence first discovers that it is signaled.
|
||||
/// Returns the queue that should be informed about it.
|
||||
#[inline]
|
||||
pub(crate) unsafe fn set_signaled(&mut self) -> Option<Arc<Queue>> {
|
||||
self.is_signaled = true;
|
||||
self.in_use_by.take().and_then(|queue| queue.upgrade())
|
||||
}
|
||||
|
||||
/// Called when a queue is unlocking resources.
|
||||
#[inline]
|
||||
pub(crate) unsafe fn set_finished(&mut self) {
|
||||
self.is_signaled = true;
|
||||
self.in_use_by = None;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn reset(&mut self) {
|
||||
debug_assert!(self.in_use_by.is_none());
|
||||
self.is_signaled = false;
|
||||
@ -795,10 +792,9 @@ pub enum FenceError {
|
||||
}
|
||||
|
||||
impl Error for FenceError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
Self::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
Self::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -810,7 +806,6 @@ impl Display for FenceError {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
Self::DeviceLost => write!(f, "the device was lost"),
|
||||
Self::Timeout => write!(f, "the timeout has been reached"),
|
||||
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
@ -819,14 +814,12 @@ impl Display for FenceError {
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
|
||||
Self::InUse => write!(f, "the fence is currently in use by a queue"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for FenceError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
e @ VulkanError::OutOfHostMemory | e @ VulkanError::OutOfDeviceMemory => {
|
||||
@ -839,14 +832,12 @@ impl From<VulkanError> for FenceError {
|
||||
}
|
||||
|
||||
impl From<OomError> for FenceError {
|
||||
#[inline]
|
||||
fn from(err: OomError) -> Self {
|
||||
Self::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for FenceError {
|
||||
#[inline]
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
|
@ -20,7 +20,6 @@ use parking_lot::{Mutex, MutexGuard};
|
||||
use std::{mem::replace, ops::Range, sync::Arc, time::Duration};
|
||||
|
||||
/// Builds a new fence signal future.
|
||||
#[inline]
|
||||
pub fn then_signal_fence<F>(future: F, behavior: FenceSignalFutureBehavior) -> FenceSignalFuture<F>
|
||||
where
|
||||
F: GpuFuture,
|
||||
@ -167,7 +166,6 @@ where
|
||||
{
|
||||
// Implementation of `cleanup_finished`, but takes a `&self` instead of a `&mut self`.
|
||||
// This is an external function so that we can also call it from an `Arc<FenceSignalFuture>`.
|
||||
#[inline]
|
||||
fn cleanup_finished_impl(&self) {
|
||||
let mut state = self.state.lock();
|
||||
|
||||
@ -353,12 +351,11 @@ where
|
||||
}
|
||||
|
||||
impl<F> FenceSignalFutureState<F> {
|
||||
#[inline]
|
||||
fn get_prev(&self) -> Option<&F> {
|
||||
match *self {
|
||||
FenceSignalFutureState::Pending(ref prev, _) => Some(prev),
|
||||
FenceSignalFutureState::PartiallyFlushed(ref prev, _) => Some(prev),
|
||||
FenceSignalFutureState::Flushed(ref prev, _) => Some(prev),
|
||||
match self {
|
||||
FenceSignalFutureState::Pending(prev, _) => Some(prev),
|
||||
FenceSignalFutureState::PartiallyFlushed(prev, _) => Some(prev),
|
||||
FenceSignalFutureState::Flushed(prev, _) => Some(prev),
|
||||
FenceSignalFutureState::Cleaned => None,
|
||||
FenceSignalFutureState::Poisoned => None,
|
||||
}
|
||||
@ -369,18 +366,16 @@ unsafe impl<F> GpuFuture for FenceSignalFuture<F>
|
||||
where
|
||||
F: GpuFuture,
|
||||
{
|
||||
#[inline]
|
||||
fn cleanup_finished(&mut self) {
|
||||
self.cleanup_finished_impl()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
|
||||
let mut state = self.state.lock();
|
||||
self.flush_impl(&mut state)?;
|
||||
|
||||
match *state {
|
||||
FenceSignalFutureState::Flushed(_, ref fence) => match self.behavior {
|
||||
match &*state {
|
||||
FenceSignalFutureState::Flushed(_, fence) => match self.behavior {
|
||||
FenceSignalFutureBehavior::Block { timeout } => {
|
||||
fence.wait(timeout)?;
|
||||
}
|
||||
@ -394,13 +389,11 @@ where
|
||||
Ok(SubmitAnyBuilder::Empty)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&self) -> Result<(), FlushError> {
|
||||
let mut state = self.state.lock();
|
||||
self.flush_impl(&mut state)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn signal_finished(&self) {
|
||||
let state = self.state.lock();
|
||||
match *state {
|
||||
@ -412,7 +405,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue_change_allowed(&self) -> bool {
|
||||
match self.behavior {
|
||||
FenceSignalFutureBehavior::Continue => {
|
||||
@ -423,7 +415,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue(&self) -> Option<Arc<Queue>> {
|
||||
let state = self.state.lock();
|
||||
if let Some(prev) = state.get_prev() {
|
||||
@ -433,7 +424,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_buffer_access(
|
||||
&self,
|
||||
buffer: &UnsafeBuffer,
|
||||
@ -449,7 +439,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_image_access(
|
||||
&self,
|
||||
image: &UnsafeImage,
|
||||
@ -484,7 +473,6 @@ unsafe impl<F> DeviceOwned for FenceSignalFuture<F>
|
||||
where
|
||||
F: GpuFuture,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
&self.device
|
||||
}
|
||||
@ -528,39 +516,32 @@ unsafe impl<F> GpuFuture for Arc<FenceSignalFuture<F>>
|
||||
where
|
||||
F: GpuFuture,
|
||||
{
|
||||
#[inline]
|
||||
fn cleanup_finished(&mut self) {
|
||||
self.cleanup_finished_impl()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
|
||||
// Note that this is sound because we always return `SubmitAnyBuilder::Empty`. See the
|
||||
// documentation of `build_submission`.
|
||||
(**self).build_submission()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&self) -> Result<(), FlushError> {
|
||||
(**self).flush()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn signal_finished(&self) {
|
||||
(**self).signal_finished()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue_change_allowed(&self) -> bool {
|
||||
(**self).queue_change_allowed()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue(&self) -> Option<Arc<Queue>> {
|
||||
(**self).queue()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_buffer_access(
|
||||
&self,
|
||||
buffer: &UnsafeBuffer,
|
||||
@ -571,7 +552,6 @@ where
|
||||
(**self).check_buffer_access(buffer, range, exclusive, queue)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_image_access(
|
||||
&self,
|
||||
image: &UnsafeImage,
|
||||
|
@ -19,7 +19,6 @@ use std::{ops::Range, sync::Arc};
|
||||
|
||||
/// Joins two futures together.
|
||||
// TODO: handle errors
|
||||
#[inline]
|
||||
pub fn join<F, S>(first: F, second: S) -> JoinFuture<F, S>
|
||||
where
|
||||
F: GpuFuture,
|
||||
@ -49,7 +48,6 @@ where
|
||||
A: DeviceOwned,
|
||||
B: DeviceOwned,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
let device = self.first.device();
|
||||
debug_assert_eq!(
|
||||
@ -65,22 +63,20 @@ where
|
||||
A: GpuFuture,
|
||||
B: GpuFuture,
|
||||
{
|
||||
#[inline]
|
||||
fn cleanup_finished(&mut self) {
|
||||
self.first.cleanup_finished();
|
||||
self.second.cleanup_finished();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&self) -> Result<(), FlushError> {
|
||||
// Since each future remembers whether it has been flushed, there's no safety issue here
|
||||
// if we call this function multiple times.
|
||||
self.first.flush()?;
|
||||
self.second.flush()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
|
||||
// TODO: review this function
|
||||
let first = self.first.build_submission()?;
|
||||
@ -179,18 +175,15 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn signal_finished(&self) {
|
||||
self.first.signal_finished();
|
||||
self.second.signal_finished();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue_change_allowed(&self) -> bool {
|
||||
self.first.queue_change_allowed() && self.second.queue_change_allowed()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue(&self) -> Option<Arc<Queue>> {
|
||||
match (self.first.queue(), self.second.queue()) {
|
||||
(Some(q1), Some(q2)) => {
|
||||
@ -210,7 +203,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_buffer_access(
|
||||
&self,
|
||||
buffer: &UnsafeBuffer,
|
||||
@ -245,7 +237,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_image_access(
|
||||
&self,
|
||||
image: &UnsafeImage,
|
||||
|
@ -145,7 +145,7 @@ pub unsafe trait GpuFuture: DeviceOwned {
|
||||
/// Checks whether accessing a swapchain image is permitted.
|
||||
///
|
||||
/// > **Note**: Setting `before` to `true` should skip checking the current future and always
|
||||
/// > forward the call to the future before.
|
||||
/// > forward the call to the future before.
|
||||
fn check_swapchain_image_acquired(
|
||||
&self,
|
||||
image: &UnsafeImage,
|
||||
@ -166,7 +166,6 @@ pub unsafe trait GpuFuture: DeviceOwned {
|
||||
///
|
||||
/// > **Note**: This is just a shortcut function. The actual implementation is in the
|
||||
/// > `CommandBuffer` trait.
|
||||
#[inline]
|
||||
fn then_execute<Cb>(
|
||||
self,
|
||||
queue: Arc<Queue>,
|
||||
@ -183,7 +182,6 @@ pub unsafe trait GpuFuture: DeviceOwned {
|
||||
///
|
||||
/// > **Note**: This is just a shortcut function. The actual implementation is in the
|
||||
/// > `CommandBuffer` trait.
|
||||
#[inline]
|
||||
fn then_execute_same_queue<Cb>(
|
||||
self,
|
||||
command_buffer: Cb,
|
||||
@ -228,6 +226,7 @@ pub unsafe trait GpuFuture: DeviceOwned {
|
||||
{
|
||||
let f = self.then_signal_semaphore();
|
||||
f.flush()?;
|
||||
|
||||
Ok(f)
|
||||
}
|
||||
|
||||
@ -253,6 +252,7 @@ pub unsafe trait GpuFuture: DeviceOwned {
|
||||
{
|
||||
let f = self.then_signal_fence();
|
||||
f.flush()?;
|
||||
|
||||
Ok(f)
|
||||
}
|
||||
|
||||
@ -277,6 +277,7 @@ pub unsafe trait GpuFuture: DeviceOwned {
|
||||
/// Turn the current future into a `Box<dyn GpuFuture>`.
|
||||
///
|
||||
/// This is a helper function that calls `Box::new(yourFuture) as Box<dyn GpuFuture>`.
|
||||
#[inline]
|
||||
fn boxed(self) -> Box<dyn GpuFuture>
|
||||
where
|
||||
Self: Sized + 'static,
|
||||
@ -287,6 +288,7 @@ pub unsafe trait GpuFuture: DeviceOwned {
|
||||
/// Turn the current future into a `Box<dyn GpuFuture + Send>`.
|
||||
///
|
||||
/// This is a helper function that calls `Box::new(yourFuture) as Box<dyn GpuFuture + Send>`.
|
||||
#[inline]
|
||||
fn boxed_send(self) -> Box<dyn GpuFuture + Send>
|
||||
where
|
||||
Self: Sized + Send + 'static,
|
||||
@ -297,6 +299,7 @@ pub unsafe trait GpuFuture: DeviceOwned {
|
||||
/// Turn the current future into a `Box<dyn GpuFuture + Sync>`.
|
||||
///
|
||||
/// This is a helper function that calls `Box::new(yourFuture) as Box<dyn GpuFuture + Sync>`.
|
||||
#[inline]
|
||||
fn boxed_sync(self) -> Box<dyn GpuFuture + Sync>
|
||||
where
|
||||
Self: Sized + Sync + 'static,
|
||||
@ -306,7 +309,9 @@ pub unsafe trait GpuFuture: DeviceOwned {
|
||||
|
||||
/// Turn the current future into a `Box<dyn GpuFuture + Send + Sync>`.
|
||||
///
|
||||
/// This is a helper function that calls `Box::new(yourFuture) as Box<dyn GpuFuture + Send + Sync>`.
|
||||
/// This is a helper function that calls `Box::new(yourFuture) as Box<dyn GpuFuture + Send +
|
||||
/// Sync>`.
|
||||
#[inline]
|
||||
fn boxed_send_sync(self) -> Box<dyn GpuFuture + Send + Sync>
|
||||
where
|
||||
Self: Sized + Send + Sync + 'static,
|
||||
@ -319,37 +324,30 @@ unsafe impl<F: ?Sized> GpuFuture for Box<F>
|
||||
where
|
||||
F: GpuFuture,
|
||||
{
|
||||
#[inline]
|
||||
fn cleanup_finished(&mut self) {
|
||||
(**self).cleanup_finished()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
|
||||
(**self).build_submission()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&self) -> Result<(), FlushError> {
|
||||
(**self).flush()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn signal_finished(&self) {
|
||||
(**self).signal_finished()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue_change_allowed(&self) -> bool {
|
||||
(**self).queue_change_allowed()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue(&self) -> Option<Arc<Queue>> {
|
||||
(**self).queue()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_buffer_access(
|
||||
&self,
|
||||
buffer: &UnsafeBuffer,
|
||||
@ -360,7 +358,6 @@ where
|
||||
(**self).check_buffer_access(buffer, range, exclusive, queue)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_image_access(
|
||||
&self,
|
||||
image: &UnsafeImage,
|
||||
@ -431,12 +428,11 @@ pub enum AccessError {
|
||||
impl Error for AccessError {}
|
||||
|
||||
impl Display for AccessError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
match self {
|
||||
AccessError::ExclusiveDenied => "only shared access is allowed for this resource",
|
||||
AccessError::AlreadyInUse => {
|
||||
"the resource is already in use, and there is no tracking of concurrent usages"
|
||||
@ -446,14 +442,14 @@ impl Display for AccessError {
|
||||
}
|
||||
AccessError::ImageNotInitialized { .. } => {
|
||||
"trying to use an image without transitioning it from the undefined or \
|
||||
preinitialized layouts first"
|
||||
preinitialized layouts first"
|
||||
}
|
||||
AccessError::BufferNotInitialized => {
|
||||
"trying to use a buffer that still contains garbage data"
|
||||
}
|
||||
AccessError::SwapchainImageNotAcquired => {
|
||||
"trying to use a swapchain image without depending on a corresponding acquire \
|
||||
image future"
|
||||
image future"
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -472,12 +468,11 @@ pub enum AccessCheckError {
|
||||
impl Error for AccessCheckError {}
|
||||
|
||||
impl Display for AccessCheckError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
match self {
|
||||
AccessCheckError::Denied(_) => "access to the resource has been denied",
|
||||
AccessCheckError::Unknown => "the resource is unknown",
|
||||
}
|
||||
@ -486,7 +481,6 @@ impl Display for AccessCheckError {
|
||||
}
|
||||
|
||||
impl From<AccessError> for AccessCheckError {
|
||||
#[inline]
|
||||
fn from(err: AccessError) -> AccessCheckError {
|
||||
AccessCheckError::Denied(err)
|
||||
}
|
||||
@ -524,23 +518,21 @@ pub enum FlushError {
|
||||
}
|
||||
|
||||
impl Error for FlushError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
FlushError::AccessError(ref err) => Some(err),
|
||||
FlushError::OomError(ref err) => Some(err),
|
||||
match self {
|
||||
FlushError::AccessError(err) => Some(err),
|
||||
FlushError::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FlushError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
match self {
|
||||
FlushError::AccessError(_) => "access to a resource has been denied",
|
||||
FlushError::OomError(_) => "not enough memory",
|
||||
FlushError::DeviceLost => "the connection to the device has been lost",
|
||||
@ -550,8 +542,7 @@ impl Display for FlushError {
|
||||
"the swapchain no longer has full screen exclusivity"
|
||||
}
|
||||
FlushError::Timeout => {
|
||||
"the flush operation needed to block, but the timeout has \
|
||||
elapsed"
|
||||
"the flush operation needed to block, but the timeout has elapsed"
|
||||
}
|
||||
FlushError::PresentIdLessThanOrEqual => {
|
||||
"present id is less than or equal to previous"
|
||||
@ -562,14 +553,12 @@ impl Display for FlushError {
|
||||
}
|
||||
|
||||
impl From<AccessError> for FlushError {
|
||||
#[inline]
|
||||
fn from(err: AccessError) -> FlushError {
|
||||
FlushError::AccessError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VulkanError> for FlushError {
|
||||
#[inline]
|
||||
fn from(err: VulkanError) -> Self {
|
||||
match err {
|
||||
VulkanError::OutOfHostMemory | VulkanError::OutOfDeviceMemory => {
|
||||
@ -585,7 +574,6 @@ impl From<VulkanError> for FlushError {
|
||||
}
|
||||
|
||||
impl From<FenceError> for FlushError {
|
||||
#[inline]
|
||||
fn from(err: FenceError) -> FlushError {
|
||||
match err {
|
||||
FenceError::OomError(err) => FlushError::OomError(err),
|
||||
|
@ -27,7 +27,6 @@ use std::{
|
||||
};
|
||||
|
||||
/// Builds a new semaphore signal future.
|
||||
#[inline]
|
||||
pub fn then_signal_semaphore<F>(future: F) -> SemaphoreSignalFuture<F>
|
||||
where
|
||||
F: GpuFuture,
|
||||
@ -64,17 +63,15 @@ unsafe impl<F> GpuFuture for SemaphoreSignalFuture<F>
|
||||
where
|
||||
F: GpuFuture,
|
||||
{
|
||||
#[inline]
|
||||
fn cleanup_finished(&mut self) {
|
||||
self.previous.cleanup_finished();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
|
||||
// Flushing the signaling part, since it must always be submitted before the waiting part.
|
||||
self.flush()?;
|
||||
|
||||
let sem = smallvec![self.semaphore.clone()];
|
||||
|
||||
Ok(SubmitAnyBuilder::SemaphoresWait(sem))
|
||||
}
|
||||
|
||||
@ -193,24 +190,20 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn signal_finished(&self) {
|
||||
debug_assert!(*self.wait_submitted.lock());
|
||||
self.finished.store(true, Ordering::SeqCst);
|
||||
self.previous.signal_finished();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue_change_allowed(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn queue(&self) -> Option<Arc<Queue>> {
|
||||
self.previous.queue()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_buffer_access(
|
||||
&self,
|
||||
buffer: &UnsafeBuffer,
|
||||
@ -223,7 +216,6 @@ where
|
||||
.map(|_| None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn check_image_access(
|
||||
&self,
|
||||
image: &UnsafeImage,
|
||||
@ -251,7 +243,6 @@ unsafe impl<F> DeviceOwned for SemaphoreSignalFuture<F>
|
||||
where
|
||||
F: GpuFuture,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.semaphore.device()
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user