1mod dynamic_buffer;
5mod frame_constants;
6mod material;
7mod mesh;
8mod texture;
9pub(crate) mod utility;
10
11use {
12 self::{frame_constants::FrameConstants, mesh::Mesh},
13 anyhow::{Context, Result},
14 ash::vk,
15 demo_vk::graphics::vulkan::{
16 Frame, FramesInFlight, VulkanContext, raii, spirv_words,
17 },
18 dynamic_buffer::DynamicBuffer,
19 material::Material,
20 std::sync::Arc,
21};
22
23pub use self::{
24 mesh::{TrianglesMesh, Vertex},
25 texture::{Texture, TextureAtlas, TextureLoader},
26};
27
28#[derive(Debug, Clone)]
29struct DrawParams {
30 index_offset: u32,
31 vertex_offset: u32,
32 index_count: u32,
33 material: Arc<Material>,
34 transform_index: u32,
35 scissor: vk::Rect2D,
36}
37
38#[repr(C, align(16))]
39#[derive(Debug, Copy, Clone)]
40struct MeshTransform {
41 matrix: [[f32; 4]; 4],
42}
43
44struct FrameDraw {
49 vertex_buffer: DynamicBuffer<Vertex>,
50 index_buffer: DynamicBuffer<u32>,
51 transforms: DynamicBuffer<MeshTransform>,
52 draw_params: Vec<DrawParams>,
53}
54
55impl FrameDraw {
56 pub fn new(ctx: &VulkanContext) -> Result<Self> {
57 Ok(Self {
58 vertex_buffer: DynamicBuffer::new(
59 ctx,
60 INITIAL_CAPACITY,
61 vk::BufferUsageFlags::STORAGE_BUFFER
62 | vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS,
63 )?,
64 index_buffer: DynamicBuffer::new(
65 ctx,
66 INITIAL_CAPACITY,
67 vk::BufferUsageFlags::INDEX_BUFFER,
68 )?,
69 transforms: DynamicBuffer::new(
70 ctx,
71 INITIAL_CAPACITY,
72 vk::BufferUsageFlags::STORAGE_BUFFER
73 | vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS,
74 )?,
75 draw_params: Vec::with_capacity(4),
76 })
77 }
78}
79
80pub struct StreamingRenderer<PerFrameDataT: Copy = ()> {
82 frame_draw_resources: Vec<FrameDraw>,
83 frame_constants: FrameConstants<PerFrameDataT>,
84
85 pipeline_layout: raii::PipelineLayout,
86
87 default_vertex_shader_module: raii::ShaderModule,
88 default_fragment_shader_module: raii::ShaderModule,
89 default_material: Arc<Material>,
90 image_format: vk::Format,
91}
92
93const INITIAL_CAPACITY: usize = 16_384;
94
95impl<PerFrameDataT: Copy> StreamingRenderer<PerFrameDataT> {
96 pub fn new(
97 ctx: &VulkanContext,
98 image_format: vk::Format,
99 frames_in_flight: &FramesInFlight,
100 texture_atlas: &TextureAtlas,
101 ) -> Result<Self> {
102 let frame_constants = FrameConstants::new(ctx, frames_in_flight)
103 .context("Unable to create FrameData instance")?;
104
105 let pipeline_layout = Material::create_pipeline_layout(
107 ctx,
108 texture_atlas.descriptor_set_layout(),
109 frame_constants.descriptor_set_layout(),
110 )
111 .context("Unable to create pipeline layout")?;
112
113 let frame_draw_resources = {
114 let mut resources =
115 Vec::with_capacity(frames_in_flight.frame_count());
116 for frame_index in 0..frames_in_flight.frame_count() {
117 resources.push(FrameDraw::new(ctx).context(format!(
118 "Unable to create draw resources for frame {}",
119 frame_index
120 ))?);
121 }
122 resources
123 };
124
125 let default_vertex_shader_module = {
126 let vertex_shader_words =
127 spirv_words(include_bytes!("./shaders/triangle.vert.spv"))
128 .context("Unable to pack default vertex shader source")?;
129 raii::ShaderModule::new(
130 "DefaultVertexShader",
131 ctx.device.clone(),
132 &vk::ShaderModuleCreateInfo {
133 code_size: vertex_shader_words.len() * 4,
134 p_code: vertex_shader_words.as_ptr(),
135 ..Default::default()
136 },
137 )
138 .context("Unable to create default vertex shader module")?
139 };
140 let default_fragment_shader_module = {
141 let fragment_shader_words =
142 spirv_words(include_bytes!("./shaders/triangle.frag.spv"))
143 .context("Unable to pack default fragment shader source")?;
144 raii::ShaderModule::new(
145 "DefaultFragmentShader",
146 ctx.device.clone(),
147 &vk::ShaderModuleCreateInfo {
148 code_size: fragment_shader_words.len() * 4,
149 p_code: fragment_shader_words.as_ptr(),
150 ..Default::default()
151 },
152 )
153 .context("Unable to create default fragment shader module")?
154 };
155 let default_material = Arc::new(
156 Material::new(
157 ctx,
158 image_format,
159 &pipeline_layout,
160 &default_vertex_shader_module,
161 &default_fragment_shader_module,
162 )
163 .context("Unable to create default material")?,
164 );
165
166 Ok(Self {
167 frame_draw_resources,
168 frame_constants,
169
170 pipeline_layout,
171 default_vertex_shader_module,
172 default_fragment_shader_module,
173 default_material,
174 image_format,
175 })
176 }
177
178 pub fn new_material(
184 &self,
185 ctx: &VulkanContext,
186 vertex_shader: Option<&raii::ShaderModule>,
187 fragment_shader: Option<&raii::ShaderModule>,
188 ) -> Result<Arc<Material>> {
189 let material = Material::new(
190 ctx,
191 self.image_format,
192 &self.pipeline_layout,
193 vertex_shader.unwrap_or(&self.default_vertex_shader_module),
194 fragment_shader.unwrap_or(&self.default_fragment_shader_module),
195 )
196 .context("Unable to create new material!")?;
197 Ok(Arc::new(material))
198 }
199
200 pub fn default_material(&self) -> &Arc<Material> {
203 &self.default_material
204 }
205
206 pub fn prepare_meshes(
211 &mut self,
212 ctx: &VulkanContext,
213 frame: &Frame,
214 meshes: &[&dyn Mesh],
215 ) -> Result<()> {
216 let frame_draw = &mut self.frame_draw_resources[frame.frame_index()];
217 frame_draw.draw_params.clear();
218
219 let (vertex_data, index_data) = {
221 let mut vertex_data = Vec::with_capacity(meshes.len());
222 let mut index_data = Vec::with_capacity(meshes.len());
223 let mut index_offset = 0;
224 let mut vertex_offset = 0;
225
226 for (transform_index, mesh) in meshes.iter().enumerate() {
227 let vertices = mesh.vertices();
228 let indices = mesh.indices();
229 vertex_data.push(vertices);
230 index_data.push(indices);
231
232 frame_draw.draw_params.push(DrawParams {
233 index_offset,
234 vertex_offset,
235 index_count: indices.len() as u32,
236 material: mesh.material().clone(),
237 transform_index: transform_index as u32,
238 scissor: mesh.scissor(),
239 });
240
241 index_offset += indices.len() as u32;
242 vertex_offset += vertices.len() as u32;
243 }
244
245 (vertex_data, index_data)
246 };
247
248 unsafe {
250 frame_draw
251 .vertex_buffer
252 .write_chunked_data(ctx, &vertex_data)
253 .context("Unable to write frame vertex data!")?;
254 frame_draw
255 .index_buffer
256 .write_chunked_data(ctx, &index_data)
257 .context("Unable to write index data!")?;
258 frame_draw.transforms.write_iterated_data(
259 ctx,
260 meshes.iter().map(|mesh| MeshTransform {
261 matrix: mesh.transform().data.0,
262 }),
263 )?;
264 }
265
266 Ok(())
267 }
268
269 pub fn set_frame_constants(
270 &mut self,
271 frame: &Frame,
272 data: PerFrameDataT,
273 ) -> Result<()> {
274 self.frame_constants.set_data(frame, data)
275 }
276
277 pub fn bind_texture_atlas(
283 &mut self,
284 ctx: &VulkanContext,
285 frame: &Frame,
286 texture_atlas: &TextureAtlas,
287 ) {
288 unsafe {
289 ctx.cmd_bind_descriptor_sets(
290 frame.command_buffer(),
291 vk::PipelineBindPoint::GRAPHICS,
292 self.pipeline_layout.raw,
293 0,
294 &[texture_atlas.descriptor_set()],
295 &[],
296 );
297 }
298 }
299
300 pub fn write_draw_commands(
305 &mut self,
306 ctx: &VulkanContext,
307 frame: &Frame,
308 ) -> Result<()> {
309 let frame_draw = &mut self.frame_draw_resources[frame.frame_index()];
310 unsafe {
311 ctx.cmd_bind_descriptor_sets(
312 frame.command_buffer(),
313 vk::PipelineBindPoint::GRAPHICS,
314 self.pipeline_layout.raw,
315 1,
316 &[self.frame_constants.descriptor_set_for_frame(frame)],
317 &[],
318 );
319 ctx.cmd_bind_index_buffer(
320 frame.command_buffer(),
321 frame_draw.index_buffer.raw(),
322 0,
323 vk::IndexType::UINT32,
324 );
325 ctx.cmd_push_constants(
326 frame.command_buffer(),
327 self.pipeline_layout.raw,
328 vk::ShaderStageFlags::VERTEX,
329 0,
330 &frame_draw
331 .vertex_buffer
332 .buffer_device_address()
333 .to_le_bytes(),
334 );
335 ctx.cmd_push_constants(
336 frame.command_buffer(),
337 self.pipeline_layout.raw,
338 vk::ShaderStageFlags::VERTEX,
339 8,
340 &frame_draw.transforms.buffer_device_address().to_le_bytes(),
341 );
342 }
343
344 let mut last_bound_pipeline = vk::Pipeline::null();
345 for draw_params in frame_draw.draw_params.drain(0..) {
346 let pipeline = draw_params.material.pipeline().raw;
349 if pipeline != last_bound_pipeline {
350 unsafe {
351 ctx.cmd_bind_pipeline(
352 frame.command_buffer(),
353 vk::PipelineBindPoint::GRAPHICS,
354 pipeline,
355 );
356 }
357 last_bound_pipeline = pipeline;
358 }
359 unsafe {
360 ctx.cmd_push_constants(
361 frame.command_buffer(),
362 self.pipeline_layout.raw,
363 vk::ShaderStageFlags::VERTEX,
364 16,
365 &draw_params.transform_index.to_le_bytes(),
366 );
367 ctx.cmd_set_scissor(
368 frame.command_buffer(),
369 0,
370 &[draw_params.scissor],
371 );
372 ctx.cmd_draw_indexed(
373 frame.command_buffer(),
374 draw_params.index_count, 1, draw_params.index_offset, draw_params.vertex_offset as i32, 0, );
380 }
381 }
382
383 Ok(())
384 }
385}