Ejemplo n.º 1
0
        private glTFLoader.Schema.Image GetImageFromFileText(string fileName)
        {
            byte[] imageBytes = GetImageBytesFromFile(fileName);

            var textureBuffer = new glTFLoader.Schema.Buffer()
            {
                Uri        = Constants.TextBufferHeader + Convert.ToBase64String(imageBytes),
                ByteLength = imageBytes.Length,
            };

            int textureBufferIdx = dummy.Buffers.AddAndReturnIndex(textureBuffer);

            var textureBufferView = new glTFLoader.Schema.BufferView()
            {
                Buffer     = textureBufferIdx,
                ByteOffset = 0,
                ByteLength = textureBuffer.ByteLength,
            };
            int textureBufferViewIdx = dummy.BufferViews.AddAndReturnIndex(textureBufferView);

            return(new glTFLoader.Schema.Image()
            {
                BufferView = textureBufferViewIdx,
                MimeType = glTFLoader.Schema.Image.MimeTypeEnum.image_png,
            });
        }
Ejemplo n.º 2
0
        private int CreateBufferView(string name, out Schema.BufferView bufferView)
        {
            bufferView      = CreateInstance <Schema.BufferView>();
            bufferView.Name = name;
            var bufferViewIndex = bufferViews.Count();

            bufferViews.Add(bufferView);
            return(bufferViewIndex);
        }
Ejemplo n.º 3
0
        private void InitBufferViews()
        {
            _indicesBv        = new gltf.BufferView();
            _indicesBv.Buffer = 0;
            _indicesBv.Target = gltf.BufferView.TargetEnum.ELEMENT_ARRAY_BUFFER;
            _bufferViews.Add(_indicesBv);

            _coordinatesBv            = new gltf.BufferView();
            _coordinatesBv.Buffer     = 0;
            _coordinatesBv.Target     = gltf.BufferView.TargetEnum.ARRAY_BUFFER;
            _coordinatesBv.ByteStride = 12; // todo: what is this number?
            _bufferViews.Add(_coordinatesBv);
        }
Ejemplo n.º 4
0
        private void InitBufferViews()
        {
            _indicesBv        = new gltf.BufferView();
            _indicesBv.Buffer = 0;
            _indicesBv.Target = gltf.BufferView.TargetEnum.ELEMENT_ARRAY_BUFFER;
            _bufferViews.Add(_indicesBv);

            _coordinatesBv            = new gltf.BufferView();
            _coordinatesBv.Buffer     = 0;
            _coordinatesBv.Target     = gltf.BufferView.TargetEnum.ARRAY_BUFFER;
            _coordinatesBv.ByteStride = 12; // distance in bytes from one element to the next. Thanks to @tmarti
            _bufferViews.Add(_coordinatesBv);
        }
Ejemplo n.º 5
0
        private void WriteBufferView(Schema.BufferView bufferView, BinaryData binaryData, Action <int> writeData)
        {
            binaryData.Writer.Align(4);

            int byteOffset = (int)binaryData.Writer.BaseStream.Position;

            writeData(byteOffset);

            int byteLength = (int)binaryData.Writer.BaseStream.Position - byteOffset;

            bufferView.Buffer     = binaryDataToBufferIndex[binaryData];
            bufferView.ByteOffset = byteOffset;
            bufferView.ByteLength = byteLength;
        }
Ejemplo n.º 6
0
        public Image[] LoadImages()
        {
            if (gltf.Images == null)
            {
                return new Image[] {}
            }
            ;

            List <Image> textures = new List <Image> ();

            foreach (GL.Image img in gltf.Images)
            {
                Image vkimg = null;

                string imgName = img.Name;

                if (img.BufferView != null)                  //load image from gltf buffer view
                {
                    GL.BufferView bv = gltf.BufferViews[(int)img.BufferView];
                    EnsureBufferIsLoaded(bv.Buffer);
                    vkimg = Image.Load(dev, transferQ, cmdPool, bufferHandles[bv.Buffer].AddrOfPinnedObject() + bv.ByteOffset, (ulong)bv.ByteLength);
                }
                else if (img.Uri.StartsWith("data:", StringComparison.Ordinal))                     //load base64 encoded image
                {
                    Debug.WriteLine("loading embedded image {0} : {1}", img.Name, img.MimeType);
                    vkimg = Image.Load(dev, transferQ, cmdPool, glTFLoader.loadDataUri(img));
                }
                else
                {
                    Debug.WriteLine("loading image {0} : {1} : {2}", img.Name, img.MimeType, img.Uri);                     //load image from file path in uri
                    vkimg    = Image.Load(dev, transferQ, cmdPool, Path.Combine(baseDirectory, img.Uri));
                    imgName += ";" + img.Uri;
                }

                vkimg.CreateView();
                vkimg.CreateSampler();
                vkimg.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;

                vkimg.SetName(imgName);
                vkimg.Descriptor.imageView.SetDebugMarkerName(dev, "imgView " + imgName);
                vkimg.Descriptor.sampler.SetDebugMarkerName(dev, "sampler " + imgName);

                textures.Add(vkimg);
            }
            return(textures.ToArray());
        }
Ejemplo n.º 7
0
        private glTFLoader.Schema.Image GetImageFromFileBinary(string fileName)
        {
            byte[] imageBytes       = GetImageBytesFromFile(fileName);
            int    imageBytesOffset = (int)binaryBuffer.Count;

            binaryBuffer.AddRange(imageBytes);

            var textureBufferView = new glTFLoader.Schema.BufferView()
            {
                Buffer     = 0,
                ByteOffset = imageBytesOffset,
                ByteLength = imageBytes.Length,
            };
            int textureBufferViewIdx = dummy.BufferViews.AddAndReturnIndex(textureBufferView);

            return(new glTFLoader.Schema.Image()
            {
                BufferView = textureBufferViewIdx,
                MimeType = glTFLoader.Schema.Image.MimeTypeEnum.image_png,
            });
        }
Ejemplo n.º 8
0
		///// <summary>
		///// build texture array
		///// </summary>
		///// <returns>The images.</returns>
		///// <param name="textureSize">Uniformized Texture size for all images</param>
		public void BuildTexArray (ref Image texArray, uint firstImg = 0) {
			int texDim = (int)texArray.CreateInfo.extent.width;

			PrimaryCommandBuffer cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);
			texArray.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, 
						VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.Transfer);
			transferQ.EndSubmitAndWait (cmd, true);
			
			VkImageBlit imageBlit = new VkImageBlit {
				srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1, 0),
				dstOffsets_1 = new VkOffset3D (texDim, texDim, 1)
			};

			for (int l = 0; l < gltf.Images.Length; l++) {
				GL.Image img = gltf.Images[l];
				Image vkimg = null;

				if (img.BufferView != null) {//load image from gltf buffer view
					GL.BufferView bv = gltf.BufferViews[(int)img.BufferView];
					ensureBufferIsLoaded (bv.Buffer);
					vkimg = Image.Load (dev, loadedBuffers[bv.Buffer].Slice (bv.ByteOffset), (ulong)bv.ByteLength, VkImageUsageFlags.TransferSrc);
				} else if (img.Uri.StartsWith ("data:", StringComparison.Ordinal)) {//load base64 encoded image
					Debug.WriteLine ("loading embedded image {0} : {1}", img.Name, img.MimeType);
					vkimg = Image.Load (dev, glTFLoader.loadDataUri (img), VkImageUsageFlags.TransferSrc);
				} else {
					Debug.WriteLine ("loading image {0} : {1} : {2}", img.Name, img.MimeType, img.Uri);//load image from file path in uri
					vkimg = Image.Load (dev, Path.Combine (baseDirectory, img.Uri), VkImageUsageFlags.TransferSrc);
				}

				imageBlit.srcOffsets_1 = new VkOffset3D ((int)vkimg.CreateInfo.extent.width, (int)vkimg.CreateInfo.extent.height, 1);
				imageBlit.dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1, 0, (uint)l + firstImg);

				cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);

				vkimg.SetLayout (cmd, VkImageAspectFlags.Color,
						VkAccessFlags.HostWrite, VkAccessFlags.TransferRead,
						VkImageLayout.Undefined, VkImageLayout.TransferSrcOptimal,
						VkPipelineStageFlags.Host, VkPipelineStageFlags.Transfer);

				Vk.vkCmdBlitImage (cmd.Handle, vkimg.Handle, VkImageLayout.TransferSrcOptimal,
					texArray.Handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear);
				
				transferQ.EndSubmitAndWait (cmd, true);								

				vkimg.Dispose ();
			}

			cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);

			uint imgCount = (uint)gltf.Images.Length;
			VkImageSubresourceRange mipSubRange = new VkImageSubresourceRange (VkImageAspectFlags.Color, 0, 1, firstImg, imgCount);

			for (int i = 1; i < texArray.CreateInfo.mipLevels; i++) {
				imageBlit = new VkImageBlit {
					srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, imgCount, (uint)i - 1, firstImg),
					srcOffsets_1 = new VkOffset3D ((int)texDim >> (i - 1), (int)texDim >> (i - 1), 1),
					dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, imgCount, (uint)i, firstImg),
					dstOffsets_1 = new VkOffset3D ((int)texDim >> i, (int)texDim >> i, 1)
				};

				texArray.SetLayout (cmd,
					VkAccessFlags.TransferWrite, VkAccessFlags.TransferRead,
					VkImageLayout.TransferDstOptimal, VkImageLayout.TransferSrcOptimal, mipSubRange,
					VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);

				Vk.vkCmdBlitImage (cmd.Handle, texArray.Handle, VkImageLayout.TransferSrcOptimal,
					texArray.Handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear);
				texArray.SetLayout (cmd, VkImageLayout.TransferSrcOptimal, VkImageLayout.ShaderReadOnlyOptimal, mipSubRange,
					VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader);

				mipSubRange.baseMipLevel = (uint)i;
			}
			mipSubRange.baseMipLevel = texArray.CreateInfo.mipLevels - 1;
			texArray.SetLayout (cmd, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal, mipSubRange,
				VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader);

			cmd.End ();
			transferQ.Submit (cmd);
			transferQ.WaitIdle ();
			cmd.Free ();
		}
Ejemplo n.º 9
0
		//TODO: some buffer data are reused between primitives, and I duplicate the datas
		//buffers must be constructed without duplications
		public Mesh[] LoadMeshes<TVertex> (VkIndexType indexType, Buffer vbo, ulong vboOffset, Buffer ibo, ulong iboOffset) {
			ulong vCount, iCount;
			VkIndexType idxType;

			GetVertexCount (out vCount, out iCount, out idxType);

			int vertexByteSize = Marshal.SizeOf<TVertex> ();
			ulong vertSize = vCount * (ulong)vertexByteSize;
			ulong idxSize = iCount * (indexType == VkIndexType.Uint16 ? 2ul : 4ul);
			ulong size = vertSize + idxSize;

			int vertexCount = 0, indexCount = 0;
			int autoNamedMesh = 1;

			meshes = new List<Mesh> ();

			using (HostBuffer stagging = new HostBuffer (dev, VkBufferUsageFlags.TransferSrc, size)) {
				stagging.Map ();

				unsafe {

					Span<byte> stagVertPtrInit = new Span<byte>(stagging.MappedData.ToPointer (), (int)vertSize);
					Span<byte> stagIdxPtrInit = new Span<byte>((byte*)stagging.MappedData.ToPointer() + vertSize, (int)idxSize);
					Span<byte> stagVertPtr = stagVertPtrInit, stagIdxPtr = stagIdxPtrInit;

					foreach (GL.Mesh mesh in gltf.Meshes) {

						string meshName = mesh.Name;
						if (string.IsNullOrEmpty (meshName)) {
							meshName = "mesh_" + autoNamedMesh.ToString ();
							autoNamedMesh++;
						}
						Mesh m = new Mesh { Name = meshName };

						foreach (GL.MeshPrimitive p in mesh.Primitives) {
							GL.Accessor AccPos = null, AccNorm = null, AccUv = null, AccUv1 = null;

							int accessorIdx;
							if (p.Attributes.TryGetValue ("POSITION", out accessorIdx)) {
								AccPos = gltf.Accessors[accessorIdx];
								ensureBufferIsLoaded (gltf.BufferViews[(int)AccPos.BufferView].Buffer);
							}
							if (p.Attributes.TryGetValue ("NORMAL", out accessorIdx)) {
								AccNorm = gltf.Accessors[accessorIdx];
								ensureBufferIsLoaded (gltf.BufferViews[(int)AccNorm.BufferView].Buffer);
							}
							if (p.Attributes.TryGetValue ("TEXCOORD_0", out accessorIdx)) {
								AccUv = gltf.Accessors[accessorIdx];
								ensureBufferIsLoaded (gltf.BufferViews[(int)AccUv.BufferView].Buffer);
							}
							if (p.Attributes.TryGetValue ("TEXCOORD_1", out accessorIdx)) {
								AccUv1 = gltf.Accessors[accessorIdx];
								ensureBufferIsLoaded (gltf.BufferViews[(int)AccUv1.BufferView].Buffer);
							}

							Primitive prim = new Primitive {
								indexBase = (uint)indexCount,
								vertexBase = vertexCount,
								vertexCount = (uint)AccPos.Count,
								material = (uint)(p.Material ?? 0)
							};

							prim.bb.min.ImportFloatArray (AccPos.Min);
							prim.bb.max.ImportFloatArray (AccPos.Max);
							prim.bb.isValid = true;

							//Interleaving vertices
							Span<byte> inPosPtr = Span<byte>.Empty, inNormPtr = Span<byte>.Empty, inUvPtr = Span<byte>.Empty, inUv1Ptr = Span<byte>.Empty;

							GL.BufferView bv = gltf.BufferViews[(int)AccPos.BufferView];
							inPosPtr = loadedBuffers[bv.Buffer].Span.Slice (AccPos.ByteOffset + bv.ByteOffset);

							if (AccNorm != null) {
								bv = gltf.BufferViews[(int)AccNorm.BufferView];
								inNormPtr = loadedBuffers[bv.Buffer].Span.Slice (AccNorm.ByteOffset + bv.ByteOffset);
							}
							if (AccUv != null) {
								bv = gltf.BufferViews[(int)AccUv.BufferView];
								inUvPtr = loadedBuffers[bv.Buffer].Span.Slice (AccUv.ByteOffset + bv.ByteOffset);
							}
							if (AccUv1 != null) {
								bv = gltf.BufferViews[(int)AccUv1.BufferView];
								inUv1Ptr = loadedBuffers[bv.Buffer].Span.Slice (AccUv1.ByteOffset + bv.ByteOffset);
							}

							//TODO: use vertex attributes scan for copying data if they exists
							for (int j = 0; j < prim.vertexCount; j++) {
								inPosPtr.Slice (0, 12).CopyTo (stagVertPtr);
								inPosPtr = inPosPtr.Slice(12);
								if (!inNormPtr.IsEmpty) {
									inNormPtr.Slice (0, 12).CopyTo (stagVertPtr.Slice (12));
									inNormPtr = inNormPtr.Slice (12);
								}
								if (inUvPtr != null) {
									inUvPtr.Slice (0, 8).CopyTo (stagVertPtr.Slice (24));
									inUvPtr = inUvPtr.Slice (8);
								}
								if (inUv1Ptr != null) {
									inUv1Ptr.Slice (0, 8).CopyTo (stagVertPtr.Slice (32));
									inUv1Ptr = inUvPtr.Slice (8);
								}
								stagVertPtr = stagVertPtr.Slice (vertexByteSize);
							}

							/*Span<byte> s = stagVertPtrInit;
							for (int i = 0; i < s.Length; i++)
								Console.Write (s[i].ToString ("X2") + (i % 32 == 0 ? "\n" : " "));*/


							//indices loading
							if (p.Indices != null) {
								GL.Accessor acc = gltf.Accessors[(int)p.Indices];
								bv = gltf.BufferViews[(int)acc.BufferView];

								Span<byte> inIdxPtr = loadedBuffers[bv.Buffer].Span.Slice (acc.ByteOffset + bv.ByteOffset);

								//TODO:double check this, I dont seems to increment stag pointer
								if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_SHORT) {
									if (indexType == VkIndexType.Uint16) {
										inIdxPtr.Slice (0, acc.Count * 2).CopyTo (stagIdxPtr);
										stagIdxPtr = stagIdxPtr.Slice (acc.Count * 2);
									} else {

										Span<uint> usPtr = MemoryMarshal.Cast<byte, uint> (stagIdxPtr);
										Span<ushort> inPtr = MemoryMarshal.Cast < byte, ushort> (inIdxPtr);
										for (int i = 0; i < acc.Count; i++)
											usPtr[i] = inPtr[i];
										stagIdxPtr = stagIdxPtr.Slice (acc.Count * 4);
									}
								} else if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_INT) {
									if (indexType == VkIndexType.Uint32) {
										inIdxPtr.Slice (0, acc.Count * 4).CopyTo (stagIdxPtr);
										stagIdxPtr = stagIdxPtr.Slice (acc.Count * 4);
									} else {
										Span<ushort> usPtr = MemoryMarshal.Cast<byte, ushort> (stagIdxPtr);
										Span<uint> inPtr = MemoryMarshal.Cast<byte, uint> (inIdxPtr);

										for (int i = 0; i < acc.Count; i++) 
											usPtr[i] = (ushort)inPtr[i];
										stagIdxPtr = stagIdxPtr.Slice (acc.Count * 2);
									}
								} else if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_BYTE) {
									//convert
									if (indexType == VkIndexType.Uint16) {
										Span<ushort> usPtr = MemoryMarshal.Cast<byte, ushort> (stagIdxPtr);
										for (int i = 0; i < acc.Count; i++)
											usPtr[i] = (ushort)inIdxPtr[i];
										stagIdxPtr = stagIdxPtr.Slice (acc.Count * 2);
									} else {
										Span<uint> usPtr = MemoryMarshal.Cast<byte, uint> (stagIdxPtr);
										for (int i = 0; i < acc.Count; i++)
											usPtr[i] = (uint)inIdxPtr[i];
										stagIdxPtr = stagIdxPtr.Slice (acc.Count * 4);
									}
								} else
									throw new NotImplementedException ();

								prim.indexCount = (uint)acc.Count;
								indexCount += acc.Count;
							}

							m.AddPrimitive (prim);

							vertexCount += AccPos.Count;
						}
						meshes.Add (m);
					}

					/*ReadOnlySpan<byte> tmp = new ReadOnlySpan<byte> (stagging.MappedData.ToPointer (), (int)size);
					Memory<byte> mtmp = new Memory<byte> (tmp.ToArray());
					mtmp.Dump();*/
				}

				stagging.Unmap ();

				PrimaryCommandBuffer cmd = cmdPool.AllocateCommandBuffer ();
				cmd.Start (VkCommandBufferUsageFlags.OneTimeSubmit);

				stagging.CopyTo (cmd, vbo, vertSize, 0, vboOffset);
				if (iCount>0)
					stagging.CopyTo (cmd, ibo, idxSize, vertSize, iboOffset);

				cmd.End ();

				transferQ.Submit (cmd);

				dev.WaitIdle ();
				cmd.Free ();

			}

			return meshes.ToArray ();
		}
Ejemplo n.º 10
0
        private Dictionary <string, int> ConvertData(Dictionary <string, DataConvertArgs> argsMap, BinaryData binaryData, bool attribute)
        {
            Schema.BufferView bufferView = null;
            int?bufferViewIndex          = null;

            var states       = new List <ConvertDataState>();
            var accessorsMap = new Dictionary <string, int>();

            foreach (var pair in argsMap)
            {
                var args = pair.Value;

                var info = DataConverter.GetInfo(args.Data, binaryData.Writer);

                if (info.Values != null && bufferViewIndex == null)
                {
                    var bufferViewName = argsMap.Count == 1 ? argsMap.First().Value.BufferViewName : "Interleaved attributes";
                    bufferViewIndex = CreateBufferView(bufferViewName, out bufferView);
                }

                var accessor = CreateInstance <Schema.Accessor>();
                accessor.Name       = args.AccessorName;
                accessor.BufferView = bufferViewIndex;
                info.SetCommon(accessor);
                if (args.MinMax)
                {
                    info.SetMinMax(accessor);
                }

                states.Add(new ConvertDataState
                {
                    Accessor         = accessor,
                    ValuesEnumerator = info.Values?.GetEnumerator(),
                    SparseIndices    = info.SparseIndices,
                    SparseValues     = info.SparseValues,
                });

                accessorsMap.Add(pair.Key, accessors.Count);
                accessors.Add(accessor);
            }

            var counts = states.Select(state => state.Accessor.Count);

            if (counts.Skip(1).Any(count => count != counts.First()))
            {
                throw new InvalidOperationException("Data values cannot have different counts");
            }

            if (bufferView != null)
            {
                bool aligned    = false;
                int  byteStride = 0;

                WriteBufferView(bufferView, binaryData, byteOffset =>
                {
                    while (states.All(state => state.ValuesEnumerator.MoveNext()))
                    {
                        foreach (var state in states)
                        {
                            if (byteStride == 0)
                            {
                                aligned |= binaryData.Writer.Align(state.Accessor.ComponentType.GetSize());
                                state.Accessor.ByteOffset = (int)binaryData.Writer.BaseStream.Position - byteOffset;
                            }

                            state.ValuesEnumerator.Current.Write();
                        }

                        if (attribute)
                        {
                            aligned |= binaryData.Writer.Align(4);
                        }

                        if (byteStride == 0)
                        {
                            byteStride = (int)binaryData.Writer.BaseStream.Position - byteOffset;
                        }
                    }
                });

                if (aligned || argsMap.Count > 1)
                {
                    bufferView.ByteStride = byteStride;
                }
            }

            foreach (var state in states)
            {
                if (state.SparseIndices != null && state.SparseValues != null)
                {
                    state.Accessor.Sparse.Indices.BufferView = CreateBufferView("Sparse Indices", out var indicesBufferView);
                    WriteBufferView(indicesBufferView, binaryData, byteOffset =>
                    {
                        foreach (var index in state.SparseIndices)
                        {
                            index.Write();
                        }
                    });

                    state.Accessor.Sparse.Values.BufferView = CreateBufferView("Sparse Values", out var valuesBufferView);
                    WriteBufferView(valuesBufferView, binaryData, byteOffset =>
                    {
                        foreach (var index in state.SparseValues)
                        {
                            index.Write();
                        }
                    });
                }
            }

            return(accessorsMap);
        }
Ejemplo n.º 11
0
        //TODO: some buffer data are reused between primitives, and I duplicate the datas
        //buffers must be constructed without duplications
        public Mesh[] LoadMeshes <TVertex> (VkIndexType indexType, Buffer vbo, ulong vboOffset, Buffer ibo, ulong iboOffset)
        {
            ulong       vCount, iCount;
            VkIndexType idxType;

            GetVertexCount(out vCount, out iCount, out idxType);

            int   vertexByteSize = Marshal.SizeOf <TVertex> ();
            ulong vertSize       = vCount * (ulong)vertexByteSize;
            ulong idxSize        = iCount * (indexType == VkIndexType.Uint16 ? 2ul : 4ul);
            ulong size           = vertSize + idxSize;

            int vertexCount = 0, indexCount = 0;
            int autoNamedMesh = 1;

            meshes = new List <Mesh> ();

            using (HostBuffer stagging = new HostBuffer(dev, VkBufferUsageFlags.TransferSrc, size)) {
                stagging.Map();

                unsafe {
                    byte *stagVertPtrInit = (byte *)stagging.MappedData.ToPointer();
                    byte *stagIdxPtrInit  = (byte *)(stagging.MappedData.ToPointer()) + vertSize;
                    byte *stagVertPtr     = stagVertPtrInit;
                    byte *stagIdxPtr      = stagIdxPtrInit;

                    foreach (GL.Mesh mesh in gltf.Meshes)
                    {
                        string meshName = mesh.Name;
                        if (string.IsNullOrEmpty(meshName))
                        {
                            meshName = "mesh_" + autoNamedMesh.ToString();
                            autoNamedMesh++;
                        }
                        Mesh m = new Mesh {
                            Name = meshName
                        };

                        foreach (GL.MeshPrimitive p in mesh.Primitives)
                        {
                            GL.Accessor AccPos = null, AccNorm = null, AccUv = null, AccUv1 = null;

                            int accessorIdx;
                            if (p.Attributes.TryGetValue("POSITION", out accessorIdx))
                            {
                                AccPos = gltf.Accessors[accessorIdx];
                                EnsureBufferIsLoaded(gltf.BufferViews[(int)AccPos.BufferView].Buffer);
                            }
                            if (p.Attributes.TryGetValue("NORMAL", out accessorIdx))
                            {
                                AccNorm = gltf.Accessors[accessorIdx];
                                EnsureBufferIsLoaded(gltf.BufferViews[(int)AccNorm.BufferView].Buffer);
                            }
                            if (p.Attributes.TryGetValue("TEXCOORD_0", out accessorIdx))
                            {
                                AccUv = gltf.Accessors[accessorIdx];
                                EnsureBufferIsLoaded(gltf.BufferViews[(int)AccUv.BufferView].Buffer);
                            }
                            if (p.Attributes.TryGetValue("TEXCOORD_1", out accessorIdx))
                            {
                                AccUv1 = gltf.Accessors[accessorIdx];
                                EnsureBufferIsLoaded(gltf.BufferViews[(int)AccUv1.BufferView].Buffer);
                            }

                            Primitive prim = new Primitive {
                                indexBase   = (uint)indexCount,
                                vertexBase  = vertexCount,
                                vertexCount = (uint)AccPos.Count,
                                material    = (uint)(p.Material ?? 0)
                            };

                            prim.bb.min.ImportFloatArray(AccPos.Min);
                            prim.bb.max.ImportFloatArray(AccPos.Max);
                            prim.bb.isValid = true;

                            //Interleaving vertices
                            byte *inPosPtr = null, inNormPtr = null, inUvPtr = null, inUv1Ptr = null;

                            GL.BufferView bv = gltf.BufferViews[(int)AccPos.BufferView];
                            inPosPtr  = (byte *)bufferHandles[bv.Buffer].AddrOfPinnedObject().ToPointer();
                            inPosPtr += AccPos.ByteOffset + bv.ByteOffset;

                            if (AccNorm != null)
                            {
                                bv         = gltf.BufferViews[(int)AccNorm.BufferView];
                                inNormPtr  = (byte *)bufferHandles[bv.Buffer].AddrOfPinnedObject().ToPointer();
                                inNormPtr += AccNorm.ByteOffset + bv.ByteOffset;
                            }
                            if (AccUv != null)
                            {
                                bv       = gltf.BufferViews[(int)AccUv.BufferView];
                                inUvPtr  = (byte *)bufferHandles[bv.Buffer].AddrOfPinnedObject().ToPointer();
                                inUvPtr += AccUv.ByteOffset + bv.ByteOffset;
                            }
                            if (AccUv1 != null)
                            {
                                bv        = gltf.BufferViews[(int)AccUv1.BufferView];
                                inUv1Ptr  = (byte *)bufferHandles[bv.Buffer].AddrOfPinnedObject().ToPointer();
                                inUv1Ptr += AccUv1.ByteOffset + bv.ByteOffset;
                            }


                            for (int j = 0; j < prim.vertexCount; j++)
                            {
                                System.Buffer.MemoryCopy(inPosPtr, stagVertPtr, 12, 12);
                                inPosPtr += 12;
                                if (inNormPtr != null)
                                {
                                    System.Buffer.MemoryCopy(inNormPtr, stagVertPtr + 12, 12, 12);
                                    inNormPtr += 12;
                                }
                                if (inUvPtr != null)
                                {
                                    System.Buffer.MemoryCopy(inUvPtr, stagVertPtr + 24, 8, 8);
                                    inUvPtr += 8;
                                }
                                if (inUv1Ptr != null)
                                {
                                    System.Buffer.MemoryCopy(inUv1Ptr, stagVertPtr + 32, 8, 8);
                                    inUv1Ptr += 8;
                                }
                                stagVertPtr += vertexByteSize;
                            }

                            //indices loading
                            if (p.Indices != null)
                            {
                                GL.Accessor acc = gltf.Accessors[(int)p.Indices];
                                bv = gltf.BufferViews[(int)acc.BufferView];

                                byte *inIdxPtr = (byte *)bufferHandles[bv.Buffer].AddrOfPinnedObject().ToPointer();
                                inIdxPtr += acc.ByteOffset + bv.ByteOffset;

                                //TODO:double check this, I dont seems to increment stag pointer
                                if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_SHORT)
                                {
                                    if (indexType == VkIndexType.Uint16)
                                    {
                                        System.Buffer.MemoryCopy(inIdxPtr, stagIdxPtr, (long)acc.Count * 2, (long)acc.Count * 2);
                                        stagIdxPtr += (long)acc.Count * 2;
                                    }
                                    else
                                    {
                                        uint *  usPtr = (uint *)stagIdxPtr;
                                        ushort *inPtr = (ushort *)inIdxPtr;
                                        for (int i = 0; i < acc.Count; i++)
                                        {
                                            usPtr[i] = inPtr[i];
                                        }
                                        stagIdxPtr += (long)acc.Count * 4;
                                    }
                                }
                                else if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_INT)
                                {
                                    if (indexType == VkIndexType.Uint32)
                                    {
                                        System.Buffer.MemoryCopy(inIdxPtr, stagIdxPtr, (long)acc.Count * 4, (long)acc.Count * 4);
                                        stagIdxPtr += (long)acc.Count * 4;
                                    }
                                    else
                                    {
                                        ushort *usPtr = (ushort *)stagIdxPtr;
                                        uint *  inPtr = (uint *)inIdxPtr;
                                        for (int i = 0; i < acc.Count; i++)
                                        {
                                            usPtr[i] = (ushort)inPtr[i];
                                        }
                                        stagIdxPtr += (long)acc.Count * 2;
                                    }
                                }
                                else if (acc.ComponentType == GL.Accessor.ComponentTypeEnum.UNSIGNED_BYTE)
                                {
                                    //convert
                                    if (indexType == VkIndexType.Uint16)
                                    {
                                        ushort *usPtr = (ushort *)stagIdxPtr;
                                        for (int i = 0; i < acc.Count; i++)
                                        {
                                            usPtr[i] = (ushort)inIdxPtr[i];
                                        }
                                        stagIdxPtr += (long)acc.Count * 2;
                                    }
                                    else
                                    {
                                        uint *usPtr = (uint *)stagIdxPtr;
                                        for (int i = 0; i < acc.Count; i++)
                                        {
                                            usPtr[i] = (uint)inIdxPtr[i];
                                        }
                                        stagIdxPtr += (long)acc.Count * 4;
                                    }
                                }
                                else
                                {
                                    throw new NotImplementedException();
                                }

                                prim.indexCount = (uint)acc.Count;
                                indexCount     += acc.Count;
                            }

                            m.AddPrimitive(prim);

                            vertexCount += AccPos.Count;
                        }
                        meshes.Add(m);
                    }
                }

                stagging.Unmap();

                CommandBuffer cmd = cmdPool.AllocateCommandBuffer();
                cmd.Start(VkCommandBufferUsageFlags.OneTimeSubmit);

                stagging.CopyTo(cmd, vbo, vertSize, 0, vboOffset);
                if (iCount > 0)
                {
                    stagging.CopyTo(cmd, ibo, idxSize, vertSize, iboOffset);
                }

                cmd.End();

                transferQ.Submit(cmd);

                dev.WaitIdle();
                cmd.Free();
            }

            return(meshes.ToArray());
        }