מה חדש ב-WebGPU (Chrome 121)

François Beaufort
François Beaufort

תמיכה ב-WebGPU ב-Android

צוות Chrome שמח להודיע ש-WebGPU מופעל עכשיו כברירת מחדל ב-Chrome 121 במכשירים עם Android 12 ומעלה שמבוססים על מעבדי Qualcomm ו-ARM.

התמיכה תורחב בהדרגה למגוון רחב יותר של מכשירי Android, כולל מכשירים עם Android 11 בעתיד הקרוב. ההרחבה הזו תהיה תלויה בבדיקות ובאופטימיזציה נוספות כדי להבטיח חוויה חלקה במגוון רחב יותר של תצורות חומרה. מידע נוסף

צילום מסך של דוגמה ל-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.

בבדיקות ראשוניות שערכנו, המהירות של קימפול shader לחישוב הייתה גבוהה ב-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 עם שאילתת חותמת זמן.
דוגמה לחישוב של 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' ב-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.

עדכונים של Dawn

השיטות HasWGSLLanguageFeature ו-EnumerateWGSLLanguageFeatures ב-wgpu::Instance נוספו כדי לטפל בתכונות של שפת WGSL. מידע נוסף

התכונה הלא סטנדרטית 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 143

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