Drawable Renderer (#1570), Add fill-outline drawables

This commit is contained in:
Tim Sylvester
2023-05-22 12:23:29 -07:00
committed by Bart Louwers
parent c505d3077e
commit c81c665538
9 changed files with 151 additions and 106 deletions

View File

@@ -66,6 +66,10 @@ public:
return (mbgl::underlying_type(renderPass) & underlying_value) == underlying_value;
}
/// Width for lines
int32_t getLineWidth() const { return lineWidth; }
void setLineWidth(int32_t value) { lineWidth = value; }
/// not used for anything yet
DrawPriority getDrawPriority() const { return drawPriority; }
void setDrawPriority(DrawPriority value) { drawPriority = value; }
@@ -74,6 +78,10 @@ public:
int32_t getLayerIndex() const { return layerIndex; }
void setLayerIndex(int32_t value) { layerIndex = value; }
/// Determines depth range within the layer
int32_t getSubLayerIndex() const { return subLayerIndex; }
void setSubLayerIndex(int32_t value) { subLayerIndex = value; }
std::optional<OverscaledTileID> getTileID() const { return tileID; }
void setTileID(OverscaledTileID value) { tileID = value; }
@@ -129,7 +137,9 @@ protected:
mat4 matrix; //= matrix::identity4();
std::optional<OverscaledTileID> tileID;
DrawPriority drawPriority = 0;
int32_t lineWidth = 1;
int32_t layerIndex = -1;
int32_t subLayerIndex = 0;
DepthMaskType depthType; // = DepthMaskType::ReadOnly;
std::vector<DrawableTweakerPtr> tweakers;

View File

@@ -61,6 +61,10 @@ public:
int32_t getLayerIndex() const { return layerIndex; }
void setLayerIndex(int32_t value) { layerIndex = value; }
/// The layer index assigned to generated drawables
int32_t getSubLayerIndex() const { return subLayerIndex; }
void setSubLayerIndex(int32_t value) { subLayerIndex = value; }
/// Set the draw priority on all drawables including those already generated
void resetDrawPriority(DrawPriority);
@@ -77,6 +81,10 @@ public:
/// This should not be changed while a build is in progress
void setColorMode(ColorMode mode) { colorMode = mode; }
/// Width for lines
int32_t getLineWidth() const { return lineWidth; }
void setLineWidth(int32_t value) { lineWidth = value; }
DepthMaskType getDepthType() const { return depthType; }
void setDepthType(DepthMaskType value) { depthType = value; }
@@ -150,8 +158,10 @@ protected:
std::string vertexAttrName;
std::string colorAttrName;
mbgl::RenderPass renderPass;
int32_t lineWidth = 1;
DrawPriority drawPriority = 0;
int32_t layerIndex = -1;
int32_t subLayerIndex = 0;
DepthMaskType depthType = DepthMaskType::ReadOnly;
gfx::ShaderProgramBasePtr shader;
mat4 matrix;

View File

@@ -69,8 +69,8 @@ public:
std::size_t getDrawableCount() const;
const gfx::UniqueDrawable& getDrawable(mbgl::RenderPass, const OverscaledTileID&) const;
gfx::UniqueDrawable removeDrawable(mbgl::RenderPass, const OverscaledTileID&);
bool addDrawable(mbgl::RenderPass, const OverscaledTileID&, gfx::UniqueDrawable&&);
std::vector<gfx::UniqueDrawable> removeDrawables(mbgl::RenderPass, const OverscaledTileID&);
void addDrawable(mbgl::RenderPass, const OverscaledTileID&, gfx::UniqueDrawable&&);
void observeDrawables(std::function<void(gfx::Drawable&)>) override;
void observeDrawables(std::function<void(const gfx::Drawable&)>) const override;

View File

@@ -33,9 +33,11 @@ const UniqueDrawable& DrawableBuilder::getCurrentDrawable(bool createIfNone) {
void DrawableBuilder::flush() {
if (!impl->vertices.empty()) {
const auto& draw = getCurrentDrawable(/*createIfNone=*/true);
draw->setLineWidth(lineWidth);
draw->setRenderPass(renderPass);
draw->setDrawPriority(drawPriority);
draw->setLayerIndex(layerIndex);
draw->setSubLayerIndex(subLayerIndex);
draw->setDepthType(depthType);
draw->setShader(shader);
draw->setMatrix(matrix);

View File

@@ -19,7 +19,7 @@ DrawableGL::~DrawableGL() {
void DrawableGL::draw(const PaintParameters& parameters) const {
bindUniformBuffers();
impl->draw(parameters);
impl->draw(parameters, lineWidth);
unbindUniformBuffers();
}

View File

@@ -27,13 +27,13 @@ public:
Impl() = default;
~Impl() = default;
void draw(const PaintParameters& parameters) const {
void draw(const PaintParameters& parameters, int32_t lineWidth) const {
auto& glContext = static_cast<gl::Context&>(parameters.context);
if (!triangleIndexes.empty()) {
glContext.draw(gfx::Triangles(), lineIndexes.size(), triangleIndexes.size());
}
if (!lineIndexes.empty()) {
glContext.draw(gfx::Lines(1), 0, lineIndexes.size());
glContext.draw(gfx::Lines(lineWidth), 0, lineIndexes.size());
}
}

View File

@@ -25,7 +25,7 @@ struct TileLayerGroup::Impl {
Impl(std::size_t capacity)
: tileDrawables(capacity) {}
using TileMap = std::unordered_map<TileLayerGroupTileKey, gfx::UniqueDrawable, TileLayerGroupTileKey::hash>;
using TileMap = std::unordered_multimap<TileLayerGroupTileKey, gfx::UniqueDrawable, TileLayerGroupTileKey::hash>;
TileMap tileDrawables;
};
@@ -49,27 +49,17 @@ const gfx::UniqueDrawable& TileLayerGroup::getDrawable(mbgl::RenderPass pass, co
return (hit == impl->tileDrawables.end()) ? no_tile : hit->second;
}
gfx::UniqueDrawable TileLayerGroup::removeDrawable(mbgl::RenderPass pass, const OverscaledTileID& id) {
const auto hit = impl->tileDrawables.find({pass, id});
if (hit == impl->tileDrawables.end()) {
return {};
}
auto drawable = std::move(hit->second);
impl->tileDrawables.erase(hit);
return drawable;
std::vector<gfx::UniqueDrawable> TileLayerGroup::removeDrawables(mbgl::RenderPass pass, const OverscaledTileID& id) {
const auto range = impl->tileDrawables.equal_range({pass, id});
std::vector<gfx::UniqueDrawable> result(std::distance(range.first, range.second));
std::transform(std::make_move_iterator(range.first), std::make_move_iterator(range.second),
result.begin(), [](auto&& pair) { return std::move(pair.second); });
impl->tileDrawables.erase(range.first, range.second);
return result;
}
bool TileLayerGroup::addDrawable(mbgl::RenderPass pass, const OverscaledTileID& id, gfx::UniqueDrawable&& drawable) {
const auto result = impl->tileDrawables.insert(
std::make_pair(TileLayerGroupTileKey{pass, id}, gfx::UniqueDrawable()));
if (result.second) {
// New item inserted, move the drawable into it
result.first->second = std::move(drawable);
return true;
} else {
// Not inserted
return false;
}
void TileLayerGroup::addDrawable(mbgl::RenderPass pass, const OverscaledTileID& id, gfx::UniqueDrawable&& drawable) {
impl->tileDrawables.insert(std::make_pair(TileLayerGroupTileKey{pass, id}, std::move(drawable)));
}
void TileLayerGroup::observeDrawables(std::function<void(gfx::Drawable&)> f) {

View File

@@ -298,7 +298,7 @@ void RenderBackgroundLayer::update(const int32_t layerIndex,
if (!(renderPass & drawPasses)) {
// Not in this pass
if (tileDrawable) {
tileLayerGroup->removeDrawable(renderPass, tileID);
tileLayerGroup->removeDrawables(renderPass, tileID);
++stats.tileDrawablesRemoved;
}
continue;

View File

@@ -315,9 +315,11 @@ void RenderFillLayer::update(const int32_t layerIndex,
std::inserter(newTileIDs, newTileIDs.begin()),
[](const auto& renderTile) -> OverscaledTileID { return renderTile.get().getOverscaledTileID(); });
std::unique_ptr<gfx::DrawableBuilder> builder;
std::unique_ptr<gfx::DrawableBuilder> fillBuilder;
std::unique_ptr<gfx::DrawableBuilder> outlineBuilder;
std::vector<gfx::DrawablePtr> newTiles;
gfx::VertexAttributeArray vertexAttrs;
gfx::VertexAttributeArray fillVertexAttrs;
gfx::VertexAttributeArray outlineVertexAttrs;
for (const auto renderPass : {RenderPass::Opaque, RenderPass::Translucent}) {
if (!(mbgl::underlying_type(renderPass) & evaluatedProperties->renderPasses)) {
@@ -343,7 +345,8 @@ void RenderFillLayer::update(const int32_t layerIndex,
const auto removeTile = [&]() {
if (tileDrawable) {
tileLayerGroup->removeDrawable(renderPass, tileID);
// Remove and discard all drawables for the tile
tileLayerGroup->removeDrawables(renderPass, tileID);
++stats.tileDrawablesRemoved;
}
};
@@ -359,44 +362,63 @@ void RenderFillLayer::update(const int32_t layerIndex,
const auto evalColor = evaluated.get<FillColor>().constantOr(Color());
const auto fillOpacity = evaluated.get<FillOpacity>().constantOr(0);
const auto fillColor = evalColor * (fillOpacity > 0.0f ? fillOpacity : 1.0f);
const auto fillAA = evaluated.get<FillAntialias>();
const auto fillRenderPass = (fillColor.a >= 1.0f
/* && parameters.currentLayer >= parameters.opaquePassCutoff*/)
? RenderPass::Opaque
: RenderPass::Translucent;
const auto doFill = fillRenderPass == renderPass;
const auto doOutline = evaluated.get<FillAntialias>() && renderPass == RenderPass::Translucent;
if (fillRenderPass != renderPass) {
if (!doFill && !doOutline) {
removeTile();
continue;
}
vertexAttrs.clear();
fillVertexAttrs.clear();
outlineVertexAttrs.clear();
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
if (auto& p1 = paintPropertyBinders.get<FillColor>()) {
const auto count = p1->getVertexCount();
// check that vertexVector.elements() == sum(segments.vertexLength)
if (auto& attr = vertexAttrs.getOrAdd("a_color")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& packed =
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 2>>*>(
p1->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float4>(i, {packed[0], packed[1], packed[0], packed[1]});
if (doFill) {
if (auto& binder = paintPropertyBinders.get<FillColor>()) {
const auto count = binder->getVertexCount();
// check that vertexVector.elements() == sum(segments.vertexLength)
if (auto& attr = fillVertexAttrs.getOrAdd("a_color")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& packed =
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 2>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float4>(i, {packed[0], packed[1], packed[0], packed[1]});
}
}
}
}
if (auto& p1 = paintPropertyBinders.get<FillOpacity>()) {
const auto count = p1->getVertexCount();
if (auto& attr = vertexAttrs.getOrAdd("a_opacity")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& opacity =
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
p1->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float2>(i, {opacity[0], opacity[0]});
if (doOutline) {
if (auto& binder = paintPropertyBinders.get<FillOutlineColor>()) {
const auto count = binder->getVertexCount();
if (auto& attr = outlineVertexAttrs.getOrAdd("a_outline_color")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& packed =
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 2>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float4>(i, {packed[0], packed[1], packed[0], packed[1]});
}
}
}
}
if (auto& binder = paintPropertyBinders.get<FillOpacity>()) {
const auto count = binder->getVertexCount();
for (auto& attrs : {std::reference_wrapper(fillVertexAttrs), std::reference_wrapper(outlineVertexAttrs)}) {
if (auto& attr = attrs.get().getOrAdd("a_opacity")) {
for (std::size_t i = 0; i < count; ++i) {
const auto& opacity =
static_cast<const gfx::detail::VertexType<gfx::AttributeType<float, 1>>*>(
binder->getVertexValue(i))
->a1;
attr->set<gfx::VertexAttribute::float2>(i, {opacity[0], opacity[0]});
}
}
}
}
@@ -414,56 +436,32 @@ void RenderFillLayer::update(const int32_t layerIndex,
continue;
}
if (!builder) {
builder = context.createDrawableBuilder("fill");
builder->setShader(fillShader);
builder->addTweaker(context.createDrawableTweaker());
builder->setColorMode(gfx::DrawableBuilder::ColorMode::None);
builder->setDepthType(gfx::DepthMaskType::ReadWrite);
builder->setLayerIndex(layerIndex);
if (doFill && !fillBuilder) {
fillBuilder = context.createDrawableBuilder("fill");
fillBuilder->setShader(fillShader);
//fillBuilder->addTweaker(context.createDrawableTweaker());
fillBuilder->setColorMode(gfx::DrawableBuilder::ColorMode::None);
fillBuilder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite : gfx::DepthMaskType::ReadOnly);
fillBuilder->setDepthType(gfx::DepthMaskType::ReadWrite);
fillBuilder->setLayerIndex(layerIndex);
}
if (doOutline && !outlineBuilder) {
outlineBuilder = context.createDrawableBuilder("fill-outline");
outlineBuilder->setShader(outlineShader);
//outlineBuilder->addTweaker(context.createDrawableTweaker());
outlineBuilder->setColorMode(gfx::DrawableBuilder::ColorMode::None);
outlineBuilder->setLineWidth(2);
outlineBuilder->setDepthType(gfx::DepthMaskType::ReadOnly);
outlineBuilder->setLayerIndex(layerIndex);
outlineBuilder->setSubLayerIndex(unevaluated.get<FillOutlineColor>().isUndefined() ? 2 : 0);
}
// tile.translatedMatrix(evaluated.get<FillTranslate>(), evaluated.get<FillTranslateAnchor>(),
// parameters.state)
builder->setRenderPass(renderPass);
builder->setVertexAttributes(vertexAttrs);
const std::vector<gfx::VertexVector<gfx::detail::VertexType<gfx::AttributeType<int16_t, 2>>>::Vertex>&
verts = bucket.vertices.vector();
std::vector<std::array<int16_t, 2>> rawVerts(verts.size());
std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; });
builder->addVertices(rawVerts, 0, rawVerts.size());
for (const auto& seg : bucket.triangleSegments) {
builder->addTriangles(bucket.triangles.vector(), seg.indexOffset, seg.indexLength);
}
if (fillAA) {
// TODO: Different drawable? Multiple concurrent builders?
for (const auto& seg : bucket.lineSegments) {
builder->addLines(bucket.lines.vector(), seg.indexOffset, seg.indexLength);
}
}
// evaluated.get<FillTranslate>(),
// evaluated.get<FillTranslateAnchor>(),
// parameters.stencilModeForClipping(tile.id),
// parameters.colorModeForRenderPass(),
// gfx::CullFaceMode::disabled(),
//
// const auto isOpaque = (evaluated.get<FillColor>().constantOr(Color()).a >= 1.0f &&
// evaluated.get<FillOpacity>().constantOr(0) >= 1.0f
// );// && layerIndex >= parameters.opaquePassCutoff);
// const auto fillRenderPass = isOpaque ? RenderPass::Opaque : RenderPass::Translucent;
//
// if (renderPass == fillRenderPass) {
// }
// const auto depthMask = (renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite
// : gfx::DepthMaskType::ReadOnly;
// const auto depthMode = parameters.depthModeForSublayer(1, depthMask);
// if (evaluated.get<FillAntialias>() && parameters.pass == RenderPass::Translucent) {
// draw(*fillOutlineProgram,
@@ -476,22 +474,57 @@ void RenderFillLayer::update(const int32_t layerIndex,
// FillOutlineProgram::TextureBindings{});
// }
builder->flush();
// tile.translatedMatrix(evaluated.get<FillTranslate>(), evaluated.get<FillTranslateAnchor>(),
// parameters.state)
auto newDrawables = builder->clearDrawables();
if (!newDrawables.empty()) {
auto& drawable = newDrawables[0];
drawable->setTileID(tileID);
// drawable->mutableUniformBuffers().addOrReplace("FillLayerUBO", uniformBuffer);
if (fillBuilder) {
fillBuilder->setRenderPass(renderPass);
fillBuilder->setVertexAttributes(fillVertexAttrs);
}
if (outlineBuilder) {
outlineBuilder->setRenderPass(renderPass);
outlineBuilder->setVertexAttributes(outlineVertexAttrs);
}
// Track it.
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
++stats.tileDrawablesAdded;
// Log::Warning(Event::General, "Adding drawable for " + util::toString(tileID) + " total " +
// std::to_string(stats.tileDrawablesAdded+1));
const std::vector<gfx::VertexVector<gfx::detail::VertexType<gfx::AttributeType<int16_t, 2>>>::Vertex>&
verts = bucket.vertices.vector();
std::vector<std::array<int16_t, 2>> rawVerts(verts.size());
std::transform(verts.begin(), verts.end(), rawVerts.begin(), [](const auto& x) { return x.a1; });
if (fillBuilder) {
fillBuilder->addVertices(rawVerts, 0, rawVerts.size());
for (const auto& seg : bucket.triangleSegments) {
fillBuilder->addTriangles(bucket.triangles.vector(), seg.indexOffset, seg.indexLength);
}
fillBuilder->flush();
for (auto& drawable : fillBuilder->clearDrawables()) {
drawable->setTileID(tileID);
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
++stats.tileDrawablesAdded;
}
}
if (outlineBuilder) {
outlineBuilder->addVertices(rawVerts, 0, rawVerts.size());
for (const auto& seg : bucket.lineSegments) {
outlineBuilder->addLines(bucket.lines.vector(), seg.indexOffset, seg.indexLength);
}
outlineBuilder->flush();
for (auto& drawable : outlineBuilder->clearDrawables()) {
drawable->setTileID(tileID);
tileLayerGroup->addDrawable(renderPass, tileID, std::move(drawable));
++stats.tileDrawablesAdded;
}
}
}
} else {
} else { // FillPattern is defined
// if (parameters.pass != RenderPass::Translucent) {
// return;
// }