Ejemplo n.º 1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="GorgonInputLayout"/> class.
        /// </summary>
        /// <param name="graphics">The video adapter interface used to create this input layout.</param>
        /// <param name="name">Name of the object.</param>
        /// <param name="shader">Vertex shader to bind the layout with.</param>
        /// <param name="elements">The input elements to assign to this layout.</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="name"/>, <paramref name="graphics"/>, <paramref name="shader"/>, or the <paramref name="elements"/> parameter is <b>null</b>.</exception>
        /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="name"/>, or the <paramref name="elements"/> parameter is empty.</exception>
        /// <exception cref="ArgumentException">Thrown when an element with the same context, slot and index appears more than once in the <paramref name="elements"/> parameter.</exception>
        public GorgonInputLayout(GorgonGraphics graphics, string name, GorgonVertexShader shader, IEnumerable <GorgonInputElement> elements)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentEmptyException(nameof(name));
            }

            Name = name;

            // Make a copy so we don't allow changing of the original reference.
            _elements = elements?.ToArray() ?? throw new ArgumentNullException(nameof(elements));

            if (_elements.Length == 0)
            {
                throw new ArgumentEmptyException(nameof(elements));
            }

            _slotSizes = new Dictionary <int, int>();

            // Check for duplicated elements.
            for (int i = 0; i < _elements.Length; ++i)
            {
                FindDuplicateElements(_elements, _elements[i], i, nameof(elements));
            }

            Graphics = graphics ?? throw new ArgumentNullException(nameof(graphics));
            Shader   = shader ?? throw new ArgumentNullException(nameof(shader));

            UpdateVertexSize();
            BuildD3DLayout();

            this.RegisterDisposable(graphics);
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Function to build an input layout using the fields from a value type.
 /// </summary>
 /// <typeparam name="T">The type to evaluate. This must be an unmanaged value type.</typeparam>
 /// <param name="graphics">The graphics interface used to create the input layout.</param>
 /// <param name="shader">Vertex shader to bind the layout with.</param>
 /// <returns>A new <see cref="GorgonInputLayout"/> for the type passed to <typeparamref name="T"/>.</returns>
 /// <exception cref="ArgumentNullException">Thrown when the <paramref name="graphics"/>, or the <paramref name="shader"/> parameter is <b>null</b>.</exception>
 /// <exception cref="ArgumentException">Thrown when an element with the same context, slot and index appears more than once in the members of the <typeparamref name="T"/> type.</exception>
 /// <exception cref="GorgonException">Thrown when the type specified by <typeparamref name="T"/> is not safe for use with native functions (see <see cref="GorgonReflectionExtensions.IsFieldSafeForNative"/>).
 /// <para>-or-</para>
 /// <para>Thrown when the type specified by <typeparamref name="T"/> does not contain any public members.</para>
 /// <para>-or-</para>
 /// <para>Thrown if the type specified by <typeparamref name="T"/> does not have a <see cref="LayoutKind"/> of <see cref="LayoutKind.Sequential"/> or <see cref="LayoutKind.Explicit"/>.</para>
 /// </exception>
 /// <remarks>
 /// <para>
 /// This will build a new <see cref="GorgonInputLayout"/> using the fields within a value type (<c>struct</c>). Each of the members that are to be included in the layout must be decorated with a
 /// <see cref="InputElementAttribute"/>. If a member is not decorated with this attribute, then it will be ignored.
 /// </para>
 /// <para>
 /// The type parameter <typeparamref name="T"/> must be an unmanaged value type (<c>struct</c>), reference types are not supported. The members of the type must also be public fields. Properties are not
 /// supported. Futhermore, the struct must be decorated with a <see cref="StructLayoutAttribute"/> that defines a <see cref="LayoutKind"/> of <see cref="LayoutKind.Sequential"/> or
 /// <see cref="LayoutKind.Explicit"/>. This is necessary to ensure that the member of the value type are in the correct order when writing to a <see cref="GorgonVertexBuffer"/> or when
 /// generating a <see cref="GorgonInputLayout"/> from a type.
 /// </para>
 /// <para>
 /// If the type specified by <typeparamref name="T"/> has members that are not primitive types or value types with a <see cref="StructLayoutAttribute"/>, or the member has a
 /// <see cref="MarshalAsAttribute"/>, then an exception is thrown.  Gorgon does not support marshalling of complex types for vertices.
 /// </para>
 /// <para>
 /// The types of the fields must be one of the following types:
 /// <para>
 /// <list type="bullet">
 ///		<item>
 ///			<description><see cref="byte"/></description>
 ///		</item>
 ///		<item>
 ///			<description><see cref="sbyte"/></description>
 ///		</item>
 ///		<item>
 ///			<description><see cref="short"/></description>
 ///		</item>
 ///		<item>
 ///			<description><see cref="ushort"/></description>
 ///		</item>
 ///		<item>
 ///			<description><see cref="int"/></description>
 ///		</item>
 ///		<item>
 ///			<description><see cref="uint"/></description>
 ///		</item>
 ///		<item>
 ///			<description><see cref="long"/></description>
 ///		</item>
 ///		<item>
 ///			<description><see cref="ulong"/></description>
 ///		</item>
 ///		<item>
 ///			<description><see cref="float"/></description>
 ///		</item>
 ///		<item>
 ///			<description><c>Vector2</c></description>
 ///		</item>
 ///		<item>
 ///			<description><c>Vector3</c></description>
 ///		</item>
 ///		<item>
 ///			<description><c>Vector4</c></description>
 ///		</item>
 ///		<item>
 ///			<description><see cref="GorgonColor"/></description>
 ///		</item>
 /// </list>
 /// </para>
 /// If the type of the member does not match, an exception will be thrown.
 /// </para>
 /// </remarks>
 /// <seealso cref="GorgonReflectionExtensions.IsFieldSafeForNative"/>
 public static GorgonInputLayout CreateUsingType <T>(GorgonGraphics graphics, GorgonVertexShader shader)
     where T : unmanaged => CreateUsingType(graphics, typeof(T), shader);
Ejemplo n.º 3
0
        /// <summary>
        /// Function to build an input layout using the fields from a value type.
        /// </summary>
        /// <param name="graphics">The graphics interface used to create the input layout.</param>
        /// <param name="type">The type to evaluate.</param>
        /// <param name="shader">Vertex shader to bind the layout with.</param>
        /// <returns>A new <see cref="GorgonInputLayout"/> for the type passed to <paramref name="type"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="graphics"/>, <paramref name="type"/> or the <paramref name="shader"/> parameter is <b>null</b>.</exception>
        /// <exception cref="ArgumentException">Thrown when an element with the same context, slot and index appears more than once in the members of the <paramref name="type"/>.
        /// <para>-or-</para>
        /// <para>Thrown if the <paramref name="type"/> does not have a <see cref="LayoutKind"/> of <see cref="LayoutKind.Sequential"/> or <see cref="LayoutKind.Explicit"/>.</para>
        /// </exception>
        /// <exception cref="GorgonException">Thrown when the type specified by <paramref name="type"/> is not safe for use with native functions (see <see cref="GorgonReflectionExtensions.IsFieldSafeForNative"/>).
        /// <para>-or-</para>
        /// <para>Thrown when the type specified by <paramref name="type"/> does not contain any public members.</para>
        /// </exception>
        /// <remarks>
        /// <para>
        /// This will build a new <see cref="GorgonInputLayout"/> using the fields within a value type (<c>struct</c>). Each of the members that are to be included in the layout must be decorated with a
        /// <see cref="InputElementAttribute"/>. If a member is not decorated with this attribute, then it will be ignored.
        /// </para>
        /// <para>
        /// The <paramref name="type"/> parameter must be an unmanaged value type (<c>struct</c>), reference types are not supported. The members of the type must also be public fields. Properties are not
        /// supported. Futhermore, the struct must be decorated with a <see cref="StructLayoutAttribute"/> that defines a <see cref="LayoutKind"/> of <see cref="LayoutKind.Sequential"/> or
        /// <see cref="LayoutKind.Explicit"/>. This is necessary to ensure that the member of the value type are in the correct order when writing to a <see cref="GorgonVertexBuffer"/> or when
        /// generating a <see cref="GorgonInputLayout"/> from a type.
        /// </para>
        /// <para>
        /// If the type specified by <paramref name="type"/> has members that are not primitive types or value types with a <see cref="StructLayoutAttribute"/>, or the member has a
        /// <see cref="MarshalAsAttribute"/>, then an exception is thrown.  Gorgon does not support marshalling of complex types for vertices.
        /// </para>
        /// <para>
        /// The types of the fields must be one of the following types:
        /// <para>
        /// <list type="bullet">
        ///		<item>
        ///			<description><see cref="byte"/></description>
        ///		</item>
        ///		<item>
        ///			<description><see cref="sbyte"/></description>
        ///		</item>
        ///		<item>
        ///			<description><see cref="short"/></description>
        ///		</item>
        ///		<item>
        ///			<description><see cref="ushort"/></description>
        ///		</item>
        ///		<item>
        ///			<description><see cref="int"/></description>
        ///		</item>
        ///		<item>
        ///			<description><see cref="uint"/></description>
        ///		</item>
        ///		<item>
        ///			<description><see cref="long"/></description>
        ///		</item>
        ///		<item>
        ///			<description><see cref="ulong"/></description>
        ///		</item>
        ///		<item>
        ///			<description><see cref="float"/></description>
        ///		</item>
        ///		<item>
        ///			<description><c>Vector2</c></description>
        ///		</item>
        ///		<item>
        ///			<description><c>Vector3</c></description>
        ///		</item>
        ///		<item>
        ///			<description><c>Vector4</c></description>
        ///		</item>
        ///		<item>
        ///			<description><see cref="GorgonColor"/></description>
        ///		</item>
        /// </list>
        /// </para>
        /// If the type of the member does not match, an exception will be thrown.
        /// </para>
        /// </remarks>
        /// <seealso cref="GorgonReflectionExtensions.IsFieldSafeForNative"/>
        public static GorgonInputLayout CreateUsingType(GorgonGraphics graphics, Type type, GorgonVertexShader shader)
        {
            if (graphics == null)
            {
                throw new ArgumentNullException(nameof(graphics));
            }

            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if ((type.IsAutoLayout) || ((!type.IsLayoutSequential) && (!type.IsExplicitLayout)))
            {
                throw new ArgumentException(string.Format(Resources.GORGFX_ERR_LAYOUT_NOT_SEQUENTIAL_EXPLICIT, type.FullName));
            }

            if (shader == null)
            {
                throw new ArgumentNullException(nameof(shader));
            }

            int byteOffset = 0;
            List <(FieldInfo Field, InputElementAttribute InputElement)> members = GetFieldInfoList(type);

            if (members.Count == 0)
            {
                throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_ERR_VERTEX_NO_FIELDS, type.FullName));
            }

            var elements = new GorgonInputElement[members.Count];

            for (int i = 0; i < elements.Length; i++)
            {
                (FieldInfo Field, InputElementAttribute InputElement) = members[i];

                BufferFormat format      = InputElement.Format;
                string       contextName = InputElement.Context;

                // Try to determine the format from the type.
                if ((format == BufferFormat.Unknown) && (!_typeMapping.TryGetValue(Field.FieldType, out format)))
                {
                    throw new GorgonException(GorgonResult.CannotCreate, string.Format(Resources.GORGFX_ERR_LAYOUT_INVALID_ELEMENT_TYPE, Field.FieldType.FullName));
                }

                var element = new GorgonInputElement(contextName, format,
                                                     (InputElement.AutoOffset ? byteOffset : InputElement.Offset),
                                                     InputElement.Index, InputElement.Slot, InputElement.Instanced,
                                                     InputElement.Instanced ? InputElement.InstanceCount : 0);

                FindDuplicateElements(elements, element, i, nameof(element));

                elements[i] = element;
                byteOffset += element.SizeInBytes;
            }

            return(new GorgonInputLayout(graphics, type.Name, shader, elements));
        }
 /// <summary>
 /// Function to set the current vertex shader on the pipeline.
 /// </summary>
 /// <param name="vertexShader">The vertex shader to assign.</param>
 /// <returns>The fluent interface for this builder.</returns>
 public GorgonPipelineStateBuilder VertexShader(GorgonVertexShader vertexShader)
 {
     _workState.VertexShader = vertexShader;
     return(this);
 }