/// <summary> /// Creates a new <see cref="Pipeline"/> object. /// </summary> /// <param name="description">The desired properties of the created object.</param> /// <returns>A new <see cref="Pipeline"/> which, when bound to a CommandList, is used to dispatch draw commands.</returns> public Pipeline CreateGraphicsPipeline(ref GraphicsPipelineDescription description) { #if VALIDATE_USAGE if (!description.RasterizerState.DepthClipEnabled && !Features.DepthClipDisable) { throw new VeldridException( "RasterizerState.DepthClipEnabled must be true if GraphicsDeviceFeatures.DepthClipDisable is not supported."); } if (description.RasterizerState.FillMode == PolygonFillMode.Wireframe && !Features.FillModeWireframe) { throw new VeldridException( "PolygonFillMode.Wireframe requires GraphicsDeviceFeatures.FillModeWireframe."); } if (!Features.IndependentBlend) { if (description.BlendState.AttachmentStates.Length > 0) { BlendAttachmentDescription attachmentState = description.BlendState.AttachmentStates[0]; for (int i = 1; i < description.BlendState.AttachmentStates.Length; i++) { if (!attachmentState.Equals(description.BlendState.AttachmentStates[i])) { throw new VeldridException( $"If GraphcsDeviceFeatures.IndependentBlend is false, then all members of BlendState.AttachmentStates must be equal."); } } } } #endif return(CreateGraphicsPipelineCore(ref description)); }
/// <summary> /// Creates a new <see cref="Pipeline"/> object. /// </summary> /// <param name="description">The desired properties of the created object.</param> /// <returns>A new <see cref="Pipeline"/> which, when bound to a CommandList, is used to dispatch draw commands.</returns> public Pipeline CreateGraphicsPipeline(ref GraphicsPipelineDescription description) { #if VALIDATE_USAGE if (!description.RasterizerState.DepthClipEnabled && !Features.DepthClipDisable) { throw new VeldridException( "RasterizerState.DepthClipEnabled must be true if GraphicsDeviceFeatures.DepthClipDisable is not supported."); } if (description.RasterizerState.FillMode == PolygonFillMode.Wireframe && !Features.FillModeWireframe) { throw new VeldridException( "PolygonFillMode.Wireframe requires GraphicsDeviceFeatures.FillModeWireframe."); } if (!Features.IndependentBlend) { if (description.BlendState.AttachmentStates.Length > 0) { BlendAttachmentDescription attachmentState = description.BlendState.AttachmentStates[0]; for (int i = 1; i < description.BlendState.AttachmentStates.Length; i++) { if (!attachmentState.Equals(description.BlendState.AttachmentStates[i])) { throw new VeldridException( $"If GraphcsDeviceFeatures.IndependentBlend is false, then all members of BlendState.AttachmentStates must be equal."); } } } } foreach (VertexLayoutDescription layoutDesc in description.ShaderSet.VertexLayouts) { bool hasExplicitLayout = false; uint minOffset = 0; foreach (VertexElementDescription elementDesc in layoutDesc.Elements) { if (hasExplicitLayout && elementDesc.Offset == 0) { throw new VeldridException( $"If any vertex element has an explicit offset, then all elements must have an explicit offset."); } if (elementDesc.Offset != 0 && elementDesc.Offset < minOffset) { throw new VeldridException( $"Vertex element \"{elementDesc.Name}\" has an explicit offset which overlaps with the previous element."); } minOffset = elementDesc.Offset + FormatHelpers.GetSizeInBytes(elementDesc.Format); hasExplicitLayout |= elementDesc.Offset != 0; } if (minOffset > layoutDesc.Stride) { throw new VeldridException( $"The vertex layout's stride ({layoutDesc.Stride}) is less than the full size of the vertex ({minOffset})"); } } #endif return(CreateGraphicsPipelineCore(ref description)); }