예제 #1
0
파일: Image.cs 프로젝트: Svengali/vk.net
        public void BuildMipmaps(CommandBuffer cmd)
        {
            VkImageSubresourceRange mipSubRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, 0, info.arrayLayers);

            SetLayout(cmd, VkImageLayout.Undefined, VkImageLayout.TransferSrcOptimal, mipSubRange,
                      VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);

            for (int i = 1; i < info.mipLevels; i++)
            {
                VkImageBlit imageBlit = new VkImageBlit {
                    srcSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, info.arrayLayers, (uint)i - 1),
                    srcOffsets_1   = new VkOffset3D((int)info.extent.width >> (i - 1), (int)info.extent.height >> (i - 1), 1),
                    dstSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, info.arrayLayers, (uint)i),
                    dstOffsets_1   = new VkOffset3D((int)info.extent.width >> i, (int)info.extent.height >> i, 1)
                };

                mipSubRange.baseMipLevel = (uint)i;

                SetLayout(cmd, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, mipSubRange,
                          VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);
                vkCmdBlitImage(cmd.Handle, handle, VkImageLayout.TransferSrcOptimal, handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear);
                SetLayout(cmd, VkImageLayout.TransferDstOptimal, VkImageLayout.TransferSrcOptimal, mipSubRange,
                          VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);
            }
            SetLayout(cmd, VkImageAspectFlags.Color, VkImageLayout.TransferSrcOptimal, VkImageLayout.ShaderReadOnlyOptimal,
                      VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader);
        }
예제 #2
0
        public ImageView(Image image, VkImageSubresourceRange range, VkImageViewType type, VkFormat?format = null,
                         VkComponentMapping?swizzle = null)
        {
            Device = image.Device;
            Image  = image;

            unsafe
            {
                var info = new VkImageViewCreateInfo()
                {
                    SType      = VkStructureType.ImageViewCreateInfo,
                    Flags      = 0,
                    PNext      = IntPtr.Zero,
                    Format     = format ?? image.Format,
                    Components = swizzle ?? new VkComponentMapping()
                    {
                        R = VkComponentSwizzle.Identity,
                        G = VkComponentSwizzle.Identity,
                        B = VkComponentSwizzle.Identity,
                        A = VkComponentSwizzle.Identity
                    },
                    Image            = image.Handle,
                    ViewType         = type,
                    SubresourceRange = range
                };
                Handle = Device.Handle.CreateImageView(&info, Instance.AllocationCallbacks);
            }
        }
        private VkImageView[] CreateImageViews()
        {
            var imageViews = new VkImageView[SwapchainImages.Length];

            for (int i = 0; i < SwapchainImages.Length; i++)
            {
                VkImageSubresourceRange range = new VkImageSubresourceRange
                {
                    aspectMask     = VkImageAspectFlags.Color,
                    baseMipLevel   = 0,
                    levelCount     = 1,
                    baseArrayLayer = 0,
                    layerCount     = 1
                };

                VkImageViewCreateInfo createInfo = new VkImageViewCreateInfo
                {
                    sType            = VkStructureType.ImageViewCreateInfo,
                    pNext            = null,
                    format           = SwapchainFormat,
                    viewType         = VkImageViewType.Image2D,
                    subresourceRange = range,
                    image            = SwapchainImages[i]
                };

                VkImageView imageView;
                vkCreateImageView(Context.Device, &createInfo, null, out imageView);

                imageViews[i] = imageView;
            }
            return(imageViews);
        }
예제 #4
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);
        }
예제 #5
0
        public void Clear(RawColor color)
        {
            VkClearColorValue clearValue = new VkClearColorValue(color.R, color.G, color.B, color.A);

            VkImageSubresourceRange clearRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, 0, 1);

            vkCmdClearColorImage(CommandBuffer, NativeDevice.NativeSwapChain.Images[(int)imageIndex], VkImageLayout.ColorAttachmentOptimal, &clearValue, 1, &clearRange);
        }
예제 #6
0
        public void Clear(float R, float G, float B, float A = 1.0f)
        {
            VkClearColorValue clearValue = new VkClearColorValue(R, G, B);

            VkImageSubresourceRange clearRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, 0, 1);

            vkCmdClearColorImage(CommandBuffer, NativeDevice.NativeSwapChain.Images[(int)imageIndex], VkImageLayout.ColorAttachmentOptimal, &clearValue, 1, &clearRange);
        }
        private void Vkctrl_VulkanRendering(object sender, SharpVulkanWpf.VulkanEventArgs args)
        {
            var device = args.Device;
            var image  = vkctrl.AcquireNextImage();

            var command = m_commandBuffers[0];

            VulkanAPI.vkBeginCommandBuffer(command);

            VkClearColorValue clearColor = new VkClearColorValue();

            clearColor.valF32.R = 0.125f;
            clearColor.valF32.G = 0.25f;
            clearColor.valF32.B = (float)(0.5f * Math.Sin(m_frameCount * 0.1) + 0.5);
            clearColor.valF32.A = 1.0f;

            VkImageSubresourceRange range = new VkImageSubresourceRange()
            {
                baseMipLevel   = 0,
                levelCount     = 1,
                baseArrayLayer = 0,
                layerCount     = 1,
                aspectMask     = VkImageAspectFlags.VK_IMAGE_ASPECT_COLOR_BIT
            };

            setImageMemoryBarrier(command,
                                  VkAccessFlags.VK_ACCESS_MEMORY_READ_BIT, VkAccessFlags.VK_ACCESS_TRANSFER_WRITE_BIT,
                                  VkImageLayout.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VkImageLayout.VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                  image, VkImageAspectFlags.VK_IMAGE_ASPECT_COLOR_BIT);

            VulkanAPI.vkCmdClearColorImage(command,
                                           image,
                                           VkImageLayout.VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                           ref clearColor,
                                           new VkImageSubresourceRange[] { range });


            // Present のためにレイアウト変更
            setImageMemoryBarrier(command,
                                  VkAccessFlags.VK_ACCESS_TRANSFER_WRITE_BIT, VkAccessFlags.VK_ACCESS_MEMORY_READ_BIT,
                                  VkImageLayout.VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VkImageLayout.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
                                  image, VkImageAspectFlags.VK_IMAGE_ASPECT_COLOR_BIT);
            VulkanAPI.vkEndCommandBuffer(command);

            var submitInfo = new VkSubmitInfo()
            {
                commandBuffers = new[] { command }
            };

            VulkanAPI.vkQueueSubmit(args.GraphicsQueue, new VkSubmitInfo[] { submitInfo }, null);

            vkctrl.SwapBuffers();
            m_frameCount++;
        }
예제 #8
0
        /// <summary>
        /// Must be called outside of a renderpass scope.
        /// </summary>
        /// <param name="depthStencil"></param>
        /// <param name="clearValue"></param>
        public void ClearDepthStencil(DepthStencil depthStencil, VkClearDepthStencilValue clearValue)
        {
            CheckBegun();
            CheckNotInRenderPass();
            VkImageSubresourceRange imageRange = new VkImageSubresourceRange();

            imageRange.aspectMask = VkImageAspectFlags.Depth;
            imageRange.levelCount = 1;
            imageRange.layerCount = 1;

            vkCmdClearDepthStencilImage(vkCmd, depthStencil.vkImage, VkImageLayout.General, &clearValue, 1, &imageRange);
        }
예제 #9
0
        /// <summary>
        /// Must be called outside of a renderpass scope.
        /// </summary>
        /// <param name="depthStencil"></param>
        /// <param name="clearValue"></param>
        public void ClearColor(Swapchain swapchain, uint swapchainImageIndex, VkClearColorValue clearColor)
        {
            CheckBegun();
            CheckNotInRenderPass();

            VkClearValue clearValue = new VkClearValue();

            clearValue.color = clearColor;

            VkImageSubresourceRange imageRange = new VkImageSubresourceRange();

            imageRange.aspectMask = VkImageAspectFlags.Color;
            imageRange.levelCount = 1;
            imageRange.layerCount = 1;
            vkCmdClearColorImage(vkCmd, swapchain.vkSwapchain.Images[swapchainImageIndex], VkImageLayout.General, &clearColor, 1, &imageRange);
        }
예제 #10
0
파일: Tools.cs 프로젝트: bitzhuwei/vk.other
        // Fixed sub resource on first mip level and layer
        public static void setImageLayout(
            VkCommandBuffer cmdbuffer,
            VkImage image,
            VkImageAspectFlags aspectMask,
            VkImageLayout oldImageLayout,
            VkImageLayout newImageLayout,
            VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands,
            VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands)
        {
            VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange();

            subresourceRange.aspectMask   = aspectMask;
            subresourceRange.baseMipLevel = 0;
            subresourceRange.levelCount   = 1;
            subresourceRange.layerCount   = 1;
            setImageLayout(cmdbuffer, image, aspectMask, oldImageLayout, newImageLayout, subresourceRange);
        }
예제 #11
0
파일: Image.cs 프로젝트: Svengali/vk.net
        public void SetLayout(
            CommandBuffer cmdbuffer,
            VkImageAspectFlags aspectMask,
            VkImageLayout oldImageLayout,
            VkImageLayout newImageLayout,
            VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands,
            VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands)
        {
            VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange {
                aspectMask   = aspectMask,
                baseMipLevel = 0,
                levelCount   = CreateInfo.mipLevels,
                layerCount   = CreateInfo.arrayLayers,
            };

            SetLayout(cmdbuffer, oldImageLayout, newImageLayout, subresourceRange, srcStageMask, dstStageMask);
        }
예제 #12
0
 public unsafe VkImageViewCreateInfo(
     VkImage image,
     VkImageViewType viewType,
     VkFormat format,
     VkComponentMapping components,
     VkImageSubresourceRange subresourceRange,
     VkImageViewCreateFlags flags = VkImageViewCreateFlags.None,
     void *pNext = default)
 {
     sType                 = VkStructureType.ImageViewCreateInfo;
     this.pNext            = pNext;
     this.flags            = flags;
     this.image            = image;
     this.viewType         = viewType;
     this.format           = format;
     this.components       = components;
     this.subresourceRange = subresourceRange;
 }
 public VkImageMemoryBarrier(
     VkImage image,
     VkImageSubresourceRange subresourceRange,
     VkAccessFlags srcAccessMask,
     VkAccessFlags dstAccessMask,
     VkImageLayout oldLayout,
     VkImageLayout newLayout,
     uint srcQueueFamilyIndex = VulkanNative.QueueFamilyIgnored,
     uint dstQueueFamilyIndex = VulkanNative.QueueFamilyIgnored)
 {
     sType = VkStructureType.ImageMemoryBarrier;
     pNext = null;
     this.srcAccessMask       = srcAccessMask;
     this.dstAccessMask       = dstAccessMask;
     this.oldLayout           = oldLayout;
     this.newLayout           = newLayout;
     this.srcQueueFamilyIndex = srcQueueFamilyIndex;
     this.dstQueueFamilyIndex = dstQueueFamilyIndex;
     this.image            = image;
     this.subresourceRange = subresourceRange;
 }
예제 #14
0
 public unsafe VkImageMemoryBarrier(
     VkImage image,
     VkImageSubresourceRange subresourceRange,
     VkAccessFlags srcAccessMask,
     VkAccessFlags dstAccessMask,
     VkImageLayout oldLayout,
     VkImageLayout newLayout,
     uint srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
     uint dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
     void *pNext = default)
 {
     sType                    = VkStructureType.ImageMemoryBarrier;
     this.pNext               = pNext;
     this.srcAccessMask       = srcAccessMask;
     this.dstAccessMask       = dstAccessMask;
     this.oldLayout           = oldLayout;
     this.newLayout           = newLayout;
     this.srcQueueFamilyIndex = srcQueueFamilyIndex;
     this.dstQueueFamilyIndex = dstQueueFamilyIndex;
     this.image               = image;
     this.subresourceRange    = subresourceRange;
 }
예제 #15
0
        public void SetLayout(
            CommandBuffer cmdbuffer,
            VkImageAspectFlags aspectMask,
            VkAccessFlags srcAccessMask,
            VkAccessFlags dstAccessMask,
            VkImageLayout oldImageLayout,
            VkImageLayout newImageLayout,
            VkPipelineStageFlags srcStageMask = VkPipelineStageFlags.AllCommands,
            VkPipelineStageFlags dstStageMask = VkPipelineStageFlags.AllCommands,
            uint srcQueueFamilyIndex          = Vk.QueueFamilyIgnored,
            uint dstQueueFamilyIndex          = Vk.QueueFamilyIgnored)
        {
            VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange {
                aspectMask   = aspectMask,
                baseMipLevel = 0,
                levelCount   = CreateInfo.mipLevels,
                layerCount   = CreateInfo.arrayLayers,
            };

            SetLayout(cmdbuffer, srcAccessMask, dstAccessMask, oldImageLayout, newImageLayout, subresourceRange, srcStageMask, dstStageMask,
                      srcQueueFamilyIndex, dstQueueFamilyIndex);
        }
예제 #16
0
        void CreateImageView(ImageViewCreateInfo mInfo)
        {
            VkImageViewCreateInfo info = new VkImageViewCreateInfo();

            info.sType            = VkStructureType.ImageViewCreateInfo;
            info.image            = mInfo.image.Native;
            info.viewType         = mInfo.viewType;
            info.format           = mInfo.format;
            info.components       = mInfo.components;
            info.subresourceRange = mInfo.subresourceRange;

            var result = Device.Commands.createImageView(Device.Native, ref info, Device.Instance.AllocationCallbacks, out imageView);

            if (result != VkResult.Success)
            {
                throw new ImageViewException(string.Format("Error creating image view: {0}", result));
            }

            Image            = mInfo.image;
            ViewType         = mInfo.viewType;
            Format           = mInfo.format;
            Components       = mInfo.components;
            SubresourceRange = mInfo.subresourceRange;
        }
예제 #17
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);
        }
예제 #18
0
        public Image generateCubeMap(Queue staggingQ, CommandPool cmdPool, CBTarget target)
        {
            const float deltaPhi   = (2.0f * (float)Math.PI) / 180.0f;
            const float deltaTheta = (0.5f * (float)Math.PI) / 64.0f;

            VkFormat format = VkFormat.R32g32b32a32Sfloat;
            uint     dim    = 64;

            if (target == CBTarget.PREFILTEREDENV)
            {
                format = VkFormat.R16g16b16a16Sfloat;
                dim    = 512;
            }

            uint numMips = (uint)Math.Floor(Math.Log(dim, 2)) + 1;

            Image imgFbOffscreen = new Image(Dev, format, VkImageUsageFlags.TransferSrc | VkImageUsageFlags.ColorAttachment,
                                             VkMemoryPropertyFlags.DeviceLocal, dim, dim);

            imgFbOffscreen.SetName("offscreenfb");
            imgFbOffscreen.CreateView();

            Image cmap = new Image(Dev, format, VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled,
                                   VkMemoryPropertyFlags.DeviceLocal, dim, dim, VkImageType.Image2D, VkSampleCountFlags.SampleCount1, VkImageTiling.Optimal,
                                   numMips, 6, 1, VkImageCreateFlags.CubeCompatible);

            if (target == CBTarget.PREFILTEREDENV)
            {
                cmap.SetName("prefilterenvmap");
            }
            else
            {
                cmap.SetName("irradianceCube");
            }
            cmap.CreateView(VkImageViewType.Cube, VkImageAspectFlags.Color, 6, 0, numMips);
            cmap.CreateSampler(VkSamplerAddressMode.ClampToEdge);

            DescriptorPool dsPool = new DescriptorPool(Dev, 2, new VkDescriptorPoolSize(VkDescriptorType.CombinedImageSampler));

            DescriptorSetLayout dsLayout = new DescriptorSetLayout(Dev,
                                                                   new VkDescriptorSetLayoutBinding(0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler));


            GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false);

            cfg.Layout = new PipelineLayout(Dev, dsLayout);
            cfg.Layout.AddPushConstants(
                new VkPushConstantRange(VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, (uint)Marshal.SizeOf <Matrix4x4> () + 8));

            cfg.RenderPass = new RenderPass(Dev);
            cfg.RenderPass.AddAttachment(format, VkImageLayout.ColorAttachmentOptimal);
            cfg.RenderPass.ClearValues.Add(new VkClearValue {
                color = new VkClearColorValue(0, 0, 0)
            });
            cfg.RenderPass.AddSubpass(new SubPass(VkImageLayout.ColorAttachmentOptimal));

            cfg.AddVertexBinding(0, 3 * sizeof(float));
            cfg.AddVertexAttributes(0, VkFormat.R32g32b32Sfloat);

            cfg.AddShader(VkShaderStageFlags.Vertex, "shaders/filtercube.vert.spv");
            if (target == CBTarget.PREFILTEREDENV)
            {
                cfg.AddShader(VkShaderStageFlags.Fragment, "shaders/prefilterenvmap.frag.spv");
            }
            else
            {
                cfg.AddShader(VkShaderStageFlags.Fragment, "shaders/irradiancecube.frag.spv");
            }

            Matrix4x4[] matrices =
            {
                // POSITIVE_X
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(180)) * Matrix4x4.CreateRotationY(Utils.DegreesToRadians(90)),
                // NEGATIVE_X
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(180)) * Matrix4x4.CreateRotationY(Utils.DegreesToRadians(-90)),
                // POSITIVE_Y
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(-90)),
                // NEGATIVE_Y
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(90)),
                // POSITIVE_Z
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(180)),
                // NEGATIVE_Z
                Matrix4x4.CreateRotationZ(Utils.DegreesToRadians(180))
            };

            VkImageSubresourceRange subRes = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, numMips, 0, 6);

            using (GraphicPipeline pl = new GraphicPipeline(cfg)) {
                DescriptorSet       dset     = dsPool.Allocate(dsLayout);
                DescriptorSetWrites dsUpdate = new DescriptorSetWrites(dsLayout);
                dsUpdate.Write(Dev, dset, cubemap.Descriptor);
                Dev.WaitIdle();

                using (Framebuffer fb = new Framebuffer(pl.RenderPass, dim, dim, imgFbOffscreen)) {
                    CommandBuffer cmd = cmdPool.AllocateCommandBuffer();
                    cmd.Start(VkCommandBufferUsageFlags.OneTimeSubmit);

                    cmap.SetLayout(cmd, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, subRes);

                    float roughness = 0;

                    cmd.SetScissor(dim, dim);
                    cmd.SetViewport((float)(dim), (float)dim);

                    for (int m = 0; m < numMips; m++)
                    {
                        roughness = (float)m / ((float)numMips - 1f);

                        for (int f = 0; f < 6; f++)
                        {
                            pl.RenderPass.Begin(cmd, fb);

                            pl.Bind(cmd);

                            float viewPortSize = (float)Math.Pow(0.5, m) * dim;
                            cmd.SetViewport(viewPortSize, viewPortSize);
                            cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment,
                                             matrices[f] * Matrix4x4.CreatePerspectiveFieldOfView(Utils.DegreesToRadians(90), 1f, 0.1f, 512f));
                            if (target == CBTarget.IRRADIANCE)
                            {
                                cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, deltaPhi, (uint)Marshal.SizeOf <Matrix4x4> ());
                                cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, deltaTheta, (uint)Marshal.SizeOf <Matrix4x4> () + 4);
                            }
                            else
                            {
                                cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, roughness, (uint)Marshal.SizeOf <Matrix4x4> ());
                                cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, 64u, (uint)Marshal.SizeOf <Matrix4x4> () + 4);
                            }

                            cmd.BindDescriptorSet(pl.Layout, dset);
                            cmd.BindVertexBuffer(vboSkybox);
                            cmd.Draw(36);

                            pl.RenderPass.End(cmd);

                            imgFbOffscreen.SetLayout(cmd, VkImageAspectFlags.Color,
                                                     VkImageLayout.ColorAttachmentOptimal, VkImageLayout.TransferSrcOptimal);

                            VkImageCopy region = new VkImageCopy();
                            region.srcSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, 1);
                            region.dstSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, 1, (uint)m, (uint)f);
                            region.extent         = new VkExtent3D {
                                width = (uint)viewPortSize, height = (uint)viewPortSize, depth = 1
                            };

                            Vk.vkCmdCopyImage(cmd.Handle,
                                              imgFbOffscreen.Handle, VkImageLayout.TransferSrcOptimal,
                                              cmap.Handle, VkImageLayout.TransferDstOptimal,
                                              1, region.Pin());
                            region.Unpin();

                            imgFbOffscreen.SetLayout(cmd, VkImageAspectFlags.Color,
                                                     VkImageLayout.TransferSrcOptimal, VkImageLayout.ColorAttachmentOptimal);
                        }
                    }

                    cmap.SetLayout(cmd, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal, subRes);

                    cmd.End();

                    staggingQ.Submit(cmd);
                    staggingQ.WaitIdle();

                    cmd.Free();
                }
            }
            cmap.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;

            dsLayout.Dispose();
            imgFbOffscreen.Dispose();
            dsPool.Dispose();

            return(cmap);
        }
예제 #19
0
        // Setup the offscreen framebuffer for rendering the blurred scene
        // The color attachment of this framebuffer will then be used to sample frame in the fragment shader of the final pass
        void prepareOffscreen()
        {
            offscreenPass.width  = FB_DIM;
            offscreenPass.height = FB_DIM;

            // Find a suitable depth format
            VkFormat fbDepthFormat;
            VkBool32 validDepthFormat = Tools.getSupportedDepthFormat(physicalDevice, &fbDepthFormat);

            Debug.Assert(validDepthFormat);

            // Color attachment
            var imageInfo = VkImageCreateInfo.Alloc();

            imageInfo->imageType     = VkImageType._2d;// VK_IMAGE_TYPE_2D;
            imageInfo->format        = FB_COLOR_FORMAT;
            imageInfo->extent.width  = (uint)offscreenPass.width;
            imageInfo->extent.height = (uint)offscreenPass.height;
            imageInfo->extent.depth  = 1;
            imageInfo->mipLevels     = 1;
            imageInfo->arrayLayers   = 1;
            imageInfo->samples       = VkSampleCountFlagBits._1; // VK_SAMPLE_COUNT_1_BIT;
            imageInfo->tiling        = VkImageTiling.Optimal;    // VK_IMAGE_TILING_OPTIMAL;
            // We will sample directly from the color attachment
            imageInfo->usage = VkImageUsageFlagBits.ColorAttachment | VkImageUsageFlagBits.Sampled;
            //VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;

            var memAlloc = VkMemoryAllocateInfo.Alloc();
            VkMemoryRequirements memReqs;

            {
                VkImage image;
                vkCreateImage(device, imageInfo, null, &image);
                offscreenPass.colorAttachment.image = image;
            }
            vkGetImageMemoryRequirements(device, offscreenPass.colorAttachment.image, &memReqs);
            memAlloc->allocationSize  = memReqs.size;
            memAlloc->memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits,
                                                                   VkMemoryPropertyFlagBits.DeviceLocal);
            //VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
            {
                VkDeviceMemory memory;
                vkAllocateMemory(device, memAlloc, null, &memory);
                offscreenPass.colorAttachment.mem = memory;
            }
            vkBindImageMemory(device, offscreenPass.colorAttachment.image, offscreenPass.colorAttachment.mem, 0);

            var colorViewInfo = VkImageViewCreateInfo.Alloc();

            colorViewInfo->viewType                        = VkImageViewType._2d;// VK_IMAGE_VIEW_TYPE_2D;
            colorViewInfo->format                          = FB_COLOR_FORMAT;
            colorViewInfo->subresourceRange                = new VkImageSubresourceRange();
            colorViewInfo->subresourceRange.aspectMask     = VkImageAspectFlagBits.Color;// VK_IMAGE_ASPECT_COLOR_BIT;
            colorViewInfo->subresourceRange.baseMipLevel   = 0;
            colorViewInfo->subresourceRange.levelCount     = 1;
            colorViewInfo->subresourceRange.baseArrayLayer = 0;
            colorViewInfo->subresourceRange.layerCount     = 1;
            colorViewInfo->image = offscreenPass.colorAttachment.image;
            {
                VkImageView view;
                vkCreateImageView(device, colorViewInfo, null, &view);
                offscreenPass.colorAttachment.view = view;
            }

            // Create sampler to sample from the attachment in the fragment shader
            var samplerInfo = VkSamplerCreateInfo.Alloc();

            samplerInfo->magFilter     = VkFilter.Linear;                  // VK_FILTER_LINEAR;
            samplerInfo->minFilter     = VkFilter.Linear;                  // VK_FILTER_LINEAR;
            samplerInfo->mipmapMode    = VkSamplerMipmapMode.Linear;       // VK_SAMPLER_MIPMAP_MODE_LINEAR;
            samplerInfo->addressModeU  = VkSamplerAddressMode.ClampToEdge; // VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
            samplerInfo->addressModeV  = samplerInfo->addressModeU;
            samplerInfo->addressModeW  = samplerInfo->addressModeU;
            samplerInfo->mipLodBias    = 0.0f;
            samplerInfo->maxAnisotropy = 0;
            samplerInfo->minLod        = 0.0f;
            samplerInfo->maxLod        = 1.0f;
            samplerInfo->borderColor   = VkBorderColor.FloatOpaqueWhite;// VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
            {
                VkSampler sampler;
                vkCreateSampler(device, samplerInfo, null, &sampler);
                offscreenPass.sampler = sampler;
            }

            // Depth stencil attachment
            imageInfo->format = fbDepthFormat;
            imageInfo->usage  = VkImageUsageFlagBits.DepthStencilAttachment;// VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;

            {
                VkImage image;
                vkCreateImage(device, imageInfo, null, &image);
                offscreenPass.depthAttachment.image = image;
            }
            vkGetImageMemoryRequirements(device, offscreenPass.depthAttachment.image, &memReqs);
            memAlloc->allocationSize  = memReqs.size;
            memAlloc->memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits,
                                                                   VkMemoryPropertyFlagBits.DeviceLocal);
            //VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
            {
                VkDeviceMemory memory;
                vkAllocateMemory(device, memAlloc, null, &memory);
                offscreenPass.depthAttachment.mem = memory;
            }
            vkBindImageMemory(device, offscreenPass.depthAttachment.image, offscreenPass.depthAttachment.mem, 0);

            var depthViewInfo = VkImageViewCreateInfo.Alloc();

            depthViewInfo->viewType                    = VkImageViewType._2d;// VK_IMAGE_VIEW_TYPE_2D;
            depthViewInfo->format                      = fbDepthFormat;
            depthViewInfo->flags                       = 0;
            depthViewInfo->subresourceRange            = new VkImageSubresourceRange();
            depthViewInfo->subresourceRange.aspectMask = VkImageAspectFlagBits.Depth | VkImageAspectFlagBits.Stencil;
            //VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
            depthViewInfo->subresourceRange.baseMipLevel   = 0;
            depthViewInfo->subresourceRange.levelCount     = 1;
            depthViewInfo->subresourceRange.baseArrayLayer = 0;
            depthViewInfo->subresourceRange.layerCount     = 1;
            depthViewInfo->image = offscreenPass.depthAttachment.image;
            {
                VkImageView view;
                vkCreateImageView(device, depthViewInfo, null, &view);
                offscreenPass.depthAttachment.view = view;
            }

            // Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering

            var attchmentDescriptions = new VkAttachmentDescription[2];

            // Color attachment
            attchmentDescriptions[0].format         = FB_COLOR_FORMAT;
            attchmentDescriptions[0].samples        = VkSampleCountFlagBits._1;            // VK_SAMPLE_COUNT_1_BIT;
            attchmentDescriptions[0].loadOp         = VkAttachmentLoadOp.Clear;            // VK_ATTACHMENT_LOAD_OP_CLEAR;
            attchmentDescriptions[0].storeOp        = VkAttachmentStoreOp.Store;           // VK_ATTACHMENT_STORE_OP_STORE;
            attchmentDescriptions[0].stencilLoadOp  = VkAttachmentLoadOp.DontCare;         // VK_ATTACHMENT_LOAD_OP_DONT_CARE;
            attchmentDescriptions[0].stencilStoreOp = VkAttachmentStoreOp.DontCare;        // VK_ATTACHMENT_STORE_OP_DONT_CARE;
            attchmentDescriptions[0].initialLayout  = VkImageLayout.Undefined;             // VK_IMAGE_LAYOUT_UNDEFINED;
            attchmentDescriptions[0].finalLayout    = VkImageLayout.ShaderReadOnlyOptimal; // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
            // Depth attachment
            attchmentDescriptions[1].format         = fbDepthFormat;
            attchmentDescriptions[1].samples        = VkSampleCountFlagBits._1;                    // VK_SAMPLE_COUNT_1_BIT;
            attchmentDescriptions[1].loadOp         = VkAttachmentLoadOp.Clear;                    // VK_ATTACHMENT_LOAD_OP_CLEAR;
            attchmentDescriptions[1].storeOp        = VkAttachmentStoreOp.DontCare;                // VK_ATTACHMENT_STORE_OP_DONT_CARE;
            attchmentDescriptions[1].stencilLoadOp  = VkAttachmentLoadOp.DontCare;                 // VK_ATTACHMENT_LOAD_OP_DONT_CARE;
            attchmentDescriptions[1].stencilStoreOp = VkAttachmentStoreOp.DontCare;                // VK_ATTACHMENT_STORE_OP_DONT_CARE;
            attchmentDescriptions[1].initialLayout  = VkImageLayout.Undefined;                     // VK_IMAGE_LAYOUT_UNDEFINED;
            attchmentDescriptions[1].finalLayout    = VkImageLayout.DepthStencilAttachmentOptimal; // VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

            var colorReference = new VkAttachmentReference {
                attachment = 0,
                layout     = VkImageLayout.ColorAttachmentOptimal// VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
            };
            var depthReference = new VkAttachmentReference {
                attachment = 1,
                layout     = VkImageLayout.DepthStencilAttachmentOptimal// VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
            };

            VkSubpassDescription subpassDescription = new VkSubpassDescription();

            subpassDescription.pipelineBindPoint = VkPipelineBindPoint.Graphics;// VK_PIPELINE_BIND_POINT_GRAPHICS;
            subpassDescription.colorResolveAttachments.SetColorAttachments(colorReference);
            subpassDescription.pDepthStencilAttachment = &depthReference;

            // Use subpass dependencies for layout transitions
            var dependencies = new VkSubpassDependency[2];

            dependencies[0].srcSubpass    = VK_SUBPASS_EXTERNAL;
            dependencies[0].dstSubpass    = 0;
            dependencies[0].srcStageMask  = VkPipelineStageFlagBits.BottomOfPipe;          // VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
            dependencies[0].dstStageMask  = VkPipelineStageFlagBits.ColorAttachmentOutput; // VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
            dependencies[0].srcAccessMask = VkAccessFlagBits.MemoryRead;                   // VK_ACCESS_MEMORY_READ_BIT;
            dependencies[0].dstAccessMask = VkAccessFlagBits.ColorAttachmentRead | VkAccessFlagBits.ColorAttachmentWrite;
            //VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
            dependencies[0].dependencyFlags = VkDependencyFlagBits.ByRegion;// VK_DEPENDENCY_BY_REGION_BIT;
            dependencies[1].srcSubpass      = 0;
            dependencies[1].dstSubpass      = VK_SUBPASS_EXTERNAL;
            dependencies[1].srcStageMask    = VkPipelineStageFlagBits.ColorAttachmentOutput; // VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
            dependencies[1].dstStageMask    = VkPipelineStageFlagBits.BottomOfPipe;          // VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
            dependencies[1].srcAccessMask   = VkAccessFlagBits.ColorAttachmentRead | VkAccessFlagBits.ColorAttachmentWrite;
            //VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
            dependencies[1].dstAccessMask   = VkAccessFlagBits.MemoryRead;   // VK_ACCESS_MEMORY_READ_BIT;
            dependencies[1].dependencyFlags = VkDependencyFlagBits.ByRegion; // VK_DEPENDENCY_BY_REGION_BIT;

            // Create the actual renderpass
            var renderPassInfo = VkRenderPassCreateInfo.Alloc();

            renderPassInfo->attachments  = attchmentDescriptions;
            renderPassInfo->subpasses    = subpassDescription;
            renderPassInfo->dependencies = dependencies;
            {
                VkRenderPass renderPass;
                vkCreateRenderPass(device, renderPassInfo, null, &renderPass);
                offscreenPass.renderPass = renderPass;
            }

            var attachments = new VkImageView[] {
                offscreenPass.colorAttachment.view,
                offscreenPass.depthAttachment.view
            };

            var framebufferInfo = VkFramebufferCreateInfo.Alloc();

            framebufferInfo->renderPass  = offscreenPass.renderPass;
            framebufferInfo->attachments = attachments;
            framebufferInfo->width       = (uint)offscreenPass.width;
            framebufferInfo->height      = (uint)offscreenPass.height;
            framebufferInfo->layers      = 1;
            {
                VkFramebuffer framebuffer;
                vkCreateFramebuffer(device, framebufferInfo, null, &framebuffer);
                offscreenPass.framebuffer = framebuffer;
            }

            // Fill a descriptor for later use in a descriptor set
            offscreenPass.descriptorImage.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;// VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
            offscreenPass.descriptorImage.imageView   = offscreenPass.colorAttachment.view;
            offscreenPass.descriptorImage.sampler     = offscreenPass.sampler;
        }
예제 #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
        /**
         * Load a 2D texture including all mip levels
         *
         * @param filename File to load (supports .ktx and .dds)
         * @param format Vulkan format of the image data stored in the file
         * @param device Vulkan device to create the texture on
         * @param copyQueue Queue used for the texture staging copy commands (must support transfer)
         * @param (Optional) imageUsageFlags Usage flags for the texture's image (defaults to VK_IMAGE_USAGE_SAMPLED_BIT)
         * @param (Optional) imageLayout Usage layout for the texture (defaults VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
         * @param (Optional) forceLinear Force linear tiling (not advised, defaults to false)
         *
         */
        public void loadFromFile(
            string filename,
            VkFormat format,
            vksVulkanDevice device,
            VkQueue copyQueue,
            VkImageUsageFlagBits imageUsageFlags = VkImageUsageFlagBits.Sampled,
            VkImageLayout imageLayout            = VkImageLayout.ShaderReadOnlyOptimal,
            bool forceLinear = false)
        {
            KtxFile tex2D;

            using (var fs = File.OpenRead(filename)) {
                tex2D = KtxFile.Load(fs, false);
            }

            this.device = device;
            width       = tex2D.Header.PixelWidth;
            height      = tex2D.Header.PixelHeight;
            if (height == 0)
            {
                height = width;
            }
            mipLevels = tex2D.Header.NumberOfMipmapLevels;

            // Get device properites for the requested texture format
            VkFormatProperties formatProperties;

            vkGetPhysicalDeviceFormatProperties(device.PhysicalDevice, format, &formatProperties);

            // Only use linear tiling if requested (and supported by the device)
            // Support for linear tiling is mostly limited, so prefer to use
            // optimal tiling instead
            // On most implementations linear tiling will only support a very
            // limited amount of formats and features (mip maps, cubemaps, arrays, etc.)
            bool useStaging = !forceLinear;

            VkMemoryAllocateInfo memAllocInfo = new VkMemoryAllocateInfo();

            memAllocInfo.sType = MemoryAllocateInfo;
            VkMemoryRequirements memReqs;

            // Use a separate command buffer for texture loading
            VkCommandBuffer copyCmd = device.createCommandBuffer(VkCommandBufferLevel.Primary, true);

            if (useStaging)
            {
                // Create a host-visible staging buffer that contains the raw image data
                VkBuffer       stagingBuffer;
                VkDeviceMemory stagingMemory;

                VkBufferCreateInfo bufferCreateInfo = new VkBufferCreateInfo();
                bufferCreateInfo.sType = BufferCreateInfo;
                bufferCreateInfo.size  = tex2D.GetTotalSize();
                // This buffer is used as a transfer source for the buffer copy
                bufferCreateInfo.usage       = VkBufferUsageFlagBits.TransferSrc;
                bufferCreateInfo.sharingMode = VkSharingMode.Exclusive;

                vkCreateBuffer(device.LogicalDevice, &bufferCreateInfo, null, &stagingBuffer);

                // Get memory requirements for the staging buffer (alignment, memory type bits)
                vkGetBufferMemoryRequirements(device.LogicalDevice, stagingBuffer, &memReqs);

                memAllocInfo.allocationSize = memReqs.size;
                // Get memory type index for a host visible buffer
                memAllocInfo.memoryTypeIndex = device.getMemoryType(memReqs.memoryTypeBits,
                                                                    VkMemoryPropertyFlagBits.HostVisible | VkMemoryPropertyFlagBits.HostCoherent);

                vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, &stagingMemory);
                vkBindBufferMemory(device.LogicalDevice, stagingBuffer, stagingMemory, 0);

                // Copy texture data into staging buffer
                IntPtr data;
                vkMapMemory(device.LogicalDevice, stagingMemory, 0, memReqs.size, 0, &data);
                byte[] pixelData = tex2D.GetAllTextureData();
                fixed(byte *pixelDataPtr = &pixelData[0])
                {
                    Unsafe.CopyBlock(data, pixelDataPtr, (uint)pixelData.Length);
                }

                vkUnmapMemory(device.LogicalDevice, stagingMemory);

                // Setup buffer copy regions for each mip level
                var  bufferCopyRegions = new List <VkBufferImageCopy>();
                uint offset            = 0;

                for (uint i = 0; i < mipLevels; i++)
                {
                    VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy();
                    bufferCopyRegion.imageSubresource.aspectMask     = VkImageAspectFlagBits.Color;
                    bufferCopyRegion.imageSubresource.mipLevel       = i;
                    bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
                    bufferCopyRegion.imageSubresource.layerCount     = 1;
                    bufferCopyRegion.imageExtent.width  = tex2D.Faces[0].Mipmaps[i].Width;
                    bufferCopyRegion.imageExtent.height = tex2D.Faces[0].Mipmaps[i].Height;
                    bufferCopyRegion.imageExtent.depth  = 1;
                    bufferCopyRegion.bufferOffset       = offset;

                    bufferCopyRegions.Add(bufferCopyRegion);

                    offset += tex2D.Faces[0].Mipmaps[i].SizeInBytes;
                }

                // Create optimal tiled target image
                VkImageCreateInfo imageCreateInfo = new VkImageCreateInfo();
                imageCreateInfo.sType         = ImageCreateInfo;
                imageCreateInfo.imageType     = VkImageType._2d;
                imageCreateInfo.format        = format;
                imageCreateInfo.mipLevels     = mipLevels;
                imageCreateInfo.arrayLayers   = 1;
                imageCreateInfo.samples       = VkSampleCountFlagBits._1;
                imageCreateInfo.tiling        = VkImageTiling.Optimal;
                imageCreateInfo.sharingMode   = VkSharingMode.Exclusive;
                imageCreateInfo.initialLayout = VkImageLayout.Undefined;
                imageCreateInfo.extent        = new VkExtent3D {
                    width = width, height = height, depth = 1
                };
                imageCreateInfo.usage = imageUsageFlags;
                // Ensure that the TRANSFER_DST bit is set for staging
                if ((imageCreateInfo.usage & VkImageUsageFlagBits.TransferDst) == 0)
                {
                    imageCreateInfo.usage |= VkImageUsageFlagBits.TransferDst;
                }
                {
                    VkImage vkImage;
                    vkCreateImage(device.LogicalDevice, &imageCreateInfo, null, &vkImage);
                    this.image = vkImage;
                }

                vkGetImageMemoryRequirements(device.LogicalDevice, image, &memReqs);

                memAllocInfo.allocationSize = memReqs.size;

                memAllocInfo.memoryTypeIndex = device.getMemoryType(memReqs.memoryTypeBits,
                                                                    VkMemoryPropertyFlagBits.DeviceLocal);
                {
                    VkDeviceMemory memory;
                    vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, &memory);
                    this.deviceMemory = memory;
                }
                vkBindImageMemory(device.LogicalDevice, image, deviceMemory, 0);

                VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange();
                subresourceRange.aspectMask   = VkImageAspectFlagBits.Color;
                subresourceRange.baseMipLevel = 0;
                subresourceRange.levelCount   = mipLevels;
                subresourceRange.layerCount   = 1;

                // Image barrier for optimal image (target)
                // Optimal image will be used as destination for the copy
                Tools.setImageLayout(
                    copyCmd,
                    image,
                    VkImageAspectFlagBits.Color,
                    VkImageLayout.Undefined,
                    VkImageLayout.TransferDstOptimal,
                    subresourceRange);

                // Copy mip levels from staging buffer
                fixed(VkBufferImageCopy *pointer = bufferCopyRegions.ToArray())
                {
                    vkCmdCopyBufferToImage(
                        copyCmd,
                        stagingBuffer,
                        image,
                        VkImageLayout.TransferDstOptimal,
                        (UInt32)bufferCopyRegions.Count,
                        pointer);
                }

                // Change texture image layout to shader read after all mip levels have been copied
                this.imageLayout = imageLayout;
                Tools.setImageLayout(
                    copyCmd,
                    image,
                    VkImageAspectFlagBits.Color,
                    VkImageLayout.TransferDstOptimal,
                    imageLayout,
                    subresourceRange);

                device.flushCommandBuffer(copyCmd, copyQueue);

                // Clean up staging resources
                vkFreeMemory(device.LogicalDevice, stagingMemory, null);
                vkDestroyBuffer(device.LogicalDevice, stagingBuffer, null);
            }
            else
            {
                throw new NotImplementedException();

                /*
                 * // Prefer using optimal tiling, as linear tiling
                 * // may support only a small set of features
                 * // depending on implementation (e.g. no mip maps, only one layer, etc.)
                 *
                 * // Check if this support is supported for linear tiling
                 * Debug.Assert((formatProperties.linearTilingFeatures & VkFormatFeatureFlags.SampledImage) != 0);
                 *
                 * VkImage mappableImage;
                 * VkDeviceMemory mappableMemory;
                 *
                 * VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo();
                 * imageCreateInfo.imageType = VkImageType._2d;
                 * imageCreateInfo.format = format;
                 * imageCreateInfo.extent = new VkExtent3D { width = width, height = height, depth = 1 };
                 * imageCreateInfo.mipLevels = 1;
                 * imageCreateInfo.arrayLayers = 1;
                 * imageCreateInfo.samples = VkSampleCountFlags._1;
                 * imageCreateInfo.tiling = VkImageTiling.Linear;
                 * imageCreateInfo.usage = imageUsageFlags;
                 * imageCreateInfo.sharingMode = VkSharingMode.Exclusive;
                 * imageCreateInfo.initialLayout = VkImageLayout.Undefined;
                 *
                 * // Load mip map level 0 to linear tiling image
                 * Util.CheckResult(vkCreateImage(device.LogicalDevice, &imageCreateInfo, null, &mappableImage));
                 *
                 * // Get memory requirements for this image
                 * // like size and alignment
                 * vkGetImageMemoryRequirements(device.LogicalDevice, mappableImage, &memReqs);
                 * // Set memory allocation size to required memory size
                 * memAllocInfo.allocationSize = memReqs.size;
                 *
                 * // Get memory type that can be mapped to host memory
                 * memAllocInfo.memoryTypeIndex = device.GetMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent);
                 *
                 * // Allocate host memory
                 * Util.CheckResult(vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, &mappableMemory));
                 *
                 * // Bind allocated image for use
                 * Util.CheckResult(vkBindImageMemory(device.LogicalDevice, mappableImage, mappableMemory, 0));
                 *
                 * // Get sub resource layout
                 * // Mip map count, array layer, etc.
                 * VkImageSubresource subRes = new VkImageSubresource();
                 * subRes.aspectMask = VkImageAspectFlags.Color;
                 * subRes.mipLevel = 0;
                 *
                 * VkSubresourceLayout subResLayout;
                 * void* data;
                 *
                 * // Get sub resources layout
                 * // Includes row pitch, size offsets, etc.
                 * vkGetImageSubresourceLayout(device.LogicalDevice, mappableImage, &subRes, &subResLayout);
                 *
                 * // Map image memory
                 * Util.CheckResult(vkMapMemory(device.LogicalDevice, mappableMemory, 0, memReqs.size, 0, &data));
                 *
                 * // Copy image data into memory
                 * memcpy(data, tex2D[subRes.mipLevel].data(), tex2D[subRes.mipLevel].size());
                 *
                 * vkUnmapMemory(device.LogicalDevice, mappableMemory);
                 *
                 * // Linear tiled images don't need to be staged
                 * // and can be directly used as textures
                 * image = mappableImage;
                 * deviceMemory = mappableMemory;
                 * imageLayout = imageLayout;
                 *
                 * // Setup image memory barrier
                 * vks::tools::setImageLayout(copyCmd, image, VkImageAspectFlags.Color, VkImageLayout.Undefined, imageLayout);
                 *
                 * device.flushCommandBuffer(copyCmd, copyQueue);
                 */
            }

            // Create a defaultsampler
            VkSamplerCreateInfo samplerCreateInfo = new VkSamplerCreateInfo();

            samplerCreateInfo.sType        = SamplerCreateInfo;
            samplerCreateInfo.magFilter    = VkFilter.Linear;
            samplerCreateInfo.minFilter    = VkFilter.Linear;
            samplerCreateInfo.mipmapMode   = VkSamplerMipmapMode.Linear;
            samplerCreateInfo.addressModeU = VkSamplerAddressMode.Repeat;
            samplerCreateInfo.addressModeV = VkSamplerAddressMode.Repeat;
            samplerCreateInfo.addressModeW = VkSamplerAddressMode.Repeat;
            samplerCreateInfo.mipLodBias   = 0.0f;
            samplerCreateInfo.compareOp    = VkCompareOp.Never;
            samplerCreateInfo.minLod       = 0.0f;
            // Max level-of-detail should match mip level count
            samplerCreateInfo.maxLod = (useStaging) ? (float)mipLevels : 0.0f;
            // Enable anisotropic filtering
            samplerCreateInfo.maxAnisotropy    = 8;
            samplerCreateInfo.anisotropyEnable = true;
            samplerCreateInfo.borderColor      = VkBorderColor.FloatOpaqueWhite;
            {
                VkSampler vkSampler;
                vkCreateSampler(device.LogicalDevice, &samplerCreateInfo, null, &vkSampler);
                this.sampler = vkSampler;
            }

            // Create image view
            // Textures are not directly accessed by the shaders and
            // are abstracted by image views containing additional
            // information and sub resource ranges
            VkImageViewCreateInfo viewCreateInfo = new VkImageViewCreateInfo();

            viewCreateInfo.sType      = ImageViewCreateInfo;
            viewCreateInfo.viewType   = VkImageViewType._2d;
            viewCreateInfo.format     = format;
            viewCreateInfo.components = new VkComponentMapping {
                r = VkComponentSwizzle.R,
                g = VkComponentSwizzle.G,
                b = VkComponentSwizzle.B,
                a = VkComponentSwizzle.A
            };
            viewCreateInfo.subresourceRange = new VkImageSubresourceRange {
                aspectMask   = VkImageAspectFlagBits.Color,
                baseMipLevel = 0, levelCount = 1, baseArrayLayer = 0, layerCount = 1
            };
            // Linear tiling usually won't support mip maps
            // Only set mip map count if optimal tiling is used
            viewCreateInfo.subresourceRange.levelCount = (useStaging) ? mipLevels : 1;
            viewCreateInfo.image = image;
            {
                VkImageView vkImageView;
                vkCreateImageView(device.LogicalDevice, &viewCreateInfo, null, &vkImageView);
                this.view = vkImageView;
            }

            // Update descriptor image info member that can be used for setting up descriptor sets
            updateDescriptor();
        }
예제 #22
0
        private void TransferData(Image <Rgba32> tex2D)
        {
            using CommandBuffer copyCmd = device.GetCommandPool().Rent();

            VkMemoryAllocateInfo memAllocInfo = Initializers.memoryAllocateInfo();
            VkMemoryRequirements memReqs;

            copyCmd.Begin();

            // Create a host-visible staging buffer that contains the raw image data
            VkBuffer       stagingBuffer;
            VkDeviceMemory stagingMemory;


            var pixels    = tex2D.GetPixelSpan();
            var byteCount = (ulong)(pixels.Length * Unsafe.SizeOf <Rgba32>());

            VkBufferCreateInfo bufferCreateInfo = Initializers.bufferCreateInfo();

            bufferCreateInfo.size = byteCount;
            // This buffer is used as a transfer source for the buffer copy
            bufferCreateInfo.usage       = VkBufferUsageFlags.TransferSrc;
            bufferCreateInfo.sharingMode = VkSharingMode.Exclusive;

            Util.CheckResult(vkCreateBuffer(device.device, &bufferCreateInfo, null, &stagingBuffer));

            // Get memory requirements for the staging buffer (alignment, memory type bits)
            vkGetBufferMemoryRequirements(device.device, stagingBuffer, &memReqs);

            memAllocInfo.allocationSize = memReqs.size;
            // Get memory type index for a host visible buffer
            memAllocInfo.memoryTypeIndex = device.vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent);

            Util.CheckResult(vkAllocateMemory(device.device, &memAllocInfo, null, &stagingMemory));
            Util.CheckResult(vkBindBufferMemory(device.device, stagingBuffer, stagingMemory, 0));

            // Copy texture data into staging buffer
            byte *data;

            Util.CheckResult(vkMapMemory(device.device, stagingMemory, 0, memReqs.size, 0, (void **)&data));

            fixed(Rgba32 *pixelDataPtr = &pixels[0])
            {
                Unsafe.CopyBlock(data, pixelDataPtr, (uint)byteCount);
            }

            vkUnmapMemory(device.device, stagingMemory);

            // Setup buffer copy regions for each mip level
            using NativeList <VkBufferImageCopy> bufferCopyRegions = new NativeList <VkBufferImageCopy>();
            uint offset = 0;

            VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy();

            bufferCopyRegion.imageSubresource.aspectMask     = VkImageAspectFlags.Color;
            bufferCopyRegion.imageSubresource.mipLevel       = 0;
            bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
            bufferCopyRegion.imageSubresource.layerCount     = 1;
            bufferCopyRegion.imageExtent.width  = (uint)tex2D.Width;
            bufferCopyRegion.imageExtent.height = (uint)tex2D.Height;
            bufferCopyRegion.imageExtent.depth  = 1;
            bufferCopyRegion.bufferOffset       = offset;

            bufferCopyRegions.Add(bufferCopyRegion);

            VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange();

            subresourceRange.aspectMask   = VkImageAspectFlags.Color;
            subresourceRange.baseMipLevel = 0;
            subresourceRange.levelCount   = mipLevels;
            subresourceRange.layerCount   = 1;

            // Image barrier for optimal image (target)
            // Optimal image will be used as destination for the copy
            Tools.setImageLayout(
                copyCmd.vkCmd,
                image,
                VkImageAspectFlags.Color,
                VkImageLayout.Undefined,
                VkImageLayout.TransferDstOptimal,
                subresourceRange);

            // Copy mip levels from staging buffer
            vkCmdCopyBufferToImage(
                copyCmd.vkCmd,
                stagingBuffer,
                image,
                VkImageLayout.TransferDstOptimal,
                bufferCopyRegions.Count,
                bufferCopyRegions.Data);

            // Change texture image layout to shader read after all mip levels have been copied
            Tools.setImageLayout(
                copyCmd.vkCmd,
                image,
                VkImageAspectFlags.Color,
                VkImageLayout.TransferDstOptimal,
                imageLayout,
                subresourceRange);

            copyCmd.End();
            device.FlushCommandBuffer(copyCmd);

            //device.flushCommandBuffer(copyCmd, copyQueue);

            // Clean up staging resources
            vkFreeMemory(device.device, stagingMemory, null);
            vkDestroyBuffer(device.device, stagingBuffer, null);
        }
예제 #23
0
        private void InitializeFromImpl(DataBox[] dataBoxes = null)
        {
            NativeFormat = VulkanConvertExtensions.ConvertPixelFormat(ViewFormat);
            HasStencil   = IsStencilFormat(ViewFormat);

            NativeImageAspect = IsDepthStencil ? VkImageAspectFlags.Depth : VkImageAspectFlags.Color;
            if (HasStencil)
            {
                NativeImageAspect |= VkImageAspectFlags.Stencil;
            }


            var arraySlice = ArraySlice;
            var mipLevel   = MipLevel;

            GetViewSliceBounds(ViewType, ref arraySlice, ref mipLevel, out var arrayOrDepthCount, out var mipCount);
            var arrayCount = Dimension == TextureDimension.Texture3D ? 1 : arrayOrDepthCount;

            NativeResourceRange = new VkImageSubresourceRange(NativeImageAspect, (uint)mipLevel, (uint)mipCount, (uint)arraySlice, (uint)arrayCount);

            // For depth-stencil formats, automatically fall back to a supported one
            if (IsDepthStencil && HasStencil)
            {
                NativeFormat = GetFallbackDepthStencilFormat(GraphicsDevice, NativeFormat);
            }

            if (Usage == GraphicsResourceUsage.Staging)
            {
                if (NativeImage != VkImage.Null)
                {
                    throw new InvalidOperationException();
                }

                if (isNotOwningResources)
                {
                    throw new InvalidOperationException();
                }

                NativeAccessMask = VkAccessFlags.HostRead | VkAccessFlags.HostWrite;

                NativePipelineStageMask = VkPipelineStageFlags.Host;

                if (ParentTexture != null)
                {
                    // Create only a view
                    NativeBuffer = ParentTexture.NativeBuffer;
                    NativeMemory = ParentTexture.NativeMemory;
                }
                else
                {
                    CreateBuffer();

                    if (dataBoxes != null && dataBoxes.Length > 0)
                    {
                        InitializeData(dataBoxes);
                    }
                }
            }
            else
            {
                if (NativeImage != VkImage.Null)
                {
                    throw new InvalidOperationException();
                }

                NativeLayout =
                    IsRenderTarget ? VkImageLayout.ColorAttachmentOptimal :
                    IsDepthStencil ? VkImageLayout.DepthStencilAttachmentOptimal :
                    IsShaderResource ? VkImageLayout.ShaderReadOnlyOptimal :
                    VkImageLayout.General;

                if (NativeLayout == VkImageLayout.TransferDstOptimal)
                {
                    NativeAccessMask = VkAccessFlags.TransferRead;
                }

                if (NativeLayout == VkImageLayout.ColorAttachmentOptimal)
                {
                    NativeAccessMask = VkAccessFlags.ColorAttachmentWrite;
                }

                if (NativeLayout == VkImageLayout.DepthStencilAttachmentOptimal)
                {
                    NativeAccessMask = VkAccessFlags.DepthStencilAttachmentWrite;
                }

                if (NativeLayout == VkImageLayout.ShaderReadOnlyOptimal)
                {
                    NativeAccessMask = VkAccessFlags.ShaderRead | VkAccessFlags.InputAttachmentRead;
                }

                NativePipelineStageMask =
                    IsRenderTarget ? VkPipelineStageFlags.ColorAttachmentOutput :
                    IsDepthStencil ? VkPipelineStageFlags.ColorAttachmentOutput | VkPipelineStageFlags.EarlyFragmentTests | VkPipelineStageFlags.LateFragmentTests :
                    IsShaderResource ? VkPipelineStageFlags.VertexInput | VkPipelineStageFlags.FragmentShader :
                    VkPipelineStageFlags.None;

                if (ParentTexture != null)
                {
                    // Create only a view
                    NativeImage  = ParentTexture.NativeImage;
                    NativeMemory = ParentTexture.NativeMemory;
                }
                else
                {
                    if (!isNotOwningResources)
                    {
                        CreateImage();

                        InitializeData(dataBoxes);
                    }
                }

                if (!isNotOwningResources)
                {
                    NativeImageView           = GetImageView(ViewType, ArraySlice, MipLevel);
                    NativeColorAttachmentView = GetColorAttachmentView(ViewType, ArraySlice, MipLevel);
                    NativeDepthStencilView    = GetDepthStencilView();
                }
            }
        }
예제 #24
0
        /// <summary>
        /// Puts all pending transfers in the transfer queue
        /// </summary>
        /// <returns>true if anything was queued</returns>
        public bool Flush()
        {
            var flushed = 0;

            Interlocked.Increment(ref _activeFlushers);

            CommandBufferPooledExclusiveUse buffer = null;

            try
            {
                CommandBufferRecorder recorder = default;

                while (_pendingFlush.TryDequeue(out var temp))
                {
                    if (buffer == null)
                    {
                        buffer   = _cmdBufferPool.Borrow();
                        recorder = buffer.RecordCommands(VkCommandBufferUsageFlag.OneTimeSubmit);
                    }

                    flushed++;
                    buffer.SubmissionFinished += temp.Finished;
                    switch (temp)
                    {
                    case PendingFlushBuffer pendingBuffer:
                    {
                        _log.Trace(
                            $"Transferring {pendingBuffer.Size} bytes to {pendingBuffer.Destination}\t({_pendingFlush.Count} remain)");
                        var target = (IBindableBuffer)pendingBuffer;

                        if (temp.Arguments.SrcQueueFamily != _transferQueue.FamilyIndex)
                        {
                            recorder.BufferMemoryBarrier(target.BindingHandle,
                                                         VkAccessFlag.AllExceptExt, pendingBuffer.Arguments.SrcQueueFamily,
                                                         VkAccessFlag.AllExceptExt, _transferQueue.FamilyIndex, VkPipelineStageFlag.AllCommands,
                                                         VkPipelineStageFlag.AllCommands, VkDependencyFlag.None,
                                                         target.Offset, target.Size);
                        }

                        recorder.CopyBuffer(pendingBuffer.Handle.BackingBuffer, target.BindingHandle,
                                            new VkBufferCopy
                            {
                                SrcOffset = pendingBuffer.Handle.Offset,
                                DstOffset = target.Offset,
                                Size      = target.Size
                            });
                        if (temp.Arguments.DstQueueFamily != _transferQueue.FamilyIndex)
                        {
                            recorder.BufferMemoryBarrier(pendingBuffer.Destination.BindingHandle,
                                                         VkAccessFlag.AllExceptExt, _transferQueue.FamilyIndex, VkAccessFlag.AllExceptExt,
                                                         temp.Arguments.DstQueueFamily,
                                                         VkPipelineStageFlag.AllCommands, VkPipelineStageFlag.AllCommands,
                                                         VkDependencyFlag.None, target.Offset, target.Size);
                        }

                        if (temp.Arguments.SetEvent != null)
                        {
                            recorder.Handle.SetEvent(temp.Arguments.SetEvent.Handle,
                                                     VkPipelineStageFlag.AllCommands);
                        }
                        break;
                    }

                    case PendingFlushImage pendingImage:
                    {
                        _log.Trace(
                            $"Transferring {pendingImage.CopyData.BufferRowLength * pendingImage.CopyData.ImageExtent.Height} pixels to {pendingImage.Destination}\t({_pendingFlush.Count} remain)");
                        var range = new VkImageSubresourceRange
                        {
                            AspectMask     = pendingImage.CopyData.ImageSubresource.AspectMask,
                            BaseMipLevel   = pendingImage.CopyData.ImageSubresource.MipLevel,
                            LevelCount     = 1,
                            BaseArrayLayer = pendingImage.CopyData.ImageSubresource.BaseArrayLayer,
                            LayerCount     = pendingImage.CopyData.ImageSubresource.LayerCount
                        };
                        if (temp.Arguments.SrcQueueFamily != _transferQueue.FamilyIndex)
                        {
                            recorder.ImageMemoryBarrier(pendingImage.Destination.Handle,
                                                        pendingImage.Destination.Format, VkImageLayout.Undefined,
                                                        VkImageLayout.TransferDstOptimal, range, VkDependencyFlag.None,
                                                        pendingImage.Arguments.SrcQueueFamily, _transferQueue.FamilyIndex);
                        }
                        recorder.CopyBufferToImage(pendingImage.Handle.BackingBuffer.Handle,
                                                   pendingImage.Destination.Handle,
                                                   new VkBufferImageCopy
                            {
                                BufferOffset =
                                    pendingImage.Handle.Offset + pendingImage.CopyData.BufferOffset,
                                BufferRowLength   = pendingImage.CopyData.BufferRowLength,
                                BufferImageHeight = pendingImage.CopyData.BufferImageHeight,
                                ImageSubresource  = pendingImage.CopyData.ImageSubresource,
                                ImageOffset       = pendingImage.CopyData.ImageOffset,
                                ImageExtent       = pendingImage.CopyData.ImageExtent
                            });
                        if (temp.Arguments.DstQueueFamily != _transferQueue.FamilyIndex)
                        {
                            recorder.ImageMemoryBarrier(pendingImage.Destination.Handle,
                                                        pendingImage.Destination.Format, VkImageLayout.Undefined,
                                                        VkImageLayout.TransferDstOptimal, range, VkDependencyFlag.None,
                                                        _transferQueue.FamilyIndex, temp.Arguments.DstQueueFamily);
                        }

                        if (temp.Arguments.SetEvent != null)
                        {
                            recorder.Handle.SetEvent(temp.Arguments.SetEvent.Handle,
                                                     VkPipelineStageFlag.AllCommands);
                        }
                        break;
                    }

                    default:
                        throw new InvalidOperationException(
                                  $"Can't handle pending data {temp.GetType().Name}");
                    }
                }

                if (buffer != null)
                {
                    recorder.Commit();
                    _transferQueue.Submit(buffer);
                }
            }
            finally
            {
                if (buffer != null)
                {
                    _cmdBufferPool.Return(buffer);
                }
                Interlocked.Decrement(ref _activeFlushers);
            }

            return(flushed > 0);
        }
예제 #25
0
        void loadCubemap(string filename, VkFormat format, bool forceLinearTiling)
        {
            KtxFile texCube;
            using (var fs = File.OpenRead(filename))
            {
                texCube = KtxFile.Load(fs, readKeyValuePairs: false);
            }

            cubeMap.width = texCube.Header.PixelWidth;
            cubeMap.height = texCube.Header.PixelHeight;
            cubeMap.mipLevels = texCube.Header.NumberOfMipmapLevels;

            VkMemoryAllocateInfo memAllocInfo = Initializers.memoryAllocateInfo();
            VkMemoryRequirements memReqs;

            // Create a host-visible staging buffer that contains the raw image data
            VkBuffer stagingBuffer;
            VkDeviceMemory stagingMemory;

            VkBufferCreateInfo bufferCreateInfo = Initializers.bufferCreateInfo();
            bufferCreateInfo.size = texCube.GetTotalSize();
            // This buffer is used as a transfer source for the buffer copy
            bufferCreateInfo.usage = VkBufferUsageFlags.TransferSrc;
            bufferCreateInfo.sharingMode = VkSharingMode.Exclusive;

            Util.CheckResult(vkCreateBuffer(device, &bufferCreateInfo, null, &stagingBuffer));

            // Get memory requirements for the staging buffer (alignment, memory type bits)
            vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs);
            memAllocInfo.allocationSize = memReqs.size;
            // Get memory type index for a host visible buffer
            memAllocInfo.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent);
            Util.CheckResult(vkAllocateMemory(device, &memAllocInfo, null, &stagingMemory));
            Util.CheckResult(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0));

            // Copy texture data into staging buffer
            byte* data;
            Util.CheckResult(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void**)&data));
            byte[] allTextureData = texCube.GetAllTextureData();
            fixed (byte* texCubeDataPtr = &allTextureData[0])
            {
                Unsafe.CopyBlock(data, texCubeDataPtr, (uint)allTextureData.Length);
            }

            vkUnmapMemory(device, stagingMemory);

            // Create optimal tiled target image
            VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo();
            imageCreateInfo.imageType = VkImageType.Image2D;
            imageCreateInfo.format = format;
            imageCreateInfo.mipLevels = cubeMap.mipLevels;
            imageCreateInfo.samples = VkSampleCountFlags.Count1;
            imageCreateInfo.tiling = VkImageTiling.Optimal;
            imageCreateInfo.usage = VkImageUsageFlags.Sampled;
            imageCreateInfo.sharingMode = VkSharingMode.Exclusive;
            imageCreateInfo.initialLayout = VkImageLayout.Undefined;
            imageCreateInfo.extent = new VkExtent3D { width = cubeMap.width, height = cubeMap.height, depth = 1 };
            imageCreateInfo.usage = VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled;
            // Cube faces count as array layers in Vulkan
            imageCreateInfo.arrayLayers = 6;
            // This flag is required for cube map images
            imageCreateInfo.flags = VkImageCreateFlags.CubeCompatible;

            Util.CheckResult(vkCreateImage(device, &imageCreateInfo, null, out cubeMap.image));

            vkGetImageMemoryRequirements(device, cubeMap.image, &memReqs);

            memAllocInfo.allocationSize = memReqs.size;
            memAllocInfo.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal);

            Util.CheckResult(vkAllocateMemory(device, &memAllocInfo, null, out cubeMap.deviceMemory));
            Util.CheckResult(vkBindImageMemory(device, cubeMap.image, cubeMap.deviceMemory, 0));

            VkCommandBuffer copyCmd = createCommandBuffer(VkCommandBufferLevel.Primary, true);

            // Setup buffer copy regions for each face including all of it's miplevels
            NativeList<VkBufferImageCopy> bufferCopyRegions = new NativeList<VkBufferImageCopy>();
            uint offset = 0;

            for (uint face = 0; face < 6; face++)
            {
                for (uint level = 0; level < cubeMap.mipLevels; level++)
                {
                    VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy();
                    bufferCopyRegion.imageSubresource.aspectMask = VkImageAspectFlags.Color;
                    bufferCopyRegion.imageSubresource.mipLevel = level;
                    bufferCopyRegion.imageSubresource.baseArrayLayer = face;
                    bufferCopyRegion.imageSubresource.layerCount = 1;
                    bufferCopyRegion.imageExtent.width = texCube.Faces[face].Mipmaps[level].Width;
                    bufferCopyRegion.imageExtent.height = texCube.Faces[face].Mipmaps[level].Height;
                    bufferCopyRegion.imageExtent.depth = 1;
                    bufferCopyRegion.bufferOffset = offset;

                    bufferCopyRegions.Add(bufferCopyRegion);

                    // Increase offset into staging buffer for next level / face
                    offset += texCube.Faces[face].Mipmaps[level].SizeInBytes;
                }
            }

            // Image barrier for optimal image (target)
            // Set initial layout for all array layers (faces) of the optimal (target) tiled texture
            VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange();
            subresourceRange.aspectMask = VkImageAspectFlags.Color;
            subresourceRange.baseMipLevel = 0;
            subresourceRange.levelCount = cubeMap.mipLevels;
            subresourceRange.layerCount = 6;

            Tools.setImageLayout(
                copyCmd,
                cubeMap.image,
                VkImageAspectFlags.Color,
                VkImageLayout.Undefined,
                VkImageLayout.TransferDstOptimal,
                subresourceRange);

            // Copy the cube map faces from the staging buffer to the optimal tiled image
            vkCmdCopyBufferToImage(
                copyCmd,
                stagingBuffer,
                cubeMap.image,
                VkImageLayout.TransferDstOptimal,
                bufferCopyRegions.Count,
                bufferCopyRegions.Data);

            // Change texture image layout to shader read after all faces have been copied
            cubeMap.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
            Tools.setImageLayout(
                copyCmd,
                cubeMap.image,
                VkImageAspectFlags.Color,
                VkImageLayout.TransferDstOptimal,
                cubeMap.imageLayout,
                subresourceRange);

            flushCommandBuffer(copyCmd, queue, true);

            // Create sampler
            VkSamplerCreateInfo sampler = Initializers.samplerCreateInfo();
            sampler.magFilter = VkFilter.Linear;
            sampler.minFilter = VkFilter.Linear;
            sampler.mipmapMode = VkSamplerMipmapMode.Linear;
            sampler.addressModeU = VkSamplerAddressMode.ClampToEdge;
            sampler.addressModeV = sampler.addressModeU;
            sampler.addressModeW = sampler.addressModeU;
            sampler.mipLodBias = 0.0f;
            sampler.compareOp = VkCompareOp.Never;
            sampler.minLod = 0.0f;
            sampler.maxLod = cubeMap.mipLevels;
            sampler.borderColor = VkBorderColor.FloatOpaqueWhite;
            sampler.maxAnisotropy = 1.0f;
            if (vulkanDevice.features.samplerAnisotropy == 1)
            {
                sampler.maxAnisotropy = vulkanDevice.properties.limits.maxSamplerAnisotropy;
                sampler.anisotropyEnable = True;
            }
            Util.CheckResult(vkCreateSampler(device, &sampler, null, out cubeMap.sampler));

            // Create image view
            VkImageViewCreateInfo view = Initializers.imageViewCreateInfo();
            // Cube map view type
            view.viewType = VkImageViewType.ImageCube;
            view.format = format;
            view.components = new VkComponentMapping { r = VkComponentSwizzle.R, g = VkComponentSwizzle.G, b = VkComponentSwizzle.B, a = VkComponentSwizzle.A };
            view.subresourceRange = new VkImageSubresourceRange { aspectMask = VkImageAspectFlags.Color, baseMipLevel = 0, layerCount = 1, baseArrayLayer = 0, levelCount = 1 };
            // 6 array layers (faces)
            view.subresourceRange.layerCount = 6;
            // Set number of mip levels
            view.subresourceRange.levelCount = cubeMap.mipLevels;
            view.image = cubeMap.image;
            Util.CheckResult(vkCreateImageView(device, &view, null, out cubeMap.view));

            // Clean up staging resources
            vkFreeMemory(device, stagingMemory, null);
            vkDestroyBuffer(device, stagingBuffer, null);
        }
예제 #26
0
        void loadTexture(string fileName, VkFormat format, bool forceLinearTiling)
        {
            KtxFile tex2D;

            using (var fs = File.OpenRead(fileName))
            {
                tex2D = KtxFile.Load(fs, false);
            }

            VkFormatProperties formatProperties;

            texture.width     = tex2D.Header.PixelWidth;
            texture.height    = tex2D.Header.PixelHeight;
            texture.mipLevels = tex2D.Header.NumberOfMipmapLevels;

            // Get Device properites for the requested texture format
            vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties);

            // Only use linear tiling if requested (and supported by the Device)
            // Support for linear tiling is mostly limited, so prefer to use
            // optimal tiling instead
            // On most implementations linear tiling will only support a very
            // limited amount of formats and features (mip maps, cubemaps, arrays, etc.)
            uint useStaging = 1;

            // Only use linear tiling if forced
            if (forceLinearTiling)
            {
                // Don't use linear if format is not supported for (linear) shader sampling
                useStaging = ((formatProperties.linearTilingFeatures & VkFormatFeatureFlags.SampledImage) != VkFormatFeatureFlags.SampledImage) ? 1u : 0u;
            }

            VkMemoryAllocateInfo memAllocInfo = Initializers.memoryAllocateInfo();
            VkMemoryRequirements memReqs      = new VkMemoryRequirements();

            if (useStaging == 1)
            {
                // Create a host-visible staging buffer that contains the raw image data
                VkBuffer       stagingBuffer;
                VkDeviceMemory stagingMemory;

                VkBufferCreateInfo bufferCreateInfo = Initializers.bufferCreateInfo();
                bufferCreateInfo.size = tex2D.GetTotalSize();
                // This buffer is used as a transfer source for the buffer copy
                bufferCreateInfo.usage       = VkBufferUsageFlags.TransferSrc;
                bufferCreateInfo.sharingMode = VkSharingMode.Exclusive;

                Util.CheckResult(vkCreateBuffer(device, &bufferCreateInfo, null, &stagingBuffer));

                // Get memory requirements for the staging buffer (alignment, memory type bits)
                vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs);

                memAllocInfo.allocationSize = memReqs.size;
                // Get memory type index for a host visible buffer
                memAllocInfo.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent);

                Util.CheckResult(vkAllocateMemory(device, &memAllocInfo, null, &stagingMemory));
                Util.CheckResult(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0));

                // Copy texture data into staging buffer
                byte *data;
                Util.CheckResult(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data));
                byte[] allData = tex2D.GetAllTextureData();
                fixed(byte *tex2DDataPtr = &allData[0])
                {
                    Unsafe.CopyBlock(data, tex2DDataPtr, (uint)allData.Length);
                }

                vkUnmapMemory(device, stagingMemory);

                // Setup buffer copy regions for each mip level
                NativeList <VkBufferImageCopy> bufferCopyRegions = new NativeList <VkBufferImageCopy>();
                uint offset = 0;

                for (uint i = 0; i < texture.mipLevels; i++)
                {
                    VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy();
                    bufferCopyRegion.imageSubresource.aspectMask     = VkImageAspectFlags.Color;
                    bufferCopyRegion.imageSubresource.mipLevel       = i;
                    bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
                    bufferCopyRegion.imageSubresource.layerCount     = 1;
                    bufferCopyRegion.imageExtent.width  = tex2D.Faces[0].Mipmaps[i].Width;
                    bufferCopyRegion.imageExtent.height = tex2D.Faces[0].Mipmaps[i].Height;
                    bufferCopyRegion.imageExtent.depth  = 1;
                    bufferCopyRegion.bufferOffset       = offset;

                    bufferCopyRegions.Add(bufferCopyRegion);

                    offset += tex2D.Faces[0].Mipmaps[i].SizeInBytes;
                }

                // Create optimal tiled target image
                VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo();
                imageCreateInfo.imageType   = VkImageType.Image2D;
                imageCreateInfo.format      = format;
                imageCreateInfo.mipLevels   = texture.mipLevels;
                imageCreateInfo.arrayLayers = 1;
                imageCreateInfo.samples     = VkSampleCountFlags.Count1;
                imageCreateInfo.tiling      = VkImageTiling.Optimal;
                imageCreateInfo.sharingMode = VkSharingMode.Exclusive;
                // Set initial layout of the image to undefined
                imageCreateInfo.initialLayout = VkImageLayout.Undefined;
                imageCreateInfo.extent        = new VkExtent3D {
                    width = texture.width, height = texture.height, depth = 1
                };
                imageCreateInfo.usage = VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled;

                Util.CheckResult(vkCreateImage(device, &imageCreateInfo, null, out texture.image));

                vkGetImageMemoryRequirements(device, texture.image, &memReqs);

                memAllocInfo.allocationSize  = memReqs.size;
                memAllocInfo.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal);

                Util.CheckResult(vkAllocateMemory(device, &memAllocInfo, null, out texture.DeviceMemory));
                Util.CheckResult(vkBindImageMemory(device, texture.image, texture.DeviceMemory, 0));

                VkCommandBuffer copyCmd = base.createCommandBuffer(VkCommandBufferLevel.Primary, true);

                // Image barrier for optimal image

                // The sub resource range describes the regions of the image we will be transition
                VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange();
                // Image only contains color data
                subresourceRange.aspectMask = VkImageAspectFlags.Color;
                // Start at first mip level
                subresourceRange.baseMipLevel = 0;
                // We will transition on all mip levels
                subresourceRange.levelCount = texture.mipLevels;
                // The 2D texture only has one layer
                subresourceRange.layerCount = 1;

                // Optimal image will be used as destination for the copy, so we must transfer from our
                // initial undefined image layout to the transfer destination layout
                setImageLayout(
                    copyCmd,
                    texture.image,
                    VkImageAspectFlags.Color,
                    VkImageLayout.Undefined,
                    VkImageLayout.TransferDstOptimal,
                    subresourceRange);

                // Copy mip levels from staging buffer
                vkCmdCopyBufferToImage(
                    copyCmd,
                    stagingBuffer,
                    texture.image,
                    VkImageLayout.TransferDstOptimal,
                    bufferCopyRegions.Count,
                    bufferCopyRegions.Data);

                // Change texture image layout to shader read after all mip levels have been copied
                texture.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
                setImageLayout(
                    copyCmd,
                    texture.image,
                    VkImageAspectFlags.Color,
                    VkImageLayout.TransferDstOptimal,
                    texture.imageLayout,
                    subresourceRange);

                flushCommandBuffer(copyCmd, queue, true);

                // Clean up staging resources
                vkFreeMemory(device, stagingMemory, null);
                vkDestroyBuffer(device, stagingBuffer, null);
            }
            else
            {
                throw new NotImplementedException();

                /*
                 * // Prefer using optimal tiling, as linear tiling
                 * // may support only a small set of features
                 * // depending on implementation (e.g. no mip maps, only one layer, etc.)
                 *
                 * VkImage mappableImage;
                 * VkDeviceMemory mappableMemory;
                 *
                 * // Load mip map level 0 to linear tiling image
                 * VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo();
                 * imageCreateInfo.imageType = VkImageType._2d;
                 * imageCreateInfo.format = format;
                 * imageCreateInfo.mipLevels = 1;
                 * imageCreateInfo.arrayLayers = 1;
                 * imageCreateInfo.samples = VkSampleCountFlags._1;
                 * imageCreateInfo.tiling = VkImageTiling.Linear;
                 * imageCreateInfo.usage = VkImageUsageFlags.Sampled;
                 * imageCreateInfo.sharingMode = VkSharingMode.Exclusive;
                 * imageCreateInfo.initialLayout = VkImageLayout.Preinitialized;
                 * imageCreateInfo.extent = new VkExtent3D { width = texture.width, height = texture.height, depth = 1 };
                 * Util.CheckResult(vkCreateImage(Device, &imageCreateInfo, null, &mappableImage));
                 *
                 * // Get memory requirements for this image
                 * // like size and alignment
                 * vkGetImageMemoryRequirements(Device, mappableImage, &memReqs);
                 * // Set memory allocation size to required memory size
                 * memAllocInfo.allocationSize = memReqs.size;
                 *
                 * // Get memory type that can be mapped to host memory
                 * memAllocInfo.memoryTypeIndex = VulkanDevice.GetMemoryType(memReqs.memoryTypeBits,  VkMemoryPropertyFlags.HostVisible |  VkMemoryPropertyFlags.HostCoherent);
                 *
                 * // Allocate host memory
                 * Util.CheckResult(vkAllocateMemory(Device, &memAllocInfo, null, &mappableMemory));
                 *
                 * // Bind allocated image for use
                 * Util.CheckResult(vkBindImageMemory(Device, mappableImage, mappableMemory, 0));
                 *
                 * // Get sub resource layout
                 * // Mip map count, array layer, etc.
                 * VkImageSubresource subRes = new VkImageSubresource();
                 * subRes.aspectMask =  VkImageAspectFlags.Color;
                 *
                 * VkSubresourceLayout subResLayout;
                 * void* data;
                 *
                 * // Get sub resources layout
                 * // Includes row pitch, size offsets, etc.
                 * vkGetImageSubresourceLayout(Device, mappableImage, &subRes, &subResLayout);
                 *
                 * // Map image memory
                 * Util.CheckResult(vkMapMemory(Device, mappableMemory, 0, memReqs.size, 0, &data));
                 *
                 * // Copy image data into memory
                 * memcpy(data, tex2D[subRes.mipLevel].data(), tex2D[subRes.mipLevel].size());
                 *
                 * vkUnmapMemory(Device, mappableMemory);
                 *
                 * // Linear tiled images don't need to be staged
                 * // and can be directly used as textures
                 * texture.image = mappableImage;
                 * texture.DeviceMemory = mappableMemory;
                 * texture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
                 *
                 * VkCommandBuffer copyCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
                 *
                 * // Setup image memory barrier transfer image to shader read layout
                 *
                 * // The sub resource range describes the regions of the image we will be transition
                 * VkImageSubresourceRange subresourceRange = { };
                 * // Image only contains color data
                 * subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
                 * // Start at first mip level
                 * subresourceRange.baseMipLevel = 0;
                 * // Only one mip level, most implementations won't support more for linear tiled images
                 * subresourceRange.levelCount = 1;
                 * // The 2D texture only has one layer
                 * subresourceRange.layerCount = 1;
                 *
                 * setImageLayout(
                 *  copyCmd,
                 *  texture.image,
                 *  VK_IMAGE_ASPECT_COLOR_BIT,
                 *  VK_IMAGE_LAYOUT_PREINITIALIZED,
                 *  texture.imageLayout,
                 *  subresourceRange);
                 *
                 * VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true);
                 */
            }

            // Create sampler
            // In Vulkan textures are accessed by samplers
            // This separates all the sampling information from the
            // texture data
            // This means you could have multiple sampler objects
            // for the same texture with different settings
            // Similar to the samplers available with OpenGL 3.3
            VkSamplerCreateInfo sampler = Initializers.samplerCreateInfo();

            sampler.magFilter    = VkFilter.Linear;
            sampler.minFilter    = VkFilter.Linear;
            sampler.mipmapMode   = VkSamplerMipmapMode.Linear;
            sampler.addressModeU = VkSamplerAddressMode.Repeat;
            sampler.addressModeV = VkSamplerAddressMode.Repeat;
            sampler.addressModeW = VkSamplerAddressMode.Repeat;
            sampler.mipLodBias   = 0.0f;
            sampler.compareOp    = VkCompareOp.Never;
            sampler.minLod       = 0.0f;
            // Set max level-of-detail to mip level count of the texture
            sampler.maxLod = (useStaging == 1) ? (float)texture.mipLevels : 0.0f;
            // Enable anisotropic filtering
            // This feature is optional, so we must check if it's supported on the Device
            if (vulkanDevice.features.samplerAnisotropy == 1)
            {
                // Use max. level of anisotropy for this example
                sampler.maxAnisotropy    = vulkanDevice.properties.limits.maxSamplerAnisotropy;
                sampler.anisotropyEnable = True;
            }
            else
            {
                // The Device does not support anisotropic filtering
                sampler.maxAnisotropy    = 1.0f;
                sampler.anisotropyEnable = False;
            }
            sampler.borderColor = VkBorderColor.FloatOpaqueWhite;
            Util.CheckResult(vkCreateSampler(device, ref sampler, null, out texture.sampler));

            // Create image view
            // Textures are not directly accessed by the shaders and
            // are abstracted by image views containing additional
            // information and sub resource ranges
            VkImageViewCreateInfo view = Initializers.imageViewCreateInfo();

            view.viewType   = VkImageViewType.Image2D;
            view.format     = format;
            view.components = new VkComponentMapping {
                r = VkComponentSwizzle.R, g = VkComponentSwizzle.G, b = VkComponentSwizzle.B, a = VkComponentSwizzle.A
            };
            // The subresource range describes the set of mip levels (and array layers) that can be accessed through this image view
            // It's possible to create multiple image views for a single image referring to different (and/or overlapping) ranges of the image
            view.subresourceRange.aspectMask     = VkImageAspectFlags.Color;
            view.subresourceRange.baseMipLevel   = 0;
            view.subresourceRange.baseArrayLayer = 0;
            view.subresourceRange.layerCount     = 1;
            // Linear tiling usually won't support mip maps
            // Only set mip map count if optimal tiling is used
            view.subresourceRange.levelCount = (useStaging == 1) ? texture.mipLevels : 1;
            // The view will be based on the texture's image
            view.image = texture.image;
            Util.CheckResult(vkCreateImageView(device, &view, null, out texture.view));
        }
예제 #27
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);
        }
예제 #28
0
        public unsafe VkImageMemoryBarrier(
            VkImage image,
            VkImageLayout oldLayout,
            VkImageLayout newLayout,
            VkImageSubresourceRange subresourceRange,
            void *pNext = default)
        {
            sType         = VkStructureType.ImageMemoryBarrier;
            this.pNext    = pNext;
            srcAccessMask = 0;
            dstAccessMask = 0;

            // 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 (oldLayout)
            {
            case VkImageLayout.Undefined:
                // Image layout is undefined (or does not matter)
                // Only valid as initial layout
                // No flags required, listed only for completeness
                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
                srcAccessMask = VkAccessFlags.HostWrite;
                break;

            case VkImageLayout.ColorAttachmentOptimal:
                // Image is a color attachment
                // Make sure any writes to the color buffer have been finished
                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
                srcAccessMask = VkAccessFlags.DepthStencilAttachmentWrite;
                break;

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

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

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

            default:
                // Other source layouts aren't handled (yet)
                break;
            }

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

            case VkImageLayout.TransferSrcOptimal:
                // Image will be used as a transfer source
                // Make sure any reads from the image have been finished
                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
                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
                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 (srcAccessMask == 0)
                {
                    srcAccessMask = VkAccessFlags.HostWrite | VkAccessFlags.TransferWrite;
                }
                dstAccessMask = VkAccessFlags.ShaderRead;
                break;

            default:
                // Other source layouts aren't handled (yet)
                break;
            }

            this.oldLayout        = oldLayout;
            this.newLayout        = newLayout;
            srcQueueFamilyIndex   = Vulkan.QueueFamilyIgnored;
            dstQueueFamilyIndex   = Vulkan.QueueFamilyIgnored;
            this.image            = image;
            this.subresourceRange = subresourceRange;
        }
예제 #29
0
		///// <summary>
		///// build texture array
		///// </summary>
		///// <returns>The images.</returns>
		///// <param name="textureSize">Uniformized Texture size for all images</param>
		public void BuildTexArray (ref Image texArray, uint firstImg = 0) {
			int texDim = (int)texArray.CreateInfo.extent.width;

			PrimaryCommandBuffer cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);
			texArray.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, 
						VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.Transfer);
			transferQ.EndSubmitAndWait (cmd, true);
			
			VkImageBlit imageBlit = new VkImageBlit {
				srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1, 0),
				dstOffsets_1 = new VkOffset3D (texDim, texDim, 1)
			};

			for (int l = 0; l < gltf.Images.Length; l++) {
				GL.Image img = gltf.Images[l];
				Image vkimg = null;

				if (img.BufferView != null) {//load image from gltf buffer view
					GL.BufferView bv = gltf.BufferViews[(int)img.BufferView];
					ensureBufferIsLoaded (bv.Buffer);
					vkimg = Image.Load (dev, loadedBuffers[bv.Buffer].Slice (bv.ByteOffset), (ulong)bv.ByteLength, VkImageUsageFlags.TransferSrc);
				} else if (img.Uri.StartsWith ("data:", StringComparison.Ordinal)) {//load base64 encoded image
					Debug.WriteLine ("loading embedded image {0} : {1}", img.Name, img.MimeType);
					vkimg = Image.Load (dev, glTFLoader.loadDataUri (img), VkImageUsageFlags.TransferSrc);
				} else {
					Debug.WriteLine ("loading image {0} : {1} : {2}", img.Name, img.MimeType, img.Uri);//load image from file path in uri
					vkimg = Image.Load (dev, Path.Combine (baseDirectory, img.Uri), VkImageUsageFlags.TransferSrc);
				}

				imageBlit.srcOffsets_1 = new VkOffset3D ((int)vkimg.CreateInfo.extent.width, (int)vkimg.CreateInfo.extent.height, 1);
				imageBlit.dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1, 0, (uint)l + firstImg);

				cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);

				vkimg.SetLayout (cmd, VkImageAspectFlags.Color,
						VkAccessFlags.HostWrite, VkAccessFlags.TransferRead,
						VkImageLayout.Undefined, VkImageLayout.TransferSrcOptimal,
						VkPipelineStageFlags.Host, VkPipelineStageFlags.Transfer);

				Vk.vkCmdBlitImage (cmd.Handle, vkimg.Handle, VkImageLayout.TransferSrcOptimal,
					texArray.Handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear);
				
				transferQ.EndSubmitAndWait (cmd, true);								

				vkimg.Dispose ();
			}

			cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);

			uint imgCount = (uint)gltf.Images.Length;
			VkImageSubresourceRange mipSubRange = new VkImageSubresourceRange (VkImageAspectFlags.Color, 0, 1, firstImg, imgCount);

			for (int i = 1; i < texArray.CreateInfo.mipLevels; i++) {
				imageBlit = new VkImageBlit {
					srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, imgCount, (uint)i - 1, firstImg),
					srcOffsets_1 = new VkOffset3D ((int)texDim >> (i - 1), (int)texDim >> (i - 1), 1),
					dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, imgCount, (uint)i, firstImg),
					dstOffsets_1 = new VkOffset3D ((int)texDim >> i, (int)texDim >> i, 1)
				};

				texArray.SetLayout (cmd,
					VkAccessFlags.TransferWrite, VkAccessFlags.TransferRead,
					VkImageLayout.TransferDstOptimal, VkImageLayout.TransferSrcOptimal, mipSubRange,
					VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);

				Vk.vkCmdBlitImage (cmd.Handle, texArray.Handle, VkImageLayout.TransferSrcOptimal,
					texArray.Handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear);
				texArray.SetLayout (cmd, VkImageLayout.TransferSrcOptimal, VkImageLayout.ShaderReadOnlyOptimal, mipSubRange,
					VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader);

				mipSubRange.baseMipLevel = (uint)i;
			}
			mipSubRange.baseMipLevel = texArray.CreateInfo.mipLevels - 1;
			texArray.SetLayout (cmd, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal, mipSubRange,
				VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader);

			cmd.End ();
			transferQ.Submit (cmd);
			transferQ.WaitIdle ();
			cmd.Free ();
		}
예제 #30
0
        void loadTextureArray(string filename, VkFormat format)
        {
            KtxFile tex2DArray;

            using (var fs = File.OpenRead(filename))
            {
                tex2DArray = KtxFile.Load(fs, false);
            }

            textureArray.width  = tex2DArray.Header.PixelWidth;
            textureArray.height = tex2DArray.Header.PixelHeight;
            layerCount          = tex2DArray.Header.NumberOfArrayElements;

            VkMemoryAllocateInfo memAllocInfo = Initializers.memoryAllocateInfo();
            VkMemoryRequirements memReqs;

            // Create a host-visible staging buffer that contains the raw image data
            VkBuffer       stagingBuffer;
            VkDeviceMemory stagingMemory;

            VkBufferCreateInfo bufferCreateInfo = Initializers.bufferCreateInfo();

            bufferCreateInfo.size = tex2DArray.GetTotalSize();
            // This buffer is used as a transfer source for the buffer copy
            bufferCreateInfo.usage       = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
            bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

            Util.CheckResult(vkCreateBuffer(device, &bufferCreateInfo, null, &stagingBuffer));

            // Get memory requirements for the staging buffer (alignment, memory type bits)
            vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs);

            memAllocInfo.allocationSize = memReqs.size;
            // Get memory type index for a host visible buffer
            memAllocInfo.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);

            Util.CheckResult(vkAllocateMemory(device, &memAllocInfo, null, &stagingMemory));
            Util.CheckResult(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0));

            // Copy texture data into staging buffer
            byte *data;

            Util.CheckResult(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data));
            byte[] allTextureData = tex2DArray.GetAllTextureData();
            fixed(byte *texPtr = allTextureData)
            {
                Unsafe.CopyBlock(data, texPtr, (uint)allTextureData.Length);
            }

            vkUnmapMemory(device, stagingMemory);

            // Setup buffer copy regions for array layers
            NativeList <VkBufferImageCopy> bufferCopyRegions;
            IntPtr offset = IntPtr.Zero;

            for (uint layer = 0; layer < layerCount; layer++)
            {
                VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy();
                bufferCopyRegion.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
                bufferCopyRegion.imageSubresource.mipLevel       = 0;
                bufferCopyRegion.imageSubresource.baseArrayLayer = layer;
                bufferCopyRegion.imageSubresource.layerCount     = 1;
                bufferCopyRegion.imageExtent.width  = (uint)(tex2DArray[layer][0].extent().x);
                bufferCopyRegion.imageExtent.height = (uint)(tex2DArray[layer][0].extent().y);
                bufferCopyRegion.imageExtent.depth  = 1;
                bufferCopyRegion.bufferOffset       = offset;

                bufferCopyRegions.push_back(bufferCopyRegion);

                // Increase offset into staging buffer for next level / face
                offset += tex2DArray[layer][0].Count;
            }

            // Create optimal tiled target image
            VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo();

            imageCreateInfo.imageType     = VK_IMAGE_TYPE_2D;
            imageCreateInfo.format        = format;
            imageCreateInfo.mipLevels     = 1;
            imageCreateInfo.samples       = VK_SAMPLE_COUNT_1_BIT;
            imageCreateInfo.tiling        = VK_IMAGE_TILING_OPTIMAL;
            imageCreateInfo.usage         = VK_IMAGE_USAGE_SAMPLED_BIT;
            imageCreateInfo.sharingMode   = VK_SHARING_MODE_EXCLUSIVE;
            imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
            imageCreateInfo.extent        = new  { textureArray.width, textureArray.height, 1 };
            imageCreateInfo.usage         = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
            imageCreateInfo.arrayLayers   = layerCount;

            Util.CheckResult(vkCreateImage(device, &imageCreateInfo, null, &textureArray.image));

            vkGetImageMemoryRequirements(device, textureArray.image, &memReqs);

            memAllocInfo.allocationSize  = memReqs.size;
            memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);

            Util.CheckResult(vkAllocateMemory(device, &memAllocInfo, null, &textureArray.deviceMemory));
            Util.CheckResult(vkBindImageMemory(device, textureArray.image, textureArray.deviceMemory, 0));

            VkCommandBuffer copyCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);

            // Image barrier for optimal image (target)
            // Set initial layout for all array layers (faces) of the optimal (target) tiled texture
            VkImageSubresourceRange subresourceRange = { };

            subresourceRange.aspectMask   = VK_IMAGE_ASPECT_COLOR_BIT;
            subresourceRange.baseMipLevel = 0;
            subresourceRange.levelCount   = 1;
            subresourceRange.layerCount   = layerCount;

            vkstools::setImageLayout(
                copyCmd,
                textureArray.image,
                VK_IMAGE_ASPECT_COLOR_BIT,
                VK_IMAGE_LAYOUT_UNDEFINED,
                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                subresourceRange);

            // Copy the cube map faces from the staging buffer to the optimal tiled image
            vkCmdCopyBufferToImage(
                copyCmd,
                stagingBuffer,
                textureArray.image,
                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                bufferCopyRegions.Count,
                bufferCopyRegions.Data
                );

            // Change texture image layout to shader read after all faces have been copied
            textureArray.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
            vkstools::setImageLayout(
                copyCmd,
                textureArray.image,
                VK_IMAGE_ASPECT_COLOR_BIT,
                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                textureArray.imageLayout,
                subresourceRange);

            VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true);

            // Create sampler
            VkSamplerCreateInfo sampler = Initializers.samplerCreateInfo();

            sampler.magFilter     = VK_FILTER_LINEAR;
            sampler.minFilter     = VK_FILTER_LINEAR;
            sampler.mipmapMode    = VK_SAMPLER_MIPMAP_MODE_LINEAR;
            sampler.addressModeU  = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
            sampler.addressModeV  = sampler.addressModeU;
            sampler.addressModeW  = sampler.addressModeU;
            sampler.mipLodBias    = 0.0f;
            sampler.maxAnisotropy = 8;
            sampler.compareOp     = VK_COMPARE_OP_NEVER;
            sampler.minLod        = 0.0f;
            sampler.maxLod        = 0.0f;
            sampler.borderColor   = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
            Util.CheckResult(vkCreateSampler(device, &sampler, null, &textureArray.sampler));

            // Create image view
            VkImageViewCreateInfo view = Initializers.imageViewCreateInfo();

            view.viewType                    = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
            view.format                      = format;
            view.components                  = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };