Beispiel #1
0
    /// <summary>
    /// The factory method for <see cref="ID2D1Factory1.RegisterEffectFromString"/>.
    /// </summary>
    /// <param name="shaderId">The <see cref="Guid"/> for the shader.</param>
    /// <param name="inputCount">The number of inputs for the shader.</param>
    /// <param name="inputTypes">The buffer with the types of inputs for the shader.</param>
    /// <param name="inputDescriptionCount">The number of available input descriptions.</param>
    /// <param name="inputDescriptions">The buffer with the available input descriptions for the shader.</param>
    /// <param name="pixelOptions">The pixel options for the shader.</param>
    /// <param name="bytecode">The shader bytecode.</param>
    /// <param name="bytecodeSize">The size of <paramref name="bytecode"/>.</param>
    /// <param name="bufferPrecision">The buffer precision for the resulting output buffer.</param>
    /// <param name="channelDepth">The channel depth for the resulting output buffer.</param>
    /// <param name="d2D1TransformMapper">The <see cref="D2D1TransformMapper"/> instance to use for the effect.</param>
    /// <param name="effectImpl">The resulting effect instance.</param>
    /// <returns>This always returns <c>0</c>.</returns>
    private static int Factory(
        Guid shaderId,
        int inputCount,
        D2D1PixelShaderInputType *inputTypes,
        int inputDescriptionCount,
        D2D1InputDescription *inputDescriptions,
        D2D1PixelOptions pixelOptions,
        byte *bytecode,
        int bytecodeSize,
        D2D1BufferPrecision bufferPrecision,
        D2D1ChannelDepth channelDepth,
        D2D1TransformMapper?d2D1TransformMapper,
        IUnknown **effectImpl)
    {
        PixelShaderEffect * @this;

        try
        {
            @this = (PixelShaderEffect *)NativeMemory.Alloc((nuint)sizeof(PixelShaderEffect));
        }
        catch (OutOfMemoryException)
        {
            *effectImpl = null;

            return(E.E_OUTOFMEMORY);
        }

        *@this = default;

        @this->lpVtblForID2D1EffectImpl    = VtblForID2D1EffectImpl;
        @this->lpVtblForID2D1DrawTransform = VtblForID2D1DrawTransform;
        @this->referenceCount            = 1;
        @this->shaderId                  = shaderId;
        @this->inputCount                = inputCount;
        @this->inputTypes                = inputTypes;
        @this->inputDescriptionCount     = inputDescriptionCount;
        @this->inputDescriptions         = inputDescriptions;
        @this->pixelOptions              = pixelOptions;
        @this->bytecode                  = bytecode;
        @this->bytecodeSize              = bytecodeSize;
        @this->bufferPrecision           = bufferPrecision;
        @this->channelDepth              = channelDepth;
        @this->d2D1TransformMapperHandle = GCHandle.Alloc(d2D1TransformMapper);

        *effectImpl = (IUnknown *)@this;

        return(S.S_OK);
    }
Beispiel #2
0
        /// <summary>
        /// Initializes the <see cref="For{T}"/> shared state.
        /// </summary>
        /// <param name="d2D1DrawTransformMapperFactory">The factory of <see cref="ID2D1TransformMapper{T}"/> instances to use for each created effect.</param>
        /// <exception cref="InvalidOperationException">Thrown if initialization is attempted with a mismatched transform factory.</exception>
        public static void Initialize(Func <ID2D1TransformMapper <T> >?d2D1DrawTransformMapperFactory)
        {
            // This conceptually acts as a static constructor, and this type is
            // internal, so in this very specific case locking on the type is fine.
            lock (typeof(For <T>))
            {
                if (isInitialized)
                {
                    // If the factory is already initialized, ensure the draw transform mapper is the same
                    if (For <T> .d2D1DrawTransformMapperFactory != d2D1DrawTransformMapperFactory)
                    {
                        ThrowHelper.ThrowInvalidOperationException(
                            "Cannot initialize an ID2D1Effect factory for the same shader type with two different transform mappings. " +
                            "Make sure to only ever register a pixel shader effect with either no transform, or the same transform type.");
                    }
                }
                else
                {
                    // Load all shader properties
                    Guid shaderId = typeof(T).GUID;
                    ReadOnlyMemory <byte> bytecodeInfo = D2D1PixelShader.LoadBytecode <T>();
                    int   bytecodeSize = bytecodeInfo.Length;
                    byte *bytecode     = (byte *)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(For <T>), bytecodeSize);
                    D2D1BufferPrecision bufferPrecision = D2D1PixelShader.GetOutputBufferPrecision <T>();
                    D2D1ChannelDepth    channelDepth    = D2D1PixelShader.GetOutputBufferChannelDepth <T>();
                    D2D1PixelOptions    pixelOptions    = D2D1PixelShader.GetPixelOptions <T>();

                    // Prepare the inputs info
                    int inputCount = D2D1PixelShader.GetInputCount <T>();
                    D2D1PixelShaderInputType *inputTypes = (D2D1PixelShaderInputType *)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(For <T>), sizeof(D2D1PixelShaderInputType) * inputCount);

                    for (int i = 0; i < inputCount; i++)
                    {
                        inputTypes[i] = D2D1PixelShader.GetInputType <T>(i);
                    }

                    // Prepare the input descriptions
                    ReadOnlyMemory <D2D1InputDescription> inputDescriptionsInfo = D2D1PixelShader.GetInputDescriptions <T>();
                    int inputDescriptionCount = inputDescriptionsInfo.Length;
                    D2D1InputDescription *inputDescriptions = (D2D1InputDescription *)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(For <T>), sizeof(D2D1InputDescription) * inputDescriptionCount);

                    inputDescriptionsInfo.Span.CopyTo(new Span <D2D1InputDescription>(inputDescriptions, inputDescriptionCount));

                    // Copy the bytecode to the target buffer
                    bytecodeInfo.Span.CopyTo(new Span <byte>(bytecode, bytecodeSize));

                    // Set the shared state and mark the type as initialized
                    For <T> .shaderId                       = shaderId;
                    For <T> .inputCount                     = inputCount;
                    For <T> .inputTypes                     = inputTypes;
                    For <T> .inputDescriptionCount          = inputDescriptionCount;
                    For <T> .inputDescriptions              = inputDescriptions;
                    For <T> .pixelOptions                   = pixelOptions;
                    For <T> .bytecode                       = bytecode;
                    For <T> .bytecodeSize                   = bytecodeSize;
                    For <T> .bufferPrecision                = bufferPrecision;
                    For <T> .channelDepth                   = channelDepth;
                    For <T> .d2D1DrawTransformMapperFactory = d2D1DrawTransformMapperFactory;

                    isInitialized = true;
                }
            }
        }