public void Free(VkMemoryBlock block)
            {
                _freeBlocks.Add(block);
#if DEBUG
                RemoveAllocatedBlock(block);
#endif
            }
Exemple #2
0
        public VkDeviceBuffer(
            VkRenderContext rc,
            ulong size,
            VkBufferUsageFlags usage,
            VkMemoryPropertyFlags memoryProperties,
            bool dynamic)
        {
            _rc               = rc;
            usage            |= VkBufferUsageFlags.TransferSrc;
            _usage            = usage;
            _memoryProperties = memoryProperties;
            _isDynamic        = dynamic;

            VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New();

            bufferCI.size  = size;
            bufferCI.usage = _usage;
            VkResult result = vkCreateBuffer(rc.Device, ref bufferCI, null, out _buffer);

            CheckResult(result);

            vkGetBufferMemoryRequirements(rc.Device, _buffer, out _bufferMemoryRequirements);
            _bufferCapacity = _bufferMemoryRequirements.size;
            uint          memoryType  = FindMemoryType(rc.PhysicalDevice, _bufferMemoryRequirements.memoryTypeBits, memoryProperties);
            VkMemoryBlock memoryToken = rc.MemoryManager.Allocate(
                memoryType,
                _bufferMemoryRequirements.size,
                _bufferMemoryRequirements.alignment);

            _memory = memoryToken;
            vkBindBufferMemory(rc.Device, _buffer, _memory.DeviceMemory, _memory.Offset);
        }
            private void CheckAllocatedBlock(VkMemoryBlock block)
            {
                foreach (VkMemoryBlock oldBlock in _allocatedBlocks)
                {
                    Debug.Assert(!BlocksOverlap(block, oldBlock), "Allocated blocks have overlapped.");
                }

                _allocatedBlocks.Add(block);
            }
 public void Free(VkMemoryBlock block)
 {
     foreach (ChunkAllocator chunk in _allocators)
     {
         if (chunk.Memory == block.DeviceMemory)
         {
             chunk.Free(block);
         }
     }
 }
            public bool Allocate(ulong size, ulong alignment, out VkMemoryBlock block)
            {
                checked
                {
                    for (int i = 0; i < _freeBlocks.Count; i++)
                    {
                        VkMemoryBlock freeBlock        = _freeBlocks[i];
                        ulong         alignedBlockSize = freeBlock.Size;
                        if (freeBlock.Offset % alignment != 0)
                        {
                            ulong alignmentCorrection = (alignment - freeBlock.Offset % alignment);
                            if (alignedBlockSize <= alignmentCorrection)
                            {
                                continue;
                            }
                            alignedBlockSize -= alignmentCorrection;
                        }

                        if (alignedBlockSize >= size) // Valid match -- split it and return.
                        {
                            _freeBlocks.Remove(freeBlock);

                            freeBlock.Size = alignedBlockSize;
                            if ((freeBlock.Offset % alignment) != 0)
                            {
                                freeBlock.Offset += alignment - (freeBlock.Offset % alignment);
                            }

                            block = freeBlock;

                            if (alignedBlockSize != size)
                            {
                                VkMemoryBlock splitBlock = new VkMemoryBlock(
                                    freeBlock.DeviceMemory,
                                    freeBlock.Offset + size,
                                    freeBlock.Size - size,
                                    _memoryTypeIndex);
                                _freeBlocks.Add(splitBlock);
                                block      = freeBlock;
                                block.Size = size;
                            }

#if DEBUG
                            CheckAllocatedBlock(block);
#endif
                            _totalAllocatedBytes += alignedBlockSize;
                            return(true);
                        }
                    }

                    block = null;
                    return(false);
                }
            }
            private bool BlocksOverlap(VkMemoryBlock first, VkMemoryBlock second)
            {
                ulong firstStart  = first.Offset;
                ulong firstEnd    = first.Offset + first.Size;
                ulong secondStart = second.Offset;
                ulong secondEnd   = second.Offset + second.Size;

                return(firstStart <= secondStart && firstEnd > secondStart ||
                       firstStart >= secondStart && firstEnd <= secondEnd ||
                       firstStart < secondEnd && firstEnd >= secondEnd ||
                       firstStart <= secondStart && firstEnd >= secondEnd);
            }
            public bool Allocate(ulong size, ulong alignment, out VkMemoryBlock block)
            {
                foreach (ChunkAllocator allocator in _allocators)
                {
                    if (allocator.Allocate(size, alignment, out block))
                    {
                        return(true);
                    }
                }

                ChunkAllocator newAllocator = new ChunkAllocator(_device, _memoryTypeIndex);

                _allocators.Add(newAllocator);
                return(newAllocator.Allocate(size, alignment, out block));
            }
            public ChunkAllocator(VkDevice device, uint memoryTypeIndex)
            {
                _device          = device;
                _memoryTypeIndex = memoryTypeIndex;

                VkMemoryAllocateInfo memoryAI = VkMemoryAllocateInfo.New();

                memoryAI.allocationSize  = _totalMemorySize;
                memoryAI.memoryTypeIndex = _memoryTypeIndex;
                VkResult result = vkAllocateMemory(_device, ref memoryAI, null, out _memory);

                CheckResult(result);

                VkMemoryBlock initialBlock = new VkMemoryBlock(_memory, 0, _totalMemorySize, _memoryTypeIndex);

                _freeBlocks.Add(initialBlock);
            }
        public static void CreateImage(
            VkDevice device,
            VkPhysicalDevice physicalDevice,
            VkDeviceMemoryManager memoryManager,
            uint width,
            uint height,
            uint arrayLayers,
            VkFormat format,
            VkImageTiling tiling,
            VkImageUsageFlags usage,
            VkMemoryPropertyFlags properties,
            out VkImage image,
            out VkMemoryBlock memory)
        {
            VkImageCreateInfo imageCI = VkImageCreateInfo.New();

            imageCI.imageType     = VkImageType.Image2D;
            imageCI.extent.width  = width;
            imageCI.extent.height = height;
            imageCI.extent.depth  = 1;
            imageCI.mipLevels     = 1;
            imageCI.arrayLayers   = arrayLayers;
            imageCI.format        = format;
            imageCI.tiling        = tiling;
            imageCI.initialLayout = VkImageLayout.Preinitialized;
            imageCI.usage         = usage;
            imageCI.sharingMode   = VkSharingMode.Exclusive;
            imageCI.samples       = VkSampleCountFlags.Count1;

            VkResult result = vkCreateImage(device, ref imageCI, null, out image);

            CheckResult(result);

            vkGetImageMemoryRequirements(device, image, out VkMemoryRequirements memRequirements);
            VkMemoryBlock memoryToken = memoryManager.Allocate(
                FindMemoryType(physicalDevice, memRequirements.memoryTypeBits, properties),
                memRequirements.size,
                memRequirements.alignment);

            memory = memoryToken;
            result = vkBindImageMemory(device, image, memory.DeviceMemory, memory.Offset);
            CheckResult(result);
        }
Exemple #10
0
        private void EnsureBufferSize(int dataSizeInBytes)
        {
            if (_bufferCapacity < (ulong)dataSizeInBytes)
            {
                VkBufferCreateInfo newBufferCI = VkBufferCreateInfo.New();
                newBufferCI.size  = (ulong)dataSizeInBytes;
                newBufferCI.usage = _usage | VkBufferUsageFlags.TransferDst;
                VkResult result = vkCreateBuffer(_rc.Device, ref newBufferCI, null, out VkBuffer newBuffer);
                CheckResult(result);
                vkGetBufferMemoryRequirements(_rc.Device, newBuffer, out VkMemoryRequirements newMemoryRequirements);

                uint          memoryType = FindMemoryType(_rc.PhysicalDevice, newMemoryRequirements.memoryTypeBits, _memoryProperties);
                VkMemoryBlock newMemory  = _rc.MemoryManager.Allocate(
                    memoryType,
                    newMemoryRequirements.size,
                    newMemoryRequirements.alignment);

                result = vkBindBufferMemory(_rc.Device, newBuffer, newMemory.DeviceMemory, newMemory.Offset);
                CheckResult(result);

                if (_bufferDataSize > 0)
                {
                    VkCommandBuffer copyCmd = _rc.BeginOneTimeCommands();
                    VkBufferCopy    region  = new VkBufferCopy();
                    region.size = _bufferDataSize;
                    vkCmdCopyBuffer(copyCmd, _buffer, newBuffer, 1, ref region);
                    _rc.EndOneTimeCommands(copyCmd, VkFence.Null);
                }

                _rc.MemoryManager.Free(_memory);
                vkDestroyBuffer(_rc.Device, _buffer, null);

                _buffer         = newBuffer;
                _memory         = newMemory;
                _bufferCapacity = (ulong)dataSizeInBytes;
            }
        }
        public VkCubemapTexture(
            VkDevice device,
            VkPhysicalDevice physicalDevice,
            VkDeviceMemoryManager memoryManager,
            VkRenderContext rc,
            IntPtr pixelsFront,
            IntPtr pixelsBack,
            IntPtr pixelsLeft,
            IntPtr pixelsRight,
            IntPtr pixelsTop,
            IntPtr pixelsBottom,
            int width,
            int height,
            PixelFormat format)
        {
            _device         = device;
            _physicalDevice = physicalDevice;
            _rc             = rc;
            _memoryManager  = memoryManager;

            Width     = width;
            Height    = height;
            _format   = format;
            _vkFormat = VkFormats.VeldridToVkPixelFormat(_format);

            vkGetPhysicalDeviceImageFormatProperties(
                _physicalDevice,
                _vkFormat,
                VkImageType.Image2D,
                VkImageTiling.Linear,
                VkImageUsageFlags.Sampled,
                VkImageCreateFlags.CubeCompatible,
                out VkImageFormatProperties linearProps);

            vkGetPhysicalDeviceImageFormatProperties(
                _physicalDevice,
                _vkFormat,
                VkImageType.Image2D,
                VkImageTiling.Optimal,
                VkImageUsageFlags.Sampled,
                VkImageCreateFlags.CubeCompatible,
                out VkImageFormatProperties optimalProps);

            bool useSingleStagingBuffer = linearProps.maxArrayLayers >= 6;

            VkImageCreateInfo imageCI = VkImageCreateInfo.New();

            imageCI.imageType     = VkImageType.Image2D;
            imageCI.flags         = VkImageCreateFlags.CubeCompatible;
            imageCI.format        = _vkFormat;
            imageCI.extent.width  = (uint)width;
            imageCI.extent.height = (uint)height;
            imageCI.extent.depth  = 1;
            imageCI.mipLevels     = 1;
            imageCI.arrayLayers   = 6;
            imageCI.samples       = VkSampleCountFlags.Count1;
            imageCI.tiling        = useSingleStagingBuffer ? VkImageTiling.Linear : VkImageTiling.Optimal;
            imageCI.usage         = VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferDst;
            imageCI.initialLayout = VkImageLayout.Preinitialized;

            VkResult result = vkCreateImage(_device, ref imageCI, null, out _image);

            CheckResult(result);

            vkGetImageMemoryRequirements(_device, _image, out VkMemoryRequirements memReqs);
            uint memoryType = FindMemoryType(_physicalDevice, memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal);

            _memory = memoryManager.Allocate(memoryType, memReqs.size, memReqs.alignment);
            vkBindImageMemory(_device, _image, _memory.DeviceMemory, _memory.Offset);

            if (useSingleStagingBuffer)
            {
                CopyDataSingleStagingBuffer(pixelsFront, pixelsBack, pixelsLeft, pixelsRight, pixelsTop, pixelsBottom, memReqs);
            }
            else
            {
                CopyDataMultiImage(pixelsFront, pixelsBack, pixelsLeft, pixelsRight, pixelsTop, pixelsBottom);
            }

            TransitionImageLayout(_image, (uint)MipLevels, 0, 6, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal);
            _imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
        }
        private void CopyDataSingleStagingBuffer(IntPtr pixelsFront, IntPtr pixelsBack, IntPtr pixelsLeft, IntPtr pixelsRight, IntPtr pixelsTop, IntPtr pixelsBottom, VkMemoryRequirements memReqs)
        {
            VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New();

            bufferCI.size  = memReqs.size;
            bufferCI.usage = VkBufferUsageFlags.TransferSrc;
            vkCreateBuffer(_device, ref bufferCI, null, out VkBuffer stagingBuffer);

            vkGetBufferMemoryRequirements(_device, stagingBuffer, out VkMemoryRequirements stagingMemReqs);
            VkMemoryBlock stagingMemory = _memoryManager.Allocate(
                FindMemoryType(
                    _physicalDevice,
                    stagingMemReqs.memoryTypeBits,
                    VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent),
                stagingMemReqs.size,
                stagingMemReqs.alignment);

            VkResult result = vkBindBufferMemory(_device, stagingBuffer, stagingMemory.DeviceMemory, 0);

            CheckResult(result);

            StackList <IntPtr, Size6IntPtr> faces = new StackList <IntPtr, Size6IntPtr>();

            faces.Add(pixelsRight);
            faces.Add(pixelsLeft);
            faces.Add(pixelsTop);
            faces.Add(pixelsBottom);
            faces.Add(pixelsBack);
            faces.Add(pixelsFront);

            for (uint i = 0; i < 6; i++)
            {
                VkImageSubresource subresource;
                subresource.aspectMask = VkImageAspectFlags.Color;
                subresource.arrayLayer = i;
                subresource.mipLevel   = 0;
                vkGetImageSubresourceLayout(_device, _image, ref subresource, out VkSubresourceLayout faceLayout);
                void *mappedPtr;
                result = vkMapMemory(_device, stagingMemory.DeviceMemory, faceLayout.offset, faceLayout.size, 0, &mappedPtr);
                CheckResult(result);
                Buffer.MemoryCopy((void *)faces[i], mappedPtr, faceLayout.size, faceLayout.size);
                vkUnmapMemory(_device, stagingMemory.DeviceMemory);
            }

            StackList <VkBufferImageCopy, Size512Bytes> copyRegions = new StackList <VkBufferImageCopy, Size512Bytes>();

            for (uint i = 0; i < 6; i++)
            {
                VkImageSubresource subres;
                subres.aspectMask = VkImageAspectFlags.Color;
                subres.mipLevel   = 0;
                subres.arrayLayer = i;
                vkGetImageSubresourceLayout(_device, _image, ref subres, out VkSubresourceLayout layout);

                VkBufferImageCopy copyRegion;
                copyRegion.bufferOffset       = layout.offset;
                copyRegion.bufferImageHeight  = 0;
                copyRegion.bufferRowLength    = 0;
                copyRegion.imageExtent.width  = (uint)Width;
                copyRegion.imageExtent.height = (uint)Height;
                copyRegion.imageExtent.depth  = 1;
                copyRegion.imageOffset.x      = 0;
                copyRegion.imageOffset.y      = 0;
                copyRegion.imageOffset.z      = 0;
                copyRegion.imageSubresource.baseArrayLayer = i;
                copyRegion.imageSubresource.aspectMask     = VkImageAspectFlags.Color;
                copyRegion.imageSubresource.layerCount     = 1;
                copyRegion.imageSubresource.mipLevel       = 0;

                copyRegions.Add(copyRegion);
            }

            VkFenceCreateInfo fenceCI = VkFenceCreateInfo.New();

            result = vkCreateFence(_device, ref fenceCI, null, out VkFence copyFence);
            CheckResult(result);

            TransitionImageLayout(_image, (uint)MipLevels, 0, 6, _imageLayout, VkImageLayout.TransferDstOptimal);

            VkCommandBuffer copyCmd = _rc.BeginOneTimeCommands();

            vkCmdCopyBufferToImage(copyCmd, stagingBuffer, _image, VkImageLayout.TransferDstOptimal, copyRegions.Count, (IntPtr)copyRegions.Data);
            _rc.EndOneTimeCommands(copyCmd, copyFence);
            result = vkWaitForFences(_device, 1, ref copyFence, true, ulong.MaxValue);
            CheckResult(result);

            vkDestroyBuffer(_device, stagingBuffer, null);
            _memoryManager.Free(stagingMemory);
        }
Exemple #13
0
        public VkTexture2D(
            VkDevice device,
            VkPhysicalDevice physicalDevice,
            VkDeviceMemoryManager memoryManager,
            VkRenderContext rc,
            int mipLevels,
            int width,
            int height,
            PixelFormat veldridFormat,
            DeviceTextureCreateOptions createOptions)
        {
            _device         = device;
            _physicalDevice = physicalDevice;
            _memoryManager  = memoryManager;
            _rc             = rc;

            MipLevels      = mipLevels;
            _width         = width;
            _height        = height;
            _createOptions = createOptions;
            if (createOptions == DeviceTextureCreateOptions.DepthStencil)
            {
                Format = VkFormat.D16Unorm;
            }
            else
            {
                Format = VkFormats.VeldridToVkPixelFormat(veldridFormat);
            }

            _veldridFormat = veldridFormat;

            VkImageCreateInfo imageCI = VkImageCreateInfo.New();

            imageCI.mipLevels     = (uint)mipLevels;
            imageCI.arrayLayers   = 1;
            imageCI.imageType     = VkImageType.Image2D;
            imageCI.extent.width  = (uint)width;
            imageCI.extent.height = (uint)height;
            imageCI.extent.depth  = 1;
            imageCI.initialLayout = VkImageLayout.Preinitialized; // TODO: Use proper VkImageLayout values and transitions.
            imageCI.usage         = VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled;
            if (createOptions == DeviceTextureCreateOptions.RenderTarget)
            {
                imageCI.usage |= VkImageUsageFlags.ColorAttachment;
            }
            else if (createOptions == DeviceTextureCreateOptions.DepthStencil)
            {
                imageCI.usage |= VkImageUsageFlags.DepthStencilAttachment;
            }
            imageCI.tiling = createOptions == DeviceTextureCreateOptions.DepthStencil ? VkImageTiling.Optimal : VkImageTiling.Optimal;
            imageCI.format = Format;

            imageCI.samples = VkSampleCountFlags.Count1;

            VkResult result = vkCreateImage(device, ref imageCI, null, out _image);

            CheckResult(result);

            vkGetImageMemoryRequirements(_device, _image, out VkMemoryRequirements memoryRequirements);

            VkMemoryBlock memoryToken = memoryManager.Allocate(
                FindMemoryType(
                    _physicalDevice,
                    memoryRequirements.memoryTypeBits,
                    VkMemoryPropertyFlags.DeviceLocal),
                memoryRequirements.size,
                memoryRequirements.alignment);

            _memory = memoryToken;
            vkBindImageMemory(_device, _image, _memory.DeviceMemory, _memory.Offset);
        }
 public void Free(VkMemoryBlock block)
 {
     GetAllocator(block.MemoryTypeIndex).Free(block);
 }
 private void RemoveAllocatedBlock(VkMemoryBlock block)
 {
     Debug.Assert(_allocatedBlocks.Remove(block), "Unable to remove a supposedly allocated block.");
 }