public unsafe void Update(Rectangle <uint> bounds, ReadOnlySpan <byte> data) { Vk vk = _renderer.Vk; Buffer <byte> stagingBuffer = new(BufferUsageFlags.BufferUsageTransferSrcBit, MemoryPropertyFlags.MemoryPropertyHostVisibleBit | MemoryPropertyFlags.MemoryPropertyHostCoherentBit, _renderer); stagingBuffer.Update(data); TransitionImageLayout(ImageLayout.ShaderReadOnlyOptimal, ImageLayout.TransferDstOptimal); CommandBuffer commandBuffer = BeginImageCommandBuffer(); BufferImageCopy bufferImageCopy = new() { BufferOffset = 0, BufferRowLength = 0, BufferImageHeight = 0, ImageSubresource = new ImageSubresourceLayers() { AspectMask = ImageAspectFlags.ImageAspectColorBit, MipLevel = 0, BaseArrayLayer = 0, LayerCount = 1 }, ImageOffset = new Offset3D() { X = 0, Y = 0, Z = 0 }, ImageExtent = new Extent3D() { Width = Size.X, Height = Size.Y, Depth = 1 } }; vk.CmdCopyBufferToImage(commandBuffer, stagingBuffer.Handle, _image, ImageLayout.TransferDstOptimal, 1, bufferImageCopy); EndImageCommandBuffer(commandBuffer); TransitionImageLayout(ImageLayout.TransferDstOptimal, ImageLayout.ShaderReadOnlyOptimal); stagingBuffer.Dispose(); }
private unsafe CommandBuffer BeginImageCommandBuffer() { Device device = _renderer.Params.Device; Vk vk = _renderer.Vk; CommandBufferAllocateInfo commandBufferAllocateInfo = new() { SType = StructureType.CommandBufferAllocateInfo, CommandBufferCount = 1, CommandPool = _renderer.ImageTransitionPool }; _renderer.AssertVulkan(vk.AllocateCommandBuffers(device, commandBufferAllocateInfo, out CommandBuffer commandBuffer)); CommandBufferBeginInfo commandBufferBeginInfo = new() { SType = StructureType.CommandBufferBeginInfo, Flags = CommandBufferUsageFlags.CommandBufferUsageOneTimeSubmitBit, PInheritanceInfo = null }; _renderer.AssertVulkan(vk.BeginCommandBuffer(commandBuffer, commandBufferBeginInfo)); return(commandBuffer); } private unsafe void EndImageCommandBuffer(CommandBuffer commandBuffer) { Device device = _renderer.Params.Device; Vk vk = _renderer.Vk; _renderer.AssertVulkan(vk.EndCommandBuffer(commandBuffer)); SubmitInfo submitInfo = new() { SType = StructureType.SubmitInfo, CommandBufferCount = 1, PCommandBuffers = &commandBuffer, SignalSemaphoreCount = 0, PSignalSemaphores = null, WaitSemaphoreCount = 0, PWaitSemaphores = null, PWaitDstStageMask = null }; _renderer.AssertVulkan(vk.QueueSubmit(_renderer.ImageTransitionQueue, 1, submitInfo, default)); _renderer.AssertVulkan(vk.QueueWaitIdle(_renderer.ImageTransitionQueue)); vk.FreeCommandBuffers(device, _renderer.ImageTransitionPool, 1, commandBuffer); } private unsafe void TransitionImageLayout(ImageLayout oldLayout, ImageLayout newLayout) { Vk vk = _renderer.Vk; CommandBuffer commandBuffer = BeginImageCommandBuffer(); ImageMemoryBarrier imageMemoryBarrier = new() { SType = StructureType.ImageMemoryBarrier, OldLayout = oldLayout, NewLayout = newLayout, SrcQueueFamilyIndex = Vk.QueueFamilyIgnored, DstQueueFamilyIndex = Vk.QueueFamilyIgnored, Image = _image, SubresourceRange = new ImageSubresourceRange() { AspectMask = ImageAspectFlags.ImageAspectColorBit, BaseArrayLayer = 0, LayerCount = 1, BaseMipLevel = 0, LevelCount = _mipLevelCount }, SrcAccessMask = 0, DstAccessMask = 0 }; if ((oldLayout == ImageLayout.Undefined) && (newLayout == ImageLayout.TransferDstOptimal)) { imageMemoryBarrier.SrcAccessMask = 0; imageMemoryBarrier.DstAccessMask = AccessFlags.AccessTransferWriteBit; vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTopOfPipeBit, PipelineStageFlags.PipelineStageTransferBit, 0, 0, null, 0, null, 1, imageMemoryBarrier); } else if ((oldLayout == ImageLayout.TransferDstOptimal) && (newLayout == ImageLayout.ShaderReadOnlyOptimal)) { imageMemoryBarrier.SrcAccessMask = AccessFlags.AccessTransferWriteBit; imageMemoryBarrier.DstAccessMask = AccessFlags.AccessShaderReadBit; vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageFragmentShaderBit, 0, 0, null, 0, null, 1, imageMemoryBarrier); } else if ((oldLayout == ImageLayout.ShaderReadOnlyOptimal) && (newLayout == ImageLayout.TransferDstOptimal)) { imageMemoryBarrier.SrcAccessMask = AccessFlags.AccessShaderReadBit; imageMemoryBarrier.DstAccessMask = AccessFlags.AccessTransferWriteBit; vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageFragmentShaderBit, PipelineStageFlags.PipelineStageTransferBit, 0, 0, null, 0, null, 1, imageMemoryBarrier); } EndImageCommandBuffer(commandBuffer); } private void CopyBufferToImage(Buffer <byte> source) { Vk vk = _renderer.Vk; CommandBuffer commandBuffer = BeginImageCommandBuffer(); BufferImageCopy bufferImageCopy = new() { BufferOffset = 0, BufferRowLength = 0, BufferImageHeight = 0, ImageSubresource = new ImageSubresourceLayers() { AspectMask = ImageAspectFlags.ImageAspectColorBit, MipLevel = 0, BaseArrayLayer = 0, LayerCount = 1 }, ImageOffset = new Offset3D() { X = 0, Y = 0, Z = 0 }, ImageExtent = new Extent3D() { Width = Size.X, Height = Size.Y, Depth = 1 } }; vk.CmdCopyBufferToImage(commandBuffer, source.Handle, _image, ImageLayout.TransferDstOptimal, 1, bufferImageCopy); EndImageCommandBuffer(commandBuffer); }