예제 #1
0
        protected void TransitionImageLayout(VkImage image, uint mipLevels, uint baseArrayLayer, uint layerCount, VkImageLayout oldLayout, VkImageLayout newLayout)
        {
            VkCommandBuffer cb = BeginOneTimeCommands();

            VkImageMemoryBarrier barrier = VkImageMemoryBarrier.New();

            barrier.oldLayout           = oldLayout;
            barrier.newLayout           = newLayout;
            barrier.srcQueueFamilyIndex = QueueFamilyIgnored;
            barrier.dstQueueFamilyIndex = QueueFamilyIgnored;
            barrier.image = image;
            barrier.subresourceRange.aspectMask     = VkImageAspectFlags.Color;
            barrier.subresourceRange.baseMipLevel   = 0;
            barrier.subresourceRange.levelCount     = mipLevels;
            barrier.subresourceRange.baseArrayLayer = baseArrayLayer;
            barrier.subresourceRange.layerCount     = layerCount;

            vkCmdPipelineBarrier(
                cb,
                VkPipelineStageFlags.TopOfPipe,
                VkPipelineStageFlags.TopOfPipe,
                VkDependencyFlags.None,
                0, null,
                0, null,
                1, &barrier);

            EndOneTimeCommands(cb);
        }
        private void setImageMemoryBarrier(VkCommandBuffer command,
                                           VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
                                           VkImageLayout oldLayout, VkImageLayout newLayout,
                                           VkImage image, VkImageAspectFlags aspectFlags)
        {
            var imageMemoryBarrier = new VkImageMemoryBarrier()
            {
                srcAccessMask       = srcAccessMask,
                dstAccessMask       = dstAccessMask,
                oldLayout           = oldLayout,
                newLayout           = newLayout,
                srcQueueFamilyIndex = ~0u,
                dstQueueFamilyIndex = ~0u,
                subresourceRange    = new VkImageSubresourceRange
                {
                    aspectMask     = aspectFlags,
                    baseMipLevel   = 0,
                    levelCount     = 1,
                    baseArrayLayer = 0,
                    layerCount     = 1,
                },
                image = image
            };

            VulkanAPI.vkCmdPipelineBarrier(
                command,
                VkPipelineStageFlags.VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
                VkPipelineStageFlags.VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
                0,
                null, // MemoryBarriers
                null, // BufferMemoryBarriers
                new VkImageMemoryBarrier[] { imageMemoryBarrier }
                );
        }
예제 #3
0
        public void SetLayout(
            CommandBuffer cmdbuffer,
            VkAccessFlags srcAccessMask,
            VkAccessFlags dstAccessMask,
            VkImageLayout oldImageLayout,
            VkImageLayout newImageLayout,
            VkImageSubresourceRange subresourceRange,
            VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands,
            VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands,
            uint srcQueueFamilyIndex          = Vk.QueueFamilyIgnored,
            uint dstQueueFamilyIndex          = Vk.QueueFamilyIgnored)
        {
            VkImageMemoryBarrier imageMemoryBarrier = VkImageMemoryBarrier.New();

            imageMemoryBarrier.srcQueueFamilyIndex = srcQueueFamilyIndex;
            imageMemoryBarrier.dstQueueFamilyIndex = dstQueueFamilyIndex;
            imageMemoryBarrier.oldLayout           = oldImageLayout;
            imageMemoryBarrier.newLayout           = newImageLayout;
            imageMemoryBarrier.image            = handle;
            imageMemoryBarrier.subresourceRange = subresourceRange;
            imageMemoryBarrier.srcAccessMask    = srcAccessMask;
            imageMemoryBarrier.dstAccessMask    = dstAccessMask;

            Vk.vkCmdPipelineBarrier(
                cmdbuffer.Handle,
                srcStageMask,
                dstStageMask,
                0,
                0, IntPtr.Zero,
                0, IntPtr.Zero,
                1, ref imageMemoryBarrier);
        }
예제 #4
0
        public void Barrier(PipelineStage srcStage, PipelineStage dstStage, BufferMemoryBarrier[] bufferBarriers, ImageMemoryBarrier[] imageBarriers)
        {
            if (locked)
            {
                var bufferBarrier = new VkBufferMemoryBarrier[bufferBarriers == null ? 0 : bufferBarriers.Length];
                if (bufferBarriers != null)
                {
                    for (int i = 0; i < bufferBarrier.Length; i++)
                    {
                        bufferBarrier[i] = new VkBufferMemoryBarrier()
                        {
                            sType  = VkStructureType.StructureTypeBufferMemoryBarrier,
                            buffer = bufferBarriers[i].Buffer.hndl,
                            srcQueueFamilyIndex = GraphicsDevice.GetFamilyIndex(devID, bufferBarriers[i].SrcFamily),
                            dstQueueFamilyIndex = GraphicsDevice.GetFamilyIndex(devID, bufferBarriers[i].DstFamily),
                            srcAccessMask       = (VkAccessFlags)bufferBarriers[i].Accesses,
                            dstAccessMask       = (VkAccessFlags)bufferBarriers[i].Stores,
                            offset = bufferBarriers[i].Offset,
                            size   = bufferBarriers[i].Size,
                        };
                    }
                }

                var imageBarrier = new VkImageMemoryBarrier[imageBarriers == null ? 0 : imageBarriers.Length];
                if (imageBarriers != null)
                {
                    for (int i = 0; i < imageBarrier.Length; i++)
                    {
                        imageBarrier[i] = new VkImageMemoryBarrier()
                        {
                            sType               = VkStructureType.StructureTypeImageMemoryBarrier,
                            oldLayout           = (VkImageLayout)imageBarriers[i].OldLayout,
                            newLayout           = (VkImageLayout)imageBarriers[i].NewLayout,
                            image               = imageBarriers[i].Image.hndl,
                            srcQueueFamilyIndex = GraphicsDevice.GetFamilyIndex(devID, imageBarriers[i].SrcFamily),
                            dstQueueFamilyIndex = GraphicsDevice.GetFamilyIndex(devID, imageBarriers[i].DstFamily),
                            srcAccessMask       = (VkAccessFlags)imageBarriers[i].Accesses,
                            dstAccessMask       = (VkAccessFlags)imageBarriers[i].Stores,
                            subresourceRange    = new VkImageSubresourceRange()
                            {
                                aspectMask     = (imageBarriers[i].Image.Format == ImageFormat.Depth32f ? VkImageAspectFlags.ImageAspectDepthBit : VkImageAspectFlags.ImageAspectColorBit),
                                baseArrayLayer = imageBarriers[i].BaseArrayLayer,
                                baseMipLevel   = imageBarriers[i].BaseMipLevel,
                                layerCount     = imageBarriers[i].LayerCount,
                                levelCount     = imageBarriers[i].LevelCount,
                            },
                        };
                    }
                }
                var imageBarrier_ptr  = imageBarrier.Pointer();
                var bufferBarrier_ptr = bufferBarrier.Pointer();
                vkCmdPipelineBarrier(hndl, (VkPipelineStageFlags)srcStage, (VkPipelineStageFlags)dstStage, 0, 0, IntPtr.Zero, (uint)bufferBarrier.Length, bufferBarrier_ptr, (uint)imageBarrier.Length, imageBarrier_ptr);
                IsEmpty = false;
            }
            else
            {
                throw new Exception("Command buffer not built.");
            }
        }
예제 #5
0
파일: Initializers.cs 프로젝트: gomson/vk
        /** @brief Initialize an image memory barrier with no image transfer ownership */
        public static VkImageMemoryBarrier imageMemoryBarrier()
        {
            VkImageMemoryBarrier imageMemoryBarrier = VkImageMemoryBarrier.New();

            imageMemoryBarrier.srcQueueFamilyIndex = QueueFamilyIgnored;
            imageMemoryBarrier.dstQueueFamilyIndex = QueueFamilyIgnored;
            return(imageMemoryBarrier);
        }
예제 #6
0
        void TransitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout)
        {
            var commandBuffer = BeginSingleTimeCommands();

            var barrier = new VkImageMemoryBarrier();

            barrier.oldLayout           = oldLayout;
            barrier.newLayout           = newLayout;
            barrier.srcQueueFamilyIndex = -1;    //VK_QUEUE_FAMILY_IGNORED
            barrier.dstQueueFamilyIndex = -1;
            barrier.image = image;
            barrier.subresourceRange.aspectMask     = VkImageAspectFlags.ColorBit;
            barrier.subresourceRange.baseMipLevel   = 0;
            barrier.subresourceRange.levelCount     = 1;
            barrier.subresourceRange.baseArrayLayer = 0;
            barrier.subresourceRange.layerCount     = 1;

            VkPipelineStageFlags source;
            VkPipelineStageFlags dest;

            if (oldLayout == VkImageLayout.Undefined && newLayout == VkImageLayout.TransferSrcOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.HostWriteBit;
                barrier.dstAccessMask = VkAccessFlags.TransferReadBit;

                source = VkPipelineStageFlags.HostBit;
                dest   = VkPipelineStageFlags.TransferBit;
            }
            else if (oldLayout == VkImageLayout.Undefined && newLayout == VkImageLayout.TransferDstOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.HostWriteBit;
                barrier.dstAccessMask = VkAccessFlags.TransferWriteBit;

                source = VkPipelineStageFlags.HostBit;
                dest   = VkPipelineStageFlags.TransferBit;
            }
            else if (oldLayout == VkImageLayout.TransferDstOptimal && newLayout == VkImageLayout.ShaderReadOnlyOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.TransferWriteBit;
                barrier.dstAccessMask = VkAccessFlags.ShaderReadBit;

                source = VkPipelineStageFlags.TransferBit;
                dest   = VkPipelineStageFlags.FragmentShaderBit;
            }
            else
            {
                throw new Exception("Unsupported transition");
            }

            commandBuffer.PipelineBarrier(
                source, dest,
                VkDependencyFlags.None,
                null, null, new List <VkImageMemoryBarrier> {
                barrier
            });

            EndSingleTimeCommand(commandBuffer);
        }
예제 #7
0
 /// <summary>
 /// To record a pipeline barrier, call:
 /// </summary>
 /// <param name="srcStageMask">is a bitmask of <c>VkPipelineStageFlagBits</c> specifying the <a href='https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#synchronization-pipeline-stages-masks'> source stage mask</a>.</param>
 /// <param name="dstStageMask">is a bitmask of <c>VkPipelineStageFlagBits</c> specifying the <a href='https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#synchronization-pipeline-stages-masks'> destination stage mask</a>.</param>
 /// <param name="dependencyFlags">is a bitmask of <c>VkDependencyFlagBits</c> specifying how execution and memory dependencies are formed.</param>
 /// <param name="barrier">is a pointer to an array of <see cref="VkMemoryBarrier"/> structures.</param>
 /// <param name="bufferBarrier">is a pointer to an array of <see cref="VkBufferMemoryBarrier"/> structures.</param>
 /// <param name="imageBarrier">is a pointer to an array of <see cref="VkImageMemoryBarrier"/> structures.</param>
 public void PipelineBarrier(VkPipelineStageFlag srcStageMask,
                             VkPipelineStageFlag dstStageMask,
                             VkDependencyFlag dependencyFlags, VkMemoryBarrier barrier = default(VkMemoryBarrier),
                             VkBufferMemoryBarrier bufferBarrier = default(VkBufferMemoryBarrier),
                             VkImageMemoryBarrier imageBarrier   = default(VkImageMemoryBarrier))
 {
     unsafe
     {
         VkCommandBuffer.vkCmdPipelineBarrier(Handle, srcStageMask, dstStageMask, dependencyFlags,
                                              barrier.SType != VkStructureType.BufferMemoryBarrier ? 0 : 1u, &barrier,
                                              bufferBarrier.SType != VkStructureType.BufferMemoryBarrier ? 0 : 1u, &bufferBarrier,
                                              imageBarrier.SType != VkStructureType.ImageMemoryBarrier ? 0 : 1u, &imageBarrier);
     }
 }
예제 #8
0
        public unsafe void TransferImageLayout(
            VkImage image,
            VkFormat format,
            VkImageLayout oldLayout,
            VkImageLayout newLayout,
            uint mipLevel = 0
            )
        {
            var aspect           = GetAspectFlags(image.Handle, format, newLayout);
            var sourceFlags      = GetImageTransferFlags(oldLayout);
            var destinationFlags = GetImageTransferFlags(newLayout);

            var barrier = new VkImageMemoryBarrier
            {
                sType               = VkStructureType.ImageMemoryBarrier,
                oldLayout           = oldLayout,
                newLayout           = newLayout,
                srcQueueFamilyIndex = VulkanNative.QueueFamilyIgnored,
                dstQueueFamilyIndex = VulkanNative.QueueFamilyIgnored,
                image               = image.Handle,
                srcAccessMask       = sourceFlags.Key,
                dstAccessMask       = destinationFlags.Key,
                subresourceRange    = new VkImageSubresourceRange
                {
                    aspectMask     = aspect,
                    baseMipLevel   = mipLevel,
                    levelCount     = 1,
                    baseArrayLayer = 0,
                    layerCount     = 1,
                }
            };

            VulkanNative.vkCmdPipelineBarrier(
                _handle,
                sourceFlags.Value,
                destinationFlags.Value,
                0, 0, null, 0, null,
                1,
                &barrier
                );
        }
예제 #9
0
        /// <summary>
        /// Records the an image memory barrier
        /// </summary>
        /// <param name="img">image</param>
        /// <param name="format">format</param>
        /// <param name="old">old layout</param>
        /// <param name="new">new layout</param>
        /// <param name="range">resource range</param>
        /// <param name="srcQueue">source queue</param>
        /// <param name="dstQueue">destination queue</param>
        /// <param name="flags">dependency flags</param>
        /// <returns>this</returns>
        public void ImageMemoryBarrier(VkImage img, VkFormat format, VkImageLayout old,
                                       VkImageLayout @new, VkImageSubresourceRange range, VkDependencyFlag flags = 0,
                                       uint srcQueue = Vulkan.QueueFamilyIgnored,
                                       uint dstQueue = Vulkan.QueueFamilyIgnored)
        {
            var spec = new VkImageMemoryBarrier()
            {
                SType               = VkStructureType.ImageMemoryBarrier,
                PNext               = IntPtr.Zero,
                OldLayout           = old,
                NewLayout           = @new,
                SrcQueueFamilyIndex = srcQueue,
                DstQueueFamilyIndex = dstQueue,
                Image               = img,
                SubresourceRange    = range,
                SrcAccessMask       = VkAccessFlag.None,
                DstAccessMask       = VkAccessFlag.None
            };

            GetStageInfo(old, out VkPipelineStageFlag srcFlag, out spec.SrcAccessMask);
            GetStageInfo(@new, out VkPipelineStageFlag dstFlag, out spec.DstAccessMask);
            PipelineBarrier(srcFlag, dstFlag, flags, default(VkMemoryBarrier),
                            default(VkBufferMemoryBarrier), spec);
        }
예제 #10
0
        public void WaitEvents(List <Event> events, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
                               List <MemoryBarrier> memoryBarriers, List <BufferMemoryBarrier> bufferMemoryBarriers, List <ImageMemoryBarrier> imageMemoryBarriers)
        {
            unsafe
            {
                var eventsNative = stackalloc VkEvent[events.Count];
                Interop.Marshal <VkEvent, Event>(events, eventsNative);

                int mbCount = 0;
                int bbCount = 0;
                int ibCount = 0;

                if (memoryBarriers != null)
                {
                    mbCount = memoryBarriers.Count;
                }
                if (bufferMemoryBarriers != null)
                {
                    bbCount = bufferMemoryBarriers.Count;
                }
                if (imageMemoryBarriers != null)
                    ibCount = imageMemoryBarriers.Count; }

                var mbNative = stackalloc VkMemoryBarrier[mbCount];
                var bbNative = stackalloc VkBufferMemoryBarrier[bbCount];
                var ibNative = stackalloc VkImageMemoryBarrier[ibCount];

                for (int i = 0; i < mbCount; i++)
                {
                    var mb = memoryBarriers[i];
                    mbNative[i]               = new VkMemoryBarrier();
                    mbNative[i].sType         = VkStructureType.MemoryBarrier;
                    mbNative[i].srcAccessMask = mb.srcAccessMask;
                    mbNative[i].dstAccessMask = mb.dstAccessMask;
                }

                for (int i = 0; i < bbCount; i++)
                {
                    var bb = bufferMemoryBarriers[i];
                    bbNative[i]                     = new VkBufferMemoryBarrier();
                    bbNative[i].sType               = VkStructureType.BufferMemoryBarrier;
                    bbNative[i].srcAccessMask       = bb.srcAccessMask;
                    bbNative[i].dstAccessMask       = bb.dstAccessMask;
                    bbNative[i].srcQueueFamilyIndex = bb.srcQueueFamilyIndex;
                    bbNative[i].dstQueueFamilyIndex = bb.dstQueueFamilyIndex;
                    bbNative[i].buffer              = bb.buffer.Native;
                    bbNative[i].offset              = bb.offset;
                    bbNative[i].size                = bb.size;
                }

                for (int i = 0; i < ibCount; i++)
                {
                    var ib = imageMemoryBarriers[i];
                    ibNative[i]                     = new VkImageMemoryBarrier();
                    ibNative[i].sType               = VkStructureType.ImageMemoryBarrier;
                    ibNative[i].srcAccessMask       = ib.srcAccessMask;
                    ibNative[i].dstAccessMask       = ib.dstAccessMask;
                    ibNative[i].oldLayout           = ib.oldLayout;
                    ibNative[i].newLayout           = ib.newLayout;
                    ibNative[i].srcQueueFamilyIndex = ib.srcQueueFamilyIndex;
                    ibNative[i].dstQueueFamilyIndex = ib.dstQueueFamilyIndex;
                    ibNative[i].image               = ib.image.Native;
                    ibNative[i].subresourceRange    = ib.subresourceRange;
                }

                Device.Commands.cmdWaitEvents(commandBuffer,
                                              (uint)events.Count, (IntPtr)eventsNative,
                                              srcStageMask, dstStageMask,
                                              (uint)mbCount, (IntPtr)mbNative,
                                              (uint)bbCount, (IntPtr)bbNative,
                                              (uint)ibCount, (IntPtr)ibNative);
            }
예제 #11
0
        void Preprocess()
        {
            Shader shader = Resources.Load <Shader>("shaders/brdf.shader");

            {
                Pass pass = shader.GetPass("SpMap");

                uint numMipTailLevels = (uint)kEnvMapLevels - 1;

                // Compute pre-filtered specular environment map.
                var specializationInfo = new SpecializationInfo(new VkSpecializationMapEntry(0, 0, sizeof(uint)));
                specializationInfo.Write(0, numMipTailLevels);
                pass.ComputeShader.SpecializationInfo = specializationInfo;
                DescriptorSetLayout resLayout = pass.GetResourceLayout(0);

                spSet = new DescriptorSet(resLayout);

                CommandBuffer commandBuffer = Graphics.BeginPrimaryCmd();

                // Copy base mipmap level into destination environment map.
                {
                    Span <VkImageMemoryBarrier> preCopyBarriers = stackalloc[]
                    {
                        new VkImageMemoryBarrier(cubeMap.image, 0, VkAccessFlags.TransferRead, VkImageLayout.ShaderReadOnlyOptimal, VkImageLayout.TransferSrcOptimal, VkImageAspectFlags.Color, 0, 1),
                        new VkImageMemoryBarrier(envMap.image, 0, VkAccessFlags.TransferWrite, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal),
                    };

                    Span <VkImageMemoryBarrier> postCopyBarriers = stackalloc[]
                    {
                        new VkImageMemoryBarrier(cubeMap.image, VkAccessFlags.TransferRead, VkAccessFlags.ShaderRead, VkImageLayout.TransferSrcOptimal, VkImageLayout.ShaderReadOnlyOptimal, VkImageAspectFlags.Color, 0, 1),
                        new VkImageMemoryBarrier(envMap.image, VkAccessFlags.TransferWrite, VkAccessFlags.ShaderWrite, VkImageLayout.TransferDstOptimal, VkImageLayout.General),
                    };

                    commandBuffer.PipelineBarrier(VkPipelineStageFlags.TopOfPipe, VkPipelineStageFlags.Transfer, preCopyBarriers);

                    VkImageCopy copyRegion = new VkImageCopy
                    {
                        extent = new VkExtent3D(envMap.width, envMap.height, 1)
                    };

                    copyRegion.srcSubresource.aspectMask = VkImageAspectFlags.Color;
                    copyRegion.srcSubresource.layerCount = envMap.layers;
                    copyRegion.dstSubresource            = copyRegion.srcSubresource;

                    commandBuffer.CopyImage(cubeMap.image, VkImageLayout.TransferSrcOptimal, envMap.image, VkImageLayout.TransferDstOptimal, ref copyRegion);
                    commandBuffer.PipelineBarrier(VkPipelineStageFlags.Transfer, VkPipelineStageFlags.ComputeShader, postCopyBarriers);

                    // Pre-filter rest of the mip-chain.
                    List <ImageView> envTextureMipTailViews = new List <ImageView>();

                    var inputTexture = new VkDescriptorImageInfo(computeSampler, cubeMap.imageView, VkImageLayout.ShaderReadOnlyOptimal);
                    spSet.Bind(0, ref inputTexture);

                    Span <VkDescriptorImageInfo> envTextureMipTailDescriptors = stackalloc VkDescriptorImageInfo[(int)numMipTailLevels];
                    for (uint level = 0; level < numMipTailLevels; ++level)
                    {
                        var view = ImageView.Create(envMap.image, VkImageViewType.ImageCube, VkFormat.R16G16B16A16SFloat, VkImageAspectFlags.Color, level + 1, 1, 0, envMap.image.arrayLayers);
                        envTextureMipTailViews.Add(view);
                        envTextureMipTailDescriptors[(int)level] = new VkDescriptorImageInfo(VkSampler.Null, view, VkImageLayout.General);
                    }

                    spSet.Bind(1, envTextureMipTailDescriptors);
                    spSet.UpdateSets();

                    commandBuffer.BindComputePipeline(pass);
                    commandBuffer.BindComputeResourceSet(pass.PipelineLayout, 0, spSet);

                    float deltaRoughness = 1.0f / Math.Max((float)numMipTailLevels, 1.0f);
                    for (uint level = 1, size = kEnvMapSize / 2; level < kEnvMapLevels; ++level, size /= 2)
                    {
                        uint numGroups = Math.Max(1, size / 32);

                        var pushConstants = new SpecularFilterPushConstants {
                            level = level - 1, roughness = level * deltaRoughness
                        };
                        commandBuffer.PushConstants(pass.PipelineLayout, VkShaderStageFlags.Compute, 0, ref pushConstants);
                        commandBuffer.Dispatch(numGroups, numGroups, 6);
                    }

                    var barrier = new VkImageMemoryBarrier(envMap.image, VkAccessFlags.ShaderWrite, 0, VkImageLayout.General, VkImageLayout.ShaderReadOnlyOptimal);
                    commandBuffer.PipelineBarrier(VkPipelineStageFlags.ComputeShader, VkPipelineStageFlags.BottomOfPipe, ref barrier);
                }

                Graphics.EndPrimaryCmd(commandBuffer);
            }

            // Compute diffuse irradiance cubemap
            {
                Pass pass = shader.GetPass("IrMap");
                DescriptorSetLayout resLayout = pass.GetResourceLayout(0);
                irSet = new DescriptorSet(resLayout, cubeMap, irMap);

                CommandBuffer commandBuffer = Graphics.BeginPrimaryCmd();
                {
                    Span <VkImageMemoryBarrier> barriers = stackalloc [] { new VkImageMemoryBarrier(irMap.image, 0, VkAccessFlags.ShaderWrite, VkImageLayout.Undefined, VkImageLayout.General) };
                    commandBuffer.PipelineBarrier(VkPipelineStageFlags.TopOfPipe, VkPipelineStageFlags.ComputeShader, barriers);

                    commandBuffer.BindComputePipeline(pass);
                    commandBuffer.BindComputeResourceSet(pass.PipelineLayout, 0, irSet);
                    commandBuffer.Dispatch(kIrradianceMapSize / 32, kIrradianceMapSize / 32, 6);

                    Span <VkImageMemoryBarrier> postDispatchBarrier = stackalloc [] { new VkImageMemoryBarrier(irMap.image, VkAccessFlags.ShaderWrite, 0, VkImageLayout.General, VkImageLayout.ShaderReadOnlyOptimal) };
                    commandBuffer.PipelineBarrier(VkPipelineStageFlags.ComputeShader, VkPipelineStageFlags.BottomOfPipe, postDispatchBarrier);
                }

                Graphics.EndPrimaryCmd(commandBuffer);
            }

            // Compute Cook-Torrance BRDF 2D LUT for split-sum approximation.
            {
                var pass = shader.GetPass("BrdfLUT");
                DescriptorSetLayout resLayout = pass.GetResourceLayout(0);
                brdfLUTSet = new DescriptorSet(resLayout, brdfLUT);

                CommandBuffer commandBuffer = Graphics.BeginPrimaryCmd();
                {
                    Span <VkImageMemoryBarrier> barriers = stackalloc [] { new VkImageMemoryBarrier(brdfLUT.image, 0, VkAccessFlags.ShaderWrite, VkImageLayout.Undefined, VkImageLayout.General) };
                    commandBuffer.PipelineBarrier(VkPipelineStageFlags.TopOfPipe, VkPipelineStageFlags.ComputeShader, barriers);

                    commandBuffer.BindComputePipeline(pass);
                    commandBuffer.BindComputeResourceSet(pass.PipelineLayout, 0, brdfLUTSet);
                    commandBuffer.Dispatch(kBRDF_LUT_Size / 32, kBRDF_LUT_Size / 32, 6);

                    Span <VkImageMemoryBarrier> postDispatchBarrier = stackalloc [] { new VkImageMemoryBarrier(brdfLUT.image, VkAccessFlags.ShaderWrite, 0, VkImageLayout.General, VkImageLayout.ShaderReadOnlyOptimal) };
                    commandBuffer.PipelineBarrier(VkPipelineStageFlags.ComputeShader, VkPipelineStageFlags.BottomOfPipe, postDispatchBarrier);
                }

                Graphics.EndPrimaryCmd(commandBuffer);
            }
        }

        int selected = 0;
        private unsafe void CreateBackBuffers()
        {
            // Create the texture object
            var backBufferDescription = new TextureDescription
            {
                ArraySize        = 1,
                Dimension        = TextureDimension.Texture2D,
                Height           = Description.BackBufferHeight,
                Width            = Description.BackBufferWidth,
                Depth            = 1,
                Flags            = TextureFlags.RenderTarget,
                Format           = Description.BackBufferFormat,
                MipLevels        = 1,
                MultisampleCount = MultisampleCount.None,
                Usage            = GraphicsResourceUsage.Default
            };

            backbuffer.InitializeWithoutResources(backBufferDescription);

            var createInfo = new VkImageViewCreateInfo
            {
                sType            = VkStructureType.ImageViewCreateInfo,
                subresourceRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, 0, 1),
                format           = backbuffer.NativeFormat,
                viewType         = VkImageViewType.Image2D,
            };

            // We initialize swapchain images to PresentSource, since we swap them out while in this layout.
            backbuffer.NativeAccessMask = VkAccessFlags.MemoryRead;
            backbuffer.NativeLayout     = VkImageLayout.PresentSrcKHR;

            var imageMemoryBarrier = new VkImageMemoryBarrier
            {
                sType            = VkStructureType.ImageMemoryBarrier,
                subresourceRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, 0, 1),
                oldLayout        = VkImageLayout.Undefined,
                newLayout        = VkImageLayout.PresentSrcKHR,
                srcAccessMask    = VkAccessFlags.None,
                dstAccessMask    = VkAccessFlags.MemoryRead
            };

            var commandBufferAllocationInfo = new VkCommandBufferAllocateInfo
            {
                sType              = VkStructureType.CommandBufferAllocateInfo,
                level              = VkCommandBufferLevel.Primary,
                commandPool        = GraphicsDevice.NativeCopyCommandPools.Value,
                commandBufferCount = 1
            };
            VkCommandBuffer commandBuffer;

            vkAllocateCommandBuffers(GraphicsDevice.NativeDevice, &commandBufferAllocationInfo, &commandBuffer);

            var beginInfo = new VkCommandBufferBeginInfo {
                sType = VkStructureType.CommandBufferBeginInfo
            };

            vkBeginCommandBuffer(commandBuffer, &beginInfo);

            var buffers = vkGetSwapchainImagesKHR(GraphicsDevice.NativeDevice, swapChain);

            swapchainImages = new SwapChainImageInfo[buffers.Length];

            for (int i = 0; i < buffers.Length; i++)
            {
                // Create image views
                swapchainImages[i].NativeImage = createInfo.image = buffers[i];
                vkCreateImageView(GraphicsDevice.NativeDevice, &createInfo, null, out swapchainImages[i].NativeColorAttachmentView);

                // Transition to default layout
                imageMemoryBarrier.image = buffers[i];
                vkCmdPipelineBarrier(commandBuffer, VkPipelineStageFlags.AllCommands, VkPipelineStageFlags.AllCommands, VkDependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier);
            }

            // Close and submit
            vkEndCommandBuffer(commandBuffer);

            var submitInfo = new VkSubmitInfo
            {
                sType = VkStructureType.SubmitInfo,
                commandBufferCount = 1,
                pCommandBuffers    = &commandBuffer,
            };

            lock (GraphicsDevice.QueueLock)
            {
                vkQueueSubmit(GraphicsDevice.NativeCommandQueue, 1, &submitInfo, VkFence.Null);
                vkQueueWaitIdle(GraphicsDevice.NativeCommandQueue);
            }

            vkFreeCommandBuffers(GraphicsDevice.NativeDevice, GraphicsDevice.NativeCopyCommandPools.Value, 1, &commandBuffer);

            // Get next image
            vkAcquireNextImageKHR(GraphicsDevice.NativeDevice, swapChain, ulong.MaxValue, GraphicsDevice.GetNextPresentSemaphore(), VkFence.Null, out currentBufferIndex);

            // Apply the first swap chain image to the texture
            backbuffer.SetNativeHandles(swapchainImages[currentBufferIndex].NativeImage, swapchainImages[currentBufferIndex].NativeColorAttachmentView);
        }
예제 #13
0
        private void RecordCommandBuffers()
        {
            VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange()
            {
                aspectMask     = VkImageAspectFlags.Color,
                baseMipLevel   = 0,
                baseArrayLayer = 0,
                layerCount     = 1,
                levelCount     = 1
            };

            for (int i = 0; i < CommandBuffers.Length; i++)
            {
                VkCommandBuffer cmdBuffer = CommandBuffers[i];

                VkCommandBufferBeginInfo beginInfo = new VkCommandBufferBeginInfo()
                {
                    sType = VkStructureType.CommandBufferBeginInfo,
                    flags = VkCommandBufferUsageFlags.SimultaneousUse
                };
                vkBeginCommandBuffer(cmdBuffer, &beginInfo);

                if (Context.PresentQueue != Context.GraphicsQueue)
                {
                    var barrierFromPresentToDraw = new VkImageMemoryBarrier(
                        SwapchainImages[i], subresourceRange,
                        VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentWrite,
                        VkImageLayout.Undefined, VkImageLayout.PresentSrcKHR,
                        (uint)Context.PresentQueueFamilyIndex, (uint)Context.GraphicsQueueFamilyIndex);

                    vkCmdPipelineBarrier(cmdBuffer,
                                         VkPipelineStageFlags.ColorAttachmentOutput,
                                         VkPipelineStageFlags.ColorAttachmentOutput,
                                         0,
                                         0, null, 0, null,
                                         1, &barrierFromPresentToDraw
                                         );
                }

                RecordCommandBuffer(cmdBuffer, i);

                if (Context.PresentQueue != Context.GraphicsQueue)
                {
                    var barrierFromDrawToPresent = new VkImageMemoryBarrier(
                        SwapchainImages[i], subresourceRange,
                        VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead,
                        VkImageLayout.PresentSrcKHR, VkImageLayout.PresentSrcKHR,
                        (uint)Context.GraphicsQueueFamilyIndex, (uint)Context.PresentQueueFamilyIndex);

                    vkCmdPipelineBarrier(cmdBuffer,
                                         VkPipelineStageFlags.ColorAttachmentOutput,
                                         VkPipelineStageFlags.BottomOfPipe,
                                         0,
                                         0, null, 0, null,
                                         1, &barrierFromDrawToPresent
                                         );
                }

                VkResult result = vkEndCommandBuffer(cmdBuffer);
                result.CheckResult();
            }
        }
예제 #14
0
        public void Execute(VkCommandBuffer buffer)
        {
            VkImageMemoryBarrier imageMemoryBarrier = VkImageMemoryBarrier.New();

            imageMemoryBarrier.srcAccessMask       = VkAccessFlags.None;
            imageMemoryBarrier.dstAccessMask       = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite;
            imageMemoryBarrier.oldLayout           = VkImageLayout.Undefined;
            imageMemoryBarrier.newLayout           = VkImageLayout.ColorAttachmentOptimal;
            imageMemoryBarrier.srcQueueFamilyIndex = VulkanNative.QueueFamilyIgnored;
            imageMemoryBarrier.dstQueueFamilyIndex = VulkanNative.QueueFamilyIgnored;
            imageMemoryBarrier.image            = swapchainImage;
            imageMemoryBarrier.subresourceRange = new VkImageSubresourceRange()
            {
                baseMipLevel   = 0,
                levelCount     = 1,
                baseArrayLayer = 0,
                layerCount     = 1,
                aspectMask     = VkImageAspectFlags.Color
            };

            vkCmdPipelineBarrier(buffer, VkPipelineStageFlags.AllGraphics, VkPipelineStageFlags.AllGraphics, VkDependencyFlags.ByRegion,
                                 0, null, 0, null, 1, &imageMemoryBarrier);

            VkClearColorValue clearColorValue = new VkClearColorValue {
                float32_0 = 3f / 255f, float32_1 = 2f / 255, float32_2 = 12f / 255, float32_3 = 1
            };
            VkClearDepthStencilValue clearDepthStencilValue = new VkClearDepthStencilValue(1, 0);

            VkClearValue[] clearValues = new VkClearValue[2];
            clearValues[0].color        = clearColorValue;
            clearValues[1].depthStencil = clearDepthStencilValue;

            VkRenderPassBeginInfo passBeginInfo = VkRenderPassBeginInfo.New();

            passBeginInfo.renderPass               = renderPass;
            passBeginInfo.framebuffer              = swapchainFramebuffer;
            passBeginInfo.renderArea.extent.width  = (uint)Program.width;
            passBeginInfo.renderArea.extent.height = (uint)Program.height;
            passBeginInfo.clearValueCount          = (uint)clearValues.Length;

            fixed(VkClearValue *ptr = clearValues)
            passBeginInfo.pClearValues = ptr;

            vkCmdBeginRenderPass(buffer, &passBeginInfo, VkSubpassContents.Inline);

            VkViewport viewport = new VkViewport();

            viewport.x      = 0;
            viewport.y      = (float)Program.height;
            viewport.width  = (float)Program.width;
            viewport.height = -(float)Program.height;

            VkRect2D scissor = new VkRect2D();

            scissor.offset.x      = 0;
            scissor.offset.y      = 0;
            scissor.extent.width  = (uint)Program.width;
            scissor.extent.height = (uint)Program.height;

            vkCmdSetViewport(buffer, 0, 1, &viewport);
            vkCmdSetScissor(buffer, 0, 1, &scissor);

            vkCmdBindPipeline(buffer, VkPipelineBindPoint.Graphics, pipeline);
            if (mesh.IsReady)
            {
                mesh.Use();
                VkBuffer[] databuffers = new VkBuffer[] { mesh.Mesh.vertices.Buffer, mesh.Mesh.vertices.Buffer, mesh.Mesh.vertices.Buffer, mesh.Mesh.vertices.Buffer };
                ulong[]    offsets     = new ulong[] { 0, 3 * 4, 6 * 4, 6 * 4 + 2 * 4 };

                fixed(VkBuffer *bptr = databuffers)
                fixed(ulong *optr = offsets)
                vkCmdBindVertexBuffers(buffer, 0, 4, bptr, optr);

                vkCmdBindIndexBuffer(buffer, mesh.Mesh.indices.Buffer, 0, VkIndexType.Uint32);

                uniformdata.Write(0, camera.View.ToFloatArray());
                uniformdata.Write(16, camera.Projection.ToFloatArray());

                UpdateUniformData(uniformdata, swapchainImageIndex);

                VkDescriptorSet  sets   = descriptorSets[swapchainImageIndex];
                VkPipelineLayout layout = pipelineLayout;
                vkCmdBindDescriptorSets(buffer, VkPipelineBindPoint.Graphics, layout, 0, 1, &sets, 0, null);

                vkCmdDrawIndexed(buffer, (uint)mesh.Mesh.indices.Length, 1, 0, 0, 0);
                mesh.StopUse();
            }

            vkCmdEndRenderPass(buffer);
        }
예제 #15
0
        /// <inheritdoc cref="Copy(GraphicsTexture, GraphicsBuffer)" />
        public void Copy(VulkanGraphicsTexture destination, VulkanGraphicsBuffer source)
        {
            ThrowIfNull(destination, nameof(destination));
            ThrowIfNull(source, nameof(source));

            var vulkanCommandBuffer = VulkanCommandBuffer;
            var vulkanImage         = destination.VulkanImage;

            BeginCopy();

            var vulkanBufferImageCopy = new VkBufferImageCopy {
                imageSubresource = new VkImageSubresourceLayers {
                    aspectMask = (uint)VK_IMAGE_ASPECT_COLOR_BIT,
                    layerCount = 1,
                },
                imageExtent = new VkExtent3D {
                    width  = (uint)destination.Width,
                    height = destination.Height,
                    depth  = destination.Depth,
                },
            };

            vkCmdCopyBufferToImage(vulkanCommandBuffer, source.VulkanBuffer, vulkanImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &vulkanBufferImageCopy);

            EndCopy();

            void BeginCopy()
            {
                var vulkanImageMemoryBarrier = new VkImageMemoryBarrier {
                    sType            = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
                    dstAccessMask    = (uint)VK_ACCESS_TRANSFER_WRITE_BIT,
                    oldLayout        = VK_IMAGE_LAYOUT_UNDEFINED,
                    newLayout        = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                    image            = vulkanImage,
                    subresourceRange = new VkImageSubresourceRange {
                        aspectMask = (uint)VK_IMAGE_ASPECT_COLOR_BIT,
                        levelCount = 1,
                        layerCount = 1,
                    },
                };

                vkCmdPipelineBarrier(vulkanCommandBuffer, (uint)VK_PIPELINE_STAGE_HOST_BIT, (uint)VK_PIPELINE_STAGE_TRANSFER_BIT, dependencyFlags: 0, memoryBarrierCount: 0, pMemoryBarriers: null, bufferMemoryBarrierCount: 0, pBufferMemoryBarriers: null, imageMemoryBarrierCount: 1, &vulkanImageMemoryBarrier);
            }

            void EndCopy()
            {
                var vulkanImageMemoryBarrier = new VkImageMemoryBarrier {
                    sType            = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
                    srcAccessMask    = (uint)VK_ACCESS_TRANSFER_WRITE_BIT,
                    dstAccessMask    = (uint)VK_ACCESS_SHADER_READ_BIT,
                    oldLayout        = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                    newLayout        = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
                    image            = vulkanImage,
                    subresourceRange = new VkImageSubresourceRange {
                        aspectMask = (uint)VK_IMAGE_ASPECT_COLOR_BIT,
                        levelCount = 1,
                        layerCount = 1,
                    },
                };

                vkCmdPipelineBarrier(vulkanCommandBuffer, (uint)VK_PIPELINE_STAGE_TRANSFER_BIT, (uint)VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, dependencyFlags: 0, memoryBarrierCount: 0, pMemoryBarriers: null, bufferMemoryBarrierCount: 0, pBufferMemoryBarriers: null, imageMemoryBarrierCount: 1, &vulkanImageMemoryBarrier);
            }
        }
예제 #16
0
 public void PipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint memoryBarrierCount, VkMemoryBarrier *memoryBarriers, uint bufferMemoryBarrierCount, VkBufferMemoryBarrier *bufferMemoryBarriers, VkImageMemoryBarrier imageMemoryBarriers)
 {
     vkCmdPipelineBarrier(handle, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, memoryBarriers, bufferMemoryBarrierCount, null, 1, &imageMemoryBarriers);
 }
예제 #17
0
        internal static VulkanImage Texture2D(VulkanContext ctx, TextureData tex2D)
        {
            ulong    size = (ulong)tex2D.Mipmaps[0].Size;
            VkBuffer stagingBuffer;
            var      bufferCreateInfo = new VkBufferCreateInfo
            {
                sType = VkStructureType.BufferCreateInfo,
                pNext = null,
                size  = (ulong)tex2D.Mipmaps[0].Size,
                usage = VkBufferUsageFlags.TransferSrc
            };

            vkCreateBuffer(ctx.Device, &bufferCreateInfo, null, out stagingBuffer);

            vkGetPhysicalDeviceMemoryProperties(ctx.PhysicalDevice, out VkPhysicalDeviceMemoryProperties memoryProperties);
            vkGetBufferMemoryRequirements(ctx.Device, stagingBuffer, out VkMemoryRequirements stagingMemReq);
            uint heapIndex = BufferHelper.GetMemoryTypeIndex(stagingMemReq.memoryTypeBits, VkMemoryPropertyFlags.HostVisible, memoryProperties);

            VkMemoryAllocateInfo memAllocInfo = new VkMemoryAllocateInfo()
            {
                sType           = VkStructureType.MemoryAllocateInfo,
                pNext           = null,
                allocationSize  = stagingMemReq.size,
                memoryTypeIndex = heapIndex
            };

            VkDeviceMemory stagingMemory;
            VkResult       result = vkAllocateMemory(ctx.Device, &memAllocInfo, null, &stagingMemory);

            result.CheckResult();

            result = vkBindBufferMemory(ctx.Device, stagingBuffer, stagingMemory, 0);
            result.CheckResult();

            void *vertexPtr;

            result = vkMapMemory(ctx.Device, stagingMemory, 0, (ulong)tex2D.Mipmaps[0].Size, 0, &vertexPtr);
            result.CheckResult();

            fixed(byte *dataPtr = &tex2D.Mipmaps[0].Data[0])
            {
                Buffer.MemoryCopy(dataPtr, vertexPtr, size, size);
            }

            vkUnmapMemory(ctx.Device, stagingMemory);

            // Setup buffer copy regions for each mip level.
            var bufferCopyRegions = new VkBufferImageCopy[tex2D.Mipmaps.Length]; // TODO: stackalloc
            int offset            = 0;

            for (int i = 0; i < bufferCopyRegions.Length; i++)
            {
                // TODO: from VulkanCore, doesn't look correct (reassigns bufferCopyRegions in each loop)
                bufferCopyRegions = new[]
                {
                    new VkBufferImageCopy
                    {
                        imageSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, (uint)i, 0, 1),
                        imageExtent      = tex2D.Mipmaps[0].Extent,
                        bufferOffset     = (ulong)offset
                    }
                };
                offset += tex2D.Mipmaps[i].Size;
            }

            // Create optimal tiled target image.
            var createInfo = new VkImageCreateInfo
            {
                sType         = VkStructureType.ImageCreateInfo,
                pNext         = null,
                imageType     = VkImageType.Image2D,
                format        = tex2D.Format,
                mipLevels     = (uint)tex2D.Mipmaps.Length,
                arrayLayers   = 1,
                samples       = VkSampleCountFlags.Count1,
                tiling        = VkImageTiling.Optimal,
                sharingMode   = VkSharingMode.Exclusive,
                initialLayout = VkImageLayout.Undefined,
                extent        = tex2D.Mipmaps[0].Extent,
                usage         = VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferDst
            };

            VkImage image;

            result = vkCreateImage(ctx.Device, &createInfo, null, out image);
            result.CheckResult();

            VkMemoryRequirements imageMemReq;

            vkGetImageMemoryRequirements(ctx.Device, image, out imageMemReq);

            vkGetPhysicalDeviceMemoryProperties(ctx.PhysicalDevice, out VkPhysicalDeviceMemoryProperties imageMemoryProperties);

            uint imageHeapIndex = BufferHelper.GetMemoryTypeIndex(imageMemReq.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal, imageMemoryProperties);

            var allocInfo = new VkMemoryAllocateInfo
            {
                sType           = VkStructureType.MemoryAllocateInfo,
                pNext           = null,
                allocationSize  = imageMemReq.size,
                memoryTypeIndex = imageHeapIndex,
            };
            VkDeviceMemory memory;

            result = vkAllocateMemory(ctx.Device, &allocInfo, null, &memory);
            result.CheckResult();

            result = vkBindImageMemory(ctx.Device, image, memory, 0);
            result.CheckResult();

            var subresourceRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, (uint)tex2D.Mipmaps.Length, 0, 1);

            // Copy the data from staging buffers to device local buffers.
            var allocInfo2 = new VkCommandBufferAllocateInfo()
            {
                sType       = VkStructureType.CommandBufferAllocateInfo,
                commandPool = ctx.GraphicsCommandPool,

                level = VkCommandBufferLevel.Primary,
                commandBufferCount = 1,
            };
            VkCommandBuffer cmdBuffer;

            vkAllocateCommandBuffers(ctx.Device, &allocInfo2, &cmdBuffer);

            VkCommandBufferBeginInfo beginInfo = new VkCommandBufferBeginInfo()
            {
                sType = VkStructureType.CommandBufferBeginInfo,
                flags = VkCommandBufferUsageFlags.OneTimeSubmit,
            };

            vkBeginCommandBuffer(cmdBuffer, &beginInfo);

            VkImageMemoryBarrier imageMemoryBarrier = new VkImageMemoryBarrier
            {
                sType               = VkStructureType.ImageMemoryBarrier,
                pNext               = null,
                image               = image,
                subresourceRange    = subresourceRange,
                srcAccessMask       = 0,
                dstAccessMask       = VkAccessFlags.TransferWrite,
                oldLayout           = VkImageLayout.Undefined,
                newLayout           = VkImageLayout.TransferDstOptimal,
                srcQueueFamilyIndex = QueueFamilyIgnored,
                dstQueueFamilyIndex = QueueFamilyIgnored
            };

            vkCmdPipelineBarrier(cmdBuffer, VkPipelineStageFlags.TopOfPipe, VkPipelineStageFlags.Transfer, VkDependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier);

            fixed(VkBufferImageCopy *regionsPtr = bufferCopyRegions)
            {
                vkCmdCopyBufferToImage(cmdBuffer, stagingBuffer, image, VkImageLayout.TransferDstOptimal, (uint)bufferCopyRegions.Length, regionsPtr);
            }

            VkImageMemoryBarrier imageMemoryBarrier2 = new VkImageMemoryBarrier
            {
                sType               = VkStructureType.ImageMemoryBarrier,
                pNext               = null,
                image               = image,
                subresourceRange    = subresourceRange,
                srcAccessMask       = VkAccessFlags.TransferWrite,
                dstAccessMask       = VkAccessFlags.ShaderRead,
                oldLayout           = VkImageLayout.TransferDstOptimal,
                newLayout           = VkImageLayout.ShaderReadOnlyOptimal,
                srcQueueFamilyIndex = (uint)QueueFamilyIgnored,
                dstQueueFamilyIndex = (uint)QueueFamilyIgnored
            };

            vkCmdPipelineBarrier(cmdBuffer, VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader, VkDependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier2);

            vkEndCommandBuffer(cmdBuffer);

            // Submit.
            VkFenceCreateInfo fenceCreateInfo = new VkFenceCreateInfo
            {
                sType = VkStructureType.FenceCreateInfo,
                pNext = null
            };
            VkFence fence;

            result = vkCreateFence(ctx.Device, &fenceCreateInfo, null, out fence);
            result.CheckResult();

            var submitInfo = new VkSubmitInfo
            {
                sType = VkStructureType.SubmitInfo,
                pNext = null,
                commandBufferCount = 1,
                pCommandBuffers    = &cmdBuffer
            };

            vkQueueSubmit(ctx.GraphicsQueue, submitInfo, fence);

            result = vkWaitForFences(ctx.Device, 1, &fence, false, ulong.MaxValue);
            result.CheckResult();

            // Cleanup staging resources.
            vkDestroyFence(ctx.Device, fence, null);
            vkFreeMemory(ctx.Device, stagingMemory, null);
            vkDestroyBuffer(ctx.Device, stagingBuffer, null);

            // Create image view.
            VkImageViewCreateInfo imageViewCreateInfo = new VkImageViewCreateInfo()
            {
                sType            = VkStructureType.ImageViewCreateInfo,
                image            = image,
                viewType         = VkImageViewType.Image2D,
                format           = tex2D.Format,
                subresourceRange = subresourceRange
            };

            VkImageView view;

            vkCreateImageView(ctx.Device, &imageViewCreateInfo, null, out view);

            return(new VulkanImage(ctx, image, memory, view, tex2D.Format));
        }
예제 #18
0
        // Create an image memory barrier for changing the layout of
        // an image and put it into an active command buffer
        void setImageLayout(
            VkCommandBuffer cmdBuffer,
            VkImage image,
            VkImageAspectFlags aspectMask,
            VkImageLayout oldImageLayout,
            VkImageLayout newImageLayout,
            VkImageSubresourceRange subresourceRange)
        {
            // Create an image barrier object
            VkImageMemoryBarrier imageMemoryBarrier = Initializers.imageMemoryBarrier();;

            imageMemoryBarrier.oldLayout        = oldImageLayout;
            imageMemoryBarrier.newLayout        = newImageLayout;
            imageMemoryBarrier.image            = image;
            imageMemoryBarrier.subresourceRange = subresourceRange;

            // Only sets masks for layouts used in this example
            // For a more complete version that can be used with other layouts see vks::tools::setImageLayout

            // Source layouts (old)
            switch (oldImageLayout)
            {
            case VkImageLayout.Undefined:
                // Only valid as initial layout, memory contents are not preserved
                // Can be accessed directly, no source dependency required
                imageMemoryBarrier.srcAccessMask = 0;
                break;

            case VkImageLayout.Preinitialized:
                // Only valid as initial layout for linear images, preserves memory contents
                // Make sure host writes to the image have been finished
                imageMemoryBarrier.srcAccessMask = VkAccessFlags.HostWrite;
                break;

            case VkImageLayout.TransferDstOptimal:
                // Old layout is transfer destination
                // Make sure any writes to the image have been finished
                imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferWrite;
                break;
            }

            // Target layouts (new)
            switch (newImageLayout)
            {
            case VkImageLayout.TransferSrcOptimal:
                // Transfer source (copy, blit)
                // Make sure any reads from the image have been finished
                imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferRead;
                break;

            case VkImageLayout.TransferDstOptimal:
                // Transfer destination (copy, blit)
                // Make sure any writes to the image have been finished
                imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferWrite;
                break;

            case VkImageLayout.ShaderReadOnlyOptimal:
                // Shader read (sampler, input attachment)
                imageMemoryBarrier.dstAccessMask = VkAccessFlags.ShaderRead;
                break;
            }

            // Put barrier on top of pipeline
            VkPipelineStageFlags srcStageFlags  = VkPipelineStageFlags.TopOfPipe;
            VkPipelineStageFlags destStageFlags = VkPipelineStageFlags.TopOfPipe;

            // Put barrier inside setup command buffer
            vkCmdPipelineBarrier(
                cmdBuffer,
                srcStageFlags,
                destStageFlags,
                VkDependencyFlags.None,
                0, null,
                0, null,
                1, &imageMemoryBarrier);
        }
예제 #19
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);
        }
예제 #20
0
파일: Tools.cs 프로젝트: bitzhuwei/vk.other
        // Create an image memory barrier for changing the layout of
        // an image and put it into an active command buffer
        // See chapter 11.4 "Image Layout" for details

        public static void setImageLayout(
            VkCommandBuffer cmdbuffer,
            VkImage image,
            VkImageAspectFlags aspectMask,
            VkImageLayout oldImageLayout,
            VkImageLayout newImageLayout,
            VkImageSubresourceRange subresourceRange,
            VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands,
            VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands)
        {
            // Create an image barrier object
            VkImageMemoryBarrier imageMemoryBarrier = Initializers.imageMemoryBarrier();

            imageMemoryBarrier.oldLayout        = oldImageLayout;
            imageMemoryBarrier.newLayout        = newImageLayout;
            imageMemoryBarrier.image            = image;
            imageMemoryBarrier.subresourceRange = subresourceRange;

            // Source layouts (old)
            // Source access mask controls actions that have to be finished on the old layout
            // before it will be transitioned to the new layout
            switch (oldImageLayout)
            {
            case VkImageLayout.Undefined:
                // Image layout is undefined (or does not matter)
                // Only valid as initial layout
                // No flags required, listed only for completeness
                imageMemoryBarrier.srcAccessMask = 0;
                break;

            case VkImageLayout.Preinitialized:
                // Image is preinitialized
                // Only valid as initial layout for linear images, preserves memory contents
                // Make sure host writes have been finished
                imageMemoryBarrier.srcAccessMask = VkAccessFlags.HostWrite;
                break;

            case VkImageLayout.ColorAttachmentOptimal:
                // Image is a color attachment
                // Make sure any writes to the color buffer have been finished
                imageMemoryBarrier.srcAccessMask = VkAccessFlags.ColorAttachmentWrite;
                break;

            case VkImageLayout.DepthStencilAttachmentOptimal:
                // Image is a depth/stencil attachment
                // Make sure any writes to the depth/stencil buffer have been finished
                imageMemoryBarrier.srcAccessMask = VkAccessFlags.DepthStencilAttachmentWrite;
                break;

            case VkImageLayout.TransferSrcOptimal:
                // Image is a transfer source
                // Make sure any reads from the image have been finished
                imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferRead;
                break;

            case VkImageLayout.TransferDstOptimal:
                // Image is a transfer destination
                // Make sure any writes to the image have been finished
                imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferWrite;
                break;

            case VkImageLayout.ShaderReadOnlyOptimal:
                // Image is read by a shader
                // Make sure any shader reads from the image have been finished
                imageMemoryBarrier.srcAccessMask = VkAccessFlags.ShaderRead;
                break;
            }

            // Target layouts (new)
            // Destination access mask controls the dependency for the new image layout
            switch (newImageLayout)
            {
            case VkImageLayout.TransferDstOptimal:
                // Image will be used as a transfer destination
                // Make sure any writes to the image have been finished
                imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferWrite;
                break;

            case VkImageLayout.TransferSrcOptimal:
                // Image will be used as a transfer source
                // Make sure any reads from and writes to the image have been finished
                imageMemoryBarrier.srcAccessMask = imageMemoryBarrier.srcAccessMask | VkAccessFlags.TransferRead;
                imageMemoryBarrier.dstAccessMask = VkAccessFlags.TransferRead;
                break;

            case VkImageLayout.ColorAttachmentOptimal:
                // Image will be used as a color attachment
                // Make sure any writes to the color buffer have been finished
                imageMemoryBarrier.srcAccessMask = VkAccessFlags.TransferRead;
                imageMemoryBarrier.dstAccessMask = VkAccessFlags.ColorAttachmentWrite;
                break;

            case VkImageLayout.DepthStencilAttachmentOptimal:
                // Image layout will be used as a depth/stencil attachment
                // Make sure any writes to depth/stencil buffer have been finished
                imageMemoryBarrier.dstAccessMask = imageMemoryBarrier.dstAccessMask | VkAccessFlags.DepthStencilAttachmentWrite;
                break;

            case VkImageLayout.ShaderReadOnlyOptimal:
                // Image will be read in a shader (sampler, input attachment)
                // Make sure any writes to the image have been finished
                if (imageMemoryBarrier.srcAccessMask == 0)
                {
                    imageMemoryBarrier.srcAccessMask = VkAccessFlags.HostWrite | VkAccessFlags.TransferWrite;
                }
                imageMemoryBarrier.dstAccessMask = VkAccessFlags.ShaderRead;
                break;
            }

            // Put barrier inside setup command buffer
            vkCmdPipelineBarrier(
                cmdbuffer,
                srcStageMask,
                dstStageMask,
                0,
                0, null,
                0, null,
                1, &imageMemoryBarrier);
        }
예제 #21
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));
        }
예제 #22
0
        public static void TransitionImageLayout(
            VkCommandBuffer cb,
            VkImage image,
            uint baseMipLevel,
            uint levelCount,
            uint baseArrayLayer,
            uint layerCount,
            VkImageAspectFlags aspectMask,
            VkImageLayout oldLayout,
            VkImageLayout newLayout)
        {
            Debug.Assert(oldLayout != newLayout);
            VkImageMemoryBarrier barrier = VkImageMemoryBarrier.New();

            barrier.oldLayout           = oldLayout;
            barrier.newLayout           = newLayout;
            barrier.srcQueueFamilyIndex = QueueFamilyIgnored;
            barrier.dstQueueFamilyIndex = QueueFamilyIgnored;
            barrier.image = image;
            barrier.subresourceRange.aspectMask     = aspectMask;
            barrier.subresourceRange.baseMipLevel   = baseMipLevel;
            barrier.subresourceRange.levelCount     = levelCount;
            barrier.subresourceRange.baseArrayLayer = baseArrayLayer;
            barrier.subresourceRange.layerCount     = layerCount;

            VkPipelineStageFlags srcStageFlags = VkPipelineStageFlags.None;
            VkPipelineStageFlags dstStageFlags = VkPipelineStageFlags.None;

            if ((oldLayout == VkImageLayout.Undefined || oldLayout == VkImageLayout.Preinitialized) && newLayout == VkImageLayout.TransferDstOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.None;
                barrier.dstAccessMask = VkAccessFlags.TransferWrite;
                srcStageFlags         = VkPipelineStageFlags.TopOfPipe;
                dstStageFlags         = VkPipelineStageFlags.Transfer;
            }
            else if (oldLayout == VkImageLayout.ShaderReadOnlyOptimal && newLayout == VkImageLayout.TransferSrcOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.ShaderRead;
                barrier.dstAccessMask = VkAccessFlags.TransferRead;
                srcStageFlags         = VkPipelineStageFlags.FragmentShader;
                dstStageFlags         = VkPipelineStageFlags.Transfer;
            }
            else if (oldLayout == VkImageLayout.ShaderReadOnlyOptimal && newLayout == VkImageLayout.TransferDstOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.ShaderRead;
                barrier.dstAccessMask = VkAccessFlags.TransferWrite;
                srcStageFlags         = VkPipelineStageFlags.FragmentShader;
                dstStageFlags         = VkPipelineStageFlags.Transfer;
            }
            else if (oldLayout == VkImageLayout.Preinitialized && newLayout == VkImageLayout.TransferSrcOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.None;
                barrier.dstAccessMask = VkAccessFlags.TransferRead;
                srcStageFlags         = VkPipelineStageFlags.TopOfPipe;
                dstStageFlags         = VkPipelineStageFlags.Transfer;
            }
            else if (oldLayout == VkImageLayout.TransferSrcOptimal && newLayout == VkImageLayout.ShaderReadOnlyOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.TransferRead;
                barrier.dstAccessMask = VkAccessFlags.ShaderRead;
                srcStageFlags         = VkPipelineStageFlags.Transfer;
                dstStageFlags         = VkPipelineStageFlags.FragmentShader;
            }
            else if (oldLayout == VkImageLayout.TransferDstOptimal && newLayout == VkImageLayout.ShaderReadOnlyOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.TransferWrite;
                barrier.dstAccessMask = VkAccessFlags.ShaderRead;
                srcStageFlags         = VkPipelineStageFlags.Transfer;
                dstStageFlags         = VkPipelineStageFlags.FragmentShader;
            }
            else if (oldLayout == VkImageLayout.TransferSrcOptimal && newLayout == VkImageLayout.TransferDstOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.TransferRead;
                barrier.dstAccessMask = VkAccessFlags.TransferWrite;
                srcStageFlags         = VkPipelineStageFlags.Transfer;
                dstStageFlags         = VkPipelineStageFlags.Transfer;
            }
            else if (oldLayout == VkImageLayout.TransferDstOptimal && newLayout == VkImageLayout.TransferSrcOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.TransferWrite;
                barrier.dstAccessMask = VkAccessFlags.TransferRead;
                srcStageFlags         = VkPipelineStageFlags.Transfer;
                dstStageFlags         = VkPipelineStageFlags.Transfer;
            }
            else if (oldLayout == VkImageLayout.ColorAttachmentOptimal && newLayout == VkImageLayout.TransferSrcOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.ColorAttachmentWrite;
                barrier.dstAccessMask = VkAccessFlags.TransferRead;
                srcStageFlags         = VkPipelineStageFlags.ColorAttachmentOutput;
                dstStageFlags         = VkPipelineStageFlags.Transfer;
            }
            else if (oldLayout == VkImageLayout.ColorAttachmentOptimal && newLayout == VkImageLayout.TransferDstOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.ColorAttachmentWrite;
                barrier.dstAccessMask = VkAccessFlags.TransferWrite;
                srcStageFlags         = VkPipelineStageFlags.ColorAttachmentOutput;
                dstStageFlags         = VkPipelineStageFlags.Transfer;
            }
            else if (oldLayout == VkImageLayout.ColorAttachmentOptimal && newLayout == VkImageLayout.ShaderReadOnlyOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.ColorAttachmentWrite;
                barrier.dstAccessMask = VkAccessFlags.ShaderRead;
                srcStageFlags         = VkPipelineStageFlags.ColorAttachmentOutput;
                dstStageFlags         = VkPipelineStageFlags.FragmentShader;
            }
            else if (oldLayout == VkImageLayout.DepthStencilAttachmentOptimal && newLayout == VkImageLayout.ShaderReadOnlyOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.DepthStencilAttachmentWrite;
                barrier.dstAccessMask = VkAccessFlags.ShaderRead;
                srcStageFlags         = VkPipelineStageFlags.LateFragmentTests;
                dstStageFlags         = VkPipelineStageFlags.FragmentShader;
            }
            else if (oldLayout == VkImageLayout.ColorAttachmentOptimal && newLayout == VkImageLayout.PresentSrcKHR)
            {
                barrier.srcAccessMask = VkAccessFlags.ColorAttachmentWrite;
                barrier.dstAccessMask = VkAccessFlags.MemoryRead;
                srcStageFlags         = VkPipelineStageFlags.ColorAttachmentOutput;
                dstStageFlags         = VkPipelineStageFlags.BottomOfPipe;
            }
            else if (oldLayout == VkImageLayout.TransferDstOptimal && newLayout == VkImageLayout.ColorAttachmentOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.TransferWrite;
                barrier.dstAccessMask = VkAccessFlags.ColorAttachmentWrite;
                srcStageFlags         = VkPipelineStageFlags.Transfer;
                dstStageFlags         = VkPipelineStageFlags.ColorAttachmentOutput;
            }
            else if (oldLayout == VkImageLayout.TransferDstOptimal && newLayout == VkImageLayout.DepthStencilAttachmentOptimal)
            {
                barrier.srcAccessMask = VkAccessFlags.TransferWrite;
                barrier.dstAccessMask = VkAccessFlags.DepthStencilAttachmentWrite;
                srcStageFlags         = VkPipelineStageFlags.Transfer;
                dstStageFlags         = VkPipelineStageFlags.LateFragmentTests;
            }
            else
            {
                Debug.Fail("Invalid image layout transition.");
            }

            vkCmdPipelineBarrier(
                cb,
                srcStageFlags,
                dstStageFlags,
                VkDependencyFlags.None,
                0, null,
                0, null,
                1, &barrier);
        }
예제 #23
0
        private unsafe void InitializeImage(DataBox[] dataBoxes)
        {
            // Begin copy command buffer
            var commandBufferAllocateInfo = new VkCommandBufferAllocateInfo
            {
                sType              = VkStructureType.CommandBufferAllocateInfo,
                commandPool        = GraphicsDevice.NativeCopyCommandPool,
                commandBufferCount = 1,
                level              = VkCommandBufferLevel.Primary
            };
            VkCommandBuffer commandBuffer;

            lock (GraphicsDevice.QueueLock)
            {
                vkAllocateCommandBuffers(GraphicsDevice.NativeDevice, &commandBufferAllocateInfo, &commandBuffer);
            }

            var beginInfo = new VkCommandBufferBeginInfo {
                sType = VkStructureType.CommandBufferBeginInfo, flags = VkCommandBufferUsageFlags.OneTimeSubmit
            };

            vkBeginCommandBuffer(commandBuffer, &beginInfo);

            if (dataBoxes != null && dataBoxes.Length > 0)
            {
                // Buffer-to-image copies need to be aligned to the pixel size and 4 (always a power of 2)
                var blockSize     = Format.IsCompressed() ? NativeFormat.BlockSizeInBytes() : TexturePixelSize;
                var alignmentMask = (blockSize < 4 ? 4 : blockSize) - 1;

                int totalSize = dataBoxes.Length * alignmentMask;
                for (int i = 0; i < dataBoxes.Length; i++)
                {
                    totalSize += dataBoxes[i].SlicePitch;
                }

                VkBuffer uploadResource;
                int      uploadOffset;
                var      uploadMemory = GraphicsDevice.AllocateUploadBuffer(totalSize, out uploadResource, out uploadOffset);

                // Upload buffer barrier
                var bufferMemoryBarrier = new VkBufferMemoryBarrier(uploadResource, VkAccessFlags.HostWrite, VkAccessFlags.TransferRead, (ulong)uploadOffset, (ulong)totalSize);

                // Image barrier
                var initialBarrier = new VkImageMemoryBarrier(NativeImage, new VkImageSubresourceRange(NativeImageAspect, 0, uint.MaxValue, 0, uint.MaxValue), VkAccessFlags.None, VkAccessFlags.TransferWrite, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal);
                vkCmdPipelineBarrier(commandBuffer, VkPipelineStageFlags.Host, VkPipelineStageFlags.Transfer, VkDependencyFlags.None, 0, null, 1, &bufferMemoryBarrier, 1, &initialBarrier);

                // Copy data boxes to upload buffer
                var copies = new VkBufferImageCopy[dataBoxes.Length];
                for (int i = 0; i < copies.Length; i++)
                {
                    var slicePitch = dataBoxes[i].SlicePitch;

                    int arraySlice        = i / MipLevels;
                    int mipSlice          = i % MipLevels;
                    var mipMapDescription = GetMipMapDescription(mipSlice);

                    var alignment = ((uploadOffset + alignmentMask) & ~alignmentMask) - uploadOffset;
                    uploadMemory += alignment;
                    uploadOffset += alignment;

                    Utilities.CopyMemory(uploadMemory, dataBoxes[i].DataPointer, slicePitch);

                    // TODO VULKAN: Check if pitches are valid
                    copies[i] = new VkBufferImageCopy
                    {
                        bufferOffset      = (ulong)uploadOffset,
                        imageSubresource  = new VkImageSubresourceLayers(VkImageAspectFlags.Color, (uint)mipSlice, (uint)arraySlice, 1),
                        bufferRowLength   = 0, //(uint)(dataBoxes[i].RowPitch / pixelSize),
                        bufferImageHeight = 0, //(uint)(dataBoxes[i].SlicePitch / dataBoxes[i].RowPitch),
                        imageOffset       = new Vortice.Mathematics.Point3(0, 0, 0),
                        imageExtent       = new Vortice.Mathematics.Size3(mipMapDescription.Width, mipMapDescription.Height, mipMapDescription.Depth)
                    };

                    uploadMemory += slicePitch;
                    uploadOffset += slicePitch;
                }

                // Copy from upload buffer to image
                fixed(VkBufferImageCopy *copiesPointer = &copies[0])
                {
                    vkCmdCopyBufferToImage(commandBuffer, uploadResource, NativeImage, VkImageLayout.TransferDstOptimal, (uint)copies.Length, copiesPointer);
                }

                IsInitialized = true;
            }

            // Transition to default layout
            var imageMemoryBarrier = new VkImageMemoryBarrier(NativeImage,
                                                              new VkImageSubresourceRange(NativeImageAspect, 0, uint.MaxValue, 0, uint.MaxValue),
                                                              dataBoxes == null || dataBoxes.Length == 0 ? VkAccessFlags.None : VkAccessFlags.TransferWrite, NativeAccessMask,
                                                              dataBoxes == null || dataBoxes.Length == 0 ? VkImageLayout.Undefined : VkImageLayout.TransferDstOptimal, NativeLayout);

            vkCmdPipelineBarrier(commandBuffer, VkPipelineStageFlags.Transfer, VkPipelineStageFlags.AllCommands, VkDependencyFlags.None, 0, null, 0, null, 1, &imageMemoryBarrier);

            // Close and submit
            vkEndCommandBuffer(commandBuffer);

            var submitInfo = new VkSubmitInfo
            {
                sType = VkStructureType.SubmitInfo,
                commandBufferCount = 1,
                pCommandBuffers    = &commandBuffer,
            };

            lock (GraphicsDevice.QueueLock)
            {
                vkQueueSubmit(GraphicsDevice.NativeCommandQueue, 1, &submitInfo, VkFence.Null);
                vkQueueWaitIdle(GraphicsDevice.NativeCommandQueue);
                vkFreeCommandBuffers(GraphicsDevice.NativeDevice, GraphicsDevice.NativeCopyCommandPool, 1, &commandBuffer);
            }
        }