From 90a23347b40e92bd93590648ac8dfc9c6f165b45 Mon Sep 17 00:00:00 2001 From: Vaclav Elias Date: Tue, 24 Oct 2023 19:18:38 +0100 Subject: [PATCH 1/6] Update 2023-10-23-new-diagnostic-analyzers-feature.md --- posts/2023-10-23-new-diagnostic-analyzers-feature.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/posts/2023-10-23-new-diagnostic-analyzers-feature.md b/posts/2023-10-23-new-diagnostic-analyzers-feature.md index da6d86fd..dd378f0f 100644 --- a/posts/2023-10-23-new-diagnostic-analyzers-feature.md +++ b/posts/2023-10-23-new-diagnostic-analyzers-feature.md @@ -18,7 +18,7 @@ Stride continues to evolve, adding new utilities and features every week. This b ## What is a `DiagnosticAnalyzer`? -A `DiagnosticAnalyzer` is a feature from Roslyn that scans your code while you are typing in your IDE. C# also utilizes this feature; every time you see a warning or red squiggly lines in your IDE, a `DiagnosticAnalyzer` gets triggered. Importantly, this analysis has nothing to do with telemetry. +A `DiagnosticAnalyzer` is a feature from Roslyn that scans your code while you are typing in your IDE. C# also utilizes this feature; every time you see a warning or red squiggly lines in your IDE, a `DiagnosticAnalyzer` gets triggered. Analyzers are offline tools used by the compiler to assist programmers. They are not used to collect telemetry on how Stride is being used. ## What does it do? @@ -42,4 +42,4 @@ Adding new analyzers to the Stride engine is straightforward. However, be aware This is a new quality-of-life feature that simplifies development in Stride by providing immediate feedback on coding issues. -Thank you for reading 📖, and happy coding đŸ’ģ👩‍đŸ’ģ👨‍đŸ’ģ! \ No newline at end of file +Thank you for reading 📖, and happy coding đŸ’ģ👩‍đŸ’ģ👨‍đŸ’ģ! From e027697603382e684bb58d1d3b0f1e28be631ceb Mon Sep 17 00:00:00 2001 From: Vaclav Elias Date: Thu, 26 Oct 2023 23:41:58 +0100 Subject: [PATCH 2/6] feat: Diagnostic example section added with an image --- images/blog/2023-10/diagnostics-example.webp | Bin 0 -> 21810 bytes ...-10-23-new-diagnostic-analyzers-feature.md | 30 ++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 images/blog/2023-10/diagnostics-example.webp diff --git a/images/blog/2023-10/diagnostics-example.webp b/images/blog/2023-10/diagnostics-example.webp new file mode 100644 index 0000000000000000000000000000000000000000..b487404f9d30948a9fd6949cac391030e2c18c87 GIT binary patch literal 21810 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 literal 0 HcmV?d00001 diff --git a/posts/2023-10-23-new-diagnostic-analyzers-feature.md b/posts/2023-10-23-new-diagnostic-analyzers-feature.md index dd378f0f..6a4506da 100644 --- a/posts/2023-10-23-new-diagnostic-analyzers-feature.md +++ b/posts/2023-10-23-new-diagnostic-analyzers-feature.md @@ -26,8 +26,38 @@ The new `Diagnostics` primarily focus on [Serialization](https://doc.stride3d.ne Each error code follows this format: `STRDIAGXXX`, where 'X' represents a numerical digit. Clicking on these error codes will open a help page that explains in depth why the `DiagnosticAnalyzer` was triggered and how to resolve the warning. You can find these error code pages [here](https://doc.stride3d.net/latest/en/diagnostics/). +## Example + +In this example, we'll delve into a common scenario where the `DiagnosticAnalyzer` spots issues related to Stride's serialization rules. We have a `Dictionary` property named `Name` within a class `Example`. We've also adorned the `Name` property with `[DataMember]` and `[DataMemberIgnore]` attributes which are contradictory, and this is where the `DiagnosticAnalyzer` steps in to provide valuable feedback. + + +```csharp +public class Example +{ + [DataMember] + [DataMemberIgnore] + public Dictionary Name { private get; set; } +} +``` + +Upon compiling, the `DiagnosticAnalyzer` flags three diagnostic warnings related to the attributes and the property's accessibility: + +```yml +STRDIAG000: There is an Attribute Contradiction on 'Name' Member. [DataMemberIgnore] Attribute on a [DataMember] is not supported. Except if it has also [DataMemberUpdatable] Attribute. +STRDIAG009: The member 'Name' implements IDictionary with an unsupported type for the key. Only primitive types ( like int,float,.. ) are supported or string or enums as the Dictionary Key in asset serialization. When used in other contexts the warning may not apply and can be suppressed. +STRDIAG004: The property 'Name' with [DataMember] does not have an accessible getter which is required for serialization. A public/internal/internal protected getter is expected. +``` + +The following image demonstrates how these warnings are displayed in Visual Studio: + +{% img-click 'Diagnostics warning in Visual Studio' '/images/blog/2023-10/diagnostics-example.webp' %} + +These warnings provide immediate feedback, aiding the developer in adhering to Stride's serialization rules. The `DiagnosticAnalyzer` not only pinpoints the issues but also suggests the necessary adjustments to align the code with Stride's standards. For instance, it suggests the removal of the `[DataMemberIgnore]` attribute or the addition of a `[DataMemberUpdatable]` attribute to resolve the attribute contradiction on the `Name` member. It also highlights the requirement for an accessible getter for serialization, and informs about the supported types for the `Dictionary` key in asset serialization. + ## Why use it? +This real-time feedback is invaluable, making the coding process smoother and less error-prone, and ensuring that the codebase remains compliant with Stride's serialization standards. + This feature aims to minimize those "Why is my property not showing up in the [Game Studio](https://doc.stride3d.net/latest/en/manual/game-studio/index.html)?" moments. It's often unclear why certain properties don't appear in the editor. These analyzers are designed to clarify such situations, aiding your development process in Stride. ## Current State From 6128dc217aac611d264543ec04eaf3829aaf8365 Mon Sep 17 00:00:00 2001 From: Vaclav Elias Date: Fri, 27 Oct 2023 10:02:24 +0100 Subject: [PATCH 3/6] Update site.json - Website version bumped --- _data/site.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_data/site.json b/_data/site.json index 73a2dbde..c31a385a 100644 --- a/_data/site.json +++ b/_data/site.json @@ -1,5 +1,5 @@ { - "version": "2.0.0.21", + "version": "2.0.0.22", "engine": "Eleventy 2.0", "title": "Stride Game Engine", "description": "C# Stride Game Engine is a powerful and versatile game development engine that is based on the C# programming language", From 94ea13acc71e96ed4942b3a256ecb85a952742e4 Mon Sep 17 00:00:00 2001 From: = <=> Date: Fri, 10 Nov 2023 23:32:26 +0100 Subject: [PATCH 4/6] Blog post for Spirv --- images/Spir.png | Bin 0 -> 16828 bytes ...vestigating-spirv-for-the-shader-system.md | 86 ++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 images/Spir.png create mode 100644 posts/investigating-spirv-for-the-shader-system.md diff --git a/images/Spir.png b/images/Spir.png new file mode 100644 index 0000000000000000000000000000000000000000..f49cfd1e1814d07900c309497289a216493ecf33 GIT binary patch literal 16828 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 literal 0 HcmV?d00001 diff --git a/posts/investigating-spirv-for-the-shader-system.md b/posts/investigating-spirv-for-the-shader-system.md new file mode 100644 index 00000000..385925fb --- /dev/null +++ b/posts/investigating-spirv-for-the-shader-system.md @@ -0,0 +1,86 @@ +--- +title: "Investigating spir-v for the shader system" +author: youness +popular: false +image: /images/spir.png +tags: ['.NET', 'spir-v', 'shader', 'hlsl', 'glsl', 'sdsl', 'compilation'] +--- + +Let's investigate how the shader system works in Stride and how to make it better thanks to spir-v. +--- + +Table of Contents: + +[[TOC]] + +The Stride engine has a powerful shader system, helping users build very complex shaders thanks to its language features like composition and inheritance, and its C# integration through the very powerful material system. + +## What are shaders ? + +Simply put, they are typically snippets of codes that are run on the GPU, moslty written in C-like languages like GLSL and HLSL. + +When a game has to render on the screen, it starts by preparing the data on the GPU and then sends shaders with commands. The GPU then executes those commands and if everything goes well, the game ends with a lovely screen ! + +## How does it work in Stride ? + +To first understand how it works in Stride we have to know the many barriers we're facing. + +Stride is meant to run on a wide range of devices, from computers to mobiles. For that we have to make sure our shaders can run on many kind of GPUs through different drivers. + +There are 3 most used shader languages and they are, for some, tide to different kind of machines. + +* For Windows machines, HLSL and GLSL are the most used languages through Vulkan, OpenGL and Direct3D drivers. Where HLSL with Direct3D is only available on Windows. +* For Linux and Android machines, Vulkan and OpenGL are the most used options. +* For Mac and iOS machines, MSL is used with Metal. + +Since there is no one-size-fits-all solution, every game engine has to come up with a more complex solution that makes sure we have one shader language for every machines. A language that will either be transpiled or cross-compiled into another one. + +This is where SDSL was born. + +## SDSL and transpilation + +For the sake of this article we won't dive into the language, but you can learn a lot more about SDSL [through the manual](https://doc.stride3d.net/latest/en/manual/graphics/effects-and-shaders/index.html). +From here, the article will assume you have a high level view about how programming languages are compiled and knowledge about shader programming. + +SDSL (StriDe Shader Language), was born for the need to transpile HLSL code to GLSL. It is heavily inspired from HLSL but with more features to simplify the process of creating complex shader computations. + +The shader system has 3 sides to it, an effect system, a shader mixer and the transpilation. + +The effect system will use the many different SDSL features to create uber-shaders/permutations for creating complex pipeline rendering. + +Since HLSL and GLSL are very close to each other, all this mixing is done through the abstract syntax tree level(AST). There are very few modification on the code itself, most of the work is done for managing input/output of shaders. + +The SDSL AST will then be transformed into HLSL or GLSL depending the graphics driver used. + + +## Why investigating spir-v? + +Unfortunately for us, this complex transpilation involves issues regarding performance. Working with tree structures, especially with string data, makes computations very slow can introduce issues like defensive copies. + +We would need tools to help us transpile this SDSL into other languages without going through tree structures, but maybe through arrays. + +Three things happened lately, Vulkan was released with a new kind of bytecode shader language called spir-v and .NET core came out with a new feature for operating on arrays without loss of performance, namely `Span`. And most importantly, spirv-cross was created as a mean to perform cross-compilation of shaders in a performant way. + +It was clear for everyone, we had to investigate how we could compile SDSL to spir-v and use tools like spirv-cross. + +## Problems ahead + +SDSL is a very peculiar shader language, using current spir-v tools to generate spir-v byte code would be extremely difficult to design given how spir-v has a very tight specification. +Another problem is that most spir-v tools are written in system languages like Rust/C/C++, which is another barrier for a .NET based game engine. + +To be able to use spir-v to it's fullest we have to create a C#/.NET library from scratch, something that will help us assemble and manipulate spir-v bytecode the way SDSL works. + +## Mise en bouche for Part 2 of this article + +I've started to work on this issue not long ago through two projects : + +* [A new simplified parser for SDSL](https://github.com/ykafia/SDSLParser) +* [A spir-v assembler library for SDSL](https://github.com/ykafia/SoftTouch.Spirv) + +Those will be the core subjects of part 2! + +## Summary + +Embracing spir-v for Stride's shader system will hopefully empower us with a better control over the shader language but also improve performance for shader compilation! + +Thank you for reading! From 3c2f0de0bf261963d4fc59ed75d3a22505e4f3fd Mon Sep 17 00:00:00 2001 From: Youness KAFIA <32330908+ykafia@users.noreply.github.com> Date: Mon, 13 Nov 2023 10:11:18 +0100 Subject: [PATCH 5/6] Better structure for spirv blog --- images/blog/spirv/shaders-explanation.png | Bin 0 -> 15141 bytes ...vestigating-spirv-for-the-shader-system.md | 86 +++++++++++------- 2 files changed, 53 insertions(+), 33 deletions(-) create mode 100644 images/blog/spirv/shaders-explanation.png diff --git a/images/blog/spirv/shaders-explanation.png b/images/blog/spirv/shaders-explanation.png new file mode 100644 index 0000000000000000000000000000000000000000..6148eeee84d8196843ced57e18b69987d44268df GIT binary patch literal 15141 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 RKYzthSJru0qG`. And most importantly, spirv-cross was created as a mean to perform cross-compilation of shaders in a performant way. +#### Drivers are not all the same -It was clear for everyone, we had to investigate how we could compile SDSL to spir-v and use tools like spirv-cross. +Drivers can be seen as a front-end API to use the GPU. They have different paradigm and logic which may result in your shader code needing to be different across different drivers. -## Problems ahead +Here's a table of which language is supported by which machine depending on the driver used. I chose the most used machines for gaming. -SDSL is a very peculiar shader language, using current spir-v tools to generate spir-v byte code would be extremely difficult to design given how spir-v has a very tight specification. -Another problem is that most spir-v tools are written in system languages like Rust/C/C++, which is another barrier for a .NET based game engine. +Note that some APIs are tied to the machine you're developing for, adding more complexity to the shader system, needing to handle GPUs that have very specific features. +
-To be able to use spir-v to it's fullest we have to create a C#/.NET library from scratch, something that will help us assemble and manipulate spir-v bytecode the way SDSL works. +| | Direct3D | Vulkan | OpenGL | Metal | PSGL | NVN | +|-----------------|----------|-----------|--------|-------|------|----------------| +| Windows | HLSL | HLSL/GLSL | GLSL | | | | +| Linux | | HLSL/GLSL | GLSL | | | | +| Mac/iOS | | | | MSL | | | +| Android | | HLSL/GLSL | GLSL | | | | +| Playstation 4/5 | | | | | PSSL | | +| Nintendo Switch | | HLSL/GLSL | | | | NVN language ? | +| XBOX Series X/S | HLSL | | | | | | +
+
-## Mise en bouche for Part 2 of this article +#### Performance Cost -I've started to work on this issue not long ago through two projects : +Managed languages like C# are well known to be slower with string objects since they treat them as immutable. On top of that, tree structures, especially the one used for shader compilation in Stride, tend to perform very slowly and are prone to be slow and work against the GC. + +## Why investigating spir-v? + +Three things happened in the past 10 years, Vulkan was released with a new kind of bytecode shader language called spir-v, .NET core came out with a new high performance feature for operating on slices of array (something that C# is way better at than processing string objects), namely `Span`, and most importantly, tools like [spirv-cross](https://github.com/KhronosGroup/SPIRV-Cross) and [naga](https://github.com/gfx-rs/wgpu/tree/trunk/naga) were created as a mean to translate shaders through spir-v. + +It was clear for everyone that we had to investigate how we could compile SDSL to spir-v and use all those very performant tools to transpile SDSL to other languages. + +## Problems ahead -* [A new simplified parser for SDSL](https://github.com/ykafia/SDSLParser) -* [A spir-v assembler library for SDSL](https://github.com/ykafia/SoftTouch.Spirv) +SDSL is a very peculiar language and shifting from processing tree structures to processing segments of byte code is a great endeavor, especially for an engine. -Those will be the core subjects of part 2! +The following parts of this series of blog posts will focus on how such system can be made thanks to many new C# and .NET features that came out since .NET Core. ## Summary From 8a8608e10c3132fabc197be76828292c0b95de22 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 13 Nov 2023 12:17:41 +0100 Subject: [PATCH 6/6] Structure + text --- .../shaders-explanation.png | Bin ...estigating-spirv-for-the-shader-system.md} | 61 ++++++++++-------- 2 files changed, 33 insertions(+), 28 deletions(-) rename images/blog/{spirv => 2023-11}/shaders-explanation.png (100%) rename posts/{investigating-spirv-for-the-shader-system.md => 2023-11-10-investigating-spirv-for-the-shader-system.md} (64%) diff --git a/images/blog/spirv/shaders-explanation.png b/images/blog/2023-11/shaders-explanation.png similarity index 100% rename from images/blog/spirv/shaders-explanation.png rename to images/blog/2023-11/shaders-explanation.png diff --git a/posts/investigating-spirv-for-the-shader-system.md b/posts/2023-11-10-investigating-spirv-for-the-shader-system.md similarity index 64% rename from posts/investigating-spirv-for-the-shader-system.md rename to posts/2023-11-10-investigating-spirv-for-the-shader-system.md index 4f332006..4689e83b 100644 --- a/posts/investigating-spirv-for-the-shader-system.md +++ b/posts/2023-11-10-investigating-spirv-for-the-shader-system.md @@ -1,12 +1,12 @@ --- -title: "Investigating spir-v for the shader system - Part 1" +title: "Investigating spirv for the shader system - Part 1" author: youness popular: false image: /images/spir.png -tags: ['.NET', 'spir-v', 'shader', 'hlsl', 'glsl', 'sdsl', 'compilation'] +tags: ['.NET', 'Shaders'] --- -Let's investigate how the shader system works in Stride and how to make it better thanks to spir-v. +Let's investigate how the shader system works in Stride and how to make it better thanks to spirv. --- @@ -23,7 +23,7 @@ Simply put, they are typically snippets of codes that are run on the GPU, moslty When a game has to render on the screen, it starts by preparing the data on the GPU and then sends shaders with commands. The GPU then executes those commands and if everything goes well, the game ends with a lovely picture drawn on the screen ! This single call of a GPU is called a `draw call`. -![shader overview](/images/blog/spirv/shaders-explanation.png) +![shader overview](/images/blog/2023-11/shaders-explanation.png) It can be simplified to this view. There is a first stage called `Vertex stage` which is meant to compute vertices and make sure they are transformed into data that can be rasterized by your GPU, and a final stage called `Pixel stage` or `Fragment stage` that takes the rasterized output of the rasterizer and computes color for each pixel on the screen based on which triangles they belong to. @@ -31,11 +31,11 @@ In both stages, you can provide textures/images and data through buffers, this c ## Rendering in game engines -Drawing a single mesh is simple, one buffer of vertices, maybe some textures, do a draw call and marvel at the screen. Repeat it many times and you get a video, very useful to make video games. +Drawing a single mesh is simple, one buffer of vertices, maybe some textures, do a draw call and ✨ marvel at the screen ✨. Repeat it many times and you get a video, very useful to make video games 👾. In game engines, objects being drawn the same ways are grouped into `materials`. A material can be seen as a recipe for drawing a mesh with ingredients like shader code, textures, vertices and other informations. -Having many different materials implies creating many shader source code, and depending if you use [forward or deferred shading](https://learnopengl.com/Advanced-Lighting/Deferred-Shading), you might need reuse code from one file to another leading to some duplicate code. +Having many different materials implies creating many shader source code, and depending if you use [forward or deferred shading](https://learnopengl.com/Advanced-Lighting/Deferred-Shading), you might need to reuse code from one file to another leading to lots of duplicate code 👩‍đŸ’ģ👨‍đŸ’ģ. To solve this problem, all game engines have developped shader systems that help create permutation of shader code depending the material you're using. It helps re-use code you've already written, which speeds up development gives you the power to organize your code in more manageable ways! @@ -47,53 +47,58 @@ Stride has its own shader language called SDSL which stands for **S**tri**D**e * SDSL uses a very smart system of composition and inheritance, similar to object oriented programming. You can learn more about it [through the manual](https://doc.stride3d.net/latest/en/manual/graphics/effects-and-shaders/index.html). -### The barriers +## The many problems shader systems are facing To create permutations you need to be aware of the many limitations you will face while writing code for GPU. -#### GPUs are all different + +### GPUs are all different As obvious as it sounds, it needs to be reminded. Whenever you write code for your GPU you have to be aware that it will not work for all other GPUs. 10 years ago, two languages were the most used for writing shader code : HLSL and GLSL. -In the case of OpenGL GPU vendors would provide you with their own compilers to work for their GPUs through different drivers. A valid code for one compiler would be a syntax error for another. It was a big mess! +In the case of OpenGL, GPU vendors would provide you with their own GLSL compilers to work for their GPUs through different drivers. A valid code for one compiler would be a syntax error for another. It was a big mess 💩, but a manageable one! -Stride was created during this period and it was designed to run on a wide variety of devices. +Stride was created during this period and it was designed to run on a wide variety of devices 🎮 🕹ī¸ đŸ’ģ đŸ–Ĩī¸. -The solution chosen for creating code permutations that could work on many different machine was transpilation. Text would be parsed in abstract syntax trees and the text would be translated from one language to another by manipulating those trees. [To have a better idea of how abstract syntax tree work, this playlist will definitely help !](https://www.youtube.com/watch?v=cxNlb2GTKIc&list=PLTd6ceoshpreZuklA7RBMubSmhE0OHWh_&pp=iAQB) +The solution chosen for creating code permutations that could work on many different machine was transpilation. Text would be parsed in abstract syntax trees and the text would be translated from one language to another by manipulating those trees. [To have a better idea of how abstract syntax tree work, this playlist of videos will definitely help !](https://www.youtube.com/watch?v=cxNlb2GTKIc&list=PLTd6ceoshpreZuklA7RBMubSmhE0OHWh_&pp=iAQB) -#### Drivers are not all the same +### Drivers are not all the same Drivers can be seen as a front-end API to use the GPU. They have different paradigm and logic which may result in your shader code needing to be different across different drivers. Here's a table of which language is supported by which machine depending on the driver used. I chose the most used machines for gaming. -Note that some APIs are tied to the machine you're developing for, adding more complexity to the shader system, needing to handle GPUs that have very specific features. +Note that some APIs are tied to the machine you're developing for, adding more complexity to the shader system, needing to handle GPUs that have very specific features. Vulkan and OpenGL can be used on Mac and iOS but OpenGL is deprecated and Vulkan run on MoltenVK, a Vulkan implementation on top of Metal.
-| | Direct3D | Vulkan | OpenGL | Metal | PSGL | NVN | -|-----------------|----------|-----------|--------|-------|------|----------------| -| Windows | HLSL | HLSL/GLSL | GLSL | | | | -| Linux | | HLSL/GLSL | GLSL | | | | -| Mac/iOS | | | | MSL | | | -| Android | | HLSL/GLSL | GLSL | | | | -| Playstation 4/5 | | | | | PSSL | | -| Nintendo Switch | | HLSL/GLSL | | | | NVN language ? | -| XBOX Series X/S | HLSL | | | | | | +| | Direct3D | Vulkan | OpenGL | Metal | PSGL | NVN | +|-----------------|--------------|-----------|--------|-------|------|-----| +| Windows/XBox | HLSL | HLSL/GLSL | GLSL | | | | +| Linux | | HLSL/GLSL | GLSL | | | | +| Mac/iOS | | HLSL/GLSL | GLSL | MSL | | | +| Android | | HLSL/GLSL | GLSL | | | | +| Playstation 4/5 | | | | | PSSL | | +| Nintendo Switch | | HLSL/GLSL | GLSL | | | ? | +

-#### Performance Cost +### Performance Cost Managed languages like C# are well known to be slower with string objects since they treat them as immutable. On top of that, tree structures, especially the one used for shader compilation in Stride, tend to perform very slowly and are prone to be slow and work against the GC. -## Why investigating spir-v? +## Why investigating spirv? + +Three things happened in the past 10 years : + +* Vulkan was released with a new kind of bytecode shader language called spirv -Three things happened in the past 10 years, Vulkan was released with a new kind of bytecode shader language called spir-v, .NET core came out with a new high performance feature for operating on slices of array (something that C# is way better at than processing string objects), namely `Span`, and most importantly, tools like [spirv-cross](https://github.com/KhronosGroup/SPIRV-Cross) and [naga](https://github.com/gfx-rs/wgpu/tree/trunk/naga) were created as a mean to translate shaders through spir-v. +* .NET core came out with a new high performance feature for operating on slices of array (something that C# is way better at than processing string objects), namely `Span` -It was clear for everyone that we had to investigate how we could compile SDSL to spir-v and use all those very performant tools to transpile SDSL to other languages. +* Most importantly, tools like [spirv-cross](https://github.com/KhronosGroup/SPIRV-Cross) and [naga](https://github.com/gfx-rs/wgpu/tree/trunk/naga) were created as a mean to translate shaders through spirv. -## Problems ahead +It was clear for everyone that we had to investigate how we could compile SDSL to spirv and use all those very performant tools to transpile SDSL to other languages. SDSL is a very peculiar language and shifting from processing tree structures to processing segments of byte code is a great endeavor, especially for an engine. @@ -101,6 +106,6 @@ The following parts of this series of blog posts will focus on how such system c ## Summary -Embracing spir-v for Stride's shader system will hopefully empower us with a better control over the shader language but also improve performance for shader compilation! +Embracing spirv for Stride's shader system will hopefully empower us with a better control over the shader language but also improve performance for shader compilation! đŸ’ĒđŸ’Ē Thank you for reading!