Deinterleaved Vertex Buffer Update

This commit is contained in:
2026-10-09 16:30:11 -07:00
parent c320c4bb19
commit c1aa2837ca
3 changed files with 97 additions and 14 deletions

View File

@ -14,6 +14,7 @@ import iron.math.Vec4;
import iron.math.Mat4; import iron.math.Mat4;
import iron.data.SceneFormat; import iron.data.SceneFormat;
import iron.data.MeshData; import iron.data.MeshData;
import iron.data.ShaderData;
class Geometry { class Geometry {
#if lnx_deinterleaved #if lnx_deinterleaved
@ -208,7 +209,7 @@ class Geometry {
for (v in 0...vertexBuffers.length) for (v in 0...vertexBuffers.length)
if (vertexBuffers[v].name == e.name) { if (vertexBuffers[v].name == e.name) {
vbs.push(vertexBuffers[v].buffer); vbs.push(vertexBuffers[v].buffer);
continue; break;
} }
if (e.name == "ipos" && instancedVB != null) { if (e.name == "ipos" && instancedVB != null) {
vbs.push(instancedVB); vbs.push(instancedVB);
@ -264,7 +265,7 @@ class Geometry {
for (i in 0...vaLength) for (i in 0...vaLength)
vertexBuffers[i] = { vertexBuffers[i] = {
name: vertexArrays[i].attrib, name: vertexArrays[i].attrib,
buffer: makeDeinterleavedVB(vertexArrays[i].values, vertexArrays[i].attrib, vertexArrays[i].size) buffer: makeDeinterleavedVB(vertexArrays[i])
}; };
#else #else
@ -295,14 +296,20 @@ class Geometry {
} }
#if lnx_deinterleaved #if lnx_deinterleaved
function makeDeinterleavedVB(data: ByteArray, name: String, structLength: Int): VertexBuffer { function makeDeinterleavedVB(va: TVertexArray): VertexBuffer {
var struct = new VertexStructure(); var struct = new VertexStructure();
struct.add(name, structLength == 2 ? VertexData.Short2Norm : VertexData.Short4Norm); struct.add(va.attrib, ShaderContext.parseData(va.data));
var vertexBuffer = new VertexBuffer(Std.int(data.byteLength / 2 / structLength), struct, usage); var vcount = verticesCount(va);
var vertexBuffer = new VertexBuffer(vcount, struct, usage);
var stride = Std.int(struct.byteSize() / 2);
var vertices = vertexBuffer.lock(); var vertices = vertexBuffer.lock();
for (i in 0...Std.int(vertices.byteLength / 2)) vertices.setInt16(i * 2, data.getInt16(i * 2)); var di = -1;
for (i in 0...vcount) {
for (o in 0...va.size) vertices.setInt16(++di * 2, va.values[i * va.size + o]);
for (o in va.size...stride) vertices.setInt16(++di * 2, 0);
}
vertexBuffer.unlock(); vertexBuffer.unlock();
return vertexBuffer; return vertexBuffer;

View File

@ -73,11 +73,11 @@ class MeshBatch {
var scontext = b.shader.getContext(context); var scontext = b.shader.getContext(context);
if (scontext == null) continue; if (scontext == null) continue;
g.setPipeline(scontext.pipeState); g.setPipeline(scontext.pipeState);
// #if lnx_deinterleaved // TODO #if lnx_deinterleaved
// g.setVertexBuffers(b.vertexBuffers); g.setVertexBuffers(b.getVertexBuffers(scontext.raw.vertex_elements));
// #else #else
g.setVertexBuffer(b.getVertexBuffer(scontext.raw.vertex_elements)); g.setVertexBuffer(b.getVertexBuffer(scontext.raw.vertex_elements));
// #end #end
g.setIndexBuffer(b.indexBuffer); g.setIndexBuffer(b.indexBuffer);
Uniforms.setContextConstants(g, scontext, bindParams); Uniforms.setContextConstants(g, scontext, bindParams);
@ -127,8 +127,12 @@ class Bucket {
public var batched = false; public var batched = false;
public var shader: ShaderData; public var shader: ShaderData;
#if lnx_deinterleaved
public var vertexBuffers: Array<InterleavedVertexBuffer> = [];
#else
var vertexBuffer: VertexBuffer; var vertexBuffer: VertexBuffer;
var vertexBufferMap: Map<String, VertexBuffer> = new Map(); var vertexBufferMap: Map<String, VertexBuffer> = new Map();
#end
public var indexBuffer: IndexBuffer; public var indexBuffer: IndexBuffer;
public var meshes: Array<MeshObject> = []; public var meshes: Array<MeshObject> = [];
@ -138,8 +142,12 @@ class Bucket {
public function remove() { public function remove() {
indexBuffer.delete(); indexBuffer.delete();
#if lnx_deinterleaved
for (buf in vertexBuffers) buf.buffer.delete();
#else
// this.vertexBuffer is in the map, so it's also deleted here // this.vertexBuffer is in the map, so it's also deleted here
for (buf in vertexBufferMap) buf.delete(); for (buf in vertexBufferMap) buf.delete();
#end
meshes = []; meshes = [];
} }
@ -151,6 +159,20 @@ class Bucket {
meshes.remove(m); meshes.remove(m);
} }
#if lnx_deinterleaved
public function getVertexBuffers(elems: Array<TVertexElement>): Array<VertexBuffer> {
var vbs: Array<VertexBuffer> = [];
for (e in elems) {
for (v in vertexBuffers) {
if (v.name == e.name) {
vbs.push(v.buffer);
break;
}
}
}
return vbs;
}
#else
function copyAttribute(attribSize: Int, count: Int, to: ByteArray, toStride: Int, toOffset: Int, from: ByteArray, fromStride: Int, fromOffset: Int) { function copyAttribute(attribSize: Int, count: Int, to: ByteArray, toStride: Int, toOffset: Int, from: ByteArray, fromStride: Int, fromOffset: Int) {
for (i in 0...count) { for (i in 0...count) {
for (j in 0...attribSize) { for (j in 0...attribSize) {
@ -196,6 +218,7 @@ class Bucket {
} }
return vb; return vb;
} }
#end
function vertexCount(g: Geometry, hasUVs: Bool): Int { function vertexCount(g: Geometry, hasUVs: Bool): Int {
var vcount = g.getVerticesLength(); var vcount = g.getVerticesLength();
@ -240,6 +263,50 @@ class Bucket {
if (mdatas.length == 0) return; if (mdatas.length == 0) return;
#if lnx_deinterleaved
var attrNames: Array<String> = [];
var attrReps = new Map<String, TVertexArray>();
for (md in mdatas) {
for (va in md.geom.vertexArrays) {
if (attrReps.get(va.attrib) == null) {
attrReps.set(va.attrib, va);
attrNames.push(va.attrib);
}
}
}
for (name in attrNames) {
var rep = attrReps.get(name);
var attrStruct = new VertexStructure();
attrStruct.add(name, ShaderContext.parseData(rep.data));
var stride = Std.int(attrStruct.byteSize() / 2);
var vtotal = 0;
for (md in mdatas) vtotal += md.geom.getVerticesCount();
var vb = new VertexBuffer(vtotal, attrStruct, Usage.StaticUsage);
var vertices = vb.lock();
var ai = -1;
for (md in mdatas) {
var va: TVertexArray = null;
for (v in md.geom.vertexArrays) {
if (v.attrib == name) {
va = v;
break;
}
}
if (va != null && va.values != null) {
var nverts = md.geom.getVerticesCount();
for (i in 0...nverts) {
for (o in 0...va.size) vertices.setInt16(++ai * 2, va.values[i * va.size + o]);
for (o in va.size...stride) vertices.setInt16(++ai * 2, 0);
}
}
else {
for (i in 0...md.geom.getVerticesCount() * stride) vertices.setInt16(++ai * 2, 0);
}
}
vb.unlock();
vertexBuffers.push({name: name, buffer: vb});
}
#else
// Pick UVs if present // Pick UVs if present
var vs = mdatas[0].geom.struct; var vs = mdatas[0].geom.struct;
for (md in mdatas) if (md.geom.struct.size() > vs.size()) vs = md.geom.struct; for (md in mdatas) if (md.geom.struct.size() > vs.size()) vs = md.geom.struct;

View File

@ -102,8 +102,9 @@ class ShaderContext {
constants = []; constants = [];
textureUnits = []; textureUnits = [];
var instStruct: VertexStructure = null;
if (instancingType > 0) { // Instancing if (instancingType > 0) { // Instancing
var instStruct = new VertexStructure(); instStruct = new VertexStructure();
instStruct.add("ipos", VertexData.Float3); instStruct.add("ipos", VertexData.Float3);
if (instancingType == 2 || instancingType == 4) { if (instancingType == 2 || instancingType == 4) {
instStruct.add("irot", VertexData.Float3); instStruct.add("irot", VertexData.Float3);
@ -117,11 +118,19 @@ class ShaderContext {
this.instanceStride = Std.int(instStruct.byteSize() / 4); this.instanceStride = Std.int(instStruct.byteSize() / 4);
instStruct.instanced = true; instStruct.instanced = true;
pipeState.inputLayout = [structure, instStruct];
} }
else { // Regular #if lnx_deinterleaved
pipeState.inputLayout = [structure]; var layouts: Array<VertexStructure> = [];
for (e in structure.elements) {
var s = new VertexStructure();
s.add(e.name, e.data);
layouts.push(s);
} }
#else
var layouts = [structure];
#end
if (instStruct != null) layouts.push(instStruct);
pipeState.inputLayout = layouts;
// Depth // Depth
pipeState.depthWrite = raw.depth_write; pipeState.depthWrite = raw.depth_write;