/// <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)); }
/// <summary> /// Constructs a new VertexLayoutDescription. The stride is assumed to be the sum of the size of all elements. /// </summary> /// <param name="elements">An array of <see cref="VertexElementDescription"/> objects, each describing a single element /// of vertex data.</param> public VertexLayoutDescription(params VertexElementDescription[] elements) { Elements = elements; uint computedStride = 0; for (int i = 0; i < elements.Length; i++) { computedStride += FormatHelpers.GetSizeInBytes(elements[i].Format); } Stride = computedStride; }
internal static uint ComputeMipOffset(Texture tex, uint mipLevel) { uint offset = 0; for (uint level = 0; level < mipLevel; level++) { Util.GetMipDimensions(tex, level, out uint mipWidth, out uint mipHeight, out uint mipDepth); offset += mipWidth * mipHeight * mipDepth * FormatHelpers.GetSizeInBytes(tex.Format); } return(offset); }
internal static uint ComputeArrayLayerOffset(Texture tex, uint arrayLayer) { if (arrayLayer == 0) { return(0); } uint layerPitch = 0; for (uint level = 0; level < tex.MipLevels; level++) { Util.GetMipDimensions(tex, level, out uint mipWidth, out uint mipHeight, out uint mipDepth); layerPitch += mipWidth * mipHeight * mipDepth * FormatHelpers.GetSizeInBytes(tex.Format); } return(layerPitch * arrayLayer); }
/// <summary> /// Constructs a new VertexLayoutDescription. The stride is assumed to be the sum of the size of all elements. /// </summary> /// <param name="elements">An array of <see cref="VertexElementDescription"/> objects, each describing a single element /// of vertex data.</param> public VertexLayoutDescription(params VertexElementDescription[] elements) { Elements = elements; uint computedStride = 0; for (int i = 0; i < elements.Length; i++) { uint elementSize = FormatHelpers.GetSizeInBytes(elements[i].Format); if (elements[i].Offset != 0) { computedStride = elements[i].Offset + elementSize; } else { computedStride += elementSize; } } Stride = computedStride; InstanceStepRate = 0; }
public static unsafe void CopyTextureRegion( void *src, uint srcX, uint srcY, uint srcZ, uint srcRowPitch, uint srcDepthPitch, void *dst, uint dstX, uint dstY, uint dstZ, uint dstRowPitch, uint dstDepthPitch, uint width, uint height, uint depth, PixelFormat format) { uint blockSize = FormatHelpers.IsCompressedFormat(format) ? 4u : 1u; uint blockSizeInBytes = blockSize > 1 ? FormatHelpers.GetBlockSizeInBytes(format) : FormatHelpers.GetSizeInBytes(format); uint compressedSrcX = srcX / blockSize; uint compressedSrcY = srcY / blockSize; uint compressedDstX = dstX / blockSize; uint compressedDstY = dstY / blockSize; uint numRows = FormatHelpers.GetNumRows(height, format); uint rowSize = width / blockSize * blockSizeInBytes; if (srcRowPitch == dstRowPitch && srcDepthPitch == dstDepthPitch) { uint totalCopySize = depth * srcDepthPitch; Buffer.MemoryCopy( src, dst, totalCopySize, totalCopySize); } else { for (uint zz = 0; zz < depth; zz++) { for (uint yy = 0; yy < numRows; yy++) { byte *rowCopyDst = (byte *)dst + dstDepthPitch * (zz + dstZ) + dstRowPitch * (yy + compressedDstY) + blockSizeInBytes * compressedDstX; byte *rowCopySrc = (byte *)src + srcDepthPitch * (zz + srcZ) + srcRowPitch * (yy + compressedSrcY) + blockSizeInBytes * compressedSrcX; Unsafe.CopyBlock(rowCopyDst, rowCopySrc, rowSize); } } } }