/// <summary> /// Copies the content an array of data on CPU memory to this buffer into GPU memory. /// </summary> /// <param name="device">The <see cref="GraphicsDevice"/>.</param> /// <param name="fromData">A data pointer.</param> /// <param name="offsetInBytes">The offset in bytes to write to.</param> /// <exception cref="System.ArgumentException"></exception> /// <remarks> /// See the unmanaged documentation about Map/UnMap for usage and restrictions. /// </remarks> public void SetData(CommandList commandList, DataPointer fromData, int offsetInBytes = 0) { // Check size validity of data to copy to if (fromData.Size > this.Description.SizeInBytes) { throw new ArgumentException("Size of data to upload larger than size of buffer"); } // If this texture is declared as default usage, we can only use UpdateSubresource, which is not optimal but better than nothing if (this.Description.Usage == GraphicsResourceUsage.Default) { // Setup the dest region inside the buffer if ((this.Description.BufferFlags & BufferFlags.ConstantBuffer) != 0) { commandList.UpdateSubresource(this, 0, new DataBox(fromData.Pointer, 0, 0)); } else { var destRegion = new ResourceRegion(offsetInBytes, 0, 0, offsetInBytes + fromData.Size, 1, 1); commandList.UpdateSubresource(this, 0, new DataBox(fromData.Pointer, 0, 0), destRegion); } } else { if (offsetInBytes > 0) { throw new ArgumentException("offset is only supported for textured declared with ResourceUsage.Default", "offsetInBytes"); } var mappedResource = commandList.MapSubresource(this, 0, Usage == GraphicsResourceUsage.Staging ? MapMode.Write : MapMode.WriteDiscard); Utilities.CopyMemory(mappedResource.DataBox.DataPointer, fromData.Pointer, fromData.Size); commandList.UnmapSubresource(mappedResource); } }
public void Unmap() { if (UseBufferOffsets && mappedConstantBuffer.Resource != null) { using (new DefaultCommandListLock(commandList)) { commandList.UnmapSubresource(mappedConstantBuffer); mappedConstantBuffer = new MappedResource(); } } }
public void Apply(CommandList commandList, ResourceGroup[] resourceGroups, int resourceGroupsOffset) { if (resourceGroupBindings.Length == 0) { return; } var resourceGroupBinding = Interop.Pin(ref resourceGroupBindings[0]); for (int i = 0; i < resourceGroupBindings.Length; i++, resourceGroupBinding = Interop.IncrementPinned(resourceGroupBinding)) { var resourceGroup = resourceGroups[resourceGroupsOffset + i]; // Upload cbuffer (if not done yet) if (resourceGroupBinding.ConstantBufferSlot != -1 && resourceGroup != null && resourceGroup.ConstantBuffer.Data != IntPtr.Zero) { var preallocatedBuffer = resourceGroup.ConstantBuffer.Buffer; bool needUpdate = true; if (preallocatedBuffer == null) { preallocatedBuffer = resourceGroupBinding.ConstantBufferPreallocated; // If it's preallocated buffer, we always upload } else if (resourceGroup.ConstantBuffer.Uploaded) { needUpdate = false; // If it's not preallocated and already uploaded, we can avoid uploading it again } else { resourceGroup.ConstantBuffer.Uploaded = true; // First time it is uploaded } if (needUpdate) { if (hasResourceRenaming) { var mappedConstantBuffer = commandList.MapSubresource(preallocatedBuffer, 0, MapMode.WriteDiscard); Utilities.CopyMemory(mappedConstantBuffer.DataBox.DataPointer, resourceGroup.ConstantBuffer.Data, resourceGroup.ConstantBuffer.Size); commandList.UnmapSubresource(mappedConstantBuffer); } else { commandList.UpdateSubresource(preallocatedBuffer, 0, new DataBox(resourceGroup.ConstantBuffer.Data, resourceGroup.ConstantBuffer.Size, 0)); } } resourceGroup.DescriptorSet.SetConstantBuffer(resourceGroupBinding.ConstantBufferSlot, preallocatedBuffer, resourceGroup.ConstantBuffer.Offset, resourceGroup.ConstantBuffer.Size); } } }
/// <summary> /// Copies the content of this buffer from GPU memory to a CPU memory using a specific staging resource. /// </summary> /// <param name="stagingTexture">The staging buffer used to transfer the buffer.</param> /// <param name="toData">To data pointer.</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 when called from the main thread that is accessing the main <see cref="GraphicsDevice"/>. /// </remarks> public void GetData(CommandList commandList, Buffer stagingTexture, DataPointer toData) { // Check size validity of data to copy to if (toData.Size > this.Description.SizeInBytes) { throw new ArgumentException("Length of TData is larger than size of buffer"); } // Copy the texture to a staging resource if (!ReferenceEquals(this, stagingTexture)) { commandList.Copy(this, stagingTexture); } // Map the staging resource to a CPU accessible memory var mappedResource = commandList.MapSubresource(stagingTexture, 0, MapMode.Read); Utilities.CopyMemory(toData.Pointer, mappedResource.DataBox.DataPointer, toData.Size); // Make sure that we unmap the resource in case of an exception commandList.UnmapSubresource(mappedResource); }