From 822df3dd514ec3d05f876e6746cb8ba6348ac89d Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 1 Aug 2017 12:22:16 -0700 Subject: [core] Use separate attribute component for line normals Broadcom GPUs don't cope well with using the least significant bit for this. --- include/mbgl/util/constants.hpp | 3 ++- mapbox-gl-js | 2 +- package.json | 5 +++-- scripts/generate-shaders.js | 4 ++-- src/mbgl/programs/attributes.hpp | 1 + src/mbgl/programs/line_program.cpp | 2 +- src/mbgl/programs/line_program.hpp | 12 +++++++----- src/mbgl/renderer/buckets/line_bucket.cpp | 6 +++--- src/mbgl/shaders/line.cpp | 20 +++++++++----------- src/mbgl/shaders/line_pattern.cpp | 19 +++++++++---------- src/mbgl/shaders/line_sdf.cpp | 19 +++++++++---------- 11 files changed, 47 insertions(+), 46 deletions(-) diff --git a/include/mbgl/util/constants.hpp b/include/mbgl/util/constants.hpp index c2250c6f2e..250c77b078 100644 --- a/include/mbgl/util/constants.hpp +++ b/include/mbgl/util/constants.hpp @@ -19,7 +19,8 @@ constexpr float tileSize = 512; * * Positions are stored as signed 16bit integers. * One bit is lost for signedness to support features extending past the left edge of the tile. - * One bit is lost because the line vertex buffer packs 1 bit of other data into the int. + * One bit is lost because the line vertex buffer used to pack 1 bit of other data into the int. + * This is no longer the case but we're reserving this bit anyway. * One bit is lost to support features extending past the extent on the right edge of the tile. * This leaves us with 2^13 = 8192 */ diff --git a/mapbox-gl-js b/mapbox-gl-js index b93bc451cc..94ded74b15 160000 --- a/mapbox-gl-js +++ b/mapbox-gl-js @@ -1 +1 @@ -Subproject commit b93bc451ccb57a3a0debddab9590d37b5cb06d47 +Subproject commit 94ded74b1562ac0adba97ab80fb8eae970ad2473 diff --git a/package.json b/package.json index f2329fb9fd..2f665e680a 100644 --- a/package.json +++ b/package.json @@ -13,14 +13,15 @@ }, "license": "BSD-2-Clause", "dependencies": { - "node-pre-gyp": "^0.6.28", - "nan": "^2.4.0" + "nan": "^2.4.0", + "node-pre-gyp": "^0.6.36" }, "devDependencies": { "aws-sdk": "^2.3.5", "csscolorparser": "^1.0.2", "ejs": "^2.4.1", "express": "^4.11.1", + "flow-remove-types": "^1.2.1", "lodash": "^4.16.4", "mapbox-gl-styles": "2.0.2", "pixelmatch": "^4.0.2", diff --git a/scripts/generate-shaders.js b/scripts/generate-shaders.js index 39aed3053e..cf54b1b100 100755 --- a/scripts/generate-shaders.js +++ b/scripts/generate-shaders.js @@ -1,8 +1,8 @@ #!/usr/bin/env node -const path = require('path'); -const fs = require('fs'); +require('flow-remove-types/register'); +const path = require('path'); const shaders = require('../mapbox-gl-js/src/shaders'); const outputPath = 'src/mbgl/shaders'; diff --git a/src/mbgl/programs/attributes.hpp b/src/mbgl/programs/attributes.hpp index 684d9d6099..3a38453d30 100644 --- a/src/mbgl/programs/attributes.hpp +++ b/src/mbgl/programs/attributes.hpp @@ -23,6 +23,7 @@ inline uint16_t packUint8Pair(T a, T b) { MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_pos); MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_extrude); MBGL_DEFINE_ATTRIBUTE(int16_t, 4, a_pos_offset); +MBGL_DEFINE_ATTRIBUTE(int16_t, 3, a_pos_normal); MBGL_DEFINE_ATTRIBUTE(float, 3, a_projected_pos); MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_label_pos); MBGL_DEFINE_ATTRIBUTE(int16_t, 2, a_anchor_pos); diff --git a/src/mbgl/programs/line_program.cpp b/src/mbgl/programs/line_program.cpp index db5c916d32..f9e91f569f 100644 --- a/src/mbgl/programs/line_program.cpp +++ b/src/mbgl/programs/line_program.cpp @@ -10,7 +10,7 @@ namespace mbgl { using namespace style; -static_assert(sizeof(LineLayoutVertex) == 8, "expected LineLayoutVertex size"); +static_assert(sizeof(LineLayoutVertex) == 10, "expected LineLayoutVertex size"); template Values makeValues(const RenderLinePaintProperties::PossiblyEvaluated& properties, diff --git a/src/mbgl/programs/line_program.hpp b/src/mbgl/programs/line_program.hpp index ed4a09bf10..95b9362b85 100644 --- a/src/mbgl/programs/line_program.hpp +++ b/src/mbgl/programs/line_program.hpp @@ -30,7 +30,7 @@ MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_gl_units_to_pixels); } // namespace uniforms struct LineLayoutAttributes : gl::Attributes< - attributes::a_pos, + attributes::a_pos_normal, attributes::a_data> {}; @@ -50,14 +50,16 @@ public: /* * @param p vertex position * @param e extrude normal - * @param t texture normal + * @param round whether the vertex uses a round line cap + * @param up whether the line normal points up or down * @param dir direction of the line cap (-1/0/1) */ - static LayoutVertex layoutVertex(Point p, Point e, Point t, int8_t dir, int32_t linesofar = 0) { + static LayoutVertex layoutVertex(Point p, Point e, bool round, bool up, int8_t dir, int32_t linesofar = 0) { return LayoutVertex { {{ - static_cast((p.x * 2) | t.x), - static_cast((p.y * 2) | t.y) + p.x, + p.y, + static_cast(attributes::packUint8Pair(round ? 1 : 0, up ? 1 : 0)) }}, {{ // add 128 to store a byte in an unsigned byte diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp index 194b012eee..a96518df38 100644 --- a/src/mbgl/renderer/buckets/line_bucket.cpp +++ b/src/mbgl/renderer/buckets/line_bucket.cpp @@ -401,7 +401,7 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate, Point extrude = normal; if (endLeft) extrude = extrude - (util::perp(normal) * endLeft); - vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, { round, false }, endLeft, distance * LINE_DISTANCE_SCALE)); + vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, round, false, endLeft, distance * LINE_DISTANCE_SCALE)); e3 = vertices.vertexSize() - 1 - startVertex; if (e1 >= 0 && e2 >= 0) { triangleStore.emplace_back(e1, e2, e3); @@ -412,7 +412,7 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate, extrude = normal * -1.0; if (endRight) extrude = extrude - (util::perp(normal) * endRight); - vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, { round, true }, -endRight, distance * LINE_DISTANCE_SCALE)); + vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, round, true, -endRight, distance * LINE_DISTANCE_SCALE)); e3 = vertices.vertexSize() - 1 - startVertex; if (e1 >= 0 && e2 >= 0) { triangleStore.emplace_back(e1, e2, e3); @@ -437,7 +437,7 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex, std::size_t startVertex, std::vector& triangleStore) { Point flippedExtrude = extrude * (lineTurnsLeft ? -1.0 : 1.0); - vertices.emplace_back(LineProgram::layoutVertex(currentVertex, flippedExtrude, { false, lineTurnsLeft }, 0, distance * LINE_DISTANCE_SCALE)); + vertices.emplace_back(LineProgram::layoutVertex(currentVertex, flippedExtrude, false, lineTurnsLeft, 0, distance * LINE_DISTANCE_SCALE)); e3 = vertices.vertexSize() - 1 - startVertex; if (e1 >= 0 && e2 >= 0) { triangleStore.emplace_back(e1, e2, e3); diff --git a/src/mbgl/shaders/line.cpp b/src/mbgl/shaders/line.cpp index 26dda5e73c..f68cc91377 100644 --- a/src/mbgl/shaders/line.cpp +++ b/src/mbgl/shaders/line.cpp @@ -21,7 +21,7 @@ const char* line::vertexSource = R"MBGL_SHADER( // #define scale 63.0 #define scale 0.015873016 -attribute vec2 a_pos; +attribute vec3 a_pos_normal; attribute vec4 a_data; uniform mat4 u_matrix; @@ -131,20 +131,21 @@ void main() { vec2 a_extrude = a_data.xy - 128.0; float a_direction = mod(a_data.z, 4.0) - 1.0; - // We store the texture normals in the most insignificant bit - // transform y so that 0 => -1 and 1 => 1 + vec2 pos = a_pos_normal.xy; + + // transform y normal so that 0 => -1 and 1 => 1 // In the texture normal, x is 0 if the normal points straight up/down and 1 if it's a round cap // y is 1 if the normal points up, and -1 if it points down - mediump vec2 normal = mod(a_pos, 2.0); + mediump vec2 normal = unpack_float(a_pos_normal.z); normal.y = sign(normal.y - 0.5); - v_normal = normal; + v_normal = normal; - // these transformations used to be applied in the JS and native code bases. - // moved them into the shader for clarity and simplicity. + // these transformations used to be applied in the JS and native code bases. + // moved them into the shader for clarity and simplicity. gapwidth = gapwidth / 2.0; float halfwidth = width / 2.0; - offset = -1.0 * offset; + offset = -1.0 * offset; float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0); float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING; @@ -161,9 +162,6 @@ void main() { mediump float t = 1.0 - abs(u); mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t); - // Remove the texture normal bit to get the position - vec2 pos = floor(a_pos * 0.5); - vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0); gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude; diff --git a/src/mbgl/shaders/line_pattern.cpp b/src/mbgl/shaders/line_pattern.cpp index 9eee9192d4..f1e64577e2 100644 --- a/src/mbgl/shaders/line_pattern.cpp +++ b/src/mbgl/shaders/line_pattern.cpp @@ -23,7 +23,7 @@ const char* line_pattern::vertexSource = R"MBGL_SHADER( // Retina devices need a smaller distance to avoid aliasing. #define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0 -attribute vec2 a_pos; +attribute vec3 a_pos_normal; attribute vec4 a_data; uniform mat4 u_matrix; @@ -119,19 +119,21 @@ void main() { float a_direction = mod(a_data.z, 4.0) - 1.0; float a_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * LINE_DISTANCE_SCALE; - // We store the texture normals in the most insignificant bit - // transform y so that 0 => -1 and 1 => 1 + vec2 pos = a_pos_normal.xy; + + // transform y normal so that 0 => -1 and 1 => 1 // In the texture normal, x is 0 if the normal points straight up/down and 1 if it's a round cap // y is 1 if the normal points up, and -1 if it points down - mediump vec2 normal = mod(a_pos, 2.0); + mediump vec2 normal = unpack_float(a_pos_normal.z); normal.y = sign(normal.y - 0.5); + v_normal = normal; - // these transformations used to be applied in the JS and native code bases. - // moved them into the shader for clarity and simplicity. + // these transformations used to be applied in the JS and native code bases. + // moved them into the shader for clarity and simplicity. gapwidth = gapwidth / 2.0; float halfwidth = width / 2.0; - offset = -1.0 * offset; + offset = -1.0 * offset; float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0); float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING; @@ -148,9 +150,6 @@ void main() { mediump float t = 1.0 - abs(u); mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t); - // Remove the texture normal bit to get the position - vec2 pos = floor(a_pos * 0.5); - vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0); gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude; diff --git a/src/mbgl/shaders/line_sdf.cpp b/src/mbgl/shaders/line_sdf.cpp index e1aadffcf4..dd81433543 100644 --- a/src/mbgl/shaders/line_sdf.cpp +++ b/src/mbgl/shaders/line_sdf.cpp @@ -23,7 +23,7 @@ const char* line_sdf::vertexSource = R"MBGL_SHADER( // Retina devices need a smaller distance to avoid aliasing. #define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0 -attribute vec2 a_pos; +attribute vec3 a_pos_normal; attribute vec4 a_data; uniform mat4 u_matrix; @@ -157,20 +157,22 @@ void main() { float a_direction = mod(a_data.z, 4.0) - 1.0; float a_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * LINE_DISTANCE_SCALE; - // We store the texture normals in the most insignificant bit - // transform y so that 0 => -1 and 1 => 1 + vec2 pos = a_pos_normal.xy; + + // transform y normal so that 0 => -1 and 1 => 1 // In the texture normal, x is 0 if the normal points straight up/down and 1 if it's a round cap // y is 1 if the normal points up, and -1 if it points down - mediump vec2 normal = mod(a_pos, 2.0); + mediump vec2 normal = unpack_float(a_pos_normal.z); normal.y = sign(normal.y - 0.5); + v_normal = normal; - // these transformations used to be applied in the JS and native code bases. - // moved them into the shader for clarity and simplicity. + // these transformations used to be applied in the JS and native code bases. + // moved them into the shader for clarity and simplicity. gapwidth = gapwidth / 2.0; float halfwidth = width / 2.0; offset = -1.0 * offset; - + float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0); float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING; @@ -186,9 +188,6 @@ void main() { mediump float t = 1.0 - abs(u); mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t); - // Remove the texture normal bit to get the position - vec2 pos = floor(a_pos * 0.5); - vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0); gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude; -- cgit v1.2.1