render: more progress on immediate mode rendering and DrawableText
This commit is contained in:
parent
f4acbdddad
commit
e57fdca1bc
@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineDescriptor},
|
||||
pipeline::{PipelineDescriptor, PipelineLayout},
|
||||
render_resource::{
|
||||
BindGroup, BindGroupId, BufferId, BufferUsage, RenderResource, RenderResourceBinding,
|
||||
RenderResourceBindings, SharedBuffers,
|
||||
AssetRenderResourceBindings, BindGroup, BindGroupId, BufferId, BufferUsage, RenderResource,
|
||||
RenderResourceBinding, RenderResourceBindings, SharedBuffers,
|
||||
},
|
||||
renderer::RenderResourceContext,
|
||||
};
|
||||
@ -31,7 +31,6 @@ pub enum RenderCommand {
|
||||
},
|
||||
SetBindGroup {
|
||||
index: u32,
|
||||
bind_group_descriptor: BindGroupDescriptorId,
|
||||
bind_group: BindGroupId,
|
||||
dynamic_uniform_indices: Option<Arc<Vec<u32>>>,
|
||||
},
|
||||
@ -64,6 +63,7 @@ impl Draw {
|
||||
pipelines: &'a Assets<PipelineDescriptor>,
|
||||
render_resource_context: &'a dyn RenderResourceContext,
|
||||
render_resource_bindings: &'a RenderResourceBindings,
|
||||
asset_render_resource_bindings: &'a AssetRenderResourceBindings,
|
||||
shared_buffers: &'a SharedBuffers,
|
||||
) -> DrawContext {
|
||||
DrawContext {
|
||||
@ -71,6 +71,7 @@ impl Draw {
|
||||
pipelines,
|
||||
render_resource_context,
|
||||
render_resource_bindings,
|
||||
asset_render_resource_bindings,
|
||||
shared_buffers,
|
||||
current_pipeline: None,
|
||||
}
|
||||
@ -89,6 +90,8 @@ pub enum DrawError {
|
||||
NoPipelineSet,
|
||||
#[error("Pipeline has no layout")]
|
||||
PipelineHasNoLayout,
|
||||
#[error("A BindGroup with the given index does not exist")]
|
||||
BindGroupDescriptorDoesNotExist { index: u32 },
|
||||
#[error("Failed to get a buffer for the given RenderResource.")]
|
||||
BufferAllocationFailure,
|
||||
}
|
||||
@ -98,6 +101,7 @@ pub struct DrawContext<'a> {
|
||||
pub pipelines: &'a Assets<PipelineDescriptor>,
|
||||
pub render_resource_context: &'a dyn RenderResourceContext,
|
||||
pub render_resource_bindings: &'a RenderResourceBindings,
|
||||
pub asset_render_resource_bindings: &'a AssetRenderResourceBindings,
|
||||
pub shared_buffers: &'a SharedBuffers,
|
||||
pub current_pipeline: Option<&'a PipelineDescriptor>,
|
||||
}
|
||||
@ -146,14 +150,9 @@ impl<'a> DrawContext<'a> {
|
||||
self.render_command(RenderCommand::SetIndexBuffer { buffer, offset });
|
||||
}
|
||||
|
||||
pub fn set_bind_group(
|
||||
&mut self,
|
||||
bind_group_descriptor: &BindGroupDescriptor,
|
||||
bind_group: &BindGroup,
|
||||
) {
|
||||
pub fn set_bind_group(&mut self, index: u32, bind_group: &BindGroup) {
|
||||
self.render_command(RenderCommand::SetBindGroup {
|
||||
index: bind_group_descriptor.index,
|
||||
bind_group_descriptor: bind_group_descriptor.id,
|
||||
index,
|
||||
bind_group: bind_group.id,
|
||||
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]
|
||||
pub fn render_command(&mut self, render_command: RenderCommand) {
|
||||
self.draw.render_commands.push(render_command);
|
||||
@ -185,6 +218,7 @@ pub fn draw_system<T: Drawable + Component>(
|
||||
pipelines: Res<Assets<PipelineDescriptor>>,
|
||||
render_resource_bindings: Res<RenderResourceBindings>,
|
||||
render_resource_context: Res<Box<dyn RenderResourceContext>>,
|
||||
asset_render_resource_bindings: Res<AssetRenderResourceBindings>,
|
||||
shared_buffers: Res<SharedBuffers>,
|
||||
mut draw: ComMut<Draw>,
|
||||
mut drawable: ComMut<T>,
|
||||
@ -193,6 +227,7 @@ pub fn draw_system<T: Drawable + Component>(
|
||||
&pipelines,
|
||||
&**render_resource_context,
|
||||
&render_resource_bindings,
|
||||
&asset_render_resource_bindings,
|
||||
&shared_buffers,
|
||||
);
|
||||
draw_context.draw(drawable.as_mut()).unwrap();
|
||||
|
@ -18,7 +18,7 @@ pub trait RenderPass {
|
||||
fn set_bind_group(
|
||||
&mut self,
|
||||
index: u32,
|
||||
bind_group_descriptor: BindGroupDescriptorId,
|
||||
bind_group_descriptor_id: BindGroupDescriptorId,
|
||||
bind_group: BindGroupId,
|
||||
dynamic_uniform_indices: Option<&[u32]>,
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::{
|
||||
state_descriptors::PrimitiveTopology, PipelineDescriptor, RenderPipeline, RenderPipelines,
|
||||
state_descriptors::PrimitiveTopology, PipelineDescriptor, RenderPipelines,
|
||||
VertexBufferDescriptors,
|
||||
};
|
||||
use crate::{
|
||||
@ -8,9 +8,8 @@ use crate::{
|
||||
shader::{Shader, ShaderSource},
|
||||
};
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use legion::prelude::*;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Default)]
|
||||
pub struct PipelineSpecialization {
|
||||
@ -78,20 +77,22 @@ impl PipelineCompiler {
|
||||
|
||||
fn compile_pipeline(
|
||||
&mut self,
|
||||
vertex_buffer_descriptors: &VertexBufferDescriptors,
|
||||
render_resource_context: &dyn RenderResourceContext,
|
||||
pipelines: &mut Assets<PipelineDescriptor>,
|
||||
shaders: &mut Assets<Shader>,
|
||||
pipeline_descriptor: &PipelineDescriptor,
|
||||
render_pipeline: &RenderPipeline,
|
||||
source_pipeline: Handle<PipelineDescriptor>,
|
||||
vertex_buffer_descriptors: &VertexBufferDescriptors,
|
||||
pipeline_specialization: &PipelineSpecialization,
|
||||
render_resource_bindings: &RenderResourceBindings,
|
||||
) -> PipelineDescriptor {
|
||||
let mut compiled_pipeline_descriptor = pipeline_descriptor.clone();
|
||||
|
||||
compiled_pipeline_descriptor.shader_stages.vertex = self.compile_shader(
|
||||
) -> Handle<PipelineDescriptor> {
|
||||
let source_descriptor = pipelines.get(&source_pipeline).unwrap();
|
||||
let mut compiled_descriptor = source_descriptor.clone();
|
||||
compiled_descriptor.shader_stages.vertex = self.compile_shader(
|
||||
shaders,
|
||||
&pipeline_descriptor.shader_stages.vertex,
|
||||
&render_pipeline.specialization.shader_specialization,
|
||||
&compiled_descriptor.shader_stages.vertex,
|
||||
&pipeline_specialization.shader_specialization,
|
||||
);
|
||||
compiled_pipeline_descriptor.shader_stages.fragment = pipeline_descriptor
|
||||
compiled_descriptor.shader_stages.fragment = compiled_descriptor
|
||||
.shader_stages
|
||||
.fragment
|
||||
.as_ref()
|
||||
@ -99,23 +100,42 @@ impl PipelineCompiler {
|
||||
self.compile_shader(
|
||||
shaders,
|
||||
fragment,
|
||||
&render_pipeline.specialization.shader_specialization,
|
||||
&pipeline_specialization.shader_specialization,
|
||||
)
|
||||
});
|
||||
|
||||
compiled_pipeline_descriptor.reflect_layout(
|
||||
compiled_descriptor.reflect_layout(
|
||||
shaders,
|
||||
true,
|
||||
Some(vertex_buffer_descriptors),
|
||||
Some(render_resource_bindings),
|
||||
);
|
||||
|
||||
compiled_pipeline_descriptor.primitive_topology =
|
||||
render_pipeline.specialization.primitive_topology;
|
||||
compiled_pipeline_descriptor
|
||||
compiled_descriptor.primitive_topology = pipeline_specialization.primitive_topology;
|
||||
let compiled_pipeline_handle =
|
||||
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,
|
||||
vertex_buffer_descriptors: &VertexBufferDescriptors,
|
||||
pipelines: &mut Assets<PipelineDescriptor>,
|
||||
@ -125,44 +145,27 @@ impl PipelineCompiler {
|
||||
) {
|
||||
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
||||
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)) =
|
||||
self.specialized_pipelines
|
||||
.get_mut(&source_pipeline)
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|(pipeline_specialization, _compiled_pipeline_handle)| {
|
||||
*pipeline_specialization == render_pipeline.specialization
|
||||
.and_then(|specialized_pipelines| {
|
||||
specialized_pipelines.iter().find(
|
||||
|(pipeline_specialization, _compiled_pipeline_handle)| {
|
||||
*pipeline_specialization == render_pipeline.specialization
|
||||
},
|
||||
)
|
||||
}) {
|
||||
*compiled_pipeline_handle
|
||||
} else {
|
||||
let pipeline_descriptor = pipelines.get(&source_pipeline).unwrap();
|
||||
let compiled_pipeline_descriptor = self.compile_pipeline(
|
||||
vertex_buffer_descriptors,
|
||||
self.compile_pipeline(
|
||||
render_resource_context,
|
||||
pipelines,
|
||||
shaders,
|
||||
pipeline_descriptor,
|
||||
render_pipeline,
|
||||
source_pipeline,
|
||||
vertex_buffer_descriptors,
|
||||
&render_pipeline.specialization,
|
||||
&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);
|
||||
@ -198,15 +201,44 @@ pub fn compile_pipelines_system(
|
||||
mut pipeline_compiler: ResMut<PipelineCompiler>,
|
||||
mut shaders: ResMut<Assets<Shader>>,
|
||||
mut pipelines: ResMut<Assets<PipelineDescriptor>>,
|
||||
// pipeline_asset_events: Res<Events<AssetEvent<PipelineDescriptor>>>,
|
||||
vertex_buffer_descriptors: Res<VertexBufferDescriptors>,
|
||||
render_resource_context: Res<Box<dyn RenderResourceContext>>,
|
||||
query: &mut Query<Write<RenderPipelines>>,
|
||||
) {
|
||||
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
|
||||
for mut render_pipelines in query.iter_mut(world) {
|
||||
pipeline_compiler.compile_pipelines(
|
||||
pipeline_compiler.compile_render_pipelines(
|
||||
&vertex_buffer_descriptors,
|
||||
&mut pipelines,
|
||||
&mut shaders,
|
||||
|
@ -9,6 +9,12 @@ pub struct 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 {
|
||||
let mut bind_groups = HashMap::<u32, BindGroupDescriptor>::new();
|
||||
let mut vertex_buffer_descriptors = Vec::new();
|
||||
|
@ -69,12 +69,12 @@ impl Drawable for RenderPipelines {
|
||||
.bindings
|
||||
.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
|
||||
.render_resource_bindings
|
||||
.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;
|
||||
|
@ -80,6 +80,10 @@ impl CommandQueue {
|
||||
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) {
|
||||
for command in self.queue.lock().unwrap().drain(..) {
|
||||
match command {
|
||||
|
@ -131,13 +131,15 @@ impl Node for MainPassNode {
|
||||
}
|
||||
RenderCommand::SetBindGroup {
|
||||
index,
|
||||
bind_group_descriptor,
|
||||
bind_group,
|
||||
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(
|
||||
*index,
|
||||
*bind_group_descriptor,
|
||||
bind_group_descriptor.id,
|
||||
*bind_group,
|
||||
dynamic_uniform_indices
|
||||
.as_ref()
|
@ -1,13 +1,15 @@
|
||||
mod camera_node;
|
||||
mod pass_node;
|
||||
mod main_pass_node;
|
||||
mod render_resources_node;
|
||||
mod shared_buffers_node;
|
||||
mod texture_copy_node;
|
||||
mod window_swapchain_node;
|
||||
mod window_texture_node;
|
||||
|
||||
pub use camera_node::*;
|
||||
pub use pass_node::*;
|
||||
pub use main_pass_node::*;
|
||||
pub use render_resources_node::*;
|
||||
pub use shared_buffers_node::*;
|
||||
pub use texture_copy_node::*;
|
||||
pub use window_swapchain_node::*;
|
||||
pub use window_texture_node::*;
|
@ -1,6 +1,5 @@
|
||||
use crate::{
|
||||
render_graph::{Node, ResourceSlots},
|
||||
render_resource::SharedBuffers,
|
||||
renderer::RenderContext,
|
||||
};
|
||||
use legion::prelude::*;
|
||||
@ -12,13 +11,14 @@ impl Node for SharedBuffersNode {
|
||||
fn update(
|
||||
&mut self,
|
||||
_world: &World,
|
||||
resources: &Resources,
|
||||
render_context: &mut dyn RenderContext,
|
||||
_resources: &Resources,
|
||||
_render_context: &mut dyn RenderContext,
|
||||
_input: &ResourceSlots,
|
||||
_output: &mut ResourceSlots,
|
||||
) {
|
||||
let shared_buffers = resources.get::<SharedBuffers>().unwrap();
|
||||
let mut command_queue = shared_buffers.reset_command_queue();
|
||||
// TODO: enable me
|
||||
// let shared_buffers = resources.get::<SharedBuffers>().unwrap();
|
||||
// let mut command_queue = shared_buffers.reset_command_queue();
|
||||
// command_queue.execute(render_context);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 std::{
|
||||
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> {
|
||||
self.bind_groups.get(&id)
|
||||
}
|
||||
|
@ -1,41 +1,11 @@
|
||||
use crate::{
|
||||
pipeline::{PipelineCompiler, PipelineDescriptor, RenderPipelines},
|
||||
render_resource::{BindGroupStatus, RenderResourceBindings},
|
||||
render_resource::RenderResourceBindings,
|
||||
renderer::RenderResourceContext,
|
||||
};
|
||||
use bevy_asset::Assets;
|
||||
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(
|
||||
world: &mut SubWorld,
|
||||
pipelines: Res<Assets<PipelineDescriptor>>,
|
||||
@ -47,11 +17,7 @@ pub fn bind_groups_system(
|
||||
let render_resource_context = &**render_resource_context;
|
||||
for compiled_pipeline_handle in pipeline_compiler.iter_all_compiled_pipelines() {
|
||||
let pipeline = pipelines.get(compiled_pipeline_handle).unwrap();
|
||||
update_bind_groups(
|
||||
pipeline,
|
||||
&mut render_resource_bindings,
|
||||
render_resource_context,
|
||||
)
|
||||
render_resource_bindings.update_bind_groups(pipeline, render_resource_context);
|
||||
}
|
||||
for mut render_pipelines in query.iter_mut(world) {
|
||||
let render_pipelines = render_pipelines.as_mut();
|
||||
@ -59,11 +25,7 @@ pub fn bind_groups_system(
|
||||
let pipeline = pipelines
|
||||
.get(&render_pipeline.specialized_pipeline.unwrap())
|
||||
.unwrap();
|
||||
update_bind_groups(
|
||||
pipeline,
|
||||
&mut render_pipelines.bindings,
|
||||
render_resource_context,
|
||||
)
|
||||
render_pipelines.bindings.update_bind_groups(pipeline, render_resource_context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
use crate::{Font, FontAtlasSet};
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use bevy_asset::Assets;
|
||||
use bevy_render::{
|
||||
draw::{DrawError, Drawable},
|
||||
draw::{DrawContext, DrawError, Drawable},
|
||||
mesh,
|
||||
render_resource::{BindGroup, BufferUsage, RenderResourceId},
|
||||
Color,
|
||||
};
|
||||
use bevy_sprite::TextureAtlas;
|
||||
use glam::Vec2;
|
||||
use bevy_sprite::{TextureAtlas, TextureAtlasSprite};
|
||||
use glam::{Vec2, Vec3};
|
||||
|
||||
pub struct TextStyle {
|
||||
pub font_size: f32,
|
||||
@ -14,9 +16,8 @@ pub struct TextStyle {
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct DrawableText<'a> {
|
||||
font_handle: Handle<Font>,
|
||||
fonts: &'a Assets<Font>,
|
||||
font_atlas_sets: &'a Assets<FontAtlasSet>,
|
||||
font: &'a Font,
|
||||
font_atlas_set: &'a FontAtlasSet,
|
||||
texture_atlases: &'a Assets<TextureAtlas>,
|
||||
position: Vec2,
|
||||
style: &'a TextStyle,
|
||||
@ -25,18 +26,16 @@ pub struct DrawableText<'a> {
|
||||
|
||||
impl<'a> DrawableText<'a> {
|
||||
pub fn new(
|
||||
font_handle: Handle<Font>,
|
||||
fonts: &'a Assets<Font>,
|
||||
font_atlas_sets: &'a Assets<FontAtlasSet>,
|
||||
font: &'a Font,
|
||||
font_atlas_set: &'a FontAtlasSet,
|
||||
texture_atlases: &'a Assets<TextureAtlas>,
|
||||
position: Vec2,
|
||||
style: &'a TextStyle,
|
||||
text: &'a str,
|
||||
) -> Self {
|
||||
Self {
|
||||
font_handle,
|
||||
fonts,
|
||||
font_atlas_sets,
|
||||
font,
|
||||
font_atlas_set,
|
||||
texture_atlases,
|
||||
position,
|
||||
style,
|
||||
@ -46,25 +45,58 @@ impl<'a> DrawableText<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Drawable for DrawableText<'a> {
|
||||
fn draw(&mut self, _draw: &mut bevy_render::draw::DrawContext) -> Result<(), DrawError> {
|
||||
// draw.set_pipeline(bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE)?;
|
||||
// let render_resource_context = draw.render_resource_context;
|
||||
// // TODO: add draw.set_mesh(slot)
|
||||
// let quad_vertex_buffer = render_resource_context
|
||||
// .get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::VERTEX_BUFFER_ASSET_INDEX)
|
||||
// .unwrap();
|
||||
// let quad_index_buffer = render_resource_context
|
||||
// .get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::INDEX_BUFFER_ASSET_INDEX)
|
||||
// .unwrap();
|
||||
// draw.set_vertex_buffer(0, quad_vertex_buffer, 0);
|
||||
// draw.set_index_buffer(quad_index_buffer, 0);
|
||||
// draw.set_global_bind_groups()?;
|
||||
fn draw(&mut self, draw: &mut DrawContext) -> Result<(), DrawError> {
|
||||
draw.set_pipeline(bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE)?;
|
||||
let render_resource_context = draw.render_resource_context;
|
||||
// TODO: add draw.set_mesh(slot)
|
||||
if let Some(RenderResourceId::Buffer(quad_vertex_buffer)) = render_resource_context
|
||||
.get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::VERTEX_BUFFER_ASSET_INDEX)
|
||||
{
|
||||
draw.set_vertex_buffer(0, quad_vertex_buffer, 0);
|
||||
}
|
||||
let mut indices = 0..0;
|
||||
if let Some(RenderResourceId::Buffer(quad_index_buffer)) = render_resource_context
|
||||
.get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::INDEX_BUFFER_ASSET_INDEX)
|
||||
{
|
||||
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
|
||||
// // here using render_resource_context.get_asset_bind_group(texture_atlas)
|
||||
// let mut atlas_set = RenderResourceSet::build()
|
||||
// .add_assignment(0, draw.get_uniform_buffer(&10)?)
|
||||
// .finish();
|
||||
// set global bindings
|
||||
draw.set_bind_groups_from_bindings(&draw.render_resource_bindings)?;
|
||||
|
||||
// set local per-character bindings
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use bevy_asset::{Assets, Handle};
|
||||
use bevy_render::{
|
||||
draw::Draw,
|
||||
pipeline::PipelineDescriptor,
|
||||
render_resource::{RenderResourceBindings, SharedBuffers},
|
||||
render_resource::{AssetRenderResourceBindings, RenderResourceBindings, SharedBuffers},
|
||||
renderer::RenderResourceContext,
|
||||
texture::Texture,
|
||||
Color,
|
||||
@ -80,6 +80,7 @@ impl Label {
|
||||
pub fn draw_label_system(
|
||||
_pipelines: Res<Assets<PipelineDescriptor>>,
|
||||
_render_resource_bindings: Res<RenderResourceBindings>,
|
||||
_asset_render_resource_bindings: Res<AssetRenderResourceBindings>,
|
||||
_render_resource_context: Res<Box<dyn RenderResourceContext>>,
|
||||
_shared_buffers: Res<SharedBuffers>,
|
||||
_fonts: Res<Assets<Font>>,
|
||||
@ -89,19 +90,18 @@ impl Label {
|
||||
_label: Com<Label>,
|
||||
_quad: Com<Quad>,
|
||||
) {
|
||||
// let context = &*render_resources.context;
|
||||
// let mut draw_context = draw.get_context(
|
||||
// &pipelines,
|
||||
// context,
|
||||
// &**render_resource_context,
|
||||
// &render_resource_bindings,
|
||||
// &asset_render_resource_bindings,
|
||||
// &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(
|
||||
// label.font,
|
||||
// &fonts,
|
||||
// &font_atlas_sets,
|
||||
// fonts.get(&label.font).unwrap(),
|
||||
// font_atlas_sets.get(&label.font.as_handle::<FontAtlasSet>()).unwrap(),
|
||||
// &texture_atlases,
|
||||
// quad.position,
|
||||
// &label.style,
|
||||
|
@ -52,11 +52,11 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
|
||||
fn set_bind_group(
|
||||
&mut self,
|
||||
index: u32,
|
||||
bind_group_descriptor: BindGroupDescriptorId,
|
||||
bind_group_descriptor_id: BindGroupDescriptorId,
|
||||
bind_group: BindGroupId,
|
||||
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) {
|
||||
const EMPTY: &'static [u32] = &[];
|
||||
let dynamic_uniform_indices =
|
||||
@ -68,7 +68,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
|
||||
|
||||
log::trace!(
|
||||
"set bind group {:?} {:?}: {:?}",
|
||||
bind_group_descriptor,
|
||||
bind_group_descriptor_id,
|
||||
dynamic_uniform_indices,
|
||||
bind_group
|
||||
);
|
||||
|
@ -36,7 +36,7 @@ fn atlas_render_system(
|
||||
if state.added {
|
||||
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() {
|
||||
state.added = true;
|
||||
let atlas = texture_atlases.get(&atlas.texture_atlas).unwrap();
|
||||
|
@ -8,7 +8,7 @@ fn main() {
|
||||
.add_default_plugins()
|
||||
.add_plugin(FrameTimeDiagnosticsPlugin::default())
|
||||
.add_startup_system(setup.system())
|
||||
.add_system(text_update_system.system())
|
||||
// .add_system(text_update_system.system())
|
||||
.run();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user