initial multi-threaded resource creation using WgpuRenderContext
This commit is contained in:
parent
d8c748644c
commit
a7605b2d7a
@ -3,6 +3,8 @@ mod camera;
|
||||
pub mod entity;
|
||||
pub mod mesh;
|
||||
pub mod render_graph;
|
||||
pub mod render_graph_2;
|
||||
pub mod renderer_2;
|
||||
pub mod shader;
|
||||
|
||||
mod color;
|
||||
|
||||
0
bevy_render/src/render_graph_2/mod.rs
Normal file
0
bevy_render/src/render_graph_2/mod.rs
Normal file
@ -1,9 +1,17 @@
|
||||
use crate::{mesh::Mesh, texture::Texture};
|
||||
use bevy_asset::Handle;
|
||||
use std::collections::HashMap;
|
||||
use uuid::Uuid;
|
||||
|
||||
// TODO: Rename to RenderResourceId
|
||||
#[derive(Copy, Clone, Hash, Debug, Eq, PartialEq)]
|
||||
pub struct RenderResource(pub u64);
|
||||
pub struct RenderResource(Uuid);
|
||||
|
||||
impl RenderResource {
|
||||
pub fn new() -> Self {
|
||||
RenderResource(Uuid::new_v4())
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: consider scoping breaking these mappings up by type: Texture, Sampler, etc
|
||||
// the overlap could cause accidents.
|
||||
@ -13,7 +21,6 @@ pub struct RenderResources {
|
||||
pub texture_to_sampler_resource: HashMap<Handle<Texture>, RenderResource>,
|
||||
pub mesh_to_vertices_resource: HashMap<Handle<Mesh>, RenderResource>,
|
||||
pub mesh_to_indices_resource: HashMap<Handle<Mesh>, RenderResource>,
|
||||
pub resource_index: u64,
|
||||
}
|
||||
|
||||
impl RenderResources {
|
||||
@ -52,11 +59,4 @@ impl RenderResources {
|
||||
pub fn get_texture_sampler_resource(&self, texture: Handle<Texture>) -> Option<RenderResource> {
|
||||
self.texture_to_sampler_resource.get(&texture).cloned()
|
||||
}
|
||||
|
||||
pub fn get_next_resource(&mut self) -> RenderResource {
|
||||
let resource = self.resource_index;
|
||||
self.resource_index += 1;
|
||||
|
||||
RenderResource(resource)
|
||||
}
|
||||
}
|
||||
|
||||
3
bevy_render/src/renderer_2/mod.rs
Normal file
3
bevy_render/src/renderer_2/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
mod render_context;
|
||||
|
||||
pub use render_context::*;
|
||||
61
bevy_render/src/renderer_2/render_context.rs
Normal file
61
bevy_render/src/renderer_2/render_context.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use crate::{
|
||||
render_resource::{
|
||||
BufferInfo, RenderResource, RenderResources, ResourceInfo,
|
||||
},
|
||||
texture::{SamplerDescriptor, TextureDescriptor},
|
||||
};
|
||||
|
||||
pub trait RenderContext {
|
||||
fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource;
|
||||
fn create_texture(
|
||||
&mut self,
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
) -> RenderResource;
|
||||
fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource;
|
||||
fn create_buffer_mapped(
|
||||
&mut self,
|
||||
buffer_info: BufferInfo,
|
||||
setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderContext),
|
||||
) -> RenderResource;
|
||||
fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource;
|
||||
fn remove_buffer(&mut self, resource: RenderResource);
|
||||
fn remove_texture(&mut self, resource: RenderResource);
|
||||
fn remove_sampler(&mut self, resource: RenderResource);
|
||||
fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo>;
|
||||
fn get_resource_info_mut(&mut self, resource: RenderResource) -> Option<&mut ResourceInfo>;
|
||||
fn render_resources(&self) -> &RenderResources;
|
||||
fn render_resources_mut(&mut self) -> &mut RenderResources;
|
||||
// fn setup_render_pipeline(
|
||||
// &mut self,
|
||||
// pipeline_handle: Handle<PipelineDescriptor>,
|
||||
// pipeline_descriptor: &mut PipelineDescriptor,
|
||||
// shader_storage: &AssetStorage<Shader>,
|
||||
// );
|
||||
// fn setup_bind_groups(
|
||||
// &mut self,
|
||||
// render_resource_assignments: &mut RenderResourceAssignments,
|
||||
// pipeline_descriptor: &PipelineDescriptor,
|
||||
// );
|
||||
|
||||
fn create_texture_with_data(
|
||||
&mut self,
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
bytes: Option<&[u8]>,
|
||||
) -> RenderResource;
|
||||
fn copy_buffer_to_buffer(
|
||||
&mut self,
|
||||
source_buffer: RenderResource,
|
||||
source_offset: u64,
|
||||
destination_buffer: RenderResource,
|
||||
destination_offset: u64,
|
||||
size: u64,
|
||||
);
|
||||
// fn copy_buffer_to_texture(
|
||||
// &mut self,
|
||||
// source_buffer: RenderResource,
|
||||
// source_offset: u64,
|
||||
// destination_buffer: RenderResource,
|
||||
// destination_offset: u64,
|
||||
// size: u64,
|
||||
// );
|
||||
}
|
||||
@ -22,4 +22,5 @@ legion = { path = "../bevy_legion" }
|
||||
wgpu = { version = "0.5.0" }
|
||||
|
||||
futures = "0.3"
|
||||
log = { version = "0.4", features = ["release_max_level_info"] }
|
||||
log = { version = "0.4", features = ["release_max_level_info"] }
|
||||
crossbeam-channel = "0.4.2"
|
||||
@ -2,6 +2,7 @@ mod wgpu_render_pass;
|
||||
mod wgpu_renderer;
|
||||
mod wgpu_resources;
|
||||
mod wgpu_type_converter;
|
||||
pub mod renderer_2;
|
||||
|
||||
pub use wgpu_render_pass::*;
|
||||
pub use wgpu_renderer::*;
|
||||
|
||||
3
bevy_wgpu/src/renderer_2/mod.rs
Normal file
3
bevy_wgpu/src/renderer_2/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
mod wgpu_render_context;
|
||||
|
||||
pub use wgpu_render_context::*;
|
||||
133
bevy_wgpu/src/renderer_2/wgpu_render_context.rs
Normal file
133
bevy_wgpu/src/renderer_2/wgpu_render_context.rs
Normal file
@ -0,0 +1,133 @@
|
||||
use crate::WgpuResources;
|
||||
|
||||
use bevy_render::{
|
||||
render_resource::{BufferInfo, RenderResource, RenderResources, ResourceInfo},
|
||||
renderer_2::RenderContext,
|
||||
texture::{SamplerDescriptor, TextureDescriptor},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Default)]
|
||||
struct LazyCommandEncoder {
|
||||
command_encoder: Option<wgpu::CommandEncoder>,
|
||||
}
|
||||
|
||||
impl LazyCommandEncoder {
|
||||
pub fn get_or_create(&mut self, device: &wgpu::Device) -> &mut wgpu::CommandEncoder {
|
||||
match self.command_encoder {
|
||||
Some(ref mut command_encoder) => command_encoder,
|
||||
None => {
|
||||
let command_encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
||||
self.command_encoder = Some(command_encoder);
|
||||
self.command_encoder.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take(&mut self) -> Option<wgpu::CommandEncoder> {
|
||||
self.command_encoder.take()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WgpuRenderContext {
|
||||
pub device: Arc<wgpu::Device>,
|
||||
command_encoder: LazyCommandEncoder,
|
||||
wgpu_resources: WgpuResources,
|
||||
}
|
||||
|
||||
impl WgpuRenderContext {
|
||||
pub fn new(device: Arc<wgpu::Device>) -> Self {
|
||||
WgpuRenderContext {
|
||||
device,
|
||||
command_encoder: LazyCommandEncoder::default(),
|
||||
wgpu_resources: WgpuResources::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finish(&mut self) -> Option<wgpu::CommandBuffer> {
|
||||
self.command_encoder.take().map(|encoder| encoder.finish())
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderContext for WgpuRenderContext {
|
||||
fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource {
|
||||
self.wgpu_resources
|
||||
.create_sampler(&self.device, sampler_descriptor)
|
||||
}
|
||||
fn create_texture(&mut self, texture_descriptor: &TextureDescriptor) -> RenderResource {
|
||||
self.wgpu_resources
|
||||
.create_texture(&self.device, texture_descriptor)
|
||||
}
|
||||
fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource {
|
||||
self.wgpu_resources.create_buffer(&self.device, buffer_info)
|
||||
}
|
||||
|
||||
// TODO: clean this up
|
||||
fn create_buffer_mapped(
|
||||
&mut self,
|
||||
buffer_info: BufferInfo,
|
||||
setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderContext),
|
||||
) -> RenderResource {
|
||||
let buffer = WgpuResources::begin_create_buffer_mapped_render_context(
|
||||
&buffer_info,
|
||||
self,
|
||||
setup_data,
|
||||
);
|
||||
self.wgpu_resources.assign_buffer(buffer, buffer_info)
|
||||
}
|
||||
fn create_texture_with_data(
|
||||
&mut self,
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
bytes: Option<&[u8]>,
|
||||
) -> RenderResource {
|
||||
self.wgpu_resources.create_texture_with_data(
|
||||
&self.device,
|
||||
self.command_encoder.get_or_create(&self.device),
|
||||
texture_descriptor,
|
||||
bytes,
|
||||
)
|
||||
}
|
||||
fn remove_buffer(&mut self, resource: RenderResource) {
|
||||
self.wgpu_resources.remove_buffer(resource);
|
||||
}
|
||||
fn remove_texture(&mut self, resource: RenderResource) {
|
||||
self.wgpu_resources.remove_texture(resource);
|
||||
}
|
||||
fn remove_sampler(&mut self, resource: RenderResource) {
|
||||
self.wgpu_resources.remove_sampler(resource);
|
||||
}
|
||||
fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> {
|
||||
self.wgpu_resources.resource_info.get(&resource)
|
||||
}
|
||||
fn get_resource_info_mut(&mut self, resource: RenderResource) -> Option<&mut ResourceInfo> {
|
||||
self.wgpu_resources.resource_info.get_mut(&resource)
|
||||
}
|
||||
fn render_resources(&self) -> &RenderResources {
|
||||
&self.wgpu_resources.render_resources
|
||||
}
|
||||
fn render_resources_mut(&mut self) -> &mut RenderResources {
|
||||
&mut self.wgpu_resources.render_resources
|
||||
}
|
||||
fn copy_buffer_to_buffer(
|
||||
&mut self,
|
||||
source_buffer: RenderResource,
|
||||
source_offset: u64,
|
||||
destination_buffer: RenderResource,
|
||||
destination_offset: u64,
|
||||
size: u64,
|
||||
) {
|
||||
self.wgpu_resources.copy_buffer_to_buffer(
|
||||
self.command_encoder.get_or_create(&self.device),
|
||||
source_buffer,
|
||||
source_offset,
|
||||
destination_buffer,
|
||||
destination_offset,
|
||||
size,
|
||||
);
|
||||
}
|
||||
fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource {
|
||||
self.wgpu_resources
|
||||
.create_buffer_with_data(&self.device, buffer_info, data)
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@ use super::{
|
||||
wgpu_type_converter::{OwnedWgpuVertexBufferDescriptor, WgpuInto},
|
||||
WgpuRenderPass, WgpuResources,
|
||||
};
|
||||
use crate::renderer_2::WgpuRenderContext;
|
||||
use bevy_app::{EventReader, Events};
|
||||
use bevy_asset::{AssetStorage, Handle};
|
||||
use bevy_render::{
|
||||
@ -12,8 +13,8 @@ use bevy_render::{
|
||||
pipeline::{update_shader_assignments, PipelineCompiler, PipelineDescriptor},
|
||||
render_graph::RenderGraph,
|
||||
render_resource::{
|
||||
resource_name, BufferInfo, RenderResource, RenderResourceAssignments, RenderResources,
|
||||
ResourceInfo,
|
||||
resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments,
|
||||
RenderResources, ResourceInfo,
|
||||
},
|
||||
renderer::Renderer,
|
||||
shader::Shader,
|
||||
@ -359,6 +360,43 @@ impl Renderer for WgpuRenderer {
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }),
|
||||
);
|
||||
|
||||
// use bevy_render::renderer_2::RenderContext;
|
||||
// let thread_count = 5;
|
||||
// let (sender, receiver) = crossbeam_channel::bounded(thread_count);
|
||||
// for i in 0..thread_count {
|
||||
// let device = self.device.clone();
|
||||
// let sender = sender.clone();
|
||||
// std::thread::spawn(move || {
|
||||
// let mut context = WgpuRenderContext::new(device);
|
||||
// let data: Vec::<u8> = vec![1, 2, 3,4 ];
|
||||
// let data2: Vec::<u8> = vec![4, 2, 3,4 ];
|
||||
// let buffer = context.create_buffer_with_data(BufferInfo {
|
||||
// buffer_usage: BufferUsage::COPY_SRC,
|
||||
// ..Default::default()
|
||||
// }, &data);
|
||||
|
||||
// let buffer2 = context.create_buffer_with_data(BufferInfo {
|
||||
// buffer_usage: BufferUsage::UNIFORM |BufferUsage::COPY_DST,
|
||||
// ..Default::default()
|
||||
// }, &data2);
|
||||
|
||||
// context.copy_buffer_to_buffer(buffer, 0, buffer2, 0, data.len() as u64);
|
||||
|
||||
// sender.send(context.finish()).unwrap();
|
||||
// });
|
||||
// }
|
||||
|
||||
// let mut command_buffers = Vec::new();
|
||||
// for i in 0..thread_count {
|
||||
// if let Some(command_buffer) = receiver.recv().unwrap() {
|
||||
// command_buffers.push(command_buffer);
|
||||
// }
|
||||
|
||||
// println!("got {}", i);
|
||||
// }
|
||||
|
||||
// self.queue.submit(&command_buffers);
|
||||
|
||||
self.update_resource_providers(world, resources);
|
||||
update_shader_assignments(world, resources, self);
|
||||
self.create_queued_textures(resources);
|
||||
@ -434,8 +472,7 @@ impl Renderer for WgpuRenderer {
|
||||
}
|
||||
|
||||
fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource {
|
||||
self.wgpu_resources
|
||||
.create_buffer(&self.device, buffer_info)
|
||||
self.wgpu_resources.create_buffer(&self.device, buffer_info)
|
||||
}
|
||||
|
||||
fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> {
|
||||
@ -487,7 +524,7 @@ impl Renderer for WgpuRenderer {
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
bytes: Option<&[u8]>,
|
||||
) -> RenderResource {
|
||||
self.wgpu_resources.create_texture(
|
||||
self.wgpu_resources.create_texture_with_data(
|
||||
&self.device,
|
||||
self.encoder.as_mut().unwrap(),
|
||||
texture_descriptor,
|
||||
@ -564,10 +601,11 @@ impl Renderer for WgpuRenderer {
|
||||
})
|
||||
.collect::<Vec<wgpu::BindGroupLayoutEntry>>();
|
||||
let wgpu_bind_group_layout =
|
||||
self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: bind_group_layout_binding.as_slice(),
|
||||
label: None,
|
||||
});
|
||||
self.device
|
||||
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: bind_group_layout_binding.as_slice(),
|
||||
label: None,
|
||||
});
|
||||
|
||||
self.wgpu_resources
|
||||
.bind_group_layouts
|
||||
@ -587,9 +625,11 @@ impl Renderer for WgpuRenderer {
|
||||
})
|
||||
.collect::<Vec<&wgpu::BindGroupLayout>>();
|
||||
|
||||
let pipeline_layout = self.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: bind_group_layouts.as_slice(),
|
||||
});
|
||||
let pipeline_layout = self
|
||||
.device
|
||||
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: bind_group_layouts.as_slice(),
|
||||
});
|
||||
|
||||
let owned_vertex_buffer_descriptors = layout
|
||||
.vertex_buffer_descriptors
|
||||
@ -617,8 +657,11 @@ impl Renderer for WgpuRenderer {
|
||||
|
||||
if let Some(fragment_handle) = pipeline_descriptor.shader_stages.fragment {
|
||||
if let None = self.wgpu_resources.shader_modules.get(&fragment_handle) {
|
||||
self.wgpu_resources
|
||||
.create_shader_module(&self.device, fragment_handle, shader_storage);
|
||||
self.wgpu_resources.create_shader_module(
|
||||
&self.device,
|
||||
fragment_handle,
|
||||
shader_storage,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -673,7 +716,9 @@ impl Renderer for WgpuRenderer {
|
||||
alpha_to_coverage_enabled: pipeline_descriptor.alpha_to_coverage_enabled,
|
||||
};
|
||||
|
||||
let render_pipeline = self.device.create_render_pipeline(&mut render_pipeline_descriptor);
|
||||
let render_pipeline = self
|
||||
.device
|
||||
.create_render_pipeline(&mut render_pipeline_descriptor);
|
||||
self.render_pipelines
|
||||
.insert(pipeline_handle, render_pipeline);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use super::WgpuRenderer;
|
||||
use crate::wgpu_type_converter::WgpuInto;
|
||||
use crate::{renderer_2::WgpuRenderContext, wgpu_type_converter::WgpuInto};
|
||||
use bevy_asset::{AssetStorage, Handle};
|
||||
use bevy_render::{
|
||||
pipeline::{BindGroupDescriptor, BindGroupDescriptorId, BindType},
|
||||
@ -9,7 +9,7 @@ use bevy_render::{
|
||||
},
|
||||
renderer::Renderer,
|
||||
shader::Shader,
|
||||
texture::{SamplerDescriptor, TextureDescriptor},
|
||||
texture::{SamplerDescriptor, TextureDescriptor}, renderer_2::RenderContext,
|
||||
};
|
||||
use bevy_window::WindowId;
|
||||
use std::collections::HashMap;
|
||||
@ -154,7 +154,7 @@ impl WgpuResources {
|
||||
usage: buffer_info.buffer_usage.wgpu_into(),
|
||||
});
|
||||
|
||||
let resource = self.render_resources.get_next_resource();
|
||||
let resource = RenderResource::new();
|
||||
self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info));
|
||||
|
||||
self.buffers.insert(resource, buffer);
|
||||
@ -186,7 +186,7 @@ impl WgpuResources {
|
||||
buffer: wgpu::Buffer,
|
||||
buffer_info: BufferInfo,
|
||||
) -> RenderResource {
|
||||
let resource = self.render_resources.get_next_resource();
|
||||
let resource = RenderResource::new();
|
||||
self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info));
|
||||
self.buffers.insert(resource, buffer);
|
||||
resource
|
||||
@ -209,6 +209,24 @@ impl WgpuResources {
|
||||
mapped.finish()
|
||||
}
|
||||
|
||||
// TODO: clean this up
|
||||
pub fn begin_create_buffer_mapped_render_context(
|
||||
buffer_info: &BufferInfo,
|
||||
render_context: &mut WgpuRenderContext,
|
||||
setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderContext),
|
||||
) -> wgpu::Buffer {
|
||||
let device = render_context.device.clone();
|
||||
let mut mapped = device.create_buffer_mapped(
|
||||
&wgpu::BufferDescriptor {
|
||||
size: buffer_info.size as u64,
|
||||
usage: buffer_info.buffer_usage.wgpu_into(),
|
||||
label: None,
|
||||
}
|
||||
);
|
||||
setup_data(&mut mapped.data, render_context);
|
||||
mapped.finish()
|
||||
}
|
||||
|
||||
pub fn copy_buffer_to_buffer(
|
||||
&mut self,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
@ -242,13 +260,27 @@ impl WgpuResources {
|
||||
) -> RenderResource {
|
||||
let descriptor: wgpu::SamplerDescriptor = (*sampler_descriptor).wgpu_into();
|
||||
let sampler = device.create_sampler(&descriptor);
|
||||
let resource = self.render_resources.get_next_resource();
|
||||
let resource = RenderResource::new();
|
||||
self.samplers.insert(resource, sampler);
|
||||
self.add_resource_info(resource, ResourceInfo::Sampler);
|
||||
resource
|
||||
}
|
||||
|
||||
pub fn create_texture(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
texture_descriptor: &TextureDescriptor,
|
||||
) -> RenderResource {
|
||||
let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).wgpu_into();
|
||||
let texture = device.create_texture(&descriptor);
|
||||
let texture_view = texture.create_default_view();
|
||||
let resource = RenderResource::new();
|
||||
self.add_resource_info(resource, ResourceInfo::Texture);
|
||||
self.textures.insert(resource, texture_view);
|
||||
resource
|
||||
}
|
||||
|
||||
pub fn create_texture_with_data(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
@ -277,7 +309,7 @@ impl WgpuResources {
|
||||
);
|
||||
}
|
||||
|
||||
let resource = self.render_resources.get_next_resource();
|
||||
let resource = RenderResource::new();
|
||||
self.add_resource_info(resource, ResourceInfo::Texture);
|
||||
self.textures.insert(resource, texture_view);
|
||||
resource
|
||||
|
||||
Loading…
Reference in New Issue
Block a user