delegate layout reflection to RenderResourceContext (#691)
* delegate layout reflection to RenderResourceContext Also: * auto-reflect DynamicBindings * use RenderPipeline::new, update dynamic_bindings linting. * add dynamic binding generation Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
parent
8607ccf669
commit
60fa2d5f93
@ -4,7 +4,7 @@ use bevy_ecs::Bundle;
|
|||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
draw::Draw,
|
draw::Draw,
|
||||||
mesh::Mesh,
|
mesh::Mesh,
|
||||||
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
|
pipeline::{RenderPipeline, RenderPipelines},
|
||||||
render_graph::base::MainPass,
|
render_graph::base::MainPass,
|
||||||
};
|
};
|
||||||
use bevy_transform::prelude::{GlobalTransform, Transform};
|
use bevy_transform::prelude::{GlobalTransform, Transform};
|
||||||
@ -24,23 +24,8 @@ pub struct PbrComponents {
|
|||||||
impl Default for PbrComponents {
|
impl Default for PbrComponents {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::specialized(
|
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
|
||||||
FORWARD_PIPELINE_HANDLE,
|
FORWARD_PIPELINE_HANDLE,
|
||||||
PipelineSpecialization {
|
|
||||||
dynamic_bindings: vec![
|
|
||||||
// Transform
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 2,
|
|
||||||
binding: 0,
|
|
||||||
},
|
|
||||||
// StandardMaterial_albedo
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 3,
|
|
||||||
binding: 0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)]),
|
)]),
|
||||||
mesh: Default::default(),
|
mesh: Default::default(),
|
||||||
material: Default::default(),
|
material: Default::default(),
|
||||||
|
@ -37,8 +37,8 @@ use camera::{
|
|||||||
ActiveCameras, Camera, OrthographicProjection, PerspectiveProjection, VisibleEntities,
|
ActiveCameras, Camera, OrthographicProjection, PerspectiveProjection, VisibleEntities,
|
||||||
};
|
};
|
||||||
use pipeline::{
|
use pipeline::{
|
||||||
DynamicBinding, IndexFormat, PipelineCompiler, PipelineDescriptor, PipelineSpecialization,
|
IndexFormat, PipelineCompiler, PipelineDescriptor, PipelineSpecialization, PrimitiveTopology,
|
||||||
PrimitiveTopology, ShaderSpecialization,
|
ShaderSpecialization,
|
||||||
};
|
};
|
||||||
use render_graph::{
|
use render_graph::{
|
||||||
base::{self, BaseRenderGraphBuilder, BaseRenderGraphConfig},
|
base::{self, BaseRenderGraphBuilder, BaseRenderGraphConfig},
|
||||||
@ -66,7 +66,7 @@ pub mod stage {
|
|||||||
|
|
||||||
/// Adds core render types and systems to an App
|
/// Adds core render types and systems to an App
|
||||||
pub struct RenderPlugin {
|
pub struct RenderPlugin {
|
||||||
/// configures the "base render graph". If this is not `None`, the "base render graph" will be added
|
/// configures the "base render graph". If this is not `None`, the "base render graph" will be added
|
||||||
pub base_render_graph_config: Option<BaseRenderGraphConfig>,
|
pub base_render_graph_config: Option<BaseRenderGraphConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,6 @@ impl Plugin for RenderPlugin {
|
|||||||
.register_property::<Color>()
|
.register_property::<Color>()
|
||||||
.register_property::<Range<f32>>()
|
.register_property::<Range<f32>>()
|
||||||
.register_property::<ShaderSpecialization>()
|
.register_property::<ShaderSpecialization>()
|
||||||
.register_property::<DynamicBinding>()
|
|
||||||
.register_property::<PrimitiveTopology>()
|
.register_property::<PrimitiveTopology>()
|
||||||
.register_property::<IndexFormat>()
|
.register_property::<IndexFormat>()
|
||||||
.register_properties::<PipelineSpecialization>()
|
.register_properties::<PipelineSpecialization>()
|
||||||
|
@ -4,13 +4,9 @@ use super::{
|
|||||||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, IndexFormat,
|
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, IndexFormat,
|
||||||
PrimitiveTopology, RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
PrimitiveTopology, RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
||||||
},
|
},
|
||||||
BindType, DynamicBinding, PipelineLayout, StencilStateDescriptor,
|
PipelineLayout, StencilStateDescriptor,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{shader::ShaderStages, texture::TextureFormat};
|
||||||
shader::{Shader, ShaderStages},
|
|
||||||
texture::TextureFormat,
|
|
||||||
};
|
|
||||||
use bevy_asset::Assets;
|
|
||||||
use bevy_type_registry::TypeUuid;
|
use bevy_type_registry::TypeUuid;
|
||||||
|
|
||||||
#[derive(Clone, Debug, TypeUuid)]
|
#[derive(Clone, Debug, TypeUuid)]
|
||||||
@ -117,63 +113,4 @@ impl PipelineDescriptor {
|
|||||||
pub fn get_layout_mut(&mut self) -> Option<&mut PipelineLayout> {
|
pub fn get_layout_mut(&mut self) -> Option<&mut PipelineLayout> {
|
||||||
self.layout.as_mut()
|
self.layout.as_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reflects the pipeline layout from its shaders.
|
|
||||||
///
|
|
||||||
/// If `bevy_conventions` is true, it will be assumed that the shader follows "bevy shader conventions". These allow
|
|
||||||
/// richer reflection, such as inferred Vertex Buffer names and inferred instancing.
|
|
||||||
///
|
|
||||||
/// If `dynamic_bindings` has values, shader uniforms will be set to "dynamic" if there is a matching binding in the list
|
|
||||||
///
|
|
||||||
/// If `vertex_buffer_descriptors` is set, the pipeline's vertex buffers
|
|
||||||
/// will inherit their layouts from global descriptors, otherwise the layout will be assumed to be complete / local.
|
|
||||||
pub fn reflect_layout(
|
|
||||||
&mut self,
|
|
||||||
shaders: &Assets<Shader>,
|
|
||||||
bevy_conventions: bool,
|
|
||||||
dynamic_bindings: &[DynamicBinding],
|
|
||||||
) {
|
|
||||||
let vertex_spirv = shaders.get(&self.shader_stages.vertex).unwrap();
|
|
||||||
let fragment_spirv = self
|
|
||||||
.shader_stages
|
|
||||||
.fragment
|
|
||||||
.as_ref()
|
|
||||||
.map(|handle| shaders.get(handle).unwrap());
|
|
||||||
|
|
||||||
let mut layouts = vec![vertex_spirv.reflect_layout(bevy_conventions).unwrap()];
|
|
||||||
if let Some(ref fragment_spirv) = fragment_spirv {
|
|
||||||
layouts.push(fragment_spirv.reflect_layout(bevy_conventions).unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut layout = PipelineLayout::from_shader_layouts(&mut layouts);
|
|
||||||
|
|
||||||
if !dynamic_bindings.is_empty() {
|
|
||||||
// set binding uniforms to dynamic if render resource bindings use dynamic
|
|
||||||
for bind_group in layout.bind_groups.iter_mut() {
|
|
||||||
let mut binding_changed = false;
|
|
||||||
for binding in bind_group.bindings.iter_mut() {
|
|
||||||
let current = DynamicBinding {
|
|
||||||
bind_group: bind_group.index,
|
|
||||||
binding: binding.index,
|
|
||||||
};
|
|
||||||
|
|
||||||
if dynamic_bindings.contains(¤t) {
|
|
||||||
if let BindType::Uniform {
|
|
||||||
ref mut dynamic, ..
|
|
||||||
} = binding.bind_type
|
|
||||||
{
|
|
||||||
*dynamic = true;
|
|
||||||
binding_changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if binding_changed {
|
|
||||||
bind_group.update_id();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.layout = Some(layout);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::{state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor};
|
use super::{state_descriptors::PrimitiveTopology, IndexFormat, PipelineDescriptor};
|
||||||
use crate::{
|
use crate::{
|
||||||
pipeline::{
|
pipeline::{
|
||||||
InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat,
|
BindType, InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat,
|
||||||
VERTEX_FALLBACK_LAYOUT_NAME,
|
VERTEX_FALLBACK_LAYOUT_NAME,
|
||||||
},
|
},
|
||||||
renderer::RenderResourceContext,
|
renderer::RenderResourceContext,
|
||||||
@ -18,7 +18,7 @@ use std::borrow::Cow;
|
|||||||
pub struct PipelineSpecialization {
|
pub struct PipelineSpecialization {
|
||||||
pub shader_specialization: ShaderSpecialization,
|
pub shader_specialization: ShaderSpecialization,
|
||||||
pub primitive_topology: PrimitiveTopology,
|
pub primitive_topology: PrimitiveTopology,
|
||||||
pub dynamic_bindings: Vec<DynamicBinding>,
|
pub dynamic_bindings: Vec<String>,
|
||||||
pub index_format: IndexFormat,
|
pub index_format: IndexFormat,
|
||||||
pub vertex_buffer_descriptor: VertexBufferDescriptor,
|
pub vertex_buffer_descriptor: VertexBufferDescriptor,
|
||||||
pub sample_count: u32,
|
pub sample_count: u32,
|
||||||
@ -61,12 +61,6 @@ struct SpecializedPipeline {
|
|||||||
specialization: PipelineSpecialization,
|
specialization: PipelineSpecialization,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Debug, Default, Serialize, Deserialize, Property)]
|
|
||||||
pub struct DynamicBinding {
|
|
||||||
pub bind_group: u32,
|
|
||||||
pub binding: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct PipelineCompiler {
|
pub struct PipelineCompiler {
|
||||||
specialized_shaders: HashMap<Handle<Shader>, Vec<SpecializedShader>>,
|
specialized_shaders: HashMap<Handle<Shader>, Vec<SpecializedShader>>,
|
||||||
@ -163,12 +157,39 @@ impl PipelineCompiler {
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
specialized_descriptor.reflect_layout(
|
let mut layout = render_resource_context.reflect_pipeline_layout(
|
||||||
shaders,
|
&shaders,
|
||||||
|
&specialized_descriptor.shader_stages,
|
||||||
true,
|
true,
|
||||||
&pipeline_specialization.dynamic_bindings,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if !pipeline_specialization.dynamic_bindings.is_empty() {
|
||||||
|
// set binding uniforms to dynamic if render resource bindings use dynamic
|
||||||
|
for bind_group in layout.bind_groups.iter_mut() {
|
||||||
|
let mut binding_changed = false;
|
||||||
|
for binding in bind_group.bindings.iter_mut() {
|
||||||
|
if pipeline_specialization
|
||||||
|
.dynamic_bindings
|
||||||
|
.iter()
|
||||||
|
.any(|b| b == &binding.name)
|
||||||
|
{
|
||||||
|
if let BindType::Uniform {
|
||||||
|
ref mut dynamic, ..
|
||||||
|
} = binding.bind_type
|
||||||
|
{
|
||||||
|
*dynamic = true;
|
||||||
|
binding_changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if binding_changed {
|
||||||
|
bind_group.update_id();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
specialized_descriptor.layout = Some(layout);
|
||||||
|
|
||||||
// create a vertex layout that provides all attributes from either the specialized vertex buffers or a zero buffer
|
// create a vertex layout that provides all attributes from either the specialized vertex buffers or a zero buffer
|
||||||
let mut pipeline_layout = specialized_descriptor.layout.as_mut().unwrap();
|
let mut pipeline_layout = specialized_descriptor.layout.as_mut().unwrap();
|
||||||
// the vertex buffer descriptor of the mesh
|
// the vertex buffer descriptor of the mesh
|
||||||
|
@ -14,13 +14,16 @@ use bevy_property::Properties;
|
|||||||
pub struct RenderPipeline {
|
pub struct RenderPipeline {
|
||||||
pub pipeline: Handle<PipelineDescriptor>,
|
pub pipeline: Handle<PipelineDescriptor>,
|
||||||
pub specialization: PipelineSpecialization,
|
pub specialization: PipelineSpecialization,
|
||||||
|
/// used to track if PipelineSpecialization::dynamic_bindings is in sync with RenderResourceBindings
|
||||||
|
pub dynamic_bindings_generation: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderPipeline {
|
impl RenderPipeline {
|
||||||
pub fn new(pipeline: Handle<PipelineDescriptor>) -> Self {
|
pub fn new(pipeline: Handle<PipelineDescriptor>) -> Self {
|
||||||
RenderPipeline {
|
RenderPipeline {
|
||||||
|
specialization: Default::default(),
|
||||||
pipeline,
|
pipeline,
|
||||||
..Default::default()
|
dynamic_bindings_generation: std::usize::MAX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +34,7 @@ impl RenderPipeline {
|
|||||||
RenderPipeline {
|
RenderPipeline {
|
||||||
pipeline,
|
pipeline,
|
||||||
specialization,
|
specialization,
|
||||||
|
dynamic_bindings_generation: std::usize::MAX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,10 +104,24 @@ pub fn draw_render_pipelines_system(
|
|||||||
let render_pipelines = &mut *render_pipelines;
|
let render_pipelines = &mut *render_pipelines;
|
||||||
for pipeline in render_pipelines.pipelines.iter_mut() {
|
for pipeline in render_pipelines.pipelines.iter_mut() {
|
||||||
pipeline.specialization.sample_count = msaa.samples;
|
pipeline.specialization.sample_count = msaa.samples;
|
||||||
// TODO: move these to mesh.rs?
|
if pipeline.dynamic_bindings_generation
|
||||||
|
!= render_pipelines.bindings.dynamic_bindings_generation()
|
||||||
|
{
|
||||||
|
pipeline.specialization.dynamic_bindings = render_pipelines
|
||||||
|
.bindings
|
||||||
|
.iter_dynamic_bindings()
|
||||||
|
.map(|name| name.to_string())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
pipeline.dynamic_bindings_generation =
|
||||||
|
render_pipelines.bindings.dynamic_bindings_generation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for render_pipeline in render_pipelines.pipelines.iter() {
|
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
||||||
|
let render_resource_bindings = &mut [
|
||||||
|
&mut render_pipelines.bindings,
|
||||||
|
&mut render_resource_bindings,
|
||||||
|
];
|
||||||
draw_context
|
draw_context
|
||||||
.set_pipeline(
|
.set_pipeline(
|
||||||
&mut draw,
|
&mut draw,
|
||||||
@ -112,13 +130,7 @@ pub fn draw_render_pipelines_system(
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
draw_context
|
draw_context
|
||||||
.set_bind_groups_from_bindings(
|
.set_bind_groups_from_bindings(&mut draw, render_resource_bindings)
|
||||||
&mut draw,
|
|
||||||
&mut [
|
|
||||||
&mut render_pipelines.bindings,
|
|
||||||
&mut render_resource_bindings,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
draw_context
|
draw_context
|
||||||
.set_vertex_buffers_from_bindings(&mut draw, &[&render_pipelines.bindings])
|
.set_vertex_buffers_from_bindings(&mut draw, &[&render_pipelines.bindings])
|
||||||
|
@ -35,6 +35,13 @@ impl RenderResourceBinding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_dynamic_buffer(&self) -> bool {
|
||||||
|
matches!(self, RenderResourceBinding::Buffer {
|
||||||
|
dynamic_index: Some(_),
|
||||||
|
..
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_sampler(&self) -> Option<SamplerId> {
|
pub fn get_sampler(&self) -> Option<SamplerId> {
|
||||||
if let RenderResourceBinding::Sampler(sampler) = self {
|
if let RenderResourceBinding::Sampler(sampler) = self {
|
||||||
Some(*sampler)
|
Some(*sampler)
|
||||||
@ -103,7 +110,7 @@ pub enum BindGroupStatus {
|
|||||||
// PERF: if the bindings are scoped to a specific pipeline layout, then names could be replaced with indices here for a perf boost
|
// PERF: if the bindings are scoped to a specific pipeline layout, then names could be replaced with indices here for a perf boost
|
||||||
#[derive(Eq, PartialEq, Debug, Default, Clone)]
|
#[derive(Eq, PartialEq, Debug, Default, Clone)]
|
||||||
pub struct RenderResourceBindings {
|
pub struct RenderResourceBindings {
|
||||||
bindings: HashMap<String, RenderResourceBinding>,
|
pub bindings: HashMap<String, RenderResourceBinding>,
|
||||||
/// A Buffer that contains all attributes a mesh has defined
|
/// A Buffer that contains all attributes a mesh has defined
|
||||||
pub vertex_attribute_buffer: Option<BufferId>,
|
pub vertex_attribute_buffer: Option<BufferId>,
|
||||||
/// A Buffer that is filled with zeros that will be used for attributes required by the shader, but undefined by the mesh.
|
/// A Buffer that is filled with zeros that will be used for attributes required by the shader, but undefined by the mesh.
|
||||||
@ -112,6 +119,7 @@ pub struct RenderResourceBindings {
|
|||||||
bind_groups: HashMap<BindGroupId, BindGroup>,
|
bind_groups: HashMap<BindGroupId, BindGroup>,
|
||||||
bind_group_descriptors: HashMap<BindGroupDescriptorId, Option<BindGroupId>>,
|
bind_group_descriptors: HashMap<BindGroupDescriptorId, Option<BindGroupId>>,
|
||||||
dirty_bind_groups: HashSet<BindGroupId>,
|
dirty_bind_groups: HashSet<BindGroupId>,
|
||||||
|
dynamic_bindings_generation: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderResourceBindings {
|
impl RenderResourceBindings {
|
||||||
@ -124,9 +132,17 @@ impl RenderResourceBindings {
|
|||||||
self.bindings.insert(name.to_string(), binding);
|
self.bindings.insert(name.to_string(), binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The current "generation" of dynamic bindings. This number increments every time a dynamic binding changes
|
||||||
|
pub fn dynamic_bindings_generation(&self) -> usize {
|
||||||
|
self.dynamic_bindings_generation
|
||||||
|
}
|
||||||
|
|
||||||
fn try_set_dirty(&mut self, name: &str, binding: &RenderResourceBinding) {
|
fn try_set_dirty(&mut self, name: &str, binding: &RenderResourceBinding) {
|
||||||
if let Some(current_binding) = self.bindings.get(name) {
|
if let Some(current_binding) = self.bindings.get(name) {
|
||||||
if current_binding != binding {
|
if current_binding != binding {
|
||||||
|
if current_binding.is_dynamic_buffer() {
|
||||||
|
self.dynamic_bindings_generation += 1;
|
||||||
|
}
|
||||||
// TODO: this is crude. we shouldn't need to invalidate all bind groups
|
// TODO: this is crude. we shouldn't need to invalidate all bind groups
|
||||||
for id in self.bind_groups.keys() {
|
for id in self.bind_groups.keys() {
|
||||||
self.dirty_bind_groups.insert(*id);
|
self.dirty_bind_groups.insert(*id);
|
||||||
@ -236,6 +252,18 @@ impl RenderResourceBindings {
|
|||||||
|
|
||||||
Some(bind_group_builder.finish())
|
Some(bind_group_builder.finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn iter_dynamic_bindings(&self) -> impl Iterator<Item = &str> {
|
||||||
|
self.bindings
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, binding)| {
|
||||||
|
matches!(binding, RenderResourceBinding::Buffer {
|
||||||
|
dynamic_index: Some(_),
|
||||||
|
..
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map(|(name, _)| name.as_str())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
pipeline::{BindGroupDescriptorId, PipelineDescriptor},
|
pipeline::{BindGroupDescriptorId, PipelineDescriptor, PipelineLayout},
|
||||||
renderer::{BindGroup, BufferId, BufferInfo, RenderResourceId, SamplerId, TextureId},
|
renderer::{BindGroup, BufferId, BufferInfo, RenderResourceId, SamplerId, TextureId},
|
||||||
shader::Shader,
|
shader::{Shader, ShaderLayout, ShaderStages},
|
||||||
texture::{SamplerDescriptor, TextureDescriptor},
|
texture::{SamplerDescriptor, TextureDescriptor},
|
||||||
};
|
};
|
||||||
use bevy_asset::{Asset, Assets, Handle, HandleUntyped};
|
use bevy_asset::{Asset, Assets, Handle, HandleUntyped};
|
||||||
@ -60,6 +60,34 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
|
|||||||
bind_group: &BindGroup,
|
bind_group: &BindGroup,
|
||||||
);
|
);
|
||||||
fn clear_bind_groups(&self);
|
fn clear_bind_groups(&self);
|
||||||
|
/// Reflects the pipeline layout from its shaders.
|
||||||
|
///
|
||||||
|
/// If `bevy_conventions` is true, it will be assumed that the shader follows "bevy shader conventions". These allow
|
||||||
|
/// richer reflection, such as inferred Vertex Buffer names and inferred instancing.
|
||||||
|
///
|
||||||
|
/// If `dynamic_bindings` has values, shader uniforms will be set to "dynamic" if there is a matching binding in the list
|
||||||
|
///
|
||||||
|
/// If `vertex_buffer_descriptors` is set, the pipeline's vertex buffers
|
||||||
|
/// will inherit their layouts from global descriptors, otherwise the layout will be assumed to be complete / local.
|
||||||
|
fn reflect_pipeline_layout(
|
||||||
|
&self,
|
||||||
|
shaders: &Assets<Shader>,
|
||||||
|
shader_stages: &ShaderStages,
|
||||||
|
enforce_bevy_conventions: bool,
|
||||||
|
) -> PipelineLayout {
|
||||||
|
// TODO: maybe move this default implementation to PipelineLayout?
|
||||||
|
let mut shader_layouts: Vec<ShaderLayout> = shader_stages
|
||||||
|
.iter()
|
||||||
|
.map(|handle| {
|
||||||
|
shaders
|
||||||
|
.get(&handle)
|
||||||
|
.unwrap()
|
||||||
|
.reflect_layout(enforce_bevy_conventions)
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
PipelineLayout::from_shader_layouts(&mut shader_layouts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl dyn RenderResourceContext {
|
impl dyn RenderResourceContext {
|
||||||
|
@ -6,7 +6,7 @@ use bevy_asset::Handle;
|
|||||||
use bevy_ecs::Bundle;
|
use bevy_ecs::Bundle;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
mesh::Mesh,
|
mesh::Mesh,
|
||||||
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
|
pipeline::{RenderPipeline, RenderPipelines},
|
||||||
prelude::Draw,
|
prelude::Draw,
|
||||||
render_graph::base::MainPass,
|
render_graph::base::MainPass,
|
||||||
};
|
};
|
||||||
@ -28,23 +28,8 @@ impl Default for SpriteComponents {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
mesh: QUAD_HANDLE,
|
mesh: QUAD_HANDLE,
|
||||||
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::specialized(
|
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
|
||||||
SPRITE_PIPELINE_HANDLE,
|
SPRITE_PIPELINE_HANDLE,
|
||||||
PipelineSpecialization {
|
|
||||||
dynamic_bindings: vec![
|
|
||||||
// Transform
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 2,
|
|
||||||
binding: 0,
|
|
||||||
},
|
|
||||||
// Sprite
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 2,
|
|
||||||
binding: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)]),
|
)]),
|
||||||
draw: Draw {
|
draw: Draw {
|
||||||
is_transparent: true,
|
is_transparent: true,
|
||||||
@ -79,23 +64,8 @@ pub struct SpriteSheetComponents {
|
|||||||
impl Default for SpriteSheetComponents {
|
impl Default for SpriteSheetComponents {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::specialized(
|
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
|
||||||
SPRITE_SHEET_PIPELINE_HANDLE,
|
SPRITE_SHEET_PIPELINE_HANDLE,
|
||||||
PipelineSpecialization {
|
|
||||||
dynamic_bindings: vec![
|
|
||||||
// Transform
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 2,
|
|
||||||
binding: 0,
|
|
||||||
},
|
|
||||||
// TextureAtlasSprite
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 2,
|
|
||||||
binding: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)]),
|
)]),
|
||||||
draw: Draw {
|
draw: Draw {
|
||||||
is_transparent: true,
|
is_transparent: true,
|
||||||
|
@ -11,7 +11,7 @@ use bevy_render::{
|
|||||||
camera::{Camera, OrthographicProjection, VisibleEntities, WindowOrigin},
|
camera::{Camera, OrthographicProjection, VisibleEntities, WindowOrigin},
|
||||||
draw::Draw,
|
draw::Draw,
|
||||||
mesh::Mesh,
|
mesh::Mesh,
|
||||||
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
|
pipeline::{RenderPipeline, RenderPipelines},
|
||||||
};
|
};
|
||||||
use bevy_sprite::{ColorMaterial, QUAD_HANDLE};
|
use bevy_sprite::{ColorMaterial, QUAD_HANDLE};
|
||||||
use bevy_transform::prelude::{GlobalTransform, Transform};
|
use bevy_transform::prelude::{GlobalTransform, Transform};
|
||||||
@ -32,23 +32,8 @@ impl Default for NodeComponents {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
NodeComponents {
|
NodeComponents {
|
||||||
mesh: QUAD_HANDLE,
|
mesh: QUAD_HANDLE,
|
||||||
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::specialized(
|
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
|
||||||
UI_PIPELINE_HANDLE,
|
UI_PIPELINE_HANDLE,
|
||||||
PipelineSpecialization {
|
|
||||||
dynamic_bindings: vec![
|
|
||||||
// Transform
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 0,
|
|
||||||
},
|
|
||||||
// Node_size
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)]),
|
)]),
|
||||||
node: Default::default(),
|
node: Default::default(),
|
||||||
style: Default::default(),
|
style: Default::default(),
|
||||||
@ -78,23 +63,8 @@ impl Default for ImageComponents {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
ImageComponents {
|
ImageComponents {
|
||||||
mesh: QUAD_HANDLE,
|
mesh: QUAD_HANDLE,
|
||||||
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::specialized(
|
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
|
||||||
UI_PIPELINE_HANDLE,
|
UI_PIPELINE_HANDLE,
|
||||||
PipelineSpecialization {
|
|
||||||
dynamic_bindings: vec![
|
|
||||||
// Transform
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 0,
|
|
||||||
},
|
|
||||||
// Node_size
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)]),
|
)]),
|
||||||
node: Default::default(),
|
node: Default::default(),
|
||||||
image: Default::default(),
|
image: Default::default(),
|
||||||
@ -158,23 +128,8 @@ impl Default for ButtonComponents {
|
|||||||
ButtonComponents {
|
ButtonComponents {
|
||||||
button: Button,
|
button: Button,
|
||||||
mesh: QUAD_HANDLE,
|
mesh: QUAD_HANDLE,
|
||||||
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::specialized(
|
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
|
||||||
UI_PIPELINE_HANDLE,
|
UI_PIPELINE_HANDLE,
|
||||||
PipelineSpecialization {
|
|
||||||
dynamic_bindings: vec![
|
|
||||||
// Transform
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 0,
|
|
||||||
},
|
|
||||||
// Node_size
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)]),
|
)]),
|
||||||
interaction: Default::default(),
|
interaction: Default::default(),
|
||||||
focus_policy: Default::default(),
|
focus_policy: Default::default(),
|
||||||
|
@ -2,7 +2,7 @@ use bevy::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
render::{
|
render::{
|
||||||
mesh::{shape, VertexAttributeValues},
|
mesh::{shape, VertexAttributeValues},
|
||||||
pipeline::{DynamicBinding, PipelineDescriptor, PipelineSpecialization, RenderPipeline},
|
pipeline::{PipelineDescriptor, RenderPipeline},
|
||||||
render_graph::{base, AssetRenderResourcesNode, RenderGraph},
|
render_graph::{base, AssetRenderResourcesNode, RenderGraph},
|
||||||
renderer::RenderResources,
|
renderer::RenderResources,
|
||||||
shader::{ShaderStage, ShaderStages},
|
shader::{ShaderStage, ShaderStages},
|
||||||
@ -129,19 +129,8 @@ fn setup(
|
|||||||
// cube
|
// cube
|
||||||
.spawn(MeshComponents {
|
.spawn(MeshComponents {
|
||||||
mesh: meshes.add(cube_with_vertex_colors), // use our cube with vertex colors
|
mesh: meshes.add(cube_with_vertex_colors), // use our cube with vertex colors
|
||||||
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::specialized(
|
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
|
||||||
pipeline_handle,
|
pipeline_handle,
|
||||||
// NOTE: in the future you wont need to manually declare dynamic bindings
|
|
||||||
PipelineSpecialization {
|
|
||||||
dynamic_bindings: vec![
|
|
||||||
// Transform
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)]),
|
)]),
|
||||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
|
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -2,7 +2,7 @@ use bevy::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
render::{
|
render::{
|
||||||
mesh::shape,
|
mesh::shape,
|
||||||
pipeline::{DynamicBinding, PipelineDescriptor, PipelineSpecialization, RenderPipeline},
|
pipeline::{PipelineDescriptor, RenderPipeline},
|
||||||
render_graph::{base, AssetRenderResourcesNode, RenderGraph},
|
render_graph::{base, AssetRenderResourcesNode, RenderGraph},
|
||||||
renderer::RenderResources,
|
renderer::RenderResources,
|
||||||
shader::{ShaderStage, ShaderStages},
|
shader::{ShaderStage, ShaderStages},
|
||||||
@ -85,24 +85,8 @@ fn setup(
|
|||||||
// cube
|
// cube
|
||||||
.spawn(MeshComponents {
|
.spawn(MeshComponents {
|
||||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||||
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::specialized(
|
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
|
||||||
pipeline_handle,
|
pipeline_handle,
|
||||||
// NOTE: in the future you wont need to manually declare dynamic bindings
|
|
||||||
PipelineSpecialization {
|
|
||||||
dynamic_bindings: vec![
|
|
||||||
// Transform
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 0,
|
|
||||||
},
|
|
||||||
// MyMaterial_color
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)]),
|
)]),
|
||||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
|
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -2,7 +2,7 @@ use bevy::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
render::{
|
render::{
|
||||||
mesh::shape,
|
mesh::shape,
|
||||||
pipeline::{DynamicBinding, PipelineDescriptor, PipelineSpecialization, RenderPipeline},
|
pipeline::{PipelineDescriptor, RenderPipeline},
|
||||||
render_graph::{base, AssetRenderResourcesNode, RenderGraph},
|
render_graph::{base, AssetRenderResourcesNode, RenderGraph},
|
||||||
renderer::RenderResources,
|
renderer::RenderResources,
|
||||||
shader::{asset_shader_defs_system, ShaderDefs, ShaderStage, ShaderStages},
|
shader::{asset_shader_defs_system, ShaderDefs, ShaderStage, ShaderStages},
|
||||||
@ -106,24 +106,8 @@ fn setup(
|
|||||||
// cube
|
// cube
|
||||||
.spawn(MeshComponents {
|
.spawn(MeshComponents {
|
||||||
mesh: cube_handle.clone(),
|
mesh: cube_handle.clone(),
|
||||||
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::specialized(
|
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
|
||||||
pipeline_handle.clone(),
|
pipeline_handle.clone(),
|
||||||
// NOTE: in the future you wont need to manually declare dynamic bindings
|
|
||||||
PipelineSpecialization {
|
|
||||||
dynamic_bindings: vec![
|
|
||||||
// Transform
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 0,
|
|
||||||
},
|
|
||||||
// MyMaterial_color
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)]),
|
)]),
|
||||||
transform: Transform::from_translation(Vec3::new(-2.0, 0.0, 0.0)),
|
transform: Transform::from_translation(Vec3::new(-2.0, 0.0, 0.0)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -132,24 +116,8 @@ fn setup(
|
|||||||
// cube
|
// cube
|
||||||
.spawn(MeshComponents {
|
.spawn(MeshComponents {
|
||||||
mesh: cube_handle,
|
mesh: cube_handle,
|
||||||
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::specialized(
|
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
|
||||||
pipeline_handle,
|
pipeline_handle,
|
||||||
// NOTE: in the future you wont need to manually declare dynamic bindings
|
|
||||||
PipelineSpecialization {
|
|
||||||
dynamic_bindings: vec![
|
|
||||||
// Transform
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 0,
|
|
||||||
},
|
|
||||||
// MyMaterial_color
|
|
||||||
DynamicBinding {
|
|
||||||
bind_group: 1,
|
|
||||||
binding: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)]),
|
)]),
|
||||||
transform: Transform::from_translation(Vec3::new(2.0, 0.0, 0.0)),
|
transform: Transform::from_translation(Vec3::new(2.0, 0.0, 0.0)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
Loading…
Reference in New Issue
Block a user