Skip to content
51 changes: 51 additions & 0 deletions src/Veldrid.SPIRV.Tests/CompilationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,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));
Assert.NotNull(result.VertexShader);
Assert.NotNull(result.FragmentShader);
}

[Theory]
[InlineData("simple.comp", CrossCompileTarget.HLSL)]
[InlineData("simple.comp", CrossCompileTarget.GLSL)]
Expand Down Expand Up @@ -143,5 +169,30 @@ public void GlslToSpirv_Succeeds(string name, ShaderStages stage)
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,
stage,
new GlslCompileOptions(
false,
SourceLanguage.HLSL,
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);
}
}
}
45 changes: 45 additions & 0 deletions src/Veldrid.SPIRV.Tests/TestShaders/instance.frag.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
struct FragmentIn
{
float4 Position : SV_Position;
float3 Position_WorldSpace : POSITION0;
float3 Normal : NORMAL0;
float3 TexCoord : TEXCOORD0;
};

[[vk::binding(2)]]
cbuffer LightInfo
{
float3 LightDirection;
float padding0;
float3 CameraPosition;
float padding1;
}

[[vk::binding(0)]]
Texture2DArray Tex;
[[vk::binding(1)]]
SamplerState Samp;

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;
}
86 changes: 86 additions & 0 deletions src/Veldrid.SPIRV.Tests/TestShaders/instance.vert.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
[[vk::binding(0)]]
cbuffer ProjView
{
float4x4 View;
float4x4 Proj;
}

[[vk::binding(1)]]
cbuffer RotationInfo
{
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;
}
45 changes: 45 additions & 0 deletions src/Veldrid.SPIRV.Tests/TestShaders/planet.frag.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
struct FragmentIn
{
float4 Position : SV_Position;
float3 Position_WorldSpace : POSITION0;
float3 Normal : NORMAL0;
float2 TexCoord : TEXCOORD0;
};

[[vk::binding(2)]]
cbuffer LightInfo
{
float3 LightDirection;
float padding0;
float3 CameraPosition;
float padding1;
}

[[vk::binding(0)]]
Texture2D Tex;
[[vk::binding(1)]]
SamplerState Samp;

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;
}
32 changes: 32 additions & 0 deletions src/Veldrid.SPIRV.Tests/TestShaders/planet.vert.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[[vk::binding(0)]]
cbuffer ProjView
{
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;
}
52 changes: 52 additions & 0 deletions src/Veldrid.SPIRV.Tests/TestShaders/starfield.frag.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#define HASHSCALE3 float3(443.897, 441.423, 437.195)
#define STARFREQUENCY 0.01

[[vk::binding(0)]]
cbuffer InvCameraInfo
{
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);
}
16 changes: 16 additions & 0 deletions src/Veldrid.SPIRV.Tests/TestShaders/starfield.vert.hlsl
Original file line number Diff line number Diff line change
@@ -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;
}
20 changes: 20 additions & 0 deletions src/Veldrid.SPIRV/CrossCompileOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ namespace Veldrid.SPIRV
/// </summary>
public class CrossCompileOptions
{
/// <summary>Source language from which to translate. The default is GLSL.</summary>
public SourceLanguage SourceLanguage { get; set; }

/// <summary>
/// Indicates whether or not the compiled shader output should include a clip-space Z-range fixup at the end of the
/// vertex shader.
Expand All @@ -33,6 +36,7 @@ public class CrossCompileOptions
/// </summary>
public CrossCompileOptions()
{
SourceLanguage = SourceLanguage.GLSL;
Specializations = Array.Empty<SpecializationConstant>();
}

Expand All @@ -58,7 +62,23 @@ public CrossCompileOptions(bool fixClipSpaceZ, bool invertVertexOutputY)
/// <param name="specializations">An array of <see cref="SpecializationConstant"/> which will be substituted into the
/// shader as new constants.</param>
public CrossCompileOptions(bool fixClipSpaceZ, bool invertVertexOutputY, params SpecializationConstant[] specializations)
: this(SourceLanguage.GLSL, fixClipSpaceZ, invertVertexOutputY, specializations)
{
}

/// <summary>
/// Constructs a new <see cref="CrossCompileOptions"/>, used to control the parameters of shader translation.
/// </summary>
/// <param name="sourceLanguage">Source language from which to translate.</param>
/// <param name="fixClipSpaceZ">Indicates whether or not the compiled shader output should include a clip-space Z-range
/// fixup at the end of the vertex shader.</param>
/// <param name="invertVertexOutputY">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.</param>
/// <param name="specializations">An array of <see cref="SpecializationConstant"/> which will be substituted into the
/// shader as new constants.</param>
public CrossCompileOptions(SourceLanguage sourceLanguage, bool fixClipSpaceZ, bool invertVertexOutputY, params SpecializationConstant[] specializations)
{
SourceLanguage = sourceLanguage;
FixClipSpaceZ = fixClipSpaceZ;
InvertVertexOutputY = invertVertexOutputY;
Specializations = specializations;
Expand Down
1 change: 1 addition & 0 deletions src/Veldrid.SPIRV/GlslCompileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal unsafe struct GlslCompileInfo
/// Element type: byte
/// </summary>
public InteropArray FileName;
public ShadercSourceLanguage Language;
public ShadercShaderKind Kind;
public Bool32 Debug;
/// <summary>
Expand Down
Loading