[core] Don't crash when attribute count is exceeded
This commit is contained in:
committed by
Lauren Budorick
parent
f6da3ba9be
commit
c3346f473a
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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 };
|
||||
|
||||
parameters.programs.heatmapTexture.draw(
|
||||
parameters.context, gl::Triangles(), gl::DepthMode::disabled(),
|
||||
gl::StencilMode::disabled(), parameters.colorModeForRenderPass(),
|
||||
auto& programInstance = parameters.programs.heatmapTexture;
|
||||
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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()
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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()
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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()
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -81,6 +81,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
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user