Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Preserve depth buffer between 3D layers + optimize render order #9931

Merged
merged 14 commits into from
Sep 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/mbgl/renderer/renderer_backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class RendererBackend {
// set to the current state.
virtual void bind() = 0;

virtual Size getFramebufferSize() const = 0;

protected:
// Called with the name of an OpenGL extension that should be loaded. RendererBackend implementations
// must call the API-specific version that obtains the function pointer for this function,
Expand Down
8 changes: 4 additions & 4 deletions platform/android/src/native_map_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ void NativeMapView::bind() {
setViewport(0, 0, getFramebufferSize());
}

mbgl::Size NativeMapView::getFramebufferSize() const {
return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) };
}

/**
* From mbgl::RendererBackend.
*/
Expand Down Expand Up @@ -1428,10 +1432,6 @@ void NativeMapView::_destroySurface() {
}
}

mbgl::Size NativeMapView::getFramebufferSize() const {
return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) };
}

void NativeMapView::updateAssumedState() {
assumeFramebufferBinding(0);
assumeViewport(0, 0, getFramebufferSize());
Expand Down
5 changes: 3 additions & 2 deletions platform/android/src/native_map_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class NativeMapView : public RendererBackend, public MapObserver {
// mbgl::RendererBackend //

void bind() override;

mbgl::Size getFramebufferSize() const override;

void updateAssumedState() override;

// Deprecated //
Expand Down Expand Up @@ -282,8 +285,6 @@ class NativeMapView : public RendererBackend, public MapObserver {

EGLConfig chooseConfig(const EGLConfig configs[], EGLint numConfigs);

mbgl::Size getFramebufferSize() const;

void updateFps();

private:
Expand Down
4 changes: 4 additions & 0 deletions platform/default/mbgl/gl/headless_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ void HeadlessBackend::bind() {
context_.viewport = { 0, 0, size };
}

Size HeadlessBackend::getFramebufferSize() const {
return size;
}

void HeadlessBackend::updateAssumedState() {
// no-op
}
Expand Down
1 change: 1 addition & 0 deletions platform/default/mbgl/gl/headless_backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class HeadlessBackend : public RendererBackend {
~HeadlessBackend() override;

void bind() override;
Size getFramebufferSize() const override;
void updateAssumedState() override;

void setSize(Size);
Expand Down
2 changes: 1 addition & 1 deletion platform/glfw/glfw_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class GLFWView : public mbgl::RendererBackend, public mbgl::MapObserver {
void invalidate();

mbgl::Size getSize() const;
mbgl::Size getFramebufferSize() const;
mbgl::Size getFramebufferSize() const override;

// mbgl::RendererBackend implementation
void bind() override;
Expand Down
4 changes: 4 additions & 0 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -5464,6 +5464,10 @@ void bind() override {
}
}

mbgl::Size getFramebufferSize() const override {
return nativeView.framebufferSize;
}

void onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) override {
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
[nativeView cameraWillChangeAnimated:animated];
Expand Down
4 changes: 4 additions & 0 deletions platform/macos/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2883,6 +2883,10 @@ void bind() override {
setViewport(0, 0, nativeView.framebufferSize);
}

mbgl::Size getFramebufferSize() const override {
return nativeView.framebufferSize;
}

mbgl::PremultipliedImage readStillImage() {
return readFramebuffer(nativeView.framebufferSize);
}
Expand Down
1 change: 0 additions & 1 deletion platform/node/test/ignores.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"render-tests/debug/tile": "https://github.com/mapbox/mapbox-gl-native/issues/3841",
"render-tests/extent/1024-circle": "needs investigation",
"render-tests/extent/1024-symbol": "needs investigation",
"render-tests/fill-extrusion-multiple/multiple": "https://github.com/mapbox/mapbox-gl-native/issues/9894",
"render-tests/fill-extrusion-pattern/@2x": "https://github.com/mapbox/mapbox-gl-js/issues/3327",
"render-tests/fill-extrusion-pattern/function-2": "https://github.com/mapbox/mapbox-gl-js/issues/3327",
"render-tests/fill-extrusion-pattern/function": "https://github.com/mapbox/mapbox-gl-js/issues/3327",
Expand Down
8 changes: 4 additions & 4 deletions platform/qt/src/qmapboxgl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,7 @@ QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settin
static_cast<mbgl::GLContextMode>(settings.contextMode())),
*this);
connect(frontend.get(), SIGNAL(updated()), this, SLOT(invalidate()));

mapObj = std::make_unique<mbgl::Map>(
*frontend,
*this, sanitizedSize(size),
Expand All @@ -1528,18 +1528,18 @@ QMapboxGLPrivate::~QMapboxGLPrivate()
{
}

mbgl::Size QMapboxGLPrivate::framebufferSize() const {
mbgl::Size QMapboxGLPrivate::getFramebufferSize() const {
return sanitizedSize(fbSize);
}

void QMapboxGLPrivate::updateAssumedState() {
assumeFramebufferBinding(fbObject);
assumeViewport(0, 0, framebufferSize());
assumeViewport(0, 0, getFramebufferSize());
}

void QMapboxGLPrivate::bind() {
setFramebufferBinding(fbObject);
setViewport(0, 0, framebufferSize());
setViewport(0, 0, getFramebufferSize());
}

void QMapboxGLPrivate::invalidate()
Expand Down
2 changes: 1 addition & 1 deletion platform/qt/src/qmapboxgl_p.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ class QMapboxGLPrivate : public QObject, public mbgl::RendererBackend, public mb
explicit QMapboxGLPrivate(QMapboxGL *, const QMapboxGLSettings &, const QSize &size, qreal pixelRatio);
virtual ~QMapboxGLPrivate();

mbgl::Size framebufferSize() const;

// mbgl::RendererBackend implementation.
void bind() final;
mbgl::Size getFramebufferSize() const final;
void updateAssumedState() final;
void activate() final {}
void deactivate() final {}
Expand Down
3 changes: 3 additions & 0 deletions src/mbgl/gl/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,9 @@ Framebuffer Context::createFramebuffer(const Texture& color) {
Framebuffer
Context::createFramebuffer(const Texture& color,
const Renderbuffer<RenderbufferType::DepthComponent>& depthTarget) {
if (color.size != depthTarget.size) {
throw std::runtime_error("Renderbuffer size mismatch");
}
auto fbo = createFramebuffer();
bindFramebuffer = fbo;
MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color.texture, 0));
Expand Down
16 changes: 15 additions & 1 deletion src/mbgl/gl/renderbuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,23 @@ namespace gl {
template <RenderbufferType renderbufferType>
class Renderbuffer {
public:
Renderbuffer(Size size_, UniqueRenderbuffer renderbuffer_, bool dirty_ = false)
: size(std::move(size_)), renderbuffer(std::move(renderbuffer_)), dirty(dirty_) {
}

using type = std::integral_constant<RenderbufferType, renderbufferType>;
Size size;
gl::UniqueRenderbuffer renderbuffer;
UniqueRenderbuffer renderbuffer;

void shouldClear(bool clear) {
dirty = clear;
}
bool needsClearing() {
return dirty;
}

private:
bool dirty;
};

} // namespace gl
Expand Down
194 changes: 91 additions & 103 deletions src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ void RenderFillExtrusionLayer::transition(const TransitionParameters& parameters
void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& parameters) {
evaluated = unevaluated.evaluate(parameters);

passes = (evaluated.get<style::FillExtrusionOpacity>() > 0) ? RenderPass::Translucent
: RenderPass::None;
passes = (evaluated.get<style::FillExtrusionOpacity>() > 0)
? (RenderPass::Translucent | RenderPass::Pass3D)
: RenderPass::None;
}

bool RenderFillExtrusionLayer::hasTransition() const {
Expand All @@ -50,113 +51,100 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters, RenderSource*
return;
}

const auto size = parameters.context.viewport.getCurrentValue().size;
if (parameters.pass == RenderPass::Pass3D) {
const auto& size = parameters.staticData.backendSize;

if (!parameters.staticData.extrusionTexture || parameters.staticData.extrusionTexture->getSize() != size) {
parameters.staticData.extrusionTexture = OffscreenTexture(parameters.context, size, OffscreenTextureAttachment::Depth);
}

parameters.staticData.extrusionTexture->bind();

parameters.context.setStencilMode(gl::StencilMode::disabled());
parameters.context.setDepthMode(parameters.depthModeForSublayer(0, gl::DepthMode::ReadWrite));
parameters.context.clear(Color{ 0.0f, 0.0f, 0.0f, 0.0f }, 1.0f, {});

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.depthModeForSublayer(0, gl::DepthMode::ReadWrite),
gl::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
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());
if (!renderTexture || renderTexture->getSize() != size) {
renderTexture = OffscreenTexture(parameters.context, size, *parameters.staticData.depthRenderbuffer);
}
} else {
optional<ImagePosition> imagePosA = parameters.imageManager.getPattern(evaluated.get<FillExtrusionPattern>().from);
optional<ImagePosition> imagePosB = parameters.imageManager.getPattern(evaluated.get<FillExtrusionPattern>().to);

if (!imagePosA || !imagePosB) {
return;
renderTexture->bind();

optional<float> depthClearValue = {};
if (parameters.staticData.depthRenderbuffer->needsClearing()) depthClearValue = 1.0;
// Flag the depth buffer as no longer needing to be cleared for the remainder of this pass.
parameters.staticData.depthRenderbuffer->shouldClear(false);

parameters.context.setStencilMode(gl::StencilMode::disabled());
parameters.context.clear(Color{ 0.0f, 0.0f, 0.0f, 0.0f }, depthClearValue, {});

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(),
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());
}
} else {
optional<ImagePosition> imagePosA =
parameters.imageManager.getPattern(evaluated.get<FillExtrusionPattern>().from);
optional<ImagePosition> imagePosB =
parameters.imageManager.getPattern(evaluated.get<FillExtrusionPattern>().to);

if (!imagePosA || !imagePosB) {
return;
}

parameters.imageManager.bind(parameters.context, 0);

for (const RenderTile& tile : renderTiles) {
assert(dynamic_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl)));
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(),
FillExtrusionPatternUniforms::values(
tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(),
evaluated.get<FillExtrusionTranslateAnchor>(),
parameters.state),
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.imageManager.bind(parameters.context, 0);

for (const RenderTile& tile : renderTiles) {
assert(dynamic_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl)));
FillExtrusionBucket& bucket = *reinterpret_cast<FillExtrusionBucket*>(tile.tile.getBucket(*baseImpl));

parameters.programs.fillExtrusionPattern.get(evaluated).draw(
parameters.context,
gl::Triangles(),
parameters.depthModeForSublayer(0, gl::DepthMode::ReadWrite),
gl::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
FillExtrusionPatternUniforms::values(
tile.translatedClipMatrix(evaluated.get<FillExtrusionTranslate>(),
evaluated.get<FillExtrusionTranslateAnchor>(),
parameters.state),
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());
}
}
} else if (parameters.pass == RenderPass::Translucent) {
parameters.context.bindTexture(renderTexture->getTexture());

parameters.backend.bind();
parameters.context.bindTexture(parameters.staticData.extrusionTexture->getTexture());

mat4 viewportMat;
matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1);

const Properties<>::PossiblyEvaluated properties;

parameters.programs.extrusionTexture.draw(
parameters.context,
gl::Triangles(),
gl::DepthMode::disabled(),
gl::StencilMode::disabled(),
parameters.colorModeForRenderPass(),
ExtrusionTextureProgram::UniformValues{
uniforms::u_matrix::Value{ viewportMat }, uniforms::u_world::Value{ size },
uniforms::u_image::Value{ 0 },
uniforms::u_opacity::Value{ evaluated.get<FillExtrusionOpacity>() }
},
parameters.staticData.extrusionTextureVertexBuffer,
parameters.staticData.quadTriangleIndexBuffer,
parameters.staticData.extrusionTextureSegments,
ExtrusionTextureProgram::PaintPropertyBinders{ properties, 0 },
properties,
parameters.state.getZoom(),
getID());
const auto& size = parameters.staticData.backendSize;

mat4 viewportMat;
matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1);

const Properties<>::PossiblyEvaluated properties;

parameters.programs.extrusionTexture.draw(
parameters.context, gl::Triangles(), gl::DepthMode::disabled(),
gl::StencilMode::disabled(), parameters.colorModeForRenderPass(),
ExtrusionTextureProgram::UniformValues{
uniforms::u_matrix::Value{ viewportMat }, uniforms::u_world::Value{ size },
uniforms::u_image::Value{ 0 },
uniforms::u_opacity::Value{ evaluated.get<FillExtrusionOpacity>() } },
parameters.staticData.extrusionTextureVertexBuffer,
parameters.staticData.quadTriangleIndexBuffer,
parameters.staticData.extrusionTextureSegments,
ExtrusionTextureProgram::PaintPropertyBinders{ properties, 0 }, properties,
parameters.state.getZoom(), getID());
}
}

bool RenderFillExtrusionLayer::queryIntersectsFeature(
Expand Down
Loading