public void CmdCopyBuffer(VulkanBuffer srcBuffer, VulkanBuffer dstBuffer, BufferCopy?pRegion) { unsafe { BufferCopy valpRegion = pRegion ?? default(BufferCopy); BufferCopy *ptrpRegion = pRegion != null ? &valpRegion : (BufferCopy *)IntPtr.Zero; Interop.NativeMethods.vkCmdCopyBuffer(this.m, srcBuffer != null ? srcBuffer.m : default(UInt64), dstBuffer != null ? dstBuffer.m : default(UInt64), (UInt32)(pRegion != null ? 1 : 0), ptrpRegion); } }
public void CopyBuffer(string queue, string src, string dest, int size) { if (!mBuffers.ContainsKey(src)) { Misc.SafeInvoke(eErrorSpam, "No buffer named: " + src + "..."); return; } if (!mBuffers.ContainsKey(dest)) { Misc.SafeInvoke(eErrorSpam, "No buffer named: " + dest + "..."); return; } if (!mCommandPools.ContainsKey(queue)) { Misc.SafeInvoke(eErrorSpam, "No pool named: " + queue + "..."); return; } CommandBufferAllocateInfo cbai = new CommandBufferAllocateInfo(); cbai.Level = CommandBufferLevel.Primary; cbai.CommandBufferCount = 1; CommandBuffer [] bufs = mCommandPools[queue].AllocateBuffers(cbai); CommandBufferBeginInfo cbbi = new CommandBufferBeginInfo( CommandBufferUsages.OneTimeSubmit); bufs[0].Begin(cbbi); BufferCopy bc = new BufferCopy(size, 0, 0); bufs[0].CmdCopyBuffer(mBuffers[src], mBuffers[dest], bc); bufs[0].End(); SubmitInfo si = new SubmitInfo(); si.CommandBuffers = new IntPtr[] { bufs[0].Handle }; SubmitToQueue(si, queue, null); mQueueNames[queue].WaitIdle(); bufs[0].Dispose(); }
public unsafe void ConvertI8ToI16(VulkanRenderer gd, CommandBufferScoped cbs, BufferHolder src, BufferHolder dst, int srcOffset, int size) { // TODO: Do this with a compute shader? var srcBuffer = src.GetBuffer().Get(cbs, srcOffset, size).Value; var dstBuffer = dst.GetBuffer().Get(cbs, 0, size * 2).Value; gd.Api.CmdFillBuffer(cbs.CommandBuffer, dstBuffer, 0, Vk.WholeSize, 0); var bufferCopy = new BufferCopy[size]; for (ulong i = 0; i < (ulong)size; i++) { bufferCopy[i] = new BufferCopy((ulong)srcOffset + i, i * 2, 1); } BufferHolder.InsertBufferBarrier( gd, cbs.CommandBuffer, dstBuffer, BufferHolder.DefaultAccessFlags, AccessFlags.AccessTransferWriteBit, PipelineStageFlags.PipelineStageAllCommandsBit, PipelineStageFlags.PipelineStageTransferBit, 0, size * 2); fixed(BufferCopy *pBufferCopy = bufferCopy) { gd.Api.CmdCopyBuffer(cbs.CommandBuffer, srcBuffer, dstBuffer, (uint)size, pBufferCopy); } BufferHolder.InsertBufferBarrier( gd, cbs.CommandBuffer, dstBuffer, AccessFlags.AccessTransferWriteBit, BufferHolder.DefaultAccessFlags, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageAllCommandsBit, 0, size * 2); }
public static unsafe void Copy( VulkanRenderer gd, CommandBufferScoped cbs, Auto <DisposableBuffer> src, Auto <DisposableBuffer> dst, int srcOffset, int dstOffset, int size) { var srcBuffer = src.Get(cbs, srcOffset, size).Value; var dstBuffer = dst.Get(cbs, dstOffset, size).Value; InsertBufferBarrier( gd, cbs.CommandBuffer, dstBuffer, BufferHolder.DefaultAccessFlags, AccessFlags.AccessTransferWriteBit, PipelineStageFlags.PipelineStageAllCommandsBit, PipelineStageFlags.PipelineStageTransferBit, dstOffset, size); var region = new BufferCopy((ulong)srcOffset, (ulong)dstOffset, (ulong)size); gd.Api.CmdCopyBuffer(cbs.CommandBuffer, srcBuffer, dstBuffer, 1, ®ion); InsertBufferBarrier( gd, cbs.CommandBuffer, dstBuffer, AccessFlags.AccessTransferWriteBit, BufferHolder.DefaultAccessFlags, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageAllCommandsBit, dstOffset, size); }
/// <summary> /// Explicitly recreate buffer with given data. Usually called after a <see cref="GraphicsDevice"/> reset. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataPointer"></param> public unsafe void Recreate(IntPtr dataPointer) { var createInfo = new BufferCreateInfo { StructureType = StructureType.BufferCreateInfo, Size = (ulong)bufferDescription.SizeInBytes, Flags = BufferCreateFlags.None, }; createInfo.Usage |= BufferUsageFlags.TransferSource; // We always fill using transfer //if (bufferDescription.Usage != GraphicsResourceUsage.Immutable) createInfo.Usage |= BufferUsageFlags.TransferDestination; if (Usage == GraphicsResourceUsage.Staging) { NativeAccessMask = AccessFlags.HostRead | AccessFlags.HostWrite; NativePipelineStageMask |= PipelineStageFlags.Host; } else { if ((ViewFlags & BufferFlags.VertexBuffer) != 0) { createInfo.Usage |= BufferUsageFlags.VertexBuffer; NativeAccessMask |= AccessFlags.VertexAttributeRead; NativePipelineStageMask |= PipelineStageFlags.VertexInput; } if ((ViewFlags & BufferFlags.IndexBuffer) != 0) { createInfo.Usage |= BufferUsageFlags.IndexBuffer; NativeAccessMask |= AccessFlags.IndexRead; NativePipelineStageMask |= PipelineStageFlags.VertexInput; } if ((ViewFlags & BufferFlags.ConstantBuffer) != 0) { createInfo.Usage |= BufferUsageFlags.UniformBuffer; NativeAccessMask |= AccessFlags.UniformRead; NativePipelineStageMask |= PipelineStageFlags.VertexShader | PipelineStageFlags.FragmentShader; } if ((ViewFlags & BufferFlags.ShaderResource) != 0) { createInfo.Usage |= BufferUsageFlags.UniformTexelBuffer; NativeAccessMask |= AccessFlags.ShaderRead; NativePipelineStageMask |= PipelineStageFlags.VertexShader | PipelineStageFlags.FragmentShader; if ((ViewFlags & BufferFlags.UnorderedAccess) != 0) { createInfo.Usage |= BufferUsageFlags.StorageTexelBuffer; NativeAccessMask |= AccessFlags.ShaderWrite; } } } // Create buffer NativeBuffer = GraphicsDevice.NativeDevice.CreateBuffer(ref createInfo); // Allocate memory var memoryProperties = MemoryPropertyFlags.DeviceLocal; if (bufferDescription.Usage == GraphicsResourceUsage.Staging || Usage == GraphicsResourceUsage.Dynamic) { memoryProperties = MemoryPropertyFlags.HostVisible | MemoryPropertyFlags.HostCoherent; } MemoryRequirements memoryRequirements; GraphicsDevice.NativeDevice.GetBufferMemoryRequirements(NativeBuffer, out memoryRequirements); AllocateMemory(memoryProperties, memoryRequirements); if (NativeMemory != DeviceMemory.Null) { GraphicsDevice.NativeDevice.BindBufferMemory(NativeBuffer, NativeMemory, 0); } if (SizeInBytes > 0) { // Begin copy command buffer var commandBufferAllocateInfo = new CommandBufferAllocateInfo { StructureType = StructureType.CommandBufferAllocateInfo, CommandPool = GraphicsDevice.NativeCopyCommandPool, CommandBufferCount = 1, Level = CommandBufferLevel.Primary }; CommandBuffer commandBuffer; lock (GraphicsDevice.QueueLock) { GraphicsDevice.NativeDevice.AllocateCommandBuffers(ref commandBufferAllocateInfo, &commandBuffer); } var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo, Flags = CommandBufferUsageFlags.OneTimeSubmit }; commandBuffer.Begin(ref beginInfo); // Copy to upload buffer if (dataPointer != IntPtr.Zero) { if (Usage == GraphicsResourceUsage.Dynamic) { var uploadMemory = GraphicsDevice.NativeDevice.MapMemory(NativeMemory, 0, (ulong)SizeInBytes, MemoryMapFlags.None); Utilities.CopyMemory(uploadMemory, dataPointer, SizeInBytes); GraphicsDevice.NativeDevice.UnmapMemory(NativeMemory); } else { var sizeInBytes = bufferDescription.SizeInBytes; SharpVulkan.Buffer uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(sizeInBytes, out uploadResource, out uploadOffset); Utilities.CopyMemory(uploadMemory, dataPointer, sizeInBytes); // Barrier var memoryBarrier = new BufferMemoryBarrier(uploadResource, AccessFlags.HostWrite, AccessFlags.TransferRead, (ulong)uploadOffset, (ulong)sizeInBytes); commandBuffer.PipelineBarrier(PipelineStageFlags.Host, PipelineStageFlags.Transfer, DependencyFlags.None, 0, null, 1, &memoryBarrier, 0, null); // Copy var bufferCopy = new BufferCopy { SourceOffset = (uint)uploadOffset, DestinationOffset = 0, Size = (uint)sizeInBytes }; commandBuffer.CopyBuffer(uploadResource, NativeBuffer, 1, &bufferCopy); } } else { commandBuffer.FillBuffer(NativeBuffer, 0, (uint)bufferDescription.SizeInBytes, 0); } // Barrier var bufferMemoryBarrier = new BufferMemoryBarrier(NativeBuffer, AccessFlags.TransferWrite, NativeAccessMask); commandBuffer.PipelineBarrier(PipelineStageFlags.Transfer, PipelineStageFlags.AllCommands, DependencyFlags.None, 0, null, 1, &bufferMemoryBarrier, 0, null); // Close and submit commandBuffer.End(); var submitInfo = new SubmitInfo { StructureType = StructureType.SubmitInfo, CommandBufferCount = 1, CommandBuffers = new IntPtr(&commandBuffer), }; lock (GraphicsDevice.QueueLock) { GraphicsDevice.NativeCommandQueue.Submit(1, &submitInfo, Fence.Null); GraphicsDevice.NativeCommandQueue.WaitIdle(); //commandBuffer.Reset(CommandBufferResetFlags.None); GraphicsDevice.NativeDevice.FreeCommandBuffers(GraphicsDevice.NativeCopyCommandPool, 1, &commandBuffer); } InitializeViews(); } }
private unsafe void CreateBuffers() { PositionColorVertex[] positionData = VertexData.IndexedCubeData; ushort[] indexData = VertexData.CubeIndexData; InstanceData[] instanceData = new InstanceData[] { new InstanceData(new Vector3(0, 0, 0)), new InstanceData(new Vector3(2, 0, 0)), new InstanceData(new Vector3(-2, 0, 0)) }; CreateHostBufferWithContent <PositionColorVertex>(positionData, out var hostBuffer1, out var hostAlloc1); CreateHostBufferWithContent <ushort>(indexData, out var hostBuffer2, out var hostAlloc2); CreateHostBufferWithContent <InstanceData>(instanceData, out var hostBuffer3, out var hostAlloc3); CreateDeviceLocalBuffer(BufferUsageFlags.BufferUsageVertexBufferBit, GetByteLength(positionData), out this.VertexBuffer, out this.VertexAllocation); CreateDeviceLocalBuffer(BufferUsageFlags.BufferUsageIndexBufferBit, GetByteLength(indexData), out this.IndexBuffer, out this.IndexAllocation); CreateDeviceLocalBuffer(BufferUsageFlags.BufferUsageVertexBufferBit, GetByteLength(instanceData), out this.InstanceBuffer, out this.InstanceAllocation); var cbuffer = AllocateCommandBuffer(CommandBufferLevel.Primary); BufferCopy *copies = stackalloc BufferCopy[1]; BeginCommandBuffer(cbuffer, CommandBufferUsageFlags.CommandBufferUsageOneTimeSubmitBit); copies[0] = new BufferCopy(0, 0, (ulong)GetByteLength(positionData)); VkApi.CmdCopyBuffer(cbuffer, hostBuffer1, this.VertexBuffer, 1, copies); copies[0] = new BufferCopy(0, 0, (ulong)GetByteLength(indexData)); VkApi.CmdCopyBuffer(cbuffer, hostBuffer2, this.IndexBuffer, 1, copies); copies[0] = new BufferCopy(0, 0, (ulong)GetByteLength(instanceData)); VkApi.CmdCopyBuffer(cbuffer, hostBuffer3, this.InstanceBuffer, 1, copies); EndCommandBuffer(cbuffer); var subInfo = new SubmitInfo(commandBufferCount: 1, pCommandBuffers: &cbuffer); var fence = CreateFence(); var res = VkApi.QueueSubmit(GraphicsQueue, 1, &subInfo, fence); if (res != Result.Success) { throw new Exception("Unable to submit to queue. " + res); } var bufferTmp = cbuffer; //Allows the capture of this command buffer in a lambda BufferCopyPromise = this.scheduler.WaitForFenceAsync(fence); BufferCopyPromise.GetAwaiter().OnCompleted(() => { VkApi.DestroyFence(Device, fence, null); FreeCommandBuffer(bufferTmp); VkApi.DestroyBuffer(Device, hostBuffer1, null); VkApi.DestroyBuffer(Device, hostBuffer2, null); VkApi.DestroyBuffer(Device, hostBuffer3, null); hostAlloc1.Dispose(); hostAlloc2.Dispose(); hostAlloc3.Dispose(); }); this.VertexCount = (uint)positionData.Length; this.IndexCount = (uint)indexData.Length; this.InstanceCount = (uint)instanceData.Length; }
/// <summary> /// Explicitly recreate buffer with given data. Usually called after a <see cref="GraphicsDevice"/> reset. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataPointer"></param> public unsafe void Recreate(IntPtr dataPointer) { var createInfo = new BufferCreateInfo { StructureType = StructureType.BufferCreateInfo, Size = (ulong)bufferDescription.SizeInBytes, Flags = BufferCreateFlags.None, }; createInfo.Usage |= BufferUsageFlags.TransferSource; // We always fill using transfer //if (bufferDescription.Usage != GraphicsResourceUsage.Immutable) createInfo.Usage |= BufferUsageFlags.TransferDestination; if ((ViewFlags & BufferFlags.VertexBuffer) != 0) { createInfo.Usage |= BufferUsageFlags.VertexBuffer; NativeAccessMask |= AccessFlags.VertexAttributeRead; NativePipelineStageMask |= PipelineStageFlags.VertexInput; } if ((ViewFlags & BufferFlags.IndexBuffer) != 0) { createInfo.Usage |= BufferUsageFlags.IndexBuffer; NativeAccessMask |= AccessFlags.IndexRead; NativePipelineStageMask |= PipelineStageFlags.VertexInput; } if ((ViewFlags & BufferFlags.ConstantBuffer) != 0) { createInfo.Usage |= BufferUsageFlags.UniformBuffer; NativeAccessMask |= AccessFlags.UniformRead; NativePipelineStageMask |= PipelineStageFlags.VertexShader | PipelineStageFlags.FragmentShader; } if ((ViewFlags & BufferFlags.ShaderResource) != 0) { createInfo.Usage |= BufferUsageFlags.UniformTexelBuffer; NativeAccessMask |= AccessFlags.ShaderRead; NativePipelineStageMask |= PipelineStageFlags.VertexShader | PipelineStageFlags.FragmentShader; if ((ViewFlags & BufferFlags.UnorderedAccess) != 0) { createInfo.Usage |= BufferUsageFlags.StorageTexelBuffer; NativeAccessMask |= AccessFlags.ShaderWrite; } } // Create buffer NativeBuffer = GraphicsDevice.NativeDevice.CreateBuffer(ref createInfo); // Allocate memory var memoryProperties = MemoryPropertyFlags.DeviceLocal; if (bufferDescription.Usage == GraphicsResourceUsage.Staging) { throw new NotImplementedException(); } else if (Usage == GraphicsResourceUsage.Dynamic) { memoryProperties = MemoryPropertyFlags.HostVisible | MemoryPropertyFlags.HostCoherent; } MemoryRequirements memoryRequirements; GraphicsDevice.NativeDevice.GetBufferMemoryRequirements(NativeBuffer, out memoryRequirements); AllocateMemory(memoryProperties, memoryRequirements); if (NativeMemory != DeviceMemory.Null) { GraphicsDevice.NativeDevice.BindBufferMemory(NativeBuffer, NativeMemory, 0); } if (SizeInBytes > 0) { // Begin copy command buffer var commandBufferAllocateInfo = new CommandBufferAllocateInfo { StructureType = StructureType.CommandBufferAllocateInfo, CommandPool = GraphicsDevice.NativeCopyCommandPool, CommandBufferCount = 1, Level = CommandBufferLevel.Primary }; CommandBuffer commandBuffer; GraphicsDevice.NativeDevice.AllocateCommandBuffers(ref commandBufferAllocateInfo, &commandBuffer); var beginInfo = new CommandBufferBeginInfo { StructureType = StructureType.CommandBufferBeginInfo, Flags = CommandBufferUsageFlags.OneTimeSubmit }; commandBuffer.Begin(ref beginInfo); // Copy to upload buffer if (dataPointer != IntPtr.Zero) { if (Usage == GraphicsResourceUsage.Dynamic) { var uploadMemory = GraphicsDevice.NativeDevice.MapMemory(NativeMemory, 0, (ulong)SizeInBytes, MemoryMapFlags.None); Utilities.CopyMemory(uploadMemory, dataPointer, SizeInBytes); GraphicsDevice.NativeDevice.UnmapMemory(NativeMemory); } else { var sizeInBytes = bufferDescription.SizeInBytes; SharpVulkan.Buffer uploadResource; int uploadOffset; var uploadMemory = GraphicsDevice.AllocateUploadBuffer(sizeInBytes, out uploadResource, out uploadOffset); Utilities.CopyMemory(uploadMemory, dataPointer, sizeInBytes); // Barrier var memoryBarrier = new BufferMemoryBarrier(uploadResource, AccessFlags.HostWrite, AccessFlags.TransferRead, (ulong)uploadOffset, (ulong)sizeInBytes); commandBuffer.PipelineBarrier(PipelineStageFlags.Host, PipelineStageFlags.Transfer, DependencyFlags.None, 0, null, 1, &memoryBarrier, 0, null); // Copy var bufferCopy = new BufferCopy { SourceOffset = (uint)uploadOffset, DestinationOffset = 0, Size = (uint)sizeInBytes }; commandBuffer.CopyBuffer(uploadResource, NativeBuffer, 1, &bufferCopy); } } else { commandBuffer.FillBuffer(NativeBuffer, 0, (uint)bufferDescription.SizeInBytes, 0); } // Barrier var bufferMemoryBarrier = new BufferMemoryBarrier(NativeBuffer, AccessFlags.TransferWrite, NativeAccessMask); commandBuffer.PipelineBarrier(PipelineStageFlags.Transfer, PipelineStageFlags.AllCommands, DependencyFlags.None, 0, null, 1, &bufferMemoryBarrier, 0, null); // Close and submit commandBuffer.End(); var submitInfo = new SubmitInfo { StructureType = StructureType.SubmitInfo, CommandBufferCount = 1, CommandBuffers = new IntPtr(&commandBuffer), }; lock (GraphicsDevice.QueueLock) { GraphicsDevice.NativeCommandQueue.Submit(1, &submitInfo, Fence.Null); GraphicsDevice.NativeCommandQueue.WaitIdle(); //commandBuffer.Reset(CommandBufferResetFlags.None); GraphicsDevice.NativeDevice.FreeCommandBuffers(GraphicsDevice.NativeCopyCommandPool, 1, &commandBuffer); } InitializeViews(); } }
public unsafe void CopyBuffer(Buffer sourceBuffer, Buffer destinationBuffer, uint regionCount, BufferCopy* regions) { vkCmdCopyBuffer(this, sourceBuffer, destinationBuffer, regionCount, regions); }
internal static unsafe extern void vkCmdCopyBuffer(CommandBuffer commandBuffer, Buffer sourceBuffer, Buffer destinationBuffer, uint regionCount, BufferCopy* regions);