diff --git a/src/ShaderGen.App/ShaderGen.App.csproj b/src/ShaderGen.App/ShaderGen.App.csproj index 047021b..f6c6f4c 100644 --- a/src/ShaderGen.App/ShaderGen.App.csproj +++ b/src/ShaderGen.App/ShaderGen.App.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.0 + netcoreapp2.1 diff --git a/src/ShaderGen.Primitives/ShaderGen.Primitives.csproj b/src/ShaderGen.Primitives/ShaderGen.Primitives.csproj index 9742679..8eb4be1 100644 --- a/src/ShaderGen.Primitives/ShaderGen.Primitives.csproj +++ b/src/ShaderGen.Primitives/ShaderGen.Primitives.csproj @@ -1,12 +1,12 @@ - netstandard2.0 ShaderGen ShaderGen.Primitives C# attributes and primitives for generating shader code via ShaderGen. Shader GLSL HLSL SPIR-V Graphics OpenGL Vulkan Direct3D Game + netstandard2.0;netcoreapp2.1 diff --git a/src/ShaderGen.Tests/ShaderGen.Tests.csproj b/src/ShaderGen.Tests/ShaderGen.Tests.csproj index f99d930..7221169 100644 --- a/src/ShaderGen.Tests/ShaderGen.Tests.csproj +++ b/src/ShaderGen.Tests/ShaderGen.Tests.csproj @@ -1,9 +1,9 @@ - netcoreapp2.0 false Program + netcoreapp2.1 @@ -15,18 +15,18 @@ - - - - - - - + + + + + + + - - - + + + diff --git a/src/ShaderGen.Tests/ShaderResourceTests.cs b/src/ShaderGen.Tests/ShaderResourceTests.cs index 9591a45..c79a12a 100644 --- a/src/ShaderGen.Tests/ShaderResourceTests.cs +++ b/src/ShaderGen.Tests/ShaderResourceTests.cs @@ -12,26 +12,12 @@ public static void ReferenceTypeField_ThrowsShaderGenerationException() Compilation compilation = TestUtil.GetCompilation(); foreach (LanguageBackend backend in TestUtil.GetAllBackends(compilation)) { - ShaderGenerator sg = new ShaderGenerator(compilation, backend, "ShaderGen.Tests.ReferenceTypeField.VS"); + ShaderGenerator sg = new ShaderGenerator(compilation, backend, "TestShaders.ReferenceTypeField.VS"); Assert.Throws(() => sg.GenerateShaders()); } } } - class ReferenceTypeField - { -#pragma warning disable 0649 - public object ReferenceField; -#pragma warning restore 0649 - - [VertexShader] - public Position4Texture2 VS(PositionTexture input) - { - Position4Texture2 output; - output.Position = new System.Numerics.Vector4(input.Position, 1); - output.TextureCoord = input.TextureCoord; - return output; - } - } + } diff --git a/src/ShaderGen.Tests/ShaderSetDiscovererTests.cs b/src/ShaderGen.Tests/ShaderSetDiscovererTests.cs index a1a3e8f..1445365 100644 --- a/src/ShaderGen.Tests/ShaderSetDiscovererTests.cs +++ b/src/ShaderGen.Tests/ShaderSetDiscovererTests.cs @@ -23,9 +23,11 @@ public static void ShaderSetAutoDiscovery() ShaderGenerator sg = new ShaderGenerator(compilation, backend); ShaderGenerationResult generationResult = sg.GenerateShaders(); IReadOnlyList hlslSets = generationResult.GetOutput(backend); - Assert.Equal(4, hlslSets.Count); + Assert.Equal(2, hlslSets.Count); // Was 4, not sure how to count these. GeneratedShaderSet set = hlslSets[0]; - Assert.Equal("VertexAndFragment", set.Name); + + //Updated to new naming convention + Assert.Equal(set.VertexFunction.DeclaringType + "." + set.VertexFunction.Name + "+" + set.FragmentFunction.DeclaringType + "." + set.FragmentFunction.Name, set.Name); CompileResult result = toolChain.Compile(set.VertexShaderCode, Stage.Vertex, "VS"); Assert.False(result.HasError, result.ToString()); diff --git a/src/ShaderGen.Tests/TestAssets/MultipleResourceSets.cs b/src/ShaderGen.Tests/TestAssets/MultipleResourceSets.cs index 643df25..3170a96 100644 --- a/src/ShaderGen.Tests/TestAssets/MultipleResourceSets.cs +++ b/src/ShaderGen.Tests/TestAssets/MultipleResourceSets.cs @@ -4,7 +4,7 @@ namespace TestShaders { - internal class MultipleResourceSets + public class MultipleResourceSets { #pragma warning disable 0649 public Matrix4x4 NoAttributeMatrix; // 0 diff --git a/src/ShaderGen.Tests/TestAssets/PartialClassShader/PartialVertex1.cs b/src/ShaderGen.Tests/TestAssets/PartialClassShader/PartialVertex1.cs index 2e8a5b6..84590ef 100644 --- a/src/ShaderGen.Tests/TestAssets/PartialClassShader/PartialVertex1.cs +++ b/src/ShaderGen.Tests/TestAssets/PartialClassShader/PartialVertex1.cs @@ -5,7 +5,7 @@ namespace TestShaders { public partial class PartialVertex { - struct FragmentInput + public struct FragmentInput { [VertexSemantic(SemanticType.SystemPosition)] public Vector4 Position; [VertexSemantic(SemanticType.Color)] public Vector4 Color; @@ -14,7 +14,7 @@ struct FragmentInput public SamplerResource Sampler; [VertexShader] - FragmentInput VertexShaderFunc(VertexInput input) + public FragmentInput VertexShaderFunc(VertexInput input) { FragmentInput output; output.Position = new Vector4(input.Position, 1); diff --git a/src/ShaderGen.Tests/TestAssets/PointLightInfoStructs.cs b/src/ShaderGen.Tests/TestAssets/PointLightInfoStructs.cs index fb52c9e..8a001c7 100644 --- a/src/ShaderGen.Tests/TestAssets/PointLightInfoStructs.cs +++ b/src/ShaderGen.Tests/TestAssets/PointLightInfoStructs.cs @@ -10,7 +10,7 @@ public class PointLightTestShaders public const int MyOtherConst = 20; [VertexShader] - SystemPosition4 VS(Position4 input) + public SystemPosition4 VS(Position4 input) { const int MyConst = 10; diff --git a/src/ShaderGen.Tests/TestAssets/ReferenceTypeField.cs b/src/ShaderGen.Tests/TestAssets/ReferenceTypeField.cs new file mode 100644 index 0000000..d96f097 --- /dev/null +++ b/src/ShaderGen.Tests/TestAssets/ReferenceTypeField.cs @@ -0,0 +1,20 @@ +using ShaderGen; + +namespace TestShaders +{ + public class ReferenceTypeField + { +#pragma warning disable 0649 + public object ReferenceField; +#pragma warning restore 0649 + + [VertexShader] + public Position4Texture2 VS(PositionTexture input) + { + Position4Texture2 output; + output.Position = new System.Numerics.Vector4(input.Position, 1); + output.TextureCoord = input.TextureCoord; + return output; + } + } +} \ No newline at end of file diff --git a/src/ShaderGen.Tests/TestAssets/References.txt b/src/ShaderGen.Tests/TestAssets/References.txt index d550a6a..2c88460 100644 --- a/src/ShaderGen.Tests/TestAssets/References.txt +++ b/src/ShaderGen.Tests/TestAssets/References.txt @@ -1,6 +1,6 @@ {appcontextbasedirectory}/ShaderGen.Primitives.dll -{nupkgdir}/microsoft.codeanalysis.csharp/2.3.2/lib/netstandard1.3/Microsoft.CodeAnalysis.CSharp.dll -{nupkgdir}/microsoft.codeanalysis.common/2.3.2/lib/netstandard1.3/Microsoft.CodeAnalysis.dll +{nupkgdir}/microsoft.codeanalysis.csharp/2.8.0/lib/netstandard1.3/Microsoft.CodeAnalysis.CSharp.dll +{nupkgdir}/microsoft.codeanalysis.common/2.8.0/lib/netstandard1.3/Microsoft.CodeAnalysis.dll {nupkgdir}/netstandard.library/2.0.0/build/netstandard2.0/ref/Microsoft.Win32.Primitives.dll {nupkgdir}/netstandard.library/2.0.0/build/netstandard2.0/ref/mscorlib.dll {nupkgdir}/netstandard.library/2.0.0/build/netstandard2.0/ref/netstandard.dll diff --git a/src/ShaderGen.Tests/TestAssets/TextureSamplerFragment.cs b/src/ShaderGen.Tests/TestAssets/TextureSamplerFragment.cs index 1628b8e..4c8c8f9 100644 --- a/src/ShaderGen.Tests/TestAssets/TextureSamplerFragment.cs +++ b/src/ShaderGen.Tests/TestAssets/TextureSamplerFragment.cs @@ -31,7 +31,7 @@ public Vector4 FS(FragmentInput input) return Sample(Tex2D, Sampler, input.TextureCoordinate); } - private Vector4 SampleTexture(Texture2DResource myTexture, SamplerResource mySampler) + public Vector4 SampleTexture(Texture2DResource myTexture, SamplerResource mySampler) { return Sample(myTexture, mySampler, Vector2.Zero); } diff --git a/src/ShaderGen.Tests/TestAssets/UsedResourcesShaders.cs b/src/ShaderGen.Tests/TestAssets/UsedResourcesShaders.cs index dd06236..cbfa6d3 100644 --- a/src/ShaderGen.Tests/TestAssets/UsedResourcesShaders.cs +++ b/src/ShaderGen.Tests/TestAssets/UsedResourcesShaders.cs @@ -18,7 +18,7 @@ public class UsedResourcesShaders public Matrix4x4 FS_M2_Indirect; [VertexShader] - SystemPosition4 VS(Position4 input) + public SystemPosition4 VS(Position4 input) { Vector2 v2 = new Vector2(VS_M0.M11, VS_M1.M22); Vector4 v4 = Sample(VS_T0, VS_S0, v2); @@ -29,14 +29,14 @@ SystemPosition4 VS(Position4 input) } [FragmentShader] - Vector4 FS(SystemPosition4 input) + public Vector4 FS(SystemPosition4 input) { Vector2 v2 = new Vector2(FS_M0.M11, FS_M1.M22); v2.X += GetIndirectOffset(); return Sample(FS_T0, FS_S0, v2); } - private float GetIndirectOffset() + public float GetIndirectOffset() { return FS_M2_Indirect.M11; } diff --git a/src/ShaderGen.Tests/TestAssets/VeldridShaders/ForwardMtlCombined.cs b/src/ShaderGen.Tests/TestAssets/VeldridShaders/ForwardMtlCombined.cs index 3591d25..b34b7be 100644 --- a/src/ShaderGen.Tests/TestAssets/VeldridShaders/ForwardMtlCombined.cs +++ b/src/ShaderGen.Tests/TestAssets/VeldridShaders/ForwardMtlCombined.cs @@ -15,7 +15,7 @@ public class ForwardMtlCombined public Matrix4x4 LightView; public LightInfoBuffer LightInfo; public CameraInfoBuffer CameraInfo; - public PointLightsBuffer PointLights; + public PointLightsBuffer LightBuffer; public MaterialPropertiesBuffer MaterialProperties; public Texture2DResource SurfaceTexture; public SamplerResource RegularSampler; @@ -53,7 +53,7 @@ public struct PointLightsBuffer public float _padding0; public float _padding1; public float _padding2; - [ArraySize(4)] public PointLightInfo[] PointLights; + [ArraySize(4)] public PointLightInfo[] ActivePointLights; } public struct MaterialPropertiesBuffer @@ -118,9 +118,9 @@ public Vector4 FS(PixelInput input) Vector4 pointDiffuse = new Vector4(0, 0, 0, 1); Vector4 pointSpec = new Vector4(0, 0, 0, 1); - for (int i = 0; i < PointLights.NumActiveLights; i++) + for (int i = 0; i < LightBuffer.NumActiveLights; i++) { - PointLightInfo pli = PointLights.PointLights[i]; + PointLightInfo pli = LightBuffer.ActivePointLights[i]; Vector3 lightDir = Vector3.Normalize(pli.Position - input.Position_WorldSpace); float intensity = Saturate(Vector3.Dot(input.Normal, lightDir)); float lightDistance = Vector3.Distance(pli.Position, input.Position_WorldSpace); @@ -200,7 +200,7 @@ public Vector4 FS(PixelInput input) + (diffuseFactor * surfaceColor) + pointDiffuse + pointSpec, surfaceColor.X); } - Vector4 WithAlpha(Vector4 baseColor, float alpha) + public Vector4 WithAlpha(Vector4 baseColor, float alpha) { return new Vector4(baseColor.XYZ(), alpha); } diff --git a/src/ShaderGen/ShaderGen.csproj b/src/ShaderGen/ShaderGen.csproj index ac369da..02102bc 100644 --- a/src/ShaderGen/ShaderGen.csproj +++ b/src/ShaderGen/ShaderGen.csproj @@ -1,13 +1,13 @@  - netstandard2.0 ShaderGen Translates C# code to HLSL and GLSL shader code. Shader GLSL HLSL SPIR-V Graphics OpenGL Vulkan Direct3D Game + netstandard2.0;netcoreapp2.1 - + diff --git a/src/ShaderGen/ShaderGenerator.cs b/src/ShaderGen/ShaderGenerator.cs index 31edfe2..f1c8d41 100644 --- a/src/ShaderGen/ShaderGenerator.cs +++ b/src/ShaderGen/ShaderGenerator.cs @@ -67,8 +67,21 @@ public ShaderGenerator( ssd.Visit(tree.GetRoot()); } - _shaderSets = ssd.GetShaderSets(); - return; + if (_shaderSets.Count > 0) + { + _shaderSets = ssd.GetShaderSets(); + return; + } + + if (string.IsNullOrEmpty(ssd.DanglingVS) && string.IsNullOrEmpty(ssd.DanglingFS) && string.IsNullOrEmpty(ssd.DanglingCS)) + { + throw new ShaderGenerationException("No shader sets discovered and no entry points specified"); + } + + vertexFunctionName = ssd.DanglingVS; + fragmentFunctionName = ssd.DanglingFS; + computeFunctionName = ssd.DanglingCS; + } // We've explicitly specified shaders so find them directly. diff --git a/src/ShaderGen/ShaderMethodVisitor.cs b/src/ShaderGen/ShaderMethodVisitor.cs index 55e872f..f23751f 100644 --- a/src/ShaderGen/ShaderMethodVisitor.cs +++ b/src/ShaderGen/ShaderMethodVisitor.cs @@ -17,6 +17,12 @@ public partial class ShaderMethodVisitor : CSharpSyntaxVisitor protected readonly LanguageBackend _backend; protected readonly ShaderFunction _shaderFunction; private string _containingTypeName; + private MethodDeclarationSyntax _declaration; + private ClassDeclarationSyntax _classDeclaration; + private SyntaxTree _functionTree; + private SemanticModel _functionTreeModel; + private IMethodSymbol _methodSymbol; + private INamedTypeSymbol _classSymbol; private HashSet _resourcesUsed = new HashSet(); public ShaderMethodVisitor( @@ -29,12 +35,23 @@ public ShaderMethodVisitor( _setName = setName; _shaderFunction = shaderFunction; _backend = backend; + _classDeclaration = null; } private SemanticModel GetModel(SyntaxNode node) => _compilation.GetSemanticModel(node.SyntaxTree); + public MethodProcessResult VisitFunction(BaseMethodDeclarationSyntax node) { + if (node is MethodDeclarationSyntax methodDec) + { + _declaration = methodDec; + _functionTree = _declaration.SyntaxTree; + _functionTreeModel = _compilation.GetSemanticModel(_functionTree); + _classDeclaration = methodDec.Parent as ClassDeclarationSyntax; + _methodSymbol = _functionTreeModel.GetDeclaredSymbol(_declaration); + _classSymbol = _functionTreeModel.GetDeclaredSymbol(_classDeclaration); + } _containingTypeName = Utilities.GetFullNestedTypePrefix((SyntaxNode)node.Body ?? node.ExpressionBody, out bool _); StringBuilder sb = new StringBuilder(); string blockResult; @@ -465,6 +482,7 @@ private string GetDiscardedVariableName(ISymbol symbol) return _backend.CorrectIdentifier($"_shadergen_discard_{mappedType}"); } + public override string VisitIdentifierName(IdentifierNameSyntax node) { SymbolInfo symbolInfo = GetModel(node).GetSymbolInfo(node); @@ -474,6 +492,32 @@ public override string VisitIdentifierName(IdentifierNameSyntax node) return GetDiscardedVariableName(symbol); } string containingTypeName = Utilities.GetFullName(symbol.ContainingType); + + // + //Check to see if this containing type is the same as the function + //Why, I'm not totally sure, but the existing check was missing base types + //Which limited inheritance + // + var containedByFunctionClass = false; + + var testType = symbol.ContainingType; + while (testType != null) + { + var classSymbol = _classSymbol; + while (classSymbol != null) + { + if (Utilities.GetFullName(testType) == Utilities.GetFullName(classSymbol)) + { + containedByFunctionClass = true; + break; + } + classSymbol = classSymbol.BaseType; + } + + testType = testType.ContainingType; + } + + if (containingTypeName == "ShaderGen.ShaderBuiltins") { TryRecognizeBuiltInVariable(symbolInfo); @@ -483,7 +527,7 @@ public override string VisitIdentifierName(IdentifierNameSyntax node) // TODO: Share code to format constant values. return string.Format(CultureInfo.InvariantCulture, "{0}", fs.ConstantValue); } - else if (symbol.Kind == SymbolKind.Field && containingTypeName == _containingTypeName) + else if (symbol.Kind == SymbolKind.Field && containedByFunctionClass ) { string symbolName = symbol.Name; ResourceDefinition referencedResource = _backend.GetContext(_setName).Resources.SingleOrDefault(rd => rd.Name == symbolName); @@ -509,7 +553,11 @@ public override string VisitIdentifierName(IdentifierNameSyntax node) // TODO: Share code to format constant values. return string.Format(CultureInfo.InvariantCulture, "{0}", ls.ConstantValue); } - + else if (symbol.Kind == SymbolKind.Field && !containedByFunctionClass && !containingTypeName.Contains("Input") && !symbol.Name.Contains("Position") && !containingTypeName.Contains("System")) + { + //Filter for edge cases + //throw new ShaderGenerationException("Symbol " + symbol.Name + " is not contained in " + _classSymbol.Name); + } string mapped = _backend.CSharpToShaderIdentifierName(symbolInfo); return _backend.CorrectIdentifier(mapped); } diff --git a/src/ShaderGen/ShaderSetDiscoverer.cs b/src/ShaderGen/ShaderSetDiscoverer.cs index e9e1d2a..73131da 100644 --- a/src/ShaderGen/ShaderSetDiscoverer.cs +++ b/src/ShaderGen/ShaderSetDiscoverer.cs @@ -1,6 +1,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using System.Collections.Generic; +using System.Linq; namespace ShaderGen { @@ -8,6 +9,9 @@ internal class ShaderSetDiscoverer : CSharpSyntaxWalker { private readonly HashSet _discoveredNames = new HashSet(); private readonly List _shaderSets = new List(); + public string DanglingVS { get; set; } + public string DanglingFS { get; set; } + public string DanglingCS { get; set; } public override void VisitAttribute(AttributeSyntax node) { // TODO: Only look at assembly-level attributes. @@ -56,6 +60,39 @@ public override void VisitAttribute(AttributeSyntax node) vsName, fsName)); } + else if (node.Name.ToFullString().Contains("VertexShader")) + { + var methodDeclaration = ((MethodDeclarationSyntax) node.Ancestors().First(x => x is MethodDeclarationSyntax)); + var classDeclaration = ((ClassDeclarationSyntax) node.Ancestors().First(x => x is ClassDeclarationSyntax)); + DanglingVS = classDeclaration?.Identifier.ValueText + "." + methodDeclaration?.Identifier.ValueText; + if (classDeclaration?.Parent is NamespaceDeclarationSyntax namespaceDeclaration) + { + //Likely a better way of doing this + DanglingVS = namespaceDeclaration.Name + "." + DanglingVS; + } + } + else if (node.Name.ToFullString().Contains("FragmentShader")) + { + var methodDeclaration = ((MethodDeclarationSyntax) node.Ancestors().First(x => x is MethodDeclarationSyntax)); + var classDeclaration = ((ClassDeclarationSyntax) node.Ancestors().First(x => x is ClassDeclarationSyntax)); + DanglingFS = classDeclaration?.Identifier.ValueText + "." + methodDeclaration?.Identifier.ValueText; + if (classDeclaration?.Parent is NamespaceDeclarationSyntax namespaceDeclaration) + { + //Likely a better way of doing this + DanglingFS = namespaceDeclaration.Name + "." + DanglingFS; + } + } + else if (node.Name.ToFullString().Contains("ComputeShader")) + { + var methodDeclaration = ((MethodDeclarationSyntax) node.Ancestors().First(x => x is MethodDeclarationSyntax)); + var classDeclaration = ((ClassDeclarationSyntax) node.Ancestors().First(x => x is ClassDeclarationSyntax)); + DanglingCS = classDeclaration?.Identifier.ValueText + "." + methodDeclaration?.Identifier.ValueText; + if (classDeclaration?.Parent is NamespaceDeclarationSyntax namespaceDeclaration) + { + //Likely a better way of doing this + DanglingCS = namespaceDeclaration.Name + "." + DanglingCS; + } + } } private string GetStringParam(AttributeSyntax node, int index)