From e839f058afd290bdf8db58ecf94fc68c6f1376c5 Mon Sep 17 00:00:00 2001 From: Chance Snow Date: Sun, 18 Nov 2018 08:10:16 -0800 Subject: [PATCH 1/9] Add HLSL support --- src/Veldrid.SPIRV.Tests/CompilationTests.cs | 52 ++++++++++++ .../TestShaders/instance.frag.hlsl | 42 ++++++++++ .../TestShaders/instance.vert.hlsl | 84 +++++++++++++++++++ .../TestShaders/planet.frag.hlsl | 42 ++++++++++ .../TestShaders/planet.vert.hlsl | 31 +++++++ .../TestShaders/starfield.frag.hlsl | 51 +++++++++++ .../TestShaders/starfield.vert.hlsl | 16 ++++ src/Veldrid.SPIRV/CrossCompileOptions.cs | 20 +++++ src/Veldrid.SPIRV/GlslCompileInfo.cs | 1 + src/Veldrid.SPIRV/GlslCompileOptions.cs | 7 +- .../ResourceFactoryExtensions.cs | 9 +- src/Veldrid.SPIRV/ShadercSourceLanguage.cs | 8 ++ src/Veldrid.SPIRV/SourceLanguage.cs | 9 ++ src/Veldrid.SPIRV/SpirvCompilation.cs | 24 ++++-- src/libveldrid-spirv/InteropStructs.hpp | 1 + src/libveldrid-spirv/libveldrid-spirv.cpp | 2 + 16 files changed, 385 insertions(+), 14 deletions(-) create mode 100644 src/Veldrid.SPIRV.Tests/TestShaders/instance.frag.hlsl create mode 100644 src/Veldrid.SPIRV.Tests/TestShaders/instance.vert.hlsl create mode 100644 src/Veldrid.SPIRV.Tests/TestShaders/planet.frag.hlsl create mode 100644 src/Veldrid.SPIRV.Tests/TestShaders/planet.vert.hlsl create mode 100644 src/Veldrid.SPIRV.Tests/TestShaders/starfield.frag.hlsl create mode 100644 src/Veldrid.SPIRV.Tests/TestShaders/starfield.vert.hlsl create mode 100644 src/Veldrid.SPIRV/ShadercSourceLanguage.cs create mode 100644 src/Veldrid.SPIRV/SourceLanguage.cs diff --git a/src/Veldrid.SPIRV.Tests/CompilationTests.cs b/src/Veldrid.SPIRV.Tests/CompilationTests.cs index 4f88312..e060134 100644 --- a/src/Veldrid.SPIRV.Tests/CompilationTests.cs +++ b/src/Veldrid.SPIRV.Tests/CompilationTests.cs @@ -60,6 +60,32 @@ public void VertexFragmentSucceeds(string vs, string fs, CrossCompileTarget targ Assert.NotNull(result.FragmentShader); } + [Theory] + [InlineData("instance.vert.hlsl", "instance.frag.hlsl", CrossCompileTarget.HLSL)] + [InlineData("instance.vert.hlsl", "instance.frag.hlsl", CrossCompileTarget.GLSL)] + [InlineData("instance.vert.hlsl", "instance.frag.hlsl", CrossCompileTarget.ESSL)] + [InlineData("instance.vert.hlsl", "instance.frag.hlsl", CrossCompileTarget.MSL)] + [InlineData("planet.vert.hlsl", "planet.frag.hlsl", CrossCompileTarget.HLSL)] + [InlineData("planet.vert.hlsl", "planet.frag.hlsl", CrossCompileTarget.GLSL)] + [InlineData("planet.vert.hlsl", "planet.frag.hlsl", CrossCompileTarget.ESSL)] + [InlineData("planet.vert.hlsl", "planet.frag.hlsl", CrossCompileTarget.MSL)] + [InlineData("starfield.vert.hlsl", "starfield.frag.hlsl", CrossCompileTarget.HLSL)] + [InlineData("starfield.vert.hlsl", "starfield.frag.hlsl", CrossCompileTarget.GLSL)] + [InlineData("starfield.vert.hlsl", "starfield.frag.hlsl", CrossCompileTarget.ESSL)] + [InlineData("starfield.vert.hlsl", "starfield.frag.hlsl", CrossCompileTarget.MSL)] + public void VertexFragmentSucceeds_Hlsl(string vs, string fs, CrossCompileTarget target) + { + byte[] vsBytes = TestUtil.LoadBytes(vs); + byte[] fsBytes = TestUtil.LoadBytes(fs); + VertexFragmentCompilationResult result = SpirvCompilation.CompileVertexFragment( + vsBytes, + fsBytes, + target, + new CrossCompileOptions(SourceLanguage.HLSL, false, false, specializations)); + Assert.NotNull(result.VertexShader); + Assert.NotNull(result.FragmentShader); + } + [Theory] [InlineData("simple.comp", CrossCompileTarget.HLSL)] [InlineData("simple.comp", CrossCompileTarget.GLSL)] @@ -114,6 +140,32 @@ public void GlslToSpirv_Succeeds(string name, ShaderStages stage) SpirvCompilationResult result = SpirvCompilation.CompileGlslToSpirv( TestUtil.LoadShaderText(name), name, + SourceLanguage.GLSL, + stage, + new GlslCompileOptions( + false, + new MacroDefinition("Name0", "Value0"), + new MacroDefinition("Name1", "Value1"), + new MacroDefinition("Name2"))); + + Assert.NotNull(result.SpirvBytes); + Assert.True(result.SpirvBytes.Length > 4); + Assert.True(result.SpirvBytes.Length % 4 == 0); + } + + [Theory] + [InlineData("instance.vert.hlsl", ShaderStages.Vertex)] + [InlineData("instance.frag.hlsl", ShaderStages.Fragment)] + [InlineData("planet.vert.hlsl", ShaderStages.Vertex)] + [InlineData("planet.frag.hlsl", ShaderStages.Fragment)] + [InlineData("starfield.vert.hlsl", ShaderStages.Vertex)] + [InlineData("starfield.frag.hlsl", ShaderStages.Fragment)] + public void HlslToSpirv_Succeeds(string name, ShaderStages stage) + { + SpirvCompilationResult result = SpirvCompilation.CompileGlslToSpirv( + TestUtil.LoadShaderText(name), + name, + SourceLanguage.HLSL, stage, new GlslCompileOptions( false, diff --git a/src/Veldrid.SPIRV.Tests/TestShaders/instance.frag.hlsl b/src/Veldrid.SPIRV.Tests/TestShaders/instance.frag.hlsl new file mode 100644 index 0000000..5b34bf6 --- /dev/null +++ b/src/Veldrid.SPIRV.Tests/TestShaders/instance.frag.hlsl @@ -0,0 +1,42 @@ +struct FragmentIn +{ + float4 Position : SV_Position; + float3 Position_WorldSpace : POSITION0; + float3 Normal : NORMAL0; + float3 TexCoord : TEXCOORD0; +}; + +cbuffer LightInfo : register(b2) +{ + float3 LightDirection; + float padding0; + float3 CameraPosition; + float padding1; +} + +Texture2DArray Tex : register(t0); +SamplerState Samp : register(s0); + +float4 FS(FragmentIn input) : SV_Target0 +{ + float4 texColor = Tex.Sample(Samp, input.TexCoord); + + float diffuseIntensity = saturate(dot(input.Normal, -LightDirection)); + float4 diffuseColor = texColor * diffuseIntensity; + + // Specular color + float4 specColor = float4(0, 0, 0, 0); + float3 lightColor = float3(1, 1, 1); + float specPower = 5.0f; + float specIntensity = 0.3f; + float3 vertexToEye = -normalize(input.Position_WorldSpace - CameraPosition); + float3 lightReflect = normalize(reflect(LightDirection, input.Normal)); + float specularFactor = dot(vertexToEye, lightReflect); + if (specularFactor > 0) + { + specularFactor = pow(abs(specularFactor), specPower); + specColor = float4(lightColor * specIntensity * specularFactor, 1.0f) * texColor; + } + + return diffuseColor + specColor; +} diff --git a/src/Veldrid.SPIRV.Tests/TestShaders/instance.vert.hlsl b/src/Veldrid.SPIRV.Tests/TestShaders/instance.vert.hlsl new file mode 100644 index 0000000..b60e2a4 --- /dev/null +++ b/src/Veldrid.SPIRV.Tests/TestShaders/instance.vert.hlsl @@ -0,0 +1,84 @@ +cbuffer ProjView : register(b0) +{ + float4x4 View; + float4x4 Proj; +} + +cbuffer RotationInfo : register(b1) +{ + float LocalRotation; + float GlobalRotation; + float2 padding0; +} + +struct VertexIn +{ + float3 Position : POSITION0; + float3 Normal : NORMAL0; + float2 TexCoord : TEXCOORD0; + float3 InstancePosition : POSITION1; + float3 InstanceRotation : TEXCOORD1; + float3 InstanceScale : TEXCOORD2; + int InstanceTexArrayIndex : TEXCOORD3; +}; + +struct FragmentIn +{ + float4 Position : SV_Position; + float3 Position_WorldSpace : POSITION0; + float3 Normal : NORMAL0; + float3 TexCoord : TEXCOORD0; +}; + +FragmentIn VS(VertexIn input) +{ + float cosX = cos(input.InstanceRotation.x); + float sinX = sin(input.InstanceRotation.x); + float3x3 instanceRotX = + { + 1, 0, 0, + 0, cosX, -sinX, + 0, sinX, cosX + }; + + float cosY = cos(input.InstanceRotation.y + LocalRotation); + float sinY = sin(input.InstanceRotation.y + LocalRotation); + float3x3 instanceRotY = + { + cosY, 0, sinY, + 0, 1, 0, + -sinY, 0, cosY + }; + + float cosZ = cos(input.InstanceRotation.z); + float sinZ = sin(input.InstanceRotation.z); + float3x3 instanceRotZ = + { + cosZ, -sinZ, 0, + sinZ, cosZ, 0, + 0, 0, 1 + }; + + float3x3 instanceRotFull = mul(instanceRotZ, mul(instanceRotY, instanceRotZ)); + float3x3 scalingMat = { input.InstanceScale.x, 0, 0, 0, input.InstanceScale.y, 0, 0, 0, input.InstanceScale.z }; + + float globalCos = cos(GlobalRotation); + float globalSin = sin(GlobalRotation); + + float3x3 globalRotMat = + { + globalCos, 0, globalSin, + 0, 1, 0, + -globalSin, 0, globalCos + }; + + FragmentIn output; + float3 transformedPos = (mul(scalingMat, mul(instanceRotFull, input.Position)) + input.InstancePosition); + transformedPos = mul(globalRotMat, transformedPos); + float4 pos = float4(transformedPos, 1); + output.Position_WorldSpace = transformedPos; + output.Position = mul(Proj, mul(View, pos)); + output.Normal = normalize(mul(globalRotMat, mul(instanceRotFull, input.Normal))); + output.TexCoord = float3(input.TexCoord, input.InstanceTexArrayIndex); + return output; +} diff --git a/src/Veldrid.SPIRV.Tests/TestShaders/planet.frag.hlsl b/src/Veldrid.SPIRV.Tests/TestShaders/planet.frag.hlsl new file mode 100644 index 0000000..d4602a7 --- /dev/null +++ b/src/Veldrid.SPIRV.Tests/TestShaders/planet.frag.hlsl @@ -0,0 +1,42 @@ +struct FragmentIn +{ + float4 Position : SV_Position; + float3 Position_WorldSpace : POSITION0; + float3 Normal : NORMAL0; + float2 TexCoord : TEXCOORD0; +}; + +cbuffer LightInfo : register(b2) +{ + float3 LightDirection; + float padding0; + float3 CameraPosition; + float padding1; +} + +Texture2D Tex : register(t0); +SamplerState Samp : register(s0); + +float4 FS(FragmentIn input) : SV_Target0 +{ + float4 texColor = Tex.Sample(Samp, input.TexCoord); + + float diffuseIntensity = saturate(dot(input.Normal, -LightDirection)); + float4 diffuseColor = texColor * diffuseIntensity; + + // Specular color + float4 specColor = float4(0, 0, 0, 0); + float3 lightColor = float3(1, 1, 1); + float specPower = 5.0f; + float specIntensity = 1.f; + float3 vertexToEye = -normalize(input.Position_WorldSpace - CameraPosition); + float3 lightReflect = normalize(reflect(LightDirection, input.Normal)); + float specularFactor = dot(vertexToEye, lightReflect); + if (specularFactor > 0) + { + specularFactor = pow(abs(specularFactor), specPower); + specColor = float4(lightColor * specIntensity * specularFactor, 1.0f) * texColor; + } + + return diffuseColor + specColor; +} diff --git a/src/Veldrid.SPIRV.Tests/TestShaders/planet.vert.hlsl b/src/Veldrid.SPIRV.Tests/TestShaders/planet.vert.hlsl new file mode 100644 index 0000000..3c37a17 --- /dev/null +++ b/src/Veldrid.SPIRV.Tests/TestShaders/planet.vert.hlsl @@ -0,0 +1,31 @@ +cbuffer ProjView : register(b0) +{ + float4x4 View; + float4x4 Proj; +} + +struct VertexIn +{ + float3 Position : POSITION0; + float3 Normal : NORMAL0; + float2 TexCoord : TEXCOORD0; +}; + +struct FragmentIn +{ + float4 Position : SV_Position; + float3 Position_WorldSpace : POSITION0; + float3 Normal : NORMAL0; + float2 TexCoord : TEXCOORD0; +}; + +FragmentIn VS(VertexIn input) +{ + FragmentIn output; + float4 pos = float4(input.Position, 1); + output.Position_WorldSpace = input.Position; + output.Position = mul(Proj, mul(View, pos)); + output.Normal = input.Normal; + output.TexCoord = input.TexCoord * float2(10, 6); + return output; +} diff --git a/src/Veldrid.SPIRV.Tests/TestShaders/starfield.frag.hlsl b/src/Veldrid.SPIRV.Tests/TestShaders/starfield.frag.hlsl new file mode 100644 index 0000000..8955bcb --- /dev/null +++ b/src/Veldrid.SPIRV.Tests/TestShaders/starfield.frag.hlsl @@ -0,0 +1,51 @@ +#define HASHSCALE3 float3(443.897, 441.423, 437.195) +#define STARFREQUENCY 0.01 + +cbuffer InvCameraInfo : register(b0) +{ + float4x4 InvProj; + float4x4 InvView; +} + +struct FragmentIn +{ + float4 Position : SV_Position; + float4 ClipPos : Position0; + float3 TexCoord : TEXCOORD0; +}; + +// Hash function by Dave Hoskins (https://www.shadertoy.com/view/4djSRW) +float hash33(float3 p3) +{ + p3 = frac(p3 * HASHSCALE3); + p3 += dot(p3, p3.yxz + float3(19.19, 19.19, 19.19)); + return frac((p3.x + p3.y) * p3.z + (p3.x + p3.z) * p3.y + (p3.y + p3.z) * p3.x); +} + +float3 starField(float3 pos) +{ + float3 color = float3(0, 0, 0); + float threshhold = (1.0 - STARFREQUENCY); + float rnd = hash33(pos); + if (rnd >= threshhold) + { + float starCol = pow(abs((rnd - threshhold) / (1.0 - threshhold)), 16.0); + color += float3(starCol, starCol, starCol); + } + return color; +} + +float4 FS(FragmentIn input) : SV_Target0 +{ + // View Coordinates + float4 viewCoords = mul(InvProj, input.ClipPos); + viewCoords.z = -1.0f; + viewCoords.w = 0.0f; + + float3 worldDirection = mul(InvView, viewCoords).xyz; + worldDirection = normalize(worldDirection); + + worldDirection = floor(worldDirection * 700) / 700; + + return float4(starField(worldDirection), 1.0); +} diff --git a/src/Veldrid.SPIRV.Tests/TestShaders/starfield.vert.hlsl b/src/Veldrid.SPIRV.Tests/TestShaders/starfield.vert.hlsl new file mode 100644 index 0000000..6c81d46 --- /dev/null +++ b/src/Veldrid.SPIRV.Tests/TestShaders/starfield.vert.hlsl @@ -0,0 +1,16 @@ +struct FragmentIn +{ + float4 Position : SV_Position; + float4 ClipPos : POSITION0; + float3 TexCoord : TEXCOORD0; +}; + +FragmentIn VS(uint vertexID : SV_VertexID) +{ + FragmentIn output; + output.TexCoord = float3((vertexID << 1) & 2, vertexID & 2, vertexID & 2); + output.Position = float4(output.TexCoord.xy * 2.0f - 1.0f, 0.0f, 1.0f); + output.ClipPos = output.Position; + + return output; +} diff --git a/src/Veldrid.SPIRV/CrossCompileOptions.cs b/src/Veldrid.SPIRV/CrossCompileOptions.cs index 8f1be1c..510b67b 100644 --- a/src/Veldrid.SPIRV/CrossCompileOptions.cs +++ b/src/Veldrid.SPIRV/CrossCompileOptions.cs @@ -7,6 +7,9 @@ namespace Veldrid.SPIRV /// public class CrossCompileOptions { + /// Source language from which to translate. The default is GLSL. + public SourceLanguage SourceLanguage { get; set; } + /// /// Indicates whether or not the compiled shader output should include a clip-space Z-range fixup at the end of the /// vertex shader. @@ -33,6 +36,7 @@ public class CrossCompileOptions /// public CrossCompileOptions() { + SourceLanguage = SourceLanguage.GLSL; Specializations = Array.Empty(); } @@ -58,7 +62,23 @@ public CrossCompileOptions(bool fixClipSpaceZ, bool invertVertexOutputY) /// An array of which will be substituted into the /// shader as new constants. public CrossCompileOptions(bool fixClipSpaceZ, bool invertVertexOutputY, params SpecializationConstant[] specializations) + : this(SourceLanguage.GLSL, fixClipSpaceZ, invertVertexOutputY, specializations) + { + } + + /// + /// Constructs a new , used to control the parameters of shader translation. + /// + /// Source language from which to translate. + /// Indicates whether or not the compiled shader output should include a clip-space Z-range + /// fixup at the end of the vertex shader. + /// Indicates whether or not the compiled shader output should include a fixup at the + /// end of the vertex shader which inverts the clip-space Y value. + /// An array of which will be substituted into the + /// shader as new constants. + public CrossCompileOptions(SourceLanguage sourceLanguage, bool fixClipSpaceZ, bool invertVertexOutputY, params SpecializationConstant[] specializations) { + SourceLanguage = sourceLanguage; FixClipSpaceZ = fixClipSpaceZ; InvertVertexOutputY = invertVertexOutputY; Specializations = specializations; diff --git a/src/Veldrid.SPIRV/GlslCompileInfo.cs b/src/Veldrid.SPIRV/GlslCompileInfo.cs index 028e284..f6f2015 100644 --- a/src/Veldrid.SPIRV/GlslCompileInfo.cs +++ b/src/Veldrid.SPIRV/GlslCompileInfo.cs @@ -13,6 +13,7 @@ internal unsafe struct GlslCompileInfo /// Element type: byte /// public InteropArray FileName; + public ShadercSourceLanguage Language; public ShadercShaderKind Kind; public Bool32 Debug; /// diff --git a/src/Veldrid.SPIRV/GlslCompileOptions.cs b/src/Veldrid.SPIRV/GlslCompileOptions.cs index 0e08c64..5018dee 100644 --- a/src/Veldrid.SPIRV/GlslCompileOptions.cs +++ b/src/Veldrid.SPIRV/GlslCompileOptions.cs @@ -3,10 +3,13 @@ namespace Veldrid.SPIRV { /// - /// An object used to control the options for compiling from GLSL to SPIR-V. + /// An object used to control the options for compiling from GLSL/HLSL to SPIR-V. /// public class GlslCompileOptions { + /// Source language from which to compile. The default is GLSL. + public SourceLanguage Language { get; set; } + /// /// Indicates whether the compiled output should preserve debug information. NOTE: If the resulting SPIR-V is intended to /// be used as the source of an OpenGL-style GLSL shader, then this property should be set to . @@ -28,6 +31,7 @@ public class GlslCompileOptions /// public GlslCompileOptions() { + Language = SourceLanguage.GLSL; Macros = Array.Empty(); } @@ -41,6 +45,7 @@ public GlslCompileOptions() /// when compiling the GLSL source code. public GlslCompileOptions(bool debug, params MacroDefinition[] macros) { + Language = SourceLanguage.GLSL; Debug = debug; Macros = macros; } diff --git a/src/Veldrid.SPIRV/ResourceFactoryExtensions.cs b/src/Veldrid.SPIRV/ResourceFactoryExtensions.cs index 6457a84..8d1f740 100644 --- a/src/Veldrid.SPIRV/ResourceFactoryExtensions.cs +++ b/src/Veldrid.SPIRV/ResourceFactoryExtensions.cs @@ -48,8 +48,8 @@ public static Shader[] CreateFromSpirv( GraphicsBackend backend = factory.BackendType; if (backend == GraphicsBackend.Vulkan) { - vertexShaderDescription.ShaderBytes = EnsureSpirv(vertexShaderDescription); - fragmentShaderDescription.ShaderBytes = EnsureSpirv(fragmentShaderDescription); + vertexShaderDescription.ShaderBytes = EnsureSpirv(vertexShaderDescription, options); + fragmentShaderDescription.ShaderBytes = EnsureSpirv(fragmentShaderDescription, options); return new Shader[] { @@ -121,7 +121,7 @@ public static Shader CreateFromSpirv( GraphicsBackend backend = factory.BackendType; if (backend == GraphicsBackend.Vulkan) { - computeShaderDescription.ShaderBytes = EnsureSpirv(computeShaderDescription); + computeShaderDescription.ShaderBytes = EnsureSpirv(computeShaderDescription, options); return factory.CreateShader(ref computeShaderDescription); } @@ -141,7 +141,7 @@ public static Shader CreateFromSpirv( computeEntryPoint)); } - private static unsafe byte[] EnsureSpirv(ShaderDescription description) + private static unsafe byte[] EnsureSpirv(ShaderDescription description, CrossCompileOptions options) { if (Util.HasSpirvHeader(description.ShaderBytes)) { @@ -155,6 +155,7 @@ private static unsafe byte[] EnsureSpirv(ShaderDescription description) (uint)description.ShaderBytes.Length, sourceAsciiPtr, null, + options.SourceLanguage, description.Stage, description.Debug, 0, diff --git a/src/Veldrid.SPIRV/ShadercSourceLanguage.cs b/src/Veldrid.SPIRV/ShadercSourceLanguage.cs new file mode 100644 index 0000000..a6d35e2 --- /dev/null +++ b/src/Veldrid.SPIRV/ShadercSourceLanguage.cs @@ -0,0 +1,8 @@ +namespace Veldrid.SPIRV +{ + internal enum ShadercSourceLanguage + { + GLSL, + HLSL, + } +} diff --git a/src/Veldrid.SPIRV/SourceLanguage.cs b/src/Veldrid.SPIRV/SourceLanguage.cs new file mode 100644 index 0000000..19ff6d2 --- /dev/null +++ b/src/Veldrid.SPIRV/SourceLanguage.cs @@ -0,0 +1,9 @@ +namespace Veldrid.SPIRV +{ + /// Source language from which to compile a shader. + enum SourceLanguage + { + GLSL, + HLSL, + } +} \ No newline at end of file diff --git a/src/Veldrid.SPIRV/SpirvCompilation.cs b/src/Veldrid.SPIRV/SpirvCompilation.cs index 8db9079..f073062 100644 --- a/src/Veldrid.SPIRV/SpirvCompilation.cs +++ b/src/Veldrid.SPIRV/SpirvCompilation.cs @@ -52,6 +52,7 @@ public static unsafe VertexFragmentCompilationResult CompileVertexFragment( (uint)vsBytes.Length, sourceTextPtr, string.Empty, + options.SourceLanguage, ShaderStages.Vertex, target == CrossCompileTarget.GLSL || target == CrossCompileTarget.ESSL, 0, @@ -72,6 +73,7 @@ public static unsafe VertexFragmentCompilationResult CompileVertexFragment( (uint)fsBytes.Length, sourceTextPtr, string.Empty, + options.SourceLanguage, ShaderStages.Fragment, target == CrossCompileTarget.GLSL || target == CrossCompileTarget.ESSL, 0, @@ -124,19 +126,19 @@ public static unsafe VertexFragmentCompilationResult CompileVertexFragment( } /// - /// Cross-compiles the given vertex-fragment pair into some target language. + /// Cross-compiles the given compute shader into some target language. /// - /// The compute shader's SPIR-V bytecode or ASCII-encoded GLSL source code. + /// The compute shader's SPIR-V bytecode or ASCII-encoded GLSL/HLSL source code. /// The target language. /// A containing the compiled output. public static unsafe ComputeCompilationResult CompileCompute( byte[] csBytes, - CrossCompileTarget target) => CompileCompute(csBytes, target, new CrossCompileOptions()); + CrossCompileTarget target) => CompileCompute(csBytes, language, target, new CrossCompileOptions()); /// - /// Cross-compiles the given vertex-fragment pair into some target language. + /// Cross-compiles the given compute shader into some target language. /// - /// The compute shader's SPIR-V bytecode or ASCII-encoded GLSL source code. + /// The compute shader's SPIR-V bytecode or ASCII-encoded GLSL/HLSL source code. /// The target language. /// The options for shader translation. /// A containing the compiled output. @@ -155,15 +157,16 @@ public static unsafe ComputeCompilationResult CompileCompute( { fixed (byte* sourceTextPtr = csBytes) { - SpirvCompilationResult vsCompileResult = CompileGlslToSpirv( + SpirvCompilationResult compileResult = CompileGlslToSpirv( (uint)csBytes.Length, sourceTextPtr, string.Empty, + options.SourceLanguage, ShaderStages.Compute, target == CrossCompileTarget.GLSL || target == CrossCompileTarget.ESSL, 0, null); - csSpirvBytes = vsCompileResult.SpirvBytes; + csSpirvBytes = compileResult.SpirvBytes; } } @@ -201,12 +204,12 @@ public static unsafe ComputeCompilationResult CompileCompute( } /// - /// Compiles the given GLSL source code into SPIR-V. + /// Compiles the given GLSL/HLSL source code into SPIR-V. /// /// The shader source code. /// A descriptive name for the shader. May be null. /// The which the shader is used in. - /// Parameters for the GLSL compiler. + /// Parameters for the compiler. /// A containing the compiled SPIR-V bytecode. public static unsafe SpirvCompilationResult CompileGlslToSpirv( string sourceText, @@ -232,6 +235,7 @@ public static unsafe SpirvCompilationResult CompileGlslToSpirv( (uint)sourceAsciiCount, sourceAsciiPtr, fileName, + options.Language, stage, options.Debug, (uint)macroCount, @@ -242,12 +246,14 @@ internal static unsafe SpirvCompilationResult CompileGlslToSpirv( uint sourceLength, byte* sourceTextPtr, string fileName, + SourceLanguage language, ShaderStages stage, bool debug, uint macroCount, NativeMacroDefinition* macros) { GlslCompileInfo info; + info.Language = language; info.Kind = GetShadercKind(stage); info.SourceText = new InteropArray(sourceLength, sourceTextPtr); info.Debug = debug; diff --git a/src/libveldrid-spirv/InteropStructs.hpp b/src/libveldrid-spirv/InteropStructs.hpp index 8233e2b..0115da8 100644 --- a/src/libveldrid-spirv/InteropStructs.hpp +++ b/src/libveldrid-spirv/InteropStructs.hpp @@ -162,6 +162,7 @@ struct GlslCompileInfo { InteropArray SourceText; InteropArray FileName; + shaderc_source_language Language; shaderc_shader_kind Kind; Bool32 Debug; InteropArray Macros; diff --git a/src/libveldrid-spirv/libveldrid-spirv.cpp b/src/libveldrid-spirv/libveldrid-spirv.cpp index fbda7cf..a05deaa 100644 --- a/src/libveldrid-spirv/libveldrid-spirv.cpp +++ b/src/libveldrid-spirv/libveldrid-spirv.cpp @@ -560,6 +560,8 @@ VD_EXPORT CompilationResult* CompileGlslToSpirv(GlslCompileInfo* info) { shaderc::CompileOptions options; + options.SetSourceLanguage(info->Language); + if (info->Debug) { options.SetGenerateDebugInfo(); From bf601ec8d60c056d1a883a21bc0714bb7294a746 Mon Sep 17 00:00:00 2001 From: Chance Snow Date: Tue, 20 Nov 2018 08:54:04 -0800 Subject: [PATCH 2/9] Fix _BuildConfig bash variable declaration --- build-local-package.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build-local-package.sh b/build-local-package.sh index 35fefdd..0dbbcdf 100755 --- a/build-local-package.sh +++ b/build-local-package.sh @@ -2,7 +2,7 @@ scriptPath="`dirname \"$0\"`" -_BuildConfig = Debug +_BuildConfig=Debug while :; do if [ $# -le 0 ]; then @@ -25,4 +25,4 @@ while :; do done $scriptPath/build-native.sh $_BuildConfig -dotnet pack -c $_BuildConfig $scriptPath/src/Veldrid.SPIRV/Veldrid.SPIRV.csproj \ No newline at end of file +dotnet pack -c $_BuildConfig $scriptPath/src/Veldrid.SPIRV/Veldrid.SPIRV.csproj From 9116d550916eb06722da8ba425e5d09e2ca41b93 Mon Sep 17 00:00:00 2001 From: Chance Snow Date: Tue, 20 Nov 2018 08:57:40 -0800 Subject: [PATCH 3/9] Fix SourceLanguage enum visibility --- src/Veldrid.SPIRV/SourceLanguage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Veldrid.SPIRV/SourceLanguage.cs b/src/Veldrid.SPIRV/SourceLanguage.cs index 19ff6d2..1427791 100644 --- a/src/Veldrid.SPIRV/SourceLanguage.cs +++ b/src/Veldrid.SPIRV/SourceLanguage.cs @@ -1,7 +1,7 @@ namespace Veldrid.SPIRV { /// Source language from which to compile a shader. - enum SourceLanguage + public enum SourceLanguage { GLSL, HLSL, From 69dc05e245616327768a173e64c0abae9f0c5a30 Mon Sep 17 00:00:00 2001 From: Chance Snow Date: Tue, 20 Nov 2018 09:06:47 -0800 Subject: [PATCH 4/9] Fix GlslCompileInfo.Language initializer, convert to interop enum value --- src/Veldrid.SPIRV/SpirvCompilation.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Veldrid.SPIRV/SpirvCompilation.cs b/src/Veldrid.SPIRV/SpirvCompilation.cs index f073062..2feadb7 100644 --- a/src/Veldrid.SPIRV/SpirvCompilation.cs +++ b/src/Veldrid.SPIRV/SpirvCompilation.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Text; namespace Veldrid.SPIRV @@ -253,7 +253,7 @@ internal static unsafe SpirvCompilationResult CompileGlslToSpirv( NativeMacroDefinition* macros) { GlslCompileInfo info; - info.Language = language; + info.Language = GetShadercLanguage(language); info.Kind = GetShadercKind(stage); info.SourceText = new InteropArray(sourceLength, sourceTextPtr); info.Debug = debug; @@ -299,6 +299,16 @@ internal static unsafe SpirvCompilationResult CompileGlslToSpirv( } } + private static ShadercSourceLanguage GetShadercLanguage(SourceLanguage language) + { + switch (language) + { + case SourceLanguage.GLSL: return ShadercSourceLanguage.GLSL; + case SourceLanguage.HLSL: return ShadercSourceLanguage.HLSL; + default: throw new SpirvCompilationException($"Invalid shader source language: {language}"); + } + } + private static ShadercShaderKind GetShadercKind(ShaderStages stage) { switch (stage) From 15046e34b249c3309dd92a6f14933825896cd02a Mon Sep 17 00:00:00 2001 From: Chance Snow Date: Tue, 20 Nov 2018 09:15:47 -0800 Subject: [PATCH 5/9] Fix CompileCompute overload call, remove "language" typo --- src/Veldrid.SPIRV/SpirvCompilation.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Veldrid.SPIRV/SpirvCompilation.cs b/src/Veldrid.SPIRV/SpirvCompilation.cs index 2feadb7..fe897c3 100644 --- a/src/Veldrid.SPIRV/SpirvCompilation.cs +++ b/src/Veldrid.SPIRV/SpirvCompilation.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Text; namespace Veldrid.SPIRV @@ -133,7 +133,7 @@ public static unsafe VertexFragmentCompilationResult CompileVertexFragment( /// A containing the compiled output. public static unsafe ComputeCompilationResult CompileCompute( byte[] csBytes, - CrossCompileTarget target) => CompileCompute(csBytes, language, target, new CrossCompileOptions()); + CrossCompileTarget target) => CompileCompute(csBytes, target, new CrossCompileOptions()); /// /// Cross-compiles the given compute shader into some target language. From 8b9c5ef16e6a48246a830d9e545e2cfa15e8c188 Mon Sep 17 00:00:00 2001 From: Chance Snow Date: Tue, 20 Nov 2018 09:27:52 -0800 Subject: [PATCH 6/9] Add GlslCompileOptions constructor overload for SourceLanguage parameter --- src/Veldrid.SPIRV/GlslCompileOptions.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Veldrid.SPIRV/GlslCompileOptions.cs b/src/Veldrid.SPIRV/GlslCompileOptions.cs index 5018dee..a771986 100644 --- a/src/Veldrid.SPIRV/GlslCompileOptions.cs +++ b/src/Veldrid.SPIRV/GlslCompileOptions.cs @@ -49,5 +49,21 @@ public GlslCompileOptions(bool debug, params MacroDefinition[] macros) Debug = debug; Macros = macros; } + + /// + /// Constructs a new . + /// + /// Indicates whether the compiled output should preserve debug information. NOTE: If the resulting + /// SPIR-V is intended to be used as the source of an OpenGL-style GLSL shader, then this property should be set to + /// . + /// Source language from which to compile a shader. + /// An array of which defines the set of preprocessor macros to define + /// when compiling the GLSL source code. + public GlslCompileOptions(bool debug, SourceLanguage language, params MacroDefinition[] macros) + { + Language = language; + Debug = debug; + Macros = macros; + } } } \ No newline at end of file From 36c685e54b65c1c97658423f7f523eb56f644f65 Mon Sep 17 00:00:00 2001 From: Chance Snow Date: Tue, 20 Nov 2018 09:29:34 -0800 Subject: [PATCH 7/9] Fix HLSL compilation tests --- src/Veldrid.SPIRV.Tests/CompilationTests.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Veldrid.SPIRV.Tests/CompilationTests.cs b/src/Veldrid.SPIRV.Tests/CompilationTests.cs index e060134..2aa7112 100644 --- a/src/Veldrid.SPIRV.Tests/CompilationTests.cs +++ b/src/Veldrid.SPIRV.Tests/CompilationTests.cs @@ -81,7 +81,7 @@ public void VertexFragmentSucceeds_Hlsl(string vs, string fs, CrossCompileTarget vsBytes, fsBytes, target, - new CrossCompileOptions(SourceLanguage.HLSL, false, false, specializations)); + new CrossCompileOptions(SourceLanguage.HLSL, false, false)); Assert.NotNull(result.VertexShader); Assert.NotNull(result.FragmentShader); } @@ -140,7 +140,6 @@ public void GlslToSpirv_Succeeds(string name, ShaderStages stage) SpirvCompilationResult result = SpirvCompilation.CompileGlslToSpirv( TestUtil.LoadShaderText(name), name, - SourceLanguage.GLSL, stage, new GlslCompileOptions( false, @@ -165,10 +164,10 @@ public void HlslToSpirv_Succeeds(string name, ShaderStages stage) SpirvCompilationResult result = SpirvCompilation.CompileGlslToSpirv( TestUtil.LoadShaderText(name), name, - SourceLanguage.HLSL, stage, new GlslCompileOptions( false, + SourceLanguage.HLSL, new MacroDefinition("Name0", "Value0"), new MacroDefinition("Name1", "Value1"), new MacroDefinition("Name2"))); From 138828f5ab59f491ff88428216fa6600ae76f35d Mon Sep 17 00:00:00 2001 From: Chance Snow Date: Tue, 20 Nov 2018 09:46:38 -0800 Subject: [PATCH 8/9] Add doc comments to SourceLanguage enum members --- src/Veldrid.SPIRV/SourceLanguage.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Veldrid.SPIRV/SourceLanguage.cs b/src/Veldrid.SPIRV/SourceLanguage.cs index 1427791..5eeb530 100644 --- a/src/Veldrid.SPIRV/SourceLanguage.cs +++ b/src/Veldrid.SPIRV/SourceLanguage.cs @@ -3,7 +3,13 @@ namespace Veldrid.SPIRV /// Source language from which to compile a shader. public enum SourceLanguage { + /// + /// Compile a shader from GLSL source. + /// GLSL, + /// + /// Compile a shader from HLSL source. + /// HLSL, } } \ No newline at end of file From 62759724ce135e129f07b553d4fd7997818a700e Mon Sep 17 00:00:00 2001 From: Chance Snow Date: Tue, 20 Nov 2018 18:48:32 -0800 Subject: [PATCH 9/9] Replace resource bindings with vk::binding attribute syntax --- src/Veldrid.SPIRV.Tests/TestShaders/instance.frag.hlsl | 9 ++++++--- src/Veldrid.SPIRV.Tests/TestShaders/instance.vert.hlsl | 6 ++++-- src/Veldrid.SPIRV.Tests/TestShaders/planet.frag.hlsl | 9 ++++++--- src/Veldrid.SPIRV.Tests/TestShaders/planet.vert.hlsl | 3 ++- src/Veldrid.SPIRV.Tests/TestShaders/starfield.frag.hlsl | 3 ++- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/Veldrid.SPIRV.Tests/TestShaders/instance.frag.hlsl b/src/Veldrid.SPIRV.Tests/TestShaders/instance.frag.hlsl index 5b34bf6..598dad9 100644 --- a/src/Veldrid.SPIRV.Tests/TestShaders/instance.frag.hlsl +++ b/src/Veldrid.SPIRV.Tests/TestShaders/instance.frag.hlsl @@ -6,7 +6,8 @@ struct FragmentIn float3 TexCoord : TEXCOORD0; }; -cbuffer LightInfo : register(b2) +[[vk::binding(2)]] +cbuffer LightInfo { float3 LightDirection; float padding0; @@ -14,8 +15,10 @@ cbuffer LightInfo : register(b2) float padding1; } -Texture2DArray Tex : register(t0); -SamplerState Samp : register(s0); +[[vk::binding(0)]] +Texture2DArray Tex; +[[vk::binding(1)]] +SamplerState Samp; float4 FS(FragmentIn input) : SV_Target0 { diff --git a/src/Veldrid.SPIRV.Tests/TestShaders/instance.vert.hlsl b/src/Veldrid.SPIRV.Tests/TestShaders/instance.vert.hlsl index b60e2a4..bb62499 100644 --- a/src/Veldrid.SPIRV.Tests/TestShaders/instance.vert.hlsl +++ b/src/Veldrid.SPIRV.Tests/TestShaders/instance.vert.hlsl @@ -1,10 +1,12 @@ -cbuffer ProjView : register(b0) +[[vk::binding(0)]] +cbuffer ProjView { float4x4 View; float4x4 Proj; } -cbuffer RotationInfo : register(b1) +[[vk::binding(1)]] +cbuffer RotationInfo { float LocalRotation; float GlobalRotation; diff --git a/src/Veldrid.SPIRV.Tests/TestShaders/planet.frag.hlsl b/src/Veldrid.SPIRV.Tests/TestShaders/planet.frag.hlsl index d4602a7..5927c5c 100644 --- a/src/Veldrid.SPIRV.Tests/TestShaders/planet.frag.hlsl +++ b/src/Veldrid.SPIRV.Tests/TestShaders/planet.frag.hlsl @@ -6,7 +6,8 @@ struct FragmentIn float2 TexCoord : TEXCOORD0; }; -cbuffer LightInfo : register(b2) +[[vk::binding(2)]] +cbuffer LightInfo { float3 LightDirection; float padding0; @@ -14,8 +15,10 @@ cbuffer LightInfo : register(b2) float padding1; } -Texture2D Tex : register(t0); -SamplerState Samp : register(s0); +[[vk::binding(0)]] +Texture2D Tex; +[[vk::binding(1)]] +SamplerState Samp; float4 FS(FragmentIn input) : SV_Target0 { diff --git a/src/Veldrid.SPIRV.Tests/TestShaders/planet.vert.hlsl b/src/Veldrid.SPIRV.Tests/TestShaders/planet.vert.hlsl index 3c37a17..b50853e 100644 --- a/src/Veldrid.SPIRV.Tests/TestShaders/planet.vert.hlsl +++ b/src/Veldrid.SPIRV.Tests/TestShaders/planet.vert.hlsl @@ -1,4 +1,5 @@ -cbuffer ProjView : register(b0) +[[vk::binding(0)]] +cbuffer ProjView { float4x4 View; float4x4 Proj; diff --git a/src/Veldrid.SPIRV.Tests/TestShaders/starfield.frag.hlsl b/src/Veldrid.SPIRV.Tests/TestShaders/starfield.frag.hlsl index 8955bcb..150671b 100644 --- a/src/Veldrid.SPIRV.Tests/TestShaders/starfield.frag.hlsl +++ b/src/Veldrid.SPIRV.Tests/TestShaders/starfield.frag.hlsl @@ -1,7 +1,8 @@ #define HASHSCALE3 float3(443.897, 441.423, 437.195) #define STARFREQUENCY 0.01 -cbuffer InvCameraInfo : register(b0) +[[vk::binding(0)]] +cbuffer InvCameraInfo { float4x4 InvProj; float4x4 InvView;