mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-22 06:45:23 +00:00
Add unsafe support for push constants
This commit is contained in:
parent
e9d82d8c18
commit
f6733628e8
@ -29,3 +29,5 @@
|
||||
- This repository contains the `vulkano-shaders` library, which generates Rust code that uses the `vulkano` library. If the API of `vulkano` gets
|
||||
a breaking change, there is no way to enforce or to check the fact that the user uses a correct combination of versions for `vulkano-shaders`
|
||||
and `vulkano`.
|
||||
|
||||
- No way to set the alignment of a struct member, or to force the size of a struct to be a multiple of a certain size.
|
||||
|
@ -220,7 +220,7 @@ fn main() {
|
||||
.draw_inline(&renderpass, &framebuffer, renderpass::ClearValues {
|
||||
color: [0.0, 0.0, 1.0, 1.0]
|
||||
})
|
||||
.draw(&pipeline, &vertex_buffer, &vulkano::command_buffer::DynamicState::none(), set.clone())
|
||||
.draw(&pipeline, &vertex_buffer, &vulkano::command_buffer::DynamicState::none(), set.clone(), &())
|
||||
.draw_end()
|
||||
.build().unwrap()
|
||||
}).collect::<Vec<_>>();
|
||||
|
@ -216,7 +216,7 @@ fn main() {
|
||||
depth: 1.0,
|
||||
})
|
||||
.draw_indexed(&pipeline, (&vertex_buffer, &normals_buffer), &index_buffer,
|
||||
&vulkano::command_buffer::DynamicState::none(), &set)
|
||||
&vulkano::command_buffer::DynamicState::none(), &set, &())
|
||||
.draw_end()
|
||||
.build().unwrap()
|
||||
}).collect::<Vec<_>>();
|
||||
|
@ -237,7 +237,7 @@ fn main() {
|
||||
let command_buffers = framebuffers.iter().map(|framebuffer| {
|
||||
vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
|
||||
.draw_inline(&renderpass, &framebuffer, ([0.0, 0.0, 1.0, 1.0],))
|
||||
.draw(&pipeline, vertex_buffer.clone(), &vulkano::command_buffer::DynamicState::none(), ())
|
||||
.draw(&pipeline, vertex_buffer.clone(), &vulkano::command_buffer::DynamicState::none(), (), &())
|
||||
.draw_end()
|
||||
.build().unwrap()
|
||||
}).collect::<Vec<_>>();
|
||||
|
@ -686,15 +686,15 @@ impl InnerCommandBufferBuilder {
|
||||
|
||||
/// Calls `vkCmdDraw`.
|
||||
// FIXME: push constants
|
||||
pub unsafe fn draw<V, Pv, Pl, L, Rp>(mut self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
|
||||
pub unsafe fn draw<V, Pv, Pl, L, Rp, Pc>(mut self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
|
||||
vertices: V, dynamic: &DynamicState,
|
||||
sets: L) -> InnerCommandBufferBuilder
|
||||
sets: L, push_constants: &Pc) -> InnerCommandBufferBuilder
|
||||
where Pv: 'static + VertexDefinition + VertexSource<V>, L: DescriptorSetsCollection + Send + Sync,
|
||||
Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync
|
||||
Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync, Pc: 'static + Clone
|
||||
{
|
||||
// FIXME: add buffers to the resources
|
||||
|
||||
self.bind_gfx_pipeline_state(pipeline, dynamic, sets);
|
||||
self.bind_gfx_pipeline_state(pipeline, dynamic, sets, push_constants);
|
||||
|
||||
let vertices = pipeline.vertex_definition().decode(vertices);
|
||||
|
||||
@ -727,17 +727,18 @@ impl InnerCommandBufferBuilder {
|
||||
|
||||
/// Calls `vkCmdDrawIndexed`.
|
||||
// FIXME: push constants
|
||||
pub unsafe fn draw_indexed<'a, V, Pv, Pl, Rp, L, I, Ib, Ibb>(mut self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
|
||||
pub unsafe fn draw_indexed<'a, V, Pv, Pl, Rp, L, I, Ib, Ibb, Pc>(mut self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
|
||||
vertices: V, indices: Ib, dynamic: &DynamicState,
|
||||
sets: L) -> InnerCommandBufferBuilder
|
||||
sets: L, push_constants: &Pc) -> InnerCommandBufferBuilder
|
||||
where L: DescriptorSetsCollection + Send + Sync,
|
||||
Pv: 'static + VertexDefinition + VertexSource<V>,
|
||||
Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync,
|
||||
Ib: Into<BufferSlice<'a, [I], Ibb>>, I: 'static + Index, Ibb: Buffer + 'static
|
||||
Ib: Into<BufferSlice<'a, [I], Ibb>>, I: 'static + Index, Ibb: Buffer + 'static,
|
||||
Pc: 'static + Clone
|
||||
{
|
||||
// FIXME: add buffers to the resources
|
||||
|
||||
self.bind_gfx_pipeline_state(pipeline, dynamic, sets);
|
||||
self.bind_gfx_pipeline_state(pipeline, dynamic, sets, push_constants);
|
||||
|
||||
|
||||
let indices = indices.into();
|
||||
@ -830,10 +831,10 @@ impl InnerCommandBufferBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_gfx_pipeline_state<V, Pl, L, Rp>(&mut self, pipeline: &Arc<GraphicsPipeline<V, Pl, Rp>>,
|
||||
dynamic: &DynamicState, sets: L)
|
||||
fn bind_gfx_pipeline_state<V, Pl, L, Rp, Pc>(&mut self, pipeline: &Arc<GraphicsPipeline<V, Pl, Rp>>,
|
||||
dynamic: &DynamicState, sets: L, push_constants: &Pc)
|
||||
where V: 'static + VertexDefinition + Send + Sync, L: DescriptorSetsCollection + Send + Sync,
|
||||
Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync
|
||||
Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync, Pc: 'static + Clone
|
||||
{
|
||||
unsafe {
|
||||
//assert!(sets.is_compatible_with(pipeline.layout()));
|
||||
@ -905,6 +906,18 @@ impl InnerCommandBufferBuilder {
|
||||
for d in descriptor_sets.iter() { self.keep_alive.push(mem::transmute(d.clone()) /* FIXME: */); }
|
||||
let mut descriptor_sets = Some(descriptor_sets.into_iter().map(|set| set.inner_descriptor_set().internal_object()).collect::<SmallVec<[_; 32]>>());
|
||||
|
||||
if mem::size_of_val(push_constants) >= 1 {
|
||||
let pipeline = PipelineLayout::inner_pipeline_layout(&**pipeline.layout()).internal_object();
|
||||
let size = mem::size_of_val(push_constants);
|
||||
let push_constants = push_constants.clone();
|
||||
assert!((size % 4) == 0);
|
||||
|
||||
self.render_pass_staging_commands.push(Box::new(move |vk, cmd| {
|
||||
vk.CmdPushConstants(cmd, pipeline, 0x7fffffff, 0, size as u32,
|
||||
&push_constants as *const Pc as *const _);
|
||||
}));
|
||||
}
|
||||
|
||||
// FIXME: input attachments of descriptor sets have to be checked against input
|
||||
// attachments of the render pass
|
||||
|
||||
|
@ -281,17 +281,17 @@ pub struct PrimaryCommandBufferBuilderInlineDraw {
|
||||
impl PrimaryCommandBufferBuilderInlineDraw {
|
||||
/// Calls `vkCmdDraw`.
|
||||
// FIXME: push constants
|
||||
pub fn draw<V, L, Pv, Pl, Rp>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
|
||||
vertices: V, dynamic: &DynamicState, sets: L)
|
||||
pub fn draw<V, L, Pv, Pl, Rp, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
|
||||
vertices: V, dynamic: &DynamicState, sets: L, push_constants: &Pc)
|
||||
-> PrimaryCommandBufferBuilderInlineDraw
|
||||
where Pv: VertexDefinition + VertexSource<V> + 'static, Pl: PipelineLayout + 'static + Send + Sync, Rp: 'static + Send + Sync,
|
||||
L: DescriptorSetsCollection + Send + Sync
|
||||
L: DescriptorSetsCollection + Send + Sync, Pc: 'static + Clone
|
||||
{
|
||||
// FIXME: check subpass
|
||||
|
||||
unsafe {
|
||||
PrimaryCommandBufferBuilderInlineDraw {
|
||||
inner: self.inner.draw(pipeline, vertices, dynamic, sets),
|
||||
inner: self.inner.draw(pipeline, vertices, dynamic, sets, push_constants),
|
||||
num_subpasses: self.num_subpasses,
|
||||
current_subpass: self.current_subpass,
|
||||
}
|
||||
@ -299,18 +299,18 @@ impl PrimaryCommandBufferBuilderInlineDraw {
|
||||
}
|
||||
|
||||
/// Calls `vkCmdDrawIndexed`.
|
||||
pub fn draw_indexed<'a, V, L, Pv, Pl, Rp, I, Ib, Ibb>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
|
||||
pub fn draw_indexed<'a, V, L, Pv, Pl, Rp, I, Ib, Ibb, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
|
||||
vertices: V, indices: Ib, dynamic: &DynamicState,
|
||||
sets: L) -> PrimaryCommandBufferBuilderInlineDraw
|
||||
sets: L, push_constants: &Pc) -> PrimaryCommandBufferBuilderInlineDraw
|
||||
where Pv: 'static + VertexDefinition + VertexSource<V> + Send + Sync, Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync,
|
||||
Ib: Into<BufferSlice<'a, [I], Ibb>>, I: 'static + Index, Ibb: Buffer + 'static + Send + Sync,
|
||||
L: DescriptorSetsCollection + Send + Sync
|
||||
L: DescriptorSetsCollection + Send + Sync, Pc: 'static + Clone
|
||||
{
|
||||
// FIXME: check subpass
|
||||
|
||||
unsafe {
|
||||
PrimaryCommandBufferBuilderInlineDraw {
|
||||
inner: self.inner.draw_indexed(pipeline, vertices, indices, dynamic, sets),
|
||||
inner: self.inner.draw_indexed(pipeline, vertices, indices, dynamic, sets, push_constants),
|
||||
num_subpasses: self.num_subpasses,
|
||||
current_subpass: self.current_subpass,
|
||||
}
|
||||
@ -528,19 +528,19 @@ impl<R> SecondaryGraphicsCommandBufferBuilder<R>
|
||||
|
||||
/// Calls `vkCmdDraw`.
|
||||
// FIXME: push constants
|
||||
pub fn draw<V, L, Pv, Pl, Rp>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
|
||||
vertices: V, dynamic: &DynamicState, sets: L)
|
||||
pub fn draw<V, L, Pv, Pl, Rp, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
|
||||
vertices: V, dynamic: &DynamicState, sets: L, push_constants: &Pc)
|
||||
-> SecondaryGraphicsCommandBufferBuilder<R>
|
||||
where Pv: VertexDefinition + VertexSource<V> + 'static, Pl: PipelineLayout + 'static + Send + Sync,
|
||||
Rp: RenderPass + 'static + Send + Sync, L: DescriptorSetsCollection + Send + Sync,
|
||||
R: RenderPassCompatible<Rp>
|
||||
R: RenderPassCompatible<Rp>, Pc: 'static + Clone
|
||||
{
|
||||
assert!(self.render_pass.is_compatible_with(pipeline.subpass().render_pass()));
|
||||
assert_eq!(self.render_pass_subpass, pipeline.subpass().index());
|
||||
|
||||
unsafe {
|
||||
SecondaryGraphicsCommandBufferBuilder {
|
||||
inner: self.inner.draw(pipeline, vertices, dynamic, sets),
|
||||
inner: self.inner.draw(pipeline, vertices, dynamic, sets, push_constants),
|
||||
render_pass: self.render_pass,
|
||||
render_pass_subpass: self.render_pass_subpass,
|
||||
framebuffer: self.framebuffer,
|
||||
@ -549,20 +549,20 @@ impl<R> SecondaryGraphicsCommandBufferBuilder<R>
|
||||
}
|
||||
|
||||
/// Calls `vkCmdDrawIndexed`.
|
||||
pub fn draw_indexed<'a, V, L, Pv, Pl, Rp, I, Ib, Ibb>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
|
||||
pub fn draw_indexed<'a, V, L, Pv, Pl, Rp, I, Ib, Ibb, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
|
||||
vertices: V, indices: Ib, dynamic: &DynamicState,
|
||||
sets: L) -> SecondaryGraphicsCommandBufferBuilder<R>
|
||||
sets: L, push_constants: &Pc) -> SecondaryGraphicsCommandBufferBuilder<R>
|
||||
where Pv: 'static + VertexDefinition + VertexSource<V>, Pl: 'static + PipelineLayout + Send + Sync,
|
||||
Rp: RenderPass + 'static + Send + Sync,
|
||||
Ib: Into<BufferSlice<'a, [I], Ibb>>, I: 'static + Index, Ibb: Buffer + 'static,
|
||||
L: DescriptorSetsCollection + Send + Sync
|
||||
L: DescriptorSetsCollection + Send + Sync, Pc: 'static + Clone
|
||||
{
|
||||
assert!(self.render_pass.is_compatible_with(pipeline.subpass().render_pass()));
|
||||
assert_eq!(self.render_pass_subpass, pipeline.subpass().index());
|
||||
|
||||
unsafe {
|
||||
SecondaryGraphicsCommandBufferBuilder {
|
||||
inner: self.inner.draw_indexed(pipeline, vertices, indices, dynamic, sets),
|
||||
inner: self.inner.draw_indexed(pipeline, vertices, indices, dynamic, sets, push_constants),
|
||||
render_pass: self.render_pass,
|
||||
render_pass_subpass: self.render_pass_subpass,
|
||||
framebuffer: self.framebuffer,
|
||||
|
@ -314,7 +314,7 @@ impl DescriptorType {
|
||||
}
|
||||
|
||||
/// Describes which shader stages have access to a descriptor.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct ShaderStages {
|
||||
/// `True` means that the descriptor will be used by the vertex shader.
|
||||
pub vertex: bool,
|
||||
@ -344,6 +344,19 @@ impl ShaderStages {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `ShaderStages` struct will all stages set to `false`.
|
||||
#[inline]
|
||||
pub fn none() -> ShaderStages {
|
||||
ShaderStages {
|
||||
vertex: false,
|
||||
tessellation_control: false,
|
||||
tessellation_evaluation: false,
|
||||
geometry: false,
|
||||
fragment: false,
|
||||
compute: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `ShaderStages` struct will all graphics stages set to `true`.
|
||||
#[inline]
|
||||
pub fn all_graphics() -> ShaderStages {
|
||||
|
@ -21,16 +21,23 @@ use sampler::Sampler;
|
||||
// TODO: more docs
|
||||
#[macro_export]
|
||||
macro_rules! pipeline_layout {
|
||||
($($name:ident: { $($field:ident: $ty:ty),* }),*) => {
|
||||
(push_constants: { $($pc_f:ident: $pc_t:ty),* } $(, $name:ident: { $($field:ident: $ty:ty),* })*) => {
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
use std::vec::IntoIter as VecIntoIter;
|
||||
use $crate::OomError;
|
||||
use $crate::device::Device;
|
||||
use $crate::descriptor::descriptor::DescriptorDesc;
|
||||
use $crate::descriptor::descriptor::ShaderStages;
|
||||
use $crate::descriptor::pipeline_layout::PipelineLayout;
|
||||
use $crate::descriptor::pipeline_layout::PipelineLayoutDesc;
|
||||
use $crate::descriptor::pipeline_layout::UnsafePipelineLayout;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PushConstants {
|
||||
$(pub $pc_f: $pc_t,)*
|
||||
}
|
||||
|
||||
pub struct CustomPipeline {
|
||||
inner: UnsafePipelineLayout
|
||||
}
|
||||
@ -44,8 +51,14 @@ macro_rules! pipeline_layout {
|
||||
),*
|
||||
];
|
||||
|
||||
let push_constants = if mem::size_of::<PushConstants>() >= 1 {
|
||||
Some((0, mem::size_of::<PushConstants>(), ShaderStages::all()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let inner = unsafe {
|
||||
try!(UnsafePipelineLayout::new(device, layouts.iter()))
|
||||
try!(UnsafePipelineLayout::new(device, layouts.iter(), push_constants))
|
||||
};
|
||||
|
||||
Ok(Arc::new(CustomPipeline {
|
||||
@ -85,6 +98,10 @@ macro_rules! pipeline_layout {
|
||||
pipeline_layout!{__inner__ (0) $($name: {$($field: $ty),*})*}
|
||||
};
|
||||
|
||||
($($name:ident: { $($field:ident: $ty:ty),* }),*) => {
|
||||
pipeline_layout!{ push_constants: {} $(, $name: {$($field: $ty),*})* }
|
||||
};
|
||||
|
||||
(__inner__ ($num:expr) $name:ident: { $($field:ident: $ty:ty),* } $($rest:tt)*) => {
|
||||
pub mod $name {
|
||||
#![allow(unused_imports)]
|
||||
|
@ -18,6 +18,7 @@ use VulkanObject;
|
||||
use VulkanPointers;
|
||||
use vk;
|
||||
|
||||
use descriptor::descriptor::ShaderStages;
|
||||
use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
|
||||
use device::Device;
|
||||
|
||||
@ -33,16 +34,19 @@ impl UnsafePipelineLayout {
|
||||
/// Creates a new `UnsafePipelineLayout`.
|
||||
// TODO: is this function unsafe?
|
||||
#[inline]
|
||||
pub unsafe fn new<'a, I>(device: &Arc<Device>, layouts: I)
|
||||
pub unsafe fn new<'a, I, P>(device: &Arc<Device>, layouts: I, push_constants: P)
|
||||
-> Result<UnsafePipelineLayout, OomError>
|
||||
where I: IntoIterator<Item = &'a Arc<UnsafeDescriptorSetLayout>>
|
||||
where I: IntoIterator<Item = &'a Arc<UnsafeDescriptorSetLayout>>,
|
||||
P: IntoIterator<Item = (usize, usize, ShaderStages)>,
|
||||
{
|
||||
UnsafePipelineLayout::new_inner(device, layouts.into_iter().map(|e| e.clone()).collect())
|
||||
UnsafePipelineLayout::new_inner(device, layouts.into_iter().map(|e| e.clone()).collect(),
|
||||
push_constants.into_iter().collect())
|
||||
}
|
||||
|
||||
// TODO: is this function unsafe?
|
||||
unsafe fn new_inner(device: &Arc<Device>,
|
||||
layouts: SmallVec<[Arc<UnsafeDescriptorSetLayout>; 16]>)
|
||||
layouts: SmallVec<[Arc<UnsafeDescriptorSetLayout>; 16]>,
|
||||
push_constants: SmallVec<[(usize, usize, ShaderStages); 8]>)
|
||||
-> Result<UnsafePipelineLayout, OomError>
|
||||
{
|
||||
let vk = device.pointers();
|
||||
@ -51,6 +55,21 @@ impl UnsafePipelineLayout {
|
||||
let layouts_ids = layouts.iter().map(|l| l.internal_object())
|
||||
.collect::<SmallVec<[_; 16]>>();
|
||||
|
||||
let push_constants = push_constants.iter().map(|pc| {
|
||||
// TODO: error
|
||||
assert!(pc.2 != ShaderStages::none());
|
||||
assert!(pc.1 > 0);
|
||||
assert!((pc.1 % 4) == 0);
|
||||
assert!(pc.0 + pc.1 <=
|
||||
device.physical_device().limits().max_push_constants_size() as usize);
|
||||
|
||||
vk::PushConstantRange {
|
||||
stageFlags: pc.2.into(),
|
||||
offset: pc.0 as u32,
|
||||
size: pc.1 as u32,
|
||||
}
|
||||
}).collect::<SmallVec<[_; 8]>>();
|
||||
|
||||
let layout = {
|
||||
let infos = vk::PipelineLayoutCreateInfo {
|
||||
sType: vk::STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
@ -58,8 +77,8 @@ impl UnsafePipelineLayout {
|
||||
flags: 0, // reserved
|
||||
setLayoutCount: layouts_ids.len() as u32,
|
||||
pSetLayouts: layouts_ids.as_ptr(),
|
||||
pushConstantRangeCount: 0, // TODO: unimplemented
|
||||
pPushConstantRanges: ptr::null(), // TODO: unimplemented
|
||||
pushConstantRangeCount: push_constants.len() as u32,
|
||||
pPushConstantRanges: push_constants.as_ptr(),
|
||||
};
|
||||
|
||||
let mut output = mem::uninitialized();
|
||||
|
Loading…
Reference in New Issue
Block a user