createBuffer method

  1. @override
StorageBuffer createBuffer(
  1. BufferDescriptor descriptor, {
  2. ByteData? contents,
})
override

A buffer of BufferDescriptor.lengthInBytes bytes, for the usages it names, holding contents (zeros by default).

The general form of uploadGeometry: one allocation a compute pass writes, an indirect draw reads its counts from, and a draw binds as vertices (StorageBuffer.asVertices) or indices (StorageBuffer.asIndices). DeviceFeature.buffers; a BufferUsage.storage buffer needs compute or renderStageStorage, and a BufferUsage.indirect one indirectDraw or indirectDispatch. Released through releaseStorageBuffer.

The one way to make a storage buffer, since 1.0. createStorageBuffer was a second call for a subset of this one: what it made is BufferUsage.standardStorage with the bytes as contents, plus BufferUsage.hostReadable for hostReadable: true and BufferUsage.index for bindableAsIndices: true (H11: a compute pass writes a draw's order and the draw reads it, nothing crossing back).

Implementation

@override
StorageBuffer createBuffer(
  BufferDescriptor descriptor, {
  ByteData? contents,
}) {
  features.require(DeviceFeature.buffers, backend: _name);
  if (descriptor.usage.contains(BufferUsage.storage)) {
    features.require(DeviceFeature.renderStageStorage, backend: _name);
  }
  calls.add(RecordedCall('createBuffer', arguments: descriptor));
  final serial = _serial++;
  GeometryBuffer? view(BufferUsage usage) => descriptor.usage.contains(usage)
      ? wrapGeometry(
          backend: 'fake buffer $serial',
          offsetInBytes: 0,
          lengthInBytes: descriptor.lengthInBytes,
        )
      : null;
  return _born(
    wrapStorageBuffer(
      owner: this,
      backend: 'fake buffer $serial',
      lengthInBytes: descriptor.lengthInBytes,
      hostReadable: descriptor.usage.contains(BufferUsage.hostReadable),
      asIndices: view(BufferUsage.index),
      asVertices: view(BufferUsage.vertex),
      usage: descriptor.usage,
    ),
  );
}