Skip to content

Commit b98e4ba

Browse files
committed
Batcher : Added BytesArray to avoid large Bytes allocation
1 parent ecd2044 commit b98e4ba

2 files changed

Lines changed: 80 additions & 40 deletions

File tree

h3d/prim/BatchPrimitive.hx

Lines changed: 76 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,51 @@
11
package h3d.prim;
22

3+
class BytesArray {
4+
public var bytes(default, null) : Array<haxe.io.Bytes>;
5+
public var pos(default, null) : Array<Int>;
6+
public var totalSize(default, null) : Int;
7+
var maxSize : Int;
8+
9+
public function new(bSize: Int, maxSize : Int) {
10+
if ( bSize > maxSize && maxSize > 0 )
11+
throw "assert";
12+
this.maxSize = maxSize;
13+
bytes = [haxe.io.Bytes.alloc(bSize)];
14+
pos = [0];
15+
}
16+
17+
public function alloc(bSize : Int) : { b : haxe.io.Bytes, pos : Int } {
18+
if ( bSize > maxSize && maxSize > 0 )
19+
throw "assert";
20+
totalSize += bSize;
21+
var bIdx = bytes.length - 1;
22+
var b = bytes[bIdx];
23+
var bStart = pos[bIdx];
24+
var bNeeded = bStart + bSize;
25+
if ( bNeeded > b.length ) {
26+
if ( bNeeded < maxSize || maxSize < 0 ) {
27+
var oldB = b;
28+
b = bytes[bIdx] = haxe.io.Bytes.alloc( (bNeeded >> 1) * 3 );
29+
b.blit(0, oldB, 0, bStart);
30+
} else {
31+
b = bytes[++bIdx] = haxe.io.Bytes.alloc(bSize);
32+
bNeeded = bSize;
33+
bStart = 0;
34+
}
35+
}
36+
pos[bIdx] = bNeeded;
37+
return { b : b, pos : bStart };
38+
}
39+
40+
public function upload( buffer : h3d.Buffer, vStart : Int = 0 ) {
41+
for ( i => b in bytes ) {
42+
var vCount = Std.int(pos[i] / buffer.format.strideBytes);
43+
buffer.uploadBytes(b, 0, vCount, vStart);
44+
vStart += vCount;
45+
}
46+
}
47+
}
48+
349
class SubMesh {
450
public var subParts : Array<SubPart>;
551
public var subPartStart : Int;
@@ -27,10 +73,10 @@ class BatchPrimitive extends MeshPrimitive {
2773
public var subMeshes(default, null) : Array<SubMesh> = [];
2874
var models(default, null) : Array<h3d.prim.HMDModel> = [];
2975
var bounds = new h3d.col.Bounds();
30-
var vbuf : haxe.io.Bytes;
31-
var vByteStart : Int = 0;
32-
var ibuf : haxe.io.Bytes;
33-
var iByteStart : Int = 0;
76+
77+
var vBytes : BytesArray;
78+
var iBytes : BytesArray;
79+
var maxByteSize = -1;
3480

3581
var subMeshCount : Int = 0;
3682
public var cpuSubMeshInfos : haxe.io.Bytes;
@@ -46,11 +92,9 @@ class BatchPrimitive extends MeshPrimitive {
4692
public var hasLogicNormal(get, never) : Bool;
4793
function get_hasLogicNormal() return logicNormals != null;
4894

49-
public function new(format) {
95+
public function new(format, maxByteSize = -1) {
5096
vertexFormat = format;
51-
52-
vbuf = haxe.io.Bytes.alloc(0);
53-
ibuf = haxe.io.Bytes.alloc(0);
97+
this.maxByteSize = maxByteSize;
5498
}
5599

56100
public function addModel( model : h3d.prim.HMDModel ) : Int {
@@ -95,44 +139,38 @@ class BatchPrimitive extends MeshPrimitive {
95139

96140
for ( lod in model.lods ) {
97141
var vByteSize = lod.vertexCount * vertexFormat.strideBytes;
98-
var vByteNeeded = vByteStart + vByteSize;
99-
if ( vByteNeeded > vbuf.length ) {
100-
var oldVbuf = vbuf;
101-
vbuf = haxe.io.Bytes.alloc( (vByteNeeded >> 1) * 3 );
102-
vbuf.blit(0, oldVbuf, 0, vByteStart);
103-
}
142+
if ( vBytes == null )
143+
vBytes = new BytesArray(vByteSize, maxByteSize);
144+
var vStart = Std.int(vBytes.totalSize / vertexFormat.strideBytes);
145+
var vAlloc = vBytes.alloc(vByteSize);
146+
var vbuf = vAlloc.b;
147+
var vByteStart = vAlloc.pos;
104148
var vertices = entry.fetchBytes(dataPosition + lod.vertexPosition, vByteSize);
105149
vbuf.blit(vByteStart, vertices, 0, vByteSize);
106150

107151
var iCount = lod.indexCount;
108152
var iByteSize = iCount * 4;
109-
var iByteNeeded = iByteStart + iByteSize;
110-
if ( iByteNeeded > ibuf.length ) {
111-
var oldIbuf = ibuf;
112-
ibuf = haxe.io.Bytes.alloc( (iByteNeeded >> 1) * 3 );
113-
ibuf.blit(0, oldIbuf, 0, iByteStart);
153+
if ( iBytes == null )
154+
iBytes = new BytesArray(iByteSize, maxByteSize);
155+
156+
var iStart = iBytes.totalSize >> 2;
157+
for ( count in lod.indexCounts ) {
158+
indexStarts.push(iStart);
159+
iStart += count;
114160
}
115161

162+
var iAlloc = iBytes.alloc(iByteSize);
163+
var ibuf = iAlloc.b;
164+
var iByteStart = iAlloc.pos;
165+
116166
var lodIs32 = lod.vertexCount > 0x10000;
117167
var iLodByteSize = (lodIs32 ? 4 : 2) * iCount;
118-
var inIndices = entry.fetchBytes(dataPosition + lod.indexPosition, iLodByteSize);
119-
var outIndices : haxe.io.Bytes = !lodIs32 ? haxe.io.Bytes.alloc( iCount * 4 ) : inIndices;
120-
var vStart = Std.int(vByteStart / vertexFormat.strideBytes);
168+
var indices = entry.fetchBytes(dataPosition + lod.indexPosition, iLodByteSize);
121169
for ( i in 0...iCount )
122170
if ( lodIs32 )
123-
outIndices.setInt32(i << 2, inIndices.getInt32(i << 2) + vStart);
171+
ibuf.setInt32(iByteStart + (i << 2), indices.getInt32(i << 2) + vStart);
124172
else
125-
outIndices.setInt32(i << 2, inIndices.getUInt16(i << 1) + vStart);
126-
ibuf.blit(iByteStart, outIndices, 0, iByteSize);
127-
128-
var iStart = iByteStart >> 2;
129-
for ( count in lod.indexCounts ) {
130-
indexStarts.push(iStart);
131-
iStart += count;
132-
}
133-
134-
vByteStart = vByteNeeded;
135-
iByteStart = iByteNeeded;
173+
ibuf.setInt32(iByteStart + (i << 2), indices.getUInt16(i << 1) + vStart);
136174
}
137175

138176
for ( matIdx in 0...matCount ) {
@@ -268,13 +306,13 @@ class BatchPrimitive extends MeshPrimitive {
268306
override public function alloc( engine : h3d.Engine ) {
269307
dispose();
270308

271-
var vCount = Std.int(vByteStart / vertexFormat.strideBytes);
309+
var vCount = Std.int(vBytes.totalSize / vertexFormat.strideBytes);
272310
buffer = new h3d.Buffer(vCount, vertexFormat);
273-
buffer.uploadBytes(vbuf, 0, vCount);
311+
vBytes.upload(buffer);
274312

275-
var iCount = iByteStart >> 2;
313+
var iCount = iBytes.totalSize >> 2;
276314
indexes = new h3d.Indexes(iCount, true);
277-
indexes.uploadBytes(ibuf, 0, iCount);
315+
iBytes.upload(indexes);
278316

279317
if ( hasLogicNormal )
280318
addBuffer(h3d.Buffer.ofFloats(logicNormals, hxd.BufferFormat.make([{ name : "logicNormal", type : DVec3 }])));

h3d/scene/Batcher.hx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,17 @@ class BatchLibrary {
1919
static final BATCH_START_FMT = hxd.BufferFormat.make([{ name : "Batch_Start", type : DFloat }]);
2020
var primitives : Array<h3d.prim.BatchPrimitive> = [];
2121
var instancesOffset : h3d.Buffer;
22+
var maxUploadSize : Int;
2223

23-
public function new() {
24+
public function new(maxUploadSize = -1) {
25+
this.maxUploadSize = maxUploadSize;
2426
}
2527

2628
function getPrimitive( format : hxd.BufferFormat ) {
2729
for ( p in primitives )
2830
if ( p.vertexFormat == format )
2931
return p;
30-
var p = new h3d.prim.BatchPrimitive(format);
32+
var p = new h3d.prim.BatchPrimitive(format, maxUploadSize);
3133
primitives.push(p);
3234
return p;
3335
}

0 commit comments

Comments
 (0)