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

רשימה של כל הנושאים שמופיעים בסדרת המאמרים מה חדש ב-WebGPU.

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