ประกาศ ComputeSharp 2.0 — เรียกใช้ C# บน GPU อย่างง่ายดายผ่าน DirectX 12 และ D2D1!

Nov 30 2022
หลังจากทำงานมากว่า 2 ปี ฉันยินดีที่จะประกาศว่าในที่สุด ComputeSharp 2.0 ก็พร้อมใช้งานแล้ว! นี่เป็นการเขียนไลบรารีใหม่ทั้งหมด โดยมีการรองรับทั้งสองอย่าง

หลังจากทำงานมากว่า 2 ปี ฉันยินดีที่จะประกาศว่าในที่สุด ComputeSharp 2.0 ก็พร้อมใช้งานแล้ว! นี่คือการเขียนไลบรารีใหม่ทั้งหมด โดยมีการรองรับทั้ง .NET Standard 2.0 และ .NET 6, ตัวกำเนิดซอร์สใหม่เพื่อแทนที่การสร้างรหัสรันไทม์อย่างสมบูรณ์, API ใหม่จำนวนมาก , การสนับสนุนใหม่ล่าสุดสำหรับ D2D1 pixel shaders ด้วย, XAML ควบคุมสำหรับ UWP และ WinUI 3 และอีกมากมาย!

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

สำหรับผู้ที่ชอบรูปแบบวิดีโอนี่คือลิงก์ไปยังการพูดคุยของฉันเกี่ยวกับ ComputeSharp ที่ .NET Conf 2022และสำหรับผู้ที่ต้องการเพียงแค่ข้ามไปที่โค้ดนี่คือลิงก์ไปยัง GitHub repoเช่นกัน กระโดดเข้าสู่ ComputeSharp 2.0 กันเถอะ!

เรามาเริ่มกันที่การนำเสนอขั้นสูงสำหรับไลบรารี: ComputeSharp เป็นไลบรารี .NET เพื่อเรียกใช้โค้ด C# แบบขนานบน GPU ผ่าน DX12, D2D1 และตัวประมวลผลการประมวลผล HLSL ที่สร้างขึ้นแบบไดนามิก โดยมีเป้าหมายเพื่อให้การประมวลผล GPU ใช้งานง่ายสำหรับทุกคน นักพัฒนา NET! มันช่วยให้คุณเขียน shaders (เช่น โค้ดที่สามารถทำงานบน GPU) โดยใช้ C# จากนั้นมันจะทำการยกน้ำหนักทั้งหมดเพื่อแปลงโค้ดนั้นและส่งจริงบน GPU ที่ใช้งานบนเครื่องของคุณ สามารถใช้กับฮาร์ดแวร์เพื่อเร่งความเร็วเวิร์กโหลดได้ทุกประเภท เช่น การประมวลผลภาพ การคำนวณแบบขนาน การสร้างแอนิเมชั่นแฟนซี เป็นต้น และทั้งหมดนี้โดยที่คุณไม่จำเป็นต้องเจาะลึกเข้าไปใน API เฉพาะของแพลตฟอร์มที่จำเป็นต่อการทำงานใดๆ ก็ตาม และไม่ต้องเรียนรู้วิธีเขียน HLSL ซึ่งเป็นภาษาโปรแกรมที่ DirectX ใช้สำหรับ shader

สำหรับตัวอย่างที่ใช้งานได้จริง นี่คือแอปตัวอย่าง ComputeSharp ที่ใช้งานจริง:

ที่นี่ คุณสามารถดูหนึ่งในตัวควบคุม XAML ที่ ComputeSharp เสนอสำหรับ UWP และ WinUI 3 ที่ใช้เพื่อแสดงตัวแปลงการประมวลผลแบบเคลื่อนไหวหลายตัว ในกรณีนี้ ทำงานในแอปพลิเคชัน WinUI 3 ซอร์สโค้ดทั้งหมดมีอยู่ใน GitHubและ shader ทั้งหมดที่คุณเห็นได้รับการพอร์ตจาก GLSL shaders จากshadertoyไปเป็น C# และทั้งหมดขับเคลื่อนโดย ComputeSharp และทำงานโดยใช้ DirectX 12 compute shaders

และนี่คืออีกตัวอย่างหนึ่งของการทำงานของ ComputeSharp:

Paint.NET 5.0 แสดงเอฟเฟ็กต์เบลอโบเก้ที่ขับเคลื่อนโดย ComputeSharp

ฉันใช้เวลาไม่กี่เดือนที่ผ่านมาในการเพิ่มการรองรับ Direct2D ให้กับ ComputeSharp ซึ่งตอนนี้เป็นองค์ประกอบพื้นฐานของการเปิดตัว Paint.NET 5.0 ที่กำลังจะ มา ถึง ComputeSharp.D2D1 (เวอร์ชันของไลบรารีสำหรับ D2D1 pixel shaders) กำลังถูกใช้เพื่อสร้างเอฟเฟ็กต์ภาพจำนวนมากในแอป ซึ่งเขียนด้วยภาษา C# และ GPU ทั้งหมดถูกเร่งผ่านพลังของ D2D สิ่งนี้ทำให้Rick Brewsterผู้พัฒนา Paint.NET สามารถเพิ่มจำนวนเอฟเฟกต์ที่เขาสามารถเรียกใช้บน GPU ได้อย่างมาก ในขณะเดียวกันก็ลดความซับซ้อนของแอปพลิเคชันลงอย่างมากในส่วนที่เกี่ยวกับเอฟเฟกต์ D2D GPU เนื่องจากไม่มีอีกต่อไป ความจำเป็นในการเขียนเอฟเฟ็กต์ด้วยตนเองใน HLSL และคอมไพล์ด้วยขั้นตอนการสร้างแบบกำหนดเอง — ComputeSharp ทำงานทั้งหมดนี้อยู่เบื้องหลัง!

เรื่องน่ารู้ — โบเก้เบลอที่แสดงในภาพหน้าจอ Paint.NET ด้านบนคือพอร์ตของ Rick ของตัวอย่างภาพเบลอโบเก้ ComputeSharp.D2D1 ของฉัน ซึ่งเป็นพอร์ตที่ฉันทำกับตัวอย่างภาพเบลอโบเก้ ComputeSharp ของฉัน ซึ่งเป็นพอร์ตจากเวอร์ชัน C# ที่ฉันเขียน สำหรับ ImageSharpซึ่งเป็นพอร์ตจากเวอร์ชัน Python ที่ศาสตราจารย์ Mike Pound เขียนสำหรับวิดีโอ Computerphile ของเขาเกี่ยวกับเอฟเฟกต์ โบเก้เบลอ ไปลองดูสิ!

และสิ่งนี้ยังมีให้สำหรับผู้เขียนปลั๊กอิน ซึ่งหมายความว่าตอนนี้ทุกคนสามารถใช้ ComputeSharp.D2D1 เพื่อเขียนเอฟเฟกต์ที่ปรับแต่งอย่างเต็มที่และ GPU ที่เร่งความเร็วเพื่อรวมเข้ากับ Paint.NET สิ่งที่เคยต้องการความรู้ของ HLSL และ D2D internals ตอนนี้สามารถเข้าถึงได้ง่ายสำหรับนักพัฒนา C# ทั้งหมด ด้วยโค้ดเพียงไม่กี่บรรทัดและ API ระดับสูงที่เป็นมิตร

หากคุณอยากรู้ว่า ComputeSharp Shader หน้าตาเป็นอย่างไร นี่คือวิธีที่เรียบง่ายมาก: Hello World Shader ซึ่งจะแสดงการไล่ระดับสีแบบเคลื่อนไหวที่เปลี่ยนไปตามเวลา นี่คือรหัส C # สำหรับมัน:

ตัวประมวลผล DirectX 12 ที่เขียนด้วย C# ด้วย ComputeSharp

คุณสามารถดูได้ว่า Shader เป็นเพียงประเภทโครงสร้าง C# ที่จับค่าบางอย่าง (ในกรณีนี้คือทศนิยมเพื่อระบุเวลาที่ผ่านไป) จากนั้นทำการคำนวณเพื่อคำนวณสีที่จะแสดงในเอาต์พุต นี่คือ shader ทั้งหมด ซึ่ง ComputeSharp จะดูแลการประมวลผลในเวลาสร้างผ่านตัวสร้างซอร์ส เพื่อแปลงเป็น HLSL และสร้างโค้ดเพิ่มเติมเพื่อรองรับการดำเนินการ

นี่คือลักษณะของรหัส HLSL ที่เป็นผลลัพธ์สำหรับ shader นี้:

ตัวแปลง HLSL ที่แปลแล้วสำหรับประเภท C#

เป็นเรื่องง่ายที่จะเห็นการเปลี่ยนแปลงบางอย่างที่ ComputeSharp ทำอยู่เบื้องหลัง: ขณะนี้ shader มีบัฟเฟอร์คงที่ซึ่งใช้เพื่อรวบรวมค่าที่บันทึกไปยัง GPU มีคำอธิบายประกอบขนาดเธรดเพื่อควบคุมการส่ง shader การตรวจสอบขอบเขตอัตโนมัติได้ ถูกเพิ่มเข้ามา และ shader ยังจับภาพพื้นผิวเอาต์พุตโดยปริยายและกำหนดพิกเซลผลลัพธ์ให้กับพื้นผิวนั้น ในฐานะนักพัฒนาซอฟต์แวร์ C# ที่ใช้ ComputeSharp คุณจะไม่ต้องกังวลกับสิ่งเหล่านี้เลย: ตัวกำเนิดซอร์สที่มาพร้อมกับ ComputeSharp จะจัดการงานหนักทั้งหมดนี้ ในขณะที่คุณสามารถเขียน C# และรับประโยชน์จาก IntelliSense และเครื่องมือที่ยอดเยี่ยมทั้งหมดที่ C# มีให้

ฉันยังต้องการแสดงตัวอย่างแบบ end-to-end สองสามตัวอย่างสำหรับการรันโค้ดบน GPU โดยใช้ ComputeSharp เราได้เห็นวิธีการเขียนเชดเดอร์แล้ว แต่คุณอาจสงสัยว่าการลงสีนั้นยากจริงหรือไม่ มันไม่ใช่! และยังมีหลายวิธีในการทำเช่นนั้น ดังนั้นคุณจึงสามารถเลือกวิธีที่เหมาะกับความต้องการของคุณมากที่สุดได้เช่นกัน

ComputeSharp นำเสนอโหมดการดำเนินการที่กระตือรือร้นและโหมดกราฟการคำนวณ แบบแรกมีประโยชน์อย่างยิ่งหากคุณเพิ่งเริ่มต้นใช้งานไลบรารี ต้องการลองใช้งานหรือเพียงแค่ต้องเรียกใช้สคริปต์ง่ายๆ และไม่ต้องการกังวลเกี่ยวกับการตั้งค่าไปป์ไลน์การดำเนินการที่ซับซ้อนมากขึ้น ต่อไปนี้คือวิธีเรียกใช้การทดสอบ Shader แบบง่ายๆ:

โหมดการดำเนินการที่กระตือรือร้นใน ComputeSharp

นั่นคือทั้งหมดที่คุณต้องทำเพื่อรันโค้ด C# บน GPU! คุณสามารถดูได้ว่าเรามี shader แบบง่ายๆ ได้อย่างไร ซึ่งเพียงแค่คูณค่าทั้งหมดในพื้นผิวด้วย 2 จากนั้นเราจะส่งมันไปยังบัฟเฟอร์ที่เขียนได้ซึ่งเราจัดสรรไว้ใน GPU โดยมีค่าสุ่มอยู่ในนั้น หลังจากส่ง shader แล้ว เรายังสามารถคัดลอกบัฟเฟอร์ GPU นั้นกลับไปที่ CPU เพื่อให้เราอ่านเนื้อหาได้ ComputeSharp แสดง API ที่ใช้งานง่ายมากจำนวนมากเพื่อดำเนินการทั่วไปเช่นนี้ ซึ่งสามารถปรับให้เข้ากับสถานการณ์ทั้งหมด ตั้งแต่สคริปต์ขั้นต่ำที่เรียบง่ายไปจนถึงสถาปัตยกรรมที่ซับซ้อนมากขึ้น

ลองดูตัวอย่างโดยใช้โหมดกราฟการคำนวณ:

โหมดกราฟการคำนวณใน ComputeSharp

โหมดนี้เหมาะอย่างยิ่งหากคุณต้องการสร้างไปป์ไลน์การดำเนินการที่ปรับแต่งได้อย่างเต็มที่ ซึ่งสามารถบีบประสิทธิภาพสูงสุดออกจาก GPU ในโหมดนี้ ก่อนอื่นเราจะสร้างComputeContextซึ่งเป็นวัตถุที่ช่วยให้เราสามารถจัดคิวการทำงานบน GPU ได้ จากนั้นเราจะสร้างไปป์ไลน์ของเรา (รวมถึงการดำเนินการต่างๆ เช่น การส่ง shader การควบคุมการเปลี่ยนเพื่อซิงโครไนซ์การเข้าถึงทรัพยากรที่ใช้ร่วมกัน และอื่นๆ) และสุดท้าย เราจะส่งสิ่งนั้นไปยัง GPU เมื่ออยู่นอกขอบเขตของบริบท คุณยังสามารถดูได้ที่นี่ว่าเราใช้ประโยชน์จากการรอคอยโดยใช้ไวยากรณ์เพื่อดำเนินการทั้งหมดนี้แบบอะซิงโครนัสบน GPU อย่างไร เราจึงไม่ปิดกั้นเธรดปัจจุบันจนกว่า GPU จะประมวลผลคำขอของเราเสร็จสิ้น

การสนับสนุน XAML เป็นอย่างไร ComputeSharp นำเสนอการควบคุม 2 แบบ ( ComputeShaderPanelและAnimatedComputeShaderPanel ) ซึ่งทำให้ง่ายสุด ๆ ในการรวมเอฟเฟกต์ที่ขับเคลื่อนด้วย ComputeSharp เข้ากับแอปพลิเคชัน UWP หรือ WinUI 3: เพียงแค่ใส่ตัวควบคุม XAML ลงในมุมมองของคุณ กำหนด shader Runner objec ให้กับมัน และคุณ ดีไป!

ComputeShaderPanel ใช้ในมุมมอง XAML

ต่อไปนี้เป็นวิธีที่สามารถประกาศComputeShaderPanel ภายในมุมมองได้อย่างง่ายดาย จากนั้น เพียงแค่ต้องการ อินสแตนซ์ IShaderRunnerเพื่อทราบวิธีการเรนเดอร์แต่ละเฟรม สำหรับกรณีง่ายๆ เช่น เมื่อเราเพียงต้องการแสดงภาพเคลื่อนไหวเชดเดอร์ประเภท ShaderRunner<T> ในตัว ก็เพียงพอแล้ว:

เชดเดอร์รันเนอร์ ถูกกำหนดให้กับ ComputeShaderPanel

และนั่นแหล่ะ! แผงจะใช้ตัวไล่เฉดสีเพื่อวาดแต่ละเฟรม และจะดูแลการตั้งค่าทั้งหมดที่จำเป็นในการแสดงแต่ละเฟรมที่สร้างขึ้นจริง สำหรับสถานการณ์ขั้นสูง คุณยังสามารถใช้ shader Runner ได้ด้วยตัวคุณเอง ซึ่งช่วยให้คุณควบคุมเวลาของเฟรมได้อย่างเต็มที่ กราฟการคำนวณที่ใช้สร้างแต่ละภาพที่จะแสดง และอื่นๆ อีกมากมาย!

สุดท้าย ฉันต้องการแสดงตัวอย่าง D2D1 pixel shader เหล่านี้คือตัวแรเงาที่ Paint.NET ใช้ และยังเป็นส่วนหนึ่งของโครงสร้างพื้นฐานที่ฉันกำลังดำเนินการเพื่อเปิดใช้งานการใช้สิ่งเหล่านี้ในแอปพลิเคชัน UWP และ WinUI 3 ผ่านไลบรารี Win2D (คุณสามารถดูข้อเสนอของฉันได้ที่นี่เช่นกัน ). แตกต่างอย่างมากจากตัวประมวลผลเฉดสี DirectX 12 แต่ด้วยโครงสร้างพื้นฐานของ ComputeSharp ทำให้ติดตั้งได้ง่ายพอๆ กัน และยังสามารถเรียกใช้ได้โดยไม่ต้องออกแรงมากเกินไปโดยใช้ประโยชน์จากเอฟเฟกต์พิกเซลเฉดเดอร์ในตัวที่ ComputeSharp.D2D1 มีให้

นี่คือตัวอย่างเอฟเฟกต์พิกเซลจาก Paint.NET:

pixelate D2D1 pixel shader จาก Paint.NET

คุณจะสังเกตได้ว่ามีความแตกต่างบางอย่างระหว่าง shader นี้กับ DX12 shader ที่แสดงด้านบน แต่ประสบการณ์ของนักพัฒนาส่วนใหญ่จะเหมือนกัน: คุณเพียงแค่ต้องสร้างประเภท C# ใช้การฉายภาพ HLSL และ API ที่ ComputeSharp รวมอยู่ ปล่อยให้ IntelliSense เป็นผู้แนะนำ คุณ จากนั้นให้ ComputeSharp ทำงานที่เหลือทั้งหมดให้คุณในเวลาคอมไพล์

ลองดูโค้ดที่แปลแล้วสำหรับ shader นี้ด้วย:

เอฟเฟกต์พิกเซลเปลี่ยนเป็น HLSL

อีกครั้ง ประเภท C# ได้รับการแปลงตามความจำเป็นเพื่อให้เป็นไปตามข้อกำหนด HLSL ที่จำเป็น ในกรณีนี้สำหรับตัวสร้างพิกเซล D2D1 โดยเฉพาะ เราได้ประกาศฟิลด์เพื่อแมปกับค่าที่จับได้ต่างๆ ใน ​​C# ข้อมูลภายในทั้งหมดถูกส่งต่อไปยังค่าเทียบเท่า HLSL ไวยากรณ์ของ shader ได้รับการอัปเดต และอื่นๆ อีกมากมาย และเชดเดอร์ทั้งหมดเหล่านี้ เช่นเดียวกับ DX12 ยังสามารถคอมไพล์ล่วงหน้าได้ในขณะสร้าง ซึ่งหมายความว่าแอปพลิเคชันของคุณสามารถมีประสิทธิภาพการเริ่มต้นที่รวดเร็วอย่างเห็นได้ชัด และไม่จำเป็นต้องเรียกใช้หรือรวมกลุ่มคอมไพเลอร์เชดเดอร์เลยเมื่อปรับใช้!

มีอีกมากมายที่มีอยู่ใน ComputeSharp และนี่เป็นเพียงรุ่นแรกที่เสถียรหลังจากเขียนใหม่ — มีคุณลักษณะและการปรับปรุงใหม่มากมายที่ฉันกำลังดำเนินการอยู่ และฉันวางแผนที่จะรวมไว้ในรุ่นต่อๆ ไป! คุณสามารถตรวจสอบพื้นที่เก็บข้อมูลบน GitHubลองใช้ห้องสมุด ( คุณสามารถค้นหาได้ใน NuGet! ) และแสดงความคิดเห็นและแสดงความคิดเห็น!

และถ้าคุณใช้มันและสร้างบางอย่าง - โปรดแบ่งปัน! ฉันชอบที่จะเห็นสิ่งดีๆ ทั้งหมดที่ผู้คนสามารถสร้างโดยใช้ ComputeSharp!

มีความสุขในการเข้ารหัส!