1
1

sync.d 1.7 KB

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