atagen

monolith

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