Exemple #1
0
 public void BindIndexBuffer(Vk api, CommandBufferScoped cbs)
 {
     if (_buffer != null)
     {
         api.CmdBindIndexBuffer(cbs.CommandBuffer, _buffer.Get(cbs, _offset, _size).Value, (ulong)_offset, _type);
     }
 }
Exemple #2
0
        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));
        }
        private DescriptorSetCollection CreateBuffer(CommandBufferScoped cbs, ref BufferHandleSet key, int setIndex, DescriptorType type)
        {
            var dsc = _gd.DescriptorSetManager.AllocateDescriptorSet(_gd.Api, _descriptorSetLayouts[setIndex]).Get(cbs);

            Span <DescriptorBufferInfo> bufferInfos = stackalloc DescriptorBufferInfo[key.Count];

            for (int i = 0; i < key.Count; i++)
            {
                uint size = key.Sizes[i];

                if (type == DescriptorType.UniformBufferDynamic)
                {
                    size = Math.Min(size, 0x10000);
                }

                bufferInfos[i] = new DescriptorBufferInfo()
                {
                    Buffer = new VkBuffer(key.Handles[i]),
                    Offset = 0,
                    Range  = size
                };
            }

            dsc.UpdateBuffers(0, 0, bufferInfos, type);

            return(dsc);
        }
Exemple #4
0
 public void SetDataInline(CommandBufferScoped cbs, Action endRenderPass, int dstOffset, ReadOnlySpan <byte> data)
 {
     if (!TryPushData(cbs, endRenderPass, dstOffset, data))
     {
         throw new ArgumentException($"Invalid offset 0x{dstOffset:X} or data size 0x{data.Length:X}.");
     }
 }
Exemple #5
0
        public void AddCommandBufferDependencies(CommandBufferScoped cbs)
        {
            // We don't want to add a reference to this object to the command buffer
            // more than once, so if we detect that the command buffer already has ownership
            // of this object, then we can just return without doing anything else.
            if (_cbOwnership.Set(cbs.CommandBufferIndex))
            {
                if (_waitable != null)
                {
                    cbs.AddWaitable(_waitable);
                }

                cbs.AddDependant(this);

                // We need to add a dependency on the command buffer to all objects this object
                // references aswell.
                if (_referencedObjs != null)
                {
                    for (int i = 0; i < _referencedObjs.Length; i++)
                    {
                        _referencedObjs[i].AddCommandBufferDependencies(cbs);
                    }
                }
            }
        }
Exemple #6
0
        public void BindTransformFeedbackBuffer(VulkanRenderer gd, CommandBufferScoped cbs, uint binding)
        {
            if (_buffer != null)
            {
                var buffer = _buffer.Get(cbs, _offset, _size).Value;

                gd.TransformFeedbackApi.CmdBindTransformFeedbackBuffers(cbs.CommandBuffer, binding, 1, buffer, (ulong)_offset, (ulong)_size);
            }
        }
Exemple #7
0
        public Auto <DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, BufferHandle handle, int offset, int size)
        {
            if (TryGetBuffer(handle, out var holder))
            {
                return(holder.GetBufferI8ToI16(cbs, offset, size));
            }

            return(null);
        }
Exemple #8
0
        public void BindVertexBuffer(VulkanGraphicsDevice gd, CommandBufferScoped cbs, uint binding)
        {
            if (_buffer != null)
            {
                var buffer = _buffer.Get(cbs, _offset, _size).Value;

                gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, binding, 1, buffer, (ulong)_offset);
            }
        }
Exemple #9
0
        public T Get(CommandBufferScoped cbs)
        {
            if (!_destroyed)
            {
                AddCommandBufferDependencies(cbs);
            }

            return(_value);
        }
Exemple #10
0
        public BufferView GetBufferView(CommandBufferScoped cbs)
        {
            if (_bufferView == null)
            {
                _bufferView = _gd.BufferManager.CreateView(_bufferHandle, VkFormat, _offset, _size);
            }

            return _bufferView?.Get(cbs, _offset, _size).Value ?? default;
        }
        private static void UpdateBuffer(CommandBufferScoped cbs, ref DescriptorBufferInfo info, Auto <DisposableBuffer> buffer)
        {
            info.Buffer = buffer?.Get(cbs, (int)info.Offset, (int)info.Range).Value ?? default;

            // The spec requires that buffers with null handle have offset as 0 and range as VK_WHOLE_SIZE.
            if (info.Buffer.Handle == 0)
            {
                info.Offset = 0;
                info.Range  = Vk.WholeSize;
            }
        }
Exemple #12
0
        public Auto <DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, int offset, int size)
        {
            if (!_cachedConvertedIndexBuffers.TryGetValue(offset, size, out var holder))
            {
                holder = _gd.BufferManager.Create(_gd, (size * 2 + 3) & ~3);

                _gd.HelperShader.ConvertI8ToI16(_gd, cbs, this, holder, offset, size);

                _cachedConvertedIndexBuffers.Add(offset, size, holder);
            }

            return(holder.GetBuffer());
        }
Exemple #13
0
        public void SetCommandBuffer(CommandBufferScoped cbs)
        {
            CommandBuffer = (Cbs = cbs).CommandBuffer;

            // Restore per-command buffer state.

            if (Pipeline != null)
            {
                Gd.Api.CmdBindPipeline(CommandBuffer, Pbp, Pipeline.Get(CurrentCommandBuffer).Value);
            }

            SignalCommandBufferChange();
        }
Exemple #14
0
        private unsafe bool TryPushData(CommandBufferScoped cbs, Action endRenderPass, int dstOffset, ReadOnlySpan <byte> data)
        {
            if ((dstOffset & 3) != 0 || (data.Length & 3) != 0)
            {
                return(false);
            }

            endRenderPass();

            var dstBuffer = GetBuffer(cbs.CommandBuffer, true).Get(cbs, dstOffset, data.Length).Value;

            InsertBufferBarrier(
                _gd,
                cbs.CommandBuffer,
                dstBuffer,
                BufferHolder.DefaultAccessFlags,
                AccessFlags.AccessTransferWriteBit,
                PipelineStageFlags.PipelineStageAllCommandsBit,
                PipelineStageFlags.PipelineStageTransferBit,
                dstOffset,
                data.Length);

            fixed(byte *pData = data)
            {
                for (ulong offset = 0; offset < (ulong)data.Length;)
                {
                    ulong size = Math.Min(MaxUpdateBufferSize, (ulong)data.Length - offset);
                    _gd.Api.CmdUpdateBuffer(cbs.CommandBuffer, dstBuffer, (ulong)dstOffset + offset, size, pData + offset);
                    offset += size;
                }
            }

            InsertBufferBarrier(
                _gd,
                cbs.CommandBuffer,
                dstBuffer,
                AccessFlags.AccessTransferWriteBit,
                BufferHolder.DefaultAccessFlags,
                PipelineStageFlags.PipelineStageTransferBit,
                PipelineStageFlags.PipelineStageAllCommandsBit,
                dstOffset,
                data.Length);

            // Not flushing commands here causes glitches on Intel (driver bug?)
            if (_gd.IsIntelGpu)
            {
                _gd.FlushAllCommands();
            }

            return(true);
        }
        private static DescriptorSetCollection GetOrCreate <T>(
            CommandBufferScoped cbs,
            ref T key,
            Dictionary <T, DescriptorSetCollection> hashTable,
            CreateCallback <T> createCallback)
        {
            if (!hashTable.TryGetValue(key, out var ds))
            {
                ds = createCallback(cbs, ref key);
                hashTable.Add(key, ds);
            }

            return(ds);
        }
        private DescriptorSetCollection CreateBufferImage(CommandBufferScoped cbs, ref HandleSet key, int setIndex, DescriptorType type)
        {
            var dsc = _gd.DescriptorSetManager.AllocateDescriptorSet(_gd.Api, _descriptorSetLayouts[setIndex]).Get(cbs);

            Span <BufferView> texelBufferView = stackalloc BufferView[key.Count];

            for (int i = 0; i < key.Count; i++)
            {
                texelBufferView[i] = new BufferView(key.Handles[i]);
            }

            dsc.UpdateBufferImages(0, 0, texelBufferView, type);

            return(dsc);
        }
Exemple #17
0
        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);
        }
Exemple #18
0
        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();
            }
        }
        private DescriptorSetCollection CreateImage(CommandBufferScoped cbs, ref HandleSet key)
        {
            var dsc = _gd.DescriptorSetManager.AllocateDescriptorSet(_gd.Api, _descriptorSetLayouts[PipelineBase.ImageSetIndex]).Get(cbs);

            Span <DescriptorImageInfo> imageInfos = stackalloc DescriptorImageInfo[key.Count];

            for (int i = 0; i < key.Count; i++)
            {
                imageInfos[i] = new DescriptorImageInfo()
                {
                    ImageLayout = ImageLayout.General,
                    ImageView   = new ImageView(key.Handles[i])
                };
            }

            dsc.UpdateImages(0, 0, imageInfos, DescriptorType.StorageImage);

            return(dsc);
        }
Exemple #20
0
        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 void UpdateAndBindDescriptorSets(CommandBufferScoped cbs, PipelineBindPoint pbp)
        {
            if ((_dirty & DirtyFlags.All) == 0)
            {
                return;
            }

            // System.Console.WriteLine("modified " + _dirty + " " + _modified + " on program " + _program.GetHashCode().ToString("X"));

            if (_dirty.HasFlag(DirtyFlags.Uniform))
            {
                UpdateAndBind(cbs, PipelineBase.UniformSetIndex, DirtyFlags.Uniform, pbp);
            }

            if (_dirty.HasFlag(DirtyFlags.Storage))
            {
                UpdateAndBind(cbs, PipelineBase.StorageSetIndex, DirtyFlags.Storage, pbp);
            }

            if (_dirty.HasFlag(DirtyFlags.Texture))
            {
                UpdateAndBind(cbs, PipelineBase.TextureSetIndex, DirtyFlags.Texture, pbp);
            }

            if (_dirty.HasFlag(DirtyFlags.Image))
            {
                UpdateAndBind(cbs, PipelineBase.ImageSetIndex, DirtyFlags.Image, pbp);
            }

            if (_dirty.HasFlag(DirtyFlags.BufferTexture))
            {
                UpdateAndBind(cbs, PipelineBase.BufferTextureSetIndex, DirtyFlags.BufferTexture, pbp);
            }

            if (_dirty.HasFlag(DirtyFlags.BufferImage))
            {
                UpdateAndBind(cbs, PipelineBase.BufferImageSetIndex, DirtyFlags.BufferImage, pbp);
            }

            _dirty = DirtyFlags.None;
        }
Exemple #22
0
        public BufferView GetBufferView(CommandBufferScoped cbs, GAL.Format format)
        {
            var vkFormat = FormatTable.GetFormat(format);
            if (vkFormat == VkFormat)
            {
                return GetBufferView(cbs);
            }

            if (_selfManagedViews != null && _selfManagedViews.TryGetValue(format, out var bufferView))
            {
                return bufferView.Get(cbs, _offset, _size).Value;
            }

            bufferView = _gd.BufferManager.CreateView(_bufferHandle, vkFormat, _offset, _size);

            if (bufferView != null)
            {
                (_selfManagedViews ??= new Dictionary<GAL.Format, Auto<DisposableBufferView>>()).Add(format, bufferView);
            }

            return bufferView?.Get(cbs, _offset, _size).Value ?? default;
        }
Exemple #23
0
        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, &region);

            InsertBufferBarrier(
                gd,
                cbs.CommandBuffer,
                dstBuffer,
                AccessFlags.AccessTransferWriteBit,
                BufferHolder.DefaultAccessFlags,
                PipelineStageFlags.PipelineStageTransferBit,
                PipelineStageFlags.PipelineStageAllCommandsBit,
                dstOffset,
                size);
        }
Exemple #24
0
        public void BindVertexBuffer(VulkanRenderer gd, CommandBufferScoped cbs, uint binding)
        {
            if (_buffer != null)
            {
                var buffer = _buffer.Get(cbs, _offset, _size).Value;

                if (gd.Capabilities.SupportsExtendedDynamicState)
                {
                    gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2(
                        cbs.CommandBuffer,
                        binding,
                        1,
                        buffer,
                        (ulong)_offset,
                        (ulong)_size,
                        _stride);
                }
                else
                {
                    gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, binding, 1, buffer, (ulong)_offset);
                }
            }
        }
Exemple #25
0
        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);
        }
Exemple #26
0
        public unsafe Auto <DisposableFramebuffer> Create(Vk api, CommandBufferScoped cbs, Auto <DisposableRenderPass> renderPass)
        {
            ImageView *attachments = stackalloc ImageView[_attachments.Length];

            for (int i = 0; i < _attachments.Length; i++)
            {
                attachments[i] = _attachments[i].Get(cbs).Value;
            }

            var framebufferCreateInfo = new FramebufferCreateInfo()
            {
                SType           = StructureType.FramebufferCreateInfo,
                RenderPass      = renderPass.Get(cbs).Value,
                AttachmentCount = (uint)_attachments.Length,
                PAttachments    = attachments,
                Width           = Width,
                Height          = Height,
                Layers          = Layers
            };

            api.CreateFramebuffer(_device, framebufferCreateInfo, null, out var framebuffer).ThrowOnError();
            return(new Auto <DisposableFramebuffer>(new DisposableFramebuffer(api, _device, framebuffer), null, _attachments));
        }
 public DescriptorSetCollection GetTexture(CommandBufferScoped cbs, ref CombinedImageHandleSet key)
 {
     return(GetOrCreate(cbs, ref key, _tCache, CreateImage));
 }
 private DescriptorSetCollection CreateStorageBuffer(CommandBufferScoped cbs, ref BufferHandleSet key)
 {
     return(CreateBuffer(cbs, ref key, PipelineBase.StorageSetIndex, DescriptorType.StorageBufferDynamic));
 }
 public DescriptorSetCollection GetBufferImage(CommandBufferScoped cbs, ref HandleSet key)
 {
     return(GetOrCreate(cbs, ref key, _bICache, CreateBufferImage));
 }
 private DescriptorSetCollection CreateBufferImage(CommandBufferScoped cbs, ref HandleSet key)
 {
     return(CreateBufferImage(cbs, ref key, PipelineBase.BufferImageSetIndex, DescriptorType.StorageTexelBuffer));
 }