2 คะแนน โดย GN⁺ 2024-02-15 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • แม้ M1 จะค้างอยู่ที่ OpenGL 4.1 มาหลายปี แต่ไดรเวอร์ M1/M2 รุ่นล่าสุดของ Fedora Asahi Remix รองรับ OpenGL 4.6 และ OpenGL ES 3.2 อย่างสมบูรณ์แล้ว
  • ไดรเวอร์ Linux แบบโอเพนซอร์สของ Asahi เป็น ไดรเวอร์ที่ผ่านการรับรองความสอดคล้อง ซึ่งอยู่ในรายชื่อของ Khronos ต่างจากไดรเวอร์ 4.1 ของผู้ผลิตที่ไม่สอดคล้องกัน จึงขยายความเข้ากันได้กับเวิร์กโหลด OpenGL สมัยใหม่อย่าง Blender
  • OpenGL 4.6 ต้องการ robustness, SPIR-V, clip control, cull distance, compute shaders และ transform feedback ที่ปรับปรุงแล้ว แต่ ฮาร์ดแวร์ M1 ไม่ได้ตรงกับมาตรฐานกราฟิกสมัยใหม่แบบตรงตัว
  • ฟีเจอร์ที่ฮาร์ดแวร์ไม่มีถูกชดเชยด้วยเทคนิคของไดรเวอร์และคอมไพเลอร์: geometry shaders, tessellation, transform feedback ถูกทำผ่าน compute shaders ส่วน cull distance และ clip control จัดการด้วยการแปลง shader
  • เพื่อผ่านการทดสอบความสอดคล้องมากกว่า 100,000 รายการ ได้มีการทำ robustness ของบัฟเฟอร์และอิมเมจในซอฟต์แวร์ พร้อมลดต้นทุนเพิ่มเติมด้วย clamp, การเพิ่มประสิทธิภาพ preamble และวิธีเลี่ยง mipmap

ใช้ OpenGL 4.6/ES 3.2 ได้บน Fedora Asahi Remix

  • ก่อนหน้านี้ M1 รองรับได้ถึง OpenGL 4.1 เท่านั้น แต่ตอนนี้รองรับ OpenGL 4.6 และ OpenGL ES 3.2 แล้ว
  • ไดรเวอร์ล่าสุดสำหรับซีรีส์ M1/M2 ใช้งานได้ผ่านการติดตั้ง Fedora Asahi Remix
  • ผู้ใช้ที่ติดตั้งไว้แล้วอัปเดตได้ด้วยคำสั่งต่อไปนี้
    • dnf upgrade --refresh
  • ไดรเวอร์ Mesa แบบโอเพนซอร์สของ Asahi มี ความสอดคล้อง (conformance) กับ OpenGL เวอร์ชันใหม่ ต่างจากไดรเวอร์ 4.1 ของผู้ผลิตที่ไม่สอดคล้องกัน
  • ไดรเวอร์ 4.6/3.2 ที่สอดคล้องต้องผ่าน การทดสอบมากกว่า 100,000 รายการ เพื่อรับประกันความถูกต้อง
    • รายชื่อทางการของ Khronos มี OpenGL 4.6 และ OpenGL ES 3.2 ของ Asahi รวมอยู่ด้วย
  • หลังจากเมื่อ 6 เดือนก่อนมีไดรเวอร์ OpenGL ES 3.1 ซึ่งเป็นไดรเวอร์ตัวแรกของ M1 ที่ผ่านความสอดคล้องสำหรับกราฟิก API มาตรฐาน ครั้งนี้ก็ทำ OpenGL 4.6 ได้สำเร็จแล้ว
  • การรองรับ Vulkan ก็อยู่ระหว่างดำเนินการ

การทำฟีเจอร์เพื่อข้ามกำแพง OpenGL 4.1

  • OpenGL 4.6 เพิ่ม ฟีเจอร์บังคับ หลายอย่างเมื่อเทียบกับ 4.1
    • Robustness
    • SPIR-V
    • Clip control
    • Cull distance
    • Compute shaders
    • transform feedback ที่อัปเกรดแล้ว
  • M1 ไม่ได้เหมาะกับมาตรฐานกราฟิกที่ใหม่กว่า OpenGL ES 3.1 มากนัก
    • Vulkan ทำให้บางฟีเจอร์เป็นตัวเลือกได้ แต่หากจะซ้อน DirectX และ OpenGL ไว้ด้านบน ก็ยังต้องการฟีเจอร์ที่ขาดหายไป
    • วิธีเดิมบน M1 จึงไปไม่เกินชุดฟีเจอร์ของ OpenGL 4.1
  • ฟีเจอร์ใหม่ที่ไม่มีการรองรับในฮาร์ดแวร์ถูกทำขึ้นด้วย เทคนิคของไดรเวอร์
    • Geometry shaders, tessellation และ transform feedback ถูกทำผ่าน compute shaders
    • Cull distance จัดการผ่านค่าการอินเตอร์โพเลตที่แปลงแล้ว
    • Clip control ถูกทำใน vertex shader epilogue

Buffer robustness และการชดเชยด้วยซอฟต์แวร์บน M1

  • โดยดั้งเดิม GPU ให้ความสำคัญกับประสิทธิภาพมากกว่าความปลอดภัย จึงอาจเกิด พฤติกรรมไม่กำหนดแน่ชัด เมื่อ shader มีโค้ดผิดพลาดที่อ่านเกินขอบเขตบัฟเฟอร์
  • สำหรับแอปพลิเคชันอย่างเว็บเบราว์เซอร์ที่ต้องจัดการ shader ที่ไม่น่าเชื่อถือ การแลกเปลี่ยนเช่นนี้ไม่เหมาะสม
    • ตัวกราฟิก API เองไม่ใช่ขอบเขตด้านความปลอดภัย จึงยังต้องมีการ sanitization บางส่วน
    • การลดพฤติกรรมไม่กำหนดแน่ชัดของ API ช่วยเรื่อง defense in depth
  • เมื่อเปิด Robustness แอปพลิเคชันสามารถเลือกพฤติกรรมที่กำหนดไว้สำหรับการเข้าถึงนอกขอบเขตได้ โดยแลกกับประสิทธิภาพบางส่วน
  • ผลของการโหลดบัฟเฟอร์นอกขอบเขตแตกต่างกันไปตาม API
    • Direct3D และ Vulkan robustBufferAccess2: คืนค่า 0
    • OpenGL และ Vulkan robustBufferAccess: คืนค่า 0 หรือข้อมูลบางส่วนที่ยังอยู่ในบัฟเฟอร์
    • OpenGL ES: อาจเป็นค่าใดก็ได้ แต่ต้องไม่ทำให้แครช
  • ข้อกำหนดของ OpenGL คือการเข้าถึงนอกขอบเขตต้องคืนค่า 0 หรือข้อมูลในบัฟเฟอร์ ดังนั้นจึงสามารถคำนวณ unsigned minimum ระหว่างดัชนีที่เข้าถึงกับดัชนีที่ยังใช้ได้ตัวสุดท้าย แล้วโหลดด้วยดัชนีที่ปลอดภัย
    • การโหลด uniform buffer แบบไม่มี robustness: load.i32 result, buffer, index
    • หลังใส่ robustness: umin idx, index, last แล้วตามด้วย load.i32 result, buffer, idx
  • preamble ของ M1 ช่วยคำนวณค่าที่เหมือนกันสำหรับทุก thread เพียงครั้งเดียวแล้วนำกลับมาใช้ซ้ำ แทนการคำนวณซ้ำ
    • ขนาดของ uniform buffer เป็นค่าคงที่ จึงย้ายเลขคณิต robustness เพิ่มเติมไปไว้ใน preamble ได้
    • แม้ใน robust storage buffer จะย้ายตัว load/store เองไม่ได้ แต่การคำนวณ clamp ก็ยังย้ายไปไว้ใน preamble ได้

การทำ vertex buffer robustness

  • ในกราฟิก API แอปพลิเคชันจะตั้งค่า GPU base address ของ vertex buffer และ layout ของแอตทริบิวต์
    • แต่ละแอตทริบิวต์มี offset และ format
    • บัฟเฟอร์มี stride ที่บอกจำนวนไบต์ต่อ vertex
    • vertex shader จะอ่านแอตทริบิวต์ด้วยการอ้างดัชนีแบบปริยายตาม vertex
  • ฮาร์ดแวร์บางตัวทำ robust vertex fetch ได้แบบเนทีฟ หรือเร่ง software fetch ด้วยบัฟเฟอร์ที่ตรวจขอบเขตได้ แต่ M1 ไม่มีทั้งสองแบบ
  • การโหลดหน่วยความจำของ GPU บน M1 ใช้ 64-bit base address และ offset ระดับ element พร้อมมีคำสั่ง imad สำหรับ integer multiply-add
    • การโหลดแอตทริบิวต์ขนาด 32 บิตทำได้ด้วยสองคำสั่งคือ imad idx, stride/4, vertex, offset/4 และ load.i32 result, base, idx
    • แอตทริบิวต์แบบเวกเตอร์ที่มีค่า 32 บิต 4 ค่าเรียงกันแน่น สามารถโหลดได้ด้วยคำสั่งเดียว load.v4i32 result, base, vertex << 2
  • Robustness ต้องมีการ clamp แต่ขนาด vertex buffer อยู่ในหน่วยไบต์ ขณะที่การโหลดแบบปรับแต่งแล้วใช้ดัชนีระดับ vertex
  • แนวทางแก้คือมองหลายแอตทริบิวต์และ offset ภายในบัฟเฟอร์เดียวใหม่ให้เป็นเหมือน base address แยกตามแอตทริบิวต์
    • ส่งค่า base ของแต่ละแอตทริบิวต์เข้าไปแทนการบวก offset ใน shader
    • แปลงขนาดบัฟเฟอร์แบบไบต์ให้เป็นขนาดระดับ vertex สำหรับแต่ละแอตทริบิวต์ได้
    • ทำการ clamp ที่ vertex index แทน offset
  • ไดรเวอร์จะคำนวณดัชนี vertex ที่ยังใช้ได้ตัวสุดท้ายล่วงหน้าจากขนาดของ format ของแต่ละแอตทริบิวต์ แล้วส่งเข้า shader
  • หากบัฟเฟอร์เล็กจนโหลดอะไรไม่ได้เลย การใช้ clamp จะแก้ไม่ได้ จึงสลับบัฟเฟอร์ของแอตทริบิวต์นั้นให้เป็น zero buffer ขนาดเล็กแทน
    • เพราะใช้ base address แยกตามแอตทริบิวต์ จึงตัดสินใจแบบนี้ได้เป็นรายแอตทริบิวต์ด้วย
  • สุดท้ายแล้ว robust vertex buffer ถูกทำได้ด้วยการคำนวณเล็กน้อยในไดรเวอร์และต้นทุนของ umin เพียงหนึ่งตัว

Image robustness และการเลี่ยง mipmap

  • นอกจาก buffer robustness แล้ว ยังต้องมี image robustness ด้วย โดย image load ที่เกินขอบเขตต้องคืนค่า 0
  • อิมเมจที่มี mipmap จะมีหลาย level of detail
    • base level คืออิมเมจต้นฉบับ
    • แต่ละระดับถัดไปคืออิมเมจที่ย่อจากระดับก่อนหน้า
    • ระหว่างการเรนเดอร์ ฮาร์ดแวร์จะเลือกระดับที่ใกล้กับขนาดบนหน้าจอเพื่อเพิ่มทั้งประสิทธิภาพและคุณภาพภาพ
  • สเปกระบุว่าเมื่อเปิด robustness การโหลดอิมเมจต้องคืนค่า 0 ในกรณีต่อไปนี้
    • พิกัด X หรือ Y อยู่นอกขอบเขต
    • level อยู่นอกขอบเขต
  • พฤติกรรม image load ของ GPU M1 ไม่ตรงกับข้อกำหนดนี้
    • หากพิกัด X หรือ Y อยู่นอกขอบเขต จะคืนค่า 0
    • หาก level อยู่นอกขอบเขต จะคืนค่าจาก level สุดท้าย
  • เนื่องจากผู้ผลิตไม่ได้เผยแพร่เอกสารฮาร์ดแวร์ จึงไม่อาจรู้ได้ว่านี่เป็นพฤติกรรมที่ตั้งใจไว้หรือเป็นบั๊กของฮาร์ดแวร์ และจำเป็นต้องมีวิธีเลี่ยงเพื่อให้ผ่านการรับรองความสอดคล้อง
  • วิธีเลี่ยงแบบตรงไปตรงมาคือโหลดเฉพาะเมื่อ level ใช้ได้เท่านั้น มิฉะนั้นคืนค่า 0 ด้วยการแตก branch แต่ branch ไม่มีประสิทธิภาพ
  • วิธีที่ดีกว่าคืออาศัยข้อเท็จจริงว่าการโหลดใน level ที่อยู่นอกขอบเขตไม่ทำให้แครช โดยโหลดก่อนแล้วใช้ compare-select เพื่อเลือกค่า 0
    • แต่ชุดคำสั่งของ GPU M1 เป็นแบบ scalar ขณะที่ image load คืนค่าเวกเตอร์ 4 คอมโพเนนต์คือ red/green/blue/alpha
    • จึงต้องใช้ ulesel แยกต่อคอมโพเนนต์ ทำให้ assembly ใหญ่ขึ้น
  • วิธีเลี่ยงสุดท้ายอาศัยข้อเท็จจริงว่าหาก X หรือ Y อยู่นอกขอบเขต ฮาร์ดแวร์จะคืนค่า 0
    • เนื่องจากความกว้างอิมเมจสูงสุดคือ 16384px จึงเปลี่ยน X เป็นค่าอย่าง 20000 เพื่อให้แน่ใจว่าเกินขอบเขต
    • ถ้า level ใช้ได้ก็ใช้ค่า X เดิม แต่ถ้าไม่ใช้ได้ก็เปลี่ยน X เป็น 20000 เพื่อให้ image load คืนค่า 0
  • วิธีนี้เปลี่ยนเพียง scalar ตัวเดียวโดยไม่ต้องเลือกทั้งเวกเตอร์ จึงคอมไพล์เป็น assembly ที่กะทัดรัด
    • หากโหลดค่าคงที่ไว้ใน uniform register ล่วงหน้า ต้นทุนของวิธีเลี่ยงจะเหลือเพียงคำสั่งเดียว
    • วิธีนี้ทำให้ผ่านการรับรองความสอดคล้องได้

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

 
GN⁺ 2024-02-15
ความคิดเห็นจาก Hacker News
  • Alyssa Rosenzweig เหมือนเป็นของขวัญชิ้นใหญ่ที่ยังคงมอบให้คอมมูนิตี้อย่างต่อเนื่อง
    ทุกครั้งที่อ่านบล็อกโพสต์ของเธอ มักได้เรียนรู้อะไรใหม่ ๆ เกี่ยวกับ โครงสร้างภายในของฮาร์ดแวร์กราฟิกสมัยใหม่ ที่ไม่เคยรู้มาก่อนเสมอ

  • เป็นงานที่แสดงให้เห็นว่า ฝีมือจริง ชนะคำพูดทุกครั้ง
    แค่อ่านบล็อกก็มีเรื่องให้ขบคิดมากจนหัวร้อน และแม้บทสรุปจะอยู่ที่ประโยคที่สอง ไม่ใช่ประโยคสุดท้าย สุดท้ายก็ยังถูกพาให้ตามการจัดการบิตทีละจุดลึกลงไปในโพรงกระต่ายอยู่ดี
    ถ้ามีเบนช์มาร์กแบบจำนวนความกระจ่างต่อย่อหน้า Alyssa น่าจะได้ที่หนึ่งทั้งหมด

  • ถ้าวันหนึ่ง Apple เลิกใช้ OpenGL 3.3 core ในที่สุดทุกคนก็คงต้องเลิกตามไปด้วยก็เป็นได้
    โดยทั่วไปได้ยินมาว่า OpenGL ใช้ง่ายกว่า Vulkan แต่ API ที่ซับซ้อนเกินไปทำให้นักพัฒนาที่มีประสบการณ์น้อยใช้ GPU ได้ยากขึ้น และกลายเป็นกำแพงทางเข้าที่ผลักนักพัฒนาเกมอินดี้ออกไป
    ทุกวันนี้ทุกคนใช้ Unity กับ Unreal กันหมด การสร้างเองตั้งแต่ต้นหรือใช้เอนจินอื่นเลยดูแปลก และถึงจะน่าสนใจที่เห็นวงการพัฒนาเกมเริ่มตื่นตัวหลังจาก Unity พยายามล็อกให้มากขึ้น แต่ก็น่าหงุดหงิดด้วย
    โอเพนซอร์สในงานพัฒนาเกมมักอยู่ในสภาพตึงมือเสมอ และแม้จะมี Godot อยู่ ก็ยังดูยากที่จะต่อกรกับ Unity และ Unreal อย่างจริงจัง
    ต่อให้ Godot ทำได้ดีพอ นักพัฒนาอินดี้ก็อาจยังอยู่กับ Unity และ Unreal ต่อไป เพราะคุ้นเคยมากกว่า
    สภาพของโอเพนซอร์ส ในการพัฒนาเกมบางครั้งให้ความรู้สึกสิ้นหวัง และการมาถึงของกราฟิก API รุ่นถัดไปก็ไม่ได้ทำให้งานง่ายขึ้น

    • คำพูดที่ว่า OpenGL ง่ายกว่า Vulkan นั้นค่อนข้างมีเหตุผล
      ตัวอย่างการเรนเดอร์สามเหลี่ยมด้วย OpenGL ยาวประมาณ 200 บรรทัด ส่วน ตัวอย่างการเรนเดอร์สามเหลี่ยมด้วย Vulkan ยาวประมาณ 1000 บรรทัด
    • โดยส่วนตัวคิดว่า Metal ใช้ง่ายกว่า Vulkan
      Vulkan ถูกออกแบบมาให้ยืดหยุ่นมาก แต่แทบไม่มีฟีเจอร์อำนวยความสะดวก
      ไม่ว่าจะทางไหน OpenGL ก็เป็น API ระดับสูงเกินไปสำหรับเปิดเผยเป็น API โดยตรงของไดรเวอร์ และการมี API ระดับต่ำอย่าง Vulkan เป็นเลเยอร์ฐาน แล้ววางบางอย่างแบบ OpenGL ไว้ข้างบน น่าจะสอดคล้องกับวิธีที่ฮาร์ดแวร์ GPU ทำงานมากกว่า
      อีกอย่าง ไม่ใช่ทุกคนที่ใช้ Unity กับ Unreal
      เกมที่เข้าชิง Game of the Year ทั้ง 6 เกมใน The Game Awards 2023 ล้วนสร้างด้วยเอนจินของตัวเอง และในฝั่งอินดี้ก็ยังมีนักพัฒนาที่ทำเอนจินเองอย่าง Hades อยู่
      แต่ก็จริงที่คนส่วนใหญ่ใช้เอนจินสำเร็จรูป
    • OpenGL ไม่ได้ถูกเลิกใช้ แต่เรียบง่ายกว่า และยังถูกใช้ต่อไปในจุดที่ Vulkan ดูเกินความจำเป็น
      ถ้ามันตอบโจทย์ฟีเจอร์ที่ต้องการได้ทั้งหมด และยอมรับเรนเดอริงไปป์ไลน์แบบอิงสถานะได้ การใช้ในโปรเจกต์ใหม่ก็เป็นตัวเลือกที่ดี
    • บน macOS และ iOS นั้น OpenGL อยู่ในสถานะเตรียมเลิกใช้ มาหลายปีแล้ว
      มันยังทำงานได้ และทุกวันนี้รันเป็นเลเยอร์บน Metal แต่ถ้าบิลด์โค้ด GL สำหรับ macOS หรือ iOS ก็จะมีคำเตือน deprecated ขึ้นมาตลอด
      ปิดด้วย define ได้
    • WGPU ค่อนข้างเป็นความพยายามแก้ปัญหานี้ในฐานะ API ข้ามแพลตฟอร์มที่ใช้ง่ายกว่า Vulkan
      ปัญหาของ OpenGL คือมันอยู่ไกลจากวิธีทำงานของ GPU เกินไป จึงทำประสิทธิภาพที่ดีได้ยาก
  • สงสัยว่าจากงานนี้ มีสัดส่วนเท่าไรที่ผูกกับ โค้ด GPU ของ M1 และมีฟีเจอร์ซ้อนบนฟีเจอร์มากแค่ไหนที่นำไปใช้ซ้ำที่อื่นได้
    ดูคล้ายกับวิธีที่ Zink รันฟีเจอร์ OpenGL ที่ซับซ้อนบน Vulkan ที่ดิบกว่ามาก แต่ M1 ยังไม่มีแบ็กเอนด์ Vulkan ให้เป็นเป้าหมาย

    • โดยทั่วไปกว่านั้น OpenGL หรือ Vulkan ที่ซับซ้อนสามารถรันบนการผสมผสานใด ๆ ระหว่าง CPU software rendering กับการรองรับ native acceleration เฉพาะฮาร์ดแวร์ได้
      สุดท้ายเป็นเรื่องปริมาณงาน และสามารถนำไปใช้ซ้ำกับฮาร์ดแวร์หลากหลายได้
      มันอาจช่วยฮาร์ดแวร์ที่เก่าและเข้าใจกันดีแล้ว แต่ยากจะใช้เดี่ยว ๆ กับเวิร์กโหลดสมัยใหม่ได้ด้วย
  • อยากรู้มากว่า ผลกระทบต่อประสิทธิภาพ จากสิ่งนี้ โดยเฉพาะเมื่อเทียบกับการใช้ Metal โดยตรงบน macOS จะอยู่ที่ประมาณไหน
    คำตอบคงเป็น “แล้วแต่กรณี” แน่นอน แต่ก็ยังอยากรู้อยู่ดี
    อาจมีคำตอบอยู่ในบทความแล้ว แต่ส่วนใหญ่ผมไม่เข้าใจ

    • ระหว่างการทำฟีเจอร์ด้วยโค้ด compute ในไดรเวอร์ กับการทำด้วยการรองรับจากฮาร์ดแวร์ GPU ไม่จำเป็นต้องมีความต่างมากเสมอไป
      “การรองรับจากฮาร์ดแวร์” โดยปกติก็มักทำด้วย ไมโครโค้ดของ GPU และหลายครั้งก็ผ่านซิลิคอนเดียวกัน
      ฟีเจอร์ใด ๆ ก็อาจกลายเป็นคอขวดด้านประสิทธิภาพได้ และก่อนลงมือจริงก็ยากจะรู้ว่าคอขวดจะอยู่ตรงไหน
    • คำอธิบายของ Alyssa ฟังดูแปลกอยู่บ้าง
      จริงที่ Apple GPU ไม่รองรับ geometry shader แบบเนทีฟ แต่ geometry shader ออกแบบมาไม่ดีและไม่เข้ากับฮาร์ดแวร์ GPU นัก
      แม้ในฮาร์ดแวร์ที่บอกว่ารองรับจริง ก็เป็นที่รู้กันว่าช้า และมีเหตุผลที่ Nvidia ออกแบบ mesh shading ขึ้นมา
      transform feedback ก็ถูกพูดถึงบ่อย แต่ Apple GPU สามารถเขียนไปยังตำแหน่งหน่วยความจำใด ๆ ได้จาก shader stage ใด ๆ ดังนั้น transform feedback จึงแทบไม่จำเป็น
      ประเด็นสำคัญคือ Apple ได้ทำ สถาปัตยกรรม compute ที่กะทัดรัด โดยตัดของเก่าค้างยุคและฟีเจอร์จำนวนมากที่เป็นที่รู้กันว่าใช้งานได้ไม่ดีออกไป
      สำนวนว่า “M1 ติดอยู่กับ OpenGL 4.1” ดูไม่ค่อยเหมาะ
      ผมเลิกตาม OpenGL มานานแล้ว เลยไม่รู้ว่าฟีเจอร์หลัง 4.1 หมายถึงอะไรบ้าง แต่ถ้ามีฟีเจอร์ที่ทำได้ใน OpenGL แต่ทำใน Metal ไม่ได้ ผมคงแปลกใจมาก
      ในทางกลับกัน มีหลายอย่างที่ทำได้ใน Metal แต่ทำใน OpenGL ไม่ได้เลย และการที่ Metal Shading Language มีพอยน์เตอร์เต็มรูปแบบก็เป็นตัวอย่างหนึ่ง
  • นี่เป็นเรื่องสำหรับ Fedora บน M1
    ถ้าทำให้ใช้บน macOS ได้ด้วยก็คงน่าทึ่ง แต่ก็สงสัยว่าต้องใช้อะไรบ้างถึงจะสร้างสิ่งนั้นได้

    • สุดท้ายแล้วโครงสร้างคือการสร้าง command buffer แล้วส่งไปยัง GPU ดังนั้นบน macOS จึงต้องมีวิธีทำแบบนั้น
      ไดรเวอร์ Mesa รุ่นแรก ๆ สำหรับ M1 GPU ก็ bootstrap ด้วยวิธีส่ง command buffer ไปยังไดรเวอร์ AGX ของ macOS ผ่าน IOKit
      https://rosenzweig.io/blog/asahi-gpu-part-2.html
      https://github.com/AsahiLinux/gpu/blob/main/demo/iokit.c
      ดังนั้นจึงต้องมีโค้ดเชื่อมฝั่ง Mesa เพิ่มอีกเล็กน้อย เพื่อส่ง surface ของ GPU ให้เป็นวัตถุที่สามารถ composite เข้ากับหน้าจอ macOS ได้
    • ตามที่นักพัฒนาบอก Apple ไม่มี public kernel API ที่เสถียร ดังนั้นในทางปฏิบัติจึงทำได้ยาก: https://social.treehouse.systems/@AsahiLinux/111930744188229065
    • คิดว่าอาจเป็นไปได้อยู่แล้วผ่านเส้นทาง MoltenVK → Vulkan → Zink
    • ดูเหมือน Apple จะห้าม kernel driver ของ third party
      ผมเข้าใจว่าถ้าจะสร้าง implementation ของ Vulkan หรือ OpenGL ที่สมบูรณ์จริง ๆ จำเป็นต้องมีคู่ฝั่ง kernel ที่รับผิดชอบงานประมวลผลของ GPU
      บางทีนี่อาจเป็นเหตุผลที่ดูเหมือนไม่มีใครพยายามทำ native Vulkan สำหรับ macOS
      แต่ถ้าทำบนไดรเวอร์ของ Apple ได้ ก็ไม่แน่ใจเหมือนกัน
    • สามารถ implementation ไดรเวอร์ OpenGL บน Metal ได้
      แต่ไม่แน่ใจว่ามีเหตุผลพอไหมที่จะทุ่มทรัพยากรมากขนาดนั้นเพื่อ legacy API ที่ไม่ใช่ทางเลือกที่เหมาะที่สุด
  • ค่อนข้างตลกที่เรียกการเปลี่ยนการเข้าถึงนอกขอบเขตจากการ trap เป็นการคืนค่าข้อมูลตามอำเภอใจว่า robustness
    การเขียนโปรแกรมกราฟิกนี่แปลกจริง ๆ

    • ถ้ามองจากมุมของการเขียนไดรเวอร์กราฟิก มันก็สมเหตุสมผล และเข้ากับกฎของ Postel หรือ หลักการ robustness ด้วย
      งานหลักของไดรเวอร์ GPU คือทำให้แอปพลิเคชันที่พังทำงานได้ หรือทำให้รันเร็วขึ้น
      การตั้งค่า default ให้เข้มงวดไม่ได้แก้ปัญหาเชิงโครงสร้างของอุตสาหกรรมวิดีโอเกมที่ปล่อยโค้ดพัง ๆ ออกมา แต่จะทำให้ผู้ใช้หนีไปเท่านั้น
      บนฮาร์ดแวร์ที่โดยทั่วไป branching มีต้นทุนสูงมาก flag ที่บอกให้ระบบจัดการ edge case อย่างเงียบ ๆ ด้วยวิธีที่มีประสิทธิภาพที่สุดก็ดูมีประโยชน์
      น่าจะมี use case ที่ถูกต้องอยู่มาก ที่โปรแกรมเมอร์สามารถมั่นใจได้อย่างสมเหตุสมผลว่า edge case เหล่านั้นแทบไม่ส่งผลต่อเฟรมเรนเดอร์สุดท้าย
    • การไม่มีการตรวจสอบ robustness ไม่ได้แปลว่าการเข้าถึงนอกขอบเขตจะต้องถูก trap เสมอไป ดังนั้น robustness ในที่นี้หมายถึงการให้ ผลลัพธ์ที่ทราบแน่ชัด แม้ในกรณีแปลก ๆ แบบนั้น
      เมื่อรวมกับข้อเท็จจริงที่ว่าโดยรวมแล้ว GPU ไม่ค่อยชอบ trap ก็สมเหตุสมผล
      Carmack ก็เคยพูดตอนออกแบบ megatexture ว่าการทำให้ผู้ผลิตยอมรับแนวคิด virtual memory นั้นเป็นเรื่องเจ็บปวด
    • ดังนั้นในแวดวงกราฟิก, high-performance computing, ฟิสิกส์พลังงานสูง และการเทรดความถี่สูง อนาคตของ C และ C++ ก็ยังสดใส
      การพูดถึงภาษาโปรแกรมอื่นในสาขาที่วัฒนธรรม “ประสิทธิภาพมาก่อนความปลอดภัย” ครอบงำอยู่ ก็คล้ายกับพูดใส่กำแพง
  • แน่นอนว่าเป็นเรื่องที่น่าสนใจมาก แต่สงสัยว่าทำไมถึงไม่ตั้งเป้าไปที่ Vulkan ก่อน
    ทุกวันนี้ดูเหมือนเป็นเป้าหมายที่สำคัญกว่า และบนมันก็มี implementation ของ OpenGL อยู่แล้ว

    • compatibility layer ของ OpenGL บน Vulkan ไม่ใช่เวทมนตร์
      ถ้าจะรองรับฟีเจอร์เฉพาะของ OpenGL ไดรเวอร์ Vulkan ก็ต้องรองรับฟีเจอร์ที่สอดคล้องกัน และโดยปกติต้องมี extension
      กล่าวคือ แค่ implement ไดรเวอร์ Vulkan พื้นฐานไม่ได้ทำให้ได้การรองรับ OGL 4.6 มาฟรี ๆ และถ้าจะให้ Mesa แปล OGL 4.6 เป็น Vulkan ก็ต้อง implement ฟีเจอร์ OGL 4.6 ทั้งหมดในไดรเวอร์ Vulkan
      แถม Alyssa ก็เป็นคนที่เคยทำโปรเจกต์ reverse engineering และไดรเวอร์ OpenGL มาแล้ว
      ไม่รู้รายละเอียดแน่ชัด แต่การทำไดรเวอร์สำหรับ API ที่คุ้นเคยน่าจะง่ายและเร็วกว่า API ที่ไม่คุ้นเคยมาก
    • ตอนแรกตั้งเป้าไปที่ OpenGL รุ่นเก่าเพื่อทำให้ชุดฟีเจอร์พื้นฐานทำงานได้
      จากจุดนั้น การยกระดับไปถึง OpenGL รุ่นใหม่กว่าน่าจะใช้แรงงานน้อยกว่าการทำ Vulkan implementation แบบสมบูรณ์ และคงได้เรียนรู้อะไรหลายอย่างที่จำเป็นต่อ Vulkan ด้วย
    • ผมก็คิดคล้ายกัน แต่ถ้าจะรองรับ OpenGL บน Vulkan ยังไงก็ต้องใช้ Vulkan เวอร์ชันที่สูงกว่า และงานก็เยอะ
      ดังนั้นดูเหมือนพวกเขาเลือกเริ่มจาก OpenGL เวอร์ชันต่ำกว่า เพื่อให้ได้อะไรสักอย่างที่ทำงานได้เร็วกว่า
  • ถ้าลองคิดว่าหากในยุค 90 John Carmack ไม่ได้ยืนกรานที่จะใช้ OpenGL ใน Quake II แล้ว OpenGL อาจไม่มีบทบาทเด่นในเกม 3D ก็ถือว่าน่าทึ่งทีเดียว

    • Quake อาจเป็นเพียงส่วนเล็ก ๆ ในประวัติศาสตร์เท่านั้น
      สิ่งที่ทำให้ OpenGL กลายมาเป็นอย่างที่เป็นในที่สุดคือ SGI และความพยายามครั้งใหญ่ในการสร้างการใช้งานที่เข้ากันได้บนระบบและสถาปัตยกรรมที่หลากหลาย
    • ข้อเท็จจริงสนุก ๆ คือ เว็บไซต์ OpenGL ที่เก็บถาวรไว้เก่าที่สุดมีแบนเนอร์ FAST GAMES GRAPHICS ขนาดใหญ่ พร้อมกราฟิก Quake 1 แบบแอนิเมชันและเมนูอื่น ๆ :-P
      https://web.archive.org/web/19970707113513/http://www.opengl.org/
    • ไม่แน่ใจว่านั่นเป็นเหตุผลเดียวหรือไม่ แต่การที่ Carmack ช่วยผลักดัน OpenGL นั้นช่วยได้อย่างชัดเจน
      หลายสิ่งหลายอย่างที่เกี่ยวข้องกับเกม 3D เกิดขึ้นได้เพราะ Doom และ Quake
    • หลายปีต่อมาในปี 2011 John Carmack กล่าวว่า Direct3D เป็น API ที่ดีกว่าในเวลานั้น
      เขามองว่า Microsoft มีความกล้าพอที่จะทำการเปลี่ยนแปลงใหญ่ที่ไม่เข้ากันย้อนหลังต่อไปเพื่อปรับปรุง API ส่วน OpenGL ถูกฉุดรั้งไว้ด้วยความกังวลเรื่องความเข้ากันได้
      เขากล่าวว่า Direct3D จัดการมัลติเธรดได้ดีกว่า และเวอร์ชันใหม่ ๆ ก็มีการจัดการสถานะที่ดีกว่าด้วย
      ถึงอย่างนั้น เขาบอกว่าเหตุผลที่ id Software ยังคงอยู่กับ OpenGL ก็เป็นเพราะแรงเฉื่อย และแม้ Direct3D จะมีข้อดี แต่ก็ไม่มีแผนจะย้ายไปใช้ Direct3D
      แหล่งที่มา: https://www.bit-tech.net/news/gaming/pc/carmack-directx-better-opengl/1/
    • เอกสารประกอบบริบท: https://www.chrishecker.com/OpenGL/Press_Release