@genome-spy/core 0.18.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +44 -117
- package/dist/schema.json +0 -4
- package/package.json +3 -2
- package/src/data/collector.js +9 -4
- package/src/data/collector.test.js +2 -0
- package/src/data/dataFlow.test.js +2 -0
- package/src/data/flow.test.js +1 -0
- package/src/data/flowNode.test.js +1 -0
- package/src/data/flowOptimizer.js +6 -0
- package/src/data/flowOptimizer.test.js +1 -0
- package/src/data/formats/fasta.test.js +1 -0
- package/src/data/sources/inlineSource.test.js +1 -0
- package/src/data/sources/sequenceSource.test.js +1 -0
- package/src/data/transforms/clone.test.js +1 -0
- package/src/data/transforms/coverage.test.js +1 -0
- package/src/data/transforms/filter.test.js +1 -0
- package/src/data/transforms/flattenDelimited.test.js +1 -0
- package/src/data/transforms/flattenSequence.test.js +1 -0
- package/src/data/transforms/formula.test.js +1 -0
- package/src/data/transforms/identifier.test.js +1 -0
- package/src/data/transforms/pileup.test.js +1 -0
- package/src/data/transforms/project.test.js +1 -0
- package/src/data/transforms/regexExtract.test.js +1 -0
- package/src/data/transforms/regexFold.test.js +1 -0
- package/src/data/transforms/sample.test.js +1 -0
- package/src/data/transforms/stack.test.js +1 -0
- package/src/encoder/accessor.test.js +1 -0
- package/src/encoder/encoder.test.js +1 -0
- package/src/genome/genome.js +14 -2
- package/src/genome/genome.test.js +36 -0
- package/src/genome/scaleIndex.js +3 -2
- package/src/genome/scaleIndex.test.js +23 -6
- package/src/genome/scaleLocus.test.js +1 -0
- package/src/gl/dataToVertices.js +9 -6
- package/src/gl/includes/common.glsl +3 -3
- package/src/gl/includes/scales.glsl +33 -2
- package/src/gl/point.vertex.glsl +0 -2
- package/src/gl/rule.vertex.glsl +1 -1
- package/src/gl/webGLHelper.js +0 -3
- package/src/marks/mark.js +10 -13
- package/src/scale/glslScaleGenerator.js +56 -17
- package/src/scale/scale.test.js +1 -0
- package/src/scale/ticks.test.js +1 -0
- package/src/spec/scale.d.ts +0 -9
- package/src/utils/addBaseUrl.test.js +1 -0
- package/src/utils/cloner.test.js +1 -0
- package/src/utils/coalesce.test.js +1 -0
- package/src/utils/concatIterables.test.js +1 -0
- package/src/utils/domainArray.test.js +1 -0
- package/src/utils/indexer.test.js +1 -0
- package/src/utils/iterateNestedMaps.test.js +1 -0
- package/src/utils/kWayMerge.test.js +1 -0
- package/src/utils/layout/flexLayout.test.js +1 -0
- package/src/utils/layout/rectangle.test.js +1 -0
- package/src/utils/mergeObjects.test.js +1 -0
- package/src/utils/numberExtractor.test.js +1 -0
- package/src/utils/propertyCacher.test.js +1 -0
- package/src/utils/propertyCoalescer.test.js +1 -0
- package/src/utils/reservationMap.test.js +1 -0
- package/src/utils/topK.test.js +1 -0
- package/src/utils/variableTools.test.js +1 -0
- package/src/view/axisResolution.test.js +1 -0
- package/src/view/flowBuilder.test.js +1 -0
- package/src/view/scaleResolution.js +5 -11
- package/src/view/scaleResolution.test.js +1 -0
- package/src/view/unitView.js +8 -4
- package/src/view/view.test.js +1 -0
- package/src/view/viewFactory.test.js +1 -0
- package/src/gl/includes/fp64-arithmetic.glsl +0 -187
- package/src/gl/includes/fp64-utils.js +0 -142
- package/src/gl/includes/scales_fp64.glsl +0 -30
package/dist/schema.json
CHANGED
|
@@ -4062,10 +4062,6 @@
|
|
|
4062
4062
|
"description": "The exponent of the `pow` scale.",
|
|
4063
4063
|
"type": "number"
|
|
4064
4064
|
},
|
|
4065
|
-
"fp64": {
|
|
4066
|
-
"description": "Use emulated 64bit floating points on the GPU to increase precision.\n\nEmulation has a performance cost when compared to the native 32bit processing, but the effect is negligible in the most cases.\n\n__Default value:__ `true` for `\"locus\"` scale, `false` for others.",
|
|
4067
|
-
"type": "boolean"
|
|
4068
|
-
},
|
|
4069
4065
|
"interpolate": {
|
|
4070
4066
|
"anyOf": [
|
|
4071
4067
|
{
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"contributors": [],
|
|
9
9
|
"license": "BSD-2-Clause",
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.19.1",
|
|
11
11
|
"main": "dist/index.js",
|
|
12
12
|
"module": "src/index.js",
|
|
13
13
|
"exports": {
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"dev": "node dev-server.js",
|
|
29
29
|
"build": "vite build && npm run build:schema",
|
|
30
30
|
"prepublishOnly": "npm run build",
|
|
31
|
+
"test:vitest": "vitest run",
|
|
31
32
|
"test:tsc": "tsc -p tsconfig.json",
|
|
32
33
|
"checkSpec": "tsc --allowJs --checkJs --strict --noEmit --moduleResolution node --target es6 src/spec/root.d.ts",
|
|
33
34
|
"build:schema": "mkdir -p dist && ts-json-schema-generator --path 'src/spec/*.ts' --type RootSpec > dist/schema.json"
|
|
@@ -52,5 +53,5 @@
|
|
|
52
53
|
"vega-scale": "^7.1.1",
|
|
53
54
|
"vega-util": "^1.16.0"
|
|
54
55
|
},
|
|
55
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "ca14d08659918a002fb330ffcd325e9c1e122a8c"
|
|
56
57
|
}
|
package/src/data/collector.js
CHANGED
|
@@ -27,7 +27,7 @@ export default class Collector extends FlowNode {
|
|
|
27
27
|
/** @type {(function(Collector):void)[]} */
|
|
28
28
|
this.observers = [];
|
|
29
29
|
|
|
30
|
-
/** @type {Map<any | any[], Data>} */
|
|
30
|
+
/** @type {Map<any | any[], Data>} TODO: proper type for key */
|
|
31
31
|
this.facetBatches = undefined;
|
|
32
32
|
|
|
33
33
|
this._init();
|
|
@@ -59,8 +59,6 @@ export default class Collector extends FlowNode {
|
|
|
59
59
|
* @param {import("./flowBatch").FlowBatch} flowBatch
|
|
60
60
|
*/
|
|
61
61
|
beginBatch(flowBatch) {
|
|
62
|
-
// TODO: Propagate batches to children(?)
|
|
63
|
-
|
|
64
62
|
if (isFacetBatch(flowBatch)) {
|
|
65
63
|
this._data = [];
|
|
66
64
|
this.facetBatches.set(asArray(flowBatch.facetId), this._data);
|
|
@@ -103,7 +101,14 @@ export default class Collector extends FlowNode {
|
|
|
103
101
|
}
|
|
104
102
|
|
|
105
103
|
if (this.children.length) {
|
|
106
|
-
for (const data of this.facetBatches.
|
|
104
|
+
for (const [key, data] of this.facetBatches.entries()) {
|
|
105
|
+
if (key) {
|
|
106
|
+
/** @type {import("./flowBatch").FacetBatch} */
|
|
107
|
+
const facetBatch = { type: "facet", facetId: key };
|
|
108
|
+
for (const child of this.children) {
|
|
109
|
+
child.beginBatch(facetBatch);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
107
112
|
for (const datum of data) {
|
|
108
113
|
this._propagate(datum);
|
|
109
114
|
}
|
package/src/data/flow.test.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Collector from "./collector";
|
|
1
2
|
import { BEHAVIOR_CLONES } from "./flowNode";
|
|
2
3
|
import CloneTransform from "./transforms/clone";
|
|
3
4
|
|
|
@@ -31,6 +32,11 @@ export function validateLinks(node, parent = undefined) {
|
|
|
31
32
|
* @param {FlowNode} node
|
|
32
33
|
*/
|
|
33
34
|
export function removeRedundantCloneTransforms(node, cloneRequired = false) {
|
|
35
|
+
if (node instanceof Collector) {
|
|
36
|
+
// If an object is modified downstream of Collector, it must be cloned
|
|
37
|
+
cloneRequired = true;
|
|
38
|
+
}
|
|
39
|
+
|
|
34
40
|
if (node instanceof CloneTransform) {
|
|
35
41
|
if (cloneRequired) {
|
|
36
42
|
cloneRequired = false;
|
package/src/genome/genome.js
CHANGED
|
@@ -257,15 +257,27 @@ export default class Genome {
|
|
|
257
257
|
parseInterval(str) {
|
|
258
258
|
// TODO: consider changing [0-9XY] to support other species besides humans
|
|
259
259
|
const matches = str.match(
|
|
260
|
-
/^(chr[0-9A-Z]+)
|
|
260
|
+
/^(chr[0-9A-Z]+)(?::([0-9,]+)(?:-(?:(chr[0-9A-Z]+):)?([0-9,]+))?)?$/
|
|
261
261
|
);
|
|
262
262
|
|
|
263
263
|
if (matches) {
|
|
264
264
|
const startChr = matches[1];
|
|
265
|
+
|
|
266
|
+
if (matches.slice(2).every((x) => x === undefined)) {
|
|
267
|
+
const chrom = this.getChromosome(startChr);
|
|
268
|
+
if (chrom) {
|
|
269
|
+
return [chrom.continuousStart, chrom.continuousEnd];
|
|
270
|
+
}
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
265
274
|
const endChr = matches[3] || startChr;
|
|
266
275
|
|
|
267
276
|
const startIndex = parseInt(matches[2].replace(/,/g, ""));
|
|
268
|
-
const endIndex =
|
|
277
|
+
const endIndex =
|
|
278
|
+
matches[4] !== undefined
|
|
279
|
+
? parseInt(matches[4].replace(/,/g, ""))
|
|
280
|
+
: startIndex;
|
|
269
281
|
|
|
270
282
|
return [
|
|
271
283
|
this.toContinuous(startChr, startIndex - 1),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
1
2
|
import Genome from "./genome";
|
|
2
3
|
|
|
3
4
|
describe("Human genome, chromosome names prefixed with 'chr'", () => {
|
|
@@ -150,3 +151,38 @@ describe("C. elegans genome, chromosome names prefixed with 'chr'", () => {
|
|
|
150
151
|
expect(g.toContinuous("III", 10)).toEqual(30351865);
|
|
151
152
|
});
|
|
152
153
|
});
|
|
154
|
+
|
|
155
|
+
describe("Parse interval strings", () => {
|
|
156
|
+
const chromosomes = [
|
|
157
|
+
{ name: "chr1", size: 1000 },
|
|
158
|
+
{ name: "chr2", size: 2000 },
|
|
159
|
+
{ name: "chr3", size: 3000 },
|
|
160
|
+
{ name: "chrX", size: 4000 },
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
const g = new Genome({ name: "random", contigs: chromosomes });
|
|
164
|
+
|
|
165
|
+
test("Parses a single chromosome, returns an interval spanning the chromosome", () => {
|
|
166
|
+
expect(g.parseInterval("chr2")).toEqual([1000, 3000]);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("Returns undefined on unknown chromosome", () => {
|
|
170
|
+
expect(g.parseInterval("chrZ")).toBeUndefined();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test("Parses a single coordinate without a thousand separator", () => {
|
|
174
|
+
expect(g.parseInterval("chr2:1500")).toEqual([2499, 2500]);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test("Parses a single coordinate with a thousand separator", () => {
|
|
178
|
+
expect(g.parseInterval("chr2:1,500")).toEqual([2499, 2500]);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("Parses an interval within a single chromosome", () => {
|
|
182
|
+
expect(g.parseInterval("chr2:1,500-1,700")).toEqual([2499, 2700]);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test("Parses an interval spanning multiple chromosomes", () => {
|
|
186
|
+
expect(g.parseInterval("chr2:1,500-chr3:1,500")).toEqual([2499, 4500]);
|
|
187
|
+
});
|
|
188
|
+
});
|
package/src/genome/scaleIndex.js
CHANGED
|
@@ -24,7 +24,7 @@ export default function scaleIndex() {
|
|
|
24
24
|
let numberingOffset = 0;
|
|
25
25
|
|
|
26
26
|
const scaleFunction = (/** @type {number} */ x) =>
|
|
27
|
-
((x - domain[0]) / domainSpan) * rangeSpan + range[0];
|
|
27
|
+
((x + align - domain[0]) / domainSpan) * rangeSpan + range[0];
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* In principle, the domain consists of integer indices. However,
|
|
@@ -34,7 +34,8 @@ export default function scaleIndex() {
|
|
|
34
34
|
*/
|
|
35
35
|
const scale = /** @type {any} */ (scaleFunction);
|
|
36
36
|
|
|
37
|
-
scale.invert = (y) =>
|
|
37
|
+
scale.invert = (y) =>
|
|
38
|
+
((y - range[0]) / rangeSpan) * domainSpan + domain[0] - align;
|
|
38
39
|
|
|
39
40
|
// @ts-expect-error
|
|
40
41
|
scale.domain = function (_) {
|
|
@@ -1,23 +1,40 @@
|
|
|
1
|
+
import { expect, test } from "vitest";
|
|
1
2
|
import scaleIndex from "./scaleIndex";
|
|
2
3
|
|
|
3
4
|
test("Scale with defaults works as expected", () => {
|
|
4
5
|
const scale = scaleIndex();
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
expect(scale(
|
|
8
|
-
expect(scale(
|
|
9
|
-
expect(scale(
|
|
7
|
+
// Align is 0.5 by default
|
|
8
|
+
expect(scale(-1)).toEqual(-0.5);
|
|
9
|
+
expect(scale(0)).toEqual(0.5);
|
|
10
|
+
expect(scale(1)).toEqual(1.5);
|
|
11
|
+
expect(scale(2)).toEqual(2.5);
|
|
10
12
|
});
|
|
11
13
|
|
|
12
14
|
test("Scale scales correctly with custom domain and range", () => {
|
|
13
|
-
const scale = scaleIndex().domain([0, 10]).range([100, 200]);
|
|
15
|
+
const scale = scaleIndex().domain([0, 10]).range([100, 200]).align(0.0);
|
|
14
16
|
|
|
15
17
|
expect(scale(0)).toEqual(100);
|
|
16
18
|
expect(scale(10)).toEqual(200);
|
|
17
19
|
});
|
|
18
20
|
|
|
19
21
|
test("Invert works as expected", () => {
|
|
20
|
-
const scale = scaleIndex().domain([0, 10]).range([100, 200]);
|
|
22
|
+
const scale = scaleIndex().domain([0, 10]).range([100, 200]).align(0.0);
|
|
23
|
+
|
|
24
|
+
expect(scale.invert(scale(0))).toEqual(0);
|
|
25
|
+
expect(scale.invert(scale(5))).toEqual(5);
|
|
26
|
+
expect(scale.invert(scale(10))).toEqual(10);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("Scale scales correctly with custom domain, range, and align", () => {
|
|
30
|
+
const scale = scaleIndex().domain([0, 10]).range([100, 200]).align(0.5);
|
|
31
|
+
|
|
32
|
+
expect(scale(0)).toEqual(105);
|
|
33
|
+
expect(scale(10)).toEqual(205);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("Invert works as expected with align", () => {
|
|
37
|
+
const scale = scaleIndex().domain([0, 10]).range([100, 200]).align(0.5);
|
|
21
38
|
|
|
22
39
|
expect(scale.invert(scale(0))).toEqual(0);
|
|
23
40
|
expect(scale.invert(scale(5))).toEqual(5);
|
package/src/gl/dataToVertices.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { InternMap } from "internmap";
|
|
2
2
|
import { format } from "d3-format";
|
|
3
3
|
import { isString } from "vega-util";
|
|
4
|
-
import { fp64ify } from "./includes/fp64-utils";
|
|
5
4
|
import ArrayBuilder from "./arrayBuilder";
|
|
6
5
|
import { SDF_PADDING } from "../fonts/bmFontMetrics";
|
|
7
6
|
import { peek } from "../utils/arrayUtils";
|
|
8
7
|
import createBinningRangeIndexer from "../utils/binnedRangeIndex";
|
|
9
8
|
import { isValueDef } from "../encoder/encoder";
|
|
9
|
+
import {
|
|
10
|
+
isHighPrecisionScale,
|
|
11
|
+
splitHighPrecision,
|
|
12
|
+
} from "../scale/glslScaleGenerator";
|
|
10
13
|
|
|
11
14
|
/**
|
|
12
15
|
* @typedef {object} RangeEntry Represents a location of a vertex subset
|
|
@@ -55,7 +58,7 @@ export class GeometryBuilder {
|
|
|
55
58
|
const accessor = ce.accessor;
|
|
56
59
|
|
|
57
60
|
const doubleArray = [0, 0];
|
|
58
|
-
const
|
|
61
|
+
const hp = isHighPrecisionScale(ce.scale.type);
|
|
59
62
|
|
|
60
63
|
const indexer = ce.indexer;
|
|
61
64
|
|
|
@@ -68,14 +71,14 @@ export class GeometryBuilder {
|
|
|
68
71
|
*/
|
|
69
72
|
const f = indexer
|
|
70
73
|
? (d) => indexer(accessor(d))
|
|
71
|
-
:
|
|
72
|
-
? (d) =>
|
|
74
|
+
: hp
|
|
75
|
+
? (d) => splitHighPrecision(accessor(d), doubleArray)
|
|
73
76
|
: accessor;
|
|
74
77
|
|
|
75
78
|
this.variableBuilder.addConverter(channel, {
|
|
76
79
|
f,
|
|
77
|
-
numComponents:
|
|
78
|
-
arrayReference:
|
|
80
|
+
numComponents: hp ? 2 : 1,
|
|
81
|
+
arrayReference: hp ? doubleArray : undefined,
|
|
79
82
|
});
|
|
80
83
|
}
|
|
81
84
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#define PI 3.141593
|
|
2
2
|
|
|
3
3
|
/** Offset in "unit" units */
|
|
4
|
-
uniform vec2 uViewOffset;
|
|
4
|
+
uniform mediump vec2 uViewOffset;
|
|
5
5
|
|
|
6
|
-
uniform vec2 uViewScale;
|
|
6
|
+
uniform mediump vec2 uViewScale;
|
|
7
7
|
|
|
8
8
|
/** Size of the logical viewport in pixels, i.e., the view */
|
|
9
|
-
uniform vec2 uViewportSize;
|
|
9
|
+
uniform mediump vec2 uViewportSize;
|
|
10
10
|
|
|
11
11
|
uniform lowp float uDevicePixelRatio;
|
|
12
12
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const float inf = 1.0 / 0.0;
|
|
2
|
+
|
|
1
3
|
// Utils ------------
|
|
2
4
|
|
|
3
5
|
vec3 getDiscreteColor(sampler2D s, int index) {
|
|
@@ -67,15 +69,44 @@ float scaleBand(float value, vec2 domainExtent, vec2 range,
|
|
|
67
69
|
// TODO: reverse
|
|
68
70
|
float start = range[0];
|
|
69
71
|
float stop = range[1];
|
|
72
|
+
float rangeSpan = stop - start;
|
|
70
73
|
|
|
71
74
|
float n = domainExtent[1] - domainExtent[0];
|
|
72
75
|
|
|
76
|
+
// This fix departs from Vega and d3: https://github.com/vega/vega/issues/3357#issuecomment-1063253596
|
|
73
77
|
paddingInner = int(n) > 1 ? paddingInner : 0.0;
|
|
74
78
|
|
|
75
79
|
// Adapted from: https://github.com/d3/d3-scale/blob/master/src/band.js
|
|
76
|
-
float step =
|
|
77
|
-
start += (
|
|
80
|
+
float step = rangeSpan / max(1.0, n - paddingInner + paddingOuter * 2.0);
|
|
81
|
+
start += (rangeSpan - step * (n - paddingInner)) * align;
|
|
78
82
|
float bandwidth = step * (1.0 - paddingInner);
|
|
79
83
|
|
|
80
84
|
return start + (value - domainExtent[0]) * step + bandwidth * band;
|
|
81
85
|
}
|
|
86
|
+
|
|
87
|
+
// High precision variant of scaleBand for index/locus scales
|
|
88
|
+
float scaleBandHp(vec2 value, vec3 domainExtent, vec2 range,
|
|
89
|
+
float paddingInner, float paddingOuter,
|
|
90
|
+
float align, float band) {
|
|
91
|
+
|
|
92
|
+
// TODO: reverse
|
|
93
|
+
float start = range[0];
|
|
94
|
+
float stop = range[1];
|
|
95
|
+
float rangeSpan = stop - start;
|
|
96
|
+
|
|
97
|
+
vec2 domainStart = domainExtent.xy;
|
|
98
|
+
float n = domainExtent[2];
|
|
99
|
+
|
|
100
|
+
// The following computation is identical for every vertex. Could be done on the JS side.
|
|
101
|
+
float step = rangeSpan / max(1.0, n - paddingInner + paddingOuter * 2.0);
|
|
102
|
+
start += (rangeSpan - step * (n - paddingInner)) * align;
|
|
103
|
+
float bandwidth = step * (1.0 - paddingInner);
|
|
104
|
+
|
|
105
|
+
// Using max to prevent the shader compiler from wrecking the precision.
|
|
106
|
+
// Othwewise the compiler could optimize the sum of the four terms into
|
|
107
|
+
// some equivalent form that does premature rounding.
|
|
108
|
+
float hi = max(value[0] - domainStart[0], -inf);
|
|
109
|
+
float lo = max(value[1] - domainStart[1], -inf);
|
|
110
|
+
|
|
111
|
+
return dot(vec4(start, hi, lo, bandwidth), vec4(1.0, step, step, band));
|
|
112
|
+
}
|
package/src/gl/point.vertex.glsl
CHANGED
package/src/gl/rule.vertex.glsl
CHANGED
package/src/gl/webGLHelper.js
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
setTextureFromArray,
|
|
9
9
|
} from "twgl.js";
|
|
10
10
|
import { isArray, isString } from "vega-util";
|
|
11
|
-
import { getPlatformShaderDefines } from "./includes/fp64-utils";
|
|
12
11
|
|
|
13
12
|
import { isDiscrete, isDiscretizing, isInterpolating } from "vega-scale";
|
|
14
13
|
import {
|
|
@@ -81,8 +80,6 @@ export default class WebGLHelper {
|
|
|
81
80
|
// Always use pre-multiplied alpha
|
|
82
81
|
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
|
83
82
|
|
|
84
|
-
this._shaderDefines = getPlatformShaderDefines(gl);
|
|
85
|
-
|
|
86
83
|
this.canvas = canvas;
|
|
87
84
|
this.gl = gl;
|
|
88
85
|
|
package/src/marks/mark.js
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
setUniforms,
|
|
9
9
|
} from "twgl.js";
|
|
10
10
|
import { isDiscrete } from "vega-scale";
|
|
11
|
-
import { fp64ify } from "../gl/includes/fp64-utils";
|
|
12
11
|
import createEncoders, {
|
|
13
12
|
isChannelDefWithScale,
|
|
14
13
|
isDatumDef,
|
|
@@ -20,11 +19,12 @@ import {
|
|
|
20
19
|
generateScaleGlsl,
|
|
21
20
|
RANGE_TEXTURE_PREFIX,
|
|
22
21
|
ATTRIBUTE_PREFIX,
|
|
22
|
+
isHighPrecisionScale,
|
|
23
|
+
toHighPrecisionDomainUniform,
|
|
24
|
+
splitHighPrecision,
|
|
23
25
|
} from "../scale/glslScaleGenerator";
|
|
24
|
-
import FP64 from "../gl/includes/fp64-arithmetic.glsl";
|
|
25
26
|
import GLSL_COMMON from "../gl/includes/common.glsl";
|
|
26
27
|
import GLSL_SCALES from "../gl/includes/scales.glsl";
|
|
27
|
-
import GLSL_SCALES_FP64 from "../gl/includes/scales_fp64.glsl";
|
|
28
28
|
import GLSL_SAMPLE_FACET from "../gl/includes/sampleFacet.glsl";
|
|
29
29
|
import GLSL_PICKING_VERTEX from "../gl/includes/picking.vertex.glsl";
|
|
30
30
|
import GLSL_PICKING_FRAGMENT from "../gl/includes/picking.fragment.glsl";
|
|
@@ -334,7 +334,10 @@ export default class Mark {
|
|
|
334
334
|
"};\n\n"
|
|
335
335
|
: "";
|
|
336
336
|
|
|
337
|
+
const vertexPrecision = "precision highp float;\n";
|
|
338
|
+
|
|
337
339
|
const vertexParts = [
|
|
340
|
+
vertexPrecision,
|
|
338
341
|
...extraHeaders,
|
|
339
342
|
GLSL_COMMON,
|
|
340
343
|
GLSL_SCALES,
|
|
@@ -345,11 +348,6 @@ export default class Mark {
|
|
|
345
348
|
vertexShader,
|
|
346
349
|
];
|
|
347
350
|
|
|
348
|
-
if (vertexParts.some((code) => /[Ff]p64/.test(code))) {
|
|
349
|
-
vertexParts.unshift(GLSL_SCALES_FP64);
|
|
350
|
-
vertexParts.unshift(FP64);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
351
|
const fragmentParts = [
|
|
354
352
|
...extraHeaders,
|
|
355
353
|
GLSL_COMMON,
|
|
@@ -413,8 +411,8 @@ export default class Mark {
|
|
|
413
411
|
|
|
414
412
|
const datum = encoder.indexer
|
|
415
413
|
? encoder.indexer(channelDef.datum)
|
|
416
|
-
: encoder.scale.
|
|
417
|
-
?
|
|
414
|
+
: isHighPrecisionScale(encoder.scale.type)
|
|
415
|
+
? splitHighPrecision(+channelDef.datum)
|
|
418
416
|
: +channelDef.datum;
|
|
419
417
|
|
|
420
418
|
setUniforms(this.programInfo, {
|
|
@@ -579,8 +577,8 @@ export default class Mark {
|
|
|
579
577
|
: scale.domain();
|
|
580
578
|
|
|
581
579
|
setter(
|
|
582
|
-
scale.
|
|
583
|
-
? domain
|
|
580
|
+
isHighPrecisionScale(scale.type)
|
|
581
|
+
? toHighPrecisionDomainUniform(domain)
|
|
584
582
|
: domain
|
|
585
583
|
);
|
|
586
584
|
}
|
|
@@ -624,7 +622,6 @@ export default class Mark {
|
|
|
624
622
|
}
|
|
625
623
|
|
|
626
624
|
setUniforms(this.programInfo, {
|
|
627
|
-
ONE: 1.0, // a hack needed by emulated 64 bit floats
|
|
628
625
|
uDevicePixelRatio: this.glHelper.dpr,
|
|
629
626
|
uViewOpacity: this.unitView.getEffectiveOpacity(),
|
|
630
627
|
// TODO: Rendering of the mark should be completely skipped if it doesn't
|