From 14af53c6a9f66008641df55ef0eb59507f223359 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 23 Sep 2023 23:11:42 +0200 Subject: [PATCH 1/7] Add HierarchyInfo.GetFullyQualifiedTypeName() API --- .../Models/HierarchyInfo.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/ComputeSharp.SourceGeneration/Models/HierarchyInfo.cs b/src/ComputeSharp.SourceGeneration/Models/HierarchyInfo.cs index c0ef8fd00..520bd83bb 100644 --- a/src/ComputeSharp.SourceGeneration/Models/HierarchyInfo.cs +++ b/src/ComputeSharp.SourceGeneration/Models/HierarchyInfo.cs @@ -42,6 +42,26 @@ public static HierarchyInfo From(INamedTypeSymbol typeSymbol) hierarchy.ToImmutable()); } + /// + /// Gets the fully qualified type name for the current instance. + /// + /// The fully qualified type name for the current instance. + public string GetFullyQualifiedTypeName() + { + using ImmutableArrayBuilder fullyQualifiedTypeName = ImmutableArrayBuilder.Rent(); + + fullyQualifiedTypeName.AddRange("global::".AsSpan()); + fullyQualifiedTypeName.AddRange(Namespace.AsSpan()); + + for (int i = Hierarchy.Length - 1; i >= 0; i--) + { + fullyQualifiedTypeName.Add('.'); + fullyQualifiedTypeName.AddRange(Hierarchy[i].QualifiedName.AsSpan()); + } + + return fullyQualifiedTypeName.ToString(); + } + /// /// Creates a instance for the current hierarchy. /// From f9aa96ce3d8249819d4abcfa2a6b19d62a916b00 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 23 Sep 2023 23:12:01 +0200 Subject: [PATCH 2/7] Generate constant buffer native layout mapping type --- ...tor.CreateLoadDispatchDataMethod.Syntax.cs | 134 +++++++++++++++++- .../ID2D1ShaderGenerator.cs | 4 +- .../Mappings/HlslKnownTypes.cs | 12 +- 3 files changed, 146 insertions(+), 4 deletions(-) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadDispatchDataMethod.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadDispatchDataMethod.Syntax.cs index 381e0b6d4..a97ea1b91 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadDispatchDataMethod.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadDispatchDataMethod.Syntax.cs @@ -1,7 +1,11 @@ +using System; using System.Collections.Immutable; using ComputeSharp.D2D1.__Internals; using ComputeSharp.D2D1.SourceGenerators.Models; using ComputeSharp.SourceGeneration.Helpers; +using ComputeSharp.SourceGeneration.Mappings; +using ComputeSharp.SourceGeneration.Models; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; @@ -19,10 +23,22 @@ partial class LoadDispatchData /// /// Creates a instance for the LoadDispatchDataMethod method. /// + /// The hiararchy info of the shader type. /// The dispatch info gathered for the current shader. + /// Any additional instances needed by the generated code, if needed. /// The resulting instance for the LoadDispatchDataMethod method. - public static MethodDeclarationSyntax GetSyntax(DispatchDataInfo dispatchInfo) + public static MethodDeclarationSyntax GetSyntax(HierarchyInfo hierarchyInfo, DispatchDataInfo dispatchInfo, out TypeDeclarationSyntax[] additionalTypes) { + // Declare the mapping constant buffer type, if needed (ie. if the shader has at least one field) + if (dispatchInfo.FieldInfos.Length == 0) + { + additionalTypes = Array.Empty(); + } + else + { + additionalTypes = new[] { GetConstantBufferDeclaration(hierarchyInfo, dispatchInfo.FieldInfos, dispatchInfo.ConstantBufferSizeInBytes) }; + } + // This code produces a method declaration as follows: // // readonly void global::ComputeSharp.D2D1.__Internals.ID2D1Shader.LoadDispatchData(ref TLoader loader) @@ -38,6 +54,122 @@ public static MethodDeclarationSyntax GetSyntax(DispatchDataInfo dispatchInfo) .WithBody(Block(GetDispatchDataLoadingStatements(dispatchInfo.FieldInfos, dispatchInfo.ConstantBufferSizeInBytes))); } + /// + /// Gets a type definition to map the constant buffer of a given shader type. + /// + /// The hiararchy info of the shader type. + /// The array of values for all captured fields. + /// The size of the shader constant buffer. + /// The object for the mapped constant buffer for the current shader type. + private static TypeDeclarationSyntax GetConstantBufferDeclaration(HierarchyInfo hierarchyInfo, ImmutableArray fieldInfos, int constantBufferSizeInBytes) + { + string fullyQualifiedTypeName = hierarchyInfo.GetFullyQualifiedTypeName(); + + using ImmutableArrayBuilder fieldDeclarations = ImmutableArrayBuilder.Rent(); + + // Appends a new field declaration for a constant buffer field: + // + // + // [global::System.Runtime.InteropServices.FieldOffset()] + // public ; + void AppendFieldDeclaration( + string comment, + TypeSyntax typeIdentifier, + string identifierName, + int fieldOffset) + { + fieldDeclarations.Add( + FieldDeclaration( + VariableDeclaration(typeIdentifier) + .AddVariables(VariableDeclarator(Identifier(identifierName)))) + .AddAttributeLists(AttributeList(SingletonSeparatedList( + Attribute(IdentifierName("global::System.Runtime.InteropServices.FieldOffset")) + .AddArgumentListArguments(AttributeArgument( + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(fieldOffset))))))) + .AddModifiers(Token(SyntaxKind.PublicKeyword)) + .WithLeadingTrivia(Comment(comment))); + } + + // Declare fields for every mapped item from the shader layout + foreach (FieldInfo fieldInfo in fieldInfos) + { + switch (fieldInfo) + { + case FieldInfo.Primitive { TypeName: "System.Boolean" } primitive: + + // Append a field as a global::ComputeSharp.Bool value (will use the implicit conversion from bool values) + AppendFieldDeclaration( + comment: $"""/// """, + typeIdentifier: IdentifierName("global::ComputeSharp.Bool"), + identifierName: string.Join("_", primitive.FieldPath), + fieldOffset: primitive.Offset); + break; + case FieldInfo.Primitive primitive: + + // Append primitive fields of other types with their mapped names + AppendFieldDeclaration( + comment: $"""/// """, + typeIdentifier: IdentifierName(HlslKnownTypes.GetMappedName(primitive.TypeName)), + identifierName: string.Join("_", primitive.FieldPath), + fieldOffset: primitive.Offset); + break; + + case FieldInfo.NonLinearMatrix matrix: + string rowTypeName = HlslKnownTypes.GetMappedName($"ComputeSharp.{matrix.ElementName}{matrix.Columns}"); + string fieldNamePrefix = string.Join("_", matrix.FieldPath); + + // Declare a field for every row of the matrix type + for (int j = 0; j < matrix.Rows; j++) + { + AppendFieldDeclaration( + comment: $"""/// Row {j} of .""", + typeIdentifier: IdentifierName(rowTypeName), + identifierName: $"{fieldNamePrefix}_{j}", + fieldOffset: matrix.Offsets[j]); + } + + break; + } + } + + // Create the constant buffer type: + // + // /// + // /// A type representing the constant buffer native layout for . + // /// + // [global::System.CodeDom.Compiler.GeneratedCode("...", "...")] + // [global::System.Diagnostics.DebuggerNonUserCode] + // [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + // [global::System.Runtime.InteropServices.StructLayout(global::System.Runtime.InteropServices.LayoutKind.Explicit, Size = )] + // file struct ConstantBuffer + // { + // + // } + return + StructDeclaration("ConstantBuffer") + .AddModifiers(Token(SyntaxKind.FileKeyword)) + .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")))), + AttributeList(SingletonSeparatedList( + Attribute(IdentifierName("global::System.Runtime.InteropServices.StructLayout")).AddArgumentListArguments( + AttributeArgument(MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("global::System.Runtime.InteropServices.LayoutKind"), + IdentifierName("Explicit"))), + AttributeArgument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(constantBufferSizeInBytes))) + .WithNameEquals(NameEquals(IdentifierName("Size"))))))) + .AddMembers(fieldDeclarations.ToArray()) + .WithLeadingTrivia( + Comment("/// "), + Comment($"""/// A type representing the constant buffer native layout for ."""), + Comment("/// ")); + } + /// /// Gets a sequence of statements to load the dispatch data for a given shader. /// diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs index 5194aafa8..1d85eac37 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs @@ -307,8 +307,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Generate the LoadDispatchData() methods context.RegisterSourceOutput(dispatchDataInfo, static (context, item) => { - MethodDeclarationSyntax loadDispatchDataMethod = LoadDispatchData.GetSyntax(item.Info.Dispatch); - CompilationUnitSyntax compilationUnit = GetCompilationUnitFromMember(item.Info.Hierarchy, loadDispatchDataMethod, item.CanUseSkipLocalsInit); + MethodDeclarationSyntax loadDispatchDataMethod = LoadDispatchData.GetSyntax(item.Info.Hierarchy, item.Info.Dispatch, out TypeDeclarationSyntax[] additionalTypes); + CompilationUnitSyntax compilationUnit = GetCompilationUnitFromMember(item.Info.Hierarchy, loadDispatchDataMethod, item.CanUseSkipLocalsInit, additionalMemberDeclarations: additionalTypes); context.AddSource($"{item.Info.Hierarchy.FullyQualifiedMetadataName}.{nameof(LoadDispatchData)}.g.cs", compilationUnit.GetText(Encoding.UTF8)); }); diff --git a/src/ComputeSharp.SourceGeneration.Hlsl/Mappings/HlslKnownTypes.cs b/src/ComputeSharp.SourceGeneration.Hlsl/Mappings/HlslKnownTypes.cs index cecae13fe..280c41969 100644 --- a/src/ComputeSharp.SourceGeneration.Hlsl/Mappings/HlslKnownTypes.cs +++ b/src/ComputeSharp.SourceGeneration.Hlsl/Mappings/HlslKnownTypes.cs @@ -181,8 +181,18 @@ public static string GetMappedElementName(IArrayTypeSymbol typeSymbol) /// Gets the mapped HLSL-compatible type name for the input type name. /// /// The input type name to map. - /// The resulting mapped type name, if found. /// The HLSL-compatible type name that can be used in an HLSL shader. + public static string GetMappedName(string originalName) + { + return KnownHlslTypes[originalName]; + } + + /// + /// Tries to get the mapped HLSL-compatible type name for the input type name. + /// + /// The input type name to map. + /// The resulting mapped type name, if found. + /// Whether a mapped name was available. public static bool TryGetMappedName(string originalName, out string? mappedName) { return KnownHlslTypes.TryGetValue(originalName, out mappedName); From 502e5e81facbf37331d02b2a482d24b8939a3d02 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 23 Sep 2023 23:33:25 +0200 Subject: [PATCH 3/7] Implement simple row accessors for matrix types --- .../Primitives/Bool/BoolMxN.g.cs | 64 +++++++++---------- .../Primitives/Bool/BoolMxN.tt | 2 +- .../Primitives/Double/DoubleMxN.g.cs | 64 +++++++++---------- .../Primitives/Double/DoubleMxN.tt | 2 +- .../Primitives/Float/FloatMxN.g.cs | 64 +++++++++---------- .../Primitives/Float/FloatMxN.tt | 2 +- .../Primitives/Int/IntMxN.g.cs | 64 +++++++++---------- .../Primitives/Int/IntMxN.tt | 2 +- .../Primitives/MatrixType.ttinclude | 4 +- .../Primitives/UInt/UIntMxN.g.cs | 64 +++++++++---------- .../Primitives/UInt/UIntMxN.tt | 2 +- 11 files changed, 167 insertions(+), 167 deletions(-) diff --git a/src/ComputeSharp.Core/Primitives/Bool/BoolMxN.g.cs b/src/ComputeSharp.Core/Primitives/Bool/BoolMxN.g.cs index b173a1474..2d09df216 100644 --- a/src/ComputeSharp.Core/Primitives/Bool/BoolMxN.g.cs +++ b/src/ComputeSharp.Core/Primitives/Bool/BoolMxN.g.cs @@ -36,10 +36,10 @@ public Bool1x1(bool m11) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref bool this[int row] => ref *(bool*)UndefinedData; + public ref bool this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(bool) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -184,10 +184,10 @@ public Bool1x2(bool m11, bool m12) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Bool2 this[int row] => ref *(Bool2*)UndefinedData; + public ref Bool2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Bool2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -350,10 +350,10 @@ public Bool1x3(bool m11, bool m12, bool m13) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Bool3 this[int row] => ref *(Bool3*)UndefinedData; + public ref Bool3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Bool3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -528,10 +528,10 @@ public Bool1x4(bool m11, bool m12, bool m13, bool m14) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Bool4 this[int row] => ref *(Bool4*)UndefinedData; + public ref Bool4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Bool4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -703,10 +703,10 @@ public Bool2x1(bool m11, bool m21) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref bool this[int row] => ref *(bool*)UndefinedData; + public ref bool this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(bool) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -887,10 +887,10 @@ public Bool2x2(Bool2 row1, Bool2 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Bool2 this[int row] => ref *(Bool2*)UndefinedData; + public ref Bool2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Bool2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1091,10 +1091,10 @@ public Bool2x3(Bool3 row1, Bool3 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Bool3 this[int row] => ref *(Bool3*)UndefinedData; + public ref Bool3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Bool3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1321,10 +1321,10 @@ public Bool2x4(Bool4 row1, Bool4 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Bool4 this[int row] => ref *(Bool4*)UndefinedData; + public ref Bool4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Bool4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1523,10 +1523,10 @@ public Bool3x1(bool m11, bool m21, bool m31) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref bool this[int row] => ref *(bool*)UndefinedData; + public ref bool this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(bool) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1727,10 +1727,10 @@ public Bool3x2(Bool2 row1, Bool2 row2, Bool2 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Bool2 this[int row] => ref *(Bool2*)UndefinedData; + public ref Bool2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Bool2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1964,10 +1964,10 @@ public Bool3x3(Bool3 row1, Bool3 row2, Bool3 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Bool3 this[int row] => ref *(Bool3*)UndefinedData; + public ref Bool3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Bool3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2240,10 +2240,10 @@ public Bool3x4(Bool4 row1, Bool4 row2, Bool4 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Bool4 this[int row] => ref *(Bool4*)UndefinedData; + public ref Bool4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Bool4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2475,10 +2475,10 @@ public Bool4x1(bool m11, bool m21, bool m31, bool m41) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref bool this[int row] => ref *(bool*)UndefinedData; + public ref bool this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(bool) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2699,10 +2699,10 @@ public Bool4x2(Bool2 row1, Bool2 row2, Bool2 row3, Bool2 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Bool2 this[int row] => ref *(Bool2*)UndefinedData; + public ref Bool2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Bool2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2969,10 +2969,10 @@ public Bool4x3(Bool3 row1, Bool3 row2, Bool3 row3, Bool3 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Bool3 this[int row] => ref *(Bool3*)UndefinedData; + public ref Bool3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Bool3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -3291,10 +3291,10 @@ public Bool4x4(Bool4 row1, Bool4 row2, Bool4 row3, Bool4 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Bool4 this[int row] => ref *(Bool4*)UndefinedData; + public ref Bool4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Bool4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. diff --git a/src/ComputeSharp.Core/Primitives/Bool/BoolMxN.tt b/src/ComputeSharp.Core/Primitives/Bool/BoolMxN.tt index 76a0d8bcc..dca930d91 100644 --- a/src/ComputeSharp.Core/Primitives/Bool/BoolMxN.tt +++ b/src/ComputeSharp.Core/Primitives/Bool/BoolMxN.tt @@ -1,4 +1,4 @@ -<#@include file="..\MatrixType.ttinclude" #> +<#@include file="..\MatrixType.ttinclude" #> <# GenerateAllMatrixProperties("Bool", sizeof(int)); #> \ No newline at end of file diff --git a/src/ComputeSharp.Core/Primitives/Double/DoubleMxN.g.cs b/src/ComputeSharp.Core/Primitives/Double/DoubleMxN.g.cs index f946b9c5e..5657f6e26 100644 --- a/src/ComputeSharp.Core/Primitives/Double/DoubleMxN.g.cs +++ b/src/ComputeSharp.Core/Primitives/Double/DoubleMxN.g.cs @@ -36,10 +36,10 @@ public Double1x1(double m11) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref double this[int row] => ref *(double*)UndefinedData; + public ref double this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(double) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -238,10 +238,10 @@ public Double1x2(double m11, double m12) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Double2 this[int row] => ref *(Double2*)UndefinedData; + public ref Double2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Double2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -458,10 +458,10 @@ public Double1x3(double m11, double m12, double m13) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Double3 this[int row] => ref *(Double3*)UndefinedData; + public ref Double3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Double3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -690,10 +690,10 @@ public Double1x4(double m11, double m12, double m13, double m14) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Double4 this[int row] => ref *(Double4*)UndefinedData; + public ref Double4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Double4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -919,10 +919,10 @@ public Double2x1(double m11, double m21) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref double this[int row] => ref *(double*)UndefinedData; + public ref double this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(double) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1157,10 +1157,10 @@ public Double2x2(Double2 row1, Double2 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Double2 this[int row] => ref *(Double2*)UndefinedData; + public ref Double2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Double2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1415,10 +1415,10 @@ public Double2x3(Double3 row1, Double3 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Double3 this[int row] => ref *(Double3*)UndefinedData; + public ref Double3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Double3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1699,10 +1699,10 @@ public Double2x4(Double4 row1, Double4 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Double4 this[int row] => ref *(Double4*)UndefinedData; + public ref Double4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Double4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1955,10 +1955,10 @@ public Double3x1(double m11, double m21, double m31) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref double this[int row] => ref *(double*)UndefinedData; + public ref double this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(double) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2213,10 +2213,10 @@ public Double3x2(Double2 row1, Double2 row2, Double2 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Double2 this[int row] => ref *(Double2*)UndefinedData; + public ref Double2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Double2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2504,10 +2504,10 @@ public Double3x3(Double3 row1, Double3 row2, Double3 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Double3 this[int row] => ref *(Double3*)UndefinedData; + public ref Double3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Double3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2834,10 +2834,10 @@ public Double3x4(Double4 row1, Double4 row2, Double4 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Double4 this[int row] => ref *(Double4*)UndefinedData; + public ref Double4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Double4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -3123,10 +3123,10 @@ public Double4x1(double m11, double m21, double m31, double m41) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref double this[int row] => ref *(double*)UndefinedData; + public ref double this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(double) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -3401,10 +3401,10 @@ public Double4x2(Double2 row1, Double2 row2, Double2 row3, Double2 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Double2 this[int row] => ref *(Double2*)UndefinedData; + public ref Double2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Double2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -3725,10 +3725,10 @@ public Double4x3(Double3 row1, Double3 row2, Double3 row3, Double3 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Double3 this[int row] => ref *(Double3*)UndefinedData; + public ref Double3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Double3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -4101,10 +4101,10 @@ public Double4x4(Double4 row1, Double4 row2, Double4 row3, Double4 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Double4 this[int row] => ref *(Double4*)UndefinedData; + public ref Double4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Double4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. diff --git a/src/ComputeSharp.Core/Primitives/Double/DoubleMxN.tt b/src/ComputeSharp.Core/Primitives/Double/DoubleMxN.tt index 6ecc4f828..93988f0d5 100644 --- a/src/ComputeSharp.Core/Primitives/Double/DoubleMxN.tt +++ b/src/ComputeSharp.Core/Primitives/Double/DoubleMxN.tt @@ -1,4 +1,4 @@ -<#@include file="..\MatrixType.ttinclude" #> +<#@include file="..\MatrixType.ttinclude" #> <# GenerateAllMatrixProperties("Double", sizeof(double)); #> \ No newline at end of file diff --git a/src/ComputeSharp.Core/Primitives/Float/FloatMxN.g.cs b/src/ComputeSharp.Core/Primitives/Float/FloatMxN.g.cs index 33554337e..d0585c39b 100644 --- a/src/ComputeSharp.Core/Primitives/Float/FloatMxN.g.cs +++ b/src/ComputeSharp.Core/Primitives/Float/FloatMxN.g.cs @@ -37,10 +37,10 @@ public Float1x1(float m11) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref float this[int row] => ref *(float*)UndefinedData; + public ref float this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(float) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -257,10 +257,10 @@ public Float1x2(float m11, float m12) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Float2 this[int row] => ref *(Float2*)UndefinedData; + public ref Float2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Float2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -579,10 +579,10 @@ public Float1x3(float m11, float m12, float m13) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Float3 this[int row] => ref *(Float3*)UndefinedData; + public ref Float3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Float3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -913,10 +913,10 @@ public Float1x4(float m11, float m12, float m13, float m14) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Float4 this[int row] => ref *(Float4*)UndefinedData; + public ref Float4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Float4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1244,10 +1244,10 @@ public Float2x1(float m11, float m21) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref float this[int row] => ref *(float*)UndefinedData; + public ref float this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(float) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1570,10 +1570,10 @@ public Float2x2(Float2 row1, Float2 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Float2 this[int row] => ref *(Float2*)UndefinedData; + public ref Float2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Float2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1846,10 +1846,10 @@ public Float2x3(Float3 row1, Float3 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Float3 this[int row] => ref *(Float3*)UndefinedData; + public ref Float3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Float3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2232,10 +2232,10 @@ public Float2x4(Float4 row1, Float4 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Float4 this[int row] => ref *(Float4*)UndefinedData; + public ref Float4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Float4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2590,10 +2590,10 @@ public Float3x1(float m11, float m21, float m31) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref float this[int row] => ref *(float*)UndefinedData; + public ref float this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(float) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2936,10 +2936,10 @@ public Float3x2(Float2 row1, Float2 row2, Float2 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Float2 this[int row] => ref *(Float2*)UndefinedData; + public ref Float2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Float2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -3329,10 +3329,10 @@ public Float3x3(Float3 row1, Float3 row2, Float3 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Float3 this[int row] => ref *(Float3*)UndefinedData; + public ref Float3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Float3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -3677,10 +3677,10 @@ public Float3x4(Float4 row1, Float4 row2, Float4 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Float4 this[int row] => ref *(Float4*)UndefinedData; + public ref Float4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Float4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -4068,10 +4068,10 @@ public Float4x1(float m11, float m21, float m31, float m41) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref float this[int row] => ref *(float*)UndefinedData; + public ref float this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(float) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -4434,10 +4434,10 @@ public Float4x2(Float2 row1, Float2 row2, Float2 row3, Float2 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Float2 this[int row] => ref *(Float2*)UndefinedData; + public ref Float2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Float2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -4860,10 +4860,10 @@ public Float4x3(Float3 row1, Float3 row2, Float3 row3, Float3 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Float3 this[int row] => ref *(Float3*)UndefinedData; + public ref Float3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Float3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -5338,10 +5338,10 @@ public Float4x4(Float4 row1, Float4 row2, Float4 row3, Float4 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Float4 this[int row] => ref *(Float4*)UndefinedData; + public ref Float4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Float4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. diff --git a/src/ComputeSharp.Core/Primitives/Float/FloatMxN.tt b/src/ComputeSharp.Core/Primitives/Float/FloatMxN.tt index 977557519..3d8164070 100644 --- a/src/ComputeSharp.Core/Primitives/Float/FloatMxN.tt +++ b/src/ComputeSharp.Core/Primitives/Float/FloatMxN.tt @@ -1,4 +1,4 @@ -<#@include file="..\MatrixType.ttinclude" #> +<#@include file="..\MatrixType.ttinclude" #> <# GenerateAllMatrixProperties("Float", sizeof(float)); #> \ No newline at end of file diff --git a/src/ComputeSharp.Core/Primitives/Int/IntMxN.g.cs b/src/ComputeSharp.Core/Primitives/Int/IntMxN.g.cs index a092d2b5b..3a0bed1a6 100644 --- a/src/ComputeSharp.Core/Primitives/Int/IntMxN.g.cs +++ b/src/ComputeSharp.Core/Primitives/Int/IntMxN.g.cs @@ -37,10 +37,10 @@ public Int1x1(int m11) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref int this[int row] => ref *(int*)UndefinedData; + public ref int this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(int) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -355,10 +355,10 @@ public Int1x2(int m11, int m12) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Int2 this[int row] => ref *(Int2*)UndefinedData; + public ref Int2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Int2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -775,10 +775,10 @@ public Int1x3(int m11, int m12, int m13) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Int3 this[int row] => ref *(Int3*)UndefinedData; + public ref Int3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Int3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1207,10 +1207,10 @@ public Int1x4(int m11, int m12, int m13, int m14) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Int4 this[int row] => ref *(Int4*)UndefinedData; + public ref Int4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Int4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1636,10 +1636,10 @@ public Int2x1(int m11, int m21) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref int this[int row] => ref *(int*)UndefinedData; + public ref int this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(int) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2060,10 +2060,10 @@ public Int2x2(Int2 row1, Int2 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Int2 this[int row] => ref *(Int2*)UndefinedData; + public ref Int2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Int2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2434,10 +2434,10 @@ public Int2x3(Int3 row1, Int3 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Int3 this[int row] => ref *(Int3*)UndefinedData; + public ref Int3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Int3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2918,10 +2918,10 @@ public Int2x4(Int4 row1, Int4 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Int4 this[int row] => ref *(Int4*)UndefinedData; + public ref Int4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Int4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -3374,10 +3374,10 @@ public Int3x1(int m11, int m21, int m31) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref int this[int row] => ref *(int*)UndefinedData; + public ref int this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(int) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -3818,10 +3818,10 @@ public Int3x2(Int2 row1, Int2 row2, Int2 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Int2 this[int row] => ref *(Int2*)UndefinedData; + public ref Int2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Int2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -4309,10 +4309,10 @@ public Int3x3(Int3 row1, Int3 row2, Int3 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Int3 this[int row] => ref *(Int3*)UndefinedData; + public ref Int3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Int3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -4755,10 +4755,10 @@ public Int3x4(Int4 row1, Int4 row2, Int4 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Int4 this[int row] => ref *(Int4*)UndefinedData; + public ref Int4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Int4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -5244,10 +5244,10 @@ public Int4x1(int m11, int m21, int m31, int m41) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref int this[int row] => ref *(int*)UndefinedData; + public ref int this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(int) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -5708,10 +5708,10 @@ public Int4x2(Int2 row1, Int2 row2, Int2 row3, Int2 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Int2 this[int row] => ref *(Int2*)UndefinedData; + public ref Int2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Int2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -6232,10 +6232,10 @@ public Int4x3(Int3 row1, Int3 row2, Int3 row3, Int3 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Int3 this[int row] => ref *(Int3*)UndefinedData; + public ref Int3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Int3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -6808,10 +6808,10 @@ public Int4x4(Int4 row1, Int4 row2, Int4 row3, Int4 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref Int4 this[int row] => ref *(Int4*)UndefinedData; + public ref Int4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(Int4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. diff --git a/src/ComputeSharp.Core/Primitives/Int/IntMxN.tt b/src/ComputeSharp.Core/Primitives/Int/IntMxN.tt index bf70cf4d6..71f5f0c28 100644 --- a/src/ComputeSharp.Core/Primitives/Int/IntMxN.tt +++ b/src/ComputeSharp.Core/Primitives/Int/IntMxN.tt @@ -1,4 +1,4 @@ -<#@include file="..\MatrixType.ttinclude" #> +<#@include file="..\MatrixType.ttinclude" #> <# GenerateAllMatrixProperties("Int", sizeof(int)); #> \ No newline at end of file diff --git a/src/ComputeSharp.Core/Primitives/MatrixType.ttinclude b/src/ComputeSharp.Core/Primitives/MatrixType.ttinclude index ab58fef34..9c5a9d0ae 100644 --- a/src/ComputeSharp.Core/Primitives/MatrixType.ttinclude +++ b/src/ComputeSharp.Core/Primitives/MatrixType.ttinclude @@ -152,10 +152,10 @@ public unsafe partial struct <#=fullTypeName#> /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref <#=rowTypeName#> this[int row] => ref *(<#=rowTypeName#>*)UndefinedData; + public ref <#=rowTypeName#> this[int row] => ref Unsafe.As<<#=fieldElementTypeName#>, <#=rowTypeName#>>(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(<#=rowTypeName#>) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. diff --git a/src/ComputeSharp.Core/Primitives/UInt/UIntMxN.g.cs b/src/ComputeSharp.Core/Primitives/UInt/UIntMxN.g.cs index 14df1cf2f..7f1a728cc 100644 --- a/src/ComputeSharp.Core/Primitives/UInt/UIntMxN.g.cs +++ b/src/ComputeSharp.Core/Primitives/UInt/UIntMxN.g.cs @@ -36,10 +36,10 @@ public UInt1x1(uint m11) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref uint this[int row] => ref *(uint*)UndefinedData; + public ref uint this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(uint) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -329,10 +329,10 @@ public UInt1x2(uint m11, uint m12) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref UInt2 this[int row] => ref *(UInt2*)UndefinedData; + public ref UInt2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(UInt2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -640,10 +640,10 @@ public UInt1x3(uint m11, uint m12, uint m13) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref UInt3 this[int row] => ref *(UInt3*)UndefinedData; + public ref UInt3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(UInt3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -963,10 +963,10 @@ public UInt1x4(uint m11, uint m12, uint m13, uint m14) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref UInt4 this[int row] => ref *(UInt4*)UndefinedData; + public ref UInt4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(UInt4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1283,10 +1283,10 @@ public UInt2x1(uint m11, uint m21) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref uint this[int row] => ref *(uint*)UndefinedData; + public ref uint this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(uint) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1612,10 +1612,10 @@ public UInt2x2(UInt2 row1, UInt2 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref UInt2 this[int row] => ref *(UInt2*)UndefinedData; + public ref UInt2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(UInt2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -1961,10 +1961,10 @@ public UInt2x3(UInt3 row1, UInt3 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref UInt3 this[int row] => ref *(UInt3*)UndefinedData; + public ref UInt3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(UInt3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2336,10 +2336,10 @@ public UInt2x4(UInt4 row1, UInt4 row2) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref UInt4 this[int row] => ref *(UInt4*)UndefinedData; + public ref UInt4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(UInt4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -2683,10 +2683,10 @@ public UInt3x1(uint m11, uint m21, uint m31) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref uint this[int row] => ref *(uint*)UndefinedData; + public ref uint this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(uint) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -3032,10 +3032,10 @@ public UInt3x2(UInt2 row1, UInt2 row2, UInt2 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref UInt2 this[int row] => ref *(UInt2*)UndefinedData; + public ref UInt2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(UInt2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -3414,10 +3414,10 @@ public UInt3x3(UInt3 row1, UInt3 row2, UInt3 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref UInt3 this[int row] => ref *(UInt3*)UndefinedData; + public ref UInt3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(UInt3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -3835,10 +3835,10 @@ public UInt3x4(UInt4 row1, UInt4 row2, UInt4 row3) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref UInt4 this[int row] => ref *(UInt4*)UndefinedData; + public ref UInt4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(UInt4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -4215,10 +4215,10 @@ public UInt4x1(uint m11, uint m21, uint m31, uint m41) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref uint this[int row] => ref *(uint*)UndefinedData; + public ref uint this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(uint) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -4584,10 +4584,10 @@ public UInt4x2(UInt2 row1, UInt2 row2, UInt2 row3, UInt2 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref UInt2 this[int row] => ref *(UInt2*)UndefinedData; + public ref UInt2 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(UInt2) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -4999,10 +4999,10 @@ public UInt4x3(UInt3 row1, UInt3 row2, UInt3 row3, UInt3 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref UInt3 this[int row] => ref *(UInt3*)UndefinedData; + public ref UInt3 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(UInt3) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. @@ -5466,10 +5466,10 @@ public UInt4x4(UInt4 row1, UInt4 row2, UInt4 row3, UInt4 row4) /// The row to access. /// /// Unlike with vector types, these properties cannot validate in advance which combinations are writeable, so callers should ensure proper use. - /// This method is an intrinsic and can only be used within a shader on the GPU. Using it on the CPU is undefined behavior. + /// Invoking this method with an invalid row argument results in undefined behavior. /// [UnscopedRef] - public ref UInt4 this[int row] => ref *(UInt4*)UndefinedData; + public ref UInt4 this[int row] => ref Unsafe.As(ref Unsafe.AddByteOffset(ref this.m11, (nint)(uint)(sizeof(UInt4) * row))); /// /// Gets a swizzled reference to a specific sequence of items in the current instance. diff --git a/src/ComputeSharp.Core/Primitives/UInt/UIntMxN.tt b/src/ComputeSharp.Core/Primitives/UInt/UIntMxN.tt index 59d27cd95..2ea2fb43a 100644 --- a/src/ComputeSharp.Core/Primitives/UInt/UIntMxN.tt +++ b/src/ComputeSharp.Core/Primitives/UInt/UIntMxN.tt @@ -1,4 +1,4 @@ -<#@include file="..\MatrixType.ttinclude" #> +<#@include file="..\MatrixType.ttinclude" #> <# GenerateAllMatrixProperties("UInt", sizeof(uint)); #> \ No newline at end of file From bfc44bb6d9230d5750fba522bce996030ca5d993 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 23 Sep 2023 23:52:42 +0200 Subject: [PATCH 4/7] Use generated constant buffer type in LoadDispatchData --- ...tor.CreateLoadDispatchDataMethod.Syntax.cs | 127 ++++++++---------- 1 file changed, 57 insertions(+), 70 deletions(-) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadDispatchDataMethod.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadDispatchDataMethod.Syntax.cs index a97ea1b91..c33133234 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadDispatchDataMethod.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadDispatchDataMethod.Syntax.cs @@ -41,14 +41,14 @@ public static MethodDeclarationSyntax GetSyntax(HierarchyInfo hierarchyInfo, Dis // This code produces a method declaration as follows: // - // readonly void global::ComputeSharp.D2D1.__Internals.ID2D1Shader.LoadDispatchData(ref TLoader loader) + // readonly unsafe void global::ComputeSharp.D2D1.__Internals.ID2D1Shader.LoadDispatchData(ref TLoader loader) // { // // } return MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier(nameof(LoadDispatchData))) .WithExplicitInterfaceSpecifier(ExplicitInterfaceSpecifier(IdentifierName($"global::ComputeSharp.D2D1.__Internals.{nameof(ID2D1Shader)}"))) - .AddModifiers(Token(SyntaxKind.ReadOnlyKeyword)) + .AddModifiers(Token(SyntaxKind.ReadOnlyKeyword), Token(SyntaxKind.UnsafeKeyword)) .AddTypeParameterListParameters(TypeParameter(Identifier("TLoader"))) .AddParameterListParameters(Parameter(Identifier("loader")).AddModifiers(Token(SyntaxKind.RefKeyword)).WithType(IdentifierName("TLoader"))) .WithBody(Block(GetDispatchDataLoadingStatements(dispatchInfo.FieldInfos, dispatchInfo.ConstantBufferSizeInBytes))); @@ -178,10 +178,11 @@ void AppendFieldDeclaration( /// The sequence of instances to load the shader dispatch data. private static ImmutableArray GetDispatchDataLoadingStatements(ImmutableArray fieldInfos, int constantBufferSizeInBytes) { - // If there are no fields, just load an empty buffer + // If there are no fields, just load an empty buffer: + // + // loader.LoadConstantBuffer(default); if (fieldInfos.IsEmpty) { - // loader.LoadConstantBuffer(default); return ImmutableArray.Create( ExpressionStatement( @@ -198,95 +199,72 @@ private static ImmutableArray GetDispatchDataLoadingStatements( using ImmutableArrayBuilder statements = ImmutableArrayBuilder.Rent(); - // 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(constantBufferSizeInBytes))))))))))); - - // ref byte r0 = ref data[0]; + // ConstantBuffer data; 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)))))))))); + VariableDeclaration(IdentifierName("ConstantBuffer")) + .AddVariables(VariableDeclarator(Identifier("data"))))); // Generate loading statements for each captured field foreach (FieldInfo fieldInfo in fieldInfos) { switch (fieldInfo) { - case FieldInfo.Primitive { TypeName: "System.Boolean" } primitive: - - // Read a boolean value and cast it to Bool first, which will apply the correct size expansion. This will generate the following: - // - // global::System.Runtime.CompilerServices.Unsafe.As( - // ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint))) = (global::ComputeSharp.Bool) - statements.Add(ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - ParseExpression($"global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint){primitive.Offset}))"), - ParseExpression($"(global::ComputeSharp.Bool){string.Join(".", primitive.FieldPath)}")))); - break; case FieldInfo.Primitive primitive: - // Read a primitive value and serialize it into the target buffer. This will generate: + // Assign a primitive value: // - // 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){primitive.Offset}))"), - ParseExpression($"{string.Join(".", primitive.FieldPath)}")))); + // data. = this.; + statements.Add( + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("data"), + IdentifierName(string.Join("_", primitive.FieldPath))), + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ThisExpression(), + IdentifierName(string.Join(".", primitive.FieldPath)))))); break; case FieldInfo.NonLinearMatrix matrix: - string rowTypeName = $"global::ComputeSharp.{matrix.ElementName}{matrix.Columns}"; - string rowLocalName = $"__{string.Join("_", matrix.FieldPath)}__row0"; - - // Declare a local to index into individual rows. This will generate: - // - // ref = ref global::System.Runtime.CompilerServices.Unsafe.As, >( - // ref global::System.Runtime.CompilerServices.Unsafe.AsRef(in )); - statements.Add(ParseStatement($"ref {rowTypeName} {rowLocalName} = ref global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AsRef(in {string.Join(".", matrix.FieldPath)}));")); + string fieldPath = string.Join(".", matrix.FieldPath); + string fieldNamePrefix = string.Join("_", matrix.FieldPath); - // Generate the loading code for each individual row, with proper alignment. - // This will result in the following (assuming Float2x3 m): + // Assign all rows of a given matrix type: // - // ref global::ComputeSharp.Float3 __m__row0 = ref global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AsRef(in m)); - // global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint)rawDataOffset)) = global::System.Runtime.CompilerServices.Unsafe.Add(ref __m__row0, 0); - // global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint)(rawDataOffset + 16))) = global::System.Runtime.CompilerServices.Unsafe.Add(ref __m__row0, 1); + // data. = this.[0]; + // data. = this.[1]; + // ... + // data. = this.[N]; for (int j = 0; j < matrix.Rows; j++) { - statements.Add(ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - ParseExpression($"global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint){matrix.Offsets[j]}))"), - ParseExpression($"global::System.Runtime.CompilerServices.Unsafe.Add(ref {rowLocalName}, {j})")))); + statements.Add( + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("data"), + IdentifierName($"{fieldNamePrefix}_{j}")), + ElementAccessExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ThisExpression(), + IdentifierName(fieldPath))) + .AddArgumentListArguments( + Argument(LiteralExpression( + SyntaxKind.NumericLiteralExpression, + Literal(j))))))); } break; } } - // loader.LoadConstantBuffer(data); + // loader.LoadConstantBuffer(new global::System.ReadOnlySpan(&data, sizeof(ConstantBuffer))); statements.Add( ExpressionStatement( InvocationExpression( @@ -294,7 +272,16 @@ private static ImmutableArray GetDispatchDataLoadingStatements( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("loader"), IdentifierName("LoadConstantBuffer"))) - .AddArgumentListArguments(Argument(IdentifierName("data"))))); + .AddArgumentListArguments(Argument( + ObjectCreationExpression( + GenericName(Identifier("global::System.ReadOnlySpan")) + .AddTypeArgumentListArguments(PredefinedType(Token(SyntaxKind.ByteKeyword)))) + .AddArgumentListArguments( + Argument( + PrefixUnaryExpression( + SyntaxKind.AddressOfExpression, + IdentifierName("data"))), + Argument(SizeOfExpression(IdentifierName("ConstantBuffer")))))))); return statements.ToImmutable(); } From 55e415d1b12206a16cdec6ce656ef93a2ad3a2b8 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 24 Sep 2023 15:29:09 +0200 Subject: [PATCH 5/7] Use generated constant buffer type in InitializeFromDispatchData --- ...InitializeFromDispatchDataMethod.Syntax.cs | 113 ++++++++++++------ ...tor.CreateLoadDispatchDataMethod.Syntax.cs | 20 ++-- 2 files changed, 85 insertions(+), 48 deletions(-) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInitializeFromDispatchDataMethod.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInitializeFromDispatchDataMethod.Syntax.cs index 0c1a35981..7ad7435af 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInitializeFromDispatchDataMethod.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateInitializeFromDispatchDataMethod.Syntax.cs @@ -67,20 +67,31 @@ private static ImmutableArray GetDispatchDataUnloadingStatement IdentifierName("IsEmpty")), Block(ReturnStatement()))); - // ref byte r0 = ref global::System.Runtime.InteropServices.MemoryMarshal.GetReference(data); + // ref readonly ConstantBuffer buffer = ref global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.InteropServices.MemoryMarshal.GetReference(data)); statements.Add( LocalDeclarationStatement( - VariableDeclaration(RefType(PredefinedType(Token(SyntaxKind.ByteKeyword)))) - .AddVariables( - VariableDeclarator(Identifier("r0")) - .WithInitializer(EqualsValueClause( - RefExpression( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("global::System.Runtime.InteropServices.MemoryMarshal"), - IdentifierName("GetReference"))) - .AddArgumentListArguments(Argument(IdentifierName("data"))))))))); + VariableDeclaration(RefType(IdentifierName("ConstantBuffer")).WithReadOnlyKeyword(Token(SyntaxKind.ReadOnlyKeyword))) + .AddVariables( + VariableDeclarator(Identifier("buffer")) + .WithInitializer( + EqualsValueClause(RefExpression( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("global::System.Runtime.CompilerServices.Unsafe"), + GenericName(Identifier("As")) + .AddTypeArgumentListArguments( + PredefinedType(Token(SyntaxKind.ByteKeyword)), + IdentifierName("ConstantBuffer")))) + .AddArgumentListArguments( + Argument( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("global::System.Runtime.InteropServices.MemoryMarshal"), + IdentifierName("GetReference"))) + .AddArgumentListArguments(Argument(IdentifierName("data")))) + .WithRefOrOutKeyword(Token(SyntaxKind.RefKeyword))))))))); // Generate loading statements for each captured field foreach (FieldInfo fieldInfo in fieldInfos) @@ -89,40 +100,66 @@ private static ImmutableArray GetDispatchDataUnloadingStatement { case FieldInfo.Primitive primitive: - // Read a primitive value from the target buffer. This will generate: + // Read a primitive value: // - // Unsafe.AsRef(in ) = 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.AsRef(in {string.Join(".", primitive.FieldPath)})"), - ParseExpression($"global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint){primitive.Offset}))")))); + // global::System.Runtime.CompilerServices.Unsafe.AsRef(in this.) = buffer.; + statements.Add( + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("global::System.Runtime.CompilerServices.Unsafe"), + IdentifierName("AsRef"))) + .AddArgumentListArguments( + Argument(MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ThisExpression(), + IdentifierName(string.Join(".", primitive.FieldPath)))) + .WithRefKindKeyword(Token(SyntaxKind.InKeyword))), + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("buffer"), + IdentifierName(string.Join("_", primitive.FieldPath)))))); break; case FieldInfo.NonLinearMatrix matrix: - string rowTypeName = $"global::ComputeSharp.{matrix.ElementName}{matrix.Columns}"; - string rowLocalName = $"__{string.Join("_", matrix.FieldPath)}__row0"; - - // Declare a local to index into individual rows. This will generate: - // - // ref = ref global::System.Runtime.CompilerServices.Unsafe.As, >( - // ref global::System.Runtime.CompilerServices.Unsafe.AsRef(in )); - statements.Add(ParseStatement($"ref {rowTypeName} {rowLocalName} = ref global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AsRef(in {string.Join(".", matrix.FieldPath)}));")); + string fieldPath = string.Join(".", matrix.FieldPath); + string fieldNamePrefix = string.Join("_", matrix.FieldPath); - // Generate the loading code for each individual row, with proper alignment. - // This will result in the following (assuming Float2x3 m): + // Read all rows of a given matrix type: // - // ref global::ComputeSharp.Float3 __m__row0 = ref global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AsRef(in m)); - // global::System.Runtime.CompilerServices.Unsafe.Add(ref __m__row0, 0) = global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint)rawDataOffset)); - // global::System.Runtime.CompilerServices.Unsafe.Add(ref __m__row0, 1) = global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint)(rawDataOffset + 16))); + // global::System.Runtime.CompilerServices.Unsafe.AsRef(in this.)[0] = buffer.; + // global::System.Runtime.CompilerServices.Unsafe.AsRef(in this.)[1] = buffer.; + // ... + // global::System.Runtime.CompilerServices.Unsafe.AsRef(in this.)[N] = buffer.; for (int j = 0; j < matrix.Rows; j++) { - statements.Add(ExpressionStatement( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - ParseExpression($"global::System.Runtime.CompilerServices.Unsafe.Add(ref {rowLocalName}, {j})"), - ParseExpression($"global::System.Runtime.CompilerServices.Unsafe.As(ref global::System.Runtime.CompilerServices.Unsafe.AddByteOffset(ref r0, (nint){matrix.Offsets[j]}))")))); + statements.Add( + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + ElementAccessExpression( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("global::System.Runtime.CompilerServices.Unsafe"), + IdentifierName("AsRef"))) + .AddArgumentListArguments( + Argument(MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ThisExpression(), + IdentifierName(fieldPath))) + .WithRefKindKeyword(Token(SyntaxKind.InKeyword)))) + .AddArgumentListArguments( + Argument(LiteralExpression( + SyntaxKind.NumericLiteralExpression, + Literal(j)))), + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("buffer"), + IdentifierName($"{fieldNamePrefix}_{j}"))))); } break; diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadDispatchDataMethod.Syntax.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadDispatchDataMethod.Syntax.cs index c33133234..0390b344c 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadDispatchDataMethod.Syntax.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateLoadDispatchDataMethod.Syntax.cs @@ -199,11 +199,11 @@ private static ImmutableArray GetDispatchDataLoadingStatements( using ImmutableArrayBuilder statements = ImmutableArrayBuilder.Rent(); - // ConstantBuffer data; + // ConstantBuffer buffer; statements.Add( LocalDeclarationStatement( VariableDeclaration(IdentifierName("ConstantBuffer")) - .AddVariables(VariableDeclarator(Identifier("data"))))); + .AddVariables(VariableDeclarator(Identifier("buffer"))))); // Generate loading statements for each captured field foreach (FieldInfo fieldInfo in fieldInfos) @@ -214,14 +214,14 @@ private static ImmutableArray GetDispatchDataLoadingStatements( // Assign a primitive value: // - // data. = this.; + // buffer. = this.; statements.Add( ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("data"), + IdentifierName("buffer"), IdentifierName(string.Join("_", primitive.FieldPath))), MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, @@ -235,10 +235,10 @@ private static ImmutableArray GetDispatchDataLoadingStatements( // Assign all rows of a given matrix type: // - // data. = this.[0]; - // data. = this.[1]; + // buffer. = this.[0]; + // buffer. = this.[1]; // ... - // data. = this.[N]; + // buffer. = this.[N]; for (int j = 0; j < matrix.Rows; j++) { statements.Add( @@ -247,7 +247,7 @@ private static ImmutableArray GetDispatchDataLoadingStatements( SyntaxKind.SimpleAssignmentExpression, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("data"), + IdentifierName("buffer"), IdentifierName($"{fieldNamePrefix}_{j}")), ElementAccessExpression( MemberAccessExpression( @@ -264,7 +264,7 @@ private static ImmutableArray GetDispatchDataLoadingStatements( } } - // loader.LoadConstantBuffer(new global::System.ReadOnlySpan(&data, sizeof(ConstantBuffer))); + // loader.LoadConstantBuffer(new global::System.ReadOnlySpan(&buffer, sizeof(ConstantBuffer))); statements.Add( ExpressionStatement( InvocationExpression( @@ -280,7 +280,7 @@ private static ImmutableArray GetDispatchDataLoadingStatements( Argument( PrefixUnaryExpression( SyntaxKind.AddressOfExpression, - IdentifierName("data"))), + IdentifierName("buffer"))), Argument(SizeOfExpression(IdentifierName("ConstantBuffer")))))))); return statements.ToImmutable(); From 0d5370c941bd81ec33ce37c15a2a3a0cec44a6a3 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 24 Sep 2023 16:31:16 +0200 Subject: [PATCH 6/7] Generate both dispatch methods in same file --- .../ID2D1ShaderGenerator.Helpers.cs | 48 +++++++++++++++++++ .../ID2D1ShaderGenerator.cs | 27 ++++------- 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.Helpers.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.Helpers.cs index ab1f0d5d1..dd7bc25e6 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.Helpers.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.Helpers.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using ComputeSharp.SourceGeneration.Models; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -34,6 +35,53 @@ public static bool IsD2D1PixelShaderType(INamedTypeSymbol typeSymbol, Compilatio return false; } + /// + /// Creates a instance wrapping the given method. + /// + /// The instance for the current type. + /// The items to insert. + /// Additional member declarations to also emit, if any. + /// A object wrapping . + private static CompilationUnitSyntax GetCompilationUnitFromMembers( + HierarchyInfo hierarchyInfo, + (MemberDeclarationSyntax Member, bool SkipLocalsInit)[] memberDeclarations, + params MemberDeclarationSyntax[] additionalMemberDeclarations) + { + // Method attributes + AttributeListSyntax[] attributes = + { + 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")))), + AttributeList(SingletonSeparatedList( + Attribute(IdentifierName("global::System.ComponentModel.EditorBrowsable")).AddArgumentListArguments( + AttributeArgument(ParseExpression("global::System.ComponentModel.EditorBrowsableState.Never"))))), + AttributeList(SingletonSeparatedList( + Attribute(IdentifierName("global::System.Obsolete")).AddArgumentListArguments( + AttributeArgument(LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal("This method is not intended to be used directly by user code")))))) + }; + + MemberDeclarationSyntax[] membersToAdd = memberDeclarations.Select(item => + { + MemberDeclarationSyntax memberToAdd = item.Member.AddAttributeLists(attributes); + + // Add [SkipLocalsInit] if needed + if (item.SkipLocalsInit) + { + memberToAdd = memberToAdd.AddAttributeLists(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Runtime.CompilerServices.SkipLocalsInit"))))); + } + + return memberToAdd; + }).ToArray(); + + return hierarchyInfo.GetSyntax(membersToAdd, additionalMemberDeclarations); + } + /// /// Creates a instance wrapping the given method. /// diff --git a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs index 1d85eac37..9b09f4be5 100644 --- a/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs +++ b/src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs @@ -285,30 +285,21 @@ public void Initialize(IncrementalGeneratorInitializationContext context) context.AddSource($"{item.Hierarchy.FullyQualifiedMetadataName}.{nameof(ResourceTextureDescriptions)}.g.cs", compilationUnit.GetText(Encoding.UTF8)); }); - // Get the info for InitializeFromDispatchData() (hierarchy and dispatch data) - IncrementalValuesProvider<(HierarchyInfo Hierarchy, DispatchDataInfo Dispatch)> initializeFromDispatchDataInfo = - shaderInfoWithErrors - .Select(static (item, _) => (item.Hierarchy, item.DispatchData)); - - // Generate the InitializeFromDispatchData() methods - context.RegisterSourceOutput(initializeFromDispatchDataInfo, static (context, item) => - { - MethodDeclarationSyntax loadDispatchDataMethod = InitializeFromDispatchData.GetSyntax(item.Dispatch); - CompilationUnitSyntax compilationUnit = GetCompilationUnitFromMember(item.Hierarchy, loadDispatchDataMethod, canUseSkipLocalsInit: false); - - context.AddSource($"{item.Hierarchy.FullyQualifiedMetadataName}.{nameof(InitializeFromDispatchData)}.g.cs", compilationUnit.GetText(Encoding.UTF8)); - }); - - // Get the info for LoadDispatchData() (same as InitializeFromDispatchData(), but with [SkipLocalsInit] support flag as well) + // Get the info for InitializeFromDispatchData() and LoadDispatchData() (hierarchy, dispatch data and [SkipLocalsInit] support flag) IncrementalValuesProvider<((HierarchyInfo Hierarchy, DispatchDataInfo Dispatch) Info, bool CanUseSkipLocalsInit)> dispatchDataInfo = - initializeFromDispatchDataInfo + shaderInfoWithErrors + .Select(static (item, _) => (item.Hierarchy, item.DispatchData)) .Combine(canUseSkipLocalsInit); - // Generate the LoadDispatchData() methods + // Generate the InitializeFromDispatchData() and LoadDispatchData() methods context.RegisterSourceOutput(dispatchDataInfo, static (context, item) => { + MethodDeclarationSyntax initializeFromDispatchDataMethod = InitializeFromDispatchData.GetSyntax(item.Info.Dispatch); MethodDeclarationSyntax loadDispatchDataMethod = LoadDispatchData.GetSyntax(item.Info.Hierarchy, item.Info.Dispatch, out TypeDeclarationSyntax[] additionalTypes); - CompilationUnitSyntax compilationUnit = GetCompilationUnitFromMember(item.Info.Hierarchy, loadDispatchDataMethod, item.CanUseSkipLocalsInit, additionalMemberDeclarations: additionalTypes); + CompilationUnitSyntax compilationUnit = GetCompilationUnitFromMembers( + item.Info.Hierarchy, + memberDeclarations: new (MemberDeclarationSyntax, bool)[] { (initializeFromDispatchDataMethod, false), (loadDispatchDataMethod, item.CanUseSkipLocalsInit) }, + additionalMemberDeclarations: additionalTypes); context.AddSource($"{item.Info.Hierarchy.FullyQualifiedMetadataName}.{nameof(LoadDispatchData)}.g.cs", compilationUnit.GetText(Encoding.UTF8)); }); From 856475d9f8aefb2b06d0e7d2c3adf2cf452863de Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 28 Sep 2023 02:19:30 +0200 Subject: [PATCH 7/7] Remove two unused methods Note clear why this wasn't failing the build before --- .../TriangleGridContouring.cs | 6 ------ .../TriangleGridContouring.cs | 6 ------ 2 files changed, 12 deletions(-) diff --git a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TriangleGridContouring.cs b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TriangleGridContouring.cs index d472f8e6a..970bd7757 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TriangleGridContouring.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.D2D1.Shared/TriangleGridContouring.cs @@ -32,12 +32,6 @@ private static float2x2 Rotate2x2(in float a) return new(c, -s, s, c); } - // IQ's float2 to float hash. - private static float Hash21(float2 p) - { - return Hlsl.Frac(Hlsl.Sin(Hlsl.Dot(p, new float2(27.619f, 57.583f))) * 43758.5453f); - } - // float2 to float2 hash. private float2 Hash22(float2 p) { diff --git a/samples/ComputeSharp.SwapChain.Shaders.Shared/TriangleGridContouring.cs b/samples/ComputeSharp.SwapChain.Shaders.Shared/TriangleGridContouring.cs index 52c87473d..4486624ef 100644 --- a/samples/ComputeSharp.SwapChain.Shaders.Shared/TriangleGridContouring.cs +++ b/samples/ComputeSharp.SwapChain.Shaders.Shared/TriangleGridContouring.cs @@ -25,12 +25,6 @@ private static float2x2 Rotate2x2(in float a) return new(c, -s, s, c); } - // IQ's float2 to float hash. - private static float Hash21(float2 p) - { - return Hlsl.Frac(Hlsl.Sin(Hlsl.Dot(p, new float2(27.619f, 57.583f))) * 43758.5453f); - } - // float2 to float2 hash. private float2 Hash22(float2 p) {