מה חדש ב-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) כדי לקמפל הצללות במחשבי Windows D3D12 שמצוידים בחומרה גרפית SM6+. בעבר, WebGPU הסתמך על FXC (FX Compiler) לצורך קומפילציה של Shader ב-Windows. למרות ש-FXC היה פונקציונלי, לא היו בו את התכונות ואת האופטימיזציות של הביצועים שהיו ב-DXC.

בבדיקות ראשוניות שערכנו, ראינו עלייה ממוצעת של 20% במהירות ההידור של הצללות חישוביות כשמשתמשים ב-DXC בהשוואה ל-FXC.

שאילתות של חותמות זמן במעברי חישוב ועיבוד

שאילתות של חותמות זמן מאפשרות לאפליקציות WebGPU למדוד במדויק (עד לרמת הננו-שנייה) כמה זמן לוקח לפקודות ה-GPU שלהן לבצע חישובים ולהעביר שלבי עיבוד. הם משמשים בעיקר כדי לקבל תובנות לגבי הביצועים וההתנהגות של עומסי עבודה של מעבד גרפי.

אם התכונה "timestamp-query" זמינה ב-GPUAdapter, אפשר לבצע את הפעולות הבאות:

  • שליחת בקשה לGPUDevice באמצעות התכונה "timestamp-query".
  • יצירת GPUQuerySet מסוג "timestamp".
  • משתמשים ב-GPUComputePassDescriptor.timestampWrites וב-GPURenderPassDescriptor.timestampWrites כדי להגדיר איפה לכתוב ערכי חותמת זמן ב-GPUQuerySet.
  • המרת ערכים של חותמות זמן לערך GPUBuffer באמצעות resolveQuerySet().
  • כדי לקרוא את ערכי חותמת הזמן, מעתיקים את התוצאות מ-GPUBuffer אל המעבד.
  • פענוח ערכי חותמת הזמן כ-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, אפשר להשבית את הכימות של חותמות הזמן על ידי הפעלת הדגל WebGPU Developer Features (תכונות למפתחים של WebGPU) בכתובת chrome://flags/#enable-webgpu-developer-features במהלך הפיתוח של האפליקציה. מידע נוסף זמין במאמר כימות של שאילתות חותמות זמן.

יכול להיות שמדי פעם תהיה איפוס של מונה חותמות הזמן ב-GPU, מה שיכול לגרום לערכים לא צפויים כמו דלתאות שליליות בין חותמות זמן. לכן מומלץ לעיין בשינויים ב-git diff שמוסיפים תמיכה בשאילתות של חותמות זמן לדוגמה הבאה של Compute Boids.

צילום מסך של דוגמה ל-Compute Boids עם שאילתת חותמת זמן.
דוגמה ל-Compute Boids עם שאילתת חותמת זמן.

נקודות כניסה שמוגדרות כברירת מחדל למודולים של Shader

כדי לשפר את חוויית המפתחים, עכשיו אפשר להשמיט את entryPoint של מודול ההצללה כשיוצרים צינור עיבוד נתונים או צינור עיבוד תמונה. אם לא נמצאה נקודת כניסה ייחודית לשלב ההצללה בקוד ההצללה, תופעל GPUValidationError. דוגמה: issue 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, כמו הגודל והסוג של ערימות הזיכרון שזמינות במתאם. התכונה הניסיונית הזו זמינה רק כשהדגל 'WebGPU Developer Features' (תכונות למפתחים של WebGPU) מופעל בכתובת chrome://flags/#enable-webgpu-developer-features. דוגמה: issue 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.

עדכונים לגבי שעות השחר

השיטות 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 Texture Sharing,‏ D3D11 multithread protected,‏ Implicit Device Synchronization,‏ Norm16 texture formats,‏ Timestamp Query Inside Passes,‏ Pixel Local Storage,‏ Shader Features ו-Multi Planar Formats.

צוות Chrome יצר מאגר רשמי של Dawn ב-GitHub.

הסקירה הזו כוללת רק חלק מהנקודות העיקריות. רשימה מלאה של קומיטים

מה חדש ב-WebGPU

רשימה של כל הנושאים שמופיעים בסדרה What's New in WebGPU.

‫Chrome 142

Chrome 141

Chrome 140

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