createGpuTexture function

TextureHandle createGpuTexture(
  1. StorageMode storageMode,
  2. int width,
  3. int height, {
  4. TextureFormat format = TextureFormat.r8g8b8a8UNormInt,
  5. int sampleCount = 1,
  6. bool enableRenderTargetUsage = true,
  7. bool enableShaderReadUsage = true,
  8. int mipLevelCount = 1,
  9. TextureType type = TextureType.texture2D,
})

Creates a flutter_gpu texture together with the single handle that will ever stand for it.

The only place in lib/ that constructs a TextureHandle. That is what makes the identity contract hold rather than merely be documented: this returns the handle, the gpu.Texture never escapes as a value, and so no call site is in a position to wrap one a second time. identical() on two handles therefore answers the question callers actually mean.

The argument list mirrors gpuContext.createTexture — including its defaults — so a call site that moves here reads the same.

type is passed through rather than inferred. flutter_gpu derives a multisample type from sampleCount on its own, but a cube is not something any other argument implies, and it changes what the texture is: gpu.Texture.sliceCount becomes six, and overwrite starts taking a face index. A cube also asks for enableRenderTargetUsage false at every call site there is — nothing renders into a face, because ColorTarget has no slice to render into.

Implementation

TextureHandle createGpuTexture(
  StorageMode storageMode,
  int width,
  int height, {
  TextureFormat format = TextureFormat.r8g8b8a8UNormInt,
  int sampleCount = 1,
  bool enableRenderTargetUsage = true,
  bool enableShaderReadUsage = true,
  int mipLevelCount = 1,
  TextureType type = TextureType.texture2D,
}) {
  final texture = gpu.gpuContext.createTexture(
    storageMode.toGpu(),
    width,
    height,
    format: format.toGpu(),
    // Multisampling still decides the type when the caller has no opinion, and
    // that is not a nicety — passing a plain `texture2D` with a sample count
    // above one is a combination flutter_gpu refuses, and it refuses it as
    // "Texture creation failed" with nothing about which argument was wrong.
    // This line used to be absent for exactly that reason; a cube is the first
    // type no other argument implies, so the type is passed *and* the old
    // inference is kept.
    textureType: type == TextureType.texture2D && sampleCount > 1
        ? gpu.TextureType.texture2DMultisample
        : type.toGpu(),
    sampleCount: sampleCount,
    // Clamped to what the device will allocate. `fullMipCount` stops one short
    // of one-by-one, and asking for more than it throws — so the trim happens
    // here, where the limit is, rather than at every call site.
    mipLevelCount: mipLevelCount <= 1
        ? 1
        : (mipLevelCount < gpu.Texture.fullMipCount(width, height)
              ? mipLevelCount
              : gpu.Texture.fullMipCount(width, height)),
    enableRenderTargetUsage: enableRenderTargetUsage,
    enableShaderReadUsage: enableShaderReadUsage,
  );
  return TextureHandle(
    backend: texture,
    width: width,
    height: height,
    format: format,
    sampleCount: sampleCount,
    storageMode: storageMode,
    type: type,
  );
}