Tonemapping.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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/Tonemapping.h>
  6. #include <AnKi/Renderer/DownscaleBlur.h>
  7. #include <AnKi/Renderer/Renderer.h>
  8. namespace anki {
  9. Error Tonemapping::init()
  10. {
  11. const Error err = initInternal();
  12. if(err)
  13. {
  14. ANKI_R_LOGE("Failed to initialize tonemapping");
  15. }
  16. return err;
  17. }
  18. Error Tonemapping::initInternal()
  19. {
  20. m_inputTexMip = m_r->getDownscaleBlur().getMipmapCount() - 2;
  21. const U32 width = m_r->getDownscaleBlur().getPassWidth(m_inputTexMip);
  22. const U32 height = m_r->getDownscaleBlur().getPassHeight(m_inputTexMip);
  23. ANKI_R_LOGV("Initializing tonemapping. Resolution %ux%u", width, height);
  24. // Create program
  25. ANKI_CHECK(getResourceManager().loadResource("ShaderBinaries/TonemappingAverageLuminance.ankiprogbin", m_prog));
  26. ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
  27. variantInitInfo.addConstant("INPUT_TEX_SIZE", UVec2(width, height));
  28. const ShaderProgramResourceVariant* variant;
  29. m_prog->getOrCreateVariant(variantInitInfo, variant);
  30. m_grProg = variant->getProgram();
  31. // Create buffer
  32. m_luminanceBuff = getGrManager().newBuffer(BufferInitInfo(
  33. sizeof(Vec4), BufferUsageBit::ALL_STORAGE | BufferUsageBit::ALL_UNIFORM | BufferUsageBit::TRANSFER_DESTINATION,
  34. BufferMapAccessBit::NONE, "AvgLum"));
  35. CommandBufferInitInfo cmdbinit;
  36. cmdbinit.m_flags = CommandBufferFlag::SMALL_BATCH | CommandBufferFlag::GENERAL_WORK;
  37. CommandBufferPtr cmdb = getGrManager().newCommandBuffer(cmdbinit);
  38. TransferGpuAllocatorHandle handle;
  39. ANKI_CHECK(m_r->getResourceManager().getTransferGpuAllocator().allocate(sizeof(Vec4), handle));
  40. void* data = handle.getMappedMemory();
  41. *static_cast<Vec4*>(data) = Vec4(0.5);
  42. cmdb->copyBufferToBuffer(handle.getBuffer(), handle.getOffset(), m_luminanceBuff, 0, handle.getRange());
  43. FencePtr fence;
  44. cmdb->flush({}, &fence);
  45. m_r->getResourceManager().getTransferGpuAllocator().release(handle, fence);
  46. return Error::NONE;
  47. }
  48. void Tonemapping::importRenderTargets(RenderingContext& ctx)
  49. {
  50. // Computation of the AVG luminance will run first in the frame and it will use the m_luminanceBuff as storage
  51. // read/write. To skip the barrier import it as read/write as well.
  52. m_runCtx.m_buffHandle = ctx.m_renderGraphDescr.importBuffer(
  53. m_luminanceBuff, BufferUsageBit::STORAGE_COMPUTE_READ | BufferUsageBit::STORAGE_COMPUTE_WRITE);
  54. }
  55. void Tonemapping::populateRenderGraph(RenderingContext& ctx)
  56. {
  57. RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
  58. // Create the pass
  59. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("Avg lum");
  60. pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
  61. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  62. cmdb->bindShaderProgram(m_grProg);
  63. rgraphCtx.bindStorageBuffer(0, 1, m_runCtx.m_buffHandle);
  64. TextureSubresourceInfo inputTexSubresource;
  65. inputTexSubresource.m_firstMipmap = m_inputTexMip;
  66. rgraphCtx.bindTexture(0, 0, m_r->getDownscaleBlur().getRt(), inputTexSubresource);
  67. cmdb->dispatchCompute(1, 1, 1);
  68. });
  69. pass.newDependency(
  70. {m_runCtx.m_buffHandle, BufferUsageBit::STORAGE_COMPUTE_READ | BufferUsageBit::STORAGE_COMPUTE_WRITE});
  71. TextureSubresourceInfo inputTexSubresource;
  72. inputTexSubresource.m_firstMipmap = m_inputTexMip;
  73. pass.newDependency({m_r->getDownscaleBlur().getRt(), TextureUsageBit::SAMPLED_COMPUTE, inputTexSubresource});
  74. }
  75. } // end namespace anki