public void SetLayout( CommandBuffer cmdbuffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldImageLayout, VkImageLayout newImageLayout, VkImageSubresourceRange subresourceRange, VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands, VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands, uint srcQueueFamilyIndex = Vk.QueueFamilyIgnored, uint dstQueueFamilyIndex = Vk.QueueFamilyIgnored) { VkImageMemoryBarrier imageMemoryBarrier = VkImageMemoryBarrier.New(); imageMemoryBarrier.srcQueueFamilyIndex = srcQueueFamilyIndex; imageMemoryBarrier.dstQueueFamilyIndex = dstQueueFamilyIndex; imageMemoryBarrier.oldLayout = oldImageLayout; imageMemoryBarrier.newLayout = newImageLayout; imageMemoryBarrier.image = handle; imageMemoryBarrier.subresourceRange = subresourceRange; imageMemoryBarrier.srcAccessMask = srcAccessMask; imageMemoryBarrier.dstAccessMask = dstAccessMask; Vk.vkCmdPipelineBarrier( cmdbuffer.Handle, srcStageMask, dstStageMask, 0, 0, IntPtr.Zero, 0, IntPtr.Zero, 1, ref imageMemoryBarrier); }
protected void TransitionImageLayout(VkImage image, uint mipLevels, uint baseArrayLayer, uint layerCount, VkImageLayout oldLayout, VkImageLayout newLayout) { VkCommandBuffer cb = BeginOneTimeCommands(); VkImageMemoryBarrier barrier = VkImageMemoryBarrier.New(); barrier.oldLayout = oldLayout; barrier.newLayout = newLayout; barrier.srcQueueFamilyIndex = QueueFamilyIgnored; barrier.dstQueueFamilyIndex = QueueFamilyIgnored; barrier.image = image; barrier.subresourceRange.aspectMask = VkImageAspectFlags.Color; barrier.subresourceRange.baseMipLevel = 0; barrier.subresourceRange.levelCount = mipLevels; barrier.subresourceRange.baseArrayLayer = baseArrayLayer; barrier.subresourceRange.layerCount = layerCount; vkCmdPipelineBarrier( cb, VkPipelineStageFlags.TopOfPipe, VkPipelineStageFlags.TopOfPipe, VkDependencyFlags.None, 0, null, 0, null, 1, &barrier); EndOneTimeCommands(cb); }
/** @brief Initialize an image memory barrier with no image transfer ownership */ public static VkImageMemoryBarrier imageMemoryBarrier() { VkImageMemoryBarrier imageMemoryBarrier = VkImageMemoryBarrier.New(); imageMemoryBarrier.srcQueueFamilyIndex = QueueFamilyIgnored; imageMemoryBarrier.dstQueueFamilyIndex = QueueFamilyIgnored; return(imageMemoryBarrier); }
public static void TransitionImageLayout( VkCommandBuffer cb, VkImage image, uint baseMipLevel, uint levelCount, uint baseArrayLayer, uint layerCount, VkImageAspectFlags aspectMask, VkImageLayout oldLayout, VkImageLayout newLayout) { Debug.Assert(oldLayout != newLayout); VkImageMemoryBarrier barrier = VkImageMemoryBarrier.New(); barrier.oldLayout = oldLayout; barrier.newLayout = newLayout; barrier.srcQueueFamilyIndex = QueueFamilyIgnored; barrier.dstQueueFamilyIndex = QueueFamilyIgnored; barrier.image = image; barrier.subresourceRange.aspectMask = aspectMask; barrier.subresourceRange.baseMipLevel = baseMipLevel; barrier.subresourceRange.levelCount = levelCount; barrier.subresourceRange.baseArrayLayer = baseArrayLayer; barrier.subresourceRange.layerCount = layerCount; VkPipelineStageFlags srcStageFlags = VkPipelineStageFlags.None; VkPipelineStageFlags dstStageFlags = VkPipelineStageFlags.None; if ((oldLayout == VkImageLayout.Undefined || oldLayout == VkImageLayout.Preinitialized) && newLayout == VkImageLayout.TransferDstOptimal) { barrier.srcAccessMask = VkAccessFlags.None; barrier.dstAccessMask = VkAccessFlags.TransferWrite; srcStageFlags = VkPipelineStageFlags.TopOfPipe; dstStageFlags = VkPipelineStageFlags.Transfer; } else if (oldLayout == VkImageLayout.ShaderReadOnlyOptimal && newLayout == VkImageLayout.TransferSrcOptimal) { barrier.srcAccessMask = VkAccessFlags.ShaderRead; barrier.dstAccessMask = VkAccessFlags.TransferRead; srcStageFlags = VkPipelineStageFlags.FragmentShader; dstStageFlags = VkPipelineStageFlags.Transfer; } else if (oldLayout == VkImageLayout.ShaderReadOnlyOptimal && newLayout == VkImageLayout.TransferDstOptimal) { barrier.srcAccessMask = VkAccessFlags.ShaderRead; barrier.dstAccessMask = VkAccessFlags.TransferWrite; srcStageFlags = VkPipelineStageFlags.FragmentShader; dstStageFlags = VkPipelineStageFlags.Transfer; } else if (oldLayout == VkImageLayout.Preinitialized && newLayout == VkImageLayout.TransferSrcOptimal) { barrier.srcAccessMask = VkAccessFlags.None; barrier.dstAccessMask = VkAccessFlags.TransferRead; srcStageFlags = VkPipelineStageFlags.TopOfPipe; dstStageFlags = VkPipelineStageFlags.Transfer; } else if (oldLayout == VkImageLayout.TransferSrcOptimal && newLayout == VkImageLayout.ShaderReadOnlyOptimal) { barrier.srcAccessMask = VkAccessFlags.TransferRead; barrier.dstAccessMask = VkAccessFlags.ShaderRead; srcStageFlags = VkPipelineStageFlags.Transfer; dstStageFlags = VkPipelineStageFlags.FragmentShader; } else if (oldLayout == VkImageLayout.TransferDstOptimal && newLayout == VkImageLayout.ShaderReadOnlyOptimal) { barrier.srcAccessMask = VkAccessFlags.TransferWrite; barrier.dstAccessMask = VkAccessFlags.ShaderRead; srcStageFlags = VkPipelineStageFlags.Transfer; dstStageFlags = VkPipelineStageFlags.FragmentShader; } else if (oldLayout == VkImageLayout.TransferSrcOptimal && newLayout == VkImageLayout.TransferDstOptimal) { barrier.srcAccessMask = VkAccessFlags.TransferRead; barrier.dstAccessMask = VkAccessFlags.TransferWrite; srcStageFlags = VkPipelineStageFlags.Transfer; dstStageFlags = VkPipelineStageFlags.Transfer; } else if (oldLayout == VkImageLayout.TransferDstOptimal && newLayout == VkImageLayout.TransferSrcOptimal) { barrier.srcAccessMask = VkAccessFlags.TransferWrite; barrier.dstAccessMask = VkAccessFlags.TransferRead; srcStageFlags = VkPipelineStageFlags.Transfer; dstStageFlags = VkPipelineStageFlags.Transfer; } else if (oldLayout == VkImageLayout.ColorAttachmentOptimal && newLayout == VkImageLayout.TransferSrcOptimal) { barrier.srcAccessMask = VkAccessFlags.ColorAttachmentWrite; barrier.dstAccessMask = VkAccessFlags.TransferRead; srcStageFlags = VkPipelineStageFlags.ColorAttachmentOutput; dstStageFlags = VkPipelineStageFlags.Transfer; } else if (oldLayout == VkImageLayout.ColorAttachmentOptimal && newLayout == VkImageLayout.TransferDstOptimal) { barrier.srcAccessMask = VkAccessFlags.ColorAttachmentWrite; barrier.dstAccessMask = VkAccessFlags.TransferWrite; srcStageFlags = VkPipelineStageFlags.ColorAttachmentOutput; dstStageFlags = VkPipelineStageFlags.Transfer; } else if (oldLayout == VkImageLayout.ColorAttachmentOptimal && newLayout == VkImageLayout.ShaderReadOnlyOptimal) { barrier.srcAccessMask = VkAccessFlags.ColorAttachmentWrite; barrier.dstAccessMask = VkAccessFlags.ShaderRead; srcStageFlags = VkPipelineStageFlags.ColorAttachmentOutput; dstStageFlags = VkPipelineStageFlags.FragmentShader; } else if (oldLayout == VkImageLayout.DepthStencilAttachmentOptimal && newLayout == VkImageLayout.ShaderReadOnlyOptimal) { barrier.srcAccessMask = VkAccessFlags.DepthStencilAttachmentWrite; barrier.dstAccessMask = VkAccessFlags.ShaderRead; srcStageFlags = VkPipelineStageFlags.LateFragmentTests; dstStageFlags = VkPipelineStageFlags.FragmentShader; } else if (oldLayout == VkImageLayout.ColorAttachmentOptimal && newLayout == VkImageLayout.PresentSrcKHR) { barrier.srcAccessMask = VkAccessFlags.ColorAttachmentWrite; barrier.dstAccessMask = VkAccessFlags.MemoryRead; srcStageFlags = VkPipelineStageFlags.ColorAttachmentOutput; dstStageFlags = VkPipelineStageFlags.BottomOfPipe; } else if (oldLayout == VkImageLayout.TransferDstOptimal && newLayout == VkImageLayout.ColorAttachmentOptimal) { barrier.srcAccessMask = VkAccessFlags.TransferWrite; barrier.dstAccessMask = VkAccessFlags.ColorAttachmentWrite; srcStageFlags = VkPipelineStageFlags.Transfer; dstStageFlags = VkPipelineStageFlags.ColorAttachmentOutput; } else if (oldLayout == VkImageLayout.TransferDstOptimal && newLayout == VkImageLayout.DepthStencilAttachmentOptimal) { barrier.srcAccessMask = VkAccessFlags.TransferWrite; barrier.dstAccessMask = VkAccessFlags.DepthStencilAttachmentWrite; srcStageFlags = VkPipelineStageFlags.Transfer; dstStageFlags = VkPipelineStageFlags.LateFragmentTests; } else { Debug.Fail("Invalid image layout transition."); } vkCmdPipelineBarrier( cb, srcStageFlags, dstStageFlags, VkDependencyFlags.None, 0, null, 0, null, 1, &barrier); }
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)); }
private static VkImage LoadTexture(VkDevice device, VkPhysicalDevice physicalDevice, int cmdPoolID, VkQueue queue, string[] paths, uint mipLevels) { Bitmap[] bitmaps = new Bitmap[paths.Length]; FDataBuffer <byte>[] tempBuffer = new FDataBuffer <byte> [paths.Length]; uint width = 0, height = 0; for (int j = 0; j < paths.Length; j++) { bitmaps[j] = new Bitmap(System.Drawing.Image.FromFile(paths[j])); var data = bitmaps[j].LockBits(new Rectangle(0, 0, bitmaps[j].Width, bitmaps[j].Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmaps[j].PixelFormat); width = (uint)data.Width; height = (uint)data.Height;//TODO add size check Span <byte> img = new Span <byte>((void *)data.Scan0, data.Stride * data.Height); tempBuffer[j] = new FDataBuffer <byte>(device, physicalDevice, img.Length, VkBufferUsageFlags.TransferSrc, VkSharingMode.Exclusive); Span <byte> buffer = tempBuffer[j].Map(); for (int i = 0; i < img.Length; i += 4) { buffer[i + 2] = img[i]; buffer[i + 1] = img[i + 1]; buffer[i] = img[i + 2]; buffer[i + 3] = img[i + 3]; } buffer = tempBuffer[j].UnMap(); } VkImage texture = VkImage.Null; VkDeviceMemory memory = VkDeviceMemory.Null; VkImageCreateInfo createInfo = VkImageCreateInfo.New(); createInfo.imageType = VkImageType.Image2D; createInfo.extent.width = width; createInfo.extent.height = height; createInfo.extent.depth = 1; createInfo.mipLevels = mipLevels; createInfo.arrayLayers = (uint)paths.Length; createInfo.format = VkFormat.R8g8b8a8Unorm; createInfo.tiling = VkImageTiling.Optimal; createInfo.initialLayout = VkImageLayout.Undefined; createInfo.usage = VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferSrc; createInfo.sharingMode = VkSharingMode.Exclusive; createInfo.samples = VkSampleCountFlags.Count1; Assert(vkCreateImage(device, &createInfo, null, &texture)); VkMemoryRequirements memoryRequirements; vkGetImageMemoryRequirements(device, texture, &memoryRequirements); VkPhysicalDeviceMemoryProperties memoryProperties = new VkPhysicalDeviceMemoryProperties(); vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties); VkMemoryAllocateInfo allocateInfo = VkMemoryAllocateInfo.New(); allocateInfo.allocationSize = memoryRequirements.size; allocateInfo.memoryTypeIndex = FDataBuffer <byte> .SelectMemoryType(memoryProperties, memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal); Assert(vkAllocateMemory(device, &allocateInfo, null, &memory)); vkBindImageMemory(device, texture, memory, 0); VkCommandBufferAllocateInfo pAllocateInfo = VkCommandBufferAllocateInfo.New(); pAllocateInfo.commandPool = CommandPoolManager.GetPool(cmdPoolID); pAllocateInfo.level = VkCommandBufferLevel.Primary; pAllocateInfo.commandBufferCount = 1; VkCommandBuffer cmdBuffer = VkCommandBuffer.Null; Assert(vkAllocateCommandBuffers(device, &pAllocateInfo, &cmdBuffer)); VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.New(); beginInfo.flags = VkCommandBufferUsageFlags.OneTimeSubmit; Assert(vkBeginCommandBuffer(cmdBuffer, &beginInfo)); VkImageMemoryBarrier imageMemoryBarrier = VkImageMemoryBarrier.New(); imageMemoryBarrier.srcAccessMask = VkAccessFlags.None; imageMemoryBarrier.dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite; imageMemoryBarrier.oldLayout = VkImageLayout.Undefined; imageMemoryBarrier.newLayout = VkImageLayout.TransferDstOptimal; imageMemoryBarrier.srcQueueFamilyIndex = VulkanNative.QueueFamilyIgnored; imageMemoryBarrier.dstQueueFamilyIndex = VulkanNative.QueueFamilyIgnored; imageMemoryBarrier.image = texture; imageMemoryBarrier.subresourceRange = new VkImageSubresourceRange() { baseMipLevel = 0, levelCount = mipLevels, baseArrayLayer = 0, layerCount = (uint)paths.Length, aspectMask = VkImageAspectFlags.Color }; vkCmdPipelineBarrier(cmdBuffer, VkPipelineStageFlags.AllCommands, VkPipelineStageFlags.AllCommands, VkDependencyFlags.ByRegion, 0, null, 0, null, 1, &imageMemoryBarrier); for (int j = 0; j < tempBuffer.Length; j++) { VkBufferImageCopy region = new VkBufferImageCopy(); region.bufferOffset = 0; region.bufferRowLength = 0; region.bufferImageHeight = 0; region.imageSubresource.aspectMask = VkImageAspectFlags.Color; region.imageSubresource.mipLevel = 0; region.imageSubresource.baseArrayLayer = (uint)j; region.imageSubresource.layerCount = 1; region.imageOffset = new VkOffset3D(); region.imageExtent = new VkExtent3D() { width = width, height = height, depth = 1 }; vkCmdCopyBufferToImage(cmdBuffer, tempBuffer[j].Buffer, texture, VkImageLayout.TransferDstOptimal, 1, ®ion); } imageMemoryBarrier.oldLayout = VkImageLayout.TransferDstOptimal; imageMemoryBarrier.newLayout = VkImageLayout.ShaderReadOnlyOptimal; 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)); Assert(vkQueueWaitIdle(queue)); vkFreeCommandBuffers(device, CommandPoolManager.GetPool(cmdPoolID), 1, &cmdBuffer); return(texture); }
public void Execute(VkCommandBuffer buffer) { VkImageMemoryBarrier imageMemoryBarrier = VkImageMemoryBarrier.New(); imageMemoryBarrier.srcAccessMask = VkAccessFlags.None; imageMemoryBarrier.dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite; imageMemoryBarrier.oldLayout = VkImageLayout.Undefined; imageMemoryBarrier.newLayout = VkImageLayout.ColorAttachmentOptimal; imageMemoryBarrier.srcQueueFamilyIndex = VulkanNative.QueueFamilyIgnored; imageMemoryBarrier.dstQueueFamilyIndex = VulkanNative.QueueFamilyIgnored; imageMemoryBarrier.image = swapchainImage; imageMemoryBarrier.subresourceRange = new VkImageSubresourceRange() { baseMipLevel = 0, levelCount = 1, baseArrayLayer = 0, layerCount = 1, aspectMask = VkImageAspectFlags.Color }; vkCmdPipelineBarrier(buffer, VkPipelineStageFlags.AllGraphics, VkPipelineStageFlags.AllGraphics, VkDependencyFlags.ByRegion, 0, null, 0, null, 1, &imageMemoryBarrier); VkClearColorValue clearColorValue = new VkClearColorValue { float32_0 = 3f / 255f, float32_1 = 2f / 255, float32_2 = 12f / 255, float32_3 = 1 }; VkClearDepthStencilValue clearDepthStencilValue = new VkClearDepthStencilValue(1, 0); VkClearValue[] clearValues = new VkClearValue[2]; clearValues[0].color = clearColorValue; clearValues[1].depthStencil = clearDepthStencilValue; VkRenderPassBeginInfo passBeginInfo = VkRenderPassBeginInfo.New(); passBeginInfo.renderPass = renderPass; passBeginInfo.framebuffer = swapchainFramebuffer; passBeginInfo.renderArea.extent.width = (uint)Program.width; passBeginInfo.renderArea.extent.height = (uint)Program.height; passBeginInfo.clearValueCount = (uint)clearValues.Length; fixed(VkClearValue *ptr = clearValues) passBeginInfo.pClearValues = ptr; vkCmdBeginRenderPass(buffer, &passBeginInfo, VkSubpassContents.Inline); VkViewport viewport = new VkViewport(); viewport.x = 0; viewport.y = (float)Program.height; viewport.width = (float)Program.width; viewport.height = -(float)Program.height; VkRect2D scissor = new VkRect2D(); scissor.offset.x = 0; scissor.offset.y = 0; scissor.extent.width = (uint)Program.width; scissor.extent.height = (uint)Program.height; vkCmdSetViewport(buffer, 0, 1, &viewport); vkCmdSetScissor(buffer, 0, 1, &scissor); vkCmdBindPipeline(buffer, VkPipelineBindPoint.Graphics, pipeline); if (mesh.IsReady) { mesh.Use(); VkBuffer[] databuffers = new VkBuffer[] { mesh.Mesh.vertices.Buffer, mesh.Mesh.vertices.Buffer, mesh.Mesh.vertices.Buffer, mesh.Mesh.vertices.Buffer }; ulong[] offsets = new ulong[] { 0, 3 * 4, 6 * 4, 6 * 4 + 2 * 4 }; fixed(VkBuffer *bptr = databuffers) fixed(ulong *optr = offsets) vkCmdBindVertexBuffers(buffer, 0, 4, bptr, optr); vkCmdBindIndexBuffer(buffer, mesh.Mesh.indices.Buffer, 0, VkIndexType.Uint32); uniformdata.Write(0, camera.View.ToFloatArray()); uniformdata.Write(16, camera.Projection.ToFloatArray()); UpdateUniformData(uniformdata, swapchainImageIndex); VkDescriptorSet sets = descriptorSets[swapchainImageIndex]; VkPipelineLayout layout = pipelineLayout; vkCmdBindDescriptorSets(buffer, VkPipelineBindPoint.Graphics, layout, 0, 1, &sets, 0, null); vkCmdDrawIndexed(buffer, (uint)mesh.Mesh.indices.Length, 1, 0, 0, 0); mesh.StopUse(); } vkCmdEndRenderPass(buffer); }
// Create an image memory barrier for changing the layout of // an image and put it into an active command buffer // See chapter 11.4 "Image Layout" for details public void SetLayout( CommandBuffer cmdbuffer, VkImageLayout oldImageLayout, VkImageLayout newImageLayout, VkImageSubresourceRange subresourceRange, VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands, VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands) { // Create an image barrier object VkImageMemoryBarrier imageMemoryBarrier = VkImageMemoryBarrier.New(); imageMemoryBarrier.srcQueueFamilyIndex = Vk.QueueFamilyIgnored; imageMemoryBarrier.dstQueueFamilyIndex = Vk.QueueFamilyIgnored; imageMemoryBarrier.oldLayout = oldImageLayout; imageMemoryBarrier.newLayout = newImageLayout; imageMemoryBarrier.image = handle; imageMemoryBarrier.subresourceRange = subresourceRange; // Source layouts (old) // Source access mask controls actions that have to be finished on the old layout // before it will be transitioned to the new layout switch (oldImageLayout) { case VkImageLayout.Undefined: // Image layout is undefined (or does not matter) // Only valid as initial layout // No flags required, listed only for completeness imageMemoryBarrier.srcAccessMask = 0; break; case VkImageLayout.Preinitialized: // Image is preinitialized // Only valid as initial layout for linear images, preserves memory contents // Make sure host writes have been finished imageMemoryBarrier.srcAccessMask = VkAccessFlags.HostWrite; break; case VkImageLayout.ColorAttachmentOptimal: // Image is a color attachment // Make sure any writes to the color buffer have been finished imageMemoryBarrier.srcAccessMask = VkAccessFlags.ColorAttachmentWrite; break; case VkImageLayout.DepthStencilAttachmentOptimal: // Image is a depth/stencil attachment // Make sure any writes to the depth/stencil buffer have been finished imageMemoryBarrier.srcAccessMask = VkAccessFlags.DepthStencilAttachmentWrite; break; case VkImageLayout.TransferSrcOptimal: // Image is a transfer source // Make sure any reads from the image have been finished imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferRead; break; case VkImageLayout.TransferDstOptimal: // Image is a transfer destination // Make sure any writes to the image have been finished imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferWrite; break; case VkImageLayout.ShaderReadOnlyOptimal: // Image is read by a shader // Make sure any shader reads from the image have been finished imageMemoryBarrier.srcAccessMask = VkAccessFlags.ShaderRead; break; } // Target layouts (new) // Destination access mask controls the dependency for the new image layout switch (newImageLayout) { case VkImageLayout.TransferDstOptimal: // Image will be used as a transfer destination // Make sure any writes to the image have been finished imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferWrite; break; case VkImageLayout.TransferSrcOptimal: // Image will be used as a transfer source // Make sure any reads from and writes to the image have been finished imageMemoryBarrier.srcAccessMask = imageMemoryBarrier.srcAccessMask | VkAccessFlags.TransferRead; imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferRead; break; case VkImageLayout.ColorAttachmentOptimal: // Image will be used as a color attachment // Make sure any writes to the color buffer have been finished imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferRead; imageMemoryBarrier.dstAccessMask = VkAccessFlags.ColorAttachmentWrite; break; case VkImageLayout.DepthStencilAttachmentOptimal: // Image layout will be used as a depth/stencil attachment // Make sure any writes to depth/stencil buffer have been finished imageMemoryBarrier.dstAccessMask = imageMemoryBarrier.dstAccessMask | VkAccessFlags.DepthStencilAttachmentWrite; break; case VkImageLayout.ShaderReadOnlyOptimal: // Image will be read in a shader (sampler, input attachment) // Make sure any writes to the image have been finished if (imageMemoryBarrier.srcAccessMask == 0) { imageMemoryBarrier.srcAccessMask = VkAccessFlags.HostWrite | VkAccessFlags.TransferWrite; } imageMemoryBarrier.dstAccessMask = VkAccessFlags.ShaderRead; break; } // Put barrier inside setup command buffer Vk.vkCmdPipelineBarrier( cmdbuffer.Handle, srcStageMask, dstStageMask, 0, 0, IntPtr.Zero, 0, IntPtr.Zero, 1, ref imageMemoryBarrier); }