- ตั้งแต่ OBS Studio 32.0.0 สำหรับ macOS ได้มีการเพิ่ม แบ็กเอนด์เรนเดอเรอร์ที่ใช้ Apple Metal แบบทดลอง โดยมีเป้าหมายเพื่อปรับปรุงประสิทธิภาพและความคุ้มค่าจากเดิมเมื่อเทียบกับ OpenGL
- Metal เป็น API ที่ออกแบบมาเพื่อ ลดโอเวอร์เฮดและสะท้อนสถาปัตยกรรม GPU สมัยใหม่ ทำให้ OBS ต้องปรับวิธีโต้ตอบกับ GPU ใหม่ในระดับพื้นฐานเพื่อรองรับ
- เนื่องจากเรนเดอเรอร์เดิมของ OBS วางโครงสร้างโดยยึด Direct3D เป็นศูนย์กลาง แบ็กเอนด์ Metal จึงต้องทำ งานด้านความเข้ากันได้ครั้งใหญ่ ทั้งการแปลงเชดเดอร์และการจัดการรีซอร์ส
- โดยเฉพาะมีการติดตั้งระบบที่ซับซ้อนสำหรับ แปลงเชดเดอร์ HLSL เป็น MSL แบบเรียลไทม์ และ จำลองพฤติกรรม
map/unmap ของ Direct3D ภายใน Metal
- แม้แบ็กเอนด์ Metal จะยังอยู่ในขั้น “Experimental” แต่ก็เป็นจุดเปลี่ยนสำคัญต่อสภาพแวดล้อมการพัฒนาบน macOS ด้วยประสิทธิภาพที่เร็วกว่า OpenGL, โครงสร้างโค้ดที่ปลอดภัยด้วย Swift และ การรองรับพรีวิวแบบ EDR
ภาพรวมการนำเรนเดอเรอร์ Metal มาใช้
- ตั้งแต่ OBS Studio 32.0.0 ได้เริ่มให้บริการ เรนเดอเรอร์ที่ใช้ Metal Graphics API แบบทดลองบน macOS
- เป็นทางเลือกแทนแบ็กเอนด์ OpenGL เดิม โดยมุ่งหวัง เพิ่มประสิทธิภาพและประสิทธิผล
- Metal เป็น API สมัยใหม่ที่เปลี่ยนวิธีโต้ตอบกับ GPU ในระดับพื้นฐาน ทำให้ OBS ต้องปรับโครงสร้างภายในให้สอดคล้อง
- แบ็กเอนด์ Metal ถูกระบุว่าเป็น “Experimental” และยังมีปัญหาและข้อจำกัดที่ทราบอยู่บางส่วน
- เรนเดอเรอร์ OpenGL ยังคงเป็นค่าเริ่มต้น และผู้ใช้สามารถลองใช้เวอร์ชัน Metal ได้ด้วยตนเอง
- แนะนำให้นักพัฒนาที่มีประสบการณ์กับ Metal ส่ง ข้อเสนอแนะและ Pull Request เข้ามา
ภูมิหลังและแนวคิดการออกแบบของ Metal
- Apple เปิดตัว Metal ครั้งแรกในปี 2014 สำหรับ iPhone และขยายมาสู่ Mac ในปี 2015
- ในเวลานั้น Metal เป็นหนึ่งใน Graphics API ยุคถัดไปตัวแรก ๆ ที่รองรับทั้ง Intel, AMD และ NVIDIA GPU
- Metal ผสานแนวคิดจาก Mantle ของ AMD เข้ากับ OpenGL และ Direct3D เดิม แต่ ตัดองค์ประกอบแบบเลกาซีออก แล้วออกแบบใหม่
- เป็น API ที่อิง Objective-C และ Swift จึงมีโครงสร้างที่คุ้นเคยสำหรับนักพัฒนา iOS และ macOS
- รองรับการทำงานแบบบูรณาการใน Xcode สำหรับ การดีบักเชดเดอร์และการวิเคราะห์ GPU
ความต่างด้านการออกแบบ API และการปรับตัวของเรนเดอเรอร์ OBS
- OpenGL และ Direct3D แบบเดิมให้ API จัดการ การบริหารรีซอร์สและการซิงโครไนซ์ ให้อัตโนมัติ แต่
API สมัยใหม่อย่าง Metal ต้องให้นักพัฒนาจัดการเองโดยตรง
- API รุ่นใหม่มอง GPU เป็น อุปกรณ์ประมวลผลที่ใช้คิวคำสั่งแบบขนาน และจัดการสถานะของ pipeline ด้วยอ็อบเจ็กต์แบบไม่เปลี่ยนแปลง
- เรนเดอเรอร์เดิมของ OBS ถูกออกแบบตามแนวทางของ Direct3D
จึงต้องสร้าง เลเยอร์ความเข้ากันได้ในระดับแบ็กเอนด์ เพื่อรองรับ Metal
โครงสร้างของเรนเดอเรอร์ OBS และปัญหาความเข้ากันได้กับ Metal
- OBS ใช้แบ็กเอนด์ Direct3D (Windows) และ OpenGL (Linux/macOS) แยกตามแพลตฟอร์ม
- แกนของเรนเดอเรอร์ไม่ผูกกับ API ใดเป็นพิเศษ แต่ก็ยังมีสมมติฐานบางส่วนที่ ยึด Direct3D เป็นหลัก
- ข้อจำกัดหลัก
- เชดเดอร์เขียนด้วย HLSL จึงต้องแปลงระหว่างรันไทม์
- มีทั้ง การใช้ตัวแปรโกลบอล, สมมติฐานว่าทำงานแบบลำดับขั้น, และ การจัดการเท็กซ์เจอร์แบบ Direct3D
- การเรนเดอร์พรีวิว พึ่งพาโมเดล
discard ของ DXGI
การแปลงเชดเดอร์ (Transpiling Shaders)
- ไฟล์เอฟเฟกต์ของ OBS เขียนด้วย HLSL และถูกแปลงให้เหมาะกับแต่ละ API
- เพื่อรองรับ Metal จึงมีการเพิ่ม ตัวแปลง HLSL → MSL
- ความแตกต่างสำคัญ
- MSL ต้อง แยก struct ของอินพุตและเอาต์พุต และ ไม่รองรับตัวแปรโกลบอล
- ข้อมูล uniform ทั้งหมดต้อง ส่งผ่าน GPU buffer และต้องส่งเป็นอาร์กิวเมนต์ของฟังก์ชันอย่างชัดเจน
- เวลาเรียกใช้ฟังก์ชันจะมีการตรวจสอบ ความตรงกันของชนิดข้อมูลและ signature อย่างเข้มงวด
- ตัวแปลงจะ เขียนโค้ดเชดเดอร์บางส่วนใหม่ ในช่วงรันไทม์เพื่อให้เป็นไปตามกฎของ MSL
- เช่น แปลงตัวแปร
uniform ของ HLSL ให้เป็น constant buffer ของ MSL
- และแทรกตรรกะ แปลงชนิดข้อมูลอัตโนมัติ เช่น
int3 → uint2 + uint
การจำลองพฤติกรรมของ Direct3D
- เรนเดอเรอร์ของ OBS ถูกออกแบบโดยตั้งสมมติฐานว่ามีพฤติกรรม
map/unmap ของ Direct3D
- แต่ Metal ไม่มีการซิงโครไนซ์อัตโนมัติแบบนี้ จึงต้อง ทำขึ้นเองภายในแบ็กเอนด์
- วิธีการทำงานของแบ็กเอนด์ Metal
- ตอนเขียนข้อมูลจะสร้าง GPU buffer และ แชร์กับหน่วยความจำของ CPU โดยตรง
- ตอน
unmap จะจองคำสั่ง blit ของ GPU เพื่อคัดลอกไปยังเท็กซ์เจอร์
- ตอนอ่านข้อมูลจะใช้ GPU buffer ร่วมกัน แต่ป้องกันการชนกันด้วย การซิงโครไนซ์แบบชัดแจ้ง
- ผลลัพธ์คือมีการจำลอง การติดตามรีซอร์สและการซิงโครไนซ์ แบบของ Direct3D ไว้ภายใน Metal
ปัญหาการเรนเดอร์พรีวิวและวิธีแก้ชั่วคราว
- Metal Layer บน macOS ต่างจาก DXGI ตรงที่แอปไม่สามารถเลือกแสดงเฟรมได้ตามต้องการ
- ระบบจะควบคุมอัตราเฟรมตาม ProMotion และโหมดประหยัดพลังงาน
- เนื่องจากลูปเรนเดอร์ของ OBS ไม่สอดคล้องกับรอบการแสดงผลของ macOS จึงเกิด ความหน่วงในพรีวิว
- วิธีแก้ชั่วคราว
- OBS จะ เรนเดอร์ลงเท็กซ์เจอร์เสมือนก่อน แล้วให้เธรดแยก คัดลอกไปยัง Surface ของหน้าจอ
- กระบวนการนี้ต้องมีการซิงโครไนซ์ GPU และอาจเกิดความไม่ตรงกันของเฟรมได้
- หลัง macOS 14 ยังมีแนวโน้มว่าจะมีความท้าทายเพิ่มเติมจาก ตัวจับเวลาอิสระรายหน้าต่าง
ต้นทุนแฝงของ Graphics API สมัยใหม่
- การพัฒนาแบ็กเอนด์ Metal ต้องผ่าน การวิจัยและการออกแบบซ้ำหลายรอบเป็นเวลาหลายเดือน
- และยืนยันให้เห็นว่าเหตุใดการย้ายจาก OpenGL ไป Vulkan หรือจาก D3D11 ไป D3D12 จึงอาจทำให้ประสิทธิภาพลดลงได้
- API สมัยใหม่ทำให้แอปพลิเคชันต้อง รับภาระงานที่ไดรเวอร์เคยจัดการเอง
- จึงต้องมี ความเข้าใจเชิงลึกเกี่ยวกับการทำงานของ GPU และความสัมพันธ์ของคำสั่ง
- แม้แบ็กเอนด์ Metal จะนำโอเวอร์เฮดบางส่วนกลับมา แต่ก็ให้ข้อดีดังนี้
- ประสิทธิภาพเทียบเท่าหรือดีกว่า OpenGL
- ความสามารถด้านการวิเคราะห์ที่ทรงพลัง เช่น การดีบักเชดเดอร์และเท็กซ์เจอร์
- โครงสร้างโค้ดที่ปลอดภัยด้วย Swift
- การรองรับพรีวิวแบบ EDR เพื่อรองรับงานวิดีโอคุณภาพสูง
- ด้วยความสามารถในการวิเคราะห์แบบบูรณาการใน Xcode ประสิทธิภาพในการดูแล OBS บน macOS จึงดีขึ้น และทีมพัฒนายังขอ ข้อเสนอแนะจากนักพัฒนา เพื่อมุ่งสู่การเปลี่ยนให้ Metal เป็นเรนเดอเรอร์ค่าเริ่มต้น ในอนาคต
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เป็นบทความที่ดีมาก คำอธิบายเรื่องวิธีประมวลผลเชดเดอร์น่าทึ่งมาก
สงสัยว่าถ้าจะให้เชดเดอร์ของปลั๊กอินภายนอกทำงานได้บนหลายแบ็กเอนด์ จำเป็นต้องผ่านกระบวนการแบบนั้นจริง ๆ หรือเป็นเพราะต้องคงความเข้ากันได้ย้อนหลังเลยต้องทำแบบนั้น
จากมุมของทีมแกนหลัก การบอกนักพัฒนาภายนอกว่า “ให้เขียนแยกในทุกภาษาเชดเดอร์” อาจจะง่าย แต่ในโลกความจริงมันไม่ใช่ทางเลือกที่ดีนัก
ทุกคนคิดว่ามันไม่มีประสิทธิภาพ แต่ในทางปฏิบัติก็แทบไม่มีทางเลือกอื่น
หัวข้อบทความซ่อนประเด็นสำคัญไว้
น่าจะเปลี่ยนเป็นประมาณว่า “OBS Studio เพิ่มเรนเดอเรอร์ใหม่: เส้นทางสู่การรองรับ Metal”
นี่แสดงให้เห็นอย่างชัดเจนถึงต้นทุนที่ Apple ต้องจ่ายจากการสร้าง API เพื่อปกป้องระบบนิเวศของตัวเองแทนที่จะใช้ Vulkan
OBS Studio เพิ่มการรองรับ Vulkan ตั้งแต่เดือนมีนาคม 2020 ในเวอร์ชัน 25.0 ตอนนี้ก็ผ่านมาห้าปีครึ่งแล้ว
ในสภาพแวดล้อมแบบฝังตัวยังเป็น OpenGL ES เป็นหลัก
ฉันไม่ใช่ผู้เชี่ยวชาญในหัวข้อนี้ เข้าใจได้แค่ราว 5% ของสิ่งที่อ่าน แต่ก็อยากให้มีบทความที่อธิบายรายละเอียดทางเทคนิคแบบนี้มากขึ้น
แถลงการณ์อย่างเดียวมันให้ความรู้สึกเหมือนงานการตลาด
ส่วนตัวฉันตื่นเต้นกับการรองรับ VST3ที่กำลังจะมามากกว่า แต่ข่าวนี้ก็น่ายินดี
ง่ายกว่าการตั้งค่าการเข้ารหัสด้วยฮาร์ดแวร์บน Rockchip SoC มาก
คำอธิบายที่ว่า Metal ต่อยอดแนวทางเชิงวัตถุของ Direct3D ไปอีกขั้น แล้วผสมเข้ากับการออกแบบ API แบบ “พูดมาก” ของ Objective-C และ Swift น่าสนใจมาก
น่าทึ่งที่ API กราฟิก 3D ระดับระบบปฏิบัติการจะถูกสร้างขึ้นบนพื้นฐานของภาษาที่มีความเป็นไดนามิกแบบนี้
ฉันคิดว่านี่เป็นเพราะการปรับแต่ง
objc_msgSend()Vulkan/Metal/DirectX 12 จะใส่หลายคำสั่งลงใน command buffer แล้วส่งต่อ แทนที่จะเรียกทีละคำสั่ง
ช่วงต้นยุค 2000 มีหนังสือสอนใช้ Direct3D กับ C# ซึ่งเปลี่ยนมุมมองว่าภาษาแบบมี GC ก็ทำกราฟิกประสิทธิภาพสูงได้
แก่นสำคัญคือโครงสร้างแบบประมวลผลเป็นชุดที่อ้างอิงบัฟเฟอร์ที่จัดสรรไว้ล่วงหน้าเพื่อลดโอเวอร์เฮดของรันไทม์
หลังจาก Cocoa เป็นต้นมา ส่วนใหญ่เขียนด้วยชุดย่อยของ C++ แบบจำกัด (เช่น IOKit)
ฉันหวังว่าAPI ของ GPU สมัยใหม่จะเป็นเพียงช่วงเปลี่ยนผ่านไปสู่สิ่งที่เรียบง่ายกว่านี้
OpenGL เป็นทั้งรักทั้งเกลียด แต่หลังจากได้ใช้ API ใหม่ ๆ แล้วกลับยิ่งคิดถึงความเรียบง่ายของ OpenGL
สงสัยว่า Metal จะช่วยเพิ่มประสิทธิภาพบนIntel Mac รุ่นเก่าด้วยหรือไม่ หรือเป็นการปรับแต่งสำหรับตระกูล Mเท่านั้น
แต่ Metal 3 ก็ยังรองรับ Intel Mac หลายรุ่นอยู่ ทำไมถึงจำกัดแบบนี้ก็ยังน่าสงสัย
กำลังคิดจะประกอบอุปกรณ์สตรีมมิงด้วย Mac Mini
เลยสงสัยว่าการเพิ่มประสิทธิภาพครั้งนี้จะทำให้ใช้งานได้จริงแค่ไหน
ถ้าเป็นเกมอาร์เคด 2D หรือหน้าจอสำหรับงานพัฒนา ก็ไม่มีปัญหา
แต่ถ้าเป็นเกม AAA รุ่นใหม่ ๆ การใช้การ์ดแคปเจอร์รับภาพจากพีซีจะดีกว่า
ราวปี 2017 การสตรีมบน macOS ยังลำบาก แต่ตอนนี้ถ้าเป็นตระกูล M ก็เพียงพอแล้ว
การปรับปรุงครั้งนี้น่าจะช่วยเพิ่มประสิทธิภาพการใช้ทรัพยากรได้อีก
อยากให้ Apple ลงทรัพยากรมากกว่านี้เพื่อเพิ่มกรณีความสำเร็จจากภายนอกของ Metal
นอกจากภายใน Apple เองแล้ว Metal ยังไม่ค่อยประสบความสำเร็จมากนัก