มีอะไรใหม่ใน WebGPU (Chrome 121)

François Beaufort
François Beaufort

รองรับ WebGPU ใน Android

ทีม Chrome ยินดีที่จะประกาศให้ทราบว่าตอนนี้ WebGPU เปิดใช้โดยค่าเริ่มต้นใน Chrome 121 บนอุปกรณ์ที่ใช้ Android 12 ขึ้นไปซึ่งขับเคลื่อนโดย GPU ของ Qualcomm และ ARM

เราจะค่อยๆ ขยายการรองรับให้ครอบคลุมอุปกรณ์ Android ที่หลากหลายมากขึ้น รวมถึงอุปกรณ์ที่ใช้ Android 11 ในอนาคตอันใกล้นี้ การขยายการให้บริการนี้จะขึ้นอยู่กับการทดสอบและการเพิ่มประสิทธิภาพเพิ่มเติมเพื่อให้มั่นใจว่าจะได้รับประสบการณ์การใช้งานที่ราบรื่นในฮาร์ดแวร์ที่มีการกำหนดค่าที่หลากหลายมากขึ้น ดูปัญหา chromium:1497815

ภาพหน้าจอของตัวอย่าง WebGPU ที่ทำงานใน Chrome สำหรับ Android
ตัวอย่าง WebGPU ที่ทำงานใน Chrome สำหรับ Android

ใช้ DXC แทน FXC สำหรับการคอมไพล์ Shader ใน Windows

ตอนนี้ Chrome ใช้ประสิทธิภาพของ DXC (DirectX Compiler) เพื่อคอมไพล์ Shader ในเครื่อง Windows D3D12 ที่มีฮาร์ดแวร์กราฟิก SM6+ ก่อนหน้านี้ WebGPU อาศัย FXC (FX Compiler) ในการคอมไพล์ Shader บน Windows แม้จะใช้งานได้ แต่ FXC ไม่มีชุดฟีเจอร์และการเพิ่มประสิทธิภาพที่ DXC มี

การทดสอบเบื้องต้นแสดงให้เห็นว่าความเร็วในการคอมไพล์ Compute Shader เพิ่มขึ้นโดยเฉลี่ย 20% เมื่อใช้ DXC เทียบกับ FXC

การค้นหาการประทับเวลาในพาสการประมวลผลและการแสดงผล

การค้นหาการประทับเวลาช่วยให้แอปพลิเคชัน WebGPU วัดได้อย่างแม่นยำ (ถึงระดับนาโนวินาที) ว่าคำสั่ง GPU ใช้เวลานานเท่าใดในการดำเนินการคำนวณและส่งผ่านการแสดงผล ซึ่งใช้กันอย่างแพร่หลายเพื่อรับข้อมูลเชิงลึกเกี่ยวกับประสิทธิภาพและลักษณะการทำงานของเวิร์กโหลด GPU

เมื่อฟีเจอร์ "timestamp-query" พร้อมใช้งานใน GPUAdapter คุณจะทำสิ่งต่อไปนี้ได้

  • ขอ GPUDevice ด้วยฟีเจอร์ "timestamp-query"
  • สร้าง GPUQuerySet ประเภท "timestamp"
  • ใช้ GPUComputePassDescriptor.timestampWrites และ GPURenderPassDescriptor.timestampWrites เพื่อกำหนดตำแหน่งที่จะเขียนค่าการประทับเวลาใน GPUQuerySet
  • แปลงค่าการประทับเวลาเป็น GPUBuffer ด้วย resolveQuerySet()
  • อ่านค่าการประทับเวลาย้อนกลับโดยคัดลอกผลลัพธ์จาก GPUBuffer ไปยัง CPU
  • ถอดรหัสค่าการประทับเวลาเป็น BigInt64Array

ดูตัวอย่างต่อไปนี้และออกคำสั่ง dawn:1800

const adapter = await navigator.gpu.requestAdapter();
if (!adapter.features.has("timestamp-query")) {
  throw new Error("Timestamp query feature is not available");
}
// Explicitly request timestamp query feature.
const device = await adapter.requestDevice({
  requiredFeatures: ["timestamp-query"],
});
const commandEncoder = device.createCommandEncoder();

// Create a GPUQuerySet which holds 2 timestamp query results: one for the
// beginning and one for the end of compute pass execution.
const querySet = device.createQuerySet({ type: "timestamp", count: 2 });
const timestampWrites = {
  querySet,
  beginningOfPassWriteIndex: 0, // Write timestamp in index 0 when pass begins.
  endOfPassWriteIndex: 1, // Write timestamp in index 1 when pass ends.
};
const passEncoder = commandEncoder.beginComputePass({ timestampWrites });
// TODO: Set pipeline, bind group, and dispatch work to be performed.
passEncoder.end();

// Resolve timestamps in nanoseconds as a 64-bit unsigned integer into a GPUBuffer.
const size = 2 * BigInt64Array.BYTES_PER_ELEMENT;
const resolveBuffer = device.createBuffer({
  size,
  usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC,
});
commandEncoder.resolveQuerySet(querySet, 0, 2, resolveBuffer, 0);

// Read GPUBuffer memory.
const resultBuffer = device.createBuffer({
  size,
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
});
commandEncoder.copyBufferToBuffer(resolveBuffer, 0, resultBuffer, 0, size);

// Submit commands to the GPU.
device.queue.submit([commandEncoder.finish()]);

// Log compute pass duration in nanoseconds.
await resultBuffer.mapAsync(GPUMapMode.READ);
const times = new BigInt64Array(resultBuffer.getMappedRange());
console.log(`Compute pass duration: ${Number(times[1] - times[0])}ns`);
resultBuffer.unmap();

เนื่องจากข้อกังวลเรื่องการโจมตีแบบกำหนดเวลา ระบบจึงกำหนดปริมาณการค้นหาการประทับเวลาด้วยความละเอียด 100 ไมโครวินาที ซึ่งเป็นการประนีประนอมที่ดีระหว่างความแม่นยำและความปลอดภัย ในเบราว์เซอร์ Chrome คุณสามารถปิดใช้การหาปริมาณการประทับเวลาได้โดยการเปิดใช้Flag "ฟีเจอร์สำหรับนักพัฒนาซอฟต์แวร์ WebGPU" ที่ chrome://flags/#enable-webgpu-developer-features ในระหว่างการพัฒนาแอป ดูข้อมูลเพิ่มเติมได้ที่การหาปริมาณการค้นหาการประทับเวลา

เนื่องจาก GPU อาจรีเซ็ตตัวนับการประทับเวลาเป็นครั้งคราว ซึ่งอาจส่งผลให้เกิดค่าที่ไม่คาดคิด เช่น ค่าเดลต้าที่เป็นลบระหว่างการประทับเวลา ฉันขอแนะนำให้คุณดูการเปลี่ยนแปลง git diff ที่เพิ่มการรองรับการค้นหาการประทับเวลาในตัวอย่าง Compute Boids ต่อไปนี้

ภาพหน้าจอของตัวอย่าง Compute Boids ที่มีการค้นหาการประทับเวลา
ตัวอย่าง Compute Boids ที่มีการค้นหาการประทับเวลา

จุดแรกเข้าเริ่มต้นของโมดูล Shader

ตอนนี้คุณสามารถละเว้น entryPoint ของโมดูล Shader เมื่อสร้างไปป์ไลน์การประมวลผลหรือการแสดงผลได้แล้ว เพื่อปรับปรุงประสบการณ์ของนักพัฒนาแอป หากไม่พบจุดแรกเข้าที่ไม่ซ้ำกันสำหรับขั้นตอนของ Shader ในโค้ด Shader ระบบจะทริกเกอร์ GPUValidationError ดูตัวอย่างต่อไปนี้และปัญหา dawn:2254

const code = `
    @vertex fn vertexMain(@builtin(vertex_index) i : u32) ->
      @builtin(position) vec4f {
       const pos = array(vec2f(0, 1), vec2f(-1, -1), vec2f(1, -1));
       return vec4f(pos[i], 0, 1);
    }
    @fragment fn fragmentMain() -> @location(0) vec4f {
      return vec4f(1, 0, 0, 1);
    }`;
const module = myDevice.createShaderModule({ code });
const format = navigator.gpu.getPreferredCanvasFormat();
const pipeline = await myDevice.createRenderPipelineAsync({
  layout: "auto",
  vertex: { module, entryPoint: "vertexMain" },
  fragment: { module, entryPoint: "fragmentMain", targets: [{ format }] },
  vertex: { module },
  fragment: { module, targets: [{ format }] },
});

รองรับ display-p3 เป็นพื้นที่สี GPUExternalTexture

ตอนนี้คุณสามารถตั้งค่า"display-p3"พื้นที่สีปลายทางเมื่อนำเข้า GPUExternalTexture จากวิดีโอ HDR ด้วย importExternalTexture() ได้แล้ว ดูวิธีที่ WebGPU จัดการพื้นที่สี โปรดดูตัวอย่างต่อไปนี้และปัญหา chromium:1330250

// Create texture from HDR video.
const video = document.querySelector("video");
const texture = myDevice.importExternalTexture({
  source: video,
  colorSpace: "display-p3",
});

ข้อมูลฮีปหน่วยความจำ

requestAdapterInfo() จะแสดงข้อมูล memoryHeaps เช่น ขนาดและประเภทของฮีปหน่วยความจำที่พร้อมใช้งานในอแดปเตอร์ เพื่อช่วยให้คุณคาดการณ์ข้อจำกัดด้านหน่วยความจำเมื่อจัดสรรหน่วยความจำจำนวนมากในระหว่างการพัฒนาแอป ฟีเจอร์ทดลองนี้จะเข้าถึงได้ก็ต่อเมื่อเปิดใช้Flag "ฟีเจอร์สำหรับนักพัฒนาซอฟต์แวร์ WebGPU" ที่ chrome://flags/#enable-webgpu-developer-features ดูตัวอย่างต่อไปนี้และปัญหา dawn:2249

const adapter = await navigator.gpu.requestAdapter();
const adapterInfo = await adapter.requestAdapterInfo();

for (const { size, properties } of adapterInfo.memoryHeaps) {
  console.log(size); // memory heap size in bytes
  if (properties & GPUHeapProperty.DEVICE_LOCAL)  { /* ... */ }
  if (properties & GPUHeapProperty.HOST_VISIBLE)  { /* ... */ }
  if (properties & GPUHeapProperty.HOST_COHERENT) { /* ... */ }
  if (properties & GPUHeapProperty.HOST_UNCACHED) { /* ... */ }
  if (properties & GPUHeapProperty.HOST_CACHED)   { /* ... */ }
}
ภาพหน้าจอของ https://webgpureport.org ที่แสดงฮีปหน่วยความจำในข้อมูลอะแดปเตอร์
ฮีปหน่วยความจำของข้อมูลอะแดปเตอร์ที่แสดงใน https://webgpureport.org

ข้อมูลอัปเดตเกี่ยวกับ Dawn

ระบบได้เพิ่มเมธอด HasWGSLLanguageFeature และ EnumerateWGSLLanguageFeatures ใน wgpu::Instance เพื่อจัดการฟีเจอร์ภาษา WGSL ดูปัญหา dawn:2260

ฟีเจอร์ wgpu::Feature::BufferMapExtendedUsages ที่ไม่ใช่มาตรฐานช่วยให้คุณสร้างบัฟเฟอร์ GPU ด้วย wgpu::BufferUsage::MapRead หรือ wgpu::BufferUsage::MapWrite และ wgpu::BufferUsage อื่นๆ ดูตัวอย่างต่อไปนี้และปัญหา dawn:2204

wgpu::BufferDescriptor descriptor = {
  .size = 128,
  .usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::Uniform
};
wgpu::Buffer uniformBuffer = device.CreateBuffer(&descriptor);

uniformBuffer.MapAsync(wgpu::MapMode::Write, 0, 128,
   [](WGPUBufferMapAsyncStatus status, void* userdata)
   {
      wgpu::Buffer* buffer = static_cast<wgpu::Buffer*>(userdata);
      memcpy(buffer->GetMappedRange(), data, sizeof(data));
   },
   &uniformBuffer);

ฟีเจอร์ต่อไปนี้ได้รับการบันทึกไว้แล้ว การแชร์เท็กซ์เจอร์ ANGLE, D3D11 แบบหลายเธรดที่ได้รับการปกป้อง, การซิงค์อุปกรณ์โดยนัย, รูปแบบเท็กซ์เจอร์ Norm16, การค้นหาการประทับเวลาภายในพาส, ที่เก็บข้อมูลในเครื่องระดับพิกเซล, ฟีเจอร์ของ Shader และรูปแบบหลายระนาบ

ทีม Chrome ได้สร้างที่เก็บ GitHub อย่างเป็นทางการสำหรับ Dawn

ซึ่งเป็นเพียงไฮไลต์สำคัญบางส่วนเท่านั้น ดูรายการคอมมิตทั้งหมด

มีอะไรใหม่ใน WebGPU

รายการทุกอย่างที่ครอบคลุมในซีรีส์มีอะไรใหม่ใน WebGPU

Chrome 139

Chrome 138

Chrome 137

Chrome 136

Chrome 135

Chrome 134

Chrome 133

Chrome 132

Chrome 131

Chrome 130

Chrome 129

Chrome 128

Chrome 127

Chrome 126

Chrome 125

Chrome 124

Chrome 123

Chrome 122

Chrome 121

Chrome 120

Chrome 119

Chrome 118

Chrome 117

Chrome 116

Chrome 115

Chrome 114

Chrome 113