sync.d 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. module three.gl.sync;
  2. public import derelict.opengl3.gl3;
  3. import three.gl.util;
  4. import std.experimental.logger;
  5. enum kOneSecondInNanoSeconds = GLuint64(1000000000);
  6. struct GlSyncManager {
  7. private:
  8. struct LockRange
  9. {
  10. size_t startOffset;
  11. size_t length;
  12. bool overlaps(LockRange rhs) pure const const @safe nothrow {
  13. return startOffset < (rhs.startOffset + rhs.length) && rhs.startOffset < (startOffset + length);
  14. }
  15. }
  16. struct Lock
  17. {
  18. LockRange range;
  19. GLsync sync;
  20. }
  21. Lock[] locks;
  22. public:
  23. void construct() pure @safe nothrow @nogc {
  24. }
  25. void destruct() pure @safe nothrow @nogc {
  26. }
  27. void waitForLockedRange(size_t lockBeginOffset, size_t lockLength) nothrow {
  28. LockRange testRange = LockRange(lockBeginOffset, lockLength);
  29. Lock[] swapLocks;
  30. foreach(ref lock; locks) {
  31. if (testRange.overlaps(lock.range)) {
  32. waitForSync(lock.sync);
  33. glCheck!glDeleteSync(lock.sync);
  34. }
  35. else {
  36. swapLocks ~= lock;
  37. }
  38. }
  39. locks = swapLocks;
  40. }
  41. void lockRange(size_t lockBeginOffset, size_t lockLength) nothrow {
  42. LockRange newRange = LockRange(lockBeginOffset, lockLength);
  43. GLsync syncName = glCheck!glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
  44. locks ~= Lock(newRange, syncName);
  45. }
  46. private:
  47. void waitForSync(ref GLsync sync) nothrow {
  48. version(LockBusyWait) {
  49. GLbitfield waitFlags = 0;
  50. GLuint64 waitDuration = 0;
  51. while(true) {
  52. GLenum waitRet = glCheck!glClientWaitSync(sync, waitFlags, waitDuration);
  53. if (waitRet == GL_ALREADY_SIGNALED || waitRet == GL_CONDITION_SATISFIED) {
  54. return;
  55. }
  56. if (waitRet == GL_WAIT_FAILED) {
  57. assert(!"Not sure what to do here. Probably raise an exception or something.");
  58. return;
  59. }
  60. // After the first time, need to start flushing, and wait for a looong time.
  61. waitFlags = GL_SYNC_FLUSH_COMMANDS_BIT;
  62. waitDuration = kOneSecondInNanoSeconds;
  63. }
  64. }
  65. else {
  66. glCheck!glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
  67. }
  68. }
  69. }