Add image prototype system for layout transitionning

This commit is contained in:
Pierre Krieger 2016-02-18 10:55:58 +01:00
parent d3b9a82171
commit 41b664ed71
4 changed files with 159 additions and 49 deletions

View File

@ -138,9 +138,16 @@ fn main() {
// implicitely does a lot of computation whenever you draw. In Vulkan, you have to do all this
// manually.
// We are going to create a command buffer below. Command buffers need to be allocated
// from a *command buffer pool*, so we create the pool.
let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.lock().unwrap().family())
.expect("failed to create command buffer pool");
// We are going to draw on the images returned when creating the swapchain. To do so, we must
// convert them into *image views*. TODO: explain more
let images = images.into_iter().map(|image| {
let image = image.transition(vulkano::image::Layout::PresentSrc, &cb_pool,
&mut queue.lock().unwrap()).unwrap();
vulkano::image::ImageView::new(&image).expect("failed to create image view")
}).collect::<Vec<_>>();
@ -181,11 +188,6 @@ fn main() {
vulkano::framebuffer::Framebuffer::new(&renderpass, (1244, 699, 1), image).unwrap()
}).collect::<Vec<_>>();
// We are going to create a command buffer right below. Command buffers need to be allocated
// from a *command buffer pool*, so we create the pool.
let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.lock().unwrap().family())
.expect("failed to create command buffer pool");
// The final initialization step is to create a command buffer.
//
// A command buffer contains a list of commands that the GPU must execute. This can include

View File

@ -453,8 +453,7 @@ impl InnerCommandBuffer {
};
unsafe {
try!(check_errors(vk.QueueSubmit(queue.internal_object(), 1,
&infos, mem::transmute(0u64) /*vk::NULL_HANDLE*/)));
try!(check_errors(vk.QueueSubmit(queue.internal_object(), 1, &infos, 0)));
}
Ok(())

View File

@ -19,7 +19,9 @@ use std::mem;
use std::ptr;
use std::sync::Arc;
use command_buffer::CommandBufferPool;
use device::Device;
use device::Queue;
use formats::FormatMarker;
use memory::ChunkProperties;
use memory::MemorySource;
@ -82,20 +84,6 @@ pub unsafe trait CanCreateView<Dest>: ImageTypeMarker where Dest: ImageViewTypeM
unsafe impl<T> CanCreateView<T> for T where T: ImageTypeMarker + ImageViewTypeMarker {}
pub unsafe trait MultisampleType: TypeMarker {}
/// A storage for pixels or arbitrary data.
pub struct Image<Ty, F, M> where Ty: ImageTypeMarker {
device: Arc<Device>,
image: vk::Image,
memory: M,
usage: vk::ImageUsageFlagBits,
dimensions: Ty::Dimensions,
samples: Ty::NumSamples,
mipmaps: u32,
needs_destruction: bool,
default_layout: Layout,
marker: PhantomData<F>,
}
/// Specifies how many mipmaps must be allocated.
///
/// Note that at least one mipmap must be allocated, to store the main level of the image.
@ -119,6 +107,20 @@ impl From<u32> for MipmapsCount {
}
}
/// A storage for pixels or arbitrary data.
pub struct Image<Ty, F, M> where Ty: ImageTypeMarker {
device: Arc<Device>,
image: vk::Image,
memory: M,
usage: vk::ImageUsageFlagBits,
dimensions: Ty::Dimensions,
samples: Ty::NumSamples,
mipmaps: u32,
needs_destruction: bool,
layout: Layout,
marker: PhantomData<F>,
}
impl<Ty, F, M> Image<Ty, F, M>
where M: MemorySourceChunk, Ty: ImageTypeMarker, F: FormatMarker
{
@ -132,7 +134,7 @@ impl<Ty, F, M> Image<Ty, F, M>
///
pub fn new<S, Mi>(device: &Arc<Device>, usage: &Usage, memory: S, dimensions: Ty::Dimensions,
num_samples: Ty::NumSamples, mipmaps: Mi)
-> Result<Arc<Image<Ty, F, M>>, OomError>
-> Result<ImagePrototype<Ty, F, M>, OomError>
where S: MemorySource<Chunk = M>, Mi: Into<MipmapsCount>
{
let vk = device.pointers();
@ -213,7 +215,8 @@ impl<Ty, F, M> Image<Ty, F, M>
}
}
Ok(Arc::new(Image {
Ok(ImagePrototype {
image: Image {
device: device.clone(),
image: image,
memory: memory,
@ -222,9 +225,10 @@ impl<Ty, F, M> Image<Ty, F, M>
samples: num_samples,
mipmaps: mipmaps,
needs_destruction: true,
default_layout: Layout::General, // FIXME:
layout: Layout::Undefined, // TODO:
marker: PhantomData,
}))
},
})
}
/// Creates an image from a raw handle. The image won't be destroyed.
@ -232,9 +236,10 @@ impl<Ty, F, M> Image<Ty, F, M>
/// This function is for example used at the swapchain's initialization.
pub unsafe fn from_raw_unowned(device: &Arc<Device>, handle: u64, memory: M, usage: u32,
dimensions: Ty::Dimensions, samples: Ty::NumSamples, mipmaps: u32)
-> Arc<Image<Ty, F, M>>
-> ImagePrototype<Ty, F, M>
{
Arc::new(Image {
ImagePrototype{
image: Image {
device: device.clone(),
image: handle,
memory: memory,
@ -243,9 +248,10 @@ impl<Ty, F, M> Image<Ty, F, M>
samples: samples,
mipmaps: mipmaps,
needs_destruction: false,
default_layout: Layout::General, // FIXME:
layout: Layout::Undefined,
marker: PhantomData,
})
},
}
}
/// Returns the dimensions of this image.
@ -328,7 +334,7 @@ unsafe impl<Ty, F, M> ImageGpuAccess for Image<Ty, F, M>
{
#[inline]
fn default_layout(&self) -> Layout {
self.default_layout
self.layout
}
}
@ -348,6 +354,108 @@ impl<Ty, F, M> Drop for Image<Ty, F, M>
}
}
pub struct ImagePrototype<Ty, F, M> where Ty: ImageTypeMarker {
image: Image<Ty, F, M>,
}
impl<Ty, F, M> ImagePrototype<Ty, F, M>
where Ty: ImageTypeMarker
{
/// Transitions the image prototype into a real image by submitting a one-shot command buffer.
///
/// # Panic
///
/// - Panicks if `layout` is `Undefined` or `Preinitialized`.
// FIXME: PresentSrc is only allowed for swapchain images
pub fn transition(self, layout: Layout, pool: &CommandBufferPool, submit_queue: &mut Queue)
-> Result<Arc<Image<Ty, F, M>>, OomError> // FIXME: error type
{
// FIXME: check pool and submit queue correspondance
assert!(layout != Layout::Undefined);
assert!(layout != Layout::Preinitialized);
let mut image = self.image;
let old_layout = image.layout;
image.layout = layout;
let device = image.device.clone();
let vk = device.pointers();
unsafe {
let cmd = {
let infos = vk::CommandBufferAllocateInfo {
sType: vk::STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
pNext: ptr::null(),
commandPool: pool.internal_object(),
level: vk::COMMAND_BUFFER_LEVEL_SECONDARY,
commandBufferCount: 1,
};
let mut output = mem::uninitialized();
try!(check_errors(vk.AllocateCommandBuffers(device.internal_object(), &infos,
&mut output)));
output
};
{
let infos = vk::CommandBufferBeginInfo {
sType: vk::STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
pNext: ptr::null(),
flags: vk::COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
pInheritanceInfo: ptr::null(),
};
try!(check_errors(vk.BeginCommandBuffer(cmd, &infos)));
}
{
let barrier = vk::ImageMemoryBarrier {
sType: vk::STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
pNext: ptr::null(),
srcAccessMask: 0,
dstAccessMask: vk::ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
oldLayout: image.layout as u32,
newLayout: layout as u32,
srcQueueFamilyIndex: vk::QUEUE_FAMILY_IGNORED,
dstQueueFamilyIndex: vk::QUEUE_FAMILY_IGNORED,
image: image.image,
subresourceRange: vk::ImageSubresourceRange {
aspectMask: vk::IMAGE_ASPECT_COLOR_BIT, // FIXME:
baseMipLevel: 0,
levelCount: vk::REMAINING_MIP_LEVELS,
baseArrayLayer: 0,
layerCount: vk::REMAINING_ARRAY_LAYERS,
}
};
vk.CmdPipelineBarrier(cmd, 0, vk::PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0,
ptr::null(), 0, ptr::null(), 1, &barrier);
}
try!(check_errors(vk.EndCommandBuffer(cmd)));
{
let infos = vk::SubmitInfo {
sType: vk::STRUCTURE_TYPE_SUBMIT_INFO,
pNext: ptr::null(),
waitSemaphoreCount: 0,
pWaitSemaphores: ptr::null(),
pWaitDstStageMask: ptr::null(),
commandBufferCount: 1,
pCommandBuffers: &cmd,
signalSemaphoreCount: 0, // TODO:
pSignalSemaphores: ptr::null(), // TODO:
};
try!(check_errors(vk.QueueSubmit(submit_queue.internal_object(), 1, &infos, 0)));
}
}
Ok(Arc::new(image))
}
}
/// Describes how an image is going to be used. This is **not** an optimization.
///
/// If you try to use an image in a way that you didn't declare, a panic will happen.

View File

@ -8,6 +8,7 @@ use device::Device;
use device::Queue;
use formats::FormatMarker;
use image::Image;
use image::ImagePrototype;
use image::Type2d;
use image::Usage as ImageUsage;
use memory::ChunkProperties;
@ -58,7 +59,7 @@ impl Swapchain {
pub fn new<F>(device: &Arc<Device>, surface: &Arc<Surface>, num_images: u32, format: F,
dimensions: [u32; 2], layers: u32, usage: &ImageUsage,
transform: SurfaceTransform, alpha: CompositeAlpha, mode: PresentMode,
clipped: bool) -> Result<(Arc<Swapchain>, Vec<Arc<Image<Type2d, F, SwapchainAllocatedChunk>>>), OomError>
clipped: bool) -> Result<(Arc<Swapchain>, Vec<ImagePrototype<Type2d, F, SwapchainAllocatedChunk>>), OomError>
where F: FormatMarker
{
// FIXME: check that the parameters are supported