2020-04-12 07:05:47 +00:00
|
|
|
use crate::renderer_2::{
|
2020-04-24 04:41:13 +00:00
|
|
|
render_resource_sets_system, WgpuRenderContext, WgpuRenderGraphExecutor,
|
|
|
|
WgpuRenderResourceContext,
|
2020-04-12 07:05:47 +00:00
|
|
|
};
|
2020-04-06 03:19:02 +00:00
|
|
|
use bevy_app::{EventReader, Events};
|
|
|
|
use bevy_render::{
|
2020-04-24 04:41:13 +00:00
|
|
|
pipeline::update_shader_assignments,
|
2020-04-06 03:19:02 +00:00
|
|
|
render_graph::RenderGraph,
|
2020-04-24 04:41:13 +00:00
|
|
|
render_graph_2::{DependentNodeStager, RenderGraph2, RenderGraphStager},
|
2020-04-13 20:04:31 +00:00
|
|
|
render_resource::RenderResourceAssignments,
|
2020-04-24 00:24:41 +00:00
|
|
|
renderer_2::{GlobalRenderResourceContext, RenderResourceContext},
|
2020-01-20 08:57:54 +00:00
|
|
|
};
|
2020-04-10 08:39:38 +00:00
|
|
|
use bevy_window::{WindowCreated, WindowResized, Windows};
|
2020-04-06 03:19:02 +00:00
|
|
|
use legion::prelude::*;
|
2020-04-21 18:43:35 +00:00
|
|
|
use std::{ops::Deref, sync::Arc};
|
2020-03-03 01:53:39 +00:00
|
|
|
pub struct WgpuRenderer {
|
2020-04-15 03:17:22 +00:00
|
|
|
pub device: Arc<wgpu::Device>,
|
2020-03-03 01:53:39 +00:00
|
|
|
pub queue: wgpu::Queue,
|
2020-04-01 01:04:54 +00:00
|
|
|
pub window_resized_event_reader: EventReader<WindowResized>,
|
|
|
|
pub window_created_event_reader: EventReader<WindowCreated>,
|
2020-03-23 01:22:35 +00:00
|
|
|
pub intialized: bool,
|
2020-03-03 01:53:39 +00:00
|
|
|
}
|
|
|
|
|
2020-01-20 08:57:54 +00:00
|
|
|
impl WgpuRenderer {
|
2020-03-31 02:21:12 +00:00
|
|
|
pub async fn new(
|
2020-04-01 01:04:54 +00:00
|
|
|
window_resized_event_reader: EventReader<WindowResized>,
|
|
|
|
window_created_event_reader: EventReader<WindowCreated>,
|
2020-03-31 02:21:12 +00:00
|
|
|
) -> Self {
|
2020-01-20 08:57:54 +00:00
|
|
|
let adapter = wgpu::Adapter::request(
|
|
|
|
&wgpu::RequestAdapterOptions {
|
|
|
|
power_preference: wgpu::PowerPreference::Default,
|
2020-04-08 02:36:57 +00:00
|
|
|
compatible_surface: None,
|
2020-01-20 08:57:54 +00:00
|
|
|
},
|
|
|
|
wgpu::BackendBit::PRIMARY,
|
|
|
|
)
|
2020-03-30 07:56:15 +00:00
|
|
|
.await
|
2020-01-20 08:57:54 +00:00
|
|
|
.unwrap();
|
|
|
|
|
2020-03-31 02:21:12 +00:00
|
|
|
let (device, queue) = adapter
|
|
|
|
.request_device(&wgpu::DeviceDescriptor {
|
|
|
|
extensions: wgpu::Extensions {
|
|
|
|
anisotropic_filtering: false,
|
|
|
|
},
|
|
|
|
limits: wgpu::Limits::default(),
|
|
|
|
})
|
|
|
|
.await;
|
2020-04-12 01:40:30 +00:00
|
|
|
let device = Arc::new(device);
|
2020-01-20 08:57:54 +00:00
|
|
|
WgpuRenderer {
|
2020-04-15 03:17:22 +00:00
|
|
|
device,
|
2020-01-20 08:57:54 +00:00
|
|
|
queue,
|
2020-04-01 01:04:54 +00:00
|
|
|
window_resized_event_reader,
|
|
|
|
window_created_event_reader,
|
2020-03-23 01:22:35 +00:00
|
|
|
intialized: false,
|
2020-01-20 08:57:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-10 08:39:38 +00:00
|
|
|
pub fn initialize_resource_providers(
|
|
|
|
world: &mut World,
|
2020-04-15 03:17:22 +00:00
|
|
|
resources: &Resources,
|
|
|
|
render_context: &mut WgpuRenderContext,
|
2020-04-10 08:39:38 +00:00
|
|
|
) {
|
2020-04-05 20:22:27 +00:00
|
|
|
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
2020-02-18 00:33:46 +00:00
|
|
|
for resource_provider in render_graph.resource_providers.iter_mut() {
|
2020-04-10 08:39:38 +00:00
|
|
|
resource_provider.initialize(render_context, world, resources);
|
2020-02-18 00:33:46 +00:00
|
|
|
}
|
|
|
|
}
|
2020-01-27 09:13:38 +00:00
|
|
|
|
2020-04-12 07:05:47 +00:00
|
|
|
fn parallel_resource_provider_update(
|
|
|
|
world: &World,
|
|
|
|
resources: &Resources,
|
2020-04-10 20:10:46 +00:00
|
|
|
device: Arc<wgpu::Device>,
|
2020-04-15 03:17:22 +00:00
|
|
|
render_resource_context: &WgpuRenderResourceContext,
|
|
|
|
) -> Vec<wgpu::CommandBuffer> {
|
2020-04-12 07:54:51 +00:00
|
|
|
let max_thread_count = 8;
|
2020-04-12 07:05:47 +00:00
|
|
|
let (sender, receiver) = crossbeam_channel::bounded(max_thread_count);
|
2020-03-22 02:57:59 +00:00
|
|
|
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
2020-04-12 21:47:41 +00:00
|
|
|
let chunk_size =
|
|
|
|
(render_graph.resource_providers.len() + max_thread_count - 1) / max_thread_count; // divide ints rounding remainder up
|
|
|
|
// println!("chunk {} {}", chunk_size, render_graph.resource_providers.len());
|
2020-04-12 07:05:47 +00:00
|
|
|
let mut actual_thread_count = 0;
|
|
|
|
crossbeam_utils::thread::scope(|s| {
|
|
|
|
for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) {
|
|
|
|
let device = device.clone();
|
|
|
|
let sender = sender.clone();
|
|
|
|
let world = &*world;
|
|
|
|
let resources = &*resources;
|
|
|
|
actual_thread_count += 1;
|
2020-04-15 03:17:22 +00:00
|
|
|
let render_resource_context = render_resource_context.clone();
|
2020-04-12 07:05:47 +00:00
|
|
|
s.spawn(move |_| {
|
2020-04-15 03:17:22 +00:00
|
|
|
let mut render_context =
|
|
|
|
WgpuRenderContext::new(device, render_resource_context);
|
2020-04-12 07:05:47 +00:00
|
|
|
for resource_provider in resource_provider_chunk.iter_mut() {
|
|
|
|
resource_provider.update(&mut render_context, world, resources);
|
|
|
|
}
|
|
|
|
sender.send(render_context.finish()).unwrap();
|
|
|
|
});
|
2020-04-10 20:10:46 +00:00
|
|
|
}
|
2020-04-12 21:47:41 +00:00
|
|
|
})
|
|
|
|
.unwrap();
|
2020-04-12 07:05:47 +00:00
|
|
|
|
2020-04-10 20:10:46 +00:00
|
|
|
let mut command_buffers = Vec::new();
|
2020-04-12 21:47:41 +00:00
|
|
|
for _i in 0..actual_thread_count {
|
2020-04-15 03:17:22 +00:00
|
|
|
let command_buffer = receiver.recv().unwrap();
|
2020-04-10 20:10:46 +00:00
|
|
|
if let Some(command_buffer) = command_buffer {
|
|
|
|
command_buffers.push(command_buffer);
|
|
|
|
}
|
2020-03-22 02:57:59 +00:00
|
|
|
}
|
2020-01-20 08:57:54 +00:00
|
|
|
|
2020-04-15 03:17:22 +00:00
|
|
|
command_buffers
|
2020-04-12 07:05:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn update_resource_providers(
|
2020-04-15 03:17:22 +00:00
|
|
|
&mut self,
|
2020-04-12 07:05:47 +00:00
|
|
|
world: &mut World,
|
2020-04-15 03:17:22 +00:00
|
|
|
resources: &Resources,
|
|
|
|
render_resource_context: &WgpuRenderResourceContext,
|
2020-04-12 07:05:47 +00:00
|
|
|
) {
|
2020-04-15 03:17:22 +00:00
|
|
|
let mut command_buffers = Self::parallel_resource_provider_update(
|
2020-04-12 21:47:41 +00:00
|
|
|
world,
|
|
|
|
resources,
|
2020-04-15 03:17:22 +00:00
|
|
|
self.device.clone(),
|
|
|
|
render_resource_context,
|
2020-04-12 21:47:41 +00:00
|
|
|
);
|
2020-04-12 01:40:30 +00:00
|
|
|
|
2020-04-12 07:05:47 +00:00
|
|
|
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
2020-04-10 20:10:46 +00:00
|
|
|
let mut results = Vec::new();
|
2020-04-12 07:05:47 +00:00
|
|
|
let thread_count = 5;
|
|
|
|
let chunk_size = (render_graph.resource_providers.len() + thread_count - 1) / thread_count; // divide ints rounding remainder up
|
2020-04-12 21:47:41 +00:00
|
|
|
// crossbeam_utils::thread::scope(|s| {
|
2020-04-12 01:40:30 +00:00
|
|
|
for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) {
|
2020-04-15 03:17:22 +00:00
|
|
|
let device = self.device.clone();
|
|
|
|
let mut render_context =
|
|
|
|
WgpuRenderContext::new(device, render_resource_context.clone());
|
2020-04-12 01:40:30 +00:00
|
|
|
for resource_provider in resource_provider_chunk.iter_mut() {
|
|
|
|
resource_provider.finish_update(&mut render_context, world, resources);
|
2020-04-10 20:10:46 +00:00
|
|
|
}
|
2020-04-12 01:40:30 +00:00
|
|
|
results.push(render_context.finish());
|
|
|
|
}
|
2020-04-10 20:10:46 +00:00
|
|
|
|
2020-04-15 03:17:22 +00:00
|
|
|
for command_buffer in results {
|
2020-04-10 20:10:46 +00:00
|
|
|
if let Some(command_buffer) = command_buffer {
|
|
|
|
command_buffers.push(command_buffer);
|
|
|
|
}
|
2020-03-22 02:57:59 +00:00
|
|
|
}
|
2020-04-10 20:10:46 +00:00
|
|
|
|
2020-04-15 03:17:22 +00:00
|
|
|
self.queue.submit(&command_buffers);
|
2020-03-22 02:57:59 +00:00
|
|
|
}
|
2020-02-18 00:33:46 +00:00
|
|
|
|
2020-04-15 03:17:22 +00:00
|
|
|
pub fn create_queued_textures(
|
|
|
|
&mut self,
|
|
|
|
resources: &Resources,
|
|
|
|
global_render_resources: &mut WgpuRenderResourceContext,
|
|
|
|
) {
|
2020-03-22 02:57:59 +00:00
|
|
|
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
2020-03-27 06:40:25 +00:00
|
|
|
let mut render_resource_assignments =
|
|
|
|
resources.get_mut::<RenderResourceAssignments>().unwrap();
|
2020-03-22 02:57:59 +00:00
|
|
|
for (name, texture_descriptor) in render_graph.queued_textures.drain(..) {
|
2020-04-15 03:17:22 +00:00
|
|
|
let resource = global_render_resources.create_texture(&texture_descriptor);
|
2020-03-27 06:40:25 +00:00
|
|
|
render_resource_assignments.set(&name, resource);
|
2020-03-22 02:57:59 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-05 06:07:02 +00:00
|
|
|
|
2020-04-10 08:39:38 +00:00
|
|
|
pub fn handle_window_created_events(
|
2020-04-15 03:17:22 +00:00
|
|
|
&mut self,
|
|
|
|
resources: &Resources,
|
|
|
|
global_render_resource_context: &mut WgpuRenderResourceContext,
|
2020-04-10 08:39:38 +00:00
|
|
|
) {
|
2020-03-31 02:21:12 +00:00
|
|
|
let windows = resources.get::<Windows>().unwrap();
|
2020-04-01 01:04:54 +00:00
|
|
|
let window_created_events = resources.get::<Events<WindowCreated>>().unwrap();
|
2020-04-15 03:17:22 +00:00
|
|
|
for window_created_event in
|
|
|
|
window_created_events.iter(&mut self.window_created_event_reader)
|
|
|
|
{
|
2020-03-31 02:21:12 +00:00
|
|
|
let window = windows
|
|
|
|
.get(window_created_event.id)
|
|
|
|
.expect("Received window created event for non-existent window");
|
2020-04-06 03:19:02 +00:00
|
|
|
#[cfg(feature = "bevy_winit")]
|
2020-03-31 02:21:12 +00:00
|
|
|
{
|
2020-04-06 03:19:02 +00:00
|
|
|
let winit_windows = resources.get::<bevy_winit::WinitWindows>().unwrap();
|
2020-04-21 18:43:35 +00:00
|
|
|
let winit_window = winit_windows.get_window(window.id).unwrap();
|
|
|
|
let surface = wgpu::Surface::create(winit_window.deref());
|
2020-04-15 03:17:22 +00:00
|
|
|
global_render_resource_context
|
|
|
|
.wgpu_resources
|
|
|
|
.set_window_surface(window.id, surface);
|
2020-03-28 20:56:29 +00:00
|
|
|
}
|
2020-01-27 05:44:01 +00:00
|
|
|
}
|
2020-01-20 08:57:54 +00:00
|
|
|
}
|
|
|
|
|
2020-04-20 21:29:21 +00:00
|
|
|
pub fn run_graph(&mut self, world: &mut World, resources: &mut Resources) {
|
2020-04-24 00:24:41 +00:00
|
|
|
// run systems
|
2020-04-20 21:29:21 +00:00
|
|
|
let mut executor = {
|
|
|
|
let mut render_graph = resources.get_mut::<RenderGraph2>().unwrap();
|
|
|
|
render_graph.take_executor()
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(executor) = executor.as_mut() {
|
|
|
|
executor.execute(world, resources);
|
|
|
|
}
|
|
|
|
|
2020-04-24 04:41:13 +00:00
|
|
|
render_resource_sets_system().run(world, resources);
|
|
|
|
|
2020-04-20 21:29:21 +00:00
|
|
|
let mut render_graph = resources.get_mut::<RenderGraph2>().unwrap();
|
|
|
|
if let Some(executor) = executor.take() {
|
|
|
|
render_graph.set_executor(executor);
|
|
|
|
}
|
|
|
|
|
2020-04-24 00:24:41 +00:00
|
|
|
// stage nodes
|
|
|
|
let mut stager = DependentNodeStager::loose_grouping();
|
|
|
|
let stages = stager.get_stages(&render_graph).unwrap();
|
|
|
|
let mut borrowed = stages.borrow(&mut render_graph);
|
|
|
|
|
|
|
|
// execute stages
|
|
|
|
let executor = WgpuRenderGraphExecutor {
|
|
|
|
max_thread_count: 2,
|
|
|
|
};
|
2020-04-24 04:41:13 +00:00
|
|
|
executor.execute(
|
|
|
|
world,
|
|
|
|
resources,
|
|
|
|
self.device.clone(),
|
|
|
|
&mut self.queue,
|
|
|
|
&mut borrowed,
|
|
|
|
);
|
2020-04-20 21:29:21 +00:00
|
|
|
}
|
|
|
|
|
2020-04-12 21:47:41 +00:00
|
|
|
pub fn update(&mut self, world: &mut World, resources: &mut Resources) {
|
2020-04-24 04:41:13 +00:00
|
|
|
{
|
2020-04-15 03:17:22 +00:00
|
|
|
let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap();
|
2020-04-15 18:42:56 +00:00
|
|
|
let render_resource_context = global_context
|
|
|
|
.context
|
2020-04-15 03:17:22 +00:00
|
|
|
.downcast_mut::<WgpuRenderResourceContext>()
|
|
|
|
.unwrap();
|
2020-04-10 08:39:38 +00:00
|
|
|
|
2020-04-15 03:17:22 +00:00
|
|
|
self.handle_window_created_events(resources, render_resource_context);
|
2020-02-04 08:06:17 +00:00
|
|
|
|
2020-04-15 03:17:22 +00:00
|
|
|
let mut render_context =
|
|
|
|
WgpuRenderContext::new(self.device.clone(), render_resource_context.clone());
|
|
|
|
if !self.intialized {
|
|
|
|
Self::initialize_resource_providers(world, resources, &mut render_context);
|
|
|
|
let buffer = render_context.finish();
|
|
|
|
if let Some(buffer) = buffer {
|
|
|
|
self.queue.submit(&[buffer]);
|
|
|
|
}
|
|
|
|
self.intialized = true;
|
|
|
|
}
|
|
|
|
|
2020-04-15 18:42:56 +00:00
|
|
|
self.update_resource_providers(world, resources, render_resource_context);
|
2020-04-15 03:17:22 +00:00
|
|
|
|
|
|
|
update_shader_assignments(world, resources, &render_context);
|
|
|
|
self.create_queued_textures(resources, &mut render_context.render_resources);
|
|
|
|
};
|
|
|
|
|
2020-04-21 18:43:35 +00:00
|
|
|
self.run_graph(world, resources);
|
2020-04-15 03:17:22 +00:00
|
|
|
|
2020-04-24 04:41:13 +00:00
|
|
|
let render_resource_context = resources.get::<GlobalRenderResourceContext>().unwrap();
|
|
|
|
render_resource_context
|
|
|
|
.context
|
2020-04-21 18:43:35 +00:00
|
|
|
.drop_all_swap_chain_textures();
|
2020-01-20 08:57:54 +00:00
|
|
|
}
|
2020-03-11 04:57:57 +00:00
|
|
|
}
|