2021-09-13 15:14:54 +00:00
|
|
|
// 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.
|
|
|
|
|
2022-03-06 19:30:49 +00:00
|
|
|
use bytemuck::{Pod, Zeroable};
|
2022-10-27 18:59:47 +00:00
|
|
|
use std::sync::Arc;
|
2022-03-06 19:30:49 +00:00
|
|
|
use vulkano::{
|
2023-01-12 12:56:10 +00:00
|
|
|
buffer::{Buffer, BufferAllocateInfo, BufferUsage, Subbuffer},
|
2022-05-29 16:53:36 +00:00
|
|
|
command_buffer::{
|
2022-10-05 09:09:26 +00:00
|
|
|
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder,
|
|
|
|
CommandBufferInheritanceInfo, CommandBufferUsage, SecondaryAutoCommandBuffer,
|
|
|
|
},
|
|
|
|
descriptor_set::{
|
|
|
|
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
|
2022-05-29 16:53:36 +00:00
|
|
|
},
|
2022-03-06 19:30:49 +00:00
|
|
|
device::Queue,
|
|
|
|
image::ImageViewAbstract,
|
2022-10-26 14:25:01 +00:00
|
|
|
memory::allocator::MemoryAllocator,
|
2022-03-06 19:30:49 +00:00
|
|
|
pipeline::{
|
|
|
|
graphics::{
|
|
|
|
input_assembly::InputAssemblyState,
|
2023-01-03 17:49:12 +00:00
|
|
|
vertex_input::Vertex,
|
2022-03-06 19:30:49 +00:00
|
|
|
viewport::{Viewport, ViewportState},
|
|
|
|
},
|
|
|
|
GraphicsPipeline, Pipeline, PipelineBindPoint,
|
|
|
|
},
|
|
|
|
render_pass::Subpass,
|
|
|
|
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo, SamplerMipmapMode},
|
2021-09-13 15:14:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Vertex for textured quads
|
2021-11-24 14:19:57 +00:00
|
|
|
#[repr(C)]
|
2022-12-28 10:23:36 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)]
|
2021-09-13 15:14:54 +00:00
|
|
|
pub struct TexturedVertex {
|
2022-12-28 10:23:36 +00:00
|
|
|
#[format(R32G32_SFLOAT)]
|
2021-09-13 15:14:54 +00:00
|
|
|
pub position: [f32; 2],
|
2022-12-28 10:23:36 +00:00
|
|
|
#[format(R32G32_SFLOAT)]
|
2021-09-13 15:14:54 +00:00
|
|
|
pub tex_coords: [f32; 2],
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn textured_quad(width: f32, height: f32) -> (Vec<TexturedVertex>, Vec<u32>) {
|
|
|
|
(
|
|
|
|
vec![
|
|
|
|
TexturedVertex {
|
|
|
|
position: [-(width / 2.0), -(height / 2.0)],
|
|
|
|
tex_coords: [0.0, 1.0],
|
|
|
|
},
|
|
|
|
TexturedVertex {
|
|
|
|
position: [-(width / 2.0), height / 2.0],
|
|
|
|
tex_coords: [0.0, 0.0],
|
|
|
|
},
|
|
|
|
TexturedVertex {
|
|
|
|
position: [width / 2.0, height / 2.0],
|
|
|
|
tex_coords: [1.0, 0.0],
|
|
|
|
},
|
|
|
|
TexturedVertex {
|
|
|
|
position: [width / 2.0, -(height / 2.0)],
|
|
|
|
tex_coords: [1.0, 1.0],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
vec![0, 2, 1, 0, 3, 2],
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A subpass pipeline that fills a quad over frame
|
|
|
|
pub struct PixelsDrawPipeline {
|
|
|
|
gfx_queue: Arc<Queue>,
|
2022-05-29 16:53:36 +00:00
|
|
|
subpass: Subpass,
|
2021-09-13 15:14:54 +00:00
|
|
|
pipeline: Arc<GraphicsPipeline>,
|
2022-10-27 18:59:47 +00:00
|
|
|
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
|
|
|
|
descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
|
2023-01-12 12:56:10 +00:00
|
|
|
vertices: Subbuffer<[TexturedVertex]>,
|
|
|
|
indices: Subbuffer<[u32]>,
|
2021-09-13 15:14:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl PixelsDrawPipeline {
|
2022-10-05 09:09:26 +00:00
|
|
|
pub fn new(
|
|
|
|
gfx_queue: Arc<Queue>,
|
|
|
|
subpass: Subpass,
|
2022-10-26 14:25:01 +00:00
|
|
|
memory_allocator: &impl MemoryAllocator,
|
2022-10-27 18:59:47 +00:00
|
|
|
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
|
|
|
|
descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
|
2022-10-05 09:09:26 +00:00
|
|
|
) -> PixelsDrawPipeline {
|
2021-09-13 15:14:54 +00:00
|
|
|
let (vertices, indices) = textured_quad(2.0, 2.0);
|
2023-01-12 12:56:10 +00:00
|
|
|
let vertex_buffer = Buffer::from_iter(
|
2022-10-26 14:25:01 +00:00
|
|
|
memory_allocator,
|
2023-01-12 12:56:10 +00:00
|
|
|
BufferAllocateInfo {
|
|
|
|
buffer_usage: BufferUsage::VERTEX_BUFFER,
|
|
|
|
..Default::default()
|
|
|
|
},
|
2022-03-06 19:30:49 +00:00
|
|
|
vertices,
|
2021-09-13 15:14:54 +00:00
|
|
|
)
|
|
|
|
.unwrap();
|
2023-01-12 12:56:10 +00:00
|
|
|
let index_buffer = Buffer::from_iter(
|
2022-10-26 14:25:01 +00:00
|
|
|
memory_allocator,
|
2023-01-12 12:56:10 +00:00
|
|
|
BufferAllocateInfo {
|
|
|
|
buffer_usage: BufferUsage::INDEX_BUFFER,
|
|
|
|
..Default::default()
|
|
|
|
},
|
2022-03-06 19:30:49 +00:00
|
|
|
indices,
|
2021-09-13 15:14:54 +00:00
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let pipeline = {
|
2021-11-13 15:06:16 +00:00
|
|
|
let vs = vs::load(gfx_queue.device().clone()).expect("failed to create shader module");
|
|
|
|
let fs = fs::load(gfx_queue.device().clone()).expect("failed to create shader module");
|
2021-11-02 20:33:58 +00:00
|
|
|
GraphicsPipeline::start()
|
2023-01-03 17:49:12 +00:00
|
|
|
.vertex_input_state(TexturedVertex::per_vertex())
|
2021-11-13 15:06:16 +00:00
|
|
|
.vertex_shader(vs.entry_point("main").unwrap(), ())
|
2021-11-02 20:33:58 +00:00
|
|
|
.input_assembly_state(InputAssemblyState::new())
|
2021-11-13 15:06:16 +00:00
|
|
|
.fragment_shader(fs.entry_point("main").unwrap(), ())
|
2021-11-02 20:33:58 +00:00
|
|
|
.viewport_state(ViewportState::viewport_dynamic_scissor_irrelevant())
|
2022-05-29 16:53:36 +00:00
|
|
|
.render_pass(subpass.clone())
|
2021-11-02 20:33:58 +00:00
|
|
|
.build(gfx_queue.device().clone())
|
|
|
|
.unwrap()
|
2021-09-13 15:14:54 +00:00
|
|
|
};
|
2022-10-05 09:09:26 +00:00
|
|
|
|
2021-09-13 15:14:54 +00:00
|
|
|
PixelsDrawPipeline {
|
|
|
|
gfx_queue,
|
2022-05-29 16:53:36 +00:00
|
|
|
subpass,
|
2021-09-13 15:14:54 +00:00
|
|
|
pipeline,
|
2022-10-05 09:09:26 +00:00
|
|
|
command_buffer_allocator,
|
|
|
|
descriptor_set_allocator,
|
2021-09-13 15:14:54 +00:00
|
|
|
vertices: vertex_buffer,
|
|
|
|
indices: index_buffer,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-02 20:33:58 +00:00
|
|
|
fn create_descriptor_set(
|
|
|
|
&self,
|
|
|
|
image: Arc<dyn ImageViewAbstract>,
|
|
|
|
) -> Arc<PersistentDescriptorSet> {
|
2022-02-25 22:52:44 +00:00
|
|
|
let layout = self.pipeline.layout().set_layouts().get(0).unwrap();
|
2022-02-26 08:46:53 +00:00
|
|
|
let sampler = Sampler::new(
|
|
|
|
self.gfx_queue.device().clone(),
|
|
|
|
SamplerCreateInfo {
|
|
|
|
mag_filter: Filter::Linear,
|
|
|
|
min_filter: Filter::Linear,
|
|
|
|
address_mode: [SamplerAddressMode::Repeat; 3],
|
|
|
|
mipmap_mode: SamplerMipmapMode::Linear,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.unwrap();
|
2022-01-11 03:32:53 +00:00
|
|
|
|
2021-12-18 10:32:38 +00:00
|
|
|
PersistentDescriptorSet::new(
|
2022-10-31 07:08:59 +00:00
|
|
|
&self.descriptor_set_allocator,
|
2021-12-18 10:32:38 +00:00
|
|
|
layout.clone(),
|
|
|
|
[WriteDescriptorSet::image_view_sampler(
|
|
|
|
0,
|
|
|
|
image.clone(),
|
|
|
|
sampler,
|
|
|
|
)],
|
|
|
|
)
|
|
|
|
.unwrap()
|
2021-09-13 15:14:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Draw input `image` over a quad of size -1.0 to 1.0
|
|
|
|
pub fn draw(
|
2022-10-07 06:59:54 +00:00
|
|
|
&self,
|
2021-09-13 15:14:54 +00:00
|
|
|
viewport_dimensions: [u32; 2],
|
2021-09-29 17:00:56 +00:00
|
|
|
image: Arc<dyn ImageViewAbstract>,
|
2021-09-13 15:14:54 +00:00
|
|
|
) -> SecondaryAutoCommandBuffer {
|
2022-05-29 16:53:36 +00:00
|
|
|
let mut builder = AutoCommandBufferBuilder::secondary(
|
2022-10-31 07:08:59 +00:00
|
|
|
&self.command_buffer_allocator,
|
2022-09-10 06:00:08 +00:00
|
|
|
self.gfx_queue.queue_family_index(),
|
2021-09-13 15:14:54 +00:00
|
|
|
CommandBufferUsage::MultipleSubmit,
|
2022-05-29 16:53:36 +00:00
|
|
|
CommandBufferInheritanceInfo {
|
|
|
|
render_pass: Some(self.subpass.clone().into()),
|
|
|
|
..Default::default()
|
|
|
|
},
|
2021-09-13 15:14:54 +00:00
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
let desc_set = self.create_descriptor_set(image);
|
|
|
|
builder
|
|
|
|
.set_viewport(
|
|
|
|
0,
|
|
|
|
[Viewport {
|
|
|
|
origin: [0.0, 0.0],
|
|
|
|
dimensions: [viewport_dimensions[0] as f32, viewport_dimensions[1] as f32],
|
|
|
|
depth_range: 0.0..1.0,
|
|
|
|
}],
|
|
|
|
)
|
|
|
|
.bind_pipeline_graphics(self.pipeline.clone())
|
|
|
|
.bind_descriptor_sets(
|
|
|
|
PipelineBindPoint::Graphics,
|
|
|
|
self.pipeline.layout().clone(),
|
|
|
|
0,
|
|
|
|
desc_set,
|
|
|
|
)
|
|
|
|
.bind_vertex_buffers(0, self.vertices.clone())
|
|
|
|
.bind_index_buffer(self.indices.clone())
|
|
|
|
.draw_indexed(self.indices.len() as u32, 1, 0, 0, 0)
|
|
|
|
.unwrap();
|
|
|
|
builder.build().unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mod vs {
|
|
|
|
vulkano_shaders::shader! {
|
|
|
|
ty: "vertex",
|
|
|
|
src: "
|
|
|
|
#version 450
|
|
|
|
layout(location=0) in vec2 position;
|
|
|
|
layout(location=1) in vec2 tex_coords;
|
|
|
|
|
|
|
|
layout(location = 0) out vec2 f_tex_coords;
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
gl_Position = vec4(position, 0.0, 1.0);
|
|
|
|
f_tex_coords = tex_coords;
|
|
|
|
}
|
|
|
|
"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mod fs {
|
|
|
|
vulkano_shaders::shader! {
|
|
|
|
ty: "fragment",
|
|
|
|
src: "
|
|
|
|
#version 450
|
|
|
|
layout(location = 0) in vec2 v_tex_coords;
|
|
|
|
|
|
|
|
layout(location = 0) out vec4 f_color;
|
|
|
|
|
|
|
|
layout(set = 0, binding = 0) uniform sampler2D tex;
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
f_color = texture(tex, v_tex_coords);
|
|
|
|
}
|
|
|
|
"
|
|
|
|
}
|
|
|
|
}
|