Skip to content

GltfLoader is slow populating buffers #2125

@tonihele

Description

@tonihele

GltfLoader is slow populating buffers. Like super slow. It takes ages to load the textures. They are read one byte at a time. From memory, so disk I/O is not the problem here. It takes way over 10 minutes (I had to stop it running). It is a long time. I profiled and the problems are the tangent generating and GltfUtils.populateXArray methods. In this particular case, the populateByteArray. But all of the populate methods could be significantly made faster.

        int arrayIndex = 0;
        byte[] buffer = new byte[numComponents];
        while (index < end) {
            stream.read(buffer, 0, numComponents);
            System.arraycopy(buffer, 0, array, arrayIndex, numComponents);
            arrayIndex += numComponents;
            if (dataLength < stride) {
                stream.skipBytes(stride - dataLength);
            }
            index += stride;
        }

This is a great start, but with the images in this sample I used, come down to having dataLength == stride (both actually 1). So following shortcut should be considered:

    private static void populateByteArray(byte[] array, LittleEndien stream, int count, int byteOffset, int byteStride, int numComponents, VertexBuffer.Format format) throws IOException {
        int componentSize = format.getComponentSize();
        int index = byteOffset;
        int dataLength = componentSize * numComponents;
        int stride = Math.max(dataLength, byteStride);
        int end = count * stride + byteOffset;
        stream.skipBytes(byteOffset);

// Shortcut, read all
        if (dataLength == stride) {
            byte[] buffer = new byte[end - index];
            stream.read(buffer, 0, buffer.length);
            System.arraycopy(buffer, 0, array, 0, buffer.length);

            return;
        }

        int arrayIndex = 0;
        byte[] buffer = new byte[numComponents];
        while (index < end) {
            stream.read(buffer, 0, numComponents);
            System.arraycopy(buffer, 0, array, arrayIndex, numComponents);
            arrayIndex += numComponents;
            if (dataLength < stride) {
                stream.skipBytes(stride - dataLength);
            }
            index += stride;
        }
    }

With this shortcut the data is just read instantly. The images are quite huge. I still haven't managed to read the scene to jME. So this is why I post this issue here, instead of a PR.

I tested with the Bistro scene. Loaded it in Blender, exported as GLB.
https://developer.nvidia.com/orca/amazon-lumberyard-bistro

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions