写在前面
在看本文前,建议了解前置内容:[090]unsignaled-buffer-latch功能 - 简书
本文仍在修正补充中...
sf对fence状态的不同处理
在 Android 显示系统的合成流程中,SurfaceFlinger 负责将来自不同 Layer 的 buffer 合成到屏幕输出。 每个 buffer 通过 Fence来标记它是否已经准备好被读取,Fence 消息是由生产方在写入完成后发出的。
- Signaled fence:表示 buffer 被硬件写入完毕
- Unsignaled fence:表示 buffer 还没写好
sf侧有三种处理Unsignaled fence的策略:
enum class LatchUnsignaledConfig {
// 当acquireFence处于无信号状态时,不会进行对应Tranaction的提交
Disabled,
// 对于只携带一个了Layer属性的Transaction,会跳过acquireFence状态检查
AutoSingleLayer,
// 所有Transaction都会跳过acquireFence状态检查
Always,
};
配置时通过debug.sf.auto_latch_unsignaled和debug.sf.latch_unsignaled属性指定模式,在sf启动时会读取该属性:
//不同芯片厂商定制策略不同,部分厂商没有这段代码
LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() {
if (base::GetBoolProperty("debug.sf.latch_unsignaled"s, true)) {
return LatchUnsignaledConfig::Always;
}
if (base::GetBoolProperty("debug.sf.auto_latch_unsignaled"s, true)) {
return LatchUnsignaledConfig::AutoSingleLayer;
}
return LatchUnsignaledConfig::Disabled;
}
开启debug.sf.auto_latch_unsignaled时会执行AutoSingleLayer模式(MTK默认使用Always模式)
AutoSingleLayer的使用条件
debug.sf.latch_unsignaled = false
debug.sf.auto_latch_unsignaled = true
能使用到AutoSingleLayer的判定逻辑主要在下面代码中
1.未使用Disabled模式
2.变更的图层只有1个
3.开启了AutoSingleLayer并且是该图层首个事件
4.不是Early()状态
bool SurfaceFlinger::shouldLatchUnsignaled(const layer_state_t& state, size_t numStates,
bool firstTransaction) const {
if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Disabled) {
ATRACE_FORMAT_INSTANT("%s: false (LatchUnsignaledConfig::Disabled)", __func__);
return false;
}
// We only want to latch unsignaled when a single layer is updated in this
// transaction (i.e. not a blast sync transaction).
//numStates表示在当前事务中更新的图层数量
//只针对带有一个Layer属性的Transaction
if (numStates != 1) {
ATRACE_FORMAT_INSTANT("%s: false (numStates=%zu)", __func__, numStates);
return false;
}
if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::AutoSingleLayer) {
//是否是第一个transaction
if (!firstTransaction) {
ATRACE_FORMAT_INSTANT("%s: false (LatchUnsignaledConfig::AutoSingleLayer; not first "
"transaction)",
__func__);
return false;
}
//如果当前处于 Early 模式或客户端合成模式,我们不希望进行 Latch Unsignaled,因为这会导致:
//RenderEngine 等待未完成的 buffer,造成卡顿 (jank)
//动画(尤其是窗口动画)变慢
//判断是否处于“Early”模式
if (mScheduler->vsyncModulator().isVsyncConfigEarly()) {
ATRACE_FORMAT_INSTANT("%s: false (LatchUnsignaledConfig::AutoSingleLayer; "
"isVsyncConfigEarly)",
__func__);
return false;
}
}
return true;
}
trace现象
如图,sf验证buffer状态时(左边竖线),该buffer是fence未释放状态,但仍然被sf取用。
虽然当前开启的是Always,但是该场景下只有一个layer的修改,开启autoSingleLayer也会是同样的情况
代码走读
commit阶段处理transaction
循环处理一些条件,然后再apply fence未释放的transaction,具体处理逻辑看下文
std::vector<TransactionState> TransactionHandler::flushTransactions() {
// Collect transaction that are ready to be applied.
std::vector<TransactionState> transactions;
TransactionFlushState flushState;
flushState.queueProcessTime = systemTime();
int lastTransactionsPendingBarrier = 0;
int transactionsPendingBarrier = 0;
do {
lastTransactionsPendingBarrier = transactionsPendingBarrier;
// Collect transactions that are ready to be applied.
transactionsPendingBarrier = flushPendingTransactionQueues(transactions, flushState);
} while (lastTransactionsPendingBarrier != transactionsPendingBarrier);
applyUnsignaledBufferTransaction(transactions, flushState);
mPendingTransactionCount.fetch_sub(transactions.size());
ATRACE_INT("TransactionQueue", static_cast<int>(mPendingTransactionCount.load()));
return transactions;
}
继续调用applyFilters判断是否达到取用标准
达到使用autoSingleLayer的buffer会进入情况3的判断
int TransactionHandler::flushPendingTransactionQueues(
std::vector<QueuedTransactionState>& transactions, TransactionFlushState& flushState) {
int transactionsPendingBarrier = 0; // 统计有多少事务被 Barrier 阻塞(Barrier 是一种同步控制信号,这里用来限制事务处理顺序)
auto it = mPendingTransactionQueues.begin(); // mPendingTransactionQueues 保存按 applyToken 分组的待处理事务队列
while (it != mPendingTransactionQueues.end()) {
auto& [applyToken, queue] = *it;
while (!queue.empty()) {
auto& transaction = queue.front(); // 获取队列最前面的事务(FIFO)
flushState.transaction = &transaction;
//applyFilters会进入TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferCheck
auto ready = applyFilters(flushState);
if (ready == TransactionReadiness::NotReadyBarrier) {
// 情况1:事务由于 Barrier 未准备好,必须等待前置事务完成
transactionsPendingBarrier++;
break; // 阻塞条件下退出当前队列的处理循环
} else if (ready == TransactionReadiness::NotReady) {
// 情况2:事务只是还没准备好(非 Barrier),保留在队列中,等待下次 flush
break;
} else if (ready == TransactionReadiness::NotReadyUnsignaled) {
// 情况3:事务依赖的 Buffer 还没发出信号,但可能是唯一一个可处理的事务
flushState.queueWithUnsignaledBuffer = applyToken;
break;
}
// 情况4:事务已准备好,可以执行
popTransactionFromPending(transactions, flushState, queue);
// 从 pending 队列中取出该事务,加入 transactions 待执行列表,并更新 flush 状态
}
if (queue.empty()) {
// 当前队列处理完,从 mPendingTransactionQueues 中删除这个队列
it = mPendingTransactionQueues.erase(it);
} else {
// 否则,移动到下一个队列继续处理
it = std::next(it, 1);
}
}
return transactionsPendingBarrier; // 返回还有多少事务被 Barrier 阻塞
}
TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferCheck(
const TransactionHandler::TransactionFlushState& flushState) {
.....
if (!fenceSignaled){
...
const bool allowLatchUnsignaled =
shouldLatchUnsignaled(s, transaction.states.size(),
flushState.firstTransaction) &&
layer->isSimpleBufferUpdate(s);
if (allowLatchUnsignaled) {
ATRACE_FORMAT("fence unsignaled try allowLatchUnsignaled %s",
layer->name.c_str());
//注意这个返回值,对应flushPendingTransactionQueues方法的情况3
ready = TransactionReadiness::NotReadyUnsignaled;
} else {
ready = TransactionReadiness::NotReady;
......
isSimpleBufferUpdate()返回true是进入shouldLatchUnsignaled的前提
方法通过3个阶段判断是简单buffer:
-
s.what中必须包含layer_state_t::eBufferChanged标志,表示事务确实提供了一个新的 buffer。 -
不能包含 deniedFlags
-
s.what不能包含以下任意标志,否则返回 false: -
- 断开生产者(
eProducerDisconnect) - 改变 Layer 属性(
eLayerChanged) - 改变相对 Layer(
eRelativeLayerChanged) - 修改透明区域(
eTransparentRegionChanged) - 修改高斯模糊区域(
eBlurRegionsChanged) - 改变 LayerStack(
eLayerStackChanged) - Layer 重新父子关系(
eReparent) - (视 FlagManager 配置而定)自动刷新变化(
eAutoRefreshChanged) - (视 FlagManager 配置而定)
eFlagsChanged
- 断开生产者(
-
这里过滤掉所有结构性变化,确保事务只是在替换 buffer,而不是调整图层关系。
-
-
不能包含 deniedChanges
diff(s)表示事务中 layer 属性发生了哪些变化(和之前状态的差异)。- 必须保证这些变化中 不包含:
- 几何变化(位置、矩阵、裁剪等)
- 透明度变化(Alpha)
- 颜色/色彩空间变化(ColorTransform、Dataspace 等)
- 圆角、模糊半径等 UI 装饰变化
- buffer transformation / crop / destination frame 变化
- HDR 元数据变化、亮度调整
- Shadow、Overlay、Stretch 等视觉效果变化
- 以及某些 Flag 变化(取决于配置)
- 这些都是会影响合成或渲染结果的属性变化,一旦出现,就不再属于“简单 buffer 更新”。
bool RequestedLayerState::isSimpleBufferUpdate(const layer_state_t& s) const {
static constexpr uint64_t requiredFlags = layer_state_t::eBufferChanged;
if ((s.what & requiredFlags) != requiredFlags) {
ATRACE_FORMAT_INSTANT("%s: false [missing required flags 0x%" PRIx64 "]", __func__,
(s.what | requiredFlags) & ~s.what);
return false;
}
const uint64_t deniedFlags = layer_state_t::eProducerDisconnect | layer_state_t::eLayerChanged |
layer_state_t::eRelativeLayerChanged | layer_state_t::eTransparentRegionChanged |
layer_state_t::eBlurRegionsChanged | layer_state_t::eLayerStackChanged |
layer_state_t::eReparent |
(FlagManager::getInstance().latch_unsignaled_with_auto_refresh_changed()
? 0
: (layer_state_t::eAutoRefreshChanged | layer_state_t::eFlagsChanged));
if (s.what & deniedFlags) {
ATRACE_FORMAT_INSTANT("%s: false [has denied flags 0x%" PRIx64 "]", __func__,
s.what & deniedFlags);
return false;
}
const uint64_t changedFlags = diff(s);
const uint64_t deniedChanges = layer_state_t::ePositionChanged | layer_state_t::eAlphaChanged |
layer_state_t::eColorTransformChanged | layer_state_t::eBackgroundColorChanged |
layer_state_t::eMatrixChanged | layer_state_t::eCornerRadiusChanged |
layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBufferTransformChanged |
layer_state_t::eTransformToDisplayInverseChanged | layer_state_t::eCropChanged |
layer_state_t::eDataspaceChanged | layer_state_t::eHdrMetadataChanged |
layer_state_t::eSidebandStreamChanged | layer_state_t::eColorSpaceAgnosticChanged |
layer_state_t::eShadowRadiusChanged | layer_state_t::eFixedTransformHintChanged |
layer_state_t::eTrustedOverlayChanged | layer_state_t::eStretchChanged |
layer_state_t::eBufferCropChanged | layer_state_t::eDestinationFrameChanged |
layer_state_t::eDimmingEnabledChanged | layer_state_t::eExtendedRangeBrightnessChanged |
layer_state_t::eDesiredHdrHeadroomChanged |
(FlagManager::getInstance().latch_unsignaled_with_auto_refresh_changed()
? layer_state_t::eFlagsChanged
: 0);
if (changedFlags & deniedChanges) {
ATRACE_FORMAT_INSTANT("%s: false [has denied changes flags 0x%" PRIx64 "]", __func__,
changedFlags & deniedChanges);
return false;
}
return true;
}
这段代码就是上面我们分析过的
bool SurfaceFlinger::shouldLatchUnsignaled(const layer_state_t& state, size_t numStates,
bool firstTransaction) const {
if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Disabled) {
ATRACE_FORMAT_INSTANT("%s: false (LatchUnsignaledConfig::Disabled)", __func__);
return false;
}
// We only want to latch unsignaled when a single layer is updated in this
// transaction (i.e. not a blast sync transaction).
if (numStates != 1) {
ATRACE_FORMAT_INSTANT("%s: false (numStates=%zu)", __func__, numStates);
return false;
}
if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::AutoSingleLayer) {
if (!firstTransaction) {
ATRACE_FORMAT_INSTANT("%s: false (LatchUnsignaledConfig::AutoSingleLayer; not first "
"transaction)",
__func__);
return false;
}
// We don't want to latch unsignaled if are in early / client composition
// as it leads to jank due to RenderEngine waiting for unsignaled buffer
// or window animations being slow.
if (mScheduler->vsyncModulator().isVsyncConfigEarly()) {
ATRACE_FORMAT_INSTANT("%s: false (LatchUnsignaledConfig::AutoSingleLayer; "
"isVsyncConfigEarly)",
__func__);
return false;
}
}
return true;
}
回到TransactionHandler::flushTransactions()中,循环处理了所有pending的 transaction,现在判断是否latch fence未释放的buffer
void TransactionHandler::applyUnsignaledBufferTransaction(
std::vector<TransactionState>& transactions, TransactionFlushState& flushState) {
// 情况1:如果 flushState 里没有记录 "未发出信号的队列"
// 说明在 flushPendingTransactionQueues 遍历时,没有发现唯一的 NotReadyUnsignaled 状态事务
// 直接返回,不做处理
if (!flushState.queueWithUnsignaledBuffer) {
return;
}
// 情况2:只在当前 flush 周期内,它是 "第一个且唯一" 的事务时才会处理
// 如果已经有其他事务准备执行,就不处理这个未发信号的事务
if (!transactions.empty()) {
ATRACE_NAME("fence unsignaled");
return;
}
// 情况3:定位这个 queueWithUnsignaledBuffer 对应的事务队列
auto it = mPendingTransactionQueues.find(flushState.queueWithUnsignaledBuffer);
LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mPendingTransactionQueues.end(),
"Could not find queue with unsignaled buffer!");
// 拿到该队列的引用
auto& queue = it->second;
// 情况4:使用 popTransactionFromPending 将该事务真正移出 pending 队列,加入执行事务列表
popTransactionFromPending(transactions, flushState, queue);
if (queue.empty()) {
it = mPendingTransactionQueues.erase(it);
}
}
将这个fence未释放的buffer加入到待执行队列等待取用。
void TransactionHandler::popTransactionFromPending(std::vector<TransactionState>& transactions,
TransactionFlushState& flushState,
std::queue<TransactionState>& queue) {
auto& transaction = queue.front();
// 当前事务已准备好,将它从 pending 队列移动到正式执行列表
flushState.firstTransaction = false;
// 从“阻塞事务集合”中移除这个事务的 ID
removeFromStalledTransactions(transaction.id);
// 将事务对象移动到可执行事务集合 transactions 中
transactions.emplace_back(std::move(transaction));
queue.pop();
// 取刚刚加入执行队列的事务的引用
auto& readyToApplyTransaction = transactions.back();
// 遍历该事务包含的所有 layer_state,注意一个事务中可能包含多个 Layer 的更新
readyToApplyTransaction.traverseStatesWithBuffers([&](const layer_state_t& state) {
const bool frameNumberChanged =
state.bufferData->flags.test(BufferData::BufferDataChange::frameNumberChanged);
// 检查该 Layer 的 buffer 状态中,图像缓冲区的帧号是否发生变化
if (frameNumberChanged) {
// 如果帧号发生变化,说明 Layer 准备显示新的 Buffer
flushState.bufferLayersReadyToPresent.emplace_or_replace(
state.surface.get(),
state.bufferData->frameNumber
);
} else {
flushState.bufferLayersReadyToPresent.emplace_or_replace(
state.surface.get(),
std::numeric_limits<uint64_t>::max()
);
}
});
}
总结
要达到使用 AutoSingleLayer latch 未 signal buffer 的条件,必须全部满足:
- Fence 未 signal。
- LatchUnsignaledConfig 配置不为 Disabled。
- 事务只涉及一个图层(
numStates == 1)。 - 配置为 AutoSingleLayer 时:
- 必须是该图层的首个事务(
firstTransaction == true)。 - 当前 Vsync 模式不是 Early(
!isVsyncConfigEarly())。
- 必须是该图层的首个事务(
- 该 layer 必须为 简单 buffer 更新(
isSimpleBufferUpdate(s))。 - 在 commit 阶段,这个事务是唯一要执行的事务(本轮 flush 没有其他 ready 事务)。
可见想要达成使用条件是不太容易的。
只有纯粹的“换了一帧画面”,且不伴随任何图层结构调整、属性变化、视觉效果变化的事务,才会被认为是简单 buffer 更新。 这就是为什么它配合 AutoSingleLayer 机制,可以安全地提前 latch 未 signal buffer,因为这样的事务合成代价非常低、风险很小。
谷歌官方介绍
使用 AutoSingleLayer 进行无信号缓冲区锁存 | Android Open Source Project
推荐关注大佬@王小二的技术栈