BsVulkanGpuPipelineState.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  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 "BsVulkanRenderAPI.h"
  9. #include "BsVulkanGpuPipelineParamInfo.h"
  10. #include "Managers/BsVulkanVertexInputManager.h"
  11. #include "BsVulkanCommandBuffer.h"
  12. #include "Renderapi/BsRasterizerState.h"
  13. #include "Renderapi/BsDepthStencilState.h"
  14. #include "Renderapi/BsBlendState.h"
  15. #include "Profiling/BsRenderStats.h"
  16. namespace bs { namespace ct
  17. {
  18. VulkanPipeline::VulkanPipeline(VulkanResourceManager* owner, VkPipeline pipeline,
  19. const std::array<bool, BS_MAX_MULTIPLE_RENDER_TARGETS>& colorReadOnly, bool depthStencilReadOnly)
  20. : VulkanResource(owner, true), mPipeline(pipeline), mReadOnlyColor(colorReadOnly)
  21. , mReadOnlyDepth(depthStencilReadOnly)
  22. { }
  23. VulkanPipeline::VulkanPipeline(VulkanResourceManager* owner, VkPipeline pipeline)
  24. : VulkanResource(owner, true), mPipeline(pipeline), mReadOnlyColor(), mReadOnlyDepth(false)
  25. { }
  26. VulkanPipeline::~VulkanPipeline()
  27. {
  28. vkDestroyPipeline(mOwner->getDevice().getLogical(), mPipeline, gVulkanAllocator);
  29. }
  30. VulkanGraphicsPipelineState::GpuPipelineKey::GpuPipelineKey(
  31. UINT32 framebufferId, UINT32 vertexInputId, UINT32 readOnlyFlags, DrawOperationType drawOp)
  32. : framebufferId(framebufferId), vertexInputId(vertexInputId), readOnlyFlags(readOnlyFlags)
  33. , drawOp(drawOp)
  34. {
  35. }
  36. size_t VulkanGraphicsPipelineState::HashFunc::operator()(const GpuPipelineKey& key) const
  37. {
  38. size_t hash = 0;
  39. hash_combine(hash, key.framebufferId);
  40. hash_combine(hash, key.vertexInputId);
  41. hash_combine(hash, key.readOnlyFlags);
  42. hash_combine(hash, key.drawOp);
  43. return hash;
  44. }
  45. bool VulkanGraphicsPipelineState::EqualFunc::operator()(const GpuPipelineKey& a, const GpuPipelineKey& b) const
  46. {
  47. if (a.framebufferId != b.framebufferId)
  48. return false;
  49. if (a.vertexInputId != b.vertexInputId)
  50. return false;
  51. if (a.readOnlyFlags != b.readOnlyFlags)
  52. return false;
  53. if (a.drawOp != b.drawOp)
  54. return false;
  55. return true;
  56. }
  57. VulkanGraphicsPipelineState::VulkanGraphicsPipelineState(const PIPELINE_STATE_DESC& desc,
  58. GpuDeviceFlags deviceMask)
  59. :GraphicsPipelineState(desc, deviceMask), mScissorEnabled(false), mDeviceMask(deviceMask)
  60. {
  61. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  62. {
  63. mPerDeviceData[i].device = nullptr;
  64. mPerDeviceData[i].pipelineLayout = VK_NULL_HANDLE;
  65. }
  66. }
  67. VulkanGraphicsPipelineState::~VulkanGraphicsPipelineState()
  68. {
  69. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  70. {
  71. if (mPerDeviceData[i].device == nullptr)
  72. continue;
  73. for(auto& entry : mPerDeviceData[i].pipelines)
  74. entry.second->destroy();
  75. }
  76. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_PipelineState);
  77. }
  78. void VulkanGraphicsPipelineState::initialize()
  79. {
  80. Lock(mMutex);
  81. GraphicsPipelineState::initialize();
  82. std::pair<VkShaderStageFlagBits, GpuProgram*> stages[] =
  83. {
  84. { VK_SHADER_STAGE_VERTEX_BIT, mData.vertexProgram.get() },
  85. { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, mData.hullProgram.get() },
  86. { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, mData.domainProgram.get() },
  87. { VK_SHADER_STAGE_GEOMETRY_BIT, mData.geometryProgram.get() },
  88. { VK_SHADER_STAGE_FRAGMENT_BIT, mData.fragmentProgram.get() }
  89. };
  90. UINT32 stageOutputIdx = 0;
  91. UINT32 numStages = sizeof(stages) / sizeof(stages[0]);
  92. for(UINT32 i = 0; i < numStages; i++)
  93. {
  94. VulkanGpuProgram* program = static_cast<VulkanGpuProgram*>(stages[i].second);
  95. if (program == nullptr)
  96. continue;
  97. VkPipelineShaderStageCreateInfo& stageCI = mShaderStageInfos[stageOutputIdx];
  98. stageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  99. stageCI.pNext = nullptr;
  100. stageCI.flags = 0;
  101. stageCI.stage = stages[i].first;
  102. stageCI.module = VK_NULL_HANDLE;
  103. stageCI.pName = program->getProperties().getEntryPoint().c_str();
  104. stageCI.pSpecializationInfo = nullptr;
  105. stageOutputIdx++;
  106. }
  107. UINT32 numUsedStages = stageOutputIdx;
  108. bool tesselationEnabled = mData.hullProgram != nullptr && mData.domainProgram != nullptr;
  109. mInputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  110. mInputAssemblyInfo.pNext = nullptr;
  111. mInputAssemblyInfo.flags = 0;
  112. mInputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; // Assigned at runtime
  113. mInputAssemblyInfo.primitiveRestartEnable = false;
  114. mTesselationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
  115. mTesselationInfo.pNext = nullptr;
  116. mTesselationInfo.flags = 0;
  117. mTesselationInfo.patchControlPoints = 3; // Assigned at runtime
  118. mViewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  119. mViewportInfo.pNext = nullptr;
  120. mViewportInfo.flags = 0;
  121. mViewportInfo.viewportCount = 1; // Spec says this need to be at least 1...
  122. mViewportInfo.scissorCount = 1;
  123. mViewportInfo.pViewports = nullptr; // Dynamic
  124. mViewportInfo.pScissors = nullptr; // Dynamic
  125. RasterizerState* rasterizerState = getRasterizerState().get();
  126. if (rasterizerState == nullptr)
  127. rasterizerState = RasterizerState::getDefault().get();
  128. BlendState* blendState = getBlendState().get();
  129. if (blendState == nullptr)
  130. blendState = BlendState::getDefault().get();
  131. DepthStencilState* depthStencilState = getDepthStencilState().get();
  132. if (depthStencilState == nullptr)
  133. depthStencilState = DepthStencilState::getDefault().get();
  134. const RasterizerProperties& rstProps = rasterizerState->getProperties();
  135. const BlendProperties& blendProps = blendState->getProperties();
  136. const DepthStencilProperties dsProps = depthStencilState->getProperties();
  137. mRasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  138. mRasterizationInfo.pNext = nullptr;
  139. mRasterizationInfo.flags = 0;
  140. mRasterizationInfo.depthClampEnable = !rstProps.getDepthClipEnable();
  141. mRasterizationInfo.rasterizerDiscardEnable = VK_FALSE;
  142. mRasterizationInfo.polygonMode = VulkanUtility::getPolygonMode(rstProps.getPolygonMode());
  143. mRasterizationInfo.cullMode = VulkanUtility::getCullMode(rstProps.getCullMode());
  144. mRasterizationInfo.frontFace = VK_FRONT_FACE_CLOCKWISE;
  145. mRasterizationInfo.depthBiasEnable = rstProps.getDepthBias() != 0.0f;
  146. mRasterizationInfo.depthBiasConstantFactor = rstProps.getDepthBias();
  147. mRasterizationInfo.depthBiasSlopeFactor = rstProps.getSlopeScaledDepthBias();
  148. mRasterizationInfo.depthBiasClamp = mRasterizationInfo.depthClampEnable ? rstProps.getDepthBiasClamp() : 0.0f;
  149. mRasterizationInfo.lineWidth = 1.0f;
  150. mMultiSampleInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  151. mMultiSampleInfo.pNext = nullptr;
  152. mMultiSampleInfo.flags = 0;
  153. mMultiSampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; // Assigned at runtime
  154. mMultiSampleInfo.sampleShadingEnable = VK_FALSE; // When enabled, perform shading per sample instead of per pixel (more expensive, essentially FSAA)
  155. mMultiSampleInfo.minSampleShading = 1.0f; // Minimum percent of samples to run full shading for when sampleShadingEnable is enabled (1.0f to run for all)
  156. mMultiSampleInfo.pSampleMask = nullptr; // Normally one bit for each sample: e.g. 0x0000000F to enable all samples in a 4-sample setup
  157. mMultiSampleInfo.alphaToCoverageEnable = blendProps.getAlphaToCoverageEnabled();
  158. mMultiSampleInfo.alphaToOneEnable = VK_FALSE;
  159. VkStencilOpState stencilFrontInfo;
  160. stencilFrontInfo.compareOp = VulkanUtility::getCompareOp(dsProps.getStencilFrontCompFunc());
  161. stencilFrontInfo.depthFailOp = VulkanUtility::getStencilOp(dsProps.getStencilFrontZFailOp());
  162. stencilFrontInfo.passOp = VulkanUtility::getStencilOp(dsProps.getStencilFrontPassOp());
  163. stencilFrontInfo.failOp = VulkanUtility::getStencilOp(dsProps.getStencilFrontFailOp());
  164. stencilFrontInfo.reference = 0; // Dynamic
  165. stencilFrontInfo.compareMask = (UINT32)dsProps.getStencilReadMask();
  166. stencilFrontInfo.writeMask = (UINT32)dsProps.getStencilWriteMask();
  167. VkStencilOpState stencilBackInfo;
  168. stencilBackInfo.compareOp = VulkanUtility::getCompareOp(dsProps.getStencilBackCompFunc());
  169. stencilBackInfo.depthFailOp = VulkanUtility::getStencilOp(dsProps.getStencilBackZFailOp());
  170. stencilBackInfo.passOp = VulkanUtility::getStencilOp(dsProps.getStencilBackPassOp());
  171. stencilBackInfo.failOp = VulkanUtility::getStencilOp(dsProps.getStencilBackFailOp());
  172. stencilBackInfo.reference = 0; // Dynamic
  173. stencilBackInfo.compareMask = (UINT32)dsProps.getStencilReadMask();
  174. stencilBackInfo.writeMask = (UINT32)dsProps.getStencilWriteMask();
  175. mDepthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
  176. mDepthStencilInfo.pNext = nullptr;
  177. mDepthStencilInfo.flags = 0;
  178. mDepthStencilInfo.depthBoundsTestEnable = false;
  179. mDepthStencilInfo.minDepthBounds = 0.0f;
  180. mDepthStencilInfo.maxDepthBounds = 1.0f;
  181. mDepthStencilInfo.depthTestEnable = dsProps.getDepthReadEnable();
  182. mDepthStencilInfo.depthWriteEnable = dsProps.getDepthWriteEnable();
  183. mDepthStencilInfo.depthCompareOp = VulkanUtility::getCompareOp(dsProps.getDepthComparisonFunc());
  184. mDepthStencilInfo.front = stencilFrontInfo;
  185. mDepthStencilInfo.back = stencilBackInfo;
  186. mDepthStencilInfo.stencilTestEnable = dsProps.getStencilEnable();
  187. for(UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
  188. {
  189. UINT32 rtIdx = 0;
  190. if (blendProps.getIndependantBlendEnable())
  191. rtIdx = i;
  192. VkPipelineColorBlendAttachmentState& blendState = mAttachmentBlendStates[i];
  193. blendState.blendEnable = blendProps.getBlendEnabled(rtIdx);
  194. blendState.colorBlendOp = VulkanUtility::getBlendOp(blendProps.getBlendOperation(rtIdx));
  195. blendState.srcColorBlendFactor = VulkanUtility::getBlendFactor(blendProps.getSrcBlend(rtIdx));
  196. blendState.dstColorBlendFactor = VulkanUtility::getBlendFactor(blendProps.getDstBlend(rtIdx));
  197. blendState.alphaBlendOp = VulkanUtility::getBlendOp(blendProps.getAlphaBlendOperation(rtIdx));
  198. blendState.srcAlphaBlendFactor = VulkanUtility::getBlendFactor(blendProps.getAlphaSrcBlend(rtIdx));
  199. blendState.dstAlphaBlendFactor = VulkanUtility::getBlendFactor(blendProps.getAlphaDstBlend(rtIdx));
  200. blendState.colorWriteMask = blendProps.getRenderTargetWriteMask(rtIdx) & 0xF;
  201. }
  202. mColorBlendStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  203. mColorBlendStateInfo.pNext = nullptr;
  204. mColorBlendStateInfo.flags = 0;
  205. mColorBlendStateInfo.logicOpEnable = VK_FALSE;
  206. mColorBlendStateInfo.logicOp = VK_LOGIC_OP_NO_OP;
  207. mColorBlendStateInfo.attachmentCount = 0; // Assigned at runtime
  208. mColorBlendStateInfo.pAttachments = mAttachmentBlendStates;
  209. mColorBlendStateInfo.blendConstants[0] = 0.0f;
  210. mColorBlendStateInfo.blendConstants[1] = 0.0f;
  211. mColorBlendStateInfo.blendConstants[2] = 0.0f;
  212. mColorBlendStateInfo.blendConstants[3] = 0.0f;
  213. mDynamicStates[0] = VK_DYNAMIC_STATE_VIEWPORT;
  214. mDynamicStates[1] = VK_DYNAMIC_STATE_SCISSOR;
  215. mDynamicStates[2] = VK_DYNAMIC_STATE_STENCIL_REFERENCE;
  216. UINT32 numDynamicStates = sizeof(mDynamicStates) / sizeof(mDynamicStates[0]);
  217. assert(numDynamicStates == 3);
  218. mDynamicStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
  219. mDynamicStateInfo.pNext = nullptr;
  220. mDynamicStateInfo.flags = 0;
  221. mDynamicStateInfo.dynamicStateCount = numDynamicStates;
  222. mDynamicStateInfo.pDynamicStates = mDynamicStates;
  223. mPipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  224. mPipelineInfo.pNext = nullptr;
  225. mPipelineInfo.flags = 0;
  226. mPipelineInfo.stageCount = numUsedStages;
  227. mPipelineInfo.pStages = mShaderStageInfos;
  228. mPipelineInfo.pVertexInputState = nullptr; // Assigned at runtime
  229. mPipelineInfo.pInputAssemblyState = &mInputAssemblyInfo;
  230. mPipelineInfo.pTessellationState = tesselationEnabled ? &mTesselationInfo : nullptr;
  231. mPipelineInfo.pViewportState = &mViewportInfo;
  232. mPipelineInfo.pRasterizationState = &mRasterizationInfo;
  233. mPipelineInfo.pMultisampleState = &mMultiSampleInfo;
  234. mPipelineInfo.pDepthStencilState = nullptr; // Assigned at runtime
  235. mPipelineInfo.pColorBlendState = nullptr; // Assigned at runtime
  236. mPipelineInfo.pDynamicState = &mDynamicStateInfo;
  237. mPipelineInfo.renderPass = VK_NULL_HANDLE; // Assigned at runtime
  238. mPipelineInfo.layout = VK_NULL_HANDLE; // Assigned at runtime
  239. mPipelineInfo.subpass = 0;
  240. mPipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
  241. mPipelineInfo.basePipelineIndex = -1;
  242. mScissorEnabled = rstProps.getScissorEnable();
  243. if(mData.vertexProgram != nullptr)
  244. mVertexDecl = mData.vertexProgram->getInputDeclaration();
  245. VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPI::instance());
  246. VulkanDevice* devices[BS_MAX_DEVICES];
  247. VulkanUtility::getDevices(rapi, mDeviceMask, devices);
  248. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  249. {
  250. if (devices[i] == nullptr)
  251. continue;
  252. mPerDeviceData[i].device = devices[i];
  253. VulkanDescriptorManager& descManager = mPerDeviceData[i].device->getDescriptorManager();
  254. VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
  255. UINT32 numLayouts = vkParamInfo.getNumSets();
  256. VulkanDescriptorLayout** layouts = (VulkanDescriptorLayout**)bs_stack_alloc(sizeof(VulkanDescriptorLayout*) * numLayouts);
  257. for (UINT32 j = 0; j < numLayouts; j++)
  258. layouts[j] = vkParamInfo.getLayout(i, j);
  259. mPerDeviceData[i].pipelineLayout = descManager.getPipelineLayout(layouts, numLayouts);
  260. bs_stack_free(layouts);
  261. }
  262. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_PipelineState);
  263. }
  264. VulkanPipeline* VulkanGraphicsPipelineState::getPipeline(
  265. UINT32 deviceIdx, VulkanFramebuffer* framebuffer, UINT32 readOnlyFlags, DrawOperationType drawOp,
  266. const SPtr<VulkanVertexInput>& vertexInput)
  267. {
  268. Lock(mMutex);
  269. if (mPerDeviceData[deviceIdx].device == nullptr)
  270. return nullptr;
  271. readOnlyFlags &= ~FBT_COLOR; // Ignore the color
  272. GpuPipelineKey key(framebuffer->getId(), vertexInput->getId(), readOnlyFlags, drawOp);
  273. PerDeviceData& perDeviceData = mPerDeviceData[deviceIdx];
  274. auto iterFind = perDeviceData.pipelines.find(key);
  275. if (iterFind != perDeviceData.pipelines.end())
  276. return iterFind->second;
  277. VulkanPipeline* newPipeline = createPipeline(deviceIdx, framebuffer, readOnlyFlags, drawOp, vertexInput);
  278. perDeviceData.pipelines[key] = newPipeline;
  279. return newPipeline;
  280. }
  281. VkPipelineLayout VulkanGraphicsPipelineState::getPipelineLayout(UINT32 deviceIdx) const
  282. {
  283. return mPerDeviceData[deviceIdx].pipelineLayout;
  284. }
  285. void VulkanGraphicsPipelineState::registerPipelineResources(VulkanCmdBuffer* cmdBuffer)
  286. {
  287. UINT32 deviceIdx = cmdBuffer->getDeviceIdx();
  288. std::array<VulkanGpuProgram*, 5> programs = {
  289. static_cast<VulkanGpuProgram*>(mData.vertexProgram.get()),
  290. static_cast<VulkanGpuProgram*>(mData.hullProgram.get()),
  291. static_cast<VulkanGpuProgram*>(mData.domainProgram.get()),
  292. static_cast<VulkanGpuProgram*>(mData.geometryProgram.get()),
  293. static_cast<VulkanGpuProgram*>(mData.fragmentProgram.get()),
  294. };
  295. for(auto& entry : programs)
  296. {
  297. if (entry != nullptr)
  298. {
  299. VulkanShaderModule* module = entry->getShaderModule(deviceIdx);
  300. if(module != nullptr)
  301. cmdBuffer->registerResource(module, VulkanUseFlag::Read);
  302. }
  303. }
  304. }
  305. VulkanPipeline* VulkanGraphicsPipelineState::createPipeline(UINT32 deviceIdx, VulkanFramebuffer* framebuffer,
  306. UINT32 readOnlyFlags, DrawOperationType drawOp, const SPtr<VulkanVertexInput>& vertexInput)
  307. {
  308. mInputAssemblyInfo.topology = VulkanUtility::getDrawOp(drawOp);
  309. mTesselationInfo.patchControlPoints = 3; // Not provided by our shaders for now
  310. mMultiSampleInfo.rasterizationSamples = framebuffer->getSampleFlags();
  311. mColorBlendStateInfo.attachmentCount = framebuffer->getNumColorAttachments();
  312. DepthStencilState* dsState = getDepthStencilState().get();
  313. if (dsState == nullptr)
  314. dsState = DepthStencilState::getDefault().get();
  315. const DepthStencilProperties dsProps = dsState->getProperties();
  316. bool enableDepthWrites = dsProps.getDepthWriteEnable() && (readOnlyFlags & FBT_DEPTH) == 0;
  317. mDepthStencilInfo.depthWriteEnable = enableDepthWrites; // If depth stencil attachment is read only, depthWriteEnable must be VK_FALSE
  318. // Save stencil ops as we might need to change them if depth/stencil is read-only
  319. VkStencilOp oldFrontPassOp = mDepthStencilInfo.front.passOp;
  320. VkStencilOp oldFrontFailOp = mDepthStencilInfo.front.failOp;
  321. VkStencilOp oldFrontZFailOp = mDepthStencilInfo.front.depthFailOp;
  322. VkStencilOp oldBackPassOp = mDepthStencilInfo.back.passOp;
  323. VkStencilOp oldBackFailOp = mDepthStencilInfo.back.failOp;
  324. VkStencilOp oldBackZFailOp = mDepthStencilInfo.back.depthFailOp;
  325. if((readOnlyFlags & FBT_STENCIL) != 0)
  326. {
  327. // Disable any stencil writes
  328. mDepthStencilInfo.front.passOp = VK_STENCIL_OP_KEEP;
  329. mDepthStencilInfo.front.failOp = VK_STENCIL_OP_KEEP;
  330. mDepthStencilInfo.front.depthFailOp = VK_STENCIL_OP_KEEP;
  331. mDepthStencilInfo.back.passOp = VK_STENCIL_OP_KEEP;
  332. mDepthStencilInfo.back.failOp = VK_STENCIL_OP_KEEP;
  333. mDepthStencilInfo.back.depthFailOp = VK_STENCIL_OP_KEEP;
  334. }
  335. // Note: We can use the default render pass here (default clear/load/read flags), even though that might not be the
  336. // exact one currently bound. This is because load/store operations and layout transitions are allowed to differ
  337. // (as per spec 7.2., such render passes are considered compatible).
  338. mPipelineInfo.renderPass = framebuffer->getRenderPass(RT_NONE, RT_NONE, CLEAR_NONE);
  339. mPipelineInfo.layout = mPerDeviceData[deviceIdx].pipelineLayout;
  340. mPipelineInfo.pVertexInputState = vertexInput->getCreateInfo();
  341. bool depthReadOnly;
  342. if (framebuffer->hasDepthAttachment())
  343. {
  344. mPipelineInfo.pDepthStencilState = &mDepthStencilInfo;
  345. depthReadOnly = (readOnlyFlags & FBT_DEPTH) != 0;
  346. }
  347. else
  348. {
  349. mPipelineInfo.pDepthStencilState = nullptr;
  350. depthReadOnly = true;
  351. }
  352. std::array<bool, BS_MAX_MULTIPLE_RENDER_TARGETS> colorReadOnly;
  353. if (framebuffer->getNumColorAttachments() > 0)
  354. {
  355. mPipelineInfo.pColorBlendState = &mColorBlendStateInfo;
  356. for (UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
  357. {
  358. VkPipelineColorBlendAttachmentState& blendState = mAttachmentBlendStates[i];
  359. colorReadOnly[i] = blendState.colorWriteMask == 0;
  360. }
  361. }
  362. else
  363. {
  364. mPipelineInfo.pColorBlendState = nullptr;
  365. for (UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
  366. {
  367. VkPipelineColorBlendAttachmentState& blendState = mAttachmentBlendStates[i];
  368. colorReadOnly[i] = true;
  369. }
  370. }
  371. std::pair<VkShaderStageFlagBits, GpuProgram*> stages[] =
  372. {
  373. { VK_SHADER_STAGE_VERTEX_BIT, mData.vertexProgram.get() },
  374. { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, mData.hullProgram.get() },
  375. { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, mData.domainProgram.get() },
  376. { VK_SHADER_STAGE_GEOMETRY_BIT, mData.geometryProgram.get() },
  377. { VK_SHADER_STAGE_FRAGMENT_BIT, mData.fragmentProgram.get() }
  378. };
  379. UINT32 stageOutputIdx = 0;
  380. UINT32 numStages = sizeof(stages) / sizeof(stages[0]);
  381. for (UINT32 i = 0; i < numStages; i++)
  382. {
  383. VulkanGpuProgram* program = static_cast<VulkanGpuProgram*>(stages[i].second);
  384. if (program == nullptr)
  385. continue;
  386. VkPipelineShaderStageCreateInfo& stageCI = mShaderStageInfos[stageOutputIdx];
  387. VulkanShaderModule* module = program->getShaderModule(deviceIdx);
  388. if (module != nullptr)
  389. stageCI.module = module->getHandle();
  390. else
  391. stageCI.module = VK_NULL_HANDLE;
  392. stageOutputIdx++;
  393. }
  394. VulkanDevice* device = mPerDeviceData[deviceIdx].device;
  395. VkDevice vkDevice = mPerDeviceData[deviceIdx].device->getLogical();
  396. VkPipeline pipeline;
  397. VkResult result = vkCreateGraphicsPipelines(vkDevice, VK_NULL_HANDLE, 1, &mPipelineInfo, gVulkanAllocator, &pipeline);
  398. assert(result == VK_SUCCESS);
  399. // Restore previous stencil op states
  400. mDepthStencilInfo.front.passOp = oldFrontPassOp;
  401. mDepthStencilInfo.front.failOp = oldFrontFailOp;
  402. mDepthStencilInfo.front.depthFailOp = oldFrontZFailOp;
  403. mDepthStencilInfo.back.passOp = oldBackPassOp;
  404. mDepthStencilInfo.back.failOp = oldBackFailOp;
  405. mDepthStencilInfo.back.depthFailOp = oldBackZFailOp;
  406. return device->getResourceManager().create<VulkanPipeline>(pipeline, colorReadOnly, depthReadOnly);
  407. }
  408. VulkanComputePipelineState::VulkanComputePipelineState(const SPtr<GpuProgram>& program,
  409. GpuDeviceFlags deviceMask)
  410. :ComputePipelineState(program, deviceMask), mDeviceMask(deviceMask)
  411. {
  412. bs_zero_out(mPerDeviceData);
  413. }
  414. VulkanComputePipelineState::~VulkanComputePipelineState()
  415. {
  416. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  417. {
  418. if (mPerDeviceData[i].device == nullptr)
  419. continue;
  420. mPerDeviceData[i].pipeline->destroy();
  421. }
  422. }
  423. void VulkanComputePipelineState::initialize()
  424. {
  425. ComputePipelineState::initialize();
  426. // This might happen fairly often if shaders with unsupported languages are loaded, in which case the pipeline
  427. // will never get used, and its fine not to initialize it.
  428. if (!mProgram->isCompiled())
  429. return;
  430. VulkanGpuProgram* vkProgram = static_cast<VulkanGpuProgram*>(mProgram.get());
  431. VkPipelineShaderStageCreateInfo stageCI;
  432. stageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  433. stageCI.pNext = nullptr;
  434. stageCI.flags = 0;
  435. stageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT;
  436. stageCI.module = VK_NULL_HANDLE;
  437. stageCI.pName = vkProgram->getProperties().getEntryPoint().c_str();
  438. stageCI.pSpecializationInfo = nullptr;
  439. VkComputePipelineCreateInfo pipelineCI;
  440. pipelineCI.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
  441. pipelineCI.pNext = nullptr;
  442. pipelineCI.flags = 0;
  443. pipelineCI.stage = stageCI;
  444. pipelineCI.basePipelineHandle = VK_NULL_HANDLE;
  445. pipelineCI.basePipelineIndex = -1;
  446. VulkanRenderAPI& rapi = static_cast<VulkanRenderAPI&>(RenderAPI::instance());
  447. VulkanDevice* devices[BS_MAX_DEVICES];
  448. VulkanUtility::getDevices(rapi, mDeviceMask, devices);
  449. for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
  450. {
  451. if (devices[i] == nullptr)
  452. continue;
  453. mPerDeviceData[i].device = devices[i];
  454. VulkanDescriptorManager& descManager = devices[i]->getDescriptorManager();
  455. VulkanResourceManager& rescManager = devices[i]->getResourceManager();
  456. VulkanGpuPipelineParamInfo& vkParamInfo = static_cast<VulkanGpuPipelineParamInfo&>(*mParamInfo);
  457. UINT32 numLayouts = vkParamInfo.getNumSets();
  458. VulkanDescriptorLayout** layouts = (VulkanDescriptorLayout**)bs_stack_alloc(sizeof(VulkanDescriptorLayout*) * numLayouts);
  459. for (UINT32 j = 0; j < numLayouts; j++)
  460. layouts[j] = vkParamInfo.getLayout(i, j);
  461. VulkanShaderModule* module = vkProgram->getShaderModule(i);
  462. if (module != nullptr)
  463. pipelineCI.stage.module = module->getHandle();
  464. else
  465. pipelineCI.stage.module = VK_NULL_HANDLE;
  466. pipelineCI.layout = descManager.getPipelineLayout(layouts, numLayouts);
  467. VkPipeline pipeline;
  468. VkResult result = vkCreateComputePipelines(devices[i]->getLogical(), VK_NULL_HANDLE, 1, &pipelineCI,
  469. gVulkanAllocator, &pipeline);
  470. assert(result == VK_SUCCESS);
  471. mPerDeviceData[i].pipeline = rescManager.create<VulkanPipeline>(pipeline);
  472. mPerDeviceData[i].pipelineLayout = pipelineCI.layout;
  473. bs_stack_free(layouts);
  474. }
  475. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_PipelineState);
  476. }
  477. VulkanPipeline* VulkanComputePipelineState::getPipeline(UINT32 deviceIdx) const
  478. {
  479. return mPerDeviceData[deviceIdx].pipeline;
  480. }
  481. VkPipelineLayout VulkanComputePipelineState::getPipelineLayout(UINT32 deviceIdx) const
  482. {
  483. return mPerDeviceData[deviceIdx].pipelineLayout;
  484. }
  485. void VulkanComputePipelineState::registerPipelineResources(VulkanCmdBuffer* cmdBuffer)
  486. {
  487. UINT32 deviceIdx = cmdBuffer->getDeviceIdx();
  488. VulkanGpuProgram* program = static_cast<VulkanGpuProgram*>(mProgram.get());
  489. if(program != nullptr)
  490. {
  491. VulkanShaderModule* module = program->getShaderModule(deviceIdx);
  492. if (module != nullptr)
  493. cmdBuffer->registerResource(module, VulkanUseFlag::Read);
  494. }
  495. }
  496. }}