2024-10-10 10:16:14 +00:00
|
|
|
use crate::{App, RenderContext};
|
|
|
|
use std::{alloc::Layout, slice, sync::Arc};
|
2024-09-20 11:30:36 +00:00
|
|
|
use vulkano::{
|
|
|
|
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
|
|
|
|
command_buffer::RenderPassBeginInfo,
|
|
|
|
format::Format,
|
|
|
|
image::{
|
|
|
|
view::{ImageView, ImageViewCreateInfo},
|
2024-10-10 10:16:14 +00:00
|
|
|
Image, ImageAspects, ImageSubresourceRange, ImageUsage,
|
2024-09-20 11:30:36 +00:00
|
|
|
},
|
|
|
|
memory::allocator::{AllocationCreateInfo, DeviceLayout, MemoryTypeFilter},
|
|
|
|
pipeline::{
|
|
|
|
graphics::{
|
|
|
|
color_blend::{ColorBlendAttachmentState, ColorBlendState},
|
|
|
|
input_assembly::InputAssemblyState,
|
|
|
|
multisample::MultisampleState,
|
|
|
|
rasterization::RasterizationState,
|
|
|
|
vertex_input::{Vertex, VertexDefinition},
|
|
|
|
viewport::ViewportState,
|
|
|
|
GraphicsPipelineCreateInfo,
|
|
|
|
},
|
2024-10-10 10:16:14 +00:00
|
|
|
DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo,
|
2024-09-20 11:30:36 +00:00
|
|
|
},
|
|
|
|
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
|
|
|
};
|
|
|
|
use vulkano_taskgraph::{
|
2024-10-10 10:16:14 +00:00
|
|
|
command_buffer::RecordingCommandBuffer,
|
|
|
|
resource::{HostAccessType, Resources},
|
|
|
|
Id, Task, TaskContext, TaskResult,
|
2024-09-20 11:30:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
pub struct SceneTask {
|
|
|
|
render_pass: Arc<RenderPass>,
|
|
|
|
pipeline: Arc<GraphicsPipeline>,
|
|
|
|
framebuffer: Arc<Framebuffer>,
|
|
|
|
vertex_buffer_id: Id<Buffer>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SceneTask {
|
2024-10-10 10:16:14 +00:00
|
|
|
pub fn new(
|
|
|
|
app: &App,
|
|
|
|
pipeline_layout: &Arc<PipelineLayout>,
|
|
|
|
bloom_image_id: Id<Image>,
|
|
|
|
) -> Self {
|
2024-09-20 11:30:36 +00:00
|
|
|
let render_pass = vulkano::single_pass_renderpass!(
|
2024-10-10 10:16:14 +00:00
|
|
|
app.device.clone(),
|
2024-09-20 11:30:36 +00:00
|
|
|
attachments: {
|
|
|
|
color: {
|
|
|
|
format: Format::R32_UINT,
|
|
|
|
samples: 1,
|
|
|
|
load_op: Clear,
|
|
|
|
store_op: Store,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
pass: {
|
|
|
|
color: [color],
|
|
|
|
depth_stencil: {},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let pipeline = {
|
2024-10-10 10:16:14 +00:00
|
|
|
let vs = vs::load(app.device.clone())
|
2024-09-20 11:30:36 +00:00
|
|
|
.unwrap()
|
|
|
|
.entry_point("main")
|
|
|
|
.unwrap();
|
2024-10-10 10:16:14 +00:00
|
|
|
let fs = fs::load(app.device.clone())
|
2024-09-20 11:30:36 +00:00
|
|
|
.unwrap()
|
|
|
|
.entry_point("main")
|
|
|
|
.unwrap();
|
|
|
|
let vertex_input_state = MyVertex::per_vertex().definition(&vs).unwrap();
|
|
|
|
let stages = [
|
|
|
|
PipelineShaderStageCreateInfo::new(vs),
|
|
|
|
PipelineShaderStageCreateInfo::new(fs),
|
|
|
|
];
|
|
|
|
let subpass = Subpass::from(render_pass.clone(), 0).unwrap();
|
|
|
|
|
|
|
|
GraphicsPipeline::new(
|
2024-10-10 10:16:14 +00:00
|
|
|
app.device.clone(),
|
2024-09-20 11:30:36 +00:00
|
|
|
None,
|
|
|
|
GraphicsPipelineCreateInfo {
|
|
|
|
stages: stages.into_iter().collect(),
|
|
|
|
vertex_input_state: Some(vertex_input_state),
|
|
|
|
input_assembly_state: Some(InputAssemblyState::default()),
|
|
|
|
viewport_state: Some(ViewportState::default()),
|
|
|
|
rasterization_state: Some(RasterizationState::default()),
|
|
|
|
multisample_state: Some(MultisampleState::default()),
|
|
|
|
color_blend_state: Some(ColorBlendState::with_attachment_states(
|
|
|
|
subpass.num_color_attachments(),
|
|
|
|
ColorBlendAttachmentState::default(),
|
|
|
|
)),
|
|
|
|
dynamic_state: [DynamicState::Viewport].into_iter().collect(),
|
|
|
|
subpass: Some(subpass.into()),
|
2024-10-10 10:16:14 +00:00
|
|
|
..GraphicsPipelineCreateInfo::layout(pipeline_layout.clone())
|
2024-09-20 11:30:36 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
.unwrap()
|
|
|
|
};
|
|
|
|
|
2024-10-10 10:16:14 +00:00
|
|
|
let framebuffer = window_size_dependent_setup(&app.resources, bloom_image_id, &render_pass);
|
2024-09-20 11:30:36 +00:00
|
|
|
|
|
|
|
let vertices = [
|
|
|
|
MyVertex {
|
|
|
|
position: [-0.5, 0.5],
|
|
|
|
},
|
|
|
|
MyVertex {
|
|
|
|
position: [0.5, 0.5],
|
|
|
|
},
|
|
|
|
MyVertex {
|
|
|
|
position: [0.0, -0.5],
|
|
|
|
},
|
|
|
|
];
|
2024-10-10 10:16:14 +00:00
|
|
|
let vertex_buffer_id = app
|
2024-09-20 11:30:36 +00:00
|
|
|
.resources
|
|
|
|
.create_buffer(
|
|
|
|
BufferCreateInfo {
|
|
|
|
usage: BufferUsage::VERTEX_BUFFER,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
AllocationCreateInfo {
|
|
|
|
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
|
|
|
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
DeviceLayout::from_layout(Layout::for_value(&vertices)).unwrap(),
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
vulkano_taskgraph::execute(
|
2024-10-10 10:16:14 +00:00
|
|
|
&app.queue,
|
|
|
|
&app.resources,
|
|
|
|
app.flight_id,
|
2024-09-20 11:30:36 +00:00
|
|
|
|_cbf, tcx| {
|
|
|
|
tcx.write_buffer::<[MyVertex]>(vertex_buffer_id, ..)?
|
|
|
|
.copy_from_slice(&vertices);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
},
|
|
|
|
[(vertex_buffer_id, HostAccessType::Write)],
|
|
|
|
[],
|
|
|
|
[],
|
|
|
|
)
|
|
|
|
}
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
SceneTask {
|
|
|
|
render_pass,
|
|
|
|
pipeline,
|
|
|
|
framebuffer,
|
|
|
|
vertex_buffer_id,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-10 10:16:14 +00:00
|
|
|
pub fn handle_resize(&mut self, resources: &Resources, bloom_image_id: Id<Image>) {
|
|
|
|
self.framebuffer =
|
|
|
|
window_size_dependent_setup(resources, bloom_image_id, &self.render_pass);
|
2024-09-20 11:30:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Task for SceneTask {
|
|
|
|
type World = RenderContext;
|
|
|
|
|
|
|
|
unsafe fn execute(
|
|
|
|
&self,
|
|
|
|
cbf: &mut RecordingCommandBuffer<'_>,
|
|
|
|
_tcx: &mut TaskContext<'_>,
|
|
|
|
rcx: &Self::World,
|
|
|
|
) -> TaskResult {
|
|
|
|
cbf.as_raw().begin_render_pass(
|
|
|
|
&RenderPassBeginInfo {
|
|
|
|
clear_values: vec![Some([0u32; 4].into())],
|
|
|
|
..RenderPassBeginInfo::framebuffer(self.framebuffer.clone())
|
|
|
|
},
|
|
|
|
&Default::default(),
|
|
|
|
)?;
|
|
|
|
cbf.set_viewport(0, slice::from_ref(&rcx.viewport))?;
|
|
|
|
cbf.bind_pipeline_graphics(&self.pipeline)?;
|
|
|
|
cbf.bind_vertex_buffers(0, &[self.vertex_buffer_id], &[0], &[], &[])?;
|
|
|
|
|
|
|
|
unsafe { cbf.draw(3, 1, 0, 0) }?;
|
|
|
|
|
|
|
|
cbf.as_raw().end_render_pass(&Default::default())?;
|
|
|
|
|
2024-10-10 10:16:14 +00:00
|
|
|
cbf.destroy_object(self.framebuffer.clone());
|
|
|
|
|
2024-09-20 11:30:36 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, BufferContents, Vertex)]
|
|
|
|
#[repr(C)]
|
|
|
|
struct MyVertex {
|
|
|
|
#[format(R32G32_SFLOAT)]
|
|
|
|
position: [f32; 2],
|
|
|
|
}
|
|
|
|
|
2024-10-10 10:16:14 +00:00
|
|
|
fn window_size_dependent_setup(
|
|
|
|
resources: &Resources,
|
|
|
|
bloom_image_id: Id<Image>,
|
|
|
|
render_pass: &Arc<RenderPass>,
|
|
|
|
) -> Arc<Framebuffer> {
|
|
|
|
let image_state = resources.image(bloom_image_id).unwrap();
|
|
|
|
let image = image_state.image();
|
|
|
|
let view = ImageView::new(
|
|
|
|
image.clone(),
|
|
|
|
ImageViewCreateInfo {
|
|
|
|
format: Format::R32_UINT,
|
|
|
|
subresource_range: ImageSubresourceRange {
|
|
|
|
aspects: ImageAspects::COLOR,
|
|
|
|
mip_levels: 0..1,
|
|
|
|
array_layers: 0..1,
|
|
|
|
},
|
|
|
|
usage: ImageUsage::COLOR_ATTACHMENT,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
Framebuffer::new(
|
|
|
|
render_pass.clone(),
|
|
|
|
FramebufferCreateInfo {
|
|
|
|
attachments: vec![view],
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
|
2024-09-20 11:30:36 +00:00
|
|
|
mod vs {
|
|
|
|
vulkano_shaders::shader! {
|
|
|
|
ty: "vertex",
|
|
|
|
src: r"
|
|
|
|
#version 450
|
|
|
|
|
|
|
|
layout(location = 0) in vec2 position;
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
gl_Position = vec4(position, 0.0, 1.0);
|
|
|
|
}
|
|
|
|
",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mod fs {
|
|
|
|
vulkano_shaders::shader! {
|
|
|
|
ty: "fragment",
|
|
|
|
src: r"
|
|
|
|
#version 450
|
|
|
|
#include <shared_exponent.glsl>
|
|
|
|
|
|
|
|
layout(location = 0) out uint f_color;
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
f_color = convertToSharedExponent(vec3(2.0, 0.0, 0.0));
|
|
|
|
}
|
|
|
|
",
|
|
|
|
include: ["."],
|
|
|
|
}
|
|
|
|
}
|