public ParameterConstantBuffer(GraphicsDevice device, string constantBufferName, ShaderConstantBufferDescription constantBufferDesc) { ConstantBufferDesc = constantBufferDesc; constantBufferDatas = new ConstantBufferData[GraphicsDevice.ThreadCount]; dataStreams = new DataPointer[GraphicsDevice.ThreadCount]; for (uint i = 0; i < GraphicsDevice.ThreadCount; ++i) { constantBufferDatas[i] = new ConstantBufferData(constantBufferDesc); dataStreams[i] = new DataPointer(constantBufferDatas[i].Data, constantBufferDesc.Size); } Buffer = SiliconStudio.Paradox.Graphics.Buffer.New(device, constantBufferDatas[0].Desc.Size, BufferFlags.ConstantBuffer, UsingMap ? GraphicsResourceUsage.Dynamic : GraphicsResourceUsage.Default); // We want to clear flags // TODO: Should be later replaced with either an internal field on GraphicsResourceBase, or a reset counter somewhere? Buffer.Reload = Reload; }
/// <summary> /// Loads an image from an unmanaged memory pointer. /// </summary> /// <param name="dataBuffer">Pointer to an unmanaged memory. If <see cref="makeACopy"/> is false, this buffer must be allocated with <see cref="Utilities.AllocateMemory"/>.</param> /// <param name="makeACopy">True to copy the content of the buffer to a new allocated buffer, false otherwhise.</param> /// <returns>An new image.</returns> /// <remarks>If <see cref="makeACopy"/> is set to false, the returned image is now the holder of the unmanaged pointer and will release it on Dispose. </remarks> public static Image Load(DataPointer dataBuffer, bool makeACopy = false) { return Load(dataBuffer.Pointer, dataBuffer.Size, makeACopy); }
/// <summary> /// Creates a new <see cref="Buffer" /> instance. /// </summary> /// <param name="device">The <see cref="GraphicsDevice"/>.</param> /// <param name="dataPointer">The data pointer.</param> /// <param name="elementSize">Size of the element.</param> /// <param name="bufferFlags">The buffer flags to specify the type of buffer.</param> /// <param name="usage">The usage.</param> /// <returns>An instance of a new <see cref="Buffer" /></returns> public static Buffer New(GraphicsDevice device, DataPointer dataPointer, int elementSize, BufferFlags bufferFlags, GraphicsResourceUsage usage = GraphicsResourceUsage.Default) { return(New(device, dataPointer, elementSize, bufferFlags, PixelFormat.None, usage)); }
/// <summary> /// Copies the content an array of data on CPU memory to this buffer into GPU memory. /// </summary> /// <param name="fromData">A data pointer.</param> /// <param name="offsetInBytes">The offset in bytes to write to.</param> /// <exception cref="System.ArgumentException"></exception> /// <remarks> /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>. See the unmanaged documentation about Map/UnMap for usage and restrictions. /// </remarks> public void SetData(DataPointer fromData, int offsetInBytes = 0) { SetData(GraphicsDevice, fromData, offsetInBytes); }
/// <summary> /// Creates a new index buffer with <see cref="GraphicsResourceUsage.Immutable"/> uasge by default. /// </summary> /// <param name="device">The <see cref="GraphicsDevice"/>.</param> /// <param name="value">The value to initialize the index buffer.</param> /// <param name="usage">The usage of this resource.</param> /// <returns>A index buffer</returns> public static Buffer New(GraphicsDevice device, DataPointer value, GraphicsResourceUsage usage = GraphicsResourceUsage.Immutable) { return(Buffer.New(device, value, 0, BufferFlags.IndexBuffer, usage)); }
/// <summary> /// Copies the content an data on CPU memory to this texture into GPU memory. /// </summary> /// <param name="device">The <see cref="GraphicsDevice"/>.</param> /// <param name="fromData">The data to copy from.</param> /// <param name="arraySlice">The array slice index. This value must be set to 0 for Texture 3D.</param> /// <param name="mipSlice">The mip slice index.</param> /// <param name="region">Destination region</param> /// <exception cref="System.ArgumentException">When strides is different from optimal strides, and TData is not the same size as the pixel format, or Width * Height != toData.Length</exception> /// <remarks> /// See unmanaged documentation for usage and restrictions. /// </remarks> public unsafe void SetData(GraphicsDevice device, DataPointer fromData, int arraySlice = 0, int mipSlice = 0, ResourceRegion?region = null) { if (device == null) { throw new ArgumentNullException("device"); } if (region.HasValue && this.Description.Usage != GraphicsResourceUsage.Default) { throw new ArgumentException("Region is only supported for textures with ResourceUsage.Default"); } // Get mipmap description for the specified mipSlice var mipMapDesc = this.GetMipMapDescription(mipSlice); int width = mipMapDesc.Width; int height = mipMapDesc.Height; int depth = mipMapDesc.Depth; // If we are using a region, then check that parameters are fine if (region.HasValue) { int newWidth = region.Value.Right - region.Value.Left; int newHeight = region.Value.Bottom - region.Value.Top; int newDepth = region.Value.Back - region.Value.Front; if (newWidth > width) { throw new ArgumentException(string.Format("Region width [{0}] cannot be greater than mipmap width [{1}]", newWidth, width), "region"); } if (newHeight > height) { throw new ArgumentException(string.Format("Region height [{0}] cannot be greater than mipmap height [{1}]", newHeight, height), "region"); } if (newDepth > depth) { throw new ArgumentException(string.Format("Region depth [{0}] cannot be greater than mipmap depth [{1}]", newDepth, depth), "region"); } width = newWidth; height = newHeight; depth = newDepth; } // Size per pixel var sizePerElement = Description.Format.SizeInBytes(); // Calculate depth stride based on mipmap level int rowStride; // Depth Stride int textureDepthStride; // Compute Actual pitch Image.ComputePitch(this.Description.Format, width, height, out rowStride, out textureDepthStride, out width, out height); // Size Of actual texture data int sizeOfTextureData = textureDepthStride * depth; // Check size validity of data to copy to if (fromData.Size != sizeOfTextureData) { throw new ArgumentException(string.Format("Size of toData ({0} bytes) is not compatible expected size ({1} bytes) : Width * Height * Depth * sizeof(PixelFormat) size in bytes", fromData.Size, sizeOfTextureData)); } // Calculate the subResourceIndex for a Texture int subResourceIndex = this.GetSubResourceIndex(arraySlice, mipSlice); // If this texture is declared as default usage, we use UpdateSubresource that supports sub resource region. if (this.Description.Usage == GraphicsResourceUsage.Default) { // If using a specific region, we need to handle this case if (region.HasValue) { var regionValue = region.Value; var sourceDataPtr = fromData.Pointer; // Workaround when using region with a deferred context and a device that does not support CommandList natively // see http://blogs.msdn.com/b/chuckw/archive/2010/07/28/known-issue-direct3d-11-updatesubresource-and-deferred-contexts.aspx if (device.NeedWorkAroundForUpdateSubResource) { if (IsBlockCompressed) { regionValue.Left /= 4; regionValue.Right /= 4; regionValue.Top /= 4; regionValue.Bottom /= 4; } sourceDataPtr = new IntPtr((byte *)sourceDataPtr - (regionValue.Front * textureDepthStride) - (regionValue.Top * rowStride) - (regionValue.Left * sizePerElement)); } device.UpdateSubresource(this, subResourceIndex, new DataBox(sourceDataPtr, rowStride, textureDepthStride), regionValue); } else { device.UpdateSubresource(this, subResourceIndex, new DataBox(fromData.Pointer, rowStride, textureDepthStride)); } } else { var mappedResource = device.MapSubresource(this, subResourceIndex, this.Description.Usage == GraphicsResourceUsage.Dynamic ? MapMode.WriteDiscard : MapMode.Write); var box = mappedResource.DataBox; // If depth == 1 (Texture1D, Texture2D or TextureCube), then depthStride is not used var boxDepthStride = this.Description.Depth == 1 ? box.SlicePitch : textureDepthStride; // The fast way: If same stride, we can directly copy the whole texture in one shot if (box.RowPitch == rowStride && boxDepthStride == textureDepthStride) { Utilities.CopyMemory(box.DataPointer, fromData.Pointer, sizeOfTextureData); } else { // Otherwise, the long way by copying each scanline var destPerDepthPtr = (byte *)box.DataPointer; var sourcePtr = (byte *)fromData.Pointer; // Iterate on all depths for (int j = 0; j < depth; j++) { var destPtr = destPerDepthPtr; // Iterate on each line for (int i = 0; i < height; i++) { Utilities.CopyMemory((IntPtr)destPtr, (IntPtr)sourcePtr, rowStride); destPtr += box.RowPitch; sourcePtr += rowStride; } destPerDepthPtr += box.SlicePitch; } } device.UnmapSubresource(mappedResource); } }
/// <summary> /// Copies the content of this texture from GPU memory to a pointer on CPU memory using a specific staging resource. /// </summary> /// <param name="stagingTexture">The staging texture used to transfer the texture to.</param> /// <param name="toData">The pointer to data in CPU memory.</param> /// <param name="arraySlice">The array slice index. This value must be set to 0 for Texture 3D.</param> /// <param name="mipSlice">The mip slice index.</param> /// <param name="doNotWait">if set to <c>true</c> this method will return immediately if the resource is still being used by the GPU for writing. Default is false</param> /// <returns><c>true</c> if data was correctly retrieved, <c>false</c> if <see cref="doNotWait"/> flag was true and the resource is still being used by the GPU for writing.</returns> /// <exception cref="System.ArgumentException">When strides is different from optimal strides, and TData is not the same size as the pixel format, or Width * Height != toData.Length</exception> /// <remarks> /// This method is only working when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>. /// </remarks> public unsafe bool GetData(Texture stagingTexture, DataPointer toData, int arraySlice = 0, int mipSlice = 0, bool doNotWait = false) { if (stagingTexture == null) { throw new ArgumentNullException("stagingTexture"); } var device = GraphicsDevice; //var deviceContext = device.NativeDeviceContext; // Get mipmap description for the specified mipSlice var mipmap = this.GetMipMapDescription(mipSlice); // Copy height, depth int height = mipmap.HeightPacked; int depth = mipmap.Depth; // Calculate depth stride based on mipmap level int rowStride = mipmap.RowStride; // Depth Stride int textureDepthStride = mipmap.DepthStride; // MipMap Stride int mipMapSize = mipmap.MipmapSize; // Check size validity of data to copy to if (toData.Size > mipMapSize) { throw new ArgumentException(string.Format("Size of toData ({0} bytes) is not compatible expected size ({1} bytes) : Width * Height * Depth * sizeof(PixelFormat) size in bytes", toData.Size, mipMapSize)); } // Copy the actual content of the texture to the staging resource if (!ReferenceEquals(this, stagingTexture)) { device.Copy(this, stagingTexture); } // Calculate the subResourceIndex for a Texture2D int subResourceIndex = this.GetSubResourceIndex(arraySlice, mipSlice); // Map the staging resource to a CPU accessible memory var mappedResource = device.MapSubresource(stagingTexture, subResourceIndex, MapMode.Read, doNotWait); // Box can be empty if DoNotWait is set to true, return false if empty var box = mappedResource.DataBox; if (box.IsEmpty) { return(false); } // If depth == 1 (Texture1D, Texture2D or TextureCube), then depthStride is not used var boxDepthStride = this.Description.Depth == 1 ? box.SlicePitch : textureDepthStride; var isFlippedTexture = IsFlippedTexture(); // The fast way: If same stride, we can directly copy the whole texture in one shot if (box.RowPitch == rowStride && boxDepthStride == textureDepthStride && !isFlippedTexture) { Utilities.CopyMemory(toData.Pointer, box.DataPointer, mipMapSize); } else { // Otherwise, the long way by copying each scanline var sourcePerDepthPtr = (byte *)box.DataPointer; var destPtr = (byte *)toData.Pointer; // Iterate on all depths for (int j = 0; j < depth; j++) { var sourcePtr = sourcePerDepthPtr; // Iterate on each line if (isFlippedTexture) { sourcePtr = sourcePtr + box.RowPitch * (height - 1); for (int i = height - 1; i >= 0; i--) { // Copy a single row Utilities.CopyMemory(new IntPtr(destPtr), new IntPtr(sourcePtr), rowStride); sourcePtr -= box.RowPitch; destPtr += rowStride; } } else { for (int i = 0; i < height; i++) { // Copy a single row Utilities.CopyMemory(new IntPtr(destPtr), new IntPtr(sourcePtr), rowStride); sourcePtr += box.RowPitch; destPtr += rowStride; } } sourcePerDepthPtr += box.SlicePitch; } } // Make sure that we unmap the resource in case of an exception device.UnmapSubresource(mappedResource); return(true); }
/// <summary> /// Copies the content an data on CPU memory to this texture into GPU memory using the specified <see cref="GraphicsDevice"/> (The graphics device could be deffered). /// </summary> /// <param name="fromData">The data to copy from.</param> /// <param name="arraySlice">The array slice index. This value must be set to 0 for Texture 3D.</param> /// <param name="mipSlice">The mip slice index.</param> /// <param name="region">Destination region</param> /// <exception cref="System.ArgumentException">When strides is different from optimal strides, and TData is not the same size as the pixel format, or Width * Height != toData.Length</exception> /// <remarks> /// This method is only working on the main graphics device. Use method with explicit graphics device to set data on a deferred context. /// See also unmanaged documentation about Map/UnMap for usage and restrictions. /// </remarks> public void SetData(DataPointer fromData, int arraySlice = 0, int mipSlice = 0, ResourceRegion?region = null) { SetData(GraphicsDevice, fromData, arraySlice, mipSlice, region); }
/// <summary> /// Creates a new StructuredCounter buffer <see cref="GraphicsResourceUsage.Default" /> uasge. /// </summary> /// <param name="device">The <see cref="GraphicsDevice"/>.</param> /// <param name="value">The value to initialize the StructuredCounter buffer.</param> /// <param name="elementSize">Size of the element.</param> /// <returns>A StructuredCounter buffer</returns> public static Buffer New(GraphicsDevice device, DataPointer value, int elementSize) { const BufferFlags BufferFlags = BufferFlags.StructuredCounterBuffer | BufferFlags.ShaderResource | BufferFlags.UnorderedAccess; return(Buffer.New(device, value, elementSize, BufferFlags)); }
/// <summary> /// Creates a new constant buffer with <see cref="GraphicsResourceUsage.Dynamic"/> usage. /// </summary> /// <param name="device">The <see cref="GraphicsDevice"/>.</param> /// <param name="value">The value to initialize the constant buffer.</param> /// <param name="usage">The usage of this resource.</param> /// <returns>A constant buffer</returns> public static Buffer New(GraphicsDevice device, DataPointer value, GraphicsResourceUsage usage = GraphicsResourceUsage.Dynamic) { return(Buffer.New(device, value, 0, BufferFlags.ConstantBuffer, usage)); }
/// <summary> /// Creates a new Raw buffer with <see cref="GraphicsResourceUsage.Default"/> uasge by default. /// </summary> /// <param name="device">The <see cref="GraphicsDevice"/>.</param> /// <param name="value">The value to initialize the Raw buffer.</param> /// <param name="additionalBindings">The additional bindings (for example, to create a combined raw/index buffer, pass <see cref="BufferFlags.IndexBuffer" />)</param> /// <param name="usage">The usage of this resource.</param> /// <returns>A Raw buffer</returns> public static Buffer New(GraphicsDevice device, DataPointer value, BufferFlags additionalBindings = BufferFlags.None, GraphicsResourceUsage usage = GraphicsResourceUsage.Default) { return(Buffer.New(device, value, 0, BufferFlags.RawBuffer | additionalBindings, usage)); }
/// <summary> /// Creates a new Typed buffer <see cref="GraphicsResourceUsage.Default" /> uasge. /// </summary> /// <param name="device">The <see cref="GraphicsDevice"/>.</param> /// <param name="value">The value to initialize the Typed buffer.</param> /// <param name="viewFormat">The view format of the buffer.</param> /// <param name="isUnorderedAccess">if set to <c>true</c> this buffer supports unordered access (RW in HLSL).</param> /// <param name="usage">The usage of this resource.</param> /// <returns>A Typed buffer</returns> public static Buffer New(GraphicsDevice device, DataPointer value, PixelFormat viewFormat, bool isUnorderedAccess = false, GraphicsResourceUsage usage = GraphicsResourceUsage.Default) { return(Buffer.New(device, value, 0, BufferFlags.ShaderResource | (isUnorderedAccess?BufferFlags.UnorderedAccess : BufferFlags.None), viewFormat, usage)); }
/// <summary> /// Loads an image from an unmanaged memory pointer. /// </summary> /// <param name="dataBuffer">Pointer to an unmanaged memory. If <see cref="makeACopy"/> is false, this buffer must be allocated with <see cref="Utilities.AllocateMemory"/>.</param> /// <param name="makeACopy">True to copy the content of the buffer to a new allocated buffer, false otherwhise.</param> /// <param name="loadAsSRGB">Indicate if the image should be loaded as an sRGB texture</param> /// <returns>An new image.</returns> /// <remarks>If <see cref="makeACopy"/> is set to false, the returned image is now the holder of the unmanaged pointer and will release it on Dispose. </remarks> public static Image Load(DataPointer dataBuffer, bool makeACopy = false, bool loadAsSRGB = true) { return Load(dataBuffer.Pointer, dataBuffer.Size, makeACopy, loadAsSRGB); }