Merge branch 'main' into gridouter
This commit is contained in:
commit
cd4c2a4c4d
@ -7,8 +7,8 @@
|
||||
}
|
||||
#import bevy_core_pipeline::tonemapping::tone_mapping
|
||||
|
||||
@group(2) @binding(0) var my_array_texture: texture_2d_array<f32>;
|
||||
@group(2) @binding(1) var my_array_texture_sampler: sampler;
|
||||
@group(3) @binding(0) var my_array_texture: texture_2d_array<f32>;
|
||||
@group(3) @binding(1) var my_array_texture_sampler: sampler;
|
||||
|
||||
@fragment
|
||||
fn fragment(
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
view_transformations::position_world_to_clip
|
||||
}
|
||||
|
||||
@group(2) @binding(0) var texture: texture_2d<f32>;
|
||||
@group(2) @binding(1) var texture_sampler: sampler;
|
||||
@group(3) @binding(0) var texture: texture_2d<f32>;
|
||||
@group(3) @binding(1) var texture_sampler: sampler;
|
||||
|
||||
struct Vertex {
|
||||
@builtin(instance_index) instance_index: u32,
|
||||
|
||||
@ -15,12 +15,12 @@ struct MaterialBindings {
|
||||
}
|
||||
|
||||
#ifdef BINDLESS
|
||||
@group(2) @binding(0) var<storage> materials: array<MaterialBindings>;
|
||||
@group(2) @binding(10) var<storage> material_color: binding_array<Color>;
|
||||
@group(3) @binding(0) var<storage> materials: array<MaterialBindings>;
|
||||
@group(3) @binding(10) var<storage> material_color: binding_array<Color>;
|
||||
#else // BINDLESS
|
||||
@group(2) @binding(0) var<uniform> material_color: Color;
|
||||
@group(2) @binding(1) var material_color_texture: texture_2d<f32>;
|
||||
@group(2) @binding(2) var material_color_sampler: sampler;
|
||||
@group(3) @binding(0) var<uniform> material_color: Color;
|
||||
@group(3) @binding(1) var material_color_texture: texture_2d<f32>;
|
||||
@group(3) @binding(2) var material_color_sampler: sampler;
|
||||
#endif // BINDLESS
|
||||
|
||||
@fragment
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
#import bevy_pbr::forward_io::VertexOutput
|
||||
|
||||
#ifdef CUBEMAP_ARRAY
|
||||
@group(2) @binding(0) var base_color_texture: texture_cube_array<f32>;
|
||||
@group(3) @binding(0) var base_color_texture: texture_cube_array<f32>;
|
||||
#else
|
||||
@group(2) @binding(0) var base_color_texture: texture_cube<f32>;
|
||||
@group(3) @binding(0) var base_color_texture: texture_cube<f32>;
|
||||
#endif
|
||||
|
||||
@group(2) @binding(1) var base_color_sampler: sampler;
|
||||
@group(3) @binding(1) var base_color_sampler: sampler;
|
||||
|
||||
@fragment
|
||||
fn fragment(
|
||||
|
||||
@ -3,10 +3,10 @@ layout(location = 0) in vec2 v_Uv;
|
||||
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
|
||||
layout(set = 2, binding = 0) uniform vec4 CustomMaterial_color;
|
||||
layout(set = 3, binding = 0) uniform vec4 CustomMaterial_color;
|
||||
|
||||
layout(set = 2, binding = 1) uniform texture2D CustomMaterial_texture;
|
||||
layout(set = 2, binding = 2) uniform sampler CustomMaterial_sampler;
|
||||
layout(set = 3, binding = 1) uniform texture2D CustomMaterial_texture;
|
||||
layout(set = 3, binding = 2) uniform sampler CustomMaterial_sampler;
|
||||
|
||||
// wgsl modules can be imported and used in glsl
|
||||
// FIXME - this doesn't work any more ...
|
||||
|
||||
@ -25,9 +25,9 @@ struct Mesh {
|
||||
};
|
||||
|
||||
#ifdef PER_OBJECT_BUFFER_BATCH_SIZE
|
||||
layout(set = 1, binding = 0) uniform Mesh Meshes[#{PER_OBJECT_BUFFER_BATCH_SIZE}];
|
||||
layout(set = 2, binding = 0) uniform Mesh Meshes[#{PER_OBJECT_BUFFER_BATCH_SIZE}];
|
||||
#else
|
||||
layout(set = 1, binding = 0) readonly buffer _Meshes {
|
||||
layout(set = 2, binding = 0) readonly buffer _Meshes {
|
||||
Mesh Meshes[];
|
||||
};
|
||||
#endif // PER_OBJECT_BUFFER_BATCH_SIZE
|
||||
|
||||
@ -10,7 +10,7 @@ struct CustomMaterial {
|
||||
time: vec4<f32>,
|
||||
}
|
||||
|
||||
@group(2) @binding(0) var<uniform> material: CustomMaterial;
|
||||
@group(3) @binding(0) var<uniform> material: CustomMaterial;
|
||||
|
||||
@fragment
|
||||
fn fragment(
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
// we can import items from shader modules in the assets folder with a quoted path
|
||||
#import "shaders/custom_material_import.wgsl"::COLOR_MULTIPLIER
|
||||
|
||||
@group(2) @binding(0) var<uniform> material_color: vec4<f32>;
|
||||
@group(2) @binding(1) var material_color_texture: texture_2d<f32>;
|
||||
@group(2) @binding(2) var material_color_sampler: sampler;
|
||||
@group(3) @binding(0) var<uniform> material_color: vec4<f32>;
|
||||
@group(3) @binding(1) var material_color_texture: texture_2d<f32>;
|
||||
@group(3) @binding(2) var material_color_sampler: sampler;
|
||||
|
||||
@fragment
|
||||
fn fragment(
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
utils::coords_to_viewport_uv,
|
||||
}
|
||||
|
||||
@group(2) @binding(0) var texture: texture_2d<f32>;
|
||||
@group(2) @binding(1) var texture_sampler: sampler;
|
||||
@group(3) @binding(0) var texture: texture_2d<f32>;
|
||||
@group(3) @binding(1) var texture_sampler: sampler;
|
||||
|
||||
@fragment
|
||||
fn fragment(
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
struct CustomMaterial {
|
||||
color: vec4<f32>,
|
||||
};
|
||||
@group(2) @binding(0) var<uniform> material: CustomMaterial;
|
||||
@group(3) @binding(0) var<uniform> material: CustomMaterial;
|
||||
|
||||
struct Vertex {
|
||||
@builtin(instance_index) instance_index: u32,
|
||||
|
||||
@ -19,7 +19,7 @@ struct MyExtendedMaterial {
|
||||
quantize_steps: u32,
|
||||
}
|
||||
|
||||
@group(2) @binding(100)
|
||||
@group(3) @binding(100)
|
||||
var<uniform> my_extended_material: MyExtendedMaterial;
|
||||
|
||||
@fragment
|
||||
|
||||
@ -42,19 +42,19 @@ struct ExampleBindlessExtendedMaterial {
|
||||
|
||||
// The indices of the bindless resources in the bindless resource arrays, for
|
||||
// the `ExampleBindlessExtension` fields.
|
||||
@group(2) @binding(100) var<storage> example_extended_material_indices:
|
||||
@group(3) @binding(100) var<storage> example_extended_material_indices:
|
||||
array<ExampleBindlessExtendedMaterialIndices>;
|
||||
// An array that holds the `ExampleBindlessExtendedMaterial` plain old data,
|
||||
// indexed by `ExampleBindlessExtendedMaterialIndices.material`.
|
||||
@group(2) @binding(101) var<storage> example_extended_material:
|
||||
@group(3) @binding(101) var<storage> example_extended_material:
|
||||
array<ExampleBindlessExtendedMaterial>;
|
||||
|
||||
#else // BINDLESS
|
||||
|
||||
// In non-bindless mode, we simply use a uniform for the plain old data.
|
||||
@group(2) @binding(50) var<uniform> example_extended_material: ExampleBindlessExtendedMaterial;
|
||||
@group(2) @binding(51) var modulate_texture: texture_2d<f32>;
|
||||
@group(2) @binding(52) var modulate_sampler: sampler;
|
||||
@group(3) @binding(50) var<uniform> example_extended_material: ExampleBindlessExtendedMaterial;
|
||||
@group(3) @binding(51) var modulate_texture: texture_2d<f32>;
|
||||
@group(3) @binding(52) var modulate_sampler: sampler;
|
||||
|
||||
#endif // BINDLESS
|
||||
|
||||
|
||||
@ -1,22 +1,22 @@
|
||||
#import bevy_pbr::forward_io::VertexOutput
|
||||
|
||||
@group(2) @binding(0) var test_texture_1d: texture_1d<f32>;
|
||||
@group(2) @binding(1) var test_texture_1d_sampler: sampler;
|
||||
@group(3) @binding(0) var test_texture_1d: texture_1d<f32>;
|
||||
@group(3) @binding(1) var test_texture_1d_sampler: sampler;
|
||||
|
||||
@group(2) @binding(2) var test_texture_2d: texture_2d<f32>;
|
||||
@group(2) @binding(3) var test_texture_2d_sampler: sampler;
|
||||
@group(3) @binding(2) var test_texture_2d: texture_2d<f32>;
|
||||
@group(3) @binding(3) var test_texture_2d_sampler: sampler;
|
||||
|
||||
@group(2) @binding(4) var test_texture_2d_array: texture_2d_array<f32>;
|
||||
@group(2) @binding(5) var test_texture_2d_array_sampler: sampler;
|
||||
@group(3) @binding(4) var test_texture_2d_array: texture_2d_array<f32>;
|
||||
@group(3) @binding(5) var test_texture_2d_array_sampler: sampler;
|
||||
|
||||
@group(2) @binding(6) var test_texture_cube: texture_cube<f32>;
|
||||
@group(2) @binding(7) var test_texture_cube_sampler: sampler;
|
||||
@group(3) @binding(6) var test_texture_cube: texture_cube<f32>;
|
||||
@group(3) @binding(7) var test_texture_cube_sampler: sampler;
|
||||
|
||||
@group(2) @binding(8) var test_texture_cube_array: texture_cube_array<f32>;
|
||||
@group(2) @binding(9) var test_texture_cube_array_sampler: sampler;
|
||||
@group(3) @binding(8) var test_texture_cube_array: texture_cube_array<f32>;
|
||||
@group(3) @binding(9) var test_texture_cube_array_sampler: sampler;
|
||||
|
||||
@group(2) @binding(10) var test_texture_3d: texture_3d<f32>;
|
||||
@group(2) @binding(11) var test_texture_3d_sampler: sampler;
|
||||
@group(3) @binding(10) var test_texture_3d: texture_3d<f32>;
|
||||
@group(3) @binding(11) var test_texture_3d_sampler: sampler;
|
||||
|
||||
@fragment
|
||||
fn fragment(in: VertexOutput) {}
|
||||
|
||||
@ -12,7 +12,7 @@ struct VoxelVisualizationIrradianceVolumeInfo {
|
||||
intensity: f32,
|
||||
}
|
||||
|
||||
@group(2) @binding(100)
|
||||
@group(3) @binding(100)
|
||||
var<uniform> irradiance_volume_info: VoxelVisualizationIrradianceVolumeInfo;
|
||||
|
||||
@fragment
|
||||
|
||||
@ -4,7 +4,7 @@ struct LineMaterial {
|
||||
color: vec4<f32>,
|
||||
};
|
||||
|
||||
@group(2) @binding(0) var<uniform> material: LineMaterial;
|
||||
@group(3) @binding(0) var<uniform> material: LineMaterial;
|
||||
|
||||
@fragment
|
||||
fn fragment(
|
||||
|
||||
@ -4,7 +4,7 @@ struct CustomMaterial {
|
||||
color: vec4<f32>,
|
||||
};
|
||||
|
||||
@group(2) @binding(0) var<uniform> material: CustomMaterial;
|
||||
@group(3) @binding(0) var<uniform> material: CustomMaterial;
|
||||
|
||||
@fragment
|
||||
fn fragment(
|
||||
|
||||
@ -11,7 +11,7 @@ struct ShowPrepassSettings {
|
||||
padding_1: u32,
|
||||
padding_2: u32,
|
||||
}
|
||||
@group(2) @binding(0) var<uniform> settings: ShowPrepassSettings;
|
||||
@group(3) @binding(0) var<uniform> settings: ShowPrepassSettings;
|
||||
|
||||
@fragment
|
||||
fn fragment(
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
view_transformations::position_world_to_clip
|
||||
}
|
||||
|
||||
@group(2) @binding(0) var<storage, read> colors: array<vec4<f32>, 5>;
|
||||
@group(3) @binding(0) var<storage, read> colors: array<vec4<f32>, 5>;
|
||||
|
||||
struct Vertex {
|
||||
@builtin(instance_index) instance_index: u32,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#import bevy_pbr::forward_io::VertexOutput
|
||||
|
||||
@group(2) @binding(0) var textures: binding_array<texture_2d<f32>>;
|
||||
@group(2) @binding(1) var nearest_sampler: sampler;
|
||||
@group(3) @binding(0) var textures: binding_array<texture_2d<f32>>;
|
||||
@group(3) @binding(1) var nearest_sampler: sampler;
|
||||
// We can also have array of samplers
|
||||
// var samplers: binding_array<sampler>;
|
||||
|
||||
|
||||
@ -23,9 +23,9 @@ struct WaterSettings {
|
||||
|
||||
@group(0) @binding(1) var<uniform> globals: Globals;
|
||||
|
||||
@group(2) @binding(100) var water_normals_texture: texture_2d<f32>;
|
||||
@group(2) @binding(101) var water_normals_sampler: sampler;
|
||||
@group(2) @binding(102) var<uniform> water_settings: WaterSettings;
|
||||
@group(3) @binding(100) var water_normals_texture: texture_2d<f32>;
|
||||
@group(3) @binding(101) var water_normals_sampler: sampler;
|
||||
@group(3) @binding(102) var<uniform> water_settings: WaterSettings;
|
||||
|
||||
// Samples a single octave of noise and returns the resulting normal.
|
||||
fn sample_noise_octave(uv: vec2<f32>, strength: f32) -> vec3<f32> {
|
||||
|
||||
@ -20,7 +20,7 @@ serde = { version = "1.0", features = [
|
||||
], default-features = false, optional = true }
|
||||
thiserror = { version = "2", default-features = false }
|
||||
derive_more = { version = "2", default-features = false, features = ["from"] }
|
||||
wgpu-types = { version = "24", default-features = false, optional = true }
|
||||
wgpu-types = { version = "25", default-features = false, optional = true }
|
||||
encase = { version = "0.10", default-features = false, optional = true }
|
||||
|
||||
[features]
|
||||
|
||||
@ -123,8 +123,7 @@ impl SpecializedRenderPipeline for LineGizmoPipeline {
|
||||
.mesh_pipeline
|
||||
.get_view_layout(key.view_key.into())
|
||||
.clone();
|
||||
|
||||
let layout = vec![view_layout, self.uniform_layout.clone()];
|
||||
let layout = vec![view_layout.main_layout.clone(), self.uniform_layout.clone()];
|
||||
|
||||
let fragment_entry_point = match key.line_style {
|
||||
GizmoLineStyle::Solid => "fragment_solid",
|
||||
@ -220,8 +219,7 @@ impl SpecializedRenderPipeline for LineJointGizmoPipeline {
|
||||
.mesh_pipeline
|
||||
.get_view_layout(key.view_key.into())
|
||||
.clone();
|
||||
|
||||
let layout = vec![view_layout, self.uniform_layout.clone()];
|
||||
let layout = vec![view_layout.main_layout.clone(), self.uniform_layout.clone()];
|
||||
|
||||
if key.joints == GizmoLineJoint::None {
|
||||
error!("There is no entry point for line joints with GizmoLineJoints::None. Please consider aborting the drawing process before reaching this stage.");
|
||||
|
||||
@ -63,7 +63,7 @@ image = { version = "0.25.2", default-features = false }
|
||||
# misc
|
||||
bitflags = { version = "2.3", features = ["serde"] }
|
||||
bytemuck = { version = "1.5" }
|
||||
wgpu-types = { version = "24", default-features = false }
|
||||
wgpu-types = { version = "25", default-features = false }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
thiserror = { version = "2", default-features = false }
|
||||
futures-lite = "2.0.1"
|
||||
|
||||
@ -27,7 +27,7 @@ bevy_platform = { path = "../bevy_platform", version = "0.17.0-dev", default-fea
|
||||
# other
|
||||
bitflags = { version = "2.3", features = ["serde"] }
|
||||
bytemuck = { version = "1.5" }
|
||||
wgpu-types = { version = "24", default-features = false }
|
||||
wgpu-types = { version = "25", default-features = false }
|
||||
serde = { version = "1", default-features = false, features = [
|
||||
"derive",
|
||||
], optional = true }
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
enable dual_source_blending;
|
||||
|
||||
#import bevy_pbr::atmosphere::{
|
||||
types::{Atmosphere, AtmosphereSettings},
|
||||
bindings::{atmosphere, view, atmosphere_transforms},
|
||||
@ -19,9 +21,11 @@
|
||||
#endif
|
||||
|
||||
struct RenderSkyOutput {
|
||||
@location(0) inscattering: vec4<f32>,
|
||||
#ifdef DUAL_SOURCE_BLENDING
|
||||
@location(0) @second_blend_source transmittance: vec4<f32>,
|
||||
@location(0) @blend_src(0) inscattering: vec4<f32>,
|
||||
@location(0) @blend_src(1) transmittance: vec4<f32>,
|
||||
#else
|
||||
@location(0) inscattering: vec4<f32>,
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
}
|
||||
#import bevy_render::maths::project_onto
|
||||
|
||||
@group(2) @binding(200)
|
||||
@group(3) @binding(200)
|
||||
var<uniform> inv_depth_fade_factor: f32;
|
||||
|
||||
struct ForwardDecalInformation {
|
||||
|
||||
@ -29,7 +29,7 @@ struct PbrDeferredLightingDepthId {
|
||||
_webgl2_padding_2: f32,
|
||||
#endif
|
||||
}
|
||||
@group(1) @binding(0)
|
||||
@group(2) @binding(0)
|
||||
var<uniform> depth_id: PbrDeferredLightingDepthId;
|
||||
|
||||
@vertex
|
||||
|
||||
@ -184,9 +184,9 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let bind_group_1 = render_context.render_device().create_bind_group(
|
||||
"deferred_lighting_layout_group_1",
|
||||
&deferred_lighting_layout.bind_group_layout_1,
|
||||
let bind_group_2 = render_context.render_device().create_bind_group(
|
||||
"deferred_lighting_layout_group_2",
|
||||
&deferred_lighting_layout.bind_group_layout_2,
|
||||
&BindGroupEntries::single(deferred_lighting_pass_id_binding),
|
||||
);
|
||||
|
||||
@ -208,7 +208,7 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode {
|
||||
render_pass.set_render_pipeline(pipeline);
|
||||
render_pass.set_bind_group(
|
||||
0,
|
||||
&mesh_view_bind_group.value,
|
||||
&mesh_view_bind_group.main,
|
||||
&[
|
||||
view_uniform_offset.offset,
|
||||
view_lights_offset.offset,
|
||||
@ -218,7 +218,8 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode {
|
||||
**view_environment_map_offset,
|
||||
],
|
||||
);
|
||||
render_pass.set_bind_group(1, &bind_group_1, &[]);
|
||||
render_pass.set_bind_group(1, &mesh_view_bind_group.binding_array, &[]);
|
||||
render_pass.set_bind_group(2, &bind_group_2, &[]);
|
||||
render_pass.draw(0..3, 0..1);
|
||||
|
||||
Ok(())
|
||||
@ -228,7 +229,7 @@ impl ViewNode for DeferredOpaquePass3dPbrLightingNode {
|
||||
#[derive(Resource)]
|
||||
pub struct DeferredLightingLayout {
|
||||
mesh_pipeline: MeshPipeline,
|
||||
bind_group_layout_1: BindGroupLayout,
|
||||
bind_group_layout_2: BindGroupLayout,
|
||||
deferred_lighting_shader: Handle<Shader>,
|
||||
}
|
||||
|
||||
@ -346,11 +347,13 @@ impl SpecializedRenderPipeline for DeferredLightingLayout {
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||
shader_defs.push("SIXTEEN_BYTE_ALIGNMENT".into());
|
||||
|
||||
let layout = self.mesh_pipeline.get_view_layout(key.into());
|
||||
RenderPipelineDescriptor {
|
||||
label: Some("deferred_lighting_pipeline".into()),
|
||||
layout: vec![
|
||||
self.mesh_pipeline.get_view_layout(key.into()).clone(),
|
||||
self.bind_group_layout_1.clone(),
|
||||
layout.main_layout.clone(),
|
||||
layout.binding_array_layout.clone(),
|
||||
self.bind_group_layout_2.clone(),
|
||||
],
|
||||
vertex: VertexState {
|
||||
shader: self.deferred_lighting_shader.clone(),
|
||||
@ -408,7 +411,7 @@ impl FromWorld for DeferredLightingLayout {
|
||||
);
|
||||
Self {
|
||||
mesh_pipeline: world.resource::<MeshPipeline>().clone(),
|
||||
bind_group_layout_1: layout,
|
||||
bind_group_layout_2: layout,
|
||||
deferred_lighting_shader: load_embedded_asset!(world, "deferred_lighting.wgsl"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,8 +152,8 @@ fn shader_ref(path: PathBuf) -> ShaderRef {
|
||||
const MESHLET_VISIBILITY_BUFFER_RESOLVE_SHADER_HANDLE: Handle<Shader> =
|
||||
weak_handle!("69187376-3dea-4d0f-b3f5-185bde63d6a2");
|
||||
|
||||
pub const TONEMAPPING_LUT_TEXTURE_BINDING_INDEX: u32 = 26;
|
||||
pub const TONEMAPPING_LUT_SAMPLER_BINDING_INDEX: u32 = 27;
|
||||
pub const TONEMAPPING_LUT_TEXTURE_BINDING_INDEX: u32 = 18;
|
||||
pub const TONEMAPPING_LUT_SAMPLER_BINDING_INDEX: u32 = 19;
|
||||
|
||||
/// Sets up the entire PBR infrastructure of bevy.
|
||||
pub struct PbrPlugin {
|
||||
|
||||
@ -3,11 +3,11 @@
|
||||
#import bevy_pbr::mesh_bindings::mesh
|
||||
|
||||
#ifdef MULTIPLE_LIGHTMAPS_IN_ARRAY
|
||||
@group(1) @binding(4) var lightmaps_textures: binding_array<texture_2d<f32>, 4>;
|
||||
@group(1) @binding(5) var lightmaps_samplers: binding_array<sampler, 4>;
|
||||
@group(2) @binding(4) var lightmaps_textures: binding_array<texture_2d<f32>, 4>;
|
||||
@group(2) @binding(5) var lightmaps_samplers: binding_array<sampler, 4>;
|
||||
#else // MULTIPLE_LIGHTMAPS_IN_ARRAY
|
||||
@group(1) @binding(4) var lightmaps_texture: texture_2d<f32>;
|
||||
@group(1) @binding(5) var lightmaps_sampler: sampler;
|
||||
@group(2) @binding(4) var lightmaps_texture: texture_2d<f32>;
|
||||
@group(2) @binding(5) var lightmaps_sampler: sampler;
|
||||
#endif // MULTIPLE_LIGHTMAPS_IN_ARRAY
|
||||
|
||||
// Samples the lightmap, if any, and returns indirect illumination from it.
|
||||
|
||||
@ -120,9 +120,9 @@ use tracing::error;
|
||||
/// In WGSL shaders, the material's binding would look like this:
|
||||
///
|
||||
/// ```wgsl
|
||||
/// @group(2) @binding(0) var<uniform> color: vec4<f32>;
|
||||
/// @group(2) @binding(1) var color_texture: texture_2d<f32>;
|
||||
/// @group(2) @binding(2) var color_sampler: sampler;
|
||||
/// @group(3) @binding(0) var<uniform> color: vec4<f32>;
|
||||
/// @group(3) @binding(1) var color_texture: texture_2d<f32>;
|
||||
/// @group(3) @binding(2) var color_sampler: sampler;
|
||||
/// ```
|
||||
pub trait Material: Asset + AsBindGroup + Clone + Sized {
|
||||
/// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader
|
||||
@ -501,7 +501,7 @@ where
|
||||
descriptor.fragment.as_mut().unwrap().shader = fragment_shader.clone();
|
||||
}
|
||||
|
||||
descriptor.layout.insert(2, self.material_layout.clone());
|
||||
descriptor.layout.insert(3, self.material_layout.clone());
|
||||
|
||||
M::specialize(self, &mut descriptor, layout, key)?;
|
||||
|
||||
@ -544,8 +544,9 @@ impl<M: Material> FromWorld for MaterialPipeline<M> {
|
||||
type DrawMaterial<M> = (
|
||||
SetItemPipeline,
|
||||
SetMeshViewBindGroup<0>,
|
||||
SetMeshBindGroup<1>,
|
||||
SetMaterialBindGroup<M, 2>,
|
||||
SetMeshViewBindingArrayBindGroup<1>,
|
||||
SetMeshBindGroup<2>,
|
||||
SetMaterialBindGroup<M, 3>,
|
||||
DrawMesh,
|
||||
);
|
||||
|
||||
|
||||
@ -186,13 +186,17 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass<M: Material>(
|
||||
let mut shader_defs = material_fragment.shader_defs;
|
||||
shader_defs.push("MESHLET_MESH_MATERIAL_PASS".into());
|
||||
|
||||
let layout = mesh_pipeline.get_view_layout(view_key.into());
|
||||
let layout = vec![
|
||||
layout.main_layout.clone(),
|
||||
layout.binding_array_layout.clone(),
|
||||
resource_manager.material_shade_bind_group_layout.clone(),
|
||||
material_pipeline.material_layout.clone(),
|
||||
];
|
||||
|
||||
let pipeline_descriptor = RenderPipelineDescriptor {
|
||||
label: material_pipeline_descriptor.label,
|
||||
layout: vec![
|
||||
mesh_pipeline.get_view_layout(view_key.into()).clone(),
|
||||
resource_manager.material_shade_bind_group_layout.clone(),
|
||||
material_pipeline.material_layout.clone(),
|
||||
],
|
||||
layout,
|
||||
push_constant_ranges: vec![],
|
||||
vertex: VertexState {
|
||||
shader: MESHLET_MESH_MATERIAL_SHADER_HANDLE,
|
||||
|
||||
@ -106,7 +106,7 @@ impl ViewNode for MeshletMainOpaquePass3dNode {
|
||||
|
||||
render_pass.set_bind_group(
|
||||
0,
|
||||
&mesh_view_bind_group.value,
|
||||
&mesh_view_bind_group.main,
|
||||
&[
|
||||
view_uniform_offset.offset,
|
||||
view_lights_offset.offset,
|
||||
|
||||
@ -149,15 +149,15 @@ fn get_meshlet_vertex_position(meshlet: ptr<function, Meshlet>, vertex_id: u32)
|
||||
#endif
|
||||
|
||||
#ifdef MESHLET_MESH_MATERIAL_PASS
|
||||
@group(1) @binding(0) var meshlet_visibility_buffer: texture_storage_2d<r64uint, read>;
|
||||
@group(1) @binding(1) var<storage, read> meshlet_cluster_meshlet_ids: array<u32>; // Per cluster
|
||||
@group(1) @binding(2) var<storage, read> meshlets: array<Meshlet>; // Per meshlet
|
||||
@group(1) @binding(3) var<storage, read> meshlet_indices: array<u32>; // Many per meshlet
|
||||
@group(1) @binding(4) var<storage, read> meshlet_vertex_positions: array<u32>; // Many per meshlet
|
||||
@group(1) @binding(5) var<storage, read> meshlet_vertex_normals: array<u32>; // Many per meshlet
|
||||
@group(1) @binding(6) var<storage, read> meshlet_vertex_uvs: array<vec2<f32>>; // Many per meshlet
|
||||
@group(1) @binding(7) var<storage, read> meshlet_cluster_instance_ids: array<u32>; // Per cluster
|
||||
@group(1) @binding(8) var<storage, read> meshlet_instance_uniforms: array<Mesh>; // Per entity instance
|
||||
@group(2) @binding(0) var meshlet_visibility_buffer: texture_storage_2d<r64uint, read>;
|
||||
@group(2) @binding(1) var<storage, read> meshlet_cluster_meshlet_ids: array<u32>; // Per cluster
|
||||
@group(2) @binding(2) var<storage, read> meshlets: array<Meshlet>; // Per meshlet
|
||||
@group(2) @binding(3) var<storage, read> meshlet_indices: array<u32>; // Many per meshlet
|
||||
@group(2) @binding(4) var<storage, read> meshlet_vertex_positions: array<u32>; // Many per meshlet
|
||||
@group(2) @binding(5) var<storage, read> meshlet_vertex_normals: array<u32>; // Many per meshlet
|
||||
@group(2) @binding(6) var<storage, read> meshlet_vertex_uvs: array<vec2<f32>>; // Many per meshlet
|
||||
@group(2) @binding(7) var<storage, read> meshlet_cluster_instance_ids: array<u32>; // Per cluster
|
||||
@group(2) @binding(8) var<storage, read> meshlet_instance_uniforms: array<Mesh>; // Per entity instance
|
||||
|
||||
// TODO: Load only twice, instead of 3x in cases where you load 3 indices per thread?
|
||||
fn get_meshlet_vertex_id(index_id: u32) -> u32 {
|
||||
|
||||
@ -206,7 +206,7 @@ impl ResourceManager {
|
||||
visibility_buffer_raster_bind_group_layout: render_device.create_bind_group_layout(
|
||||
"meshlet_visibility_buffer_raster_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::all(),
|
||||
ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
|
||||
(
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
@ -225,7 +225,7 @@ impl ResourceManager {
|
||||
.create_bind_group_layout(
|
||||
"meshlet_visibility_buffer_raster_shadow_view_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::all(),
|
||||
ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
|
||||
(
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
|
||||
@ -95,7 +95,6 @@ where
|
||||
Render,
|
||||
prepare_prepass_view_bind_group::<M>.in_set(RenderSystems::PrepareBindGroups),
|
||||
)
|
||||
.init_resource::<PrepassViewBindGroup>()
|
||||
.init_resource::<SpecializedMeshPipelines<PrepassPipeline<M>>>()
|
||||
.allow_ambiguous_resource::<SpecializedMeshPipelines<PrepassPipeline<M>>>();
|
||||
}
|
||||
@ -105,7 +104,9 @@ where
|
||||
return;
|
||||
};
|
||||
|
||||
render_app.init_resource::<PrepassPipeline<M>>();
|
||||
render_app
|
||||
.init_resource::<PrepassPipeline<M>>()
|
||||
.init_resource::<PrepassViewBindGroup>();
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,6 +273,7 @@ pub struct PrepassPipelineInternal {
|
||||
pub view_layout_motion_vectors: BindGroupLayout,
|
||||
pub view_layout_no_motion_vectors: BindGroupLayout,
|
||||
pub mesh_layouts: MeshLayouts,
|
||||
pub empty_layout: BindGroupLayout,
|
||||
pub material_layout: BindGroupLayout,
|
||||
pub prepass_material_vertex_shader: Option<Handle<Shader>>,
|
||||
pub prepass_material_fragment_shader: Option<Handle<Shader>>,
|
||||
@ -381,6 +383,7 @@ impl<M: Material> FromWorld for PrepassPipeline<M> {
|
||||
skins_use_uniform_buffers: skin::skins_use_uniform_buffers(render_device),
|
||||
depth_clip_control_supported,
|
||||
binding_arrays_are_usable: binding_arrays_are_usable(render_device, render_adapter),
|
||||
empty_layout: render_device.create_bind_group_layout("prepass_empty_layout", &[]),
|
||||
};
|
||||
PrepassPipeline {
|
||||
internal,
|
||||
@ -425,13 +428,14 @@ impl PrepassPipelineInternal {
|
||||
layout: &MeshVertexBufferLayoutRef,
|
||||
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
|
||||
let mut shader_defs = shader_defs;
|
||||
let mut bind_group_layouts = vec![if mesh_key
|
||||
.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS)
|
||||
{
|
||||
self.view_layout_motion_vectors.clone()
|
||||
} else {
|
||||
self.view_layout_no_motion_vectors.clone()
|
||||
}];
|
||||
let mut bind_group_layouts = vec![
|
||||
if mesh_key.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS) {
|
||||
self.view_layout_motion_vectors.clone()
|
||||
} else {
|
||||
self.view_layout_no_motion_vectors.clone()
|
||||
},
|
||||
self.empty_layout.clone(),
|
||||
];
|
||||
let mut vertex_attributes = Vec::new();
|
||||
|
||||
// Let the shader code know that it's running in a prepass pipeline.
|
||||
@ -556,7 +560,7 @@ impl PrepassPipelineInternal {
|
||||
&mut vertex_attributes,
|
||||
self.skins_use_uniform_buffers,
|
||||
);
|
||||
bind_group_layouts.insert(1, bind_group);
|
||||
bind_group_layouts.insert(2, bind_group);
|
||||
let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?;
|
||||
// Setup prepass fragment targets - normals in slot 0 (or None if not needed), motion vectors in slot 1
|
||||
let mut targets = prepass_target_descriptors(
|
||||
@ -723,10 +727,29 @@ pub fn prepare_previous_view_uniforms(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Resource)]
|
||||
#[derive(Resource)]
|
||||
pub struct PrepassViewBindGroup {
|
||||
pub motion_vectors: Option<BindGroup>,
|
||||
pub no_motion_vectors: Option<BindGroup>,
|
||||
pub empty_bind_group: BindGroup,
|
||||
}
|
||||
|
||||
impl FromWorld for PrepassViewBindGroup {
|
||||
fn from_world(world: &mut World) -> Self {
|
||||
let pipeline = world.resource::<PrepassPipeline<StandardMaterial>>();
|
||||
|
||||
let render_device = world.resource::<RenderDevice>();
|
||||
let empty_bind_group = render_device.create_bind_group(
|
||||
"prepass_view_empty_bind_group",
|
||||
&pipeline.internal.empty_layout,
|
||||
&[],
|
||||
);
|
||||
PrepassViewBindGroup {
|
||||
motion_vectors: None,
|
||||
no_motion_vectors: None,
|
||||
empty_bind_group,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prepare_prepass_view_bind_group<M: Material>(
|
||||
@ -1284,7 +1307,26 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetPrepassViewBindGroup<
|
||||
);
|
||||
}
|
||||
}
|
||||
RenderCommandResult::Success
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SetPrepassViewEmptyBindGroup<const I: usize>;
|
||||
impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetPrepassViewEmptyBindGroup<I> {
|
||||
type Param = SRes<PrepassViewBindGroup>;
|
||||
type ViewQuery = ();
|
||||
type ItemQuery = ();
|
||||
|
||||
#[inline]
|
||||
fn render<'w>(
|
||||
_item: &P,
|
||||
_view: (),
|
||||
_entity: Option<()>,
|
||||
prepass_view_bind_group: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult {
|
||||
let prepass_view_bind_group = prepass_view_bind_group.into_inner();
|
||||
pass.set_bind_group(I, &prepass_view_bind_group.empty_bind_group, &[]);
|
||||
RenderCommandResult::Success
|
||||
}
|
||||
}
|
||||
@ -1292,7 +1334,8 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetPrepassViewBindGroup<
|
||||
pub type DrawPrepass<M> = (
|
||||
SetItemPipeline,
|
||||
SetPrepassViewBindGroup<0>,
|
||||
SetMeshBindGroup<1>,
|
||||
SetMaterialBindGroup<M, 2>,
|
||||
SetPrepassViewEmptyBindGroup<1>,
|
||||
SetMeshBindGroup<2>,
|
||||
SetMaterialBindGroup<M, 3>,
|
||||
DrawMesh,
|
||||
);
|
||||
|
||||
@ -1864,7 +1864,10 @@ impl MeshPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_view_layout(&self, layout_key: MeshPipelineViewLayoutKey) -> &BindGroupLayout {
|
||||
pub fn get_view_layout(
|
||||
&self,
|
||||
layout_key: MeshPipelineViewLayoutKey,
|
||||
) -> &MeshPipelineViewLayout {
|
||||
self.view_layouts.get_view_layout(layout_key)
|
||||
}
|
||||
}
|
||||
@ -2320,7 +2323,11 @@ impl SpecializedMeshPipeline for MeshPipeline {
|
||||
shader_defs.push("PBR_SPECULAR_TEXTURES_SUPPORTED".into());
|
||||
}
|
||||
|
||||
let mut bind_group_layout = vec![self.get_view_layout(key.into()).clone()];
|
||||
let bind_group_layout = self.get_view_layout(key.into());
|
||||
let mut bind_group_layout = vec![
|
||||
bind_group_layout.main_layout.clone(),
|
||||
bind_group_layout.binding_array_layout.clone(),
|
||||
];
|
||||
|
||||
if key.msaa_samples() > 1 {
|
||||
shader_defs.push("MULTISAMPLED".into());
|
||||
@ -2890,7 +2897,47 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshViewBindGroup<I>
|
||||
if let Some(layers_count_offset) = maybe_oit_layers_count_offset {
|
||||
offsets.push(layers_count_offset.offset);
|
||||
}
|
||||
pass.set_bind_group(I, &mesh_view_bind_group.value, &offsets);
|
||||
pass.set_bind_group(I, &mesh_view_bind_group.main, &offsets);
|
||||
|
||||
RenderCommandResult::Success
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SetMeshViewBindingArrayBindGroup<const I: usize>;
|
||||
impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshViewBindingArrayBindGroup<I> {
|
||||
type Param = ();
|
||||
type ViewQuery = (Read<MeshViewBindGroup>,);
|
||||
type ItemQuery = ();
|
||||
|
||||
#[inline]
|
||||
fn render<'w>(
|
||||
_item: &P,
|
||||
(mesh_view_bind_group,): ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
_entity: Option<()>,
|
||||
_: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult {
|
||||
pass.set_bind_group(I, &mesh_view_bind_group.binding_array, &[]);
|
||||
|
||||
RenderCommandResult::Success
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SetMeshViewEmptyBindGroup<const I: usize>;
|
||||
impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshViewEmptyBindGroup<I> {
|
||||
type Param = ();
|
||||
type ViewQuery = (Read<MeshViewBindGroup>,);
|
||||
type ItemQuery = ();
|
||||
|
||||
#[inline]
|
||||
fn render<'w>(
|
||||
_item: &P,
|
||||
(mesh_view_bind_group,): ROQueryItem<'w, '_, Self::ViewQuery>,
|
||||
_entity: Option<()>,
|
||||
_: SystemParamItem<'w, '_, Self::Param>,
|
||||
pass: &mut TrackedRenderPass<'w>,
|
||||
) -> RenderCommandResult {
|
||||
pass.set_bind_group(I, &mesh_view_bind_group.empty, &[]);
|
||||
|
||||
RenderCommandResult::Success
|
||||
}
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
|
||||
#ifndef MESHLET_MESH_MATERIAL_PASS
|
||||
#ifdef PER_OBJECT_BUFFER_BATCH_SIZE
|
||||
@group(1) @binding(0) var<uniform> mesh: array<Mesh, #{PER_OBJECT_BUFFER_BATCH_SIZE}u>;
|
||||
@group(2) @binding(0) var<uniform> mesh: array<Mesh, #{PER_OBJECT_BUFFER_BATCH_SIZE}u>;
|
||||
#else
|
||||
@group(1) @binding(0) var<storage> mesh: array<Mesh>;
|
||||
@group(2) @binding(0) var<storage> mesh: array<Mesh>;
|
||||
#endif // PER_OBJECT_BUFFER_BATCH_SIZE
|
||||
#endif // MESHLET_MESH_MATERIAL_PASS
|
||||
|
||||
@ -59,7 +59,9 @@ use {crate::MESH_PIPELINE_VIEW_LAYOUT_SAFE_MAX_TEXTURES, bevy_utils::once, traci
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MeshPipelineViewLayout {
|
||||
pub bind_group_layout: BindGroupLayout,
|
||||
pub main_layout: BindGroupLayout,
|
||||
pub binding_array_layout: BindGroupLayout,
|
||||
pub empty_layout: BindGroupLayout,
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
pub texture_count: usize,
|
||||
@ -213,7 +215,11 @@ fn layout_entries(
|
||||
layout_key: MeshPipelineViewLayoutKey,
|
||||
render_device: &RenderDevice,
|
||||
render_adapter: &RenderAdapter,
|
||||
) -> Vec<BindGroupLayoutEntry> {
|
||||
) -> [Vec<BindGroupLayoutEntry>; 2] {
|
||||
// EnvironmentMapLight
|
||||
let environment_map_entries =
|
||||
environment_map::get_bind_group_layout_entries(render_device, render_adapter);
|
||||
|
||||
let mut entries = DynamicBindGroupLayoutEntries::new_with_indices(
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
@ -325,45 +331,15 @@ fn layout_entries(
|
||||
16,
|
||||
texture_2d(TextureSampleType::Float { filterable: false }),
|
||||
),
|
||||
(17, environment_map_entries[3]),
|
||||
),
|
||||
);
|
||||
|
||||
// EnvironmentMapLight
|
||||
let environment_map_entries =
|
||||
environment_map::get_bind_group_layout_entries(render_device, render_adapter);
|
||||
entries = entries.extend_with_indices((
|
||||
(17, environment_map_entries[0]),
|
||||
(18, environment_map_entries[1]),
|
||||
(19, environment_map_entries[2]),
|
||||
(20, environment_map_entries[3]),
|
||||
));
|
||||
|
||||
// Irradiance volumes
|
||||
if IRRADIANCE_VOLUMES_ARE_USABLE {
|
||||
let irradiance_volume_entries =
|
||||
irradiance_volume::get_bind_group_layout_entries(render_device, render_adapter);
|
||||
entries = entries.extend_with_indices((
|
||||
(21, irradiance_volume_entries[0]),
|
||||
(22, irradiance_volume_entries[1]),
|
||||
));
|
||||
}
|
||||
|
||||
// Clustered decals
|
||||
if let Some(clustered_decal_entries) =
|
||||
decal::clustered::get_bind_group_layout_entries(render_device, render_adapter)
|
||||
{
|
||||
entries = entries.extend_with_indices((
|
||||
(23, clustered_decal_entries[0]),
|
||||
(24, clustered_decal_entries[1]),
|
||||
(25, clustered_decal_entries[2]),
|
||||
));
|
||||
}
|
||||
|
||||
// Tonemapping
|
||||
let tonemapping_lut_entries = get_lut_bind_group_layout_entries();
|
||||
entries = entries.extend_with_indices((
|
||||
(26, tonemapping_lut_entries[0]),
|
||||
(27, tonemapping_lut_entries[1]),
|
||||
(18, tonemapping_lut_entries[0]),
|
||||
(19, tonemapping_lut_entries[1]),
|
||||
));
|
||||
|
||||
// Prepass
|
||||
@ -373,7 +349,7 @@ fn layout_entries(
|
||||
{
|
||||
for (entry, binding) in prepass::get_bind_group_layout_entries(layout_key)
|
||||
.iter()
|
||||
.zip([28, 29, 30, 31])
|
||||
.zip([20, 21, 22, 23])
|
||||
{
|
||||
if let Some(entry) = entry {
|
||||
entries = entries.extend_with_indices(((binding as u32, *entry),));
|
||||
@ -384,10 +360,10 @@ fn layout_entries(
|
||||
// View Transmission Texture
|
||||
entries = entries.extend_with_indices((
|
||||
(
|
||||
32,
|
||||
24,
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
),
|
||||
(33, sampler(SamplerBindingType::Filtering)),
|
||||
(25, sampler(SamplerBindingType::Filtering)),
|
||||
));
|
||||
|
||||
// OIT
|
||||
@ -398,19 +374,47 @@ fn layout_entries(
|
||||
if is_oit_supported(render_adapter, render_device, false) {
|
||||
entries = entries.extend_with_indices((
|
||||
// oit_layers
|
||||
(34, storage_buffer_sized(false, None)),
|
||||
(26, storage_buffer_sized(false, None)),
|
||||
// oit_layer_ids,
|
||||
(35, storage_buffer_sized(false, None)),
|
||||
(27, storage_buffer_sized(false, None)),
|
||||
// oit_layer_count
|
||||
(
|
||||
36,
|
||||
28,
|
||||
uniform_buffer::<OrderIndependentTransparencySettings>(true),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
entries.to_vec()
|
||||
let mut binding_array_entries = DynamicBindGroupLayoutEntries::new(ShaderStages::FRAGMENT);
|
||||
binding_array_entries = binding_array_entries.extend_with_indices((
|
||||
(0, environment_map_entries[0]),
|
||||
(1, environment_map_entries[1]),
|
||||
(2, environment_map_entries[2]),
|
||||
));
|
||||
|
||||
// Irradiance volumes
|
||||
if IRRADIANCE_VOLUMES_ARE_USABLE {
|
||||
let irradiance_volume_entries =
|
||||
irradiance_volume::get_bind_group_layout_entries(render_device, render_adapter);
|
||||
binding_array_entries = binding_array_entries.extend_with_indices((
|
||||
(3, irradiance_volume_entries[0]),
|
||||
(4, irradiance_volume_entries[1]),
|
||||
));
|
||||
}
|
||||
|
||||
// Clustered decals
|
||||
if let Some(clustered_decal_entries) =
|
||||
decal::clustered::get_bind_group_layout_entries(render_device, render_adapter)
|
||||
{
|
||||
binding_array_entries = binding_array_entries.extend_with_indices((
|
||||
(5, clustered_decal_entries[0]),
|
||||
(6, clustered_decal_entries[1]),
|
||||
(7, clustered_decal_entries[2]),
|
||||
));
|
||||
}
|
||||
|
||||
[entries.to_vec(), binding_array_entries.to_vec()]
|
||||
}
|
||||
|
||||
/// Stores the view layouts for every combination of pipeline keys.
|
||||
@ -447,12 +451,21 @@ impl FromWorld for MeshPipelineViewLayouts {
|
||||
#[cfg(debug_assertions)]
|
||||
let texture_count: usize = entries
|
||||
.iter()
|
||||
.filter(|entry| matches!(entry.ty, BindingType::Texture { .. }))
|
||||
.flat_map(|e| {
|
||||
e.iter()
|
||||
.filter(|entry| matches!(entry.ty, BindingType::Texture { .. }))
|
||||
})
|
||||
.count();
|
||||
|
||||
MeshPipelineViewLayout {
|
||||
bind_group_layout: render_device
|
||||
.create_bind_group_layout(key.label().as_str(), &entries),
|
||||
main_layout: render_device
|
||||
.create_bind_group_layout(key.label().as_str(), &entries[0]),
|
||||
binding_array_layout: render_device.create_bind_group_layout(
|
||||
format!("{}_binding_array", key.label()).as_str(),
|
||||
&entries[1],
|
||||
),
|
||||
empty_layout: render_device
|
||||
.create_bind_group_layout(format!("{}_empty", key.label()).as_str(), &[]),
|
||||
#[cfg(debug_assertions)]
|
||||
texture_count,
|
||||
}
|
||||
@ -461,7 +474,10 @@ impl FromWorld for MeshPipelineViewLayouts {
|
||||
}
|
||||
|
||||
impl MeshPipelineViewLayouts {
|
||||
pub fn get_view_layout(&self, layout_key: MeshPipelineViewLayoutKey) -> &BindGroupLayout {
|
||||
pub fn get_view_layout(
|
||||
&self,
|
||||
layout_key: MeshPipelineViewLayoutKey,
|
||||
) -> &MeshPipelineViewLayout {
|
||||
let index = layout_key.bits() as usize;
|
||||
let layout = &self[index];
|
||||
|
||||
@ -471,7 +487,7 @@ impl MeshPipelineViewLayouts {
|
||||
once!(warn!("Too many textures in mesh pipeline view layout, this might cause us to hit `wgpu::Limits::max_sampled_textures_per_shader_stage` in some environments."));
|
||||
}
|
||||
|
||||
&layout.bind_group_layout
|
||||
layout
|
||||
}
|
||||
}
|
||||
|
||||
@ -496,12 +512,20 @@ pub fn generate_view_layouts(
|
||||
#[cfg(debug_assertions)]
|
||||
let texture_count: usize = entries
|
||||
.iter()
|
||||
.filter(|entry| matches!(entry.ty, BindingType::Texture { .. }))
|
||||
.flat_map(|e| {
|
||||
e.iter()
|
||||
.filter(|entry| matches!(entry.ty, BindingType::Texture { .. }))
|
||||
})
|
||||
.count();
|
||||
|
||||
MeshPipelineViewLayout {
|
||||
bind_group_layout: render_device
|
||||
.create_bind_group_layout(key.label().as_str(), &entries),
|
||||
main_layout: render_device.create_bind_group_layout(key.label().as_str(), &entries[0]),
|
||||
binding_array_layout: render_device.create_bind_group_layout(
|
||||
format!("{}_binding_array", key.label()).as_str(),
|
||||
&entries[1],
|
||||
),
|
||||
empty_layout: render_device
|
||||
.create_bind_group_layout(format!("{}_empty", key.label()).as_str(), &[]),
|
||||
#[cfg(debug_assertions)]
|
||||
texture_count,
|
||||
}
|
||||
@ -510,7 +534,9 @@ pub fn generate_view_layouts(
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct MeshViewBindGroup {
|
||||
pub value: BindGroup,
|
||||
pub main: BindGroup,
|
||||
pub binding_array: BindGroup,
|
||||
pub empty: BindGroup,
|
||||
}
|
||||
|
||||
pub fn prepare_mesh_view_bind_groups(
|
||||
@ -597,7 +623,7 @@ pub fn prepare_mesh_view_bind_groups(
|
||||
layout_key |= MeshPipelineViewLayoutKey::OIT_ENABLED;
|
||||
}
|
||||
|
||||
let layout = &mesh_pipeline.get_view_layout(layout_key);
|
||||
let layout = mesh_pipeline.get_view_layout(layout_key);
|
||||
|
||||
let mut entries = DynamicBindGroupEntries::new_with_indices((
|
||||
(0, view_binding.clone()),
|
||||
@ -626,6 +652,58 @@ pub fn prepare_mesh_view_bind_groups(
|
||||
(16, ssao_view),
|
||||
));
|
||||
|
||||
entries = entries.extend_with_indices(((17, environment_map_binding.clone()),));
|
||||
|
||||
let lut_bindings =
|
||||
get_lut_bindings(&images, &tonemapping_luts, tonemapping, &fallback_image);
|
||||
entries = entries.extend_with_indices(((18, lut_bindings.0), (19, lut_bindings.1)));
|
||||
|
||||
// When using WebGL, we can't have a depth texture with multisampling
|
||||
let prepass_bindings;
|
||||
if cfg!(any(not(feature = "webgl"), not(target_arch = "wasm32"))) || msaa.samples() == 1
|
||||
{
|
||||
prepass_bindings = prepass::get_bindings(prepass_textures);
|
||||
for (binding, index) in prepass_bindings
|
||||
.iter()
|
||||
.map(Option::as_ref)
|
||||
.zip([20, 21, 22, 23])
|
||||
.flat_map(|(b, i)| b.map(|b| (b, i)))
|
||||
{
|
||||
entries = entries.extend_with_indices(((index, binding),));
|
||||
}
|
||||
};
|
||||
|
||||
let transmission_view = transmission_texture
|
||||
.map(|transmission| &transmission.view)
|
||||
.unwrap_or(&fallback_image_zero.texture_view);
|
||||
|
||||
let transmission_sampler = transmission_texture
|
||||
.map(|transmission| &transmission.sampler)
|
||||
.unwrap_or(&fallback_image_zero.sampler);
|
||||
|
||||
entries =
|
||||
entries.extend_with_indices(((24, transmission_view), (25, transmission_sampler)));
|
||||
|
||||
if has_oit {
|
||||
if let (
|
||||
Some(oit_layers_binding),
|
||||
Some(oit_layer_ids_binding),
|
||||
Some(oit_settings_binding),
|
||||
) = (
|
||||
oit_buffers.layers.binding(),
|
||||
oit_buffers.layer_ids.binding(),
|
||||
oit_buffers.settings.binding(),
|
||||
) {
|
||||
entries = entries.extend_with_indices((
|
||||
(26, oit_layers_binding.clone()),
|
||||
(27, oit_layer_ids_binding.clone()),
|
||||
(28, oit_settings_binding.clone()),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let mut entries_binding_array = DynamicBindGroupEntries::new();
|
||||
|
||||
let environment_map_bind_group_entries = RenderViewEnvironmentMapBindGroupEntries::get(
|
||||
render_view_environment_maps,
|
||||
&images,
|
||||
@ -633,18 +711,16 @@ pub fn prepare_mesh_view_bind_groups(
|
||||
&render_device,
|
||||
&render_adapter,
|
||||
);
|
||||
|
||||
match environment_map_bind_group_entries {
|
||||
RenderViewEnvironmentMapBindGroupEntries::Single {
|
||||
diffuse_texture_view,
|
||||
specular_texture_view,
|
||||
sampler,
|
||||
} => {
|
||||
entries = entries.extend_with_indices((
|
||||
(17, diffuse_texture_view),
|
||||
(18, specular_texture_view),
|
||||
(19, sampler),
|
||||
(20, environment_map_binding.clone()),
|
||||
entries_binding_array = entries_binding_array.extend_with_indices((
|
||||
(0, diffuse_texture_view),
|
||||
(1, specular_texture_view),
|
||||
(2, sampler),
|
||||
));
|
||||
}
|
||||
RenderViewEnvironmentMapBindGroupEntries::Multiple {
|
||||
@ -652,11 +728,10 @@ pub fn prepare_mesh_view_bind_groups(
|
||||
ref specular_texture_views,
|
||||
sampler,
|
||||
} => {
|
||||
entries = entries.extend_with_indices((
|
||||
(17, diffuse_texture_views.as_slice()),
|
||||
(18, specular_texture_views.as_slice()),
|
||||
(19, sampler),
|
||||
(20, environment_map_binding.clone()),
|
||||
entries_binding_array = entries_binding_array.extend_with_indices((
|
||||
(0, diffuse_texture_views.as_slice()),
|
||||
(1, specular_texture_views.as_slice()),
|
||||
(2, sampler),
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -678,14 +753,15 @@ pub fn prepare_mesh_view_bind_groups(
|
||||
texture_view,
|
||||
sampler,
|
||||
}) => {
|
||||
entries = entries.extend_with_indices(((21, texture_view), (22, sampler)));
|
||||
entries_binding_array = entries_binding_array
|
||||
.extend_with_indices(((3, texture_view), (4, sampler)));
|
||||
}
|
||||
Some(RenderViewIrradianceVolumeBindGroupEntries::Multiple {
|
||||
ref texture_views,
|
||||
sampler,
|
||||
}) => {
|
||||
entries = entries
|
||||
.extend_with_indices(((21, texture_views.as_slice()), (22, sampler)));
|
||||
entries_binding_array = entries_binding_array
|
||||
.extend_with_indices(((3, texture_views.as_slice()), (4, sampler)));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
@ -701,76 +777,42 @@ pub fn prepare_mesh_view_bind_groups(
|
||||
|
||||
// Add the decal bind group entries.
|
||||
if let Some(ref render_view_decal_bind_group_entries) = decal_bind_group_entries {
|
||||
entries = entries.extend_with_indices((
|
||||
entries_binding_array = entries_binding_array.extend_with_indices((
|
||||
// `clustered_decals`
|
||||
(
|
||||
23,
|
||||
5,
|
||||
render_view_decal_bind_group_entries
|
||||
.decals
|
||||
.as_entire_binding(),
|
||||
),
|
||||
// `clustered_decal_textures`
|
||||
(
|
||||
24,
|
||||
6,
|
||||
render_view_decal_bind_group_entries
|
||||
.texture_views
|
||||
.as_slice(),
|
||||
),
|
||||
// `clustered_decal_sampler`
|
||||
(25, render_view_decal_bind_group_entries.sampler),
|
||||
(7, render_view_decal_bind_group_entries.sampler),
|
||||
));
|
||||
}
|
||||
|
||||
let lut_bindings =
|
||||
get_lut_bindings(&images, &tonemapping_luts, tonemapping, &fallback_image);
|
||||
entries = entries.extend_with_indices(((26, lut_bindings.0), (27, lut_bindings.1)));
|
||||
|
||||
// When using WebGL, we can't have a depth texture with multisampling
|
||||
let prepass_bindings;
|
||||
if cfg!(any(not(feature = "webgl"), not(target_arch = "wasm32"))) || msaa.samples() == 1
|
||||
{
|
||||
prepass_bindings = prepass::get_bindings(prepass_textures);
|
||||
for (binding, index) in prepass_bindings
|
||||
.iter()
|
||||
.map(Option::as_ref)
|
||||
.zip([28, 29, 30, 31])
|
||||
.flat_map(|(b, i)| b.map(|b| (b, i)))
|
||||
{
|
||||
entries = entries.extend_with_indices(((index, binding),));
|
||||
}
|
||||
};
|
||||
|
||||
let transmission_view = transmission_texture
|
||||
.map(|transmission| &transmission.view)
|
||||
.unwrap_or(&fallback_image_zero.texture_view);
|
||||
|
||||
let transmission_sampler = transmission_texture
|
||||
.map(|transmission| &transmission.sampler)
|
||||
.unwrap_or(&fallback_image_zero.sampler);
|
||||
|
||||
entries =
|
||||
entries.extend_with_indices(((32, transmission_view), (33, transmission_sampler)));
|
||||
|
||||
if has_oit {
|
||||
if let (
|
||||
Some(oit_layers_binding),
|
||||
Some(oit_layer_ids_binding),
|
||||
Some(oit_settings_binding),
|
||||
) = (
|
||||
oit_buffers.layers.binding(),
|
||||
oit_buffers.layer_ids.binding(),
|
||||
oit_buffers.settings.binding(),
|
||||
) {
|
||||
entries = entries.extend_with_indices((
|
||||
(34, oit_layers_binding.clone()),
|
||||
(35, oit_layer_ids_binding.clone()),
|
||||
(36, oit_settings_binding.clone()),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
commands.entity(entity).insert(MeshViewBindGroup {
|
||||
value: render_device.create_bind_group("mesh_view_bind_group", layout, &entries),
|
||||
main: render_device.create_bind_group(
|
||||
"mesh_view_bind_group",
|
||||
&layout.main_layout,
|
||||
&entries,
|
||||
),
|
||||
binding_array: render_device.create_bind_group(
|
||||
"mesh_view_bind_group_binding_array",
|
||||
&layout.binding_array_layout,
|
||||
&entries_binding_array,
|
||||
),
|
||||
empty: render_device.create_bind_group(
|
||||
"mesh_view_bind_group_empty",
|
||||
&layout.empty_layout,
|
||||
&[],
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,70 +50,70 @@ const VISIBILITY_RANGE_UNIFORM_BUFFER_SIZE: u32 = 64u;
|
||||
|
||||
@group(0) @binding(15) var<uniform> ssr_settings: types::ScreenSpaceReflectionsSettings;
|
||||
@group(0) @binding(16) var screen_space_ambient_occlusion_texture: texture_2d<f32>;
|
||||
|
||||
#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY
|
||||
@group(0) @binding(17) var diffuse_environment_maps: binding_array<texture_cube<f32>, 8u>;
|
||||
@group(0) @binding(18) var specular_environment_maps: binding_array<texture_cube<f32>, 8u>;
|
||||
#else
|
||||
@group(0) @binding(17) var diffuse_environment_map: texture_cube<f32>;
|
||||
@group(0) @binding(18) var specular_environment_map: texture_cube<f32>;
|
||||
#endif
|
||||
@group(0) @binding(19) var environment_map_sampler: sampler;
|
||||
@group(0) @binding(20) var<uniform> environment_map_uniform: types::EnvironmentMapUniform;
|
||||
|
||||
#ifdef IRRADIANCE_VOLUMES_ARE_USABLE
|
||||
#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY
|
||||
@group(0) @binding(21) var irradiance_volumes: binding_array<texture_3d<f32>, 8u>;
|
||||
#else
|
||||
@group(0) @binding(21) var irradiance_volume: texture_3d<f32>;
|
||||
#endif
|
||||
@group(0) @binding(22) var irradiance_volume_sampler: sampler;
|
||||
#endif
|
||||
|
||||
#ifdef CLUSTERED_DECALS_ARE_USABLE
|
||||
@group(0) @binding(23) var<storage> clustered_decals: types::ClusteredDecals;
|
||||
@group(0) @binding(24) var clustered_decal_textures: binding_array<texture_2d<f32>, 8u>;
|
||||
@group(0) @binding(25) var clustered_decal_sampler: sampler;
|
||||
#endif // CLUSTERED_DECALS_ARE_USABLE
|
||||
@group(0) @binding(17) var<uniform> environment_map_uniform: types::EnvironmentMapUniform;
|
||||
|
||||
// NB: If you change these, make sure to update `tonemapping_shared.wgsl` too.
|
||||
@group(0) @binding(26) var dt_lut_texture: texture_3d<f32>;
|
||||
@group(0) @binding(27) var dt_lut_sampler: sampler;
|
||||
@group(0) @binding(18) var dt_lut_texture: texture_3d<f32>;
|
||||
@group(0) @binding(19) var dt_lut_sampler: sampler;
|
||||
|
||||
#ifdef MULTISAMPLED
|
||||
#ifdef DEPTH_PREPASS
|
||||
@group(0) @binding(28) var depth_prepass_texture: texture_depth_multisampled_2d;
|
||||
@group(0) @binding(20) var depth_prepass_texture: texture_depth_multisampled_2d;
|
||||
#endif // DEPTH_PREPASS
|
||||
#ifdef NORMAL_PREPASS
|
||||
@group(0) @binding(29) var normal_prepass_texture: texture_multisampled_2d<f32>;
|
||||
@group(0) @binding(21) var normal_prepass_texture: texture_multisampled_2d<f32>;
|
||||
#endif // NORMAL_PREPASS
|
||||
#ifdef MOTION_VECTOR_PREPASS
|
||||
@group(0) @binding(30) var motion_vector_prepass_texture: texture_multisampled_2d<f32>;
|
||||
@group(0) @binding(22) var motion_vector_prepass_texture: texture_multisampled_2d<f32>;
|
||||
#endif // MOTION_VECTOR_PREPASS
|
||||
|
||||
#else // MULTISAMPLED
|
||||
|
||||
#ifdef DEPTH_PREPASS
|
||||
@group(0) @binding(28) var depth_prepass_texture: texture_depth_2d;
|
||||
@group(0) @binding(20) var depth_prepass_texture: texture_depth_2d;
|
||||
#endif // DEPTH_PREPASS
|
||||
#ifdef NORMAL_PREPASS
|
||||
@group(0) @binding(29) var normal_prepass_texture: texture_2d<f32>;
|
||||
@group(0) @binding(21) var normal_prepass_texture: texture_2d<f32>;
|
||||
#endif // NORMAL_PREPASS
|
||||
#ifdef MOTION_VECTOR_PREPASS
|
||||
@group(0) @binding(30) var motion_vector_prepass_texture: texture_2d<f32>;
|
||||
@group(0) @binding(22) var motion_vector_prepass_texture: texture_2d<f32>;
|
||||
#endif // MOTION_VECTOR_PREPASS
|
||||
|
||||
#endif // MULTISAMPLED
|
||||
|
||||
#ifdef DEFERRED_PREPASS
|
||||
@group(0) @binding(31) var deferred_prepass_texture: texture_2d<u32>;
|
||||
@group(0) @binding(23) var deferred_prepass_texture: texture_2d<u32>;
|
||||
#endif // DEFERRED_PREPASS
|
||||
|
||||
@group(0) @binding(32) var view_transmission_texture: texture_2d<f32>;
|
||||
@group(0) @binding(33) var view_transmission_sampler: sampler;
|
||||
@group(0) @binding(24) var view_transmission_texture: texture_2d<f32>;
|
||||
@group(0) @binding(25) var view_transmission_sampler: sampler;
|
||||
|
||||
#ifdef OIT_ENABLED
|
||||
@group(0) @binding(34) var<storage, read_write> oit_layers: array<vec2<u32>>;
|
||||
@group(0) @binding(35) var<storage, read_write> oit_layer_ids: array<atomic<i32>>;
|
||||
@group(0) @binding(36) var<uniform> oit_settings: types::OrderIndependentTransparencySettings;
|
||||
@group(0) @binding(26) var<storage, read_write> oit_layers: array<vec2<u32>>;
|
||||
@group(0) @binding(27) var<storage, read_write> oit_layer_ids: array<atomic<i32>>;
|
||||
@group(0) @binding(28) var<uniform> oit_settings: types::OrderIndependentTransparencySettings;
|
||||
#endif // OIT_ENABLED
|
||||
|
||||
#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY
|
||||
@group(1) @binding(0) var diffuse_environment_maps: binding_array<texture_cube<f32>, 8u>;
|
||||
@group(1) @binding(1) var specular_environment_maps: binding_array<texture_cube<f32>, 8u>;
|
||||
#else
|
||||
@group(1) @binding(0) var diffuse_environment_map: texture_cube<f32>;
|
||||
@group(1) @binding(1) var specular_environment_map: texture_cube<f32>;
|
||||
#endif
|
||||
@group(1) @binding(2) var environment_map_sampler: sampler;
|
||||
|
||||
#ifdef IRRADIANCE_VOLUMES_ARE_USABLE
|
||||
#ifdef MULTIPLE_LIGHT_PROBES_IN_ARRAY
|
||||
@group(1) @binding(3) var irradiance_volumes: binding_array<texture_3d<f32>, 8u>;
|
||||
#else
|
||||
@group(1) @binding(3) var irradiance_volume: texture_3d<f32>;
|
||||
#endif
|
||||
@group(1) @binding(4) var irradiance_volume_sampler: sampler;
|
||||
#endif
|
||||
|
||||
#ifdef CLUSTERED_DECALS_ARE_USABLE
|
||||
@group(1) @binding(5) var<storage> clustered_decals: types::ClusteredDecals;
|
||||
@group(1) @binding(6) var clustered_decal_textures: binding_array<texture_2d<f32>, 8u>;
|
||||
@group(1) @binding(7) var clustered_decal_sampler: sampler;
|
||||
#endif // CLUSTERED_DECALS_ARE_USABLE
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
|
||||
#import bevy_pbr::mesh_types::MorphWeights;
|
||||
|
||||
@group(1) @binding(2) var<uniform> morph_weights: MorphWeights;
|
||||
@group(1) @binding(3) var morph_targets: texture_3d<f32>;
|
||||
@group(1) @binding(7) var<uniform> prev_morph_weights: MorphWeights;
|
||||
@group(2) @binding(2) var<uniform> morph_weights: MorphWeights;
|
||||
@group(2) @binding(3) var morph_targets: texture_3d<f32>;
|
||||
@group(2) @binding(7) var<uniform> prev_morph_weights: MorphWeights;
|
||||
|
||||
// NOTE: Those are the "hardcoded" values found in `MorphAttributes` struct
|
||||
// in crates/bevy_render/src/mesh/morph/visitors.rs
|
||||
|
||||
@ -37,53 +37,53 @@ struct StandardMaterialBindings {
|
||||
specular_tint_sampler: u32, // 30
|
||||
}
|
||||
|
||||
@group(2) @binding(0) var<storage> material_indices: array<StandardMaterialBindings>;
|
||||
@group(2) @binding(10) var<storage> material_array: array<StandardMaterial>;
|
||||
@group(3) @binding(0) var<storage> material_indices: array<StandardMaterialBindings>;
|
||||
@group(3) @binding(10) var<storage> material_array: array<StandardMaterial>;
|
||||
|
||||
#else // BINDLESS
|
||||
|
||||
@group(2) @binding(0) var<uniform> material: StandardMaterial;
|
||||
@group(2) @binding(1) var base_color_texture: texture_2d<f32>;
|
||||
@group(2) @binding(2) var base_color_sampler: sampler;
|
||||
@group(2) @binding(3) var emissive_texture: texture_2d<f32>;
|
||||
@group(2) @binding(4) var emissive_sampler: sampler;
|
||||
@group(2) @binding(5) var metallic_roughness_texture: texture_2d<f32>;
|
||||
@group(2) @binding(6) var metallic_roughness_sampler: sampler;
|
||||
@group(2) @binding(7) var occlusion_texture: texture_2d<f32>;
|
||||
@group(2) @binding(8) var occlusion_sampler: sampler;
|
||||
@group(2) @binding(9) var normal_map_texture: texture_2d<f32>;
|
||||
@group(2) @binding(10) var normal_map_sampler: sampler;
|
||||
@group(2) @binding(11) var depth_map_texture: texture_2d<f32>;
|
||||
@group(2) @binding(12) var depth_map_sampler: sampler;
|
||||
@group(3) @binding(0) var<uniform> material: StandardMaterial;
|
||||
@group(3) @binding(1) var base_color_texture: texture_2d<f32>;
|
||||
@group(3) @binding(2) var base_color_sampler: sampler;
|
||||
@group(3) @binding(3) var emissive_texture: texture_2d<f32>;
|
||||
@group(3) @binding(4) var emissive_sampler: sampler;
|
||||
@group(3) @binding(5) var metallic_roughness_texture: texture_2d<f32>;
|
||||
@group(3) @binding(6) var metallic_roughness_sampler: sampler;
|
||||
@group(3) @binding(7) var occlusion_texture: texture_2d<f32>;
|
||||
@group(3) @binding(8) var occlusion_sampler: sampler;
|
||||
@group(3) @binding(9) var normal_map_texture: texture_2d<f32>;
|
||||
@group(3) @binding(10) var normal_map_sampler: sampler;
|
||||
@group(3) @binding(11) var depth_map_texture: texture_2d<f32>;
|
||||
@group(3) @binding(12) var depth_map_sampler: sampler;
|
||||
|
||||
#ifdef PBR_ANISOTROPY_TEXTURE_SUPPORTED
|
||||
@group(2) @binding(13) var anisotropy_texture: texture_2d<f32>;
|
||||
@group(2) @binding(14) var anisotropy_sampler: sampler;
|
||||
@group(3) @binding(13) var anisotropy_texture: texture_2d<f32>;
|
||||
@group(3) @binding(14) var anisotropy_sampler: sampler;
|
||||
#endif // PBR_ANISOTROPY_TEXTURE_SUPPORTED
|
||||
|
||||
#ifdef PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
||||
@group(2) @binding(15) var specular_transmission_texture: texture_2d<f32>;
|
||||
@group(2) @binding(16) var specular_transmission_sampler: sampler;
|
||||
@group(2) @binding(17) var thickness_texture: texture_2d<f32>;
|
||||
@group(2) @binding(18) var thickness_sampler: sampler;
|
||||
@group(2) @binding(19) var diffuse_transmission_texture: texture_2d<f32>;
|
||||
@group(2) @binding(20) var diffuse_transmission_sampler: sampler;
|
||||
@group(3) @binding(15) var specular_transmission_texture: texture_2d<f32>;
|
||||
@group(3) @binding(16) var specular_transmission_sampler: sampler;
|
||||
@group(3) @binding(17) var thickness_texture: texture_2d<f32>;
|
||||
@group(3) @binding(18) var thickness_sampler: sampler;
|
||||
@group(3) @binding(19) var diffuse_transmission_texture: texture_2d<f32>;
|
||||
@group(3) @binding(20) var diffuse_transmission_sampler: sampler;
|
||||
#endif // PBR_TRANSMISSION_TEXTURES_SUPPORTED
|
||||
|
||||
#ifdef PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
||||
@group(2) @binding(21) var clearcoat_texture: texture_2d<f32>;
|
||||
@group(2) @binding(22) var clearcoat_sampler: sampler;
|
||||
@group(2) @binding(23) var clearcoat_roughness_texture: texture_2d<f32>;
|
||||
@group(2) @binding(24) var clearcoat_roughness_sampler: sampler;
|
||||
@group(2) @binding(25) var clearcoat_normal_texture: texture_2d<f32>;
|
||||
@group(2) @binding(26) var clearcoat_normal_sampler: sampler;
|
||||
@group(3) @binding(21) var clearcoat_texture: texture_2d<f32>;
|
||||
@group(3) @binding(22) var clearcoat_sampler: sampler;
|
||||
@group(3) @binding(23) var clearcoat_roughness_texture: texture_2d<f32>;
|
||||
@group(3) @binding(24) var clearcoat_roughness_sampler: sampler;
|
||||
@group(3) @binding(25) var clearcoat_normal_texture: texture_2d<f32>;
|
||||
@group(3) @binding(26) var clearcoat_normal_sampler: sampler;
|
||||
#endif // PBR_MULTI_LAYER_MATERIAL_TEXTURES_SUPPORTED
|
||||
|
||||
#ifdef PBR_SPECULAR_TEXTURES_SUPPORTED
|
||||
@group(2) @binding(27) var specular_texture: texture_2d<f32>;
|
||||
@group(2) @binding(28) var specular_sampler: sampler;
|
||||
@group(2) @binding(29) var specular_tint_texture: texture_2d<f32>;
|
||||
@group(2) @binding(30) var specular_tint_sampler: sampler;
|
||||
@group(3) @binding(27) var specular_texture: texture_2d<f32>;
|
||||
@group(3) @binding(28) var specular_sampler: sampler;
|
||||
@group(3) @binding(29) var specular_tint_texture: texture_2d<f32>;
|
||||
@group(3) @binding(30) var specular_tint_sampler: sampler;
|
||||
#endif // PBR_SPECULAR_TEXTURES_SUPPORTED
|
||||
|
||||
#endif // BINDLESS
|
||||
|
||||
@ -6,9 +6,9 @@
|
||||
#ifdef SKINNED
|
||||
|
||||
#ifdef SKINS_USE_UNIFORM_BUFFERS
|
||||
@group(1) @binding(1) var<uniform> joint_matrices: SkinnedMesh;
|
||||
@group(2) @binding(1) var<uniform> joint_matrices: SkinnedMesh;
|
||||
#else // SKINS_USE_UNIFORM_BUFFERS
|
||||
@group(1) @binding(1) var<storage> joint_matrices: array<mat4x4<f32>>;
|
||||
@group(2) @binding(1) var<storage> joint_matrices: array<mat4x4<f32>>;
|
||||
#endif // SKINS_USE_UNIFORM_BUFFERS
|
||||
|
||||
// An array of matrices specifying the joint positions from the previous frame.
|
||||
@ -18,9 +18,9 @@
|
||||
// If this is the first frame, or we're otherwise prevented from using data from
|
||||
// the previous frame, this is simply the same as `joint_matrices` above.
|
||||
#ifdef SKINS_USE_UNIFORM_BUFFERS
|
||||
@group(1) @binding(6) var<uniform> prev_joint_matrices: SkinnedMesh;
|
||||
@group(2) @binding(6) var<uniform> prev_joint_matrices: SkinnedMesh;
|
||||
#else // SKINS_USE_UNIFORM_BUFFERS
|
||||
@group(1) @binding(6) var<storage> prev_joint_matrices: array<mat4x4<f32>>;
|
||||
@group(2) @binding(6) var<storage> prev_joint_matrices: array<mat4x4<f32>>;
|
||||
#endif // SKINS_USE_UNIFORM_BUFFERS
|
||||
|
||||
fn skin_model(
|
||||
|
||||
@ -323,7 +323,7 @@ impl ViewNode for ScreenSpaceReflectionsNode {
|
||||
render_pass.set_render_pipeline(render_pipeline);
|
||||
render_pass.set_bind_group(
|
||||
0,
|
||||
&view_bind_group.value,
|
||||
&view_bind_group.main,
|
||||
&[
|
||||
view_uniform_offset.offset,
|
||||
view_lights_offset.offset,
|
||||
@ -333,9 +333,10 @@ impl ViewNode for ScreenSpaceReflectionsNode {
|
||||
**view_environment_map_offset,
|
||||
],
|
||||
);
|
||||
render_pass.set_bind_group(1, &view_bind_group.binding_array, &[]);
|
||||
|
||||
// Perform the SSR render pass.
|
||||
render_pass.set_bind_group(1, &ssr_bind_group, &[]);
|
||||
render_pass.set_bind_group(2, &ssr_bind_group, &[]);
|
||||
render_pass.draw(0..3, 0..1);
|
||||
|
||||
Ok(())
|
||||
@ -517,9 +518,14 @@ impl SpecializedRenderPipeline for ScreenSpaceReflectionsPipeline {
|
||||
type Key = ScreenSpaceReflectionsPipelineKey;
|
||||
|
||||
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
|
||||
let mesh_view_layout = self
|
||||
let layout = self
|
||||
.mesh_view_layouts
|
||||
.get_view_layout(key.mesh_pipeline_view_key);
|
||||
let layout = vec![
|
||||
layout.main_layout.clone(),
|
||||
layout.binding_array_layout.clone(),
|
||||
self.bind_group_layout.clone(),
|
||||
];
|
||||
|
||||
let mut shader_defs = vec![
|
||||
"DEPTH_PREPASS".into(),
|
||||
@ -537,7 +543,7 @@ impl SpecializedRenderPipeline for ScreenSpaceReflectionsPipeline {
|
||||
|
||||
RenderPipelineDescriptor {
|
||||
label: Some("SSR pipeline".into()),
|
||||
layout: vec![mesh_view_layout.clone(), self.bind_group_layout.clone()],
|
||||
layout,
|
||||
vertex: self.fullscreen_shader.to_vertex_state(),
|
||||
fragment: Some(FragmentState {
|
||||
shader: self.fragment_shader.clone(),
|
||||
|
||||
@ -25,10 +25,10 @@
|
||||
}
|
||||
|
||||
// Allows us to sample from the depth buffer with bilinear filtering.
|
||||
@group(1) @binding(2) var depth_linear_sampler: sampler;
|
||||
@group(2) @binding(2) var depth_linear_sampler: sampler;
|
||||
|
||||
// Allows us to sample from the depth buffer with nearest-neighbor filtering.
|
||||
@group(1) @binding(3) var depth_nearest_sampler: sampler;
|
||||
@group(2) @binding(3) var depth_nearest_sampler: sampler;
|
||||
|
||||
// Main code
|
||||
|
||||
|
||||
@ -36,10 +36,10 @@
|
||||
#endif
|
||||
|
||||
// The texture representing the color framebuffer.
|
||||
@group(1) @binding(0) var color_texture: texture_2d<f32>;
|
||||
@group(2) @binding(0) var color_texture: texture_2d<f32>;
|
||||
|
||||
// The sampler that lets us sample from the color framebuffer.
|
||||
@group(1) @binding(1) var color_sampler: sampler;
|
||||
@group(2) @binding(1) var color_sampler: sampler;
|
||||
|
||||
// Group 1, bindings 2 and 3 are in `raymarch.wgsl`.
|
||||
|
||||
|
||||
@ -461,7 +461,7 @@ impl ViewNode for VolumetricFogNode {
|
||||
render_pass.set_pipeline(pipeline);
|
||||
render_pass.set_bind_group(
|
||||
0,
|
||||
&view_bind_group.value,
|
||||
&view_bind_group.main,
|
||||
&[
|
||||
view_uniform_offset.offset,
|
||||
view_lights_offset.offset,
|
||||
@ -511,10 +511,6 @@ impl SpecializedRenderPipeline for VolumetricFogPipeline {
|
||||
type Key = VolumetricFogPipelineKey;
|
||||
|
||||
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
|
||||
let mesh_view_layout = self
|
||||
.mesh_view_layouts
|
||||
.get_view_layout(key.mesh_pipeline_view_key);
|
||||
|
||||
// We always use hardware 2x2 filtering for sampling the shadow map; the
|
||||
// more accurate versions with percentage-closer filtering aren't worth
|
||||
// the overhead.
|
||||
@ -559,9 +555,17 @@ impl SpecializedRenderPipeline for VolumetricFogPipeline {
|
||||
shader_defs.push("DENSITY_TEXTURE".into());
|
||||
}
|
||||
|
||||
let layout = self
|
||||
.mesh_view_layouts
|
||||
.get_view_layout(key.mesh_pipeline_view_key);
|
||||
let layout = vec![
|
||||
layout.main_layout.clone(),
|
||||
volumetric_view_bind_group_layout.clone(),
|
||||
];
|
||||
|
||||
RenderPipelineDescriptor {
|
||||
label: Some("volumetric lighting pipeline".into()),
|
||||
layout: vec![mesh_view_layout.clone(), volumetric_view_bind_group_layout],
|
||||
layout,
|
||||
push_constant_ranges: vec![],
|
||||
vertex: VertexState {
|
||||
shader: self.shader.clone(),
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
DrawMesh, MeshPipeline, MeshPipelineKey, RenderMeshInstanceFlags, RenderMeshInstances,
|
||||
SetMeshBindGroup, SetMeshViewBindGroup, ViewKeyCache, ViewSpecializationTicks,
|
||||
SetMeshBindGroup, SetMeshViewBindGroup, SetMeshViewBindingArrayBindGroup, ViewKeyCache,
|
||||
ViewSpecializationTicks,
|
||||
};
|
||||
use bevy_app::{App, Plugin, PostUpdate, Startup, Update};
|
||||
use bevy_asset::{
|
||||
@ -318,7 +319,8 @@ impl<P: PhaseItem> RenderCommand<P> for SetWireframe3dPushConstants {
|
||||
pub type DrawWireframe3d = (
|
||||
SetItemPipeline,
|
||||
SetMeshViewBindGroup<0>,
|
||||
SetMeshBindGroup<1>,
|
||||
SetMeshViewBindingArrayBindGroup<1>,
|
||||
SetMeshBindGroup<2>,
|
||||
SetWireframe3dPushConstants,
|
||||
DrawMesh,
|
||||
);
|
||||
|
||||
@ -109,7 +109,7 @@ uuid = { version = "1.13.1", default-features = false, optional = true, features
|
||||
"serde",
|
||||
] }
|
||||
variadics_please = "1.1"
|
||||
wgpu-types = { version = "24", features = [
|
||||
wgpu-types = { version = "25", features = [
|
||||
"serde",
|
||||
], optional = true, default-features = false }
|
||||
|
||||
|
||||
@ -85,19 +85,21 @@ bevy_platform = { path = "../bevy_platform", version = "0.17.0-dev", default-fea
|
||||
image = { version = "0.25.2", default-features = false }
|
||||
|
||||
# misc
|
||||
codespan-reporting = "0.11.0"
|
||||
codespan-reporting = "0.12.0"
|
||||
# `fragile-send-sync-non-atomic-wasm` feature means we can't use Wasm threads for rendering
|
||||
# It is enabled for now to avoid having to do a significant overhaul of the renderer just for wasm.
|
||||
# When the 'atomics' feature is enabled `fragile-send-sync-non-atomic` does nothing
|
||||
# and Bevy instead wraps `wgpu` types to verify they are not used off their origin thread.
|
||||
wgpu = { version = "24", default-features = false, features = [
|
||||
wgpu = { version = "25", default-features = false, features = [
|
||||
"wgsl",
|
||||
"dx12",
|
||||
"metal",
|
||||
"vulkan",
|
||||
"gles",
|
||||
"naga-ir",
|
||||
"fragile-send-sync-non-atomic-wasm",
|
||||
] }
|
||||
naga = { version = "24", features = ["wgsl-in"] }
|
||||
naga = { version = "25", features = ["wgsl-in"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
bytemuck = { version = "1.5", features = ["derive", "must_cast"] }
|
||||
downcast-rs = { version = "2", default-features = false, features = ["std"] }
|
||||
@ -123,7 +125,7 @@ wesl = { version = "0.1.2", optional = true }
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
# Omit the `glsl` feature in non-WebAssembly by default.
|
||||
naga_oil = { version = "0.17.1", default-features = false, features = [
|
||||
naga_oil = { version = "0.18", default-features = false, features = [
|
||||
"test_shader",
|
||||
] }
|
||||
|
||||
@ -131,7 +133,7 @@ naga_oil = { version = "0.17.1", default-features = false, features = [
|
||||
proptest = "1"
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
naga_oil = "0.17.1"
|
||||
naga_oil = { version = "0.18" }
|
||||
js-sys = "0.3"
|
||||
web-sys = { version = "0.3.67", features = [
|
||||
'Blob',
|
||||
|
||||
@ -204,7 +204,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
||||
#bind_group_layout_entries.push(
|
||||
#render_path::render_resource::BindGroupLayoutEntry {
|
||||
binding: #binding_array_binding,
|
||||
visibility: #render_path::render_resource::ShaderStages::all(),
|
||||
visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::COMPUTE,
|
||||
ty: #render_path::render_resource::BindingType::Buffer {
|
||||
ty: #uniform_binding_type,
|
||||
has_dynamic_offset: false,
|
||||
@ -253,7 +253,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
||||
#bind_group_layout_entries.push(
|
||||
#render_path::render_resource::BindGroupLayoutEntry {
|
||||
binding: #binding_array_binding,
|
||||
visibility: #render_path::render_resource::ShaderStages::all(),
|
||||
visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::COMPUTE,
|
||||
ty: #render_path::render_resource::BindingType::Buffer {
|
||||
ty: #uniform_binding_type,
|
||||
has_dynamic_offset: false,
|
||||
@ -279,7 +279,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
||||
#bind_group_layout_entries.push(
|
||||
#render_path::render_resource::BindGroupLayoutEntry {
|
||||
binding: #binding_index,
|
||||
visibility: #render_path::render_resource::ShaderStages::all(),
|
||||
visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::COMPUTE,
|
||||
ty: #render_path::render_resource::BindingType::Buffer {
|
||||
ty: #uniform_binding_type,
|
||||
has_dynamic_offset: false,
|
||||
@ -519,7 +519,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
||||
#bind_group_layout_entries.push(
|
||||
#render_path::render_resource::BindGroupLayoutEntry {
|
||||
binding: #binding_array_binding,
|
||||
visibility: #render_path::render_resource::ShaderStages::all(),
|
||||
visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::COMPUTE,
|
||||
ty: #render_path::render_resource::BindingType::Buffer {
|
||||
ty: #render_path::render_resource::BufferBindingType::Storage {
|
||||
read_only: #read_only
|
||||
@ -834,7 +834,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
||||
#bind_group_layout_entries.push(
|
||||
#render_path::render_resource::BindGroupLayoutEntry {
|
||||
binding: #binding_index,
|
||||
visibility: #render_path::render_resource::ShaderStages::all(),
|
||||
visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::COMPUTE,
|
||||
ty: #render_path::render_resource::BindingType::Buffer {
|
||||
ty: #uniform_binding_type,
|
||||
has_dynamic_offset: false,
|
||||
@ -881,7 +881,7 @@ pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
|
||||
non_bindless_binding_layouts.push(quote!{
|
||||
#bind_group_layout_entries.push(#render_path::render_resource::BindGroupLayoutEntry {
|
||||
binding: #binding_index,
|
||||
visibility: #render_path::render_resource::ShaderStages::all(),
|
||||
visibility: #render_path::render_resource::ShaderStages::FRAGMENT | #render_path::render_resource::ShaderStages::VERTEX | #render_path::render_resource::ShaderStages::COMPUTE,
|
||||
ty: #render_path::render_resource::BindingType::Buffer {
|
||||
ty: #uniform_binding_type,
|
||||
has_dynamic_offset: false,
|
||||
@ -1337,7 +1337,13 @@ impl VisibilityFlags {
|
||||
impl ShaderStageVisibility {
|
||||
fn hygienic_quote(&self, path: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
|
||||
match self {
|
||||
ShaderStageVisibility::All => quote! { #path::ShaderStages::all() },
|
||||
ShaderStageVisibility::All => quote! {
|
||||
if cfg!(feature = "webgpu") {
|
||||
todo!("Please use a more specific shader stage: https://github.com/gfx-rs/wgpu/issues/7708")
|
||||
} else {
|
||||
#path::ShaderStages::all()
|
||||
}
|
||||
},
|
||||
ShaderStageVisibility::None => quote! { #path::ShaderStages::NONE },
|
||||
ShaderStageVisibility::Flags(flags) => {
|
||||
let mut quoted = Vec::new();
|
||||
|
||||
@ -16,22 +16,22 @@
|
||||
|
||||
// Binding 0 is the bindless index table.
|
||||
// Filtering samplers.
|
||||
@group(2) @binding(1) var bindless_samplers_filtering: binding_array<sampler>;
|
||||
@group(3) @binding(1) var bindless_samplers_filtering: binding_array<sampler>;
|
||||
// Non-filtering samplers (nearest neighbor).
|
||||
@group(2) @binding(2) var bindless_samplers_non_filtering: binding_array<sampler>;
|
||||
@group(3) @binding(2) var bindless_samplers_non_filtering: binding_array<sampler>;
|
||||
// Comparison samplers (typically for shadow mapping).
|
||||
@group(2) @binding(3) var bindless_samplers_comparison: binding_array<sampler>;
|
||||
@group(3) @binding(3) var bindless_samplers_comparison: binding_array<sampler>;
|
||||
// 1D textures.
|
||||
@group(2) @binding(4) var bindless_textures_1d: binding_array<texture_1d<f32>>;
|
||||
@group(3) @binding(4) var bindless_textures_1d: binding_array<texture_1d<f32>>;
|
||||
// 2D textures.
|
||||
@group(2) @binding(5) var bindless_textures_2d: binding_array<texture_2d<f32>>;
|
||||
@group(3) @binding(5) var bindless_textures_2d: binding_array<texture_2d<f32>>;
|
||||
// 2D array textures.
|
||||
@group(2) @binding(6) var bindless_textures_2d_array: binding_array<texture_2d_array<f32>>;
|
||||
@group(3) @binding(6) var bindless_textures_2d_array: binding_array<texture_2d_array<f32>>;
|
||||
// 3D textures.
|
||||
@group(2) @binding(7) var bindless_textures_3d: binding_array<texture_3d<f32>>;
|
||||
@group(3) @binding(7) var bindless_textures_3d: binding_array<texture_3d<f32>>;
|
||||
// Cubemap textures.
|
||||
@group(2) @binding(8) var bindless_textures_cube: binding_array<texture_cube<f32>>;
|
||||
@group(3) @binding(8) var bindless_textures_cube: binding_array<texture_cube<f32>>;
|
||||
// Cubemap array textures.
|
||||
@group(2) @binding(9) var bindless_textures_cube_array: binding_array<texture_cube_array<f32>>;
|
||||
@group(3) @binding(9) var bindless_textures_cube_array: binding_array<texture_cube_array<f32>>;
|
||||
|
||||
#endif // BINDLESS
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use crate::renderer::{RenderAdapterInfo, RenderDevice, RenderQueue};
|
||||
use tracy_client::{Client, GpuContext, GpuContextType};
|
||||
use wgpu::{
|
||||
Backend, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, Maintain, MapMode,
|
||||
Backend, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, MapMode, PollType,
|
||||
QuerySetDescriptor, QueryType, QUERY_SIZE,
|
||||
};
|
||||
|
||||
@ -14,7 +14,7 @@ pub fn new_tracy_gpu_context(
|
||||
Backend::Vulkan => GpuContextType::Vulkan,
|
||||
Backend::Dx12 => GpuContextType::Direct3D12,
|
||||
Backend::Gl => GpuContextType::OpenGL,
|
||||
Backend::Metal | Backend::BrowserWebGpu | Backend::Empty => GpuContextType::Invalid,
|
||||
Backend::Metal | Backend::BrowserWebGpu | Backend::Noop => GpuContextType::Invalid,
|
||||
};
|
||||
|
||||
let tracy_client = Client::running().unwrap();
|
||||
@ -60,7 +60,9 @@ fn initial_timestamp(device: &RenderDevice, queue: &RenderQueue) -> i64 {
|
||||
queue.submit([timestamp_encoder.finish(), copy_encoder.finish()]);
|
||||
|
||||
map_buffer.slice(..).map_async(MapMode::Read, |_| ());
|
||||
device.poll(Maintain::Wait);
|
||||
device
|
||||
.poll(PollType::Wait)
|
||||
.expect("Failed to poll device for map async");
|
||||
|
||||
let view = map_buffer.slice(..).get_mapped_range();
|
||||
i64::from_le_bytes((*view).try_into().unwrap())
|
||||
|
||||
@ -352,10 +352,12 @@ impl Plugin for RenderPlugin {
|
||||
backend_options: wgpu::BackendOptions {
|
||||
gl: wgpu::GlBackendOptions {
|
||||
gles_minor_version: settings.gles3_minor_version,
|
||||
fence_behavior: wgpu::GlFenceBehavior::Normal,
|
||||
},
|
||||
dx12: wgpu::Dx12BackendOptions {
|
||||
shader_compiler: settings.dx12_shader_compiler.clone(),
|
||||
},
|
||||
noop: wgpu::NoopBackendOptions { enable: false },
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -168,14 +168,16 @@ impl<P: PhaseItem> DrawFunctions<P> {
|
||||
/// ```
|
||||
/// # use bevy_render::render_phase::SetItemPipeline;
|
||||
/// # struct SetMeshViewBindGroup<const N: usize>;
|
||||
/// # struct SetMeshViewBindingArrayBindGroup<const N: usize>;
|
||||
/// # struct SetMeshBindGroup<const N: usize>;
|
||||
/// # struct SetMaterialBindGroup<M, const N: usize>(std::marker::PhantomData<M>);
|
||||
/// # struct DrawMesh;
|
||||
/// pub type DrawMaterial<M> = (
|
||||
/// SetItemPipeline,
|
||||
/// SetMeshViewBindGroup<0>,
|
||||
/// SetMeshBindGroup<1>,
|
||||
/// SetMaterialBindGroup<M, 2>,
|
||||
/// SetMeshViewBindingArrayBindGroup<1>,
|
||||
/// SetMeshBindGroup<2>,
|
||||
/// SetMaterialBindGroup<M, 3>,
|
||||
/// DrawMesh,
|
||||
/// );
|
||||
/// ```
|
||||
|
||||
@ -133,12 +133,12 @@ impl Deref for BindGroup {
|
||||
/// In WGSL shaders, the binding would look like this:
|
||||
///
|
||||
/// ```wgsl
|
||||
/// @group(2) @binding(0) var<uniform> color: vec4<f32>;
|
||||
/// @group(2) @binding(1) var color_texture: texture_2d<f32>;
|
||||
/// @group(2) @binding(2) var color_sampler: sampler;
|
||||
/// @group(2) @binding(3) var<storage> storage_buffer: array<f32>;
|
||||
/// @group(2) @binding(4) var<storage> raw_buffer: array<f32>;
|
||||
/// @group(2) @binding(5) var storage_texture: texture_storage_2d<rgba8unorm, read_write>;
|
||||
/// @group(3) @binding(0) var<uniform> color: vec4<f32>;
|
||||
/// @group(3) @binding(1) var color_texture: texture_2d<f32>;
|
||||
/// @group(3) @binding(2) var color_sampler: sampler;
|
||||
/// @group(3) @binding(3) var<storage> storage_buffer: array<f32>;
|
||||
/// @group(3) @binding(4) var<storage> raw_buffer: array<f32>;
|
||||
/// @group(3) @binding(5) var storage_texture: texture_storage_2d<rgba8unorm, read_write>;
|
||||
/// ```
|
||||
/// Note that the "group" index is determined by the usage context. It is not defined in [`AsBindGroup`]. For example, in Bevy material bind groups
|
||||
/// are generally bound to group 2.
|
||||
@ -261,7 +261,7 @@ impl Deref for BindGroup {
|
||||
/// roughness: f32,
|
||||
/// };
|
||||
///
|
||||
/// @group(2) @binding(0) var<uniform> material: CoolMaterial;
|
||||
/// @group(3) @binding(0) var<uniform> material: CoolMaterial;
|
||||
/// ```
|
||||
///
|
||||
/// Some less common scenarios will require "struct-level" attributes. These are the currently supported struct-level attributes:
|
||||
@ -312,7 +312,7 @@ impl Deref for BindGroup {
|
||||
/// declaration:
|
||||
///
|
||||
/// ```wgsl
|
||||
/// @group(2) @binding(10) var<storage> material_array: binding_array<StandardMaterial>;
|
||||
/// @group(3) @binding(10) var<storage> material_array: binding_array<StandardMaterial>;
|
||||
/// ```
|
||||
///
|
||||
/// On the other hand, if you write this declaration:
|
||||
@ -325,7 +325,7 @@ impl Deref for BindGroup {
|
||||
/// Then Bevy produces a binding that matches this WGSL declaration instead:
|
||||
///
|
||||
/// ```wgsl
|
||||
/// @group(2) @binding(10) var<storage> material_array: array<StandardMaterial>;
|
||||
/// @group(3) @binding(10) var<storage> material_array: array<StandardMaterial>;
|
||||
/// ```
|
||||
///
|
||||
/// * Just as with the structure-level `uniform` attribute, Bevy converts the
|
||||
@ -338,7 +338,7 @@ impl Deref for BindGroup {
|
||||
/// this in WGSL in non-bindless mode:
|
||||
///
|
||||
/// ```wgsl
|
||||
/// @group(2) @binding(0) var<uniform> material: StandardMaterial;
|
||||
/// @group(3) @binding(0) var<uniform> material: StandardMaterial;
|
||||
/// ```
|
||||
///
|
||||
/// * For efficiency reasons, `data` is generally preferred over `uniform`
|
||||
|
||||
@ -287,6 +287,12 @@ impl<'b> DynamicBindGroupEntries<'b> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
entries: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend_with_indices<const N: usize>(
|
||||
mut self,
|
||||
entries: impl IntoIndexedBindingArray<'b, N>,
|
||||
|
||||
@ -334,6 +334,13 @@ impl DynamicBindGroupLayoutEntries {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(default_visibility: ShaderStages) -> Self {
|
||||
Self {
|
||||
default_visibility,
|
||||
entries: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend_with_indices<const N: usize>(
|
||||
mut self,
|
||||
entries: impl IntoIndexedBindGroupLayoutEntryBuilderArray<N>,
|
||||
@ -570,6 +577,16 @@ pub mod binding_types {
|
||||
}
|
||||
|
||||
pub fn acceleration_structure() -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::AccelerationStructure.into_bind_group_layout_entry_builder()
|
||||
BindingType::AccelerationStructure {
|
||||
vertex_return: false,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn acceleration_structure_vertex_return() -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::AccelerationStructure {
|
||||
vertex_return: true,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,35 +243,65 @@ pub fn create_bindless_bind_group_layout_entries(
|
||||
false,
|
||||
NonZeroU64::new(bindless_index_table_length as u64 * size_of::<u32>() as u64),
|
||||
)
|
||||
.build(*bindless_index_table_binding_number, ShaderStages::all()),
|
||||
.build(
|
||||
*bindless_index_table_binding_number,
|
||||
ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
|
||||
),
|
||||
// Continue with the common bindless resource arrays.
|
||||
sampler(SamplerBindingType::Filtering)
|
||||
.count(bindless_slab_resource_limit)
|
||||
.build(1, ShaderStages::all()),
|
||||
.build(
|
||||
1,
|
||||
ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
|
||||
),
|
||||
sampler(SamplerBindingType::NonFiltering)
|
||||
.count(bindless_slab_resource_limit)
|
||||
.build(2, ShaderStages::all()),
|
||||
.build(
|
||||
2,
|
||||
ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
|
||||
),
|
||||
sampler(SamplerBindingType::Comparison)
|
||||
.count(bindless_slab_resource_limit)
|
||||
.build(3, ShaderStages::all()),
|
||||
.build(
|
||||
3,
|
||||
ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
|
||||
),
|
||||
texture_1d(TextureSampleType::Float { filterable: true })
|
||||
.count(bindless_slab_resource_limit)
|
||||
.build(4, ShaderStages::all()),
|
||||
.build(
|
||||
4,
|
||||
ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
|
||||
),
|
||||
texture_2d(TextureSampleType::Float { filterable: true })
|
||||
.count(bindless_slab_resource_limit)
|
||||
.build(5, ShaderStages::all()),
|
||||
.build(
|
||||
5,
|
||||
ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
|
||||
),
|
||||
texture_2d_array(TextureSampleType::Float { filterable: true })
|
||||
.count(bindless_slab_resource_limit)
|
||||
.build(6, ShaderStages::all()),
|
||||
.build(
|
||||
6,
|
||||
ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
|
||||
),
|
||||
texture_3d(TextureSampleType::Float { filterable: true })
|
||||
.count(bindless_slab_resource_limit)
|
||||
.build(7, ShaderStages::all()),
|
||||
.build(
|
||||
7,
|
||||
ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
|
||||
),
|
||||
texture_cube(TextureSampleType::Float { filterable: true })
|
||||
.count(bindless_slab_resource_limit)
|
||||
.build(8, ShaderStages::all()),
|
||||
.build(
|
||||
8,
|
||||
ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
|
||||
),
|
||||
texture_cube_array(TextureSampleType::Float { filterable: true })
|
||||
.count(bindless_slab_resource_limit)
|
||||
.build(9, ShaderStages::all()),
|
||||
.build(
|
||||
9,
|
||||
ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -49,18 +49,18 @@ pub use wgpu::{
|
||||
ComputePassDescriptor, ComputePipelineDescriptor as RawComputePipelineDescriptor,
|
||||
CreateBlasDescriptor, CreateTlasDescriptor, DepthBiasState, DepthStencilState, DownlevelFlags,
|
||||
Extent3d, Face, Features as WgpuFeatures, FilterMode, FragmentState as RawFragmentState,
|
||||
FrontFace, ImageSubresourceRange, IndexFormat, Limits as WgpuLimits, LoadOp, Maintain, MapMode,
|
||||
FrontFace, ImageSubresourceRange, IndexFormat, Limits as WgpuLimits, LoadOp, MapMode,
|
||||
MultisampleState, Operations, Origin3d, PipelineCompilationOptions, PipelineLayout,
|
||||
PipelineLayoutDescriptor, PolygonMode, PrimitiveState, PrimitiveTopology, PushConstantRange,
|
||||
RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor,
|
||||
RenderPipelineDescriptor as RawRenderPipelineDescriptor, Sampler as WgpuSampler,
|
||||
SamplerBindingType, SamplerBindingType as WgpuSamplerBindingType, SamplerDescriptor,
|
||||
ShaderModule, ShaderModuleDescriptor, ShaderSource, ShaderStages, StencilFaceState,
|
||||
StencilOperation, StencilState, StorageTextureAccess, StoreOp, TexelCopyBufferInfo,
|
||||
TexelCopyBufferLayout, TexelCopyTextureInfo, TextureAspect, TextureDescriptor,
|
||||
TextureDimension, TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures,
|
||||
TextureSampleType, TextureUsages, TextureView as WgpuTextureView, TextureViewDescriptor,
|
||||
TextureViewDimension, Tlas, TlasInstance, TlasPackage, VertexAttribute,
|
||||
PipelineLayoutDescriptor, PollType, PolygonMode, PrimitiveState, PrimitiveTopology,
|
||||
PushConstantRange, RenderPassColorAttachment, RenderPassDepthStencilAttachment,
|
||||
RenderPassDescriptor, RenderPipelineDescriptor as RawRenderPipelineDescriptor,
|
||||
Sampler as WgpuSampler, SamplerBindingType, SamplerBindingType as WgpuSamplerBindingType,
|
||||
SamplerDescriptor, ShaderModule, ShaderModuleDescriptor, ShaderSource, ShaderStages,
|
||||
StencilFaceState, StencilOperation, StencilState, StorageTextureAccess, StoreOp,
|
||||
TexelCopyBufferInfo, TexelCopyBufferLayout, TexelCopyTextureInfo, TextureAspect,
|
||||
TextureDescriptor, TextureDimension, TextureFormat, TextureFormatFeatureFlags,
|
||||
TextureFormatFeatures, TextureSampleType, TextureUsages, TextureView as WgpuTextureView,
|
||||
TextureViewDescriptor, TextureViewDimension, Tlas, TlasInstance, TlasPackage, VertexAttribute,
|
||||
VertexBufferLayout as RawVertexBufferLayout, VertexFormat, VertexState as RawVertexState,
|
||||
VertexStepMode, COPY_BUFFER_ALIGNMENT,
|
||||
};
|
||||
|
||||
@ -873,7 +873,7 @@ impl PipelineCache {
|
||||
|
||||
// TODO: Expose the rest of this somehow
|
||||
let compilation_options = PipelineCompilationOptions {
|
||||
constants: &default(),
|
||||
constants: &[],
|
||||
zero_initialize_workgroup_memory: descriptor.zero_initialize_workgroup_memory,
|
||||
};
|
||||
|
||||
@ -955,7 +955,7 @@ impl PipelineCache {
|
||||
entry_point: Some(&descriptor.entry_point),
|
||||
// TODO: Expose the rest of this somehow
|
||||
compilation_options: PipelineCompilationOptions {
|
||||
constants: &default(),
|
||||
constants: &[],
|
||||
zero_initialize_workgroup_memory: descriptor
|
||||
.zero_initialize_workgroup_memory,
|
||||
},
|
||||
@ -1155,8 +1155,12 @@ fn get_capabilities(features: Features, downlevel: DownlevelFlags) -> Capabiliti
|
||||
features.contains(Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING),
|
||||
);
|
||||
capabilities.set(
|
||||
Capabilities::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
|
||||
features.contains(Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING),
|
||||
Capabilities::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
|
||||
features.contains(Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING),
|
||||
);
|
||||
capabilities.set(
|
||||
Capabilities::UNIFORM_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
||||
features.contains(Features::UNIFORM_BUFFER_BINDING_ARRAYS),
|
||||
);
|
||||
// TODO: This needs a proper wgpu feature
|
||||
capabilities.set(
|
||||
@ -1229,6 +1233,14 @@ fn get_capabilities(features: Features, downlevel: DownlevelFlags) -> Capabiliti
|
||||
Capabilities::TEXTURE_INT64_ATOMIC,
|
||||
features.contains(Features::TEXTURE_INT64_ATOMIC),
|
||||
);
|
||||
capabilities.set(
|
||||
Capabilities::SHADER_FLOAT16,
|
||||
features.contains(Features::SHADER_F16),
|
||||
);
|
||||
capabilities.set(
|
||||
Capabilities::RAY_HIT_VERTEX_POSITION,
|
||||
features.intersects(Features::EXPERIMENTAL_RAY_HIT_VERTEX_RETURN),
|
||||
);
|
||||
|
||||
capabilities
|
||||
}
|
||||
|
||||
@ -301,6 +301,8 @@ impl From<&Source> for naga_oil::compose::ShaderType {
|
||||
naga::ShaderStage::Vertex => naga_oil::compose::ShaderType::GlslVertex,
|
||||
naga::ShaderStage::Fragment => naga_oil::compose::ShaderType::GlslFragment,
|
||||
naga::ShaderStage::Compute => panic!("glsl compute not yet implemented"),
|
||||
naga::ShaderStage::Task => panic!("task shaders not yet implemented"),
|
||||
naga::ShaderStage::Mesh => panic!("mesh shaders not yet implemented"),
|
||||
},
|
||||
#[cfg(all(not(feature = "shader_format_glsl"), not(target_arch = "wasm32")))]
|
||||
Source::Glsl(_, _) => panic!(
|
||||
|
||||
@ -23,7 +23,7 @@ use bevy_platform::time::Instant;
|
||||
use bevy_time::TimeSender;
|
||||
use wgpu::{
|
||||
Adapter, AdapterInfo, CommandBuffer, CommandEncoder, DeviceType, Instance, Queue,
|
||||
RequestAdapterOptions,
|
||||
RequestAdapterOptions, Trace,
|
||||
};
|
||||
|
||||
/// Updates the [`RenderGraph`] with all of its nodes and then runs it to render the entire frame.
|
||||
@ -177,7 +177,7 @@ pub async fn initialize_renderer(
|
||||
// discrete GPUs due to having to transfer data across the PCI-E bus and so it
|
||||
// should not be automatically enabled in this case. It is however beneficial for
|
||||
// integrated GPUs.
|
||||
features -= wgpu::Features::MAPPABLE_PRIMARY_BUFFERS;
|
||||
features.remove(wgpu::Features::MAPPABLE_PRIMARY_BUFFERS);
|
||||
}
|
||||
|
||||
limits = adapter.limits();
|
||||
@ -185,7 +185,7 @@ pub async fn initialize_renderer(
|
||||
|
||||
// Enforce the disabled features
|
||||
if let Some(disabled_features) = options.disabled_features {
|
||||
features -= disabled_features;
|
||||
features.remove(disabled_features);
|
||||
}
|
||||
// NOTE: |= is used here to ensure that any explicitly-enabled features are respected.
|
||||
features |= options.features;
|
||||
@ -234,6 +234,12 @@ pub async fn initialize_renderer(
|
||||
max_uniform_buffers_per_shader_stage: limits
|
||||
.max_uniform_buffers_per_shader_stage
|
||||
.min(constrained_limits.max_uniform_buffers_per_shader_stage),
|
||||
max_binding_array_elements_per_shader_stage: limits
|
||||
.max_binding_array_elements_per_shader_stage
|
||||
.min(constrained_limits.max_binding_array_elements_per_shader_stage),
|
||||
max_binding_array_sampler_elements_per_shader_stage: limits
|
||||
.max_binding_array_sampler_elements_per_shader_stage
|
||||
.min(constrained_limits.max_binding_array_sampler_elements_per_shader_stage),
|
||||
max_uniform_buffer_binding_size: limits
|
||||
.max_uniform_buffer_binding_size
|
||||
.min(constrained_limits.max_uniform_buffer_binding_size),
|
||||
@ -304,15 +310,14 @@ pub async fn initialize_renderer(
|
||||
}
|
||||
|
||||
let (device, queue) = adapter
|
||||
.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
label: options.device_label.as_ref().map(AsRef::as_ref),
|
||||
required_features: features,
|
||||
required_limits: limits,
|
||||
memory_hints: options.memory_hints.clone(),
|
||||
},
|
||||
options.trace_path.as_deref(),
|
||||
)
|
||||
.request_device(&wgpu::DeviceDescriptor {
|
||||
label: options.device_label.as_ref().map(AsRef::as_ref),
|
||||
required_features: features,
|
||||
required_limits: limits,
|
||||
memory_hints: options.memory_hints.clone(),
|
||||
// See https://github.com/gfx-rs/wgpu/issues/5974
|
||||
trace: Trace::Off,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
let queue = Arc::new(WgpuWrapper::new(queue));
|
||||
|
||||
@ -7,7 +7,7 @@ use bevy_ecs::resource::Resource;
|
||||
use bevy_utils::WgpuWrapper;
|
||||
use wgpu::{
|
||||
util::DeviceExt, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor,
|
||||
BindGroupLayoutEntry, BufferAsyncError, BufferBindingType, MaintainResult,
|
||||
BindGroupLayoutEntry, BufferAsyncError, BufferBindingType, PollError, PollStatus,
|
||||
};
|
||||
|
||||
/// This GPU device is responsible for the creation of most rendering and compute resources.
|
||||
@ -67,11 +67,14 @@ impl RenderDevice {
|
||||
// This call passes binary data to the backend as-is and can potentially result in a driver crash or bogus behavior.
|
||||
// No attempt is made to ensure that data is valid SPIR-V.
|
||||
unsafe {
|
||||
self.device
|
||||
.create_shader_module_spirv(&wgpu::ShaderModuleDescriptorSpirV {
|
||||
label: desc.label,
|
||||
source: source.clone(),
|
||||
})
|
||||
self.device.create_shader_module_passthrough(
|
||||
wgpu::ShaderModuleDescriptorPassthrough::SpirV(
|
||||
wgpu::ShaderModuleDescriptorSpirV {
|
||||
label: desc.label,
|
||||
source: source.clone(),
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
// SAFETY:
|
||||
@ -118,7 +121,7 @@ impl RenderDevice {
|
||||
///
|
||||
/// no-op on the web, device is automatically polled.
|
||||
#[inline]
|
||||
pub fn poll(&self, maintain: wgpu::Maintain) -> MaintainResult {
|
||||
pub fn poll(&self, maintain: wgpu::PollType) -> Result<PollStatus, PollError> {
|
||||
self.device.poll(maintain)
|
||||
}
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ use crate::renderer::{
|
||||
RenderAdapter, RenderAdapterInfo, RenderDevice, RenderInstance, RenderQueue,
|
||||
};
|
||||
use alloc::borrow::Cow;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use wgpu::DxcShaderModel;
|
||||
pub use wgpu::{
|
||||
Backends, Dx12Compiler, Features as WgpuFeatures, Gles3MinorVersion, InstanceFlags,
|
||||
Limits as WgpuLimits, MemoryHints, PowerPreference,
|
||||
@ -53,8 +53,6 @@ pub struct WgpuSettings {
|
||||
pub instance_flags: InstanceFlags,
|
||||
/// This hints to the WGPU device about the preferred memory allocation strategy.
|
||||
pub memory_hints: MemoryHints,
|
||||
/// The path to pass to wgpu for API call tracing. This only has an effect if wgpu's tracing functionality is enabled.
|
||||
pub trace_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Default for WgpuSettings {
|
||||
@ -114,6 +112,7 @@ impl Default for WgpuSettings {
|
||||
Dx12Compiler::DynamicDxc {
|
||||
dxc_path: String::from(dxc),
|
||||
dxil_path: String::from(dxil),
|
||||
max_shader_model: DxcShaderModel::V6_7,
|
||||
}
|
||||
} else {
|
||||
Dx12Compiler::Fxc
|
||||
@ -137,7 +136,6 @@ impl Default for WgpuSettings {
|
||||
gles3_minor_version,
|
||||
instance_flags,
|
||||
memory_hints: MemoryHints::default(),
|
||||
trace_path: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +46,6 @@ impl SolariPlugin {
|
||||
| WgpuFeatures::EXPERIMENTAL_RAY_QUERY
|
||||
| WgpuFeatures::BUFFER_BINDING_ARRAY
|
||||
| WgpuFeatures::TEXTURE_BINDING_ARRAY
|
||||
| WgpuFeatures::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING
|
||||
| WgpuFeatures::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING
|
||||
| WgpuFeatures::PARTIALLY_BOUND_BINDING_ARRAY
|
||||
}
|
||||
|
||||
@ -71,8 +71,8 @@ struct DirectionalLight {
|
||||
@group(0) @binding(9) var<storage> light_sources: array<LightSource>;
|
||||
@group(0) @binding(10) var<storage> directional_lights: array<DirectionalLight>;
|
||||
|
||||
const RAY_T_MIN = 0.01;
|
||||
const RAY_T_MAX = 100000.0;
|
||||
const RAY_T_MIN = 0.01f;
|
||||
const RAY_T_MAX = 100000.0f;
|
||||
|
||||
const RAY_NO_CULL = 0xFFu;
|
||||
|
||||
@ -120,7 +120,7 @@ fn resolve_material(material: Material, uv: vec2<f32>) -> ResolvedMaterial {
|
||||
|
||||
fn resolve_ray_hit_full(ray_hit: RayIntersection) -> ResolvedRayHitFull {
|
||||
let barycentrics = vec3(1.0 - ray_hit.barycentrics.x - ray_hit.barycentrics.y, ray_hit.barycentrics);
|
||||
return resolve_triangle_data_full(ray_hit.instance_id, ray_hit.primitive_index, barycentrics);
|
||||
return resolve_triangle_data_full(ray_hit.instance_index, ray_hit.primitive_index, barycentrics);
|
||||
}
|
||||
|
||||
fn resolve_triangle_data_full(instance_id: u32, triangle_id: u32, barycentrics: vec3<f32>) -> ResolvedRayHitFull {
|
||||
|
||||
@ -59,7 +59,7 @@ cfg-if = "1.0"
|
||||
raw-window-handle = "0.6"
|
||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||
bytemuck = { version = "1.5", optional = true }
|
||||
wgpu-types = { version = "24", optional = true }
|
||||
wgpu-types = { version = "25", optional = true }
|
||||
accesskit = "0.19"
|
||||
tracing = { version = "0.1", default-features = false, features = ["std"] }
|
||||
|
||||
|
||||
@ -22,8 +22,8 @@ use bevy::{
|
||||
render_asset::{RenderAssetUsages, RenderAssets},
|
||||
render_graph::{self, NodeRunError, RenderGraph, RenderGraphContext, RenderLabel},
|
||||
render_resource::{
|
||||
Buffer, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, Extent3d, Maintain,
|
||||
MapMode, TexelCopyBufferInfo, TexelCopyBufferLayout, TextureDimension, TextureFormat,
|
||||
Buffer, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, Extent3d, MapMode,
|
||||
PollType, TexelCopyBufferInfo, TexelCopyBufferLayout, TextureDimension, TextureFormat,
|
||||
TextureUsages,
|
||||
},
|
||||
renderer::{RenderContext, RenderDevice, RenderQueue},
|
||||
@ -41,7 +41,6 @@ use std::{
|
||||
},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
// To communicate between the main world and the render world we need a channel.
|
||||
// Since the main world and render world run in parallel, there will always be a frame of latency
|
||||
// between the data sent from the render world and the data received in the main world
|
||||
@ -460,7 +459,9 @@ fn receive_image_from_buffer(
|
||||
// `Maintain::Wait` will cause the thread to wait on native but not on WebGpu.
|
||||
|
||||
// This blocks until the gpu is done executing everything
|
||||
render_device.poll(Maintain::wait()).panic_on_timeout();
|
||||
render_device
|
||||
.poll(PollType::Wait)
|
||||
.expect("Failed to poll device for map async");
|
||||
|
||||
// This blocks until the buffer is mapped
|
||||
r.recv().expect("Failed to receive the map_async message");
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
use std::ops::Range;
|
||||
|
||||
use bevy::pbr::SetMeshViewEmptyBindGroup;
|
||||
use bevy::{
|
||||
core_pipeline::core_3d::graph::{Core3d, Node3d},
|
||||
ecs::{
|
||||
@ -193,17 +194,19 @@ impl SpecializedMeshPipeline for StencilPipeline {
|
||||
}
|
||||
// This will automatically generate the correct `VertexBufferLayout` based on the vertex attributes
|
||||
let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?;
|
||||
|
||||
let view_layout = self
|
||||
.mesh_pipeline
|
||||
.get_view_layout(MeshPipelineViewLayoutKey::from(key));
|
||||
Ok(RenderPipelineDescriptor {
|
||||
label: Some("Specialized Mesh Pipeline".into()),
|
||||
// We want to reuse the data from bevy so we use the same bind groups as the default
|
||||
// mesh pipeline
|
||||
layout: vec![
|
||||
// Bind group 0 is the view uniform
|
||||
self.mesh_pipeline
|
||||
.get_view_layout(MeshPipelineViewLayoutKey::from(key))
|
||||
.clone(),
|
||||
// Bind group 1 is the mesh uniform
|
||||
view_layout.main_layout.clone(),
|
||||
// Bind group 1 is empty
|
||||
view_layout.empty_layout.clone(),
|
||||
// Bind group 2 is the mesh uniform
|
||||
self.mesh_pipeline.mesh_layouts.model_only.clone(),
|
||||
],
|
||||
push_constant_ranges: vec![],
|
||||
@ -244,8 +247,10 @@ type DrawMesh3dStencil = (
|
||||
SetItemPipeline,
|
||||
// This will set the view bindings in group 0
|
||||
SetMeshViewBindGroup<0>,
|
||||
// This will set the mesh bindings in group 1
|
||||
SetMeshBindGroup<1>,
|
||||
// This will set an empty bind group in group 1
|
||||
SetMeshViewEmptyBindGroup<1>,
|
||||
// This will set the mesh bindings in group 2
|
||||
SetMeshBindGroup<2>,
|
||||
// This will draw the mesh
|
||||
DrawMesh,
|
||||
);
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
//! implementation using bevy's low level rendering api.
|
||||
//! It's generally recommended to try the built-in instancing before going with this approach.
|
||||
|
||||
use bevy::pbr::SetMeshViewBindingArrayBindGroup;
|
||||
use bevy::{
|
||||
core_pipeline::core_3d::Transparent3d,
|
||||
ecs::{
|
||||
@ -248,7 +249,8 @@ impl SpecializedMeshPipeline for CustomPipeline {
|
||||
type DrawCustom = (
|
||||
SetItemPipeline,
|
||||
SetMeshViewBindGroup<0>,
|
||||
SetMeshBindGroup<1>,
|
||||
SetMeshViewBindingArrayBindGroup<1>,
|
||||
SetMeshBindGroup<2>,
|
||||
DrawMeshInstanced,
|
||||
);
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ use bevy::{
|
||||
math::{vec3, vec4},
|
||||
pbr::{
|
||||
DrawMesh, MeshPipeline, MeshPipelineKey, MeshPipelineViewLayoutKey, RenderMeshInstances,
|
||||
SetMeshBindGroup, SetMeshViewBindGroup,
|
||||
SetMeshBindGroup, SetMeshViewBindGroup, SetMeshViewEmptyBindGroup,
|
||||
},
|
||||
prelude::*,
|
||||
render::{
|
||||
@ -153,8 +153,10 @@ type DrawSpecializedPipelineCommands = (
|
||||
SetItemPipeline,
|
||||
// Set the view uniform at bind group 0
|
||||
SetMeshViewBindGroup<0>,
|
||||
// Set the mesh uniform at bind group 1
|
||||
SetMeshBindGroup<1>,
|
||||
// Set an empty material bind group at bind group 1
|
||||
SetMeshViewEmptyBindGroup<1>,
|
||||
// Set the mesh uniform at bind group 2
|
||||
SetMeshBindGroup<2>,
|
||||
// Draw the mesh
|
||||
DrawMesh,
|
||||
);
|
||||
@ -210,14 +212,15 @@ impl SpecializedMeshPipeline for CustomMeshPipeline {
|
||||
// This will automatically generate the correct `VertexBufferLayout` based on the vertex attributes
|
||||
let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?;
|
||||
|
||||
let view_layout = self
|
||||
.mesh_pipeline
|
||||
.get_view_layout(MeshPipelineViewLayoutKey::from(mesh_key));
|
||||
|
||||
Ok(RenderPipelineDescriptor {
|
||||
label: Some("Specialized Mesh Pipeline".into()),
|
||||
layout: vec![
|
||||
// Bind group 0 is the view uniform
|
||||
self.mesh_pipeline
|
||||
.get_view_layout(MeshPipelineViewLayoutKey::from(mesh_key))
|
||||
.clone(),
|
||||
// Bind group 1 is the mesh uniform
|
||||
view_layout.main_layout.clone(),
|
||||
view_layout.empty_layout.clone(),
|
||||
self.mesh_pipeline.mesh_layouts.model_only.clone(),
|
||||
],
|
||||
push_constant_ranges: vec![],
|
||||
|
||||
@ -163,7 +163,7 @@ impl AsBindGroup for BindlessMaterial {
|
||||
(
|
||||
// Screen texture
|
||||
//
|
||||
// @group(2) @binding(0) var textures: binding_array<texture_2d<f32>>;
|
||||
// @group(3) @binding(0) var textures: binding_array<texture_2d<f32>>;
|
||||
(
|
||||
0,
|
||||
texture_2d(TextureSampleType::Float { filterable: true })
|
||||
@ -171,7 +171,7 @@ impl AsBindGroup for BindlessMaterial {
|
||||
),
|
||||
// Sampler
|
||||
//
|
||||
// @group(2) @binding(1) var nearest_sampler: sampler;
|
||||
// @group(3) @binding(1) var nearest_sampler: sampler;
|
||||
//
|
||||
// Note: as with textures, multiple samplers can also be bound
|
||||
// onto one binding slot:
|
||||
|
||||
22
release-content/migration-guides/wgpu_25.md
Normal file
22
release-content/migration-guides/wgpu_25.md
Normal file
@ -0,0 +1,22 @@
|
||||
---
|
||||
title: `wgpu` 25
|
||||
pull_requests: [ 19563 ]
|
||||
---
|
||||
|
||||
`wgpu` 25 introduces a number of breaking changes, most notably in the way Bevy is required to handle
|
||||
uniforms with dynamic offsets which are used pervasively in the renderer. Dynamic offsets and uniforms
|
||||
of any kind are no longer allowed to be used in the same bind group as binding arrays. As such, the
|
||||
following changes to the default bind group numbering have been made in 3d:
|
||||
|
||||
- `@group(0)` view binding resources
|
||||
- `@group(1)` view resources requiring binding arrays
|
||||
- `@group(2)` mesh binding resources
|
||||
- `@group(3)` material binding resources
|
||||
|
||||
Most users who are not using mid-level render APIs will simply need to switch their material bind groups
|
||||
from `@group(2)` to `@group(3)`.
|
||||
|
||||
Exported float constants from shaders without an explicit type declaration like `const FOO = 1.0;` are no
|
||||
longer supported and must be explicitly typed like `const FOO: f32 = 1.0;`.
|
||||
|
||||
See the full changelog [here](https://github.com/gfx-rs/wgpu/blob/trunk/CHANGELOG.md#v2500-2025-04-10).
|
||||
Loading…
Reference in New Issue
Block a user