diff --git a/crates/bevy_pathfinder/Cargo.toml b/crates/bevy_pathfinder/Cargo.toml index 6c86da18f0..97bee67c6a 100644 --- a/crates/bevy_pathfinder/Cargo.toml +++ b/crates/bevy_pathfinder/Cargo.toml @@ -21,3 +21,4 @@ pathfinder_color = { path = "../pathfinder/color" } pathfinder_canvas = { path = "../pathfinder/canvas" } zerocopy = "0.3.0" +byteorder = "1.3" diff --git a/crates/bevy_pathfinder/src/device.rs b/crates/bevy_pathfinder/src/device.rs index 896379f302..92f002b075 100644 --- a/crates/bevy_pathfinder/src/device.rs +++ b/crates/bevy_pathfinder/src/device.rs @@ -22,15 +22,16 @@ use bevy_render::{ }, Color, }; +use byteorder::{NativeEndian, WriteBytesExt}; use pathfinder_canvas::vec2i; use pathfinder_geometry::{rect::RectI, vector::Vector2I}; use pathfinder_gpu::{ BufferData, BufferTarget, BufferUploadMode, Device, FeatureLevel, ProgramKind, RenderState, - RenderTarget, ShaderKind, TextureData, TextureDataRef, TextureSamplingFlags, VertexAttrClass, - VertexAttrDescriptor, VertexAttrType, + RenderTarget, ShaderKind, TextureData, TextureDataRef, TextureSamplingFlags, UniformData, + VertexAttrClass, VertexAttrDescriptor, VertexAttrType, }; use pathfinder_resources::ResourceLoader; -use std::{borrow::Cow, cell::RefCell, collections::HashMap, mem, rc::Rc, time::Duration}; +use std::{borrow::Cow, cell::RefCell, collections::HashMap, mem, rc::Rc, time::Duration, ops::Range}; use zerocopy::AsBytes; pub struct BevyPathfinderDevice<'a> { @@ -59,10 +60,31 @@ impl<'a> BevyPathfinderDevice<'a> { pub fn prepare_to_draw(&self, render_state: &RenderState) { let pass_descriptor = self.create_pass_descriptor(render_state); - self.update_pipline_descriptor(render_state, &pass_descriptor); - // setup uniforms + self.setup_pipline_descriptor(render_state, &pass_descriptor, &render_state.vertex_array.requested_descriptors.borrow()); + // TODO: setup uniforms let mut render_context = self.render_context.borrow_mut(); - let render_resource_assignments = RenderResourceAssignments::default(); + let mut render_resource_assignments = RenderResourceAssignments::default(); + for (i, vertex_buffer) in render_state + .vertex_array + .vertex_buffers + .borrow() + .iter() + .enumerate() + { + let resource = vertex_buffer.handle.borrow().unwrap(); + let mut indices_resource = None; + if i == 0 { + if let Some(ref index_buffer) = *render_state.vertex_array.index_buffer.borrow() { + indices_resource = Some(index_buffer.handle.borrow().unwrap()); + } + } + render_resource_assignments.set_vertex_buffer(get_vertex_buffer_name(i), resource, indices_resource); + } + + // if let Some(ref index_buffer) = *render_state.vertex_array.index_buffer.borrow() { + // let resource = index_buffer.handle.borrow().unwrap(); + // pass.set_index_buffer(resource, 0); + // } render_context.begin_pass( &pass_descriptor, &render_resource_assignments, @@ -81,21 +103,8 @@ impl<'a> BevyPathfinderDevice<'a> { pass.set_stencil_reference(stencil_state.reference); } - for (i, vertex_buffer) in render_state - .vertex_array - .vertex_buffers - .borrow() - .iter() - .enumerate() - { - let resource = vertex_buffer.handle.borrow().unwrap(); - pass.set_vertex_buffer(i as u32, resource, 0); - } - - if let Some(ref index_buffer) = *render_state.vertex_array.index_buffer.borrow(){ - let resource = index_buffer.handle.borrow().unwrap(); - pass.set_index_buffer(resource, 0); - } + let pipeline_descriptor = render_state.program.pipeline_descriptor.borrow(); + pass.set_render_resources(&pipeline_descriptor, &render_resource_assignments); }, ) } @@ -119,16 +128,37 @@ impl<'a> BevyPathfinderDevice<'a> { Some(TextureFormat::Bgra8UnormSrgb) } - pub fn update_pipline_descriptor( + pub fn setup_pipline_descriptor( &self, render_state: &RenderState, pass_descriptor: &PassDescriptor, + requested_vertex_descriptors: &HashMap, ) { - if self.render_context.borrow().resources().get_asset_resource(render_state.program.pipeline_handle, 0).is_some() { - return + if self + .render_context + .borrow() + .resources() + .get_asset_resource(render_state.program.pipeline_handle, 0) + .is_some() + { + return; } - let mut pipeline_descriptor = render_state.program.pipeline_descriptor.borrow_mut(); + { + let mut layout = pipeline_descriptor.get_layout_mut().unwrap(); + let mut i = 0; + let mut descriptors = Vec::with_capacity(requested_vertex_descriptors.len()); + loop { + if let Some(descriptor) = requested_vertex_descriptors.get(&i) { + descriptors.push(descriptor.clone()); + i += 1; + } else { + break; + } + } + layout.vertex_buffer_descriptors = descriptors; + } + let color_texture_format = if let TextureAttachment::RenderResource(texture_resource) = pass_descriptor .color_attachments @@ -218,6 +248,15 @@ impl<'a> BevyPathfinderDevice<'a> { descriptor.stencil_back = stencil_descriptor; } } + + self.render_context + .borrow() + .resources() + .create_render_pipeline( + render_state.program.pipeline_handle, + &pipeline_descriptor, + &self.shaders.borrow(), + ); } pub fn create_pass_descriptor( @@ -278,6 +317,114 @@ impl<'a> BevyPathfinderDevice<'a> { sample_count: 1, } } + fn create_uniform_buffer(&self, uniforms: &[(&BevyUniform, UniformData)]) -> UniformBuffer { + let (mut uniform_buffer_data, mut uniform_buffer_ranges) = (vec![], vec![]); + for &(_, uniform_data) in uniforms.iter() { + let start_index = uniform_buffer_data.len(); + match uniform_data { + UniformData::Float(value) => uniform_buffer_data + .write_f32::(value) + .unwrap(), + UniformData::IVec2(vector) => { + uniform_buffer_data + .write_i32::(vector.x()) + .unwrap(); + uniform_buffer_data + .write_i32::(vector.y()) + .unwrap(); + } + UniformData::IVec3(values) => { + uniform_buffer_data + .write_i32::(values[0]) + .unwrap(); + uniform_buffer_data + .write_i32::(values[1]) + .unwrap(); + uniform_buffer_data + .write_i32::(values[2]) + .unwrap(); + } + UniformData::Int(value) => uniform_buffer_data + .write_i32::(value) + .unwrap(), + UniformData::Mat2(matrix) => { + uniform_buffer_data + .write_f32::(matrix.x()) + .unwrap(); + uniform_buffer_data + .write_f32::(matrix.y()) + .unwrap(); + uniform_buffer_data + .write_f32::(matrix.z()) + .unwrap(); + uniform_buffer_data + .write_f32::(matrix.w()) + .unwrap(); + } + UniformData::Mat4(matrix) => { + for column in &matrix { + uniform_buffer_data + .write_f32::(column.x()) + .unwrap(); + uniform_buffer_data + .write_f32::(column.y()) + .unwrap(); + uniform_buffer_data + .write_f32::(column.z()) + .unwrap(); + uniform_buffer_data + .write_f32::(column.w()) + .unwrap(); + } + } + UniformData::Vec2(vector) => { + uniform_buffer_data + .write_f32::(vector.x()) + .unwrap(); + uniform_buffer_data + .write_f32::(vector.y()) + .unwrap(); + } + UniformData::Vec3(array) => { + uniform_buffer_data + .write_f32::(array[0]) + .unwrap(); + uniform_buffer_data + .write_f32::(array[1]) + .unwrap(); + uniform_buffer_data + .write_f32::(array[2]) + .unwrap(); + } + UniformData::Vec4(vector) => { + uniform_buffer_data + .write_f32::(vector.x()) + .unwrap(); + uniform_buffer_data + .write_f32::(vector.y()) + .unwrap(); + uniform_buffer_data + .write_f32::(vector.z()) + .unwrap(); + uniform_buffer_data + .write_f32::(vector.w()) + .unwrap(); + } + UniformData::TextureUnit(_) | UniformData::ImageUnit(_) => {} + } + // TODO: this padding might not be necessary + let end_index = uniform_buffer_data.len(); + while uniform_buffer_data.len() % 256 != 0 { + uniform_buffer_data.push(0); + } + uniform_buffer_ranges.push(start_index..end_index); + } + + UniformBuffer { + data: uniform_buffer_data, + ranges: uniform_buffer_ranges, + } + } } pub struct BevyTimerQuery {} @@ -482,6 +629,7 @@ impl<'a> Device for BevyPathfinderDevice<'a> { bevy_attr: &BevyVertexAttr, descriptor: &VertexAttrDescriptor, ) { + println!("configure"); let format = match (descriptor.class, descriptor.attr_type, descriptor.size) { (VertexAttrClass::Int, VertexAttrType::I8, 2) => VertexFormat::Char2, // (VertexAttrClass::Int, VertexAttrType::I8, 3) => VertexFormat::Char3, @@ -564,7 +712,7 @@ impl<'a> Device for BevyPathfinderDevice<'a> { requested_descriptors .entry(buffer_index) .or_insert_with(|| VertexBufferDescriptor { - name: Cow::Borrowed("placeholder"), + name: Cow::Borrowed(get_vertex_buffer_name(buffer_index as usize)), attributes: Vec::new(), step_mode, stride: descriptor.stride as u64, @@ -924,3 +1072,23 @@ impl ToBevyCompareFunction for pathfinder_gpu::StencilFunc { } } } + +struct UniformBuffer { + data: Vec, + ranges: Vec>, +} + +pub const pathfinder_vertex_buffer_0: &'static str = "P0"; +pub const pathfinder_vertex_buffer_1: &'static str = "P1"; +pub const pathfinder_vertex_buffer_2: &'static str = "P2"; +pub const pathfinder_vertex_buffer_3: &'static str = "P3"; + +pub fn get_vertex_buffer_name(index: usize) -> &'static str { + match index { + 0 => pathfinder_vertex_buffer_0, + 1 => pathfinder_vertex_buffer_1, + 2 => pathfinder_vertex_buffer_2, + 3 => pathfinder_vertex_buffer_3, + _ => panic!("encountered unknown vertex buffer index"), + } +} \ No newline at end of file diff --git a/crates/bevy_render/src/render_graph/command.rs b/crates/bevy_render/src/render_graph/command.rs index e368107e44..5619d55201 100644 --- a/crates/bevy_render/src/render_graph/command.rs +++ b/crates/bevy_render/src/render_graph/command.rs @@ -20,6 +20,7 @@ pub enum Command { destination_array_layer: u32, size: Extent3d, }, + // TODO: Frees probably don't need to be queued? FreeBuffer(RenderResource), }