Example #1
0
        private MgStorageBlockInfo[] SubdivideByMemoryPropertyFlags(MgStorageBlockInfo sector, MgStorageBlockAllocationInfo[] allocations)
        {
            // EXACT MATCH ONLY
            var groups = new Dictionary <MgMemoryPropertyFlagBits, MgStorageBlockInfo>();

            foreach (var attr in sector.Attributes)
            {
                var allocation = allocations[attr.Index];
                MgStorageBlockInfo found;
                if (!groups.TryGetValue(allocation.MemoryPropertyFlags, out found))
                {
                    found = new MgStorageBlockInfo
                    {
                        Usage      = attr.Usage,
                        Attributes = new List <MgStorageBlockAttribute>(),
                    };
                    groups.Add(allocation.MemoryPropertyFlags, found);
                }
                found.Attributes.Add(attr);
            }

            var noOfGroups = groups.Keys.Count;
            var segments   = new MgStorageBlockInfo[noOfGroups];

            groups.Values.CopyTo(segments, 0);
            return(segments);
        }
Example #2
0
        private MgStorageBlockInfo[] SplitToSingleBuffers(MgStorageBlockInfo second)
        {
            var slices = new List <MgStorageBlockInfo>();

            foreach (var attr in second.Attributes)
            {
                var slice = new MgStorageBlockInfo
                {
                    Usage      = attr.Usage,
                    Attributes = new List <MgStorageBlockAttribute>(),
                };
                slice.Attributes.Add(attr);
                slices.Add(slice);
            }
            return(slices.ToArray());
        }
Example #3
0
        private void OntoFinalChance(List <MgStorageBufferInstance> output, MgStorageBlockInfo second, MgOptimizedStorageCreateInfo createInfo)
        {
            var individuals = SplitToSingleBuffers(second);

            foreach (var single in individuals)
            {
                if (DoPack(single, createInfo, out MgStorageBufferInstance thirdOutput))
                {
                    output.Add(thirdOutput);
                }
                else
                {
                    throw new InvalidOperationException("Cannot create buffer for MgOptimizedMesh");
                }
            }
        }
Example #4
0
        private void OntoSecondChance(List <MgStorageBufferInstance> output, MgStorageBlockInfo sector, MgOptimizedStorageCreateInfo createInfo)
        {
            MgStorageBlockInfo[] slices = SubdivideByMemoryPropertyFlags(sector, createInfo.Allocations);

            foreach (var second in slices)
            {
                if (DoPack(second, createInfo, out MgStorageBufferInstance secondOutput))
                {
                    output.Add(secondOutput);
                }
                else
                {
                    OntoFinalChance(output, second, createInfo);
                }
            }
        }
Example #5
0
        public MgStorageBlockInfo[] Setup(MgStorageBlockAllocationInfo[] attributes)
        {
            var layouts = new List <MgStorageBlockInfo>();

            MgBufferUsageFlagBits?[] unallocatedAttributes = TransformAttributes(attributes);

            foreach (var combination in mLayout.Combinations)
            {
                MgStorageBlockInfo currentLayout = null;
                for (var i = 0U; i < unallocatedAttributes.Length; i += 1)
                {
                    var attr = unallocatedAttributes[i];

                    if (attr.HasValue)
                    {
                        var mask = (attr.Value & combination.Usage);
                        if (mask == attr.Value)
                        {
                            MgStorageBlockInfo destination = null;

                            if (currentLayout == null)
                            {
                                currentLayout = new MgStorageBlockInfo
                                {
                                    Usage      = mask,
                                    Attributes = new List <MgStorageBlockAttribute>(),
                                };
                                layouts.Add(currentLayout);
                                destination = currentLayout;
                            }
                            else
                            {
                                // CREATE ADDITIONAL BUFFER IF NEEDED
                                if ((attr.Value & combination.SeparateBlockRequired) == attr.Value
                                    // IF CURRENT LAYOUT ALREADY HAS OCCUPIED, THEN CREATE NEW SEGMENT
                                    && (currentLayout.Usage & attr.Value) == attr.Value)
                                {
                                    var temp = new MgStorageBlockInfo
                                    {
                                        Usage      = mask,
                                        Attributes = new List <MgStorageBlockAttribute>(),
                                    };
                                    layouts.Add(temp);
                                    destination = temp;
                                }
                                else
                                {
                                    // APPEND ATTRIBUTE
                                    currentLayout.Usage |= attr.Value;
                                    // currentBuffer.RequestedSize += attr.Size;
                                    destination = currentLayout;
                                }
                            }

                            var location = new MgStorageBlockAttribute
                            {
                                Index = i,
                                Usage = attr.Value,
                            };
                            destination.Attributes.Add(location);

                            // REMOVE attributes
                            unallocatedAttributes[i] = null;
                        }
                    }
                }
            }
            return(layouts.ToArray());
        }
Example #6
0
        private bool DoPack(MgStorageBlockInfo sector, MgOptimizedStorageCreateInfo createInfo, out MgStorageBufferInstance instance)
        {
            MgBufferUsageFlagBits    bufferUsage            = 0;
            MgMemoryPropertyFlagBits deviceMemoryProperties = 0;

            var sortedList = new SortedDictionary <SortedKey, uint>();

            foreach (var attr in sector.Attributes)
            {
                bufferUsage            |= attr.Usage;
                deviceMemoryProperties |= createInfo.Allocations[attr.Index].MemoryPropertyFlags;

                var firstGroup = 0U;
                for (var i = 0U; i < mPackingOrder.Length; i += 1)
                {
                    firstGroup = i;
                    var first = (mPackingOrder[i] & createInfo.Allocations[attr.Index].Usage) > 0;
                    if (first)
                    {
                        break;
                    }
                }

                Debug.Assert(firstGroup <= mPackingOrder.Length);

                var key = new SortedKey
                {
                    Group    = firstGroup,
                    SubOrder = attr.Index,
                };
                sortedList.Add(key, attr.Index);
            }

            ulong overallSize = 0;

            var pCreateInfo = new MgBufferCreateInfo
            {
                SharingMode        = createInfo.SharingMode,
                QueueFamilyIndices = createInfo.QueueFamilyIndices,
                Size  = 0,
                Usage = bufferUsage,
            };

            // The alignment member is identical for all VkBuffer objects created with the same combination of values
            // for the usage and flags members in the VkBufferCreateInfo structure passed to vkCreateBuffer.

            var err = mConfiguration.Device.CreateBuffer(pCreateInfo, null, out IMgBuffer pZeroBuffer);

            if (err != Result.SUCCESS)
            {
                instance = null;
                return(false);
            }

            mConfiguration.Device.GetBufferMemoryRequirements(pZeroBuffer, out MgMemoryRequirements pZeroMemReqs);
            pZeroBuffer.DestroyBuffer(mConfiguration.Device, null);

            var requiredAlignment = pZeroMemReqs.Alignment;

            var mappings = new List <MgStorageBufferOffset>();

            foreach (var element in sortedList.Values)
            {
                var attr = createInfo.Allocations[element];

                var mapping = new MgStorageBufferOffset
                {
                    Index  = element,
                    Offset = UpperBounded(overallSize, requiredAlignment),
                    Size   = attr.Size,
                    Usage  = attr.Usage,
                };
                mappings.Add(mapping);

                overallSize = mapping.Offset + mapping.Size;
            }

            // Real memory allocation
            pCreateInfo.Size = overallSize;

            err = mConfiguration.Device.CreateBuffer(pCreateInfo, null, out IMgBuffer pBuffer);
            if (err != Result.SUCCESS)
            {
                instance = null;
                return(false);
            }

            mConfiguration.Device.GetBufferMemoryRequirements(pBuffer, out MgMemoryRequirements pMemReqs);

            if (mConfiguration.MemoryProperties.GetMemoryType(pMemReqs.MemoryTypeBits, deviceMemoryProperties, out uint typeIndex))
            {
                instance = new MgStorageBufferInstance
                {
                    Buffer = pBuffer,
                    Usage  = bufferUsage,
                    MemoryPropertyFlags = deviceMemoryProperties,
                    TypeIndex           = typeIndex,
                    AllocationSize      = pMemReqs.Size,
                    Mappings            = mappings.ToArray(),
                };
                return(true);
            }
            else
            {
                // CLEAN UP
                pBuffer.DestroyBuffer(mConfiguration.Device, null);
                instance = null;
                return(false);
            }
        }