Finished up most documentation
This commit is contained in:
@@ -231,3 +231,114 @@ test('reduced-motion opening keeps the existing 70 ms transition duration', (t)
|
||||
step(1)
|
||||
assert.equal(pack.state, 'stackReady')
|
||||
})
|
||||
|
||||
test('GPU preparation uploads unique textures and compiles hidden fronts and both edge looks', async (t) => {
|
||||
const { pack, canvas } = setupPack(t)
|
||||
pack.setActive(false)
|
||||
const scene = new THREE.Scene()
|
||||
scene.environment = pack.options.environment
|
||||
const backTexture = new THREE.Texture()
|
||||
pack.options.backMaterial.map = backTexture
|
||||
const uploaded = []
|
||||
const compiledEdges = []
|
||||
let reveals = 0
|
||||
canvas.addEventListener('packreveal', () => reveals++)
|
||||
const before = geometryHash(pack.wrapper)
|
||||
let finishCompile
|
||||
const firstCompile = new Promise((resolve) => { finishCompile = resolve })
|
||||
const renderer = {
|
||||
initTexture(texture) { uploaded.push(texture) },
|
||||
async compileAsync(root, camera, targetScene) {
|
||||
assert.equal(root, pack.root)
|
||||
assert.equal(camera, pack.camera)
|
||||
assert.equal(targetScene, scene)
|
||||
assert.equal(root.visible, false)
|
||||
assert.equal(pack.state, 'sealed')
|
||||
assert.equal(pack.cards.some((card) => card.front.visible), false)
|
||||
assert.ok(pack.cards.every((card) => root.getObjectById(card.front.id)))
|
||||
compiledEdges.push(pack.cards.map((card) => card.edge.clearcoat))
|
||||
if (compiledEdges.length === 1) await firstCompile
|
||||
},
|
||||
}
|
||||
let ready = false
|
||||
const preparation = pack.prepareGPU(renderer, scene).then(() => { ready = true })
|
||||
await Promise.resolve()
|
||||
assert.equal(ready, false)
|
||||
finishCompile()
|
||||
await preparation
|
||||
assert.equal(uploaded.length, new Set(uploaded).size)
|
||||
assert.equal(uploaded.length, 9, '4 artwork/mask textures, normal, environment, back and 2 wrapper maps')
|
||||
for (const { artwork, mask } of Object.values(pack.options.textures)) {
|
||||
assert.ok(uploaded.includes(artwork))
|
||||
assert.ok(uploaded.includes(mask))
|
||||
}
|
||||
assert.ok(uploaded.includes(backTexture))
|
||||
assert.ok(uploaded.includes(pack.options.normalMap))
|
||||
assert.ok(uploaded.includes(scene.environment))
|
||||
assert.deepEqual(compiledEdges, [[0.02, 0.02, 0.02], [0, 0.02, 0.18]])
|
||||
assert.deepEqual(pack.cards.map((card) => card.edge.clearcoat), [0.02, 0.02, 0.02])
|
||||
assert.equal(geometryHash(pack.wrapper), before)
|
||||
assert.equal(reveals, 0)
|
||||
})
|
||||
|
||||
test('failed reveal-material warmup restores neutral edges and can be retried', async (t) => {
|
||||
const { pack } = setupPack(t)
|
||||
pack.setActive(false)
|
||||
let compilations = 0
|
||||
const failure = new Error('GPU compilation failed')
|
||||
const renderer = {
|
||||
initTexture() {},
|
||||
async compileAsync() {
|
||||
if (++compilations === 2) throw failure
|
||||
},
|
||||
}
|
||||
const scene = new THREE.Scene()
|
||||
await assert.rejects(pack.prepareGPU(renderer, scene), (error) => error === failure)
|
||||
assert.deepEqual(pack.cards.map((card) => card.edge.clearcoat), [0.02, 0.02, 0.02])
|
||||
assert.equal(pack.root.visible, false)
|
||||
assert.equal(pack.state, 'sealed')
|
||||
await pack.prepareGPU(renderer, scene)
|
||||
assert.equal(compilations, 4)
|
||||
})
|
||||
|
||||
test('GPU upload errors propagate and preparation cannot mutate an active pack', async (t) => {
|
||||
const { pack } = setupPack(t)
|
||||
const failure = new Error('GPU upload failed')
|
||||
let uploads = 0
|
||||
const renderer = {
|
||||
initTexture() { uploads++; throw failure },
|
||||
async compileAsync() { assert.fail('Compilation must not run after upload failure') },
|
||||
}
|
||||
const scene = new THREE.Scene()
|
||||
await assert.rejects(pack.prepareGPU(renderer, scene), /before activating/)
|
||||
assert.equal(uploads, 0)
|
||||
pack.setActive(false)
|
||||
await assert.rejects(pack.prepareGPU(renderer, scene), (error) => error === failure)
|
||||
})
|
||||
|
||||
test('pack cleanup disposes owned resources without disposing shared or caller-owned textures', (t) => {
|
||||
const { pack } = setupPack(t)
|
||||
const scene = new THREE.Scene()
|
||||
scene.add(pack.root)
|
||||
const shared = [
|
||||
pack.options.backMaterial, pack.options.normalMap, pack.options.environment,
|
||||
...Object.values(pack.options.textures).flatMap(({ artwork, mask }) => [artwork, mask]),
|
||||
]
|
||||
const sharedSpies = shared.map((resource) => t.mock.method(resource, 'dispose'))
|
||||
const geometries = new Set()
|
||||
const materials = new Set()
|
||||
pack.root.traverse((object) => {
|
||||
if (!(object instanceof THREE.Mesh)) return
|
||||
geometries.add(object.geometry)
|
||||
materials.add(object.material)
|
||||
})
|
||||
materials.delete(pack.options.backMaterial)
|
||||
const resources = [...geometries, ...materials,
|
||||
...new Set(pack.wrapper.root.children.map((mesh) => mesh.material.map))]
|
||||
const ownedSpies = resources.map((resource) => t.mock.method(resource, 'dispose'))
|
||||
pack.dispose()
|
||||
assert.equal(pack.root.parent, null)
|
||||
assert.equal(pack.root.visible, false)
|
||||
assert.ok(ownedSpies.every((spy) => spy.mock.callCount() === 1))
|
||||
assert.ok(sharedSpies.every((spy) => spy.mock.callCount() === 0))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user