2023-03-24 13:03:49 +00:00
|
|
|
use crate::app::App;
|
2022-10-27 18:59:47 +00:00
|
|
|
use std::sync::Arc;
|
2022-03-06 19:30:49 +00:00
|
|
|
use vulkano::{
|
2022-05-29 16:53:36 +00:00
|
|
|
command_buffer::{
|
2023-12-20 12:04:01 +00:00
|
|
|
allocator::StandardCommandBufferAllocator, CommandBuffer, CommandBufferBeginInfo,
|
|
|
|
CommandBufferInheritanceInfo, CommandBufferLevel, CommandBufferUsage,
|
|
|
|
RecordingCommandBuffer,
|
2022-10-05 09:09:26 +00:00
|
|
|
},
|
|
|
|
descriptor_set::{
|
2023-11-12 16:17:37 +00:00
|
|
|
allocator::StandardDescriptorSetAllocator, DescriptorSet, WriteDescriptorSet,
|
2022-05-29 16:53:36 +00:00
|
|
|
},
|
2022-03-06 19:30:49 +00:00
|
|
|
device::Queue,
|
2023-06-30 09:21:18 +00:00
|
|
|
image::{
|
|
|
|
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo, SamplerMipmapMode},
|
2023-07-03 20:37:29 +00:00
|
|
|
view::ImageView,
|
2023-06-30 09:21:18 +00:00
|
|
|
},
|
2022-03-06 19:30:49 +00:00
|
|
|
pipeline::{
|
|
|
|
graphics::{
|
2023-10-07 14:46:03 +00:00
|
|
|
color_blend::{ColorBlendAttachmentState, ColorBlendState},
|
2022-03-06 19:30:49 +00:00
|
|
|
input_assembly::InputAssemblyState,
|
2023-04-18 18:53:08 +00:00
|
|
|
multisample::MultisampleState,
|
|
|
|
rasterization::RasterizationState,
|
2024-01-16 18:30:14 +00:00
|
|
|
vertex_input::VertexInputState,
|
2022-03-06 19:30:49 +00:00
|
|
|
viewport::{Viewport, ViewportState},
|
2023-04-22 18:46:22 +00:00
|
|
|
GraphicsPipelineCreateInfo,
|
2022-03-06 19:30:49 +00:00
|
|
|
},
|
2023-04-22 18:46:22 +00:00
|
|
|
layout::PipelineDescriptorSetLayoutCreateInfo,
|
2023-10-07 14:46:03 +00:00
|
|
|
DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout,
|
2023-06-25 18:08:27 +00:00
|
|
|
PipelineShaderStageCreateInfo,
|
2022-03-06 19:30:49 +00:00
|
|
|
},
|
|
|
|
render_pass::Subpass,
|
2022-02-02 16:21:32 +00:00
|
|
|
};
|
|
|
|
|
2023-03-05 18:56:35 +00:00
|
|
|
/// A subpass pipeline that fills a quad over the frame.
|
2022-02-02 16:21:32 +00:00
|
|
|
pub struct PixelsDrawPipeline {
|
|
|
|
gfx_queue: Arc<Queue>,
|
2022-05-29 16:53:36 +00:00
|
|
|
subpass: Subpass,
|
2022-02-02 16:21:32 +00:00
|
|
|
pipeline: Arc<GraphicsPipeline>,
|
2022-10-27 18:59:47 +00:00
|
|
|
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
|
|
|
|
descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
|
2022-02-02 16:21:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl PixelsDrawPipeline {
|
2023-03-24 13:03:49 +00:00
|
|
|
pub fn new(app: &App, gfx_queue: Arc<Queue>, subpass: Subpass) -> PixelsDrawPipeline {
|
2022-02-02 16:21:32 +00:00
|
|
|
let pipeline = {
|
2023-04-22 18:46:22 +00:00
|
|
|
let device = gfx_queue.device();
|
|
|
|
let vs = vs::load(device.clone())
|
2023-04-18 18:53:08 +00:00
|
|
|
.expect("failed to create shader module")
|
|
|
|
.entry_point("main")
|
|
|
|
.expect("shader entry point not found");
|
2023-04-22 18:46:22 +00:00
|
|
|
let fs = fs::load(device.clone())
|
2023-04-18 18:53:08 +00:00
|
|
|
.expect("failed to create shader module")
|
|
|
|
.entry_point("main")
|
|
|
|
.expect("shader entry point not found");
|
2023-04-22 18:46:22 +00:00
|
|
|
let stages = [
|
2023-06-25 18:08:27 +00:00
|
|
|
PipelineShaderStageCreateInfo::new(vs),
|
|
|
|
PipelineShaderStageCreateInfo::new(fs),
|
2023-04-22 18:46:22 +00:00
|
|
|
];
|
|
|
|
let layout = PipelineLayout::new(
|
|
|
|
device.clone(),
|
|
|
|
PipelineDescriptorSetLayoutCreateInfo::from_stages(&stages)
|
|
|
|
.into_pipeline_layout_create_info(device.clone())
|
|
|
|
.unwrap(),
|
|
|
|
)
|
|
|
|
.unwrap();
|
2023-07-03 20:37:29 +00:00
|
|
|
|
2023-04-22 18:46:22 +00:00
|
|
|
GraphicsPipeline::new(
|
|
|
|
device.clone(),
|
|
|
|
None,
|
|
|
|
GraphicsPipelineCreateInfo {
|
|
|
|
stages: stages.into_iter().collect(),
|
2024-01-16 18:30:14 +00:00
|
|
|
vertex_input_state: Some(VertexInputState::default()),
|
2023-04-22 18:46:22 +00:00
|
|
|
input_assembly_state: Some(InputAssemblyState::default()),
|
2023-10-07 14:46:03 +00:00
|
|
|
viewport_state: Some(ViewportState::default()),
|
2023-04-22 18:46:22 +00:00
|
|
|
rasterization_state: Some(RasterizationState::default()),
|
|
|
|
multisample_state: Some(MultisampleState::default()),
|
2023-10-07 14:46:03 +00:00
|
|
|
color_blend_state: Some(ColorBlendState::with_attachment_states(
|
|
|
|
subpass.num_color_attachments(),
|
|
|
|
ColorBlendAttachmentState::default(),
|
|
|
|
)),
|
|
|
|
dynamic_state: [DynamicState::Viewport].into_iter().collect(),
|
2023-04-22 18:46:22 +00:00
|
|
|
subpass: Some(subpass.clone().into()),
|
|
|
|
..GraphicsPipelineCreateInfo::layout(layout)
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.unwrap()
|
2022-02-02 16:21:32 +00:00
|
|
|
};
|
2022-10-05 09:09:26 +00:00
|
|
|
|
2022-02-02 16:21:32 +00:00
|
|
|
PixelsDrawPipeline {
|
|
|
|
gfx_queue,
|
2022-05-29 16:53:36 +00:00
|
|
|
subpass,
|
2022-02-02 16:21:32 +00:00
|
|
|
pipeline,
|
2023-03-24 13:03:49 +00:00
|
|
|
command_buffer_allocator: app.command_buffer_allocator.clone(),
|
|
|
|
descriptor_set_allocator: app.descriptor_set_allocator.clone(),
|
2022-02-02 16:21:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-12 16:17:37 +00:00
|
|
|
fn create_image_sampler_nearest(&self, image: Arc<ImageView>) -> Arc<DescriptorSet> {
|
2023-12-28 19:32:13 +00:00
|
|
|
let layout = &self.pipeline.layout().set_layouts()[0];
|
2022-02-26 08:46:53 +00:00
|
|
|
let sampler = Sampler::new(
|
|
|
|
self.gfx_queue.device().clone(),
|
|
|
|
SamplerCreateInfo {
|
|
|
|
mag_filter: Filter::Nearest,
|
|
|
|
min_filter: Filter::Nearest,
|
|
|
|
address_mode: [SamplerAddressMode::Repeat; 3],
|
|
|
|
mipmap_mode: SamplerMipmapMode::Nearest,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.unwrap();
|
2022-02-02 16:21:32 +00:00
|
|
|
|
2023-11-12 16:17:37 +00:00
|
|
|
DescriptorSet::new(
|
2023-11-12 14:10:22 +00:00
|
|
|
self.descriptor_set_allocator.clone(),
|
2022-02-02 16:21:32 +00:00
|
|
|
layout.clone(),
|
2023-10-08 12:10:19 +00:00
|
|
|
[
|
|
|
|
WriteDescriptorSet::sampler(0, sampler),
|
|
|
|
WriteDescriptorSet::image_view(1, image),
|
|
|
|
],
|
2023-06-03 12:56:27 +00:00
|
|
|
[],
|
2022-02-02 16:21:32 +00:00
|
|
|
)
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
|
2023-03-05 18:56:35 +00:00
|
|
|
/// Draws input `image` over a quad of size -1.0 to 1.0.
|
2023-12-20 12:04:01 +00:00
|
|
|
pub fn draw(&self, viewport_dimensions: [u32; 2], image: Arc<ImageView>) -> Arc<CommandBuffer> {
|
|
|
|
let mut builder = RecordingCommandBuffer::new(
|
2023-11-14 16:57:43 +00:00
|
|
|
self.command_buffer_allocator.clone(),
|
2022-09-10 06:00:08 +00:00
|
|
|
self.gfx_queue.queue_family_index(),
|
2023-12-20 12:04:01 +00:00
|
|
|
CommandBufferLevel::Secondary,
|
|
|
|
CommandBufferBeginInfo {
|
|
|
|
usage: CommandBufferUsage::MultipleSubmit,
|
|
|
|
inheritance_info: Some(CommandBufferInheritanceInfo {
|
|
|
|
render_pass: Some(self.subpass.clone().into()),
|
|
|
|
..Default::default()
|
|
|
|
}),
|
2022-05-29 16:53:36 +00:00
|
|
|
..Default::default()
|
|
|
|
},
|
2022-02-02 16:21:32 +00:00
|
|
|
)
|
|
|
|
.unwrap();
|
2023-12-25 03:01:16 +00:00
|
|
|
|
2022-02-02 16:21:32 +00:00
|
|
|
builder
|
|
|
|
.set_viewport(
|
|
|
|
0,
|
|
|
|
[Viewport {
|
2023-06-25 18:08:27 +00:00
|
|
|
offset: [0.0, 0.0],
|
|
|
|
extent: [viewport_dimensions[0] as f32, viewport_dimensions[1] as f32],
|
|
|
|
depth_range: 0.0..=1.0,
|
2023-05-18 11:03:37 +00:00
|
|
|
}]
|
|
|
|
.into_iter()
|
|
|
|
.collect(),
|
2022-02-02 16:21:32 +00:00
|
|
|
)
|
2023-08-04 18:55:16 +00:00
|
|
|
.unwrap()
|
2022-02-02 16:21:32 +00:00
|
|
|
.bind_pipeline_graphics(self.pipeline.clone())
|
2023-08-04 18:55:16 +00:00
|
|
|
.unwrap()
|
2022-02-02 16:21:32 +00:00
|
|
|
.bind_descriptor_sets(
|
|
|
|
PipelineBindPoint::Graphics,
|
|
|
|
self.pipeline.layout().clone(),
|
|
|
|
0,
|
2023-12-25 03:01:16 +00:00
|
|
|
self.create_image_sampler_nearest(image),
|
2022-02-02 16:21:32 +00:00
|
|
|
)
|
|
|
|
.unwrap();
|
2023-12-25 03:01:16 +00:00
|
|
|
|
|
|
|
unsafe {
|
2024-01-16 18:30:14 +00:00
|
|
|
builder.draw(6, 1, 0, 0).unwrap();
|
2023-12-25 03:01:16 +00:00
|
|
|
}
|
|
|
|
|
2023-12-09 11:24:52 +00:00
|
|
|
builder.end().unwrap()
|
2022-02-02 16:21:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mod vs {
|
|
|
|
vulkano_shaders::shader! {
|
|
|
|
ty: "vertex",
|
2023-03-05 18:56:35 +00:00
|
|
|
src: r"
|
|
|
|
#version 450
|
2024-01-16 18:30:14 +00:00
|
|
|
|
|
|
|
const vec2[6] POSITIONS = {
|
|
|
|
vec2(-1.0, -1.0),
|
|
|
|
vec2( 1.0, 1.0),
|
|
|
|
vec2(-1.0, 1.0),
|
|
|
|
vec2(-1.0, -1.0),
|
|
|
|
vec2( 1.0, -1.0),
|
|
|
|
vec2( 1.0, 1.0),
|
|
|
|
};
|
|
|
|
|
|
|
|
const vec2[6] TEX_COORDS = {
|
|
|
|
vec2(0.0, 1.0),
|
|
|
|
vec2(1.0, 0.0),
|
|
|
|
vec2(0.0, 0.0),
|
|
|
|
vec2(0.0, 1.0),
|
|
|
|
vec2(1.0, 1.0),
|
|
|
|
vec2(1.0, 0.0),
|
|
|
|
};
|
2023-03-05 18:56:35 +00:00
|
|
|
|
|
|
|
layout(location = 0) out vec2 f_tex_coords;
|
|
|
|
|
|
|
|
void main() {
|
2024-01-16 18:30:14 +00:00
|
|
|
gl_Position = vec4(POSITIONS[gl_VertexIndex], 0.0, 1.0);
|
|
|
|
f_tex_coords = TEX_COORDS[gl_VertexIndex];
|
2023-03-05 18:56:35 +00:00
|
|
|
}
|
|
|
|
",
|
2022-02-02 16:21:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mod fs {
|
|
|
|
vulkano_shaders::shader! {
|
|
|
|
ty: "fragment",
|
2023-03-05 18:56:35 +00:00
|
|
|
src: r"
|
|
|
|
#version 450
|
|
|
|
layout(location = 0) in vec2 v_tex_coords;
|
2022-02-02 16:21:32 +00:00
|
|
|
|
2023-03-05 18:56:35 +00:00
|
|
|
layout(location = 0) out vec4 f_color;
|
2022-02-02 16:21:32 +00:00
|
|
|
|
2023-10-08 12:10:19 +00:00
|
|
|
layout(set = 0, binding = 0) uniform sampler s;
|
|
|
|
layout(set = 0, binding = 1) uniform texture2D tex;
|
2022-02-02 16:21:32 +00:00
|
|
|
|
2023-03-05 18:56:35 +00:00
|
|
|
void main() {
|
2023-10-08 12:10:19 +00:00
|
|
|
f_color = texture(sampler2D(tex, s), v_tex_coords);
|
2023-03-05 18:56:35 +00:00
|
|
|
}
|
|
|
|
",
|
2022-02-02 16:21:32 +00:00
|
|
|
}
|
|
|
|
}
|