fn put_dynamic_array_max_index(
        &mut self,
        handle: Handle<crate::GlobalVariable>,
        context: &ExpressionContext,
    ) -> BackendResult {
        let global = &context.module.global_variables[handle];
        let (offset, array_ty) = match context.module.types[global.ty].inner {
            crate::TypeInner::Struct { ref members, .. } => match members.last() {
                Some(&crate::StructMember { offset, ty, .. }) => (offset, ty),
                None => return Err(Error::Validation),
            },
            crate::TypeInner::Array {
                size: crate::ArraySize::Dynamic,
                ..
            } => (0, global.ty),
            _ => return Err(Error::Validation),
        };

        let (size, stride) = match context.module.types[array_ty].inner {
            crate::TypeInner::Array { base, stride, .. } => (
                context.module.types[base]
                    .inner
                    .size(&context.module.constants),
                stride,
            ),
            _ => return Err(Error::Validation),
        };

        // When the stride length is larger than the size, the final element's stride of
        // bytes would have padding following the value. But the buffer size in
        // `buffer_sizes.sizeN` may not include this padding - it only needs to be large
        // enough to hold the actual values' bytes.
        //
        // So subtract off the size to get a byte size that falls at the start or within
        // the final element. Then divide by the stride size, to get one less than the
        // length, and then add one. This works even if the buffer size does include the
        // stride padding, since division rounds towards zero (MSL 2.4 §6.1). It will fail
        // if there are zero elements in the array, but the WebGPU `validating shader binding`
        // rules, together with draw-time validation when `minBindingSize` is zero,
        // prevent that.
        write!(
            self.out,
            "(_buffer_sizes.size{idx} - {offset} - {size}) / {stride}",
            idx = handle.index(),
            offset = offset,
            size = size,
            stride = stride,
        )?;
        Ok(())
    }
/// Write the maximum valid index of the dynamically sized array at the end of `handle`.
///
/// The 'maximum valid index' is simply one less than the array's length.
///
/// This emits an expression of the form `a / b`, so the caller must
/// parenthesize its output if it will be applying operators of higher
/// precedence.
///
/// `handle` must be the handle of a global variable whose final member is a
/// dynamically sized array.
Write the maximum valid index of the dynamically sized array at the end of `handle`.
The 'maximum valid index' is simply one less than the array's length.

This emits an expression of the form `a / b`, so the caller must
parenthesize its output if it will be applying operators of higher
precedence.

`handle` must be the handle of a global variable whose final member is a
dynamically sized array.
Write the maximum valid index of the dynamically sized array at the end of ` handle ` . The ' maximum valid index ' is simply one less than the array ' s length . This emits an expression of the form ` a / b ` so the caller must parenthesize its output if it will be applying operators of higher precedence . ` handle ` must be the handle of a global variable whose final member is a dynamically sized array .
fn put_dynamic_array_max_index(
        &mut self,
        handle: Handle<crate::GlobalVariable>,
        context: &ExpressionContext,
    ) -> BackendResult {
        let global = &context.module.global_variables[handle];
        let (offset, array_ty) = match context.module.types[global.ty].inner {
            crate::TypeInner::Struct { ref members, .. } => match members.last() {
                Some(&crate::StructMember { offset, ty, .. }) => (offset, ty),
                None => return Err(Error::Validation),
            },
            crate::TypeInner::Array {
                size: crate::ArraySize::Dynamic,
                ..
            } => (0, global.ty),
            _ => return Err(Error::Validation),
        };
        let (size, stride) = match context.module.types[array_ty].inner {
            crate::TypeInner::Array { base, stride, .. } => (
                context.module.types[base]
                    .inner
                    .size(&context.module.constants),
                stride,
            ),
            _ => return Err(Error::Validation),
        };
        // When the stride length is larger than the size, the final element's stride of
        // bytes would have padding following the value. But the buffer size in
        // `buffer_sizes.sizeN` may not include this padding - it only needs to be large
        // enough to hold the actual values' bytes.
        //
        // So subtract off the size to get a byte size that falls at the start or within
        // the final element. Then divide by the stride size, to get one less than the
        // length, and then add one. This works even if the buffer size does include the
        // stride padding, since division rounds towards zero (MSL 2.4 §6.1). It will fail
        // if there are zero elements in the array, but the WebGPU `validating shader binding`
        // rules, together with draw-time validation when `minBindingSize` is zero,
        // prevent that.
        write!(
            self.out,
            "(_buffer_sizes.size{idx} - {offset} - {size}) / {stride}",
            idx = handle.index(),
            offset = offset,
            size = size,
            stride = stride,
        )?;
        Ok(())
    }
fn put_dynamic_array_max_index ( & mut self , handle : Handle < crate :: GlobalVariable > , context : & ExpressionContext , ) -> BackendResult { let global = & context . module . global_variables [ handle ] ; let ( offset , array_ty ) = match context . module . types [ global . ty ] . inner { crate :: TypeInner :: Struct { ref members , .. } => match members . last ( ) { Some ( & crate :: StructMember { offset , ty , .. } ) => ( offset , ty ) , None => return Err ( Error :: Validation ) , } , crate :: TypeInner :: Array { size : crate :: ArraySize :: Dynamic , .. } => ( 0 , global . ty ) , _ => return Err ( Error :: Validation ) , } ; let ( size , stride ) = match context . module . types [ array_ty ] . inner { crate :: TypeInner :: Array { base , stride , .. } => ( context . module . types [ base ] . inner . size ( & context . module . constants ) , stride , ) , _ => return Err ( Error :: Validation ) , } ; // When the stride length is larger than the size, the final element's stride of // bytes would have padding following the value. But the buffer size in // `buffer_sizes.sizeN` may not include this padding - it only needs to be large // enough to hold the actual values' bytes. // // So subtract off the size to get a byte size that falls at the start or within // the final element. Then divide by the stride size, to get one less than the // length, and then add one. This works even if the buffer size does include the // stride padding, since division rounds towards zero (MSL 2.4 §6.1). It will fail // if there are zero elements in the array, but the WebGPU `validating shader binding` // rules, together with draw-time validation when `minBindingSize` is zero, // prevent that. write ! ( self out " " idx handle index ( ) offset offset size size stride stride ) ? ; Ok ( ( ) ) }
Write the maximum valid index of the dynamically sized array at the end of `handle`.
Write the maximum valid index of the dynamically sized array at the end of ` handle ` .
&mut self
handle
Handle<crate::GlobalVariable>
context
&ExpressionContext
&mut self
handle
Handle<crate::GlobalVariable>
context
&ExpressionContext