Example #1
0
        /// <summary>
        /// Rebuilds the render target to use a new size.
        /// </summary>
        /// <param name="width">The new width of the render target.</param>
        /// <param name="height">The new height of the render target.</param>
        /// <param name="force">If <c>true</c>, the render target will be rebuilt even if the size doesnt change.</param>
        public void Rebuild(uint width, uint height, bool force = false)
        {
            if (!force && width == Width && height == Height)
            {
                return;
            }
            Width  = width;
            Height = height;

            // Destroy the existing objects, if needed
            VkView?.Dispose();
            VkImage?.Dispose();
            VkMemory?.Dispose();

            // Create the image
            var ici = new Vk.ImageCreateInfo
            {
                ImageType     = Vk.ImageType.Image2D,
                Extent        = new Vk.Extent3D((int)width, (int)height, 1),
                MipLevels     = 1,
                ArrayLayers   = 1,
                Format        = (Vk.Format)Format,
                Tiling        = Vk.ImageTiling.Optimal,
                InitialLayout = Vk.ImageLayout.Undefined,
                Usage         = Vk.ImageUsages.Sampled | Vk.ImageUsages.TransferSrc | Vk.ImageUsages.TransferDst |
                                (HasDepth ? Vk.ImageUsages.DepthStencilAttachment : Vk.ImageUsages.ColorAttachment), // No subpassInput support yet, but add it here
                SharingMode = Vk.SharingMode.Exclusive,
                Samples     = Vk.SampleCounts.Count1,                                                                // TODO: Change when we support multisampling
                Flags       = Vk.ImageCreateFlags.None
            };

            VkImage = Device.VkDevice.CreateImage(ici);

            // Create the backing memory for the image
            var memReq = VkImage.GetMemoryRequirements();
            var memIdx = Device.FindMemoryTypeIndex(memReq.MemoryTypeBits, Vk.MemoryProperties.DeviceLocal);

            if (memIdx == -1)
            {
                throw new InvalidOperationException("Cannot find a memory type that supports render targets (this means bad or out-of-date hardware)");
            }
            var mai = new Vk.MemoryAllocateInfo(memReq.Size, memIdx);

            VkMemory = Device.VkDevice.AllocateMemory(mai);
            DataSize = (uint)memReq.Size;
            VkImage.BindMemory(VkMemory);

            // Create the view
            var vci = new Vk.ImageViewCreateInfo(
                (Vk.Format)Format,
                new Vk.ImageSubresourceRange(VkAspects, 0, 1, 0, 1),
                viewType: Vk.ImageViewType.Image2D
                );

            VkView = VkImage.CreateView(vci);

            // Make the initial layout transition
            Device.SubmitScratchCommand(buf => {
                buf.CmdPipelineBarrier(Vk.PipelineStages.AllGraphics, Vk.PipelineStages.AllGraphics, imageMemoryBarriers: new[] { new Vk.ImageMemoryBarrier(
                                                                                                                                      VkImage, new Vk.ImageSubresourceRange(VkAspects, 0, 1, 0, 1), Vk.Accesses.None, Vk.Accesses.None,
                                                                                                                                      Vk.ImageLayout.Undefined, DefaultImageLayout
                                                                                                                                      ) });
            });

            // Build the transitions
            ClearBarrier = new Vk.ImageMemoryBarrier(
                VkImage, new Vk.ImageSubresourceRange(VkAspects, 0, 1, 0, 1), Vk.Accesses.None, Vk.Accesses.None,
                DefaultImageLayout, Vk.ImageLayout.TransferDstOptimal
                );
            AttachBarrier = new Vk.ImageMemoryBarrier(
                VkImage, new Vk.ImageSubresourceRange(VkAspects, 0, 1, 0, 1), Vk.Accesses.None, Vk.Accesses.None,
                Vk.ImageLayout.TransferDstOptimal, DefaultImageLayout
                );
        }