Ejemplo n.º 1
0
        public unsafe QueueFamilyIndices(VkPhysicalDevice device, VkSurfaceKHR surface)
        {
            int graphicsIndex = -1;
            int presentIndex  = -1;

            uint queueFamilyCount = 0;

            VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, null);
            VkQueueFamilyProperties *queueFamilies = stackalloc VkQueueFamilyProperties[(int)queueFamilyCount];

            VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies);

            for (int i = 0; i < queueFamilyCount; i++)
            {
                var q = queueFamilies[i];

                if (q.queueCount > 0 && (q.queueFlags & VkQueueFlagBits.VK_QUEUE_GRAPHICS_BIT) != 0)
                {
                    graphicsIndex = i;
                }

                VkBool32 presentSupported = false;
                VkResult result           = VulkanNative.vkGetPhysicalDeviceSurfaceSupportKHR(device, (uint)i, surface, &presentSupported);
                Helpers.CheckErrors(result);
                if (presentIndex < 0 && q.queueCount > 0 && presentSupported)
                {
                    presentIndex = i;
                }
            }

            GraphicsFamily = graphicsIndex;
            PresentFamily  = presentIndex;
        }
Ejemplo n.º 2
0
 public VkResult WaitForFences(
     [FromProperty("this")] GenDevice device,
     [CountFor("fences")] int fenceCount,
     [IsArray] GenFence *pFences,
     VkBool32 waitAll,
     ulong timeout)
 => default(VkResult);
Ejemplo n.º 3
0
 public VkResult WaitForFences(
     [FromProperty("this")] GenDevice device,
     [CountFor("fences")] int fenceCount,
     [IsArray] GenFence* pFences,
     VkBool32 waitAll,
     ulong timeout)
     => default(VkResult);
Ejemplo n.º 4
0
        public bool GetPresentIsSupported(uint qFamilyIndex, VkSurfaceKHR surf)
        {
            VkBool32 isSupported = false;

            vkGetPhysicalDeviceSurfaceSupportKHR(phy, qFamilyIndex, surf, out isSupported);
            return(isSupported);
        }
Ejemplo n.º 5
0
 public VkDisplayNativeHdrSurfaceCapabilitiesAMD(
     VkBool32 localDimmingSupport = default
     )
 {
     sType = TYPE;
     pNext = null;
     LocalDimmingSupport = localDimmingSupport;
 }
Ejemplo n.º 6
0
 public VkPhysicalDeviceCoherentMemoryFeaturesAMD(
     VkBool32 deviceCoherentMemory = default
     )
 {
     sType = TYPE;
     pNext = null;
     DeviceCoherentMemory = deviceCoherentMemory;
 }
Ejemplo n.º 7
0
 public VkTextureLODGatherFormatPropertiesAMD(
     VkBool32 supportsTextureGatherLODBiasAMD = default
     )
 {
     sType = TYPE;
     pNext = null;
     SupportsTextureGatherLODBiasAMD = supportsTextureGatherLODBiasAMD;
 }
Ejemplo n.º 8
0
 public VkSwapchainDisplayNativeHdrCreateInfoAMD(
     VkBool32 localDimmingEnable = default
     )
 {
     sType = TYPE;
     pNext = null;
     LocalDimmingEnable = localDimmingEnable;
 }
Ejemplo n.º 9
0
 public VkPerformanceOverrideInfoINTEL(
     VkPerformanceOverrideTypeINTEL type = default,
     VkBool32 enable = default,
     ulong parameter = default
     )
 {
     sType     = TYPE;
     pNext     = null;
     Type      = type;
     Enable    = enable;
     Parameter = parameter;
 }
Ejemplo n.º 10
0
        private QueueFamilyIndices FindQueueFamilies(VkPhysicalDevice physicalDevice)
        {
            QueueFamilyIndices indices = default;

            uint queueFamilyCount = 0;

            VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, null);

            VkQueueFamilyProperties *queueFamilies = stackalloc VkQueueFamilyProperties[(int)queueFamilyCount];

            VulkanNative.vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilies);

            for (uint i = 0; i < queueFamilyCount; i++)
            {
                var queueFamily = queueFamilies[i];
                if ((queueFamily.queueFlags & VkQueueFlags.VK_QUEUE_GRAPHICS_BIT) != 0)
                {
                    indices.graphicsFamily = i;
                }

                VkBool32 presentSupport = false;
                Helpers.CheckErrors(VulkanNative.vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, this.surface, &presentSupport));

                if (presentSupport)
                {
                    indices.presentFamily = i;
                }

                if (indices.IsComplete())
                {
                    break;
                }
            }

            return(indices);
        }
Ejemplo n.º 11
0
        private void ConvertMinFilter(TextureFilter filter, out VkFilter minFilter, out VkFilter magFilter, out VkSamplerMipmapMode mipmapMode, out VkBool32 enableComparison, out VkBool32 enableAnisotropy)
        {
            minFilter        = magFilter = VkFilter.Nearest;
            mipmapMode       = VkSamplerMipmapMode.Nearest;
            enableComparison = false;
            enableAnisotropy = false;

            switch (filter)
            {
            // Mip point
            case TextureFilter.Point:
                break;

            case TextureFilter.MinLinearMagMipPoint:
                minFilter = VkFilter.Linear;
                break;

            case TextureFilter.MinPointMagLinearMipPoint:
                magFilter = VkFilter.Linear;
                break;

            case TextureFilter.MinMagLinearMipPoint:
                minFilter = VkFilter.Linear;
                magFilter = VkFilter.Linear;
                break;

            // Mip linear
            case TextureFilter.MinMagPointMipLinear:
                mipmapMode = VkSamplerMipmapMode.Linear;
                break;

            case TextureFilter.MinLinearMagPointMipLinear:
                mipmapMode = VkSamplerMipmapMode.Linear;
                minFilter  = VkFilter.Linear;
                break;

            case TextureFilter.MinPointMagMipLinear:
                mipmapMode = VkSamplerMipmapMode.Linear;
                magFilter  = VkFilter.Linear;
                break;

            case TextureFilter.Linear:
                mipmapMode = VkSamplerMipmapMode.Linear;
                minFilter  = VkFilter.Linear;
                magFilter  = VkFilter.Linear;
                break;

            case TextureFilter.Anisotropic:
                enableAnisotropy = true;
                mipmapMode       = VkSamplerMipmapMode.Linear;
                minFilter        = VkFilter.Linear;
                magFilter        = VkFilter.Linear;
                break;

            // Comparison mip point
            case TextureFilter.ComparisonPoint:
                enableComparison = true;
                break;

            case TextureFilter.ComparisonMinLinearMagMipPoint:
                enableComparison = true;
                minFilter        = VkFilter.Linear;
                break;

            case TextureFilter.ComparisonMinPointMagLinearMipPoint:
                enableComparison = true;
                magFilter        = VkFilter.Linear;
                break;

            case TextureFilter.ComparisonMinMagLinearMipPoint:
                enableComparison = true;
                minFilter        = VkFilter.Linear;
                magFilter        = VkFilter.Linear;
                break;

            // Comparison mip linear
            case TextureFilter.ComparisonMinMagPointMipLinear:
                enableComparison = true;
                mipmapMode       = VkSamplerMipmapMode.Linear;
                break;

            case TextureFilter.ComparisonMinLinearMagPointMipLinear:
                enableComparison = true;
                mipmapMode       = VkSamplerMipmapMode.Linear;
                minFilter        = VkFilter.Linear;
                break;

            case TextureFilter.ComparisonMinPointMagMipLinear:
                enableComparison = true;
                mipmapMode       = VkSamplerMipmapMode.Linear;
                magFilter        = VkFilter.Linear;
                break;

            case TextureFilter.ComparisonLinear:
                enableComparison = true;
                mipmapMode       = VkSamplerMipmapMode.Linear;
                minFilter        = VkFilter.Linear;
                magFilter        = VkFilter.Linear;
                break;

            case TextureFilter.ComparisonAnisotropic:
                enableComparison = true;
                enableAnisotropy = true;
                mipmapMode       = VkSamplerMipmapMode.Linear;
                minFilter        = VkFilter.Linear;
                magFilter        = VkFilter.Linear;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Ejemplo n.º 12
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
            VkImageCreateInfo image = Initializers.imageCreateInfo();

            image.imageType     = VK_IMAGE_TYPE_2D;
            image.format        = FB_COLOR_FORMAT;
            image.extent.width  = (uint)offscreenPass.width;
            image.extent.height = (uint)offscreenPass.height;
            image.extent.depth  = 1;
            image.mipLevels     = 1;
            image.arrayLayers   = 1;
            image.samples       = VK_SAMPLE_COUNT_1_BIT;
            image.tiling        = VK_IMAGE_TILING_OPTIMAL;
            // We will sample directly from the color attachment
            image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;

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

            Util.CheckResult(vkCreateImage(device, &image, null, out offscreenPass.color.image));
            vkGetImageMemoryRequirements(device, offscreenPass.color.image, &memReqs);
            memAlloc.allocationSize  = memReqs.size;
            memAlloc.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
            Util.CheckResult(vkAllocateMemory(device, &memAlloc, null, out offscreenPass.color.mem));
            Util.CheckResult(vkBindImageMemory(device, offscreenPass.color.image, offscreenPass.color.mem, 0));

            VkImageViewCreateInfo colorImageView = Initializers.imageViewCreateInfo();

            colorImageView.viewType                        = VK_IMAGE_VIEW_TYPE_2D;
            colorImageView.format                          = FB_COLOR_FORMAT;
            colorImageView.subresourceRange                = new VkImageSubresourceRange();
            colorImageView.subresourceRange.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
            colorImageView.subresourceRange.baseMipLevel   = 0;
            colorImageView.subresourceRange.levelCount     = 1;
            colorImageView.subresourceRange.baseArrayLayer = 0;
            colorImageView.subresourceRange.layerCount     = 1;
            colorImageView.image = offscreenPass.color.image;
            Util.CheckResult(vkCreateImageView(device, &colorImageView, null, out offscreenPass.color.view));

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

            samplerInfo.magFilter     = VK_FILTER_LINEAR;
            samplerInfo.minFilter     = VK_FILTER_LINEAR;
            samplerInfo.mipmapMode    = VK_SAMPLER_MIPMAP_MODE_LINEAR;
            samplerInfo.addressModeU  = 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   = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
            Util.CheckResult(vkCreateSampler(device, &samplerInfo, null, out offscreenPass.sampler));

            // Depth stencil attachment
            image.format = fbDepthFormat;
            image.usage  = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;

            Util.CheckResult(vkCreateImage(device, &image, null, out offscreenPass.depth.image));
            vkGetImageMemoryRequirements(device, offscreenPass.depth.image, &memReqs);
            memAlloc.allocationSize  = memReqs.size;
            memAlloc.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
            Util.CheckResult(vkAllocateMemory(device, &memAlloc, null, out offscreenPass.depth.mem));
            Util.CheckResult(vkBindImageMemory(device, offscreenPass.depth.image, offscreenPass.depth.mem, 0));

            VkImageViewCreateInfo depthStencilView = Initializers.imageViewCreateInfo();

            depthStencilView.viewType                        = VK_IMAGE_VIEW_TYPE_2D;
            depthStencilView.format                          = fbDepthFormat;
            depthStencilView.flags                           = 0;
            depthStencilView.subresourceRange                = new VkImageSubresourceRange();
            depthStencilView.subresourceRange.aspectMask     = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
            depthStencilView.subresourceRange.baseMipLevel   = 0;
            depthStencilView.subresourceRange.levelCount     = 1;
            depthStencilView.subresourceRange.baseArrayLayer = 0;
            depthStencilView.subresourceRange.layerCount     = 1;
            depthStencilView.image                           = offscreenPass.depth.image;
            Util.CheckResult(vkCreateImageView(device, &depthStencilView, null, out offscreenPass.depth.view));

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

            FixedArray2 <VkAttachmentDescription> attchmentDescriptions = new FixedArray2 <VkAttachmentDescription>();

            // Color attachment
            attchmentDescriptions.First.format         = FB_COLOR_FORMAT;
            attchmentDescriptions.First.samples        = VK_SAMPLE_COUNT_1_BIT;
            attchmentDescriptions.First.loadOp         = VK_ATTACHMENT_LOAD_OP_CLEAR;
            attchmentDescriptions.First.storeOp        = VK_ATTACHMENT_STORE_OP_STORE;
            attchmentDescriptions.First.stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
            attchmentDescriptions.First.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
            attchmentDescriptions.First.initialLayout  = VK_IMAGE_LAYOUT_UNDEFINED;
            attchmentDescriptions.First.finalLayout    = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
            // Depth attachment
            attchmentDescriptions.Second.format         = fbDepthFormat;
            attchmentDescriptions.Second.samples        = VK_SAMPLE_COUNT_1_BIT;
            attchmentDescriptions.Second.loadOp         = VK_ATTACHMENT_LOAD_OP_CLEAR;
            attchmentDescriptions.Second.storeOp        = VK_ATTACHMENT_STORE_OP_DONT_CARE;
            attchmentDescriptions.Second.stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
            attchmentDescriptions.Second.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
            attchmentDescriptions.Second.initialLayout  = VK_IMAGE_LAYOUT_UNDEFINED;
            attchmentDescriptions.Second.finalLayout    = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

            VkAttachmentReference colorReference = new VkAttachmentReference {
                attachment = 0, layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
            };
            VkAttachmentReference depthReference = new VkAttachmentReference {
                attachment = 1, layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
            };

            VkSubpassDescription subpassDescription = new VkSubpassDescription();

            subpassDescription.pipelineBindPoint       = VK_PIPELINE_BIND_POINT_GRAPHICS;
            subpassDescription.colorAttachmentCount    = 1;
            subpassDescription.pColorAttachments       = &colorReference;
            subpassDescription.pDepthStencilAttachment = &depthReference;

            // Use subpass dependencies for layout transitions
            FixedArray2 <VkSubpassDependency> dependencies = new FixedArray2 <VkSubpassDependency>();

            dependencies.First.srcSubpass      = VK_SUBPASS_EXTERNAL;
            dependencies.First.dstSubpass      = 0;
            dependencies.First.srcStageMask    = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
            dependencies.First.dstStageMask    = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
            dependencies.First.srcAccessMask   = VK_ACCESS_MEMORY_READ_BIT;
            dependencies.First.dstAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
            dependencies.First.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

            dependencies.Second.srcSubpass      = 0;
            dependencies.Second.dstSubpass      = VK_SUBPASS_EXTERNAL;
            dependencies.Second.srcStageMask    = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
            dependencies.Second.dstStageMask    = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
            dependencies.Second.srcAccessMask   = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
            dependencies.Second.dstAccessMask   = VK_ACCESS_MEMORY_READ_BIT;
            dependencies.Second.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

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

            renderPassInfo.attachmentCount = attchmentDescriptions.Count;
            renderPassInfo.pAttachments    = &attchmentDescriptions.First;
            renderPassInfo.subpassCount    = 1;
            renderPassInfo.pSubpasses      = &subpassDescription;
            renderPassInfo.dependencyCount = dependencies.Count;
            renderPassInfo.pDependencies   = &dependencies.First;

            Util.CheckResult(vkCreateRenderPass(device, &renderPassInfo, null, out offscreenPass.renderPass));

            FixedArray2 <VkImageView> attachments = new FixedArray2 <VkImageView>(offscreenPass.color.view, offscreenPass.depth.view);

            VkFramebufferCreateInfo fbufCreateInfo = Initializers.framebufferCreateInfo();

            fbufCreateInfo.renderPass      = offscreenPass.renderPass;
            fbufCreateInfo.attachmentCount = 2;
            fbufCreateInfo.pAttachments    = &attachments.First;
            fbufCreateInfo.width           = (uint)offscreenPass.width;
            fbufCreateInfo.height          = (uint)offscreenPass.height;
            fbufCreateInfo.layers          = 1;

            Util.CheckResult(vkCreateFramebuffer(device, &fbufCreateInfo, null, out offscreenPass.frameBuffer));

            // Fill a descriptor for later use in a descriptor set
            offscreenPass.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
            offscreenPass.descriptor.imageView   = offscreenPass.color.view;
            offscreenPass.descriptor.sampler     = offscreenPass.sampler;
        }
Ejemplo n.º 13
0
 public static VkResult vkWaitForFences(VkDevice device, ReadOnlySpan <VkFence> fences, VkBool32 waitAll, ulong timeout)
 {
     fixed(VkFence *fencesPtr = fences)
     {
         return(vkWaitForFences(device, fences.Length, fencesPtr, waitAll, timeout));
     }
 }
Ejemplo n.º 14
0
 public static VkResult vkWaitForFences(VkDevice device, VkFence fence, VkBool32 waitAll, ulong timeout)
 {
     return(vkWaitForFences(device, 1, &fence, waitAll, timeout));
 }
Ejemplo n.º 15
0
        static VkPhysicalDevice PickPhysicalDevice(VkInstance instance, VkSurfaceKHR surface, out uint queueFamilyIndex)
        {
            queueFamilyIndex = 0;
            uint deviceCount = 0;

            vkEnumeratePhysicalDevices(instance, &deviceCount, null);
            Console.WriteLine($"There are {deviceCount} devices available.");
            VkPhysicalDevice[] devices = new VkPhysicalDevice[deviceCount];
            if (deviceCount <= 0)
                return(VkPhysicalDevice.Null);

            fixed(VkPhysicalDevice *ptr = &devices[0])
            vkEnumeratePhysicalDevices(instance, &deviceCount, ptr);

            VkPhysicalDeviceProperties props = new VkPhysicalDeviceProperties();


            for (int i = 0; i < deviceCount; i++)
            {
                bool badGpu           = true;
                bool onlyPickDiscrete = true;

                vkGetPhysicalDeviceProperties(devices[i], &props);

                uint familyQueueCount = 0;
                vkGetPhysicalDeviceQueueFamilyProperties(devices[i], &familyQueueCount, null);
                VkQueueFamilyProperties[] famProps = new VkQueueFamilyProperties[familyQueueCount];

                fixed(VkQueueFamilyProperties *ptr = famProps)
                vkGetPhysicalDeviceQueueFamilyProperties(devices[i], &familyQueueCount, ptr);

                VkPhysicalDeviceFeatures deviceFeatures;
                vkGetPhysicalDeviceFeatures(devices[i], &deviceFeatures);
                if (deviceFeatures.samplerAnisotropy == VkBool32.False)
                {
                    continue;
                }

                for (uint k = 0; k < familyQueueCount; k++)
                {
                    if ((int)(famProps[k].queueFlags & VkQueueFlags.Graphics) <= 0)
                    {
                        continue;
                    }
                    VkBool32 supported = VkBool32.False;
                    Assert(vkGetPhysicalDeviceSurfaceSupportKHR(devices[i], k, surface, &supported));
                    if (supported == VkBool32.False)
                    {
                        continue;
                    }

                    /*fixed (VkPhysicalDevice* ptr = &(devices[i]))
                     *  if (!GLFW.Vulkan.GetPhysicalDevicePresentationSupport((IntPtr)(&instance), (IntPtr)ptr, k))//Throws exception
                     *  {
                     *      continue;
                     *  }*/
                    if (onlyPickDiscrete && !(props.deviceType == VkPhysicalDeviceType.DiscreteGpu))
                    {
                        continue;
                    }

                    queueFamilyIndex = k;
                    badGpu           = false;
                }



                //Here we pick if its acceptable
                if (badGpu)
                {
                    continue;
                }


                Console.WriteLine($"Picking GPU: {Marshal.PtrToStringUTF8((IntPtr)props.deviceName)}");
                return(devices[i]);
            }

            throw new System.Exception("There was no GPU that filled our needs.");
        }
Ejemplo n.º 16
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;
        }