Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plotly - device-independent and stable codegen + codegen cache. #637

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
641 changes: 495 additions & 146 deletions dist/regl.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/regl.js.map

Large diffs are not rendered by default.

348 changes: 177 additions & 171 deletions dist/regl.min.js

Large diffs are not rendered by default.

564 changes: 460 additions & 104 deletions dist/regl.unchecked.js

Large diffs are not rendered by default.

157 changes: 109 additions & 48 deletions lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ module.exports = function reglCore (
drawState,
contextState,
timer,
cachedCode,
config) {
var AttributeRecord = attributeState.Record

Expand Down Expand Up @@ -386,6 +387,14 @@ module.exports = function reglCore (
}
GL_VARIABLES[name] = func
}

function hasVariableReference (exp) {
if (!isNaN(exp)) {
return false;
}
// strengthen this function if variable values can be non-(null/number) literals.
return true;
}

// Dithering
stateFlag(S_DITHER, GL_DITHER)
Expand Down Expand Up @@ -497,7 +506,7 @@ module.exports = function reglCore (

var drawCallCounter = 0
function createREGLEnvironment () {
var env = createEnvironment()
var env = createEnvironment({cache: cachedCode})
var link = env.link
var global = env.global
env.id = drawCallCounter++
Expand Down Expand Up @@ -2288,6 +2297,7 @@ module.exports = function reglCore (
var CURRENT_VARS = env.current
var CURRENT_STATE = shared.current
var GL = shared.gl
var VALUE
sortState(Object.keys(options)).forEach(function (param) {
var defn = options[param]
if (filter && !filter(defn)) {
Expand All @@ -2297,17 +2307,17 @@ module.exports = function reglCore (
if (GL_FLAGS[param]) {
var flag = GL_FLAGS[param]
if (isStatic(defn)) {
if (variable) {
scope(GL, '.enable(', flag, ');')
} else {
scope(GL, '.disable(', flag, ');')
}
VALUE = env.link(variable, {stable: true})
scope(env.cond(VALUE)
.then(GL, '.enable(', flag, ');')
.else(GL, '.disable(', flag, ');'))
scope(CURRENT_STATE, '.', param, '=', VALUE, ';')
} else {
scope(env.cond(variable)
.then(GL, '.enable(', flag, ');')
.else(GL, '.disable(', flag, ');'))
scope(CURRENT_STATE, '.', param, '=', variable, ';')
}
scope(CURRENT_STATE, '.', param, '=', variable, ';')
} else if (isArrayLike(variable)) {
var CURRENT = CURRENT_VARS[param]
scope(
Expand All @@ -2316,9 +2326,16 @@ module.exports = function reglCore (
return CURRENT + '[' + i + ']=' + v
}).join(';'), ';')
} else {
scope(
GL, '.', GL_VARIABLES[param], '(', variable, ');',
CURRENT_STATE, '.', param, '=', variable, ';')
if (isStatic(defn)) {
VALUE = env.link(variable, {stable: true})
scope(
GL, '.', GL_VARIABLES[param], '(', VALUE, ');',
CURRENT_STATE, '.', param, '=', VALUE, ';')
} else {
scope(
GL, '.', GL_VARIABLES[param], '(', variable, ');',
CURRENT_STATE, '.', param, '=', variable, ';')
}
}
})
}
Expand Down Expand Up @@ -3403,10 +3420,18 @@ module.exports = function reglCore (
var value = defn.append(env, scope)
if (isArrayLike(value)) {
value.forEach(function (v, i) {
scope.set(env.next[name], '[' + i + ']', v)
if (hasVariableReference(v)) {
scope.set(env.next[name], '[' + i + ']', v)
} else {
scope.set(env.next[name], '[' + i + ']', env.link(v, {stable: true}))
}
})
} else {
scope.set(shared.next, '.' + name, value)
if (isStatic(defn)) {
scope.set(shared.next, '.' + name, env.link(value, {stable: true}))
} else {
scope.set(shared.next, '.' + name, value)
}
}
})

Expand All @@ -3418,17 +3443,28 @@ module.exports = function reglCore (
if (!variable) {
return
}
scope.set(shared.draw, '.' + opt, '' + variable.append(env, scope))
var VARIABLE = variable.append(env, scope)
if (hasVariableReference(VARIABLE)) {
scope.set(shared.draw, '.' + opt, VARIABLE)
} else {
scope.set(shared.draw, '.' + opt, env.link(VARIABLE), {stable: true})
}
})

Object.keys(args.uniforms).forEach(function (opt) {
var value = args.uniforms[opt].append(env, scope)
if (Array.isArray(value)) {
value = '[' + value.join() + ']'
value = '[' + value.map(function (v) {
if (hasVariableReference(v)) {
return v;
} else {
return env.link(v, {stable: true})
}
}) + ']'
}
scope.set(
shared.uniforms,
'[' + stringStore.id(opt) + ']',
'[' + env.link(stringStore.id(opt), {stable: true}) + ']',
value)
})

Expand All @@ -3441,13 +3477,23 @@ module.exports = function reglCore (
})

if (args.scopeVAO) {
scope.set(shared.vao, '.targetVAO', args.scopeVAO.append(env, scope))
var VARIABLE = args.scopeVAO.append(env, scope)
if (hasVariableReference(VARIABLE)) {
scope.set(shared.vao, '.targetVAO', VARIABLE)
} else {
scope.set(shared.vao, '.targetVAO', env.link(VARIABLE, {stable: true}))
}
}

function saveShader (name) {
var shader = args.shader[name]
if (shader) {
scope.set(shared.shader, '.' + name, shader.append(env, scope))
var VARIABLE = shader.append(env, scope)
if (hasVariableReference(VARIABLE)) {
scope.set(shared.shader, '.' + name, VARIABLE)
} else {
scope.set(shared.shader, '.' + name, env.link(VARIABLE, {stable: true}))
}
}
}
saveShader(S_VERT)
Expand Down Expand Up @@ -3560,6 +3606,15 @@ module.exports = function reglCore (

var args = parseArguments(options, attributes, uniforms, context, env)

if (args.shader.program) {
args.shader.program.attributes.sort(function (a, b) {
return a.name < b.name ? -1 : 1
})
args.shader.program.uniforms.sort(function (a, b) {
return a.name < b.name ? -1 : 1
})
}

emitDrawProc(env, args)
emitScopeProc(env, args)
emitBatchProc(env, args)
Expand Down Expand Up @@ -3607,37 +3662,43 @@ module.exports = function reglCore (
if (extensions.oes_vertex_array_object) {
refresh(env.link(extensions.oes_vertex_array_object), '.bindVertexArrayOES(null);')
}
for (var i = 0; i < limits.maxAttributes; ++i) {
var BINDING = refresh.def(shared.attributes, '[', i, ']')
var ifte = env.cond(BINDING, '.buffer')
ifte.then(
GL, '.enableVertexAttribArray(', i, ');',
GL, '.bindBuffer(',
GL_ARRAY_BUFFER, ',',
BINDING, '.buffer.buffer);',
GL, '.vertexAttribPointer(',
i, ',',
BINDING, '.size,',
BINDING, '.type,',
BINDING, '.normalized,',
BINDING, '.stride,',
BINDING, '.offset);'
).else(
GL, '.disableVertexAttribArray(', i, ');',
GL, '.vertexAttrib4f(',
i, ',',
BINDING, '.x,',
BINDING, '.y,',
BINDING, '.z,',
BINDING, '.w);',
BINDING, '.buffer=null;')
refresh(ifte)
if (extInstancing) {
refresh(
INSTANCING, '.vertexAttribDivisorANGLE(',
i, ',',
BINDING, '.divisor);')
}
var BINDING = refresh.def(shared.attributes)
var TEMP_BINDING = refresh.def(0)

var ifte = env.cond(TEMP_BINDING, '.buffer')
ifte.then(
GL, '.enableVertexAttribArray(i);',
GL, '.bindBuffer(',
GL_ARRAY_BUFFER, ',',
TEMP_BINDING, '.buffer.buffer);',
GL, '.vertexAttribPointer(i,',
TEMP_BINDING, '.size,',
TEMP_BINDING, '.type,',
TEMP_BINDING, '.normalized,',
TEMP_BINDING, '.stride,',
TEMP_BINDING, '.offset);'
).else(
GL, '.disableVertexAttribArray(i);',
GL, '.vertexAttrib4f(i,',
TEMP_BINDING, '.x,',
TEMP_BINDING, '.y,',
TEMP_BINDING, '.z,',
TEMP_BINDING, '.w);',
TEMP_BINDING, '.buffer=null;')
var MAX_ATTRIBUTES = env.link(limits.maxAttributes, {stable: true})
refresh(
'for(var i=0;i<', MAX_ATTRIBUTES, ';++i){',
TEMP_BINDING, '=', BINDING, '[i];',
ifte,
'}'
)

if (extInstancing) {
refresh(
'for(var i=0;i<', MAX_ATTRIBUTES, ';++i){',
INSTANCING, '.vertexAttribDivisorANGLE(i,',
BINDING, '[i].divisor);',
'}')
}
refresh(
env.shared.vao, '.currentVAO=null;',
Expand Down
3 changes: 2 additions & 1 deletion lib/util/check.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ var constructorKeys = [
'extensions',
'optionalExtensions',
'profile',
'onDone'
'onDone',
'cachedCode'
]

function checkConstructor (obj) {
Expand Down
32 changes: 27 additions & 5 deletions lib/util/codegen.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var extend = require('./extend')
var SHA256 = require("./sha256")

function slice (x) {
return Array.prototype.slice.call(x)
Expand All @@ -8,7 +9,9 @@ function join (x) {
return slice(x).join('')
}

module.exports = function createEnvironment () {
module.exports = function createEnvironment (options) {
var cache = options && options.cache

// Unique variable id counter
var varCounter = 0

Expand All @@ -17,16 +20,21 @@ module.exports = function createEnvironment () {
// the variable name which it is bound to
var linkedNames = []
var linkedValues = []
function link (value) {
for (var i = 0; i < linkedValues.length; ++i) {
if (linkedValues[i] === value) {
return linkedNames[i]
var isStable = []
function link (value, options) {
var stable = options && options.stable
if (!stable) {
for (var i = 0; i < linkedValues.length; ++i) {
if (linkedValues[i] === value && !isStable[i]) {
return linkedNames[i]
}
}
}

var name = 'g' + (varCounter++)
linkedNames.push(name)
linkedValues.push(value)
isStable.push(stable)
return name
}

Expand Down Expand Up @@ -166,7 +174,21 @@ module.exports = function createEnvironment () {
.replace(/;/g, ';\n')
.replace(/}/g, '}\n')
.replace(/{/g, '{\n')

var key
if (cache) {
key = SHA256(src);

if (cache[key]) {
return cache[key].apply(null, linkedValues)
}
}

var proc = Function.apply(null, linkedNames.concat(src))

if (cache) {
cache[key] = proc
}
return proc.apply(null, linkedValues)
}

Expand Down
Loading