FramebufferImpl.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. // Copyright (C) 2009-2020, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <anki/gr/vulkan/FramebufferImpl.h>
  6. #include <anki/gr/Framebuffer.h>
  7. #include <anki/gr/vulkan/GrManagerImpl.h>
  8. #include <anki/gr/vulkan/TextureImpl.h>
  9. namespace anki
  10. {
  11. FramebufferImpl::~FramebufferImpl()
  12. {
  13. if(m_fb)
  14. {
  15. vkDestroyFramebuffer(getDevice(), m_fb, nullptr);
  16. }
  17. for(auto it : m_rpasses)
  18. {
  19. VkRenderPass rpass = it;
  20. ANKI_ASSERT(rpass);
  21. vkDestroyRenderPass(getDevice(), rpass, nullptr);
  22. }
  23. m_rpasses.destroy(getAllocator());
  24. if(m_compatibleRpass)
  25. {
  26. vkDestroyRenderPass(getDevice(), m_compatibleRpass, nullptr);
  27. }
  28. }
  29. Error FramebufferImpl::init(const FramebufferInitInfo& init)
  30. {
  31. ANKI_ASSERT(init.isValid());
  32. // Init common
  33. for(U32 i = 0; i < init.m_colorAttachmentCount; ++i)
  34. {
  35. m_colorAttachmentMask.set(i);
  36. m_colorAttCount = U8(i + 1);
  37. }
  38. if(init.m_depthStencilAttachment.m_textureView)
  39. {
  40. m_aspect = init.m_depthStencilAttachment.m_textureView->getSubresource().m_depthStencilAspect;
  41. }
  42. initClearValues(init);
  43. // Create a renderpass.
  44. initRpassCreateInfo(init);
  45. ANKI_VK_CHECK(vkCreateRenderPass(getDevice(), &m_rpassCi, nullptr, &m_compatibleRpass));
  46. getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
  47. m_compatibleRpass);
  48. // Create the FB
  49. ANKI_CHECK(initFbs(init));
  50. return Error::NONE;
  51. }
  52. void FramebufferImpl::initClearValues(const FramebufferInitInfo& init)
  53. {
  54. for(U i = 0; i < m_colorAttCount; ++i)
  55. {
  56. if(init.m_colorAttachments[i].m_loadOperation == AttachmentLoadOperation::CLEAR)
  57. {
  58. F32* col = &m_clearVals[i].color.float32[0];
  59. col[0] = init.m_colorAttachments[i].m_clearValue.m_colorf[0];
  60. col[1] = init.m_colorAttachments[i].m_clearValue.m_colorf[1];
  61. col[2] = init.m_colorAttachments[i].m_clearValue.m_colorf[2];
  62. col[3] = init.m_colorAttachments[i].m_clearValue.m_colorf[3];
  63. }
  64. else
  65. {
  66. m_clearVals[i] = {};
  67. }
  68. }
  69. if(hasDepthStencil())
  70. {
  71. if(init.m_depthStencilAttachment.m_loadOperation == AttachmentLoadOperation::CLEAR
  72. || init.m_depthStencilAttachment.m_stencilLoadOperation == AttachmentLoadOperation::CLEAR)
  73. {
  74. m_clearVals[m_colorAttCount].depthStencil.depth =
  75. init.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth;
  76. m_clearVals[m_colorAttCount].depthStencil.stencil =
  77. init.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_stencil;
  78. }
  79. else
  80. {
  81. m_clearVals[m_colorAttCount] = {};
  82. }
  83. }
  84. }
  85. Error FramebufferImpl::initFbs(const FramebufferInitInfo& init)
  86. {
  87. VkFramebufferCreateInfo ci = {};
  88. ci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  89. ci.renderPass = m_compatibleRpass;
  90. ci.attachmentCount = init.m_colorAttachmentCount + ((hasDepthStencil()) ? 1 : 0);
  91. ci.layers = 1;
  92. Array<VkImageView, MAX_COLOR_ATTACHMENTS + 1> imgViews;
  93. U count = 0;
  94. for(U i = 0; i < init.m_colorAttachmentCount; ++i)
  95. {
  96. const FramebufferAttachmentInfo& att = init.m_colorAttachments[i];
  97. const TextureViewImpl& view = static_cast<const TextureViewImpl&>(*att.m_textureView);
  98. const TextureImpl& tex = view.getTextureImpl();
  99. ANKI_ASSERT(tex.isSubresourceGoodForFramebufferAttachment(view.getSubresource()));
  100. imgViews[count++] = view.getHandle();
  101. if(m_width == 0)
  102. {
  103. m_width = tex.getWidth() >> view.getSubresource().m_firstMipmap;
  104. m_height = tex.getHeight() >> view.getSubresource().m_firstMipmap;
  105. }
  106. m_refs[i] = att.m_textureView;
  107. if(!!(tex.getTextureUsage() & TextureUsageBit::PRESENT))
  108. {
  109. m_presentableTex = true;
  110. }
  111. }
  112. if(hasDepthStencil())
  113. {
  114. const FramebufferAttachmentInfo& att = init.m_depthStencilAttachment;
  115. const TextureViewImpl& view = static_cast<const TextureViewImpl&>(*att.m_textureView);
  116. const TextureImpl& tex = view.getTextureImpl();
  117. ANKI_ASSERT(tex.isSubresourceGoodForFramebufferAttachment(view.getSubresource()));
  118. imgViews[count++] = view.getHandle();
  119. if(m_width == 0)
  120. {
  121. m_width = tex.getWidth() >> view.getSubresource().m_firstMipmap;
  122. m_height = tex.getHeight() >> view.getSubresource().m_firstMipmap;
  123. }
  124. m_refs[MAX_COLOR_ATTACHMENTS] = att.m_textureView;
  125. }
  126. ci.width = m_width;
  127. ci.height = m_height;
  128. ci.pAttachments = &imgViews[0];
  129. ANKI_ASSERT(count == ci.attachmentCount);
  130. ANKI_VK_CHECK(vkCreateFramebuffer(getDevice(), &ci, nullptr, &m_fb));
  131. getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, m_fb);
  132. return Error::NONE;
  133. }
  134. void FramebufferImpl::setupAttachmentDescriptor(const FramebufferAttachmentInfo& att, VkAttachmentDescription& desc,
  135. VkImageLayout layout) const
  136. {
  137. desc = {};
  138. desc.format = convertFormat(static_cast<const TextureViewImpl&>(*att.m_textureView).getTextureImpl().getFormat());
  139. desc.samples = VK_SAMPLE_COUNT_1_BIT;
  140. desc.loadOp = convertLoadOp(att.m_loadOperation);
  141. desc.storeOp = convertStoreOp(att.m_storeOperation);
  142. desc.stencilLoadOp = convertLoadOp(att.m_stencilLoadOperation);
  143. desc.stencilStoreOp = convertStoreOp(att.m_stencilStoreOperation);
  144. desc.initialLayout = layout;
  145. desc.finalLayout = layout;
  146. }
  147. void FramebufferImpl::initRpassCreateInfo(const FramebufferInitInfo& init)
  148. {
  149. // Setup attachments and references
  150. for(U32 i = 0; i < init.m_colorAttachmentCount; ++i)
  151. {
  152. setupAttachmentDescriptor(init.m_colorAttachments[i], m_attachmentDescriptions[i],
  153. VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
  154. m_references[i].attachment = i;
  155. m_references[i].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  156. }
  157. if(hasDepthStencil())
  158. {
  159. setupAttachmentDescriptor(init.m_depthStencilAttachment, m_attachmentDescriptions[init.m_colorAttachmentCount],
  160. VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
  161. VkAttachmentReference& dsReference = m_references[init.m_colorAttachmentCount];
  162. dsReference.attachment = init.m_colorAttachmentCount;
  163. dsReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  164. }
  165. // Setup the render pass
  166. m_rpassCi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  167. m_rpassCi.pAttachments = &m_attachmentDescriptions[0];
  168. m_rpassCi.attachmentCount = init.m_colorAttachmentCount + ((hasDepthStencil()) ? 1 : 0);
  169. // Subpass
  170. m_subpassDescr.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  171. m_subpassDescr.colorAttachmentCount = init.m_colorAttachmentCount;
  172. m_subpassDescr.pColorAttachments = (init.m_colorAttachmentCount) ? &m_references[0] : nullptr;
  173. m_subpassDescr.pDepthStencilAttachment = (hasDepthStencil()) ? &m_references[init.m_colorAttachmentCount] : nullptr;
  174. m_rpassCi.subpassCount = 1;
  175. m_rpassCi.pSubpasses = &m_subpassDescr;
  176. }
  177. VkRenderPass FramebufferImpl::getRenderPassHandle(const Array<VkImageLayout, MAX_COLOR_ATTACHMENTS>& colorLayouts,
  178. VkImageLayout dsLayout)
  179. {
  180. VkRenderPass out = {};
  181. // Create hash
  182. Array<VkImageLayout, MAX_COLOR_ATTACHMENTS + 1> allLayouts;
  183. U allLayoutCount = 0;
  184. for(U i = 0; i < m_colorAttCount; ++i)
  185. {
  186. ANKI_ASSERT(colorLayouts[i] != VK_IMAGE_LAYOUT_UNDEFINED);
  187. allLayouts[allLayoutCount++] = colorLayouts[i];
  188. }
  189. if(hasDepthStencil())
  190. {
  191. ANKI_ASSERT(dsLayout != VK_IMAGE_LAYOUT_UNDEFINED);
  192. allLayouts[allLayoutCount++] = dsLayout;
  193. }
  194. U64 hash = computeHash(&allLayouts[0], allLayoutCount * sizeof(allLayouts[0]));
  195. // Get or create
  196. LockGuard<Mutex> lock(m_rpassesMtx);
  197. auto it = m_rpasses.find(hash);
  198. if(it != m_rpasses.getEnd())
  199. {
  200. out = *it;
  201. }
  202. else
  203. {
  204. // Create
  205. VkRenderPassCreateInfo ci = m_rpassCi;
  206. Array<VkAttachmentDescription, MAX_COLOR_ATTACHMENTS + 1> attachmentDescriptions = m_attachmentDescriptions;
  207. Array<VkAttachmentReference, MAX_COLOR_ATTACHMENTS + 1> references = m_references;
  208. VkSubpassDescription subpassDescr = m_subpassDescr;
  209. // Fix pointers
  210. subpassDescr.pColorAttachments = &references[0];
  211. ci.pAttachments = &attachmentDescriptions[0];
  212. ci.pSubpasses = &subpassDescr;
  213. for(U i = 0; i < subpassDescr.colorAttachmentCount; ++i)
  214. {
  215. const VkImageLayout lay = colorLayouts[i];
  216. ANKI_ASSERT(lay != VK_IMAGE_LAYOUT_UNDEFINED);
  217. attachmentDescriptions[i].initialLayout = lay;
  218. attachmentDescriptions[i].finalLayout = lay;
  219. references[i].layout = lay;
  220. }
  221. if(hasDepthStencil())
  222. {
  223. const U i = subpassDescr.colorAttachmentCount;
  224. const VkImageLayout lay = dsLayout;
  225. ANKI_ASSERT(lay != VK_IMAGE_LAYOUT_UNDEFINED);
  226. attachmentDescriptions[i].initialLayout = lay;
  227. attachmentDescriptions[i].finalLayout = lay;
  228. references[subpassDescr.colorAttachmentCount].layout = lay;
  229. subpassDescr.pDepthStencilAttachment = &references[subpassDescr.colorAttachmentCount];
  230. }
  231. ANKI_VK_CHECKF(vkCreateRenderPass(getDevice(), &ci, nullptr, &out));
  232. getGrManagerImpl().trySetVulkanHandleName(getName(), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, out);
  233. m_rpasses.emplace(getAllocator(), hash, out);
  234. }
  235. ANKI_ASSERT(out);
  236. return out;
  237. }
  238. } // end namespace anki