mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 14:40:19 +00:00
use swap chain node
This commit is contained in:
parent
5fec31b63c
commit
b6711d8eae
7 changed files with 97 additions and 105 deletions
|
@ -40,21 +40,22 @@ use self::{
|
|||
render_graph::RenderGraph,
|
||||
render_resource::{
|
||||
entity_render_resource_assignments_system,
|
||||
resource_providers::{
|
||||
LightResourceProvider,
|
||||
UniformResourceProvider,
|
||||
},
|
||||
resource_providers::{LightResourceProvider, UniformResourceProvider},
|
||||
AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments,
|
||||
},
|
||||
shader::{uniforms::StandardMaterial, Shader},
|
||||
texture::Texture,
|
||||
};
|
||||
|
||||
use bevy_app::{stage, AppBuilder, AppPlugin};
|
||||
use bevy_app::{stage, AppBuilder, AppPlugin, GetEventReader};
|
||||
use bevy_asset::AssetStorage;
|
||||
use bevy_transform::prelude::LocalToWorld;
|
||||
use render_resource::resource_providers::{mesh_resource_provider_system};
|
||||
use render_graph_2::{nodes::{Camera2dNode, CameraNode}, RenderGraph2};
|
||||
use bevy_window::{WindowCreated, WindowResized};
|
||||
use render_graph_2::{
|
||||
nodes::{Camera2dNode, CameraNode, SwapChainWindowSource, WindowSwapChainNode},
|
||||
RenderGraph2,
|
||||
};
|
||||
use render_resource::resource_providers::mesh_resource_provider_system;
|
||||
|
||||
pub static RENDER_RESOURCE_STAGE: &str = "render_resource";
|
||||
pub static RENDER_STAGE: &str = "render";
|
||||
|
@ -88,8 +89,14 @@ impl RenderPlugin {
|
|||
impl AppPlugin for RenderPlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
let mut render_graph = RenderGraph2::default();
|
||||
render_graph.add_system_node(CameraNode::default(), app.resources_mut());
|
||||
render_graph.add_system_node(Camera2dNode::default(), app.resources_mut());
|
||||
let resources = app.resources_mut();
|
||||
render_graph.add_system_node(CameraNode::default(), resources);
|
||||
render_graph.add_system_node(Camera2dNode::default(), resources);
|
||||
render_graph.add_node(WindowSwapChainNode::new(
|
||||
SwapChainWindowSource::Primary,
|
||||
resources.get_event_reader::<WindowCreated>(),
|
||||
resources.get_event_reader::<WindowResized>(),
|
||||
));
|
||||
let mut asset_batchers = AssetBatchers::default();
|
||||
asset_batchers.batch_types2::<Mesh, StandardMaterial>();
|
||||
app.add_stage_after(stage::POST_UPDATE, RENDER_RESOURCE_STAGE)
|
||||
|
@ -111,10 +118,7 @@ impl AppPlugin for RenderPlugin {
|
|||
// core systems
|
||||
.add_system(entity_render_resource_assignments_system())
|
||||
.add_system_to_stage_init(stage::POST_UPDATE, camera::camera_update_system)
|
||||
.add_system_to_stage(
|
||||
stage::POST_UPDATE,
|
||||
mesh::mesh_specializer_system(),
|
||||
)
|
||||
.add_system_to_stage(stage::POST_UPDATE, mesh::mesh_specializer_system())
|
||||
.add_system_to_stage(stage::POST_UPDATE, mesh::mesh_batcher_system())
|
||||
.add_system_to_stage(
|
||||
stage::POST_UPDATE,
|
||||
|
|
|
@ -1,19 +1,41 @@
|
|||
use crate::{
|
||||
render_graph_2::{Node, ResourceBindings, ResourceSlot},
|
||||
render_resource::{RenderResource, ResourceInfo},
|
||||
render_resource::ResourceInfo,
|
||||
renderer_2::RenderContext,
|
||||
texture::TextureDescriptor,
|
||||
};
|
||||
use bevy_app::{EventReader, Events};
|
||||
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
|
||||
use legion::prelude::*;
|
||||
|
||||
pub enum SwapChainWindowSource {
|
||||
Primary,
|
||||
Id(WindowId),
|
||||
}
|
||||
|
||||
impl Default for SwapChainWindowSource {
|
||||
fn default() -> Self {
|
||||
SwapChainWindowSource::Primary
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WindowSwapChainNode {
|
||||
window_id: WindowId,
|
||||
use_primary_window: bool,
|
||||
window_resized_event_reader: EventReader<WindowResized>,
|
||||
source_window: SwapChainWindowSource,
|
||||
window_created_event_reader: EventReader<WindowCreated>,
|
||||
swap_chain_resource: Option<RenderResource>,
|
||||
window_resized_event_reader: EventReader<WindowResized>,
|
||||
}
|
||||
|
||||
impl WindowSwapChainNode {
|
||||
pub fn new(
|
||||
source_window: SwapChainWindowSource,
|
||||
window_created_event_reader: EventReader<WindowCreated>,
|
||||
window_resized_event_reader: EventReader<WindowResized>,
|
||||
) -> Self {
|
||||
WindowSwapChainNode {
|
||||
source_window,
|
||||
window_created_event_reader,
|
||||
window_resized_event_reader,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for WindowSwapChainNode {
|
||||
|
@ -39,32 +61,30 @@ impl Node for WindowSwapChainNode {
|
|||
let windows = resources.get::<Windows>().unwrap();
|
||||
|
||||
let render_resources = render_context.resources_mut();
|
||||
let window = if self.use_primary_window {
|
||||
let window = match self.source_window {
|
||||
SwapChainWindowSource::Primary => {
|
||||
windows.get_primary().expect("No primary window exists")
|
||||
} else {
|
||||
windows
|
||||
.get(self.window_id)
|
||||
.expect("Received window resized event for non-existent window")
|
||||
}
|
||||
SwapChainWindowSource::Id(id) => windows
|
||||
.get(id)
|
||||
.expect("Received window resized event for non-existent window"),
|
||||
};
|
||||
|
||||
// create window swapchain
|
||||
if let Some(_) = window_created_events
|
||||
.find_latest(&mut self.window_created_event_reader, |e| {
|
||||
e.id == window.id
|
||||
})
|
||||
.find_latest(&mut self.window_created_event_reader, |e| e.id == window.id)
|
||||
{
|
||||
render_resources.create_swap_chain(window);
|
||||
}
|
||||
|
||||
// resize window swapchain
|
||||
if let Some(_) = window_resized_events
|
||||
.find_latest(&mut self.window_resized_event_reader, |e| {
|
||||
e.id == window.id
|
||||
})
|
||||
.find_latest(&mut self.window_resized_event_reader, |e| e.id == window.id)
|
||||
{
|
||||
render_resources.create_swap_chain(window);
|
||||
}
|
||||
|
||||
output.set(WINDOW_TEXTURE, self.swap_chain_resource.unwrap());
|
||||
let swap_chain_texture = render_resources.next_swap_chain_texture(window.id);
|
||||
output.set(WINDOW_TEXTURE, swap_chain_texture);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,8 +24,9 @@ impl GlobalRenderResourceContext {
|
|||
|
||||
pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
|
||||
fn create_swap_chain(&self, window: &Window);
|
||||
fn next_swap_chain_texture(&self, window_id: WindowId);
|
||||
fn drop_swap_chain_texture(&self, window_id: WindowId);
|
||||
fn next_swap_chain_texture(&self, window_id: WindowId) -> RenderResource;
|
||||
fn drop_swap_chain_texture(&self, render_resource: RenderResource);
|
||||
fn drop_all_swap_chain_textures(&self);
|
||||
fn create_sampler(&self, sampler_descriptor: &SamplerDescriptor) -> RenderResource;
|
||||
fn create_texture(&self, texture_descriptor: &TextureDescriptor) -> RenderResource;
|
||||
fn create_buffer(&self, buffer_info: BufferInfo) -> RenderResource;
|
||||
|
|
|
@ -426,7 +426,6 @@ impl RenderContext for WgpuRenderContext {
|
|||
let mut encoder = self.command_encoder.take().unwrap();
|
||||
{
|
||||
let render_pass = create_render_pass(
|
||||
self,
|
||||
pass_descriptor,
|
||||
render_resource_assignments,
|
||||
&refs,
|
||||
|
@ -447,7 +446,6 @@ impl RenderContext for WgpuRenderContext {
|
|||
}
|
||||
|
||||
pub fn create_render_pass<'a, 'b>(
|
||||
render_context: &'a WgpuRenderContext,
|
||||
pass_descriptor: &PassDescriptor,
|
||||
global_render_resource_assignments: &'b RenderResourceAssignments,
|
||||
refs: &WgpuResourceRefs<'a>,
|
||||
|
@ -459,7 +457,6 @@ pub fn create_render_pass<'a, 'b>(
|
|||
.iter()
|
||||
.map(|c| {
|
||||
create_wgpu_color_attachment_descriptor(
|
||||
render_context,
|
||||
global_render_resource_assignments,
|
||||
refs,
|
||||
c,
|
||||
|
@ -468,7 +465,6 @@ pub fn create_render_pass<'a, 'b>(
|
|||
.collect::<Vec<wgpu::RenderPassColorAttachmentDescriptor>>(),
|
||||
depth_stencil_attachment: pass_descriptor.depth_stencil_attachment.as_ref().map(|d| {
|
||||
create_wgpu_depth_stencil_attachment_descriptor(
|
||||
render_context,
|
||||
global_render_resource_assignments,
|
||||
refs,
|
||||
d,
|
||||
|
@ -478,7 +474,6 @@ pub fn create_render_pass<'a, 'b>(
|
|||
}
|
||||
|
||||
fn get_texture_view<'a>(
|
||||
render_context: &'a WgpuRenderContext,
|
||||
global_render_resource_assignments: &RenderResourceAssignments,
|
||||
refs: &WgpuResourceRefs<'a>,
|
||||
name: &str,
|
||||
|
@ -487,10 +482,10 @@ fn get_texture_view<'a>(
|
|||
resource_name::texture::SWAP_CHAIN => {
|
||||
if let Some(primary_swap_chain) = refs
|
||||
.swap_chain_outputs
|
||||
.get(render_context.primary_window.as_ref().unwrap())
|
||||
.map(|output| &output.view)
|
||||
.values()
|
||||
.next()
|
||||
{
|
||||
primary_swap_chain
|
||||
&primary_swap_chain.view
|
||||
} else {
|
||||
panic!("No primary swap chain found for color attachment");
|
||||
}
|
||||
|
@ -509,13 +504,11 @@ fn get_texture_view<'a>(
|
|||
}
|
||||
|
||||
fn create_wgpu_color_attachment_descriptor<'a>(
|
||||
render_context: &'a WgpuRenderContext,
|
||||
global_render_resource_assignments: &RenderResourceAssignments,
|
||||
refs: &WgpuResourceRefs<'a>,
|
||||
color_attachment_descriptor: &RenderPassColorAttachmentDescriptor,
|
||||
) -> wgpu::RenderPassColorAttachmentDescriptor<'a> {
|
||||
let attachment = get_texture_view(
|
||||
render_context,
|
||||
global_render_resource_assignments,
|
||||
refs,
|
||||
color_attachment_descriptor.attachment.as_str(),
|
||||
|
@ -526,7 +519,6 @@ fn create_wgpu_color_attachment_descriptor<'a>(
|
|||
.as_ref()
|
||||
.map(|target| {
|
||||
get_texture_view(
|
||||
render_context,
|
||||
global_render_resource_assignments,
|
||||
refs,
|
||||
target.as_str(),
|
||||
|
@ -543,13 +535,11 @@ fn create_wgpu_color_attachment_descriptor<'a>(
|
|||
}
|
||||
|
||||
fn create_wgpu_depth_stencil_attachment_descriptor<'a>(
|
||||
render_context: &'a WgpuRenderContext,
|
||||
global_render_resource_assignments: &RenderResourceAssignments,
|
||||
refs: &WgpuResourceRefs<'a>,
|
||||
depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor,
|
||||
) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<'a> {
|
||||
let attachment = get_texture_view(
|
||||
render_context,
|
||||
global_render_resource_assignments,
|
||||
refs,
|
||||
depth_stencil_attachment_descriptor.attachment.as_str(),
|
||||
|
|
|
@ -7,7 +7,7 @@ use bevy_render::{
|
|||
shader::Shader,
|
||||
texture::{SamplerDescriptor, TextureDescriptor},
|
||||
};
|
||||
use bevy_window::{Window, WindowId};
|
||||
use bevy_window::Window;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -99,11 +99,15 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
self.wgpu_resources
|
||||
.create_window_swap_chain(&self.device, window)
|
||||
}
|
||||
fn next_swap_chain_texture(&self, window_id: bevy_window::WindowId) {
|
||||
self.wgpu_resources.next_swap_chain_texture(window_id);
|
||||
fn next_swap_chain_texture(&self, window_id: bevy_window::WindowId) -> RenderResource {
|
||||
self.wgpu_resources.next_swap_chain_texture(window_id)
|
||||
}
|
||||
fn drop_swap_chain_texture(&self, window_id: WindowId) {
|
||||
self.wgpu_resources.remove_swap_chain_texture(window_id);
|
||||
fn drop_swap_chain_texture(&self, render_resource: RenderResource) {
|
||||
self.wgpu_resources
|
||||
.remove_swap_chain_texture(render_resource);
|
||||
}
|
||||
fn drop_all_swap_chain_textures(&self) {
|
||||
self.wgpu_resources.remove_all_swap_chain_textures();
|
||||
}
|
||||
fn set_asset_resource_untyped(
|
||||
&self,
|
||||
|
|
|
@ -12,7 +12,7 @@ use bevy_render::{
|
|||
};
|
||||
use bevy_window::{WindowCreated, WindowResized, Windows};
|
||||
use legion::prelude::*;
|
||||
use std::{collections::HashSet, ops::Deref, sync::Arc};
|
||||
use std::{ops::Deref, sync::Arc};
|
||||
pub struct WgpuRenderer {
|
||||
pub device: Arc<wgpu::Device>,
|
||||
pub queue: wgpu::Queue,
|
||||
|
@ -171,35 +171,6 @@ impl WgpuRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn handle_window_resized_events(
|
||||
&mut self,
|
||||
resources: &Resources,
|
||||
global_render_resources: &dyn RenderResourceContext,
|
||||
) {
|
||||
let windows = resources.get::<Windows>().unwrap();
|
||||
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
|
||||
let mut handled_windows = HashSet::new();
|
||||
// iterate in reverse order so we can handle the latest window resize event first for each window.
|
||||
// we skip earlier events for the same window because it results in redundant work
|
||||
for window_resized_event in window_resized_events
|
||||
.iter(&mut self.window_resized_event_reader)
|
||||
.rev()
|
||||
{
|
||||
if handled_windows.contains(&window_resized_event.id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let window = windows
|
||||
.get(window_resized_event.id)
|
||||
.expect("Received window resized event for non-existent window");
|
||||
|
||||
// TODO: consider making this a WgpuRenderContext method
|
||||
global_render_resources.create_swap_chain(window);
|
||||
|
||||
handled_windows.insert(window_resized_event.id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_window_created_events(
|
||||
&mut self,
|
||||
resources: &Resources,
|
||||
|
@ -216,12 +187,11 @@ impl WgpuRenderer {
|
|||
#[cfg(feature = "bevy_winit")]
|
||||
{
|
||||
let winit_windows = resources.get::<bevy_winit::WinitWindows>().unwrap();
|
||||
let primary_winit_window = winit_windows.get_window(window.id).unwrap();
|
||||
let surface = wgpu::Surface::create(primary_winit_window.deref());
|
||||
let winit_window = winit_windows.get_window(window.id).unwrap();
|
||||
let surface = wgpu::Surface::create(winit_window.deref());
|
||||
global_render_resource_context
|
||||
.wgpu_resources
|
||||
.set_window_surface(window.id, surface);
|
||||
global_render_resource_context.create_swap_chain(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -251,7 +221,13 @@ impl WgpuRenderer {
|
|||
for mut stage in linear_scheduler.get_stages(&mut render_graph) {
|
||||
for job in stage.iter_mut() {
|
||||
for node_state in job.iter_mut() {
|
||||
node_state.node.update(world, resources, &mut render_context, &node_state.input, &mut node_state.output);
|
||||
node_state.node.update(
|
||||
world,
|
||||
resources,
|
||||
&mut render_context,
|
||||
&node_state.input,
|
||||
&mut node_state.output,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -263,7 +239,6 @@ impl WgpuRenderer {
|
|||
}
|
||||
|
||||
pub fn update(&mut self, world: &mut World, resources: &mut Resources) {
|
||||
self.run_graph(world, resources);
|
||||
let mut encoder = {
|
||||
let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap();
|
||||
let render_resource_context = global_context
|
||||
|
@ -273,7 +248,6 @@ impl WgpuRenderer {
|
|||
|
||||
self.handle_window_created_events(resources, render_resource_context);
|
||||
|
||||
self.handle_window_resized_events(resources, render_resource_context);
|
||||
let mut render_context =
|
||||
WgpuRenderContext::new(self.device.clone(), render_resource_context.clone());
|
||||
if !self.intialized {
|
||||
|
@ -292,6 +266,7 @@ impl WgpuRenderer {
|
|||
render_context.command_encoder.take()
|
||||
};
|
||||
|
||||
self.run_graph(world, resources);
|
||||
// TODO: add to POST_UPDATE and remove redundant global_context
|
||||
render_resource_sets_system().run(world, resources);
|
||||
let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap();
|
||||
|
@ -317,9 +292,6 @@ impl WgpuRenderer {
|
|||
.get_primary()
|
||||
.map(|window| window.id);
|
||||
if let Some(primary_window_id) = primary_window_id {
|
||||
render_context
|
||||
.render_resources
|
||||
.next_swap_chain_texture(primary_window_id);
|
||||
render_context.primary_window = Some(primary_window_id);
|
||||
}
|
||||
|
||||
|
@ -371,11 +343,9 @@ impl WgpuRenderer {
|
|||
self.queue.submit(&[command_buffer]);
|
||||
}
|
||||
|
||||
// clear primary swap chain texture
|
||||
if let Some(primary_window_id) = primary_window_id {
|
||||
// clear swap chain textures
|
||||
render_context
|
||||
.render_resources
|
||||
.drop_swap_chain_texture(primary_window_id);
|
||||
}
|
||||
.drop_all_swap_chain_textures();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ pub struct WgpuBindGroupInfo {
|
|||
pub struct WgpuResourcesReadLock<'a> {
|
||||
pub buffers: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::Buffer>>,
|
||||
pub textures: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::TextureView>>,
|
||||
pub swap_chain_outputs: RwLockReadGuard<'a, HashMap<WindowId, wgpu::SwapChainOutput>>,
|
||||
pub swap_chain_outputs: RwLockReadGuard<'a, HashMap<RenderResource, wgpu::SwapChainOutput>>,
|
||||
pub render_pipelines:
|
||||
RwLockReadGuard<'a, HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>>,
|
||||
pub bind_groups: RwLockReadGuard<'a, HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>>,
|
||||
|
@ -65,7 +65,7 @@ impl<'a> WgpuResourcesReadLock<'a> {
|
|||
pub struct WgpuResourceRefs<'a> {
|
||||
pub buffers: &'a HashMap<RenderResource, wgpu::Buffer>,
|
||||
pub textures: &'a HashMap<RenderResource, wgpu::TextureView>,
|
||||
pub swap_chain_outputs: &'a HashMap<WindowId, wgpu::SwapChainOutput>,
|
||||
pub swap_chain_outputs: &'a HashMap<RenderResource, wgpu::SwapChainOutput>,
|
||||
pub render_pipelines: &'a HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
|
||||
pub bind_groups: &'a HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>,
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ pub struct WgpuResources {
|
|||
// TODO: remove this from WgpuResources. it doesn't need to be here
|
||||
pub window_surfaces: Arc<RwLock<HashMap<WindowId, wgpu::Surface>>>,
|
||||
pub window_swap_chains: Arc<RwLock<HashMap<WindowId, wgpu::SwapChain>>>,
|
||||
pub swap_chain_outputs: Arc<RwLock<HashMap<WindowId, wgpu::SwapChainOutput>>>,
|
||||
pub swap_chain_outputs: Arc<RwLock<HashMap<RenderResource, wgpu::SwapChainOutput>>>,
|
||||
pub buffers: Arc<RwLock<HashMap<RenderResource, wgpu::Buffer>>>,
|
||||
pub textures: Arc<RwLock<HashMap<RenderResource, wgpu::TextureView>>>,
|
||||
pub samplers: Arc<RwLock<HashMap<RenderResource, wgpu::Sampler>>>,
|
||||
|
@ -105,18 +105,21 @@ impl WgpuResources {
|
|||
.insert(window_id, surface);
|
||||
}
|
||||
|
||||
pub fn next_swap_chain_texture(&self, window_id: WindowId) {
|
||||
pub fn next_swap_chain_texture(&self, window_id: WindowId) -> RenderResource {
|
||||
let mut swap_chain_outputs = self.window_swap_chains.write().unwrap();
|
||||
let swap_chain_output = swap_chain_outputs.get_mut(&window_id).unwrap();
|
||||
let next_texture = swap_chain_output.get_next_texture().unwrap();
|
||||
let render_resource = RenderResource::new();
|
||||
// TODO: Add ResourceInfo
|
||||
self.swap_chain_outputs
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(window_id, next_texture);
|
||||
.insert(render_resource, next_texture);
|
||||
render_resource
|
||||
}
|
||||
|
||||
pub fn remove_swap_chain_texture(&self, window_id: WindowId) {
|
||||
self.swap_chain_outputs.write().unwrap().remove(&window_id);
|
||||
pub fn remove_swap_chain_texture(&self, render_resource: RenderResource) {
|
||||
self.swap_chain_outputs.write().unwrap().remove(&render_resource);
|
||||
}
|
||||
|
||||
pub fn remove_all_swap_chain_textures(&self) {
|
||||
|
|
Loading…
Reference in a new issue