summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2019-09-17 08:32:43 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2019-09-17 08:32:43 +0200
commitd49d076431d7579ecb33147187fe07eb148112ba (patch)
tree668370fb9a2eec50000e371125136921ef4518ab /src/gui
parentb01e69684b9b36492cc43472edeb72058be9f706 (diff)
parent35cdcddd605d8823b7b57129e8d7279133a3ca89 (diff)
Merge remote-tracking branch 'origin/5.15' into dev
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/image/qiconloader.cpp2
-rw-r--r--src/gui/image/qimage.cpp2
-rw-r--r--src/gui/image/qimage_conversions.cpp218
-rw-r--r--src/gui/image/qimagereader.cpp6
-rw-r--r--src/gui/image/qpicture.cpp3
-rw-r--r--src/gui/kernel/qguiapplication.cpp19
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp9
-rw-r--r--src/gui/kernel/qopenglcontext.cpp11
-rw-r--r--src/gui/kernel/qtouchdevice.cpp10
-rw-r--r--src/gui/painting/qcolormatrix_p.h22
-rw-r--r--src/gui/painting/qcolorspace.cpp39
-rw-r--r--src/gui/painting/qcolorspace.h9
-rw-r--r--src/gui/painting/qcolorspace_p.h6
-rw-r--r--src/gui/painting/qcolortransferfunction_p.h4
-rw-r--r--src/gui/painting/qcolortransform.cpp12
-rw-r--r--src/gui/painting/qdrawhelper.cpp6
-rw-r--r--src/gui/painting/qdrawhelper_ssse3.cpp45
-rw-r--r--src/gui/painting/qicc.cpp3
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp20
-rw-r--r--src/gui/painting/qplatformbackingstore.h3
-rw-r--r--src/gui/rhi/cs_tdr.h209
-rw-r--r--src/gui/rhi/qrhi.cpp152
-rw-r--r--src/gui/rhi/qrhi_p.h9
-rw-r--r--src/gui/rhi/qrhi_p_p.h6
-rw-r--r--src/gui/rhi/qrhid3d11.cpp509
-rw-r--r--src/gui/rhi/qrhid3d11_p.h3
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h27
-rw-r--r--src/gui/rhi/qrhigles2.cpp219
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h7
-rw-r--r--src/gui/rhi/qrhimetal.mm502
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h4
-rw-r--r--src/gui/rhi/qrhinull.cpp13
-rw-r--r--src/gui/rhi/qrhinull_p_p.h4
-rw-r--r--src/gui/rhi/qrhiprofiler.cpp14
-rw-r--r--src/gui/rhi/qrhiprofiler_p_p.h6
-rw-r--r--src/gui/rhi/qrhivulkan.cpp387
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h5
-rw-r--r--src/gui/rhi/tdr.hlsl9
-rw-r--r--src/gui/text/qtextdocument.cpp5
-rw-r--r--src/gui/text/qtextengine.cpp15
-rw-r--r--src/gui/text/qtextformat.cpp1
41 files changed, 1618 insertions, 937 deletions
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 1d0c93f26f..27c82bc09f 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -281,7 +281,7 @@ static quint32 icon_name_hash(const char *p)
QVector<const char *> QIconCacheGtkReader::lookup(const QStringRef &name)
{
QVector<const char *> ret;
- if (!isValid())
+ if (!isValid() || name.isEmpty())
return ret;
QByteArray nameUtf8 = name.toUtf8();
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 86130132a4..dda407181a 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -3370,7 +3370,7 @@ void QImage::mirrored_inplace(bool horizontal, bool vertical)
\sa {QImage#Image Transformations}{Image Transformations}
*/
-inline void rgbSwapped_generic(int width, int height, const QImage *src, QImage *dst, const QPixelLayout* layout)
+static inline void rgbSwapped_generic(int width, int height, const QImage *src, QImage *dst, const QPixelLayout* layout)
{
const RbSwapFunc func = layout->rbSwap;
if (!func) {
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 539bac222a..9e1df7058c 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -564,6 +564,67 @@ static bool convert_RGBA_to_ARGB_inplace(QImageData *data, Qt::ImageConversionFl
return true;
}
+static void convert_rgbswap_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const RbSwapFunc func = qPixelLayouts[src->format].rbSwap;
+ Q_ASSERT(func);
+
+ const qsizetype sbpl = src->bytes_per_line;
+ const qsizetype dbpl = dest->bytes_per_line;
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ func(dest_data, src_data, src->width);
+
+ src_data += sbpl;
+ dest_data += dbpl;
+ }
+}
+
+static bool convert_rgbswap_generic_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+ const RbSwapFunc func = qPixelLayouts[data->format].rbSwap;
+ Q_ASSERT(func);
+
+ const qsizetype bpl = data->bytes_per_line;
+ uchar *line_data = data->data;
+
+ for (int i = 0; i < data->height; ++i) {
+ func(line_data, line_data, data->width);
+ line_data += bpl;
+ }
+
+ switch (data->format) {
+ case QImage::Format_RGB888:
+ data->format = QImage::Format_BGR888;
+ break;
+ case QImage::Format_BGR888:
+ data->format = QImage::Format_RGB888;
+ break;
+ case QImage::Format_BGR30:
+ data->format = QImage::Format_RGB30;
+ break;
+ case QImage::Format_A2BGR30_Premultiplied:
+ data->format = QImage::Format_A2RGB30_Premultiplied;
+ break;
+ case QImage::Format_RGB30:
+ data->format = QImage::Format_BGR30;
+ break;
+ case QImage::Format_A2RGB30_Premultiplied:
+ data->format = QImage::Format_A2BGR30_Premultiplied;
+ break;
+ default:
+ Q_UNREACHABLE();
+ data->format = QImage::Format_Invalid;
+ return false;
+ }
+ return true;
+}
+
template<QtPixelOrder PixelOrder, bool RGBA>
static void convert_RGB_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
@@ -693,74 +754,10 @@ static bool convert_A2RGB30_PM_to_RGB30_inplace(QImageData *data, Qt::ImageConve
return true;
}
-static void convert_BGR30_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
-{
- Q_ASSERT(src->format == QImage::Format_RGB30 || src->format == QImage::Format_BGR30 ||
- src->format == QImage::Format_A2RGB30_Premultiplied || src->format == QImage::Format_A2BGR30_Premultiplied);
- Q_ASSERT(dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_BGR30 ||
- dest->format == QImage::Format_A2RGB30_Premultiplied || dest->format == QImage::Format_A2BGR30_Premultiplied);
- Q_ASSERT(src->width == dest->width);
- Q_ASSERT(src->height == dest->height);
-
- const int src_pad = (src->bytes_per_line >> 2) - src->width;
- const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
- const quint32 *src_data = (quint32 *) src->data;
- quint32 *dest_data = (quint32 *) dest->data;
-
- for (int i = 0; i < src->height; ++i) {
- const quint32 *end = src_data + src->width;
- while (src_data < end) {
- *dest_data = qRgbSwapRgb30(*src_data);
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
- }
-}
-
-static bool convert_BGR30_to_RGB30_inplace(QImageData *data, Qt::ImageConversionFlags)
-{
- Q_ASSERT(data->format == QImage::Format_RGB30 || data->format == QImage::Format_BGR30 ||
- data->format == QImage::Format_A2RGB30_Premultiplied || data->format == QImage::Format_A2BGR30_Premultiplied);
-
- const int pad = (data->bytes_per_line >> 2) - data->width;
- uint *rgb_data = (uint *) data->data;
-
- for (int i = 0; i < data->height; ++i) {
- const uint *end = rgb_data + data->width;
- while (rgb_data < end) {
- *rgb_data = qRgbSwapRgb30(*rgb_data);
- ++rgb_data;
- }
- rgb_data += pad;
- }
-
- switch (data->format) {
- case QImage::Format_BGR30:
- data->format = QImage::Format_RGB30;
- break;
- case QImage::Format_A2BGR30_Premultiplied:
- data->format = QImage::Format_A2RGB30_Premultiplied;
- break;
- case QImage::Format_RGB30:
- data->format = QImage::Format_BGR30;
- break;
- case QImage::Format_A2RGB30_Premultiplied:
- data->format = QImage::Format_A2BGR30_Premultiplied;
- break;
- default:
- Q_UNREACHABLE();
- data->format = QImage::Format_Invalid;
- return false;
- }
- return true;
-}
-
static bool convert_BGR30_to_A2RGB30_inplace(QImageData *data, Qt::ImageConversionFlags flags)
{
Q_ASSERT(data->format == QImage::Format_RGB30 || data->format == QImage::Format_BGR30);
- if (!convert_BGR30_to_RGB30_inplace(data, flags))
+ if (!convert_rgbswap_generic_inplace(data, flags))
return false;
if (data->format == QImage::Format_RGB30)
@@ -1421,69 +1418,6 @@ static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt
}
}
-static void convert_RGB888_to_BGR888(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
-{
- Q_ASSERT(src->format == QImage::Format_RGB888 || src->format == QImage::Format_BGR888);
- Q_ASSERT(dest->format == QImage::Format_RGB888 || dest->format == QImage::Format_BGR888);
- Q_ASSERT(src->width == dest->width);
- Q_ASSERT(src->height == dest->height);
-
- const qsizetype sbpl = src->bytes_per_line;
- const qsizetype dbpl = dest->bytes_per_line;
- const uchar *src_data = src->data;
- uchar *dest_data = dest->data;
-
- for (int i = 0; i < src->height; ++i) {
- int pixel = 0;
- // Handle 4 pixels (12 bytes) at a time
- for (; pixel + 3 < src->width; pixel += 4) {
- const uchar *src = src_data + pixel * 3;
- quint32 *dest_packed = (quint32 *) (dest_data + pixel * 3);
- dest_packed[0] = (src[5] << 24) | (src[0] << 16) | (src[1] << 8) | (src[2] << 0);
- dest_packed[1] = (src[7] << 24) | (src[8] << 16) | (src[3] << 8) | (src[4] << 0);
- dest_packed[2] = (src[9] << 24) | (src[10] << 16) | (src[11] << 8) | (src[6] << 0);
- }
-
- // epilog: handle left over pixels
- for (; pixel < src->width; ++pixel) {
- dest_data[pixel * 3 + 0] = src_data[pixel * 3 + 2];
- dest_data[pixel * 3 + 1] = src_data[pixel * 3 + 1];
- dest_data[pixel * 3 + 2] = src_data[pixel * 3 + 0];
- }
-
- src_data += sbpl;
- dest_data += dbpl;
- }
-}
-
-static bool convert_RGB888_to_BGR888_inplace(QImageData *data, Qt::ImageConversionFlags)
-{
- Q_ASSERT(data->format == QImage::Format_RGB888 || data->format == QImage::Format_BGR888);
-
- const qsizetype bpl = data->bytes_per_line;
- uchar *line_data = data->data;
-
- for (int i = 0; i < data->height; ++i) {
- for (int j = 0; j < data->width; ++j)
- qSwap(line_data[j * 3 + 0], line_data[j * 3 + 2]);
- line_data += bpl;
- }
-
- switch (data->format) {
- case QImage::Format_RGB888:
- data->format = QImage::Format_BGR888;
- break;
- case QImage::Format_BGR888:
- data->format = QImage::Format_RGB888;
- break;
- default:
- Q_UNREACHABLE();
- data->format = QImage::Format_Invalid;
- return false;
- }
- return true;
-}
-
static QVector<QRgb> fix_color_table(const QVector<QRgb> &ctbl, QImage::Format format)
{
QVector<QRgb> colorTable = ctbl;
@@ -2635,7 +2569,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_RGB888_to_RGB<true>,
convert_RGB888_to_RGB<true>,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- convert_RGB888_to_BGR888,
+ convert_rgbswap_generic,
}, // Format_RGB888
{
@@ -2781,8 +2715,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
convert_passthrough,
- convert_BGR30_to_RGB30,
- convert_BGR30_to_RGB30,
+ convert_rgbswap_generic,
+ convert_rgbswap_generic,
0, 0,
0, 0, 0, 0, 0
}, // Format_BGR30
@@ -2809,7 +2743,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_A2RGB30_PM_to_RGB30<false>,
0,
convert_A2RGB30_PM_to_RGB30<true>,
- convert_BGR30_to_RGB30,
+ convert_rgbswap_generic,
0, 0,
0, 0, 0, 0, 0
}, // Format_A2BGR30_Premultiplied
@@ -2833,8 +2767,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- convert_BGR30_to_RGB30,
- convert_BGR30_to_RGB30,
+ convert_rgbswap_generic,
+ convert_rgbswap_generic,
0,
convert_passthrough,
0, 0, 0, 0, 0, 0, 0
@@ -2860,7 +2794,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_A2RGB30_PM_to_ARGB<PixelOrderRGB, true>,
0,
convert_A2RGB30_PM_to_RGB30<true>,
- convert_BGR30_to_RGB30,
+ convert_rgbswap_generic,
convert_A2RGB30_PM_to_RGB30<false>,
0,
0, 0,
@@ -3013,7 +2947,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- convert_RGB888_to_BGR888,
+ convert_rgbswap_generic,
0,
0,
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
@@ -3161,7 +3095,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
}, // Format_ARGB8555_Premultiplied
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- convert_RGB888_to_BGR888_inplace
+ convert_rgbswap_generic_inplace
}, // Format_RGB888
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
@@ -3267,7 +3201,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0, // self
convert_passthrough_inplace<QImage::Format_A2BGR30_Premultiplied>,
- convert_BGR30_to_RGB30_inplace,
+ convert_rgbswap_generic_inplace,
convert_BGR30_to_A2RGB30_inplace,
0, 0,
0, 0, 0, 0, 0
@@ -3295,7 +3229,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_A2RGB30_PM_to_RGB30_inplace<false>,
0, // self
convert_A2RGB30_PM_to_RGB30_inplace<true>,
- convert_BGR30_to_RGB30_inplace,
+ convert_rgbswap_generic_inplace,
0, 0, 0, 0, 0, 0, 0
}, // Format_A2BGR30_Premultiplied
{
@@ -3318,7 +3252,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- convert_BGR30_to_RGB30_inplace,
+ convert_rgbswap_generic_inplace,
convert_BGR30_to_A2RGB30_inplace,
0, // self
convert_passthrough_inplace<QImage::Format_A2RGB30_Premultiplied>,
@@ -3345,7 +3279,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_A2RGB30_PM_to_ARGB_inplace<PixelOrderRGB, true>,
0,
convert_A2RGB30_PM_to_RGB30_inplace<true>,
- convert_BGR30_to_RGB30_inplace,
+ convert_rgbswap_generic_inplace,
convert_A2RGB30_PM_to_RGB30_inplace<false>,
0, // self
0, 0,
@@ -3427,7 +3361,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
}, // Format_Grayscale16
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- convert_RGB888_to_BGR888_inplace,
+ convert_rgbswap_generic_inplace,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_BGR888
};
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 6a0763e696..dff24b449a 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -150,7 +150,7 @@
// factory loader
#include <qcoreapplication.h>
#include <private/qfactoryloader_p.h>
-#include <QMutexLocker>
+#include <QtCore/private/qlocking_p.h>
// for qt_getImageText
#include <private/qimage_p.h>
@@ -186,8 +186,8 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
QByteArray suffix;
#ifndef QT_NO_IMAGEFORMATPLUGIN
- static QMutex mutex;
- QMutexLocker locker(&mutex);
+ static QBasicMutex mutex;
+ const auto locker = qt_scoped_lock(mutex);
typedef QMultiMap<int, QString> PluginKeyMap;
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index 8548f1857e..978a07b9f9 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -57,6 +57,7 @@
#include "qregexp.h"
#include "qregion.h"
#include "qdebug.h"
+#include <QtCore/private/qlocking_p.h>
#include <algorithm>
@@ -1427,7 +1428,7 @@ void qt_init_picture_plugins()
typedef PluginKeyMap::const_iterator PluginKeyMapConstIterator;
static QBasicMutex mutex;
- QMutexLocker locker(&mutex);
+ const auto locker = qt_scoped_lock(mutex);
static QFactoryLoader loader(QPictureFormatInterface_iid,
QStringLiteral("/pictureformats"));
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index cb7a0b8ac9..a3ef3b2314 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -58,6 +58,7 @@
#include <QtCore/private/qabstracteventdispatcher_p.h>
#include <QtCore/qmutex.h>
#include <QtCore/private/qthread_p.h>
+#include <QtCore/private/qlocking_p.h>
#include <QtCore/qdir.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qnumeric.h>
@@ -2762,7 +2763,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
QWindow *window = e->window.data();
typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints;
QHash<QWindow *, StatesAndTouchPoints> windowsNeedingEvents;
- bool stationaryTouchPointChangedVelocity = false;
+ bool stationaryTouchPointChangedProperty = false;
for (int i = 0; i < e->points.count(); ++i) {
QTouchEvent::TouchPoint touchPoint = e->points.at(i);
@@ -2842,7 +2843,11 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
if (touchPoint.state() == Qt::TouchPointStationary) {
if (touchInfo.touchPoint.velocity() != touchPoint.velocity()) {
touchInfo.touchPoint.setVelocity(touchPoint.velocity());
- stationaryTouchPointChangedVelocity = true;
+ stationaryTouchPointChangedProperty = true;
+ }
+ if (!qFuzzyCompare(touchInfo.touchPoint.pressure(), touchPoint.pressure())) {
+ touchInfo.touchPoint.setPressure(touchPoint.pressure());
+ stationaryTouchPointChangedProperty = true;
}
} else {
touchInfo.touchPoint = touchPoint;
@@ -2883,7 +2888,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
break;
case Qt::TouchPointStationary:
// don't send the event if nothing changed
- if (!stationaryTouchPointChangedVelocity)
+ if (!stationaryTouchPointChangedProperty)
continue;
Q_FALLTHROUGH();
default:
@@ -3301,7 +3306,7 @@ void QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(QWindow *window)
QFont QGuiApplication::font()
{
Q_ASSERT_X(QGuiApplicationPrivate::self, "QGuiApplication::font()", "no QGuiApplication instance");
- QMutexLocker locker(&applicationFontMutex);
+ const auto locker = qt_scoped_lock(applicationFontMutex);
initFontUnlocked();
return *QGuiApplicationPrivate::app_font;
}
@@ -3313,7 +3318,7 @@ QFont QGuiApplication::font()
*/
void QGuiApplication::setFont(const QFont &font)
{
- QMutexLocker locker(&applicationFontMutex);
+ auto locker = qt_unique_lock(applicationFontMutex);
const bool emitChange = !QGuiApplicationPrivate::app_font
|| (*QGuiApplicationPrivate::app_font != font);
if (!QGuiApplicationPrivate::app_font)
@@ -3501,7 +3506,7 @@ Qt::ApplicationState QGuiApplication::applicationState()
\since 5.14
Sets the high-DPI scale factor rounding policy for the application. The
- policy decides how non-integer scale factors (such as Windows 150%) are
+ \a policy decides how non-integer scale factors (such as Windows 150%) are
handled, for applications that have AA_EnableHighDpiScaling enabled.
The two principal options are whether fractional scale factors should
@@ -4077,7 +4082,7 @@ void QGuiApplicationPrivate::notifyThemeChanged()
sendApplicationPaletteChange();
}
if (!(applicationResourceFlags & ApplicationFontExplicitlySet)) {
- QMutexLocker locker(&applicationFontMutex);
+ const auto locker = qt_scoped_lock(applicationFontMutex);
clearFontUnlocked();
initFontUnlocked();
}
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index ec4feeba8b..ee54fd4fa1 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -538,7 +538,7 @@ void QHighDpiScaling::updateHighDpiScaling()
++i;
}
}
- m_active = m_globalScalingActive || m_usePixelDensity;
+ m_active = m_globalScalingActive || m_screenFactorSet || m_usePixelDensity;
}
/*
@@ -680,8 +680,11 @@ QDpi QHighDpiScaling::logicalDpi(const QScreen *screen)
if (!screen || !screen->handle())
return QDpi(96, 96);
- if (!m_usePixelDensity)
- return QPlatformScreen::overrideDpi(screen->handle()->logicalDpi());
+ if (!m_usePixelDensity) {
+ const qreal screenScaleFactor = screenSubfactor(screen->handle());
+ const QDpi dpi = QPlatformScreen::overrideDpi(screen->handle()->logicalDpi());
+ return QDpi{ dpi.first / screenScaleFactor, dpi.second / screenScaleFactor };
+ }
const qreal scaleFactor = rawScaleFactor(screen->handle());
const qreal roundedScaleFactor = roundScaleFactor(scaleFactor);
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 6f51fe3095..638eb1d12f 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -45,6 +45,7 @@
#include <QtCore/QThreadStorage>
#include <QtCore/QThread>
+#include <QtCore/private/qlocking_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qopengl_p.h>
@@ -1442,7 +1443,7 @@ QOpenGLContextGroup *QOpenGLContextGroup::currentContextGroup()
void QOpenGLContextGroupPrivate::addContext(QOpenGLContext *ctx)
{
- QMutexLocker locker(&m_mutex);
+ const auto locker = qt_scoped_lock(m_mutex);
m_refs.ref();
m_shares << ctx;
}
@@ -1454,7 +1455,7 @@ void QOpenGLContextGroupPrivate::removeContext(QOpenGLContext *ctx)
bool deleteObject = false;
{
- QMutexLocker locker(&m_mutex);
+ const auto locker = qt_scoped_lock(m_mutex);
m_shares.removeOne(ctx);
if (ctx == m_context && !m_shares.isEmpty())
@@ -1502,7 +1503,7 @@ void QOpenGLContextGroupPrivate::cleanup()
void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx)
{
- QMutexLocker locker(&m_mutex);
+ const auto locker = qt_scoped_lock(m_mutex);
const QList<QOpenGLSharedResource *> pending = m_pendingDeletion;
m_pendingDeletion.clear();
@@ -1543,7 +1544,7 @@ void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx)
QOpenGLSharedResource::QOpenGLSharedResource(QOpenGLContextGroup *group)
: m_group(group)
{
- QMutexLocker locker(&m_group->d_func()->m_mutex);
+ const auto locker = qt_scoped_lock(m_group->d_func()->m_mutex);
m_group->d_func()->m_sharedResources << this;
}
@@ -1559,7 +1560,7 @@ void QOpenGLSharedResource::free()
return;
}
- QMutexLocker locker(&m_group->d_func()->m_mutex);
+ const auto locker = qt_scoped_lock(m_group->d_func()->m_mutex);
m_group->d_func()->m_sharedResources.removeOne(this);
m_group->d_func()->m_pendingDeletion << this;
diff --git a/src/gui/kernel/qtouchdevice.cpp b/src/gui/kernel/qtouchdevice.cpp
index ea187f54aa..8293fddc59 100644
--- a/src/gui/kernel/qtouchdevice.cpp
+++ b/src/gui/kernel/qtouchdevice.cpp
@@ -228,7 +228,7 @@ TouchDevices::TouchDevices()
*/
QList<const QTouchDevice *> QTouchDevice::devices()
{
- QMutexLocker lock(&devicesMutex);
+ const auto locker = qt_scoped_lock(devicesMutex);
return deviceList->list;
}
@@ -237,13 +237,13 @@ QList<const QTouchDevice *> QTouchDevice::devices()
*/
bool QTouchDevicePrivate::isRegistered(const QTouchDevice *dev)
{
- QMutexLocker locker(&devicesMutex);
+ const auto locker = qt_scoped_lock(devicesMutex);
return deviceList->list.contains(dev);
}
const QTouchDevice *QTouchDevicePrivate::deviceById(quint8 id)
{
- QMutexLocker locker(&devicesMutex);
+ const auto locker = qt_scoped_lock(devicesMutex);
for (const QTouchDevice *dev : qAsConst(deviceList->list))
if (QTouchDevicePrivate::get(const_cast<QTouchDevice *>(dev))->id == id)
return dev;
@@ -255,7 +255,7 @@ const QTouchDevice *QTouchDevicePrivate::deviceById(quint8 id)
*/
void QTouchDevicePrivate::registerDevice(const QTouchDevice *dev)
{
- QMutexLocker lock(&devicesMutex);
+ const auto locker = qt_scoped_lock(devicesMutex);
deviceList->list.append(dev);
}
@@ -264,7 +264,7 @@ void QTouchDevicePrivate::registerDevice(const QTouchDevice *dev)
*/
void QTouchDevicePrivate::unregisterDevice(const QTouchDevice *dev)
{
- QMutexLocker lock(&devicesMutex);
+ const auto locker = qt_scoped_lock(devicesMutex);
deviceList->list.removeOne(dev);
}
diff --git a/src/gui/painting/qcolormatrix_p.h b/src/gui/painting/qcolormatrix_p.h
index 66db95df7e..edb2d32258 100644
--- a/src/gui/painting/qcolormatrix_p.h
+++ b/src/gui/painting/qcolormatrix_p.h
@@ -62,17 +62,16 @@ class QColorVector
{
public:
QColorVector() = default;
- Q_DECL_CONSTEXPR QColorVector(float x, float y, float z) : x(x), y(y), z(z), _unused(0.0f) { }
+ Q_DECL_CONSTEXPR QColorVector(float x, float y, float z) : x(x), y(y), z(z) { }
explicit Q_DECL_CONSTEXPR QColorVector(const QPointF &chr) // from XY chromaticity
: x(chr.x() / chr.y())
, y(1.0f)
, z((1.0 - chr.x() - chr.y()) / chr.y())
- , _unused(0.0f)
{ }
- float x; // X, x or red
- float y; // Y, y or green
- float z; // Z, Y or blue
- float _unused;
+ float x = 0.0f; // X, x or red
+ float y = 0.0f; // Y, y or green
+ float z = 0.0f; // Z, Y or blue
+ float _unused = 0.0f;
friend inline bool operator==(const QColorVector &v1, const QColorVector &v2);
friend inline bool operator!=(const QColorVector &v1, const QColorVector &v2);
@@ -81,7 +80,6 @@ public:
return !x && !y && !z;
}
- static Q_DECL_CONSTEXPR QColorVector null() { return QColorVector(0.0f, 0.0f, 0.0f); }
static bool isValidChromaticity(const QPointF &chr)
{
if (chr.x() < qreal(0.0) || chr.x() > qreal(1.0))
@@ -187,10 +185,6 @@ public:
{ r.z, g.z, b.z } };
}
- static QColorMatrix null()
- {
- return { QColorVector::null(), QColorVector::null(), QColorVector::null() };
- }
static QColorMatrix identity()
{
return { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } };
@@ -226,12 +220,6 @@ public:
{ 0.1351922452f, 0.7118769884f, 0.0000000000f },
{ 0.0313525312f, 0.0000856627f, 0.8251883388f } };
}
- static QColorMatrix toXyzFromBt2020()
- {
- return QColorMatrix { { 0.6506130099f, 0.2695676684f, -0.0018652577f },
- { 0.1865101457f, 0.6840794086f, 0.0172256753f },
- { 0.1270887405f, 0.0463530831f, 0.8098278046f } };
- }
};
inline bool operator==(const QColorMatrix &m1, const QColorMatrix &m2)
diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp
index 39ab358879..937bb505c9 100644
--- a/src/gui/painting/qcolorspace.cpp
+++ b/src/gui/painting/qcolorspace.cpp
@@ -70,12 +70,6 @@ QColorSpacePrimaries::QColorSpacePrimaries(QColorSpace::Primaries primaries)
bluePoint = QPointF(0.150, 0.060);
whitePoint = QColorVector::D65Chromaticity();
break;
- case QColorSpace::Primaries::Bt2020:
- redPoint = QPointF(0.708, 0.292);
- greenPoint = QPointF(0.190, 0.797);
- bluePoint = QPointF(0.131, 0.046);
- whitePoint = QColorVector::D65Chromaticity();
- break;
case QColorSpace::Primaries::AdobeRgb:
redPoint = QPointF(0.640, 0.330);
greenPoint = QPointF(0.210, 0.710);
@@ -152,17 +146,11 @@ QColorMatrix QColorSpacePrimaries::toXyzMatrix() const
}
QColorSpacePrivate::QColorSpacePrivate()
- : primaries(QColorSpace::Primaries::Custom)
- , transferFunction(QColorSpace::TransferFunction::Custom)
- , gamma(0.0f)
- , whitePoint(QColorVector::null())
- , toXyz(QColorMatrix::null())
{
}
QColorSpacePrivate::QColorSpacePrivate(QColorSpace::NamedColorSpace namedColorSpace)
: namedColorSpace(namedColorSpace)
- , gamma(0.0f)
{
switch (namedColorSpace) {
case QColorSpace::SRgb:
@@ -191,11 +179,6 @@ QColorSpacePrivate::QColorSpacePrivate(QColorSpace::NamedColorSpace namedColorSp
transferFunction = QColorSpace::TransferFunction::ProPhotoRgb;
description = QStringLiteral("ProPhoto RGB");
break;
- case QColorSpace::Bt2020:
- primaries = QColorSpace::Primaries::Bt2020;
- transferFunction = QColorSpace::TransferFunction::Bt2020;
- description = QStringLiteral("BT.2020");
- break;
default:
Q_UNREACHABLE();
}
@@ -277,14 +260,6 @@ void QColorSpacePrivate::identifyColorSpace()
}
}
break;
- case QColorSpace::Primaries::Bt2020:
- if (transferFunction == QColorSpace::TransferFunction::Bt2020) {
- namedColorSpace = QColorSpace::Bt2020;
- if (description.isEmpty())
- description = QStringLiteral("BT.2020");
- return;
- }
- break;
default:
break;
}
@@ -301,7 +276,7 @@ void QColorSpacePrivate::initialize()
void QColorSpacePrivate::setToXyzMatrix()
{
if (primaries == QColorSpace::Primaries::Custom) {
- toXyz = QColorMatrix::null();
+ toXyz = QColorMatrix();
whitePoint = QColorVector::D50();
return;
}
@@ -335,12 +310,6 @@ void QColorSpacePrivate::setTransferFunction()
if (qFuzzyIsNull(gamma))
gamma = 1.8f;
break;
- case QColorSpace::TransferFunction::Bt2020:
- trc[0].m_type = QColorTrc::Type::Function;
- trc[0].m_fun = QColorTransferFunction::fromBt2020();
- if (qFuzzyIsNull(gamma))
- gamma = 1.961f;
- break;
case QColorSpace::TransferFunction::Custom:
break;
default:
@@ -415,8 +384,6 @@ QColorTransform QColorSpacePrivate::transformationToColorSpace(const QColorSpace
\l{http://www.color.org/chardata/rgb/DCIP3.xalter}{ICC registration of DCI-P3}
\value ProPhotoRgb The Pro Photo RGB color space, also known as ROMM RGB is a very wide gamut color space.
\l{http://www.color.org/chardata/rgb/rommrgb.xalter}{ICC registration of ROMM RGB}
- \value Bt2020 BT.2020 also known as Rec.2020 is the color space of HDR TVs.
- \l{http://www.color.org/chardata/rgb/BT2020.xalter}{ICC registration of BT.2020}
*/
/*!
@@ -429,7 +396,6 @@ QColorTransform QColorSpacePrivate::transformationToColorSpace(const QColorSpace
\value AdobeRgb The Adobe RGB primaries
\value DciP3D65 The DCI-P3 primaries with the D65 whitepoint
\value ProPhotoRgb The ProPhoto RGB primaries with the D50 whitepoint
- \value Bt2020 The BT.2020 primaries
*/
/*!
@@ -442,7 +408,6 @@ QColorTransform QColorSpacePrivate::transformationToColorSpace(const QColorSpace
\value Gamma A transfer function that is a real gamma curve based on the value of gamma()
\value SRgb The sRGB transfer function, composed of linear and gamma parts
\value ProPhotoRgb The ProPhoto RGB transfer function, composed of linear and gamma parts
- \value Bt2020 The BT.2020 transfer function, composed of linear and gamma parts
*/
/*!
@@ -457,7 +422,7 @@ QColorSpace::QColorSpace()
*/
QColorSpace::QColorSpace(NamedColorSpace namedColorSpace)
{
- static QColorSpacePrivate *predefinedColorspacePrivates[QColorSpace::Bt2020 + 1];
+ static QColorSpacePrivate *predefinedColorspacePrivates[QColorSpace::ProPhotoRgb + 1];
if (!predefinedColorspacePrivates[namedColorSpace]) {
predefinedColorspacePrivates[namedColorSpace] = new QColorSpacePrivate(namedColorSpace);
predefinedColorspacePrivates[namedColorSpace]->ref.ref();
diff --git a/src/gui/painting/qcolorspace.h b/src/gui/painting/qcolorspace.h
index 11987b9a37..e6bc62d58a 100644
--- a/src/gui/painting/qcolorspace.h
+++ b/src/gui/painting/qcolorspace.h
@@ -59,8 +59,7 @@ public:
SRgbLinear,
AdobeRgb,
DisplayP3,
- ProPhotoRgb,
- Bt2020,
+ ProPhotoRgb
};
Q_ENUM(NamedColorSpace)
enum class Primaries {
@@ -68,8 +67,7 @@ public:
SRgb,
AdobeRgb,
DciP3D65,
- ProPhotoRgb,
- Bt2020,
+ ProPhotoRgb
};
Q_ENUM(Primaries)
enum class TransferFunction {
@@ -77,8 +75,7 @@ public:
Linear,
Gamma,
SRgb,
- ProPhotoRgb,
- Bt2020,
+ ProPhotoRgb
};
Q_ENUM(TransferFunction)
diff --git a/src/gui/painting/qcolorspace_p.h b/src/gui/painting/qcolorspace_p.h
index c06681df6b..e7add19ed3 100644
--- a/src/gui/painting/qcolorspace_p.h
+++ b/src/gui/painting/qcolorspace_p.h
@@ -124,9 +124,9 @@ public:
static constexpr QColorSpace::NamedColorSpace Unknown = QColorSpace::NamedColorSpace(0);
QColorSpace::NamedColorSpace namedColorSpace = Unknown;
- QColorSpace::Primaries primaries;
- QColorSpace::TransferFunction transferFunction;
- float gamma;
+ QColorSpace::Primaries primaries = QColorSpace::Primaries::Custom;
+ QColorSpace::TransferFunction transferFunction = QColorSpace::TransferFunction::Custom;
+ float gamma = 0.0f;
QColorVector whitePoint;
QColorTrc trc[3];
diff --git a/src/gui/painting/qcolortransferfunction_p.h b/src/gui/painting/qcolortransferfunction_p.h
index fd7cfa2b2b..0575dbd888 100644
--- a/src/gui/painting/qcolortransferfunction_p.h
+++ b/src/gui/painting/qcolortransferfunction_p.h
@@ -130,10 +130,6 @@ public:
{
return QColorTransferFunction(1.0f / 1.055f, 0.055f / 1.055f, 1.0f / 12.92f, 0.04045f, 0.0f, 0.0f, 2.4f);
}
- static QColorTransferFunction fromBt2020()
- {
- return QColorTransferFunction(1.0f / 1.0993f, 0.0993f / 1.0993f, 1.0f / 4.5f, 0.08145f, 0.0f, 0.0f, 2.2f);
- }
static QColorTransferFunction fromProPhotoRgb()
{
return QColorTransferFunction(1.0f, 0.0f, 1.0f / 16.0f, 16.0f / 512.0f, 0.0f, 0.0f, 1.8f);
diff --git a/src/gui/painting/qcolortransform.cpp b/src/gui/painting/qcolortransform.cpp
index 53fd1dfbaa..10ccefed74 100644
--- a/src/gui/painting/qcolortransform.cpp
+++ b/src/gui/painting/qcolortransform.cpp
@@ -612,6 +612,15 @@ static void storeOpaque(QRgba64 *dst, const QRgba64 *src, const QColorVector *bu
static constexpr qsizetype WorkBlockSize = 256;
+template <typename T, int Count = 1>
+class QUninitialized
+{
+public:
+ operator T*() { return reinterpret_cast<T *>(this); }
+private:
+ alignas(T) char data[sizeof(T) * Count];
+};
+
template<typename T>
void QColorTransformPrivate::apply(T *dst, const T *src, qsizetype count, TransformFlags flags) const
{
@@ -623,7 +632,8 @@ void QColorTransformPrivate::apply(T *dst, const T *src, qsizetype count, Transf
bool doApplyMatrix = (colorMatrix != QColorMatrix::identity());
- QColorVector buffer[WorkBlockSize];
+ QUninitialized<QColorVector, WorkBlockSize> buffer;
+
qsizetype i = 0;
while (i < count) {
const qsizetype len = qMin(count - i, WorkBlockSize);
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index c17bf2ddfd..edb363ac69 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -669,8 +669,7 @@ static void QT_FASTCALL rbSwap_rgb30(uchar *d, const uchar *s, int count)
{
const uint *src = reinterpret_cast<const uint *>(s);
uint *dest = reinterpret_cast<uint *>(d);
- for (int i = 0; i < count; ++i)
- dest[i] = qRgbSwapRgb30(src[i]);
+ UNALIASED_CONVERSION_LOOP(dest, src, count, qRgbSwapRgb30);
}
template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixelLayoutRGB()
@@ -6774,6 +6773,9 @@ static void qInitDrawhelperFunctions()
qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_ssse3;
qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_ssse3;
sourceFetchUntransformed[QImage::Format_RGB888] = qt_fetchUntransformed_888_ssse3;
+ extern void QT_FASTCALL rbSwap_888_ssse3(uchar *dst, const uchar *src, int count);
+ qPixelLayouts[QImage::Format_RGB888].rbSwap = rbSwap_888_ssse3;
+ qPixelLayouts[QImage::Format_BGR888].rbSwap = rbSwap_888_ssse3;
}
#endif // SSSE3
diff --git a/src/gui/painting/qdrawhelper_ssse3.cpp b/src/gui/painting/qdrawhelper_ssse3.cpp
index 35d61c3e6c..14d7047bb6 100644
--- a/src/gui/painting/qdrawhelper_ssse3.cpp
+++ b/src/gui/painting/qdrawhelper_ssse3.cpp
@@ -40,7 +40,7 @@
#include <private/qdrawhelper_x86_p.h>
-#ifdef QT_COMPILER_SUPPORTS_SSSE3
+#if defined(QT_COMPILER_SUPPORTS_SSSE3)
#include <private/qdrawingprimitive_sse2_p.h>
@@ -254,6 +254,49 @@ void qt_memfill24_ssse3(quint24 *dest, quint24 color, qsizetype count)
}
}
+void QT_FASTCALL rbSwap_888_ssse3(uchar *dst, const uchar *src, int count)
+{
+ int i = 0;
+
+ const static __m128i shuffleMask1 = _mm_setr_epi8(2, 1, 0, 5, 4, 3, 8, 7, 6, 11, 10, 9, 14, 13, 12, /*!!*/15);
+ const static __m128i shuffleMask2 = _mm_setr_epi8(0, /*!!*/1, 4, 3, 2, 7, 6, 5, 10, 9, 8, 13, 12, 11, /*!!*/14, 15);
+ const static __m128i shuffleMask3 = _mm_setr_epi8(/*!!*/0, 3, 2, 1, 6, 5, 4, 9, 8, 7, 12, 11, 10, 15, 14, 13);
+
+ for (; i + 15 < count; i += 16) {
+ __m128i s1 = _mm_loadu_si128((const __m128i *)src);
+ __m128i s2 = _mm_loadu_si128((const __m128i *)(src + 16));
+ __m128i s3 = _mm_loadu_si128((const __m128i *)(src + 32));
+ s1 = _mm_shuffle_epi8(s1, shuffleMask1);
+ s2 = _mm_shuffle_epi8(s2, shuffleMask2);
+ s3 = _mm_shuffle_epi8(s3, shuffleMask3);
+ _mm_storeu_si128((__m128i *)dst, s1);
+ _mm_storeu_si128((__m128i *)(dst + 16), s2);
+ _mm_storeu_si128((__m128i *)(dst + 32), s3);
+
+ // Now fix the last four misplaced values
+ std::swap(dst[15], dst[17]);
+ std::swap(dst[30], dst[32]);
+
+ src += 48;
+ dst += 48;
+ }
+
+ if (src != dst) {
+ SIMD_EPILOGUE(i, count, 15) {
+ dst[0] = src[2];
+ dst[1] = src[1];
+ dst[2] = src[0];
+ dst += 3;
+ src += 3;
+ }
+ } else {
+ SIMD_EPILOGUE(i, count, 15) {
+ std::swap(dst[0], dst[2]);
+ dst += 3;
+ }
+ }
+}
+
QT_END_NAMESPACE
#endif // QT_COMPILER_SUPPORTS_SSSE3
diff --git a/src/gui/painting/qicc.cpp b/src/gui/painting/qicc.cpp
index 45b64de960..18f212f8e9 100644
--- a/src/gui/painting/qicc.cpp
+++ b/src/gui/painting/qicc.cpp
@@ -687,9 +687,6 @@ bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace)
} else if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromDciP3D65()) {
qCDebug(lcIcc) << "fromIccProfile: DCI-P3 D65 primaries detected";
colorspaceDPtr->primaries = QColorSpace::Primaries::DciP3D65;
- } else if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromBt2020()) {
- qCDebug(lcIcc) << "fromIccProfile: BT.2020 primaries detected";
- colorspaceDPtr->primaries = QColorSpace::Primaries::Bt2020;
}
if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromProPhotoRgb()) {
qCDebug(lcIcc) << "fromIccProfile: ProPhoto RGB primaries detected";
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index c71d82546a..601dc97be1 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -446,14 +446,22 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
d_ptr->blitter->setRedBlueSwizzle(false);
}
- // There is no way to tell if the OpenGL-rendered content is premultiplied or not.
- // For compatibility, assume that it is not, and use normal alpha blend always.
- if (d_ptr->premultiplied)
- funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
-
// Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
+ bool blendIsPremultiplied = d_ptr->premultiplied;
for (int i = 0; i < textures->count(); ++i) {
- if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
+ const QPlatformTextureList::Flags flags = textures->flags(i);
+ if (flags.testFlag(QPlatformTextureList::NeedsPremultipliedAlphaBlending)) {
+ if (!blendIsPremultiplied) {
+ funcs->glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
+ blendIsPremultiplied = true;
+ }
+ } else {
+ if (blendIsPremultiplied) {
+ funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
+ blendIsPremultiplied = false;
+ }
+ }
+ if (flags.testFlag(QPlatformTextureList::StacksOnTop))
blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset, canUseSrgb);
}
diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h
index 414d2bf0de..4f08b0092f 100644
--- a/src/gui/painting/qplatformbackingstore.h
+++ b/src/gui/painting/qplatformbackingstore.h
@@ -81,7 +81,8 @@ class Q_GUI_EXPORT QPlatformTextureList : public QObject
public:
enum Flag {
StacksOnTop = 0x01,
- TextureIsSrgb = 0x02
+ TextureIsSrgb = 0x02,
+ NeedsPremultipliedAlphaBlending = 0x04
};
Q_DECLARE_FLAGS(Flags, Flag)
diff --git a/src/gui/rhi/cs_tdr.h b/src/gui/rhi/cs_tdr.h
new file mode 100644
index 0000000000..f80cb3a498
--- /dev/null
+++ b/src/gui/rhi/cs_tdr.h
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Gui module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qglobal.h>
+
+#ifdef Q_OS_WIN
+
+#include <qt_windows.h>
+
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ConstantBuffer
+// {
+//
+// uint zero; // Offset: 0 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// uav UAV uint buf u0 1
+// ConstantBuffer cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// no Input
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// no Output
+cs_5_0
+dcl_globalFlags refactoringAllowed
+dcl_constantbuffer CB0[1], immediateIndexed
+dcl_uav_typed_buffer (uint,uint,uint,uint) u0
+dcl_input vThreadID.x
+dcl_thread_group 256, 1, 1
+loop
+ breakc_nz cb0[0].x
+ store_uav_typed u0.xyzw, vThreadID.xxxx, cb0[0].xxxx
+endloop
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_killDeviceByTimingOut[] =
+{
+ 68, 88, 66, 67, 217, 62,
+ 220, 38, 136, 51, 86, 245,
+ 161, 96, 18, 35, 141, 17,
+ 26, 13, 1, 0, 0, 0,
+ 164, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 100, 1, 0, 0, 116, 1,
+ 0, 0, 132, 1, 0, 0,
+ 8, 2, 0, 0, 82, 68,
+ 69, 70, 40, 1, 0, 0,
+ 1, 0, 0, 0, 144, 0,
+ 0, 0, 2, 0, 0, 0,
+ 60, 0, 0, 0, 0, 5,
+ 83, 67, 0, 1, 0, 0,
+ 0, 1, 0, 0, 82, 68,
+ 49, 49, 60, 0, 0, 0,
+ 24, 0, 0, 0, 32, 0,
+ 0, 0, 40, 0, 0, 0,
+ 36, 0, 0, 0, 12, 0,
+ 0, 0, 0, 0, 0, 0,
+ 124, 0, 0, 0, 4, 0,
+ 0, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 128, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 117, 97,
+ 118, 0, 67, 111, 110, 115,
+ 116, 97, 110, 116, 66, 117,
+ 102, 102, 101, 114, 0, 171,
+ 128, 0, 0, 0, 1, 0,
+ 0, 0, 168, 0, 0, 0,
+ 16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 208, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0,
+ 2, 0, 0, 0, 220, 0,
+ 0, 0, 0, 0, 0, 0,
+ 255, 255, 255, 255, 0, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 122, 101,
+ 114, 111, 0, 100, 119, 111,
+ 114, 100, 0, 171, 0, 0,
+ 19, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 213, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46,
+ 49, 0, 73, 83, 71, 78,
+ 8, 0, 0, 0, 0, 0,
+ 0, 0, 8, 0, 0, 0,
+ 79, 83, 71, 78, 8, 0,
+ 0, 0, 0, 0, 0, 0,
+ 8, 0, 0, 0, 83, 72,
+ 69, 88, 124, 0, 0, 0,
+ 80, 0, 5, 0, 31, 0,
+ 0, 0, 106, 8, 0, 1,
+ 89, 0, 0, 4, 70, 142,
+ 32, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 156, 8,
+ 0, 4, 0, 224, 17, 0,
+ 0, 0, 0, 0, 68, 68,
+ 0, 0, 95, 0, 0, 2,
+ 18, 0, 2, 0, 155, 0,
+ 0, 4, 0, 1, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 48, 0, 0, 1,
+ 3, 0, 4, 4, 10, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 164, 0,
+ 0, 7, 242, 224, 17, 0,
+ 0, 0, 0, 0, 6, 0,
+ 2, 0, 6, 128, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 22, 0, 0, 1,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 148, 0, 0, 0,
+ 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0
+};
+
+#endif // Q_OS_WIN
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index 4414b61d55..858be0159b 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -439,6 +439,18 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
visible in external GPU debugging tools will not be available and functions
like QRhiCommandBuffer::debugMarkBegin() will become a no-op. Avoid
enabling in production builds as it may involve a performance penalty.
+
+ \value PreferSoftwareRenderer Indicates that backends should prefer
+ choosing an adapter or physical device that renders in software on the CPU.
+ For example, with Direct3D there is typically a "Basic Render Driver"
+ adapter available with \c{DXGI_ADAPTER_FLAG_SOFTWARE}. Setting this flag
+ requests the backend to choose that adapter over any other, as long as no
+ specific adapter was forced by other backend-specific means. With Vulkan
+ this maps to preferring physical devices with
+ \c{VK_PHYSICAL_DEVICE_TYPE_CPU}. When not available, or when it is not
+ possible to decide if an adapter/device is software-based, this flag is
+ ignored. It may also be ignored with graphics APIs that have no concept and
+ means of enumerating adapters/devices.
*/
/*!
@@ -455,8 +467,8 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
\value FrameOpDeviceLost The graphics device was lost. This can be
recoverable by attempting to repeat the operation (such as, beginFrame())
- and releasing and reinitializing all objects backed by native graphics
- resources.
+ after releasing and reinitializing all objects backed by native graphics
+ resources. See isDeviceLost().
*/
/*!
@@ -673,7 +685,7 @@ bool operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClear
*/
uint qHash(const QRhiDepthStencilClearValue &v, uint seed) Q_DECL_NOTHROW
{
- return seed * (qFloor(v.depthClearValue() * 100) + v.stencilClearValue());
+ return seed * (uint(qFloor(qreal(v.depthClearValue()) * 100)) + v.stencilClearValue());
}
#ifndef QT_NO_DEBUG_STREAM
@@ -768,7 +780,8 @@ bool operator!=(const QRhiViewport &a, const QRhiViewport &b) Q_DECL_NOTHROW
uint qHash(const QRhiViewport &v, uint seed) Q_DECL_NOTHROW
{
const std::array<float, 4> r = v.viewport();
- return seed + r[0] + r[1] + r[2] + r[3] + qFloor(v.minDepth() * 100) + qFloor(v.maxDepth() * 100);
+ return seed + uint(r[0]) + uint(r[1]) + uint(r[2]) + uint(r[3])
+ + uint(qFloor(qreal(v.minDepth()) * 100)) + uint(qFloor(qreal(v.maxDepth()) * 100));
}
#ifndef QT_NO_DEBUG_STREAM
@@ -850,7 +863,7 @@ bool operator!=(const QRhiScissor &a, const QRhiScissor &b) Q_DECL_NOTHROW
uint qHash(const QRhiScissor &v, uint seed) Q_DECL_NOTHROW
{
const std::array<int, 4> r = v.scissor();
- return seed + r[0] + r[1] + r[2] + r[3];
+ return seed + uint(r[0]) + uint(r[1]) + uint(r[2]) + uint(r[3]);
}
#ifndef QT_NO_DEBUG_STREAM
@@ -1136,7 +1149,7 @@ bool operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribut
*/
uint qHash(const QRhiVertexInputAttribute &v, uint seed) Q_DECL_NOTHROW
{
- return seed + v.binding() + v.location() + v.format() + v.offset();
+ return seed + uint(v.binding()) + uint(v.location()) + uint(v.format()) + v.offset();
}
#ifndef QT_NO_DEBUG_STREAM
@@ -3001,7 +3014,7 @@ bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBind
uint qHash(const QRhiShaderResourceBinding &b, uint seed) Q_DECL_NOTHROW
{
const char *u = reinterpret_cast<const char *>(&b.d->u);
- return seed + b.d->binding + 10 * b.d->stage + 100 * b.d->type
+ return seed + uint(b.d->binding) + 10 * uint(b.d->stage) + 100 * uint(b.d->type)
+ qHash(QByteArray::fromRawData(u, sizeof(b.d->u)), seed);
}
@@ -3457,10 +3470,18 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
Flag values to describe swapchain properties
\value SurfaceHasPreMulAlpha Indicates that the target surface has
- transparency with premultiplied alpha.
+ transparency with premultiplied alpha. For example, this is what Qt Quick
+ uses when the alpha channel is enabled on the target QWindow, because the
+ scenegraph rendrerer always outputs fragments with alpha multiplied into
+ the red, green, and blue values. To ensure identical behavior across
+ platforms, always set QSurfaceFormat::alphaBufferSize() to a non-zero value
+ on the target QWindow whenever this flag is set on the swapchain.
\value SurfaceHasNonPreMulAlpha Indicates the target surface has
- transparencyt with non-premultiplied alpha.
+ transparency with non-premultiplied alpha. Be aware that this may not be
+ supported on some systems, if the system compositor always expects content
+ with premultiplied alpha. In that case the behavior with this flag set is
+ expected to be equivalent to SurfaceHasPreMulAlpha.
\value sRGB Requests to pick an sRGB format for the swapchain and/or its
render target views, where applicable. Note that this implies that sRGB
@@ -3823,8 +3844,8 @@ void QRhiImplementation::compressedFormatInfo(QRhiTexture::Format format, const
break;
}
- const quint32 wblocks = (size.width() + xdim - 1) / xdim;
- const quint32 hblocks = (size.height() + ydim - 1) / ydim;
+ const quint32 wblocks = uint((size.width() + xdim - 1) / xdim);
+ const quint32 hblocks = uint((size.height() + ydim - 1) / ydim);
if (bpl)
*bpl = wblocks * blockSize;
@@ -3880,9 +3901,9 @@ void QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSi
}
if (bpl)
- *bpl = size.width() * bpc;
+ *bpl = uint(size.width()) * bpc;
if (byteSize)
- *byteSize = size.width() * size.height() * bpc;
+ *byteSize = uint(size.width() * size.height()) * bpc;
}
// Approximate because it excludes subresource alignment or multisampling.
@@ -3892,12 +3913,12 @@ quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format,
quint32 approxSize = 0;
for (int level = 0; level < mipCount; ++level) {
quint32 byteSize = 0;
- const QSize size(qFloor(float(qMax(1, baseSize.width() >> level))),
- qFloor(float(qMax(1, baseSize.height() >> level))));
+ const QSize size(qFloor(qreal(qMax(1, baseSize.width() >> level))),
+ qFloor(qreal(qMax(1, baseSize.height() >> level))));
textureFormatInfo(format, size, nullptr, &byteSize);
approxSize += byteSize;
}
- approxSize *= layerCount;
+ approxSize *= uint(layerCount);
return approxSize;
}
@@ -5001,10 +5022,17 @@ const QRhiNativeHandles *QRhi::nativeHandles()
has to ensure external OpenGL code provided by the application can still
run like it did before with direct usage of OpenGL, as long as the QRhi is
using the OpenGL backend.
+
+ \return false when failed, similarly to QOpenGLContext::makeCurrent(). When
+ the operation failed, isDeviceLost() can be called to determine if there
+ was a loss of context situation. Such a check is equivalent to checking via
+ QOpenGLContext::isValid().
+
+ \sa QOpenGLContext::makeCurrent(), QOpenGLContext::isValid()
*/
-void QRhi::makeThreadLocalNativeContextCurrent()
+bool QRhi::makeThreadLocalNativeContextCurrent()
{
- d->makeThreadLocalNativeContextCurrent();
+ return d->makeThreadLocalNativeContextCurrent();
}
/*!
@@ -5020,6 +5048,70 @@ QRhiProfiler *QRhi::profiler()
}
/*!
+ Attempts to release resources in the backend's caches. This can include both
+ CPU and GPU resources. Only memory and resources that can be recreated
+ automatically are in scope. As an example, if the backend's
+ QRhiGraphicsPipeline implementation maintains a cache of shader compilation
+ results, calling this function leads to emptying that cache, thus
+ potentially freeing up memory and graphics resources.
+
+ Calling this function makes sense in resource constrained environments,
+ where at a certain point there is a need to ensure minimal resource usage,
+ at the expense of performance.
+ */
+void QRhi::releaseCachedResources()
+{
+ d->releaseCachedResources();
+}
+
+/*!
+ \return true if the graphics device was lost.
+
+ The loss of the device is typically detected in beginFrame(), endFrame() or
+ QRhiSwapChain::buildOrResize(), depending on the backend and the underlying
+ native APIs. The most common is endFrame() because that is where presenting
+ happens. With some backends QRhiSwapChain::buildOrResize() can also fail
+ due to a device loss. Therefore this function is provided as a generic way
+ to check if a device loss was detected by a previous operation.
+
+ When the device is lost, no further operations should be done via the QRhi.
+ Rather, all QRhi resources should be released, followed by destroying the
+ QRhi. A new QRhi can then be attempted to be created. If successful, all
+ graphics resources must be reinitialized. If not, try again later,
+ repeatedly.
+
+ While simple applications may decide to not care about device loss,
+ on the commonly used desktop platforms a device loss can happen
+ due to a variety of reasons, including physically disconnecting the
+ graphics adapter, disabling the device or driver, uninstalling or upgrading
+ the graphics driver, or due to errors that lead to a graphics device reset.
+ Some of these can happen under perfectly normal circumstances as well, for
+ example the upgrade of the graphics driver to a newer version is a common
+ task that can happen at any time while a Qt application is running. Users
+ may very well expect applications to be able to survive this, even when the
+ application is actively using an API like OpenGL or Direct3D.
+
+ Qt's own frameworks built on top of QRhi, such as, Qt Quick, can be
+ expected to handle and take appropriate measures when a device loss occurs.
+ If the data for graphics resources, such as textures and buffers, are still
+ available on the CPU side, such an event may not be noticeable on the
+ application level at all since graphics resources can seamlessly be
+ reinitialized then. However, applications and libraries working directly
+ with QRhi are expected to be prepared to check and handle device loss
+ situations themselves.
+
+ \note With OpenGL, applications may need to opt-in to context reset
+ notifications by setting QSurfaceFormat::ResetNotification on the
+ QOpenGLContext. This is typically done by enabling the flag in
+ QRhiGles2InitParams::format. Keep in mind however that some systems may
+ generate context resets situations even when this flag is not set.
+ */
+bool QRhi::isDeviceLost() const
+{
+ return d->isDeviceLost();
+}
+
+/*!
\return a new graphics pipeline resource.
\sa QRhiResource::release()
@@ -5180,7 +5272,17 @@ QRhiSwapChain *QRhi::newSwapChain()
\endlist
- \sa endFrame(), beginOffscreenFrame()
+ \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
+ value on failure. Some of these should be treated as soft, "try again
+ later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
+ the swapchain is to be resized or updated by calling
+ QRhiSwapChain::buildOrResize(). The application should then attempt to
+ generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
+ lost but this may also be recoverable by releasing all resources, including
+ the QRhi itself, and then recreating all resources. See isDeviceLost() for
+ further discussion.
+
+ \sa endFrame(), beginOffscreenFrame(), isDeviceLost()
*/
QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
{
@@ -5205,7 +5307,17 @@ QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags f
Passing QRhi::SkipPresent skips queuing the Present command or calling
swapBuffers.
- \sa beginFrame()
+ \return QRhi::FrameOpSuccess on success, or another QRhi::FrameOpResult
+ value on failure. Some of these should be treated as soft, "try again
+ later" type of errors: When QRhi::FrameOpSwapChainOutOfDate is returned,
+ the swapchain is to be resized or updated by calling
+ QRhiSwapChain::buildOrResize(). The application should then attempt to
+ generate a new frame. QRhi::FrameOpDeviceLost means the graphics device is
+ lost but this may also be recoverable by releasing all resources, including
+ the QRhi itself, and then recreating all resources. See isDeviceLost() for
+ further discussion.
+
+ \sa beginFrame(), isDeviceLost()
*/
QRhi::FrameOpResult QRhi::endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags)
{
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index 2d36c19e99..c73f03cf72 100644
--- a/src/gui/rhi/qrhi_p.h
+++ b/src/gui/rhi/qrhi_p.h
@@ -1294,7 +1294,8 @@ public:
enum Flag {
EnableProfiling = 1 << 0,
- EnableDebugMarkers = 1 << 1
+ EnableDebugMarkers = 1 << 1,
+ PreferSoftwareRenderer = 1 << 2
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -1413,13 +1414,17 @@ public:
int resourceLimit(ResourceLimit limit) const;
const QRhiNativeHandles *nativeHandles();
- void makeThreadLocalNativeContextCurrent();
+ bool makeThreadLocalNativeContextCurrent();
QRhiProfiler *profiler();
static const int MAX_LAYERS = 6; // cubemaps only
static const int MAX_LEVELS = 16; // a width and/or height of 65536 should be enough for everyone
+ void releaseCachedResources();
+
+ bool isDeviceLost() const;
+
protected:
QRhi();
diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h
index 0914cf268b..63f27b6de4 100644
--- a/src/gui/rhi/qrhi_p_p.h
+++ b/src/gui/rhi/qrhi_p_p.h
@@ -156,7 +156,9 @@ public:
virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0;
virtual const QRhiNativeHandles *nativeHandles() = 0;
virtual void sendVMemStatsToProfiler() = 0;
- virtual void makeThreadLocalNativeContextCurrent() = 0;
+ virtual bool makeThreadLocalNativeContextCurrent() = 0;
+ virtual void releaseCachedResources() = 0;
+ virtual bool isDeviceLost() const = 0;
bool isCompressedFormat(QRhiTexture::Format format) const;
void compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
@@ -205,6 +207,8 @@ public:
QRhi *q;
+ static const int MAX_SHADER_CACHE_ENTRIES = 128;
+
protected:
bool debugMarkers = false;
int currentFrameSlot = 0; // for vk, mtl, and similar. unused by gl and d3d11.
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 3e136cdb80..1d2f3cfa80 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -36,6 +36,7 @@
#include "qrhid3d11_p_p.h"
#include "qshader_p.h"
+#include "cs_tdr.h"
#include <QWindow>
#include <QOperatingSystemVersion>
#include <qmath.h>
@@ -118,10 +119,20 @@ QT_BEGIN_NAMESPACE
\c{ID3D11Texture2D *}.
*/
+// help mingw with its ancient sdk headers
+#ifndef DXGI_ADAPTER_FLAG_SOFTWARE
+#define DXGI_ADAPTER_FLAG_SOFTWARE 2
+#endif
+
QRhiD3D11::QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice)
- : ofr(this)
+ : ofr(this),
+ deviceCurse(this)
{
debugLayer = params->enableDebugLayer;
+
+ deviceCurse.framesToActivate = params->framesUntilKillingDeviceViaTdr;
+ deviceCurse.permanent = params->repeatDeviceKill;
+
importedDevice = importDevice != nullptr;
if (importedDevice) {
dev = reinterpret_cast<ID3D11Device *>(importDevice->dev);
@@ -155,7 +166,7 @@ static QString comErrorMessage(HRESULT hr)
}
template <class Int>
-static inline Int aligned(Int v, Int byteAlign)
+inline Int aligned(Int v, Int byteAlign)
{
return (v + byteAlign - 1) & ~(byteAlign - 1);
}
@@ -166,7 +177,7 @@ static IDXGIFactory1 *createDXGIFactory2()
if (QOperatingSystemVersion::current() > QOperatingSystemVersion::Windows7) {
using PtrCreateDXGIFactory2 = HRESULT (WINAPI *)(UINT, REFIID, void **);
QSystemLibrary dxgilib(QStringLiteral("dxgi"));
- if (auto createDXGIFactory2 = (PtrCreateDXGIFactory2)dxgilib.resolve("CreateDXGIFactory2")) {
+ if (auto createDXGIFactory2 = reinterpret_cast<PtrCreateDXGIFactory2>(dxgilib.resolve("CreateDXGIFactory2"))) {
const HRESULT hr = createDXGIFactory2(0, IID_IDXGIFactory2, reinterpret_cast<void **>(&result));
if (FAILED(hr)) {
qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s", qPrintable(comErrorMessage(hr)));
@@ -221,11 +232,29 @@ bool QRhiD3D11::create(QRhi::Flags flags)
int requestedAdapterIndex = -1;
if (qEnvironmentVariableIsSet("QT_D3D_ADAPTER_INDEX"))
requestedAdapterIndex = qEnvironmentVariableIntValue("QT_D3D_ADAPTER_INDEX");
- for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
+
+ if (requestedAdapterIndex < 0 && flags.testFlag(QRhi::PreferSoftwareRenderer)) {
+ for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
+ DXGI_ADAPTER_DESC1 desc;
+ adapter->GetDesc1(&desc);
+ adapter->Release();
+ if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
+ requestedAdapterIndex = adapterIndex;
+ break;
+ }
+ }
+ }
+
+ for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
- const QString name = QString::fromUtf16((char16_t *) desc.Description);
- qCDebug(QRHI_LOG_INFO, "Adapter %d: '%s' (flags 0x%x)", adapterIndex, qPrintable(name), desc.Flags);
+ const QString name = QString::fromUtf16(reinterpret_cast<char16_t *>(desc.Description));
+ qCDebug(QRHI_LOG_INFO, "Adapter %d: '%s' (vendor 0x%X device 0x%X flags 0x%X)",
+ adapterIndex,
+ qPrintable(name),
+ desc.VendorId,
+ desc.DeviceId,
+ desc.Flags);
if (!adapterToUse && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
adapterToUse = adapter;
qCDebug(QRHI_LOG_INFO, " using this adapter");
@@ -261,16 +290,33 @@ bool QRhiD3D11::create(QRhi::Flags flags)
if (FAILED(context->QueryInterface(IID_ID3DUserDefinedAnnotation, reinterpret_cast<void **>(&annotations))))
annotations = nullptr;
+ deviceLost = false;
+
nativeHandlesStruct.dev = dev;
nativeHandlesStruct.context = context;
+ if (deviceCurse.framesToActivate > 0)
+ deviceCurse.initResources();
+
return true;
}
+void QRhiD3D11::clearShaderCache()
+{
+ for (Shader &s : m_shaderCache)
+ s.s->Release();
+
+ m_shaderCache.clear();
+}
+
void QRhiD3D11::destroy()
{
finishActiveReadbacks();
+ clearShaderCache();
+
+ deviceCurse.releaseResources();
+
if (annotations) {
annotations->Release();
annotations = nullptr;
@@ -322,9 +368,9 @@ DXGI_SAMPLE_DESC QRhiD3D11::effectiveSampleCount(int sampleCount) const
return desc;
}
- desc.Count = s;
+ desc.Count = UINT(s);
if (s > 1)
- desc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
+ desc.Quality = UINT(D3D11_STANDARD_MULTISAMPLE_PATTERN);
else
desc.Quality = 0;
@@ -456,9 +502,20 @@ void QRhiD3D11::sendVMemStatsToProfiler()
// nothing to do here
}
-void QRhiD3D11::makeThreadLocalNativeContextCurrent()
+bool QRhiD3D11::makeThreadLocalNativeContextCurrent()
{
- // nothing to do here
+ // not applicable
+ return false;
+}
+
+void QRhiD3D11::releaseCachedResources()
+{
+ clearShaderCache();
+}
+
+bool QRhiD3D11::isDeviceLost() const
+{
+ return deviceLost;
}
QRhiRenderBuffer *QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
@@ -640,7 +697,7 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
for (int i = 0; i < dynamicOffsetCount; ++i) {
const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
- const uint binding = dynOfs.first;
+ const uint binding = uint(dynOfs.first);
Q_ASSERT(aligned(dynOfs.second, quint32(256)) == dynOfs.second);
const uint offsetInConstants = dynOfs.second / 16;
*p++ = binding;
@@ -776,10 +833,10 @@ void QRhiD3D11::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
QD3D11CommandBuffer::Command cmd;
cmd.cmd = QD3D11CommandBuffer::Command::BlendConstants;
cmd.args.blendConstants.ps = QRHI_RES(QD3D11GraphicsPipeline, cbD->currentGraphicsPipeline);
- cmd.args.blendConstants.c[0] = c.redF();
- cmd.args.blendConstants.c[1] = c.greenF();
- cmd.args.blendConstants.c[2] = c.blueF();
- cmd.args.blendConstants.c[3] = c.alphaF();
+ cmd.args.blendConstants.c[0] = float(c.redF());
+ cmd.args.blendConstants.c[1] = float(c.greenF());
+ cmd.args.blendConstants.c[2] = float(c.blueF());
+ cmd.args.blendConstants.c[3] = float(c.alphaF());
cbD->commands.append(cmd);
}
@@ -977,8 +1034,14 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
if (!flags.testFlag(QRhi::SkipPresent)) {
const UINT presentFlags = 0;
HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
- if (FAILED(hr))
+ if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
+ qWarning("Device loss detected in Present()");
+ deviceLost = true;
+ return QRhi::FrameOpDeviceLost;
+ } else if (FAILED(hr)) {
qWarning("Failed to present: %s", qPrintable(comErrorMessage(hr)));
+ return QRhi::FrameOpError;
+ }
// move on to the next buffer
swapChainD->currentFrameSlot = (swapChainD->currentFrameSlot + 1) % QD3D11SwapChain::BUFFER_COUNT;
@@ -988,6 +1051,20 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
swapChainD->frameCount += 1;
contextState.currentSwapChain = nullptr;
+
+ if (deviceCurse.framesToActivate > 0) {
+ deviceCurse.framesLeft -= 1;
+ if (deviceCurse.framesLeft == 0) {
+ deviceCurse.framesLeft = deviceCurse.framesToActivate;
+ if (!deviceCurse.permanent)
+ deviceCurse.framesToActivate = -1;
+
+ deviceCurse.activate();
+ } else if (deviceCurse.framesLeft % 100 == 0) {
+ qDebug("Impending doom: %d frames left", deviceCurse.framesLeft);
+ }
+ }
+
return QRhi::FrameOpSuccess;
}
@@ -1161,7 +1238,7 @@ QRhi::FrameOpResult QRhiD3D11::finish()
void QRhiD3D11::enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc)
{
- UINT subres = D3D11CalcSubresource(level, layer, texD->mipLevelCount);
+ UINT subres = D3D11CalcSubresource(UINT(level), UINT(layer), texD->mipLevelCount);
const QPoint dp = subresDesc.destinationTopLeft();
D3D11_BOX box;
box.front = 0;
@@ -1192,13 +1269,13 @@ void QRhiD3D11::enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cb
} else {
cmd.args.updateSubRes.src = cbD->retainImage(img);
}
- box.left = dp.x();
- box.top = dp.y();
- box.right = dp.x() + size.width();
- box.bottom = dp.y() + size.height();
+ box.left = UINT(dp.x());
+ box.top = UINT(dp.y());
+ box.right = UINT(dp.x() + size.width());
+ box.bottom = UINT(dp.y() + size.height());
cmd.args.updateSubRes.hasDstBox = true;
cmd.args.updateSubRes.dstBox = box;
- cmd.args.updateSubRes.srcRowPitch = bpl;
+ cmd.args.updateSubRes.srcRowPitch = UINT(bpl);
} else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
: subresDesc.sourceSize();
@@ -1208,10 +1285,10 @@ void QRhiD3D11::enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cb
// Everything must be a multiple of the block width and
// height, so e.g. a mip level of size 2x2 will be 4x4 when it
// comes to the actual data.
- box.left = aligned(dp.x(), blockDim.width());
- box.top = aligned(dp.y(), blockDim.height());
- box.right = aligned(dp.x() + size.width(), blockDim.width());
- box.bottom = aligned(dp.y() + size.height(), blockDim.height());
+ box.left = UINT(aligned(dp.x(), blockDim.width()));
+ box.top = UINT(aligned(dp.y(), blockDim.height()));
+ box.right = UINT(aligned(dp.x() + size.width(), blockDim.width()));
+ box.bottom = UINT(aligned(dp.y() + size.height(), blockDim.height()));
cmd.args.updateSubRes.hasDstBox = true;
cmd.args.updateSubRes.dstBox = box;
cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
@@ -1220,12 +1297,11 @@ void QRhiD3D11::enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cb
const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
: subresDesc.sourceSize();
quint32 bpl = 0;
- QSize blockDim;
textureFormatInfo(texD->m_format, size, &bpl, nullptr);
- box.left = dp.x();
- box.top = dp.y();
- box.right = dp.x() + size.width();
- box.bottom = dp.y() + size.height();
+ box.left = UINT(dp.x());
+ box.top = UINT(dp.y());
+ box.right = UINT(dp.x() + size.width());
+ box.bottom = UINT(dp.y() + size.height());
cmd.args.updateSubRes.hasDstBox = true;
cmd.args.updateSubRes.dstBox = box;
cmd.args.updateSubRes.src = cbD->retainData(subresDesc.data());
@@ -1247,7 +1323,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
for (const QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate &u : ud->dynamicBufferUpdates) {
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, u.buf);
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
- memcpy(bufD->dynBuf.data() + u.offset, u.data.constData(), u.data.size());
+ memcpy(bufD->dynBuf.data() + u.offset, u.data.constData(), size_t(u.data.size()));
bufD->hasPendingDynamicUpdates = true;
}
@@ -1265,10 +1341,10 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
// since the ID3D11Buffer's size is rounded up to be a multiple of 256
// while the data we have has the original size.
D3D11_BOX box;
- box.left = u.offset;
+ box.left = UINT(u.offset);
box.top = box.front = 0;
box.back = box.bottom = 1;
- box.right = u.offset + u.data.size(); // no -1: right, bottom, back are exclusive, see D3D11_BOX doc
+ box.right = UINT(u.offset + u.data.size()); // no -1: right, bottom, back are exclusive, see D3D11_BOX doc
cmd.args.updateSubRes.hasDstBox = true;
cmd.args.updateSubRes.dstBox = box;
cbD->commands.append(cmd);
@@ -1287,25 +1363,25 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
Q_ASSERT(u.copy.src && u.copy.dst);
QD3D11Texture *srcD = QRHI_RES(QD3D11Texture, u.copy.src);
QD3D11Texture *dstD = QRHI_RES(QD3D11Texture, u.copy.dst);
- UINT srcSubRes = D3D11CalcSubresource(u.copy.desc.sourceLevel(), u.copy.desc.sourceLayer(), srcD->mipLevelCount);
- UINT dstSubRes = D3D11CalcSubresource(u.copy.desc.destinationLevel(), u.copy.desc.destinationLayer(), dstD->mipLevelCount);
+ UINT srcSubRes = D3D11CalcSubresource(UINT(u.copy.desc.sourceLevel()), UINT(u.copy.desc.sourceLayer()), srcD->mipLevelCount);
+ UINT dstSubRes = D3D11CalcSubresource(UINT(u.copy.desc.destinationLevel()), UINT(u.copy.desc.destinationLayer()), dstD->mipLevelCount);
const QPoint dp = u.copy.desc.destinationTopLeft();
const QSize size = u.copy.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.copy.desc.pixelSize();
const QPoint sp = u.copy.desc.sourceTopLeft();
D3D11_BOX srcBox;
- srcBox.left = sp.x();
- srcBox.top = sp.y();
+ srcBox.left = UINT(sp.x());
+ srcBox.top = UINT(sp.y());
srcBox.front = 0;
// back, right, bottom are exclusive
- srcBox.right = srcBox.left + size.width();
- srcBox.bottom = srcBox.top + size.height();
+ srcBox.right = srcBox.left + UINT(size.width());
+ srcBox.bottom = srcBox.top + UINT(size.height());
srcBox.back = 1;
QD3D11CommandBuffer::Command cmd;
cmd.cmd = QD3D11CommandBuffer::Command::CopySubRes;
cmd.args.copySubRes.dst = dstD->tex;
cmd.args.copySubRes.dstSubRes = dstSubRes;
- cmd.args.copySubRes.dstX = dp.x();
- cmd.args.copySubRes.dstY = dp.y();
+ cmd.args.copySubRes.dstX = UINT(dp.x());
+ cmd.args.copySubRes.dstY = UINT(dp.y());
cmd.args.copySubRes.src = srcD->tex;
cmd.args.copySubRes.srcSubRes = srcSubRes;
cmd.args.copySubRes.hasSrcBox = true;
@@ -1333,7 +1409,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
dxgiFormat = texD->dxgiFormat;
pixelSize = u.read.rb.level() > 0 ? q->sizeForMipLevel(u.read.rb.level(), texD->m_pixelSize) : texD->m_pixelSize;
format = texD->m_format;
- subres = D3D11CalcSubresource(u.read.rb.level(), u.read.rb.layer(), texD->mipLevelCount);
+ subres = D3D11CalcSubresource(UINT(u.read.rb.level()), UINT(u.read.rb.layer()), texD->mipLevelCount);
} else {
Q_ASSERT(contextState.currentSwapChain);
swapChainD = QRHI_RES(QD3D11SwapChain, contextState.currentSwapChain);
@@ -1362,8 +1438,8 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
D3D11_TEXTURE2D_DESC desc;
memset(&desc, 0, sizeof(desc));
- desc.Width = pixelSize.width();
- desc.Height = pixelSize.height();
+ desc.Width = UINT(pixelSize.width());
+ desc.Height = UINT(pixelSize.height());
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = dxgiFormat;
@@ -1376,7 +1452,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
qWarning("Failed to create readback staging texture: %s", qPrintable(comErrorMessage(hr)));
return;
}
- QRHI_PROF_F(newReadbackBuffer(quint64(quintptr(stagingTex)),
+ QRHI_PROF_F(newReadbackBuffer(qint64(qintptr(stagingTex)),
texD ? static_cast<QRhiResource *>(texD) : static_cast<QRhiResource *>(swapChainD),
bufSize));
@@ -1419,7 +1495,7 @@ void QRhiD3D11::finishActiveReadbacks()
const QRhiD3D11::ActiveReadback &aRb(activeReadbacks[i]);
aRb.result->format = aRb.format;
aRb.result->pixelSize = aRb.pixelSize;
- aRb.result->data.resize(aRb.bufSize);
+ aRb.result->data.resize(int(aRb.bufSize));
D3D11_MAPPED_SUBRESOURCE mp;
HRESULT hr = context->Map(aRb.stagingTex, 0, D3D11_MAP_READ, 0, &mp);
@@ -1440,7 +1516,7 @@ void QRhiD3D11::finishActiveReadbacks()
context->Unmap(aRb.stagingTex, 0);
aRb.stagingTex->Release();
- QRHI_PROF_F(releaseReadbackBuffer(quint64(quintptr(aRb.stagingTex))));
+ QRHI_PROF_F(releaseReadbackBuffer(qint64(qintptr(aRb.stagingTex))));
if (aRb.result->completed)
completedCallbacks.append(aRb.result->completed);
@@ -1509,10 +1585,10 @@ void QRhiD3D11::beginPass(QRhiCommandBuffer *cb,
if (rtD->dsAttCount && wantsDsClear)
clearCmd.args.clear.mask |= QD3D11CommandBuffer::Command::Depth | QD3D11CommandBuffer::Command::Stencil;
- clearCmd.args.clear.c[0] = colorClearValue.redF();
- clearCmd.args.clear.c[1] = colorClearValue.greenF();
- clearCmd.args.clear.c[2] = colorClearValue.blueF();
- clearCmd.args.clear.c[3] = colorClearValue.alphaF();
+ clearCmd.args.clear.c[0] = float(colorClearValue.redF());
+ clearCmd.args.clear.c[1] = float(colorClearValue.greenF());
+ clearCmd.args.clear.c[2] = float(colorClearValue.blueF());
+ clearCmd.args.clear.c[3] = float(colorClearValue.alphaF());
clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
cbD->commands.append(clearCmd);
@@ -1543,8 +1619,8 @@ void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
QD3D11CommandBuffer::Command cmd;
cmd.cmd = QD3D11CommandBuffer::Command::ResolveSubRes;
cmd.args.resolveSubRes.dst = dstTexD->tex;
- cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(colorAtt.resolveLevel(),
- colorAtt.resolveLayer(),
+ cmd.args.resolveSubRes.dstSubRes = D3D11CalcSubresource(UINT(colorAtt.resolveLevel()),
+ UINT(colorAtt.resolveLayer()),
dstTexD->mipLevelCount);
if (srcTexD) {
cmd.args.resolveSubRes.src = srcTexD->tex;
@@ -1571,7 +1647,7 @@ void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
continue;
}
}
- cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, colorAtt.layer(), 1);
+ cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
cbD->commands.append(cmd);
}
@@ -1638,9 +1714,9 @@ void QRhiD3D11::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
QD3D11CommandBuffer::Command cmd;
cmd.cmd = QD3D11CommandBuffer::Command::Dispatch;
- cmd.args.dispatch.x = x;
- cmd.args.dispatch.y = y;
- cmd.args.dispatch.z = z;
+ cmd.args.dispatch.x = UINT(x);
+ cmd.args.dispatch.y = UINT(y);
+ cmd.args.dispatch.z = UINT(z);
cbD->commands.append(cmd);
}
@@ -1682,11 +1758,11 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
// dynamic ubuf offsets are not considered here, those are baked in
// at a later stage, which is good as vsubufoffsets and friends are
// per-srb, not per-setShaderResources call
- const uint offsetInConstants = b->u.ubuf.offset / 16;
+ const uint offsetInConstants = uint(b->u.ubuf.offset) / 16;
// size must be 16 mult. (in constants, i.e. multiple of 256 bytes).
// We can round up if needed since the buffers's actual size
// (ByteWidth) is always a multiple of 256.
- const uint sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256) / 16;
+ 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);
@@ -1804,7 +1880,7 @@ void QRhiD3D11::executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD)
D3D11_MAPPED_SUBRESOURCE mp;
HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
if (SUCCEEDED(hr)) {
- memcpy(mp.pData, bufD->dynBuf.constData(), bufD->dynBuf.size());
+ memcpy(mp.pData, bufD->dynBuf.constData(), size_t(bufD->dynBuf.size()));
context->Unmap(bufD->buffer, 0);
} else {
qWarning("Failed to map buffer: %s", qPrintable(comErrorMessage(hr)));
@@ -1817,13 +1893,13 @@ static void applyDynamicOffsets(QVarLengthArray<UINT, 4> *offsets,
QRhiBatchedBindings<UINT> *ubufoffsets,
const uint *dynOfsPairs, int dynOfsPairCount)
{
- const UINT count = ubufs->batches[batchIndex].resources.count();
+ const int count = ubufs->batches[batchIndex].resources.count();
const UINT startBinding = ubufs->batches[batchIndex].startBinding;
*offsets = ubufoffsets->batches[batchIndex].resources;
- for (UINT b = 0; b < count; ++b) {
+ for (int b = 0; b < count; ++b) {
for (int di = 0; di < dynOfsPairCount; ++di) {
const uint binding = dynOfsPairs[2 * di];
- if (binding == startBinding + b) {
+ if (binding == startBinding + UINT(b)) {
const uint offsetInConstants = dynOfsPairs[2 * di + 1];
(*offsets)[b] = offsetInConstants;
break;
@@ -1838,37 +1914,37 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
{
if (!offsetOnlyChange) {
for (const auto &batch : srbD->vssamplers.batches)
- context->VSSetSamplers(batch.startBinding, batch.resources.count(), batch.resources.constData());
+ context->VSSetSamplers(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData());
for (const auto &batch : srbD->vsshaderresources.batches) {
- context->VSSetShaderResources(batch.startBinding, batch.resources.count(), batch.resources.constData());
+ context->VSSetShaderResources(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData());
contextState.vsHighestActiveSrvBinding = qMax<int>(contextState.vsHighestActiveSrvBinding,
- batch.startBinding + batch.resources.count() - 1);
+ int(batch.startBinding) + batch.resources.count() - 1);
}
for (const auto &batch : srbD->fssamplers.batches)
- context->PSSetSamplers(batch.startBinding, batch.resources.count(), batch.resources.constData());
+ context->PSSetSamplers(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData());
for (const auto &batch : srbD->fsshaderresources.batches) {
- context->PSSetShaderResources(batch.startBinding, batch.resources.count(), batch.resources.constData());
+ context->PSSetShaderResources(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData());
contextState.fsHighestActiveSrvBinding = qMax<int>(contextState.fsHighestActiveSrvBinding,
- batch.startBinding + batch.resources.count() - 1);
+ int(batch.startBinding) + batch.resources.count() - 1);
}
for (const auto &batch : srbD->cssamplers.batches)
- context->CSSetSamplers(batch.startBinding, batch.resources.count(), batch.resources.constData());
+ context->CSSetSamplers(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData());
for (const auto &batch : srbD->csshaderresources.batches) {
- context->CSSetShaderResources(batch.startBinding, batch.resources.count(), batch.resources.constData());
+ context->CSSetShaderResources(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData());
contextState.csHighestActiveSrvBinding = qMax<int>(contextState.csHighestActiveSrvBinding,
- batch.startBinding + batch.resources.count() - 1);
+ int(batch.startBinding) + batch.resources.count() - 1);
}
}
for (int i = 0, ie = srbD->vsubufs.batches.count(); i != ie; ++i) {
if (!dynOfsPairCount) {
context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
- srbD->vsubufs.batches[i].resources.count(),
+ UINT(srbD->vsubufs.batches[i].resources.count()),
srbD->vsubufs.batches[i].resources.constData(),
srbD->vsubufoffsets.batches[i].resources.constData(),
srbD->vsubufsizes.batches[i].resources.constData());
@@ -1876,7 +1952,7 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
QVarLengthArray<UINT, 4> offsets;
applyDynamicOffsets(&offsets, i, &srbD->vsubufs, &srbD->vsubufoffsets, dynOfsPairs, dynOfsPairCount);
context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
- srbD->vsubufs.batches[i].resources.count(),
+ UINT(srbD->vsubufs.batches[i].resources.count()),
srbD->vsubufs.batches[i].resources.constData(),
offsets.constData(),
srbD->vsubufsizes.batches[i].resources.constData());
@@ -1886,7 +1962,7 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
for (int i = 0, ie = srbD->fsubufs.batches.count(); i != ie; ++i) {
if (!dynOfsPairCount) {
context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
- srbD->fsubufs.batches[i].resources.count(),
+ UINT(srbD->fsubufs.batches[i].resources.count()),
srbD->fsubufs.batches[i].resources.constData(),
srbD->fsubufoffsets.batches[i].resources.constData(),
srbD->fsubufsizes.batches[i].resources.constData());
@@ -1894,7 +1970,7 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
QVarLengthArray<UINT, 4> offsets;
applyDynamicOffsets(&offsets, i, &srbD->fsubufs, &srbD->fsubufoffsets, dynOfsPairs, dynOfsPairCount);
context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
- srbD->fsubufs.batches[i].resources.count(),
+ UINT(srbD->fsubufs.batches[i].resources.count()),
srbD->fsubufs.batches[i].resources.constData(),
offsets.constData(),
srbD->fsubufsizes.batches[i].resources.constData());
@@ -1904,7 +1980,7 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
for (int i = 0, ie = srbD->csubufs.batches.count(); i != ie; ++i) {
if (!dynOfsPairCount) {
context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
- srbD->csubufs.batches[i].resources.count(),
+ UINT(srbD->csubufs.batches[i].resources.count()),
srbD->csubufs.batches[i].resources.constData(),
srbD->csubufoffsets.batches[i].resources.constData(),
srbD->csubufsizes.batches[i].resources.constData());
@@ -1912,7 +1988,7 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
QVarLengthArray<UINT, 4> offsets;
applyDynamicOffsets(&offsets, i, &srbD->csubufs, &srbD->csubufoffsets, dynOfsPairs, dynOfsPairCount);
context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
- srbD->csubufs.batches[i].resources.count(),
+ UINT(srbD->csubufs.batches[i].resources.count()),
srbD->csubufs.batches[i].resources.constData(),
offsets.constData(),
srbD->csubufsizes.batches[i].resources.constData());
@@ -1921,13 +1997,13 @@ void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
for (int i = 0, ie = srbD->csUAVs.batches.count(); i != ie; ++i) {
const uint startBinding = srbD->csUAVs.batches[i].startBinding;
- const uint count = srbD->csUAVs.batches[i].resources.count();
+ const uint count = uint(srbD->csUAVs.batches[i].resources.count());
context->CSSetUnorderedAccessViews(startBinding,
count,
srbD->csUAVs.batches[i].resources.constData(),
nullptr);
contextState.csHighestActiveUavBinding = qMax<int>(contextState.csHighestActiveUavBinding,
- startBinding + count - 1);
+ int(startBinding + count - 1));
}
}
@@ -1951,7 +2027,7 @@ void QRhiD3D11::resetShaderResources()
QVarLengthArray<UINT, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> nulloffsets(count);
for (int i = 0; i < count; ++i)
nulloffsets[i] = 0;
- context->IASetVertexBuffers(0, count, nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
+ context->IASetVertexBuffers(0, UINT(count), nullbufs.constData(), nullstrides.constData(), nulloffsets.constData());
contextState.vsHighestActiveVertexBufferBinding = -1;
}
@@ -1964,15 +2040,15 @@ void QRhiD3D11::resetShaderResources()
for (int i = 0; i < nullsrvs.count(); ++i)
nullsrvs[i] = nullptr;
if (contextState.vsHighestActiveSrvBinding >= 0) {
- context->VSSetShaderResources(0, contextState.vsHighestActiveSrvBinding + 1, nullsrvs.constData());
+ context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
contextState.vsHighestActiveSrvBinding = -1;
}
if (contextState.fsHighestActiveSrvBinding >= 0) {
- context->PSSetShaderResources(0, contextState.fsHighestActiveSrvBinding + 1, nullsrvs.constData());
+ context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
contextState.fsHighestActiveSrvBinding = -1;
}
if (contextState.csHighestActiveSrvBinding >= 0) {
- context->CSSetShaderResources(0, contextState.csHighestActiveSrvBinding + 1, nullsrvs.constData());
+ context->CSSetShaderResources(0, UINT(contextState.csHighestActiveSrvBinding + 1), nullsrvs.constData());
contextState.csHighestActiveSrvBinding = -1;
}
}
@@ -1983,7 +2059,7 @@ void QRhiD3D11::resetShaderResources()
D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> nulluavs(nulluavCount);
for (int i = 0; i < nulluavCount; ++i)
nulluavs[i] = nullptr;
- context->CSSetUnorderedAccessViews(0, nulluavCount, nulluavs.constData(), nullptr);
+ context->CSSetUnorderedAccessViews(0, UINT(nulluavCount), nulluavs.constData(), nullptr);
contextState.csHighestActiveUavBinding = -1;
}
}
@@ -2005,7 +2081,7 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
// writing the first timestamp only afterwards.
context->Begin(tsDisjoint);
QD3D11RenderTargetData *rtD = rtData(&timestampSwapChain->rt);
- context->OMSetRenderTargets(rtD->colorAttCount, rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
+ context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
context->End(tsStart); // just record a timestamp, no Begin needed
}
}
@@ -2018,7 +2094,7 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
case QD3D11CommandBuffer::Command::SetRenderTarget:
{
QD3D11RenderTargetData *rtD = rtData(cmd.args.setRenderTarget.rt);
- context->OMSetRenderTargets(rtD->colorAttCount, rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
+ context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
}
break;
case QD3D11CommandBuffer::Command::Clear:
@@ -2034,7 +2110,7 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
if (cmd.args.clear.mask & QD3D11CommandBuffer::Command::Stencil)
ds |= D3D11_CLEAR_STENCIL;
if (ds)
- context->ClearDepthStencilView(rtD->dsv, ds, cmd.args.clear.d, cmd.args.clear.s);
+ context->ClearDepthStencilView(rtD->dsv, ds, cmd.args.clear.d, UINT8(cmd.args.clear.s));
}
break;
case QD3D11CommandBuffer::Command::Viewport:
@@ -2064,8 +2140,8 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
contextState.vsHighestActiveVertexBufferBinding = qMax<int>(
contextState.vsHighestActiveVertexBufferBinding,
cmd.args.bindVertexBuffers.startSlot + cmd.args.bindVertexBuffers.slotCount - 1);
- context->IASetVertexBuffers(cmd.args.bindVertexBuffers.startSlot,
- cmd.args.bindVertexBuffers.slotCount,
+ context->IASetVertexBuffers(UINT(cmd.args.bindVertexBuffers.startSlot),
+ UINT(cmd.args.bindVertexBuffers.slotCount),
cmd.args.bindVertexBuffers.buffers,
cmd.args.bindVertexBuffers.strides,
cmd.args.bindVertexBuffers.offsets);
@@ -2208,7 +2284,7 @@ static inline uint toD3DBufferUsage(QRhiBuffer::UsageFlags usage)
u |= D3D11_BIND_CONSTANT_BUFFER;
if (usage.testFlag(QRhiBuffer::StorageBuffer))
u |= D3D11_BIND_UNORDERED_ACCESS;
- return u;
+ return uint(u);
}
bool QD3D11Buffer::build()
@@ -2231,7 +2307,7 @@ bool QD3D11Buffer::build()
D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(desc));
- desc.ByteWidth = roundedSize;
+ desc.ByteWidth = UINT(roundedSize);
desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
desc.BindFlags = toD3DBufferUsage(m_usage);
desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
@@ -2250,10 +2326,10 @@ bool QD3D11Buffer::build()
}
if (!m_objectName.isEmpty())
- buffer->SetPrivateData(WKPDID_D3DDebugObjectName, m_objectName.size(), m_objectName.constData());
+ buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
QRHI_PROF;
- QRHI_PROF_F(newBuffer(this, roundedSize, m_type == Dynamic ? 2 : 1, m_type == Dynamic ? 1 : 0));
+ QRHI_PROF_F(newBuffer(this, quint32(roundedSize), m_type == Dynamic ? 2 : 1, m_type == Dynamic ? 1 : 0));
generation += 1;
rhiD->registerResource(this);
@@ -2271,7 +2347,7 @@ ID3D11UnorderedAccessView *QD3D11Buffer::unorderedAccessView()
desc.Format = DXGI_FORMAT_R32_TYPELESS;
desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
desc.Buffer.FirstElement = 0;
- desc.Buffer.NumElements = aligned(m_size, 4) / 4;
+ desc.Buffer.NumElements = UINT(aligned(m_size, 4) / 4);
desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
QRHI_RES_RHI(QRhiD3D11);
@@ -2332,8 +2408,8 @@ bool QD3D11RenderBuffer::build()
D3D11_TEXTURE2D_DESC desc;
memset(&desc, 0, sizeof(desc));
- desc.Width = m_pixelSize.width();
- desc.Height = m_pixelSize.height();
+ desc.Width = UINT(m_pixelSize.width());
+ desc.Height = UINT(m_pixelSize.height());
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.SampleDesc = sampleDesc;
@@ -2382,10 +2458,10 @@ bool QD3D11RenderBuffer::build()
}
if (!m_objectName.isEmpty())
- tex->SetPrivateData(WKPDID_D3DDebugObjectName, m_objectName.size(), m_objectName.constData());
+ tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
QRHI_PROF;
- QRHI_PROF_F(newRenderBuffer(this, false, false, sampleDesc.Count));
+ QRHI_PROF_F(newRenderBuffer(this, false, false, int(sampleDesc.Count)));
rhiD->registerResource(this);
return true;
@@ -2475,7 +2551,7 @@ bool QD3D11Texture::prepareBuild(QSize *adjustedSize)
QRHI_RES_RHI(QRhiD3D11);
dxgiFormat = toD3DTextureFormat(m_format, m_flags);
- mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
+ mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
if (sampleDesc.Count > 1) {
if (isCube) {
@@ -2561,8 +2637,8 @@ bool QD3D11Texture::build()
D3D11_TEXTURE2D_DESC desc;
memset(&desc, 0, sizeof(desc));
- desc.Width = size.width();
- desc.Height = size.height();
+ desc.Width = UINT(size.width());
+ desc.Height = UINT(size.height());
desc.MipLevels = mipLevelCount;
desc.ArraySize = isCube ? 6 : 1;
desc.Format = dxgiFormat;
@@ -2582,10 +2658,10 @@ bool QD3D11Texture::build()
return false;
if (!m_objectName.isEmpty())
- tex->SetPrivateData(WKPDID_D3DDebugObjectName, m_objectName.size(), m_objectName.constData());
+ tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
QRHI_PROF;
- QRHI_PROF_F(newTexture(this, true, mipLevelCount, isCube ? 6 : 1, sampleDesc.Count));
+ QRHI_PROF_F(newTexture(this, true, int(mipLevelCount), isCube ? 6 : 1, int(sampleDesc.Count)));
owns = true;
rhiD->registerResource(this);
@@ -2607,7 +2683,7 @@ bool QD3D11Texture::buildFrom(const QRhiNativeHandles *src)
return false;
QRHI_PROF;
- QRHI_PROF_F(newTexture(this, false, mipLevelCount, m_flags.testFlag(CubeMap) ? 6 : 1, sampleDesc.Count));
+ QRHI_PROF_F(newTexture(this, false, int(mipLevelCount), m_flags.testFlag(CubeMap) ? 6 : 1, int(sampleDesc.Count)));
owns = false;
QRHI_RES_RHI(QRhiD3D11);
@@ -2631,12 +2707,12 @@ ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level)
desc.Format = dxgiFormat;
if (isCube) {
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
- desc.Texture2DArray.MipSlice = level;
+ desc.Texture2DArray.MipSlice = UINT(level);
desc.Texture2DArray.FirstArraySlice = 0;
desc.Texture2DArray.ArraySize = 6;
} else {
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
- desc.Texture2D.MipSlice = level;
+ desc.Texture2D.MipSlice = UINT(level);
}
QRHI_RES_RHI(QRhiD3D11);
@@ -2896,15 +2972,15 @@ bool QD3D11TextureRenderTarget::build()
rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
- rtvDesc.Texture2DArray.MipSlice = colorAttachments[i].level();
- rtvDesc.Texture2DArray.FirstArraySlice = colorAttachments[i].layer();
+ rtvDesc.Texture2DArray.MipSlice = UINT(colorAttachments[i].level());
+ rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAttachments[i].layer());
rtvDesc.Texture2DArray.ArraySize = 1;
} else {
if (texD->sampleDesc.Count > 1) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
} else {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
- rtvDesc.Texture2D.MipSlice = colorAttachments[i].level();
+ rtvDesc.Texture2D.MipSlice = UINT(colorAttachments[i].level());
}
}
HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->tex, &rtvDesc, &rtv[i]);
@@ -2915,7 +2991,7 @@ bool QD3D11TextureRenderTarget::build()
ownsRtv[i] = true;
if (i == 0) {
d.pixelSize = texD->pixelSize();
- d.sampleCount = texD->sampleDesc.Count;
+ d.sampleCount = int(texD->sampleDesc.Count);
}
} else if (rb) {
QD3D11RenderBuffer *rbD = QRHI_RES(QD3D11RenderBuffer, rb);
@@ -2923,7 +2999,7 @@ bool QD3D11TextureRenderTarget::build()
rtv[i] = rbD->rtv;
if (i == 0) {
d.pixelSize = rbD->pixelSize();
- d.sampleCount = rbD->sampleDesc.Count;
+ d.sampleCount = int(rbD->sampleDesc.Count);
}
}
}
@@ -2945,7 +3021,7 @@ bool QD3D11TextureRenderTarget::build()
}
if (d.colorAttCount == 0) {
d.pixelSize = depthTexD->pixelSize();
- d.sampleCount = depthTexD->sampleDesc.Count;
+ d.sampleCount = int(depthTexD->sampleDesc.Count);
}
} else {
ownsDsv = false;
@@ -2953,7 +3029,7 @@ bool QD3D11TextureRenderTarget::build()
dsv = depthRbD->dsv;
if (d.colorAttCount == 0) {
d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
- d.sampleCount = depthRbD->sampleDesc.Count;
+ d.sampleCount = int(depthRbD->sampleDesc.Count);
}
}
d.dsAttCount = 1;
@@ -3177,9 +3253,9 @@ static inline D3D11_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topol
}
}
-static inline uint toD3DColorWriteMask(QRhiGraphicsPipeline::ColorMask c)
+static inline UINT8 toD3DColorWriteMask(QRhiGraphicsPipeline::ColorMask c)
{
- uint f = 0;
+ UINT8 f = 0;
if (c.testFlag(QRhiGraphicsPipeline::R))
f |= D3D11_COLOR_WRITE_ENABLE_RED;
if (c.testFlag(QRhiGraphicsPipeline::G))
@@ -3314,22 +3390,22 @@ static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Varian
ID3DBlob *bytecode = nullptr;
ID3DBlob *errors = nullptr;
- HRESULT hr = d3dCompile(hlslSource.shader().constData(), hlslSource.shader().size(),
+ HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
nullptr, nullptr, nullptr,
hlslSource.entryPoint().constData(), target, 0, 0, &bytecode, &errors);
if (FAILED(hr) || !bytecode) {
qWarning("HLSL shader compilation failed: 0x%x", uint(hr));
if (errors) {
*error = QString::fromUtf8(static_cast<const char *>(errors->GetBufferPointer()),
- errors->GetBufferSize());
+ int(errors->GetBufferSize()));
errors->Release();
}
return QByteArray();
}
QByteArray result;
- result.resize(bytecode->GetBufferSize());
- memcpy(result.data(), bytecode->GetBufferPointer(), result.size());
+ result.resize(int(bytecode->GetBufferSize()));
+ memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
bytecode->Release();
return result;
}
@@ -3361,8 +3437,8 @@ bool QD3D11GraphicsPipeline::build()
dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
dsDesc.StencilEnable = m_stencilTest;
if (m_stencilTest) {
- dsDesc.StencilReadMask = m_stencilReadMask;
- dsDesc.StencilWriteMask = m_stencilWriteMask;
+ dsDesc.StencilReadMask = UINT8(m_stencilReadMask);
+ dsDesc.StencilWriteMask = UINT8(m_stencilWriteMask);
dsDesc.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
dsDesc.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
dsDesc.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
@@ -3409,30 +3485,57 @@ bool QD3D11GraphicsPipeline::build()
QByteArray vsByteCode;
for (const QRhiShaderStage &shaderStage : qAsConst(m_shaderStages)) {
- QString error;
- QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error);
- if (bytecode.isEmpty()) {
- qWarning("HLSL shader compilation failed: %s", qPrintable(error));
- return false;
- }
- switch (shaderStage.type()) {
- case QRhiShaderStage::Vertex:
- hr = rhiD->dev->CreateVertexShader(bytecode.constData(), bytecode.size(), nullptr, &vs);
- if (FAILED(hr)) {
- qWarning("Failed to create vertex shader: %s", qPrintable(comErrorMessage(hr)));
- return false;
+ auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
+ if (cacheIt != rhiD->m_shaderCache.constEnd()) {
+ switch (shaderStage.type()) {
+ case QRhiShaderStage::Vertex:
+ vs = static_cast<ID3D11VertexShader *>(cacheIt->s);
+ vs->AddRef();
+ vsByteCode = cacheIt->bytecode;
+ break;
+ case QRhiShaderStage::Fragment:
+ fs = static_cast<ID3D11PixelShader *>(cacheIt->s);
+ fs->AddRef();
+ break;
+ default:
+ break;
}
- vsByteCode = bytecode;
- break;
- case QRhiShaderStage::Fragment:
- hr = rhiD->dev->CreatePixelShader(bytecode.constData(), bytecode.size(), nullptr, &fs);
- if (FAILED(hr)) {
- qWarning("Failed to create pixel shader: %s", qPrintable(comErrorMessage(hr)));
+ } else {
+ QString error;
+ const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error);
+ if (bytecode.isEmpty()) {
+ qWarning("HLSL shader compilation failed: %s", qPrintable(error));
return false;
}
- break;
- default:
- break;
+
+ if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES) {
+ // Use the simplest strategy: too many cached shaders -> drop them all.
+ rhiD->clearShaderCache();
+ }
+
+ switch (shaderStage.type()) {
+ case QRhiShaderStage::Vertex:
+ hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &vs);
+ 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();
+ break;
+ case QRhiShaderStage::Fragment:
+ hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs);
+ 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();
+ break;
+ default:
+ break;
+ }
}
}
@@ -3447,20 +3550,21 @@ bool QD3D11GraphicsPipeline::build()
memset(&desc, 0, sizeof(desc));
// the output from SPIRV-Cross uses TEXCOORD<location> as the semantic
desc.SemanticName = "TEXCOORD";
- desc.SemanticIndex = attribute.location();
+ desc.SemanticIndex = UINT(attribute.location());
desc.Format = toD3DAttributeFormat(attribute.format());
- desc.InputSlot = attribute.binding();
+ desc.InputSlot = UINT(attribute.binding());
desc.AlignedByteOffset = attribute.offset();
const QRhiVertexInputBinding &binding(bindings[attribute.binding()]);
if (binding.classification() == QRhiVertexInputBinding::PerInstance) {
desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
- desc.InstanceDataStepRate = binding.instanceStepRate();
+ desc.InstanceDataStepRate = UINT(binding.instanceStepRate());
} else {
desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
}
inputDescs.append(desc);
}
- hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), inputDescs.count(), vsByteCode, vsByteCode.size(), &inputLayout);
+ hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
+ vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
if (FAILED(hr)) {
qWarning("Failed to create input layout: %s", qPrintable(comErrorMessage(hr)));
return false;
@@ -3502,19 +3606,31 @@ bool QD3D11ComputePipeline::build()
QRHI_RES_RHI(QRhiD3D11);
- QString error;
- QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error);
- if (bytecode.isEmpty()) {
- qWarning("HLSL compute shader compilation failed: %s", qPrintable(error));
- return false;
- }
+ auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
+ if (cacheIt != rhiD->m_shaderCache.constEnd()) {
+ cs = static_cast<ID3D11ComputeShader *>(cacheIt->s);
+ } else {
+ QString error;
+ const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error);
+ if (bytecode.isEmpty()) {
+ qWarning("HLSL compute shader compilation failed: %s", qPrintable(error));
+ return false;
+ }
- HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), bytecode.size(), nullptr, &cs);
- if (FAILED(hr)) {
- qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr)));
- return false;
+ HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &cs);
+ if (FAILED(hr)) {
+ qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr)));
+ return false;
+ }
+
+ if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
+ rhiD->clearShaderCache();
+
+ rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs, bytecode));
}
+ cs->AddRef();
+
generation += 1;
rhiD->registerResource(this);
return true;
@@ -3637,8 +3753,8 @@ bool QD3D11SwapChain::newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI
{
D3D11_TEXTURE2D_DESC desc;
memset(&desc, 0, sizeof(desc));
- desc.Width = size.width();
- desc.Height = size.height();
+ desc.Width = UINT(size.width());
+ desc.Height = UINT(size.height());
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = format;
@@ -3694,11 +3810,23 @@ bool QD3D11SwapChain::buildOrResize()
const UINT swapChainFlags = 0;
QRHI_RES_RHI(QRhiD3D11);
- const bool useFlipDiscard = rhiD->hasDxgi2 && rhiD->supportsFlipDiscardSwapchain;
+ bool useFlipDiscard = rhiD->hasDxgi2 && rhiD->supportsFlipDiscardSwapchain;
if (!swapChain) {
HWND hwnd = reinterpret_cast<HWND>(window->winId());
sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
+ // Take a shortcut for alpha: our QWindow is OpenGLSurface so whatever
+ // the platform plugin does to enable transparency for OpenGL window
+ // will be sufficient for us too on the legacy (DISCARD) path. For
+ // FLIP_DISCARD we'd need to use DirectComposition (create a
+ // IDCompositionDevice/Target/Visual), avoid that for now.
+ if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
+ useFlipDiscard = false;
+ if (window->requestedFormat().alphaBufferSize() <= 0)
+ qWarning("Swapchain says surface has alpha but the window has no alphaBufferSize set. "
+ "This may lead to problems.");
+ }
+
HRESULT hr;
if (useFlipDiscard) {
// We use FLIP_DISCARD which implies a buffer count of 2 (as opposed to the
@@ -3709,18 +3837,17 @@ bool QD3D11SwapChain::buildOrResize()
DXGI_SWAP_CHAIN_DESC1 desc;
memset(&desc, 0, sizeof(desc));
- desc.Width = pixelSize.width();
- desc.Height = pixelSize.height();
+ desc.Width = UINT(pixelSize.width());
+ desc.Height = UINT(pixelSize.height());
desc.Format = colorFormat;
desc.SampleDesc.Count = 1;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.BufferCount = BUFFER_COUNT;
desc.Scaling = DXGI_SCALING_STRETCH;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
- if (m_flags.testFlag(SurfaceHasPreMulAlpha))
- desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
- else if (m_flags.testFlag(SurfaceHasNonPreMulAlpha))
- desc.AlphaMode = DXGI_ALPHA_MODE_STRAIGHT;
+ // Do not bother with AlphaMode, if won't work unless we go through
+ // DirectComposition. Instead, we just take the other (DISCARD)
+ // path for now when alpha is requested.
desc.Flags = swapChainFlags;
IDXGISwapChain1 *sc1;
@@ -3735,8 +3862,8 @@ bool QD3D11SwapChain::buildOrResize()
DXGI_SWAP_CHAIN_DESC desc;
memset(&desc, 0, sizeof(desc));
- desc.BufferDesc.Width = pixelSize.width();
- desc.BufferDesc.Height = pixelSize.height();
+ desc.BufferDesc.Width = UINT(pixelSize.width());
+ desc.BufferDesc.Height = UINT(pixelSize.height());
desc.BufferDesc.RefreshRate.Numerator = 60;
desc.BufferDesc.RefreshRate.Denominator = 1;
desc.BufferDesc.Format = colorFormat;
@@ -3758,9 +3885,13 @@ bool QD3D11SwapChain::buildOrResize()
} else {
releaseBuffers();
const UINT count = useFlipDiscard ? BUFFER_COUNT : 1;
- HRESULT hr = swapChain->ResizeBuffers(count, pixelSize.width(), pixelSize.height(),
+ HRESULT hr = swapChain->ResizeBuffers(count, UINT(pixelSize.width()), UINT(pixelSize.height()),
colorFormat, swapChainFlags);
- if (FAILED(hr)) {
+ if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
+ qWarning("Device loss detected in ResizeBuffers()");
+ rhiD->deviceLost = true;
+ return false;
+ } else if (FAILED(hr)) {
qWarning("Failed to resize D3D11 swapchain: %s", qPrintable(comErrorMessage(hr)));
return false;
}
@@ -3821,13 +3952,13 @@ bool QD3D11SwapChain::buildOrResize()
QD3D11ReferenceRenderTarget *rtD = QRHI_RES(QD3D11ReferenceRenderTarget, &rt);
rtD->d.rp = QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
rtD->d.pixelSize = pixelSize;
- rtD->d.dpr = window->devicePixelRatio();
- rtD->d.sampleCount = sampleDesc.Count;
+ rtD->d.dpr = float(window->devicePixelRatio());
+ rtD->d.sampleCount = int(sampleDesc.Count);
rtD->d.colorAttCount = 1;
rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
QRHI_PROF;
- QRHI_PROF_F(resizeSwapChain(this, BUFFER_COUNT, sampleDesc.Count > 1 ? BUFFER_COUNT : 0, sampleDesc.Count));
+ QRHI_PROF_F(resizeSwapChain(this, BUFFER_COUNT, sampleDesc.Count > 1 ? BUFFER_COUNT : 0, int(sampleDesc.Count)));
if (rhiP) {
D3D11_QUERY_DESC queryDesc;
memset(&queryDesc, 0, sizeof(queryDesc));
@@ -3861,4 +3992,34 @@ bool QD3D11SwapChain::buildOrResize()
return true;
}
+void QRhiD3D11::DeviceCurse::initResources()
+{
+ framesLeft = framesToActivate;
+
+ HRESULT hr = q->dev->CreateComputeShader(g_killDeviceByTimingOut, sizeof(g_killDeviceByTimingOut), nullptr, &cs);
+ if (FAILED(hr)) {
+ qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr)));
+ return;
+ }
+}
+
+void QRhiD3D11::DeviceCurse::releaseResources()
+{
+ if (cs) {
+ cs->Release();
+ cs = nullptr;
+ }
+}
+
+void QRhiD3D11::DeviceCurse::activate()
+{
+ if (!cs)
+ return;
+
+ qDebug("Activating Curse. Goodbye Cruel World.");
+
+ q->context->CSSetShader(cs, nullptr, 0);
+ q->context->Dispatch(256, 1, 1);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhid3d11_p.h b/src/gui/rhi/qrhid3d11_p.h
index 3e2e492d9c..5df1843b1e 100644
--- a/src/gui/rhi/qrhid3d11_p.h
+++ b/src/gui/rhi/qrhid3d11_p.h
@@ -58,6 +58,9 @@ QT_BEGIN_NAMESPACE
struct Q_GUI_EXPORT QRhiD3D11InitParams : public QRhiInitParams
{
bool enableDebugLayer = false;
+
+ int framesUntilKillingDeviceViaTdr = -1;
+ bool repeatDeviceKill = false;
};
struct Q_GUI_EXPORT QRhiD3D11NativeHandles : public QRhiNativeHandles
diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h
index 582146315d..cf4808510c 100644
--- a/src/gui/rhi/qrhid3d11_p_p.h
+++ b/src/gui/rhi/qrhid3d11_p_p.h
@@ -631,7 +631,9 @@ public:
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
void sendVMemStatsToProfiler() override;
- void makeThreadLocalNativeContextCurrent() override;
+ bool makeThreadLocalNativeContextCurrent() override;
+ void releaseCachedResources() override;
+ bool isDeviceLost() const override;
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
@@ -646,6 +648,7 @@ public:
DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount) const;
void finishActiveReadbacks();
void reportLiveObjects(ID3D11Device *device);
+ void clearShaderCache();
bool debugLayer = false;
bool importedDevice = false;
@@ -656,6 +659,7 @@ public:
IDXGIFactory1 *dxgiFactory = nullptr;
bool hasDxgi2 = false;
bool supportsFlipDiscardSwapchain = false;
+ bool deviceLost = false;
QRhiD3D11NativeHandles nativeHandlesStruct;
struct {
@@ -684,6 +688,27 @@ public:
QRhiTexture::Format format;
};
QVector<ActiveReadback> activeReadbacks;
+
+ struct Shader {
+ Shader() = default;
+ Shader(IUnknown *s, const QByteArray &bytecode) : s(s), bytecode(bytecode) { }
+ IUnknown *s;
+ QByteArray bytecode;
+ };
+ QHash<QRhiShaderStage, Shader> m_shaderCache;
+
+ struct DeviceCurse {
+ DeviceCurse(QRhiD3D11 *impl) : q(impl) { }
+ QRhiD3D11 *q;
+ int framesToActivate = -1;
+ bool permanent = false;
+ int framesLeft = 0;
+ ID3D11ComputeShader *cs = nullptr;
+
+ void initResources();
+ void releaseResources();
+ void activate();
+ } deviceCurse;
};
Q_DECLARE_TYPEINFO(QRhiD3D11::ActiveReadback, Q_MOVABLE_TYPE);
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index f4e711e33e..2d51d892e3 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -371,7 +371,12 @@ bool QRhiGles2::ensureContext(QSurface *surface) const
return true;
if (!ctx->makeCurrent(surface)) {
- qWarning("QRhiGles2: Failed to make context current. Expect bad things to happen.");
+ if (ctx->isValid()) {
+ qWarning("QRhiGles2: Failed to make context current. Expect bad things to happen.");
+ } else {
+ qWarning("QRhiGles2: Context is lost.");
+ contextLost = true;
+ }
return false;
}
@@ -491,6 +496,8 @@ bool QRhiGles2::create(QRhi::Flags flags)
nativeHandlesStruct.context = ctx;
+ contextLost = false;
+
return true;
}
@@ -502,6 +509,10 @@ void QRhiGles2::destroy()
ensureContext();
executeDeferredReleases();
+ for (uint shader : m_shaderCache)
+ f->glDeleteShader(shader);
+ m_shaderCache.clear();
+
if (!importedContext) {
delete ctx;
ctx = nullptr;
@@ -650,7 +661,7 @@ static inline GLenum toGlCompressedTextureFormat(QRhiTexture::Format format, QRh
bool QRhiGles2::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
{
if (isCompressedFormat(format))
- return supportedCompressedFormats.contains(toGlCompressedTextureFormat(format, flags));
+ return supportedCompressedFormats.contains(GLint(toGlCompressedTextureFormat(format, flags)));
switch (format) {
case QRhiTexture::D16:
@@ -749,12 +760,28 @@ void QRhiGles2::sendVMemStatsToProfiler()
// nothing to do here
}
-void QRhiGles2::makeThreadLocalNativeContextCurrent()
+bool QRhiGles2::makeThreadLocalNativeContextCurrent()
{
if (inFrame && !ofr.active)
- ensureContext(currentSwapChain->surface);
+ return ensureContext(currentSwapChain->surface);
else
- ensureContext();
+ return ensureContext();
+}
+
+void QRhiGles2::releaseCachedResources()
+{
+ if (!ensureContext())
+ return;
+
+ for (uint shader : m_shaderCache)
+ f->glDeleteShader(shader);
+
+ m_shaderCache.clear();
+}
+
+bool QRhiGles2::isDeviceLost() const
+{
+ return contextLost;
}
QRhiRenderBuffer *QRhiGles2::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
@@ -915,7 +942,7 @@ void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
uint *p = cmd.args.bindShaderResources.dynamicOffsetPairs;
for (int i = 0; i < dynamicOffsetCount; ++i) {
const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
- *p++ = dynOfs.first;
+ *p++ = uint(dynOfs.first);
*p++ = dynOfs.second;
}
} else {
@@ -1008,10 +1035,10 @@ void QRhiGles2::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
QGles2CommandBuffer::Command cmd;
cmd.cmd = QGles2CommandBuffer::Command::BlendConstants;
- cmd.args.blendConstants.r = c.redF();
- cmd.args.blendConstants.g = c.greenF();
- cmd.args.blendConstants.b = c.blueF();
- cmd.args.blendConstants.a = c.alphaF();
+ cmd.args.blendConstants.r = float(c.redF());
+ cmd.args.blendConstants.g = float(c.greenF());
+ cmd.args.blendConstants.b = float(c.blueF());
+ cmd.args.blendConstants.a = float(c.alphaF());
cbD->commands.append(cmd);
}
@@ -1141,7 +1168,7 @@ QRhi::FrameOpResult QRhiGles2::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginF
QGles2SwapChain *swapChainD = QRHI_RES(QGles2SwapChain, swapChain);
if (!ensureContext(swapChainD->surface))
- return QRhi::FrameOpError;
+ return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
currentSwapChain = swapChainD;
@@ -1164,7 +1191,7 @@ QRhi::FrameOpResult QRhiGles2::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
addBoundaryCommand(&swapChainD->cb, QGles2CommandBuffer::Command::EndFrame);
if (!ensureContext(swapChainD->surface))
- return QRhi::FrameOpError;
+ return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
executeCommandBuffer(&swapChainD->cb);
@@ -1188,7 +1215,7 @@ QRhi::FrameOpResult QRhiGles2::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi:
{
Q_UNUSED(flags);
if (!ensureContext())
- return QRhi::FrameOpError;
+ return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
ofr.active = true;
@@ -1210,7 +1237,7 @@ QRhi::FrameOpResult QRhiGles2::endOffscreenFrame(QRhi::EndFrameFlags flags)
addBoundaryCommand(&ofr.cbWrapper, QGles2CommandBuffer::Command::EndFrame);
if (!ensureContext())
- return QRhi::FrameOpError;
+ return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
executeCommandBuffer(&ofr.cbWrapper);
@@ -1224,14 +1251,14 @@ QRhi::FrameOpResult QRhiGles2::finish()
Q_ASSERT(!currentSwapChain);
Q_ASSERT(ofr.cbWrapper.recordingPass == QGles2CommandBuffer::NoPass);
if (!ensureContext())
- return QRhi::FrameOpError;
+ return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
executeCommandBuffer(&ofr.cbWrapper);
ofr.cbWrapper.resetCommands();
} else {
Q_ASSERT(currentSwapChain);
Q_ASSERT(currentSwapChain->cb.recordingPass == QGles2CommandBuffer::NoPass);
if (!ensureContext(currentSwapChain->surface))
- return QRhi::FrameOpError;
+ return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
executeCommandBuffer(&currentSwapChain->cb);
currentSwapChain->cb.resetCommands();
}
@@ -1299,7 +1326,7 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
}
cmd.args.subImage.target = texD->target;
cmd.args.subImage.texture = texD->texture;
- cmd.args.subImage.faceTarget = faceTargetBase + layer;
+ cmd.args.subImage.faceTarget = faceTargetBase + uint(layer);
cmd.args.subImage.level = level;
cmd.args.subImage.dx = dp.x();
cmd.args.subImage.dy = dp.y();
@@ -1318,7 +1345,7 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.cmd = QGles2CommandBuffer::Command::CompressedSubImage;
cmd.args.compressedSubImage.target = texD->target;
cmd.args.compressedSubImage.texture = texD->texture;
- cmd.args.compressedSubImage.faceTarget = faceTargetBase + layer;
+ cmd.args.compressedSubImage.faceTarget = faceTargetBase + uint(layer);
cmd.args.compressedSubImage.level = level;
cmd.args.compressedSubImage.dx = dp.x();
cmd.args.compressedSubImage.dy = dp.y();
@@ -1333,7 +1360,7 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.cmd = QGles2CommandBuffer::Command::CompressedImage;
cmd.args.compressedImage.target = texD->target;
cmd.args.compressedImage.texture = texD->texture;
- cmd.args.compressedImage.faceTarget = faceTargetBase + layer;
+ cmd.args.compressedImage.faceTarget = faceTargetBase + uint(layer);
cmd.args.compressedImage.level = level;
cmd.args.compressedImage.glintformat = texD->glintformat;
cmd.args.compressedImage.w = size.width();
@@ -1351,7 +1378,7 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.cmd = QGles2CommandBuffer::Command::SubImage;
cmd.args.subImage.target = texD->target;
cmd.args.subImage.texture = texD->texture;
- cmd.args.subImage.faceTarget = faceTargetBase + layer;
+ cmd.args.subImage.faceTarget = faceTargetBase + uint(layer);
cmd.args.subImage.level = level;
cmd.args.subImage.dx = dp.x();
cmd.args.subImage.dy = dp.y();
@@ -1379,7 +1406,7 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, u.buf);
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) {
- memcpy(bufD->ubuf.data() + u.offset, u.data.constData(), u.data.size());
+ memcpy(bufD->ubuf.data() + u.offset, u.data.constData(), size_t(u.data.size()));
} else {
trackedBufferBarrier(cbD, bufD, QGles2Buffer::AccessUpdate);
QGles2CommandBuffer::Command cmd;
@@ -1398,7 +1425,7 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
if (bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer)) {
- memcpy(bufD->ubuf.data() + u.offset, u.data.constData(), u.data.size());
+ memcpy(bufD->ubuf.data() + u.offset, u.data.constData(), size_t(u.data.size()));
} else {
trackedBufferBarrier(cbD, bufD, QGles2Buffer::AccessUpdate);
QGles2CommandBuffer::Command cmd;
@@ -1443,7 +1470,7 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QGles2CommandBuffer::Command cmd;
cmd.cmd = QGles2CommandBuffer::Command::CopyTex;
- cmd.args.copyTex.srcFaceTarget = srcFaceTargetBase + u.copy.desc.sourceLayer();
+ cmd.args.copyTex.srcFaceTarget = srcFaceTargetBase + uint(u.copy.desc.sourceLayer());
cmd.args.copyTex.srcTexture = srcD->texture;
cmd.args.copyTex.srcLevel = u.copy.desc.sourceLevel();
cmd.args.copyTex.srcX = sp.x();
@@ -1451,7 +1478,7 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
cmd.args.copyTex.dstTarget = dstD->target;
cmd.args.copyTex.dstTexture = dstD->texture;
- cmd.args.copyTex.dstFaceTarget = dstFaceTargetBase + u.copy.desc.destinationLayer();
+ cmd.args.copyTex.dstFaceTarget = dstFaceTargetBase + uint(u.copy.desc.destinationLayer());
cmd.args.copyTex.dstLevel = u.copy.desc.destinationLevel();
cmd.args.copyTex.dstX = dp.x();
cmd.args.copyTex.dstY = dp.y();
@@ -1465,7 +1492,8 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
cmd.cmd = QGles2CommandBuffer::Command::ReadPixels;
cmd.args.readPixels.result = u.read.result;
QGles2Texture *texD = QRHI_RES(QGles2Texture, u.read.rb.texture());
- trackedImageBarrier(cbD, texD, QGles2Texture::AccessRead);
+ if (texD)
+ trackedImageBarrier(cbD, texD, QGles2Texture::AccessRead);
cmd.args.readPixels.texture = texD ? texD->texture : 0;
if (texD) {
cmd.args.readPixels.w = texD->m_pixelSize.width();
@@ -1473,7 +1501,7 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
cmd.args.readPixels.format = texD->m_format;
const GLenum faceTargetBase = texD->m_flags.testFlag(QRhiTexture::CubeMap)
? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
- cmd.args.readPixels.readTarget = faceTargetBase + u.read.rb.layer();
+ cmd.args.readPixels.readTarget = faceTargetBase + uint(u.read.rb.layer());
cmd.args.readPixels.level = u.read.rb.level();
}
cbD->commands.append(cmd);
@@ -1833,7 +1861,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
f->glBindVertexArray(0);
break;
case QGles2CommandBuffer::Command::Viewport:
- f->glViewport(cmd.args.viewport.x, cmd.args.viewport.y, cmd.args.viewport.w, cmd.args.viewport.h);
+ f->glViewport(GLint(cmd.args.viewport.x), GLint(cmd.args.viewport.y), GLsizei(cmd.args.viewport.w), GLsizei(cmd.args.viewport.h));
f->glDepthRangef(cmd.args.viewport.d0, cmd.args.viewport.d1);
break;
case QGles2CommandBuffer::Command::Scissor:
@@ -1846,8 +1874,8 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
{
QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, cmd.args.stencilRef.ps);
if (psD) {
- f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), cmd.args.stencilRef.ref, psD->m_stencilReadMask);
- f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), cmd.args.stencilRef.ref, psD->m_stencilReadMask);
+ f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), GLint(cmd.args.stencilRef.ref), psD->m_stencilReadMask);
+ f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), GLint(cmd.args.stencilRef.ref), psD->m_stencilReadMask);
} else {
qWarning("No graphics pipeline active for setStencilRef; ignored");
}
@@ -1867,7 +1895,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
// we do not support more than one vertex buffer
f->glBindBuffer(GL_ARRAY_BUFFER, cmd.args.bindVertexBuffer.buffer);
- const int stride = bindings[bindingIdx].stride();
+ const int stride = int(bindings[bindingIdx].stride());
int size = 1;
GLenum type = GL_FLOAT;
bool normalize = false;
@@ -1909,13 +1937,13 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
const int locationIdx = a.location();
quint32 ofs = a.offset() + cmd.args.bindVertexBuffer.offset;
- f->glVertexAttribPointer(locationIdx, size, type, normalize, stride,
+ f->glVertexAttribPointer(GLuint(locationIdx), size, type, normalize, stride,
reinterpret_cast<const GLvoid *>(quintptr(ofs)));
- f->glEnableVertexAttribArray(locationIdx);
+ f->glEnableVertexAttribArray(GLuint(locationIdx));
if (bindings[bindingIdx].classification() == QRhiVertexInputBinding::PerInstance
&& caps.instancing)
{
- f->glVertexAttribDivisor(locationIdx, bindings[bindingIdx].instanceStepRate());
+ f->glVertexAttribDivisor(GLuint(locationIdx), GLuint(bindings[bindingIdx].instanceStepRate()));
}
}
} else {
@@ -1934,10 +1962,10 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, cmd.args.draw.ps);
if (psD) {
if (cmd.args.draw.instanceCount == 1 || !caps.instancing) {
- f->glDrawArrays(psD->drawMode, cmd.args.draw.firstVertex, cmd.args.draw.vertexCount);
+ f->glDrawArrays(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount));
} else {
- f->glDrawArraysInstanced(psD->drawMode, cmd.args.draw.firstVertex, cmd.args.draw.vertexCount,
- cmd.args.draw.instanceCount);
+ f->glDrawArraysInstanced(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount),
+ GLsizei(cmd.args.draw.instanceCount));
}
} else {
qWarning("No graphics pipeline active for draw; ignored");
@@ -1953,30 +1981,30 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
if (cmd.args.drawIndexed.instanceCount == 1 || !caps.instancing) {
if (cmd.args.drawIndexed.baseVertex != 0 && caps.baseVertex) {
f->glDrawElementsBaseVertex(psD->drawMode,
- cmd.args.drawIndexed.indexCount,
+ GLsizei(cmd.args.drawIndexed.indexCount),
indexType,
ofs,
cmd.args.drawIndexed.baseVertex);
} else {
f->glDrawElements(psD->drawMode,
- cmd.args.drawIndexed.indexCount,
+ GLsizei(cmd.args.drawIndexed.indexCount),
indexType,
ofs);
}
} else {
if (cmd.args.drawIndexed.baseVertex != 0 && caps.baseVertex) {
f->glDrawElementsInstancedBaseVertex(psD->drawMode,
- cmd.args.drawIndexed.indexCount,
+ GLsizei(cmd.args.drawIndexed.indexCount),
indexType,
ofs,
- cmd.args.drawIndexed.instanceCount,
+ GLsizei(cmd.args.drawIndexed.instanceCount),
cmd.args.drawIndexed.baseVertex);
} else {
f->glDrawElementsInstanced(psD->drawMode,
- cmd.args.drawIndexed.indexCount,
+ GLsizei(cmd.args.drawIndexed.indexCount),
indexType,
ofs,
- cmd.args.drawIndexed.instanceCount);
+ GLsizei(cmd.args.drawIndexed.instanceCount));
}
}
} else {
@@ -2001,7 +2029,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
const int colorAttCount = cmd.args.bindFramebuffer.colorAttCount;
QVarLengthArray<GLenum, 8> bufs;
for (int i = 0; i < colorAttCount; ++i)
- bufs.append(GL_COLOR_ATTACHMENT0 + i);
+ bufs.append(GL_COLOR_ATTACHMENT0 + uint(i));
f->glDrawBuffers(colorAttCount, bufs.constData());
}
} else {
@@ -2029,7 +2057,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
f->glClearDepthf(cmd.args.clear.d);
}
if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT)
- f->glClearStencil(cmd.args.clear.s);
+ f->glClearStencil(GLint(cmd.args.clear.s));
f->glClear(cmd.args.clear.mask);
break;
case QGles2CommandBuffer::Command::BufferSubData:
@@ -2273,7 +2301,7 @@ void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *maybeGraphicsPs, QRhiC
if (dynOfsCount) {
for (int j = 0; j < dynOfsCount; ++j) {
if (dynOfsPairs[2 * j] == uint(b->binding)) {
- viewOffset = dynOfsPairs[2 * j + 1];
+ viewOffset = int(dynOfsPairs[2 * j + 1]);
break;
}
}
@@ -2364,20 +2392,20 @@ void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *maybeGraphicsPs, QRhiC
for (QGles2SamplerDescription &sampler : samplers) {
if (sampler.binding == b->binding) {
- f->glActiveTexture(GL_TEXTURE0 + texUnit);
+ f->glActiveTexture(GL_TEXTURE0 + uint(texUnit));
f->glBindTexture(texD->target, texD->texture);
if (texD->samplerState != samplerD->d) {
- f->glTexParameteri(texD->target, GL_TEXTURE_MIN_FILTER, samplerD->d.glminfilter);
- f->glTexParameteri(texD->target, GL_TEXTURE_MAG_FILTER, samplerD->d.glmagfilter);
- f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_S, samplerD->d.glwraps);
- f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_T, samplerD->d.glwrapt);
+ f->glTexParameteri(texD->target, GL_TEXTURE_MIN_FILTER, GLint(samplerD->d.glminfilter));
+ f->glTexParameteri(texD->target, GL_TEXTURE_MAG_FILTER, GLint(samplerD->d.glmagfilter));
+ f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_S, GLint(samplerD->d.glwraps));
+ f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_T, GLint(samplerD->d.glwrapt));
// 3D textures not supported by GLES 2.0 or by us atm...
//f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_R, samplerD->d.glwrapr);
if (caps.textureCompareMode) {
if (samplerD->d.gltexcomparefunc != GL_NEVER) {
f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
- f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_FUNC, samplerD->d.gltexcomparefunc);
+ f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_FUNC, GLint(samplerD->d.gltexcomparefunc));
} else {
f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
}
@@ -2404,7 +2432,7 @@ void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *maybeGraphicsPs, QRhiC
access = GL_READ_ONLY;
else if (b->type == QRhiShaderResourceBinding::ImageStore)
access = GL_WRITE_ONLY;
- f->glBindImageTexture(b->binding, texD->texture,
+ f->glBindImageTexture(GLuint(b->binding), texD->texture,
b->u.simage.level, layered, 0,
access, texD->glsizedintformat);
}
@@ -2417,9 +2445,9 @@ void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *maybeGraphicsPs, QRhiC
{
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.sbuf.buf);
if (b->u.sbuf.offset == 0 && b->u.sbuf.maybeSize == 0)
- f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, b->binding, bufD->buffer);
+ f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, GLuint(b->binding), bufD->buffer);
else
- f->glBindBufferRange(GL_SHADER_STORAGE_BUFFER, b->binding, bufD->buffer,
+ f->glBindBufferRange(GL_SHADER_STORAGE_BUFFER, GLuint(b->binding), bufD->buffer,
b->u.sbuf.offset, b->u.sbuf.maybeSize ? b->u.sbuf.maybeSize : bufD->m_size);
}
break;
@@ -2541,10 +2569,10 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb,
clearCmd.args.clear.mask |= GL_COLOR_BUFFER_BIT;
if (rtD->dsAttCount && wantsDsClear)
clearCmd.args.clear.mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
- clearCmd.args.clear.c[0] = colorClearValue.redF();
- clearCmd.args.clear.c[1] = colorClearValue.greenF();
- clearCmd.args.clear.c[2] = colorClearValue.blueF();
- clearCmd.args.clear.c[3] = colorClearValue.alphaF();
+ clearCmd.args.clear.c[0] = float(colorClearValue.redF());
+ clearCmd.args.clear.c[1] = float(colorClearValue.greenF());
+ clearCmd.args.clear.c[2] = float(colorClearValue.blueF());
+ clearCmd.args.clear.c[3] = float(colorClearValue.alphaF());
clearCmd.args.clear.d = depthStencilClearValue.depthClearValue();
clearCmd.args.clear.s = depthStencilClearValue.stencilClearValue();
cbD->commands.append(clearCmd);
@@ -2582,7 +2610,7 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
QGles2Texture *colorTexD = QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
const GLenum faceTargetBase = colorTexD->m_flags.testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X
: colorTexD->target;
- cmd.args.blitFromRb.target = faceTargetBase + colorAtt.resolveLayer();
+ cmd.args.blitFromRb.target = faceTargetBase + uint(colorAtt.resolveLayer());
cmd.args.blitFromRb.texture = colorTexD->texture;
cmd.args.blitFromRb.dstLevel = colorAtt.resolveLevel();
cbD->commands.append(cmd);
@@ -2649,9 +2677,9 @@ void QRhiGles2::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
QGles2CommandBuffer::Command cmd;
cmd.cmd = QGles2CommandBuffer::Command::Dispatch;
- cmd.args.dispatch.x = x;
- cmd.args.dispatch.y = y;
- cmd.args.dispatch.z = z;
+ cmd.args.dispatch.x = GLuint(x);
+ cmd.args.dispatch.y = GLuint(y);
+ cmd.args.dispatch.z = GLuint(z);
cbD->commands.append(cmd);
}
@@ -2673,7 +2701,6 @@ static inline GLenum toGlShaderType(QRhiShaderStage::Type type)
bool QRhiGles2::compileShader(GLuint program, const QRhiShaderStage &shaderStage,
QShaderDescription *desc, int *glslVersionUsed)
{
- GLuint shader = f->glCreateShader(toGlShaderType(shaderStage.type()));
const QShader bakedShader = shaderStage.shader();
QVector<int> versionsToTry;
QByteArray source;
@@ -2733,27 +2760,40 @@ bool QRhiGles2::compileShader(GLuint program, const QRhiShaderStage &shaderStage
return false;
}
- const char *srcStr = source.constData();
- const GLint srcLength = source.count();
- f->glShaderSource(shader, 1, &srcStr, &srcLength);
- f->glCompileShader(shader);
- GLint compiled = 0;
- f->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
- if (!compiled) {
- GLint infoLogLength = 0;
- f->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
- QByteArray log;
- if (infoLogLength > 1) {
- GLsizei length = 0;
- log.resize(infoLogLength);
- f->glGetShaderInfoLog(shader, infoLogLength, &length, log.data());
+ GLuint shader;
+ auto cacheIt = m_shaderCache.constFind(shaderStage);
+ if (cacheIt != m_shaderCache.constEnd()) {
+ shader = *cacheIt;
+ } else {
+ shader = f->glCreateShader(toGlShaderType(shaderStage.type()));
+ const char *srcStr = source.constData();
+ const GLint srcLength = source.count();
+ f->glShaderSource(shader, 1, &srcStr, &srcLength);
+ f->glCompileShader(shader);
+ GLint compiled = 0;
+ f->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+ if (!compiled) {
+ GLint infoLogLength = 0;
+ f->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
+ QByteArray log;
+ if (infoLogLength > 1) {
+ GLsizei length = 0;
+ log.resize(infoLogLength);
+ f->glGetShaderInfoLog(shader, infoLogLength, &length, log.data());
+ }
+ qWarning("Failed to compile shader: %s\nSource was:\n%s", log.constData(), source.constData());
+ return false;
}
- qWarning("Failed to compile shader: %s\nSource was:\n%s", log.constData(), source.constData());
- return false;
+ if (m_shaderCache.count() >= MAX_SHADER_CACHE_ENTRIES) {
+ // Use the simplest strategy: too many cached shaders -> drop them all.
+ for (uint shader : m_shaderCache)
+ f->glDeleteShader(shader); // does not actually get released yet when attached to a not-yet-released program
+ m_shaderCache.clear();
+ }
+ m_shaderCache.insert(shaderStage, shader);
}
f->glAttachShader(program, shader);
- f->glDeleteShader(shader);
*desc = bakedShader.description();
return true;
@@ -2791,7 +2831,7 @@ void QRhiGles2::gatherUniforms(GLuint program, const QShaderDescription::Uniform
uniform.glslLocation = f->glGetUniformLocation(program, name.constData());
if (uniform.glslLocation >= 0) {
uniform.binding = ub.binding;
- uniform.offset = blockMember.offset;
+ uniform.offset = uint(blockMember.offset);
uniform.size = blockMember.size;
dst->append(uniform);
}
@@ -2855,7 +2895,7 @@ bool QGles2Buffer::build()
return false;
}
ubuf.resize(nonZeroSize);
- QRHI_PROF_F(newBuffer(this, nonZeroSize, 0, 1));
+ QRHI_PROF_F(newBuffer(this, uint(nonZeroSize), 0, 1));
return true;
}
@@ -2874,7 +2914,7 @@ bool QGles2Buffer::build()
usageState.access = AccessNone;
- QRHI_PROF_F(newBuffer(this, nonZeroSize, 1, 0));
+ QRHI_PROF_F(newBuffer(this, uint(nonZeroSize), 1, 0));
rhiD->registerResource(this);
return true;
}
@@ -3145,13 +3185,13 @@ bool QGles2Texture::build()
for (int layer = 0, layerCount = isCube ? 6 : 1; layer != layerCount; ++layer) {
for (int level = 0; level != mipLevelCount; ++level) {
const QSize mipSize = rhiD->q->sizeForMipLevel(level, size);
- rhiD->f->glTexImage2D(faceTargetBase + layer, level, glintformat,
+ rhiD->f->glTexImage2D(faceTargetBase + uint(layer), level, GLint(glintformat),
mipSize.width(), mipSize.height(), 0,
glformat, gltype, nullptr);
}
}
} else {
- rhiD->f->glTexImage2D(target, 0, glintformat, size.width(), size.height(),
+ rhiD->f->glTexImage2D(target, 0, GLint(glintformat), size.width(), size.height(),
0, glformat, gltype, nullptr);
}
} else {
@@ -3354,14 +3394,15 @@ bool QGles2TextureRenderTarget::build()
QGles2Texture *texD = QRHI_RES(QGles2Texture, texture);
Q_ASSERT(texD->texture && texD->specified);
const GLenum faceTargetBase = texD->flags().testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
- rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, faceTargetBase + colorAtt.layer(), texD->texture, colorAtt.level());
+ rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(i), faceTargetBase + uint(colorAtt.layer()),
+ texD->texture, colorAtt.level());
if (i == 0) {
d.pixelSize = texD->pixelSize();
d.sampleCount = 1;
}
} else if (renderBuffer) {
QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, renderBuffer);
- rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER, rbD->renderbuffer);
+ rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(i), GL_RENDERBUFFER, rbD->renderbuffer);
if (i == 0) {
d.pixelSize = rbD->pixelSize();
d.sampleCount = rbD->samples;
@@ -3511,7 +3552,7 @@ bool QGles2GraphicsPipeline::build()
for (auto inVar : vsDesc.inputVariables()) {
const QByteArray name = inVar.name.toUtf8();
- rhiD->f->glBindAttribLocation(program, inVar.location, name.constData());
+ rhiD->f->glBindAttribLocation(program, GLuint(inVar.location), name.constData());
}
if (!rhiD->linkProgram(program))
@@ -3657,7 +3698,7 @@ bool QGles2SwapChain::buildOrResize()
rt.d.rp = QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
rt.d.pixelSize = pixelSize;
- rt.d.dpr = m_window->devicePixelRatio();
+ rt.d.dpr = float(m_window->devicePixelRatio());
rt.d.sampleCount = qBound(1, m_sampleCount, 64);
rt.d.colorAttCount = 1;
rt.d.dsAttCount = m_depthStencil ? 1 : 0;
diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h
index 6da529be92..e7bcb626b6 100644
--- a/src/gui/rhi/qrhigles2_p_p.h
+++ b/src/gui/rhi/qrhigles2_p_p.h
@@ -664,7 +664,9 @@ public:
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
void sendVMemStatsToProfiler() override;
- void makeThreadLocalNativeContextCurrent() override;
+ bool makeThreadLocalNativeContextCurrent() override;
+ void releaseCachedResources() override;
+ bool isDeviceLost() const override;
bool ensureContext(QSurface *surface = nullptr) const;
void executeDeferredReleases();
@@ -768,6 +770,7 @@ public:
QVector<GLint> supportedCompressedFormats;
mutable QVector<int> supportedSampleCountList;
QRhiGles2NativeHandles nativeHandlesStruct;
+ mutable bool contextLost = false;
struct DeferredReleaseEntry {
enum Type {
@@ -804,6 +807,8 @@ public:
bool active = false;
QGles2CommandBuffer cbWrapper;
} ofr;
+
+ QHash<QRhiShaderStage, uint> m_shaderCache;
};
Q_DECLARE_TYPEINFO(QRhiGles2::DeferredReleaseEntry, Q_MOVABLE_TYPE);
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 07753c985c..0b1ab72c2c 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -138,6 +138,20 @@ QT_BEGIN_NAMESPACE
\l{QRhiCommandBuffer::endPass()}.
*/
+struct QMetalShader
+{
+ id<MTLLibrary> lib = nil;
+ id<MTLFunction> func = nil;
+ std::array<uint, 3> localSize;
+
+ void release() {
+ [lib release];
+ lib = nil;
+ [func release];
+ func = nil;
+ }
+};
+
struct QRhiMetalData
{
QRhiMetalData(QRhiImplementation *rhi) : ofr(rhi) { }
@@ -206,6 +220,8 @@ struct QRhiMetalData
API_AVAILABLE(macos(10.13), ios(11.0)) id<MTLCaptureScope> captureScope = nil;
static const int TEXBUF_ALIGN = 256; // probably not accurate
+
+ QHash<QRhiShaderStage, QMetalShader> shaderCache;
};
Q_DECLARE_TYPEINFO(QRhiMetalData::DeferredReleaseEntry, Q_MOVABLE_TYPE);
@@ -289,17 +305,14 @@ struct QMetalGraphicsPipelineData
MTLPrimitiveType primitiveType;
MTLWinding winding;
MTLCullMode cullMode;
- id<MTLLibrary> vsLib = nil;
- id<MTLFunction> vsFunc = nil;
- id<MTLLibrary> fsLib = nil;
- id<MTLFunction> fsFunc = nil;
+ QMetalShader vs;
+ QMetalShader fs;
};
struct QMetalComputePipelineData
{
id<MTLComputePipelineState> ps = nil;
- id<MTLLibrary> csLib = nil;
- id<MTLFunction> csFunc = nil;
+ QMetalShader cs;
MTLSize localSize;
};
@@ -339,7 +352,8 @@ QRhiMetal::~QRhiMetal()
delete d;
}
-static inline uint aligned(uint v, uint byteAlign)
+template <class Int>
+inline Int aligned(Int v, Int byteAlign)
{
return (v + byteAlign - 1) & ~(byteAlign - 1);
}
@@ -404,6 +418,10 @@ void QRhiMetal::destroy()
executeDeferredReleases(true);
finishActiveReadbacks(true);
+ for (QMetalShader &s : d->shaderCache)
+ s.release();
+ d->shaderCache.clear();
+
if (@available(macOS 10.13, iOS 11.0, *)) {
[d->captureScope release];
d->captureScope = nil;
@@ -565,9 +583,23 @@ void QRhiMetal::sendVMemStatsToProfiler()
// nothing to do here
}
-void QRhiMetal::makeThreadLocalNativeContextCurrent()
+bool QRhiMetal::makeThreadLocalNativeContextCurrent()
{
- // nothing to do here
+ // not applicable
+ return false;
+}
+
+void QRhiMetal::releaseCachedResources()
+{
+ for (QMetalShader &s : d->shaderCache)
+ s.release();
+
+ d->shaderCache.clear();
+}
+
+bool QRhiMetal::isDeviceLost() const
+{
+ return false;
}
QRhiRenderBuffer *QRhiMetal::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
@@ -630,7 +662,7 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
{
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, b->u.ubuf.buf);
id<MTLBuffer> mtlbuf = bufD->d->buf[bufD->d->slotted ? currentFrameSlot : 0];
- uint offset = b->u.ubuf.offset;
+ uint offset = uint(b->u.ubuf.offset);
for (int i = 0; i < dynamicOffsetCount; ++i) {
const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
if (dynOfs.first == b->binding) {
@@ -694,7 +726,7 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
{
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, b->u.sbuf.buf);
id<MTLBuffer> mtlbuf = bufD->d->buf[0];
- uint offset = b->u.sbuf.offset;
+ uint offset = uint(b->u.sbuf.offset);
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
res[0].buffers.feed(b->binding, mtlbuf);
res[0].bufferOffsets.feed(b->binding, offset);
@@ -726,17 +758,17 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
case 0:
[cbD->d->currentRenderPassEncoder setVertexBuffers: bufferBatch.resources.constData()
offsets: offsetBatch.resources.constData()
- withRange: NSMakeRange(bufferBatch.startBinding, bufferBatch.resources.count())];
+ withRange: NSMakeRange(bufferBatch.startBinding, NSUInteger(bufferBatch.resources.count()))];
break;
case 1:
[cbD->d->currentRenderPassEncoder setFragmentBuffers: bufferBatch.resources.constData()
offsets: offsetBatch.resources.constData()
- withRange: NSMakeRange(bufferBatch.startBinding, bufferBatch.resources.count())];
+ withRange: NSMakeRange(bufferBatch.startBinding, NSUInteger(bufferBatch.resources.count()))];
break;
case 2:
[cbD->d->currentComputePassEncoder setBuffers: bufferBatch.resources.constData()
offsets: offsetBatch.resources.constData()
- withRange: NSMakeRange(bufferBatch.startBinding, bufferBatch.resources.count())];
+ withRange: NSMakeRange(bufferBatch.startBinding, NSUInteger(bufferBatch.resources.count()))];
break;
default:
Q_UNREACHABLE();
@@ -755,15 +787,15 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
switch (idx) {
case 0:
[cbD->d->currentRenderPassEncoder setVertexTextures: batch.resources.constData()
- withRange: NSMakeRange(batch.startBinding, batch.resources.count())];
+ withRange: NSMakeRange(batch.startBinding, NSUInteger(batch.resources.count()))];
break;
case 1:
[cbD->d->currentRenderPassEncoder setFragmentTextures: batch.resources.constData()
- withRange: NSMakeRange(batch.startBinding, batch.resources.count())];
+ withRange: NSMakeRange(batch.startBinding, NSUInteger(batch.resources.count()))];
break;
case 2:
[cbD->d->currentComputePassEncoder setTextures: batch.resources.constData()
- withRange: NSMakeRange(batch.startBinding, batch.resources.count())];
+ withRange: NSMakeRange(batch.startBinding, NSUInteger(batch.resources.count()))];
break;
default:
Q_UNREACHABLE();
@@ -775,15 +807,15 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
switch (idx) {
case 0:
[cbD->d->currentRenderPassEncoder setVertexSamplerStates: batch.resources.constData()
- withRange: NSMakeRange(batch.startBinding, batch.resources.count())];
+ withRange: NSMakeRange(batch.startBinding, NSUInteger(batch.resources.count()))];
break;
case 1:
[cbD->d->currentRenderPassEncoder setFragmentSamplerStates: batch.resources.constData()
- withRange: NSMakeRange(batch.startBinding, batch.resources.count())];
+ withRange: NSMakeRange(batch.startBinding, NSUInteger(batch.resources.count()))];
break;
case 2:
[cbD->d->currentComputePassEncoder setSamplerStates: batch.resources.constData()
- withRange: NSMakeRange(batch.startBinding, batch.resources.count())];
+ withRange: NSMakeRange(batch.startBinding, NSUInteger(batch.resources.count()))];
break;
default:
Q_UNREACHABLE();
@@ -981,7 +1013,7 @@ void QRhiMetal::setVertexInput(QRhiCommandBuffer *cb,
[cbD->d->currentRenderPassEncoder setVertexBuffers:
bufferBatch.resources.constData()
offsets: offsetBatch.resources.constData()
- withRange: NSMakeRange(firstVertexBinding + bufferBatch.startBinding, bufferBatch.resources.count())];
+ withRange: NSMakeRange(uint(firstVertexBinding) + bufferBatch.startBinding, NSUInteger(bufferBatch.resources.count()))];
}
}
@@ -997,11 +1029,44 @@ void QRhiMetal::setVertexInput(QRhiCommandBuffer *cb,
}
}
+QSize safeOutputSize(QRhiMetal *rhiD, QMetalCommandBuffer *cbD)
+{
+ QSize size = cbD->currentTarget->pixelSize();
+
+ // So now we have the issue that the texture (drawable) size may have
+ // changed again since swapchain buildOrResize() was called. This can
+ // happen for example when interactively resizing the window a lot in one
+ // go, and command buffer building happens on a dedicated thread (f.ex.
+ // using the threaded render loop of Qt Quick).
+ //
+ // This is only an issue when running in debug mode with XCode because Metal
+ // validation will fail when setting viewport or scissor with the real size
+ // being smaller than what we think it is. So query the drawable size right
+ // here, in debug mode at least.
+ //
+ // In addition, we have to take the smaller of the two widths and heights
+ // to be safe, apparently. In some cases validation seems to think that the
+ // "render pass width" (or height) is the old(?) value.
+
+#ifdef QT_DEBUG
+ if (cbD->currentTarget->resourceType() == QRhiResource::RenderTarget) {
+ Q_ASSERT(rhiD->currentSwapChain);
+ const QSize otherSize = rhiD->currentSwapChain->surfacePixelSize();
+ size.setWidth(qMin(size.width(), otherSize.width()));
+ size.setHeight(qMin(size.height(), otherSize.height()));
+ }
+#else
+ Q_UNUSED(rhiD);
+#endif
+
+ return size;
+}
+
void QRhiMetal::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
{
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::RenderPass);
- const QSize outputSize = cbD->currentTarget->pixelSize();
+ const QSize outputSize = safeOutputSize(this, cbD);
// x,y is top-left in MTLViewportRect but bottom-left in QRhiViewport
float x, y, w, h;
@@ -1009,21 +1074,21 @@ void QRhiMetal::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
return;
MTLViewport vp;
- vp.originX = x;
- vp.originY = y;
- vp.width = w;
- vp.height = h;
- vp.znear = viewport.minDepth();
- vp.zfar = viewport.maxDepth();
+ vp.originX = double(x);
+ vp.originY = double(y);
+ vp.width = double(w);
+ vp.height = double(h);
+ vp.znear = double(viewport.minDepth());
+ vp.zfar = double(viewport.maxDepth());
[cbD->d->currentRenderPassEncoder setViewport: vp];
if (!QRHI_RES(QMetalGraphicsPipeline, cbD->currentGraphicsPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) {
MTLScissorRect s;
- s.x = x;
- s.y = y;
- s.width = w;
- s.height = h;
+ s.x = NSUInteger(x);
+ s.y = NSUInteger(y);
+ s.width = NSUInteger(w);
+ s.height = NSUInteger(h);
[cbD->d->currentRenderPassEncoder setScissorRect: s];
}
}
@@ -1033,7 +1098,7 @@ void QRhiMetal::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::RenderPass);
Q_ASSERT(QRHI_RES(QMetalGraphicsPipeline, cbD->currentGraphicsPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor));
- const QSize outputSize = cbD->currentTarget->pixelSize();
+ const QSize outputSize = safeOutputSize(this, cbD);
// x,y is top-left in MTLScissorRect but bottom-left in QRhiScissor
int x, y, w, h;
@@ -1041,10 +1106,10 @@ void QRhiMetal::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
return;
MTLScissorRect s;
- s.x = x;
- s.y = y;
- s.width = w;
- s.height = h;
+ s.x = NSUInteger(x);
+ s.y = NSUInteger(y);
+ s.width = NSUInteger(w);
+ s.height = NSUInteger(h);
[cbD->d->currentRenderPassEncoder setScissorRect: s];
}
@@ -1054,7 +1119,8 @@ void QRhiMetal::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::RenderPass);
- [cbD->d->currentRenderPassEncoder setBlendColorRed: c.redF() green: c.greenF() blue: c.blueF() alpha: c.alphaF()];
+ [cbD->d->currentRenderPassEncoder setBlendColorRed: float(c.redF())
+ green: float(c.greenF()) blue: float(c.blueF()) alpha: float(c.alphaF())];
}
void QRhiMetal::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
@@ -1086,7 +1152,7 @@ void QRhiMetal::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
return;
const quint32 indexOffset = cbD->currentIndexOffset + firstIndex * (cbD->currentIndexFormat == QRhiCommandBuffer::IndexUInt16 ? 2 : 4);
- Q_ASSERT(indexOffset == aligned(indexOffset, 4));
+ Q_ASSERT(indexOffset == aligned<quint32>(indexOffset, 4));
QMetalBuffer *ibufD = QRHI_RES(QMetalBuffer, cbD->currentIndexBuffer);
id<MTLBuffer> mtlbuf = ibufD->d->buf[ibufD->d->slotted ? currentFrameSlot : 0];
@@ -1344,7 +1410,7 @@ MTLRenderPassDescriptor *QRhiMetalData::createDefaultRenderPass(bool hasDepthSte
MTLClearColor c = MTLClearColorMake(colorClearValue.redF(), colorClearValue.greenF(), colorClearValue.blueF(),
colorClearValue.alphaF());
- for (int i = 0; i < colorAttCount; ++i) {
+ for (uint i = 0; i < uint(colorAttCount); ++i) {
rp.colorAttachments[i].loadAction = MTLLoadActionClear;
rp.colorAttachments[i].storeAction = MTLStoreActionStore;
rp.colorAttachments[i].clearColor = c;
@@ -1355,7 +1421,7 @@ MTLRenderPassDescriptor *QRhiMetalData::createDefaultRenderPass(bool hasDepthSte
rp.depthAttachment.storeAction = MTLStoreActionDontCare;
rp.stencilAttachment.loadAction = MTLLoadActionClear;
rp.stencilAttachment.storeAction = MTLStoreActionDontCare;
- rp.depthAttachment.clearDepth = depthStencilClearValue.depthClearValue();
+ rp.depthAttachment.clearDepth = double(depthStencilClearValue.depthClearValue());
rp.stencilAttachment.clearStencil = depthStencilClearValue.stencilClearValue();
}
@@ -1368,7 +1434,7 @@ qsizetype QRhiMetal::subresUploadByteSize(const QRhiTextureSubresourceUploadDesc
const qsizetype imageSizeBytes = subresDesc.image().isNull() ?
subresDesc.data().size() : subresDesc.image().sizeInBytes();
if (imageSizeBytes > 0)
- size += aligned(imageSizeBytes, QRhiMetalData::TEXBUF_ALIGN);
+ size += aligned<qsizetype>(imageSizeBytes, QRhiMetalData::TEXBUF_ALIGN);
return size;
}
@@ -1396,31 +1462,31 @@ void QRhiMetal::enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEnc
h = subresDesc.sourceSize().height();
}
if (img.depth() == 32) {
- memcpy(reinterpret_cast<char *>(mp) + *curOfs, img.constBits(), fullImageSizeBytes);
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs, img.constBits(), size_t(fullImageSizeBytes));
srcOffset = sy * bpl + sx * 4;
// bpl remains set to the original image's row stride
} else {
img = img.copy(sx, sy, w, h);
bpl = img.bytesPerLine();
Q_ASSERT(img.sizeInBytes() <= fullImageSizeBytes);
- memcpy(reinterpret_cast<char *>(mp) + *curOfs, img.constBits(), img.sizeInBytes());
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs, img.constBits(), size_t(img.sizeInBytes()));
}
} else {
- memcpy(reinterpret_cast<char *>(mp) + *curOfs, img.constBits(), fullImageSizeBytes);
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs, img.constBits(), size_t(fullImageSizeBytes));
}
[blitEnc copyFromBuffer: texD->d->stagingBuf[currentFrameSlot]
- sourceOffset: *curOfs + srcOffset
- sourceBytesPerRow: bpl
+ sourceOffset: NSUInteger(*curOfs + srcOffset)
+ sourceBytesPerRow: NSUInteger(bpl)
sourceBytesPerImage: 0
- sourceSize: MTLSizeMake(w, h, 1)
+ sourceSize: MTLSizeMake(NSUInteger(w), NSUInteger(h), 1)
toTexture: texD->d->tex
- destinationSlice: layer
- destinationLevel: level
- destinationOrigin: MTLOriginMake(dp.x(), dp.y(), 0)
+ destinationSlice: NSUInteger(layer)
+ destinationLevel: NSUInteger(level)
+ destinationOrigin: MTLOriginMake(NSUInteger(dp.x()), NSUInteger(dp.y()), 0)
options: MTLBlitOptionNone];
- *curOfs += aligned(fullImageSizeBytes, QRhiMetalData::TEXBUF_ALIGN);
+ *curOfs += aligned<qsizetype>(fullImageSizeBytes, QRhiMetalData::TEXBUF_ALIGN);
} else if (!rawData.isEmpty() && isCompressedFormat(texD->m_format)) {
const QSize subresSize = q->sizeForMipLevel(level, texD->m_pixelSize);
const int subresw = subresSize.width();
@@ -1445,17 +1511,17 @@ void QRhiMetal::enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEnc
if (dy + h != subresh)
h = aligned(h, blockDim.height());
- memcpy(reinterpret_cast<char *>(mp) + *curOfs, rawData.constData(), rawData.size());
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs, rawData.constData(), size_t(rawData.size()));
[blitEnc copyFromBuffer: texD->d->stagingBuf[currentFrameSlot]
- sourceOffset: *curOfs
+ sourceOffset: NSUInteger(*curOfs)
sourceBytesPerRow: bpl
sourceBytesPerImage: 0
- sourceSize: MTLSizeMake(w, h, 1)
+ sourceSize: MTLSizeMake(NSUInteger(w), NSUInteger(h), 1)
toTexture: texD->d->tex
- destinationSlice: layer
- destinationLevel: level
- destinationOrigin: MTLOriginMake(dx, dy, 0)
+ destinationSlice: NSUInteger(layer)
+ destinationLevel: NSUInteger(level)
+ destinationOrigin: MTLOriginMake(NSUInteger(dx), NSUInteger(dy), 0)
options: MTLBlitOptionNone];
*curOfs += aligned(rawData.size(), QRhiMetalData::TEXBUF_ALIGN);
@@ -1474,17 +1540,17 @@ void QRhiMetal::enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEnc
quint32 bpl = 0;
textureFormatInfo(texD->m_format, QSize(w, h), &bpl, nullptr);
- memcpy(reinterpret_cast<char *>(mp) + *curOfs, rawData.constData(), rawData.size());
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs, rawData.constData(), size_t(rawData.size()));
[blitEnc copyFromBuffer: texD->d->stagingBuf[currentFrameSlot]
- sourceOffset: *curOfs
+ sourceOffset: NSUInteger(*curOfs)
sourceBytesPerRow: bpl
sourceBytesPerImage: 0
- sourceSize: MTLSizeMake(w, h, 1)
+ sourceSize: MTLSizeMake(NSUInteger(w), NSUInteger(h), 1)
toTexture: texD->d->tex
- destinationSlice: layer
- destinationLevel: level
- destinationOrigin: MTLOriginMake(dp.x(), dp.y(), 0)
+ destinationSlice: NSUInteger(layer)
+ destinationLevel: NSUInteger(level)
+ destinationOrigin: MTLOriginMake(NSUInteger(dp.x()), NSUInteger(dp.y()), 0)
options: MTLBlitOptionNone];
*curOfs += aligned(rawData.size(), QRhiMetalData::TEXBUF_ALIGN);
@@ -1538,9 +1604,9 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
ensureBlit();
Q_ASSERT(!utexD->d->stagingBuf[currentFrameSlot]);
- utexD->d->stagingBuf[currentFrameSlot] = [d->dev newBufferWithLength: stagingSize
+ utexD->d->stagingBuf[currentFrameSlot] = [d->dev newBufferWithLength: NSUInteger(stagingSize)
options: MTLResourceStorageModeShared];
- QRHI_PROF_F(newTextureStagingArea(utexD, currentFrameSlot, stagingSize));
+ QRHI_PROF_F(newTextureStagingArea(utexD, currentFrameSlot, quint32(stagingSize)));
void *mp = [utexD->d->stagingBuf[currentFrameSlot] contents];
qsizetype curOfs = 0;
@@ -1570,14 +1636,14 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
ensureBlit();
[blitEnc copyFromTexture: srcD->d->tex
- sourceSlice: u.copy.desc.sourceLayer()
- sourceLevel: u.copy.desc.sourceLevel()
- sourceOrigin: MTLOriginMake(sp.x(), sp.y(), 0)
- sourceSize: MTLSizeMake(size.width(), size.height(), 1)
+ sourceSlice: NSUInteger(u.copy.desc.sourceLayer())
+ sourceLevel: NSUInteger(u.copy.desc.sourceLevel())
+ sourceOrigin: MTLOriginMake(NSUInteger(sp.x()), NSUInteger(sp.y()), 0)
+ sourceSize: MTLSizeMake(NSUInteger(size.width()), NSUInteger(size.height()), 1)
toTexture: dstD->d->tex
- destinationSlice: u.copy.desc.destinationLayer()
- destinationLevel: u.copy.desc.destinationLevel()
- destinationOrigin: MTLOriginMake(dp.x(), dp.y(), 0)];
+ destinationSlice: NSUInteger(u.copy.desc.destinationLayer())
+ destinationLevel: NSUInteger(u.copy.desc.destinationLevel())
+ destinationOrigin: MTLOriginMake(NSUInteger(dp.x()), NSUInteger(dp.y()), 0)];
srcD->lastActiveFrameSlot = dstD->lastActiveFrameSlot = currentFrameSlot;
} else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) {
@@ -1617,16 +1683,16 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
textureFormatInfo(aRb.format, aRb.pixelSize, &bpl, &aRb.bufSize);
aRb.buf = [d->dev newBufferWithLength: aRb.bufSize options: MTLResourceStorageModeShared];
- QRHI_PROF_F(newReadbackBuffer(quint64(quintptr(aRb.buf)),
+ QRHI_PROF_F(newReadbackBuffer(qint64(qintptr(aRb.buf)),
texD ? static_cast<QRhiResource *>(texD) : static_cast<QRhiResource *>(swapChainD),
aRb.bufSize));
ensureBlit();
[blitEnc copyFromTexture: src
- sourceSlice: u.read.rb.layer()
- sourceLevel: u.read.rb.level()
+ sourceSlice: NSUInteger(u.read.rb.layer())
+ sourceLevel: NSUInteger(u.read.rb.level())
sourceOrigin: MTLOriginMake(0, 0, 0)
- sourceSize: MTLSizeMake(srcSize.width(), srcSize.height(), 1)
+ sourceSize: MTLSizeMake(NSUInteger(srcSize.width()), NSUInteger(srcSize.height()), 1)
toBuffer: aRb.buf
destinationOffset: 0
destinationBytesPerRow: bpl
@@ -1664,14 +1730,14 @@ void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
int changeEnd = -1;
for (const QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate &u : updates) {
Q_ASSERT(bufD == QRHI_RES(QMetalBuffer, u.buf));
- memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), u.data.size());
+ memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
if (changeBegin == -1 || u.offset < changeBegin)
changeBegin = u.offset;
if (changeEnd == -1 || u.offset + u.data.size() > changeEnd)
changeEnd = u.offset + u.data.size();
}
if (changeBegin >= 0 && bufD->d->managed)
- [bufD->d->buf[idx] didModifyRange: NSMakeRange(changeBegin, changeEnd - changeBegin)];
+ [bufD->d->buf[idx] didModifyRange: NSMakeRange(NSUInteger(changeBegin), NSUInteger(changeEnd - changeBegin))];
updates.clear();
}
@@ -1728,7 +1794,7 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
rtD = rtTex->d;
cbD->d->currentPassRpDesc = d->createDefaultRenderPass(rtD->dsAttCount, colorClearValue, depthStencilClearValue, rtD->colorAttCount);
if (rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents)) {
- for (int i = 0; i < rtD->colorAttCount; ++i)
+ for (uint i = 0; i < uint(rtD->colorAttCount); ++i)
cbD->d->currentPassRpDesc.colorAttachments[i].loadAction = MTLLoadActionLoad;
}
if (rtD->dsAttCount && rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents)) {
@@ -1755,15 +1821,15 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
break;
}
- for (int i = 0; i < rtD->colorAttCount; ++i) {
+ for (uint i = 0; i < uint(rtD->colorAttCount); ++i) {
cbD->d->currentPassRpDesc.colorAttachments[i].texture = rtD->fb.colorAtt[i].tex;
- cbD->d->currentPassRpDesc.colorAttachments[i].slice = rtD->fb.colorAtt[i].layer;
- cbD->d->currentPassRpDesc.colorAttachments[i].level = rtD->fb.colorAtt[i].level;
+ cbD->d->currentPassRpDesc.colorAttachments[i].slice = NSUInteger(rtD->fb.colorAtt[i].layer);
+ cbD->d->currentPassRpDesc.colorAttachments[i].level = NSUInteger(rtD->fb.colorAtt[i].level);
if (rtD->fb.colorAtt[i].resolveTex) {
cbD->d->currentPassRpDesc.colorAttachments[i].storeAction = MTLStoreActionMultisampleResolve;
cbD->d->currentPassRpDesc.colorAttachments[i].resolveTexture = rtD->fb.colorAtt[i].resolveTex;
- cbD->d->currentPassRpDesc.colorAttachments[i].resolveSlice = rtD->fb.colorAtt[i].resolveLayer;
- cbD->d->currentPassRpDesc.colorAttachments[i].resolveLevel = rtD->fb.colorAtt[i].resolveLevel;
+ cbD->d->currentPassRpDesc.colorAttachments[i].resolveSlice = NSUInteger(rtD->fb.colorAtt[i].resolveLayer);
+ cbD->d->currentPassRpDesc.colorAttachments[i].resolveLevel = NSUInteger(rtD->fb.colorAtt[i].resolveLevel);
}
}
@@ -1845,7 +1911,7 @@ void QRhiMetal::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::ComputePass);
QMetalComputePipeline *psD = QRHI_RES(QMetalComputePipeline, cbD->currentComputePipeline);
- [cbD->d->currentComputePassEncoder dispatchThreadgroups: MTLSizeMake(x, y, z)
+ [cbD->d->currentComputePassEncoder dispatchThreadgroups: MTLSizeMake(NSUInteger(x), NSUInteger(y), NSUInteger(z))
threadsPerThreadgroup: psD->d->localSize];
}
@@ -1913,12 +1979,12 @@ void QRhiMetal::finishActiveReadbacks(bool forced)
if (forced || currentFrameSlot == aRb.activeFrameSlot || aRb.activeFrameSlot < 0) {
aRb.result->format = aRb.format;
aRb.result->pixelSize = aRb.pixelSize;
- aRb.result->data.resize(aRb.bufSize);
+ aRb.result->data.resize(int(aRb.bufSize));
void *p = [aRb.buf contents];
memcpy(aRb.result->data.data(), p, aRb.bufSize);
[aRb.buf release];
- QRHI_PROF_F(releaseReadbackBuffer(quint64(quintptr(aRb.buf))));
+ QRHI_PROF_F(releaseReadbackBuffer(qint64(qintptr(aRb.buf))));
if (aRb.result->completed)
completedCallbacks.append(aRb.result->completed);
@@ -1977,8 +2043,8 @@ bool QMetalBuffer::build()
return false;
}
- const int nonZeroSize = m_size <= 0 ? 256 : m_size;
- const int roundedSize = m_usage.testFlag(QRhiBuffer::UniformBuffer) ? aligned(nonZeroSize, 256) : nonZeroSize;
+ const uint nonZeroSize = m_size <= 0 ? 256 : uint(m_size);
+ const uint roundedSize = m_usage.testFlag(QRhiBuffer::UniformBuffer) ? aligned<uint>(nonZeroSize, 256) : nonZeroSize;
d->managed = false;
MTLResourceOptions opts = MTLResourceStorageModeShared;
@@ -2065,10 +2131,10 @@ bool QMetalRenderBuffer::build()
MTLTextureDescriptor *desc = [[MTLTextureDescriptor alloc] init];
desc.textureType = samples > 1 ? MTLTextureType2DMultisample : MTLTextureType2D;
- desc.width = m_pixelSize.width();
- desc.height = m_pixelSize.height();
+ desc.width = NSUInteger(m_pixelSize.width());
+ desc.height = NSUInteger(m_pixelSize.height());
if (samples > 1)
- desc.sampleCount = samples;
+ desc.sampleCount = NSUInteger(samples);
desc.resourceOptions = MTLResourceStorageModePrivate;
desc.usage = MTLTextureUsageRenderTarget;
@@ -2335,11 +2401,11 @@ bool QMetalTexture::build()
else
desc.textureType = samples > 1 ? MTLTextureType2DMultisample : MTLTextureType2D;
desc.pixelFormat = d->format;
- desc.width = size.width();
- desc.height = size.height();
- desc.mipmapLevelCount = mipLevelCount;
+ desc.width = NSUInteger(size.width());
+ desc.height = NSUInteger(size.height());
+ desc.mipmapLevelCount = NSUInteger(mipLevelCount);
if (samples > 1)
- desc.sampleCount = samples;
+ desc.sampleCount = NSUInteger(samples);
desc.resourceOptions = MTLResourceStorageModePrivate;
desc.storageMode = MTLStorageModePrivate;
desc.usage = MTLTextureUsageShaderRead;
@@ -2405,7 +2471,7 @@ id<MTLTexture> QMetalTextureData::viewForLevel(int level)
const MTLTextureType type = [tex textureType];
const bool isCube = q->m_flags.testFlag(QRhiTexture::CubeMap);
id<MTLTexture> view = [tex newTextureViewWithPixelFormat: format textureType: type
- levels: NSMakeRange(level, 1) slices: NSMakeRange(0, isCube ? 6 : 1)];
+ levels: NSMakeRange(NSUInteger(level), 1) slices: NSMakeRange(0, isCube ? 6 : 1)];
perLevelViews[level] = view;
return view;
@@ -2615,13 +2681,13 @@ QRhiRenderPassDescriptor *QMetalTextureRenderTarget::newCompatibleRenderPassDesc
for (int i = 0, ie = colorAttachments.count(); i != ie; ++i) {
QMetalTexture *texD = QRHI_RES(QMetalTexture, colorAttachments[i].texture());
QMetalRenderBuffer *rbD = QRHI_RES(QMetalRenderBuffer, colorAttachments[i].renderBuffer());
- rpD->colorFormat[i] = texD ? texD->d->format : rbD->d->format;
+ rpD->colorFormat[i] = int(texD ? texD->d->format : rbD->d->format);
}
if (m_desc.depthTexture())
- rpD->dsFormat = QRHI_RES(QMetalTexture, m_desc.depthTexture())->d->format;
+ rpD->dsFormat = int(QRHI_RES(QMetalTexture, m_desc.depthTexture())->d->format);
else if (m_desc.depthStencilBuffer())
- rpD->dsFormat = QRHI_RES(QMetalRenderBuffer, m_desc.depthStencilBuffer())->d->format;
+ rpD->dsFormat = int(QRHI_RES(QMetalRenderBuffer, m_desc.depthStencilBuffer())->d->format);
return rpD;
}
@@ -2810,36 +2876,17 @@ void QMetalGraphicsPipeline::release()
{
QRHI_RES_RHI(QRhiMetal);
- if (!d->ps)
- return;
-
- if (d->ps) {
- [d->ps release];
- d->ps = nil;
- }
+ d->vs.release();
+ d->fs.release();
- if (d->ds) {
- [d->ds release];
- d->ds = nil;
- }
+ [d->ds release];
+ d->ds = nil;
- if (d->vsFunc) {
- [d->vsFunc release];
- d->vsFunc = nil;
- }
- if (d->vsLib) {
- [d->vsLib release];
- d->vsLib = nil;
- }
+ if (!d->ps)
+ return;
- if (d->fsFunc) {
- [d->fsFunc release];
- d->fsFunc = nil;
- }
- if (d->fsLib) {
- [d->fsLib release];
- d->fsLib = nil;
- }
+ [d->ps release];
+ d->ps = nil;
rhiD->unregisterResource(this);
}
@@ -3040,7 +3087,7 @@ id<MTLLibrary> QRhiMetalData::createMetalLib(const QShader &shader, QShader::Var
QShaderCode mtllib = shader.shader({ QShader::MetalLibShader, 12, shaderVariant });
if (!mtllib.shader().isEmpty()) {
dispatch_data_t data = dispatch_data_create(mtllib.shader().constData(),
- mtllib.shader().size(),
+ size_t(mtllib.shader().size()),
dispatch_get_global_queue(0, 0),
DISPATCH_DATA_DESTRUCTOR_DEFAULT);
NSError *err = nil;
@@ -3100,19 +3147,19 @@ bool QMetalGraphicsPipeline::build()
MTLVertexDescriptor *inputLayout = [MTLVertexDescriptor vertexDescriptor];
const QVector<QRhiVertexInputAttribute> attributes = m_vertexInputLayout.attributes();
for (const QRhiVertexInputAttribute &attribute : attributes) {
- const int loc = attribute.location();
+ const uint loc = uint(attribute.location());
inputLayout.attributes[loc].format = toMetalAttributeFormat(attribute.format());
- inputLayout.attributes[loc].offset = attribute.offset();
- inputLayout.attributes[loc].bufferIndex = firstVertexBinding + attribute.binding();
+ inputLayout.attributes[loc].offset = NSUInteger(attribute.offset());
+ inputLayout.attributes[loc].bufferIndex = NSUInteger(firstVertexBinding + attribute.binding());
}
const QVector<QRhiVertexInputBinding> bindings = m_vertexInputLayout.bindings();
for (int i = 0, ie = bindings.count(); i != ie; ++i) {
const QRhiVertexInputBinding &binding(bindings[i]);
- const int layoutIdx = firstVertexBinding + i;
+ const uint layoutIdx = uint(firstVertexBinding + i);
inputLayout.layouts[layoutIdx].stepFunction =
binding.classification() == QRhiVertexInputBinding::PerInstance
? MTLVertexStepFunctionPerInstance : MTLVertexStepFunctionPerVertex;
- inputLayout.layouts[layoutIdx].stepRate = binding.instanceStepRate();
+ inputLayout.layouts[layoutIdx].stepRate = NSUInteger(binding.instanceStepRate());
inputLayout.layouts[layoutIdx].stride = binding.stride();
}
@@ -3126,34 +3173,66 @@ bool QMetalGraphicsPipeline::build()
// buffers not just the resource binding layout) so leave it at the default
for (const QRhiShaderStage &shaderStage : qAsConst(m_shaderStages)) {
- QString error;
- QByteArray entryPoint;
- id<MTLLibrary> lib = rhiD->d->createMetalLib(shaderStage.shader(), shaderStage.shaderVariant(), &error, &entryPoint);
- if (!lib) {
- qWarning("MSL shader compilation failed: %s", qPrintable(error));
- return false;
- }
- id<MTLFunction> func = rhiD->d->createMSLShaderFunction(lib, entryPoint);
- if (!func) {
- qWarning("MSL function for entry point %s not found", entryPoint.constData());
- [lib release];
- return false;
- }
- switch (shaderStage.type()) {
- case QRhiShaderStage::Vertex:
- rpDesc.vertexFunction = func;
- d->vsLib = lib;
- d->vsFunc = func;
- break;
- case QRhiShaderStage::Fragment:
- rpDesc.fragmentFunction = func;
- d->fsLib = lib;
- d->fsFunc = func;
- break;
- default:
- [func release];
- [lib release];
- break;
+ auto cacheIt = rhiD->d->shaderCache.constFind(shaderStage);
+ if (cacheIt != rhiD->d->shaderCache.constEnd()) {
+ switch (shaderStage.type()) {
+ case QRhiShaderStage::Vertex:
+ d->vs = *cacheIt;
+ [d->vs.lib retain];
+ [d->vs.func retain];
+ rpDesc.vertexFunction = d->vs.func;
+ break;
+ case QRhiShaderStage::Fragment:
+ d->fs = *cacheIt;
+ [d->fs.lib retain];
+ [d->fs.func retain];
+ rpDesc.fragmentFunction = d->fs.func;
+ break;
+ default:
+ break;
+ }
+ } else {
+ QString error;
+ QByteArray entryPoint;
+ id<MTLLibrary> lib = rhiD->d->createMetalLib(shaderStage.shader(), shaderStage.shaderVariant(), &error, &entryPoint);
+ if (!lib) {
+ qWarning("MSL shader compilation failed: %s", qPrintable(error));
+ return false;
+ }
+ id<MTLFunction> func = rhiD->d->createMSLShaderFunction(lib, entryPoint);
+ if (!func) {
+ qWarning("MSL function for entry point %s not found", entryPoint.constData());
+ [lib release];
+ return false;
+ }
+ if (rhiD->d->shaderCache.count() >= QRhiMetal::MAX_SHADER_CACHE_ENTRIES) {
+ // Use the simplest strategy: too many cached shaders -> drop them all.
+ for (QMetalShader &s : rhiD->d->shaderCache)
+ s.release();
+ rhiD->d->shaderCache.clear();
+ }
+ switch (shaderStage.type()) {
+ case QRhiShaderStage::Vertex:
+ d->vs.lib = lib;
+ d->vs.func = func;
+ rhiD->d->shaderCache.insert(shaderStage, d->vs);
+ [d->vs.lib retain];
+ [d->vs.func retain];
+ rpDesc.vertexFunction = func;
+ break;
+ case QRhiShaderStage::Fragment:
+ d->fs.lib = lib;
+ d->fs.func = func;
+ rhiD->d->shaderCache.insert(shaderStage, d->fs);
+ [d->fs.lib retain];
+ [d->fs.func retain];
+ rpDesc.fragmentFunction = func;
+ break;
+ default:
+ [func release];
+ [lib release];
+ break;
+ }
}
}
@@ -3168,8 +3247,8 @@ bool QMetalGraphicsPipeline::build()
Q_ASSERT(m_targetBlends.count() == rpD->colorAttachmentCount
|| (m_targetBlends.isEmpty() && rpD->colorAttachmentCount == 1));
- for (int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
- const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
+ for (uint i = 0, ie = uint(m_targetBlends.count()); i != ie; ++i) {
+ const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[int(i)]);
rpDesc.colorAttachments[i].pixelFormat = MTLPixelFormat(rpD->colorFormat[i]);
rpDesc.colorAttachments[i].blendingEnabled = b.enable;
rpDesc.colorAttachments[i].sourceRGBBlendFactor = toMetalBlendFactor(b.srcColor);
@@ -3191,7 +3270,7 @@ bool QMetalGraphicsPipeline::build()
rpDesc.stencilAttachmentPixelFormat = fmt;
}
- rpDesc.sampleCount = rhiD->effectiveSampleCount(m_sampleCount);
+ rpDesc.sampleCount = NSUInteger(rhiD->effectiveSampleCount(m_sampleCount));
NSError *err = nil;
d->ps = [rhiD->d->dev newRenderPipelineStateWithDescriptor: rpDesc error: &err];
@@ -3253,22 +3332,13 @@ void QMetalComputePipeline::release()
{
QRHI_RES_RHI(QRhiMetal);
- if (d->csFunc) {
- [d->csFunc release];
- d->csFunc = nil;
- }
- if (d->csLib) {
- [d->csLib release];
- d->csLib = nil;
- }
+ d->cs.release();
if (!d->ps)
return;
- if (d->ps) {
- [d->ps release];
- d->ps = nil;
- }
+ [d->ps release];
+ d->ps = nil;
rhiD->unregisterResource(this);
}
@@ -3280,28 +3350,44 @@ bool QMetalComputePipeline::build()
QRHI_RES_RHI(QRhiMetal);
- const QShader shader = m_shaderStage.shader();
- QString error;
- QByteArray entryPoint;
- id<MTLLibrary> lib = rhiD->d->createMetalLib(shader, m_shaderStage.shaderVariant(),
- &error, &entryPoint);
- if (!lib) {
- qWarning("MSL shader compilation failed: %s", qPrintable(error));
- return false;
- }
- id<MTLFunction> func = rhiD->d->createMSLShaderFunction(lib, entryPoint);
- if (!func) {
- qWarning("MSL function for entry point %s not found", entryPoint.constData());
- [lib release];
- return false;
+ auto cacheIt = rhiD->d->shaderCache.constFind(m_shaderStage);
+ if (cacheIt != rhiD->d->shaderCache.constEnd()) {
+ d->cs = *cacheIt;
+ } else {
+ const QShader shader = m_shaderStage.shader();
+ QString error;
+ QByteArray entryPoint;
+ id<MTLLibrary> lib = rhiD->d->createMetalLib(shader, m_shaderStage.shaderVariant(),
+ &error, &entryPoint);
+ if (!lib) {
+ qWarning("MSL shader compilation failed: %s", qPrintable(error));
+ return false;
+ }
+ id<MTLFunction> func = rhiD->d->createMSLShaderFunction(lib, entryPoint);
+ if (!func) {
+ qWarning("MSL function for entry point %s not found", entryPoint.constData());
+ [lib release];
+ return false;
+ }
+ d->cs.lib = lib;
+ d->cs.func = func;
+ d->cs.localSize = shader.description().computeShaderLocalSize();
+
+ if (rhiD->d->shaderCache.count() >= QRhiMetal::MAX_SHADER_CACHE_ENTRIES) {
+ for (QMetalShader &s : rhiD->d->shaderCache)
+ s.release();
+ rhiD->d->shaderCache.clear();
+ }
+ rhiD->d->shaderCache.insert(m_shaderStage, d->cs);
}
- d->csLib = lib;
- d->csFunc = func;
- std::array<uint, 3> localSize = shader.description().computeShaderLocalSize();
- d->localSize = MTLSizeMake(localSize[0], localSize[1], localSize[2]);
+
+ [d->cs.lib retain];
+ [d->cs.func retain];
+
+ d->localSize = MTLSizeMake(d->cs.localSize[0], d->cs.localSize[1], d->cs.localSize[2]);
NSError *err = nil;
- d->ps = [rhiD->d->dev newComputePipelineStateWithFunction: d->csFunc error: &err];
+ d->ps = [rhiD->d->dev newComputePipelineStateWithFunction: d->cs.func error: &err];
if (!d->ps) {
const QString msg = QString::fromNSString(err.localizedDescription);
qWarning("Failed to create render pipeline state: %s", qPrintable(msg));
@@ -3439,7 +3525,7 @@ QSize QMetalSwapChain::surfacePixelSize()
CAMetalLayer *layer = (CAMetalLayer *) [v layer];
if (layer) {
CGSize size = [layer drawableSize];
- return QSize(size.width, size.height);
+ return QSize(int(size.width), int(size.height));
}
}
return QSize();
@@ -3454,7 +3540,7 @@ QRhiRenderPassDescriptor *QMetalSwapChain::newCompatibleRenderPassDescriptor()
rpD->colorAttachmentCount = 1;
rpD->hasDepthStencil = m_depthStencil != nullptr;
- rpD->colorFormat[0] = d->colorFormat;
+ rpD->colorFormat[0] = int(d->colorFormat);
// m_depthStencil may not be built yet so cannot rely on computed fields in it
rpD->dsFormat = rhiD->d->dev.depth24Stencil8PixelFormatSupported
@@ -3511,6 +3597,18 @@ bool QMetalSwapChain::buildOrResize()
}
#endif
+ if (m_flags.testFlag(SurfaceHasPreMulAlpha)) {
+ d->layer.opaque = NO;
+ } else if (m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
+ // The CoreAnimation compositor is said to expect premultiplied alpha,
+ // so this is then wrong when it comes to the blending operations but
+ // there's nothing we can do. Fortunately Qt Quick always outputs
+ // premultiplied alpha so it is not a problem there.
+ d->layer.opaque = NO;
+ } else {
+ d->layer.opaque = YES;
+ }
+
m_currentPixelSize = surfacePixelSize();
pixelSize = m_currentPixelSize;
@@ -3538,7 +3636,7 @@ bool QMetalSwapChain::buildOrResize()
}
rtWrapper.d->pixelSize = pixelSize;
- rtWrapper.d->dpr = window->devicePixelRatio();
+ rtWrapper.d->dpr = float(window->devicePixelRatio());
rtWrapper.d->sampleCount = samples;
rtWrapper.d->colorAttCount = 1;
rtWrapper.d->dsAttCount = ds ? 1 : 0;
@@ -3549,9 +3647,9 @@ bool QMetalSwapChain::buildOrResize()
MTLTextureDescriptor *desc = [[MTLTextureDescriptor alloc] init];
desc.textureType = MTLTextureType2DMultisample;
desc.pixelFormat = d->colorFormat;
- desc.width = pixelSize.width();
- desc.height = pixelSize.height();
- desc.sampleCount = samples;
+ desc.width = NSUInteger(pixelSize.width());
+ desc.height = NSUInteger(pixelSize.height());
+ desc.sampleCount = NSUInteger(samples);
desc.resourceOptions = MTLResourceStorageModePrivate;
desc.storageMode = MTLStorageModePrivate;
desc.usage = MTLTextureUsageRenderTarget;
diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h
index c448865f4d..a08f56072a 100644
--- a/src/gui/rhi/qrhimetal_p_p.h
+++ b/src/gui/rhi/qrhimetal_p_p.h
@@ -416,7 +416,9 @@ public:
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
void sendVMemStatsToProfiler() override;
- void makeThreadLocalNativeContextCurrent() override;
+ bool makeThreadLocalNativeContextCurrent() override;
+ void releaseCachedResources() override;
+ bool isDeviceLost() const override;
void executeDeferredReleases(bool forced = false);
void finishActiveReadbacks(bool forced = false);
diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp
index dff6e05268..60d620813b 100644
--- a/src/gui/rhi/qrhinull.cpp
+++ b/src/gui/rhi/qrhinull.cpp
@@ -169,11 +169,22 @@ void QRhiNull::sendVMemStatsToProfiler()
// nothing to do here
}
-void QRhiNull::makeThreadLocalNativeContextCurrent()
+bool QRhiNull::makeThreadLocalNativeContextCurrent()
+{
+ // not applicable
+ return false;
+}
+
+void QRhiNull::releaseCachedResources()
{
// nothing to do here
}
+bool QRhiNull::isDeviceLost() const
+{
+ return false;
+}
+
QRhiRenderBuffer *QRhiNull::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
int sampleCount, QRhiRenderBuffer::Flags flags)
{
diff --git a/src/gui/rhi/qrhinull_p_p.h b/src/gui/rhi/qrhinull_p_p.h
index bdf0d59724..ee301d247b 100644
--- a/src/gui/rhi/qrhinull_p_p.h
+++ b/src/gui/rhi/qrhinull_p_p.h
@@ -282,7 +282,9 @@ public:
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
void sendVMemStatsToProfiler() override;
- void makeThreadLocalNativeContextCurrent() override;
+ bool makeThreadLocalNativeContextCurrent() override;
+ void releaseCachedResources() override;
+ bool isDeviceLost() const override;
QRhiNullNativeHandles nativeHandlesStruct;
QRhiSwapChain *currentSwapChain = nullptr;
diff --git a/src/gui/rhi/qrhiprofiler.cpp b/src/gui/rhi/qrhiprofiler.cpp
index e74e446a1c..1521c0f36e 100644
--- a/src/gui/rhi/qrhiprofiler.cpp
+++ b/src/gui/rhi/qrhiprofiler.cpp
@@ -319,7 +319,7 @@ void QRhiProfilerPrivate::writeFloat(const char *key, float f)
Q_ASSERT(key[0] == 'F');
buf.append(key);
buf.append(',');
- buf.append(QByteArray::number(f));
+ buf.append(QByteArray::number(double(f)));
buf.append(',');
}
@@ -385,7 +385,7 @@ void QRhiProfilerPrivate::newRenderBuffer(QRhiRenderBuffer *rb, bool transientBa
const QRhiTexture::Format assumedFormat = type == QRhiRenderBuffer::DepthStencil ? QRhiTexture::D32F : QRhiTexture::RGBA8;
quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(assumedFormat, sz, 1, 1);
if (sampleCount > 1)
- byteSize *= sampleCount;
+ byteSize *= uint(sampleCount);
startEntry(QRhiProfiler::NewRenderBuffer, ts.elapsed(), rb);
writeInt("type", type);
@@ -416,7 +416,7 @@ void QRhiProfilerPrivate::newTexture(QRhiTexture *tex, bool owns, int mipCount,
const QSize sz = tex->pixelSize();
quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(format, sz, mipCount, layerCount);
if (sampleCount > 1)
- byteSize *= sampleCount;
+ byteSize *= uint(sampleCount);
startEntry(QRhiProfiler::NewTexture, ts.elapsed(), tex);
writeInt("width", sz.width());
@@ -467,7 +467,7 @@ void QRhiProfilerPrivate::resizeSwapChain(QRhiSwapChain *sc, int bufferCount, in
const QSize sz = sc->currentPixelSize();
quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(QRhiTexture::BGRA8, sz, 1, 1);
- byteSize = byteSize * bufferCount + byteSize * msaaBufferCount * sampleCount;
+ byteSize = byteSize * uint(bufferCount) + byteSize * uint(msaaBufferCount) * uint(sampleCount);
startEntry(QRhiProfiler::ResizeSwapChain, ts.elapsed(), sc);
writeInt("width", sz.width());
@@ -569,7 +569,7 @@ void QRhiProfilerPrivate::swapChainFrameGpuTime(QRhiSwapChain *sc, float gpuTime
}
}
-void QRhiProfilerPrivate::newReadbackBuffer(quint64 id, QRhiResource *src, quint32 size)
+void QRhiProfilerPrivate::newReadbackBuffer(qint64 id, QRhiResource *src, quint32 size)
{
if (!outputDevice)
return;
@@ -580,7 +580,7 @@ void QRhiProfilerPrivate::newReadbackBuffer(quint64 id, QRhiResource *src, quint
endEntry();
}
-void QRhiProfilerPrivate::releaseReadbackBuffer(quint64 id)
+void QRhiProfilerPrivate::releaseReadbackBuffer(qint64 id)
{
if (!outputDevice)
return;
@@ -590,7 +590,7 @@ void QRhiProfilerPrivate::releaseReadbackBuffer(quint64 id)
endEntry();
}
-void QRhiProfilerPrivate::vmemStat(int realAllocCount, int subAllocCount, quint32 totalSize, quint32 unusedSize)
+void QRhiProfilerPrivate::vmemStat(uint realAllocCount, uint subAllocCount, quint32 totalSize, quint32 unusedSize)
{
if (!outputDevice)
return;
diff --git a/src/gui/rhi/qrhiprofiler_p_p.h b/src/gui/rhi/qrhiprofiler_p_p.h
index 49c6bd78ed..7d0f183fb1 100644
--- a/src/gui/rhi/qrhiprofiler_p_p.h
+++ b/src/gui/rhi/qrhiprofiler_p_p.h
@@ -79,10 +79,10 @@ public:
void endSwapChainFrame(QRhiSwapChain *sc, int frameCount);
void swapChainFrameGpuTime(QRhiSwapChain *sc, float gpuTimeMs);
- void newReadbackBuffer(quint64 id, QRhiResource *src, quint32 size);
- void releaseReadbackBuffer(quint64 id);
+ void newReadbackBuffer(qint64 id, QRhiResource *src, quint32 size);
+ void releaseReadbackBuffer(qint64 id);
- void vmemStat(int realAllocCount, int subAllocCount, quint32 totalSize, quint32 unusedSize);
+ void vmemStat(uint realAllocCount, uint subAllocCount, quint32 totalSize, quint32 unusedSize);
void startEntry(QRhiProfiler::StreamOp op, qint64 timestamp, QRhiResource *res);
void writeInt(const char *key, qint64 v);
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index dfc85fb853..444c91dd75 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -211,7 +211,8 @@ QT_BEGIN_NAMESPACE
\brief Holds the Vulkan render pass object backing a QRhiRenderPassDescriptor.
*/
-static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+template <class Int>
+inline Int aligned(Int v, Int byteAlign)
{
return (v + byteAlign - 1) & ~(byteAlign - 1);
}
@@ -370,7 +371,7 @@ bool QRhiVulkan::create(QRhi::Flags flags)
auto queryQueueFamilyProps = [this, &queueFamilyProps] {
uint32_t queueCount = 0;
f->vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
- queueFamilyProps.resize(queueCount);
+ queueFamilyProps.resize(int(queueCount));
f->vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueFamilyProps.data());
};
@@ -387,22 +388,42 @@ bool QRhiVulkan::create(QRhi::Flags flags)
qWarning("Failed to enumerate physical devices: %d", err);
return false;
}
+
int physDevIndex = -1;
int requestedPhysDevIndex = -1;
if (qEnvironmentVariableIsSet("QT_VK_PHYSICAL_DEVICE_INDEX"))
requestedPhysDevIndex = qEnvironmentVariableIntValue("QT_VK_PHYSICAL_DEVICE_INDEX");
- for (uint32_t i = 0; i < physDevCount; ++i) {
+
+ if (requestedPhysDevIndex < 0 && flags.testFlag(QRhi::PreferSoftwareRenderer)) {
+ for (int i = 0; i < int(physDevCount); ++i) {
+ f->vkGetPhysicalDeviceProperties(physDevs[i], &physDevProperties);
+ if (physDevProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
+ requestedPhysDevIndex = i;
+ break;
+ }
+ }
+ }
+
+ for (int i = 0; i < int(physDevCount); ++i) {
f->vkGetPhysicalDeviceProperties(physDevs[i], &physDevProperties);
- qCDebug(QRHI_LOG_INFO, "Physical device %d: '%s' %d.%d.%d", i,
+ qCDebug(QRHI_LOG_INFO, "Physical device %d: '%s' %d.%d.%d (api %d.%d.%d vendor 0x%X device 0x%X type %d)",
+ i,
physDevProperties.deviceName,
VK_VERSION_MAJOR(physDevProperties.driverVersion),
VK_VERSION_MINOR(physDevProperties.driverVersion),
- VK_VERSION_PATCH(physDevProperties.driverVersion));
+ VK_VERSION_PATCH(physDevProperties.driverVersion),
+ VK_VERSION_MAJOR(physDevProperties.apiVersion),
+ VK_VERSION_MINOR(physDevProperties.apiVersion),
+ VK_VERSION_PATCH(physDevProperties.apiVersion),
+ physDevProperties.vendorID,
+ physDevProperties.deviceID,
+ physDevProperties.deviceType);
if (physDevIndex < 0 && (requestedPhysDevIndex < 0 || requestedPhysDevIndex == int(i))) {
physDevIndex = i;
qCDebug(QRHI_LOG_INFO, " using this physical device");
}
}
+
if (physDevIndex < 0) {
qWarning("No matching physical device");
return false;
@@ -423,7 +444,7 @@ bool QRhiVulkan::create(QRhi::Flags flags)
i, queueFamilyProps[i].queueFlags, queueFamilyProps[i].queueCount);
if (gfxQueueFamilyIdx == -1
&& (queueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
- && (!maybeWindow || inst->supportsPresent(physDev, i, maybeWindow)))
+ && (!maybeWindow || inst->supportsPresent(physDev, uint32_t(i), maybeWindow)))
{
if (queueFamilyProps[i].queueFlags & VK_QUEUE_COMPUTE_BIT)
gfxQueueFamilyIdx = i;
@@ -444,7 +465,7 @@ bool QRhiVulkan::create(QRhi::Flags flags)
const float prio[] = { 0 };
memset(queueInfo, 0, sizeof(queueInfo));
queueInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
- queueInfo[0].queueFamilyIndex = gfxQueueFamilyIdx;
+ queueInfo[0].queueFamilyIndex = uint32_t(gfxQueueFamilyIdx);
queueInfo[0].queueCount = 1;
queueInfo[0].pQueuePriorities = prio;
@@ -480,9 +501,9 @@ bool QRhiVulkan::create(QRhi::Flags flags)
devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
devInfo.queueCreateInfoCount = 1;
devInfo.pQueueCreateInfos = queueInfo;
- devInfo.enabledLayerCount = devLayers.count();
+ devInfo.enabledLayerCount = uint32_t(devLayers.count());
devInfo.ppEnabledLayerNames = devLayers.constData();
- devInfo.enabledExtensionCount = requestedDevExts.count();
+ devInfo.enabledExtensionCount = uint32_t(requestedDevExts.count());
devInfo.ppEnabledExtensionNames = requestedDevExts.constData();
err = f->vkCreateDevice(physDev, &devInfo, nullptr, &dev);
@@ -498,7 +519,7 @@ bool QRhiVulkan::create(QRhi::Flags flags)
VkCommandPoolCreateInfo poolInfo;
memset(&poolInfo, 0, sizeof(poolInfo));
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- poolInfo.queueFamilyIndex = gfxQueueFamilyIdx;
+ poolInfo.queueFamilyIndex = uint32_t(gfxQueueFamilyIdx);
VkResult err = df->vkCreateCommandPool(dev, &poolInfo, nullptr, &cmdPool);
if (err != VK_SUCCESS) {
qWarning("Failed to create command pool: %d", err);
@@ -508,7 +529,7 @@ bool QRhiVulkan::create(QRhi::Flags flags)
if (gfxQueueFamilyIdx != -1) {
if (!gfxQueue)
- df->vkGetDeviceQueue(dev, gfxQueueFamilyIdx, 0, &gfxQueue);
+ df->vkGetDeviceQueue(dev, uint32_t(gfxQueueFamilyIdx), 0, &gfxQueue);
if (queueFamilyProps.isEmpty())
queryQueueFamilyProps();
@@ -588,6 +609,8 @@ bool QRhiVulkan::create(QRhi::Flags flags)
vkDebugMarkerSetObjectName = reinterpret_cast<PFN_vkDebugMarkerSetObjectNameEXT>(f->vkGetDeviceProcAddr(dev, "vkDebugMarkerSetObjectNameEXT"));
}
+ deviceLost = false;
+
nativeHandlesStruct.physDev = physDev;
nativeHandlesStruct.dev = dev;
nativeHandlesStruct.gfxQueueFamilyIdx = gfxQueueFamilyIdx;
@@ -603,7 +626,8 @@ void QRhiVulkan::destroy()
if (!df)
return;
- df->vkDeviceWaitIdle(dev);
+ if (!deviceLost)
+ df->vkDeviceWaitIdle(dev);
executeDeferredReleases(true);
finishActiveReadbacks(true);
@@ -691,7 +715,7 @@ bool QRhiVulkan::allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, V
df->vkResetDescriptorPool(dev, descriptorPools[i].pool, 0);
descriptorPools[i].allocedDescSets = 0;
}
- if (descriptorPools[i].allocedDescSets + allocInfo->descriptorSetCount <= QVK_DESC_SETS_PER_POOL) {
+ if (descriptorPools[i].allocedDescSets + int(allocInfo->descriptorSetCount) <= QVK_DESC_SETS_PER_POOL) {
VkResult err = tryAllocate(i);
if (err == VK_SUCCESS) {
descriptorPools[i].allocedDescSets += allocInfo->descriptorSetCount;
@@ -901,8 +925,8 @@ bool QRhiVulkan::createTransientImage(VkFormat format,
imgInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imgInfo.imageType = VK_IMAGE_TYPE_2D;
imgInfo.format = format;
- imgInfo.extent.width = pixelSize.width();
- imgInfo.extent.height = pixelSize.height();
+ imgInfo.extent.width = uint32_t(pixelSize.width());
+ imgInfo.extent.height = uint32_t(pixelSize.height());
imgInfo.extent.depth = 1;
imgInfo.mipLevels = imgInfo.arrayLayers = 1;
imgInfo.samples = samples;
@@ -925,7 +949,7 @@ bool QRhiVulkan::createTransientImage(VkFormat format,
VkMemoryAllocateInfo memInfo;
memset(&memInfo, 0, sizeof(memInfo));
memInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- memInfo.allocationSize = aligned(memReq.size, memReq.alignment) * count;
+ memInfo.allocationSize = aligned(memReq.size, memReq.alignment) * VkDeviceSize(count);
uint32_t startIndex = 0;
do {
@@ -1175,7 +1199,7 @@ bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp,
VkSubpassDescription subpassDesc;
memset(&subpassDesc, 0, sizeof(subpassDesc));
subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpassDesc.colorAttachmentCount = colorRefs.count();
+ subpassDesc.colorAttachmentCount = uint32_t(colorRefs.count());
Q_ASSERT(colorRefs.count() == resolveRefs.count());
subpassDesc.pColorAttachments = !colorRefs.isEmpty() ? colorRefs.constData() : nullptr;
subpassDesc.pDepthStencilAttachment = hasDepthStencil ? &dsRef : nullptr;
@@ -1184,7 +1208,7 @@ bool QRhiVulkan::createOffscreenRenderPass(VkRenderPass *rp,
VkRenderPassCreateInfo rpInfo;
memset(&rpInfo, 0, sizeof(rpInfo));
rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- rpInfo.attachmentCount = attDescs.count();
+ rpInfo.attachmentCount = uint32_t(attDescs.count());
rpInfo.pAttachments = attDescs.constData();
rpInfo.subpassCount = 1;
rpInfo.pSubpasses = &subpassDesc;
@@ -1325,7 +1349,7 @@ bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain)
}
if (actualSwapChainBufferCount != reqBufferCount)
qCDebug(QRHI_LOG_INFO, "Actual swapchain buffer count is %u", actualSwapChainBufferCount);
- swapChainD->bufferCount = actualSwapChainBufferCount;
+ swapChainD->bufferCount = int(actualSwapChainBufferCount);
VkImage swapChainImages[QVkSwapChain::MAX_BUFFER_COUNT];
err = vkGetSwapchainImagesKHR(dev, swapChainD->sc, &actualSwapChainBufferCount, swapChainImages);
@@ -1424,7 +1448,8 @@ void QRhiVulkan::releaseSwapChainResources(QRhiSwapChain *swapChain)
if (swapChainD->sc == VK_NULL_HANDLE)
return;
- df->vkDeviceWaitIdle(dev);
+ if (!deviceLost)
+ df->vkDeviceWaitIdle(dev);
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
QVkSwapChain::FrameResources &frame(swapChainD->frameRes[i]);
@@ -1487,15 +1512,6 @@ void QRhiVulkan::releaseSwapChainResources(QRhiSwapChain *swapChain)
// NB! surface and similar must remain intact
}
-static inline bool checkDeviceLost(VkResult err)
-{
- if (err == VK_ERROR_DEVICE_LOST) {
- qWarning("Device lost");
- return true;
- }
- return false;
-}
-
QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
{
QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
@@ -1522,10 +1538,12 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin
} else if (err == VK_ERROR_OUT_OF_DATE_KHR) {
return QRhi::FrameOpSwapChainOutOfDate;
} else {
- if (checkDeviceLost(err))
+ if (err == VK_ERROR_DEVICE_LOST) {
+ qWarning("Device loss detected in vkAcquireNextImageKHR()");
+ deviceLost = true;
return QRhi::FrameOpDeviceLost;
- else
- qWarning("Failed to acquire next swapchain image: %d", err);
+ }
+ qWarning("Failed to acquire next swapchain image: %d", err);
return QRhi::FrameOpError;
}
}
@@ -1540,12 +1558,12 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin
// will make B wait for A's frame 0 commands, so if a resource is written
// in B's frame or when B checks for pending resource releases, that won't
// mess up A's in-flight commands (as they are not in flight anymore).
- waitCommandCompletion(swapChainD->currentFrameSlot);
+ waitCommandCompletion(int(swapChainD->currentFrameSlot));
// Now is the time to read the timestamps for the previous frame for this slot.
if (frame.timestampQueryIndex >= 0) {
quint64 timestamp[2] = { 0, 0 };
- VkResult err = df->vkGetQueryPoolResults(dev, timestampQueryPool, frame.timestampQueryIndex, 2,
+ VkResult err = df->vkGetQueryPoolResults(dev, timestampQueryPool, uint32_t(frame.timestampQueryIndex), 2,
2 * sizeof(quint64), timestamp, sizeof(quint64),
VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
timestampQueryPoolMap.clearBit(frame.timestampQueryIndex / 2);
@@ -1585,10 +1603,10 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin
}
}
if (timestampQueryIdx >= 0) {
- df->vkCmdResetQueryPool(frame.cmdBuf, timestampQueryPool, timestampQueryIdx, 2);
+ df->vkCmdResetQueryPool(frame.cmdBuf, timestampQueryPool, uint32_t(timestampQueryIdx), 2);
// record timestamp at the start of the command buffer
df->vkCmdWriteTimestamp(frame.cmdBuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
- timestampQueryPool, timestampQueryIdx);
+ timestampQueryPool, uint32_t(timestampQueryIdx));
frame.timestampQueryIndex = timestampQueryIdx;
}
@@ -1598,7 +1616,7 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin
QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]);
swapChainD->rtWrapper.d.fb = image.fb;
- currentFrameSlot = swapChainD->currentFrameSlot;
+ currentFrameSlot = int(swapChainD->currentFrameSlot);
currentSwapChain = swapChainD;
if (swapChainD->ds)
swapChainD->ds->lastActiveFrameSlot = currentFrameSlot;
@@ -1653,7 +1671,7 @@ QRhi::FrameOpResult QRhiVulkan::endFrame(QRhiSwapChain *swapChain, QRhi::EndFram
// record another timestamp, when enabled
if (frame.timestampQueryIndex >= 0) {
df->vkCmdWriteTimestamp(frame.cmdBuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
- timestampQueryPool, frame.timestampQueryIndex + 1);
+ timestampQueryPool, uint32_t(frame.timestampQueryIndex + 1));
}
// stop recording and submit to the queue
@@ -1689,10 +1707,12 @@ QRhi::FrameOpResult QRhiVulkan::endFrame(QRhiSwapChain *swapChain, QRhi::EndFram
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
return QRhi::FrameOpSwapChainOutOfDate;
} else if (err != VK_SUBOPTIMAL_KHR) {
- if (checkDeviceLost(err))
+ if (err == VK_ERROR_DEVICE_LOST) {
+ qWarning("Device loss detected in vkQueuePresentKHR()");
+ deviceLost = true;
return QRhi::FrameOpDeviceLost;
- else
- qWarning("Failed to present: %d", err);
+ }
+ qWarning("Failed to present: %d", err);
return QRhi::FrameOpError;
}
}
@@ -1749,10 +1769,12 @@ QRhi::FrameOpResult QRhiVulkan::startPrimaryCommandBuffer(VkCommandBuffer *cb)
VkResult err = df->vkAllocateCommandBuffers(dev, &cmdBufInfo, cb);
if (err != VK_SUCCESS) {
- if (checkDeviceLost(err))
+ if (err == VK_ERROR_DEVICE_LOST) {
+ qWarning("Device loss detected in vkAllocateCommandBuffers()");
+ deviceLost = true;
return QRhi::FrameOpDeviceLost;
- else
- qWarning("Failed to allocate frame command buffer: %d", err);
+ }
+ qWarning("Failed to allocate frame command buffer: %d", err);
return QRhi::FrameOpError;
}
@@ -1762,10 +1784,12 @@ QRhi::FrameOpResult QRhiVulkan::startPrimaryCommandBuffer(VkCommandBuffer *cb)
err = df->vkBeginCommandBuffer(*cb, &cmdBufBeginInfo);
if (err != VK_SUCCESS) {
- if (checkDeviceLost(err))
+ if (err == VK_ERROR_DEVICE_LOST) {
+ qWarning("Device loss detected in vkBeginCommandBuffer()");
+ deviceLost = true;
return QRhi::FrameOpDeviceLost;
- else
- qWarning("Failed to begin frame command buffer: %d", err);
+ }
+ qWarning("Failed to begin frame command buffer: %d", err);
return QRhi::FrameOpError;
}
@@ -1777,10 +1801,12 @@ QRhi::FrameOpResult QRhiVulkan::endAndSubmitPrimaryCommandBuffer(VkCommandBuffer
{
VkResult err = df->vkEndCommandBuffer(cb);
if (err != VK_SUCCESS) {
- if (checkDeviceLost(err))
+ if (err == VK_ERROR_DEVICE_LOST) {
+ qWarning("Device loss detected in vkEndCommandBuffer()");
+ deviceLost = true;
return QRhi::FrameOpDeviceLost;
- else
- qWarning("Failed to end frame command buffer: %d", err);
+ }
+ qWarning("Failed to end frame command buffer: %d", err);
return QRhi::FrameOpError;
}
@@ -1802,10 +1828,12 @@ QRhi::FrameOpResult QRhiVulkan::endAndSubmitPrimaryCommandBuffer(VkCommandBuffer
err = df->vkQueueSubmit(gfxQueue, 1, &submitInfo, cmdFence);
if (err != VK_SUCCESS) {
- if (checkDeviceLost(err))
+ if (err == VK_ERROR_DEVICE_LOST) {
+ qWarning("Device loss detected in vkQueueSubmit()");
+ deviceLost = true;
return QRhi::FrameOpDeviceLost;
- else
- qWarning("Failed to submit to graphics queue: %d", err);
+ }
+ qWarning("Failed to submit to graphics queue: %d", err);
return QRhi::FrameOpError;
}
@@ -1932,8 +1960,8 @@ static inline QRhiPassResourceTracker::UsageState toPassTrackerUsageState(const
{
QRhiPassResourceTracker::UsageState u;
u.layout = 0; // unused with buffers
- u.access = bufUsage.access;
- u.stage = bufUsage.stage;
+ u.access = int(bufUsage.access);
+ u.stage = int(bufUsage.stage);
return u;
}
@@ -1941,8 +1969,8 @@ static inline QRhiPassResourceTracker::UsageState toPassTrackerUsageState(const
{
QRhiPassResourceTracker::UsageState u;
u.layout = texUsage.layout;
- u.access = texUsage.access;
- u.stage = texUsage.stage;
+ u.access = int(texUsage.access);
+ u.stage = int(texUsage.stage);
return u;
}
@@ -2106,8 +2134,8 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb,
rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
rpBeginInfo.renderPass = rtD->rp->rp;
rpBeginInfo.framebuffer = rtD->fb;
- rpBeginInfo.renderArea.extent.width = rtD->pixelSize.width();
- rpBeginInfo.renderArea.extent.height = rtD->pixelSize.height();
+ rpBeginInfo.renderArea.extent.width = uint32_t(rtD->pixelSize.width());
+ rpBeginInfo.renderArea.extent.height = uint32_t(rtD->pixelSize.height());
QVarLengthArray<VkClearValue, 4> cvs;
for (int i = 0; i < rtD->colorAttCount; ++i) {
@@ -2127,7 +2155,7 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb,
float(colorClearValue.alphaF()) } };
cvs.append(cv);
}
- rpBeginInfo.clearValueCount = cvs.count();
+ rpBeginInfo.clearValueCount = uint32_t(cvs.count());
QVkCommandBuffer::Command cmd;
cmd.cmd = QVkCommandBuffer::Command::BeginRenderPass;
@@ -2229,7 +2257,7 @@ void QRhiVulkan::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::ComputePass);
if (cbD->useSecondaryCb) {
- df->vkCmdDispatch(cbD->secondaryCbs.last(), x, y, z);
+ df->vkCmdDispatch(cbD->secondaryCbs.last(), uint32_t(x), uint32_t(y), uint32_t(z));
} else {
QVkCommandBuffer::Command cmd;
cmd.cmd = QVkCommandBuffer::Command::Dispatch;
@@ -2245,7 +2273,7 @@ VkShaderModule QRhiVulkan::createShader(const QByteArray &spirv)
VkShaderModuleCreateInfo shaderInfo;
memset(&shaderInfo, 0, sizeof(shaderInfo));
shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
- shaderInfo.codeSize = spirv.size();
+ shaderInfo.codeSize = size_t(spirv.size());
shaderInfo.pCode = reinterpret_cast<const quint32 *>(spirv.constData());
VkShaderModule shaderModule;
VkResult err = df->vkCreateShaderModule(dev, &shaderInfo, nullptr, &shaderModule);
@@ -2292,7 +2320,7 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
memset(&writeInfo, 0, sizeof(writeInfo));
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.dstSet = srbD->descSets[frameSlot];
- writeInfo.dstBinding = b->binding;
+ writeInfo.dstBinding = uint32_t(b->binding);
writeInfo.descriptorCount = 1;
switch (b->type) {
@@ -2306,8 +2334,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
bd.ubuf.generation = bufD->generation;
VkDescriptorBufferInfo bufInfo;
bufInfo.buffer = bufD->m_type == QRhiBuffer::Dynamic ? bufD->buffers[frameSlot] : bufD->buffers[0];
- bufInfo.offset = b->u.ubuf.offset;
- bufInfo.range = b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size;
+ bufInfo.offset = VkDeviceSize(b->u.ubuf.offset);
+ bufInfo.range = VkDeviceSize(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size);
// be nice and assert when we know the vulkan device would die a horrible death due to non-aligned reads
Q_ASSERT(aligned(bufInfo.offset, ubufAlign) == bufInfo.offset);
bufferInfos.append(bufInfo);
@@ -2364,8 +2392,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
bd.sbuf.generation = bufD->generation;
VkDescriptorBufferInfo bufInfo;
bufInfo.buffer = bufD->m_type == QRhiBuffer::Dynamic ? bufD->buffers[frameSlot] : bufD->buffers[0];
- bufInfo.offset = b->u.ubuf.offset;
- bufInfo.range = b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size;
+ bufInfo.offset = VkDeviceSize(b->u.ubuf.offset);
+ bufInfo.range = VkDeviceSize(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size);
bufferInfos.append(bufInfo);
writeInfo.pBufferInfo = &bufferInfos.last();
}
@@ -2379,7 +2407,7 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
++frameSlot;
}
- df->vkUpdateDescriptorSets(dev, writeInfos.count(), writeInfos.constData(), 0, nullptr);
+ df->vkUpdateDescriptorSets(dev, uint32_t(writeInfos.count()), writeInfos.constData(), 0, nullptr);
}
static inline bool accessIsWrite(VkAccessFlags access)
@@ -2487,10 +2515,10 @@ void QRhiVulkan::subresourceBarrier(QVkCommandBuffer *cbD, VkImage image,
memset(&barrier, 0, sizeof(barrier));
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- barrier.subresourceRange.baseMipLevel = startLevel;
- barrier.subresourceRange.levelCount = levelCount;
- barrier.subresourceRange.baseArrayLayer = startLayer;
- barrier.subresourceRange.layerCount = layerCount;
+ barrier.subresourceRange.baseMipLevel = uint32_t(startLevel);
+ barrier.subresourceRange.levelCount = uint32_t(levelCount);
+ barrier.subresourceRange.baseArrayLayer = uint32_t(startLayer);
+ barrier.subresourceRange.layerCount = uint32_t(layerCount);
barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout;
barrier.srcAccessMask = srcAccess;
@@ -2511,7 +2539,7 @@ VkDeviceSize QRhiVulkan::subresUploadByteSize(const QRhiTextureSubresourceUpload
const qsizetype imageSizeBytes = subresDesc.image().isNull() ?
subresDesc.data().size() : subresDesc.image().sizeInBytes();
if (imageSizeBytes > 0)
- size += aligned(imageSizeBytes, texbufAlign);
+ size += aligned(VkDeviceSize(imageSizeBytes), texbufAlign);
return size;
}
@@ -2528,8 +2556,8 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
memset(&copyInfo, 0, sizeof(copyInfo));
copyInfo.bufferOffset = *curOfs;
copyInfo.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copyInfo.imageSubresource.mipLevel = level;
- copyInfo.imageSubresource.baseArrayLayer = layer;
+ copyInfo.imageSubresource.mipLevel = uint32_t(level);
+ copyInfo.imageSubresource.baseArrayLayer = uint32_t(layer);
copyInfo.imageSubresource.layerCount = 1;
copyInfo.imageExtent.depth = 1;
@@ -2544,7 +2572,7 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
// be taken into account for bufferRowLength.
int bpc = qMax(1, image.depth() / 8);
// this is in pixels, not bytes, to make it more complicated...
- copyInfo.bufferRowLength = image.bytesPerLine() / bpc;
+ copyInfo.bufferRowLength = uint32_t(image.bytesPerLine() / bpc);
if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
const int sx = subresDesc.sourceTopLeft().x();
const int sy = subresDesc.sourceTopLeft().y();
@@ -2554,7 +2582,7 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
// The staging buffer will get the full image
// regardless, just adjust the vk
// buffer-to-image copy start offset.
- copyInfo.bufferOffset += sy * image.bytesPerLine() + sx * 4;
+ copyInfo.bufferOffset += VkDeviceSize(sy * image.bytesPerLine() + sx * 4);
// bufferRowLength remains set to the original image's width
} else {
image = image.copy(sx, sy, size.width(), size.height());
@@ -2563,13 +2591,13 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
// space reserved for this mip will be unused.
copySizeBytes = image.sizeInBytes();
bpc = qMax(1, image.depth() / 8);
- copyInfo.bufferRowLength = image.bytesPerLine() / bpc;
+ copyInfo.bufferRowLength = uint32_t(image.bytesPerLine() / bpc);
}
}
copyInfo.imageOffset.x = dp.x();
copyInfo.imageOffset.y = dp.y();
- copyInfo.imageExtent.width = size.width();
- copyInfo.imageExtent.height = size.height();
+ copyInfo.imageExtent.width = uint32_t(size.width());
+ copyInfo.imageExtent.height = uint32_t(size.height());
copyInfos->append(copyInfo);
} else if (!rawData.isEmpty() && isCompressedFormat(texD->m_format)) {
copySizeBytes = imageSizeBytes = rawData.size();
@@ -2588,8 +2616,8 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
copyInfo.imageOffset.y = aligned(dp.y(), blockDim.height());
// width and height must be multiples of the block width and height
// or x + width and y + height must equal the subresource width and height
- copyInfo.imageExtent.width = dp.x() + w == subresw ? w : aligned(w, blockDim.width());
- copyInfo.imageExtent.height = dp.y() + h == subresh ? h : aligned(h, blockDim.height());
+ copyInfo.imageExtent.width = uint32_t(dp.x() + w == subresw ? w : aligned(w, blockDim.width()));
+ copyInfo.imageExtent.height = uint32_t(dp.y() + h == subresh ? h : aligned(h, blockDim.height()));
copyInfos->append(copyInfo);
} else if (!rawData.isEmpty()) {
copySizeBytes = imageSizeBytes = rawData.size();
@@ -2599,15 +2627,15 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
size = subresDesc.sourceSize();
copyInfo.imageOffset.x = dp.x();
copyInfo.imageOffset.y = dp.y();
- copyInfo.imageExtent.width = size.width();
- copyInfo.imageExtent.height = size.height();
+ copyInfo.imageExtent.width = uint32_t(size.width());
+ copyInfo.imageExtent.height = uint32_t(size.height());
copyInfos->append(copyInfo);
} else {
qWarning("Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
}
- memcpy(reinterpret_cast<char *>(mp) + *curOfs, src, copySizeBytes);
- *curOfs += aligned(imageSizeBytes, texbufAlign);
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs, src, size_t(copySizeBytes));
+ *curOfs += aligned(VkDeviceSize(imageSizeBytes), texbufAlign);
}
void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates)
@@ -2633,7 +2661,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
// must cover the entire buffer - this way multiple, partial updates per frame
// are supported even when the staging buffer is reused (Static)
- bufferInfo.size = bufD->m_size;
+ bufferInfo.size = VkDeviceSize(bufD->m_size);
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
VmaAllocationCreateInfo allocInfo;
@@ -2645,7 +2673,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
&bufD->stagingBuffers[currentFrameSlot], &allocation, nullptr);
if (err == VK_SUCCESS) {
bufD->stagingAllocations[currentFrameSlot] = allocation;
- QRHI_PROF_F(newBufferStagingArea(bufD, currentFrameSlot, bufD->m_size));
+ QRHI_PROF_F(newBufferStagingArea(bufD, currentFrameSlot, quint32(bufD->m_size)));
} else {
qWarning("Failed to create staging buffer of size %d: %d", bufD->m_size, err);
continue;
@@ -2659,18 +2687,18 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
qWarning("Failed to map buffer: %d", err);
continue;
}
- memcpy(static_cast<uchar *>(p) + u.offset, u.data.constData(), u.data.size());
+ memcpy(static_cast<uchar *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
vmaUnmapMemory(toVmaAllocator(allocator), a);
- vmaFlushAllocation(toVmaAllocator(allocator), a, u.offset, u.data.size());
+ vmaFlushAllocation(toVmaAllocator(allocator), a, VkDeviceSize(u.offset), VkDeviceSize(u.data.size()));
trackedBufferBarrier(cbD, bufD, 0,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
VkBufferCopy copyInfo;
memset(&copyInfo, 0, sizeof(copyInfo));
- copyInfo.srcOffset = u.offset;
- copyInfo.dstOffset = u.offset;
- copyInfo.size = u.data.size();
+ copyInfo.srcOffset = VkDeviceSize(u.offset);
+ copyInfo.dstOffset = VkDeviceSize(u.offset);
+ copyInfo.size = VkDeviceSize(u.data.size());
QVkCommandBuffer::Command cmd;
cmd.cmd = QVkCommandBuffer::Command::CopyBuffer;
@@ -2732,7 +2760,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
continue;
}
utexD->stagingAllocations[currentFrameSlot] = allocation;
- QRHI_PROF_F(newTextureStagingArea(utexD, currentFrameSlot, stagingSize));
+ QRHI_PROF_F(newTextureStagingArea(utexD, currentFrameSlot, quint32(stagingSize)));
BufferImageCopyList copyInfos;
size_t curOfs = 0;
@@ -2799,24 +2827,24 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
memset(&region, 0, sizeof(region));
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- region.srcSubresource.mipLevel = u.copy.desc.sourceLevel();
- region.srcSubresource.baseArrayLayer = u.copy.desc.sourceLayer();
+ region.srcSubresource.mipLevel = uint32_t(u.copy.desc.sourceLevel());
+ region.srcSubresource.baseArrayLayer = uint32_t(u.copy.desc.sourceLayer());
region.srcSubresource.layerCount = 1;
region.srcOffset.x = u.copy.desc.sourceTopLeft().x();
region.srcOffset.y = u.copy.desc.sourceTopLeft().y();
region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- region.dstSubresource.mipLevel = u.copy.desc.destinationLevel();
- region.dstSubresource.baseArrayLayer = u.copy.desc.destinationLayer();
+ region.dstSubresource.mipLevel = uint32_t(u.copy.desc.destinationLevel());
+ region.dstSubresource.baseArrayLayer = uint32_t(u.copy.desc.destinationLayer());
region.dstSubresource.layerCount = 1;
region.dstOffset.x = u.copy.desc.destinationTopLeft().x();
region.dstOffset.y = u.copy.desc.destinationTopLeft().y();
const QSize size = u.copy.desc.pixelSize().isEmpty() ? srcD->m_pixelSize : u.copy.desc.pixelSize();
- region.extent.width = size.width();
- region.extent.height = size.height();
+ region.extent.width = uint32_t(size.width());
+ region.extent.height = uint32_t(size.height());
region.extent.depth = 1;
trackedImageBarrier(cbD, srcD, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
@@ -2883,7 +2911,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
VkResult err = vmaCreateBuffer(toVmaAllocator(allocator), &bufferInfo, &allocInfo, &aRb.buf, &allocation, nullptr);
if (err == VK_SUCCESS) {
aRb.bufAlloc = allocation;
- QRHI_PROF_F(newReadbackBuffer(quint64(aRb.buf),
+ QRHI_PROF_F(newReadbackBuffer(qint64(aRb.buf),
texD ? static_cast<QRhiResource *>(texD) : static_cast<QRhiResource *>(swapChainD),
aRb.bufSize));
} else {
@@ -2896,11 +2924,11 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
memset(&copyDesc, 0, sizeof(copyDesc));
copyDesc.bufferOffset = 0;
copyDesc.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copyDesc.imageSubresource.mipLevel = u.read.rb.level();
- copyDesc.imageSubresource.baseArrayLayer = u.read.rb.layer();
+ copyDesc.imageSubresource.mipLevel = uint32_t(u.read.rb.level());
+ copyDesc.imageSubresource.baseArrayLayer = uint32_t(u.read.rb.layer());
copyDesc.imageSubresource.layerCount = 1;
- copyDesc.imageExtent.width = aRb.pixelSize.width();
- copyDesc.imageExtent.height = aRb.pixelSize.height();
+ copyDesc.imageExtent.width = uint32_t(aRb.pixelSize.width());
+ copyDesc.imageExtent.height = uint32_t(aRb.pixelSize.height());
copyDesc.imageExtent.depth = 1;
if (texD) {
@@ -2953,7 +2981,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
if (!origStage)
origStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- for (uint level = 1; level < utexD->mipLevelCount; ++level) {
+ for (int level = 1; level < int(utexD->mipLevelCount); ++level) {
if (level == 1) {
subresourceBarrier(cbD, utexD->image,
origLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
@@ -2981,8 +3009,8 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
memset(&region, 0, sizeof(region));
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- region.srcSubresource.mipLevel = level - 1;
- region.srcSubresource.baseArrayLayer = u.mipgen.layer;
+ region.srcSubresource.mipLevel = uint32_t(level) - 1;
+ region.srcSubresource.baseArrayLayer = uint32_t(u.mipgen.layer);
region.srcSubresource.layerCount = 1;
region.srcOffsets[1].x = qMax(1, w);
@@ -2990,8 +3018,8 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
region.srcOffsets[1].z = 1;
region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- region.dstSubresource.mipLevel = level;
- region.dstSubresource.baseArrayLayer = u.mipgen.layer;
+ region.dstSubresource.mipLevel = uint32_t(level);
+ region.dstSubresource.baseArrayLayer = uint32_t(u.mipgen.layer);
region.dstSubresource.layerCount = 1;
region.dstOffsets[1].x = qMax(1, w >> 1);
@@ -3018,13 +3046,13 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
VK_ACCESS_TRANSFER_READ_BIT, origAccess,
VK_PIPELINE_STAGE_TRANSFER_BIT, origStage,
u.mipgen.layer, 1,
- 0, utexD->mipLevelCount - 1);
+ 0, int(utexD->mipLevelCount) - 1);
subresourceBarrier(cbD, utexD->image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, origLayout,
VK_ACCESS_TRANSFER_WRITE_BIT, origAccess,
VK_PIPELINE_STAGE_TRANSFER_BIT, origStage,
u.mipgen.layer, 1,
- utexD->mipLevelCount - 1, 1);
+ int(utexD->mipLevelCount) - 1, 1);
}
utexD->lastActiveFrameSlot = currentFrameSlot;
@@ -3055,7 +3083,7 @@ void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
int changeEnd = -1;
for (const QRhiResourceUpdateBatchPrivate::DynamicBufferUpdate &u : updates) {
Q_ASSERT(bufD == QRHI_RES(QVkBuffer, u.buf));
- memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), u.data.size());
+ memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
if (changeBegin == -1 || u.offset < changeBegin)
changeBegin = u.offset;
if (changeEnd == -1 || u.offset + u.data.size() > changeEnd)
@@ -3063,7 +3091,7 @@ void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
}
vmaUnmapMemory(toVmaAllocator(allocator), a);
if (changeBegin >= 0)
- vmaFlushAllocation(toVmaAllocator(allocator), a, changeBegin, changeEnd - changeBegin);
+ vmaFlushAllocation(toVmaAllocator(allocator), a, VkDeviceSize(changeBegin), VkDeviceSize(changeEnd - changeBegin));
updates.clear();
}
@@ -3164,7 +3192,7 @@ void QRhiVulkan::finishActiveReadbacks(bool forced)
if (forced || currentFrameSlot == aRb.activeFrameSlot || aRb.activeFrameSlot < 0) {
aRb.result->format = aRb.format;
aRb.result->pixelSize = aRb.pixelSize;
- aRb.result->data.resize(aRb.bufSize);
+ aRb.result->data.resize(int(aRb.bufSize));
void *p = nullptr;
VmaAllocation a = toVmaAllocation(aRb.bufAlloc);
VkResult err = vmaMapMemory(toVmaAllocator(allocator), a, &p);
@@ -3176,7 +3204,7 @@ void QRhiVulkan::finishActiveReadbacks(bool forced)
vmaUnmapMemory(toVmaAllocator(allocator), a);
vmaDestroyBuffer(toVmaAllocator(allocator), aRb.buf, a);
- QRHI_PROF_F(releaseReadbackBuffer(quint64(aRb.buf)));
+ QRHI_PROF_F(releaseReadbackBuffer(qint64(aRb.buf)));
if (aRb.result->completed)
completedCallbacks.append(aRb.result->completed);
@@ -3266,7 +3294,7 @@ void QRhiVulkan::recordPrimaryCommandBuffer(QVkCommandBuffer *cbD)
case QVkCommandBuffer::Command::CopyBufferToImage:
df->vkCmdCopyBufferToImage(cbD->cb, cmd.args.copyBufferToImage.src, cmd.args.copyBufferToImage.dst,
cmd.args.copyBufferToImage.dstLayout,
- cmd.args.copyBufferToImage.count,
+ uint32_t(cmd.args.copyBufferToImage.count),
cbD->pools.bufferImageCopy.constData() + cmd.args.copyBufferToImage.bufferImageCopyIndex);
break;
case QVkCommandBuffer::Command::CopyImage:
@@ -3315,13 +3343,13 @@ void QRhiVulkan::recordPrimaryCommandBuffer(QVkCommandBuffer *cbD)
df->vkCmdBindDescriptorSets(cbD->cb, cmd.args.bindDescriptorSet.bindPoint,
cmd.args.bindDescriptorSet.pipelineLayout,
0, 1, &cmd.args.bindDescriptorSet.descSet,
- cmd.args.bindDescriptorSet.dynamicOffsetCount,
+ uint32_t(cmd.args.bindDescriptorSet.dynamicOffsetCount),
offsets);
}
break;
case QVkCommandBuffer::Command::BindVertexBuffer:
- df->vkCmdBindVertexBuffers(cbD->cb, cmd.args.bindVertexBuffer.startBinding,
- cmd.args.bindVertexBuffer.count,
+ df->vkCmdBindVertexBuffers(cbD->cb, uint32_t(cmd.args.bindVertexBuffer.startBinding),
+ uint32_t(cmd.args.bindVertexBuffer.count),
cbD->pools.vertexBuffer.constData() + cmd.args.bindVertexBuffer.vertexBufferIndex,
cbD->pools.vertexBufferOffset.constData() + cmd.args.bindVertexBuffer.vertexBufferOffsetIndex);
break;
@@ -3367,7 +3395,7 @@ void QRhiVulkan::recordPrimaryCommandBuffer(QVkCommandBuffer *cbD)
recordTransitionPassResources(cbD, cbD->passResTrackers[cmd.args.transitionResources.trackerIndex]);
break;
case QVkCommandBuffer::Command::Dispatch:
- df->vkCmdDispatch(cbD->cb, cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
+ df->vkCmdDispatch(cbD->cb, uint32_t(cmd.args.dispatch.x), uint32_t(cmd.args.dispatch.y), uint32_t(cmd.args.dispatch.z));
break;
case QVkCommandBuffer::Command::ExecuteSecondary:
df->vkCmdExecuteCommands(cbD->cb, 1, &cmd.args.executeSecondary.cb);
@@ -3421,8 +3449,8 @@ static inline VkPipelineStageFlags toVkPipelineStage(QRhiPassResourceTracker::Bu
static inline QVkBuffer::UsageState toVkBufferUsageState(QRhiPassResourceTracker::UsageState usage)
{
QVkBuffer::UsageState u;
- u.access = usage.access;
- u.stage = usage.stage;
+ u.access = VkAccessFlags(usage.access);
+ u.stage = VkPipelineStageFlags(usage.stage);
return u;
}
@@ -3494,8 +3522,8 @@ static inline QVkTexture::UsageState toVkTextureUsageState(QRhiPassResourceTrack
{
QVkTexture::UsageState u;
u.layout = VkImageLayout(usage.layout);
- u.access = usage.access;
- u.stage = usage.stage;
+ u.access = VkAccessFlags(usage.access);
+ u.stage = VkPipelineStageFlags(usage.stage);
return u;
}
@@ -3603,7 +3631,7 @@ QRhiBuffer *QRhiVulkan::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFla
int QRhiVulkan::ubufAlignment() const
{
- return ubufAlign; // typically 256 (bytes)
+ return int(ubufAlign); // typically 256 (bytes)
}
bool QRhiVulkan::isYUpInFramebuffer() const
@@ -3711,9 +3739,9 @@ int QRhiVulkan::resourceLimit(QRhi::ResourceLimit limit) const
case QRhi::TextureSizeMin:
return 1;
case QRhi::TextureSizeMax:
- return physDevProperties.limits.maxImageDimension2D;
+ return int(physDevProperties.limits.maxImageDimension2D);
case QRhi::MaxColorAttachments:
- return physDevProperties.limits.maxColorAttachments;
+ return int(physDevProperties.limits.maxColorAttachments);
case QRhi::FramesInFlight:
return QVK_FRAMES_IN_FLIGHT;
default:
@@ -3736,14 +3764,25 @@ void QRhiVulkan::sendVMemStatsToProfiler()
VmaStats stats;
vmaCalculateStats(toVmaAllocator(allocator), &stats);
QRHI_PROF_F(vmemStat(stats.total.blockCount, stats.total.allocationCount,
- stats.total.usedBytes, stats.total.unusedBytes));
+ quint32(stats.total.usedBytes), quint32(stats.total.unusedBytes)));
+}
+
+bool QRhiVulkan::makeThreadLocalNativeContextCurrent()
+{
+ // not applicable
+ return false;
}
-void QRhiVulkan::makeThreadLocalNativeContextCurrent()
+void QRhiVulkan::releaseCachedResources()
{
// nothing to do here
}
+bool QRhiVulkan::isDeviceLost() const
+{
+ return deviceLost;
+}
+
QRhiRenderBuffer *QRhiVulkan::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
int sampleCount, QRhiRenderBuffer::Flags flags)
{
@@ -4003,7 +4042,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
gfxPsD ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE,
gfxPsD ? gfxPsD->layout : compPsD->layout,
0, 1, &srbD->descSets[descSetIdx],
- dynOfs.count(),
+ uint32_t(dynOfs.count()),
dynOfs.count() ? dynOfs.constData() : nullptr);
} else {
QVkCommandBuffer::Command cmd;
@@ -4073,8 +4112,8 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
}
if (cbD->useSecondaryCb) {
- df->vkCmdBindVertexBuffers(cbD->secondaryCbs.last(), startBinding,
- bufs.count(), bufs.constData(), ofs.constData());
+ df->vkCmdBindVertexBuffers(cbD->secondaryCbs.last(), uint32_t(startBinding),
+ uint32_t(bufs.count()), bufs.constData(), ofs.constData());
} else {
QVkCommandBuffer::Command cmd;
cmd.cmd = QVkCommandBuffer::Command::BindVertexBuffer;
@@ -4155,10 +4194,10 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport
if (!QRHI_RES(QVkGraphicsPipeline, cbD->currentGraphicsPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) {
VkRect2D *s = &cmd.args.setScissor.scissor;
- s->offset.x = x;
- s->offset.y = y;
- s->extent.width = w;
- s->extent.height = h;
+ s->offset.x = int32_t(x);
+ s->offset.y = int32_t(y);
+ s->extent.width = uint32_t(w);
+ s->extent.height = uint32_t(h);
if (cbD->useSecondaryCb) {
df->vkCmdSetScissor(cbD->secondaryCbs.last(), 0, 1, s);
} else {
@@ -4184,8 +4223,8 @@ void QRhiVulkan::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
VkRect2D *s = &cmd.args.setScissor.scissor;
s->offset.x = x;
s->offset.y = y;
- s->extent.width = w;
- s->extent.height = h;
+ s->extent.width = uint32_t(w);
+ s->extent.height = uint32_t(h);
if (cbD->useSecondaryCb) {
df->vkCmdSetScissor(cbD->secondaryCbs.last(), 0, 1, s);
@@ -4206,10 +4245,10 @@ void QRhiVulkan::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
} else {
QVkCommandBuffer::Command cmd;
cmd.cmd = QVkCommandBuffer::Command::SetBlendConstants;
- cmd.args.setBlendConstants.c[0] = c.redF();
- cmd.args.setBlendConstants.c[1] = c.greenF();
- cmd.args.setBlendConstants.c[2] = c.blueF();
- cmd.args.setBlendConstants.c[3] = c.alphaF();
+ cmd.args.setBlendConstants.c[0] = float(c.redF());
+ cmd.args.setBlendConstants.c[1] = float(c.greenF());
+ cmd.args.setBlendConstants.c[2] = float(c.blueF());
+ cmd.args.setBlendConstants.c[3] = float(c.alphaF());
cbD->commands.append(cmd);
}
}
@@ -4838,7 +4877,7 @@ bool QVkBuffer::build()
VkBufferCreateInfo bufferInfo;
memset(&bufferInfo, 0, sizeof(bufferInfo));
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- bufferInfo.size = nonZeroSize;
+ bufferInfo.size = uint32_t(nonZeroSize);
bufferInfo.usage = toVkBufferUsage(m_usage);
VmaAllocationCreateInfo allocInfo;
@@ -4885,7 +4924,7 @@ bool QVkBuffer::build()
}
QRHI_PROF;
- QRHI_PROF_F(newBuffer(this, nonZeroSize, m_type != Dynamic ? 1 : QVK_FRAMES_IN_FLIGHT, 0));
+ QRHI_PROF_F(newBuffer(this, uint(nonZeroSize), m_type != Dynamic ? 1 : QVK_FRAMES_IN_FLIGHT, 0));
lastActiveFrameSlot = -1;
generation += 1;
@@ -5076,7 +5115,7 @@ bool QVkTexture::prepareBuild(QSize *adjustedSize)
const bool isCube = m_flags.testFlag(CubeMap);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
- mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
+ mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
const int maxLevels = QRhi::MAX_LEVELS;
if (mipLevelCount > maxLevels) {
qWarning("Too many mip levels (%d, max is %d), truncating mip chain", mipLevelCount, maxLevels);
@@ -5155,8 +5194,8 @@ bool QVkTexture::build()
imageInfo.flags = isCube ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.format = vkformat;
- imageInfo.extent.width = size.width();
- imageInfo.extent.height = size.height();
+ imageInfo.extent.width = uint32_t(size.width());
+ imageInfo.extent.height = uint32_t(size.height());
imageInfo.extent.depth = 1;
imageInfo.mipLevels = mipLevelCount;
imageInfo.arrayLayers = isCube ? 6 : 1;
@@ -5197,7 +5236,7 @@ bool QVkTexture::build()
rhiD->setObjectName(uint64_t(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, m_objectName);
QRHI_PROF;
- QRHI_PROF_F(newTexture(this, true, mipLevelCount, isCube ? 6 : 1, samples));
+ QRHI_PROF_F(newTexture(this, true, int(mipLevelCount), isCube ? 6 : 1, samples));
owns = true;
rhiD->registerResource(this);
@@ -5219,7 +5258,7 @@ bool QVkTexture::buildFrom(const QRhiNativeHandles *src)
return false;
QRHI_PROF;
- QRHI_PROF_F(newTexture(this, false, mipLevelCount, m_flags.testFlag(CubeMap) ? 6 : 1, samples));
+ QRHI_PROF_F(newTexture(this, false, int(mipLevelCount), m_flags.testFlag(CubeMap) ? 6 : 1, samples));
usageState.layout = h->layout;
@@ -5255,7 +5294,7 @@ VkImageView QVkTexture::imageViewForLevel(int level)
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
viewInfo.subresourceRange.aspectMask = isDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
- viewInfo.subresourceRange.baseMipLevel = level;
+ viewInfo.subresourceRange.baseMipLevel = uint32_t(level);
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = isCube ? 6 : 1;
@@ -5496,9 +5535,9 @@ bool QVkTextureRenderTarget::build()
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- viewInfo.subresourceRange.baseMipLevel = colorAttachments[i].level();
+ viewInfo.subresourceRange.baseMipLevel = uint32_t(colorAttachments[i].level());
viewInfo.subresourceRange.levelCount = 1;
- viewInfo.subresourceRange.baseArrayLayer = colorAttachments[i].layer();
+ viewInfo.subresourceRange.baseArrayLayer = uint32_t(colorAttachments[i].layer());
viewInfo.subresourceRange.layerCount = 1;
VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &rtv[i]);
if (err != VK_SUCCESS) {
@@ -5560,9 +5599,9 @@ bool QVkTextureRenderTarget::build()
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- viewInfo.subresourceRange.baseMipLevel = colorAttachments[i].resolveLevel();
+ viewInfo.subresourceRange.baseMipLevel = uint32_t(colorAttachments[i].resolveLevel());
viewInfo.subresourceRange.levelCount = 1;
- viewInfo.subresourceRange.baseArrayLayer = colorAttachments[i].resolveLayer();
+ viewInfo.subresourceRange.baseArrayLayer = uint32_t(colorAttachments[i].resolveLayer());
viewInfo.subresourceRange.layerCount = 1;
VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &resrtv[i]);
if (err != VK_SUCCESS) {
@@ -5583,10 +5622,10 @@ bool QVkTextureRenderTarget::build()
memset(&fbInfo, 0, sizeof(fbInfo));
fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fbInfo.renderPass = d.rp->rp;
- fbInfo.attachmentCount = d.colorAttCount + d.dsAttCount + d.resolveAttCount;
+ fbInfo.attachmentCount = uint32_t(d.colorAttCount + d.dsAttCount + d.resolveAttCount);
fbInfo.pAttachments = views.constData();
- fbInfo.width = d.pixelSize.width();
- fbInfo.height = d.pixelSize.height();
+ fbInfo.width = uint32_t(d.pixelSize.width());
+ fbInfo.height = uint32_t(d.pixelSize.height());
fbInfo.layers = 1;
VkResult err = rhiD->df->vkCreateFramebuffer(rhiD->dev, &fbInfo, nullptr, &d.fb);
@@ -5670,7 +5709,7 @@ bool QVkShaderResourceBindings::build()
const QRhiShaderResourceBindingPrivate *b = QRhiShaderResourceBindingPrivate::get(&binding);
VkDescriptorSetLayoutBinding vkbinding;
memset(&vkbinding, 0, sizeof(vkbinding));
- vkbinding.binding = b->binding;
+ vkbinding.binding = uint32_t(b->binding);
vkbinding.descriptorType = toVkDescriptorType(b);
vkbinding.descriptorCount = 1; // no array support yet
vkbinding.stageFlags = toVkShaderStageFlags(b->stage);
@@ -5787,7 +5826,7 @@ bool QVkGraphicsPipeline::build()
shaderStageCreateInfos.append(shaderInfo);
}
}
- pipelineInfo.stageCount = shaderStageCreateInfos.count();
+ pipelineInfo.stageCount = uint32_t(shaderStageCreateInfos.count());
pipelineInfo.pStages = shaderStageCreateInfos.constData();
const QVector<QRhiVertexInputBinding> bindings = m_vertexInputLayout.bindings();
@@ -5828,15 +5867,15 @@ bool QVkGraphicsPipeline::build()
VkPipelineVertexInputStateCreateInfo vertexInputInfo;
memset(&vertexInputInfo, 0, sizeof(vertexInputInfo));
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
- vertexInputInfo.vertexBindingDescriptionCount = vertexBindings.count();
+ vertexInputInfo.vertexBindingDescriptionCount = uint32_t(vertexBindings.count());
vertexInputInfo.pVertexBindingDescriptions = vertexBindings.constData();
- vertexInputInfo.vertexAttributeDescriptionCount = vertexAttributes.count();
+ vertexInputInfo.vertexAttributeDescriptionCount = uint32_t(vertexAttributes.count());
vertexInputInfo.pVertexAttributeDescriptions = vertexAttributes.constData();
VkPipelineVertexInputDivisorStateCreateInfoEXT divisorInfo;
if (!nonOneStepRates.isEmpty()) {
memset(&divisorInfo, 0, sizeof(divisorInfo));
divisorInfo.sType = VkStructureType(1000190001); // VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT
- divisorInfo.vertexBindingDivisorCount = nonOneStepRates.count();
+ divisorInfo.vertexBindingDivisorCount = uint32_t(nonOneStepRates.count());
divisorInfo.pVertexBindingDivisors = nonOneStepRates.constData();
vertexInputInfo.pNext = &divisorInfo;
}
@@ -5853,7 +5892,7 @@ bool QVkGraphicsPipeline::build()
VkPipelineDynamicStateCreateInfo dynamicInfo;
memset(&dynamicInfo, 0, sizeof(dynamicInfo));
dynamicInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
- dynamicInfo.dynamicStateCount = dynEnable.count();
+ dynamicInfo.dynamicStateCount = uint32_t(dynEnable.count());
dynamicInfo.pDynamicStates = dynEnable.constData();
pipelineInfo.pDynamicState = &dynamicInfo;
@@ -5925,7 +5964,7 @@ bool QVkGraphicsPipeline::build()
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
vktargetBlends.append(blend);
}
- blendInfo.attachmentCount = vktargetBlends.count();
+ blendInfo.attachmentCount = uint32_t(vktargetBlends.count());
blendInfo.pAttachments = vktargetBlends.constData();
pipelineInfo.pColorBlendState = &blendInfo;
@@ -6126,11 +6165,11 @@ QSize QVkSwapChain::surfacePixelSize()
QRHI_RES_RHI(QRhiVulkan);
rhiD->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(rhiD->physDev, surface, &surfaceCaps);
VkExtent2D bufferSize = surfaceCaps.currentExtent;
- if (bufferSize.width == quint32(-1)) {
- Q_ASSERT(bufferSize.height == quint32(-1));
+ if (bufferSize.width == uint32_t(-1)) {
+ Q_ASSERT(bufferSize.height == uint32_t(-1));
return m_window->size() * m_window->devicePixelRatio();
}
- return QSize(bufferSize.width, bufferSize.height);
+ return QSize(int(bufferSize.width), int(bufferSize.height));
}
QRhiRenderPassDescriptor *QVkSwapChain::newCompatibleRenderPassDescriptor()
@@ -6198,7 +6237,7 @@ bool QVkSwapChain::ensureSurface()
QRHI_RES_RHI(QRhiVulkan);
if (rhiD->gfxQueueFamilyIdx != -1) {
- if (!rhiD->inst->supportsPresent(rhiD->physDev, rhiD->gfxQueueFamilyIdx, m_window)) {
+ if (!rhiD->inst->supportsPresent(rhiD->physDev, uint32_t(rhiD->gfxQueueFamilyIdx), m_window)) {
qWarning("Presenting not supported on this window");
return false;
}
@@ -6227,7 +6266,7 @@ bool QVkSwapChain::ensureSurface()
rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR(rhiD->physDev, surface, &formatCount, formats.data());
const bool srgbRequested = m_flags.testFlag(sRGB);
- for (quint32 i = 0; i < formatCount; ++i) {
+ for (int i = 0; i < int(formatCount); ++i) {
if (formats[i].format != VK_FORMAT_UNDEFINED && srgbRequested == isSrgbFormat(formats[i].format)) {
colorFormat = formats[i].format;
colorSpace = formats[i].colorSpace;
@@ -6288,7 +6327,7 @@ bool QVkSwapChain::buildOrResize()
Q_ASSERT(rtWrapper.d.rp && rtWrapper.d.rp->rp);
rtWrapper.d.pixelSize = pixelSize;
- rtWrapper.d.dpr = window->devicePixelRatio();
+ rtWrapper.d.dpr = float(window->devicePixelRatio());
rtWrapper.d.sampleCount = samples;
rtWrapper.d.colorAttCount = 1;
if (m_depthStencil) {
@@ -6315,10 +6354,10 @@ bool QVkSwapChain::buildOrResize()
memset(&fbInfo, 0, sizeof(fbInfo));
fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fbInfo.renderPass = rtWrapper.d.rp->rp;
- fbInfo.attachmentCount = rtWrapper.d.colorAttCount + rtWrapper.d.dsAttCount + rtWrapper.d.resolveAttCount;
+ fbInfo.attachmentCount = uint32_t(rtWrapper.d.colorAttCount + rtWrapper.d.dsAttCount + rtWrapper.d.resolveAttCount);
fbInfo.pAttachments = views;
- fbInfo.width = pixelSize.width();
- fbInfo.height = pixelSize.height();
+ fbInfo.width = uint32_t(pixelSize.width());
+ fbInfo.height = uint32_t(pixelSize.height());
fbInfo.layers = 1;
VkResult err = rhiD->df->vkCreateFramebuffer(rhiD->dev, &fbInfo, nullptr, &image.fb);
diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h
index 962a1b8eb7..a390bc3707 100644
--- a/src/gui/rhi/qrhivulkan_p_p.h
+++ b/src/gui/rhi/qrhivulkan_p_p.h
@@ -711,7 +711,9 @@ public:
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
void sendVMemStatsToProfiler() override;
- void makeThreadLocalNativeContextCurrent() override;
+ bool makeThreadLocalNativeContextCurrent() override;
+ void releaseCachedResources() override;
+ bool isDeviceLost() const override;
VkResult createDescriptorPool(VkDescriptorPool *pool);
bool allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, VkDescriptorSet *result, int *resultPoolIndex);
@@ -803,6 +805,7 @@ public:
VkDeviceSize ubufAlign;
VkDeviceSize texbufAlign;
bool hasWideLines = false;
+ bool deviceLost = false;
bool debugMarkersAvailable = false;
bool vertexAttribDivisorAvailable = false;
diff --git a/src/gui/rhi/tdr.hlsl b/src/gui/rhi/tdr.hlsl
new file mode 100644
index 0000000000..f79de91c4a
--- /dev/null
+++ b/src/gui/rhi/tdr.hlsl
@@ -0,0 +1,9 @@
+RWBuffer<uint> uav;
+cbuffer ConstantBuffer { uint zero; }
+
+[numthreads(256, 1, 1)]
+void killDeviceByTimingOut(uint3 id: SV_DispatchThreadID)
+{
+ while (zero == 0)
+ uav[id.x] = zero;
+}
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index c80617f929..3652a180a8 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -2067,8 +2067,9 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
\enum QTextDocument::ResourceType
This enum describes the types of resources that can be loaded by
- QTextDocument's loadResource() function.
+ QTextDocument's loadResource() function or by QTextBrowser::setSource().
+ \value UnknownResource No resource is loaded, or the resource type is not known.
\value HtmlResource The resource contains HTML.
\value ImageResource The resource contains image data.
Currently supported data types are QVariant::Pixmap and
@@ -2082,7 +2083,7 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
\value UserResource The first available value for user defined
resource types.
- \sa loadResource()
+ \sa loadResource(), QTextBrowser::sourceType()
*/
/*!
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index c267ade0c2..b37353bf2c 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -399,6 +399,7 @@ struct QBidiAlgorithm {
analysis[i].bidiDirection = (level & 1) ? QChar::DirR : QChar::DirL;
runHasContent = true;
lastRunWithContent = -1;
+ ++isolatePairPosition;
}
int runBeforeIsolate = runs.size();
ushort newLevel = isRtl ? ((stack.top().level + 1) | 1) : ((stack.top().level + 2) & ~1);
@@ -440,21 +441,19 @@ struct QBidiAlgorithm {
doEmbed(true, true, false);
break;
case QChar::DirLRI:
- Q_ASSERT(isolatePairs.at(isolatePairPosition).start == i);
doEmbed(false, false, true);
- ++isolatePairPosition;
break;
case QChar::DirRLI:
- Q_ASSERT(isolatePairs.at(isolatePairPosition).start == i);
doEmbed(true, false, true);
- ++isolatePairPosition;
break;
case QChar::DirFSI: {
- const auto &pair = isolatePairs.at(isolatePairPosition);
- Q_ASSERT(pair.start == i);
- bool isRtl = QStringView(text + pair.start + 1, pair.end - pair.start - 1).isRightToLeft();
+ bool isRtl = false;
+ if (isolatePairPosition < isolatePairs.size()) {
+ const auto &pair = isolatePairs.at(isolatePairPosition);
+ Q_ASSERT(pair.start == i);
+ isRtl = QStringView(text + pair.start + 1, pair.end - pair.start - 1).isRightToLeft();
+ }
doEmbed(isRtl, false, true);
- ++isolatePairPosition;
break;
}
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 47a38db3ad..e3bd49a15e 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -650,6 +650,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\value TableColumns
\value TableColumnWidthConstraints
\value TableHeaderRowCount
+ \value TableBorderCollapse Specifies the \l QTextTableFormat::borderCollapse property.
Table cell properties