public FCommandBuffer(VkDevice device, int pool) { VkCommandBufferAllocateInfo pAllocateInfo = VkCommandBufferAllocateInfo.New(); pAllocateInfo.commandPool = CommandPoolManager.GetPool(pool); pAllocateInfo.level = VkCommandBufferLevel.Primary; pAllocateInfo.commandBufferCount = 1; VkCommandBuffer cmdBuffer = VkCommandBuffer.Null; Assert(vkAllocateCommandBuffers(device, &pAllocateInfo, &cmdBuffer)); buffer = cmdBuffer; }
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); }
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)); }
static void Main(string[] args) { Console.WriteLine(AppContext.GetData("NATIVE_DLL_SEARCH_DIRECTORIES").ToString()); Console.WriteLine($"Hello Vulkan!"); Init(); if (!GLFW.Vulkan.IsSupported) { Console.Error.WriteLine("GLFW says that vulkan is not supported."); return; } WindowHint(Hint.ClientApi, ClientApi.None); NativeWindow window = new GLFW.NativeWindow(width, height, "Fabricor"); Glfw.SetKeyCallback(window, (a, b, c, d, e) => { GLFWInput.KeyCallback(a, b, c, d, e); }); FInstance finst = new FInstance(); VkSurfaceKHR surface = CreateSurface(finst.instance, window); VkDevice device = CreateDevice(finst.instance, out var physicalDevice, surface, out var queueFamilyIndex); VkSwapchainKHR swapchain = CreateSwapchain(VkSwapchainKHR.Null, finst.instance, device, physicalDevice, surface, queueFamilyIndex); VkRenderPass renderPass = CreateRenderPass(device); uint swapchainImageCount = 0; Assert(vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, null));////////////IMAGES VkImage[] swapchainImages = new VkImage[swapchainImageCount]; fixed(VkImage *ptr = &swapchainImages[0]) Assert(vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, ptr)); CommandPoolManager.Init(device, queueFamilyIndex); int poolId = CommandPoolManager.CreateCommandPool(VkCommandPoolCreateFlags.ResetCommandBuffer); VkSemaphoreCreateInfo pCreateInfo = VkSemaphoreCreateInfo.New(); VkSemaphore acquireSemaphore = new VkSemaphore(); vkCreateSemaphore(device, &pCreateInfo, null, &acquireSemaphore); VkSemaphore releaseSemaphore = new VkSemaphore(); vkCreateSemaphore(device, &pCreateInfo, null, &releaseSemaphore); VkQueue graphicsQueue = VkQueue.Null; vkGetDeviceQueue(device, queueFamilyIndex, 0, &graphicsQueue); string[] textures = new string[] { "res/Linus.png", "res/Alex.png", "res/Victor.png", "res/Alex2.png", //"res/Cyan.png", "res/Alex3.png", //"res/Red.png", }; FTexture texture = new FTexture(device, physicalDevice, poolId, graphicsQueue, textures, VkFormat.R8g8b8a8Unorm, 512, 512, (uint)(Math.Log(512) / Math.Log(2)) + 1); VkPipelineCache pipelineCache = VkPipelineCache.Null;//This is critcal for performance. FGraphicsPipeline voxelPipeline = new FGraphicsPipeline(device, physicalDevice, pipelineCache, renderPass, "shaders/voxel", swapchainImageCount, texture); voxelPipeline.CreateDepthBuffer(physicalDevice, (uint)width, (uint)height); VkImageView[] swapchainImageViews = new VkImageView[swapchainImageCount]; for (int i = 0; i < swapchainImageCount; i++) { swapchainImageViews[i] = FTexture.CreateColourImageView(device, swapchainImages[i], surfaceFormat.format); } VkFramebuffer[] frambuffers = new VkFramebuffer[swapchainImageCount]; for (int i = 0; i < swapchainImageCount; i++) { frambuffers[i] = CreateFramebuffer(device, renderPass, swapchainImageViews[i], voxelPipeline.depthImageView); } MeshWrapper <VoxelVertex> mesh = VoxelMeshFactory.GenerateMesh(device, physicalDevice); Action updateMesh = delegate { VoxelMeshFactory.UpdateMesh(device, physicalDevice, mesh); }; GLFWInput.Subscribe(Keys.U, updateMesh, InputState.Press); Action changeTexture = delegate { Span <VoxelVertex> span = mesh.Mesh.vertices.Map(); for (int j = 0; j < span.Length; j++) { span[j].textureId++; } span = mesh.Mesh.vertices.UnMap(); }; GLFWInput.Subscribe(Keys.F, changeTexture, InputState.Press); FCommandBuffer[] cmdBuffers = new FCommandBuffer[swapchainImageCount]; VkFence[] fences = new VkFence[swapchainImageCount]; for (int i = 0; i < swapchainImageCount; i++) { cmdBuffers[i] = new FCommandBuffer(device, poolId); VkFenceCreateInfo createInfo = VkFenceCreateInfo.New(); createInfo.flags = VkFenceCreateFlags.Signaled; VkFence fence = VkFence.Null; Assert(vkCreateFence(device, &createInfo, null, &fence)); fences[i] = fence; } FCamera camera = new FCamera(); camera.AspectWidth = width; camera.AspectHeight = height; camera.position.Z = -1f; //camera.rotation=Quaternion.CreateFromYawPitchRoll(MathF.PI,0,0); double lastTime = Glfw.Time; int nbFrames = 0; while (!WindowShouldClose(window)) { PollEvents(); GLFWInput.Update(); // Measure speed double currentTime = Glfw.Time; nbFrames++; if (currentTime - lastTime >= 1.0) { // If last prinf() was more than 1 sec ago // printf and reset timer Console.WriteLine($"ms/frame: {1000.0 / nbFrames}"); nbFrames = 0; lastTime += 1.0; } if (GLFWInput.TimeKeyPressed(Keys.D) > 0) { camera.position += Vector3.Transform(Vector3.UnitX * 0.00015f, camera.rotation); } if (GLFWInput.TimeKeyPressed(Keys.A) > 0) { camera.position -= Vector3.Transform(Vector3.UnitX * 0.00015f, camera.rotation); } if (GLFWInput.TimeKeyPressed(Keys.W) > 0) { camera.position += Vector3.Transform(Vector3.UnitZ * 0.00015f, camera.rotation); } if (GLFWInput.TimeKeyPressed(Keys.S) > 0) { camera.position -= Vector3.Transform(Vector3.UnitZ * 0.00015f, camera.rotation); } if (GLFWInput.TimeKeyPressed(Keys.Space) > 0) { camera.position += Vector3.Transform(Vector3.UnitY * 0.00015f, camera.rotation); } if (GLFWInput.TimeKeyPressed(Keys.LeftShift) > 0) { camera.position -= Vector3.Transform(Vector3.UnitY * 0.00015f, camera.rotation); } if (GLFWInput.TimeKeyPressed(Keys.Right) > 0) { camera.rotation *= Quaternion.CreateFromAxisAngle(Vector3.UnitY, 0.00015f); } if (GLFWInput.TimeKeyPressed(Keys.Left) > 0) { camera.rotation *= Quaternion.CreateFromAxisAngle(Vector3.UnitY, -0.00015f); } uint imageIndex = 0; Assert(vkAcquireNextImageKHR(device, swapchain, ulong.MaxValue, acquireSemaphore, VkFence.Null, &imageIndex)); VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.New(); beginInfo.flags = VkCommandBufferUsageFlags.OneTimeSubmit; voxelPipeline.swapchainFramebuffer = frambuffers[imageIndex]; voxelPipeline.swapchainImage = swapchainImages[imageIndex]; voxelPipeline.swapchainImageIndex = imageIndex; voxelPipeline.mesh = mesh; voxelPipeline.camera = camera; fixed(VkFence *ptr = &(fences[imageIndex])) { vkWaitForFences(device, 1, ptr, VkBool32.False, ulong.MaxValue); vkResetFences(device, 1, ptr); } cmdBuffers[imageIndex].RecordCommandBuffer(new Action <VkCommandBuffer>[] { voxelPipeline.Execute, }); VkPipelineStageFlags submitStageMask = VkPipelineStageFlags.ColorAttachmentOutput; VkSubmitInfo submitInfo = VkSubmitInfo.New(); submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = &acquireSemaphore; submitInfo.pWaitDstStageMask = &submitStageMask; submitInfo.commandBufferCount = 1; fixed(VkCommandBuffer *ptr = &(cmdBuffers[imageIndex].buffer)) submitInfo.pCommandBuffers = ptr; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = &releaseSemaphore; Assert(vkQueueSubmit(graphicsQueue, 1, &submitInfo, fences[imageIndex])); VkPresentInfoKHR presentInfoKHR = VkPresentInfoKHR.New(); presentInfoKHR.swapchainCount = 1; presentInfoKHR.pSwapchains = &swapchain; presentInfoKHR.pImageIndices = &imageIndex; presentInfoKHR.waitSemaphoreCount = 1; presentInfoKHR.pWaitSemaphores = &releaseSemaphore; Assert(vkQueuePresentKHR(graphicsQueue, &presentInfoKHR)); vkDeviceWaitIdle(device); } finst.Destroy(); DestroyWindow(window); Terminate(); }