BsVulkanGpuPipelineState.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsVulkanGpuPipelineState.h"
  4. #include "BsVulkanDevice.h"
  5. #include "BsVulkanGpuProgram.h"
  6. #include "BsVulkanFramebuffer.h"
  7. #include "BsVulkanUtility.h"
  8. #include "BsRasterizerState.h"
  9. #include "BsDepthStencilState.h"
  10. #include "BsBlendState.h"
  11. #include "BsRenderStats.h"
  12. namespace BansheeEngine
  13. {
  14. VulkanPipeline::VulkanPipeline(VulkanResourceManager* owner, VkPipeline pipeline)
  15. :VulkanResource(owner, true), mPipeline(pipeline)
  16. { }
  17. VulkanPipeline::~VulkanPipeline()
  18. {
  19. vkDestroyPipeline(mOwner->getDevice().getLogical(), mPipeline, gVulkanAllocator);
  20. }
  21. VulkanGpuPipelineStateCore::VulkanGpuPipelineStateCore(const PIPELINE_STATE_CORE_DESC& desc, GpuDeviceFlags deviceMask)
  22. :GpuPipelineStateCore(desc, deviceMask)
  23. {
  24. }
  25. VulkanGpuPipelineStateCore::~VulkanGpuPipelineStateCore()
  26. {
  27. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_PipelineState);
  28. }
  29. void VulkanGpuPipelineStateCore::initialize()
  30. {
  31. std::pair<VkShaderStageFlagBits, GpuProgramCore*> stages[] =
  32. {
  33. { VK_SHADER_STAGE_VERTEX_BIT, mData.vertexProgram.get() },
  34. { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, mData.hullProgram.get() },
  35. { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, mData.domainProgram.get() },
  36. { VK_SHADER_STAGE_GEOMETRY_BIT, mData.geometryProgram.get() },
  37. { VK_SHADER_STAGE_FRAGMENT_BIT, mData.fragmentProgram.get() }
  38. };
  39. UINT32 stageOutputIdx = 0;
  40. UINT32 numStages = sizeof(stages) / sizeof(stages[0]);
  41. for(UINT32 i = 0; i < numStages; i++)
  42. {
  43. VulkanGpuProgramCore* program = static_cast<VulkanGpuProgramCore*>(stages[i].second);
  44. if (program == nullptr)
  45. continue;
  46. VkPipelineShaderStageCreateInfo& stageCI = mShaderStageInfos[stageOutputIdx];
  47. stageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  48. stageCI.pNext = nullptr;
  49. stageCI.flags = 0;
  50. stageCI.stage = stages[i].first;
  51. stageCI.module = program->getHandle();
  52. stageCI.pName = program->getProperties().getEntryPoint().c_str();
  53. stageCI.pSpecializationInfo = nullptr;
  54. stageOutputIdx++;
  55. }
  56. UINT32 numUsedStages = stageOutputIdx;
  57. bool tesselationEnabled = mData.hullProgram != nullptr && mData.domainProgram != nullptr;
  58. mInputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  59. mInputAssemblyInfo.pNext = nullptr;
  60. mInputAssemblyInfo.flags = 0;
  61. mInputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; // Assigned at runtime
  62. mInputAssemblyInfo.primitiveRestartEnable = false;
  63. mTesselationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
  64. mTesselationInfo.patchControlPoints = 3; // Assigned at runtime
  65. mViewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  66. mViewportInfo.pNext = nullptr;
  67. mViewportInfo.flags = 0;
  68. mViewportInfo.viewportCount = 1; // Spec says this need to be at least 1...
  69. mViewportInfo.scissorCount = 1;
  70. mViewportInfo.pViewports = nullptr; // Dynamic
  71. mViewportInfo.pScissors = nullptr; // Dynamic
  72. const RasterizerProperties& rstProps = getRasterizerState()->getProperties();
  73. const BlendProperties& blendProps = getBlendState()->getProperties();
  74. const DepthStencilProperties dsProps = getDepthStencilState()->getProperties();
  75. mRasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  76. mRasterizationInfo.pNext = nullptr;
  77. mRasterizationInfo.flags = 0;
  78. mRasterizationInfo.depthClampEnable = !rstProps.getDepthClipEnable();
  79. mRasterizationInfo.rasterizerDiscardEnable = VK_FALSE;
  80. mRasterizationInfo.polygonMode = VulkanUtility::getPolygonMode(rstProps.getPolygonMode());
  81. mRasterizationInfo.cullMode = VulkanUtility::getCullMode(rstProps.getCullMode());
  82. mRasterizationInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
  83. mRasterizationInfo.depthBiasEnable = rstProps.getDepthBias() != 0.0f;
  84. mRasterizationInfo.depthBiasConstantFactor = rstProps.getDepthBias();
  85. mRasterizationInfo.depthBiasSlopeFactor = rstProps.getSlopeScaledDepthBias();
  86. mRasterizationInfo.depthBiasClamp = mRasterizationInfo.depthClampEnable ? rstProps.getDepthBiasClamp() : 0.0f;
  87. mRasterizationInfo.lineWidth = 1.0f;
  88. mMultiSampleInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  89. mMultiSampleInfo.pNext = nullptr;
  90. mMultiSampleInfo.flags = 0;
  91. mMultiSampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; // Assigned at runtime
  92. mMultiSampleInfo.sampleShadingEnable = VK_FALSE; // When enabled, perform shading per sample instead of per pixel (more expensive, essentially FSAA)
  93. mMultiSampleInfo.minSampleShading = 1.0f; // Minimum percent of samples to run full shading for when sampleShadingEnable is enabled (1.0f to run for all)
  94. mMultiSampleInfo.pSampleMask = nullptr; // Normally one bit for each sample: e.g. 0x0000000F to enable all samples in a 4-sample setup
  95. mMultiSampleInfo.alphaToCoverageEnable = blendProps.getAlphaToCoverageEnabled();
  96. mMultiSampleInfo.alphaToOneEnable = VK_FALSE;
  97. VkStencilOpState stencilFrontInfo;
  98. stencilFrontInfo.compareOp = VulkanUtility::getCompareOp(dsProps.getStencilFrontCompFunc());
  99. stencilFrontInfo.depthFailOp = VulkanUtility::getStencilOp(dsProps.getStencilFrontZFailOp());
  100. stencilFrontInfo.passOp = VulkanUtility::getStencilOp(dsProps.getStencilFrontPassOp());
  101. stencilFrontInfo.failOp = VulkanUtility::getStencilOp(dsProps.getStencilFrontFailOp());
  102. stencilFrontInfo.reference = 0; // Dynamic
  103. stencilFrontInfo.compareMask = (UINT32)dsProps.getStencilReadMask();
  104. stencilFrontInfo.writeMask = (UINT32)dsProps.getStencilWriteMask();
  105. VkStencilOpState stencilBackInfo;
  106. stencilBackInfo.compareOp = VulkanUtility::getCompareOp(dsProps.getStencilBackCompFunc());
  107. stencilBackInfo.depthFailOp = VulkanUtility::getStencilOp(dsProps.getStencilBackZFailOp());
  108. stencilBackInfo.passOp = VulkanUtility::getStencilOp(dsProps.getStencilBackPassOp());
  109. stencilBackInfo.failOp = VulkanUtility::getStencilOp(dsProps.getStencilBackFailOp());
  110. stencilBackInfo.reference = 0; // Dynamic
  111. stencilBackInfo.compareMask = (UINT32)dsProps.getStencilReadMask();
  112. stencilBackInfo.writeMask = (UINT32)dsProps.getStencilWriteMask();
  113. mDepthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
  114. mDepthStencilInfo.pNext = nullptr;
  115. mDepthStencilInfo.flags = 0;
  116. mDepthStencilInfo.depthBoundsTestEnable = false;
  117. mDepthStencilInfo.minDepthBounds = 0.0f;
  118. mDepthStencilInfo.maxDepthBounds = 1.0f;
  119. mDepthStencilInfo.depthTestEnable = dsProps.getDepthReadEnable();
  120. mDepthStencilInfo.depthWriteEnable = dsProps.getDepthWriteEnable();
  121. mDepthStencilInfo.depthCompareOp = VulkanUtility::getCompareOp(dsProps.getDepthComparisonFunc());
  122. mDepthStencilInfo.front = stencilFrontInfo;
  123. mDepthStencilInfo.back = stencilBackInfo;
  124. mDepthStencilInfo.stencilTestEnable = dsProps.getStencilEnable();
  125. for(UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
  126. {
  127. UINT32 rtIdx = 0;
  128. if (blendProps.getIndependantBlendEnable())
  129. rtIdx = i;
  130. VkPipelineColorBlendAttachmentState& blendState = mAttachmentBlendStates[i];
  131. blendState.blendEnable = blendProps.getBlendEnabled(rtIdx);
  132. blendState.colorBlendOp = VulkanUtility::getBlendOp(blendProps.getBlendOperation(rtIdx));
  133. blendState.srcColorBlendFactor = VulkanUtility::getBlendFactor(blendProps.getSrcBlend(rtIdx));
  134. blendState.dstColorBlendFactor = VulkanUtility::getBlendFactor(blendProps.getDstBlend(rtIdx));
  135. blendState.alphaBlendOp = VulkanUtility::getBlendOp(blendProps.getAlphaBlendOperation(rtIdx));
  136. blendState.srcAlphaBlendFactor = VulkanUtility::getBlendFactor(blendProps.getAlphaSrcBlend(rtIdx));
  137. blendState.dstAlphaBlendFactor = VulkanUtility::getBlendFactor(blendProps.getAlphaDstBlend(rtIdx));
  138. blendState.colorWriteMask = blendProps.getRenderTargetWriteMask(rtIdx) & 0xF;
  139. }
  140. mColorBlendStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  141. mColorBlendStateInfo.pNext = nullptr;
  142. mColorBlendStateInfo.flags = 0;
  143. mColorBlendStateInfo.logicOpEnable = VK_FALSE;
  144. mColorBlendStateInfo.logicOp = VK_LOGIC_OP_NO_OP;
  145. mColorBlendStateInfo.attachmentCount = 0; // Assigned at runtime
  146. mColorBlendStateInfo.pAttachments = mAttachmentBlendStates;
  147. mColorBlendStateInfo.blendConstants[0] = 0.0f;
  148. mColorBlendStateInfo.blendConstants[1] = 0.0f;
  149. mColorBlendStateInfo.blendConstants[2] = 0.0f;
  150. mColorBlendStateInfo.blendConstants[3] = 0.0f;
  151. mDynamicStates[0] = VK_DYNAMIC_STATE_VIEWPORT;
  152. mDynamicStates[1] = VK_DYNAMIC_STATE_SCISSOR;
  153. mDynamicStates[2] = VK_DYNAMIC_STATE_STENCIL_REFERENCE;
  154. UINT32 numDynamicStates = sizeof(mDynamicStates) / sizeof(mDynamicStates[0]);
  155. assert(numDynamicStates == 3);
  156. mDynamicStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
  157. mDynamicStateInfo.pNext = nullptr;
  158. mDynamicStateInfo.flags = 0;
  159. mDynamicStateInfo.dynamicStateCount = numDynamicStates;
  160. mDynamicStateInfo.pDynamicStates = mDynamicStates;
  161. mPipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  162. mPipelineInfo.pNext = nullptr;
  163. mPipelineInfo.flags = 0;
  164. mPipelineInfo.stageCount = numUsedStages;
  165. mPipelineInfo.pStages = mShaderStageInfos;
  166. mPipelineInfo.pVertexInputState = nullptr; // Assigned at runtime
  167. mPipelineInfo.pInputAssemblyState = &mInputAssemblyInfo;
  168. mPipelineInfo.pTessellationState = tesselationEnabled ? &mTesselationInfo : nullptr;
  169. mPipelineInfo.pViewportState = &mViewportInfo;
  170. mPipelineInfo.pRasterizationState = &mRasterizationInfo;
  171. mPipelineInfo.pMultisampleState = &mMultiSampleInfo;
  172. mPipelineInfo.pDepthStencilState = nullptr; // Assigned at runtime
  173. mPipelineInfo.pColorBlendState = nullptr; // Assigned at runtime
  174. mPipelineInfo.pDynamicState = &mDynamicStateInfo;
  175. mPipelineInfo.renderPass = VK_NULL_HANDLE; // Assigned at runtime
  176. mPipelineInfo.layout = VK_NULL_HANDLE; // Assigned at runtime
  177. mPipelineInfo.subpass = 0;
  178. mPipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
  179. mPipelineInfo.basePipelineIndex = -1;
  180. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_PipelineState);
  181. GpuPipelineStateCore::initialize();
  182. }
  183. VkPipeline VulkanGpuPipelineStateCore::createPipeline(VkDevice device, VulkanFramebuffer* framebuffer,
  184. bool readOnlyDepth, DrawOperationType drawOp,
  185. VkPipelineLayout pipelineLayout,
  186. VkPipelineVertexInputStateCreateInfo* vertexInputState)
  187. {
  188. mInputAssemblyInfo.topology = VulkanUtility::getDrawOp(drawOp);
  189. mTesselationInfo.patchControlPoints = 3; // Not provided by our shaders for now
  190. mMultiSampleInfo.rasterizationSamples = framebuffer->getSampleFlags();
  191. mColorBlendStateInfo.attachmentCount = framebuffer->getNumAttachments();
  192. const DepthStencilProperties dsProps = getDepthStencilState()->getProperties();
  193. bool enableDepthWrites = dsProps.getDepthWriteEnable() && !readOnlyDepth;
  194. mDepthStencilInfo.depthWriteEnable = enableDepthWrites; // If depth stencil attachment is read only, depthWriteEnable must be VK_FALSE
  195. // Save stencil ops as we might need to change them if depth/stencil is read-only
  196. VkStencilOp oldFrontPassOp = mDepthStencilInfo.front.passOp;
  197. VkStencilOp oldFrontFailOp = mDepthStencilInfo.front.failOp;
  198. VkStencilOp oldFrontZFailOp = mDepthStencilInfo.front.depthFailOp;
  199. VkStencilOp oldBackPassOp = mDepthStencilInfo.back.passOp;
  200. VkStencilOp oldBackFailOp = mDepthStencilInfo.back.failOp;
  201. VkStencilOp oldBackZFailOp = mDepthStencilInfo.back.depthFailOp;
  202. if(!enableDepthWrites)
  203. {
  204. // Disable any stencil writes
  205. mDepthStencilInfo.front.passOp = VK_STENCIL_OP_KEEP;
  206. mDepthStencilInfo.front.failOp = VK_STENCIL_OP_KEEP;
  207. mDepthStencilInfo.front.depthFailOp = VK_STENCIL_OP_KEEP;
  208. mDepthStencilInfo.back.passOp = VK_STENCIL_OP_KEEP;
  209. mDepthStencilInfo.back.failOp = VK_STENCIL_OP_KEEP;
  210. mDepthStencilInfo.back.depthFailOp = VK_STENCIL_OP_KEEP;
  211. }
  212. mPipelineInfo.renderPass = framebuffer->getRenderPass();
  213. mPipelineInfo.layout = pipelineLayout;
  214. mPipelineInfo.pVertexInputState = vertexInputState;
  215. if (framebuffer->hasDepthAttachment())
  216. mPipelineInfo.pDepthStencilState = &mDepthStencilInfo;
  217. else
  218. mPipelineInfo.pDepthStencilState = nullptr;
  219. if (framebuffer->getNumColorAttachments() > 0)
  220. mPipelineInfo.pColorBlendState = &mColorBlendStateInfo;
  221. else
  222. mPipelineInfo.pColorBlendState = nullptr;
  223. VkPipeline pipeline;
  224. VkResult result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &mPipelineInfo, gVulkanAllocator, &pipeline);
  225. assert(result != VK_SUCCESS);
  226. // Restore previous stencil op states
  227. mDepthStencilInfo.front.passOp = oldFrontPassOp;
  228. mDepthStencilInfo.front.failOp = oldFrontFailOp;
  229. mDepthStencilInfo.front.depthFailOp = oldFrontZFailOp;
  230. mDepthStencilInfo.back.passOp = oldBackPassOp;
  231. mDepthStencilInfo.back.failOp = oldBackFailOp;
  232. mDepthStencilInfo.back.depthFailOp = oldBackZFailOp;
  233. return pipeline;
  234. }
  235. }