1
1

sync.d 1.8 KB

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