Beispiel #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
                );
        }
Beispiel #2
0
        public Framebuffer(VkDevice Device, int Width, int Height)
        {
            _Device           = Device;
            _Width            = Width;
            _Height           = Height;
            _FrameBufferColor = _Device.CreateImage(VkImageCreateFlag.NONE,
                                                    VkFormat.VK_FORMAT_B8G8R8A8_SRGB,
                                                    Width, Height,
                                                    1, 1,
                                                    VkSampleCountFlag.VK_SAMPLE_COUNT_1,
                                                    VkImageTiling.VK_IMAGE_TILING_OPTIMAL,
                                                    VkImageUsageFlag.VK_IMAGE_USAGE_COLOR_ATTACHMENT,
                                                    VkSharingMode.VK_SHARING_MODE_EXCLUSIVE,
                                                    null,
                                                    VkImageLayout.VK_IMAGE_LAYOUT_UNDEFINED);

            _ImageSize = _FrameBufferColor.MemoryRequirements.size;


            // We will back this image with Device Accessible Memomy so we can map it an copy
            // the content from the Host.
            // To do so we need to find the right memory type first.
            VkMemoryType deviceMemory = new VkMemoryType();

            foreach (VkMemoryType memoryType in _FrameBufferColor.MemoryRequirements.memoryTypes)
            {
                // Pick the first memory type that can be mapped into host memory
                if ((memoryType.propertyFlags & VkMemoryPropertyFlags.VK_MEMORY_PROPERTY_DEVICE_LOCAL) != 0)
                {
                    deviceMemory = memoryType;
                    break;
                }
            }

            VkDeviceMemory FrameBufferMemory = _Device.AllocateMemory(_FrameBufferColor.MemoryRequirements.size, deviceMemory);

            _FrameBufferColor.BindMemory(FrameBufferMemory, 0);

            // Allocate the host visible memory to transfer the framebuffer
            _TransferBuffer = _Device.CreateBuffer(0, _FrameBufferColor.MemoryRequirements.size, VkBufferUsageFlag.VK_BUFFER_USAGE_TRANSFER_DST, VkSharingMode.VK_SHARING_MODE_EXCLUSIVE, new VkQueueFamilyProperties[] { _Device.Queues[0].Family });

            // We will use a host visible buffer so we can map it an copy
            // the content from the Host.
            // To do so we need to find the right memory type first.
            VkMemoryType hostMemory = new VkMemoryType();

            foreach (VkMemoryType memoryType in _TransferBuffer.MemoryRequirements.memoryTypes)
            {
                // Pick the first memory type that can be mapped into host memory
                if ((memoryType.propertyFlags & VkMemoryPropertyFlags.VK_MEMORY_PROPERTY_HOST_VISIBLE) != 0)
                {
                    hostMemory = memoryType;
                    break;
                }
            }

            VkDeviceMemory TransferBufferMemory = _Device.AllocateMemory(_ImageSize, hostMemory);

            _TransferBuffer.BindMemory(TransferBufferMemory, 0);
            _TransferBufferPtr = TransferBufferMemory.Map(0, _ImageSize, VkMemoryMapFlag.NONE);


            VkImageView imageView = _FrameBufferColor.CreateImageView(VkImageViewType.VK_IMAGE_VIEW_TYPE_2D, new VkImageSubresourceRange()
            {
                aspectMask = VkImageAspectFlag.VK_IMAGE_ASPECT_COLOR_BIT, baseArrayLayer = 0, baseMipLevel = 0, layerCount = 1, levelCount = 1
            });


            VkAttachmentDescription colorAttachment = new VkAttachmentDescription();

            colorAttachment.format         = _FrameBufferColor.Format;
            colorAttachment.samples        = VkSampleCountFlag.VK_SAMPLE_COUNT_1;
            colorAttachment.loadOp         = VkAttachmentLoadOp.VK_ATTACHMENT_LOAD_OP_CLEAR;
            colorAttachment.storeOp        = VkAttachmentStoreOp.VK_ATTACHMENT_STORE_OP_STORE;
            colorAttachment.stencilLoadOp  = VkAttachmentLoadOp.VK_ATTACHMENT_LOAD_OP_DONT_CARE;
            colorAttachment.stencilStoreOp = VkAttachmentStoreOp.VK_ATTACHMENT_STORE_OP_DONT_CARE;
            colorAttachment.initialLayout  = VkImageLayout.VK_IMAGE_LAYOUT_UNDEFINED;
            colorAttachment.finalLayout    = VkImageLayout.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

            VkAttachmentReference colorAttachmentReference = new VkAttachmentReference();

            colorAttachmentReference.attachment = 0;
            colorAttachmentReference.layout     = VkImageLayout.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

            VkSubpassDescription subpass = new VkSubpassDescription();

            subpass.pipelineBindPoint      = VkPipelineBindPoint.VK_PIPELINE_BIND_POINT_GRAPHICS;
            subpass.colorAttachments       = new VkAttachmentReference[] { colorAttachmentReference };
            subpass.depthStencilAttachment = null;
            subpass.inputAttachments       = null;
            subpass.preserveAttachments    = null;
            subpass.resolveAttachments     = null;

            VkSubpassDependency dependency = new VkSubpassDependency();

            dependency.srcSubpass    = VkSubpassDependency.VK_SUBPASS_EXTERNAL;
            dependency.dstSubpass    = 0;
            dependency.srcStageMask  = VkPipelineStageFlag.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
            dependency.srcAccessMask = 0;
            dependency.dstStageMask  = VkPipelineStageFlag.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT;
            dependency.dstAccessMask = VkAccessFlag.VK_ACCESS_COLOR_ATTACHMENT_READ | VkAccessFlag.VK_ACCESS_COLOR_ATTACHMENT_WRITE;

            _RenderPass = _Device.CreateRenderPass(new VkAttachmentDescription[] { colorAttachment },
                                                   new VkSubpassDescription[] { subpass },
                                                   new VkSubpassDependency[] { dependency });

            _Framebuffer = _Device.CreateFramebuffer(_RenderPass, new VkImageView[] { imageView }, (uint)Width, (uint)Height, 1);
        }
Beispiel #3
0
        public ClearImage()
        {
            InitializeComponent();
            _Bitmap = new Bitmap(640, 480);

            // Create the VUlkan instance that we will use for this app
            _Instance = new VkInstance("ClearImage - Sample", 1, "Ratchet", 1);

            // Now lets walk all physical device and find the first one that supports graphics queue
            foreach (VkPhysicalDevice physicalDevice in _Instance.vkEnumeratePhysicalDevices())
            {
                foreach (VkQueueFamilyProperties queueFamilly in physicalDevice.QueueFamilies)
                {
                    if ((queueFamilly.queueFlags & VkQueueFlags.VK_QUEUE_GRAPHICS) != 0)
                    {
                        // We have a physical device that supports graphics queue, we can now create a Device on it
                        // with one queue and use it as our main device for this sample
                        _Device = physicalDevice.CreateDevice(new VkDeviceQueueCreateInfo[] { new VkDeviceQueueCreateInfo()
                                                                                              {
                                                                                                  queueCount = 1, queueFamily = queueFamilly, queuePriorities = new float[] { 1.0f }
                                                                                              } });

                        // Ok now lets grab the graphics queue back. Technically there should only be one
                        // But just to be clean we do an iteration and look for the queue that matches our
                        // need
                        foreach (VkQueue queue in _Device.Queues)
                        {
                            if (queue.Family.queueFlags == queueFamilly.queueFlags)
                            {
                                _Queue = queue;
                                break;
                            }
                        }

                        // Now it is time to create the image that we will fill wih the solid color
                        _Image = _Device.CreateImage(
                            VkImageCreateFlag.NONE,
                            VkFormat.VK_FORMAT_B8G8R8A8_SRGB,
                            _Bitmap.Width, _Bitmap.Height,
                            1, 1,
                            VkSampleCountFlag.VK_SAMPLE_COUNT_1,
                            VkImageTiling.VK_IMAGE_TILING_LINEAR,
                            VkImageUsageFlag.VK_IMAGE_USAGE_TRANSFER_SRC | VkImageUsageFlag.VK_IMAGE_USAGE_TRANSFER_DST,
                            VkSharingMode.VK_SHARING_MODE_EXCLUSIVE,
                            null,
                            VkImageLayout.VK_IMAGE_LAYOUT_GENERAL);

                        // We will back this image with Host Accessible Memomy so we can map it an copy
                        // the content from the Host.
                        // To do so we need to find the right memory type first.
                        VkMemoryType HostMemory = new VkMemoryType();
                        foreach (VkMemoryType memoryType in _Image.MemoryRequirements.memoryTypes)
                        {
                            // Pick the first memory type that can be mapped into host memory
                            if ((memoryType.propertyFlags & VkMemoryPropertyFlags.VK_MEMORY_PROPERTY_HOST_VISIBLE) != 0)
                            {
                                HostMemory = memoryType;
                                break;
                            }
                        }

                        // Allocate the backing memory for this image
                        VkDeviceMemory Memory = _Device.AllocateMemory(_Image.MemoryRequirements.size, HostMemory);
                        _Image.BindMemory(Memory, 0);
                        // Create the CPU mapping
                        _ImagePtr = Memory.Map(0, _Image.MemoryRequirements.size, VkMemoryMapFlag.NONE);

                        // Now we need to create a command buffer and we will fill it with a single command:
                        //   Fill the image with the color (0.1f, 0.75f, 1.0f, 1.0f) which is a Sky blue.
                        VkCommandPool Pool = _Device.CreateCommandPool(VkCommandPoolCreateFlag.NONE, _Queue.Family);
                        _CommandBuffer = Pool.AllocateCommandBuffer(VkCommandBufferLevel.VK_COMMAND_BUFFER_LEVEL_PRIMARY);
                        _CommandBuffer.Begin(VkCommandBufferUsageFlag.NONE);
                        _CommandBuffer.CmdClearColorImage(
                            _Image,
                            VkImageLayout.VK_IMAGE_LAYOUT_GENERAL,
                            0.1f, 0.75f, 1.0f, 1.0f,
                            new VkImageSubresourceRange[]
                        {
                            new VkImageSubresourceRange()
                            {
                                aspectMask     = VkImageAspectFlag.VK_IMAGE_ASPECT_COLOR_BIT,
                                baseArrayLayer = 0,
                                baseMipLevel   = 0,
                                layerCount     = 1,
                                levelCount     = 1
                            }
                        });
                        _CommandBuffer.End();

                        // Finally we will need a fence for our submission in order to wait on it
                        _Fence = _Device.CreateFence(VkFenceCreateFlag.NONE);

                        break;
                    }
                }
            }
        }