From 0759ca9f2e2517dbc0e369fa07f2845369fca606 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 23 Sep 2023 18:19:49 +0200 Subject: [PATCH 01/20] Add D2DGeneratedShaderMarshallerAttribute type --- .../Attributes/D2DCompileOptionsAttribute.cs | 2 -- .../D2DGeneratedShaderMarshallerAttribute.cs | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 src/ComputeSharp.D2D1/Attributes/D2DGeneratedShaderMarshallerAttribute.cs diff --git a/src/ComputeSharp.D2D1/Attributes/D2DCompileOptionsAttribute.cs b/src/ComputeSharp.D2D1/Attributes/D2DCompileOptionsAttribute.cs index a2ef6fee2..fe4568a05 100644 --- a/src/ComputeSharp.D2D1/Attributes/D2DCompileOptionsAttribute.cs +++ b/src/ComputeSharp.D2D1/Attributes/D2DCompileOptionsAttribute.cs @@ -15,8 +15,6 @@ namespace ComputeSharp.D2D1; /// /// /// -/// -/// /// Note that the is always enabled automatically and does not need to be /// specified. This option is mandatory, as the generated code to load the constant buffer from a shader assumes the layout /// for matrix types is row major. For the same reason, using is not diff --git a/src/ComputeSharp.D2D1/Attributes/D2DGeneratedShaderMarshallerAttribute.cs b/src/ComputeSharp.D2D1/Attributes/D2DGeneratedShaderMarshallerAttribute.cs new file mode 100644 index 000000000..7240d9f83 --- /dev/null +++ b/src/ComputeSharp.D2D1/Attributes/D2DGeneratedShaderMarshallerAttribute.cs @@ -0,0 +1,24 @@ +using System; + +namespace ComputeSharp.D2D1; + +/// +/// An attribute that indicates that a given D2D1 shader should have its associated marshalling code being generated. +/// +/// This attribute can be used on shader types that are declared as : +/// +/// [D2DGeneratedShaderMarshaller] +/// partial struct MyShader : ID2D1PixelShader +/// { +/// } +/// +/// +/// +/// When a shader is annotated with , the source generator will also add +/// to its implemented interfaces, and implement its APIs automatically. +/// +/// +[AttributeUsage(AttributeTargets.Struct, AllowMultiple = false)] +public sealed class D2DGeneratedShaderMarshallerAttribute : Attribute +{ +} \ No newline at end of file From 6b9895ed7442b4165e27adc8f14f51db0824f681 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 23 Sep 2023 18:52:55 +0200 Subject: [PATCH 02/20] Switch D2D1 generator to use ForAttributeWithMetadataName --- .../ID2D1ShaderGenerator.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs index 810264f2e..3b10c6fc2 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs @@ -5,7 +5,6 @@ using ComputeSharp.SourceGeneration.Helpers; using ComputeSharp.SourceGeneration.Models; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace ComputeSharp.D2D1.SourceGenerators; @@ -22,7 +21,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Discover all shader types and extract all the necessary info from each of them IncrementalValuesProvider shaderInfo = context.SyntaxProvider - .CreateSyntaxProvider( + .ForAttributeWithMetadataName( + "ComputeSharp.D2D1.D2DGeneratedShaderMarshallerAttribute", static (node, _) => node.IsTypeDeclarationWithOrPotentiallyWithBaseTypes(), static (context, token) => { @@ -32,14 +32,14 @@ public void Initialize(IncrementalGeneratorInitializationContext context) return default; } - StructDeclarationSyntax typeDeclaration = (StructDeclarationSyntax)context.Node; - // If the type symbol doesn't have at least one interface, it can't possibly be a shader type - if (context.SemanticModel.GetDeclaredSymbol(typeDeclaration, token) is not INamedTypeSymbol { AllInterfaces.Length: > 0 } typeSymbol) + if (context.TargetSymbol is not INamedTypeSymbol { AllInterfaces.Length: > 0 } typeSymbol) { return default; } + StructDeclarationSyntax typeDeclaration = (StructDeclarationSyntax)context.TargetNode; + // Check that the shader implements the ID2D1PixelShader interface if (!IsD2D1PixelShaderType(typeSymbol, context.SemanticModel.Compilation)) { From 4d7f288364ffe9666726590f8f8e518864484b6d Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 23 Sep 2023 18:53:04 +0200 Subject: [PATCH 03/20] Add [D2DGeneratedShaderMarshaller] to all shader types --- .../ColorfulInfinity.cs | 1 + .../ContouredLayers.cs | 1 + .../FractalTiling.cs | 1 + .../HelloWorld.cs | 1 + .../MengerJourney.cs | 1 + .../Octagrams.cs | 1 + .../ProteanClouds.cs | 1 + .../PyramidPattern.cs | 1 + .../TerracedHills.cs | 1 + .../TriangleGridContouring.cs | 1 + .../TwoTiledTruchet.cs | 1 + .../D2D1PixelShaderTests.cs | 4 ++++ .../D2D1EffectRegistrationDataTests.cs | 3 +++ .../D2D1PixelShaderEffectTests.cs | 8 ++++++++ .../D2D1PixelShaderTests.cs | 18 ++++++++++++++++++ .../D2D1ReflectionServicesTests.cs | 2 ++ .../D2D1ResourceTextureManagerTests.cs | 7 +++++++ ...nitializedFieldDiagnosticSuppressorTests.cs | 1 + .../D2D1TransformMapperTests.cs | 2 ++ .../Effects/BokehBlurEffect.cs | 4 ++++ .../Effects/CheckerboardClipEffect.cs | 1 + .../Effects/InvertEffect.cs | 1 + .../Effects/InvertWithThresholdEffect.cs | 1 + .../Effects/PixelateEffect.cs | 2 ++ .../Effects/ZonePlateEffect.cs | 1 + .../CanvasEffectTests.cs | 1 + .../PixelShaderEffectTests.cs | 5 +++++ 27 files changed, 72 insertions(+) diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ColorfulInfinity.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ColorfulInfinity.cs index 94ac59d22..aebb80fb0 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ColorfulInfinity.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ColorfulInfinity.cs @@ -11,6 +11,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct ColorfulInfinity : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ContouredLayers.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ContouredLayers.cs index 63b01ac66..1a7fa26c2 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ContouredLayers.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ContouredLayers.cs @@ -10,6 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct ContouredLayers : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/FractalTiling.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/FractalTiling.cs index db30a226e..fab955e8f 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/FractalTiling.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/FractalTiling.cs @@ -11,6 +11,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct FractalTiling : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/HelloWorld.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/HelloWorld.cs index 497277206..2332ba771 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/HelloWorld.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/HelloWorld.cs @@ -9,6 +9,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct HelloWorld : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/MengerJourney.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/MengerJourney.cs index ff9758216..410b302a8 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/MengerJourney.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/MengerJourney.cs @@ -10,6 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct MengerJourney : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/Octagrams.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/Octagrams.cs index aa16a6bba..be787a781 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/Octagrams.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/Octagrams.cs @@ -10,6 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct Octagrams : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ProteanClouds.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ProteanClouds.cs index 762bf8106..068914f4e 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ProteanClouds.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ProteanClouds.cs @@ -11,6 +11,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct ProteanClouds : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/PyramidPattern.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/PyramidPattern.cs index a272f95ce..4564cb0c5 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/PyramidPattern.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/PyramidPattern.cs @@ -11,6 +11,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct PyramidPattern : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TerracedHills.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TerracedHills.cs index 6669651c7..951a49710 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TerracedHills.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TerracedHills.cs @@ -10,6 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct TerracedHills : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TriangleGridContouring.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TriangleGridContouring.cs index 970bd7757..24bec4686 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TriangleGridContouring.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TriangleGridContouring.cs @@ -10,6 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct TriangleGridContouring : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TwoTiledTruchet.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TwoTiledTruchet.cs index 00c763740..2deb4d94e 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TwoTiledTruchet.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TwoTiledTruchet.cs @@ -10,6 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct TwoTiledTruchet : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests.AssemblyLevelAttributes/D2D1PixelShaderTests.cs b/tests/ComputeSharp.D2D1.Tests.AssemblyLevelAttributes/D2D1PixelShaderTests.cs index 566facc4a..6e912aa82 100644 --- a/tests/ComputeSharp.D2D1.Tests.AssemblyLevelAttributes/D2D1PixelShaderTests.cs +++ b/tests/ComputeSharp.D2D1.Tests.AssemblyLevelAttributes/D2D1PixelShaderTests.cs @@ -49,6 +49,7 @@ public unsafe void ShaderWithAssemblyLevelAttributes() [D2DInputSimple(0)] [D2DInputSimple(1)] [D2DInputSimple(2)] + [D2DGeneratedShaderMarshaller] private readonly partial struct ShaderWithNoCompileAttributes : ID2D1PixelShader { public float4 Execute() @@ -94,6 +95,7 @@ public unsafe void ShaderWithAssemblyLevelAttributesAndOverriddenProfile() [D2DInputSimple(1)] [D2DInputSimple(2)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] + [D2DGeneratedShaderMarshaller] private readonly partial struct ShaderWithOverriddenProfile : ID2D1PixelShader { public float4 Execute() @@ -139,6 +141,7 @@ public unsafe void ShaderWithAssemblyLevelAttributesAndOverriddenOptions() [D2DInputSimple(1)] [D2DInputSimple(2)] [D2DCompileOptions(D2D1CompileOptions.Debug | D2D1CompileOptions.AvoidFlowControl | D2D1CompileOptions.PartialPrecision)] + [D2DGeneratedShaderMarshaller] private readonly partial struct ShaderWithOverriddenOptions : ID2D1PixelShader { public float4 Execute() @@ -175,6 +178,7 @@ public unsafe void ShaderWithAssemblyLevelAttributesAndEverythingOverridden() [D2DInputSimple(2)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] [D2DCompileOptions(D2D1CompileOptions.Debug | D2D1CompileOptions.AvoidFlowControl | D2D1CompileOptions.PartialPrecision)] + [D2DGeneratedShaderMarshaller] private readonly partial struct ShaderWithOverriddenProfileAndOptions : ID2D1PixelShader { public float4 Execute() diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1EffectRegistrationDataTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1EffectRegistrationDataTests.cs index 176e03f16..562ee0920 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1EffectRegistrationDataTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1EffectRegistrationDataTests.cs @@ -51,6 +51,7 @@ public unsafe void EffectRegistrationData_Validate() [D2DInputCount(2)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private readonly partial struct TestRegistrationBlobShader : ID2D1PixelShader { @@ -96,6 +97,7 @@ public unsafe void EffectRegistrationData_WithCustomMetadata_Validate() [D2DEffectDescription("A test effect with some custom metadata")] [D2DEffectCategory("Test effects")] [D2DEffectAuthor("Bob Ross")] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private readonly partial struct TestRegistrationBlobWithCustomMetadataShader : ID2D1PixelShader { @@ -192,6 +194,7 @@ public unsafe void EffectRegistrationData_WithResourceTextures_Validate() } [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private readonly partial struct TestRegistrationBlobWithResourceTextures : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderEffectTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderEffectTests.cs index 7dd2fe164..8a0eee987 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderEffectTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderEffectTests.cs @@ -120,6 +120,7 @@ public unsafe void NullConstantBuffer_DrawImageFails() [D2DInputCount(0)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private partial struct NullConstantBufferShader : ID2D1PixelShader { @@ -151,6 +152,7 @@ public unsafe void GetValueSize_ConstantBuffer() [D2DInputCount(0)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private partial struct ConstantBufferSizeTestShader : ID2D1PixelShader { @@ -185,6 +187,7 @@ public unsafe void DefaultEffectId_MatchesValue() } [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] private partial struct ShaderWithDefaultEffectId : ID2D1PixelShader { public float4 Execute() @@ -194,6 +197,7 @@ public float4 Execute() } [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] private partial struct ShaderWithDefaultEffectId2 : ID2D1PixelShader { public float4 Execute() @@ -217,6 +221,7 @@ public unsafe void ExplicitEffectId_MatchesValue() [D2DInputCount(0)] [D2DEffectId("8E1F7F49-EF0D-4242-8912-08ADA36AB4EC")] + [D2DGeneratedShaderMarshaller] private partial struct ShaderWithExplicitEffectId : ID2D1PixelShader { public float4 Execute() @@ -235,6 +240,7 @@ public unsafe void DefaultEffectMetadata_MatchesValue() } [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] private partial struct ShaderWithDefaultEffectDisplayName : ID2D1PixelShader { public float4 Execute() @@ -254,6 +260,7 @@ public unsafe void ExplicitEffectMetadata1_MatchesValue() [D2DInputCount(0)] [D2DEffectDisplayName("Fancy blur")] + [D2DGeneratedShaderMarshaller] private partial struct ShaderWithExplicitEffectDisplayName1 : ID2D1PixelShader { public float4 Execute() @@ -276,6 +283,7 @@ public unsafe void ExplicitEffectMetadata2_MatchesValue() [D2DEffectDescription("A test effect with \nsome custom metadata")] [D2DEffectCategory("Test effects!")] [D2DEffectAuthor("Bob \r\nRoss")] + [D2DGeneratedShaderMarshaller] private partial struct ShaderWithExplicitEffectDisplayName2 : ID2D1PixelShader { public float4 Execute() diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderTests.cs index 4e146d0c0..d710f7a4a 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderTests.cs @@ -66,6 +66,7 @@ public void GetInputTypes_SameManager() [D2DInputComplex(3)] [D2DInputComplex(5)] [D2DInputSimple(6)] + [D2DGeneratedShaderMarshaller] partial struct ShaderWithMultipleInputs : ID2D1PixelShader { public Float4 Execute() @@ -93,6 +94,7 @@ public void GetOutputBufferChannelDepth() } [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] partial struct EmptyShader : ID2D1PixelShader { public Float4 Execute() @@ -103,6 +105,7 @@ public Float4 Execute() [D2DInputCount(0)] [D2DOutputBuffer(D2D1BufferPrecision.UInt16Normalized)] + [D2DGeneratedShaderMarshaller] partial struct OnlyBufferPrecisionShader : ID2D1PixelShader { public Float4 Execute() @@ -113,6 +116,7 @@ public Float4 Execute() [D2DInputCount(0)] [D2DOutputBuffer(D2D1ChannelDepth.Four)] + [D2DGeneratedShaderMarshaller] partial struct OnlyChannelDepthShader : ID2D1PixelShader { public Float4 Execute() @@ -123,6 +127,7 @@ public Float4 Execute() [D2DInputCount(0)] [D2DOutputBuffer(D2D1BufferPrecision.UInt8NormalizedSrgb, D2D1ChannelDepth.One)] + [D2DGeneratedShaderMarshaller] partial struct CustomBufferOutputShader : ID2D1PixelShader { public Float4 Execute() @@ -189,6 +194,7 @@ public void GetInputDescriptions_Custom() [D2DInputDescription(2, D2D1Filter.MinLinearMagPointMinLinear, LevelOfDetailCount = 4)] [D2DInputDescription(5, D2D1Filter.MinMagPointMipLinear)] [D2DInputDescription(6, D2D1Filter.MinPointMagMipLinear, LevelOfDetailCount = 3)] + [D2DGeneratedShaderMarshaller] partial struct ShaderWithInputDescriptions : ID2D1PixelShader { public Float4 Execute() @@ -249,6 +255,7 @@ public void GetResourceTextureCount_IsCorrect() [D2DInputComplex(1)] [D2DInputComplex(3)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] + [D2DGeneratedShaderMarshaller] [AutoConstructor] partial struct ShaderWithoutResourceTextures : ID2D1PixelShader { @@ -260,6 +267,7 @@ public Float4 Execute() [D2DInputCount(0)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] + [D2DGeneratedShaderMarshaller] [AutoConstructor] partial struct ShaderWithJustOneResourceTextures : ID2D1PixelShader { @@ -278,6 +286,7 @@ public Float4 Execute() [D2DInputComplex(1)] [D2DInputComplex(3)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] + [D2DGeneratedShaderMarshaller] [AutoConstructor] partial struct ShaderWithResourceTextures : ID2D1PixelShader { @@ -322,6 +331,7 @@ public void GetBytecode_FromDynamicBytecode() } [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] private readonly partial struct ShaderWithoutEmbeddedBytecode : ID2D1PixelShader { public float4 Execute() @@ -393,6 +403,7 @@ public void GetBytecode_FromEmbeddedBytecode_WithTargetProfileAndPackMatrixColum [D2DInputSimple(1)] [D2DInputSimple(2)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader40Level91)] + [D2DGeneratedShaderMarshaller] private readonly partial struct ShaderWithEmbeddedBytecode : ID2D1PixelShader { public float4 Execute() @@ -442,6 +453,7 @@ public void GetBytecode_FromEmbeddedBytecode_WithCompileOptions() [D2DInputSimple(2)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader40Level91)] [D2DCompileOptions(D2D1CompileOptions.IeeeStrictness | D2D1CompileOptions.OptimizationLevel2)] + [D2DGeneratedShaderMarshaller] private readonly partial struct ShaderWithEmbeddedBytecodeAndCompileOptions : ID2D1PixelShader { public float4 Execute() @@ -473,6 +485,7 @@ public void LoadBytecode_VerifyEffectiveValues_ExplicitShaderProfile() [D2DInputCount(1)] [D2DInputSimple(0)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader40Level91)] + [D2DGeneratedShaderMarshaller] private readonly partial struct SimpleShaderWithExplicitShaderProfileAndNoCompileOptions : ID2D1PixelShader { public float4 Execute() @@ -484,6 +497,7 @@ public float4 Execute() [D2DInputCount(1)] [D2DInputComplex(0)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader40Level91)] + [D2DGeneratedShaderMarshaller] private readonly partial struct ComplexShaderWithExplicitShaderProfileAndNoCompileOptions : ID2D1PixelShader { public float4 Execute() @@ -509,6 +523,7 @@ public void LoadBytecode_VerifyEffectiveValues_ExplicitCompileOptions() [D2DInputCount(1)] [D2DInputSimple(0)] [D2DCompileOptions(D2D1CompileOptions.OptimizationLevel2 | D2D1CompileOptions.IeeeStrictness)] + [D2DGeneratedShaderMarshaller] private readonly partial struct ShaderWithExplicitCompileOptionsAndNoShaderProfile : ID2D1PixelShader { public float4 Execute() @@ -557,6 +572,7 @@ public void GetConstantBuffer_Empty_Span() [D2DInputSimple(0)] [D2DInputDescription(0, D2D1Filter.MinMagMipPoint)] [D2DPixelOptions(D2D1PixelOptions.TrivialSampling)] + [D2DGeneratedShaderMarshaller] private readonly partial struct ShaderWithNoCapturedValues : ID2D1PixelShader { public float4 Execute() @@ -804,6 +820,7 @@ private static void ValidateShadersAreEqual(in ShaderWithScalarVectorAndMatrixTy } [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private readonly partial struct ShaderWithScalarVectorAndMatrixTypes : ID2D1PixelShader { @@ -896,6 +913,7 @@ public readonly partial struct FieldsContainer3 } [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private readonly partial struct ShaderWithScalarVectorAndMatrixTypesInNestedStructs : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1ReflectionServicesTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1ReflectionServicesTests.cs index fdafabd9a..31f2ef8ca 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1ReflectionServicesTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1ReflectionServicesTests.cs @@ -60,6 +60,7 @@ public void GetShaderInfo() [D2DInputComplex(2)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader41)] + [D2DGeneratedShaderMarshaller] private readonly partial struct ReflectedShader : ID2D1PixelShader { private readonly float2 offset; @@ -119,6 +120,7 @@ public void GetShaderInfoWithDoublePrecisionFeature() [D2DInputCount(1)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] + [D2DGeneratedShaderMarshaller] private readonly partial struct ReflectedShaderWithDoubleOperations : ID2D1PixelShader { private readonly double amount; diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureManagerTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureManagerTests.cs index ecd7dce1c..be8f5f88a 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureManagerTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureManagerTests.cs @@ -171,6 +171,7 @@ public unsafe void SingleThreadedFactory_AssigningRCWManagerFails() [D2DInputCount(0)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] private partial struct DummyShaderWithResourceTexture : ID2D1PixelShader { [D2DResourceTextureIndex(0)] @@ -459,6 +460,7 @@ public unsafe void LoadPixelsFromResourceTexture2D_AlternatingResourceTextureMan [D2DInputCount(0)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] private partial struct IndexFrom2DResourceTextureShader : ID2D1PixelShader { [D2DResourceTextureIndex(0)] @@ -533,6 +535,7 @@ public unsafe void LoadPixelsFromResourceTexture3D() [D2DInputCount(0)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private partial struct IndexFrom3DResourceTextureShader : ID2D1PixelShader { @@ -620,6 +623,7 @@ public unsafe void UpdateResourceTexture1D(int width, int startOffset, int updat [D2DInputCount(0)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private partial struct CopyFromResourceTexture1DShader : ID2D1PixelShader { @@ -717,6 +721,7 @@ public unsafe void UpdateResourceTexture2D( [D2DInputCount(0)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private partial struct CopyFromResourceTexture2DShader : ID2D1PixelShader { @@ -823,6 +828,7 @@ public unsafe void UpdateResourceTexture3D( [D2DInputCount(0)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private partial struct CopyFromResourceTexture3DShader : ID2D1PixelShader { @@ -868,6 +874,7 @@ public unsafe void NullResourceTexture_DrawImageFails() [D2DInputCount(0)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] private partial struct NullResourceTextureShader : ID2D1PixelShader { [D2DResourceTextureIndex(0)] diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureUninitializedFieldDiagnosticSuppressorTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureUninitializedFieldDiagnosticSuppressorTests.cs index 7b5b24ddc..0d05dc10e 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureUninitializedFieldDiagnosticSuppressorTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureUninitializedFieldDiagnosticSuppressorTests.cs @@ -6,6 +6,7 @@ namespace ComputeSharp.D2D1.Tests; internal sealed partial class D2D1ResourceTextureUninitializedFieldDiagnosticSuppressorTests { [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] public readonly partial struct MyShader : ID2D1PixelShader { // This test just needs to validate the project builds fine with this shader. diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1TransformMapperTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1TransformMapperTests.cs index ff4dcb6c7..0c8a37e57 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1TransformMapperTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1TransformMapperTests.cs @@ -198,6 +198,7 @@ static void Test(GCHandle transformMapperHandle) } [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] private partial struct DummyShader : ID2D1PixelShader { public float4 Execute() @@ -287,6 +288,7 @@ public override void MapOutputToInputs(in Rectangle output, Span inpu [D2DInputCount(1)] [D2DInputSimple(0)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private partial struct ShaderWithDispatchArea : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/BokehBlurEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/BokehBlurEffect.cs index 7e7dfc0d3..16cca7ff2 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/BokehBlurEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/BokehBlurEffect.cs @@ -509,6 +509,7 @@ private sealed partial class VerticalConvolution [D2DOutputBuffer(D2D1BufferPrecision.Float32, D2D1ChannelDepth.Four)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] [AutoConstructor] public readonly partial struct Shader : ID2D1PixelShader { @@ -558,6 +559,7 @@ private sealed partial class HorizontalConvolutionAndAccumulatePartials [D2DOutputBuffer(D2D1BufferPrecision.Float32, D2D1ChannelDepth.Four)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] [D2DRequiresScenePosition] + [D2DGeneratedShaderMarshaller] [AutoConstructor] public readonly partial struct Shader : ID2D1PixelShader { @@ -602,6 +604,7 @@ public float4 Execute() [D2DInputDescription(0, D2D1Filter.MinMagMipPoint)] [D2DOutputBuffer(D2D1BufferPrecision.Float32, D2D1ChannelDepth.Four)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] + [D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct GammaHighlight : ID2D1PixelShader { @@ -624,6 +627,7 @@ public float4 Execute() [D2DInputDescription(0, D2D1Filter.MinMagMipPoint)] [D2DOutputBuffer(D2D1BufferPrecision.Float32, D2D1ChannelDepth.Four)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] + [D2DGeneratedShaderMarshaller] [AutoConstructor] internal readonly partial struct InverseGammaHighlight : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/CheckerboardClipEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/CheckerboardClipEffect.cs index 22ca046c7..5755e139f 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/CheckerboardClipEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/CheckerboardClipEffect.cs @@ -4,6 +4,7 @@ namespace ComputeSharp.D2D1.Tests.Effects; [D2DInputSimple(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] public partial struct CheckerboardClipEffect : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/InvertEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/InvertEffect.cs index b48972ccd..949cf282c 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/InvertEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/InvertEffect.cs @@ -3,6 +3,7 @@ namespace ComputeSharp.D2D1.Tests.Effects; [D2DInputCount(1)] [D2DInputSimple(0)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] public partial struct InvertEffect : ID2D1PixelShader { /// diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/InvertWithThresholdEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/InvertWithThresholdEffect.cs index 542ed4908..03b5505a6 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/InvertWithThresholdEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/InvertWithThresholdEffect.cs @@ -3,6 +3,7 @@ namespace ComputeSharp.D2D1.Tests.Effects; [D2DInputCount(1)] [D2DInputSimple(0)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] public partial struct InvertWithThresholdEffect : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/PixelateEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/PixelateEffect.cs index 59ed43c79..07b491358 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/PixelateEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/PixelateEffect.cs @@ -4,9 +4,11 @@ namespace ComputeSharp.D2D1.Tests.Effects; [D2DInputComplex(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader40)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] public readonly partial struct PixelateEffect : ID2D1PixelShader { + [D2DGeneratedShaderMarshaller] [AutoConstructor] public readonly partial struct Constants { diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/ZonePlateEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/ZonePlateEffect.cs index 8f68bced9..e4a6b8083 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/ZonePlateEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/ZonePlateEffect.cs @@ -12,6 +12,7 @@ internal static class MathF [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] +[D2DGeneratedShaderMarshaller] [AutoConstructor] public readonly partial struct ZonePlateEffect : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.UI.Tests/CanvasEffectTests.cs b/tests/ComputeSharp.D2D1.UI.Tests/CanvasEffectTests.cs index 6bdccd446..3b1711075 100644 --- a/tests/ComputeSharp.D2D1.UI.Tests/CanvasEffectTests.cs +++ b/tests/ComputeSharp.D2D1.UI.Tests/CanvasEffectTests.cs @@ -698,6 +698,7 @@ public void Dispose() } [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private partial struct ShaderWithNoInputs : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.UI.Tests/PixelShaderEffectTests.cs b/tests/ComputeSharp.D2D1.UI.Tests/PixelShaderEffectTests.cs index 7440367f4..eaa83d7aa 100644 --- a/tests/ComputeSharp.D2D1.UI.Tests/PixelShaderEffectTests.cs +++ b/tests/ComputeSharp.D2D1.UI.Tests/PixelShaderEffectTests.cs @@ -459,6 +459,7 @@ public unsafe void Interop_WrapperFactoryDetectsMismatchedDevices() } [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private partial struct ShaderWithSomeProperties : ID2D1PixelShader { @@ -475,6 +476,7 @@ public float4 Execute() } [D2DInputCount(1)] + [D2DGeneratedShaderMarshaller] [AutoConstructor] private partial struct ShaderWithSomePropertiesAndInputs : ID2D1PixelShader { @@ -487,6 +489,7 @@ public float4 Execute() } [D2DInputCount(0)] + [D2DGeneratedShaderMarshaller] private partial struct ShaderWith0Inputs : ID2D1PixelShader { public float4 Execute() @@ -497,6 +500,7 @@ public float4 Execute() [D2DInputCount(1)] [D2DInputSimple(0)] + [D2DGeneratedShaderMarshaller] private partial struct ShaderWith1Input : ID2D1PixelShader { public float4 Execute() @@ -508,6 +512,7 @@ public float4 Execute() [D2DInputCount(2)] [D2DInputSimple(0)] [D2DInputSimple(1)] + [D2DGeneratedShaderMarshaller] private partial struct ShaderWith2Inputs : ID2D1PixelShader { public float4 Execute() From 933dca22ed8d82a23b08159c04e4abceee42ac6b Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 1 Oct 2023 14:09:43 +0200 Subject: [PATCH 04/20] Rename to D2DGeneratedPixelShaderDescriptorAttribute --- .../ColorfulInfinity.cs | 2 +- .../ContouredLayers.cs | 2 +- .../FractalTiling.cs | 2 +- .../HelloWorld.cs | 2 +- .../MengerJourney.cs | 2 +- .../Octagrams.cs | 2 +- .../ProteanClouds.cs | 2 +- .../PyramidPattern.cs | 2 +- .../TerracedHills.cs | 2 +- .../TriangleGridContouring.cs | 2 +- .../TwoTiledTruchet.cs | 2 +- .../ID2D1ShaderGenerator.cs | 2 +- ...eneratedPixelShaderDescriptorAttribute.cs} | 8 ++--- .../D2D1PixelShaderTests.cs | 8 ++--- .../D2D1EffectRegistrationDataTests.cs | 6 ++-- .../D2D1PixelShaderEffectTests.cs | 16 ++++----- .../D2D1PixelShaderTests.cs | 36 +++++++++---------- .../D2D1ReflectionServicesTests.cs | 4 +-- .../D2D1ResourceTextureManagerTests.cs | 14 ++++---- ...itializedFieldDiagnosticSuppressorTests.cs | 2 +- .../D2D1TransformMapperTests.cs | 4 +-- .../Effects/BokehBlurEffect.cs | 8 ++--- .../Effects/CheckerboardClipEffect.cs | 2 +- .../Effects/InvertEffect.cs | 2 +- .../Effects/InvertWithThresholdEffect.cs | 2 +- .../Effects/PixelateEffect.cs | 4 +-- .../Effects/ZonePlateEffect.cs | 2 +- .../CanvasEffectTests.cs | 2 +- .../PixelShaderEffectTests.cs | 10 +++--- 29 files changed, 77 insertions(+), 77 deletions(-) rename src/ComputeSharp.D2D1/Attributes/{D2DGeneratedShaderMarshallerAttribute.cs => D2DGeneratedPixelShaderDescriptorAttribute.cs} (65%) diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ColorfulInfinity.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ColorfulInfinity.cs index aebb80fb0..846712197 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ColorfulInfinity.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ColorfulInfinity.cs @@ -11,7 +11,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct ColorfulInfinity : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ContouredLayers.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ContouredLayers.cs index 1a7fa26c2..d2cf799e6 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ContouredLayers.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ContouredLayers.cs @@ -10,7 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct ContouredLayers : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/FractalTiling.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/FractalTiling.cs index fab955e8f..9b3e49957 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/FractalTiling.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/FractalTiling.cs @@ -11,7 +11,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct FractalTiling : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/HelloWorld.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/HelloWorld.cs index 2332ba771..f69707050 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/HelloWorld.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/HelloWorld.cs @@ -9,7 +9,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct HelloWorld : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/MengerJourney.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/MengerJourney.cs index 410b302a8..ef1a0d13c 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/MengerJourney.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/MengerJourney.cs @@ -10,7 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct MengerJourney : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/Octagrams.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/Octagrams.cs index be787a781..2e83fe790 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/Octagrams.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/Octagrams.cs @@ -10,7 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct Octagrams : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ProteanClouds.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ProteanClouds.cs index 068914f4e..00527c5c0 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ProteanClouds.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/ProteanClouds.cs @@ -11,7 +11,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct ProteanClouds : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/PyramidPattern.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/PyramidPattern.cs index 4564cb0c5..93bff4b01 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/PyramidPattern.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/PyramidPattern.cs @@ -11,7 +11,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct PyramidPattern : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TerracedHills.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TerracedHills.cs index 951a49710..b45fe7c17 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TerracedHills.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TerracedHills.cs @@ -10,7 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct TerracedHills : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TriangleGridContouring.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TriangleGridContouring.cs index 24bec4686..f2d3b62a8 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TriangleGridContouring.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TriangleGridContouring.cs @@ -10,7 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct TriangleGridContouring : ID2D1PixelShader { diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TwoTiledTruchet.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TwoTiledTruchet.cs index 2deb4d94e..4e61a9a15 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TwoTiledTruchet.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TwoTiledTruchet.cs @@ -10,7 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1; [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct TwoTiledTruchet : ID2D1PixelShader { diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs index 3b10c6fc2..50a3fd9e9 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs @@ -22,7 +22,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) IncrementalValuesProvider shaderInfo = context.SyntaxProvider .ForAttributeWithMetadataName( - "ComputeSharp.D2D1.D2DGeneratedShaderMarshallerAttribute", + "ComputeSharp.D2D1.D2DGeneratedPixelShaderDescriptorAttribute", static (node, _) => node.IsTypeDeclarationWithOrPotentiallyWithBaseTypes(), static (context, token) => { diff --git a/src/ComputeSharp.D2D1/Attributes/D2DGeneratedShaderMarshallerAttribute.cs b/src/ComputeSharp.D2D1/Attributes/D2DGeneratedPixelShaderDescriptorAttribute.cs similarity index 65% rename from src/ComputeSharp.D2D1/Attributes/D2DGeneratedShaderMarshallerAttribute.cs rename to src/ComputeSharp.D2D1/Attributes/D2DGeneratedPixelShaderDescriptorAttribute.cs index 7240d9f83..da27d2fe7 100644 --- a/src/ComputeSharp.D2D1/Attributes/D2DGeneratedShaderMarshallerAttribute.cs +++ b/src/ComputeSharp.D2D1/Attributes/D2DGeneratedPixelShaderDescriptorAttribute.cs @@ -3,22 +3,22 @@ namespace ComputeSharp.D2D1; /// -/// An attribute that indicates that a given D2D1 shader should have its associated marshalling code being generated. +/// An attribute that indicates that a given D2D1 shader should have its associated descriptor code being generated. /// /// This attribute can be used on shader types that are declared as : /// -/// [D2DGeneratedShaderMarshaller] +/// [D2DGeneratedPixelShaderDescriptor] /// partial struct MyShader : ID2D1PixelShader /// { /// } /// /// /// -/// When a shader is annotated with , the source generator will also add +/// When a shader is annotated with , the source generator will also add /// to its implemented interfaces, and implement its APIs automatically. /// /// [AttributeUsage(AttributeTargets.Struct, AllowMultiple = false)] -public sealed class D2DGeneratedShaderMarshallerAttribute : Attribute +public sealed class D2DGeneratedPixelShaderDescriptorAttribute : Attribute { } \ No newline at end of file diff --git a/tests/ComputeSharp.D2D1.Tests.AssemblyLevelAttributes/D2D1PixelShaderTests.cs b/tests/ComputeSharp.D2D1.Tests.AssemblyLevelAttributes/D2D1PixelShaderTests.cs index 6e912aa82..e84fdad4a 100644 --- a/tests/ComputeSharp.D2D1.Tests.AssemblyLevelAttributes/D2D1PixelShaderTests.cs +++ b/tests/ComputeSharp.D2D1.Tests.AssemblyLevelAttributes/D2D1PixelShaderTests.cs @@ -49,7 +49,7 @@ public unsafe void ShaderWithAssemblyLevelAttributes() [D2DInputSimple(0)] [D2DInputSimple(1)] [D2DInputSimple(2)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct ShaderWithNoCompileAttributes : ID2D1PixelShader { public float4 Execute() @@ -95,7 +95,7 @@ public unsafe void ShaderWithAssemblyLevelAttributesAndOverriddenProfile() [D2DInputSimple(1)] [D2DInputSimple(2)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct ShaderWithOverriddenProfile : ID2D1PixelShader { public float4 Execute() @@ -141,7 +141,7 @@ public unsafe void ShaderWithAssemblyLevelAttributesAndOverriddenOptions() [D2DInputSimple(1)] [D2DInputSimple(2)] [D2DCompileOptions(D2D1CompileOptions.Debug | D2D1CompileOptions.AvoidFlowControl | D2D1CompileOptions.PartialPrecision)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct ShaderWithOverriddenOptions : ID2D1PixelShader { public float4 Execute() @@ -178,7 +178,7 @@ public unsafe void ShaderWithAssemblyLevelAttributesAndEverythingOverridden() [D2DInputSimple(2)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] [D2DCompileOptions(D2D1CompileOptions.Debug | D2D1CompileOptions.AvoidFlowControl | D2D1CompileOptions.PartialPrecision)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct ShaderWithOverriddenProfileAndOptions : ID2D1PixelShader { public float4 Execute() diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1EffectRegistrationDataTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1EffectRegistrationDataTests.cs index 562ee0920..c0cd430a6 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1EffectRegistrationDataTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1EffectRegistrationDataTests.cs @@ -51,7 +51,7 @@ public unsafe void EffectRegistrationData_Validate() [D2DInputCount(2)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private readonly partial struct TestRegistrationBlobShader : ID2D1PixelShader { @@ -97,7 +97,7 @@ public unsafe void EffectRegistrationData_WithCustomMetadata_Validate() [D2DEffectDescription("A test effect with some custom metadata")] [D2DEffectCategory("Test effects")] [D2DEffectAuthor("Bob Ross")] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private readonly partial struct TestRegistrationBlobWithCustomMetadataShader : ID2D1PixelShader { @@ -194,7 +194,7 @@ public unsafe void EffectRegistrationData_WithResourceTextures_Validate() } [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private readonly partial struct TestRegistrationBlobWithResourceTextures : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderEffectTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderEffectTests.cs index 8a0eee987..2659b3251 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderEffectTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderEffectTests.cs @@ -120,7 +120,7 @@ public unsafe void NullConstantBuffer_DrawImageFails() [D2DInputCount(0)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private partial struct NullConstantBufferShader : ID2D1PixelShader { @@ -152,7 +152,7 @@ public unsafe void GetValueSize_ConstantBuffer() [D2DInputCount(0)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private partial struct ConstantBufferSizeTestShader : ID2D1PixelShader { @@ -187,7 +187,7 @@ public unsafe void DefaultEffectId_MatchesValue() } [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct ShaderWithDefaultEffectId : ID2D1PixelShader { public float4 Execute() @@ -197,7 +197,7 @@ public float4 Execute() } [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct ShaderWithDefaultEffectId2 : ID2D1PixelShader { public float4 Execute() @@ -221,7 +221,7 @@ public unsafe void ExplicitEffectId_MatchesValue() [D2DInputCount(0)] [D2DEffectId("8E1F7F49-EF0D-4242-8912-08ADA36AB4EC")] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct ShaderWithExplicitEffectId : ID2D1PixelShader { public float4 Execute() @@ -240,7 +240,7 @@ public unsafe void DefaultEffectMetadata_MatchesValue() } [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct ShaderWithDefaultEffectDisplayName : ID2D1PixelShader { public float4 Execute() @@ -260,7 +260,7 @@ public unsafe void ExplicitEffectMetadata1_MatchesValue() [D2DInputCount(0)] [D2DEffectDisplayName("Fancy blur")] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct ShaderWithExplicitEffectDisplayName1 : ID2D1PixelShader { public float4 Execute() @@ -283,7 +283,7 @@ public unsafe void ExplicitEffectMetadata2_MatchesValue() [D2DEffectDescription("A test effect with \nsome custom metadata")] [D2DEffectCategory("Test effects!")] [D2DEffectAuthor("Bob \r\nRoss")] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct ShaderWithExplicitEffectDisplayName2 : ID2D1PixelShader { public float4 Execute() diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderTests.cs index d710f7a4a..e66de1f30 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1PixelShaderTests.cs @@ -66,7 +66,7 @@ public void GetInputTypes_SameManager() [D2DInputComplex(3)] [D2DInputComplex(5)] [D2DInputSimple(6)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] partial struct ShaderWithMultipleInputs : ID2D1PixelShader { public Float4 Execute() @@ -94,7 +94,7 @@ public void GetOutputBufferChannelDepth() } [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] partial struct EmptyShader : ID2D1PixelShader { public Float4 Execute() @@ -105,7 +105,7 @@ public Float4 Execute() [D2DInputCount(0)] [D2DOutputBuffer(D2D1BufferPrecision.UInt16Normalized)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] partial struct OnlyBufferPrecisionShader : ID2D1PixelShader { public Float4 Execute() @@ -116,7 +116,7 @@ public Float4 Execute() [D2DInputCount(0)] [D2DOutputBuffer(D2D1ChannelDepth.Four)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] partial struct OnlyChannelDepthShader : ID2D1PixelShader { public Float4 Execute() @@ -127,7 +127,7 @@ public Float4 Execute() [D2DInputCount(0)] [D2DOutputBuffer(D2D1BufferPrecision.UInt8NormalizedSrgb, D2D1ChannelDepth.One)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] partial struct CustomBufferOutputShader : ID2D1PixelShader { public Float4 Execute() @@ -194,7 +194,7 @@ public void GetInputDescriptions_Custom() [D2DInputDescription(2, D2D1Filter.MinLinearMagPointMinLinear, LevelOfDetailCount = 4)] [D2DInputDescription(5, D2D1Filter.MinMagPointMipLinear)] [D2DInputDescription(6, D2D1Filter.MinPointMagMipLinear, LevelOfDetailCount = 3)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] partial struct ShaderWithInputDescriptions : ID2D1PixelShader { public Float4 Execute() @@ -255,7 +255,7 @@ public void GetResourceTextureCount_IsCorrect() [D2DInputComplex(1)] [D2DInputComplex(3)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] partial struct ShaderWithoutResourceTextures : ID2D1PixelShader { @@ -267,7 +267,7 @@ public Float4 Execute() [D2DInputCount(0)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] partial struct ShaderWithJustOneResourceTextures : ID2D1PixelShader { @@ -286,7 +286,7 @@ public Float4 Execute() [D2DInputComplex(1)] [D2DInputComplex(3)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] partial struct ShaderWithResourceTextures : ID2D1PixelShader { @@ -331,7 +331,7 @@ public void GetBytecode_FromDynamicBytecode() } [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct ShaderWithoutEmbeddedBytecode : ID2D1PixelShader { public float4 Execute() @@ -403,7 +403,7 @@ public void GetBytecode_FromEmbeddedBytecode_WithTargetProfileAndPackMatrixColum [D2DInputSimple(1)] [D2DInputSimple(2)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader40Level91)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct ShaderWithEmbeddedBytecode : ID2D1PixelShader { public float4 Execute() @@ -453,7 +453,7 @@ public void GetBytecode_FromEmbeddedBytecode_WithCompileOptions() [D2DInputSimple(2)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader40Level91)] [D2DCompileOptions(D2D1CompileOptions.IeeeStrictness | D2D1CompileOptions.OptimizationLevel2)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct ShaderWithEmbeddedBytecodeAndCompileOptions : ID2D1PixelShader { public float4 Execute() @@ -485,7 +485,7 @@ public void LoadBytecode_VerifyEffectiveValues_ExplicitShaderProfile() [D2DInputCount(1)] [D2DInputSimple(0)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader40Level91)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct SimpleShaderWithExplicitShaderProfileAndNoCompileOptions : ID2D1PixelShader { public float4 Execute() @@ -497,7 +497,7 @@ public float4 Execute() [D2DInputCount(1)] [D2DInputComplex(0)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader40Level91)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct ComplexShaderWithExplicitShaderProfileAndNoCompileOptions : ID2D1PixelShader { public float4 Execute() @@ -523,7 +523,7 @@ public void LoadBytecode_VerifyEffectiveValues_ExplicitCompileOptions() [D2DInputCount(1)] [D2DInputSimple(0)] [D2DCompileOptions(D2D1CompileOptions.OptimizationLevel2 | D2D1CompileOptions.IeeeStrictness)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct ShaderWithExplicitCompileOptionsAndNoShaderProfile : ID2D1PixelShader { public float4 Execute() @@ -572,7 +572,7 @@ public void GetConstantBuffer_Empty_Span() [D2DInputSimple(0)] [D2DInputDescription(0, D2D1Filter.MinMagMipPoint)] [D2DPixelOptions(D2D1PixelOptions.TrivialSampling)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct ShaderWithNoCapturedValues : ID2D1PixelShader { public float4 Execute() @@ -820,7 +820,7 @@ private static void ValidateShadersAreEqual(in ShaderWithScalarVectorAndMatrixTy } [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private readonly partial struct ShaderWithScalarVectorAndMatrixTypes : ID2D1PixelShader { @@ -913,7 +913,7 @@ public readonly partial struct FieldsContainer3 } [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private readonly partial struct ShaderWithScalarVectorAndMatrixTypesInNestedStructs : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1ReflectionServicesTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1ReflectionServicesTests.cs index 31f2ef8ca..df51cd07b 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1ReflectionServicesTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1ReflectionServicesTests.cs @@ -60,7 +60,7 @@ public void GetShaderInfo() [D2DInputComplex(2)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader41)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct ReflectedShader : ID2D1PixelShader { private readonly float2 offset; @@ -120,7 +120,7 @@ public void GetShaderInfoWithDoublePrecisionFeature() [D2DInputCount(1)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private readonly partial struct ReflectedShaderWithDoubleOperations : ID2D1PixelShader { private readonly double amount; diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureManagerTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureManagerTests.cs index be8f5f88a..67cdca7dc 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureManagerTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureManagerTests.cs @@ -171,7 +171,7 @@ public unsafe void SingleThreadedFactory_AssigningRCWManagerFails() [D2DInputCount(0)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct DummyShaderWithResourceTexture : ID2D1PixelShader { [D2DResourceTextureIndex(0)] @@ -460,7 +460,7 @@ public unsafe void LoadPixelsFromResourceTexture2D_AlternatingResourceTextureMan [D2DInputCount(0)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct IndexFrom2DResourceTextureShader : ID2D1PixelShader { [D2DResourceTextureIndex(0)] @@ -535,7 +535,7 @@ public unsafe void LoadPixelsFromResourceTexture3D() [D2DInputCount(0)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private partial struct IndexFrom3DResourceTextureShader : ID2D1PixelShader { @@ -623,7 +623,7 @@ public unsafe void UpdateResourceTexture1D(int width, int startOffset, int updat [D2DInputCount(0)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private partial struct CopyFromResourceTexture1DShader : ID2D1PixelShader { @@ -721,7 +721,7 @@ public unsafe void UpdateResourceTexture2D( [D2DInputCount(0)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private partial struct CopyFromResourceTexture2DShader : ID2D1PixelShader { @@ -828,7 +828,7 @@ public unsafe void UpdateResourceTexture3D( [D2DInputCount(0)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private partial struct CopyFromResourceTexture3DShader : ID2D1PixelShader { @@ -874,7 +874,7 @@ public unsafe void NullResourceTexture_DrawImageFails() [D2DInputCount(0)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct NullResourceTextureShader : ID2D1PixelShader { [D2DResourceTextureIndex(0)] diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureUninitializedFieldDiagnosticSuppressorTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureUninitializedFieldDiagnosticSuppressorTests.cs index 0d05dc10e..16a613e65 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureUninitializedFieldDiagnosticSuppressorTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1ResourceTextureUninitializedFieldDiagnosticSuppressorTests.cs @@ -6,7 +6,7 @@ namespace ComputeSharp.D2D1.Tests; internal sealed partial class D2D1ResourceTextureUninitializedFieldDiagnosticSuppressorTests { [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] public readonly partial struct MyShader : ID2D1PixelShader { // This test just needs to validate the project builds fine with this shader. diff --git a/tests/ComputeSharp.D2D1.Tests/D2D1TransformMapperTests.cs b/tests/ComputeSharp.D2D1.Tests/D2D1TransformMapperTests.cs index 0c8a37e57..e8c8d8738 100644 --- a/tests/ComputeSharp.D2D1.Tests/D2D1TransformMapperTests.cs +++ b/tests/ComputeSharp.D2D1.Tests/D2D1TransformMapperTests.cs @@ -198,7 +198,7 @@ static void Test(GCHandle transformMapperHandle) } [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct DummyShader : ID2D1PixelShader { public float4 Execute() @@ -288,7 +288,7 @@ public override void MapOutputToInputs(in Rectangle output, Span inpu [D2DInputCount(1)] [D2DInputSimple(0)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private partial struct ShaderWithDispatchArea : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/BokehBlurEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/BokehBlurEffect.cs index 16cca7ff2..a45388ea2 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/BokehBlurEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/BokehBlurEffect.cs @@ -509,7 +509,7 @@ private sealed partial class VerticalConvolution [D2DOutputBuffer(D2D1BufferPrecision.Float32, D2D1ChannelDepth.Four)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] public readonly partial struct Shader : ID2D1PixelShader { @@ -559,7 +559,7 @@ private sealed partial class HorizontalConvolutionAndAccumulatePartials [D2DOutputBuffer(D2D1BufferPrecision.Float32, D2D1ChannelDepth.Four)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] [D2DRequiresScenePosition] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] public readonly partial struct Shader : ID2D1PixelShader { @@ -604,7 +604,7 @@ public float4 Execute() [D2DInputDescription(0, D2D1Filter.MinMagMipPoint)] [D2DOutputBuffer(D2D1BufferPrecision.Float32, D2D1ChannelDepth.Four)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct GammaHighlight : ID2D1PixelShader { @@ -627,7 +627,7 @@ public float4 Execute() [D2DInputDescription(0, D2D1Filter.MinMagMipPoint)] [D2DOutputBuffer(D2D1BufferPrecision.Float32, D2D1ChannelDepth.Four)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] internal readonly partial struct InverseGammaHighlight : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/CheckerboardClipEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/CheckerboardClipEffect.cs index 5755e139f..2d448d99a 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/CheckerboardClipEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/CheckerboardClipEffect.cs @@ -4,7 +4,7 @@ namespace ComputeSharp.D2D1.Tests.Effects; [D2DInputSimple(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] public partial struct CheckerboardClipEffect : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/InvertEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/InvertEffect.cs index 949cf282c..dbe72401a 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/InvertEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/InvertEffect.cs @@ -3,7 +3,7 @@ namespace ComputeSharp.D2D1.Tests.Effects; [D2DInputCount(1)] [D2DInputSimple(0)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] public partial struct InvertEffect : ID2D1PixelShader { /// diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/InvertWithThresholdEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/InvertWithThresholdEffect.cs index 03b5505a6..cca2b3a41 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/InvertWithThresholdEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/InvertWithThresholdEffect.cs @@ -3,7 +3,7 @@ namespace ComputeSharp.D2D1.Tests.Effects; [D2DInputCount(1)] [D2DInputSimple(0)] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] public partial struct InvertWithThresholdEffect : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/PixelateEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/PixelateEffect.cs index 07b491358..fd5a28afb 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/PixelateEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/PixelateEffect.cs @@ -4,11 +4,11 @@ namespace ComputeSharp.D2D1.Tests.Effects; [D2DInputComplex(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader40)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] public readonly partial struct PixelateEffect : ID2D1PixelShader { - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] public readonly partial struct Constants { diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/ZonePlateEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/ZonePlateEffect.cs index e4a6b8083..4526d8a37 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/ZonePlateEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/ZonePlateEffect.cs @@ -12,7 +12,7 @@ internal static class MathF [D2DInputCount(0)] [D2DRequiresScenePosition] [D2DShaderProfile(D2D1ShaderProfile.PixelShader50)] -[D2DGeneratedShaderMarshaller] +[D2DGeneratedPixelShaderDescriptor] [AutoConstructor] public readonly partial struct ZonePlateEffect : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.UI.Tests/CanvasEffectTests.cs b/tests/ComputeSharp.D2D1.UI.Tests/CanvasEffectTests.cs index 3b1711075..82f2bb659 100644 --- a/tests/ComputeSharp.D2D1.UI.Tests/CanvasEffectTests.cs +++ b/tests/ComputeSharp.D2D1.UI.Tests/CanvasEffectTests.cs @@ -698,7 +698,7 @@ public void Dispose() } [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private partial struct ShaderWithNoInputs : ID2D1PixelShader { diff --git a/tests/ComputeSharp.D2D1.UI.Tests/PixelShaderEffectTests.cs b/tests/ComputeSharp.D2D1.UI.Tests/PixelShaderEffectTests.cs index eaa83d7aa..ba221a167 100644 --- a/tests/ComputeSharp.D2D1.UI.Tests/PixelShaderEffectTests.cs +++ b/tests/ComputeSharp.D2D1.UI.Tests/PixelShaderEffectTests.cs @@ -459,7 +459,7 @@ public unsafe void Interop_WrapperFactoryDetectsMismatchedDevices() } [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private partial struct ShaderWithSomeProperties : ID2D1PixelShader { @@ -476,7 +476,7 @@ public float4 Execute() } [D2DInputCount(1)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] private partial struct ShaderWithSomePropertiesAndInputs : ID2D1PixelShader { @@ -489,7 +489,7 @@ public float4 Execute() } [D2DInputCount(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct ShaderWith0Inputs : ID2D1PixelShader { public float4 Execute() @@ -500,7 +500,7 @@ public float4 Execute() [D2DInputCount(1)] [D2DInputSimple(0)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct ShaderWith1Input : ID2D1PixelShader { public float4 Execute() @@ -512,7 +512,7 @@ public float4 Execute() [D2DInputCount(2)] [D2DInputSimple(0)] [D2DInputSimple(1)] - [D2DGeneratedShaderMarshaller] + [D2DGeneratedPixelShaderDescriptor] private partial struct ShaderWith2Inputs : ID2D1PixelShader { public float4 Execute() From 821bc6ba0de2e1740568c2192aac7129efeb8c4a Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 1 Oct 2023 14:53:41 +0200 Subject: [PATCH 05/20] Add MissingPixelShaderDescriptorOnPixelShaderAnalyzer --- .../AnalyzerReleases.Shipped.md | 1 + ...elShaderDescriptorOnPixelShaderAnalyzer.cs | 61 +++++++++++++++++++ .../Diagnostics/DiagnosticDescriptors.cs | 22 +++++++ .../Extensions/ISymbolExtensions.cs | 11 ++++ .../Extensions/ITypeSymbolExtensions.cs | 19 ++++++ 5 files changed, 114 insertions(+) create mode 100644 src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/Analyzers/MissingPixelShaderDescriptorOnPixelShaderAnalyzer.cs diff --git a/src/ComputeSharp.D2D1.SourceGenerators/AnalyzerReleases.Shipped.md b/src/ComputeSharp.D2D1.SourceGenerators/AnalyzerReleases.Shipped.md index 7a211015b..947bb3591 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/AnalyzerReleases.Shipped.md +++ b/src/ComputeSharp.D2D1.SourceGenerators/AnalyzerReleases.Shipped.md @@ -71,3 +71,4 @@ CMPSD2D0061 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github CMPSD2D0062 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github.com/Sergio0694/ComputeSharp) CMPSD2D0063 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github.com/Sergio0694/ComputeSharp) CMPSD2D0064 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github.com/Sergio0694/ComputeSharp) +CMPSD2D0065 | ComputeSharp.D2D1.Shaders | Warning | [Documentation](https://github.com/Sergio0694/ComputeSharp) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/Analyzers/MissingPixelShaderDescriptorOnPixelShaderAnalyzer.cs b/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/Analyzers/MissingPixelShaderDescriptorOnPixelShaderAnalyzer.cs new file mode 100644 index 000000000..2f125cf00 --- /dev/null +++ b/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/Analyzers/MissingPixelShaderDescriptorOnPixelShaderAnalyzer.cs @@ -0,0 +1,61 @@ +using System.Collections.Immutable; +using System.Linq; +using ComputeSharp.SourceGeneration.Extensions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using static ComputeSharp.SourceGeneration.Diagnostics.DiagnosticDescriptors; + +namespace ComputeSharp.D2D1.SourceGenerators; + +/// +/// A diagnostic analyzer that generates a warning whenever a D2D1 shader type does not have an associated descriptor. +/// +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class MissingPixelShaderDescriptorOnPixelShaderAnalyzer : DiagnosticAnalyzer +{ + /// + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(MissingPixelShaderDescriptorOnPixelShaderType); + + /// + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); + context.EnableConcurrentExecution(); + + context.RegisterCompilationStartAction(static context => + { + // Get the ID2D1PixelShader, ID2D1PixelShaderDescriptor and [D2DGeneratedPixelShaderDescriptor] symbols + if (context.Compilation.GetTypeByMetadataName("ComputeSharp.D2D1.ID2D1PixelShader") is not { } d2D1PixelShaderSymbol || + context.Compilation.GetTypeByMetadataName("ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor`1") is not { } d2D1PixelShaderDescriptorSymbol || + context.Compilation.GetTypeByMetadataName("ComputeSharp.D2D1.D2DGeneratedPixelShaderDescriptorAttribute") is not { } d2DGeneratedPixelShaderDescriptorAttributeSymbol) + { + return; + } + + context.RegisterSymbolAction(context => + { + // Only struct types are possible targets + if (context.Symbol is not INamedTypeSymbol { TypeKind: TypeKind.Struct } typeSymbol) + { + return; + } + + // If the type is not a pixel shader type, immediately bail out + if (!typeSymbol.HasInterfaceWithType(d2D1PixelShaderSymbol)) + { + return; + } + + // Emit a diagnostic if the descriptor is missing for the shader type + if (!typeSymbol.HasInterfaceWithType(d2D1PixelShaderDescriptorSymbol) && + !typeSymbol.HasAttributeWithType(d2DGeneratedPixelShaderDescriptorAttributeSymbol)) + { + context.ReportDiagnostic(Diagnostic.Create( + MissingPixelShaderDescriptorOnPixelShaderType, + typeSymbol.Locations.FirstOrDefault(), + typeSymbol)); + } + }, SymbolKind.NamedType); + }); + } +} \ No newline at end of file diff --git a/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs b/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs index a5110fe2c..c4107fd70 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs @@ -7,6 +7,11 @@ namespace ComputeSharp.SourceGeneration.Diagnostics; /// partial class DiagnosticDescriptors { + /// + /// The diagnostic id for . + /// + public const string MissingPixelShaderDescriptorOnPixelShaderTypeId = "CMPSD2D0065"; + /// /// Gets a for an invalid shader field. /// @@ -954,4 +959,21 @@ partial class DiagnosticDescriptors description: "Unsafe blocks must be enabled for the source generators to emit valid code (the true option must be set in the .csproj/.props file).", helpLinkUri: "https://github.com/Sergio0694/ComputeSharp", customTags: WellKnownDiagnosticTags.CompilationEnd); + + /// + /// Gets a for when a pixel shader type doesn't have an associated descriptor. + /// + /// Format: "The D2D1 shader of type {0} does not have an associated descriptor (it can be autogenerated via the [D2DGeneratedPixelShaderDescriptor] attribute)". + /// + /// + public static readonly DiagnosticDescriptor MissingPixelShaderDescriptorOnPixelShaderType = new DiagnosticDescriptor( + id: MissingPixelShaderDescriptorOnPixelShaderTypeId, + title: "Missing descriptor for D2D1 pixel shader type", + messageFormat: "The D2D1 shader of type {0} does not have an associated descriptor (it can be autogenerated via the [D2DGeneratedPixelShaderDescriptor] attribute)", + category: "ComputeSharp.D2D1.Shaders", + defaultSeverity: DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: "All D2D1 shader types must have an associated descriptor (it can be autogenerated via the [D2DGeneratedPixelShaderDescriptor] attribute).", + helpLinkUri: "https://github.com/Sergio0694/ComputeSharp", + customTags: WellKnownDiagnosticTags.CompilationEnd); } \ No newline at end of file diff --git a/src/ComputeSharp.SourceGeneration/Extensions/ISymbolExtensions.cs b/src/ComputeSharp.SourceGeneration/Extensions/ISymbolExtensions.cs index b0a317243..a0dd6fbe3 100644 --- a/src/ComputeSharp.SourceGeneration/Extensions/ISymbolExtensions.cs +++ b/src/ComputeSharp.SourceGeneration/Extensions/ISymbolExtensions.cs @@ -27,6 +27,17 @@ public static string GetFullyQualifiedName(this ISymbol symbol) return symbol.ToDisplayString(FullyQualifiedWithoutGlobalFormat); } + /// + /// Checks whether or not a given symbol has an attribute with the specified type. + /// + /// The input instance to check. + /// The instance for the attribute type to look for. + /// Whether or not has an attribute with the specified type. + public static bool HasAttributeWithType(this ISymbol symbol, ITypeSymbol typeSymbol) + { + return TryGetAttributeWithType(symbol, typeSymbol, out _); + } + /// /// Tries to get an attribute with the specified type. /// diff --git a/src/ComputeSharp.SourceGeneration/Extensions/ITypeSymbolExtensions.cs b/src/ComputeSharp.SourceGeneration/Extensions/ITypeSymbolExtensions.cs index a9fd5b261..5149f647a 100644 --- a/src/ComputeSharp.SourceGeneration/Extensions/ITypeSymbolExtensions.cs +++ b/src/ComputeSharp.SourceGeneration/Extensions/ITypeSymbolExtensions.cs @@ -24,6 +24,25 @@ public static bool HasFullyQualifiedMetadataName(this ITypeSymbol symbol, string return builder.WrittenSpan.SequenceEqual(name.AsSpan()); } + /// + /// Checks whether or not a given implements an interface of a specified type. + /// + /// The target instance to check. + /// The instane to check for inheritance from. + /// Whether or not has an interface of type . + public static bool HasInterfaceWithType(this ITypeSymbol typeSymbol, ITypeSymbol interfaceSymbol) + { + foreach (INamedTypeSymbol interfaceType in typeSymbol.AllInterfaces) + { + if (SymbolEqualityComparer.Default.Equals(interfaceType, interfaceSymbol)) + { + return true; + } + } + + return false; + } + /// /// Gets the fully qualified metadata name for a given instance. /// From e343035efef1a0f7a483793a4884fdd5b5e054d6 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 1 Oct 2023 15:11:07 +0200 Subject: [PATCH 06/20] Add blank ComputeSharp.D2D1.CodeFixers project --- ComputeSharp.sln | 12 +++++++++++- build/Directory.Build.props | 2 +- .../ComputeSharp.D2D1.CodeFixers.csproj | 7 +++++++ src/Directory.Build.props | 4 ++-- 4 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 src/ComputeSharp.D2D1.CodeFixers/ComputeSharp.D2D1.CodeFixers.csproj diff --git a/ComputeSharp.sln b/ComputeSharp.sln index a6a67a140..6e30315eb 100644 --- a/ComputeSharp.sln +++ b/ComputeSharp.sln @@ -156,7 +156,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComputeSharp.D2D1.Uwp.Tests EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComputeSharp.D2D1.WinUI.Tests", "tests\ComputeSharp.D2D1.WinUI.Tests\ComputeSharp.D2D1.WinUI.Tests.csproj", "{73C32D0F-64DB-4674-84E9-8FCC41228474}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComputeSharp.D3D12MemoryAllocator", "src\ComputeSharp.D3D12MemoryAllocator\ComputeSharp.D3D12MemoryAllocator.csproj", "{E017B3B6-C7D3-4E53-A7F6-1036178E98C3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComputeSharp.D3D12MemoryAllocator", "src\ComputeSharp.D3D12MemoryAllocator\ComputeSharp.D3D12MemoryAllocator.csproj", "{E017B3B6-C7D3-4E53-A7F6-1036178E98C3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComputeSharp.D2D1.CodeFixers", "src\ComputeSharp.D2D1.CodeFixers\ComputeSharp.D2D1.CodeFixers.csproj", "{54654960-54B5-4E19-B3ED-993591CA39E5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -454,6 +456,14 @@ Global {E017B3B6-C7D3-4E53-A7F6-1036178E98C3}.Release|ARM64.Build.0 = Release|Any CPU {E017B3B6-C7D3-4E53-A7F6-1036178E98C3}.Release|x64.ActiveCfg = Release|Any CPU {E017B3B6-C7D3-4E53-A7F6-1036178E98C3}.Release|x64.Build.0 = Release|Any CPU + {54654960-54B5-4E19-B3ED-993591CA39E5}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {54654960-54B5-4E19-B3ED-993591CA39E5}.Debug|ARM64.Build.0 = Debug|Any CPU + {54654960-54B5-4E19-B3ED-993591CA39E5}.Debug|x64.ActiveCfg = Debug|Any CPU + {54654960-54B5-4E19-B3ED-993591CA39E5}.Debug|x64.Build.0 = Debug|Any CPU + {54654960-54B5-4E19-B3ED-993591CA39E5}.Release|ARM64.ActiveCfg = Release|Any CPU + {54654960-54B5-4E19-B3ED-993591CA39E5}.Release|ARM64.Build.0 = Release|Any CPU + {54654960-54B5-4E19-B3ED-993591CA39E5}.Release|x64.ActiveCfg = Release|Any CPU + {54654960-54B5-4E19-B3ED-993591CA39E5}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/build/Directory.Build.props b/build/Directory.Build.props index a9bcf4a60..9381df45e 100644 --- a/build/Directory.Build.props +++ b/build/Directory.Build.props @@ -141,7 +141,7 @@ $([MSBuild]::MakeRelative('$(MSBuildThisFileDirectory)..\', $(MSBuildProjectDirectory))) $(ProjectDirectoryPathFromSourceRoot.StartsWith('src\')) false - true + true false true $(ProjectDirectoryPathFromSourceRoot.StartsWith('tests\')) diff --git a/src/ComputeSharp.D2D1.CodeFixers/ComputeSharp.D2D1.CodeFixers.csproj b/src/ComputeSharp.D2D1.CodeFixers/ComputeSharp.D2D1.CodeFixers.csproj new file mode 100644 index 000000000..9f5c4f4ab --- /dev/null +++ b/src/ComputeSharp.D2D1.CodeFixers/ComputeSharp.D2D1.CodeFixers.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 8395dc9ca..8c96bd8c6 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -76,9 +76,9 @@ - + all build;analyzers From caf35addfacef9531bdee809c53575278d53700b Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 1 Oct 2023 15:34:21 +0200 Subject: [PATCH 07/20] Add MissingPixelShaderDescriptorOnPixelShaderCodeFixer --- .../ComputeSharp.D2D1.CodeFixers.csproj | 8 +- ...lShaderDescriptorOnPixelShaderCodeFixer.cs | 74 +++++++++++++++++++ .../ComputeSharp.D2D1.SourceGenerators.csproj | 5 ++ src/Directory.Build.props | 2 +- .../ComputeSharp.D2D1.Tests.csproj | 1 + 5 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs diff --git a/src/ComputeSharp.D2D1.CodeFixers/ComputeSharp.D2D1.CodeFixers.csproj b/src/ComputeSharp.D2D1.CodeFixers/ComputeSharp.D2D1.CodeFixers.csproj index 9f5c4f4ab..41ca05c4e 100644 --- a/src/ComputeSharp.D2D1.CodeFixers/ComputeSharp.D2D1.CodeFixers.csproj +++ b/src/ComputeSharp.D2D1.CodeFixers/ComputeSharp.D2D1.CodeFixers.csproj @@ -1,7 +1,13 @@ - netstandard2.0 + + + + + + + diff --git a/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs b/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs new file mode 100644 index 000000000..61e775e8d --- /dev/null +++ b/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs @@ -0,0 +1,74 @@ +using System.Collections.Immutable; +using System.Composition; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.Text; +using static ComputeSharp.SourceGeneration.Diagnostics.DiagnosticDescriptors; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace ComputeSharp.D2D1.CodeFixers; + +/// +/// A code fixer that adds the [D2DGeneratedPixelShaderDescriptor] to D2D1 shader types with no descriptor. +/// +[ExportCodeFixProvider(LanguageNames.CSharp)] +[Shared] +public sealed class MissingPixelShaderDescriptorOnPixelShaderCodeFixer : CodeFixProvider +{ + /// + public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(MissingPixelShaderDescriptorOnPixelShaderTypeId); + + /// + public override FixAllProvider? GetFixAllProvider() + { + return WellKnownFixAllProviders.BatchFixer; + } + + /// + public override async Task RegisterCodeFixesAsync(CodeFixContext context) + { + Diagnostic diagnostic = context.Diagnostics[0]; + TextSpan diagnosticSpan = context.Span; + + SyntaxNode? root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); + + // Get the struct declaration from the target diagnostic + if (root!.FindNode(diagnosticSpan) is StructDeclarationSyntax structDeclaration) + { + // Register the code fix to update the return type to be Task instead + context.RegisterCodeFix( + CodeAction.Create( + title: "Add [D2DGeneratedPixelShaderDescriptor] attribute", + createChangedDocument: token => ChangeReturnType(context.Document, root, structDeclaration, token), + equivalenceKey: "Add [D2DGeneratedPixelShaderDescriptor] attribute"), + diagnostic); + } + } + + /// + /// Applies the code fix to add the [D2DGeneratedPixelShaderDescriptor] attribute to a target type. + /// + /// The original document being fixed. + /// The original tree root belonging to the current document. + /// The to update. + /// The cancellation token for the operation. + /// An updated document with the applied code fix, and the return type of the method being . + private static Task ChangeReturnType(Document document, SyntaxNode root, StructDeclarationSyntax structDeclaration, CancellationToken cancellationToken) + { + // Create the attribute syntax + AttributeListSyntax attributeList = AttributeList(SingletonSeparatedList(Attribute(IdentifierName("D2DGeneratedPixelShaderDescriptor")))); + + // Create a new syntax node with the new attribute + SyntaxNode typeSyntax = SyntaxGenerator.GetGenerator(document).AddAttributes(structDeclaration, attributeList); + + // Replace the node in the document tree + Document updatedDocument = document.WithSyntaxRoot(root.ReplaceNode(structDeclaration, typeSyntax)); + + return Task.FromResult(updatedDocument); + } +} diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ComputeSharp.D2D1.SourceGenerators.csproj b/src/ComputeSharp.D2D1.SourceGenerators/ComputeSharp.D2D1.SourceGenerators.csproj index 8240a9ff3..934ad6442 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ComputeSharp.D2D1.SourceGenerators.csproj +++ b/src/ComputeSharp.D2D1.SourceGenerators/ComputeSharp.D2D1.SourceGenerators.csproj @@ -108,4 +108,9 @@ + + + + + diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 8c96bd8c6..98b026937 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -78,7 +78,7 @@ Reference PolySharp for all .NET Standard 2.0 polyfills. Only needed for the .Core project and all analyzers. --> - + all build;analyzers diff --git a/tests/ComputeSharp.D2D1.Tests/ComputeSharp.D2D1.Tests.csproj b/tests/ComputeSharp.D2D1.Tests/ComputeSharp.D2D1.Tests.csproj index db4c547d9..a6633afc5 100644 --- a/tests/ComputeSharp.D2D1.Tests/ComputeSharp.D2D1.Tests.csproj +++ b/tests/ComputeSharp.D2D1.Tests/ComputeSharp.D2D1.Tests.csproj @@ -20,6 +20,7 @@ + From 80221ce0cd11348fedfd193ad437fe8ed194571a Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 1 Oct 2023 15:49:49 +0200 Subject: [PATCH 08/20] Update code fixer to add attribute right after D2D ones --- ...lShaderDescriptorOnPixelShaderCodeFixer.cs | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs b/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs index 61e775e8d..2f091f3aa 100644 --- a/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs +++ b/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs @@ -60,11 +60,42 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) /// An updated document with the applied code fix, and the return type of the method being . private static Task ChangeReturnType(Document document, SyntaxNode root, StructDeclarationSyntax structDeclaration, CancellationToken cancellationToken) { - // Create the attribute syntax - AttributeListSyntax attributeList = AttributeList(SingletonSeparatedList(Attribute(IdentifierName("D2DGeneratedPixelShaderDescriptor")))); + int index = 0; + + // Find the index to use to insert the attribute. We want to make it so that if the struct declaration + // has a bunch of D2D attributes, the new one will be inserted right after that. This way the final list + // will be nicely sorted, instead of having D2D attributes interleaving other unrelated attributes, if any. + foreach (AttributeListSyntax attributeList in structDeclaration.AttributeLists) + { + // Make sure we have an attribute to check + if (attributeList.Attributes is not [AttributeSyntax attribute, ..]) + { + continue; + } + + // Make sure we find a readable identifier for the attribute + if (attribute.Name is not IdentifierNameSyntax { Identifier.Value: string identifier }) + { + break; + } + + // If the attribute is D2D one, increment the index and continue + if (identifier.Contains("D2D")) + { + index++; + } + else + { + // Otherwise, stop here, we reached the end of the sequence + break; + } + } + + // Create the attribute syntax for the new attribute + AttributeListSyntax newAttributeList = AttributeList(SingletonSeparatedList(Attribute(IdentifierName("D2DGeneratedPixelShaderDescriptor")))); // Create a new syntax node with the new attribute - SyntaxNode typeSyntax = SyntaxGenerator.GetGenerator(document).AddAttributes(structDeclaration, attributeList); + SyntaxNode typeSyntax = SyntaxGenerator.GetGenerator(document).InsertAttributes(structDeclaration, index, newAttributeList); // Replace the node in the document tree Document updatedDocument = document.WithSyntaxRoot(root.ReplaceNode(structDeclaration, typeSyntax)); From ec77fb7e6f3aebc7479618280baada5f2930a122 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 1 Oct 2023 16:10:20 +0200 Subject: [PATCH 09/20] Rename D2D1 generator file names and generated name --- ...erator.CreateFromConstantBuffer.Syntax.cs} | 4 +-- ...derDescriptorGenerator.EffectId.Syntax.cs} | 4 +-- ...ixelShaderDescriptorGenerator.EffectId.cs} | 2 +- ...criptorGenerator.EffectMetadata.Syntax.cs} | 4 +-- ...aderDescriptorGenerator.EffectMetadata.cs} | 2 +- ...escriptorGenerator.HlslBytecode.Syntax.cs} | 10 +++--- ...ShaderDescriptorGenerator.HlslBytecode.cs} | 2 +- ...rDescriptorGenerator.HlslSource.Syntax.cs} | 4 +-- ...elShaderDescriptorGenerator.HlslSource.cs} | 2 +- ...ptorGenerator.InputDescriptions.Syntax.cs} | 6 ++-- ...rDescriptorGenerator.InputDescriptions.cs} | 2 +- ...rDescriptorGenerator.InputTypes.Syntax.cs} | 6 ++-- ...elShaderDescriptorGenerator.InputTypes.cs} | 2 +- ...torGenerator.LoadConstantBuffer.Syntax.cs} | 6 ++-- ...DescriptorGenerator.LoadConstantBuffer.cs} | 2 +- ...ptorGenerator.NumericProperties.Syntax.cs} | 8 ++--- ...escriptorGenerator.OutputBuffer.Syntax.cs} | 6 ++-- ...ShaderDescriptorGenerator.OutputBuffer.cs} | 2 +- ...escriptorGenerator.PixelOptions.Syntax.cs} | 4 +-- ...ShaderDescriptorGenerator.PixelOptions.cs} | 2 +- ...tor.ResourceTextureDescriptions.Syntax.cs} | 4 +-- ...rGenerator.ResourceTextureDescriptions.cs} | 2 +- ...s => D2DPixelShaderDescriptorGenerator.cs} | 13 +++++--- ...eUninitializedFieldDiagnosticSuppressor.cs | 6 ++-- .../ID2D1ShaderGenerator.Helpers.cs | 31 ------------------- .../IndentedTextWriterExtensions.cs | 12 ++++--- 26 files changed, 62 insertions(+), 86 deletions(-) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateCreateFromConstantBufferMethod.Syntax.cs => D2DPixelShaderDescriptorGenerator.CreateFromConstantBuffer.Syntax.cs} (97%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateEffectIdProperty.Syntax.cs => D2DPixelShaderDescriptorGenerator.EffectId.Syntax.cs} (97%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateEffectIdProperty.cs => D2DPixelShaderDescriptorGenerator.EffectId.cs} (99%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateEffectMetadataProperties.Syntax.cs => D2DPixelShaderDescriptorGenerator.EffectMetadata.Syntax.cs} (97%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateEffectMetadataProperties.cs => D2DPixelShaderDescriptorGenerator.EffectMetadata.cs} (98%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateHlslBytecodeProperties.Syntax.cs => D2DPixelShaderDescriptorGenerator.HlslBytecode.Syntax.cs} (95%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateHlslBytecodeProperties.cs => D2DPixelShaderDescriptorGenerator.HlslBytecode.cs} (99%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateHlslSourceProperty.Syntax.cs => D2DPixelShaderDescriptorGenerator.HlslSource.Syntax.cs} (91%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateHlslSourceProperty.cs => D2DPixelShaderDescriptorGenerator.HlslSource.cs} (99%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateInputDescriptionsProperty.Syntax.cs => D2DPixelShaderDescriptorGenerator.InputDescriptions.Syntax.cs} (96%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateInputDescriptionsProperty.cs => D2DPixelShaderDescriptorGenerator.InputDescriptions.cs} (98%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateInputTypesProperty.Syntax.cs => D2DPixelShaderDescriptorGenerator.InputTypes.Syntax.cs} (96%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateInputTypesProperty.cs => D2DPixelShaderDescriptorGenerator.InputTypes.cs} (99%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateLoadConstantBufferMethod.Syntax.cs => D2DPixelShaderDescriptorGenerator.LoadConstantBuffer.Syntax.cs} (97%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateLoadConstantBufferMethod.cs => D2DPixelShaderDescriptorGenerator.LoadConstantBuffer.cs} (99%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateNumericProperties.Syntax.cs => D2DPixelShaderDescriptorGenerator.NumericProperties.Syntax.cs} (90%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateOutputBufferProperties.Syntax.cs => D2DPixelShaderDescriptorGenerator.OutputBuffer.Syntax.cs} (93%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateOutputBufferProperties.cs => D2DPixelShaderDescriptorGenerator.OutputBuffer.cs} (98%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreatePixelOptionsProperty.Syntax.cs => D2DPixelShaderDescriptorGenerator.PixelOptions.Syntax.cs} (92%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreatePixelOptionsProperty.cs => D2DPixelShaderDescriptorGenerator.PixelOptions.cs} (95%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateResourceTextureDescriptionsProperty.Syntax.cs => D2DPixelShaderDescriptorGenerator.ResourceTextureDescriptions.Syntax.cs} (97%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateResourceTextureDescriptionsProperty.cs => D2DPixelShaderDescriptorGenerator.ResourceTextureDescriptions.cs} (99%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.cs => D2DPixelShaderDescriptorGenerator.cs} (95%) delete mode 100644 src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.Helpers.cs diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateCreateFromConstantBufferMethod.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.CreateFromConstantBuffer.Syntax.cs similarity index 97% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateCreateFromConstantBufferMethod.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.CreateFromConstantBuffer.Syntax.cs index aa1be8d8b..333864120 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateCreateFromConstantBufferMethod.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.CreateFromConstantBuffer.Syntax.cs @@ -6,7 +6,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// partial class CreateFromConstantBuffer @@ -21,7 +21,7 @@ public static void WriteSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) string typeName = info.Hierarchy.Hierarchy[0].QualifiedName; writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.WriteLine("[global::System.Runtime.CompilerServices.SkipLocalsInit]"); writer.WriteLine($"readonly unsafe {typeName} global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{typeName}>.CreateFromConstantBuffer(global::System.ReadOnlySpan data)"); diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateEffectIdProperty.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.EffectId.Syntax.cs similarity index 97% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateEffectIdProperty.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.EffectId.Syntax.cs index 1a783458f..7d4f82843 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateEffectIdProperty.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.EffectId.Syntax.cs @@ -5,7 +5,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// partial class EffectId @@ -18,7 +18,7 @@ partial class EffectId public static void WriteSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) { writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.WriteLine($"readonly ref readonly global::System.Guid global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.EffectId"); using (writer.WriteBlock()) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateEffectIdProperty.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.EffectId.cs similarity index 99% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateEffectIdProperty.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.EffectId.cs index a38c5f47d..c57150184 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateEffectIdProperty.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.EffectId.cs @@ -11,7 +11,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// /// A helper with all logic to generate the EffectId property. diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateEffectMetadataProperties.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.EffectMetadata.Syntax.cs similarity index 97% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateEffectMetadataProperties.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.EffectMetadata.Syntax.cs index 860de917c..954b31662 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateEffectMetadataProperties.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.EffectMetadata.Syntax.cs @@ -5,7 +5,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// partial class EffectMetadata @@ -60,7 +60,7 @@ public static void WriteEffectAuthorSyntax(D2D1ShaderInfo info, IndentedTextWrit private static void WriteEffectMetadataSyntax(string qualifiedName, string propertyName, string? metadataValue, IndentedTextWriter writer) { writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.Write($"readonly string? global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{qualifiedName}>.{propertyName} => "); // Append null or the metadata value as a string literal diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateEffectMetadataProperties.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.EffectMetadata.cs similarity index 98% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateEffectMetadataProperties.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.EffectMetadata.cs index d2158878d..5ffcb5024 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateEffectMetadataProperties.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.EffectMetadata.cs @@ -4,7 +4,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// /// A helper with all logic to generate the effect metadata properties. diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateHlslBytecodeProperties.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.Syntax.cs similarity index 95% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateHlslBytecodeProperties.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.Syntax.cs index 6c2b84c7c..242f61b52 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateHlslBytecodeProperties.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.Syntax.cs @@ -7,7 +7,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// partial class HlslBytecode @@ -20,7 +20,7 @@ partial class HlslBytecode public static void WriteShaderProfileSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) { writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.WriteLine($"readonly ComputeSharp.D2D1.D2D1ShaderProfile global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.ShaderProfile => global::ComputeSharp.D2D1.D2D1ShaderProfile.{info.HlslInfoKey.EffectiveShaderProfile};"); } @@ -40,7 +40,7 @@ public static void WriteCompileOptionsSyntax(D2D1ShaderInfo info, IndentedTextWr .Aggregate("", static (left, right) => left.Length > 0 ? $"{left} | {right}" : right); writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.WriteLine($"readonly ComputeSharp.D2D1.D2D1CompileOptions global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.CompileOptions => {compileOptionsExpression};"); } @@ -52,7 +52,7 @@ public static void WriteCompileOptionsSyntax(D2D1ShaderInfo info, IndentedTextWr public static void WriteHlslBytecodeSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) { writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.Write($"readonly global::System.ReadOnlyMemory global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.HlslBytecode => "); // If there is no bytecode, just return a default expression. @@ -98,7 +98,7 @@ static void Callback(D2D1ShaderInfo info, IndentedTextWriter writer) writer.WriteLine($$"""/// """); writer.WriteLine($$"""/// implementation to get the HLSL bytecode."""); writer.WriteLine($$"""/// """); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator), useFullyQualifiedTypeNames: false); + writer.WriteGeneratedAttributes(GeneratorName, useFullyQualifiedTypeNames: false); writer.WriteLine($$"""file sealed class HlslBytecodeMemoryManager : MemoryManager"""); using (writer.WriteBlock()) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateHlslBytecodeProperties.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.cs similarity index 99% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateHlslBytecodeProperties.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.cs index fcf764fae..3784f2e26 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateHlslBytecodeProperties.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.cs @@ -18,7 +18,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// /// A helper with all logic to generate the HLSL bytecode properties. diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateHlslSourceProperty.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslSource.Syntax.cs similarity index 91% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateHlslSourceProperty.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslSource.Syntax.cs index b065bca39..b9650bea7 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateHlslSourceProperty.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslSource.Syntax.cs @@ -5,7 +5,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// partial class HlslSource @@ -18,7 +18,7 @@ partial class HlslSource public static void WriteSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) { writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.WriteLine($"readonly string global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.HlslSource =>"); writer.IncreaseIndent(); writer.WriteLine("\"\"\""); diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateHlslSourceProperty.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslSource.cs similarity index 99% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateHlslSourceProperty.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslSource.cs index 73ece91a3..bf547c42c 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateHlslSourceProperty.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslSource.cs @@ -17,7 +17,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// /// A helper with all logic to generate the HlslSource property. diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputDescriptionsProperty.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.InputDescriptions.Syntax.cs similarity index 96% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputDescriptionsProperty.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.InputDescriptions.Syntax.cs index f7bde651e..c2a6b125e 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputDescriptionsProperty.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.InputDescriptions.Syntax.cs @@ -7,7 +7,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// private static partial class InputDescriptions @@ -20,7 +20,7 @@ private static partial class InputDescriptions public static void WriteSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) { writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.Write($"readonly global::System.ReadOnlyMemory global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.InputDescriptions => "); // If there are no input descriptions, just return a default expression. @@ -66,7 +66,7 @@ static void Callback(D2D1ShaderInfo info, IndentedTextWriter writer) writer.WriteLine($$"""/// """); writer.WriteLine($$"""/// A container type for additional data needed by the shader."""); writer.WriteLine($$"""/// """); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator), useFullyQualifiedTypeNames: false); + writer.WriteGeneratedAttributes(GeneratorName, useFullyQualifiedTypeNames: false); writer.WriteLine($$"""file static class Data"""); using (writer.WriteBlock()) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputDescriptionsProperty.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.InputDescriptions.cs similarity index 98% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputDescriptionsProperty.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.InputDescriptions.cs index dbe31d176..f6786a195 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputDescriptionsProperty.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.InputDescriptions.cs @@ -10,7 +10,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// /// A helper with all logic to generate the InputDescriptions property. diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputTypesProperty.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.InputTypes.Syntax.cs similarity index 96% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputTypesProperty.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.InputTypes.Syntax.cs index 4774ef8f1..5c0255fba 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputTypesProperty.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.InputTypes.Syntax.cs @@ -5,7 +5,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// partial class InputTypes @@ -18,7 +18,7 @@ partial class InputTypes public static void WriteSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) { writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.Write($"readonly global::System.ReadOnlyMemory global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.InputTypes => "); // If there are no inputs, simply return a default expression. Otherwise, create @@ -65,7 +65,7 @@ static void Callback(D2D1ShaderInfo info, IndentedTextWriter writer) writer.WriteLine($$"""/// """); writer.WriteLine($$"""/// A implementation to get the input types."""); writer.WriteLine($$"""/// """); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator), useFullyQualifiedTypeNames: false); + writer.WriteGeneratedAttributes(GeneratorName, useFullyQualifiedTypeNames: false); writer.WriteLine($$"""file sealed class InputTypesMemoryManager : MemoryManager"""); using (writer.WriteBlock()) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputTypesProperty.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.InputTypes.cs similarity index 99% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputTypesProperty.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.InputTypes.cs index 7b2d19a7e..74e902d8f 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputTypesProperty.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.InputTypes.cs @@ -9,7 +9,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// /// A helper with all logic to generate the InputTypes properties. diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadConstantBufferMethod.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.LoadConstantBuffer.Syntax.cs similarity index 97% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadConstantBufferMethod.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.LoadConstantBuffer.Syntax.cs index 04fa769a2..a6232d492 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadConstantBufferMethod.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.LoadConstantBuffer.Syntax.cs @@ -6,7 +6,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// partial class LoadConstantBuffer @@ -21,7 +21,7 @@ public static void WriteSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) string typeName = info.Hierarchy.Hierarchy[0].QualifiedName; writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.WriteLine("[global::System.Runtime.CompilerServices.SkipLocalsInit]"); writer.WriteLine($"readonly unsafe void global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{typeName}>.LoadConstantBuffer(in {typeName} shader, ref TLoader loader)"); @@ -105,7 +105,7 @@ static void Callback(D2D1ShaderInfo info, IndentedTextWriter writer) writer.WriteLine($$"""/// """); writer.WriteLine($$"""/// A type representing the constant buffer native layout for ."""); writer.WriteLine($$"""/// """); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator), useFullyQualifiedTypeNames: false); + writer.WriteGeneratedAttributes(GeneratorName, useFullyQualifiedTypeNames: false); writer.WriteLine($$"""[StructLayout(LayoutKind.Explicit, Size = {{info.ConstantBufferSizeInBytes}})]"""); writer.WriteLine($$"""file struct ConstantBuffer"""); diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadConstantBufferMethod.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.LoadConstantBuffer.cs similarity index 99% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadConstantBufferMethod.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.LoadConstantBuffer.cs index dc12107f4..b950c73be 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadConstantBufferMethod.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.LoadConstantBuffer.cs @@ -15,7 +15,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// /// A helper with all logic to generate the LoadConstantBuffer method. diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateNumericProperties.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.NumericProperties.Syntax.cs similarity index 90% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateNumericProperties.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.NumericProperties.Syntax.cs index 4c9ca529a..a4896594b 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateNumericProperties.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.NumericProperties.Syntax.cs @@ -5,7 +5,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// /// A helper with all logic to generate the available numeric properties. @@ -20,7 +20,7 @@ private static partial class NumericProperties public static void WriteConstantBufferSizeSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) { writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.WriteLine($"readonly int global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.ConstantBufferSize => {info.ConstantBufferSizeInBytes};"); } @@ -32,7 +32,7 @@ public static void WriteConstantBufferSizeSyntax(D2D1ShaderInfo info, IndentedTe public static void WriteInputCountSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) { writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.WriteLine($"readonly int global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.InputCount => {info.InputTypes.Length};"); } @@ -44,7 +44,7 @@ public static void WriteInputCountSyntax(D2D1ShaderInfo info, IndentedTextWriter public static void WriteResourceTextureCountSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) { writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.WriteLine($"readonly int global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.ResourceTextureCount => {info.ResourceTextureDescriptions.Length};"); } } diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateOutputBufferProperties.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.OutputBuffer.Syntax.cs similarity index 93% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateOutputBufferProperties.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.OutputBuffer.Syntax.cs index 6d536f8cf..3767bb783 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateOutputBufferProperties.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.OutputBuffer.Syntax.cs @@ -6,7 +6,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// partial class OutputBuffer @@ -27,7 +27,7 @@ public static void WriteBufferPrecisionSyntax(D2D1ShaderInfo info, IndentedTextW }; writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.WriteLine($"readonly ComputeSharp.D2D1.D2D1BufferPrecision global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.BufferPrecision => {bufferPrecisionExpression};"); } @@ -46,7 +46,7 @@ public static void WriteChannelDepthSyntax(D2D1ShaderInfo info, IndentedTextWrit }; writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.WriteLine($"readonly ComputeSharp.D2D1.D2D1ChannelDepth global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.ChannelDepth => {channelDepthExpression};"); } } diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateOutputBufferProperties.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.OutputBuffer.cs similarity index 98% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateOutputBufferProperties.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.OutputBuffer.cs index 9c01e195c..aae4ada1b 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateOutputBufferProperties.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.OutputBuffer.cs @@ -4,7 +4,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// /// A helper with all logic to generate the output buffer properties. diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreatePixelOptionsProperty.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.PixelOptions.Syntax.cs similarity index 92% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreatePixelOptionsProperty.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.PixelOptions.Syntax.cs index a87afa5a2..a469a3421 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreatePixelOptionsProperty.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.PixelOptions.Syntax.cs @@ -5,7 +5,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// partial class PixelOptions @@ -25,7 +25,7 @@ public static void WriteSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) }; writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.WriteLine($"readonly ComputeSharp.D2D1.D2D1PixelOptions global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.PixelOptions => {pixelOptionsExpression};"); } } diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreatePixelOptionsProperty.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.PixelOptions.cs similarity index 95% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreatePixelOptionsProperty.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.PixelOptions.cs index 089078150..5c9743521 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreatePixelOptionsProperty.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.PixelOptions.cs @@ -4,7 +4,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// /// A helper with all logic to generate the PixelOptions property. diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateResourceTextureDescriptionsProperty.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.ResourceTextureDescriptions.Syntax.cs similarity index 97% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateResourceTextureDescriptionsProperty.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.ResourceTextureDescriptions.Syntax.cs index 94d202a3a..d0bb8a8b5 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateResourceTextureDescriptionsProperty.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.ResourceTextureDescriptions.Syntax.cs @@ -7,7 +7,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// private static partial class ResourceTextureDescriptions @@ -20,7 +20,7 @@ private static partial class ResourceTextureDescriptions public static void WriteSyntax(D2D1ShaderInfo info, IndentedTextWriter writer) { writer.WriteLine("/// "); - writer.WriteGeneratedAttributes(typeof(ID2D1ShaderGenerator)); + writer.WriteGeneratedAttributes(GeneratorName); writer.Write($"readonly global::System.ReadOnlyMemory global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.ResourceTextureDescriptions => "); // If there are no resource texture descriptions, just return a default expression. diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateResourceTextureDescriptionsProperty.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.ResourceTextureDescriptions.cs similarity index 99% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateResourceTextureDescriptionsProperty.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.ResourceTextureDescriptions.cs index 79dbdce9e..6282b6066 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateResourceTextureDescriptionsProperty.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.ResourceTextureDescriptions.cs @@ -11,7 +11,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -partial class ID2D1ShaderGenerator +partial class D2DPixelShaderDescriptorGenerator { /// /// A helper with all logic to generate the ResourceTextureDescriptions property. diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.cs similarity index 95% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs rename to src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.cs index 50a3fd9e9..9f83daa72 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.cs @@ -10,11 +10,16 @@ namespace ComputeSharp.D2D1.SourceGenerators; /// -/// A source generator creating data loaders for the type. +/// A source generator creating pixel shader descriptors for annotated D2D1 pixel shader types. /// [Generator(LanguageNames.CSharp)] -public sealed partial class ID2D1ShaderGenerator : IIncrementalGenerator +public sealed partial class D2DPixelShaderDescriptorGenerator : IIncrementalGenerator { + /// + /// The name of generator to include in the generated code. + /// + private const string GeneratorName = "ComputeSharp.D2D1.D2DPixelShaderDescriptorGenerator"; + /// public void Initialize(IncrementalGeneratorInitializationContext context) { @@ -41,7 +46,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) StructDeclarationSyntax typeDeclaration = (StructDeclarationSyntax)context.TargetNode; // Check that the shader implements the ID2D1PixelShader interface - if (!IsD2D1PixelShaderType(typeSymbol, context.SemanticModel.Compilation)) + if (!typeSymbol.HasInterfaceWithType(context.SemanticModel.Compilation.GetTypeByMetadataName("ComputeSharp.D2D1.ID2D1PixelShader")!)) { return default; } @@ -151,7 +156,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) effectiveCompileOptions, hasErrors); - // TODO: cache this across transform runs + // Get the existing compiled shader, or compile the processed HLSL code HlslBytecodeInfo hlslInfo = HlslBytecode.GetInfo(ref hlslInfoKey, token); token.ThrowIfCancellationRequested(); diff --git a/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/Suppressors/D2D1ResourceTextureUninitializedFieldDiagnosticSuppressor.cs b/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/Suppressors/D2D1ResourceTextureUninitializedFieldDiagnosticSuppressor.cs index a570e68f7..664da5675 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/Suppressors/D2D1ResourceTextureUninitializedFieldDiagnosticSuppressor.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/Suppressors/D2D1ResourceTextureUninitializedFieldDiagnosticSuppressor.cs @@ -52,15 +52,13 @@ public override void ReportSuppressions(SuppressionAnalysisContext context) HlslKnownTypes.IsResourceTextureType(fieldSymbol.Type.GetFullyQualifiedMetadataName())) { // Get the ID2D1PixelShader interface symbol to the check the containing type of the field - INamedTypeSymbol? pixelShaderInterfaceSymbol = semanticModel.Compilation.GetTypeByMetadataName(typeof(ID2D1PixelShader).FullName)!; - - if (pixelShaderInterfaceSymbol is null) + if (semanticModel.Compilation.GetTypeByMetadataName("ComputeSharp.D2D1.ID2D1PixelShader") is not { } d2D1PixelShaderSymbol) { continue; } // Also check if the containing type is in fact a D2D1 pixel shader type - if (ID2D1ShaderGenerator.IsD2D1PixelShaderType(structSymbol, semanticModel.Compilation)) + if (structSymbol.HasInterfaceWithType(d2D1PixelShaderSymbol)) { context.ReportSuppression(Suppression.Create(UninitializedD2D1ResourceTextureField, diagnostic)); } diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.Helpers.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.Helpers.cs deleted file mode 100644 index ff29a0e69..000000000 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.Helpers.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.CodeAnalysis; - -namespace ComputeSharp.D2D1.SourceGenerators; - -/// -partial class ID2D1ShaderGenerator -{ - /// - /// Gets the shader type for a given shader, if any. - /// - /// The input instance to check. - /// The instance currently in use. - /// Whether or not is a D2D1 interface type. - public static bool IsD2D1PixelShaderType(INamedTypeSymbol typeSymbol, Compilation compilation) - { - foreach (INamedTypeSymbol interfaceSymbol in typeSymbol.AllInterfaces) - { - if (interfaceSymbol.Name == nameof(ID2D1PixelShader)) - { - INamedTypeSymbol d2D1PixelShaderSymbol = compilation.GetTypeByMetadataName("ComputeSharp.D2D1.ID2D1PixelShader")!; - - if (SymbolEqualityComparer.Default.Equals(interfaceSymbol, d2D1PixelShaderSymbol)) - { - return true; - } - } - } - - return false; - } -} \ No newline at end of file diff --git a/src/ComputeSharp.SourceGeneration/Extensions/IndentedTextWriterExtensions.cs b/src/ComputeSharp.SourceGeneration/Extensions/IndentedTextWriterExtensions.cs index 9803e9981..262e6aa2b 100644 --- a/src/ComputeSharp.SourceGeneration/Extensions/IndentedTextWriterExtensions.cs +++ b/src/ComputeSharp.SourceGeneration/Extensions/IndentedTextWriterExtensions.cs @@ -17,19 +17,23 @@ internal static class IndentedTextWriterExtensions /// /// /// The instance to write into. - /// The type of the running generator. + /// The name of the generator. /// Whether to use fully qualified type names or not. - public static void WriteGeneratedAttributes(this IndentedTextWriter writer, Type generatorType, bool useFullyQualifiedTypeNames = true) + public static void WriteGeneratedAttributes(this IndentedTextWriter writer, string generatorName, bool useFullyQualifiedTypeNames = true) { + // We can use this class to get the assembly, as all files for generators are just included + // via shared projects. As such, the assembly will be the same as the generator type itself. + Version assemblyVersion = typeof(IndentedTextWriterExtensions).Assembly.GetName().Version; + if (useFullyQualifiedTypeNames) { - writer.WriteLine($$"""[global::System.CodeDom.Compiler.GeneratedCode("{{generatorType.FullName}}", "{{generatorType.Assembly.GetName().Version}}")]"""); + writer.WriteLine($$"""[global::System.CodeDom.Compiler.GeneratedCode("{{generatorName}}", "{{assemblyVersion}}")]"""); writer.WriteLine($$"""[global::System.Diagnostics.DebuggerNonUserCode]"""); writer.WriteLine($$"""[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]"""); } else { - writer.WriteLine($$"""[GeneratedCode("{{generatorType.FullName}}", "{{generatorType.Assembly.GetName().Version}}")]"""); + writer.WriteLine($$"""[GeneratedCode("{{generatorName}}", "{{assemblyVersion}}")]"""); writer.WriteLine($$"""[DebuggerNonUserCode]"""); writer.WriteLine($$"""[ExcludeFromCodeCoverage]"""); } From afb467f1ff623377b136d6a0a455464a6bdd51c5 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 1 Oct 2023 16:17:08 +0200 Subject: [PATCH 10/20] Add InvalidD2DGeneratedPixelShaderDescriptorAttributeTargetAnalyzer --- .../AnalyzerReleases.Shipped.md | 1 + ...ShaderDescriptorAttributeTargetAnalyzer.cs | 53 +++++++++++++++++++ .../Diagnostics/DiagnosticDescriptors.cs | 16 ++++++ .../Effects/PixelateEffect.cs | 1 - 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/Analyzers/InvalidD2DGeneratedPixelShaderDescriptorAttributeTargetAnalyzer.cs diff --git a/src/ComputeSharp.D2D1.SourceGenerators/AnalyzerReleases.Shipped.md b/src/ComputeSharp.D2D1.SourceGenerators/AnalyzerReleases.Shipped.md index 947bb3591..53d2153b9 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/AnalyzerReleases.Shipped.md +++ b/src/ComputeSharp.D2D1.SourceGenerators/AnalyzerReleases.Shipped.md @@ -72,3 +72,4 @@ CMPSD2D0062 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github CMPSD2D0063 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github.com/Sergio0694/ComputeSharp) CMPSD2D0064 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github.com/Sergio0694/ComputeSharp) CMPSD2D0065 | ComputeSharp.D2D1.Shaders | Warning | [Documentation](https://github.com/Sergio0694/ComputeSharp) +CMPSD2D0066 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github.com/Sergio0694/ComputeSharp) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/Analyzers/InvalidD2DGeneratedPixelShaderDescriptorAttributeTargetAnalyzer.cs b/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/Analyzers/InvalidD2DGeneratedPixelShaderDescriptorAttributeTargetAnalyzer.cs new file mode 100644 index 000000000..4dc12f691 --- /dev/null +++ b/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/Analyzers/InvalidD2DGeneratedPixelShaderDescriptorAttributeTargetAnalyzer.cs @@ -0,0 +1,53 @@ +using System.Collections.Immutable; +using ComputeSharp.SourceGeneration.Extensions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using static ComputeSharp.SourceGeneration.Diagnostics.DiagnosticDescriptors; + +namespace ComputeSharp.D2D1.SourceGenerators; + +/// +/// A diagnostic analyzer that generates an error whenever the [D2DGeneratedPixelShaderDescriptor] attribute is used on an invalid target type. +/// +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class InvalidD2DGeneratedPixelShaderDescriptorAttributeTargetAnalyzer : DiagnosticAnalyzer +{ + /// + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(InvalidD2DGeneratedPixelShaderDescriptorAttributeTarget); + + /// + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); + context.EnableConcurrentExecution(); + + context.RegisterCompilationStartAction(static context => + { + // Get the ID2D1PixelShader and [D2DGeneratedPixelShaderDescriptor] symbols + if (context.Compilation.GetTypeByMetadataName("ComputeSharp.D2D1.ID2D1PixelShader") is not { } d2D1PixelShaderSymbol || + context.Compilation.GetTypeByMetadataName("ComputeSharp.D2D1.D2DGeneratedPixelShaderDescriptorAttribute") is not { } d2DGeneratedPixelShaderDescriptorAttributeSymbol) + { + return; + } + + context.RegisterSymbolAction(context => + { + // Only struct types are possible targets + if (context.Symbol is not INamedTypeSymbol { TypeKind: TypeKind.Struct } typeSymbol) + { + return; + } + + // Emit a diagnostic if the target type is using [D2DGeneratedPixelShaderDescriptor] but does not implement ID2D1PixelShader + if (typeSymbol.TryGetAttributeWithType(d2DGeneratedPixelShaderDescriptorAttributeSymbol, out AttributeData? attribute) && + !typeSymbol.HasInterfaceWithType(d2D1PixelShaderSymbol)) + { + context.ReportDiagnostic(Diagnostic.Create( + InvalidD2DGeneratedPixelShaderDescriptorAttributeTarget, + attribute.GetLocation(), + typeSymbol)); + } + }, SymbolKind.NamedType); + }); + } +} \ No newline at end of file diff --git a/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs b/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs index c4107fd70..7b8844205 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs @@ -976,4 +976,20 @@ partial class DiagnosticDescriptors description: "All D2D1 shader types must have an associated descriptor (it can be autogenerated via the [D2DGeneratedPixelShaderDescriptor] attribute).", helpLinkUri: "https://github.com/Sergio0694/ComputeSharp", customTags: WellKnownDiagnosticTags.CompilationEnd); + + /// + /// Gets a for when the [D2DGeneratedPixelShaderDescriptor] attribute is being used on an invalid target type. + /// + /// Format: "The type {0} is not a valid target for the [D2DGeneratedPixelShaderDescriptor] attribute (only types implementing the ID2D1PixelShader interface are valid)". + /// + /// + public static readonly DiagnosticDescriptor InvalidD2DGeneratedPixelShaderDescriptorAttributeTarget = new DiagnosticDescriptor( + id: "CMPSD2D0066", + title: "Invalid [D2DGeneratedPixelShaderDescriptor] attribute target", + messageFormat: "The type {0} is not a valid target for the [D2DGeneratedPixelShaderDescriptor] attribute (only types implementing ID2D1PixelShader interface are valid)", + category: "ComputeSharp.D2D1.Shaders", + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: "The [D2DGeneratedPixelShaderDescriptor] attribute must be used on types that implement the ID2D1PixelShader interface.", + helpLinkUri: "https://github.com/Sergio0694/ComputeSharp"); } \ No newline at end of file diff --git a/tests/ComputeSharp.D2D1.Tests/Effects/PixelateEffect.cs b/tests/ComputeSharp.D2D1.Tests/Effects/PixelateEffect.cs index fd5a28afb..3e9a9a4c3 100644 --- a/tests/ComputeSharp.D2D1.Tests/Effects/PixelateEffect.cs +++ b/tests/ComputeSharp.D2D1.Tests/Effects/PixelateEffect.cs @@ -8,7 +8,6 @@ namespace ComputeSharp.D2D1.Tests.Effects; [AutoConstructor] public readonly partial struct PixelateEffect : ID2D1PixelShader { - [D2DGeneratedPixelShaderDescriptor] [AutoConstructor] public readonly partial struct Constants { From a426bb74d75ae5b6049017535b9d8a130936377e Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 1 Oct 2023 16:30:03 +0200 Subject: [PATCH 11/20] Update shared .targets to also pack code fixer projects --- src/Directory.Build.targets | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 5fb368ada..a19860024 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -2,11 +2,18 @@ - + + + false true $(TargetFrameworks.Split(';')[0].Trim()) + + + false + true + $(TargetFrameworks.Split(';')[0].Trim()) @@ -24,6 +31,21 @@ Visible="false" /> + + + + + + + + + + - - false + + false - - true + + true false From 681e48d3fc94dc1e291e0aca2fd4de59989cf021 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 1 Oct 2023 18:34:27 +0200 Subject: [PATCH 14/20] Automatically add using directive from code fixer --- ...lShaderDescriptorOnPixelShaderCodeFixer.cs | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs b/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs index 02d00cf1a..056636921 100644 --- a/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs +++ b/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs @@ -1,14 +1,15 @@ using System.Collections.Immutable; using System.Composition; +using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; +using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Text; using static ComputeSharp.SourceGeneration.Diagnostics.DiagnosticDescriptors; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace ComputeSharp.D2D1.CodeFixers; @@ -43,7 +44,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix( CodeAction.Create( title: "Add [D2DGeneratedPixelShaderDescriptor] attribute", - createChangedDocument: token => ChangeReturnType(context.Document, root, structDeclaration), + createChangedDocument: token => ChangeReturnType(context.Document, root, structDeclaration, token), equivalenceKey: "Add [D2DGeneratedPixelShaderDescriptor] attribute"), diagnostic); } @@ -55,9 +56,22 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) /// The original document being fixed. /// The original tree root belonging to the current document. /// The to update. + /// The cancellation token for the operation. /// An updated document with the applied code fix, and the return type of the method being . - private static Task ChangeReturnType(Document document, SyntaxNode root, StructDeclarationSyntax structDeclaration) + private static async Task ChangeReturnType(Document document, SyntaxNode root, StructDeclarationSyntax structDeclaration, CancellationToken cancellationToken) { + // Get the semantic model (bail if it's not available) + if (await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false) is not SemanticModel semanticModel) + { + return document; + } + + // Also bail if we can't resolve the [D2DGeneratedPixelShaderDescriptor] attribute symbol (this should really never happen) + if (semanticModel.Compilation.GetTypeByMetadataName("ComputeSharp.D2D1.D2DGeneratedPixelShaderDescriptorAttribute") is not INamedTypeSymbol attributeSymbol) + { + return document; + } + int index = 0; // Find the index to use to insert the attribute. We want to make it so that if the struct declaration @@ -89,15 +103,16 @@ private static Task ChangeReturnType(Document document, SyntaxNode roo } } - // Create the attribute syntax for the new attribute - AttributeListSyntax newAttributeList = AttributeList(SingletonSeparatedList(Attribute(IdentifierName("D2DGeneratedPixelShaderDescriptor")))); + SyntaxGenerator syntaxGenerator = SyntaxGenerator.GetGenerator(document); - // Create a new syntax node with the new attribute - SyntaxNode typeSyntax = SyntaxGenerator.GetGenerator(document).InsertAttributes(structDeclaration, index, newAttributeList); + // Create the attribute syntax for the new attribute. Also annotate it + // to automatically add using directives to the document, if needed. + // Then create the attribute syntax and insert it at the right position. + SyntaxNode attributeTypeSyntax = syntaxGenerator.TypeExpression(attributeSymbol).WithAdditionalAnnotations(Simplifier.AddImportsAnnotation); + SyntaxNode attributeSyntax = syntaxGenerator.Attribute(attributeTypeSyntax); + SyntaxNode updatedStructDeclarationSyntax = syntaxGenerator.InsertAttributes(structDeclaration, index, attributeSyntax); // Replace the node in the document tree - Document updatedDocument = document.WithSyntaxRoot(root.ReplaceNode(structDeclaration, typeSyntax)); - - return Task.FromResult(updatedDocument); + return document.WithSyntaxRoot(root.ReplaceNode(structDeclaration, updatedStructDeclarationSyntax)); } } From 21f410e7c4ad34fa021d5a2da864fcbc1f1dd5f3 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 1 Oct 2023 18:43:03 +0200 Subject: [PATCH 15/20] Add blank ComputeSharp.D2D1.Tests.SourceGenerators project --- ComputeSharp.sln | 13 ++++++++++++- ...puteSharp.D2D1.Tests.SourceGenerators.csproj | 17 +++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/ComputeSharp.D2D1.Tests.SourceGenerators/ComputeSharp.D2D1.Tests.SourceGenerators.csproj diff --git a/ComputeSharp.sln b/ComputeSharp.sln index 6e30315eb..5094cf24c 100644 --- a/ComputeSharp.sln +++ b/ComputeSharp.sln @@ -158,7 +158,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComputeSharp.D2D1.WinUI.Tes EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComputeSharp.D3D12MemoryAllocator", "src\ComputeSharp.D3D12MemoryAllocator\ComputeSharp.D3D12MemoryAllocator.csproj", "{E017B3B6-C7D3-4E53-A7F6-1036178E98C3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComputeSharp.D2D1.CodeFixers", "src\ComputeSharp.D2D1.CodeFixers\ComputeSharp.D2D1.CodeFixers.csproj", "{54654960-54B5-4E19-B3ED-993591CA39E5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComputeSharp.D2D1.CodeFixers", "src\ComputeSharp.D2D1.CodeFixers\ComputeSharp.D2D1.CodeFixers.csproj", "{54654960-54B5-4E19-B3ED-993591CA39E5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComputeSharp.D2D1.Tests.SourceGenerators", "tests\ComputeSharp.D2D1.Tests.SourceGenerators\ComputeSharp.D2D1.Tests.SourceGenerators.csproj", "{59A17380-24A0-4BD7-9012-B105A9E7D46F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -464,6 +466,14 @@ Global {54654960-54B5-4E19-B3ED-993591CA39E5}.Release|ARM64.Build.0 = Release|Any CPU {54654960-54B5-4E19-B3ED-993591CA39E5}.Release|x64.ActiveCfg = Release|Any CPU {54654960-54B5-4E19-B3ED-993591CA39E5}.Release|x64.Build.0 = Release|Any CPU + {59A17380-24A0-4BD7-9012-B105A9E7D46F}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {59A17380-24A0-4BD7-9012-B105A9E7D46F}.Debug|ARM64.Build.0 = Debug|Any CPU + {59A17380-24A0-4BD7-9012-B105A9E7D46F}.Debug|x64.ActiveCfg = Debug|Any CPU + {59A17380-24A0-4BD7-9012-B105A9E7D46F}.Debug|x64.Build.0 = Debug|Any CPU + {59A17380-24A0-4BD7-9012-B105A9E7D46F}.Release|ARM64.ActiveCfg = Release|Any CPU + {59A17380-24A0-4BD7-9012-B105A9E7D46F}.Release|ARM64.Build.0 = Release|Any CPU + {59A17380-24A0-4BD7-9012-B105A9E7D46F}.Release|x64.ActiveCfg = Release|Any CPU + {59A17380-24A0-4BD7-9012-B105A9E7D46F}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -504,6 +514,7 @@ Global {346AEB10-A4EA-427E-8578-F60915DB3053} = {F8EFBB27-4EE2-4463-A75B-7EFDFB55D0F7} {4D4BB2F6-5653-4DB5-A8DD-90D58D8FE4D3} = {F8EFBB27-4EE2-4463-A75B-7EFDFB55D0F7} {73C32D0F-64DB-4674-84E9-8FCC41228474} = {F8EFBB27-4EE2-4463-A75B-7EFDFB55D0F7} + {59A17380-24A0-4BD7-9012-B105A9E7D46F} = {F8EFBB27-4EE2-4463-A75B-7EFDFB55D0F7} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4664C5E3-0340-4E22-BCFD-98AAEDF5F2DC} diff --git a/tests/ComputeSharp.D2D1.Tests.SourceGenerators/ComputeSharp.D2D1.Tests.SourceGenerators.csproj b/tests/ComputeSharp.D2D1.Tests.SourceGenerators/ComputeSharp.D2D1.Tests.SourceGenerators.csproj new file mode 100644 index 000000000..07aa1ff84 --- /dev/null +++ b/tests/ComputeSharp.D2D1.Tests.SourceGenerators/ComputeSharp.D2D1.Tests.SourceGenerators.csproj @@ -0,0 +1,17 @@ + + + net6.0 + + + + + + + + + + + + + + From d992600689fa4eae899a11d998d774fddb6cbb8b Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 1 Oct 2023 20:28:59 +0200 Subject: [PATCH 16/20] Add tests for missing descriptor attribute code fixer --- ...teSharp.D2D1.Tests.SourceGenerators.csproj | 7 +- ...lShaderDescriptorOnPixelShaderCodeFixer.cs | 178 ++++++++++++++++++ 2 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 tests/ComputeSharp.D2D1.Tests.SourceGenerators/Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs diff --git a/tests/ComputeSharp.D2D1.Tests.SourceGenerators/ComputeSharp.D2D1.Tests.SourceGenerators.csproj b/tests/ComputeSharp.D2D1.Tests.SourceGenerators/ComputeSharp.D2D1.Tests.SourceGenerators.csproj index 07aa1ff84..8a221bb18 100644 --- a/tests/ComputeSharp.D2D1.Tests.SourceGenerators/ComputeSharp.D2D1.Tests.SourceGenerators.csproj +++ b/tests/ComputeSharp.D2D1.Tests.SourceGenerators/ComputeSharp.D2D1.Tests.SourceGenerators.csproj @@ -7,11 +7,16 @@ + + + - + + + diff --git a/tests/ComputeSharp.D2D1.Tests.SourceGenerators/Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs b/tests/ComputeSharp.D2D1.Tests.SourceGenerators/Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs new file mode 100644 index 000000000..d85854259 --- /dev/null +++ b/tests/ComputeSharp.D2D1.Tests.SourceGenerators/Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs @@ -0,0 +1,178 @@ +extern alias Core; +extern alias D2D1; + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using CSharpCodeFixTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixTest< + ComputeSharp.D2D1.SourceGenerators.MissingPixelShaderDescriptorOnPixelShaderAnalyzer, + ComputeSharp.D2D1.CodeFixers.MissingPixelShaderDescriptorOnPixelShaderCodeFixer, + Microsoft.CodeAnalysis.Testing.Verifiers.MSTestVerifier>; + +namespace ComputeSharp.D2D1.Tests.SourceGenerators; + +[TestClass] +public class Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer +{ + [TestMethod] + public async Task FileContainsComputeSharpD2D1UsingDirective() + { + string original = """ + using ComputeSharp.D2D1; + + partial struct {|CMPSD2D0065:MyShader|} : ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + """; + + string @fixed = """ + using ComputeSharp.D2D1; + + [D2DGeneratedPixelShaderDescriptor] + partial struct MyShader : ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + """; + + CSharpCodeFixTest test = new() + { + TestCode = original, + FixedCode = @fixed, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + }; + + test.TestState.AdditionalReferences.Add(typeof(Core::ComputeSharp.Float4).Assembly); + test.TestState.AdditionalReferences.Add(typeof(D2D1::ComputeSharp.D2D1.ID2D1PixelShader).Assembly); + test.TestState.AnalyzerConfigFiles.Add(("/.editorconfig", "[*]\nend_of_line = lf")); + + await test.RunAsync(); + } + + [TestMethod] + public async Task FileDoesNotContainComputeSharpD2D1UsingDirective() + { + string original = """ + partial struct {|CMPSD2D0065:MyShader|} : ComputeSharp.D2D1.ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + """; + + string @fixed = """ + using ComputeSharp.D2D1; + + [D2DGeneratedPixelShaderDescriptor] + partial struct MyShader : ComputeSharp.D2D1.ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + """; + + CSharpCodeFixTest test = new() + { + TestCode = original, + FixedCode = @fixed, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + }; + + test.TestState.AdditionalReferences.Add(typeof(Core::ComputeSharp.Float4).Assembly); + test.TestState.AdditionalReferences.Add(typeof(D2D1::ComputeSharp.D2D1.ID2D1PixelShader).Assembly); + test.TestState.AnalyzerConfigFiles.Add(("/.editorconfig", "[*]\nend_of_line = lf")); + + await test.RunAsync(); + } + + [TestMethod] + public async Task InsertsAttributeAfterAllOtherD2DAttributes() + { + string original = """ + using ComputeSharp.D2D1; + + [D2DInputCount(1)] + [D2DInputSimple(0)] + partial struct {|CMPSD2D0065:MyShader|} : ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + """; + + string @fixed = """ + using ComputeSharp.D2D1; + + [D2DInputCount(1)] + [D2DInputSimple(0)] + [D2DGeneratedPixelShaderDescriptor] + partial struct MyShader : ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + """; + + CSharpCodeFixTest test = new() + { + TestCode = original, + FixedCode = @fixed, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + }; + + test.TestState.AdditionalReferences.Add(typeof(Core::ComputeSharp.Float4).Assembly); + test.TestState.AdditionalReferences.Add(typeof(D2D1::ComputeSharp.D2D1.ID2D1PixelShader).Assembly); + test.TestState.AnalyzerConfigFiles.Add(("/.editorconfig", "[*]\nend_of_line = lf")); + + await test.RunAsync(); + } + + [TestMethod] + public async Task InsertsAttributeAfterAllOtherD2DAttributes_WithOtherNonD2DAttribute() + { + string original = """ + using System; + using ComputeSharp.D2D1; + + [D2DInputCount(1)] + [D2DInputSimple(0)] + [Test] + partial struct {|CMPSD2D0065:MyShader|} : ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + + public class TestAttribute : Attribute + { + } + """; + + string @fixed = """ + using System; + using ComputeSharp.D2D1; + + [D2DInputCount(1)] + [D2DInputSimple(0)] + [D2DGeneratedPixelShaderDescriptor] + [Test] + partial struct MyShader : ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + + public class TestAttribute : Attribute + { + } + """; + + CSharpCodeFixTest test = new() + { + TestCode = original, + FixedCode = @fixed, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + }; + + test.TestState.AdditionalReferences.Add(typeof(Core::ComputeSharp.Float4).Assembly); + test.TestState.AdditionalReferences.Add(typeof(D2D1::ComputeSharp.D2D1.ID2D1PixelShader).Assembly); + test.TestState.AnalyzerConfigFiles.Add(("/.editorconfig", "[*]\nend_of_line = lf")); + + await test.RunAsync(); + } +} From 1029ad2622505de40b716a2b97da68fde9d37732 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 1 Oct 2023 21:40:26 +0200 Subject: [PATCH 17/20] Add ComputeSharp.D2D1.Tests.SourceGenerators to CI script --- .github/workflows/dotnet.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 72d9f9ea8..3fcb049c0 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -118,6 +118,11 @@ jobs: - name: Run ComputeSharp.D2D1.Tests.AssemblyLevelAttributes run: dotnet test tests\ComputeSharp.D2D1.Tests.AssemblyLevelAttributes\ComputeSharp.D2D1.Tests.AssemblyLevelAttributes.csproj -c Release -f ${{matrix.framework}} -v n -l "console;verbosity=detailed" + # Run the D2D1 source generators tests as well (only on .NET 6, like for the DX12 ones) + - if: matrix.framework == 'net6.0' + name: Run ComputeSharp.D2D1.Tests.SourceGenerators + run: dotnet test tests\ComputeSharp.D2D1.Tests.SourceGenerators\ComputeSharp.D2D1.Tests.SourceGenerators.csproj -v n -l "console;verbosity=detailed" + # Run all unit tests using D3D12MA run-tests-d3d12ma: needs: [build-solution] From 610fc5808e1f2502a11826785207fa6359c5f315 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Tue, 3 Oct 2023 01:15:04 +0200 Subject: [PATCH 18/20] Simplify HlslBytecodeInfoKey model --- ...derDescriptorGenerator.HlslBytecode.Syntax.cs | 4 ++-- ...ixelShaderDescriptorGenerator.HlslBytecode.cs | 15 +++++++++------ .../D2DPixelShaderDescriptorGenerator.cs | 7 ++----- .../Models/HlslBytecodeInfoKey.cs | 16 ++++++---------- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.Syntax.cs index 242f61b52..2f65635cc 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.Syntax.cs @@ -21,7 +21,7 @@ public static void WriteShaderProfileSyntax(D2D1ShaderInfo info, IndentedTextWri { writer.WriteLine("/// "); writer.WriteGeneratedAttributes(GeneratorName); - writer.WriteLine($"readonly ComputeSharp.D2D1.D2D1ShaderProfile global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.ShaderProfile => global::ComputeSharp.D2D1.D2D1ShaderProfile.{info.HlslInfoKey.EffectiveShaderProfile};"); + writer.WriteLine($"readonly ComputeSharp.D2D1.D2D1ShaderProfile global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<{info.Hierarchy.Hierarchy[0].QualifiedName}>.ShaderProfile => global::ComputeSharp.D2D1.D2D1ShaderProfile.{info.HlslInfoKey.ShaderProfile};"); } /// @@ -33,7 +33,7 @@ public static void WriteCompileOptionsSyntax(D2D1ShaderInfo info, IndentedTextWr { // Get a formatted representation of the compile options being used string compileOptionsExpression = - info.HlslInfoKey.EffectiveCompileOptions + info.HlslInfoKey.CompileOptions .ToString() .Split(',') .Select(static name => $"global::ComputeSharp.D2D1.D2D1CompileOptions.{name.Trim()}") diff --git a/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.cs index 3784f2e26..7289f8591 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.HlslBytecode.cs @@ -87,9 +87,13 @@ internal static partial class HlslBytecode /// Gets the effective shader profile to use. /// /// The requested shader profile. + /// Whether compilation should be performed with the input profile. /// The effective shader profile. - public static D2D1ShaderProfile GetEffectiveShaderProfile(D2D1ShaderProfile? shaderProfile) + public static D2D1ShaderProfile GetEffectiveShaderProfile(D2D1ShaderProfile? shaderProfile, out bool isCompilationEnabled) { + // Compilation is only enabled if the user explicitly selected a shader profile + isCompilationEnabled = shaderProfile is not null; + // The effective shader profile is either be the requested one, or the default value (which maps to PS5.0) return shaderProfile ?? D2D1ShaderProfile.PixelShader50; } @@ -150,11 +154,10 @@ public static HlslBytecodeInfo GetInfo(ref HlslBytecodeInfoKey key, Cancellation { static unsafe HlslBytecodeInfo GetInfo(HlslBytecodeInfoKey key, CancellationToken token) { - // No embedded shader was requested, or there were some errors earlier in the pipeline. + // Check if the compilation is not enabled (eg. if there's been errors earlier in the pipeline). // In this case, skip the compilation, as diagnostic will be emitted for those anyway. // Compiling would just add overhead and result in more errors, as the HLSL would be invalid. - // We also skip compilation if no shader profile has been requested (we never just assume one). - if (key.HasErrors || key.RequestedShaderProfile is null) + if (!key.IsCompilationEnabled) { return HlslBytecodeInfo.Missing.Instance; } @@ -166,8 +169,8 @@ static unsafe HlslBytecodeInfo GetInfo(HlslBytecodeInfoKey key, CancellationToke // Compile the shader bytecode using the effective parameters using ComPtr dxcBlobBytecode = D3DCompiler.Compile( key.HlslSource.AsSpan(), - key.EffectiveShaderProfile, - key.EffectiveCompileOptions); + key.ShaderProfile, + key.CompileOptions); token.ThrowIfCancellationRequested(); diff --git a/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.cs b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.cs index 9f83daa72..9342c22ec 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/D2DPixelShaderDescriptorGenerator.cs @@ -140,9 +140,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) bool isLinkingSupported = HlslBytecode.IsSimpleInputShader(typeSymbol, inputCount); D2D1ShaderProfile? requestedShaderProfile = HlslBytecode.GetRequestedShaderProfile(typeSymbol); D2D1CompileOptions? requestedCompileOptions = HlslBytecode.GetRequestedCompileOptions(diagnostics, typeSymbol); - D2D1ShaderProfile effectiveShaderProfile = HlslBytecode.GetEffectiveShaderProfile(requestedShaderProfile); + D2D1ShaderProfile effectiveShaderProfile = HlslBytecode.GetEffectiveShaderProfile(requestedShaderProfile, out bool isCompilationEnabled); D2D1CompileOptions effectiveCompileOptions = HlslBytecode.GetEffectiveCompileOptions(requestedCompileOptions, isLinkingSupported); - bool hasErrors = diagnostics.Count > 0; token.ThrowIfCancellationRequested(); @@ -150,11 +149,9 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // This is done last so that it can be skipped if any errors happened before. HlslBytecodeInfoKey hlslInfoKey = new( hlslSource, - requestedShaderProfile, - requestedCompileOptions, effectiveShaderProfile, effectiveCompileOptions, - hasErrors); + isCompilationEnabled); // Get the existing compiled shader, or compile the processed HLSL code HlslBytecodeInfo hlslInfo = HlslBytecode.GetInfo(ref hlslInfoKey, token); diff --git a/src/ComputeSharp.D2D1.SourceGenerators/Models/HlslBytecodeInfoKey.cs b/src/ComputeSharp.D2D1.SourceGenerators/Models/HlslBytecodeInfoKey.cs index 772e9aea3..035f71446 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/Models/HlslBytecodeInfoKey.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/Models/HlslBytecodeInfoKey.cs @@ -4,15 +4,11 @@ namespace ComputeSharp.D2D1.SourceGenerators.Models; /// A model with info to be a unique key for instances. /// /// The input HLSL source code. -/// The requested shader profile, if available. -/// The requested compile options, if available. -/// The effective shader profile. -/// The effective compile options. -/// Whether any errors were produced when analyzing the shader. +/// The shader profile. +/// The compile options. +/// Whether compilation should be attempted for the current info. internal sealed record HlslBytecodeInfoKey( string HlslSource, - D2D1ShaderProfile? RequestedShaderProfile, - D2D1CompileOptions? RequestedCompileOptions, - D2D1ShaderProfile EffectiveShaderProfile, - D2D1CompileOptions EffectiveCompileOptions, - bool HasErrors); \ No newline at end of file + D2D1ShaderProfile ShaderProfile, + D2D1CompileOptions CompileOptions, + bool IsCompilationEnabled); \ No newline at end of file From 1013cfb6f3cd4f53fc22173b0305fd2d6ce79bca Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Tue, 3 Oct 2023 13:23:48 +0200 Subject: [PATCH 19/20] Add FixAllProvider and unit tests with multiple diagnostics --- ...lShaderDescriptorOnPixelShaderCodeFixer.cs | 82 ++++++++++-- ...lShaderDescriptorOnPixelShaderCodeFixer.cs | 119 ++++++++++++++++++ 2 files changed, 192 insertions(+), 9 deletions(-) diff --git a/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs b/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs index 056636921..9688b5b3d 100644 --- a/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs +++ b/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs @@ -24,9 +24,9 @@ public sealed class MissingPixelShaderDescriptorOnPixelShaderCodeFixer : CodeFix public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(MissingPixelShaderDescriptorOnPixelShaderTypeId); /// - public override FixAllProvider? GetFixAllProvider() + public override Microsoft.CodeAnalysis.CodeFixes.FixAllProvider? GetFixAllProvider() { - return WellKnownFixAllProviders.BatchFixer; + return new FixAllProvider(); } /// @@ -38,13 +38,13 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) SyntaxNode? root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); // Get the struct declaration from the target diagnostic - if (root!.FindNode(diagnosticSpan) is StructDeclarationSyntax structDeclaration) + if (root?.FindNode(diagnosticSpan) is StructDeclarationSyntax structDeclaration) { // Register the code fix to update the return type to be Task instead context.RegisterCodeFix( CodeAction.Create( title: "Add [D2DGeneratedPixelShaderDescriptor] attribute", - createChangedDocument: token => ChangeReturnType(context.Document, root, structDeclaration, token), + createChangedDocument: token => AddMissingD2DGeneratedPixelShaderDescriptorAttribute(context.Document, root, structDeclaration, token), equivalenceKey: "Add [D2DGeneratedPixelShaderDescriptor] attribute"), diagnostic); } @@ -58,18 +58,44 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) /// The to update. /// The cancellation token for the operation. /// An updated document with the applied code fix, and the return type of the method being . - private static async Task ChangeReturnType(Document document, SyntaxNode root, StructDeclarationSyntax structDeclaration, CancellationToken cancellationToken) + private static async Task AddMissingD2DGeneratedPixelShaderDescriptorAttribute( + Document document, + SyntaxNode root, + StructDeclarationSyntax structDeclaration, + CancellationToken cancellationToken) + { + // Get the new struct declaration + SyntaxNode updatedStructDeclaration = await AddMissingD2DGeneratedPixelShaderDescriptorAttribute( + document, + structDeclaration, + cancellationToken); + + // Replace the node in the document tree + return document.WithSyntaxRoot(root.ReplaceNode(structDeclaration, updatedStructDeclaration)); + } + + /// + /// Applies the code fix to add the [D2DGeneratedPixelShaderDescriptor] attribute to a target type. + /// + /// The original document being fixed. + /// The to update. + /// The cancellation token for the operation. + /// An updated document with the applied code fix, and the return type of the method being . + private static async Task AddMissingD2DGeneratedPixelShaderDescriptorAttribute( + Document document, + StructDeclarationSyntax structDeclaration, + CancellationToken cancellationToken) { // Get the semantic model (bail if it's not available) if (await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false) is not SemanticModel semanticModel) { - return document; + return structDeclaration; } // Also bail if we can't resolve the [D2DGeneratedPixelShaderDescriptor] attribute symbol (this should really never happen) if (semanticModel.Compilation.GetTypeByMetadataName("ComputeSharp.D2D1.D2DGeneratedPixelShaderDescriptorAttribute") is not INamedTypeSymbol attributeSymbol) { - return document; + return structDeclaration; } int index = 0; @@ -112,7 +138,45 @@ private static async Task ChangeReturnType(Document document, SyntaxNo SyntaxNode attributeSyntax = syntaxGenerator.Attribute(attributeTypeSyntax); SyntaxNode updatedStructDeclarationSyntax = syntaxGenerator.InsertAttributes(structDeclaration, index, attributeSyntax); - // Replace the node in the document tree - return document.WithSyntaxRoot(root.ReplaceNode(structDeclaration, updatedStructDeclarationSyntax)); + // Replace the node in the syntax tree + return updatedStructDeclarationSyntax; + } + + /// + /// A custom with the logic from . + /// + private sealed class FixAllProvider : DocumentBasedFixAllProvider + { + /// + protected override async Task FixAllAsync(FixAllContext fixAllContext, Document document, ImmutableArray diagnostics) + { + // Get the document root (this should always succeed) + if (await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false) is not SyntaxNode root) + { + return document; + } + + SyntaxEditor syntaxEditor = new(root, fixAllContext.Solution.Services); + + foreach (Diagnostic diagnostic in diagnostics) + { + // Get the current struct declaration for the diagnostic + if (root.FindNode(diagnostic.Location.SourceSpan) is not StructDeclarationSyntax structDeclaration) + { + continue; + } + + // Get the syntax node with the updated declaration + SyntaxNode updatedStructDeclaration = await AddMissingD2DGeneratedPixelShaderDescriptorAttribute( + document, + structDeclaration, + fixAllContext.CancellationToken); + + // Replace the node via the editor + syntaxEditor.ReplaceNode(structDeclaration, updatedStructDeclaration); + } + + return document.WithSyntaxRoot(syntaxEditor.GetChangedRoot()); + } } } diff --git a/tests/ComputeSharp.D2D1.Tests.SourceGenerators/Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs b/tests/ComputeSharp.D2D1.Tests.SourceGenerators/Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs index d85854259..dc404974e 100644 --- a/tests/ComputeSharp.D2D1.Tests.SourceGenerators/Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs +++ b/tests/ComputeSharp.D2D1.Tests.SourceGenerators/Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs @@ -50,6 +50,67 @@ partial struct MyShader : ID2D1PixelShader await test.RunAsync(); } + [TestMethod] + public async Task FileContainsComputeSharpD2D1UsingDirective_MultipleOccurrences() + { + string original = """ + using System; + using ComputeSharp.D2D1; + + partial struct {|CMPSD2D0065:MyShader1|} : ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + + [D2DInputCount(0)] + [TestAttribute] + partial struct {|CMPSD2D0065:MyShader2|} : ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + + public class TestAttribute : Attribute + { + } + """; + + string @fixed = """ + using System; + using ComputeSharp.D2D1; + + [D2DGeneratedPixelShaderDescriptor] + partial struct MyShader1 : ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + + [D2DInputCount(0)] + [D2DGeneratedPixelShaderDescriptor] + [TestAttribute] + partial struct MyShader2 : ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + + public class TestAttribute : Attribute + { + } + """; + + CSharpCodeFixTest test = new() + { + TestCode = original, + FixedCode = @fixed, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + }; + + test.TestState.AdditionalReferences.Add(typeof(Core::ComputeSharp.Float4).Assembly); + test.TestState.AdditionalReferences.Add(typeof(D2D1::ComputeSharp.D2D1.ID2D1PixelShader).Assembly); + test.TestState.AnalyzerConfigFiles.Add(("/.editorconfig", "[*]\nend_of_line = lf")); + + await test.RunAsync(); + } + [TestMethod] public async Task FileDoesNotContainComputeSharpD2D1UsingDirective() { @@ -84,6 +145,64 @@ partial struct MyShader : ComputeSharp.D2D1.ID2D1PixelShader await test.RunAsync(); } + [TestMethod] + public async Task FileDoesNotContainComputeSharpD2D1UsingDirective_MultipleOccurrences() + { + string original = """ + using System; + + partial struct {|CMPSD2D0065:MyShader1|} : ComputeSharp.D2D1.ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + + [TestAttribute] + partial struct {|CMPSD2D0065:MyShader2|} : ComputeSharp.D2D1.ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + + public class TestAttribute : Attribute + { + } + """; + + string @fixed = """ + using System; + using ComputeSharp.D2D1; + + [D2DGeneratedPixelShaderDescriptor] + partial struct MyShader1 : ComputeSharp.D2D1.ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + + [D2DGeneratedPixelShaderDescriptor] + [TestAttribute] + partial struct MyShader2 : ComputeSharp.D2D1.ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + + public class TestAttribute : Attribute + { + } + """; + + CSharpCodeFixTest test = new() + { + TestCode = original, + FixedCode = @fixed, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + }; + + test.TestState.AdditionalReferences.Add(typeof(Core::ComputeSharp.Float4).Assembly); + test.TestState.AdditionalReferences.Add(typeof(D2D1::ComputeSharp.D2D1.ID2D1PixelShader).Assembly); + test.TestState.AnalyzerConfigFiles.Add(("/.editorconfig", "[*]\nend_of_line = lf")); + + await test.RunAsync(); + } + [TestMethod] public async Task InsertsAttributeAfterAllOtherD2DAttributes() { From 112a4af860d6082868d122e7ef308cd6c9c56014 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Tue, 3 Oct 2023 21:14:24 +0200 Subject: [PATCH 20/20] Correctly insert attribute after built-in D2D attributes --- ...lShaderDescriptorOnPixelShaderCodeFixer.cs | 32 +++++++++- .../ComputeSharp.SourceGeneration.projitems | 1 + .../Extensions/SymbolInfoExtensions.cs | 44 +++++++++++++ ...lShaderDescriptorOnPixelShaderCodeFixer.cs | 64 +++++++++++++++++++ 4 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 src/ComputeSharp.SourceGeneration/Extensions/SymbolInfoExtensions.cs diff --git a/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs b/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs index 9688b5b3d..bddd91ada 100644 --- a/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs +++ b/src/ComputeSharp.D2D1.CodeFixers/MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs @@ -2,6 +2,7 @@ using System.Composition; using System.Threading; using System.Threading.Tasks; +using ComputeSharp.SourceGeneration.Extensions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; @@ -20,6 +21,25 @@ namespace ComputeSharp.D2D1.CodeFixers; [Shared] public sealed class MissingPixelShaderDescriptorOnPixelShaderCodeFixer : CodeFixProvider { + /// + /// The set of type names for all D2D attributes that can be over shader types. + /// + private static readonly ImmutableArray D2DAttributeTypeNames = ImmutableArray.Create( + "ComputeSharp.D2D1.D2DCompileOptionsAttribute", + "ComputeSharp.D2D1.D2DEffectAuthorAttribute", + "ComputeSharp.D2D1.D2DEffectCategoryAttribute", + "ComputeSharp.D2D1.D2DEffectDescriptionAttribute", + "ComputeSharp.D2D1.D2DEffectDisplayNameAttribute", + "ComputeSharp.D2D1.D2DEffectIdAttribute", + "ComputeSharp.D2D1.D2DInputComplexAttribute", + "ComputeSharp.D2D1.D2DInputCountAttribute", + "ComputeSharp.D2D1.D2DInputDescriptionAttribute", + "ComputeSharp.D2D1.D2DInputSimpleAttribute", + "ComputeSharp.D2D1.D2DOutputBufferAttribute", + "ComputeSharp.D2D1.D2DPixelOptionsAttribute", + "ComputeSharp.D2D1.D2DRequiresScenePositionAttribute", + "ComputeSharp.D2D1.D2DShaderProfileAttribute"); + /// public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(MissingPixelShaderDescriptorOnPixelShaderTypeId); @@ -92,6 +112,12 @@ private static async Task AddMissingD2DGeneratedPixelShaderDescripto return structDeclaration; } + // Build the map of D2D attributes to look for + if (!semanticModel.Compilation.TryBuildNamedTypeSymbolSet(D2DAttributeTypeNames, out ImmutableHashSet? d2DAttributeTypeSymbols)) + { + return structDeclaration; + } + // Also bail if we can't resolve the [D2DGeneratedPixelShaderDescriptor] attribute symbol (this should really never happen) if (semanticModel.Compilation.GetTypeByMetadataName("ComputeSharp.D2D1.D2DGeneratedPixelShaderDescriptorAttribute") is not INamedTypeSymbol attributeSymbol) { @@ -111,14 +137,14 @@ private static async Task AddMissingD2DGeneratedPixelShaderDescripto continue; } - // Make sure we find a readable identifier for the attribute - if (attribute.Name is not IdentifierNameSyntax { Identifier.Value: string identifier }) + // Resolve the symbol for the attribute (stop here if this failed for whatever reason) + if (!semanticModel.GetSymbolInfo(attribute, cancellationToken).TryGetAttributeTypeSymbol(out INamedTypeSymbol? attributeTypeSymbol)) { break; } // If the attribute is D2D one, increment the index and continue - if (identifier.Contains("D2D")) + if (d2DAttributeTypeSymbols.Contains(attributeTypeSymbol)) { index++; } diff --git a/src/ComputeSharp.SourceGeneration/ComputeSharp.SourceGeneration.projitems b/src/ComputeSharp.SourceGeneration/ComputeSharp.SourceGeneration.projitems index 3a2bf8d37..413e50cc8 100644 --- a/src/ComputeSharp.SourceGeneration/ComputeSharp.SourceGeneration.projitems +++ b/src/ComputeSharp.SourceGeneration/ComputeSharp.SourceGeneration.projitems @@ -18,6 +18,7 @@ + diff --git a/src/ComputeSharp.SourceGeneration/Extensions/SymbolInfoExtensions.cs b/src/ComputeSharp.SourceGeneration/Extensions/SymbolInfoExtensions.cs new file mode 100644 index 000000000..2317a5d1f --- /dev/null +++ b/src/ComputeSharp.SourceGeneration/Extensions/SymbolInfoExtensions.cs @@ -0,0 +1,44 @@ +using System.Diagnostics.CodeAnalysis; +using Microsoft.CodeAnalysis; + +namespace ComputeSharp.SourceGeneration.Extensions; + +/// +/// Extension methods for the type. +/// +internal static class SymbolInfoExtensions +{ + /// + /// Tries to get the resolved attribute type symbol from a given value. + /// + /// The value to check. + /// The resulting attribute type symbol, if correctly resolved. + /// Whether is resolved to a symbol. + /// + /// This can be used to ensure users haven't eg. spelled names incorrecty or missed a using directive. Normally, code would just + /// not compile if that was the case, but that doesn't apply for attributes using invalid targets. In that case, Roslyn will ignore + /// any errors, meaning the generator has to validate the type symbols are correctly resolved on its own. + /// + public static bool TryGetAttributeTypeSymbol(this SymbolInfo symbolInfo, [NotNullWhen(true)] out INamedTypeSymbol? typeSymbol) + { + ISymbol? attributeSymbol = symbolInfo.Symbol; + + // If no symbol is selected and there is a single candidate symbol, use that + if (attributeSymbol is null && symbolInfo.CandidateSymbols is [ISymbol candidateSymbol]) + { + attributeSymbol = candidateSymbol; + } + + // Extract the symbol from either the current one or the containing type + if ((attributeSymbol as INamedTypeSymbol ?? attributeSymbol?.ContainingType) is not INamedTypeSymbol resultingSymbol) + { + typeSymbol = null; + + return false; + } + + typeSymbol = resultingSymbol; + + return true; + } +} diff --git a/tests/ComputeSharp.D2D1.Tests.SourceGenerators/Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs b/tests/ComputeSharp.D2D1.Tests.SourceGenerators/Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs index dc404974e..756229cf0 100644 --- a/tests/ComputeSharp.D2D1.Tests.SourceGenerators/Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs +++ b/tests/ComputeSharp.D2D1.Tests.SourceGenerators/Test_MissingPixelShaderDescriptorOnPixelShaderCodeFixer.cs @@ -294,4 +294,68 @@ public class TestAttribute : Attribute await test.RunAsync(); } + + [TestMethod] + public async Task InsertsAttributeAfterAllOtherD2DAttributes_WithFakeAttributes() + { + string original = """ + using System; + using ComputeSharp.D2D1; + + [D2DInputCount(2)] + [D2DInputSimple(0)] + [ComputeSharp.D2D1.D2DInputSimple(1)] + [D2DFake] + [Test] + partial struct {|CMPSD2D0065:MyShader|} : ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + + public class TestAttribute : Attribute + { + } + + public class D2DFakeAttribute : Attribute + { + } + """; + + string @fixed = """ + using System; + using ComputeSharp.D2D1; + + [D2DInputCount(2)] + [D2DInputSimple(0)] + [ComputeSharp.D2D1.D2DInputSimple(1)] + [D2DGeneratedPixelShaderDescriptor] + [D2DFake] + [Test] + partial struct {|CMPSD2D0065:MyShader|} : ID2D1PixelShader + { + public ComputeSharp.Float4 Execute() => 0; + } + + public class TestAttribute : Attribute + { + } + + public class D2DFakeAttribute : Attribute + { + } + """; + + CSharpCodeFixTest test = new() + { + TestCode = original, + FixedCode = @fixed, + ReferenceAssemblies = ReferenceAssemblies.Net.Net60 + }; + + test.TestState.AdditionalReferences.Add(typeof(Core::ComputeSharp.Float4).Assembly); + test.TestState.AdditionalReferences.Add(typeof(D2D1::ComputeSharp.D2D1.ID2D1PixelShader).Assembly); + test.TestState.AnalyzerConfigFiles.Add(("/.editorconfig", "[*]\nend_of_line = lf")); + + await test.RunAsync(); + } }