summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/tests/cts/checkout/src/webgpu/util/texture.ts
blob: d26508878f476ca1fd79af5ca5f393f11a46476a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import { assert } from '../../common/util/util.js';
import { kTextureFormatInfo } from '../capability_info.js';

import { align } from './math.js';
import { TexelView } from './texture/texel_view.js';
import { reifyExtent3D } from './unions.js';

/**
 * Creates a texture with the contents of a TexelView.
 */
export function makeTextureWithContents(
  device: GPUDevice,
  texelView: TexelView,
  desc: Omit<GPUTextureDescriptor, 'format'>
): GPUTexture {
  const { width, height, depthOrArrayLayers } = reifyExtent3D(desc.size);

  const { bytesPerBlock, blockWidth } = kTextureFormatInfo[texelView.format];
  // Currently unimplemented for compressed textures.
  assert(blockWidth === 1);

  // Compute bytes per row.
  const bytesPerRow = align(bytesPerBlock * width, 256);

  // Create a staging buffer to upload the texture contents.
  const stagingBuffer = device.createBuffer({
    mappedAtCreation: true,
    size: bytesPerRow * height * depthOrArrayLayers,
    usage: GPUBufferUsage.COPY_SRC,
  });

  // Write the texels into the staging buffer.
  texelView.writeTextureData(new Uint8Array(stagingBuffer.getMappedRange()), {
    bytesPerRow,
    rowsPerImage: height,
    subrectOrigin: [0, 0, 0],
    subrectSize: [width, height, depthOrArrayLayers],
  });
  stagingBuffer.unmap();

  // Create the texture.
  const texture = device.createTexture({
    ...desc,
    format: texelView.format,
    usage: desc.usage | GPUTextureUsage.COPY_DST,
  });

  // Copy from the staging buffer into the texture.
  const commandEncoder = device.createCommandEncoder();
  commandEncoder.copyBufferToTexture(
    { buffer: stagingBuffer, bytesPerRow },
    { texture },
    desc.size
  );
  device.queue.submit([commandEncoder.finish()]);

  // Clean up the staging buffer.
  stagingBuffer.destroy();

  return texture;
}