summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2018-05-04 01:31:43 +0200
committerLauren Budorick <lauren@mapbox.com>2018-05-03 16:31:43 -0700
commitc3346f473ac7e3d49219c8dbc381d92f8fe3f017 (patch)
tree7e7d1c1569c849192209b0c5f5a58ef7736896a1 /src
parentf6da3ba9be27ff9b279730603c517c4cb5e57007 (diff)
downloadqtlocation-mapboxgl-c3346f473ac7e3d49219c8dbc381d92f8fe3f017.tar.gz
[core] Don't crash when attribute count is exceeded
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/gl/attribute.cpp14
-rw-r--r--src/mbgl/gl/attribute.hpp18
-rw-r--r--src/mbgl/gl/context.cpp10
-rw-r--r--src/mbgl/gl/context.hpp4
-rw-r--r--src/mbgl/gl/program.hpp2
-rw-r--r--src/mbgl/gl/vertex_array.cpp6
-rw-r--r--src/mbgl/gl/vertex_array.hpp13
-rw-r--r--src/mbgl/programs/program.hpp34
-rw-r--r--src/mbgl/programs/symbol_program.hpp50
-rw-r--r--src/mbgl/renderer/layers/render_background_layer.cpp63
-rw-r--r--src/mbgl/renderer/layers/render_circle_layer.cpp37
-rw-r--r--src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp91
-rw-r--r--src/mbgl/renderer/layers/render_fill_layer.cpp66
-rw-r--r--src/mbgl/renderer/layers/render_heatmap_layer.cpp68
-rw-r--r--src/mbgl/renderer/layers/render_hillshade_layer.cpp65
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.cpp27
-rw-r--r--src/mbgl/renderer/layers/render_raster_layer.cpp33
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.cpp31
-rw-r--r--src/mbgl/renderer/render_layer.cpp29
-rw-r--r--src/mbgl/renderer/render_layer.hpp11
-rw-r--r--src/mbgl/renderer/render_tile.cpp70
-rw-r--r--src/mbgl/renderer/renderer_impl.cpp24
-rw-r--r--src/mbgl/renderer/sources/render_image_source.cpp28
23 files changed, 557 insertions, 237 deletions
diff --git a/src/mbgl/gl/attribute.cpp b/src/mbgl/gl/attribute.cpp
index bb5b2ddc34..b2d05fe665 100644
--- a/src/mbgl/gl/attribute.cpp
+++ b/src/mbgl/gl/attribute.cpp
@@ -1,14 +1,20 @@
#include <mbgl/gl/attribute.hpp>
+#include <mbgl/gl/context.hpp>
#include <mbgl/gl/gl.hpp>
namespace mbgl {
namespace gl {
-void bindAttributeLocation(ProgramID id, AttributeLocation location, const char* name) {
- if (location >= MAX_ATTRIBUTES) {
- throw gl::Error("too many vertex attributes");
+void bindAttributeLocation(Context& context, ProgramID id, AttributeLocation location, const char* name) {
+ // We're using sequentially numberered attribute locations starting with 0. Therefore we can use
+ // the location as a proxy for the number of attributes.
+ if (location >= context.maximumVertexBindingCount) {
+ // Don't bind the location on this hardware since it exceeds the limit (otherwise we'd get
+ // an OpenGL error). This means we'll see rendering errors, and possibly slow rendering due
+ // to unbound attributes.
+ } else {
+ MBGL_CHECK_ERROR(glBindAttribLocation(id, location, name));
}
- MBGL_CHECK_ERROR(glBindAttribLocation(id, location, name));
}
std::set<std::string> getActiveAttributes(ProgramID id) {
diff --git a/src/mbgl/gl/attribute.hpp b/src/mbgl/gl/attribute.hpp
index fa6c2ddeab..3763f0a583 100644
--- a/src/mbgl/gl/attribute.hpp
+++ b/src/mbgl/gl/attribute.hpp
@@ -17,8 +17,6 @@
namespace mbgl {
namespace gl {
-static constexpr std::size_t MAX_ATTRIBUTES = 8;
-
template <class> struct DataTypeOf;
template <> struct DataTypeOf< int8_t> : std::integral_constant<DataType, DataType::Byte> {};
template <> struct DataTypeOf<uint8_t> : std::integral_constant<DataType, DataType::UnsignedByte> {};
@@ -45,7 +43,7 @@ public:
}
};
-using AttributeBindingArray = std::array<optional<AttributeBinding>, MAX_ATTRIBUTES>;
+using AttributeBindingArray = std::vector<optional<AttributeBinding>>;
/*
gl::Attribute<T,N> manages the binding of a vertex buffer to a GL program attribute.
@@ -214,7 +212,8 @@ const std::size_t Vertex<A1, A2, A3, A4, A5>::attributeOffsets[5] = {
} // namespace detail
-void bindAttributeLocation(ProgramID, AttributeLocation, const char * name);
+class Context;
+void bindAttributeLocation(Context&, ProgramID, AttributeLocation, const char * name);
std::set<std::string> getActiveAttributes(ProgramID);
template <class... As>
@@ -231,13 +230,13 @@ public:
using Vertex = detail::Vertex<typename As::Type...>;
- static Locations bindLocations(const ProgramID& id) {
+ static Locations bindLocations(Context& context, const ProgramID& id) {
std::set<std::string> activeAttributes = getActiveAttributes(id);
AttributeLocation location = 0;
auto maybeBindLocation = [&](const char* name) -> optional<AttributeLocation> {
if (activeAttributes.count(name)) {
- bindAttributeLocation(id, location, name);
+ bindAttributeLocation(context, id, location, name);
return location++;
} else {
return {};
@@ -277,6 +276,7 @@ public:
static AttributeBindingArray toBindingArray(const Locations& locations, const Bindings& bindings) {
AttributeBindingArray result;
+ result.resize(sizeof...(As));
auto maybeAddBinding = [&] (const optional<AttributeLocation>& location,
const optional<AttributeBinding>& binding) {
@@ -289,6 +289,12 @@ public:
return result;
}
+
+ static uint32_t activeBindingCount(const Bindings& bindings) {
+ uint32_t result = 0;
+ util::ignore({ ((result += bool(bindings.template get<As>())), 0)... });
+ return result;
+ }
};
namespace detail {
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index ba44adb42b..c6352d3e84 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -94,7 +94,13 @@ static_assert(underlying_type(BufferUsage::DynamicDraw) == GL_DYNAMIC_DRAW, "Ope
static_assert(std::is_same<BinaryProgramFormat, GLenum>::value, "OpenGL type mismatch");
-Context::Context() = default;
+Context::Context()
+ : maximumVertexBindingCount([] {
+ GLint value;
+ MBGL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value));
+ return value;
+ }()) {
+}
Context::~Context() {
if (cleanupOnDestruction) {
@@ -351,7 +357,7 @@ VertexArray Context::createVertexArray() {
VertexArrayID id = 0;
MBGL_CHECK_ERROR(vertexArray->genVertexArrays(1, &id));
UniqueVertexArray vao(std::move(id), { this });
- return { UniqueVertexArrayState(new VertexArrayState(std::move(vao), *this), VertexArrayStateDeleter { true })};
+ return { UniqueVertexArrayState(new VertexArrayState(std::move(vao)), VertexArrayStateDeleter { true })};
} else {
// On GL implementations which do not support vertex arrays, attribute bindings are global state.
// So return a VertexArray which shares our global state tracking and whose deleter is a no-op.
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index 67624288e2..d95311115e 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -226,7 +226,7 @@ public:
State<value::BindVertexBuffer> vertexBuffer;
State<value::BindVertexArray, const Context&> bindVertexArray { *this };
- VertexArrayState globalVertexArrayState { UniqueVertexArray(0, { this }), *this };
+ VertexArrayState globalVertexArrayState { UniqueVertexArray(0, { this }) };
State<value::PixelStorePack> pixelStorePack;
State<value::PixelStoreUnpack> pixelStoreUnpack;
@@ -239,6 +239,8 @@ public:
#endif // MBGL_USE_GLES2
bool supportsHalfFloatTextures = false;
+ const uint32_t maximumVertexBindingCount;
+ static constexpr const uint32_t minimumRequiredVertexBindingCount = 8;
private:
State<value::StencilFunc> stencilFunc;
diff --git a/src/mbgl/gl/program.hpp b/src/mbgl/gl/program.hpp
index af02ad3d54..f33501cd11 100644
--- a/src/mbgl/gl/program.hpp
+++ b/src/mbgl/gl/program.hpp
@@ -35,7 +35,7 @@ public:
context.createProgram(context.createShader(ShaderType::Vertex, vertexSource),
context.createShader(ShaderType::Fragment, fragmentSource))),
uniformsState((context.linkProgram(program), Uniforms::bindLocations(program))),
- attributeLocations(Attributes::bindLocations(program)) {
+ attributeLocations(Attributes::bindLocations(context, program)) {
// Re-link program after manually binding only active attributes in Attributes::bindLocations
context.linkProgram(program);
diff --git a/src/mbgl/gl/vertex_array.cpp b/src/mbgl/gl/vertex_array.cpp
index 68a500ac45..d552a8292e 100644
--- a/src/mbgl/gl/vertex_array.cpp
+++ b/src/mbgl/gl/vertex_array.cpp
@@ -9,7 +9,11 @@ void VertexArray::bind(Context& context, BufferID indexBuffer, const AttributeBi
context.bindVertexArray = state->vertexArray;
state->indexBuffer = indexBuffer;
- for (AttributeLocation location = 0; location < MAX_ATTRIBUTES; ++location) {
+ state->bindings.reserve(bindings.size());
+ for (AttributeLocation location = 0; location < bindings.size(); ++location) {
+ if (state->bindings.size() <= location) {
+ state->bindings.emplace_back(context, AttributeLocation(location));
+ }
state->bindings[location] = bindings[location];
}
}
diff --git a/src/mbgl/gl/vertex_array.hpp b/src/mbgl/gl/vertex_array.hpp
index 46c67017bb..604754f672 100644
--- a/src/mbgl/gl/vertex_array.hpp
+++ b/src/mbgl/gl/vertex_array.hpp
@@ -15,9 +15,8 @@ class Context;
class VertexArrayState {
public:
- VertexArrayState(UniqueVertexArray vertexArray_, Context& context)
- : vertexArray(std::move(vertexArray_)),
- bindings(makeBindings(context, std::make_index_sequence<MAX_ATTRIBUTES>())) {
+ VertexArrayState(UniqueVertexArray vertexArray_)
+ : vertexArray(std::move(vertexArray_)) {
}
void setDirty() {
@@ -31,13 +30,7 @@ public:
State<value::BindElementBuffer> indexBuffer;
using AttributeState = State<value::VertexAttribute, Context&, AttributeLocation>;
- std::array<AttributeState, MAX_ATTRIBUTES> bindings;
-
-private:
- template <std::size_t... I>
- std::array<AttributeState, MAX_ATTRIBUTES> makeBindings(Context& context, std::index_sequence<I...>) {
- return {{ AttributeState { context, I }... }};
- }
+ std::vector<AttributeState> bindings;
};
class VertexArrayStateDeleter {
diff --git a/src/mbgl/programs/program.hpp b/src/mbgl/programs/program.hpp
index bcdb270b9c..4d5de05337 100644
--- a/src/mbgl/programs/program.hpp
+++ b/src/mbgl/programs/program.hpp
@@ -46,26 +46,38 @@ public:
Shaders::fragmentSource)) {
}
+ static typename AllUniforms::Values computeAllUniformValues(
+ const UniformValues& uniformValues,
+ const PaintPropertyBinders& paintPropertyBinders,
+ const typename PaintProperties::PossiblyEvaluated& currentProperties,
+ float currentZoom) {
+ return uniformValues
+ .concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties));
+ }
+
+ static typename Attributes::Bindings computeAllAttributeBindings(
+ const gl::VertexBuffer<LayoutVertex>& layoutVertexBuffer,
+ const PaintPropertyBinders& paintPropertyBinders,
+ const typename PaintProperties::PossiblyEvaluated& currentProperties) {
+ return LayoutAttributes::bindings(layoutVertexBuffer)
+ .concat(paintPropertyBinders.attributeBindings(currentProperties));
+ }
+
+ static uint32_t activeBindingCount(const typename Attributes::Bindings& allAttributeBindings) {
+ return Attributes::activeBindingCount(allAttributeBindings);
+ }
+
template <class DrawMode>
void draw(gl::Context& context,
DrawMode drawMode,
gl::DepthMode depthMode,
gl::StencilMode stencilMode,
gl::ColorMode colorMode,
- const UniformValues& uniformValues,
- const gl::VertexBuffer<LayoutVertex>& layoutVertexBuffer,
const gl::IndexBuffer<DrawMode>& indexBuffer,
const SegmentVector<Attributes>& segments,
- const PaintPropertyBinders& paintPropertyBinders,
- const typename PaintProperties::PossiblyEvaluated& currentProperties,
- float currentZoom,
+ const typename AllUniforms::Values& allUniformValues,
+ const typename Attributes::Bindings& allAttributeBindings,
const std::string& layerID) {
- typename AllUniforms::Values allUniformValues = uniformValues
- .concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties));
-
- typename Attributes::Bindings allAttributeBindings = LayoutAttributes::bindings(layoutVertexBuffer)
- .concat(paintPropertyBinders.attributeBindings(currentProperties));
-
for (auto& segment : segments) {
auto vertexArrayIt = segment.vertexArrays.find(layerID);
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
index 9b5037ed9f..51f9a48f7f 100644
--- a/src/mbgl/programs/symbol_program.hpp
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -278,35 +278,45 @@ public:
Shaders::fragmentSource)) {
}
+ static typename AllUniforms::Values computeAllUniformValues(
+ const UniformValues& uniformValues,
+ const SymbolSizeBinder& symbolSizeBinder,
+ const PaintPropertyBinders& paintPropertyBinders,
+ const typename PaintProperties::PossiblyEvaluated& currentProperties,
+ float currentZoom) {
+ return uniformValues.concat(symbolSizeBinder.uniformValues(currentZoom))
+ .concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties));
+ }
+
+ static typename Attributes::Bindings computeAllAttributeBindings(
+ const gl::VertexBuffer<LayoutVertex>& layoutVertexBuffer,
+ const gl::VertexBuffer<SymbolDynamicLayoutAttributes::Vertex>& dynamicLayoutVertexBuffer,
+ const gl::VertexBuffer<SymbolOpacityAttributes::Vertex>& opacityVertexBuffer,
+ const PaintPropertyBinders& paintPropertyBinders,
+ const typename PaintProperties::PossiblyEvaluated& currentProperties) {
+ assert(layoutVertexBuffer.vertexCount == dynamicLayoutVertexBuffer.vertexCount &&
+ layoutVertexBuffer.vertexCount == opacityVertexBuffer.vertexCount);
+ return LayoutAttributes::bindings(layoutVertexBuffer)
+ .concat(SymbolDynamicLayoutAttributes::bindings(dynamicLayoutVertexBuffer))
+ .concat(SymbolOpacityAttributes::bindings(opacityVertexBuffer))
+ .concat(paintPropertyBinders.attributeBindings(currentProperties));
+ }
+
+ static uint32_t activeBindingCount(const typename Attributes::Bindings& allAttributeBindings) {
+ return Attributes::activeBindingCount(allAttributeBindings);
+ }
+
template <class DrawMode>
void draw(gl::Context& context,
DrawMode drawMode,
gl::DepthMode depthMode,
gl::StencilMode stencilMode,
gl::ColorMode colorMode,
- const UniformValues& uniformValues,
- const gl::VertexBuffer<LayoutVertex>& layoutVertexBuffer,
- const gl::VertexBuffer<SymbolDynamicLayoutAttributes::Vertex>& dynamicLayoutVertexBuffer,
- const gl::VertexBuffer<SymbolOpacityAttributes::Vertex>& opacityVertexBuffer,
- const SymbolSizeBinder& symbolSizeBinder,
const gl::IndexBuffer<DrawMode>& indexBuffer,
const SegmentVector<Attributes>& segments,
- const PaintPropertyBinders& paintPropertyBinders,
- const typename PaintProperties::PossiblyEvaluated& currentProperties,
- float currentZoom,
+ const typename AllUniforms::Values& allUniformValues,
+ const typename Attributes::Bindings& allAttributeBindings,
const std::string& layerID) {
- typename AllUniforms::Values allUniformValues = uniformValues
- .concat(symbolSizeBinder.uniformValues(currentZoom))
- .concat(paintPropertyBinders.uniformValues(currentZoom, currentProperties));
-
- typename Attributes::Bindings allAttributeBindings = LayoutAttributes::bindings(layoutVertexBuffer)
- .concat(SymbolDynamicLayoutAttributes::bindings(dynamicLayoutVertexBuffer))
- .concat(SymbolOpacityAttributes::bindings(opacityVertexBuffer))
- .concat(paintPropertyBinders.attributeBindings(currentProperties));
-
- assert(layoutVertexBuffer.vertexCount == dynamicLayoutVertexBuffer.vertexCount &&
- layoutVertexBuffer.vertexCount == opacityVertexBuffer.vertexCount);
-
for (auto& segment : segments) {
auto vertexArrayIt = segment.vertexArrays.find(layerID);
diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp
index aebc4cc9aa..f22402ac98 100644
--- a/src/mbgl/renderer/layers/render_background_layer.cpp
+++ b/src/mbgl/renderer/layers/render_background_layer.cpp
@@ -49,6 +49,35 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) {
const Properties<>::PossiblyEvaluated properties;
const BackgroundProgram::PaintPropertyBinders paintAttributeData(properties, 0);
+ auto draw = [&](auto& program, auto&& uniformValues) {
+ const auto allUniformValues = program.computeAllUniformValues(
+ std::move(uniformValues),
+ paintAttributeData,
+ properties,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = program.computeAllAttributeBindings(
+ parameters.staticData.tileVertexBuffer,
+ paintAttributeData,
+ properties
+ );
+
+ checkRenderability(parameters, program.activeBindingCount(allAttributeBindings));
+
+ program.draw(
+ parameters.context,
+ gl::Triangles(),
+ parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ gl::StencilMode::disabled(),
+ parameters.colorModeForRenderPass(),
+ parameters.staticData.quadTriangleIndexBuffer,
+ parameters.staticData.tileTriangleSegments,
+ allUniformValues,
+ allAttributeBindings,
+ getID()
+ );
+ };
+
if (!evaluated.get<BackgroundPattern>().to.empty()) {
optional<ImagePosition> imagePosA = parameters.imageManager.getPattern(evaluated.get<BackgroundPattern>().from);
optional<ImagePosition> imagePosB = parameters.imageManager.getPattern(evaluated.get<BackgroundPattern>().to);
@@ -59,12 +88,8 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) {
parameters.imageManager.bind(parameters.context, 0);
for (const auto& tileID : util::tileCover(parameters.state, parameters.state.getIntegerZoom())) {
- parameters.programs.backgroundPattern.draw(
- parameters.context,
- gl::Triangles(),
- parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
- gl::StencilMode::disabled(),
- parameters.colorModeForRenderPass(),
+ draw(
+ parameters.programs.backgroundPattern,
BackgroundPatternUniforms::values(
parameters.matrixForTile(tileID),
evaluated.get<BackgroundOpacity>(),
@@ -74,36 +99,18 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) {
evaluated.get<BackgroundPattern>(),
tileID,
parameters.state
- ),
- parameters.staticData.tileVertexBuffer,
- parameters.staticData.quadTriangleIndexBuffer,
- parameters.staticData.tileTriangleSegments,
- paintAttributeData,
- properties,
- parameters.state.getZoom(),
- getID()
+ )
);
}
} else {
for (const auto& tileID : util::tileCover(parameters.state, parameters.state.getIntegerZoom())) {
- parameters.programs.background.draw(
- parameters.context,
- gl::Triangles(),
- parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
- gl::StencilMode::disabled(),
- parameters.colorModeForRenderPass(),
+ draw(
+ parameters.programs.background,
BackgroundProgram::UniformValues {
uniforms::u_matrix::Value{ parameters.matrixForTile(tileID) },
uniforms::u_color::Value{ evaluated.get<BackgroundColor>() },
uniforms::u_opacity::Value{ evaluated.get<BackgroundOpacity>() },
- },
- parameters.staticData.tileVertexBuffer,
- parameters.staticData.quadTriangleIndexBuffer,
- parameters.staticData.tileTriangleSegments,
- paintAttributeData,
- properties,
- parameters.state.getZoom(),
- getID()
+ }
);
}
}
diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp
index 6092ff5452..4c96137143 100644
--- a/src/mbgl/renderer/layers/render_circle_layer.cpp
+++ b/src/mbgl/renderer/layers/render_circle_layer.cpp
@@ -59,14 +59,11 @@ void RenderCircleLayer::render(PaintParameters& parameters, RenderSource*) {
assert(dynamic_cast<CircleBucket*>(tile.tile.getBucket(*baseImpl)));
CircleBucket& bucket = *reinterpret_cast<CircleBucket*>(tile.tile.getBucket(*baseImpl));
- parameters.programs.circle.get(evaluated).draw(
- parameters.context,
- gl::Triangles(),
- parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
- parameters.mapMode != MapMode::Continuous
- ? parameters.stencilModeForClipping(tile.clip)
- : gl::StencilMode::disabled(),
- parameters.colorModeForRenderPass(),
+ const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
+
+ auto& programInstance = parameters.programs.circle.get(evaluated);
+
+ const auto allUniformValues = programInstance.computeAllUniformValues(
CircleProgram::UniformValues {
uniforms::u_matrix::Value{
tile.translatedMatrix(evaluated.get<CircleTranslate>(),
@@ -82,12 +79,30 @@ void RenderCircleLayer::render(PaintParameters& parameters, RenderSource*) {
uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() },
uniforms::u_pitch_with_map::Value{ pitchWithMap }
},
+ paintPropertyBinders,
+ evaluated,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
*bucket.vertexBuffer,
+ paintPropertyBinders,
+ evaluated
+ );
+
+ checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
+
+ programInstance.draw(
+ parameters.context,
+ gl::Triangles(),
+ parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ parameters.mapMode != MapMode::Continuous
+ ? parameters.stencilModeForClipping(tile.clip)
+ : gl::StencilMode::disabled(),
+ parameters.colorModeForRenderPass(),
*bucket.indexBuffer,
bucket.segments,
- bucket.paintPropertyBinders.at(getID()),
- evaluated,
- parameters.state.getZoom(),
+ allUniformValues,
+ allAttributeBindings,
getID()
);
}
diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
index fbd6160e8a..00ab05858f 100644
--- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
+++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
@@ -68,24 +68,53 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
parameters.context.setStencilMode(gl::StencilMode::disabled());
parameters.context.clear(Color{ 0.0f, 0.0f, 0.0f, 0.0f }, depthClearValue, {});
+ auto draw = [&](auto& programInstance, const auto& tileBucket, auto&& uniformValues) {
+ const auto& paintPropertyBinders = tileBucket.paintPropertyBinders.at(getID());
+
+ const auto allUniformValues = programInstance.computeAllUniformValues(
+ std::move(uniformValues),
+ paintPropertyBinders,
+ evaluated,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
+ *tileBucket.vertexBuffer,
+ paintPropertyBinders,
+ evaluated
+ );
+
+ checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
+
+ programInstance.draw(
+ parameters.context,
+ gl::Triangles(),
+ parameters.depthModeFor3D(gl::DepthMode::ReadWrite),
+ gl::StencilMode::disabled(),
+ parameters.colorModeForRenderPass(),
+ *tileBucket.indexBuffer,
+ tileBucket.triangleSegments,
+ allUniformValues,
+ allAttributeBindings,
+ getID());
+ };
+
if (evaluated.get<FillExtrusionPattern>().from.empty()) {
for (const RenderTile& tile : renderTiles) {
assert(dynamic_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl)));
FillExtrusionBucket& bucket =
*reinterpret_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl));
- parameters.programs.fillExtrusion.get(evaluated).draw(
- parameters.context, gl::Triangles(),
- parameters.depthModeFor3D(gl::DepthMode::ReadWrite),
- gl::StencilMode::disabled(), parameters.colorModeForRenderPass(),
+ draw(
+ parameters.programs.fillExtrusion.get(evaluated),
+ bucket,
FillExtrusionUniforms::values(
tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(),
evaluated.get<FillExtrusionTranslateAnchor>(),
parameters.state),
- parameters.state, parameters.evaluatedLight),
- *bucket.vertexBuffer, *bucket.indexBuffer, bucket.triangleSegments,
- bucket.paintPropertyBinders.at(getID()), evaluated, parameters.state.getZoom(),
- getID());
+ parameters.state,
+ parameters.evaluatedLight
+ )
+ );
}
} else {
optional<ImagePosition> imagePosA =
@@ -104,10 +133,9 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
FillExtrusionBucket& bucket =
*reinterpret_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl));
- parameters.programs.fillExtrusionPattern.get(evaluated).draw(
- parameters.context, gl::Triangles(),
- parameters.depthModeFor3D(gl::DepthMode::ReadWrite),
- gl::StencilMode::disabled(), parameters.colorModeForRenderPass(),
+ draw(
+ parameters.programs.fillExtrusionPattern.get(evaluated),
+ bucket,
FillExtrusionPatternUniforms::values(
tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(),
evaluated.get<FillExtrusionTranslateAnchor>(),
@@ -115,10 +143,9 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
parameters.imageManager.getPixelSize(), *imagePosA, *imagePosB,
evaluated.get<FillExtrusionPattern>(), tile.id, parameters.state,
-std::pow(2, tile.id.canonical.z) / util::tileSize / 8.0f,
- parameters.evaluatedLight),
- *bucket.vertexBuffer, *bucket.indexBuffer, bucket.triangleSegments,
- bucket.paintPropertyBinders.at(getID()), evaluated, parameters.state.getZoom(),
- getID());
+ parameters.evaluatedLight
+ )
+ );
}
}
@@ -131,19 +158,39 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1);
const Properties<>::PossiblyEvaluated properties;
+ const ExtrusionTextureProgram::PaintPropertyBinders paintAttributeData{ properties, 0 };
+
+ auto& programInstance = parameters.programs.extrusionTexture;
- parameters.programs.extrusionTexture.draw(
- parameters.context, gl::Triangles(), gl::DepthMode::disabled(),
- gl::StencilMode::disabled(), parameters.colorModeForRenderPass(),
+ const auto allUniformValues = programInstance.computeAllUniformValues(
ExtrusionTextureProgram::UniformValues{
uniforms::u_matrix::Value{ viewportMat }, uniforms::u_world::Value{ size },
uniforms::u_image::Value{ 0 },
- uniforms::u_opacity::Value{ evaluated.get<FillExtrusionOpacity>() } },
+ uniforms::u_opacity::Value{ evaluated.get<FillExtrusionOpacity>() }
+ },
+ paintAttributeData,
+ properties,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
parameters.staticData.extrusionTextureVertexBuffer,
+ paintAttributeData,
+ properties
+ );
+
+ checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
+
+ programInstance.draw(
+ parameters.context,
+ gl::Triangles(),
+ gl::DepthMode::disabled(),
+ gl::StencilMode::disabled(),
+ parameters.colorModeForRenderPass(),
parameters.staticData.quadTriangleIndexBuffer,
parameters.staticData.extrusionTextureSegments,
- ExtrusionTextureProgram::PaintPropertyBinders{ properties, 0 }, properties,
- parameters.state.getZoom(), getID());
+ allUniformValues,
+ allAttributeBindings,
+ getID());
}
}
diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp
index 22cb9563c1..2607ebc170 100644
--- a/src/mbgl/renderer/layers/render_fill_layer.cpp
+++ b/src/mbgl/renderer/layers/render_fill_layer.cpp
@@ -69,12 +69,11 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
const auto& depthMode,
const auto& indexBuffer,
const auto& segments) {
- program.get(evaluated).draw(
- parameters.context,
- drawMode,
- depthMode,
- parameters.stencilModeForClipping(tile.clip),
- parameters.colorModeForRenderPass(),
+ auto& programInstance = program.get(evaluated);
+
+ const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
+
+ const auto allUniformValues = programInstance.computeAllUniformValues(
FillProgram::UniformValues {
uniforms::u_matrix::Value{
tile.translatedMatrix(evaluated.get<FillTranslate>(),
@@ -83,12 +82,28 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
},
uniforms::u_world::Value{ parameters.context.viewport.getCurrentValue().size },
},
+ paintPropertyBinders,
+ evaluated,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
*bucket.vertexBuffer,
+ paintPropertyBinders,
+ evaluated
+ );
+
+ checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
+
+ programInstance.draw(
+ parameters.context,
+ drawMode,
+ depthMode,
+ parameters.stencilModeForClipping(tile.clip),
+ parameters.colorModeForRenderPass(),
indexBuffer,
segments,
- bucket.paintPropertyBinders.at(getID()),
- evaluated,
- parameters.state.getZoom(),
+ allUniformValues,
+ allAttributeBindings,
getID()
);
};
@@ -139,12 +154,11 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
const auto& depthMode,
const auto& indexBuffer,
const auto& segments) {
- program.get(evaluated).draw(
- parameters.context,
- drawMode,
- depthMode,
- parameters.stencilModeForClipping(tile.clip),
- parameters.colorModeForRenderPass(),
+ auto& programInstance = program.get(evaluated);
+
+ const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
+
+ const auto allUniformValues = programInstance.computeAllUniformValues(
FillPatternUniforms::values(
tile.translatedMatrix(evaluated.get<FillTranslate>(),
evaluated.get<FillTranslateAnchor>(),
@@ -157,12 +171,28 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
tile.id,
parameters.state
),
+ paintPropertyBinders,
+ evaluated,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
*bucket.vertexBuffer,
+ paintPropertyBinders,
+ evaluated
+ );
+
+ checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
+
+ programInstance.draw(
+ parameters.context,
+ drawMode,
+ depthMode,
+ parameters.stencilModeForClipping(tile.clip),
+ parameters.colorModeForRenderPass(),
indexBuffer,
segments,
- bucket.paintPropertyBinders.at(getID()),
- evaluated,
- parameters.state.getZoom(),
+ allUniformValues,
+ allAttributeBindings,
getID()
);
};
diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp
index 4f2e899220..86884b01a4 100644
--- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp
+++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp
@@ -92,23 +92,38 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
? parameters.stencilModeForClipping(tile.clip)
: gl::StencilMode::disabled();
- parameters.programs.heatmap.get(evaluated).draw(
+ const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
+
+ auto& programInstance = parameters.programs.heatmap.get(evaluated);
+
+ const auto allUniformValues = programInstance.computeAllUniformValues(
+ HeatmapProgram::UniformValues {
+ uniforms::u_intensity::Value{ evaluated.get<style::HeatmapIntensity>() },
+ uniforms::u_matrix::Value{ tile.matrix },
+ uniforms::heatmap::u_extrude_scale::Value{ extrudeScale }
+ },
+ paintPropertyBinders,
+ evaluated,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
+ *bucket.vertexBuffer,
+ paintPropertyBinders,
+ evaluated
+ );
+
+ checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
+
+ programInstance.draw(
parameters.context,
gl::Triangles(),
parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
stencilMode,
gl::ColorMode::additive(),
- HeatmapProgram::UniformValues {
- uniforms::u_intensity::Value{evaluated.get<style::HeatmapIntensity>()},
- uniforms::u_matrix::Value{tile.matrix},
- uniforms::heatmap::u_extrude_scale::Value{extrudeScale}
- },
- *bucket.vertexBuffer,
*bucket.indexBuffer,
bucket.segments,
- bucket.paintPropertyBinders.at(getID()),
- evaluated,
- parameters.state.getZoom(),
+ allUniformValues,
+ allAttributeBindings,
getID()
);
}
@@ -123,20 +138,41 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1);
const Properties<>::PossiblyEvaluated properties;
+ const HeatmapTextureProgram::PaintPropertyBinders paintAttributeData{ properties, 0 };
+
+ auto& programInstance = parameters.programs.heatmapTexture;
- parameters.programs.heatmapTexture.draw(
- parameters.context, gl::Triangles(), gl::DepthMode::disabled(),
- gl::StencilMode::disabled(), parameters.colorModeForRenderPass(),
+ const auto allUniformValues = programInstance.computeAllUniformValues(
HeatmapTextureProgram::UniformValues{
uniforms::u_matrix::Value{ viewportMat }, uniforms::u_world::Value{ size },
uniforms::u_image::Value{ 0 },
uniforms::u_color_ramp::Value{ 1 },
- uniforms::u_opacity::Value{ evaluated.get<HeatmapOpacity>() } },
+ uniforms::u_opacity::Value{ evaluated.get<HeatmapOpacity>() }
+ },
+ paintAttributeData,
+ properties,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
parameters.staticData.extrusionTextureVertexBuffer,
+ paintAttributeData,
+ properties
+ );
+
+ checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
+
+ programInstance.draw(
+ parameters.context,
+ gl::Triangles(),
+ gl::DepthMode::disabled(),
+ gl::StencilMode::disabled(),
+ parameters.colorModeForRenderPass(),
parameters.staticData.quadTriangleIndexBuffer,
parameters.staticData.extrusionTextureSegments,
- HeatmapTextureProgram::PaintPropertyBinders{ properties, 0 }, properties,
- parameters.state.getZoom(), getID());
+ allUniformValues,
+ allAttributeBindings,
+ getID()
+ );
}
}
diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp
index bcfd4ffe99..411305edf4 100644
--- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp
+++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp
@@ -69,12 +69,11 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
const auto& indexBuffer,
const auto& segments,
const UnwrappedTileID& id) {
- parameters.programs.hillshade.draw(
- parameters.context,
- gl::Triangles(),
- parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
- gl::StencilMode::disabled(),
- parameters.colorModeForRenderPass(),
+ auto& programInstance = parameters.programs.hillshade;
+
+ const HillshadeProgram::PaintPropertyBinders paintAttributeData{ evaluated, 0 };
+
+ const auto allUniformValues = programInstance.computeAllUniformValues(
HillshadeProgram::UniformValues {
uniforms::u_matrix::Value{ matrix },
uniforms::u_image::Value{ 0 },
@@ -84,12 +83,28 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
uniforms::u_light::Value{ getLight(parameters) },
uniforms::u_latrange::Value{ getLatRange(id) },
},
+ paintAttributeData,
+ evaluated,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
vertexBuffer,
+ paintAttributeData,
+ evaluated
+ );
+
+ checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
+
+ programInstance.draw(
+ parameters.context,
+ gl::Triangles(),
+ parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ gl::StencilMode::disabled(),
+ parameters.colorModeForRenderPass(),
indexBuffer,
segments,
- HillshadeProgram::PaintPropertyBinders { evaluated, 0 },
- evaluated,
- parameters.state.getZoom(),
+ allUniformValues,
+ allAttributeBindings,
getID()
);
};
@@ -112,13 +127,11 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
parameters.context.bindTexture(*bucket.dem, 0, gl::TextureFilter::Nearest, gl::TextureMipMap::No, gl::TextureWrap::Clamp, gl::TextureWrap::Clamp);
const Properties<>::PossiblyEvaluated properties;
+ const HillshadePrepareProgram::PaintPropertyBinders paintAttributeData{ properties, 0 };
- parameters.programs.hillshadePrepare.draw(
- parameters.context,
- gl::Triangles(),
- parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
- gl::StencilMode::disabled(),
- parameters.colorModeForRenderPass(),
+ auto& programInstance = parameters.programs.hillshadePrepare;
+
+ const auto allUniformValues = programInstance.computeAllUniformValues(
HillshadePrepareProgram::UniformValues {
uniforms::u_matrix::Value { mat },
uniforms::u_dimension::Value { {{uint16_t(tilesize * 2), uint16_t(tilesize * 2) }} },
@@ -126,12 +139,28 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src
uniforms::u_maxzoom::Value{ float(maxzoom) },
uniforms::u_image::Value{ 0 }
},
+ paintAttributeData,
+ properties,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
parameters.staticData.rasterVertexBuffer,
+ paintAttributeData,
+ properties
+ );
+
+ checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
+
+ programInstance.draw(
+ parameters.context,
+ gl::Triangles(),
+ parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ gl::StencilMode::disabled(),
+ parameters.colorModeForRenderPass(),
parameters.staticData.quadTriangleIndexBuffer,
parameters.staticData.rasterSegments,
- HillshadePrepareProgram::PaintPropertyBinders { properties, 0 },
- properties,
- parameters.state.getZoom(),
+ allUniformValues,
+ allAttributeBindings,
getID()
);
bucket.texture = std::move(view.getTexture());
diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp
index 1b4a1c0ff7..e7fe4d34b2 100644
--- a/src/mbgl/renderer/layers/render_line_layer.cpp
+++ b/src/mbgl/renderer/layers/render_line_layer.cpp
@@ -62,19 +62,34 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
LineBucket& bucket = *reinterpret_cast<LineBucket*>(tile.tile.getBucket(*baseImpl));
auto draw = [&] (auto& program, auto&& uniformValues) {
- program.get(evaluated).draw(
+ auto& programInstance = program.get(evaluated);
+
+ const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
+
+ const auto allUniformValues = programInstance.computeAllUniformValues(
+ std::move(uniformValues),
+ paintPropertyBinders,
+ evaluated,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
+ *bucket.vertexBuffer,
+ paintPropertyBinders,
+ evaluated
+ );
+
+ checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
+
+ programInstance.draw(
parameters.context,
gl::Triangles(),
parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
parameters.stencilModeForClipping(tile.clip),
parameters.colorModeForRenderPass(),
- std::move(uniformValues),
- *bucket.vertexBuffer,
*bucket.indexBuffer,
bucket.segments,
- bucket.paintPropertyBinders.at(getID()),
- evaluated,
- parameters.state.getZoom(),
+ allUniformValues,
+ allAttributeBindings,
getID()
);
};
diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp
index b41b2ac560..f202ed4ebb 100644
--- a/src/mbgl/renderer/layers/render_raster_layer.cpp
+++ b/src/mbgl/renderer/layers/render_raster_layer.cpp
@@ -73,16 +73,15 @@ void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source
if (parameters.pass != RenderPass::Translucent)
return;
+ RasterProgram::PaintPropertyBinders paintAttributeData{ evaluated, 0 };
+
auto draw = [&] (const mat4& matrix,
const auto& vertexBuffer,
const auto& indexBuffer,
const auto& segments) {
- parameters.programs.raster.draw(
- parameters.context,
- gl::Triangles(),
- parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
- gl::StencilMode::disabled(),
- parameters.colorModeForRenderPass(),
+ auto& programInstance = parameters.programs.raster;
+
+ const auto allUniformValues = programInstance.computeAllUniformValues(
RasterProgram::UniformValues {
uniforms::u_matrix::Value{ matrix },
uniforms::u_image0::Value{ 0 },
@@ -98,12 +97,28 @@ void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source
uniforms::u_scale_parent::Value{ 1.0f },
uniforms::u_tl_parent::Value{ std::array<float, 2> {{ 0.0f, 0.0f }} },
},
+ paintAttributeData,
+ evaluated,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
vertexBuffer,
+ paintAttributeData,
+ evaluated
+ );
+
+ checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
+
+ programInstance.draw(
+ parameters.context,
+ gl::Triangles(),
+ parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ gl::StencilMode::disabled(),
+ parameters.colorModeForRenderPass(),
indexBuffer,
segments,
- RasterProgram::PaintPropertyBinders { evaluated, 0 },
- evaluated,
- parameters.state.getZoom(),
+ allUniformValues,
+ allAttributeBindings,
getID()
);
};
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp
index 9e493003c0..e48c0e2f92 100644
--- a/src/mbgl/renderer/layers/render_symbol_layer.cpp
+++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp
@@ -88,7 +88,26 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
const auto& binders,
const auto& paintProperties)
{
- program.get(paintProperties).draw(
+ auto& programInstance = program.get(paintProperties);
+
+ const auto allUniformValues = programInstance.computeAllUniformValues(
+ std::move(uniformValues),
+ *symbolSizeBinder,
+ binders,
+ paintProperties,
+ parameters.state.getZoom()
+ );
+ const auto allAttributeBindings = programInstance.computeAllAttributeBindings(
+ *buffers.vertexBuffer,
+ *buffers.dynamicVertexBuffer,
+ *buffers.opacityVertexBuffer,
+ binders,
+ paintProperties
+ );
+
+ checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings));
+
+ programInstance.draw(
parameters.context,
gl::Triangles(),
values_.pitchAlignment == AlignmentType::Map
@@ -96,16 +115,10 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
: gl::DepthMode::disabled(),
gl::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
- std::move(uniformValues),
- *buffers.vertexBuffer,
- *buffers.dynamicVertexBuffer,
- *buffers.opacityVertexBuffer,
- *symbolSizeBinder,
*buffers.indexBuffer,
buffers.segments,
- binders,
- paintProperties,
- parameters.state.getZoom(),
+ allUniformValues,
+ allAttributeBindings,
getID()
);
};
diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp
index bcdc175f14..a667d5837e 100644
--- a/src/mbgl/renderer/render_layer.cpp
+++ b/src/mbgl/renderer/render_layer.cpp
@@ -9,8 +9,10 @@
#include <mbgl/renderer/layers/render_raster_layer.hpp>
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
#include <mbgl/renderer/layers/render_heatmap_layer.hpp>
+#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/util/logging.hpp>
namespace mbgl {
@@ -73,5 +75,32 @@ void RenderLayer::setRenderTiles(std::vector<std::reference_wrapper<RenderTile>>
renderTiles = std::move(tiles);
}
+void RenderLayer::checkRenderability(const PaintParameters& parameters,
+ const uint32_t activeBindingCount) {
+ // Only warn once for every layer.
+ if (hasRenderFailures) {
+ return;
+ }
+
+ if (activeBindingCount > parameters.context.maximumVertexBindingCount) {
+ Log::Error(Event::OpenGL,
+ "The layer '%s' uses more data-driven properties than the current device "
+ "supports, and will have rendering errors. To ensure compatibility with this "
+ "device, use %d fewer data driven properties in this layer.",
+ getID().c_str(),
+ activeBindingCount - parameters.context.minimumRequiredVertexBindingCount);
+ hasRenderFailures = true;
+ } else if (activeBindingCount > parameters.context.minimumRequiredVertexBindingCount) {
+ Log::Error(Event::OpenGL,
+ "The layer '%s' uses more data-driven properties than some devices may support. "
+ "Though it will render correctly on this device, it may have rendering errors "
+ "on other devices. To ensure compatibility with all devices, use %d fewer "
+ "data-driven properties in this layer.",
+ getID().c_str(),
+ activeBindingCount - parameters.context.minimumRequiredVertexBindingCount);
+ hasRenderFailures = true;
+ }
+}
+
} //namespace mbgl
diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp
index 55831cb72c..5b92ffa4db 100644
--- a/src/mbgl/renderer/render_layer.hpp
+++ b/src/mbgl/renderer/render_layer.hpp
@@ -82,6 +82,11 @@ public:
friend std::string layoutKey(const RenderLayer&);
protected:
+ // Checks whether the current hardware can render this layer. If it can't, we'll show a warning
+ // in the console to inform the developer.
+ void checkRenderability(const PaintParameters&, uint32_t activeBindingCount);
+
+protected:
// renderTiles are exposed directly to CrossTileSymbolIndex and Placement so they
// can update opacities in the symbol buckets immediately before rendering
friend class CrossTileSymbolIndex;
@@ -92,6 +97,12 @@ protected:
// Stores what render passes this layer is currently enabled for. This depends on the
// evaluated StyleProperties object and is updated accordingly.
RenderPass passes = RenderPass::None;
+
+private:
+ // Some layers may not render correctly on some hardware when the vertex attribute limit of
+ // that GPU is exceeded. More attributes are used when adding many data driven paint properties
+ // to a layer.
+ bool hasRenderFailures = false;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp
index 35b34833e4..64790938ef 100644
--- a/src/mbgl/renderer/render_tile.cpp
+++ b/src/mbgl/renderer/render_tile.cpp
@@ -74,6 +74,8 @@ void RenderTile::finishRender(PaintParameters& parameters) {
static const style::Properties<>::PossiblyEvaluated properties {};
static const DebugProgram::PaintPropertyBinders paintAttributeData(properties, 0);
+ auto& program = parameters.programs.debug;
+
if (parameters.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) {
if (!tile.debugBucket || tile.debugBucket->renderable != tile.isRenderable() ||
tile.debugBucket->complete != tile.isComplete() ||
@@ -85,41 +87,51 @@ void RenderTile::finishRender(PaintParameters& parameters) {
tile.expires, parameters.debugOptions, parameters.context);
}
- parameters.programs.debug.draw(
+ const auto allAttributeBindings = program.computeAllAttributeBindings(
+ *tile.debugBucket->vertexBuffer,
+ paintAttributeData,
+ properties
+ );
+
+ program.draw(
parameters.context,
gl::Lines { 4.0f * parameters.pixelRatio },
gl::DepthMode::disabled(),
parameters.stencilModeForClipping(clip),
gl::ColorMode::unblended(),
- DebugProgram::UniformValues {
- uniforms::u_matrix::Value{ matrix },
- uniforms::u_color::Value{ Color::white() }
- },
- *tile.debugBucket->vertexBuffer,
*tile.debugBucket->indexBuffer,
tile.debugBucket->segments,
- paintAttributeData,
- properties,
- parameters.state.getZoom(),
+ program.computeAllUniformValues(
+ DebugProgram::UniformValues {
+ uniforms::u_matrix::Value{ matrix },
+ uniforms::u_color::Value{ Color::white() }
+ },
+ paintAttributeData,
+ properties,
+ parameters.state.getZoom()
+ ),
+ allAttributeBindings,
"debug"
);
- parameters.programs.debug.draw(
+ program.draw(
parameters.context,
gl::Lines { 2.0f * parameters.pixelRatio },
gl::DepthMode::disabled(),
parameters.stencilModeForClipping(clip),
gl::ColorMode::unblended(),
- DebugProgram::UniformValues {
- uniforms::u_matrix::Value{ matrix },
- uniforms::u_color::Value{ Color::black() }
- },
- *tile.debugBucket->vertexBuffer,
*tile.debugBucket->indexBuffer,
tile.debugBucket->segments,
- paintAttributeData,
- properties,
- parameters.state.getZoom(),
+ program.computeAllUniformValues(
+ DebugProgram::UniformValues {
+ uniforms::u_matrix::Value{ matrix },
+ uniforms::u_color::Value{ Color::black() }
+ },
+ paintAttributeData,
+ properties,
+ parameters.state.getZoom()
+ ),
+ allAttributeBindings,
"debug"
);
}
@@ -131,16 +143,22 @@ void RenderTile::finishRender(PaintParameters& parameters) {
gl::DepthMode::disabled(),
parameters.stencilModeForClipping(clip),
gl::ColorMode::unblended(),
- DebugProgram::UniformValues {
- uniforms::u_matrix::Value{ matrix },
- uniforms::u_color::Value{ Color::red() }
- },
- parameters.staticData.tileVertexBuffer,
parameters.staticData.tileBorderIndexBuffer,
parameters.staticData.tileBorderSegments,
- paintAttributeData,
- properties,
- parameters.state.getZoom(),
+ program.computeAllUniformValues(
+ DebugProgram::UniformValues {
+ uniforms::u_matrix::Value{ matrix },
+ uniforms::u_color::Value{ Color::red() }
+ },
+ paintAttributeData,
+ properties,
+ parameters.state.getZoom()
+ ),
+ program.computeAllAttributeBindings(
+ parameters.staticData.tileVertexBuffer,
+ paintAttributeData,
+ properties
+ ),
"debug"
);
}
diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp
index 2ac714e122..7b25b37cf2 100644
--- a/src/mbgl/renderer/renderer_impl.cpp
+++ b/src/mbgl/renderer/renderer_impl.cpp
@@ -495,7 +495,9 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
static const ClippingMaskProgram::PaintPropertyBinders paintAttributeData(properties, 0);
for (const auto& clipID : parameters.clipIDGenerator.getClipIDs()) {
- parameters.staticData.programs.clippingMask.draw(
+ auto& program = parameters.staticData.programs.clippingMask;
+
+ program.draw(
parameters.context,
gl::Triangles(),
gl::DepthMode::disabled(),
@@ -508,15 +510,21 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
gl::StencilMode::Replace
},
gl::ColorMode::disabled(),
- ClippingMaskProgram::UniformValues {
- uniforms::u_matrix::Value{ parameters.matrixForTile(clipID.first) },
- },
- parameters.staticData.tileVertexBuffer,
parameters.staticData.quadTriangleIndexBuffer,
parameters.staticData.tileTriangleSegments,
- paintAttributeData,
- properties,
- parameters.state.getZoom(),
+ program.computeAllUniformValues(
+ ClippingMaskProgram::UniformValues {
+ uniforms::u_matrix::Value{ parameters.matrixForTile(clipID.first) },
+ },
+ paintAttributeData,
+ properties,
+ parameters.state.getZoom()
+ ),
+ program.computeAllAttributeBindings(
+ parameters.staticData.tileVertexBuffer,
+ paintAttributeData,
+ properties
+ ),
"clipping"
);
}
diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp
index 31a5916a34..4946b0bc30 100644
--- a/src/mbgl/renderer/sources/render_image_source.cpp
+++ b/src/mbgl/renderer/sources/render_image_source.cpp
@@ -58,24 +58,32 @@ void RenderImageSource::finishRender(PaintParameters& parameters) {
static const style::Properties<>::PossiblyEvaluated properties {};
static const DebugProgram::PaintPropertyBinders paintAttributeData(properties, 0);
+ auto& programInstance = parameters.programs.debug;
+
for (auto matrix : matrices) {
- parameters.programs.debug.draw(
+ programInstance.draw(
parameters.context,
gl::LineStrip { 4.0f * parameters.pixelRatio },
gl::DepthMode::disabled(),
gl::StencilMode::disabled(),
gl::ColorMode::unblended(),
- DebugProgram::UniformValues {
- uniforms::u_matrix::Value{ matrix },
- uniforms::u_color::Value{ Color::red() }
- },
- parameters.staticData.tileVertexBuffer,
parameters.staticData.tileBorderIndexBuffer,
parameters.staticData.tileBorderSegments,
- paintAttributeData,
- properties,
- parameters.state.getZoom(),
- "debug"
+ programInstance.computeAllUniformValues(
+ DebugProgram::UniformValues {
+ uniforms::u_matrix::Value{ matrix },
+ uniforms::u_color::Value{ Color::red() }
+ },
+ paintAttributeData,
+ properties,
+ parameters.state.getZoom()
+ ),
+ programInstance.computeAllAttributeBindings(
+ parameters.staticData.tileVertexBuffer,
+ paintAttributeData,
+ properties
+ ),
+ "image"
);
}
}