private void setImageMemoryBarrier(VkCommandBuffer command,
                                           VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
                                           VkImageLayout oldLayout, VkImageLayout newLayout,
                                           VkImage image, VkImageAspectFlags aspectFlags)
        {
            var imageMemoryBarrier = new VkImageMemoryBarrier()
            {
                srcAccessMask       = srcAccessMask,
                dstAccessMask       = dstAccessMask,
                oldLayout           = oldLayout,
                newLayout           = newLayout,
                srcQueueFamilyIndex = ~0u,
                dstQueueFamilyIndex = ~0u,
                subresourceRange    = new VkImageSubresourceRange
                {
                    aspectMask     = aspectFlags,
                    baseMipLevel   = 0,
                    levelCount     = 1,
                    baseArrayLayer = 0,
                    layerCount     = 1,
                },
                image = image
            };

            VulkanAPI.vkCmdPipelineBarrier(
                command,
                VkPipelineStageFlags.VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
                VkPipelineStageFlags.VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
                0,
                null, // MemoryBarriers
                null, // BufferMemoryBarriers
                new VkImageMemoryBarrier[] { imageMemoryBarrier }
                );
        }
Пример #2
0
        public void SetLayout(
            CommandBuffer cmdbuffer,
            VkAccessFlags srcAccessMask,
            VkAccessFlags dstAccessMask,
            VkImageLayout oldImageLayout,
            VkImageLayout newImageLayout,
            VkImageSubresourceRange subresourceRange,
            VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands,
            VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands,
            uint srcQueueFamilyIndex          = Vk.QueueFamilyIgnored,
            uint dstQueueFamilyIndex          = Vk.QueueFamilyIgnored)
        {
            VkImageMemoryBarrier imageMemoryBarrier = VkImageMemoryBarrier.New();

            imageMemoryBarrier.srcQueueFamilyIndex = srcQueueFamilyIndex;
            imageMemoryBarrier.dstQueueFamilyIndex = dstQueueFamilyIndex;
            imageMemoryBarrier.oldLayout           = oldImageLayout;
            imageMemoryBarrier.newLayout           = newImageLayout;
            imageMemoryBarrier.image            = handle;
            imageMemoryBarrier.subresourceRange = subresourceRange;
            imageMemoryBarrier.srcAccessMask    = srcAccessMask;
            imageMemoryBarrier.dstAccessMask    = dstAccessMask;

            Vk.vkCmdPipelineBarrier(
                cmdbuffer.Handle,
                srcStageMask,
                dstStageMask,
                0,
                0, IntPtr.Zero,
                0, IntPtr.Zero,
                1, ref imageMemoryBarrier);
        }
Пример #3
0
 public unsafe VkMemoryBarrier(VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask)
 {
     this.sType         = VkStructureType.MemoryBarrier;
     this.pNext         = null;
     this.srcAccessMask = (VkAccessFlags)srcAccessMask;
     this.dstAccessMask = (VkAccessFlags)dstAccessMask;
 }
Пример #4
0
        public void SetMemoryBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
                                     VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkDependencyFlags dependencyFlags = VkDependencyFlags.ByRegion)
        {
            VkMemoryBarrier memoryBarrier = VkMemoryBarrier.New();

            memoryBarrier.srcAccessMask = srcAccessMask;
            memoryBarrier.dstAccessMask = dstAccessMask;
            Vk.vkCmdPipelineBarrier(Handle, srcStageMask, dstStageMask,
                                    dependencyFlags, 1, ref memoryBarrier, 0, IntPtr.Zero, 0, IntPtr.Zero);
        }
Пример #5
0
 public void SetFullHandles(VkImage image, VkImageView attachmentView,
                            VkImageLayout layout, VkAccessFlags accessMask,
                            VkFormat nativeFormat, VkImageAspectFlags aspect)
 {
     NativeImage = image;
     NativeColorAttachmentView = attachmentView;
     NativeLayout      = layout;
     NativeAccessMask  = accessMask;
     NativeFormat      = nativeFormat;
     NativeImageAspect = aspect;
 }
Пример #6
0
        private void barrier(VkPipelineStageFlags src_stages, VkAccessFlags src_access, VkPipelineStageFlags dst_stages,
                             VkAccessFlags dst_access)
        {
            VkMemoryBarrier barrier = new()
            {
                sType = VkStructureType.MemoryBarrier,
            };

            barrier.srcAccessMask = src_access;
            barrier.dstAccessMask = dst_access;
            vkCmdPipelineBarrier(handle, src_stages, dst_stages, 0, 1, &barrier, 0, null, 0, null);
        }
Пример #7
0
 public void AddDependency(uint srcSubpass, uint dstSubpass,
                           VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
                           VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
                           VkDependencyFlags dependencyFlags = VkDependencyFlags.ByRegion)
 {
     dependencies.Add(new VkSubpassDependency {
         srcSubpass      = srcSubpass,
         dstSubpass      = dstSubpass,
         srcStageMask    = srcStageMask,
         dstStageMask    = dstStageMask,
         srcAccessMask   = srcAccessMask,
         dstAccessMask   = dstAccessMask,
         dependencyFlags = dependencyFlags
     });
 }
Пример #8
0
 public unsafe VkImageMemoryBarrier(VkImage image, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout,
                                    VkImageAspectFlags aspectMask = VkImageAspectFlags.Color, uint baseMipLevel = 0, uint levelCount = uint.MaxValue)
 {
     this.sType                           = VkStructureType.ImageMemoryBarrier;
     this.pNext                           = null;
     this.srcAccessMask                   = (VkAccessFlags)srcAccessMask;
     this.dstAccessMask                   = (VkAccessFlags)dstAccessMask;
     this.oldLayout                       = (VkImageLayout)oldLayout;
     this.newLayout                       = (VkImageLayout)newLayout;
     this.srcQueueFamilyIndex             = uint.MaxValue;
     this.dstQueueFamilyIndex             = uint.MaxValue;
     this.image                           = image;
     this.subresourceRange.aspectMask     = (VkImageAspectFlags)aspectMask;
     this.subresourceRange.baseMipLevel   = baseMipLevel;
     this.subresourceRange.baseArrayLayer = 0;
     this.subresourceRange.levelCount     = levelCount;
     this.subresourceRange.layerCount     = uint.MaxValue;
 }
Пример #9
0
 public unsafe VkBufferMemoryBarrier(
     VkBuffer buffer,
     VkAccessFlags srcAccessMask,
     VkAccessFlags dstAccessMask,
     ulong offset             = 0,
     ulong size               = Vulkan.WholeSize,
     uint srcQueueFamilyIndex = Vulkan.QueueFamilyIgnored,
     uint dstQueueFamilyIndex = Vulkan.QueueFamilyIgnored,
     void *pNext              = default)
 {
     sType                    = VkStructureType.BufferMemoryBarrier;
     this.pNext               = pNext;
     this.srcAccessMask       = srcAccessMask;
     this.dstAccessMask       = dstAccessMask;
     this.srcQueueFamilyIndex = srcQueueFamilyIndex;
     this.dstQueueFamilyIndex = dstQueueFamilyIndex;
     this.buffer              = buffer;
     this.offset              = offset;
     this.size                = size;
 }
Пример #10
0
 public VkBufferMemoryBarrier(
     VkBuffer buffer,
     VkAccessFlags srcAccessMask,
     VkAccessFlags dstAccessMask,
     ulong offset             = 0,
     ulong size               = VK_WHOLE_SIZE,
     uint srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
     uint dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
     void *pNext              = default)
 {
     sType                    = VkStructureType.BufferMemoryBarrier;
     this.pNext               = pNext;
     this.srcAccessMask       = srcAccessMask;
     this.dstAccessMask       = dstAccessMask;
     this.srcQueueFamilyIndex = srcQueueFamilyIndex;
     this.dstQueueFamilyIndex = dstQueueFamilyIndex;
     this.buffer              = buffer;
     this.offset              = offset;
     this.size                = size;
 }
 public VkImageMemoryBarrier(
     VkImage image,
     VkImageSubresourceRange subresourceRange,
     VkAccessFlags srcAccessMask,
     VkAccessFlags dstAccessMask,
     VkImageLayout oldLayout,
     VkImageLayout newLayout,
     uint srcQueueFamilyIndex = VulkanNative.QueueFamilyIgnored,
     uint dstQueueFamilyIndex = VulkanNative.QueueFamilyIgnored)
 {
     sType = VkStructureType.ImageMemoryBarrier;
     pNext = null;
     this.srcAccessMask       = srcAccessMask;
     this.dstAccessMask       = dstAccessMask;
     this.oldLayout           = oldLayout;
     this.newLayout           = newLayout;
     this.srcQueueFamilyIndex = srcQueueFamilyIndex;
     this.dstQueueFamilyIndex = dstQueueFamilyIndex;
     this.image            = image;
     this.subresourceRange = subresourceRange;
 }
Пример #12
0
        public void SetLayout(
            CommandBuffer cmdbuffer,
            VkImageAspectFlags aspectMask,
            VkAccessFlags srcAccessMask,
            VkAccessFlags dstAccessMask,
            VkImageLayout oldImageLayout,
            VkImageLayout newImageLayout,
            VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands,
            VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands,
            uint srcQueueFamilyIndex          = Vk.QueueFamilyIgnored,
            uint dstQueueFamilyIndex          = Vk.QueueFamilyIgnored)
        {
            VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange {
                aspectMask   = aspectMask,
                baseMipLevel = 0,
                levelCount   = CreateInfo.mipLevels,
                layerCount   = CreateInfo.arrayLayers,
            };

            SetLayout(cmdbuffer, srcAccessMask, dstAccessMask, oldImageLayout, newImageLayout, subresourceRange, srcStageMask, dstStageMask,
                      srcQueueFamilyIndex, dstQueueFamilyIndex);
        }
Пример #13
0
 public unsafe VkImageMemoryBarrier(
     VkImage image,
     VkImageSubresourceRange subresourceRange,
     VkAccessFlags srcAccessMask,
     VkAccessFlags dstAccessMask,
     VkImageLayout oldLayout,
     VkImageLayout newLayout,
     uint srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
     uint dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
     void *pNext = default)
 {
     sType                    = VkStructureType.ImageMemoryBarrier;
     this.pNext               = pNext;
     this.srcAccessMask       = srcAccessMask;
     this.dstAccessMask       = dstAccessMask;
     this.oldLayout           = oldLayout;
     this.newLayout           = newLayout;
     this.srcQueueFamilyIndex = srcQueueFamilyIndex;
     this.dstQueueFamilyIndex = dstQueueFamilyIndex;
     this.image               = image;
     this.subresourceRange    = subresourceRange;
 }
Пример #14
0
        /// <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)
        {
            // capture vertex information for possible later easy batching or physics mesh generation
            if (dataPointer != IntPtr.Zero &&
                (ViewFlags == BufferFlags.VertexBuffer && (CaptureAllModelBuffers || bufferDescription.SizeInBytes <= CaptureVertexBuffersOfSize) ||
                 ViewFlags == BufferFlags.IndexBuffer && (CaptureAllModelBuffers || bufferDescription.SizeInBytes <= CaptureIndexBuffersOfSize)))
            {
                VertIndexData = new byte[Description.SizeInBytes];
                fixed(byte *vid = &VertIndexData[0])
                {
                    Utilities.CopyMemory((IntPtr)vid, dataPointer, VertIndexData.Length);
                }
            }
            else
            {
                VertIndexData = null;
            }

            var createInfo = new VkBufferCreateInfo
            {
                sType = VkStructureType.BufferCreateInfo,
                size  = (ulong)bufferDescription.SizeInBytes,
                flags = VkBufferCreateFlags.None,
            };

            createInfo.usage |= VkBufferUsageFlags.TransferSrc;
            createInfo.usage |= VkBufferUsageFlags.TransferDst;

            if (Usage == GraphicsResourceUsage.Staging)
            {
                NativeAccessMask         = VkAccessFlags.HostRead | VkAccessFlags.HostWrite;
                NativePipelineStageMask |= VkPipelineStageFlags.Host;
            }
            else
            {
                if ((ViewFlags & BufferFlags.VertexBuffer) != 0)
                {
                    createInfo.usage        |= VkBufferUsageFlags.VertexBuffer;
                    NativeAccessMask        |= VkAccessFlags.VertexAttributeRead;
                    NativePipelineStageMask |= VkPipelineStageFlags.VertexInput;
                }

                if ((ViewFlags & BufferFlags.IndexBuffer) != 0)
                {
                    createInfo.usage        |= VkBufferUsageFlags.IndexBuffer;
                    NativeAccessMask        |= VkAccessFlags.IndexRead;
                    NativePipelineStageMask |= VkPipelineStageFlags.VertexInput;
                }

                if ((ViewFlags & BufferFlags.ConstantBuffer) != 0)
                {
                    createInfo.usage        |= VkBufferUsageFlags.UniformBuffer;
                    NativeAccessMask        |= VkAccessFlags.UniformRead;
                    NativePipelineStageMask |= VkPipelineStageFlags.VertexShader | VkPipelineStageFlags.FragmentShader;
                }

                if ((ViewFlags & BufferFlags.ShaderResource) != 0)
                {
                    createInfo.usage        |= VkBufferUsageFlags.UniformTexelBuffer;
                    NativeAccessMask        |= VkAccessFlags.ShaderRead;
                    NativePipelineStageMask |= VkPipelineStageFlags.VertexShader | VkPipelineStageFlags.FragmentShader;

                    if ((ViewFlags & BufferFlags.UnorderedAccess) != 0)
                    {
                        createInfo.usage |= VkBufferUsageFlags.StorageTexelBuffer;
                        NativeAccessMask |= VkAccessFlags.ShaderWrite;
                    }
                }
            }

            // Create buffer
            vkCreateBuffer(GraphicsDevice.NativeDevice, &createInfo, null, out NativeBuffer);

            // Allocate memory
            var memoryProperties = VkMemoryPropertyFlags.DeviceLocal;

            if (bufferDescription.Usage == GraphicsResourceUsage.Staging || Usage == GraphicsResourceUsage.Dynamic)
            {
                memoryProperties = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent;
            }

            vkGetBufferMemoryRequirements(GraphicsDevice.NativeDevice, NativeBuffer, out var memoryRequirements);

            if (bufferDescription.Usage == GraphicsResourceUsage.Staging || Usage == GraphicsResourceUsage.Dynamic)
            {
                AllocateMemory(memoryProperties, memoryRequirements); // special case that doesn't use a pool
            }
            else if (VulkanMemoryPool.TryAllocateMemoryForBuffer(createInfo.size, GraphicsDevice.NativeDevice, GraphicsDevice.NativePhysicalDevice, ref memoryRequirements, ref memoryProperties, out var memOffset, out var devmem))
            {
                NativeMemory       = devmem;
                NativeMemoryOffset = memOffset;
            }
Пример #15
0
        /// <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 VkBufferCreateInfo
            {
                sType = VkStructureType.BufferCreateInfo,
                size  = (ulong)bufferDescription.SizeInBytes,
                flags = VkBufferCreateFlags.None,
            };

            createInfo.usage |= VkBufferUsageFlags.TransferSrc;

            // We always fill using transfer
            //if (bufferDescription.Usage != GraphicsResourceUsage.Immutable)
            createInfo.usage |= VkBufferUsageFlags.TransferDst;

            if (Usage == GraphicsResourceUsage.Staging)
            {
                NativeAccessMask         = VkAccessFlags.HostRead | VkAccessFlags.HostWrite;
                NativePipelineStageMask |= VkPipelineStageFlags.Host;
            }
            else
            {
                if ((ViewFlags & BufferFlags.VertexBuffer) != 0)
                {
                    createInfo.usage        |= VkBufferUsageFlags.VertexBuffer;
                    NativeAccessMask        |= VkAccessFlags.VertexAttributeRead;
                    NativePipelineStageMask |= VkPipelineStageFlags.VertexInput;
                }

                if ((ViewFlags & BufferFlags.IndexBuffer) != 0)
                {
                    createInfo.usage        |= VkBufferUsageFlags.IndexBuffer;
                    NativeAccessMask        |= VkAccessFlags.IndexRead;
                    NativePipelineStageMask |= VkPipelineStageFlags.VertexInput;
                }

                if ((ViewFlags & BufferFlags.ConstantBuffer) != 0)
                {
                    createInfo.usage        |= VkBufferUsageFlags.UniformBuffer;
                    NativeAccessMask        |= VkAccessFlags.UniformRead;
                    NativePipelineStageMask |= VkPipelineStageFlags.VertexShader | VkPipelineStageFlags.FragmentShader;
                }

                if ((ViewFlags & BufferFlags.ShaderResource) != 0)
                {
                    createInfo.usage        |= VkBufferUsageFlags.UniformTexelBuffer;
                    NativeAccessMask        |= VkAccessFlags.ShaderRead;
                    NativePipelineStageMask |= VkPipelineStageFlags.VertexShader | VkPipelineStageFlags.FragmentShader;

                    if ((ViewFlags & BufferFlags.UnorderedAccess) != 0)
                    {
                        createInfo.usage |= VkBufferUsageFlags.StorageTexelBuffer;
                        NativeAccessMask |= VkAccessFlags.ShaderWrite;
                    }
                }
            }

            // Create buffer
            vkCreateBuffer(GraphicsDevice.NativeDevice, &createInfo, null, out NativeBuffer);

            // Allocate memory
            var memoryProperties = VkMemoryPropertyFlags.DeviceLocal;

            if (bufferDescription.Usage == GraphicsResourceUsage.Staging || Usage == GraphicsResourceUsage.Dynamic)
            {
                memoryProperties = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent;
            }

            vkGetBufferMemoryRequirements(GraphicsDevice.NativeDevice, NativeBuffer, out var memoryRequirements);

            AllocateMemory(memoryProperties, memoryRequirements);

            if (NativeMemory != VkDeviceMemory.Null)
            {
                vkBindBufferMemory(GraphicsDevice.NativeDevice, NativeBuffer, NativeMemory, 0);
            }

            if (SizeInBytes > 0)
            {
                // Begin copy command buffer
                var commandBufferAllocateInfo = new VkCommandBufferAllocateInfo
                {
                    sType              = VkStructureType.CommandBufferAllocateInfo,
                    commandPool        = GraphicsDevice.NativeCopyCommandPool,
                    commandBufferCount = 1,
                    level              = VkCommandBufferLevel.Primary
                };
                VkCommandBuffer commandBuffer;

                lock (GraphicsDevice.QueueLock)
                {
                    vkAllocateCommandBuffers(GraphicsDevice.NativeDevice, &commandBufferAllocateInfo, &commandBuffer);
                }

                var beginInfo = new VkCommandBufferBeginInfo {
                    sType = VkStructureType.CommandBufferBeginInfo, flags = VkCommandBufferUsageFlags.OneTimeSubmit
                };
                vkBeginCommandBuffer(commandBuffer, &beginInfo);

                // Copy to upload buffer
                if (dataPointer != IntPtr.Zero)
                {
                    if (Usage == GraphicsResourceUsage.Dynamic)
                    {
                        void *uploadMemory;
                        vkMapMemory(GraphicsDevice.NativeDevice, NativeMemory, 0, (ulong)SizeInBytes, VkMemoryMapFlags.None, &uploadMemory);
                        Utilities.CopyMemory((IntPtr)uploadMemory, dataPointer, SizeInBytes);
                        vkUnmapMemory(GraphicsDevice.NativeDevice, NativeMemory);
                    }
                    else
                    {
                        var      sizeInBytes = bufferDescription.SizeInBytes;
                        VkBuffer uploadResource;
                        int      uploadOffset;
                        var      uploadMemory = GraphicsDevice.AllocateUploadBuffer(sizeInBytes, out uploadResource, out uploadOffset);

                        Utilities.CopyMemory(uploadMemory, dataPointer, sizeInBytes);

                        // Barrier
                        var memoryBarrier = new VkBufferMemoryBarrier(uploadResource, VkAccessFlags.HostWrite, VkAccessFlags.TransferRead, (ulong)uploadOffset, (ulong)sizeInBytes);
                        vkCmdPipelineBarrier(commandBuffer, VkPipelineStageFlags.Host, VkPipelineStageFlags.Transfer, VkDependencyFlags.None, 0, null, 1, &memoryBarrier, 0, null);

                        // Copy
                        var bufferCopy = new VkBufferCopy
                        {
                            srcOffset = (uint)uploadOffset,
                            dstOffset = 0,
                            size      = (uint)sizeInBytes
                        };
                        vkCmdCopyBuffer(commandBuffer, uploadResource, NativeBuffer, 1, &bufferCopy);
                    }
                }
                else
                {
                    vkCmdFillBuffer(commandBuffer, NativeBuffer, 0, (uint)bufferDescription.SizeInBytes, 0);
                }

                // Barrier
                var bufferMemoryBarrier = new VkBufferMemoryBarrier(NativeBuffer, VkAccessFlags.TransferWrite, NativeAccessMask);
                vkCmdPipelineBarrier(commandBuffer, VkPipelineStageFlags.Transfer, VkPipelineStageFlags.AllCommands, VkDependencyFlags.None, 0, null, 1, &bufferMemoryBarrier, 0, null);

                // Close and submit
                vkEndCommandBuffer(commandBuffer);

                var submitInfo = new VkSubmitInfo
                {
                    sType = VkStructureType.SubmitInfo,
                    commandBufferCount = 1,
                    pCommandBuffers    = &commandBuffer,
                };

                lock (GraphicsDevice.QueueLock)
                {
                    vkQueueSubmit(GraphicsDevice.NativeCommandQueue, 1, &submitInfo, VkFence.Null);
                    vkQueueWaitIdle(GraphicsDevice.NativeCommandQueue);
                    //commandBuffer.Reset(VkCommandBufferResetFlags.None);
                    vkFreeCommandBuffers(GraphicsDevice.NativeDevice, GraphicsDevice.NativeCopyCommandPool, 1, &commandBuffer);
                }

                InitializeViews();
            }
        }
Пример #16
0
        private void InitializeFromImpl(DataBox[] dataBoxes = null)
        {
            NativeFormat = VulkanConvertExtensions.ConvertPixelFormat(ViewFormat);
            HasStencil   = IsStencilFormat(ViewFormat);

            NativeImageAspect = IsDepthStencil ? VkImageAspectFlags.Depth : VkImageAspectFlags.Color;
            if (HasStencil)
            {
                NativeImageAspect |= VkImageAspectFlags.Stencil;
            }

            // For depth-stencil formats, automatically fall back to a supported one
            if (IsDepthStencil && HasStencil)
            {
                NativeFormat = GetFallbackDepthStencilFormat(GraphicsDevice, NativeFormat);
            }

            if (Usage == GraphicsResourceUsage.Staging)
            {
                if (NativeImage != VkImage.Null)
                {
                    throw new InvalidOperationException();
                }

                if (isNotOwningResources)
                {
                    throw new InvalidOperationException();
                }

                NativeAccessMask = VkAccessFlags.HostRead | VkAccessFlags.HostWrite;

                NativePipelineStageMask = VkPipelineStageFlags.Host;

                if (ParentTexture != null)
                {
                    // Create only a view
                    NativeBuffer = ParentTexture.NativeBuffer;
                    NativeMemory = ParentTexture.NativeMemory;
                }
                else
                {
                    CreateBuffer();

                    if (dataBoxes != null && dataBoxes.Length > 0)
                    {
                        throw new InvalidOperationException();
                    }
                }
            }
            else
            {
                if (NativeImage != VkImage.Null)
                {
                    throw new InvalidOperationException();
                }

                NativeLayout =
                    IsRenderTarget ? VkImageLayout.ColorAttachmentOptimal :
                    IsDepthStencil ? VkImageLayout.DepthStencilAttachmentOptimal :
                    IsShaderResource ? VkImageLayout.ShaderReadOnlyOptimal :
                    VkImageLayout.General;

                if (NativeLayout == VkImageLayout.TransferDstOptimal)
                {
                    NativeAccessMask = VkAccessFlags.TransferRead;
                }

                if (NativeLayout == VkImageLayout.ColorAttachmentOptimal)
                {
                    NativeAccessMask = VkAccessFlags.ColorAttachmentWrite;
                }

                if (NativeLayout == VkImageLayout.DepthStencilAttachmentOptimal)
                {
                    NativeAccessMask = VkAccessFlags.DepthStencilAttachmentWrite;
                }

                if (NativeLayout == VkImageLayout.ShaderReadOnlyOptimal)
                {
                    NativeAccessMask = VkAccessFlags.ShaderRead | VkAccessFlags.InputAttachmentRead;
                }

                NativePipelineStageMask =
                    IsRenderTarget ? VkPipelineStageFlags.ColorAttachmentOutput :
                    IsDepthStencil ? VkPipelineStageFlags.ColorAttachmentOutput | VkPipelineStageFlags.EarlyFragmentTests | VkPipelineStageFlags.LateFragmentTests :
                    IsShaderResource ? VkPipelineStageFlags.VertexInput | VkPipelineStageFlags.FragmentShader :
                    VkPipelineStageFlags.None;

                if (ParentTexture != null)
                {
                    // Create only a view
                    NativeImage  = ParentTexture.NativeImage;
                    NativeMemory = ParentTexture.NativeMemory;
                }
                else
                {
                    if (!isNotOwningResources)
                    {
                        CreateImage();

                        InitializeImage(dataBoxes);
                    }
                }

                if (!isNotOwningResources)
                {
                    NativeImageView           = GetImageView(ViewType, ArraySlice, MipLevel);
                    NativeColorAttachmentView = GetColorAttachmentView(ViewType, ArraySlice, MipLevel);
                    NativeDepthStencilView    = GetDepthStencilView();
                }
            }
        }
Пример #17
0
        // Record a buffer copy operation into the command buffer
        public void RecordBufferCopy(VkCommandBuffer cmd, ResourceType?dstBufferType, ulong dataSize,
                                     VkBuffer srcBuffer, ulong srcOffset,
                                     VkBuffer dstBuffer, ulong dstOffset)
        {
            // Get pipeline barrier values
            VkPipelineStageFlags srcStage = 0, dstStage = 0;
            VkAccessFlags        srcAccess = 0, dstAccess = 0;

            if (dstBufferType.HasValue)
            {
                GetBarrierStages(dstBufferType.Value, out srcStage, out dstStage);
                GetAccessFlags(dstBufferType.Value, out srcAccess, out dstAccess);
            }

            // Start command
            VkCommandBufferBeginInfo cbbi = new(VkCommandBufferUsageFlags.OneTimeSubmit, null);

            cmd.BeginCommandBuffer(&cbbi);

            // Src barrier
            if (dstBufferType.HasValue)
            {
                VkBufferMemoryBarrier srcBarrier = new(
                    srcAccessMask : srcAccess,
                    dstAccessMask : VkAccessFlags.TransferWrite,
                    srcQueueFamilyIndex : VkConstants.QUEUE_FAMILY_IGNORED,
                    dstQueueFamilyIndex : VkConstants.QUEUE_FAMILY_IGNORED,
                    buffer : dstBuffer,
                    offset : dstOffset,
                    size : dataSize
                    );
                cmd.CmdPipelineBarrier(
                    srcStage,
                    VkPipelineStageFlags.Transfer,
                    VkDependencyFlags.ByRegion,
                    0, null,
                    1, &srcBarrier,
                    0, null
                    );
            }

            // Create copy command
            VkBufferCopy bc = new(srcOffset, dstOffset, dataSize);

            cmd.CmdCopyBuffer(srcBuffer, dstBuffer, 1, &bc);

            // Last barrier
            if (dstBufferType.HasValue)
            {
                VkBufferMemoryBarrier dstBarrier = new(
                    srcAccessMask : VkAccessFlags.TransferWrite,
                    dstAccessMask : dstAccess,
                    srcQueueFamilyIndex : VkConstants.QUEUE_FAMILY_IGNORED,
                    dstQueueFamilyIndex : VkConstants.QUEUE_FAMILY_IGNORED,
                    buffer : dstBuffer,
                    offset : dstOffset,
                    size : dataSize
                    );
                cmd.CmdPipelineBarrier(
                    VkPipelineStageFlags.Transfer,
                    dstStage,
                    VkDependencyFlags.ByRegion,
                    0, null,
                    1, &dstBarrier,
                    0, null
                    );
            }

            // End
            cmd.EndCommandBuffer().Throw("Failed to record buffer upload commands");
        }
Пример #18
0
        /// <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)
        {
            // capture vertex information for things less than ~512 verts for possible later easy batching
            if (dataPointer != IntPtr.Zero &&
                (ViewFlags == BufferFlags.VertexBuffer && bufferDescription.SizeInBytes <= CaptureVertexBuffersOfSize ||
                 ViewFlags == BufferFlags.IndexBuffer && bufferDescription.SizeInBytes <= CaptureIndexBuffersOfSize))
            {
                VertIndexData = new byte[Description.SizeInBytes];
                fixed(byte *vid = &VertIndexData[0])
                {
                    Utilities.CopyMemory((IntPtr)vid, dataPointer, VertIndexData.Length);
                }
            }
            else
            {
                VertIndexData = null;
            }

            var createInfo = new VkBufferCreateInfo
            {
                sType = VkStructureType.BufferCreateInfo,
                size  = (ulong)bufferDescription.SizeInBytes,
                flags = VkBufferCreateFlags.None,
            };

            createInfo.usage |= VkBufferUsageFlags.TransferSrc;

            // We always fill using transfer
            //if (bufferDescription.Usage != GraphicsResourceUsage.Immutable)
            createInfo.usage |= VkBufferUsageFlags.TransferDst;

            if (Usage == GraphicsResourceUsage.Staging)
            {
                NativeAccessMask         = VkAccessFlags.HostRead | VkAccessFlags.HostWrite;
                NativePipelineStageMask |= VkPipelineStageFlags.Host;
            }
            else
            {
                if ((ViewFlags & BufferFlags.VertexBuffer) != 0)
                {
                    createInfo.usage        |= VkBufferUsageFlags.VertexBuffer;
                    NativeAccessMask        |= VkAccessFlags.VertexAttributeRead;
                    NativePipelineStageMask |= VkPipelineStageFlags.VertexInput;
                }

                if ((ViewFlags & BufferFlags.IndexBuffer) != 0)
                {
                    createInfo.usage        |= VkBufferUsageFlags.IndexBuffer;
                    NativeAccessMask        |= VkAccessFlags.IndexRead;
                    NativePipelineStageMask |= VkPipelineStageFlags.VertexInput;
                }

                if ((ViewFlags & BufferFlags.ConstantBuffer) != 0)
                {
                    createInfo.usage        |= VkBufferUsageFlags.UniformBuffer;
                    NativeAccessMask        |= VkAccessFlags.UniformRead;
                    NativePipelineStageMask |= VkPipelineStageFlags.VertexShader | VkPipelineStageFlags.FragmentShader;
                }

                if ((ViewFlags & BufferFlags.ShaderResource) != 0)
                {
                    createInfo.usage        |= VkBufferUsageFlags.UniformTexelBuffer;
                    NativeAccessMask        |= VkAccessFlags.ShaderRead;
                    NativePipelineStageMask |= VkPipelineStageFlags.VertexShader | VkPipelineStageFlags.FragmentShader;

                    if ((ViewFlags & BufferFlags.UnorderedAccess) != 0)
                    {
                        createInfo.usage |= VkBufferUsageFlags.StorageTexelBuffer;
                        NativeAccessMask |= VkAccessFlags.ShaderWrite;
                    }
                }
            }

            // Create buffer
            vkCreateBuffer(GraphicsDevice.NativeDevice, &createInfo, null, out NativeBuffer);

            // Allocate memory
            var memoryProperties = VkMemoryPropertyFlags.DeviceLocal;

            if (bufferDescription.Usage == GraphicsResourceUsage.Staging || Usage == GraphicsResourceUsage.Dynamic)
            {
                memoryProperties = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent;
            }

            vkGetBufferMemoryRequirements(GraphicsDevice.NativeDevice, NativeBuffer, out var memoryRequirements);

            AllocateMemory(memoryProperties, memoryRequirements);

            if (NativeMemory != VkDeviceMemory.Null)
            {
                vkBindBufferMemory(GraphicsDevice.NativeDevice, NativeBuffer, NativeMemory, 0);
            }

            if (SizeInBytes > 0)
            {
                // Begin copy command buffer
                var commandBufferAllocateInfo = new VkCommandBufferAllocateInfo
                {
                    sType              = VkStructureType.CommandBufferAllocateInfo,
                    commandPool        = GraphicsDevice.NativeCopyCommandPool,
                    commandBufferCount = 1,
                    level              = VkCommandBufferLevel.Primary
                };
                VkCommandBuffer commandBuffer;

                lock (BufferLocker)
                {
                    vkAllocateCommandBuffers(GraphicsDevice.NativeDevice, &commandBufferAllocateInfo, &commandBuffer);
                }

                var beginInfo = new VkCommandBufferBeginInfo {
                    sType = VkStructureType.CommandBufferBeginInfo, flags = VkCommandBufferUsageFlags.OneTimeSubmit
                };
                vkBeginCommandBuffer(commandBuffer, &beginInfo);

                GraphicsDevice.UploadBuffer?uploadBuffer = null;

                // Copy to upload buffer
                if (dataPointer != IntPtr.Zero)
                {
                    if (Usage == GraphicsResourceUsage.Dynamic)
                    {
                        void *uploadMemory;
                        vkMapMemory(GraphicsDevice.NativeDevice, NativeMemory, 0, (ulong)SizeInBytes, VkMemoryMapFlags.None, &uploadMemory);
                        Utilities.CopyMemory((IntPtr)uploadMemory, dataPointer, SizeInBytes);
                        lock (BufferLocker)
                        {
                            vkUnmapMemory(GraphicsDevice.NativeDevice, NativeMemory);
                        }
                    }
                    else
                    {
                        var sizeInBytes = bufferDescription.SizeInBytes;
                        int uploadOffset;
                        GraphicsDevice.AllocateOneTimeUploadBuffer(sizeInBytes, out var upBuf);
                        uploadBuffer = upBuf;

                        Utilities.CopyMemory(uploadBuffer.Value.address, dataPointer, sizeInBytes);

                        // Barrier
                        var memoryBarrier = new VkBufferMemoryBarrier(uploadBuffer.Value.buffer, VkAccessFlags.HostWrite, VkAccessFlags.TransferRead, 0, (ulong)sizeInBytes);
                        vkCmdPipelineBarrier(commandBuffer, VkPipelineStageFlags.Host, VkPipelineStageFlags.Transfer, VkDependencyFlags.None, 0, null, 1, &memoryBarrier, 0, null);

                        // Copy
                        var bufferCopy = new VkBufferCopy
                        {
                            srcOffset = 0,
                            dstOffset = 0,
                            size      = (uint)sizeInBytes
                        };

                        vkCmdCopyBuffer(commandBuffer, uploadBuffer.Value.buffer, NativeBuffer, 1, &bufferCopy);
                    }
                }
                else
                {
                    vkCmdFillBuffer(commandBuffer, NativeBuffer, 0, (uint)bufferDescription.SizeInBytes, 0);
                }

                // Barrier
                var bufferMemoryBarrier = new VkBufferMemoryBarrier(NativeBuffer, VkAccessFlags.TransferWrite, NativeAccessMask);
                vkCmdPipelineBarrier(commandBuffer, VkPipelineStageFlags.Transfer, VkPipelineStageFlags.AllCommands, VkDependencyFlags.None, 0, null, 1, &bufferMemoryBarrier, 0, null);

                var submitInfo = new VkSubmitInfo
                {
                    sType = VkStructureType.SubmitInfo,
                    commandBufferCount = 1,
                    pCommandBuffers    = &commandBuffer,
                };

                var fenceCreateInfo = new VkFenceCreateInfo {
                    sType = VkStructureType.FenceCreateInfo
                };
                vkCreateFence(GraphicsDevice.NativeDevice, &fenceCreateInfo, null, out var fence);

                // Close and submit
                vkEndCommandBuffer(commandBuffer);

                using (GraphicsDevice.QueueLock.ReadLock())
                {
                    vkQueueSubmit(GraphicsDevice.NativeCommandQueue, 1, &submitInfo, fence);
                }

                vkWaitForFences(GraphicsDevice.NativeDevice, 1, &fence, true, ulong.MaxValue);

                vkFreeCommandBuffers(GraphicsDevice.NativeDevice, GraphicsDevice.NativeCopyCommandPool, 1, &commandBuffer);
                vkDestroyFence(GraphicsDevice.NativeDevice, fence, null);

                if (uploadBuffer.HasValue)
                {
                    GraphicsDevice.FreeOneTimeUploadBuffer(uploadBuffer.Value);
                }

                InitializeViews();
            }
        }
Пример #19
0
        internal void Recreate()
        {
            VkBufferCreateInfo buffer_info = new VkBufferCreateInfo()
            {
                sType = VkStructureType.BufferCreateInfo,
                pNext = null,
                size  = (ulong)BufferDescription.SizeInBytes,
                flags = VkBufferCreateFlags.None,
                //sharingMode = VkSharingMode.Exclusive
            };

            buffer_info.usage |= VkBufferUsageFlags.TransferSrc;


            if (Usage == ResourceUsage.GPU_Only)
            {
                access = VkAccessFlags.HostRead | VkAccessFlags.HostWrite;
            }

            else
            {
                if ((Flags /*.HasFlag()*/ & BufferFlags.VertexBuffer) != 0)
                {
                    buffer_info.usage |= VkBufferUsageFlags.VertexBuffer;
                    access            |= VkAccessFlags.VertexAttributeRead;
                }

                if ((Flags & BufferFlags.IndexBuffer) is not 0)
                {
                    buffer_info.usage |= VkBufferUsageFlags.IndexBuffer;
                    access            |= VkAccessFlags.IndexRead;
                }

                if ((Flags & BufferFlags.ConstantBuffer) is not 0)
                {
                    buffer_info.usage |= VkBufferUsageFlags.UniformBuffer;
                    access            |= VkAccessFlags.UniformRead;
                }

                if ((Flags & BufferFlags.ShaderResource) is not 0)
                {
                    buffer_info.usage |= VkBufferUsageFlags.UniformTexelBuffer;
                    access            |= VkAccessFlags.ShaderRead;
                }

                if ((Flags & BufferFlags.UnorderedAccess) is not 0)
                {
                    buffer_info.usage |= VkBufferUsageFlags.StorageTexelBuffer;
                    access            |= VkAccessFlags.ShaderWrite;
                }


                if ((Flags & BufferFlags.StructuredBuffer) is not 0)
                {
                    buffer_info.usage |= VkBufferUsageFlags.StorageBuffer;
                    access            |= VkAccessFlags.ShaderWrite;
                }
            }

            vkCreateBuffer(NativeDevice.handle, &buffer_info, null, out handle);



            // Allocate memory
            var memoryProperties = VkMemoryPropertyFlags.DeviceLocal;

            if (BufferDescription.Usage is ResourceUsage.GPU_Only || Usage == ResourceUsage.CPU_To_GPU)
            {
                memoryProperties = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent;
            }
            if (Usage == ResourceUsage.GPU_To_CPU)
            {
                memoryProperties = VkMemoryPropertyFlags.HostVisible;
            }


            vkGetBufferMemoryRequirements(NativeDevice.handle, handle, out VkMemoryRequirements memReqs);

            VkMemoryAllocateInfo MemoryAlloc_info = new VkMemoryAllocateInfo()
            {
                sType           = VkStructureType.MemoryAllocateInfo,
                pNext           = null,
                allocationSize  = memReqs.size,
                memoryTypeIndex = NativeDevice.get_memory_type(memReqs.memoryTypeBits, memoryProperties),
            };


            VkDeviceMemory _memory;

            vkAllocateMemory(NativeDevice.handle, &MemoryAlloc_info, null, out _memory);
            memory = _memory;

            size = memReqs.size;
            vkBindBufferMemory(NativeDevice.handle, handle, memory, 0);
        }