diff options
93 files changed, 3152 insertions, 1932 deletions
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index ea5343a2a0..a3499c1963 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -277,15 +277,6 @@ cc_defaults { "-fvisibility=hidden", "-DBUILDING_LIBBINDER", ], - - target: { - vendor: { - // Trimming the exported symbols reveals a bug in vendor code, so - // disable it for the vendor variant for now. http://b/349657329 - // TODO: Fix the issue and remove this override. - cflags: ["-fvisibility=default"], - }, - }, } cc_defaults { diff --git a/libs/binder/rust/rpcbinder/src/lib.rs b/libs/binder/rust/rpcbinder/src/lib.rs index 7e5c9ddc35..774bb21efe 100644 --- a/libs/binder/rust/rpcbinder/src/lib.rs +++ b/libs/binder/rust/rpcbinder/src/lib.rs @@ -20,6 +20,8 @@ mod server; mod session; pub use server::RpcServer; +#[cfg(target_os = "trusty")] +pub use server::RpcServerConnection; #[cfg(not(target_os = "trusty"))] pub use server::RpcServerRef; pub use session::{FileDescriptorTransportMode, RpcSession, RpcSessionRef}; diff --git a/libs/binder/rust/rpcbinder/src/server/trusty.rs b/libs/binder/rust/rpcbinder/src/server/trusty.rs index fe45decf25..54d82d5bd0 100644 --- a/libs/binder/rust/rpcbinder/src/server/trusty.rs +++ b/libs/binder/rust/rpcbinder/src/server/trusty.rs @@ -106,6 +106,10 @@ pub struct RpcServerConnection { ctx: *mut c_void, } +// SAFETY: The opaque handle: `ctx` points into a dynamic allocation, +// and not tied to anything specific to the current thread. +unsafe impl Send for RpcServerConnection {} + impl Drop for RpcServerConnection { fn drop(&mut self) { // We do not need to close handle_fd since we do not own it. diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs index 6a8a69843a..771c65bf92 100644 --- a/libs/binder/rust/src/binder.rs +++ b/libs/binder/rust/src/binder.rs @@ -1160,6 +1160,12 @@ macro_rules! declare_binder_enum { pub const fn enum_values() -> [Self; $size] { [$(Self::$name),*] } + + #[inline(always)] + #[allow(missing_docs)] + pub const fn get(&self) -> $backing { + self.0 + } } impl std::fmt::Debug for $enum { diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 1aae13c1f4..5b0f21de91 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -1032,7 +1032,7 @@ void BLASTBufferQueue::mergeWithNextTransaction(SurfaceComposerClient::Transacti // Apply the transaction since we have already acquired the desired frame. t->setApplyToken(mApplyToken).apply(); } else { - mPendingTransactions.emplace_back(frameNumber, *t); + mPendingTransactions.emplace_back(frameNumber, std::move(*t)); // Clear the transaction so it can't be applied elsewhere. t->clear(); } @@ -1050,8 +1050,8 @@ void BLASTBufferQueue::applyPendingTransactions(uint64_t frameNumber) { void BLASTBufferQueue::mergePendingTransactions(SurfaceComposerClient::Transaction* t, uint64_t frameNumber) { auto mergeTransaction = - [&t, currentFrameNumber = frameNumber]( - std::tuple<uint64_t, SurfaceComposerClient::Transaction> pendingTransaction) { + [t, currentFrameNumber = frameNumber]( + std::pair<uint64_t, SurfaceComposerClient::Transaction>& pendingTransaction) { auto& [targetFrameNumber, transaction] = pendingTransaction; if (currentFrameNumber < targetFrameNumber) { return false; diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 5961b41478..bcf61e45de 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -364,8 +364,10 @@ status_t BufferQueueProducer::waitForFreeSlotThenRelock(FreeSlotCaller caller, // Producers are not allowed to dequeue more than // mMaxDequeuedBufferCount buffers. // This check is only done if a buffer has already been queued - if (mCore->mBufferHasBeenQueued && - dequeuedCount >= mCore->mMaxDequeuedBufferCount) { + using namespace com::android::graphics::libgui::flags; + bool flagGatedBufferHasBeenQueued = + bq_always_use_max_dequeued_buffer_count() || mCore->mBufferHasBeenQueued; + if (flagGatedBufferHasBeenQueued && dequeuedCount >= mCore->mMaxDequeuedBufferCount) { // Supress error logs when timeout is non-negative. if (mDequeueTimeout < 0) { BQ_LOGE("%s: attempting to exceed the max dequeued buffer " diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 269936858a..ae4b74e03b 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -26,6 +26,7 @@ #include <gui/ISurfaceComposer.h> #include <gui/LayerState.h> #include <gui/SchedulingPolicy.h> +#include <gui/TransactionState.h> #include <private/gui/ParcelUtils.h> #include <stdint.h> #include <sys/types.h> @@ -60,54 +61,12 @@ public: virtual ~BpSurfaceComposer(); - status_t setTransactionState( - const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state, - Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, - InputWindowCommands commands, int64_t desiredPresentTime, bool isAutoTimestamp, - const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks, - const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId, - const std::vector<uint64_t>& mergedTransactionIds) override { + status_t setTransactionState(TransactionState&& state) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + SAFE_PARCEL(state.writeToParcel, &data); - frameTimelineInfo.writeToParcel(&data); - - SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(state.size())); - for (const auto& s : state) { - SAFE_PARCEL(s.write, data); - } - - SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(displays.size())); - for (const auto& d : displays) { - SAFE_PARCEL(d.write, data); - } - - SAFE_PARCEL(data.writeUint32, flags); - SAFE_PARCEL(data.writeStrongBinder, applyToken); - SAFE_PARCEL(commands.write, data); - SAFE_PARCEL(data.writeInt64, desiredPresentTime); - SAFE_PARCEL(data.writeBool, isAutoTimestamp); - SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(uncacheBuffers.size())); - for (const client_cache_t& uncacheBuffer : uncacheBuffers) { - SAFE_PARCEL(data.writeStrongBinder, uncacheBuffer.token.promote()); - SAFE_PARCEL(data.writeUint64, uncacheBuffer.id); - } - SAFE_PARCEL(data.writeBool, hasListenerCallbacks); - - SAFE_PARCEL(data.writeVectorSize, listenerCallbacks); - for (const auto& [listener, callbackIds] : listenerCallbacks) { - SAFE_PARCEL(data.writeStrongBinder, listener); - SAFE_PARCEL(data.writeParcelableVector, callbackIds); - } - - SAFE_PARCEL(data.writeUint64, transactionId); - - SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(mergedTransactionIds.size())); - for (auto mergedTransactionId : mergedTransactionIds) { - SAFE_PARCEL(data.writeUint64, mergedTransactionId); - } - - if (flags & ISurfaceComposer::eOneWay) { + if (state.mFlags & ISurfaceComposer::eOneWay) { return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply, IBinder::FLAG_ONEWAY); } else { @@ -132,75 +91,9 @@ status_t BnSurfaceComposer::onTransact( case SET_TRANSACTION_STATE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - FrameTimelineInfo frameTimelineInfo; - frameTimelineInfo.readFromParcel(&data); - - uint32_t count = 0; - SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize()); - Vector<ComposerState> state; - state.setCapacity(count); - for (size_t i = 0; i < count; i++) { - ComposerState s; - SAFE_PARCEL(s.read, data); - state.add(s); - } - - SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize()); - DisplayState d; - Vector<DisplayState> displays; - displays.setCapacity(count); - for (size_t i = 0; i < count; i++) { - SAFE_PARCEL(d.read, data); - displays.add(d); - } - - uint32_t stateFlags = 0; - SAFE_PARCEL(data.readUint32, &stateFlags); - sp<IBinder> applyToken; - SAFE_PARCEL(data.readStrongBinder, &applyToken); - InputWindowCommands inputWindowCommands; - SAFE_PARCEL(inputWindowCommands.read, data); - - int64_t desiredPresentTime = 0; - bool isAutoTimestamp = true; - SAFE_PARCEL(data.readInt64, &desiredPresentTime); - SAFE_PARCEL(data.readBool, &isAutoTimestamp); - - SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize()); - std::vector<client_cache_t> uncacheBuffers(count); - sp<IBinder> tmpBinder; - for (size_t i = 0; i < count; i++) { - SAFE_PARCEL(data.readNullableStrongBinder, &tmpBinder); - uncacheBuffers[i].token = tmpBinder; - SAFE_PARCEL(data.readUint64, &uncacheBuffers[i].id); - } - - bool hasListenerCallbacks = false; - SAFE_PARCEL(data.readBool, &hasListenerCallbacks); - - std::vector<ListenerCallbacks> listenerCallbacks; - int32_t listenersSize = 0; - SAFE_PARCEL_READ_SIZE(data.readInt32, &listenersSize, data.dataSize()); - for (int32_t i = 0; i < listenersSize; i++) { - SAFE_PARCEL(data.readStrongBinder, &tmpBinder); - std::vector<CallbackId> callbackIds; - SAFE_PARCEL(data.readParcelableVector, &callbackIds); - listenerCallbacks.emplace_back(tmpBinder, callbackIds); - } - - uint64_t transactionId = -1; - SAFE_PARCEL(data.readUint64, &transactionId); - - SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize()); - std::vector<uint64_t> mergedTransactions(count); - for (size_t i = 0; i < count; i++) { - SAFE_PARCEL(data.readUint64, &mergedTransactions[i]); - } - - return setTransactionState(frameTimelineInfo, state, displays, stateFlags, applyToken, - std::move(inputWindowCommands), desiredPresentTime, - isAutoTimestamp, uncacheBuffers, hasListenerCallbacks, - listenerCallbacks, transactionId, mergedTransactions); + TransactionState state; + SAFE_PARCEL(state.readFromParcel, &data); + return setTransactionState(std::move(state)); } case GET_SCHEDULING_POLICY: { gui::SchedulingPolicy policy; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index e407a63d10..69ba1d731d 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -824,34 +824,24 @@ void removeDeadBufferCallback(void* /*context*/, uint64_t graphicBufferId) { // --------------------------------------------------------------------------- SurfaceComposerClient::Transaction::Transaction() { - mId = generateId(); + mState.mId = generateId(); mTransactionCompletedListener = TransactionCompletedListener::getInstance(); } -SurfaceComposerClient::Transaction::Transaction(const Transaction& other) - : mId(other.mId), - mFlags(other.mFlags), - mMayContainBuffer(other.mMayContainBuffer), - mDesiredPresentTime(other.mDesiredPresentTime), - mIsAutoTimestamp(other.mIsAutoTimestamp), - mFrameTimelineInfo(other.mFrameTimelineInfo), - mApplyToken(other.mApplyToken) { - mDisplayStates = other.mDisplayStates; - mComposerStates = other.mComposerStates; - mInputWindowCommands = other.mInputWindowCommands; - mListenerCallbacks = other.mListenerCallbacks; - mTransactionCompletedListener = TransactionCompletedListener::getInstance(); -} +SurfaceComposerClient::Transaction::Transaction(Transaction&& other) + : mTransactionCompletedListener(TransactionCompletedListener::getInstance()), + mState(std::move(other.mState)), + mListenerCallbacks(std::move(other.mListenerCallbacks)) {} void SurfaceComposerClient::Transaction::sanitize(int pid, int uid) { uint32_t permissions = LayerStatePermissions::getTransactionPermissions(pid, uid); - for (auto& composerState : mComposerStates) { + for (auto& composerState : mState.mComposerStates) { composerState.state.sanitize(permissions); } - if (!mInputWindowCommands.empty() && + if (!mState.mInputWindowCommands.empty() && (permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) == 0) { ALOGE("Only privileged callers are allowed to send input commands."); - mInputWindowCommands.clear(); + mState.mInputWindowCommands.clear(); } } @@ -866,31 +856,10 @@ SurfaceComposerClient::Transaction::createFromParcel(const Parcel* parcel) { status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel) { - const uint64_t transactionId = parcel->readUint64(); - const uint32_t flags = parcel->readUint32(); - const int64_t desiredPresentTime = parcel->readInt64(); - const bool isAutoTimestamp = parcel->readBool(); - const bool logCallPoints = parcel->readBool(); - FrameTimelineInfo frameTimelineInfo; - frameTimelineInfo.readFromParcel(parcel); - - sp<IBinder> applyToken; - parcel->readNullableStrongBinder(&applyToken); - size_t count = static_cast<size_t>(parcel->readUint32()); - if (count > parcel->dataSize()) { - return BAD_VALUE; - } - Vector<DisplayState> displayStates; - displayStates.setCapacity(count); - for (size_t i = 0; i < count; i++) { - DisplayState displayState; - if (displayState.read(*parcel) == BAD_VALUE) { - return BAD_VALUE; - } - displayStates.add(displayState); - } + TransactionState tmpState; + SAFE_PARCEL(tmpState.readFromParcel, parcel); - count = static_cast<size_t>(parcel->readUint32()); + size_t count = static_cast<size_t>(parcel->readUint32()); if (count > parcel->dataSize()) { return BAD_VALUE; } @@ -919,57 +888,8 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel } } - count = static_cast<size_t>(parcel->readUint32()); - if (count > parcel->dataSize()) { - return BAD_VALUE; - } - Vector<ComposerState> composerStates; - composerStates.setCapacity(count); - for (size_t i = 0; i < count; i++) { - ComposerState composerState; - if (composerState.read(*parcel) == BAD_VALUE) { - return BAD_VALUE; - } - composerStates.add(composerState); - } - - InputWindowCommands inputWindowCommands; - inputWindowCommands.read(*parcel); - - count = static_cast<size_t>(parcel->readUint32()); - if (count > parcel->dataSize()) { - return BAD_VALUE; - } - std::vector<client_cache_t> uncacheBuffers(count); - for (size_t i = 0; i < count; i++) { - sp<IBinder> tmpBinder; - SAFE_PARCEL(parcel->readStrongBinder, &tmpBinder); - uncacheBuffers[i].token = tmpBinder; - SAFE_PARCEL(parcel->readUint64, &uncacheBuffers[i].id); - } - - count = static_cast<size_t>(parcel->readUint32()); - if (count > parcel->dataSize()) { - return BAD_VALUE; - } - std::vector<uint64_t> mergedTransactionIds(count); - for (size_t i = 0; i < count; i++) { - SAFE_PARCEL(parcel->readUint64, &mergedTransactionIds[i]); - } - - // Parsing was successful. Update the object. - mId = transactionId; - mFlags = flags; - mDesiredPresentTime = desiredPresentTime; - mIsAutoTimestamp = isAutoTimestamp; - mFrameTimelineInfo = frameTimelineInfo; - mDisplayStates = std::move(displayStates); - mListenerCallbacks = listenerCallbacks; - mComposerStates = std::move(composerStates); - mInputWindowCommands = inputWindowCommands; - mApplyToken = applyToken; - mUncacheBuffers = std::move(uncacheBuffers); - mMergedTransactionIds = std::move(mergedTransactionIds); + mState = std::move(tmpState); + mListenerCallbacks = std::move(listenerCallbacks); return NO_ERROR; } @@ -987,17 +907,7 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const const_cast<SurfaceComposerClient::Transaction*>(this)->cacheBuffers(); - parcel->writeUint64(mId); - parcel->writeUint32(mFlags); - parcel->writeInt64(mDesiredPresentTime); - parcel->writeBool(mIsAutoTimestamp); - parcel->writeBool(mLogCallPoints); - mFrameTimelineInfo.writeToParcel(parcel); - parcel->writeStrongBinder(mApplyToken); - parcel->writeUint32(static_cast<uint32_t>(mDisplayStates.size())); - for (auto const& displayState : mDisplayStates) { - displayState.write(*parcel); - } + SAFE_PARCEL(mState.writeToParcel, parcel); parcel->writeUint32(static_cast<uint32_t>(mListenerCallbacks.size())); for (auto const& [listener, callbackInfo] : mListenerCallbacks) { @@ -1012,24 +922,6 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const } } - parcel->writeUint32(static_cast<uint32_t>(mComposerStates.size())); - for (auto const& composerState : mComposerStates) { - composerState.write(*parcel); - } - - mInputWindowCommands.write(*parcel); - - SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mUncacheBuffers.size())); - for (const client_cache_t& uncacheBuffer : mUncacheBuffers) { - SAFE_PARCEL(parcel->writeStrongBinder, uncacheBuffer.token.promote()); - SAFE_PARCEL(parcel->writeUint64, uncacheBuffer.id); - } - - SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(mMergedTransactionIds.size())); - for (auto mergedTransactionId : mMergedTransactionIds) { - SAFE_PARCEL(parcel->writeUint64, mergedTransactionId); - } - return NO_ERROR; } @@ -1054,50 +946,8 @@ void SurfaceComposerClient::Transaction::releaseBufferIfOverwriting(const layer_ } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) { - while (mMergedTransactionIds.size() + other.mMergedTransactionIds.size() > - MAX_MERGE_HISTORY_LENGTH - 1 && - mMergedTransactionIds.size() > 0) { - mMergedTransactionIds.pop_back(); - } - if (other.mMergedTransactionIds.size() == MAX_MERGE_HISTORY_LENGTH) { - mMergedTransactionIds.insert(mMergedTransactionIds.begin(), - other.mMergedTransactionIds.begin(), - other.mMergedTransactionIds.end() - 1); - } else if (other.mMergedTransactionIds.size() > 0u) { - mMergedTransactionIds.insert(mMergedTransactionIds.begin(), - other.mMergedTransactionIds.begin(), - other.mMergedTransactionIds.end()); - } - mMergedTransactionIds.insert(mMergedTransactionIds.begin(), other.mId); - - for (auto const& otherState : other.mComposerStates) { - if (auto it = std::find_if(mComposerStates.begin(), mComposerStates.end(), - [&otherState](const auto& composerState) { - return composerState.state.surface == - otherState.state.surface; - }); - it != mComposerStates.end()) { - if (otherState.state.what & layer_state_t::eBufferChanged) { - releaseBufferIfOverwriting(it->state); - } - it->state.merge(otherState.state); - } else { - mComposerStates.add(otherState); - } - } - - for (auto const& state : other.mDisplayStates) { - if (auto it = std::find_if(mDisplayStates.begin(), mDisplayStates.end(), - [&state](const auto& displayState) { - return displayState.token == state.token; - }); - it != mDisplayStates.end()) { - it->merge(state); - } else { - mDisplayStates.add(state); - } - } - + mState.merge(std::move(other.mState), + std::bind(&Transaction::releaseBufferIfOverwriting, this, std::placeholders::_1)); for (const auto& [listener, callbackInfo] : other.mListenerCallbacks) { auto& [callbackIds, surfaceControls] = callbackInfo; mListenerCallbacks[listener].callbackIds.insert(std::make_move_iterator( @@ -1121,50 +971,21 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr } } - for (const auto& cacheId : other.mUncacheBuffers) { - mUncacheBuffers.push_back(cacheId); - } - - mInputWindowCommands.merge(other.mInputWindowCommands); - - mMayContainBuffer |= other.mMayContainBuffer; - mFlags |= other.mFlags; - mApplyToken = other.mApplyToken; - - mergeFrameTimelineInfo(mFrameTimelineInfo, other.mFrameTimelineInfo); - - mLogCallPoints |= other.mLogCallPoints; - if (mLogCallPoints) { - ALOG(LOG_DEBUG, LOG_SURFACE_CONTROL_REGISTRY, - "Transaction %" PRIu64 " merged with transaction %" PRIu64, other.getId(), mId); - } - other.clear(); return *this; } void SurfaceComposerClient::Transaction::clear() { - mComposerStates.clear(); - mDisplayStates.clear(); + mState.clear(); mListenerCallbacks.clear(); - mInputWindowCommands.clear(); - mUncacheBuffers.clear(); - mMayContainBuffer = false; - mDesiredPresentTime = 0; - mIsAutoTimestamp = true; - mFrameTimelineInfo = {}; - mApplyToken = nullptr; - mMergedTransactionIds.clear(); - mLogCallPoints = false; - mFlags = 0; } -uint64_t SurfaceComposerClient::Transaction::getId() { - return mId; +uint64_t SurfaceComposerClient::Transaction::getId() const { + return mState.mId; } std::vector<uint64_t> SurfaceComposerClient::Transaction::getMergedTransactionIds() { - return mMergedTransactionIds; + return mState.mMergedTransactionIds; } void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { @@ -1173,12 +994,13 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { client_cache_t uncacheBuffer; uncacheBuffer.token = BufferCache::getInstance().getToken(); uncacheBuffer.id = cacheId; - Vector<ComposerState> composerStates; - Vector<DisplayState> displayStates; - status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, displayStates, - ISurfaceComposer::eOneWay, - Transaction::getDefaultApplyToken(), {}, systemTime(), - true, {uncacheBuffer}, false, {}, generateId(), {}); + TransactionState state; + state.mId = generateId(); + state.mApplyToken = Transaction::getDefaultApplyToken(); + state.mUncacheBuffers.emplace_back(std::move(uncacheBuffer)); + state.mFlags = ISurfaceComposer::eOneWay; + state.mDesiredPresentTime = systemTime(); + status_t status = sf->setTransactionState(std::move(state)); if (status != NO_ERROR) { ALOGE_AND_TRACE("SurfaceComposerClient::doUncacheBufferTransaction - %s", strerror(-status)); @@ -1186,12 +1008,12 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { } void SurfaceComposerClient::Transaction::cacheBuffers() { - if (!mMayContainBuffer) { + if (!mState.mMayContainBuffer) { return; } size_t count = 0; - for (auto& cs : mComposerStates) { + for (auto& cs : mState.mComposerStates) { layer_state_t* s = &cs.state; if (!(s->what & layer_state_t::eBufferChanged)) { continue; @@ -1219,7 +1041,7 @@ void SurfaceComposerClient::Transaction::cacheBuffers() { std::optional<client_cache_t> uncacheBuffer; cacheId = BufferCache::getInstance().cache(s->bufferData->buffer, uncacheBuffer); if (uncacheBuffer) { - mUncacheBuffers.push_back(*uncacheBuffer); + mState.mUncacheBuffers.emplace_back(*uncacheBuffer); } } s->bufferData->flags |= BufferData::BufferDataChange::cachedBufferChanged; @@ -1288,8 +1110,7 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay /*callbackContext=*/nullptr); } - bool hasListenerCallbacks = !mListenerCallbacks.empty(); - std::vector<ListenerCallbacks> listenerCallbacks; + mState.mHasListenerCallbacks = !mListenerCallbacks.empty(); // For every listener with registered callbacks for (const auto& [listener, callbackInfo] : mListenerCallbacks) { auto& [callbackIds, surfaceControls] = callbackInfo; @@ -1298,7 +1119,8 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay } if (surfaceControls.empty()) { - listenerCallbacks.emplace_back(IInterface::asBinder(listener), std::move(callbackIds)); + mState.mListenerCallbacks.emplace_back(IInterface::asBinder(listener), + std::move(callbackIds)); } else { // If the listener has any SurfaceControls set on this Transaction update the surface // state @@ -1310,7 +1132,7 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay } std::vector<CallbackId> callbacks(callbackIds.begin(), callbackIds.end()); s->what |= layer_state_t::eHasListenerCallbacksChanged; - s->listeners.emplace_back(IInterface::asBinder(listener), callbacks); + s->listeners.emplace_back(IInterface::asBinder(listener), std::move(callbacks)); } } } @@ -1322,25 +1144,21 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay ALOGE("Transaction attempted to set synchronous and one way at the same time" " this is an invalid request. Synchronous will win for safety"); } else { - mFlags |= ISurfaceComposer::eOneWay; + mState.mFlags |= ISurfaceComposer::eOneWay; } } // If both ISurfaceComposer::eEarlyWakeupStart and ISurfaceComposer::eEarlyWakeupEnd are set // it is equivalent for none uint32_t wakeupFlags = ISurfaceComposer::eEarlyWakeupStart | ISurfaceComposer::eEarlyWakeupEnd; - if ((mFlags & wakeupFlags) == wakeupFlags) { - mFlags &= ~(wakeupFlags); + if ((mState.mFlags & wakeupFlags) == wakeupFlags) { + mState.mFlags &= ~(wakeupFlags); } - sp<IBinder> applyToken = mApplyToken ? mApplyToken : getDefaultApplyToken(); + if (!mState.mApplyToken) mState.mApplyToken = getDefaultApplyToken(); sp<ISurfaceComposer> sf(ComposerService::getComposerService()); - status_t binderStatus = - sf->setTransactionState(mFrameTimelineInfo, mComposerStates, mDisplayStates, mFlags, - applyToken, mInputWindowCommands, mDesiredPresentTime, - mIsAutoTimestamp, mUncacheBuffers, hasListenerCallbacks, - listenerCallbacks, mId, mMergedTransactionIds); - mId = generateId(); + status_t binderStatus = sf->setTransactionState(std::move(mState)); + mState.mId = generateId(); // Clear the current states and flags clear(); @@ -1349,8 +1167,8 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous, bool oneWay syncCallback->wait(); } - if (mLogCallPoints) { - ALOG(LOG_DEBUG, LOG_SURFACE_CONTROL_REGISTRY, "Transaction %" PRIu64 " applied", mId); + if (mState.mLogCallPoints) { + ALOG(LOG_DEBUG, LOG_SURFACE_CONTROL_REGISTRY, "Transaction %" PRIu64 " applied", getId()); } mStatus = NO_ERROR; @@ -1385,7 +1203,7 @@ status_t SurfaceComposerClient::Transaction::sendSurfaceFlushJankDataTransaction } void SurfaceComposerClient::Transaction::enableDebugLogCallPoints() { - mLogCallPoints = true; + mState.mLogCallPoints = true; } // --------------------------------------------------------------------------- @@ -1443,34 +1261,19 @@ std::optional<gui::StalledTransactionInfo> SurfaceComposerClient::getStalledTran } void SurfaceComposerClient::Transaction::setAnimationTransaction() { - mFlags |= ISurfaceComposer::eAnimation; + mState.mFlags |= ISurfaceComposer::eAnimation; } void SurfaceComposerClient::Transaction::setEarlyWakeupStart() { - mFlags |= ISurfaceComposer::eEarlyWakeupStart; + mState.mFlags |= ISurfaceComposer::eEarlyWakeupStart; } void SurfaceComposerClient::Transaction::setEarlyWakeupEnd() { - mFlags |= ISurfaceComposer::eEarlyWakeupEnd; + mState.mFlags |= ISurfaceComposer::eEarlyWakeupEnd; } layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp<SurfaceControl>& sc) { - auto handle = sc->getLayerStateHandle(); - if (auto it = std::find_if(mComposerStates.begin(), mComposerStates.end(), - [&handle](const auto& composerState) { - return composerState.state.surface == handle; - }); - it != mComposerStates.end()) { - return &it->state; - } - - // we don't have it, add an initialized layer_state to our list - ComposerState s; - s.state.surface = handle; - s.state.layerId = sc->getLayerId(); - mComposerStates.add(s); - - return &mComposerStates.editItemAt(mComposerStates.size() - 1).state; + return mState.getLayerState(sc); } void SurfaceComposerClient::Transaction::registerSurfaceControlForCallback( @@ -1846,8 +1649,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe setReleaseBufferCallback(bufferData.get(), callback); } - if (mIsAutoTimestamp) { - mDesiredPresentTime = systemTime(); + if (mState.mIsAutoTimestamp) { + mState.mDesiredPresentTime = systemTime(); } s->what |= layer_state_t::eBufferChanged; s->bufferData = std::move(bufferData); @@ -1865,7 +1668,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe const std::vector<SurfaceControlStats>&) {}, nullptr); - mMayContainBuffer = true; + mState.mMayContainBuffer = true; return *this; } @@ -2041,8 +1844,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSideb SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDesiredPresentTime( nsecs_t desiredPresentTime) { - mDesiredPresentTime = desiredPresentTime; - mIsAutoTimestamp = false; + mState.mDesiredPresentTime = desiredPresentTime; + mState.mIsAutoTimestamp = false; return *this; } @@ -2131,14 +1934,14 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInput SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFocusedWindow( const FocusRequest& request) { - mInputWindowCommands.addFocusRequest(request); + mState.mInputWindowCommands.addFocusRequest(request); return *this; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::addWindowInfosReportedListener( sp<gui::IWindowInfosReportedListener> windowInfosReportedListener) { - mInputWindowCommands.addWindowInfosReportedListener(windowInfosReportedListener); + mState.mInputWindowCommands.addWindowInfosReportedListener(windowInfosReportedListener); return *this; } @@ -2302,7 +2105,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFixed SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo( const FrameTimelineInfo& frameTimelineInfo) { - mergeFrameTimelineInfo(mFrameTimelineInfo, frameTimelineInfo); + mState.mergeFrameTimelineInfo(frameTimelineInfo); return *this; } @@ -2341,7 +2144,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrust SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setApplyToken( const sp<IBinder>& applyToken) { - mApplyToken = applyToken; + mState.mApplyToken = applyToken; return *this; } @@ -2469,17 +2272,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setConte // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) { - if (auto it = std::find_if(mDisplayStates.begin(), mDisplayStates.end(), - [token](const auto& display) { return display.token == token; }); - it != mDisplayStates.end()) { - return *it; - } - - // If display state doesn't exist, add a new one. - DisplayState s; - s.token = token; - mDisplayStates.add(s); - return mDisplayStates.editItemAt(mDisplayStates.size() - 1); + return mState.getDisplayState(token); } status_t SurfaceComposerClient::Transaction::setDisplaySurface(const sp<IBinder>& token, @@ -2532,20 +2325,6 @@ void SurfaceComposerClient::Transaction::setDisplaySize(const sp<IBinder>& token s.what |= DisplayState::eDisplaySizeChanged; } -// copied from FrameTimelineInfo::merge() -void SurfaceComposerClient::Transaction::mergeFrameTimelineInfo(FrameTimelineInfo& t, - const FrameTimelineInfo& other) { - // When merging vsync Ids we take the oldest valid one - if (t.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID && - other.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { - if (other.vsyncId > t.vsyncId) { - t = other; - } - } else if (t.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) { - t = other; - } -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTrustedPresentationCallback( const sp<SurfaceControl>& sc, TrustedPresentationCallback cb, @@ -2766,6 +2545,7 @@ status_t SurfaceComposerClient::getStaticDisplayInfo(int64_t displayId, if (status.isOk()) { // convert gui::StaticDisplayInfo to ui::StaticDisplayInfo outInfo->connectionType = static_cast<ui::DisplayConnectionType>(ginfo.connectionType); + outInfo->port = ginfo.port; outInfo->density = ginfo.density; outInfo->secure = ginfo.secure; outInfo->installOrientation = static_cast<ui::Rotation>(ginfo.installOrientation); diff --git a/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl b/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl index 0ccda56ef5..7ff332c29e 100644 --- a/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl +++ b/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl @@ -23,6 +23,7 @@ import android.gui.Rotation; /** @hide */ parcelable StaticDisplayInfo { DisplayConnectionType connectionType = DisplayConnectionType.Internal; + int port = -1; float density; boolean secure; @nullable DeviceProductInfo deviceProductInfo; diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index db1b9fb8eb..c69b0a79ad 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -284,7 +284,7 @@ private: std::function<void(SurfaceComposerClient::Transaction*)> mTransactionReadyCallback GUARDED_BY(mMutex); SurfaceComposerClient::Transaction* mSyncTransaction GUARDED_BY(mMutex); - std::vector<std::tuple<uint64_t /* framenumber */, SurfaceComposerClient::Transaction>> + std::vector<std::pair<uint64_t /* framenumber */, SurfaceComposerClient::Transaction>> mPendingTransactions GUARDED_BY(mMutex); std::queue<std::pair<uint64_t, FrameTimelineInfo>> mPendingFrameTimelines GUARDED_BY(mMutex); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 9a422fd808..de553aef72 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -65,6 +65,7 @@ struct DisplayState; struct InputWindowCommands; class HdrCapabilities; class Rect; +class TransactionState; using gui::FrameTimelineInfo; using gui::IDisplayEventConnection; @@ -105,13 +106,7 @@ public: }; /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ - virtual status_t setTransactionState( - const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state, - Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, - InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, - bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffer, - bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, - uint64_t transactionId, const std::vector<uint64_t>& mergedTransactionIds) = 0; + virtual status_t setTransactionState(TransactionState&& state) = 0; }; // ---------------------------------------------------------------------------- diff --git a/libs/gui/include/gui/InputTransferToken.h b/libs/gui/include/gui/InputTransferToken.h index fb4aaa73ae..b83f24562b 100644 --- a/libs/gui/include/gui/InputTransferToken.h +++ b/libs/gui/include/gui/InputTransferToken.h @@ -39,15 +39,9 @@ public: return NO_ERROR; }; + bool operator==(const InputTransferToken& other) const { return mToken == other.mToken; } + sp<IBinder> mToken; }; -static inline bool operator==(const sp<InputTransferToken>& token1, - const sp<InputTransferToken>& token2) { - if (token1.get() == token2.get()) { - return true; - } - return token1->mToken == token2->mToken; -} - } // namespace android diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 4fda8deb9c..668bd6fbb8 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -52,6 +52,7 @@ #include <gui/ITransactionCompletedListener.h> #include <gui/LayerState.h> #include <gui/SurfaceControl.h> +#include <gui/TransactionState.h> #include <gui/WindowInfosListenerReporter.h> #include <math/vec3.h> @@ -442,61 +443,16 @@ public: virtual ~PresentationCallbackRAII(); }; - class Transaction : public Parcelable { + class Transaction { private: static sp<IBinder> sApplyToken; static std::mutex sApplyTokenMutex; void releaseBufferIfOverwriting(const layer_state_t& state); - static void mergeFrameTimelineInfo(FrameTimelineInfo& t, const FrameTimelineInfo& other); // Tracks registered callbacks sp<TransactionCompletedListener> mTransactionCompletedListener = nullptr; - // Prints debug logs when enabled. - bool mLogCallPoints = false; - protected: - Vector<ComposerState> mComposerStates; - Vector<DisplayState> mDisplayStates; - std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash> - mListenerCallbacks; - std::vector<client_cache_t> mUncacheBuffers; - - // We keep track of the last MAX_MERGE_HISTORY_LENGTH merged transaction ids. - // Ordered most recently merged to least recently merged. - static const size_t MAX_MERGE_HISTORY_LENGTH = 10u; - std::vector<uint64_t> mMergedTransactionIds; - - uint64_t mId; - uint32_t mFlags = 0; - - // Indicates that the Transaction may contain buffers that should be cached. The reason this - // is only a guess is that buffers can be removed before cache is called. This is only a - // hint that at some point a buffer was added to this transaction before apply was called. - bool mMayContainBuffer = false; - - // mDesiredPresentTime is the time in nanoseconds that the client would like the transaction - // to be presented. When it is not possible to present at exactly that time, it will be - // presented after the time has passed. - // - // If the client didn't pass a desired presentation time, mDesiredPresentTime will be - // populated to the time setBuffer was called, and mIsAutoTimestamp will be set to true. - // - // Desired present times that are more than 1 second in the future may be ignored. - // When a desired present time has already passed, the transaction will be presented as soon - // as possible. - // - // Transactions from the same process are presented in the same order that they are applied. - // The desired present time does not affect this ordering. - int64_t mDesiredPresentTime = 0; - bool mIsAutoTimestamp = true; - - // The vsync id provided by Choreographer.getVsyncId and the input event id - FrameTimelineInfo mFrameTimelineInfo; - - // If not null, transactions will be queued up using this token otherwise a common token - // per process will be used. - sp<IBinder> mApplyToken = nullptr; + TransactionState mState; - InputWindowCommands mInputWindowCommands; int mStatus = NO_ERROR; layer_state_t* getLayerState(const sp<SurfaceControl>& sc); @@ -506,23 +462,29 @@ public: void registerSurfaceControlForCallback(const sp<SurfaceControl>& sc); void setReleaseBufferCallback(BufferData*, ReleaseBufferCallback); + protected: + // Accessed in tests. + explicit Transaction(Transaction const& other) = default; + std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash> + mListenerCallbacks; + public: Transaction(); - virtual ~Transaction() = default; - Transaction(Transaction const& other); + Transaction(Transaction&& other); + Transaction& operator=(Transaction&& other) = default; // Factory method that creates a new Transaction instance from the parcel. static std::unique_ptr<Transaction> createFromParcel(const Parcel* parcel); - status_t writeToParcel(Parcel* parcel) const override; - status_t readFromParcel(const Parcel* parcel) override; + status_t writeToParcel(Parcel* parcel) const; + status_t readFromParcel(const Parcel* parcel); // Clears the contents of the transaction without applying it. void clear(); // Returns the current id of the transaction. // The id is updated every time the transaction is applied. - uint64_t getId(); + uint64_t getId() const; std::vector<uint64_t> getMergedTransactionIds(); diff --git a/libs/gui/include/gui/TransactionState.h b/libs/gui/include/gui/TransactionState.h index 4358227dae..79124f3ed7 100644 --- a/libs/gui/include/gui/TransactionState.h +++ b/libs/gui/include/gui/TransactionState.h @@ -26,7 +26,8 @@ namespace android { class TransactionState { public: explicit TransactionState() = default; - TransactionState(TransactionState const& other) = default; + TransactionState(TransactionState&& other) = default; + TransactionState& operator=(TransactionState&& other) = default; status_t writeToParcel(Parcel* parcel) const; status_t readFromParcel(const Parcel* parcel); layer_state_t* getLayerState(const sp<SurfaceControl>& sc); @@ -86,6 +87,9 @@ public: std::vector<ListenerCallbacks> mListenerCallbacks; private: + explicit TransactionState(TransactionState const& other) = default; + friend class TransactionApplicationTest; + friend class SurfaceComposerClient; // We keep track of the last MAX_MERGE_HISTORY_LENGTH merged transaction ids. // Ordered most recently merged to least recently merged. static constexpr size_t MAX_MERGE_HISTORY_LENGTH = 10u; diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig index 2c3222dd82..ce1bc9512c 100644 --- a/libs/gui/libgui_flags.aconfig +++ b/libs/gui/libgui_flags.aconfig @@ -130,9 +130,6 @@ flag { description: "Remove BufferQueueProducer::dequeue's wait on this fence (or the fence entirely) to prevent deadlocks" bug: "339705065" is_fixed_read_only: true - metadata { - purpose: PURPOSE_BUGFIX - } } # bq_gl_fence_cleanup flag { @@ -153,3 +150,14 @@ flag { } is_fixed_read_only: true } # allocate_buffer_priority + +flag { + name: "bq_always_use_max_dequeued_buffer_count" + namespace: "core_graphics" + description: "BufferQueueProducer::dequeue's respects setMaxDequeuedBufferCount even before a buffer is dequeued." + bug: "399328309" + metadata { + purpose: PURPOSE_BUGFIX + } + is_fixed_read_only: true +} # bq_always_use_max_dequeued_buffer_count diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index cf05fd4ba5..adf8fce472 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -222,8 +222,8 @@ public: ASSERT_EQ(InputEventType::MOTION, ev->getType()); MotionEvent* mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction()); - EXPECT_EQ(x, mev->getX(0)); - EXPECT_EQ(y, mev->getY(0)); + EXPECT_NEAR(x, mev->getX(0), EPSILON); + EXPECT_NEAR(y, mev->getY(0), EPSILON); EXPECT_EQ(flags, mev->getFlags() & flags); ev = consumeEvent(); @@ -241,8 +241,8 @@ public: MotionEvent* mev = static_cast<MotionEvent*>(ev); EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction()); const PointerCoords& coords = *mev->getRawPointerCoords(0 /*pointerIndex*/); - EXPECT_EQ(displayX, coords.getX()); - EXPECT_EQ(displayY, coords.getY()); + EXPECT_NEAR(displayX, coords.getX(), EPSILON); + EXPECT_NEAR(displayY, coords.getY(), EPSILON); EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); ev = consumeEvent(); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index e7690e2530..c4dcba856a 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -648,16 +648,7 @@ public: mSupportsPresent = supportsPresent; } - status_t setTransactionState( - const FrameTimelineInfo& /*frameTimelineInfo*/, Vector<ComposerState>& /*state*/, - Vector<DisplayState>& /*displays*/, uint32_t /*flags*/, - const sp<IBinder>& /*applyToken*/, InputWindowCommands /*inputWindowCommands*/, - int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, - const std::vector<client_cache_t>& /*cachedBuffer*/, bool /*hasListenerCallbacks*/, - const std::vector<ListenerCallbacks>& /*listenerCallbacks*/, uint64_t /*transactionId*/, - const std::vector<uint64_t>& /*mergedTransactionIds*/) override { - return NO_ERROR; - } + status_t setTransactionState(TransactionState&&) override { return NO_ERROR; } protected: IBinder* onAsBinder() override { return nullptr; } @@ -2246,6 +2237,52 @@ TEST_F(SurfaceTest, BatchIllegalOperations) { ASSERT_EQ(NO_ERROR, surface->disconnect(NATIVE_WINDOW_API_CPU)); } +TEST_F(SurfaceTest, setMaxDequeuedBufferCount_setMaxAcquiredBufferCount_allocations) { + // + // Set up the consumer and producer--nothing fancy. + // + auto [consumer, surface] = + BufferItemConsumer::create(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER); + sp<SurfaceListener> surfaceListener = sp<StubSurfaceListener>::make(); + surface->connect(NATIVE_WINDOW_API_CPU, surfaceListener); + sp<GraphicBuffer> buffer; + sp<Fence> fence; + + // + // These values are independent. The consumer can dequeue 3 and the consumer can acquire 3 at + // the same time. + // + ASSERT_EQ(OK, consumer->setMaxAcquiredBufferCount(3)); + ASSERT_EQ(OK, surface->setMaxDequeuedBufferCount(3)); + + // + // Take all three buffers out of the queue--a fourth can't be retrieved. Then queue them. + // + std::vector<Surface::BatchBuffer> dequeuedBuffers(3); + EXPECT_EQ(OK, surface->dequeueBuffers(&dequeuedBuffers)); + if (::com::android::graphics::libgui::flags::bq_always_use_max_dequeued_buffer_count()) { + EXPECT_EQ(INVALID_OPERATION, surface->dequeueBuffer(&buffer, &fence)); + } + + for (auto& batchBuffer : dequeuedBuffers) { + EXPECT_EQ(OK, + surface->queueBuffer(GraphicBuffer::from(batchBuffer.buffer), + sp<Fence>::make(batchBuffer.fenceFd))); + } + dequeuedBuffers.assign(3, {}); + + // + // Acquire all three, then we should be able to dequeue 3 more. + // + std::vector<BufferItem> acquiredBuffers(3); + for (auto& bufferItem : acquiredBuffers) { + EXPECT_EQ(OK, consumer->acquireBuffer(&bufferItem, 0)); + } + + EXPECT_EQ(OK, surface->dequeueBuffers(&dequeuedBuffers)); + EXPECT_EQ(INVALID_OPERATION, surface->dequeueBuffer(&buffer, &fence)); +} + #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS) TEST_F(SurfaceTest, PlatformBufferMethods) { diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index 7f207f0670..f9b84fa948 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -25,6 +25,7 @@ cc_defaults { defaults: [ "android.hardware.graphics.composer3-ndk_shared", "renderengine_defaults", + "libsurfaceflinger_common_deps", ], cflags: [ "-DGL_GLEXT_PROTOTYPES", @@ -117,7 +118,10 @@ filegroup { // possible if libskia_renderengine is just pulled into librenderengine via whole_static_libs. cc_defaults { name: "librenderengine_deps", - defaults: ["skia_renderengine_deps"], + defaults: [ + "skia_renderengine_deps", + "libsurfaceflinger_common_deps", + ], static_libs: ["libskia_renderengine"], } diff --git a/libs/renderengine/benchmark/Android.bp b/libs/renderengine/benchmark/Android.bp index f84db0b04c..2d18ddb0aa 100644 --- a/libs/renderengine/benchmark/Android.bp +++ b/libs/renderengine/benchmark/Android.bp @@ -28,6 +28,7 @@ cc_benchmark { "android.hardware.graphics.composer3-ndk_shared", "librenderengine_deps", "surfaceflinger_defaults", + "libsurfaceflinger_common_deps", ], srcs: [ "main.cpp", @@ -38,7 +39,6 @@ cc_benchmark { static_libs: [ "librenderengine", "libshaders", - "libsurfaceflinger_common", "libtonemap", ], cflags: [ diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp index 25afc7b465..9e1c226371 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -1236,6 +1236,16 @@ void SkiaRenderEngine::drawLayersInternal( LOG_ALWAYS_FATAL_IF(activeSurface != dstSurface); auto drawFence = sp<Fence>::make(flushAndSubmit(context, dstSurface)); trace(drawFence); + FenceTimePtr fenceTime = FenceTime::makeValid(drawFence); + for (const auto& layer : layers) { + if (FlagManager::getInstance().monitor_buffer_fences()) { + if (layer.source.buffer.buffer) { + layer.source.buffer.buffer->getBuffer() + ->getDependencyMonitor() + .addAccessCompletion(fenceTime, "RE"); + } + } + } resultPromise->set_value(std::move(drawFence)); } diff --git a/libs/renderengine/skia/filters/LutShader.cpp b/libs/renderengine/skia/filters/LutShader.cpp index f262158f2c..6a577ff41f 100644 --- a/libs/renderengine/skia/filters/LutShader.cpp +++ b/libs/renderengine/skia/filters/LutShader.cpp @@ -24,7 +24,6 @@ #include <ui/ColorSpace.h> #include "include/core/SkColorSpace.h" -#include "src/core/SkColorFilterPriv.h" using aidl::android::hardware::graphics::composer3::LutProperties; @@ -116,7 +115,7 @@ static const SkString kShader = SkString(R"( linear = mix(c0, c1, linear.b); } } - return float4(linear, rgba.a); + return float4(fromLinearSrgb(linear), rgba.a); })"); // same as shader::toColorSpace function @@ -289,9 +288,7 @@ sk_sp<SkShader> LutShader::lutShader(sk_sp<SkShader>& input, lutProperties[i].samplingKey, srcDataspace); } - auto colorXformLutToDst = - SkColorFilterPriv::MakeColorSpaceXform(lutMathColorSpace, outColorSpace); - input = input->makeWithColorFilter(colorXformLutToDst); + input = input->makeWithWorkingColorSpace(outColorSpace); } return input; } diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index 87e213e394..10cb992835 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -122,6 +122,7 @@ cc_library_shared { srcs: [ "DebugUtils.cpp", + "DependencyMonitor.cpp", "DeviceProductInfo.cpp", "DisplayIdentification.cpp", "DynamicDisplayInfo.cpp", diff --git a/libs/ui/DependencyMonitor.cpp b/libs/ui/DependencyMonitor.cpp new file mode 100644 index 0000000000..b7e490eba4 --- /dev/null +++ b/libs/ui/DependencyMonitor.cpp @@ -0,0 +1,144 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// #define LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "DependencyMonitor" + +#include <ui/DependencyMonitor.h> +#include <ui/Fence.h> +#include <utils/Timers.h> + +#include <inttypes.h> + +namespace android { + +void DependencyMonitor::addIngress(FenceTimePtr fence, std::string annotation) { + std::lock_guard lock(mMutex); + resolveLocked(); + if (mDependencies.isFull() && !mDependencies.front().updateSignalTimes(true)) { + ALOGD("%s: Clobbering unresolved dependencies -- make me bigger!", mToken.c_str()); + } + + auto& entry = mDependencies.next(); + entry.reset(mToken.c_str()); + ALOGV("%" PRId64 "/%s: addIngress at CPU time %" PRId64 " (%s)", mDependencies.back().id, + mToken.c_str(), systemTime(), annotation.c_str()); + + mDependencies.back().ingress = {std::move(fence), std::move(annotation)}; +} + +void DependencyMonitor::addAccessCompletion(FenceTimePtr fence, std::string annotation) { + std::lock_guard lock(mMutex); + if (mDependencies.size() == 0) { + return; + } + ALOGV("%" PRId64 "/%s: addAccessCompletion at CPU time %" PRId64 " (%s)", + mDependencies.back().id, mToken.c_str(), systemTime(), annotation.c_str()); + mDependencies.back().accessCompletions.emplace_back(std::move(fence), std::move(annotation)); +} + +void DependencyMonitor::addEgress(FenceTimePtr fence, std::string annotation) { + std::lock_guard lock(mMutex); + if (mDependencies.size() == 0) { + return; + } + ALOGV("%" PRId64 "/%s: addEgress at CPU time %" PRId64 " (%s)", mDependencies.back().id, + mToken.c_str(), systemTime(), annotation.c_str()); + mDependencies.back().egress = {std::move(fence), std::move(annotation)}; +} + +void DependencyMonitor::resolveLocked() { + if (mDependencies.size() == 0) { + return; + } + + for (size_t i = mDependencies.size(); i > 0; i--) { + auto& dependencyBlock = mDependencies[i - 1]; + + if (dependencyBlock.validated) { + continue; + } + + if (!dependencyBlock.updateSignalTimes(false)) { + break; + } + + dependencyBlock.validated = true; + dependencyBlock.checkUnsafeAccess(); + } +} + +bool DependencyMonitor::DependencyBlock::updateSignalTimes(bool excludeIngress) { + if (egress.fence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { + return false; + } + + if (!excludeIngress && ingress.fence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { + return false; + } + + for (auto& accessCompletion : accessCompletions) { + if (accessCompletion.fence->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { + return false; + } + } + + return true; +} + +void DependencyMonitor::DependencyBlock::checkUnsafeAccess() const { + const nsecs_t egressTime = egress.fence->getCachedSignalTime(); + const nsecs_t ingressTime = ingress.fence->getCachedSignalTime(); + + ALOGV_IF(egressTime != Fence::SIGNAL_TIME_INVALID, + "%" PRId64 "/%s: Egress time: %" PRId64 " (%s)", token, id, egressTime, + egress.annotation.c_str()); + ALOGV_IF(Fence::isValidTimestamp(egressTime) && Fence::isValidTimestamp(ingressTime) && + egressTime < ingressTime, + "%" PRId64 "/%s: Detected egress before ingress!: %" PRId64 " (%s) < %" PRId64 " (%s)", + id, token, egressTime, egress.annotation, ingressTime, ingress.annotation.c_str()); + + for (auto& accessCompletion : accessCompletions) { + const nsecs_t accessCompletionTime = accessCompletion.fence->getCachedSignalTime(); + if (!Fence::isValidTimestamp(accessCompletionTime)) { + ALOGI("%" PRId64 "/%s: Detected invalid access completion! <%s>", id, token, + accessCompletion.annotation.c_str()); + continue; + } else { + ALOGV("%" PRId64 "/%s: Access completion time: %" PRId64 " <%s>", id, token, + accessCompletionTime, accessCompletion.annotation.c_str()); + } + + ALOGI_IF(Fence::isValidTimestamp(egressTime) && accessCompletionTime > egressTime, + "%" PRId64 "/%s: Detected access completion after egress!: %" PRId64 + " (%s) > %" PRId64 " (%s)", + id, token, accessCompletionTime, accessCompletion.annotation.c_str(), egressTime, + egress.annotation.c_str()); + + ALOGI_IF(Fence::isValidTimestamp(ingressTime) && accessCompletionTime < ingressTime, + "%" PRId64 "/%s: Detected access completion prior to ingress!: %" PRId64 + " (%s) < %" PRId64 " (%s)", + id, token, accessCompletionTime, accessCompletion.annotation.c_str(), ingressTime, + ingress.annotation.c_str()); + } + + ALOGV_IF(ingressTime != Fence::SIGNAL_TIME_INVALID, + "%" PRId64 "/%s: Ingress time: %" PRId64 " (%s)", id, token, ingressTime, + ingress.annotation.c_str()); +} + +} // namespace android
\ No newline at end of file diff --git a/libs/ui/FenceTime.cpp b/libs/ui/FenceTime.cpp index 4246c40f64..81afe9ef0e 100644 --- a/libs/ui/FenceTime.cpp +++ b/libs/ui/FenceTime.cpp @@ -59,6 +59,14 @@ FenceTime::FenceTime(nsecs_t signalTime) } } +FenceTimePtr FenceTime::makeValid(const sp<Fence>& fence) { + if (fence && fence->isValid()) { + return std::make_shared<FenceTime>(fence); + } else { + return std::make_shared<FenceTime>(systemTime()); + } +} + void FenceTime::applyTrustedSnapshot(const Snapshot& src) { if (CC_UNLIKELY(src.state != Snapshot::State::SIGNAL_TIME)) { // Applying Snapshot::State::FENCE, could change the valid state of the @@ -289,9 +297,10 @@ status_t FenceTime::Snapshot::unflatten( // ============================================================================ void FenceTimeline::push(const std::shared_ptr<FenceTime>& fence) { std::lock_guard<std::mutex> lock(mMutex); - while (mQueue.size() >= MAX_ENTRIES) { + static constexpr size_t MAX_QUEUE_SIZE = 64; + while (mQueue.size() >= MAX_QUEUE_SIZE) { // This is a sanity check to make sure the queue doesn't grow unbounded. - // MAX_ENTRIES should be big enough not to trigger this path. + // MAX_QUEUE_SIZE should be big enough not to trigger this path. // In case this path is taken though, users of FenceTime must make sure // not to rely solely on FenceTimeline to get the final timestamp and // should eventually call Fence::getSignalTime on their own. diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 18c9a6bc48..f7c94005f1 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -27,6 +27,8 @@ #include <ui/GraphicBufferMapper.h> #include <utils/Trace.h> +#include <string> + namespace android { // =========================================================================== @@ -104,6 +106,7 @@ GraphicBuffer::GraphicBuffer() usage = 0; layerCount = 0; handle = nullptr; + mDependencyMonitor.setToken(std::to_string(mId)); } // deprecated @@ -155,6 +158,8 @@ GraphicBuffer::GraphicBuffer(const GraphicBufferAllocator::AllocationRequest& re layerCount = request.layerCount; usage = request.usage; usage_deprecated = int(usage); + std::string name = request.requestorName; + mDependencyMonitor.setToken(name.append(":").append(std::to_string(mId))); } } @@ -252,6 +257,7 @@ status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight, usage = inUsage; usage_deprecated = int(usage); stride = static_cast<int>(outStride); + mDependencyMonitor.setToken(requestorName.append(":").append(std::to_string(mId))); } return err; } @@ -609,6 +615,14 @@ status_t GraphicBuffer::unflatten(void const*& buffer, size_t& size, int const*& mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts); } + std::string name; + status_t err = mBufferMapper.getName(handle, &name); + if (err != NO_ERROR) { + name = "<Unknown>"; + } + + mDependencyMonitor.setToken(name.append(":").append(std::to_string(mId))); + buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded); size -= sizeNeeded; fds += numFds; diff --git a/libs/ui/include/ui/DependencyMonitor.h b/libs/ui/include/ui/DependencyMonitor.h new file mode 100644 index 0000000000..5ad1fd9528 --- /dev/null +++ b/libs/ui/include/ui/DependencyMonitor.h @@ -0,0 +1,104 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <ui/FatVector.h> +#include <ui/FenceTime.h> +#include <ui/RingBuffer.h> + +namespace android { + +// Debugging class for that tries to add userspace logging for fence depencencies. +// The model that a DependencyMonitor tries to follow is, for each access of some resource: +// 1. There is a single ingress fence, that guards whether a resource is now safe to read from +// another system. +// 2. There are multiple access fences, that are fired when a resource is read. +// 3. There is a single egress fence, that is fired when a resource is released and sent to another +// system. +// +// Note that there can be repeated ingress and egress of a resource, but the assumption is that +// there is exactly one egress for every ingress, unless the resource is destroyed rather than +// released. +// +// The DependencyMonitor will log if there is an anomaly in the fences tracked for some resource. +// This includes: +// * If (2) happens before (1) +// * If (2) happens after (3) +// +// Note that this class has no knowledge of the "other system". I.e., if the other system ignores +// the fence reported in (3), but still takes a long time to write to the resource and produce (1), +// then nothing will be logged. That other system must have its own DependencyMonitor. Conversely, +// this class has imperfect knowledge of the system it is monitoring. For example, this class does +// not know the precise start times of reading from a resource, the exact time that a read might +// occur from a hardware unit is not known to userspace. +// +// In other words, this class logs specific classes of fence violations, but is not sensitive to +// *all* violations. One property of this is that unless the system tracked by a DependencyMonitor +// is feeding in literally incorrect fences, then there is no chance of a false positive. +// +// This class is thread safe. +class DependencyMonitor { +public: + // Sets a debug token identifying the resource this monitor is tracking. + void setToken(std::string token) { mToken = std::move(token); } + + // Adds a fence that is fired when the resource ready to be ingested by the system using the + // DependencyMonitor. + void addIngress(FenceTimePtr fence, std::string annotation); + // Adds a fence that is fired when the resource is accessed. + void addAccessCompletion(FenceTimePtr fence, std::string annotation); + // Adds a fence that is fired when the resource is released to another system. + void addEgress(FenceTimePtr fence, std::string annotation); + +private: + struct AnnotatedFenceTime { + FenceTimePtr fence; + std::string annotation; + }; + + struct DependencyBlock { + int64_t id = -1; + AnnotatedFenceTime ingress = {FenceTime::NO_FENCE, ""}; + FatVector<AnnotatedFenceTime> accessCompletions; + AnnotatedFenceTime egress = {FenceTime::NO_FENCE, ""}; + bool validated = false; + const char* token = nullptr; + + void reset(const char* newToken) { + static std::atomic<int64_t> counter = 0; + id = counter++; + ingress = {FenceTime::NO_FENCE, ""}; + accessCompletions.clear(); + egress = {FenceTime::NO_FENCE, ""}; + validated = false; + token = newToken; + } + + // Returns true if all fences in this block have valid signal times. + bool updateSignalTimes(bool excludeIngress); + + void checkUnsafeAccess() const; + }; + + void resolveLocked() REQUIRES(mMutex); + + std::string mToken; + std::mutex mMutex; + ui::RingBuffer<DependencyBlock, 10> mDependencies GUARDED_BY(mMutex); +}; + +} // namespace android
\ No newline at end of file diff --git a/libs/ui/include/ui/DisplayId.h b/libs/ui/include/ui/DisplayId.h index 937e3f1486..1e1c77b9fc 100644 --- a/libs/ui/include/ui/DisplayId.h +++ b/libs/ui/include/ui/DisplayId.h @@ -20,6 +20,7 @@ #include <ostream> #include <string> +#include <ftl/match.h> #include <ftl/optional.h> namespace android { @@ -36,7 +37,6 @@ struct DisplayId { DisplayId& operator=(const DisplayId&) = default; static constexpr DisplayId fromValue(uint64_t value) { return DisplayId(value); } - constexpr bool isVirtual() const { return value & FLAG_VIRTUAL; } uint64_t value; @@ -66,13 +66,6 @@ struct PhysicalDisplayId : DisplayId { // TODO: b/162612135 - Remove default constructor. PhysicalDisplayId() = default; - static constexpr ftl::Optional<PhysicalDisplayId> tryCast(DisplayId id) { - if (id.isVirtual()) { - return std::nullopt; - } - return PhysicalDisplayId(id); - } - // Returns a stable ID based on EDID and port information. static constexpr PhysicalDisplayId fromEdid(uint8_t port, uint16_t manufacturerId, uint32_t modelHash) { @@ -90,8 +83,6 @@ struct PhysicalDisplayId : DisplayId { return PhysicalDisplayId(value); } - constexpr uint8_t getPort() const { return static_cast<uint8_t>(value); } - private: // Flag indicating that the ID is stable across reboots. static constexpr uint64_t FLAG_STABLE = 1ULL << 62; @@ -112,13 +103,6 @@ struct VirtualDisplayId : DisplayId { // Flag indicating that this virtual display is backed by the GPU. static constexpr uint64_t FLAG_GPU = 1ULL << 61; - static constexpr std::optional<VirtualDisplayId> tryCast(DisplayId id) { - if (id.isVirtual()) { - return VirtualDisplayId(id); - } - return std::nullopt; - } - static constexpr VirtualDisplayId fromValue(uint64_t value) { return VirtualDisplayId(SkipVirtualFlag{}, value); } @@ -134,13 +118,6 @@ protected: struct HalVirtualDisplayId : VirtualDisplayId { explicit constexpr HalVirtualDisplayId(BaseId baseId) : VirtualDisplayId(baseId) {} - static constexpr std::optional<HalVirtualDisplayId> tryCast(DisplayId id) { - if (id.isVirtual() && !(id.value & FLAG_GPU)) { - return HalVirtualDisplayId(id); - } - return std::nullopt; - } - static constexpr HalVirtualDisplayId fromValue(uint64_t value) { return HalVirtualDisplayId(SkipVirtualFlag{}, value); } @@ -152,13 +129,6 @@ private: struct GpuVirtualDisplayId : VirtualDisplayId { explicit constexpr GpuVirtualDisplayId(BaseId baseId) : VirtualDisplayId(FLAG_GPU | baseId) {} - static constexpr std::optional<GpuVirtualDisplayId> tryCast(DisplayId id) { - if (id.isVirtual() && (id.value & FLAG_GPU)) { - return GpuVirtualDisplayId(id); - } - return std::nullopt; - } - static constexpr GpuVirtualDisplayId fromValue(uint64_t value) { return GpuVirtualDisplayId(SkipVirtualFlag{}, value); } @@ -172,14 +142,6 @@ private: struct HalDisplayId : DisplayId { constexpr HalDisplayId(HalVirtualDisplayId other) : DisplayId(other) {} constexpr HalDisplayId(PhysicalDisplayId other) : DisplayId(other) {} - - static constexpr std::optional<HalDisplayId> tryCast(DisplayId id) { - if (GpuVirtualDisplayId::tryCast(id)) { - return std::nullopt; - } - return HalDisplayId(id); - } - static constexpr HalDisplayId fromValue(uint64_t value) { return HalDisplayId(value); } private: @@ -187,6 +149,47 @@ private: explicit constexpr HalDisplayId(DisplayId other) : DisplayId(other) {} }; +using DisplayIdVariant = std::variant<PhysicalDisplayId, GpuVirtualDisplayId, HalVirtualDisplayId>; +using VirtualDisplayIdVariant = std::variant<GpuVirtualDisplayId, HalVirtualDisplayId>; + +template <typename DisplayIdType> +inline auto asDisplayIdOfType(DisplayIdVariant variant) -> ftl::Optional<DisplayIdType> { + return ftl::match( + variant, + [](DisplayIdType id) -> ftl::Optional<DisplayIdType> { return ftl::Optional(id); }, + [](auto) -> ftl::Optional<DisplayIdType> { return std::nullopt; }); +} + +template <typename Variant> +inline auto asHalDisplayId(Variant variant) -> ftl::Optional<HalDisplayId> { + return ftl::match( + variant, + [](GpuVirtualDisplayId) -> ftl::Optional<HalDisplayId> { return std::nullopt; }, + [](auto id) -> ftl::Optional<HalDisplayId> { + return ftl::Optional(static_cast<HalDisplayId>(id)); + }); +} + +inline auto asPhysicalDisplayId(DisplayIdVariant variant) -> ftl::Optional<PhysicalDisplayId> { + return asDisplayIdOfType<PhysicalDisplayId>(variant); +} + +inline auto asVirtualDisplayId(DisplayIdVariant variant) -> ftl::Optional<VirtualDisplayId> { + return ftl::match( + variant, + [](GpuVirtualDisplayId id) -> ftl::Optional<VirtualDisplayId> { + return ftl::Optional(static_cast<VirtualDisplayId>(id)); + }, + [](HalVirtualDisplayId id) -> ftl::Optional<VirtualDisplayId> { + return ftl::Optional(static_cast<VirtualDisplayId>(id)); + }, + [](auto) -> ftl::Optional<VirtualDisplayId> { return std::nullopt; }); +} + +inline auto asDisplayId(DisplayIdVariant variant) -> DisplayId { + return ftl::match(variant, [](auto id) -> DisplayId { return static_cast<DisplayId>(id); }); +} + static_assert(sizeof(DisplayId) == sizeof(uint64_t)); static_assert(sizeof(HalDisplayId) == sizeof(uint64_t)); static_assert(sizeof(VirtualDisplayId) == sizeof(uint64_t)); diff --git a/libs/ui/include/ui/FenceTime.h b/libs/ui/include/ui/FenceTime.h index 334106f0cf..3560d57cff 100644 --- a/libs/ui/include/ui/FenceTime.h +++ b/libs/ui/include/ui/FenceTime.h @@ -17,6 +17,7 @@ #ifndef ANDROID_FENCE_TIME_H #define ANDROID_FENCE_TIME_H +#include <stddef.h> #include <ui/Fence.h> #include <utils/Flattenable.h> #include <utils/Mutex.h> @@ -30,6 +31,8 @@ namespace android { class FenceToFenceTimeMap; +class FenceTime; +using FenceTimePtr = std::shared_ptr<FenceTime>; // A wrapper around fence that only implements isValid and getSignalTime. // It automatically closes the fence in a thread-safe manner once the signal @@ -95,6 +98,10 @@ public: FenceTime& operator=(const FenceTime&) = delete; FenceTime& operator=(FenceTime&&) = delete; + // Constructs a FenceTime, falling back to a timestamp if the fence is + // invalid. + static FenceTimePtr makeValid(const sp<Fence>& fence); + // This method should only be called when replacing the fence with // a signalTime. Since this is an indirect way of setting the signal time // of a fence, the snapshot should come from a trusted source. @@ -142,8 +149,6 @@ private: std::atomic<nsecs_t> mSignalTime{Fence::SIGNAL_TIME_INVALID}; }; -using FenceTimePtr = std::shared_ptr<FenceTime>; - // A queue of FenceTimes that are expected to signal in FIFO order. // Only maintains a queue of weak pointers so it doesn't keep references // to Fences on its own. @@ -162,8 +167,6 @@ using FenceTimePtr = std::shared_ptr<FenceTime>; // different threads. class FenceTimeline { public: - static constexpr size_t MAX_ENTRIES = 64; - void push(const std::shared_ptr<FenceTime>& fence); void updateSignalTimes(); diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index 936bf8f862..9305180ecb 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -23,6 +23,7 @@ #include <string> #include <utility> #include <vector> +#include "ui/DependencyMonitor.h" #include <android/hardware_buffer.h> #include <ui/ANativeObjectBase.h> @@ -229,6 +230,8 @@ public: void addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context); + DependencyMonitor& getDependencyMonitor() { return mDependencyMonitor; } + private: ~GraphicBuffer(); @@ -295,6 +298,8 @@ private: // and informs SurfaceFlinger that it should drop its strong pointer reference to the buffer. std::vector<std::pair<GraphicBufferDeathCallback, void* /*mDeathCallbackContext*/>> mDeathCallbacks; + + DependencyMonitor mDependencyMonitor; }; } // namespace android diff --git a/libs/ui/include/ui/StaticDisplayInfo.h b/libs/ui/include/ui/StaticDisplayInfo.h index 83da821f37..53164487f3 100644 --- a/libs/ui/include/ui/StaticDisplayInfo.h +++ b/libs/ui/include/ui/StaticDisplayInfo.h @@ -28,6 +28,7 @@ enum class DisplayConnectionType { Internal, External, ftl_last = External }; // Immutable information about physical display. struct StaticDisplayInfo { DisplayConnectionType connectionType = DisplayConnectionType::Internal; + uint8_t port; float density = 0.f; bool secure = false; std::optional<DeviceProductInfo> deviceProductInfo; diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp index 2b11786df3..d950f2a23f 100644 --- a/libs/ui/tests/Android.bp +++ b/libs/ui/tests/Android.bp @@ -45,16 +45,6 @@ cc_test { } cc_test { - name: "DisplayId_test", - shared_libs: ["libui"], - srcs: ["DisplayId_test.cpp"], - cflags: [ - "-Wall", - "-Werror", - ], -} - -cc_test { name: "DisplayIdentification_test", shared_libs: ["libui"], static_libs: ["libgmock"], diff --git a/libs/ui/tests/DisplayId_test.cpp b/libs/ui/tests/DisplayId_test.cpp deleted file mode 100644 index 209acba672..0000000000 --- a/libs/ui/tests/DisplayId_test.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <ui/DisplayId.h> - -#include <gtest/gtest.h> - -namespace android::ui { - -TEST(DisplayIdTest, createPhysicalIdFromEdid) { - constexpr uint8_t port = 1; - constexpr uint16_t manufacturerId = 13; - constexpr uint32_t modelHash = 42; - const PhysicalDisplayId id = PhysicalDisplayId::fromEdid(port, manufacturerId, modelHash); - EXPECT_EQ(port, id.getPort()); - EXPECT_FALSE(VirtualDisplayId::tryCast(id)); - EXPECT_FALSE(HalVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id)); - EXPECT_TRUE(PhysicalDisplayId::tryCast(id)); - EXPECT_TRUE(HalDisplayId::tryCast(id)); - - EXPECT_EQ(id, DisplayId::fromValue(id.value)); - EXPECT_EQ(id, PhysicalDisplayId::fromValue(id.value)); -} - -TEST(DisplayIdTest, createPhysicalIdFromPort) { - constexpr uint8_t port = 3; - const PhysicalDisplayId id = PhysicalDisplayId::fromPort(port); - EXPECT_EQ(port, id.getPort()); - EXPECT_FALSE(VirtualDisplayId::tryCast(id)); - EXPECT_FALSE(HalVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id)); - EXPECT_TRUE(PhysicalDisplayId::tryCast(id)); - EXPECT_TRUE(HalDisplayId::tryCast(id)); - - EXPECT_EQ(id, DisplayId::fromValue(id.value)); - EXPECT_EQ(id, PhysicalDisplayId::fromValue(id.value)); -} - -TEST(DisplayIdTest, createGpuVirtualId) { - const GpuVirtualDisplayId id(42); - EXPECT_TRUE(VirtualDisplayId::tryCast(id)); - EXPECT_TRUE(GpuVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(HalVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(PhysicalDisplayId::tryCast(id)); - EXPECT_FALSE(HalDisplayId::tryCast(id)); - - EXPECT_EQ(id, DisplayId::fromValue(id.value)); - EXPECT_EQ(id, GpuVirtualDisplayId::fromValue(id.value)); -} - -TEST(DisplayIdTest, createVirtualIdFromGpuVirtualId) { - const VirtualDisplayId id(GpuVirtualDisplayId(42)); - EXPECT_TRUE(VirtualDisplayId::tryCast(id)); - EXPECT_TRUE(GpuVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(HalVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(PhysicalDisplayId::tryCast(id)); - EXPECT_FALSE(HalDisplayId::tryCast(id)); - - const bool isGpuVirtualId = (id.value & VirtualDisplayId::FLAG_GPU); - EXPECT_EQ((id.isVirtual() && isGpuVirtualId), GpuVirtualDisplayId::tryCast(id).has_value()); -} - -TEST(DisplayIdTest, createHalVirtualId) { - const HalVirtualDisplayId id(42); - EXPECT_TRUE(VirtualDisplayId::tryCast(id)); - EXPECT_TRUE(HalVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(PhysicalDisplayId::tryCast(id)); - EXPECT_TRUE(HalDisplayId::tryCast(id)); - - EXPECT_EQ(id, DisplayId::fromValue(id.value)); - EXPECT_EQ(id, HalVirtualDisplayId::fromValue(id.value)); -} - -TEST(DisplayIdTest, createVirtualIdFromHalVirtualId) { - const VirtualDisplayId id(HalVirtualDisplayId(42)); - EXPECT_TRUE(VirtualDisplayId::tryCast(id)); - EXPECT_TRUE(HalVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id)); - EXPECT_FALSE(PhysicalDisplayId::tryCast(id)); - EXPECT_TRUE(HalDisplayId::tryCast(id)); - - const bool isGpuVirtualId = (id.value & VirtualDisplayId::FLAG_GPU); - EXPECT_EQ((id.isVirtual() && !isGpuVirtualId), HalVirtualDisplayId::tryCast(id).has_value()); -} - -} // namespace android::ui diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 888fcfb592..95e1c06615 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -934,6 +934,7 @@ InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy, mPendingEvent(nullptr), mLastDropReason(DropReason::NOT_DROPPED), mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER), + mWindowInfosVsyncId(-1), mMinTimeBetweenUserActivityPokes(DEFAULT_USER_ACTIVITY_POKE_INTERVAL), mConnectionManager(mLooper), mTouchStates(mWindowInfos, mConnectionManager), @@ -7049,11 +7050,6 @@ void InputDispatcher::onWindowInfosChanged(const gui::WindowInfosUpdate& update) setInputWindowsLocked(handles, displayId); } - if (update.vsyncId < mWindowInfosVsyncId) { - ALOGE("Received out of order window infos update. Last update vsync id: %" PRId64 - ", current update vsync id: %" PRId64, - mWindowInfosVsyncId, update.vsyncId); - } mWindowInfosVsyncId = update.vsyncId; } // Wake up poll loop since it may need to make new input dispatching choices. diff --git a/services/stats/Android.bp b/services/stats/Android.bp index f698515545..d588017737 100644 --- a/services/stats/Android.bp +++ b/services/stats/Android.bp @@ -29,10 +29,15 @@ cc_library_shared { "libexpresslog", "libhidlbase", "liblog", - "libstatslog", "libstatssocket", "libutils", ], + generated_sources: [ + "statslog_hidl.cpp", + ], + generated_headers: [ + "statslog_hidl.h", + ], export_include_dirs: [ "include/", ], @@ -47,3 +52,28 @@ cc_library_shared { "android.frameworks.stats-service.xml", ], } + +genrule { + name: "statslog_hidl.h", + tools: ["stats-log-api-gen"], + cmd: "$(location stats-log-api-gen)" + + " --header $(genDir)/statslog_hidl.h" + + " --module statshidl" + + " --namespace android,util,statshidl", + out: [ + "statslog_hidl.h", + ], +} + +genrule { + name: "statslog_hidl.cpp", + tools: ["stats-log-api-gen"], + cmd: "$(location stats-log-api-gen)" + + " --cpp $(genDir)/statslog_hidl.cpp" + + " --module statshidl" + + " --namespace android,util,statshidl" + + " --importHeader statslog_hidl.h", + out: [ + "statslog_hidl.cpp", + ], +} diff --git a/services/stats/StatsAidl.cpp b/services/stats/StatsAidl.cpp index b22f903654..66f7682dd8 100644 --- a/services/stats/StatsAidl.cpp +++ b/services/stats/StatsAidl.cpp @@ -26,9 +26,8 @@ #include <log/log.h> #include <stats_annotations.h> #include <stats_event.h> -#include <statslog.h> -#include <unordered_map> +#include <map> namespace { static const char* g_AtomErrorMetricName = @@ -118,8 +117,8 @@ ndk::ScopedAStatus StatsHal::reportVendorAtom(const VendorAtom& vendorAtom) { } } - // populate map for quickier access for VendorAtomValue associated annotations by value index - std::unordered_map<int, int> fieldIndexToAnnotationSetMap; + // populate map for quicker access for VendorAtomValue associated annotations by value index + std::map<int, int> fieldIndexToAnnotationSetMap; if (vendorAtom.valuesAnnotations) { const std::vector<std::optional<AnnotationSet>>& valuesAnnotations = *vendorAtom.valuesAnnotations; diff --git a/services/stats/StatsHal.cpp b/services/stats/StatsHal.cpp index 19176d9aaf..0ffa4c3947 100644 --- a/services/stats/StatsHal.cpp +++ b/services/stats/StatsHal.cpp @@ -20,7 +20,7 @@ #include "StatsHal.h" #include <log/log.h> -#include <statslog.h> +#include <statslog_hidl.h> namespace android { namespace frameworks { @@ -32,24 +32,27 @@ StatsHal::StatsHal() { } hardware::Return<void> StatsHal::reportSpeakerImpedance(const SpeakerImpedance& speakerImpedance) { - android::util::stats_write(android::util::SPEAKER_IMPEDANCE_REPORTED, - speakerImpedance.speakerLocation, speakerImpedance.milliOhms); + android::util::statshidl::stats_write(android::util::statshidl::SPEAKER_IMPEDANCE_REPORTED, + speakerImpedance.speakerLocation, + speakerImpedance.milliOhms); return hardware::Void(); } hardware::Return<void> StatsHal::reportHardwareFailed(const HardwareFailed& hardwareFailed) { - android::util::stats_write(android::util::HARDWARE_FAILED, int32_t(hardwareFailed.hardwareType), - hardwareFailed.hardwareLocation, int32_t(hardwareFailed.errorCode)); + android::util::statshidl::stats_write( + android::util::statshidl::HARDWARE_FAILED, int32_t(hardwareFailed.hardwareType), + hardwareFailed.hardwareLocation, int32_t(hardwareFailed.errorCode)); return hardware::Void(); } hardware::Return<void> StatsHal::reportPhysicalDropDetected( const PhysicalDropDetected& physicalDropDetected) { - android::util::stats_write( - android::util::PHYSICAL_DROP_DETECTED, int32_t(physicalDropDetected.confidencePctg), - physicalDropDetected.accelPeak, physicalDropDetected.freefallDuration); + android::util::statshidl::stats_write(android::util::statshidl::PHYSICAL_DROP_DETECTED, + int32_t(physicalDropDetected.confidencePctg), + physicalDropDetected.accelPeak, + physicalDropDetected.freefallDuration); return hardware::Void(); } @@ -60,19 +63,19 @@ hardware::Return<void> StatsHal::reportChargeCycles(const ChargeCycles& chargeCy for (int i = 0; i < 10 - initialSize; i++) { buckets.push_back(0); // Push 0 for buckets that do not exist. } - android::util::stats_write(android::util::CHARGE_CYCLES_REPORTED, buckets[0], buckets[1], - buckets[2], buckets[3], buckets[4], buckets[5], buckets[6], - buckets[7], buckets[8], buckets[9]); + android::util::statshidl::stats_write( + android::util::statshidl::CHARGE_CYCLES_REPORTED, buckets[0], buckets[1], buckets[2], + buckets[3], buckets[4], buckets[5], buckets[6], buckets[7], buckets[8], buckets[9]); return hardware::Void(); } hardware::Return<void> StatsHal::reportBatteryHealthSnapshot( const BatteryHealthSnapshotArgs& batteryHealthSnapshotArgs) { - android::util::stats_write( - android::util::BATTERY_HEALTH_SNAPSHOT, int32_t(batteryHealthSnapshotArgs.type), - batteryHealthSnapshotArgs.temperatureDeciC, batteryHealthSnapshotArgs.voltageMicroV, - batteryHealthSnapshotArgs.currentMicroA, + android::util::statshidl::stats_write( + android::util::statshidl::BATTERY_HEALTH_SNAPSHOT, + int32_t(batteryHealthSnapshotArgs.type), batteryHealthSnapshotArgs.temperatureDeciC, + batteryHealthSnapshotArgs.voltageMicroV, batteryHealthSnapshotArgs.currentMicroA, batteryHealthSnapshotArgs.openCircuitVoltageMicroV, batteryHealthSnapshotArgs.resistanceMicroOhm, batteryHealthSnapshotArgs.levelPercent); @@ -80,23 +83,24 @@ hardware::Return<void> StatsHal::reportBatteryHealthSnapshot( } hardware::Return<void> StatsHal::reportSlowIo(const SlowIo& slowIo) { - android::util::stats_write(android::util::SLOW_IO, int32_t(slowIo.operation), slowIo.count); + android::util::statshidl::stats_write(android::util::statshidl::SLOW_IO, + int32_t(slowIo.operation), slowIo.count); return hardware::Void(); } hardware::Return<void> StatsHal::reportBatteryCausedShutdown( const BatteryCausedShutdown& batteryCausedShutdown) { - android::util::stats_write(android::util::BATTERY_CAUSED_SHUTDOWN, - batteryCausedShutdown.voltageMicroV); + android::util::statshidl::stats_write(android::util::statshidl::BATTERY_CAUSED_SHUTDOWN, + batteryCausedShutdown.voltageMicroV); return hardware::Void(); } hardware::Return<void> StatsHal::reportUsbPortOverheatEvent( const UsbPortOverheatEvent& usbPortOverheatEvent) { - android::util::stats_write( - android::util::USB_PORT_OVERHEAT_EVENT_REPORTED, + android::util::statshidl::stats_write( + android::util::statshidl::USB_PORT_OVERHEAT_EVENT_REPORTED, usbPortOverheatEvent.plugTemperatureDeciC, usbPortOverheatEvent.maxTemperatureDeciC, usbPortOverheatEvent.timeToOverheat, usbPortOverheatEvent.timeToHysteresis, usbPortOverheatEvent.timeToInactive); @@ -105,9 +109,10 @@ hardware::Return<void> StatsHal::reportUsbPortOverheatEvent( } hardware::Return<void> StatsHal::reportSpeechDspStat(const SpeechDspStat& speechDspStat) { - android::util::stats_write(android::util::SPEECH_DSP_STAT_REPORTED, - speechDspStat.totalUptimeMillis, speechDspStat.totalDowntimeMillis, - speechDspStat.totalCrashCount, speechDspStat.totalRecoverCount); + android::util::statshidl::stats_write( + android::util::statshidl::SPEECH_DSP_STAT_REPORTED, speechDspStat.totalUptimeMillis, + speechDspStat.totalDowntimeMillis, speechDspStat.totalCrashCount, + speechDspStat.totalRecoverCount); return hardware::Void(); } diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h index 252adaa8e3..2c0a66fac3 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h @@ -34,7 +34,7 @@ class CompositionEngine; * A parameter object for creating Display instances */ struct DisplayCreationArgs { - DisplayId id; + DisplayIdVariant idVariant; // Size of the display in pixels ui::Size pixels = ui::kInvalidSize; @@ -68,8 +68,8 @@ class DisplayCreationArgsBuilder { public: DisplayCreationArgs build() { return std::move(mArgs); } - DisplayCreationArgsBuilder& setId(DisplayId id) { - mArgs.id = id; + DisplayCreationArgsBuilder& setId(DisplayIdVariant idVariant) { + mArgs.idVariant = idVariant; return *this; } diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index 780758e2a3..e2ea0f1397 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -167,6 +167,8 @@ public: // Checks if the buffer's release fence has been set virtual LayerFE::ReleaseFencePromiseStatus getReleaseFencePromiseStatus() = 0; + virtual void setReleasedBuffer(sp<GraphicBuffer> buffer) = 0; + // Indicates that the picture profile request was applied to this layer. virtual void onPictureProfileCommitted() = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index bda7856596..4266da4b07 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -170,6 +170,7 @@ public: // Returns the DisplayId the output represents, if it has one virtual ftl::Optional<DisplayId> getDisplayId() const = 0; + virtual ftl::Optional<DisplayIdVariant> getDisplayIdVariant() const = 0; // Enables (or disables) composition on this output virtual void setCompositionEnabled(bool) = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index 5519aafe11..ec87acc372 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -46,6 +46,7 @@ public: // compositionengine::Output overrides ftl::Optional<DisplayId> getDisplayId() const override; + ftl::Optional<DisplayIdVariant> getDisplayIdVariant() const override; bool isValid() const override; void dump(std::string&) const override; using compositionengine::impl::Output::setReleasedLayers; @@ -104,8 +105,11 @@ private: override; bool hasPictureProcessing() const override; int32_t getMaxLayerPictureProfiles() const override; + bool isGpuVirtualDisplay() const { + return std::holds_alternative<GpuVirtualDisplayId>(mIdVariant); + } - DisplayId mId; + DisplayIdVariant mIdVariant; bool mIsDisconnected = false; adpf::PowerAdvisor* mPowerAdvisor = nullptr; bool mHasPictureProcessing = false; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index 0ccdd22919..873764b065 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -45,6 +45,7 @@ public: // compositionengine::Output overrides bool isValid() const override; ftl::Optional<DisplayId> getDisplayId() const override; + ftl::Optional<DisplayIdVariant> getDisplayIdVariant() const override; void setCompositionEnabled(bool) override; void setLayerCachingEnabled(bool) override; void setLayerCachingTexturePoolEnabled(bool) override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index d2a5a2066c..f65a9083c5 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -52,6 +52,7 @@ public: MOCK_METHOD0(createReleaseFenceFuture, ftl::Future<FenceResult>()); MOCK_METHOD1(setReleaseFence, void(const FenceResult&)); + MOCK_METHOD1(setReleasedBuffer, void(sp<GraphicBuffer>)); MOCK_METHOD0(getReleaseFencePromiseStatus, LayerFE::ReleaseFencePromiseStatus()); MOCK_CONST_METHOD0(getDebugName, const char*()); MOCK_CONST_METHOD0(getSequence, int32_t()); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index f2c265ad2e..eaa3dd37ec 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -35,6 +35,7 @@ public: MOCK_CONST_METHOD0(isValid, bool()); MOCK_CONST_METHOD0(getDisplayId, ftl::Optional<DisplayId>()); + MOCK_CONST_METHOD0(getDisplayIdVariant, ftl::Optional<DisplayIdVariant>()); MOCK_METHOD1(setCompositionEnabled, void(bool)); MOCK_METHOD1(setLayerCachingEnabled, void(bool)); diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp index 989f8e3c5e..ab2a03cd60 100644 --- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp +++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp @@ -91,13 +91,13 @@ nsecs_t CompositionEngine::getLastFrameRefreshTimestamp() const { namespace { void offloadOutputs(Outputs& outputs) { - if (!FlagManager::getInstance().multithreaded_present() || outputs.size() < 2) { + if (outputs.size() < 2) { return; } ui::PhysicalDisplayVector<compositionengine::Output*> outputsToOffload; for (const auto& output : outputs) { - if (!ftl::Optional(output->getDisplayId()).and_then(HalDisplayId::tryCast)) { + if (!output->getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) { // Not HWC-enabled, so it is always client-composited. No need to offload. continue; } diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index 8364f4efa0..5a546777f4 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -52,7 +52,7 @@ std::shared_ptr<Display> createDisplay( Display::~Display() = default; void Display::setConfiguration(const compositionengine::DisplayCreationArgs& args) { - mId = args.id; + mIdVariant = args.idVariant; mPowerAdvisor = args.powerAdvisor; mHasPictureProcessing = args.hasPictureProcessing; mMaxLayerPictureProfiles = args.maxLayerPictureProfiles; @@ -67,7 +67,7 @@ bool Display::isValid() const { } DisplayId Display::getId() const { - return mId; + return asDisplayId(mIdVariant); } bool Display::isSecure() const { @@ -79,11 +79,15 @@ void Display::setSecure(bool secure) { } bool Display::isVirtual() const { - return mId.isVirtual(); + return !std::holds_alternative<PhysicalDisplayId>(mIdVariant); } ftl::Optional<DisplayId> Display::getDisplayId() const { - return mId; + return getId(); +} + +ftl::Optional<DisplayIdVariant> Display::getDisplayIdVariant() const { + return mIdVariant; } void Display::disconnect() { @@ -93,14 +97,14 @@ void Display::disconnect() { mIsDisconnected = true; - if (const auto id = HalDisplayId::tryCast(mId)) { + if (const auto id = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) { getCompositionEngine().getHwComposer().disconnectDisplay(*id); } } void Display::setColorTransform(const compositionengine::CompositionRefreshArgs& args) { Output::setColorTransform(args); - const auto halDisplayId = HalDisplayId::tryCast(mId); + const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>); if (mIsDisconnected || !halDisplayId || CC_LIKELY(!args.colorTransformMatrix)) { return; } @@ -108,7 +112,7 @@ void Display::setColorTransform(const compositionengine::CompositionRefreshArgs& auto& hwc = getCompositionEngine().getHwComposer(); status_t result = hwc.setColorTransform(*halDisplayId, *args.colorTransformMatrix); ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display \"%s\": %d", - to_string(mId).c_str(), result); + to_string(*halDisplayId).c_str(), result); } void Display::setColorProfile(const ColorProfile& colorProfile) { @@ -125,7 +129,7 @@ void Display::setColorProfile(const ColorProfile& colorProfile) { Output::setColorProfile(colorProfile); - const auto physicalId = PhysicalDisplayId::tryCast(mId); + const auto physicalId = getDisplayIdVariant().and_then(asPhysicalDisplayId); LOG_FATAL_IF(!physicalId); getCompositionEngine().getHwComposer().setActiveColorMode(*physicalId, colorProfile.mode, colorProfile.renderIntent); @@ -133,7 +137,7 @@ void Display::setColorProfile(const ColorProfile& colorProfile) { void Display::dump(std::string& out) const { const char* const type = isVirtual() ? "virtual" : "physical"; - base::StringAppendF(&out, "Display %s (%s, \"%s\")", to_string(mId).c_str(), type, + base::StringAppendF(&out, "Display %s (%s, \"%s\")", to_string(getId()).c_str(), type, getName().c_str()); out.append("\n Composition Display State:\n"); @@ -157,7 +161,7 @@ std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer( const sp<compositionengine::LayerFE>& layerFE) const { auto outputLayer = impl::createOutputLayer(*this, layerFE); - if (const auto halDisplayId = HalDisplayId::tryCast(mId); + if (const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>); outputLayer && !mIsDisconnected && halDisplayId) { auto& hwc = getCompositionEngine().getHwComposer(); auto hwcLayer = hwc.createLayer(*halDisplayId); @@ -171,8 +175,7 @@ std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer( void Display::setReleasedLayers(const compositionengine::CompositionRefreshArgs& refreshArgs) { Output::setReleasedLayers(refreshArgs); - if (mIsDisconnected || GpuVirtualDisplayId::tryCast(mId) || - refreshArgs.layersWithQueuedFrames.empty()) { + if (mIsDisconnected || isGpuVirtualDisplay() || refreshArgs.layersWithQueuedFrames.empty()) { return; } @@ -208,7 +211,7 @@ void Display::applyDisplayBrightness(bool applyImmediately) { if (!getState().displayBrightness) { return; } - if (auto displayId = PhysicalDisplayId::tryCast(mId)) { + if (auto displayId = getDisplayIdVariant().and_then(asPhysicalDisplayId)) { auto& hwc = getCompositionEngine().getHwComposer(); status_t result = hwc.setDisplayBrightness(*displayId, *getState().displayBrightness, getState().displayBrightnessNits, @@ -226,7 +229,7 @@ void Display::beginFrame() { Output::beginFrame(); // If we don't have a HWC display, then we are done. - const auto halDisplayId = HalDisplayId::tryCast(mId); + const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>); if (!halDisplayId) { return; } @@ -244,7 +247,7 @@ bool Display::chooseCompositionStrategy( } // If we don't have a HWC display, then we are done. - const auto halDisplayId = HalDisplayId::tryCast(mId); + const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>); if (!halDisplayId) { return false; } @@ -266,9 +269,9 @@ bool Display::chooseCompositionStrategy( } if (isPowerHintSessionEnabled()) { - mPowerAdvisor->setHwcValidateTiming(mId, hwcValidateStartTime, TimePoint::now()); - if (auto halDisplayId = HalDisplayId::tryCast(mId)) { - mPowerAdvisor->setSkippedValidate(mId, hwc.getValidateSkipped(*halDisplayId)); + mPowerAdvisor->setHwcValidateTiming(getId(), hwcValidateStartTime, TimePoint::now()); + if (auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) { + mPowerAdvisor->setSkippedValidate(*halDisplayId, hwc.getValidateSkipped(*halDisplayId)); } } @@ -292,7 +295,7 @@ void Display::applyCompositionStrategy(const std::optional<DeviceRequestedChange bool Display::getSkipColorTransform() const { auto& hwc = getCompositionEngine().getHwComposer(); - if (auto halDisplayId = HalDisplayId::tryCast(mId)) { + if (auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) { return hwc.hasDisplayCapability(*halDisplayId, DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM); } @@ -383,7 +386,7 @@ void Display::applyLayerLutsToLayers(const LayerLuts& layerLuts) { } void Display::executeCommands() { - const auto halDisplayIdOpt = HalDisplayId::tryCast(mId); + const auto halDisplayIdOpt = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>); if (mIsDisconnected || !halDisplayIdOpt) { return; } @@ -394,7 +397,7 @@ void Display::executeCommands() { compositionengine::Output::FrameFences Display::presentFrame() { auto fences = impl::Output::presentFrame(); - const auto halDisplayIdOpt = HalDisplayId::tryCast(mId); + const auto halDisplayIdOpt = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>); if (mIsDisconnected || !halDisplayIdOpt) { return fences; } @@ -404,13 +407,13 @@ compositionengine::Output::FrameFences Display::presentFrame() { const TimePoint startTime = TimePoint::now(); if (isPowerHintSessionEnabled() && getState().earliestPresentTime) { - mPowerAdvisor->setHwcPresentDelayedTime(mId, *getState().earliestPresentTime); + mPowerAdvisor->setHwcPresentDelayedTime(*halDisplayIdOpt, *getState().earliestPresentTime); } hwc.presentAndGetReleaseFences(*halDisplayIdOpt, getState().earliestPresentTime); if (isPowerHintSessionEnabled()) { - mPowerAdvisor->setHwcPresentTiming(mId, startTime, TimePoint::now()); + mPowerAdvisor->setHwcPresentTiming(*halDisplayIdOpt, startTime, TimePoint::now()); } fences.presentFence = hwc.getPresentFence(*halDisplayIdOpt); @@ -433,8 +436,8 @@ compositionengine::Output::FrameFences Display::presentFrame() { void Display::setExpensiveRenderingExpected(bool enabled) { Output::setExpensiveRenderingExpected(enabled); - if (mPowerAdvisor && !GpuVirtualDisplayId::tryCast(mId)) { - mPowerAdvisor->setExpensiveRenderingExpected(mId, enabled); + if (mPowerAdvisor && !isGpuVirtualDisplay()) { + mPowerAdvisor->setExpensiveRenderingExpected(getId(), enabled); } } @@ -449,15 +452,15 @@ bool Display::isPowerHintSessionGpuReportingEnabled() { // For ADPF GPU v0 this is expected to set start time to when the GPU commands are submitted with // fence returned, i.e. when RenderEngine flushes the commands and returns the draw fence. void Display::setHintSessionGpuStart(TimePoint startTime) { - mPowerAdvisor->setGpuStartTime(mId, startTime); + mPowerAdvisor->setGpuStartTime(getId(), startTime); } void Display::setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) { - mPowerAdvisor->setGpuFenceTime(mId, std::move(gpuFence)); + mPowerAdvisor->setGpuFenceTime(getId(), std::move(gpuFence)); } void Display::setHintSessionRequiresRenderEngine(bool requiresRenderEngine) { - mPowerAdvisor->setRequiresRenderEngine(mId, requiresRenderEngine); + mPowerAdvisor->setRequiresRenderEngine(getId(), requiresRenderEngine); } const aidl::android::hardware::graphics::composer3::OverlayProperties* @@ -478,7 +481,7 @@ void Display::finishFrame(GpuCompositionResult&& result) { // 1) It is being handled by hardware composer, which may need this to // keep its virtual display state machine in sync, or // 2) There is work to be done (the dirty region isn't empty) - if (GpuVirtualDisplayId::tryCast(mId) && !mustRecompose()) { + if (isGpuVirtualDisplay() && !mustRecompose()) { ALOGV("Skipping display composition"); return; } @@ -487,7 +490,7 @@ void Display::finishFrame(GpuCompositionResult&& result) { } bool Display::supportsOffloadPresent() const { - if (auto halDisplayId = HalDisplayId::tryCast(mId)) { + if (auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) { auto& hwc = getCompositionEngine().getHwComposer(); return hwc.hasDisplayCapability(*halDisplayId, DisplayCapability::MULTI_THREADED_PRESENT); } diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index b30cf20121..00a61a5ab6 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -118,6 +118,10 @@ ftl::Optional<DisplayId> Output::getDisplayId() const { return {}; } +ftl::Optional<DisplayIdVariant> Output::getDisplayIdVariant() const { + return {}; +} + const std::string& Output::getName() const { return mName; } @@ -436,8 +440,8 @@ void Output::prepare(const compositionengine::CompositionRefreshArgs& refreshArg ftl::Future<std::monostate> Output::present( const compositionengine::CompositionRefreshArgs& refreshArgs) { const auto stringifyExpectedPresentTime = [this, &refreshArgs]() -> std::string { - return getDisplayId() - .and_then(PhysicalDisplayId::tryCast) + return getDisplayIdVariant() + .and_then(asPhysicalDisplayId) .and_then([&refreshArgs](PhysicalDisplayId id) { return refreshArgs.frameTargets.get(id); }) @@ -890,8 +894,8 @@ void Output::writeCompositionState(const compositionengine::CompositionRefreshAr return; } - if (auto frameTargetPtrOpt = getDisplayId() - .and_then(PhysicalDisplayId::tryCast) + if (auto frameTargetPtrOpt = getDisplayIdVariant() + .and_then(asPhysicalDisplayId) .and_then([&refreshArgs](PhysicalDisplayId id) { return refreshArgs.frameTargets.get(id); })) { @@ -1672,6 +1676,7 @@ void Output::presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) { Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence); } layer->getLayerFE().setReleaseFence(releaseFence); + layer->getLayerFE().setReleasedBuffer(layer->getLayerFE().getCompositionState()->buffer); } // We've got a list of layers needing fences, that are disjoint with @@ -1841,7 +1846,7 @@ void Output::applyPictureProfile() { if (!getDisplayId()) { return; } - if (auto displayId = PhysicalDisplayId::tryCast(*getDisplayId())) { + if (auto displayId = getDisplayIdVariant().and_then(asPhysicalDisplayId)) { auto& hwc = getCompositionEngine().getHwComposer(); const status_t error = hwc.setDisplayPictureProfileHandle(*displayId, getState().pictureProfileHandle); diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp index ad65c4422e..34c09db6f8 100644 --- a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp @@ -43,6 +43,10 @@ using ::testing::ReturnRef; using ::testing::SaveArg; using ::testing::StrictMock; +static constexpr PhysicalDisplayId kDisplayId1 = PhysicalDisplayId::fromPort(123u); +static constexpr PhysicalDisplayId kDisplayId2 = PhysicalDisplayId::fromPort(234u); +static constexpr PhysicalDisplayId kDisplayId3 = PhysicalDisplayId::fromPort(567u); + struct CompositionEngineTest : public testing::Test { std::shared_ptr<TimeStats> mTimeStats; @@ -52,6 +56,31 @@ struct CompositionEngineTest : public testing::Test { std::shared_ptr<mock::Output> mOutput1{std::make_shared<StrictMock<mock::Output>>()}; std::shared_ptr<mock::Output> mOutput2{std::make_shared<StrictMock<mock::Output>>()}; std::shared_ptr<mock::Output> mOutput3{std::make_shared<StrictMock<mock::Output>>()}; + + std::array<impl::OutputCompositionState, 3> mOutputStates; + + void SetUp() override { + EXPECT_CALL(*mOutput1, getDisplayId) + .WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId1))); + EXPECT_CALL(*mOutput1, getDisplayIdVariant).WillRepeatedly(Return(kDisplayId1)); + + EXPECT_CALL(*mOutput2, getDisplayId) + .WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId2))); + EXPECT_CALL(*mOutput2, getDisplayIdVariant).WillRepeatedly(Return(kDisplayId2)); + + EXPECT_CALL(*mOutput3, getDisplayId) + .WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId3))); + EXPECT_CALL(*mOutput3, getDisplayIdVariant).WillRepeatedly(Return(kDisplayId3)); + + // Most tests will depend on the outputs being enabled. + for (auto& state : mOutputStates) { + state.isEnabled = true; + } + + EXPECT_CALL(*mOutput1, getState).WillRepeatedly(ReturnRef(mOutputStates[0])); + EXPECT_CALL(*mOutput2, getState).WillRepeatedly(ReturnRef(mOutputStates[1])); + EXPECT_CALL(*mOutput3, getState).WillRepeatedly(ReturnRef(mOutputStates[2])); + } }; TEST_F(CompositionEngineTest, canInstantiateCompositionEngine) { @@ -94,7 +123,7 @@ struct CompositionEnginePresentTest : public CompositionEngineTest { StrictMock<CompositionEnginePartialMock> mEngine; }; -TEST_F(CompositionEnginePresentTest, worksWithEmptyRequest) { +TEST_F(CompositionEnginePresentTest, zeroOutputs) { // present() always calls preComposition() and postComposition() EXPECT_CALL(mEngine, preComposition(Ref(mRefreshArgs))); EXPECT_CALL(mEngine, postComposition(Ref(mRefreshArgs))); @@ -102,7 +131,7 @@ TEST_F(CompositionEnginePresentTest, worksWithEmptyRequest) { mEngine.present(mRefreshArgs); } -TEST_F(CompositionEnginePresentTest, worksAsExpected) { +TEST_F(CompositionEnginePresentTest, threeOutputs) { // Expect calls to in a certain sequence InSequence seq; @@ -114,9 +143,7 @@ TEST_F(CompositionEnginePresentTest, worksAsExpected) { EXPECT_CALL(*mOutput2, prepare(Ref(mRefreshArgs), _)); EXPECT_CALL(*mOutput3, prepare(Ref(mRefreshArgs), _)); - // All of mOutput<i> are StrictMocks. If the flag is true, it will introduce - // calls to getDisplayId, which are not relevant to this test. - SET_FLAG_FOR_TEST(flags::multithreaded_present, false); + EXPECT_CALL(*mOutput1, supportsOffloadPresent).WillOnce(Return(false)); // The last step is to actually present each output. EXPECT_CALL(*mOutput1, present(Ref(mRefreshArgs))) @@ -284,8 +311,6 @@ struct CompositionEngineOffloadTest : public testing::Test { std::shared_ptr<mock::Output> mVirtualDisplay{std::make_shared<StrictMock<mock::Output>>()}; std::shared_ptr<mock::Output> mHalVirtualDisplay{std::make_shared<StrictMock<mock::Output>>()}; - static constexpr PhysicalDisplayId kDisplayId1 = PhysicalDisplayId::fromPort(123u); - static constexpr PhysicalDisplayId kDisplayId2 = PhysicalDisplayId::fromPort(234u); static constexpr GpuVirtualDisplayId kGpuVirtualDisplayId{789u}; static constexpr HalVirtualDisplayId kHalVirtualDisplayId{456u}; @@ -294,12 +319,23 @@ struct CompositionEngineOffloadTest : public testing::Test { void SetUp() override { EXPECT_CALL(*mDisplay1, getDisplayId) .WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId1))); + EXPECT_CALL(*mDisplay1, getDisplayIdVariant).WillRepeatedly(Return(kDisplayId1)); + EXPECT_CALL(*mDisplay2, getDisplayId) .WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId2))); + EXPECT_CALL(*mDisplay2, getDisplayIdVariant).WillRepeatedly(Return(kDisplayId2)); + EXPECT_CALL(*mVirtualDisplay, getDisplayId) .WillRepeatedly(Return(std::make_optional<DisplayId>(kGpuVirtualDisplayId))); + const DisplayIdVariant gpuVariant = + GpuVirtualDisplayId::fromValue(kGpuVirtualDisplayId.value); + EXPECT_CALL(*mVirtualDisplay, getDisplayIdVariant).WillRepeatedly(Return(gpuVariant)); + EXPECT_CALL(*mHalVirtualDisplay, getDisplayId) .WillRepeatedly(Return(std::make_optional<DisplayId>(kHalVirtualDisplayId))); + const DisplayIdVariant halVariant = + HalVirtualDisplayId::fromValue(kHalVirtualDisplayId.value); + EXPECT_CALL(*mHalVirtualDisplay, getDisplayIdVariant).WillRepeatedly(Return(halVariant)); // Most tests will depend on the outputs being enabled. for (auto& state : mOutputStates) { @@ -332,7 +368,6 @@ TEST_F(CompositionEngineOffloadTest, basic) { EXPECT_CALL(*mDisplay1, offloadPresentNextFrame).Times(1); EXPECT_CALL(*mDisplay2, offloadPresentNextFrame).Times(0); - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); setOutputs({mDisplay1, mDisplay2}); mEngine.present(mRefreshArgs); @@ -345,7 +380,6 @@ TEST_F(CompositionEngineOffloadTest, dependsOnSupport) { EXPECT_CALL(*mDisplay1, offloadPresentNextFrame).Times(0); EXPECT_CALL(*mDisplay2, offloadPresentNextFrame).Times(0); - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); setOutputs({mDisplay1, mDisplay2}); mEngine.present(mRefreshArgs); @@ -358,20 +392,6 @@ TEST_F(CompositionEngineOffloadTest, dependsOnSupport2) { EXPECT_CALL(*mDisplay1, offloadPresentNextFrame).Times(0); EXPECT_CALL(*mDisplay2, offloadPresentNextFrame).Times(0); - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); - setOutputs({mDisplay1, mDisplay2}); - - mEngine.present(mRefreshArgs); -} - -TEST_F(CompositionEngineOffloadTest, dependsOnFlag) { - EXPECT_CALL(*mDisplay1, supportsOffloadPresent).Times(0); - EXPECT_CALL(*mDisplay2, supportsOffloadPresent).Times(0); - - EXPECT_CALL(*mDisplay1, offloadPresentNextFrame).Times(0); - EXPECT_CALL(*mDisplay2, offloadPresentNextFrame).Times(0); - - SET_FLAG_FOR_TEST(flags::multithreaded_present, false); setOutputs({mDisplay1, mDisplay2}); mEngine.present(mRefreshArgs); @@ -382,7 +402,6 @@ TEST_F(CompositionEngineOffloadTest, oneDisplay) { EXPECT_CALL(*mDisplay1, offloadPresentNextFrame).Times(0); - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); setOutputs({mDisplay1}); mEngine.present(mRefreshArgs); @@ -397,7 +416,6 @@ TEST_F(CompositionEngineOffloadTest, virtualDisplay) { EXPECT_CALL(*mDisplay2, offloadPresentNextFrame).Times(0); EXPECT_CALL(*mVirtualDisplay, offloadPresentNextFrame).Times(0); - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); setOutputs({mDisplay1, mDisplay2, mVirtualDisplay}); mEngine.present(mRefreshArgs); @@ -410,7 +428,6 @@ TEST_F(CompositionEngineOffloadTest, virtualDisplay2) { EXPECT_CALL(*mDisplay1, offloadPresentNextFrame).Times(0); EXPECT_CALL(*mVirtualDisplay, offloadPresentNextFrame).Times(0); - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); setOutputs({mDisplay1, mVirtualDisplay}); mEngine.present(mRefreshArgs); @@ -423,7 +440,6 @@ TEST_F(CompositionEngineOffloadTest, halVirtual) { EXPECT_CALL(*mDisplay1, offloadPresentNextFrame).Times(1); EXPECT_CALL(*mHalVirtualDisplay, offloadPresentNextFrame).Times(0); - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); setOutputs({mDisplay1, mHalVirtualDisplay}); mEngine.present(mRefreshArgs); @@ -440,7 +456,6 @@ TEST_F(CompositionEngineOffloadTest, ordering) { EXPECT_CALL(*mDisplay1, offloadPresentNextFrame).Times(1); EXPECT_CALL(*mDisplay2, offloadPresentNextFrame).Times(0); - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); setOutputs({mVirtualDisplay, mHalVirtualDisplay, mDisplay1, mDisplay2}); mEngine.present(mRefreshArgs); @@ -458,7 +473,6 @@ TEST_F(CompositionEngineOffloadTest, dependsOnEnabled) { EXPECT_CALL(*mDisplay1, offloadPresentNextFrame).Times(0); EXPECT_CALL(*mDisplay2, offloadPresentNextFrame).Times(0); - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); setOutputs({mDisplay1, mDisplay2}); mEngine.present(mRefreshArgs); @@ -478,7 +492,6 @@ TEST_F(CompositionEngineOffloadTest, disabledDisplaysDoNotPreventOthersFromOfflo EXPECT_CALL(*mDisplay2, offloadPresentNextFrame).Times(0); EXPECT_CALL(*mHalVirtualDisplay, offloadPresentNextFrame).Times(0); - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); setOutputs({mDisplay1, mDisplay2, mHalVirtualDisplay}); mEngine.present(mRefreshArgs); diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index c1e59d01de..77fd4466ef 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -278,7 +278,7 @@ TEST_F(DisplayCreationTest, createGpuVirtualDisplay) { impl::createDisplay(mCompositionEngine, getDisplayCreationArgsForGpuVirtualDisplay()); EXPECT_FALSE(display->isSecure()); EXPECT_TRUE(display->isVirtual()); - EXPECT_TRUE(GpuVirtualDisplayId::tryCast(display->getId())); + EXPECT_TRUE(display->getDisplayIdVariant().and_then(asDisplayIdOfType<GpuVirtualDisplayId>)); } /* @@ -318,6 +318,7 @@ TEST_F(DisplaySetConfigurationTest, configuresHalVirtualDisplay) { EXPECT_EQ(HAL_VIRTUAL_DISPLAY_ID, mDisplay->getId()); EXPECT_FALSE(mDisplay->isSecure()); EXPECT_TRUE(mDisplay->isVirtual()); + EXPECT_TRUE(mDisplay->getDisplayIdVariant().and_then(asDisplayIdOfType<HalVirtualDisplayId>)); EXPECT_FALSE(mDisplay->isValid()); const auto& filter = mDisplay->getState().layerFilter; @@ -337,6 +338,7 @@ TEST_F(DisplaySetConfigurationTest, configuresGpuVirtualDisplay) { EXPECT_EQ(GPU_VIRTUAL_DISPLAY_ID, mDisplay->getId()); EXPECT_FALSE(mDisplay->isSecure()); EXPECT_TRUE(mDisplay->isVirtual()); + EXPECT_TRUE(mDisplay->getDisplayIdVariant().and_then(asDisplayIdOfType<GpuVirtualDisplayId>)); EXPECT_FALSE(mDisplay->isValid()); const auto& filter = mDisplay->getState().layerFilter; @@ -572,7 +574,7 @@ TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutIfGpuDisplay) { auto args = getDisplayCreationArgsForGpuVirtualDisplay(); std::shared_ptr<Display> gpuDisplay = createPartialMockDisplay<Display>(mCompositionEngine, args); - EXPECT_TRUE(GpuVirtualDisplayId::tryCast(gpuDisplay->getId())); + EXPECT_TRUE(gpuDisplay->getDisplayIdVariant().and_then(asDisplayIdOfType<GpuVirtualDisplayId>)); chooseCompositionStrategy(gpuDisplay.get()); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 09ad9fa497..590626ace5 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -148,20 +148,23 @@ struct OutputTest : public testing::Test { virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0; virtual ftl::Optional<DisplayId> getDisplayId() const override { return mId; } + virtual ftl::Optional<DisplayIdVariant> getDisplayIdVariant() const override { + return DisplayIdVariant(mId); + } virtual bool hasPictureProcessing() const override { return mHasPictureProcessing; } virtual int32_t getMaxLayerPictureProfiles() const override { return mMaxLayerPictureProfiles; } - void setDisplayIdForTest(DisplayId value) { mId = value; } + void setDisplayIdForTest(PhysicalDisplayId value) { mId = value; } void setHasPictureProcessingForTest(bool value) { mHasPictureProcessing = value; } void setMaxLayerPictureProfilesForTest(int32_t value) { mMaxLayerPictureProfiles = value; } private: - ftl::Optional<DisplayId> mId; + PhysicalDisplayId mId; bool mHasPictureProcessing; int32_t mMaxLayerPictureProfiles; }; @@ -3311,6 +3314,17 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSetInLayerFE) { sp<Fence> layer2Fence = sp<Fence>::make(); sp<Fence> layer3Fence = sp<Fence>::make(); + // Set up layerfe buffers + LayerFECompositionState layer1State; + layer1State.buffer = sp<GraphicBuffer>::make(); + LayerFECompositionState layer2State; + layer2State.buffer = sp<GraphicBuffer>::make(); + LayerFECompositionState layer3State; + layer3State.buffer = nullptr; + EXPECT_CALL(*mLayer1.layerFE, getCompositionState()).WillOnce(Return(&layer1State)); + EXPECT_CALL(*mLayer2.layerFE, getCompositionState()).WillOnce(Return(&layer2State)); + EXPECT_CALL(*mLayer3.layerFE, getCompositionState()).WillOnce(Return(&layer3State)); + Output::FrameFences frameFences; frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence); frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence); @@ -3327,14 +3341,23 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSetInLayerFE) { .WillOnce([&layer1Fence](FenceResult releaseFence) { EXPECT_EQ(FenceResult(layer1Fence), releaseFence); }); + EXPECT_CALL(*mLayer1.layerFE, setReleasedBuffer(_)).WillOnce([&](sp<GraphicBuffer> buffer) { + EXPECT_EQ(layer1State.buffer, buffer); + }); EXPECT_CALL(*mLayer2.layerFE, setReleaseFence(_)) .WillOnce([&layer2Fence](FenceResult releaseFence) { EXPECT_EQ(FenceResult(layer2Fence), releaseFence); }); + EXPECT_CALL(*mLayer2.layerFE, setReleasedBuffer(_)).WillOnce([&](sp<GraphicBuffer> buffer) { + EXPECT_EQ(layer2State.buffer, buffer); + }); EXPECT_CALL(*mLayer3.layerFE, setReleaseFence(_)) .WillOnce([&layer3Fence](FenceResult releaseFence) { EXPECT_EQ(FenceResult(layer3Fence), releaseFence); }); + EXPECT_CALL(*mLayer3.layerFE, setReleasedBuffer(_)).WillOnce([&](sp<GraphicBuffer> buffer) { + EXPECT_EQ(layer3State.buffer, buffer); + }); constexpr bool kFlushEvenWhenDisabled = false; mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); @@ -3350,6 +3373,17 @@ TEST_F(OutputPostFramebufferTest, setReleaseFencesIncludeClientTargetAcquireFenc frameFences.layerFences.emplace(&mLayer2.hwc2Layer, sp<Fence>::make()); frameFences.layerFences.emplace(&mLayer3.hwc2Layer, sp<Fence>::make()); + // Set up layerfe buffers + LayerFECompositionState layer1State; + layer1State.buffer = sp<GraphicBuffer>::make(); + LayerFECompositionState layer2State; + layer2State.buffer = sp<GraphicBuffer>::make(); + LayerFECompositionState layer3State; + layer3State.buffer = nullptr; + EXPECT_CALL(*mLayer1.layerFE, getCompositionState()).WillOnce(Return(&layer1State)); + EXPECT_CALL(*mLayer2.layerFE, getCompositionState()).WillOnce(Return(&layer2State)); + EXPECT_CALL(*mLayer3.layerFE, getCompositionState()).WillOnce(Return(&layer3State)); + EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences)); EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); @@ -3359,6 +3393,15 @@ TEST_F(OutputPostFramebufferTest, setReleaseFencesIncludeClientTargetAcquireFenc EXPECT_CALL(*mLayer1.layerFE, setReleaseFence).WillOnce(Return()); EXPECT_CALL(*mLayer2.layerFE, setReleaseFence).WillOnce(Return()); EXPECT_CALL(*mLayer3.layerFE, setReleaseFence).WillOnce(Return()); + EXPECT_CALL(*mLayer1.layerFE, setReleasedBuffer(_)).WillOnce([&](sp<GraphicBuffer> buffer) { + EXPECT_EQ(layer1State.buffer, buffer); + }); + EXPECT_CALL(*mLayer2.layerFE, setReleasedBuffer(_)).WillOnce([&](sp<GraphicBuffer> buffer) { + EXPECT_EQ(layer2State.buffer, buffer); + }); + EXPECT_CALL(*mLayer3.layerFE, setReleasedBuffer(_)).WillOnce([&](sp<GraphicBuffer> buffer) { + EXPECT_EQ(layer3State.buffer, buffer); + }); constexpr bool kFlushEvenWhenDisabled = false; mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } @@ -3401,7 +3444,6 @@ TEST_F(OutputPostFramebufferTest, setReleasedLayersSentPresentFence) { .WillOnce([&presentFence](FenceResult fenceResult) { EXPECT_EQ(FenceResult(presentFence), fenceResult); }); - constexpr bool kFlushEvenWhenDisabled = false; mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index b39654437f..de7d455fa4 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -26,7 +26,6 @@ #include <common/trace.h> #include <compositionengine/CompositionEngine.h> -#include <compositionengine/Display.h> #include <compositionengine/DisplayColorProfile.h> #include <compositionengine/DisplayColorProfileCreationArgs.h> #include <compositionengine/DisplayCreationArgs.h> @@ -51,17 +50,6 @@ namespace android { namespace hal = hardware::graphics::composer::hal; -namespace gui { -inline std::string_view to_string(ISurfaceComposer::OptimizationPolicy optimizationPolicy) { - switch (optimizationPolicy) { - case ISurfaceComposer::OptimizationPolicy::optimizeForPower: - return "optimizeForPower"; - case ISurfaceComposer::OptimizationPolicy::optimizeForPerformance: - return "optimizeForPerformance"; - } -} -} // namespace gui - DisplayDeviceCreationArgs::DisplayDeviceCreationArgs( const sp<SurfaceFlinger>& flinger, HWComposer& hwComposer, const wp<IBinder>& displayToken, std::shared_ptr<compositionengine::Display> compositionDisplay) @@ -308,6 +296,10 @@ DisplayId DisplayDevice::getId() const { return mCompositionDisplay->getId(); } +bool DisplayDevice::isVirtual() const { + return mCompositionDisplay->isVirtual(); +} + bool DisplayDevice::isSecure() const { return mCompositionDisplay->isSecure(); } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 02522a3deb..1b14145147 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -23,6 +23,8 @@ #include <android-base/thread_annotations.h> #include <android/native_window.h> #include <binder/IBinder.h> +#include <compositionengine/Display.h> +#include <compositionengine/DisplaySurface.h> #include <gui/LayerState.h> #include <math/mat4.h> #include <renderengine/RenderEngine.h> @@ -61,15 +63,21 @@ class SurfaceFlinger; struct CompositionInfo; struct DisplayDeviceCreationArgs; -namespace compositionengine { -class Display; -class DisplaySurface; -} // namespace compositionengine - namespace display { class DisplaySnapshot; } // namespace display +namespace gui { +inline const char* to_string(ISurfaceComposer::OptimizationPolicy optimizationPolicy) { + switch (optimizationPolicy) { + case ISurfaceComposer::OptimizationPolicy::optimizeForPower: + return "optimizeForPower"; + case ISurfaceComposer::OptimizationPolicy::optimizeForPerformance: + return "optimizeForPerformance"; + } +} +} // namespace gui + class DisplayDevice : public RefBase { public: constexpr static float sDefaultMinLumiance = 0.0; @@ -85,7 +93,7 @@ public: return mCompositionDisplay; } - bool isVirtual() const { return getId().isVirtual(); } + bool isVirtual() const; bool isPrimary() const { return mIsPrimary; } // isSecure indicates whether this display can be trusted to display @@ -123,17 +131,30 @@ public: DisplayId getId() const; + DisplayIdVariant getDisplayIdVariant() const { + const auto idVariant = mCompositionDisplay->getDisplayIdVariant(); + LOG_FATAL_IF(!idVariant); + return *idVariant; + } + + std::optional<VirtualDisplayIdVariant> getVirtualDisplayIdVariant() const { + return ftl::match( + getDisplayIdVariant(), + [](PhysicalDisplayId) { return std::optional<VirtualDisplayIdVariant>(); }, + [](auto id) { return std::optional<VirtualDisplayIdVariant>(id); }); + } + // Shorthand to upcast the ID of a display whose type is known as a precondition. PhysicalDisplayId getPhysicalId() const { - const auto id = PhysicalDisplayId::tryCast(getId()); - LOG_FATAL_IF(!id); - return *id; + const auto physicalDisplayId = asPhysicalDisplayId(getDisplayIdVariant()); + LOG_FATAL_IF(!physicalDisplayId); + return *physicalDisplayId; } VirtualDisplayId getVirtualId() const { - const auto id = VirtualDisplayId::tryCast(getId()); - LOG_FATAL_IF(!id); - return *id; + const auto virtualDisplayId = asVirtualDisplayId(getDisplayIdVariant()); + LOG_FATAL_IF(!virtualDisplayId); + return *virtualDisplayId; } const wp<IBinder>& getDisplayToken() const { return mDisplayToken; } diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp index bb6bebed8d..d547af98ea 100644 --- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp @@ -1773,7 +1773,6 @@ void AidlComposer::onHotplugDisconnect(Display display) { } bool AidlComposer::hasMultiThreadedPresentSupport(Display display) { - if (!FlagManager::getInstance().multithreaded_present()) return false; const auto displayId = translate<int64_t>(display); std::vector<AidlDisplayCapability> capabilities; const auto status = mAidlComposerClient->getDisplayCapabilities(displayId, &capabilities); diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 384f7b22c7..56ed11f07a 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -47,7 +47,8 @@ namespace android { -VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, VirtualDisplayId displayId, +VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, + VirtualDisplayIdVariant virtualIdVariant, const sp<IGraphicBufferProducer>& sink, const sp<IGraphicBufferProducer>& bqProducer, const sp<IGraphicBufferConsumer>& bqConsumer, @@ -58,7 +59,7 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, VirtualDisplayId d : ConsumerBase(bqConsumer), #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ) mHwc(hwc), - mDisplayId(displayId), + mVirtualIdVariant(virtualIdVariant), mDisplayName(name), mSource{}, mDefaultOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), @@ -119,7 +120,7 @@ VirtualDisplaySurface::~VirtualDisplaySurface() { } status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) { - if (GpuVirtualDisplayId::tryCast(mDisplayId)) { + if (isBackedByGpu()) { return NO_ERROR; } @@ -133,7 +134,7 @@ status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) { } status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) { - if (GpuVirtualDisplayId::tryCast(mDisplayId)) { + if (isBackedByGpu()) { return NO_ERROR; } @@ -181,7 +182,10 @@ status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) { } status_t VirtualDisplaySurface::advanceFrame(float hdrSdrRatio) { - if (GpuVirtualDisplayId::tryCast(mDisplayId)) { + const auto halVirtualDisplayId = ftl::match( + mVirtualIdVariant, [](HalVirtualDisplayId id) { return ftl::Optional(id); }, + [](auto) { return ftl::Optional<HalVirtualDisplayId>(); }); + if (!halVirtualDisplayId) { return NO_ERROR; } @@ -212,11 +216,8 @@ status_t VirtualDisplaySurface::advanceFrame(float hdrSdrRatio) { VDS_LOGV("%s: fb=%d(%p) out=%d(%p)", __func__, mFbProducerSlot, fbBuffer.get(), mOutputProducerSlot, outBuffer.get()); - const auto halDisplayId = HalVirtualDisplayId::tryCast(mDisplayId); - LOG_FATAL_IF(!halDisplayId); - // At this point we know the output buffer acquire fence, - // so update HWC state with it. - mHwc.setOutputBuffer(*halDisplayId, mOutputFence, outBuffer); + // At this point we know the output buffer acquire fence, so update HWC state with it. + mHwc.setOutputBuffer(*halVirtualDisplayId, mOutputFence, outBuffer); status_t result = NO_ERROR; if (fbBuffer != nullptr) { @@ -227,7 +228,7 @@ status_t VirtualDisplaySurface::advanceFrame(float hdrSdrRatio) { hwcBuffer = fbBuffer; // HWC hasn't previously seen this buffer in this slot } // TODO: Correctly propagate the dataspace from GL composition - result = mHwc.setClientTarget(*halDisplayId, mFbProducerSlot, mFbFence, hwcBuffer, + result = mHwc.setClientTarget(*halVirtualDisplayId, mFbProducerSlot, mFbFence, hwcBuffer, ui::Dataspace::UNKNOWN, hdrSdrRatio); } @@ -235,8 +236,8 @@ status_t VirtualDisplaySurface::advanceFrame(float hdrSdrRatio) { } void VirtualDisplaySurface::onFrameCommitted() { - const auto halDisplayId = HalVirtualDisplayId::tryCast(mDisplayId); - if (!halDisplayId) { + const auto halDisplayId = asHalDisplayId(mVirtualIdVariant); + if (!halDisplayId.has_value()) { return; } @@ -250,8 +251,7 @@ void VirtualDisplaySurface::onFrameCommitted() { Mutex::Autolock lock(mMutex); int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot); VDS_LOGV("%s: release scratch sslot=%d", __func__, sslot); - addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], - retireFence); + addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], retireFence); releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot]); } @@ -299,7 +299,7 @@ const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const { status_t VirtualDisplaySurface::requestBuffer(int pslot, sp<GraphicBuffer>* outBuf) { - if (GpuVirtualDisplayId::tryCast(mDisplayId)) { + if (isBackedByGpu()) { return mSource[SOURCE_SINK]->requestBuffer(pslot, outBuf); } @@ -321,7 +321,7 @@ status_t VirtualDisplaySurface::setAsyncMode(bool async) { status_t VirtualDisplaySurface::dequeueBuffer(Source source, PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) { - LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value()); + LOG_ALWAYS_FATAL_IF(isBackedByGpu()); status_t result = mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight, @@ -373,7 +373,7 @@ status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, uint PixelFormat format, uint64_t usage, uint64_t* outBufferAge, FrameEventHistoryDelta* outTimestamps) { - if (GpuVirtualDisplayId::tryCast(mDisplayId)) { + if (isBackedByGpu()) { return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage, outBufferAge, outTimestamps); } @@ -459,7 +459,7 @@ status_t VirtualDisplaySurface::attachBuffer(int*, const sp<GraphicBuffer>&) { status_t VirtualDisplaySurface::queueBuffer(int pslot, const QueueBufferInput& input, QueueBufferOutput* output) { - if (GpuVirtualDisplayId::tryCast(mDisplayId)) { + if (isBackedByGpu()) { return mSource[SOURCE_SINK]->queueBuffer(pslot, input, output); } @@ -517,7 +517,7 @@ status_t VirtualDisplaySurface::queueBuffer(int pslot, status_t VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) { - if (GpuVirtualDisplayId::tryCast(mDisplayId)) { + if (isBackedByGpu()) { return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK, pslot), fence); } @@ -621,7 +621,10 @@ void VirtualDisplaySurface::resetPerFrameState() { } status_t VirtualDisplaySurface::refreshOutputBuffer() { - LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value()); + const auto halVirtualDisplayId = ftl::match( + mVirtualIdVariant, [](HalVirtualDisplayId id) { return ftl::Optional(id); }, + [](auto) { return ftl::Optional<HalVirtualDisplayId>(); }); + LOG_ALWAYS_FATAL_IF(!halVirtualDisplayId); if (mOutputProducerSlot >= 0) { mSource[SOURCE_SINK]->cancelBuffer( @@ -640,14 +643,16 @@ status_t VirtualDisplaySurface::refreshOutputBuffer() { // until after GPU calls queueBuffer(). So here we just set the buffer // (for use in HWC prepare) but not the fence; we'll call this again with // the proper fence once we have it. - const auto halDisplayId = HalVirtualDisplayId::tryCast(mDisplayId); - LOG_FATAL_IF(!halDisplayId); - result = mHwc.setOutputBuffer(*halDisplayId, Fence::NO_FENCE, + result = mHwc.setOutputBuffer(*halVirtualDisplayId, Fence::NO_FENCE, mProducerBuffers[mOutputProducerSlot]); return result; } +bool VirtualDisplaySurface::isBackedByGpu() const { + return std::holds_alternative<GpuVirtualDisplayId>(mVirtualIdVariant); +} + // This slot mapping function is its own inverse, so two copies are unnecessary. // Both are kept to make the intent clear where the function is called, and for // the (unlikely) chance that we switch to a different mapping function. diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 90426f729a..cb65c79152 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -75,7 +75,8 @@ class VirtualDisplaySurface : public compositionengine::DisplaySurface, public BnGraphicBufferProducer, private ConsumerBase { public: - VirtualDisplaySurface(HWComposer&, VirtualDisplayId, const sp<IGraphicBufferProducer>& sink, + VirtualDisplaySurface(HWComposer&, VirtualDisplayIdVariant, + const sp<IGraphicBufferProducer>& sink, const sp<IGraphicBufferProducer>& bqProducer, const sp<IGraphicBufferConsumer>& bqConsumer, const std::string& name); @@ -145,6 +146,7 @@ private: void updateQueueBufferOutput(QueueBufferOutput&&); void resetPerFrameState(); status_t refreshOutputBuffer(); + bool isBackedByGpu() const; // Both the sink and scratch buffer pools have their own set of slots // ("source slots", or "sslot"). We have to merge these into the single @@ -159,7 +161,7 @@ private: // Immutable after construction // HWComposer& mHwc; - const VirtualDisplayId mDisplayId; + const VirtualDisplayIdVariant mVirtualIdVariant; const std::string mDisplayName; sp<IGraphicBufferProducer> mSource[2]; // indexed by SOURCE_* uint32_t mDefaultOutputFormat; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 95a7170fbb..2e312827f2 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -722,6 +722,10 @@ void Layer::callReleaseBufferCallback(const sp<ITransactionCompletedListener>& l uint32_t currentMaxAcquiredBufferCount = mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid); + if (FlagManager::getInstance().monitor_buffer_fences()) { + buffer->getDependencyMonitor().addEgress(FenceTime::makeValid(fence), "Layer release"); + } + if (listener) { listener->onReleaseBuffer(callbackId, fence, currentMaxAcquiredBufferCount); } @@ -940,6 +944,7 @@ bool Layer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer, std::max(mDrawingState.frameNumber, mDrawingState.barrierFrameNumber); mDrawingState.releaseBufferListener = bufferData.releaseBufferListener; + mDrawingState.previousBuffer = std::move(mDrawingState.buffer); mDrawingState.buffer = std::move(buffer); mDrawingState.acquireFence = bufferData.flags.test(BufferData::BufferDataChange::fenceChanged) ? bufferData.acquireFence @@ -1122,6 +1127,7 @@ bool Layer::setTransactionCompletedListeners(const std::vector<sp<CallbackHandle handle->acquireTimeOrFence = mCallbackHandleAcquireTimeOrFence; handle->frameNumber = mDrawingState.frameNumber; handle->previousFrameNumber = mDrawingState.previousFrameNumber; + handle->previousBuffer = mDrawingState.previousBuffer; if (mPreviousReleaseBufferEndpoint == handle->listener) { // Add fence from previous screenshot now so that it can be dispatched to the // client. @@ -1433,8 +1439,8 @@ void Layer::onCompositionPresented(const DisplayDevice* display, presentFence, FrameTracer::FrameEvent::PRESENT_FENCE); mDeprecatedFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence)); - } else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId()); - displayId && mFlinger->getHwComposer().isConnected(*displayId)) { + } else if (const auto displayId = asPhysicalDisplayId(display->getDisplayIdVariant()); + displayId.has_value() && mFlinger->getHwComposer().isConnected(*displayId)) { // The HWC doesn't support present fences, so use the present timestamp instead. const nsecs_t presentTimestamp = mFlinger->getHwComposer().getPresentTimestamp(*displayId); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 081bb22246..88754f9fa3 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -117,6 +117,7 @@ public: uint32_t bufferTransform; bool transformToDisplayInverse; Region transparentRegionHint; + std::shared_ptr<renderengine::ExternalTexture> previousBuffer; std::shared_ptr<renderengine::ExternalTexture> buffer; sp<Fence> acquireFence; std::shared_ptr<FenceTime> acquireFenceTime; diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp index b6192685ae..5e076bdae4 100644 --- a/services/surfaceflinger/LayerFE.cpp +++ b/services/surfaceflinger/LayerFE.cpp @@ -410,6 +410,15 @@ void LayerFE::setReleaseFence(const FenceResult& releaseFence) { if (mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::FULFILLED) { return; } + + if (releaseFence.has_value()) { + if (FlagManager::getInstance().monitor_buffer_fences()) { + if (auto strongBuffer = mReleasedBuffer.promote()) { + strongBuffer->getDependencyMonitor() + .addAccessCompletion(FenceTime::makeValid(releaseFence.value()), "HWC"); + } + } + } mReleaseFence.set_value(releaseFence); mReleaseFencePromiseStatus = ReleaseFencePromiseStatus::FULFILLED; } @@ -428,6 +437,10 @@ LayerFE::ReleaseFencePromiseStatus LayerFE::getReleaseFencePromiseStatus() { return mReleaseFencePromiseStatus; } +void LayerFE::setReleasedBuffer(sp<GraphicBuffer> buffer) { + mReleasedBuffer = std::move(buffer); +} + void LayerFE::setLastHwcState(const LayerFE::HwcLayerDebugState &state) { mLastHwcState = state; } diff --git a/services/surfaceflinger/LayerFE.h b/services/surfaceflinger/LayerFE.h index a537456beb..b89b6b4b92 100644 --- a/services/surfaceflinger/LayerFE.h +++ b/services/surfaceflinger/LayerFE.h @@ -18,6 +18,7 @@ #include <android/gui/CachingHint.h> #include <gui/LayerMetadata.h> +#include <ui/GraphicBuffer.h> #include <ui/LayerStack.h> #include <ui/PictureProfileHandle.h> @@ -58,6 +59,7 @@ public: ftl::Future<FenceResult> createReleaseFenceFuture() override; void setReleaseFence(const FenceResult& releaseFence) override; LayerFE::ReleaseFencePromiseStatus getReleaseFencePromiseStatus() override; + void setReleasedBuffer(sp<GraphicBuffer> buffer) override; void onPictureProfileCommitted() override; // Used for debugging purposes, e.g. perfetto tracing, dumpsys. @@ -95,6 +97,7 @@ private: std::promise<FenceResult> mReleaseFence; ReleaseFencePromiseStatus mReleaseFencePromiseStatus = ReleaseFencePromiseStatus::UNINITIALIZED; HwcLayerDebugState mLastHwcState; + wp<GraphicBuffer> mReleasedBuffer; }; } // namespace android diff --git a/services/surfaceflinger/LayerVector.h b/services/surfaceflinger/LayerVector.h index 38dc11d3bc..81155fd697 100644 --- a/services/surfaceflinger/LayerVector.h +++ b/services/surfaceflinger/LayerVector.h @@ -49,7 +49,8 @@ public: using Visitor = std::function<void(Layer*)>; private: - const StateSet mStateSet; + // FIXME: This is set but not used anywhere. + [[maybe_unused]] const StateSet mStateSet; }; } diff --git a/services/surfaceflinger/PowerAdvisor/SessionManager.h b/services/surfaceflinger/PowerAdvisor/SessionManager.h index 93a80b55ab..afa52eb260 100644 --- a/services/surfaceflinger/PowerAdvisor/SessionManager.h +++ b/services/surfaceflinger/PowerAdvisor/SessionManager.h @@ -68,7 +68,8 @@ private: bool isLayerRelevant(int32_t layerId); // The UID of whoever created our ISessionManager connection - const uid_t mUid; + // FIXME: This is set but is not used anywhere. + [[maybe_unused]] const uid_t mUid; // State owned by the main thread @@ -99,4 +100,4 @@ private: }; } // namespace adpf -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/QueuedTransactionState.h b/services/surfaceflinger/QueuedTransactionState.h index 86683da26c..6a17a0d0cb 100644 --- a/services/surfaceflinger/QueuedTransactionState.h +++ b/services/surfaceflinger/QueuedTransactionState.h @@ -25,6 +25,7 @@ #include <common/FlagManager.h> #include <ftl/flags.h> #include <gui/LayerState.h> +#include <gui/TransactionState.h> #include <system/window.h> namespace android { @@ -50,33 +51,26 @@ public: struct QueuedTransactionState { QueuedTransactionState() = default; - QueuedTransactionState(const FrameTimelineInfo& frameTimelineInfo, - std::vector<ResolvedComposerState>& composerStates, - const Vector<DisplayState>& displayStates, uint32_t transactionFlags, - const sp<IBinder>& applyToken, - const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime, bool isAutoTimestamp, - std::vector<uint64_t> uncacheBufferIds, int64_t postTime, - bool hasListenerCallbacks, - std::vector<ListenerCallbacks> listenerCallbacks, int originPid, - int originUid, uint64_t transactionId, - std::vector<uint64_t> mergedTransactionIds) - : frameTimelineInfo(frameTimelineInfo), - states(std::move(composerStates)), - displays(displayStates), - flags(transactionFlags), - applyToken(applyToken), - inputWindowCommands(inputWindowCommands), - desiredPresentTime(desiredPresentTime), - isAutoTimestamp(isAutoTimestamp), + QueuedTransactionState(TransactionState&& transactionState, + std::vector<ResolvedComposerState>&& composerStates, + std::vector<uint64_t>&& uncacheBufferIds, int64_t postTime, + int originPid, int originUid) + : frameTimelineInfo(std::move(transactionState.mFrameTimelineInfo)), + states(composerStates), + displays(std::move(transactionState.mDisplayStates)), + flags(transactionState.mFlags), + applyToken(transactionState.mApplyToken), + inputWindowCommands(std::move(transactionState.mInputWindowCommands)), + desiredPresentTime(transactionState.mDesiredPresentTime), + isAutoTimestamp(transactionState.mIsAutoTimestamp), uncacheBufferIds(std::move(uncacheBufferIds)), postTime(postTime), - hasListenerCallbacks(hasListenerCallbacks), - listenerCallbacks(listenerCallbacks), + hasListenerCallbacks(transactionState.mHasListenerCallbacks), + listenerCallbacks(std::move(transactionState.mListenerCallbacks)), originPid(originPid), originUid(originUid), - id(transactionId), - mergedTransactionIds(std::move(mergedTransactionIds)) {} + id(transactionState.getId()), + mergedTransactionIds(std::move(transactionState.mMergedTransactionIds)) {} // Invokes `void(const layer_state_t&)` visitor for matching layers. template <typename Visitor> @@ -135,7 +129,7 @@ struct QueuedTransactionState { FrameTimelineInfo frameTimelineInfo; std::vector<ResolvedComposerState> states; - Vector<DisplayState> displays; + std::vector<DisplayState> displays; uint32_t flags; sp<IBinder> applyToken; InputWindowCommands inputWindowCommands; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 514adac20c..615492a872 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -348,7 +348,7 @@ void RegionSamplingThread::captureSample() { SurfaceFlinger::ScreenshotArgs screenshotArgs; screenshotArgs.captureTypeVariant = displayWeak; - screenshotArgs.displayId = std::nullopt; + screenshotArgs.displayIdVariant = std::nullopt; screenshotArgs.sourceCrop = sampledBounds.isEmpty() ? layerStackSpaceRect : sampledBounds; screenshotArgs.reqSize = sampledBounds.getSize(); screenshotArgs.dataspace = ui::Dataspace::V0_SRGB; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index e587178ec2..911d4894ce 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -554,8 +554,7 @@ void Scheduler::resyncAllToHardwareVsync(bool allowToEnable) { ftl::FakeGuard guard(kMainThreadContext); for (const auto& [id, display] : mDisplays) { - if (display.powerMode != hal::PowerMode::OFF || - !FlagManager::getInstance().multithreaded_present()) { + if (display.powerMode != hal::PowerMode::OFF) { resyncToHardwareVsyncLocked(id, allowToEnable); } } diff --git a/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositionCoverage.h b/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositionCoverage.h index 767462dfce..70ae940b65 100644 --- a/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositionCoverage.h +++ b/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositionCoverage.h @@ -36,7 +36,7 @@ enum class CompositionCoverage : std::uint8_t { using CompositionCoverageFlags = ftl::Flags<CompositionCoverage>; -using CompositionCoveragePerDisplay = ui::DisplayMap<DisplayId, CompositionCoverageFlags>; +using CompositionCoveragePerDisplay = ui::DisplayMap<DisplayIdVariant, CompositionCoverageFlags>; inline CompositionCoverageFlags multiDisplayUnion(const CompositionCoveragePerDisplay& displays) { CompositionCoverageFlags coverage; diff --git a/services/surfaceflinger/ScreenCaptureOutput.cpp b/services/surfaceflinger/ScreenCaptureOutput.cpp index af6d4d30e4..2906bbd5b8 100644 --- a/services/surfaceflinger/ScreenCaptureOutput.cpp +++ b/services/surfaceflinger/ScreenCaptureOutput.cpp @@ -30,11 +30,12 @@ namespace android { std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutputArgs args) { std::shared_ptr<ScreenCaptureOutput> output = compositionengine::impl::createOutputTemplated< ScreenCaptureOutput, compositionengine::CompositionEngine, - /* sourceCrop */ const Rect, std::optional<DisplayId>, + /* sourceCrop */ const Rect, ftl::Optional<DisplayIdVariant>, const compositionengine::Output::ColorProfile&, /* layerAlpha */ float, - /* regionSampling */ bool>(args.compositionEngine, args.sourceCrop, args.displayId, - args.colorProfile, args.layerAlpha, args.regionSampling, + /* regionSampling */ bool>(args.compositionEngine, args.sourceCrop, + args.displayIdVariant, args.colorProfile, args.layerAlpha, + args.regionSampling, args.dimInGammaSpaceForEnhancedScreenshots, args.enableLocalTonemapping); output->editState().isSecure = args.isSecure; @@ -59,8 +60,8 @@ std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutp { std::string name = args.regionSampling ? "RegionSampling" : "ScreenCaptureOutput"; - if (args.displayId) { - base::StringAppendF(&name, " for %" PRIu64, args.displayId.value().value); + if (const auto id = args.displayIdVariant.and_then(asDisplayIdOfType<DisplayId>)) { + base::StringAppendF(&name, " for %" PRIu64, id->value); } output->setName(name); } @@ -68,12 +69,12 @@ std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutp } ScreenCaptureOutput::ScreenCaptureOutput( - const Rect sourceCrop, std::optional<DisplayId> displayId, + const Rect sourceCrop, ftl::Optional<DisplayIdVariant> displayIdVariant, const compositionengine::Output::ColorProfile& colorProfile, float layerAlpha, bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots, bool enableLocalTonemapping) : mSourceCrop(sourceCrop), - mDisplayId(displayId), + mDisplayIdVariant(displayIdVariant), mColorProfile(colorProfile), mLayerAlpha(layerAlpha), mRegionSampling(regionSampling), @@ -137,12 +138,9 @@ ScreenCaptureOutput::generateLuts() { } std::vector<aidl::android::hardware::graphics::composer3::Luts> luts; - if (mDisplayId) { - const auto id = PhysicalDisplayId::tryCast(mDisplayId.value()); - if (id) { - auto& hwc = getCompositionEngine().getHwComposer(); - hwc.getLuts(*id, buffers, &luts); - } + if (const auto physicalDisplayId = mDisplayIdVariant.and_then(asPhysicalDisplayId)) { + auto& hwc = getCompositionEngine().getHwComposer(); + hwc.getLuts(*physicalDisplayId, buffers, &luts); } if (buffers.size() == luts.size()) { diff --git a/services/surfaceflinger/ScreenCaptureOutput.h b/services/surfaceflinger/ScreenCaptureOutput.h index b3e98b1a32..d4e20fc2f3 100644 --- a/services/surfaceflinger/ScreenCaptureOutput.h +++ b/services/surfaceflinger/ScreenCaptureOutput.h @@ -30,7 +30,7 @@ struct ScreenCaptureOutputArgs { ui::LayerStack layerStack; Rect sourceCrop; std::shared_ptr<renderengine::ExternalTexture> buffer; - std::optional<DisplayId> displayId; + ftl::Optional<DisplayIdVariant> displayIdVariant; ui::Size reqBufferSize; float sdrWhitePointNits; float displayBrightnessNits; @@ -51,7 +51,7 @@ struct ScreenCaptureOutputArgs { // SurfaceFlinger::captureLayers and SurfaceFlinger::captureDisplay. class ScreenCaptureOutput : public compositionengine::impl::Output { public: - ScreenCaptureOutput(const Rect sourceCrop, std::optional<DisplayId> displayId, + ScreenCaptureOutput(const Rect sourceCrop, ftl::Optional<DisplayIdVariant> displayIdVariant, const compositionengine::Output::ColorProfile& colorProfile, float layerAlpha, bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots, bool enableLocalTonemapping); @@ -70,7 +70,7 @@ protected: private: std::unordered_map<int32_t, aidl::android::hardware::graphics::composer3::Luts> generateLuts(); const Rect mSourceCrop; - const std::optional<DisplayId> mDisplayId; + const ftl::Optional<DisplayIdVariant> mDisplayIdVariant; const compositionengine::Output::ColorProfile& mColorProfile; const float mLayerAlpha; const bool mRegionSampling; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0029bfc63e..aa933ee8a7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -659,12 +659,14 @@ void SurfaceFlinger::enableHalVirtualDisplays(bool enable) { } } -VirtualDisplayId SurfaceFlinger::acquireVirtualDisplay(ui::Size resolution, ui::PixelFormat format, - const std::string& uniqueId) { +std::optional<VirtualDisplayIdVariant> SurfaceFlinger::acquireVirtualDisplay( + ui::Size resolution, ui::PixelFormat format, const std::string& uniqueId, + compositionengine::DisplayCreationArgsBuilder& builder) { if (auto& generator = mVirtualDisplayIdGenerators.hal) { if (const auto id = generator->generateId()) { if (getHwComposer().allocateVirtualDisplay(*id, resolution, &format)) { acquireVirtualDisplaySnapshot(*id, uniqueId); + builder.setId(*id); return *id; } @@ -679,22 +681,23 @@ VirtualDisplayId SurfaceFlinger::acquireVirtualDisplay(ui::Size resolution, ui:: const auto id = mVirtualDisplayIdGenerators.gpu.generateId(); LOG_ALWAYS_FATAL_IF(!id, "Failed to generate ID for GPU virtual display"); acquireVirtualDisplaySnapshot(*id, uniqueId); + builder.setId(*id); return *id; } -void SurfaceFlinger::releaseVirtualDisplay(VirtualDisplayId displayId) { - if (const auto id = HalVirtualDisplayId::tryCast(displayId)) { - if (auto& generator = mVirtualDisplayIdGenerators.hal) { - generator->releaseId(*id); - releaseVirtualDisplaySnapshot(*id); - } - return; - } - - const auto id = GpuVirtualDisplayId::tryCast(displayId); - LOG_ALWAYS_FATAL_IF(!id); - mVirtualDisplayIdGenerators.gpu.releaseId(*id); - releaseVirtualDisplaySnapshot(*id); +void SurfaceFlinger::releaseVirtualDisplay(VirtualDisplayIdVariant displayId) { + ftl::match( + displayId, + [this](HalVirtualDisplayId halVirtualDisplayId) { + if (auto& generator = mVirtualDisplayIdGenerators.hal) { + generator->releaseId(halVirtualDisplayId); + releaseVirtualDisplaySnapshot(halVirtualDisplayId); + } + }, + [this](GpuVirtualDisplayId gpuVirtualDisplayId) { + mVirtualDisplayIdGenerators.gpu.releaseId(gpuVirtualDisplayId); + releaseVirtualDisplaySnapshot(gpuVirtualDisplayId); + }); } void SurfaceFlinger::releaseVirtualDisplaySnapshot(VirtualDisplayId displayId) { @@ -1182,6 +1185,7 @@ status_t SurfaceFlinger::getStaticDisplayInfo(int64_t displayId, ui::StaticDispl const auto& snapshot = snapshotRef.get(); info->connectionType = snapshot.connectionType(); + info->port = snapshot.port(); info->deviceProductInfo = snapshot.deviceProductInfo(); if (mEmulatedDisplayDensity) { @@ -1265,7 +1269,17 @@ void SurfaceFlinger::getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo*& info ui::FrameRateCategoryRate frameRateCategoryRate(normal.getValue(), high.getValue()); info->frameRateCategoryRate = frameRateCategoryRate; - info->supportedRefreshRates = display->refreshRateSelector().getSupportedFrameRates(); + if (info->hasArrSupport) { + info->supportedRefreshRates = display->refreshRateSelector().getSupportedFrameRates(); + } else { + // On non-ARR devices, list the refresh rates same as the supported display modes. + std::vector<float> supportedFrameRates; + supportedFrameRates.reserve(info->supportedDisplayModes.size()); + std::transform(info->supportedDisplayModes.begin(), info->supportedDisplayModes.end(), + std::back_inserter(supportedFrameRates), + [](ui::DisplayMode mode) { return mode.peakRefreshRate; }); + info->supportedRefreshRates = supportedFrameRates; + } info->activeColorMode = display->getCompositionDisplay()->getState().colorMode; info->hdrCapabilities = filterOut4k30(display->getHdrCapabilities()); @@ -2863,9 +2877,9 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( // output. Layer stacks are not tracked in Display when we iterate through // frameTargeters. Cross-referencing layer stacks allows us to filter out displays // by ID with duplicate layer stacks before adding them to CompositionEngine output. - ui::DisplayMap<DisplayId, ui::LayerStack> physicalDisplayLayerStacks; + ui::DisplayMap<PhysicalDisplayId, ui::LayerStack> physicalDisplayLayerStacks; for (auto& [_, display] : displays) { - const auto id = PhysicalDisplayId::tryCast(display->getId()); + const auto id = asPhysicalDisplayId(display->getDisplayIdVariant()); if (id && frameTargeters.contains(*id)) { physicalDisplayLayerStacks.try_emplace(*id, display->getLayerStack()); } @@ -3131,7 +3145,7 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( for (const auto& [_, display] : displays) { const auto& state = display->getCompositionDisplay()->getState(); CompositionCoverageFlags& flags = - mCompositionCoverage.try_emplace(display->getId()).first->second; + mCompositionCoverage.try_emplace(display->getDisplayIdVariant()).first->second; if (state.usesDeviceComposition) { flags |= CompositionCoverage::Hwc; @@ -3185,8 +3199,8 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( CompositeResultsPerDisplay resultsPerDisplay; // Filter out virtual displays. - for (const auto& [id, coverage] : mCompositionCoverage) { - if (const auto idOpt = PhysicalDisplayId::tryCast(id)) { + for (const auto& [idVar, coverage] : mCompositionCoverage) { + if (const auto idOpt = asPhysicalDisplayId(idVar)) { resultsPerDisplay.try_emplace(*idOpt, CompositeResult{coverage}); } } @@ -3224,16 +3238,12 @@ bool SurfaceFlinger::isHdrLayer(const frontend::LayerSnapshot& snapshot) const { return false; } -ui::Rotation SurfaceFlinger::getPhysicalDisplayOrientation(DisplayId displayId, +ui::Rotation SurfaceFlinger::getPhysicalDisplayOrientation(PhysicalDisplayId displayId, bool isPrimary) const { - const auto id = PhysicalDisplayId::tryCast(displayId); - if (!id) { - return ui::ROTATION_0; - } if (!mIgnoreHwcPhysicalDisplayOrientation && getHwComposer().getComposer()->isSupported( Hwc2::Composer::OptionalFeature::PhysicalDisplayOrientation)) { - switch (getHwComposer().getPhysicalDisplayOrientation(*id)) { + switch (getHwComposer().getPhysicalDisplayOrientation(displayId)) { case Hwc2::AidlTransform::ROT_90: return ui::ROTATION_90; case Hwc2::AidlTransform::ROT_180: @@ -3881,13 +3891,17 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( creationArgs.hasWideColorGamut = false; creationArgs.supportedPerFrameMetadata = 0; - if (const auto physicalIdOpt = PhysicalDisplayId::tryCast(compositionDisplay->getId())) { + if (const auto physicalIdOpt = + compositionDisplay->getDisplayIdVariant().and_then(asPhysicalDisplayId)) { const auto physicalId = *physicalIdOpt; creationArgs.isPrimary = physicalId == getPrimaryDisplayIdLocked(); creationArgs.refreshRateSelector = FTL_FAKE_GUARD(kMainThreadContext, mDisplayModeController.selectorPtrFor(physicalId)); + creationArgs.physicalOrientation = + getPhysicalDisplayOrientation(physicalId, creationArgs.isPrimary); + ALOGV("Display Orientation: %s", toCString(creationArgs.physicalOrientation)); mPhysicalDisplays.get(physicalId) .transform(&PhysicalDisplay::snapshotRef) @@ -3900,7 +3914,8 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( })); } - if (const auto id = HalDisplayId::tryCast(compositionDisplay->getId())) { + if (const auto id = compositionDisplay->getDisplayIdVariant().and_then( + asHalDisplayId<DisplayIdVariant>)) { getHwComposer().getHdrCapabilities(*id, &creationArgs.hdrCapabilities); creationArgs.supportedPerFrameMetadata = getHwComposer().getSupportedPerFrameMetadata(*id); } @@ -3916,10 +3931,6 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( nativeWindow->setSwapInterval(nativeWindow.get(), 0); } - creationArgs.physicalOrientation = - getPhysicalDisplayOrientation(compositionDisplay->getId(), creationArgs.isPrimary); - ALOGV("Display Orientation: %s", toCString(creationArgs.physicalOrientation)); - if (FlagManager::getInstance().correct_virtual_display_power_state()) { creationArgs.initialPowerMode = state.initialPowerMode; } else { @@ -3949,7 +3960,8 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( mode.getPeakFps()); } - display->setLayerFilter(makeLayerFilterForDisplay(display->getId(), state.layerStack)); + display->setLayerFilter( + makeLayerFilterForDisplay(display->getDisplayIdVariant(), state.layerStack)); display->setProjection(state.orientation, state.layerStackSpaceRect, state.orientedDisplaySpaceRect); display->setDisplayName(state.displayName); @@ -4005,10 +4017,12 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, } compositionengine::DisplayCreationArgsBuilder builder; + std::optional<VirtualDisplayIdVariant> virtualDisplayIdVariantOpt; if (const auto& physical = state.physical) { builder.setId(physical->id); } else { - builder.setId(acquireVirtualDisplay(resolution, pixelFormat, state.uniqueId)); + virtualDisplayIdVariantOpt = + acquireVirtualDisplay(resolution, pixelFormat, state.uniqueId, builder); } builder.setPixels(resolution); @@ -4028,10 +4042,10 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, getFactory().createBufferQueue(&bqProducer, &bqConsumer, /*consumerIsSurfaceFlinger =*/false); if (state.isVirtual()) { - const auto displayId = VirtualDisplayId::tryCast(compositionDisplay->getId()); - LOG_FATAL_IF(!displayId); - auto surface = sp<VirtualDisplaySurface>::make(getHwComposer(), *displayId, state.surface, - bqProducer, bqConsumer, state.displayName); + LOG_FATAL_IF(!virtualDisplayIdVariantOpt); + auto surface = sp<VirtualDisplaySurface>::make(getHwComposer(), *virtualDisplayIdVariantOpt, + state.surface, bqProducer, bqConsumer, + state.displayName); displaySurface = surface; producer = std::move(surface); } else { @@ -4039,18 +4053,17 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, "adding a supported display, but rendering " "surface is provided (%p), ignoring it", state.surface.get()); - const auto displayId = PhysicalDisplayId::tryCast(compositionDisplay->getId()); - LOG_FATAL_IF(!displayId); #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ) const auto frameBufferSurface = - sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqProducer, bqConsumer, + sp<FramebufferSurface>::make(getHwComposer(), state.physical->id, bqProducer, + bqConsumer, state.physical->activeMode->getResolution(), ui::Size(maxGraphicsWidth, maxGraphicsHeight)); displaySurface = frameBufferSurface; producer = frameBufferSurface->getSurface()->getIGraphicBufferProducer(); #else displaySurface = - sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqConsumer, + sp<FramebufferSurface>::make(getHwComposer(), state.physical->id, bqConsumer, state.physical->activeMode->getResolution(), ui::Size(maxGraphicsWidth, maxGraphicsHeight)); producer = bqProducer; @@ -4107,8 +4120,8 @@ void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { if (display) { display->disconnect(); - if (display->isVirtual()) { - releaseVirtualDisplay(display->getVirtualId()); + if (const auto virtualDisplayIdVariant = display->getVirtualDisplayIdVariant()) { + releaseVirtualDisplay(*virtualDisplayIdVariant); } else { mScheduler->unregisterDisplay(display->getPhysicalId(), mActiveDisplayId); } @@ -4151,8 +4164,8 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, if (currentBinder != drawingBinder || currentState.sequenceId != drawingState.sequenceId) { if (const auto display = getDisplayDeviceLocked(displayToken)) { display->disconnect(); - if (display->isVirtual()) { - releaseVirtualDisplay(display->getVirtualId()); + if (const auto virtualDisplayIdVariant = display->getVirtualDisplayIdVariant()) { + releaseVirtualDisplay(*virtualDisplayIdVariant); } if (display->isRefreshable()) { @@ -4184,8 +4197,8 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, if (const auto display = getDisplayDeviceLocked(displayToken)) { if (currentState.layerStack != drawingState.layerStack) { - display->setLayerFilter( - makeLayerFilterForDisplay(display->getId(), currentState.layerStack)); + display->setLayerFilter(makeLayerFilterForDisplay(display->getDisplayIdVariant(), + currentState.layerStack)); } if (currentState.flags != drawingState.flags) { display->setFlags(currentState.flags); @@ -4427,7 +4440,7 @@ void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos, void SurfaceFlinger::updateCursorAsync() { compositionengine::CompositionRefreshArgs refreshArgs; for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { - if (HalDisplayId::tryCast(display->getId())) { + if (asHalDisplayId(display->getDisplayIdVariant())) { refreshArgs.outputs.push_back(display->getCompositionDisplay()); } } @@ -5015,13 +5028,7 @@ bool SurfaceFlinger::shouldLatchUnsignaled(const layer_state_t& state, size_t nu return true; } -status_t SurfaceFlinger::setTransactionState( - const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states, - Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, - InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, - const std::vector<client_cache_t>& uncacheBuffers, bool hasListenerCallbacks, - const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId, - const std::vector<uint64_t>& mergedTransactionIds) { +status_t SurfaceFlinger::setTransactionState(TransactionState&& transactionState) { SFTRACE_CALL(); IPCThreadState* ipc = IPCThreadState::self(); @@ -5029,7 +5036,7 @@ status_t SurfaceFlinger::setTransactionState( const int originUid = ipc->getCallingUid(); uint32_t permissions = LayerStatePermissions::getTransactionPermissions(originPid, originUid); ftl::Flags<adpf::Workload> queuedWorkload; - for (auto& composerState : states) { + for (auto& composerState : transactionState.mComposerStates) { composerState.state.sanitize(permissions); if (composerState.state.what & layer_state_t::COMPOSITION_EFFECTS) { queuedWorkload |= adpf::Workload::EFFECTS; @@ -5039,27 +5046,27 @@ status_t SurfaceFlinger::setTransactionState( } } - for (DisplayState& display : displays) { + for (DisplayState& display : transactionState.mDisplayStates) { display.sanitize(permissions); } - if (!inputWindowCommands.empty() && + if (!transactionState.mInputWindowCommands.empty() && (permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) == 0) { ALOGE("Only privileged callers are allowed to send input commands."); - inputWindowCommands.clear(); + transactionState.mInputWindowCommands.clear(); } - if (flags & (eEarlyWakeupStart | eEarlyWakeupEnd)) { + if (transactionState.mFlags & (eEarlyWakeupStart | eEarlyWakeupEnd)) { const bool hasPermission = (permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER) || callingThreadHasPermission(sWakeupSurfaceFlinger); if (!hasPermission) { ALOGE("Caller needs permission android.permission.WAKEUP_SURFACE_FLINGER to use " "eEarlyWakeup[Start|End] flags"); - flags &= ~(eEarlyWakeupStart | eEarlyWakeupEnd); + transactionState.mFlags &= ~(eEarlyWakeupStart | eEarlyWakeupEnd); } } - if (flags & eEarlyWakeupStart) { + if (transactionState.mFlags & eEarlyWakeupStart) { queuedWorkload |= adpf::Workload::WAKEUP; } mPowerAdvisor->setQueuedWorkload(queuedWorkload); @@ -5067,8 +5074,8 @@ status_t SurfaceFlinger::setTransactionState( const int64_t postTime = systemTime(); std::vector<uint64_t> uncacheBufferIds; - uncacheBufferIds.reserve(uncacheBuffers.size()); - for (const auto& uncacheBuffer : uncacheBuffers) { + uncacheBufferIds.reserve(transactionState.mUncacheBuffers.size()); + for (const auto& uncacheBuffer : transactionState.mUncacheBuffers) { sp<GraphicBuffer> buffer = ClientCache::getInstance().erase(uncacheBuffer); if (buffer != nullptr) { uncacheBufferIds.push_back(buffer->getId()); @@ -5076,8 +5083,8 @@ status_t SurfaceFlinger::setTransactionState( } std::vector<ResolvedComposerState> resolvedStates; - resolvedStates.reserve(states.size()); - for (auto& state : states) { + resolvedStates.reserve(transactionState.mComposerStates.size()); + for (auto& state : transactionState.mComposerStates) { resolvedStates.emplace_back(std::move(state)); auto& resolvedState = resolvedStates.back(); resolvedState.layerId = LayerHandle::getLayerId(resolvedState.state.surface); @@ -5088,9 +5095,15 @@ status_t SurfaceFlinger::setTransactionState( layer->getDebugName() : std::to_string(resolvedState.state.layerId); resolvedState.externalTexture = getExternalTextureFromBufferData(*resolvedState.state.bufferData, - layerName.c_str(), transactionId); + layerName.c_str(), transactionState.getId()); if (resolvedState.externalTexture) { resolvedState.state.bufferData->buffer = resolvedState.externalTexture->getBuffer(); + if (FlagManager::getInstance().monitor_buffer_fences()) { + resolvedState.state.bufferData->buffer->getDependencyMonitor() + .addIngress(FenceTime::makeValid( + resolvedState.state.bufferData->acquireFence), + "Incoming txn"); + } } mBufferCountTracker.increment(resolvedState.layerId); } @@ -5110,22 +5123,12 @@ status_t SurfaceFlinger::setTransactionState( } } - QueuedTransactionState state{frameTimelineInfo, - resolvedStates, - displays, - flags, - applyToken, - std::move(inputWindowCommands), - desiredPresentTime, - isAutoTimestamp, + QueuedTransactionState state{std::move(transactionState), + std::move(resolvedStates), std::move(uncacheBufferIds), postTime, - hasListenerCallbacks, - listenerCallbacks, originPid, - originUid, - transactionId, - mergedTransactionIds}; + originUid}; state.workloadHint = queuedWorkload; if (mTransactionTracing) { @@ -5148,16 +5151,16 @@ status_t SurfaceFlinger::setTransactionState( for (const auto& [displayId, data] : mNotifyExpectedPresentMap) { if (data.hintStatus.load() == NotifyExpectedPresentHintStatus::ScheduleOnTx) { - scheduleNotifyExpectedPresentHint(displayId, VsyncId{frameTimelineInfo.vsyncId}); + scheduleNotifyExpectedPresentHint(displayId, VsyncId{state.frameTimelineInfo.vsyncId}); } } - setTransactionFlags(eTransactionFlushNeeded, schedule, applyToken, frameHint); + setTransactionFlags(eTransactionFlushNeeded, schedule, state.applyToken, frameHint); return NO_ERROR; } bool SurfaceFlinger::applyTransactionState( const FrameTimelineInfo& frameTimelineInfo, std::vector<ResolvedComposerState>& states, - Vector<DisplayState>& displays, uint32_t flags, + std::span<DisplayState> displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector<uint64_t>& uncacheBufferIds, const int64_t postTime, bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, @@ -5647,7 +5650,8 @@ void SurfaceFlinger::initializeDisplays() { auto layerStack = ui::DEFAULT_LAYER_STACK.id; for (const auto& [id, display] : FTL_FAKE_GUARD(mStateLock, mPhysicalDisplays)) { - state.displays.push(DisplayState(display.token(), ui::LayerStack::fromValue(layerStack++))); + state.displays.emplace_back( + DisplayState(display.token(), ui::LayerStack::fromValue(layerStack++))); } std::vector<QueuedTransactionState> transactions; @@ -5715,7 +5719,13 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa incRefreshableDisplays(); } + if (displayId == mActiveDisplayId && + FlagManager::getInstance().correct_virtual_display_power_state()) { + applyOptimizationPolicy(__func__); + } + const auto activeMode = display->refreshRateSelector().getActiveMode().modePtr; + using OptimizationPolicy = gui::ISurfaceComposer::OptimizationPolicy; if (currentMode == hal::PowerMode::OFF) { // Turn on the display @@ -5730,22 +5740,20 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa onActiveDisplayChangedLocked(activeDisplay.get(), *display); } - if (displayId == mActiveDisplayId) { - if (FlagManager::getInstance().correct_virtual_display_power_state()) { - applyOptimizationPolicy("setPhysicalDisplayPowerMode(ON)"); - } else { - disablePowerOptimizations("setPhysicalDisplayPowerMode(ON)"); - } + if (displayId == mActiveDisplayId && + !FlagManager::getInstance().correct_virtual_display_power_state()) { + optimizeThreadScheduling("setPhysicalDisplayPowerMode(ON/DOZE)", + OptimizationPolicy::optimizeForPerformance); } getHwComposer().setPowerMode(displayId, mode); - if (mode != hal::PowerMode::DOZE_SUSPEND && - (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present())) { + if (mode != hal::PowerMode::DOZE_SUSPEND) { const bool enable = mScheduler->getVsyncSchedule(displayId)->getPendingHardwareVsyncState(); requestHardwareVsync(displayId, enable); - if (displayId == mActiveDisplayId) { + if (displayId == mActiveDisplayId && + !FlagManager::getInstance().correct_virtual_display_power_state()) { mScheduler->enableSyntheticVsync(false); } @@ -5762,21 +5770,18 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa if (const auto display = getActivatableDisplay()) { onActiveDisplayChangedLocked(activeDisplay.get(), *display); } else { - if (FlagManager::getInstance().correct_virtual_display_power_state()) { - applyOptimizationPolicy("setPhysicalDisplayPowerMode(OFF)"); - } else { - enablePowerOptimizations("setPhysicalDisplayPowerMode(OFF)"); + if (!FlagManager::getInstance().correct_virtual_display_power_state()) { + optimizeThreadScheduling("setPhysicalDisplayPowerMode(OFF)", + OptimizationPolicy::optimizeForPower); } - if (currentModeNotDozeSuspend) { - if (!FlagManager::getInstance().multithreaded_present()) { - mScheduler->disableHardwareVsync(displayId, true); - } + if (currentModeNotDozeSuspend && + !FlagManager::getInstance().correct_virtual_display_power_state()) { mScheduler->enableSyntheticVsync(); } } } - if (currentModeNotDozeSuspend && FlagManager::getInstance().multithreaded_present()) { + if (currentModeNotDozeSuspend) { constexpr bool kDisallow = true; mScheduler->disableHardwareVsync(displayId, kDisallow); } @@ -5794,24 +5799,25 @@ void SurfaceFlinger::setPhysicalDisplayPowerMode(const sp<DisplayDevice>& displa } else if (mode == hal::PowerMode::DOZE || mode == hal::PowerMode::ON) { // Update display while dozing getHwComposer().setPowerMode(displayId, mode); - if (currentMode == hal::PowerMode::DOZE_SUSPEND && - (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present())) { + if (currentMode == hal::PowerMode::DOZE_SUSPEND) { if (displayId == mActiveDisplayId) { ALOGI("Force repainting for DOZE_SUSPEND -> DOZE or ON."); mVisibleRegionsDirty = true; scheduleRepaint(); - mScheduler->enableSyntheticVsync(false); + if (!FlagManager::getInstance().correct_virtual_display_power_state()) { + mScheduler->enableSyntheticVsync(false); + } } constexpr bool kAllowToEnable = true; mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get()); } } else if (mode == hal::PowerMode::DOZE_SUSPEND) { // Leave display going to doze - if (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present()) { - constexpr bool kDisallow = true; - mScheduler->disableHardwareVsync(displayId, kDisallow); - } - if (displayId == mActiveDisplayId) { + constexpr bool kDisallow = true; + mScheduler->disableHardwareVsync(displayId, kDisallow); + + if (displayId == mActiveDisplayId && + !FlagManager::getInstance().correct_virtual_display_power_state()) { mScheduler->enableSyntheticVsync(); } getHwComposer().setPowerMode(displayId, mode); @@ -5850,43 +5856,44 @@ void SurfaceFlinger::setVirtualDisplayPowerMode(const sp<DisplayDevice>& display to_string(displayId).c_str()); } -bool SurfaceFlinger::shouldOptimizeForPerformance() { - for (const auto& [_, display] : mDisplays) { - // Displays that are optimized for power are always powered on and should not influence - // whether there is an active display for the purpose of power optimization, etc. If these - // displays are being shown somewhere, a different (physical or virtual) display that is - // optimized for performance will be powered on in addition. Displays optimized for - // performance will change power mode, so if they are off then they are not active. - if (display->isPoweredOn() && - display->getOptimizationPolicy() == - gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance) { - return true; - } - } - return false; -} - -void SurfaceFlinger::enablePowerOptimizations(const char* whence) { - ALOGD("%s: Enabling power optimizations", whence); - - setSchedAttr(false, whence); - setSchedFifo(false, whence); -} - -void SurfaceFlinger::disablePowerOptimizations(const char* whence) { - ALOGD("%s: Disabling power optimizations", whence); +void SurfaceFlinger::optimizeThreadScheduling( + const char* whence, gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy) { + ALOGD("%s: Optimizing thread scheduling: %s", whence, to_string(optimizationPolicy)); + const bool optimizeForPerformance = + optimizationPolicy == gui::ISurfaceComposer::OptimizationPolicy::optimizeForPerformance; // TODO: b/281692563 - Merge the syscalls. For now, keep uclamp in a separate syscall // and set it before SCHED_FIFO due to b/190237315. - setSchedAttr(true, whence); - setSchedFifo(true, whence); + setSchedAttr(optimizeForPerformance, whence); + setSchedFifo(optimizeForPerformance, whence); } void SurfaceFlinger::applyOptimizationPolicy(const char* whence) { - if (shouldOptimizeForPerformance()) { - disablePowerOptimizations(whence); - } else { - enablePowerOptimizations(whence); + using OptimizationPolicy = gui::ISurfaceComposer::OptimizationPolicy; + + const bool optimizeForPerformance = + std::any_of(mDisplays.begin(), mDisplays.end(), [](const auto& pair) { + const auto& display = pair.second; + return display->isPoweredOn() && + display->getOptimizationPolicy() == + OptimizationPolicy::optimizeForPerformance; + }); + + optimizeThreadScheduling(whence, + optimizeForPerformance ? OptimizationPolicy::optimizeForPerformance + : OptimizationPolicy::optimizeForPower); + + if (mScheduler) { + const bool disableSyntheticVsync = + std::any_of(mDisplays.begin(), mDisplays.end(), [](const auto& pair) { + const auto& display = pair.second; + const hal::PowerMode powerMode = display->getPowerMode(); + return powerMode != hal::PowerMode::OFF && + powerMode != hal::PowerMode::DOZE_SUSPEND && + display->getOptimizationPolicy() == + OptimizationPolicy::optimizeForPerformance; + }); + mScheduler->enableSyntheticVsync(!disableSyntheticVsync); } } @@ -6110,17 +6117,15 @@ void SurfaceFlinger::dumpDisplays(std::string& result) const { for (const auto& [token, display] : mDisplays) { if (display->isVirtual()) { - const auto displayId = display->getId(); + const VirtualDisplayId virtualId = display->getVirtualId(); utils::Dumper::Section section(dumper, - ftl::Concat("Virtual Display ", displayId.value).str()); + ftl::Concat("Virtual Display ", virtualId.value).str()); display->dump(dumper); - if (const auto virtualIdOpt = VirtualDisplayId::tryCast(displayId)) { - std::lock_guard lock(mVirtualDisplaysMutex); - const auto virtualSnapshotIt = mVirtualDisplays.find(virtualIdOpt.value()); - if (virtualSnapshotIt != mVirtualDisplays.end()) { - virtualSnapshotIt->second.dump(dumper); - } + std::lock_guard lock(mVirtualDisplaysMutex); + const auto virtualSnapshotIt = mVirtualDisplays.find(virtualId); + if (virtualSnapshotIt != mVirtualDisplays.end()) { + virtualSnapshotIt->second.dump(dumper); } } } @@ -6128,7 +6133,7 @@ void SurfaceFlinger::dumpDisplays(std::string& result) const { void SurfaceFlinger::dumpDisplayIdentificationData(std::string& result) const { for (const auto& [token, display] : mDisplays) { - const auto displayId = PhysicalDisplayId::tryCast(display->getId()); + const auto displayId = asPhysicalDisplayId(display->getDisplayIdVariant()); if (!displayId) { continue; } @@ -6337,7 +6342,7 @@ perfetto::protos::LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t t void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const { for (const auto& [token, display] : mDisplays) { - const auto displayId = HalDisplayId::tryCast(display->getId()); + const auto displayId = asHalDisplayId(display->getDisplayIdVariant()); if (!displayId) { continue; } @@ -7404,7 +7409,7 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, } wp<const DisplayDevice> displayWeak; - DisplayId displayId; + ftl::Optional<DisplayIdVariant> displayIdVariantOpt; ui::LayerStack layerStack; ui::Size reqSize(args.width, args.height); std::unordered_set<uint32_t> excludeLayerIds; @@ -7420,7 +7425,7 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, return; } displayWeak = display; - displayId = display->getId(); + displayIdVariantOpt = display->getDisplayIdVariant(); layerStack = display->getLayerStack(); displayIsSecure = display->isSecure(); @@ -7448,7 +7453,7 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, ScreenshotArgs screenshotArgs; screenshotArgs.captureTypeVariant = displayWeak; - screenshotArgs.displayId = displayId; + screenshotArgs.displayIdVariant = displayIdVariantOpt; screenshotArgs.sourceCrop = gui::aidl_utils::fromARect(captureArgs.sourceCrop); if (screenshotArgs.sourceCrop.isEmpty()) { screenshotArgs.sourceCrop = layerStackSpaceRect; @@ -7467,6 +7472,7 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args const sp<IScreenCaptureListener>& captureListener) { ui::LayerStack layerStack; wp<const DisplayDevice> displayWeak; + ftl::Optional<DisplayIdVariant> displayIdVariantOpt; ui::Size size; Rect layerStackSpaceRect; bool displayIsSecure; @@ -7482,6 +7488,7 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args } displayWeak = display; + displayIdVariantOpt = display->getDisplayIdVariant(); layerStack = display->getLayerStack(); layerStackSpaceRect = display->getLayerStackSpaceRect(); size = display->getLayerStackSpaceRect().getSize(); @@ -7516,7 +7523,7 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args ScreenshotArgs screenshotArgs; screenshotArgs.captureTypeVariant = displayWeak; - screenshotArgs.displayId = displayId; + screenshotArgs.displayIdVariant = displayIdVariantOpt; screenshotArgs.sourceCrop = layerStackSpaceRect; screenshotArgs.reqSize = size; screenshotArgs.dataspace = static_cast<ui::Dataspace>(args.dataspace); @@ -8008,7 +8015,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( .layerStack = layerStack, .sourceCrop = args.sourceCrop, .buffer = std::move(buffer), - .displayId = args.displayId, + .displayIdVariant = args.displayIdVariant, .reqBufferSize = args.reqSize, .sdrWhitePointNits = args.sdrWhitePointNits, .displayBrightnessNits = args.displayBrightnessNits, @@ -8408,8 +8415,8 @@ sp<DisplayDevice> SurfaceFlinger::getActivatableDisplay() const { // TODO(b/255635821): Choose the pacesetter display, considering both internal and external // displays. For now, pick the other internal display, assuming a dual-display foldable. return findDisplay([this](const DisplayDevice& display) REQUIRES(mStateLock) { - const auto idOpt = PhysicalDisplayId::tryCast(display.getId()); - return idOpt && *idOpt != mActiveDisplayId && display.isPoweredOn() && + const auto idOpt = asPhysicalDisplayId(display.getDisplayIdVariant()); + return idOpt.has_value() && *idOpt != mActiveDisplayId && display.isPoweredOn() && mPhysicalDisplays.get(*idOpt) .transform(&PhysicalDisplay::isInternal) .value_or(false); @@ -8946,6 +8953,7 @@ binder::Status SurfaceComposerAIDL::getStaticDisplayInfo(int64_t displayId, if (status == NO_ERROR) { // convert ui::StaticDisplayInfo to gui::StaticDisplayInfo outInfo->connectionType = static_cast<gui::DisplayConnectionType>(info.connectionType); + outInfo->port = info.port; outInfo->density = info.density; outInfo->secure = info.secure; outInfo->installOrientation = static_cast<gui::Rotation>(info.installOrientation); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 37f362fd21..f61214cc65 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -160,6 +160,7 @@ class DisplaySurface; class OutputLayer; struct CompositionRefreshArgs; +class DisplayCreationArgsBuilder; } // namespace compositionengine namespace renderengine { @@ -544,13 +545,7 @@ private: } sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const; - status_t setTransactionState( - const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& state, - Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, - InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, - bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers, - bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks, - uint64_t transactionId, const std::vector<uint64_t>& mergedTransactionIds) override; + status_t setTransactionState(TransactionState&&) override; void bootFinished(); status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const; sp<IDisplayEventConnection> createDisplayEventConnection( @@ -738,19 +733,14 @@ private: void setVirtualDisplayPowerMode(const sp<DisplayDevice>& display, hal::PowerMode mode) REQUIRES(mStateLock, kMainThreadContext); - // Returns whether to optimize globally for performance instead of power. - bool shouldOptimizeForPerformance() REQUIRES(mStateLock); - - // Turns on power optimizations, for example when there are no displays to be optimized for - // performance. - static void enablePowerOptimizations(const char* whence); - - // Turns off power optimizations. - static void disablePowerOptimizations(const char* whence); + // Adjusts thread scheduling according to the optimization policy + static void optimizeThreadScheduling( + const char* whence, gui::ISurfaceComposer::OptimizationPolicy optimizationPolicy); // Enables or disables power optimizations depending on whether there are displays that should // be optimized for performance. - void applyOptimizationPolicy(const char* whence) REQUIRES(mStateLock); + void applyOptimizationPolicy(const char* whence) REQUIRES(kMainThreadContext) + REQUIRES(mStateLock); // Returns the preferred mode for PhysicalDisplayId if the Scheduler has selected one for that // display. Falls back to the display's defaultModeId otherwise. @@ -797,7 +787,7 @@ private: */ bool applyTransactionState(const FrameTimelineInfo& info, std::vector<ResolvedComposerState>& state, - Vector<DisplayState>& displays, uint32_t flags, + std::span<DisplayState> displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector<uint64_t>& uncacheBufferIds, @@ -891,7 +881,7 @@ private: std::variant<int32_t, wp<const DisplayDevice>> captureTypeVariant; // Display ID of the display the result will be on - std::optional<DisplayId> displayId{std::nullopt}; + ftl::Optional<DisplayIdVariant> displayIdVariant{std::nullopt}; // If true, transform is inverted from the parent layer snapshot bool childrenOnly{false}; @@ -1045,10 +1035,10 @@ private: // region of all screens presenting this layer stack. void invalidateLayerStack(const ui::LayerFilter& layerFilter, const Region& dirty); - ui::LayerFilter makeLayerFilterForDisplay(DisplayId displayId, ui::LayerStack layerStack) + ui::LayerFilter makeLayerFilterForDisplay(DisplayIdVariant displayId, ui::LayerStack layerStack) REQUIRES(mStateLock) { return {layerStack, - PhysicalDisplayId::tryCast(displayId) + asPhysicalDisplayId(displayId) .and_then(display::getPhysicalDisplay(mPhysicalDisplays)) .transform(&display::PhysicalDisplay::isInternal) .value_or(false)}; @@ -1141,8 +1131,10 @@ private: void enableHalVirtualDisplays(bool); // Virtual display lifecycle for ID generation and HAL allocation. - VirtualDisplayId acquireVirtualDisplay(ui::Size, ui::PixelFormat, const std::string& uniqueId) - REQUIRES(mStateLock); + std::optional<VirtualDisplayIdVariant> acquireVirtualDisplay( + ui::Size, ui::PixelFormat, const std::string& uniqueId, + compositionengine::DisplayCreationArgsBuilder&) REQUIRES(mStateLock); + template <typename ID> void acquireVirtualDisplaySnapshot(ID displayId, const std::string& uniqueId) { std::lock_guard lock(mVirtualDisplaysMutex); @@ -1153,7 +1145,7 @@ private: } } - void releaseVirtualDisplay(VirtualDisplayId); + void releaseVirtualDisplay(VirtualDisplayIdVariant displayId); void releaseVirtualDisplaySnapshot(VirtualDisplayId displayId); // Returns a display other than `mActiveDisplayId` that can be activated, if any. @@ -1238,7 +1230,7 @@ private: bool isHdrLayer(const frontend::LayerSnapshot& snapshot) const; - ui::Rotation getPhysicalDisplayOrientation(DisplayId, bool isPrimary) const + ui::Rotation getPhysicalDisplayOrientation(PhysicalDisplayId, bool isPrimary) const REQUIRES(mStateLock); void traverseLegacyLayers(const LayerVector::Visitor& visitor) const REQUIRES(kMainThreadContext); diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp index 3297c16113..6bbc04cf6f 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp @@ -321,7 +321,7 @@ QueuedTransactionState TransactionProtoParser::fromProto( int32_t displayCount = proto.display_changes_size(); t.displays.reserve(static_cast<size_t>(displayCount)); for (int i = 0; i < displayCount; i++) { - t.displays.add(fromProto(proto.display_changes(i))); + t.displays.emplace_back(fromProto(proto.display_changes(i))); } return t; } diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index b22ec66819..2e8c8c1111 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -18,7 +18,7 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" -//#define LOG_NDEBUG 0 +// #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "TransactionCallbackInvoker" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -28,6 +28,7 @@ #include "Utils/FenceUtils.h" #include <binder/IInterface.h> +#include <common/FlagManager.h> #include <common/trace.h> #include <utils/RefBase.h> @@ -142,8 +143,17 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp<CallbackHandle>& handle->transformHint, handle->currentMaxAcquiredBufferCount, eventStats, handle->previousReleaseCallbackId); + if (handle->bufferReleaseChannel && handle->previousReleaseCallbackId != ReleaseCallbackId::INVALID_ID) { + if (FlagManager::getInstance().monitor_buffer_fences()) { + if (auto previousBuffer = handle->previousBuffer.lock()) { + previousBuffer->getBuffer() + ->getDependencyMonitor() + .addEgress(FenceTime::makeValid(handle->previousReleaseFence), + "Txn release"); + } + } mBufferReleases.emplace_back(handle->name, handle->bufferReleaseChannel, handle->previousReleaseCallbackId, handle->previousReleaseFence, diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 178ddbbe79..34f6ffc5da 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -25,6 +25,7 @@ #include <ftl/future.h> #include <gui/BufferReleaseChannel.h> #include <gui/ITransactionCompletedListener.h> +#include <renderengine/ExternalTexture.h> #include <ui/Fence.h> #include <ui/FenceResult.h> @@ -55,6 +56,7 @@ public: uint64_t previousFrameNumber = 0; ReleaseCallbackId previousReleaseCallbackId = ReleaseCallbackId::INVALID_ID; std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> bufferReleaseChannel; + std::weak_ptr<renderengine::ExternalTexture> previousBuffer; }; class TransactionCallbackInvoker { diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp index 42fa436975..bf1035149b 100644 --- a/services/surfaceflinger/common/FlagManager.cpp +++ b/services/surfaceflinger/common/FlagManager.cpp @@ -129,6 +129,7 @@ void FlagManager::dump(std::string& result) const { DUMP_ACONFIG_FLAG(correct_virtual_display_power_state); DUMP_ACONFIG_FLAG(graphite_renderengine_preview_rollout); DUMP_ACONFIG_FLAG(increase_missed_frame_jank_threshold); + DUMP_ACONFIG_FLAG(monitor_buffer_fences); DUMP_ACONFIG_FLAG(refresh_rate_overlay_on_external_display); DUMP_ACONFIG_FLAG(vsync_predictor_recovery); @@ -164,7 +165,6 @@ void FlagManager::dump(std::string& result) const { DUMP_ACONFIG_FLAG(latch_unsignaled_with_auto_refresh_changed); DUMP_ACONFIG_FLAG(local_tonemap_screenshots); DUMP_ACONFIG_FLAG(misc1); - DUMP_ACONFIG_FLAG(multithreaded_present); DUMP_ACONFIG_FLAG(no_vsyncs_on_screen_off); DUMP_ACONFIG_FLAG(override_trusted_overlay); DUMP_ACONFIG_FLAG(protected_if_client); @@ -259,7 +259,6 @@ FLAG_MANAGER_ACONFIG_FLAG(frame_rate_category_mrr, "debug.sf.frame_rate_category FLAG_MANAGER_ACONFIG_FLAG(misc1, "") FLAG_MANAGER_ACONFIG_FLAG(vrr_config, "debug.sf.enable_vrr_config") FLAG_MANAGER_ACONFIG_FLAG(hdcp_level_hal, "") -FLAG_MANAGER_ACONFIG_FLAG(multithreaded_present, "debug.sf.multithreaded_present") FLAG_MANAGER_ACONFIG_FLAG(add_sf_skipped_frames_to_trace, "") FLAG_MANAGER_ACONFIG_FLAG(use_known_refresh_rate_for_fps_consistency, "") FLAG_MANAGER_ACONFIG_FLAG(cache_when_source_crop_layer_only_moved, @@ -305,6 +304,7 @@ FLAG_MANAGER_ACONFIG_FLAG(adpf_gpu_sf, "") FLAG_MANAGER_ACONFIG_FLAG(adpf_native_session_manager, ""); FLAG_MANAGER_ACONFIG_FLAG(graphite_renderengine_preview_rollout, ""); FLAG_MANAGER_ACONFIG_FLAG(increase_missed_frame_jank_threshold, ""); +FLAG_MANAGER_ACONFIG_FLAG(monitor_buffer_fences, ""); FLAG_MANAGER_ACONFIG_FLAG(vsync_predictor_recovery, ""); /// Trunk stable server (R/W) flags from outside SurfaceFlinger /// diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h index dd7042d8cb..8f361ac610 100644 --- a/services/surfaceflinger/common/include/common/FlagManager.h +++ b/services/surfaceflinger/common/include/common/FlagManager.h @@ -63,6 +63,7 @@ public: bool correct_virtual_display_power_state() const; bool graphite_renderengine_preview_rollout() const; bool increase_missed_frame_jank_threshold() const; + bool monitor_buffer_fences() const; bool refresh_rate_overlay_on_external_display() const; bool vsync_predictor_recovery() const; @@ -99,7 +100,6 @@ public: bool local_tonemap_screenshots() const; bool luts_api() const; bool misc1() const; - bool multithreaded_present() const; bool no_vsyncs_on_screen_off() const; bool override_trusted_overlay() const; bool protected_if_client() const; diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig index d8f51fe7e4..d412a19f3c 100644 --- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig +++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig @@ -216,6 +216,13 @@ flag { } # local_tonemap_screenshots flag { + name: "monitor_buffer_fences" + namespace: "core_graphics" + description: "Monitors fences for each buffer" + bug: "360932099" +} # monitor_buffer_fences + +flag { name: "no_vsyncs_on_screen_off" namespace: "core_graphics" description: "Stop vsync / Choreographer callbacks to apps when the screen is off" diff --git a/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp b/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp index 46b98f9193..192602d7d2 100644 --- a/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp +++ b/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp @@ -52,6 +52,8 @@ protected: }; TEST_F(DereferenceSurfaceControlTest, LayerNotInTransaction) { + // Last strong pointer is removed, the layer is destroyed and is removed + // from compostion. fgLayer = nullptr; { SCOPED_TRACE("after setting null"); @@ -61,7 +63,9 @@ TEST_F(DereferenceSurfaceControlTest, LayerNotInTransaction) { } TEST_F(DereferenceSurfaceControlTest, LayerInTransaction) { - auto transaction = Transaction().show(fgLayer); + Transaction transaction; + transaction.show(fgLayer); + // |transaction| retains a strong pointer, so layer is retained. fgLayer = nullptr; { SCOPED_TRACE("after setting null"); diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp index 18bd3b92d2..94cb878311 100644 --- a/services/surfaceflinger/tests/IPC_test.cpp +++ b/services/surfaceflinger/tests/IPC_test.cpp @@ -42,14 +42,22 @@ using CallbackInfo = SurfaceComposerClient::CallbackInfo; using TCLHash = SurfaceComposerClient::TCLHash; using android::hardware::graphics::common::V1_1::BufferUsage; -class TransactionHelper : public Transaction { +class TransactionHelper : public Transaction, public Parcelable { public: + TransactionHelper() : Transaction() {} size_t getNumListeners() { return mListenerCallbacks.size(); } std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash> getListenerCallbacks() { return mListenerCallbacks; } + status_t writeToParcel(Parcel* parcel) const override { + return Transaction::writeToParcel(parcel); + } + + status_t readFromParcel(const Parcel* parcel) override { + return Transaction::readFromParcel(parcel); + } }; class IPCTestUtils { diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h index 4322af7cef..75182e5fbb 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h @@ -183,7 +183,7 @@ struct DisplayIdGetter; template <typename PhysicalDisplay> struct DisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> { - static PhysicalDisplayId get() { + static DisplayIdVariant get() { if (!PhysicalDisplay::HAS_IDENTIFICATION_DATA) { return PhysicalDisplayId::fromPort(static_cast<bool>(PhysicalDisplay::PRIMARY) ? LEGACY_DISPLAY_TYPE_PRIMARY @@ -199,12 +199,12 @@ struct DisplayIdGetter<PhysicalDisplayIdType<PhysicalDisplay>> { template <VirtualDisplayId::BaseId displayId> struct DisplayIdGetter<HalVirtualDisplayIdType<displayId>> { - static HalVirtualDisplayId get() { return HalVirtualDisplayId(displayId); } + static DisplayIdVariant get() { return HalVirtualDisplayId(displayId); } }; template <> struct DisplayIdGetter<GpuVirtualDisplayIdType> { - static GpuVirtualDisplayId get() { return GpuVirtualDisplayId(0); } + static DisplayIdVariant get() { return GpuVirtualDisplayId(0); } }; template <typename> @@ -374,9 +374,8 @@ struct HwcDisplayVariant { // Called by tests to inject a HWC display setup template <hal::PowerMode kPowerMode = hal::PowerMode::ON> static void injectHwcDisplayWithNoDefaultCapabilities(DisplayTransactionTest* test) { - const auto displayId = DisplayVariant::DISPLAY_ID::get(); - ASSERT_FALSE(GpuVirtualDisplayId::tryCast(displayId)); - TestableSurfaceFlinger::FakeHwcDisplayInjector(displayId, HWC_DISPLAY_TYPE, + TestableSurfaceFlinger::FakeHwcDisplayInjector(DisplayVariant::DISPLAY_ID::get(), + HWC_DISPLAY_TYPE, static_cast<bool>(DisplayVariant::PRIMARY)) .setHwcDisplayId(HWC_DISPLAY_ID) .setResolution(DisplayVariant::RESOLUTION) @@ -663,9 +662,8 @@ struct HwcVirtualDisplayVariant const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); - const auto displayId = Base::DISPLAY_ID::get(); auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder() - .setId(displayId) + .setId(Base::DISPLAY_ID::get()) .setPixels(Base::RESOLUTION) .setIsSecure(static_cast<bool>(Base::SECURE)) .setPowerAdvisor(&test->mPowerAdvisor) @@ -678,7 +676,12 @@ struct HwcVirtualDisplayVariant ceDisplayArgs); // Insert display data so that the HWC thinks it created the virtual display. - test->mFlinger.mutableHwcDisplayData().try_emplace(displayId); + const auto ceDisplayIdVar = compositionDisplay->getDisplayIdVariant(); + LOG_ALWAYS_FATAL_IF(!ceDisplayIdVar); + EXPECT_EQ(*ceDisplayIdVar, Base::DISPLAY_ID::get()); + const auto displayId = asHalDisplayId(*ceDisplayIdVar); + LOG_ALWAYS_FATAL_IF(!displayId); + test->mFlinger.mutableHwcDisplayData().try_emplace(*displayId); return compositionDisplay; } @@ -816,8 +819,9 @@ using HwcVirtualDisplayCase = inline DisplayModePtr createDisplayMode(DisplayModeId modeId, Fps refreshRate, int32_t group = 0, ui::Size resolution = ui::Size(1920, 1080)) { - return mock::createDisplayMode(modeId, refreshRate, group, resolution, - PrimaryDisplayVariant::DISPLAY_ID::get()); + const auto physicalDisplayId = asPhysicalDisplayId(PrimaryDisplayVariant::DISPLAY_ID::get()); + LOG_ALWAYS_FATAL_IF(!physicalDisplayId); + return mock::createDisplayMode(modeId, refreshRate, group, resolution, *physicalDisplayId); } } // namespace android diff --git a/services/surfaceflinger/tests/unittests/DualDisplayTransactionTest.h b/services/surfaceflinger/tests/unittests/DualDisplayTransactionTest.h index 90e716ff1f..edcb639f82 100644 --- a/services/surfaceflinger/tests/unittests/DualDisplayTransactionTest.h +++ b/services/surfaceflinger/tests/unittests/DualDisplayTransactionTest.h @@ -48,8 +48,10 @@ struct DualDisplayTransactionTest : DisplayTransactionTest { } } - static inline PhysicalDisplayId kInnerDisplayId = InnerDisplayVariant::DISPLAY_ID::get(); - static inline PhysicalDisplayId kOuterDisplayId = OuterDisplayVariant::DISPLAY_ID::get(); + static inline PhysicalDisplayId kInnerDisplayId = + asPhysicalDisplayId(InnerDisplayVariant::DISPLAY_ID::get()).value(); + static inline PhysicalDisplayId kOuterDisplayId = + asPhysicalDisplayId(OuterDisplayVariant::DISPLAY_ID::get()).value(); sp<DisplayDevice> mInnerDisplay, mOuterDisplay; }; diff --git a/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp b/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp index a5b347a43c..c6da1a1a79 100644 --- a/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp +++ b/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp @@ -125,13 +125,13 @@ TEST_F(FlagManagerTest, DISABLED_returnsOverrideFalse) { TEST_F(FlagManagerTest, ignoresOverrideInUnitTestMode) { mFlagManager.setUnitTestMode(); - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); + SET_FLAG_FOR_TEST(flags::no_vsyncs_on_screen_off, true); // If this has not been called in this process, it will be called. // Regardless, the result is ignored. EXPECT_CALL(mFlagManager, getBoolProperty).WillRepeatedly(Return(false)); - EXPECT_EQ(true, mFlagManager.multithreaded_present()); + EXPECT_EQ(true, mFlagManager.no_vsyncs_on_screen_off()); } TEST_F(FlagManagerTest, returnsValue) { diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 49c35e2ca7..116fcd9f6d 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -741,8 +741,6 @@ TEST_F(SchedulerTest, resyncAllDoNotAllow) FTL_FAKE_GUARD(kMainThreadContext) { } TEST_F(SchedulerTest, resyncAllSkipsOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) { - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); - // resyncAllToHardwareVsync will result in requesting hardware VSYNC on display 1, which is on, // but not on display 2, which is off. EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1); @@ -763,28 +761,6 @@ TEST_F(SchedulerTest, resyncAllSkipsOffDisplays) FTL_FAKE_GUARD(kMainThreadConte mScheduler->resyncAllToHardwareVsync(kAllowToEnable); } -TEST_F(SchedulerTest, resyncAllLegacyAppliesToOffDisplays) FTL_FAKE_GUARD(kMainThreadContext) { - SET_FLAG_FOR_TEST(flags::multithreaded_present, false); - - // In the legacy code, prior to the flag, resync applied to OFF displays. - EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId1, true)).Times(1); - EXPECT_CALL(mScheduler->mockRequestHardwareVsync, Call(kDisplayId2, true)).Times(1); - - mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON); - - mScheduler->registerDisplay(kDisplayId2, - std::make_shared<RefreshRateSelector>(kDisplay2Modes, - kDisplay2Mode60->getId())); - ASSERT_EQ(hal::PowerMode::OFF, mScheduler->getDisplayPowerMode(kDisplayId2)); - - static constexpr bool kDisallow = true; - mScheduler->disableHardwareVsync(kDisplayId1, kDisallow); - mScheduler->disableHardwareVsync(kDisplayId2, kDisallow); - - static constexpr bool kAllowToEnable = true; - mScheduler->resyncAllToHardwareVsync(kAllowToEnable); -} - class AttachedChoreographerTest : public SchedulerTest { protected: void frameRateTestScenario(Fps layerFps, int8_t frameRateCompatibility, Fps displayFps, diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp index aa5b7863a9..aa48c1b26a 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp @@ -50,9 +50,9 @@ public: EXPECT_EQ(display.requestedRefreshRate, Fps::fromValue(requestedRefreshRate)); EXPECT_EQ(name.c_str(), display.displayName); - const VirtualDisplayId vid = GpuVirtualDisplayId(baseId); sp<DisplayDevice> device = - mFlinger.createVirtualDisplayDevice(displayToken, vid, requestedRefreshRate); + mFlinger.createVirtualDisplayDevice(displayToken, GpuVirtualDisplayId(baseId), + requestedRefreshRate); EXPECT_TRUE(device->isVirtual()); device->adjustRefreshRate(Fps::fromValue(pacesetterDisplayRefreshRate)); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp index 1335640342..eac5a8e9c5 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp @@ -68,13 +68,9 @@ void DisplayTransactionCommitTest::setupCommonPreconditions() { template <typename Case, bool connected> void DisplayTransactionCommitTest::expectHotplugReceived(mock::EventThread* eventThread) { - const auto convert = [](auto physicalDisplayId) { - return std::make_optional(DisplayId{physicalDisplayId}); - }; - - EXPECT_CALL(*eventThread, - onHotplugReceived(ResultOf(convert, Case::Display::DISPLAY_ID::get()), connected)) - .Times(1); + const auto physicalDisplayId = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get()); + ASSERT_TRUE(physicalDisplayId); + EXPECT_CALL(*eventThread, onHotplugReceived(*physicalDisplayId, connected)).Times(1); } template <typename Case> @@ -111,7 +107,7 @@ void DisplayTransactionCommitTest::verifyDisplayIsConnected(const sp<IBinder>& d std::optional<DisplayDeviceState::Physical> expectedPhysical; if (Case::Display::CONNECTION_TYPE::value) { - const auto displayId = PhysicalDisplayId::tryCast(Case::Display::DISPLAY_ID::get()); + const auto displayId = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get()); ASSERT_TRUE(displayId); const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value; ASSERT_TRUE(hwcDisplayId); @@ -137,10 +133,10 @@ void DisplayTransactionCommitTest::verifyPhysicalDisplayIsConnected() { EXPECT_TRUE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID)); // SF should have a display token. - const auto displayId = Case::Display::DISPLAY_ID::get(); - ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); + const auto displayIdOpt = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get()); + ASSERT_TRUE(displayIdOpt); - const auto displayOpt = mFlinger.mutablePhysicalDisplays().get(displayId); + const auto displayOpt = mFlinger.mutablePhysicalDisplays().get(*displayIdOpt); ASSERT_TRUE(displayOpt); const auto& display = displayOpt->get(); @@ -246,9 +242,9 @@ void DisplayTransactionCommitTest::processesHotplugDisconnectCommon() { EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID)); // SF should not have a PhysicalDisplay. - const auto displayId = Case::Display::DISPLAY_ID::get(); - ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); - ASSERT_FALSE(mFlinger.mutablePhysicalDisplays().contains(displayId)); + const auto physicalDisplayIdOpt = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get()); + ASSERT_TRUE(physicalDisplayIdOpt); + ASSERT_FALSE(mFlinger.mutablePhysicalDisplays().contains(*physicalDisplayIdOpt)); // The existing token should have been removed. verifyDisplayIsNotConnected(existing.token()); @@ -356,9 +352,10 @@ TEST_F(DisplayTransactionCommitTest, processesHotplugConnectThenDisconnectPrimar EXPECT_FALSE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID)); // SF should not have a PhysicalDisplay. - const auto displayId = Case::Display::DISPLAY_ID::get(); - ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); - ASSERT_FALSE(mFlinger.mutablePhysicalDisplays().contains(displayId)); + const auto physicalDisplayIdOpt = + asPhysicalDisplayId(Case::Display::DISPLAY_ID::get()); + ASSERT_TRUE(physicalDisplayIdOpt); + ASSERT_FALSE(mFlinger.mutablePhysicalDisplays().contains(*physicalDisplayIdOpt)); }(), testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected."); } @@ -400,10 +397,12 @@ TEST_F(DisplayTransactionCommitTest, processesHotplugDisconnectThenConnectPrimar // The existing token should have been removed. verifyDisplayIsNotConnected(existing.token()); - const auto displayId = Case::Display::DISPLAY_ID::get(); - ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); + const auto physicalDisplayIdOpt = + asPhysicalDisplayId(Case::Display::DISPLAY_ID::get()); + ASSERT_TRUE(physicalDisplayIdOpt); - const auto displayOpt = mFlinger.mutablePhysicalDisplays().get(displayId); + const auto displayOpt = + mFlinger.mutablePhysicalDisplays().get(*physicalDisplayIdOpt); ASSERT_TRUE(displayOpt); EXPECT_NE(existing.token(), displayOpt->get().token()); @@ -540,9 +539,9 @@ TEST_F(DisplayTransactionCommitTest, processesVirtualDisplayRemoval) { // Preconditions // A virtual display is set up but is removed from the current state. - const auto displayId = Case::Display::DISPLAY_ID::get(); - ASSERT_TRUE(HalVirtualDisplayId::tryCast(displayId)); - mFlinger.mutableHwcDisplayData().try_emplace(displayId); + const auto displayId = asHalDisplayId(Case::Display::DISPLAY_ID::get()); + ASSERT_TRUE(displayId); + mFlinger.mutableHwcDisplayData().try_emplace(*displayId); Case::Display::injectHwcDisplay(this); auto existing = Case::Display::makeFakeExistingDisplayInjector(this); existing.inject(); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp index fde2749438..8972840c8a 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp @@ -167,7 +167,6 @@ TEST_F(FoldableTest, requestsHardwareVsyncForBothDisplays) { } TEST_F(FoldableTest, requestVsyncOnPowerOn) { - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, true)) .Times(1); EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kOuterDisplayId, true)) @@ -178,7 +177,6 @@ TEST_F(FoldableTest, requestVsyncOnPowerOn) { } TEST_F(FoldableTest, disableVsyncOnPowerOffPacesetter) { - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); // When the device boots, the inner display should be the pacesetter. ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp index 49972b03f6..b8b1b9527c 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp @@ -90,7 +90,9 @@ TEST_F(HotplugTest, createsDisplaySnapshotsForDisplaysWithIdentificationData) { mFlinger.configure(); EXPECT_TRUE(hasPhysicalHwcDisplay(PrimaryDisplay::HWC_DISPLAY_ID)); - EXPECT_TRUE(mFlinger.getHwComposer().isConnected(PrimaryDisplay::DISPLAY_ID::get())); + const auto primaryDisplayId = asPhysicalDisplayId(PrimaryDisplay::DISPLAY_ID::get()); + ASSERT_TRUE(primaryDisplayId); + EXPECT_TRUE(mFlinger.getHwComposer().isConnected(*primaryDisplayId)); const auto primaryDisplayIdOpt = mFlinger.getHwComposer().toPhysicalDisplayId(PrimaryDisplay::HWC_DISPLAY_ID); ASSERT_TRUE(primaryDisplayIdOpt.has_value()); @@ -98,13 +100,15 @@ TEST_F(HotplugTest, createsDisplaySnapshotsForDisplaysWithIdentificationData) { mFlinger.physicalDisplays().get(primaryDisplayIdOpt.value()); ASSERT_TRUE(primaryPhysicalDisplayOpt.has_value()); const auto primaryDisplaySnapshotRef = primaryPhysicalDisplayOpt->get().snapshotRef(); - EXPECT_EQ(PrimaryDisplay::DISPLAY_ID::get(), primaryDisplaySnapshotRef.get().displayId()); + EXPECT_EQ(*primaryDisplayId, primaryDisplaySnapshotRef.get().displayId()); EXPECT_EQ(PrimaryDisplay::PORT::value, primaryDisplaySnapshotRef.get().port()); EXPECT_EQ(PrimaryDisplay::CONNECTION_TYPE::value, primaryDisplaySnapshotRef.get().connectionType()); EXPECT_TRUE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID)); - EXPECT_TRUE(mFlinger.getHwComposer().isConnected(ExternalDisplay::DISPLAY_ID::get())); + const auto externalDisplayId = asPhysicalDisplayId(ExternalDisplay::DISPLAY_ID::get()); + ASSERT_TRUE(externalDisplayId); + EXPECT_TRUE(mFlinger.getHwComposer().isConnected(*externalDisplayId)); const auto externalDisplayIdOpt = mFlinger.getHwComposer().toPhysicalDisplayId(ExternalDisplay::HWC_DISPLAY_ID); ASSERT_TRUE(externalDisplayIdOpt.has_value()); @@ -112,7 +116,7 @@ TEST_F(HotplugTest, createsDisplaySnapshotsForDisplaysWithIdentificationData) { mFlinger.physicalDisplays().get(externalDisplayIdOpt.value()); ASSERT_TRUE(externalPhysicalDisplayOpt.has_value()); const auto externalDisplaySnapshotRef = externalPhysicalDisplayOpt->get().snapshotRef(); - EXPECT_EQ(ExternalDisplay::DISPLAY_ID::get(), externalDisplaySnapshotRef.get().displayId()); + EXPECT_EQ(*externalDisplayId, externalDisplaySnapshotRef.get().displayId()); EXPECT_EQ(ExternalDisplay::PORT::value, externalDisplaySnapshotRef.get().port()); EXPECT_EQ(ExternalDisplay::CONNECTION_TYPE::value, externalDisplaySnapshotRef.get().connectionType()); @@ -154,8 +158,8 @@ TEST_F(HotplugTest, createsDisplaySnapshotsForDisplaysWithoutIdentificationData) constexpr PhysicalDisplayId primaryInternalDisplayId = PhysicalDisplayId::fromPort(primaryInternalDisplayPort); EXPECT_TRUE(hasPhysicalHwcDisplay(PrimaryDisplay::HWC_DISPLAY_ID)); - ASSERT_EQ(primaryInternalDisplayId, PrimaryDisplay::DISPLAY_ID::get()); - EXPECT_TRUE(mFlinger.getHwComposer().isConnected(PrimaryDisplay::DISPLAY_ID::get())); + ASSERT_EQ(primaryInternalDisplayId, asPhysicalDisplayId(PrimaryDisplay::DISPLAY_ID::get())); + EXPECT_TRUE(mFlinger.getHwComposer().isConnected(primaryInternalDisplayId)); const auto primaryDisplayIdOpt = mFlinger.getHwComposer().toPhysicalDisplayId(PrimaryDisplay::HWC_DISPLAY_ID); ASSERT_TRUE(primaryDisplayIdOpt.has_value()); @@ -220,7 +224,9 @@ TEST_F(HotplugTest, ignoresDuplicateDisconnection) { // The display should be scheduled for removal during the next commit. At this point, it should // still exist but be marked as disconnected. EXPECT_TRUE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID)); - EXPECT_FALSE(mFlinger.getHwComposer().isConnected(ExternalDisplay::DISPLAY_ID::get())); + const auto externalDisplayId = asPhysicalDisplayId(ExternalDisplay::DISPLAY_ID::get()); + ASSERT_TRUE(externalDisplayId); + EXPECT_FALSE(mFlinger.getHwComposer().isConnected(*externalDisplayId)); } TEST_F(HotplugTest, rejectsHotplugIfFailedToLoadDisplayModes) { diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyExpectedPresentTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyExpectedPresentTest.cpp index 6cc6322bfc..9c143fdd41 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyExpectedPresentTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyExpectedPresentTest.cpp @@ -45,28 +45,15 @@ protected: void setTransactionState() { ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty()); TransactionInfo transaction; - mFlinger.setTransactionState(FrameTimelineInfo{}, transaction.states, transaction.displays, - transaction.flags, transaction.applyToken, - transaction.inputWindowCommands, - TimePoint::now().ns() + s2ns(1), transaction.isAutoTimestamp, - transaction.unCachedBuffers, - /*HasListenerCallbacks=*/false, transaction.callbacks, - transaction.id, transaction.mergedTransactionIds); + mFlinger.setTransactionState(std::move(transaction)); } - struct TransactionInfo { - Vector<ComposerState> states; - Vector<DisplayState> displays; - uint32_t flags = 0; - sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); - InputWindowCommands inputWindowCommands; - int64_t desiredPresentTime = 0; - bool isAutoTimestamp = false; - FrameTimelineInfo frameTimelineInfo{}; - std::vector<client_cache_t> unCachedBuffers; - uint64_t id = static_cast<uint64_t>(-1); - std::vector<uint64_t> mergedTransactionIds; - std::vector<ListenerCallbacks> callbacks; + struct TransactionInfo : public TransactionState { + TransactionInfo() { + mApplyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); + mIsAutoTimestamp = false; + mId = static_cast<uint64_t>(-1); + } }; struct Compositor final : ICompositor { @@ -383,4 +370,4 @@ TEST_F(NotifyExpectedPresentTest, notifyExpectedPresentRenderRateChanged) { } } } -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp index f2fbbdda72..2332bf62da 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPhysicalDisplayPowerModeTest.cpp @@ -17,6 +17,7 @@ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" +#include <android_companion_virtualdevice_flags.h> #include <com_android_graphics_surfaceflinger_flags.h> #include <common/test/FlagUtils.h> #include "DisplayTransactionTestHelpers.h" @@ -78,11 +79,19 @@ struct EventThreadBaseSupportedVariant { struct EventThreadNotSupportedVariant : public EventThreadBaseSupportedVariant { static void setupEnableVsyncCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, true)).Times(1); + setupDisableSyntheticVsyncCallExpectations(test); + } + + static void setupDisableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0); } static void setupDisableVsyncCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, false)).Times(1); + setupEnableSyntheticVsyncCallExpectations(test); + } + + static void setupEnableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0); } }; @@ -91,12 +100,20 @@ struct EventThreadIsSupportedVariant : public EventThreadBaseSupportedVariant { static void setupEnableVsyncCallExpectations(DisplayTransactionTest* test) { // Expect to enable hardware VSYNC and disable synthetic VSYNC. EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, true)).Times(1); + setupDisableSyntheticVsyncCallExpectations(test); + } + + static void setupDisableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(false)).Times(1); } static void setupDisableVsyncCallExpectations(DisplayTransactionTest* test) { // Expect to disable hardware VSYNC and enable synthetic VSYNC. EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, false)).Times(1); + setupEnableSyntheticVsyncCallExpectations(test); + } + + static void setupEnableSyntheticVsyncCallExpectations(DisplayTransactionTest* test) { EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(true)).Times(1); } }; @@ -151,7 +168,7 @@ struct TransitionOffToDozeSuspendVariant template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND); - Case::EventThread::setupVsyncNoCallExpectations(test); + Case::EventThread::setupEnableSyntheticVsyncCallExpectations(test); Case::setupRepaintEverythingCallExpectations(test); } @@ -176,7 +193,7 @@ struct TransitionDozeSuspendToOffVariant : public TransitionVariantCommon<PowerMode::DOZE_SUSPEND, PowerMode::OFF> { template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { - Case::EventThread::setupVsyncNoCallExpectations(test); + Case::EventThread::setupEnableSyntheticVsyncCallExpectations(test); Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::OFF); } @@ -188,7 +205,7 @@ struct TransitionDozeSuspendToOffVariant struct TransitionOnToDozeVariant : public TransitionVariantCommon<PowerMode::ON, PowerMode::DOZE> { template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { - Case::EventThread::setupVsyncNoCallExpectations(test); + Case::EventThread::setupDisableSyntheticVsyncCallExpectations(test); Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE); } }; @@ -206,7 +223,7 @@ struct TransitionDozeSuspendToDozeVariant struct TransitionDozeToOnVariant : public TransitionVariantCommon<PowerMode::DOZE, PowerMode::ON> { template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { - Case::EventThread::setupVsyncNoCallExpectations(test); + Case::EventThread::setupDisableSyntheticVsyncCallExpectations(test); Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON); } }; @@ -234,7 +251,7 @@ struct TransitionOnToUnknownVariant : public TransitionVariantCommon<PowerMode::ON, static_cast<PowerMode>(POWER_MODE_LEET)> { template <typename Case> static void setupCallExpectations(DisplayTransactionTest* test) { - Case::EventThread::setupVsyncNoCallExpectations(test); + Case::EventThread::setupDisableSyntheticVsyncCallExpectations(test); Case::setupNoComposerPowerModeCallExpectations(test); } }; @@ -335,11 +352,13 @@ void SetPhysicalDisplayPowerModeTest::transitionDisplayCommon() { // -------------------------------------------------------------------- // Preconditions + SET_FLAG_FOR_TEST(android::companion::virtualdevice::flags::correct_virtual_display_power_state, + true); + Case::Doze::setupComposerCallExpectations(this); auto display = Case::injectDisplayWithInitialPowerMode(this, Case::Transition::INITIAL_POWER_MODE); - auto displayId = display->getId(); - if (auto physicalDisplayId = PhysicalDisplayId::tryCast(displayId)) { + if (auto physicalDisplayId = asPhysicalDisplayId(display->getDisplayIdVariant())) { Case::setInitialHwVsyncEnabled(this, *physicalDisplayId, PowerModeInitialVSyncEnabled< Case::Transition::INITIAL_POWER_MODE>::value); @@ -393,9 +412,9 @@ TEST_F(SetPhysicalDisplayPowerModeTest, setPhysicalDisplayPowerModeDoesNothingIf // Preconditions // Insert display data so that the HWC thinks it created the virtual display. - const auto displayId = Case::Display::DISPLAY_ID::get(); - ASSERT_TRUE(HalVirtualDisplayId::tryCast(displayId)); - mFlinger.mutableHwcDisplayData().try_emplace(displayId); + const auto displayId = asHalDisplayId(Case::Display::DISPLAY_ID::get()); + ASSERT_TRUE(displayId); + ASSERT_TRUE(mFlinger.mutableHwcDisplayData().try_emplace(*displayId).second); // A virtual display device is set up Case::Display::injectHwcDisplay(this); @@ -457,7 +476,6 @@ TEST_F(SetPhysicalDisplayPowerModeTest, transitionsDisplayFromOnToUnknownPrimary } TEST_F(SetPhysicalDisplayPowerModeTest, transitionsDisplayFromOffToOnExternalDisplay) { - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOffToOnVariant>>(); } @@ -466,7 +484,6 @@ TEST_F(SetPhysicalDisplayPowerModeTest, transitionsDisplayFromOffToDozeSuspendEx } TEST_F(SetPhysicalDisplayPowerModeTest, transitionsDisplayFromOnToOffExternalDisplay) { - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToOffVariant>>(); } @@ -479,7 +496,6 @@ TEST_F(SetPhysicalDisplayPowerModeTest, transitionsDisplayFromOnToDozeExternalDi } TEST_F(SetPhysicalDisplayPowerModeTest, transitionsDisplayFromDozeSuspendToDozeExternalDisplay) { - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); transitionDisplayCommon<ExternalDisplayPowerCase<TransitionDozeSuspendToDozeVariant>>(); } @@ -488,12 +504,10 @@ TEST_F(SetPhysicalDisplayPowerModeTest, transitionsDisplayFromDozeToOnExternalDi } TEST_F(SetPhysicalDisplayPowerModeTest, transitionsDisplayFromDozeSuspendToOnExternalDisplay) { - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); transitionDisplayCommon<ExternalDisplayPowerCase<TransitionDozeSuspendToOnVariant>>(); } TEST_F(SetPhysicalDisplayPowerModeTest, transitionsDisplayFromOnToDozeSuspendExternalDisplay) { - SET_FLAG_FOR_TEST(flags::multithreaded_present, true); transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToDozeSuspendVariant>>(); } diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp index cd554ea1ec..23e73de660 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp @@ -235,7 +235,7 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { constexpr auto kConnectionTypeOpt = Case::Display::CONNECTION_TYPE::value; if constexpr (kConnectionTypeOpt) { - const auto displayId = PhysicalDisplayId::tryCast(Case::Display::DISPLAY_ID::get()); + const auto displayId = asPhysicalDisplayId(Case::Display::DISPLAY_ID::get()); ASSERT_TRUE(displayId); const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value; ASSERT_TRUE(hwcDisplayId); @@ -282,7 +282,7 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { // Postconditions ASSERT_NE(nullptr, device); - EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getId()); + EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getDisplayIdVariant()); EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), device->isVirtual()); EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure()); EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary()); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index a3ee08f6b7..13c32bdf08 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -481,7 +481,7 @@ public: SurfaceFlinger::ScreenshotArgs screenshotArgs; screenshotArgs.captureTypeVariant = display; - screenshotArgs.displayId = std::nullopt; + screenshotArgs.displayIdVariant = std::nullopt; screenshotArgs.sourceCrop = sourceCrop; screenshotArgs.reqSize = sourceCrop.getSize(); screenshotArgs.dataspace = dataspace; @@ -519,18 +519,8 @@ public: return mFlinger->mTransactionHandler.mPendingTransactionCount.load(); } - auto setTransactionState( - const FrameTimelineInfo& frameTimelineInfo, Vector<ComposerState>& states, - Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, - const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, - bool isAutoTimestamp, const std::vector<client_cache_t>& uncacheBuffers, - bool hasListenerCallbacks, std::vector<ListenerCallbacks>& listenerCallbacks, - uint64_t transactionId, const std::vector<uint64_t>& mergedTransactionIds) { - return mFlinger->setTransactionState(frameTimelineInfo, states, displays, flags, applyToken, - inputWindowCommands, desiredPresentTime, - isAutoTimestamp, uncacheBuffers, hasListenerCallbacks, - listenerCallbacks, transactionId, - mergedTransactionIds); + auto setTransactionState(TransactionState&& state) { + return mFlinger->setTransactionState(std::move(state)); } auto setTransactionStateInternal(QueuedTransactionState& transaction) { @@ -583,7 +573,7 @@ public: } sp<DisplayDevice> createVirtualDisplayDevice(const sp<IBinder> displayToken, - VirtualDisplayId displayId, + GpuVirtualDisplayId displayId, float requestedRefreshRate) { constexpr ui::Size kResolution = {1080, 1920}; auto compositionDisplay = compositionengine::impl:: @@ -827,9 +817,11 @@ public: static constexpr int32_t DEFAULT_DPI = 320; static constexpr hal::HWConfigId DEFAULT_ACTIVE_CONFIG = 0; - FakeHwcDisplayInjector(HalDisplayId displayId, hal::DisplayType hwcDisplayType, + FakeHwcDisplayInjector(DisplayIdVariant displayIdVariant, hal::DisplayType hwcDisplayType, bool isPrimary) - : mDisplayId(displayId), mHwcDisplayType(hwcDisplayType), mIsPrimary(isPrimary) {} + : mDisplayIdVariant(displayIdVariant), + mHwcDisplayType(hwcDisplayType), + mIsPrimary(isPrimary) {} auto& setHwcDisplayId(hal::HWDisplayId displayId) { mHwcDisplayId = displayId; @@ -894,7 +886,9 @@ public: display->setPowerMode(mPowerMode); - flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = std::move(display); + const auto halDisplayId = asHalDisplayId(mDisplayIdVariant); + ASSERT_TRUE(halDisplayId); + flinger->mutableHwcDisplayData()[*halDisplayId].hwcDisplay = std::move(display); EXPECT_CALL(*composer, getDisplayConfigs(mHwcDisplayId, _)) .WillRepeatedly( @@ -932,9 +926,10 @@ public: DoAll(SetArgPointee<3>(mConfigGroup), Return(hal::Error::NONE))); if (mHwcDisplayType == hal::DisplayType::PHYSICAL) { - const auto physicalId = PhysicalDisplayId::tryCast(mDisplayId); - LOG_ALWAYS_FATAL_IF(!physicalId); - flinger->mutableHwcPhysicalDisplayIdMap().emplace(mHwcDisplayId, *physicalId); + const auto physicalDisplayId = asPhysicalDisplayId(mDisplayIdVariant); + ASSERT_TRUE(physicalDisplayId); + flinger->mutableHwcPhysicalDisplayIdMap().emplace(mHwcDisplayId, + *physicalDisplayId); if (mIsPrimary) { flinger->mutablePrimaryHwcDisplayId() = mHwcDisplayId; } else { @@ -947,7 +942,7 @@ public: } private: - const HalDisplayId mDisplayId; + const DisplayIdVariant mDisplayIdVariant; const hal::DisplayType mHwcDisplayType; const bool mIsPrimary; @@ -983,8 +978,8 @@ public: sp<IBinder> token() const { return mDisplayToken; } auto physicalDisplay() const { - return ftl::Optional(mCreationArgs.compositionDisplay->getDisplayId()) - .and_then(&PhysicalDisplayId::tryCast) + return mCreationArgs.compositionDisplay->getDisplayIdVariant() + .and_then(asPhysicalDisplayId) .and_then(display::getPhysicalDisplay(mFlinger.physicalDisplays())); } @@ -1082,7 +1077,9 @@ public: DisplayDeviceState state; state.isSecure = mCreationArgs.isSecure; - if (const auto physicalId = PhysicalDisplayId::tryCast(*displayId)) { + if (const auto physicalId = + mCreationArgs.compositionDisplay->getDisplayIdVariant().and_then( + asPhysicalDisplayId)) { LOG_ALWAYS_FATAL_IF(!mConnectionType); LOG_ALWAYS_FATAL_IF(!mHwcDisplayId); diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 69dfcc4a8f..1395fb6af3 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -17,6 +17,8 @@ #undef LOG_TAG #define LOG_TAG "TransactionApplicationTest" +#include <cstdint> + #include <binder/Binder.h> #include <common/test/FlagUtils.h> #include <compositionengine/Display.h> @@ -69,38 +71,32 @@ public: TestableSurfaceFlinger mFlinger; renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); - struct TransactionInfo { - Vector<ComposerState> states; - Vector<DisplayState> displays; - uint32_t flags = 0; - sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); - InputWindowCommands inputWindowCommands; - int64_t desiredPresentTime = 0; - bool isAutoTimestamp = true; - FrameTimelineInfo frameTimelineInfo; - std::vector<client_cache_t> uncacheBuffers; - uint64_t id = static_cast<uint64_t>(-1); - std::vector<uint64_t> mergedTransactionIds; - static_assert(0xffffffffffffffff == static_cast<uint64_t>(-1)); + struct TransactionInfo : public TransactionState { + TransactionInfo() { + mApplyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); + mId = static_cast<uint64_t>(-1); + } }; - void checkEqual(TransactionInfo info, QueuedTransactionState state) { - EXPECT_EQ(0u, info.states.size()); + void checkEqual(const TransactionInfo& info, const QueuedTransactionState& state) { + EXPECT_EQ(0u, info.mComposerStates.size()); EXPECT_EQ(0u, state.states.size()); - EXPECT_EQ(0u, info.displays.size()); + EXPECT_EQ(0u, info.mDisplayStates.size()); EXPECT_EQ(0u, state.displays.size()); - EXPECT_EQ(info.flags, state.flags); - EXPECT_EQ(info.desiredPresentTime, state.desiredPresentTime); + EXPECT_EQ(info.mFlags, state.flags); + EXPECT_EQ(info.mDesiredPresentTime, state.desiredPresentTime); } void setupSingle(TransactionInfo& transaction, uint32_t flags, int64_t desiredPresentTime, bool isAutoTimestamp, const FrameTimelineInfo& frameTimelineInfo) { mTransactionNumber++; - transaction.flags |= flags; - transaction.desiredPresentTime = desiredPresentTime; - transaction.isAutoTimestamp = isAutoTimestamp; - transaction.frameTimelineInfo = frameTimelineInfo; + transaction.mFlags |= flags; + transaction.mDesiredPresentTime = desiredPresentTime; + transaction.mIsAutoTimestamp = isAutoTimestamp; + transaction.mFrameTimelineInfo = frameTimelineInfo; + transaction.mHasListenerCallbacks = mHasListenerCallbacks; + transaction.mListenerCallbacks = mCallbacks; } void NotPlacedOnTransactionQueue(uint32_t flags) { @@ -111,12 +107,7 @@ public: /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, FrameTimelineInfo{}); nsecs_t applicationTime = systemTime(); - mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states, - transaction.displays, transaction.flags, - transaction.applyToken, transaction.inputWindowCommands, - transaction.desiredPresentTime, transaction.isAutoTimestamp, - transaction.uncacheBuffers, mHasListenerCallbacks, mCallbacks, - transaction.id, transaction.mergedTransactionIds); + mFlinger.setTransactionState(std::move(transaction)); // If transaction is synchronous, SF applyTransactionState should time out (5s) wating for // SF to commit the transaction. If this is animation, it should not time out waiting. @@ -138,12 +129,7 @@ public: setupSingle(transaction, flags, /*desiredPresentTime*/ time + s2ns(1), false, FrameTimelineInfo{}); nsecs_t applicationSentTime = systemTime(); - mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states, - transaction.displays, transaction.flags, - transaction.applyToken, transaction.inputWindowCommands, - transaction.desiredPresentTime, transaction.isAutoTimestamp, - transaction.uncacheBuffers, mHasListenerCallbacks, mCallbacks, - transaction.id, transaction.mergedTransactionIds); + mFlinger.setTransactionState(std::move(transaction)); nsecs_t returnedTime = systemTime(); EXPECT_LE(returnedTime, applicationSentTime + TRANSACTION_TIMEOUT); @@ -169,12 +155,7 @@ public: /*isAutoTimestamp*/ true, FrameTimelineInfo{}); nsecs_t applicationSentTime = systemTime(); - mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states, - transactionA.displays, transactionA.flags, - transactionA.applyToken, transactionA.inputWindowCommands, - transactionA.desiredPresentTime, transactionA.isAutoTimestamp, - transactionA.uncacheBuffers, mHasListenerCallbacks, mCallbacks, - transactionA.id, transactionA.mergedTransactionIds); + mFlinger.setTransactionState(std::move(transactionA)); // This thread should not have been blocked by the above transaction // (5s is the timeout period that applyTransactionState waits for SF to @@ -184,12 +165,7 @@ public: mFlinger.flushTransactionQueues(); applicationSentTime = systemTime(); - mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states, - transactionB.displays, transactionB.flags, - transactionB.applyToken, transactionB.inputWindowCommands, - transactionB.desiredPresentTime, transactionB.isAutoTimestamp, - transactionB.uncacheBuffers, mHasListenerCallbacks, mCallbacks, - transactionB.id, transactionB.mergedTransactionIds); + mFlinger.setTransactionState(std::move(transactionB)); // this thread should have been blocked by the above transaction // if this is an animation, this thread should be blocked for 5s @@ -222,12 +198,7 @@ TEST_F(TransactionApplicationTest, AddToPendingQueue) { TransactionInfo transactionA; // transaction to go on pending queue setupSingle(transactionA, /*flags*/ 0, /*desiredPresentTime*/ s2ns(1), false, FrameTimelineInfo{}); - mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states, - transactionA.displays, transactionA.flags, transactionA.applyToken, - transactionA.inputWindowCommands, transactionA.desiredPresentTime, - transactionA.isAutoTimestamp, transactionA.uncacheBuffers, - mHasListenerCallbacks, mCallbacks, transactionA.id, - transactionA.mergedTransactionIds); + mFlinger.setTransactionState(std::move(transactionA)); auto& transactionQueue = mFlinger.getTransactionQueue(); ASSERT_FALSE(transactionQueue.isEmpty()); @@ -243,12 +214,7 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { TransactionInfo transactionA; // transaction to go on pending queue setupSingle(transactionA, /*flags*/ 0, /*desiredPresentTime*/ s2ns(1), false, FrameTimelineInfo{}); - mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states, - transactionA.displays, transactionA.flags, transactionA.applyToken, - transactionA.inputWindowCommands, transactionA.desiredPresentTime, - transactionA.isAutoTimestamp, transactionA.uncacheBuffers, - mHasListenerCallbacks, mCallbacks, transactionA.id, - transactionA.mergedTransactionIds); + mFlinger.setTransactionState(std::move(transactionA)); auto& transactionQueue = mFlinger.getTransactionQueue(); ASSERT_FALSE(transactionQueue.isEmpty()); @@ -257,12 +223,10 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { // transaction here (sending a null applyToken to fake it as from a // different process) to re-query and reset the cached expected present time TransactionInfo empty; - empty.applyToken = sp<IBinder>(); - mFlinger.setTransactionState(empty.frameTimelineInfo, empty.states, empty.displays, empty.flags, - empty.applyToken, empty.inputWindowCommands, - empty.desiredPresentTime, empty.isAutoTimestamp, - empty.uncacheBuffers, mHasListenerCallbacks, mCallbacks, empty.id, - empty.mergedTransactionIds); + empty.mApplyToken = sp<IBinder>(); + empty.mHasListenerCallbacks = mHasListenerCallbacks; + empty.mListenerCallbacks = mCallbacks; + mFlinger.setTransactionState(std::move(empty)); // flush transaction queue should flush as desiredPresentTime has // passed @@ -406,9 +370,9 @@ public: const auto kFrameTimelineInfo = FrameTimelineInfo{}; setupSingle(transaction, kFlags, kDesiredPresentTime, kIsAutoTimestamp, kFrameTimelineInfo); - transaction.applyToken = applyToken; + transaction.mApplyToken = applyToken; for (const auto& state : states) { - transaction.states.push_back(state); + transaction.mComposerStates.push_back(state); } return transaction; @@ -419,8 +383,8 @@ public: EXPECT_TRUE(mFlinger.getTransactionQueue().isEmpty()); EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size()); std::unordered_set<uint32_t> createdLayers; - for (auto transaction : transactions) { - for (auto& state : transaction.states) { + for (auto& transaction : transactions) { + for (auto& state : transaction.mComposerStates) { auto layerId = static_cast<uint32_t>(state.state.layerId); if (createdLayers.find(layerId) == createdLayers.end()) { mFlinger.addLayer(layerId); @@ -434,8 +398,8 @@ public: for (auto transaction : transactions) { std::vector<ResolvedComposerState> resolvedStates; - resolvedStates.reserve(transaction.states.size()); - for (auto& state : transaction.states) { + resolvedStates.reserve(transaction.mComposerStates.size()); + for (auto& state : transaction.mComposerStates) { ResolvedComposerState resolvedState; resolvedState.state = std::move(state.state); resolvedState.externalTexture = @@ -446,15 +410,9 @@ public: resolvedStates.emplace_back(resolvedState); } - QueuedTransactionState transactionState(transaction.frameTimelineInfo, resolvedStates, - transaction.displays, transaction.flags, - transaction.applyToken, - transaction.inputWindowCommands, - transaction.desiredPresentTime, - transaction.isAutoTimestamp, {}, systemTime(), - mHasListenerCallbacks, mCallbacks, getpid(), - static_cast<int>(getuid()), transaction.id, - transaction.mergedTransactionIds); + QueuedTransactionState transactionState(std::move(transaction), + std::move(resolvedStates), {}, systemTime(), + getpid(), static_cast<int>(getuid())); mFlinger.setTransactionStateInternal(transactionState); } mFlinger.flushTransactionQueues(); diff --git a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp index d3eec5c6f3..b36ad213c8 100644 --- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp @@ -66,7 +66,7 @@ TEST(TransactionProtoParserTest, parse) { display.token = nullptr; } display.width = 85; - t1.displays.add(display); + t1.displays.push_back(display); } class TestMapper : public TransactionProtoParser::FlingerDataMapper { diff --git a/vulkan/vkjson/vkjson.cc b/vulkan/vkjson/vkjson.cc index 18fef2bf58..531a623e90 100644 --- a/vulkan/vkjson/vkjson.cc +++ b/vulkan/vkjson/vkjson.cc @@ -56,13 +56,15 @@ inline bool IsIntegral(double value) { // Floating point fields of Vulkan structure use single precision. The string // output of max double value in c++ will be larger than Java double's infinity // value. Below fake double max/min values are only to serve the safe json text -// parsing in between C++ and Java, becasue Java json library simply cannot +// parsing in between C++ and Java, because Java json library simply cannot // handle infinity. static const double SAFE_DOUBLE_MAX = 0.99 * std::numeric_limits<double>::max(); static const double SAFE_DOUBLE_MIN = -SAFE_DOUBLE_MAX; -template <typename T> struct EnumTraits; -template <> struct EnumTraits<VkPhysicalDeviceType> { +template <typename T> +struct EnumTraits; +template <> +struct EnumTraits<VkPhysicalDeviceType> { static bool exist(uint32_t e) { switch (e) { case VK_PHYSICAL_DEVICE_TYPE_OTHER: @@ -76,7 +78,8 @@ template <> struct EnumTraits<VkPhysicalDeviceType> { } }; -template <> struct EnumTraits<VkFormat> { +template <> +struct EnumTraits<VkFormat> { static bool exist(uint32_t e) { switch (e) { case VK_FORMAT_UNDEFINED: @@ -482,708 +485,1447 @@ struct EnumTraits<VkImageLayout> { template <typename Visitor> inline bool Iterate(Visitor* visitor, VkExtent3D* extents) { + return visitor->Visit("width", &extents->width) && + visitor->Visit("height", &extents->height) && + visitor->Visit("depth", &extents->depth); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkConformanceVersionKHR* version) { + return visitor->Visit("major", &version->major) && + visitor->Visit("minor", &version->minor) && + visitor->Visit("subminor", &version->subminor) && + visitor->Visit("patch", &version->patch); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkMemoryType* type) { + return visitor->Visit("propertyFlags", &type->propertyFlags) && + visitor->Visit("heapIndex", &type->heapIndex); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkMemoryHeap* heap) { + return visitor->Visit("size", &heap->size) && + visitor->Visit("flags", &heap->flags); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonCore11* core) { + return visitor->Visit("properties", &core->properties) && + visitor->Visit("features", &core->features); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonCore12* core) { + return visitor->Visit("properties", &core->properties) && + visitor->Visit("features", &core->features); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonCore13* core) { + return visitor->Visit("properties", &core->properties) && + visitor->Visit("features", &core->features); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonCore14* core) { + return visitor->Visit("properties", &core->properties) && + visitor->Visit("features", &core->features); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonKHRVariablePointers* structs) { + return visitor->Visit("variablePointerFeaturesKHR", + &structs->variable_pointer_features_khr) && + visitor->Visit("variablePointersFeaturesKHR", + &structs->variable_pointers_features_khr); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonKHRShaderFloat16Int8* structs) { + return visitor->Visit("shaderFloat16Int8FeaturesKHR", + &structs->shader_float16_int8_features_khr) && + visitor->Visit("float16Int8FeaturesKHR", + &structs->float16_int8_features_khr); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonExtImage2dViewOf3d* structs) { + return visitor->Visit("image2DViewOf3DFeaturesEXT", + &structs->image_2d_view_of_3d_features_ext); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonExtCustomBorderColor* structs) { + return visitor->Visit("customBorderColorFeaturesEXT", + &structs->custom_border_color_features_ext); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, + VkJsonExtPrimitiveTopologyListRestart* structs) { + return visitor->Visit("primitiveTopologyListRestartFeaturesEXT", + &structs->primitive_topology_list_restart_features_ext); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonExtProvokingVertex* structs) { + return visitor->Visit("provokingVertexFeaturesEXT", + &structs->provoking_vertex_features_ext); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonKHRIndexTypeUint8* structs) { + return visitor->Visit("indexTypeUint8FeaturesKHR", + &structs->index_type_uint8_features_khr); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonExtIndexTypeUint8* structs) { + return visitor->Visit("indexTypeUint8FeaturesEXT", + &structs->index_type_uint8_features_ext); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, + VkJsonKHRVertexAttributeDivisor* structs) { + return visitor->Visit("vertexAttributeDivisorFeaturesKHR", + &structs->vertex_attribute_divisor_features_khr); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, + VkJsonExtVertexAttributeDivisor* structs) { + return visitor->Visit("vertexAttributeDivisorFeaturesEXT", + &structs->vertex_attribute_divisor_features_ext); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonExtTransformFeedback* structs) { + return visitor->Visit("transformFeedbackFeaturesEXT", + &structs->transform_feedback_features_ext); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, + VkJsonKHRShaderSubgroupUniformControlFlow* structs) { + return visitor->Visit( + "shaderSubgroupUniformControlFlowFeaturesKHR", + &structs->shader_subgroup_uniform_control_flow_features_khr); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, + VkJsonKHRShaderSubgroupExtendedTypes* structs) { + return visitor->Visit("shaderSubgroupExtendedTypesFeaturesKHR", + &structs->shader_subgroup_extended_types_features_khr); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonKHR8bitStorage* structs) { + return visitor->Visit("bit8StorageFeaturesKHR", + &structs->bit8_storage_features_khr); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, + VkJsonKHRShaderIntegerDotProduct* structs) { + return visitor->Visit("shaderIntegerDotProductFeaturesKHR", + &structs->shader_integer_dot_product_features_khr); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, + VkJsonIMGRelaxedLineRasterization* structs) { + return visitor->Visit("relaxedLineRasterizationFeaturesIMG", + &structs->relaxed_line_rasterization_features_img); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonKHRLineRasterization* structs) { + return visitor->Visit("lineRasterizationFeaturesKHR", + &structs->line_rasterization_features_khr); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonExtLineRasterization* structs) { + return visitor->Visit("lineRasterizationFeaturesEXT", + &structs->line_rasterization_features_ext); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, + VkJsonExtPrimitivesGeneratedQuery* structs) { + return visitor->Visit("primitivesGeneratedQueryFeaturesEXT", + &structs->primitives_generated_query_features_ext); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonKHRShaderFloatControls* structs) { + return visitor->Visit("floatControlsPropertiesKHR", + &structs->float_controls_properties_khr); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkJsonKHRDriverProperties* structs) { + return visitor->Visit("driverPropertiesKHR", &structs->driver_properties_khr); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceFloatControlsProperties* properties) { return - visitor->Visit("width", &extents->width) && - visitor->Visit("height", &extents->height) && - visitor->Visit("depth", &extents->depth); + + visitor->Visit("denormBehaviorIndependence", + &properties->denormBehaviorIndependence) && + visitor->Visit("roundingModeIndependence", + &properties->roundingModeIndependence) && + visitor->Visit("shaderSignedZeroInfNanPreserveFloat16", + &properties->shaderSignedZeroInfNanPreserveFloat16) && + visitor->Visit("shaderSignedZeroInfNanPreserveFloat32", + &properties->shaderSignedZeroInfNanPreserveFloat32) && + visitor->Visit("shaderSignedZeroInfNanPreserveFloat64", + &properties->shaderSignedZeroInfNanPreserveFloat64) && + visitor->Visit("shaderDenormPreserveFloat16", + &properties->shaderDenormPreserveFloat16) && + visitor->Visit("shaderDenormPreserveFloat32", + &properties->shaderDenormPreserveFloat32) && + visitor->Visit("shaderDenormPreserveFloat64", + &properties->shaderDenormPreserveFloat64) && + visitor->Visit("shaderDenormFlushToZeroFloat16", + &properties->shaderDenormFlushToZeroFloat16) && + visitor->Visit("shaderDenormFlushToZeroFloat32", + &properties->shaderDenormFlushToZeroFloat32) && + visitor->Visit("shaderDenormFlushToZeroFloat64", + &properties->shaderDenormFlushToZeroFloat64) && + visitor->Visit("shaderRoundingModeRTEFloat16", + &properties->shaderRoundingModeRTEFloat16) && + visitor->Visit("shaderRoundingModeRTEFloat32", + &properties->shaderRoundingModeRTEFloat32) && + visitor->Visit("shaderRoundingModeRTEFloat64", + &properties->shaderRoundingModeRTEFloat64) && + visitor->Visit("shaderRoundingModeRTZFloat16", + &properties->shaderRoundingModeRTZFloat16) && + visitor->Visit("shaderRoundingModeRTZFloat32", + &properties->shaderRoundingModeRTZFloat32) && + visitor->Visit("shaderRoundingModeRTZFloat64", + &properties->shaderRoundingModeRTZFloat64); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkImageFormatProperties* properties) { +inline bool Iterate(Visitor* visitor, VkPhysicalDeviceProperties* properties) { return - visitor->Visit("maxExtent", &properties->maxExtent) && - visitor->Visit("maxMipLevels", &properties->maxMipLevels) && - visitor->Visit("maxArrayLayers", &properties->maxArrayLayers) && - visitor->Visit("sampleCounts", &properties->sampleCounts) && - visitor->Visit("maxResourceSize", &properties->maxResourceSize); + + visitor->Visit("apiVersion", &properties->apiVersion) && + visitor->Visit("driverVersion", &properties->driverVersion) && + visitor->Visit("vendorID", &properties->vendorID) && + visitor->Visit("deviceID", &properties->deviceID) && + visitor->Visit("deviceType", &properties->deviceType) && + visitor->Visit("deviceName", &properties->deviceName) && + visitor->Visit("pipelineCacheUUID", &properties->pipelineCacheUUID) && + visitor->Visit("limits", &properties->limits) && + visitor->Visit("sparseProperties", &properties->sparseProperties); } -// clang-format off template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkPhysicalDeviceLimits* limits) { +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceMemoryProperties* properties) { return - visitor->Visit("maxImageDimension1D", &limits->maxImageDimension1D) && - visitor->Visit("maxImageDimension2D", &limits->maxImageDimension2D) && - visitor->Visit("maxImageDimension3D", &limits->maxImageDimension3D) && - visitor->Visit("maxImageDimensionCube", &limits->maxImageDimensionCube) && - visitor->Visit("maxImageArrayLayers", &limits->maxImageArrayLayers) && - visitor->Visit("maxTexelBufferElements", &limits->maxTexelBufferElements) && - visitor->Visit("maxUniformBufferRange", &limits->maxUniformBufferRange) && - visitor->Visit("maxStorageBufferRange", &limits->maxStorageBufferRange) && - visitor->Visit("maxPushConstantsSize", &limits->maxPushConstantsSize) && - visitor->Visit("maxMemoryAllocationCount", &limits->maxMemoryAllocationCount) && - visitor->Visit("maxSamplerAllocationCount", &limits->maxSamplerAllocationCount) && - visitor->Visit("bufferImageGranularity", &limits->bufferImageGranularity) && - visitor->Visit("sparseAddressSpaceSize", &limits->sparseAddressSpaceSize) && - visitor->Visit("maxBoundDescriptorSets", &limits->maxBoundDescriptorSets) && - visitor->Visit("maxPerStageDescriptorSamplers", &limits->maxPerStageDescriptorSamplers) && - visitor->Visit("maxPerStageDescriptorUniformBuffers", &limits->maxPerStageDescriptorUniformBuffers) && - visitor->Visit("maxPerStageDescriptorStorageBuffers", &limits->maxPerStageDescriptorStorageBuffers) && - visitor->Visit("maxPerStageDescriptorSampledImages", &limits->maxPerStageDescriptorSampledImages) && - visitor->Visit("maxPerStageDescriptorStorageImages", &limits->maxPerStageDescriptorStorageImages) && - visitor->Visit("maxPerStageDescriptorInputAttachments", &limits->maxPerStageDescriptorInputAttachments) && - visitor->Visit("maxPerStageResources", &limits->maxPerStageResources) && - visitor->Visit("maxDescriptorSetSamplers", &limits->maxDescriptorSetSamplers) && - visitor->Visit("maxDescriptorSetUniformBuffers", &limits->maxDescriptorSetUniformBuffers) && - visitor->Visit("maxDescriptorSetUniformBuffersDynamic", &limits->maxDescriptorSetUniformBuffersDynamic) && - visitor->Visit("maxDescriptorSetStorageBuffers", &limits->maxDescriptorSetStorageBuffers) && - visitor->Visit("maxDescriptorSetStorageBuffersDynamic", &limits->maxDescriptorSetStorageBuffersDynamic) && - visitor->Visit("maxDescriptorSetSampledImages", &limits->maxDescriptorSetSampledImages) && - visitor->Visit("maxDescriptorSetStorageImages", &limits->maxDescriptorSetStorageImages) && - visitor->Visit("maxDescriptorSetInputAttachments", &limits->maxDescriptorSetInputAttachments) && - visitor->Visit("maxVertexInputAttributes", &limits->maxVertexInputAttributes) && - visitor->Visit("maxVertexInputBindings", &limits->maxVertexInputBindings) && - visitor->Visit("maxVertexInputAttributeOffset", &limits->maxVertexInputAttributeOffset) && - visitor->Visit("maxVertexInputBindingStride", &limits->maxVertexInputBindingStride) && - visitor->Visit("maxVertexOutputComponents", &limits->maxVertexOutputComponents) && - visitor->Visit("maxTessellationGenerationLevel", &limits->maxTessellationGenerationLevel) && - visitor->Visit("maxTessellationPatchSize", &limits->maxTessellationPatchSize) && - visitor->Visit("maxTessellationControlPerVertexInputComponents", &limits->maxTessellationControlPerVertexInputComponents) && - visitor->Visit("maxTessellationControlPerVertexOutputComponents", &limits->maxTessellationControlPerVertexOutputComponents) && - visitor->Visit("maxTessellationControlPerPatchOutputComponents", &limits->maxTessellationControlPerPatchOutputComponents) && - visitor->Visit("maxTessellationControlTotalOutputComponents", &limits->maxTessellationControlTotalOutputComponents) && - visitor->Visit("maxTessellationEvaluationInputComponents", &limits->maxTessellationEvaluationInputComponents) && - visitor->Visit("maxTessellationEvaluationOutputComponents", &limits->maxTessellationEvaluationOutputComponents) && - visitor->Visit("maxGeometryShaderInvocations", &limits->maxGeometryShaderInvocations) && - visitor->Visit("maxGeometryInputComponents", &limits->maxGeometryInputComponents) && - visitor->Visit("maxGeometryOutputComponents", &limits->maxGeometryOutputComponents) && - visitor->Visit("maxGeometryOutputVertices", &limits->maxGeometryOutputVertices) && - visitor->Visit("maxGeometryTotalOutputComponents", &limits->maxGeometryTotalOutputComponents) && - visitor->Visit("maxFragmentInputComponents", &limits->maxFragmentInputComponents) && - visitor->Visit("maxFragmentOutputAttachments", &limits->maxFragmentOutputAttachments) && - visitor->Visit("maxFragmentDualSrcAttachments", &limits->maxFragmentDualSrcAttachments) && - visitor->Visit("maxFragmentCombinedOutputResources", &limits->maxFragmentCombinedOutputResources) && - visitor->Visit("maxComputeSharedMemorySize", &limits->maxComputeSharedMemorySize) && - visitor->Visit("maxComputeWorkGroupCount", &limits->maxComputeWorkGroupCount) && - visitor->Visit("maxComputeWorkGroupInvocations", &limits->maxComputeWorkGroupInvocations) && - visitor->Visit("maxComputeWorkGroupSize", &limits->maxComputeWorkGroupSize) && - visitor->Visit("subPixelPrecisionBits", &limits->subPixelPrecisionBits) && - visitor->Visit("subTexelPrecisionBits", &limits->subTexelPrecisionBits) && - visitor->Visit("mipmapPrecisionBits", &limits->mipmapPrecisionBits) && - visitor->Visit("maxDrawIndexedIndexValue", &limits->maxDrawIndexedIndexValue) && - visitor->Visit("maxDrawIndirectCount", &limits->maxDrawIndirectCount) && - visitor->Visit("maxSamplerLodBias", &limits->maxSamplerLodBias) && - visitor->Visit("maxSamplerAnisotropy", &limits->maxSamplerAnisotropy) && - visitor->Visit("maxViewports", &limits->maxViewports) && - visitor->Visit("maxViewportDimensions", &limits->maxViewportDimensions) && - visitor->Visit("viewportBoundsRange", &limits->viewportBoundsRange) && - visitor->Visit("viewportSubPixelBits", &limits->viewportSubPixelBits) && - visitor->Visit("minMemoryMapAlignment", &limits->minMemoryMapAlignment) && - visitor->Visit("minTexelBufferOffsetAlignment", &limits->minTexelBufferOffsetAlignment) && - visitor->Visit("minUniformBufferOffsetAlignment", &limits->minUniformBufferOffsetAlignment) && - visitor->Visit("minStorageBufferOffsetAlignment", &limits->minStorageBufferOffsetAlignment) && - visitor->Visit("minTexelOffset", &limits->minTexelOffset) && - visitor->Visit("maxTexelOffset", &limits->maxTexelOffset) && - visitor->Visit("minTexelGatherOffset", &limits->minTexelGatherOffset) && - visitor->Visit("maxTexelGatherOffset", &limits->maxTexelGatherOffset) && - visitor->Visit("minInterpolationOffset", &limits->minInterpolationOffset) && - visitor->Visit("maxInterpolationOffset", &limits->maxInterpolationOffset) && - visitor->Visit("subPixelInterpolationOffsetBits", &limits->subPixelInterpolationOffsetBits) && - visitor->Visit("maxFramebufferWidth", &limits->maxFramebufferWidth) && - visitor->Visit("maxFramebufferHeight", &limits->maxFramebufferHeight) && - visitor->Visit("maxFramebufferLayers", &limits->maxFramebufferLayers) && - visitor->Visit("framebufferColorSampleCounts", &limits->framebufferColorSampleCounts) && - visitor->Visit("framebufferDepthSampleCounts", &limits->framebufferDepthSampleCounts) && - visitor->Visit("framebufferStencilSampleCounts", &limits->framebufferStencilSampleCounts) && - visitor->Visit("framebufferNoAttachmentsSampleCounts", &limits->framebufferNoAttachmentsSampleCounts) && - visitor->Visit("maxColorAttachments", &limits->maxColorAttachments) && - visitor->Visit("sampledImageColorSampleCounts", &limits->sampledImageColorSampleCounts) && - visitor->Visit("sampledImageIntegerSampleCounts", &limits->sampledImageIntegerSampleCounts) && - visitor->Visit("sampledImageDepthSampleCounts", &limits->sampledImageDepthSampleCounts) && - visitor->Visit("sampledImageStencilSampleCounts", &limits->sampledImageStencilSampleCounts) && - visitor->Visit("storageImageSampleCounts", &limits->storageImageSampleCounts) && - visitor->Visit("maxSampleMaskWords", &limits->maxSampleMaskWords) && - visitor->Visit("timestampComputeAndGraphics", &limits->timestampComputeAndGraphics) && - visitor->Visit("timestampPeriod", &limits->timestampPeriod) && - visitor->Visit("maxClipDistances", &limits->maxClipDistances) && - visitor->Visit("maxCullDistances", &limits->maxCullDistances) && - visitor->Visit("maxCombinedClipAndCullDistances", &limits->maxCombinedClipAndCullDistances) && - visitor->Visit("discreteQueuePriorities", &limits->discreteQueuePriorities) && - visitor->Visit("pointSizeRange", &limits->pointSizeRange) && - visitor->Visit("lineWidthRange", &limits->lineWidthRange) && - visitor->Visit("pointSizeGranularity", &limits->pointSizeGranularity) && - visitor->Visit("lineWidthGranularity", &limits->lineWidthGranularity) && - visitor->Visit("strictLines", &limits->strictLines) && - visitor->Visit("standardSampleLocations", &limits->standardSampleLocations) && - visitor->Visit("optimalBufferCopyOffsetAlignment", &limits->optimalBufferCopyOffsetAlignment) && - visitor->Visit("optimalBufferCopyRowPitchAlignment", &limits->optimalBufferCopyRowPitchAlignment) && - visitor->Visit("nonCoherentAtomSize", &limits->nonCoherentAtomSize); + + visitor->Visit("memoryTypeCount", &properties->memoryTypeCount) && + visitor->VisitArray("memoryTypes", properties->memoryTypeCount, + &properties->memoryTypes) && + visitor->Visit("memoryHeapCount", &properties->memoryHeapCount) && + visitor->VisitArray("memoryHeaps", properties->memoryHeapCount, + &properties->memoryHeaps); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceSparseProperties* properties) { + VkPhysicalDeviceSubgroupProperties* properties) { return - visitor->Visit("residencyStandard2DBlockShape", &properties->residencyStandard2DBlockShape) && - visitor->Visit("residencyStandard2DMultisampleBlockShape", &properties->residencyStandard2DMultisampleBlockShape) && - visitor->Visit("residencyStandard3DBlockShape", &properties->residencyStandard3DBlockShape) && - visitor->Visit("residencyAlignedMipSize", &properties->residencyAlignedMipSize) && - visitor->Visit("residencyNonResidentStrict", &properties->residencyNonResidentStrict); + + visitor->Visit("subgroupSize", &properties->subgroupSize) && + visitor->Visit("supportedStages", &properties->supportedStages) && + visitor->Visit("supportedOperations", &properties->supportedOperations) && + visitor->Visit("quadOperationsInAllStages", + &properties->quadOperationsInAllStages); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceProperties* properties) { + VkPhysicalDevicePointClippingProperties* properties) { return - visitor->Visit("apiVersion", &properties->apiVersion) && - visitor->Visit("driverVersion", &properties->driverVersion) && - visitor->Visit("vendorID", &properties->vendorID) && - visitor->Visit("deviceID", &properties->deviceID) && - visitor->Visit("deviceType", &properties->deviceType) && - visitor->Visit("deviceName", &properties->deviceName) && - visitor->Visit("pipelineCacheUUID", &properties->pipelineCacheUUID) && - visitor->Visit("limits", &properties->limits) && - visitor->Visit("sparseProperties", &properties->sparseProperties); + + visitor->Visit("pointClippingBehavior", + &properties->pointClippingBehavior); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkPhysicalDeviceFeatures* features) { +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceMultiviewProperties* properties) { return - visitor->Visit("robustBufferAccess", &features->robustBufferAccess) && - visitor->Visit("fullDrawIndexUint32", &features->fullDrawIndexUint32) && - visitor->Visit("imageCubeArray", &features->imageCubeArray) && - visitor->Visit("independentBlend", &features->independentBlend) && - visitor->Visit("geometryShader", &features->geometryShader) && - visitor->Visit("tessellationShader", &features->tessellationShader) && - visitor->Visit("sampleRateShading", &features->sampleRateShading) && - visitor->Visit("dualSrcBlend", &features->dualSrcBlend) && - visitor->Visit("logicOp", &features->logicOp) && - visitor->Visit("multiDrawIndirect", &features->multiDrawIndirect) && - visitor->Visit("drawIndirectFirstInstance", &features->drawIndirectFirstInstance) && - visitor->Visit("depthClamp", &features->depthClamp) && - visitor->Visit("depthBiasClamp", &features->depthBiasClamp) && - visitor->Visit("fillModeNonSolid", &features->fillModeNonSolid) && - visitor->Visit("depthBounds", &features->depthBounds) && - visitor->Visit("wideLines", &features->wideLines) && - visitor->Visit("largePoints", &features->largePoints) && - visitor->Visit("alphaToOne", &features->alphaToOne) && - visitor->Visit("multiViewport", &features->multiViewport) && - visitor->Visit("samplerAnisotropy", &features->samplerAnisotropy) && - visitor->Visit("textureCompressionETC2", &features->textureCompressionETC2) && - visitor->Visit("textureCompressionASTC_LDR", &features->textureCompressionASTC_LDR) && - visitor->Visit("textureCompressionBC", &features->textureCompressionBC) && - visitor->Visit("occlusionQueryPrecise", &features->occlusionQueryPrecise) && - visitor->Visit("pipelineStatisticsQuery", &features->pipelineStatisticsQuery) && - visitor->Visit("vertexPipelineStoresAndAtomics", &features->vertexPipelineStoresAndAtomics) && - visitor->Visit("fragmentStoresAndAtomics", &features->fragmentStoresAndAtomics) && - visitor->Visit("shaderTessellationAndGeometryPointSize", &features->shaderTessellationAndGeometryPointSize) && - visitor->Visit("shaderImageGatherExtended", &features->shaderImageGatherExtended) && - visitor->Visit("shaderStorageImageExtendedFormats", &features->shaderStorageImageExtendedFormats) && - visitor->Visit("shaderStorageImageMultisample", &features->shaderStorageImageMultisample) && - visitor->Visit("shaderStorageImageReadWithoutFormat", &features->shaderStorageImageReadWithoutFormat) && - visitor->Visit("shaderStorageImageWriteWithoutFormat", &features->shaderStorageImageWriteWithoutFormat) && - visitor->Visit("shaderUniformBufferArrayDynamicIndexing", &features->shaderUniformBufferArrayDynamicIndexing) && - visitor->Visit("shaderSampledImageArrayDynamicIndexing", &features->shaderSampledImageArrayDynamicIndexing) && - visitor->Visit("shaderStorageBufferArrayDynamicIndexing", &features->shaderStorageBufferArrayDynamicIndexing) && - visitor->Visit("shaderStorageImageArrayDynamicIndexing", &features->shaderStorageImageArrayDynamicIndexing) && - visitor->Visit("shaderClipDistance", &features->shaderClipDistance) && - visitor->Visit("shaderCullDistance", &features->shaderCullDistance) && - visitor->Visit("shaderFloat64", &features->shaderFloat64) && - visitor->Visit("shaderInt64", &features->shaderInt64) && - visitor->Visit("shaderInt16", &features->shaderInt16) && - visitor->Visit("shaderResourceResidency", &features->shaderResourceResidency) && - visitor->Visit("shaderResourceMinLod", &features->shaderResourceMinLod) && - visitor->Visit("sparseBinding", &features->sparseBinding) && - visitor->Visit("sparseResidencyBuffer", &features->sparseResidencyBuffer) && - visitor->Visit("sparseResidencyImage2D", &features->sparseResidencyImage2D) && - visitor->Visit("sparseResidencyImage3D", &features->sparseResidencyImage3D) && - visitor->Visit("sparseResidency2Samples", &features->sparseResidency2Samples) && - visitor->Visit("sparseResidency4Samples", &features->sparseResidency4Samples) && - visitor->Visit("sparseResidency8Samples", &features->sparseResidency8Samples) && - visitor->Visit("sparseResidency16Samples", &features->sparseResidency16Samples) && - visitor->Visit("sparseResidencyAliased", &features->sparseResidencyAliased) && - visitor->Visit("variableMultisampleRate", &features->variableMultisampleRate) && - visitor->Visit("inheritedQueries", &features->inheritedQueries); + + visitor->Visit("maxMultiviewViewCount", + &properties->maxMultiviewViewCount) && + visitor->Visit("maxMultiviewInstanceIndex", + &properties->maxMultiviewInstanceIndex); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkJsonCore12* core) { +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceIDProperties* properties) { return - visitor->Visit("features", &core->features) && - visitor->Visit("properties", &core->properties); + + visitor->Visit("deviceUUID", &properties->deviceUUID) && + visitor->Visit("driverUUID", &properties->driverUUID) && + visitor->Visit("deviceLUID", &properties->deviceLUID) && + visitor->Visit("deviceNodeMask", &properties->deviceNodeMask) && + visitor->Visit("deviceLUIDValid", &properties->deviceLUIDValid); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkPhysicalDeviceVulkan12Properties* properties) { +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceMaintenance3Properties* properties) { return - visitor->Visit("driverID", &properties->driverID) && - visitor->Visit("driverName", &properties->driverName) && - visitor->Visit("driverInfo", &properties->driverInfo) && - visitor->Visit("conformanceVersion", &properties->conformanceVersion) && - visitor->Visit("denormBehaviorIndependence", &properties->denormBehaviorIndependence) && - visitor->Visit("roundingModeIndependence", &properties->roundingModeIndependence) && - visitor->Visit("shaderSignedZeroInfNanPreserveFloat16", &properties->shaderSignedZeroInfNanPreserveFloat16) && - visitor->Visit("shaderSignedZeroInfNanPreserveFloat32", &properties->shaderSignedZeroInfNanPreserveFloat32) && - visitor->Visit("shaderSignedZeroInfNanPreserveFloat64", &properties->shaderSignedZeroInfNanPreserveFloat64) && - visitor->Visit("shaderDenormPreserveFloat16", &properties->shaderDenormPreserveFloat16) && - visitor->Visit("shaderDenormPreserveFloat32", &properties->shaderDenormPreserveFloat32) && - visitor->Visit("shaderDenormPreserveFloat64", &properties->shaderDenormPreserveFloat64) && - visitor->Visit("shaderDenormFlushToZeroFloat16", &properties->shaderDenormFlushToZeroFloat16) && - visitor->Visit("shaderDenormFlushToZeroFloat32", &properties->shaderDenormFlushToZeroFloat32) && - visitor->Visit("shaderDenormFlushToZeroFloat64", &properties->shaderDenormFlushToZeroFloat64) && - visitor->Visit("shaderRoundingModeRTEFloat16", &properties->shaderRoundingModeRTEFloat16) && - visitor->Visit("shaderRoundingModeRTEFloat32", &properties->shaderRoundingModeRTEFloat32) && - visitor->Visit("shaderRoundingModeRTEFloat64", &properties->shaderRoundingModeRTEFloat64) && - visitor->Visit("shaderRoundingModeRTZFloat16", &properties->shaderRoundingModeRTZFloat16) && - visitor->Visit("shaderRoundingModeRTZFloat32", &properties->shaderRoundingModeRTZFloat32) && - visitor->Visit("shaderRoundingModeRTZFloat64", &properties->shaderRoundingModeRTZFloat64) && - visitor->Visit("maxUpdateAfterBindDescriptorsInAllPools", &properties->maxUpdateAfterBindDescriptorsInAllPools) && - visitor->Visit("shaderUniformBufferArrayNonUniformIndexingNative", &properties->shaderUniformBufferArrayNonUniformIndexingNative) && - visitor->Visit("shaderSampledImageArrayNonUniformIndexingNative", &properties->shaderSampledImageArrayNonUniformIndexingNative) && - visitor->Visit("shaderStorageBufferArrayNonUniformIndexingNative", &properties->shaderStorageBufferArrayNonUniformIndexingNative) && - visitor->Visit("shaderStorageImageArrayNonUniformIndexingNative", &properties->shaderStorageImageArrayNonUniformIndexingNative) && - visitor->Visit("shaderInputAttachmentArrayNonUniformIndexingNative", &properties->shaderInputAttachmentArrayNonUniformIndexingNative) && - visitor->Visit("robustBufferAccessUpdateAfterBind", &properties->robustBufferAccessUpdateAfterBind) && - visitor->Visit("quadDivergentImplicitLod", &properties->quadDivergentImplicitLod) && - visitor->Visit("maxPerStageDescriptorUpdateAfterBindSamplers", &properties->maxPerStageDescriptorUpdateAfterBindSamplers) && - visitor->Visit("maxPerStageDescriptorUpdateAfterBindUniformBuffers", &properties->maxPerStageDescriptorUpdateAfterBindUniformBuffers) && - visitor->Visit("maxPerStageDescriptorUpdateAfterBindStorageBuffers", &properties->maxPerStageDescriptorUpdateAfterBindStorageBuffers) && - visitor->Visit("maxPerStageDescriptorUpdateAfterBindSampledImages", &properties->maxPerStageDescriptorUpdateAfterBindSampledImages) && - visitor->Visit("maxPerStageDescriptorUpdateAfterBindStorageImages", &properties->maxPerStageDescriptorUpdateAfterBindStorageImages) && - visitor->Visit("maxPerStageDescriptorUpdateAfterBindInputAttachments", &properties->maxPerStageDescriptorUpdateAfterBindInputAttachments) && - visitor->Visit("maxPerStageUpdateAfterBindResources", &properties->maxPerStageUpdateAfterBindResources) && - visitor->Visit("maxDescriptorSetUpdateAfterBindSamplers", &properties->maxDescriptorSetUpdateAfterBindSamplers) && - visitor->Visit("maxDescriptorSetUpdateAfterBindUniformBuffers", &properties->maxDescriptorSetUpdateAfterBindUniformBuffers) && - visitor->Visit("maxDescriptorSetUpdateAfterBindUniformBuffersDynamic", &properties->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic) && - visitor->Visit("maxDescriptorSetUpdateAfterBindStorageBuffers", &properties->maxDescriptorSetUpdateAfterBindStorageBuffers) && - visitor->Visit("maxDescriptorSetUpdateAfterBindStorageBuffersDynamic", &properties->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic) && - visitor->Visit("maxDescriptorSetUpdateAfterBindSampledImages", &properties->maxDescriptorSetUpdateAfterBindSampledImages) && - visitor->Visit("maxDescriptorSetUpdateAfterBindStorageImages", &properties->maxDescriptorSetUpdateAfterBindStorageImages) && - visitor->Visit("maxDescriptorSetUpdateAfterBindInputAttachments", &properties->maxDescriptorSetUpdateAfterBindInputAttachments) && - visitor->Visit("supportedDepthResolveModes", &properties->supportedDepthResolveModes) && - visitor->Visit("supportedStencilResolveModes", &properties->supportedStencilResolveModes) && - visitor->Visit("independentResolveNone", &properties->independentResolveNone) && - visitor->Visit("independentResolve", &properties->independentResolve) && - visitor->Visit("filterMinmaxSingleComponentFormats", &properties->filterMinmaxSingleComponentFormats) && - visitor->Visit("filterMinmaxImageComponentMapping", &properties->filterMinmaxImageComponentMapping) && - visitor->Visit("maxTimelineSemaphoreValueDifference", &properties->maxTimelineSemaphoreValueDifference) && - visitor->Visit("framebufferIntegerColorSampleCounts", &properties->framebufferIntegerColorSampleCounts); -} - -template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkPhysicalDeviceVulkan12Features* features) { + + visitor->Visit("maxPerSetDescriptors", + &properties->maxPerSetDescriptors) && + visitor->Visit("maxMemoryAllocationSize", + &properties->maxMemoryAllocationSize); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceSparseProperties* properties) { return - visitor->Visit("samplerMirrorClampToEdge", &features->samplerMirrorClampToEdge) && - visitor->Visit("drawIndirectCount", &features->drawIndirectCount) && - visitor->Visit("storageBuffer8BitAccess", &features->storageBuffer8BitAccess) && - visitor->Visit("uniformAndStorageBuffer8BitAccess", &features->uniformAndStorageBuffer8BitAccess) && - visitor->Visit("storagePushConstant8", &features->storagePushConstant8) && - visitor->Visit("shaderBufferInt64Atomics", &features->shaderBufferInt64Atomics) && - visitor->Visit("shaderSharedInt64Atomics", &features->shaderSharedInt64Atomics) && - visitor->Visit("shaderFloat16", &features->shaderFloat16) && - visitor->Visit("shaderInt8", &features->shaderInt8) && - visitor->Visit("descriptorIndexing", &features->descriptorIndexing) && - visitor->Visit("shaderInputAttachmentArrayDynamicIndexing", &features->shaderInputAttachmentArrayDynamicIndexing) && - visitor->Visit("shaderUniformTexelBufferArrayDynamicIndexing", &features->shaderUniformTexelBufferArrayDynamicIndexing) && - visitor->Visit("shaderStorageTexelBufferArrayDynamicIndexing", &features->shaderStorageTexelBufferArrayDynamicIndexing) && - visitor->Visit("shaderUniformBufferArrayNonUniformIndexing", &features->shaderUniformBufferArrayNonUniformIndexing) && - visitor->Visit("shaderSampledImageArrayNonUniformIndexing", &features->shaderSampledImageArrayNonUniformIndexing) && - visitor->Visit("shaderStorageBufferArrayNonUniformIndexing", &features->shaderStorageBufferArrayNonUniformIndexing) && - visitor->Visit("shaderStorageImageArrayNonUniformIndexing", &features->shaderStorageImageArrayNonUniformIndexing) && - visitor->Visit("shaderInputAttachmentArrayNonUniformIndexing", &features->shaderInputAttachmentArrayNonUniformIndexing) && - visitor->Visit("shaderUniformTexelBufferArrayNonUniformIndexing", &features->shaderUniformTexelBufferArrayNonUniformIndexing) && - visitor->Visit("shaderStorageTexelBufferArrayNonUniformIndexing", &features->shaderStorageTexelBufferArrayNonUniformIndexing) && - visitor->Visit("descriptorBindingUniformBufferUpdateAfterBind", &features->descriptorBindingUniformBufferUpdateAfterBind) && - visitor->Visit("descriptorBindingSampledImageUpdateAfterBind", &features->descriptorBindingSampledImageUpdateAfterBind) && - visitor->Visit("descriptorBindingStorageImageUpdateAfterBind", &features->descriptorBindingStorageImageUpdateAfterBind) && - visitor->Visit("descriptorBindingStorageBufferUpdateAfterBind", &features->descriptorBindingStorageBufferUpdateAfterBind) && - visitor->Visit("descriptorBindingUniformTexelBufferUpdateAfterBind", &features->descriptorBindingUniformTexelBufferUpdateAfterBind) && - visitor->Visit("descriptorBindingStorageTexelBufferUpdateAfterBind", &features->descriptorBindingStorageTexelBufferUpdateAfterBind) && - visitor->Visit("descriptorBindingUpdateUnusedWhilePending", &features->descriptorBindingUpdateUnusedWhilePending) && - visitor->Visit("descriptorBindingPartiallyBound", &features->descriptorBindingPartiallyBound) && - visitor->Visit("descriptorBindingVariableDescriptorCount", &features->descriptorBindingVariableDescriptorCount) && - visitor->Visit("runtimeDescriptorArray", &features->runtimeDescriptorArray) && - visitor->Visit("samplerFilterMinmax", &features->samplerFilterMinmax) && - visitor->Visit("scalarBlockLayout", &features->scalarBlockLayout) && - visitor->Visit("imagelessFramebuffer", &features->imagelessFramebuffer) && - visitor->Visit("uniformBufferStandardLayout", &features->uniformBufferStandardLayout) && - visitor->Visit("shaderSubgroupExtendedTypes", &features->shaderSubgroupExtendedTypes) && - visitor->Visit("separateDepthStencilLayouts", &features->separateDepthStencilLayouts) && - visitor->Visit("hostQueryReset", &features->hostQueryReset) && - visitor->Visit("timelineSemaphore", &features->timelineSemaphore) && - visitor->Visit("bufferDeviceAddress", &features->bufferDeviceAddress) && - visitor->Visit("bufferDeviceAddressCaptureReplay", &features->bufferDeviceAddressCaptureReplay) && - visitor->Visit("bufferDeviceAddressMultiDevice", &features->bufferDeviceAddressMultiDevice) && - visitor->Visit("vulkanMemoryModel", &features->vulkanMemoryModel) && - visitor->Visit("vulkanMemoryModelDeviceScope", &features->vulkanMemoryModelDeviceScope) && - visitor->Visit("vulkanMemoryModelAvailabilityVisibilityChains", &features->vulkanMemoryModelAvailabilityVisibilityChains) && - visitor->Visit("shaderOutputViewportIndex", &features->shaderOutputViewportIndex) && - visitor->Visit("shaderOutputLayer", &features->shaderOutputLayer) && - visitor->Visit("subgroupBroadcastDynamicId", &features->subgroupBroadcastDynamicId); + + visitor->Visit("residencyStandard2DBlockShape", + &properties->residencyStandard2DBlockShape) && + visitor->Visit("residencyStandard2DMultisampleBlockShape", + &properties->residencyStandard2DMultisampleBlockShape) && + visitor->Visit("residencyStandard3DBlockShape", + &properties->residencyStandard3DBlockShape) && + visitor->Visit("residencyAlignedMipSize", + &properties->residencyAlignedMipSize) && + visitor->Visit("residencyNonResidentStrict", + &properties->residencyNonResidentStrict); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkJsonCore13* core) { +inline bool Iterate(Visitor* visitor, VkImageFormatProperties* properties) { return - visitor->Visit("features", &core->features) && - visitor->Visit("properties", &core->properties); + + visitor->Visit("maxExtent", &properties->maxExtent) && + visitor->Visit("maxMipLevels", &properties->maxMipLevels) && + visitor->Visit("maxArrayLayers", &properties->maxArrayLayers) && + visitor->Visit("sampleCounts", &properties->sampleCounts) && + visitor->Visit("maxResourceSize", &properties->maxResourceSize); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkPhysicalDeviceVulkan13Properties* properties) { +inline bool Iterate(Visitor* visitor, VkQueueFamilyProperties* properties) { return - visitor->Visit("minSubgroupSize", &properties->minSubgroupSize) && - visitor->Visit("maxSubgroupSize", &properties->maxSubgroupSize) && - visitor->Visit("maxComputeWorkgroupSubgroups", &properties->maxComputeWorkgroupSubgroups) && - visitor->Visit("requiredSubgroupSizeStages", &properties->requiredSubgroupSizeStages) && - visitor->Visit("maxInlineUniformBlockSize", &properties->maxInlineUniformBlockSize) && - visitor->Visit("maxPerStageDescriptorInlineUniformBlocks", &properties->maxPerStageDescriptorInlineUniformBlocks) && - visitor->Visit("maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks", &properties->maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks) && - visitor->Visit("maxDescriptorSetInlineUniformBlocks", &properties->maxDescriptorSetInlineUniformBlocks) && - visitor->Visit("maxDescriptorSetUpdateAfterBindInlineUniformBlocks", &properties->maxDescriptorSetUpdateAfterBindInlineUniformBlocks) && - visitor->Visit("maxInlineUniformTotalSize", &properties->maxInlineUniformTotalSize) && - visitor->Visit("integerDotProduct8BitUnsignedAccelerated", &properties->integerDotProduct8BitUnsignedAccelerated) && - visitor->Visit("integerDotProduct8BitSignedAccelerated", &properties->integerDotProduct8BitSignedAccelerated) && - visitor->Visit("integerDotProduct8BitMixedSignednessAccelerated", &properties->integerDotProduct8BitMixedSignednessAccelerated) && - visitor->Visit("integerDotProduct4x8BitPackedUnsignedAccelerated", &properties->integerDotProduct4x8BitPackedUnsignedAccelerated) && - visitor->Visit("integerDotProduct4x8BitPackedSignedAccelerated", &properties->integerDotProduct4x8BitPackedSignedAccelerated) && - visitor->Visit("integerDotProduct4x8BitPackedMixedSignednessAccelerated", &properties->integerDotProduct4x8BitPackedMixedSignednessAccelerated) && - visitor->Visit("integerDotProduct16BitUnsignedAccelerated", &properties->integerDotProduct16BitUnsignedAccelerated) && - visitor->Visit("integerDotProduct16BitSignedAccelerated", &properties->integerDotProduct16BitSignedAccelerated) && - visitor->Visit("integerDotProduct16BitMixedSignednessAccelerated", &properties->integerDotProduct16BitMixedSignednessAccelerated) && - visitor->Visit("integerDotProduct32BitUnsignedAccelerated", &properties->integerDotProduct32BitUnsignedAccelerated) && - visitor->Visit("integerDotProduct32BitSignedAccelerated", &properties->integerDotProduct32BitSignedAccelerated) && - visitor->Visit("integerDotProduct32BitMixedSignednessAccelerated", &properties->integerDotProduct32BitMixedSignednessAccelerated) && - visitor->Visit("integerDotProduct64BitUnsignedAccelerated", &properties->integerDotProduct64BitUnsignedAccelerated) && - visitor->Visit("integerDotProduct64BitSignedAccelerated", &properties->integerDotProduct64BitSignedAccelerated) && - visitor->Visit("integerDotProduct64BitMixedSignednessAccelerated", &properties->integerDotProduct64BitMixedSignednessAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating8BitUnsignedAccelerated", &properties->integerDotProductAccumulatingSaturating8BitUnsignedAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating8BitSignedAccelerated", &properties->integerDotProductAccumulatingSaturating8BitSignedAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated", &properties->integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated", &properties->integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated", &properties->integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated", &properties->integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating16BitUnsignedAccelerated", &properties->integerDotProductAccumulatingSaturating16BitUnsignedAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating16BitSignedAccelerated", &properties->integerDotProductAccumulatingSaturating16BitSignedAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated", &properties->integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating32BitUnsignedAccelerated", &properties->integerDotProductAccumulatingSaturating32BitUnsignedAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating32BitSignedAccelerated", &properties->integerDotProductAccumulatingSaturating32BitSignedAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated", &properties->integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating64BitUnsignedAccelerated", &properties->integerDotProductAccumulatingSaturating64BitUnsignedAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating64BitSignedAccelerated", &properties->integerDotProductAccumulatingSaturating64BitSignedAccelerated) && - visitor->Visit("integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated", &properties->integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated) && - visitor->Visit("storageTexelBufferOffsetAlignmentBytes", &properties->storageTexelBufferOffsetAlignmentBytes) && - visitor->Visit("storageTexelBufferOffsetSingleTexelAlignment", &properties->storageTexelBufferOffsetSingleTexelAlignment) && - visitor->Visit("uniformTexelBufferOffsetAlignmentBytes", &properties->uniformTexelBufferOffsetAlignmentBytes) && - visitor->Visit("uniformTexelBufferOffsetSingleTexelAlignment", &properties->uniformTexelBufferOffsetSingleTexelAlignment) && - visitor->Visit("maxBufferSize", &properties->maxBufferSize); -} - -template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkPhysicalDeviceVulkan13Features* features) { + + visitor->Visit("queueFlags", &properties->queueFlags) && + visitor->Visit("queueCount", &properties->queueCount) && + visitor->Visit("timestampValidBits", &properties->timestampValidBits) && + visitor->Visit("minImageTransferGranularity", + &properties->minImageTransferGranularity); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkExtensionProperties* properties) { return - visitor->Visit("robustImageAccess", &features->robustImageAccess) && - visitor->Visit("inlineUniformBlock", &features->inlineUniformBlock) && - visitor->Visit("descriptorBindingInlineUniformBlockUpdateAfterBind", &features->descriptorBindingInlineUniformBlockUpdateAfterBind) && - visitor->Visit("pipelineCreationCacheControl", &features->pipelineCreationCacheControl) && - visitor->Visit("privateData", &features->privateData) && - visitor->Visit("shaderDemoteToHelperInvocation", &features->shaderDemoteToHelperInvocation) && - visitor->Visit("shaderTerminateInvocation", &features->shaderTerminateInvocation) && - visitor->Visit("subgroupSizeControl", &features->subgroupSizeControl) && - visitor->Visit("computeFullSubgroups", &features->computeFullSubgroups) && - visitor->Visit("synchronization2", &features->synchronization2) && - visitor->Visit("textureCompressionASTC_HDR", &features->textureCompressionASTC_HDR) && - visitor->Visit("shaderZeroInitializeWorkgroupMemory", &features->shaderZeroInitializeWorkgroupMemory) && - visitor->Visit("dynamicRendering", &features->dynamicRendering) && - visitor->Visit("shaderIntegerDotProduct", &features->shaderIntegerDotProduct) && - visitor->Visit("maintenance4", &features->maintenance4); + + visitor->Visit("extensionName", &properties->extensionName) && + visitor->Visit("specVersion", &properties->specVersion); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkJsonCore14* core) { +inline bool Iterate(Visitor* visitor, VkLayerProperties* properties) { return - visitor->Visit("features", &core->features) && - visitor->Visit("properties", &core->properties); + + visitor->Visit("layerName", &properties->layerName) && + visitor->Visit("specVersion", &properties->specVersion) && + visitor->Visit("implementationVersion", + &properties->implementationVersion) && + visitor->Visit("description", &properties->description); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkPhysicalDeviceVulkan14Properties* properties) { +inline bool Iterate(Visitor* visitor, VkFormatProperties* properties) { return - visitor->Visit("lineSubPixelPrecisionBits", &properties->lineSubPixelPrecisionBits) && - visitor->Visit("maxVertexAttribDivisor", &properties->maxVertexAttribDivisor) && - visitor->Visit("supportsNonZeroFirstInstance", &properties->supportsNonZeroFirstInstance) && - visitor->Visit("maxPushDescriptors", &properties->maxPushDescriptors) && - visitor->Visit("dynamicRenderingLocalReadDepthStencilAttachments", &properties->dynamicRenderingLocalReadDepthStencilAttachments) && - visitor->Visit("dynamicRenderingLocalReadMultisampledAttachments", &properties->dynamicRenderingLocalReadMultisampledAttachments) && - visitor->Visit("earlyFragmentMultisampleCoverageAfterSampleCounting", &properties->earlyFragmentMultisampleCoverageAfterSampleCounting) && - visitor->Visit("earlyFragmentSampleMaskTestBeforeSampleCounting", &properties->earlyFragmentSampleMaskTestBeforeSampleCounting) && - visitor->Visit("depthStencilSwizzleOneSupport", &properties->depthStencilSwizzleOneSupport) && - visitor->Visit("polygonModePointSize", &properties->polygonModePointSize) && - visitor->Visit("nonStrictSinglePixelWideLinesUseParallelogram", &properties->nonStrictSinglePixelWideLinesUseParallelogram) && - visitor->Visit("nonStrictWideLinesUseParallelogram", &properties->nonStrictWideLinesUseParallelogram) && - visitor->Visit("blockTexelViewCompatibleMultipleLayers", &properties->blockTexelViewCompatibleMultipleLayers) && - visitor->Visit("maxCombinedImageSamplerDescriptorCount", &properties->maxCombinedImageSamplerDescriptorCount) && - visitor->Visit("fragmentShadingRateClampCombinerInputs", &properties->fragmentShadingRateClampCombinerInputs) && - visitor->Visit("defaultRobustnessStorageBuffers", &properties->defaultRobustnessStorageBuffers) && - visitor->Visit("defaultRobustnessUniformBuffers", &properties->defaultRobustnessUniformBuffers) && - visitor->Visit("defaultRobustnessVertexInputs", &properties->defaultRobustnessVertexInputs) && - visitor->Visit("defaultRobustnessImages", &properties->defaultRobustnessImages) && - visitor->Visit("copySrcLayoutCount", &properties->copySrcLayoutCount) && - visitor->VisitArray("pCopySrcLayouts", properties->copySrcLayoutCount, &properties->pCopySrcLayouts) && - visitor->Visit("copyDstLayoutCount", &properties->copyDstLayoutCount) && - visitor->VisitArray("pCopyDstLayouts", properties->copyDstLayoutCount, &properties->pCopyDstLayouts) && - visitor->Visit("optimalTilingLayoutUUID", &properties->optimalTilingLayoutUUID) && - visitor->Visit("identicalMemoryTypeRequirements", &properties->identicalMemoryTypeRequirements); -} - -template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkPhysicalDeviceVulkan14Features* features) { + + visitor->Visit("linearTilingFeatures", + &properties->linearTilingFeatures) && + visitor->Visit("optimalTilingFeatures", + &properties->optimalTilingFeatures) && + visitor->Visit("bufferFeatures", &properties->bufferFeatures); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceVariablePointersFeatures* features) { return - visitor->Visit("globalPriorityQuery", &features->globalPriorityQuery) && - visitor->Visit("shaderSubgroupRotate", &features->shaderSubgroupRotate) && - visitor->Visit("shaderSubgroupRotateClustered", &features->shaderSubgroupRotateClustered) && - visitor->Visit("shaderFloatControls2", &features->shaderFloatControls2) && - visitor->Visit("shaderExpectAssume", &features->shaderExpectAssume) && - visitor->Visit("rectangularLines", &features->rectangularLines) && - visitor->Visit("bresenhamLines", &features->bresenhamLines) && - visitor->Visit("smoothLines", &features->smoothLines) && - visitor->Visit("stippledRectangularLines", &features->stippledRectangularLines) && - visitor->Visit("stippledBresenhamLines", &features->stippledBresenhamLines) && - visitor->Visit("stippledSmoothLines", &features->stippledSmoothLines) && - visitor->Visit("vertexAttributeInstanceRateDivisor", &features->vertexAttributeInstanceRateDivisor) && - visitor->Visit("vertexAttributeInstanceRateZeroDivisor", &features->vertexAttributeInstanceRateZeroDivisor) && - visitor->Visit("indexTypeUint8", &features->indexTypeUint8) && - visitor->Visit("dynamicRenderingLocalRead", &features->dynamicRenderingLocalRead) && - visitor->Visit("maintenance5", &features->maintenance5) && - visitor->Visit("maintenance6", &features->maintenance6) && - visitor->Visit("pipelineProtectedAccess", &features->pipelineProtectedAccess) && - visitor->Visit("pipelineRobustness", &features->pipelineRobustness) && - visitor->Visit("hostImageCopy", &features->hostImageCopy); -} -// clang-format on + + visitor->Visit("variablePointersStorageBuffer", + &features->variablePointersStorageBuffer) && + visitor->Visit("variablePointers", &features->variablePointers); +} template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkJsonExtDriverProperties* properties) { - return visitor->Visit("driverPropertiesKHR", - &properties->driver_properties_khr); + VkPhysicalDeviceShaderFloat16Int8Features* features) { + return + + visitor->Visit("shaderFloat16", &features->shaderFloat16) && + visitor->Visit("shaderInt8", &features->shaderInt8); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceDriverPropertiesKHR* properties) { - return visitor->Visit("driverID", &properties->driverID) && - visitor->Visit("driverName", &properties->driverName) && - visitor->Visit("driverInfo", &properties->driverInfo) && - visitor->Visit("conformanceVersion", &properties->conformanceVersion); + VkPhysicalDeviceImage2DViewOf3DFeaturesEXT* features) { + return + + visitor->Visit("image2DViewOf3D", &features->image2DViewOf3D) && + visitor->Visit("sampler2DViewOf3D", &features->sampler2DViewOf3D); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkConformanceVersionKHR* version) { - return visitor->Visit("major", &version->major) && - visitor->Visit("minor", &version->minor) && - visitor->Visit("subminor", &version->subminor) && - visitor->Visit("patch", &version->patch); + VkPhysicalDeviceCustomBorderColorFeaturesEXT* features) { + return + + visitor->Visit("customBorderColors", &features->customBorderColors) && + visitor->Visit("customBorderColorWithoutFormat", + &features->customBorderColorWithoutFormat); +} + +template <typename Visitor> +inline bool Iterate( + Visitor* visitor, + VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT* features) { + return + + visitor->Visit("primitiveTopologyListRestart", + &features->primitiveTopologyListRestart) && + visitor->Visit("primitiveTopologyPatchListRestart", + &features->primitiveTopologyPatchListRestart); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkJsonExtVariablePointerFeatures* features) { - return visitor->Visit("variablePointerFeaturesKHR", - &features->variable_pointer_features_khr); + VkPhysicalDeviceProvokingVertexFeaturesEXT* features) { + return + + visitor->Visit("provokingVertexLast", &features->provokingVertexLast) && + visitor->Visit("transformFeedbackPreservesProvokingVertex", + &features->transformFeedbackPreservesProvokingVertex); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkJsonExtImage2DViewOf3DFeatures* features) { - return visitor->Visit("image2DViewOf3DFeaturesEXT", - &features->image_2D_view_of_3D_features_EXT); + VkPhysicalDeviceIndexTypeUint8Features* features) { + return + + visitor->Visit("indexTypeUint8", &features->indexTypeUint8); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkJsonExtShaderFloat16Int8Features* features) { - return visitor->Visit("shaderFloat16Int8FeaturesKHR", - &features->shader_float16_int8_features_khr); + VkPhysicalDeviceVertexAttributeDivisorFeatures* features) { + return + + visitor->Visit("vertexAttributeInstanceRateDivisor", + &features->vertexAttributeInstanceRateDivisor) && + visitor->Visit("vertexAttributeInstanceRateZeroDivisor", + &features->vertexAttributeInstanceRateZeroDivisor); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkMemoryType* type) { +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceTransformFeedbackFeaturesEXT* features) { return - visitor->Visit("propertyFlags", &type->propertyFlags) && - visitor->Visit("heapIndex", &type->heapIndex); + + visitor->Visit("transformFeedback", &features->transformFeedback) && + visitor->Visit("geometryStreams", &features->geometryStreams); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkMemoryHeap* heap) { +inline bool Iterate( + Visitor* visitor, + VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR* features) { return - visitor->Visit("size", &heap->size) && - visitor->Visit("flags", &heap->flags); + + visitor->Visit("shaderSubgroupUniformControlFlow", + &features->shaderSubgroupUniformControlFlow); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkPhysicalDeviceMemoryProperties* properties) { +inline bool Iterate( + Visitor* visitor, + VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures* features) { return - visitor->Visit("memoryTypeCount", &properties->memoryTypeCount) && - visitor->VisitArray("memoryTypes", properties->memoryTypeCount, &properties->memoryTypes) && - visitor->Visit("memoryHeapCount", &properties->memoryHeapCount) && - visitor->VisitArray("memoryHeaps", properties->memoryHeapCount, &properties->memoryHeaps); + + visitor->Visit("shaderSubgroupExtendedTypes", + &features->shaderSubgroupExtendedTypes); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceSubgroupProperties* properties) { - return visitor->Visit("subgroupSize", &properties->subgroupSize) && - visitor->Visit("supportedStages", &properties->supportedStages) && - visitor->Visit("supportedOperations", - &properties->supportedOperations) && - visitor->Visit("quadOperationsInAllStages", - &properties->quadOperationsInAllStages); + VkPhysicalDevice8BitStorageFeatures* features) { + return + + visitor->Visit("storageBuffer8BitAccess", + &features->storageBuffer8BitAccess) && + visitor->Visit("uniformAndStorageBuffer8BitAccess", + &features->uniformAndStorageBuffer8BitAccess) && + visitor->Visit("storagePushConstant8", &features->storagePushConstant8); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkPhysicalDevicePointClippingProperties* properties) { - return visitor->Visit("pointClippingBehavior", - &properties->pointClippingBehavior); + VkPhysicalDeviceShaderIntegerDotProductFeatures* features) { + return + + visitor->Visit("shaderIntegerDotProduct", + &features->shaderIntegerDotProduct); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceMultiviewProperties* properties) { - return visitor->Visit("maxMultiviewViewCount", - &properties->maxMultiviewViewCount) && - visitor->Visit("maxMultiviewInstanceIndex", - &properties->maxMultiviewInstanceIndex); +inline bool Iterate( + Visitor* visitor, + VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG* features) { + return + + visitor->Visit("relaxedLineRasterization", + &features->relaxedLineRasterization); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceIDProperties* properties) { - return visitor->Visit("deviceUUID", &properties->deviceUUID) && - visitor->Visit("driverUUID", &properties->driverUUID) && - visitor->Visit("deviceLUID", &properties->deviceLUID) && - visitor->Visit("deviceNodeMask", &properties->deviceNodeMask) && - visitor->Visit("deviceLUIDValid", &properties->deviceLUIDValid); + VkPhysicalDeviceLineRasterizationFeatures* features) { + return + + visitor->Visit("rectangularLines", &features->rectangularLines) && + visitor->Visit("bresenhamLines", &features->bresenhamLines) && + visitor->Visit("smoothLines", &features->smoothLines) && + visitor->Visit("stippledRectangularLines", + &features->stippledRectangularLines) && + visitor->Visit("stippledBresenhamLines", + &features->stippledBresenhamLines) && + visitor->Visit("stippledSmoothLines", &features->stippledSmoothLines); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceMaintenance3Properties* properties) { - return visitor->Visit("maxPerSetDescriptors", - &properties->maxPerSetDescriptors) && - visitor->Visit("maxMemoryAllocationSize", - &properties->maxMemoryAllocationSize); +inline bool Iterate( + Visitor* visitor, + VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT* features) { + return + + visitor->Visit("primitivesGeneratedQuery", + &features->primitivesGeneratedQuery) && + visitor->Visit( + "primitivesGeneratedQueryWithRasterizerDiscard", + &features->primitivesGeneratedQueryWithRasterizerDiscard) && + visitor->Visit("primitivesGeneratedQueryWithNonZeroStreams", + &features->primitivesGeneratedQueryWithNonZeroStreams); } template <typename Visitor> inline bool Iterate(Visitor* visitor, VkPhysicalDevice16BitStorageFeatures* features) { - return visitor->Visit("storageBuffer16BitAccess", - &features->storageBuffer16BitAccess) && - visitor->Visit("uniformAndStorageBuffer16BitAccess", - &features->uniformAndStorageBuffer16BitAccess) && - visitor->Visit("storagePushConstant16", - &features->storagePushConstant16) && - visitor->Visit("storageInputOutput16", - &features->storageInputOutput16); + return + + visitor->Visit("storageBuffer16BitAccess", + &features->storageBuffer16BitAccess) && + visitor->Visit("uniformAndStorageBuffer16BitAccess", + &features->uniformAndStorageBuffer16BitAccess) && + visitor->Visit("storagePushConstant16", + &features->storagePushConstant16) && + visitor->Visit("storageInputOutput16", &features->storageInputOutput16); } template <typename Visitor> inline bool Iterate(Visitor* visitor, VkPhysicalDeviceMultiviewFeatures* features) { - return visitor->Visit("multiview", &features->multiview) && - visitor->Visit("multiviewGeometryShader", - &features->multiviewGeometryShader) && - visitor->Visit("multiviewTessellationShader", - &features->multiviewTessellationShader); + return + + visitor->Visit("multiview", &features->multiview) && + visitor->Visit("multiviewGeometryShader", + &features->multiviewGeometryShader) && + visitor->Visit("multiviewTessellationShader", + &features->multiviewTessellationShader); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceVariablePointerFeatures* features) { - return visitor->Visit("variablePointersStorageBuffer", - &features->variablePointersStorageBuffer) && - visitor->Visit("variablePointers", &features->variablePointers); + VkPhysicalDeviceProtectedMemoryFeatures* features) { + return + + visitor->Visit("protectedMemory", &features->protectedMemory); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceImage2DViewOf3DFeaturesEXT* features) { - return visitor->Visit("image2DViewOf3D", &features->image2DViewOf3D) && - visitor->Visit("sampler2DViewOf3D", &features->sampler2DViewOf3D); + VkPhysicalDeviceSamplerYcbcrConversionFeatures* features) { + return + + visitor->Visit("samplerYcbcrConversion", + &features->samplerYcbcrConversion); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceShaderFloat16Int8FeaturesKHR* features) { - return visitor->Visit("shaderFloat16", &features->shaderFloat16) && - visitor->Visit("shaderInt8", &features->shaderInt8); + VkPhysicalDeviceShaderDrawParameterFeatures* features) { + return + + visitor->Visit("shaderDrawParameters", &features->shaderDrawParameters); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkPhysicalDeviceLimits* limits) { + return + + visitor->Visit("maxImageDimension1D", &limits->maxImageDimension1D) && + visitor->Visit("maxImageDimension2D", &limits->maxImageDimension2D) && + visitor->Visit("maxImageDimension3D", &limits->maxImageDimension3D) && + visitor->Visit("maxImageDimensionCube", &limits->maxImageDimensionCube) && + visitor->Visit("maxImageArrayLayers", &limits->maxImageArrayLayers) && + visitor->Visit("maxTexelBufferElements", + &limits->maxTexelBufferElements) && + visitor->Visit("maxUniformBufferRange", &limits->maxUniformBufferRange) && + visitor->Visit("maxStorageBufferRange", &limits->maxStorageBufferRange) && + visitor->Visit("maxPushConstantsSize", &limits->maxPushConstantsSize) && + visitor->Visit("maxMemoryAllocationCount", + &limits->maxMemoryAllocationCount) && + visitor->Visit("maxSamplerAllocationCount", + &limits->maxSamplerAllocationCount) && + visitor->Visit("bufferImageGranularity", + &limits->bufferImageGranularity) && + visitor->Visit("sparseAddressSpaceSize", + &limits->sparseAddressSpaceSize) && + visitor->Visit("maxBoundDescriptorSets", + &limits->maxBoundDescriptorSets) && + visitor->Visit("maxPerStageDescriptorSamplers", + &limits->maxPerStageDescriptorSamplers) && + visitor->Visit("maxPerStageDescriptorUniformBuffers", + &limits->maxPerStageDescriptorUniformBuffers) && + visitor->Visit("maxPerStageDescriptorStorageBuffers", + &limits->maxPerStageDescriptorStorageBuffers) && + visitor->Visit("maxPerStageDescriptorSampledImages", + &limits->maxPerStageDescriptorSampledImages) && + visitor->Visit("maxPerStageDescriptorStorageImages", + &limits->maxPerStageDescriptorStorageImages) && + visitor->Visit("maxPerStageDescriptorInputAttachments", + &limits->maxPerStageDescriptorInputAttachments) && + visitor->Visit("maxPerStageResources", &limits->maxPerStageResources) && + visitor->Visit("maxDescriptorSetSamplers", + &limits->maxDescriptorSetSamplers) && + visitor->Visit("maxDescriptorSetUniformBuffers", + &limits->maxDescriptorSetUniformBuffers) && + visitor->Visit("maxDescriptorSetUniformBuffersDynamic", + &limits->maxDescriptorSetUniformBuffersDynamic) && + visitor->Visit("maxDescriptorSetStorageBuffers", + &limits->maxDescriptorSetStorageBuffers) && + visitor->Visit("maxDescriptorSetStorageBuffersDynamic", + &limits->maxDescriptorSetStorageBuffersDynamic) && + visitor->Visit("maxDescriptorSetSampledImages", + &limits->maxDescriptorSetSampledImages) && + visitor->Visit("maxDescriptorSetStorageImages", + &limits->maxDescriptorSetStorageImages) && + visitor->Visit("maxDescriptorSetInputAttachments", + &limits->maxDescriptorSetInputAttachments) && + visitor->Visit("maxVertexInputAttributes", + &limits->maxVertexInputAttributes) && + visitor->Visit("maxVertexInputBindings", + &limits->maxVertexInputBindings) && + visitor->Visit("maxVertexInputAttributeOffset", + &limits->maxVertexInputAttributeOffset) && + visitor->Visit("maxVertexInputBindingStride", + &limits->maxVertexInputBindingStride) && + visitor->Visit("maxVertexOutputComponents", + &limits->maxVertexOutputComponents) && + visitor->Visit("maxTessellationGenerationLevel", + &limits->maxTessellationGenerationLevel) && + visitor->Visit("maxTessellationPatchSize", + &limits->maxTessellationPatchSize) && + visitor->Visit("maxTessellationControlPerVertexInputComponents", + &limits->maxTessellationControlPerVertexInputComponents) && + visitor->Visit( + "maxTessellationControlPerVertexOutputComponents", + &limits->maxTessellationControlPerVertexOutputComponents) && + visitor->Visit("maxTessellationControlPerPatchOutputComponents", + &limits->maxTessellationControlPerPatchOutputComponents) && + visitor->Visit("maxTessellationControlTotalOutputComponents", + &limits->maxTessellationControlTotalOutputComponents) && + visitor->Visit("maxTessellationEvaluationInputComponents", + &limits->maxTessellationEvaluationInputComponents) && + visitor->Visit("maxTessellationEvaluationOutputComponents", + &limits->maxTessellationEvaluationOutputComponents) && + visitor->Visit("maxGeometryShaderInvocations", + &limits->maxGeometryShaderInvocations) && + visitor->Visit("maxGeometryInputComponents", + &limits->maxGeometryInputComponents) && + visitor->Visit("maxGeometryOutputComponents", + &limits->maxGeometryOutputComponents) && + visitor->Visit("maxGeometryOutputVertices", + &limits->maxGeometryOutputVertices) && + visitor->Visit("maxGeometryTotalOutputComponents", + &limits->maxGeometryTotalOutputComponents) && + visitor->Visit("maxFragmentInputComponents", + &limits->maxFragmentInputComponents) && + visitor->Visit("maxFragmentOutputAttachments", + &limits->maxFragmentOutputAttachments) && + visitor->Visit("maxFragmentDualSrcAttachments", + &limits->maxFragmentDualSrcAttachments) && + visitor->Visit("maxFragmentCombinedOutputResources", + &limits->maxFragmentCombinedOutputResources) && + visitor->Visit("maxComputeSharedMemorySize", + &limits->maxComputeSharedMemorySize) && + visitor->Visit("maxComputeWorkGroupCount", + &limits->maxComputeWorkGroupCount) && + visitor->Visit("maxComputeWorkGroupInvocations", + &limits->maxComputeWorkGroupInvocations) && + visitor->Visit("maxComputeWorkGroupSize", + &limits->maxComputeWorkGroupSize) && + visitor->Visit("subPixelPrecisionBits", &limits->subPixelPrecisionBits) && + visitor->Visit("subTexelPrecisionBits", &limits->subTexelPrecisionBits) && + visitor->Visit("mipmapPrecisionBits", &limits->mipmapPrecisionBits) && + visitor->Visit("maxDrawIndexedIndexValue", + &limits->maxDrawIndexedIndexValue) && + visitor->Visit("maxDrawIndirectCount", &limits->maxDrawIndirectCount) && + visitor->Visit("maxSamplerLodBias", &limits->maxSamplerLodBias) && + visitor->Visit("maxSamplerAnisotropy", &limits->maxSamplerAnisotropy) && + visitor->Visit("maxViewports", &limits->maxViewports) && + visitor->Visit("maxViewportDimensions", &limits->maxViewportDimensions) && + visitor->Visit("viewportBoundsRange", &limits->viewportBoundsRange) && + visitor->Visit("viewportSubPixelBits", &limits->viewportSubPixelBits) && + visitor->Visit("minMemoryMapAlignment", &limits->minMemoryMapAlignment) && + visitor->Visit("minTexelBufferOffsetAlignment", + &limits->minTexelBufferOffsetAlignment) && + visitor->Visit("minUniformBufferOffsetAlignment", + &limits->minUniformBufferOffsetAlignment) && + visitor->Visit("minStorageBufferOffsetAlignment", + &limits->minStorageBufferOffsetAlignment) && + visitor->Visit("minTexelOffset", &limits->minTexelOffset) && + visitor->Visit("maxTexelOffset", &limits->maxTexelOffset) && + visitor->Visit("minTexelGatherOffset", &limits->minTexelGatherOffset) && + visitor->Visit("maxTexelGatherOffset", &limits->maxTexelGatherOffset) && + visitor->Visit("minInterpolationOffset", + &limits->minInterpolationOffset) && + visitor->Visit("maxInterpolationOffset", + &limits->maxInterpolationOffset) && + visitor->Visit("subPixelInterpolationOffsetBits", + &limits->subPixelInterpolationOffsetBits) && + visitor->Visit("maxFramebufferWidth", &limits->maxFramebufferWidth) && + visitor->Visit("maxFramebufferHeight", &limits->maxFramebufferHeight) && + visitor->Visit("maxFramebufferLayers", &limits->maxFramebufferLayers) && + visitor->Visit("framebufferColorSampleCounts", + &limits->framebufferColorSampleCounts) && + visitor->Visit("framebufferDepthSampleCounts", + &limits->framebufferDepthSampleCounts) && + visitor->Visit("framebufferStencilSampleCounts", + &limits->framebufferStencilSampleCounts) && + visitor->Visit("framebufferNoAttachmentsSampleCounts", + &limits->framebufferNoAttachmentsSampleCounts) && + visitor->Visit("maxColorAttachments", &limits->maxColorAttachments) && + visitor->Visit("sampledImageColorSampleCounts", + &limits->sampledImageColorSampleCounts) && + visitor->Visit("sampledImageIntegerSampleCounts", + &limits->sampledImageIntegerSampleCounts) && + visitor->Visit("sampledImageDepthSampleCounts", + &limits->sampledImageDepthSampleCounts) && + visitor->Visit("sampledImageStencilSampleCounts", + &limits->sampledImageStencilSampleCounts) && + visitor->Visit("storageImageSampleCounts", + &limits->storageImageSampleCounts) && + visitor->Visit("maxSampleMaskWords", &limits->maxSampleMaskWords) && + visitor->Visit("timestampComputeAndGraphics", + &limits->timestampComputeAndGraphics) && + visitor->Visit("timestampPeriod", &limits->timestampPeriod) && + visitor->Visit("maxClipDistances", &limits->maxClipDistances) && + visitor->Visit("maxCullDistances", &limits->maxCullDistances) && + visitor->Visit("maxCombinedClipAndCullDistances", + &limits->maxCombinedClipAndCullDistances) && + visitor->Visit("discreteQueuePriorities", + &limits->discreteQueuePriorities) && + visitor->Visit("pointSizeRange", &limits->pointSizeRange) && + visitor->Visit("lineWidthRange", &limits->lineWidthRange) && + visitor->Visit("pointSizeGranularity", &limits->pointSizeGranularity) && + visitor->Visit("lineWidthGranularity", &limits->lineWidthGranularity) && + visitor->Visit("strictLines", &limits->strictLines) && + visitor->Visit("standardSampleLocations", + &limits->standardSampleLocations) && + visitor->Visit("optimalBufferCopyOffsetAlignment", + &limits->optimalBufferCopyOffsetAlignment) && + visitor->Visit("optimalBufferCopyRowPitchAlignment", + &limits->optimalBufferCopyRowPitchAlignment) && + visitor->Visit("nonCoherentAtomSize", &limits->nonCoherentAtomSize); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkPhysicalDeviceFeatures* features) { + return + + visitor->Visit("robustBufferAccess", &features->robustBufferAccess) && + visitor->Visit("fullDrawIndexUint32", &features->fullDrawIndexUint32) && + visitor->Visit("imageCubeArray", &features->imageCubeArray) && + visitor->Visit("independentBlend", &features->independentBlend) && + visitor->Visit("geometryShader", &features->geometryShader) && + visitor->Visit("tessellationShader", &features->tessellationShader) && + visitor->Visit("sampleRateShading", &features->sampleRateShading) && + visitor->Visit("dualSrcBlend", &features->dualSrcBlend) && + visitor->Visit("logicOp", &features->logicOp) && + visitor->Visit("multiDrawIndirect", &features->multiDrawIndirect) && + visitor->Visit("drawIndirectFirstInstance", + &features->drawIndirectFirstInstance) && + visitor->Visit("depthClamp", &features->depthClamp) && + visitor->Visit("depthBiasClamp", &features->depthBiasClamp) && + visitor->Visit("fillModeNonSolid", &features->fillModeNonSolid) && + visitor->Visit("depthBounds", &features->depthBounds) && + visitor->Visit("wideLines", &features->wideLines) && + visitor->Visit("largePoints", &features->largePoints) && + visitor->Visit("alphaToOne", &features->alphaToOne) && + visitor->Visit("multiViewport", &features->multiViewport) && + visitor->Visit("samplerAnisotropy", &features->samplerAnisotropy) && + visitor->Visit("textureCompressionETC2", + &features->textureCompressionETC2) && + visitor->Visit("textureCompressionASTC_LDR", + &features->textureCompressionASTC_LDR) && + visitor->Visit("textureCompressionBC", &features->textureCompressionBC) && + visitor->Visit("occlusionQueryPrecise", + &features->occlusionQueryPrecise) && + visitor->Visit("pipelineStatisticsQuery", + &features->pipelineStatisticsQuery) && + visitor->Visit("vertexPipelineStoresAndAtomics", + &features->vertexPipelineStoresAndAtomics) && + visitor->Visit("fragmentStoresAndAtomics", + &features->fragmentStoresAndAtomics) && + visitor->Visit("shaderTessellationAndGeometryPointSize", + &features->shaderTessellationAndGeometryPointSize) && + visitor->Visit("shaderImageGatherExtended", + &features->shaderImageGatherExtended) && + visitor->Visit("shaderStorageImageExtendedFormats", + &features->shaderStorageImageExtendedFormats) && + visitor->Visit("shaderStorageImageMultisample", + &features->shaderStorageImageMultisample) && + visitor->Visit("shaderStorageImageReadWithoutFormat", + &features->shaderStorageImageReadWithoutFormat) && + visitor->Visit("shaderStorageImageWriteWithoutFormat", + &features->shaderStorageImageWriteWithoutFormat) && + visitor->Visit("shaderUniformBufferArrayDynamicIndexing", + &features->shaderUniformBufferArrayDynamicIndexing) && + visitor->Visit("shaderSampledImageArrayDynamicIndexing", + &features->shaderSampledImageArrayDynamicIndexing) && + visitor->Visit("shaderStorageBufferArrayDynamicIndexing", + &features->shaderStorageBufferArrayDynamicIndexing) && + visitor->Visit("shaderStorageImageArrayDynamicIndexing", + &features->shaderStorageImageArrayDynamicIndexing) && + visitor->Visit("shaderClipDistance", &features->shaderClipDistance) && + visitor->Visit("shaderCullDistance", &features->shaderCullDistance) && + visitor->Visit("shaderFloat64", &features->shaderFloat64) && + visitor->Visit("shaderInt64", &features->shaderInt64) && + visitor->Visit("shaderInt16", &features->shaderInt16) && + visitor->Visit("shaderResourceResidency", + &features->shaderResourceResidency) && + visitor->Visit("shaderResourceMinLod", &features->shaderResourceMinLod) && + visitor->Visit("sparseBinding", &features->sparseBinding) && + visitor->Visit("sparseResidencyBuffer", + &features->sparseResidencyBuffer) && + visitor->Visit("sparseResidencyImage2D", + &features->sparseResidencyImage2D) && + visitor->Visit("sparseResidencyImage3D", + &features->sparseResidencyImage3D) && + visitor->Visit("sparseResidency2Samples", + &features->sparseResidency2Samples) && + visitor->Visit("sparseResidency4Samples", + &features->sparseResidency4Samples) && + visitor->Visit("sparseResidency8Samples", + &features->sparseResidency8Samples) && + visitor->Visit("sparseResidency16Samples", + &features->sparseResidency16Samples) && + visitor->Visit("sparseResidencyAliased", + &features->sparseResidencyAliased) && + visitor->Visit("variableMultisampleRate", + &features->variableMultisampleRate) && + visitor->Visit("inheritedQueries", &features->inheritedQueries); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceProtectedMemoryFeatures* features) { - return visitor->Visit("protectedMemory", &features->protectedMemory); + VkPhysicalDeviceVulkan11Properties* properties) { + return + + visitor->Visit("deviceUUID", &properties->deviceUUID) && + visitor->Visit("driverUUID", &properties->driverUUID) && + visitor->Visit("deviceLUID", &properties->deviceLUID) && + visitor->Visit("deviceNodeMask", &properties->deviceNodeMask) && + visitor->Visit("deviceLUIDValid", &properties->deviceLUIDValid) && + visitor->Visit("subgroupSize", &properties->subgroupSize) && + visitor->Visit("subgroupSupportedStages", + &properties->subgroupSupportedStages) && + visitor->Visit("subgroupSupportedOperations", + &properties->subgroupSupportedOperations) && + visitor->Visit("subgroupQuadOperationsInAllStages", + &properties->subgroupQuadOperationsInAllStages) && + visitor->Visit("pointClippingBehavior", + &properties->pointClippingBehavior) && + visitor->Visit("maxMultiviewViewCount", + &properties->maxMultiviewViewCount) && + visitor->Visit("maxMultiviewInstanceIndex", + &properties->maxMultiviewInstanceIndex) && + visitor->Visit("protectedNoFault", &properties->protectedNoFault) && + visitor->Visit("maxPerSetDescriptors", + &properties->maxPerSetDescriptors) && + visitor->Visit("maxMemoryAllocationSize", + &properties->maxMemoryAllocationSize); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceSamplerYcbcrConversionFeatures* features) { - return visitor->Visit("samplerYcbcrConversion", - &features->samplerYcbcrConversion); + VkPhysicalDeviceVulkan11Features* features) { + return + + visitor->Visit("storageBuffer16BitAccess", + &features->storageBuffer16BitAccess) && + visitor->Visit("uniformAndStorageBuffer16BitAccess", + &features->uniformAndStorageBuffer16BitAccess) && + visitor->Visit("storagePushConstant16", + &features->storagePushConstant16) && + visitor->Visit("storageInputOutput16", &features->storageInputOutput16) && + visitor->Visit("multiview", &features->multiview) && + visitor->Visit("multiviewGeometryShader", + &features->multiviewGeometryShader) && + visitor->Visit("multiviewTessellationShader", + &features->multiviewTessellationShader) && + visitor->Visit("variablePointersStorageBuffer", + &features->variablePointersStorageBuffer) && + visitor->Visit("variablePointers", &features->variablePointers) && + visitor->Visit("protectedMemory", &features->protectedMemory) && + visitor->Visit("samplerYcbcrConversion", + &features->samplerYcbcrConversion) && + visitor->Visit("shaderDrawParameters", &features->shaderDrawParameters); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkPhysicalDeviceShaderDrawParameterFeatures* features) { - return visitor->Visit("shaderDrawParameters", - &features->shaderDrawParameters); + VkPhysicalDeviceVulkan12Properties* properties) { + return + + visitor->Visit("driverID", &properties->driverID) && + visitor->Visit("driverName", &properties->driverName) && + visitor->Visit("driverInfo", &properties->driverInfo) && + visitor->Visit("conformanceVersion", &properties->conformanceVersion) && + visitor->Visit("denormBehaviorIndependence", + &properties->denormBehaviorIndependence) && + visitor->Visit("roundingModeIndependence", + &properties->roundingModeIndependence) && + visitor->Visit("shaderSignedZeroInfNanPreserveFloat16", + &properties->shaderSignedZeroInfNanPreserveFloat16) && + visitor->Visit("shaderSignedZeroInfNanPreserveFloat32", + &properties->shaderSignedZeroInfNanPreserveFloat32) && + visitor->Visit("shaderSignedZeroInfNanPreserveFloat64", + &properties->shaderSignedZeroInfNanPreserveFloat64) && + visitor->Visit("shaderDenormPreserveFloat16", + &properties->shaderDenormPreserveFloat16) && + visitor->Visit("shaderDenormPreserveFloat32", + &properties->shaderDenormPreserveFloat32) && + visitor->Visit("shaderDenormPreserveFloat64", + &properties->shaderDenormPreserveFloat64) && + visitor->Visit("shaderDenormFlushToZeroFloat16", + &properties->shaderDenormFlushToZeroFloat16) && + visitor->Visit("shaderDenormFlushToZeroFloat32", + &properties->shaderDenormFlushToZeroFloat32) && + visitor->Visit("shaderDenormFlushToZeroFloat64", + &properties->shaderDenormFlushToZeroFloat64) && + visitor->Visit("shaderRoundingModeRTEFloat16", + &properties->shaderRoundingModeRTEFloat16) && + visitor->Visit("shaderRoundingModeRTEFloat32", + &properties->shaderRoundingModeRTEFloat32) && + visitor->Visit("shaderRoundingModeRTEFloat64", + &properties->shaderRoundingModeRTEFloat64) && + visitor->Visit("shaderRoundingModeRTZFloat16", + &properties->shaderRoundingModeRTZFloat16) && + visitor->Visit("shaderRoundingModeRTZFloat32", + &properties->shaderRoundingModeRTZFloat32) && + visitor->Visit("shaderRoundingModeRTZFloat64", + &properties->shaderRoundingModeRTZFloat64) && + visitor->Visit("maxUpdateAfterBindDescriptorsInAllPools", + &properties->maxUpdateAfterBindDescriptorsInAllPools) && + visitor->Visit( + "shaderUniformBufferArrayNonUniformIndexingNative", + &properties->shaderUniformBufferArrayNonUniformIndexingNative) && + visitor->Visit( + "shaderSampledImageArrayNonUniformIndexingNative", + &properties->shaderSampledImageArrayNonUniformIndexingNative) && + visitor->Visit( + "shaderStorageBufferArrayNonUniformIndexingNative", + &properties->shaderStorageBufferArrayNonUniformIndexingNative) && + visitor->Visit( + "shaderStorageImageArrayNonUniformIndexingNative", + &properties->shaderStorageImageArrayNonUniformIndexingNative) && + visitor->Visit( + "shaderInputAttachmentArrayNonUniformIndexingNative", + &properties->shaderInputAttachmentArrayNonUniformIndexingNative) && + visitor->Visit("robustBufferAccessUpdateAfterBind", + &properties->robustBufferAccessUpdateAfterBind) && + visitor->Visit("quadDivergentImplicitLod", + &properties->quadDivergentImplicitLod) && + visitor->Visit( + "maxPerStageDescriptorUpdateAfterBindSamplers", + &properties->maxPerStageDescriptorUpdateAfterBindSamplers) && + visitor->Visit( + "maxPerStageDescriptorUpdateAfterBindUniformBuffers", + &properties->maxPerStageDescriptorUpdateAfterBindUniformBuffers) && + visitor->Visit( + "maxPerStageDescriptorUpdateAfterBindStorageBuffers", + &properties->maxPerStageDescriptorUpdateAfterBindStorageBuffers) && + visitor->Visit( + "maxPerStageDescriptorUpdateAfterBindSampledImages", + &properties->maxPerStageDescriptorUpdateAfterBindSampledImages) && + visitor->Visit( + "maxPerStageDescriptorUpdateAfterBindStorageImages", + &properties->maxPerStageDescriptorUpdateAfterBindStorageImages) && + visitor->Visit( + "maxPerStageDescriptorUpdateAfterBindInputAttachments", + &properties->maxPerStageDescriptorUpdateAfterBindInputAttachments) && + visitor->Visit("maxPerStageUpdateAfterBindResources", + &properties->maxPerStageUpdateAfterBindResources) && + visitor->Visit("maxDescriptorSetUpdateAfterBindSamplers", + &properties->maxDescriptorSetUpdateAfterBindSamplers) && + visitor->Visit( + "maxDescriptorSetUpdateAfterBindUniformBuffers", + &properties->maxDescriptorSetUpdateAfterBindUniformBuffers) && + visitor->Visit( + "maxDescriptorSetUpdateAfterBindUniformBuffersDynamic", + &properties->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic) && + visitor->Visit( + "maxDescriptorSetUpdateAfterBindStorageBuffers", + &properties->maxDescriptorSetUpdateAfterBindStorageBuffers) && + visitor->Visit( + "maxDescriptorSetUpdateAfterBindStorageBuffersDynamic", + &properties->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic) && + visitor->Visit( + "maxDescriptorSetUpdateAfterBindSampledImages", + &properties->maxDescriptorSetUpdateAfterBindSampledImages) && + visitor->Visit( + "maxDescriptorSetUpdateAfterBindStorageImages", + &properties->maxDescriptorSetUpdateAfterBindStorageImages) && + visitor->Visit( + "maxDescriptorSetUpdateAfterBindInputAttachments", + &properties->maxDescriptorSetUpdateAfterBindInputAttachments) && + visitor->Visit("supportedDepthResolveModes", + &properties->supportedDepthResolveModes) && + visitor->Visit("supportedStencilResolveModes", + &properties->supportedStencilResolveModes) && + visitor->Visit("independentResolveNone", + &properties->independentResolveNone) && + visitor->Visit("independentResolve", &properties->independentResolve) && + visitor->Visit("filterMinmaxSingleComponentFormats", + &properties->filterMinmaxSingleComponentFormats) && + visitor->Visit("filterMinmaxImageComponentMapping", + &properties->filterMinmaxImageComponentMapping) && + visitor->Visit("maxTimelineSemaphoreValueDifference", + &properties->maxTimelineSemaphoreValueDifference) && + visitor->Visit("framebufferIntegerColorSampleCounts", + &properties->framebufferIntegerColorSampleCounts); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkExternalFenceProperties* properties) { - return visitor->Visit("exportFromImportedHandleTypes", - &properties->exportFromImportedHandleTypes) && - visitor->Visit("compatibleHandleTypes", - &properties->compatibleHandleTypes) && - visitor->Visit("externalFenceFeatures", - &properties->externalFenceFeatures); +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceVulkan12Features* features) { + return + + visitor->Visit("samplerMirrorClampToEdge", + &features->samplerMirrorClampToEdge) && + visitor->Visit("drawIndirectCount", &features->drawIndirectCount) && + visitor->Visit("storageBuffer8BitAccess", + &features->storageBuffer8BitAccess) && + visitor->Visit("uniformAndStorageBuffer8BitAccess", + &features->uniformAndStorageBuffer8BitAccess) && + visitor->Visit("storagePushConstant8", &features->storagePushConstant8) && + visitor->Visit("shaderBufferInt64Atomics", + &features->shaderBufferInt64Atomics) && + visitor->Visit("shaderSharedInt64Atomics", + &features->shaderSharedInt64Atomics) && + visitor->Visit("shaderFloat16", &features->shaderFloat16) && + visitor->Visit("shaderInt8", &features->shaderInt8) && + visitor->Visit("descriptorIndexing", &features->descriptorIndexing) && + visitor->Visit("shaderInputAttachmentArrayDynamicIndexing", + &features->shaderInputAttachmentArrayDynamicIndexing) && + visitor->Visit("shaderUniformTexelBufferArrayDynamicIndexing", + &features->shaderUniformTexelBufferArrayDynamicIndexing) && + visitor->Visit("shaderStorageTexelBufferArrayDynamicIndexing", + &features->shaderStorageTexelBufferArrayDynamicIndexing) && + visitor->Visit("shaderUniformBufferArrayNonUniformIndexing", + &features->shaderUniformBufferArrayNonUniformIndexing) && + visitor->Visit("shaderSampledImageArrayNonUniformIndexing", + &features->shaderSampledImageArrayNonUniformIndexing) && + visitor->Visit("shaderStorageBufferArrayNonUniformIndexing", + &features->shaderStorageBufferArrayNonUniformIndexing) && + visitor->Visit("shaderStorageImageArrayNonUniformIndexing", + &features->shaderStorageImageArrayNonUniformIndexing) && + visitor->Visit("shaderInputAttachmentArrayNonUniformIndexing", + &features->shaderInputAttachmentArrayNonUniformIndexing) && + visitor->Visit( + "shaderUniformTexelBufferArrayNonUniformIndexing", + &features->shaderUniformTexelBufferArrayNonUniformIndexing) && + visitor->Visit( + "shaderStorageTexelBufferArrayNonUniformIndexing", + &features->shaderStorageTexelBufferArrayNonUniformIndexing) && + visitor->Visit( + "descriptorBindingUniformBufferUpdateAfterBind", + &features->descriptorBindingUniformBufferUpdateAfterBind) && + visitor->Visit("descriptorBindingSampledImageUpdateAfterBind", + &features->descriptorBindingSampledImageUpdateAfterBind) && + visitor->Visit("descriptorBindingStorageImageUpdateAfterBind", + &features->descriptorBindingStorageImageUpdateAfterBind) && + visitor->Visit( + "descriptorBindingStorageBufferUpdateAfterBind", + &features->descriptorBindingStorageBufferUpdateAfterBind) && + visitor->Visit( + "descriptorBindingUniformTexelBufferUpdateAfterBind", + &features->descriptorBindingUniformTexelBufferUpdateAfterBind) && + visitor->Visit( + "descriptorBindingStorageTexelBufferUpdateAfterBind", + &features->descriptorBindingStorageTexelBufferUpdateAfterBind) && + visitor->Visit("descriptorBindingUpdateUnusedWhilePending", + &features->descriptorBindingUpdateUnusedWhilePending) && + visitor->Visit("descriptorBindingPartiallyBound", + &features->descriptorBindingPartiallyBound) && + visitor->Visit("descriptorBindingVariableDescriptorCount", + &features->descriptorBindingVariableDescriptorCount) && + visitor->Visit("runtimeDescriptorArray", + &features->runtimeDescriptorArray) && + visitor->Visit("samplerFilterMinmax", &features->samplerFilterMinmax) && + visitor->Visit("scalarBlockLayout", &features->scalarBlockLayout) && + visitor->Visit("imagelessFramebuffer", &features->imagelessFramebuffer) && + visitor->Visit("uniformBufferStandardLayout", + &features->uniformBufferStandardLayout) && + visitor->Visit("shaderSubgroupExtendedTypes", + &features->shaderSubgroupExtendedTypes) && + visitor->Visit("separateDepthStencilLayouts", + &features->separateDepthStencilLayouts) && + visitor->Visit("hostQueryReset", &features->hostQueryReset) && + visitor->Visit("timelineSemaphore", &features->timelineSemaphore) && + visitor->Visit("bufferDeviceAddress", &features->bufferDeviceAddress) && + visitor->Visit("bufferDeviceAddressCaptureReplay", + &features->bufferDeviceAddressCaptureReplay) && + visitor->Visit("bufferDeviceAddressMultiDevice", + &features->bufferDeviceAddressMultiDevice) && + visitor->Visit("vulkanMemoryModel", &features->vulkanMemoryModel) && + visitor->Visit("vulkanMemoryModelDeviceScope", + &features->vulkanMemoryModelDeviceScope) && + visitor->Visit( + "vulkanMemoryModelAvailabilityVisibilityChains", + &features->vulkanMemoryModelAvailabilityVisibilityChains) && + visitor->Visit("shaderOutputViewportIndex", + &features->shaderOutputViewportIndex) && + visitor->Visit("shaderOutputLayer", &features->shaderOutputLayer) && + visitor->Visit("subgroupBroadcastDynamicId", + &features->subgroupBroadcastDynamicId); } template <typename Visitor> inline bool Iterate(Visitor* visitor, - VkExternalSemaphoreProperties* properties) { - return visitor->Visit("exportFromImportedHandleTypes", - &properties->exportFromImportedHandleTypes) && - visitor->Visit("compatibleHandleTypes", - &properties->compatibleHandleTypes) && - visitor->Visit("externalSemaphoreFeatures", - &properties->externalSemaphoreFeatures); + VkPhysicalDeviceVulkan13Properties* properties) { + return + + visitor->Visit("minSubgroupSize", &properties->minSubgroupSize) && + visitor->Visit("maxSubgroupSize", &properties->maxSubgroupSize) && + visitor->Visit("maxComputeWorkgroupSubgroups", + &properties->maxComputeWorkgroupSubgroups) && + visitor->Visit("requiredSubgroupSizeStages", + &properties->requiredSubgroupSizeStages) && + visitor->Visit("maxInlineUniformBlockSize", + &properties->maxInlineUniformBlockSize) && + visitor->Visit("maxPerStageDescriptorInlineUniformBlocks", + &properties->maxPerStageDescriptorInlineUniformBlocks) && + visitor->Visit( + "maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks", + &properties + ->maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks) && + visitor->Visit("maxDescriptorSetInlineUniformBlocks", + &properties->maxDescriptorSetInlineUniformBlocks) && + visitor->Visit( + "maxDescriptorSetUpdateAfterBindInlineUniformBlocks", + &properties->maxDescriptorSetUpdateAfterBindInlineUniformBlocks) && + visitor->Visit("maxInlineUniformTotalSize", + &properties->maxInlineUniformTotalSize) && + visitor->Visit("integerDotProduct8BitUnsignedAccelerated", + &properties->integerDotProduct8BitUnsignedAccelerated) && + visitor->Visit("integerDotProduct8BitSignedAccelerated", + &properties->integerDotProduct8BitSignedAccelerated) && + visitor->Visit( + "integerDotProduct8BitMixedSignednessAccelerated", + &properties->integerDotProduct8BitMixedSignednessAccelerated) && + visitor->Visit( + "integerDotProduct4x8BitPackedUnsignedAccelerated", + &properties->integerDotProduct4x8BitPackedUnsignedAccelerated) && + visitor->Visit( + "integerDotProduct4x8BitPackedSignedAccelerated", + &properties->integerDotProduct4x8BitPackedSignedAccelerated) && + visitor->Visit( + "integerDotProduct4x8BitPackedMixedSignednessAccelerated", + &properties + ->integerDotProduct4x8BitPackedMixedSignednessAccelerated) && + visitor->Visit("integerDotProduct16BitUnsignedAccelerated", + &properties->integerDotProduct16BitUnsignedAccelerated) && + visitor->Visit("integerDotProduct16BitSignedAccelerated", + &properties->integerDotProduct16BitSignedAccelerated) && + visitor->Visit( + "integerDotProduct16BitMixedSignednessAccelerated", + &properties->integerDotProduct16BitMixedSignednessAccelerated) && + visitor->Visit("integerDotProduct32BitUnsignedAccelerated", + &properties->integerDotProduct32BitUnsignedAccelerated) && + visitor->Visit("integerDotProduct32BitSignedAccelerated", + &properties->integerDotProduct32BitSignedAccelerated) && + visitor->Visit( + "integerDotProduct32BitMixedSignednessAccelerated", + &properties->integerDotProduct32BitMixedSignednessAccelerated) && + visitor->Visit("integerDotProduct64BitUnsignedAccelerated", + &properties->integerDotProduct64BitUnsignedAccelerated) && + visitor->Visit("integerDotProduct64BitSignedAccelerated", + &properties->integerDotProduct64BitSignedAccelerated) && + visitor->Visit( + "integerDotProduct64BitMixedSignednessAccelerated", + &properties->integerDotProduct64BitMixedSignednessAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating8BitUnsignedAccelerated", + &properties + ->integerDotProductAccumulatingSaturating8BitUnsignedAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating8BitSignedAccelerated", + &properties + ->integerDotProductAccumulatingSaturating8BitSignedAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerate" + "d", + &properties + ->integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerat" + "ed", + &properties + ->integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerate" + "d", + &properties + ->integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAc" + "celerated", + &properties + ->integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating16BitUnsignedAccelerated", + &properties + ->integerDotProductAccumulatingSaturating16BitUnsignedAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating16BitSignedAccelerated", + &properties + ->integerDotProductAccumulatingSaturating16BitSignedAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerat" + "ed", + &properties + ->integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating32BitUnsignedAccelerated", + &properties + ->integerDotProductAccumulatingSaturating32BitUnsignedAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating32BitSignedAccelerated", + &properties + ->integerDotProductAccumulatingSaturating32BitSignedAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerat" + "ed", + &properties + ->integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating64BitUnsignedAccelerated", + &properties + ->integerDotProductAccumulatingSaturating64BitUnsignedAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating64BitSignedAccelerated", + &properties + ->integerDotProductAccumulatingSaturating64BitSignedAccelerated) && + visitor->Visit( + "integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerat" + "ed", + &properties + ->integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated) && + visitor->Visit("storageTexelBufferOffsetAlignmentBytes", + &properties->storageTexelBufferOffsetAlignmentBytes) && + visitor->Visit( + "storageTexelBufferOffsetSingleTexelAlignment", + &properties->storageTexelBufferOffsetSingleTexelAlignment) && + visitor->Visit("uniformTexelBufferOffsetAlignmentBytes", + &properties->uniformTexelBufferOffsetAlignmentBytes) && + visitor->Visit( + "uniformTexelBufferOffsetSingleTexelAlignment", + &properties->uniformTexelBufferOffsetSingleTexelAlignment) && + visitor->Visit("maxBufferSize", &properties->maxBufferSize); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkQueueFamilyProperties* properties) { +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceVulkan13Features* features) { return - visitor->Visit("queueFlags", &properties->queueFlags) && - visitor->Visit("queueCount", &properties->queueCount) && - visitor->Visit("timestampValidBits", &properties->timestampValidBits) && - visitor->Visit("minImageTransferGranularity", &properties->minImageTransferGranularity); + + visitor->Visit("robustImageAccess", &features->robustImageAccess) && + visitor->Visit("inlineUniformBlock", &features->inlineUniformBlock) && + visitor->Visit( + "descriptorBindingInlineUniformBlockUpdateAfterBind", + &features->descriptorBindingInlineUniformBlockUpdateAfterBind) && + visitor->Visit("pipelineCreationCacheControl", + &features->pipelineCreationCacheControl) && + visitor->Visit("privateData", &features->privateData) && + visitor->Visit("shaderDemoteToHelperInvocation", + &features->shaderDemoteToHelperInvocation) && + visitor->Visit("shaderTerminateInvocation", + &features->shaderTerminateInvocation) && + visitor->Visit("subgroupSizeControl", &features->subgroupSizeControl) && + visitor->Visit("computeFullSubgroups", &features->computeFullSubgroups) && + visitor->Visit("synchronization2", &features->synchronization2) && + visitor->Visit("textureCompressionASTC_HDR", + &features->textureCompressionASTC_HDR) && + visitor->Visit("shaderZeroInitializeWorkgroupMemory", + &features->shaderZeroInitializeWorkgroupMemory) && + visitor->Visit("dynamicRendering", &features->dynamicRendering) && + visitor->Visit("shaderIntegerDotProduct", + &features->shaderIntegerDotProduct) && + visitor->Visit("maintenance4", &features->maintenance4); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkExtensionProperties* properties) { +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceVulkan14Properties* properties) { return - visitor->Visit("extensionName", &properties->extensionName) && - visitor->Visit("specVersion", &properties->specVersion); + + visitor->Visit("lineSubPixelPrecisionBits", + &properties->lineSubPixelPrecisionBits) && + visitor->Visit("maxVertexAttribDivisor", + &properties->maxVertexAttribDivisor) && + visitor->Visit("supportsNonZeroFirstInstance", + &properties->supportsNonZeroFirstInstance) && + visitor->Visit("maxPushDescriptors", &properties->maxPushDescriptors) && + visitor->Visit( + "dynamicRenderingLocalReadDepthStencilAttachments", + &properties->dynamicRenderingLocalReadDepthStencilAttachments) && + visitor->Visit( + "dynamicRenderingLocalReadMultisampledAttachments", + &properties->dynamicRenderingLocalReadMultisampledAttachments) && + visitor->Visit( + "earlyFragmentMultisampleCoverageAfterSampleCounting", + &properties->earlyFragmentMultisampleCoverageAfterSampleCounting) && + visitor->Visit( + "earlyFragmentSampleMaskTestBeforeSampleCounting", + &properties->earlyFragmentSampleMaskTestBeforeSampleCounting) && + visitor->Visit("depthStencilSwizzleOneSupport", + &properties->depthStencilSwizzleOneSupport) && + visitor->Visit("polygonModePointSize", + &properties->polygonModePointSize) && + visitor->Visit( + "nonStrictSinglePixelWideLinesUseParallelogram", + &properties->nonStrictSinglePixelWideLinesUseParallelogram) && + visitor->Visit("nonStrictWideLinesUseParallelogram", + &properties->nonStrictWideLinesUseParallelogram) && + visitor->Visit("blockTexelViewCompatibleMultipleLayers", + &properties->blockTexelViewCompatibleMultipleLayers) && + visitor->Visit("maxCombinedImageSamplerDescriptorCount", + &properties->maxCombinedImageSamplerDescriptorCount) && + visitor->Visit("fragmentShadingRateClampCombinerInputs", + &properties->fragmentShadingRateClampCombinerInputs) && + visitor->Visit("defaultRobustnessStorageBuffers", + &properties->defaultRobustnessStorageBuffers) && + visitor->Visit("defaultRobustnessUniformBuffers", + &properties->defaultRobustnessUniformBuffers) && + visitor->Visit("defaultRobustnessVertexInputs", + &properties->defaultRobustnessVertexInputs) && + visitor->Visit("defaultRobustnessImages", + &properties->defaultRobustnessImages) && + visitor->Visit("copySrcLayoutCount", &properties->copySrcLayoutCount) && + visitor->VisitArray("pCopySrcLayouts", properties->copySrcLayoutCount, + &properties->pCopySrcLayouts) && + visitor->Visit("copyDstLayoutCount", &properties->copyDstLayoutCount) && + visitor->VisitArray("pCopyDstLayouts", properties->copyDstLayoutCount, + &properties->pCopyDstLayouts) && + visitor->Visit("optimalTilingLayoutUUID", + &properties->optimalTilingLayoutUUID) && + visitor->Visit("identicalMemoryTypeRequirements", + &properties->identicalMemoryTypeRequirements); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkLayerProperties* properties) { +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceVulkan14Features* features) { return - visitor->Visit("layerName", &properties->layerName) && - visitor->Visit("specVersion", &properties->specVersion) && - visitor->Visit("implementationVersion", &properties->implementationVersion) && - visitor->Visit("description", &properties->description); + + visitor->Visit("globalPriorityQuery", &features->globalPriorityQuery) && + visitor->Visit("shaderSubgroupRotate", &features->shaderSubgroupRotate) && + visitor->Visit("shaderSubgroupRotateClustered", + &features->shaderSubgroupRotateClustered) && + visitor->Visit("shaderFloatControls2", &features->shaderFloatControls2) && + visitor->Visit("shaderExpectAssume", &features->shaderExpectAssume) && + visitor->Visit("rectangularLines", &features->rectangularLines) && + visitor->Visit("bresenhamLines", &features->bresenhamLines) && + visitor->Visit("smoothLines", &features->smoothLines) && + visitor->Visit("stippledRectangularLines", + &features->stippledRectangularLines) && + visitor->Visit("stippledBresenhamLines", + &features->stippledBresenhamLines) && + visitor->Visit("stippledSmoothLines", &features->stippledSmoothLines) && + visitor->Visit("vertexAttributeInstanceRateDivisor", + &features->vertexAttributeInstanceRateDivisor) && + visitor->Visit("vertexAttributeInstanceRateZeroDivisor", + &features->vertexAttributeInstanceRateZeroDivisor) && + visitor->Visit("indexTypeUint8", &features->indexTypeUint8) && + visitor->Visit("dynamicRenderingLocalRead", + &features->dynamicRenderingLocalRead) && + visitor->Visit("maintenance5", &features->maintenance5) && + visitor->Visit("maintenance6", &features->maintenance6) && + visitor->Visit("pipelineProtectedAccess", + &features->pipelineProtectedAccess) && + visitor->Visit("pipelineRobustness", &features->pipelineRobustness) && + visitor->Visit("hostImageCopy", &features->hostImageCopy); } template <typename Visitor> -inline bool Iterate(Visitor* visitor, VkFormatProperties* properties) { +inline bool Iterate(Visitor* visitor, + VkPhysicalDeviceDriverProperties* properties) { return - visitor->Visit("linearTilingFeatures", &properties->linearTilingFeatures) && - visitor->Visit("optimalTilingFeatures", &properties->optimalTilingFeatures) && - visitor->Visit("bufferFeatures", &properties->bufferFeatures); + + visitor->Visit("driverID", &properties->driverID) && + visitor->Visit("driverName", &properties->driverName) && + visitor->Visit("driverInfo", &properties->driverInfo) && + visitor->Visit("conformanceVersion", &properties->conformanceVersion); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, VkExternalFenceProperties* properties) { + return visitor->Visit("exportFromImportedHandleTypes", + &properties->exportFromImportedHandleTypes) && + visitor->Visit("compatibleHandleTypes", + &properties->compatibleHandleTypes) && + visitor->Visit("externalFenceFeatures", + &properties->externalFenceFeatures); +} + +template <typename Visitor> +inline bool Iterate(Visitor* visitor, + VkExternalSemaphoreProperties* properties) { + return visitor->Visit("exportFromImportedHandleTypes", + &properties->exportFromImportedHandleTypes) && + visitor->Visit("compatibleHandleTypes", + &properties->compatibleHandleTypes) && + visitor->Visit("externalSemaphoreFeatures", + &properties->externalSemaphoreFeatures); } template <typename Visitor> @@ -1211,6 +1953,7 @@ inline bool Iterate(Visitor* visitor, VkJsonDevice* device) { ret &= visitor->Visit("core13", &device->core13); FALLTHROUGH_INTENDED; case VK_API_VERSION_1_2: + ret &= visitor->Visit("core11", &device->core11); ret &= visitor->Visit("core12", &device->core12); FALLTHROUGH_INTENDED; case VK_API_VERSION_1_1: @@ -1223,17 +1966,17 @@ inline bool Iterate(Visitor* visitor, VkJsonDevice* device) { visitor->Visit("idProperties", &device->id_properties) && visitor->Visit("maintenance3Properties", &device->maintenance3_properties) && - visitor->Visit("16bitStorageFeatures", - &device->bit16_storage_features) && visitor->Visit("multiviewFeatures", &device->multiview_features) && - visitor->Visit("variablePointerFeatures", - &device->variable_pointer_features) && + visitor->Visit("variablePointersFeatures", + &device->variable_pointers_features) && visitor->Visit("protectedMemoryFeatures", &device->protected_memory_features) && visitor->Visit("samplerYcbcrConversionFeatures", &device->sampler_ycbcr_conversion_features) && visitor->Visit("shaderDrawParameterFeatures", &device->shader_draw_parameter_features) && + visitor->Visit("bit16StorageFeatures", + &device->bit16_storage_features) && visitor->Visit("externalFenceProperties", &device->external_fence_properties) && visitor->Visit("externalSemaphoreProperties", @@ -1247,21 +1990,90 @@ inline bool Iterate(Visitor* visitor, VkJsonDevice* device) { visitor->Visit("extensions", &device->extensions) && visitor->Visit("layers", &device->layers) && visitor->Visit("formats", &device->formats); - if (device->ext_driver_properties.reported) { - ret &= visitor->Visit("VK_KHR_driver_properties", - &device->ext_driver_properties); - } - if (device->ext_variable_pointer_features.reported) { + + if (device->khr_variable_pointers.reported) { ret &= visitor->Visit("VK_KHR_variable_pointers", - &device->ext_variable_pointer_features); + &device->khr_variable_pointers); } - if (device->ext_image_2d_view_of_3d_features.reported) { + if (device->khr_shader_float16_int8.reported) { + ret &= visitor->Visit("VK_KHR_shader_float16_int8", + &device->khr_shader_float16_int8); + } + if (device->ext_image_2d_view_of_3d.reported) { ret &= visitor->Visit("VK_EXT_image_2d_view_of_3d", - &device->ext_image_2d_view_of_3d_features); + &device->ext_image_2d_view_of_3d); } - if (device->ext_shader_float16_int8_features.reported) { - ret &= visitor->Visit("VK_KHR_shader_float16_int8", - &device->ext_shader_float16_int8_features); + if (device->ext_custom_border_color.reported) { + ret &= visitor->Visit("VK_EXT_custom_border_color", + &device->ext_custom_border_color); + } + if (device->ext_primitive_topology_list_restart.reported) { + ret &= visitor->Visit("VK_EXT_primitive_topology_list_restart", + &device->ext_primitive_topology_list_restart); + } + if (device->ext_provoking_vertex.reported) { + ret &= visitor->Visit("VK_EXT_provoking_vertex", + &device->ext_provoking_vertex); + } + if (device->khr_index_type_uint8.reported) { + ret &= visitor->Visit("VK_KHR_index_type_uint8", + &device->khr_index_type_uint8); + } + if (device->ext_index_type_uint8.reported) { + ret &= visitor->Visit("VK_EXT_index_type_uint8", + &device->ext_index_type_uint8); + } + if (device->khr_vertex_attribute_divisor.reported) { + ret &= visitor->Visit("VK_KHR_vertex_attribute_divisor", + &device->khr_vertex_attribute_divisor); + } + if (device->ext_vertex_attribute_divisor.reported) { + ret &= visitor->Visit("VK_EXT_vertex_attribute_divisor", + &device->ext_vertex_attribute_divisor); + } + if (device->ext_transform_feedback.reported) { + ret &= visitor->Visit("VK_EXT_transform_feedback", + &device->ext_transform_feedback); + } + if (device->khr_shader_subgroup_uniform_control_flow.reported) { + ret &= + visitor->Visit("VK_KHR_shader_subgroup_uniform_control_flow", + &device->khr_shader_subgroup_uniform_control_flow); + } + if (device->khr_shader_subgroup_extended_types.reported) { + ret &= visitor->Visit("VK_KHR_shader_subgroup_extended_types", + &device->khr_shader_subgroup_extended_types); + } + if (device->khr_8bit_storage.reported) { + ret &= visitor->Visit("VK_KHR_8bit_storage", &device->khr_8bit_storage); + } + if (device->khr_shader_integer_dot_product.reported) { + ret &= visitor->Visit("VK_KHR_shader_integer_dot_product", + &device->khr_shader_integer_dot_product); + } + if (device->img_relaxed_line_rasterization.reported) { + ret &= visitor->Visit("VK_IMG_relaxed_line_rasterization", + &device->img_relaxed_line_rasterization); + } + if (device->khr_line_rasterization.reported) { + ret &= visitor->Visit("VK_KHR_line_rasterization", + &device->khr_line_rasterization); + } + if (device->ext_line_rasterization.reported) { + ret &= visitor->Visit("VK_EXT_line_rasterization", + &device->ext_line_rasterization); + } + if (device->ext_primitives_generated_query.reported) { + ret &= visitor->Visit("VK_EXT_primitives_generated_query", + &device->ext_primitives_generated_query); + } + if (device->khr_shader_float_controls.reported) { + ret &= visitor->Visit("VK_KHR_shader_float_controls", + &device->khr_shader_float_controls); + } + if (device->khr_driver_properties.reported) { + ret &= visitor->Visit("VK_KHR_driver_properties", + &device->khr_driver_properties); } } return ret; @@ -1319,7 +2131,9 @@ inline Json::Value ToJsonValue(const uint64_t& value) { return Json::Value(string); } -template <typename T, typename = EnableForEnum<T>, typename = void, +template <typename T, + typename = EnableForEnum<T>, + typename = void, typename = void> inline Json::Value ToJsonValue(const T& value) { return Json::Value(static_cast<double>(value)); @@ -1328,7 +2142,8 @@ inline Json::Value ToJsonValue(const T& value) { template <typename T> inline Json::Value ArrayToJsonValue(uint32_t count, const T* values) { Json::Value array(Json::arrayValue); - for (unsigned int i = 0; i < count; ++i) array.append(ToJsonValue(values[i])); + for (unsigned int i = 0; i < count; ++i) + array.append(ToJsonValue(values[i])); return array; } @@ -1360,7 +2175,8 @@ inline Json::Value ToJsonValue(const std::pair<F, S>& value) { template <typename F, typename S> inline Json::Value ToJsonValue(const std::map<F, S>& value) { Json::Value array(Json::arrayValue); - for (auto& kv : value) array.append(ToJsonValue(kv)); + for (auto& kv : value) + array.append(ToJsonValue(kv)); return array; } @@ -1370,7 +2186,8 @@ class JsonWriterVisitor { ~JsonWriterVisitor() {} - template <typename T> bool Visit(const char* key, const T* value) { + template <typename T> + bool Visit(const char* key, const T* value) { object_[key] = ToJsonValue(*value); return true; } @@ -1383,7 +2200,7 @@ class JsonWriterVisitor { } template <typename T> - bool VisitArray(const char* key, uint32_t count, const T *value) { + bool VisitArray(const char* key, uint32_t count, const T* value) { object_[key] = ArrayToJsonValue(count, *value); return true; } @@ -1410,7 +2227,8 @@ template <typename T, typename = EnableForStruct<T>> bool AsValue(Json::Value* json_value, T* t); inline bool AsValue(Json::Value* json_value, int32_t* value) { - if (json_value->type() != Json::realValue) return false; + if (json_value->type() != Json::realValue) + return false; double d = json_value->asDouble(); if (!IsIntegral(d) || d < static_cast<double>(std::numeric_limits<int32_t>::min()) || @@ -1421,14 +2239,16 @@ inline bool AsValue(Json::Value* json_value, int32_t* value) { } inline bool AsValue(Json::Value* json_value, uint64_t* value) { - if (json_value->type() != Json::stringValue) return false; + if (json_value->type() != Json::stringValue) + return false; int result = std::sscanf(json_value->asString().c_str(), "0x%016" PRIx64, value); return result == 1; } inline bool AsValue(Json::Value* json_value, uint32_t* value) { - if (json_value->type() != Json::realValue) return false; + if (json_value->type() != Json::realValue) + return false; double d = json_value->asDouble(); if (!IsIntegral(d) || d < 0.0 || d > static_cast<double>(std::numeric_limits<uint32_t>::max())) @@ -1447,7 +2267,8 @@ inline bool AsValue(Json::Value* json_value, uint8_t* value) { } inline bool AsValue(Json::Value* json_value, float* value) { - if (json_value->type() != Json::realValue) return false; + if (json_value->type() != Json::realValue) + return false; *value = static_cast<float>(json_value->asDouble()); return true; } @@ -1456,7 +2277,8 @@ inline bool AsValue(Json::Value* json_value, VkImageLayout* t) { uint32_t value = 0; if (!AsValue(json_value, &value)) return false; - if (!EnumTraits<VkImageLayout>::exist(value)) return false; + if (!EnumTraits<VkImageLayout>::exist(value)) + return false; *t = static_cast<VkImageLayout>(value); return true; } @@ -1466,7 +2288,8 @@ inline bool AsArray(Json::Value* json_value, uint32_t count, T* values) { if (json_value->type() != Json::arrayValue || json_value->size() != count) return false; for (uint32_t i = 0; i < count; ++i) { - if (!AsValue(&(*json_value)[i], values + i)) return false; + if (!AsValue(&(*json_value)[i], values + i)) + return false; } return true; } @@ -1478,12 +2301,13 @@ inline bool AsValue(Json::Value* json_value, T (*value)[N]) { template <size_t N> inline bool AsValue(Json::Value* json_value, char (*value)[N]) { - if (json_value->type() != Json::stringValue) return false; + if (json_value->type() != Json::stringValue) + return false; size_t len = json_value->asString().length(); if (len >= N) return false; memcpy(*value, json_value->asString().c_str(), len); - memset(*value + len, 0, N-len); + memset(*value + len, 0, N - len); return true; } @@ -1491,15 +2315,17 @@ template <typename T, typename = EnableForEnum<T>, typename = void> inline bool AsValue(Json::Value* json_value, T* t) { uint32_t value = 0; if (!AsValue(json_value, &value)) - return false; - if (!EnumTraits<T>::exist(value)) return false; + return false; + if (!EnumTraits<T>::exist(value)) + return false; *t = static_cast<T>(value); return true; } template <typename T> inline bool AsValue(Json::Value* json_value, std::vector<T>* value) { - if (json_value->type() != Json::arrayValue) return false; + if (json_value->type() != Json::arrayValue) + return false; int size = json_value->size(); value->resize(size); return AsArray(json_value, size, value->data()); @@ -1515,11 +2341,13 @@ inline bool AsValue(Json::Value* json_value, std::pair<F, S>* value) { template <typename F, typename S> inline bool AsValue(Json::Value* json_value, std::map<F, S>* value) { - if (json_value->type() != Json::arrayValue) return false; + if (json_value->type() != Json::arrayValue) + return false; int size = json_value->size(); for (int i = 0; i < size; ++i) { std::pair<F, S> elem; - if (!AsValue(&(*json_value)[i], &elem)) return false; + if (!AsValue(&(*json_value)[i], &elem)) + return false; if (!value->insert(elem).second) return false; } @@ -1527,7 +2355,9 @@ inline bool AsValue(Json::Value* json_value, std::map<F, S>* value) { } template <typename T> -bool ReadValue(Json::Value* object, const char* key, T* value, +bool ReadValue(Json::Value* object, + const char* key, + T* value, std::string* errors) { Json::Value json_value = (*object)[key]; if (!json_value) { @@ -1535,7 +2365,8 @@ bool ReadValue(Json::Value* object, const char* key, T* value, *errors = std::string(key) + " missing."; return false; } - if (AsValue(&json_value, value)) return true; + if (AsValue(&json_value, value)) + return true; if (errors) *errors = std::string("Wrong type for ") + std::string(key) + "."; return false; @@ -1551,7 +2382,8 @@ class JsonReaderVisitor { JsonReaderVisitor(Json::Value* object, std::string* errors) : object_(object), errors_(errors) {} - template <typename T> bool Visit(const char* key, T* value) const { + template <typename T> + bool Visit(const char* key, T* value) const { return ReadValue(object_, key, value, errors_); } @@ -1565,27 +2397,28 @@ class JsonReaderVisitor { *errors_ = std::string(key) + " missing."; return false; } - if (AsArray(&json_value, count, *value)) return true; + if (AsArray(&json_value, count, *value)) + return true; if (errors_) *errors_ = std::string("Wrong type for ") + std::string(key) + "."; return false; } template <typename T> - bool VisitArray(const char* key, uint32_t count, T *value) { + bool VisitArray(const char* key, uint32_t count, T* value) { Json::Value json_value = (*object_)[key]; if (!json_value) { if (errors_) *errors_ = std::string(key) + " missing."; return false; } - if (AsArray(&json_value, count, *value)) return true; + if (AsArray(&json_value, count, *value)) + return true; if (errors_) *errors_ = std::string("Wrong type for ") + std::string(key) + "."; return false; } - private: Json::Value* object_; std::string* errors_; @@ -1593,21 +2426,21 @@ class JsonReaderVisitor { template <typename T, typename /*= EnableForStruct<T>*/> bool AsValue(Json::Value* json_value, T* t) { - if (json_value->type() != Json::objectValue) return false; + if (json_value->type() != Json::objectValue) + return false; JsonReaderVisitor visitor(json_value, nullptr); return VisitForRead(&visitor, t); } - -template <typename T> std::string VkTypeToJson(const T& t) { +template <typename T> +std::string VkTypeToJson(const T& t) { JsonWriterVisitor visitor; VisitForWrite(&visitor, t); return visitor.get_object().toStyledString(); } -template <typename T> bool VkTypeFromJson(const std::string& json, - T* t, - std::string* errors) { +template <typename T> +bool VkTypeFromJson(const std::string& json, T* t, std::string* errors) { *t = T(); Json::Value object(Json::objectValue); Json::CharReaderBuilder builder; diff --git a/vulkan/vkjson/vkjson.h b/vulkan/vkjson/vkjson.h index 87a76c1ac9..d74644ca8e 100644 --- a/vulkan/vkjson/vkjson.h +++ b/vulkan/vkjson/vkjson.h @@ -21,8 +21,8 @@ #ifndef VKJSON_H_ #define VKJSON_H_ -#include <vulkan/vulkan.h> #include <string.h> +#include <vulkan/vulkan.h> #include <map> #include <string> @@ -38,44 +38,233 @@ struct VkJsonLayer { std::vector<VkExtensionProperties> extensions; }; -struct VkJsonExtDriverProperties { - VkJsonExtDriverProperties() { +struct VkJsonKHRVariablePointers { + VkJsonKHRVariablePointers() { reported = false; - memset(&driver_properties_khr, 0, - sizeof(VkPhysicalDeviceDriverPropertiesKHR)); + memset(&variable_pointer_features_khr, 0, + sizeof(VkPhysicalDeviceVariablePointerFeaturesKHR)); + memset(&variable_pointers_features_khr, 0, + sizeof(VkPhysicalDeviceVariablePointersFeaturesKHR)); } bool reported; - VkPhysicalDeviceDriverPropertiesKHR driver_properties_khr; + VkPhysicalDeviceVariablePointerFeaturesKHR variable_pointer_features_khr; + VkPhysicalDeviceVariablePointersFeaturesKHR variable_pointers_features_khr; }; -struct VkJsonExtVariablePointerFeatures { - VkJsonExtVariablePointerFeatures() { +struct VkJsonKHRShaderFloat16Int8 { + VkJsonKHRShaderFloat16Int8() { reported = false; - memset(&variable_pointer_features_khr, 0, - sizeof(VkPhysicalDeviceVariablePointerFeaturesKHR)); + memset(&shader_float16_int8_features_khr, 0, + sizeof(VkPhysicalDeviceShaderFloat16Int8FeaturesKHR)); + memset(&float16_int8_features_khr, 0, + sizeof(VkPhysicalDeviceFloat16Int8FeaturesKHR)); } bool reported; - VkPhysicalDeviceVariablePointerFeaturesKHR variable_pointer_features_khr; + VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_float16_int8_features_khr; + VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8_features_khr; }; -struct VkJsonExtImage2DViewOf3DFeatures { - VkJsonExtImage2DViewOf3DFeatures() { +struct VkJsonExtImage2dViewOf3d { + VkJsonExtImage2dViewOf3d() { reported = false; - memset(&image_2D_view_of_3D_features_EXT, 0, + memset(&image_2d_view_of_3d_features_ext, 0, sizeof(VkPhysicalDeviceImage2DViewOf3DFeaturesEXT)); } bool reported; - VkPhysicalDeviceImage2DViewOf3DFeaturesEXT image_2D_view_of_3D_features_EXT; + VkPhysicalDeviceImage2DViewOf3DFeaturesEXT image_2d_view_of_3d_features_ext; }; -struct VkJsonExtShaderFloat16Int8Features { - VkJsonExtShaderFloat16Int8Features() { +struct VkJsonExtCustomBorderColor { + VkJsonExtCustomBorderColor() { reported = false; - memset(&shader_float16_int8_features_khr, 0, - sizeof(VkPhysicalDeviceShaderFloat16Int8FeaturesKHR)); + memset(&custom_border_color_features_ext, 0, + sizeof(VkPhysicalDeviceCustomBorderColorFeaturesEXT)); } bool reported; - VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_float16_int8_features_khr; + VkPhysicalDeviceCustomBorderColorFeaturesEXT custom_border_color_features_ext; +}; + +struct VkJsonExtPrimitiveTopologyListRestart { + VkJsonExtPrimitiveTopologyListRestart() { + reported = false; + memset(&primitive_topology_list_restart_features_ext, 0, + sizeof(VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT)); + } + bool reported; + VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT + primitive_topology_list_restart_features_ext; +}; + +struct VkJsonExtProvokingVertex { + VkJsonExtProvokingVertex() { + reported = false; + memset(&provoking_vertex_features_ext, 0, + sizeof(VkPhysicalDeviceProvokingVertexFeaturesEXT)); + } + bool reported; + VkPhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex_features_ext; +}; + +struct VkJsonKHRIndexTypeUint8 { + VkJsonKHRIndexTypeUint8() { + reported = false; + memset(&index_type_uint8_features_khr, 0, + sizeof(VkPhysicalDeviceIndexTypeUint8FeaturesKHR)); + } + bool reported; + VkPhysicalDeviceIndexTypeUint8FeaturesKHR index_type_uint8_features_khr; +}; + +struct VkJsonExtIndexTypeUint8 { + VkJsonExtIndexTypeUint8() { + reported = false; + memset(&index_type_uint8_features_ext, 0, + sizeof(VkPhysicalDeviceIndexTypeUint8FeaturesEXT)); + } + bool reported; + VkPhysicalDeviceIndexTypeUint8FeaturesEXT index_type_uint8_features_ext; +}; + +struct VkJsonKHRVertexAttributeDivisor { + VkJsonKHRVertexAttributeDivisor() { + reported = false; + memset(&vertex_attribute_divisor_features_khr, 0, + sizeof(VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR)); + } + bool reported; + VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR + vertex_attribute_divisor_features_khr; +}; + +struct VkJsonExtVertexAttributeDivisor { + VkJsonExtVertexAttributeDivisor() { + reported = false; + memset(&vertex_attribute_divisor_features_ext, 0, + sizeof(VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT)); + } + bool reported; + VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT + vertex_attribute_divisor_features_ext; +}; + +struct VkJsonExtTransformFeedback { + VkJsonExtTransformFeedback() { + reported = false; + memset(&transform_feedback_features_ext, 0, + sizeof(VkPhysicalDeviceTransformFeedbackFeaturesEXT)); + } + bool reported; + VkPhysicalDeviceTransformFeedbackFeaturesEXT transform_feedback_features_ext; +}; + +struct VkJsonKHRShaderSubgroupUniformControlFlow { + VkJsonKHRShaderSubgroupUniformControlFlow() { + reported = false; + memset(&shader_subgroup_uniform_control_flow_features_khr, 0, + sizeof(VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR)); + } + bool reported; + VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR + shader_subgroup_uniform_control_flow_features_khr; +}; + +struct VkJsonKHRShaderSubgroupExtendedTypes { + VkJsonKHRShaderSubgroupExtendedTypes() { + reported = false; + memset(&shader_subgroup_extended_types_features_khr, 0, + sizeof(VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR)); + } + bool reported; + VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR + shader_subgroup_extended_types_features_khr; +}; + +struct VkJsonKHR8bitStorage { + VkJsonKHR8bitStorage() { + reported = false; + memset(&bit8_storage_features_khr, 0, + sizeof(VkPhysicalDevice8BitStorageFeaturesKHR)); + } + bool reported; + VkPhysicalDevice8BitStorageFeaturesKHR bit8_storage_features_khr; +}; + +struct VkJsonKHRShaderIntegerDotProduct { + VkJsonKHRShaderIntegerDotProduct() { + reported = false; + memset(&shader_integer_dot_product_features_khr, 0, + sizeof(VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR)); + } + bool reported; + VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR + shader_integer_dot_product_features_khr; +}; + +struct VkJsonIMGRelaxedLineRasterization { + VkJsonIMGRelaxedLineRasterization() { + reported = false; + memset(&relaxed_line_rasterization_features_img, 0, + sizeof(VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG)); + } + bool reported; + VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG + relaxed_line_rasterization_features_img; +}; + +struct VkJsonKHRLineRasterization { + VkJsonKHRLineRasterization() { + reported = false; + memset(&line_rasterization_features_khr, 0, + sizeof(VkPhysicalDeviceLineRasterizationFeaturesKHR)); + } + bool reported; + VkPhysicalDeviceLineRasterizationFeaturesKHR line_rasterization_features_khr; +}; + +struct VkJsonExtLineRasterization { + VkJsonExtLineRasterization() { + reported = false; + memset(&line_rasterization_features_ext, 0, + sizeof(VkPhysicalDeviceLineRasterizationFeaturesEXT)); + } + bool reported; + VkPhysicalDeviceLineRasterizationFeaturesEXT line_rasterization_features_ext; +}; + +struct VkJsonExtPrimitivesGeneratedQuery { + VkJsonExtPrimitivesGeneratedQuery() { + reported = false; + memset(&primitives_generated_query_features_ext, 0, + sizeof(VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT)); + } + bool reported; + VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT + primitives_generated_query_features_ext; +}; + +struct VkJsonKHRShaderFloatControls { + VkJsonKHRShaderFloatControls() { + reported = false; + memset(&float_controls_properties_khr, 0, + sizeof(VkPhysicalDeviceFloatControlsPropertiesKHR)); + } + bool reported; + VkPhysicalDeviceFloatControlsPropertiesKHR float_controls_properties_khr; +}; + +struct VkJsonKHRDriverProperties { + VkJsonKHRDriverProperties() { + reported = false; + memset(&driver_properties_khr, 0, + sizeof(VkPhysicalDeviceDriverPropertiesKHR)); + } + bool reported; + VkPhysicalDeviceDriverPropertiesKHR driver_properties_khr; +}; + +struct VkJsonCore11 { + VkPhysicalDeviceVulkan11Properties properties; + VkPhysicalDeviceVulkan11Features features; }; struct VkJsonCore12 { @@ -109,29 +298,48 @@ struct VkJsonDevice { memset(&bit16_storage_features, 0, sizeof(VkPhysicalDevice16BitStorageFeatures)); memset(&multiview_features, 0, sizeof(VkPhysicalDeviceMultiviewFeatures)); - memset(&variable_pointer_features, 0, - sizeof(VkPhysicalDeviceVariablePointerFeatures)); + memset(&variable_pointers_features, 0, + sizeof(VkPhysicalDeviceVariablePointersFeatures)); memset(&protected_memory_features, 0, sizeof(VkPhysicalDeviceProtectedMemoryFeatures)); memset(&sampler_ycbcr_conversion_features, 0, sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures)); memset(&shader_draw_parameter_features, 0, sizeof(VkPhysicalDeviceShaderDrawParameterFeatures)); + memset(&core11, 0, sizeof(VkJsonCore11)); memset(&core12, 0, sizeof(VkJsonCore12)); memset(&core13, 0, sizeof(VkJsonCore13)); memset(&core14, 0, sizeof(VkJsonCore14)); } + VkJsonKHRVariablePointers khr_variable_pointers; + VkJsonKHRShaderFloat16Int8 khr_shader_float16_int8; + VkJsonExtImage2dViewOf3d ext_image_2d_view_of_3d; + VkJsonExtCustomBorderColor ext_custom_border_color; + VkJsonExtPrimitiveTopologyListRestart ext_primitive_topology_list_restart; + VkJsonExtProvokingVertex ext_provoking_vertex; + VkJsonKHRIndexTypeUint8 khr_index_type_uint8; + VkJsonExtIndexTypeUint8 ext_index_type_uint8; + VkJsonKHRVertexAttributeDivisor khr_vertex_attribute_divisor; + VkJsonExtVertexAttributeDivisor ext_vertex_attribute_divisor; + VkJsonExtTransformFeedback ext_transform_feedback; + VkJsonKHRShaderSubgroupUniformControlFlow + khr_shader_subgroup_uniform_control_flow; + VkJsonKHRShaderSubgroupExtendedTypes khr_shader_subgroup_extended_types; + VkJsonKHR8bitStorage khr_8bit_storage; + VkJsonKHRShaderIntegerDotProduct khr_shader_integer_dot_product; + VkJsonIMGRelaxedLineRasterization img_relaxed_line_rasterization; + VkJsonKHRLineRasterization khr_line_rasterization; + VkJsonExtLineRasterization ext_line_rasterization; + VkJsonExtPrimitivesGeneratedQuery ext_primitives_generated_query; + VkJsonKHRShaderFloatControls khr_shader_float_controls; + VkJsonKHRDriverProperties khr_driver_properties; + VkJsonCore11 core11; + VkJsonCore12 core12; + VkJsonCore13 core13; + VkJsonCore14 core14; VkPhysicalDeviceProperties properties; VkPhysicalDeviceFeatures features; - VkJsonExtDriverProperties ext_driver_properties; - VkJsonExtVariablePointerFeatures ext_variable_pointer_features; - VkJsonExtImage2DViewOf3DFeatures ext_image_2d_view_of_3d_features; - VkJsonExtShaderFloat16Int8Features ext_shader_float16_int8_features; VkPhysicalDeviceMemoryProperties memory; - std::vector<VkQueueFamilyProperties> queues; - std::vector<VkExtensionProperties> extensions; - std::vector<VkLayerProperties> layers; - std::map<VkFormat, VkFormatProperties> formats; VkPhysicalDeviceSubgroupProperties subgroup_properties; VkPhysicalDevicePointClippingProperties point_clipping_properties; VkPhysicalDeviceMultiviewProperties multiview_properties; @@ -139,18 +347,19 @@ struct VkJsonDevice { VkPhysicalDeviceMaintenance3Properties maintenance3_properties; VkPhysicalDevice16BitStorageFeatures bit16_storage_features; VkPhysicalDeviceMultiviewFeatures multiview_features; - VkPhysicalDeviceVariablePointerFeatures variable_pointer_features; + VkPhysicalDeviceVariablePointersFeatures variable_pointers_features; VkPhysicalDeviceProtectedMemoryFeatures protected_memory_features; VkPhysicalDeviceSamplerYcbcrConversionFeatures sampler_ycbcr_conversion_features; VkPhysicalDeviceShaderDrawParameterFeatures shader_draw_parameter_features; + std::vector<VkQueueFamilyProperties> queues; + std::vector<VkExtensionProperties> extensions; + std::vector<VkLayerProperties> layers; + std::map<VkFormat, VkFormatProperties> formats; std::map<VkExternalFenceHandleTypeFlagBits, VkExternalFenceProperties> external_fence_properties; std::map<VkExternalSemaphoreHandleTypeFlagBits, VkExternalSemaphoreProperties> external_semaphore_properties; - VkJsonCore12 core12; - VkJsonCore13 core13; - VkJsonCore14 core14; }; struct VkJsonDeviceGroup { @@ -204,4 +413,4 @@ inline bool VkJsonAllPropertiesFromJson(const std::string& json, return VkJsonDeviceFromJson(json, properties, errors); } -#endif // VKJSON_H_ +#endif // VKJSON_H_
\ No newline at end of file diff --git a/vulkan/vkjson/vkjson_instance.cc b/vulkan/vkjson/vkjson_instance.cc index 04bb446e40..22b3204e61 100644 --- a/vulkan/vkjson/vkjson_instance.cc +++ b/vulkan/vkjson/vkjson_instance.cc @@ -79,13 +79,25 @@ VkJsonDevice VkJsonGetDevice(VkPhysicalDevice physical_device) { nullptr, {}, }; + + if (HasExtension("VK_KHR_shader_float_controls", device.extensions)) { + device.khr_shader_float_controls.reported = true; + device.khr_shader_float_controls.float_controls_properties_khr.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES; + device.khr_shader_float_controls.float_controls_properties_khr.pNext = + properties.pNext; + properties.pNext = + &device.khr_shader_float_controls.float_controls_properties_khr; + } + if (HasExtension("VK_KHR_driver_properties", device.extensions)) { - device.ext_driver_properties.reported = true; - device.ext_driver_properties.driver_properties_khr.sType = - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR; - device.ext_driver_properties.driver_properties_khr.pNext = properties.pNext; - properties.pNext = &device.ext_driver_properties.driver_properties_khr; + device.khr_driver_properties.reported = true; + device.khr_driver_properties.driver_properties_khr.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; + device.khr_driver_properties.driver_properties_khr.pNext = properties.pNext; + properties.pNext = &device.khr_driver_properties.driver_properties_khr; } + vkGetPhysicalDeviceProperties2(physical_device, &properties); device.properties = properties.properties; @@ -94,35 +106,215 @@ VkJsonDevice VkJsonGetDevice(VkPhysicalDevice physical_device) { nullptr, {}, }; + if (HasExtension("VK_KHR_variable_pointers", device.extensions)) { - device.ext_variable_pointer_features.reported = true; - device.ext_variable_pointer_features.variable_pointer_features_khr.sType = - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR; - device.ext_variable_pointer_features.variable_pointer_features_khr.pNext = + device.khr_variable_pointers.reported = true; + device.khr_variable_pointers.variable_pointer_features_khr.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES; + device.khr_variable_pointers.variable_pointer_features_khr.pNext = + features.pNext; + features.pNext = + &device.khr_variable_pointers.variable_pointer_features_khr; + device.khr_variable_pointers.variable_pointers_features_khr.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES; + device.khr_variable_pointers.variable_pointers_features_khr.pNext = + features.pNext; + features.pNext = + &device.khr_variable_pointers.variable_pointers_features_khr; + } + + if (HasExtension("VK_KHR_shader_float16_int8", device.extensions)) { + device.khr_shader_float16_int8.reported = true; + device.khr_shader_float16_int8.shader_float16_int8_features_khr.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES; + device.khr_shader_float16_int8.shader_float16_int8_features_khr.pNext = features.pNext; features.pNext = - &device.ext_variable_pointer_features.variable_pointer_features_khr; + &device.khr_shader_float16_int8.shader_float16_int8_features_khr; + device.khr_shader_float16_int8.float16_int8_features_khr.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES; + device.khr_shader_float16_int8.float16_int8_features_khr.pNext = + features.pNext; + features.pNext = &device.khr_shader_float16_int8.float16_int8_features_khr; } + if (HasExtension("VK_EXT_image_2d_view_of_3d", device.extensions)) { - device.ext_image_2d_view_of_3d_features.reported = true; - device.ext_image_2d_view_of_3d_features.image_2D_view_of_3D_features_EXT - .sType = + device.ext_image_2d_view_of_3d.reported = true; + device.ext_image_2d_view_of_3d.image_2d_view_of_3d_features_ext.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT; - device.ext_image_2d_view_of_3d_features.image_2D_view_of_3D_features_EXT + device.ext_image_2d_view_of_3d.image_2d_view_of_3d_features_ext.pNext = + features.pNext; + features.pNext = + &device.ext_image_2d_view_of_3d.image_2d_view_of_3d_features_ext; + } + + if (HasExtension("VK_EXT_custom_border_color", device.extensions)) { + device.ext_custom_border_color.reported = true; + device.ext_custom_border_color.custom_border_color_features_ext.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT; + device.ext_custom_border_color.custom_border_color_features_ext.pNext = + features.pNext; + features.pNext = + &device.ext_custom_border_color.custom_border_color_features_ext; + } + + if (HasExtension("VK_EXT_primitive_topology_list_restart", + device.extensions)) { + device.ext_primitive_topology_list_restart.reported = true; + device.ext_primitive_topology_list_restart + .primitive_topology_list_restart_features_ext.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT; + device.ext_primitive_topology_list_restart + .primitive_topology_list_restart_features_ext.pNext = features.pNext; + features.pNext = &device.ext_primitive_topology_list_restart + .primitive_topology_list_restart_features_ext; + } + + if (HasExtension("VK_EXT_provoking_vertex", device.extensions)) { + device.ext_provoking_vertex.reported = true; + device.ext_provoking_vertex.provoking_vertex_features_ext.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT; + device.ext_provoking_vertex.provoking_vertex_features_ext.pNext = + features.pNext; + features.pNext = &device.ext_provoking_vertex.provoking_vertex_features_ext; + } + + if (HasExtension("VK_KHR_index_type_uint8", device.extensions)) { + device.khr_index_type_uint8.reported = true; + device.khr_index_type_uint8.index_type_uint8_features_khr.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES; + device.khr_index_type_uint8.index_type_uint8_features_khr.pNext = + features.pNext; + features.pNext = &device.khr_index_type_uint8.index_type_uint8_features_khr; + } + + if (HasExtension("VK_EXT_index_type_uint8", device.extensions)) { + device.ext_index_type_uint8.reported = true; + device.ext_index_type_uint8.index_type_uint8_features_ext.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES; + device.ext_index_type_uint8.index_type_uint8_features_ext.pNext = + features.pNext; + features.pNext = &device.ext_index_type_uint8.index_type_uint8_features_ext; + } + + if (HasExtension("VK_KHR_vertex_attribute_divisor", device.extensions)) { + device.khr_vertex_attribute_divisor.reported = true; + device.khr_vertex_attribute_divisor.vertex_attribute_divisor_features_khr + .sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES; + device.khr_vertex_attribute_divisor.vertex_attribute_divisor_features_khr .pNext = features.pNext; - features.pNext = &device.ext_image_2d_view_of_3d_features - .image_2D_view_of_3D_features_EXT; + features.pNext = &device.khr_vertex_attribute_divisor + .vertex_attribute_divisor_features_khr; } - if (HasExtension("VK_KHR_shader_float16_int8", device.extensions)) { - device.ext_shader_float16_int8_features.reported = true; - device.ext_shader_float16_int8_features.shader_float16_int8_features_khr + + if (HasExtension("VK_EXT_vertex_attribute_divisor", device.extensions)) { + device.ext_vertex_attribute_divisor.reported = true; + device.ext_vertex_attribute_divisor.vertex_attribute_divisor_features_ext .sType = - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR; - device.ext_shader_float16_int8_features.shader_float16_int8_features_khr + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES; + device.ext_vertex_attribute_divisor.vertex_attribute_divisor_features_ext .pNext = features.pNext; - features.pNext = &device.ext_shader_float16_int8_features - .shader_float16_int8_features_khr; + features.pNext = &device.ext_vertex_attribute_divisor + .vertex_attribute_divisor_features_ext; } + + if (HasExtension("VK_EXT_transform_feedback", device.extensions)) { + device.ext_transform_feedback.reported = true; + device.ext_transform_feedback.transform_feedback_features_ext.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; + device.ext_transform_feedback.transform_feedback_features_ext.pNext = + features.pNext; + features.pNext = + &device.ext_transform_feedback.transform_feedback_features_ext; + } + + if (HasExtension("VK_KHR_shader_subgroup_uniform_control_flow", + device.extensions)) { + device.khr_shader_subgroup_uniform_control_flow.reported = true; + device.khr_shader_subgroup_uniform_control_flow + .shader_subgroup_uniform_control_flow_features_khr.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR; + device.khr_shader_subgroup_uniform_control_flow + .shader_subgroup_uniform_control_flow_features_khr.pNext = + features.pNext; + features.pNext = &device.khr_shader_subgroup_uniform_control_flow + .shader_subgroup_uniform_control_flow_features_khr; + } + + if (HasExtension("VK_KHR_shader_subgroup_extended_types", + device.extensions)) { + device.khr_shader_subgroup_extended_types.reported = true; + device.khr_shader_subgroup_extended_types + .shader_subgroup_extended_types_features_khr.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES; + device.khr_shader_subgroup_extended_types + .shader_subgroup_extended_types_features_khr.pNext = features.pNext; + features.pNext = &device.khr_shader_subgroup_extended_types + .shader_subgroup_extended_types_features_khr; + } + + if (HasExtension("VK_KHR_8bit_storage", device.extensions)) { + device.khr_8bit_storage.reported = true; + device.khr_8bit_storage.bit8_storage_features_khr.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES; + device.khr_8bit_storage.bit8_storage_features_khr.pNext = features.pNext; + features.pNext = &device.khr_8bit_storage.bit8_storage_features_khr; + } + + if (HasExtension("VK_KHR_shader_integer_dot_product", device.extensions)) { + device.khr_shader_integer_dot_product.reported = true; + device.khr_shader_integer_dot_product + .shader_integer_dot_product_features_khr.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES; + device.khr_shader_integer_dot_product + .shader_integer_dot_product_features_khr.pNext = features.pNext; + features.pNext = &device.khr_shader_integer_dot_product + .shader_integer_dot_product_features_khr; + } + + if (HasExtension("VK_IMG_relaxed_line_rasterization", device.extensions)) { + device.img_relaxed_line_rasterization.reported = true; + device.img_relaxed_line_rasterization + .relaxed_line_rasterization_features_img.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RELAXED_LINE_RASTERIZATION_FEATURES_IMG; + device.img_relaxed_line_rasterization + .relaxed_line_rasterization_features_img.pNext = features.pNext; + features.pNext = &device.img_relaxed_line_rasterization + .relaxed_line_rasterization_features_img; + } + + if (HasExtension("VK_KHR_line_rasterization", device.extensions)) { + device.khr_line_rasterization.reported = true; + device.khr_line_rasterization.line_rasterization_features_khr.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES; + device.khr_line_rasterization.line_rasterization_features_khr.pNext = + features.pNext; + features.pNext = + &device.khr_line_rasterization.line_rasterization_features_khr; + } + + if (HasExtension("VK_EXT_line_rasterization", device.extensions)) { + device.ext_line_rasterization.reported = true; + device.ext_line_rasterization.line_rasterization_features_ext.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES; + device.ext_line_rasterization.line_rasterization_features_ext.pNext = + features.pNext; + features.pNext = + &device.ext_line_rasterization.line_rasterization_features_ext; + } + + if (HasExtension("VK_EXT_primitives_generated_query", device.extensions)) { + device.ext_primitives_generated_query.reported = true; + device.ext_primitives_generated_query + .primitives_generated_query_features_ext.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT; + device.ext_primitives_generated_query + .primitives_generated_query_features_ext.pNext = features.pNext; + features.pNext = &device.ext_primitives_generated_query + .primitives_generated_query_features_ext; + } + vkGetPhysicalDeviceFeatures2(physical_device, &features); device.features = features.features; @@ -194,20 +386,15 @@ VkJsonDevice VkJsonGetDevice(VkPhysicalDevice physical_device) { vkGetPhysicalDeviceProperties2(physical_device, &properties); - device.bit16_storage_features.sType = - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES; - device.bit16_storage_features.pNext = features.pNext; - features.pNext = &device.bit16_storage_features; - device.multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES; device.multiview_features.pNext = features.pNext; features.pNext = &device.multiview_features; - device.variable_pointer_features.sType = - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES; - device.variable_pointer_features.pNext = features.pNext; - features.pNext = &device.variable_pointer_features; + device.variable_pointers_features.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES; + device.variable_pointers_features.pNext = features.pNext; + features.pNext = &device.variable_pointers_features; device.protected_memory_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES; @@ -220,10 +407,15 @@ VkJsonDevice VkJsonGetDevice(VkPhysicalDevice physical_device) { features.pNext = &device.sampler_ycbcr_conversion_features; device.shader_draw_parameter_features.sType = - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES; + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES; device.shader_draw_parameter_features.pNext = features.pNext; features.pNext = &device.shader_draw_parameter_features; + device.bit16_storage_features.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES; + device.bit16_storage_features.pNext = features.pNext; + features.pNext = &device.bit16_storage_features; + vkGetPhysicalDeviceFeatures2(physical_device, &features); VkPhysicalDeviceExternalFenceInfo external_fence_info = { @@ -271,6 +463,11 @@ VkJsonDevice VkJsonGetDevice(VkPhysicalDevice physical_device) { } if (device.properties.apiVersion >= VK_API_VERSION_1_2) { + device.core11.properties.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES; + device.core11.properties.pNext = properties.pNext; + properties.pNext = &device.core11.properties; + device.core12.properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES; device.core12.properties.pNext = properties.pNext; @@ -278,6 +475,11 @@ VkJsonDevice VkJsonGetDevice(VkPhysicalDevice physical_device) { vkGetPhysicalDeviceProperties2(physical_device, &properties); + device.core11.features.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; + device.core11.features.pNext = features.pNext; + features.pNext = &device.core11.features; + device.core12.features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; device.core12.features.pNext = features.pNext; @@ -337,7 +539,8 @@ VkJsonInstance VkJsonGetInstance() { return VkJsonInstance(); instance.layers.reserve(count); for (auto& layer : layers) { - instance.layers.push_back(VkJsonLayer{layer, std::vector<VkExtensionProperties>()}); + instance.layers.push_back( + VkJsonLayer{layer, std::vector<VkExtensionProperties>()}); if (!EnumerateExtensions(layer.layerName, &instance.layers.back().extensions)) return VkJsonInstance(); |