コード例 #1
0
    /// <summary>
    /// Loads the bytecode from an input D2D1 pixel shader.
    /// </summary>
    /// <typeparam name="T">The type of D2D1 pixel shader to load the bytecode for.</typeparam>
    /// <param name="shaderProfile">The shader profile to use to get the shader bytecode.</param>
    /// <param name="options">
    /// <para>The compile options to use to get the shader bytecode.</para>
    /// <para>For consistency with <see cref="D2DCompileOptionsAttribute"/>, <see cref="D2D1CompileOptions.PackMatrixRowMajor"/> will be automatically added.</para>
    /// </param>
    /// <returns>A <see cref="ReadOnlyMemory{T}"/> instance with the resulting shader bytecode.</returns>
    /// <exception cref="ArgumentException">Thrown if <see cref="D2D1CompileOptions.PackMatrixColumnMajor"/> is specified within <paramref name="options"/>.</exception>
    /// <remarks>
    /// If the input shader was precompiled, the returned <see cref="ReadOnlyMemory{T}"/> instance will wrap a pinned memory buffer (from the PE section).
    /// If the shader was compiled at runtime, the returned <see cref="ReadOnlyMemory{T}"/> instance will wrap a <see cref="byte"/> array with the bytecode.
    /// </remarks>
    public static ReadOnlyMemory <byte> LoadBytecode <T>(D2D1ShaderProfile shaderProfile, D2D1CompileOptions options)
        where T : unmanaged, ID2D1PixelShader
    {
        if ((options & D2D1CompileOptions.PackMatrixColumnMajor) != 0)
        {
            ThrowHelper.ThrowArgumentException(nameof(options), "The PackMatrixColumnMajor compile options is not compatible with ComputeSharp.D2D1 shaders.");
        }

        return(LoadOrCompileBytecode <T>(shaderProfile, options | D2D1CompileOptions.PackMatrixRowMajor));
    }
コード例 #2
0
    /// <summary>
    /// Creates a new <see cref="D2DEmbeddedBytecodeAttribute"/> instance with the specified parameters.
    /// </summary>
    /// <param name="shaderProfile">The target shader profile to use to compile the shader.</param>
    public D2DEmbeddedBytecodeAttribute(D2D1ShaderProfile shaderProfile)
    {
#if !SOURCE_GENERATOR
        ShaderProfile = shaderProfile switch
        {
            D2D1ShaderProfile.PixelShader40 or
            D2D1ShaderProfile.PixelShader40Level91 or
            D2D1ShaderProfile.PixelShader40Level93 or
            D2D1ShaderProfile.PixelShader41 or
            D2D1ShaderProfile.PixelShader50 => shaderProfile,
                                                   _ => ThrowHelper.ThrowArgumentException <D2D1ShaderProfile>(nameof(shaderProfile), "Invalid shader profile value.")
        };
#endif
    }
コード例 #3
0
    /// <summary>
    /// Compiles a new HLSL shader from the input source code.
    /// </summary>
    /// <param name="source">The HLSL source code to compile.</param>
    /// <param name="shaderProfile">The shader profile to use to compile the shader.</param>
    /// <param name="enableLinkingSupport">Whether to enable linking support for the shader.</param>
    /// <returns>The bytecode for the compiled shader.</returns>
    public static ComPtr <ID3DBlob> Compile(ReadOnlySpan <char> source, D2D1ShaderProfile shaderProfile, bool enableLinkingSupport)
    {
        // Compile the standalone D2D1 full shader
        using ComPtr <ID3DBlob> d3DBlobFullShader = CompileD2DFullShader(source, shaderProfile);

        if (!enableLinkingSupport)
        {
            return(d3DBlobFullShader.Move());
        }

        // Compile the export function and embed it as private data if requested
        using ComPtr <ID3DBlob> d3DBlobFunction = CompileD2DFunction(source, shaderProfile);
        using ComPtr <ID3DBlob> d3DBlobLinked   = EmbedD2DFunctionPrivateData(d3DBlobFullShader.Get(), d3DBlobFunction.Get());

        return(d3DBlobLinked.Move());
    }
コード例 #4
0
 /// <summary>
 /// Loads the bytecode from an input D2D1 pixel shader.
 /// </summary>
 /// <typeparam name="T">The type of D2D1 pixel shader to load the bytecode for.</typeparam>
 /// <param name="shaderProfile">The shader profile to use to get the shader bytecode.</param>
 /// <returns>A <see cref="ReadOnlyMemory{T}"/> instance with the resulting shader bytecode.</returns>
 /// <remarks>
 /// If the input shader was precompiled, the returned <see cref="ReadOnlyMemory{T}"/> instance will wrap a pinned memory buffer (from the PE section).
 /// If the shader was compiled at runtime, the returned <see cref="ReadOnlyMemory{T}"/> instance will wrap a <see cref="byte"/> array with the bytecode.
 /// </remarks>
 public static ReadOnlyMemory <byte> LoadPixelShaderBytecode <T>(D2D1ShaderProfile shaderProfile)
     where T : unmanaged, ID2D1PixelShader
 {
     return(LoadOrCompilePixelShaderBytecode <T>(shaderProfile));
 }
コード例 #5
0
    /// <summary>
    /// Compiles a D2D1 pixel shader with <c>D2D_FULL_SHADER</c>.
    /// </summary>
    /// <param name="source">The HLSL source code to compile.</param>
    /// <param name="shaderProfile">The shader profile to use to compile the shader.</param>
    /// <returns>The bytecode for the compiled shader.</returns>
    private static ComPtr <ID3DBlob> CompileD2DFullShader(ReadOnlySpan <char> source, D2D1ShaderProfile shaderProfile)
    {
        // Encode the HLSL source to ASCII
        int maxLength = Encoding.ASCII.GetMaxByteCount(source.Length);

        byte[] buffer = ArrayPool <byte> .Shared.Rent(maxLength);

        int writtenBytes = Encoding.ASCII.GetBytes(source, buffer);

        using ComPtr <ID3DBlob> d3DBlobBytecode = default;
        using ComPtr <ID3DBlob> d3DBlobErrors   = default;

        int hResult;

        fixed(byte *bufferPtr = buffer)
        {
            // Prepare the macros for full shader compilation:
            //
            // -D D2D_FULL_SHADER
            // -D D2D_ENTRY=Execute
            D3D_SHADER_MACRO *macros = stackalloc D3D_SHADER_MACRO[]
            {
                new()
                {
                    Name       = (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(ASCII.D2D_FULL_SHADER)),
                    Definition = (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(ASCII.NullTerminator))
                },
                new()
                {
                    Name       = (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(ASCII.D2D_ENTRY)),
                    Definition = (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(ASCII.Execute))
                },
                new()
            };

            // Compile the shader with -ps_5_0 -O3 -We -Zpr
            hResult = DirectX.D3DCompile(
                pSrcData: bufferPtr,
                SrcDataSize: (nuint)writtenBytes,
                pSourceName: null,
                pDefines: macros,
                pInclude: D3DIncludeForD2D1EffectHelpers,
                pEntrypoint: (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(ASCII.Execute)),
                pTarget: (sbyte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(ASCII.GetPixelShaderProfile(shaderProfile))),
                Flags1: D3DCOMPILE.D3DCOMPILE_OPTIMIZATION_LEVEL3 | D3DCOMPILE.D3DCOMPILE_WARNINGS_ARE_ERRORS | D3DCOMPILE.D3DCOMPILE_PACK_MATRIX_ROW_MAJOR,
                Flags2: 0,
                ppCode: d3DBlobBytecode.GetAddressOf(),
                ppErrorMsgs: d3DBlobErrors.GetAddressOf());
        }

        ArrayPool <byte> .Shared.Return(buffer);

        // Throw if an error was retrieved, then also double check the HRESULT
        if (d3DBlobErrors.Get() is not null)
        {
            ThrowHslsCompilationException(d3DBlobErrors.Get());
        }

        hResult.Assert();

        return(d3DBlobBytecode.Move());
    }
コード例 #6
0
 /// <summary>
 /// Creates a new <see cref="D2DEmbeddedBytecodeAttribute"/> instance with the specified parameters.
 /// </summary>
 /// <param name="shaderProfile">The target shader profile to use to compile the shader.</param>
 public D2DEmbeddedBytecodeAttribute(D2D1ShaderProfile shaderProfile)
 {
     ShaderProfile = shaderProfile;
 }