Exemple #1
0
        public override void Begin()
        {
            if (_commandBufferBegun)
            {
                throw new VeldridException(
                          "CommandList must be in its initial state, or End() must have been called, for Begin() to be valid to call.");
            }
            if (_commandBufferEnded)
            {
                _commandBufferEnded = false;
                _cb = GetNextCommandBuffer();
                if (_currentStagingInfo != null)
                {
                    RecycleStagingInfo(_currentStagingInfo);
                }
            }

            _currentStagingInfo = GetStagingResourceInfo();

            VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.New();

            beginInfo.flags = VkCommandBufferUsageFlags.OneTimeSubmit;
            vkBeginCommandBuffer(_cb, ref beginInfo);
            _commandBufferBegun = true;

            ClearCachedState();
            _currentFramebuffer      = null;
            _currentGraphicsPipeline = null;
            Util.ClearArray(_currentGraphicsResourceSets);
            Util.ClearArray(_scissorRects);

            _currentComputePipeline = null;
            Util.ClearArray(_currentComputeResourceSets);
        }
        public void RecordCommandBuffer(Action <VkCommandBuffer>[] executions)
        {
            Assert(vkResetCommandBuffer(buffer, VkCommandBufferResetFlags.None));
            VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.New();

            beginInfo.flags = VkCommandBufferUsageFlags.OneTimeSubmit;

            Assert(vkBeginCommandBuffer(buffer, &beginInfo));

            for (int i = 0; i < executions.Length; i++)
            {
                executions[i](buffer);
            }

            Assert(vkEndCommandBuffer(buffer));
        }
Exemple #3
0
        public override void Begin()
        {
            if (_commandBufferBegun)
            {
                throw new VeldridException(
                          "CommandList must be in it's initial state, or End() must have been called, for Begin() to be valid to call.");
            }
            if (_commandBufferEnded)
            {
                _commandBufferEnded = false;
                vkResetCommandPool(_gd.Device, _pool, VkCommandPoolResetFlags.None);
            }

            VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.New();

            vkBeginCommandBuffer(_cb, ref beginInfo);
            _commandBufferBegun = true;
        }
        protected VkCommandBuffer BeginOneTimeCommands()
        {
            VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.New();

            allocInfo.commandBufferCount = 1;
            allocInfo.commandPool        = _rc.GraphicsCommandPool;
            allocInfo.level = VkCommandBufferLevel.Primary;

            vkAllocateCommandBuffers(_device, ref allocInfo, out VkCommandBuffer cb);

            VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.New();

            beginInfo.flags = VkCommandBufferUsageFlags.OneTimeSubmit;

            vkBeginCommandBuffer(cb, ref beginInfo);

            return(cb);
        }
Exemple #5
0
            public VkCommandBuffer BeginNewCommandBuffer()
            {
                VkCommandBufferAllocateInfo allocateInfo = VkCommandBufferAllocateInfo.New();

                allocateInfo.commandBufferCount = 1;
                allocateInfo.level       = VkCommandBufferLevel.Primary;
                allocateInfo.commandPool = _pool;
                VkResult result = vkAllocateCommandBuffers(_gd.Device, ref allocateInfo, out VkCommandBuffer cb);

                CheckResult(result);

                VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.New();

                beginInfo.flags = VkCommandBufferUsageFlags.OneTimeSubmit;
                result          = vkBeginCommandBuffer(cb, ref beginInfo);
                CheckResult(result);

                return(cb);
            }
Exemple #6
0
        public VkCommandBuffer createCommandBuffer(VkCommandBufferLevel level, bool begin = false)
        {
            VkCommandBufferAllocateInfo cmdBufAllocateInfo = VkCommandBufferAllocateInfo.New();

            cmdBufAllocateInfo.commandPool        = CommandPool;
            cmdBufAllocateInfo.level              = level;
            cmdBufAllocateInfo.commandBufferCount = 1;

            VkCommandBuffer cmdBuffer;

            Util.CheckResult(vkAllocateCommandBuffers(_logicalDevice, ref cmdBufAllocateInfo, out cmdBuffer));

            // If requested, also start recording for the new command buffer
            if (begin)
            {
                VkCommandBufferBeginInfo cmdBufInfo = VkCommandBufferBeginInfo.New();
                Util.CheckResult(vkBeginCommandBuffer(cmdBuffer, ref cmdBufInfo));
            }

            return(cmdBuffer);
        }
Exemple #7
0
        public override void Begin()
        {
            if (_commandBufferBegun)
            {
                throw new VeldridException(
                          "CommandList must be in its initial state, or End() must have been called, for Begin() to be valid to call.");
            }
            if (_commandBufferEnded)
            {
                _commandBufferEnded = false;
                vkResetCommandPool(_gd.Device, _pool, VkCommandPoolResetFlags.None);
            }

            VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.New();

            vkBeginCommandBuffer(_cb, ref beginInfo);
            _commandBufferBegun = true;

            ClearCachedState();
            _currentFramebuffer      = null;
            _currentGraphicsPipeline = null;
            Util.ClearArray(_currentGraphicsResourceSets);
            Util.ClearArray(_scissorRects);

            _currentComputePipeline = null;
            Util.ClearArray(_currentComputeResourceSets);

            _referencedResources.Clear();

            foreach (VkBuffer vkBuffer in _usedStagingBuffers)
            {
                _availableStagingBuffers.Add(vkBuffer);
            }

            _usedStagingBuffers.Clear();
        }
Exemple #8
0
        protected override void buildCommandBuffers()
        {
            VkCommandBufferBeginInfo cmdBufInfo = VkCommandBufferBeginInfo.New();

            FixedArray2 <VkClearValue> clearValues = new FixedArray2 <VkClearValue>();

            clearValues.First.color         = defaultClearColor;
            clearValues.Second.depthStencil = new VkClearDepthStencilValue()
            {
                depth = 1f, stencil = 0
            };

            VkRenderPassBeginInfo renderPassBeginInfo = VkRenderPassBeginInfo.New();

            renderPassBeginInfo.renderPass               = RenderPass;
            renderPassBeginInfo.renderArea.offset.x      = 0;
            renderPassBeginInfo.renderArea.offset.y      = 0;
            renderPassBeginInfo.renderArea.extent.width  = Width;
            renderPassBeginInfo.renderArea.extent.height = Height;
            renderPassBeginInfo.clearValueCount          = 2;
            renderPassBeginInfo.pClearValues             = (VkClearValue *)Unsafe.AsPointer(ref clearValues);

            for (int i = 0; i < DrawCmdBuffers.Count; ++i)
            {
                // Set target frame buffer
                renderPassBeginInfo.framebuffer = Framebuffers[i];

                Util.CheckResult(vkBeginCommandBuffer(DrawCmdBuffers[i], ref cmdBufInfo));

                vkCmdBeginRenderPass(DrawCmdBuffers[i], ref renderPassBeginInfo, VkSubpassContents.Inline);

                VkViewport viewport = new VkViewport()
                {
                    width = Width, height = Height, minDepth = 0f, maxDepth = 1f
                };
                vkCmdSetViewport(DrawCmdBuffers[i], 0, 1, ref viewport);

                VkRect2D scissor = new VkRect2D()
                {
                    extent = new VkExtent2D()
                    {
                        width = Width, height = Height
                    }, offset = new VkOffset2D()
                };
                vkCmdSetScissor(DrawCmdBuffers[i], 0, 1, ref scissor);

                vkCmdBindDescriptorSets(DrawCmdBuffers[i], VkPipelineBindPoint.Graphics, pipelineLayout, 0, 1, ref descriptorSet, 0, null);

                ulong offsets = 0;
                vkCmdBindVertexBuffers(DrawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, ref models_cube.vertices.buffer, ref offsets);
                vkCmdBindIndexBuffer(DrawCmdBuffers[i], models_cube.indices.buffer, 0, VkIndexType.Uint32);

                // Left : Solid colored
                viewport.width = Width / 3.0f;
                vkCmdSetViewport(DrawCmdBuffers[i], 0, 1, &viewport);
                vkCmdBindPipeline(DrawCmdBuffers[i], VkPipelineBindPoint.Graphics, pipelines_phong);

                vkCmdDrawIndexed(DrawCmdBuffers[i], models_cube.indexCount, 1, 0, 0, 0);

                // Center : Toon
                viewport.x = Width / 3.0f;
                vkCmdSetViewport(DrawCmdBuffers[i], 0, 1, &viewport);
                vkCmdBindPipeline(DrawCmdBuffers[i], VkPipelineBindPoint.Graphics, pipelines_toon);
                // Line Width > 1.0f only if wide lines feature is supported
                if (DeviceFeatures.wideLines != 0)
                {
                    vkCmdSetLineWidth(DrawCmdBuffers[i], 2.0f);
                }
                vkCmdDrawIndexed(DrawCmdBuffers[i], models_cube.indexCount, 1, 0, 0, 0);

                if (DeviceFeatures.fillModeNonSolid != 0)
                {
                    // Right : Wireframe
                    viewport.x = Width / 3.0f + Width / 3.0f;
                    vkCmdSetViewport(DrawCmdBuffers[i], 0, 1, &viewport);
                    vkCmdBindPipeline(DrawCmdBuffers[i], VkPipelineBindPoint.Graphics, pipelines_wireframe);
                    vkCmdDrawIndexed(DrawCmdBuffers[i], models_cube.indexCount, 1, 0, 0, 0);
                }

                vkCmdEndRenderPass(DrawCmdBuffers[i]);

                Util.CheckResult(vkEndCommandBuffer(DrawCmdBuffers[i]));
            }
        }
Exemple #9
0
        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));
        }
Exemple #10
0
        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, &region);
            }

            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);
        }
Exemple #11
0
        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();
        }
        private void FlushFrameDrawCommands()
        {
            _scInfo.AcquireNextImage(_device, _imageAvailableSemaphore);
            for (int i = 0; i < _renderPassStates.Count; i++)
            {
                RenderPassInfo renderPassState = _renderPassStates[i];

                VkCommandBuffer primaryCommandBuffer = GetPrimaryCommandBuffer();
                renderPassState.PrimaryCommandBuffer = primaryCommandBuffer;
                VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.New();
                beginInfo.flags = VkCommandBufferUsageFlags.OneTimeSubmit;
                vkBeginCommandBuffer(primaryCommandBuffer, ref beginInfo);
                VkRenderPassBeginInfo renderPassBeginInfo = VkRenderPassBeginInfo.New();
                VkFramebufferBase     fbInfo = renderPassState.Framebuffer;
                renderPassBeginInfo.framebuffer = fbInfo.VkFramebuffer;
                renderPassBeginInfo.renderPass  = renderPassState.ClearBuffer
                    ? fbInfo.RenderPassClearBuffer
                    : fbInfo.RenderPassNoClear;

                if (renderPassState.ClearBuffer)
                {
                    VkClearColorValue colorClear = new VkClearColorValue
                    {
                        float32_0 = renderPassState.ClearColor.R,
                        float32_1 = renderPassState.ClearColor.G,
                        float32_2 = renderPassState.ClearColor.B,
                        float32_3 = renderPassState.ClearColor.A
                    };
                    VkClearDepthStencilValue depthClear = new VkClearDepthStencilValue()
                    {
                        depth = 1f, stencil = 0
                    };
                    StackList <VkClearValue, Size512Bytes> clearValues = new StackList <VkClearValue, Size512Bytes>();
                    if (fbInfo.ColorTexture != null)
                    {
                        clearValues.Add(new VkClearValue()
                        {
                            color = colorClear
                        });
                    }
                    if (fbInfo.DepthTexture != null)
                    {
                        clearValues.Add(new VkClearValue()
                        {
                            depthStencil = depthClear
                        });
                    }

                    renderPassBeginInfo.clearValueCount = clearValues.Count;
                    renderPassBeginInfo.pClearValues    = (VkClearValue *)clearValues.Data;
                }
                renderPassBeginInfo.renderArea.extent = new VkExtent2D(fbInfo.Width, fbInfo.Height);

                vkCmdBeginRenderPass(primaryCommandBuffer, ref renderPassBeginInfo, VkSubpassContents.SecondaryCommandBuffers);
                RawList <VkCommandBuffer> secondaryCBs = renderPassState.SecondaryCommandBuffers;
                if (secondaryCBs.Count > 0)
                {
                    vkCmdExecuteCommands(primaryCommandBuffer, secondaryCBs.Count, ref secondaryCBs[0]);
                }
                vkCmdEndRenderPass(primaryCommandBuffer);
                vkEndCommandBuffer(primaryCommandBuffer);

                VkSubmitInfo         submitInfo    = VkSubmitInfo.New();
                VkSemaphore          waitSemaphore = (i == 0) ? _imageAvailableSemaphore : _renderPassSemaphores[i - 1];
                VkPipelineStageFlags waitStages    = VkPipelineStageFlags.ColorAttachmentOutput;
                submitInfo.waitSemaphoreCount = 1;
                submitInfo.pWaitSemaphores    = &waitSemaphore;
                submitInfo.pWaitDstStageMask  = &waitStages;
                VkCommandBuffer cb = primaryCommandBuffer;
                submitInfo.commandBufferCount = 1;
                submitInfo.pCommandBuffers    = &cb;
                VkSemaphore signalSemaphore = _renderPassSemaphores[i];
                submitInfo.signalSemaphoreCount = 1;
                submitInfo.pSignalSemaphores    = &signalSemaphore;
                vkQueueSubmit(_graphicsQueue, 1, ref submitInfo, VkFence.Null);
            }
        }
        private void DrawPrimitives(int indexCount, int instanceCount, int startingIndex, int startingVertex)
        {
            RenderPassInfo     renderPassState  = GetCurrentRenderPass();
            VkPipelineLayout   layout           = ShaderResourceBindingSlots.PipelineLayout;
            VkPipelineCacheKey pipelineCacheKey = new VkPipelineCacheKey();

            pipelineCacheKey.RenderPass        = renderPassState.Framebuffer.RenderPassClearBuffer;
            pipelineCacheKey.PipelineLayout    = layout;
            pipelineCacheKey.BlendState        = (VkBlendState)BlendState;
            pipelineCacheKey.Framebuffer       = renderPassState.Framebuffer;
            pipelineCacheKey.DepthStencilState = (VkDepthStencilState)DepthStencilState;
            pipelineCacheKey.RasterizerState   = (VkRasterizerState)RasterizerState;
            pipelineCacheKey.PrimitiveTopology = _primitiveTopology;
            pipelineCacheKey.ShaderSet         = ShaderSet;
            pipelineCacheKey.VertexBindings    = VertexBuffers;
            VkPipeline graphicsPipeline = _resourceCache.GetGraphicsPipeline(ref pipelineCacheKey);

            VkDescriptorSetCacheKey descriptorSetCacheKey = new VkDescriptorSetCacheKey();

            descriptorSetCacheKey.ShaderResourceBindingSlots = ShaderResourceBindingSlots;
            descriptorSetCacheKey.ConstantBuffers            = _constantBuffers;
            descriptorSetCacheKey.TextureBindings            = _textureBindings;
            descriptorSetCacheKey.SamplerStates = _samplerStates;
            VkDescriptorSet descriptorSet = _resourceCache.GetDescriptorSet(ref descriptorSetCacheKey);

            VkCommandBuffer          cb        = GetCommandBuffer();
            VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.New();

            beginInfo.flags = VkCommandBufferUsageFlags.OneTimeSubmit | VkCommandBufferUsageFlags.RenderPassContinue;
            VkCommandBufferInheritanceInfo inheritanceInfo = VkCommandBufferInheritanceInfo.New();

            inheritanceInfo.renderPass = renderPassState.Framebuffer.RenderPassClearBuffer;
            beginInfo.pInheritanceInfo = &inheritanceInfo;
            vkBeginCommandBuffer(cb, ref beginInfo);

            vkCmdBindPipeline(cb, VkPipelineBindPoint.Graphics, graphicsPipeline);
            vkCmdBindDescriptorSets(
                cb,
                VkPipelineBindPoint.Graphics,
                layout,
                0,
                1,
                ref descriptorSet,
                0,
                IntPtr.Zero);

            int vbCount = ShaderSet.InputLayout.InputDescriptions.Length;
            StackList <VkBuffer, Size512Bytes> vbs = new StackList <VkBuffer, Size512Bytes>();

            for (int vbIndex = 0; vbIndex < vbCount; vbIndex++)
            {
                vbs.Add(((VkVertexBuffer)VertexBuffers[vbIndex]).DeviceBuffer);
            }

            StackList <VkBuffer, Size512Bytes> offsets = new StackList <VkBuffer, Size512Bytes>();

            vkCmdBindVertexBuffers(cb, 0, vbs.Count, (IntPtr)vbs.Data, (IntPtr)offsets.Data);
            vkCmdBindIndexBuffer(cb, IndexBuffer.DeviceBuffer, 0, IndexBuffer.IndexType);
            VkViewport viewport = new VkViewport()
            {
                x        = Viewport.X,
                y        = Viewport.Y,
                width    = Viewport.Width,
                height   = Viewport.Height,
                minDepth = 0,
                maxDepth = 1
            };

            vkCmdSetViewport(cb, 0, 1, ref viewport);
            vkCmdSetScissor(cb, 0, 1, ref _scissorRect);
            vkCmdDrawIndexed(cb, (uint)indexCount, (uint)instanceCount, (uint)startingIndex, startingVertex, 0);
            vkEndCommandBuffer(cb);

            renderPassState.SecondaryCommandBuffers.Add(cb);
        }