ManagedBuffer.hx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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. public function new( stride, size, ?flags : Array<Buffer.BufferFlag> ) {
  23. this.flags = new haxe.EnumFlags();
  24. if( flags != null )
  25. for( f in flags )
  26. this.flags.set(f);
  27. this.mem = h3d.Engine.getCurrent().mem;
  28. this.size = size;
  29. this.stride = stride;
  30. this.freeList = new FreeCell(0, size, null);
  31. mem.allocManaged(this);
  32. }
  33. public function uploadVertexBuffer( start : Int, vertices : Int, buf : hxd.FloatBuffer, bufPos = 0 ) {
  34. mem.driver.uploadVertexBuffer(vbuf, start, vertices, buf, bufPos);
  35. }
  36. public function uploadVertexBytes( start : Int, vertices : Int, data : haxe.io.Bytes, dataPos = 0 ) {
  37. mem.driver.uploadVertexBytes(vbuf, start, vertices, data, dataPos);
  38. }
  39. public function alloc(vertices,align) {
  40. var p = allocPosition(vertices, align);
  41. if( p < 0 )
  42. return null;
  43. var b = new Buffer(vertices, stride, [NoAlloc]);
  44. @:privateAccess {
  45. b.position = p;
  46. b.buffer = this;
  47. };
  48. return b;
  49. }
  50. public function getFreeVertices() {
  51. var m = 0;
  52. var l = freeList;
  53. while( l != null ) {
  54. m += l.count;
  55. l = l.next;
  56. }
  57. return m;
  58. }
  59. function allocPosition( nvert : Int, align : Int ) {
  60. var free = freeList;
  61. while( free != null ) {
  62. if( free.count >= nvert ) {
  63. var d = (align - (free.pos % align)) % align;
  64. if( d == 0 )
  65. break;
  66. // insert some padding
  67. if( free.count >= nvert + d ) {
  68. free.next = new FreeCell(free.pos + d, free.count - d, free.next);
  69. free.count = d;
  70. free = free.next;
  71. break;
  72. }
  73. }
  74. free = free.next;
  75. }
  76. if( free == null )
  77. return -1;
  78. var pos = free.pos;
  79. free.pos += nvert;
  80. free.count -= nvert;
  81. return pos;
  82. }
  83. function allocBuffer( b : Buffer ) {
  84. var align = b.flags.has(Quads) ? 4 : (b.flags.has(Triangles) ? 3 : 1);
  85. var p = allocPosition(b.vertices, align);
  86. if( p < 0 ) return false;
  87. @:privateAccess {
  88. b.position = p;
  89. b.buffer = this;
  90. };
  91. return true;
  92. }
  93. @:allow(h3d.Buffer.dispose)
  94. function freeBuffer( b : Buffer ) {
  95. var prev : FreeCell = null;
  96. var f = freeList;
  97. var nvert = b.vertices;
  98. var end = b.position + nvert;
  99. while( f != null ) {
  100. if( f.pos == end ) {
  101. f.pos -= nvert;
  102. f.count += nvert;
  103. if( prev != null && prev.pos + prev.count == f.pos ) {
  104. prev.count += f.count;
  105. prev.next = f.next;
  106. }
  107. nvert = 0;
  108. break;
  109. }
  110. if( f.pos > end ) {
  111. if( prev != null && prev.pos + prev.count == b.position )
  112. prev.count += nvert;
  113. else {
  114. var n = new FreeCell(b.position, nvert, f);
  115. if( prev == null ) freeList = n else prev.next = n;
  116. }
  117. nvert = 0;
  118. break;
  119. }
  120. prev = f;
  121. f = f.next;
  122. }
  123. if( nvert != 0 )
  124. throw "assert";
  125. if( freeList.count == size && !flags.has(Managed) )
  126. dispose();
  127. }
  128. public function dispose() {
  129. mem.freeManaged(this);
  130. }
  131. public inline function isDisposed() {
  132. return vbuf == null;
  133. }
  134. }