mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-22 06:45:23 +00:00
Avoid allocating a DynamicState every frame (#1008)
* Avoid allocating a DynamicState every frame * Don't mutate the DynamicState * Undo DynamicState::dynamic_state doc change
This commit is contained in:
parent
175763a953
commit
b0832072fc
@ -5,6 +5,7 @@
|
|||||||
- Allow custom implementations of `RenderPassDesc` to specify `VK_SUBPASS_EXTERNAL` as a dependency source or destination
|
- Allow custom implementations of `RenderPassDesc` to specify `VK_SUBPASS_EXTERNAL` as a dependency source or destination
|
||||||
- Added `vulkano_win::create_vk_surface` which allows creating a surface safely without taking ownership of
|
- Added `vulkano_win::create_vk_surface` which allows creating a surface safely without taking ownership of
|
||||||
the window.
|
the window.
|
||||||
|
- `AutoCommandBufferBuilder::draw` and friends no longer consume the `DynamicState` argument, allowing reuse between calls.
|
||||||
|
|
||||||
# Version 0.9.0 (2018-03-13)
|
# Version 0.9.0 (2018-03-13)
|
||||||
|
|
||||||
|
@ -145,6 +145,16 @@ fn main() {
|
|||||||
|
|
||||||
let mut previous_frame_end = Box::new(tex_future) as Box<GpuFuture>;
|
let mut previous_frame_end = Box::new(tex_future) as Box<GpuFuture>;
|
||||||
|
|
||||||
|
let mut dynamic_state = vulkano::command_buffer::DynamicState {
|
||||||
|
line_width: None,
|
||||||
|
viewports: Some(vec![vulkano::pipeline::viewport::Viewport {
|
||||||
|
origin: [0.0, 0.0],
|
||||||
|
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
|
||||||
|
depth_range: 0.0 .. 1.0,
|
||||||
|
}]),
|
||||||
|
scissors: None,
|
||||||
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
previous_frame_end.cleanup_finished();
|
previous_frame_end.cleanup_finished();
|
||||||
if recreate_swapchain {
|
if recreate_swapchain {
|
||||||
@ -166,6 +176,12 @@ fn main() {
|
|||||||
|
|
||||||
framebuffers = None;
|
framebuffers = None;
|
||||||
|
|
||||||
|
dynamic_state.viewports = Some(vec![vulkano::pipeline::viewport::Viewport {
|
||||||
|
origin: [0.0, 0.0],
|
||||||
|
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
|
||||||
|
depth_range: 0.0 .. 1.0,
|
||||||
|
}]);
|
||||||
|
|
||||||
recreate_swapchain = false;
|
recreate_swapchain = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,15 +210,7 @@ fn main() {
|
|||||||
framebuffers.as_ref().unwrap()[image_num].clone(), false,
|
framebuffers.as_ref().unwrap()[image_num].clone(), false,
|
||||||
vec![[0.0, 0.0, 1.0, 1.0].into()]).unwrap()
|
vec![[0.0, 0.0, 1.0, 1.0].into()]).unwrap()
|
||||||
.draw(pipeline.clone(),
|
.draw(pipeline.clone(),
|
||||||
vulkano::command_buffer::DynamicState {
|
&dynamic_state,
|
||||||
line_width: None,
|
|
||||||
viewports: Some(vec![vulkano::pipeline::viewport::Viewport {
|
|
||||||
origin: [0.0, 0.0],
|
|
||||||
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
|
|
||||||
depth_range: 0.0 .. 1.0,
|
|
||||||
}]),
|
|
||||||
scissors: None,
|
|
||||||
},
|
|
||||||
vertex_buffer.clone(),
|
vertex_buffer.clone(),
|
||||||
set.clone(), ()).unwrap()
|
set.clone(), ()).unwrap()
|
||||||
.end_render_pass().unwrap()
|
.end_render_pass().unwrap()
|
||||||
|
@ -448,7 +448,7 @@ fn main() {
|
|||||||
).unwrap()
|
).unwrap()
|
||||||
.draw(
|
.draw(
|
||||||
graphics_pipeline.clone(),
|
graphics_pipeline.clone(),
|
||||||
DynamicState::none(),
|
&DynamicState::none(),
|
||||||
vertex_buffer.clone(),
|
vertex_buffer.clone(),
|
||||||
(),
|
(),
|
||||||
(),
|
(),
|
||||||
|
@ -138,6 +138,16 @@ fn main() {
|
|||||||
let mut previous_frame = Box::new(vulkano::sync::now(device.clone())) as Box<GpuFuture>;
|
let mut previous_frame = Box::new(vulkano::sync::now(device.clone())) as Box<GpuFuture>;
|
||||||
let rotation_start = std::time::Instant::now();
|
let rotation_start = std::time::Instant::now();
|
||||||
|
|
||||||
|
let mut dynamic_state = vulkano::command_buffer::DynamicState {
|
||||||
|
line_width: None,
|
||||||
|
viewports: Some(vec![vulkano::pipeline::viewport::Viewport {
|
||||||
|
origin: [0.0, 0.0],
|
||||||
|
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
|
||||||
|
depth_range: 0.0 .. 1.0,
|
||||||
|
}]),
|
||||||
|
scissors: None,
|
||||||
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
previous_frame.cleanup_finished();
|
previous_frame.cleanup_finished();
|
||||||
|
|
||||||
@ -165,6 +175,12 @@ fn main() {
|
|||||||
|
|
||||||
proj = cgmath::perspective(cgmath::Rad(std::f32::consts::FRAC_PI_2), { dimensions[0] as f32 / dimensions[1] as f32 }, 0.01, 100.0);
|
proj = cgmath::perspective(cgmath::Rad(std::f32::consts::FRAC_PI_2), { dimensions[0] as f32 / dimensions[1] as f32 }, 0.01, 100.0);
|
||||||
|
|
||||||
|
dynamic_state.viewports = Some(vec![vulkano::pipeline::viewport::Viewport {
|
||||||
|
origin: [0.0, 0.0],
|
||||||
|
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
|
||||||
|
depth_range: 0.0 .. 1.0,
|
||||||
|
}]);
|
||||||
|
|
||||||
recreate_swapchain = false;
|
recreate_swapchain = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,15 +232,7 @@ fn main() {
|
|||||||
]).unwrap()
|
]).unwrap()
|
||||||
.draw_indexed(
|
.draw_indexed(
|
||||||
pipeline.clone(),
|
pipeline.clone(),
|
||||||
vulkano::command_buffer::DynamicState {
|
&dynamic_state,
|
||||||
line_width: None,
|
|
||||||
viewports: Some(vec![vulkano::pipeline::viewport::Viewport {
|
|
||||||
origin: [0.0, 0.0],
|
|
||||||
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
|
|
||||||
depth_range: 0.0 .. 1.0,
|
|
||||||
}]),
|
|
||||||
scissors: None,
|
|
||||||
},
|
|
||||||
(vertex_buffer.clone(), normals_buffer.clone()),
|
(vertex_buffer.clone(), normals_buffer.clone()),
|
||||||
index_buffer.clone(), set.clone(), ()).unwrap()
|
index_buffer.clone(), set.clone(), ()).unwrap()
|
||||||
.end_render_pass().unwrap()
|
.end_render_pass().unwrap()
|
||||||
|
@ -330,6 +330,16 @@ void main() {
|
|||||||
// that, we store the submission of the previous frame here.
|
// that, we store the submission of the previous frame here.
|
||||||
let mut previous_frame_end = Box::new(now(device.clone())) as Box<GpuFuture>;
|
let mut previous_frame_end = Box::new(now(device.clone())) as Box<GpuFuture>;
|
||||||
|
|
||||||
|
let mut dynamic_state = DynamicState {
|
||||||
|
line_width: None,
|
||||||
|
viewports: Some(vec![Viewport {
|
||||||
|
origin: [0.0, 0.0],
|
||||||
|
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
|
||||||
|
depth_range: 0.0 .. 1.0,
|
||||||
|
}]),
|
||||||
|
scissors: None,
|
||||||
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// It is important to call this function from time to time, otherwise resources will keep
|
// It is important to call this function from time to time, otherwise resources will keep
|
||||||
// accumulating and you will eventually reach an out of memory error.
|
// accumulating and you will eventually reach an out of memory error.
|
||||||
@ -359,6 +369,12 @@ void main() {
|
|||||||
|
|
||||||
framebuffers = None;
|
framebuffers = None;
|
||||||
|
|
||||||
|
dynamic_state.viewports = Some(vec![Viewport {
|
||||||
|
origin: [0.0, 0.0],
|
||||||
|
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
|
||||||
|
depth_range: 0.0 .. 1.0,
|
||||||
|
}]);
|
||||||
|
|
||||||
recreate_swapchain = false;
|
recreate_swapchain = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,16 +432,7 @@ void main() {
|
|||||||
// The last two parameters contain the list of resources to pass to the shaders.
|
// The last two parameters contain the list of resources to pass to the shaders.
|
||||||
// Since we used an `EmptyPipeline` object, the objects have to be `()`.
|
// Since we used an `EmptyPipeline` object, the objects have to be `()`.
|
||||||
.draw(pipeline.clone(),
|
.draw(pipeline.clone(),
|
||||||
DynamicState {
|
&dynamic_state,
|
||||||
line_width: None,
|
|
||||||
// TODO: Find a way to do this without having to dynamically allocate a Vec every frame.
|
|
||||||
viewports: Some(vec![Viewport {
|
|
||||||
origin: [0.0, 0.0],
|
|
||||||
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
|
|
||||||
depth_range: 0.0 .. 1.0,
|
|
||||||
}]),
|
|
||||||
scissors: None,
|
|
||||||
},
|
|
||||||
vertex_buffer.clone(), (), ())
|
vertex_buffer.clone(), (), ())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
||||||
|
@ -981,7 +981,7 @@ impl<P> AutoCommandBufferBuilder<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn draw<V, Gp, S, Pc>(mut self, pipeline: Gp, dynamic: DynamicState, vertices: V, sets: S,
|
pub fn draw<V, Gp, S, Pc>(mut self, pipeline: Gp, dynamic: &DynamicState, vertices: V, sets: S,
|
||||||
constants: Pc)
|
constants: Pc)
|
||||||
-> Result<Self, DrawError>
|
-> Result<Self, DrawError>
|
||||||
where Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
where Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||||
@ -991,7 +991,7 @@ impl<P> AutoCommandBufferBuilder<P> {
|
|||||||
// TODO: must check that pipeline is compatible with render pass
|
// TODO: must check that pipeline is compatible with render pass
|
||||||
|
|
||||||
self.ensure_inside_render_pass_inline(&pipeline)?;
|
self.ensure_inside_render_pass_inline(&pipeline)?;
|
||||||
check_dynamic_state_validity(&pipeline, &dynamic)?;
|
check_dynamic_state_validity(&pipeline, dynamic)?;
|
||||||
check_push_constants_validity(&pipeline, &constants)?;
|
check_push_constants_validity(&pipeline, &constants)?;
|
||||||
check_descriptor_sets_validity(&pipeline, &sets)?;
|
check_descriptor_sets_validity(&pipeline, &sets)?;
|
||||||
let vb_infos = check_vertex_buffers(&pipeline, vertices)?;
|
let vb_infos = check_vertex_buffers(&pipeline, vertices)?;
|
||||||
@ -1005,7 +1005,7 @@ impl<P> AutoCommandBufferBuilder<P> {
|
|||||||
let dynamic = self.state_cacher.dynamic_state(dynamic);
|
let dynamic = self.state_cacher.dynamic_state(dynamic);
|
||||||
|
|
||||||
push_constants(&mut self.inner, pipeline.clone(), constants);
|
push_constants(&mut self.inner, pipeline.clone(), constants);
|
||||||
set_state(&mut self.inner, dynamic);
|
set_state(&mut self.inner, &dynamic);
|
||||||
descriptor_sets(&mut self.inner,
|
descriptor_sets(&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
true,
|
true,
|
||||||
@ -1026,7 +1026,7 @@ impl<P> AutoCommandBufferBuilder<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn draw_indexed<V, Gp, S, Pc, Ib, I>(mut self, pipeline: Gp, dynamic: DynamicState,
|
pub fn draw_indexed<V, Gp, S, Pc, Ib, I>(mut self, pipeline: Gp, dynamic: &DynamicState,
|
||||||
vertices: V, index_buffer: Ib, sets: S, constants: Pc)
|
vertices: V, index_buffer: Ib, sets: S, constants: Pc)
|
||||||
-> Result<Self, DrawIndexedError>
|
-> Result<Self, DrawIndexedError>
|
||||||
where Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
where Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||||
@ -1039,7 +1039,7 @@ impl<P> AutoCommandBufferBuilder<P> {
|
|||||||
|
|
||||||
self.ensure_inside_render_pass_inline(&pipeline)?;
|
self.ensure_inside_render_pass_inline(&pipeline)?;
|
||||||
let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
|
let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
|
||||||
check_dynamic_state_validity(&pipeline, &dynamic)?;
|
check_dynamic_state_validity(&pipeline, dynamic)?;
|
||||||
check_push_constants_validity(&pipeline, &constants)?;
|
check_push_constants_validity(&pipeline, &constants)?;
|
||||||
check_descriptor_sets_validity(&pipeline, &sets)?;
|
check_descriptor_sets_validity(&pipeline, &sets)?;
|
||||||
let vb_infos = check_vertex_buffers(&pipeline, vertices)?;
|
let vb_infos = check_vertex_buffers(&pipeline, vertices)?;
|
||||||
@ -1059,7 +1059,7 @@ impl<P> AutoCommandBufferBuilder<P> {
|
|||||||
let dynamic = self.state_cacher.dynamic_state(dynamic);
|
let dynamic = self.state_cacher.dynamic_state(dynamic);
|
||||||
|
|
||||||
push_constants(&mut self.inner, pipeline.clone(), constants);
|
push_constants(&mut self.inner, pipeline.clone(), constants);
|
||||||
set_state(&mut self.inner, dynamic);
|
set_state(&mut self.inner, &dynamic);
|
||||||
descriptor_sets(&mut self.inner,
|
descriptor_sets(&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
true,
|
true,
|
||||||
@ -1079,7 +1079,7 @@ impl<P> AutoCommandBufferBuilder<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn draw_indirect<V, Gp, S, Pc, Ib>(mut self, pipeline: Gp, dynamic: DynamicState,
|
pub fn draw_indirect<V, Gp, S, Pc, Ib>(mut self, pipeline: Gp, dynamic: &DynamicState,
|
||||||
vertices: V, indirect_buffer: Ib, sets: S, constants: Pc)
|
vertices: V, indirect_buffer: Ib, sets: S, constants: Pc)
|
||||||
-> Result<Self, DrawIndirectError>
|
-> Result<Self, DrawIndirectError>
|
||||||
where Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
where Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
|
||||||
@ -1094,7 +1094,7 @@ impl<P> AutoCommandBufferBuilder<P> {
|
|||||||
// TODO: must check that pipeline is compatible with render pass
|
// TODO: must check that pipeline is compatible with render pass
|
||||||
|
|
||||||
self.ensure_inside_render_pass_inline(&pipeline)?;
|
self.ensure_inside_render_pass_inline(&pipeline)?;
|
||||||
check_dynamic_state_validity(&pipeline, &dynamic)?;
|
check_dynamic_state_validity(&pipeline, dynamic)?;
|
||||||
check_push_constants_validity(&pipeline, &constants)?;
|
check_push_constants_validity(&pipeline, &constants)?;
|
||||||
check_descriptor_sets_validity(&pipeline, &sets)?;
|
check_descriptor_sets_validity(&pipeline, &sets)?;
|
||||||
let vb_infos = check_vertex_buffers(&pipeline, vertices)?;
|
let vb_infos = check_vertex_buffers(&pipeline, vertices)?;
|
||||||
@ -1110,7 +1110,7 @@ impl<P> AutoCommandBufferBuilder<P> {
|
|||||||
let dynamic = self.state_cacher.dynamic_state(dynamic);
|
let dynamic = self.state_cacher.dynamic_state(dynamic);
|
||||||
|
|
||||||
push_constants(&mut self.inner, pipeline.clone(), constants);
|
push_constants(&mut self.inner, pipeline.clone(), constants);
|
||||||
set_state(&mut self.inner, dynamic);
|
set_state(&mut self.inner, &dynamic);
|
||||||
descriptor_sets(&mut self.inner,
|
descriptor_sets(&mut self.inner,
|
||||||
&mut self.state_cacher,
|
&mut self.state_cacher,
|
||||||
true,
|
true,
|
||||||
@ -1304,7 +1304,7 @@ unsafe fn push_constants<P, Pl, Pc>(destination: &mut SyncCommandBufferBuilder<P
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shortcut function to change the state of the pipeline.
|
// Shortcut function to change the state of the pipeline.
|
||||||
unsafe fn set_state<P>(destination: &mut SyncCommandBufferBuilder<P>, dynamic: DynamicState) {
|
unsafe fn set_state<P>(destination: &mut SyncCommandBufferBuilder<P>, dynamic: &DynamicState) {
|
||||||
if let Some(line_width) = dynamic.line_width {
|
if let Some(line_width) = dynamic.line_width {
|
||||||
destination.set_line_width(line_width);
|
destination.set_line_width(line_width);
|
||||||
}
|
}
|
||||||
|
@ -91,14 +91,17 @@ impl StateCacher {
|
|||||||
///
|
///
|
||||||
/// This function also updates the state cacher. The state cacher assumes that the state
|
/// This function also updates the state cacher. The state cacher assumes that the state
|
||||||
/// changes are going to be performed after this function returns.
|
/// changes are going to be performed after this function returns.
|
||||||
pub fn dynamic_state(&mut self, mut incoming: DynamicState) -> DynamicState {
|
pub fn dynamic_state(&mut self, incoming: &DynamicState) -> DynamicState {
|
||||||
|
let mut changed = DynamicState::none();
|
||||||
|
|
||||||
macro_rules! cmp {
|
macro_rules! cmp {
|
||||||
($field:ident) => (
|
($field:ident) => (
|
||||||
if self.dynamic_state.$field == incoming.$field {
|
if self.dynamic_state.$field != incoming.$field {
|
||||||
incoming.$field = None;
|
changed.$field = incoming.$field.clone();
|
||||||
} else if incoming.$field.is_some() {
|
if incoming.$field.is_some() {
|
||||||
self.dynamic_state.$field = incoming.$field.clone();
|
self.dynamic_state.$field = incoming.$field.clone();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +109,7 @@ impl StateCacher {
|
|||||||
cmp!(viewports);
|
cmp!(viewports);
|
||||||
cmp!(scissors);
|
cmp!(scissors);
|
||||||
|
|
||||||
incoming
|
changed
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Starts the process of comparing a list of descriptor sets to the descriptor sets currently
|
/// Starts the process of comparing a list of descriptor sets to the descriptor sets currently
|
||||||
|
Loading…
Reference in New Issue
Block a user