public EffectLayout CreateEffectLayout(IMgDevice device) { var pDsCreateInfo = new MgDescriptorSetLayoutCreateInfo { Bindings = new[] { // WORLD DATA // CAMERAS // LIGHTS new MgDescriptorSetLayoutBinding { Binding = 0, DescriptorType = MgDescriptorType.UNIFORM_BUFFER, DescriptorCount = 1, StageFlags = MgShaderStageFlagBits.VERTEX_BIT, }, // MATERIALS new MgDescriptorSetLayoutBinding { Binding = 1, DescriptorType = MgDescriptorType.UNIFORM_BUFFER, DescriptorCount = mSettings.NoOfMaterialsPerGroup, StageFlags = MgShaderStageFlagBits.FRAGMENT_BIT, }, // TEXTURES new MgDescriptorSetLayoutBinding { Binding = 5, DescriptorType = MgDescriptorType.COMBINED_IMAGE_SAMPLER, DescriptorCount = mSettings.NoOfTexturesPerGroup, StageFlags = MgShaderStageFlagBits.FRAGMENT_BIT, }, } }; var err = device.CreateDescriptorSetLayout(pDsCreateInfo, null, out IMgDescriptorSetLayout dsLayout); if (err != Result.SUCCESS) { throw new InvalidOperationException("CreateDescriptorSetLayout 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"); } return(new EffectLayout(dsLayout, layout)); }
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 [] //{ //}, }); }