private void createSwapChain() { SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice); VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats); VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes); VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities); int imageCount = swapChainSupport.capabilities.minImageCount + 1; if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) { imageCount = swapChainSupport.capabilities.maxImageCount; } VkSwapchainCreateInfoKHR createInfo = new VkSwapchainCreateInfoKHR(); createInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; createInfo.surface = surface; createInfo.minImageCount = imageCount; createInfo.imageFormat = surfaceFormat.format; createInfo.imageColorSpace = surfaceFormat.colorSpace; createInfo.imageExtent = extent; createInfo.imageArrayLayers = 1; createInfo.imageUsage = VkImageUsageFlags.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; QueueFamilyIndices indices = findQueueFamilies(physicalDevice); var queueFamilyIndices = new List <int>() { indices.graphicsFamily, indices.presentFamily }; if (indices.graphicsFamily != indices.presentFamily) { createInfo.imageSharingMode = VkSharingMode.VK_SHARING_MODE_CONCURRENT; createInfo.queueFamilyIndexCount = queueFamilyIndices.Count; createInfo.pQueueFamilyIndices = queueFamilyIndices.ToArray(); } else { createInfo.imageSharingMode = VkSharingMode.VK_SHARING_MODE_EXCLUSIVE; } createInfo.preTransform = (VkSurfaceTransformFlagBitsKHR)swapChainSupport.capabilities.currentTransform; createInfo.compositeAlpha = VkCompositeAlphaFlagBitsKHR.VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; createInfo.presentMode = presentMode; createInfo.clipped = VkBool32.VK_TRUE; createInfo.oldSwapchain = null; VkResult result = Vulkan.vkCreateSwapchainKHR(device, createInfo, null, out swapChain); if (result != VkResult.VK_SUCCESS) { throw Program.Throw("failed to create swap chain!", result); } swapChainImages = new VkImage[imageCount]; Vulkan.vkGetSwapchainImagesKHR(device, swapChain, ref imageCount, swapChainImages); swapChainImageFormat = surfaceFormat.format; swapChainExtent = extent; }
internal VkTexture(VkGraphicsDevice gd, ref TextureDescription description) { _gd = gd; _width = description.Width; _height = description.Height; _depth = description.Depth; MipLevels = description.MipLevels; ArrayLayers = description.ArrayLayers; bool isCubemap = ((description.Usage) & TextureUsage.Cubemap) == TextureUsage.Cubemap; _actualImageArrayLayers = isCubemap ? 6 * ArrayLayers : ArrayLayers; _format = description.Format; Usage = description.Usage; Type = description.Type; SampleCount = description.SampleCount; VkSampleCount = VkFormats.VdToVkSampleCount(SampleCount); VkFormat = VkFormats.VdToVkPixelFormat(Format, (description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil); bool isStaging = (Usage & TextureUsage.Staging) == TextureUsage.Staging; if (!isStaging) { VkImageCreateInfo imageCI = VkImageCreateInfo.New(); imageCI.mipLevels = MipLevels; imageCI.arrayLayers = _actualImageArrayLayers; imageCI.imageType = VkFormats.VdToVkTextureType(Type); imageCI.extent.width = Width; imageCI.extent.height = Height; imageCI.extent.depth = Depth; imageCI.initialLayout = VkImageLayout.Preinitialized; imageCI.usage = VkFormats.VdToVkTextureUsage(Usage); imageCI.tiling = isStaging ? VkImageTiling.Linear : VkImageTiling.Optimal; imageCI.format = VkFormat; imageCI.flags = VkImageCreateFlags.MutableFormat; imageCI.samples = VkSampleCount; if (isCubemap) { imageCI.flags |= VkImageCreateFlags.CubeCompatible; } uint subresourceCount = MipLevels * _actualImageArrayLayers * Depth; VkResult result = vkCreateImage(gd.Device, ref imageCI, null, out _optimalImage); CheckResult(result); VkMemoryRequirements memoryRequirements; bool prefersDedicatedAllocation; if (_gd.GetImageMemoryRequirements2 != null) { VkImageMemoryRequirementsInfo2KHR memReqsInfo2 = VkImageMemoryRequirementsInfo2KHR.New(); memReqsInfo2.image = _optimalImage; VkMemoryRequirements2KHR memReqs2 = VkMemoryRequirements2KHR.New(); VkMemoryDedicatedRequirementsKHR dedicatedReqs = VkMemoryDedicatedRequirementsKHR.New(); memReqs2.pNext = &dedicatedReqs; _gd.GetImageMemoryRequirements2(_gd.Device, &memReqsInfo2, &memReqs2); memoryRequirements = memReqs2.memoryRequirements; prefersDedicatedAllocation = dedicatedReqs.prefersDedicatedAllocation || dedicatedReqs.requiresDedicatedAllocation; } else { vkGetImageMemoryRequirements(gd.Device, _optimalImage, out memoryRequirements); prefersDedicatedAllocation = false; } VkMemoryBlock memoryToken = gd.MemoryManager.Allocate( gd.PhysicalDeviceMemProperties, memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal, false, memoryRequirements.size, memoryRequirements.alignment, prefersDedicatedAllocation, _optimalImage, Vulkan.VkBuffer.Null); _memoryBlock = memoryToken; result = vkBindImageMemory(gd.Device, _optimalImage, _memoryBlock.DeviceMemory, _memoryBlock.Offset); CheckResult(result); _imageLayouts = new VkImageLayout[subresourceCount]; for (int i = 0; i < _imageLayouts.Length; i++) { _imageLayouts[i] = VkImageLayout.Preinitialized; } } else // isStaging { uint depthPitch = FormatHelpers.GetDepthPitch( FormatHelpers.GetRowPitch(Width, Format), Height, Format); uint stagingSize = depthPitch * Depth; for (uint level = 1; level < MipLevels; level++) { Util.GetMipDimensions(this, level, out uint mipWidth, out uint mipHeight, out uint mipDepth); depthPitch = FormatHelpers.GetDepthPitch( FormatHelpers.GetRowPitch(mipWidth, Format), mipHeight, Format); stagingSize += depthPitch * mipDepth; } stagingSize *= ArrayLayers; VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New(); bufferCI.usage = VkBufferUsageFlags.TransferSrc | VkBufferUsageFlags.TransferDst; bufferCI.size = stagingSize; VkResult result = vkCreateBuffer(_gd.Device, ref bufferCI, null, out _stagingBuffer); CheckResult(result); VkMemoryRequirements bufferMemReqs; bool prefersDedicatedAllocation; if (_gd.GetBufferMemoryRequirements2 != null) { VkBufferMemoryRequirementsInfo2KHR memReqInfo2 = VkBufferMemoryRequirementsInfo2KHR.New(); memReqInfo2.buffer = _stagingBuffer; VkMemoryRequirements2KHR memReqs2 = VkMemoryRequirements2KHR.New(); VkMemoryDedicatedRequirementsKHR dedicatedReqs = VkMemoryDedicatedRequirementsKHR.New(); memReqs2.pNext = &dedicatedReqs; _gd.GetBufferMemoryRequirements2(_gd.Device, &memReqInfo2, &memReqs2); bufferMemReqs = memReqs2.memoryRequirements; prefersDedicatedAllocation = dedicatedReqs.prefersDedicatedAllocation || dedicatedReqs.requiresDedicatedAllocation; } else { vkGetBufferMemoryRequirements(gd.Device, _stagingBuffer, out bufferMemReqs); prefersDedicatedAllocation = false; } _memoryBlock = _gd.MemoryManager.Allocate( _gd.PhysicalDeviceMemProperties, bufferMemReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent, true, bufferMemReqs.size, bufferMemReqs.alignment, prefersDedicatedAllocation, VkImage.Null, _stagingBuffer); result = vkBindBufferMemory(_gd.Device, _stagingBuffer, _memoryBlock.DeviceMemory, _memoryBlock.Offset); CheckResult(result); } ClearIfRenderTarget(); TransitionIfSampled(); RefCount = new ResourceRefCount(RefCountedDispose); }
public VkFramebuffer(VkGraphicsDevice gd, ref FramebufferDescription description, bool isPresented) : base(description.DepthTarget, description.ColorTargets) { _gd = gd; VkRenderPassCreateInfo renderPassCI = VkRenderPassCreateInfo.New(); StackList <VkAttachmentDescription> attachments = new StackList <VkAttachmentDescription>(); uint colorAttachmentCount = (uint)ColorTargets.Count; StackList <VkAttachmentReference> colorAttachmentRefs = new StackList <VkAttachmentReference>(); for (int i = 0; i < colorAttachmentCount; i++) { VkTexture vkColorTex = Util.AssertSubtype <Texture, VkTexture>(ColorTargets[i].Target); VkAttachmentDescription colorAttachmentDesc = new VkAttachmentDescription(); colorAttachmentDesc.format = vkColorTex.VkFormat; colorAttachmentDesc.samples = vkColorTex.VkSampleCount; colorAttachmentDesc.loadOp = VkAttachmentLoadOp.DontCare; colorAttachmentDesc.storeOp = VkAttachmentStoreOp.Store; colorAttachmentDesc.stencilLoadOp = VkAttachmentLoadOp.DontCare; colorAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare; colorAttachmentDesc.initialLayout = VkImageLayout.Undefined; colorAttachmentDesc.finalLayout = VkImageLayout.ColorAttachmentOptimal; attachments.Add(colorAttachmentDesc); VkAttachmentReference colorAttachmentRef = new VkAttachmentReference(); colorAttachmentRef.attachment = (uint)i; colorAttachmentRef.layout = VkImageLayout.ColorAttachmentOptimal; colorAttachmentRefs.Add(colorAttachmentRef); } VkAttachmentDescription depthAttachmentDesc = new VkAttachmentDescription(); VkAttachmentReference depthAttachmentRef = new VkAttachmentReference(); if (DepthTarget != null) { VkTexture vkDepthTex = Util.AssertSubtype <Texture, VkTexture>(DepthTarget.Value.Target); bool hasStencil = FormatHelpers.IsStencilFormat(vkDepthTex.Format); depthAttachmentDesc.format = vkDepthTex.VkFormat; depthAttachmentDesc.samples = vkDepthTex.VkSampleCount; depthAttachmentDesc.loadOp = VkAttachmentLoadOp.DontCare; depthAttachmentDesc.storeOp = VkAttachmentStoreOp.Store; depthAttachmentDesc.stencilLoadOp = VkAttachmentLoadOp.DontCare; depthAttachmentDesc.stencilStoreOp = hasStencil ? VkAttachmentStoreOp.Store : VkAttachmentStoreOp.DontCare; depthAttachmentDesc.initialLayout = VkImageLayout.Undefined; depthAttachmentDesc.finalLayout = VkImageLayout.DepthStencilAttachmentOptimal; depthAttachmentRef.attachment = (uint)description.ColorTargets.Length; depthAttachmentRef.layout = VkImageLayout.DepthStencilAttachmentOptimal; } VkSubpassDescription subpass = new VkSubpassDescription(); subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics; if (ColorTargets.Count > 0) { subpass.colorAttachmentCount = colorAttachmentCount; subpass.pColorAttachments = (VkAttachmentReference *)colorAttachmentRefs.Data; } if (DepthTarget != null) { subpass.pDepthStencilAttachment = &depthAttachmentRef; attachments.Add(depthAttachmentDesc); } VkSubpassDependency subpassDependency = new VkSubpassDependency(); subpassDependency.srcSubpass = SubpassExternal; subpassDependency.srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput; subpassDependency.dstStageMask = VkPipelineStageFlags.ColorAttachmentOutput; subpassDependency.dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite; renderPassCI.attachmentCount = attachments.Count; renderPassCI.pAttachments = (VkAttachmentDescription *)attachments.Data; renderPassCI.subpassCount = 1; renderPassCI.pSubpasses = &subpass; renderPassCI.dependencyCount = 1; renderPassCI.pDependencies = &subpassDependency; VkResult creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPassNoClear); CheckResult(creationResult); for (int i = 0; i < colorAttachmentCount; i++) { attachments[i].loadOp = VkAttachmentLoadOp.Load; attachments[i].initialLayout = VkImageLayout.ColorAttachmentOptimal; } if (DepthTarget != null) { attachments[attachments.Count - 1].loadOp = VkAttachmentLoadOp.Load; attachments[attachments.Count - 1].initialLayout = VkImageLayout.DepthStencilAttachmentOptimal; bool hasStencil = FormatHelpers.IsStencilFormat(DepthTarget.Value.Target.Format); if (hasStencil) { attachments[attachments.Count - 1].stencilLoadOp = VkAttachmentLoadOp.Load; } } creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPassNoClearLoad); CheckResult(creationResult); // Load version if (DepthTarget != null) { attachments[attachments.Count - 1].loadOp = VkAttachmentLoadOp.Clear; attachments[attachments.Count - 1].initialLayout = VkImageLayout.Undefined; bool hasStencil = FormatHelpers.IsStencilFormat(DepthTarget.Value.Target.Format); if (hasStencil) { attachments[attachments.Count - 1].stencilLoadOp = VkAttachmentLoadOp.Clear; } } for (int i = 0; i < colorAttachmentCount; i++) { attachments[i].loadOp = VkAttachmentLoadOp.Clear; attachments[i].initialLayout = VkImageLayout.Undefined; } creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPassClear); CheckResult(creationResult); VkFramebufferCreateInfo fbCI = VkFramebufferCreateInfo.New(); uint fbAttachmentsCount = (uint)description.ColorTargets.Length; if (description.DepthTarget != null) { fbAttachmentsCount += 1; } VkImageView *fbAttachments = stackalloc VkImageView[(int)fbAttachmentsCount]; for (int i = 0; i < colorAttachmentCount; i++) { VkTexture vkColorTarget = Util.AssertSubtype <Texture, VkTexture>(description.ColorTargets[i].Target); VkImageViewCreateInfo imageViewCI = VkImageViewCreateInfo.New(); imageViewCI.image = vkColorTarget.OptimalDeviceImage; imageViewCI.format = vkColorTarget.VkFormat; imageViewCI.viewType = VkImageViewType.Image2D; imageViewCI.subresourceRange = new VkImageSubresourceRange( VkImageAspectFlags.Color, description.ColorTargets[i].MipLevel, 1, description.ColorTargets[i].ArrayLayer, 1); VkImageView *dest = (fbAttachments + i); VkResult result = vkCreateImageView(_gd.Device, ref imageViewCI, null, dest); CheckResult(result); _attachmentViews.Add(*dest); } // Depth if (description.DepthTarget != null) { VkTexture vkDepthTarget = Util.AssertSubtype <Texture, VkTexture>(description.DepthTarget.Value.Target); bool hasStencil = FormatHelpers.IsStencilFormat(vkDepthTarget.Format); VkImageViewCreateInfo depthViewCI = VkImageViewCreateInfo.New(); depthViewCI.image = vkDepthTarget.OptimalDeviceImage; depthViewCI.format = vkDepthTarget.VkFormat; depthViewCI.viewType = description.DepthTarget.Value.Target.ArrayLayers == 1 ? VkImageViewType.Image2D : VkImageViewType.Image2DArray; depthViewCI.subresourceRange = new VkImageSubresourceRange( hasStencil ? VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil : VkImageAspectFlags.Depth, description.DepthTarget.Value.MipLevel, 1, description.DepthTarget.Value.ArrayLayer, 1); VkImageView *dest = (fbAttachments + (fbAttachmentsCount - 1)); VkResult result = vkCreateImageView(_gd.Device, ref depthViewCI, null, dest); CheckResult(result); _attachmentViews.Add(*dest); } Texture dimTex; uint mipLevel; if (ColorTargets.Count > 0) { dimTex = ColorTargets[0].Target; mipLevel = ColorTargets[0].MipLevel; } else { Debug.Assert(DepthTarget != null); dimTex = DepthTarget.Value.Target; mipLevel = DepthTarget.Value.MipLevel; } Util.GetMipDimensions( dimTex, mipLevel, out uint mipWidth, out uint mipHeight, out _); fbCI.width = mipWidth; fbCI.height = mipHeight; fbCI.attachmentCount = fbAttachmentsCount; fbCI.pAttachments = fbAttachments; fbCI.layers = 1; fbCI.renderPass = _renderPassNoClear; creationResult = vkCreateFramebuffer(_gd.Device, ref fbCI, null, out _deviceFramebuffer); CheckResult(creationResult); if (DepthTarget != null) { AttachmentCount += 1; } AttachmentCount += (uint)ColorTargets.Count; }
public VkPipeline(VkGraphicsDevice gd, ref GraphicsPipelineDescription description) : base(ref description) { _gd = gd; IsComputePipeline = false; VkGraphicsPipelineCreateInfo pipelineCI = VkGraphicsPipelineCreateInfo.New(); // Blend State VkPipelineColorBlendStateCreateInfo blendStateCI = VkPipelineColorBlendStateCreateInfo.New(); int attachmentsCount = description.BlendState.AttachmentStates.Length; VkPipelineColorBlendAttachmentState *attachmentsPtr = stackalloc VkPipelineColorBlendAttachmentState[attachmentsCount]; for (int i = 0; i < attachmentsCount; i++) { BlendAttachmentDescription vdDesc = description.BlendState.AttachmentStates[i]; VkPipelineColorBlendAttachmentState attachmentState = new VkPipelineColorBlendAttachmentState(); attachmentState.srcColorBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.SourceColorFactor); attachmentState.dstColorBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.DestinationColorFactor); attachmentState.colorBlendOp = VkFormats.VdToVkBlendOp(vdDesc.ColorFunction); attachmentState.srcAlphaBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.SourceAlphaFactor); attachmentState.dstAlphaBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.DestinationAlphaFactor); attachmentState.alphaBlendOp = VkFormats.VdToVkBlendOp(vdDesc.AlphaFunction); attachmentState.blendEnable = vdDesc.BlendEnabled; attachmentState.colorWriteMask = VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A; attachmentsPtr[i] = attachmentState; } blendStateCI.attachmentCount = (uint)attachmentsCount; blendStateCI.pAttachments = attachmentsPtr; RgbaFloat blendFactor = description.BlendState.BlendFactor; blendStateCI.blendConstants_0 = blendFactor.R; blendStateCI.blendConstants_1 = blendFactor.G; blendStateCI.blendConstants_2 = blendFactor.B; blendStateCI.blendConstants_3 = blendFactor.A; pipelineCI.pColorBlendState = &blendStateCI; // Rasterizer State RasterizerStateDescription rsDesc = description.RasterizerState; VkPipelineRasterizationStateCreateInfo rsCI = VkPipelineRasterizationStateCreateInfo.New(); rsCI.cullMode = VkFormats.VdToVkCullMode(rsDesc.CullMode); rsCI.polygonMode = VkFormats.VdToVkPolygonMode(rsDesc.FillMode); rsCI.depthClampEnable = !rsDesc.DepthClipEnabled; rsCI.frontFace = rsDesc.FrontFace == FrontFace.Clockwise ? VkFrontFace.Clockwise : VkFrontFace.CounterClockwise; rsCI.lineWidth = 1f; pipelineCI.pRasterizationState = &rsCI; ScissorTestEnabled = rsDesc.ScissorTestEnabled; // Dynamic State VkPipelineDynamicStateCreateInfo dynamicStateCI = VkPipelineDynamicStateCreateInfo.New(); VkDynamicState *dynamicStates = stackalloc VkDynamicState[2]; dynamicStates[0] = VkDynamicState.Viewport; dynamicStates[1] = VkDynamicState.Scissor; dynamicStateCI.dynamicStateCount = 2; dynamicStateCI.pDynamicStates = dynamicStates; pipelineCI.pDynamicState = &dynamicStateCI; // Depth Stencil State DepthStencilStateDescription vdDssDesc = description.DepthStencilState; VkPipelineDepthStencilStateCreateInfo dssCI = VkPipelineDepthStencilStateCreateInfo.New(); dssCI.depthWriteEnable = vdDssDesc.DepthWriteEnabled; dssCI.depthTestEnable = vdDssDesc.DepthTestEnabled; dssCI.depthCompareOp = VkFormats.VdToVkCompareOp(vdDssDesc.DepthComparison); dssCI.stencilTestEnable = vdDssDesc.StencilTestEnabled; dssCI.front.failOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilFront.Fail); dssCI.front.passOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilFront.Pass); dssCI.front.depthFailOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilFront.DepthFail); dssCI.front.compareMask = vdDssDesc.StencilReadMask; dssCI.front.writeMask = vdDssDesc.StencilWriteMask; dssCI.front.reference = vdDssDesc.StencilReference; dssCI.back.failOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilBack.Fail); dssCI.back.passOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilBack.Pass); dssCI.back.depthFailOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilBack.DepthFail); dssCI.back.compareMask = vdDssDesc.StencilReadMask; dssCI.back.writeMask = vdDssDesc.StencilWriteMask; dssCI.back.reference = vdDssDesc.StencilReference; pipelineCI.pDepthStencilState = &dssCI; // Multisample VkPipelineMultisampleStateCreateInfo multisampleCI = VkPipelineMultisampleStateCreateInfo.New(); VkSampleCountFlags vkSampleCount = VkFormats.VdToVkSampleCount(description.Outputs.SampleCount); multisampleCI.rasterizationSamples = vkSampleCount; pipelineCI.pMultisampleState = &multisampleCI; // Input Assembly VkPipelineInputAssemblyStateCreateInfo inputAssemblyCI = VkPipelineInputAssemblyStateCreateInfo.New(); inputAssemblyCI.topology = VkFormats.VdToVkPrimitiveTopology(description.PrimitiveTopology); pipelineCI.pInputAssemblyState = &inputAssemblyCI; // Vertex Input State VkPipelineVertexInputStateCreateInfo vertexInputCI = VkPipelineVertexInputStateCreateInfo.New(); VertexLayoutDescription[] inputDescriptions = description.ShaderSet.VertexLayouts; uint bindingCount = (uint)inputDescriptions.Length; uint attributeCount = 0; for (int i = 0; i < inputDescriptions.Length; i++) { attributeCount += (uint)inputDescriptions[i].Elements.Length; } VkVertexInputBindingDescription * bindingDescs = stackalloc VkVertexInputBindingDescription[(int)bindingCount]; VkVertexInputAttributeDescription *attributeDescs = stackalloc VkVertexInputAttributeDescription[(int)attributeCount]; int targetIndex = 0; int targetLocation = 0; for (int binding = 0; binding < inputDescriptions.Length; binding++) { VertexLayoutDescription inputDesc = inputDescriptions[binding]; bindingDescs[binding] = new VkVertexInputBindingDescription() { binding = (uint)binding, inputRate = (inputDesc.InstanceStepRate != 0) ? VkVertexInputRate.Instance : VkVertexInputRate.Vertex, stride = inputDesc.Stride }; uint currentOffset = 0; for (int location = 0; location < inputDesc.Elements.Length; location++) { VertexElementDescription inputElement = inputDesc.Elements[location]; attributeDescs[targetIndex] = new VkVertexInputAttributeDescription() { format = VkFormats.VdToVkVertexElementFormat(inputElement.Format), binding = (uint)binding, location = (uint)(targetLocation + location), offset = currentOffset }; targetIndex += 1; currentOffset += FormatHelpers.GetSizeInBytes(inputElement.Format); } targetLocation += inputDesc.Elements.Length; } vertexInputCI.vertexBindingDescriptionCount = bindingCount; vertexInputCI.pVertexBindingDescriptions = bindingDescs; vertexInputCI.vertexAttributeDescriptionCount = attributeCount; vertexInputCI.pVertexAttributeDescriptions = attributeDescs; pipelineCI.pVertexInputState = &vertexInputCI; // Shader Stage Shader[] shaders = description.ShaderSet.Shaders; StackList <VkPipelineShaderStageCreateInfo> stages = new StackList <VkPipelineShaderStageCreateInfo>(); foreach (Shader shader in shaders) { VkShader vkShader = Util.AssertSubtype <Shader, VkShader>(shader); VkPipelineShaderStageCreateInfo stageCI = VkPipelineShaderStageCreateInfo.New(); stageCI.module = vkShader.ShaderModule; stageCI.stage = VkFormats.VdToVkShaderStages(shader.Stage); stageCI.pName = CommonStrings.main; // Meh stages.Add(stageCI); } pipelineCI.stageCount = stages.Count; pipelineCI.pStages = (VkPipelineShaderStageCreateInfo *)stages.Data; // ViewportState VkPipelineViewportStateCreateInfo viewportStateCI = VkPipelineViewportStateCreateInfo.New(); viewportStateCI.viewportCount = 1; viewportStateCI.scissorCount = 1; pipelineCI.pViewportState = &viewportStateCI; // Pipeline Layout ResourceLayout[] resourceLayouts = description.ResourceLayouts; VkPipelineLayoutCreateInfo pipelineLayoutCI = VkPipelineLayoutCreateInfo.New(); pipelineLayoutCI.setLayoutCount = (uint)resourceLayouts.Length; VkDescriptorSetLayout *dsls = stackalloc VkDescriptorSetLayout[resourceLayouts.Length]; for (int i = 0; i < resourceLayouts.Length; i++) { dsls[i] = Util.AssertSubtype <ResourceLayout, VkResourceLayout>(resourceLayouts[i]).DescriptorSetLayout; } pipelineLayoutCI.pSetLayouts = dsls; vkCreatePipelineLayout(_gd.Device, ref pipelineLayoutCI, null, out _pipelineLayout); pipelineCI.layout = _pipelineLayout; // Create fake RenderPass for compatibility. VkRenderPassCreateInfo renderPassCI = VkRenderPassCreateInfo.New(); OutputDescription outputDesc = description.Outputs; StackList <VkAttachmentDescription, Size512Bytes> attachments = new StackList <VkAttachmentDescription, Size512Bytes>(); // TODO: A huge portion of this next part is duplicated in VkFramebuffer.cs. StackList <VkAttachmentDescription> colorAttachmentDescs = new StackList <VkAttachmentDescription>(); StackList <VkAttachmentReference> colorAttachmentRefs = new StackList <VkAttachmentReference>(); for (uint i = 0; i < outputDesc.ColorAttachments.Length; i++) { colorAttachmentDescs[i].format = VkFormats.VdToVkPixelFormat(outputDesc.ColorAttachments[i].Format); colorAttachmentDescs[i].samples = vkSampleCount; colorAttachmentDescs[i].loadOp = VkAttachmentLoadOp.DontCare; colorAttachmentDescs[i].storeOp = VkAttachmentStoreOp.Store; colorAttachmentDescs[i].stencilLoadOp = VkAttachmentLoadOp.DontCare; colorAttachmentDescs[i].stencilStoreOp = VkAttachmentStoreOp.DontCare; colorAttachmentDescs[i].initialLayout = VkImageLayout.Undefined; colorAttachmentDescs[i].finalLayout = VkImageLayout.ShaderReadOnlyOptimal; attachments.Add(colorAttachmentDescs[i]); colorAttachmentRefs[i].attachment = i; colorAttachmentRefs[i].layout = VkImageLayout.ColorAttachmentOptimal; } VkAttachmentDescription depthAttachmentDesc = new VkAttachmentDescription(); VkAttachmentReference depthAttachmentRef = new VkAttachmentReference(); if (outputDesc.DepthAttachment != null) { PixelFormat depthFormat = outputDesc.DepthAttachment.Value.Format; bool hasStencil = FormatHelpers.IsStencilFormat(depthFormat); depthAttachmentDesc.format = VkFormats.VdToVkPixelFormat(outputDesc.DepthAttachment.Value.Format, toDepthFormat: true); depthAttachmentDesc.samples = vkSampleCount; depthAttachmentDesc.loadOp = VkAttachmentLoadOp.DontCare; depthAttachmentDesc.storeOp = VkAttachmentStoreOp.Store; depthAttachmentDesc.stencilLoadOp = VkAttachmentLoadOp.DontCare; depthAttachmentDesc.stencilStoreOp = hasStencil ? VkAttachmentStoreOp.Store : VkAttachmentStoreOp.DontCare; depthAttachmentDesc.initialLayout = VkImageLayout.Undefined; depthAttachmentDesc.finalLayout = VkImageLayout.DepthStencilAttachmentOptimal; depthAttachmentRef.attachment = (uint)outputDesc.ColorAttachments.Length; depthAttachmentRef.layout = VkImageLayout.DepthStencilAttachmentOptimal; } VkSubpassDescription subpass = new VkSubpassDescription(); subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics; subpass.colorAttachmentCount = (uint)outputDesc.ColorAttachments.Length; subpass.pColorAttachments = (VkAttachmentReference *)colorAttachmentRefs.Data; for (int i = 0; i < colorAttachmentDescs.Count; i++) { attachments.Add(colorAttachmentDescs[i]); } if (outputDesc.DepthAttachment != null) { subpass.pDepthStencilAttachment = &depthAttachmentRef; attachments.Add(depthAttachmentDesc); } VkSubpassDependency subpassDependency = new VkSubpassDependency(); subpassDependency.srcSubpass = SubpassExternal; subpassDependency.srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput; subpassDependency.dstStageMask = VkPipelineStageFlags.ColorAttachmentOutput; subpassDependency.dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite; if (outputDesc.DepthAttachment != null) { subpassDependency.dstAccessMask |= VkAccessFlags.DepthStencilAttachmentRead | VkAccessFlags.DepthStencilAttachmentWrite; } renderPassCI.attachmentCount = attachments.Count; renderPassCI.pAttachments = (VkAttachmentDescription *)attachments.Data; renderPassCI.subpassCount = 1; renderPassCI.pSubpasses = &subpass; renderPassCI.dependencyCount = 1; renderPassCI.pDependencies = &subpassDependency; VkResult creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPass); CheckResult(creationResult); pipelineCI.renderPass = _renderPass; VkResult result = vkCreateGraphicsPipelines(_gd.Device, VkPipelineCache.Null, 1, ref pipelineCI, null, out _devicePipeline); CheckResult(result); ResourceSetCount = (uint)description.ResourceLayouts.Length; }
private VkPipeline CreateGraphicsPipeline() { // Create shader modules. Shader modules are one of the objects required to create the // graphics pipeline. But after the pipeline is created, we don't need these shader // modules anymore, so we dispose them. VkShaderModule vertexShader = Content.LoadShader("Shader.vert.spv"); VkShaderModule fragmentShader = Content.LoadShader("Shader.frag.spv"); VkPipelineShaderStageCreateInfo *shaderStageCreateInfos = stackalloc VkPipelineShaderStageCreateInfo[2] { new VkPipelineShaderStageCreateInfo { sType = VkStructureType.PipelineShaderStageCreateInfo, pNext = null, stage = VkShaderStageFlags.Vertex, module = vertexShader, pName = Interop.String.ToPointer("main") }, new VkPipelineShaderStageCreateInfo { sType = VkStructureType.PipelineShaderStageCreateInfo, pNext = null, stage = VkShaderStageFlags.Fragment, module = fragmentShader, pName = Interop.String.ToPointer("main") } }; VkVertexInputBindingDescription vertexInputBindingDescription = new VkVertexInputBindingDescription { binding = 0, stride = (uint)Unsafe.SizeOf <Vertex>(), inputRate = VkVertexInputRate.Vertex }; VkVertexInputAttributeDescription *vertexInputAttributeDescription = stackalloc VkVertexInputAttributeDescription[3] { new VkVertexInputAttributeDescription { location = 0, binding = 0, format = VkFormat.R32G32B32A32SFloat, offset = 0 }, // Position. new VkVertexInputAttributeDescription { location = 1, binding = 0, format = VkFormat.R32G32B32SFloat, offset = 12 }, // Normal. new VkVertexInputAttributeDescription { location = 2, binding = 0, format = VkFormat.R32G32SFloat, offset = 24 }// TexCoord. }; var vertexInputStateCreateInfo = new VkPipelineVertexInputStateCreateInfo { sType = VkStructureType.PipelineVertexInputStateCreateInfo, pNext = null, vertexBindingDescriptionCount = 1, pVertexBindingDescriptions = &vertexInputBindingDescription, vertexAttributeDescriptionCount = 3, pVertexAttributeDescriptions = vertexInputAttributeDescription }; var inputAssemblyStateCreateInfo = new VkPipelineInputAssemblyStateCreateInfo { sType = VkStructureType.PipelineInputAssemblyStateCreateInfo, pNext = null, topology = VkPrimitiveTopology.TriangleList }; Viewport viewport = new Viewport(0, 0, Host.Width, Host.Height); Rectangle scissor = new Rectangle(0, 0, Host.Width, Host.Height); var viewportStateCreateInfo = new VkPipelineViewportStateCreateInfo { sType = VkStructureType.PipelineViewportStateCreateInfo, pNext = null, viewportCount = 1, pViewports = &viewport, scissorCount = 1, pScissors = &scissor }; var rasterizationStateCreateInfo = new VkPipelineRasterizationStateCreateInfo { sType = VkStructureType.PipelineRasterizationStateCreateInfo, polygonMode = VkPolygonMode.Fill, cullMode = VkCullModeFlags.Back, frontFace = VkFrontFace.CounterClockwise, lineWidth = 1.0f }; var multisampleStateCreateInfo = new VkPipelineMultisampleStateCreateInfo { sType = VkStructureType.PipelineMultisampleStateCreateInfo, rasterizationSamples = VkSampleCountFlags.Count1, minSampleShading = 1.0f }; var depthStencilStateCreateInfo = new VkPipelineDepthStencilStateCreateInfo { sType = VkStructureType.PipelineDepthStencilStateCreateInfo, depthTestEnable = true, depthWriteEnable = true, depthCompareOp = VkCompareOp.LessOrEqual, back = new VkStencilOpState { failOp = VkStencilOp.Keep, passOp = VkStencilOp.Keep, compareOp = VkCompareOp.Always }, front = new VkStencilOpState { failOp = VkStencilOp.Keep, passOp = VkStencilOp.Keep, compareOp = VkCompareOp.Always } }; var colorBlendAttachmentState = new VkPipelineColorBlendAttachmentState { srcColorBlendFactor = VkBlendFactor.One, dstColorBlendFactor = VkBlendFactor.Zero, colorBlendOp = VkBlendOp.Add, srcAlphaBlendFactor = VkBlendFactor.One, dstAlphaBlendFactor = VkBlendFactor.Zero, alphaBlendOp = VkBlendOp.Add, colorWriteMask = VkColorComponentFlags.All }; var colorBlendStateCreateInfo = new VkPipelineColorBlendStateCreateInfo { sType = VkStructureType.PipelineColorBlendStateCreateInfo, pNext = null, attachmentCount = 1, pAttachments = &colorBlendAttachmentState }; var pipelineCreateInfo = new VkGraphicsPipelineCreateInfo { sType = VkStructureType.GraphicsPipelineCreateInfo, pNext = null, layout = _pipelineLayout, renderPass = _renderPass, subpass = (uint)0, stageCount = 2, pStages = shaderStageCreateInfos, pInputAssemblyState = &inputAssemblyStateCreateInfo, pVertexInputState = &vertexInputStateCreateInfo, pRasterizationState = &rasterizationStateCreateInfo, pMultisampleState = &multisampleStateCreateInfo, pColorBlendState = &colorBlendStateCreateInfo, pDepthStencilState = &depthStencilStateCreateInfo, pViewportState = &viewportStateCreateInfo }; VkPipeline pipeline; VkResult result = vkCreateGraphicsPipelines(Context.Device, VkPipelineCache.Null, 1, &pipelineCreateInfo, null, &pipeline); result.CheckResult(); return(pipeline); } } }
private SoftwareImage(SoftwareDevice device, VkSwapchainCreateInfoKHR createInfo, out VkResult result) { this.m_device = device; this.m_imageFormat = createInfo.imageFormat; this.m_imageExtent = VkExtent3D.Create(createInfo.imageExtent.width, createInfo.imageExtent.height, 1); this.m_imageColorSpace = createInfo.imageColorSpace; Initialize(out result); }
private SoftwareImage(SoftwareDevice device, VkFormat format, VkExtent3D imageExtent, VkColorSpaceKHR colorSpace, out VkResult result) { this.m_device = device; this.m_imageFormat = format; this.m_imageExtent = imageExtent; this.m_imageColorSpace = colorSpace; Initialize(out result); }
public static SoftwareImage CreateSwapchainImage(SoftwareDevice device, VkSwapchainCreateInfoKHR swapchainInfo, out VkResult result) { VkImageCreateInfo createInfo = new VkImageCreateInfo(); createInfo.extent = VkExtent3D.Create(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height, 1); createInfo.format = swapchainInfo.imageFormat; createInfo.imageType = VkImageType.VK_IMAGE_TYPE_2D; createInfo.arrayLayers = swapchainInfo.imageArrayLayers; createInfo.sharingMode = swapchainInfo.imageSharingMode; createInfo.usage = VkImageUsageFlags.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VkImageUsageFlags.VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; createInfo.samples = VkSampleCountFlagBits.VK_SAMPLE_COUNT_1_BIT; createInfo.mipLevels = 1; createInfo.initialLayout = VkImageLayout.VK_IMAGE_LAYOUT_UNDEFINED; return(new SoftwareImage(device, createInfo, out result)); }
public static SoftwareImage CreateImage(SoftwareDevice device, VkImageCreateInfo createInfo, out VkResult result) { return(new SoftwareImage(device, createInfo, out result)); }
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; }
public VkResourceLayout(VkGraphicsDevice gd, ref ResourceLayoutDescription description) : base(ref description) { _gd = gd; VkDescriptorSetLayoutCreateInfo dslCI = VkDescriptorSetLayoutCreateInfo.New(); ResourceLayoutElementDescription[] elements = description.Elements; _descriptorTypes = new VkDescriptorType[elements.Length]; VkDescriptorSetLayoutBinding *bindings = stackalloc VkDescriptorSetLayoutBinding[elements.Length]; uint uniformBufferCount = 0; uint sampledImageCount = 0; uint samplerCount = 0; uint storageBufferCount = 0; uint storageImageCount = 0; for (uint i = 0; i < elements.Length; i++) { bindings[i].binding = i; bindings[i].descriptorCount = 1; VkDescriptorType descriptorType = VkFormats.VdToVkDescriptorType(elements[i].Kind, elements[i].Options); bindings[i].descriptorType = descriptorType; bindings[i].stageFlags = VkFormats.VdToVkShaderStages(elements[i].Stages); if ((elements[i].Options & ResourceLayoutElementOptions.DynamicBinding) != 0) { DynamicBufferCount += 1; } _descriptorTypes[i] = descriptorType; switch (descriptorType) { case VkDescriptorType.Sampler: samplerCount += 1; break; case VkDescriptorType.SampledImage: sampledImageCount += 1; break; case VkDescriptorType.StorageImage: storageImageCount += 1; break; case VkDescriptorType.UniformBuffer: uniformBufferCount += 1; break; case VkDescriptorType.StorageBuffer: storageBufferCount += 1; break; } } DescriptorResourceCounts = new DescriptorResourceCounts( uniformBufferCount, sampledImageCount, samplerCount, storageBufferCount, storageImageCount); dslCI.bindingCount = (uint)elements.Length; dslCI.pBindings = bindings; VkResult result = vkCreateDescriptorSetLayout(_gd.Device, ref dslCI, null, out _dsl); CheckResult(result); }
public VkPipeline(VkGraphicsDevice gd, ref ComputePipelineDescription description) : base(ref description) { _gd = gd; IsComputePipeline = true; RefCount = new ResourceRefCount(DisposeCore); VkComputePipelineCreateInfo pipelineCI = VkComputePipelineCreateInfo.New(); // Pipeline Layout ResourceLayout[] resourceLayouts = description.ResourceLayouts; VkPipelineLayoutCreateInfo pipelineLayoutCI = VkPipelineLayoutCreateInfo.New(); pipelineLayoutCI.setLayoutCount = (uint)resourceLayouts.Length; VkDescriptorSetLayout *dsls = stackalloc VkDescriptorSetLayout[resourceLayouts.Length]; for (int i = 0; i < resourceLayouts.Length; i++) { dsls[i] = Util.AssertSubtype <ResourceLayout, VkResourceLayout>(resourceLayouts[i]).DescriptorSetLayout; } pipelineLayoutCI.pSetLayouts = dsls; vkCreatePipelineLayout(_gd.Device, ref pipelineLayoutCI, null, out _pipelineLayout); pipelineCI.layout = _pipelineLayout; // Shader Stage VkSpecializationInfo specializationInfo; SpecializationConstant[] specDescs = description.Specializations; if (specDescs != null) { uint specDataSize = 0; foreach (SpecializationConstant spec in specDescs) { specDataSize += VkFormats.GetSpecializationConstantSize(spec.Type); } byte *fullSpecData = stackalloc byte[(int)specDataSize]; int specializationCount = specDescs.Length; VkSpecializationMapEntry *mapEntries = stackalloc VkSpecializationMapEntry[specializationCount]; uint specOffset = 0; for (int i = 0; i < specializationCount; i++) { ulong data = specDescs[i].Data; byte *srcData = (byte *)&data; uint dataSize = VkFormats.GetSpecializationConstantSize(specDescs[i].Type); Unsafe.CopyBlock(fullSpecData + specOffset, srcData, dataSize); mapEntries[i].constantID = specDescs[i].ID; mapEntries[i].offset = specOffset; mapEntries[i].size = (UIntPtr)dataSize; specOffset += dataSize; } specializationInfo.dataSize = (UIntPtr)specDataSize; specializationInfo.pData = fullSpecData; specializationInfo.mapEntryCount = (uint)specializationCount; specializationInfo.pMapEntries = mapEntries; } Shader shader = description.ComputeShader; VkShader vkShader = Util.AssertSubtype <Shader, VkShader>(shader); VkPipelineShaderStageCreateInfo stageCI = VkPipelineShaderStageCreateInfo.New(); stageCI.module = vkShader.ShaderModule; stageCI.stage = VkFormats.VdToVkShaderStages(shader.Stage); stageCI.pName = CommonStrings.main; // Meh stageCI.pSpecializationInfo = &specializationInfo; pipelineCI.stage = stageCI; VkResult result = vkCreateComputePipelines( _gd.Device, VkPipelineCache.Null, 1, ref pipelineCI, null, out _devicePipeline); CheckResult(result); ResourceSetCount = (uint)description.ResourceLayouts.Length; DynamicOffsetsCount = 0; foreach (VkResourceLayout layout in description.ResourceLayouts) { DynamicOffsetsCount += layout.DynamicBufferCount; } }
private void RecordCommandBuffers() { VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange() { aspectMask = VkImageAspectFlags.Color, baseMipLevel = 0, baseArrayLayer = 0, layerCount = 1, levelCount = 1 }; for (int i = 0; i < CommandBuffers.Length; i++) { VkCommandBuffer cmdBuffer = CommandBuffers[i]; VkCommandBufferBeginInfo beginInfo = new VkCommandBufferBeginInfo() { sType = VkStructureType.CommandBufferBeginInfo, flags = VkCommandBufferUsageFlags.SimultaneousUse }; vkBeginCommandBuffer(cmdBuffer, &beginInfo); if (Context.PresentQueue != Context.GraphicsQueue) { var barrierFromPresentToDraw = new VkImageMemoryBarrier( SwapchainImages[i], subresourceRange, VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentWrite, VkImageLayout.Undefined, VkImageLayout.PresentSrcKHR, (uint)Context.PresentQueueFamilyIndex, (uint)Context.GraphicsQueueFamilyIndex); vkCmdPipelineBarrier(cmdBuffer, VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.ColorAttachmentOutput, 0, 0, null, 0, null, 1, &barrierFromPresentToDraw ); } RecordCommandBuffer(cmdBuffer, i); if (Context.PresentQueue != Context.GraphicsQueue) { var barrierFromDrawToPresent = new VkImageMemoryBarrier( SwapchainImages[i], subresourceRange, VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead, VkImageLayout.PresentSrcKHR, VkImageLayout.PresentSrcKHR, (uint)Context.GraphicsQueueFamilyIndex, (uint)Context.PresentQueueFamilyIndex); vkCmdPipelineBarrier(cmdBuffer, VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe, 0, 0, null, 0, null, 1, &barrierFromDrawToPresent ); } VkResult result = vkEndCommandBuffer(cmdBuffer); result.CheckResult(); } }
private VkInstance CreateInstance(bool debug) { VkInstance instance; // Specify standard validation layers. string surfaceExtension; switch (Host.Platform) { case Platform.Android: surfaceExtension = KHRAndroidSurfaceExtensionName; break; case Platform.Win32: surfaceExtension = KHRWin32SurfaceExtensionName; break; default: throw new NotImplementedException(); } VkString name = "TODO Application Name"; var appInfo = new VkApplicationInfo { sType = VkStructureType.ApplicationInfo, pApplicationName = name, applicationVersion = new VkVersion(1, 0, 0), pEngineName = s_EngineName, engineVersion = new VkVersion(1, 0, 0), apiVersion = VkVersion.Version_1_0, }; var instanceExtensions = new List <string> { KHRSurfaceExtensionName, surfaceExtension }; var instanceLayers = new List <string>(); if (EnableValidationLayers) { FindValidationLayers(instanceLayers); } if (instanceLayers.Count > 0) { instanceExtensions.Add(EXTDebugUtilsExtensionName); } using var vkInstanceExtensions = new VkStringArray(instanceExtensions); var instanceCreateInfo = new VkInstanceCreateInfo { sType = VkStructureType.InstanceCreateInfo, pApplicationInfo = &appInfo, enabledExtensionCount = vkInstanceExtensions.Length, ppEnabledExtensionNames = vkInstanceExtensions }; using var vkLayerNames = new VkStringArray(instanceLayers); if (instanceLayers.Count > 0) { instanceCreateInfo.enabledLayerCount = vkLayerNames.Length; instanceCreateInfo.ppEnabledLayerNames = vkLayerNames; } VkResult result = vkCreateInstance(&instanceCreateInfo, null, out instance); vkLoadInstance(instance); if (instanceLayers.Count > 0) { _debugMessengerCallbackFunc = DebugMessengerCallback; var debugCreateInfo = new VkDebugUtilsMessengerCreateInfoEXT { sType = VkStructureType.DebugUtilsMessengerCreateInfoEXT, messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT.Verbose | VkDebugUtilsMessageSeverityFlagsEXT.Error | VkDebugUtilsMessageSeverityFlagsEXT.Warning, messageType = VkDebugUtilsMessageTypeFlagsEXT.General | VkDebugUtilsMessageTypeFlagsEXT.Validation | VkDebugUtilsMessageTypeFlagsEXT.Performance, pfnUserCallback = Marshal.GetFunctionPointerForDelegate(_debugMessengerCallbackFunc) }; vkCreateDebugUtilsMessengerEXT(instance, &debugCreateInfo, null, out debugMessenger).CheckResult(); } return(instance); }
public void Initialize(IVulkanAppHost host) { Host = host; #if DEBUG const bool debug = true; #else const bool debug = false; #endif _initializingPermanent = true; VkResult result = vkInitialize(); result.CheckResult(); // Calling ToDispose here registers the resource to be automatically disposed on exit. Instance = CreateInstance(debug); Surface = CreateSurface(); Context = new VulkanContext(Instance, Surface, Host.Platform); Content = new ContentManager(Host, Context, "Content"); ImageAvailableSemaphore = CreateSemaphore(Context.Device); RenderingFinishedSemaphore = CreateSemaphore(Context.Device); _initializingPermanent = false; // Calling ToDispose here registers the resource to be automatically disposed on events // such as window resize. var swapchain = CreateSwapchain(); Swapchain = swapchain; ToDispose(new ActionDisposable(() => { vkDestroySwapchainKHR(Context.Device, swapchain, null); })); // Acquire underlying images of the freshly created swapchain. uint swapchainImageCount; result = vkGetSwapchainImagesKHR(Context.Device, Swapchain, &swapchainImageCount, null); result.CheckResult(); var swapchainImages = stackalloc VkImage[(int)swapchainImageCount]; result = vkGetSwapchainImagesKHR(Context.Device, Swapchain, &swapchainImageCount, swapchainImages); result.CheckResult(); SwapchainImages = new VkImage[swapchainImageCount]; for (int i = 0; i < swapchainImageCount; i++) { SwapchainImages[i] = swapchainImages[i]; } VkCommandBufferAllocateInfo allocInfo = new VkCommandBufferAllocateInfo() { sType = VkStructureType.CommandBufferAllocateInfo, commandPool = Context.GraphicsCommandPool, level = VkCommandBufferLevel.Primary, commandBufferCount = (uint)SwapchainImages.Length, }; VkCommandBuffer[] commandBuffers = new VkCommandBuffer[SwapchainImages.Length]; fixed(VkCommandBuffer *commandBuffersPtr = &commandBuffers[0]) { vkAllocateCommandBuffers(Context.Device, &allocInfo, commandBuffersPtr).CheckResult(); } CommandBuffers = commandBuffers; // Create a fence for each commandbuffer so that we can wait before using it again _initializingPermanent = true; //We need our fences to be there permanently SubmitFences = new VkFence[SwapchainImages.Length]; for (int i = 0; i < SubmitFences.Length; i++) { VkFenceCreateInfo fenceCreateInfo = new VkFenceCreateInfo() { sType = VkStructureType.FenceCreateInfo, pNext = null, flags = VkFenceCreateFlags.Signaled }; VkFence handle; vkCreateFence(Context.Device, &fenceCreateInfo, null, out handle); SubmitFences[i] = handle; ToDispose(new ActionDisposable(() => { vkDestroyFence(Context.Device, handle, null); })); } // Allow concrete samples to initialize their resources. InitializePermanent(); _initializingPermanent = false; InitializeFrame(); // Record commands for execution by Vulkan. RecordCommandBuffers(); }
public VkResult CreateLogicalDevice( VkPhysicalDeviceFeatures enabledFeatures, string[] enabledExtensions, bool useSwapChain = true, VkQueueFlagBits requestedQueueTypes = VkQueueFlagBits.Graphics | VkQueueFlagBits.Compute) { // Desired queues need to be requested upon logical device creation // Due to differing queue family configurations of Vulkan implementations this can be a bit tricky, especially if the application // requests different queue types var queueCreateInfos = new List <VkDeviceQueueCreateInfo>(); float defaultQueuePriority = 0.0f; // Graphics queue if ((requestedQueueTypes & VkQueueFlagBits.Graphics) != 0) { QFIndices.Graphics = GetQueueFamilyIndex(VkQueueFlagBits.Graphics); VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo(); queueInfo.sType = DeviceQueueCreateInfo; queueInfo.queueFamilyIndex = QFIndices.Graphics; queueInfo.queuePriorities = defaultQueuePriority; queueCreateInfos.Add(queueInfo); } else { QFIndices.Graphics = 0; } // Dedicated compute queue if ((requestedQueueTypes & VkQueueFlagBits.Compute) != 0) { QFIndices.Compute = GetQueueFamilyIndex(VkQueueFlagBits.Compute); if (QFIndices.Compute != QFIndices.Graphics) { // If compute family index differs, we need an additional queue create info for the compute queue VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo(); queueInfo.sType = DeviceQueueCreateInfo; queueInfo.queueFamilyIndex = QFIndices.Compute; queueInfo.queuePriorities = defaultQueuePriority; queueCreateInfos.Add(queueInfo); } } else { // Else we use the same queue QFIndices.Compute = QFIndices.Graphics; } // Dedicated transfer queue if ((requestedQueueTypes & VkQueueFlagBits.Transfer) != 0) { QFIndices.Transfer = GetQueueFamilyIndex(VkQueueFlagBits.Transfer); if (QFIndices.Transfer != QFIndices.Graphics && QFIndices.Transfer != QFIndices.Compute) { // If compute family index differs, we need an additional queue create info for the transfer queue VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo(); queueInfo.sType = DeviceQueueCreateInfo; queueInfo.queueFamilyIndex = QFIndices.Transfer; queueInfo.queuePriorities = defaultQueuePriority; queueCreateInfos.Add(queueInfo); } } else { // Else we use the same queue QFIndices.Transfer = QFIndices.Graphics; } // Create the logical device representation //using (NativeList<IntPtr> deviceExtensions = new NativeList<IntPtr>(enabledExtensions)) { var deviceExtensions = new List <string>(); if (useSwapChain) { // If the device will be used for presenting to a display via a swapchain we need to request the swapchain extension deviceExtensions.Add(Strings.VK_KHR_SWAPCHAIN_EXTENSION_NAME); } var deviceCreateInfo = VkDeviceCreateInfo.Alloc(); //deviceCreateInfo.queueCreateInfoCount = (uint)queueCreateInfos.Count; //deviceCreateInfo.pQueueCreateInfos = (VkDeviceQueueCreateInfo*)queueCreateInfos.Data.ToPointer(); //{ // VkDeviceQueueCreateInfo[] array = queueCreateInfos.ToArray(); // IntPtr ptr = IntPtr.Zero; // array.Set(ref ptr, ref deviceCreateInfo.queueCreateInfoCount); // deviceCreateInfo.pQueueCreateInfos = (VkDeviceQueueCreateInfo*)ptr; //} deviceCreateInfo->queueCreateInfos = queueCreateInfos.ToArray(); deviceCreateInfo->pEnabledFeatures = &enabledFeatures; if (deviceExtensions.Count > 0) { string[] array = deviceExtensions.ToArray(); deviceCreateInfo[0].EnabledExtensions = array; } VkDevice device; VkResult result = vkCreateDevice(PhysicalDevice, deviceCreateInfo, null, &device); this._logicalDevice = device; if (result == VkResult.Success) { // Create a default command pool for graphics command buffers CommandPool = CreateCommandPool(QFIndices.Graphics); } return(result); }