public VkResourceFactory(VkGraphicsDevice vkGraphicsDevice) { _gd = vkGraphicsDevice; _device = vkGraphicsDevice.Device; }
public static extern void GetDeviceMemoryCommitment( VkDevice device, VkDeviceMemory memory, ref ulong pCommittedMemoryInBytes );
public static extern VkResult BindBufferMemory( VkDevice device, VkBuffer buffer, VkDeviceMemory memory, ulong memoryOffset );
public static extern VkResult AllocateMemory( VkDevice device, ref VkMemoryAllocateInfo pAllocateInfo, IntPtr pAllocator, out VkDeviceMemory pMemory );
public static extern void UnmapMemory( VkDevice device, VkDeviceMemory memory );
public static extern void DestroySwapchainKHR( VkDevice device, VkSwapchainKHR swapchain, IntPtr pAllocator );
public static extern void GetDeviceQueue( VkDevice device, uint queueFamilyIndex, uint queueIndex, out VkQueue pQueue );
internal VkPipeline(UInt64 Handle, VkDevice Parent) { _Parent = Parent; _Handle = Handle; }
public unsafe Device(VkPhysicalDevice physicalDevice) { _physicalDevice = physicalDevice; //get physical device information VulkanNative.vkGetPhysicalDeviceProperties( _physicalDevice, out _properties ); VulkanNative.vkGetPhysicalDeviceMemoryProperties( _physicalDevice, out _memoryProperties ); VulkanNative.vkGetPhysicalDeviceFeatures( _physicalDevice, out _features ); //get family queue properties uint familyQueuePropertiesCount; VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties( _physicalDevice, &familyQueuePropertiesCount, null ); var familyQueueProperties = new NativeList <VkQueueFamilyProperties>( familyQueuePropertiesCount ); familyQueueProperties.Count = familyQueuePropertiesCount; VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties( _physicalDevice, &familyQueuePropertiesCount, (VkQueueFamilyProperties *)familyQueueProperties.Data.ToPointer() ); //setup queue families _queueFamilies = new List <QueueFamily>(); for (uint i = 0; i < familyQueuePropertiesCount; i++) { var familyQueueProperty = familyQueueProperties[i]; _queueFamilies.Add(new QueueFamily( i, familyQueueProperty.queueCount, (QueueFamilyType)familyQueueProperty.queueFlags )); } //get queue create infos var queueCreateInfos = new NativeList <VkDeviceQueueCreateInfo>( familyQueuePropertiesCount ); queueCreateInfos.Count = familyQueuePropertiesCount; for (int i = 0; i < familyQueuePropertiesCount; i++) { queueCreateInfos[i] = _queueFamilies[i].QueueCreateInfo; } //enable extra device features var enabledFeatures = new VkPhysicalDeviceFeatures() { samplerAnisotropy = true, dualSrcBlend = true }; //enable swapchain extension for window support var enabledExtensions = new NativeList <IntPtr>(); enabledExtensions.Add(GraphicsApiConstants.VK_KHR_SWAPCHAIN_EXTENSION_NAME); var deviceInfo = new VkDeviceCreateInfo { sType = VkStructureType.DeviceCreateInfo, pEnabledFeatures = &enabledFeatures, enabledExtensionCount = enabledExtensions.Count, ppEnabledExtensionNames = (byte **)enabledExtensions.Data, enabledLayerCount = 0, ppEnabledLayerNames = null, queueCreateInfoCount = queueCreateInfos.Count, pQueueCreateInfos = (VkDeviceQueueCreateInfo *)queueCreateInfos.Data.ToPointer() }; //setup device VkDevice device; if (VulkanNative.vkCreateDevice( _physicalDevice, &deviceInfo, null, &device ) != VkResult.Success) { throw new Exception("failed to initialize device"); } _handle = device; //setup device queues foreach (var queueFamily in _queueFamilies) { queueFamily.GetQueuesFromDevice(this); } //calculate device score _score = 0; if (_properties.deviceType == VkPhysicalDeviceType.DiscreteGpu) { _score += 10; } else if (_properties.deviceType == VkPhysicalDeviceType.IntegratedGpu) { _score += 5; } else if (_properties.deviceType == VkPhysicalDeviceType.VirtualGpu) { _score += 3; } else if (_properties.deviceType == VkPhysicalDeviceType.Cpu) { _score += 1; } _score += ( //1073741824 = 1024 * 1024 * 1024 _properties.limits.maxMemoryAllocationCount / 1073741824.0f ); }
public static VkResult vkCreateImageView(VkDevice device, VkImageViewCreateInfo *createInfo, VkAllocationCallbacks *allocator, VkImageView *view) { throw new NotImplementedException(); }
public static VkResult vkCreateFramebuffer( VkDevice device, VkRenderPass renderPass, ReadOnlySpan <VkImageView> attachments, in Size extent,
public static VkResult vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, VkComputePipelineCreateInfo createInfo, out VkPipeline pipeline) { return(vkCreateComputePipelines(device, pipelineCache, 1, &createInfo, null, out pipeline)); }
public static VkResult vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint createInfoCount, VkComputePipelineCreateInfo *createInfos, VkAllocationCallbacks *allocator, out VkPipeline pipelines) { throw new NotImplementedException(); }
/** * Loads a 3D model from a file into Vulkan buffers * * @param device Pointer to the Vulkan device used to generated the vertex and index buffers on * @param filename File to load (must be a model format supported by ASSIMP) * @param layout Vertex layout components (position, normals, tangents, etc.) * @param createInfo MeshCreateInfo structure for load time settings like scale, center, etc. * @param copyQueue Queue used for the memory staging copy commands (must support transfer) * @param (Optional) flags ASSIMP model loading flags */ //public bool loadFromFile(string filename, vksVertexLayout layout, vksModelCreateInfo* createInfo, vksVulkanDevice device, VkQueue copyQueue, int flags) //{ // this.device = device.LogicalDevice; // ObjFile objFile; // using (var fs = File.OpenRead(filename)) // { // objFile = new ObjParser().Parse(fs); // } // string mtlFilename = Path.ChangeExtension(filename, "mtl"); // MtlFile mtlFile; // using (var fs = File.OpenRead(mtlFilename)) // { // mtlFile = new MtlParser().Parse(fs); // } // if (objFile != null) // { // parts.Clear(); // parts.Resize((uint)objFile.MeshGroups.Length); // Vector3 scale = new Vector3(1.0f); // Vector2 uvscale = new Vector2(1.0f); // Vector3 center = new Vector3(0.0f); // if (createInfo != null) // { // scale = createInfo->Scale; // uvscale = createInfo->UVScale; // center = createInfo->Center; // } // NativeList<float> vertexBuffer = new NativeList<float>(); // NativeList<uint> indexBuffer = new NativeList<uint>(); // vertexCount = 0; // indexCount = 0; // // Load meshes // parts.Count = (uint)objFile.MeshGroups.Length; // for (uint i = 0; i < objFile.MeshGroups.Length; i++) // { // ConstructedMeshInfo mesh = objFile.GetMesh(objFile.MeshGroups[i]); // parts[i] = new ModelPart(); // parts[i].vertexBase = vertexCount; // parts[i].indexBase = indexCount; // vertexCount += (uint)mesh.Vertices.Length; // var material = mtlFile.Definitions[objFile.MeshGroups[i].Material]; // Vector3 pColor = material.DiffuseReflectivity; // Vector3 Zero3D = Vector3.Zero; // for (uint j = 0; j < mesh.Vertices.Length; j++) // { // VertexPositionNormalTexture vertex = mesh.Vertices[j]; // Vector3* pPos = &vertex.Position; // Vector3* pNormal = &vertex.Normal; // Vector2* pTexCoord = &vertex.TextureCoordinates; // Vector3* pTangent = &Zero3D; // Vector3* pBiTangent = &Zero3D; // /* // const aiVector3D* pPos = &(paiMesh->mVertices[j]); // const aiVector3D* pNormal = &(paiMesh->mNormals[j]); // const aiVector3D* pTexCoord = (paiMesh->HasTextureCoords(0)) ? &(paiMesh->mTextureCoords[0][j]) : &Zero3D; // const aiVector3D* pTangent = (paiMesh->HasTangentsAndBitangents()) ? &(paiMesh->mTangents[j]) : &Zero3D; // const aiVector3D* pBiTangent = (paiMesh->HasTangentsAndBitangents()) ? &(paiMesh->mBitangents[j]) : &Zero3D; // */ // foreach (var component in layout.Components) // { // switch (component) // { // case VertexComponent.VERTEX_COMPONENT_POSITION: // vertexBuffer.Add(pPos.X * scale.X + center.X); // vertexBuffer.Add(-pPos.Y * scale.Y + center.Y); // vertexBuffer.Add(pPos.Z * scale.Z + center.Z); // break; // case VertexComponent.VERTEX_COMPONENT_NORMAL: // vertexBuffer.Add(pNormal.X); // vertexBuffer.Add(-pNormal.Y); // vertexBuffer.Add(pNormal.Z); // break; // case VertexComponent.VERTEX_COMPONENT_UV: // vertexBuffer.Add(pTexCoord.X * uvscale.X); // vertexBuffer.Add(pTexCoord.Y * uvscale.Y); // break; // case VertexComponent.VERTEX_COMPONENT_COLOR: // vertexBuffer.Add(pColor.X); // vertexBuffer.Add(pColor.Y); // vertexBuffer.Add(pColor.Z); // break; // case VertexComponent.VERTEX_COMPONENT_TANGENT: // vertexBuffer.Add(pTangent.X); // vertexBuffer.Add(pTangent.Y); // vertexBuffer.Add(pTangent.Z); // break; // case VertexComponent.VERTEX_COMPONENT_BITANGENT: // vertexBuffer.Add(pBiTangent.X); // vertexBuffer.Add(pBiTangent.Y); // vertexBuffer.Add(pBiTangent.Z); // break; // // Dummy components for padding // case VertexComponent.VERTEX_COMPONENT_DUMMY_FLOAT: // vertexBuffer.Add(0.0f); // break; // case VertexComponent.VERTEX_COMPONENT_DUMMY_VEC4: // vertexBuffer.Add(0.0f); // vertexBuffer.Add(0.0f); // vertexBuffer.Add(0.0f); // vertexBuffer.Add(0.0f); // break; // }; // } // dim.Max.X = Math.Max(pPos.X, dim.Max.X); // dim.Max.Y = Math.Max(pPos.Y, dim.Max.Y); // dim.Max.Z = Math.Max(pPos.Z, dim.Max.Z); // dim.Min.X = Math.Min(pPos.X, dim.Min.X); // dim.Min.Y = Math.Min(pPos.Y, dim.Min.Y); // dim.Min.Z = Math.Min(pPos.Z, dim.Min.Z); // } // dim.Size = dim.Max - dim.Min; // parts[i].vertexCount = (uint)mesh.Vertices.Length; // uint indexBase = indexBuffer.Count; // foreach (var index in mesh.Indices) // { // indexBuffer.Add(index); // } // indexCount += (uint)mesh.Indices.Length; // parts[i].indexCount += (uint)mesh.Indices.Length; // /* // for (uint j = 0; j < paiMesh->mNumFaces; j++) // { // const aiFace&Face = paiMesh->mFaces[j]; // if (Face.mNumIndices != 3) // continue; // indexBuffer.Add(indexBase + Face.mIndices[0]); // indexBuffer.Add(indexBase + Face.mIndices[1]); // indexBuffer.Add(indexBase + Face.mIndices[2]); // parts[i].indexCount += 3; // indexCount += 3; // } // */ // } // uint vBufferSize = vertexBuffer.Count * sizeof(float); // uint iBufferSize = indexBuffer.Count * sizeof(uint); // // Use staging buffer to move vertex and index buffer to device local memory // // Create staging buffers // vksBuffer vertexStaging = new vksBuffer(); // vksBuffer indexStaging = new vksBuffer(); // // Vertex buffer // Util.CheckResult(device.createBuffer( // VkBufferUsageFlags.TransferSrc, // VkMemoryPropertyFlags.HostVisible, // vertexStaging, // vBufferSize, // vertexBuffer.Data.ToPointer())); // // Index buffer // Util.CheckResult(device.createBuffer( // VkBufferUsageFlags.TransferSrc, // VkMemoryPropertyFlags.HostVisible, // indexStaging, // iBufferSize, // indexBuffer.Data.ToPointer())); // // Create device local target buffers // // Vertex buffer // Util.CheckResult(device.createBuffer( // VkBufferUsageFlags.VertexBuffer | VkBufferUsageFlags.TransferDst, // VkMemoryPropertyFlags.DeviceLocal, // vertices, // vBufferSize)); // // Index buffer // Util.CheckResult(device.createBuffer( // VkBufferUsageFlags.IndexBuffer | VkBufferUsageFlags.TransferDst, // VkMemoryPropertyFlags.DeviceLocal, // indices, // iBufferSize)); // // Copy from staging buffers // VkCommandBuffer copyCmd = device.createCommandBuffer(VkCommandBufferLevel.Primary, true); // VkBufferCopy copyRegion = new VkBufferCopy(); // copyRegion.size = vertices.size; // vkCmdCopyBuffer(copyCmd, vertexStaging.buffer, vertices.buffer, 1, ©Region); // copyRegion.size = indices.size; // vkCmdCopyBuffer(copyCmd, indexStaging.buffer, indices.buffer, 1, ©Region); // device.flushCommandBuffer(copyCmd, copyQueue); // // Destroy staging resources // vkDestroyBuffer(device.LogicalDevice, vertexStaging.buffer, null); // vkFreeMemory(device.LogicalDevice, vertexStaging.memory, null); // vkDestroyBuffer(device.LogicalDevice, indexStaging.buffer, null); // vkFreeMemory(device.LogicalDevice, indexStaging.memory, null); // return true; // } // else // { // Console.WriteLine("Error loading file."); // return false; // } //} /** * Loads a 3D model from a file into Vulkan buffers * * @param device Pointer to the Vulkan device used to generated the vertex and index buffers on * @param filename File to load (must be a model format supported by ASSIMP) * @param layout Vertex layout components (position, normals, tangents, etc.) * @param createInfo MeshCreateInfo structure for load time settings like scale, center, etc. * @param copyQueue Queue used for the memory staging copy commands (must support transfer) * @param (Optional) flags ASSIMP model loading flags */ bool loadFromFile(string filename, vksVertexLayout layout, vksModelCreateInfo *createInfo, vksVulkanDevice device, VkQueue copyQueue, PostProcessSteps flags = DefaultPostProcessSteps) { this.device = device.LogicalDevice; // Load file var assimpContext = new AssimpContext(); var pScene = assimpContext.ImportFile(filename, flags); parts.Clear(); parts.Count = (uint)pScene.Meshes.Count; Vector3 scale = new Vector3(1.0f); Vector2 uvscale = new Vector2(1.0f); Vector3 center = new Vector3(0.0f); if (createInfo != null) { scale = createInfo->Scale; uvscale = createInfo->UVScale; center = createInfo->Center; } NativeList <float> vertexBuffer = new NativeList <float>(); NativeList <uint> indexBuffer = new NativeList <uint>(); vertexCount = 0; indexCount = 0; // Load meshes for (int i = 0; i < pScene.Meshes.Count; i++) { var paiMesh = pScene.Meshes[i]; parts[i] = new ModelPart(); parts[i].vertexBase = vertexCount; parts[i].indexBase = indexCount; vertexCount += (uint)paiMesh.VertexCount; var pColor = pScene.Materials[paiMesh.MaterialIndex].ColorDiffuse; Vector3D Zero3D = new Vector3D(0.0f, 0.0f, 0.0f); for (int j = 0; j < paiMesh.VertexCount; j++) { Vector3D pPos = paiMesh.Vertices[j]; Vector3D pNormal = paiMesh.Normals[j]; Vector3D pTexCoord = paiMesh.HasTextureCoords(0) ? paiMesh.TextureCoordinateChannels[0][j] : Zero3D; Vector3D pTangent = paiMesh.HasTangentBasis ? paiMesh.Tangents[j] : Zero3D; Vector3D pBiTangent = paiMesh.HasTangentBasis ? paiMesh.BiTangents[j] : Zero3D; foreach (var component in layout.Components) { switch (component) { case VertexComponent.VERTEX_COMPONENT_POSITION: vertexBuffer.Add(pPos.X * scale.X + center.X); vertexBuffer.Add(-pPos.Y * scale.Y + center.Y); vertexBuffer.Add(pPos.Z * scale.Z + center.Z); break; case VertexComponent.VERTEX_COMPONENT_NORMAL: vertexBuffer.Add(pNormal.X); vertexBuffer.Add(-pNormal.Y); vertexBuffer.Add(pNormal.Z); break; case VertexComponent.VERTEX_COMPONENT_UV: vertexBuffer.Add(pTexCoord.X * uvscale.X); vertexBuffer.Add(pTexCoord.Y * uvscale.Y); break; case VertexComponent.VERTEX_COMPONENT_COLOR: vertexBuffer.Add(pColor.R); vertexBuffer.Add(pColor.G); vertexBuffer.Add(pColor.B); break; case VertexComponent.VERTEX_COMPONENT_TANGENT: vertexBuffer.Add(pTangent.X); vertexBuffer.Add(pTangent.Y); vertexBuffer.Add(pTangent.Z); break; case VertexComponent.VERTEX_COMPONENT_BITANGENT: vertexBuffer.Add(pBiTangent.X); vertexBuffer.Add(pBiTangent.Y); vertexBuffer.Add(pBiTangent.Z); break; // Dummy components for padding case VertexComponent.VERTEX_COMPONENT_DUMMY_FLOAT: vertexBuffer.Add(0.0f); break; case VertexComponent.VERTEX_COMPONENT_DUMMY_VEC4: vertexBuffer.Add(0.0f); vertexBuffer.Add(0.0f); vertexBuffer.Add(0.0f); vertexBuffer.Add(0.0f); break; } ; } dim.Max.X = (float)Math.Max(pPos.X, dim.Max.X); dim.Max.Y = (float)Math.Max(pPos.Y, dim.Max.Y); dim.Max.Z = (float)Math.Max(pPos.Z, dim.Max.Z); dim.Min.X = (float)Math.Min(pPos.X, dim.Min.X); dim.Min.Y = (float)Math.Min(pPos.Y, dim.Min.Y); dim.Min.Z = (float)Math.Min(pPos.Z, dim.Min.Z); } dim.Size = dim.Max - dim.Min; parts[i].vertexCount = (uint)paiMesh.VertexCount; uint indexBase = indexBuffer.Count; for (uint j = 0; j < paiMesh.FaceCount; j++) { var Face = paiMesh.Faces[(int)j]; if (Face.IndexCount != 3) { continue; } indexBuffer.Add(indexBase + (uint)Face.Indices[0]); indexBuffer.Add(indexBase + (uint)Face.Indices[1]); indexBuffer.Add(indexBase + (uint)Face.Indices[2]); parts[i].indexCount += 3; indexCount += 3; } } uint vBufferSize = (vertexBuffer.Count) * sizeof(float); uint iBufferSize = (indexBuffer.Count) * sizeof(uint); // Use staging buffer to move vertex and index buffer to device local memory // Create staging buffers vksBuffer vertexStaging = new vksBuffer(); vksBuffer indexStaging = new vksBuffer(); // Vertex buffer Util.CheckResult(device.createBuffer( VkBufferUsageFlags.TransferSrc, VkMemoryPropertyFlags.HostVisible, vertexStaging, vBufferSize, vertexBuffer.Data.ToPointer())); // Index buffer Util.CheckResult(device.createBuffer( VkBufferUsageFlags.TransferSrc, VkMemoryPropertyFlags.HostVisible, indexStaging, iBufferSize, indexBuffer.Data.ToPointer())); // Create device local target buffers // Vertex buffer Util.CheckResult(device.createBuffer( VkBufferUsageFlags.VertexBuffer | VkBufferUsageFlags.TransferDst, VkMemoryPropertyFlags.DeviceLocal, vertices, vBufferSize)); // Index buffer Util.CheckResult(device.createBuffer( VkBufferUsageFlags.IndexBuffer | VkBufferUsageFlags.TransferDst, VkMemoryPropertyFlags.DeviceLocal, indices, iBufferSize)); // Copy from staging buffers VkCommandBuffer copyCmd = device.createCommandBuffer(VkCommandBufferLevel.Primary, true); VkBufferCopy copyRegion = new VkBufferCopy(); copyRegion.size = vertices.size; vkCmdCopyBuffer(copyCmd, vertexStaging.buffer, vertices.buffer, 1, ©Region); copyRegion.size = indices.size; vkCmdCopyBuffer(copyCmd, indexStaging.buffer, indices.buffer, 1, ©Region); device.flushCommandBuffer(copyCmd, copyQueue); // Destroy staging resources vkDestroyBuffer(device.LogicalDevice, vertexStaging.buffer, null); vkFreeMemory(device.LogicalDevice, vertexStaging.memory, null); vkDestroyBuffer(device.LogicalDevice, indexStaging.buffer, null); vkFreeMemory(device.LogicalDevice, indexStaging.memory, null); return(true); }
public void Connect(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device) { Instance = instance; PhysicalDevice = physicalDevice; Device = device; }
public override VkResult CreateDevice(VkDeviceCreateInfo createInfo, out VkDevice device) { device = new DummyDevice(this, createInfo); return(VkResult.VK_SUCCESS); }
public static extern VkResult CreateSwapchainKHR( VkDevice device, ref VkSwapchainCreateInfoKHR pCreateInfo, IntPtr pAllocator, out VkSwapchainKHR pSwapchain );
public static void vkUpdateDescriptorSets(VkDevice device, VkWriteDescriptorSet writeDescriptorSet) { vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, null); }
public static extern VkResult GetSwapchainImagesKHR( VkDevice device, VkSwapchainKHR swapchain, ref uint pSwapchainImageCount, IntPtr pSwapchainImages );
public static void vkUpdateDescriptorSets(VkDevice device, VkWriteDescriptorSet writeDescriptorSet, VkCopyDescriptorSet copyDescriptorSet) { vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 1, ©DescriptorSet); }
public static extern VkResult DeviceWaitIdle( VkDevice device );
public static VkResult vkAllocateCommandBuffers(VkDevice device, VkCommandBufferAllocateInfo *allocateInfo, out VkCommandBuffer commandBuffers) { throw new NotImplementedException(); }
public static extern void FreeMemory( VkDevice device, VkDeviceMemory memory, IntPtr pAllocator );
public static void vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, VkCommandBuffer commandBuffer) { vkFreeCommandBuffers(device, commandPool, 1u, &commandBuffer); }
public static extern VkResult InvalidateMappedMemoryRanges( VkDevice device, uint memoryRangeCount, IntPtr pMemoryRanges );
public VkDeviceMemoryManager(VkDevice device, VkPhysicalDevice physicalDevice) { _device = device; _physicalDevice = physicalDevice; }
public static extern void GetBufferMemoryRequirements( VkDevice device, VkBuffer buffer, out VkMemoryRequirements pMemoryRequirements );
public ChunkAllocatorSet(VkDevice device, uint memoryTypeIndex, bool persistentMapped) { _device = device; _memoryTypeIndex = memoryTypeIndex; _persistentMapped = persistentMapped; }
public static extern void GetImageMemoryRequirements( VkDevice device, VkImage image, out VkMemoryRequirements pMemoryRequirements );
private static void InitMips(VkDevice device, VkQueue queue, VkImage image, int width, int height, uint mipLevels, uint layerCount, int cmdPool) { VkCommandBufferAllocateInfo pAllocateInfo = VkCommandBufferAllocateInfo.New(); pAllocateInfo.commandPool = CommandPoolManager.GetPool(cmdPool); pAllocateInfo.level = VkCommandBufferLevel.Primary; pAllocateInfo.commandBufferCount = 1; VkCommandBuffer cmdBuffer = VkCommandBuffer.Null; Assert(vkAllocateCommandBuffers(device, &pAllocateInfo, &cmdBuffer)); Assert(vkResetCommandBuffer(cmdBuffer, VkCommandBufferResetFlags.None)); VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.New(); beginInfo.flags = VkCommandBufferUsageFlags.OneTimeSubmit; Assert(vkBeginCommandBuffer(cmdBuffer, &beginInfo)); VkImageMemoryBarrier imageMemoryBarrier = VkImageMemoryBarrier.New(); imageMemoryBarrier.srcAccessMask = VkAccessFlags.None; imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferWrite; imageMemoryBarrier.oldLayout = VkImageLayout.Undefined; imageMemoryBarrier.newLayout = VkImageLayout.TransferDstOptimal; imageMemoryBarrier.srcQueueFamilyIndex = VulkanNative.QueueFamilyIgnored; imageMemoryBarrier.dstQueueFamilyIndex = VulkanNative.QueueFamilyIgnored; imageMemoryBarrier.image = image; imageMemoryBarrier.subresourceRange = new VkImageSubresourceRange() { baseMipLevel = 0, levelCount = mipLevels, baseArrayLayer = 0, layerCount = layerCount, aspectMask = VkImageAspectFlags.Color }; vkCmdPipelineBarrier(cmdBuffer, VkPipelineStageFlags.AllCommands, VkPipelineStageFlags.AllCommands, VkDependencyFlags.ByRegion, 0, null, 0, null, 1, &imageMemoryBarrier); for (int i = 1; i < mipLevels; i++) { imageMemoryBarrier.oldLayout = VkImageLayout.TransferDstOptimal; imageMemoryBarrier.newLayout = VkImageLayout.TransferSrcOptimal; imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferWrite; imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferRead; imageMemoryBarrier.subresourceRange.baseMipLevel = (uint)(i - 1); imageMemoryBarrier.subresourceRange.levelCount = 1; vkCmdPipelineBarrier(cmdBuffer, VkPipelineStageFlags.AllCommands, VkPipelineStageFlags.AllCommands, VkDependencyFlags.ByRegion, 0, null, 0, null, 1, &imageMemoryBarrier); VkImageBlit blit = new VkImageBlit(); blit.srcOffsets_0 = new VkOffset3D { x = 0, y = 0, z = 0 }; blit.srcOffsets_1 = new VkOffset3D { x = width, y = height, z = 1 }; blit.srcSubresource.aspectMask = VkImageAspectFlags.Color; blit.srcSubresource.mipLevel = (uint)(i - 1); blit.srcSubresource.baseArrayLayer = 0; blit.srcSubresource.layerCount = layerCount; blit.dstOffsets_0 = new VkOffset3D { x = 0, y = 0, z = 0 }; blit.dstOffsets_1 = new VkOffset3D { x = width / 2, y = height / 2, z = 1 }; blit.dstSubresource.aspectMask = VkImageAspectFlags.Color; blit.dstSubresource.mipLevel = (uint)i; blit.dstSubresource.baseArrayLayer = 0; blit.dstSubresource.layerCount = layerCount; vkCmdBlitImage(cmdBuffer, image, VkImageLayout.TransferSrcOptimal, image, VkImageLayout.TransferDstOptimal, 1, &blit, VkFilter.Linear); width /= 2; height /= 2; imageMemoryBarrier.oldLayout = VkImageLayout.TransferSrcOptimal; imageMemoryBarrier.newLayout = VkImageLayout.ShaderReadOnlyOptimal; imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferRead; imageMemoryBarrier.dstAccessMask = VkAccessFlags.ShaderRead; imageMemoryBarrier.subresourceRange.baseMipLevel = (uint)(i - 1); imageMemoryBarrier.subresourceRange.levelCount = 1; vkCmdPipelineBarrier(cmdBuffer, VkPipelineStageFlags.AllCommands, VkPipelineStageFlags.AllCommands, VkDependencyFlags.ByRegion, 0, null, 0, null, 1, &imageMemoryBarrier); } imageMemoryBarrier.oldLayout = VkImageLayout.Undefined; imageMemoryBarrier.newLayout = VkImageLayout.ShaderReadOnlyOptimal; imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferRead; imageMemoryBarrier.dstAccessMask = VkAccessFlags.ShaderRead; imageMemoryBarrier.subresourceRange.baseMipLevel = mipLevels - 1; imageMemoryBarrier.subresourceRange.levelCount = 1; vkCmdPipelineBarrier(cmdBuffer, VkPipelineStageFlags.AllCommands, VkPipelineStageFlags.AllCommands, VkDependencyFlags.ByRegion, 0, null, 0, null, 1, &imageMemoryBarrier); Assert(vkEndCommandBuffer(cmdBuffer)); VkSubmitInfo submitInfo = VkSubmitInfo.New(); submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &cmdBuffer; Assert(vkQueueSubmit(queue, 1, &submitInfo, VkFence.Null)); }