Skip to content

Commit

Permalink
Process GLTFBufferParser and GLTFTextureParser pipelines in parallel (#…
Browse files Browse the repository at this point in the history
…1638)

* feat: process GLTFBufferParser and GLTFTextureParser pipelines in parallel
  • Loading branch information
zhuxudong authored Jul 7, 2023
1 parent f69606f commit fe24102
Show file tree
Hide file tree
Showing 8 changed files with 417 additions and 360 deletions.
82 changes: 43 additions & 39 deletions packages/loader/src/gltf/GLTFUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,54 +110,58 @@ export class GLTFUtils {
}
}

static getAccessorBuffer(context: GLTFParserContext, bufferViews: IBufferView[], accessor: IAccessor): BufferInfo {
const { buffers } = context;

static getAccessorBuffer(
context: GLTFParserContext,
bufferViews: IBufferView[],
accessor: IAccessor
): Promise<BufferInfo> {
const componentType = accessor.componentType;
const bufferView = bufferViews[accessor.bufferView];

const bufferIndex = bufferView.buffer;
const buffer = buffers[bufferIndex];
const bufferByteOffset = bufferView.byteOffset || 0;
const byteOffset = accessor.byteOffset || 0;

const TypedArray = GLTFUtils.getComponentType(componentType);
const dataElementSize = GLTFUtils.getAccessorTypeSize(accessor.type);
const dataElementBytes = TypedArray.BYTES_PER_ELEMENT;
const elementStride = dataElementSize * dataElementBytes;
const accessorCount = accessor.count;
const bufferStride = bufferView.byteStride;

let bufferInfo: BufferInfo;
// According to the glTF official documentation only byteStride not undefined is allowed
if (bufferStride !== undefined && bufferStride !== elementStride) {
const bufferSlice = Math.floor(byteOffset / bufferStride);
const bufferCacheKey = accessor.bufferView + ":" + componentType + ":" + bufferSlice + ":" + accessorCount;
const accessorBufferCache = context.accessorBufferCache;
bufferInfo = accessorBufferCache[bufferCacheKey];
if (!bufferInfo) {
const offset = bufferByteOffset + bufferSlice * bufferStride;
const count = accessorCount * (bufferStride / dataElementBytes);
return context.getBuffers().then((buffers) => {
const bufferIndex = bufferView.buffer;
const buffer = buffers[bufferIndex];
const bufferByteOffset = bufferView.byteOffset || 0;
const byteOffset = accessor.byteOffset || 0;

const TypedArray = GLTFUtils.getComponentType(componentType);
const dataElementSize = GLTFUtils.getAccessorTypeSize(accessor.type);
const dataElementBytes = TypedArray.BYTES_PER_ELEMENT;
const elementStride = dataElementSize * dataElementBytes;
const accessorCount = accessor.count;
const bufferStride = bufferView.byteStride;

let bufferInfo: BufferInfo;
// According to the glTF official documentation only byteStride not undefined is allowed
if (bufferStride !== undefined && bufferStride !== elementStride) {
const bufferSlice = Math.floor(byteOffset / bufferStride);
const bufferCacheKey = accessor.bufferView + ":" + componentType + ":" + bufferSlice + ":" + accessorCount;
const accessorBufferCache = context.accessorBufferCache;
bufferInfo = accessorBufferCache[bufferCacheKey];
if (!bufferInfo) {
const offset = bufferByteOffset + bufferSlice * bufferStride;
const count = accessorCount * (bufferStride / dataElementBytes);
const data = new TypedArray(buffer, offset, count);
accessorBufferCache[bufferCacheKey] = bufferInfo = new BufferInfo(data, true, bufferStride);
bufferInfo.restoreInfo = new BufferDataRestoreInfo(
new RestoreDataAccessor(bufferIndex, TypedArray, offset, count)
);
}
} else {
const offset = bufferByteOffset + byteOffset;
const count = accessorCount * dataElementSize;
const data = new TypedArray(buffer, offset, count);
accessorBufferCache[bufferCacheKey] = bufferInfo = new BufferInfo(data, true, bufferStride);
bufferInfo = new BufferInfo(data, false, elementStride);
bufferInfo.restoreInfo = new BufferDataRestoreInfo(
new RestoreDataAccessor(bufferIndex, TypedArray, offset, count)
);
}
} else {
const offset = bufferByteOffset + byteOffset;
const count = accessorCount * dataElementSize;
const data = new TypedArray(buffer, offset, count);
bufferInfo = new BufferInfo(data, false, elementStride);
bufferInfo.restoreInfo = new BufferDataRestoreInfo(
new RestoreDataAccessor(bufferIndex, TypedArray, offset, count)
);
}

if (accessor.sparse) {
GLTFUtils.processingSparseData(bufferViews, accessor, buffers, bufferInfo);
}
return bufferInfo;
if (accessor.sparse) {
GLTFUtils.processingSparseData(bufferViews, accessor, buffers, bufferInfo);
}
return bufferInfo;
});
}

/**
Expand Down
52 changes: 27 additions & 25 deletions packages/loader/src/gltf/extensions/KHR_draco_mesh_compression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ class KHR_draco_mesh_compression extends GLTFExtensionParser {
) {
const {
glTF,
buffers,
glTFResource: { engine }
} = context;
const { bufferViews, accessors } = glTF;
Expand All @@ -53,30 +52,33 @@ class KHR_draco_mesh_compression extends GLTFExtensionParser {
useUniqueIDs: true,
indexType
};
const buffer = GLTFUtils.getBufferViewData(bufferViews[bufferViewIndex], buffers);
return KHR_draco_mesh_compression._decoder.decode(buffer, taskConfig).then((decodedGeometry) => {
const mesh = new ModelMesh(engine, glTFMesh.name);
return this._parseMeshFromGLTFPrimitiveDraco(
mesh,
glTFMesh,
glTFPrimitive,
glTF,
(attributeSemantic) => {
for (let j = 0; j < decodedGeometry.attributes.length; j++) {
if (decodedGeometry.attributes[j].name === attributeSemantic) {
return decodedGeometry.attributes[j].array;

return context.getBuffers().then((buffers) => {
const buffer = GLTFUtils.getBufferViewData(bufferViews[bufferViewIndex], buffers);
return KHR_draco_mesh_compression._decoder.decode(buffer, taskConfig).then((decodedGeometry) => {
const mesh = new ModelMesh(engine, glTFMesh.name);
return this._parseMeshFromGLTFPrimitiveDraco(
mesh,
glTFMesh,
glTFPrimitive,
glTF,
(attributeSemantic) => {
for (let j = 0; j < decodedGeometry.attributes.length; j++) {
if (decodedGeometry.attributes[j].name === attributeSemantic) {
return decodedGeometry.attributes[j].array;
}
}
}
return null;
},
(attributeSemantic, shapeIndex) => {
throw "BlendShape animation is not supported when using draco.";
},
() => {
return decodedGeometry.index.array;
},
context.keepMeshData
);
return null;
},
(attributeSemantic, shapeIndex) => {
throw "BlendShape animation is not supported when using draco.";
},
() => {
return decodedGeometry.index.array;
},
context.keepMeshData
);
});
});
}

Expand All @@ -86,7 +88,7 @@ class KHR_draco_mesh_compression extends GLTFExtensionParser {
gltfPrimitive: IMeshPrimitive,
gltf: IGLTF,
getVertexBufferData: (semantic: string) => TypedArray,
getBlendShapeData: (semantic: string, shapeIndex: number) => BufferInfo,
getBlendShapeData: (semantic: string, shapeIndex: number) => Promise<BufferInfo>,
getIndexBufferData: () => TypedArray,
keepMeshData: boolean
): Promise<ModelMesh> {
Expand Down
Loading

0 comments on commit fe24102

Please sign in to comment.