Scale.cpp 8.0 KB

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