mirror of
https://github.com/visgl/luma.gl.git
synced 2025-12-08 17:36:19 +00:00
715 lines
18 KiB
TypeScript
715 lines
18 KiB
TypeScript
/*
|
|
import test from 'tape-promise/tape';
|
|
import {webgl1Device} from '@luma.gl/test-utils';
|
|
|
|
import {GL} from '@luma.gl/constants';
|
|
import {luma} from '@luma.gl/core';
|
|
// TODO - Model test should not depend on Cube
|
|
import {Model, ProgramManager} from '@luma.gl/engine';
|
|
import {Buffer} from '@luma.gl/webgl';
|
|
import {CubeGeometry} from '@luma.gl/engine';
|
|
import {picking} from '@luma.gl/shadertools';
|
|
|
|
const stats = luma.stats.get('Resource Counts');
|
|
|
|
const DUMMY_VS = `
|
|
void main() { gl_Position = vec4(1.0); }
|
|
`;
|
|
|
|
const DUMMY_FS = `
|
|
precision highp float;
|
|
void main() { gl_FragColor = vec4(1.0); }
|
|
`;
|
|
|
|
const VS_300 = `#version 300 es
|
|
|
|
in vec4 positions;
|
|
in vec2 uvs;
|
|
|
|
out vec2 vUV;
|
|
|
|
void main() {
|
|
vUV = uvs;
|
|
gl_Position = positions;
|
|
}
|
|
`;
|
|
|
|
const FS_300 = `#version 300 es
|
|
precision highp float;
|
|
|
|
in vec2 vUV;
|
|
|
|
uniform sampler2D tex;
|
|
|
|
out vec4 fragColor;
|
|
void main() {
|
|
fragColor = texture(tex, vUV);
|
|
}
|
|
`;
|
|
|
|
test('Model#construct/destruct', (t) => {
|
|
// Avoid re-using program from ProgramManager
|
|
const vs = '/* DO_NOT_CACHE Model#construct/destruct * void main() {gl_Position = vec4(0.0);}';
|
|
const fs = '/* DO_NOT_CACHE Model#construct/destruct * void main() {gl_FragColor = vec4(0.0);}';
|
|
|
|
const model = new Model(webgl1Device, {
|
|
drawMode: GL.POINTS,
|
|
vertexCount: 0,
|
|
vs,
|
|
fs
|
|
});
|
|
|
|
t.ok(model, 'Model constructor does not throw errors');
|
|
t.ok(model.id, 'Model has an id');
|
|
t.ok(model.getProgram().handle, 'Created new program');
|
|
|
|
model.destroy();
|
|
t.notOk(model.vertexArray.handle, 'Deleted vertexArray');
|
|
t.notOk(model.program.handle, 'Deleted program');
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('Model#multiple delete', (t) => {
|
|
// Avoid re-using program from ProgramManager
|
|
const vs = '/* DO_NOT_CACHE Model#construct/destruct * void main() {gl_Position = vec4(0.0);}';
|
|
const fs = '/* DO_NOT_CACHE Model#construct/destruct * void main() {gl_FragColor = vec4(0.0);}';
|
|
|
|
const model1 = new Model(webgl1Device, {
|
|
drawMode: GL.POINTS,
|
|
vertexCount: 0,
|
|
vs,
|
|
fs
|
|
});
|
|
|
|
const model2 = new Model(webgl1Device, {
|
|
drawMode: GL.POINTS,
|
|
vertexCount: 0,
|
|
vs,
|
|
fs
|
|
});
|
|
|
|
model1.destroy();
|
|
t.ok(model2.program.handle, 'program still in use');
|
|
model1.destroy();
|
|
t.ok(model2.program.handle, 'program still in use');
|
|
model2.destroy();
|
|
t.notOk(model2.program.handle, 'program is released');
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('Model#setAttribute', (t) => {
|
|
const buffer1 = webgl1Device.createBuffer({
|
|
accessor: {size: 2},
|
|
data: new Float32Array(4).fill(1)
|
|
});
|
|
const buffer2 = webgl1Device.createBuffer({data: new Float32Array(8)});
|
|
|
|
const initialActiveBuffers = stats.get('Buffers Active').count;
|
|
|
|
const model = new Model(webgl1Device, {
|
|
vs: DUMMY_VS,
|
|
fs: DUMMY_FS,
|
|
geometry: new CubeGeometry()
|
|
});
|
|
|
|
t.is(
|
|
stats.get('Buffers Active').count - initialActiveBuffers,
|
|
4,
|
|
'Created new buffers for attributes'
|
|
);
|
|
|
|
model.setAttributes({
|
|
instanceSizes: [buffer1, {size: 1}],
|
|
instancePositions: buffer2,
|
|
instanceWeight: new Float32Array([10]),
|
|
instanceColors: {getValue: () => new Float32Array([0, 0, 0, 1])}
|
|
});
|
|
|
|
t.deepEqual(model.getAttributes(), {}, 'no longer stores local attributes');
|
|
|
|
t.is(stats.get('Buffers Active').count - initialActiveBuffers, 4, 'Did not create new buffers');
|
|
|
|
model.destroy();
|
|
|
|
buffer1.destroy();
|
|
buffer2.destroy();
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('Model#setters, getters', (t) => {
|
|
const model = new Model(webgl1Device, {vs: DUMMY_VS, fs: DUMMY_FS});
|
|
|
|
model.setUniforms({
|
|
isPickingActive: 1
|
|
});
|
|
t.deepEqual(model.getUniforms(), {isPickingActive: 1}, 'uniforms are set');
|
|
|
|
model.setInstanceCount(4);
|
|
t.is(model.getInstanceCount(), 4, 'instance count is set');
|
|
|
|
model.setDrawMode(1);
|
|
t.is(model.getDrawMode(), 1, 'draw mode is set');
|
|
|
|
model.destroy();
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('Model#draw', (t) => {
|
|
const model = new Model(webgl1Device, {
|
|
vs: DUMMY_VS,
|
|
fs: DUMMY_FS,
|
|
geometry: new CubeGeometry(),
|
|
timerQueryEnabled: true
|
|
});
|
|
|
|
model.draw();
|
|
|
|
model.render({
|
|
isPickingActive: 1
|
|
});
|
|
t.deepEqual(model.getUniforms(), {isPickingActive: 1}, 'uniforms are set');
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('Model#program management', (t) => {
|
|
const pm = new ProgramManager(webgl1Device);
|
|
|
|
const vs = `
|
|
uniform float x;
|
|
|
|
void main() {
|
|
gl_Position = vec4(x);
|
|
}
|
|
`;
|
|
|
|
const fs = `
|
|
void main() {
|
|
gl_FragColor = vec4(1.0);
|
|
}
|
|
`;
|
|
|
|
const model1 = new Model(webgl1Device, {
|
|
programManager: pm,
|
|
vs,
|
|
fs,
|
|
uniforms: {
|
|
x: 0.5
|
|
}
|
|
});
|
|
|
|
const model2 = new Model(webgl1Device, {
|
|
programManager: pm,
|
|
vs,
|
|
fs,
|
|
uniforms: {
|
|
x: -0.5
|
|
}
|
|
});
|
|
|
|
t.ok(model1.program === model2.program, 'Programs are shared.');
|
|
|
|
model1.draw();
|
|
t.deepEqual(model1.getUniforms(), model1.program.uniforms, 'Program uniforms set');
|
|
|
|
model2.draw();
|
|
t.deepEqual(model2.getUniforms(), model2.program.uniforms, 'Program uniforms set');
|
|
|
|
model2.setProgram({
|
|
vs,
|
|
fs,
|
|
defines: {
|
|
MY_DEFINE: true
|
|
}
|
|
});
|
|
|
|
t.ok(model1.program === model2.program, 'Program not updated before draw.');
|
|
|
|
model2.draw();
|
|
t.ok(model1.program !== model2.program, 'Program updated after draw.');
|
|
t.deepEqual(model2.getUniforms(), model2.program.uniforms, 'Program uniforms set');
|
|
|
|
// This part is checking that the use counts
|
|
// don't get bloated by multiple checks.
|
|
const model3 = new Model(webgl1Device, {
|
|
programManager: pm,
|
|
vs,
|
|
fs,
|
|
defines: {
|
|
MODEL3_DEFINE1: true
|
|
}
|
|
});
|
|
|
|
const oldProgram = model3.program;
|
|
|
|
// Check for program updates a few times
|
|
model3.draw();
|
|
model3.draw();
|
|
|
|
model3.setProgram({
|
|
vs,
|
|
fs,
|
|
defines: {
|
|
MODEL3_DEFINE2: true
|
|
}
|
|
});
|
|
|
|
model3.draw();
|
|
t.ok(model3.program !== oldProgram, 'Program updated after draw.');
|
|
t.ok(oldProgram.handle === null, 'Old program released after update');
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('Model#program management - getModuleUniforms', (t) => {
|
|
const pm = new ProgramManager(webgl1Device);
|
|
|
|
const vs = 'void main() {}';
|
|
const fs = 'void main() {}';
|
|
|
|
const model = new Model(webgl1Device, {
|
|
programManager: pm,
|
|
vs,
|
|
fs
|
|
});
|
|
|
|
t.deepEqual(model.getModuleUniforms(), {}, 'Module uniforms empty with no modules');
|
|
|
|
model.setProgram({
|
|
vs,
|
|
fs,
|
|
modules: [picking]
|
|
});
|
|
|
|
t.deepEqual(
|
|
model.getModuleUniforms(),
|
|
picking.getUniforms(),
|
|
'Module uniforms correct after update'
|
|
);
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('Model#getBuffersFromGeometry', (t) => {
|
|
let buffers = getBuffersFromGeometry(webgl1Device.gl, {
|
|
indices: new Uint16Array([0, 1, 2, 3]),
|
|
attributes: {
|
|
positions: {size: 3, value: new Float32Array(12)},
|
|
colors: {constant: true, value: [255, 255, 255, 255]},
|
|
uvs: {size: 2, value: new Float32Array(8)}
|
|
}
|
|
});
|
|
|
|
t.deepEqual(buffers.colors, [255, 255, 255, 255], 'colors mapped');
|
|
t.ok(buffers.positions[0] instanceof Buffer, 'positions mapped');
|
|
t.is(buffers.positions[1].size, 3, 'positions mapped');
|
|
t.ok(buffers.uvs[0] instanceof Buffer, 'uvs mapped');
|
|
t.is(buffers.uvs[1].size, 2, 'uvs mapped');
|
|
t.ok(buffers.indices[0] instanceof Buffer, 'indices mapped');
|
|
|
|
buffers.positions[0].destroy();
|
|
buffers.uvs[0].destroy();
|
|
buffers.indices[0].destroy();
|
|
|
|
// Inferring attribute size
|
|
buffers = getBuffersFromGeometry(webgl1Device.gl, {
|
|
attributes: {
|
|
indices: {value: new Uint16Array([0, 1, 2, 3])},
|
|
normals: {value: new Float32Array(12)},
|
|
texCoords: {value: new Float32Array(8)}
|
|
}
|
|
});
|
|
t.is(buffers.indices[1].size, 1, 'texCoords size');
|
|
t.is(buffers.normals[1].size, 3, 'normals size');
|
|
t.is(buffers.texCoords[1].size, 2, 'texCoords size');
|
|
|
|
buffers.indices[0].destroy();
|
|
buffers.normals[0].destroy();
|
|
buffers.texCoords[0].destroy();
|
|
|
|
t.throws(
|
|
() =>
|
|
getBuffersFromGeometry(webgl1Device.gl, {
|
|
indices: [0, 1, 2, 3]
|
|
}),
|
|
'invalid indices'
|
|
);
|
|
|
|
t.throws(
|
|
() =>
|
|
getBuffersFromGeometry(webgl1Device.gl, {
|
|
attributes: {
|
|
heights: {value: new Float32Array([0, 1, 2, 3])}
|
|
}
|
|
}),
|
|
'invalid size'
|
|
);
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('Model#transpileToGLSL100', (t) => {
|
|
let model;
|
|
|
|
t.throws(() => {
|
|
model = new Model(webgl1Device, {
|
|
vs: VS_300,
|
|
fs: FS_300
|
|
});
|
|
}, "Can't compile 300 shader with WebGL 1");
|
|
|
|
t.doesNotThrow(() => {
|
|
model = new Model(webgl1Device, {
|
|
vs: VS_300,
|
|
fs: FS_300,
|
|
transpileToGLSL100: true
|
|
});
|
|
}, 'Can compile transpiled 300 shader with WebGL 1');
|
|
|
|
@ts-expect-error object possibly undefined
|
|
t.ok(model.program, 'Created a program');
|
|
t.end();
|
|
});
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
test.skip('PipelineFactory#basic', (t) => {
|
|
const pipelineFactory = new PipelineFactory(webgl1Device);
|
|
|
|
const program1 = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
|
|
|
|
t.ok(program1, 'Got a pipeline');
|
|
|
|
const pipeline2 = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
|
|
|
|
t.ok(program1 === pipeline2, 'Got cached pipeline');
|
|
|
|
const definePipeline1 = pipelineFactory.createRenderPipeline({
|
|
vs,
|
|
fs,
|
|
topology: 'triangle-list',
|
|
defines: {
|
|
MY_DEFINE: true
|
|
}
|
|
});
|
|
|
|
t.ok(program1 !== definePipeline1, 'Define triggers new pipeline');
|
|
|
|
const definePipeline2 = pipelineFactory.createRenderPipeline({
|
|
vs,
|
|
fs,
|
|
topology: 'triangle-list',
|
|
defines: {
|
|
MY_DEFINE: true
|
|
}
|
|
});
|
|
|
|
t.ok(definePipeline1 === definePipeline2, 'Got cached pipeline with defines');
|
|
|
|
const modulePipeline1 = pipelineFactory.createRenderPipeline({
|
|
vs,
|
|
fs,
|
|
topology: 'triangle-list',
|
|
modules: [picking]
|
|
});
|
|
|
|
t.ok(program1 !== modulePipeline1, 'Module triggers new pipeline');
|
|
t.ok(definePipeline1 !== modulePipeline1, 'Module triggers new pipeline');
|
|
|
|
const modulePipeline2 = pipelineFactory.createRenderPipeline({
|
|
vs,
|
|
fs,
|
|
topology: 'triangle-list',
|
|
modules: [picking]
|
|
});
|
|
|
|
t.ok(modulePipeline1 === modulePipeline2, 'Got cached pipeline with modules');
|
|
|
|
const defineModulePipeline1 = pipelineFactory.createRenderPipeline({
|
|
vs,
|
|
fs,
|
|
topology: 'triangle-list',
|
|
modules: [picking],
|
|
defines: {
|
|
MY_DEFINE: true
|
|
}
|
|
});
|
|
|
|
t.ok(program1 !== defineModulePipeline1, 'Module and define triggers new pipeline');
|
|
t.ok(definePipeline1 !== defineModulePipeline1, 'Module and define triggers new pipeline');
|
|
t.ok(modulePipeline1 !== defineModulePipeline1, 'Module and define triggers new pipeline');
|
|
|
|
const defineModulePipeline2 = pipelineFactory.createRenderPipeline({
|
|
vs,
|
|
fs,
|
|
topology: 'triangle-list',
|
|
modules: [picking],
|
|
defines: {
|
|
MY_DEFINE: true
|
|
}
|
|
});
|
|
|
|
t.ok(
|
|
defineModulePipeline1 === defineModulePipeline2,
|
|
'Got cached pipeline with modules and defines'
|
|
);
|
|
|
|
t.end();
|
|
});
|
|
*/
|
|
|
|
/*
|
|
import {dirlight, picking} from '@luma.gl/shadertools';
|
|
|
|
const VS_300 = glsl`#version 300 es
|
|
|
|
in vec4 positions;
|
|
in vec2 uvs;
|
|
|
|
out vec2 vUV;
|
|
|
|
void main() {
|
|
vUV = uvs;
|
|
gl_Position = positions;
|
|
}
|
|
`;
|
|
|
|
const FS_300 = glsl`#version 300 es
|
|
precision highp float;
|
|
|
|
in vec2 vUV;
|
|
|
|
uniform sampler2D tex;
|
|
|
|
out vec4 fragColor;
|
|
void main() {
|
|
fragColor = texture(tex, vUV);
|
|
}
|
|
`;
|
|
|
|
|
|
// TODO - Move to model: transpilation functionality was moved to model
|
|
test('PipelineFactory#hooks', (t) => {
|
|
const pipelineFactory = new PipelineFactory(webgl1Device);
|
|
|
|
const preHookPipeline = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
|
|
|
|
pipelineFactory.addShaderHook('vs:LUMAGL_pickColor(inout vec4 color)');
|
|
pipelineFactory.addShaderHook('fs:LUMAGL_fragmentColor(inout vec4 color)', {
|
|
header: 'if (color.a == 0.0) discard;\n',
|
|
footer: 'color.a *= 1.2;\n'
|
|
});
|
|
|
|
const postHookPipeline = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
|
|
|
|
t.ok(preHookPipeline !== postHookPipeline, 'Adding hooks changes hash');
|
|
|
|
const pickingInjection = Object.assign(
|
|
{
|
|
inject: {
|
|
'vs:LUMAGL_pickColor': 'picking_setPickingColor(color.rgb);',
|
|
'fs:LUMAGL_fragmentColor': {
|
|
injection: 'color = picking_filterColor(color);',
|
|
order: Number.POSITIVE_INFINITY
|
|
}
|
|
}
|
|
},
|
|
picking
|
|
);
|
|
|
|
const noModulePipeline = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
|
|
|
|
t.ok(preHookPipeline !== noModulePipeline, 'Adding hooks changes hash');
|
|
|
|
const noModuleVs = noModulePipeline.vs.source;
|
|
const noModuleFs = noModulePipeline.fs.source;
|
|
|
|
t.ok(noModuleVs.indexOf('LUMAGL_pickColor') > -1, 'hook function injected into vertex shader');
|
|
t.ok(
|
|
noModuleFs.indexOf('LUMAGL_fragmentColor') > -1,
|
|
'hook function injected into fragment shader'
|
|
);
|
|
|
|
t.ok(
|
|
noModuleVs.indexOf('picking_setPickingColor(color.rgb)') === -1,
|
|
'injection code not included in vertex shader without module'
|
|
);
|
|
t.ok(
|
|
noModuleFs.indexOf('color = picking_filterColor(color)') === -1,
|
|
'injection code not included in fragment shader without module'
|
|
);
|
|
|
|
const modulesPipeline = pipelineFactory.createRenderPipeline({
|
|
vs,
|
|
fs,
|
|
topology: 'triangle-list',
|
|
modules: [pickingInjection]
|
|
});
|
|
const modulesVs = modulesPipeline.vs.source;
|
|
const modulesFs = modulesPipeline.fs.source;
|
|
|
|
t.ok(modulesVs.indexOf('LUMAGL_pickColor') > -1, 'hook function injected into vertex shader');
|
|
t.ok(
|
|
modulesFs.indexOf('LUMAGL_fragmentColor') > -1,
|
|
'hook function injected into fragment shader'
|
|
);
|
|
|
|
t.ok(
|
|
modulesVs.indexOf('picking_setPickingColor(color.rgb)') > -1,
|
|
'injection code included in vertex shader with module'
|
|
);
|
|
t.ok(
|
|
modulesFs.indexOf('color = picking_filterColor(color)') > -1,
|
|
'injection code included in fragment shader with module'
|
|
);
|
|
t.ok(
|
|
modulesFs.indexOf('if (color.a == 0.0) discard;') > -1,
|
|
'hook header injected into fragment shader'
|
|
);
|
|
t.ok(
|
|
modulesFs.indexOf('color.a *= 1.2;') > modulesFs.indexOf('color = picking_filterColor(color)'),
|
|
'hook footer injected after injection code'
|
|
);
|
|
|
|
const injectPipeline = pipelineFactory.createRenderPipeline({
|
|
vs,
|
|
fs,
|
|
topology: 'triangle-list',
|
|
inject: {
|
|
'vs:LUMAGL_pickColor': 'color *= 0.1;',
|
|
'fs:LUMAGL_fragmentColor': 'color += 0.1;'
|
|
}
|
|
});
|
|
const injectVs = injectPipeline.vs.source;
|
|
const injectFs = injectPipeline.fs.source;
|
|
|
|
t.ok(injectVs.indexOf('color *= 0.1') > -1, 'argument injection code included in shader hook');
|
|
t.ok(injectFs.indexOf('color += 0.1') > -1, 'argument injection code included in shader hook');
|
|
|
|
const injectDefinePipeline1 = pipelineFactory.createRenderPipeline({
|
|
vs,
|
|
fs,
|
|
topology: 'triangle-list',
|
|
inject: {
|
|
'vs:LUMAGL_pickColor': 'color *= 0.1;'
|
|
}
|
|
});
|
|
|
|
const injectDefinePipeline2 = pipelineFactory.createRenderPipeline({
|
|
vs,
|
|
fs,
|
|
topology: 'triangle-list',
|
|
defines: {
|
|
'vs:LUMAGL_pickColor': 'color *= 0.1;'
|
|
}
|
|
});
|
|
|
|
t.ok(injectDefinePipeline1 !== injectDefinePipeline2, 'Injects and defines hashed separately.');
|
|
|
|
t.end();
|
|
});
|
|
|
|
// TODO - Move to model: transpilation functionality was moved to model
|
|
test.skip('PipelineFactory#defaultModules', (t) => {
|
|
const pipelineFactory = new PipelineFactory(webgl1Device);
|
|
|
|
const {pipeline} = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
|
|
|
|
const preDefaultModulePipeline = pipelineFactory.createRenderPipeline({
|
|
vs,
|
|
fs,
|
|
topology: 'triangle-list',
|
|
modules: [dirlight]
|
|
});
|
|
|
|
const preDefaultModuleSource = preDefaultModulePipeline.fs.source;
|
|
|
|
pipelineFactory.addDefaultModule(dirlight);
|
|
|
|
const defaultModulePipeline = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
|
|
const modulePipeline = pipelineFactory.createRenderPipeline({
|
|
vs,
|
|
fs,
|
|
topology: 'triangle-list',
|
|
modules: [dirlight]
|
|
});
|
|
|
|
t.ok(pipeline !== defaultModulePipeline, 'Pipeline with new default module properly cached');
|
|
t.ok(
|
|
preDefaultModulePipeline !== defaultModulePipeline,
|
|
'Adding a default module changes the pipeline hash'
|
|
);
|
|
t.ok(
|
|
preDefaultModulePipeline.fs.source === defaultModulePipeline.fs.source,
|
|
'Default module injected correctly'
|
|
);
|
|
t.ok(
|
|
modulePipeline === defaultModulePipeline,
|
|
'Pipeline with new default module matches regular module'
|
|
);
|
|
|
|
pipelineFactory.removeDefaultModule(dirlight);
|
|
|
|
const noDefaultModulePipeline = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
|
|
|
|
t.ok(pipeline.fs.source === noDefaultModulePipeline.fs.source, 'Default module was removed');
|
|
t.ok(modulePipeline.fs.source !== noDefaultModulePipeline.fs.source, 'Default module was removed');
|
|
|
|
// Reset pipeline manager
|
|
pipelineFactory.release(pipeline);
|
|
pipelineFactory.release(modulePipeline);
|
|
pipelineFactory.release(defaultModulePipeline);
|
|
pipelineFactory.release(noDefaultModulePipeline);
|
|
|
|
pipelineFactory.addDefaultModule(dirlight);
|
|
const uncachedPipeline = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
|
|
const defaultModuleSource = uncachedPipeline.fs.source;
|
|
|
|
t.ok(defaultModulePipeline !== uncachedPipeline, 'Pipeline is not cached');
|
|
t.ok(preDefaultModuleSource === defaultModuleSource, 'Default modules create correct source');
|
|
|
|
t.end();
|
|
});
|
|
|
|
// TODO - Move to model: transpilation functionality was moved to model
|
|
test.skip('PipelineFactory#transpileToGLSL100', (t) => {
|
|
const pipelineFactory = new PipelineFactory(webgl1Device);
|
|
|
|
t.throws(() => {
|
|
pipelineFactory.createRenderPipeline({
|
|
vs: VS_300,
|
|
fs: FS_300,
|
|
topology: 'triangle-list'
|
|
});
|
|
}, 'Can\'t compile 300 shader with WebGL 1');
|
|
|
|
t.doesNotThrow(() => {
|
|
pipelineFactory.createRenderPipeline({
|
|
vs: VS_300,
|
|
fs: FS_300,
|
|
topology: 'triangle-list',
|
|
transpileToGLSL100: true
|
|
});
|
|
}, 'Can compile transpiled 300 shader with WebGL 1');
|
|
|
|
const programTranspiled = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list', transpileToGLSL100: true});
|
|
const programUntranspiled = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list'});
|
|
const programTranspiled2 = pipelineFactory.createRenderPipeline({vs, fs, topology: 'triangle-list', transpileToGLSL100: true});
|
|
|
|
t.equals(programTranspiled, programTranspiled2, 'Transpiled programs match');
|
|
t.notEquals(
|
|
programTranspiled,
|
|
programUntranspiled,
|
|
'Transpiled pipeline does not match untranspiled pipeline'
|
|
);
|
|
|
|
t.end();
|
|
});
|
|
*/
|