BsVulkanFramebuffer.cpp 9.6 KB

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