/// <summary>
        /// Submits a sequence of semaphores or command buffers to a queue.
        /// </summary>
        /// <param name="submit">Specifies a command buffer submission batch.</param>
        /// <param name="fence">
        /// An optional handle to a fence to be signaled. If fence is not <c>null</c>, it defines a
        /// fence signal operation.
        /// </param>
        /// <exception cref="VulkanException">Vulkan returns an error code.</exception>
        public void Submit(SubmitInfo submit, Fence fence = null)
        {
            submit.ToNative(out SubmitInfo.Native nativeSubmit);
            Result result = vkQueueSubmit(this, 1, &nativeSubmit, fence);

            nativeSubmit.Free();
            VulkanException.ThrowForInvalidResult(result);
        }
Exemple #2
0
        private void displayRenderTarget(RenderTarget rt)
        {
            var cimg = _swapChainImages[_syncObjects.CurrentImage];

            // Begin recording
            _commandBuffer.Begin(ONE_TIME_SUBMIT);

            if (rt != null)
            {
                // Trasition the rt to transfer src, and the sc image to transfer dst
                _rtTransferBarrier.Image = rt.VkImage.Handle;
                _commandBuffer.CmdPipelineBarrier(Vk.PipelineStages.AllCommands, Vk.PipelineStages.AllCommands,
                                                  imageMemoryBarriers: new[] { _rtTransferBarrier, cimg.TransferBarrier });

                if (rt.Size != Extent)                 // We need to do a filtered blit because of the size mismatch
                {
                    var blit = new Vk.ImageBlit
                    {
                        SrcOffset1     = BLIT_ZERO,
                        SrcOffset2     = new Vk.Offset3D(rt.Size.X, rt.Size.Y, 1),
                        SrcSubresource = BLIT_SUBRESOURCE,
                        DstOffset1     = BLIT_ZERO,
                        DstOffset2     = new Vk.Offset3D(Extent.X, Extent.Y, 1),
                        DstSubresource = BLIT_SUBRESOURCE
                    };
                    _commandBuffer.CmdBlitImage(rt.VkImage, Vk.ImageLayout.TransferSrcOptimal, cimg.Image.Handle, Vk.ImageLayout.TransferDstOptimal,
                                                new[] { blit }, Vk.Filter.Linear);
                }
                else                 // Same size, we can do a much faster direct image copy
                {
                    var copy = new Vk.ImageCopy
                    {
                        SrcOffset      = BLIT_ZERO,
                        SrcSubresource = BLIT_SUBRESOURCE,
                        DstOffset      = BLIT_ZERO,
                        DstSubresource = BLIT_SUBRESOURCE,
                        Extent         = new Vk.Extent3D(rt.Size.X, rt.Size.Y, 1)
                    };
                    _commandBuffer.CmdCopyImage(rt.VkImage, Vk.ImageLayout.TransferSrcOptimal, cimg.Image, Vk.ImageLayout.TransferDstOptimal, new[] { copy });
                }

                // Transition both images back to their standard layouts
                _rtAttachBarrier.Image = rt.VkImage.Handle;
                _commandBuffer.CmdPipelineBarrier(Vk.PipelineStages.AllCommands, Vk.PipelineStages.AllCommands,
                                                  imageMemoryBarriers: new[] { _rtAttachBarrier, cimg.PresentBarrier });
            }
            else             // No render target, valid possibility if there is no active scene
            {
                // Trasition the sc image to transfer dst
                _commandBuffer.CmdPipelineBarrier(Vk.PipelineStages.AllCommands, Vk.PipelineStages.AllCommands,
                                                  imageMemoryBarriers: new[] { cimg.TransferBarrier });

                // Simply clear the swapchain image to black
                var clear = new Vk.ClearColorValue(0, 0, 0, 1);
                _commandBuffer.CmdClearColorImage(cimg.Image, Vk.ImageLayout.TransferDstOptimal, clear,
                                                  new Vk.ImageSubresourceRange(Vk.ImageAspects.Color, 0, 1, 0, 1));

                // Transition the image back to its present layout
                _commandBuffer.CmdPipelineBarrier(Vk.PipelineStages.AllCommands, Vk.PipelineStages.AllCommands,
                                                  imageMemoryBarriers: new[] { cimg.PresentBarrier });
            }

            // End the buffer, submit, and wait for the blit to complete
            // This performs GPU-GPU synchonrization by waiting for the swapchain image to be available before blitting
            _commandBuffer.End();
            var si = new Vk.SubmitInfo(waitDstStageMask: new[] { Vk.PipelineStages.Transfer }, waitSemaphores: new[] { _syncObjects.CurrentImageAvailable },
                                       commandBuffers: new[] { _commandBuffer }, signalSemaphores: new[] { _syncObjects.CurrentBlitComplete });

            _blitFence.Reset();             // Can need to happen when the swapchain is invalidated or resized
            _presentQueue.Submit(si, _blitFence);
        }