BsVulkanGpuPipelineState.cpp 23 KB

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