mgpuReadAsyncUint32 function
        
Future<void> 
mgpuReadAsyncUint32(
    
    
- MGPUBuffer buffer,
 - Uint32List outputData, {
 - int readElements = 0,
 - int elementOffset = 0,
 
Implementation
Future<void> mgpuReadAsyncUint32(
  MGPUBuffer buffer,
  Uint32List outputData, {
  int readElements = 0,
  int elementOffset = 0,
}) async {
  final int bytesPerElem = Uint32List.bytesPerElement;
  final int elementsToRead = (readElements > 0)
      ? readElements
      : (outputData.length - elementOffset);
  final int sizeToAllocate = elementsToRead * bytesPerElem;
  if (elementsToRead <= 0 ||
      elementOffset < 0 ||
      elementOffset >= outputData.length)
    return;
  final JSNumber ptr = _malloc(sizeToAllocate.toJS);
  final int startIndex = ptr.toDartInt ~/ bytesPerElem;
  try {
    // Add bounds check for the heap access
    if (startIndex < 0 || startIndex + elementsToRead > _heapU32.length) {
      throw StateError(
        'Uint32 buffer read would exceed heap bounds: '
        'trying to read $elementsToRead elements at index $startIndex '
        'but heap size is ${_heapU32.length}',
      );
    }
    await ccall(
      "mgpuReadSyncUint32".toJS, // Use sync C++ function
      "void".toJS,
      ["number", "number", "number", "number"].toJSDeep,
      [buffer, ptr, elementsToRead.toJS, elementOffset.toJS].toJSDeep,
      {"async": true}.toJSDeep,
    ).toDart;
    final output = _heapU32.sublist(startIndex, startIndex + elementsToRead);
    outputData.setAll(elementOffset, output);
  } finally {
    _free(ptr);
  }
}