mellinoe / ShaderGen

Proof-of-concept library for generating HLSL, GLSL, and Metal shader code from C#,
MIT License
497 stars 56 forks source link

Field name collision when classes in the same file. #62

Open thargy opened 6 years ago

thargy commented 6 years ago

In an attempt to better understand ShaderGen, I've had a go at converting the ComputeParticles shaders from the Veldrid-Samples project. After lots of trial and error, I got to the following:

using System.Numerics;
using ShaderGen;
using static ShaderGen.ShaderBuiltins;

[assembly: ShaderSet("Particle", "Apocraphy.Shaders.Particle.VS", "Apocraphy.Shaders.Particle.FS")]
[assembly: ComputeShaderSet("ParticleCompute", "Apocraphy.Shaders.ParticleCompute.CS")]
namespace Apocraphy.Shaders
{
    public class ParticleCompute
    {
        public RWStructuredBuffer<ParticleInfo> Particles;
        public ScreenSize ScreenSize;

        [ComputeShader(1, 1, 1)]
        public void CS()
        {
            uint index = DispatchThreadID.X;
            if (index > 1024)
                return;

            ParticleInfo particleInfo = Particles[index];
            Vector2 pos = particleInfo.Position;
            Vector2 vel = particleInfo.Velocity;

            Vector2 newPos = pos + vel;
            Vector2 newVel = vel;
            if (newPos.X > ScreenSize.Width)
            {
                newPos.X -= newPos.X - ScreenSize.Width;
                newVel.X *= -1;
            }
            if (newPos.X < 0)
            {
                newPos.X *= -1;
                newVel.X *= -1;
            }
            if (newPos.Y > ScreenSize.Height)
            {
                newPos.Y -= newPos.Y - ScreenSize.Height;
                newVel.Y *= -1;
            }
            if (newPos.Y < 0)
            {
                newPos.Y = -newPos.Y;
                newVel.Y *= -1;
            }

            particleInfo.Position = newPos;
            particleInfo.Velocity = newVel;
            Particles[index] = particleInfo;
        }

    }

    public class Particle
    {
        public StructuredBuffer<ParticleInfo> Particles;
        public ScreenSize ScreenSize;

        [VertexShader]
        public FragmentInput VS()
        {
            ParticleInfo input = Particles[VertexID];
            FragmentInput output;
            output.Position.X = 2 * (input.Position.X / ScreenSize.Width - 0.5f);
            output.Position.Y = 2 * (input.Position.Y / ScreenSize.Height - 0.5f);
            output.Position.Z = 0f;
            output.Position.W = 1f;
            output.Color = input.Color;
            return output;
        }

        [FragmentShader]
        public Vector4 FS(FragmentInput input)
        {
            return input.Color;
        }

    }

    public struct ScreenSize
    {
        public float Width;
        public float Height;

#pragma warning disable 169
        private Vector2 _padding;
#pragma warning restore 169
    }

    public struct FragmentInput
    {
        [SystemPositionSemantic]
        public Vector4 Position;

        [ColorSemantic]
        public Vector4 Color;
    }

    public struct ParticleInfo
    {
        [PositionSemantic]
        public Vector2 Position;

        [PositionSemantic]
        public Vector2 Velocity;

        [ColorSemantic]
        public Vector4 Color;
    };
}

However, this throws the following error on build:

------ Rebuild All started: Project: Apocraphy, Configuration: Debug Any CPU ------ An error was encountered while generating shader code: System.InvalidOperationException: Sequence contains more than one matching element at System.Linq.Enumerable.Single[TSource](IEnumerable1 source, Func2 predicate) at ShaderGen.ShaderMethodVisitor.VisitIdentifierName(IdentifierNameSyntax node) in C:\projects\shadergen\src\ShaderGen\ShaderMethodVisitor.cs:line 347 at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor1.Visit(SyntaxNode node) at ShaderGen.ShaderMethodVisitor.VisitElementAccessExpression(ElementAccessExpressionSyntax node) in C:\projects\shadergen\src\ShaderGen\ShaderMethodVisitor.cs:line 520 at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor1.Visit(SyntaxNode node) at ShaderGen.ShaderMethodVisitor.VisitVariableDeclaration(VariableDeclarationSyntax node) in C:\projects\shadergen\src\ShaderGen\ShaderMethodVisitor.cs:line 505 at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor1.Visit(SyntaxNode node) at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor1.Visit(SyntaxNode node) at ShaderGen.ShaderMethodVisitor.VisitBlock(BlockSyntax node) in C:\projects\shadergen\src\ShaderGen\ShaderMethodVisitor.cs:line 73 at ShaderGen.ShaderMethodVisitor.VisitFunction(MethodDeclarationSyntax node) in C:\projects\shadergen\src\ShaderGen\ShaderMethodVisitor.cs:line 38 at ShaderGen.Hlsl.HlslBackend.GenerateFullTextCore(String setName, ShaderFunction function) in C:\projects\shadergen\src\ShaderGen\Hlsl\HlslBackend.cs:line 182 at ShaderGen.LanguageBackend.ProcessEntryFunction(String setName, ShaderFunction function) in C:\projects\shadergen\src\ShaderGen\LanguageBackend.cs:line 148 at ShaderGen.LanguageBackend.GetShaderModel(String setName) in C:\projects\shadergen\src\ShaderGen\LanguageBackend.cs:line 78 at ShaderGen.ShaderGenerator.GenerateShaders(ShaderSetInfo ss, ShaderGenerationResult result) in C:\projects\shadergen\src\ShaderGen\ShaderGenerator.cs:line 198 at ShaderGen.ShaderGenerator.GenerateShaders() in C:\projects\shadergen\src\ShaderGen\ShaderGenerator.cs:line 144 at ShaderGen.App.Program.Main(String[] args) in C:\projects\shadergen\src\ShaderGen.App\Program.cs:line 167

C:\Users\Craig.nuget\packages\shadergen.build\1.2.0-gf5792ed443\build\ShaderGen.targets(35,5): error MSB3073: The command "dotnet C:\Users\Craig.nuget\packages\shadergen.build\1.2.0-gf5792ed443\build\ShaderGen.App.dll --ref " obj\Debug\netcoreapp2.0_sgreferences.txt " --src " obj\Debug\netcoreapp2.0_sgsources.txt " --out " obj\Shaders " --genlist "obj\Debug\netcoreapp2.0_sggeneratedfiles.txt"" exited with code -1. Done building project "Apocraphy.csproj" -- FAILED. ------ Rebuild All started: Project: Apocraphy.App, Configuration: Debug Any CPU ------

Which refers to: https://github.com/mellinoe/ShaderGen/blob/347b0078c91a1e28f20149a20bc30e301aa5e393/src/ShaderGen/ShaderMethodVisitor.cs#L479

Moving the ParticleCompute class into it's own file fixes the issue. I'm raising as a bug as classes can be created in the same file (even if generally considered bad practice).

mellinoe commented 6 years ago

I recently came across a similar issue. There are some parts of the code which should be comparing fully-qualified field / member names. I don't think it will be terribly hard to fix, and we should be able to add a simple test for it.