7 คะแนน โดย GN⁺ 2025-12-17 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ตลอด 10 ปีที่ผ่านมา กราฟิกส์ API ระดับล่างอย่าง DirectX 12, Vulkan, Metal ช่วยรีดประสิทธิภาพ GPU ได้มากขึ้น แต่ก็ทำให้ความซับซ้อนและต้นทุนการดูแลรักษาเพิ่มขึ้นอย่างรวดเร็ว
  • GPU ยุคใหม่รองรับ ลำดับชั้นแคชแบบสมบูรณ์, พอยน์เตอร์ 64 บิต, ทรัพยากรแบบ bindless ทำให้ state object และโมเดลการ bind ที่ซับซ้อนแบบเดิมไม่จำเป็นอีกต่อไป
  • ดีไซน์ที่เสนอใช้ การเข้าถึงหน่วยความจำแบบพอยน์เตอร์ C/C++ และ root pointer 64 บิตเพียงตัวเดียว เพื่อลดความซับซ้อนของเรนเดอริงไปป์ไลน์อย่างมาก
  • เสนอให้ตัด การระเบิดของ PSO, resource barrier, binding API ที่ซับซ้อน ออก และเชื่อม GPU memory กับ shader language เข้าหากันโดยตรง
  • แนวทางนี้คือ API รุ่นถัดไปที่เหมาะกับสถาปัตยกรรม GPU สมัยใหม่ และชี้ทิศทางที่ DirectX 13 หรือ Vulkan 2.0 ควรมุ่งไป

การเปลี่ยนแปลงของกราฟิกส์ API ระดับล่าง

  • ในปี 2013 สถาปัตยกรรม AMD GCN ของ Xbox One และ PS4 กลายเป็นมาตรฐานของการพัฒนาเกม AAA และทำให้เกิด API ระดับล่างอย่าง Mantle, DirectX 12, Vulkan และ Metal
    • กล่าวคือ API เหล่านี้ถูกออกแบบโดยอิงกับสถาปัตยกรรม GPU ในช่วงรอบปี 2013
  • DirectX 11/OpenGL แบบเดิมมีข้อจำกัดจากการเรนเดอร์แบบเธรดเดียวและ driver overhead ที่สูง
  • API เหล่านี้ลดต้นทุนของ draw call ด้วย pipeline object (PSO) ที่คอมไพล์ล่วงหน้า แต่เพราะไม่สอดคล้องกับโครงสร้างเอนจิน จึงเพิ่มความซับซ้อนขึ้น
  • ผลลัพธ์คือภายในเอนจินต้องมี “เลเยอร์ไดรเวอร์ระดับล่าง” เพิ่มขึ้นมาอีกชั้น และบทบาทของโปรแกรมเมอร์กราฟิกส์ก็ถูกแยกย่อยมากขึ้น

ภูมิหลังทางประวัติศาสตร์: ทำไมจึงซับซ้อนถึงเพียงนี้

  • GPU ยุคแรกมีโครงสร้างที่ยึดกับหน่วยความจำแบบแยกและ fixed-function pipeline
  • OpenGL และ DirectX เลือกใช้การออกแบบแบบ state-based และ object-based เพื่อ ทำ abstraction ให้กับความหลากหลายของฮาร์ดแวร์
  • แม้กระทั่งใน DirectX 11 texture และ buffer ก็ยังถูกจัดการผ่าน descriptor แบบทึบแสง
  • และแนวคิดการออกแบบนี้ก็ยัง สืบต่อมาแบบอาศัยแรงเฉื่อย จนถึง API รุ่นหลัง

ความไม่สอดคล้องกันระหว่าง GPU ยุคใหม่กับ API

  • ปัจจุบัน GPU รองรับ ลำดับชั้นแคชที่สอดคล้องกัน, PCIe ReBAR, พอยน์เตอร์ 64 บิต, bindless texture
  • จึงสามารถมี โครงสร้างที่ CPU เขียนลง GPU memory โดยตรง และ GPU อ่านได้ทันที
  • ในสภาพแวดล้อมเช่นนี้ โครงสร้างอย่าง PSO, descriptor set, binding table จึงไม่จำเป็น
  • ปัญหาการพอกพูนของ PSO cache ทำให้ต้องใช้แคชระดับหลายร้อย GB และกลายเป็นสาเหตุของ การโหลดล่าช้าและอาการกระตุก
  • API ใหม่สามารถตัดโครงสร้างล้าสมัยเหล่านี้ออก และเปลี่ยนไปใช้ การเข้าถึงแบบพอยน์เตอร์ที่เรียบง่าย ได้

การทำให้การจัดการ GPU memory ง่ายขึ้น

  • Vulkan/DirectX 12 แบบเดิมต้อง สร้าง resource แล้วค่อยตรวจสอบความเข้ากันได้ของ heap ทำให้ไม่มีประสิทธิภาพ
  • แนวทางที่เสนอใช้ API แบบง่ายในรูป gpuMalloc/gpuFree เพื่อจอง GPU memory โดยตรง
    • CPU สามารถ map GPU memory ได้โดยตรงเพื่อทำการ initialize
    • ข้อมูลขนาดใหญ่สามารถส่งผ่านคำสั่ง copy เพื่อให้เกิด การบีบอัด DCC และการจัดการ swizzle
  • มีการแยก address ที่ CPU map ได้ออกจาก GPU address และแปลงผ่าน gpuHostToDevicePointer

การทำให้ข้อมูลและ shader language ทันสมัยขึ้น

  • ใช้ shader language แบบพอยน์เตอร์ C/C++ เช่นเดียวกับ CUDA, Metal และ OpenCL
  • สามารถเข้าถึงหน่วยความจำได้อย่างมีประสิทธิภาพด้วย wide load ระดับ struct (128 บิตขึ้นไป)
  • ByteAddressBuffer หรือ texel buffer ของ DirectX ไม่ใช่ทางเลือกที่เหมาะที่สุดอีกต่อไป
  • GLSL/HLSL ไม่รองรับพอยน์เตอร์ จึง ขาดระบบนิเวศ shader library ที่นำกลับมาใช้ซ้ำได้ ขณะที่ CUDA พัฒนาไปจนมีไลบรารีที่อุดมสมบูรณ์

Root argument และโครงสร้างข้อมูล

  • GPU kernel รับอินพุตเป็น พอยน์เตอร์ 64 บิตเพียงตัวเดียว แล้ว cast เป็น struct
  • CPU และ GPU ใช้ C/C++ header ชุดเดียวกันเพื่อคงความสอดคล้องของโครงสร้างข้อมูล
  • ใช้คีย์เวิร์ด const/restrict เพื่อช่วยให้คอมไพเลอร์ optimize ได้ดีขึ้น และตัดการแยก UBO/SSBO ที่ไม่จำเป็น
  • ใช้ประโยชน์จาก scalar register preloading และ dynamic uniform optimization ของ GPU ยุคใหม่

การทำให้ texture binding ง่ายขึ้น

  • จัดการ texture ทั้งหมดผ่าน อาเรย์ descriptor 256 บิต (heap) ที่ CPU และ GPU เขียนได้โดยตรง
  • รองรับการสุ่มตัวอย่าง texture แบบ non-uniform ด้วย การเข้าถึงผ่านดัชนี 32 บิต
  • เรียบง่ายกว่า descriptor heap ของ DirectX 12 SM 6.6 และมีลักษณะคล้าย Vulkan VK_EXT_descriptor_buffer
  • การสร้างออบเจ็กต์ texture การอัปโหลด และการ sample ถูกรวมเป็นรูปแบบเดียวที่อิงกับ GPU memory pointer

Shader pipeline และค่าคงที่

  • การสร้าง pipeline ทำได้ง่ายเพียง โหลด shader IR แล้วเรียก gpuCreatePipeline
  • ไม่ต้องมี root signature, descriptor set หรือการกำหนด binding
  • ใช้ ค่าคงที่แบบ static (อิง struct) แทน shader specialization constant เพื่อลดปัญหา การระเบิดของชุดผสม PSO
  • struct ของค่าคงที่สามารถมี GPU pointer อยู่ภายในได้ จึง hardcode runtime address ได้โดยตรง

การทำให้ barrier และ synchronization ง่ายขึ้น

  • รายการ barrier แยกราย resource ของ API เดิมไม่สอดคล้องกับโครงสร้าง GPU ยุคใหม่
  • โมเดลที่เสนอใช้เพียง bitfield flag ระดับคิว/สเตจ
  • ทำให้ง่ายขึ้นเป็นรูป gpuBarrier(before, after, hazard) โดยไม่ต้องติดตาม resource
  • ใช้คำสั่ง gpuSignalAfter / gpuWaitBefore เพื่อทำ GPU→GPU synchronization ที่คล้าย timeline semaphore

Command buffer และการเรนเดอร์

  • ใช้เฉพาะ command buffer แบบใช้ครั้งเดียว (transient) และตัดโมเดลการนำกลับมาใช้ซ้ำที่ซับซ้อนของ Vulkan ออก
  • ใช้ gpuBeginRenderPass / gpuEndRenderPass เพื่อกำหนด render target และล้างค่า
  • ไม่มี barrier อัตโนมัติระหว่าง render pass จึงสามารถ optimize งานเรนเดอร์แบบขนานและ depth pre-pass ได้

การทำให้ raster pipeline ง่ายขึ้น

  • vertex/pixel shader เข้าถึงข้อมูลแบบพอยน์เตอร์ จึงไม่ต้องมี binding API
  • แยก GpuDepthStencilState, GpuBlendState ออกจาก PSO เพื่อลดจำนวนชุดผสม
  • GPU บนมือถือรองรับ programmable blending ผ่าน framebuffer fetch intrinsic
  • PSO จึงเก็บเฉพาะสถานะขั้นต่ำที่จำเป็น เช่น topology, format และจำนวน sample

Indirect draw และการเรนเดอร์ที่ขับเคลื่อนด้วย GPU

  • ส่งอาร์กิวเมนต์ทั้งหมด (data, arguments) ผ่าน GPU pointer
  • รองรับ multi-draw ด้วย gpuDrawIndexedInstancedIndirectMulti
  • GPU สามารถสร้าง root data และ draw argument ได้เองโดยตรง ทำให้สร้าง GPU-driven rendering แบบสมบูรณ์ได้

Tooling และความเข้ากันได้

  • โครงสร้างแบบพอยน์เตอร์สามารถติดตามได้ผ่านข้อมูล symbol เช่นเดียวกับ CUDA/Metal debugger
  • ได้รับการป้องกันด้วย virtual memory จึงไม่มีปัญหาด้านความปลอดภัย และจะเกิด page fault เมื่อเข้าถึงผิดพลาด
  • เช่นเดียวกับกรณีของ MoltenVK, Proton API เดิมอย่าง DirectX/Vulkan/Metal สามารถรองรับผ่านเลเยอร์แปลงได้

สเปกขั้นต่ำและบทสรุป

  • Nvidia Turing(2018), AMD RDNA1(2019), Intel Xe1(2022), Apple M1(2020) ต่างก็รองรับความสามารถที่เสนอทั้งหมด
  • GPU ยุคนี้เปลี่ยนไปเป็นสถาปัตยกรรมแบบ bindless, พอยน์เตอร์ 64 บิต, แคชที่สอดคล้องกัน แล้ว
  • มีเพียง API เท่านั้นที่ยังติดอยู่กับ abstraction แบบเก่า
  • API แบบใหม่จะ ง่ายกว่า DirectX 11, เร็วกว่า Vulkan และยืดหยุ่นกว่า Metal
  • Vulkan 2.0 / DirectX 13 รุ่นถัดไปควรเปลี่ยนไปสู่ ดีไซน์ bindless แบบสมบูรณ์ และผลักดันการขยายระบบนิเวศด้วย shader language แบบพอยน์เตอร์ C/C++ แทน HLSL/GLSL

1 ความคิดเห็น

 
GN⁺ 2025-12-17
ความเห็นจาก Hacker News
  • บทความนี้แสดงให้เห็นได้อย่างยอดเยี่ยมว่าส่วนไหนของ Vulkan และ DX12 ที่ไม่จำเป็น
    ทุกวันนี้ DX12 ดูเหมือนถูกปล่อยทิ้งไว้จนแทบไม่รองรับแม้แต่ buffer pointer แล้ว และ Vulkan เองก็ยังไม่ได้ถูกรวบให้เป็นระเบียบใน 2.0 เลยมีไดรเวอร์จำนวนมากที่ติดตั้ง ส่วนขยาย ได้ไม่สมบูรณ์
    ถ้ามี API แบบใหม่นี้จริง ก็น่าจะจำลอง OpenGL บนมันได้เร็วขึ้นมาก และอะไรอย่าง SDL3 GPU ก็น่าจะได้ประสิทธิภาพเพิ่มขึ้น 3~4 เท่า

    • สถานะของ เอกสาร DirectX ตอนนี้แย่มาก
      หนังสือของ Frank Luna ก็ไม่ได้ครอบคลุมฟีเจอร์ใหม่ ๆ ทั้งหมด ต้องไปไล่ดูทั้งใน Learn, ตัวอย่างบน GitHub และเอกสารอ้างอิง
      Vulkan ก็ซับซ้อนเหมือนกัน และถึงจะมี 2.0 ออกมาจริง ก็ยังสงสัยว่าในแพลตฟอร์มสำคัญอย่าง Android จะใช้งานจริงอย่างไร
    • คิดว่าทั้งหมดนี้อาจเป็นเพราะข้อกำหนด PCI Resizable BAR
      นอกจาก Intel Arc แล้ว GPU ส่วนใหญ่ก็ยังทำงานได้แม้ไม่มี reBAR แต่ดูเหมือน Microsoft หรือ Intel จะต้องบังคับใช้สิ่งนี้ผ่าน UEFI ก่อน ถึงจะใช้ฟีเจอร์อย่าง bindless texture ได้อย่างเสถียร
      แต่ถ้าทำแบบนั้นก็จะมีเส้นขั้นต่ำของฮาร์ดแวร์ที่รองรับ และเมนบอร์ดก่อนปี 2020 ก็รองรับแบบไม่สม่ำเสมอ
  • บทความนี้ขาดแรงจูงใจหลักไป
    ตามดัชนีของบล็อก ใจความคือ “ในช่วง 10 ปีที่ผ่านมา ความซับซ้อนของกราฟิกส์ API และภาษาชेडเดอร์เพิ่มขึ้นอย่างรวดเร็ว ตอนนี้จึงควร ทำให้ชั้น abstraction เรียบง่ายขึ้น เพื่อเพิ่มทั้งประสิทธิภาพการพัฒนาและประสิทธิภาพการทำงาน พร้อมรับมือกับ workload ของ GPU ในอนาคต”

    • มันคล้ายกับเหตุผลที่ NVMe ถือกำเนิดขึ้น
      ตอนแรก SSD ยังใช้ส่วนต่อประสาน IDE/SATA เดิมอยู่ แต่กว่าจะดึงประสิทธิภาพได้จริงก็ต้องทิ้งสมมติฐานแบบดิสก์หมุน แล้วออกแบบวิธีส่งถ่ายข้อมูลใหม่
      กราฟิกส์ API เองก็ดูจะมาถึงจุดที่ต้องทิ้ง ข้อจำกัดแบบ legacy เช่นกัน
  • ผมอาจมีอคติอยู่บ้างเพราะติดตามงานของ Sebastian Aaltonen มานาน แต่บทความนี้ยอดเยี่ยมจริง ๆ
    ผมคิดว่าทิศทางต่อจากนี้คือ การหวนกลับไปสู่ software rendering
    เพียงแต่ครั้งนี้ต่างออกไปตรงที่อัลกอริทึมและโครงสร้างข้อมูลเหล่านั้นจะได้แรงเร่งจากฮาร์ดแวร์
    ในวงการ VFX แนวโน้มแบบนี้เกิดขึ้นแล้ว และตัวอย่างหนึ่งคือเมื่อราว 5 ปีก่อน OTOY พอร์ต OctaneRender ไปอยู่บน CUDA

    • ภายใน GPU มี ฮาร์ดแวร์แบบ fixed-function อยู่มาก ถ้าตัดสิ่งเหล่านั้นทิ้ง ประสิทธิภาพจะลดลงมาก
      ประเภทของชेडเดอร์มีหน้าที่เชื่อมช่องว่างระหว่าง pipeline เหล่านี้ ดังนั้นการทำทุกอย่างให้เป็นซอฟต์แวร์ทั้งหมดจึงไม่สมจริงนัก
    • ที่จริงการเปลี่ยนแปลงแบบนี้ก็เกิดขึ้นแล้วบางส่วน
      ตัวอย่างเช่น Nanite ของ Unreal Engine ใช้ software rasterizer ที่ทำงานด้วย compute shader ของ GPU เมื่อต้องจัดการสามเหลี่ยมขนาดเล็ก
  • รายละเอียดในบทความนี้น่าประทับใจมาก
    แม้ผมจะเข้าใจเพียงบางส่วน แต่มันน่าจะกลายเป็นเอกสารอ้างอิงสำหรับ การออกแบบกราฟิกส์ API ในอนาคต
    สำหรับเกมเมอร์ส่วนใหญ่ Vulkan/DX12 ไม่ได้ให้ประโยชน์มากนัก และหลายเกมก็มีปัญหาเพราะเรื่อง PSO
    แม้ Vulkan จะกำลังปรับปรุงอยู่ แต่ WebGPU ก็ยังรับข้อจำกัดจากการออกแบบ Vulkan ยุคแรกมาด้วย
    ในสถานการณ์ที่ฮาร์ดแวร์พัฒนาเร็วมาก การลงไปสู่ API ระดับต่ำเกินไปอาจเป็นความผิดพลาด
    บางทีแนวทางแบบ CUDA ที่เน้นการประมวลผลทั่วไปอาจเป็นทิศทางที่ดีกว่า

  • ทำให้นึกถึง Mantle ขึ้นมา
    แม้มันจะมีข้อเสีย แต่ก็ให้ความรู้สึกเหมือนได้จับฮาร์ดแวร์โดยตรง และตอนพัฒนา Xbox 360 นั้นสนุกที่สุดแล้ว

    • กราฟิกส์ API ของ Switch ก็ยอดเยี่ยมคล้ายกัน
      Nvidia กับ Nintendo เป็นผู้ออกแบบ และผมคิดว่ามันเป็น API ของคอนโซลที่เข้าใจง่ายที่สุด
  • อ่านบทความนี้แล้วรู้สึกเหมือนได้เห็น ช่วงเวลาทางประวัติศาสตร์

  • ทำให้นึกถึง Google Toucan ซึ่งดูเหมือนจะเป็นโปรเจกต์ที่เกี่ยวข้อง

  • บทความนี้ทำให้นึกถึงความทรงจำเก่า ๆ หลายอย่าง
    ปัจจัยเพิ่มเติมที่นักออกแบบ API ต้องคำนึงถึงมี เช่น

    • GPU virtualization — ความสามารถที่ทำให้หลายแอปพลิเคชันแชร์ทรัพยากร GPU ร่วมกันได้ (เช่น D3D residency API)
    • พฤติกรรมที่ไม่กำหนดไว้ (Undefined Behavior) — ถ้าแอปพลิเคชันพึ่งพาสิ่งนี้โดยไม่ตั้งใจ การย้ายไป API ใหม่จะยากขึ้น
  • สงสัยว่าทำไม Microsoft ถึงไม่ออก DirectX เวอร์ชัน ใหม่
    DirectX Ultimate หรือ 12.2 เองก็แทบจะเหมือน DX12 เดิม
    เป็นเพราะมิดเดิลแวร์อย่าง Unreal Engine ทำให้ความสำคัญของ API ของตัวเองลดลงหรือเปล่า หรือว่า EPIC ควรเป็นฝ่ายเสนอ API ใหม่

    • การถกเถียงแบบนี้มักคึกคักอยู่แค่ใน ชุมชน FOSS
      นักพัฒนาเกมตัวจริงจะสร้าง RHI (Rendering Hardware Interface) แล้วไปโฟกัสกับการทำเกม
      Ray tracing กับ mesh shader เป็นนวัตกรรมที่ใหญ่ที่สุด แต่ก็ยังถูกใช้น้อย เลยดูเหมือนยังไปต่อไม่มากนัก
    • ในระดับหนึ่งก็คงถูกทั้งคู่
      ความ รวมศูนย์ ของเอนจินอย่าง Unreal, Unity ทำให้ความสนใจต่อการสร้างนวัตกรรมใน API ลดลง และความก้าวหน้าจึงไปอยู่ฝั่ง GPU เป็นหลัก
      API ฝั่ง CPU ยังอยู่แค่ระดับการแมปบัฟเฟอร์แบบเรียบง่าย
      คงต้องมีการเปลี่ยนแปลงฮาร์ดแวร์ครั้งใหม่เหมือนตอน tessellation shader ปรากฏขึ้น ถึงจะเกิดความคืบหน้า
  • สงสัยว่า Valve จะมีโอกาสสร้างกราฟิกส์ API ของตัวเองสำหรับ SteamOS หรือไม่

    • จริง ๆ แล้วความ ซับซ้อนของ Vulkan ก็เป็นความรับผิดชอบของ Valve ไม่น้อย
      เคยได้ยินมาว่าในช่วงพัฒนา Vulkan ระยะแรก Valve เป็นหนึ่งในผู้ผลักดันหลัก