mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 14:10:19 +00:00
render: move pipeline compilation and bind group creation into draw stage. impl ResourceSet for DrawContext. progress on text drawing. general cleanup
This commit is contained in:
parent
085cda8bc6
commit
4246d47fec
11 changed files with 334 additions and 363 deletions
|
@ -33,7 +33,7 @@ impl<'a, T: 'a> Clone for Res<'a, T> {
|
||||||
|
|
||||||
impl<'a, T: 'a> Res<'a, T> {
|
impl<'a, T: 'a> Res<'a, T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn new(resource: *const T) -> Self {
|
pub fn new(resource: *const T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: resource,
|
value: resource,
|
||||||
_marker: PhantomData::default(),
|
_marker: PhantomData::default(),
|
||||||
|
@ -120,7 +120,7 @@ impl<'a, T: 'a> Clone for ResMut<'a, T> {
|
||||||
|
|
||||||
impl<'a, T: 'a> ResMut<'a, T> {
|
impl<'a, T: 'a> ResMut<'a, T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn new(resource: *mut T) -> Self {
|
pub fn new(resource: *mut T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: resource,
|
value: resource,
|
||||||
_marker: PhantomData::default(),
|
_marker: PhantomData::default(),
|
||||||
|
|
|
@ -1,18 +1,25 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
pipeline::{PipelineDescriptor, PipelineLayout},
|
pipeline::{
|
||||||
|
PipelineCompiler, PipelineDescriptor, PipelineLayout, PipelineSpecialization,
|
||||||
|
VertexBufferDescriptors,
|
||||||
|
},
|
||||||
render_resource::{
|
render_resource::{
|
||||||
AssetRenderResourceBindings, BindGroup, BindGroupId, BufferId, BufferUsage, RenderResource,
|
AssetRenderResourceBindings, BindGroup, BindGroupId, BufferId, BufferUsage, RenderResource,
|
||||||
RenderResourceBinding, RenderResourceBindings, SharedBuffers,
|
RenderResourceBinding, RenderResourceBindings, SharedBuffers,
|
||||||
},
|
},
|
||||||
renderer::RenderResourceContext,
|
renderer::RenderResourceContext,
|
||||||
|
shader::Shader,
|
||||||
};
|
};
|
||||||
use bevy_asset::{Assets, Handle};
|
use bevy_asset::{Assets, Handle};
|
||||||
use bevy_property::Properties;
|
use bevy_property::Properties;
|
||||||
use legion::{
|
use legion::{
|
||||||
prelude::{ComMut, Res},
|
prelude::{ComMut, Res, ResourceSet},
|
||||||
storage::Component,
|
systems::{resource::ResourceTypeId, ResMut},
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
ops::{Deref, DerefMut, Range},
|
||||||
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use std::{ops::Range, sync::Arc};
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
@ -58,84 +65,12 @@ impl Default for Draw {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Draw {
|
impl Draw {
|
||||||
pub fn get_context<'a>(
|
|
||||||
&'a mut self,
|
|
||||||
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 {
|
|
||||||
draw: self,
|
|
||||||
pipelines,
|
|
||||||
render_resource_context,
|
|
||||||
render_resource_bindings,
|
|
||||||
asset_render_resource_bindings,
|
|
||||||
shared_buffers,
|
|
||||||
current_pipeline: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear_render_commands(&mut self) {
|
pub fn clear_render_commands(&mut self) {
|
||||||
self.render_commands.clear();
|
self.render_commands.clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
pub fn set_pipeline(&mut self, pipeline: Handle<PipelineDescriptor>) {
|
||||||
pub enum DrawError {
|
self.render_command(RenderCommand::SetPipeline { pipeline });
|
||||||
#[error("Pipeline does not exist.")]
|
|
||||||
NonExistentPipeline,
|
|
||||||
#[error("No pipeline set")]
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DrawContext<'a> {
|
|
||||||
pub draw: &'a mut Draw,
|
|
||||||
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>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> DrawContext<'a> {
|
|
||||||
pub fn get_uniform_buffer<T: RenderResource>(
|
|
||||||
&self,
|
|
||||||
render_resource: &T,
|
|
||||||
) -> Result<RenderResourceBinding, DrawError> {
|
|
||||||
self.get_buffer(render_resource, BufferUsage::UNIFORM)
|
|
||||||
}
|
|
||||||
pub fn get_buffer<T: RenderResource>(
|
|
||||||
&self,
|
|
||||||
render_resource: &T,
|
|
||||||
buffer_usage: BufferUsage,
|
|
||||||
) -> Result<RenderResourceBinding, DrawError> {
|
|
||||||
self.shared_buffers
|
|
||||||
.get_buffer(render_resource, buffer_usage)
|
|
||||||
.ok_or_else(|| DrawError::BufferAllocationFailure)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_pipeline(
|
|
||||||
&mut self,
|
|
||||||
pipeline_handle: Handle<PipelineDescriptor>,
|
|
||||||
) -> Result<(), DrawError> {
|
|
||||||
let pipeline = self
|
|
||||||
.pipelines
|
|
||||||
.get(&pipeline_handle)
|
|
||||||
.ok_or_else(|| DrawError::NonExistentPipeline)?;
|
|
||||||
self.current_pipeline = Some(pipeline);
|
|
||||||
self.render_command(RenderCommand::SetPipeline {
|
|
||||||
pipeline: pipeline_handle,
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_vertex_buffer(&mut self, slot: u32, buffer: BufferId, offset: u64) {
|
pub fn set_vertex_buffer(&mut self, slot: u32, buffer: BufferId, offset: u64) {
|
||||||
|
@ -166,8 +101,139 @@ impl<'a> DrawContext<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn render_command(&mut self, render_command: RenderCommand) {
|
||||||
|
self.render_commands.push(render_command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum DrawError {
|
||||||
|
#[error("Pipeline does not exist.")]
|
||||||
|
NonExistentPipeline,
|
||||||
|
#[error("No pipeline set")]
|
||||||
|
NoPipelineSet,
|
||||||
|
#[error("Pipeline has no layout")]
|
||||||
|
PipelineHasNoLayout,
|
||||||
|
#[error("Failed to get a buffer for the given RenderResource.")]
|
||||||
|
BufferAllocationFailure,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct DrawContext<'a> {
|
||||||
|
pub pipelines: ResMut<'a, Assets<PipelineDescriptor>>,
|
||||||
|
pub shaders: ResMut<'a, Assets<Shader>>,
|
||||||
|
pub pipeline_compiler: ResMut<'a, PipelineCompiler>,
|
||||||
|
pub render_resource_context: Res<'a, Box<dyn RenderResourceContext>>,
|
||||||
|
pub vertex_buffer_descriptors: Res<'a, VertexBufferDescriptors>,
|
||||||
|
pub asset_render_resource_bindings: Res<'a, AssetRenderResourceBindings>,
|
||||||
|
pub shared_buffers: Res<'a, SharedBuffers>,
|
||||||
|
pub current_pipeline: Option<Handle<PipelineDescriptor>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ResourceSet for DrawContext<'a> {
|
||||||
|
type PreparedResources = DrawContext<'a>;
|
||||||
|
unsafe fn fetch_unchecked(resources: &legion::prelude::Resources) -> Self::PreparedResources {
|
||||||
|
DrawContext {
|
||||||
|
render_resource_context: Res::new(
|
||||||
|
resources
|
||||||
|
.get::<Box<dyn RenderResourceContext>>()
|
||||||
|
.unwrap()
|
||||||
|
.deref() as *const Box<dyn RenderResourceContext>,
|
||||||
|
),
|
||||||
|
vertex_buffer_descriptors: Res::new(
|
||||||
|
resources.get::<VertexBufferDescriptors>().unwrap().deref()
|
||||||
|
as *const VertexBufferDescriptors,
|
||||||
|
),
|
||||||
|
asset_render_resource_bindings: Res::new(
|
||||||
|
resources
|
||||||
|
.get::<AssetRenderResourceBindings>()
|
||||||
|
.unwrap()
|
||||||
|
.deref() as *const AssetRenderResourceBindings,
|
||||||
|
),
|
||||||
|
shared_buffers: Res::new(
|
||||||
|
resources.get::<SharedBuffers>().unwrap().deref() as *const SharedBuffers
|
||||||
|
),
|
||||||
|
pipelines: ResMut::new(
|
||||||
|
resources
|
||||||
|
.get_mut::<Assets<PipelineDescriptor>>()
|
||||||
|
.unwrap()
|
||||||
|
.deref_mut() as *mut Assets<PipelineDescriptor>,
|
||||||
|
),
|
||||||
|
shaders: ResMut::new(
|
||||||
|
resources.get_mut::<Assets<Shader>>().unwrap().deref_mut() as *mut Assets<Shader>
|
||||||
|
),
|
||||||
|
pipeline_compiler: ResMut::new(
|
||||||
|
resources.get_mut::<PipelineCompiler>().unwrap().deref_mut()
|
||||||
|
as *mut PipelineCompiler,
|
||||||
|
),
|
||||||
|
current_pipeline: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn read_types() -> Vec<legion::systems::resource::ResourceTypeId> {
|
||||||
|
vec![
|
||||||
|
ResourceTypeId::of::<Box<dyn RenderResourceContext>>(),
|
||||||
|
ResourceTypeId::of::<VertexBufferDescriptors>(),
|
||||||
|
ResourceTypeId::of::<AssetRenderResourceBindings>(),
|
||||||
|
ResourceTypeId::of::<SharedBuffers>(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
fn write_types() -> Vec<legion::systems::resource::ResourceTypeId> {
|
||||||
|
vec![
|
||||||
|
ResourceTypeId::of::<Assets<PipelineDescriptor>>(),
|
||||||
|
ResourceTypeId::of::<Assets<Shader>>(),
|
||||||
|
ResourceTypeId::of::<PipelineCompiler>(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DrawContext<'a> {
|
||||||
|
pub fn get_uniform_buffer<T: RenderResource>(
|
||||||
|
&self,
|
||||||
|
render_resource: &T,
|
||||||
|
) -> Result<RenderResourceBinding, DrawError> {
|
||||||
|
self.get_buffer(render_resource, BufferUsage::UNIFORM)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_buffer<T: RenderResource>(
|
||||||
|
&self,
|
||||||
|
render_resource: &T,
|
||||||
|
buffer_usage: BufferUsage,
|
||||||
|
) -> Result<RenderResourceBinding, DrawError> {
|
||||||
|
self.shared_buffers
|
||||||
|
.get_buffer(render_resource, buffer_usage)
|
||||||
|
.ok_or_else(|| DrawError::BufferAllocationFailure)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_pipeline(
|
||||||
|
&mut self,
|
||||||
|
draw: &mut Draw,
|
||||||
|
pipeline_handle: Handle<PipelineDescriptor>,
|
||||||
|
specialization: &PipelineSpecialization,
|
||||||
|
) -> Result<(), DrawError> {
|
||||||
|
let specialized_pipeline = if let Some(specialized_pipeline) = self
|
||||||
|
.pipeline_compiler
|
||||||
|
.get_specialized_pipeline(pipeline_handle, specialization)
|
||||||
|
{
|
||||||
|
specialized_pipeline
|
||||||
|
} else {
|
||||||
|
self.pipeline_compiler.compile_pipeline(
|
||||||
|
&**self.render_resource_context,
|
||||||
|
&mut self.pipelines,
|
||||||
|
&mut self.shaders,
|
||||||
|
pipeline_handle,
|
||||||
|
&self.vertex_buffer_descriptors,
|
||||||
|
specialization,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
draw.set_pipeline(specialized_pipeline);
|
||||||
|
self.current_pipeline = Some(specialized_pipeline);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_pipeline_descriptor(&self) -> Result<&PipelineDescriptor, DrawError> {
|
pub fn get_pipeline_descriptor(&self) -> Result<&PipelineDescriptor, DrawError> {
|
||||||
self.current_pipeline
|
self.current_pipeline
|
||||||
|
.and_then(|handle| self.pipelines.get(&handle))
|
||||||
.ok_or_else(|| DrawError::NoPipelineSet)
|
.ok_or_else(|| DrawError::NoPipelineSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,57 +246,82 @@ impl<'a> DrawContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_bind_groups_from_bindings(
|
pub fn set_bind_groups_from_bindings(
|
||||||
&mut self,
|
&self,
|
||||||
render_resource_bindings: &RenderResourceBindings,
|
draw: &mut Draw,
|
||||||
|
render_resource_bindings: &mut [&mut RenderResourceBindings],
|
||||||
) -> Result<(), DrawError> {
|
) -> Result<(), DrawError> {
|
||||||
let pipeline = self
|
let pipeline = self
|
||||||
.current_pipeline
|
.current_pipeline
|
||||||
.ok_or_else(|| DrawError::NoPipelineSet)?;
|
.ok_or_else(|| DrawError::NoPipelineSet)?;
|
||||||
let layout = pipeline
|
let pipeline_descriptor = self
|
||||||
|
.pipelines
|
||||||
|
.get(&pipeline)
|
||||||
|
.ok_or_else(|| DrawError::NonExistentPipeline)?;
|
||||||
|
let layout = pipeline_descriptor
|
||||||
.get_layout()
|
.get_layout()
|
||||||
.ok_or_else(|| DrawError::PipelineHasNoLayout)?;
|
.ok_or_else(|| DrawError::PipelineHasNoLayout)?;
|
||||||
|
for bindings in render_resource_bindings.iter_mut() {
|
||||||
|
bindings.update_bind_groups(pipeline_descriptor, &**self.render_resource_context);
|
||||||
|
}
|
||||||
for bind_group_descriptor in layout.bind_groups.iter() {
|
for bind_group_descriptor in layout.bind_groups.iter() {
|
||||||
if let Some(local_bind_group) =
|
for bindings in render_resource_bindings.iter_mut() {
|
||||||
render_resource_bindings.get_descriptor_bind_group(bind_group_descriptor.id)
|
if let Some(bind_group) =
|
||||||
|
bindings.get_descriptor_bind_group(bind_group_descriptor.id)
|
||||||
{
|
{
|
||||||
self.set_bind_group(bind_group_descriptor.index, local_bind_group);
|
draw.set_bind_group(bind_group_descriptor.index, bind_group);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
pub fn set_vertex_buffers_from_bindings(
|
||||||
pub fn render_command(&mut self, render_command: RenderCommand) {
|
&self,
|
||||||
self.draw.render_commands.push(render_command);
|
draw: &mut Draw,
|
||||||
|
render_resource_bindings: &[&RenderResourceBindings],
|
||||||
|
) -> Result<Option<Range<u32>>, DrawError> {
|
||||||
|
let mut indices = None;
|
||||||
|
let pipeline = self
|
||||||
|
.current_pipeline
|
||||||
|
.ok_or_else(|| DrawError::NoPipelineSet)?;
|
||||||
|
let pipeline_descriptor = self
|
||||||
|
.pipelines
|
||||||
|
.get(&pipeline)
|
||||||
|
.ok_or_else(|| DrawError::NonExistentPipeline)?;
|
||||||
|
let layout = pipeline_descriptor
|
||||||
|
.get_layout()
|
||||||
|
.ok_or_else(|| DrawError::PipelineHasNoLayout)?;
|
||||||
|
for (slot, vertex_buffer_descriptor) in layout.vertex_buffer_descriptors.iter().enumerate()
|
||||||
|
{
|
||||||
|
for bindings in render_resource_bindings.iter() {
|
||||||
|
if let Some((vertex_buffer, index_buffer)) =
|
||||||
|
bindings.get_vertex_buffer(&vertex_buffer_descriptor.name)
|
||||||
|
{
|
||||||
|
draw.set_vertex_buffer(slot as u32, vertex_buffer, 0);
|
||||||
|
if let Some(index_buffer) = index_buffer {
|
||||||
|
if let Some(buffer_info) =
|
||||||
|
self.render_resource_context.get_buffer_info(index_buffer)
|
||||||
|
{
|
||||||
|
indices = Some(0..(buffer_info.size / 2) as u32);
|
||||||
|
} else {
|
||||||
|
panic!("expected buffer type");
|
||||||
|
}
|
||||||
|
draw.set_index_buffer(index_buffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw<T: Drawable>(&mut self, drawable: &mut T) -> Result<(), DrawError> {
|
break;
|
||||||
drawable.draw(self)
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(indices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Drawable {
|
pub trait Drawable {
|
||||||
fn draw(&mut self, draw: &mut DrawContext) -> Result<(), DrawError>;
|
fn draw(&mut self, draw: &mut Draw, context: &mut DrawContext) -> Result<(), DrawError>;
|
||||||
}
|
|
||||||
|
|
||||||
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>,
|
|
||||||
) {
|
|
||||||
let mut draw_context = draw.get_context(
|
|
||||||
&pipelines,
|
|
||||||
&**render_resource_context,
|
|
||||||
&render_resource_bindings,
|
|
||||||
&asset_render_resource_bindings,
|
|
||||||
&shared_buffers,
|
|
||||||
);
|
|
||||||
draw_context.draw(drawable.as_mut()).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_draw_system(mut draw: ComMut<Draw>) {
|
pub fn clear_draw_system(mut draw: ComMut<Draw>) {
|
||||||
|
|
|
@ -35,12 +35,12 @@ use base_render_graph::{BaseRenderGraphBuilder, BaseRenderGraphConfig};
|
||||||
use bevy_app::{AppBuilder, AppPlugin};
|
use bevy_app::{AppBuilder, AppPlugin};
|
||||||
use bevy_asset::AddAsset;
|
use bevy_asset::AddAsset;
|
||||||
use bevy_type_registry::RegisterType;
|
use bevy_type_registry::RegisterType;
|
||||||
use draw::{clear_draw_system, draw_system, Draw};
|
use draw::{clear_draw_system, Draw};
|
||||||
use legion::prelude::IntoSystem;
|
use legion::prelude::IntoSystem;
|
||||||
use mesh::mesh_resource_provider_system;
|
use mesh::mesh_resource_provider_system;
|
||||||
use pipeline::{compile_pipelines_system, RenderPipelines};
|
use pipeline::{draw_render_pipelines_system, RenderPipelines};
|
||||||
use render_graph::{system::render_graph_schedule_executor_system, RenderGraph};
|
use render_graph::{system::render_graph_schedule_executor_system, RenderGraph};
|
||||||
use render_resource::{bind_groups_system, AssetRenderResourceBindings};
|
use render_resource::AssetRenderResourceBindings;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use texture::{PngTextureLoader, TextureResourceSystemState};
|
use texture::{PngTextureLoader, TextureResourceSystemState};
|
||||||
|
|
||||||
|
@ -112,12 +112,7 @@ impl AppPlugin for RenderPlugin {
|
||||||
stage::RENDER_GRAPH_SYSTEMS,
|
stage::RENDER_GRAPH_SYSTEMS,
|
||||||
render_graph_schedule_executor_system,
|
render_graph_schedule_executor_system,
|
||||||
)
|
)
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(stage::DRAW, draw_render_pipelines_system.system());
|
||||||
stage::RENDER_GRAPH_SYSTEMS,
|
|
||||||
compile_pipelines_system.system(),
|
|
||||||
)
|
|
||||||
.add_system_to_stage(stage::RENDER_GRAPH_SYSTEMS, bind_groups_system.system())
|
|
||||||
.add_system_to_stage(stage::DRAW, draw_system::<RenderPipelines>.system());
|
|
||||||
|
|
||||||
if let Some(ref config) = self.base_render_graph_config {
|
if let Some(ref config) = self.base_render_graph_config {
|
||||||
let resources = app.resources();
|
let resources = app.resources();
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
use super::{
|
use super::{state_descriptors::PrimitiveTopology, PipelineDescriptor, VertexBufferDescriptors};
|
||||||
state_descriptors::PrimitiveTopology, PipelineDescriptor, RenderPipelines,
|
|
||||||
VertexBufferDescriptors,
|
|
||||||
};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
renderer::RenderResourceContext,
|
renderer::RenderResourceContext,
|
||||||
shader::{Shader, ShaderSource},
|
shader::{Shader, ShaderSource},
|
||||||
};
|
};
|
||||||
use bevy_asset::{Assets, Handle, AssetEvent};
|
use bevy_asset::{Assets, Handle};
|
||||||
use legion::prelude::*;
|
use once_cell::sync::Lazy;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use bevy_app::Events;
|
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Debug, Default)]
|
#[derive(Clone, Eq, PartialEq, Debug, Default)]
|
||||||
pub struct PipelineSpecialization {
|
pub struct PipelineSpecialization {
|
||||||
|
@ -18,6 +14,14 @@ pub struct PipelineSpecialization {
|
||||||
pub dynamic_bindings: Vec<DynamicBinding>,
|
pub dynamic_bindings: Vec<DynamicBinding>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PipelineSpecialization {
|
||||||
|
pub fn empty() -> &'static PipelineSpecialization {
|
||||||
|
pub static EMPTY: Lazy<PipelineSpecialization> =
|
||||||
|
Lazy::new(|| PipelineSpecialization::default());
|
||||||
|
&EMPTY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Debug, Default)]
|
#[derive(Clone, Eq, PartialEq, Debug, Default)]
|
||||||
pub struct ShaderSpecialization {
|
pub struct ShaderSpecialization {
|
||||||
pub shader_defs: HashSet<String>,
|
pub shader_defs: HashSet<String>,
|
||||||
|
@ -90,7 +94,24 @@ impl PipelineCompiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_pipeline(
|
pub fn get_specialized_pipeline(
|
||||||
|
&self,
|
||||||
|
pipeline: Handle<PipelineDescriptor>,
|
||||||
|
specialization: &PipelineSpecialization,
|
||||||
|
) -> Option<Handle<PipelineDescriptor>> {
|
||||||
|
self.specialized_pipelines
|
||||||
|
.get(&pipeline)
|
||||||
|
.and_then(|specialized_pipelines| {
|
||||||
|
specialized_pipelines
|
||||||
|
.iter()
|
||||||
|
.find(|current_specialized_pipeline| {
|
||||||
|
¤t_specialized_pipeline.specialization == specialization
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map(|specialized_pipeline| specialized_pipeline.pipeline)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compile_pipeline(
|
||||||
&mut self,
|
&mut self,
|
||||||
render_resource_context: &dyn RenderResourceContext,
|
render_resource_context: &dyn RenderResourceContext,
|
||||||
pipelines: &mut Assets<PipelineDescriptor>,
|
pipelines: &mut Assets<PipelineDescriptor>,
|
||||||
|
@ -152,48 +173,16 @@ impl PipelineCompiler {
|
||||||
specialized_pipeline_handle
|
specialized_pipeline_handle
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_render_pipelines(
|
|
||||||
&mut self,
|
|
||||||
vertex_buffer_descriptors: &VertexBufferDescriptors,
|
|
||||||
pipelines: &mut Assets<PipelineDescriptor>,
|
|
||||||
shaders: &mut Assets<Shader>,
|
|
||||||
render_pipelines: &mut RenderPipelines,
|
|
||||||
render_resource_context: &dyn RenderResourceContext,
|
|
||||||
) {
|
|
||||||
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
|
||||||
let source_pipeline = render_pipeline.pipeline;
|
|
||||||
let compiled_pipeline_handle = if let Some(specialized_pipeline) =
|
|
||||||
self.specialized_pipelines
|
|
||||||
.get_mut(&source_pipeline)
|
|
||||||
.and_then(|specialized_pipelines| {
|
|
||||||
specialized_pipelines.iter().find(
|
|
||||||
|current_specialized_pipeline| {
|
|
||||||
current_specialized_pipeline.specialization == render_pipeline.specialization
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
specialized_pipeline.pipeline
|
|
||||||
} else {
|
|
||||||
self.compile_pipeline(
|
|
||||||
render_resource_context,
|
|
||||||
pipelines,
|
|
||||||
shaders,
|
|
||||||
source_pipeline,
|
|
||||||
vertex_buffer_descriptors,
|
|
||||||
&render_pipeline.specialization,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
render_pipeline.specialized_pipeline = Some(compiled_pipeline_handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter_compiled_pipelines(
|
pub fn iter_compiled_pipelines(
|
||||||
&self,
|
&self,
|
||||||
pipeline_handle: Handle<PipelineDescriptor>,
|
pipeline_handle: Handle<PipelineDescriptor>,
|
||||||
) -> Option<impl Iterator<Item = &Handle<PipelineDescriptor>>> {
|
) -> Option<impl Iterator<Item = &Handle<PipelineDescriptor>>> {
|
||||||
if let Some(compiled_pipelines) = self.specialized_pipelines.get(&pipeline_handle) {
|
if let Some(compiled_pipelines) = self.specialized_pipelines.get(&pipeline_handle) {
|
||||||
Some(compiled_pipelines.iter().map(|specialized_pipeline| &specialized_pipeline.pipeline))
|
Some(
|
||||||
|
compiled_pipelines
|
||||||
|
.iter()
|
||||||
|
.map(|specialized_pipeline| &specialized_pipeline.pipeline),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -210,65 +199,3 @@ impl PipelineCompiler {
|
||||||
.flatten()
|
.flatten()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make this a system
|
|
||||||
pub fn compile_pipelines_system(
|
|
||||||
world: &mut SubWorld,
|
|
||||||
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;
|
|
||||||
// NOTE: this intentionally only handles events that happened prior to this system during this frame. this results in
|
|
||||||
// "new specialized pipeline" events being ignored.
|
|
||||||
// let default_specialization = PipelineSpecialization::default();
|
|
||||||
// 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 { .. } => {
|
|
||||||
// // TODO: clean up old pipelines
|
|
||||||
// None
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// if let Some(handle_to_compile) = handle_to_compile {
|
|
||||||
// // TODO: try updating specialization here.
|
|
||||||
// pipeline_compiler.compile_pipeline(
|
|
||||||
// render_resource_context,
|
|
||||||
// &mut pipelines,
|
|
||||||
// &mut shaders,
|
|
||||||
// handle_to_compile,
|
|
||||||
// &vertex_buffer_descriptors,
|
|
||||||
// &default_specialization,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TODO: only update when RenderPipelines is changed
|
|
||||||
for mut render_pipelines in query.iter_mut(world) {
|
|
||||||
pipeline_compiler.compile_render_pipelines(
|
|
||||||
&vertex_buffer_descriptors,
|
|
||||||
&mut pipelines,
|
|
||||||
&mut shaders,
|
|
||||||
&mut render_pipelines,
|
|
||||||
render_resource_context,
|
|
||||||
);
|
|
||||||
|
|
||||||
// reset shader_defs so they can be changed next frame
|
|
||||||
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
|
||||||
render_pipeline
|
|
||||||
.specialization
|
|
||||||
.shader_specialization
|
|
||||||
.shader_defs
|
|
||||||
.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
use super::{PipelineDescriptor, PipelineSpecialization};
|
use super::{PipelineDescriptor, PipelineSpecialization};
|
||||||
use crate::{
|
use crate::{
|
||||||
draw::{DrawContext, DrawError, Drawable},
|
draw::{Draw, DrawContext, DrawError, Drawable},
|
||||||
render_resource::RenderResourceBindings,
|
render_resource::RenderResourceBindings,
|
||||||
};
|
};
|
||||||
use bevy_asset::Handle;
|
use bevy_asset::Handle;
|
||||||
use bevy_property::Properties;
|
use bevy_property::Properties;
|
||||||
|
use legion::{prelude::ComMut, systems::ResMut};
|
||||||
#[derive(Properties, Default, Clone)]
|
#[derive(Properties, Default, Clone)]
|
||||||
pub struct RenderPipeline {
|
pub struct RenderPipeline {
|
||||||
pub pipeline: Handle<PipelineDescriptor>,
|
pub pipeline: Handle<PipelineDescriptor>,
|
||||||
#[property(ignore)]
|
#[property(ignore)]
|
||||||
pub specialized_pipeline: Option<Handle<PipelineDescriptor>>,
|
|
||||||
#[property(ignore)]
|
|
||||||
pub specialization: PipelineSpecialization,
|
pub specialization: PipelineSpecialization,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +21,10 @@ impl RenderPipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn specialized(pipeline: Handle<PipelineDescriptor>, specialization: PipelineSpecialization) -> Self {
|
pub fn specialized(
|
||||||
|
pipeline: Handle<PipelineDescriptor>,
|
||||||
|
specialization: PipelineSpecialization,
|
||||||
|
) -> Self {
|
||||||
RenderPipeline {
|
RenderPipeline {
|
||||||
pipeline,
|
pipeline,
|
||||||
specialization,
|
specialization,
|
||||||
|
@ -68,55 +70,46 @@ impl Default for RenderPipelines {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drawable for RenderPipelines {
|
pub struct DrawableRenderPipelines<'a> {
|
||||||
fn draw(&mut self, draw: &mut DrawContext) -> Result<(), DrawError> {
|
pub render_pipelines: &'a mut RenderPipelines,
|
||||||
for render_pipeline in self.pipelines.iter() {
|
pub render_resource_bindings: &'a mut RenderResourceBindings,
|
||||||
let specialized_handle = if let Some(handle) = render_pipeline.specialized_pipeline {
|
}
|
||||||
handle
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let pipeline = draw.pipelines.get(&specialized_handle).unwrap();
|
|
||||||
let layout = pipeline.get_layout().unwrap();
|
|
||||||
draw.set_pipeline(specialized_handle)?;
|
|
||||||
for bind_group_descriptor in layout.bind_groups.iter() {
|
|
||||||
if let Some(local_bind_group) = self
|
|
||||||
.bindings
|
|
||||||
.get_descriptor_bind_group(bind_group_descriptor.id)
|
|
||||||
{
|
|
||||||
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.index, global_bind_group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut indices = 0..0;
|
|
||||||
for (slot, vertex_buffer_descriptor) in
|
|
||||||
layout.vertex_buffer_descriptors.iter().enumerate()
|
|
||||||
{
|
|
||||||
if let Some((vertex_buffer, index_buffer)) = self
|
|
||||||
.bindings
|
|
||||||
.get_vertex_buffer(&vertex_buffer_descriptor.name)
|
|
||||||
{
|
|
||||||
draw.set_vertex_buffer(slot as u32, vertex_buffer, 0);
|
|
||||||
if let Some(index_buffer) = index_buffer {
|
|
||||||
if let Some(buffer_info) =
|
|
||||||
draw.render_resource_context.get_buffer_info(index_buffer)
|
|
||||||
{
|
|
||||||
indices = 0..(buffer_info.size / 2) as u32;
|
|
||||||
} else {
|
|
||||||
panic!("expected buffer type");
|
|
||||||
}
|
|
||||||
draw.set_index_buffer(index_buffer, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
impl<'a> Drawable for DrawableRenderPipelines<'a> {
|
||||||
|
fn draw(&mut self, draw: &mut Draw, context: &mut DrawContext) -> Result<(), DrawError> {
|
||||||
|
for render_pipeline in self.render_pipelines.pipelines.iter() {
|
||||||
|
context.set_pipeline(
|
||||||
|
draw,
|
||||||
|
render_pipeline.pipeline,
|
||||||
|
&render_pipeline.specialization,
|
||||||
|
)?;
|
||||||
|
context.set_bind_groups_from_bindings(
|
||||||
|
draw,
|
||||||
|
&mut [
|
||||||
|
&mut self.render_pipelines.bindings,
|
||||||
|
self.render_resource_bindings,
|
||||||
|
],
|
||||||
|
)?;
|
||||||
|
let indices = context
|
||||||
|
.set_vertex_buffers_from_bindings(draw, &[&self.render_pipelines.bindings])?;
|
||||||
|
if let Some(indices) = indices {
|
||||||
draw.draw_indexed(indices, 0, 0..1);
|
draw.draw_indexed(indices, 0, 0..1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn draw_render_pipelines_system(
|
||||||
|
mut draw_context: DrawContext,
|
||||||
|
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
||||||
|
mut draw: ComMut<Draw>,
|
||||||
|
mut render_pipelines: ComMut<RenderPipelines>,
|
||||||
|
) {
|
||||||
|
let mut drawable = DrawableRenderPipelines {
|
||||||
|
render_pipelines: &mut render_pipelines,
|
||||||
|
render_resource_bindings: &mut render_resource_bindings,
|
||||||
|
};
|
||||||
|
drawable.draw(&mut draw, &mut draw_context).unwrap();
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ mod buffer;
|
||||||
mod render_resource;
|
mod render_resource;
|
||||||
mod render_resource_bindings;
|
mod render_resource_bindings;
|
||||||
mod shared_buffers;
|
mod shared_buffers;
|
||||||
mod systems;
|
|
||||||
mod texture;
|
mod texture;
|
||||||
|
|
||||||
pub use bind_group::*;
|
pub use bind_group::*;
|
||||||
|
@ -11,5 +10,4 @@ pub use buffer::*;
|
||||||
pub use render_resource::*;
|
pub use render_resource::*;
|
||||||
pub use render_resource_bindings::*;
|
pub use render_resource_bindings::*;
|
||||||
pub use shared_buffers::*;
|
pub use shared_buffers::*;
|
||||||
pub use systems::*;
|
|
||||||
pub use texture::*;
|
pub use texture::*;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use super::{BindGroup, BindGroupId, BufferId, RenderResourceId, SamplerId, TextureId};
|
use super::{BindGroup, BindGroupId, BufferId, RenderResourceId, SamplerId, TextureId};
|
||||||
use crate::{renderer::RenderResourceContext, pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineDescriptor}};
|
use crate::{
|
||||||
|
pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineDescriptor},
|
||||||
|
renderer::RenderResourceContext,
|
||||||
|
};
|
||||||
use bevy_asset::{Handle, HandleUntyped};
|
use bevy_asset::{Handle, HandleUntyped};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
|
@ -82,10 +85,8 @@ pub struct RenderResourceBindings {
|
||||||
// TODO: remove this
|
// TODO: remove this
|
||||||
vertex_buffers: HashMap<String, (BufferId, Option<BufferId>)>,
|
vertex_buffers: HashMap<String, (BufferId, Option<BufferId>)>,
|
||||||
bind_groups: HashMap<BindGroupId, BindGroup>,
|
bind_groups: HashMap<BindGroupId, BindGroup>,
|
||||||
bind_group_descriptors: HashMap<BindGroupDescriptorId, BindGroupId>,
|
bind_group_descriptors: HashMap<BindGroupDescriptorId, Option<BindGroupId>>,
|
||||||
dirty_bind_groups: HashSet<BindGroupId>,
|
dirty_bind_groups: HashSet<BindGroupId>,
|
||||||
// TODO: remove this
|
|
||||||
// pub pipeline_specialization: PipelineSpecialization,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderResourceBindings {
|
impl RenderResourceBindings {
|
||||||
|
@ -139,7 +140,7 @@ impl RenderResourceBindings {
|
||||||
if let Some(bind_group) = bind_group {
|
if let Some(bind_group) = bind_group {
|
||||||
let id = bind_group.id;
|
let id = bind_group.id;
|
||||||
self.bind_groups.insert(id, bind_group);
|
self.bind_groups.insert(id, bind_group);
|
||||||
self.bind_group_descriptors.insert(descriptor.id, id);
|
self.bind_group_descriptors.insert(descriptor.id, Some(id));
|
||||||
BindGroupStatus::Changed(id)
|
BindGroupStatus::Changed(id)
|
||||||
} else {
|
} else {
|
||||||
BindGroupStatus::NoMatch
|
BindGroupStatus::NoMatch
|
||||||
|
@ -151,18 +152,26 @@ impl RenderResourceBindings {
|
||||||
bind_group_descriptor: &BindGroupDescriptor,
|
bind_group_descriptor: &BindGroupDescriptor,
|
||||||
) -> BindGroupStatus {
|
) -> BindGroupStatus {
|
||||||
if let Some(id) = self.bind_group_descriptors.get(&bind_group_descriptor.id) {
|
if let Some(id) = self.bind_group_descriptors.get(&bind_group_descriptor.id) {
|
||||||
|
if let Some(id) = id {
|
||||||
if self.dirty_bind_groups.contains(id) {
|
if self.dirty_bind_groups.contains(id) {
|
||||||
self.dirty_bind_groups.remove(id);
|
self.dirty_bind_groups.remove(id);
|
||||||
self.create_bind_group(bind_group_descriptor)
|
self.create_bind_group(bind_group_descriptor)
|
||||||
} else {
|
} else {
|
||||||
BindGroupStatus::Unchanged(*id)
|
BindGroupStatus::Unchanged(*id)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
BindGroupStatus::NoMatch
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.create_bind_group(bind_group_descriptor)
|
self.create_bind_group(bind_group_descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_bind_groups(&mut self, pipeline: &PipelineDescriptor, render_resource_context: &dyn RenderResourceContext) {
|
pub fn update_bind_groups(
|
||||||
|
&mut self,
|
||||||
|
pipeline: &PipelineDescriptor,
|
||||||
|
render_resource_context: &dyn RenderResourceContext,
|
||||||
|
) {
|
||||||
let layout = pipeline.get_layout().unwrap();
|
let layout = pipeline.get_layout().unwrap();
|
||||||
for bind_group_descriptor in layout.bind_groups.iter() {
|
for bind_group_descriptor in layout.bind_groups.iter() {
|
||||||
match self.update_bind_group(bind_group_descriptor) {
|
match self.update_bind_group(bind_group_descriptor) {
|
||||||
|
@ -195,7 +204,13 @@ impl RenderResourceBindings {
|
||||||
pub fn get_descriptor_bind_group(&self, id: BindGroupDescriptorId) -> Option<&BindGroup> {
|
pub fn get_descriptor_bind_group(&self, id: BindGroupDescriptorId) -> Option<&BindGroup> {
|
||||||
self.bind_group_descriptors
|
self.bind_group_descriptors
|
||||||
.get(&id)
|
.get(&id)
|
||||||
.and_then(|bind_group_id| self.get_bind_group(*bind_group_id))
|
.and_then(|bind_group_id| {
|
||||||
|
if let Some(bind_group_id) = bind_group_id {
|
||||||
|
self.get_bind_group(*bind_group_id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_bind_group(&self, bind_group_descriptor: &BindGroupDescriptor) -> Option<BindGroup> {
|
fn build_bind_group(&self, bind_group_descriptor: &BindGroupDescriptor) -> Option<BindGroup> {
|
||||||
|
@ -228,6 +243,10 @@ impl AssetRenderResourceBindings {
|
||||||
.entry(HandleUntyped::from(handle))
|
.entry(HandleUntyped::from(handle))
|
||||||
.or_insert_with(|| RenderResourceBindings::default())
|
.or_insert_with(|| RenderResourceBindings::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_mut<T>(&mut self, handle: Handle<T>) -> Option<&mut RenderResourceBindings> {
|
||||||
|
self.bindings.get_mut(&HandleUntyped::from(handle))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)]
|
#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)]
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
use crate::{
|
|
||||||
pipeline::{PipelineCompiler, PipelineDescriptor, RenderPipelines},
|
|
||||||
render_resource::RenderResourceBindings,
|
|
||||||
renderer::RenderResourceContext,
|
|
||||||
};
|
|
||||||
use bevy_asset::Assets;
|
|
||||||
use legion::prelude::*;
|
|
||||||
|
|
||||||
pub fn bind_groups_system(
|
|
||||||
world: &mut SubWorld,
|
|
||||||
pipelines: Res<Assets<PipelineDescriptor>>,
|
|
||||||
pipeline_compiler: Res<PipelineCompiler>,
|
|
||||||
render_resource_context: Res<Box<dyn RenderResourceContext>>,
|
|
||||||
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
|
||||||
query: &mut Query<Write<RenderPipelines>>,
|
|
||||||
) {
|
|
||||||
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();
|
|
||||||
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();
|
|
||||||
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
|
||||||
let pipeline = pipelines
|
|
||||||
.get(&render_pipeline.specialized_pipeline.unwrap())
|
|
||||||
.unwrap();
|
|
||||||
render_pipelines.bindings.update_bind_groups(pipeline, render_resource_context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +1,10 @@
|
||||||
use crate::{Font, FontAtlasSet};
|
use crate::{Font, FontAtlasSet};
|
||||||
use bevy_asset::Assets;
|
use bevy_asset::Assets;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
draw::{DrawContext, DrawError, Drawable},
|
draw::{DrawContext, DrawError, Drawable, Draw},
|
||||||
mesh,
|
mesh,
|
||||||
render_resource::{BindGroup, BufferUsage, RenderResourceId},
|
render_resource::{BindGroup, BufferUsage, RenderResourceId},
|
||||||
Color,
|
Color, pipeline::PipelineSpecialization,
|
||||||
};
|
};
|
||||||
use bevy_sprite::{TextureAtlas, TextureAtlasSprite};
|
use bevy_sprite::{TextureAtlas, TextureAtlasSprite};
|
||||||
use glam::{Vec2, Vec3};
|
use glam::{Vec2, Vec3};
|
||||||
|
@ -45,10 +45,9 @@ impl<'a> DrawableText<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Drawable for DrawableText<'a> {
|
impl<'a> Drawable for DrawableText<'a> {
|
||||||
fn draw(&mut self, draw: &mut DrawContext) -> Result<(), DrawError> {
|
fn draw(&mut self, draw: &mut Draw, context: &mut DrawContext) -> Result<(), DrawError> {
|
||||||
draw.set_pipeline(bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE)?;
|
context.set_pipeline(draw, bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE, PipelineSpecialization::empty())?;
|
||||||
let render_resource_context = draw.render_resource_context;
|
let render_resource_context = &**context.render_resource_context;
|
||||||
// TODO: add draw.set_mesh(slot)
|
|
||||||
if let Some(RenderResourceId::Buffer(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)
|
||||||
{
|
{
|
||||||
|
@ -59,8 +58,7 @@ impl<'a> Drawable for DrawableText<'a> {
|
||||||
.get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::INDEX_BUFFER_ASSET_INDEX)
|
.get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::INDEX_BUFFER_ASSET_INDEX)
|
||||||
{
|
{
|
||||||
draw.set_index_buffer(quad_index_buffer, 0);
|
draw.set_index_buffer(quad_index_buffer, 0);
|
||||||
if let Some(buffer_info) = draw
|
if let Some(buffer_info) = render_resource_context
|
||||||
.render_resource_context
|
|
||||||
.get_buffer_info(quad_index_buffer)
|
.get_buffer_info(quad_index_buffer)
|
||||||
{
|
{
|
||||||
indices = 0..(buffer_info.size / 2) as u32;
|
indices = 0..(buffer_info.size / 2) as u32;
|
||||||
|
@ -70,7 +68,7 @@ impl<'a> Drawable for DrawableText<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set global bindings
|
// set global bindings
|
||||||
draw.set_bind_groups_from_bindings(&draw.render_resource_bindings)?;
|
// context.set_bind_groups_from_bindings(draw, &mut[context.render_resource_bindings])?;
|
||||||
|
|
||||||
// set local per-character bindings
|
// set local per-character bindings
|
||||||
for character in self.text.chars() {
|
for character in self.text.chars() {
|
||||||
|
@ -78,17 +76,17 @@ impl<'a> Drawable for DrawableText<'a> {
|
||||||
.font_atlas_set
|
.font_atlas_set
|
||||||
.get_glyph_atlas_info(self.style.font_size, character)
|
.get_glyph_atlas_info(self.style.font_size, character)
|
||||||
{
|
{
|
||||||
let atlas_render_resource_bindings = draw
|
// let atlas_render_resource_bindings = context
|
||||||
.asset_render_resource_bindings
|
// .asset_render_resource_bindings
|
||||||
.get(glyph_atlas_info.texture_atlas)
|
// .get_mut(glyph_atlas_info.texture_atlas)
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
draw.set_bind_groups_from_bindings(&atlas_render_resource_bindings)?;
|
// context.set_bind_groups_from_bindings(draw, &mut[atlas_render_resource_bindings])?;
|
||||||
let sprite_buffer = TextureAtlasSprite {
|
let sprite_buffer = TextureAtlasSprite {
|
||||||
index: glyph_atlas_info.char_index,
|
index: glyph_atlas_info.char_index,
|
||||||
position: Vec3::new(300.0, 300.0, 0.0),
|
position: Vec3::new(300.0, 300.0, 0.0),
|
||||||
scale: 5.0,
|
scale: 5.0,
|
||||||
};
|
};
|
||||||
let sprite_buffer = draw
|
let sprite_buffer = context
|
||||||
.shared_buffers
|
.shared_buffers
|
||||||
.get_buffer(&sprite_buffer, BufferUsage::UNIFORM)
|
.get_buffer(&sprite_buffer, BufferUsage::UNIFORM)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
use bevy_asset::{Assets, Handle};
|
use bevy_asset::{Assets, Handle};
|
||||||
use bevy_render::{
|
use bevy_render::{draw::{DrawContext, Draw}, texture::Texture, Color};
|
||||||
draw::Draw,
|
|
||||||
pipeline::PipelineDescriptor,
|
|
||||||
render_resource::{AssetRenderResourceBindings, RenderResourceBindings, SharedBuffers},
|
|
||||||
renderer::RenderResourceContext,
|
|
||||||
texture::Texture,
|
|
||||||
Color,
|
|
||||||
};
|
|
||||||
use bevy_sprite::{ColorMaterial, ComMut, Quad, TextureAtlas};
|
use bevy_sprite::{ColorMaterial, ComMut, Quad, TextureAtlas};
|
||||||
use bevy_text::{Font, FontAtlasSet, TextStyle};
|
use bevy_text::{Font, FontAtlasSet, TextStyle};
|
||||||
use legion::prelude::{Com, Res, ResMut};
|
use legion::prelude::{Com, Res, ResMut};
|
||||||
|
@ -78,11 +71,7 @@ impl Label {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_label_system(
|
pub fn draw_label_system(
|
||||||
_pipelines: Res<Assets<PipelineDescriptor>>,
|
mut _draw_context: DrawContext,
|
||||||
_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>>,
|
_fonts: Res<Assets<Font>>,
|
||||||
_font_atlas_sets: Res<Assets<FontAtlasSet>>,
|
_font_atlas_sets: Res<Assets<FontAtlasSet>>,
|
||||||
_texture_atlases: Res<Assets<TextureAtlas>>,
|
_texture_atlases: Res<Assets<TextureAtlas>>,
|
||||||
|
@ -90,23 +79,16 @@ impl Label {
|
||||||
_label: Com<Label>,
|
_label: Com<Label>,
|
||||||
_quad: Com<Quad>,
|
_quad: Com<Quad>,
|
||||||
) {
|
) {
|
||||||
// let mut draw_context = draw.get_context(
|
|
||||||
// &pipelines,
|
|
||||||
// &**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
|
|
||||||
// let mut drawable_text = DrawableText::new(
|
// let mut drawable_text = DrawableText::new(
|
||||||
// fonts.get(&label.font).unwrap(),
|
// fonts.get(&label.font).unwrap(),
|
||||||
// font_atlas_sets.get(&label.font.as_handle::<FontAtlasSet>()).unwrap(),
|
// font_atlas_sets
|
||||||
|
// .get(&label.font.as_handle::<FontAtlasSet>())
|
||||||
|
// .unwrap(),
|
||||||
// &texture_atlases,
|
// &texture_atlases,
|
||||||
// quad.position,
|
// quad.position,
|
||||||
// &label.style,
|
// &label.style,
|
||||||
// &label.text,
|
// &label.text,
|
||||||
// );
|
// );
|
||||||
// draw_context.draw(&mut drawable_text).unwrap();
|
// drawable_text.draw(&mut draw, &mut draw_context).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ fn setup(
|
||||||
mut textures: ResMut<Assets<Texture>>,
|
mut textures: ResMut<Assets<Texture>>,
|
||||||
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
|
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
|
||||||
) {
|
) {
|
||||||
env_logger::init();
|
|
||||||
let texture_handle = asset_server
|
let texture_handle = asset_server
|
||||||
.load_sync(
|
.load_sync(
|
||||||
&mut textures,
|
&mut textures,
|
||||||
|
|
Loading…
Reference in a new issue