BsVulkanGpuPipelineState.cpp 20 KB

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