#include #include #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { using namespace style; struct alignas(16) FillDrawableUBO { /* 0 */ std::array matrix; /* 64 */ std::array scale; /* 80 */ std::array world; /* 88 */ std::array pixel_coord_upper; /* 96 */ std::array pixel_coord_lower; /* 104 */ std::array texsize; /* 112 */ }; static_assert(sizeof(FillDrawableUBO) == 112); /// Evaluated properties that do not depend on the tile struct alignas(16) FillDrawablePropsUBO { /* 0 */ Color color; /* 16 */ Color outline_color; /* 32 */ float opacity; /* 36 */ float pad1, pad2, pad3; /* 48 */ }; static_assert(sizeof(FillDrawablePropsUBO) == 48); static constexpr std::string_view FillDrawableUBOName = "FillDrawableUBO"; static constexpr std::string_view FillDrawablePropsUBOName = "FillDrawablePropsUBO"; void FillLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { auto& context = parameters.context; const auto& props = static_cast(*evaluatedProperties); const auto& evaluated = props.evaluated; const auto& crossfade = props.crossfade; if (layerGroup.empty()) { return; } #if !defined(NDEBUG) const auto label = layerGroup.getName() + "-update-uniforms"; const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); #endif if (!propsBuffer) { const FillDrawablePropsUBO paramsUBO = { /* .color = */ evaluated.get().constantOr(FillColor::defaultValue()), /* .outline_color = */ evaluated.get().constantOr(FillOutlineColor::defaultValue()), /* .opacity = */ evaluated.get().constantOr(FillOpacity::defaultValue()), /* .padding = */ 0, 0, 0}; propsBuffer = context.createUniformBuffer(¶msUBO, sizeof(paramsUBO)); } layerGroup.observeDrawables([&](gfx::Drawable& drawable) { auto& uniforms = drawable.mutableUniformBuffers(); uniforms.addOrReplace(FillDrawablePropsUBOName, propsBuffer); if (!drawable.getTileID()) { return; } const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); const auto& translation = evaluated.get(); const auto anchor = evaluated.get(); constexpr bool inViewportPixelUnits = false; // from RenderTile::translatedMatrix constexpr bool nearClipped = false; const auto matrix = getTileMatrix( tileID, renderTree, parameters.state, translation, anchor, nearClipped, inViewportPixelUnits); // from FillPatternProgram::layoutUniformValues const auto renderableSize = parameters.backend.getDefaultRenderable().getSize(); const auto intZoom = parameters.state.getIntegerZoom(); const auto tileRatio = 1.0f / tileID.pixelsToTileUnits(1.0f, intZoom); const int32_t tileSizeAtNearestZoom = static_cast( util::tileSize_D * parameters.state.zoomScale(intZoom - tileID.canonical.z)); const int32_t pixelX = static_cast( tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * parameters.state.zoomScale(tileID.canonical.z))); const int32_t pixelY = tileSizeAtNearestZoom * tileID.canonical.y; const auto pixelRatio = parameters.pixelRatio; Size textureSize = {0, 0}; if (const auto shader = drawable.getShader()) { if (const auto index = shader->getSamplerLocation("u_image")) { if (const auto& tex = drawable.getTexture(*index)) { textureSize = tex->getSize(); } } } const FillDrawableUBO drawableUBO = { /*.matrix=*/util::cast(matrix), /*.scale=*/{pixelRatio, tileRatio, crossfade.fromScale, crossfade.toScale}, /*.world=*/{(float)renderableSize.width, (float)renderableSize.height}, /*.pixel_coord_upper=*/{static_cast(pixelX >> 16), static_cast(pixelY >> 16)}, /*.pixel_coord_lower=*/{static_cast(pixelX & 0xFFFF), static_cast(pixelY & 0xFFFF)}, /*.texsize=*/{static_cast(textureSize.width), static_cast(textureSize.height)}, }; uniforms.createOrUpdate(FillDrawableUBOName, &drawableUBO, context); }); } } // namespace mbgl