สารบัญ
- บทนำ
- การเรียนรู้การเขียนโปรแกรมกราฟิก
- อย่ายึดติดกับปัญหาเล็กน้อย
- ทำไมต้อง Vulkan?
- การเรียนรู้ Vulkan
- ภาพรวมเอนจินและการวิเคราะห์เฟรม
- คำแนะนำทั่วไป
- ไลบรารี Vulkan ที่แนะนำ
- การทำ abstraction ของ GfxDevice
- การจัดการเชดเดอร์
- Push constants, descriptor sets และ bindless descriptors
- แพตเทิร์นของ pipeline
- การใช้ Programmable Vertex Pulling (PVP) + Buffer Device Address (BDA)
- Bindless descriptors
- การจัดการข้อมูลไดนามิกที่ต้องอัปโหลดทุกเฟรม
- ตัวทำลาย, คิวลบ และการเก็บกวาด
- Synchronization
- บันทึกการติดตั้งใช้งานเพิ่มเติม
- การวาดสไปรต์จำนวนมาก
- Compute skinning
- การแยกเกม / เรนเดอเรอร์
- การโหลดซีนและ entity prefab
- MSAA
- UI
- Dear ImGui และปัญหา sRGB
- อื่น ๆ
- สิ่งที่ได้จากการย้ายมาใช้ Vulkan
- งานในอนาคต
บทนำ
- เป็นการบันทึกประสบการณ์จากการเรียนรู้ Vulkan และการเขียนเอนจินเกมขนาดเล็ก
- ทำงานอยู่ 3 เดือนโดยไม่มีความรู้พื้นฐานเกี่ยวกับ Vulkan มาก่อน
- สร้างเกม 3D ขนาดเล็กและแยกส่วนที่นำกลับมาใช้ได้ออกมาเป็นเอนจิน
การเรียนรู้การเขียนโปรแกรมกราฟิก
- สำหรับผู้ที่เพิ่งเริ่มต้นด้านการเขียนโปรแกรมกราฟิก แนะนำให้เริ่มจาก OpenGL
- การใช้ OpenGL เพื่อแสดงโมเดลที่มีเท็กซ์เจอร์บนหน้าจอ และเรียนรู้แสงแบบง่ายรวมถึง shadow mapping เป็นสิ่งที่มีประโยชน์
- แหล่งเรียนรู้ OpenGL ที่แนะนำ:
- learnopengl.com
- หนังสือ Anton’s OpenGL 4 Tutorials
- ชุดบรรยายของ Thorsten Thormählen (แนะนำ 6 วิดีโอแรก)
อย่ายึดติดกับปัญหาเล็กน้อย
- ควรระวังไม่ให้ยึดติดกับปัญหาเล็กน้อยมากเกินไป
- ควรถามตัวเองเสมอว่า "จำเป็นจริงหรือ?" และ "มันจะกลายเป็นคอขวดหรือไม่?"
- ฟีเจอร์ที่ยังไม่จำเป็นสามารถเพิ่มทีหลังได้
- ควรเริ่มจากเกมที่เรียบง่าย และระวังไม่ให้เผลอสร้างเอนจินที่ซับซ้อนเกินไป
ทำไมต้อง Vulkan?
- Vulkan เหมาะกับผู้ที่ต้องการใช้ความสามารถสมัยใหม่ของ GPU และชื่นชอบเทคโนโลยีโอเพนซอร์สกับมาตรฐานเปิด
- OpenGL เพียงพอสำหรับเกมขนาดเล็ก แต่ใช้งานความสามารถสมัยใหม่ของ GPU ได้ยาก และบน macOS ก็มีข้อจำกัดในการใช้งาน
- WebGPU เรียนรู้ง่ายกว่า Vulkan และสามารถรันเกมในเบราว์เซอร์ได้
การเรียนรู้ Vulkan
- การเรียนรู้ Vulkan ในตอนแรกดูยาก แต่ Khronos ได้ทำให้ส่วนที่ซับซ้อนง่ายขึ้นและมีไลบรารีที่เป็นประโยชน์ จึงทำให้เรียนรู้ได้ง่ายขึ้น
- แหล่งเรียนรู้ Vulkan ที่แนะนำ:
- vkguide
- ชุดบรรยาย Vulkan ของ TU Wien
- หนังสือ 3D Graphics Rendering Cookbook
- หนังสือ Mastering Graphics Programming with Vulkan
ภาพรวมเอนจินและการวิเคราะห์เฟรม
- เอนจินชื่อ EDBR (Elias Daler’s Bikeshed Engine) และเริ่มต้นจากโปรเจ็กต์เพื่อเรียนรู้ Vulkan
- เอนจินนี้เหมาะกับเกมขนาดเล็กที่มีด่านเป็นหลัก
- กระบวนการเรนเดอร์ต่อเฟรม:
- Skinning: ใช้ compute shader ในการประมวลผล model skinning
- Shadow mapping: ใช้ depth texture ขนาด 4096x4096
- Geometry และ shading: ใช้โมเดล PBR
- Depth resolve: จัดการด้วยตนเองผ่าน fragment shader
- Post-processing effects: ใช้ depth fog, tone mapping และ bloom
- UI: วาด UI ด้วย draw call เดียว
คำแนะนำทั่วไป
ไลบรารี Vulkan ที่แนะนำ
- vk-bootstrap: ทำให้โค้ดเริ่มต้น Vulkan ง่ายขึ้น
- Vulkan Memory Allocator (VMA): จัดการการจัดสรรหน่วยความจำ
- volk: ทำให้การโหลดฟังก์ชันส่วนขยายง่ายขึ้น
การทำ abstraction ของ GfxDevice
- คลาส
GfxDevice ทำหน้าที่ห่อหุ้มความสามารถของ Vulkan และจัดการเรื่องต่าง ๆ เช่น การเริ่มต้น Vulkan context, การสร้างและจัดการ swapchain
การจัดการเชดเดอร์
- เขียนเชดเดอร์ด้วย GLSL
- คอมไพล์เชดเดอร์ล่วงหน้าในขั้นตอน build เพื่อลด dependency ตอนรันไทม์
Push constants, descriptor sets และ bindless descriptors
- ใน Vulkan จะใช้ descriptor sets เพื่อส่งข้อมูลไปยังเชดเดอร์
- ใช้ bindless descriptors และ Buffer Device Address เพื่อลดการใช้ descriptor sets ให้น้อยที่สุด
แพตเทิร์นของ pipeline
- ใช้คลาส pipeline เพื่อแยกขั้นตอนการวาด
- จัดการการเริ่มต้น การเก็บกวาด และการวาดของ pipeline ผ่านเมธอด
init, cleanup, draw
การใช้ Programmable Vertex Pulling (PVP) + Buffer Device Address (BDA)
- ทำให้ vertex type เป็นแบบเดียวกัน และให้เชดเดอร์เข้าถึง vertex ได้โดยตรง
- ส่งที่อยู่บัฟเฟอร์ผ่าน push constants
Bindless descriptors
- จัดการเท็กซ์เจอร์แบบ bindless เพื่อให้เชดเดอร์เข้าถึงได้โดยตรง
- ส่ง texture ID ผ่าน push constants เพื่อใช้ในการ sample
ความเห็นของ GN⁺
- Vulkan ให้ทั้งประสิทธิภาพสูงและความสามารถสมัยใหม่ของ GPU แต่เส้นโค้งการเรียนรู้ช่วงเริ่มต้นค่อนข้างชัน
- ควรเรียนรู้ OpenGL ก่อนแล้วจึงย้ายไป Vulkan
- มีแหล่งเรียนรู้หลากหลายสำหรับ Vulkan และหากใช้ให้เป็นก็จะช่วยให้เรียนรู้ได้ง่ายขึ้น
- การเขียนเอนจินเกมขนาดเล็กด้วย Vulkan ช่วยให้เข้าใจการเขียนโปรแกรมกราฟิกได้ลึกขึ้น
- ควรใช้ไลบรารีที่มีประโยชน์เพื่อลดความซับซ้อนของ Vulkan
1 ความคิดเห็น
ความเห็นบน Hacker News
สรุปความคิดเห็นจาก Hacker News
ผลของแนวทางแบบมินิมอล: กำลังเขียนไคลเอนต์เมตาเวิร์สด้วย Rust และกำลังเจอปัญหาที่ซับซ้อนจากการใช้ Vulkan, WGPU และ Rend3 โดย WGPU พัฒนาได้ยากเพราะต้องพยายามรองรับหลายแพลตฟอร์ม
ข้อดีของ Vulkan และความเรียบง่ายของ OpenGL: Vulkan สามารถดึงความสามารถขั้นสูงของ GPU ออกมาใช้ได้อย่างเต็มที่ แต่ OpenGL เหมาะกับเกม 2D/โพลิกอนต่ำแบบเรียบง่ายมากกว่า อุตสาหกรรมเกม AAA ให้ความสำคัญกับคุณภาพกราฟิกมาก แต่ผู้เล่นจำนวนมากสนใจเกมเพลย์มากกว่า
ทำเฉพาะฟีเจอร์ที่จำเป็น: โปรแกรมเมอร์รุ่นจูเนียร์มักมีแนวโน้มยึดติดกับเครื่องมือใหม่ล่าสุดและ "best practices" แต่สิ่งสำคัญคือการโฟกัสกับฟังก์ชันขั้นต่ำที่จำเป็นต่อการแก้ปัญหาจริง
ความซับซ้อนของ Vulkan: เมื่อเทียบกับ OpenGL แล้ว Vulkan ปรับแต่งประสิทธิภาพได้ยากกว่า และต้องใช้โค้ดกับงานซิงโครไนซ์จำนวนมาก ถ้าทำเป็นงานอดิเรก OpenGL ES3 จะสะดวกกว่า
ปัญหาของชั้น abstraction เพิ่มเติม: เอกสารสอน Vulkan มักเพิ่มชั้น abstraction เข้าไป ทำให้หาตัวอย่างพื้นฐานด้านการจัดการหน่วยความจำได้ยาก
การเรียนรู้ Vulkan ที่ยากลำบาก: OpenGL เรียนได้ง่าย แต่ Vulkan ทำให้แม้งานง่าย ๆ ก็กลายเป็นเรื่องซับซ้อน และการเรียนรู้เทคโนโลยีใหม่นี้ใช้เวลามาก
การเรียนรู้ Vulkan เพื่อการทำภาพข้อมูลวิทยาศาสตร์: มีผู้เรียน Vulkan แล้วเขียนเอนจินสำหรับการทำภาพข้อมูลวิทยาศาสตร์ โดยใช้เวลามากในการทำความเข้าใจ abstraction จำนวนมากระหว่างกระบวนการเรียนรู้
ความยากของการเรียนรู้ Vulkan: เป็นเรื่องยากที่จะเข้าใจวิธีใช้ Vulkan ในเอนจินจริง ต้องการเอกสารเพิ่มเติมเพื่อเรียนรู้การออกแบบ abstraction ที่ดีและวิธีกำหนดลำดับการเรนเดอร์
การสนับสนุนจากคอมมูนิตี้กราฟิกโปรแกรมมิง: ระหว่างพัฒนาเอนจิน Vulkan การได้รับการสนับสนุนและฟีดแบ็กจากคอมมูนิตี้ช่วยได้มาก