Пример #1
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);
        }