From ff807412fac66bb76b580d5e17a842aa9970de67 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 19 Feb 2016 15:50:28 +0100 Subject: [PATCH] Draft for descriptor sets --- vulkano/src/descriptor_set.rs | 123 +++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 32 deletions(-) diff --git a/vulkano/src/descriptor_set.rs b/vulkano/src/descriptor_set.rs index b87b0545..19873a4f 100644 --- a/vulkano/src/descriptor_set.rs +++ b/vulkano/src/descriptor_set.rs @@ -1,3 +1,22 @@ + + +How does that work? + +The shader analyser determines which descriptors are used by each shader and outputs a struct +that describes this stuff. This struct implements `PipelineLayoutDesc`. + +When shaders are grouped together in the pipeline, they are passed through `CompatiblePipeline` +to be merged into a single pipeline layout struct. If the descriptors of the various shaders +are incompatible, it is detected at that moment. + +The single struct that represents the layout is stored as a template parameter of the pipeline. +It is also stored in the `PipelineLayout` object (which wraps around vulkan's pipeline layout). +When you draw, you have to pass a collection of descriptor sets that are compatible with the +pipeline layout desc of the pipeline. + + + + use std::iter; use device::Device; @@ -10,17 +29,80 @@ pub unsafe trait Layout { type RawLayout; } + + +pub unsafe trait PipelineLayoutDesc { + type DescriptorSets; + type PushConstants; +} + +// example: impl PipelineLayoutDesc for (CustomFrag1, CustomFrag2, CustomFrag3) {} + + + +pub unsafe trait CompatiblePipeline { type Out; } +pub unsafe trait CompatibleSet { type Out; } + +macro_rules! impl_tuple { + (($in_first:ident $out_first:ident) $(, ($in_rest:ident $out_rest:ident))*) => { + unsafe impl<$in_first, $out_first $(, $in_rest, $out_rest)*> + CompatibleSet<($out_first, $($out_rest,)*)> for ($in_first, $($in_rest,)*) + where $in_first: CompatibleDescriptor<$out_first> $(, $in_rest: CompatibleDescriptor<$out_rest>)* + { + type Out = ( + <$in_first as CompatibleDescriptor<$out_first>>::Out, + $( + <$in_rest as CompatibleDescriptor<$out_rest>>::Out, + )* + ); + } + + unsafe impl<$in_first, $out_first $(, $in_rest, $out_rest)*> + CompatiblePipeline<($out_first, $($out_rest,)*)> for ($in_first, $($in_rest,)*) + where $in_first: CompatibleSet<$out_first> $(, $in_rest: CompatibleSet<$out_rest>)* + { + type Out = ( + <$in_first as CompatibleSet<$out_first>>::Out, + $( + <$in_rest as CompatibleSet<$out_rest>>::Out, + )* + ); + } + + impl_tuple!{$(($in_rest $out_rest)),*} + }; + + () => (); +} + +impl_tuple!( (A N), (B O), (C P), (D Q), (E R), (F S), (G T), + (H U), (I V), (J W), (K X), (L Y), (M Z) ); + +/// If a type `A` can be interpreted as a `T`, then `A` will implement `CompatibleDescriptor`. +trait CompatibleDescriptor { type Out; } + +impl CompatibleDescriptor<()> for () { type Out = (); } +impl CompatibleDescriptor<()> for T where T: Descriptor { type Out = T; } +impl CompatibleDescriptor for () where T: Descriptor { type Out = T; } +impl CompatibleDescriptor for T where T: Descriptor { type Out = T; } + + +pub unsafe trait Descriptor {} + + + + /// Represents the layout of the resources and data that can be binded before drawing and that will /// be accessible from the shaders. /// /// The template parameter represents the descriptor sets. // TODO: push constants. -pub struct PipelineLayout { +pub struct PipelineLayout

{ device: Arc, layout: VkPipelineLayout, } -impl PipelineLayout { +impl

PipelineLayout

where P: PipelineLayoutDesc { /// Creates a new `PipelineLayout`. pub fn new(device: &Arc) -> Result>, > { let layout = unsafe { @@ -47,37 +129,14 @@ impl PipelineLayout { } } -pub trait DescriptorDef { - type BindData; +pub unsafe trait DescriptorSetDef { + type Content; + + } -pub struct StorageImageMarker; - -pub struct SamplerMarker; - -pub struct SampledImageMarker; - -pub struct CombinedImageSamplerMarker; - -pub struct UniformTexelBufferMarker(Buffer); - -pub struct StorageTexelBufferMarker(Buffer); - -pub struct UniformBufferMarker(Buffer); - -pub struct StorageBufferMarker(Buffer); - -pub struct DynamicUniformBufferMarker(Buffer); - -pub struct DynamicStorageBufferMarker(Buffer); - -pub struct InputAttachmentMarker; - -pub trait DescriptorSetDefinition { - type Raw; - - fn into_raw(self) -> Self::Raw; -} +// example: +// impl DescriptorSetDef for MyDescriptorSet { } pub struct DescriptorSetLayout { device: Arc, @@ -85,7 +144,7 @@ pub struct DescriptorSetLayout { marker: PhantomData, } -impl DescriptorSetLayout where D: DescriptorSetDefinition { +impl DescriptorSetLayout where D: DescriptorSetDef { pub fn new(device: &Arc) -> Result> { let vk = device.pointers();