Metal layer depth range support (#2013)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Alex Cristici <alex.cristici@gmail.com>
This commit is contained in:
mwilsnd
2024-01-16 09:31:44 -05:00
committed by GitHub
parent 29c16a4a81
commit d6c2b148dd
28 changed files with 109 additions and 31 deletions

View File

@@ -152,6 +152,9 @@ public:
/// Set sub-layer index
virtual void setSubLayerIndex(int32_t value) { subLayerIndex = value; }
void setLayerIndex(int32_t value) { layerIndex = value; }
int32_t getLayerIndex() const { return layerIndex; }
/// Depth writability for 2D drawables
DepthMaskType getDepthType() const { return depthType; }
@@ -252,6 +255,7 @@ protected:
DrawPriority drawPriority = 0;
int32_t lineWidth = 1;
int32_t subLayerIndex = 0;
int32_t layerIndex = 0;
DepthMaskType depthType; // = DepthMaskType::ReadOnly;
UniqueDrawableData drawableData{};
gfx::VertexAttributeArrayPtr vertexAttributes;

View File

@@ -72,7 +72,7 @@ public:
int32_t getLayerIndex() const { return layerIndex; }
/// Update the layer index to a new value
void updateLayerIndex(int32_t value) { layerIndex = value; }
virtual void updateLayerIndex(int32_t value) { layerIndex = value; }
/// Get the number of drawables contained
virtual std::size_t getDrawableCount() const = 0;
@@ -163,6 +163,13 @@ public:
void setStencilTiles(RenderTiles);
void updateLayerIndex(int32_t value) override {
layerIndex = value;
for (auto* drawable : sortedDrawables) {
drawable->setLayerIndex(value);
}
}
protected:
// When stencil clipping is enabled for the layer, this is the set
// of tile IDs that need to be rendered to the stencil buffer.
@@ -232,6 +239,13 @@ public:
std::size_t clearDrawables() override;
void updateLayerIndex(int32_t value) override {
layerIndex = value;
for (auto& drawable : drawables) {
drawable->setLayerIndex(value);
}
}
protected:
using DrawableCollection = std::set<gfx::UniqueDrawable, gfx::DrawableLessByPriority>;
DrawableCollection drawables;

View File

@@ -57,6 +57,7 @@ public:
style::TranslateAnchorType,
bool nearClipped,
bool inViewportPixelUnits,
const gfx::Drawable& drawable,
bool aligned = false);
protected:

View File

@@ -10,9 +10,15 @@ class DepthMode {
public:
DepthFunctionType func;
DepthMaskType mask;
#if MLN_RENDER_BACKEND_OPENGL
Range<float> range;
#endif
#if MLN_RENDER_BACKEND_OPENGL
static DepthMode disabled() { return DepthMode{DepthFunctionType::Always, DepthMaskType::ReadOnly, {0.0, 1.0}}; }
#else
static DepthMode disabled() { return DepthMode{DepthFunctionType::Always, DepthMaskType::ReadOnly}; }
#endif
};
} // namespace gfx

View File

@@ -490,7 +490,9 @@ void Context::setDirtyState() {
stencilMask.setDirty();
stencilTest.setDirty();
stencilOp.setDirty();
#if MLN_RENDER_BACKEND_OPENGL
depthRange.setDirty();
#endif
depthMask.setDirty();
depthTest.setDirty();
depthFunc.setDirty();
@@ -615,12 +617,16 @@ void Context::setDepthMode(const gfx::DepthMode& depth) {
// https://github.com/mapbox/mapbox-gl-native/issues/9164
depthFunc = depth.func;
depthMask = depth.mask;
#if MLN_RENDER_BACKEND_OPENGL
depthRange = depth.range;
#endif
} else {
depthTest = true;
depthFunc = depth.func;
depthMask = depth.mask;
#if MLN_RENDER_BACKEND_OPENGL
depthRange = depth.range;
#endif
}
}

View File

@@ -169,7 +169,9 @@ private:
State<value::StencilMask> stencilMask;
State<value::StencilTest> stencilTest;
State<value::StencilOp> stencilOp;
#if MLN_RENDER_BACKEND_OPENGL
State<value::DepthRange> depthRange;
#endif
State<value::DepthMask> depthMask;
State<value::DepthTest> depthTest;
State<value::DepthFunc> depthFunc;

View File

@@ -133,6 +133,7 @@ StencilOp::Type StencilOp::Get() {
Enum<gfx::StencilOpType>::from(dppass)};
}
#if MLN_RENDER_BACKEND_OPENGL
const constexpr DepthRange::Type DepthRange::Default;
void DepthRange::Set(const Type& value) {
@@ -144,6 +145,7 @@ DepthRange::Type DepthRange::Get() {
MBGL_CHECK_ERROR(glGetFloatv(GL_DEPTH_RANGE, floats));
return {floats[0], floats[1]};
}
#endif
const constexpr DepthTest::Type DepthTest::Default;

View File

@@ -98,12 +98,14 @@ constexpr bool operator!=(const StencilOp::Type& a, const StencilOp::Type& b) {
return a.sfail != b.sfail || a.dpfail != b.dpfail || a.dppass != b.dppass;
}
#if MLN_RENDER_BACKEND_OPENGL
struct DepthRange {
using Type = Range<float>;
static const constexpr Type Default = {0, 1};
static void Set(const Type&);
static Type Get();
};
#endif
struct DepthTest {
using Type = bool;

View File

@@ -269,11 +269,8 @@ const auto clipMaskStencilMode = gfx::StencilMode{
/*.depthFail=*/gfx::StencilOpType::Keep,
/*.pass=*/gfx::StencilOpType::Replace,
};
const auto clipMaskDepthMode = gfx::DepthMode{
/*.func=*/gfx::DepthFunctionType::Always,
/*.mask=*/gfx::DepthMaskType::ReadOnly,
/*.range=*/{0, 1},
};
const auto clipMaskDepthMode = gfx::DepthMode{/*.func=*/gfx::DepthFunctionType::Always,
/*.mask=*/gfx::DepthMaskType::ReadOnly};
} // namespace
bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass,

View File

@@ -10,6 +10,7 @@
namespace mbgl {
void LayerGroupBase::addDrawable(gfx::UniqueDrawable& drawable) {
drawable->setLayerIndex(layerIndex);
// init their tweakers
for (const auto& tweaker : drawable->getTweakers()) {
tweaker->init(*drawable);

View File

@@ -32,15 +32,26 @@ mat4 LayerTweaker::getTileMatrix(const UnwrappedTileID& tileID,
style::TranslateAnchorType anchor,
bool nearClipped,
bool inViewportPixelUnits,
[[maybe_unused]] const gfx::Drawable& drawable,
bool aligned) {
// from RenderTile::prepare
mat4 tileMatrix;
parameters.state.matrixFor(/*out*/ tileMatrix, tileID);
// nearClippedMatrix has near plane moved further, to enhance depth buffer precision
const auto& projMatrix = aligned ? parameters.transformParams.alignedProjMatrix
: (nearClipped ? parameters.transformParams.nearClippedProjMatrix
: parameters.transformParams.projMatrix);
auto projMatrix = aligned ? parameters.transformParams.alignedProjMatrix
: (nearClipped ? parameters.transformParams.nearClippedProjMatrix
: parameters.transformParams.projMatrix);
#if !MLN_RENDER_BACKEND_OPENGL
// Offset the projection matrix NDC depth range for the drawable's layer and sublayer.
if (!drawable.getIs3D()) {
projMatrix[14] -= ((1 + drawable.getLayerIndex()) * PaintParameters::numSublayers -
drawable.getSubLayerIndex()) *
PaintParameters::depthEpsilon;
}
#endif
matrix::multiply(tileMatrix, projMatrix, tileMatrix);
return RenderTile::translateVtxMatrix(

View File

@@ -64,7 +64,8 @@ void BackgroundLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintPara
(shader == context.getGenericShader(parameters.shaders, std::string(BackgroundPatternShaderName))));
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
const auto matrix = parameters.matrixForTile(tileID);
const auto matrix = getTileMatrix(
tileID, parameters, {0.f, 0.f}, TranslateAnchorType::Viewport, false, false, drawable);
const BackgroundDrawableUBO drawableUBO = {/* .matrix = */ util::cast<float>(matrix)};

View File

@@ -87,7 +87,8 @@ void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParamete
const auto anchor = evaluated.get<CircleTranslateAnchor>();
constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix
constexpr bool nearClipped = false;
const auto matrix = getTileMatrix(tileID, parameters, translation, anchor, nearClipped, inViewportPixelUnits);
const auto matrix = getTileMatrix(
tileID, parameters, translation, anchor, nearClipped, inViewportPixelUnits, drawable);
const auto pixelsToTileUnits = tileID.pixelsToTileUnits(1.0f, static_cast<float>(zoom));
const auto extrudeScale = pitchWithMap ? std::array<float, 2>{pixelsToTileUnits, pixelsToTileUnits}

View File

@@ -49,7 +49,8 @@ void CollisionLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParam
const auto anchor = data.translateAnchor;
constexpr bool nearClipped = false;
constexpr bool inViewportPixelUnits = false;
const auto matrix = getTileMatrix(tileID, parameters, translate, anchor, nearClipped, inViewportPixelUnits);
const auto matrix = getTileMatrix(
tileID, parameters, translate, anchor, nearClipped, inViewportPixelUnits, drawable);
// extrude scale
const auto pixelRatio = tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom()));

View File

@@ -90,7 +90,8 @@ void FillExtrusionLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintP
const auto anchor = evaluated.get<FillExtrusionTranslateAnchor>();
constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix
constexpr bool nearClipped = true;
const auto matrix = getTileMatrix(tileID, parameters, translation, anchor, nearClipped, inViewportPixelUnits);
const auto matrix = getTileMatrix(
tileID, parameters, translation, anchor, nearClipped, inViewportPixelUnits, drawable);
const auto tileRatio = 1 / tileID.pixelsToTileUnits(1, state.getIntegerZoom());
const auto zoomScale = state.zoomScale(tileID.canonical.z);

View File

@@ -153,7 +153,9 @@ void FillLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParameters
constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix
constexpr bool nearClipped = false;
const auto matrix = getTileMatrix(tileID, parameters, translation, anchor, nearClipped, inViewportPixelUnits);
const auto matrix = getTileMatrix(
tileID, parameters, translation, anchor, nearClipped, inViewportPixelUnits, drawable);
// from FillPatternProgram::layoutUniformValues
const auto tileRatio = 1.0f / tileID.pixelsToTileUnits(1.0f, intZoom);

View File

@@ -61,7 +61,7 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParamet
constexpr bool nearClipped = false;
constexpr bool inViewportPixelUnits = false;
const auto matrix = getTileMatrix(
tileID, parameters, {0.f, 0.f}, TranslateAnchorType::Viewport, nearClipped, inViewportPixelUnits);
tileID, parameters, {0.f, 0.f}, TranslateAnchorType::Viewport, nearClipped, inViewportPixelUnits, drawable);
const HeatmapDrawableUBO drawableUBO = {
/* .matrix = */ util::cast<float>(matrix),
/* .extrude_scale = */ tileID.pixelsToTileUnits(1.0f, static_cast<float>(zoom)),

View File

@@ -62,7 +62,7 @@ void HillshadeLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParam
drawable.mutableUniformBuffers().addOrReplace(idHillshadeEvaluatedPropsUBOName, evaluatedPropsUniformBuffer);
const auto matrix = getTileMatrix(
tileID, parameters, {0.f, 0.f}, TranslateAnchorType::Viewport, false, false, true);
tileID, parameters, {0.f, 0.f}, TranslateAnchorType::Viewport, false, false, drawable, true);
HillshadeDrawableUBO drawableUBO = {/* .matrix = */ util::cast<float>(matrix),
/* .latrange = */ getLatRange(tileID),
/* .light = */ getLight(parameters, evaluated)};

View File

@@ -130,7 +130,8 @@ void LineLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParameters
constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix
auto& uniforms = drawable.mutableUniformBuffers();
const auto matrix = getTileMatrix(tileID, parameters, translation, anchor, nearClipped, inViewportPixelUnits);
const auto matrix = getTileMatrix(
tileID, parameters, translation, anchor, nearClipped, inViewportPixelUnits, drawable);
uniforms.addOrReplace(idLineDynamicUBOName, dynamicBuffer);

View File

@@ -65,7 +65,14 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup,
} else {
// this is a tile drawable
const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped();
matrix = parameters.matrixForTile(tileID, !parameters.state.isChanging());
matrix = getTileMatrix(tileID,
parameters,
{0.f, 0.f},
TranslateAnchorType::Viewport,
false,
false,
drawable,
!parameters.state.isChanging());
}
const RasterDrawableUBO drawableUBO{

View File

@@ -368,7 +368,7 @@ public:
static const StringIdentity idLineUBOName = stringIndexer().get("LineBasicUBO");
{
const auto matrix = LayerTweaker::getTileMatrix(
tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, false);
tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, drawable, false);
const shaders::LineBasicUBO lineUBO{
/*matrix = */ util::cast<float>(matrix),

View File

@@ -128,7 +128,8 @@ void SymbolLayerTweaker::execute(LayerGroupBase& layerGroup, const PaintParamete
: evaluated.get<style::IconTranslateAnchor>();
constexpr bool nearClipped = false;
constexpr bool inViewportPixelUnits = false;
const auto matrix = getTileMatrix(tileID, parameters, translate, anchor, nearClipped, inViewportPixelUnits);
const auto matrix = getTileMatrix(
tileID, parameters, translate, anchor, nearClipped, inViewportPixelUnits, drawable);
// from symbol_program, makeValues
const auto currentZoom = static_cast<float>(parameters.state.getZoom());

View File

@@ -82,16 +82,25 @@ mat4 PaintParameters::matrixForTile(const UnwrappedTileID& tileID, bool aligned)
return matrix;
}
gfx::DepthMode PaintParameters::depthModeForSublayer(uint8_t n, gfx::DepthMaskType mask) const {
gfx::DepthMode PaintParameters::depthModeForSublayer([[maybe_unused]] uint8_t n, gfx::DepthMaskType mask) const {
if (currentLayer < opaquePassCutoff) {
return gfx::DepthMode::disabled();
}
#if MLN_RENDER_BACKEND_OPENGL
float depth = depthRangeSize + ((1 + currentLayer) * numSublayers + n) * depthEpsilon;
return gfx::DepthMode{gfx::DepthFunctionType::LessEqual, mask, {depth, depth}};
#else
return gfx::DepthMode{gfx::DepthFunctionType::LessEqual, mask};
#endif
}
gfx::DepthMode PaintParameters::depthModeFor3D() const {
#if MLN_RENDER_BACKEND_OPENGL
return gfx::DepthMode{gfx::DepthFunctionType::LessEqual, gfx::DepthMaskType::ReadWrite, {0.0, depthRangeSize}};
#else
return gfx::DepthMode{gfx::DepthFunctionType::LessEqual, gfx::DepthMaskType::ReadWrite};
#endif
}
namespace {

View File

@@ -121,14 +121,18 @@ private:
int32_t nextStencilID = 1;
public:
const int numSublayers = 3;
uint32_t currentLayer;
float depthRangeSize;
uint32_t opaquePassCutoff = 0;
float symbolFadeChange;
const uint64_t frameCount;
static constexpr int numSublayers = 3;
#if MLN_RENDER_BACKEND_OPENGL
static constexpr float depthEpsilon = 1.0f / (1 << 16);
#else
static constexpr float depthEpsilon = 1.0f / (1 << 12);
#endif
static constexpr int maxStencilValue = 255;
};

View File

@@ -74,7 +74,8 @@ void RenderTarget::render(RenderOrchestrator& orchestrator, const RenderTree& re
// draw layer groups, opaque pass
parameters.pass = RenderPass::Opaque;
parameters.currentLayer = 0;
parameters.depthRangeSize = 1 - (numLayerGroups() + 2) * parameters.numSublayers * PaintParameters::depthEpsilon;
parameters.depthRangeSize = 1 -
(numLayerGroups() + 2) * PaintParameters::numSublayers * PaintParameters::depthEpsilon;
visitLayerGroups([&](LayerGroupBase& layerGroup) {
layerGroup.render(orchestrator, parameters);
@@ -84,7 +85,8 @@ void RenderTarget::render(RenderOrchestrator& orchestrator, const RenderTree& re
// draw layer groups, translucent pass
parameters.pass = RenderPass::Translucent;
parameters.currentLayer = static_cast<int32_t>(numLayerGroups()) - 1;
parameters.depthRangeSize = 1 - (numLayerGroups() + 2) * parameters.numSublayers * PaintParameters::depthEpsilon;
parameters.depthRangeSize = 1 -
(numLayerGroups() + 2) * PaintParameters::numSublayers * PaintParameters::depthEpsilon;
visitLayerGroups([&](LayerGroupBase& layerGroup) {
layerGroup.render(orchestrator, parameters);

View File

@@ -330,7 +330,8 @@ void Renderer::Impl::render(const RenderTree& renderTree,
const auto maxLayerIndex = orchestrator.maxLayerIndex();
parameters.pass = RenderPass::Opaque;
parameters.currentLayer = 0;
parameters.depthRangeSize = 1 - (maxLayerIndex + 3) * parameters.numSublayers * PaintParameters::depthEpsilon;
parameters.depthRangeSize = 1 -
(maxLayerIndex + 3) * PaintParameters::numSublayers * PaintParameters::depthEpsilon;
// draw layer groups, opaque pass
orchestrator.visitLayerGroups([&](LayerGroupBase& layerGroup) {
@@ -343,7 +344,8 @@ void Renderer::Impl::render(const RenderTree& renderTree,
const auto debugGroup(parameters.renderPass->createDebugGroup("drawables-translucent"));
const auto maxLayerIndex = orchestrator.maxLayerIndex();
parameters.pass = RenderPass::Translucent;
parameters.depthRangeSize = 1 - (maxLayerIndex + 3) * parameters.numSublayers * PaintParameters::depthEpsilon;
parameters.depthRangeSize = 1 -
(maxLayerIndex + 3) * PaintParameters::numSublayers * PaintParameters::depthEpsilon;
// draw layer groups, translucent pass
orchestrator.visitLayerGroups([&](LayerGroupBase& layerGroup) {
@@ -358,7 +360,7 @@ void Renderer::Impl::render(const RenderTree& renderTree,
const auto renderLayerOpaquePass = [&] {
const auto debugGroup(parameters.renderPass->createDebugGroup("opaque"));
parameters.pass = RenderPass::Opaque;
parameters.depthRangeSize = 1 - (layerRenderItems.size() + 2) * parameters.numSublayers *
parameters.depthRangeSize = 1 - (layerRenderItems.size() + 2) * PaintParameters::numSublayers *
PaintParameters::depthEpsilon;
uint32_t i = 0;
@@ -376,7 +378,7 @@ void Renderer::Impl::render(const RenderTree& renderTree,
const auto renderLayerTranslucentPass = [&] {
const auto debugGroup(parameters.renderPass->createDebugGroup("translucent"));
parameters.pass = RenderPass::Translucent;
parameters.depthRangeSize = 1 - (layerRenderItems.size() + 2) * parameters.numSublayers *
parameters.depthRangeSize = 1 - (layerRenderItems.size() + 2) * PaintParameters::numSublayers *
PaintParameters::depthEpsilon;
int32_t i = static_cast<int32_t>(layerRenderItems.size()) - 1;

View File

@@ -208,7 +208,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr
parameters.state.matrixFor(/*out*/ tileMatrix, tileID);
const auto matrix = LayerTweaker::getTileMatrix(
tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, false);
tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, drawable, false);
static const StringIdentity idLineDynamicUBOName = stringIndexer().get("LineDynamicUBO");
const shaders::LineDynamicUBO dynamicUBO = {

View File

@@ -95,7 +95,7 @@ public:
parameters.state.matrixFor(/*out*/ tileMatrix, tileID);
const auto matrix = LayerTweaker::getTileMatrix(
tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, false);
tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, drawable, false);
static const StringIdentity idLineDynamicUBOName = stringIndexer().get("LineDynamicUBO");
const shaders::LineDynamicUBO dynamicUBO = {
@@ -149,7 +149,7 @@ public:
parameters.state.matrixFor(/*out*/ tileMatrix, tileID);
const auto matrix = LayerTweaker::getTileMatrix(
tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, false);
tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, drawable, false);
static const StringIdentity idFillDrawableUBOName = stringIndexer().get("FillDrawableUBO");
const shaders::FillDrawableUBO fillUBO{/*matrix = */ util::cast<float>(matrix)};