public SpecializationInfo(params SpecializationConstant[] constants) { uint offset = 0; entries = new VkSpecializationMapEntry[constants.Length]; for (int i = 0; i < constants.Length; i++) { entries[i] = new VkSpecializationMapEntry { constantID = constants[i].id, offset = offset, size = (UIntPtr)constants[i].Size }; offset += constants[i].Size; } int totSize = (int)offset; offset = 0; pData = Marshal.AllocHGlobal(totSize); IntPtr curPtr = pData; foreach (SpecializationConstant sc in constants) { sc.WriteTo(curPtr); curPtr += (int)sc.Size; } infos = new VkSpecializationInfo { mapEntryCount = (uint)constants.Length, pMapEntries = entries.Pin(), pData = pData, dataSize = (UIntPtr)totSize }; InfosPtr = infos.Pin(); }
public void Build(int deviceIndex) { if (!locked) { unsafe { var memHndl = SpecializationData.Pin(); var specData = new VkSpecializationInfo() { mapEntryCount = (uint)SpecializationData.Length, dataSize = (uint)SpecializationData.Length * sizeof(int), pMapEntries = Shader.Specialize(), pData = (IntPtr)memHndl.Pointer }; var specData_ptr = specData.Pointer(); var creatInfo = new VkComputePipelineCreateInfo() { sType = VkStructureType.StructureTypeComputePipelineCreateInfo, stage = new VkPipelineShaderStageCreateInfo() { sType = VkStructureType.StructureTypePipelineShaderStageCreateInfo, stage = (VkShaderStageFlags)Shader.ShaderType, module = Shader.ids[deviceIndex], pName = "main", pSpecializationInfo = specData_ptr }, layout = PipelineLayout.hndl, }; IntPtr pipeline_l = IntPtr.Zero; if (vkCreateComputePipelines(GraphicsDevice.GetDeviceInfo(deviceIndex).Device, IntPtr.Zero, 1, creatInfo.Pointer(), null, &pipeline_l) != VkResult.Success) { throw new Exception("Failed to create compute pipeline."); } hndl = pipeline_l; if (GraphicsDevice.EnableValidation) { var objName = new VkDebugUtilsObjectNameInfoEXT() { sType = VkStructureType.StructureTypeDebugUtilsObjectNameInfoExt, pObjectName = Name, objectType = VkObjectType.ObjectTypePipeline, objectHandle = (ulong)hndl }; GraphicsDevice.SetDebugUtilsObjectNameEXT(GraphicsDevice.GetDeviceInfo(deviceIndex).Device, objName.Pointer()); } devID = deviceIndex; locked = true; } } else { throw new Exception("Pipeline is locked."); } }
internal IntPtr GetNative(DisposableList <IDisposable> marshalled) { var entriesMarshalled = new MarshalledArray <VkSpecializationMapEntry>(mapEntries); var dataMarshalled = new PinnedArray <byte>(data); marshalled.Add(entriesMarshalled); marshalled.Add(dataMarshalled); var info = new VkSpecializationInfo(); info.mapEntryCount = (uint)entriesMarshalled.Count; info.pMapEntries = entriesMarshalled.Address; info.dataSize = (uint)dataMarshalled.Count; info.pData = dataMarshalled.Address; var infoMarshalled = new Marshalled <VkSpecializationInfo>(info); marshalled.Add(infoMarshalled); return(infoMarshalled.Address); }
void preparePipelines() { VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = Initializers.pipelineInputAssemblyStateCreateInfo( VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, False); VkPipelineRasterizationStateCreateInfo rasterizationState = Initializers.pipelineRasterizationStateCreateInfo( VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE, 0); VkPipelineColorBlendAttachmentState blendAttachmentState = Initializers.pipelineColorBlendAttachmentState( 0xf, False); VkPipelineColorBlendStateCreateInfo colorBlendState = Initializers.pipelineColorBlendStateCreateInfo( 1, &blendAttachmentState); VkPipelineDepthStencilStateCreateInfo depthStencilState = Initializers.pipelineDepthStencilStateCreateInfo( True, True, VK_COMPARE_OP_LESS_OR_EQUAL); VkPipelineViewportStateCreateInfo viewportState = Initializers.pipelineViewportStateCreateInfo(1, 1, 0); VkPipelineMultisampleStateCreateInfo multisampleState = Initializers.pipelineMultisampleStateCreateInfo( VK_SAMPLE_COUNT_1_BIT, 0); FixedArray3 <VkDynamicState> dynamicStateEnables = new FixedArray3 <VkDynamicState>( VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_LINE_WIDTH); VkPipelineDynamicStateCreateInfo dynamicState = Initializers.pipelineDynamicStateCreateInfo( &dynamicStateEnables.First, dynamicStateEnables.Count, 0); FixedArray2 <VkPipelineShaderStageCreateInfo> shaderStages = new FixedArray2 <VkPipelineShaderStageCreateInfo>(); VkGraphicsPipelineCreateInfo pipelineCreateInfo = Initializers.pipelineCreateInfo( pipelineLayout, 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; // Prepare specialization data SpecializationData specializationData = SpecializationData.Default; // Each shader constant of a shader stage corresponds to one map entry FixedArray2 <VkSpecializationMapEntry> specializationMapEntries = new FixedArray2 <VkSpecializationMapEntry>(); // Shader bindings based on specialization constants are marked by the new "constant_id" layout qualifier: // layout (constant_id = 0) const int LIGHTING_MODEL = 0; // layout (constant_id = 1) const float PARAM_TOON_DESATURATION = 0.0f; // Map entry for the lighting model to be used by the fragment shader specializationMapEntries.First.constantID = 0; specializationMapEntries.First.size = (UIntPtr)sizeof(uint); specializationMapEntries.First.offset = 0; // Map entry for the toon shader parameter specializationMapEntries.Second.constantID = 1; specializationMapEntries.Second.size = (UIntPtr)sizeof(float); specializationMapEntries.Second.offset = (sizeof(uint)); // Prepare specialization info block for the shader stage VkSpecializationInfo specializationInfo = new VkSpecializationInfo(); specializationInfo.dataSize = (UIntPtr)sizeof(SpecializationData); specializationInfo.mapEntryCount = specializationMapEntries.Count; specializationInfo.pMapEntries = &specializationMapEntries.First; specializationInfo.pData = &specializationData; // Create pipelines // All pipelines will use the same "uber" shader and specialization constants to change branching and parameters of that shader shaderStages.First = loadShader(getAssetPath() + "shaders/specializationconstants/uber.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); shaderStages.Second = loadShader(getAssetPath() + "shaders/specializationconstants/uber.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); // Specialization info is assigned is part of the shader stage (modul) and must be set after creating the module and before creating the pipeline shaderStages.Second.pSpecializationInfo = &specializationInfo; // Solid phong shading specializationData.lightingModel = 0; Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_phong)); // Phong and textured specializationData.lightingModel = 1; Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_toon)); // Textured discard specializationData.lightingModel = 2; Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_textured)); }
public void Build(int deviceIndex) { if (!locked) { unsafe { //create pipeline shader stages var shaderStages = new VkPipelineShaderStageCreateInfo[Shaders.Length]; var shaderSpecializations = new ManagedPtr <VkSpecializationInfo> [Shaders.Length]; var shaderSpecializationBufferPtrs = new MemoryHandle[Shaders.Length]; for (int i = 0; i < shaderStages.Length; i++) { if (SpecializationData != null) { shaderSpecializationBufferPtrs[i] = SpecializationData[i].Pin(); shaderSpecializations[i] = new VkSpecializationInfo() { mapEntryCount = (uint)SpecializationData[i].Length, pMapEntries = Shaders[i].Specialize(), dataSize = (uint)SpecializationData[i].Length * sizeof(int), pData = (IntPtr)shaderSpecializationBufferPtrs[i].Pointer }.Pointer(); } shaderStages[i].sType = VkStructureType.StructureTypePipelineShaderStageCreateInfo; shaderStages[i].stage = (VkShaderStageFlags)Shaders[i].ShaderType; shaderStages[i].module = Shaders[i].ids[deviceIndex]; shaderStages[i].pName = "main"; shaderStages[i].pSpecializationInfo = shaderSpecializations[i] != null ? shaderSpecializations[i] : IntPtr.Zero; } var shaderStages_ptr = shaderStages.Pointer(); //VkPipelineVertexInputStateCreateInfo - dummy, engine doesn't support fix function vertex input var vertexInputInfo = new VkPipelineVertexInputStateCreateInfo() { sType = VkStructureType.StructureTypePipelineVertexInputStateCreateInfo, vertexBindingDescriptionCount = 0, vertexAttributeDescriptionCount = 0, }; var vertexInputInfo_ptr = vertexInputInfo.Pointer(); //VkPipelineInputAssemblyStateCreateInfo - state var inputAssembly = new VkPipelineInputAssemblyStateCreateInfo() { sType = VkStructureType.StructureTypePipelineInputAssemblyStateCreateInfo, topology = (VkPrimitiveTopology)Topology, primitiveRestartEnable = false, }; var inputAssembly_ptr = inputAssembly.Pointer(); //VkPipelineViewportStateCreateInfo - dynamic state, no scissor var viewport = new VkViewport() { x = ViewportX, y = ViewportY, width = ViewportWidth, height = ViewportHeight, minDepth = ViewportMinDepth, maxDepth = ViewportMaxDepth, }; var scissor = new VkRect2D() { offset = new VkOffset2D() { x = (int)ViewportX, y = (int)ViewportY }, extent = new VkExtent2D() { width = ViewportWidth, height = ViewportHeight } }; var viewport_ptr = viewport.Pointer(); var scissor_ptr = scissor.Pointer(); var viewportCreateInfo = new VkPipelineViewportStateCreateInfo() { sType = VkStructureType.StructureTypePipelineViewportStateCreateInfo, viewportCount = 1, pViewports = viewport_ptr, scissorCount = 1, pScissors = scissor_ptr }; var viewportCreateInfo_ptr = viewportCreateInfo.Pointer(); //VkPipelineRasterizationStateCreateInfo - state var rasterizer = new VkPipelineRasterizationStateCreateInfo() { sType = VkStructureType.StructureTypePipelineRasterizationStateCreateInfo, depthClampEnable = DepthClamp, rasterizerDiscardEnable = RasterizerDiscard, polygonMode = (VkPolygonMode)Fill, lineWidth = LineWidth, cullMode = (VkCullModeFlags)CullMode, frontFace = VkFrontFace.FrontFaceCounterClockwise, //OpenGL default depthBiasEnable = false, depthBiasConstantFactor = 0, depthBiasClamp = 0, depthBiasSlopeFactor = 0, }; var rasterizer_ptr = rasterizer.Pointer(); //VkPipelineMultisampleStateCreateInfo - don't support for now var multisampling = new VkPipelineMultisampleStateCreateInfo() { sType = VkStructureType.StructureTypePipelineMultisampleStateCreateInfo, sampleShadingEnable = false, rasterizationSamples = VkSampleCountFlags.SampleCount1Bit, minSampleShading = 1, pSampleMask = null, alphaToCoverageEnable = false, alphaToOneEnable = false }; var multisampling_ptr = multisampling.Pointer(); //VkPipelineDepthStencilStateCreateInfo - state var depthStencil = new VkPipelineDepthStencilStateCreateInfo() { sType = VkStructureType.StructureTypePipelineDepthStencilStateCreateInfo, depthTestEnable = true, depthCompareOp = (VkCompareOp)DepthTest, depthWriteEnable = DepthWrite, depthBoundsTestEnable = false, stencilTestEnable = false, maxDepthBounds = ViewportMaxDepth, minDepthBounds = ViewportMinDepth, }; var depthStencil_ptr = depthStencil.Pointer(); //VkPipelineColorBlendStateCreateInfo - state var colorBlendStates = new VkPipelineColorBlendAttachmentState[RenderPass.ColorAttachments == null ? 0 : RenderPass.ColorAttachments.Length]; for (int i = 0; i < colorBlendStates.Length; i++) { colorBlendStates[i] = new VkPipelineColorBlendAttachmentState() { colorWriteMask = VkColorComponentFlags.ColorComponentRBit | VkColorComponentFlags.ColorComponentGBit | VkColorComponentFlags.ColorComponentBBit | VkColorComponentFlags.ColorComponentABit, blendEnable = false, }; } var colorBlendStates_ptr = colorBlendStates.Pointer(); var colorBlend = new VkPipelineColorBlendStateCreateInfo() { sType = VkStructureType.StructureTypePipelineColorBlendStateCreateInfo, logicOpEnable = false, logicOp = VkLogicOp.LogicOpCopy, attachmentCount = (uint)colorBlendStates.Length, pAttachments = colorBlendStates_ptr, }; colorBlend.blendConstants[0] = 0; colorBlend.blendConstants[1] = 0; colorBlend.blendConstants[2] = 0; colorBlend.blendConstants[3] = 0; var colorBlend_ptr = colorBlend.Pointer(); var dynamicStates = stackalloc VkDynamicState[] { VkDynamicState.DynamicStateViewport }; var dynamicState = new VkPipelineDynamicStateCreateInfo() { sType = VkStructureType.StructureTypePipelineDynamicStateCreateInfo, dynamicStateCount = ViewportDynamic ? 1u : 0u, pDynamicStates = dynamicStates }; var dynamicState_ptr = dynamicState.Pointer(); //Setup graphics pipeline var pipelineInfo = new VkGraphicsPipelineCreateInfo() { sType = VkStructureType.StructureTypeGraphicsPipelineCreateInfo, stageCount = (uint)shaderStages.Length, pStages = shaderStages_ptr, pVertexInputState = vertexInputInfo_ptr, pInputAssemblyState = inputAssembly_ptr, pViewportState = viewportCreateInfo_ptr, pRasterizationState = rasterizer_ptr, pMultisampleState = multisampling_ptr, pDepthStencilState = depthStencil_ptr, pColorBlendState = colorBlend_ptr, pDynamicState = dynamicState_ptr, layout = PipelineLayout.hndl, renderPass = RenderPass.hndl, subpass = 0, basePipelineHandle = IntPtr.Zero, basePipelineIndex = -1, }; IntPtr pipeline_l = IntPtr.Zero; if (vkCreateGraphicsPipelines(GraphicsDevice.GetDeviceInfo(deviceIndex).Device, IntPtr.Zero, 1, pipelineInfo.Pointer(), null, &pipeline_l) != VkResult.Success) { throw new Exception("Failed to create graphics pipeline."); } hndl = pipeline_l; if (GraphicsDevice.EnableValidation) { var objName = new VkDebugUtilsObjectNameInfoEXT() { sType = VkStructureType.StructureTypeDebugUtilsObjectNameInfoExt, pObjectName = Name, objectType = VkObjectType.ObjectTypePipeline, objectHandle = (ulong)hndl }; GraphicsDevice.SetDebugUtilsObjectNameEXT(GraphicsDevice.GetDeviceInfo(deviceIndex).Device, objName.Pointer()); } devID = deviceIndex; locked = true; } } else { throw new Exception("Pipeline is locked."); } }