core: Tolerate stencil clipping setup failures (#4317)
This commit is contained in:
@@ -3,7 +3,6 @@
|
|||||||
#define GL_GLEXT_PROTOTYPES
|
#define GL_GLEXT_PROTOTYPES
|
||||||
|
|
||||||
#include <GLES3/gl3.h>
|
#include <GLES3/gl3.h>
|
||||||
#include <GLES3/gl3ext.h>
|
|
||||||
|
|
||||||
namespace mbgl {
|
namespace mbgl {
|
||||||
namespace platform {
|
namespace platform {
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
#include <mbgl/shaders/attributes.hpp>
|
#include <mbgl/shaders/attributes.hpp>
|
||||||
#include <mbgl/util/literal.hpp>
|
#include <mbgl/util/literal.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <algorithm>
|
||||||
#include <string>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace mbgl {
|
namespace mbgl {
|
||||||
namespace gl {
|
namespace gl {
|
||||||
@@ -34,9 +35,12 @@ public:
|
|||||||
void queryLocations(const ProgramID& id) {
|
void queryLocations(const ProgramID& id) {
|
||||||
locations = Locations{
|
locations = Locations{
|
||||||
queryLocation(id, concat_literals<&string_literal<'a', '_'>::value, &As::name>::value())...};
|
queryLocation(id, concat_literals<&string_literal<'a', '_'>::value, &As::name>::value())...};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasExpectedFirstLocation() const {
|
||||||
using TypeOfFirst = typename std::tuple_element_t<0, std::tuple<As...>>;
|
using TypeOfFirst = typename std::tuple_element_t<0, std::tuple<As...>>;
|
||||||
[[maybe_unused]] auto first = locations.template get<TypeOfFirst>();
|
const auto location = locations.template get<TypeOfFirst>();
|
||||||
assert(first && first.value() == 0);
|
return location && *location == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr const char* getFirstAttribName() {
|
static constexpr const char* getFirstAttribName() {
|
||||||
@@ -67,12 +71,24 @@ public:
|
|||||||
|
|
||||||
AttributeBindingArray toBindingArray(const gfx::AttributeBindings<TypeList<As...>>& bindings) const {
|
AttributeBindingArray toBindingArray(const gfx::AttributeBindings<TypeList<As...>>& bindings) const {
|
||||||
AttributeBindingArray result;
|
AttributeBindingArray result;
|
||||||
result.resize(sizeof...(As));
|
|
||||||
|
std::optional<AttributeLocation> maxLocation;
|
||||||
|
auto updateMaxLocation = [&](const std::optional<AttributeLocation>& location) {
|
||||||
|
if (location) {
|
||||||
|
maxLocation = maxLocation ? std::max(*maxLocation, *location) : *location;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
util::ignore({(updateMaxLocation(locations.template get<As>()), 0)...});
|
||||||
|
|
||||||
|
if (maxLocation) {
|
||||||
|
result.resize(*maxLocation + 1);
|
||||||
|
}
|
||||||
|
|
||||||
auto maybeAddBinding = [&](const std::optional<AttributeLocation>& location,
|
auto maybeAddBinding = [&](const std::optional<AttributeLocation>& location,
|
||||||
const std::optional<gfx::AttributeBinding>& binding) {
|
const std::optional<gfx::AttributeBinding>& binding) {
|
||||||
if (location) {
|
if (location) {
|
||||||
result.at(*location) = binding;
|
result[*location] = binding;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -693,6 +693,12 @@ void Context::setStencilMode(const gfx::StencilMode& stencil) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Context::hasStencilBuffer() const {
|
||||||
|
GLint bits = 0;
|
||||||
|
MBGL_CHECK_ERROR(glGetIntegerv(GL_STENCIL_BITS, &bits));
|
||||||
|
return bits > 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Context::setColorMode(const gfx::ColorMode& color) {
|
void Context::setColorMode(const gfx::ColorMode& color) {
|
||||||
if (color.blendFunction.is<gfx::ColorMode::Replace>()) {
|
if (color.blendFunction.is<gfx::ColorMode::Replace>()) {
|
||||||
blend = false;
|
blend = false;
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ public:
|
|||||||
void setColorMode(const gfx::ColorMode&);
|
void setColorMode(const gfx::ColorMode&);
|
||||||
void setCullFaceMode(const gfx::CullFaceMode&);
|
void setCullFaceMode(const gfx::CullFaceMode&);
|
||||||
void setScissorTest(const gfx::ScissorRect&);
|
void setScissorTest(const gfx::ScissorRect&);
|
||||||
|
bool hasStencilBuffer() const;
|
||||||
|
|
||||||
void draw(const gfx::DrawMode&, std::size_t indexOffset, std::size_t indexLength);
|
void draw(const gfx::DrawMode&, std::size_t indexOffset, std::size_t indexLength);
|
||||||
|
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ gfx::ColorMode DrawableGL::makeColorMode(PaintParameters& parameters) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gfx::StencilMode DrawableGL::makeStencilMode(PaintParameters& parameters) const {
|
gfx::StencilMode DrawableGL::makeStencilMode(PaintParameters& parameters) const {
|
||||||
if (enableStencil) {
|
if (enableStencil && parameters.stencilClippingAvailable) {
|
||||||
if (!is3D && tileID) {
|
if (!is3D && tileID) {
|
||||||
return parameters.stencilModeForClipping(tileID->toUnwrapped());
|
return parameters.stencilModeForClipping(tileID->toUnwrapped());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,9 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters)
|
|||||||
bool stencil3d = false;
|
bool stencil3d = false;
|
||||||
gfx::StencilMode stencilMode3d;
|
gfx::StencilMode stencilMode3d;
|
||||||
|
|
||||||
if (getDrawableCount()) {
|
parameters.stencilClippingAvailable = parameters.renderTargetHasStencilBuffer;
|
||||||
|
|
||||||
|
if (getDrawableCount() && parameters.stencilClippingAvailable) {
|
||||||
MLN_TRACE_ZONE(clip masks);
|
MLN_TRACE_ZONE(clip masks);
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
const auto label_clip = getName() + (getName().empty() ? "" : "-") + "tile-clip-masks";
|
const auto label_clip = getName() + (getName().empty() ? "" : "-") + "tile-clip-masks";
|
||||||
@@ -90,10 +92,16 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters)
|
|||||||
if (features3d) {
|
if (features3d) {
|
||||||
stencilMode3d = stencil3d ? parameters.stencilModeFor3D() : gfx::StencilMode::disabled();
|
stencilMode3d = stencil3d ? parameters.stencilModeFor3D() : gfx::StencilMode::disabled();
|
||||||
} else if (stencilTiles && !stencilTiles->empty()) {
|
} else if (stencilTiles && !stencilTiles->empty()) {
|
||||||
parameters.renderTileClippingMasks(stencilTiles);
|
if (!parameters.renderTileClippingMasks(stencilTiles)) {
|
||||||
|
parameters.stencilClippingAvailable = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!parameters.stencilClippingAvailable) {
|
||||||
|
context.setStencilMode(gfx::StencilMode::disabled());
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
const auto label_render = getName() + (getName().empty() ? "" : "-") + "render";
|
const auto label_render = getName() + (getName().empty() ? "" : "-") + "render";
|
||||||
const auto debugGroupRender = parameters.encoder->createDebugGroup(label_render.c_str());
|
const auto debugGroupRender = parameters.encoder->createDebugGroup(label_render.c_str());
|
||||||
@@ -167,6 +175,12 @@ void LayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& context = static_cast<gl::Context&>(parameters.context);
|
||||||
|
parameters.stencilClippingAvailable = parameters.renderTargetHasStencilBuffer;
|
||||||
|
if (!parameters.stencilClippingAvailable) {
|
||||||
|
context.setStencilMode(gfx::StencilMode::disabled());
|
||||||
|
}
|
||||||
|
|
||||||
bool bindUBOs = false;
|
bool bindUBOs = false;
|
||||||
visitDrawables([&](gfx::Drawable& drawable) {
|
visitDrawables([&](gfx::Drawable& drawable) {
|
||||||
if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) {
|
if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <mbgl/util/logging.hpp>
|
#include <mbgl/util/logging.hpp>
|
||||||
|
|
||||||
#if MLN_RENDER_BACKEND_OPENGL
|
#if MLN_RENDER_BACKEND_OPENGL
|
||||||
|
#include <mbgl/gl/context.hpp>
|
||||||
#include <mbgl/shaders/gl/legacy/clipping_mask_program.hpp>
|
#include <mbgl/shaders/gl/legacy/clipping_mask_program.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -95,6 +96,18 @@ PaintParameters::PaintParameters(gfx::Context& context_,
|
|||||||
|
|
||||||
PaintParameters::~PaintParameters() = default;
|
PaintParameters::~PaintParameters() = default;
|
||||||
|
|
||||||
|
#if MLN_RENDER_BACKEND_OPENGL
|
||||||
|
void PaintParameters::updateStencilBufferAvailability() {
|
||||||
|
auto& glContext = static_cast<gl::Context&>(context);
|
||||||
|
renderTargetHasStencilBuffer = glContext.hasStencilBuffer();
|
||||||
|
stencilClippingAvailable = renderTargetHasStencilBuffer;
|
||||||
|
|
||||||
|
if (!stencilClippingAvailable) {
|
||||||
|
glContext.setStencilMode(gfx::StencilMode::disabled());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
mat4 PaintParameters::matrixForTile(const UnwrappedTileID& tileID, bool aligned) const {
|
mat4 PaintParameters::matrixForTile(const UnwrappedTileID& tileID, bool aligned) const {
|
||||||
mat4 matrix;
|
mat4 matrix;
|
||||||
state.matrixFor(matrix, tileID);
|
state.matrixFor(matrix, tileID);
|
||||||
@@ -169,10 +182,14 @@ void PaintParameters::clearStencil() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) {
|
bool PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) {
|
||||||
// We can avoid updating the mask if it already contains the same set of tiles.
|
// We can avoid updating the mask if it already contains the same set of tiles.
|
||||||
if (!renderTiles || !renderPass || tileIDsCovered(renderTiles, tileClippingMaskIDs)) {
|
if (!renderTiles || tileIDsCovered(renderTiles, tileClippingMaskIDs)) {
|
||||||
return;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!renderPass) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tileClippingMaskIDs.clear();
|
tileClippingMaskIDs.clear();
|
||||||
@@ -292,11 +309,9 @@ void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) {
|
|||||||
auto program = staticData.shaders->getLegacyGroup().get<ClippingMaskProgram>();
|
auto program = staticData.shaders->getLegacyGroup().get<ClippingMaskProgram>();
|
||||||
|
|
||||||
if (!program) {
|
if (!program) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static_cast<gl::Context&>(context).renderingStats().stencilUpdates++;
|
|
||||||
|
|
||||||
const style::Properties<>::PossiblyEvaluated properties{};
|
const style::Properties<>::PossiblyEvaluated properties{};
|
||||||
const ClippingMaskProgram::Binders paintAttributeData(properties, 0);
|
const ClippingMaskProgram::Binders paintAttributeData(properties, 0);
|
||||||
|
|
||||||
@@ -313,32 +328,38 @@ void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
program->draw(context,
|
if (!program->draw(context,
|
||||||
*renderPass,
|
*renderPass,
|
||||||
gfx::Triangles(),
|
gfx::Triangles(),
|
||||||
gfx::DepthMode::disabled(),
|
gfx::DepthMode::disabled(),
|
||||||
gfx::StencilMode{gfx::StencilMode::Always{},
|
gfx::StencilMode{gfx::StencilMode::Always{},
|
||||||
stencilID,
|
stencilID,
|
||||||
0b11111111,
|
0b11111111,
|
||||||
gfx::StencilOpType::Keep,
|
gfx::StencilOpType::Keep,
|
||||||
gfx::StencilOpType::Keep,
|
gfx::StencilOpType::Keep,
|
||||||
gfx::StencilOpType::Replace},
|
gfx::StencilOpType::Replace},
|
||||||
gfx::ColorMode::disabled(),
|
gfx::ColorMode::disabled(),
|
||||||
gfx::CullFaceMode::disabled(),
|
gfx::CullFaceMode::disabled(),
|
||||||
*staticData.quadTriangleIndexBuffer,
|
*staticData.quadTriangleIndexBuffer,
|
||||||
staticData.clippingMaskSegments,
|
staticData.clippingMaskSegments,
|
||||||
ClippingMaskProgram::computeAllUniformValues(
|
ClippingMaskProgram::computeAllUniformValues(
|
||||||
ClippingMaskProgram::LayoutUniformValues{
|
ClippingMaskProgram::LayoutUniformValues{
|
||||||
uniforms::matrix::Value(matrixForTile(tileID)),
|
uniforms::matrix::Value(matrixForTile(tileID)),
|
||||||
},
|
},
|
||||||
paintAttributeData,
|
paintAttributeData,
|
||||||
properties,
|
properties,
|
||||||
static_cast<float>(state.getZoom())),
|
static_cast<float>(state.getZoom())),
|
||||||
ClippingMaskProgram::computeAllAttributeBindings(
|
ClippingMaskProgram::computeAllAttributeBindings(
|
||||||
*staticData.tileVertexBuffer, paintAttributeData, properties),
|
*staticData.tileVertexBuffer, paintAttributeData, properties),
|
||||||
"clipping/" + util::toString(stencilID));
|
"clipping/" + util::toString(stencilID))) {
|
||||||
|
tileClippingMaskIDs.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
static_cast<gl::Context&>(context).renderingStats().stencilUpdates++;
|
||||||
#endif // MLN_RENDER_BACKEND_OPENGL
|
#endif // MLN_RENDER_BACKEND_OPENGL
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::StencilMode PaintParameters::stencilModeForClipping(const UnwrappedTileID& tileID) const {
|
gfx::StencilMode PaintParameters::stencilModeForClipping(const UnwrappedTileID& tileID) const {
|
||||||
|
|||||||
@@ -97,7 +97,20 @@ public:
|
|||||||
|
|
||||||
// Stencil handling
|
// Stencil handling
|
||||||
public:
|
public:
|
||||||
void renderTileClippingMasks(const RenderTiles&);
|
#if MLN_RENDER_BACKEND_OPENGL
|
||||||
|
/// Update cached stencil availability for the currently bound GL framebuffer.
|
||||||
|
void updateStencilBufferAvailability();
|
||||||
|
|
||||||
|
/// Whether the current GL render target has a stencil buffer.
|
||||||
|
bool renderTargetHasStencilBuffer = true;
|
||||||
|
|
||||||
|
/// Transient GL draw state for the current layer group. GL layer groups reset this from
|
||||||
|
/// `renderTargetHasStencilBuffer`, then disable it if clipping-mask setup fails.
|
||||||
|
bool stencilClippingAvailable = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @return True when clipping mask state is ready or no update was needed.
|
||||||
|
bool renderTileClippingMasks(const RenderTiles&);
|
||||||
|
|
||||||
/// Clear the stencil buffer, even if there are no tile masks (for 3D)
|
/// Clear the stencil buffer, even if there are no tile masks (for 3D)
|
||||||
void clearStencil();
|
void clearStencil();
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ void RenderTarget::render(RenderOrchestrator& orchestrator, const RenderTree& re
|
|||||||
.clearColor = Color{0.0f, 0.0f, 0.0f, 1.0f},
|
.clearColor = Color{0.0f, 0.0f, 0.0f, 1.0f},
|
||||||
.clearDepth = {},
|
.clearDepth = {},
|
||||||
.clearStencil = {}});
|
.clearStencil = {}});
|
||||||
|
#if MLN_RENDER_BACKEND_OPENGL
|
||||||
|
parameters.updateStencilBufferAvailability();
|
||||||
|
#endif
|
||||||
|
|
||||||
const gfx::ScissorRect prevScissorRect = parameters.scissorRect;
|
const gfx::ScissorRect prevScissorRect = parameters.scissorRect;
|
||||||
const auto& size = getTexture()->getSize();
|
const auto& size = getTexture()->getSize();
|
||||||
|
|||||||
@@ -318,6 +318,9 @@ void Renderer::Impl::render(const RenderTree& renderTree, const std::shared_ptr<
|
|||||||
|
|
||||||
const auto debugGroup(parameters.encoder->createDebugGroup("common-3d"));
|
const auto debugGroup(parameters.encoder->createDebugGroup("common-3d"));
|
||||||
parameters.pass = RenderPass::Pass3D;
|
parameters.pass = RenderPass::Pass3D;
|
||||||
|
#if MLN_RENDER_BACKEND_OPENGL
|
||||||
|
parameters.updateStencilBufferAvailability();
|
||||||
|
#endif
|
||||||
|
|
||||||
// TODO is this needed?
|
// TODO is this needed?
|
||||||
// if (!parameters.staticData.depthRenderbuffer ||
|
// if (!parameters.staticData.depthRenderbuffer ||
|
||||||
@@ -368,6 +371,9 @@ void Renderer::Impl::render(const RenderTree& renderTree, const std::shared_ptr<
|
|||||||
.clearColor = color,
|
.clearColor = color,
|
||||||
.clearDepth = 1.0f,
|
.clearDepth = 1.0f,
|
||||||
.clearStencil = 0});
|
.clearStencil = 0});
|
||||||
|
#if MLN_RENDER_BACKEND_OPENGL
|
||||||
|
parameters.updateStencilBufferAvailability();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class DrawMode>
|
template <class DrawMode>
|
||||||
void draw(gfx::Context& context,
|
bool draw(gfx::Context& context,
|
||||||
gfx::RenderPass& renderPass,
|
gfx::RenderPass& renderPass,
|
||||||
const DrawMode& drawMode,
|
const DrawMode& drawMode,
|
||||||
const gfx::DepthMode& depthMode,
|
const gfx::DepthMode& depthMode,
|
||||||
@@ -106,7 +106,7 @@ public:
|
|||||||
static_assert(Primitive == gfx::PrimitiveTypeOf<DrawMode>::value, "incompatible draw mode");
|
static_assert(Primitive == gfx::PrimitiveTypeOf<DrawMode>::value, "incompatible draw mode");
|
||||||
|
|
||||||
if (!programBase) {
|
if (!programBase) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto drawScopeIt = segment.drawScopes.find(layerID);
|
auto drawScopeIt = segment.drawScopes.find(layerID);
|
||||||
@@ -114,23 +114,23 @@ public:
|
|||||||
drawScopeIt = segment.drawScopes.emplace(layerID, context.createDrawScope()).first;
|
drawScopeIt = segment.drawScopes.emplace(layerID, context.createDrawScope()).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
programBase->draw(context,
|
return programBase->draw(context,
|
||||||
renderPass,
|
renderPass,
|
||||||
drawMode,
|
drawMode,
|
||||||
depthMode,
|
depthMode,
|
||||||
stencilMode,
|
stencilMode,
|
||||||
colorMode,
|
colorMode,
|
||||||
cullFaceMode,
|
cullFaceMode,
|
||||||
uniformValues,
|
uniformValues,
|
||||||
drawScopeIt->second,
|
drawScopeIt->second,
|
||||||
allAttributeBindings.offset(segment.vertexOffset),
|
allAttributeBindings.offset(segment.vertexOffset),
|
||||||
indexBuffer,
|
indexBuffer,
|
||||||
segment.indexOffset,
|
segment.indexOffset,
|
||||||
segment.indexLength);
|
segment.indexLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class DrawMode>
|
template <class DrawMode>
|
||||||
void draw(gfx::Context& context,
|
bool draw(gfx::Context& context,
|
||||||
gfx::RenderPass& renderPass,
|
gfx::RenderPass& renderPass,
|
||||||
const DrawMode& drawMode,
|
const DrawMode& drawMode,
|
||||||
const gfx::DepthMode& depthMode,
|
const gfx::DepthMode& depthMode,
|
||||||
@@ -145,7 +145,7 @@ public:
|
|||||||
static_assert(Primitive == gfx::PrimitiveTypeOf<DrawMode>::value, "incompatible draw mode");
|
static_assert(Primitive == gfx::PrimitiveTypeOf<DrawMode>::value, "incompatible draw mode");
|
||||||
|
|
||||||
if (!programBase) {
|
if (!programBase) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& segment : segments) {
|
for (auto& segment : segments) {
|
||||||
@@ -155,20 +155,23 @@ public:
|
|||||||
drawScopeIt = segment.drawScopes.emplace(layerID, context.createDrawScope()).first;
|
drawScopeIt = segment.drawScopes.emplace(layerID, context.createDrawScope()).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
programBase->draw(context,
|
if (!programBase->draw(context,
|
||||||
renderPass,
|
renderPass,
|
||||||
drawMode,
|
drawMode,
|
||||||
depthMode,
|
depthMode,
|
||||||
stencilMode,
|
stencilMode,
|
||||||
colorMode,
|
colorMode,
|
||||||
cullFaceMode,
|
cullFaceMode,
|
||||||
uniformValues,
|
uniformValues,
|
||||||
drawScopeIt->second,
|
drawScopeIt->second,
|
||||||
allAttributeBindings.offset(segment.vertexOffset),
|
allAttributeBindings.offset(segment.vertexOffset),
|
||||||
indexBuffer,
|
indexBuffer,
|
||||||
segment.indexOffset,
|
segment.indexOffset,
|
||||||
segment.indexLength);
|
segment.indexLength)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
#include <mbgl/util/io.hpp>
|
#include <mbgl/util/io.hpp>
|
||||||
#include <mbgl/util/logging.hpp>
|
#include <mbgl/util/logging.hpp>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace mbgl {
|
namespace mbgl {
|
||||||
@@ -45,6 +47,10 @@ public:
|
|||||||
context.createShader(ShaderType::Fragment, fragmentSource),
|
context.createShader(ShaderType::Fragment, fragmentSource),
|
||||||
attributeLocations.getFirstAttribName())) {
|
attributeLocations.getFirstAttribName())) {
|
||||||
attributeLocations.queryLocations(program);
|
attributeLocations.queryLocations(program);
|
||||||
|
if (!attributeLocations.hasExpectedFirstLocation()) {
|
||||||
|
throw std::runtime_error("Shader is missing active attribute at location 0: " +
|
||||||
|
std::string(attributeLocations.getFirstAttribName()));
|
||||||
|
}
|
||||||
uniformStates.queryLocations(program);
|
uniformStates.queryLocations(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +86,7 @@ public:
|
|||||||
gl::UniformStates<UniformList> uniformStates;
|
gl::UniformStates<UniformList> uniformStates;
|
||||||
};
|
};
|
||||||
|
|
||||||
void draw(gfx::Context& genericContext,
|
bool draw(gfx::Context& genericContext,
|
||||||
gfx::RenderPass&,
|
gfx::RenderPass&,
|
||||||
const gfx::DrawMode& drawMode,
|
const gfx::DrawMode& drawMode,
|
||||||
const gfx::DepthMode& depthMode,
|
const gfx::DepthMode& depthMode,
|
||||||
@@ -101,6 +107,10 @@ public:
|
|||||||
context.setCullFaceMode(cullFaceMode);
|
context.setCullFaceMode(cullFaceMode);
|
||||||
|
|
||||||
const uint32_t key = gl::AttributeKey<AttributeList>::compute(attributeBindings);
|
const uint32_t key = gl::AttributeKey<AttributeList>::compute(attributeBindings);
|
||||||
|
if (failedInstances.contains(key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto it = instances.find(key);
|
auto it = instances.find(key);
|
||||||
if (it == instances.end()) {
|
if (it == instances.end()) {
|
||||||
try {
|
try {
|
||||||
@@ -112,7 +122,8 @@ public:
|
|||||||
.first;
|
.first;
|
||||||
} catch (const std::runtime_error& e) {
|
} catch (const std::runtime_error& e) {
|
||||||
Log::Error(Event::OpenGL, e.what());
|
Log::Error(Event::OpenGL, e.what());
|
||||||
return;
|
failedInstances.insert(key);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,10 +136,12 @@ public:
|
|||||||
vertexArray.bind(context, indexBuffer, instance.attributeLocations.toBindingArray(attributeBindings));
|
vertexArray.bind(context, indexBuffer, instance.attributeLocations.toBindingArray(attributeBindings));
|
||||||
|
|
||||||
context.draw(drawMode, indexOffset, indexLength);
|
context.draw(drawMode, indexOffset, indexLength);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<uint32_t, std::unique_ptr<Instance>> instances;
|
std::map<uint32_t, std::unique_ptr<Instance>> instances;
|
||||||
|
std::set<uint32_t> failedInstances;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gl
|
} // namespace gl
|
||||||
|
|||||||
Reference in New Issue
Block a user