/// <summary> /// Initializes the <see cref="For{T}"/> shared state. /// </summary> /// <param name="factory">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> >?factory) { // 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 (d2D1DrawTransformMapperFactory != factory) { 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 guid = typeof(T).GUID; int inputCount = (int)D2D1InteropServices.GetPixelShaderInputCount <T>(); ReadOnlyMemory <byte> buffer = D2D1InteropServices.LoadPixelShaderBytecode <T>(); byte *typeAssociatedMemory = (byte *)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(For <T>), buffer.Length); // Copy the bytecode to the target buffer buffer.Span.CopyTo(new Span <byte>(typeAssociatedMemory, buffer.Length)); // Set the shared state and mark the type as initialized shaderId = guid; numberOfInputs = inputCount; bytecode = typeAssociatedMemory; bytecodeSize = buffer.Length; d2D1DrawTransformMapperFactory = factory; isInitialized = true; } } }
public unsafe void GetInputCount() { Assert.AreEqual(D2D1InteropServices.GetPixelShaderInputCount <InvertEffect>(), 1u); Assert.AreEqual(D2D1InteropServices.GetPixelShaderInputCount <PixelateEffect.Shader>(), 1u); Assert.AreEqual(D2D1InteropServices.GetPixelShaderInputCount <ZonePlateEffect>(), 0u); }