From ac7d9648d3b37814b71e097d1f4b461f3a31a88c Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 23 Sep 2023 15:16:35 +0200 Subject: [PATCH 1/2] Generate input descriptions as ReadOnlyMemory --- .../ComputeSharp.D2D1.SourceGenerators.csproj | 1 + ...nerator.CreateInputTypesProperty.Syntax.cs | 2 +- ...reateLoadInputDescriptionsMethod.Syntax.cs | 215 +++++++++--------- ...rator.CreateLoadInputDescriptionsMethod.cs | 4 +- .../ID2D1ShaderGenerator.cs | 4 +- .../Models/InputDescription.cs | 4 +- .../Interfaces/__Internals/ID2D1Shader.cs | 7 + .../Shaders/Interop/D2D1InputDescription.cs | 17 +- 8 files changed, 144 insertions(+), 110 deletions(-) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ComputeSharp.D2D1.SourceGenerators.csproj b/src/ComputeSharp.D2D1.SourceGenerators/ComputeSharp.D2D1.SourceGenerators.csproj index 5629c18d9..9fff66b5e 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ComputeSharp.D2D1.SourceGenerators.csproj +++ b/src/ComputeSharp.D2D1.SourceGenerators/ComputeSharp.D2D1.SourceGenerators.csproj @@ -85,6 +85,7 @@ + diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputTypesProperty.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputTypesProperty.Syntax.cs index e7cd8e024..fe837ca3a 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputTypesProperty.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputTypesProperty.Syntax.cs @@ -75,7 +75,7 @@ private static TypeDeclarationSyntax GetMemoryManagerDeclaration(ImmutableArray< // Create the MemoryManager declaration: // // /// - // /// implementation to get the input types. + // /// A implementation to get the input types. // /// // [global::System.CodeDom.Compiler.GeneratedCode("...", "...")] // [global::System.Diagnostics.DebuggerNonUserCode] diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.Syntax.cs index b2413cfe0..543a46e33 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.Syntax.cs @@ -1,7 +1,8 @@ -using System.Collections.Immutable; +using System; using ComputeSharp.D2D1.__Internals; using ComputeSharp.D2D1.SourceGenerators.Models; using ComputeSharp.SourceGeneration.Helpers; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; @@ -17,12 +18,32 @@ partial class ID2D1ShaderGenerator private static partial class LoadInputDescriptions { /// - /// Creates a instance for the LoadInputDescriptions method. + /// Creates a instance for the InputDescriptions property. /// /// The input descriptions info gathered for the current shader. - /// The resulting instance for the LoadInputDescriptions method. - public static MethodDeclarationSyntax GetSyntax(InputDescriptionsInfo inputDescriptionsInfo) + /// Any additional instances needed by the generated code, if needed. + /// The resulting instance for the InputDescriptions property. + public static PropertyDeclarationSyntax GetSyntax(InputDescriptionsInfo inputDescriptionsInfo, out TypeDeclarationSyntax[] additionalTypes) { + ExpressionSyntax memoryExpression; + + // If there are no input descriptions, just return a default expression. + // Otherwise, declare the shared array and return it from the property. + if (inputDescriptionsInfo.InputDescriptions.Length == 0) + { + memoryExpression = LiteralExpression(SyntaxKind.DefaultLiteralExpression, Token(SyntaxKind.DefaultKeyword)); + additionalTypes = Array.Empty(); + } + else + { + memoryExpression = MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("Data"), + IdentifierName("InputDescriptions")); + + additionalTypes = new[] { GetArrayDeclaration(inputDescriptionsInfo) }; + } + // This code produces a method declaration as follows: // // readonly void global::ComputeSharp.D2D1.__Internals.ID2D1Shader.LoadInputDescriptions(ref TLoader loader) @@ -30,120 +51,110 @@ public static MethodDeclarationSyntax GetSyntax(InputDescriptionsInfo inputDescr // // } return - MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier(nameof(LoadInputDescriptions))) + PropertyDeclaration( + GenericName(Identifier("global::System.ReadOnlyMemory")) + .AddTypeArgumentListArguments(IdentifierName("global::ComputeSharp.D2D1.Interop.D2D1InputDescription")), + Identifier("InputDescriptions")) .WithExplicitInterfaceSpecifier(ExplicitInterfaceSpecifier(IdentifierName($"global::ComputeSharp.D2D1.__Internals.{nameof(ID2D1Shader)}"))) .AddModifiers(Token(SyntaxKind.ReadOnlyKeyword)) - .AddTypeParameterListParameters(TypeParameter(Identifier("TLoader"))) - .AddParameterListParameters(Parameter(Identifier("loader")).AddModifiers(Token(SyntaxKind.RefKeyword)).WithType(IdentifierName("TLoader"))) - .WithBody(Block(GetInputDescriptionsLoadingStatements(inputDescriptionsInfo.InputDescriptions))); + .WithExpressionBody(ArrowExpressionClause(memoryExpression)) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); } /// - /// Gets a sequence of statements to load the input descriptions for a given shader. + /// Gets the array declaration for the given input descriptions. /// - /// The array of values for all available input descriptions. - /// The sequence of instances to load the input descriptions data. - private static ImmutableArray GetInputDescriptionsLoadingStatements(ImmutableArray inputDescriptions) + /// The input descriptions info gathered for the current shader. + /// The array declaration for the given input descriptions. + private static TypeDeclarationSyntax GetArrayDeclaration(InputDescriptionsInfo inputDescriptionsInfo) { - // If there are no input descriptions available, just load an empty buffer - if (inputDescriptions.IsEmpty) - { - // loader.LoadInputDescriptions(default); - return - ImmutableArray.Create( - ExpressionStatement( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("loader"), - IdentifierName("LoadInputDescriptions"))) - .AddArgumentListArguments(Argument( - LiteralExpression( - SyntaxKind.DefaultLiteralExpression, - Token(SyntaxKind.DefaultKeyword)))))); - } - - using ImmutableArrayBuilder statements = ImmutableArrayBuilder.Rent(); - - // The size of the buffer with the input descriptions is the number of input descriptions, times the size of each - // input description, which is a struct containing three int-sized fields (index, filter, and level of detail). - int inputDescriptionSizeInBytes = inputDescriptions.Length * sizeof(int) * 3; - - // global::System.Span data = stackalloc byte[]; - statements.Add( - LocalDeclarationStatement( - VariableDeclaration( - GenericName(Identifier("global::System.Span")) - .AddTypeArgumentListArguments(PredefinedType(Token(SyntaxKind.ByteKeyword)))) - .AddVariables( - VariableDeclarator(Identifier("data")) - .WithInitializer(EqualsValueClause( - StackAllocArrayCreationExpression( - ArrayType(PredefinedType(Token(SyntaxKind.ByteKeyword))) - .AddRankSpecifiers( - ArrayRankSpecifier(SingletonSeparatedList( - LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(inputDescriptionSizeInBytes))))))))))); - - // ref byte r0 = ref data[0]; - statements.Add( - LocalDeclarationStatement( - VariableDeclaration(RefType(PredefinedType(Token(SyntaxKind.ByteKeyword)))) - .AddVariables( - VariableDeclarator(Identifier("r0")) - .WithInitializer(EqualsValueClause( - RefExpression( - ElementAccessExpression(IdentifierName("data")) - .AddArgumentListArguments(Argument( - LiteralExpression( - SyntaxKind.NumericLiteralExpression, - Literal(0)))))))))); - - int offset = 0; + using ImmutableArrayBuilder inputDescriptionExpressions = ImmutableArrayBuilder.Rent(); - // Generate loading statements for each input description - foreach (InputDescription inputDescription in inputDescriptions) + foreach (InputDescription inputDescription in inputDescriptionsInfo.InputDescriptions) { - // Write the index of the current input description: + // Create the description expression (excluding level of detail): // - // global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint))) = ; - statements.Add(ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - ParseExpression($"global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint){offset}))"), - LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal((int)inputDescription.Index))))); + // new(, ) + ImplicitObjectCreationExpressionSyntax inputDescriptionExpression = + ImplicitObjectCreationExpression() + .AddArgumentListArguments( + Argument(LiteralExpression( + SyntaxKind.NumericLiteralExpression, + Literal(inputDescription.Index))), + Argument( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("global::ComputeSharp.D2D1.D2D1Filter"), + IdentifierName(inputDescription.Filter.ToString())))); - // Write the filter of the current input description: + // Add the level of detail, if needed: // - // global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint) + 4)) = ; - statements.Add(ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - ParseExpression($"global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint){offset + 4}))"), - LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal((int)inputDescription.Filter))))); - - // Write the level of detail of the current input description: - // - // global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint) + 8)) = ; - statements.Add(ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - ParseExpression($"global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint){offset + 8}))"), - LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(inputDescription.LevelOfDetail))))); + // { LevelOfDetailCount = } + if (inputDescription.LevelOfDetailCount != 0) + { + inputDescriptionExpression = + inputDescriptionExpression + .WithInitializer( + InitializerExpression(SyntaxKind.ObjectInitializerExpression) + .AddExpressions( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName("LevelOfDetailCount"), + LiteralExpression( + SyntaxKind.NumericLiteralExpression, + Literal(inputDescription.LevelOfDetailCount))))); + } - offset += sizeof(int) * 3; + inputDescriptionExpressions.Add(inputDescriptionExpression); } - // loader.LoadInputDescriptions(data); - statements.Add( - ExpressionStatement( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("loader"), - IdentifierName("LoadInputDescriptions"))) - .AddArgumentListArguments(Argument(IdentifierName("data"))))); + // Declare the singleton property to get the memory instance: + // + // /// The singleton instance for the memory manager. + // public static readonly global::ComputeSharp.D2D1.Interop.D2D1InputDescription[] InputDescriptions = { }; + FieldDeclarationSyntax fieldDeclaration = + FieldDeclaration( + VariableDeclaration( + ArrayType(IdentifierName("global::ComputeSharp.D2D1.Interop.D2D1InputDescription")) + .AddRankSpecifiers(ArrayRankSpecifier(SingletonSeparatedList(OmittedArraySizeExpression())))) + .AddVariables( + VariableDeclarator(Identifier("InputDescriptions")) + .WithInitializer(EqualsValueClause( + InitializerExpression(SyntaxKind.ArrayInitializerExpression) + .AddExpressions(inputDescriptionExpressions.ToArray()))))) + .AddModifiers( + Token(SyntaxKind.PublicKeyword), + Token(SyntaxKind.StaticKeyword), + Token(SyntaxKind.ReadOnlyKeyword)) + .WithLeadingTrivia(Comment("""/// The singleton array instance.""")); - return statements.ToImmutable(); + // Create the container type declaration: + // + // /// + // /// A container type for input descriptions. + // /// + // [global::System.CodeDom.Compiler.GeneratedCode("...", "...")] + // [global::System.Diagnostics.DebuggerNonUserCode] + // [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + // file static class Data + // { + // + // } + return + ClassDeclaration("Data") + .AddModifiers(Token(SyntaxKind.FileKeyword), Token(SyntaxKind.StaticKeyword)) + .AddAttributeLists( + AttributeList(SingletonSeparatedList( + Attribute(IdentifierName("global::System.CodeDom.Compiler.GeneratedCode")).AddArgumentListArguments( + AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ID2D1ShaderGenerator).FullName))), + AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ID2D1ShaderGenerator).Assembly.GetName().Version.ToString())))))), + AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.DebuggerNonUserCode")))), + AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage"))))) + .AddMembers(fieldDeclaration) + .WithLeadingTrivia( + Comment("/// "), + Comment("/// A container type for input descriptions."), + Comment("/// ")); } } } \ No newline at end of file diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.cs index 02b5362e4..7dafa78b8 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.cs @@ -47,7 +47,7 @@ public static void GetInfo( _ = attributeData.TryGetNamedArgument("LevelOfDetailCount", out int levelOfDetailCount); - inputDescriptionsBuilder.Add(new InputDescription((uint)index, filter, levelOfDetailCount)); + inputDescriptionsBuilder.Add(new InputDescription(index, filter, levelOfDetailCount)); } break; @@ -82,7 +82,7 @@ public static void GetInfo( // All input description indices must be unique foreach (InputDescription inputDescription in inputDescriptionsBuilder.WrittenSpan) { - ref bool isInputDescriptionIndexUsed = ref selectedInputDescriptionIndices[(int)inputDescription.Index]; + ref bool isInputDescriptionIndexUsed = ref selectedInputDescriptionIndices[inputDescription.Index]; if (isInputDescriptionIndexUsed) { diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs index 43553b4bd..547873583 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs @@ -409,8 +409,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Generate the LoadInputDescriptions() methods context.RegisterSourceOutput(inputDescriptionsInfo, static (context, item) => { - MethodDeclarationSyntax loadInputDescriptionsMethod = LoadInputDescriptions.GetSyntax(item.Info.InputDescriptions); - CompilationUnitSyntax compilationUnit = GetCompilationUnitFromMember(item.Info.Hierarchy, loadInputDescriptionsMethod, item.CanUseSkipLocalsInit); + PropertyDeclarationSyntax inputDescriptionsProperty = LoadInputDescriptions.GetSyntax(item.Info.InputDescriptions, out TypeDeclarationSyntax[] additionalTypes); + CompilationUnitSyntax compilationUnit = GetCompilationUnitFromMember(item.Info.Hierarchy, inputDescriptionsProperty, item.CanUseSkipLocalsInit, additionalMemberDeclarations: additionalTypes); context.AddSource($"{item.Info.Hierarchy.FullyQualifiedMetadataName}.{nameof(LoadInputDescriptions)}.g.cs", compilationUnit.GetText(Encoding.UTF8)); }); diff --git a/src/ComputeSharp.D2D1.SourceGenerators/Models/InputDescription.cs b/src/ComputeSharp.D2D1.SourceGenerators/Models/InputDescription.cs index 8beeb22bd..405bdc5e3 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/Models/InputDescription.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/Models/InputDescription.cs @@ -5,5 +5,5 @@ namespace ComputeSharp.D2D1.SourceGenerators.Models; /// /// The index of the input resource the description is for. /// The input filter to use. -/// The level of detail to use. -internal sealed record InputDescription(uint Index, D2D1Filter Filter, int LevelOfDetail); \ No newline at end of file +/// The level of detail to use. +internal sealed record InputDescription(int Index, D2D1Filter Filter, int LevelOfDetailCount); \ No newline at end of file diff --git a/src/ComputeSharp.D2D1/Interfaces/__Internals/ID2D1Shader.cs b/src/ComputeSharp.D2D1/Interfaces/__Internals/ID2D1Shader.cs index d826f0c6d..25eb8a4b0 100644 --- a/src/ComputeSharp.D2D1/Interfaces/__Internals/ID2D1Shader.cs +++ b/src/ComputeSharp.D2D1/Interfaces/__Internals/ID2D1Shader.cs @@ -84,6 +84,13 @@ public interface ID2D1Shader [Obsolete("This method is not intended to be used directly by user code")] ReadOnlyMemory InputTypes { get; } + /// + /// Gets the input descriptions for the current shader. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This method is not intended to be used directly by user code")] + ReadOnlyMemory InputDescriptions { get; } + /// /// Loads the input descriptions for the shader, if any. /// diff --git a/src/ComputeSharp.D2D1/Shaders/Interop/D2D1InputDescription.cs b/src/ComputeSharp.D2D1/Shaders/Interop/D2D1InputDescription.cs index 26a1909e8..45081c6a7 100644 --- a/src/ComputeSharp.D2D1/Shaders/Interop/D2D1InputDescription.cs +++ b/src/ComputeSharp.D2D1/Shaders/Interop/D2D1InputDescription.cs @@ -33,6 +33,17 @@ public readonly struct D2D1InputDescription /// private readonly int levelOfDetailCount; + /// + /// Creates a new instance with the specified parameters. + /// + /// The index of the resource the description belongs to. + /// The type of filter to apply to the input texture. + public D2D1InputDescription(int index, D2D1Filter filter) + { + this.index = index; + this.filter = filter; + } + /// /// Gets the index of the resource the description belongs to. /// @@ -46,5 +57,9 @@ public readonly struct D2D1InputDescription /// /// Gets the mip level to retrieve from the upstream transform, if specified. /// - public int LevelOfDetailCount => this.levelOfDetailCount; + public int LevelOfDetailCount + { + get => this.levelOfDetailCount; + init => this.levelOfDetailCount = value; + } } \ No newline at end of file From e37fd8e6d97d11ccd9eb6f20f56a8b71732cf655 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 23 Sep 2023 15:20:22 +0200 Subject: [PATCH 2/2] Remove LoadInputDescriptions API --- .../ComputeSharp.D2D1.SourceGenerators.csproj | 1 - ...CreateInputDescriptionsProperty.Syntax.cs} | 8 ++--- ...erator.CreateInputDescriptionsProperty.cs} | 4 +-- .../ID2D1ShaderGenerator.cs | 12 +++---- .../ID2D1InputDescriptionsLoader.cs | 18 ---------- .../Interfaces/__Internals/ID2D1Shader.cs | 10 ------ .../Shaders/Interop/D2D1PixelShader.cs | 6 +--- .../D2D1ByteArrayInputDescriptionsLoader.cs | 36 ------------------- 8 files changed, 13 insertions(+), 82 deletions(-) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.Syntax.cs => ID2D1ShaderGenerator.CreateInputDescriptionsProperty.Syntax.cs} (97%) rename src/ComputeSharp.D2D1.SourceGenerators/{ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.cs => ID2D1ShaderGenerator.CreateInputDescriptionsProperty.cs} (96%) delete mode 100644 src/ComputeSharp.D2D1/Interfaces/__Internals/ID2D1InputDescriptionsLoader.cs delete mode 100644 src/ComputeSharp.D2D1/Shaders/Loaders/D2D1ByteArrayInputDescriptionsLoader.cs diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ComputeSharp.D2D1.SourceGenerators.csproj b/src/ComputeSharp.D2D1.SourceGenerators/ComputeSharp.D2D1.SourceGenerators.csproj index 9fff66b5e..671299125 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ComputeSharp.D2D1.SourceGenerators.csproj +++ b/src/ComputeSharp.D2D1.SourceGenerators/ComputeSharp.D2D1.SourceGenerators.csproj @@ -80,7 +80,6 @@ - diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputDescriptionsProperty.Syntax.cs similarity index 97% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.Syntax.cs rename to src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputDescriptionsProperty.Syntax.cs index 543a46e33..08312b7a2 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputDescriptionsProperty.Syntax.cs @@ -15,7 +15,7 @@ namespace ComputeSharp.D2D1.SourceGenerators; partial class ID2D1ShaderGenerator { /// - private static partial class LoadInputDescriptions + private static partial class InputDescriptions { /// /// Creates a instance for the InputDescriptions property. @@ -39,7 +39,7 @@ public static PropertyDeclarationSyntax GetSyntax(InputDescriptionsInfo inputDes memoryExpression = MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("Data"), - IdentifierName("InputDescriptions")); + IdentifierName(nameof(InputDescriptions))); additionalTypes = new[] { GetArrayDeclaration(inputDescriptionsInfo) }; } @@ -54,7 +54,7 @@ public static PropertyDeclarationSyntax GetSyntax(InputDescriptionsInfo inputDes PropertyDeclaration( GenericName(Identifier("global::System.ReadOnlyMemory")) .AddTypeArgumentListArguments(IdentifierName("global::ComputeSharp.D2D1.Interop.D2D1InputDescription")), - Identifier("InputDescriptions")) + Identifier(nameof(InputDescriptions))) .WithExplicitInterfaceSpecifier(ExplicitInterfaceSpecifier(IdentifierName($"global::ComputeSharp.D2D1.__Internals.{nameof(ID2D1Shader)}"))) .AddModifiers(Token(SyntaxKind.ReadOnlyKeyword)) .WithExpressionBody(ArrowExpressionClause(memoryExpression)) @@ -118,7 +118,7 @@ private static TypeDeclarationSyntax GetArrayDeclaration(InputDescriptionsInfo i ArrayType(IdentifierName("global::ComputeSharp.D2D1.Interop.D2D1InputDescription")) .AddRankSpecifiers(ArrayRankSpecifier(SingletonSeparatedList(OmittedArraySizeExpression())))) .AddVariables( - VariableDeclarator(Identifier("InputDescriptions")) + VariableDeclarator(Identifier(nameof(InputDescriptions))) .WithInitializer(EqualsValueClause( InitializerExpression(SyntaxKind.ArrayInitializerExpression) .AddExpressions(inputDescriptionExpressions.ToArray()))))) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputDescriptionsProperty.cs similarity index 96% rename from src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.cs rename to src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputDescriptionsProperty.cs index 7dafa78b8..dbe31d176 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadInputDescriptionsMethod.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInputDescriptionsProperty.cs @@ -13,9 +13,9 @@ namespace ComputeSharp.D2D1.SourceGenerators; partial class ID2D1ShaderGenerator { /// - /// A helper with all logic to generate the LoadInputDescriptions method. + /// A helper with all logic to generate the InputDescriptions property. /// - private static partial class LoadInputDescriptions + private static partial class InputDescriptions { /// /// Extracts the input descriptions for the current shader. diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs index 547873583..93f432e5d 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs @@ -131,8 +131,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) token.ThrowIfCancellationRequested(); - // Get the info for LoadInputDescriptions() - LoadInputDescriptions.GetInfo( + // Get the info for InputDescriptions + InputDescriptions.GetInfo( diagnostics, typeSymbol, out ImmutableArray inputDescriptions); @@ -400,19 +400,19 @@ public void Initialize(IncrementalGeneratorInitializationContext context) context.AddSource($"{item.Hierarchy.FullyQualifiedMetadataName}.{nameof(GetOutputBuffer)}.g.cs", compilationUnit.GetText(Encoding.UTF8)); }); - // Get the LoadInputDescriptions() info (hierarchy and input descriptions) + // Get the InputDescriptions info (hierarchy and input descriptions) IncrementalValuesProvider<((HierarchyInfo Hierarchy, InputDescriptionsInfo InputDescriptions) Info, bool CanUseSkipLocalsInit)> inputDescriptionsInfo = shaderInfoWithErrors .Select(static (item, _) => (item.Hierarchy, item.InputDescriptions)) .Combine(canUseSkipLocalsInit); - // Generate the LoadInputDescriptions() methods + // Generate the InputDescriptions properties context.RegisterSourceOutput(inputDescriptionsInfo, static (context, item) => { - PropertyDeclarationSyntax inputDescriptionsProperty = LoadInputDescriptions.GetSyntax(item.Info.InputDescriptions, out TypeDeclarationSyntax[] additionalTypes); + PropertyDeclarationSyntax inputDescriptionsProperty = InputDescriptions.GetSyntax(item.Info.InputDescriptions, out TypeDeclarationSyntax[] additionalTypes); CompilationUnitSyntax compilationUnit = GetCompilationUnitFromMember(item.Info.Hierarchy, inputDescriptionsProperty, item.CanUseSkipLocalsInit, additionalMemberDeclarations: additionalTypes); - context.AddSource($"{item.Info.Hierarchy.FullyQualifiedMetadataName}.{nameof(LoadInputDescriptions)}.g.cs", compilationUnit.GetText(Encoding.UTF8)); + context.AddSource($"{item.Info.Hierarchy.FullyQualifiedMetadataName}.{nameof(InputDescriptions)}.g.cs", compilationUnit.GetText(Encoding.UTF8)); }); // Get the GetPixelOptions() info (hierarchy and pixel options) diff --git a/src/ComputeSharp.D2D1/Interfaces/__Internals/ID2D1InputDescriptionsLoader.cs b/src/ComputeSharp.D2D1/Interfaces/__Internals/ID2D1InputDescriptionsLoader.cs deleted file mode 100644 index d1795a3f3..000000000 --- a/src/ComputeSharp.D2D1/Interfaces/__Internals/ID2D1InputDescriptionsLoader.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.ComponentModel; - -namespace ComputeSharp.D2D1.__Internals; - -/// -/// A base representing a loader for input descriptions in a D2D1 shader. -/// -[EditorBrowsable(EditorBrowsableState.Never)] -[Obsolete("This interface is not intended to be used directly by user code")] -public interface ID2D1InputDescriptionsLoader -{ - /// - /// Loads the available input descriptions for the shader. - /// - /// The sequence of serialized input descriptions. - void LoadInputDescriptions(ReadOnlySpan data); -} \ No newline at end of file diff --git a/src/ComputeSharp.D2D1/Interfaces/__Internals/ID2D1Shader.cs b/src/ComputeSharp.D2D1/Interfaces/__Internals/ID2D1Shader.cs index 25eb8a4b0..f5ca18f5f 100644 --- a/src/ComputeSharp.D2D1/Interfaces/__Internals/ID2D1Shader.cs +++ b/src/ComputeSharp.D2D1/Interfaces/__Internals/ID2D1Shader.cs @@ -91,16 +91,6 @@ public interface ID2D1Shader [Obsolete("This method is not intended to be used directly by user code")] ReadOnlyMemory InputDescriptions { get; } - /// - /// Loads the input descriptions for the shader, if any. - /// - /// The type of input descriptions loader being used. - /// The instance to use to load the input descriptions. - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("This method is not intended to be used directly by user code")] - void LoadInputDescriptions(ref TLoader loader) - where TLoader : struct, ID2D1InputDescriptionsLoader; - /// /// Loads the resource texture descriptions for the shader, if any. /// diff --git a/src/ComputeSharp.D2D1/Shaders/Interop/D2D1PixelShader.cs b/src/ComputeSharp.D2D1/Shaders/Interop/D2D1PixelShader.cs index b146d8ac9..d968c8c60 100644 --- a/src/ComputeSharp.D2D1/Shaders/Interop/D2D1PixelShader.cs +++ b/src/ComputeSharp.D2D1/Shaders/Interop/D2D1PixelShader.cs @@ -279,13 +279,9 @@ public static ReadOnlyMemory GetInputTypes() public static ReadOnlyMemory GetInputDescriptions() where T : unmanaged, ID2D1PixelShader { - D2D1ByteArrayInputDescriptionsLoader inputDescriptionsLoader = default; - Unsafe.SkipInit(out T shader); - shader.LoadInputDescriptions(ref inputDescriptionsLoader); - - return inputDescriptionsLoader.GetResultingInputDescriptions(); + return shader.InputDescriptions; } /// diff --git a/src/ComputeSharp.D2D1/Shaders/Loaders/D2D1ByteArrayInputDescriptionsLoader.cs b/src/ComputeSharp.D2D1/Shaders/Loaders/D2D1ByteArrayInputDescriptionsLoader.cs deleted file mode 100644 index 88c714f71..000000000 --- a/src/ComputeSharp.D2D1/Shaders/Loaders/D2D1ByteArrayInputDescriptionsLoader.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using ComputeSharp.D2D1.__Internals; -using ComputeSharp.D2D1.Interop; - -#pragma warning disable CS0618 - -namespace ComputeSharp.D2D1.Shaders.Loaders; - -/// -/// An input descriptions loader for D2D1 pixel shaders. -/// -internal struct D2D1ByteArrayInputDescriptionsLoader : ID2D1InputDescriptionsLoader -{ - /// - /// The resulting array. - /// - private D2D1InputDescription[]? inputDescriptions; - - /// - /// Gets the resulting input descriptions. - /// - /// A array with the available input descriptions. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly D2D1InputDescription[] GetResultingInputDescriptions() - { - return this.inputDescriptions!; - } - - /// - void ID2D1InputDescriptionsLoader.LoadInputDescriptions(ReadOnlySpan data) - { - this.inputDescriptions = MemoryMarshal.Cast(data).ToArray(); - } -} \ No newline at end of file