diff --git a/mp_elements/src/app.rs b/mp_elements/src/app.rs index 90131b4..b4c96af 100644 --- a/mp_elements/src/app.rs +++ b/mp_elements/src/app.rs @@ -1,4 +1,6 @@ -use crate::elements::{ElementAttach, Elements}; +use std::collections::HashMap; + +use crate::elements::{ElementAttach, Elements, ElementsRef}; use crate::elementvec::ElementVec; use wgpu::{Backends, Instance}; @@ -14,6 +16,8 @@ pub struct App { _texture: wgpu::Texture, texture_view: wgpu::TextureView, pipelines: Option, + + buffer_pool: DataBufferPool, } impl App { @@ -63,6 +67,9 @@ impl App { // Create a texture view from the texture. This texture view will be used as the output texture for the render pass. let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default()); + // Buffer pool + let buffer_pool = DataBufferPool::new(); + Self { device, queue, @@ -70,6 +77,7 @@ impl App { pipelines: None, _texture: texture, texture_view, + buffer_pool, } } @@ -165,16 +173,16 @@ impl<'a> Ctx<'a> { } } -pub struct DrawList<'a> { - pub elements: Vec<(&'a ElementAttach, &'a Elements)>, // 修复字段访问权限 +pub struct DrawList<'b, 'a: 'b> { + pub elements: Vec<(&'b ElementAttach, ElementsRef<'a>)>, // 修复字段访问权限 } -impl<'a> DrawList<'a> { +impl<'b, 'a: 'b> DrawList<'b, 'a> { pub fn new() -> Self { Self { elements: vec![] } } - pub fn push>(&mut self, element: Ele, attach: &'a ElementAttach) { + pub fn push>>(&mut self, element: Ele, attach: &'a ElementAttach) { self.elements.push((attach, element.into())); } } @@ -239,7 +247,25 @@ impl CommonUtils { } } -pub struct Elementi {} +pub struct DataBufferPool { + buffers: HashMap, +} + +impl DataBufferPool { + pub fn new() -> Self { + Self { + buffers: HashMap::new(), + } + } + + pub fn get_or_create_buffer(&mut self) {} +} + +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct BufferKey { + pub size: u64, + pub from: String, +} mod test { use mp_core::{PluginManager, RadarGridData}; @@ -257,29 +283,35 @@ mod test { pollster::block_on(async { let mut app = App::instant().await; + app.init().await; + + let pipelines = app.pipelines(); + let ctx = app.ctx(); + + let ppi = pipelines.ppi(); if let Ok(data) = data { let first_block = data.first().unwrap(); - if let Ok(data) = <&mp_core::Data as TryInto<&RadarGridData>>::try_into(first_block) - { + // Convert the first block into a PPI struct. + if let Ok(data) = first_block.try_into() { + let buffer_pool = &mut app.buffer_pool; + // Reused buffer is None, so a new attachment is created. + let attachment = ppi.new_attachment(&ctx, buffer_pool); + + // Load the data into the attachment. + ppi.load_data(&ctx, data, &attachment); + + // Create a new draw list and push the attachment into it. + let mut draw_list = DrawList::new(); + draw_list.push(ppi, &attachment); + + // Draw the elements in the draw list. + app.draw(draw_list); } + } else { + panic!("Failed to load data"); } - // app.init().await; - - // let pipelines = app.pipelines(); - // let ppi = pipelines.ppi(); - - // let ctx = app.ctx(); - - // let attachment = ppi.new_attachment(&ctx); - - // ppi.bake() - - // attachment.update_data(&ctx, data); - - // let mut draw_list = DrawList::new(); - // draw_list.push(pipelines.ppi()); }) } } diff --git a/mp_elements/src/elements/mod.rs b/mp_elements/src/elements/mod.rs index 0cb0501..72acde4 100644 --- a/mp_elements/src/elements/mod.rs +++ b/mp_elements/src/elements/mod.rs @@ -1,5 +1,5 @@ pub mod ppi; -use crate::app::Ctx; +use crate::app::{Ctx, DataBufferPool}; pub use ppi::PPI; use std::any::Any; use wgpu::util::DeviceExt; @@ -10,12 +10,22 @@ macro_rules! elements { $($element_name($element),)+ } + pub enum ElementsRef<'a> { + $($element_name(&'a $element),)+ + } + $( impl From<$element> for Elements { fn from(element: $element) -> Self { Elements::$element_name(element) } } + + impl<'a> From<&'a $element> for ElementsRef<'a> { + fn from(element: &'a $element) -> Self { + ElementsRef::$element_name(element) + } + } )+ impl Elements { @@ -32,6 +42,20 @@ macro_rules! elements { } } + impl<'a> ElementsRef<'a> { + pub fn pipeline(&'a self) -> &wgpu::RenderPipeline { + match self { + $(ElementsRef::$element_name(element) => element.pipeline(),)+ + } + } + + pub fn draw(&'a self, attach: &ElementAttach, render_pass: &mut wgpu::RenderPass) { + match self { + $(ElementsRef::$element_name(element) => element.draw(attach, render_pass),)+ + } + } + } + }; } @@ -42,7 +66,7 @@ pub trait Element { fn new(ctx: &Ctx) -> Self; - fn new_attachment(&self, ctx: &Ctx) -> ElementAttach; + fn new_attachment<'a>(&self, ctx: &Ctx, buffer_pool: &'a mut DataBufferPool) -> ElementAttach; // Bake the data into vertices and indices fn bake(&self, data: &Self::Data) -> (Vec, Option>); @@ -54,6 +78,8 @@ pub trait Element { fn pipeline(&self) -> &wgpu::RenderPipeline; fn draw(&self, attach: &ElementAttach, render_pass: &mut wgpu::RenderPass); + + fn load_data(&self, ctx: &Ctx, data: &Self::Data, attach: &ElementAttach); } pub struct ElementAttach { diff --git a/mp_elements/src/elements/ppi.rs b/mp_elements/src/elements/ppi.rs index ef0d885..42171ff 100644 --- a/mp_elements/src/elements/ppi.rs +++ b/mp_elements/src/elements/ppi.rs @@ -1,6 +1,9 @@ -use std::ops::Sub; +use std::{ops::Sub, result}; -use crate::{app::Ctx, utils::merge_shader}; +use crate::{ + app::{Ctx, DataBufferPool}, + utils::merge_shader, +}; use bytemuck; use glam::Vec3; use mp_core::{data::CoordType, RadarGridData}; @@ -152,11 +155,18 @@ impl Element for PPI { } } - fn new_attachment(&self, ctx: &Ctx) -> ElementAttach { + fn new_attachment<'a>(&self, ctx: &Ctx, buffer_pool: &'a mut DataBufferPool) -> ElementAttach { let device = ctx.device; // Buffers - let data_buffer = Self::create_data_buffer(device); + + let data_buffer = buffer_pool.get_or_create_buffer(); + // let data_buffer = if let Some(reused) = reused_buffer { + // reused[0] + // } else { + // &Self::create_data_buffer(device) + // }; + let uniform_buffer = Self::create_uniform_buffer(device); // Bind Group @@ -229,6 +239,30 @@ impl Element for PPI { fn draw(&self, attach: &ElementAttach, render_pass: &mut wgpu::RenderPass) { render_pass.draw_indexed(0..attach.num_indices, 0, 0..1); } + + fn load_data(&self, ctx: &Ctx, data: &Self::Data, attach: &ElementAttach) { + let (vertex, index) = self.bake(data); + let queue = ctx.queue; + + // Update Vertex Buffer + let vertex_buffer = &attach.vertex_buffer; + queue.write_buffer(vertex_buffer, 0, bytemuck::cast_slice(&vertex)); + + // Update Index Buffer + if let Some(indices) = index { + let index_buffer = attach.index_buffer.as_ref().unwrap(); + queue.write_buffer(index_buffer, 0, bytemuck::cast_slice(&indices)); + } + + // Load Data + let data_array = data.get_data(); + let data_array_f32 = data_array.cast_to::(); + queue.write_buffer( + data_buffer, + 0, + bytemuck::cast_slice(data_array_f32.as_slice().unwrap()), + ); + } } impl PPI {