예제 #1
0
        private static List <MgVertexInputAttributeDescription> ExtractAttributeDescriptions(MgOptimizedStorageContainer container, List <GltfMeshAccessor> accessors)
        {
            const MgBufferUsageFlagBits VERT_MASK = MgBufferUsageFlagBits.VERTEX_BUFFER_BIT;
            var inputAttributes = new List <MgVertexInputAttributeDescription>();

            for (var i = 0; i < accessors.Count; i += 1)
            {
                var srcAttribute = accessors[i];
                var dstAttribute = container.Map.Allocations[i];

                if ((dstAttribute.Usage & VERT_MASK) == VERT_MASK)
                {
                    var attribute = new MgVertexInputAttributeDescription
                    {
                        Location = srcAttribute.LocationIndex,
                        Binding  = dstAttribute.BlockIndex,
                        Format   = srcAttribute.Format,
                        Offset   = (uint)dstAttribute.Offset,
                    };

                    inputAttributes.Add(attribute);
                }
            }

            return(inputAttributes);
        }
예제 #2
0
        public BufferInfo(IMgThreadPartition partition, MgBufferUsageFlagBits usage, MgMemoryPropertyFlagBits propertyFlags, uint bufferSize)
        {
            Debug.Assert(partition != null);

            mDevice = partition.Device;
            Debug.Assert(mDevice != null);

            mUsageFlags = usage;

            mMemoryPropertyFlags = propertyFlags;

            var bufferCreateInfo = new MgBufferCreateInfo
            {
                Usage = usage,
                Size  = bufferSize,
            };

            IMgBuffer buffer;

            var device = partition.Device;

            var result = device.CreateBuffer(bufferCreateInfo, null, out buffer);

            Debug.Assert(result == Result.SUCCESS);

            MgMemoryRequirements memReqs;

            device.GetBufferMemoryRequirements(buffer, out memReqs);
            mAlignment  = memReqs.Alignment;
            mBufferSize = memReqs.Size;

            uint memoryTypeIndex;

            partition.GetMemoryType(memReqs.MemoryTypeBits, mMemoryPropertyFlags, out memoryTypeIndex);

            var memAlloc = new MgMemoryAllocateInfo
            {
                MemoryTypeIndex = memoryTypeIndex,
                AllocationSize  = memReqs.Size,
            };

            IMgDeviceMemory deviceMemory;

            result = device.AllocateMemory(memAlloc, null, out deviceMemory);
            Debug.Assert(result == Result.SUCCESS);

            buffer.BindBufferMemory(device, deviceMemory, 0);


            mBuffer       = buffer;
            mDeviceMemory = deviceMemory;

            mDescriptor = new MgDescriptorBufferInfo
            {
                Buffer = mBuffer,
                Offset = 0,
                Range  = mBufferSize,
            };
        }
예제 #3
0
        private MeshDrawCommand[] ExtractDrawCommand(MgOptimizedStorageContainer container, List <GltfMeshAccessor> accessors)
        {
            const MgBufferUsageFlagBits VERT_MASK  = MgBufferUsageFlagBits.VERTEX_BUFFER_BIT;
            const MgBufferUsageFlagBits INDEX_MASK = MgBufferUsageFlagBits.INDEX_BUFFER_BIT;
            var primitives = new Dictionary <uint, MeshDrawCommand>();

            for (var i = 0; i < accessors.Count; i += 1)
            {
                var srcAttribute = accessors[i];
                if (!primitives.TryGetValue(srcAttribute.PrimitiveIndex, out MeshDrawCommand found))
                {
                    found = new MeshDrawCommand
                    {
                        PrimitiveIndex = srcAttribute.PrimitiveIndex,
                        Vertices       = new List <VertexDataBinding>(),
                    };
                    primitives.Add(srcAttribute.PrimitiveIndex, found);
                }

                if ((srcAttribute.Usage & VERT_MASK) == VERT_MASK)
                {
                    var dstAttribute = container.Map.Allocations[i];
                    var dstInstance  = container.Storage.Blocks[dstAttribute.BlockIndex];

                    var vertexInfo = new VertexDataBinding
                    {
                        BlockIndex = dstAttribute.BlockIndex,
                        Buffer     = dstInstance.Buffer,
                        Offset     = dstAttribute.Offset + dstInstance.MemoryOffset,
                    };
                    found.Vertices.Add(vertexInfo);
                }

                if ((srcAttribute.Usage & INDEX_MASK) == INDEX_MASK)
                {
                    var dstAttribute = container.Map.Allocations[i];
                    var dstInstance  = container.Storage.Blocks[dstAttribute.BlockIndex];

                    var indexInfo = new IndexDataBinding
                    {
                        Buffer    = dstInstance.Buffer,
                        IndexType = (srcAttribute.Format == MgFormat.R32_UINT)
                            ? MgIndexType.UINT32
                            : MgIndexType.UINT16,
                        Offset = dstAttribute.Offset + dstInstance.MemoryOffset,
                    };
                    found.IndexBuffer = indexInfo;
                }
            }

            var commands = new MeshDrawCommand[primitives.Count];

            primitives.Values.CopyTo(commands, 0);
            return(commands);
        }
예제 #4
0
        private uint DetermineBufferMemoryType(MgBufferUsageFlagBits usage)
        {
            var flags = MgBufferUsageFlagBits.STORAGE_BUFFER_BIT;

            // 1st precedence
            if ((usage & flags) == flags)
            {
                return(GLMemoryBufferType.SSBO.GetMask());
            }

            flags = MgBufferUsageFlagBits.VERTEX_BUFFER_BIT;
            if ((usage & flags) == flags)
            {
                return(GLMemoryBufferType.VERTEX.GetMask());
            }

            flags = MgBufferUsageFlagBits.INDIRECT_BUFFER_BIT;
            if ((usage & flags) == flags)
            {
                return(GLMemoryBufferType.INDIRECT.GetMask());
            }

            flags = MgBufferUsageFlagBits.UNIFORM_BUFFER_BIT;
            if ((usage & flags) == flags)
            {
                return(GLMemoryBufferType.UNIFORM.GetMask());
            }

            flags = MgBufferUsageFlagBits.INDEX_BUFFER_BIT;
            if ((usage & flags) == flags)
            {
                return(GLMemoryBufferType.INDEX.GetMask());
            }

            flags = MgBufferUsageFlagBits.TRANSFER_DST_BIT;
            if ((usage & flags) == flags)
            {
                return(GLMemoryBufferType.TRANSFER_DST.GetMask());
            }

            flags = MgBufferUsageFlagBits.TRANSFER_SRC_BIT;
            if ((usage & flags) == flags)
            {
                return(GLMemoryBufferType.TRANSFER_SRC.GetMask());
            }
            else
            {
                throw new NotSupportedException("BufferMemoryType not supported");
            }
        }
예제 #5
0
        private MgBufferUsageFlagBits?[] TransformAttributes(MgStorageBlockAllocationInfo[] attributes)
        {
            var unallocatedAttributes = new MgBufferUsageFlagBits?[attributes.Length];

            for (var i = 0; i < unallocatedAttributes.Length; i += 1)
            {
                MgBufferUsageFlagBits original = attributes[i].Usage;
                bool isFound = mLayout.PreTransforms.TryGetValue(
                    original,
                    out MgBufferUsageFlagBits updated);

                unallocatedAttributes[i] = isFound ? updated : original;
            }

            return(unallocatedAttributes);
        }
예제 #6
0
        public void AsStorageBufferUsage()
        {
            var expected = MgBufferUsageFlagBits.STORAGE_BUFFER_BIT;
            var selector = new PerMaterialTextureStorageQuery(
                new MgPhysicalDeviceLimits
            {
                MaxPerStageDescriptorStorageBuffers = 1,
                MaxUniformBufferRange = 100,
                MaxStorageBufferRange = 1000,
            }
                );

            MgBufferUsageFlagBits actual = selector.GetAppropriateBufferUsage();

            Assert.AreEqual(expected, actual);
        }
예제 #7
0
        private static List <MgVertexInputBindingDescription> ExtractBindings(MgOptimizedStorageContainer container, BufferViewInfo[] bufferViews, List <GltfMeshAccessor> accessors)
        {
            var bindings = new List <MgVertexInputBindingDescription>();
            const MgBufferUsageFlagBits VERT_MASK = MgBufferUsageFlagBits.VERTEX_BUFFER_BIT;

            for (var i = 0U; i < container.Storage.Blocks.Length; i += 1)
            {
                var srcBlock = bufferViews[i];
                var dstBlock = container.Storage.Blocks[i];

                if ((dstBlock.Usage & VERT_MASK) == VERT_MASK)
                {
                    var byteStride = 0U;

                    if (srcBlock.ByteStride.HasValue)
                    {
                        byteStride = (uint)srcBlock.ByteStride.Value;
                    }
                    else
                    {
                        foreach (var order in dstBlock.PackingOrder)
                        {
                            var attrIndex    = (int)order;
                            var srcAttribute = accessors[attrIndex];
                            var dstAttribute = container.Map.Allocations[attrIndex];

                            if ((dstAttribute.Usage & VERT_MASK) == VERT_MASK)
                            {
                                byteStride += (uint)(srcAttribute.ElementByteSize * srcAttribute.ElementCount);
                            }
                        }
                    }

                    var binding = new MgVertexInputBindingDescription
                    {
                        Binding   = (uint)bindings.Count,
                        InputRate = MgVertexInputRate.VERTEX,
                        Stride    = byteStride,
                    };
                    bindings.Add(binding);
                }
            }

            return(bindings);
        }
예제 #8
0
        public uint GetElementRange(
            MgBufferUsageFlagBits usage,
            uint texturesPerMaterial,
            uint sizeOfBlock
            )
        {
            var countPerMaxTextures =
                mLimits.MaxPerStageDescriptorSampledImages
                / texturesPerMaterial;

            var maxBufferSize =
                (usage == MgBufferUsageFlagBits.STORAGE_BUFFER_BIT)
                ? mLimits.MaxStorageBufferRange
                : mLimits.MaxUniformBufferRange;

            var countPerBlockSize =
                maxBufferSize / sizeOfBlock;

            return(Math.Min(countPerBlockSize, countPerMaxTextures));
        }
예제 #9
0
 public void BindBufferRange(MgBufferUsageFlagBits usage, int index, int buffer, IntPtr offset, ulong size)
 {
     //  GL.BindBufferRange();
 }
예제 #10
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);
            }
        }