QtBase  v6.3.1
qshader.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Gui module
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qshader_p_p.h"
41 #include <QDataStream>
42 #include <QBuffer>
43 
45 
224  : d(new QShaderPrivate)
225 {
226 }
227 
232 {
233  qAtomicDetach(d);
234 }
235 
240  : d(other.d)
241 {
242  d->ref.ref();
243 }
244 
249 {
250  qAtomicAssign(d, other.d);
251  return *this;
252 }
253 
258 {
259  if (!d->ref.deref())
260  delete d;
261 }
262 
266 bool QShader::isValid() const
267 {
268  return !d->shaders.isEmpty();
269 }
270 
275 {
276  return d->stage;
277 }
278 
283 {
284  if (stage != d->stage) {
285  detach();
286  d->stage = stage;
287  }
288 }
289 
294 {
295  return d->desc;
296 }
297 
302 {
303  detach();
304  d->desc = desc;
305 }
306 
311 {
312  return d->shaders.keys().toVector();
313 }
314 
319 {
320  return d->shaders.value(key);
321 }
322 
327 {
328  if (d->shaders.value(key) == shader)
329  return;
330 
331  detach();
332  d->shaders[key] = shader;
333 }
334 
340 {
341  auto it = d->shaders.find(key);
342  if (it == d->shaders.end())
343  return;
344 
345  detach();
346  d->shaders.erase(it);
347 }
348 
349 static void writeShaderKey(QDataStream *ds, const QShaderKey &k)
350 {
351  *ds << int(k.source());
352  *ds << k.sourceVersion().version();
353  *ds << k.sourceVersion().flags();
354  *ds << int(k.sourceVariant());
355 }
356 
364 {
365  QBuffer buf;
366  QDataStream ds(&buf);
368  if (!buf.open(QIODevice::WriteOnly))
369  return QByteArray();
370 
372  ds << int(d->stage);
373  d->desc.serialize(&ds);
374  ds << int(d->shaders.count());
375  for (auto it = d->shaders.cbegin(), itEnd = d->shaders.cend(); it != itEnd; ++it) {
376  const QShaderKey &k(it.key());
377  writeShaderKey(&ds, k);
378  const QShaderCode &shader(d->shaders.value(k));
379  ds << shader.shader();
380  ds << shader.entryPoint();
381  }
382  ds << int(d->bindings.count());
383  for (auto it = d->bindings.cbegin(), itEnd = d->bindings.cend(); it != itEnd; ++it) {
384  const QShaderKey &k(it.key());
385  writeShaderKey(&ds, k);
386  const NativeResourceBindingMap &map(it.value());
387  ds << int(map.count());
388  for (auto mapIt = map.cbegin(), mapItEnd = map.cend(); mapIt != mapItEnd; ++mapIt) {
389  ds << mapIt.key();
390  ds << mapIt.value().first;
391  ds << mapIt.value().second;
392  }
393  }
394 
395  return qCompress(buf.buffer());
396 }
397 
398 static void readShaderKey(QDataStream *ds, QShaderKey *k)
399 {
400  int intVal;
401  *ds >> intVal;
402  k->setSource(QShader::Source(intVal));
403  QShaderVersion ver;
404  *ds >> intVal;
405  ver.setVersion(intVal);
406  *ds >> intVal;
407  ver.setFlags(QShaderVersion::Flags(intVal));
408  k->setSourceVersion(ver);
409  *ds >> intVal;
411 }
412 
419 {
420  QByteArray udata = qUncompress(data);
421  QBuffer buf(&udata);
422  QDataStream ds(&buf);
424  if (!buf.open(QIODevice::ReadOnly))
425  return QShader();
426 
427  QShader bs;
429  Q_ASSERT(d->ref.loadRelaxed() == 1); // must be detached
430  int intVal;
431  ds >> intVal;
432  d->qsbVersion = intVal;
433  if (d->qsbVersion != QShaderPrivate::QSB_VERSION
435  && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_CBOR
438  {
439  qWarning("Attempted to deserialize QShader with unknown version %d.", d->qsbVersion);
440  return QShader();
441  }
442 
443  ds >> intVal;
444  d->stage = Stage(intVal);
445  if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_CBOR) {
446  d->desc = QShaderDescription::deserialize(&ds, d->qsbVersion);
447  } else if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON) {
448  qWarning("Can no longer load QShaderDescription from CBOR.");
449  d->desc = QShaderDescription();
450  } else {
451  qWarning("Can no longer load QShaderDescription from binary JSON.");
452  d->desc = QShaderDescription();
453  }
454  int count;
455  ds >> count;
456  for (int i = 0; i < count; ++i) {
457  QShaderKey k;
458  readShaderKey(&ds, &k);
460  QByteArray s;
461  ds >> s;
462  shader.setShader(s);
463  ds >> s;
464  shader.setEntryPoint(s);
465  d->shaders[k] = shader;
466  }
467 
469  ds >> count;
470  for (int i = 0; i < count; ++i) {
471  QShaderKey k;
472  readShaderKey(&ds, &k);
474  int mapSize;
475  ds >> mapSize;
476  for (int b = 0; b < mapSize; ++b) {
477  int binding;
478  ds >> binding;
479  int firstNativeBinding;
480  ds >> firstNativeBinding;
481  int secondNativeBinding;
482  ds >> secondNativeBinding;
483  map.insert(binding, { firstNativeBinding, secondNativeBinding });
484  }
485  d->bindings.insert(k, map);
486  }
487  }
488 
489  return bs;
490 }
491 
493  : m_version(v), m_flags(f)
494 {
495 }
496 
498  : m_shader(code), m_entryPoint(entry)
499 {
500 }
501 
503  const QShaderVersion &sver,
504  QShader::Variant svar)
505  : m_source(s),
506  m_sourceVersion(sver),
507  m_sourceVariant(svar)
508 {
509 }
510 
518 bool operator==(const QShader &lhs, const QShader &rhs) noexcept
519 {
520  return lhs.d->stage == rhs.d->stage
521  && lhs.d->shaders == rhs.d->shaders;
522  // do not bother with desc and bindings, if the shader code is the same, the description must match too
523 }
524 
540 size_t qHash(const QShader &s, size_t seed) noexcept
541 {
543  seed = hash(seed, s.stage());
544  seed = qHashRange(s.d->shaders.keyValueBegin(),
545  s.d->shaders.keyValueEnd(),
546  seed);
547  return seed;
548 }
549 
556 bool operator==(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
557 {
558  return lhs.version() == rhs.version() && lhs.flags() == rhs.flags();
559 }
560 
561 #ifdef Q_OS_INTEGRITY
562 size_t qHash(const QShaderVersion &s, size_t seed) noexcept
563 {
564  return qHashMulti(seed, s.version(), s.flags());
565 }
566 #endif
567 
583 bool operator==(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
584 {
585  return lhs.source() == rhs.source() && lhs.sourceVersion() == rhs.sourceVersion()
586  && lhs.sourceVariant() == rhs.sourceVariant();
587 }
588 
604 size_t qHash(const QShaderKey &k, size_t seed) noexcept
605 {
606  return qHashMulti(seed,
607  k.source(),
608  k.sourceVersion().version(),
609  k.sourceVersion().flags(),
610  k.sourceVariant());
611 }
612 
618 bool operator==(const QShaderCode &lhs, const QShaderCode &rhs) noexcept
619 {
620  return lhs.shader() == rhs.shader() && lhs.entryPoint() == rhs.entryPoint();
621 }
622 
638 size_t qHash(const QShaderCode &k, size_t seed) noexcept
639 {
640  return qHash(k.shader(), seed);
641 }
642 
643 #ifndef QT_NO_DEBUG_STREAM
645 {
646  const QShaderPrivate *d = bs.d;
647  QDebugStateSaver saver(dbg);
648 
649  dbg.nospace() << "QShader("
650  << "stage=" << d->stage
651  << " shaders=" << d->shaders.keys()
652  << " desc.isValid=" << d->desc.isValid()
653  << ')';
654 
655  return dbg;
656 }
657 
659 {
660  QDebugStateSaver saver(dbg);
661  dbg.nospace() << "ShaderKey(" << k.source()
662  << " " << k.sourceVersion()
663  << " " << k.sourceVariant() << ")";
664  return dbg;
665 }
666 
668 {
669  QDebugStateSaver saver(dbg);
670  dbg.nospace() << "Version(" << v.version() << " " << v.flags() << ")";
671  return dbg;
672 }
673 #endif // QT_NO_DEBUG_STREAM
674 
712 {
713  auto it = d->bindings.constFind(key);
714  if (it == d->bindings.cend())
715  return nullptr;
716 
717  return &it.value();
718 }
719 
726 {
727  detach();
728  d->bindings[key] = map;
729 }
730 
735 {
736  auto it = d->bindings.find(key);
737  if (it == d->bindings.end())
738  return;
739 
740  detach();
741  d->bindings.erase(it);
742 }
743 
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
bool ref() noexcept
Definition: qbasicatomic.h:101
bool deref() noexcept
Definition: qbasicatomic.h:102
The QBuffer class provides a QIODevice interface for a QByteArray.
Definition: qbuffer.h:52
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:66
operator<<(QDataStream &ds, qfloat16 f)
Definition: qfloat16.cpp:327
void setVersion(int)
Definition: qdatastream.h:385
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:65
QDebug & nospace()
Definition: qdebug.h:113
Convenience class for custom QDebug operators.
Definition: qdebug.h:176
template< typename Enum > size_t qHash(QFlags< Enum > flags, size_t seed=0) noexcept
template< typename Enum > bool operator==(Enum lhs, QFlags< Enum > rhs)
template< typename InputIterator > size_t qHashRange(InputIterator first, InputIterator last, size_t seed=0)
const_iterator cbegin() const noexcept
Definition: qhash.h:1157
iterator find(const Key &key)
Definition: qhash.h:1204
QList< Key > keys() const
Definition: qhash.h:1029
iterator erase(const_iterator it)
Definition: qhash.h:1172
T value(const Key &key) const noexcept
Definition: qhash.h:997
iterator end() noexcept
Definition: qhash.h:1159
const_iterator cend() const noexcept
Definition: qhash.h:1161
template< typename... T > size_t qHashMulti(size_t seed, const T &...args)
qsizetype count(const Key &key) const noexcept
Definition: qhash.h:950
bool isEmpty() const noexcept
Definition: qhash.h:881
Definition: qlist.h:108
iterator insert(const Key &key, const T &value)
Definition: qmap.h:719
size_type count(const Key &key) const
Definition: qmap.h:439
const_iterator cend() const
Definition: qmap.h:640
const_iterator cbegin() const
Definition: qmap.h:636
bool operator==(const QShaderCode &lhs, const QShaderCode &rhs) noexcept
Definition: qshader.cpp:618
QShaderCode()=default
static QShaderDescription deserialize(QDataStream *stream, int version)
void serialize(QDataStream *stream) const
void removeResourceBindingMap(const QShaderKey &key)
Definition: qshader.cpp:734
QShaderCode shader(const QShaderKey &key) const
Definition: qshader.cpp:318
QList< QShaderKey > availableShaders() const
Definition: qshader.cpp:310
QShader & operator=(const QShader &other)
Definition: qshader.cpp:248
QByteArray serialized() const
Definition: qshader.cpp:363
static QShader fromSerialized(const QByteArray &data)
Definition: qshader.cpp:418
Stage stage() const
Definition: qshader.cpp:274
void removeShader(const QShaderKey &key)
Definition: qshader.cpp:339
QShader()
Definition: qshader.cpp:223
void setShader(const QShaderKey &key, const QShaderCode &shader)
Definition: qshader.cpp:326
void setResourceBindingMap(const QShaderKey &key, const NativeResourceBindingMap &map)
Definition: qshader.cpp:725
const NativeResourceBindingMap * nativeResourceBindingMap(const QShaderKey &key) const
Definition: qshader.cpp:711
void detach()
Definition: qshader.cpp:231
~QShader()
Definition: qshader.cpp:257
QShaderDescription description() const
Definition: qshader.cpp:293
void setDescription(const QShaderDescription &desc)
Definition: qshader.cpp:301
bool isValid() const
Definition: qshader.cpp:266
void setStage(Stage stage)
Definition: qshader.cpp:282
size_t qHash(const QShaderKey &k, size_t seed) noexcept
Definition: qshader.cpp:604
void setSource(QShader::Source s)
Definition: qshader_p.h:189
void setSourceVariant(QShader::Variant svar)
Definition: qshader_p.h:195
void setSourceVersion(const QShaderVersion &sver)
Definition: qshader_p.h:192
QShader::Source source() const
Definition: qshader_p.h:188
QShaderVersion sourceVersion() const
Definition: qshader_p.h:191
QShader::Variant sourceVariant() const
Definition: qshader_p.h:194
bool operator==(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
Definition: qshader.cpp:583
QShaderKey()=default
void setVersion(int v)
Definition: qshader_p.h:79
void setFlags(Flags f)
Definition: qshader_p.h:82
Flags flags() const
Definition: qshader_p.h:81
QShaderVersion()=default
int version() const
Definition: qshader_p.h:78
bool operator==(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
Definition: qshader.cpp:556
QHash< int, QWidget * > hash
[35multi]
QMap< QString, QString > map
[6]
QT_WARNING_POP void qAtomicAssign(T *&d, T *x)
Definition: qatomic.h:241
void qAtomicDetach(T *&d)
Definition: qatomic.h:260
Q_CORE_EXPORT QByteArray qCompress(const uchar *data, qsizetype nbytes, int compressionLevel=-1)
Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, qsizetype nbytes)
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
Flags
@ desc
#define qWarning
Definition: qlogging.h:179
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint64 key
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint entry
Definition: qopenglext.h:11002
GLuint shader
Definition: qopenglext.h:665
GLdouble s
[6]
Definition: qopenglext.h:235
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
@ desc
QSharedPointer< T > other(t)
[5]
QStringList::Iterator it
static const int QSB_VERSION_WITH_CBOR
Definition: qshader_p_p.h:65
QHash< QShaderKey, QShaderCode > shaders
Definition: qshader_p_p.h:91
static const int QSB_VERSION_WITH_BINARY_JSON
Definition: qshader_p_p.h:66
QShader::Stage stage
Definition: qshader_p_p.h:89
static const int QSB_VERSION_WITHOUT_BINDINGS
Definition: qshader_p_p.h:67
static const int QSB_VERSION_WITHOUT_VAR_ARRAYDIMS
Definition: qshader_p_p.h:64
static QShaderPrivate * get(QShader *s)
Definition: qshader_p_p.h:84
QAtomicInt ref
Definition: qshader_p_p.h:87
QHash< QShaderKey, QShader::NativeResourceBindingMap > bindings
Definition: qshader_p_p.h:92
QShaderDescription desc
Definition: qshader_p_p.h:90
static const int QSB_VERSION
Definition: qshader_p_p.h:63
Definition: inftrees.h:24
#define rhs