BsVulkanFramebuffer.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsVulkanFramebuffer.h"
  4. #include "BsVulkanTexture.h"
  5. #include "BsVulkanUtility.h"
  6. #include "BsVulkanDevice.h"
  7. namespace bs { namespace ct
  8. {
  9. VulkanFramebuffer::VariantKey::VariantKey(RenderSurfaceMask loadMask, RenderSurfaceMask readMask,
  10. ClearMask clearMask)
  11. :loadMask(loadMask), readMask(readMask), clearMask(clearMask)
  12. { }
  13. size_t VulkanFramebuffer::VariantKey::HashFunction::operator()(const VariantKey& v) const
  14. {
  15. size_t hash = 0;
  16. hash_combine(hash, v.readMask);
  17. hash_combine(hash, v.loadMask);
  18. hash_combine(hash, v.clearMask);
  19. return hash;
  20. }
  21. bool VulkanFramebuffer::VariantKey::EqualFunction::operator()(const VariantKey& lhs,
  22. const VariantKey& rhs) const
  23. {
  24. return lhs.loadMask == rhs.loadMask && lhs.readMask == rhs.readMask && lhs.clearMask == rhs.clearMask;
  25. }
  26. UINT32 VulkanFramebuffer::sNextValidId = 1;
  27. VulkanFramebuffer::VulkanFramebuffer(VulkanResourceManager* owner, const VULKAN_FRAMEBUFFER_DESC& desc)
  28. : VulkanResource(owner, false), mNumAttachments(0), mNumColorAttachments(0), mNumLayers(desc.layers)
  29. , mColorAttachments(), mDepthStencilAttachment(), mHasDepth(false), mSampleFlags(VK_SAMPLE_COUNT_1_BIT)
  30. {
  31. mId = sNextValidId++;
  32. mSampleFlags = VulkanUtility::getSampleFlags(desc.numSamples);
  33. UINT32 attachmentIdx = 0;
  34. for(UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
  35. {
  36. if (desc.color[i].image == nullptr)
  37. continue;
  38. VkAttachmentDescription& attachmentDesc = mAttachments[attachmentIdx];
  39. attachmentDesc.flags = 0;
  40. attachmentDesc.format = desc.color[i].format;
  41. attachmentDesc.samples = mSampleFlags;
  42. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  43. attachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  44. attachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  45. attachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  46. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  47. // If offscreen we make the assumption the surface will be read by a shader
  48. if(desc.offscreen)
  49. attachmentDesc.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  50. else
  51. attachmentDesc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  52. mColorAttachments[attachmentIdx].baseLayer = desc.color[i].baseLayer;
  53. mColorAttachments[attachmentIdx].image = desc.color[i].image;
  54. mColorAttachments[attachmentIdx].finalLayout = attachmentDesc.finalLayout;
  55. mColorAttachments[attachmentIdx].index = i;
  56. mColorAttachments[attachmentIdx].surface = desc.color[i].surface;
  57. VkAttachmentReference& ref = mColorReferences[attachmentIdx];
  58. ref.attachment = attachmentIdx;
  59. ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  60. if (desc.color[i].surface.numMipLevels == 0)
  61. mAttachmentViews[attachmentIdx] = desc.color[i].image->getView(true);
  62. else
  63. mAttachmentViews[attachmentIdx] = desc.color[i].image->getView(desc.color[i].surface, true);
  64. attachmentIdx++;
  65. }
  66. mNumColorAttachments = attachmentIdx;
  67. mHasDepth = desc.depth.image != nullptr;
  68. if (mHasDepth)
  69. {
  70. VkAttachmentDescription& attachmentDesc = mAttachments[attachmentIdx];
  71. attachmentDesc.flags = 0;
  72. attachmentDesc.format = desc.depth.format;
  73. attachmentDesc.samples = mSampleFlags;
  74. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  75. attachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  76. attachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  77. attachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
  78. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  79. attachmentDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  80. mDepthStencilAttachment.baseLayer = desc.depth.baseLayer;
  81. mDepthStencilAttachment.image = desc.depth.image;
  82. mDepthStencilAttachment.finalLayout = attachmentDesc.finalLayout;
  83. mDepthStencilAttachment.index = 0;
  84. mDepthStencilAttachment.surface = desc.depth.surface;
  85. VkAttachmentReference& ref = mDepthReference;
  86. ref.attachment = attachmentIdx;
  87. ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  88. if (desc.depth.surface.numMipLevels == 0)
  89. mAttachmentViews[attachmentIdx] = desc.depth.image->getView(true);
  90. else
  91. mAttachmentViews[attachmentIdx] = desc.depth.image->getView(desc.depth.surface, true);
  92. attachmentIdx++;
  93. }
  94. mNumAttachments = attachmentIdx;
  95. mSubpassDesc.flags = 0;
  96. mSubpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  97. mSubpassDesc.colorAttachmentCount = mNumColorAttachments;
  98. mSubpassDesc.inputAttachmentCount = 0;
  99. mSubpassDesc.pInputAttachments = nullptr;
  100. mSubpassDesc.preserveAttachmentCount = 0;
  101. mSubpassDesc.pPreserveAttachments = nullptr;
  102. mSubpassDesc.pResolveAttachments = nullptr;
  103. if (mNumColorAttachments > 0)
  104. mSubpassDesc.pColorAttachments = mColorReferences;
  105. else
  106. mSubpassDesc.pColorAttachments = nullptr;
  107. if (mHasDepth)
  108. mSubpassDesc.pDepthStencilAttachment = &mDepthReference;
  109. else
  110. mSubpassDesc.pDepthStencilAttachment = nullptr;
  111. // Subpass dependencies for layout transitions
  112. mDependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
  113. mDependencies[0].dstSubpass = 0;
  114. mDependencies[0].srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
  115. mDependencies[0].dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
  116. mDependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
  117. mDependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
  118. VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
  119. mDependencies[0].dependencyFlags = 0;
  120. mDependencies[1].srcSubpass = 0;
  121. mDependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
  122. mDependencies[1].srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
  123. mDependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  124. mDependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
  125. VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
  126. mDependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT;
  127. mDependencies[1].dependencyFlags = 0;
  128. // Create render pass and frame buffer create infos
  129. mRenderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  130. mRenderPassCI.pNext = nullptr;
  131. mRenderPassCI.flags = 0;
  132. mRenderPassCI.attachmentCount = mNumAttachments;
  133. mRenderPassCI.pAttachments = mAttachments;
  134. mRenderPassCI.subpassCount = 1;
  135. mRenderPassCI.pSubpasses = &mSubpassDesc;
  136. mRenderPassCI.dependencyCount = 2;
  137. mRenderPassCI.pDependencies = mDependencies;
  138. mFramebufferCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  139. mFramebufferCI.pNext = nullptr;
  140. mFramebufferCI.flags = 0;
  141. mFramebufferCI.renderPass = VK_NULL_HANDLE;
  142. mFramebufferCI.attachmentCount = mNumAttachments;
  143. mFramebufferCI.pAttachments = mAttachmentViews;
  144. mFramebufferCI.width = desc.width;
  145. mFramebufferCI.height = desc.height;
  146. mFramebufferCI.layers = desc.layers;
  147. mDefault = createVariant(RT_NONE, RT_NONE, CLEAR_NONE);
  148. }
  149. VulkanFramebuffer::~VulkanFramebuffer()
  150. {
  151. VkDevice device = mOwner->getDevice().getLogical();
  152. vkDestroyFramebuffer(device, mDefault.framebuffer, gVulkanAllocator);
  153. vkDestroyRenderPass(device, mDefault.renderPass, gVulkanAllocator);
  154. for(auto& entry : mVariants)
  155. {
  156. vkDestroyFramebuffer(device, entry.second.framebuffer, gVulkanAllocator);
  157. vkDestroyRenderPass(device, entry.second.renderPass, gVulkanAllocator);
  158. }
  159. }
  160. VulkanFramebuffer::Variant VulkanFramebuffer::createVariant(RenderSurfaceMask loadMask,
  161. RenderSurfaceMask readMask, ClearMask clearMask) const
  162. {
  163. for (UINT32 i = 0; i < mNumColorAttachments; i++)
  164. {
  165. const VulkanFramebufferAttachment& attachment = mColorAttachments[i];
  166. VkAttachmentDescription& attachmentDesc = mAttachments[i];
  167. VkAttachmentReference& attachmentRef = mColorReferences[i];
  168. if (loadMask.isSet((RenderSurfaceMaskBits)(1 << attachment.index)))
  169. {
  170. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
  171. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  172. }
  173. else if (clearMask.isSet((ClearMaskBits)(1 << attachment.index)))
  174. {
  175. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  176. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  177. }
  178. else
  179. {
  180. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  181. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  182. }
  183. if(readMask.isSet((RenderSurfaceMaskBits)(1 << attachment.index)))
  184. attachmentRef.layout = VK_IMAGE_LAYOUT_GENERAL;
  185. else
  186. attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  187. }
  188. if (mHasDepth)
  189. {
  190. VkAttachmentDescription& attachmentDesc = mAttachments[mNumColorAttachments];
  191. VkAttachmentReference& attachmentRef = mDepthReference;
  192. if (loadMask.isSet(RT_DEPTH) || loadMask.isSet(RT_STENCIL))
  193. {
  194. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
  195. attachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
  196. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  197. }
  198. else
  199. {
  200. if(clearMask.isSet(CLEAR_DEPTH))
  201. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  202. else
  203. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  204. if(clearMask.isSet(CLEAR_STENCIL))
  205. attachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  206. else
  207. attachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  208. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  209. }
  210. // When depth-stencil is readable it's up to the caller to ensure he doesn't try to write to it as well, so we
  211. // just assume a read-only layout.
  212. if (readMask.isSet(RT_DEPTH))
  213. {
  214. if (readMask.isSet(RT_STENCIL))
  215. attachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
  216. else // Depth readable but stencil isn't
  217. attachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR;
  218. }
  219. else
  220. {
  221. if (readMask.isSet(RT_STENCIL)) // Stencil readable but depth isn't
  222. attachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR;
  223. else
  224. attachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  225. }
  226. }
  227. VkDevice device = mOwner->getDevice().getLogical();
  228. Variant variant;
  229. VkResult result = vkCreateRenderPass(device, &mRenderPassCI, gVulkanAllocator, &variant.renderPass);
  230. assert(result == VK_SUCCESS);
  231. mFramebufferCI.renderPass = variant.renderPass;
  232. result = vkCreateFramebuffer(device, &mFramebufferCI, gVulkanAllocator, &variant.framebuffer);
  233. assert(result == VK_SUCCESS);
  234. return variant;
  235. }
  236. VkRenderPass VulkanFramebuffer::getRenderPass(RenderSurfaceMask loadMask, RenderSurfaceMask readMask,
  237. ClearMask clearMask) const
  238. {
  239. if (loadMask == RT_NONE && readMask == RT_NONE && clearMask == CLEAR_NONE)
  240. return mDefault.renderPass;
  241. VariantKey key(loadMask, readMask, clearMask);
  242. auto iterFind = mVariants.find(key);
  243. if (iterFind != mVariants.end())
  244. return iterFind->second.renderPass;
  245. Variant newVariant = createVariant(loadMask, readMask, clearMask);
  246. mVariants[key] = newVariant;
  247. return newVariant.renderPass;
  248. }
  249. VkFramebuffer VulkanFramebuffer::getFramebuffer(RenderSurfaceMask loadMask, RenderSurfaceMask readMask,
  250. ClearMask clearMask) const
  251. {
  252. if (loadMask == RT_NONE && readMask == RT_NONE && clearMask == CLEAR_NONE)
  253. return mDefault.framebuffer;
  254. VariantKey key(loadMask, readMask, clearMask);
  255. auto iterFind = mVariants.find(key);
  256. if (iterFind != mVariants.end())
  257. return iterFind->second.framebuffer;
  258. Variant newVariant = createVariant(loadMask, readMask, clearMask);
  259. mVariants[key] = newVariant;
  260. return newVariant.framebuffer;
  261. }
  262. UINT32 VulkanFramebuffer::getNumClearEntries(ClearMask clearMask) const
  263. {
  264. if (clearMask == CLEAR_NONE)
  265. return 0;
  266. else if (clearMask == CLEAR_ALL)
  267. return getNumAttachments();
  268. else if (((UINT32)clearMask & (UINT32)(CLEAR_DEPTH | CLEAR_STENCIL)) != 0 && hasDepthAttachment())
  269. return getNumAttachments();
  270. UINT32 numAttachments = 0;
  271. for(INT32 i = BS_MAX_MULTIPLE_RENDER_TARGETS - 1; i >= 0; i--)
  272. {
  273. if(((1 << i) & (UINT32)clearMask) != 0)
  274. {
  275. numAttachments = i + 1;
  276. break;
  277. }
  278. }
  279. return std::min(numAttachments, getNumColorAttachments());
  280. }
  281. }}