BsVulkanFramebuffer.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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
  8. {
  9. VulkanFramebuffer::VariantKey::VariantKey(RenderSurfaceMask loadMask, RenderSurfaceMask readMask)
  10. :loadMask(loadMask), readMask(readMask)
  11. { }
  12. size_t VulkanFramebuffer::VariantKey::HashFunction::operator()(const VariantKey& v) const
  13. {
  14. size_t hash = 0;
  15. hash_combine(hash, v.readMask);
  16. hash_combine(hash, v.loadMask);
  17. return hash;
  18. }
  19. bool VulkanFramebuffer::VariantKey::EqualFunction::operator()(const VariantKey& lhs,
  20. const VariantKey& rhs) const
  21. {
  22. return lhs.loadMask == rhs.loadMask && lhs.readMask == rhs.readMask;
  23. }
  24. UINT32 VulkanFramebuffer::sNextValidId = 1;
  25. VulkanFramebuffer::VulkanFramebuffer(VulkanResourceManager* owner, const VULKAN_FRAMEBUFFER_DESC& desc)
  26. : VulkanResource(owner, false), mNumAttachments(0), mNumColorAttachments(0), mNumLayers(desc.layers)
  27. , mColorAttachments(), mDepthStencilAttachment(), mHasDepth(false), mSampleFlags(VK_SAMPLE_COUNT_1_BIT)
  28. {
  29. mId = sNextValidId++;
  30. mSampleFlags = VulkanUtility::getSampleFlags(desc.numSamples);
  31. UINT32 attachmentIdx = 0;
  32. for(UINT32 i = 0; i < BS_MAX_MULTIPLE_RENDER_TARGETS; i++)
  33. {
  34. if (desc.color[i].image == nullptr)
  35. continue;
  36. VkAttachmentDescription& attachmentDesc = mAttachments[attachmentIdx];
  37. attachmentDesc.flags = 0;
  38. attachmentDesc.format = desc.color[i].format;
  39. attachmentDesc.samples = mSampleFlags;
  40. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  41. attachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  42. attachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  43. attachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  44. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  45. // If offscreen we make the assumption the surface will be read by a shader
  46. if(desc.offscreen)
  47. attachmentDesc.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  48. else
  49. attachmentDesc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  50. mColorAttachments[attachmentIdx].baseLayer = desc.color[i].baseLayer;
  51. mColorAttachments[attachmentIdx].image = desc.color[i].image;
  52. mColorAttachments[attachmentIdx].finalLayout = attachmentDesc.finalLayout;
  53. mColorAttachments[attachmentIdx].index = i;
  54. VkAttachmentReference& ref = mColorReferences[attachmentIdx];
  55. ref.attachment = attachmentIdx;
  56. ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  57. mAttachmentViews[attachmentIdx] = desc.color[i].view;
  58. attachmentIdx++;
  59. }
  60. mNumColorAttachments = attachmentIdx;
  61. mHasDepth = desc.depth.view != VK_NULL_HANDLE;
  62. if (mHasDepth)
  63. {
  64. VkAttachmentDescription& attachmentDesc = mAttachments[attachmentIdx];
  65. attachmentDesc.flags = 0;
  66. attachmentDesc.format = desc.depth.format;
  67. attachmentDesc.samples = mSampleFlags;
  68. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  69. attachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  70. attachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  71. attachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
  72. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  73. attachmentDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  74. mDepthStencilAttachment.baseLayer = desc.depth.baseLayer;
  75. mDepthStencilAttachment.image = desc.depth.image;
  76. mDepthStencilAttachment.finalLayout = attachmentDesc.finalLayout;
  77. mDepthStencilAttachment.index = 0;
  78. VkAttachmentReference& ref = mDepthReference;
  79. ref.attachment = attachmentIdx;
  80. ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  81. mAttachmentViews[attachmentIdx] = desc.depth.view;
  82. attachmentIdx++;
  83. }
  84. mNumAttachments = attachmentIdx;
  85. mSubpassDesc.flags = 0;
  86. mSubpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  87. mSubpassDesc.colorAttachmentCount = mNumColorAttachments;
  88. mSubpassDesc.inputAttachmentCount = 0;
  89. mSubpassDesc.pInputAttachments = nullptr;
  90. mSubpassDesc.preserveAttachmentCount = 0;
  91. mSubpassDesc.pPreserveAttachments = nullptr;
  92. mSubpassDesc.pResolveAttachments = nullptr;
  93. if (mNumColorAttachments > 0)
  94. mSubpassDesc.pColorAttachments = mColorReferences;
  95. else
  96. mSubpassDesc.pColorAttachments = nullptr;
  97. if (mHasDepth)
  98. mSubpassDesc.pDepthStencilAttachment = &mDepthReference;
  99. else
  100. mSubpassDesc.pDepthStencilAttachment = nullptr;
  101. // Subpass dependencies for layout transitions
  102. mDependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
  103. mDependencies[0].dstSubpass = 0;
  104. mDependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  105. mDependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  106. mDependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
  107. mDependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  108. mDependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; // Note: Is this really required?
  109. mDependencies[1].srcSubpass = 0;
  110. mDependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
  111. mDependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  112. mDependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  113. mDependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  114. mDependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
  115. mDependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;// Note: Is this really required?
  116. // Create render pass and frame buffer create infos
  117. mRenderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  118. mRenderPassCI.pNext = nullptr;
  119. mRenderPassCI.flags = 0;
  120. mRenderPassCI.attachmentCount = mNumAttachments;
  121. mRenderPassCI.pAttachments = mAttachments;
  122. mRenderPassCI.subpassCount = 1;
  123. mRenderPassCI.pSubpasses = &mSubpassDesc;
  124. mRenderPassCI.dependencyCount = 2;
  125. mRenderPassCI.pDependencies = mDependencies;
  126. mFramebufferCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  127. mFramebufferCI.pNext = nullptr;
  128. mFramebufferCI.flags = 0;
  129. mFramebufferCI.renderPass = VK_NULL_HANDLE;
  130. mFramebufferCI.attachmentCount = mNumAttachments;
  131. mFramebufferCI.pAttachments = mAttachmentViews;
  132. mFramebufferCI.width = desc.width;
  133. mFramebufferCI.height = desc.height;
  134. mFramebufferCI.layers = desc.layers;
  135. mDefault = createVariant(RT_NONE, RT_NONE);
  136. }
  137. VulkanFramebuffer::~VulkanFramebuffer()
  138. {
  139. VkDevice device = mOwner->getDevice().getLogical();
  140. vkDestroyFramebuffer(device, mDefault.framebuffer, gVulkanAllocator);
  141. vkDestroyRenderPass(device, mDefault.renderPass, gVulkanAllocator);
  142. for(auto& entry : mVariants)
  143. {
  144. vkDestroyFramebuffer(device, entry.second.framebuffer, gVulkanAllocator);
  145. vkDestroyRenderPass(device, entry.second.renderPass, gVulkanAllocator);
  146. }
  147. }
  148. VulkanFramebuffer::Variant VulkanFramebuffer::createVariant(RenderSurfaceMask loadMask,
  149. RenderSurfaceMask readMask) const
  150. {
  151. for (UINT32 i = 0; i < mNumColorAttachments; i++)
  152. {
  153. const VulkanFramebufferAttachment& attachment = mColorAttachments[i];
  154. VkAttachmentDescription& attachmentDesc = mAttachments[i];
  155. VkAttachmentReference& attachmentRef = mColorReferences[i];
  156. if (loadMask.isSet((RenderSurfaceMaskBits)(1 << attachment.index)))
  157. {
  158. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
  159. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  160. }
  161. else
  162. {
  163. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  164. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  165. }
  166. if(readMask.isSet((RenderSurfaceMaskBits)(1 << attachment.index)))
  167. attachmentRef.layout = VK_IMAGE_LAYOUT_GENERAL;
  168. else
  169. attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  170. }
  171. if (mHasDepth)
  172. {
  173. VkAttachmentDescription& attachmentDesc = mAttachments[mNumColorAttachments];
  174. VkAttachmentReference& attachmentRef = mDepthReference;
  175. if (loadMask.isSet(RT_DEPTH))
  176. {
  177. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
  178. attachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
  179. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  180. }
  181. else
  182. {
  183. attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  184. attachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  185. attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  186. }
  187. if (readMask.isSet(RT_DEPTH))
  188. attachmentRef.layout = VK_IMAGE_LAYOUT_GENERAL;
  189. else
  190. attachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  191. }
  192. VkDevice device = mOwner->getDevice().getLogical();
  193. Variant variant;
  194. VkResult result = vkCreateRenderPass(device, &mRenderPassCI, gVulkanAllocator, &variant.renderPass);
  195. assert(result == VK_SUCCESS);
  196. mFramebufferCI.renderPass = variant.renderPass;
  197. result = vkCreateFramebuffer(device, &mFramebufferCI, gVulkanAllocator, &variant.framebuffer);
  198. assert(result == VK_SUCCESS);
  199. return variant;
  200. }
  201. VkRenderPass VulkanFramebuffer::getRenderPass(RenderSurfaceMask loadMask, RenderSurfaceMask readMask) const
  202. {
  203. if (loadMask == RT_NONE && readMask == RT_NONE)
  204. return mDefault.renderPass;
  205. VariantKey key(loadMask, readMask);
  206. auto iterFind = mVariants.find(key);
  207. if (iterFind != mVariants.end())
  208. return iterFind->second.renderPass;
  209. Variant newVariant = createVariant(loadMask, readMask);
  210. mVariants[key] = newVariant;
  211. return newVariant.renderPass;
  212. }
  213. VkFramebuffer VulkanFramebuffer::getFramebuffer(RenderSurfaceMask loadMask, RenderSurfaceMask readMask) const
  214. {
  215. if (loadMask == RT_NONE && readMask == RT_NONE)
  216. return mDefault.framebuffer;
  217. VariantKey key(loadMask, readMask);
  218. auto iterFind = mVariants.find(key);
  219. if (iterFind != mVariants.end())
  220. return iterFind->second.framebuffer;
  221. Variant newVariant = createVariant(loadMask, readMask);
  222. mVariants[key] = newVariant;
  223. return newVariant.framebuffer;
  224. }
  225. }