remove DrawTargets in favor of PassNodes and in preparation for "immediate mode" drawing api

This commit is contained in:
Carter Anderson 2020-06-08 14:35:13 -07:00
parent 6531ccddab
commit 1426208e2f
17 changed files with 253 additions and 392 deletions

View File

@ -2,7 +2,6 @@ use crate::{material::StandardMaterial, nodes::LightsNode, pipelines::build_forw
use bevy_asset::Assets;
use bevy_render::{
base_render_graph,
draw_target::AssignedMeshesDrawTarget,
pipeline::PipelineDescriptor,
render_graph::{
nodes::{AssetUniformNode, PassNode, UniformNode},
@ -41,10 +40,7 @@ impl ForwardPbrRenderGraphBuilder for RenderGraph {
let main_pass: &mut PassNode = self
.get_node_mut(base_render_graph::node::MAIN_PASS)
.unwrap();
main_pass.add_pipeline(
pipelines.add_default(build_forward_pipeline(&mut shaders)),
vec![Box::new(AssignedMeshesDrawTarget)],
);
main_pass.add_pipeline(pipelines.add_default(build_forward_pipeline(&mut shaders)));
}
// TODO: replace these with "autowire" groups

View File

@ -0,0 +1,41 @@
use crate::{render_resource::RenderResourceId, pipeline::PipelineDescriptor};
use bevy_asset::Handle;
use std::ops::Range;
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum DrawType {
Instanced {
indices: Range<u32>,
base_vertex: i32,
instances: Range<u32>,
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct VertexBufferBinding {
pub slot: u32,
pub vertex_buffer: RenderResourceId,
pub offset: u64,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct IndexBufferBinding {
pub vertex_buffer: RenderResourceId,
pub offset: u64,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct BindGroupBinding {
pub vertex_buffer: RenderResourceId,
pub offset: u64,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct DrawCall {
pub pipeline: Handle<PipelineDescriptor>,
pub draw_type: DrawType,
pub vertex_buffers: Vec<VertexBufferBinding>,
pub index_buffer: Option<IndexBufferBinding>,
}
pub struct Draw {}

View File

@ -1,25 +0,0 @@
use crate::{pass::RenderPass, pipeline::PipelineDescriptor, renderer::RenderContext};
use bevy_asset::Handle;
use legion::prelude::{Resources, World};
// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc
pub trait DrawTarget: Send + Sync + 'static {
fn draw(
&self,
world: &World,
resources: &Resources,
render_pass: &mut dyn RenderPass,
pipeline_handle: Handle<PipelineDescriptor>,
pipeline_descriptor: &PipelineDescriptor,
);
fn setup(
&mut self,
_world: &World,
_resources: &Resources,
_render_context: &mut dyn RenderContext,
_pipeline_handle: Handle<PipelineDescriptor>,
_pipeline_descriptor: &PipelineDescriptor,
) {
}
fn get_name(&self) -> String;
}

View File

@ -1,106 +0,0 @@
use bevy_asset::Handle;
use legion::prelude::*;
use crate::{
draw_target::DrawTarget,
pass::RenderPass,
pipeline::{PipelineAssignments, PipelineDescriptor},
render_resource::{
EntitiesWaitingForAssets, EntityRenderResourceAssignments, RenderResourceAssignments,
},
renderer::RenderContext,
Renderable,
};
#[derive(Default)]
pub struct AssignedMeshesDrawTarget;
impl AssignedMeshesDrawTarget {
pub const NAME: &'static str = "AssignedMeshes";
}
impl DrawTarget for AssignedMeshesDrawTarget {
fn draw(
&self,
world: &World,
resources: &Resources,
render_pass: &mut dyn RenderPass,
pipeline_handle: Handle<PipelineDescriptor>,
pipeline_descriptor: &PipelineDescriptor,
) {
let shader_pipeline_assignments = resources.get::<PipelineAssignments>().unwrap();
let entity_render_resource_assignments =
resources.get::<EntityRenderResourceAssignments>().unwrap();
let entities_waiting_for_assets = resources.get::<EntitiesWaitingForAssets>().unwrap();
let global_render_resource_assignments =
resources.get::<RenderResourceAssignments>().unwrap();
render_pass.set_render_resources(pipeline_descriptor, &global_render_resource_assignments);
let assigned_render_resource_assignments = shader_pipeline_assignments
.assignments
.get(&pipeline_handle);
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();
let renderable = world.get_component::<Renderable>(*entity).unwrap();
if !renderable.is_visible
|| renderable.is_instanced
|| entities_waiting_for_assets.contains(entity)
{
continue;
}
if let Some(indices) = render_pass.set_render_resources(
pipeline_descriptor,
&renderable.render_resource_assignments,
) {
render_pass.draw_indexed(indices, 0, 0..1);
}
}
}
}
fn setup(
&mut self,
world: &World,
resources: &Resources,
render_context: &mut dyn RenderContext,
pipeline_handle: Handle<PipelineDescriptor>,
pipeline_descriptor: &PipelineDescriptor,
) {
let pipeline_assignments = resources.get::<PipelineAssignments>().unwrap();
let entity_render_resource_assignments =
resources.get::<EntityRenderResourceAssignments>().unwrap();
let assigned_render_resource_assignments =
pipeline_assignments.assignments.get(&pipeline_handle);
let global_render_resource_assignments =
resources.get::<RenderResourceAssignments>().unwrap();
render_context
.resources()
.setup_bind_groups(pipeline_descriptor, &global_render_resource_assignments);
if let Some(assigned_render_resource_assignments) = assigned_render_resource_assignments {
for assignment_id in assigned_render_resource_assignments.iter() {
let entity = entity_render_resource_assignments
.get(*assignment_id)
.unwrap();
let renderable = world.get_component::<Renderable>(*entity).unwrap();
if !renderable.is_visible || renderable.is_instanced {
continue;
}
render_context.resources().setup_bind_groups(
pipeline_descriptor,
&renderable.render_resource_assignments,
);
}
}
}
fn get_name(&self) -> String {
AssignedMeshesDrawTarget::NAME.to_string()
}
}

View File

@ -1,71 +0,0 @@
use crate::{
draw_target::DrawTarget,
mesh::{self, Mesh},
pass::RenderPass,
pipeline::PipelineDescriptor,
render_resource::ResourceInfo,
Renderable,
};
use bevy_asset::Handle;
use legion::prelude::*;
#[derive(Default)]
pub struct MeshesDrawTarget;
impl MeshesDrawTarget {
pub const NAME: &'static str = "Meshes";
}
impl DrawTarget for MeshesDrawTarget {
fn draw(
&self,
world: &World,
_resources: &Resources,
render_pass: &mut dyn RenderPass,
_pipeline_handle: Handle<PipelineDescriptor>,
pipeline_descriptor: &PipelineDescriptor,
) {
let mut current_mesh_handle = None;
let mut current_mesh_index_len = 0;
let mesh_query = <(Read<Handle<Mesh>>, Read<Renderable>)>::query();
for (mesh_handle, renderable) in mesh_query.iter(world) {
if !renderable.is_visible || renderable.is_instanced {
continue;
}
let render_context = render_pass.get_render_context();
let render_resources = render_context.resources();
if current_mesh_handle != Some(*mesh_handle) {
if let Some(vertex_buffer_resource) = render_resources
.get_asset_resource(*mesh_handle, mesh::VERTEX_BUFFER_ASSET_INDEX)
{
let index_buffer_resource = render_resources
.get_asset_resource(*mesh_handle, mesh::INDEX_BUFFER_ASSET_INDEX)
.unwrap();
render_resources.get_resource_info(
index_buffer_resource,
&mut |resource_info| match resource_info {
Some(ResourceInfo::Buffer(Some(buffer_info))) => {
current_mesh_index_len = (buffer_info.size / 2) as u32
}
_ => panic!("expected a buffer type"),
},
);
render_pass.set_index_buffer(index_buffer_resource, 0);
render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0);
}
// TODO: Verify buffer format matches render pass
current_mesh_handle = Some(*mesh_handle);
}
// TODO: validate bind group properties against shader uniform properties at least once
render_pass
.set_render_resources(pipeline_descriptor, &renderable.render_resource_assignments);
render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1);
}
}
fn get_name(&self) -> String {
MeshesDrawTarget::NAME.to_string()
}
}

View File

@ -1,5 +0,0 @@
mod assigned_meshes_draw_target;
mod meshes_draw_target;
pub use assigned_meshes_draw_target::*;
pub use meshes_draw_target::*;

View File

@ -1,5 +0,0 @@
mod draw_target;
mod draw_targets;
pub use draw_target::*;
pub use draw_targets::*;

View File

@ -1,5 +1,6 @@
pub mod batch;
mod camera;
pub mod draw;
pub mod entity;
pub mod mesh;
pub mod render_graph;
@ -16,7 +17,6 @@ pub use renderable::*;
pub use vertex::Vertex;
pub mod base_render_graph;
pub mod draw_target;
pub mod pass;
pub mod pipeline;
pub mod render_resource;

View File

@ -1,6 +1,6 @@
use crate::{
pipeline::PipelineDescriptor,
render_resource::{RenderResourceId, RenderResourceAssignments},
pipeline::{BindGroupDescriptor, PipelineDescriptor},
render_resource::{RenderResourceId, RenderResourceSet},
renderer::RenderContext,
};
use bevy_asset::Handle;
@ -15,10 +15,9 @@ pub trait RenderPass {
fn set_stencil_reference(&mut self, reference: u32);
fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>);
fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>);
// TODO: try to somehow take into account the "set" pipeline instead of passing it in here
fn set_render_resources(
fn set_bind_group(
&mut self,
pipeline_descriptor: &PipelineDescriptor,
render_resource_assignments: &RenderResourceAssignments,
) -> Option<Range<u32>>;
bind_group_descriptor: &BindGroupDescriptor,
render_resource_set: &RenderResourceSet,
);
}

View File

@ -1,18 +1,22 @@
use crate::{
draw_target::DrawTarget,
pass::{PassDescriptor, TextureAttachment},
pipeline::{PipelineCompiler, PipelineDescriptor},
pass::{PassDescriptor, RenderPass, TextureAttachment},
pipeline::{PipelineAssignments, PipelineCompiler, PipelineDescriptor},
render_graph::{Node, ResourceSlotInfo, ResourceSlots},
render_resource::{ResourceInfo, RenderResourceAssignments},
render_resource::{
EntitiesWaitingForAssets, EntityRenderResourceAssignments, RenderResourceAssignments,
ResourceInfo,
},
renderer::RenderContext,
shader::Shader,
Renderable,
};
use bevy_asset::{Assets, Handle};
use legion::prelude::*;
use std::ops::Range;
pub struct PassNode {
descriptor: PassDescriptor,
pipelines: Vec<(Handle<PipelineDescriptor>, Vec<Box<dyn DrawTarget>>)>,
pipelines: Vec<Handle<PipelineDescriptor>>,
inputs: Vec<ResourceSlotInfo>,
color_attachment_input_indices: Vec<Option<usize>>,
depth_stencil_attachment_input_index: Option<usize>,
@ -54,12 +58,64 @@ impl PassNode {
}
}
pub fn add_pipeline(
&mut self,
pipeline_handle: Handle<PipelineDescriptor>,
draw_targets: Vec<Box<dyn DrawTarget>>,
) {
self.pipelines.push((pipeline_handle, draw_targets));
pub fn add_pipeline(&mut self, pipeline_handle: Handle<PipelineDescriptor>) {
self.pipelines.push(pipeline_handle);
}
fn set_render_resources(
render_pass: &mut dyn RenderPass,
pipeline_descriptor: &PipelineDescriptor,
render_resource_assignments: &RenderResourceAssignments,
) -> Option<Range<u32>> {
let pipeline_layout = pipeline_descriptor.get_layout().unwrap();
// PERF: vertex buffer lookup comes at a cost when vertex buffers aren't in render_resource_assignments. iterating over render_resource_assignment vertex buffers
// would likely be faster
let mut indices = None;
for (i, vertex_buffer_descriptor) in
pipeline_layout.vertex_buffer_descriptors.iter().enumerate()
{
if let Some((vertex_buffer, index_buffer)) =
render_resource_assignments.get_vertex_buffer(&vertex_buffer_descriptor.name)
{
log::trace!(
"set vertex buffer {}: {} ({:?})",
i,
vertex_buffer_descriptor.name,
vertex_buffer
);
render_pass.set_vertex_buffer(i as u32, vertex_buffer, 0);
if let Some(index_buffer) = index_buffer {
log::trace!(
"set index buffer: {} ({:?})",
vertex_buffer_descriptor.name,
index_buffer
);
render_pass.set_index_buffer(index_buffer, 0);
render_pass
.get_render_context()
.resources()
.get_resource_info(
index_buffer,
&mut |resource_info| match resource_info {
Some(ResourceInfo::Buffer(Some(buffer_info))) => {
indices = Some(0..(buffer_info.size / 2) as u32)
}
_ => panic!("expected a buffer type"),
},
);
}
}
}
for bind_group in pipeline_layout.bind_groups.iter() {
if let Some(render_resource_set) =
render_resource_assignments.get_render_resource_set(bind_group.id)
{
render_pass.set_bind_group(bind_group, &render_resource_set);
}
}
indices
}
}
@ -78,6 +134,12 @@ impl Node for PassNode {
) {
let pipeline_compiler = resources.get::<PipelineCompiler>().unwrap();
let pipelines = resources.get::<Assets<PipelineDescriptor>>().unwrap();
let shader_pipeline_assignments = resources.get::<PipelineAssignments>().unwrap();
let entity_render_resource_assignments =
resources.get::<EntityRenderResourceAssignments>().unwrap();
let entities_waiting_for_assets = resources.get::<EntitiesWaitingForAssets>().unwrap();
let mut render_resource_assignments =
resources.get_mut::<RenderResourceAssignments>().unwrap();
for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() {
if let Some(input_index) = self.color_attachment_input_indices[i] {
@ -94,50 +156,71 @@ impl Node for PassNode {
.attachment = TextureAttachment::RenderResource(input.get(input_index).unwrap());
}
let shaders = resources.get::<Assets<Shader>>().unwrap();
for (pipeline_handle, draw_targets) in self.pipelines.iter_mut() {
if let Some(compiled_pipelines_iter) =
pipeline_compiler.iter_compiled_pipelines(*pipeline_handle)
{
for compiled_pipeline_handle in compiled_pipelines_iter {
let compiled_pipeline_descriptor =
pipelines.get(compiled_pipeline_handle).unwrap();
{
let render_resource_context = render_context.resources();
let pipeline_layout = compiled_pipeline_descriptor.get_layout().unwrap();
{
// TODO: this breaks down in a parallel setting. it needs to change. ideally in a way that
// doesn't require modifying RenderResourceAssignments
let mut render_resource_assignments =
resources.get_mut::<RenderResourceAssignments>().unwrap();
for bind_group in pipeline_layout.bind_groups.iter() {
render_resource_assignments.update_render_resource_set_id(bind_group);
// TODO: try merging the two pipeline loops below
let shaders = resources.get::<Assets<Shader>>().unwrap();
for pipeline_handle in self.pipelines.iter() {
if let Some(compiled_pipelines_iter) =
pipeline_compiler.iter_compiled_pipelines(*pipeline_handle)
{
for compiled_pipeline_handle in compiled_pipelines_iter {
let compiled_pipeline_descriptor =
pipelines.get(compiled_pipeline_handle).unwrap();
let pipeline_layout = compiled_pipeline_descriptor.get_layout().unwrap();
{
// TODO: this breaks down in a parallel setting. it needs to change. ideally in a way that
// doesn't require modifying RenderResourceAssignments
for bind_group in pipeline_layout.bind_groups.iter() {
render_resource_assignments
.update_render_resource_set_id(bind_group);
}
}
}
render_context.resources().create_render_pipeline(
*compiled_pipeline_handle,
&compiled_pipeline_descriptor,
&shaders,
);
for draw_target in draw_targets.iter_mut() {
draw_target.setup(
world,
resources,
render_context,
render_resource_context.create_render_pipeline(
*compiled_pipeline_handle,
compiled_pipeline_descriptor,
&compiled_pipeline_descriptor,
&shaders,
);
render_resource_context.setup_bind_groups(
compiled_pipeline_descriptor,
&render_resource_assignments,
);
let assigned_render_resource_assignments = shader_pipeline_assignments
.assignments
.get(&compiled_pipeline_handle);
if let Some(assigned_render_resource_assignments) =
assigned_render_resource_assignments
{
for assignment_id in assigned_render_resource_assignments.iter() {
let entity = entity_render_resource_assignments
.get(*assignment_id)
.unwrap();
let renderable =
world.get_component::<Renderable>(*entity).unwrap();
if !renderable.is_visible || renderable.is_instanced {
continue;
}
render_resource_context.setup_bind_groups(
compiled_pipeline_descriptor,
&renderable.render_resource_assignments,
);
}
}
}
}
}
}
let render_resource_assignments = resources.get::<RenderResourceAssignments>().unwrap();
render_context.begin_pass(
&self.descriptor,
&render_resource_assignments,
&mut |render_pass| {
for (pipeline_handle, draw_targets) in self.pipelines.iter() {
for pipeline_handle in self.pipelines.iter() {
if let Some(compiled_pipelines_iter) =
pipeline_compiler.iter_compiled_pipelines(*pipeline_handle)
{
@ -145,14 +228,45 @@ impl Node for PassNode {
let compiled_pipeline_descriptor =
pipelines.get(compiled_pipeline_handle).unwrap();
render_pass.set_pipeline(*compiled_pipeline_handle);
for draw_target in draw_targets.iter() {
draw_target.draw(
world,
resources,
render_pass,
*compiled_pipeline_handle,
compiled_pipeline_descriptor,
);
// set global render resources
Self::set_render_resources(
render_pass,
compiled_pipeline_descriptor,
&render_resource_assignments,
);
// draw entities assigned to this pipeline
let assigned_render_resource_assignments = shader_pipeline_assignments
.assignments
.get(&compiled_pipeline_handle);
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();
let renderable =
world.get_component::<Renderable>(*entity).unwrap();
if !renderable.is_visible
|| renderable.is_instanced
|| entities_waiting_for_assets.contains(entity)
{
continue;
}
// set local render resources
if let Some(indices) = Self::set_render_resources(
render_pass,
compiled_pipeline_descriptor,
&renderable.render_resource_assignments,
) {
render_pass.draw_indexed(indices, 0, 0..1);
}
}
}
}
}

View File

@ -2,7 +2,6 @@ use crate::{ColorMaterial, Quad, TextureAtlas, TextureAtlasSprite};
use bevy_asset::{Assets, Handle};
use bevy_render::{
base_render_graph,
draw_target::AssignedMeshesDrawTarget,
pipeline::{state_descriptors::*, PipelineDescriptor},
render_graph::{
nodes::{AssetUniformNode, PassNode, UniformNode},
@ -153,14 +152,8 @@ impl SpriteRenderGraphBuilder for RenderGraph {
let main_pass: &mut PassNode = self
.get_node_mut(base_render_graph::node::MAIN_PASS)
.unwrap();
main_pass.add_pipeline(
SPRITE_PIPELINE_HANDLE,
vec![Box::new(AssignedMeshesDrawTarget)],
);
main_pass.add_pipeline(
SPRITE_SHEET_PIPELINE_HANDLE,
vec![Box::new(AssignedMeshesDrawTarget)],
);
main_pass.add_pipeline(SPRITE_PIPELINE_HANDLE);
main_pass.add_pipeline(SPRITE_SHEET_PIPELINE_HANDLE);
self
}
}

View File

@ -1,7 +1,6 @@
use bevy_asset::{Assets, Handle};
use bevy_render::{
base_render_graph,
draw_target::AssignedMeshesDrawTarget,
pipeline::{state_descriptors::*, PipelineDescriptor},
render_graph::{
nodes::{CameraNode, PassNode},
@ -83,7 +82,7 @@ impl UiRenderGraphBuilder for RenderGraph {
let main_pass: &mut PassNode = self
.get_node_mut(base_render_graph::node::MAIN_PASS)
.unwrap();
main_pass.add_pipeline(UI_PIPELINE_HANDLE, vec![Box::new(AssignedMeshesDrawTarget)]);
main_pass.add_pipeline(UI_PIPELINE_HANDLE);
self
}
}

View File

@ -6,12 +6,12 @@ use bevy_render::{
PassDescriptor, RenderPass, RenderPassColorAttachmentDescriptor,
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
},
render_resource::{RenderResourceId, RenderResourceAssignment, RenderResourceAssignments},
render_resource::{RenderResourceAssignment, RenderResourceAssignments, RenderResourceId},
renderer::{RenderContext, RenderResourceContext},
texture::Extent3d,
};
use std::{collections::HashMap, sync::Arc};
use std::sync::Arc;
#[derive(Default)]
pub struct LazyCommandEncoder {
@ -138,10 +138,10 @@ impl RenderContext for WgpuRenderContext {
&mut encoder,
);
let mut wgpu_render_pass = WgpuRenderPass {
render_context: self,
render_pass,
render_context: self,
render_resources: refs,
bound_bind_groups: HashMap::default(),
pipeline_descriptor: None,
};
run_pass(&mut wgpu_render_pass);

View File

@ -2,19 +2,17 @@ use crate::{renderer::WgpuRenderContext, WgpuResourceRefs};
use bevy_asset::Handle;
use bevy_render::{
pass::RenderPass,
pipeline::PipelineDescriptor,
render_resource::{
RenderResourceId, RenderResourceAssignments, RenderResourceSetId, ResourceInfo,
},
pipeline::{BindGroupDescriptor, PipelineDescriptor},
render_resource::{RenderResourceId, RenderResourceSet},
renderer::RenderContext,
};
use std::{collections::HashMap, ops::Range};
use std::ops::Range;
pub struct WgpuRenderPass<'a> {
pub render_pass: wgpu::RenderPass<'a>,
pub render_context: &'a WgpuRenderContext,
pub render_resources: WgpuResourceRefs<'a>,
pub bound_bind_groups: HashMap<u32, RenderResourceSetId>,
pub pipeline_descriptor: Option<&'a PipelineDescriptor>,
}
impl<'a> RenderPass for WgpuRenderPass<'a> {
@ -51,102 +49,42 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
self.render_pass.draw(vertices, instances);
}
fn set_render_resources(
fn set_bind_group(
&mut self,
pipeline_descriptor: &PipelineDescriptor,
render_resource_assignments: &RenderResourceAssignments,
) -> Option<Range<u32>> {
let pipeline_layout = pipeline_descriptor.get_layout().unwrap();
// PERF: vertex buffer lookup comes at a cost when vertex buffers aren't in render_resource_assignments. iterating over render_resource_assignment vertex buffers
// would likely be faster
let mut indices = None;
for (i, vertex_buffer_descriptor) in
pipeline_layout.vertex_buffer_descriptors.iter().enumerate()
bind_group_descriptor: &BindGroupDescriptor,
render_resource_set: &RenderResourceSet,
) {
if let Some(bind_group_info) = self
.render_resources
.bind_groups
.get(&bind_group_descriptor.id)
{
if let Some((vertex_buffer, index_buffer)) =
render_resource_assignments.get_vertex_buffer(&vertex_buffer_descriptor.name)
if let Some(wgpu_bind_group) = bind_group_info.bind_groups.get(&render_resource_set.id)
{
log::trace!(
"set vertex buffer {}: {} ({:?})",
i,
vertex_buffer_descriptor.name,
vertex_buffer
);
self.set_vertex_buffer(i as u32, vertex_buffer, 0);
if let Some(index_buffer) = index_buffer {
log::trace!(
"set index buffer: {} ({:?})",
vertex_buffer_descriptor.name,
index_buffer
);
self.set_index_buffer(index_buffer, 0);
self.render_context.resources().get_resource_info(
index_buffer,
&mut |resource_info| match resource_info {
Some(ResourceInfo::Buffer(Some(buffer_info))) => {
indices = Some(0..(buffer_info.size / 2) as u32)
}
_ => panic!("expected a buffer type"),
},
);
}
}
}
for bind_group in pipeline_layout.bind_groups.iter() {
if let Some(resource_set) =
render_resource_assignments.get_render_resource_set(bind_group.id)
{
if let Some(bind_group_info) = self.render_resources.bind_groups.get(&bind_group.id)
const EMPTY: &'static [u32] = &[];
let dynamic_uniform_indices = if let Some(ref dynamic_uniform_indices) =
render_resource_set.dynamic_uniform_indices
{
if let Some(wgpu_bind_group) = bind_group_info.bind_groups.get(&resource_set.id)
{
const EMPTY: &'static [u32] = &[];
let dynamic_uniform_indices = if let Some(ref dynamic_uniform_indices) =
resource_set.dynamic_uniform_indices
{
dynamic_uniform_indices.as_slice()
} else {
EMPTY
};
// don't bind bind groups if they are already set
// TODO: these checks come at a performance cost. make sure it's worth it!
if let Some(bound_render_resource_set) =
self.bound_bind_groups.get(&bind_group.index)
{
if *bound_render_resource_set == resource_set.id
&& dynamic_uniform_indices.len() == 0
{
continue;
}
}
if dynamic_uniform_indices.len() == 0 {
self.bound_bind_groups
.insert(bind_group.index, resource_set.id);
} else {
self.bound_bind_groups.remove(&bind_group.index);
}
log::trace!(
"set bind group {} {:?}: {:?}",
bind_group.index,
dynamic_uniform_indices,
resource_set.id
);
self.render_pass.set_bind_group(
bind_group.index,
wgpu_bind_group,
dynamic_uniform_indices,
);
}
dynamic_uniform_indices.as_slice()
} else {
EMPTY
};
log::trace!(
"set bind group {:?} {:?}: {:?}",
bind_group_descriptor.id,
dynamic_uniform_indices,
render_resource_set.id
);
self.render_pass.set_bind_group(
bind_group_descriptor.index,
wgpu_bind_group,
dynamic_uniform_indices,
);
}
}
indices
}
fn set_pipeline(&mut self, pipeline_handle: Handle<PipelineDescriptor>) {
let pipeline = self.render_resources.render_pipelines.get(&pipeline_handle).expect(
"Attempted to use a pipeline that does not exist in this RenderPass's RenderContext",

View File

@ -55,10 +55,7 @@ fn setup(
render_graph.add_system_node("my_material", AssetUniformNode::<MyMaterial>::new(true));
let main_pass: &mut PassNode = render_graph.get_node_mut("main_pass").unwrap();
main_pass.add_pipeline(
pipeline_handle,
vec![Box::new(draw_target::AssignedMeshesDrawTarget)],
);
main_pass.add_pipeline(pipeline_handle);
pipeline_handle
};

View File

@ -65,10 +65,7 @@ fn setup(
}));
render_graph.add_system_node("my_material", AssetUniformNode::<MyMaterial>::new(true));
let main_pass: &mut PassNode = render_graph.get_node_mut("main_pass").unwrap();
main_pass.add_pipeline(
pipeline_handle,
vec![Box::new(draw_target::AssignedMeshesDrawTarget)],
);
main_pass.add_pipeline(pipeline_handle);
pipeline_handle
};

View File

@ -14,7 +14,6 @@ pub use crate::{
pbr::{entity::*, light::Light, material::StandardMaterial},
property::{DynamicProperties, Properties, PropertiesVal, Property, PropertyVal},
render::{
draw_target,
entity::*,
mesh::{shape, Mesh},
pipeline::PipelineDescriptor,