Code Monkey home page Code Monkey logo

veldrid-spirv's Introduction

Veldrid

Veldrid is a cross-platform, graphics API-agnostic rendering and compute library for .NET. It provides a powerful, unified interface to a system's GPU and includes more advanced features than any other .NET library. Unlike other platform- or vendor-specific technologies, Veldrid can be used to create high-performance 3D applications that are truly portable.

As of February 2023, I'm no longer able to publicly share updates to Veldrid and related libraries. If you're an active user or have contributed improvements in the past, feel free to reach out or join the Discord server for more information about the status of Veldrid.

Supported backends:

  • Direct3D 11
  • Vulkan
  • Metal
  • OpenGL 3
  • OpenGL ES 3

Veldrid documentation site

Join the Discord server:

Join the Discord server

Veldrid is available on NuGet:

NuGet

Pre-release versions of Veldrid are also available from MyGet: https://www.myget.org/feed/mellinoe/package/nuget/Veldrid

Sponza

Build instructions

Veldrid uses the standard .NET Core tooling. Install the tools and build normally (dotnet build).

Run the NeoDemo program to see a quick demonstration of the rendering capabilities of the library.

veldrid-spirv's People

Contributors

etinquis avatar feliwir avatar frenzibyte avatar gleblebedev avatar mellinoe avatar tarcontar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

veldrid-spirv's Issues

enable build for aarch64 linux

As the title implies with asahi linux now being a thing, aarch64 linux is finally moving could be amazing to support this architecture !

Querying struct member info

Hi there,
I was looking at building out a dynamic material binding system for my game, which basically would use the reflection to find the struct members by name and allow the game code to set values to these members using string references - something along the lines of this:

material.SetVector("SunColor", new Vector4(1, 1, 1, 1));

Which in the shader could correspond to something like this

layout(set = 1, binding = 0) uniform SkyboxParameters
{
    vec4 SkyColor;
    vec4 SunColor;
    vec4 HorizonColor;
};

I can get enough information out of the reflection to find the resource sets and bindings, but can't seem to drill down deep enough to find the members of the structs, aka SunColor in this example. Am I just missing something in the existing API, or is this not currently exposed through the Veldrid SPIRV library? It looks to be possible using SPIRV Cross https://github.com/KhronosGroup/SPIRV-Cross/wiki/Reflection-API-user-guide#struct-member-reflection

If it is missing, I would be happy to have a go at adding this functionality if you would consider it for a PR.
Thanks

How to get reflection info?

The API's recommended usage (I.E. through ResourceFactory) doesn't output the compilation results needed to get the reflection info. I looked at the code a bit and this doesn't seem easy to implement. Especially given how differently Vulkan compilation is handled.

ShaderDescription entryPoint different to "main"

When I try to load a shader with an entryPoint of the ShaderDescription set to something else than "main", I get a null reference exception in CreateFromSpirv, no matter if that function actually exists in shader or not.

(Since includes are quite mystical to mee, how they are supposed to work in glsl and also here, my idea was to just shovel everything into a single file, and generating different actual shaders by setting different entry points, but it doesn't work with this parameter.)

[GLSL/SPIR-V->HLSL] UAV/Structured buffer binds don't account for the output buffers

Compilation from GLSL or SPIR-V to HLSL does not seem to account for output buffers taking up the same namespace as UAVs/structured buffers, which leads to compilation errors when compiling the HLSL code.

Here's the error it gives for my shader, as an example:

unknown(48,21-29): error X4509: UAV registers live in the same name space as outputs, so they must be bound to at least u3, manual bind to slot u0 failed

Output reflection data with resource binding info?

Hello again! I'm just having a little look at this library. Does it already generate some sort of resource reflection data? I saw some code for iterating resources but I'm not sure if that was doing something different.

spirv-cross has a nice --reflection flag now. I assume the same thing is available when using the API - would you be interested in having it exposed by this library?

ShaderDescription Debug flag not being passed to cross-compiled shaders

When passing a ShaderDescription struct to CreateFromSpirv extension method, Debug flag from passed struct is not used, which makes me unable to view and debug DX11 shaders under RenderDoc.

The relevant lines:

Shader vertexShader = factory.CreateShader(new ShaderDescription(

Shader fragmentShader = factory.CreateShader(new ShaderDescription(

return factory.CreateShader(new ShaderDescription(

When corresponding Debug value is passed to resulting structs, I'm able to see and edit shader sources - although all identifiers are mangled, it's better than nothing.

P.S.: Until it's implemented upstream, I hacked up a version of that extension class that uses the passed flag:

Click to expand code
namespace Common;

using System.Text;
using Veldrid;
using Veldrid.SPIRV;

    /// <summary>
    /// Contains extension methods for loading <see cref="Shader"/> modules from SPIR-V bytecode.
    /// </summary>
    public static class RFExt
    {
        /// <summary>
        /// Creates a vertex and fragment shader pair from the given <see cref="ShaderDescription"/> pair containing SPIR-V
        /// bytecode or GLSL source code.
        /// </summary>
        /// <param name="factory">The <see cref="ResourceFactory"/> used to compile the translated shader code.</param>
        /// <param name="vertexShaderDescription">The vertex shader's description. <see cref="ShaderDescription.ShaderBytes"/>
        /// should contain SPIR-V bytecode or Vulkan-style GLSL source code which can be compiled to SPIR-V.</param>
        /// <param name="fragmentShaderDescription">The fragment shader's description.
        /// <see cref="ShaderDescription.ShaderBytes"/> should contain SPIR-V bytecode or Vulkan-style GLSL source code which
        /// can be compiled to SPIR-V.</param>
        /// <returns>A two-element array, containing the vertex shader (element 0) and the fragment shader (element 1).</returns>
        public static Shader[] CrossCompile(
            this ResourceFactory factory,
            ShaderDescription vertexShaderDescription,
            ShaderDescription fragmentShaderDescription)
        {
            return CrossCompile(factory, vertexShaderDescription, fragmentShaderDescription, new CrossCompileOptions());
        }

        /// <summary>
        /// Creates a vertex and fragment shader pair from the given <see cref="ShaderDescription"/> pair containing SPIR-V
        /// bytecode or GLSL source code.
        /// </summary>
        /// <param name="factory">The <see cref="ResourceFactory"/> used to compile the translated shader code.</param>
        /// <param name="vertexShaderDescription">The vertex shader's description. <see cref="ShaderDescription.ShaderBytes"/>
        /// should contain SPIR-V bytecode or Vulkan-style GLSL source code which can be compiled to SPIR-V.</param>
        /// <param name="fragmentShaderDescription">The fragment shader's description.
        /// <see cref="ShaderDescription.ShaderBytes"/> should contain SPIR-V bytecode or Vulkan-style GLSL source code which
        /// can be compiled to SPIR-V.</param>
        /// <param name="options">The <see cref="CrossCompileOptions"/> which will control the parameters used to translate the
        /// shaders from SPIR-V to the target language.</param>
        /// <returns>A two-element array, containing the vertex shader (element 0) and the fragment shader (element 1).</returns>
        public static Shader[] CrossCompile(
            this ResourceFactory factory,
            ShaderDescription vertexShaderDescription,
            ShaderDescription fragmentShaderDescription,
            CrossCompileOptions options)
        {
            options.NormalizeResourceNames = true;
            GraphicsBackend backend = factory.BackendType;
            if (backend == GraphicsBackend.Vulkan)
            {
                vertexShaderDescription.ShaderBytes = EnsureSpirv(backend, vertexShaderDescription);
                fragmentShaderDescription.ShaderBytes = EnsureSpirv(backend, fragmentShaderDescription);

                return new Shader[]
                {
                    factory.CreateShader(ref vertexShaderDescription),
                    factory.CreateShader(ref fragmentShaderDescription)
                };
            }

            CrossCompileTarget target = GetCompilationTarget(factory.BackendType);
            VertexFragmentCompilationResult compilationResult = SpirvCompilation.CompileVertexFragment(
                vertexShaderDescription.ShaderBytes,
                fragmentShaderDescription.ShaderBytes,
                target,
                options);

            string vertexEntryPoint = (backend == GraphicsBackend.Metal && vertexShaderDescription.EntryPoint == "main")
                ? "main0"
                : vertexShaderDescription.EntryPoint;
            byte[] vertexBytes = GetBytes(backend, compilationResult.VertexShader);
            Shader vertexShader = factory.CreateShader(new ShaderDescription(
                vertexShaderDescription.Stage,
                vertexBytes,
                vertexEntryPoint)
                {
                    Debug = vertexShaderDescription.Debug
                });

            string fragmentEntryPoint = (backend == GraphicsBackend.Metal && fragmentShaderDescription.EntryPoint == "main")
                ? "main0"
                : fragmentShaderDescription.EntryPoint;
            byte[] fragmentBytes = GetBytes(backend, compilationResult.FragmentShader);
            Shader fragmentShader = factory.CreateShader(new ShaderDescription(
                fragmentShaderDescription.Stage,
                fragmentBytes,
                fragmentEntryPoint)
                {
                    Debug = fragmentShaderDescription.Debug
                });

            return new Shader[] { vertexShader, fragmentShader };
        }

        /// <summary>
        /// Creates a compute shader from the given <see cref="ShaderDescription"/> containing SPIR-V bytecode or GLSL source
        /// code.
        /// </summary>
        /// <param name="factory">The <see cref="ResourceFactory"/> used to compile the translated shader code.</param>
        /// <param name="computeShaderDescription">The compute shader's description.
        /// <see cref="ShaderDescription.ShaderBytes"/> should contain SPIR-V bytecode or Vulkan-style GLSL source code which
        /// can be compiled to SPIR-V.</param>
        /// <returns>The compiled compute <see cref="Shader"/>.</returns>
        public static Shader CrossCompile(
            this ResourceFactory factory,
            ShaderDescription computeShaderDescription)
        {
            return CrossCompile(factory, computeShaderDescription, new CrossCompileOptions());
        }

        /// <summary>
        /// Creates a compute shader from the given <see cref="ShaderDescription"/> containing SPIR-V bytecode or GLSL source
        /// code.
        /// </summary>
        /// <param name="factory">The <see cref="ResourceFactory"/> used to compile the translated shader code.</param>
        /// <param name="computeShaderDescription">The compute shader's description.
        /// <see cref="ShaderDescription.ShaderBytes"/> should contain SPIR-V bytecode or Vulkan-style GLSL source code which
        /// can be compiled to SPIR-V.</param>
        /// <param name="options">The <see cref="CrossCompileOptions"/> which will control the parameters used to translate the
        /// shaders from SPIR-V to the target language.</param>
        /// <returns>The compiled compute <see cref="Shader"/>.</returns>
        public static Shader CrossCompile(
            this ResourceFactory factory,
            ShaderDescription computeShaderDescription,
            CrossCompileOptions options)
        {
            GraphicsBackend backend = factory.BackendType;
            if (backend == GraphicsBackend.Vulkan)
            {
                computeShaderDescription.ShaderBytes = EnsureSpirv(backend, computeShaderDescription);
                return factory.CreateShader(ref computeShaderDescription);
            }

            CrossCompileTarget target = GetCompilationTarget(factory.BackendType);
            ComputeCompilationResult compilationResult = SpirvCompilation.CompileCompute(
                computeShaderDescription.ShaderBytes,
                target,
                options);

            string computeEntryPoint = (backend == GraphicsBackend.Metal && computeShaderDescription.EntryPoint == "main")
                ? "main0"
                : computeShaderDescription.EntryPoint;
            byte[] computeBytes = GetBytes(backend, compilationResult.ComputeShader);
            return factory.CreateShader(new ShaderDescription(
                computeShaderDescription.Stage,
                computeBytes,
                computeEntryPoint)
                {
                    Debug = computeShaderDescription.Debug
                });
        }

        private static unsafe byte[] EnsureSpirv(GraphicsBackend backend, ShaderDescription description)
        {
            if (HasSpirvHeader(description.ShaderBytes))
            {
                return description.ShaderBytes;
            }
            else
            {
                var src = GetSource(backend, description.ShaderBytes);
                var result = SpirvCompilation.CompileGlslToSpirv(
                    src,
                    null,
                    description.Stage,
                    new GlslCompileOptions(description.Debug)
                );
                return result.SpirvBytes;
            }
        }

        private static bool HasSpirvHeader(byte[] bytes)
        {
            return bytes.Length > 4
                && bytes[0] == 0x03
                && bytes[1] == 0x02
                && bytes[2] == 0x23
                && bytes[3] == 0x07;
        }

        private static byte[] GetBytes(GraphicsBackend backend, string code)
        {
            switch (backend)
            {
                case GraphicsBackend.Direct3D11:
                case GraphicsBackend.OpenGL:
                case GraphicsBackend.OpenGLES:
                    return Encoding.ASCII.GetBytes(code);
                case GraphicsBackend.Metal:
                    return Encoding.UTF8.GetBytes(code);
                default:
                    throw new SpirvCompilationException($"Invalid GraphicsBackend: {backend}");
            }
        }

        private static string GetSource(GraphicsBackend backend, byte[] code)
        {
            switch (backend)
            {
                case GraphicsBackend.Direct3D11:
                case GraphicsBackend.OpenGL:
                case GraphicsBackend.OpenGLES:
                    return Encoding.ASCII.GetString(code);
                case GraphicsBackend.Metal:
                    return Encoding.UTF8.GetString(code);
                default:
                    throw new SpirvCompilationException($"Invalid GraphicsBackend: {backend}");
            }
        }

        private static CrossCompileTarget GetCompilationTarget(GraphicsBackend backend)
        {
            switch (backend)
            {
                case GraphicsBackend.Direct3D11:
                    return CrossCompileTarget.HLSL;
                case GraphicsBackend.OpenGL:
                    return CrossCompileTarget.GLSL;
                case GraphicsBackend.Metal:
                    return CrossCompileTarget.MSL;
                case GraphicsBackend.OpenGLES:
                    return CrossCompileTarget.ESSL;
                default:
                    throw new SpirvCompilationException($"Invalid GraphicsBackend: {backend}");
            }
        }
    }

Shaders refuse to compile only under OpenGL and GLES GLSL

I am working on getting a NanoVG C# port running with a Veldrid backend, currently, it pretty much works on Vulkan and DirectX (I don't have a mac to test the Metal API) OpenGL and ESSL both Crash the program with. I am unsure if I am missing something, but I am using in my own project these shaders with a C# ShaderC binding, and compiling them with Veldrid.Spirv and they work fine.

this is the repo containing the Veldrid Backend, it sits under https://github.com/Redhacker1/SilkyNvg/tree/main/src/rendering/SilkyNvg.Rendering.Veldrid
the example code to run this is in https://github.com/Redhacker1/SilkyNvg/tree/main/samples/Veldrid%20Example

"
error: struct type mismatch between shaders for uniform (named vdspv_fsin17)
error: struct type mismatch between shaders for uniform (named vdspv_fsin2)
"

Build for Maccatalyst

When i try to use libveldrid-spirv.dylib on Maccatalyst, get this error:

ld: building for Mac Catalyst, but linking in dylib built for macOS, file '/Users/zhouyang/Syncthing/veldrid_lastest/src/MauiSample/Veldrid.Maui.Samples/obj/Debug/net6.0-maccatalyst/maccatalyst-x64/linker-cache/libveldrid-spirv.dylib' for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

Update SPIRV-Cross

I found a bug in SPIRV-Cross, which has now been fixed:
KhronosGroup/SPIRV-Cross#796 (comment)

Please could you cut a new release based on the latest version of SPIRV-Cross? I’m not sure what update schedule you have in mind, no problem if this doesn’t fit with that.

(By the way, the fix for the bug I reported only applies when the platform is set to macOS, but as far as I can tell Veldrid.SPIRV doesn’t specify the MSL target so it defaults to macOS, which happens to work out for me.)

Reason for hard-linking Vertex and Fragment shaders?

What is the reason for requiring both a vertex and fragment shader when using the factories to create Shaders?

In my engine I'd like to:

  • Create a single VertexShader for static meshes (and only compile it once)
  • Have multiple FragmentShaders for different kinds of static meshes
  • Then combine the single VertexShader in the various pipelines/shader sets with whatever FragmentShader is needed for the respective mesh.

Maybe I just couldn't find the correct way, but there doesn't seem to be a workflow that allows a single shader stage to be compiled from a generic language (like GLSL) to the currently used backend (whichever that may be depending on the running platform).
(Refer to the CreateFromSpirv ResourceFactory extensions)

Dylib for apple silicon

How can I build this for mac arm64? My 2 hour adventure has been unfruitful. Help is much appreciated...

Update shaderc

It seems like the version currently used by Veldrid.SPIRV is not quite up-to-date. For instance, it doesn't allow me to use GL_EXT_samplerless_texture_functions, which is definitely supported in newer builds. Do you think you could make a new release based on the latest version?

Uniform names changed

in version 1.0.12 the names of the uniforms get changed from the original code.
the source uniform definition:
#version 450 layout(set = 0, binding = 2) uniform World { mat4 field_World; };

after crosscompile in 1.0.12:
#version 330 layout(std140) uniform vdspv_0_2 { mat4 field_World; } _13;

after crosscompile in 1.0.11:
#version 330 layout(std140) uniform World { mat4 field_World; } _13;

System.DllNotFoundException: libveldrid-spirv

Similar story to: veldrid/veldrid#24 (comment)

Running with mono on mac, and I'm getting:

System.DllNotFoundException: libveldrid-spirv
  at (wrapper managed-to-native) Veldrid.SPIRV.VeldridSpirvNative.CompileGlslToSpirv(Veldrid.SPIRV.GlslCompileInfo*)
  at Veldrid.SPIRV.SpirvCompilation.CompileGlslToSpirv (System.UInt32 sourceLength, System.Byte* sourceTextPtr, System.String fileName, Veldrid.ShaderStages stage, System.Boolean debug, System.UInt32 macroCount, Veldrid.SPIRV.NativeMacroDefinition* macros) [0x0009c] in <6bb6e2dfb45547aabdc0ab126bf5387e>:0 
  at Veldrid.SPIRV.SpirvCompilation.CompileVertexFragment (System.Byte[] vsBytes, System.Byte[] fsBytes, Veldrid.SPIRV.CrossCompileTarget target, Veldrid.SPIRV.CrossCompileOptions options) [0x00029] in <6bb6e2dfb45547aabdc0ab126bf5387e>:0 
  at Veldrid.SPIRV.ResourceFactoryExtensions.CreateFromSpirv (Veldrid.ResourceFactory factory, Veldrid.ShaderDescription vertexShaderDescription, Veldrid.ShaderDescription fragmentShaderDescription, Veldrid.SPIRV.CrossCompileOptions options) [0x0004e] in <6bb6e2dfb45547aabdc0ab126bf5387e>:0 
  at Veldrid.SPIRV.ResourceFactoryExtensions.CreateFromSpirv (Veldrid.ResourceFactory factory, Veldrid.ShaderDescription vertexShaderDescription, Veldrid.ShaderDescription fragmentShaderDescription) [0x00008] in <6bb6e2dfb45547aabdc0ab126bf5387e>:0 
  at AGS.Engine.Desktop.VeldridGraphics.Init () [0x0004d] in /Users/zachi/Projects/MonoAGS/Source/Engine/AGS.Engine.Desktop/Veldrid/VeldridGraphics.cs:235 
  at AGS.Engine.AGSGame.onGameWindowLoaded (Autofac.TypedParameter settingsParameter, AGS.API.IGameSettings settings) [0x0003b] in /Users/zachi/Projects/MonoAGS/Source/Engine/AGS.Engine/Game/AGSGame.cs:255 
  at AGS.Engine.AGSGame+<>c__DisplayClass89_0.<Start>b__0 (System.Object sender, System.EventArgs e) [0x00001] in /Users/zachi/Projects/MonoAGS/Source/Engine/AGS.Engine/Game/AGSGame.cs:128 
  at AGS.Engine.Desktop.VeldridGameWindow.onShown () [0x00000] in /Users/zachi/Projects/MonoAGS/Source/Engine/AGS.Engine.Desktop/Veldrid/VeldridGameWindow.cs:137 
  at Veldrid.Sdl2.Sdl2Window.HandleWindowEvent (Veldrid.Sdl2.SDL_WindowEvent windowEvent) [0x00082] in <0cc1ad6b9b954430b07cefd96775c479>:0 
  at Veldrid.Sdl2.Sdl2Window.HandleEvent (Veldrid.Sdl2.SDL_Event* ev) [0x0018f] in <0cc1ad6b9b954430b07cefd96775c479>:0 
  at Veldrid.Sdl2.Sdl2Window.ProcessEvents (Veldrid.Sdl2.SDLEventHandler eventHandler) [0x0002f] in <0cc1ad6b9b954430b07cefd96775c479>:0 
  at Veldrid.Sdl2.Sdl2Window.PumpEvents () [0x00038] in <0cc1ad6b9b954430b07cefd96775c479>:0 
  at AGS.Engine.Desktop.VeldridGameWindow.onRenderFrame (System.Object sender, AGS.Engine.FrameEventArgs e) [0x00015] in /Users/zachi/Projects/MonoAGS/Source/Engine/AGS.Engine.Desktop/Veldrid/VeldridGameWindow.cs:144 
  at (wrapper delegate-invoke) System.EventHandler`1[AGS.Engine.FrameEventArgs].invoke_void_object_TEventArgs(object,AGS.Engine.FrameEventArgs)
  at AGS.Engine.AGSUpdateThread.RaiseUpdateFrame (System.Double elapsed, System.Double& timestamp) [0x0000e] in /Users/zachi/Projects/MonoAGS/Source/Engine/AGS.Engine/Game/AGSUpdateThread.cs:227 
  at AGS.Engine.AGSUpdateThread.DispatchUpdateFrame () [0x0002c] in /Users/zachi/Projects/MonoAGS/Source/Engine/AGS.Engine/Game/AGSUpdateThread.cs:193 
  at AGS.Engine.AGSUpdateThread.threadLoop () [0x00028] in /Users/zachi/Projects/MonoAGS/Source/Engine/AGS.Engine/Game/AGSUpdateThread.cs:176 
  at AGS.Engine.AGSUpdateThread.Run (System.Double updates_per_second, System.Boolean spawnThread) [0x0008a] in /Users/zachi/Projects/MonoAGS/Source/Engine/AGS.Engine/Game/AGSUpdateThread.cs:165 
  at AGS.Engine.Desktop.VeldridGameWindow.Run (System.Double updateRate) [0x00032] in /Users/zachi/Projects/MonoAGS/Source/Engine/AGS.Engine.Desktop/Veldrid/VeldridGameWindow.cs:124 
  at AGS.Engine.AGSGame.Start () [0x0019e] in /Users/zachi/Projects/MonoAGS/Source/Engine/AGS.Engine/Game/AGSGame.cs:150 

Worked around it for now by copying the file manually from
~/.nuget/packages/veldrid.spirv/1.0.7/runtimes/osx-x64/native/libveldrid-spirv.dylib

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.