render: more progress on immediate mode rendering and DrawableText

This commit is contained in:
Carter Anderson 2020-06-17 13:10:33 -07:00
parent f4acbdddad
commit e57fdca1bc
16 changed files with 259 additions and 158 deletions

View File

@ -1,8 +1,8 @@
use crate::{ use crate::{
pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineDescriptor}, pipeline::{PipelineDescriptor, PipelineLayout},
render_resource::{ render_resource::{
BindGroup, BindGroupId, BufferId, BufferUsage, RenderResource, RenderResourceBinding, AssetRenderResourceBindings, BindGroup, BindGroupId, BufferId, BufferUsage, RenderResource,
RenderResourceBindings, SharedBuffers, RenderResourceBinding, RenderResourceBindings, SharedBuffers,
}, },
renderer::RenderResourceContext, renderer::RenderResourceContext,
}; };
@ -31,7 +31,6 @@ pub enum RenderCommand {
}, },
SetBindGroup { SetBindGroup {
index: u32, index: u32,
bind_group_descriptor: BindGroupDescriptorId,
bind_group: BindGroupId, bind_group: BindGroupId,
dynamic_uniform_indices: Option<Arc<Vec<u32>>>, dynamic_uniform_indices: Option<Arc<Vec<u32>>>,
}, },
@ -64,6 +63,7 @@ impl Draw {
pipelines: &'a Assets<PipelineDescriptor>, pipelines: &'a Assets<PipelineDescriptor>,
render_resource_context: &'a dyn RenderResourceContext, render_resource_context: &'a dyn RenderResourceContext,
render_resource_bindings: &'a RenderResourceBindings, render_resource_bindings: &'a RenderResourceBindings,
asset_render_resource_bindings: &'a AssetRenderResourceBindings,
shared_buffers: &'a SharedBuffers, shared_buffers: &'a SharedBuffers,
) -> DrawContext { ) -> DrawContext {
DrawContext { DrawContext {
@ -71,6 +71,7 @@ impl Draw {
pipelines, pipelines,
render_resource_context, render_resource_context,
render_resource_bindings, render_resource_bindings,
asset_render_resource_bindings,
shared_buffers, shared_buffers,
current_pipeline: None, current_pipeline: None,
} }
@ -89,6 +90,8 @@ pub enum DrawError {
NoPipelineSet, NoPipelineSet,
#[error("Pipeline has no layout")] #[error("Pipeline has no layout")]
PipelineHasNoLayout, PipelineHasNoLayout,
#[error("A BindGroup with the given index does not exist")]
BindGroupDescriptorDoesNotExist { index: u32 },
#[error("Failed to get a buffer for the given RenderResource.")] #[error("Failed to get a buffer for the given RenderResource.")]
BufferAllocationFailure, BufferAllocationFailure,
} }
@ -98,6 +101,7 @@ pub struct DrawContext<'a> {
pub pipelines: &'a Assets<PipelineDescriptor>, pub pipelines: &'a Assets<PipelineDescriptor>,
pub render_resource_context: &'a dyn RenderResourceContext, pub render_resource_context: &'a dyn RenderResourceContext,
pub render_resource_bindings: &'a RenderResourceBindings, pub render_resource_bindings: &'a RenderResourceBindings,
pub asset_render_resource_bindings: &'a AssetRenderResourceBindings,
pub shared_buffers: &'a SharedBuffers, pub shared_buffers: &'a SharedBuffers,
pub current_pipeline: Option<&'a PipelineDescriptor>, pub current_pipeline: Option<&'a PipelineDescriptor>,
} }
@ -146,14 +150,9 @@ impl<'a> DrawContext<'a> {
self.render_command(RenderCommand::SetIndexBuffer { buffer, offset }); self.render_command(RenderCommand::SetIndexBuffer { buffer, offset });
} }
pub fn set_bind_group( pub fn set_bind_group(&mut self, index: u32, bind_group: &BindGroup) {
&mut self,
bind_group_descriptor: &BindGroupDescriptor,
bind_group: &BindGroup,
) {
self.render_command(RenderCommand::SetBindGroup { self.render_command(RenderCommand::SetBindGroup {
index: bind_group_descriptor.index, index,
bind_group_descriptor: bind_group_descriptor.id,
bind_group: bind_group.id, bind_group: bind_group.id,
dynamic_uniform_indices: bind_group.dynamic_uniform_indices.clone(), dynamic_uniform_indices: bind_group.dynamic_uniform_indices.clone(),
}); });
@ -167,6 +166,40 @@ impl<'a> DrawContext<'a> {
}); });
} }
pub fn get_pipeline_descriptor(&self) -> Result<&PipelineDescriptor, DrawError> {
self.current_pipeline
.ok_or_else(|| DrawError::NoPipelineSet)
}
pub fn get_pipeline_layout(&self) -> Result<&PipelineLayout, DrawError> {
self.get_pipeline_descriptor().and_then(|descriptor| {
descriptor
.get_layout()
.ok_or_else(|| DrawError::PipelineHasNoLayout)
})
}
pub fn set_bind_groups_from_bindings(
&mut self,
render_resource_bindings: &RenderResourceBindings,
) -> Result<(), DrawError> {
let pipeline = self
.current_pipeline
.ok_or_else(|| DrawError::NoPipelineSet)?;
let layout = pipeline
.get_layout()
.ok_or_else(|| DrawError::PipelineHasNoLayout)?;
for bind_group_descriptor in layout.bind_groups.iter() {
if let Some(local_bind_group) =
render_resource_bindings.get_descriptor_bind_group(bind_group_descriptor.id)
{
self.set_bind_group(bind_group_descriptor.index, local_bind_group);
}
}
Ok(())
}
#[inline] #[inline]
pub fn render_command(&mut self, render_command: RenderCommand) { pub fn render_command(&mut self, render_command: RenderCommand) {
self.draw.render_commands.push(render_command); self.draw.render_commands.push(render_command);
@ -185,6 +218,7 @@ pub fn draw_system<T: Drawable + Component>(
pipelines: Res<Assets<PipelineDescriptor>>, pipelines: Res<Assets<PipelineDescriptor>>,
render_resource_bindings: Res<RenderResourceBindings>, render_resource_bindings: Res<RenderResourceBindings>,
render_resource_context: Res<Box<dyn RenderResourceContext>>, render_resource_context: Res<Box<dyn RenderResourceContext>>,
asset_render_resource_bindings: Res<AssetRenderResourceBindings>,
shared_buffers: Res<SharedBuffers>, shared_buffers: Res<SharedBuffers>,
mut draw: ComMut<Draw>, mut draw: ComMut<Draw>,
mut drawable: ComMut<T>, mut drawable: ComMut<T>,
@ -193,6 +227,7 @@ pub fn draw_system<T: Drawable + Component>(
&pipelines, &pipelines,
&**render_resource_context, &**render_resource_context,
&render_resource_bindings, &render_resource_bindings,
&asset_render_resource_bindings,
&shared_buffers, &shared_buffers,
); );
draw_context.draw(drawable.as_mut()).unwrap(); draw_context.draw(drawable.as_mut()).unwrap();

View File

@ -18,7 +18,7 @@ pub trait RenderPass {
fn set_bind_group( fn set_bind_group(
&mut self, &mut self,
index: u32, index: u32,
bind_group_descriptor: BindGroupDescriptorId, bind_group_descriptor_id: BindGroupDescriptorId,
bind_group: BindGroupId, bind_group: BindGroupId,
dynamic_uniform_indices: Option<&[u32]>, dynamic_uniform_indices: Option<&[u32]>,
); );

View File

@ -1,5 +1,5 @@
use super::{ use super::{
state_descriptors::PrimitiveTopology, PipelineDescriptor, RenderPipeline, RenderPipelines, state_descriptors::PrimitiveTopology, PipelineDescriptor, RenderPipelines,
VertexBufferDescriptors, VertexBufferDescriptors,
}; };
use crate::{ use crate::{
@ -8,9 +8,8 @@ use crate::{
shader::{Shader, ShaderSource}, shader::{Shader, ShaderSource},
}; };
use bevy_asset::{Assets, Handle}; use bevy_asset::{Assets, Handle};
use std::collections::{HashMap, HashSet};
use legion::prelude::*; use legion::prelude::*;
use std::collections::{HashMap, HashSet};
#[derive(Clone, Eq, PartialEq, Debug, Default)] #[derive(Clone, Eq, PartialEq, Debug, Default)]
pub struct PipelineSpecialization { pub struct PipelineSpecialization {
@ -78,20 +77,22 @@ impl PipelineCompiler {
fn compile_pipeline( fn compile_pipeline(
&mut self, &mut self,
vertex_buffer_descriptors: &VertexBufferDescriptors, render_resource_context: &dyn RenderResourceContext,
pipelines: &mut Assets<PipelineDescriptor>,
shaders: &mut Assets<Shader>, shaders: &mut Assets<Shader>,
pipeline_descriptor: &PipelineDescriptor, source_pipeline: Handle<PipelineDescriptor>,
render_pipeline: &RenderPipeline, vertex_buffer_descriptors: &VertexBufferDescriptors,
pipeline_specialization: &PipelineSpecialization,
render_resource_bindings: &RenderResourceBindings, render_resource_bindings: &RenderResourceBindings,
) -> PipelineDescriptor { ) -> Handle<PipelineDescriptor> {
let mut compiled_pipeline_descriptor = pipeline_descriptor.clone(); let source_descriptor = pipelines.get(&source_pipeline).unwrap();
let mut compiled_descriptor = source_descriptor.clone();
compiled_pipeline_descriptor.shader_stages.vertex = self.compile_shader( compiled_descriptor.shader_stages.vertex = self.compile_shader(
shaders, shaders,
&pipeline_descriptor.shader_stages.vertex, &compiled_descriptor.shader_stages.vertex,
&render_pipeline.specialization.shader_specialization, &pipeline_specialization.shader_specialization,
); );
compiled_pipeline_descriptor.shader_stages.fragment = pipeline_descriptor compiled_descriptor.shader_stages.fragment = compiled_descriptor
.shader_stages .shader_stages
.fragment .fragment
.as_ref() .as_ref()
@ -99,23 +100,42 @@ impl PipelineCompiler {
self.compile_shader( self.compile_shader(
shaders, shaders,
fragment, fragment,
&render_pipeline.specialization.shader_specialization, &pipeline_specialization.shader_specialization,
) )
}); });
compiled_pipeline_descriptor.reflect_layout( compiled_descriptor.reflect_layout(
shaders, shaders,
true, true,
Some(vertex_buffer_descriptors), Some(vertex_buffer_descriptors),
Some(render_resource_bindings), Some(render_resource_bindings),
); );
compiled_pipeline_descriptor.primitive_topology = compiled_descriptor.primitive_topology = pipeline_specialization.primitive_topology;
render_pipeline.specialization.primitive_topology; let compiled_pipeline_handle =
compiled_pipeline_descriptor if *pipeline_specialization == PipelineSpecialization::default() {
pipelines.set(source_pipeline, compiled_descriptor);
source_pipeline
} else {
pipelines.add(compiled_descriptor)
};
render_resource_context.create_render_pipeline(
compiled_pipeline_handle,
pipelines.get(&compiled_pipeline_handle).unwrap(),
&shaders,
);
let compiled_pipelines = self
.specialized_pipelines
.entry(source_pipeline)
.or_insert_with(|| Vec::new());
compiled_pipelines.push((pipeline_specialization.clone(), compiled_pipeline_handle));
compiled_pipeline_handle
} }
fn compile_pipelines( fn compile_render_pipelines(
&mut self, &mut self,
vertex_buffer_descriptors: &VertexBufferDescriptors, vertex_buffer_descriptors: &VertexBufferDescriptors,
pipelines: &mut Assets<PipelineDescriptor>, pipelines: &mut Assets<PipelineDescriptor>,
@ -125,44 +145,27 @@ impl PipelineCompiler {
) { ) {
for render_pipeline in render_pipelines.pipelines.iter_mut() { for render_pipeline in render_pipelines.pipelines.iter_mut() {
let source_pipeline = render_pipeline.pipeline; let source_pipeline = render_pipeline.pipeline;
if let None = self.specialized_pipelines.get(&source_pipeline) {
self.specialized_pipelines
.insert(source_pipeline, Vec::new());
}
let compiled_pipeline_handle = if let Some((_shader_defs, compiled_pipeline_handle)) = let compiled_pipeline_handle = if let Some((_shader_defs, compiled_pipeline_handle)) =
self.specialized_pipelines self.specialized_pipelines
.get_mut(&source_pipeline) .get_mut(&source_pipeline)
.unwrap() .and_then(|specialized_pipelines| {
.iter() specialized_pipelines.iter().find(
.find(|(pipeline_specialization, _compiled_pipeline_handle)| { |(pipeline_specialization, _compiled_pipeline_handle)| {
*pipeline_specialization == render_pipeline.specialization *pipeline_specialization == render_pipeline.specialization
},
)
}) { }) {
*compiled_pipeline_handle *compiled_pipeline_handle
} else { } else {
let pipeline_descriptor = pipelines.get(&source_pipeline).unwrap(); self.compile_pipeline(
let compiled_pipeline_descriptor = self.compile_pipeline( render_resource_context,
vertex_buffer_descriptors, pipelines,
shaders, shaders,
pipeline_descriptor, source_pipeline,
render_pipeline, vertex_buffer_descriptors,
&render_pipeline.specialization,
&render_pipelines.bindings, &render_pipelines.bindings,
); )
let compiled_pipeline_handle = pipelines.add(compiled_pipeline_descriptor);
render_resource_context.create_render_pipeline(
compiled_pipeline_handle,
pipelines.get(&compiled_pipeline_handle).unwrap(),
&shaders,
);
let compiled_pipelines = self
.specialized_pipelines
.get_mut(&source_pipeline)
.unwrap();
compiled_pipelines.push((
render_pipeline.specialization.clone(),
compiled_pipeline_handle,
));
compiled_pipeline_handle
}; };
render_pipeline.specialized_pipeline = Some(compiled_pipeline_handle); render_pipeline.specialized_pipeline = Some(compiled_pipeline_handle);
@ -198,15 +201,44 @@ pub fn compile_pipelines_system(
mut pipeline_compiler: ResMut<PipelineCompiler>, mut pipeline_compiler: ResMut<PipelineCompiler>,
mut shaders: ResMut<Assets<Shader>>, mut shaders: ResMut<Assets<Shader>>,
mut pipelines: ResMut<Assets<PipelineDescriptor>>, mut pipelines: ResMut<Assets<PipelineDescriptor>>,
// pipeline_asset_events: Res<Events<AssetEvent<PipelineDescriptor>>>,
vertex_buffer_descriptors: Res<VertexBufferDescriptors>, vertex_buffer_descriptors: Res<VertexBufferDescriptors>,
render_resource_context: Res<Box<dyn RenderResourceContext>>, render_resource_context: Res<Box<dyn RenderResourceContext>>,
query: &mut Query<Write<RenderPipelines>>, query: &mut Query<Write<RenderPipelines>>,
) { ) {
let render_resource_context = &**render_resource_context; let render_resource_context = &**render_resource_context;
// let default_specialization = PipelineSpecialization::default();
// NOTE: this intentionally only handles events that happened prior to this system during this frame. this results in
// "specialized pipeline" events being ignored.
// for event in pipeline_asset_events.iter_current_update_events() {
// let handle_to_compile = match event {
// AssetEvent::Created { handle } => Some(*handle),
// AssetEvent::Modified { handle } => {
// // TODO: clean up old pipelines
// Some(*handle)
// }
// AssetEvent::Removed { handle } => {
// // TODO: clean up old pipelines
// None
// }
// };
// if let Some(handle_to_compile) = handle_to_compile {
// pipeline_compiler.compile_pipeline(
// render_resource_context,
// &mut pipelines,
// &mut shaders,
// handle_to_compile,
// &vertex_buffer_descriptors,
// &default_specialization,
// None,
// );
// }
// }
// TODO: only update when RenderPipelines is changed // TODO: only update when RenderPipelines is changed
for mut render_pipelines in query.iter_mut(world) { for mut render_pipelines in query.iter_mut(world) {
pipeline_compiler.compile_pipelines( pipeline_compiler.compile_render_pipelines(
&vertex_buffer_descriptors, &vertex_buffer_descriptors,
&mut pipelines, &mut pipelines,
&mut shaders, &mut shaders,

View File

@ -9,6 +9,12 @@ pub struct PipelineLayout {
} }
impl PipelineLayout { impl PipelineLayout {
pub fn get_bind_group(&self, index: u32) -> Option<&BindGroupDescriptor> {
self.bind_groups
.iter()
.find(|bind_group| bind_group.index == index)
}
pub fn from_shader_layouts(shader_layouts: &mut [ShaderLayout]) -> Self { pub fn from_shader_layouts(shader_layouts: &mut [ShaderLayout]) -> Self {
let mut bind_groups = HashMap::<u32, BindGroupDescriptor>::new(); let mut bind_groups = HashMap::<u32, BindGroupDescriptor>::new();
let mut vertex_buffer_descriptors = Vec::new(); let mut vertex_buffer_descriptors = Vec::new();

View File

@ -69,12 +69,12 @@ impl Drawable for RenderPipelines {
.bindings .bindings
.get_descriptor_bind_group(bind_group_descriptor.id) .get_descriptor_bind_group(bind_group_descriptor.id)
{ {
draw.set_bind_group(bind_group_descriptor, local_bind_group); draw.set_bind_group(bind_group_descriptor.index, local_bind_group);
} else if let Some(global_bind_group) = draw } else if let Some(global_bind_group) = draw
.render_resource_bindings .render_resource_bindings
.get_descriptor_bind_group(bind_group_descriptor.id) .get_descriptor_bind_group(bind_group_descriptor.id)
{ {
draw.set_bind_group(bind_group_descriptor, global_bind_group); draw.set_bind_group(bind_group_descriptor.index, global_bind_group);
} }
} }
let mut indices = 0..0; let mut indices = 0..0;

View File

@ -80,6 +80,10 @@ impl CommandQueue {
self.push(Command::FreeBuffer(buffer)); self.push(Command::FreeBuffer(buffer));
} }
pub fn clear(&mut self) {
self.queue.lock().unwrap().clear();
}
pub fn execute(&mut self, render_context: &mut dyn RenderContext) { pub fn execute(&mut self, render_context: &mut dyn RenderContext) {
for command in self.queue.lock().unwrap().drain(..) { for command in self.queue.lock().unwrap().drain(..) {
match command { match command {

View File

@ -131,13 +131,15 @@ impl Node for MainPassNode {
} }
RenderCommand::SetBindGroup { RenderCommand::SetBindGroup {
index, index,
bind_group_descriptor,
bind_group, bind_group,
dynamic_uniform_indices, dynamic_uniform_indices,
} => { } => {
let pipeline = pipelines.get(&draw_state.pipeline.unwrap()).unwrap();
let layout = pipeline.get_layout().unwrap();
let bind_group_descriptor = layout.get_bind_group(*index).unwrap();
render_pass.set_bind_group( render_pass.set_bind_group(
*index, *index,
*bind_group_descriptor, bind_group_descriptor.id,
*bind_group, *bind_group,
dynamic_uniform_indices dynamic_uniform_indices
.as_ref() .as_ref()

View File

@ -1,13 +1,15 @@
mod camera_node; mod camera_node;
mod pass_node; mod main_pass_node;
mod render_resources_node; mod render_resources_node;
mod shared_buffers_node;
mod texture_copy_node; mod texture_copy_node;
mod window_swapchain_node; mod window_swapchain_node;
mod window_texture_node; mod window_texture_node;
pub use camera_node::*; pub use camera_node::*;
pub use pass_node::*; pub use main_pass_node::*;
pub use render_resources_node::*; pub use render_resources_node::*;
pub use shared_buffers_node::*;
pub use texture_copy_node::*; pub use texture_copy_node::*;
pub use window_swapchain_node::*; pub use window_swapchain_node::*;
pub use window_texture_node::*; pub use window_texture_node::*;

View File

@ -1,6 +1,5 @@
use crate::{ use crate::{
render_graph::{Node, ResourceSlots}, render_graph::{Node, ResourceSlots},
render_resource::SharedBuffers,
renderer::RenderContext, renderer::RenderContext,
}; };
use legion::prelude::*; use legion::prelude::*;
@ -12,13 +11,14 @@ impl Node for SharedBuffersNode {
fn update( fn update(
&mut self, &mut self,
_world: &World, _world: &World,
resources: &Resources, _resources: &Resources,
render_context: &mut dyn RenderContext, _render_context: &mut dyn RenderContext,
_input: &ResourceSlots, _input: &ResourceSlots,
_output: &mut ResourceSlots, _output: &mut ResourceSlots,
) { ) {
let shared_buffers = resources.get::<SharedBuffers>().unwrap(); // TODO: enable me
let mut command_queue = shared_buffers.reset_command_queue(); // let shared_buffers = resources.get::<SharedBuffers>().unwrap();
// let mut command_queue = shared_buffers.reset_command_queue();
// command_queue.execute(render_context); // command_queue.execute(render_context);
} }
} }

View File

@ -1,5 +1,5 @@
use super::{BindGroup, BindGroupId, BufferId, RenderResourceId, SamplerId, TextureId}; use super::{BindGroup, BindGroupId, BufferId, RenderResourceId, SamplerId, TextureId};
use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId}; use crate::{renderer::RenderResourceContext, pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineDescriptor}};
use bevy_asset::{Handle, HandleUntyped}; use bevy_asset::{Handle, HandleUntyped};
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
@ -162,6 +162,32 @@ impl RenderResourceBindings {
} }
} }
pub fn update_bind_groups(&mut self, pipeline: &PipelineDescriptor, render_resource_context: &dyn RenderResourceContext) {
let layout = pipeline.get_layout().unwrap();
for bind_group_descriptor in layout.bind_groups.iter() {
match self.update_bind_group(bind_group_descriptor) {
BindGroupStatus::Changed(id) => {
let bind_group = self
.get_bind_group(id)
.expect("RenderResourceSet was just changed, so it should exist");
render_resource_context.create_bind_group(bind_group_descriptor.id, bind_group);
}
// TODO: Don't re-create bind groups if they havent changed. this will require cleanup of orphan bind groups and
// removal of global context.clear_bind_groups()
// PERF: see above
BindGroupStatus::Unchanged(id) => {
let bind_group = self
.get_bind_group(id)
.expect("RenderResourceSet was just changed, so it should exist");
render_resource_context.create_bind_group(bind_group_descriptor.id, bind_group);
}
BindGroupStatus::NoMatch => {
// ignore unchanged / unmatched render resource sets
}
}
}
}
pub fn get_bind_group(&self, id: BindGroupId) -> Option<&BindGroup> { pub fn get_bind_group(&self, id: BindGroupId) -> Option<&BindGroup> {
self.bind_groups.get(&id) self.bind_groups.get(&id)
} }

View File

@ -1,41 +1,11 @@
use crate::{ use crate::{
pipeline::{PipelineCompiler, PipelineDescriptor, RenderPipelines}, pipeline::{PipelineCompiler, PipelineDescriptor, RenderPipelines},
render_resource::{BindGroupStatus, RenderResourceBindings}, render_resource::RenderResourceBindings,
renderer::RenderResourceContext, renderer::RenderResourceContext,
}; };
use bevy_asset::Assets; use bevy_asset::Assets;
use legion::prelude::*; use legion::prelude::*;
fn update_bind_groups(
pipeline: &PipelineDescriptor,
render_resource_bindings: &mut RenderResourceBindings,
render_resource_context: &dyn RenderResourceContext,
) {
let layout = pipeline.get_layout().unwrap();
for bind_group_descriptor in layout.bind_groups.iter() {
match render_resource_bindings.update_bind_group(bind_group_descriptor) {
BindGroupStatus::Changed(id) => {
let bind_group = render_resource_bindings
.get_bind_group(id)
.expect("RenderResourceSet was just changed, so it should exist");
render_resource_context.create_bind_group(bind_group_descriptor.id, bind_group);
}
// TODO: Don't re-create bind groups if they havent changed. this will require cleanup of orphan bind groups and
// removal of global context.clear_bind_groups()
// PERF: see above
BindGroupStatus::Unchanged(id) => {
let bind_group = render_resource_bindings
.get_bind_group(id)
.expect("RenderResourceSet was just changed, so it should exist");
render_resource_context.create_bind_group(bind_group_descriptor.id, bind_group);
}
BindGroupStatus::NoMatch => {
// ignore unchanged / unmatched render resource sets
}
}
}
}
pub fn bind_groups_system( pub fn bind_groups_system(
world: &mut SubWorld, world: &mut SubWorld,
pipelines: Res<Assets<PipelineDescriptor>>, pipelines: Res<Assets<PipelineDescriptor>>,
@ -47,11 +17,7 @@ pub fn bind_groups_system(
let render_resource_context = &**render_resource_context; let render_resource_context = &**render_resource_context;
for compiled_pipeline_handle in pipeline_compiler.iter_all_compiled_pipelines() { for compiled_pipeline_handle in pipeline_compiler.iter_all_compiled_pipelines() {
let pipeline = pipelines.get(compiled_pipeline_handle).unwrap(); let pipeline = pipelines.get(compiled_pipeline_handle).unwrap();
update_bind_groups( render_resource_bindings.update_bind_groups(pipeline, render_resource_context);
pipeline,
&mut render_resource_bindings,
render_resource_context,
)
} }
for mut render_pipelines in query.iter_mut(world) { for mut render_pipelines in query.iter_mut(world) {
let render_pipelines = render_pipelines.as_mut(); let render_pipelines = render_pipelines.as_mut();
@ -59,11 +25,7 @@ pub fn bind_groups_system(
let pipeline = pipelines let pipeline = pipelines
.get(&render_pipeline.specialized_pipeline.unwrap()) .get(&render_pipeline.specialized_pipeline.unwrap())
.unwrap(); .unwrap();
update_bind_groups( render_pipelines.bindings.update_bind_groups(pipeline, render_resource_context);
pipeline,
&mut render_pipelines.bindings,
render_resource_context,
)
} }
} }
} }

View File

@ -1,11 +1,13 @@
use crate::{Font, FontAtlasSet}; use crate::{Font, FontAtlasSet};
use bevy_asset::{Assets, Handle}; use bevy_asset::Assets;
use bevy_render::{ use bevy_render::{
draw::{DrawError, Drawable}, draw::{DrawContext, DrawError, Drawable},
mesh,
render_resource::{BindGroup, BufferUsage, RenderResourceId},
Color, Color,
}; };
use bevy_sprite::TextureAtlas; use bevy_sprite::{TextureAtlas, TextureAtlasSprite};
use glam::Vec2; use glam::{Vec2, Vec3};
pub struct TextStyle { pub struct TextStyle {
pub font_size: f32, pub font_size: f32,
@ -14,9 +16,8 @@ pub struct TextStyle {
#[allow(dead_code)] #[allow(dead_code)]
pub struct DrawableText<'a> { pub struct DrawableText<'a> {
font_handle: Handle<Font>, font: &'a Font,
fonts: &'a Assets<Font>, font_atlas_set: &'a FontAtlasSet,
font_atlas_sets: &'a Assets<FontAtlasSet>,
texture_atlases: &'a Assets<TextureAtlas>, texture_atlases: &'a Assets<TextureAtlas>,
position: Vec2, position: Vec2,
style: &'a TextStyle, style: &'a TextStyle,
@ -25,18 +26,16 @@ pub struct DrawableText<'a> {
impl<'a> DrawableText<'a> { impl<'a> DrawableText<'a> {
pub fn new( pub fn new(
font_handle: Handle<Font>, font: &'a Font,
fonts: &'a Assets<Font>, font_atlas_set: &'a FontAtlasSet,
font_atlas_sets: &'a Assets<FontAtlasSet>,
texture_atlases: &'a Assets<TextureAtlas>, texture_atlases: &'a Assets<TextureAtlas>,
position: Vec2, position: Vec2,
style: &'a TextStyle, style: &'a TextStyle,
text: &'a str, text: &'a str,
) -> Self { ) -> Self {
Self { Self {
font_handle, font,
fonts, font_atlas_set,
font_atlas_sets,
texture_atlases, texture_atlases,
position, position,
style, style,
@ -46,25 +45,58 @@ impl<'a> DrawableText<'a> {
} }
impl<'a> Drawable for DrawableText<'a> { impl<'a> Drawable for DrawableText<'a> {
fn draw(&mut self, _draw: &mut bevy_render::draw::DrawContext) -> Result<(), DrawError> { fn draw(&mut self, draw: &mut DrawContext) -> Result<(), DrawError> {
// draw.set_pipeline(bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE)?; draw.set_pipeline(bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE)?;
// let render_resource_context = draw.render_resource_context; let render_resource_context = draw.render_resource_context;
// // TODO: add draw.set_mesh(slot) // TODO: add draw.set_mesh(slot)
// let quad_vertex_buffer = render_resource_context if let Some(RenderResourceId::Buffer(quad_vertex_buffer)) = render_resource_context
// .get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::VERTEX_BUFFER_ASSET_INDEX) .get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::VERTEX_BUFFER_ASSET_INDEX)
// .unwrap(); {
// let quad_index_buffer = render_resource_context draw.set_vertex_buffer(0, quad_vertex_buffer, 0);
// .get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::INDEX_BUFFER_ASSET_INDEX) }
// .unwrap(); let mut indices = 0..0;
// draw.set_vertex_buffer(0, quad_vertex_buffer, 0); if let Some(RenderResourceId::Buffer(quad_index_buffer)) = render_resource_context
// draw.set_index_buffer(quad_index_buffer, 0); .get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::INDEX_BUFFER_ASSET_INDEX)
// draw.set_global_bind_groups()?; {
draw.set_index_buffer(quad_index_buffer, 0);
if let Some(buffer_info) = draw
.render_resource_context
.get_buffer_info(quad_index_buffer)
{
indices = 0..(buffer_info.size / 2) as u32;
} else {
panic!("expected buffer type");
}
}
// // TODO: ideally the TexureAtlas bind group is automatically generated by AssetRenderResourcesNode and is retrievable // set global bindings
// // here using render_resource_context.get_asset_bind_group(texture_atlas) draw.set_bind_groups_from_bindings(&draw.render_resource_bindings)?;
// let mut atlas_set = RenderResourceSet::build()
// .add_assignment(0, draw.get_uniform_buffer(&10)?) // set local per-character bindings
// .finish(); for character in self.text.chars() {
if let Some(glyph_atlas_info) = self
.font_atlas_set
.get_glyph_atlas_info(self.style.font_size, character)
{
let atlas_render_resource_bindings = draw
.asset_render_resource_bindings
.get(glyph_atlas_info.texture_atlas)
.unwrap();
draw.set_bind_groups_from_bindings(&atlas_render_resource_bindings)?;
let sprite_buffer = TextureAtlasSprite {
index: glyph_atlas_info.char_index,
position: Vec3::new(300.0, 300.0, 0.0),
scale: 5.0,
};
let sprite_buffer = draw
.shared_buffers
.get_buffer(&sprite_buffer, BufferUsage::UNIFORM)
.unwrap();
let sprite_bind_group = BindGroup::build().add_binding(0, sprite_buffer).finish();
draw.set_bind_group(2, &sprite_bind_group);
draw.draw_indexed(indices.clone(), 0, 0..1);
}
}
Ok(()) Ok(())
} }
} }

View File

@ -2,7 +2,7 @@ use bevy_asset::{Assets, Handle};
use bevy_render::{ use bevy_render::{
draw::Draw, draw::Draw,
pipeline::PipelineDescriptor, pipeline::PipelineDescriptor,
render_resource::{RenderResourceBindings, SharedBuffers}, render_resource::{AssetRenderResourceBindings, RenderResourceBindings, SharedBuffers},
renderer::RenderResourceContext, renderer::RenderResourceContext,
texture::Texture, texture::Texture,
Color, Color,
@ -80,6 +80,7 @@ impl Label {
pub fn draw_label_system( pub fn draw_label_system(
_pipelines: Res<Assets<PipelineDescriptor>>, _pipelines: Res<Assets<PipelineDescriptor>>,
_render_resource_bindings: Res<RenderResourceBindings>, _render_resource_bindings: Res<RenderResourceBindings>,
_asset_render_resource_bindings: Res<AssetRenderResourceBindings>,
_render_resource_context: Res<Box<dyn RenderResourceContext>>, _render_resource_context: Res<Box<dyn RenderResourceContext>>,
_shared_buffers: Res<SharedBuffers>, _shared_buffers: Res<SharedBuffers>,
_fonts: Res<Assets<Font>>, _fonts: Res<Assets<Font>>,
@ -89,19 +90,18 @@ impl Label {
_label: Com<Label>, _label: Com<Label>,
_quad: Com<Quad>, _quad: Com<Quad>,
) { ) {
// let context = &*render_resources.context;
// let mut draw_context = draw.get_context( // let mut draw_context = draw.get_context(
// &pipelines, // &pipelines,
// context, // &**render_resource_context,
// &render_resource_bindings, // &render_resource_bindings,
// &asset_render_resource_bindings,
// &shared_buffers, // &shared_buffers,
// ); // );
// // TODO: getting a font mutably will send out font change events. the atlas should be split from the font to avoid this // TODO: getting a font mutably will send out font change events. the atlas should be split from the font to avoid this
// let mut drawable_text = DrawableText::new( // let mut drawable_text = DrawableText::new(
// label.font, // fonts.get(&label.font).unwrap(),
// &fonts, // font_atlas_sets.get(&label.font.as_handle::<FontAtlasSet>()).unwrap(),
// &font_atlas_sets,
// &texture_atlases, // &texture_atlases,
// quad.position, // quad.position,
// &label.style, // &label.style,

View File

@ -52,11 +52,11 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
fn set_bind_group( fn set_bind_group(
&mut self, &mut self,
index: u32, index: u32,
bind_group_descriptor: BindGroupDescriptorId, bind_group_descriptor_id: BindGroupDescriptorId,
bind_group: BindGroupId, bind_group: BindGroupId,
dynamic_uniform_indices: Option<&[u32]>, dynamic_uniform_indices: Option<&[u32]>,
) { ) {
if let Some(bind_group_info) = self.wgpu_resources.bind_groups.get(&bind_group_descriptor) { if let Some(bind_group_info) = self.wgpu_resources.bind_groups.get(&bind_group_descriptor_id) {
if let Some(wgpu_bind_group) = bind_group_info.bind_groups.get(&bind_group) { if let Some(wgpu_bind_group) = bind_group_info.bind_groups.get(&bind_group) {
const EMPTY: &'static [u32] = &[]; const EMPTY: &'static [u32] = &[];
let dynamic_uniform_indices = let dynamic_uniform_indices =
@ -68,7 +68,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
log::trace!( log::trace!(
"set bind group {:?} {:?}: {:?}", "set bind group {:?} {:?}: {:?}",
bind_group_descriptor, bind_group_descriptor_id,
dynamic_uniform_indices, dynamic_uniform_indices,
bind_group bind_group
); );

View File

@ -36,7 +36,7 @@ fn atlas_render_system(
if state.added { if state.added {
return; return;
} }
if let Some(set) = font_atlas_sets.get(&Handle::from_id(state.handle.id)) { if let Some(set) = font_atlas_sets.get(&state.handle.as_handle::<FontAtlasSet>()) {
for (_size, atlas) in set.iter() { for (_size, atlas) in set.iter() {
state.added = true; state.added = true;
let atlas = texture_atlases.get(&atlas.texture_atlas).unwrap(); let atlas = texture_atlases.get(&atlas.texture_atlas).unwrap();

View File

@ -8,7 +8,7 @@ fn main() {
.add_default_plugins() .add_default_plugins()
.add_plugin(FrameTimeDiagnosticsPlugin::default()) .add_plugin(FrameTimeDiagnosticsPlugin::default())
.add_startup_system(setup.system()) .add_startup_system(setup.system())
.add_system(text_update_system.system()) // .add_system(text_update_system.system())
.run(); .run();
} }