Ejemplo n.º 1
0
        public static unsafe void InsertImageBarrier(
            Vk api,
            CommandBuffer commandBuffer,
            Image image,
            AccessFlags srcAccessMask,
            AccessFlags dstAccessMask,
            PipelineStageFlags srcStageMask,
            PipelineStageFlags dstStageMask,
            ImageAspectFlags aspectFlags,
            int firstLayer,
            int firstLevel,
            int layers,
            int levels)
        {
            ImageMemoryBarrier memoryBarrier = new ImageMemoryBarrier()
            {
                SType               = StructureType.ImageMemoryBarrier,
                SrcAccessMask       = srcAccessMask,
                DstAccessMask       = dstAccessMask,
                SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
                DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
                Image               = image,
                OldLayout           = ImageLayout.General,
                NewLayout           = ImageLayout.General,
                SubresourceRange    = new ImageSubresourceRange(aspectFlags, (uint)firstLevel, (uint)levels, (uint)firstLayer, (uint)layers)
            };

            api.CmdPipelineBarrier(
                commandBuffer,
                srcStageMask,
                dstStageMask,
                0,
                0,
                null,
                0,
                null,
                1,
                memoryBarrier);
        }
Ejemplo n.º 2
0
        private unsafe CommandBuffer BeginImageCommandBuffer()
        {
            Device device = _renderer.Params.Device;
            Vk     vk     = _renderer.Vk;

            CommandBufferAllocateInfo commandBufferAllocateInfo = new()
            {
                SType = StructureType.CommandBufferAllocateInfo,

                CommandBufferCount = 1,
                CommandPool        = _renderer.ImageTransitionPool
            };

            _renderer.AssertVulkan(vk.AllocateCommandBuffers(device, commandBufferAllocateInfo, out CommandBuffer commandBuffer));

            CommandBufferBeginInfo commandBufferBeginInfo = new()
            {
                SType = StructureType.CommandBufferBeginInfo,
                Flags = CommandBufferUsageFlags.CommandBufferUsageOneTimeSubmitBit,

                PInheritanceInfo = null
            };

            _renderer.AssertVulkan(vk.BeginCommandBuffer(commandBuffer, commandBufferBeginInfo));

            return(commandBuffer);
        }

        private unsafe void EndImageCommandBuffer(CommandBuffer commandBuffer)
        {
            Device device = _renderer.Params.Device;
            Vk     vk     = _renderer.Vk;

            _renderer.AssertVulkan(vk.EndCommandBuffer(commandBuffer));

            SubmitInfo submitInfo = new()
            {
                SType = StructureType.SubmitInfo,

                CommandBufferCount = 1,
                PCommandBuffers    = &commandBuffer,

                SignalSemaphoreCount = 0,
                PSignalSemaphores    = null,
                WaitSemaphoreCount   = 0,
                PWaitSemaphores      = null,
                PWaitDstStageMask    = null
            };

            _renderer.AssertVulkan(vk.QueueSubmit(_renderer.ImageTransitionQueue, 1, submitInfo, default));
            _renderer.AssertVulkan(vk.QueueWaitIdle(_renderer.ImageTransitionQueue));

            vk.FreeCommandBuffers(device, _renderer.ImageTransitionPool, 1, commandBuffer);
        }

        private unsafe void TransitionImageLayout(ImageLayout oldLayout, ImageLayout newLayout)
        {
            Vk vk = _renderer.Vk;

            CommandBuffer commandBuffer = BeginImageCommandBuffer();

            ImageMemoryBarrier imageMemoryBarrier = new()
            {
                SType = StructureType.ImageMemoryBarrier,

                OldLayout = oldLayout,
                NewLayout = newLayout,

                SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
                DstQueueFamilyIndex = Vk.QueueFamilyIgnored,

                Image = _image,

                SubresourceRange = new ImageSubresourceRange()
                {
                    AspectMask     = ImageAspectFlags.ImageAspectColorBit,
                    BaseArrayLayer = 0,
                    LayerCount     = 1,
                    BaseMipLevel   = 0,
                    LevelCount     = _mipLevelCount
                },

                SrcAccessMask = 0,
                DstAccessMask = 0
            };

            if ((oldLayout == ImageLayout.Undefined) && (newLayout == ImageLayout.TransferDstOptimal))
            {
                imageMemoryBarrier.SrcAccessMask = 0;
                imageMemoryBarrier.DstAccessMask = AccessFlags.AccessTransferWriteBit;

                vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTopOfPipeBit, PipelineStageFlags.PipelineStageTransferBit, 0, 0, null, 0, null, 1, imageMemoryBarrier);
            }
            else if ((oldLayout == ImageLayout.TransferDstOptimal) && (newLayout == ImageLayout.ShaderReadOnlyOptimal))
            {
                imageMemoryBarrier.SrcAccessMask = AccessFlags.AccessTransferWriteBit;
                imageMemoryBarrier.DstAccessMask = AccessFlags.AccessShaderReadBit;

                vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageFragmentShaderBit, 0, 0, null, 0, null, 1, imageMemoryBarrier);
            }
            else if ((oldLayout == ImageLayout.ShaderReadOnlyOptimal) && (newLayout == ImageLayout.TransferDstOptimal))
            {
                imageMemoryBarrier.SrcAccessMask = AccessFlags.AccessShaderReadBit;
                imageMemoryBarrier.DstAccessMask = AccessFlags.AccessTransferWriteBit;

                vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageFragmentShaderBit, PipelineStageFlags.PipelineStageTransferBit, 0, 0, null, 0, null, 1, imageMemoryBarrier);
            }

            EndImageCommandBuffer(commandBuffer);
        }

        private void CopyBufferToImage(Buffer <byte> source)
        {
            Vk vk = _renderer.Vk;

            CommandBuffer commandBuffer = BeginImageCommandBuffer();

            BufferImageCopy bufferImageCopy = new()
            {
                BufferOffset      = 0,
                BufferRowLength   = 0,
                BufferImageHeight = 0,

                ImageSubresource = new ImageSubresourceLayers()
                {
                    AspectMask     = ImageAspectFlags.ImageAspectColorBit,
                    MipLevel       = 0,
                    BaseArrayLayer = 0,
                    LayerCount     = 1
                },

                ImageOffset = new Offset3D()
                {
                    X = 0,
                    Y = 0,
                    Z = 0
                },
                ImageExtent = new Extent3D()
                {
                    Width  = Size.X,
                    Height = Size.Y,
                    Depth  = 1
                }
            };

            vk.CmdCopyBufferToImage(commandBuffer, source.Handle, _image, ImageLayout.TransferDstOptimal, 1, bufferImageCopy);

            EndImageCommandBuffer(commandBuffer);
        }
Ejemplo n.º 3
0
        public unsafe void Mipmaps()
        {
            PhysicalDevice physicalDevice = _renderer.Params.PhysicalDevice;
            Vk             vk             = _renderer.Vk;

            vk.GetPhysicalDeviceFormatProperties(physicalDevice, _format, out FormatProperties formatProperties);
            if (!formatProperties.OptimalTilingFeatures.HasFlag(FormatFeatureFlags.FormatFeatureSampledImageFilterLinearBit)) // bitting not supported.
            {
                return;
            }

            CommandBuffer commandBuffer = BeginImageCommandBuffer();

            uint mipWidth  = Size.X;
            uint mipHeight = Size.Y;

            ImageMemoryBarrier barrier = new()
            {
                SType = StructureType.ImageMemoryBarrier,

                Image = _image,
                SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
                DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
                SubresourceRange    = new ImageSubresourceRange()
                {
                    AspectMask     = ImageAspectFlags.ImageAspectColorBit,
                    BaseArrayLayer = 0,
                    LayerCount     = 1,
                    BaseMipLevel   = 0,
                    LevelCount     = 1
                }
            };

            for (uint i = 1; i < _mipLevelCount; i++)
            {
                barrier.SubresourceRange.BaseMipLevel = i - 1;
                barrier.OldLayout     = ImageLayout.TransferDstOptimal;
                barrier.NewLayout     = ImageLayout.TransferSrcOptimal;
                barrier.SrcAccessMask = AccessFlags.AccessTransferWriteBit;
                barrier.DstAccessMask = AccessFlags.AccessTransferReadBit;

                vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageTransferBit, 0, 0, null, 0, null, 1, barrier);

                ImageBlit blit = new()
                {
                    SrcOffsets = new ImageBlit.SrcOffsetsBuffer()
                    {
                        Element0 = new Offset3D()
                        {
                            X = 0,
                            Y = 0,
                            Z = 0,
                        },
                        Element1 = new Offset3D()
                        {
                            X = (int)mipWidth,
                            Y = (int)mipHeight,
                            Z = 1
                        }
                    },
                    SrcSubresource = new ImageSubresourceLayers()
                    {
                        AspectMask     = ImageAspectFlags.ImageAspectColorBit,
                        MipLevel       = i - 1,
                        BaseArrayLayer = 0,
                        LayerCount     = 1
                    },
                    DstOffsets = new ImageBlit.DstOffsetsBuffer()
                    {
                        Element0 = new Offset3D()
                        {
                            X = 0,
                            Y = 0,
                            Z = 0
                        },
                        Element1 = new Offset3D()
                        {
                            X = (int)((mipWidth > 1) ? mipWidth / 2 : 1),
                            Y = (int)((mipHeight > 1) ? mipHeight / 2 : 1),
                            Z = 1
                        }
                    },
                    DstSubresource = new ImageSubresourceLayers()
                    {
                        AspectMask     = ImageAspectFlags.ImageAspectColorBit,
                        MipLevel       = i,
                        BaseArrayLayer = 0,
                        LayerCount     = 1
                    }
                };

                vk.CmdBlitImage(commandBuffer, _image, ImageLayout.TransferSrcOptimal,
                                _image, ImageLayout.TransferDstOptimal, 1, blit, HasFlag(ImageFlags.Nearest) ? Filter.Nearest : Filter.Linear);

                barrier.OldLayout     = ImageLayout.TransferSrcOptimal;
                barrier.NewLayout     = ImageLayout.ShaderReadOnlyOptimal;
                barrier.SrcAccessMask = AccessFlags.AccessTransferReadBit;
                barrier.DstAccessMask = AccessFlags.AccessShaderReadBit;

                vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageFragmentShaderBit, 0, 0, null, 0, null, 1, barrier);

                mipWidth  /= 2;
                mipHeight /= 2;
            }

            barrier.SubresourceRange.BaseMipLevel = _mipLevelCount - 1;
            barrier.OldLayout     = ImageLayout.TransferDstOptimal;
            barrier.NewLayout     = ImageLayout.ShaderReadOnlyOptimal;
            barrier.SrcAccessMask = AccessFlags.AccessTransferWriteBit;
            barrier.DstAccessMask = AccessFlags.AccessShaderReadBit;

            vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTransferBit, PipelineStageFlags.PipelineStageFragmentShaderBit, 0, 0, null, 0, null, 1, barrier);

            EndImageCommandBuffer(commandBuffer);
        }
Ejemplo n.º 4
0
        public unsafe void Run(int currentFrameIndex, int imageIndex, Semaphore waitSemaphore, Semaphore signalSemaphore, Fence signal)
        {
            var bufferInfo = new DescriptorBufferInfo(_commandBuffers[currentFrameIndex], 0,
                                                      (ulong)(sizeof(uint) * _commandBufferCapacities[currentFrameIndex]));

            _vk.UpdateDescriptorSets(_device, 1,
                                     new WriteDescriptorSet(dstSet: _targetDescriptorSets[currentFrameIndex], dstBinding: 1, dstArrayElement: 0,
                                                            descriptorCount: 1, descriptorType: DescriptorType.StorageBuffer, pBufferInfo: &bufferInfo), 0,
                                     null);


            var currentFrame = _frames[currentFrameIndex];

            _vk.ResetCommandPool(_device, currentFrame.CommandPool, 0).ThrowCode();
            _vk.AllocateCommandBuffers(_device,
                                       new CommandBufferAllocateInfo(commandPool: currentFrame.CommandPool, level: CommandBufferLevel.Primary,
                                                                     commandBufferCount: 1), out var commandBuffer).ThrowCode();

            Name(ObjectType.CommandBuffer, (ulong)commandBuffer.Handle, $"Command Buffer Frame {currentFrameIndex}");

            var renderContext = new RenderContext(_targetImageViews[imageIndex],
                                                  _targetSize, currentFrameIndex);

            _vk.BeginCommandBuffer(commandBuffer,
                                   new CommandBufferBeginInfo(flags: CommandBufferUsageFlags.CommandBufferUsageOneTimeSubmitBit))
            .ThrowCode();

            // var memoryBarrier = new ImageMemoryBarrier2KHR(srcStageMask: PipelineStageFlags2KHR.PipelineStage2TopOfPipeBitKhr,
            //     srcAccessMask: AccessFlags2KHR.Access2NoneKhr, dstStageMask: PipelineStageFlags2KHR.PipelineStage2TransferBitKhr,
            //     dstAccessMask: AccessFlags2KHR.Access2TransferWriteBitKhr,
            //     oldLayout: ImageLayout.Undefined, newLayout: ImageLayout.TransferDstOptimal,
            //     srcQueueFamilyIndex: Vk.QueueFamilyIgnored, dstQueueFamilyIndex: Vk.QueueFamilyIgnored,
            //     image: _targetImages.Span[imageIndex], subresourceRange: new ImageSubresourceRange(ImageAspectFlags.ImageAspectColorBit, 0, 1, 0, 1),
            //     sType: StructureType.ImageMemoryBarrier2Khr, pNext: null);
            // _khrSynchronization2.CmdPipelineBarrier2(commandBuffer, new DependencyInfoKHR(imageMemoryBarrierCount: 1,
            //     pImageMemoryBarriers: &memoryBarrier, dependencyFlags: 0, memoryBarrierCount: 0, pMemoryBarriers: null, bufferMemoryBarrierCount: 0, pBufferMemoryBarriers: null));

            _vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTopOfPipeBit,
                                   PipelineStageFlags.PipelineStageTransferBit, 0, 0, null, 0, null, 1,
                                   new ImageMemoryBarrier(srcAccessMask: AccessFlags.AccessNoneKhr,
                                                          dstAccessMask: AccessFlags.AccessTransferWriteBit, oldLayout: ImageLayout.Undefined,
                                                          newLayout: ImageLayout.TransferDstOptimal, srcQueueFamilyIndex: Vk.QueueFamilyIgnored,
                                                          dstQueueFamilyIndex: Vk.QueueFamilyIgnored, image: _targetImages.Span[imageIndex],
                                                          subresourceRange: new ImageSubresourceRange(ImageAspectFlags.ImageAspectColorBit, 0, 1, 0, 1)));

            _vk.CmdClearColorImage(commandBuffer, _targetImages.Span[imageIndex], ImageLayout.TransferDstOptimal,
                                   new ClearColorValue(0f, 0f, 0f, 1f), 1,
                                   new ImageSubresourceRange(ImageAspectFlags.ImageAspectColorBit, 0, 1, 0, 1));

            // var memoryBarrier2 = new ImageMemoryBarrier2KHR(srcStageMask: PipelineStageFlags2KHR.PipelineStage2TransferBitKhr,
            //     srcAccessMask: AccessFlags2KHR.Access2TransferWriteBitKhr, dstStageMask: PipelineStageFlags2KHR.PipelineStage2ComputeShaderBitKhr,
            //     dstAccessMask: AccessFlags2KHR.Access2ShaderReadBitKhr | AccessFlags2KHR.Access2ShaderWriteBitKhr,
            //     oldLayout: ImageLayout.TransferDstOptimal, newLayout: ImageLayout.General,
            //     srcQueueFamilyIndex: Vk.QueueFamilyIgnored, dstQueueFamilyIndex: Vk.QueueFamilyIgnored,
            //     image: _targetImages.Span[imageIndex], subresourceRange: new ImageSubresourceRange(ImageAspectFlags.ImageAspectColorBit, 0, 1, 0, 1));
            // _khrSynchronization2.CmdPipelineBarrier2(commandBuffer, new DependencyInfoKHR(imageMemoryBarrierCount: 1,
            //     pImageMemoryBarriers: &memoryBarrier2));

            _vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageTransferBit,
                                   PipelineStageFlags.PipelineStageComputeShaderBit, 0, 0, null, 0, null, 1,
                                   new ImageMemoryBarrier(srcAccessMask: AccessFlags.AccessTransferWriteBit,
                                                          dstAccessMask: AccessFlags.AccessShaderReadBit | AccessFlags.AccessShaderWriteBit, oldLayout: ImageLayout.TransferDstOptimal,
                                                          newLayout: ImageLayout.General, srcQueueFamilyIndex: Vk.QueueFamilyIgnored,
                                                          dstQueueFamilyIndex: Vk.QueueFamilyIgnored, image: _targetImages.Span[imageIndex],
                                                          subresourceRange: new ImageSubresourceRange(ImageAspectFlags.ImageAspectColorBit, 0, 1, 0, 1)));

            Span <uint> pValues = stackalloc uint[]
            {
                _targetSize.X, _targetSize.Y
            };

            _vk.CmdPushConstants(commandBuffer, _pipelineLayout, ShaderStageFlags.ShaderStageComputeBit, 0, (uint)pValues.Length * sizeof(uint), pValues);
            _vk.CmdBindDescriptorSets(commandBuffer, PipelineBindPoint.Compute, _pipelineLayout, 0, 1,
                                      _targetDescriptorSets[imageIndex], 0, null);
            _computeShader.Record(renderContext, commandBuffer);

            // var memoryBarrier3 = new ImageMemoryBarrier2KHR(srcStageMask: PipelineStageFlags2KHR.PipelineStage2ComputeShaderBitKhr,
            //      srcAccessMask: AccessFlags2KHR.Access2ShaderReadBitKhr | AccessFlags2KHR.Access2ShaderWriteBitKhr, dstStageMask: PipelineStageFlags2KHR.PipelineStage2BottomOfPipeBitKhr,
            //      dstAccessMask: AccessFlags2KHR.Access2NoneKhr,
            //      oldLayout: ImageLayout.General, newLayout: ImageLayout.PresentSrcKhr,
            //      srcQueueFamilyIndex: Vk.QueueFamilyIgnored, dstQueueFamilyIndex: Vk.QueueFamilyIgnored,
            //      image: _targetImages.Span[imageIndex], subresourceRange: new ImageSubresourceRange(ImageAspectFlags.ImageAspectColorBit, 0, 1, 0, 1));
            //  _khrSynchronization2.CmdPipelineBarrier2(commandBuffer, new DependencyInfoKHR(imageMemoryBarrierCount: 1,
            //      pImageMemoryBarriers: &memoryBarrier3));

            _vk.CmdPipelineBarrier(commandBuffer, PipelineStageFlags.PipelineStageComputeShaderBit,
                                   PipelineStageFlags.PipelineStageBottomOfPipeBit, 0, 0, null, 0, null, 1,
                                   new ImageMemoryBarrier(srcAccessMask: AccessFlags.AccessShaderReadBit | AccessFlags.AccessShaderWriteBit,
                                                          dstAccessMask: AccessFlags.AccessNoneKhr, oldLayout: ImageLayout.General,
                                                          newLayout: ImageLayout.PresentSrcKhr, srcQueueFamilyIndex: Vk.QueueFamilyIgnored,
                                                          dstQueueFamilyIndex: Vk.QueueFamilyIgnored, image: _targetImages.Span[imageIndex],
                                                          subresourceRange: new ImageSubresourceRange(ImageAspectFlags.ImageAspectColorBit, 0, 1, 0, 1)));

            _vk.EndCommandBuffer(commandBuffer);

            var waitDstStageMask = PipelineStageFlags.PipelineStageTransferBit;

            _vk.QueueSubmit(Queue, 1,
                            new SubmitInfo(waitSemaphoreCount: 1, pWaitSemaphores: &waitSemaphore, commandBufferCount: 1,
                                           pCommandBuffers: &commandBuffer, signalSemaphoreCount: 1, pSignalSemaphores: &signalSemaphore,
                                           pWaitDstStageMask: &waitDstStageMask), signal).ThrowCode();
        }