Beispiel #1
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 []
                //{

                //},
            });
        }
Beispiel #2
0
        public EffectVariant Initialize(
            IMgDevice device,
            IMgPipelineLayout layout,
            IMgRenderPass renderPass,
            PerVertexInputPipelineState vertexInput,
            EffectVariantOptions options
            )
        {
            using (var vertFs = mPath.OpenVertexShader())
                using (var fragFs = mPath.OpenFragmentShader())
                {
                    var vsCreateInfo = new MgShaderModuleCreateInfo
                    {
                        Code     = vertFs,
                        CodeSize = new UIntPtr((ulong)vertFs.Length),
                    };
                    device.CreateShaderModule(vsCreateInfo, null, out IMgShaderModule vsModule);

                    var fsCreateInfo = new MgShaderModuleCreateInfo
                    {
                        Code     = fragFs,
                        CodeSize = new UIntPtr((ulong)fragFs.Length),
                    };
                    device.CreateShaderModule(fsCreateInfo, null, out IMgShaderModule fsModule);

                    var createInfo = new MgGraphicsPipelineCreateInfo
                    {
                        Stages = new MgPipelineShaderStageCreateInfo[]
                        {
                            new MgPipelineShaderStageCreateInfo
                            {
                                Stage  = MgShaderStageFlagBits.VERTEX_BIT,
                                Module = vsModule,
                                Name   = "vertFunc",
                            },
                            new MgPipelineShaderStageCreateInfo
                            {
                                Stage  = MgShaderStageFlagBits.FRAGMENT_BIT,
                                Module = fsModule,
                                Name   = "fragFunc",
                            },
                        },

                        ColorBlendState = new MgPipelineColorBlendStateCreateInfo
                        {
                            Attachments = new[]
                            {
                                new MgPipelineColorBlendAttachmentState
                                {
                                    ColorWriteMask = MgColorComponentFlagBits.ALL_BITS,
                                    BlendEnable    = false,
                                }
                            },
                        },
                        DepthStencilState = new MgPipelineDepthStencilStateCreateInfo
                        {
                            DepthTestEnable       = true,
                            DepthWriteEnable      = true,
                            DepthCompareOp        = MgCompareOp.LESS_OR_EQUAL,
                            DepthBoundsTestEnable = false,
                            Back = new MgStencilOpState
                            {
                                FailOp    = MgStencilOp.KEEP,
                                PassOp    = MgStencilOp.KEEP,
                                CompareOp = MgCompareOp.ALWAYS,
                            },
                            StencilTestEnable = false,
                            Front             = new MgStencilOpState
                            {
                                FailOp    = MgStencilOp.KEEP,
                                PassOp    = MgStencilOp.KEEP,
                                CompareOp = MgCompareOp.ALWAYS,
                            },
                        },
                        DynamicState = new MgPipelineDynamicStateCreateInfo
                        {
                            DynamicStates = new[]
                            {
                                MgDynamicState.VIEWPORT,
                                MgDynamicState.SCISSOR,
                            }
                        },
                        InputAssemblyState = new MgPipelineInputAssemblyStateCreateInfo
                        {
                            Topology = options.Topology,
                        },
                        Layout           = layout,
                        MultisampleState = new MgPipelineMultisampleStateCreateInfo
                        {
                            RasterizationSamples = MgSampleCountFlagBits.COUNT_1_BIT,
                            SampleMask           = null,
                        },
                        RasterizationState = new MgPipelineRasterizationStateCreateInfo
                        {
                            PolygonMode             = MgPolygonMode.FILL,
                            FrontFace               = options.FrontFace,
                            CullMode                = options.CullMode,
                            DepthClampEnable        = false,
                            RasterizerDiscardEnable = false,
                            DepthBiasEnable         = false,
                            LineWidth               = 1.0f,
                        },
                        RenderPass       = renderPass,
                        VertexInputState = vertexInput.VertexInputState,
                        ViewportState    = null,
                    };

                    var err = device.CreateGraphicsPipelines(null,
                                                             new[] { createInfo }, null, out IMgPipeline[] pPipelines);

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

                    vsModule.DestroyShaderModule(device, null);
                    fsModule.DestroyShaderModule(device, null);

                    return(new EffectVariant
                    {
                        Key = new EffectVariantKey
                        {
                            Definition = vertexInput.VertexMask,
                            Options = EffectVariantEncoder.Encode(options),
                        },
                        Pipeline = pPipelines[0],
                    });
                }
        }