mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
RenderResource ids
This commit is contained in:
parent
f84e71d051
commit
79c900bc2d
16 changed files with 503 additions and 241 deletions
|
@ -146,8 +146,8 @@ impl AppBuilder {
|
|||
assigned_meshes_draw_target,
|
||||
)
|
||||
.add_draw_target(resource_name::draw_target::UI, ui_draw_target)
|
||||
.add_resource_provider(Box::new(CameraResourceProvider))
|
||||
.add_resource_provider(Box::new(Camera2dResourceProvider))
|
||||
.add_resource_provider(Box::new(CameraResourceProvider::default()))
|
||||
.add_resource_provider(Box::new(Camera2dResourceProvider::default()))
|
||||
.add_resource_provider(Box::new(LightResourceProvider::new(10)))
|
||||
.add_resource_provider(Box::new(UiResourceProvider::new()))
|
||||
.add_resource_provider(Box::new(UniformResourceProvider::<StandardMaterial>::new()))
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Handle, Mesh},
|
||||
legion::prelude::*,
|
||||
render::render_graph::{
|
||||
resource_name, PipelineDescriptor, RenderPass, Renderable, ShaderPipelineAssignments,
|
||||
},
|
||||
render::render_graph::{PipelineDescriptor, RenderPass, Renderable, ShaderPipelineAssignments},
|
||||
};
|
||||
|
||||
use zerocopy::AsBytes;
|
||||
|
@ -19,6 +17,8 @@ pub fn assigned_meshes_draw_target(
|
|||
.get_mut::<ShaderPipelineAssignments>()
|
||||
.unwrap();
|
||||
let mut current_mesh_id = None;
|
||||
let mut current_mesh_vertex_buffer = None;
|
||||
let mut current_mesh_index_buffer = None;
|
||||
let mut current_mesh_index_length = 0;
|
||||
|
||||
let assigned_entities = shader_pipeline_assignments
|
||||
|
@ -42,25 +42,25 @@ pub fn assigned_meshes_draw_target(
|
|||
if should_load_mesh {
|
||||
if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) {
|
||||
let renderer = render_pass.get_renderer();
|
||||
renderer.create_buffer_with_data(
|
||||
resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME,
|
||||
if let Some(buffer) = current_mesh_vertex_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
|
||||
if let Some(buffer) = current_mesh_index_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
current_mesh_vertex_buffer = Some(renderer.create_buffer_with_data(
|
||||
mesh_asset.vertices.as_bytes(),
|
||||
wgpu::BufferUsage::VERTEX,
|
||||
);
|
||||
renderer.create_buffer_with_data(
|
||||
resource_name::buffer::TEMP_MESH_INDEX_BUFFER_NAME,
|
||||
));
|
||||
current_mesh_index_buffer = Some(renderer.create_buffer_with_data(
|
||||
mesh_asset.indices.as_bytes(),
|
||||
wgpu::BufferUsage::INDEX,
|
||||
);
|
||||
));
|
||||
|
||||
// TODO: Verify buffer format matches render pass
|
||||
render_pass
|
||||
.set_index_buffer(resource_name::buffer::TEMP_MESH_INDEX_BUFFER_NAME, 0);
|
||||
render_pass.set_vertex_buffer(
|
||||
0,
|
||||
resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME,
|
||||
0,
|
||||
);
|
||||
render_pass.set_index_buffer(current_mesh_index_buffer.unwrap(), 0);
|
||||
render_pass.set_vertex_buffer(0, current_mesh_vertex_buffer.unwrap(), 0);
|
||||
current_mesh_id = Some(mesh.id);
|
||||
current_mesh_index_length = mesh_asset.indices.len() as u32;
|
||||
};
|
||||
|
@ -73,7 +73,12 @@ pub fn assigned_meshes_draw_target(
|
|||
|
||||
// cleanup buffers
|
||||
let renderer = render_pass.get_renderer();
|
||||
renderer.remove_buffer(resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME);
|
||||
renderer.remove_buffer(resource_name::buffer::TEMP_MESH_INDEX_BUFFER_NAME);
|
||||
if let Some(buffer) = current_mesh_vertex_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
|
||||
if let Some(buffer) = current_mesh_index_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
asset::{AssetStorage, Handle, Mesh},
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
render_graph::{resource_name, PipelineDescriptor, RenderPass, Renderable},
|
||||
render_graph::{PipelineDescriptor, RenderPass, Renderable},
|
||||
Instanced,
|
||||
},
|
||||
};
|
||||
|
@ -16,9 +16,12 @@ pub fn meshes_draw_target(
|
|||
) {
|
||||
let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
let mut current_mesh_id = None;
|
||||
let mut current_mesh_vertex_buffer = None;
|
||||
let mut current_mesh_index_buffer = None;
|
||||
let mut current_mesh_index_length = 0;
|
||||
let mesh_query =
|
||||
<(Read<Handle<Mesh>>, Read<Renderable>)>::query().filter(!component::<Instanced>());
|
||||
|
||||
for (entity, (mesh, renderable)) in mesh_query.iter_entities(world) {
|
||||
if !renderable.is_visible {
|
||||
continue;
|
||||
|
@ -32,24 +35,25 @@ pub fn meshes_draw_target(
|
|||
if should_load_mesh {
|
||||
if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) {
|
||||
let renderer = render_pass.get_renderer();
|
||||
renderer.create_buffer_with_data(
|
||||
resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME,
|
||||
if let Some(buffer) = current_mesh_vertex_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
|
||||
if let Some(buffer) = current_mesh_index_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
current_mesh_vertex_buffer = Some(renderer.create_buffer_with_data(
|
||||
mesh_asset.vertices.as_bytes(),
|
||||
wgpu::BufferUsage::VERTEX,
|
||||
);
|
||||
renderer.create_buffer_with_data(
|
||||
resource_name::buffer::TEMP_MESH_INDEX_BUFFER_NAME,
|
||||
));
|
||||
current_mesh_index_buffer = Some(renderer.create_buffer_with_data(
|
||||
mesh_asset.indices.as_bytes(),
|
||||
wgpu::BufferUsage::INDEX,
|
||||
);
|
||||
));
|
||||
|
||||
// TODO: Verify buffer format matches render pass
|
||||
render_pass.set_index_buffer(resource_name::buffer::TEMP_MESH_INDEX_BUFFER_NAME, 0);
|
||||
render_pass.set_vertex_buffer(
|
||||
0,
|
||||
resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME,
|
||||
0,
|
||||
);
|
||||
render_pass.set_index_buffer(current_mesh_index_buffer.unwrap(), 0);
|
||||
render_pass.set_vertex_buffer(0, current_mesh_vertex_buffer.unwrap(), 0);
|
||||
current_mesh_id = Some(mesh.id);
|
||||
current_mesh_index_length = mesh_asset.indices.len() as u32;
|
||||
};
|
||||
|
@ -62,6 +66,12 @@ pub fn meshes_draw_target(
|
|||
|
||||
// cleanup buffers
|
||||
let renderer = render_pass.get_renderer();
|
||||
renderer.remove_buffer(resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME);
|
||||
renderer.remove_buffer(resource_name::buffer::TEMP_MESH_INDEX_BUFFER_NAME);
|
||||
|
||||
if let Some(buffer) = current_mesh_vertex_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
|
||||
if let Some(buffer) = current_mesh_index_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,11 +12,20 @@ pub fn ui_draw_target(
|
|||
_pipeline_handle: Handle<PipelineDescriptor>,
|
||||
) {
|
||||
let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
let mut current_mesh_vertex_buffer = None;
|
||||
let mut current_mesh_index_buffer = None;
|
||||
let ui_instances_buffer = {
|
||||
let renderer = render_pass.get_renderer();
|
||||
match renderer.get_named_resource(resource_name::buffer::UI_INSTANCES) {
|
||||
Some(buffer) => buffer,
|
||||
None => return,
|
||||
}
|
||||
};
|
||||
// NOTE: this is ugly and borrowing is stupid
|
||||
let result = {
|
||||
let renderer = render_pass.get_renderer();
|
||||
let result = if let Some(ResourceInfo::InstanceBuffer { count, mesh_id, .. }) =
|
||||
renderer.get_resource_info(resource_name::buffer::UI_INSTANCES)
|
||||
renderer.get_resource_info(ui_instances_buffer)
|
||||
{
|
||||
Some((*count, *mesh_id))
|
||||
} else {
|
||||
|
@ -25,16 +34,21 @@ pub fn ui_draw_target(
|
|||
|
||||
if let Some((instance_count, mesh_id)) = result {
|
||||
if let Some(mesh_asset) = mesh_storage.get_id(mesh_id) {
|
||||
renderer.create_buffer_with_data(
|
||||
resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME,
|
||||
if let Some(buffer) = current_mesh_vertex_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
|
||||
if let Some(buffer) = current_mesh_index_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
current_mesh_vertex_buffer = Some(renderer.create_buffer_with_data(
|
||||
mesh_asset.vertices.as_bytes(),
|
||||
wgpu::BufferUsage::VERTEX,
|
||||
);
|
||||
renderer.create_buffer_with_data(
|
||||
resource_name::buffer::TEMP_MESH_INDEX_BUFFER_NAME,
|
||||
));
|
||||
current_mesh_index_buffer = Some(renderer.create_buffer_with_data(
|
||||
mesh_asset.indices.as_bytes(),
|
||||
wgpu::BufferUsage::INDEX,
|
||||
);
|
||||
));
|
||||
Some((instance_count, mesh_asset.indices.len()))
|
||||
} else {
|
||||
None
|
||||
|
@ -45,9 +59,18 @@ pub fn ui_draw_target(
|
|||
};
|
||||
if let Some((instance_count, indices_length)) = result {
|
||||
render_pass.setup_bind_groups(None);
|
||||
render_pass.set_index_buffer(resource_name::buffer::TEMP_MESH_INDEX_BUFFER_NAME, 0);
|
||||
render_pass.set_vertex_buffer(0, resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME, 0);
|
||||
render_pass.set_vertex_buffer(1, resource_name::buffer::UI_INSTANCES, 0);
|
||||
render_pass.set_index_buffer(current_mesh_index_buffer.unwrap(), 0);
|
||||
render_pass.set_vertex_buffer(0, current_mesh_vertex_buffer.unwrap(), 0);
|
||||
render_pass.set_vertex_buffer(1, ui_instances_buffer, 0);
|
||||
render_pass.draw_indexed(0..indices_length as u32, 0, 0..(instance_count as u32));
|
||||
}
|
||||
|
||||
let renderer = render_pass.get_renderer();
|
||||
if let Some(buffer) = current_mesh_vertex_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
|
||||
if let Some(buffer) = current_mesh_index_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ mod pipeline;
|
|||
mod pipeline_layout;
|
||||
pub mod pipelines;
|
||||
mod render_graph;
|
||||
mod render_resource;
|
||||
mod renderable;
|
||||
mod renderer;
|
||||
pub mod renderers;
|
||||
|
@ -21,6 +22,7 @@ pub use pass::*;
|
|||
pub use pipeline::*;
|
||||
pub use pipeline_layout::*;
|
||||
pub use render_graph::*;
|
||||
pub use render_resource::*;
|
||||
pub use renderable::*;
|
||||
pub use renderer::*;
|
||||
pub use resource::*;
|
||||
|
|
|
@ -16,10 +16,6 @@ layout(set = 1, binding = 0) uniform Object {
|
|||
mat4 Model;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 1) uniform StandardMaterial_albedo {
|
||||
vec4 Albedo;
|
||||
};
|
||||
|
||||
void main() {
|
||||
v_Normal = mat3(Model) * vec3(a_Normal.xyz);
|
||||
v_Position = Model * vec4(a_Pos);
|
||||
|
|
37
src/render/render_graph/render_resource.rs
Normal file
37
src/render/render_graph/render_resource.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
use crate::asset::{Handle, Texture};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Copy, Clone, Hash, Debug, Eq, PartialEq)]
|
||||
pub struct RenderResource(pub u64);
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RenderResources {
|
||||
pub name_to_resource: HashMap<String, RenderResource>,
|
||||
pub texture_to_resource: HashMap<Handle<Texture>, RenderResource>,
|
||||
pub resource_index: u64,
|
||||
}
|
||||
|
||||
impl RenderResources {
|
||||
pub fn set_named_resource(&mut self, name: &str, resource: RenderResource) {
|
||||
self.name_to_resource.insert(name.to_string(), resource);
|
||||
}
|
||||
|
||||
pub fn get_named_resource(&self, name: &str) -> Option<RenderResource> {
|
||||
self.name_to_resource.get(name).cloned()
|
||||
}
|
||||
|
||||
pub fn set_texture_resource(&mut self, texture: Handle<Texture>, resource: RenderResource) {
|
||||
self.texture_to_resource.insert(texture, resource);
|
||||
}
|
||||
|
||||
pub fn get_texture_resource(&self, texture: Handle<Texture>) -> Option<RenderResource> {
|
||||
self.texture_to_resource.get(&texture).cloned()
|
||||
}
|
||||
|
||||
pub fn get_next_resource(&mut self) -> RenderResource {
|
||||
let resource = self.resource_index;
|
||||
self.resource_index += 1;
|
||||
|
||||
RenderResource(resource)
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{
|
||||
legion::prelude::*,
|
||||
render::render_graph::{
|
||||
DynamicUniformBufferInfo, PipelineDescriptor, RenderGraph, ResourceInfo, TextureDescriptor,
|
||||
render_resource::RenderResource, DynamicUniformBufferInfo, PipelineDescriptor, RenderGraph,
|
||||
ResourceInfo, TextureDescriptor,
|
||||
},
|
||||
};
|
||||
use std::ops::Range;
|
||||
|
@ -17,57 +18,74 @@ pub trait Renderer {
|
|||
);
|
||||
fn process_render_graph(&mut self, render_graph: &mut RenderGraph, world: &mut World);
|
||||
// TODO: swap out wgpu::BufferUsage for non-wgpu type
|
||||
fn create_buffer_with_data(&mut self, name: &str, data: &[u8], buffer_usage: wgpu::BufferUsage);
|
||||
fn create_texture(&mut self, name: &str, texture_descriptor: &TextureDescriptor);
|
||||
fn get_dynamic_uniform_buffer_info(&self, name: &str) -> Option<&DynamicUniformBufferInfo>;
|
||||
fn create_buffer_with_data(
|
||||
&mut self,
|
||||
data: &[u8],
|
||||
buffer_usage: wgpu::BufferUsage,
|
||||
) -> RenderResource;
|
||||
fn create_texture(&mut self, texture_descriptor: &TextureDescriptor) -> RenderResource;
|
||||
fn create_texture_with_data(
|
||||
&mut self,
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
bytes: Option<&[u8]>,
|
||||
) -> RenderResource;
|
||||
// TODO: remove this and replace it with ResourceInfo
|
||||
fn get_dynamic_uniform_buffer_info(
|
||||
&self,
|
||||
resource: RenderResource,
|
||||
) -> Option<&DynamicUniformBufferInfo>;
|
||||
fn get_dynamic_uniform_buffer_info_mut(
|
||||
&mut self,
|
||||
name: &str,
|
||||
resource: RenderResource,
|
||||
) -> Option<&mut DynamicUniformBufferInfo>;
|
||||
fn add_dynamic_uniform_buffer_info(&mut self, name: &str, info: DynamicUniformBufferInfo);
|
||||
fn create_buffer(&mut self, name: &str, size: u64, buffer_usage: wgpu::BufferUsage);
|
||||
fn add_dynamic_uniform_buffer_info(
|
||||
&mut self,
|
||||
resource: RenderResource,
|
||||
info: DynamicUniformBufferInfo,
|
||||
);
|
||||
fn create_buffer(&mut self, size: u64, buffer_usage: wgpu::BufferUsage) -> RenderResource;
|
||||
fn create_instance_buffer(
|
||||
&mut self,
|
||||
name: &str,
|
||||
mesh_id: usize,
|
||||
size: usize,
|
||||
count: usize,
|
||||
buffer_usage: wgpu::BufferUsage,
|
||||
);
|
||||
) -> RenderResource;
|
||||
fn create_instance_buffer_with_data(
|
||||
&mut self,
|
||||
name: &str,
|
||||
mesh_id: usize,
|
||||
data: &[u8],
|
||||
size: usize,
|
||||
count: usize,
|
||||
buffer_usage: wgpu::BufferUsage,
|
||||
);
|
||||
) -> RenderResource;
|
||||
fn create_buffer_mapped(
|
||||
&mut self,
|
||||
name: &str,
|
||||
size: usize,
|
||||
buffer_usage: wgpu::BufferUsage,
|
||||
func: &mut dyn FnMut(&mut [u8]),
|
||||
);
|
||||
fn remove_buffer(&mut self, name: &str);
|
||||
fn get_resource_info(&self, name: &str) -> Option<&ResourceInfo>;
|
||||
) -> RenderResource;
|
||||
fn remove_buffer(&mut self, resource: RenderResource);
|
||||
fn remove_texture(&mut self, resource: RenderResource);
|
||||
fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo>;
|
||||
fn copy_buffer_to_buffer(
|
||||
&mut self,
|
||||
source_buffer: &str,
|
||||
source_buffer: RenderResource,
|
||||
source_offset: u64,
|
||||
destination_buffer: &str,
|
||||
destination_buffer: RenderResource,
|
||||
destination_offset: u64,
|
||||
size: u64,
|
||||
);
|
||||
fn get_named_resource(&self, name: &str) -> Option<RenderResource>;
|
||||
fn set_named_resource(&mut self, name: &str, resource: RenderResource);
|
||||
}
|
||||
|
||||
pub trait RenderPass {
|
||||
// TODO: consider using static dispatch for the renderer: Renderer<WgpuBackend>. compare compile times
|
||||
fn get_renderer(&mut self) -> &mut dyn Renderer;
|
||||
fn get_pipeline_descriptor(&self) -> &PipelineDescriptor;
|
||||
fn set_index_buffer(&mut self, name: &str, offset: u64);
|
||||
fn set_vertex_buffer(&mut self, start_slot: u32, name: &str, offset: u64);
|
||||
fn set_index_buffer(&mut self, resource: RenderResource, offset: u64);
|
||||
fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64);
|
||||
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>);
|
||||
fn setup_bind_groups(&mut self, entity: Option<&Entity>);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ use crate::{
|
|||
resource_name, update_shader_assignments, BindGroup, BindType,
|
||||
DynamicUniformBufferInfo, PassDescriptor, PipelineDescriptor, PipelineLayout,
|
||||
PipelineLayoutType, RenderGraph, RenderPass, RenderPassColorAttachmentDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, Renderer, ResourceInfo, TextureDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, RenderResource, RenderResources, Renderer,
|
||||
ResourceInfo, TextureDescriptor,
|
||||
},
|
||||
Shader,
|
||||
},
|
||||
|
@ -20,12 +21,13 @@ pub struct WgpuRenderer {
|
|||
pub encoder: Option<wgpu::CommandEncoder>,
|
||||
pub swap_chain_descriptor: wgpu::SwapChainDescriptor,
|
||||
pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
|
||||
pub buffers: HashMap<String, wgpu::Buffer>,
|
||||
pub textures: HashMap<String, wgpu::TextureView>,
|
||||
pub resource_info: HashMap<String, ResourceInfo>,
|
||||
pub buffers: HashMap<RenderResource, wgpu::Buffer>,
|
||||
pub textures: HashMap<RenderResource, wgpu::TextureView>,
|
||||
pub resource_info: HashMap<RenderResource, ResourceInfo>,
|
||||
pub bind_groups: HashMap<u64, BindGroupInfo>,
|
||||
pub bind_group_layouts: HashMap<u64, wgpu::BindGroupLayout>,
|
||||
pub dynamic_uniform_buffer_info: HashMap<String, DynamicUniformBufferInfo>,
|
||||
pub dynamic_uniform_buffer_info: HashMap<RenderResource, DynamicUniformBufferInfo>,
|
||||
pub render_resources: RenderResources,
|
||||
}
|
||||
|
||||
impl WgpuRenderer {
|
||||
|
@ -66,11 +68,13 @@ impl WgpuRenderer {
|
|||
bind_groups: HashMap::new(),
|
||||
bind_group_layouts: HashMap::new(),
|
||||
dynamic_uniform_buffer_info: HashMap::new(),
|
||||
render_resources: RenderResources::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_render_pipeline(
|
||||
dynamic_uniform_buffer_info: &HashMap<String, DynamicUniformBufferInfo>,
|
||||
render_resources: &RenderResources,
|
||||
dynamic_uniform_buffer_info: &HashMap<RenderResource, DynamicUniformBufferInfo>,
|
||||
pipeline_descriptor: &mut PipelineDescriptor,
|
||||
bind_group_layouts: &mut HashMap<u64, wgpu::BindGroupLayout>,
|
||||
device: &wgpu::Device,
|
||||
|
@ -106,8 +110,12 @@ impl WgpuRenderer {
|
|||
ref mut dynamic, ..
|
||||
} = binding.bind_type
|
||||
{
|
||||
if dynamic_uniform_buffer_info.contains_key(&binding.name) {
|
||||
*dynamic = true;
|
||||
if let Some(resource) =
|
||||
render_resources.get_named_resource(&binding.name)
|
||||
{
|
||||
if dynamic_uniform_buffer_info.contains_key(&resource) {
|
||||
*dynamic = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,16 +224,30 @@ impl WgpuRenderer {
|
|||
) -> wgpu::RenderPassColorAttachmentDescriptor<'a> {
|
||||
let attachment = match color_attachment_descriptor.attachment.as_str() {
|
||||
resource_name::texture::SWAP_CHAIN => &frame.view,
|
||||
_ => self
|
||||
.textures
|
||||
.get(&color_attachment_descriptor.attachment)
|
||||
.unwrap(),
|
||||
_ => {
|
||||
match self
|
||||
.render_resources
|
||||
.get_named_resource(&color_attachment_descriptor.attachment)
|
||||
{
|
||||
Some(resource) => self.textures.get(&resource).unwrap(),
|
||||
None => panic!(
|
||||
"Color attachment {} does not exist",
|
||||
&color_attachment_descriptor.attachment
|
||||
),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let resolve_target = match color_attachment_descriptor.resolve_target {
|
||||
Some(ref target) => match target.as_str() {
|
||||
resource_name::texture::SWAP_CHAIN => Some(&frame.view),
|
||||
_ => Some(&frame.view),
|
||||
_ => match self.render_resources.get_named_resource(target.as_str()) {
|
||||
Some(resource) => Some(self.textures.get(&resource).unwrap()),
|
||||
None => panic!(
|
||||
"Color attachment {} does not exist",
|
||||
&color_attachment_descriptor.attachment
|
||||
),
|
||||
},
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
@ -246,10 +268,18 @@ impl WgpuRenderer {
|
|||
) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<&'a wgpu::TextureView> {
|
||||
let attachment = match depth_stencil_attachment_descriptor.attachment.as_str() {
|
||||
resource_name::texture::SWAP_CHAIN => &frame.view,
|
||||
_ => self
|
||||
.textures
|
||||
.get(&depth_stencil_attachment_descriptor.attachment)
|
||||
.unwrap(),
|
||||
_ => {
|
||||
match self
|
||||
.render_resources
|
||||
.get_named_resource(&depth_stencil_attachment_descriptor.attachment)
|
||||
{
|
||||
Some(ref resource) => self.textures.get(&resource).unwrap(),
|
||||
None => panic!(
|
||||
"Depth stencil attachment {} does not exist",
|
||||
&depth_stencil_attachment_descriptor.attachment
|
||||
),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
||||
|
@ -263,8 +293,8 @@ impl WgpuRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_resource_info(&mut self, name: &str, resource_info: ResourceInfo) {
|
||||
self.resource_info.insert(name.to_string(), resource_info);
|
||||
fn add_resource_info(&mut self, resource: RenderResource, resource_info: ResourceInfo) {
|
||||
self.resource_info.insert(resource, resource_info);
|
||||
}
|
||||
|
||||
// TODO: consider moving this to a resource provider
|
||||
|
@ -273,31 +303,45 @@ impl WgpuRenderer {
|
|||
|
||||
if let None = self.bind_groups.get(&bind_group_id) {
|
||||
let mut unset_uniforms = Vec::new();
|
||||
|
||||
let mut binding_resources = Vec::with_capacity(bind_group.bindings.len());
|
||||
// if a uniform resource buffer doesn't exist, create a new empty one
|
||||
for binding in bind_group.bindings.iter() {
|
||||
if let None = self.resource_info.get(&binding.name) {
|
||||
println!(
|
||||
"Warning: creating new empty buffer for binding {}",
|
||||
binding.name
|
||||
);
|
||||
unset_uniforms.push(binding.name.to_string());
|
||||
if let BindType::Uniform { .. } = &binding.bind_type {
|
||||
let size = binding.bind_type.get_uniform_size().unwrap();
|
||||
self.create_buffer(
|
||||
&binding.name,
|
||||
size,
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
)
|
||||
let resource = match self.render_resources.get_named_resource(&binding.name) {
|
||||
Some(resource) => resource,
|
||||
None => {
|
||||
println!(
|
||||
"Warning: creating new empty buffer for binding {} {:?}",
|
||||
binding.name, binding
|
||||
);
|
||||
unset_uniforms.push(binding.name.to_string());
|
||||
match binding.bind_type {
|
||||
BindType::Uniform { .. } => {
|
||||
let size = binding.bind_type.get_uniform_size().unwrap();
|
||||
let resource = self.create_buffer(
|
||||
size,
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
);
|
||||
|
||||
self.render_resources
|
||||
.set_named_resource(&binding.name, resource);
|
||||
resource
|
||||
}
|
||||
_ => panic!("unsupported bind type: {:?}", binding),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
binding_resources.push(resource);
|
||||
}
|
||||
|
||||
// create wgpu Bindings
|
||||
let bindings = bind_group
|
||||
.bindings
|
||||
.iter()
|
||||
.map(|binding| {
|
||||
let resource_info = self.resource_info.get(&binding.name).unwrap();
|
||||
.zip(binding_resources)
|
||||
.map(|(binding, resource)| {
|
||||
let resource_info = self.resource_info.get(&resource).unwrap();
|
||||
wgpu::Binding {
|
||||
binding: binding.index,
|
||||
resource: match &binding.bind_type {
|
||||
|
@ -310,7 +354,7 @@ impl WgpuRenderer {
|
|||
buffer_usage: _,
|
||||
} = resource_info
|
||||
{
|
||||
let buffer = self.buffers.get(&binding.name).unwrap();
|
||||
let buffer = self.buffers.get(&resource).unwrap();
|
||||
wgpu::BindingResource::Buffer {
|
||||
buffer,
|
||||
range: 0..*size,
|
||||
|
@ -430,7 +474,8 @@ impl Renderer for WgpuRenderer {
|
|||
update_shader_assignments(world, render_graph);
|
||||
|
||||
for (name, texture_descriptor) in render_graph.queued_textures.drain(..) {
|
||||
self.create_texture(&name, &texture_descriptor);
|
||||
let resource = self.create_texture(&texture_descriptor);
|
||||
self.render_resources.set_named_resource(&name, resource);
|
||||
}
|
||||
|
||||
let mut encoder = self.encoder.take().unwrap();
|
||||
|
@ -467,6 +512,7 @@ impl Renderer for WgpuRenderer {
|
|||
.as_ref()
|
||||
.map(|handle| &*shader_storage.get(&handle).unwrap());
|
||||
let render_pipeline = WgpuRenderer::create_render_pipeline(
|
||||
&self.render_resources,
|
||||
&self.dynamic_uniform_buffer_info,
|
||||
pipeline_descriptor,
|
||||
&mut self.bind_group_layouts,
|
||||
|
@ -514,48 +560,51 @@ impl Renderer for WgpuRenderer {
|
|||
|
||||
fn create_buffer_with_data(
|
||||
&mut self,
|
||||
name: &str,
|
||||
data: &[u8],
|
||||
buffer_usage: wgpu::BufferUsage,
|
||||
) {
|
||||
) -> RenderResource {
|
||||
let resource = self.render_resources.get_next_resource();
|
||||
let buffer = self.device.create_buffer_with_data(data, buffer_usage);
|
||||
self.add_resource_info(
|
||||
name,
|
||||
resource,
|
||||
ResourceInfo::Buffer {
|
||||
buffer_usage,
|
||||
size: data.len() as u64,
|
||||
},
|
||||
);
|
||||
|
||||
self.buffers.insert(name.to_string(), buffer);
|
||||
self.buffers.insert(resource, buffer);
|
||||
resource
|
||||
}
|
||||
|
||||
fn create_buffer(&mut self, name: &str, size: u64, buffer_usage: wgpu::BufferUsage) {
|
||||
fn create_buffer(&mut self, size: u64, buffer_usage: wgpu::BufferUsage) -> RenderResource {
|
||||
let buffer = self.device.create_buffer(&wgpu::BufferDescriptor {
|
||||
size,
|
||||
usage: buffer_usage,
|
||||
});
|
||||
|
||||
self.add_resource_info(name, ResourceInfo::Buffer { buffer_usage, size });
|
||||
let resource = self.render_resources.get_next_resource();
|
||||
self.add_resource_info(resource, ResourceInfo::Buffer { buffer_usage, size });
|
||||
|
||||
self.buffers.insert(name.to_string(), buffer);
|
||||
self.buffers.insert(resource, buffer);
|
||||
resource
|
||||
}
|
||||
|
||||
fn create_instance_buffer(
|
||||
&mut self,
|
||||
name: &str,
|
||||
mesh_id: usize,
|
||||
size: usize,
|
||||
count: usize,
|
||||
buffer_usage: wgpu::BufferUsage,
|
||||
) {
|
||||
) -> RenderResource {
|
||||
let buffer = self.device.create_buffer(&wgpu::BufferDescriptor {
|
||||
size: (size * count) as u64,
|
||||
usage: buffer_usage,
|
||||
});
|
||||
|
||||
let resource = self.render_resources.get_next_resource();
|
||||
self.add_resource_info(
|
||||
name,
|
||||
resource,
|
||||
ResourceInfo::InstanceBuffer {
|
||||
buffer_usage,
|
||||
size,
|
||||
|
@ -564,22 +613,23 @@ impl Renderer for WgpuRenderer {
|
|||
},
|
||||
);
|
||||
|
||||
self.buffers.insert(name.to_string(), buffer);
|
||||
self.buffers.insert(resource, buffer);
|
||||
resource
|
||||
}
|
||||
|
||||
fn create_instance_buffer_with_data(
|
||||
&mut self,
|
||||
name: &str,
|
||||
mesh_id: usize,
|
||||
data: &[u8],
|
||||
size: usize,
|
||||
count: usize,
|
||||
buffer_usage: wgpu::BufferUsage,
|
||||
) {
|
||||
) -> RenderResource {
|
||||
let buffer = self.device.create_buffer_with_data(data, buffer_usage);
|
||||
let resource = self.render_resources.get_next_resource();
|
||||
|
||||
self.add_resource_info(
|
||||
name,
|
||||
resource,
|
||||
ResourceInfo::InstanceBuffer {
|
||||
buffer_usage,
|
||||
size,
|
||||
|
@ -588,73 +638,131 @@ impl Renderer for WgpuRenderer {
|
|||
},
|
||||
);
|
||||
|
||||
self.buffers.insert(name.to_string(), buffer);
|
||||
self.buffers.insert(resource, buffer);
|
||||
resource
|
||||
}
|
||||
|
||||
fn get_resource_info(&self, name: &str) -> Option<&ResourceInfo> {
|
||||
self.resource_info.get(name)
|
||||
fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> {
|
||||
self.resource_info.get(&resource)
|
||||
}
|
||||
|
||||
fn remove_buffer(&mut self, name: &str) {
|
||||
self.buffers.remove(name);
|
||||
fn remove_buffer(&mut self, resource: RenderResource) {
|
||||
self.buffers.remove(&resource);
|
||||
self.resource_info.remove(&resource);
|
||||
}
|
||||
|
||||
fn create_buffer_mapped(
|
||||
&mut self,
|
||||
name: &str,
|
||||
size: usize,
|
||||
buffer_usage: wgpu::BufferUsage,
|
||||
setup_data: &mut dyn FnMut(&mut [u8]),
|
||||
) {
|
||||
) -> RenderResource {
|
||||
let mut mapped = self.device.create_buffer_mapped(size, buffer_usage);
|
||||
setup_data(&mut mapped.data);
|
||||
let buffer = mapped.finish();
|
||||
|
||||
let resource = self.render_resources.get_next_resource();
|
||||
self.add_resource_info(
|
||||
name,
|
||||
resource,
|
||||
ResourceInfo::Buffer {
|
||||
buffer_usage,
|
||||
size: size as u64,
|
||||
},
|
||||
);
|
||||
|
||||
self.buffers.insert(name.to_string(), buffer);
|
||||
self.buffers.insert(resource, buffer);
|
||||
resource
|
||||
}
|
||||
|
||||
fn copy_buffer_to_buffer(
|
||||
&mut self,
|
||||
source_buffer: &str,
|
||||
source_buffer: RenderResource,
|
||||
source_offset: u64,
|
||||
destination_buffer: &str,
|
||||
destination_buffer: RenderResource,
|
||||
destination_offset: u64,
|
||||
size: u64,
|
||||
) {
|
||||
let source = self.buffers.get(source_buffer).unwrap();
|
||||
let destination = self.buffers.get(destination_buffer).unwrap();
|
||||
let source = self.buffers.get(&source_buffer).unwrap();
|
||||
let destination = self.buffers.get(&destination_buffer).unwrap();
|
||||
let encoder = self.encoder.as_mut().unwrap();
|
||||
encoder.copy_buffer_to_buffer(source, source_offset, destination, destination_offset, size);
|
||||
}
|
||||
fn get_dynamic_uniform_buffer_info(&self, name: &str) -> Option<&DynamicUniformBufferInfo> {
|
||||
self.dynamic_uniform_buffer_info.get(name)
|
||||
fn get_dynamic_uniform_buffer_info(
|
||||
&self,
|
||||
resource: RenderResource,
|
||||
) -> Option<&DynamicUniformBufferInfo> {
|
||||
self.dynamic_uniform_buffer_info.get(&resource)
|
||||
}
|
||||
|
||||
fn get_dynamic_uniform_buffer_info_mut(
|
||||
&mut self,
|
||||
name: &str,
|
||||
resource: RenderResource,
|
||||
) -> Option<&mut DynamicUniformBufferInfo> {
|
||||
self.dynamic_uniform_buffer_info.get_mut(name)
|
||||
self.dynamic_uniform_buffer_info.get_mut(&resource)
|
||||
}
|
||||
|
||||
fn add_dynamic_uniform_buffer_info(&mut self, name: &str, info: DynamicUniformBufferInfo) {
|
||||
self.dynamic_uniform_buffer_info
|
||||
.insert(name.to_string(), info);
|
||||
fn add_dynamic_uniform_buffer_info(
|
||||
&mut self,
|
||||
resource: RenderResource,
|
||||
info: DynamicUniformBufferInfo,
|
||||
) {
|
||||
self.dynamic_uniform_buffer_info.insert(resource, info);
|
||||
}
|
||||
|
||||
fn create_texture(&mut self, name: &str, texture_descriptor: &TextureDescriptor) {
|
||||
fn create_texture(&mut self, texture_descriptor: &TextureDescriptor) -> RenderResource {
|
||||
let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).into();
|
||||
let texture = self.device.create_texture(&descriptor);
|
||||
let resource = self.render_resources.get_next_resource();
|
||||
self.textures
|
||||
.insert(name.to_string(), texture.create_default_view());
|
||||
.insert(resource, texture.create_default_view());
|
||||
resource
|
||||
}
|
||||
|
||||
fn create_texture_with_data(
|
||||
&mut self,
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
bytes: Option<&[u8]>,
|
||||
) -> RenderResource {
|
||||
let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).into();
|
||||
let texture = self.device.create_texture(&descriptor);
|
||||
let texture_view = texture.create_default_view();
|
||||
if let Some(bytes) = bytes {
|
||||
let temp_buf = self
|
||||
.device
|
||||
.create_buffer_with_data(bytes, wgpu::BufferUsage::COPY_SRC);
|
||||
self.encoder.as_mut().unwrap().copy_buffer_to_texture(
|
||||
wgpu::BufferCopyView {
|
||||
buffer: &temp_buf,
|
||||
offset: 0,
|
||||
row_pitch: 4 * descriptor.size.width,
|
||||
image_height: descriptor.size.height,
|
||||
},
|
||||
wgpu::TextureCopyView {
|
||||
texture: &texture,
|
||||
mip_level: 0,
|
||||
array_layer: 0,
|
||||
origin: wgpu::Origin3d { x: 0, y: 0, z: 0 },
|
||||
},
|
||||
descriptor.size,
|
||||
);
|
||||
}
|
||||
|
||||
let resource = self.render_resources.get_next_resource();
|
||||
self.add_resource_info(resource, ResourceInfo::Texture);
|
||||
resource
|
||||
}
|
||||
|
||||
fn get_named_resource(&self, name: &str) -> Option<RenderResource> {
|
||||
self.render_resources.get_named_resource(name)
|
||||
}
|
||||
|
||||
fn set_named_resource(&mut self, name: &str, resource: RenderResource) {
|
||||
self.render_resources.set_named_resource(name, resource);
|
||||
}
|
||||
|
||||
fn remove_texture(&mut self, resource: RenderResource) {
|
||||
self.textures.remove(&resource);
|
||||
self.resource_info.remove(&resource);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -673,14 +781,14 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
|
|||
self.pipeline_descriptor
|
||||
}
|
||||
|
||||
fn set_vertex_buffer(&mut self, start_slot: u32, name: &str, offset: u64) {
|
||||
let buffer = self.renderer.buffers.get(name).unwrap();
|
||||
fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64) {
|
||||
let buffer = self.renderer.buffers.get(&resource).unwrap();
|
||||
self.render_pass
|
||||
.set_vertex_buffers(start_slot, &[(&buffer, offset)]);
|
||||
}
|
||||
|
||||
fn set_index_buffer(&mut self, name: &str, offset: u64) {
|
||||
let buffer = self.renderer.buffers.get(name).unwrap();
|
||||
fn set_index_buffer(&mut self, resource: RenderResource, offset: u64) {
|
||||
let buffer = self.renderer.buffers.get(&resource).unwrap();
|
||||
self.render_pass.set_index_buffer(&buffer, offset);
|
||||
}
|
||||
|
||||
|
@ -707,16 +815,22 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
|
|||
continue;
|
||||
}
|
||||
|
||||
// PERF: This hashmap get is pretty expensive (10 fps for 10000 entities)
|
||||
if let Some(dynamic_uniform_buffer_info) =
|
||||
self.renderer.dynamic_uniform_buffer_info.get(&binding.name)
|
||||
if let Some(resource) = self
|
||||
.renderer
|
||||
.render_resources
|
||||
.get_named_resource(&binding.name)
|
||||
{
|
||||
let index = dynamic_uniform_buffer_info
|
||||
.offsets
|
||||
.get(entity.unwrap())
|
||||
.unwrap();
|
||||
// PERF: This hashmap get is pretty expensive (10 fps for 10000 entities)
|
||||
if let Some(dynamic_uniform_buffer_info) =
|
||||
self.renderer.dynamic_uniform_buffer_info.get(&resource)
|
||||
{
|
||||
let index = dynamic_uniform_buffer_info
|
||||
.offsets
|
||||
.get(entity.unwrap())
|
||||
.unwrap();
|
||||
|
||||
dynamic_uniform_indices.push(*index);
|
||||
dynamic_uniform_indices.push(*index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,4 +15,5 @@ pub enum ResourceInfo {
|
|||
mesh_id: usize,
|
||||
// pub layout: Option<
|
||||
},
|
||||
Texture,
|
||||
}
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
use crate::render::{
|
||||
render_graph::{resource_name, Renderer, ResourceProvider},
|
||||
render_graph::{resource_name, RenderResource, Renderer, ResourceProvider},
|
||||
ActiveCamera2d, Camera,
|
||||
};
|
||||
use legion::prelude::*;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
pub struct Camera2dResourceProvider;
|
||||
#[derive(Default)]
|
||||
pub struct Camera2dResourceProvider {
|
||||
pub camera_buffer: Option<RenderResource>,
|
||||
pub tmp_buffer: Option<RenderResource>,
|
||||
}
|
||||
|
||||
impl ResourceProvider for Camera2dResourceProvider {
|
||||
fn initialize(&mut self, renderer: &mut dyn Renderer, _world: &mut World) {
|
||||
renderer.create_buffer(
|
||||
resource_name::uniform::CAMERA2D,
|
||||
let buffer = renderer.create_buffer(
|
||||
std::mem::size_of::<[[f32; 4]; 4]>() as u64,
|
||||
wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
|
||||
);
|
||||
|
||||
renderer.set_named_resource(resource_name::uniform::CAMERA2D, buffer);
|
||||
self.camera_buffer = Some(buffer);
|
||||
}
|
||||
|
||||
fn update(&mut self, _renderer: &mut dyn Renderer, _world: &mut World) {}
|
||||
|
@ -23,19 +29,22 @@ impl ResourceProvider for Camera2dResourceProvider {
|
|||
camera.update(width, height);
|
||||
let camera_matrix: [[f32; 4]; 4] = camera.view_matrix.to_cols_array_2d();
|
||||
|
||||
renderer.create_buffer_mapped(
|
||||
"camera2d_tmp",
|
||||
if let Some(old_tmp_buffer) = self.tmp_buffer {
|
||||
renderer.remove_buffer(old_tmp_buffer);
|
||||
}
|
||||
|
||||
self.tmp_buffer = Some(renderer.create_buffer_mapped(
|
||||
matrix_size,
|
||||
wgpu::BufferUsage::COPY_SRC,
|
||||
&mut |data| {
|
||||
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
|
||||
},
|
||||
);
|
||||
));
|
||||
|
||||
renderer.copy_buffer_to_buffer(
|
||||
"camera2d_tmp",
|
||||
self.tmp_buffer.unwrap(),
|
||||
0,
|
||||
resource_name::uniform::CAMERA2D,
|
||||
self.camera_buffer.unwrap(),
|
||||
0,
|
||||
matrix_size as u64,
|
||||
);
|
||||
|
|
|
@ -1,20 +1,26 @@
|
|||
use crate::render::{
|
||||
render_graph::{resource_name, Renderer, ResourceProvider},
|
||||
render_graph::{resource_name, RenderResource, Renderer, ResourceProvider},
|
||||
ActiveCamera, Camera,
|
||||
};
|
||||
use bevy_transform::prelude::LocalToWorld;
|
||||
use legion::prelude::*;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
pub struct CameraResourceProvider;
|
||||
#[derive(Default)]
|
||||
pub struct CameraResourceProvider {
|
||||
pub camera_buffer: Option<RenderResource>,
|
||||
pub tmp_buffer: Option<RenderResource>,
|
||||
}
|
||||
|
||||
impl ResourceProvider for CameraResourceProvider {
|
||||
fn initialize(&mut self, renderer: &mut dyn Renderer, _world: &mut World) {
|
||||
renderer.create_buffer(
|
||||
resource_name::uniform::CAMERA,
|
||||
let buffer = renderer.create_buffer(
|
||||
std::mem::size_of::<[[f32; 4]; 4]>() as u64,
|
||||
wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
|
||||
);
|
||||
|
||||
renderer.set_named_resource(resource_name::uniform::CAMERA, buffer);
|
||||
self.camera_buffer = Some(buffer);
|
||||
}
|
||||
|
||||
fn update(&mut self, _renderer: &mut dyn Renderer, _world: &mut World) {}
|
||||
|
@ -27,19 +33,22 @@ impl ResourceProvider for CameraResourceProvider {
|
|||
let camera_matrix: [[f32; 4]; 4] =
|
||||
(camera.view_matrix * local_to_world.0).to_cols_array_2d();
|
||||
|
||||
renderer.create_buffer_mapped(
|
||||
"camera_tmp",
|
||||
if let Some(old_tmp_buffer) = self.tmp_buffer {
|
||||
renderer.remove_buffer(old_tmp_buffer);
|
||||
}
|
||||
|
||||
self.tmp_buffer = Some(renderer.create_buffer_mapped(
|
||||
matrix_size,
|
||||
wgpu::BufferUsage::COPY_SRC,
|
||||
&mut |data| {
|
||||
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
|
||||
},
|
||||
);
|
||||
));
|
||||
|
||||
renderer.copy_buffer_to_buffer(
|
||||
"camera_tmp",
|
||||
self.tmp_buffer.unwrap(),
|
||||
0,
|
||||
resource_name::uniform::CAMERA,
|
||||
self.camera_buffer.unwrap(),
|
||||
0,
|
||||
matrix_size as u64,
|
||||
);
|
||||
|
|
|
@ -21,7 +21,13 @@ impl FrameTextureResourceProvider {
|
|||
let window_size = window.inner_size();
|
||||
self.descriptor.size.width = window_size.width;
|
||||
self.descriptor.size.height = window_size.height;
|
||||
renderer.create_texture(&self.name, &self.descriptor);
|
||||
|
||||
if let Some(old_resource) = renderer.get_named_resource(&self.name) {
|
||||
renderer.remove_texture(old_resource);
|
||||
}
|
||||
|
||||
let texture_resource = renderer.create_texture(&self.descriptor);
|
||||
renderer.set_named_resource(&self.name, texture_resource);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::render::{
|
||||
render_graph::{resource_name, Renderer, ResourceProvider},
|
||||
render_graph::{resource_name, RenderResource, Renderer, ResourceProvider},
|
||||
Light, LightRaw,
|
||||
};
|
||||
use bevy_transform::prelude::{LocalToWorld, Translation};
|
||||
|
@ -9,6 +9,9 @@ use zerocopy::AsBytes;
|
|||
pub struct LightResourceProvider {
|
||||
pub lights_are_dirty: bool,
|
||||
pub max_lights: usize,
|
||||
pub light_buffer: Option<RenderResource>,
|
||||
pub tmp_light_buffer: Option<RenderResource>,
|
||||
pub tmp_count_buffer: Option<RenderResource>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -22,6 +25,9 @@ impl LightResourceProvider {
|
|||
LightResourceProvider {
|
||||
lights_are_dirty: true,
|
||||
max_lights,
|
||||
light_buffer: None,
|
||||
tmp_light_buffer: None,
|
||||
tmp_count_buffer: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +38,12 @@ impl ResourceProvider for LightResourceProvider {
|
|||
+ self.max_lights * std::mem::size_of::<LightRaw>())
|
||||
as wgpu::BufferAddress;
|
||||
|
||||
renderer.create_buffer(
|
||||
resource_name::uniform::LIGHTS,
|
||||
let buffer = renderer.create_buffer(
|
||||
light_uniform_size,
|
||||
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::COPY_DST,
|
||||
);
|
||||
renderer.set_named_resource(resource_name::uniform::LIGHTS, buffer);
|
||||
self.light_buffer = Some(buffer);
|
||||
}
|
||||
|
||||
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World) {
|
||||
|
@ -52,8 +59,16 @@ impl ResourceProvider for LightResourceProvider {
|
|||
let size = std::mem::size_of::<LightRaw>();
|
||||
let total_size = size * light_count;
|
||||
let light_count_size = std::mem::size_of::<LightCount>();
|
||||
renderer.create_buffer_mapped(
|
||||
"LIGHT_TMP",
|
||||
|
||||
if let Some(old_tmp_light_buffer) = self.tmp_light_buffer {
|
||||
renderer.remove_buffer(old_tmp_light_buffer);
|
||||
}
|
||||
|
||||
if let Some(old_tmp_count_buffer) = self.tmp_count_buffer {
|
||||
renderer.remove_buffer(old_tmp_count_buffer);
|
||||
}
|
||||
|
||||
self.tmp_light_buffer = Some(renderer.create_buffer_mapped(
|
||||
total_size,
|
||||
wgpu::BufferUsage::COPY_SRC,
|
||||
&mut |data| {
|
||||
|
@ -65,28 +80,27 @@ impl ResourceProvider for LightResourceProvider {
|
|||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
renderer.create_buffer_mapped(
|
||||
"LIGHT_COUNT_TMP",
|
||||
));
|
||||
self.tmp_count_buffer = Some(renderer.create_buffer_mapped(
|
||||
light_count_size,
|
||||
wgpu::BufferUsage::COPY_SRC,
|
||||
&mut |data| {
|
||||
data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
|
||||
},
|
||||
);
|
||||
));
|
||||
|
||||
renderer.copy_buffer_to_buffer(
|
||||
"LIGHT_COUNT_TMP",
|
||||
self.tmp_count_buffer.unwrap(),
|
||||
0,
|
||||
resource_name::uniform::LIGHTS,
|
||||
self.light_buffer.unwrap(),
|
||||
0,
|
||||
light_count_size as wgpu::BufferAddress,
|
||||
);
|
||||
|
||||
renderer.copy_buffer_to_buffer(
|
||||
"LIGHT_TMP",
|
||||
self.tmp_light_buffer.unwrap(),
|
||||
0,
|
||||
resource_name::uniform::LIGHTS,
|
||||
self.light_buffer.unwrap(),
|
||||
light_count_size as u64,
|
||||
total_size as wgpu::BufferAddress,
|
||||
);
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
asset::{Asset, AssetStorage, Handle, Mesh, MeshType},
|
||||
ecs, math,
|
||||
prelude::Node,
|
||||
render::render_graph::{resource_name, Renderer, ResourceProvider},
|
||||
render::render_graph::{resource_name, RenderResource, Renderer, ResourceProvider},
|
||||
};
|
||||
use bevy_transform::prelude::Parent;
|
||||
use legion::prelude::*;
|
||||
|
@ -19,11 +19,15 @@ pub struct RectData {
|
|||
|
||||
pub struct UiResourceProvider {
|
||||
pub quad: Option<Handle<Mesh>>,
|
||||
pub instance_buffer: Option<RenderResource>,
|
||||
}
|
||||
|
||||
impl UiResourceProvider {
|
||||
pub fn new() -> Self {
|
||||
UiResourceProvider { quad: None }
|
||||
UiResourceProvider {
|
||||
quad: None,
|
||||
instance_buffer: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, renderer: &mut dyn Renderer, world: &World) {
|
||||
|
@ -66,14 +70,20 @@ impl UiResourceProvider {
|
|||
|
||||
let mesh_id = self.quad.as_ref().unwrap().id;
|
||||
|
||||
renderer.create_instance_buffer_with_data(
|
||||
resource_name::buffer::UI_INSTANCES,
|
||||
if let Some(old_instance_buffer) = self.instance_buffer {
|
||||
renderer.remove_buffer(old_instance_buffer);
|
||||
}
|
||||
|
||||
let buffer = renderer.create_instance_buffer_with_data(
|
||||
mesh_id,
|
||||
data.as_bytes(),
|
||||
size,
|
||||
data.len(),
|
||||
wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::VERTEX,
|
||||
);
|
||||
|
||||
renderer.set_named_resource(resource_name::buffer::UI_INSTANCES, buffer);
|
||||
self.instance_buffer = Some(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::render::render_graph::{
|
||||
AsUniforms, BindType, DynamicUniformBufferInfo, Renderable, Renderer, ResourceProvider,
|
||||
UniformInfoIter,
|
||||
render_resource::RenderResource, AsUniforms, BindType, DynamicUniformBufferInfo, Renderable,
|
||||
Renderer, ResourceProvider, UniformInfoIter,
|
||||
};
|
||||
use legion::prelude::*;
|
||||
use std::{marker::PhantomData, ops::Deref};
|
||||
|
@ -10,7 +10,7 @@ where
|
|||
T: AsUniforms + Send + Sync,
|
||||
{
|
||||
_marker: PhantomData<T>,
|
||||
uniform_buffer_info_names: Vec<String>,
|
||||
uniform_buffer_info_resources: Vec<(String, Option<RenderResource>)>,
|
||||
}
|
||||
|
||||
impl<T> UniformResourceProvider<T>
|
||||
|
@ -19,7 +19,7 @@ where
|
|||
{
|
||||
pub fn new() -> Self {
|
||||
UniformResourceProvider {
|
||||
uniform_buffer_info_names: Vec::new(),
|
||||
uniform_buffer_info_resources: Vec::new(),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
@ -40,80 +40,86 @@ where
|
|||
// (2) if we create new buffers, the old bind groups will be invalid
|
||||
|
||||
// reset all uniform buffer info counts
|
||||
for name in self.uniform_buffer_info_names.iter() {
|
||||
for (_name, resource) in self.uniform_buffer_info_resources.iter() {
|
||||
renderer
|
||||
.get_dynamic_uniform_buffer_info_mut(name)
|
||||
.get_dynamic_uniform_buffer_info_mut(resource.unwrap())
|
||||
.unwrap()
|
||||
.count = 0;
|
||||
}
|
||||
|
||||
let mut counts = Vec::new();
|
||||
for (uniforms, _renderable) in query.iter(world) {
|
||||
let mut uniform_index = 0;
|
||||
let field_uniform_names = uniforms.get_field_uniform_names();
|
||||
for (i, uniform_info) in UniformInfoIter::new(field_uniform_names, uniforms.deref())
|
||||
.filter(|u| {
|
||||
if let BindType::Uniform { .. } = u.bind_type {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
for uniform_info in UniformInfoIter::new(field_uniform_names, uniforms.deref()) {
|
||||
match uniform_info.bind_type {
|
||||
BindType::Uniform { .. } => {
|
||||
// only add the first time a uniform info is processed
|
||||
if self.uniform_buffer_info_resources.len() <= uniform_index {
|
||||
self.uniform_buffer_info_resources
|
||||
.push((uniform_info.name.to_string(), None));
|
||||
}
|
||||
|
||||
if counts.len() <= uniform_index {
|
||||
counts.push(0);
|
||||
}
|
||||
|
||||
counts[uniform_index] += 1;
|
||||
uniform_index += 1;
|
||||
}
|
||||
})
|
||||
.enumerate()
|
||||
{
|
||||
// only add the first time a uniform info is processed
|
||||
if self.uniform_buffer_info_names.len() <= i {
|
||||
self.uniform_buffer_info_names
|
||||
.push(uniform_info.name.to_string());
|
||||
BindType::SampledTexture { .. } => {
|
||||
// TODO: look up Handle and load
|
||||
}
|
||||
BindType::Sampler { .. } => {
|
||||
// TODO: look up Handle and load
|
||||
}
|
||||
_ => panic!(
|
||||
"encountered unsupported bind_type {:?}",
|
||||
uniform_info.bind_type
|
||||
),
|
||||
}
|
||||
|
||||
if counts.len() <= i {
|
||||
counts.push(0);
|
||||
}
|
||||
|
||||
counts[i] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// create and update uniform buffer info. this is separate from the last block to avoid
|
||||
// the expense of hashing for large numbers of entities
|
||||
for (i, name) in self.uniform_buffer_info_names.iter().enumerate() {
|
||||
if let None = renderer.get_dynamic_uniform_buffer_info(name) {
|
||||
let info = DynamicUniformBufferInfo::new();
|
||||
renderer.add_dynamic_uniform_buffer_info(name, info);
|
||||
}
|
||||
|
||||
let info = renderer.get_dynamic_uniform_buffer_info_mut(name).unwrap();
|
||||
info.count = counts[i];
|
||||
}
|
||||
|
||||
// allocate uniform buffers
|
||||
for name in self.uniform_buffer_info_names.iter() {
|
||||
if let Some(_) = renderer.get_resource_info(name) {
|
||||
for (i, (name, resource)) in self.uniform_buffer_info_resources.iter_mut().enumerate() {
|
||||
if let Some(resource) = resource {
|
||||
let mut info = renderer
|
||||
.get_dynamic_uniform_buffer_info_mut(*resource)
|
||||
.unwrap();
|
||||
info.count = counts[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
let info = renderer.get_dynamic_uniform_buffer_info_mut(name).unwrap();
|
||||
|
||||
// allocate enough space for twice as many entities as there are currently;
|
||||
info.capacity = info.count * 2;
|
||||
let size = wgpu::BIND_BUFFER_ALIGNMENT * info.capacity;
|
||||
renderer.create_buffer(
|
||||
name,
|
||||
let capacity = counts[i] * 2;
|
||||
let size = wgpu::BIND_BUFFER_ALIGNMENT * capacity;
|
||||
let created_resource = renderer.create_buffer(
|
||||
size,
|
||||
wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
|
||||
);
|
||||
|
||||
let mut info = DynamicUniformBufferInfo::new();
|
||||
info.count = counts[i];
|
||||
info.capacity = capacity;
|
||||
renderer.add_dynamic_uniform_buffer_info(created_resource, info);
|
||||
*resource = Some(created_resource);
|
||||
renderer.set_named_resource(name, created_resource);
|
||||
}
|
||||
|
||||
// copy entity uniform data to buffers
|
||||
for name in self.uniform_buffer_info_names.iter() {
|
||||
for (name, resource) in self.uniform_buffer_info_resources.iter() {
|
||||
let resource = resource.unwrap();
|
||||
let size = {
|
||||
let info = renderer.get_dynamic_uniform_buffer_info(name).unwrap();
|
||||
let info = renderer.get_dynamic_uniform_buffer_info(resource).unwrap();
|
||||
wgpu::BIND_BUFFER_ALIGNMENT * info.count
|
||||
};
|
||||
|
||||
let alignment = wgpu::BIND_BUFFER_ALIGNMENT as usize;
|
||||
let mut offset = 0usize;
|
||||
let info = renderer.get_dynamic_uniform_buffer_info_mut(name).unwrap();
|
||||
let info = renderer
|
||||
.get_dynamic_uniform_buffer_info_mut(resource)
|
||||
.unwrap();
|
||||
for (i, (entity, _)) in query.iter_entities(world).enumerate() {
|
||||
// TODO: check if index has changed. if it has, then entity should be updated
|
||||
// TODO: only mem-map entities if their data has changed
|
||||
|
@ -125,8 +131,7 @@ where
|
|||
}
|
||||
|
||||
// let mut data = vec![Default::default(); size as usize];
|
||||
renderer.create_buffer_mapped(
|
||||
"tmp_uniform_mapped",
|
||||
let mapped_buffer_resource = renderer.create_buffer_mapped(
|
||||
size as usize,
|
||||
wgpu::BufferUsage::COPY_SRC,
|
||||
&mut |mapped| {
|
||||
|
@ -136,7 +141,7 @@ where
|
|||
// TODO: check if index has changed. if it has, then entity should be updated
|
||||
// TODO: only mem-map entities if their data has changed
|
||||
// TODO: try getting bytes ref first
|
||||
if let Some(uniform_bytes) = uniforms.get_uniform_bytes(name) {
|
||||
if let Some(uniform_bytes) = uniforms.get_uniform_bytes(&name) {
|
||||
mapped[offset..(offset + uniform_bytes.len())]
|
||||
.copy_from_slice(uniform_bytes.as_slice());
|
||||
offset += alignment;
|
||||
|
@ -145,7 +150,10 @@ where
|
|||
},
|
||||
);
|
||||
|
||||
renderer.copy_buffer_to_buffer("tmp_uniform_mapped", 0, name, 0, size);
|
||||
renderer.copy_buffer_to_buffer(mapped_buffer_resource, 0, resource, 0, size);
|
||||
|
||||
// TODO: uncomment this to free resource?
|
||||
renderer.remove_buffer(mapped_buffer_resource);
|
||||
}
|
||||
|
||||
// update shader assignments based on current macro defs
|
||||
|
|
Loading…
Reference in a new issue