function getCopyBufferToTextureViaRenderCode()

in src/webgpu/util/texture.ts [260:401]


function getCopyBufferToTextureViaRenderCode(
  srcFormat: GPUTextureFormat,
  dstFormat: GPUTextureFormat
) {
  const info = kLoadValueFromStorageInfo[srcFormat];
  assert(!!info);
  const { storageType, texelType, unpackWGSL } = info;
  const { useFragDepth, discardWithStencil } = getDepthStencilOptionsForFormat(dstFormat);

  const [depthDecl, depthCode] = useFragDepth
    ? ['@builtin(frag_depth) d: f32,', 'fs.d = fs.v[0];']
    : ['', ''];

  const stencilCode = discardWithStencil ? 'if ((fs.v.r & vin.stencilMask) == 0) { discard; }' : '';

  const code = `
    struct Uniforms {
      numTexelRows: u32,
      bytesPerRow: u32,
      bytesPerSample: u32,
      sampleCount: u32,
      offset: u32,
    };

    struct VSOutput {
      @builtin(position) pos: vec4f,
      @location(0) @interpolate(flat, either) sampleIndex: u32,
      @location(1) @interpolate(flat, either) stencilMask: u32,
    };

    @vertex fn vs(@builtin(vertex_index) vNdx: u32, @builtin(instance_index) iNdx: u32) -> VSOutput {
      let points = array(
        vec2f(0, 0), vec2f(1, 0), vec2f(0, 1), vec2f(1, 1),
      );
      let sampleRow = vNdx / 4;
      let numSampleRows = f32(uni.numTexelRows * uni.sampleCount);
      let rowOffset = f32(sampleRow) / numSampleRows;
      let rowMult = 1.0 / numSampleRows;
      let p = (points[vNdx % 4] * vec2f(1, rowMult) + vec2f(0, rowOffset)) * 2.0 - 1.0;
      return VSOutput(
        vec4f(p, 0, 1),
        uni.sampleCount - sampleRow % uni.sampleCount - 1,
        1u << iNdx);
    }

    @group(0) @binding(0) var<uniform> uni: Uniforms;
    @group(0) @binding(1) var src: texture_2d<${storageType}>;

    // get a u32/i32/f32 from a r32uint/r32sint/r32float as though it was 1d array
    fn getSrc(offset: u32) -> ${storageType} {
      let width = textureDimensions(src, 0).x;
      let x = offset % width;
      let y = offset / width;
      return textureLoad(src, vec2u(x, y), 0).r;
    }

    const kFloat32FormatMantissaBits = 23;
    const kFloat32FormatBias = 127;
    fn floatBitsToNumber(
        rawBits: u32,
        bitOffset: u32,
        exponentBits: u32,
        mantissaBits: u32,
        bias: u32,
        signed: bool) -> f32 {
      let nonSignBits = exponentBits + mantissaBits;
      let allBits = nonSignBits + select(0u, 1u, signed);
      let allMask = (1u << allBits) - 1u;
      let bits = (rawBits >> bitOffset) & allMask;
      let nonSignBitsMask = (1u << nonSignBits) - 1u;
      let exponentAndMantissaBits = bits & nonSignBitsMask;
      let exponentMask = ((1u << exponentBits) - 1u) << mantissaBits;
      let infinityOrNaN = (bits & exponentMask) == exponentMask;
      if (infinityOrNaN) {
        let mantissaMask = (1u << mantissaBits) - 1;
        let signBit = 1u << nonSignBits;
        let isNegative = (bits & signBit) != 0;
        if ((bits & mantissaMask) != 0u) {
          return 0.0; // NaN (does not exist in WGSL)
        }
        if (isNegative) {
          return f32(-2e38); // NEGATIVE_INFINITY (does not exist in WGSL)
        } else {
          return f32(2e38); // POSITIVE_INFINITY (does not exist in WGSL)
        }
      }
      var f32BitsWithWrongBias =
        exponentAndMantissaBits << (kFloat32FormatMantissaBits - mantissaBits);
      // add in the sign
      f32BitsWithWrongBias |= (bits << (31u - nonSignBits)) & 0x80000000u;
      let numberWithWrongBias = bitcast<f32>(f32BitsWithWrongBias);
      return numberWithWrongBias * pow(2.0f, f32(kFloat32FormatBias - bias));
    }

    fn unpackRG11B10UFloat(v: u32) -> vec4f {
      return vec4f(
        floatBitsToNumber(v,  0, 5, 6, 15, false),
        floatBitsToNumber(v, 11, 5, 6, 15, false),
        floatBitsToNumber(v, 22, 5, 5, 15, false),
        1
      );
    }

    fn unpack(byteOffset: u32) -> ${texelType} {
      ${unpackWGSL};
    }

    struct FSOutput {
      @location(0) v: ${texelType},
      ${depthDecl}
    };

    @fragment fn fs(vin: VSOutput) -> FSOutput {
      let coord = vec2u(vin.pos.xy);
      let byteOffset =
        uni.offset +
        coord.y * uni.bytesPerRow +
        (coord.x * uni.sampleCount + vin.sampleIndex) * uni.bytesPerSample;
      var fs: FSOutput;
      fs.v = unpack(byteOffset);
      ${depthCode}
      ${stencilCode}
      return fs;
    }
    `;

  let dataFormat: GPUTextureFormat;
  switch (storageType) {
    case 'f32':
      dataFormat = 'r32float';
      break;
    case 'i32':
      dataFormat = 'r32sint';
      break;
    case 'u32':
      dataFormat = 'r32uint';
      break;
    default:
      unreachable();
  }
  return { code, dataFormat };
}