Fix bind group errors when prepasses are enabled.

This commit is contained in:
Robin KAY 2023-11-22 00:57:07 +00:00
parent 878fecf5a6
commit bf2385f167
5 changed files with 63 additions and 44 deletions

View File

@ -1,4 +1,4 @@
use bevy::pbr::{DrawMesh, SetMeshBindGroup, SetMeshViewBindGroup}; use bevy::pbr::{DrawMesh, SetMeshBindGroup};
use bevy::prelude::*; use bevy::prelude::*;
use bevy::render::render_asset::RenderAssets; use bevy::render::render_asset::RenderAssets;
use bevy::render::render_phase::{DrawFunctions, RenderPhase, SetItemPipeline}; use bevy::render::render_phase::{DrawFunctions, RenderPhase, SetItemPipeline};
@ -16,10 +16,9 @@ use crate::OutlineRenderLayers;
pub(crate) type DrawStencil = ( pub(crate) type DrawStencil = (
SetItemPipeline, SetItemPipeline,
SetMeshViewBindGroup<0>, SetOutlineViewBindGroup<0>,
SetMeshBindGroup<1>, SetMeshBindGroup<1>,
SetOutlineViewBindGroup<2>, SetOutlineStencilBindGroup<2>,
SetOutlineStencilBindGroup<3>,
DrawMesh, DrawMesh,
); );
@ -87,10 +86,9 @@ pub(crate) fn queue_outline_stencil_mesh(
pub(crate) type DrawOutline = ( pub(crate) type DrawOutline = (
SetItemPipeline, SetItemPipeline,
SetMeshViewBindGroup<0>, SetOutlineViewBindGroup<0>,
SetMeshBindGroup<1>, SetMeshBindGroup<1>,
SetOutlineViewBindGroup<2>, SetOutlineVolumeBindGroup<2>,
SetOutlineVolumeBindGroup<3>,
DrawMesh, DrawMesh,
); );

View File

@ -11,7 +11,7 @@ struct OutlineFragmentUniform {
}; };
#ifdef VOLUME #ifdef VOLUME
@group(3) @binding(1) @group(2) @binding(1)
var<uniform> fstage: OutlineFragmentUniform; var<uniform> fstage: OutlineFragmentUniform;
#endif #endif

View File

@ -42,14 +42,14 @@ struct OutlineVertexUniform {
@group(0) @binding(0) @group(0) @binding(0)
var<uniform> view: View; var<uniform> view: View;
@group(0) @binding(1)
var<uniform> view_uniform: OutlineViewUniform;
#import bevy_pbr::mesh_bindings #import bevy_pbr::mesh_bindings
#import bevy_pbr::skinning #import bevy_pbr::skinning
#import bevy_pbr::morph #import bevy_pbr::morph
@group(2) @binding(0) @group(2) @binding(0)
var<uniform> view_uniform: OutlineViewUniform;
@group(3) @binding(0)
var<uniform> vstage: OutlineVertexUniform; var<uniform> vstage: OutlineVertexUniform;
#ifdef MORPH_TARGETS #ifdef MORPH_TARGETS

View File

@ -4,8 +4,7 @@ use bevy::ecs::query::QueryItem;
use bevy::ecs::system::lifetimeless::Read; use bevy::ecs::system::lifetimeless::Read;
use bevy::ecs::system::SystemParamItem; use bevy::ecs::system::SystemParamItem;
use bevy::pbr::{ use bevy::pbr::{
setup_morph_and_skinning_defs, MeshFlags, MeshPipelineKey, MeshPipelineViewLayoutKey, setup_morph_and_skinning_defs, MeshFlags, MeshPipelineKey, MeshTransforms, MeshUniform,
MeshTransforms, MeshUniform,
}; };
use bevy::prelude::*; use bevy::prelude::*;
use bevy::render::batching::GetBatchData; use bevy::render::batching::GetBatchData;
@ -13,13 +12,13 @@ use bevy::render::render_resource::{
BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BlendState, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BlendState,
BufferBindingType, BufferSize, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState, BufferBindingType, BufferSize, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState,
DepthStencilState, Face, FragmentState, FrontFace, MultisampleState, PolygonMode, DepthStencilState, Face, FragmentState, FrontFace, MultisampleState, PolygonMode,
PrimitiveState, PrimitiveTopology, ShaderDefVal, ShaderSize, ShaderStages, StencilState, PrimitiveState, PrimitiveTopology, ShaderDefVal, ShaderSize, ShaderStages, ShaderType,
TextureFormat, VertexState, StencilState, TextureFormat, VertexState,
}; };
use bevy::render::renderer::RenderDevice; use bevy::render::renderer::RenderDevice;
use bevy::render::settings::WgpuSettings; use bevy::render::settings::WgpuSettings;
use bevy::render::texture::BevyDefault; use bevy::render::texture::BevyDefault;
use bevy::render::view::ViewTarget; use bevy::render::view::{ViewTarget, ViewUniform};
use bevy::{ use bevy::{
pbr::MeshPipeline, pbr::MeshPipeline,
render::{ render::{
@ -172,16 +171,28 @@ impl FromWorld for OutlinePipeline {
let outline_view_bind_group_layout = let outline_view_bind_group_layout =
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: Some("outline_view_bind_group_layout"), label: Some("outline_view_bind_group_layout"),
entries: &[BindGroupLayoutEntry { entries: &[
binding: 0, BindGroupLayoutEntry {
visibility: ShaderStages::VERTEX, binding: 0,
ty: BindingType::Buffer { visibility: ShaderStages::VERTEX,
ty: BufferBindingType::Uniform, ty: BindingType::Buffer {
has_dynamic_offset: true, ty: BufferBindingType::Uniform,
min_binding_size: BufferSize::new(OutlineViewUniform::SHADER_SIZE.get()), has_dynamic_offset: true,
min_binding_size: Some(ViewUniform::min_size()),
},
count: None,
}, },
count: None, BindGroupLayoutEntry {
}], binding: 1,
visibility: ShaderStages::VERTEX,
ty: BindingType::Buffer {
ty: BufferBindingType::Uniform,
has_dynamic_offset: true,
min_binding_size: Some(OutlineViewUniform::min_size()),
},
count: None,
},
],
}); });
let outline_volume_bind_group_layout = let outline_volume_bind_group_layout =
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
@ -254,14 +265,7 @@ impl SpecializedMeshPipeline for OutlinePipeline {
buffer_attrs.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0)); buffer_attrs.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));
} }
let mut bind_layouts = vec![self let mut bind_layouts = vec![self.outline_view_bind_group_layout.clone()];
.mesh_pipeline
.get_view_layout(if key.msaa() == Msaa::Off {
MeshPipelineViewLayoutKey::empty()
} else {
MeshPipelineViewLayoutKey::MULTISAMPLED
})
.clone()];
bind_layouts.push(setup_morph_and_skinning_defs( bind_layouts.push(setup_morph_and_skinning_defs(
&self.mesh_pipeline.mesh_layouts, &self.mesh_pipeline.mesh_layouts,
@ -272,7 +276,6 @@ impl SpecializedMeshPipeline for OutlinePipeline {
&mut buffer_attrs, &mut buffer_attrs,
)); ));
bind_layouts.push(self.outline_view_bind_group_layout.clone());
let cull_mode; let cull_mode;
if key.depth_mode() == DepthMode::Flat { if key.depth_mode() == DepthMode::Flat {
let val = ShaderDefVal::from("FLAT_DEPTH"); let val = ShaderDefVal::from("FLAT_DEPTH");

View File

@ -1,3 +1,4 @@
use bevy::ecs::query::ROQueryItem;
use bevy::ecs::system::lifetimeless::{Read, SRes}; use bevy::ecs::system::lifetimeless::{Read, SRes};
use bevy::ecs::system::SystemParamItem; use bevy::ecs::system::SystemParamItem;
use bevy::prelude::*; use bevy::prelude::*;
@ -8,7 +9,7 @@ use bevy::render::render_phase::{
use bevy::render::render_resource::ShaderType; use bevy::render::render_resource::ShaderType;
use bevy::render::render_resource::{BindGroup, BindGroupEntry}; use bevy::render::render_resource::{BindGroup, BindGroupEntry};
use bevy::render::renderer::RenderDevice; use bevy::render::renderer::RenderDevice;
use bevy::render::view::RenderLayers; use bevy::render::view::{RenderLayers, ViewUniformOffset, ViewUniforms};
use bevy::render::Extract; use bevy::render::Extract;
use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline}; use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline};
@ -53,16 +54,26 @@ pub(crate) fn prepare_outline_view_bind_group(
mut commands: Commands, mut commands: Commands,
render_device: Res<RenderDevice>, render_device: Res<RenderDevice>,
outline_pipeline: Res<OutlinePipeline>, outline_pipeline: Res<OutlinePipeline>,
view_uniforms: Res<ComponentUniforms<OutlineViewUniform>>, core_view_uniforms: Res<ViewUniforms>,
outline_view_uniforms: Res<ComponentUniforms<OutlineViewUniform>>,
) { ) {
if let Some(view_binding) = view_uniforms.binding() { if let (Some(core_view_binding), Some(outline_view_binding)) = (
core_view_uniforms.uniforms.binding(),
outline_view_uniforms.binding(),
) {
let bind_group = render_device.create_bind_group( let bind_group = render_device.create_bind_group(
"outline_view_bind_group", "outline_view_bind_group",
&outline_pipeline.outline_view_bind_group_layout, &outline_pipeline.outline_view_bind_group_layout,
&[BindGroupEntry { &[
binding: 0, BindGroupEntry {
resource: view_binding.clone(), binding: 0,
}], resource: core_view_binding.clone(),
},
BindGroupEntry {
binding: 1,
resource: outline_view_binding.clone(),
},
],
); );
commands.insert_resource(OutlineViewBindGroup { bind_group }); commands.insert_resource(OutlineViewBindGroup { bind_group });
} }
@ -71,17 +82,24 @@ pub(crate) fn prepare_outline_view_bind_group(
pub(crate) struct SetOutlineViewBindGroup<const I: usize>(); pub(crate) struct SetOutlineViewBindGroup<const I: usize>();
impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetOutlineViewBindGroup<I> { impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetOutlineViewBindGroup<I> {
type ViewWorldQuery = Read<DynamicUniformIndex<OutlineViewUniform>>; type ViewWorldQuery = (
Read<ViewUniformOffset>,
Read<DynamicUniformIndex<OutlineViewUniform>>,
);
type ItemWorldQuery = (); type ItemWorldQuery = ();
type Param = SRes<OutlineViewBindGroup>; type Param = SRes<OutlineViewBindGroup>;
fn render<'w>( fn render<'w>(
_item: &P, _item: &P,
view_data: &DynamicUniformIndex<OutlineViewUniform>, (core_view_data, outline_view_data): ROQueryItem<'w, Self::ViewWorldQuery>,
_entity_data: (), _entity_data: (),
bind_group: SystemParamItem<'w, '_, Self::Param>, bind_group: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>, pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult { ) -> RenderCommandResult {
pass.set_bind_group(I, &bind_group.into_inner().bind_group, &[view_data.index()]); pass.set_bind_group(
I,
&bind_group.into_inner().bind_group,
&[core_view_data.offset, outline_view_data.index()],
);
RenderCommandResult::Success RenderCommandResult::Success
} }
} }