roast2d_internal 0.3.0-alpha.1

Roast2D internal crate
Documentation
use crate::engine::Engine;
use crate::prelude::renderer_types::{TextureResource, Vertex};
use crate::prelude::wgpu::util::DeviceExt;
use crate::prelude::wgpu::{self, Device, RenderPass};

use crate::render::BackendState;
use crate::renderer::traits::PostRenderer;

struct State {
    device: Device,
    pipeline: wgpu::RenderPipeline,
    bind_group_layout: wgpu::BindGroupLayout,
    vertex_buffer: wgpu::Buffer,
    index_buffer: wgpu::Buffer,
}

impl State {
    pub fn new(param: &BackendState) -> Self {
        let BackendState {
            device,
            queue: _,
            surface_config,
        } = param;
        let format = surface_config.format;
        let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
            label: Some("screen shader"),
            source: wgpu::ShaderSource::Wgsl(
                include_str!("../../assets/shaders/screen.wgsl").into(),
            ),
        });
        let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
            label: Some("Screen Bind Group Layout"),
            entries: &[
                wgpu::BindGroupLayoutEntry {
                    binding: 0,
                    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: 1,
                    visibility: wgpu::ShaderStages::FRAGMENT,
                    ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
                    count: None,
                },
            ],
        });
        let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
            label: Some("screen layout"),
            bind_group_layouts: &[&bind_group_layout],
            push_constant_ranges: &[],
        });
        let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
            cache: None,
            label: Some("screen pipeline"),
            layout: Some(&pipeline_layout),
            vertex: wgpu::VertexState {
                module: &shader,
                entry_point: Some("vs_main"),
                buffers: &[Vertex::desc()],
                compilation_options: Default::default(),
            },
            fragment: Some(wgpu::FragmentState {
                module: &shader,
                entry_point: Some("fs_main"),
                targets: &[Some(wgpu::ColorTargetState {
                    format,
                    blend: Some(wgpu::BlendState::ALPHA_BLENDING),
                    write_mask: wgpu::ColorWrites::ALL,
                })],
                compilation_options: Default::default(),
            }),
            primitive: wgpu::PrimitiveState {
                topology: wgpu::PrimitiveTopology::TriangleList,
                strip_index_format: None,
                front_face: wgpu::FrontFace::Ccw,
                cull_mode: Some(wgpu::Face::Back),
                polygon_mode: wgpu::PolygonMode::Fill,
                unclipped_depth: false,
                conservative: false,
            },
            depth_stencil: None,
            multisample: wgpu::MultisampleState::default(),
            multiview: None,
        });
        let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
            label: Some("screen vertex buffer"),
            contents: bytemuck::cast_slice(&[
                Vertex {
                    pos: [-1.0, -1.0],
                    color: [1.0, 1.0, 1.0, 1.0],
                    tex_coord: [0.0, 1.0],
                },
                Vertex {
                    pos: [1.0, -1.0],
                    color: [1.0, 1.0, 1.0, 1.0],
                    tex_coord: [1.0, 1.0],
                },
                Vertex {
                    pos: [1.0, 1.0],
                    color: [1.0, 1.0, 1.0, 1.0],
                    tex_coord: [1.0, 0.0],
                },
                Vertex {
                    pos: [-1.0, 1.0],
                    color: [1.0, 1.0, 1.0, 1.0],
                    tex_coord: [0.0, 0.0],
                },
            ]),
            usage: wgpu::BufferUsages::VERTEX,
        });
        let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
            label: Some("screen index buffer"),
            contents: bytemuck::cast_slice(&[0u16, 1, 2, 0, 2, 3]),
            usage: wgpu::BufferUsages::INDEX,
        });
        Self {
            device: device.clone(),
            pipeline,
            bind_group_layout,
            vertex_buffer,
            index_buffer,
        }
    }
}

pub struct ScreenRenderer {
    state: State,
}

impl ScreenRenderer {
    pub fn setup(param: &BackendState) -> Self {
        let state = State::new(param);
        Self { state }
    }
}

impl PostRenderer for ScreenRenderer {
    fn resize(&self, _g: &Engine) {}

    fn draw(&self, texture: &TextureResource, pass: &mut RenderPass) {
        let bind_group = self
            .state
            .device
            .create_bind_group(&wgpu::BindGroupDescriptor {
                layout: &self.state.bind_group_layout,
                entries: &[
                    wgpu::BindGroupEntry {
                        binding: 0,
                        resource: wgpu::BindingResource::TextureView(&texture.view),
                    },
                    wgpu::BindGroupEntry {
                        binding: 1,
                        resource: wgpu::BindingResource::Sampler(&texture.sampler),
                    },
                ],
                label: Some("Screen bind group"),
            });
        pass.set_pipeline(&self.state.pipeline);
        pass.set_bind_group(0, &bind_group, &[]);
        pass.set_vertex_buffer(0, self.state.vertex_buffer.slice(..));
        pass.set_index_buffer(self.state.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
        pass.draw_indexed(0..6, 0, 0..1);
    }

    fn frame_pass(&self, _g: &Engine, _pass: &mut RenderPass) {}

    fn frame_end(&self, _pass: &mut RenderPass) {}
}