#[derive(Clone, Debug, Error)] #[non_exhaustive] pubenum BindGroupLayoutEntryError { #[error("Cube dimension is not expected for texture storage")]
StorageTextureCube, #[error("Atomic storage textures are not allowed by baseline webgpu, they require the native only feature TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES")]
StorageTextureAtomic, #[error("Arrays of bindings unsupported for this type of binding")]
ArrayUnsupported, #[error("Multisampled binding with sample type `TextureSampleType::Float` must have filterable set to false.")]
SampleTypeFloatFilterableBindingMultisampled, #[error("Multisampled texture binding view dimension must be 2d, got {0:?}")]
Non2DMultisampled(wgt::TextureViewDimension), #[error(transparent)]
MissingFeatures(#[from] MissingFeatures), #[error(transparent)]
MissingDownlevelFlags(#[from] MissingDownlevelFlags),
}
#[derive(Clone, Debug, Error)] #[non_exhaustive] pubenum CreateBindGroupLayoutError { #[error(transparent)]
Device(#[from] DeviceError), #[error("Conflicting binding at index {0}")]
ConflictBinding(u32), #[error("Binding {binding} entry is invalid")]
Entry {
binding: u32, #[source]
error: BindGroupLayoutEntryError,
}, #[error(transparent)]
TooManyBindings(BindingTypeMaxCountError), #[error("Bind groups may not contain both a binding array and a dynamically offset buffer")]
ContainsBothBindingArrayAndDynamicOffsetArray, #[error("Bind groups may not contain both a binding array and a uniform buffer")]
ContainsBothBindingArrayAndUniformBuffer, #[error("Binding index {binding} is greater than the maximum number {maximum}")]
InvalidBindingIndex { binding: u32, maximum: u32 }, #[error("Invalid visibility {0:?}")]
InvalidVisibility(wgt::ShaderStages), #[error("Binding index {binding}: {access:?} access to storage textures with format {format:?} is not supported")]
UnsupportedStorageTextureAccess {
binding: u32,
access: wgt::StorageTextureAccess,
format: wgt::TextureFormat,
},
}
// TODO: there may be additional variants here that can be extracted into // `BindingError`. #[derive(Clone, Debug, Error)] #[non_exhaustive] pubenum CreateBindGroupError { #[error(transparent)]
Device(#[from] DeviceError), #[error(transparent)]
DestroyedResource(#[from] DestroyedResourceError), #[error(transparent)]
BindingError(#[from] BindingError), #[error( "Binding count declared with at most {expected} items, but {actual} items were provided"
)]
BindingArrayPartialLengthMismatch { actual: usize, expected: usize }, #[error( "Binding count declared with exactly {expected} items, but {actual} items were provided"
)]
BindingArrayLengthMismatch { actual: usize, expected: usize }, #[error("Array binding provided zero elements")]
BindingArrayZeroLength, #[error("Binding size {actual} of {buffer} is less than minimum {min}")]
BindingSizeTooSmall {
buffer: ResourceErrorIdent,
actual: u64,
min: u64,
}, #[error("{0} binding size is zero")]
BindingZeroSize(ResourceErrorIdent), #[error("Number of bindings in bind group descriptor ({actual}) does not match the number of bindings defined in the bind group layout ({expected})")]
BindingsNumMismatch { actual: usize, expected: usize }, #[error("Binding {0} is used at least twice in the descriptor")]
DuplicateBinding(u32), #[error("Unable to find a corresponding declaration for the given binding {0}")]
MissingBindingDeclaration(u32), #[error(transparent)]
MissingBufferUsage(#[from] MissingBufferUsageError), #[error(transparent)]
MissingTextureUsage(#[from] MissingTextureUsageError), #[error("Binding declared as a single item, but bind group is using it as an array")]
SingleBindingExpected, #[error("Effective buffer binding size {size} for storage buffers is expected to align to {alignment}, but size is {size}")]
UnalignedEffectiveBufferBindingSizeForStorage { alignment: u32, size: u64 }, #[error("Buffer offset {0} does not respect device's requested `{1}` limit {2}")]
UnalignedBufferOffset(wgt::BufferAddress, &'static str, u32), #[error( "Buffer binding {binding} range {given} exceeds `max_*_buffer_binding_size` limit {limit}"
)]
BufferRangeTooLarge {
binding: u32,
given: u64,
limit: u64,
}, #[error("Binding {binding} has a different type ({actual:?}) than the one in the layout ({expected:?})")]
WrongBindingType { // Index of the binding
binding: u32, // The type given to the function
actual: wgt::BindingType, // Human-readable description of expected types
expected: &'static str,
}, #[error("Texture binding {binding} expects multisampled = {layout_multisampled}, but given a view with samples = {view_samples}")]
InvalidTextureMultisample {
binding: u32,
layout_multisampled: bool,
view_samples: u32,
}, #[error( "Texture binding {} expects sample type {:?}, but was given a view with format {:?} (sample type {:?})",
binding,
layout_sample_type,
view_format,
view_sample_type
)]
InvalidTextureSampleType {
binding: u32,
layout_sample_type: wgt::TextureSampleType,
view_format: wgt::TextureFormat,
view_sample_type: wgt::TextureSampleType,
}, #[error("Texture binding {binding} expects dimension = {layout_dimension:?}, but given a view with dimension = {view_dimension:?}")]
InvalidTextureDimension {
binding: u32,
layout_dimension: wgt::TextureViewDimension,
view_dimension: wgt::TextureViewDimension,
}, #[error("Storage texture binding {binding} expects format = {layout_format:?}, but given a view with format = {view_format:?}")]
InvalidStorageTextureFormat {
binding: u32,
layout_format: wgt::TextureFormat,
view_format: wgt::TextureFormat,
}, #[error("Storage texture bindings must have a single mip level, but given a view with mip_level_count = {mip_level_count:?} at binding {binding}")]
InvalidStorageTextureMipLevelCount { binding: u32, mip_level_count: u32 }, #[error("External texture bindings must have a single mip level, but given a view with mip_level_count = {mip_level_count:?} at binding {binding}")]
InvalidExternalTextureMipLevelCount { binding: u32, mip_level_count: u32 }, #[error("External texture bindings must have a format of `rgba8unorm`, `bgra8unorm`, or `rgba16float, but given a view with format = {format:?} at binding {binding}")]
InvalidExternalTextureFormat {
binding: u32,
format: wgt::TextureFormat,
}, #[error("Sampler binding {binding} expects comparison = {layout_cmp}, but given a sampler with comparison = {sampler_cmp}")]
WrongSamplerComparison {
binding: u32,
layout_cmp: bool,
sampler_cmp: bool,
}, #[error("Sampler binding {binding} expects filtering = {layout_flt}, but given a sampler with filtering = {sampler_flt}")]
WrongSamplerFiltering {
binding: u32,
layout_flt: bool,
sampler_flt: bool,
}, #[error("TLAS binding {binding} is required to support vertex returns but is missing flag AccelerationStructureFlags::ALLOW_RAY_HIT_VERTEX_RETURN")]
MissingTLASVertexReturn { binding: u32 }, #[error("Bound texture views can not have both depth and stencil aspects enabled")]
DepthStencilAspect, #[error(transparent)]
ResourceUsageCompatibility(#[from] ResourceUsageCompatibilityError), #[error(transparent)]
InvalidResource(#[from] InvalidResourceError),
}
/// Validate that the bind group layout does not contain both a binding array and a dynamic offset array. /// /// This allows us to use `UPDATE_AFTER_BIND` on vulkan for bindless arrays. Vulkan does not allow /// `UPDATE_AFTER_BIND` on dynamic offset arrays. See <https://github.com/gfx-rs/wgpu/issues/6737> pub(crate) fn validate_binding_arrays(&self) -> Result<(), CreateBindGroupLayoutError> { let has_dynamic_offset_array = self.dynamic_uniform_buffers > 0 || self.dynamic_storage_buffers > 0; let has_uniform_buffer = self.uniform_buffers.max().1 > 0; ifself.has_bindless_array && has_dynamic_offset_array { return Err(CreateBindGroupLayoutError::ContainsBothBindingArrayAndDynamicOffsetArray);
} ifself.has_bindless_array && has_uniform_buffer { return Err(CreateBindGroupLayoutError::ContainsBothBindingArrayAndUniformBuffer);
}
Ok(())
}
}
/// Bindable resource and the slot to bind it to. /// cbindgen:ignore #[derive(Clone, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pubstruct BindGroupEntry< 'a,
B = BufferId,
S = SamplerId,
TV = TextureViewId,
TLAS = TlasId,
ET = ExternalTextureId,
> where
[BufferBinding<B>]: ToOwned,
[S]: ToOwned,
[TV]: ToOwned,
[TLAS]: ToOwned,
<[BufferBinding<B>] as ToOwned>::Owned: fmt::Debug,
<[S] as ToOwned>::Owned: fmt::Debug,
<[TV] as ToOwned>::Owned: fmt::Debug,
<[TLAS] as ToOwned>::Owned: fmt::Debug,
{ /// Slot for which binding provides resource. Corresponds to an entry of the same /// binding index in the [`BindGroupLayoutDescriptor`]. pub binding: u32, #[cfg_attr(
feature = "serde",
serde(bound(deserialize = "BindingResource<'a, B, S, TV, TLAS, ET>: Deserialize<'de>"))
)] /// Resource to attach to the binding pub resource: BindingResource<'a, B, S, TV, TLAS, ET>,
}
/// Describes a group of bindings and the resources to be bound. #[derive(Clone, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pubstruct BindGroupDescriptor< 'a,
BGL = BindGroupLayoutId,
B = BufferId,
S = SamplerId,
TV = TextureViewId,
TLAS = TlasId,
ET = ExternalTextureId,
> where
[BufferBinding<B>]: ToOwned,
[S]: ToOwned,
[TV]: ToOwned,
[TLAS]: ToOwned,
<[BufferBinding<B>] as ToOwned>::Owned: fmt::Debug,
<[S] as ToOwned>::Owned: fmt::Debug,
<[TV] as ToOwned>::Owned: fmt::Debug,
<[TLAS] as ToOwned>::Owned: fmt::Debug,
[BindGroupEntry<'a, B, S, TV, TLAS, ET>]: ToOwned,
<[BindGroupEntry<'a, B, S, TV, TLAS, ET>] as ToOwned>::Owned: fmt::Debug,
{ /// Debug label of the bind group. /// /// This will show up in graphics debuggers for easy identification. pub label: Label<'a>, /// The [`BindGroupLayout`] that corresponds to this bind group. pub layout: BGL, #[cfg_attr(
feature = "serde",
serde(bound(
deserialize = "<[BindGroupEntry<'a, B, S, TV, TLAS, ET>] as ToOwned>::Owned: Deserialize<'de>"
))
)] /// The resources to bind to this bind group. #[allow(clippy::type_complexity)] pub entries: Cow<'a, [BindGroupEntry<'a, B, S, TV, TLAS, ET>]>,
}
/// Describes a [`BindGroupLayout`]. #[derive(Clone, Debug)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pubstruct BindGroupLayoutDescriptor<'a> { /// Debug label of the bind group layout. /// /// This will show up in graphics debuggers for easy identification. pub label: Label<'a>, /// Array of entries in this BindGroupLayout pub entries: Cow<'a, [wgt::BindGroupLayoutEntry]>,
}
/// Used by [`BindGroupLayout`]. It indicates whether the BGL must be /// used with a specific pipeline. This constraint only happens when /// the BGLs have been derived from a pipeline without a layout. #[derive(Clone, Debug)] pub(crate) enum ExclusivePipeline {
None,
Render(Weak<RenderPipeline>),
Compute(Weak<ComputePipeline>),
}
#[derive(Debug)] pubenum RawBindGroupLayout {
Owning(ManuallyDrop<Box<dyn hal::DynBindGroupLayout>>), /// The empty BGL was created by the device and will be destroyed by the device.
RefDeviceEmptyBGL,
}
/// Bind group layout. #[derive(Debug)] pubstruct BindGroupLayout { pub(crate) raw: RawBindGroupLayout, pub(crate) device: Arc<Device>, pub(crate) entries: bgl::EntryMap, /// It is very important that we know if the bind group comes from the BGL pool. /// /// If it does, then we need to remove it from the pool when we drop it. /// /// We cannot unconditionally remove from the pool, as BGLs that don't come from the pool /// (derived BGLs) must not be removed. pub(crate) origin: bgl::Origin, pub(crate) exclusive_pipeline: crate::OnceCellOrLock<ExclusivePipeline>, pub(crate) binding_count_validator: BindingTypeMaxCountValidator, /// The `label` from the descriptor used to create the resource. pub(crate) label: String,
}
impl Drop for BindGroupLayout { fn drop(&mutself) {
resource_log!("Destroy raw {}", self.error_ident()); if matches!(self.origin, bgl::Origin::Pool) { self.device.bgl_pool.remove(&self.entries);
} matchself.raw {
RawBindGroupLayout::Owning(refmut raw) => { // SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point. let raw = unsafe { ManuallyDrop::take(raw) }; unsafe { self.device.raw().destroy_bind_group_layout(raw);
}
}
RawBindGroupLayout::RefDeviceEmptyBGL => {}
}
}
}
#[derive(Clone, Debug, Error)] #[non_exhaustive] pubenum ImmediateUploadError { #[error( "Start offset {start_offset} overruns the immediate data range with a size of {immediate_size}"
)]
StartOffsetOverrun {
start_offset: u32,
immediate_size: u32,
}, #[error( "Provided immediate data start offset {0} does not respect \
`IMMEDIATE_DATA_ALIGNMENT` ({ida})",
ida = wgt::IMMEDIATE_DATA_ALIGNMENT
)]
StartOffsetUnaligned(u32), #[error( "Provided immediate data byte size {0} does not respect \
`IMMEDIATE_DATA_ALIGNMENT` ({ida})",
ida = wgt::IMMEDIATE_DATA_ALIGNMENT
)]
SizeUnaligned(u32), #[error( "Provided immediate data start offset {} + size {} overruns the immediate data range \
with a size of {}",
start_offset,
size,
immediate_size
)]
EndOffsetOverrun {
start_offset: u32,
size: u32,
immediate_size: u32,
}, #[error("Start index {start_index} overruns the value data range with {data_size} element(s)")]
ValueStartIndexOverrun { start_index: u32, data_size: usize }, #[error( "Start index {} + count of {} overruns the value data range \
with {} element(s)",
start_index,
count,
data_size
)]
ValueEndIndexOverrun {
start_index: u32,
count: u32,
data_size: usize,
},
}
/// Describes a pipeline layout. /// /// A `PipelineLayoutDescriptor` can be used to create a pipeline layout. #[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(bound = "BGL: Serialize"))] pubstruct PipelineLayoutDescriptor<'a, BGL = BindGroupLayoutId> where
[Option<BGL>]: ToOwned,
<[Option<BGL>] as ToOwned>::Owned: fmt::Debug,
{ /// Debug label of the pipeline layout. /// /// This will show up in graphics debuggers for easy identification. pub label: Label<'a>, /// Bind groups that this pipeline uses. The first entry will provide all the bindings for /// "set = 0", second entry will provide all the bindings for "set = 1" etc. #[cfg_attr(
feature = "serde",
serde(bound(deserialize = "<[Option<BGL>] as ToOwned>::Owned: Deserialize<'de>"))
)] pub bind_group_layouts: Cow<'a, [Option<BGL>]>, /// The number of bytes of immediate data that are allocated for use /// in the shader. The `var<immediate>`s in the shader attached to /// this pipeline must be equal or smaller than this size. /// /// If this value is non-zero, [`wgt::Features::IMMEDIATES`] must be enabled. pub immediate_size: u32,
}
#[derive(Debug)] pubstruct PipelineLayout { pub(crate) raw: ManuallyDrop<Box<dyn hal::DynPipelineLayout>>, pub(crate) device: Arc<Device>, /// The `label` from the descriptor used to create the resource. pub(crate) label: String, pub(crate) bind_group_layouts: ArrayVec<Option<Arc<BindGroupLayout>>, { hal::MAX_BIND_GROUPS }>, pub(crate) immediate_size: u32,
}
impl Drop for PipelineLayout { fn drop(&mutself) {
resource_log!("Destroy raw {}", self.error_ident()); // SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point. let raw = unsafe { ManuallyDrop::take(&mutself.raw) }; unsafe { self.device.raw().destroy_pipeline_layout(raw);
}
}
}
pub(crate) fn get_bgl_entry(
&self,
group: u32,
binding: u32,
) -> Option<&wgt::BindGroupLayoutEntry> { let bgl = self.bind_group_layouts.get(group as usize)?; let bgl = bgl.as_ref()?;
bgl.entries.get(binding)
}
/// Validate immediates match up with expected ranges. pub(crate) fn validate_immediates_ranges(
&self,
offset: u32,
size_bytes: u32,
) -> Result<(), ImmediateUploadError> { // Don't need to validate size against the immediate data size limit here, // as immediate data ranges are already validated to be within bounds, // and we validate that they are within the ranges.
if !offset.is_multiple_of(wgt::IMMEDIATE_DATA_ALIGNMENT) { return Err(ImmediateUploadError::StartOffsetUnaligned(offset));
}
if !size_bytes.is_multiple_of(wgt::IMMEDIATE_DATA_ALIGNMENT) { return Err(ImmediateUploadError::SizeUnaligned(offset));
}
/// Size of the binding. If `None`, the binding spans from `offset` to the /// end of the buffer. /// /// We use `BufferAddress` to allow a size of zero on this `wgpu_core` type, /// because JavaScript bindings cannot readily express `Option<NonZeroU64>`. /// The `wgpu` API uses `Option<BufferSize>` (i.e. `NonZeroU64`) for this /// field. pub size: Option<wgt::BufferAddress>,
}
#[derive(Debug)] pubstruct BindGroupDynamicBindingData { /// The index of the binding. /// /// Used for more descriptive errors. pub(crate) binding_idx: u32, /// The size of the buffer. /// /// Used for more descriptive errors. pub(crate) buffer_size: wgt::BufferAddress, /// The range that the binding covers. /// /// Used for more descriptive errors. pub(crate) binding_range: Range<wgt::BufferAddress>, /// The maximum value the dynamic offset can have before running off the end of the buffer. pub(crate) maximum_dynamic_offset: wgt::BufferAddress, /// The binding type. pub(crate) binding_type: wgt::BufferBindingType,
}
#[derive(Debug)] pub(crate) struct BindGroupLateBufferBindingInfo { /// The normal binding index in the bind group. pub binding_index: u32, /// The size that exists at bind time. pub size: wgt::BufferSize,
}
#[derive(Debug)] pubstruct BindGroup { pub(crate) raw: Snatchable<Box<dyn hal::DynBindGroup>>, pub(crate) device: Arc<Device>, pub(crate) layout: Arc<BindGroupLayout>, /// The `label` from the descriptor used to create the resource. pub(crate) label: String, pub(crate) tracking_data: TrackingData, pub(crate) used: BindGroupStates, pub(crate) buffer_init_actions: Vec<BufferInitTrackerAction>, pub(crate) texture_init_actions: Vec<TextureInitTrackerAction>, /// INVARIANT: Sorted by binding index order. pub(crate) dynamic_binding_info: Vec<BindGroupDynamicBindingData>, /// Actual binding sizes for buffers that don't have `min_binding_size` /// specified in BGL. Listed in the order of iteration of `BGL.entries`. pub(crate) late_buffer_binding_infos: Vec<BindGroupLateBufferBindingInfo>,
}
impl Drop for BindGroup { fn drop(&mutself) { iflet Some(raw) = self.raw.take() {
resource_log!("Destroy raw {}", self.error_ident()); unsafe { self.device.raw().destroy_bind_group(raw);
}
}
}
}
#[derive(Clone, Debug, Error, Eq, PartialEq)] #[error( "In bind group index {group_index}, the buffer bound at binding index {binding_index} \
is bound with size {bound_size} where the shader expects {shader_size}."
)] pubstruct LateMinBufferBindingSizeMismatch { pub group_index: u32, pub binding_index: u32, pub shader_size: wgt::BufferAddress, pub bound_size: wgt::BufferAddress,
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.25 Sekunden
(vorverarbeitet am 2026-08-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.