โลกของการเขียนโปรแกรมกราฟิกส์ได้แบ่งออกเป็นสองแนวทางมาอย่างยาวนาน คือ ภาษา shader แบบดั้งเดิมอย่าง GLSL และ HLSL สำหรับงานกราฟิกส์ และภาษาที่มีความสามารถมากกว่าอย่าง C++ สำหรับการคำนวณทั่วไป การแบ่งแยกนี้สร้างปัญหาให้กับนักพัฒนาที่ต้องจัดการกับไวยากรณ์ที่แตกต่างกัน ฟีเจอร์ที่จำกัด และโค้ดเบสที่แยกจากกัน ตอนนี้ คอมไพเลอร์ Vcc สัญญาว่าจะเชื่อมช่องว่างนี้ด้วยการอนุญาตให้โค้ด C++ มาตรฐานทำงานโดยตรงเป็น Vulkan shader
ปัญหาของภาษา Shader แบบดั้งเดิม
ภาษา shader ปัจจุบันยังคงมีภาระจากยุคแรกเริ่มเมื่อฮาร์ดแวร์กราฟิกส์มีข้อจำกัดมากกว่านี้ GLSL และ HLSL ถูกออกแบบมาเมื่อโปรแกรม shader ยังเรียบง่ายและมีขนาดเล็ก ทำให้เกิดข้อจำกัดเรื่อง pointer การเรียกตัวเองซ้ำ และการจัดสรรหน่วยความจำแบบไดนามิก ข้อจำกัดเหล่านี้สมเหตุสมผลในอดีต แต่การเขียนโปรแกรมกราฟิกส์สมัยใหม่ต้องการโค้ดที่ซับซ้อนมากกว่านี้
ชุมชนนักพัฒนาเริ่มหงุดหงิดกับข้อจำกัดเหล่านี้ นักพัฒนามักพบว่าตัวเองต้องเขียนลอจิกซ้ำในหลายภาษา - ครั้งหนึ่งสำหรับโค้ด CPU และอีกครั้งสำหรับ GPU shader การทำซ้ำนี้สร้างบัก เสียเวลา และทำให้การดีบักยากลำบากเพราะอัลกอริทึมเดียวกันอาจทำงานแตกต่างกันในแต่ละแพลตฟอร์ม
ข้อจำกัดปัจจุบันของภาษา Shader:
- ไม่รองรับ pointer ใน GLSL/HLSL แบบดั้งเดิม
- การเรียกซ้ำ (Recursion) ถูกห้ามหรือมีข้อจำกัดอย่างมาก
- ไม่มีการจัดสรรหน่วยความจำแบบไดนามิก
- รองรับ function pointer อย่างจำกัด
- มีเวิร์กโฟลว์การคอมไพล์และดีบักแยกต่างหาก
เหตุผลที่ C++ สำหรับ Shader สมเหตุสมผล
การผลักดันให้ใช้การเขียนโปรแกรม shader ที่ใช้ C++ ไม่ได้เป็นเพียงเรื่องความสะดวก CUDA ได้พิสูจน์แล้วว่า C++ สามารถทำงานได้อย่างยอดเยี่ยมสำหรับการเขียนโปรแกรม GPU โดยรองรับมาตรฐาน C++20 เต็มรูปแบบในขณะที่ยังคงประสิทธิภาพสูงสุด ข้อมูลเชิงลึกที่สำคัญคือการเรียนรู้ที่จะเขียน C++ ที่ทำงานร่วมกับฮาร์ดแวร์ GPU แทนที่จะต่อต้านมัน
นักพัฒนาหลายคนในชุมชนได้สัมผัสประโยชน์ด้วยตัวเอง ไลบรารี Mathematics ของ Unity แสดงให้เห็นแนวทางนี้อย่างสมบูรณ์แบบ - มันให้ไทป์ C# ที่สะท้อน vector และ matrix ในตัวของ HLSL อย่างแม่นยำ สิ่งนี้ช่วยให้นักพัฒนาเขียนฟังก์ชันคณิตศาสตร์ครั้งเดียวใน C# และคัดลอกไปยังไฟล์ HLSL โดยตรงโดยไม่ต้องเปลี่ยนแปลงใดๆ
ผมแค่คัดลอกและวางส่วนของโค้ด CPU ตรงไปในไฟล์ HLSL โดยคาดหวังเต็มที่ว่าจะเกิด syntax error หรือต้องปรับแต่ง แต่ไม่เลย มันทำงานได้อย่างสมบูรณ์แบบ ไม่ต้องเปลี่ยนแปลงอะไรเลย
ประสบการณ์การพัฒนาที่ดีกว่าขับเคลื่อนการยอมรับ
นอกเหนือจากการพิจารณาประสิทธิภาพแล้ว ประสบการณ์การพัฒนายังมีบทบาทสำคัญในแนวโน้มนี้ C++ มีเครื่องมือที่เหนือกว่าเมื่อเปรียบเทียบกับภาษา shader แบบดั้งเดิม - debugger ที่ดีกว่า เฟรมเวิร์กสำหรับทดสอบ การเน้นไวยากรณ์ และการสนับสนุน IDE เมื่อทำงานกับโปรเจกต์กราฟิกส์ที่ซับซ้อน เครื่องมือเหล่านี้สามารถเร่งการพัฒนาและลดบักได้อย่างมีนัยสำคัญ
ความสามารถในการดีบักลอจิก shader บน CPU ก่อน จากนั้นจึงย้ายไปยัง GPU ด้วยการเปลี่ยนแปลงเพียงเล็กน้อย แสดงถึงการปรับปรุงเวิร์กโฟลว์ที่สำคัญ เครื่องมือดีบัก CPU มีความเป็นผู้ใหญ่มากกว่าทางเลือกของ GPU ทำให้แนวทางนี้มีคุณค่าเป็นพิเศษสำหรับอัลกอริทึมที่ซับซ้อนอย่าง path tracing หรือการคำนวณแสงขั้นสูง
ความท้าทายทางเทคนิคและแนวทางแก้ไข
คอมไพเลอร์ Vcc เผชิญกับอุปสรรคทางเทคนิคที่สำคัญในการแปล C++ เป็นโค้ดที่เข้ากันได้กับ shader GPU สมัยใหม่รองรับฟีเจอร์อย่าง buffer device address สำหรับการดำเนินการแบบ pointer แต่ความสามารถเหล่านี้ไม่สามารถใช้ได้ทั่วไปในทุกแพลตฟอร์ม อุปกรณ์ Android มือถือโดยเฉพาะอาจอ้างว่ารองรับฟีเจอร์ Vulkan ขั้นสูงในขณะที่มีปัญหาไดรเวอร์ในทางปฏิบัติ
คอมไพเลอร์ยังต้องจัดการ control flow อย่างระมัดระวัง สถาปัตยกรรม GPU ทำงานได้ดีที่สุดกับ structured control flow แต่ความยืดหยุ่นของ C++ สามารถสร้างรูปแบบที่ไม่สามารถแมปไปยังโมเดลการทำงานของ GPU ได้ดี ฟีเจอร์อย่าง subgroup intrinsic ต้องการการจัดการพิเศษที่คอมไพเลอร์ C++ มาตรฐานไม่ได้ให้
สถานะการรองรับแพลตฟอร์ม:
- Buffer device addresses: รองรับ 97.89% ใน Vulkan 1.2
- Mobile Android: การรองรับของไดรเวอร์มีข้อจำกัด/ไม่เสถียร
- Desktop GPUs: รองรับอย่างแพร่หลาย
- Subgroup intrinsics: ต้องการ structured control flow ที่ยังไม่ได้ถูกพัฒนา
โมเมนตัมของอุตสาหกรรมกำลังสร้างขึ้น
อุตสาหกรรมกราฟิกส์กำลังเคลื่อนไปสู่โมเดลการเขียนโปรแกรมแบบรวม DirectX ของ Microsoft ตอนนี้รองรับ SPIR-V และภาษาใหม่อย่าง Slang (ซึ่งเป็น HLSL++ โดยพื้นฐาน) กำลังได้รับความนิยม แม้แต่ Metal Shading Language ของ Apple ก็ใช้ subset ของ C++ ในขณะเดียวกัน ภาษา shader แบบดั้งเดิมกำลังสูญเสียโมเมนตัม - Khronos ยอมรับว่าการพัฒนา GLSL หยุดชะงักโดยพื้นฐาน โดยบริษัทส่วนใหญ่เปลี่ยนไปใช้ HLSL หรือทางเลือกใหม่ๆ
การบรรจบกันนี้สมเหตุสมผลทั้งจากมุมมองทางเทคนิคและธุรกิจ เกมเอนจินและแอปพลิเคชันกราฟิกส์โดยทั่วไปเขียนด้วย C++ ดังนั้นการใช้ภาษาเดียวกันสำหรับ shader จึงขจัดการเปลี่ยนบริบทและลดเส้นโค้งการเรียนรู้สำหรับนักพัฒนา
คอมไพเลอร์ Vcc แสดงถึงก้าวสำคัญในการทำให้การเขียนโปรแกรม GPU เข้าถึงได้และมีประสิทธิผลมากขึ้น แม้ว่าจะยังมีความท้าทายเรื่องความเข้ากันได้ของแพลตฟอร์มและการเพิ่มประสิทธิภาพ แต่แนวทางพื้นฐานของการปฏิบัติต่อ shader เป็นภาษาเฉพาะโดเมนที่ฝังอยู่ใน C++ ดูเหมือนจะเป็นอนาคตของการเขียนโปรแกรมกราฟิกส์
อ้างอิง: No More Shading Languages: Compiling C++ to Vulkan Shaders