198 lines
7.7 KiB
Rust
198 lines
7.7 KiB
Rust
use std::sync::Arc;
|
|
|
|
use vulkano::{
|
|
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer},
|
|
device::Device,
|
|
format::Format,
|
|
memory::allocator::{AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter},
|
|
pipeline::{
|
|
graphics::{
|
|
color_blend::{ColorBlendAttachmentState, ColorBlendState},
|
|
input_assembly::InputAssemblyState,
|
|
multisample::MultisampleState,
|
|
rasterization::RasterizationState,
|
|
subpass::PipelineRenderingCreateInfo,
|
|
vertex_input::{Vertex, VertexDefinition},
|
|
viewport::ViewportState,
|
|
GraphicsPipelineCreateInfo,
|
|
},
|
|
layout::PipelineDescriptorSetLayoutCreateInfo,
|
|
DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo,
|
|
},
|
|
};
|
|
|
|
pub fn test_pipeline(
|
|
device: Arc<Device>,
|
|
memory_allocator: Arc<dyn MemoryAllocator>,
|
|
image_format: Format,
|
|
) -> (Subbuffer<[MyVertex]>, Arc<GraphicsPipeline>) {
|
|
let vertices = [
|
|
MyVertex {
|
|
position: [-0.5, -0.25],
|
|
},
|
|
MyVertex {
|
|
position: [0.0, 0.5],
|
|
},
|
|
MyVertex {
|
|
position: [0.25, -0.1],
|
|
},
|
|
];
|
|
let vertex_buffer = Buffer::from_iter(
|
|
memory_allocator,
|
|
BufferCreateInfo {
|
|
usage: BufferUsage::VERTEX_BUFFER,
|
|
..Default::default()
|
|
},
|
|
AllocationCreateInfo {
|
|
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
|
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
|
..Default::default()
|
|
},
|
|
vertices,
|
|
)
|
|
.unwrap();
|
|
|
|
|
|
|
|
let pipeline = {
|
|
// First, we load the shaders that the pipeline will use:
|
|
// the vertex shader and the fragment shader.
|
|
//
|
|
// A Vulkan shader can in theory contain multiple entry points, so we have to specify which
|
|
// one.
|
|
let vs = vs::load(device.clone())
|
|
.unwrap()
|
|
.entry_point("main")
|
|
.unwrap();
|
|
let fs = fs::load(device.clone())
|
|
.unwrap()
|
|
.entry_point("main")
|
|
.unwrap();
|
|
|
|
// Automatically generate a vertex input state from the vertex shader's input interface,
|
|
// that takes a single vertex buffer containing `Vertex` structs.
|
|
let vertex_input_state = MyVertex::per_vertex().definition(&vs).unwrap();
|
|
|
|
// Make a list of the shader stages that the pipeline will have.
|
|
let stages = [
|
|
PipelineShaderStageCreateInfo::new(vs),
|
|
PipelineShaderStageCreateInfo::new(fs),
|
|
];
|
|
|
|
// We must now create a **pipeline layout** object, which describes the locations and types
|
|
// of descriptor sets and push constants used by the shaders in the pipeline.
|
|
//
|
|
// Multiple pipelines can share a common layout object, which is more efficient.
|
|
// The shaders in a pipeline must use a subset of the resources described in its pipeline
|
|
// layout, but the pipeline layout is allowed to contain resources that are not present in
|
|
// the shaders; they can be used by shaders in other pipelines that share the same
|
|
// layout. Thus, it is a good idea to design shaders so that many pipelines have
|
|
// common resource locations, which allows them to share pipeline layouts.
|
|
let layout = PipelineLayout::new(
|
|
device.clone(),
|
|
// Since we only have one pipeline in this example, and thus one pipeline layout,
|
|
// we automatically generate the creation info for it from the resources used in the
|
|
// shaders. In a real application, you would specify this information manually so that
|
|
// you can re-use one layout in multiple pipelines.
|
|
PipelineDescriptorSetLayoutCreateInfo::from_stages(&stages)
|
|
.into_pipeline_layout_create_info(device.clone())
|
|
.unwrap(),
|
|
)
|
|
.unwrap();
|
|
|
|
// We describe the formats of attachment images where the colors, depth and/or stencil
|
|
// information will be written. The pipeline will only be usable with this particular
|
|
// configuration of the attachment images.
|
|
let subpass = PipelineRenderingCreateInfo {
|
|
// We specify a single color attachment that will be rendered to. When we begin
|
|
// rendering, we will specify a swapchain image to be used as this attachment, so here
|
|
// we set its format to be the same format as the swapchain.
|
|
color_attachment_formats: vec![Some(image_format)],
|
|
..Default::default()
|
|
};
|
|
|
|
// Finally, create the pipeline.
|
|
GraphicsPipeline::new(
|
|
device.clone(),
|
|
None,
|
|
GraphicsPipelineCreateInfo {
|
|
stages: stages.into_iter().collect(),
|
|
// How vertex data is read from the vertex buffers into the vertex shader.
|
|
vertex_input_state: Some(vertex_input_state),
|
|
// How vertices are arranged into primitive shapes.
|
|
// The default primitive shape is a triangle.
|
|
input_assembly_state: Some(InputAssemblyState::default()),
|
|
// How primitives are transformed and clipped to fit the framebuffer.
|
|
// We use a resizable viewport, set to draw over the entire window.
|
|
viewport_state: Some(ViewportState::default()),
|
|
// How polygons are culled and converted into a raster of pixels.
|
|
// The default value does not perform any culling.
|
|
rasterization_state: Some(RasterizationState::default()),
|
|
// How multiple fragment shader samples are converted to a single pixel value.
|
|
// The default value does not perform any multisampling.
|
|
multisample_state: Some(MultisampleState::default()),
|
|
// How pixel values are combined with the values already present in the framebuffer.
|
|
// The default value overwrites the old value with the new one, without any
|
|
// blending.
|
|
color_blend_state: Some(ColorBlendState::with_attachment_states(
|
|
subpass.color_attachment_formats.len() as u32,
|
|
ColorBlendAttachmentState::default(),
|
|
)),
|
|
// Dynamic states allows us to specify parts of the pipeline settings when
|
|
// recording the command buffer, before we perform drawing.
|
|
// Here, we specify that the viewport should be dynamic.
|
|
dynamic_state: [DynamicState::Viewport].into_iter().collect(),
|
|
subpass: Some(subpass.into()),
|
|
..GraphicsPipelineCreateInfo::layout(layout)
|
|
},
|
|
)
|
|
.unwrap()
|
|
};
|
|
|
|
(vertex_buffer, pipeline)
|
|
}
|
|
|
|
#[derive(BufferContents, Vertex)]
|
|
#[repr(C)]
|
|
pub struct MyVertex {
|
|
#[format(R32G32_SFLOAT)]
|
|
position: [f32; 2],
|
|
}
|
|
|
|
mod vs {
|
|
vulkano_shaders::shader! {
|
|
ty: "vertex",
|
|
src: r"
|
|
#version 450
|
|
|
|
layout(location = 0) in vec2 position;
|
|
|
|
layout(location = 0) out vec3 fragColor;
|
|
|
|
vec3 colors[3] = vec3[](vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0));
|
|
|
|
void main() {
|
|
gl_Position = vec4(position, 0.0, 1.0);
|
|
fragColor = colors[gl_VertexIndex];
|
|
}
|
|
",
|
|
}
|
|
}
|
|
|
|
mod fs {
|
|
vulkano_shaders::shader! {
|
|
ty: "fragment",
|
|
src: r"
|
|
#version 450
|
|
|
|
layout(location = 0) in vec3 fragColor;
|
|
|
|
layout(location = 0) out vec4 f_color;
|
|
|
|
void main() {
|
|
f_color = vec4(fragColor, 1.0);
|
|
}
|
|
",
|
|
}
|
|
}
|