/// <summary> /// Creates a <see cref="MethodDeclarationSyntax"/> instance for the <c>LoadDispatchMetadata</c> method. /// </summary> /// <param name="metadataInfo">The dispatch metadata for the current shader..</param> /// <returns>The resulting <see cref="MethodDeclarationSyntax"/> instance for the <c>LoadDispatchMetadata</c> method.</returns> public static MethodDeclarationSyntax GetSyntax(DispatchMetadataInfo metadataInfo) { // This code produces a method declaration as follows: // // readonly void global::ComputeSharp.__Internals.IShader.LoadDispatchMetadata<TLoader>(ref TLoader loader, out global::System.IntPtr result) // { // <BODY> // } return (MethodDeclaration( PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("LoadDispatchMetadata")) .WithExplicitInterfaceSpecifier(ExplicitInterfaceSpecifier(IdentifierName($"global::ComputeSharp.__Internals.{nameof(IShader)}"))) .AddModifiers(Token(SyntaxKind.ReadOnlyKeyword)) .AddTypeParameterListParameters(TypeParameter(Identifier("TLoader"))) .AddParameterListParameters( Parameter(Identifier("loader")) .AddModifiers(Token(SyntaxKind.RefKeyword)) .WithType(IdentifierName("TLoader")), Parameter(Identifier("result")) .AddModifiers(Token(SyntaxKind.OutKeyword)) .WithType(IdentifierName($"global::System.{typeof(IntPtr).Name}"))) .WithBody(Block(GetDispatchMetadataLoadingStatements(metadataInfo)))); }
/// <summary> /// Gets a sequence of statements to load the dispatch metadata for a given shader type. /// </summary> /// <param name="metadataInfo">The dispatch metadata for the current shader..</param> /// <returns>The sequence of <see cref="StatementSyntax"/> instances to load shader dispatch data.</returns> private static ImmutableArray <StatementSyntax> GetDispatchMetadataLoadingStatements(DispatchMetadataInfo metadataInfo) { ImmutableArray <StatementSyntax> .Builder statements = ImmutableArray.CreateBuilder <StatementSyntax>(); // global::System.Span<byte> span0 = stackalloc byte[5]; statements.Add( LocalDeclarationStatement( VariableDeclaration( GenericName(Identifier("global::System.Span")) .AddTypeArgumentListArguments(PredefinedType(Token(SyntaxKind.ByteKeyword)))) .AddVariables( VariableDeclarator(Identifier("span0")) .WithInitializer(EqualsValueClause( StackAllocArrayCreationExpression( ArrayType(PredefinedType(Token(SyntaxKind.ByteKeyword))) .AddRankSpecifiers( ArrayRankSpecifier(SingletonSeparatedList <ExpressionSyntax>( LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(5))))))))))); // Compute the total number of resources int totalResourcesCount = metadataInfo.ResourceDescriptors.Length; // Span<global::ComputeSharp.__Internals.ResourceDescriptor> span1 = stackalloc global::ComputeSharp.__Internals.ResourceDescriptor[<ADJUSTED_COUNT>]; statements.Add( LocalDeclarationStatement( VariableDeclaration( GenericName(Identifier("global::System.Span")) .AddTypeArgumentListArguments(IdentifierName("global::ComputeSharp.__Internals.ResourceDescriptor"))) .AddVariables( VariableDeclarator(Identifier("span1")) .WithInitializer(EqualsValueClause( StackAllocArrayCreationExpression( ArrayType(IdentifierName("global::ComputeSharp.__Internals.ResourceDescriptor")) .AddRankSpecifiers( ArrayRankSpecifier(SingletonSeparatedList <ExpressionSyntax>( LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(totalResourcesCount))))))))))); // ref byte r0 = ref span0[0]; statements.Add( LocalDeclarationStatement( VariableDeclaration(RefType(PredefinedType(Token(SyntaxKind.ByteKeyword)))) .AddVariables( VariableDeclarator(Identifier("r0")) .WithInitializer(EqualsValueClause( RefExpression( ElementAccessExpression(IdentifierName("span0")) .AddArgumentListArguments(Argument( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(0)))))))))); // ref global::ComputeSharp.__Internals.ResourceDescriptor r1 = ref span1[0]; statements.Add( LocalDeclarationStatement( VariableDeclaration(RefType(IdentifierName("global::ComputeSharp.__Internals.ResourceDescriptor"))) .AddVariables( VariableDeclarator(Identifier("r1")) .WithInitializer(EqualsValueClause( RefExpression( ElementAccessExpression(IdentifierName("span1")) .AddArgumentListArguments(Argument( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(0)))))))))); // Serialized shader metadata statements.Add(ParseStatement($"global::System.Runtime.CompilerServices.Unsafe.WriteUnaligned<int>(ref global::System.Runtime.CompilerServices.Unsafe.Add(ref r0, 0), {metadataInfo.Root32BitConstantCount});")); statements.Add(ParseStatement($"global::System.Runtime.CompilerServices.Unsafe.WriteUnaligned<bool>(ref global::System.Runtime.CompilerServices.Unsafe.Add(ref r0, 4), {metadataInfo.IsSamplerUsed.ToString().ToLowerInvariant()});")); // Populate the sequence of resource descriptors foreach (ResourceDescriptor descriptor in metadataInfo.ResourceDescriptors) { statements.Add(ParseStatement($"global::ComputeSharp.__Internals.ResourceDescriptor.Create({descriptor.TypeId}, {descriptor.RegisterOffset}, out global::System.Runtime.CompilerServices.Unsafe.Add(ref r1, {descriptor.Offset}));")); } // Invoke the value delegate to create the opaque root signature handle statements.Add(ParseStatement("loader.LoadMetadataHandle(span0, span1, out result);")); return(statements.ToImmutable()); }