موارد جدید در WebGPU (Chrome 121)

فرانسوا بوفور
François Beaufort

پشتیبانی از WebGPU در اندروید

تیم کروم با هیجان اعلام می‌کند که WebGPU اکنون به طور پیش‌فرض در کروم ۱۲۱ در دستگاه‌هایی که اندروید ۱۲ و بالاتر دارند و از پردازنده‌های گرافیکی کوالکام و ARM استفاده می‌کنند، فعال شده است.

پشتیبانی به تدریج گسترش خواهد یافت تا طیف وسیع‌تری از دستگاه‌های اندرویدی، از جمله دستگاه‌هایی که در آینده نزدیک با اندروید ۱۱ کار می‌کنند را در بر بگیرد. این گسترش به آزمایش و بهینه‌سازی بیشتر برای اطمینان از یک تجربه یکپارچه در طیف وسیع‌تری از پیکربندی‌های سخت‌افزاری بستگی دارد. به شماره Chrome:1497815 مراجعه کنید.

تصویر نمونه WebGPU که روی کروم اندروید اجرا می‌شود.
نمونه WebGPU در حال اجرا بر روی کروم برای اندروید.

برای کامپایل سایه‌زن در ویندوز، به جای FXC از DXC استفاده کنید

کروم اکنون از قدرت DXC (کامپایلر دایرکت‌ایکس) برای کامپایل سایه‌زن‌ها در دستگاه‌های ویندوز D3D12 مجهز به سخت‌افزار گرافیکی SM6+ استفاده می‌کند. پیش از این، WebGPU برای کامپایل سایه‌زن‌ها در ویندوز به FXC (کامپایلر FX) متکی بود. FXC در حالی که کاربردی بود، فاقد مجموعه ویژگی‌ها و بهینه‌سازی‌های عملکرد موجود در DXC بود.

آزمایش‌های اولیه نشان می‌دهد که هنگام استفاده از DXC در مقایسه با FXC، به طور متوسط ​​20 درصد افزایش در سرعت کامپایل سایه‌زن محاسباتی وجود دارد.

کوئری‌های برچسب زمانی در پاس‌های محاسبه و رندر

پرس‌وجوهای برچسب زمانی به برنامه‌های WebGPU اجازه می‌دهند تا دقیقاً (تا حد نانوثانیه) مدت زمان لازم برای اجرای دستورات GPU و رندر را اندازه‌گیری کنند. آن‌ها به شدت برای کسب بینش در مورد عملکرد و رفتار بارهای کاری GPU مورد استفاده قرار می‌گیرند.

وقتی ویژگی "timestamp-query" در GPUAdapter در دسترس باشد، اکنون می‌توانید کارهای زیر را انجام دهید:

  • درخواست یک GPUDevice با ویژگی "timestamp-query" .
  • یک GPUQuerySet از نوع "timestamp" ایجاد کنید.
  • GPUComputePassDescriptor.timestampWrites و GPURenderPassDescriptor.timestampWrites برای تعریف محل نوشتن مقادیر timestamp در GPUQuerySet استفاده کنید.
  • مقادیر timestamp را با استفاده از resolveQuerySet() در یک GPUBuffer حل کنید.
  • با کپی کردن نتایج از GPUBuffer به CPU، مقادیر timestamp را دوباره بخوانید.
  • مقادیر timestamp را به صورت یک 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();

با توجه به نگرانی‌های مربوط به حمله زمان‌بندی ، کوئری‌های برچسب زمانی با وضوح ۱۰۰ میکروثانیه کوانتیزه می‌شوند که سازش خوبی بین دقت و امنیت ایجاد می‌کند. در مرورگر کروم، می‌توانید کوانتیزه کردن برچسب زمانی را با فعال کردن پرچم "ویژگی‌های توسعه‌دهنده WebGPU" در chrome://flags/#enable-webgpu-developer-features در طول توسعه برنامه خود غیرفعال کنید. برای کسب اطلاعات بیشتر به کوانتیزه کردن کوئری‌های برچسب زمانی مراجعه کنید.

از آنجایی که پردازنده‌های گرافیکی (GPU) ممکن است گاهی اوقات شمارنده‌ی مهر زمانی (timestamp) را ریست کنند، که می‌تواند منجر به مقادیر غیرمنتظره‌ای مانند اختلاف منفی بین مهرهای زمانی شود، توصیه می‌کنم تغییرات git diff را که پشتیبانی از پرس‌وجوی مهر زمانی را به نمونه‌ی Compute Boids زیر اضافه می‌کند، بررسی کنید.

تصویر نمونه Compute Boids با نمایش پرس و جوی مهر زمانی.
نمونه Compute Boids با پرس و جوی مهر زمانی.

نقاط ورودی پیش‌فرض به ماژول‌های سایه‌زن

برای بهبود تجربه توسعه‌دهنده، اکنون می‌توانید هنگام ایجاد یک خط لوله محاسبه یا رندر، 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

اکنون می‌توانید هنگام وارد کردن یک GPUExternalTexture از ویدیوهای HDR با استفاده از importExternalTexture() ، فضای رنگی مقصد را "display-p3" تنظیم کنید. بررسی کنید که WebGPU چگونه فضاهای رنگی را مدیریت می‌کند. به مثال زیر مراجعه کنید و chroma: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 نشان داده شده است.

به‌روزرسانی‌های سپیده‌دم

متدهای HasWGSLLanguageFeature و EnumerateWGSLLanguageFeatures در wgpu::Instance برای مدیریت ویژگی‌های زبان WGSL اضافه شده‌اند. به شماره dawn:2260 مراجعه کنید.

ویژگی غیر استاندارد wgpu::Feature::BufferMapExtendedUsages به شما امکان می‌دهد با wgpu::BufferUsage::MapRead یا wgpu::BufferUsage::MapWrite و هر wgpu::BufferUsage دیگری، یک بافر GPU ایجاد کنید. به مثال زیر و مشکل 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 ، پرس‌وجوی مهر زمانی درون گذرها ، ذخیره‌سازی محلی پیکسل ، ویژگی‌های سایه‌زن و قالب‌های چندصفحه‌ای .

تیم کروم یک مخزن رسمی گیت‌هاب برای داون ایجاد کرده است.

این فقط برخی از نکات برجسته کلیدی را پوشش می‌دهد. لیست جامع کامیت‌ها را بررسی کنید.

ویژگی‌های جدید WebGPU

فهرستی از تمام مواردی که در مجموعه «ویژگی‌های جدید WebGPU» پوشش داده شده است.

کروم ۱۵۱-۱۵۲

کروم ۱۴۹-۱۵۰

کروم ۱۴۷-۱۴۸

کروم ۱۴۶

کروم ۱۴۵

کروم ۱۴۴

کروم ۱۴۳

کروم ۱۴۲

کروم ۱۴۱

کروم ۱۴۰

کروم ۱۳۹

کروم ۱۳۸

کروم ۱۳۷

کروم ۱۳۶

کروم ۱۳۵

کروم ۱۳۴

کروم ۱۳۳

کروم ۱۳۲

کروم ۱۳۱

کروم ۱۳۰

کروم ۱۲۹

کروم ۱۲۸

کروم ۱۲۷

کروم ۱۲۶

کروم ۱۲۵

کروم ۱۲۴

کروم ۱۲۳

کروم ۱۲۲

کروم ۱۲۱

کروم ۱۲۰

کروم ۱۱۹

کروم ۱۱۸

کروم ۱۱۷

کروم ۱۱۶

کروم ۱۱۵

کروم ۱۱۴

کروم ۱۱۳

،

فرانسوا بوفور
François Beaufort

پشتیبانی از WebGPU در اندروید

تیم کروم با هیجان اعلام می‌کند که WebGPU اکنون به طور پیش‌فرض در کروم ۱۲۱ در دستگاه‌هایی که اندروید ۱۲ و بالاتر دارند و از پردازنده‌های گرافیکی کوالکام و ARM استفاده می‌کنند، فعال شده است.

پشتیبانی به تدریج گسترش خواهد یافت تا طیف وسیع‌تری از دستگاه‌های اندرویدی، از جمله دستگاه‌هایی که در آینده نزدیک با اندروید ۱۱ کار می‌کنند را در بر بگیرد. این گسترش به آزمایش و بهینه‌سازی بیشتر برای اطمینان از یک تجربه یکپارچه در طیف وسیع‌تری از پیکربندی‌های سخت‌افزاری بستگی دارد. به شماره Chrome:1497815 مراجعه کنید.

تصویر نمونه WebGPU که روی کروم اندروید اجرا می‌شود.
نمونه WebGPU در حال اجرا بر روی کروم برای اندروید.

برای کامپایل سایه‌زن در ویندوز، به جای FXC از DXC استفاده کنید

کروم اکنون از قدرت DXC (کامپایلر دایرکت‌ایکس) برای کامپایل سایه‌زن‌ها در دستگاه‌های ویندوز D3D12 مجهز به سخت‌افزار گرافیکی SM6+ استفاده می‌کند. پیش از این، WebGPU برای کامپایل سایه‌زن‌ها در ویندوز به FXC (کامپایلر FX) متکی بود. FXC در حالی که کاربردی بود، فاقد مجموعه ویژگی‌ها و بهینه‌سازی‌های عملکرد موجود در DXC بود.

آزمایش‌های اولیه نشان می‌دهد که هنگام استفاده از DXC در مقایسه با FXC، به طور متوسط ​​20 درصد افزایش در سرعت کامپایل سایه‌زن محاسباتی وجود دارد.

کوئری‌های برچسب زمانی در پاس‌های محاسبه و رندر

پرس‌وجوهای برچسب زمانی به برنامه‌های WebGPU اجازه می‌دهند تا دقیقاً (تا حد نانوثانیه) مدت زمان لازم برای اجرای دستورات GPU و رندر را اندازه‌گیری کنند. آن‌ها به شدت برای کسب بینش در مورد عملکرد و رفتار بارهای کاری GPU مورد استفاده قرار می‌گیرند.

وقتی ویژگی "timestamp-query" در GPUAdapter در دسترس باشد، اکنون می‌توانید کارهای زیر را انجام دهید:

  • درخواست یک GPUDevice با ویژگی "timestamp-query" .
  • یک GPUQuerySet از نوع "timestamp" ایجاد کنید.
  • GPUComputePassDescriptor.timestampWrites و GPURenderPassDescriptor.timestampWrites برای تعریف محل نوشتن مقادیر timestamp در GPUQuerySet استفاده کنید.
  • مقادیر timestamp را با استفاده از resolveQuerySet() در یک GPUBuffer حل کنید.
  • با کپی کردن نتایج از GPUBuffer به CPU، مقادیر timestamp را دوباره بخوانید.
  • مقادیر timestamp را به صورت یک 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();

با توجه به نگرانی‌های مربوط به حمله زمان‌بندی ، کوئری‌های برچسب زمانی با وضوح ۱۰۰ میکروثانیه کوانتیزه می‌شوند که سازش خوبی بین دقت و امنیت ایجاد می‌کند. در مرورگر کروم، می‌توانید کوانتیزه کردن برچسب زمانی را با فعال کردن پرچم "ویژگی‌های توسعه‌دهنده WebGPU" در chrome://flags/#enable-webgpu-developer-features در طول توسعه برنامه خود غیرفعال کنید. برای کسب اطلاعات بیشتر به کوانتیزه کردن کوئری‌های برچسب زمانی مراجعه کنید.

از آنجایی که پردازنده‌های گرافیکی (GPU) ممکن است گاهی اوقات شمارنده‌ی مهر زمانی (timestamp) را ریست کنند، که می‌تواند منجر به مقادیر غیرمنتظره‌ای مانند اختلاف منفی بین مهرهای زمانی شود، توصیه می‌کنم تغییرات git diff را که پشتیبانی از پرس‌وجوی مهر زمانی را به نمونه‌ی Compute Boids زیر اضافه می‌کند، بررسی کنید.

تصویر نمونه Compute Boids با نمایش پرس و جوی مهر زمانی.
نمونه Compute Boids با پرس و جوی مهر زمانی.

نقاط ورودی پیش‌فرض به ماژول‌های سایه‌زن

برای بهبود تجربه توسعه‌دهنده، اکنون می‌توانید هنگام ایجاد یک خط لوله محاسبه یا رندر، 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

اکنون می‌توانید هنگام وارد کردن یک GPUExternalTexture از ویدیوهای HDR با استفاده از importExternalTexture() ، فضای رنگی مقصد را "display-p3" تنظیم کنید. بررسی کنید که WebGPU چگونه فضاهای رنگی را مدیریت می‌کند. به مثال زیر مراجعه کنید و chroma: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 نشان داده شده است.

به‌روزرسانی‌های سپیده‌دم

متدهای HasWGSLLanguageFeature و EnumerateWGSLLanguageFeatures در wgpu::Instance برای مدیریت ویژگی‌های زبان WGSL اضافه شده‌اند. به شماره dawn:2260 مراجعه کنید.

ویژگی غیر استاندارد wgpu::Feature::BufferMapExtendedUsages به شما امکان می‌دهد با wgpu::BufferUsage::MapRead یا wgpu::BufferUsage::MapWrite و هر wgpu::BufferUsage دیگری، یک بافر GPU ایجاد کنید. به مثال زیر و مشکل 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 ، پرس‌وجوی مهر زمانی درون گذرها ، ذخیره‌سازی محلی پیکسل ، ویژگی‌های سایه‌زن و قالب‌های چندصفحه‌ای .

تیم کروم یک مخزن رسمی گیت‌هاب برای داون ایجاد کرده است.

این فقط برخی از نکات برجسته کلیدی را پوشش می‌دهد. لیست جامع کامیت‌ها را بررسی کنید.

ویژگی‌های جدید WebGPU

فهرستی از تمام مواردی که در مجموعه «ویژگی‌های جدید WebGPU» پوشش داده شده است.

کروم ۱۵۱-۱۵۲

کروم ۱۴۹-۱۵۰

کروم ۱۴۷-۱۴۸

کروم ۱۴۶

کروم ۱۴۵

کروم ۱۴۴

کروم ۱۴۳

کروم ۱۴۲

کروم ۱۴۱

کروم ۱۴۰

کروم ۱۳۹

کروم ۱۳۸

کروم ۱۳۷

کروم ۱۳۶

کروم ۱۳۵

کروم ۱۳۴

کروم ۱۳۳

کروم ۱۳۲

کروم ۱۳۱

کروم ۱۳۰

کروم ۱۲۹

کروم ۱۲۸

کروم ۱۲۷

کروم ۱۲۶

کروم ۱۲۵

کروم ۱۲۴

کروم ۱۲۳

کروم ۱۲۲

کروم ۱۲۱

کروم ۱۲۰

کروم ۱۱۹

کروم ۱۱۸

کروم ۱۱۷

کروم ۱۱۶

کروم ۱۱۵

کروم ۱۱۴

کروم ۱۱۳

،

فرانسوا بوفور
François Beaufort

پشتیبانی از WebGPU در اندروید

تیم کروم با هیجان اعلام می‌کند که WebGPU اکنون به طور پیش‌فرض در کروم ۱۲۱ در دستگاه‌هایی که اندروید ۱۲ و بالاتر دارند و از پردازنده‌های گرافیکی کوالکام و ARM استفاده می‌کنند، فعال شده است.

پشتیبانی به تدریج گسترش خواهد یافت تا طیف وسیع‌تری از دستگاه‌های اندرویدی، از جمله دستگاه‌هایی که در آینده نزدیک با اندروید ۱۱ کار می‌کنند را در بر بگیرد. این گسترش به آزمایش و بهینه‌سازی بیشتر برای اطمینان از یک تجربه یکپارچه در طیف وسیع‌تری از پیکربندی‌های سخت‌افزاری بستگی دارد. به شماره Chrome:1497815 مراجعه کنید.

تصویر نمونه WebGPU که روی کروم اندروید اجرا می‌شود.
نمونه WebGPU در حال اجرا بر روی کروم برای اندروید.

برای کامپایل سایه‌زن در ویندوز، به جای FXC از DXC استفاده کنید

کروم اکنون از قدرت DXC (کامپایلر دایرکت‌ایکس) برای کامپایل سایه‌زن‌ها در دستگاه‌های ویندوز D3D12 مجهز به سخت‌افزار گرافیکی SM6+ استفاده می‌کند. پیش از این، WebGPU برای کامپایل سایه‌زن‌ها در ویندوز به FXC (کامپایلر FX) متکی بود. FXC در حالی که کاربردی بود، فاقد مجموعه ویژگی‌ها و بهینه‌سازی‌های عملکرد موجود در DXC بود.

آزمایش‌های اولیه نشان می‌دهد که هنگام استفاده از DXC در مقایسه با FXC، به طور متوسط ​​20 درصد افزایش در سرعت کامپایل سایه‌زن محاسباتی وجود دارد.

کوئری‌های برچسب زمانی در پاس‌های محاسبه و رندر

پرس‌وجوهای برچسب زمانی به برنامه‌های WebGPU اجازه می‌دهند تا دقیقاً (تا حد نانوثانیه) مدت زمان لازم برای اجرای دستورات GPU و رندر را اندازه‌گیری کنند. آن‌ها به شدت برای کسب بینش در مورد عملکرد و رفتار بارهای کاری GPU مورد استفاده قرار می‌گیرند.

وقتی ویژگی "timestamp-query" در GPUAdapter در دسترس باشد، اکنون می‌توانید کارهای زیر را انجام دهید:

  • درخواست یک GPUDevice با ویژگی "timestamp-query" .
  • یک GPUQuerySet از نوع "timestamp" ایجاد کنید.
  • GPUComputePassDescriptor.timestampWrites و GPURenderPassDescriptor.timestampWrites برای تعریف محل نوشتن مقادیر timestamp در GPUQuerySet استفاده کنید.
  • مقادیر timestamp را با استفاده از resolveQuerySet() در یک GPUBuffer حل کنید.
  • با کپی کردن نتایج از GPUBuffer به CPU، مقادیر timestamp را دوباره بخوانید.
  • مقادیر timestamp را به صورت یک 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();

با توجه به نگرانی‌های مربوط به حمله زمان‌بندی ، کوئری‌های برچسب زمانی با وضوح ۱۰۰ میکروثانیه کوانتیزه می‌شوند که سازش خوبی بین دقت و امنیت ایجاد می‌کند. در مرورگر کروم، می‌توانید کوانتیزه کردن برچسب زمانی را با فعال کردن پرچم "ویژگی‌های توسعه‌دهنده WebGPU" در chrome://flags/#enable-webgpu-developer-features در طول توسعه برنامه خود غیرفعال کنید. برای کسب اطلاعات بیشتر به کوانتیزه کردن کوئری‌های برچسب زمانی مراجعه کنید.

از آنجایی که پردازنده‌های گرافیکی (GPU) ممکن است گاهی اوقات شمارنده‌ی مهر زمانی (timestamp) را ریست کنند، که می‌تواند منجر به مقادیر غیرمنتظره‌ای مانند اختلاف منفی بین مهرهای زمانی شود، توصیه می‌کنم تغییرات git diff را که پشتیبانی از پرس‌وجوی مهر زمانی را به نمونه‌ی Compute Boids زیر اضافه می‌کند، بررسی کنید.

تصویر نمونه Compute Boids با نمایش پرس و جوی مهر زمانی.
نمونه Compute Boids با پرس و جوی مهر زمانی.

نقاط ورودی پیش‌فرض به ماژول‌های سایه‌زن

برای بهبود تجربه توسعه‌دهنده، اکنون می‌توانید هنگام ایجاد یک خط لوله محاسبه یا رندر، 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

اکنون می‌توانید هنگام وارد کردن یک GPUExternalTexture از ویدیوهای HDR با استفاده از importExternalTexture() ، فضای رنگی مقصد را "display-p3" تنظیم کنید. بررسی کنید که WebGPU چگونه فضاهای رنگی را مدیریت می‌کند. به مثال زیر مراجعه کنید و chroma: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 نشان داده شده است.

به‌روزرسانی‌های سپیده‌دم

متدهای HasWGSLLanguageFeature و EnumerateWGSLLanguageFeatures در wgpu::Instance برای مدیریت ویژگی‌های زبان WGSL اضافه شده‌اند. به شماره dawn:2260 مراجعه کنید.

ویژگی غیر استاندارد wgpu::Feature::BufferMapExtendedUsages به شما امکان می‌دهد با wgpu::BufferUsage::MapRead یا wgpu::BufferUsage::MapWrite و هر wgpu::BufferUsage دیگری، یک بافر GPU ایجاد کنید. به مثال زیر و مشکل 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 ، پرس‌وجوی مهر زمانی درون گذرها ، ذخیره‌سازی محلی پیکسل ، ویژگی‌های سایه‌زن و قالب‌های چندصفحه‌ای .

تیم کروم یک مخزن رسمی گیت‌هاب برای داون ایجاد کرده است.

این فقط برخی از نکات برجسته کلیدی را پوشش می‌دهد. لیست جامع کامیت‌ها را بررسی کنید.

ویژگی‌های جدید WebGPU

فهرستی از تمام مواردی که در مجموعه «ویژگی‌های جدید WebGPU» پوشش داده شده است.

کروم ۱۵۱-۱۵۲

کروم ۱۴۹-۱۵۰

کروم ۱۴۷-۱۴۸

کروم ۱۴۶

کروم ۱۴۵

کروم ۱۴۴

کروم ۱۴۳

کروم ۱۴۲

کروم ۱۴۱

کروم ۱۴۰

کروم ۱۳۹

کروم ۱۳۸

کروم ۱۳۷

کروم ۱۳۶

کروم ۱۳۵

کروم ۱۳۴

کروم ۱۳۳

کروم ۱۳۲

کروم ۱۳۱

کروم ۱۳۰

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

،

François Beaufort
François Beaufort

Support WebGPU on Android

The Chrome team is excited to announce that WebGPU is now enabled by default in Chrome 121 on devices running Android 12 and greater powered by Qualcomm and ARM GPUs.

Support will gradually expand to encompass a wider range of Android devices, including those running on Android 11 in a near future. This expansion will be dependent on further testing and optimization to ensure a seamless experience across a broader range of hardware configurations. See issue chromium:1497815 .

Screenshot of WebGPU sample running on Chrome for Android.
WebGPU sample running on Chrome for Android.

Use DXC instead of FXC for shader compilation on Windows

Chrome now uses the power of DXC (DirectX Compiler) to compile shaders on Windows D3D12 machines equipped with SM6+ graphics hardware. Previously, WebGPU relied on FXC (FX Compiler) for shader compilation on Windows. While functional, FXC lacked the feature set and performance optimizations present in DXC.

Initial testing shows a 20% average increase in compute shader compilation speed when using DXC compared to FXC.

Timestamp queries in compute and render passes

Timestamp queries allow WebGPU applications to measure precisely (down to the nanosecond) how much time their GPU commands take to execute compute and render passes. They are heavily used to gain insights into the performance and behavior of GPU workloads.

When the "timestamp-query" feature is available in a GPUAdapter , you can now do the following things:

See the following example and issue 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();

Due to timing attack concerns, timestamp queries are quantized with a resolution of 100 microseconds, which provides a good compromise between precision and security. In Chrome browser, you can disable timestamp quantization by enabling the "WebGPU Developer Features" flag at chrome://flags/#enable-webgpu-developer-features during the development of your app. See Timestamp queries quantization to learn more.

As GPUs may reset the timestamp counter occasionally, which can result in unexpected values such as negative deltas between timestamps, I recommend you check out the git diff changes that adds timestamp query support to the following Compute Boids sample.

Screenshot of Compute Boids sample featuring timestamp query.
Compute Boids sample featuring timestamp query.

Default entry points to shader modules

To improve the developer experience, you can now omit the entryPoint of your shader module when creating a compute or render pipeline. If no unique entry point for the shader stage is found in the shader code, a GPUValidationError will be triggered. See the following example and 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 }] },
});

Support display-p3 as GPUExternalTexture color space

You can now set "display-p3" destination color space when importing a GPUExternalTexture from HDR videos with importExternalTexture() . Check out how WebGPU handles color spaces . See the following example and issue chromium:1330250 .

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

Memory heaps info

To help you anticipate memory limitations when allocating large amounts during the development of your app, requestAdapterInfo() now exposes memoryHeaps information such as the size and type of memory heaps available on the adapter. This experimental feature is accessible only when the "WebGPU Developer Features" flag at chrome://flags/#enable-webgpu-developer-features is enabled. See the following example and 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)   { /* ... */ }
}
Screenshot of https://webgpureport.org featuring memory heaps in adapter info.
Adapter info memory heaps shown on https://webgpureport.org .

Dawn updates

The HasWGSLLanguageFeature and EnumerateWGSLLanguageFeatures methods on wgpu::Instance have been added to handle WGSL language features. See issue dawn:2260 .

The non-standard wgpu::Feature::BufferMapExtendedUsages feature lets you create a GPU buffer with wgpu::BufferUsage::MapRead or wgpu::BufferUsage::MapWrite and any other wgpu::BufferUsage . See the following example and issue 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);

The following features have been documented: ANGLE Texture Sharing , D3D11 multithread protected , Implicit Device Synchronization , Norm16 texture formats , Timestamp Query Inside Passes , Pixel Local Storage , Shader Features , and Multi Planar Formats .

The Chrome team has created an official GitHub repository for Dawn .

This covers only some of the key highlights. Check out the exhaustive list of commits .

What's New in WebGPU

A list of everything that has been covered in the What's New in WebGPU series.

Chrome 151-152

Chrome 149-150

Chrome 147-148

Chrome 146

Chrome 145

Chrome 144

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