ManagedBuffer.hx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. package h3d.impl;
  2. @:allow(h3d)
  3. private class FreeCell {
  4. var pos : Int;
  5. var count : Int;
  6. var next : FreeCell;
  7. function new(pos,count,next) {
  8. this.pos = pos;
  9. this.count = count;
  10. this.next = next;
  11. }
  12. }
  13. @:allow(h3d.impl.MemoryManager)
  14. class ManagedBuffer {
  15. var mem : MemoryManager;
  16. public var stride(default,null) : Int;
  17. public var size(default,null) : Int;
  18. public var flags(default, null) : haxe.EnumFlags<Buffer.BufferFlag>;
  19. var vbuf : Driver.VertexBuffer;
  20. var freeList : FreeCell;
  21. var next : ManagedBuffer;
  22. #if debug
  23. var allocHead : Buffer;
  24. #end
  25. public function new( stride, size, ?flags : Array<Buffer.BufferFlag> ) {
  26. this.flags = new haxe.EnumFlags();
  27. if( flags != null )
  28. for( f in flags )
  29. this.flags.set(f);
  30. this.size = size;
  31. this.stride = stride;
  32. this.freeList = new FreeCell(0, size, null);
  33. #if !noEngine
  34. this.mem = h3d.Engine.getCurrent().mem;
  35. mem.allocManaged(this);
  36. #end
  37. }
  38. public function uploadVertexBuffer( start : Int, vertices : Int, buf : hxd.FloatBuffer, bufPos = 0 ) {
  39. mem.driver.uploadVertexBuffer(vbuf, start, vertices, buf, bufPos);
  40. }
  41. public function uploadVertexBytes( start : Int, vertices : Int, data : haxe.io.Bytes, dataPos = 0 ) {
  42. mem.driver.uploadVertexBytes(vbuf, start, vertices, data, dataPos);
  43. }
  44. public function readVertexBytes( start : Int, vertices : Int, data : haxe.io.Bytes, dataPos = 0 ) {
  45. mem.driver.readVertexBytes(vbuf, start, vertices, data, dataPos);
  46. }
  47. public function alloc(vertices,align) {
  48. var p = allocPosition(vertices, align);
  49. if( p < 0 )
  50. return null;
  51. var b = new Buffer(vertices, stride, [NoAlloc]);
  52. @:privateAccess {
  53. b.position = p;
  54. b.buffer = this;
  55. };
  56. #if debug
  57. @:privateAccess b.allocNext = allocHead;
  58. allocHead = b;
  59. #end
  60. return b;
  61. }
  62. public function getFreeVertices() {
  63. var m = 0;
  64. var l = freeList;
  65. while( l != null ) {
  66. m += l.count;
  67. l = l.next;
  68. }
  69. return m;
  70. }
  71. function allocPosition( nvert : Int, align : Int ) {
  72. var free = freeList;
  73. while( free != null ) {
  74. if( free.count >= nvert ) {
  75. var d = (align - (free.pos % align)) % align;
  76. if( d == 0 )
  77. break;
  78. // insert some padding
  79. if( free.count >= nvert + d ) {
  80. free.next = new FreeCell(free.pos + d, free.count - d, free.next);
  81. free.count = d;
  82. free = free.next;
  83. break;
  84. }
  85. }
  86. free = free.next;
  87. }
  88. if( free == null )
  89. return -1;
  90. var pos = free.pos;
  91. free.pos += nvert;
  92. free.count -= nvert;
  93. return pos;
  94. }
  95. function allocBuffer( b : Buffer ) {
  96. var align = b.flags.has(Quads) ? 4 : (b.flags.has(Triangles) ? 3 : 1);
  97. var p = allocPosition(b.vertices, align);
  98. if( p < 0 ) return false;
  99. @:privateAccess {
  100. b.position = p;
  101. b.buffer = this;
  102. };
  103. #if debug
  104. @:privateAccess b.allocNext = allocHead;
  105. allocHead = b;
  106. #end
  107. return true;
  108. }
  109. @:allow(h3d.Buffer.dispose)
  110. function freeBuffer( b : Buffer ) {
  111. var prev : FreeCell = null;
  112. var f = freeList;
  113. var nvert = b.vertices;
  114. var end = b.position + nvert;
  115. while( f != null ) {
  116. if( f.pos == end ) {
  117. f.pos -= nvert;
  118. f.count += nvert;
  119. if( prev != null && prev.pos + prev.count == f.pos ) {
  120. prev.count += f.count;
  121. prev.next = f.next;
  122. }
  123. nvert = 0;
  124. break;
  125. }
  126. if( f.pos > end ) {
  127. if( prev != null && prev.pos + prev.count == b.position )
  128. prev.count += nvert;
  129. else {
  130. var n = new FreeCell(b.position, nvert, f);
  131. if( prev == null ) freeList = n else prev.next = n;
  132. }
  133. nvert = 0;
  134. break;
  135. }
  136. prev = f;
  137. f = f.next;
  138. }
  139. if( nvert != 0 )
  140. throw "assert";
  141. #if debug
  142. @:privateAccess {
  143. var cur = allocHead, prev : Buffer = null;
  144. while( cur != null ) {
  145. if( cur == b ) {
  146. if( prev == null )
  147. allocHead = b.allocNext;
  148. else
  149. prev.allocNext = b.allocNext;
  150. break;
  151. }
  152. prev = cur;
  153. cur = cur.allocNext;
  154. }
  155. }
  156. #end
  157. if( freeList.count == size && !flags.has(Managed) )
  158. dispose();
  159. }
  160. public function dispose() {
  161. mem.freeManaged(this);
  162. }
  163. public inline function isDisposed() {
  164. return vbuf == null;
  165. }
  166. }