pittore 0.2.4

Simple toolkit for 2D visualization based on wgpu.
Documentation
use crate::backend::RenderState;

use super::{bind_group::AsBindGroup, PipelineSet, PIPELINE_VIEWPORT};

pub struct PipelineBindGroup;

impl AsBindGroup for PipelineBindGroup {
    fn bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
        device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
            label: None,
            entries: &[
                wgpu::BindGroupLayoutEntry {
                    binding: 0,
                    visibility: wgpu::ShaderStages::VERTEX,
                    ty: wgpu::BindingType::Buffer {
                        ty: wgpu::BufferBindingType::Uniform,
                        has_dynamic_offset: false,
                        min_binding_size: None,
                    },
                    count: None,
                },
                wgpu::BindGroupLayoutEntry {
                    binding: 1,
                    visibility: wgpu::ShaderStages::FRAGMENT,
                    ty: wgpu::BindingType::Texture {
                        sample_type: wgpu::TextureSampleType::Float { filterable: true },
                        view_dimension: wgpu::TextureViewDimension::D2,
                        multisampled: false,
                    },
                    count: None,
                },
                wgpu::BindGroupLayoutEntry {
                    binding: 2,
                    visibility: wgpu::ShaderStages::FRAGMENT,
                    ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
                    count: None,
                },
            ],
        })
    }

    fn as_bind_group(&self, render_state: &RenderState) -> wgpu::BindGroup {
        render_state
            .device
            .create_bind_group(&wgpu::BindGroupDescriptor {
                label: None,
                layout: &Self::bind_group_layout(&render_state.device),
                entries: &[
                    wgpu::BindGroupEntry {
                        binding: 0,
                        resource: render_state.viewport.scale_buffer.as_entire_binding(),
                    },
                    wgpu::BindGroupEntry {
                        binding: 1,
                        resource: wgpu::BindingResource::TextureView(
                            &render_state.viewport.viewport_texture.texture_view,
                        ),
                    },
                    wgpu::BindGroupEntry {
                        binding: 2,
                        resource: wgpu::BindingResource::Sampler(&render_state.default_sampler),
                    },
                ],
            })
    }
}

pub fn register_viewport_pipeline(
    RenderState {
        pipelines,
        surface_format,
        device,
        ..
    }: &mut RenderState,
) {
    let copy_shader = device.create_shader_module(wgpu::include_wgsl!("shaders/viewport.wgsl"));

    let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
        bind_group_layouts: &[&PipelineBindGroup::bind_group_layout(device)],
        ..Default::default()
    });
    let fragment_target = &[Some(wgpu::ColorTargetState {
        format: *surface_format,
        blend: Some(wgpu::BlendState::ALPHA_BLENDING),
        write_mask: wgpu::ColorWrites::ALL,
    })];
    let descriptor = wgpu::RenderPipelineDescriptor {
        label: Some("viewport_pipeline"),
        layout: Some(&pipeline_layout),
        vertex: wgpu::VertexState {
            module: &copy_shader,
            entry_point: None,
            buffers: &[],
            compilation_options: wgpu::PipelineCompilationOptions::default(),
        },
        fragment: Some(wgpu::FragmentState {
            module: &copy_shader,
            entry_point: None,
            compilation_options: wgpu::PipelineCompilationOptions::default(),
            targets: fragment_target,
        }),
        primitive: wgpu::PrimitiveState {
            topology: wgpu::PrimitiveTopology::TriangleList,
            ..Default::default()
        },
        depth_stencil: None,
        multisample: wgpu::MultisampleState::default(),
        multiview: None,
        cache: None,
    };

    let pipeline = device.create_render_pipeline(&descriptor);
    let copy_pipeline = PipelineSet {
        pipeline: pipeline,
        pipeline_bind_group: Box::new(PipelineBindGroup),
    };

    pipelines.insert(PIPELINE_VIEWPORT, copy_pipeline);
}