vulkano/examples/interactive-fractal/place_over_frame.rs
marc0246 4c515a81cb
Improve the examples' directory structure (#2375)
* Make each example its own workspace member

* Fix runtime-shader example

* Fix shader-include example

* Fix teapot example

* Fix `run_all.sh`

* Fix output files getting saved in cwd

* Fix spelling for examples readme filename

* Remove wrong leftover dependencies for gl-interop

* Fix pipeline-cache example

* Clearer .gitignore

* Help cargo be less useless
2023-10-29 18:46:14 +01:00

143 lines
4.7 KiB
Rust

// Copyright (c) 2021 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
use crate::pixels_draw_pipeline::PixelsDrawPipeline;
use std::sync::Arc;
use vulkano::{
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
RenderPassBeginInfo, SubpassBeginInfo, SubpassContents,
},
descriptor_set::allocator::StandardDescriptorSetAllocator,
device::Queue,
format::Format,
image::view::ImageView,
memory::allocator::StandardMemoryAllocator,
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
sync::GpuFuture,
};
/// A render pass which places an incoming image over frame filling it.
pub struct RenderPassPlaceOverFrame {
gfx_queue: Arc<Queue>,
render_pass: Arc<RenderPass>,
pixels_draw_pipeline: PixelsDrawPipeline,
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
}
impl RenderPassPlaceOverFrame {
pub fn new(
gfx_queue: Arc<Queue>,
memory_allocator: Arc<StandardMemoryAllocator>,
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
output_format: Format,
) -> RenderPassPlaceOverFrame {
let render_pass = vulkano::single_pass_renderpass!(
gfx_queue.device().clone(),
attachments: {
color: {
format: output_format,
samples: 1,
load_op: Clear,
store_op: Store,
},
},
pass: {
color: [color],
depth_stencil: {},
},
)
.unwrap();
let subpass = Subpass::from(render_pass.clone(), 0).unwrap();
let pixels_draw_pipeline = PixelsDrawPipeline::new(
gfx_queue.clone(),
subpass,
memory_allocator,
command_buffer_allocator.clone(),
descriptor_set_allocator,
);
RenderPassPlaceOverFrame {
gfx_queue,
render_pass,
pixels_draw_pipeline,
command_buffer_allocator,
}
}
/// Places the view exactly over the target swapchain image. The texture draw pipeline uses a
/// quad onto which it places the view.
pub fn render<F>(
&self,
before_future: F,
view: Arc<ImageView>,
target: Arc<ImageView>,
) -> Box<dyn GpuFuture>
where
F: GpuFuture + 'static,
{
// Get dimensions.
let img_dims: [u32; 2] = target.image().extent()[0..2].try_into().unwrap();
// Create framebuffer (must be in same order as render pass description in `new`.
let framebuffer = Framebuffer::new(
self.render_pass.clone(),
FramebufferCreateInfo {
attachments: vec![target],
..Default::default()
},
)
.unwrap();
// Create primary command buffer builder.
let mut command_buffer_builder = AutoCommandBufferBuilder::primary(
self.command_buffer_allocator.as_ref(),
self.gfx_queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
// Begin render pass.
command_buffer_builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0; 4].into())],
..RenderPassBeginInfo::framebuffer(framebuffer)
},
SubpassBeginInfo {
contents: SubpassContents::SecondaryCommandBuffers,
..Default::default()
},
)
.unwrap();
// Create secondary command buffer from texture pipeline & send draw commands.
let cb = self.pixels_draw_pipeline.draw(img_dims, view);
// Execute above commands (subpass).
command_buffer_builder.execute_commands(cb).unwrap();
// End render pass.
command_buffer_builder
.end_render_pass(Default::default())
.unwrap();
// Build command buffer.
let command_buffer = command_buffer_builder.build().unwrap();
// Execute primary command buffer.
let after_future = before_future
.then_execute(self.gfx_queue.clone(), command_buffer)
.unwrap();
after_future.boxed()
}
}