Created
July 17, 2025 16:34
-
-
Save cgcostume/44d44d204e5c2df521070fcc7c080f58 to your computer and use it in GitHub Desktop.
Progressive LMV-Rendering Expectations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This script helps to verify the following assumption: | |
// | |
// given: | |
// - a single camera change | |
// - a small model that can be rendered within a single tick | |
// expected: | |
// - a single tick per camera change | |
// - two FINAL_FRAME_RENDERED_CHANGED_EVENT events per change | |
// - one RENDER_PRESENTED_EVENT event per change | |
// - one renderSome call per change | |
// This helped to verify https://git.autodesk.com/A360/firefly.js/pull/9443 | |
async function testProgressiveRenderingIssue(viewer, targetFPS = 30, numIterations = 4, offset = 1.0) { | |
console.log(` -- progressive rendering test for ${numIterations} camera changes...`); | |
const primitiveCounter = await viewer.loadExtension('Autodesk.DeveloperTools.PrimitiveCounter'); | |
primitiveCounter.activate(); | |
primitiveCounter.clearCache(); | |
viewer.impl.setFPSTargets(targetFPS, targetFPS, targetFPS); | |
const { FunctionIntrusion, HookType } = await import('/src/tools/FunctionIntrusion.js'); | |
const implIntrusion = new FunctionIntrusion(viewer.impl); | |
const renderSceneIntrusion = new FunctionIntrusion(viewer.impl.modelQueue()); | |
let renderSomeCallCount = 0; | |
let tickCallCount = 0; | |
implIntrusion.addHook('tick', () => tickCallCount++, HookType.Before); | |
renderSceneIntrusion.addHook('renderSome', () => renderSomeCallCount++, HookType.Before); | |
const results = []; | |
let currentIteration = 0; | |
let currentIterationData = null; | |
let totalRenderPresentedCount = 0; | |
let totalFrameCount = 0; | |
const onRenderPresented = (event) => { | |
if (!currentIterationData) return; | |
currentIterationData.renderPresentedCount++; | |
totalRenderPresentedCount++; | |
console.log(`RENDER_PRESENTED #${currentIterationData.renderPresentedCount}`, event); | |
}; | |
const onFinalFrameChanged = (event) => { | |
if (!currentIterationData) return; | |
currentIterationData.frameCount++; | |
totalFrameCount++; | |
const finalFrame = event.value?.finalFrame; | |
console.log(`FINAL_FRAME_CHANGED #${currentIterationData.frameCount}`, event.value); | |
if (!finalFrame) return; | |
const finalCounts = primitiveCounter.getAccumulatedTickCounts(true); | |
const result = { | |
iteration: currentIteration + 1, | |
finalCounts, | |
tickCallsThisIteration: tickCallCount - currentIterationData.startTickCount, | |
renderSomeCallsThisIteration: renderSomeCallCount - currentIterationData.startRenderSomeCount, | |
renderPresentedCount: currentIterationData.renderPresentedCount, | |
frameCount: currentIterationData.frameCount | |
}; | |
console.log(`ITERATION ${currentIteration + 1} done:`, result); | |
results.push(result); | |
currentIterationData.resolve(result); | |
}; | |
viewer.addEventListener(Autodesk.Viewing.RENDER_PRESENTED_EVENT, onRenderPresented); | |
viewer.addEventListener(Autodesk.Viewing.FINAL_FRAME_RENDERED_CHANGED_EVENT, onFinalFrameChanged); | |
for (let i = 0; i < numIterations; ++i) { | |
console.log(` -- iteration ${i + 1}/${numIterations}`); | |
currentIteration = i; | |
const camera = viewer.getCamera(); | |
const newPosition = { | |
x: camera.position.x + (Math.random() - 0.5) * offset, | |
y: camera.position.y + (Math.random() - 0.5) * offset, | |
z: camera.position.z + (Math.random() - 0.5) * offset | |
}; | |
const startTickCount = tickCallCount; | |
const startRenderSomeCount = renderSomeCallCount; | |
primitiveCounter.getAccumulatedTickCounts(true); | |
const iterationResult = await new Promise((resolve) => { | |
currentIterationData = { | |
renderPresentedCount: 0, | |
frameCount: 0, | |
startTickCount, | |
startRenderSomeCount, | |
resolve | |
}; | |
viewer.navigation.setView(new THREE.Vector3(newPosition.x, newPosition.y, newPosition.z), camera.target, camera.up); | |
}); | |
// if (i < numIterations - 1) { await new Promise(resolve => setTimeout(resolve, 300)); } | |
} | |
viewer.removeEventListener(Autodesk.Viewing.RENDER_PRESENTED_EVENT, onRenderPresented); | |
viewer.removeEventListener(Autodesk.Viewing.FINAL_FRAME_RENDERED_CHANGED_EVENT, onFinalFrameChanged); | |
implIntrusion.removeAllHooks(); | |
renderSceneIntrusion.removeAllHooks(); | |
primitiveCounter.deactivate(); | |
console.log(' -- Summary'); | |
console.log(` -- Total tick calls across all iterations: ${tickCallCount}`); | |
console.log(` -- Total renderSome calls across all iterations: ${renderSomeCallCount}`); | |
const avgRenderPresented = totalRenderPresentedCount / numIterations; | |
const avgFrameEvents = totalFrameCount / numIterations; | |
console.log(` -- Total render presented events: ${totalRenderPresentedCount}`); | |
console.log(` -- Total final frame events: ${totalFrameCount}`); | |
console.log(` -- Average render presented per iteration: ${avgRenderPresented.toFixed(2)}`); | |
console.log(` -- Average final frame events per iteration: ${avgFrameEvents.toFixed(2)}`); | |
} | |
testProgressiveRenderingIssue(NOP_VIEWER, 30, 4, 100.0); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment