rafx_plugins/features/tile_layer/jobs/
write.rs

1use rafx::render_feature_write_job_prelude::*;
2
3use super::*;
4use rafx::api::{
5    RafxIndexBufferBinding, RafxIndexType, RafxPrimitiveTopology, RafxVertexAttributeRate,
6    RafxVertexBufferBinding,
7};
8use rafx::framework::{MaterialPassResource, ResourceArc, VertexDataLayout, VertexDataSetLayout};
9use rafx::render_features::{BeginSubmitNodeBatchArgs, RenderSubmitNodeArgs};
10use std::marker::PhantomData;
11
12/// Vertex format for vertices sent to the GPU
13#[derive(Clone, Debug, Copy, Default)]
14#[repr(C)]
15pub struct TileLayerVertex {
16    pub position: [f32; 3],
17    pub uv: [f32; 2],
18}
19
20lazy_static::lazy_static! {
21    pub static ref TILE_LAYER_VERTEX_LAYOUT : VertexDataSetLayout = {
22        use rafx::api::RafxFormat;
23        VertexDataLayout::build_vertex_layout(&TileLayerVertex::default(), RafxVertexAttributeRate::Vertex, |builder, vertex| {
24            builder.add_member(&vertex.position, "POSITION", RafxFormat::R32G32B32_SFLOAT);
25            builder.add_member(&vertex.uv, "TEXCOORD", RafxFormat::R32G32_SFLOAT);
26        }).into_set(RafxPrimitiveTopology::TriangleList)
27    };
28}
29
30pub struct TileLayerWriteJob<'write> {
31    tile_layer_material_pass: Option<ResourceArc<MaterialPassResource>>,
32    render_objects: TileLayerRenderObjectSet,
33    _frame_packet: Box<TileLayerFramePacket>,
34    submit_packet: Box<TileLayerSubmitPacket>,
35    phantom: PhantomData<&'write ()>,
36}
37
38impl<'write> TileLayerWriteJob<'write> {
39    pub fn new(
40        _write_context: &RenderJobWriteContext<'write>,
41        frame_packet: Box<TileLayerFramePacket>,
42        submit_packet: Box<TileLayerSubmitPacket>,
43        render_objects: TileLayerRenderObjectSet,
44    ) -> Arc<dyn RenderFeatureWriteJob<'write> + 'write> {
45        Arc::new(Self {
46            tile_layer_material_pass: {
47                frame_packet
48                    .per_frame_data()
49                    .get()
50                    .tile_layer_material_pass
51                    .clone()
52            },
53            render_objects,
54            _frame_packet: frame_packet,
55            submit_packet,
56            phantom: Default::default(),
57        })
58    }
59}
60
61impl<'write> RenderFeatureWriteJob<'write> for TileLayerWriteJob<'write> {
62    fn begin_submit_node_batch(
63        &self,
64        write_context: &mut RenderJobCommandBufferContext,
65        args: BeginSubmitNodeBatchArgs,
66    ) -> RafxResult<()> {
67        if !args.feature_changed {
68            return Ok(());
69        }
70
71        profiling::scope!(super::render_feature_debug_constants().begin_submit_node_batch);
72
73        let command_buffer = &write_context.command_buffer;
74
75        let pipeline = write_context
76            .resource_context()
77            .graphics_pipeline_cache()
78            .get_or_create_graphics_pipeline(
79                Some(args.render_phase_index),
80                self.tile_layer_material_pass.as_ref().unwrap(),
81                &write_context.render_target_meta,
82                &TILE_LAYER_VERTEX_LAYOUT,
83            )
84            .unwrap();
85
86        command_buffer.cmd_bind_pipeline(&pipeline.get_raw().pipeline)?;
87
88        Ok(())
89    }
90
91    fn render_submit_node(
92        &self,
93        write_context: &mut RenderJobCommandBufferContext,
94        args: RenderSubmitNodeArgs,
95    ) -> RafxResult<()> {
96        profiling::scope!(super::render_feature_debug_constants().render_submit_node);
97
98        let command_buffer = &write_context.command_buffer;
99
100        let view_submit_packet = self.submit_packet.view_submit_packet(args.view_frame_index);
101
102        let per_view_submit_data = view_submit_packet.per_view_submit_data().get();
103
104        // Bind per-pass data (UBO with view/proj matrix, sampler)
105        per_view_submit_data
106            .descriptor_set_arc
107            .as_ref()
108            .unwrap()
109            .bind(command_buffer)?;
110
111        let submit_node = view_submit_packet
112            .get_submit_node_data_from_render_phase(args.render_phase_index, args.submit_node_id);
113
114        let render_objects = self.render_objects.read();
115        let tile_layer_render_object = render_objects.get_id(&submit_node.render_object_id);
116        tile_layer_render_object
117            .per_layer_descriptor_set
118            .bind(command_buffer)?;
119
120        for draw_call in &tile_layer_render_object.draw_call_data {
121            command_buffer.cmd_bind_vertex_buffers(
122                0,
123                &[RafxVertexBufferBinding {
124                    buffer: &tile_layer_render_object.vertex_buffer.get_raw().buffer,
125                    byte_offset: draw_call.vertex_data_offset_in_bytes as u64,
126                }],
127            )?;
128
129            command_buffer.cmd_bind_index_buffer(&RafxIndexBufferBinding {
130                buffer: &tile_layer_render_object.index_buffer.get_raw().buffer,
131                byte_offset: draw_call.index_data_offset_in_bytes as u64,
132                index_type: RafxIndexType::Uint16,
133            })?;
134
135            command_buffer.cmd_draw_indexed(draw_call.index_count, 0, 0)?;
136        }
137
138        Ok(())
139    }
140
141    fn feature_debug_constants(&self) -> &'static RenderFeatureDebugConstants {
142        super::render_feature_debug_constants()
143    }
144
145    fn feature_index(&self) -> RenderFeatureIndex {
146        super::render_feature_index()
147    }
148}