mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-16 17:12:29 +00:00
Rewrite copy commands (#1873)
* Allow `SyncCommandBufferBuilder` commands to specify the access range * Allow `SyncCommandBufferBuilder` commands to specify the access range * Better handling of image initialization * Small fix * Rewrite copy commands * Better handling of maintenance1 * Small leftovers * Remove conflict_key
This commit is contained in:
parent
44e30574d9
commit
201e21d3e6
@ -17,7 +17,7 @@
|
||||
use std::{fs::File, io::BufWriter, path::Path};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, CopyImageToBufferInfo},
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
@ -230,7 +230,10 @@ fn main() {
|
||||
1,
|
||||
])
|
||||
.unwrap()
|
||||
.copy_image_to_buffer(image.clone(), buf.clone())
|
||||
.copy_image_to_buffer(CopyImageToBufferInfo::image_buffer(
|
||||
image.clone(),
|
||||
buf.clone(),
|
||||
))
|
||||
.unwrap();
|
||||
let command_buffer = builder.build().unwrap();
|
||||
|
||||
|
@ -99,8 +99,8 @@ mod linux {
|
||||
Format::R16G16B16A16_UNORM,
|
||||
ImageUsage {
|
||||
sampled: true,
|
||||
transfer_source: true,
|
||||
transfer_destination: true,
|
||||
transfer_src: true,
|
||||
transfer_dst: true,
|
||||
..ImageUsage::none()
|
||||
},
|
||||
ImageCreateFlags {
|
||||
|
@ -12,16 +12,19 @@ use std::{io::Cursor, sync::Arc};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryCommandBuffer, SubpassContents,
|
||||
AutoCommandBufferBuilder, BlitImageInfo, BufferImageCopy, ClearColorImageInfo,
|
||||
CommandBufferUsage, CopyBufferToImageInfo, CopyImageInfo, ImageBlit, ImageCopy,
|
||||
PrimaryCommandBuffer, SubpassContents,
|
||||
},
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
|
||||
},
|
||||
format::{ClearValue, Format},
|
||||
format::Format,
|
||||
image::{
|
||||
view::ImageView, ImageAccess, ImageDimensions, ImageUsage, StorageImage, SwapchainImage,
|
||||
view::ImageView, ImageAccess, ImageDimensions, ImageLayout, ImageUsage, StorageImage,
|
||||
SwapchainImage,
|
||||
},
|
||||
impl_vertex,
|
||||
instance::{Instance, InstanceCreateInfo},
|
||||
@ -207,7 +210,7 @@ fn main() {
|
||||
|
||||
let buffer = CpuAccessibleBuffer::from_iter(
|
||||
device.clone(),
|
||||
BufferUsage::transfer_source(),
|
||||
BufferUsage::transfer_src(),
|
||||
false,
|
||||
image_data,
|
||||
)
|
||||
@ -222,49 +225,60 @@ fn main() {
|
||||
// here, we perform image copying and blitting on the same image
|
||||
builder
|
||||
// clear the image buffer
|
||||
.clear_color_image(image.clone(), ClearValue::Float([0.0, 0.0, 0.0, 0.0]))
|
||||
.clear_color_image(ClearColorImageInfo::image(image.clone()))
|
||||
.unwrap()
|
||||
// put our image in the top left corner
|
||||
.copy_buffer_to_image_dimensions(
|
||||
buffer,
|
||||
image.clone(),
|
||||
[0, 0, 0],
|
||||
[img_size[0], img_size[1], 1],
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
)
|
||||
.copy_buffer_to_image(CopyBufferToImageInfo {
|
||||
regions: [BufferImageCopy {
|
||||
image_subresource: image.subresource_layers(),
|
||||
image_extent: [img_size[0], img_size[1], 1],
|
||||
..Default::default()
|
||||
}]
|
||||
.into(),
|
||||
..CopyBufferToImageInfo::buffer_image(buffer, image.clone())
|
||||
})
|
||||
.unwrap()
|
||||
// copy from the top left corner to the bottom right corner
|
||||
.copy_image(
|
||||
image.clone(),
|
||||
[0, 0, 0],
|
||||
0,
|
||||
0,
|
||||
image.clone(),
|
||||
[img_size[0] as i32, img_size[1] as i32, 0],
|
||||
0,
|
||||
0,
|
||||
[img_size[0], img_size[1], 1],
|
||||
1,
|
||||
)
|
||||
.copy_image(CopyImageInfo {
|
||||
// Copying within the same image requires the General layout if the source and
|
||||
// destination subresources overlap.
|
||||
src_image_layout: ImageLayout::General,
|
||||
dst_image_layout: ImageLayout::General,
|
||||
regions: [ImageCopy {
|
||||
src_subresource: image.subresource_layers(),
|
||||
src_offset: [0, 0, 0],
|
||||
dst_subresource: image.subresource_layers(),
|
||||
dst_offset: [img_size[0], img_size[1], 0],
|
||||
extent: [img_size[0], img_size[1], 1],
|
||||
..Default::default()
|
||||
}]
|
||||
.into(),
|
||||
..CopyImageInfo::images(image.clone(), image.clone())
|
||||
})
|
||||
.unwrap()
|
||||
// blit from the bottom right corner to the top right corner (flipped)
|
||||
.blit_image(
|
||||
image.clone(),
|
||||
[img_size[0] as i32, img_size[1] as i32, 0],
|
||||
[img_size[0] as i32 * 2, img_size[1] as i32 * 2, 1],
|
||||
0,
|
||||
0,
|
||||
image.clone(),
|
||||
// flipping the top_left and bottom_right corners results in flipped image
|
||||
[img_size[0] as i32 * 2 - 1, img_size[1] as i32 - 1, 0],
|
||||
[img_size[0] as i32, 0, 1],
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
Filter::Nearest,
|
||||
)
|
||||
.blit_image(BlitImageInfo {
|
||||
// Same for blitting.
|
||||
src_image_layout: ImageLayout::General,
|
||||
dst_image_layout: ImageLayout::General,
|
||||
regions: [ImageBlit {
|
||||
src_subresource: image.subresource_layers(),
|
||||
src_offsets: [
|
||||
[img_size[0], img_size[1], 0],
|
||||
[img_size[0] * 2, img_size[1] * 2, 1],
|
||||
],
|
||||
dst_subresource: image.subresource_layers(),
|
||||
// swapping the two corners results in flipped image
|
||||
dst_offsets: [
|
||||
[img_size[0] * 2 - 1, img_size[1] - 1, 0],
|
||||
[img_size[0], 0, 1],
|
||||
],
|
||||
..Default::default()
|
||||
}]
|
||||
.into(),
|
||||
filter: Filter::Nearest,
|
||||
..BlitImageInfo::images(image.clone(), image.clone())
|
||||
})
|
||||
.unwrap();
|
||||
let command_buffer = builder.build().unwrap();
|
||||
|
||||
|
@ -130,7 +130,7 @@ void main() {
|
||||
// We can use copy_buffer(), fill_buffer() and some other functions that copies data to
|
||||
// buffer also.
|
||||
builder
|
||||
.update_buffer(immutable_data_buffer_init, &3u32)
|
||||
.update_buffer(&3u32, immutable_data_buffer_init, 0)
|
||||
.unwrap();
|
||||
|
||||
let command_buffer = builder.build().unwrap();
|
||||
|
@ -69,7 +69,8 @@ use std::{fs::File, io::BufWriter, path::Path};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryCommandBuffer, SubpassContents,
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, CopyImageToBufferInfo, PrimaryCommandBuffer,
|
||||
SubpassContents,
|
||||
},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
@ -317,7 +318,10 @@ fn main() {
|
||||
.unwrap()
|
||||
.end_render_pass()
|
||||
.unwrap()
|
||||
.copy_image_to_buffer(image.clone(), buf.clone())
|
||||
.copy_image_to_buffer(CopyImageToBufferInfo::image_buffer(
|
||||
image.clone(),
|
||||
buf.clone(),
|
||||
))
|
||||
.unwrap();
|
||||
let command_buffer = builder.build().unwrap();
|
||||
|
||||
|
@ -290,7 +290,7 @@ pub fn create_device_image(queue: Arc<Queue>, size: [u32; 2], format: Format) ->
|
||||
sampled: true,
|
||||
storage: true,
|
||||
color_attachment: true,
|
||||
transfer_destination: true,
|
||||
transfer_dst: true,
|
||||
..ImageUsage::none()
|
||||
},
|
||||
flags,
|
||||
|
@ -17,15 +17,18 @@ use bytemuck::{Pod, Zeroable};
|
||||
use std::{fs::File, io::BufWriter, path::Path, sync::Arc};
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, BufferImageCopy, CommandBufferUsage, CopyImageToBufferInfo,
|
||||
SubpassContents,
|
||||
},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
Device, DeviceCreateInfo, DeviceExtensions, Features, QueueCreateInfo,
|
||||
},
|
||||
format::Format,
|
||||
image::{
|
||||
view::ImageView, ImageAccess, ImageCreateFlags, ImageDimensions, ImageLayout, ImageUsage,
|
||||
SampleCount, StorageImage,
|
||||
view::ImageView, ImageAccess, ImageCreateFlags, ImageDimensions, ImageLayout,
|
||||
ImageSubresourceLayers, ImageUsage, SampleCount, StorageImage,
|
||||
},
|
||||
impl_vertex,
|
||||
instance::{Instance, InstanceCreateInfo, InstanceExtensions},
|
||||
@ -125,7 +128,7 @@ fn main() {
|
||||
},
|
||||
Format::B8G8R8A8_SRGB,
|
||||
ImageUsage {
|
||||
transfer_source: true,
|
||||
transfer_src: true,
|
||||
color_attachment: true,
|
||||
..ImageUsage::none()
|
||||
},
|
||||
@ -293,25 +296,31 @@ fn main() {
|
||||
|
||||
// copy the image layers to different buffers to save them as individual images to disk
|
||||
builder
|
||||
.copy_image_to_buffer_dimensions(
|
||||
image.clone(),
|
||||
buffer1.clone(),
|
||||
[0, 0, 0],
|
||||
image.dimensions().width_height_depth(),
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
)
|
||||
.copy_image_to_buffer(CopyImageToBufferInfo {
|
||||
regions: [BufferImageCopy {
|
||||
image_subresource: ImageSubresourceLayers {
|
||||
array_layers: 0..1,
|
||||
..image.subresource_layers()
|
||||
},
|
||||
image_extent: image.dimensions().width_height_depth(),
|
||||
..Default::default()
|
||||
}]
|
||||
.into(),
|
||||
..CopyImageToBufferInfo::image_buffer(image.clone(), buffer1.clone())
|
||||
})
|
||||
.unwrap()
|
||||
.copy_image_to_buffer_dimensions(
|
||||
image.clone(),
|
||||
buffer2.clone(),
|
||||
[0, 0, 0],
|
||||
image.dimensions().width_height_depth(),
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
)
|
||||
.copy_image_to_buffer(CopyImageToBufferInfo {
|
||||
regions: [BufferImageCopy {
|
||||
image_subresource: ImageSubresourceLayers {
|
||||
array_layers: 1..2,
|
||||
..image.subresource_layers()
|
||||
},
|
||||
image_extent: image.dimensions().width_height_depth(),
|
||||
..Default::default()
|
||||
}]
|
||||
.into(),
|
||||
..CopyImageToBufferInfo::image_buffer(image.clone(), buffer2.clone())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let command_buffer = builder.build().unwrap();
|
||||
|
@ -12,7 +12,9 @@
|
||||
|
||||
use vulkano::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer},
|
||||
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, BufferCopy, CommandBufferUsage, CopyBufferInfoTyped,
|
||||
},
|
||||
descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet},
|
||||
device::{
|
||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||
@ -104,8 +106,8 @@ fn main() {
|
||||
device.clone(),
|
||||
BufferUsage {
|
||||
storage_buffer: true,
|
||||
transfer_source: true,
|
||||
transfer_destination: true,
|
||||
transfer_src: true,
|
||||
transfer_dst: true,
|
||||
..BufferUsage::none()
|
||||
},
|
||||
false,
|
||||
@ -129,13 +131,16 @@ fn main() {
|
||||
.unwrap();
|
||||
builder
|
||||
// copy from the first half to the second half (inside the same buffer) before we run the computation
|
||||
.copy_buffer_dimensions(
|
||||
data_buffer.clone(),
|
||||
0,
|
||||
data_buffer.clone(),
|
||||
65536 / 2,
|
||||
65536 / 2,
|
||||
)
|
||||
.copy_buffer(CopyBufferInfoTyped {
|
||||
regions: [BufferCopy {
|
||||
src_offset: 0,
|
||||
dst_offset: 65536 / 2,
|
||||
size: 65536 / 2,
|
||||
..Default::default()
|
||||
}]
|
||||
.into(),
|
||||
..CopyBufferInfoTyped::buffers(data_buffer.clone(), data_buffer.clone())
|
||||
})
|
||||
.unwrap()
|
||||
.bind_pipeline_compute(pipeline.clone())
|
||||
.bind_descriptor_sets(
|
||||
|
@ -409,11 +409,6 @@ where
|
||||
fn size(&self) -> DeviceSize {
|
||||
self.inner.size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> (u64, u64) {
|
||||
(self.inner.key(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, A> BufferAccessObject for Arc<CpuAccessibleBuffer<T, A>>
|
||||
|
@ -81,7 +81,7 @@ use std::{
|
||||
/// .unwrap()
|
||||
/// // For the sake of the example we just call `update_buffer` on the buffer, even though
|
||||
/// // it is pointless to do that.
|
||||
/// .update_buffer(sub_buffer.clone(), &[0.2, 0.3, 0.4, 0.5])
|
||||
/// .update_buffer(&[0.2, 0.3, 0.4, 0.5], sub_buffer.clone(), 0)
|
||||
/// .unwrap()
|
||||
/// .build().unwrap()
|
||||
/// .execute(queue.clone())
|
||||
@ -217,7 +217,7 @@ where
|
||||
/// - Panics if `T` has zero size.
|
||||
#[inline]
|
||||
pub fn upload(device: Arc<Device>) -> CpuBufferPool<T> {
|
||||
CpuBufferPool::new(device, BufferUsage::transfer_source())
|
||||
CpuBufferPool::new(device, BufferUsage::transfer_src())
|
||||
}
|
||||
|
||||
/// Builds a `CpuBufferPool` meant for simple downloads.
|
||||
@ -230,7 +230,7 @@ where
|
||||
/// - Panics if `T` has zero size.
|
||||
#[inline]
|
||||
pub fn download(device: Arc<Device>) -> CpuBufferPool<T> {
|
||||
CpuBufferPool::new(device, BufferUsage::transfer_destination())
|
||||
CpuBufferPool::new(device, BufferUsage::transfer_dst())
|
||||
}
|
||||
|
||||
/// Builds a `CpuBufferPool` meant for usage as a uniform buffer.
|
||||
@ -675,19 +675,6 @@ where
|
||||
fn size(&self) -> DeviceSize {
|
||||
self.requested_len * size_of::<T>() as DeviceSize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> (u64, u64) {
|
||||
(
|
||||
self.buffer.inner.key(),
|
||||
// ensure the special cased empty buffers don't collide with a regular buffer starting at 0
|
||||
if self.requested_len == 0 {
|
||||
u64::MAX
|
||||
} else {
|
||||
self.index
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, A> BufferAccessObject for Arc<CpuBufferPoolChunk<T, A>>
|
||||
@ -807,11 +794,6 @@ where
|
||||
fn size(&self) -> DeviceSize {
|
||||
self.chunk.size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> (u64, u64) {
|
||||
self.chunk.conflict_key()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, A> BufferAccessObject for Arc<CpuBufferPoolSubbuffer<T, A>>
|
||||
|
@ -319,11 +319,6 @@ where
|
||||
fn size(&self) -> DeviceSize {
|
||||
self.inner.size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> (u64, u64) {
|
||||
(self.inner.key(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, A> BufferAccessObject for Arc<DeviceLocalBuffer<T, A>>
|
||||
|
@ -25,7 +25,7 @@ use super::{
|
||||
use crate::{
|
||||
buffer::{sys::UnsafeBufferCreateInfo, BufferCreationError, TypedBufferAccess},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferExecFuture, CommandBufferUsage,
|
||||
AutoCommandBufferBuilder, CommandBufferExecFuture, CommandBufferUsage, CopyBufferInfo,
|
||||
PrimaryAutoCommandBuffer, PrimaryCommandBuffer,
|
||||
},
|
||||
device::{physical::QueueFamily, Device, DeviceOwned, Queue},
|
||||
@ -91,9 +91,9 @@ where
|
||||
B: TypedBufferAccess<Content = T> + 'static,
|
||||
{
|
||||
unsafe {
|
||||
// We automatically set `transfer_destination` to true in order to avoid annoying errors.
|
||||
// We automatically set `transfer_dst` to true in order to avoid annoying errors.
|
||||
let actual_usage = BufferUsage {
|
||||
transfer_destination: true,
|
||||
transfer_dst: true,
|
||||
..usage
|
||||
};
|
||||
|
||||
@ -109,7 +109,8 @@ where
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)?;
|
||||
cbb.copy_buffer(source, init).unwrap(); // TODO: return error?
|
||||
cbb.copy_buffer(CopyBufferInfo::buffers(source, init))
|
||||
.unwrap(); // TODO: return error?
|
||||
let cb = cbb.build().unwrap(); // TODO: return OomError
|
||||
|
||||
let future = match cb.execute(queue) {
|
||||
@ -150,7 +151,7 @@ where
|
||||
> {
|
||||
let source = CpuAccessibleBuffer::from_data(
|
||||
queue.device().clone(),
|
||||
BufferUsage::transfer_source(),
|
||||
BufferUsage::transfer_src(),
|
||||
false,
|
||||
data,
|
||||
)?;
|
||||
@ -218,7 +219,7 @@ where
|
||||
{
|
||||
let source = CpuAccessibleBuffer::from_iter(
|
||||
queue.device().clone(),
|
||||
BufferUsage::transfer_source(),
|
||||
BufferUsage::transfer_src(),
|
||||
false,
|
||||
data,
|
||||
)?;
|
||||
@ -417,11 +418,6 @@ where
|
||||
fn size(&self) -> DeviceSize {
|
||||
self.inner.size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> (u64, u64) {
|
||||
(self.inner.key(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, A> BufferAccessObject for Arc<ImmutableBuffer<T, A>>
|
||||
@ -506,11 +502,6 @@ where
|
||||
fn size(&self) -> DeviceSize {
|
||||
self.buffer.size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> (u64, u64) {
|
||||
(self.buffer.inner.key(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, A> BufferAccessObject for Arc<ImmutableBufferInitialization<T, A>>
|
||||
@ -586,12 +577,7 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::buffer::cpu_access::CpuAccessibleBuffer;
|
||||
use crate::buffer::immutable::ImmutableBuffer;
|
||||
use crate::buffer::BufferUsage;
|
||||
use crate::command_buffer::AutoCommandBufferBuilder;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::command_buffer::PrimaryCommandBuffer;
|
||||
use super::*;
|
||||
use crate::sync::GpuFuture;
|
||||
|
||||
#[test]
|
||||
@ -610,7 +596,8 @@ mod tests {
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.copy_buffer(buffer, destination.clone()).unwrap();
|
||||
cbb.copy_buffer(CopyBufferInfo::buffers(buffer, destination.clone()))
|
||||
.unwrap();
|
||||
let _ = cbb
|
||||
.build()
|
||||
.unwrap()
|
||||
@ -648,7 +635,8 @@ mod tests {
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.copy_buffer(buffer, destination.clone()).unwrap();
|
||||
cbb.copy_buffer(CopyBufferInfo::buffers(buffer, destination.clone()))
|
||||
.unwrap();
|
||||
let _ = cbb
|
||||
.build()
|
||||
.unwrap()
|
||||
@ -680,9 +668,9 @@ mod tests {
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.copy_buffer(source.clone(), init)
|
||||
cbb.copy_buffer(CopyBufferInfo::buffers(source.clone(), init))
|
||||
.unwrap()
|
||||
.copy_buffer(buffer, source.clone())
|
||||
.copy_buffer(CopyBufferInfo::buffers(buffer, source.clone()))
|
||||
.unwrap();
|
||||
let _ = cbb
|
||||
.build()
|
||||
@ -711,7 +699,8 @@ mod tests {
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.copy_buffer(source.clone(), init).unwrap();
|
||||
cbb.copy_buffer(CopyBufferInfo::buffers(source.clone(), init))
|
||||
.unwrap();
|
||||
let cb1 = cbb.build().unwrap();
|
||||
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
@ -720,7 +709,8 @@ mod tests {
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.copy_buffer(buffer, source.clone()).unwrap();
|
||||
cbb.copy_buffer(CopyBufferInfo::buffers(buffer, source.clone()))
|
||||
.unwrap();
|
||||
let cb2 = cbb.build().unwrap();
|
||||
|
||||
let _ = cb1
|
||||
|
@ -225,11 +225,6 @@ where
|
||||
fn size(&self) -> DeviceSize {
|
||||
self.size
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> (u64, u64) {
|
||||
self.resource.conflict_key()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, B> BufferAccessObject for Arc<BufferSlice<T, B>>
|
||||
|
@ -331,10 +331,10 @@ impl UnsafeBuffer {
|
||||
self.size
|
||||
}
|
||||
|
||||
/// Returns the buffer the image was created with.
|
||||
/// Returns the usage the buffer was created with.
|
||||
#[inline]
|
||||
pub fn usage(&self) -> BufferUsage {
|
||||
self.usage
|
||||
pub fn usage(&self) -> &BufferUsage {
|
||||
&self.usage
|
||||
}
|
||||
|
||||
/// Returns a key unique to each `UnsafeBuffer`. Can be used for the `conflicts_key` method.
|
||||
|
@ -7,7 +7,7 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use super::{sys::UnsafeBuffer, BufferContents, BufferSlice};
|
||||
use super::{sys::UnsafeBuffer, BufferContents, BufferSlice, BufferUsage};
|
||||
use crate::{device::DeviceOwned, DeviceSize, SafeDeref, VulkanObject};
|
||||
use std::{
|
||||
error, fmt,
|
||||
@ -28,6 +28,12 @@ pub unsafe trait BufferAccess: DeviceOwned + Send + Sync {
|
||||
/// Returns the size of the buffer in bytes.
|
||||
fn size(&self) -> DeviceSize;
|
||||
|
||||
/// Returns the usage the buffer was created with.
|
||||
#[inline]
|
||||
fn usage(&self) -> &BufferUsage {
|
||||
self.inner().buffer.usage()
|
||||
}
|
||||
|
||||
/// Returns a `BufferSlice` covering the whole buffer.
|
||||
#[inline]
|
||||
fn into_buffer_slice(self: &Arc<Self>) -> Arc<BufferSlice<Self::Content, Self>>
|
||||
@ -62,18 +68,6 @@ pub unsafe trait BufferAccess: DeviceOwned + Send + Sync {
|
||||
BufferSlice::index(&self.into_buffer_slice(), index)
|
||||
}
|
||||
|
||||
/// Returns a key that uniquely identifies the buffer. Two buffers or images that potentially
|
||||
/// overlap in memory must return the same key.
|
||||
///
|
||||
/// The key is shared amongst all buffers and images, which means that you can make several
|
||||
/// different buffer objects share the same memory, or make some buffer objects share memory
|
||||
/// with images, as long as they return the same key.
|
||||
///
|
||||
/// Since it is possible to accidentally return the same key for memory ranges that don't
|
||||
/// overlap, the `conflicts_buffer` or `conflicts_image` function should always be called to
|
||||
/// verify whether they actually overlap.
|
||||
fn conflict_key(&self) -> (u64, u64);
|
||||
|
||||
/// Gets the device address for this buffer.
|
||||
///
|
||||
/// # Safety
|
||||
@ -148,11 +142,6 @@ where
|
||||
fn size(&self) -> DeviceSize {
|
||||
(**self).size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> (u64, u64) {
|
||||
(**self).conflict_key()
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait for `BufferAccess`. Indicates the type of the content of the buffer.
|
||||
@ -177,6 +166,14 @@ where
|
||||
type Content = <T::Target as TypedBufferAccess>::Content;
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn BufferAccess {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("dyn BufferAccess")
|
||||
.field("inner", &self.inner())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for dyn BufferAccess {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
|
@ -17,8 +17,8 @@ use std::ops::BitOr;
|
||||
/// there is no restriction in the combination of BufferUsages that can be enabled.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub struct BufferUsage {
|
||||
pub transfer_source: bool,
|
||||
pub transfer_destination: bool,
|
||||
pub transfer_src: bool,
|
||||
pub transfer_dst: bool,
|
||||
pub uniform_texel_buffer: bool,
|
||||
pub storage_texel_buffer: bool,
|
||||
pub uniform_buffer: bool,
|
||||
@ -35,8 +35,8 @@ impl BufferUsage {
|
||||
#[inline]
|
||||
pub const fn none() -> BufferUsage {
|
||||
BufferUsage {
|
||||
transfer_source: false,
|
||||
transfer_destination: false,
|
||||
transfer_src: false,
|
||||
transfer_dst: false,
|
||||
uniform_texel_buffer: false,
|
||||
storage_texel_buffer: false,
|
||||
uniform_buffer: false,
|
||||
@ -53,8 +53,8 @@ impl BufferUsage {
|
||||
#[inline]
|
||||
pub const fn all() -> BufferUsage {
|
||||
BufferUsage {
|
||||
transfer_source: true,
|
||||
transfer_destination: true,
|
||||
transfer_src: true,
|
||||
transfer_dst: true,
|
||||
uniform_texel_buffer: true,
|
||||
storage_texel_buffer: true,
|
||||
uniform_buffer: true,
|
||||
@ -67,20 +67,20 @@ impl BufferUsage {
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a `BufferUsage` with `transfer_source` set to true and the rest to false.
|
||||
/// Builds a `BufferUsage` with `transfer_src` set to true and the rest to false.
|
||||
#[inline]
|
||||
pub const fn transfer_source() -> BufferUsage {
|
||||
pub const fn transfer_src() -> BufferUsage {
|
||||
BufferUsage {
|
||||
transfer_source: true,
|
||||
transfer_src: true,
|
||||
..BufferUsage::none()
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a `BufferUsage` with `transfer_destination` set to true and the rest to false.
|
||||
/// Builds a `BufferUsage` with `transfer_dst` set to true and the rest to false.
|
||||
#[inline]
|
||||
pub const fn transfer_destination() -> BufferUsage {
|
||||
pub const fn transfer_dst() -> BufferUsage {
|
||||
BufferUsage {
|
||||
transfer_destination: true,
|
||||
transfer_dst: true,
|
||||
..BufferUsage::none()
|
||||
}
|
||||
}
|
||||
@ -94,13 +94,13 @@ impl BufferUsage {
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a `BufferUsage` with `vertex_buffer` and `transfer_destination` set to true and the rest
|
||||
/// Builds a `BufferUsage` with `vertex_buffer` and `transfer_dst` set to true and the rest
|
||||
/// to false.
|
||||
#[inline]
|
||||
pub const fn vertex_buffer_transfer_destination() -> BufferUsage {
|
||||
pub const fn vertex_buffer_transfer_dst() -> BufferUsage {
|
||||
BufferUsage {
|
||||
vertex_buffer: true,
|
||||
transfer_destination: true,
|
||||
transfer_dst: true,
|
||||
..BufferUsage::none()
|
||||
}
|
||||
}
|
||||
@ -114,12 +114,12 @@ impl BufferUsage {
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a `BufferUsage` with `index_buffer` and `transfer_destination` set to true and the rest to false.
|
||||
/// Builds a `BufferUsage` with `index_buffer` and `transfer_dst` set to true and the rest to false.
|
||||
#[inline]
|
||||
pub const fn index_buffer_transfer_destination() -> BufferUsage {
|
||||
pub const fn index_buffer_transfer_dst() -> BufferUsage {
|
||||
BufferUsage {
|
||||
index_buffer: true,
|
||||
transfer_destination: true,
|
||||
transfer_dst: true,
|
||||
..BufferUsage::none()
|
||||
}
|
||||
}
|
||||
@ -142,13 +142,13 @@ impl BufferUsage {
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a `BufferUsage` with `uniform_buffer` and `transfer_destination` set to true and the rest
|
||||
/// Builds a `BufferUsage` with `uniform_buffer` and `transfer_dst` set to true and the rest
|
||||
/// to false.
|
||||
#[inline]
|
||||
pub const fn uniform_buffer_transfer_destination() -> BufferUsage {
|
||||
pub const fn uniform_buffer_transfer_dst() -> BufferUsage {
|
||||
BufferUsage {
|
||||
uniform_buffer: true,
|
||||
transfer_destination: true,
|
||||
transfer_dst: true,
|
||||
..BufferUsage::none()
|
||||
}
|
||||
}
|
||||
@ -162,13 +162,13 @@ impl BufferUsage {
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a `BufferUsage` with `indirect_buffer` and `transfer_destination` set to true and the rest
|
||||
/// Builds a `BufferUsage` with `indirect_buffer` and `transfer_dst` set to true and the rest
|
||||
/// to false.
|
||||
#[inline]
|
||||
pub const fn indirect_buffer_transfer_destination() -> BufferUsage {
|
||||
pub const fn indirect_buffer_transfer_dst() -> BufferUsage {
|
||||
BufferUsage {
|
||||
indirect_buffer: true,
|
||||
transfer_destination: true,
|
||||
transfer_dst: true,
|
||||
..BufferUsage::none()
|
||||
}
|
||||
}
|
||||
@ -186,10 +186,10 @@ impl BufferUsage {
|
||||
impl From<BufferUsage> for ash::vk::BufferUsageFlags {
|
||||
fn from(val: BufferUsage) -> Self {
|
||||
let mut result = ash::vk::BufferUsageFlags::empty();
|
||||
if val.transfer_source {
|
||||
if val.transfer_src {
|
||||
result |= ash::vk::BufferUsageFlags::TRANSFER_SRC;
|
||||
}
|
||||
if val.transfer_destination {
|
||||
if val.transfer_dst {
|
||||
result |= ash::vk::BufferUsageFlags::TRANSFER_DST;
|
||||
}
|
||||
if val.uniform_texel_buffer {
|
||||
@ -226,8 +226,8 @@ impl BitOr for BufferUsage {
|
||||
#[inline]
|
||||
fn bitor(self, rhs: Self) -> Self {
|
||||
BufferUsage {
|
||||
transfer_source: self.transfer_source || rhs.transfer_source,
|
||||
transfer_destination: self.transfer_destination || rhs.transfer_destination,
|
||||
transfer_src: self.transfer_src || rhs.transfer_src,
|
||||
transfer_dst: self.transfer_dst || rhs.transfer_dst,
|
||||
uniform_texel_buffer: self.uniform_texel_buffer || rhs.uniform_texel_buffer,
|
||||
storage_texel_buffer: self.storage_texel_buffer || rhs.storage_texel_buffer,
|
||||
uniform_buffer: self.uniform_buffer || rhs.uniform_buffer,
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
use super::{
|
||||
commands::{
|
||||
image::{CheckBlitImageError, CheckClearColorImageError, CheckClearDepthStencilImageError},
|
||||
pipeline::{
|
||||
CheckDescriptorSetsValidityError, CheckDispatchError, CheckDynamicStateValidityError,
|
||||
CheckIndexBufferError, CheckIndirectBufferError, CheckPipelineError,
|
||||
@ -19,10 +18,6 @@ use super::{
|
||||
CheckBeginQueryError, CheckCopyQueryPoolResultsError, CheckEndQueryError,
|
||||
CheckResetQueryPoolError, CheckWriteTimestampError,
|
||||
},
|
||||
transfer::{
|
||||
CheckCopyBufferError, CheckCopyBufferImageError, CheckCopyImageError,
|
||||
CheckFillBufferError, CheckUpdateBufferError,
|
||||
},
|
||||
},
|
||||
pool::{
|
||||
standard::{StandardCommandPoolAlloc, StandardCommandPoolBuilder},
|
||||
@ -787,54 +782,12 @@ err_gen!(BeginRenderPassError {
|
||||
SyncCommandBufferBuilderError,
|
||||
});
|
||||
|
||||
err_gen!(CopyImageError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckCopyImageError,
|
||||
SyncCommandBufferBuilderError,
|
||||
});
|
||||
|
||||
err_gen!(BlitImageError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckBlitImageError,
|
||||
SyncCommandBufferBuilderError,
|
||||
});
|
||||
|
||||
err_gen!(ClearColorImageError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckClearColorImageError,
|
||||
SyncCommandBufferBuilderError,
|
||||
});
|
||||
|
||||
err_gen!(ClearDepthStencilImageError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckClearDepthStencilImageError,
|
||||
SyncCommandBufferBuilderError,
|
||||
});
|
||||
|
||||
err_gen!(CopyBufferError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckCopyBufferError,
|
||||
SyncCommandBufferBuilderError,
|
||||
});
|
||||
|
||||
err_gen!(CopyBufferImageError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckCopyBufferImageError,
|
||||
SyncCommandBufferBuilderError,
|
||||
});
|
||||
|
||||
err_gen!(CopyQueryPoolResultsError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckCopyQueryPoolResultsError,
|
||||
SyncCommandBufferBuilderError,
|
||||
});
|
||||
|
||||
err_gen!(FillBufferError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckFillBufferError,
|
||||
SyncCommandBufferBuilderError,
|
||||
});
|
||||
|
||||
err_gen!(DispatchError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckPipelineError,
|
||||
@ -923,12 +876,6 @@ err_gen!(ResetQueryPoolError {
|
||||
CheckResetQueryPoolError,
|
||||
});
|
||||
|
||||
err_gen!(UpdateBufferError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckUpdateBufferError,
|
||||
SyncCommandBufferBuilderError,
|
||||
});
|
||||
|
||||
/// Errors that can happen when calling [`clear_attachments`](AutoCommandBufferBuilder::clear_attachments)
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum ClearAttachmentsError {
|
||||
@ -1097,6 +1044,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer},
|
||||
command_buffer::{BufferCopy, CopyBufferInfoTyped, CopyError},
|
||||
device::{physical::PhysicalDevice, DeviceCreateInfo, QueueCreateInfo},
|
||||
};
|
||||
|
||||
@ -1148,8 +1096,17 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
cbb.copy_buffer_dimensions(source.clone(), 0, destination.clone(), 1, 2)
|
||||
.unwrap();
|
||||
cbb.copy_buffer(CopyBufferInfoTyped {
|
||||
regions: [BufferCopy {
|
||||
src_offset: 0,
|
||||
dst_offset: 1,
|
||||
size: 2,
|
||||
..Default::default()
|
||||
}]
|
||||
.into(),
|
||||
..CopyBufferInfoTyped::buffers(source.clone(), destination.clone())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let cb = cbb.build().unwrap();
|
||||
|
||||
@ -1256,7 +1213,16 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
builder
|
||||
.copy_buffer_dimensions(source.clone(), 0, source.clone(), 2, 2)
|
||||
.copy_buffer(CopyBufferInfoTyped {
|
||||
regions: [BufferCopy {
|
||||
src_offset: 0,
|
||||
dst_offset: 2,
|
||||
size: 2,
|
||||
..Default::default()
|
||||
}]
|
||||
.into(),
|
||||
..CopyBufferInfoTyped::buffers(source.clone(), source.clone())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let cb = builder.build().unwrap();
|
||||
@ -1293,10 +1259,20 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
assert!(matches!(
|
||||
builder.copy_buffer_dimensions(source.clone(), 0, source.clone(), 1, 2),
|
||||
Err(CopyBufferError::CheckCopyBufferError(
|
||||
CheckCopyBufferError::OverlappingRanges
|
||||
))
|
||||
builder.copy_buffer(CopyBufferInfoTyped {
|
||||
regions: [BufferCopy {
|
||||
src_offset: 0,
|
||||
dst_offset: 1,
|
||||
size: 2,
|
||||
..Default::default()
|
||||
}]
|
||||
.into(),
|
||||
..CopyBufferInfoTyped::buffers(source.clone(), source.clone())
|
||||
}),
|
||||
Err(CopyError::OverlappingRegions {
|
||||
src_region_index: 0,
|
||||
dst_region_index: 0,
|
||||
})
|
||||
));
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,3 +17,586 @@ pub(super) mod render_pass;
|
||||
pub(super) mod secondary;
|
||||
pub(super) mod sync;
|
||||
pub(super) mod transfer;
|
||||
|
||||
use super::synced::SyncCommandBufferBuilderError;
|
||||
use crate::{
|
||||
format::Format,
|
||||
image::{ImageAspects, ImageLayout, SampleCount, SampleCounts},
|
||||
DeviceSize,
|
||||
};
|
||||
use std::{error, fmt};
|
||||
|
||||
/// Error that can happen when recording a copy command.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum CopyError {
|
||||
SyncCommandBufferBuilderError(SyncCommandBufferBuilderError),
|
||||
|
||||
ExtensionNotEnabled {
|
||||
extension: &'static str,
|
||||
reason: &'static str,
|
||||
},
|
||||
|
||||
/// Operation forbidden inside of a render pass.
|
||||
ForbiddenInsideRenderPass,
|
||||
|
||||
/// The queue family doesn't allow this operation.
|
||||
NotSupportedByQueueFamily,
|
||||
|
||||
/// The array layer counts of the source and destination subresource ranges of a region do not
|
||||
/// match.
|
||||
ArrayLayerCountMismatch {
|
||||
region_index: usize,
|
||||
src_layer_count: u32,
|
||||
dst_layer_count: u32,
|
||||
},
|
||||
|
||||
/// The end of the range of accessed array layers of the subresource range of a region is
|
||||
/// greater than the number of array layers in the image.
|
||||
ArrayLayersOutOfRange {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
array_layers_range_end: u32,
|
||||
image_array_layers: u32,
|
||||
},
|
||||
|
||||
/// The aspects of the source and destination subresource ranges of a region do not match.
|
||||
AspectsMismatch {
|
||||
region_index: usize,
|
||||
src_aspects: ImageAspects,
|
||||
dst_aspects: ImageAspects,
|
||||
},
|
||||
|
||||
/// The aspects of the subresource range of a region contain aspects that are not present
|
||||
/// in the image, or that are not allowed.
|
||||
AspectsNotAllowed {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
aspects: ImageAspects,
|
||||
allowed_aspects: ImageAspects,
|
||||
},
|
||||
|
||||
/// The buffer image height of a region is not a multiple of the required buffer alignment.
|
||||
BufferImageHeightNotAligned {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
image_height: u32,
|
||||
required_alignment: u32,
|
||||
},
|
||||
|
||||
/// The buffer image height of a region is smaller than the image extent height.
|
||||
BufferImageHeightTooSmall {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
image_height: u32,
|
||||
min: u32,
|
||||
},
|
||||
|
||||
/// The buffer row length of a region is not a multiple of the required buffer alignment.
|
||||
BufferRowLengthNotAligned {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
row_length: u32,
|
||||
required_alignment: u32,
|
||||
},
|
||||
|
||||
/// The buffer row length of a region specifies a row of texels that is greater than 0x7FFFFFFF
|
||||
/// bytes in size.
|
||||
BufferRowLengthTooLarge {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
buffer_row_length: u32,
|
||||
},
|
||||
|
||||
/// The buffer row length of a region is smaller than the image extent width.
|
||||
BufferRowLengthTooSmall {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
row_length: u32,
|
||||
min: u32,
|
||||
},
|
||||
|
||||
/// The provided data has a size larger than the maximum allowed.
|
||||
DataTooLarge {
|
||||
size: DeviceSize,
|
||||
max: DeviceSize,
|
||||
},
|
||||
|
||||
/// 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.
|
||||
ExtentNotAlignedForImage {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
extent: [u32; 3],
|
||||
required_alignment: [u32; 3],
|
||||
},
|
||||
|
||||
/// The chosen filter type does not support the dimensionality of the source image.
|
||||
FilterNotSupportedForImageType,
|
||||
|
||||
/// The chosen filter type does not support the format of the source image.
|
||||
FilterNotSupportedByFormat,
|
||||
|
||||
/// The format of an image is not supported for this operation.
|
||||
FormatNotSupported {
|
||||
resource: CopyErrorResource,
|
||||
format: Format,
|
||||
},
|
||||
|
||||
/// The format of the source image does not match the format of the destination image.
|
||||
FormatsMismatch {
|
||||
src_format: Format,
|
||||
dst_format: Format,
|
||||
},
|
||||
|
||||
/// The format of the source image subresource is not compatible with the format of the
|
||||
/// destination image subresource.
|
||||
FormatsNotCompatible {
|
||||
src_format: Format,
|
||||
dst_format: Format,
|
||||
},
|
||||
|
||||
/// A specified image layout is not valid for this operation.
|
||||
ImageLayoutInvalid {
|
||||
resource: CopyErrorResource,
|
||||
image_layout: ImageLayout,
|
||||
},
|
||||
|
||||
/// The end of the range of accessed mip levels of the subresource range of a region is greater
|
||||
/// than the number of mip levels in the image.
|
||||
MipLevelsOutOfRange {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
mip_levels_range_end: u32,
|
||||
image_mip_levels: u32,
|
||||
},
|
||||
|
||||
/// An image does not have a required format feature.
|
||||
MissingFormatFeature {
|
||||
resource: CopyErrorResource,
|
||||
format_feature: &'static str,
|
||||
},
|
||||
|
||||
/// A resource did not have a required usage enabled.
|
||||
MissingUsage {
|
||||
resource: CopyErrorResource,
|
||||
usage: &'static str,
|
||||
},
|
||||
|
||||
/// A subresource range of a region specifies multiple aspects, but only one aspect can be
|
||||
/// selected for the image.
|
||||
MultipleAspectsNotAllowed {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
aspects: ImageAspects,
|
||||
},
|
||||
|
||||
/// The buffer offset of a region is not a multiple of the required buffer alignment.
|
||||
OffsetNotAlignedForBuffer {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
offset: DeviceSize,
|
||||
required_alignment: DeviceSize,
|
||||
},
|
||||
|
||||
/// The image offset of a region is not a multiple of the required image alignment.
|
||||
OffsetNotAlignedForImage {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
offset: [u32; 3],
|
||||
required_alignment: [u32; 3],
|
||||
},
|
||||
|
||||
/// The image offsets of a region are not the values required for that axis ([0, 1]) for the
|
||||
/// type of the image.
|
||||
OffsetsInvalidForImageType {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
offsets: [u32; 2],
|
||||
},
|
||||
|
||||
/// The source bounds of a region overlap with the destination bounds of a region.
|
||||
OverlappingRegions {
|
||||
src_region_index: usize,
|
||||
dst_region_index: usize,
|
||||
},
|
||||
|
||||
/// The source subresources of a region overlap with the destination subresources of a region,
|
||||
/// but the source image layout does not equal the destination image layout.
|
||||
OverlappingSubresourcesLayoutMismatch {
|
||||
src_region_index: usize,
|
||||
dst_region_index: usize,
|
||||
src_image_layout: ImageLayout,
|
||||
dst_image_layout: ImageLayout,
|
||||
},
|
||||
|
||||
/// The end of the range of accessed byte offsets of a region is greater than the size of the
|
||||
/// buffer.
|
||||
RegionOutOfBufferBounds {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
offset_range_end: DeviceSize,
|
||||
buffer_size: DeviceSize,
|
||||
},
|
||||
|
||||
/// The end of the range of accessed texel offsets of a region is greater than the extent of
|
||||
/// the selected subresource of the image.
|
||||
RegionOutOfImageBounds {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
offset_range_end: [u32; 3],
|
||||
subresource_extent: [u32; 3],
|
||||
},
|
||||
|
||||
/// An image has a sample count that is not valid for this operation.
|
||||
SampleCountInvalid {
|
||||
resource: CopyErrorResource,
|
||||
sample_count: SampleCount,
|
||||
allowed_sample_counts: SampleCounts,
|
||||
},
|
||||
|
||||
/// The source image has a different sample count than the destination image.
|
||||
SampleCountMismatch {
|
||||
src_sample_count: SampleCount,
|
||||
dst_sample_count: SampleCount,
|
||||
},
|
||||
|
||||
/// The buffer size of a region is not a multiple of the required buffer alignment.
|
||||
SizeNotAlignedForBuffer {
|
||||
resource: CopyErrorResource,
|
||||
region_index: usize,
|
||||
size: DeviceSize,
|
||||
required_alignment: DeviceSize,
|
||||
},
|
||||
}
|
||||
|
||||
impl error::Error for CopyError {
|
||||
#[inline]
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self {
|
||||
Self::SyncCommandBufferBuilderError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CopyError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"),
|
||||
Self::ExtensionNotEnabled { extension, reason } => write!(
|
||||
f,
|
||||
"the extension {} must be enabled: {}",
|
||||
extension, reason
|
||||
),
|
||||
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: {})",
|
||||
region_index, src_layer_count, dst_layer_count,
|
||||
),
|
||||
Self::ArrayLayersOutOfRange {
|
||||
resource,
|
||||
region_index,
|
||||
array_layers_range_end,
|
||||
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 ({})",
|
||||
array_layers_range_end, resource, region_index, resource, image_array_layers,
|
||||
),
|
||||
Self::AspectsMismatch {
|
||||
region_index,
|
||||
src_aspects,
|
||||
dst_aspects,
|
||||
} => write!(
|
||||
f,
|
||||
"the aspects of the source and destination subresource ranges of region {} do not match (source: {:?}; destination: {:?})",
|
||||
region_index, src_aspects, dst_aspects,
|
||||
),
|
||||
Self::AspectsNotAllowed {
|
||||
resource,
|
||||
region_index,
|
||||
aspects,
|
||||
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 ({:?})",
|
||||
aspects, resource, region_index, resource, allowed_aspects,
|
||||
),
|
||||
Self::BufferImageHeightNotAligned {
|
||||
resource,
|
||||
region_index,
|
||||
image_height,
|
||||
required_alignment,
|
||||
} => write!(
|
||||
f,
|
||||
"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 {
|
||||
resource,
|
||||
region_index,
|
||||
buffer_row_length,
|
||||
} => write!(
|
||||
f,
|
||||
"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 {
|
||||
resource,
|
||||
region_index,
|
||||
image_height,
|
||||
min,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} buffer image height ({}) of region {} is smaller than the {} image extent height ({})",
|
||||
resource, image_height, region_index, resource, min,
|
||||
),
|
||||
Self::BufferRowLengthNotAligned {
|
||||
resource,
|
||||
region_index,
|
||||
row_length,
|
||||
required_alignment,
|
||||
} => write!(
|
||||
f,
|
||||
"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 {
|
||||
resource,
|
||||
region_index,
|
||||
row_length,
|
||||
min,
|
||||
} => write!(
|
||||
f,
|
||||
"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!(
|
||||
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",
|
||||
),
|
||||
Self::ExtentNotAlignedForImage {
|
||||
resource,
|
||||
region_index,
|
||||
extent,
|
||||
required_alignment,
|
||||
} => write!(
|
||||
f,
|
||||
"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"
|
||||
),
|
||||
Self::FilterNotSupportedByFormat => write!(
|
||||
f,
|
||||
"the chosen filter is not supported by the format of the source image"
|
||||
),
|
||||
Self::FormatNotSupported {
|
||||
resource,
|
||||
format,
|
||||
} => write!(
|
||||
f,
|
||||
"the format of the {} image ({:?}) is not supported for this operation",
|
||||
resource, format,
|
||||
),
|
||||
Self::FormatsMismatch {
|
||||
src_format,
|
||||
dst_format,
|
||||
} => write!(
|
||||
f,
|
||||
"the format of the source image ({:?}) does not match the format of the destination image ({:?})",
|
||||
src_format, dst_format,
|
||||
),
|
||||
Self::FormatsNotCompatible {
|
||||
src_format,
|
||||
dst_format,
|
||||
} => write!(
|
||||
f,
|
||||
"the format of the source image subresource ({:?}) is not compatible with the format of the destination image subresource ({:?})",
|
||||
src_format, dst_format,
|
||||
),
|
||||
Self::ImageLayoutInvalid {
|
||||
resource,
|
||||
image_layout,
|
||||
} => write!(
|
||||
f,
|
||||
"the specified {} image layout {:?} is not valid for this operation",
|
||||
resource, image_layout,
|
||||
),
|
||||
Self::MipLevelsOutOfRange {
|
||||
resource,
|
||||
region_index,
|
||||
mip_levels_range_end,
|
||||
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 ({})",
|
||||
mip_levels_range_end, resource, region_index, resource, image_mip_levels,
|
||||
),
|
||||
Self::MissingFormatFeature {
|
||||
resource,
|
||||
format_feature,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} image does not have the required format feature {}",
|
||||
resource, format_feature,
|
||||
),
|
||||
Self::MissingUsage { resource, usage } => write!(
|
||||
f,
|
||||
"the {} resource did not have the required usage {} enabled",
|
||||
resource, usage,
|
||||
),
|
||||
Self::MultipleAspectsNotAllowed {
|
||||
resource,
|
||||
region_index,
|
||||
aspects,
|
||||
} => write!(
|
||||
f,
|
||||
"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 {
|
||||
resource,
|
||||
region_index,
|
||||
offset,
|
||||
required_alignment,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} buffer offset ({}) of region {} is not a multiple of the required {} buffer alignment ({})",
|
||||
resource, offset, region_index, resource, required_alignment,
|
||||
),
|
||||
Self::OffsetNotAlignedForImage {
|
||||
resource,
|
||||
region_index,
|
||||
offset,
|
||||
required_alignment,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} image offset ({:?}) of region {} is not a multiple of the required {} image alignment ({:?})",
|
||||
resource, offset, region_index, resource, required_alignment,
|
||||
),
|
||||
Self::OffsetsInvalidForImageType {
|
||||
resource,
|
||||
region_index,
|
||||
offsets,
|
||||
} => write!(
|
||||
f,
|
||||
"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 {
|
||||
src_region_index,
|
||||
dst_region_index,
|
||||
} => write!(
|
||||
f,
|
||||
"the source bounds of region {} overlap with the destination bounds of region {}",
|
||||
src_region_index, dst_region_index,
|
||||
),
|
||||
Self::OverlappingSubresourcesLayoutMismatch {
|
||||
src_region_index,
|
||||
dst_region_index,
|
||||
src_image_layout,
|
||||
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 ({:?})",
|
||||
src_region_index, dst_region_index, src_image_layout, dst_image_layout,
|
||||
),
|
||||
Self::RegionOutOfBufferBounds {
|
||||
resource,
|
||||
region_index,
|
||||
offset_range_end,
|
||||
buffer_size,
|
||||
} => write!(
|
||||
f,
|
||||
"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 {
|
||||
resource,
|
||||
region_index,
|
||||
offset_range_end,
|
||||
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 ({:?})",
|
||||
resource, offset_range_end, region_index, resource, subresource_extent,
|
||||
),
|
||||
Self::SampleCountInvalid {
|
||||
resource,
|
||||
sample_count,
|
||||
allowed_sample_counts,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} image has a sample count ({:?}) that is not valid for this operation ({:?})",
|
||||
resource, sample_count, allowed_sample_counts,
|
||||
),
|
||||
Self::SampleCountMismatch {
|
||||
src_sample_count,
|
||||
dst_sample_count,
|
||||
} => write!(
|
||||
f,
|
||||
"the source image has a different sample count ({:?}) than the destination image ({:?})",
|
||||
src_sample_count, dst_sample_count,
|
||||
),
|
||||
Self::SizeNotAlignedForBuffer {
|
||||
resource,
|
||||
region_index,
|
||||
size,
|
||||
required_alignment,
|
||||
} => write!(
|
||||
f,
|
||||
"the {} buffer size ({}) of region {} is not a multiple of the required {} buffer alignment ({})",
|
||||
resource, size, region_index, resource, required_alignment,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SyncCommandBufferBuilderError> for CopyError {
|
||||
#[inline]
|
||||
fn from(err: SyncCommandBufferBuilderError) -> Self {
|
||||
Self::SyncCommandBufferBuilderError(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates which resource a `CopyError` applies to.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum CopyErrorResource {
|
||||
Source,
|
||||
Destination,
|
||||
}
|
||||
|
||||
impl fmt::Display for CopyErrorResource {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match self {
|
||||
Self::Source => write!(f, "source"),
|
||||
Self::Destination => write!(f, "destination"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -453,7 +453,7 @@ where
|
||||
query_pool.device().internal_object(),
|
||||
);
|
||||
|
||||
if !buffer_inner.buffer.usage().transfer_destination {
|
||||
if !buffer_inner.buffer.usage().transfer_dst {
|
||||
return Err(CheckCopyQueryPoolResultsError::DestinationMissingTransferUsage);
|
||||
}
|
||||
|
||||
@ -816,7 +816,7 @@ impl UnsafeCommandBufferBuilder {
|
||||
let destination = destination.inner();
|
||||
let range = queries.range();
|
||||
debug_assert!(destination.offset < destination.buffer.size());
|
||||
debug_assert!(destination.buffer.usage().transfer_destination);
|
||||
debug_assert!(destination.buffer.usage().transfer_dst);
|
||||
debug_assert!(destination.offset % size_of::<T>() as DeviceSize == 0);
|
||||
debug_assert!(stride % size_of::<T>() as DeviceSize == 0);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -78,7 +78,10 @@
|
||||
|
||||
pub use self::commands::{
|
||||
debug::DebugUtilsError,
|
||||
image::{CheckBlitImageError, CheckClearColorImageError, CheckClearDepthStencilImageError},
|
||||
image::{
|
||||
BlitImageInfo, ClearColorImageInfo, ClearDepthStencilImageInfo, ImageBlit, ImageResolve,
|
||||
ResolveImageInfo,
|
||||
},
|
||||
pipeline::{
|
||||
CheckDescriptorSetsValidityError, CheckDispatchError, CheckDynamicStateValidityError,
|
||||
CheckIndexBufferError, CheckIndirectBufferError, CheckPipelineError,
|
||||
@ -89,19 +92,19 @@ pub use self::commands::{
|
||||
CheckResetQueryPoolError, CheckWriteTimestampError,
|
||||
},
|
||||
transfer::{
|
||||
CheckCopyBufferError, CheckCopyBufferImageError, CheckCopyImageError, CheckFillBufferError,
|
||||
CheckUpdateBufferError,
|
||||
BufferCopy, BufferImageCopy, CopyBufferInfo, CopyBufferInfoTyped, CopyBufferToImageInfo,
|
||||
CopyImageInfo, CopyImageToBufferInfo, FillBufferInfo, ImageCopy,
|
||||
},
|
||||
CopyError, CopyErrorResource,
|
||||
};
|
||||
pub use self::{
|
||||
auto::{
|
||||
AutoCommandBufferBuilder, AutoCommandBufferBuilderContextError, BeginError,
|
||||
BeginQueryError, BeginRenderPassError, BlitImageError, BuildError, ClearColorImageError,
|
||||
CopyBufferError, CopyBufferImageError, CopyImageError, CopyQueryPoolResultsError,
|
||||
BeginQueryError, BeginRenderPassError, BuildError, CopyQueryPoolResultsError,
|
||||
DispatchError, DispatchIndirectError, DrawError, DrawIndexedError,
|
||||
DrawIndexedIndirectError, DrawIndirectError, EndQueryError, ExecuteCommandsError,
|
||||
FillBufferError, PrimaryAutoCommandBuffer, ResetQueryPoolError, SecondaryAutoCommandBuffer,
|
||||
UpdateBufferError, WriteTimestampError,
|
||||
PrimaryAutoCommandBuffer, ResetQueryPoolError, SecondaryAutoCommandBuffer,
|
||||
WriteTimestampError,
|
||||
},
|
||||
traits::{
|
||||
CommandBufferExecError, CommandBufferExecFuture, PrimaryCommandBuffer,
|
||||
|
@ -508,31 +508,25 @@ impl std::fmt::Debug for dyn Command {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::SyncCommandBufferBuilder;
|
||||
use crate::buffer::BufferUsage;
|
||||
use crate::buffer::CpuAccessibleBuffer;
|
||||
use crate::buffer::ImmutableBuffer;
|
||||
use crate::command_buffer::pool::CommandPool;
|
||||
use crate::command_buffer::pool::CommandPoolBuilderAlloc;
|
||||
use crate::command_buffer::sys::CommandBufferBeginInfo;
|
||||
use crate::command_buffer::AutoCommandBufferBuilder;
|
||||
use crate::command_buffer::CommandBufferLevel;
|
||||
use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::descriptor_set::layout::DescriptorSetLayout;
|
||||
use crate::descriptor_set::layout::DescriptorSetLayoutBinding;
|
||||
use crate::descriptor_set::layout::DescriptorSetLayoutCreateInfo;
|
||||
use crate::descriptor_set::layout::DescriptorType;
|
||||
use crate::descriptor_set::PersistentDescriptorSet;
|
||||
use crate::descriptor_set::WriteDescriptorSet;
|
||||
use crate::device::Device;
|
||||
use crate::pipeline::layout::PipelineLayout;
|
||||
use crate::pipeline::layout::PipelineLayoutCreateInfo;
|
||||
use crate::pipeline::PipelineBindPoint;
|
||||
use crate::sampler::Sampler;
|
||||
use crate::sampler::SamplerCreateInfo;
|
||||
use crate::shader::ShaderStages;
|
||||
use crate::sync::GpuFuture;
|
||||
use std::sync::Arc;
|
||||
use super::*;
|
||||
use crate::{
|
||||
buffer::{BufferUsage, CpuAccessibleBuffer, ImmutableBuffer},
|
||||
command_buffer::{
|
||||
pool::{CommandPool, CommandPoolBuilderAlloc},
|
||||
sys::CommandBufferBeginInfo,
|
||||
AutoCommandBufferBuilder, CommandBufferLevel, CommandBufferUsage, FillBufferInfo,
|
||||
},
|
||||
descriptor_set::{
|
||||
layout::{
|
||||
DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo,
|
||||
DescriptorType,
|
||||
},
|
||||
PersistentDescriptorSet, WriteDescriptorSet,
|
||||
},
|
||||
pipeline::{layout::PipelineLayoutCreateInfo, PipelineBindPoint, PipelineLayout},
|
||||
sampler::{Sampler, SamplerCreateInfo},
|
||||
shader::ShaderStages,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn basic_creation() {
|
||||
@ -563,12 +557,9 @@ mod tests {
|
||||
let (device, queue) = gfx_dev_and_queue!();
|
||||
|
||||
// Create a tiny test buffer
|
||||
let (buf, future) = ImmutableBuffer::from_data(
|
||||
0u32,
|
||||
BufferUsage::transfer_destination(),
|
||||
queue.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
let (buf, future) =
|
||||
ImmutableBuffer::from_data(0u32, BufferUsage::transfer_dst(), queue.clone())
|
||||
.unwrap();
|
||||
future
|
||||
.then_signal_fence_and_flush()
|
||||
.unwrap()
|
||||
@ -584,7 +575,12 @@ mod tests {
|
||||
CommandBufferUsage::SimultaneousUse,
|
||||
)
|
||||
.unwrap();
|
||||
builder.fill_buffer(buf.clone(), 42u32).unwrap();
|
||||
builder
|
||||
.fill_buffer(FillBufferInfo {
|
||||
data: 42u32,
|
||||
..FillBufferInfo::dst_buffer(buf.clone())
|
||||
})
|
||||
.unwrap();
|
||||
Arc::new(builder.build().unwrap())
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -8,14 +8,8 @@
|
||||
// according to those terms.
|
||||
|
||||
pub use super::commands::{
|
||||
bind_push::UnsafeCommandBufferBuilderBindVertexBuffer,
|
||||
image::{
|
||||
UnsafeCommandBufferBuilderColorImageClear,
|
||||
UnsafeCommandBufferBuilderDepthStencilImageClear, UnsafeCommandBufferBuilderImageBlit,
|
||||
},
|
||||
render_pass::RenderPassBeginInfo,
|
||||
bind_push::UnsafeCommandBufferBuilderBindVertexBuffer, render_pass::RenderPassBeginInfo,
|
||||
secondary::UnsafeCommandBufferBuilderExecuteCommands,
|
||||
transfer::{UnsafeCommandBufferBuilderBufferImageCopy, UnsafeCommandBufferBuilderImageCopy},
|
||||
};
|
||||
use super::{
|
||||
pool::UnsafeCommandPoolAlloc, CommandBufferInheritanceInfo, CommandBufferLevel,
|
||||
|
@ -95,7 +95,7 @@
|
||||
use crate::{
|
||||
device::physical::PhysicalDevice, image::ImageAspects, shader::spirv::ImageFormat, DeviceSize,
|
||||
};
|
||||
use std::{ops::BitOr, vec::IntoIter as VecIntoIter};
|
||||
use std::ops::BitOr;
|
||||
|
||||
// Generated by build.rs
|
||||
include!(concat!(env!("OUT_DIR"), "/formats.rs"));
|
||||
@ -283,6 +283,25 @@ pub enum ChromaSampling {
|
||||
Mode420,
|
||||
}
|
||||
|
||||
impl ChromaSampling {
|
||||
pub fn subsampled_extent(&self, mut extent: [u32; 3]) -> [u32; 3] {
|
||||
match self {
|
||||
ChromaSampling::Mode444 => (),
|
||||
ChromaSampling::Mode422 => {
|
||||
debug_assert!(extent[0] % 2 == 0);
|
||||
extent[0] /= 2;
|
||||
}
|
||||
ChromaSampling::Mode420 => {
|
||||
debug_assert!(extent[0] % 2 == 0 && extent[1] % 2 == 0);
|
||||
extent[0] /= 2;
|
||||
extent[1] /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
extent
|
||||
}
|
||||
}
|
||||
|
||||
/// The numeric type that represents data of a format in memory.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum NumericType {
|
||||
@ -421,152 +440,259 @@ pub enum ClearValue {
|
||||
DepthStencil((f32, u32)),
|
||||
}
|
||||
|
||||
// TODO: remove all these From implementations once they are no longer needed
|
||||
|
||||
impl From<[f32; 1]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [f32; 1]) -> ClearValue {
|
||||
ClearValue::Float([val[0], 0.0, 0.0, 1.0])
|
||||
fn from(val: [f32; 1]) -> Self {
|
||||
Self::Float([val[0], 0.0, 0.0, 1.0])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 2]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [f32; 2]) -> ClearValue {
|
||||
ClearValue::Float([val[0], val[1], 0.0, 1.0])
|
||||
fn from(val: [f32; 2]) -> Self {
|
||||
Self::Float([val[0], val[1], 0.0, 1.0])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 3]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [f32; 3]) -> ClearValue {
|
||||
ClearValue::Float([val[0], val[1], val[2], 1.0])
|
||||
fn from(val: [f32; 3]) -> Self {
|
||||
Self::Float([val[0], val[1], val[2], 1.0])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 4]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [f32; 4]) -> ClearValue {
|
||||
ClearValue::Float(val)
|
||||
fn from(val: [f32; 4]) -> Self {
|
||||
Self::Float(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u32; 1]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [u32; 1]) -> ClearValue {
|
||||
ClearValue::Uint([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct?
|
||||
fn from(val: [u32; 1]) -> Self {
|
||||
Self::Uint([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct?
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u32; 2]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [u32; 2]) -> ClearValue {
|
||||
ClearValue::Uint([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct?
|
||||
fn from(val: [u32; 2]) -> Self {
|
||||
Self::Uint([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct?
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u32; 3]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [u32; 3]) -> ClearValue {
|
||||
ClearValue::Uint([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct?
|
||||
fn from(val: [u32; 3]) -> Self {
|
||||
Self::Uint([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct?
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u32; 4]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [u32; 4]) -> ClearValue {
|
||||
ClearValue::Uint(val)
|
||||
fn from(val: [u32; 4]) -> Self {
|
||||
Self::Uint(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[i32; 1]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [i32; 1]) -> ClearValue {
|
||||
ClearValue::Int([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct?
|
||||
fn from(val: [i32; 1]) -> Self {
|
||||
Self::Int([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct?
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[i32; 2]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [i32; 2]) -> ClearValue {
|
||||
ClearValue::Int([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct?
|
||||
fn from(val: [i32; 2]) -> Self {
|
||||
Self::Int([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct?
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[i32; 3]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [i32; 3]) -> ClearValue {
|
||||
ClearValue::Int([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct?
|
||||
fn from(val: [i32; 3]) -> Self {
|
||||
Self::Int([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct?
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[i32; 4]> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: [i32; 4]) -> ClearValue {
|
||||
ClearValue::Int(val)
|
||||
fn from(val: [i32; 4]) -> Self {
|
||||
Self::Int(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: f32) -> ClearValue {
|
||||
ClearValue::Depth(val)
|
||||
fn from(val: f32) -> Self {
|
||||
Self::Depth(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: u32) -> ClearValue {
|
||||
ClearValue::Stencil(val)
|
||||
fn from(val: u32) -> Self {
|
||||
Self::Stencil(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, u32)> for ClearValue {
|
||||
#[inline]
|
||||
fn from(val: (f32, u32)) -> ClearValue {
|
||||
ClearValue::DepthStencil(val)
|
||||
fn from(val: (f32, u32)) -> Self {
|
||||
Self::DepthStencil(val)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove once no longer needed
|
||||
pub unsafe trait ClearValuesTuple {
|
||||
type Iter: Iterator<Item = ClearValue>;
|
||||
fn iter(self) -> Self::Iter;
|
||||
/// A value that will be used to clear a color image.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum ClearColorValue {
|
||||
/// Value for formats with a numeric type that is not `SINT` or `UINT`.
|
||||
Float([f32; 4]),
|
||||
/// Value for formats with a numeric type of `SINT`.
|
||||
Int([i32; 4]),
|
||||
/// Value for formats with a numeric type of `UINT`.
|
||||
Uint([u32; 4]),
|
||||
}
|
||||
|
||||
macro_rules! impl_clear_values_tuple {
|
||||
($first:ident $($others:ident)+) => (
|
||||
#[allow(non_snake_case)]
|
||||
unsafe impl<$first $(, $others)*> ClearValuesTuple for ($first, $($others,)+)
|
||||
where $first: Into<ClearValue> $(, $others: Into<ClearValue>)*
|
||||
{
|
||||
type Iter = VecIntoIter<ClearValue>;
|
||||
#[inline]
|
||||
fn iter(self) -> VecIntoIter<ClearValue> {
|
||||
let ($first, $($others,)+) = self;
|
||||
vec![
|
||||
$first.into() $(, $others.into())+
|
||||
].into_iter()
|
||||
}
|
||||
impl From<ClearColorValue> for ash::vk::ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: ClearColorValue) -> Self {
|
||||
match val {
|
||||
ClearColorValue::Float(float32) => Self { float32 },
|
||||
ClearColorValue::Int(int32) => Self { int32 },
|
||||
ClearColorValue::Uint(uint32) => Self { uint32 },
|
||||
}
|
||||
|
||||
impl_clear_values_tuple!($($others)*);
|
||||
);
|
||||
|
||||
($first:ident) => (
|
||||
unsafe impl<$first> ClearValuesTuple for ($first,)
|
||||
where $first: Into<ClearValue>
|
||||
{
|
||||
type Iter = VecIntoIter<ClearValue>;
|
||||
#[inline]
|
||||
fn iter(self) -> VecIntoIter<ClearValue> {
|
||||
vec![self.0.into()].into_iter()
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl_clear_values_tuple!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z);
|
||||
impl From<[f32; 1]> for ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: [f32; 1]) -> Self {
|
||||
Self::Float([val[0], 0.0, 0.0, 1.0])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 2]> for ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: [f32; 2]) -> Self {
|
||||
Self::Float([val[0], val[1], 0.0, 1.0])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 3]> for ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: [f32; 3]) -> Self {
|
||||
Self::Float([val[0], val[1], val[2], 1.0])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 4]> for ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: [f32; 4]) -> Self {
|
||||
Self::Float(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[i32; 1]> for ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: [i32; 1]) -> Self {
|
||||
Self::Int([val[0], 0, 0, 1])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[i32; 2]> for ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: [i32; 2]) -> Self {
|
||||
Self::Int([val[0], val[1], 0, 1])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[i32; 3]> for ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: [i32; 3]) -> Self {
|
||||
Self::Int([val[0], val[1], val[2], 1])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[i32; 4]> for ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: [i32; 4]) -> Self {
|
||||
Self::Int(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u32; 1]> for ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: [u32; 1]) -> Self {
|
||||
Self::Uint([val[0], 0, 0, 1])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u32; 2]> for ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: [u32; 2]) -> Self {
|
||||
Self::Uint([val[0], val[1], 0, 1])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u32; 3]> for ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: [u32; 3]) -> Self {
|
||||
Self::Uint([val[0], val[1], val[2], 1])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u32; 4]> for ClearColorValue {
|
||||
#[inline]
|
||||
fn from(val: [u32; 4]) -> Self {
|
||||
Self::Uint(val)
|
||||
}
|
||||
}
|
||||
|
||||
/// A value that will be used to clear a depth/stencil image.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||
pub struct ClearDepthStencilValue {
|
||||
/// Value for the depth component.
|
||||
pub depth: f32,
|
||||
/// Value for the stencil component.
|
||||
pub stencil: u32,
|
||||
}
|
||||
|
||||
impl From<ClearDepthStencilValue> for ash::vk::ClearDepthStencilValue {
|
||||
#[inline]
|
||||
fn from(val: ClearDepthStencilValue) -> Self {
|
||||
Self {
|
||||
depth: val.depth,
|
||||
stencil: val.stencil,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for ClearDepthStencilValue {
|
||||
#[inline]
|
||||
fn from(depth: f32) -> Self {
|
||||
Self { depth, stencil: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for ClearDepthStencilValue {
|
||||
#[inline]
|
||||
fn from(stencil: u32) -> Self {
|
||||
Self {
|
||||
depth: 0.0,
|
||||
stencil,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(f32, u32)> for ClearDepthStencilValue {
|
||||
#[inline]
|
||||
fn from((depth, stencil): (f32, u32)) -> Self {
|
||||
Self { depth, stencil }
|
||||
}
|
||||
}
|
||||
|
||||
/// The properties of a format that are supported by a physical device.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
|
||||
|
@ -14,7 +14,7 @@ use super::{
|
||||
SampleCount,
|
||||
};
|
||||
use crate::{
|
||||
device::Device,
|
||||
device::{Device, DeviceOwned},
|
||||
format::{ClearValue, Format},
|
||||
image::{sys::UnsafeImageCreateInfo, ImageDimensions},
|
||||
memory::{
|
||||
@ -561,7 +561,7 @@ where
|
||||
ImageInner {
|
||||
image: &self.image,
|
||||
first_layer: 0,
|
||||
num_layers: self.image.dimensions().array_layers() as usize,
|
||||
num_layers: self.image.dimensions().array_layers(),
|
||||
first_mipmap_level: 0,
|
||||
num_mipmap_levels: 1,
|
||||
}
|
||||
@ -587,11 +587,6 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> u64 {
|
||||
self.image.key()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn layout_initialized(&self) {
|
||||
self.initialized.store(true, Ordering::SeqCst);
|
||||
@ -613,6 +608,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> DeviceOwned for AttachmentImage<A> {
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.image.device()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> ImageClearValue<ClearValue> for AttachmentImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
|
@ -9,15 +9,16 @@
|
||||
|
||||
use super::{
|
||||
sys::UnsafeImage, traits::ImageContent, ImageAccess, ImageCreateFlags, ImageCreationError,
|
||||
ImageDescriptorLayouts, ImageDimensions, ImageInner, ImageLayout, ImageUsage, MipmapsCount,
|
||||
ImageDescriptorLayouts, ImageDimensions, ImageInner, ImageLayout, ImageSubresourceLayers,
|
||||
ImageUsage, MipmapsCount,
|
||||
};
|
||||
use crate::{
|
||||
buffer::{BufferAccess, BufferContents, BufferUsage, CpuAccessibleBuffer},
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferExecFuture, CommandBufferUsage,
|
||||
PrimaryAutoCommandBuffer, PrimaryCommandBuffer,
|
||||
AutoCommandBufferBuilder, BlitImageInfo, CommandBufferExecFuture, CommandBufferUsage,
|
||||
CopyBufferToImageInfo, ImageBlit, PrimaryAutoCommandBuffer, PrimaryCommandBuffer,
|
||||
},
|
||||
device::{physical::QueueFamily, Device, Queue},
|
||||
device::{physical::QueueFamily, Device, DeviceOwned, Queue},
|
||||
format::Format,
|
||||
image::sys::UnsafeImageCreateInfo,
|
||||
memory::{
|
||||
@ -49,53 +50,6 @@ pub struct ImmutableImage<A = PotentialDedicatedAllocation<StdMemoryPoolAlloc>>
|
||||
layout: ImageLayout,
|
||||
}
|
||||
|
||||
/// Image whose purpose is to access only a part of one image, for any kind of access
|
||||
/// We define a part of one image here by a level of mipmap, or a layer of an array
|
||||
/// The image attribute must be an implementation of ImageAccess
|
||||
/// The mip_levels_access must be a range showing which mipmaps will be accessed
|
||||
/// The array_layers_access must be a range showing which layers will be accessed
|
||||
/// The layout must be the layout of the image at the beginning and at the end of the command buffer
|
||||
pub struct SubImage {
|
||||
image: Arc<dyn ImageAccess>,
|
||||
mip_levels_access: Range<u32>,
|
||||
array_layers_access: Range<u32>,
|
||||
layout: ImageLayout,
|
||||
}
|
||||
|
||||
impl SubImage {
|
||||
pub fn new(
|
||||
image: Arc<dyn ImageAccess>,
|
||||
mip_level: u32,
|
||||
mip_level_count: u32,
|
||||
layer_level: u32,
|
||||
layer_level_count: u32,
|
||||
layout: ImageLayout,
|
||||
) -> Arc<SubImage> {
|
||||
debug_assert!(mip_level + mip_level_count <= image.mip_levels());
|
||||
debug_assert!(layer_level + layer_level_count <= image.dimensions().array_layers());
|
||||
|
||||
let last_level = mip_level + mip_level_count;
|
||||
let mip_levels_access = mip_level..last_level;
|
||||
|
||||
let last_level = layer_level + layer_level_count;
|
||||
let array_layers_access = layer_level..last_level;
|
||||
|
||||
Arc::new(SubImage {
|
||||
image,
|
||||
mip_levels_access,
|
||||
array_layers_access,
|
||||
layout,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Must not implement Clone, as that would lead to multiple `used` values.
|
||||
pub struct ImmutableImageInitialization<A = PotentialDedicatedAllocation<StdMemoryPoolAlloc>> {
|
||||
image: Arc<ImmutableImage<A>>,
|
||||
mip_levels_access: Range<u32>,
|
||||
array_layers_access: Range<u32>,
|
||||
}
|
||||
|
||||
fn has_mipmaps(mipmaps: MipmapsCount) -> bool {
|
||||
match mipmaps {
|
||||
MipmapsCount::One => false,
|
||||
@ -111,36 +65,34 @@ fn generate_mipmaps<L>(
|
||||
layout: ImageLayout,
|
||||
) {
|
||||
for level in 1..image.mip_levels() {
|
||||
for layer in 0..image.dimensions().array_layers() {
|
||||
let [xs, ys, ds] = dimensions
|
||||
.mip_level_dimensions(level - 1)
|
||||
.unwrap()
|
||||
.width_height_depth();
|
||||
let [xd, yd, dd] = dimensions
|
||||
.mip_level_dimensions(level)
|
||||
.unwrap()
|
||||
.width_height_depth();
|
||||
let src_size = dimensions
|
||||
.mip_level_dimensions(level - 1)
|
||||
.unwrap()
|
||||
.width_height_depth();
|
||||
let dst_size = dimensions
|
||||
.mip_level_dimensions(level)
|
||||
.unwrap()
|
||||
.width_height_depth();
|
||||
|
||||
let src = SubImage::new(image.clone(), level - 1, 1, layer, 1, layout);
|
||||
|
||||
let dst = SubImage::new(image.clone(), level, 1, layer, 1, layout);
|
||||
|
||||
cbb.blit_image(
|
||||
src, //source
|
||||
[0, 0, 0], //source_top_left
|
||||
[xs as i32, ys as i32, ds as i32], //source_bottom_right
|
||||
layer, //source_base_array_layer
|
||||
level - 1, //source_mip_level
|
||||
dst, //destination
|
||||
[0, 0, 0], //destination_top_left
|
||||
[xd as i32, yd as i32, dd as i32], //destination_bottom_right
|
||||
layer, //destination_base_array_layer
|
||||
level, //destination_mip_level
|
||||
1, //layer_count
|
||||
Filter::Linear, //filter
|
||||
)
|
||||
.expect("failed to blit a mip map to image!");
|
||||
}
|
||||
cbb.blit_image(BlitImageInfo {
|
||||
regions: [ImageBlit {
|
||||
src_subresource: ImageSubresourceLayers {
|
||||
mip_level: level - 1,
|
||||
..image.subresource_layers()
|
||||
},
|
||||
src_offsets: [[0; 3], src_size],
|
||||
dst_subresource: ImageSubresourceLayers {
|
||||
mip_level: level,
|
||||
..image.subresource_layers()
|
||||
},
|
||||
dst_offsets: [[0; 3], dst_size],
|
||||
..Default::default()
|
||||
}]
|
||||
.into(),
|
||||
filter: Filter::Linear,
|
||||
..BlitImageInfo::images(image.clone(), image.clone())
|
||||
})
|
||||
.expect("failed to blit a mip map to image!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,8 +132,8 @@ impl ImmutableImage {
|
||||
M: Into<MipmapsCount>,
|
||||
{
|
||||
let usage = ImageUsage {
|
||||
transfer_source: true, // for blits
|
||||
transfer_destination: true,
|
||||
transfer_src: true, // for blits
|
||||
transfer_dst: true,
|
||||
sampled: true,
|
||||
..ImageUsage::none()
|
||||
};
|
||||
@ -306,7 +258,7 @@ impl ImmutableImage {
|
||||
{
|
||||
let source = CpuAccessibleBuffer::from_iter(
|
||||
queue.device().clone(),
|
||||
BufferUsage::transfer_source(),
|
||||
BufferUsage::transfer_src(),
|
||||
false,
|
||||
iter,
|
||||
)?;
|
||||
@ -329,8 +281,8 @@ impl ImmutableImage {
|
||||
> {
|
||||
let need_to_generate_mipmaps = has_mipmaps(mip_levels);
|
||||
let usage = ImageUsage {
|
||||
transfer_destination: true,
|
||||
transfer_source: need_to_generate_mipmaps,
|
||||
transfer_dst: true,
|
||||
transfer_src: need_to_generate_mipmaps,
|
||||
sampled: true,
|
||||
..ImageUsage::none()
|
||||
};
|
||||
@ -348,23 +300,13 @@ impl ImmutableImage {
|
||||
source.device().active_queue_families(),
|
||||
)?;
|
||||
|
||||
let init = SubImage::new(initializer, 0, 1, 0, 1, ImageLayout::ShaderReadOnlyOptimal);
|
||||
|
||||
let mut cbb = AutoCommandBufferBuilder::primary(
|
||||
source.device().clone(),
|
||||
queue.family(),
|
||||
CommandBufferUsage::MultipleSubmit,
|
||||
)?;
|
||||
cbb.copy_buffer_to_image_dimensions(
|
||||
source,
|
||||
init,
|
||||
[0, 0, 0],
|
||||
dimensions.width_height_depth(),
|
||||
0,
|
||||
dimensions.array_layers(),
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
cbb.copy_buffer_to_image(CopyBufferToImageInfo::buffer_image(source, initializer))
|
||||
.unwrap();
|
||||
|
||||
if need_to_generate_mipmaps {
|
||||
generate_mipmaps(
|
||||
@ -386,6 +328,12 @@ impl ImmutableImage {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> DeviceOwned for ImmutableImage<A> {
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.image.device()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> ImageAccess for ImmutableImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
@ -395,9 +343,9 @@ where
|
||||
ImageInner {
|
||||
image: &self.image,
|
||||
first_layer: 0,
|
||||
num_layers: self.image.dimensions().array_layers() as usize,
|
||||
num_layers: self.image.dimensions().array_layers(),
|
||||
first_mipmap_level: 0,
|
||||
num_mipmap_levels: self.image.mip_levels() as usize,
|
||||
num_mipmap_levels: self.image.mip_levels(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,11 +374,6 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> u64 {
|
||||
self.image.key()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn current_mip_levels_access(&self) -> Range<u32> {
|
||||
0..self.mip_levels()
|
||||
@ -452,41 +395,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl ImageAccess for SubImage {
|
||||
#[inline]
|
||||
fn inner(&self) -> ImageInner {
|
||||
self.image.inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initial_layout_requirement(&self) -> ImageLayout {
|
||||
self.image.initial_layout_requirement()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn final_layout_requirement(&self) -> ImageLayout {
|
||||
self.image.final_layout_requirement()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
|
||||
None
|
||||
}
|
||||
|
||||
fn current_mip_levels_access(&self) -> Range<u32> {
|
||||
self.mip_levels_access.clone()
|
||||
}
|
||||
|
||||
fn current_array_layers_access(&self) -> Range<u32> {
|
||||
self.array_layers_access.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> u64 {
|
||||
self.image.conflict_key()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> PartialEq for ImmutableImage<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
@ -509,6 +417,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// Must not implement Clone, as that would lead to multiple `used` values.
|
||||
pub struct ImmutableImageInitialization<A = PotentialDedicatedAllocation<StdMemoryPoolAlloc>> {
|
||||
image: Arc<ImmutableImage<A>>,
|
||||
mip_levels_access: Range<u32>,
|
||||
array_layers_access: Range<u32>,
|
||||
}
|
||||
|
||||
unsafe impl<A> DeviceOwned for ImmutableImageInitialization<A> {
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.image.device()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> ImageAccess for ImmutableImageInitialization<A>
|
||||
where
|
||||
A: MemoryPoolAlloc,
|
||||
@ -533,11 +454,6 @@ where
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> u64 {
|
||||
self.image.image.key()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn current_mip_levels_access(&self) -> Range<u32> {
|
||||
self.mip_levels_access.clone()
|
||||
|
@ -555,6 +555,36 @@ impl ImageDimensions {
|
||||
}
|
||||
}
|
||||
|
||||
/// One or more subresources of an image, spanning a single mip level, that should be accessed by a
|
||||
/// command.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ImageSubresourceLayers {
|
||||
/// Selects the aspects that will be included.
|
||||
///
|
||||
/// The value must not be empty, and must not include any of the `memory_plane` aspects.
|
||||
/// The `color` aspect cannot be selected together any of with the `plane` aspects.
|
||||
pub aspects: ImageAspects,
|
||||
|
||||
/// Selects mip level that will be included.
|
||||
pub mip_level: u32,
|
||||
|
||||
/// Selects the range of array layers that will be included.
|
||||
///
|
||||
/// The range must not be empty.
|
||||
pub array_layers: Range<u32>,
|
||||
}
|
||||
|
||||
impl From<ImageSubresourceLayers> for ash::vk::ImageSubresourceLayers {
|
||||
fn from(val: ImageSubresourceLayers) -> Self {
|
||||
Self {
|
||||
aspect_mask: val.aspects.into(),
|
||||
mip_level: val.mip_level,
|
||||
base_array_layer: val.array_layers.start,
|
||||
layer_count: val.array_layers.end - val.array_layers.start,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// One or more subresources of an image that should be accessed by a command.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ImageSubresourceRange {
|
||||
@ -576,6 +606,7 @@ pub struct ImageSubresourceRange {
|
||||
}
|
||||
|
||||
impl From<ImageSubresourceRange> for ash::vk::ImageSubresourceRange {
|
||||
#[inline]
|
||||
fn from(val: ImageSubresourceRange) -> Self {
|
||||
Self {
|
||||
aspect_mask: val.aspects.into(),
|
||||
@ -587,6 +618,17 @@ impl From<ImageSubresourceRange> for ash::vk::ImageSubresourceRange {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ImageSubresourceLayers> for ImageSubresourceRange {
|
||||
#[inline]
|
||||
fn from(val: ImageSubresourceLayers) -> Self {
|
||||
Self {
|
||||
aspects: val.aspects,
|
||||
mip_levels: val.mip_level..val.mip_level + 1,
|
||||
array_layers: val.array_layers,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The image configuration to query in
|
||||
/// [`PhysicalDevice::image_format_properties`](crate::device::physical::PhysicalDevice::image_format_properties).
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -14,7 +14,7 @@ use super::{
|
||||
ImageInner, ImageLayout, ImageUsage,
|
||||
};
|
||||
use crate::{
|
||||
device::{physical::QueueFamily, Device},
|
||||
device::{physical::QueueFamily, Device, DeviceOwned},
|
||||
format::{ClearValue, Format},
|
||||
image::sys::UnsafeImageCreateInfo,
|
||||
memory::{
|
||||
@ -79,8 +79,8 @@ impl StorageImage {
|
||||
}
|
||||
|
||||
let usage = ImageUsage {
|
||||
transfer_source: true,
|
||||
transfer_destination: true,
|
||||
transfer_src: true,
|
||||
transfer_dst: true,
|
||||
sampled: true,
|
||||
storage: true,
|
||||
color_attachment: !is_depth,
|
||||
@ -240,6 +240,15 @@ impl StorageImage {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> DeviceOwned for StorageImage<A>
|
||||
where
|
||||
A: MemoryPool,
|
||||
{
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.image.device()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A> ImageAccess for StorageImage<A>
|
||||
where
|
||||
A: MemoryPool,
|
||||
@ -249,7 +258,7 @@ where
|
||||
ImageInner {
|
||||
image: &self.image,
|
||||
first_layer: 0,
|
||||
num_layers: self.dimensions.array_layers() as usize,
|
||||
num_layers: self.dimensions.array_layers(),
|
||||
first_mipmap_level: 0,
|
||||
num_mipmap_levels: 1,
|
||||
}
|
||||
@ -275,11 +284,6 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> u64 {
|
||||
self.image.key()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn current_mip_levels_access(&self) -> Range<u32> {
|
||||
0..self.mip_levels()
|
||||
|
@ -11,7 +11,12 @@ use super::{
|
||||
traits::{ImageClearValue, ImageContent},
|
||||
ImageAccess, ImageDescriptorLayouts, ImageInner, ImageLayout,
|
||||
};
|
||||
use crate::{format::ClearValue, swapchain::Swapchain, OomError};
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
format::ClearValue,
|
||||
swapchain::Swapchain,
|
||||
OomError,
|
||||
};
|
||||
use std::{
|
||||
hash::{Hash, Hasher},
|
||||
ops::Range,
|
||||
@ -76,6 +81,12 @@ impl<W> SwapchainImage<W> {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<W> DeviceOwned for SwapchainImage<W> {
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.swapchain.device()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<W> ImageAccess for SwapchainImage<W>
|
||||
where
|
||||
W: Send + Sync,
|
||||
@ -105,11 +116,6 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> u64 {
|
||||
self.my_image().image.key()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn layout_initialized(&self) {
|
||||
self.layout_initialized();
|
||||
|
@ -14,8 +14,9 @@
|
||||
//! that you create must wrap around the types in this module.
|
||||
|
||||
use super::{
|
||||
ImageAspect, ImageCreateFlags, ImageDimensions, ImageLayout, ImageSubresourceRange,
|
||||
ImageTiling, ImageUsage, SampleCount, SampleCounts,
|
||||
ImageAspect, ImageAspects, ImageCreateFlags, ImageDimensions, ImageLayout,
|
||||
ImageSubresourceLayers, ImageSubresourceRange, ImageTiling, ImageUsage, SampleCount,
|
||||
SampleCounts,
|
||||
};
|
||||
use crate::{
|
||||
buffer::cpu_access::{ReadLockError, WriteLockError},
|
||||
@ -397,14 +398,14 @@ impl UnsafeImage {
|
||||
|
||||
// These flags only exist in later versions, ignore them otherwise
|
||||
if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 {
|
||||
if usage.transfer_source && !format_features.transfer_src {
|
||||
if usage.transfer_src && !format_features.transfer_src {
|
||||
return Err(ImageCreationError::FormatUsageNotSupported {
|
||||
usage: "transfer_source",
|
||||
usage: "transfer_src",
|
||||
});
|
||||
}
|
||||
if usage.transfer_destination && !format_features.transfer_dst {
|
||||
if usage.transfer_dst && !format_features.transfer_dst {
|
||||
return Err(ImageCreationError::FormatUsageNotSupported {
|
||||
usage: "transfer_destination",
|
||||
usage: "transfer_dst",
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -632,8 +633,8 @@ impl UnsafeImage {
|
||||
// VUID-VkImageCreateInfo-samples-02257 already states that multisampling+linear
|
||||
// is invalid so no need to check for that here.
|
||||
&& ImageUsage {
|
||||
transfer_source: false,
|
||||
transfer_destination: false,
|
||||
transfer_src: false,
|
||||
transfer_dst: false,
|
||||
..usage.clone()
|
||||
} == ImageUsage::none())
|
||||
} else {
|
||||
@ -1167,6 +1168,44 @@ impl UnsafeImage {
|
||||
self.block_texel_view_compatible
|
||||
}
|
||||
|
||||
/// Returns an `ImageSubresourceLayers` covering the first mip level of the image. All aspects
|
||||
/// of the image are selected, or `plane0` if the image is multi-planar.
|
||||
#[inline]
|
||||
pub fn subresource_layers(&self) -> ImageSubresourceLayers {
|
||||
ImageSubresourceLayers {
|
||||
aspects: {
|
||||
let aspects = self.format.unwrap().aspects();
|
||||
|
||||
if aspects.plane0 {
|
||||
ImageAspects {
|
||||
plane0: true,
|
||||
..ImageAspects::none()
|
||||
}
|
||||
} else {
|
||||
aspects
|
||||
}
|
||||
},
|
||||
mip_level: 0,
|
||||
array_layers: 0..self.dimensions.array_layers(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an `ImageSubresourceRange` covering the whole image. If the image is multi-planar,
|
||||
/// only the `color` aspect is selected.
|
||||
#[inline]
|
||||
pub fn subresource_range(&self) -> ImageSubresourceRange {
|
||||
ImageSubresourceRange {
|
||||
aspects: ImageAspects {
|
||||
plane0: false,
|
||||
plane1: false,
|
||||
plane2: false,
|
||||
..self.format.unwrap().aspects()
|
||||
},
|
||||
mip_levels: 0..self.mip_levels,
|
||||
array_layers: 0..self.dimensions.array_layers(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a key unique to each `UnsafeImage`. Can be used for the `conflicts_key` method.
|
||||
#[inline]
|
||||
pub fn key(&self) -> u64 {
|
||||
|
@ -7,28 +7,46 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use super::{sys::UnsafeImage, ImageDescriptorLayouts, ImageDimensions, ImageLayout, SampleCount};
|
||||
use super::{
|
||||
sys::UnsafeImage, ImageDescriptorLayouts, ImageDimensions, ImageLayout, ImageSubresourceLayers,
|
||||
ImageSubresourceRange, ImageUsage, SampleCount,
|
||||
};
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
format::{ClearValue, Format, FormatFeatures},
|
||||
SafeDeref,
|
||||
};
|
||||
use std::{
|
||||
fmt,
|
||||
hash::{Hash, Hasher},
|
||||
ops::Range,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
/// Trait for types that represent the way a GPU can access an image.
|
||||
pub unsafe trait ImageAccess: Send + Sync {
|
||||
pub unsafe trait ImageAccess: DeviceOwned + Send + Sync {
|
||||
/// Returns the inner unsafe image object used by this image.
|
||||
fn inner(&self) -> ImageInner;
|
||||
|
||||
/// Returns the dimensions of the image.
|
||||
#[inline]
|
||||
fn dimensions(&self) -> ImageDimensions {
|
||||
// TODO: not necessarily correct because of the new inner() design?
|
||||
self.inner().image.dimensions()
|
||||
}
|
||||
|
||||
/// Returns the format of this image.
|
||||
#[inline]
|
||||
fn format(&self) -> Format {
|
||||
self.inner().image.format().unwrap()
|
||||
}
|
||||
|
||||
/// Returns the features supported by the image's format.
|
||||
#[inline]
|
||||
fn format_features(&self) -> &FormatFeatures {
|
||||
self.inner().image.format_features()
|
||||
}
|
||||
|
||||
/// Returns the number of mipmap levels of this image.
|
||||
#[inline]
|
||||
fn mip_levels(&self) -> u32 {
|
||||
@ -42,17 +60,24 @@ pub unsafe trait ImageAccess: Send + Sync {
|
||||
self.inner().image.samples()
|
||||
}
|
||||
|
||||
/// Returns the dimensions of the image.
|
||||
/// Returns the usage the image was created with.
|
||||
#[inline]
|
||||
fn dimensions(&self) -> ImageDimensions {
|
||||
// TODO: not necessarily correct because of the new inner() design?
|
||||
self.inner().image.dimensions()
|
||||
fn usage(&self) -> &ImageUsage {
|
||||
self.inner().image.usage()
|
||||
}
|
||||
|
||||
/// Returns the features supported by the image's format.
|
||||
/// Returns an `ImageSubresourceLayers` covering the first mip level of the image. All aspects
|
||||
/// of the image are selected, or `plane0` if the image is multi-planar.
|
||||
#[inline]
|
||||
fn format_features(&self) -> &FormatFeatures {
|
||||
self.inner().image.format_features()
|
||||
fn subresource_layers(&self) -> ImageSubresourceLayers {
|
||||
self.inner().image.subresource_layers()
|
||||
}
|
||||
|
||||
/// Returns an `ImageSubresourceRange` covering the whole image. If the image is multi-planar,
|
||||
/// only the `color` aspect is selected.
|
||||
#[inline]
|
||||
fn subresource_range(&self) -> ImageSubresourceRange {
|
||||
self.inner().image.subresource_range()
|
||||
}
|
||||
|
||||
/// When images are created their memory layout is initially `Undefined` or `Preinitialized`.
|
||||
@ -120,18 +145,6 @@ pub unsafe trait ImageAccess: Send + Sync {
|
||||
/// This must return `Some` if the image is to be used to create an image view.
|
||||
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts>;
|
||||
|
||||
/// Returns a key that uniquely identifies the memory content of the image.
|
||||
/// Two ranges that potentially overlap in memory must return the same key.
|
||||
///
|
||||
/// The key is shared amongst all buffers and images, which means that you can make several
|
||||
/// different image objects share the same memory, or make some image objects share memory
|
||||
/// with buffers, as long as they return the same key.
|
||||
///
|
||||
/// Since it is possible to accidentally return the same key for memory ranges that don't
|
||||
/// overlap, the `conflicts_image` or `conflicts_buffer` function should always be called to
|
||||
/// verify whether they actually overlap.
|
||||
fn conflict_key(&self) -> u64;
|
||||
|
||||
/// Returns the current mip level that is accessed by the gpu
|
||||
fn current_mip_levels_access(&self) -> Range<u32>;
|
||||
|
||||
@ -146,16 +159,24 @@ pub struct ImageInner<'a> {
|
||||
pub image: &'a Arc<UnsafeImage>,
|
||||
|
||||
/// The first layer of `image` to consider.
|
||||
pub first_layer: usize,
|
||||
pub first_layer: u32,
|
||||
|
||||
/// The number of layers of `image` to consider.
|
||||
pub num_layers: usize,
|
||||
pub num_layers: u32,
|
||||
|
||||
/// The first mipmap level of `image` to consider.
|
||||
pub first_mipmap_level: usize,
|
||||
pub first_mipmap_level: u32,
|
||||
|
||||
/// The number of mipmap levels of `image` to consider.
|
||||
pub num_mipmap_levels: usize,
|
||||
pub num_mipmap_levels: u32,
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn ImageAccess {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("dyn ImageAccess")
|
||||
.field("inner", &self.inner())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for dyn ImageAccess {
|
||||
@ -182,6 +203,15 @@ pub struct ImageAccessFromUndefinedLayout<I> {
|
||||
preinitialized: bool,
|
||||
}
|
||||
|
||||
unsafe impl<I> DeviceOwned for ImageAccessFromUndefinedLayout<I>
|
||||
where
|
||||
I: ImageAccess,
|
||||
{
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.image.device()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<I> ImageAccess for ImageAccessFromUndefinedLayout<I>
|
||||
where
|
||||
I: ImageAccess,
|
||||
@ -210,11 +240,6 @@ where
|
||||
self.image.descriptor_layouts()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> u64 {
|
||||
self.image.conflict_key()
|
||||
}
|
||||
|
||||
fn current_mip_levels_access(&self) -> Range<u32> {
|
||||
self.image.current_mip_levels_access()
|
||||
}
|
||||
@ -283,11 +308,6 @@ where
|
||||
(**self).descriptor_layouts()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_key(&self) -> u64 {
|
||||
(**self).conflict_key()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn layout_initialized(&self) {
|
||||
(**self).layout_initialized();
|
||||
|
@ -19,10 +19,10 @@ use std::ops::BitOr;
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ImageUsage {
|
||||
/// Can be used as a source for transfers. Includes blits.
|
||||
pub transfer_source: bool,
|
||||
pub transfer_src: bool,
|
||||
|
||||
/// Can be used as a destination for transfers. Includes blits.
|
||||
pub transfer_destination: bool,
|
||||
pub transfer_dst: bool,
|
||||
|
||||
/// Can be sampled from a shader.
|
||||
pub sampled: bool,
|
||||
@ -54,8 +54,8 @@ impl ImageUsage {
|
||||
#[inline]
|
||||
pub fn all() -> ImageUsage {
|
||||
ImageUsage {
|
||||
transfer_source: true,
|
||||
transfer_destination: true,
|
||||
transfer_src: true,
|
||||
transfer_dst: true,
|
||||
sampled: true,
|
||||
storage: true,
|
||||
color_attachment: true,
|
||||
@ -73,7 +73,7 @@ impl ImageUsage {
|
||||
/// use vulkano::image::ImageUsage as ImageUsage;
|
||||
///
|
||||
/// let _usage = ImageUsage {
|
||||
/// transfer_destination: true,
|
||||
/// transfer_dst: true,
|
||||
/// sampled: true,
|
||||
/// .. ImageUsage::none()
|
||||
/// };
|
||||
@ -81,8 +81,8 @@ impl ImageUsage {
|
||||
#[inline]
|
||||
pub fn none() -> ImageUsage {
|
||||
ImageUsage {
|
||||
transfer_source: false,
|
||||
transfer_destination: false,
|
||||
transfer_src: false,
|
||||
transfer_dst: false,
|
||||
sampled: false,
|
||||
storage: false,
|
||||
color_attachment: false,
|
||||
@ -96,8 +96,8 @@ impl ImageUsage {
|
||||
#[inline]
|
||||
pub fn color_attachment() -> ImageUsage {
|
||||
ImageUsage {
|
||||
transfer_source: false,
|
||||
transfer_destination: false,
|
||||
transfer_src: false,
|
||||
transfer_dst: false,
|
||||
sampled: false,
|
||||
storage: false,
|
||||
color_attachment: true,
|
||||
@ -111,8 +111,8 @@ impl ImageUsage {
|
||||
#[inline]
|
||||
pub fn depth_stencil_attachment() -> ImageUsage {
|
||||
ImageUsage {
|
||||
transfer_source: false,
|
||||
transfer_destination: false,
|
||||
transfer_src: false,
|
||||
transfer_dst: false,
|
||||
sampled: false,
|
||||
storage: false,
|
||||
color_attachment: false,
|
||||
@ -126,8 +126,8 @@ impl ImageUsage {
|
||||
#[inline]
|
||||
pub fn transient_color_attachment() -> ImageUsage {
|
||||
ImageUsage {
|
||||
transfer_source: false,
|
||||
transfer_destination: false,
|
||||
transfer_src: false,
|
||||
transfer_dst: false,
|
||||
sampled: false,
|
||||
storage: false,
|
||||
color_attachment: true,
|
||||
@ -141,8 +141,8 @@ impl ImageUsage {
|
||||
#[inline]
|
||||
pub fn transient_depth_stencil_attachment() -> ImageUsage {
|
||||
ImageUsage {
|
||||
transfer_source: false,
|
||||
transfer_destination: false,
|
||||
transfer_src: false,
|
||||
transfer_dst: false,
|
||||
sampled: false,
|
||||
storage: false,
|
||||
color_attachment: false,
|
||||
@ -157,10 +157,10 @@ impl From<ImageUsage> for ash::vk::ImageUsageFlags {
|
||||
#[inline]
|
||||
fn from(val: ImageUsage) -> Self {
|
||||
let mut result = ash::vk::ImageUsageFlags::empty();
|
||||
if val.transfer_source {
|
||||
if val.transfer_src {
|
||||
result |= ash::vk::ImageUsageFlags::TRANSFER_SRC;
|
||||
}
|
||||
if val.transfer_destination {
|
||||
if val.transfer_dst {
|
||||
result |= ash::vk::ImageUsageFlags::TRANSFER_DST;
|
||||
}
|
||||
if val.sampled {
|
||||
@ -189,8 +189,8 @@ impl From<ash::vk::ImageUsageFlags> for ImageUsage {
|
||||
#[inline]
|
||||
fn from(val: ash::vk::ImageUsageFlags) -> ImageUsage {
|
||||
ImageUsage {
|
||||
transfer_source: !(val & ash::vk::ImageUsageFlags::TRANSFER_SRC).is_empty(),
|
||||
transfer_destination: !(val & ash::vk::ImageUsageFlags::TRANSFER_DST).is_empty(),
|
||||
transfer_src: !(val & ash::vk::ImageUsageFlags::TRANSFER_SRC).is_empty(),
|
||||
transfer_dst: !(val & ash::vk::ImageUsageFlags::TRANSFER_DST).is_empty(),
|
||||
sampled: !(val & ash::vk::ImageUsageFlags::SAMPLED).is_empty(),
|
||||
storage: !(val & ash::vk::ImageUsageFlags::STORAGE).is_empty(),
|
||||
color_attachment: !(val & ash::vk::ImageUsageFlags::COLOR_ATTACHMENT).is_empty(),
|
||||
@ -209,8 +209,8 @@ impl BitOr for ImageUsage {
|
||||
#[inline]
|
||||
fn bitor(self, rhs: Self) -> Self {
|
||||
ImageUsage {
|
||||
transfer_source: self.transfer_source || rhs.transfer_source,
|
||||
transfer_destination: self.transfer_destination || rhs.transfer_destination,
|
||||
transfer_src: self.transfer_src || rhs.transfer_src,
|
||||
transfer_dst: self.transfer_dst || rhs.transfer_dst,
|
||||
sampled: self.sampled || rhs.sampled,
|
||||
storage: self.storage || rhs.storage,
|
||||
color_attachment: self.color_attachment || rhs.color_attachment,
|
||||
|
@ -101,10 +101,6 @@ mod tests {
|
||||
fn size(&self) -> DeviceSize {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn conflict_key(&self) -> (u64, u64) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl DeviceOwned for DummyBufferA {
|
||||
@ -127,10 +123,6 @@ mod tests {
|
||||
fn size(&self) -> DeviceSize {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn conflict_key(&self) -> (u64, u64) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl DeviceOwned for DummyBufferB {
|
||||
|
@ -688,7 +688,7 @@ impl<W> Swapchain<W> {
|
||||
self.images.get(offset).map(|i| ImageInner {
|
||||
image: &i.image,
|
||||
first_layer: 0,
|
||||
num_layers: self.image_array_layers as usize,
|
||||
num_layers: self.image_array_layers,
|
||||
first_mipmap_level: 0,
|
||||
num_mipmap_levels: 1,
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user