Exemple #1
0
 public override void GetBufferMemoryRequirements(VkBuffer buffer, out VkMemoryRequirements pMemoryRequirements)
 {
     pMemoryRequirements = new VkMemoryRequirements();
     pMemoryRequirements.memoryTypeBits = 1;
     pMemoryRequirements.size           = ((SoftwareBuffer)buffer).createInfo.size;
     pMemoryRequirements.alignment      = 4;
 }
Exemple #2
0
        internal void GetImageMemoryRequirements(out VkMemoryRequirements pMemoryRequirements)
        {
            int pixelSize = 4;

            pMemoryRequirements.alignment      = 4;
            pMemoryRequirements.memoryTypeBits = int.MaxValue;
            pMemoryRequirements.size           = m_imageExtent.width * m_imageExtent.height * m_imageExtent.depth * pixelSize;
        }
Exemple #3
0
        protected unsafe void AllocateMemory(VkMemoryPropertyFlags memoryProperties, VkMemoryRequirements memoryRequirements)
        {
            if (NativeMemory != VkDeviceMemory.Null)
            {
                return;
            }

            if (memoryRequirements.size == 0)
            {
                return;
            }

            var allocateInfo = new VkMemoryAllocateInfo
            {
                sType          = VkStructureType.MemoryAllocateInfo,
                allocationSize = memoryRequirements.size,
            };

            VkPhysicalDeviceMemoryProperties localProps;

            if (!gotProps)
            {
                gotProps = true;
                vkGetPhysicalDeviceMemoryProperties(GraphicsDevice.NativePhysicalDevice, out physicalDeviceMemoryProperties);
            }
            localProps = physicalDeviceMemoryProperties;

            var typeBits = memoryRequirements.memoryTypeBits;

            for (uint i = 0; i < localProps.memoryTypeCount; i++)
            {
                if ((typeBits & 1) == 1)
                {
                    // Type is available, does it match user properties?
                    var memoryType = *(&localProps.memoryTypes_0 + i);
                    if ((memoryType.propertyFlags & memoryProperties) == memoryProperties)
                    {
                        allocateInfo.memoryTypeIndex = i;
                        break;
                    }
                }
                typeBits >>= 1;
            }

            var result = vkAllocateMemory(GraphicsDevice.NativeDevice, &allocateInfo, null, out NativeMemory);

            if (result != VkResult.Success)
            {
                string err = "Couldn't allocate memory: " + result + ", NativeMemory: " + NativeMemory + ", type: " + allocateInfo.memoryTypeIndex + ", size: " + memoryRequirements.size;
                Xenko.Core.ErrorFileLogger.WriteLogToFile(err);
                throw new Exception(err);
            }
        }
Exemple #4
0
        public FDataBuffer(VkDevice device, VkPhysicalDevice physicalDevice, int length, VkBufferUsageFlags usage, VkSharingMode sharingMode)
        {
            this.device = device;

            VkBufferCreateInfo createInfo = VkBufferCreateInfo.New();

            size                   = (ulong)(sizeof(T) * length);
            createInfo.size        = size;
            createInfo.usage       = usage;
            createInfo.sharingMode = sharingMode;

            VkBuffer buffer = VkBuffer.Null;

            Assert(vkCreateBuffer(device, &createInfo, null, &buffer));
            this.Buffer = buffer;

            VkMemoryRequirements memoryRequirements = new VkMemoryRequirements();

            vkGetBufferMemoryRequirements(device, this.Buffer, &memoryRequirements);

            VkPhysicalDeviceMemoryProperties memoryProperties = new VkPhysicalDeviceMemoryProperties();

            vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);

            VkMemoryAllocateInfo allocateInfo = VkMemoryAllocateInfo.New();

            allocateInfo.allocationSize  = memoryRequirements.size;
            allocateInfo.memoryTypeIndex = SelectMemoryType(memoryProperties, memoryRequirements.memoryTypeBits,
                                                            VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent);

            VkDeviceMemory memory = new VkDeviceMemory();

            Assert(vkAllocateMemory(device, &allocateInfo, null, &memory));
            Memory = memory;

            Assert(vkBindBufferMemory(device, this.Buffer, memory, 0));

            spanLength = length;
        }
Exemple #5
0
        protected unsafe void AllocateMemory(VkMemoryPropertyFlags memoryProperties, VkMemoryRequirements memoryRequirements)
        {
            if (NativeMemory != VkDeviceMemory.Null)
            {
                return;
            }

            if (memoryRequirements.size == 0)
            {
                return;
            }

            var allocateInfo = new VkMemoryAllocateInfo
            {
                sType          = VkStructureType.MemoryAllocateInfo,
                allocationSize = memoryRequirements.size,
            };

            vkGetPhysicalDeviceMemoryProperties(GraphicsDevice.NativePhysicalDevice, out var physicalDeviceMemoryProperties);
            var typeBits = memoryRequirements.memoryTypeBits;

            for (uint i = 0; i < physicalDeviceMemoryProperties.memoryTypeCount; i++)
            {
                if ((typeBits & 1) == 1)
                {
                    // Type is available, does it match user properties?
                    var memoryType = *(&physicalDeviceMemoryProperties.memoryTypes_0 + i);
                    if ((memoryType.propertyFlags & memoryProperties) == memoryProperties)
                    {
                        allocateInfo.memoryTypeIndex = i;
                        break;
                    }
                }
                typeBits >>= 1;
            }

            fixed(VkDeviceMemory *nativeMemoryPtr = &NativeMemory)
            vkAllocateMemory(GraphicsDevice.NativeDevice, &allocateInfo, null, nativeMemoryPtr);
        }
Exemple #6
0
        void loadTexture(string fileName, VkFormat format, bool forceLinearTiling)
        {
            KtxFile tex2D;

            using (var fs = File.OpenRead(fileName))
            {
                tex2D = KtxFile.Load(fs, false);
            }

            VkFormatProperties formatProperties;

            texture.width     = tex2D.Header.PixelWidth;
            texture.height    = tex2D.Header.PixelHeight;
            texture.mipLevels = tex2D.Header.NumberOfMipmapLevels;

            // Get Device properites for the requested texture format
            vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties);

            // Only use linear tiling if requested (and supported by the Device)
            // Support for linear tiling is mostly limited, so prefer to use
            // optimal tiling instead
            // On most implementations linear tiling will only support a very
            // limited amount of formats and features (mip maps, cubemaps, arrays, etc.)
            uint useStaging = 1;

            // Only use linear tiling if forced
            if (forceLinearTiling)
            {
                // Don't use linear if format is not supported for (linear) shader sampling
                useStaging = ((formatProperties.linearTilingFeatures & VkFormatFeatureFlags.SampledImage) != VkFormatFeatureFlags.SampledImage) ? 1u : 0u;
            }

            VkMemoryAllocateInfo memAllocInfo = Initializers.memoryAllocateInfo();
            VkMemoryRequirements memReqs      = new VkMemoryRequirements();

            if (useStaging == 1)
            {
                // Create a host-visible staging buffer that contains the raw image data
                VkBuffer       stagingBuffer;
                VkDeviceMemory stagingMemory;

                VkBufferCreateInfo bufferCreateInfo = Initializers.bufferCreateInfo();
                bufferCreateInfo.size = tex2D.GetTotalSize();
                // This buffer is used as a transfer source for the buffer copy
                bufferCreateInfo.usage       = VkBufferUsageFlags.TransferSrc;
                bufferCreateInfo.sharingMode = VkSharingMode.Exclusive;

                Util.CheckResult(vkCreateBuffer(device, &bufferCreateInfo, null, &stagingBuffer));

                // Get memory requirements for the staging buffer (alignment, memory type bits)
                vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs);

                memAllocInfo.allocationSize = memReqs.size;
                // Get memory type index for a host visible buffer
                memAllocInfo.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent);

                Util.CheckResult(vkAllocateMemory(device, &memAllocInfo, null, &stagingMemory));
                Util.CheckResult(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0));

                // Copy texture data into staging buffer
                byte *data;
                Util.CheckResult(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data));
                byte[] allData = tex2D.GetAllTextureData();
                fixed(byte *tex2DDataPtr = &allData[0])
                {
                    Unsafe.CopyBlock(data, tex2DDataPtr, (uint)allData.Length);
                }

                vkUnmapMemory(device, stagingMemory);

                // Setup buffer copy regions for each mip level
                NativeList <VkBufferImageCopy> bufferCopyRegions = new NativeList <VkBufferImageCopy>();
                uint offset = 0;

                for (uint i = 0; i < texture.mipLevels; i++)
                {
                    VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy();
                    bufferCopyRegion.imageSubresource.aspectMask     = VkImageAspectFlags.Color;
                    bufferCopyRegion.imageSubresource.mipLevel       = i;
                    bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
                    bufferCopyRegion.imageSubresource.layerCount     = 1;
                    bufferCopyRegion.imageExtent.width  = tex2D.Faces[0].Mipmaps[i].Width;
                    bufferCopyRegion.imageExtent.height = tex2D.Faces[0].Mipmaps[i].Height;
                    bufferCopyRegion.imageExtent.depth  = 1;
                    bufferCopyRegion.bufferOffset       = offset;

                    bufferCopyRegions.Add(bufferCopyRegion);

                    offset += tex2D.Faces[0].Mipmaps[i].SizeInBytes;
                }

                // Create optimal tiled target image
                VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo();
                imageCreateInfo.imageType   = VkImageType.Image2D;
                imageCreateInfo.format      = format;
                imageCreateInfo.mipLevels   = texture.mipLevels;
                imageCreateInfo.arrayLayers = 1;
                imageCreateInfo.samples     = VkSampleCountFlags.Count1;
                imageCreateInfo.tiling      = VkImageTiling.Optimal;
                imageCreateInfo.sharingMode = VkSharingMode.Exclusive;
                // Set initial layout of the image to undefined
                imageCreateInfo.initialLayout = VkImageLayout.Undefined;
                imageCreateInfo.extent        = new VkExtent3D {
                    width = texture.width, height = texture.height, depth = 1
                };
                imageCreateInfo.usage = VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled;

                Util.CheckResult(vkCreateImage(device, &imageCreateInfo, null, out texture.image));

                vkGetImageMemoryRequirements(device, texture.image, &memReqs);

                memAllocInfo.allocationSize  = memReqs.size;
                memAllocInfo.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal);

                Util.CheckResult(vkAllocateMemory(device, &memAllocInfo, null, out texture.DeviceMemory));
                Util.CheckResult(vkBindImageMemory(device, texture.image, texture.DeviceMemory, 0));

                VkCommandBuffer copyCmd = base.createCommandBuffer(VkCommandBufferLevel.Primary, true);

                // Image barrier for optimal image

                // The sub resource range describes the regions of the image we will be transition
                VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange();
                // Image only contains color data
                subresourceRange.aspectMask = VkImageAspectFlags.Color;
                // Start at first mip level
                subresourceRange.baseMipLevel = 0;
                // We will transition on all mip levels
                subresourceRange.levelCount = texture.mipLevels;
                // The 2D texture only has one layer
                subresourceRange.layerCount = 1;

                // Optimal image will be used as destination for the copy, so we must transfer from our
                // initial undefined image layout to the transfer destination layout
                setImageLayout(
                    copyCmd,
                    texture.image,
                    VkImageAspectFlags.Color,
                    VkImageLayout.Undefined,
                    VkImageLayout.TransferDstOptimal,
                    subresourceRange);

                // Copy mip levels from staging buffer
                vkCmdCopyBufferToImage(
                    copyCmd,
                    stagingBuffer,
                    texture.image,
                    VkImageLayout.TransferDstOptimal,
                    bufferCopyRegions.Count,
                    bufferCopyRegions.Data);

                // Change texture image layout to shader read after all mip levels have been copied
                texture.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
                setImageLayout(
                    copyCmd,
                    texture.image,
                    VkImageAspectFlags.Color,
                    VkImageLayout.TransferDstOptimal,
                    texture.imageLayout,
                    subresourceRange);

                flushCommandBuffer(copyCmd, queue, true);

                // Clean up staging resources
                vkFreeMemory(device, stagingMemory, null);
                vkDestroyBuffer(device, stagingBuffer, null);
            }
            else
            {
                throw new NotImplementedException();

                /*
                 * // Prefer using optimal tiling, as linear tiling
                 * // may support only a small set of features
                 * // depending on implementation (e.g. no mip maps, only one layer, etc.)
                 *
                 * VkImage mappableImage;
                 * VkDeviceMemory mappableMemory;
                 *
                 * // Load mip map level 0 to linear tiling image
                 * VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo();
                 * imageCreateInfo.imageType = VkImageType._2d;
                 * imageCreateInfo.format = format;
                 * imageCreateInfo.mipLevels = 1;
                 * imageCreateInfo.arrayLayers = 1;
                 * imageCreateInfo.samples = VkSampleCountFlags._1;
                 * imageCreateInfo.tiling = VkImageTiling.Linear;
                 * imageCreateInfo.usage = VkImageUsageFlags.Sampled;
                 * imageCreateInfo.sharingMode = VkSharingMode.Exclusive;
                 * imageCreateInfo.initialLayout = VkImageLayout.Preinitialized;
                 * imageCreateInfo.extent = new VkExtent3D { width = texture.width, height = texture.height, depth = 1 };
                 * Util.CheckResult(vkCreateImage(Device, &imageCreateInfo, null, &mappableImage));
                 *
                 * // Get memory requirements for this image
                 * // like size and alignment
                 * vkGetImageMemoryRequirements(Device, mappableImage, &memReqs);
                 * // Set memory allocation size to required memory size
                 * memAllocInfo.allocationSize = memReqs.size;
                 *
                 * // Get memory type that can be mapped to host memory
                 * memAllocInfo.memoryTypeIndex = VulkanDevice.GetMemoryType(memReqs.memoryTypeBits,  VkMemoryPropertyFlags.HostVisible |  VkMemoryPropertyFlags.HostCoherent);
                 *
                 * // Allocate host memory
                 * Util.CheckResult(vkAllocateMemory(Device, &memAllocInfo, null, &mappableMemory));
                 *
                 * // Bind allocated image for use
                 * Util.CheckResult(vkBindImageMemory(Device, mappableImage, mappableMemory, 0));
                 *
                 * // Get sub resource layout
                 * // Mip map count, array layer, etc.
                 * VkImageSubresource subRes = new VkImageSubresource();
                 * subRes.aspectMask =  VkImageAspectFlags.Color;
                 *
                 * VkSubresourceLayout subResLayout;
                 * void* data;
                 *
                 * // Get sub resources layout
                 * // Includes row pitch, size offsets, etc.
                 * vkGetImageSubresourceLayout(Device, mappableImage, &subRes, &subResLayout);
                 *
                 * // Map image memory
                 * Util.CheckResult(vkMapMemory(Device, mappableMemory, 0, memReqs.size, 0, &data));
                 *
                 * // Copy image data into memory
                 * memcpy(data, tex2D[subRes.mipLevel].data(), tex2D[subRes.mipLevel].size());
                 *
                 * vkUnmapMemory(Device, mappableMemory);
                 *
                 * // Linear tiled images don't need to be staged
                 * // and can be directly used as textures
                 * texture.image = mappableImage;
                 * texture.DeviceMemory = mappableMemory;
                 * texture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
                 *
                 * VkCommandBuffer copyCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
                 *
                 * // Setup image memory barrier transfer image to shader read layout
                 *
                 * // The sub resource range describes the regions of the image we will be transition
                 * VkImageSubresourceRange subresourceRange = { };
                 * // Image only contains color data
                 * subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
                 * // Start at first mip level
                 * subresourceRange.baseMipLevel = 0;
                 * // Only one mip level, most implementations won't support more for linear tiled images
                 * subresourceRange.levelCount = 1;
                 * // The 2D texture only has one layer
                 * subresourceRange.layerCount = 1;
                 *
                 * setImageLayout(
                 *  copyCmd,
                 *  texture.image,
                 *  VK_IMAGE_ASPECT_COLOR_BIT,
                 *  VK_IMAGE_LAYOUT_PREINITIALIZED,
                 *  texture.imageLayout,
                 *  subresourceRange);
                 *
                 * VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true);
                 */
            }

            // Create sampler
            // In Vulkan textures are accessed by samplers
            // This separates all the sampling information from the
            // texture data
            // This means you could have multiple sampler objects
            // for the same texture with different settings
            // Similar to the samplers available with OpenGL 3.3
            VkSamplerCreateInfo sampler = Initializers.samplerCreateInfo();

            sampler.magFilter    = VkFilter.Linear;
            sampler.minFilter    = VkFilter.Linear;
            sampler.mipmapMode   = VkSamplerMipmapMode.Linear;
            sampler.addressModeU = VkSamplerAddressMode.Repeat;
            sampler.addressModeV = VkSamplerAddressMode.Repeat;
            sampler.addressModeW = VkSamplerAddressMode.Repeat;
            sampler.mipLodBias   = 0.0f;
            sampler.compareOp    = VkCompareOp.Never;
            sampler.minLod       = 0.0f;
            // Set max level-of-detail to mip level count of the texture
            sampler.maxLod = (useStaging == 1) ? (float)texture.mipLevels : 0.0f;
            // Enable anisotropic filtering
            // This feature is optional, so we must check if it's supported on the Device
            if (vulkanDevice.features.samplerAnisotropy == 1)
            {
                // Use max. level of anisotropy for this example
                sampler.maxAnisotropy    = vulkanDevice.properties.limits.maxSamplerAnisotropy;
                sampler.anisotropyEnable = True;
            }
            else
            {
                // The Device does not support anisotropic filtering
                sampler.maxAnisotropy    = 1.0f;
                sampler.anisotropyEnable = False;
            }
            sampler.borderColor = VkBorderColor.FloatOpaqueWhite;
            Util.CheckResult(vkCreateSampler(device, ref sampler, null, out texture.sampler));

            // Create image view
            // Textures are not directly accessed by the shaders and
            // are abstracted by image views containing additional
            // information and sub resource ranges
            VkImageViewCreateInfo view = Initializers.imageViewCreateInfo();

            view.viewType   = VkImageViewType.Image2D;
            view.format     = format;
            view.components = new VkComponentMapping {
                r = VkComponentSwizzle.R, g = VkComponentSwizzle.G, b = VkComponentSwizzle.B, a = VkComponentSwizzle.A
            };
            // The subresource range describes the set of mip levels (and array layers) that can be accessed through this image view
            // It's possible to create multiple image views for a single image referring to different (and/or overlapping) ranges of the image
            view.subresourceRange.aspectMask     = VkImageAspectFlags.Color;
            view.subresourceRange.baseMipLevel   = 0;
            view.subresourceRange.baseArrayLayer = 0;
            view.subresourceRange.layerCount     = 1;
            // Linear tiling usually won't support mip maps
            // Only set mip map count if optimal tiling is used
            view.subresourceRange.levelCount = (useStaging == 1) ? texture.mipLevels : 1;
            // The view will be based on the texture's image
            view.image = texture.image;
            Util.CheckResult(vkCreateImageView(device, &view, null, out texture.view));
        }
Exemple #7
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);
        }
Exemple #8
0
 public override void GetImageMemoryRequirements(VkImage image, out VkMemoryRequirements pMemoryRequirements)
 {
     throw new NotImplementedException();
 }
Exemple #9
0
 public override void GetBufferMemoryRequirements(VkBuffer buffer, out VkMemoryRequirements pMemoryRequirements)
 {
     throw new NotImplementedException();
 }
 public VulkanMemorySlice Allocate(VkMemoryRequirements requirements, bool hostVisible)
 => Allocate(requirements.size, requirements.alignment, requirements.memoryTypeBits, hostVisible);
        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);
        }
        internal static unsafe void AllocatePool(out VkDeviceMemory NativeMemory, ref VkDevice device, ref VkPhysicalDevice pDevice, ref VkMemoryPropertyFlags memoryProperties, ref VkMemoryRequirements memoryRequirements, ulong size)
        {
            var allocateInfo = new VkMemoryAllocateInfo
            {
                sType          = VkStructureType.MemoryAllocateInfo,
                allocationSize = size,
            };

            Vortice.Vulkan.Vulkan.vkGetPhysicalDeviceMemoryProperties(pDevice, out var physicalDeviceMemoryProperties);

            var typeBits = memoryRequirements.memoryTypeBits;

            for (uint i = 0; i < physicalDeviceMemoryProperties.memoryTypeCount; i++)
            {
                if ((typeBits & 1) == 1)
                {
                    // Type is available, does it match user properties?
                    var memoryType = *(&physicalDeviceMemoryProperties.memoryTypes_0 + i);
                    if ((memoryType.propertyFlags & memoryProperties) == memoryProperties)
                    {
                        allocateInfo.memoryTypeIndex = i;
                        break;
                    }
                }
                typeBits >>= 1;
            }

            NativeMemory = new VkDeviceMemory();

            Vortice.Vulkan.Vulkan.vkAllocateMemory(device, &allocateInfo, null, out NativeMemory);
        }
Exemple #13
0
 public static void GetImageMemoryRequirements(Image image, out VkMemoryRequirements pMemoryRequirements)
 {
     vkGetImageMemoryRequirements(device, image, out pMemoryRequirements);
 }
Exemple #14
0
 public static void GetBufferMemoryRequirements(VkBuffer buffer, out VkMemoryRequirements pMemoryRequirements)
 {
     vkGetBufferMemoryRequirements(device, buffer, out pMemoryRequirements);
 }
Exemple #15
0
 public override void GetImageMemoryRequirements(VkImage image, out VkMemoryRequirements pMemoryRequirements)
 {
     ((SoftwareImage)image).GetImageMemoryRequirements(out pMemoryRequirements);
 }
Exemple #16
0
 public static extern void GetBufferMemoryRequirements(
     VkDevice device,
     VkBuffer buffer,
     out VkMemoryRequirements pMemoryRequirements
     );
Exemple #17
0
 public static extern void GetImageMemoryRequirements(
     VkDevice device,
     VkImage image,
     out VkMemoryRequirements pMemoryRequirements
     );
 public abstract void GetBufferMemoryRequirements(VkBuffer buffer, out VkMemoryRequirements pMemoryRequirements);
        public static bool TryAllocateMemoryForBuffer(ulong size, VkDevice device, VkPhysicalDevice pDevice, ref VkMemoryRequirements memoryRequirements, ref VkMemoryPropertyFlags memoryProperties, out ulong offset, out VkDeviceMemory mem)
        {
            if (size > Buffer.LargestBufferSize)
            {
                Buffer.LargestBufferSize = size;
            }

            if (size >= Buffer.LargePooledBufferSize)
            {
                offset = 0;
                mem    = VkDeviceMemory.Null;
                Buffer.PoolMissesDueToSize++;
                return(false);
            }
            else if (size >= Buffer.SmallPooledBufferSize)
            {
                if (BigMemoryPool == VkDeviceMemory.Null)
                {
                    AllocatePool(out BigMemoryPool, ref device, ref pDevice, ref memoryProperties, ref memoryRequirements, Buffer.LargePooledBufferCount * Buffer.LargePooledBufferSize);
                    for (ulong i = 0; i < Buffer.LargePooledBufferCount; i++)
                    {
                        FreeBig.Enqueue(i * Buffer.LargePooledBufferSize);
                    }
                }

                if (FreeBig.TryDequeue(out offset))
                {
                    Buffer.CurrentFreeBigPool = FreeBig.Count;
                    mem = BigMemoryPool;
                    return(true);
                }
            }
            else
            {
                if (SmallMemoryPool == VkDeviceMemory.Null)
                {
                    AllocatePool(out SmallMemoryPool, ref device, ref pDevice, ref memoryProperties, ref memoryRequirements, Buffer.SmallPooledBufferCount * Buffer.SmallPooledBufferSize);
                    for (ulong i = 0; i < Buffer.SmallPooledBufferCount; i++)
                    {
                        FreeSmall.Enqueue(i * Buffer.SmallPooledBufferSize);
                    }
                }

                if (FreeSmall.TryDequeue(out offset))
                {
                    Buffer.CurrentFreeSmallPool = FreeSmall.Count;
                    mem = SmallMemoryPool;
                    return(true);
                }
            }

            offset = 0;
            mem    = VkDeviceMemory.Null;
            Buffer.PoolMissesDueToExaustion++;
            return(false);
        }
 public abstract void GetImageMemoryRequirements(VkImage image, out VkMemoryRequirements pMemoryRequirements);
Exemple #21
0
        //VkMemoryPropertyFlagBits.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
        private uint GetMemoryTypeIndex(VkPhysicalDeviceMemoryProperties memoryProperties, VkMemoryRequirements memoryReq, VkMemoryPropertyFlagBits flags)
        {
            uint          result       = 0;
            bool          heapIndexSet = false;
            VkMemoryType *memoryTypes  = (VkMemoryType *)memoryProperties.memoryTypes;

            for (uint i = 0; i < memoryProperties.memoryTypeCount; i++)
            {
                if (((memoryReq.memoryTypeBits >> (int)i) & 1) == 1 &&
                    (memoryTypes[i].propertyFlags & flags) == flags)
                {
                    result       = i;
                    heapIndexSet = true;
                    break;
                }
            }

            if (!heapIndexSet)
            {
                result = memoryTypes[0].heapIndex;
            }

            return(result);
        }
Exemple #22
0
        public unsafe Buffer(
            Device device,
            uint size,
            VkBufferUsageFlags bufferUsageFlags,
            VkMemoryPropertyFlags memoryProperty
            )
        {
            if (size == 0)
            {
                throw new Exception("cannot create buffer with size of zero bytes");
            }

            //make sure buffer supports transfer data to and from buffer
            if ((bufferUsageFlags & VkBufferUsageFlags.TransferSrc) == 0)
            {
                bufferUsageFlags |= VkBufferUsageFlags.TransferSrc;
            }
            if ((bufferUsageFlags & VkBufferUsageFlags.TransferDst) == 0)
            {
                bufferUsageFlags |= VkBufferUsageFlags.TransferDst;
            }

            //store parameter information
            _size           = size;
            _device         = device;
            _bufferUsage    = bufferUsageFlags;
            _memoryProperty = memoryProperty;

            var queueFamilyIndices = new NativeList <uint>();

            foreach (var queueFamily in device.QueueFamilies)
            {
                queueFamilyIndices.Add(queueFamily.Index);
            }

            //buffer create info
            var bufferCreateInfo = new VkBufferCreateInfo
            {
                sType                 = VkStructureType.BufferCreateInfo,
                size                  = size,
                usage                 = bufferUsageFlags,
                sharingMode           = VkSharingMode.Concurrent,
                queueFamilyIndexCount = queueFamilyIndices.Count,
                pQueueFamilyIndices   = (uint *)queueFamilyIndices.Data.ToPointer()
            };

            //setup buffer handler
            VkBuffer buffer;

            if (VulkanNative.vkCreateBuffer(
                    device.Handle,
                    &bufferCreateInfo,
                    null,
                    &buffer
                    ) != VkResult.Success)
            {
                throw new Exception("failed to create vulkan buffer handle");
            }
            _handle = buffer;

            //memory allocation info
            _memoryRequirements = GetMemoryRequirements(device.Handle, buffer);
            var memoryAllocateInfo = new VkMemoryAllocateInfo
            {
                sType           = VkStructureType.MemoryAllocateInfo,
                allocationSize  = _memoryRequirements.size,
                memoryTypeIndex = device.FindMemoryType(
                    _memoryRequirements.memoryTypeBits,
                    _memoryProperty
                    )
            };

            //setup device memory
            VkDeviceMemory deviceMemory;

            if (VulkanNative.vkAllocateMemory(
                    device.Handle,
                    &memoryAllocateInfo,
                    null,
                    &deviceMemory
                    ) != VkResult.Success)
            {
                throw new Exception("failed to allocat device memory");
            }
            _memoryHandle = deviceMemory;

            //bind buffer handle with device memory
            if (VulkanNative.vkBindBufferMemory(
                    device.Handle,
                    buffer,
                    deviceMemory,
                    0
                    ) != VkResult.Success)
            {
                throw new Exception("failed to bind buffer handler to device memory");
            }
        }