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

François Beaufort
François Beaufort

การรองรับฟังก์ชันบิวท์อิน DP4a ใน WGSL

DP4a (Dot Product of 4 Elements and Accumulate) หมายถึงชุดคำสั่ง GPU ที่ใช้กันโดยทั่วไปในการอนุมานการเรียนรู้เชิงลึกสำหรับการหาปริมาณ โดยจะดำเนินการ Dot Product ของจำนวนเต็ม 8 บิตอย่างมีประสิทธิภาพเพื่อเร่งการคำนวณโมเดลที่หาปริมาณ int8 ดังกล่าว ซึ่งช่วยประหยัดหน่วยความจำและแบนด์วิดท์เครือข่ายได้ (สูงสุด 75%) และปรับปรุงประสิทธิภาพของโมเดลแมชชีนเลิร์นนิงในการอนุมานเมื่อเทียบกับเวอร์ชัน f32 ด้วยเหตุนี้ ปัจจุบันจึงมีการใช้งานอย่างแพร่หลายในเฟรมเวิร์ก AI ยอดนิยมมากมาย

เมื่อส่วนขยายภาษา WGSL "packed_4x8_integer_dot_product" language extension อยู่ใน navigator.gpu.wgslLanguageFeatures ตอนนี้คุณสามารถใช้สเกลาร์จำนวนเต็ม 32 บิตเพื่อแพ็กเวกเตอร์ 4 องค์ประกอบของจำนวนเต็ม 8 บิตเป็นอินพุตสำหรับคำสั่ง Dot Product ในโค้ด Shader WGSL ด้วยฟังก์ชันบิวท์อิน dot4U8Packed และ dot4I8Packed นอกจากนี้ คุณยังใช้คำสั่งการแพ็กและการแกะแพ็กกับเวกเตอร์ 4 องค์ประกอบที่แพ็กแล้วของจำนวนเต็ม 8 บิตด้วย pack4xI8, pack4xU8, pack4xI8Clamp, pack4xU8Clamp, unpack4xI8, และ unpack4xU8 ฟังก์ชันบิวท์อิน WGSL ได้ด้วย

เราขอแนะนำให้ใช้ requires-directive เพื่อส่งสัญญาณถึงความเป็นไปได้ที่จะเกิดการไม่สามารถใช้งานร่วมกันได้ด้วย requires packed_4x8_integer_dot_product; ที่ด้านบนของโค้ด Shader WGSL ดูตัวอย่างต่อไปนี้และ ปัญหา tint:1497

if (!navigator.gpu.wgslLanguageFeatures.has("packed_4x8_integer_dot_product")) {
  throw new Error(`DP4a built-in functions are not available`);
}

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

const shaderModule = device.createShaderModule({ code: `
  requires packed_4x8_integer_dot_product;

  fn main() {
    const result: u32 = dot4U8Packed(0x01020304u, 0x02040405u); // 42
  }`,
});

ขอขอบคุณทีม Web Graphics ของ Intel ในเซี่ยงไฮ้เป็นพิเศษที่ขับเคลื่อนข้อกำหนดและการใช้งานนี้จนเสร็จสมบูรณ์

พารามิเตอร์ตัวชี้ที่ไม่จำกัดใน WGSL

ส่วนขยายภาษา WGSL "unrestricted_pointer_parameters" ช่วยลดข้อจำกัดเกี่ยวกับตัวชี้ที่สามารถส่งไปยังฟังก์ชัน WGSL ได้ดังนี้

  • ตัวชี้พารามิเตอร์ของพื้นที่ที่อยู่ storage, uniform และ workgroup ไปยังฟังก์ชันที่ผู้ใช้ประกาศ

  • การส่งตัวชี้ไปยังสมาชิกโครงสร้างและองค์ประกอบอาร์เรย์ไปยังฟังก์ชันที่ผู้ใช้ประกาศ

ดูข้อมูลเพิ่มเติมได้ที่ Pointers As Function Parameters | Tour of WGSL

คุณตรวจหาฟีเจอร์นี้ได้โดยใช้ navigator.gpu.wgslLanguageFeatures เราขอแนะนำให้ใช้ requires-directive เสมอเพื่อส่งสัญญาณถึงความเป็นไปได้ที่จะเกิดการไม่สามารถใช้งานร่วมกันได้ด้วย requires unrestricted_pointer_parameters; ที่ด้านบนของโค้ด Shader WGSL ดูตัวอย่างต่อไปนี้ การเปลี่ยนแปลงข้อกำหนด WGSL และ ปัญหา tint:2053

if (!navigator.gpu.wgslLanguageFeatures.has("unrestricted_pointer_parameters")) {
  throw new Error(`Unrestricted pointer parameters are not available`);
}

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

const shaderModule = device.createShaderModule({ code: `
  requires unrestricted_pointer_parameters;

  @group(0) @binding(0) var<storage, read_write> S : i32;

  fn func(pointer : ptr<storage, i32, read_write>) {
    *pointer = 42;
  }

  @compute @workgroup_size(1)
  fn main() {
    func(&S);
  }`
});

Syntax Sugar สำหรับการอ้างอิงแบบคอมโพสิตใน WGSL

เมื่อส่วนขยายภาษา WGSL "pointer_composite_access" อยู่ใน navigator.gpu.wgslLanguageFeatures ตอนนี้โค้ด Shader WGSL รองรับการเข้าถึงคอมโพเนนต์ของประเภทข้อมูลที่ซับซ้อนโดยใช้ไวยากรณ์จุด (.) เดียวกัน ไม่ว่าคุณจะทำงานกับข้อมูลโดยตรงหรือใช้ Pointer ไปยังข้อมูลนั้น วิธีการมีดังนี้

  • หาก foo เป็น Pointer foo.bar จะเป็นวิธีที่สะดวกกว่าในการเขียน (*foo).bar โดยปกติแล้วจะต้องใช้ดอกจัน (*) เพื่อเปลี่ยน Pointer ให้เป็น "การอ้างอิง" ที่สามารถอ้างอิงได้ แต่ตอนนี้ทั้ง Pointer และการอ้างอิงมีความคล้ายคลึงกันมากขึ้นและสามารถใช้แทนกันได้เกือบทั้งหมด

  • หาก foo ไม่ใช่ Pointer โอเปอเรเตอร์จุด (.) จะทำงานเหมือนกับที่คุณคุ้นเคยสำหรับการเข้าถึงสมาชิกโดยตรง

ในทำนองเดียวกัน หาก pa เป็นตัวชี้ที่จัดเก็บที่อยู่เริ่มต้นของอาร์เรย์ การใช้ pa[i] จะช่วยให้คุณเข้าถึงตำแหน่งหน่วยความจำที่จัดเก็บองค์ประกอบที่ 'i'th ของอาร์เรย์นั้นได้โดยตรง

เราขอแนะนำให้ใช้ requires-directive เพื่อส่งสัญญาณถึงความเป็นไปได้ที่จะเกิดการไม่สามารถใช้งานร่วมกันได้ด้วย requires pointer_composite_access; ที่ด้านบนของโค้ด Shader WGSL ดูตัวอย่างต่อไปนี้และ ปัญหา tint:2113

if (!navigator.gpu.wgslLanguageFeatures.has("pointer_composite_access")) {
  throw new Error(`Pointer composite access is not available`);
}

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

const shaderModule = device.createShaderModule({ code: `
  requires pointer_composite_access;

  fn main() {
    var a = vec3f();
    let p : ptr<function, vec3f> = &a;
    let r1 = (*p).x; // always valid.
    let r2 = p.x; // requires pointer composite access.
  }`
});

สถานะอ่านอย่างเดียวแยกกันสำหรับด้านข้างของสเตนซิลและความลึก

ก่อนหน้านี้ สิ่งแนบความลึก-สเตนซิลแบบอ่านอย่างเดียวใน Render Pass กำหนดให้ทั้ง 2 ด้านข้าง (ความลึกและสเตนซิล) ต้องเป็นแบบอ่านอย่างเดียว แต่ตอนนี้เราได้ยกเลิกข้อจำกัดนี้แล้ว โดยคุณสามารถใช้ด้านข้างความลึกในลักษณะอ่านอย่างเดียวได้ เช่น สำหรับการติดตามเงาที่สัมผัส ในขณะที่เขียนบัฟเฟอร์สเตนซิลเพื่อระบุพิกเซลสำหรับการประมวลผลเพิ่มเติม ดู ปัญหา dawn:2146

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

ตอนนี้ระบบจะเรียกใช้การเรียกกลับข้อผิดพลาดที่ไม่ได้ดักจับซึ่งตั้งค่าด้วย wgpuDeviceSetUncapturedErrorCallback() ทันทีเมื่อเกิดข้อผิดพลาด ซึ่งเป็นสิ่งที่นักพัฒนาแอปคาดหวังและต้องการอย่างสม่ำเสมอสำหรับการแก้ไขข้อบกพร่อง ดูการเปลี่ยนแปลง dawn:173620

เราได้นำเมธอด wgpuSurfaceGetPreferredFormat() จาก webgpu.h API มาใช้แล้ว ดู ปัญหา dawn:1362

ข้อมูลนี้ครอบคลุมเฉพาะไฮไลต์สำคัญบางส่วนเท่านั้น ดูรายการคอมมิตทั้งหมด

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

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

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