1
1

sync.d 2.0 KB

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