public void Prepare(IMgGraphicsConfiguration configuration, IMgGraphicsDevice screen) { var loader = new Loader(); var dataLoader = new DataLoader(); var device = configuration.Device; using (var fs = File.Open("Data/Triangle.gltf", FileMode.Open)) { // load model file var model = glTFLoader.Interface.LoadModel(fs); // load meta data var metaData = loader.LoadMetaData(model); // load data var data = dataLoader.LoadData(".", model); var staticRequest = new MgStorageBlockAllocationRequest(); // allocate partitions for static data // mesh var meshLocations = AllocateMeshes(staticRequest, metaData.Meshes, metaData.Accessors, metaData.BufferViews); var meshPrimitives = ExtractMeshPrimitives(metaData.Materials, out MgtfMaterial[] sceneMaterials, metaData.Meshes, meshLocations); // images var images = ExamineImages(data.Images, data.Buffers); // initialize static data storage var staticCreateInfo = new MgOptimizedStorageCreateInfo { Allocations = staticRequest.ToArray(), }; mStaticStorage = mBuilder.Build(staticCreateInfo); // build static artifacts // render target // descriptor set layout + pipeline layout var pass = new ScenePass { RenderTarget = screen, Effects = new[] { new ScenePassEffect { Factory = mPbrFactory, EffectLayout = mPbrFactory.CreateEffectLayout(configuration.Device), } } }; pass.Initialize( configuration.Device, meshPrimitives, sceneMaterials); // allocate dynamic data var dynamicRequest = new MgStorageBlockAllocationRequest(); var limits = new MgPhysicalDeviceLimits(); var worldData = AllocateWorldData(dynamicRequest, limits.MaxUniformBufferRange); var storageIndices = AllocateMaterials(sceneMaterials, dynamicRequest, limits); // per instance data // build dynamic artifacts // semaphores // fences // descriptor sets // initialize dynamic data storage // copy data across // buffers // images // map dynamic data // build command buffers } }
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); }
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 [] //{ //}, }); }