void preparePipelines() { VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = Initializers.pipelineInputAssemblyStateCreateInfo( VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); VkPipelineRasterizationStateCreateInfo rasterizationState = Initializers.pipelineRasterizationStateCreateInfo( VK_POLYGON_MODE_FILL, VK_CULL_MODE_FRONT_BIT, VK_FRONT_FACE_CLOCKWISE, 0); VkPipelineColorBlendAttachmentState blendAttachmentState = Initializers.pipelineColorBlendAttachmentState( 0xf, VK_FALSE); VkPipelineColorBlendStateCreateInfo colorBlendState = Initializers.pipelineColorBlendStateCreateInfo( 1, &blendAttachmentState); VkPipelineDepthStencilStateCreateInfo depthStencilState = Initializers.pipelineDepthStencilStateCreateInfo( VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); VkPipelineViewportStateCreateInfo viewportState = Initializers.pipelineViewportStateCreateInfo(1, 1, 0); VkPipelineMultisampleStateCreateInfo multisampleState = Initializers.pipelineMultisampleStateCreateInfo( VkSampleCountFlags.Count1, 0); FixedArray2<VkDynamicState> dynamicStateEnables = new FixedArray2<VkDynamicState>( VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR); VkPipelineDynamicStateCreateInfo dynamicState = Initializers.pipelineDynamicStateCreateInfo( &dynamicStateEnables.First, dynamicStateEnables.Count, 0); // Solid rendering pipeline // Load shaders FixedArray2<VkPipelineShaderStageCreateInfo> shaderStages = new FixedArray2<VkPipelineShaderStageCreateInfo>( loadShader(getAssetPath() + "shaders/offscreen/quad.vert.spv", VK_SHADER_STAGE_VERTEX_BIT), loadShader(getAssetPath() + "shaders/offscreen/quad.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT)); VkGraphicsPipelineCreateInfo pipelineCreateInfo = Initializers.pipelineCreateInfo( pipelineLayouts_textured, renderPass, 0); var vis = vertices_inputState; pipelineCreateInfo.pVertexInputState = &vis; pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState; pipelineCreateInfo.pRasterizationState = &rasterizationState; pipelineCreateInfo.pColorBlendState = &colorBlendState; pipelineCreateInfo.pMultisampleState = &multisampleState; pipelineCreateInfo.pViewportState = &viewportState; pipelineCreateInfo.pDepthStencilState = &depthStencilState; pipelineCreateInfo.pDynamicState = &dynamicState; pipelineCreateInfo.stageCount = shaderStages.Count; pipelineCreateInfo.pStages = &shaderStages.First; Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_debug)); // Mirror shaderStages.First = loadShader(getAssetPath() + "shaders/offscreen/mirror.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages.Second = loadShader(getAssetPath() + "shaders/offscreen/mirror.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); rasterizationState.cullMode = VK_CULL_MODE_NONE; Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_mirror)); // Flip culling rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT; // Phong shading pipelines pipelineCreateInfo.layout = pipelineLayouts_shaded; // Scene shaderStages.First = loadShader(getAssetPath() + "shaders/offscreen/phong.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages.Second = loadShader(getAssetPath() + "shaders/offscreen/phong.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_shaded)); // Offscreen // Flip culling rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT; pipelineCreateInfo.renderPass = offscreenPass.renderPass; Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_shadedOffscreen)); }
protected override void buildCommandBuffers() { VkCommandBufferBeginInfo cmdBufInfo = Initializers.commandBufferBeginInfo(); FixedArray2<VkClearValue> clearValues = new FixedArray2<VkClearValue>(); clearValues.First.color = defaultClearColor; clearValues.Second.depthStencil = new VkClearDepthStencilValue { depth = 1.0f, stencil = 0 }; VkRenderPassBeginInfo renderPassBeginInfo = Initializers.renderPassBeginInfo(); renderPassBeginInfo.renderPass = renderPass; renderPassBeginInfo.renderArea.offset.x = 0; renderPassBeginInfo.renderArea.offset.y = 0; renderPassBeginInfo.renderArea.extent.width = width; renderPassBeginInfo.renderArea.extent.height = height; renderPassBeginInfo.clearValueCount = 2; renderPassBeginInfo.pClearValues = &clearValues.First; for (int i = 0; i < drawCmdBuffers.Count; ++i) { // Set target frame buffer renderPassBeginInfo.framebuffer = frameBuffers[i]; Util.CheckResult(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); VkViewport viewport = Initializers.viewport((float)width, (float)height, 0.0f, 1.0f); vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); VkRect2D scissor = Initializers.rect2D(width, height, 0, 0); vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); ulong offsets = 0; if (debugDisplay) { vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts_textured, 0, 1, ref descriptorSets_debugQuad, 0, null); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines_debug); vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, ref models_quad.vertices.buffer, &offsets); vkCmdBindIndexBuffer(drawCmdBuffers[i], models_quad.indices.buffer, 0, VK_INDEX_TYPE_UINT32); vkCmdDrawIndexed(drawCmdBuffers[i], models_quad.indexCount, 1, 0, 0, 0); } // Scene vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines_debug); // Reflection plane vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts_textured, 0, 1, ref descriptorSets_mirror, 0, null); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines_mirror); vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, ref models_plane.vertices.buffer, &offsets); vkCmdBindIndexBuffer(drawCmdBuffers[i], models_plane.indices.buffer, 0, VK_INDEX_TYPE_UINT32); vkCmdDrawIndexed(drawCmdBuffers[i], models_plane.indexCount, 1, 0, 0, 0); // Model vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts_shaded, 0, 1, ref descriptorSets_model, 0, null); vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines_shaded); vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, ref models_example.vertices.buffer, &offsets); vkCmdBindIndexBuffer(drawCmdBuffers[i], models_example.indices.buffer, 0, VK_INDEX_TYPE_UINT32); vkCmdDrawIndexed(drawCmdBuffers[i], models_example.indexCount, 1, 0, 0, 0); vkCmdEndRenderPass(drawCmdBuffers[i]); Util.CheckResult(vkEndCommandBuffer(drawCmdBuffers[i])); } }
void setupDescriptorSet() { var dsl = descriptorSetLayouts_textured; // Mirror plane descriptor set VkDescriptorSetAllocateInfo allocInfo = Initializers.descriptorSetAllocateInfo( descriptorPool, &dsl, 1); Util.CheckResult(vkAllocateDescriptorSets(device, &allocInfo, out descriptorSets_mirror)); var descriptor0 = uniformBuffers_vsMirror.descriptor; var descriptor1 = offscreenPass.descriptor; var descriptor2 = textures_colorMap.descriptor; FixedArray3<VkWriteDescriptorSet> writeDescriptorSets = new FixedArray3<VkWriteDescriptorSet>( // Binding 0 : Vertex shader uniform buffer Initializers.writeDescriptorSet( descriptorSets_mirror, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &descriptor0), // Binding 1 : Fragment shader texture sampler Initializers.writeDescriptorSet( descriptorSets_mirror, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &descriptor1), // Binding 2 : Fragment shader texture sampler Initializers.writeDescriptorSet( descriptorSets_mirror, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, &descriptor2)); vkUpdateDescriptorSets(device, writeDescriptorSets.Count, &writeDescriptorSets.First, 0, null); // Debug quad Util.CheckResult(vkAllocateDescriptorSets(device, &allocInfo, out descriptorSets_debugQuad)); var descriptor3 = uniformBuffers_vsDebugQuad.descriptor; var descriptor4 = offscreenPass.descriptor; FixedArray2<VkWriteDescriptorSet> debugQuadWriteDescriptorSets = new FixedArray2<VkWriteDescriptorSet>( // Binding 0 : Vertex shader uniform buffer Initializers.writeDescriptorSet( descriptorSets_debugQuad, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &descriptor3), // Binding 1 : Fragment shader texture sampler Initializers.writeDescriptorSet( descriptorSets_debugQuad, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, &descriptor4)); vkUpdateDescriptorSets(device, debugQuadWriteDescriptorSets.Count, &debugQuadWriteDescriptorSets.First, 0, null); var dsls_shaded = descriptorSetLayouts_shaded; // Shaded descriptor sets allocInfo.pSetLayouts = &dsls_shaded; // Model // No texture Util.CheckResult(vkAllocateDescriptorSets(device, &allocInfo, out descriptorSets_model)); var descriptor5 = uniformBuffers_vsShared.descriptor; VkWriteDescriptorSet modelWriteDescriptorSets = // Binding 0 : Vertex shader uniform buffer Initializers.writeDescriptorSet( descriptorSets_model, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &descriptor5); vkUpdateDescriptorSets(device, 1, &modelWriteDescriptorSets, 0, null); // Offscreen Util.CheckResult(vkAllocateDescriptorSets(device, &allocInfo, out descriptorSets_offscreen)); var descriptor6 = uniformBuffers_vsOffScreen.descriptor; VkWriteDescriptorSet offScreenWriteDescriptorSets = // Binding 0 : Vertex shader uniform buffer Initializers.writeDescriptorSet( descriptorSets_offscreen, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &descriptor6); vkUpdateDescriptorSets(device, 1, &offScreenWriteDescriptorSets, 0, null); }
// Setup the offscreen framebuffer for rendering the mirrored scene // The color attachment of this framebuffer will then be used to sample from 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 = VkSampleCountFlags.Count1; 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(VkImageAspectFlags.Color); 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 = VkSampleCountFlags.Count1; 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 = VkSampleCountFlags.Count1; 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; }
private void CreatePipelineCache() { VkPipelineCacheCreateInfo pipelineCacheCreateInfo = VkPipelineCacheCreateInfo.New(); Util.CheckResult(vkCreatePipelineCache(Device, ref pipelineCacheCreateInfo, null, out _pipelineCache)); }
protected virtual void SetupRenderPass() { using (NativeList <VkAttachmentDescription> attachments = new NativeList <VkAttachmentDescription>()) { attachments.Count = 2; // Color attachment attachments[0] = new VkAttachmentDescription(); attachments[0].format = Swapchain.ColorFormat; attachments[0].samples = VkSampleCountFlags._1; attachments[0].loadOp = VkAttachmentLoadOp.Clear; attachments[0].storeOp = VkAttachmentStoreOp.Store; attachments[0].stencilLoadOp = VkAttachmentLoadOp.DontCare; attachments[0].stencilStoreOp = VkAttachmentStoreOp.DontCare; attachments[0].initialLayout = VkImageLayout.Undefined; attachments[0].finalLayout = VkImageLayout.PresentSrc; // Depth attachment attachments[1] = new VkAttachmentDescription(); attachments[1].format = DepthFormat; attachments[1].samples = VkSampleCountFlags._1; attachments[1].loadOp = VkAttachmentLoadOp.Clear; attachments[1].storeOp = VkAttachmentStoreOp.Store; attachments[1].stencilLoadOp = VkAttachmentLoadOp.DontCare; attachments[1].stencilStoreOp = VkAttachmentStoreOp.DontCare; attachments[1].initialLayout = VkImageLayout.Undefined; attachments[1].finalLayout = VkImageLayout.DepthStencilAttachmentOptimal; VkAttachmentReference colorReference = new VkAttachmentReference(); colorReference.attachment = 0; colorReference.layout = VkImageLayout.ColorAttachmentOptimal; VkAttachmentReference depthReference = new VkAttachmentReference(); depthReference.attachment = 1; depthReference.layout = VkImageLayout.DepthStencilAttachmentOptimal; VkSubpassDescription subpassDescription = new VkSubpassDescription(); subpassDescription.pipelineBindPoint = VkPipelineBindPoint.Graphics; subpassDescription.colorAttachmentCount = 1; subpassDescription.pColorAttachments = &colorReference; subpassDescription.pDepthStencilAttachment = &depthReference; subpassDescription.inputAttachmentCount = 0; subpassDescription.pInputAttachments = null; subpassDescription.preserveAttachmentCount = 0; subpassDescription.pPreserveAttachments = null; subpassDescription.pResolveAttachments = null; // Subpass dependencies for layout transitions using (NativeList <VkSubpassDependency> dependencies = new NativeList <VkSubpassDependency>(2)) { dependencies.Count = 2; dependencies[0].srcSubpass = SubpassExternal; dependencies[0].dstSubpass = 0; dependencies[0].srcStageMask = VkPipelineStageFlags.BottomOfPipe; dependencies[0].dstStageMask = VkPipelineStageFlags.ColorAttachmentOutput; dependencies[0].srcAccessMask = VkAccessFlags.MemoryRead; dependencies[0].dstAccessMask = (VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite); dependencies[0].dependencyFlags = VkDependencyFlags.ByRegion; dependencies[1].srcSubpass = 0; dependencies[1].dstSubpass = SubpassExternal; dependencies[1].srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput; dependencies[1].dstStageMask = VkPipelineStageFlags.BottomOfPipe; dependencies[1].srcAccessMask = (VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite); dependencies[1].dstAccessMask = VkAccessFlags.MemoryRead; dependencies[1].dependencyFlags = VkDependencyFlags.ByRegion; VkRenderPassCreateInfo renderPassInfo = new VkRenderPassCreateInfo(); renderPassInfo.sType = VkStructureType.RenderPassCreateInfo; renderPassInfo.attachmentCount = attachments.Count; renderPassInfo.pAttachments = (VkAttachmentDescription *)attachments.Data.ToPointer(); renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subpassDescription; renderPassInfo.dependencyCount = dependencies.Count; renderPassInfo.pDependencies = (VkSubpassDependency *)dependencies.Data; Util.CheckResult(vkCreateRenderPass(Device, &renderPassInfo, null, out _renderPass)); } } }
protected void prepareFrame() { // Acquire the next image from the swap chaing Util.CheckResult(Swapchain.AcquireNextImage(Semaphores[0].PresentComplete, ref currentBuffer)); }
public void InitVulkan() { VkResult err; err = CreateInstance(true); if (err != VkResult.Success) { throw new InvalidOperationException("Could not create Vulkan instance."); } if (Settings.Validation) { } // Physical Device uint gpuCount = 0; Util.CheckResult(vkEnumeratePhysicalDevices(Instance, &gpuCount, null)); Debug.Assert(gpuCount > 0); // Enumerate devices IntPtr *physicalDevices = stackalloc IntPtr[(int)gpuCount]; err = vkEnumeratePhysicalDevices(Instance, &gpuCount, (VkPhysicalDevice *)physicalDevices); if (err != VkResult.Success) { throw new InvalidOperationException("Could not enumerate physical devices."); } // GPU selection // Select physical Device to be used for the Vulkan example // Defaults to the first Device unless specified by command line uint selectedDevice = 0; // TODO: Implement arg parsing, etc. PhysicalDevice = ((VkPhysicalDevice *)physicalDevices)[selectedDevice]; // Store properties (including limits) and features of the phyiscal Device // So examples can check against them and see if a feature is actually supported VkPhysicalDeviceProperties deviceProperties; vkGetPhysicalDeviceProperties(PhysicalDevice, &deviceProperties); DeviceProperties = deviceProperties; VkPhysicalDeviceFeatures deviceFeatures; vkGetPhysicalDeviceFeatures(PhysicalDevice, &deviceFeatures); DeviceFeatures = deviceFeatures; // Gather physical Device memory properties VkPhysicalDeviceMemoryProperties deviceMemoryProperties; vkGetPhysicalDeviceMemoryProperties(PhysicalDevice, &deviceMemoryProperties); DeviceMemoryProperties = deviceMemoryProperties; // Derived examples can override this to set actual features (based on above readings) to enable for logical device creation getEnabledFeatures(); // Vulkan Device creation // This is handled by a separate class that gets a logical Device representation // and encapsulates functions related to a Device VulkanDevice = new vksVulkanDevice(PhysicalDevice); VkResult res = VulkanDevice.CreateLogicalDevice(EnabledFeatures, EnabledExtensions); if (res != VkResult.Success) { throw new InvalidOperationException("Could not create Vulkan Device."); } Device = VulkanDevice.LogicalDevice; // Get a graphics queue from the Device VkQueue queue; vkGetDeviceQueue(Device, VulkanDevice.QFIndices.Graphics, 0, &queue); Queue = queue; // Find a suitable depth format VkFormat depthFormat; uint validDepthFormat = Tools.getSupportedDepthFormat(PhysicalDevice, &depthFormat); Debug.Assert(validDepthFormat == True); DepthFormat = depthFormat; Swapchain.Connect(Instance, PhysicalDevice, Device); // Create synchronization objects VkSemaphoreCreateInfo semaphoreCreateInfo = Initializers.SemaphoreCreateInfo(); // Create a semaphore used to synchronize image presentation // Ensures that the image is displayed before we start submitting new commands to the queu Util.CheckResult(vkCreateSemaphore(Device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->PresentComplete)); // Create a semaphore used to synchronize command submission // Ensures that the image is not presented until all commands have been sumbitted and executed Util.CheckResult(vkCreateSemaphore(Device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->RenderComplete)); // Create a semaphore used to synchronize command submission // Ensures that the image is not presented until all commands for the text overlay have been sumbitted and executed // Will be inserted after the render complete semaphore if the text overlay is enabled Util.CheckResult(vkCreateSemaphore(Device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->TextOverlayComplete)); // Set up submit info structure // Semaphores will stay the same during application lifetime // Command buffer submission info is set by each example SubmitInfo = Initializers.SubmitInfo(); SubmitInfo.pWaitDstStageMask = (VkPipelineStageFlags *)submitPipelineStages.Data; SubmitInfo.waitSemaphoreCount = 1; SubmitInfo.pWaitSemaphores = &GetSemaphoresPtr()->PresentComplete; SubmitInfo.signalSemaphoreCount = 1; SubmitInfo.pSignalSemaphores = &GetSemaphoresPtr()->RenderComplete; }