public void Set(params VkVertexInputAttributeDescription[] value) { IntPtr ptr = (IntPtr)this.pointer; value.Set(ref ptr, ref this.count); this.pointer = (VkVertexInputAttributeDescription *)ptr; }
public VkVertexInputAttributeDescriptionGroup(params VkVertexInputAttributeDescription[] value) { this.count = 0; this.pointer = null; if (value != null) { IntPtr ptr = IntPtr.Zero; value.Set(ref ptr, ref this.count); this.pointer = (VkVertexInputAttributeDescription *)ptr; } }
void setupVertexDescriptions() { // Binding description bindingDescs = new VkVertexInputBindingDescription[1]; bindingDescs[0].binding = VERTEX_BUFFER_BIND_ID; bindingDescs[0].stride = vertexLayout.stride(); bindingDescs[0].inputRate = VkVertexInputRate.Vertex;// VK_VERTEX_INPUT_RATE_VERTEX; // Attribute descriptions attributeDescs = VkVertexInputAttributeDescription.Alloc(4); // Location 0 : Position attributeDescs[0].binding = VERTEX_BUFFER_BIND_ID; attributeDescs[0].location = 0; attributeDescs[0].format = VkFormat.R32g32b32Sfloat;// VK_FORMAT_R32G32B32_SFLOAT, attributeDescs[0].offset = 0; // Location 1 : Texture coordinates attributeDescs[1].binding = VERTEX_BUFFER_BIND_ID; attributeDescs[1].location = 1; attributeDescs[1].format = VkFormat.R32g32Sfloat;// VK_FORMAT_R32G32_SFLOAT, attributeDescs[1].offset = sizeof(float) * 3; // Location 2 : Color attributeDescs[2].binding = VERTEX_BUFFER_BIND_ID; attributeDescs[2].location = 2; attributeDescs[2].format = VkFormat.R32g32b32Sfloat;// VK_FORMAT_R32G32B32_SFLOAT, attributeDescs[2].offset = sizeof(float) * 5; // Location 3 : Normal attributeDescs[3].binding = VERTEX_BUFFER_BIND_ID; attributeDescs[3].location = 3; attributeDescs[3].format = VkFormat.R32g32b32Sfloat;// VK_FORMAT_R32G32B32_SFLOAT, attributeDescs[3].offset = sizeof(float) * 8; inputInfo = VkPipelineVertexInputStateCreateInfo.Alloc(); inputInfo[0].vertexBindingDescriptions = bindingDescs; inputInfo[0].vertexAttributeDescriptions.count = 4; inputInfo[0].vertexAttributeDescriptions.pointer = attributeDescs; }
public VkPipeline(VkGraphicsDevice gd, ref GraphicsPipelineDescription description) : base(ref description) { _gd = gd; IsComputePipeline = false; RefCount = new ResourceRefCount(DisposeCore); 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.compareOp = VkFormats.VdToVkCompareOp(vdDssDesc.StencilFront.Comparison); 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.compareOp = VkFormats.VdToVkCompareOp(vdDssDesc.StencilBack.Comparison); 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; multisampleCI.alphaToCoverageEnable = description.BlendState.AlphaToCoverageEnabled; 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 = inputElement.Offset != 0 ? inputElement.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 VkSpecializationInfo specializationInfo; SpecializationConstant[] specDescs = description.ShaderSet.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[] 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 stageCI.pName = new FixedUtf8String(shader.EntryPoint); // TODO: DONT ALLOCATE HERE stageCI.pSpecializationInfo = &specializationInfo; 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; 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; DynamicOffsetsCount = 0; foreach (VkResourceLayout layout in description.ResourceLayouts) { DynamicOffsetsCount += layout.DynamicBufferCount; } }
public VkPipeline(VkGraphicsDevice gd, ref PipelineDescription description) { _gd = gd; 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 = VkFrontFace.Clockwise; rsCI.lineWidth = 1f; pipelineCI.pRasterizationState = &rsCI; // 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.ComparisonKind); pipelineCI.pDepthStencilState = &dssCI; // Multisample VkPipelineMultisampleStateCreateInfo multisampleCI = VkPipelineMultisampleStateCreateInfo.New(); multisampleCI.rasterizationSamples = VkSampleCountFlags.Count1; 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[targetIndex] = new VkVertexInputBindingDescription() { binding = (uint)binding, inputRate = (inputDesc.Elements[0].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 ShaderStageDescription[] stageDescs = description.ShaderSet.ShaderStages; StackList <VkPipelineShaderStageCreateInfo> stages = new StackList <VkPipelineShaderStageCreateInfo>(); foreach (ShaderStageDescription stageDesc in stageDescs) { VkShader vkShader = Util.AssertSubtype <Shader, VkShader>(stageDesc.Shader); VkPipelineShaderStageCreateInfo stageCI = VkPipelineShaderStageCreateInfo.New(); stageCI.module = vkShader.ShaderModule; stageCI.stage = VkFormats.VdToVkShaderStages(stageDesc.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; if (outputDesc.ColorAttachments.Length > 1) { throw new NotImplementedException("Laziness"); } VkAttachmentDescription colorAttachmentDesc = new VkAttachmentDescription(); colorAttachmentDesc.format = outputDesc.ColorAttachments.Length > 0 ? VkFormats.VdToVkPixelFormat(outputDesc.ColorAttachments[0].Format) : 0; colorAttachmentDesc.samples = VkSampleCountFlags.Count1; colorAttachmentDesc.loadOp = VkAttachmentLoadOp.Clear; colorAttachmentDesc.storeOp = VkAttachmentStoreOp.Store; colorAttachmentDesc.stencilLoadOp = VkAttachmentLoadOp.DontCare; colorAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare; colorAttachmentDesc.initialLayout = VkImageLayout.Undefined; colorAttachmentDesc.finalLayout = VkImageLayout.PresentSrcKHR; VkAttachmentReference colorAttachmentRef = new VkAttachmentReference(); colorAttachmentRef.attachment = 0; colorAttachmentRef.layout = VkImageLayout.ColorAttachmentOptimal; VkAttachmentDescription depthAttachmentDesc = new VkAttachmentDescription(); VkAttachmentReference depthAttachmentRef = new VkAttachmentReference(); if (outputDesc.DepthAttachment != null) { depthAttachmentDesc.format = VkFormats.VdToVkPixelFormat(outputDesc.DepthAttachment.Value.Format, toDepthFormat: true); depthAttachmentDesc.samples = VkSampleCountFlags.Count1; depthAttachmentDesc.loadOp = VkAttachmentLoadOp.Clear; depthAttachmentDesc.storeOp = VkAttachmentStoreOp.Store; depthAttachmentDesc.stencilLoadOp = VkAttachmentLoadOp.DontCare; depthAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare; depthAttachmentDesc.initialLayout = VkImageLayout.Undefined; depthAttachmentDesc.finalLayout = VkImageLayout.DepthStencilAttachmentOptimal; depthAttachmentRef.attachment = outputDesc.ColorAttachments.Length == 0 ? 0u : 1u; depthAttachmentRef.layout = VkImageLayout.DepthStencilAttachmentOptimal; } VkSubpassDescription subpass = new VkSubpassDescription(); StackList <VkAttachmentDescription, Size512Bytes> attachments = new StackList <VkAttachmentDescription, Size512Bytes>(); subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics; if (outputDesc.ColorAttachments.Length > 0) { subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &colorAttachmentRef; attachments.Add(colorAttachmentDesc); } 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 CreateNewGraphicsPipeline(ref VkPipelineCacheKey cacheKey) { VkGraphicsPipelineCreateInfo pipelineCI = VkGraphicsPipelineCreateInfo.New(); // RenderPass pipelineCI.renderPass = cacheKey.RenderPass; pipelineCI.subpass = 0; pipelineCI.layout = cacheKey.PipelineLayout; // DynamicState 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; // ColorBlendState VkPipelineColorBlendAttachmentState colorBlendAttachementState = new VkPipelineColorBlendAttachmentState(); colorBlendAttachementState.colorWriteMask = VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A; colorBlendAttachementState.blendEnable = cacheKey.BlendState.IsBlendEnabled; colorBlendAttachementState.srcColorBlendFactor = VkFormats.VeldridToVkBlendFactor(cacheKey.BlendState.SourceColorBlend); colorBlendAttachementState.dstColorBlendFactor = VkFormats.VeldridToVkBlendFactor(cacheKey.BlendState.DestinationColorBlend); colorBlendAttachementState.colorBlendOp = VkFormats.VeldridToVkBlendOp(cacheKey.BlendState.ColorBlendFunction); colorBlendAttachementState.srcAlphaBlendFactor = VkFormats.VeldridToVkBlendFactor(cacheKey.BlendState.SourceAlphaBlend); colorBlendAttachementState.dstAlphaBlendFactor = VkFormats.VeldridToVkBlendFactor(cacheKey.BlendState.DestinationAlphaBlend); colorBlendAttachementState.alphaBlendOp = VkFormats.VeldridToVkBlendOp(cacheKey.BlendState.AlphaBlendFunction); VkPipelineColorBlendStateCreateInfo colorBlendStateCI = VkPipelineColorBlendStateCreateInfo.New(); if (cacheKey.Framebuffer.ColorTexture != null) { colorBlendStateCI.attachmentCount = 1; colorBlendStateCI.pAttachments = &colorBlendAttachementState; colorBlendStateCI.blendConstants_0 = cacheKey.BlendState.BlendFactor.R; colorBlendStateCI.blendConstants_1 = cacheKey.BlendState.BlendFactor.G; colorBlendStateCI.blendConstants_2 = cacheKey.BlendState.BlendFactor.B; colorBlendStateCI.blendConstants_3 = cacheKey.BlendState.BlendFactor.A; pipelineCI.pColorBlendState = &colorBlendStateCI; } // DepthStencilState VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = VkPipelineDepthStencilStateCreateInfo.New(); depthStencilStateCI.depthCompareOp = VkFormats.VeldridToVkDepthComparison(cacheKey.DepthStencilState.DepthComparison); depthStencilStateCI.depthWriteEnable = cacheKey.DepthStencilState.IsDepthWriteEnabled; depthStencilStateCI.depthTestEnable = cacheKey.DepthStencilState.IsDepthEnabled; pipelineCI.pDepthStencilState = &depthStencilStateCI; // MultisampleState VkPipelineMultisampleStateCreateInfo multisampleStateCI = VkPipelineMultisampleStateCreateInfo.New(); multisampleStateCI.rasterizationSamples = VkSampleCountFlags.Count1; pipelineCI.pMultisampleState = &multisampleStateCI; // RasterizationState VkPipelineRasterizationStateCreateInfo rasterizationStateCI = ((VkRasterizerState)cacheKey.RasterizerState).RasterizerStateCreateInfo; rasterizationStateCI.lineWidth = 1f; pipelineCI.pRasterizationState = &rasterizationStateCI; // ViewportState VkPipelineViewportStateCreateInfo viewportStateCI = VkPipelineViewportStateCreateInfo.New(); viewportStateCI.viewportCount = 1; viewportStateCI.scissorCount = 1; pipelineCI.pViewportState = &viewportStateCI; // InputAssemblyState VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = VkPipelineInputAssemblyStateCreateInfo.New(); inputAssemblyStateCI.topology = cacheKey.PrimitiveTopology; pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; // VertexInputState VkPipelineVertexInputStateCreateInfo vertexInputStateCI = VkPipelineVertexInputStateCreateInfo.New(); VertexInputDescription[] inputDescriptions = cacheKey.ShaderSet.InputLayout.InputDescriptions; uint bindingCount = (uint)inputDescriptions.Length; uint attributeCount = (uint)inputDescriptions.Sum(desc => desc.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++) { VertexInputDescription inputDesc = inputDescriptions[binding]; bindingDescs[targetIndex] = new VkVertexInputBindingDescription() { binding = (uint)binding, inputRate = (inputDesc.Elements[0].StorageClassifier == VertexElementInputClass.PerInstance) ? VkVertexInputRate.Instance : VkVertexInputRate.Vertex, stride = ((VkVertexBuffer)cacheKey.VertexBindings[binding]).Stride }; uint currentOffset = 0; for (int location = 0; location < inputDesc.Elements.Length; location++) { VertexInputElement inputElement = inputDesc.Elements[location]; attributeDescs[targetIndex] = new VkVertexInputAttributeDescription() { format = VkFormats.VeldridToVkVertexElementFormat(inputElement.ElementFormat), binding = (uint)binding, location = (uint)(targetLocation + location), offset = currentOffset }; targetIndex += 1; currentOffset += inputElement.SizeInBytes; } targetLocation += inputDesc.Elements.Length; } vertexInputStateCI.vertexBindingDescriptionCount = bindingCount; vertexInputStateCI.pVertexBindingDescriptions = bindingDescs; vertexInputStateCI.vertexAttributeDescriptionCount = attributeCount; vertexInputStateCI.pVertexAttributeDescriptions = attributeDescs; pipelineCI.pVertexInputState = &vertexInputStateCI; // ShaderStage StackList <VkPipelineShaderStageCreateInfo> shaderStageCIs = new StackList <VkPipelineShaderStageCreateInfo>(); VkPipelineShaderStageCreateInfo vertexStage = VkPipelineShaderStageCreateInfo.New(); vertexStage.stage = VkShaderStageFlags.Vertex; vertexStage.module = cacheKey.ShaderSet.VertexShader.ShaderModule; vertexStage.pName = CommonStrings.main; shaderStageCIs.Add(vertexStage); VkPipelineShaderStageCreateInfo fragmentStage = VkPipelineShaderStageCreateInfo.New(); fragmentStage.stage = VkShaderStageFlags.Fragment; fragmentStage.module = cacheKey.ShaderSet.FragmentShader.ShaderModule; fragmentStage.pName = CommonStrings.main; shaderStageCIs.Add(fragmentStage); if (cacheKey.ShaderSet.TessellationControlShader != null) { VkPipelineShaderStageCreateInfo tcStage = VkPipelineShaderStageCreateInfo.New(); tcStage.stage = VkShaderStageFlags.TessellationControl; tcStage.module = cacheKey.ShaderSet.TessellationControlShader.ShaderModule; tcStage.pName = CommonStrings.main; shaderStageCIs.Add(tcStage); } if (cacheKey.ShaderSet.TessellationEvaluationShader != null) { VkPipelineShaderStageCreateInfo teStage = VkPipelineShaderStageCreateInfo.New(); teStage.stage = VkShaderStageFlags.TessellationEvaluation; teStage.module = cacheKey.ShaderSet.TessellationEvaluationShader.ShaderModule; teStage.pName = CommonStrings.main; shaderStageCIs.Add(teStage); } if (cacheKey.ShaderSet.GeometryShader != null) { VkPipelineShaderStageCreateInfo geometryStage = VkPipelineShaderStageCreateInfo.New(); geometryStage.stage = VkShaderStageFlags.Geometry; geometryStage.module = cacheKey.ShaderSet.GeometryShader.ShaderModule; geometryStage.pName = CommonStrings.main; shaderStageCIs.Add(geometryStage); } pipelineCI.stageCount = shaderStageCIs.Count; pipelineCI.pStages = (VkPipelineShaderStageCreateInfo *)shaderStageCIs.Data; VkResult result = vkCreateGraphicsPipelines(_device, VkPipelineCache.Null, 1, ref pipelineCI, null, out VkPipeline ret); CheckResult(result); return(ret); }
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); } } }