mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-18 18:12:32 +00:00
Add TrackedImage trait and the equivalent of buffers for images
This commit is contained in:
parent
8d928cba1c
commit
b94e62fbde
@ -16,6 +16,7 @@ use std::sync::mpsc::Sender;
|
||||
use buffer::sys::UnsafeBuffer;
|
||||
use command_buffer::Submission;
|
||||
use device::Queue;
|
||||
use image::Image;
|
||||
use memory::Content;
|
||||
|
||||
use sync::AccessFlagBits;
|
||||
@ -68,7 +69,7 @@ pub unsafe trait Buffer: 'static + Send + Sync {
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait for `Buffer`. Types that implement this can used in a `StdCommandBuffer`.
|
||||
/// Extension trait for `Buffer`. Types that implement this can be used in a `StdCommandBuffer`.
|
||||
///
|
||||
/// Each buffer and image used in a `StdCommandBuffer` have an associated state which is
|
||||
/// represented by the `CommandListState` associated type of this trait. You can make multiple
|
||||
@ -87,10 +88,19 @@ pub unsafe trait TrackedBuffer: Buffer {
|
||||
/// If `is_same` returns true, then the type of `CommandListState` must be the same as for the
|
||||
/// other buffer. Otherwise a panic will occur.
|
||||
#[inline]
|
||||
fn is_same<B>(&self, other: &B) -> bool where B: Buffer {
|
||||
fn is_same_buffer<B>(&self, other: &B) -> bool where B: Buffer {
|
||||
self.inner().internal_object() == other.inner().internal_object()
|
||||
}
|
||||
|
||||
/// Returns true if TODO.
|
||||
///
|
||||
/// If `is_same` returns true, then the type of `CommandListState` must be the same as for the
|
||||
/// other image. Otherwise a panic will occur.
|
||||
#[inline]
|
||||
fn is_same_image<I>(&self, other: &I) -> bool where I: Image {
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns the state of the buffer when it has not yet been used.
|
||||
fn initial_state(&self) -> Self::CommandListState;
|
||||
}
|
||||
@ -156,7 +166,7 @@ pub struct PipelineMemoryBarrierRequest {
|
||||
pub destination_access: AccessFlagBits,
|
||||
}
|
||||
|
||||
/// Trait for objects that represent the state of a slice of the buffer in a command buffer.
|
||||
/// Trait for objects that represent the state of the buffer in a command buffer.
|
||||
pub trait CommandBufferState {
|
||||
/// Called right before the command buffer is submitted.
|
||||
// TODO: function should be unsafe because it must be guaranteed that a cb is submitted
|
||||
@ -199,8 +209,13 @@ unsafe impl<B> TrackedBuffer for Arc<B> where B: TrackedBuffer, Arc<B>: Buffer {
|
||||
type FinishedState = B::FinishedState;
|
||||
|
||||
#[inline]
|
||||
fn is_same<Bo>(&self, other: &Bo) -> bool where Bo: Buffer {
|
||||
(**self).is_same(other)
|
||||
fn is_same_buffer<Bo>(&self, other: &Bo) -> bool where Bo: Buffer {
|
||||
(**self).is_same_buffer(other)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_same_image<I>(&self, other: &I) -> bool where I: Image {
|
||||
(**self).is_same_image(other)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -26,6 +26,7 @@ use command_buffer::sys::Kind;
|
||||
use device::Device;
|
||||
use device::Queue;
|
||||
use framebuffer::EmptySinglePassRenderPass;
|
||||
use image::traits::TrackedImage;
|
||||
use instance::QueueFamily;
|
||||
use sync::Fence;
|
||||
use sync::PipelineStages;
|
||||
@ -77,6 +78,13 @@ unsafe impl<P> StdCommandsList for PrimaryCbBuilder<P> where P: CommandPool {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn extract_current_image_state<I>(&mut self, image: &I) -> Option<I::CommandListState>
|
||||
where I: TrackedImage
|
||||
{
|
||||
None
|
||||
}
|
||||
|
||||
unsafe fn raw_build<I, F>(self, additional_elements: F, transitions: I,
|
||||
final_transitions: PipelineBarrierBuilder) -> Self::Output
|
||||
where F: FnOnce(&mut UnsafeCommandBufferBuilder<Self::Pool>),
|
||||
|
@ -15,6 +15,7 @@ use command_buffer::submit::CommandBuffer;
|
||||
use command_buffer::sys::PipelineBarrierBuilder;
|
||||
use command_buffer::sys::UnsafeCommandBufferBuilder;
|
||||
use framebuffer::RenderPass;
|
||||
use image::traits::TrackedImage;
|
||||
use instance::QueueFamily;
|
||||
|
||||
pub use self::empty::PrimaryCb;
|
||||
@ -76,6 +77,17 @@ pub unsafe trait StdCommandsList {
|
||||
unsafe fn extract_current_buffer_state<B>(&mut self, buffer: &B) -> Option<B::CommandListState>
|
||||
where B: TrackedBuffer;
|
||||
|
||||
/// Returns the current status of an image, or `None` if the image hasn't been used yet.
|
||||
///
|
||||
/// See the description of `extract_current_buffer_state`.
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// - Panics if the state of that image has already been previously extracted.
|
||||
///
|
||||
unsafe fn extract_current_image_state<I>(&mut self, image: &I) -> Option<I::CommandListState>
|
||||
where I: TrackedImage;
|
||||
|
||||
/// Turns the commands list into a command buffer.
|
||||
///
|
||||
/// This function accepts additional arguments that will customize the output:
|
||||
|
@ -25,6 +25,7 @@ use command_buffer::sys::PipelineBarrierBuilder;
|
||||
use command_buffer::sys::UnsafeCommandBuffer;
|
||||
use command_buffer::sys::UnsafeCommandBufferBuilder;
|
||||
use device::Queue;
|
||||
use image::traits::TrackedImage;
|
||||
use instance::QueueFamily;
|
||||
use sync::AccessFlagBits;
|
||||
use sync::Fence;
|
||||
@ -99,7 +100,7 @@ unsafe impl<'a, L, B, D: ?Sized> StdCommandsList for UpdateCommand<'a, L, B, D>
|
||||
-> Option<Ob::CommandListState>
|
||||
where Ob: TrackedBuffer
|
||||
{
|
||||
if self.buffer.is_same(buffer) {
|
||||
if self.buffer.is_same_buffer(buffer) {
|
||||
let s: &mut Option<Ob::CommandListState> = (&mut self.buffer_state as &mut Any)
|
||||
.downcast_mut().unwrap();
|
||||
Some(s.take().unwrap())
|
||||
@ -109,6 +110,19 @@ unsafe impl<'a, L, B, D: ?Sized> StdCommandsList for UpdateCommand<'a, L, B, D>
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn extract_current_image_state<I>(&mut self, image: &I) -> Option<I::CommandListState>
|
||||
where I: TrackedImage
|
||||
{
|
||||
if self.buffer.is_same_image(image) {
|
||||
let s: &mut Option<I::CommandListState> = (&mut self.buffer_state as &mut Any)
|
||||
.downcast_mut().unwrap();
|
||||
Some(s.take().unwrap())
|
||||
|
||||
} else {
|
||||
self.previous.extract_current_image_state(image)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn raw_build<I, F>(mut self, additional_elements: F, transitions: I,
|
||||
mut final_transitions: PipelineBarrierBuilder) -> Self::Output
|
||||
where F: FnOnce(&mut UnsafeCommandBufferBuilder<L::Pool>),
|
||||
|
@ -56,6 +56,7 @@ use framebuffer::UnsafeRenderPass;
|
||||
use image::Image;
|
||||
use image::sys::Layout;
|
||||
use image::sys::UnsafeImage;
|
||||
use image::traits::PipelineBarrierRequest as ImagePipelineBarrierRequest;
|
||||
use pipeline::ComputePipeline;
|
||||
use pipeline::GraphicsPipeline;
|
||||
use pipeline::input_assembly::IndexType;
|
||||
@ -1190,6 +1191,10 @@ impl PipelineBarrierBuilder {
|
||||
} else {*/
|
||||
(vk::QUEUE_FAMILY_IGNORED, vk::QUEUE_FAMILY_IGNORED)
|
||||
/*}*/;
|
||||
|
||||
// TODO: add more debug asserts
|
||||
|
||||
debug_assert!(memory_barrier.offset + memory_barrier.size <= buffer.size());
|
||||
|
||||
self.buffer_barriers.push(vk::BufferMemoryBarrier {
|
||||
sType: vk::STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||
@ -1205,6 +1210,51 @@ impl PipelineBarrierBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn add_image_barrier_request(&mut self, image: &UnsafeImage,
|
||||
request: ImagePipelineBarrierRequest)
|
||||
{
|
||||
if !request.by_region {
|
||||
self.dependency_flags = 0;
|
||||
}
|
||||
|
||||
self.src_stage_mask |= request.source_stage.into();
|
||||
self.dst_stage_mask |= request.destination_stages.into();
|
||||
|
||||
if let Some(memory_barrier) = request.memory_barrier {
|
||||
let (src_queue, dest_queue) = /*if let Some((src_queue, dest_queue)) = queue_transfer {
|
||||
(src_queue, dest_queue)
|
||||
} else {*/
|
||||
(vk::QUEUE_FAMILY_IGNORED, vk::QUEUE_FAMILY_IGNORED)
|
||||
/*}*/;
|
||||
|
||||
// TODO: add more debug asserts
|
||||
|
||||
debug_assert!(memory_barrier.first_mipmap +
|
||||
memory_barrier.num_mipmaps <= image.mipmap_levels());
|
||||
debug_assert!(memory_barrier.first_layer +
|
||||
memory_barrier.num_layers <= image.dimensions().array_layers());
|
||||
|
||||
self.image_barriers.push(vk::ImageMemoryBarrier {
|
||||
sType: vk::STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
pNext: ptr::null(),
|
||||
srcAccessMask: memory_barrier.source_access.into(),
|
||||
dstAccessMask: memory_barrier.destination_access.into(),
|
||||
oldLayout: memory_barrier.old_layout as u32,
|
||||
newLayout: memory_barrier.new_layout as u32,
|
||||
srcQueueFamilyIndex: src_queue,
|
||||
dstQueueFamilyIndex: dest_queue,
|
||||
image: image.internal_object(),
|
||||
subresourceRange: vk::ImageSubresourceRange {
|
||||
aspectMask: 1 | 2 | 4 | 8, // FIXME: wrong
|
||||
baseMipLevel: memory_barrier.first_mipmap,
|
||||
levelCount: memory_barrier.num_mipmaps,
|
||||
baseArrayLayer: memory_barrier.first_layer,
|
||||
layerCount: memory_barrier.num_layers,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a buffer memory barrier. This means that all the memory writes to the given buffer by
|
||||
/// the given source stages for the given source accesses must be visible by the given dest
|
||||
/// stages for the given dest accesses.
|
||||
|
@ -7,10 +7,15 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use std::any::Any;
|
||||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::mpsc::Receiver;
|
||||
|
||||
use buffer::Buffer;
|
||||
use command_buffer::Submission;
|
||||
use device::Queue;
|
||||
use format::ClearValue;
|
||||
use format::Format;
|
||||
use image::sys::Dimensions;
|
||||
@ -18,8 +23,13 @@ use image::sys::Layout;
|
||||
use image::sys::UnsafeImage;
|
||||
use image::sys::UnsafeImageView;
|
||||
use sampler::Sampler;
|
||||
use sync::AccessFlagBits;
|
||||
use sync::PipelineStages;
|
||||
use sync::Fence;
|
||||
use sync::Semaphore;
|
||||
|
||||
use VulkanObject;
|
||||
|
||||
/// Trait for types that represent images.
|
||||
pub unsafe trait Image: 'static + Send + Sync {
|
||||
/// Returns the inner unsafe image object used by this image.
|
||||
@ -115,6 +125,122 @@ pub unsafe trait Image: 'static + Send + Sync {
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait for `Image`. Types that implement this can be used in a `StdCommandBuffer`.
|
||||
///
|
||||
/// Each buffer and image used in a `StdCommandBuffer` have an associated state which is
|
||||
/// represented by the `CommandListState` associated type of this trait. You can make multiple
|
||||
/// buffers or images share the same state by making `is_same` return true.
|
||||
pub unsafe trait TrackedImage: Image {
|
||||
/// State of the image in a list of commands.
|
||||
///
|
||||
/// The `Any` bound is here for stupid reasons, sorry.
|
||||
// TODO: remove Any bound
|
||||
type CommandListState: Any + CommandListState<FinishedState = Self::FinishedState>;
|
||||
/// State of the buffer in a finished list of commands.
|
||||
type FinishedState: CommandBufferState;
|
||||
|
||||
/// Returns true if TODO.
|
||||
///
|
||||
/// If `is_same` returns true, then the type of `CommandListState` must be the same as for the
|
||||
/// other buffer. Otherwise a panic will occur.
|
||||
#[inline]
|
||||
fn is_same_buffer<B>(&self, other: &B) -> bool where B: Buffer {
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns true if TODO.
|
||||
///
|
||||
/// If `is_same` returns true, then the type of `CommandListState` must be the same as for the
|
||||
/// other image. Otherwise a panic will occur.
|
||||
#[inline]
|
||||
fn is_same_image<I>(&self, other: &I) -> bool where I: Image {
|
||||
self.inner().internal_object() == other.inner().internal_object()
|
||||
}
|
||||
|
||||
/// Returns the state of the image when it has not yet been used.
|
||||
fn initial_state(&self) -> Self::CommandListState;
|
||||
}
|
||||
|
||||
/// Trait for objects that represent the state of a slice of the image in a list of commands.
|
||||
pub trait CommandListState {
|
||||
type FinishedState: CommandBufferState;
|
||||
|
||||
/// Returns a new state that corresponds to the moment after a slice of the image has been
|
||||
/// used in the pipeline. The parameters indicate in which way it has been used.
|
||||
///
|
||||
/// If the transition should result in a pipeline barrier, then it must be returned by this
|
||||
/// function.
|
||||
fn transition(self, num_command: usize, image: &UnsafeImage, first_mipmap: u32,
|
||||
num_mipmaps: u32, first_layer: u32, num_layers: u32, write: bool, layout: Layout,
|
||||
stage: PipelineStages, access: AccessFlagBits)
|
||||
-> (Self, Option<PipelineBarrierRequest>)
|
||||
where Self: Sized;
|
||||
|
||||
/// Function called when the command buffer builder is turned into a real command buffer.
|
||||
///
|
||||
/// This function can return an additional pipeline barrier that will be applied at the end
|
||||
/// of the command buffer.
|
||||
fn finish(self) -> (Self::FinishedState, Option<PipelineBarrierRequest>);
|
||||
}
|
||||
|
||||
/// Requests that a pipeline barrier is created.
|
||||
pub struct PipelineBarrierRequest {
|
||||
/// The number of the command after which the barrier should be placed. Must usually match
|
||||
/// the number that was passed to the previous call to `transition`, or 0 if the image hasn't
|
||||
/// been used yet.
|
||||
pub after_command_num: usize,
|
||||
|
||||
/// The source pipeline stages of the transition.
|
||||
pub source_stage: PipelineStages,
|
||||
|
||||
/// The destination pipeline stages of the transition.
|
||||
pub destination_stages: PipelineStages,
|
||||
|
||||
/// If true, the pipeliner barrier is by region.
|
||||
pub by_region: bool,
|
||||
|
||||
/// An optional memory barrier. See the docs of `PipelineMemoryBarrierRequest`.
|
||||
pub memory_barrier: Option<PipelineMemoryBarrierRequest>,
|
||||
}
|
||||
|
||||
/// Requests that a memory barrier is created as part of the pipeline barrier.
|
||||
///
|
||||
/// By default, a pipeline barrier only guarantees that the source operations are executed before
|
||||
/// the destination operations, but it doesn't make memory writes made by source operations visible
|
||||
/// to the destination operations. In order to make so, you have to add a memory barrier.
|
||||
///
|
||||
/// The memory barrier always concerns the image that is currently being processed. You can't add
|
||||
/// a memory barrier that concerns another resource.
|
||||
pub struct PipelineMemoryBarrierRequest {
|
||||
pub first_mipmap: u32,
|
||||
pub num_mipmaps: u32,
|
||||
pub first_layer: u32,
|
||||
pub num_layers: u32,
|
||||
|
||||
pub old_layout: Layout,
|
||||
pub new_layout: Layout,
|
||||
|
||||
/// Source accesses.
|
||||
pub source_access: AccessFlagBits,
|
||||
/// Destination accesses.
|
||||
pub destination_access: AccessFlagBits,
|
||||
}
|
||||
|
||||
/// Trait for objects that represent the state of the image in a command buffer.
|
||||
pub trait CommandBufferState {
|
||||
/// Called right before the command buffer is submitted.
|
||||
// TODO: function should be unsafe because it must be guaranteed that a cb is submitted
|
||||
fn on_submit<I, F>(&self, image: &I, queue: &Arc<Queue>, fence: F) -> SubmitInfos
|
||||
where I: Image, F: FnOnce() -> Arc<Fence>;
|
||||
}
|
||||
|
||||
pub struct SubmitInfos {
|
||||
pub pre_semaphore: Option<(Receiver<Arc<Semaphore>>, PipelineStages)>,
|
||||
pub post_semaphore: Option<Sender<Arc<Semaphore>>>,
|
||||
pub pre_barrier: Option<PipelineBarrierRequest>,
|
||||
pub post_barrier: Option<PipelineBarrierRequest>,
|
||||
}
|
||||
|
||||
/// Extension trait for images. Checks whether the value `T` can be used as a clear value for the
|
||||
/// given image.
|
||||
// TODO: isn't that for image views instead?
|
||||
|
Loading…
Reference in New Issue
Block a user