summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qfloat16.cpp2
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp8
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h1
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp5
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp10
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h5
-rw-r--r--src/corelib/text/qstring.cpp3
-rw-r--r--src/corelib/time/qdatetime.cpp24
-rw-r--r--src/corelib/tools/qhash.cpp8
-rw-r--r--src/corelib/tools/qhash.h43
-rw-r--r--src/corelib/tools/qiterator.h26
-rw-r--r--src/corelib/tools/qiterator.qdoc13
-rw-r--r--src/corelib/tools/qmap.cpp8
-rw-r--r--src/corelib/tools/qmap.h53
-rw-r--r--src/gui/image/qbmphandler.cpp7
-rw-r--r--src/gui/image/qbmphandler_p.h3
-rw-r--r--src/gui/image/qpnghandler.cpp7
-rw-r--r--src/gui/image/qpnghandler_p.h4
-rw-r--r--src/gui/image/qppmhandler.cpp7
-rw-r--r--src/gui/image/qppmhandler_p.h4
-rw-r--r--src/gui/image/qxbmhandler.cpp7
-rw-r--r--src/gui/image/qxbmhandler_p.h4
-rw-r--r--src/gui/image/qxpmhandler.cpp7
-rw-r--r--src/gui/image/qxpmhandler_p.h4
-rw-r--r--src/gui/kernel/qwindow.cpp10
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp13
-rw-r--r--src/gui/rhi/qrhi.cpp33
-rw-r--r--src/gui/rhi/qrhi_p.h1
-rw-r--r--src/gui/rhi/qrhid3d11.cpp269
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h24
-rw-r--r--src/gui/rhi/qrhimetal.mm23
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h1
-rw-r--r--src/gui/rhi/qrhivulkan.cpp90
-rw-r--r--src/gui/rhi/qrhivulkan_p.h1
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h4
-rw-r--r--src/gui/rhi/qshader.cpp3
-rw-r--r--src/gui/rhi/qshader_p_p.h3
-rw-r--r--src/gui/rhi/qshaderdescription.cpp57
-rw-r--r--src/gui/rhi/qshaderdescription_p.h3
-rw-r--r--src/gui/rhi/qshaderdescription_p_p.h2
-rw-r--r--src/gui/text/qtextmarkdownimporter.cpp7
-rw-r--r--src/gui/text/qtextmarkdownimporter_p.h3
-rw-r--r--src/gui/vulkan/qvulkaninstance.cpp2
-rw-r--r--src/gui/vulkan/qvulkanwindow.cpp13
-rw-r--r--src/gui/vulkan/qvulkanwindow.h1
-rw-r--r--src/network/access/qnetworkreply.cpp15
-rw-r--r--src/network/access/qnetworkreply.h4
-rw-r--r--src/network/access/qnetworkreplydataimpl.cpp2
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp2
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp4
-rw-r--r--src/plugins/imageformats/gif/qgifhandler.cpp7
-rw-r--r--src/plugins/imageformats/gif/qgifhandler_p.h4
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp11
-rw-r--r--src/plugins/imageformats/ico/qicohandler.h4
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler.cpp7
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler_p.h4
-rw-r--r--src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp25
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm61
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoavulkaninstance.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoavulkaninstance.mm9
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac.mm21
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp4
-rw-r--r--src/tools/uic/python/pythonwriteimports.cpp2
-rw-r--r--src/widgets/widgets/qmenu.cpp9
68 files changed, 642 insertions, 401 deletions
diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp
index 80a851e4e4..3d82bbe95a 100644
--- a/src/corelib/global/qfloat16.cpp
+++ b/src/corelib/global/qfloat16.cpp
@@ -147,7 +147,7 @@ QT_BEGIN_NAMESPACE
/*!
\since 5.15
- \fn qfloat16::copySign(qfloat16 sign) const noexcept
+ \fn qfloat16 qfloat16::copySign(qfloat16 sign) const noexcept
Returns a qfloat16 with the sign of \a sign but the rest of its value taken
from this qfloat16. Serves as qfloat16's equivalent of std::copysign().
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index 8616631603..f2216d4113 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -884,7 +884,11 @@ void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier)
return;
}
#endif
+ doUnregisterEventNotifier(notifier);
+}
+void QEventDispatcherWin32::doUnregisterEventNotifier(QWinEventNotifier *notifier)
+{
Q_D(QEventDispatcherWin32);
int i = d->winEventNotifierList.indexOf(notifier);
@@ -996,6 +1000,10 @@ void QEventDispatcherWin32::closingDown()
doUnregisterSocketNotifier((*(d->sn_except.begin()))->obj);
Q_ASSERT(d->active_fd.isEmpty());
+ // clean up any eventnotifiers
+ while (!d->winEventNotifierList.isEmpty())
+ doUnregisterEventNotifier(d->winEventNotifierList.first());
+
// clean up any timers
for (int i = 0; i < d->timerVec.count(); ++i)
d->unregisterTimer(d->timerVec.at(i));
diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h
index e6620178d8..a482c8b7db 100644
--- a/src/corelib/kernel/qeventdispatcher_win_p.h
+++ b/src/corelib/kernel/qeventdispatcher_win_p.h
@@ -110,6 +110,7 @@ protected:
QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent = 0);
virtual void sendPostedEvents();
void doUnregisterSocketNotifier(QSocketNotifier *notifier);
+ void doUnregisterEventNotifier(QWinEventNotifier *notifier);
private:
friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp
index db5d44b276..0c574e9a4b 100644
--- a/src/corelib/kernel/qwineventnotifier.cpp
+++ b/src/corelib/kernel/qwineventnotifier.cpp
@@ -198,11 +198,8 @@ void QWinEventNotifier::setEnabled(bool enable)
d->enabled = enable;
QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed();
- if (!eventDispatcher) { // perhaps application is shutting down
- if (!enable && d->waitHandle != nullptr)
- d->unregisterWaitObject();
+ if (!eventDispatcher) // perhaps application is shutting down
return;
- }
if (Q_UNLIKELY(thread() != QThread::currentThread())) {
qWarning("QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread");
return;
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index 4aee772366..9dba72923a 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -664,7 +664,15 @@ QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnu
load(data, size);
}
-#endif
+#else // !QT_CONFIG(mimetype_database)
+// never called in release mode, but some debug builds may need
+// this to be defined.
+QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
+ : QMimeProviderBase(db, QString())
+{
+ Q_UNREACHABLE();
+}
+#endif // QT_CONFIG(mimetype_database)
QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory)
: QMimeProviderBase(db, directory)
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index c4e712b318..9c91903684 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -135,13 +135,10 @@ public:
enum InternalDatabaseEnum { InternalDatabase };
#if QT_CONFIG(mimetype_database)
enum : bool { InternalDatabaseAvailable = true };
- QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum);
#else
enum : bool { InternalDatabaseAvailable = false };
- QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
- : QMimeProviderBase(db, QString())
- { Q_UNREACHABLE(); };
#endif
+ QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum);
QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory);
~QMimeXMLProvider();
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index da2c44bef6..757f248e8a 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -7626,7 +7626,10 @@ static ResultList splitString(const StringSource &source, const QChar *sep,
#if QT_DEPRECATED_SINCE(5, 15)
Qt::SplitBehavior mapSplitBehavior(QString::SplitBehavior sb)
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return sb & QString::SkipEmptyParts ? Qt::SkipEmptyParts : Qt::KeepEmptyParts;
+QT_WARNING_POP
}
#endif
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index e9fe34110a..47539141bd 100644
--- a/src/corelib/time/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -1383,6 +1383,10 @@ QT_WARNING_POP
If the datetime is invalid, an empty string will be returned.
+ \note If localized month and day names are desired, please switch to using
+ QLocale::system().toString() as QDate methods shall change to use English (C
+ locale) names at Qt 6.
+
\sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
*/
@@ -1884,6 +1888,10 @@ QT_WARNING_POP
\snippet code/src_corelib_tools_qdatetime.cpp 3
+ \note If localized month and day names are used, please switch to using
+ QLocale::system().toDate() as QDate methods shall change to only recognize
+ English (C locale) names at Qt 6.
+
\sa toString(), QDateTime::fromString(), QTime::fromString(),
QLocale::toDate()
*/
@@ -2244,6 +2252,10 @@ QT_WARNING_POP
If the time is invalid, an empty string will be returned.
If \a format is empty, the default format "hh:mm:ss" is used.
+ \note If localized forms of am or pm (the AP, ap, A or a formats) are
+ desired, please switch to using QLocale::system().toString() as QTime
+ methods shall change to use English (C locale) at Qt 6.
+
\sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
*/
QString QTime::toString(QStringView format) const
@@ -2641,6 +2653,10 @@ QT_WARNING_POP
\snippet code/src_corelib_tools_qdatetime.cpp 8
+ \note If localized forms of am or pm (the AP, ap, A or a formats) are used,
+ please switch to using QLocale::system().toTime() as QTime methods shall
+ change to only recognize English (C locale) at Qt 6.
+
\sa toString(), QDateTime::fromString(), QDate::fromString(),
QLocale::toTime()
*/
@@ -4541,6 +4557,10 @@ QT_WARNING_POP
If the datetime is invalid, an empty string will be returned.
+ \note If localized month and day names are desired, please switch to using
+ QLocale::system().toString() as QDateTime methods shall change to use
+ English (C locale) names at Qt 6.
+
\sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString()
*/
QString QDateTime::toString(QStringView format) const
@@ -5580,6 +5600,10 @@ QT_WARNING_POP
\snippet code/src_corelib_tools_qdatetime.cpp 14
+ \note If localized month and day names are used, please switch to using
+ QLocale::system().toDateTime() as QDateTime methods shall change to only
+ recognize English (C locale) names at Qt 6.
+
\sa toString(), QDate::fromString(), QTime::fromString(),
QLocale::toDateTime()
*/
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 15f731a603..7ebc374d9f 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -1574,7 +1574,6 @@ uint qHash(long double key, uint seed) noexcept
*/
/*! \fn template <class Key, class T> int QHash<Key, T>::count(const Key &key) const
- \obsolete
Returns the number of items associated with the \a key.
@@ -2693,13 +2692,6 @@ uint qHash(long double key, uint seed) noexcept
\sa QHash::remove()
*/
-/*! \fn template <class Key, class T> int QMultiHash<Key, T>::count(const Key &key) const
-
- Returns the number of items associated with the \a key.
-
- \sa contains(), insert()
-*/
-
/*!
\fn template <class Key, class T> int QMultiHash<Key, T>::count(const Key &key, const T &value) const
\since 4.3
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 59883e3968..c87cf56988 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -309,10 +309,10 @@ public:
QList<Key> keys(const T &value) const;
QList<T> values() const;
#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QList<Key> uniqueKeys() const;
- QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QList<T> values(const Key &key) const;
- QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") int count(const Key &key) const;
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") QList<Key> uniqueKeys() const;
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") QList<T> values(const Key &key) const;
#endif
+ int count(const Key &key) const;
class const_iterator;
@@ -512,8 +512,8 @@ public:
iterator insert(const Key &key, const T &value);
void insert(const QHash &hash);
#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
- QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QHash &unite(const QHash &other);
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") QHash &unite(const QHash &other);
#endif
// STL compatibility
@@ -711,6 +711,19 @@ Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values() const
}
template <class Key, class T>
+Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::count(const Key &akey) const
+{
+ int cnt = 0;
+ Node *node = *findNode(akey);
+ if (node != e) {
+ do {
+ ++cnt;
+ } while ((node = node->next) != e && node->key == akey);
+ }
+ return cnt;
+}
+
+template <class Key, class T>
Q_INLINE_TEMPLATE const T QHash<Key, T>::operator[](const Key &akey) const
{
return value(akey);
@@ -1053,7 +1066,6 @@ public:
int remove(const Key &key, const T &value);
- int count(const Key &key) const;
int count(const Key &key, const T &value) const;
QList<Key> uniqueKeys() const;
@@ -1207,12 +1219,6 @@ Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values(const Key &akey) const
}
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::count(const Key &akey) const
-{
- return static_cast<const QMultiHash<Key, T> *>(this)->count(akey);
-}
-
-template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QList<Key> QHash<Key, T>::uniqueKeys() const
{
return static_cast<const QMultiHash<Key, T> *>(this)->uniqueKeys();
@@ -1232,19 +1238,6 @@ Q_OUTOFLINE_TEMPLATE QList<T> QMultiHash<Key, T>::values(const Key &akey) const
return res;
}
-template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE int QMultiHash<Key, T>::count(const Key &akey) const
-{
- int cnt = 0;
- Node *node = *findNode(akey);
- if (node != this->e) {
- do {
- ++cnt;
- } while ((node = node->next) != this->e && node->key == akey);
- }
- return cnt;
-}
-
#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
template <class Key, class T>
class QHashIterator
diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h
index 84a0e116ca..c4665c7c87 100644
--- a/src/corelib/tools/qiterator.h
+++ b/src/corelib/tools/qiterator.h
@@ -195,7 +195,6 @@ public:
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::difference_type difference_type;
typedef std::pair<Key, T> value_type;
- typedef const value_type *pointer;
typedef const value_type &reference;
QKeyValueIterator() = default;
@@ -206,6 +205,31 @@ public:
return std::pair<Key, T>(i.key(), i.value());
}
+ struct pointer {
+ pointer(value_type&& r_)
+ : r(std::move(r_))
+ {}
+
+ pointer() = default;
+ pointer(const pointer &other) = default;
+ pointer(pointer &&other) = default;
+ pointer& operator=(const pointer &other) = default;
+ pointer& operator=(pointer &&other) = default;
+
+ value_type& operator*() const {
+ return r;
+ }
+
+ value_type r;
+ const value_type *operator->() const {
+ return &r;
+ }
+ };
+
+ pointer operator->() const {
+ return pointer(std::pair<Key, T>(i.key(), i.value()));
+ }
+
friend bool operator==(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i == rhs.i; }
friend bool operator!=(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i != rhs.i; }
diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc
index 69f9d52ce5..8cfa665ffd 100644
--- a/src/corelib/tools/qiterator.qdoc
+++ b/src/corelib/tools/qiterator.qdoc
@@ -57,7 +57,7 @@
\internal
*/
-/*! \typedef QKeyValueIterator::pointer
+/*! \struct QKeyValueIterator::pointer
\internal
*/
@@ -75,11 +75,20 @@
Constructs a QKeyValueIterator on top of \a o.
*/
-/*! \fn template<typename Key, typename T, class Iterator> const T &QKeyValueIterator<Key, T, Iterator>::operator*() const
+/*! \fn template<typename Key, typename T, class Iterator> std::pair<Key, T> QKeyValueIterator<Key, T, Iterator>::operator*() const
Returns the current entry as a pair.
*/
+/*! \fn template<typename Key, typename T, class Iterator> pointer QKeyValueIterator<Key, T, Iterator>::operator->() const
+
+ Returns the current entry as a pointer-like object to the pair.
+
+ \since 5.15
+
+ \sa operator*()
+*/
+
/*! \fn template<typename Key, typename T, class Iterator> bool operator==(QKeyValueIterator<Key, T, Iterator> lhs, QKeyValueIterator<Key, T, Iterator> rhs)
\relates QKeyValueIterator
diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp
index 6d2b8f7a3e..25ea5f25d7 100644
--- a/src/corelib/tools/qmap.cpp
+++ b/src/corelib/tools/qmap.cpp
@@ -814,11 +814,10 @@ void QMapDataBase::freeData(QMapDataBase *d)
*/
/*! \fn template <class Key, class T> int QMap<Key, T>::count(const Key &key) const
- \obsolete
Returns the number of items associated with key \a key.
- \sa QMultiMap::count()
+ \sa contains(), QMultiMap::count()
*/
/*! \fn template <class Key, class T> int QMap<Key, T>::count() const
@@ -2115,11 +2114,6 @@ void QMapDataBase::freeData(QMapDataBase *d)
inserted one.
*/
-/*! \fn template <class Key, class T> int QMultiMap<Key, T>::count(const Key &key) const
-
- Returns the number of items associated with key \a key.
-*/
-
/*! \fn template <class Key, class T> QList<Key> QMultiMap<Key, T>::uniqueKeys() const
\since 4.2
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index a971919e54..6081019294 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -373,10 +373,10 @@ public:
QList<Key> keys(const T &value) const;
QList<T> values() const;
#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") QList<Key> uniqueKeys() const;
- QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") QList<T> values(const Key &key) const;
- QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") int count(const Key &key) const;
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QList<Key> uniqueKeys() const;
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QList<T> values(const Key &key) const;
#endif
+ int count(const Key &key) const;
inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
@@ -559,9 +559,9 @@ public:
iterator insert(const_iterator pos, const Key &key, const T &value);
void insert(const QMap<Key, T> &map);
#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
- QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const_iterator pos, const Key &akey, const T &avalue);
- QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") QMap<Key, T> &unite(const QMap<Key, T> &other);
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const_iterator pos, const Key &akey, const T &avalue);
+ QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QMap<Key, T> &unite(const QMap<Key, T> &other);
#endif
// STL compatibility
@@ -655,6 +655,23 @@ Q_INLINE_TEMPLATE T &QMap<Key, T>::operator[](const Key &akey)
}
template <class Key, class T>
+Q_INLINE_TEMPLATE int QMap<Key, T>::count(const Key &akey) const
+{
+ Node *firstNode;
+ Node *lastNode;
+ d->nodeRange(akey, &firstNode, &lastNode);
+
+ const_iterator ci_first(firstNode);
+ const const_iterator ci_last(lastNode);
+ int cnt = 0;
+ while (ci_first != ci_last) {
+ ++cnt;
+ ++ci_first;
+ }
+ return cnt;
+}
+
+template <class Key, class T>
Q_INLINE_TEMPLATE bool QMap<Key, T>::contains(const Key &akey) const
{
return d->findNode(akey) != nullptr;
@@ -1116,7 +1133,6 @@ public:
int remove(const Key &key, const T &value);
- int count(const Key &key) const;
int count(const Key &key, const T &value) const;
typename QMap<Key, T>::iterator find(const Key &key, const T &value) {
@@ -1290,23 +1306,6 @@ Q_INLINE_TEMPLATE int QMultiMap<Key, T>::remove(const Key &key, const T &value)
}
template <class Key, class T>
-Q_INLINE_TEMPLATE int QMultiMap<Key, T>::count(const Key &akey) const
-{
- QMultiMap::Node *firstNode;
- QMultiMap::Node *lastNode;
- this->d->nodeRange(akey, &firstNode, &lastNode);
-
- typename QMap<Key, T>::const_iterator ci_first(firstNode);
- const typename QMap<Key, T>::const_iterator ci_last(lastNode);
- int cnt = 0;
- while (ci_first != ci_last) {
- ++cnt;
- ++ci_first;
- }
- return cnt;
-}
-
-template <class Key, class T>
Q_INLINE_TEMPLATE int QMultiMap<Key, T>::count(const Key &key, const T &value) const
{
int n = 0;
@@ -1334,12 +1333,6 @@ QList<T> QMap<Key, T>::values(const Key &key) const
}
template<class Key, class T>
-int QMap<Key, T>::count(const Key &key) const
-{
- return static_cast<const QMultiMap<Key, T> *>(this)->count(key);
-}
-
-template<class Key, class T>
typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &key, const T &value)
{
return static_cast<QMultiMap<Key, T> *>(this)->insert(key, value);
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index d447faaceb..d559913161 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -870,13 +870,6 @@ void QBmpHandler::setOption(ImageOption option, const QVariant &value)
Q_UNUSED(value);
}
-#if QT_DEPRECATED_SINCE(5, 13)
-QByteArray QBmpHandler::name() const
-{
- return formatName();
-}
-#endif
-
QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_BMP
diff --git a/src/gui/image/qbmphandler_p.h b/src/gui/image/qbmphandler_p.h
index 33b5b9c501..fd044fc442 100644
--- a/src/gui/image/qbmphandler_p.h
+++ b/src/gui/image/qbmphandler_p.h
@@ -113,9 +113,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
-#if QT_DEPRECATED_SINCE(5, 13)
- QByteArray name() const override;
-#endif
static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override;
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index e6a3604ad4..5738148718 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -1296,13 +1296,6 @@ void QPngHandler::setOption(ImageOption option, const QVariant &value)
d->scaledSize = value.toSize();
}
-#if QT_DEPRECATED_SINCE(5, 13)
-QByteArray QPngHandler::name() const
-{
- return "png";
-}
-#endif
-
QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_PNG
diff --git a/src/gui/image/qpnghandler_p.h b/src/gui/image/qpnghandler_p.h
index 5d4da97395..9e12d2d081 100644
--- a/src/gui/image/qpnghandler_p.h
+++ b/src/gui/image/qpnghandler_p.h
@@ -69,10 +69,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
-#if QT_DEPRECATED_SINCE(5, 13)
- QByteArray name() const override;
-#endif
-
QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const override;
diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp
index 195e58d283..16136e6be3 100644
--- a/src/gui/image/qppmhandler.cpp
+++ b/src/gui/image/qppmhandler.cpp
@@ -576,13 +576,6 @@ void QPpmHandler::setOption(ImageOption option, const QVariant &value)
subType = value.toByteArray().toLower();
}
-#if QT_DEPRECATED_SINCE(5, 13)
-QByteArray QPpmHandler::name() const
-{
- return subType.isEmpty() ? QByteArray("ppm") : subType;
-}
-#endif
-
QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_PPM
diff --git a/src/gui/image/qppmhandler_p.h b/src/gui/image/qppmhandler_p.h
index 2f3811b759..f2faf93984 100644
--- a/src/gui/image/qppmhandler_p.h
+++ b/src/gui/image/qppmhandler_p.h
@@ -67,10 +67,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
-#if QT_DEPRECATED_SINCE(5, 13)
- QByteArray name() const override;
-#endif
-
static bool canRead(QIODevice *device, QByteArray *subType = nullptr);
QVariant option(ImageOption option) const override;
diff --git a/src/gui/image/qxbmhandler.cpp b/src/gui/image/qxbmhandler.cpp
index 3cd15b3e4d..f06561690c 100644
--- a/src/gui/image/qxbmhandler.cpp
+++ b/src/gui/image/qxbmhandler.cpp
@@ -357,13 +357,6 @@ void QXbmHandler::setOption(ImageOption option, const QVariant &value)
fileName = value.toString();
}
-#if QT_DEPRECATED_SINCE(5, 13)
-QByteArray QXbmHandler::name() const
-{
- return "xbm";
-}
-#endif
-
QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_XBM
diff --git a/src/gui/image/qxbmhandler_p.h b/src/gui/image/qxbmhandler_p.h
index ae590a1944..db5f352d46 100644
--- a/src/gui/image/qxbmhandler_p.h
+++ b/src/gui/image/qxbmhandler_p.h
@@ -66,10 +66,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
-#if QT_DEPRECATED_SINCE(5, 13)
- QByteArray name() const override;
-#endif
-
static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override;
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index f9424b62bb..07fec929bf 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -1280,13 +1280,6 @@ void QXpmHandler::setOption(ImageOption option, const QVariant &value)
fileName = value.toString();
}
-#if QT_DEPRECATED_SINCE(5, 13)
-QByteArray QXpmHandler::name() const
-{
- return "xpm";
-}
-#endif
-
QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_XPM
diff --git a/src/gui/image/qxpmhandler_p.h b/src/gui/image/qxpmhandler_p.h
index a4dd88cd17..646e8df69e 100644
--- a/src/gui/image/qxpmhandler_p.h
+++ b/src/gui/image/qxpmhandler_p.h
@@ -68,10 +68,6 @@ public:
static bool canRead(QIODevice *device);
-#if QT_DEPRECATED_SINCE(5, 13)
- QByteArray name() const override;
-#endif
-
QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const override;
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index c099ec9692..702c055fbb 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1731,7 +1731,7 @@ void QWindow::setGeometry(const QRect &rect)
if (newScreen && isTopLevel())
nativeRect = QHighDpi::toNativePixels(rect, newScreen);
else
- nativeRect = QHighDpi::toNativePixels(rect, this);
+ nativeRect = QHighDpi::toNativeLocalPosition(rect, newScreen);
d->platformWindow->setGeometry(nativeRect);
} else {
d->geometry = rect;
@@ -1782,8 +1782,12 @@ QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry) const
QRect QWindow::geometry() const
{
Q_D(const QWindow);
- if (d->platformWindow)
- return QHighDpi::fromNativePixels(d->platformWindow->geometry(), this);
+ if (d->platformWindow) {
+ const auto nativeGeometry = d->platformWindow->geometry();
+ return isTopLevel()
+ ? QHighDpi::fromNativePixels(nativeGeometry, this)
+ : QHighDpi::fromNativeLocalPosition(nativeGeometry, this);
+ }
return d->geometry;
}
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 2de0131640..6ecd908296 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -298,14 +298,21 @@ QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow
, window(window)
, newGeometry(newGeometry)
{
- if (const QPlatformWindow *pw = window->handle())
- requestedGeometry = QHighDpi::fromNativePixels(pw->QPlatformWindow::geometry(), window);
+ if (const QPlatformWindow *pw = window->handle()) {
+ const auto nativeGeometry = pw->QPlatformWindow::geometry();
+ requestedGeometry = window->isTopLevel()
+ ? QHighDpi::fromNativePixels(nativeGeometry, window)
+ : QHighDpi::fromNativeLocalPosition(nativeGeometry, window);
+ }
}
QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect)
{
Q_ASSERT(window);
- QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, QHighDpi::fromNativePixels(newRect, window));
+ const auto newRectDi = window->isTopLevel()
+ ? QHighDpi::fromNativePixels(newRect, window)
+ : QHighDpi::fromNativeLocalPosition(newRect, window);
+ auto e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, newRectDi);
if (window->handle()) {
// Persist the new geometry so that QWindow::geometry() can be queried in the resize event
window->handle()->QPlatformWindow::setGeometry(newRect);
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index 7a0d53e1e4..c805e23ad0 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -2048,11 +2048,9 @@ QRhiResource::Type QRhiBuffer::resourceType() const
UniformBuffer may not even be backed by a native buffer object at all if
uniform buffers are not used or supported by a given backend and graphics
API. There are also differences to how data is written to the buffer and
- the type of backing memory used, and, if host visible memory is involved,
- when memory writes become available and visible. Therefore, in general it
- is recommended to limit native buffer object access to vertex and index
- buffers with types Static or Immutable, because these operate in a
- relatively uniform manner with all backends.
+ the type of backing memory used. For buffers backed by host visible memory,
+ calling this function guarantees that pending host writes are executed for
+ all the returned native buffers.
\sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
*/
@@ -2342,6 +2340,31 @@ bool QRhiTexture::buildFrom(QRhiTexture::NativeTexture src)
}
/*!
+ With some graphics APIs, such as Vulkan, integrating custom rendering code
+ that uses the graphics API directly needs special care when it comes to
+ image layouts. This function allows communicating the expected layout the
+ image backing the QRhiTexture is in after the native rendering commands.
+
+ For example, consider rendering into a QRhiTexture's VkImage directly with
+ Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and
+ QRhiCommandBuffer::endExternal(), followed by using the image for texture
+ sampling in a QRhi-based render pass. To avoid potentially incorrect image
+ layout transitions, this function can be used to indicate what the image
+ layout will be once the commands recorded in said code block complete.
+
+ Calling this function makes sense only after
+ QRhiCommandBuffer::endExternal() and before a subsequent
+ QRhiCommandBuffer::beginPass().
+
+ This function has no effect with QRhi backends where the underlying
+ graphics API does not expose a concept of image layouts.
+ */
+void QRhiTexture::setNativeLayout(int layout)
+{
+ Q_UNUSED(layout);
+}
+
+/*!
\class QRhiSampler
\internal
\inmodule QtGui
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index 8f53808d34..17c911a5ff 100644
--- a/src/gui/rhi/qrhi_p.h
+++ b/src/gui/rhi/qrhi_p.h
@@ -791,6 +791,7 @@ public:
virtual bool build() = 0;
virtual NativeTexture nativeTexture();
virtual bool buildFrom(NativeTexture src);
+ virtual void setNativeLayout(int layout);
protected:
QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_,
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index f7c7f4a9f2..7b583e6fd2 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -580,6 +580,11 @@ void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
}
}
+static const int RBM_SUPPORTED_STAGES = 3;
+static const int RBM_VERTEX = 0;
+static const int RBM_FRAGMENT = 1;
+static const int RBM_COMPUTE = 2;
+
void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
int dynamicOffsetCount,
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
@@ -608,7 +613,7 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
{
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.ubuf.buf);
if (bufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(bufD);
+ executeBufferHostWrites(bufD);
if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
srbUpdate = true;
@@ -667,8 +672,17 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
}
}
- if (srbUpdate)
- updateShaderResourceBindings(srbD);
+ if (srbUpdate) {
+ const QShader::NativeResourceBindingMap *resBindMaps[RBM_SUPPORTED_STAGES];
+ memset(resBindMaps, 0, sizeof(resBindMaps));
+ if (gfxPsD) {
+ resBindMaps[RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
+ resBindMaps[RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
+ } else {
+ resBindMaps[RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
+ }
+ updateShaderResourceBindings(srbD, resBindMaps);
+ }
const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
@@ -725,7 +739,7 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb,
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, bindings[i].first);
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
if (bufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(bufD);
+ executeBufferHostWrites(bufD);
if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
|| cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
@@ -757,7 +771,7 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb,
QD3D11Buffer *ibufD = QRHI_RES(QD3D11Buffer, indexBuf);
Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
if (ibufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(ibufD);
+ executeBufferHostWrites(ibufD);
const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
: DXGI_FORMAT_R32_UINT;
@@ -1774,7 +1788,26 @@ void QRhiD3D11::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
cbD->commands.append(cmd);
}
-void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
+static inline QPair<int, int> mapBinding(int binding,
+ int stageIndex,
+ const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
+{
+ const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
+ if (!map || map->isEmpty())
+ return { binding, binding }; // old QShader versions do not have this map, assume 1:1 mapping then
+
+ auto it = map->constFind(binding);
+ if (it != map->cend())
+ return *it;
+
+ // Hitting this path is normal too. It is not given that the resource is
+ // present in the shaders for all the stages specified by the visibility
+ // mask in the QRhiShaderResourceBinding.
+ return { -1, -1 };
+}
+
+void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
+ const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
{
srbD->vsubufs.clear();
srbD->vsubufoffsets.clear();
@@ -1799,6 +1832,31 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
srbD->csUAVs.clear();
+ struct Stage {
+ struct Buffer {
+ int breg; // b0, b1, ...
+ ID3D11Buffer *buffer;
+ uint offsetInConstants;
+ uint sizeInConstants;
+ };
+ struct Texture {
+ int treg; // t0, t1, ...
+ ID3D11ShaderResourceView *srv;
+ };
+ struct Sampler {
+ int sreg; // s0, s1, ...
+ ID3D11SamplerState *sampler;
+ };
+ struct Uav {
+ int ureg;
+ ID3D11UnorderedAccessView *uav;
+ };
+ QVarLengthArray<Buffer, 8> buffers;
+ QVarLengthArray<Texture, 8> textures;
+ QVarLengthArray<Sampler, 8> samplers;
+ QVarLengthArray<Uav, 8> uavs;
+ } res[RBM_SUPPORTED_STAGES];
+
for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding::Data *b = srbD->sortedBindings.at(i).data();
QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
@@ -1818,26 +1876,24 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
// (ByteWidth) is always a multiple of 256.
const uint sizeInConstants = uint(aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256) / 16);
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
- srbD->vsubufs.feed(b->binding, bufD->buffer);
- srbD->vsubufoffsets.feed(b->binding, offsetInConstants);
- srbD->vsubufsizes.feed(b->binding, sizeInConstants);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_VERTEX].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
- srbD->fsubufs.feed(b->binding, bufD->buffer);
- srbD->fsubufoffsets.feed(b->binding, offsetInConstants);
- srbD->fsubufsizes.feed(b->binding, sizeInConstants);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_FRAGMENT].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- srbD->csubufs.feed(b->binding, bufD->buffer);
- srbD->csubufoffsets.feed(b->binding, offsetInConstants);
- srbD->csubufsizes.feed(b->binding, sizeInConstants);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_COMPUTE].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
}
}
break;
case QRhiShaderResourceBinding::SampledTexture:
{
- // A sampler with binding N is mapped to a HLSL sampler and texture
- // with registers sN and tN by SPIRV-Cross.
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler);
bd.stex.texId = texD->m_id;
@@ -1845,16 +1901,25 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.stex.samplerId = samplerD->m_id;
bd.stex.samplerGeneration = samplerD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
- srbD->vssamplers.feed(b->binding, samplerD->samplerState);
- srbD->vsshaderresources.feed(b->binding, texD->srv);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
+ res[RBM_VERTEX].textures.append({ nativeBinding.first, texD->srv });
+ res[RBM_VERTEX].samplers.append({ nativeBinding.second, samplerD->samplerState });
+ }
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
- srbD->fssamplers.feed(b->binding, samplerD->samplerState);
- srbD->fsshaderresources.feed(b->binding, texD->srv);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
+ res[RBM_FRAGMENT].textures.append({ nativeBinding.first, texD->srv });
+ res[RBM_FRAGMENT].samplers.append({ nativeBinding.second, samplerD->samplerState });
+ }
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- srbD->cssamplers.feed(b->binding, samplerD->samplerState);
- srbD->csshaderresources.feed(b->binding, texD->srv);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
+ res[RBM_COMPUTE].textures.append({ nativeBinding.first, texD->srv });
+ res[RBM_COMPUTE].samplers.append({ nativeBinding.second, samplerD->samplerState });
+ }
}
}
break;
@@ -1866,9 +1931,12 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.simage.id = texD->m_id;
bd.simage.generation = texD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
- if (uav)
- srbD->csUAVs.feed(b->binding, uav);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0) {
+ ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
+ if (uav)
+ res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
+ }
} else {
qWarning("Unordered access only supported at compute stage");
}
@@ -1882,9 +1950,12 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.sbuf.id = bufD->m_id;
bd.sbuf.generation = bufD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView();
- if (uav)
- srbD->csUAVs.feed(b->binding, uav);
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0) {
+ ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView();
+ if (uav)
+ res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
+ }
} else {
qWarning("Unordered access only supported at compute stage");
}
@@ -1896,31 +1967,79 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
}
}
+ // QRhiBatchedBindings works with the native bindings and expects
+ // sorted input. The pre-sorted QRhiShaderResourceBinding list (based
+ // on the QRhi (SPIR-V) binding) is not helpful in this regard, so we
+ // have to sort here every time.
+ for (int stage = 0; stage < RBM_SUPPORTED_STAGES; ++stage) {
+ std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](const Stage::Buffer &a, const Stage::Buffer &b) {
+ return a.breg < b.breg;
+ });
+ std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](const Stage::Texture &a, const Stage::Texture &b) {
+ return a.treg < b.treg;
+ });
+ std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](const Stage::Sampler &a, const Stage::Sampler &b) {
+ return a.sreg < b.sreg;
+ });
+ std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](const Stage::Uav &a, const Stage::Uav &b) {
+ return a.ureg < b.ureg;
+ });
+ }
+
+ for (const Stage::Buffer &buf : qAsConst(res[RBM_VERTEX].buffers)) {
+ srbD->vsubufs.feed(buf.breg, buf.buffer);
+ srbD->vsubufoffsets.feed(buf.breg, buf.offsetInConstants);
+ srbD->vsubufsizes.feed(buf.breg, buf.sizeInConstants);
+ }
srbD->vsubufs.finish();
srbD->vsubufoffsets.finish();
srbD->vsubufsizes.finish();
+ for (const Stage::Buffer &buf : qAsConst(res[RBM_FRAGMENT].buffers)) {
+ srbD->fsubufs.feed(buf.breg, buf.buffer);
+ srbD->fsubufoffsets.feed(buf.breg, buf.offsetInConstants);
+ srbD->fsubufsizes.feed(buf.breg, buf.sizeInConstants);
+ }
srbD->fsubufs.finish();
srbD->fsubufoffsets.finish();
srbD->fsubufsizes.finish();
+ for (const Stage::Buffer &buf : qAsConst(res[RBM_COMPUTE].buffers)) {
+ srbD->csubufs.feed(buf.breg, buf.buffer);
+ srbD->csubufoffsets.feed(buf.breg, buf.offsetInConstants);
+ srbD->csubufsizes.feed(buf.breg, buf.sizeInConstants);
+ }
srbD->csubufs.finish();
srbD->csubufoffsets.finish();
srbD->csubufsizes.finish();
+ for (const Stage::Texture &t : qAsConst(res[RBM_VERTEX].textures))
+ srbD->vsshaderresources.feed(t.treg, t.srv);
+ for (const Stage::Sampler &s : qAsConst(res[RBM_VERTEX].samplers))
+ srbD->vssamplers.feed(s.sreg, s.sampler);
srbD->vssamplers.finish();
srbD->vsshaderresources.finish();
+ for (const Stage::Texture &t : qAsConst(res[RBM_FRAGMENT].textures))
+ srbD->fsshaderresources.feed(t.treg, t.srv);
+ for (const Stage::Sampler &s : qAsConst(res[RBM_FRAGMENT].samplers))
+ srbD->fssamplers.feed(s.sreg, s.sampler);
srbD->fssamplers.finish();
srbD->fsshaderresources.finish();
+ for (const Stage::Texture &t : qAsConst(res[RBM_COMPUTE].textures))
+ srbD->csshaderresources.feed(t.treg, t.srv);
+ for (const Stage::Sampler &s : qAsConst(res[RBM_COMPUTE].samplers))
+ srbD->cssamplers.feed(s.sreg, s.sampler);
srbD->cssamplers.finish();
srbD->csshaderresources.finish();
+ for (const Stage::Uav &u : qAsConst(res[RBM_COMPUTE].uavs))
+ srbD->csUAVs.feed(u.ureg, u.uav);
srbD->csUAVs.finish();
}
-void QRhiD3D11::executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD)
+void QRhiD3D11::executeBufferHostWrites(QD3D11Buffer *bufD)
{
if (!bufD->hasPendingDynamicUpdates)
return;
@@ -2205,8 +2324,8 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
case QD3D11CommandBuffer::Command::BindGraphicsPipeline:
{
QD3D11GraphicsPipeline *psD = cmd.args.bindGraphicsPipeline.ps;
- context->VSSetShader(psD->vs, nullptr, 0);
- context->PSSetShader(psD->fs, nullptr, 0);
+ context->VSSetShader(psD->vs.shader, nullptr, 0);
+ context->PSSetShader(psD->fs.shader, nullptr, 0);
context->IASetPrimitiveTopology(psD->d3dTopology);
context->IASetInputLayout(psD->inputLayout);
context->OMSetDepthStencilState(psD->dsState, stencilRef);
@@ -2281,7 +2400,7 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
annotations->SetMarker(reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
break;
case QD3D11CommandBuffer::Command::BindComputePipeline:
- context->CSSetShader(cmd.args.bindComputePipeline.ps->cs, nullptr, 0);
+ context->CSSetShader(cmd.args.bindComputePipeline.ps->cs.shader, nullptr, 0);
break;
case QD3D11CommandBuffer::Command::Dispatch:
context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
@@ -2388,6 +2507,10 @@ bool QD3D11Buffer::build()
QRhiBuffer::NativeBuffer QD3D11Buffer::nativeBuffer()
{
+ if (m_type == Dynamic) {
+ QRHI_RES_RHI(QRhiD3D11);
+ rhiD->executeBufferHostWrites(this);
+ }
return { { &buffer }, 1 };
}
@@ -3133,6 +3256,7 @@ QD3D11ShaderResourceBindings::~QD3D11ShaderResourceBindings()
void QD3D11ShaderResourceBindings::release()
{
sortedBindings.clear();
+ boundResourceData.clear();
}
bool QD3D11ShaderResourceBindings::build()
@@ -3149,8 +3273,8 @@ bool QD3D11ShaderResourceBindings::build()
boundResourceData.resize(sortedBindings.count());
- QRHI_RES_RHI(QRhiD3D11);
- rhiD->updateShaderResourceBindings(this);
+ for (BoundResourceData &bd : boundResourceData)
+ memset(&bd, 0, sizeof(BoundResourceData));
generation += 1;
return true;
@@ -3191,15 +3315,17 @@ void QD3D11GraphicsPipeline::release()
rastState = nullptr;
}
- if (vs) {
- vs->Release();
- vs = nullptr;
+ if (vs.shader) {
+ vs.shader->Release();
+ vs.shader = nullptr;
}
+ vs.nativeResourceBindingMap.clear();
- if (fs) {
- fs->Release();
- fs = nullptr;
+ if (fs.shader) {
+ fs.shader->Release();
+ fs.shader = nullptr;
}
+ fs.nativeResourceBindingMap.clear();
rhiD->unregisterResource(this);
}
@@ -3401,13 +3527,14 @@ static pD3DCompile resolveD3DCompile()
return nullptr;
}
-static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error)
+static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error, QShaderKey *usedShaderKey)
{
QShaderCode dxbc = shader.shader({ QShader::DxbcShader, 50, shaderVariant });
if (!dxbc.shader().isEmpty())
return dxbc.shader();
- QShaderCode hlslSource = shader.shader({ QShader::HlslShader, 50, shaderVariant });
+ const QShaderKey key = { QShader::HlslShader, 50, shaderVariant };
+ QShaderCode hlslSource = shader.shader(key);
if (hlslSource.shader().isEmpty()) {
qWarning() << "No HLSL (shader model 5.0) code found in baked shader" << shader;
return QByteArray();
@@ -3459,6 +3586,9 @@ static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Varian
return QByteArray();
}
+ if (usedShaderKey)
+ *usedShaderKey = key;
+
QByteArray result;
result.resize(int(bytecode->GetBufferSize()));
memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
@@ -3550,20 +3680,23 @@ bool QD3D11GraphicsPipeline::build()
if (cacheIt != rhiD->m_shaderCache.constEnd()) {
switch (shaderStage.type()) {
case QRhiShaderStage::Vertex:
- vs = static_cast<ID3D11VertexShader *>(cacheIt->s);
- vs->AddRef();
+ vs.shader = static_cast<ID3D11VertexShader *>(cacheIt->s);
+ vs.shader->AddRef();
vsByteCode = cacheIt->bytecode;
+ vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
break;
case QRhiShaderStage::Fragment:
- fs = static_cast<ID3D11PixelShader *>(cacheIt->s);
- fs->AddRef();
+ fs.shader = static_cast<ID3D11PixelShader *>(cacheIt->s);
+ fs.shader->AddRef();
+ fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
break;
default:
break;
}
} else {
QString error;
- const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error);
+ QShaderKey shaderKey;
+ const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error, &shaderKey);
if (bytecode.isEmpty()) {
qWarning("HLSL shader compilation failed: %s", qPrintable(error));
return false;
@@ -3576,23 +3709,27 @@ bool QD3D11GraphicsPipeline::build()
switch (shaderStage.type()) {
case QRhiShaderStage::Vertex:
- hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &vs);
+ hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &vs.shader);
if (FAILED(hr)) {
qWarning("Failed to create vertex shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
vsByteCode = bytecode;
- rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs, bytecode));
- vs->AddRef();
+ if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey))
+ vs.nativeResourceBindingMap = *map;
+ rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
+ vs.shader->AddRef();
break;
case QRhiShaderStage::Fragment:
- hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs);
+ hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs.shader);
if (FAILED(hr)) {
qWarning("Failed to create pixel shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
- rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs, bytecode));
- fs->AddRef();
+ if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey))
+ fs.nativeResourceBindingMap = *map;
+ rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
+ fs.shader->AddRef();
break;
default:
break;
@@ -3651,46 +3788,52 @@ void QD3D11ComputePipeline::release()
{
QRHI_RES_RHI(QRhiD3D11);
- if (!cs)
+ if (!cs.shader)
return;
- cs->Release();
- cs = nullptr;
+ cs.shader->Release();
+ cs.shader = nullptr;
+ cs.nativeResourceBindingMap.clear();
rhiD->unregisterResource(this);
}
bool QD3D11ComputePipeline::build()
{
- if (cs)
+ if (cs.shader)
release();
QRHI_RES_RHI(QRhiD3D11);
auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
if (cacheIt != rhiD->m_shaderCache.constEnd()) {
- cs = static_cast<ID3D11ComputeShader *>(cacheIt->s);
+ cs.shader = static_cast<ID3D11ComputeShader *>(cacheIt->s);
+ cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
} else {
QString error;
- const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error);
+ QShaderKey shaderKey;
+ const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error, &shaderKey);
if (bytecode.isEmpty()) {
qWarning("HLSL compute shader compilation failed: %s", qPrintable(error));
return false;
}
- HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &cs);
+ HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &cs.shader);
if (FAILED(hr)) {
qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
+ if (const QShader::NativeResourceBindingMap *map = m_shaderStage.shader().nativeResourceBindingMap(shaderKey))
+ cs.nativeResourceBindingMap = *map;
+
if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
rhiD->clearShaderCache();
- rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs, bytecode));
+ rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
}
- cs->AddRef();
+ cs.shader->AddRef();
generation += 1;
rhiD->registerResource(this);
diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h
index 04751397f7..f749b612b5 100644
--- a/src/gui/rhi/qrhid3d11_p_p.h
+++ b/src/gui/rhi/qrhid3d11_p_p.h
@@ -270,8 +270,14 @@ struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline
ID3D11DepthStencilState *dsState = nullptr;
ID3D11BlendState *blendState = nullptr;
- ID3D11VertexShader *vs = nullptr;
- ID3D11PixelShader *fs = nullptr;
+ struct {
+ ID3D11VertexShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } vs;
+ struct {
+ ID3D11PixelShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } fs;
ID3D11InputLayout *inputLayout = nullptr;
D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
ID3D11RasterizerState *rastState = nullptr;
@@ -286,7 +292,10 @@ struct QD3D11ComputePipeline : public QRhiComputePipeline
void release() override;
bool build() override;
- ID3D11ComputeShader *cs = nullptr;
+ struct {
+ ID3D11ComputeShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } cs;
uint generation = 0;
friend class QRhiD3D11;
};
@@ -642,8 +651,9 @@ public:
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
- void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD);
- void executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD);
+ void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
+ const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]);
+ void executeBufferHostWrites(QD3D11Buffer *bufD);
void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
const uint *dynOfsPairs, int dynOfsPairCount,
bool offsetOnlyChange);
@@ -701,9 +711,11 @@ public:
struct Shader {
Shader() = default;
- Shader(IUnknown *s, const QByteArray &bytecode) : s(s), bytecode(bytecode) { }
+ Shader(IUnknown *s, const QByteArray &bytecode, const QShader::NativeResourceBindingMap &rbm)
+ : s(s), bytecode(bytecode), nativeResourceBindingMap(rbm) { }
IUnknown *s;
QByteArray bytecode;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
};
QHash<QRhiShaderStage, Shader> m_shaderCache;
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 48a562ef1d..314c58b0b7 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -1827,16 +1827,15 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
}
// this handles all types of buffers, not just Dynamic
-void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
+void QRhiMetal::executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot)
{
- const int idx = bufD->d->slotted ? currentFrameSlot : 0;
- if (bufD->d->pendingUpdates[idx].isEmpty())
+ if (bufD->d->pendingUpdates[slot].isEmpty())
return;
- void *p = [bufD->d->buf[idx] contents];
+ void *p = [bufD->d->buf[slot] contents];
int changeBegin = -1;
int changeEnd = -1;
- for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->d->pendingUpdates[idx])) {
+ for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->d->pendingUpdates[slot])) {
Q_ASSERT(bufD == QRHI_RES(QMetalBuffer, u.buf));
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
if (changeBegin == -1 || u.offset < changeBegin)
@@ -1846,10 +1845,15 @@ void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
}
#ifdef Q_OS_MACOS
if (changeBegin >= 0 && bufD->d->managed)
- [bufD->d->buf[idx] didModifyRange: NSMakeRange(NSUInteger(changeBegin), NSUInteger(changeEnd - changeBegin))];
+ [bufD->d->buf[slot] didModifyRange: NSMakeRange(NSUInteger(changeBegin), NSUInteger(changeEnd - changeBegin))];
#endif
- bufD->d->pendingUpdates[idx].clear();
+ bufD->d->pendingUpdates[slot].clear();
+}
+
+void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
+{
+ executeBufferHostWritesForSlot(bufD, bufD->d->slotted ? currentFrameSlot : 0);
}
void QRhiMetal::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
@@ -2205,8 +2209,11 @@ QRhiBuffer::NativeBuffer QMetalBuffer::nativeBuffer()
if (d->slotted) {
NativeBuffer b;
Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QMTL_FRAMES_IN_FLIGHT));
- for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
+ for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
+ QRHI_RES_RHI(QRhiMetal);
+ rhiD->executeBufferHostWritesForSlot(this, i);
b.objects[i] = &d->buf[i];
+ }
b.slotCount = QMTL_FRAMES_IN_FLIGHT;
return b;
}
diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h
index 212b731b71..a5af5611a6 100644
--- a/src/gui/rhi/qrhimetal_p_p.h
+++ b/src/gui/rhi/qrhimetal_p_p.h
@@ -437,6 +437,7 @@ public:
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc,
qsizetype *curOfs);
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
+ void executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot);
void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);
static const int SUPPORTED_STAGES = 3;
void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD,
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index d378e2a4ad..a92c3e14e9 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -149,6 +149,10 @@ QT_BEGIN_NAMESPACE
for other windows as well, as long as they all have their
QWindow::surfaceType() set to QSurface::VulkanSurface.
+ To request additional extensions to be enabled on the Vulkan device, list them
+ in deviceExtensions. This can be relevant when integrating with native Vulkan
+ rendering code.
+
\section2 Working with existing Vulkan devices
When interoperating with another graphics engine, it may be necessary to
@@ -299,6 +303,7 @@ QRhiVulkan::QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *im
{
inst = params->inst;
maybeWindow = params->window; // may be null
+ requestedDeviceExtensions = params->deviceExtensions;
importedDevice = importDevice != nullptr;
if (importedDevice) {
@@ -463,40 +468,59 @@ bool QRhiVulkan::create(QRhi::Flags flags)
if (inst->layers().contains("VK_LAYER_LUNARG_standard_validation"))
devLayers.append("VK_LAYER_LUNARG_standard_validation");
+ QVulkanInfoVector<QVulkanExtension> devExts;
uint32_t devExtCount = 0;
f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, nullptr);
- QVector<VkExtensionProperties> devExts(devExtCount);
- f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, devExts.data());
+ if (devExtCount) {
+ QVector<VkExtensionProperties> extProps(devExtCount);
+ f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, extProps.data());
+ for (const VkExtensionProperties &p : qAsConst(extProps))
+ devExts.append({ p.extensionName, p.specVersion });
+ }
qCDebug(QRHI_LOG_INFO, "%d device extensions available", devExts.count());
QVector<const char *> requestedDevExts;
requestedDevExts.append("VK_KHR_swapchain");
debugMarkersAvailable = false;
+ if (devExts.contains(VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
+ requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
+ debugMarkersAvailable = true;
+ }
+
vertexAttribDivisorAvailable = false;
- for (const VkExtensionProperties &ext : devExts) {
- if (!strcmp(ext.extensionName, VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
- requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
- debugMarkersAvailable = true;
- } else if (!strcmp(ext.extensionName, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
- if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) {
- requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
- vertexAttribDivisorAvailable = true;
- }
+ if (devExts.contains(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
+ if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) {
+ requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
+ vertexAttribDivisorAvailable = true;
}
}
- QByteArrayList envExtList;
- if (qEnvironmentVariableIsSet("QT_VULKAN_DEVICE_EXTENSIONS")) {
- envExtList = qgetenv("QT_VULKAN_DEVICE_EXTENSIONS").split(';');
- for (auto ext : requestedDevExts)
- envExtList.removeAll(ext);
- for (const QByteArray &ext : envExtList) {
- if (!ext.isEmpty())
+ for (const QByteArray &ext : requestedDeviceExtensions) {
+ if (!ext.isEmpty()) {
+ if (devExts.contains(ext))
requestedDevExts.append(ext.constData());
+ else
+ qWarning("Device extension %s is not supported", ext.constData());
}
}
+ QByteArrayList envExtList = qgetenv("QT_VULKAN_DEVICE_EXTENSIONS").split(';');
+ for (const QByteArray &ext : envExtList) {
+ if (!ext.isEmpty() && !requestedDevExts.contains(ext)) {
+ if (devExts.contains(ext))
+ requestedDevExts.append(ext.constData());
+ else
+ qWarning("Device extension %s is not supported", ext.constData());
+ }
+ }
+
+ if (QRHI_LOG_INFO().isEnabled(QtDebugMsg)) {
+ qCDebug(QRHI_LOG_INFO, "Enabling device extensions:");
+ for (const char *ext : requestedDevExts)
+ qCDebug(QRHI_LOG_INFO, " %s", ext);
+ }
+
VkDeviceCreateInfo devInfo;
memset(&devInfo, 0, sizeof(devInfo));
devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
@@ -2903,7 +2927,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf);
if (bufD->m_type == QRhiBuffer::Dynamic) {
- executeBufferHostWritesForCurrentFrame(bufD);
+ executeBufferHostWritesForSlot(bufD, currentFrameSlot);
void *p = nullptr;
VmaAllocation a = toVmaAllocation(bufD->allocations[currentFrameSlot]);
VkResult err = vmaMapMemory(toVmaAllocator(allocator), a, &p);
@@ -3300,14 +3324,14 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
ud->free();
}
-void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
+void QRhiVulkan::executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot)
{
- if (bufD->pendingDynamicUpdates[currentFrameSlot].isEmpty())
+ if (bufD->pendingDynamicUpdates[slot].isEmpty())
return;
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
void *p = nullptr;
- VmaAllocation a = toVmaAllocation(bufD->allocations[currentFrameSlot]);
+ VmaAllocation a = toVmaAllocation(bufD->allocations[slot]);
// The vmaMap/Unmap are basically a no-op when persistently mapped since it
// refcounts; this is great because we don't need to care if the allocation
// was created as persistently mapped or not.
@@ -3318,7 +3342,7 @@ void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
}
int changeBegin = -1;
int changeEnd = -1;
- for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->pendingDynamicUpdates[currentFrameSlot])) {
+ for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->pendingDynamicUpdates[slot])) {
Q_ASSERT(bufD == QRHI_RES(QVkBuffer, u.buf));
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
if (changeBegin == -1 || u.offset < changeBegin)
@@ -3330,7 +3354,7 @@ void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
if (changeBegin >= 0)
vmaFlushAllocation(toVmaAllocator(allocator), a, VkDeviceSize(changeBegin), VkDeviceSize(changeEnd - changeBegin));
- bufD->pendingDynamicUpdates[currentFrameSlot].clear();
+ bufD->pendingDynamicUpdates[slot].clear();
}
static void qrhivk_releaseBuffer(const QRhiVulkan::DeferredReleaseEntry &e, void *allocator)
@@ -4166,7 +4190,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
if (bufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(bufD);
+ executeBufferHostWritesForSlot(bufD, currentFrameSlot);
bufD->lastActiveFrameSlot = currentFrameSlot;
trackedRegisterBuffer(&passResTracker, bufD, bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0,
@@ -4240,7 +4264,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer));
if (bufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(bufD);
+ executeBufferHostWritesForSlot(bufD, currentFrameSlot);
bufD->lastActiveFrameSlot = currentFrameSlot;
QRhiPassResourceTracker::BufferAccess access;
@@ -4349,7 +4373,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
bufD->lastActiveFrameSlot = currentFrameSlot;
if (bufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(bufD);
+ executeBufferHostWritesForSlot(bufD, currentFrameSlot);
const VkBuffer vkvertexbuf = bufD->buffers[bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0];
if (cbD->currentVertexBuffers[inputSlot] != vkvertexbuf
@@ -4395,7 +4419,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
ibufD->lastActiveFrameSlot = currentFrameSlot;
if (ibufD->m_type == QRhiBuffer::Dynamic)
- executeBufferHostWritesForCurrentFrame(ibufD);
+ executeBufferHostWritesForSlot(ibufD, currentFrameSlot);
const int slot = ibufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0;
const VkBuffer vkindexbuf = ibufD->buffers[slot];
@@ -5188,10 +5212,13 @@ bool QVkBuffer::build()
QRhiBuffer::NativeBuffer QVkBuffer::nativeBuffer()
{
if (m_type == Dynamic) {
+ QRHI_RES_RHI(QRhiVulkan);
NativeBuffer b;
Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QVK_FRAMES_IN_FLIGHT));
- for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
+ rhiD->executeBufferHostWritesForSlot(this, i);
b.objects[i] = &buffers[i];
+ }
b.slotCount = QVK_FRAMES_IN_FLIGHT;
return b;
}
@@ -5536,6 +5563,11 @@ QRhiTexture::NativeTexture QVkTexture::nativeTexture()
return {&image, usageState.layout};
}
+void QVkTexture::setNativeLayout(int layout)
+{
+ usageState.layout = VkImageLayout(layout);
+}
+
VkImageView QVkTexture::imageViewForLevel(int level)
{
Q_ASSERT(level >= 0 && level < int(mipLevelCount));
diff --git a/src/gui/rhi/qrhivulkan_p.h b/src/gui/rhi/qrhivulkan_p.h
index d495919671..f8870dcd77 100644
--- a/src/gui/rhi/qrhivulkan_p.h
+++ b/src/gui/rhi/qrhivulkan_p.h
@@ -57,6 +57,7 @@ struct Q_GUI_EXPORT QRhiVulkanInitParams : public QRhiInitParams
{
QVulkanInstance *inst = nullptr;
QWindow *window = nullptr;
+ QByteArrayList deviceExtensions;
};
struct Q_GUI_EXPORT QRhiVulkanNativeHandles : public QRhiNativeHandles
diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h
index 6322882569..fd65417e75 100644
--- a/src/gui/rhi/qrhivulkan_p_p.h
+++ b/src/gui/rhi/qrhivulkan_p_p.h
@@ -123,6 +123,7 @@ struct QVkTexture : public QRhiTexture
bool build() override;
bool buildFrom(NativeTexture src) override;
NativeTexture nativeTexture() override;
+ void setNativeLayout(int layout) override;
bool prepareBuild(QSize *adjustedSize = nullptr);
bool finishBuild();
@@ -778,7 +779,7 @@ public:
size_t *curOfs, void *mp,
BufferImageCopyList *copyInfos);
void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates);
- void executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD);
+ void executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot);
void enqueueTransitionPassResources(QVkCommandBuffer *cbD);
void recordPrimaryCommandBuffer(QVkCommandBuffer *cbD);
void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
@@ -810,6 +811,7 @@ public:
QVulkanInstance *inst = nullptr;
QWindow *maybeWindow = nullptr;
+ QByteArrayList requestedDeviceExtensions;
bool importedDevice = false;
VkPhysicalDevice physDev = VK_NULL_HANDLE;
VkDevice dev = VK_NULL_HANDLE;
diff --git a/src/gui/rhi/qshader.cpp b/src/gui/rhi/qshader.cpp
index 69f4a68215..945f4820c2 100644
--- a/src/gui/rhi/qshader.cpp
+++ b/src/gui/rhi/qshader.cpp
@@ -428,6 +428,7 @@ QShader QShader::fromSerialized(const QByteArray &data)
ds >> intVal;
d->qsbVersion = intVal;
if (d->qsbVersion != QShaderPrivate::QSB_VERSION
+ && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_VAR_ARRAYDIMS
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_CBOR
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_BINDINGS)
@@ -439,7 +440,7 @@ QShader QShader::fromSerialized(const QByteArray &data)
ds >> intVal;
d->stage = Stage(intVal);
if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_CBOR) {
- d->desc = QShaderDescription::deserialize(&ds);
+ d->desc = QShaderDescription::deserialize(&ds, d->qsbVersion);
} else if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON) {
QByteArray descBin;
ds >> descBin;
diff --git a/src/gui/rhi/qshader_p_p.h b/src/gui/rhi/qshader_p_p.h
index 66ef18f391..ec9d25971f 100644
--- a/src/gui/rhi/qshader_p_p.h
+++ b/src/gui/rhi/qshader_p_p.h
@@ -57,7 +57,8 @@ QT_BEGIN_NAMESPACE
struct Q_GUI_EXPORT QShaderPrivate
{
- static const int QSB_VERSION = 4;
+ static const int QSB_VERSION = 5;
+ static const int QSB_VERSION_WITHOUT_VAR_ARRAYDIMS = 4;
static const int QSB_VERSION_WITH_CBOR = 3;
static const int QSB_VERSION_WITH_BINARY_JSON = 2;
static const int QSB_VERSION_WITHOUT_BINDINGS = 1;
diff --git a/src/gui/rhi/qshaderdescription.cpp b/src/gui/rhi/qshaderdescription.cpp
index 96c8d082fc..f3ef5edd12 100644
--- a/src/gui/rhi/qshaderdescription.cpp
+++ b/src/gui/rhi/qshaderdescription.cpp
@@ -35,6 +35,7 @@
****************************************************************************/
#include "qshaderdescription_p_p.h"
+#include "qshader_p_p.h"
#include <QDebug>
#include <QDataStream>
#include <QJsonObject>
@@ -402,10 +403,10 @@ QShaderDescription QShaderDescription::fromCbor(const QByteArray &data)
return desc;
}
-QShaderDescription QShaderDescription::deserialize(QDataStream *stream)
+QShaderDescription QShaderDescription::deserialize(QDataStream *stream, int version)
{
QShaderDescription desc;
- QShaderDescriptionPrivate::get(&desc)->loadFromStream(stream);
+ QShaderDescriptionPrivate::get(&desc)->loadFromStream(stream, version);
return desc;
}
@@ -783,6 +784,8 @@ QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var)
dbg.nospace() << " imageFormat=" << imageFormatStr(var.imageFormat);
if (var.imageFlags)
dbg.nospace() << " imageFlags=" << var.imageFlags;
+ if (!var.arrayDims.isEmpty())
+ dbg.nospace() << " array=" << var.arrayDims;
dbg.nospace() << ')';
return dbg;
}
@@ -878,6 +881,12 @@ static void addDeco(QJsonObject *obj, const QShaderDescription::InOutVariable &v
(*obj)[imageFormatKey] = imageFormatStr(v.imageFormat);
if (v.imageFlags)
(*obj)[imageFlagsKey] = int(v.imageFlags);
+ if (!v.arrayDims.isEmpty()) {
+ QJsonArray dimArr;
+ for (int dim : v.arrayDims)
+ dimArr.append(dim);
+ (*obj)[arrayDimsKey] = dimArr;
+ }
}
static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v)
@@ -887,6 +896,9 @@ static void serializeDecorations(QDataStream *stream, const QShaderDescription::
(*stream) << v.descriptorSet;
(*stream) << int(v.imageFormat);
(*stream) << int(v.imageFlags);
+ (*stream) << v.arrayDims.count();
+ for (int dim : v.arrayDims)
+ (*stream) << dim;
}
static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v)
@@ -1124,10 +1136,15 @@ static QShaderDescription::InOutVariable inOutVar(const QJsonObject &obj)
var.imageFormat = mapImageFormat(obj[imageFormatKey].toString());
if (obj.contains(imageFlagsKey))
var.imageFlags = QShaderDescription::ImageFlags(obj[imageFlagsKey].toInt());
+ if (obj.contains(arrayDimsKey)) {
+ QJsonArray dimArr = obj[arrayDimsKey].toArray();
+ for (int i = 0; i < dimArr.count(); ++i)
+ var.arrayDims.append(dimArr.at(i).toInt());
+ }
return var;
}
-static void deserializeDecorations(QDataStream *stream, QShaderDescription::InOutVariable *v)
+static void deserializeDecorations(QDataStream *stream, int version, QShaderDescription::InOutVariable *v)
{
(*stream) >> v->location;
(*stream) >> v->binding;
@@ -1137,16 +1154,23 @@ static void deserializeDecorations(QDataStream *stream, QShaderDescription::InOu
v->imageFormat = QShaderDescription::ImageFormat(f);
(*stream) >> f;
v->imageFlags = QShaderDescription::ImageFlags(f);
+
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_VAR_ARRAYDIMS) {
+ (*stream) >> f;
+ v->arrayDims.resize(f);
+ for (int i = 0; i < f; ++i)
+ (*stream) >> v->arrayDims[i];
+ }
}
-static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream)
+static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream, int version)
{
QShaderDescription::InOutVariable var;
(*stream) >> var.name;
int t;
(*stream) >> t;
var.type = QShaderDescription::VariableType(t);
- deserializeDecorations(stream, &var);
+ deserializeDecorations(stream, version, &var);
return var;
}
@@ -1176,7 +1200,7 @@ static QShaderDescription::BlockVariable blockVar(const QJsonObject &obj)
return var;
}
-static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream)
+static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream, int version)
{
QShaderDescription::BlockVariable var;
(*stream) >> var.name;
@@ -1196,7 +1220,7 @@ static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *
(*stream) >> count;
var.structMembers.resize(count);
for (int i = 0; i < count; ++i)
- var.structMembers[i] = deserializeBlockMemberVar(stream);
+ var.structMembers[i] = deserializeBlockMemberVar(stream, version);
return var;
}
@@ -1304,7 +1328,7 @@ void QShaderDescriptionPrivate::loadDoc(const QJsonDocument &doc)
}
}
-void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
+void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version)
{
Q_ASSERT(ref.loadRelaxed() == 1); // must be detached
@@ -1312,12 +1336,12 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
(*stream) >> count;
inVars.resize(count);
for (int i = 0; i < count; ++i)
- inVars[i] = deserializeInOutVar(stream);
+ inVars[i] = deserializeInOutVar(stream, version);
(*stream) >> count;
outVars.resize(count);
for (int i = 0; i < count; ++i)
- outVars[i] = deserializeInOutVar(stream);
+ outVars[i] = deserializeInOutVar(stream, version);
(*stream) >> count;
uniformBlocks.resize(count);
@@ -1331,7 +1355,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
(*stream) >> memberCount;
uniformBlocks[i].members.resize(memberCount);
for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
- uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream);
+ uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
}
(*stream) >> count;
@@ -1343,7 +1367,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
(*stream) >> memberCount;
pushConstantBlocks[i].members.resize(memberCount);
for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
- pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream);
+ pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
}
(*stream) >> count;
@@ -1358,7 +1382,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
(*stream) >> memberCount;
storageBlocks[i].members.resize(memberCount);
for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
- storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream);
+ storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
}
(*stream) >> count;
@@ -1368,7 +1392,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
int t;
(*stream) >> t;
combinedImageSamplers[i].type = QShaderDescription::VariableType(t);
- deserializeDecorations(stream, &combinedImageSamplers[i]);
+ deserializeDecorations(stream, version, &combinedImageSamplers[i]);
}
(*stream) >> count;
@@ -1378,7 +1402,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
int t;
(*stream) >> t;
storageImages[i].type = QShaderDescription::VariableType(t);
- deserializeDecorations(stream, &storageImages[i]);
+ deserializeDecorations(stream, version, &storageImages[i]);
}
for (size_t i = 0; i < 3; ++i)
@@ -1420,7 +1444,8 @@ bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescr
&& lhs.binding == rhs.binding
&& lhs.descriptorSet == rhs.descriptorSet
&& lhs.imageFormat == rhs.imageFormat
- && lhs.imageFlags == rhs.imageFlags;
+ && lhs.imageFlags == rhs.imageFlags
+ && lhs.arrayDims == rhs.arrayDims;
}
/*!
diff --git a/src/gui/rhi/qshaderdescription_p.h b/src/gui/rhi/qshaderdescription_p.h
index 108fc32a56..e5650ed921 100644
--- a/src/gui/rhi/qshaderdescription_p.h
+++ b/src/gui/rhi/qshaderdescription_p.h
@@ -78,7 +78,7 @@ public:
static QShaderDescription fromBinaryJson(const QByteArray &data);
#endif
static QShaderDescription fromCbor(const QByteArray &data);
- static QShaderDescription deserialize(QDataStream *stream);
+ static QShaderDescription deserialize(QDataStream *stream, int version);
enum VariableType {
Unknown = 0,
@@ -216,6 +216,7 @@ public:
int descriptorSet = -1;
ImageFormat imageFormat = ImageFormatUnknown;
ImageFlags imageFlags;
+ QVector<int> arrayDims;
};
struct BlockVariable {
diff --git a/src/gui/rhi/qshaderdescription_p_p.h b/src/gui/rhi/qshaderdescription_p_p.h
index 69b6e811a1..ec2b0b6b4c 100644
--- a/src/gui/rhi/qshaderdescription_p_p.h
+++ b/src/gui/rhi/qshaderdescription_p_p.h
@@ -82,7 +82,7 @@ struct Q_GUI_EXPORT QShaderDescriptionPrivate
QJsonDocument makeDoc();
void writeToStream(QDataStream *stream);
void loadDoc(const QJsonDocument &doc);
- void loadFromStream(QDataStream *stream);
+ void loadFromStream(QDataStream *stream, int version);
QAtomicInt ref;
QVector<QShaderDescription::InOutVariable> inVars;
diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp
index 7e18a10895..5e75e7816b 100644
--- a/src/gui/text/qtextmarkdownimporter.cpp
+++ b/src/gui/text/qtextmarkdownimporter.cpp
@@ -577,7 +577,10 @@ void QTextMarkdownImporter::insertBlock()
QTextBlockFormat blockFormat;
if (!m_listStack.isEmpty() && !m_needsInsertList && m_listItem) {
QTextList *list = m_listStack.top();
- blockFormat = list->item(list->count() - 1).blockFormat();
+ if (list)
+ blockFormat = list->item(list->count() - 1).blockFormat();
+ else
+ qWarning() << "attempted to insert into a list that no longer exists";
}
if (m_blockQuoteDepth) {
blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth);
@@ -607,7 +610,7 @@ void QTextMarkdownImporter::insertBlock()
}
if (m_needsInsertList) {
m_listStack.push(m_cursor->createList(m_listFormat));
- } else if (!m_listStack.isEmpty() && m_listItem) {
+ } else if (!m_listStack.isEmpty() && m_listItem && m_listStack.top()) {
m_listStack.top()->add(m_cursor->block());
}
m_needsInsertList = false;
diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h
index f450da5eb3..f12b725d8e 100644
--- a/src/gui/text/qtextmarkdownimporter_p.h
+++ b/src/gui/text/qtextmarkdownimporter_p.h
@@ -56,6 +56,7 @@
#include <QtGui/qpalette.h>
#include <QtGui/qtextdocument.h>
#include <QtGui/qtextlist.h>
+#include <QtCore/qpointer.h>
#include <QtCore/qstack.h>
QT_BEGIN_NAMESPACE
@@ -113,7 +114,7 @@ private:
#endif
QString m_blockCodeLanguage;
QVector<int> m_nonEmptyTableCells; // in the current row
- QStack<QTextList *> m_listStack;
+ QStack<QPointer<QTextList>> m_listStack;
QStack<QTextCharFormat> m_spanFormatStack;
QFont m_monoFont;
QPalette m_palette;
diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp
index 4b961a6f20..555dee3a9c 100644
--- a/src/gui/vulkan/qvulkaninstance.cpp
+++ b/src/gui/vulkan/qvulkaninstance.cpp
@@ -781,6 +781,8 @@ bool QVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, uint32_t
system dependent synchronization. For example, on Wayland this will
add send a wl_surface.frame request in order to prevent the driver from
blocking for minimized windows.
+
+ \since 5.15
*/
void QVulkanInstance::presentAboutToBeQueued(QWindow *window)
{
diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp
index e211863f21..ee49cf0999 100644
--- a/src/gui/vulkan/qvulkanwindow.cpp
+++ b/src/gui/vulkan/qvulkanwindow.cpp
@@ -1596,19 +1596,6 @@ bool QVulkanWindow::event(QEvent *e)
*/
/*!
- Return a previously set queue create info modification function.
-
- \sa setQueueCreateInfoModifier()
-
- \since 5.15
- */
-QVulkanWindow::QueueCreateInfoModifier QVulkanWindow::queueCreateInfoModifier() const
-{
- Q_D(const QVulkanWindow);
- return d->queueCreateInfoModifier;
-}
-
-/*!
Set a queue create info modification function.
\sa queueCreateInfoModifier()
diff --git a/src/gui/vulkan/qvulkanwindow.h b/src/gui/vulkan/qvulkanwindow.h
index 530b6c0744..511b9501bd 100644
--- a/src/gui/vulkan/qvulkanwindow.h
+++ b/src/gui/vulkan/qvulkanwindow.h
@@ -106,7 +106,6 @@ public:
typedef std::function<void(const VkQueueFamilyProperties *,
uint32_t,
QVector<VkDeviceQueueCreateInfo> &)> QueueCreateInfoModifier;
- QueueCreateInfoModifier queueCreateInfoModifier() const;
void setQueueCreateInfoModifier(QueueCreateInfoModifier modifier);
bool isValid() const;
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index fb30bfd4f1..22c522756c 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -91,7 +91,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
content.
\note Do not delete the object in the slot connected to the
- error() or finished() signal. Use deleteLater().
+ errorOccurred() or finished() signal. Use deleteLater().
\sa QNetworkRequest, QNetworkAccessManager
*/
@@ -219,6 +219,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
the server response was detected
\sa error()
+ \sa errorOccurred()
*/
/*!
@@ -362,6 +363,14 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
/*!
\fn void QNetworkReply::error(QNetworkReply::NetworkError code)
+ \obsolete
+
+ Use errorOccurred() instead.
+*/
+
+/*!
+ \fn void QNetworkReply::errorOccurred(QNetworkReply::NetworkError code)
+ \since 5.15
This signal is emitted when the reply detects an error in
processing. The finished() signal will probably follow, indicating
@@ -442,7 +451,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
QNetworkAccessManager functions to do that.
*/
QNetworkReply::QNetworkReply(QObject *parent)
- : QIODevice(*new QNetworkReplyPrivate, parent)
+ : QNetworkReply(*new QNetworkReplyPrivate, parent)
{
}
@@ -452,6 +461,8 @@ QNetworkReply::QNetworkReply(QObject *parent)
QNetworkReply::QNetworkReply(QNetworkReplyPrivate &dd, QObject *parent)
: QIODevice(dd, parent)
{
+ // Support the deprecated error() signal:
+ connect(this, &QNetworkReply::errorOccurred, this, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error));
}
/*!
diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h
index 4a402daa91..82349f9e2a 100644
--- a/src/network/access/qnetworkreply.h
+++ b/src/network/access/qnetworkreply.h
@@ -156,7 +156,11 @@ public Q_SLOTS:
Q_SIGNALS:
void metaDataChanged();
void finished();
+#if QT_DEPRECATED_SINCE(5,15)
+ QT_DEPRECATED_X("Use QNetworkReply::errorOccurred(QNetworkReply::NetworkError) instead")
void error(QNetworkReply::NetworkError);
+#endif
+ void errorOccurred(QNetworkReply::NetworkError);
#if QT_CONFIG(ssl)
void encrypted();
void sslErrors(const QList<QSslError> &errors);
diff --git a/src/network/access/qnetworkreplydataimpl.cpp b/src/network/access/qnetworkreplydataimpl.cpp
index 924c905b1a..2f75020446 100644
--- a/src/network/access/qnetworkreplydataimpl.cpp
+++ b/src/network/access/qnetworkreplydataimpl.cpp
@@ -88,7 +88,7 @@ QNetworkReplyDataImpl::QNetworkReplyDataImpl(QObject *parent, const QNetworkRequ
const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend",
"Invalid URI: %1").arg(url.toString());
setError(QNetworkReply::ProtocolFailure, msg);
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolFailure));
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
}
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index c7d22be8f5..bb65660ba8 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -2253,7 +2253,7 @@ void QNetworkReplyHttpImplPrivate::error(QNetworkReplyImpl::NetworkError code, c
// note: might not be a good idea, since users could decide to delete us
// which would delete the backend too...
// maybe we should protect the backend
- emit q->error(code);
+ emit q->errorOccurred(code);
}
void QNetworkReplyHttpImplPrivate::_q_metaDataChanged()
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 51bb386186..a0b4ace470 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -855,7 +855,7 @@ void QNetworkReplyImplPrivate::error(QNetworkReplyImpl::NetworkError code, const
// note: might not be a good idea, since users could decide to delete us
// which would delete the backend too...
// maybe we should protect the backend
- emit q->error(code);
+ emit q->errorOccurred(code);
}
void QNetworkReplyImplPrivate::metaDataChanged()
@@ -1128,7 +1128,7 @@ QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent,
"Network access is disabled.");
setError(UnknownNetworkError, msg);
- QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, UnknownNetworkError));
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
}
diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp
index a672e92006..d45ebfb314 100644
--- a/src/plugins/imageformats/gif/qgifhandler.cpp
+++ b/src/plugins/imageformats/gif/qgifhandler.cpp
@@ -1215,11 +1215,4 @@ int QGifHandler::currentImageNumber() const
return frameNumber;
}
-#if QT_DEPRECATED_SINCE(5, 13)
-QByteArray QGifHandler::name() const
-{
- return "gif";
-}
-#endif
-
QT_END_NAMESPACE
diff --git a/src/plugins/imageformats/gif/qgifhandler_p.h b/src/plugins/imageformats/gif/qgifhandler_p.h
index c6592043ce..f19777fa18 100644
--- a/src/plugins/imageformats/gif/qgifhandler_p.h
+++ b/src/plugins/imageformats/gif/qgifhandler_p.h
@@ -73,10 +73,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
-#if QT_DEPRECATED_SINCE(5, 13)
- QByteArray name() const override;
-#endif
-
static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override;
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index 1982e05344..4c8ff7d489 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -809,17 +809,6 @@ bool QtIcoHandler::write(const QImage &image)
return ICOReader::write(device, imgs);
}
-#if QT_DEPRECATED_SINCE(5, 13)
-/*!
- * Return the common identifier of the format.
- * For ICO format this will return "ico".
- */
-QByteArray QtIcoHandler::name() const
-{
- return "ico";
-}
-#endif
-
/*! \reimp
*/
diff --git a/src/plugins/imageformats/ico/qicohandler.h b/src/plugins/imageformats/ico/qicohandler.h
index 328dfce47e..0d44a67dfc 100644
--- a/src/plugins/imageformats/ico/qicohandler.h
+++ b/src/plugins/imageformats/ico/qicohandler.h
@@ -54,10 +54,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
-#if QT_DEPRECATED_SINCE(5, 13)
- QByteArray name() const override;
-#endif
-
int imageCount() const override;
bool jumpToImage(int imageNumber) override;
bool jumpToNextImage() override;
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
index c31e2db3c5..fed585a82e 100644
--- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp
+++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
@@ -1184,11 +1184,4 @@ void QJpegHandler::setOption(ImageOption option, const QVariant &value)
}
}
-#if QT_DEPRECATED_SINCE(5, 13)
-QByteArray QJpegHandler::name() const
-{
- return "jpeg";
-}
-#endif
-
QT_END_NAMESPACE
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler_p.h b/src/plugins/imageformats/jpeg/qjpeghandler_p.h
index fafa930c11..43ca17317a 100644
--- a/src/plugins/imageformats/jpeg/qjpeghandler_p.h
+++ b/src/plugins/imageformats/jpeg/qjpeghandler_p.h
@@ -68,10 +68,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
-#if QT_DEPRECATED_SINCE(5, 13)
- QByteArray name() const override;
-#endif
-
static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override;
diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
index ca16efe34f..07776a4a76 100644
--- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
+++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
@@ -202,9 +202,7 @@ public:
const QString &path)
: QAbstractFileEngineIterator(filters, nameFilters)
{
- m_stack.push_back(FolderIterator::fromCache(cleanedAssetPath(path), true));
- if (m_stack.last()->empty())
- m_stack.pop_back();
+ m_currentIterator = FolderIterator::fromCache(cleanedAssetPath(path), true);
}
QFileInfo currentFileInfo() const override
@@ -228,36 +226,23 @@ public:
bool hasNext() const override
{
- if (m_stack.empty())
+ if (!m_currentIterator)
return false;
- if (!m_stack.last()->hasNext()) {
- m_stack.pop_back();
- return hasNext();
- }
- return true;
+ return m_currentIterator->hasNext();
}
QString next() override
{
- if (m_stack.empty()) {
- m_currentIterator.reset();
+ if (!m_currentIterator)
return {};
- }
- m_currentIterator = m_stack.last();
auto res = m_currentIterator->next();
if (!res)
return {};
- if (res->second.type == AssetItem::Type::Folder) {
- m_stack.push_back(FolderIterator::fromCache(cleanedAssetPath(currentFilePath()), true));
- if (m_stack.last()->empty())
- m_stack.pop_back();
- }
return res->first;
}
private:
- mutable QSharedPointer<FolderIterator> m_currentIterator;
- mutable QVector<QSharedPointer<FolderIterator>> m_stack;
+ QSharedPointer<FolderIterator> m_currentIterator;
};
class AndroidAbstractFileEngine: public QAbstractFileEngine
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 6aa21d78d1..8b76e45616 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -419,8 +419,7 @@ static QString strippedText(QString s)
[mPopUpButton setHidden:chooseDirsOnly]; // TODO hide the whole sunken pane instead?
if (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) {
- const QStringList ext = [self acceptableExtensionsForSave];
- [mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : qt_mac_QStringListToNSMutableArray(ext)];
+ [self recomputeAcceptableExtensionsForSave];
} else {
[mOpenPanel setAllowedFileTypes:nil]; // delegate panel:shouldEnableURL: does the file filtering for NSOpenPanel
}
@@ -457,25 +456,49 @@ static QString strippedText(QString s)
}
/*
- Returns a list of extensions (e.g. "png", "jpg", "gif")
- for the current name filter. If a filter do not conform
- to the format *.xyz or * or *.*, an empty list
- is returned meaning accept everything.
+ Computes a list of extensions (e.g. "png", "jpg", "gif")
+ for the current name filter, and updates the save panel.
+
+ If a filter do not conform to the format *.xyz or * or *.*,
+ all files types are allowed.
+
+ Extensions with more than one part (e.g. "tar.gz") are
+ reduced to their final part, as NSSavePanel does not deal
+ well with multi-part extensions.
*/
-- (QStringList)acceptableExtensionsForSave
-{
- QStringList result;
- for (int i=0; i<mSelectedNameFilter->count(); ++i) {
- const QString &filter = mSelectedNameFilter->at(i);
- if (filter.startsWith(QLatin1String("*."))
- && !filter.contains(QLatin1Char('?'))
- && filter.count(QLatin1Char('*')) == 1) {
- result += filter.mid(2);
- } else {
- return QStringList(); // Accept everything
- }
+- (void)recomputeAcceptableExtensionsForSave
+{
+ QStringList fileTypes;
+ for (const QString &filter : *mSelectedNameFilter) {
+ if (!filter.startsWith(QLatin1String("*.")))
+ continue;
+
+ if (filter.contains(QLatin1Char('?')))
+ continue;
+
+ if (filter.count(QLatin1Char('*')) != 1)
+ continue;
+
+ auto extensions = filter.split('.', Qt::SkipEmptyParts);
+ fileTypes += extensions.last();
+
+ // Explicitly show extensions if we detect a filter
+ // that has a multi-part extension. This prevents
+ // confusing situations where the user clicks e.g.
+ // 'foo.tar.gz' and 'foo.tar' is populated in the
+ // file name box, but when then clicking save macOS
+ // will warn that the file needs to end in .gz,
+ // due to thinking the user tried to save the file
+ // as a 'tar' file instead. Unfortunately this
+ // property can only be set before the panel is
+ // shown, so it will not have any effect when
+ // swithcing filters in an already opened dialog.
+ if (extensions.size() > 2)
+ mSavePanel.extensionHidden = NO;
}
- return result;
+
+ mSavePanel.allowedFileTypes = fileTypes.isEmpty() ? nil
+ : qt_mac_QStringListToNSMutableArray(fileTypes);
}
- (QString)removeExtensions:(const QString &)filter
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index d0e69bdca5..450329f569 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -107,7 +107,7 @@ void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceS
#if QT_CONFIG(vulkan)
} else if (resourceString == "vkSurface") {
if (QVulkanInstance *instance = window->vulkanInstance())
- return static_cast<QCocoaVulkanInstance *>(instance->handle())->createSurface(window);
+ return static_cast<QCocoaVulkanInstance *>(instance->handle())->surface(window);
#endif
}
return nullptr;
diff --git a/src/plugins/platforms/cocoa/qcocoavulkaninstance.h b/src/plugins/platforms/cocoa/qcocoavulkaninstance.h
index 5fe6a612af..2a8d04757e 100644
--- a/src/plugins/platforms/cocoa/qcocoavulkaninstance.h
+++ b/src/plugins/platforms/cocoa/qcocoavulkaninstance.h
@@ -61,9 +61,11 @@ public:
void createOrAdoptInstance() override;
- VkSurfaceKHR *createSurface(QWindow *window);
- VkSurfaceKHR createSurface(NSView *view);
+ VkSurfaceKHR *surface(QWindow *window);
+
private:
+ VkSurfaceKHR createSurface(NSView *view);
+
QVulkanInstance *m_instance = nullptr;
QLibrary m_lib;
VkSurfaceKHR m_nullSurface = nullptr;
diff --git a/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm b/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm
index 7ce78ee738..9e714859f2 100644
--- a/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm
+++ b/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm
@@ -57,12 +57,11 @@ void QCocoaVulkanInstance::createOrAdoptInstance()
initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_MVK_macos_surface"));
}
-VkSurfaceKHR *QCocoaVulkanInstance::createSurface(QWindow *window)
+VkSurfaceKHR *QCocoaVulkanInstance::surface(QWindow *window)
{
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
- if (cocoaWindow->m_vulkanSurface)
- destroySurface(cocoaWindow->m_vulkanSurface);
- cocoaWindow->m_vulkanSurface = createSurface(cocoaWindow->m_view);
+ if (!cocoaWindow->m_vulkanSurface)
+ cocoaWindow->m_vulkanSurface = createSurface(cocoaWindow->m_view);
return &cocoaWindow->m_vulkanSurface;
}
@@ -81,7 +80,7 @@ VkSurfaceKHR QCocoaVulkanInstance::createSurface(NSView *view)
surfaceInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
surfaceInfo.pNext = nullptr;
surfaceInfo.flags = 0;
- surfaceInfo.pView = view;
+ surfaceInfo.pView = view.layer;
VkSurfaceKHR surface = nullptr;
VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface);
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
index cadb76d2e4..429c47dc3b 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
@@ -394,16 +394,19 @@ QCoreGraphicsPaintEngine::begin(QPaintDevice *pdev)
d->cosmeticPenSize = 1;
d->current.clipEnabled = false;
d->pixelSize = QPoint(1,1);
- QMacCGContext ctx(pdev);
- d->hd = CGContextRetain(ctx);
- if (d->hd) {
- d->saveGraphicsState();
- d->orig_xform = CGContextGetCTM(d->hd);
- if (d->shading) {
- CGShadingRelease(d->shading);
- d->shading = nullptr;
+
+ if (pdev->devType() != QInternal::Printer) {
+ QMacCGContext ctx(pdev);
+ d->hd = CGContextRetain(ctx);
+ if (d->hd) {
+ d->saveGraphicsState();
+ d->orig_xform = CGContextGetCTM(d->hd);
+ if (d->shading) {
+ CGShadingRelease(d->shading);
+ d->shading = nullptr;
+ }
+ d->setClip(nullptr); //clear the context's clipping
}
- d->setClip(nullptr); //clear the context's clipping
}
setActive(true);
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 77340387d8..8963f2ad17 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -343,7 +343,9 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
QWindowsWindowData requested;
requested.flags = window->flags();
- requested.geometry = QHighDpi::toNativePixels(window->geometry(), window);
+ requested.geometry = window->isTopLevel()
+ ? QHighDpi::toNativePixels(window->geometry(), window)
+ : QHighDpi::toNativeLocalPosition(window->geometry(), window);
// Apply custom margins (see QWindowsWindow::setCustomMargins())).
const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
if (customMarginsV.isValid())
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
index 53562c87dd..d6a5b29a71 100644
--- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
@@ -424,8 +424,12 @@ bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result)
if (screen) {
emit contextMenuRequested(globalPos, screen);
emit activated(Context);
- if (m_menu)
+ if (m_menu) {
+ // Set the foreground window to the controlling window so that clicking outside
+ // of the menu or window will cause the menu to close
+ SetForegroundWindow(m_hwnd);
m_menu->trackPopupMenu(message.hwnd, globalPos.x(), globalPos.y());
+ }
}
}
break;
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index e635463951..3dfffa6de6 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1954,10 +1954,8 @@ void QWindowsWindow::checkForScreenChanged(ScreenChangeMode mode)
qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
<< ' ' << window() << " \"" << (currentScreen ? currentScreen->name() : QString())
<< "\"->\"" << newScreen->name() << '"';
- if (mode == FromGeometryChange)
- setFlag(SynchronousGeometryChangeEvent);
updateFullFrameMargins();
- QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+ QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(window(), newScreen->screen());
}
void QWindowsWindow::handleGeometryChange()
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 71ec47b053..5be04a984a 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -274,7 +274,9 @@ void QXcbWindow::create()
QXcbScreen *currentScreen = xcbScreen();
QXcbScreen *platformScreen = parent() ? parentScreen() : initialScreen();
- QRect rect = QHighDpi::toNativePixels(window()->geometry(), platformScreen);
+ QRect rect = parent()
+ ? QHighDpi::toNativeLocalPosition(window()->geometry(), platformScreen)
+ : QHighDpi::toNativePixels(window()->geometry(), platformScreen);
if (type == Qt::Desktop) {
m_window = platformScreen->root();
diff --git a/src/tools/uic/python/pythonwriteimports.cpp b/src/tools/uic/python/pythonwriteimports.cpp
index d33b4c6210..95e039e6f0 100644
--- a/src/tools/uic/python/pythonwriteimports.cpp
+++ b/src/tools/uic/python/pythonwriteimports.cpp
@@ -131,6 +131,8 @@ void WriteImports::acceptCustomWidget(DomCustomWidget *node)
output << "import " << className << '\n';
} else { // When we do have elementHeader, we know it's a relative import.
QString modulePath = node->elementHeader()->text();
+ // Replace the '/' by '.'
+ modulePath.replace(QLatin1Char('/'), QLatin1Char('.'));
// '.h' is added by default on headers for <customwidget>
if (modulePath.endsWith(QLatin1String(".h")))
modulePath.chop(2);
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index cae776159d..23292062cb 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -1473,6 +1473,9 @@ void QMenuPrivate::_q_actionTriggered()
}
}
activateCausedStack(list, action, QAction::Trigger, false);
+ // if a widget action fires, we need to hide the menu explicitly
+ if (qobject_cast<QWidgetAction*>(action))
+ hideUpToMenuBar();
}
}
}
@@ -1640,10 +1643,8 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action)
Widgets can be inserted into menus with the QWidgetAction class.
Instances of this class are used to hold widgets, and are inserted
- into menus with the addAction() overload that takes a QAction.
-
- Conversely, actions can be added to widgets with the addAction(),
- addActions() and insertAction() functions.
+ into menus with the addAction() overload that takes a QAction. If the
+ QWidgetAction fires the triggered() signal, the menu will close.
\warning To make QMenu visible on the screen, exec() or popup() should be
used instead of show().