Repository: playcanvas/engine
File: src/platform/graphics/transform-feedback.js (JavaScript)

Code before:
     * If not specified, a buffer with parameters matching the input buffer will be created.
     * @param {number} [usage] - The optional usage type of the output vertex buffer. Can be:
     *
     * - {@link BUFFER_STATIC}
     * - {@link BUFFER_DYNAMIC}
     * - {@link BUFFER_STREAM}
     * - {@link BUFFER_GPUDYNAMIC}
     *
     * Defaults to {@link BUFFER_GPUDYNAMIC} (which is recommended for continuous update).
     */
    constructor(inputBuffer, outputBuffer, usage = BUFFER_GPUDYNAMIC) {

        if (outputBuffer !== undefined && !(outputBuffer instanceof VertexBuffer)) {

            Debug.deprecated('Such a constructor that takes the second parameter usage is deprecated.');

            usage = outputBuffer;
            outputBuffer = undefined;
        }

        this.device = inputBuffer.device;

        const gl = this.device.gl;

        if (outputBuffer) {
            Debug.assert(outputBuffer.format.interleaved || outputBuffer.format.elements.length <= 1,
                'Output vertex buffer used by TransformFeedback needs to be interleaved.');

            if (usage === BUFFER_GPUDYNAMIC && outputBuffer.usage !== usage) {
                // have to recreate input buffer with other usage
                gl.bindBuffer(gl.ARRAY_BUFFER, outputBuffer.impl.bufferId);
                gl.bufferData(gl.ARRAY_BUFFER, outputBuffer.storage, gl.DYNAMIC_COPY);
            }

        } else {
            Debug.assert(inputBuffer.format.interleaved || inputBuffer.format.elements.length <= 1,
                'Input vertex buffer used by TransformFeedback needs to be interleaved.');

            if (usage === BUFFER_GPUDYNAMIC && inputBuffer.usage !== usage) {
                // have to recreate input buffer with other usage
                gl.bindBuffer(gl.ARRAY_BUFFER, inputBuffer.impl.bufferId);
                gl.bufferData(gl.ARRAY_BUFFER, inputBuffer.storage, gl.DYNAMIC_COPY);
            }
        }

        this._inputBuffer = inputBuffer;

        this._swapEquivalent = inputBuffer.format === outputBuffer?.format;
        this._destroyOutputBuffer = !outputBuffer;
        this._outputBuffer = outputBuffer ?? new VertexBuffer(inputBuffer.device, inputBuffer.format, inputBuffer.numVertices, {
            usage: usage,

Review comment (refactor):
this code is duplicated, just with a different buffer.
I suggest:
```
const outVB = outputBuffer ?? inputBuffer;

// run the code once on outVB
```

Code after:
     * If not specified, a buffer with parameters matching the input buffer will be created.
     * @param {number} [usage] - The optional usage type of the output vertex buffer. Can be:
     *
     * - {@link BUFFER_STATIC}
     * - {@link BUFFER_DYNAMIC}
     * - {@link BUFFER_STREAM}
     * - {@link BUFFER_GPUDYNAMIC}
     *
     * Defaults to {@link BUFFER_GPUDYNAMIC} (which is recommended for continuous update).
     */
    constructor(inputBuffer, outputBuffer, usage = BUFFER_GPUDYNAMIC) {

        if (outputBuffer !== undefined && !(outputBuffer instanceof VertexBuffer)) {

            Debug.deprecated('Such a constructor that takes the second parameter usage is deprecated.');

            usage = outputBuffer;
            outputBuffer = undefined;
        }

        this.device = inputBuffer.device;

        const gl = this.device.gl;
        const outVB = outputBuffer ?? inputBuffer;

        Debug.assert(outVB.format.interleaved || outVB.format.elements.length <= 1, outputBuffer ?
            'Output vertex buffer used by TransformFeedback needs to be interleaved.' :
            'Input vertex buffer used by TransformFeedback needs to be interleaved.'
        );

        if (usage === BUFFER_GPUDYNAMIC && outVB.usage !== usage) {
            // have to recreate input buffer with other usage
            gl.bindBuffer(gl.ARRAY_BUFFER, outVB.impl.bufferId);
            gl.bufferData(gl.ARRAY_BUFFER, outVB.storage, gl.DYNAMIC_COPY);
        }

        this._inputBuffer = inputBuffer;
        this._destroyOutputBuffer = !outputBuffer;
        this._outputBuffer = outputBuffer ?? new VertexBuffer(inputBuffer.device, inputBuffer.format, inputBuffer.numVertices, {
            usage: usage,
            data: inputBuffer.storage
        });
    }

    /**
     * Creates a transform feedback ready vertex shader from code.
     *
     * @param {GraphicsDevice} graphicsDevice - The graphics device used by the renderer.
     * @param {string} vertexCode - Vertex shader code. Should contain output variables starting with "out_" or feedbackVaryings.
     * @param {string} name - Unique name for caching the shader.
     * @param {string[]} [feedbackVaryings] - A list of shader output variable names that will be captured.