atagen

monolith

public
Star0
Watch0
5b7cddd2e177149d7bdb4006fcb9b174e08cb3cc
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git

Blame: crates/render-vk/src/pipeline.rs

824bf02b6e55atagen2026-10-16 09:15 UTC1
use crate::Error;
824bf02b6e55atagen2026-10-16 09:15 UTC2
use crate::device::Shared;
824bf02b6e55atagen2026-10-16 09:15 UTC3
use ash::vk;
824bf02b6e55atagen2026-10-16 09:15 UTC4
use std::collections::HashMap;
824bf02b6e55atagen2026-10-16 09:15 UTC5
use std::sync::Arc;
824bf02b6e55atagen2026-10-16 09:15 UTC6
824bf02b6e55atagen2026-10-16 09:15 UTC7
/// Push constants shared by every shader, see `shaders/push.glsl`.
824bf02b6e55atagen2026-10-16 09:15 UTC8
/// `dst` is the quad in normalized device coordinates as (x, y, w, h),
824bf02b6e55atagen2026-10-16 09:15 UTC9
/// `uv` the texture coordinate at each corner (TL, TR, BL, BR).
824bf02b6e55atagen2026-10-16 09:15 UTC10
#[repr(C)]
824bf02b6e55atagen2026-10-16 09:15 UTC11
#[derive(Clone, Copy, Debug, Default)]
824bf02b6e55atagen2026-10-16 09:15 UTC12
pub(crate) struct Push {
824bf02b6e55atagen2026-10-16 09:15 UTC13
    pub color: [f32; 4],
824bf02b6e55atagen2026-10-16 09:15 UTC14
    pub dst: [f32; 4],
824bf02b6e55atagen2026-10-16 09:15 UTC15
    pub uv: [[f32; 2]; 4],
824bf02b6e55atagen2026-10-16 09:15 UTC16
}
824bf02b6e55atagen2026-10-16 09:15 UTC17
824bf02b6e55atagen2026-10-16 09:15 UTC18
impl Push {
824bf02b6e55atagen2026-10-16 09:15 UTC19
    pub fn bytes(&self) -> &[u8] {
824bf02b6e55atagen2026-10-16 09:15 UTC20
        unsafe { std::slice::from_raw_parts((self as *const Self).cast::<u8>(), size_of::<Self>()) }
824bf02b6e55atagen2026-10-16 09:15 UTC21
    }
824bf02b6e55atagen2026-10-16 09:15 UTC22
}
824bf02b6e55atagen2026-10-16 09:15 UTC23
824bf02b6e55atagen2026-10-16 09:15 UTC24
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
824bf02b6e55atagen2026-10-16 09:15 UTC25
pub(crate) enum Kind {
824bf02b6e55atagen2026-10-16 09:15 UTC26
    Solid,
824bf02b6e55atagen2026-10-16 09:15 UTC27
    Texture,
824bf02b6e55atagen2026-10-16 09:15 UTC28
}
824bf02b6e55atagen2026-10-16 09:15 UTC29
824bf02b6e55atagen2026-10-16 09:15 UTC30
pub(crate) struct Pipelines {
824bf02b6e55atagen2026-10-16 09:15 UTC31
    shared: Arc<Shared>,
824bf02b6e55atagen2026-10-16 09:15 UTC32
    pub set_layout: vk::DescriptorSetLayout,
824bf02b6e55atagen2026-10-16 09:15 UTC33
    pub layout: vk::PipelineLayout,
824bf02b6e55atagen2026-10-16 09:15 UTC34
    vert: vk::ShaderModule,
824bf02b6e55atagen2026-10-16 09:15 UTC35
    solid: vk::ShaderModule,
824bf02b6e55atagen2026-10-16 09:15 UTC36
    texture: vk::ShaderModule,
824bf02b6e55atagen2026-10-16 09:15 UTC37
    cache: HashMap<(vk::Format, Kind), vk::Pipeline>,
824bf02b6e55atagen2026-10-16 09:15 UTC38
}
824bf02b6e55atagen2026-10-16 09:15 UTC39
824bf02b6e55atagen2026-10-16 09:15 UTC40
const QUAD_VERT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/quad.vert.spv"));
824bf02b6e55atagen2026-10-16 09:15 UTC41
const SOLID_FRAG: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/solid.frag.spv"));
824bf02b6e55atagen2026-10-16 09:15 UTC42
const TEXTURE_FRAG: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/texture.frag.spv"));
824bf02b6e55atagen2026-10-16 09:15 UTC43
824bf02b6e55atagen2026-10-16 09:15 UTC44
impl Pipelines {
824bf02b6e55atagen2026-10-16 09:15 UTC45
    pub fn new(shared: &Arc<Shared>) -> Result<Self, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC46
        let d = &shared.device.device;
824bf02b6e55atagen2026-10-16 09:15 UTC47
        let bindings = [vk::DescriptorSetLayoutBinding::default()
824bf02b6e55atagen2026-10-16 09:15 UTC48
            .binding(0)
824bf02b6e55atagen2026-10-16 09:15 UTC49
            .descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)
824bf02b6e55atagen2026-10-16 09:15 UTC50
            .descriptor_count(1)
824bf02b6e55atagen2026-10-16 09:15 UTC51
            .stage_flags(vk::ShaderStageFlags::FRAGMENT)];
824bf02b6e55atagen2026-10-16 09:15 UTC52
        let set_layout = unsafe {
824bf02b6e55atagen2026-10-16 09:15 UTC53
            d.create_descriptor_set_layout(
824bf02b6e55atagen2026-10-16 09:15 UTC54
                &vk::DescriptorSetLayoutCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC55
                    .flags(vk::DescriptorSetLayoutCreateFlags::PUSH_DESCRIPTOR_KHR)
824bf02b6e55atagen2026-10-16 09:15 UTC56
                    .bindings(&bindings),
824bf02b6e55atagen2026-10-16 09:15 UTC57
                None,
824bf02b6e55atagen2026-10-16 09:15 UTC58
            )?
824bf02b6e55atagen2026-10-16 09:15 UTC59
        };
824bf02b6e55atagen2026-10-16 09:15 UTC60
        let ranges = [vk::PushConstantRange::default()
824bf02b6e55atagen2026-10-16 09:15 UTC61
            .stage_flags(vk::ShaderStageFlags::VERTEX | vk::ShaderStageFlags::FRAGMENT)
824bf02b6e55atagen2026-10-16 09:15 UTC62
            .size(size_of::<Push>() as u32)];
824bf02b6e55atagen2026-10-16 09:15 UTC63
        let set_layouts = [set_layout];
824bf02b6e55atagen2026-10-16 09:15 UTC64
        let layout = unsafe {
824bf02b6e55atagen2026-10-16 09:15 UTC65
            d.create_pipeline_layout(
824bf02b6e55atagen2026-10-16 09:15 UTC66
                &vk::PipelineLayoutCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC67
                    .set_layouts(&set_layouts)
824bf02b6e55atagen2026-10-16 09:15 UTC68
                    .push_constant_ranges(&ranges),
824bf02b6e55atagen2026-10-16 09:15 UTC69
                None,
824bf02b6e55atagen2026-10-16 09:15 UTC70
            )?
824bf02b6e55atagen2026-10-16 09:15 UTC71
        };
824bf02b6e55atagen2026-10-16 09:15 UTC72
        let module = |code: &[u8]| -> Result<vk::ShaderModule, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC73
            let words = ash::util::read_spv(&mut std::io::Cursor::new(code))
824bf02b6e55atagen2026-10-16 09:15 UTC74
                .map_err(|_| vk::Result::ERROR_INVALID_SHADER_NV)?;
824bf02b6e55atagen2026-10-16 09:15 UTC75
            Ok(unsafe {
824bf02b6e55atagen2026-10-16 09:15 UTC76
                d.create_shader_module(&vk::ShaderModuleCreateInfo::default().code(&words), None)?
824bf02b6e55atagen2026-10-16 09:15 UTC77
            })
824bf02b6e55atagen2026-10-16 09:15 UTC78
        };
824bf02b6e55atagen2026-10-16 09:15 UTC79
        Ok(Self {
824bf02b6e55atagen2026-10-16 09:15 UTC80
            shared: shared.clone(),
824bf02b6e55atagen2026-10-16 09:15 UTC81
            set_layout,
824bf02b6e55atagen2026-10-16 09:15 UTC82
            layout,
824bf02b6e55atagen2026-10-16 09:15 UTC83
            vert: module(QUAD_VERT)?,
824bf02b6e55atagen2026-10-16 09:15 UTC84
            solid: module(SOLID_FRAG)?,
824bf02b6e55atagen2026-10-16 09:15 UTC85
            texture: module(TEXTURE_FRAG)?,
824bf02b6e55atagen2026-10-16 09:15 UTC86
            cache: HashMap::new(),
824bf02b6e55atagen2026-10-16 09:15 UTC87
        })
824bf02b6e55atagen2026-10-16 09:15 UTC88
    }
824bf02b6e55atagen2026-10-16 09:15 UTC89
824bf02b6e55atagen2026-10-16 09:15 UTC90
    pub fn get(&mut self, format: vk::Format, kind: Kind) -> Result<vk::Pipeline, Error> {
824bf02b6e55atagen2026-10-16 09:15 UTC91
        if let Some(&p) = self.cache.get(&(format, kind)) {
824bf02b6e55atagen2026-10-16 09:15 UTC92
            return Ok(p);
824bf02b6e55atagen2026-10-16 09:15 UTC93
        }
824bf02b6e55atagen2026-10-16 09:15 UTC94
        let d = &self.shared.device.device;
824bf02b6e55atagen2026-10-16 09:15 UTC95
        let frag = match kind {
824bf02b6e55atagen2026-10-16 09:15 UTC96
            Kind::Solid => self.solid,
824bf02b6e55atagen2026-10-16 09:15 UTC97
            Kind::Texture => self.texture,
824bf02b6e55atagen2026-10-16 09:15 UTC98
        };
824bf02b6e55atagen2026-10-16 09:15 UTC99
        let stages = [
824bf02b6e55atagen2026-10-16 09:15 UTC100
            vk::PipelineShaderStageCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC101
                .stage(vk::ShaderStageFlags::VERTEX)
824bf02b6e55atagen2026-10-16 09:15 UTC102
                .module(self.vert)
824bf02b6e55atagen2026-10-16 09:15 UTC103
                .name(c"main"),
824bf02b6e55atagen2026-10-16 09:15 UTC104
            vk::PipelineShaderStageCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC105
                .stage(vk::ShaderStageFlags::FRAGMENT)
824bf02b6e55atagen2026-10-16 09:15 UTC106
                .module(frag)
824bf02b6e55atagen2026-10-16 09:15 UTC107
                .name(c"main"),
824bf02b6e55atagen2026-10-16 09:15 UTC108
        ];
824bf02b6e55atagen2026-10-16 09:15 UTC109
        let vertex = vk::PipelineVertexInputStateCreateInfo::default();
824bf02b6e55atagen2026-10-16 09:15 UTC110
        let assembly = vk::PipelineInputAssemblyStateCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC111
            .topology(vk::PrimitiveTopology::TRIANGLE_STRIP);
824bf02b6e55atagen2026-10-16 09:15 UTC112
        let viewport = vk::PipelineViewportStateCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC113
            .viewport_count(1)
824bf02b6e55atagen2026-10-16 09:15 UTC114
            .scissor_count(1);
824bf02b6e55atagen2026-10-16 09:15 UTC115
        let raster = vk::PipelineRasterizationStateCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC116
            .polygon_mode(vk::PolygonMode::FILL)
824bf02b6e55atagen2026-10-16 09:15 UTC117
            .cull_mode(vk::CullModeFlags::NONE)
824bf02b6e55atagen2026-10-16 09:15 UTC118
            .line_width(1.0);
824bf02b6e55atagen2026-10-16 09:15 UTC119
        let multisample = vk::PipelineMultisampleStateCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC120
            .rasterization_samples(vk::SampleCountFlags::TYPE_1);
824bf02b6e55atagen2026-10-16 09:15 UTC121
        let attachments = [vk::PipelineColorBlendAttachmentState::default()
824bf02b6e55atagen2026-10-16 09:15 UTC122
            .blend_enable(true)
824bf02b6e55atagen2026-10-16 09:15 UTC123
            .src_color_blend_factor(vk::BlendFactor::ONE)
824bf02b6e55atagen2026-10-16 09:15 UTC124
            .dst_color_blend_factor(vk::BlendFactor::ONE_MINUS_SRC_ALPHA)
824bf02b6e55atagen2026-10-16 09:15 UTC125
            .color_blend_op(vk::BlendOp::ADD)
824bf02b6e55atagen2026-10-16 09:15 UTC126
            .src_alpha_blend_factor(vk::BlendFactor::ONE)
824bf02b6e55atagen2026-10-16 09:15 UTC127
            .dst_alpha_blend_factor(vk::BlendFactor::ONE_MINUS_SRC_ALPHA)
824bf02b6e55atagen2026-10-16 09:15 UTC128
            .alpha_blend_op(vk::BlendOp::ADD)
824bf02b6e55atagen2026-10-16 09:15 UTC129
            .color_write_mask(vk::ColorComponentFlags::RGBA)];
824bf02b6e55atagen2026-10-16 09:15 UTC130
        let blend = vk::PipelineColorBlendStateCreateInfo::default().attachments(&attachments);
824bf02b6e55atagen2026-10-16 09:15 UTC131
        let dynamic_states = [vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR];
824bf02b6e55atagen2026-10-16 09:15 UTC132
        let dynamic = vk::PipelineDynamicStateCreateInfo::default().dynamic_states(&dynamic_states);
824bf02b6e55atagen2026-10-16 09:15 UTC133
        let formats = [format];
824bf02b6e55atagen2026-10-16 09:15 UTC134
        let mut rendering =
824bf02b6e55atagen2026-10-16 09:15 UTC135
            vk::PipelineRenderingCreateInfo::default().color_attachment_formats(&formats);
824bf02b6e55atagen2026-10-16 09:15 UTC136
        let info = vk::GraphicsPipelineCreateInfo::default()
824bf02b6e55atagen2026-10-16 09:15 UTC137
            .stages(&stages)
824bf02b6e55atagen2026-10-16 09:15 UTC138
            .vertex_input_state(&vertex)
824bf02b6e55atagen2026-10-16 09:15 UTC139
            .input_assembly_state(&assembly)
824bf02b6e55atagen2026-10-16 09:15 UTC140
            .viewport_state(&viewport)
824bf02b6e55atagen2026-10-16 09:15 UTC141
            .rasterization_state(&raster)
824bf02b6e55atagen2026-10-16 09:15 UTC142
            .multisample_state(&multisample)
824bf02b6e55atagen2026-10-16 09:15 UTC143
            .color_blend_state(&blend)
824bf02b6e55atagen2026-10-16 09:15 UTC144
            .dynamic_state(&dynamic)
824bf02b6e55atagen2026-10-16 09:15 UTC145
            .layout(self.layout)
824bf02b6e55atagen2026-10-16 09:15 UTC146
            .push_next(&mut rendering);
824bf02b6e55atagen2026-10-16 09:15 UTC147
        let pipeline =
824bf02b6e55atagen2026-10-16 09:15 UTC148
            unsafe { d.create_graphics_pipelines(vk::PipelineCache::null(), &[info], None) }
824bf02b6e55atagen2026-10-16 09:15 UTC149
                .map_err(|(_, e)| e)?[0];
824bf02b6e55atagen2026-10-16 09:15 UTC150
        self.cache.insert((format, kind), pipeline);
824bf02b6e55atagen2026-10-16 09:15 UTC151
        Ok(pipeline)
824bf02b6e55atagen2026-10-16 09:15 UTC152
    }
824bf02b6e55atagen2026-10-16 09:15 UTC153
}
824bf02b6e55atagen2026-10-16 09:15 UTC154
824bf02b6e55atagen2026-10-16 09:15 UTC155
impl Drop for Pipelines {
824bf02b6e55atagen2026-10-16 09:15 UTC156
    fn drop(&mut self) {
824bf02b6e55atagen2026-10-16 09:15 UTC157
        let d = &self.shared.device.device;
824bf02b6e55atagen2026-10-16 09:15 UTC158
        unsafe {
824bf02b6e55atagen2026-10-16 09:15 UTC159
            for (_, p) in self.cache.drain() {
824bf02b6e55atagen2026-10-16 09:15 UTC160
                d.destroy_pipeline(p, None);
824bf02b6e55atagen2026-10-16 09:15 UTC161
            }
824bf02b6e55atagen2026-10-16 09:15 UTC162
            d.destroy_shader_module(self.vert, None);
824bf02b6e55atagen2026-10-16 09:15 UTC163
            d.destroy_shader_module(self.solid, None);
824bf02b6e55atagen2026-10-16 09:15 UTC164
            d.destroy_shader_module(self.texture, None);
824bf02b6e55atagen2026-10-16 09:15 UTC165
            d.destroy_pipeline_layout(self.layout, None);
824bf02b6e55atagen2026-10-16 09:15 UTC166
            d.destroy_descriptor_set_layout(self.set_layout, None);
824bf02b6e55atagen2026-10-16 09:15 UTC167
        }
824bf02b6e55atagen2026-10-16 09:15 UTC168
    }
824bf02b6e55atagen2026-10-16 09:15 UTC169
}