pipeline
This commit is contained in:
parent
f0fff72bce
commit
81f1ee1f96
8
crates/renderer/shaders/compile.sh
Executable file
8
crates/renderer/shaders/compile.sh
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SLANGC="/opt/shader-slang-bin/bin/slangc"
|
||||||
|
|
||||||
|
$SLANGC egui.slang -profile glsl_450 -target spirv -o egui_vert.spv -entry vertex
|
||||||
|
$SLANGC egui.slang -profile glsl_450 -target spirv -o egui_frag.spv -entry fragment
|
48
crates/renderer/shaders/egui.slang
Normal file
48
crates/renderer/shaders/egui.slang
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
struct Fragment {
|
||||||
|
float4 color : SV_Target;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VertexIn {
|
||||||
|
[[vk::layout(0)]] float2 pos;
|
||||||
|
[[vk::layout(1)]] float2 uv;
|
||||||
|
[[vk::layout(2)]] float4 color;
|
||||||
|
}
|
||||||
|
struct VertexOut {
|
||||||
|
[[vk::layout(0)]] float4 color;
|
||||||
|
[[vk::layout(1)]] float2 uv;
|
||||||
|
float4 position : SV_Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PushConstant {
|
||||||
|
float2 screen_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[vk::push_constant]]
|
||||||
|
ConstantBuffer<PushConstant> push_constant;
|
||||||
|
|
||||||
|
[shader("vertex")]
|
||||||
|
VertexOut vertex(VertexIn vertex) {
|
||||||
|
VertexOut output;
|
||||||
|
|
||||||
|
output.position = float4(
|
||||||
|
2.0 * vertex.pos.x / push_constant.screen_size.x - 1.0,
|
||||||
|
2.0 * vertex.pos.y / push_constant.screen_size.y - 1.0,
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
);
|
||||||
|
output.color = vertex.color;
|
||||||
|
output.uv = vertex.uv;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[vk::binding(0)]]
|
||||||
|
Sampler2D texture;
|
||||||
|
|
||||||
|
[shader("fragment")]
|
||||||
|
Fragment fragment(VertexOut input) {
|
||||||
|
Fragment output;
|
||||||
|
|
||||||
|
output.color = input.color * texture.Sample(input.uv);
|
||||||
|
return output;
|
||||||
|
}
|
BIN
crates/renderer/shaders/egui_frag.spv
Normal file
BIN
crates/renderer/shaders/egui_frag.spv
Normal file
Binary file not shown.
BIN
crates/renderer/shaders/egui_vert.spv
Normal file
BIN
crates/renderer/shaders/egui_vert.spv
Normal file
Binary file not shown.
|
@ -227,6 +227,22 @@ impl SingleUseCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn begin_rendering(&self, rendering_info: vk::RenderingInfo<'_>) {
|
||||||
|
unsafe {
|
||||||
|
self.device
|
||||||
|
.dev()
|
||||||
|
.cmd_begin_rendering(self.buffer(), &rendering_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn
|
||||||
|
|
||||||
|
pub fn end_rendering(&self) {
|
||||||
|
unsafe {
|
||||||
|
self.device.dev().cmd_end_rendering(self.buffer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn submit_fence(
|
pub fn submit_fence(
|
||||||
&self,
|
&self,
|
||||||
wait: Option<(vk::Semaphore, vk::PipelineStageFlags)>,
|
wait: Option<(vk::Semaphore, vk::PipelineStageFlags)>,
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
use std::{borrow::Cow, collections::BTreeMap, ops::Deref, sync::Arc};
|
use std::{borrow::Cow, collections::BTreeMap, ops::Deref, sync::Arc};
|
||||||
|
|
||||||
use ash::{khr, prelude::VkResult, vk};
|
use ash::{
|
||||||
|
khr,
|
||||||
|
prelude::VkResult,
|
||||||
|
vk::{self, Handle},
|
||||||
|
};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use tinyvec::{array_vec, ArrayVec};
|
use tinyvec::{array_vec, ArrayVec};
|
||||||
|
|
||||||
|
@ -273,8 +277,20 @@ pub struct DeviceOwnedDebugObject<T> {
|
||||||
name: Option<Cow<'static, str>>,
|
name: Option<Cow<'static, str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: std::fmt::Debug + vk::Handle + Copy> std::fmt::Debug for DeviceOwnedDebugObject<T> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct(core::any::type_name::<T>())
|
||||||
|
.field_with("device", |f| {
|
||||||
|
write!(f, "0x{:x}", self.device.0.device.handle().as_raw())
|
||||||
|
})
|
||||||
|
.field_with("handle", |f| write!(f, "0x{:x}", &self.object.as_raw()))
|
||||||
|
.field("name", &self.name)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> DeviceOwnedDebugObject<T> {
|
impl<T> DeviceOwnedDebugObject<T> {
|
||||||
fn new<S: Into<Cow<'static, str>>>(
|
pub fn new<S: Into<Cow<'static, str>>>(
|
||||||
device: crate::Device,
|
device: crate::Device,
|
||||||
object: T,
|
object: T,
|
||||||
name: Option<S>,
|
name: Option<S>,
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
closure_lifetime_binder,
|
closure_lifetime_binder,
|
||||||
let_chains,
|
let_chains,
|
||||||
negative_impls,
|
negative_impls,
|
||||||
map_try_insert
|
map_try_insert,
|
||||||
|
debug_closure_helpers
|
||||||
)]
|
)]
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -38,6 +39,7 @@ mod buffers;
|
||||||
mod commands;
|
mod commands;
|
||||||
mod device;
|
mod device;
|
||||||
mod images;
|
mod images;
|
||||||
|
mod pipeline;
|
||||||
mod render_graph;
|
mod render_graph;
|
||||||
mod sync;
|
mod sync;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
486
crates/renderer/src/pipeline.rs
Normal file
486
crates/renderer/src/pipeline.rs
Normal file
|
@ -0,0 +1,486 @@
|
||||||
|
use std::{borrow::Cow, path::Path, sync::Arc};
|
||||||
|
|
||||||
|
use ash::{prelude::*, vk};
|
||||||
|
|
||||||
|
use crate::device::{Device, DeviceOwnedDebugObject};
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct ShaderStageDesc<'a> {
|
||||||
|
pub flags: vk::PipelineShaderStageCreateFlags,
|
||||||
|
pub module: vk::ShaderModule,
|
||||||
|
pub stage: vk::ShaderStageFlags,
|
||||||
|
pub entry: Cow<'a, std::ffi::CStr>,
|
||||||
|
// specialization: Option<vk::SpecializationInfo>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct DescriptorSetLayoutBindingDesc {
|
||||||
|
pub binding: u32,
|
||||||
|
pub count: u32,
|
||||||
|
pub kind: vk::DescriptorType,
|
||||||
|
pub stage: vk::ShaderStageFlags,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct DescriptorSetLayoutDesc<'a> {
|
||||||
|
pub flags: vk::DescriptorSetLayoutCreateFlags,
|
||||||
|
pub bindings: &'a [DescriptorSetLayoutBindingDesc],
|
||||||
|
pub name: Option<Cow<'static, str>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct PipelineLayoutDesc<'a> {
|
||||||
|
pub descriptor_set_layouts: &'a [Arc<DescriptorSetLayout>],
|
||||||
|
pub push_constant_ranges: &'a [vk::PushConstantRange],
|
||||||
|
pub name: Option<Cow<'static, str>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PipelineDesc<'a> {
|
||||||
|
Compute(ComputePipelineDesc<'a>),
|
||||||
|
Graphics(GraphicsPipelineDesc<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PipelineDesc<'_> {
|
||||||
|
fn name(self) -> Option<Cow<'static, str>> {
|
||||||
|
match self {
|
||||||
|
PipelineDesc::Compute(desc) => desc.name,
|
||||||
|
PipelineDesc::Graphics(desc) => desc.name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ComputePipelineDesc<'a> {
|
||||||
|
pub flags: vk::PipelineCreateFlags,
|
||||||
|
pub name: Option<Cow<'static, str>>,
|
||||||
|
pub shader_stage: ShaderStageDesc<'a>,
|
||||||
|
pub layout: Arc<PipelineLayout>,
|
||||||
|
pub base_pipeline: Option<Arc<Pipeline>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct VertexInputState<'a> {
|
||||||
|
// pub flags: vk::PipelineVertexInputStateCreateFlags,
|
||||||
|
pub bindings: &'a [vk::VertexInputBindingDescription],
|
||||||
|
pub attributes: &'a [vk::VertexInputAttributeDescription],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct TessellationState {
|
||||||
|
pub flags: vk::PipelineTessellationStateCreateFlags,
|
||||||
|
pub patch_control_points: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct InputAssemblyState {
|
||||||
|
// pub flags: vk::PipelineInputAssemblyStateCreateFlags,
|
||||||
|
pub topology: vk::PrimitiveTopology,
|
||||||
|
pub primitive_restart: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct ViewportState<'a> {
|
||||||
|
pub num_scissors: u32,
|
||||||
|
pub scissors: Option<&'a [vk::Rect2D]>,
|
||||||
|
pub num_viewports: u32,
|
||||||
|
pub viewports: Option<&'a [vk::Viewport]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct DepthBiasState {
|
||||||
|
pub clamp: f32,
|
||||||
|
pub constant_factor: f32,
|
||||||
|
pub slope_factor: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RasterizationState {
|
||||||
|
pub depth_clamp_enable: bool,
|
||||||
|
pub discard_enable: bool,
|
||||||
|
pub line_width: f32,
|
||||||
|
pub cull_mode: vk::CullModeFlags,
|
||||||
|
pub depth_bias: Option<DepthBiasState>,
|
||||||
|
pub polygon_mode: vk::PolygonMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RasterizationState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
depth_clamp_enable: false,
|
||||||
|
line_width: 1.0,
|
||||||
|
cull_mode: vk::CullModeFlags::BACK,
|
||||||
|
depth_bias: Default::default(),
|
||||||
|
polygon_mode: vk::PolygonMode::FILL,
|
||||||
|
discard_enable: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct MultisampleState<'a> {
|
||||||
|
pub flags: vk::PipelineMultisampleStateCreateFlags,
|
||||||
|
pub sample_shading_enable: bool,
|
||||||
|
pub rasterization_samples: vk::SampleCountFlags,
|
||||||
|
pub min_sample_shading: f32,
|
||||||
|
pub sample_mask: &'a [vk::SampleMask],
|
||||||
|
pub alpha_to_coverage_enable: bool,
|
||||||
|
pub alpha_to_one_enable: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DepthBounds {
|
||||||
|
pub min: f32,
|
||||||
|
pub max: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct DepthState {
|
||||||
|
pub write_enable: bool,
|
||||||
|
/// sets depthTestEnable to true when `Some`
|
||||||
|
pub compare_op: Option<vk::CompareOp>,
|
||||||
|
/// sets depthBoundsTestEnable to true when `Some`
|
||||||
|
pub bounds: Option<DepthBounds>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct StencilState {
|
||||||
|
pub front: vk::StencilOpState,
|
||||||
|
pub back: vk::StencilOpState,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct DepthStencilState {
|
||||||
|
pub flags: vk::PipelineDepthStencilStateCreateFlags,
|
||||||
|
pub depth: Option<DepthState>,
|
||||||
|
pub stencil: Option<StencilState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct ColorBlendState<'a> {
|
||||||
|
pub flags: vk::PipelineColorBlendStateCreateFlags,
|
||||||
|
pub attachments: &'a [vk::PipelineColorBlendAttachmentState],
|
||||||
|
pub logic_op: Option<vk::LogicOp>,
|
||||||
|
pub blend_constants: [f32; 4],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct DynamicState<'a> {
|
||||||
|
pub flags: vk::PipelineDynamicStateCreateFlags,
|
||||||
|
pub dynamic_states: &'a [vk::DynamicState],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GraphicsPipelineDesc<'a> {
|
||||||
|
pub flags: vk::PipelineCreateFlags,
|
||||||
|
pub name: Option<Cow<'static, str>>,
|
||||||
|
pub shader_stages: &'a [ShaderStageDesc<'a>],
|
||||||
|
pub render_pass: Option<vk::RenderPass>,
|
||||||
|
pub layout: Arc<PipelineLayout>,
|
||||||
|
pub subpass: Option<u32>,
|
||||||
|
pub base_pipeline: Option<Arc<Pipeline>>,
|
||||||
|
|
||||||
|
pub vertex_input: Option<VertexInputState<'a>>,
|
||||||
|
pub input_assembly: Option<InputAssemblyState>,
|
||||||
|
pub tessellation: Option<TessellationState>,
|
||||||
|
pub viewport: Option<ViewportState<'a>>,
|
||||||
|
pub rasterization: Option<RasterizationState>,
|
||||||
|
pub multisample: Option<MultisampleState<'a>>,
|
||||||
|
pub depth_stencil: Option<DepthStencilState>,
|
||||||
|
pub color_blend: Option<ColorBlendState<'a>>,
|
||||||
|
pub dynamic: Option<DynamicState<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DescriptorSetLayout {
|
||||||
|
set_layout: DeviceOwnedDebugObject<vk::DescriptorSetLayout>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for DescriptorSetLayout {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
self.set_layout
|
||||||
|
.dev()
|
||||||
|
.dev()
|
||||||
|
.destroy_descriptor_set_layout(self.set_layout.handle(), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DescriptorSetLayout {
|
||||||
|
pub fn new(device: Device, desc: DescriptorSetLayoutDesc) -> VkResult<Self> {
|
||||||
|
let bindings = desc
|
||||||
|
.bindings
|
||||||
|
.iter()
|
||||||
|
.map(|binding| {
|
||||||
|
vk::DescriptorSetLayoutBinding::default()
|
||||||
|
.binding(binding.binding)
|
||||||
|
.descriptor_count(binding.count)
|
||||||
|
.descriptor_type(binding.kind)
|
||||||
|
.stage_flags(binding.stage)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let info = &vk::DescriptorSetLayoutCreateInfo::default()
|
||||||
|
.bindings(&bindings)
|
||||||
|
.flags(desc.flags);
|
||||||
|
|
||||||
|
let layout = unsafe { device.dev().create_descriptor_set_layout(info, None)? };
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
set_layout: DeviceOwnedDebugObject::new(device, layout, desc.name)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PipelineLayout {
|
||||||
|
pipeline_layout: DeviceOwnedDebugObject<vk::PipelineLayout>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for PipelineLayout {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
self.pipeline_layout
|
||||||
|
.dev()
|
||||||
|
.dev()
|
||||||
|
.destroy_pipeline_layout(self.pipeline_layout.handle(), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PipelineLayout {
|
||||||
|
pub fn new(device: Device, desc: PipelineLayoutDesc) -> VkResult<Self> {
|
||||||
|
let set_layouts = desc
|
||||||
|
.descriptor_set_layouts
|
||||||
|
.iter()
|
||||||
|
.map(|desc| desc.set_layout.handle())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let info = &vk::PipelineLayoutCreateInfo::default()
|
||||||
|
.set_layouts(&set_layouts)
|
||||||
|
.push_constant_ranges(desc.push_constant_ranges);
|
||||||
|
let layout = unsafe { device.dev().create_pipeline_layout(info, None)? };
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
pipeline_layout: DeviceOwnedDebugObject::new(device, layout, desc.name)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Pipeline {
|
||||||
|
pipeline: DeviceOwnedDebugObject<vk::Pipeline>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Pipeline {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
self.pipeline
|
||||||
|
.dev()
|
||||||
|
.dev()
|
||||||
|
.destroy_pipeline(self.pipeline.handle(), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShaderStageDesc<'_> {
|
||||||
|
fn into_create_info(&self) -> vk::PipelineShaderStageCreateInfo {
|
||||||
|
vk::PipelineShaderStageCreateInfo::default()
|
||||||
|
.module(self.module)
|
||||||
|
.flags(self.flags)
|
||||||
|
.stage(self.stage)
|
||||||
|
.name(&self.entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pipeline {
|
||||||
|
pub fn new(device: Device, desc: PipelineDesc) -> VkResult<Self> {
|
||||||
|
let name: Option<Cow<'static, str>>;
|
||||||
|
let result = match desc {
|
||||||
|
PipelineDesc::Compute(desc) => {
|
||||||
|
name = desc.name;
|
||||||
|
let info = &vk::ComputePipelineCreateInfo::default()
|
||||||
|
.layout(desc.layout.pipeline_layout.handle())
|
||||||
|
.stage(desc.shader_stage.into_create_info());
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
device.dev().create_compute_pipelines(
|
||||||
|
vk::PipelineCache::null(),
|
||||||
|
core::slice::from_ref(info),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PipelineDesc::Graphics(desc) => {
|
||||||
|
name = desc.name;
|
||||||
|
|
||||||
|
let stages = desc
|
||||||
|
.shader_stages
|
||||||
|
.iter()
|
||||||
|
.map(|stage| stage.into_create_info())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let vertex_input = desc.vertex_input.map(|vertex| {
|
||||||
|
vk::PipelineVertexInputStateCreateInfo::default()
|
||||||
|
.vertex_attribute_descriptions(vertex.attributes)
|
||||||
|
.vertex_binding_descriptions(vertex.bindings)
|
||||||
|
});
|
||||||
|
let input_assembly = desc.input_assembly.map(|state| {
|
||||||
|
vk::PipelineInputAssemblyStateCreateInfo::default()
|
||||||
|
.primitive_restart_enable(state.primitive_restart)
|
||||||
|
.topology(state.topology)
|
||||||
|
});
|
||||||
|
let tessellation = desc.tessellation.map(|state| {
|
||||||
|
vk::PipelineTessellationStateCreateInfo::default()
|
||||||
|
.flags(state.flags)
|
||||||
|
.patch_control_points(state.patch_control_points)
|
||||||
|
});
|
||||||
|
let viewport = desc.viewport.map(|state| {
|
||||||
|
let mut info = vk::PipelineViewportStateCreateInfo::default()
|
||||||
|
.scissor_count(state.num_scissors)
|
||||||
|
.viewport_count(state.num_viewports);
|
||||||
|
if let Some(viewports) = state.viewports {
|
||||||
|
info = info.viewports(viewports);
|
||||||
|
}
|
||||||
|
if let Some(scissors) = state.scissors {
|
||||||
|
info = info.scissors(scissors);
|
||||||
|
}
|
||||||
|
|
||||||
|
info
|
||||||
|
});
|
||||||
|
|
||||||
|
let rasterization = desc.rasterization.map(|state| {
|
||||||
|
let mut info = vk::PipelineRasterizationStateCreateInfo::default()
|
||||||
|
.line_width(state.line_width)
|
||||||
|
.cull_mode(state.cull_mode)
|
||||||
|
.polygon_mode(state.polygon_mode)
|
||||||
|
.rasterizer_discard_enable(state.discard_enable)
|
||||||
|
.depth_clamp_enable(state.depth_clamp_enable);
|
||||||
|
|
||||||
|
if let Some(depth_bias) = state.depth_bias {
|
||||||
|
info = info
|
||||||
|
.depth_bias_enable(true)
|
||||||
|
.depth_bias_clamp(depth_bias.clamp)
|
||||||
|
.depth_bias_constant_factor(depth_bias.constant_factor)
|
||||||
|
.depth_bias_slope_factor(depth_bias.slope_factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
info
|
||||||
|
});
|
||||||
|
|
||||||
|
let multisample = desc.multisample.map(|state| {
|
||||||
|
let mut info = vk::PipelineMultisampleStateCreateInfo::default()
|
||||||
|
.flags(state.flags)
|
||||||
|
.min_sample_shading(state.min_sample_shading)
|
||||||
|
.rasterization_samples(state.rasterization_samples)
|
||||||
|
.sample_mask(state.sample_mask)
|
||||||
|
.alpha_to_coverage_enable(state.alpha_to_coverage_enable)
|
||||||
|
.alpha_to_one_enable(state.alpha_to_one_enable);
|
||||||
|
|
||||||
|
info
|
||||||
|
});
|
||||||
|
|
||||||
|
let color_blend = desc.color_blend.map(|state| {
|
||||||
|
let mut info = vk::PipelineColorBlendStateCreateInfo::default()
|
||||||
|
.flags(state.flags)
|
||||||
|
.attachments(state.attachments)
|
||||||
|
.blend_constants(state.blend_constants)
|
||||||
|
.logic_op(state.logic_op.unwrap_or(Default::default()))
|
||||||
|
.logic_op_enable(state.logic_op.is_some());
|
||||||
|
|
||||||
|
info
|
||||||
|
});
|
||||||
|
|
||||||
|
let depth_stencil = desc.depth_stencil.map(|state| {
|
||||||
|
let mut info =
|
||||||
|
vk::PipelineDepthStencilStateCreateInfo::default().flags(state.flags);
|
||||||
|
|
||||||
|
if let Some(depth) = state.depth {
|
||||||
|
info = info
|
||||||
|
.depth_compare_op(depth.compare_op.unwrap_or(vk::CompareOp::default()))
|
||||||
|
.depth_test_enable(depth.compare_op.is_some())
|
||||||
|
.depth_write_enable(depth.write_enable)
|
||||||
|
.depth_bounds_test_enable(depth.bounds.is_some());
|
||||||
|
if let Some(bounds) = depth.bounds {
|
||||||
|
info = info
|
||||||
|
.max_depth_bounds(bounds.max)
|
||||||
|
.min_depth_bounds(bounds.min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(stencil) = state.stencil {
|
||||||
|
info = info
|
||||||
|
.stencil_test_enable(true)
|
||||||
|
.front(stencil.front)
|
||||||
|
.back(stencil.back);
|
||||||
|
}
|
||||||
|
|
||||||
|
info
|
||||||
|
});
|
||||||
|
|
||||||
|
let dynamic = desc.dynamic.map(|state| {
|
||||||
|
let mut info = vk::PipelineDynamicStateCreateInfo::default()
|
||||||
|
.flags(state.flags)
|
||||||
|
.dynamic_states(state.dynamic_states);
|
||||||
|
|
||||||
|
info
|
||||||
|
});
|
||||||
|
|
||||||
|
fn option_to_ptr<T>(option: &Option<T>) -> *const T {
|
||||||
|
option
|
||||||
|
.as_ref()
|
||||||
|
.map(|t| t as *const T)
|
||||||
|
.unwrap_or(core::ptr::null())
|
||||||
|
}
|
||||||
|
|
||||||
|
let info = &vk::GraphicsPipelineCreateInfo {
|
||||||
|
flags: desc.flags,
|
||||||
|
stage_count: stages.len() as u32,
|
||||||
|
p_stages: stages.as_ptr(),
|
||||||
|
p_vertex_input_state: option_to_ptr(&vertex_input),
|
||||||
|
p_input_assembly_state: option_to_ptr(&input_assembly),
|
||||||
|
p_tessellation_state: option_to_ptr(&tessellation),
|
||||||
|
p_viewport_state: option_to_ptr(&viewport),
|
||||||
|
p_rasterization_state: option_to_ptr(&rasterization),
|
||||||
|
p_multisample_state: option_to_ptr(&multisample),
|
||||||
|
p_depth_stencil_state: option_to_ptr(&depth_stencil),
|
||||||
|
p_color_blend_state: option_to_ptr(&color_blend),
|
||||||
|
p_dynamic_state: option_to_ptr(&dynamic),
|
||||||
|
layout: desc.layout.pipeline_layout.handle(),
|
||||||
|
render_pass: desc.render_pass.unwrap_or(vk::RenderPass::null()),
|
||||||
|
subpass: desc.subpass.unwrap_or(0),
|
||||||
|
base_pipeline_handle: desc
|
||||||
|
.base_pipeline
|
||||||
|
.map(|piepline| piepline.pipeline.handle())
|
||||||
|
.unwrap_or(vk::Pipeline::null()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
device.dev().create_graphics_pipelines(
|
||||||
|
vk::PipelineCache::null(),
|
||||||
|
core::slice::from_ref(info),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let pipeline = match result {
|
||||||
|
Ok(pipelines) => pipelines[0],
|
||||||
|
Err((pipelines, error)) => {
|
||||||
|
tracing::error!("failed to create pipelines with :{error}");
|
||||||
|
for pipeline in pipelines {
|
||||||
|
unsafe {
|
||||||
|
device.dev().destroy_pipeline(pipeline, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Err(error.into());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
pipeline: DeviceOwnedDebugObject::new(device, pipeline, name)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue