Exemplo n.º 1
0
        public void BuildMipmaps(Queue copyQ, CommandPool copyCmdPool)
        {
            if (info.mipLevels == 1)
            {
                Debug.WriteLine("Invoking BuildMipmaps on image that has only one mipLevel");
                return;
            }
            CommandBuffer cmd = copyCmdPool.AllocateCommandBuffer();

            cmd.Start(VkCommandBufferUsageFlags.OneTimeSubmit);
            BuildMipmaps(cmd);
            cmd.End();

            copyQ.Submit(cmd);
            copyQ.WaitIdle();

            cmd.Free();
        }
Exemplo n.º 2
0
        void generateBRDFLUT(Queue staggingQ, CommandPool cmdPool)
        {
            const VkFormat format = VkFormat.R16g16Sfloat;
            const int      dim    = 512;

            lutBrdf = new Image(Dev, format, VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.Sampled,
                                VkMemoryPropertyFlags.DeviceLocal, dim, dim);
            lutBrdf.SetName("lutBrdf");

            lutBrdf.CreateView();
            lutBrdf.CreateSampler(VkSamplerAddressMode.ClampToEdge);

            GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false);

            cfg.Layout     = new PipelineLayout(Dev, new DescriptorSetLayout(Dev));
            cfg.RenderPass = new RenderPass(Dev);
            cfg.RenderPass.AddAttachment(format, VkImageLayout.ShaderReadOnlyOptimal);
            cfg.RenderPass.ClearValues.Add(new VkClearValue {
                color = new VkClearColorValue(0, 0, 0)
            });
            cfg.RenderPass.AddSubpass(new SubPass(VkImageLayout.ColorAttachmentOptimal));
            cfg.AddShader(VkShaderStageFlags.Vertex, "shaders/genbrdflut.vert.spv");
            cfg.AddShader(VkShaderStageFlags.Fragment, "shaders/genbrdflut.frag.spv");

            using (GraphicPipeline pl = new GraphicPipeline(cfg)) {
                using (Framebuffer fb = new Framebuffer(cfg.RenderPass, dim, dim, lutBrdf)) {
                    CommandBuffer cmd = cmdPool.AllocateCommandBuffer();
                    cmd.Start(VkCommandBufferUsageFlags.OneTimeSubmit);
                    pl.RenderPass.Begin(cmd, fb);
                    cmd.SetViewport(dim, dim);
                    cmd.SetScissor(dim, dim);
                    pl.Bind(cmd);
                    cmd.Draw(3, 1, 0, 0);
                    pl.RenderPass.End(cmd);
                    cmd.End();

                    staggingQ.Submit(cmd);
                    staggingQ.WaitIdle();

                    cmd.Free();
                }
            }
            lutBrdf.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
        }
Exemplo n.º 3
0
        /// <summary>
        /// load bitmap from pointer
        /// </summary>
        void load(Queue staggingQ, CommandPool staggingCmdPool, IntPtr bitmap, bool generateMipmaps = true)
        {
            long size = info.extent.width * info.extent.height * 4 * info.extent.depth;

            if (MemoryFlags.HasFlag(VkMemoryPropertyFlags.HostVisible))
            {
                Map();
                unsafe {
                    System.Buffer.MemoryCopy(bitmap.ToPointer(), MappedData.ToPointer(), size, size);
                }
                Unmap();

                if (generateMipmaps)
                {
                    BuildMipmaps(staggingQ, staggingCmdPool);
                }
            }
            else
            {
                using (HostBuffer stagging = new HostBuffer(Dev, VkBufferUsageFlags.TransferSrc, (UInt64)size, bitmap)) {
                    CommandBuffer cmd = staggingCmdPool.AllocateCommandBuffer();

                    cmd.Start(VkCommandBufferUsageFlags.OneTimeSubmit);

                    stagging.CopyTo(cmd, this);
                    if (generateMipmaps)
                    {
                        BuildMipmaps(cmd);
                    }

                    cmd.End();
                    staggingQ.Submit(cmd);
                    staggingQ.WaitIdle();
                    cmd.Free();
                }
            }
        }
Exemplo n.º 4
0
 /// <summary>
 /// End command recording, submit, and wait queue idle
 /// </summary>
 public void EndSubmitAndWait(CommandBuffer cmd)
 {
     cmd.End();
     Submit(cmd);
     WaitIdle();
 }
Exemplo n.º 5
0
        public Image generateCubeMap(Queue staggingQ, CommandPool cmdPool, CBTarget target)
        {
            const float deltaPhi   = (2.0f * (float)Math.PI) / 180.0f;
            const float deltaTheta = (0.5f * (float)Math.PI) / 64.0f;

            VkFormat format = VkFormat.R32g32b32a32Sfloat;
            uint     dim    = 64;

            if (target == CBTarget.PREFILTEREDENV)
            {
                format = VkFormat.R16g16b16a16Sfloat;
                dim    = 512;
            }

            uint numMips = (uint)Math.Floor(Math.Log(dim, 2)) + 1;

            Image imgFbOffscreen = new Image(Dev, format, VkImageUsageFlags.TransferSrc | VkImageUsageFlags.ColorAttachment,
                                             VkMemoryPropertyFlags.DeviceLocal, dim, dim);

            imgFbOffscreen.SetName("offscreenfb");
            imgFbOffscreen.CreateView();

            Image cmap = new Image(Dev, format, VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled,
                                   VkMemoryPropertyFlags.DeviceLocal, dim, dim, VkImageType.Image2D, VkSampleCountFlags.SampleCount1, VkImageTiling.Optimal,
                                   numMips, 6, 1, VkImageCreateFlags.CubeCompatible);

            if (target == CBTarget.PREFILTEREDENV)
            {
                cmap.SetName("prefilterenvmap");
            }
            else
            {
                cmap.SetName("irradianceCube");
            }
            cmap.CreateView(VkImageViewType.Cube, VkImageAspectFlags.Color, 6, 0, numMips);
            cmap.CreateSampler(VkSamplerAddressMode.ClampToEdge);

            DescriptorPool dsPool = new DescriptorPool(Dev, 2, new VkDescriptorPoolSize(VkDescriptorType.CombinedImageSampler));

            DescriptorSetLayout dsLayout = new DescriptorSetLayout(Dev,
                                                                   new VkDescriptorSetLayoutBinding(0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler));


            GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false);

            cfg.Layout = new PipelineLayout(Dev, dsLayout);
            cfg.Layout.AddPushConstants(
                new VkPushConstantRange(VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, (uint)Marshal.SizeOf <Matrix4x4> () + 8));

            cfg.RenderPass = new RenderPass(Dev);
            cfg.RenderPass.AddAttachment(format, VkImageLayout.ColorAttachmentOptimal);
            cfg.RenderPass.ClearValues.Add(new VkClearValue {
                color = new VkClearColorValue(0, 0, 0)
            });
            cfg.RenderPass.AddSubpass(new SubPass(VkImageLayout.ColorAttachmentOptimal));

            cfg.AddVertexBinding(0, 3 * sizeof(float));
            cfg.AddVertexAttributes(0, VkFormat.R32g32b32Sfloat);

            cfg.AddShader(VkShaderStageFlags.Vertex, "shaders/filtercube.vert.spv");
            if (target == CBTarget.PREFILTEREDENV)
            {
                cfg.AddShader(VkShaderStageFlags.Fragment, "shaders/prefilterenvmap.frag.spv");
            }
            else
            {
                cfg.AddShader(VkShaderStageFlags.Fragment, "shaders/irradiancecube.frag.spv");
            }

            Matrix4x4[] matrices =
            {
                // POSITIVE_X
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(180)) * Matrix4x4.CreateRotationY(Utils.DegreesToRadians(90)),
                // NEGATIVE_X
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(180)) * Matrix4x4.CreateRotationY(Utils.DegreesToRadians(-90)),
                // POSITIVE_Y
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(-90)),
                // NEGATIVE_Y
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(90)),
                // POSITIVE_Z
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(180)),
                // NEGATIVE_Z
                Matrix4x4.CreateRotationZ(Utils.DegreesToRadians(180))
            };

            VkImageSubresourceRange subRes = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, numMips, 0, 6);

            using (GraphicPipeline pl = new GraphicPipeline(cfg)) {
                DescriptorSet       dset     = dsPool.Allocate(dsLayout);
                DescriptorSetWrites dsUpdate = new DescriptorSetWrites(dsLayout);
                dsUpdate.Write(Dev, dset, cubemap.Descriptor);
                Dev.WaitIdle();

                using (Framebuffer fb = new Framebuffer(pl.RenderPass, dim, dim, imgFbOffscreen)) {
                    CommandBuffer cmd = cmdPool.AllocateCommandBuffer();
                    cmd.Start(VkCommandBufferUsageFlags.OneTimeSubmit);

                    cmap.SetLayout(cmd, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, subRes);

                    float roughness = 0;

                    cmd.SetScissor(dim, dim);
                    cmd.SetViewport((float)(dim), (float)dim);

                    for (int m = 0; m < numMips; m++)
                    {
                        roughness = (float)m / ((float)numMips - 1f);

                        for (int f = 0; f < 6; f++)
                        {
                            pl.RenderPass.Begin(cmd, fb);

                            pl.Bind(cmd);

                            float viewPortSize = (float)Math.Pow(0.5, m) * dim;
                            cmd.SetViewport(viewPortSize, viewPortSize);
                            cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment,
                                             matrices[f] * Matrix4x4.CreatePerspectiveFieldOfView(Utils.DegreesToRadians(90), 1f, 0.1f, 512f));
                            if (target == CBTarget.IRRADIANCE)
                            {
                                cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, deltaPhi, (uint)Marshal.SizeOf <Matrix4x4> ());
                                cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, deltaTheta, (uint)Marshal.SizeOf <Matrix4x4> () + 4);
                            }
                            else
                            {
                                cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, roughness, (uint)Marshal.SizeOf <Matrix4x4> ());
                                cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, 64u, (uint)Marshal.SizeOf <Matrix4x4> () + 4);
                            }

                            cmd.BindDescriptorSet(pl.Layout, dset);
                            cmd.BindVertexBuffer(vboSkybox);
                            cmd.Draw(36);

                            pl.RenderPass.End(cmd);

                            imgFbOffscreen.SetLayout(cmd, VkImageAspectFlags.Color,
                                                     VkImageLayout.ColorAttachmentOptimal, VkImageLayout.TransferSrcOptimal);

                            VkImageCopy region = new VkImageCopy();
                            region.srcSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, 1);
                            region.dstSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, 1, (uint)m, (uint)f);
                            region.extent         = new VkExtent3D {
                                width = (uint)viewPortSize, height = (uint)viewPortSize, depth = 1
                            };

                            Vk.vkCmdCopyImage(cmd.Handle,
                                              imgFbOffscreen.Handle, VkImageLayout.TransferSrcOptimal,
                                              cmap.Handle, VkImageLayout.TransferDstOptimal,
                                              1, region.Pin());
                            region.Unpin();

                            imgFbOffscreen.SetLayout(cmd, VkImageAspectFlags.Color,
                                                     VkImageLayout.TransferSrcOptimal, VkImageLayout.ColorAttachmentOptimal);
                        }
                    }

                    cmap.SetLayout(cmd, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal, subRes);

                    cmd.End();

                    staggingQ.Submit(cmd);
                    staggingQ.WaitIdle();

                    cmd.Free();
                }
            }
            cmap.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;

            dsLayout.Dispose();
            imgFbOffscreen.Dispose();
            dsPool.Dispose();

            return(cmap);
        }
Exemplo n.º 6
0
        ///// <summary>
        ///// build texture array
        ///// </summary>
        ///// <returns>The images.</returns>
        ///// <param name="textureSize">Texture size.</param>
        public void BuildTexArray(ref Image texArray, uint firstImg = 0)
        {
            int texDim = (int)texArray.CreateInfo.extent.width;

            CommandBuffer cmd = cmdPool.AllocateAndStart(VkCommandBufferUsageFlags.OneTimeSubmit);

            texArray.SetLayout(cmd, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal,
                               VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.Transfer);
            cmd.End();
            transferQ.Submit(cmd);
            transferQ.WaitIdle();
            cmd.Free();

            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, 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, 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, Path.Combine(baseDirectory, img.Uri));
                }

                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, VkImageLayout.Undefined, VkImageLayout.TransferSrcOptimal,
                                VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);

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

                cmd.End();
                transferQ.Submit(cmd);
                transferQ.WaitIdle();
                cmd.Free();

                vkimg.Dispose();
            }

            uint imgCount = (uint)gltf.Images.Length;

            VkImageSubresourceRange mipSubRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, firstImg, imgCount);

            cmd = cmdPool.AllocateAndStart(VkCommandBufferUsageFlags.OneTimeSubmit);
            texArray.SetLayout(cmd, VkImageLayout.Undefined, VkImageLayout.TransferSrcOptimal, mipSubRange,
                               VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);

            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)
                };
                mipSubRange.baseMipLevel = (uint)i;

                texArray.SetLayout(cmd, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, 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.TransferDstOptimal, VkImageLayout.TransferSrcOptimal, mipSubRange,
                                   VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);
            }

            texArray.SetLayout(cmd, VkImageAspectFlags.Color, VkImageLayout.TransferSrcOptimal, VkImageLayout.ShaderReadOnlyOptimal,
                               VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader);

            cmd.End();
            transferQ.Submit(cmd);
            transferQ.WaitIdle();
            cmd.Free();
        }
Exemplo n.º 7
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());
        }