Beispiel #1
0
        public VkBuffer(VkGraphicsDevice gd, ulong sizeInBytes, bool dynamic, VkBufferUsageFlags usage)
        {
            _gd         = gd;
            SizeInBytes = sizeInBytes;
            usage      |= VkBufferUsageFlags.TransferSrc | VkBufferUsageFlags.TransferDst;

            VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New();

            bufferCI.size  = sizeInBytes;
            bufferCI.usage = usage;
            VkResult result = vkCreateBuffer(gd.Device, ref bufferCI, null, out _deviceBuffer);

            CheckResult(result);

            vkGetBufferMemoryRequirements(gd.Device, _deviceBuffer, out VkMemoryRequirements bufferMemoryRequirements);

            VkMemoryBlock memoryToken = gd.MemoryManager.Allocate(
                gd.PhysicalDeviceMemProperties,
                bufferMemoryRequirements.memoryTypeBits,
                VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
                dynamic,
                bufferMemoryRequirements.size,
                bufferMemoryRequirements.alignment);

            _memory = memoryToken;
            result  = vkBindBufferMemory(gd.Device, _deviceBuffer, _memory.DeviceMemory, _memory.Offset);
            CheckResult(result);
        }
Beispiel #2
0
            public void Free(VkMemoryBlock block)
            {
                _freeBlocks.Add(block);
#if DEBUG
                RemoveAllocatedBlock(block);
#endif
            }
            private void MergeContiguousBlocks()
            {
                int contiguousLength = 1;

                for (int i = 0; i < _freeBlocks.Count - 1; i++)
                {
                    ulong blockStart = _freeBlocks[i].Offset;
                    while (i + contiguousLength < _freeBlocks.Count &&
                           _freeBlocks[i + contiguousLength - 1].End == _freeBlocks[i + contiguousLength].Offset)
                    {
                        contiguousLength += 1;
                    }

                    if (contiguousLength > 1)
                    {
                        ulong blockEnd = _freeBlocks[i + contiguousLength - 1].End;
                        _freeBlocks.RemoveRange(i, contiguousLength);
                        VkMemoryBlock mergedBlock = new VkMemoryBlock(
                            Memory,
                            blockStart,
                            blockEnd - blockStart,
                            _memoryTypeIndex,
                            _mappedPtr,
                            false);
                        _freeBlocks.Insert(i, mergedBlock);
                        contiguousLength = 0;
                    }
                }
            }
Beispiel #4
0
 public void Free(VkMemoryBlock block)
 {
     lock (_lock)
     {
         GetAllocator(block.MemoryTypeIndex, block.IsPersistentMapped).Free(block);
     }
 }
Beispiel #5
0
        public VkBuffer(VkGraphicsDevice gd, uint sizeInBytes, BufferUsage usage)
        {
            _gd         = gd;
            SizeInBytes = sizeInBytes;
            Usage       = usage;

            VkBufferUsageFlags vkUsage = VkBufferUsageFlags.TransferSrc | VkBufferUsageFlags.TransferDst;

            if ((usage & BufferUsage.VertexBuffer) == BufferUsage.VertexBuffer)
            {
                vkUsage |= VkBufferUsageFlags.VertexBuffer;
            }
            if ((usage & BufferUsage.IndexBuffer) == BufferUsage.IndexBuffer)
            {
                vkUsage |= VkBufferUsageFlags.IndexBuffer;
            }
            if ((usage & BufferUsage.UniformBuffer) == BufferUsage.UniformBuffer)
            {
                vkUsage |= VkBufferUsageFlags.UniformBuffer;
            }
            if ((usage & BufferUsage.StructuredBufferReadWrite) == BufferUsage.StructuredBufferReadWrite ||
                (usage & BufferUsage.StructuredBufferReadOnly) == BufferUsage.StructuredBufferReadOnly)
            {
                vkUsage |= VkBufferUsageFlags.StorageBuffer;
            }
            if ((usage & BufferUsage.IndirectBuffer) == BufferUsage.IndirectBuffer)
            {
                vkUsage |= VkBufferUsageFlags.IndirectBuffer;
            }

            VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New();

            bufferCI.size  = sizeInBytes;
            bufferCI.usage = vkUsage;
            VkResult result = vkCreateBuffer(gd.Device, ref bufferCI, null, out _deviceBuffer);

            CheckResult(result);

            vkGetBufferMemoryRequirements(gd.Device, _deviceBuffer, out _bufferMemoryRequirements);

            bool hostVisible = (usage & BufferUsage.Dynamic) == BufferUsage.Dynamic ||
                               (usage & BufferUsage.Staging) == BufferUsage.Staging;

            VkMemoryPropertyFlags memoryPropertyFlags =
                hostVisible
                ? VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent
                : VkMemoryPropertyFlags.DeviceLocal;

            VkMemoryBlock memoryToken = gd.MemoryManager.Allocate(
                gd.PhysicalDeviceMemProperties,
                _bufferMemoryRequirements.memoryTypeBits,
                memoryPropertyFlags,
                hostVisible,
                _bufferMemoryRequirements.size,
                _bufferMemoryRequirements.alignment);

            _memory = memoryToken;
            result  = vkBindBufferMemory(gd.Device, _deviceBuffer, _memory.DeviceMemory, _memory.Offset);
            CheckResult(result);
        }
Beispiel #6
0
            public ChunkAllocator(VkDevice device, uint memoryTypeIndex, bool persistentMapped)
            {
                _device           = device;
                _memoryTypeIndex  = memoryTypeIndex;
                _persistentMapped = persistentMapped;
                _totalMemorySize  = persistentMapped ? PersistentMappedChunkSize : UnmappedChunkSize;

                VkMemoryAllocateInfo memoryAI = VkMemoryAllocateInfo.New();

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

                CheckResult(result);

                void *mappedPtr = null;

                if (persistentMapped)
                {
                    result = vkMapMemory(_device, _memory, 0, _totalMemorySize, 0, &mappedPtr);
                    CheckResult(result);
                }

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

                _freeBlocks.Add(initialBlock);
            }
Beispiel #7
0
        internal IntPtr Map(VkMemoryBlock memoryBlock)
        {
            void *   ret;
            VkResult result = vkMapMemory(_device, memoryBlock.DeviceMemory, memoryBlock.Offset, memoryBlock.Size, 0, &ret);

            CheckResult(result);
            return((IntPtr)ret);
        }
Beispiel #8
0
            private void CheckAllocatedBlock(VkMemoryBlock block)
            {
                foreach (VkMemoryBlock oldBlock in _allocatedBlocks)
                {
                    Debug.Assert(!BlocksOverlap(block, oldBlock), "Allocated blocks have overlapped.");
                }

                _allocatedBlocks.Add(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.RemoveAt(i);

                            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,
                                    freeBlock.BaseMappedPointer,
                                    false);
                                _freeBlocks.Insert(i, splitBlock);
                                block      = freeBlock;
                                block.Size = size;
                            }

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

                    block = default(VkMemoryBlock);
                    return(false);
                }
            }
Beispiel #10
0
 public void Free(VkMemoryBlock block)
 {
     foreach (ChunkAllocator chunk in _allocators)
     {
         if (chunk.Memory == block.DeviceMemory)
         {
             chunk.Free(block);
         }
     }
 }
Beispiel #11
0
            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 void Free(VkMemoryBlock block)
 {
     lock (_lock)
     {
         if (block.DedicatedAllocation)
         {
             vkFreeMemory(_device, block.DeviceMemory, null);
         }
         else
         {
             GetAllocator(block.MemoryTypeIndex, block.IsPersistentMapped).Free(block);
         }
     }
 }
Beispiel #13
0
            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, _persistentMapped);

                _allocators.Add(newAllocator);
                return(newAllocator.Allocate(size, alignment, out block));
            }
Beispiel #14
0
        public static void CreateImage(
            VkDevice device,
            VkPhysicalDeviceMemoryProperties physicalDeviceMemProperties,
            VkDeviceMemoryManager memoryManager,
            uint width,
            uint height,
            uint depth,
            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  = depth;
            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(
                physicalDeviceMemProperties,
                memRequirements.memoryTypeBits,
                properties,
                false,
                memRequirements.size,
                memRequirements.alignment);

            memory = memoryToken;
            result = vkBindImageMemory(device, image, memory.DeviceMemory, memory.Offset);
            CheckResult(result);
        }
            public void Free(VkMemoryBlock block)
            {
                for (int i = 0; i < _freeBlocks.Count; i++)
                {
                    if (_freeBlocks[i].Offset > block.Offset)
                    {
                        _freeBlocks.Insert(i, block);
                        MergeContiguousBlocks();
#if DEBUG
                        RemoveAllocatedBlock(block);
#endif
                        return;
                    }
                }

                _freeBlocks.Add(block);
#if DEBUG
                RemoveAllocatedBlock(block);
#endif
            }
Beispiel #16
0
        internal VkTexture(VkGraphicsDevice gd, ref TextureDescription description)
        {
            _gd         = gd;
            Width       = description.Width;
            Height      = description.Height;
            Depth       = description.Depth;
            MipLevels   = description.MipLevels;
            ArrayLayers = description.ArrayLayers;
            bool isCubemap = ((description.Usage) & TextureUsage.Cubemap) == TextureUsage.Cubemap;

            _actualImageArrayLayers = isCubemap
                ? 6 * ArrayLayers
                : ArrayLayers;
            Format        = description.Format;
            Usage         = description.Usage;
            SampleCount   = description.SampleCount;
            VkSampleCount = VkFormats.VdToVkSampleCount(SampleCount);
            VkFormat      = VkFormats.VdToVkPixelFormat(Format, (description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil);

            VkImageCreateInfo imageCI = VkImageCreateInfo.New();

            imageCI.mipLevels     = MipLevels;
            imageCI.arrayLayers   = _actualImageArrayLayers;
            imageCI.imageType     = Depth == 1 ? VkImageType.Image2D : VkImageType.Image3D;
            imageCI.extent.width  = Width;
            imageCI.extent.height = Height;
            imageCI.extent.depth  = Depth;
            imageCI.initialLayout = VkImageLayout.Preinitialized;
            imageCI.usage         = VkImageUsageFlags.TransferDst | VkImageUsageFlags.TransferSrc;
            bool isDepthStencil = (description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil;

            if ((description.Usage & TextureUsage.Sampled) == TextureUsage.Sampled)
            {
                imageCI.usage |= VkImageUsageFlags.Sampled;
            }
            if (isDepthStencil)
            {
                imageCI.usage |= VkImageUsageFlags.DepthStencilAttachment;
            }
            if ((description.Usage & TextureUsage.RenderTarget) == TextureUsage.RenderTarget)
            {
                imageCI.usage |= VkImageUsageFlags.ColorAttachment;
            }
            if ((description.Usage & TextureUsage.Storage) == TextureUsage.Storage)
            {
                imageCI.usage |= VkImageUsageFlags.Storage;
            }

            bool isStaging = (Usage & TextureUsage.Staging) == TextureUsage.Staging;

            imageCI.tiling = isStaging ? VkImageTiling.Linear : VkImageTiling.Optimal;
            imageCI.format = VkFormat;

            imageCI.samples = VkSampleCount;
            if (isCubemap)
            {
                imageCI.flags = VkImageCreateFlags.CubeCompatible;
            }

            uint subresourceCount = MipLevels * _actualImageArrayLayers;

            if (!isStaging)
            {
                VkResult result = vkCreateImage(gd.Device, ref imageCI, null, out _optimalImage);
                CheckResult(result);

                vkGetImageMemoryRequirements(gd.Device, _optimalImage, out VkMemoryRequirements memoryRequirements);

                VkMemoryBlock memoryToken = gd.MemoryManager.Allocate(
                    gd.PhysicalDeviceMemProperties,
                    memoryRequirements.memoryTypeBits,
                    VkMemoryPropertyFlags.DeviceLocal,
                    false,
                    memoryRequirements.size,
                    memoryRequirements.alignment);
                _optimalMemory = memoryToken;
                vkBindImageMemory(gd.Device, _optimalImage, _optimalMemory.DeviceMemory, _optimalMemory.Offset);
            }
            else
            {
                // Linear images must have one array layer and mip level.
                imageCI.arrayLayers = 1;
                imageCI.mipLevels   = 1;

                _stagingImages   = new VkImage[subresourceCount];
                _stagingMemories = new VkMemoryBlock[subresourceCount];
                for (uint arrayLayer = 0; arrayLayer < ArrayLayers; arrayLayer++)
                {
                    for (uint level = 0; level < MipLevels; level++)
                    {
                        uint subresource = CalculateSubresource(level, arrayLayer);
                        Util.GetMipDimensions(
                            this,
                            level,
                            out imageCI.extent.width,
                            out imageCI.extent.height,
                            out imageCI.extent.depth);

                        VkResult result = vkCreateImage(gd.Device, ref imageCI, null, out _stagingImages[subresource]);
                        CheckResult(result);

                        vkGetImageMemoryRequirements(
                            gd.Device,
                            _stagingImages[subresource],
                            out VkMemoryRequirements memoryRequirements);

                        VkMemoryBlock memoryToken = gd.MemoryManager.Allocate(
                            gd.PhysicalDeviceMemProperties,
                            memoryRequirements.memoryTypeBits,
                            VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
                            true,
                            memoryRequirements.size,
                            memoryRequirements.alignment);
                        _stagingMemories[subresource] = memoryToken;

                        result = vkBindImageMemory(
                            gd.Device,
                            _stagingImages[subresource],
                            memoryToken.DeviceMemory,
                            memoryToken.Offset);
                        CheckResult(result);
                    }
                }
            }

            _imageLayouts = new VkImageLayout[subresourceCount];
            for (int i = 0; i < _imageLayouts.Length; i++)
            {
                _imageLayouts[i] = VkImageLayout.Preinitialized;
            }
        }
Beispiel #17
0
        public VkBuffer(VkGraphicsDevice gd, uint sizeInBytes, BufferUsage usage, string callerMember = null)
        {
            _gd         = gd;
            SizeInBytes = sizeInBytes;
            Usage       = usage;

            VkBufferUsageFlags vkUsage = VkBufferUsageFlags.TransferSrc | VkBufferUsageFlags.TransferDst;

            if ((usage & BufferUsage.VertexBuffer) == BufferUsage.VertexBuffer)
            {
                vkUsage |= VkBufferUsageFlags.VertexBuffer;
            }
            if ((usage & BufferUsage.IndexBuffer) == BufferUsage.IndexBuffer)
            {
                vkUsage |= VkBufferUsageFlags.IndexBuffer;
            }
            if ((usage & BufferUsage.UniformBuffer) == BufferUsage.UniformBuffer)
            {
                vkUsage |= VkBufferUsageFlags.UniformBuffer;
            }
            if ((usage & BufferUsage.StructuredBufferReadWrite) == BufferUsage.StructuredBufferReadWrite ||
                (usage & BufferUsage.StructuredBufferReadOnly) == BufferUsage.StructuredBufferReadOnly)
            {
                vkUsage |= VkBufferUsageFlags.StorageBuffer;
            }
            if ((usage & BufferUsage.IndirectBuffer) == BufferUsage.IndirectBuffer)
            {
                vkUsage |= VkBufferUsageFlags.IndirectBuffer;
            }

            VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New();

            bufferCI.size  = sizeInBytes;
            bufferCI.usage = vkUsage;
            VkResult result = vkCreateBuffer(gd.Device, ref bufferCI, null, out _deviceBuffer);

            CheckResult(result);

            bool prefersDedicatedAllocation;

            if (_gd.GetBufferMemoryRequirements2 != null)
            {
                VkBufferMemoryRequirementsInfo2KHR memReqInfo2 = VkBufferMemoryRequirementsInfo2KHR.New();
                memReqInfo2.buffer = _deviceBuffer;
                VkMemoryRequirements2KHR         memReqs2      = VkMemoryRequirements2KHR.New();
                VkMemoryDedicatedRequirementsKHR dedicatedReqs = VkMemoryDedicatedRequirementsKHR.New();
                memReqs2.pNext = &dedicatedReqs;
                _gd.GetBufferMemoryRequirements2(_gd.Device, &memReqInfo2, &memReqs2);
                _bufferMemoryRequirements  = memReqs2.memoryRequirements;
                prefersDedicatedAllocation = dedicatedReqs.prefersDedicatedAllocation || dedicatedReqs.requiresDedicatedAllocation;
            }
            else
            {
                vkGetBufferMemoryRequirements(gd.Device, _deviceBuffer, out _bufferMemoryRequirements);
                prefersDedicatedAllocation = false;
            }

            bool hostVisible = (usage & BufferUsage.Dynamic) == BufferUsage.Dynamic ||
                               (usage & BufferUsage.Staging) == BufferUsage.Staging;

            VkMemoryPropertyFlags memoryPropertyFlags =
                hostVisible
                ? VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent
                : VkMemoryPropertyFlags.DeviceLocal;

            VkMemoryBlock memoryToken = gd.MemoryManager.Allocate(
                gd.PhysicalDeviceMemProperties,
                _bufferMemoryRequirements.memoryTypeBits,
                memoryPropertyFlags,
                hostVisible,
                _bufferMemoryRequirements.size,
                _bufferMemoryRequirements.alignment,
                prefersDedicatedAllocation,
                VkImage.Null,
                _deviceBuffer);

            _memory = memoryToken;
            result  = vkBindBufferMemory(gd.Device, _deviceBuffer, _memory.DeviceMemory, _memory.Offset);
            CheckResult(result);

            RefCount = new ResourceRefCount(DisposeCore);
        }
Beispiel #18
0
 private void RemoveAllocatedBlock(VkMemoryBlock block)
 {
     Debug.Assert(_allocatedBlocks.Remove(block), "Unable to remove a supposedly allocated block.");
 }
Beispiel #19
0
        internal VkTexture(VkGraphicsDevice gd, ref TextureDescription description)
        {
            _gd         = gd;
            Width       = description.Width;
            Height      = description.Height;
            Depth       = description.Depth;
            MipLevels   = description.MipLevels;
            ArrayLayers = description.ArrayLayers;
            Format      = description.Format;
            Usage       = description.Usage;
            if ((description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil)
            {
                if (Format != PixelFormat.R16_UNorm && Format != PixelFormat.R32_Float)
                {
                    throw new NotImplementedException("The only supported depth texture formats are R16_UInt and R32_Float.");
                }
                if (Format == PixelFormat.R16_UNorm)
                {
                    VkFormat = VkFormat.D16Unorm;
                }
                else
                {
                    VkFormat = VkFormat.D32Sfloat;
                }
            }
            else
            {
                VkFormat = VkFormats.VdToVkPixelFormat(Format);
            }

            VkImageCreateInfo imageCI = VkImageCreateInfo.New();

            imageCI.mipLevels     = MipLevels;
            imageCI.arrayLayers   = description.ArrayLayers;
            imageCI.imageType     = Depth == 1 ? VkImageType.Image2D : VkImageType.Image3D;
            imageCI.extent.width  = Width;
            imageCI.extent.height = Height;
            imageCI.extent.depth  = Depth;
            imageCI.initialLayout = VkImageLayout.Preinitialized;
            imageCI.usage         = VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled;
            bool isDepthStencil = (description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil;

            if ((description.Usage & TextureUsage.Sampled) == TextureUsage.Sampled)
            {
                imageCI.usage |= VkImageUsageFlags.Sampled;
            }
            if (isDepthStencil)
            {
                imageCI.usage |= VkImageUsageFlags.DepthStencilAttachment;
            }
            imageCI.tiling = VkImageTiling.Optimal;
            imageCI.format = VkFormat;

            imageCI.samples = VkSampleCountFlags.Count1;
            if ((Usage & TextureUsage.Cubemap) == TextureUsage.Cubemap)
            {
                imageCI.flags        = VkImageCreateFlags.CubeCompatible;
                imageCI.arrayLayers *= 6;
            }

            VkResult result = vkCreateImage(gd.Device, ref imageCI, null, out _image);

            CheckResult(result);
            ImageLayouts = new VkImageLayout[MipLevels];
            for (int i = 0; i < MipLevels; i++)
            {
                ImageLayouts[i] = VkImageLayout.Preinitialized;
            }

            vkGetImageMemoryRequirements(gd.Device, _image, out VkMemoryRequirements memoryRequirements);

            VkMemoryBlock memoryToken = gd.MemoryManager.Allocate(
                gd.PhysicalDeviceMemProperties,
                memoryRequirements.memoryTypeBits,
                VkMemoryPropertyFlags.DeviceLocal,
                false,
                memoryRequirements.size,
                memoryRequirements.alignment);

            _memory = memoryToken;
            vkBindImageMemory(gd.Device, _image, _memory.DeviceMemory, _memory.Offset);
        }
Beispiel #20
0
        internal VkTexture(VkGraphicsDevice gd, ref TextureDescription description)
        {
            _gd         = gd;
            _width      = description.Width;
            _height     = description.Height;
            _depth      = description.Depth;
            MipLevels   = description.MipLevels;
            ArrayLayers = description.ArrayLayers;
            bool isCubemap = ((description.Usage) & TextureUsage.Cubemap) == TextureUsage.Cubemap;

            _actualImageArrayLayers = isCubemap
                ? 6 * ArrayLayers
                : ArrayLayers;
            _format       = description.Format;
            Usage         = description.Usage;
            Type          = description.Type;
            SampleCount   = description.SampleCount;
            VkSampleCount = VkFormats.VdToVkSampleCount(SampleCount);
            VkFormat      = VkFormats.VdToVkPixelFormat(Format, (description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil);

            bool isStaging = (Usage & TextureUsage.Staging) == TextureUsage.Staging;

            if (!isStaging)
            {
                VkImageCreateInfo imageCI = VkImageCreateInfo.New();
                imageCI.mipLevels     = MipLevels;
                imageCI.arrayLayers   = _actualImageArrayLayers;
                imageCI.imageType     = VkFormats.VdToVkTextureType(Type);
                imageCI.extent.width  = Width;
                imageCI.extent.height = Height;
                imageCI.extent.depth  = Depth;
                imageCI.initialLayout = VkImageLayout.Preinitialized;
                imageCI.usage         = VkFormats.VdToVkTextureUsage(Usage);
                imageCI.tiling        = isStaging ? VkImageTiling.Linear : VkImageTiling.Optimal;
                imageCI.format        = VkFormat;

                imageCI.samples = VkSampleCount;
                if (isCubemap)
                {
                    imageCI.flags = VkImageCreateFlags.CubeCompatible;
                }

                uint     subresourceCount = MipLevels * _actualImageArrayLayers * Depth;
                VkResult result           = vkCreateImage(gd.Device, ref imageCI, null, out _optimalImage);
                CheckResult(result);

                vkGetImageMemoryRequirements(gd.Device, _optimalImage, out VkMemoryRequirements memoryRequirements);

                VkMemoryBlock memoryToken = gd.MemoryManager.Allocate(
                    gd.PhysicalDeviceMemProperties,
                    memoryRequirements.memoryTypeBits,
                    VkMemoryPropertyFlags.DeviceLocal,
                    false,
                    memoryRequirements.size,
                    memoryRequirements.alignment);
                _memoryBlock = memoryToken;
                result       = vkBindImageMemory(gd.Device, _optimalImage, _memoryBlock.DeviceMemory, _memoryBlock.Offset);
                CheckResult(result);

                _imageLayouts = new VkImageLayout[subresourceCount];
                for (int i = 0; i < _imageLayouts.Length; i++)
                {
                    _imageLayouts[i] = VkImageLayout.Preinitialized;
                }
            }
            else // isStaging
            {
                uint depthPitch = FormatHelpers.GetDepthPitch(
                    FormatHelpers.GetRowPitch(Width, Format),
                    Height,
                    Format);
                uint stagingSize = depthPitch * Depth;
                for (uint level = 1; level < MipLevels; level++)
                {
                    Util.GetMipDimensions(this, level, out uint mipWidth, out uint mipHeight, out uint mipDepth);

                    depthPitch = FormatHelpers.GetDepthPitch(
                        FormatHelpers.GetRowPitch(mipWidth, Format),
                        mipHeight,
                        Format);

                    stagingSize += depthPitch * mipDepth;
                }
                stagingSize *= ArrayLayers;

                VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New();
                bufferCI.usage = VkBufferUsageFlags.TransferSrc | VkBufferUsageFlags.TransferDst;
                bufferCI.size  = stagingSize;
                VkResult result = vkCreateBuffer(_gd.Device, ref bufferCI, null, out _stagingBuffer);
                CheckResult(result);
                vkGetBufferMemoryRequirements(_gd.Device, _stagingBuffer, out VkMemoryRequirements bufferMemReqs);
                _memoryBlock = _gd.MemoryManager.Allocate(
                    _gd.PhysicalDeviceMemProperties,
                    bufferMemReqs.memoryTypeBits,
                    VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
                    true,
                    bufferMemReqs.size,
                    bufferMemReqs.alignment);

                result = vkBindBufferMemory(_gd.Device, _stagingBuffer, _memoryBlock.DeviceMemory, _memoryBlock.Offset);
                CheckResult(result);
            }

            ClearIfRenderTarget();
        }
Beispiel #21
0
        internal VkTexture(VkGraphicsDevice gd, ref TextureDescription description)
        {
            _gd         = gd;
            _width      = description.Width;
            _height     = description.Height;
            _depth      = description.Depth;
            MipLevels   = description.MipLevels;
            ArrayLayers = description.ArrayLayers;
            bool isCubemap = ((description.Usage) & TextureUsage.Cubemap) == TextureUsage.Cubemap;

            _actualImageArrayLayers = isCubemap
                ? 6 * ArrayLayers
                : ArrayLayers;
            _format       = description.Format;
            Usage         = description.Usage;
            Type          = description.Type;
            SampleCount   = description.SampleCount;
            VkSampleCount = VkFormats.VdToVkSampleCount(SampleCount);
            VkFormat      = VkFormats.VdToVkPixelFormat(Format, (description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil);

            bool isStaging = (Usage & TextureUsage.Staging) == TextureUsage.Staging;

            if (!isStaging)
            {
                VkImageCreateInfo imageCI = VkImageCreateInfo.New();
                imageCI.mipLevels     = MipLevels;
                imageCI.arrayLayers   = _actualImageArrayLayers;
                imageCI.imageType     = VkFormats.VdToVkTextureType(Type);
                imageCI.extent.width  = Width;
                imageCI.extent.height = Height;
                imageCI.extent.depth  = Depth;
                imageCI.initialLayout = VkImageLayout.Preinitialized;
                imageCI.usage         = VkFormats.VdToVkTextureUsage(Usage);
                imageCI.tiling        = isStaging ? VkImageTiling.Linear : VkImageTiling.Optimal;
                imageCI.format        = VkFormat;
                imageCI.flags         = VkImageCreateFlags.MutableFormat;

                imageCI.samples = VkSampleCount;
                if (isCubemap)
                {
                    imageCI.flags |= VkImageCreateFlags.CubeCompatible;
                }

                uint     subresourceCount = MipLevels * _actualImageArrayLayers * Depth;
                VkResult result           = vkCreateImage(gd.Device, ref imageCI, null, out _optimalImage);
                CheckResult(result);

                VkMemoryRequirements memoryRequirements;
                bool prefersDedicatedAllocation;
                if (_gd.GetImageMemoryRequirements2 != null)
                {
                    VkImageMemoryRequirementsInfo2KHR memReqsInfo2 = VkImageMemoryRequirementsInfo2KHR.New();
                    memReqsInfo2.image = _optimalImage;
                    VkMemoryRequirements2KHR         memReqs2      = VkMemoryRequirements2KHR.New();
                    VkMemoryDedicatedRequirementsKHR dedicatedReqs = VkMemoryDedicatedRequirementsKHR.New();
                    memReqs2.pNext = &dedicatedReqs;
                    _gd.GetImageMemoryRequirements2(_gd.Device, &memReqsInfo2, &memReqs2);
                    memoryRequirements         = memReqs2.memoryRequirements;
                    prefersDedicatedAllocation = dedicatedReqs.prefersDedicatedAllocation || dedicatedReqs.requiresDedicatedAllocation;
                }
                else
                {
                    vkGetImageMemoryRequirements(gd.Device, _optimalImage, out memoryRequirements);
                    prefersDedicatedAllocation = false;
                }

                VkMemoryBlock memoryToken = gd.MemoryManager.Allocate(
                    gd.PhysicalDeviceMemProperties,
                    memoryRequirements.memoryTypeBits,
                    VkMemoryPropertyFlags.DeviceLocal,
                    false,
                    memoryRequirements.size,
                    memoryRequirements.alignment,
                    prefersDedicatedAllocation,
                    _optimalImage,
                    Vulkan.VkBuffer.Null);
                _memoryBlock = memoryToken;
                result       = vkBindImageMemory(gd.Device, _optimalImage, _memoryBlock.DeviceMemory, _memoryBlock.Offset);
                CheckResult(result);

                _imageLayouts = new VkImageLayout[subresourceCount];
                for (int i = 0; i < _imageLayouts.Length; i++)
                {
                    _imageLayouts[i] = VkImageLayout.Preinitialized;
                }
            }
            else // isStaging
            {
                uint depthPitch = FormatHelpers.GetDepthPitch(
                    FormatHelpers.GetRowPitch(Width, Format),
                    Height,
                    Format);
                uint stagingSize = depthPitch * Depth;
                for (uint level = 1; level < MipLevels; level++)
                {
                    Util.GetMipDimensions(this, level, out uint mipWidth, out uint mipHeight, out uint mipDepth);

                    depthPitch = FormatHelpers.GetDepthPitch(
                        FormatHelpers.GetRowPitch(mipWidth, Format),
                        mipHeight,
                        Format);

                    stagingSize += depthPitch * mipDepth;
                }
                stagingSize *= ArrayLayers;

                VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New();
                bufferCI.usage = VkBufferUsageFlags.TransferSrc | VkBufferUsageFlags.TransferDst;
                bufferCI.size  = stagingSize;
                VkResult result = vkCreateBuffer(_gd.Device, ref bufferCI, null, out _stagingBuffer);
                CheckResult(result);

                VkMemoryRequirements bufferMemReqs;
                bool prefersDedicatedAllocation;
                if (_gd.GetBufferMemoryRequirements2 != null)
                {
                    VkBufferMemoryRequirementsInfo2KHR memReqInfo2 = VkBufferMemoryRequirementsInfo2KHR.New();
                    memReqInfo2.buffer = _stagingBuffer;
                    VkMemoryRequirements2KHR         memReqs2      = VkMemoryRequirements2KHR.New();
                    VkMemoryDedicatedRequirementsKHR dedicatedReqs = VkMemoryDedicatedRequirementsKHR.New();
                    memReqs2.pNext = &dedicatedReqs;
                    _gd.GetBufferMemoryRequirements2(_gd.Device, &memReqInfo2, &memReqs2);
                    bufferMemReqs = memReqs2.memoryRequirements;
                    prefersDedicatedAllocation = dedicatedReqs.prefersDedicatedAllocation || dedicatedReqs.requiresDedicatedAllocation;
                }
                else
                {
                    vkGetBufferMemoryRequirements(gd.Device, _stagingBuffer, out bufferMemReqs);
                    prefersDedicatedAllocation = false;
                }

                // Use "host cached" memory when available, for better performance of GPU -> CPU transfers
                var propertyFlags = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent | VkMemoryPropertyFlags.HostCached;
                if (!TryFindMemoryType(_gd.PhysicalDeviceMemProperties, bufferMemReqs.memoryTypeBits, propertyFlags, out _))
                {
                    propertyFlags ^= VkMemoryPropertyFlags.HostCached;
                }
                _memoryBlock = _gd.MemoryManager.Allocate(
                    _gd.PhysicalDeviceMemProperties,
                    bufferMemReqs.memoryTypeBits,
                    propertyFlags,
                    true,
                    bufferMemReqs.size,
                    bufferMemReqs.alignment,
                    prefersDedicatedAllocation,
                    VkImage.Null,
                    _stagingBuffer);

                result = vkBindBufferMemory(_gd.Device, _stagingBuffer, _memoryBlock.DeviceMemory, _memoryBlock.Offset);
                CheckResult(result);
            }

            ClearIfRenderTarget();
            TransitionIfSampled();
            RefCount = new ResourceRefCount(RefCountedDispose);
        }