Skip to content

Commit

Permalink
Set invariant gl_Position to workaround M1 precision issues
Browse files Browse the repository at this point in the history
  • Loading branch information
Justin Hendrick committed Dec 22, 2023
1 parent 9dbac40 commit f92aeda
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 2 deletions.
6 changes: 6 additions & 0 deletions circle-vert.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ attribute float size, borderSize;
attribute vec4 colorId, borderColorId;
attribute float isActive;

// `invariant` effectively turns off optimizations for the position.
// We need this because -fast-math on M1 Macs is re-ordering
// floating point operations in a way that causes floating point
// precision limits to put points in the wrong locations.
invariant gl_Position;

uniform bool constPointSize;
uniform float pixelRatio;
uniform vec2 paletteSize, scale, scaleFract, translate, translateFract;
Expand Down
8 changes: 7 additions & 1 deletion marker-vert.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ attribute float size, borderSize;
attribute vec4 colorId, borderColorId;
attribute float isActive;

// `invariant` effectively turns off optimizations for the position.
// We need this because -fast-math on M1 Macs is re-ordering
// floating point operations in a way that causes floating point
// precision limits to put points in the wrong locations.
invariant gl_Position;

uniform bool constPointSize;
uniform float pixelRatio;
uniform vec2 scale, scaleFract, translate, translateFract, paletteSize;
Expand Down Expand Up @@ -58,4 +64,4 @@ void main() {

fragBorderColorLevel = clamp(borderLevel - borderLevel * borderSize / size, 0., 1.);
fragColorLevel = clamp(borderLevel + (1. - borderLevel) * borderSize / size, 0., 1.);
}
}
32 changes: 31 additions & 1 deletion test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,37 @@ t('missing points #2334', async t => {
t.end()
})

t('large values precision M1 mac (plotly/plotly.js Issue #6820)', async t => {
var N = 1000
var positions = new Float64Array(2 * N)

// M1 macs have precision issues with large values near 1e9.
// -fast-math is causing a re-order of floating point operations and points are placed at the wrong location
var x_base = 1e9
// 1e17 is large enough that we're going to have precision issues on any platform.
var y_base = 1e17 + 555
for(var i=0; i<2*N; i += 2) {
positions[i] = x_base + i
positions[i + 1] = y_base + i
}

var scatter = createScatter(regl)
scatter.update([{
positions: positions,
}])
scatter.render()

// This is a regression test. To make a new test or update an existing one, you need to generate the expected image.
// Use this code to save the manually inspected image to become the expected output for the subsequent runs:
// const output = require('image-output')
// output(scatter.gl, './test/img/filename.png')

t.ok(eq(scatter.gl, await load('./test/img/large_values_precision_M1_mac.png'), .1))

regl.clear({color: [0,0,0,0]})
t.end()
})

t('unsnapped elements render')

t('snapped elements render')
Expand All @@ -174,4 +205,3 @@ t('single point')
t('no-boundaries')

t('cluster with external buffer')

0 comments on commit f92aeda

Please sign in to comment.