コード例 #1
0
        private unsafe void ReleaseDevice()
        {
            EmptyTexelBuffer.Dispose();
            EmptyTexelBuffer = null;

            // Wait for all queues to be idle
            nativeDevice.WaitIdle();

            // Destroy all remaining fences
            GetCompletedValue();

            // Mark upload buffer for destruction
            if (nativeUploadBuffer != SharpVulkan.Buffer.Null)
            {
                NativeDevice.UnmapMemory(nativeUploadBufferMemory);
                nativeResourceCollector.Add(lastCompletedFence, nativeUploadBuffer);
                nativeResourceCollector.Add(lastCompletedFence, nativeUploadBufferMemory);

                nativeUploadBuffer       = SharpVulkan.Buffer.Null;
                nativeUploadBufferMemory = DeviceMemory.Null;
            }

            // Release fenced resources
            nativeResourceCollector.Dispose();
            DescriptorPools.Dispose();

            nativeDevice.DestroyCommandPool(NativeCopyCommandPool);
            nativeDevice.Destroy();
        }
コード例 #2
0
        private unsafe void CreateBuffer()
        {
            var createInfo = new BufferCreateInfo
            {
                StructureType = StructureType.BufferCreateInfo,
                Flags         = BufferCreateFlags.None
            };

            for (int i = 0; i < MipLevels; i++)
            {
                var mipmap = GetMipMapDescription(i);
                createInfo.Size += (uint)(mipmap.DepthStride * mipmap.Depth * ArraySize);
            }

            createInfo.Usage = BufferUsageFlags.TransferSource | BufferUsageFlags.TransferDestination;

            // Create buffer
            NativeBuffer = GraphicsDevice.NativeDevice.CreateBuffer(ref createInfo);

            // Allocate and bind memory
            MemoryRequirements memoryRequirements;

            GraphicsDevice.NativeDevice.GetBufferMemoryRequirements(NativeBuffer, out memoryRequirements);

            AllocateMemory(MemoryPropertyFlags.HostVisible | MemoryPropertyFlags.HostCoherent, memoryRequirements);

            if (NativeMemory != DeviceMemory.Null)
            {
                GraphicsDevice.NativeDevice.BindBufferMemory(NativeBuffer, NativeMemory, 0);
            }
        }
コード例 #3
0
        /// <inheritdoc/>
        protected internal override void OnDestroyed()
        {
            if (ParentTexture != null || isNotOwningResources)
            {
                NativeImage  = SharpVulkan.Image.Null;
                NativeMemory = DeviceMemory.Null;
            }

            if (!isNotOwningResources)
            {
                if (NativeMemory != DeviceMemory.Null)
                {
                    GraphicsDevice.Collect(NativeMemory);
                    NativeMemory = DeviceMemory.Null;
                    SharedHandle = IntPtr.Zero;
                }

                if (NativeImage != SharpVulkan.Image.Null)
                {
                    GraphicsDevice.Collect(NativeImage);
                    NativeImage = SharpVulkan.Image.Null;
                }

                if (NativeBuffer != SharpVulkan.Buffer.Null)
                {
                    GraphicsDevice.Collect(NativeBuffer);
                    NativeBuffer = SharpVulkan.Buffer.Null;
                }

                if (NativeImageView != ImageView.Null)
                {
                    GraphicsDevice.Collect(NativeImageView);
                    NativeImageView = ImageView.Null;
                }

                if (NativeColorAttachmentView != ImageView.Null)
                {
                    GraphicsDevice.Collect(NativeColorAttachmentView);
                    NativeColorAttachmentView = ImageView.Null;
                }

                if (NativeDepthStencilView != ImageView.Null)
                {
                    GraphicsDevice.Collect(NativeDepthStencilView);
                    NativeDepthStencilView = ImageView.Null;
                }
            }

            base.OnDestroyed();
        }
コード例 #4
0
        internal unsafe IntPtr AllocateUploadBuffer(int size, out SharpVulkan.Buffer resource, out int offset)
        {
            // TODO D3D12 thread safety, should we simply use locks?
            if (nativeUploadBuffer == SharpVulkan.Buffer.Null || nativeUploadBufferOffset + size > nativeUploadBufferSize)
            {
                if (nativeUploadBuffer != SharpVulkan.Buffer.Null)
                {
                    NativeDevice.UnmapMemory(nativeUploadBufferMemory);
                    Collect(nativeUploadBuffer);
                    Collect(nativeUploadBufferMemory);
                }

                // Allocate new buffer
                // TODO D3D12 recycle old ones (using fences to know when GPU is done with them)
                // TODO D3D12 ResourceStates.CopySource not working?
                nativeUploadBufferSize = Math.Max(4 * 1024 * 1024, size);

                var bufferCreateInfo = new BufferCreateInfo
                {
                    StructureType = StructureType.BufferCreateInfo,
                    Size          = (ulong)nativeUploadBufferSize,
                    Flags         = BufferCreateFlags.None,
                    Usage         = BufferUsageFlags.TransferSource,
                };
                nativeUploadBuffer = NativeDevice.CreateBuffer(ref bufferCreateInfo);
                AllocateMemory(MemoryPropertyFlags.HostVisible | MemoryPropertyFlags.HostCoherent);

                nativeUploadBufferStart  = NativeDevice.MapMemory(nativeUploadBufferMemory, 0, (ulong)nativeUploadBufferSize, MemoryMapFlags.None);
                nativeUploadBufferOffset = 0;
            }

            // Bump allocate
            resource = nativeUploadBuffer;
            offset   = nativeUploadBufferOffset;
            nativeUploadBufferOffset += size;
            return(nativeUploadBufferStart + offset);
        }
コード例 #5
0
        /// <inheritdoc/>
        protected internal override void OnDestroyed()
        {
            GraphicsDevice.BuffersMemory -= SizeInBytes / (float)0x100000;

            if (NativeBufferView != BufferView.Null)
            {
                GraphicsDevice.Collect(NativeBufferView);
                NativeBufferView = BufferView.Null;
            }

            if (NativeBuffer != SharpVulkan.Buffer.Null)
            {
                GraphicsDevice.Collect(NativeBuffer);
                NativeBuffer = SharpVulkan.Buffer.Null;
            }

            if (NativeMemory != DeviceMemory.Null)
            {
                GraphicsDevice.Collect(NativeMemory);
                NativeMemory = DeviceMemory.Null;
            }

            base.OnDestroyed();
        }
コード例 #6
0
        /// <inheritdoc/>
        protected internal override void OnDestroyed()
        {
            GraphicsDevice.RegisterBufferMemoryUsage(-SizeInBytes);

            if (NativeBufferView != BufferView.Null)
            {
                GraphicsDevice.Collect(NativeBufferView);
                NativeBufferView = BufferView.Null;
            }

            if (NativeBuffer != SharpVulkan.Buffer.Null)
            {
                GraphicsDevice.Collect(NativeBuffer);
                NativeBuffer = SharpVulkan.Buffer.Null;
            }

            if (NativeMemory != DeviceMemory.Null)
            {
                GraphicsDevice.Collect(NativeMemory);
                NativeMemory = DeviceMemory.Null;
            }

            base.OnDestroyed();
        }
コード例 #7
0
        /// <inheritdoc/>
        protected internal override void OnDestroyed()
        {
            GraphicsDevice.BuffersMemory -= SizeInBytes / (float)0x100000;

            if (NativeBufferView != BufferView.Null)
            {
                GraphicsDevice.Collect(NativeBufferView);
                NativeBufferView = BufferView.Null;
            }

            if (NativeBuffer != SharpVulkan.Buffer.Null)
            {
                GraphicsDevice.Collect(NativeBuffer);
                NativeBuffer = SharpVulkan.Buffer.Null;
            }

            if (NativeMemory != DeviceMemory.Null)
            {
                GraphicsDevice.Collect(NativeMemory);
                NativeMemory = DeviceMemory.Null;
            }

            base.OnDestroyed();
        }
コード例 #8
0
        private void InitializeFromImpl(DataBox[] dataBoxes = null)
        {
            NativeFormat = VulkanConvertExtensions.ConvertPixelFormat(ViewFormat);
            HasStencil   = IsStencilFormat(ViewFormat);

            NativeImageAspect = IsDepthStencil ? ImageAspectFlags.Depth : ImageAspectFlags.Color;
            if (HasStencil)
            {
                NativeImageAspect |= ImageAspectFlags.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 != SharpVulkan.Image.Null)
                {
                    throw new InvalidOperationException();
                }

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

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

                    if (dataBoxes != null)
                    {
                        throw new InvalidOperationException();
                    }
                }
            }
            else
            {
                if (NativeImage != SharpVulkan.Image.Null)
                {
                    throw new InvalidOperationException();
                }

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

                if (NativeLayout == ImageLayout.TransferDestinationOptimal)
                {
                    NativeAccessMask = AccessFlags.TransferRead;
                }

                if (NativeLayout == ImageLayout.ColorAttachmentOptimal)
                {
                    NativeAccessMask = AccessFlags.ColorAttachmentWrite;
                }

                if (NativeLayout == ImageLayout.DepthStencilAttachmentOptimal)
                {
                    NativeAccessMask = AccessFlags.DepthStencilAttachmentWrite;
                }

                if (NativeLayout == ImageLayout.ShaderReadOnlyOptimal)
                {
                    NativeAccessMask = AccessFlags.ShaderRead | AccessFlags.InputAttachmentRead;
                }

                NativePipelineStageMask =
                    IsRenderTarget ? PipelineStageFlags.ColorAttachmentOutput :
                    IsDepthStencil ? PipelineStageFlags.ColorAttachmentOutput | PipelineStageFlags.EarlyFragmentTests | PipelineStageFlags.LateFragmentTests :
                    IsShaderResource ? PipelineStageFlags.VertexInput | PipelineStageFlags.FragmentShader :
                    PipelineStageFlags.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();
                }
            }
        }
コード例 #9
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 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();
            }
        }
コード例 #10
0
        private void InitializeFromImpl(DataBox[] dataBoxes = null)
        {
            NativeFormat = VulkanConvertExtensions.ConvertPixelFormat(ViewFormat);
            HasStencil = IsStencilFormat(ViewFormat);
            
            NativeImageAspect = IsDepthStencil ? ImageAspectFlags.Depth : ImageAspectFlags.Color;
            if (HasStencil)
                NativeImageAspect |= ImageAspectFlags.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 != SharpVulkan.Image.Null)
                    throw new InvalidOperationException();

                if (isNotOwningResources)
                    throw new InvalidOperationException();

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

                    if (dataBoxes != null)
                        throw new InvalidOperationException();
                }
            }
            else
            {
                if (NativeImage != SharpVulkan.Image.Null)
                    throw new InvalidOperationException();

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

                if (NativeLayout == ImageLayout.TransferDestinationOptimal)
                    NativeAccessMask = AccessFlags.TransferRead;

                if (NativeLayout == ImageLayout.ColorAttachmentOptimal)
                    NativeAccessMask = AccessFlags.ColorAttachmentWrite;

                if (NativeLayout == ImageLayout.DepthStencilAttachmentOptimal)
                    NativeAccessMask = AccessFlags.DepthStencilAttachmentWrite;

                if (NativeLayout == ImageLayout.ShaderReadOnlyOptimal)
                    NativeAccessMask = AccessFlags.ShaderRead | AccessFlags.InputAttachmentRead;

                NativePipelineStageMask =
                    IsRenderTarget ? PipelineStageFlags.ColorAttachmentOutput :
                    IsDepthStencil ? PipelineStageFlags.ColorAttachmentOutput | PipelineStageFlags.EarlyFragmentTests | PipelineStageFlags.LateFragmentTests :
                    IsShaderResource ? PipelineStageFlags.VertexInput | PipelineStageFlags.FragmentShader :
                    PipelineStageFlags.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();
                }
            }
        }
コード例 #11
0
        /// <inheritdoc/>
        protected internal override void OnDestroyed()
        {
            if (ParentTexture != null || isNotOwningResources)
            {
                NativeImage = SharpVulkan.Image.Null;
                NativeMemory = DeviceMemory.Null;
            }

            if (!isNotOwningResources)
            {
                if (NativeMemory != DeviceMemory.Null)
                {
                    GraphicsDevice.Collect(NativeMemory);
                    NativeMemory = DeviceMemory.Null;
                }

                if (NativeImage != SharpVulkan.Image.Null)
                {
                    GraphicsDevice.Collect(NativeImage);
                    NativeImage = SharpVulkan.Image.Null;
                }

                if (NativeBuffer != SharpVulkan.Buffer.Null)
                {
                    GraphicsDevice.Collect(NativeBuffer);
                    NativeBuffer = SharpVulkan.Buffer.Null;
                }

                if (NativeImageView != ImageView.Null)
                {
                    GraphicsDevice.Collect(NativeImageView);
                    NativeImageView = ImageView.Null;
                }

                if (NativeColorAttachmentView != ImageView.Null)
                {
                    GraphicsDevice.Collect(NativeColorAttachmentView);
                    NativeColorAttachmentView = ImageView.Null;
                }

                if (NativeDepthStencilView != ImageView.Null)
                {
                    GraphicsDevice.Collect(NativeDepthStencilView);
                    NativeDepthStencilView = ImageView.Null;
                }
            }

            base.OnDestroyed();
        }
コード例 #12
0
        private unsafe void CreateBuffer()
        {
            var createInfo = new BufferCreateInfo
            {
                StructureType = StructureType.BufferCreateInfo,
                Flags = BufferCreateFlags.None
            };

            for (int i = 0; i < MipLevels; i++)
            { 
                var mipmap = GetMipMapDescription(i);
                createInfo.Size += (uint)(mipmap.DepthStride * mipmap.Depth * ArraySize);
            }

            createInfo.Usage = BufferUsageFlags.TransferSource | BufferUsageFlags.TransferDestination;

            // Create buffer
            NativeBuffer = GraphicsDevice.NativeDevice.CreateBuffer(ref createInfo);

            // Allocate and bind memory
            MemoryRequirements memoryRequirements;
            GraphicsDevice.NativeDevice.GetBufferMemoryRequirements(NativeBuffer, out memoryRequirements);

            AllocateMemory(MemoryPropertyFlags.HostVisible | MemoryPropertyFlags.HostCoherent, memoryRequirements);

            if (NativeMemory != DeviceMemory.Null)
            {
                GraphicsDevice.NativeDevice.BindBufferMemory(NativeBuffer, NativeMemory, 0);
            }
        }
コード例 #13
0
 public BufferInfo(long fenceValue, SharpVulkan.Buffer buffer, DeviceMemory memory)
 {
     FenceValue = fenceValue;
     Buffer     = buffer;
     Memory     = memory;
 }
コード例 #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)
        {
            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();
            }
        }