public PbrModelSeparatedTextures(Queue transferQ, string path, DescriptorSetLayout layout, params AttachmentType[] attachments) { dev = transferQ.Dev; using (CommandPool cmdPool = new CommandPool(dev, transferQ.index)) { using (glTFLoader ctx = new glTFLoader(path, transferQ, cmdPool)) { ulong vertexCount, indexCount; ctx.GetVertexCount(out vertexCount, out indexCount, out IndexBufferType); ulong vertSize = vertexCount * (ulong)Marshal.SizeOf <Vertex> (); ulong idxSize = indexCount * (IndexBufferType == VkIndexType.Uint16 ? 2ul : 4ul); ulong size = vertSize + idxSize; vbo = new GPUBuffer(dev, VkBufferUsageFlags.VertexBuffer | VkBufferUsageFlags.TransferDst, vertSize); ibo = new GPUBuffer(dev, VkBufferUsageFlags.IndexBuffer | VkBufferUsageFlags.TransferDst, idxSize); vbo.SetName("vbo gltf"); ibo.SetName("ibo gltf"); Meshes = new List <Mesh> (ctx.LoadMeshes <Vertex> (IndexBufferType, vbo, 0, ibo, 0)); textures = ctx.LoadImages(); loadMaterials(ctx, layout, attachments); materialUBO = new HostBuffer <Material> (dev, VkBufferUsageFlags.UniformBuffer, materials); Scenes = new List <Scene> (ctx.LoadScenes(out defaultSceneIndex)); } } }
public DebugDrawPipeline(Device dev, DescriptorSetLayout dsLayout, VkFormat colorFormat, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1) : base(new RenderPass(dev, colorFormat), "Debug draw pipeline") { GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.LineList, samples); cfg.rasterizationState.lineWidth = 1.0f; cfg.RenderPass = RenderPass; cfg.Layout = new PipelineLayout(dev, dsLayout); cfg.Layout.AddPushConstants( new VkPushConstantRange(VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf <Matrix4x4> () * 2) ); cfg.AddVertexBinding(0, 6 * sizeof(float)); cfg.SetVertexAttributes(0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat); cfg.blendAttachments[0] = new VkPipelineColorBlendAttachmentState(true); cfg.AddShader(VkShaderStageFlags.Vertex, "shaders/debug.vert.spv"); cfg.AddShader(VkShaderStageFlags.Fragment, "shaders/debug.frag.spv"); layout = cfg.Layout; init(cfg); Vertices = new HostBuffer(dev, VkBufferUsageFlags.VertexBuffer, vboLength); Vertices.Map(); }
public PbrModelTexArray(Queue transferQ, string path) { dev = transferQ.Dev; using (CommandPool cmdPool = new CommandPool(dev, transferQ.index)) { using (glTFLoader ctx = new glTFLoader(path, transferQ, cmdPool)) { ulong vertexCount, indexCount; ctx.GetVertexCount(out vertexCount, out indexCount, out IndexBufferType); ulong vertSize = vertexCount * (ulong)Marshal.SizeOf <Vertex> (); ulong idxSize = indexCount * (IndexBufferType == VkIndexType.Uint16 ? 2ul : 4ul); ulong size = vertSize + idxSize; vbo = new GPUBuffer(dev, VkBufferUsageFlags.VertexBuffer | VkBufferUsageFlags.TransferDst, vertSize); ibo = new GPUBuffer(dev, VkBufferUsageFlags.IndexBuffer | VkBufferUsageFlags.TransferDst, idxSize); vbo.SetName("vbo gltf"); ibo.SetName("ibo gltf"); Meshes = new List <Mesh> (ctx.LoadMeshes <Vertex> (IndexBufferType, vbo, 0, ibo, 0)); if (ctx.ImageCount > 0) { texArray = new Image(dev, Image.DefaultTextureFormat, VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferDst | VkImageUsageFlags.TransferSrc, VkMemoryPropertyFlags.DeviceLocal, TEXTURE_DIM, TEXTURE_DIM, VkImageType.Image2D, VkSampleCountFlags.SampleCount1, VkImageTiling.Optimal, Image.ComputeMipLevels(TEXTURE_DIM), ctx.ImageCount); ctx.BuildTexArray(ref texArray, 0); texArray.CreateView(VkImageViewType.ImageView2DArray, VkImageAspectFlags.Color, texArray.CreateInfo.arrayLayers); texArray.CreateSampler(); texArray.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; texArray.SetName("model texArray"); } loadMaterials(ctx); materialUBO = new HostBuffer <Material> (dev, VkBufferUsageFlags.UniformBuffer, materials); Scenes = new List <Scene> (ctx.LoadScenes(out defaultSceneIndex)); } } }
/// <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(); } } }
public PBRPipeline(Queue staggingQ, RenderPass renderPass, Image uiImage, PipelineCache pipelineCache = null) : base(renderPass, pipelineCache, "pbr pipeline") { descriptorPool = new DescriptorPool(Dev, 2, new VkDescriptorPoolSize(VkDescriptorType.UniformBuffer, 2), new VkDescriptorPoolSize(VkDescriptorType.CombinedImageSampler, 9) ); descLayoutMain = new DescriptorSetLayout(Dev, new VkDescriptorSetLayoutBinding(0, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer), new VkDescriptorSetLayoutBinding(1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), new VkDescriptorSetLayoutBinding(2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), new VkDescriptorSetLayoutBinding(3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), new VkDescriptorSetLayoutBinding(4, VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer), new VkDescriptorSetLayoutBinding(5, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler));//ui image descLayoutTextures = new DescriptorSetLayout(Dev, new VkDescriptorSetLayoutBinding(0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), new VkDescriptorSetLayoutBinding(1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), new VkDescriptorSetLayoutBinding(2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), new VkDescriptorSetLayoutBinding(3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), new VkDescriptorSetLayoutBinding(4, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) ); GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.TriangleList, renderPass.Samples); cfg.Layout = new PipelineLayout(Dev, descLayoutMain, descLayoutTextures); cfg.Layout.AddPushConstants( new VkPushConstantRange(VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf <Matrix4x4> ()), new VkPushConstantRange(VkShaderStageFlags.Fragment, sizeof(int), 64) ); cfg.RenderPass = renderPass; cfg.AddVertexBinding <PbrModel2.Vertex> (0); cfg.AddVertexAttributes(0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat, VkFormat.R32g32Sfloat); cfg.AddShader(VkShaderStageFlags.Vertex, "shaders/pbr.vert.spv"); cfg.AddShader(VkShaderStageFlags.Fragment, "shaders/pbr_khr.frag.spv"); layout = cfg.Layout; init(cfg); dsMain = descriptorPool.Allocate(descLayoutMain); envCube = new EnvironmentCube(dsMain, layout, staggingQ, RenderPass); matrices.prefilteredCubeMipLevels = envCube.prefilterCube.CreateInfo.mipLevels; uboMats = new HostBuffer(Dev, VkBufferUsageFlags.UniformBuffer, matrices, true); string[] modelPathes = { "data/models/DamagedHelmet/glTF/DamagedHelmet.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Avocado/glTF/Avocado.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/BarramundiFish/glTF/BarramundiFish.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/BoomBoxWithAxes/glTF/BoomBoxWithAxes.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Box/glTF/Box.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/EnvironmentTest/glTF/EnvironmentTest.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/MetalRoughSpheres/glTF/MetalRoughSpheres.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/OrientationTest/glTF/OrientationTest.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Buggy/glTF/Buggy.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/2CylinderEngine/glTF-Embedded/2CylinderEngine.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/FlightHelmet/glTF/FlightHelmet.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/GearboxAssy/glTF/GearboxAssy.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Lantern/glTF/Lantern.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/SciFiHelmet/glTF/SciFiHelmet.gltf", "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Sponza/glTF/Sponza.gltf", "/mnt/devel/vkChess/data/chess.gltf" }; model = new PbrModel2(staggingQ, modelPathes[0], descLayoutTextures, AttachmentType.Color, AttachmentType.PhysicalProps, AttachmentType.Normal, AttachmentType.AmbientOcclusion, AttachmentType.Emissive); //model = new Model (Dev, presentQueue, "../data/models/icosphere.gltf"); //model = new Model (Dev, presentQueue, cmdPool, "../data/models/cube.gltf"); DescriptorSetWrites uboUpdate = new DescriptorSetWrites(descLayoutMain); uboUpdate.Write(Dev, dsMain, uboMats.Descriptor, envCube.irradianceCube.Descriptor, envCube.prefilterCube.Descriptor, envCube.lutBrdf.Descriptor, model.materialUBO.Descriptor, uiImage.Descriptor); }
//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()); }