Fence.cpp 2.5 KB

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