Ejemplo n.º 1
0
        public int Insert(MgStorageBlockAllocationInfo info)
        {
            int count = mItems.Count;

            mItems.Add(info);
            return(count);
        }
Ejemplo n.º 2
0
        private MgOptimizedStorageContainer GenerateMesh(
            glTFLoader.Schema.Gltf model,
            glTFLoader.Schema.Mesh mesh,
            IEffect effect,
            List <byte[]> buffers,
            BufferViewInfo[] bufferViews
            )
        {
            var  shaderLocations = effect.GetShaderAttributeLocations();
            var  accessors       = new List <GltfMeshAccessor>();
            uint primitiveIndex  = 0U;

            foreach (var primitive in mesh.Primitives)
            {
                if (primitive.Indices.HasValue)
                {
                    var accessor = ExtractAccessor(model, primitive.Indices.Value);
                    accessor.PrimitiveIndex = primitiveIndex;
                    accessor.Usage          = MgBufferUsageFlagBits.INDEX_BUFFER_BIT;
                    accessors.Add(accessor);
                }

                foreach (var attr in primitive.Attributes)
                {
                    var locationName  = attr.Key;
                    var accessorIndex = attr.Value;

                    var accessor = ExtractAccessor(model, accessorIndex);
                    accessor.PrimitiveIndex = primitiveIndex;
                    accessor.Usage          = MgBufferUsageFlagBits.VERTEX_BUFFER_BIT;
                    accessor.LocationIndex  = shaderLocations[locationName];
                    accessor.LocationName   = locationName;

                    accessors.Add(accessor);
                }
                primitiveIndex += 1;
            }

            var usedBufferViews  = new bool[bufferViews.Length];
            var blockAllocations = new List <MgStorageBlockAllocationInfo>();

            foreach (var attr in accessors)
            {
                var allocation = new MgStorageBlockAllocationInfo
                {
                    MemoryPropertyFlags = MgMemoryPropertyFlagBits.HOST_COHERENT_BIT,
                    Usage           = attr.Usage,
                    ElementByteSize = attr.ElementByteSize,
                    Size            = (ulong)(attr.NoOfComponents * attr.ElementCount * attr.ElementByteSize),
                };

                if (attr.BufferViewIndex.HasValue)
                {
                    usedBufferViews[attr.BufferViewIndex.Value] = true;
                }

                blockAllocations.Add(allocation);
            }

            var createInfo = new MgOptimizedStorageCreateInfo
            {
                Allocations = blockAllocations.ToArray(),
            };

            var meshData = mBuilder.Build(createInfo);

            var metaData = InitializeMetaData(meshData, usedBufferViews, bufferViews, accessors);

            // copy buffer data into device memory
            CopyBuffersInto(meshData, buffers, bufferViews, accessors);

            return(meshData);
        }
Ejemplo n.º 3
0
        private static int ExtractVertices(uint vertexCount,
                                           MgStorageBlockAllocationRequest request,
                                           MgtfAccessor[] accessors,
                                           MgtfBufferView[] bufferViews,
                                           IMgtfPerVertexDataLocator locator,
                                           out GltfInterleavedOperation[] vertexCopies)
        {
            var totalSize    = 0UL;
            var vertexFields = new int?[]
            {
                locator.Position,
                locator.Normal,
                locator.Tangent,
                locator.TexCoords0,
                locator.TexCoords1,
                locator.Color0,
                locator.Color1,
                locator.Joints0,
                locator.Joints1,
                locator.Weights0,
                locator.Weights1,
            };

            var DEFAULT_PADDING_BYTE_STRIDE = new uint[]
            {
                12U,
                12U,
                16U,
                8U,
                8U,
                16U,
                16U,
                4U,
                4U,
                16U,
                16U,
            };

            var copyOps = new List <GltfInterleavedOperation>();

            var vertexBufferStride = 0U;

            for (var i = 0; i < vertexFields.Length; i += 1)
            {
                var field = vertexFields[i];
                if (field.HasValue)
                {
                    var selected = accessors[field.Value];
                    var op       = GenerateCopyOperation(selected, bufferViews);
                    copyOps.Add(op);
                    vertexBufferStride += op.ByteStride;
                    totalSize          += selected.TotalByteSize;
                }
                else
                {
                    vertexBufferStride += DEFAULT_PADDING_BYTE_STRIDE[i];
                    totalSize          += vertexCount * DEFAULT_PADDING_BYTE_STRIDE[i];
                }
            }

            foreach (var op in copyOps)
            {
                op.DstStride = vertexBufferStride;
            }

            var vertexInfo = new MgStorageBlockAllocationInfo
            {
                MemoryPropertyFlags = MgMemoryPropertyFlagBits.HOST_COHERENT_BIT,
                Usage           = MgBufferUsageFlagBits.VERTEX_BUFFER_BIT,
                ElementByteSize = vertexBufferStride,
                Size            = totalSize,
            };

            vertexCopies = copyOps.ToArray();
            return(request.Insert(vertexInfo));
        }
Ejemplo n.º 4
0
        private static int[] AllocateMaterials(MgtfMaterial[] materials, MgStorageBlockAllocationRequest dynamicRequest, MgPhysicalDeviceLimits limits)
        {
            // materials
            var query        = new PerMaterialTextureStorageQuery(limits);
            var noOfSamplers = query.GetMaxNoOfCombinedImageSamplers();

            const uint PBR_TEXTURES_PER_MATERIALS = 5U;
            var        blockSize = (uint)Marshal.SizeOf(typeof(MaterialUBO));

            const uint HI_RES  = 32U;
            const uint LOW_RES = 16U;

            // GONNA RESERVE 5 BINDINGS SLOTS
            // IN VK, a global binding range is used by all descriptors
            // IN OPENGL/WEBGL, buffer and textures have the own binding range
            // THEREFORE, Mg standard is not to overlap binding values between descriptors
            // OTHERWISE, separate sets implementation (TODO) could be used to handle separate ranges
            const uint NO_OF_RESERVED_BINDINGS = 5U;
            var        range = noOfSamplers - NO_OF_RESERVED_BINDINGS;

            if (noOfSamplers < LOW_RES)
            {
                throw new InvalidOperationException("not enough combined samplers for pbr");
            }

            // pick between hi res and low res
            bool isHighRes      = (noOfSamplers >= HI_RES);
            uint bindableImages = isHighRes ? 32U : 16U;

            var elementRange = query.GetElementRange(
                MgBufferUsageFlagBits.UNIFORM_BUFFER_BIT,
                PBR_TEXTURES_PER_MATERIALS,
                blockSize);

            if (isHighRes)
            {
                // floor(no_of_samplers - reserved_slots / textures_per_mat) = floor((32 - 5)/5) = 5
                if (elementRange < 5U)
                {
                    throw new InvalidOperationException("hi res not applicable");
                }
                elementRange = 5U;
            }
            else
            {
                // floor(no_of_samplers - reserved_slots / textures_per_mat) = floor((16 - 5)/5) = 2
                if (elementRange < 2U)
                {
                    throw new InvalidOperationException("low res not applicable");
                }
                elementRange = 2U;
            }

            var noOfAllocations = (materials.Length / elementRange);

            noOfAllocations += (materials.Length % elementRange == 0) ? 0 : 1;

            var info = new MgStorageBlockAllocationInfo
            {
                Usage = MgBufferUsageFlagBits.UNIFORM_BUFFER_BIT,
                MemoryPropertyFlags = MgMemoryPropertyFlagBits.HOST_VISIBLE_BIT,
                Size = elementRange * blockSize,
            };

            var materialIndices = new int[noOfAllocations];

            for (var i = 0; i < noOfAllocations; i += 1)
            {
                materialIndices[i] = dynamicRequest.Insert(info);
            }
            return(materialIndices);
        }
Ejemplo n.º 5
0
        private static GltfInterleavedOperation[] GenerateCopyOps(uint vertexCount, MgStorageBlockAllocationRequest request, GltfAccessor[] accessors, GltfBufferView[] bufferViews, IPerVertexDataLocator locator, GltfPrimitiveStorageLocation finalLocation)
        {
            var totalSize    = 0UL;
            var vertexFields = new int?[]
            {
                locator.Position,
                locator.Normal,
                locator.Tangent,
                locator.TexCoords0,
                locator.TexCoords1,
                locator.Color0,
                locator.Color1,
                locator.Joints0,
                locator.Joints1,
                locator.Weights0,
                locator.Weights1,
            };

            var paddingByteStride = new uint[]
            {
                12U,
                12U,
                16U,
                8U,
                8U,
                16U,
                16U,
                4U,
                4U,
                16U,
                16U,
            };

            var copyOps = new List <GltfInterleavedOperation>();

            var vertexBufferStride = 0U;

            for (var i = 0; i < vertexFields.Length; i += 1)
            {
                var field = vertexFields[i];
                if (field.HasValue)
                {
                    var selected = accessors[field.Value];
                    var op       = CreateCopyOp(copyOps, selected, bufferViews);
                    vertexBufferStride += op.ByteStride;
                    totalSize          += selected.TotalByteSize;
                }
                else
                {
                    vertexBufferStride += paddingByteStride[i];
                    totalSize          += vertexCount * paddingByteStride[i];
                }
            }

            foreach (var op in copyOps)
            {
                op.DstStride = vertexBufferStride;
            }

            var vertexInfo = new MgStorageBlockAllocationInfo
            {
                MemoryPropertyFlags = MgMemoryPropertyFlagBits.HOST_COHERENT_BIT,
                Usage           = MgBufferUsageFlagBits.VERTEX_BUFFER_BIT,
                ElementByteSize = vertexBufferStride,
                Size            = totalSize,
            };

            finalLocation.Vertex = request.Insert(vertexInfo);

            if (locator.Indices.HasValue)
            {
                var selected = accessors[locator.Indices.Value];
                var op       = CreateCopyOp(copyOps, selected, bufferViews);
                op.DstStride = selected.ElementByteSize;

                var indexInfo = new MgStorageBlockAllocationInfo
                {
                    MemoryPropertyFlags = MgMemoryPropertyFlagBits.HOST_COHERENT_BIT,
                    Usage           = MgBufferUsageFlagBits.INDEX_BUFFER_BIT,
                    Size            = selected.TotalByteSize,
                    ElementByteSize = selected.ElementByteSize,
                };

                finalLocation.Index = request.Insert(indexInfo);
            }

            return(copyOps.ToArray());
        }
Ejemplo n.º 6
0
        public GltfScene Load(IMgDevice device, IMgEffectFramework framework, string modelFilePath)
        {
            var model   = Interface.LoadModel(modelFilePath);
            var baseDir = Path.GetDirectoryName(modelFilePath);

            var buffers = ExtractBuffers(model, baseDir);

            var request = new MgStorageBlockAllocationRequest();

            const int MAX_NO_OF_CAMERAS    = 1;
            var       cameraAllocationInfo = new GltfBucketAllocationInfo <CameraUBO>
            {
                BucketSize          = MAX_NO_OF_CAMERAS,
                Usage               = MgBufferUsageFlagBits.UNIFORM_BUFFER_BIT,
                MemoryPropertyFlags = MgMemoryPropertyFlagBits.HOST_VISIBLE_BIT,
            };

            var cameraSlots = cameraAllocationInfo.Prepare(model.Cameras != null ? model.Cameras.Length : 0, request);

            var accessors = ExtractAccessors(model);

            var bufferViews = ExtractBufferViews(model);

            const int MAX_NO_OF_MATERIALS = 16;

            var materialAllocationInfo = new GltfBucketAllocationInfo <MaterialUBO>
            {
                BucketSize          = MAX_NO_OF_MATERIALS,
                Usage               = MgBufferUsageFlagBits.UNIFORM_BUFFER_BIT,
                MemoryPropertyFlags = MgMemoryPropertyFlagBits.HOST_VISIBLE_BIT,
            };

            var images = ExtractImages(baseDir, model.Images, bufferViews, buffers);

            var samplers = ExtractSamplers(device, model.Samplers);

            const int MAX_NO_OF_LIGHTS = 4;

            const int MAX_NO_OF_TEXTURES = 16;
            // var textures = AllocateTextures(MAX_NO_OF_TEXTURES, model.Textures, images);

            var materialSlots = materialAllocationInfo.Prepare(model.Materials != null ? model.Materials.Length : 0, request);

            var materialChunks = ExtractMaterials(materialSlots.BucketSize, model.Materials);

            var meshes = ExtractMeshes(model, accessors, materialSlots);

            PadMeshes(meshes);

            var meshLocations = AllocateMeshes(request, meshes, accessors, bufferViews);

            var nodes = ExtractNodes(model, cameraSlots);

            var pDsCreateInfo = new MgDescriptorSetLayoutCreateInfo
            {
                Bindings = new[]
                {
                    // CAMERA
                    new MgDescriptorSetLayoutBinding
                    {
                        Binding         = 0,
                        DescriptorType  = MgDescriptorType.UNIFORM_BUFFER,
                        DescriptorCount = MAX_NO_OF_CAMERAS,
                        StageFlags      = MgShaderStageFlagBits.VERTEX_BIT,
                    },
                    // LIGHTS
                    new MgDescriptorSetLayoutBinding
                    {
                        Binding         = 1,
                        DescriptorType  = MgDescriptorType.UNIFORM_BUFFER,
                        DescriptorCount = MAX_NO_OF_LIGHTS,
                        StageFlags      = MgShaderStageFlagBits.VERTEX_BIT,
                    },
                    // MATERIALS
                    new MgDescriptorSetLayoutBinding
                    {
                        Binding         = 2,
                        DescriptorType  = MgDescriptorType.UNIFORM_BUFFER,
                        DescriptorCount = MAX_NO_OF_MATERIALS,
                        StageFlags      = MgShaderStageFlagBits.FRAGMENT_BIT,
                    },
                    // TEXTURES
                    new MgDescriptorSetLayoutBinding
                    {
                        Binding         = 3,
                        DescriptorType  = MgDescriptorType.COMBINED_IMAGE_SAMPLER,
                        DescriptorCount = MAX_NO_OF_TEXTURES,
                        StageFlags      = MgShaderStageFlagBits.FRAGMENT_BIT,
                    },
                }
            };

            var err = device.CreateDescriptorSetLayout(pDsCreateInfo, null, out IMgDescriptorSetLayout dsLayout);

            if (err != Result.SUCCESS)
            {
                throw new InvalidOperationException("CreatePipelineLayout failed");
            }

            var pCreateInfo = new MgPipelineLayoutCreateInfo
            {
                SetLayouts = new[]
                {
                    dsLayout,
                }
            };

            err = device.CreatePipelineLayout(pCreateInfo, null, out IMgPipelineLayout layout);
            if (err != Result.SUCCESS)
            {
                throw new InvalidOperationException("CreatePipelineLayout failed");
            }

            var pbrEffect  = new EffectPipelineDictionary();
            var pbrFactory = new PbrEffectVariantFactory(mPbrEffectPath);

            var instanceDrawGroups = new Dictionary <GltfInstancedGroupKey, GltfInstanceDrawGroup>();

            foreach (var node in nodes)
            {
                if (node.Mesh.HasValue)
                {
                    var options = new EffectVariantOptions
                    {
                    };

                    var meshIndex = node.Mesh.Value;
                    var mesh      = meshes[meshIndex];

                    options.FrontFace =
                        node.IsMirrored
                        ? MgFrontFace.CLOCKWISE
                        : MgFrontFace.COUNTER_CLOCKWISE;

                    foreach (var primitive in mesh.Primitives)
                    {
                        options.Topology = primitive.Topology;

                        var materialItem = materialChunks[primitive.Material.BucketIndex].Items[primitive.Material.Offset];

                        options.CullMode =
                            materialItem.DoubleSided
                            ? MgCullModeFlagBits.NONE
                            : MgCullModeFlagBits.BACK_BIT;

                        var key = new EffectVariantKey
                        {
                            Definition = PerVertexDefinitionEncoder.Encode(primitive.FinalDefinition),
                            Options    = EffectVariantEncoder.Encode(options),
                        };

                        if (!pbrEffect.TryGetValue(key, out EffectVariant found))
                        {
                            var vertexInput = new PerVertexInputPipelineState(primitive.FinalDefinition);
                            found = pbrFactory.Initialize(device, layout, framework.Renderpass, vertexInput, options);

                            pbrEffect.Add(key, found);
                        }

                        AppendToGroup(instanceDrawGroups, node, meshIndex, primitive, key, found);
                    }
                }
            }

            var stride = Marshal.SizeOf(typeof(PerInstance));

            var perInstances = new List <GltfInstanceRenderGroup>();

            foreach (var group in instanceDrawGroups.Values)
            {
                var slotInfo = new MgStorageBlockAllocationInfo
                {
                    MemoryPropertyFlags = MgMemoryPropertyFlagBits.HOST_VISIBLE_BIT,
                    Usage           = MgBufferUsageFlagBits.VERTEX_BUFFER_BIT,
                    ElementByteSize = (uint)stride,
                    Size            = (ulong)(group.Members.Count * stride),
                };

                var instanceGroup = new GltfInstanceRenderGroup
                {
                    Variant      = group.Variant,
                    StorageIndex = request.Insert(slotInfo),
                    Members      = group.Members.ToArray(),
                };
                perInstances.Add(instanceGroup);
            }

            var storage = mBuilder.Build(
                new MgOptimizedStorageCreateInfo
            {
                Allocations = request.ToArray()
            }
                );

            // MAP DATA

            var finalMaterials = new List <GltfMaterialInfo>();

            for (var i = 0; i < materialChunks.Length; i += 1)
            {
                var slot  = materialSlots.Slots[i];
                var chunk = materialChunks[i];
                for (var j = 0; j < chunk.Items.Length; j += 1)
                {
                    var values = chunk.Items[j];
                    var mat    = new GltfMaterialInfo
                    {
                        StorageIndex = slot,

                        BucketIndex = i,
                        SetOffset   = j,
                        Values      = values,
                    };
                }
            }

            return(new GltfScene
            {
                //Cameras = new []
                //{

                //},
                DescriptorSets = new IMgDescriptorSet[]
                {
                },
                Effects = new []
                {
                    new Effect
                    {
                        DescriptorSetLayout = dsLayout,
                        Layout = layout,
                        Variants = pbrEffect,
                    }
                },
                //Meshes = new[]
                //{

                //},
                Materials = finalMaterials.ToArray(),
                //Nodes = new []
                //{

                //},
                PerInstances = perInstances.ToArray(),
                Samplers = samplers,
                Storage = storage,
                //Textures = new []
                //{

                //},
            });
        }