mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 06:00:20 +00:00
refactor renderer to avoid resource access collisions. this fixes the legion errors in debug builds.
NOTE: these "random resource access" issues are a pretty compelling reason to remove Resources from the render api
This commit is contained in:
parent
6d53100ff3
commit
7bb889bada
14 changed files with 276 additions and 247 deletions
|
@ -22,6 +22,7 @@ pub trait DrawTarget {
|
|||
_resources: &Resources,
|
||||
_renderer: &mut dyn Renderer,
|
||||
_pipeline_handle: Handle<PipelineDescriptor>,
|
||||
_pipeline_descriptor: &PipelineDescriptor,
|
||||
) {
|
||||
}
|
||||
fn get_name(&self) -> String;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
asset::Handle,
|
||||
legion::prelude::*,
|
||||
prelude::Renderable,
|
||||
render::{
|
||||
|
@ -68,17 +68,17 @@ impl DrawTarget for AssignedBatchesDrawTarget {
|
|||
resources: &Resources,
|
||||
renderer: &mut dyn Renderer,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
pipeline_descriptor: &PipelineDescriptor,
|
||||
) {
|
||||
let mut asset_batches = resources.get_mut::<AssetBatchers>().unwrap();
|
||||
let pipeline_storage = resources.get::<AssetStorage<PipelineDescriptor>>().unwrap();
|
||||
let pipeline_descriptor = pipeline_storage.get(&pipeline_handle).unwrap();
|
||||
|
||||
let mut global_render_resource_assignments =
|
||||
resources.get_mut::<RenderResourceAssignments>().unwrap();
|
||||
|
||||
log::debug!(
|
||||
"setting up batch bind groups for pipeline: {:?}",
|
||||
pipeline_handle
|
||||
"setting up batch bind groups for pipeline: {:?} {:?}",
|
||||
pipeline_handle,
|
||||
pipeline_descriptor.name,
|
||||
);
|
||||
log::trace!("setting up global bind groups");
|
||||
renderer.setup_bind_groups(&mut global_render_resource_assignments, pipeline_descriptor);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
asset::Handle,
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
draw_target::DrawTarget,
|
||||
|
@ -83,6 +83,7 @@ impl DrawTarget for AssignedMeshesDrawTarget {
|
|||
resources: &Resources,
|
||||
renderer: &mut dyn Renderer,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
pipeline_descriptor: &PipelineDescriptor,
|
||||
) {
|
||||
let shader_pipeline_assignments = resources.get::<ShaderPipelineAssignments>().unwrap();
|
||||
let entity_render_resource_assignments =
|
||||
|
@ -90,14 +91,11 @@ impl DrawTarget for AssignedMeshesDrawTarget {
|
|||
let assigned_render_resource_assignments = shader_pipeline_assignments
|
||||
.assignments
|
||||
.get(&pipeline_handle);
|
||||
let pipeline_storage = resources.get::<AssetStorage<PipelineDescriptor>>().unwrap();
|
||||
let pipeline_descriptor = pipeline_storage.get(&pipeline_handle).unwrap();
|
||||
let mut global_render_resource_assignments =
|
||||
resources.get_mut::<RenderResourceAssignments>().unwrap();
|
||||
renderer.setup_bind_groups(&mut global_render_resource_assignments, pipeline_descriptor);
|
||||
if let Some(assigned_render_resource_assignments) = assigned_render_resource_assignments {
|
||||
for assignment_id in assigned_render_resource_assignments.iter() {
|
||||
// TODO: hopefully legion has better random access apis that are more like queries?
|
||||
let entity = entity_render_resource_assignments
|
||||
.get(*assignment_id)
|
||||
.unwrap();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
asset::{Asset, AssetStorage, Handle},
|
||||
asset::{Asset, Handle},
|
||||
legion::prelude::*,
|
||||
math,
|
||||
prelude::MeshType,
|
||||
|
@ -72,7 +72,8 @@ impl DrawTarget for UiDrawTarget {
|
|||
_world: &mut World,
|
||||
resources: &Resources,
|
||||
renderer: &mut dyn Renderer,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
_pipeline_handle: Handle<PipelineDescriptor>,
|
||||
pipeline_descriptor: &PipelineDescriptor,
|
||||
) {
|
||||
// don't create meshes if they have already been created
|
||||
if let Some(_) = self.mesh_vertex_buffer {
|
||||
|
@ -100,8 +101,6 @@ impl DrawTarget for UiDrawTarget {
|
|||
|
||||
let mut global_render_resource_assignments =
|
||||
resources.get_mut::<RenderResourceAssignments>().unwrap();
|
||||
let pipeline_storage = resources.get::<AssetStorage<PipelineDescriptor>>().unwrap();
|
||||
let pipeline_descriptor = pipeline_storage.get(&pipeline_handle).unwrap();
|
||||
renderer.setup_bind_groups(&mut global_render_resource_assignments, pipeline_descriptor);
|
||||
}
|
||||
fn get_name(&self) -> String {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use super::{BindType, PipelineDescriptor, PipelineLayout, PipelineLayoutType};
|
||||
use super::{BindType, PipelineDescriptor, PipelineLayout, PipelineLayoutType, VertexBufferDescriptors};
|
||||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
prelude::{Renderable, Resources, Shader, World},
|
||||
render::{
|
||||
render_graph::RenderGraph,
|
||||
render_resource::{
|
||||
BufferInfo, RenderResourceAssignments, RenderResourceAssignmentsId, ResourceInfo,
|
||||
},
|
||||
|
@ -32,7 +31,7 @@ impl PipelineCompiler {
|
|||
|
||||
fn reflect_layout(
|
||||
shader_storage: &AssetStorage<Shader>,
|
||||
render_graph: &RenderGraph,
|
||||
vertex_buffer_descriptors: &VertexBufferDescriptors,
|
||||
pipeline_descriptor: &mut PipelineDescriptor,
|
||||
renderer: &dyn Renderer,
|
||||
render_resource_assignments: &RenderResourceAssignments,
|
||||
|
@ -52,7 +51,7 @@ impl PipelineCompiler {
|
|||
}
|
||||
|
||||
let mut layout = PipelineLayout::from_shader_layouts(&mut layouts);
|
||||
layout.sync_vertex_buffer_descriptors_with_render_graph(render_graph);
|
||||
layout.sync_vertex_buffer_descriptors(vertex_buffer_descriptors);
|
||||
|
||||
// set binding uniforms to dynamic if render resource assignments use dynamic
|
||||
// TODO: this breaks down if different assignments have different "dynamic" status or if the dynamic status changes.
|
||||
|
@ -113,7 +112,7 @@ impl PipelineCompiler {
|
|||
|
||||
fn compile_pipeline(
|
||||
&mut self,
|
||||
render_graph: &RenderGraph,
|
||||
vertex_buffer_descriptors: &VertexBufferDescriptors,
|
||||
shader_storage: &mut AssetStorage<Shader>,
|
||||
renderer: &dyn Renderer,
|
||||
pipeline_descriptor: &PipelineDescriptor,
|
||||
|
@ -140,7 +139,7 @@ impl PipelineCompiler {
|
|||
|
||||
Self::reflect_layout(
|
||||
shader_storage,
|
||||
render_graph,
|
||||
vertex_buffer_descriptors,
|
||||
&mut compiled_pipeline_descriptor,
|
||||
renderer,
|
||||
render_resource_assignments,
|
||||
|
@ -151,7 +150,7 @@ impl PipelineCompiler {
|
|||
|
||||
fn update_shader_assignments(
|
||||
&mut self,
|
||||
render_graph: &RenderGraph,
|
||||
vertex_buffer_descriptors: &VertexBufferDescriptors,
|
||||
shader_pipeline_assignments: &mut ShaderPipelineAssignments,
|
||||
renderer: &dyn Renderer,
|
||||
pipeline_storage: &mut AssetStorage<PipelineDescriptor>,
|
||||
|
@ -177,7 +176,7 @@ impl PipelineCompiler {
|
|||
} else {
|
||||
let pipeline_descriptor = pipeline_storage.get(pipeline_handle).unwrap();
|
||||
let compiled_pipeline = self.compile_pipeline(
|
||||
render_graph,
|
||||
vertex_buffer_descriptors,
|
||||
shader_storage,
|
||||
renderer,
|
||||
pipeline_descriptor,
|
||||
|
@ -248,7 +247,7 @@ pub fn update_shader_assignments(
|
|||
resources.get_mut::<ShaderPipelineAssignments>().unwrap();
|
||||
let mut pipeline_compiler = resources.get_mut::<PipelineCompiler>().unwrap();
|
||||
let mut shader_storage = resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
let vertex_buffer_descriptors = resources.get::<VertexBufferDescriptors>().unwrap();
|
||||
let mut pipeline_descriptor_storage = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
|
@ -264,7 +263,7 @@ pub fn update_shader_assignments(
|
|||
}
|
||||
|
||||
pipeline_compiler.update_shader_assignments(
|
||||
&mut render_graph,
|
||||
&vertex_buffer_descriptors,
|
||||
&mut shader_pipeline_assignments,
|
||||
renderer,
|
||||
&mut pipeline_descriptor_storage,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::{BindGroupDescriptor, VertexBufferDescriptor};
|
||||
use crate::render::{render_graph::RenderGraph, shader::ShaderLayout};
|
||||
use super::{BindGroupDescriptor, VertexBufferDescriptor, VertexBufferDescriptors};
|
||||
use crate::render::shader::ShaderLayout;
|
||||
use std::{collections::HashMap, hash::Hash};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
|
@ -56,10 +56,13 @@ impl PipelineLayout {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn sync_vertex_buffer_descriptors_with_render_graph(&mut self, render_graph: &RenderGraph) {
|
||||
pub fn sync_vertex_buffer_descriptors(
|
||||
&mut self,
|
||||
vertex_buffer_descriptors: &VertexBufferDescriptors,
|
||||
) {
|
||||
for vertex_buffer_descriptor in self.vertex_buffer_descriptors.iter_mut() {
|
||||
if let Some(graph_descriptor) =
|
||||
render_graph.get_vertex_buffer_descriptor(&vertex_buffer_descriptor.name)
|
||||
vertex_buffer_descriptors.get(&vertex_buffer_descriptor.name)
|
||||
{
|
||||
vertex_buffer_descriptor.sync_with_descriptor(graph_descriptor);
|
||||
} else {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::VertexFormat;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct VertexBufferDescriptor {
|
||||
|
@ -41,3 +42,21 @@ pub struct VertexAttributeDescriptor {
|
|||
pub format: VertexFormat,
|
||||
pub shader_location: u32,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct VertexBufferDescriptors {
|
||||
pub descriptors: HashMap<String, VertexBufferDescriptor>,
|
||||
}
|
||||
|
||||
impl VertexBufferDescriptors {
|
||||
pub fn set(&mut self, vertex_buffer_descriptor: VertexBufferDescriptor) {
|
||||
self.descriptors.insert(
|
||||
vertex_buffer_descriptor.name.to_string(),
|
||||
vertex_buffer_descriptor,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get(&self, name: &str) -> Option<&VertexBufferDescriptor> {
|
||||
self.descriptors.get(name)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use super::RenderGraphBuilder;
|
||||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
prelude::Shader,
|
||||
prelude::{Resources, Shader, World},
|
||||
render::{
|
||||
draw_target::DrawTarget,
|
||||
pass::PassDescriptor,
|
||||
pipeline::{PipelineDescriptor, VertexBufferDescriptor},
|
||||
pipeline::{PipelineCompiler, PipelineDescriptor},
|
||||
render_resource::ResourceProvider,
|
||||
renderer::Renderer,
|
||||
texture::TextureDescriptor,
|
||||
},
|
||||
};
|
||||
|
@ -21,7 +22,6 @@ pub struct RenderGraph {
|
|||
pub resource_providers: Vec<Box<dyn ResourceProvider + Send + Sync>>,
|
||||
pub queued_textures: Vec<(String, TextureDescriptor)>,
|
||||
pub draw_targets: HashMap<String, Box<dyn DrawTarget + Send + Sync>>,
|
||||
pub vertex_buffer_descriptors: HashMap<String, VertexBufferDescriptor>,
|
||||
}
|
||||
|
||||
impl RenderGraph {
|
||||
|
@ -49,17 +49,52 @@ impl RenderGraph {
|
|||
pass_pipelines.push(pipeline);
|
||||
}
|
||||
|
||||
pub fn set_vertex_buffer_descriptor(
|
||||
pub fn setup_pipeline_draw_targets(
|
||||
&mut self,
|
||||
vertex_buffer_descriptor: VertexBufferDescriptor,
|
||||
world: &mut World,
|
||||
resources: &Resources,
|
||||
renderer: &mut dyn Renderer,
|
||||
) {
|
||||
self.vertex_buffer_descriptors.insert(
|
||||
vertex_buffer_descriptor.name.to_string(),
|
||||
vertex_buffer_descriptor,
|
||||
);
|
||||
}
|
||||
let shader_storage = resources.get::<AssetStorage<Shader>>().unwrap();
|
||||
let pipeline_compiler = resources.get::<PipelineCompiler>().unwrap();
|
||||
|
||||
pub fn get_vertex_buffer_descriptor(&self, name: &str) -> Option<&VertexBufferDescriptor> {
|
||||
self.vertex_buffer_descriptors.get(name)
|
||||
for (pass_name, _pass_descriptor) in self.pass_descriptors.iter() {
|
||||
if let Some(pass_pipelines) = self.pass_pipelines.get(pass_name) {
|
||||
for pass_pipeline in pass_pipelines.iter() {
|
||||
if let Some(compiled_pipelines_iter) =
|
||||
pipeline_compiler.iter_compiled_pipelines(*pass_pipeline)
|
||||
{
|
||||
for compiled_pipeline_handle in compiled_pipelines_iter {
|
||||
let mut pipeline_storage = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let compiled_pipeline_descriptor =
|
||||
pipeline_storage.get_mut(compiled_pipeline_handle).unwrap();
|
||||
|
||||
// create wgpu pipeline if it doesn't exist
|
||||
renderer.setup_render_pipeline(
|
||||
*compiled_pipeline_handle,
|
||||
compiled_pipeline_descriptor,
|
||||
&shader_storage,
|
||||
);
|
||||
|
||||
// setup pipeline draw targets
|
||||
for draw_target_name in compiled_pipeline_descriptor.draw_targets.iter()
|
||||
{
|
||||
let draw_target =
|
||||
self.draw_targets.get_mut(draw_target_name).unwrap();
|
||||
draw_target.setup(
|
||||
world,
|
||||
resources,
|
||||
renderer,
|
||||
*compiled_pipeline_handle,
|
||||
compiled_pipeline_descriptor,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use super::{
|
|||
AssignedBatchesDrawTarget, AssignedMeshesDrawTarget, MeshesDrawTarget, UiDrawTarget,
|
||||
},
|
||||
pass::passes::ForwardPassBuilder,
|
||||
pipeline::{pipelines::ForwardPipelineBuilder, PipelineCompiler, ShaderPipelineAssignments},
|
||||
pipeline::{pipelines::ForwardPipelineBuilder, PipelineCompiler, ShaderPipelineAssignments, VertexBufferDescriptors},
|
||||
render_graph::RenderGraph,
|
||||
render_resource::{
|
||||
build_entity_render_resource_assignments_system,
|
||||
|
@ -62,6 +62,7 @@ impl AppPlugin for RenderPlugin {
|
|||
.add_resource(AssetStorage::<StandardMaterial>::new())
|
||||
.add_resource(AssetStorage::<PipelineDescriptor>::new())
|
||||
.add_resource(ShaderPipelineAssignments::new())
|
||||
.add_resource(VertexBufferDescriptors::default())
|
||||
.add_resource(PipelineCompiler::new())
|
||||
.add_resource(RenderResourceAssignments::default())
|
||||
.add_resource(EntityRenderResourceAssignments::default())
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
prelude::Renderable,
|
||||
render::{
|
||||
mesh::Mesh,
|
||||
render_graph::RenderGraph,
|
||||
pipeline::VertexBufferDescriptors,
|
||||
render_resource::{
|
||||
AssetBatchers, BufferInfo, BufferUsage, RenderResourceAssignments, ResourceProvider,
|
||||
},
|
||||
|
@ -92,9 +92,8 @@ impl ResourceProvider for MeshResourceProvider {
|
|||
_world: &mut World,
|
||||
resources: &Resources,
|
||||
) {
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph
|
||||
.set_vertex_buffer_descriptor(Vertex::get_vertex_buffer_descriptor().cloned().unwrap());
|
||||
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap();
|
||||
vertex_buffer_descriptors.set(Vertex::get_vertex_buffer_descriptor().cloned().unwrap());
|
||||
}
|
||||
|
||||
fn update(&mut self, _renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
ecs,
|
||||
prelude::Node,
|
||||
render::{
|
||||
render_graph::RenderGraph,
|
||||
pipeline::VertexBufferDescriptors,
|
||||
render_resource::{
|
||||
resource_name, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource,
|
||||
RenderResourceAssignments, ResourceProvider,
|
||||
|
@ -113,9 +113,8 @@ impl ResourceProvider for UiResourceProvider {
|
|||
_world: &mut World,
|
||||
resources: &Resources,
|
||||
) {
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph
|
||||
.set_vertex_buffer_descriptor(Rect::get_vertex_buffer_descriptor().cloned().unwrap());
|
||||
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap();
|
||||
vertex_buffer_descriptors.set(Rect::get_vertex_buffer_descriptor().cloned().unwrap());
|
||||
}
|
||||
|
||||
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
render::{
|
||||
render_graph::RenderGraph,
|
||||
pipeline::VertexBufferDescriptors,
|
||||
render_resource::{
|
||||
AssetBatchers, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource,
|
||||
RenderResourceAssignments, ResourceInfo, ResourceProvider,
|
||||
|
@ -543,12 +543,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn initialize_vertex_buffer_descriptor(&self, render_graph: &mut RenderGraph) {
|
||||
fn initialize_vertex_buffer_descriptor(
|
||||
&self,
|
||||
vertex_buffer_descriptors: &mut VertexBufferDescriptors,
|
||||
) {
|
||||
let vertex_buffer_descriptor = T::get_vertex_buffer_descriptor();
|
||||
if let Some(vertex_buffer_descriptor) = vertex_buffer_descriptor {
|
||||
if let None = render_graph.get_vertex_buffer_descriptor(&vertex_buffer_descriptor.name)
|
||||
{
|
||||
render_graph.set_vertex_buffer_descriptor(vertex_buffer_descriptor.clone());
|
||||
if let None = vertex_buffer_descriptors.get(&vertex_buffer_descriptor.name) {
|
||||
vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -601,8 +603,8 @@ where
|
|||
world: &mut World,
|
||||
resources: &Resources,
|
||||
) {
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
self.initialize_vertex_buffer_descriptor(&mut render_graph);
|
||||
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap();
|
||||
self.initialize_vertex_buffer_descriptor(&mut vertex_buffer_descriptors);
|
||||
self.update(renderer, world, resources);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
pipeline::PipelineDescriptor,
|
||||
render_resource::{
|
||||
BufferInfo, RenderResource, RenderResourceAssignments, RenderResources, ResourceInfo,
|
||||
},
|
||||
shader::Shader,
|
||||
texture::{SamplerDescriptor, TextureDescriptor},
|
||||
},
|
||||
};
|
||||
|
@ -40,6 +42,12 @@ pub trait Renderer {
|
|||
);
|
||||
fn get_render_resources(&self) -> &RenderResources;
|
||||
fn get_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,
|
||||
|
|
|
@ -82,143 +82,10 @@ impl WgpuRenderer {
|
|||
self.intialized = true;
|
||||
}
|
||||
|
||||
pub fn create_render_pipeline(
|
||||
&mut self,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
pipeline_descriptor: &mut PipelineDescriptor,
|
||||
shader_storage: &AssetStorage<Shader>,
|
||||
) {
|
||||
let device = self.device.borrow();
|
||||
let layout = pipeline_descriptor.get_layout().unwrap();
|
||||
for bind_group in layout.bind_groups.iter() {
|
||||
if let None = self.wgpu_resources.bind_group_layouts.get(&bind_group.id) {
|
||||
let bind_group_layout_binding = bind_group
|
||||
.bindings
|
||||
.iter()
|
||||
.map(|binding| wgpu::BindGroupLayoutEntry {
|
||||
binding: binding.index,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: (&binding.bind_type).into(),
|
||||
})
|
||||
.collect::<Vec<wgpu::BindGroupLayoutEntry>>();
|
||||
let wgpu_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: bind_group_layout_binding.as_slice(),
|
||||
});
|
||||
|
||||
self.wgpu_resources
|
||||
.bind_group_layouts
|
||||
.insert(bind_group.id, wgpu_bind_group_layout);
|
||||
}
|
||||
}
|
||||
|
||||
// setup and collect bind group layouts
|
||||
let bind_group_layouts = layout
|
||||
.bind_groups
|
||||
.iter()
|
||||
.map(|bind_group| {
|
||||
self.wgpu_resources
|
||||
.bind_group_layouts
|
||||
.get(&bind_group.id)
|
||||
.unwrap()
|
||||
})
|
||||
.collect::<Vec<&wgpu::BindGroupLayout>>();
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: bind_group_layouts.as_slice(),
|
||||
});
|
||||
|
||||
let owned_vertex_buffer_descriptors = layout
|
||||
.vertex_buffer_descriptors
|
||||
.iter()
|
||||
.map(|v| v.into())
|
||||
.collect::<Vec<OwnedWgpuVertexBufferDescriptor>>();
|
||||
|
||||
let color_states = pipeline_descriptor
|
||||
.color_states
|
||||
.iter()
|
||||
.map(|c| c.into())
|
||||
.collect::<Vec<wgpu::ColorStateDescriptor>>();
|
||||
|
||||
if let None = self
|
||||
.wgpu_resources
|
||||
.shader_modules
|
||||
.get(&pipeline_descriptor.shader_stages.vertex)
|
||||
{
|
||||
self.wgpu_resources.create_shader_module(
|
||||
&device,
|
||||
pipeline_descriptor.shader_stages.vertex,
|
||||
shader_storage,
|
||||
);
|
||||
}
|
||||
|
||||
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(&device, fragment_handle, shader_storage);
|
||||
}
|
||||
};
|
||||
|
||||
let vertex_shader_module = self
|
||||
.wgpu_resources
|
||||
.shader_modules
|
||||
.get(&pipeline_descriptor.shader_stages.vertex)
|
||||
.unwrap();
|
||||
|
||||
let fragment_shader_module = match pipeline_descriptor.shader_stages.fragment {
|
||||
Some(fragment_handle) => Some(
|
||||
self.wgpu_resources
|
||||
.shader_modules
|
||||
.get(&fragment_handle)
|
||||
.unwrap(),
|
||||
),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let mut render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: &vertex_shader_module,
|
||||
entry_point: "main",
|
||||
},
|
||||
fragment_stage: match pipeline_descriptor.shader_stages.fragment {
|
||||
Some(_) => Some(wgpu::ProgrammableStageDescriptor {
|
||||
entry_point: "main",
|
||||
module: fragment_shader_module.as_ref().unwrap(),
|
||||
}),
|
||||
None => None,
|
||||
},
|
||||
rasterization_state: pipeline_descriptor
|
||||
.rasterization_state
|
||||
.as_ref()
|
||||
.map(|r| r.into()),
|
||||
primitive_topology: pipeline_descriptor.primitive_topology.into(),
|
||||
color_states: &color_states,
|
||||
depth_stencil_state: pipeline_descriptor
|
||||
.depth_stencil_state
|
||||
.as_ref()
|
||||
.map(|d| d.into()),
|
||||
vertex_state: wgpu::VertexStateDescriptor {
|
||||
index_format: pipeline_descriptor.index_format.into(),
|
||||
vertex_buffers: &owned_vertex_buffer_descriptors
|
||||
.iter()
|
||||
.map(|v| v.into())
|
||||
.collect::<Vec<wgpu::VertexBufferDescriptor>>(),
|
||||
},
|
||||
sample_count: pipeline_descriptor.sample_count,
|
||||
sample_mask: pipeline_descriptor.sample_mask,
|
||||
alpha_to_coverage_enabled: pipeline_descriptor.alpha_to_coverage_enabled,
|
||||
};
|
||||
|
||||
let render_pipeline = device.create_render_pipeline(&mut render_pipeline_descriptor);
|
||||
self.render_pipelines
|
||||
.insert(pipeline_handle, render_pipeline);
|
||||
}
|
||||
|
||||
pub fn create_render_pass<'a>(
|
||||
pub fn create_render_pass<'a, 'b>(
|
||||
wgpu_resources: &'a WgpuResources,
|
||||
pass_descriptor: &PassDescriptor,
|
||||
global_render_resource_assignments: &RenderResourceAssignments,
|
||||
global_render_resource_assignments: &'b RenderResourceAssignments,
|
||||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
primary_swap_chain: &Option<String>,
|
||||
swap_chain_outputs: &'a HashMap<String, wgpu::SwapChainOutput>,
|
||||
|
@ -344,12 +211,13 @@ impl WgpuRenderer {
|
|||
}
|
||||
|
||||
pub fn initialize_resource_providers(&mut self, world: &mut World, resources: &mut Resources) {
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
self.encoder = Some(
|
||||
self.device
|
||||
.borrow()
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }),
|
||||
);
|
||||
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
for resource_provider in render_graph.resource_providers.iter_mut() {
|
||||
resource_provider.initialize(self, world, resources);
|
||||
}
|
||||
|
@ -491,68 +359,29 @@ impl Renderer for WgpuRenderer {
|
|||
|
||||
let mut encoder = self.encoder.take().unwrap();
|
||||
|
||||
let mut pipeline_storage = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let shader_storage = resources.get::<AssetStorage<Shader>>().unwrap();
|
||||
let render_graph = resources.get::<RenderGraph>().unwrap();
|
||||
let mut render_graph_mut = resources.get_mut::<RenderGraph>().unwrap();
|
||||
let global_render_resource_assignments =
|
||||
resources.get::<RenderResourceAssignments>().unwrap();
|
||||
let pipeline_compiler = resources.get::<PipelineCompiler>().unwrap();
|
||||
|
||||
// setup draw targets
|
||||
for (pass_name, _pass_descriptor) in render_graph.pass_descriptors.iter() {
|
||||
if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) {
|
||||
for pass_pipeline in pass_pipelines.iter() {
|
||||
if let Some(compiled_pipelines_iter) =
|
||||
pipeline_compiler.iter_compiled_pipelines(*pass_pipeline)
|
||||
{
|
||||
for compiled_pipeline_handle in compiled_pipelines_iter {
|
||||
let compiled_pipeline_descriptor =
|
||||
pipeline_storage.get_mut(compiled_pipeline_handle).unwrap();
|
||||
|
||||
// create wgpu pipeline if it doesn't exist
|
||||
if !self.render_pipelines.contains_key(compiled_pipeline_handle) {
|
||||
self.create_render_pipeline(
|
||||
*compiled_pipeline_handle,
|
||||
compiled_pipeline_descriptor,
|
||||
&shader_storage,
|
||||
);
|
||||
}
|
||||
|
||||
// setup pipeline draw targets
|
||||
for draw_target_name in compiled_pipeline_descriptor.draw_targets.iter()
|
||||
{
|
||||
let draw_target = render_graph_mut
|
||||
.draw_targets
|
||||
.get_mut(draw_target_name)
|
||||
.unwrap();
|
||||
draw_target.setup(
|
||||
world,
|
||||
resources,
|
||||
self,
|
||||
*compiled_pipeline_handle,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph.setup_pipeline_draw_targets(world, resources, self);
|
||||
|
||||
let (primary_swap_chain, swap_chain_outputs) = self.get_swap_chain_outputs(resources);
|
||||
|
||||
// begin render passes
|
||||
let pipeline_storage = resources.get::<AssetStorage<PipelineDescriptor>>().unwrap();
|
||||
let pipeline_compiler = resources.get::<PipelineCompiler>().unwrap();
|
||||
|
||||
for (pass_name, pass_descriptor) in render_graph.pass_descriptors.iter() {
|
||||
let mut render_pass = Self::create_render_pass(
|
||||
&self.wgpu_resources,
|
||||
pass_descriptor,
|
||||
&global_render_resource_assignments,
|
||||
&mut encoder,
|
||||
&primary_swap_chain,
|
||||
&swap_chain_outputs,
|
||||
);
|
||||
let mut render_pass = {
|
||||
let global_render_resource_assignments =
|
||||
resources.get::<RenderResourceAssignments>().unwrap();
|
||||
Self::create_render_pass(
|
||||
&self.wgpu_resources,
|
||||
pass_descriptor,
|
||||
&global_render_resource_assignments,
|
||||
&mut encoder,
|
||||
&primary_swap_chain,
|
||||
&swap_chain_outputs,
|
||||
)
|
||||
};
|
||||
if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) {
|
||||
for pass_pipeline in pass_pipelines.iter() {
|
||||
if let Some(compiled_pipelines_iter) =
|
||||
|
@ -705,4 +534,141 @@ impl Renderer for WgpuRenderer {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_render_pipeline(
|
||||
&mut self,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
pipeline_descriptor: &mut PipelineDescriptor,
|
||||
shader_storage: &AssetStorage<Shader>,
|
||||
) {
|
||||
if self.render_pipelines.contains_key(&pipeline_handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
let device = self.device.borrow();
|
||||
let layout = pipeline_descriptor.get_layout().unwrap();
|
||||
for bind_group in layout.bind_groups.iter() {
|
||||
if let None = self.wgpu_resources.bind_group_layouts.get(&bind_group.id) {
|
||||
let bind_group_layout_binding = bind_group
|
||||
.bindings
|
||||
.iter()
|
||||
.map(|binding| wgpu::BindGroupLayoutEntry {
|
||||
binding: binding.index,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: (&binding.bind_type).into(),
|
||||
})
|
||||
.collect::<Vec<wgpu::BindGroupLayoutEntry>>();
|
||||
let wgpu_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
bindings: bind_group_layout_binding.as_slice(),
|
||||
});
|
||||
|
||||
self.wgpu_resources
|
||||
.bind_group_layouts
|
||||
.insert(bind_group.id, wgpu_bind_group_layout);
|
||||
}
|
||||
}
|
||||
|
||||
// setup and collect bind group layouts
|
||||
let bind_group_layouts = layout
|
||||
.bind_groups
|
||||
.iter()
|
||||
.map(|bind_group| {
|
||||
self.wgpu_resources
|
||||
.bind_group_layouts
|
||||
.get(&bind_group.id)
|
||||
.unwrap()
|
||||
})
|
||||
.collect::<Vec<&wgpu::BindGroupLayout>>();
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
bind_group_layouts: bind_group_layouts.as_slice(),
|
||||
});
|
||||
|
||||
let owned_vertex_buffer_descriptors = layout
|
||||
.vertex_buffer_descriptors
|
||||
.iter()
|
||||
.map(|v| v.into())
|
||||
.collect::<Vec<OwnedWgpuVertexBufferDescriptor>>();
|
||||
|
||||
let color_states = pipeline_descriptor
|
||||
.color_states
|
||||
.iter()
|
||||
.map(|c| c.into())
|
||||
.collect::<Vec<wgpu::ColorStateDescriptor>>();
|
||||
|
||||
if let None = self
|
||||
.wgpu_resources
|
||||
.shader_modules
|
||||
.get(&pipeline_descriptor.shader_stages.vertex)
|
||||
{
|
||||
self.wgpu_resources.create_shader_module(
|
||||
&device,
|
||||
pipeline_descriptor.shader_stages.vertex,
|
||||
shader_storage,
|
||||
);
|
||||
}
|
||||
|
||||
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(&device, fragment_handle, shader_storage);
|
||||
}
|
||||
};
|
||||
|
||||
let vertex_shader_module = self
|
||||
.wgpu_resources
|
||||
.shader_modules
|
||||
.get(&pipeline_descriptor.shader_stages.vertex)
|
||||
.unwrap();
|
||||
|
||||
let fragment_shader_module = match pipeline_descriptor.shader_stages.fragment {
|
||||
Some(fragment_handle) => Some(
|
||||
self.wgpu_resources
|
||||
.shader_modules
|
||||
.get(&fragment_handle)
|
||||
.unwrap(),
|
||||
),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let mut render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
|
||||
layout: &pipeline_layout,
|
||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||
module: &vertex_shader_module,
|
||||
entry_point: "main",
|
||||
},
|
||||
fragment_stage: match pipeline_descriptor.shader_stages.fragment {
|
||||
Some(_) => Some(wgpu::ProgrammableStageDescriptor {
|
||||
entry_point: "main",
|
||||
module: fragment_shader_module.as_ref().unwrap(),
|
||||
}),
|
||||
None => None,
|
||||
},
|
||||
rasterization_state: pipeline_descriptor
|
||||
.rasterization_state
|
||||
.as_ref()
|
||||
.map(|r| r.into()),
|
||||
primitive_topology: pipeline_descriptor.primitive_topology.into(),
|
||||
color_states: &color_states,
|
||||
depth_stencil_state: pipeline_descriptor
|
||||
.depth_stencil_state
|
||||
.as_ref()
|
||||
.map(|d| d.into()),
|
||||
vertex_state: wgpu::VertexStateDescriptor {
|
||||
index_format: pipeline_descriptor.index_format.into(),
|
||||
vertex_buffers: &owned_vertex_buffer_descriptors
|
||||
.iter()
|
||||
.map(|v| v.into())
|
||||
.collect::<Vec<wgpu::VertexBufferDescriptor>>(),
|
||||
},
|
||||
sample_count: pipeline_descriptor.sample_count,
|
||||
sample_mask: pipeline_descriptor.sample_mask,
|
||||
alpha_to_coverage_enabled: pipeline_descriptor.alpha_to_coverage_enabled,
|
||||
};
|
||||
|
||||
let render_pipeline = device.create_render_pipeline(&mut render_pipeline_descriptor);
|
||||
self.render_pipelines
|
||||
.insert(pipeline_handle, render_pipeline);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue