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; }
public VkResult WaitForFences( [FromProperty("this")] GenDevice device, [CountFor("fences")] int fenceCount, [IsArray] GenFence *pFences, VkBool32 waitAll, ulong timeout) => default(VkResult);
public VkResult WaitForFences( [FromProperty("this")] GenDevice device, [CountFor("fences")] int fenceCount, [IsArray] GenFence* pFences, VkBool32 waitAll, ulong timeout) => default(VkResult);
public bool GetPresentIsSupported(uint qFamilyIndex, VkSurfaceKHR surf) { VkBool32 isSupported = false; vkGetPhysicalDeviceSurfaceSupportKHR(phy, qFamilyIndex, surf, out isSupported); return(isSupported); }
public VkDisplayNativeHdrSurfaceCapabilitiesAMD( VkBool32 localDimmingSupport = default ) { sType = TYPE; pNext = null; LocalDimmingSupport = localDimmingSupport; }
public VkPhysicalDeviceCoherentMemoryFeaturesAMD( VkBool32 deviceCoherentMemory = default ) { sType = TYPE; pNext = null; DeviceCoherentMemory = deviceCoherentMemory; }
public VkTextureLODGatherFormatPropertiesAMD( VkBool32 supportsTextureGatherLODBiasAMD = default ) { sType = TYPE; pNext = null; SupportsTextureGatherLODBiasAMD = supportsTextureGatherLODBiasAMD; }
public VkSwapchainDisplayNativeHdrCreateInfoAMD( VkBool32 localDimmingEnable = default ) { sType = TYPE; pNext = null; LocalDimmingEnable = localDimmingEnable; }
public VkPerformanceOverrideInfoINTEL( VkPerformanceOverrideTypeINTEL type = default, VkBool32 enable = default, ulong parameter = default ) { sType = TYPE; pNext = null; Type = type; Enable = enable; Parameter = parameter; }
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); }
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(); } }
// 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; }
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)); } }
public static VkResult vkWaitForFences(VkDevice device, VkFence fence, VkBool32 waitAll, ulong timeout) { return(vkWaitForFences(device, 1, &fence, waitAll, timeout)); }
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."); }
// 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; }