Scale.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // Copyright (C) 2009-2022, 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/Renderer/Scale.h>
  6. #include <AnKi/Renderer/Renderer.h>
  7. #include <AnKi/Renderer/TemporalAA.h>
  8. #include <AnKi/Core/ConfigSet.h>
  9. #if ANKI_COMPILER_GCC_COMPATIBLE
  10. # pragma GCC diagnostic push
  11. # pragma GCC diagnostic ignored "-Wunused-function"
  12. # pragma GCC diagnostic ignored "-Wignored-qualifiers"
  13. #elif ANKI_COMPILER_MSVC
  14. # pragma warning(push)
  15. # pragma warning(disable : 4505)
  16. #endif
  17. #define A_CPU
  18. #include <ThirdParty/FidelityFX/ffx_a.h>
  19. #include <ThirdParty/FidelityFX/ffx_fsr1.h>
  20. #if ANKI_COMPILER_GCC_COMPATIBLE
  21. # pragma GCC diagnostic pop
  22. #elif ANKI_COMPILER_MSVC
  23. # pragma warning(pop)
  24. #endif
  25. namespace anki {
  26. Scale::~Scale()
  27. {
  28. }
  29. Error Scale::init()
  30. {
  31. ANKI_R_LOGV("Initializing scale");
  32. const Bool needsScaling = m_r->getPostProcessResolution() != m_r->getInternalResolution();
  33. const Bool needsSharpening = getConfig().getRSharpen();
  34. if(!needsScaling && !needsSharpening)
  35. {
  36. return Error::NONE;
  37. }
  38. const Bool preferCompute = getConfig().getRPreferCompute();
  39. const U32 fsrQuality = getConfig().getRFsr();
  40. m_fsr = fsrQuality != 0;
  41. // Program
  42. if(needsScaling)
  43. {
  44. CString shaderFname;
  45. if(m_fsr && preferCompute)
  46. {
  47. shaderFname = "ShaderBinaries/FsrCompute.ankiprogbin";
  48. }
  49. else if(m_fsr)
  50. {
  51. shaderFname = "ShaderBinaries/FsrRaster.ankiprogbin";
  52. }
  53. else if(preferCompute)
  54. {
  55. shaderFname = "ShaderBinaries/BlitCompute.ankiprogbin";
  56. }
  57. else
  58. {
  59. shaderFname = "ShaderBinaries/BlitRaster.ankiprogbin";
  60. }
  61. ANKI_CHECK(getResourceManager().loadResource(shaderFname, m_scaleProg));
  62. const ShaderProgramResourceVariant* variant;
  63. if(m_fsr)
  64. {
  65. ShaderProgramResourceVariantInitInfo variantInitInfo(m_scaleProg);
  66. variantInitInfo.addMutation("SHARPEN", 0);
  67. variantInitInfo.addMutation("FSR_QUALITY", fsrQuality - 1);
  68. m_scaleProg->getOrCreateVariant(variantInitInfo, variant);
  69. }
  70. else
  71. {
  72. m_scaleProg->getOrCreateVariant(variant);
  73. }
  74. m_scaleGrProg = variant->getProgram();
  75. }
  76. if(needsSharpening)
  77. {
  78. ANKI_CHECK(getResourceManager().loadResource((preferCompute) ? "ShaderBinaries/FsrCompute.ankiprogbin"
  79. : "ShaderBinaries/FsrRaster.ankiprogbin",
  80. m_sharpenProg));
  81. ShaderProgramResourceVariantInitInfo variantInitInfo(m_sharpenProg);
  82. variantInitInfo.addMutation("SHARPEN", 1);
  83. variantInitInfo.addMutation("FSR_QUALITY", 0);
  84. const ShaderProgramResourceVariant* variant;
  85. m_sharpenProg->getOrCreateVariant(variantInitInfo, variant);
  86. m_sharpenGrProg = variant->getProgram();
  87. }
  88. // Descriptors
  89. m_rtDesc = m_r->create2DRenderTargetDescription(
  90. m_r->getPostProcessResolution().x(), m_r->getPostProcessResolution().y(),
  91. (getGrManager().getDeviceCapabilities().m_unalignedBbpTextureFormats) ? Format::R8G8B8_UNORM
  92. : Format::R8G8B8A8_UNORM,
  93. "Scaled");
  94. m_rtDesc.bake();
  95. m_fbDescr.m_colorAttachmentCount = 1;
  96. m_fbDescr.bake();
  97. return Error::NONE;
  98. }
  99. void Scale::populateRenderGraph(RenderingContext& ctx)
  100. {
  101. if(!doScaling() && !doSharpening())
  102. {
  103. m_runCtx.m_scaledRt = m_r->getTemporalAA().getRt();
  104. m_runCtx.m_sharpenedRt = m_r->getTemporalAA().getRt();
  105. return;
  106. }
  107. RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
  108. const Bool preferCompute = getConfig().getRPreferCompute();
  109. if(doScaling())
  110. {
  111. m_runCtx.m_scaledRt = rgraph.newRenderTarget(m_rtDesc);
  112. if(preferCompute)
  113. {
  114. ComputeRenderPassDescription& pass = ctx.m_renderGraphDescr.newComputeRenderPass("Scale");
  115. pass.newDependency(RenderPassDependency(m_r->getTemporalAA().getRt(), TextureUsageBit::SAMPLED_COMPUTE));
  116. pass.newDependency(RenderPassDependency(m_runCtx.m_scaledRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
  117. pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
  118. runScaling(rgraphCtx);
  119. });
  120. }
  121. else
  122. {
  123. GraphicsRenderPassDescription& pass = ctx.m_renderGraphDescr.newGraphicsRenderPass("Scale");
  124. pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_scaledRt});
  125. pass.newDependency(RenderPassDependency(m_r->getTemporalAA().getRt(), TextureUsageBit::SAMPLED_FRAGMENT));
  126. pass.newDependency(
  127. RenderPassDependency(m_runCtx.m_scaledRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
  128. pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
  129. runScaling(rgraphCtx);
  130. });
  131. }
  132. }
  133. if(doSharpening())
  134. {
  135. m_runCtx.m_sharpenedRt = rgraph.newRenderTarget(m_rtDesc);
  136. if(preferCompute)
  137. {
  138. ComputeRenderPassDescription& pass = ctx.m_renderGraphDescr.newComputeRenderPass("Sharpen");
  139. pass.newDependency(RenderPassDependency((!doScaling()) ? m_r->getTemporalAA().getRt() : m_runCtx.m_scaledRt,
  140. TextureUsageBit::SAMPLED_COMPUTE));
  141. pass.newDependency(RenderPassDependency(m_runCtx.m_sharpenedRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
  142. pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
  143. runSharpening(rgraphCtx);
  144. });
  145. }
  146. else
  147. {
  148. GraphicsRenderPassDescription& pass = ctx.m_renderGraphDescr.newGraphicsRenderPass("Sharpen");
  149. pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_sharpenedRt});
  150. pass.newDependency(RenderPassDependency((!doScaling()) ? m_r->getTemporalAA().getRt() : m_runCtx.m_scaledRt,
  151. TextureUsageBit::SAMPLED_FRAGMENT));
  152. pass.newDependency(
  153. RenderPassDependency(m_runCtx.m_sharpenedRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
  154. pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
  155. runSharpening(rgraphCtx);
  156. });
  157. }
  158. }
  159. }
  160. void Scale::runScaling(RenderPassWorkContext& rgraphCtx)
  161. {
  162. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  163. const Bool preferCompute = getConfig().getRPreferCompute();
  164. cmdb->bindShaderProgram(m_scaleGrProg);
  165. cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
  166. rgraphCtx.bindColorTexture(0, 1, m_r->getTemporalAA().getRt());
  167. if(preferCompute)
  168. {
  169. rgraphCtx.bindImage(0, 2, m_runCtx.m_scaledRt);
  170. }
  171. if(m_fsr)
  172. {
  173. class
  174. {
  175. public:
  176. UVec4 m_fsrConsts0;
  177. UVec4 m_fsrConsts1;
  178. UVec4 m_fsrConsts2;
  179. UVec4 m_fsrConsts3;
  180. UVec2 m_viewportSize;
  181. UVec2 m_padding;
  182. } pc;
  183. const Vec2 inRez(m_r->getInternalResolution());
  184. const Vec2 outRez(m_r->getPostProcessResolution());
  185. FsrEasuCon(&pc.m_fsrConsts0[0], &pc.m_fsrConsts1[0], &pc.m_fsrConsts2[0], &pc.m_fsrConsts3[0], inRez.x(),
  186. inRez.y(), inRez.x(), inRez.y(), outRez.x(), outRez.y());
  187. pc.m_viewportSize = m_r->getPostProcessResolution();
  188. cmdb->setPushConstants(&pc, sizeof(pc));
  189. }
  190. else if(preferCompute)
  191. {
  192. class
  193. {
  194. public:
  195. Vec2 m_viewportSize;
  196. UVec2 m_viewportSizeU;
  197. } pc;
  198. pc.m_viewportSize = Vec2(m_r->getPostProcessResolution());
  199. pc.m_viewportSizeU = m_r->getPostProcessResolution();
  200. cmdb->setPushConstants(&pc, sizeof(pc));
  201. }
  202. if(preferCompute)
  203. {
  204. dispatchPPCompute(cmdb, 8, 8, m_r->getPostProcessResolution().x(), m_r->getPostProcessResolution().y());
  205. }
  206. else
  207. {
  208. cmdb->setViewport(0, 0, m_r->getPostProcessResolution().x(), m_r->getPostProcessResolution().y());
  209. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 3);
  210. }
  211. }
  212. void Scale::runSharpening(RenderPassWorkContext& rgraphCtx)
  213. {
  214. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  215. const Bool preferCompute = getConfig().getRPreferCompute();
  216. cmdb->bindShaderProgram(m_sharpenGrProg);
  217. cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
  218. rgraphCtx.bindColorTexture(0, 1, (!doScaling()) ? m_r->getTemporalAA().getRt() : m_runCtx.m_scaledRt);
  219. if(preferCompute)
  220. {
  221. rgraphCtx.bindImage(0, 2, m_runCtx.m_sharpenedRt);
  222. }
  223. class
  224. {
  225. public:
  226. UVec4 m_fsrConsts0;
  227. UVec4 m_fsrConsts1;
  228. UVec4 m_fsrConsts2;
  229. UVec4 m_fsrConsts3;
  230. UVec2 m_viewportSize;
  231. UVec2 m_padding;
  232. } pc;
  233. FsrRcasCon(&pc.m_fsrConsts0[0], 0.2f);
  234. pc.m_viewportSize = m_r->getPostProcessResolution();
  235. cmdb->setPushConstants(&pc, sizeof(pc));
  236. if(preferCompute)
  237. {
  238. dispatchPPCompute(cmdb, 8, 8, m_r->getPostProcessResolution().x(), m_r->getPostProcessResolution().y());
  239. }
  240. else
  241. {
  242. cmdb->setViewport(0, 0, m_r->getPostProcessResolution().x(), m_r->getPostProcessResolution().y());
  243. cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 3);
  244. }
  245. }
  246. } // end namespace anki