Fence.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // Copyright (C) 2009-2023, 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/Fence.h>
  6. #include <AnKi/Gr/gl/FenceImpl.h>
  7. #include <AnKi/Gr/CommandBuffer.h>
  8. #include <AnKi/Gr/gl/CommandBufferImpl.h>
  9. #include <AnKi/Gr/GrManager.h>
  10. #include <AnKi/Util/HighRezTimer.h>
  11. namespace anki {
  12. Bool Fence::clientWait(Second seconds)
  13. {
  14. if(static_cast<FenceImpl&>(*this).m_signaled.load())
  15. {
  16. return true;
  17. }
  18. class CheckFenceCommand final : public GlCommand
  19. {
  20. public:
  21. FencePtr m_fence;
  22. Second m_timeout;
  23. Second m_flushTime;
  24. Barrier* m_barrier;
  25. CheckFenceCommand(FencePtr fence, Second timeout, Second flushTime, Barrier* barrier)
  26. : m_fence(fence)
  27. , m_timeout(timeout)
  28. , m_flushTime(flushTime)
  29. , m_barrier(barrier)
  30. {
  31. }
  32. Error operator()(GlState&)
  33. {
  34. // Since there is a delay between flushing the cmdb and returning this result try to adjust the time we
  35. // wait
  36. Second timeToWait;
  37. if(m_timeout != 0.0)
  38. {
  39. timeToWait = m_timeout - (HighRezTimer::getCurrentTime() - m_flushTime);
  40. timeToWait = max(0.0, timeToWait);
  41. }
  42. else
  43. {
  44. timeToWait = 0.0;
  45. }
  46. FenceImpl& impl = static_cast<FenceImpl&>(*m_fence);
  47. GLenum out = glClientWaitSync(impl.m_fence, GL_SYNC_FLUSH_COMMANDS_BIT, timeToWait * 1e+9);
  48. if(out == GL_ALREADY_SIGNALED || out == GL_CONDITION_SATISFIED)
  49. {
  50. impl.m_signaled.store(true);
  51. }
  52. else if(out == GL_TIMEOUT_EXPIRED)
  53. {
  54. // Do nothing
  55. }
  56. else
  57. {
  58. ANKI_ASSERT(out == GL_WAIT_FAILED);
  59. return Error::kFunctionFailed;
  60. }
  61. if(m_barrier)
  62. {
  63. m_barrier->wait();
  64. }
  65. return Error::kNone;
  66. }
  67. };
  68. CommandBufferPtr cmdb = getManager().newCommandBuffer(CommandBufferInitInfo());
  69. if(seconds == 0.0)
  70. {
  71. // Send a cmd that will update the fence's status in case someone calls clientWait with seconds==0.0 all the
  72. // time
  73. static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<CheckFenceCommand>(FencePtr(this), seconds, 0.0, nullptr);
  74. static_cast<CommandBufferImpl&>(*cmdb).flush();
  75. return false;
  76. }
  77. else
  78. {
  79. Barrier barrier(2);
  80. Second flushTime = HighRezTimer::getCurrentTime();
  81. static_cast<CommandBufferImpl&>(*cmdb).pushBackNewCommand<CheckFenceCommand>(FencePtr(this), seconds, flushTime, &barrier);
  82. static_cast<CommandBufferImpl&>(*cmdb).flush();
  83. barrier.wait();
  84. return static_cast<FenceImpl&>(*this).m_signaled.load();
  85. }
  86. }
  87. } // end namespace anki