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(
|
||||
&self,
|
||||
wait: Option<(vk::Semaphore, vk::PipelineStageFlags)>,
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
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 tinyvec::{array_vec, ArrayVec};
|
||||
|
||||
|
@ -273,8 +277,20 @@ pub struct DeviceOwnedDebugObject<T> {
|
|||
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> {
|
||||
fn new<S: Into<Cow<'static, str>>>(
|
||||
pub fn new<S: Into<Cow<'static, str>>>(
|
||||
device: crate::Device,
|
||||
object: T,
|
||||
name: Option<S>,
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
closure_lifetime_binder,
|
||||
let_chains,
|
||||
negative_impls,
|
||||
map_try_insert
|
||||
map_try_insert,
|
||||
debug_closure_helpers
|
||||
)]
|
||||
#![allow(unused)]
|
||||
use std::{
|
||||
|
@ -38,6 +39,7 @@ mod buffers;
|
|||
mod commands;
|
||||
mod device;
|
||||
mod images;
|
||||
mod pipeline;
|
||||
mod render_graph;
|
||||
mod sync;
|
||||
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