private void PushDataImpl(CommandBufferScoped cbs, BufferHolder dst, int dstOffset, ReadOnlySpan <byte> data) { var srcBuffer = _buffer.GetBuffer(); var dstBuffer = dst.GetBuffer(); int offset = _freeOffset; int capacity = BufferSize - offset; if (capacity < data.Length) { _buffer.SetDataUnchecked(offset, data.Slice(0, capacity)); _buffer.SetDataUnchecked(0, data.Slice(capacity)); BufferHolder.Copy(_gd, cbs, srcBuffer, dstBuffer, offset, dstOffset, capacity); BufferHolder.Copy(_gd, cbs, srcBuffer, dstBuffer, 0, dstOffset + capacity, data.Length - capacity); } else { _buffer.SetDataUnchecked(offset, data); BufferHolder.Copy(_gd, cbs, srcBuffer, dstBuffer, offset, dstOffset, data.Length); } _freeOffset = (offset + data.Length) & (BufferSize - 1); _freeSize -= data.Length; Debug.Assert(_freeSize >= 0); _pendingCopies.Enqueue(new PendingCopy(cbs.GetFence(), data.Length)); }
public void ClearBuffer(BufferHandle destination, int offset, int size, uint value) { EndRenderPass(); var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, true).Get(Cbs, offset, size).Value; BufferHolder.InsertBufferBarrier( Gd, Cbs.CommandBuffer, dst, BufferHolder.DefaultAccessFlags, AccessFlags.AccessTransferWriteBit, PipelineStageFlags.PipelineStageAllCommandsBit, PipelineStageFlags.PipelineStageTransferBit, offset, size); Gd.Api.CmdFillBuffer(CommandBuffer, dst, (ulong)offset, (ulong)size, value); BufferHolder.InsertBufferBarrier( Gd, Cbs.CommandBuffer, dst, AccessFlags.AccessTransferWriteBit, BufferHolder.DefaultAccessFlags, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageAllCommandsBit, offset, size); }
public StagingBuffer(VulkanGraphicsDevice gd, BufferManager bufferManager) { _gd = gd; _buffer = bufferManager.Create(gd, BufferSize); _pendingCopies = new Queue <PendingCopy>(); _freeSize = BufferSize; }
public void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size) { EndRenderPass(); var src = Gd.BufferManager.GetBuffer(CommandBuffer, source, false); var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, true); BufferHolder.Copy(Gd, Cbs, src, dst, srcOffset, dstOffset, size); }
private bool TryGetBuffer(BufferHandle handle, out BufferHolder holder) { int index = (int)Unsafe.As <BufferHandle, ulong>(ref handle) - 1; if ((uint)index < _buffers.Count) { holder = _buffers[index]; return(true); } holder = default; return(false); }
public Span <byte> GetBufferData(CommandBufferPool cbp, BufferHolder buffer, int offset, int size) { var flushStorage = ResizeIfNeeded(size); using (var cbs = cbp.Rent()) { var srcBuffer = buffer.GetBuffer(cbs.CommandBuffer); var dstBuffer = flushStorage.GetBuffer(cbs.CommandBuffer); BufferHolder.Copy(_gd, cbs, srcBuffer, dstBuffer, offset, 0, size); } flushStorage.WaitForFences(); return(flushStorage.GetDataStorage(0, size)); }
public unsafe bool TryPushData(CommandBufferScoped cbs, Action endRenderPass, BufferHolder dst, int dstOffset, ReadOnlySpan <byte> data) { if (data.Length > BufferSize) { return(false); } if (_freeSize < data.Length) { FreeCompleted(); if (_freeSize < data.Length) { return(false); } } endRenderPass(); var srcBuffer = _buffer.GetBuffer(); var dstBuffer = dst.GetBuffer(); int offset = _freeOffset; int capacity = BufferSize - offset; if (capacity < data.Length) { _buffer.SetDataUnchecked(offset, data.Slice(0, capacity)); _buffer.SetDataUnchecked(0, data.Slice(capacity)); BufferHolder.Copy(_gd, cbs, srcBuffer, dstBuffer, offset, dstOffset, capacity); BufferHolder.Copy(_gd, cbs, srcBuffer, dstBuffer, 0, dstOffset + capacity, data.Length - capacity); } else { _buffer.SetDataUnchecked(offset, data); BufferHolder.Copy(_gd, cbs, srcBuffer, dstBuffer, offset, dstOffset, data.Length); } _freeOffset = (offset + data.Length) & (BufferSize - 1); _freeSize -= data.Length; Debug.Assert(_freeSize >= 0); _pendingCopies.Enqueue(new PendingCopy(cbs.GetFence(), data.Length)); return(true); }
private BufferHolder ResizeIfNeeded(int size) { var flushStorage = _flushStorage; if (flushStorage == null || size > _flushStorage.Size) { if (flushStorage != null) { flushStorage.Dispose(); } flushStorage = _gd.BufferManager.Create(_gd, size); _flushStorage = flushStorage; } return(flushStorage); }
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 unsafe void PushData(CommandBufferPool cbp, CommandBufferScoped?cbs, Action endRenderPass, BufferHolder dst, int dstOffset, ReadOnlySpan <byte> data) { bool isRender = cbs != null; CommandBufferScoped scoped = cbs ?? cbp.Rent(); // Must push all data to the buffer. If it can't fit, split it up. endRenderPass?.Invoke(); while (data.Length > 0) { if (_freeSize < data.Length) { FreeCompleted(); } while (_freeSize == 0) { if (!WaitFreeCompleted(cbp)) { if (isRender) { _gd.FlushAllCommands(); scoped = cbp.Rent(); isRender = false; } else { scoped = cbp.ReturnAndRent(scoped); } } } int chunkSize = Math.Min(_freeSize, data.Length); PushDataImpl(scoped, dst, dstOffset, data.Slice(0, chunkSize)); dstOffset += chunkSize; data = data.Slice(chunkSize); } if (!isRender) { scoped.Dispose(); } }
public unsafe bool TryPushData(CommandBufferScoped cbs, Action endRenderPass, BufferHolder dst, int dstOffset, ReadOnlySpan <byte> data) { if (data.Length > BufferSize) { return(false); } if (_freeSize < data.Length) { FreeCompleted(); if (_freeSize < data.Length) { return(false); } } endRenderPass(); PushDataImpl(cbs, dst, dstOffset, data); return(true); }
public DescriptorSetUpdater(VulkanRenderer gd, PipelineBase pipeline) { _gd = gd; _pipeline = pipeline; // Some of the bindings counts needs to be multiplied by 2 because we have buffer and // regular textures/images interleaved on the same descriptor set. _uniformBufferRefs = new Auto <DisposableBuffer> [Constants.MaxUniformBufferBindings]; _storageBufferRefs = new Auto <DisposableBuffer> [Constants.MaxStorageBufferBindings]; _textureRefs = new Auto <DisposableImageView> [Constants.MaxTextureBindings * 2]; _samplerRefs = new Auto <DisposableSampler> [Constants.MaxTextureBindings * 2]; _imageRefs = new Auto <DisposableImageView> [Constants.MaxImageBindings * 2]; _bufferTextureRefs = new TextureBuffer[Constants.MaxTextureBindings * 2]; _bufferImageRefs = new TextureBuffer[Constants.MaxImageBindings * 2]; _bufferImageFormats = new GAL.Format[Constants.MaxImageBindings * 2]; _uniformBuffers = new DescriptorBufferInfo[Constants.MaxUniformBufferBindings]; _storageBuffers = new DescriptorBufferInfo[Constants.MaxStorageBufferBindings]; _textures = new DescriptorImageInfo[Constants.MaxTexturesPerStage]; _images = new DescriptorImageInfo[Constants.MaxImagesPerStage]; _bufferTextures = new BufferView[Constants.MaxTexturesPerStage]; _bufferImages = new BufferView[Constants.MaxImagesPerStage]; var initialImageInfo = new DescriptorImageInfo() { ImageLayout = ImageLayout.General }; _textures.AsSpan().Fill(initialImageInfo); _images.AsSpan().Fill(initialImageInfo); _uniformSet = new bool[Constants.MaxUniformBufferBindings]; _storageSet = new bool[Constants.MaxStorageBufferBindings]; if (gd.Capabilities.SupportsNullDescriptors) { // If null descriptors are supported, we can pass null as the handle. _dummyBuffer = null; } else { // If null descriptors are not supported, we need to pass the handle of a dummy buffer on unused bindings. _dummyBuffer = gd.BufferManager.Create(gd, 0x10000, forConditionalRendering: false, deviceLocal: true); } _dummyTexture = gd.CreateTextureView(new GAL.TextureCreateInfo( 1, 1, 1, 1, 1, 1, 1, 4, GAL.Format.R8G8B8A8Unorm, DepthStencilMode.Depth, Target.Texture2D, SwizzleComponent.Red, SwizzleComponent.Green, SwizzleComponent.Blue, SwizzleComponent.Alpha), 1f); _dummySampler = (SamplerHolder)gd.CreateSampler(new GAL.SamplerCreateInfo( MinFilter.Nearest, MagFilter.Nearest, false, AddressMode.Repeat, AddressMode.Repeat, AddressMode.Repeat, CompareMode.None, GAL.CompareOp.Always, new ColorF(0, 0, 0, 0), 0, 0, 0, 1f)); }
private bool TryGetBuffer(BufferHandle handle, out BufferHolder holder) { return(_buffers.TryGetValue((int)Unsafe.As <BufferHandle, ulong>(ref handle), out holder)); }
private static void BlitDepthStencilWithBuffer( VulkanRenderer gd, CommandBufferScoped cbs, TextureView src, TextureView dst, Extents2D srcRegion, Extents2D dstRegion) { int drBaseX = Math.Min(dstRegion.X1, dstRegion.X2); int drBaseY = Math.Min(dstRegion.Y1, dstRegion.Y2); int drWidth = Math.Abs(dstRegion.X2 - dstRegion.X1); int drHeight = Math.Abs(dstRegion.Y2 - dstRegion.Y1); var drOriginZero = new Extents2D( dstRegion.X1 - drBaseX, dstRegion.Y1 - drBaseY, dstRegion.X2 - drBaseX, dstRegion.Y2 - drBaseY); var d32SrcStorageInfo = TextureStorage.NewCreateInfoWith(ref src._info, GAL.Format.D32Float, 4); var d32DstStorageInfo = TextureStorage.NewCreateInfoWith(ref dst._info, GAL.Format.D32Float, 4, drWidth, drHeight); var s8SrcStorageInfo = TextureStorage.NewCreateInfoWith(ref src._info, GAL.Format.S8Uint, 1); var s8DstStorageInfo = TextureStorage.NewCreateInfoWith(ref dst._info, GAL.Format.S8Uint, 1, drWidth, drHeight); using var d32SrcStorage = gd.CreateTextureStorage(d32SrcStorageInfo, src.Storage.ScaleFactor); using var d32DstStorage = gd.CreateTextureStorage(d32DstStorageInfo, dst.Storage.ScaleFactor); using var s8SrcStorage = gd.CreateTextureStorage(s8SrcStorageInfo, src.Storage.ScaleFactor); using var s8DstStorage = gd.CreateTextureStorage(s8DstStorageInfo, dst.Storage.ScaleFactor); void SlowBlit(TextureStorage srcTemp, TextureStorage dstTemp, ImageAspectFlags aspectFlags) { int levels = Math.Min(src.Info.Levels, dst.Info.Levels); int srcSize = 0; int dstSize = 0; for (int l = 0; l < levels; l++) { srcSize += srcTemp.Info.GetMipSize2D(l); dstSize += dstTemp.Info.GetMipSize2D(l); } using var srcTempBuffer = gd.BufferManager.Create(gd, srcSize, deviceLocal: true); using var dstTempBuffer = gd.BufferManager.Create(gd, dstSize, deviceLocal: true); src.Storage.CopyFromOrToBuffer( cbs.CommandBuffer, srcTempBuffer.GetBuffer().Get(cbs, 0, srcSize).Value, src.GetImage().Get(cbs).Value, srcSize, to: true, 0, 0, src.FirstLayer, src.FirstLevel, 1, levels, true, aspectFlags, false); BufferHolder.InsertBufferBarrier( gd, cbs.CommandBuffer, srcTempBuffer.GetBuffer().Get(cbs, 0, srcSize).Value, AccessFlags.AccessTransferWriteBit, AccessFlags.AccessTransferReadBit, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageTransferBit, 0, srcSize); srcTemp.CopyFromOrToBuffer( cbs.CommandBuffer, srcTempBuffer.GetBuffer().Get(cbs, 0, srcSize).Value, srcTemp.GetImage().Get(cbs).Value, srcSize, to: false, 0, 0, 0, 0, 1, levels, true, aspectFlags, false); InsertImageBarrier( gd.Api, cbs.CommandBuffer, srcTemp.GetImage().Get(cbs).Value, AccessFlags.AccessTransferWriteBit, AccessFlags.AccessTransferReadBit, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageTransferBit, aspectFlags, 0, 0, 1, levels); TextureCopy.Blit( gd.Api, cbs.CommandBuffer, srcTemp.GetImage().Get(cbs).Value, dstTemp.GetImage().Get(cbs).Value, srcTemp.Info, dstTemp.Info, srcRegion, drOriginZero, 0, 0, 0, 0, 1, levels, false, aspectFlags, aspectFlags); InsertImageBarrier( gd.Api, cbs.CommandBuffer, dstTemp.GetImage().Get(cbs).Value, AccessFlags.AccessTransferWriteBit, AccessFlags.AccessTransferReadBit, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageTransferBit, aspectFlags, 0, 0, 1, levels); dstTemp.CopyFromOrToBuffer( cbs.CommandBuffer, dstTempBuffer.GetBuffer().Get(cbs, 0, dstSize).Value, dstTemp.GetImage().Get(cbs).Value, dstSize, to: true, 0, 0, 0, 0, 1, levels, true, aspectFlags, false); BufferHolder.InsertBufferBarrier( gd, cbs.CommandBuffer, dstTempBuffer.GetBuffer().Get(cbs, 0, dstSize).Value, AccessFlags.AccessTransferWriteBit, AccessFlags.AccessTransferReadBit, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageTransferBit, 0, dstSize); dst.Storage.CopyFromOrToBuffer( cbs.CommandBuffer, dstTempBuffer.GetBuffer().Get(cbs, 0, dstSize).Value, dst.GetImage().Get(cbs).Value, dstSize, to: false, drBaseX, drBaseY, dst.FirstLayer, dst.FirstLevel, 1, levels, true, aspectFlags, false); } SlowBlit(d32SrcStorage, d32DstStorage, ImageAspectFlags.ImageAspectDepthBit); SlowBlit(s8SrcStorage, s8DstStorage, ImageAspectFlags.ImageAspectStencilBit); }