1// A compute shader that unpacks bins.2//3// This shader runs before mesh preprocessing in order to generate4// `PreprocessWorkItem`s from cached bins. A single dispatch of this shader5// corresponds to a single batch set, and one invocation of this shader6// corresponds to one binned entity. Each shader invocation builds the work item7// for its entity by copying over the mesh input uniform index and calculating8// the position of the command in the indirect parameters buffer that will draw9// that entity.11#import bevy_pbr::mesh_preprocess_types::PreprocessWorkItem13// Information needed to unpack bins belonging to a single batch set.14struct BinUnpackingMetadata {15 // The index of the first `PreprocessWorkItem` that this compute shader16 // dispatch is to write to.17 base_output_work_item_index: u32,18 // The index of the first GPU indirect parameters command for this batch19 // set.20 base_indirect_parameters_index: u32,21 // The number of binned mesh instances in the `binned_mesh_instances`22 // array.23 binned_mesh_instance_count: u32,24 // Padding.25 pad_a: u32,26 // Padding.27 pad_b: array<vec4<u32>, 15>,28};30// One mesh instance in a bin.31//32// This corresponds to the CPU-side `GpuRenderBinnedMeshInstance` structure.33//34// Note that this structure isn't sorted within the35// `binned_mesh_instances` buffer. Instances from the same bin aren't36// guaranteed to be adjacent to one another.37struct BinnedMeshInstance {38 // The index of the `MeshInputUniform` corresponding to this mesh instance39 // in the `MeshInputUniform` buffer.40 input_uniform_index: u32,41 // The index of the bin that this mesh instance belongs to.42 bin_index: u32,43};45// Metadata for the entire batch set.46@group(0) @binding(0) var<uniform> bin_unpacking_metadata: BinUnpackingMetadata;48// The input array of `BinnedMeshInstance`s.49//50// Note that this array isn't sorted.51@group(0) @binding(1) var<storage> binned_mesh_instances: array<BinnedMeshInstance>;53// The output list of `PreprocessWorkItem`s.54@group(0) @binding(2) var<storage, read_write> preprocess_work_items: array<PreprocessWorkItem>;56// A mapping from each `bin_index` to the index of the GPU indirect parameters57// for this bin, relative to the start of the indirect parameters for this batch58// set.59@group(0) @binding(3) var<storage> bin_index_to_indirect_parameters_offset: array<u32>;61@compute62@workgroup_size(64)63fn main(@builtin(global_invocation_id) global_invocation_id: vec3<u32>) {64 // Figure out which instance we're looking at.65 let global_id = global_invocation_id.x;66 if (global_id >= bin_unpacking_metadata.binned_mesh_instance_count) {67 return;68 }70 // Unpack the `BinnedMeshInstance`.71 let input_uniform_index = binned_mesh_instances[global_id].input_uniform_index;72 let bin_index = binned_mesh_instances[global_id].bin_index;74 // Look up the indirect parameters index for this bin, relative to the first75 // indirect parameters offset for this batch set.76 let indirect_parameters_offset = bin_index_to_indirect_parameters_offset[bin_index];78 // Determine the location we should write the work item to.79 let output_index = bin_unpacking_metadata.base_output_work_item_index + global_id;81 // Write out the resulting work item.82 preprocess_work_items[output_index].input_index = input_uniform_index;83 preprocess_work_items[output_index].output_or_indirect_parameters_index =84 bin_unpacking_metadata.base_indirect_parameters_index + indirect_parameters_offset;85}