1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2019 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Gui module |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL3$ |
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 http://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free |
28 | ** Software Foundation and appearing in the file LICENSE.GPL included in |
29 | ** the packaging of this file. Please review the following information to |
30 | ** ensure the GNU General Public License version 2.0 requirements will be |
31 | ** met: http://www.gnu.org/licenses/gpl-2.0.html. |
32 | ** |
33 | ** $QT_END_LICENSE$ |
34 | ** |
35 | ****************************************************************************/ |
36 | |
37 | #include "qshaderdescription_p_p.h" |
38 | #include "qshader_p_p.h" |
39 | #include <QDebug> |
40 | #include <QDataStream> |
41 | #include <QJsonObject> |
42 | #include <QJsonArray> |
43 | |
44 | QT_BEGIN_NAMESPACE |
45 | |
46 | /*! |
47 | \class QShaderDescription |
48 | \internal |
49 | \inmodule QtGui |
50 | |
51 | \brief Describes the interface of a shader. |
52 | |
53 | A shader typically has a set of inputs and outputs. A vertex shader for |
54 | example has a number of input variables and may use one or more uniform |
55 | buffers to access data (e.g. a modelview matrix) provided by the |
56 | application. The shader for the fragment stage receives data from the |
57 | vertex stage (in a simple setup) and may also rely on data from uniform |
58 | buffers, images, and samplers. |
59 | |
60 | When it comes to vertex inputs and the layout of the uniform buffers (what |
61 | are the names of the members? what is there size, offset, and so on), |
62 | applications and frameworks may need to discover this dynamically at run |
63 | time. This is typical when the shader is not built-in but provided by an |
64 | external entity, like the user. |
65 | |
66 | Modern and lean graphics APIs may no longer provide a way to query shader |
67 | reflection information at run time. Therefore, such data is now |
68 | automatically generated by QShaderBaker and is provided as a |
69 | QShaderDescription object for each and every QShader. |
70 | |
71 | \section2 Example |
72 | |
73 | Take the following vertex shader: |
74 | |
75 | \badcode |
76 | #version 440 |
77 | |
78 | layout(location = 0) in vec4 position; |
79 | layout(location = 1) in vec3 color; |
80 | layout(location = 0) out vec3 v_color; |
81 | |
82 | layout(std140, binding = 0) uniform buf { |
83 | mat4 mvp; |
84 | float opacity; |
85 | } ubuf; |
86 | |
87 | out gl_PerVertex { vec4 gl_Position; }; |
88 | |
89 | void main() |
90 | { |
91 | v_color = color; |
92 | gl_Position = ubuf.mvp * position; |
93 | } |
94 | \endcode |
95 | |
96 | This shader has two inputs: \c position at location 0 with a type of \c |
97 | vec4, and \c color at location 1 with a type of \c vec3. It has one output: |
98 | \c v_color, although this is typically not interesting for applications. |
99 | What is more important, there is a uniform block at binding 0 with a size |
100 | of 68 bytes and two members, a 4x4 matrix named \c mvp at offset 0, and a |
101 | float \c opacity at offset 64. |
102 | |
103 | All this is described by a QShaderDescription object. QShaderDescription can |
104 | be serialized to JSON and to a binary format via QDataStream, and can be |
105 | deserialized from this binary format. In practice this is rarely needed |
106 | since QShader takes care of the associated QShaderDescription automatically, |
107 | but if the QShaderDescription of the above shader would be written out as |
108 | JSON (like it is done by the \c qsb tool's \c{-d} option), it would look |
109 | like the following: |
110 | |
111 | \badcode |
112 | { |
113 | "inputs": [ |
114 | { |
115 | "location": 1, |
116 | "name": "color", |
117 | "type": "vec3" |
118 | }, |
119 | { |
120 | "location": 0, |
121 | "name": "position", |
122 | "type": "vec4" |
123 | } |
124 | ], |
125 | "outputs": [ |
126 | { |
127 | "location": 0, |
128 | "name": "v_color", |
129 | "type": "vec3" |
130 | } |
131 | ], |
132 | "uniformBlocks": [ |
133 | { |
134 | "binding": 0, |
135 | "blockName": "buf", |
136 | "members": [ |
137 | { |
138 | "matrixStride": 16, |
139 | "name": "mvp", |
140 | "offset": 0, |
141 | "size": 64, |
142 | "type": "mat4" |
143 | }, |
144 | { |
145 | "name": "opacity", |
146 | "offset": 64, |
147 | "size": 4, |
148 | "type": "float" |
149 | } |
150 | ], |
151 | "set": 0, |
152 | "size": 68, |
153 | "structName": "ubuf" |
154 | } |
155 | ] |
156 | } |
157 | \endcode |
158 | |
159 | The C++ API allows accessing a data structure like the above. For |
160 | simplicity the inner structs only contain public data members, also |
161 | considering that their layout is unlikely to change in the future. |
162 | |
163 | \sa QShaderBaker, QShader |
164 | */ |
165 | |
166 | /*! |
167 | \enum QShaderDescription::VariableType |
168 | Represents the type of a variable or block member. |
169 | |
170 | \value Unknown |
171 | \value Float |
172 | \value Vec2 |
173 | \value Vec3 |
174 | \value Vec4 |
175 | \value Mat2 |
176 | \value Mat2x3 |
177 | \value Mat2x4 |
178 | \value Mat3 |
179 | \value Mat3x2 |
180 | \value Mat3x4 |
181 | \value Mat4 |
182 | \value Mat4x2 |
183 | \value Mat4x3 |
184 | \value Int |
185 | \value Int2 |
186 | \value Int3 |
187 | \value Int4 |
188 | \value Uint |
189 | \value Uint2 |
190 | \value Uint3 |
191 | \value Uint4 |
192 | \value Bool |
193 | \value Bool2 |
194 | \value Bool3 |
195 | \value Bool4 |
196 | \value Double |
197 | \value Double2 |
198 | \value Double3 |
199 | \value Double4 |
200 | \value DMat2 |
201 | \value DMat2x3 |
202 | \value DMat2x4 |
203 | \value DMat3 |
204 | \value DMat3x2 |
205 | \value DMat3x4 |
206 | \value DMat4 |
207 | \value DMat4x2 |
208 | \value DMat4x3 |
209 | \value Sampler1D |
210 | \value Sampler2D |
211 | \value Sampler2DMS |
212 | \value Sampler3D |
213 | \value SamplerCube |
214 | \value Sampler1DArray |
215 | \value Sampler2DArray |
216 | \value Sampler2DMSArray |
217 | \value Sampler3DArray |
218 | \value SamplerCubeArray |
219 | \value SamplerRect |
220 | \value SamplerBuffer |
221 | \value Image1D |
222 | \value Image2D |
223 | \value Image2DMS |
224 | \value Image3D |
225 | \value ImageCube |
226 | \value Image1DArray |
227 | \value Image2DArray |
228 | \value Image2DMSArray |
229 | \value Image3DArray |
230 | \value ImageCubeArray |
231 | \value ImageRect |
232 | \value ImageBuffer |
233 | \value Struct |
234 | */ |
235 | |
236 | /*! |
237 | \class QShaderDescription::InOutVariable |
238 | \internal |
239 | \inmodule QtGui |
240 | |
241 | \brief Describes an input or output variable in the shader. |
242 | */ |
243 | |
244 | /*! |
245 | \class QShaderDescription::BlockVariable |
246 | \internal |
247 | \inmodule QtGui |
248 | |
249 | \brief Describes a member of a uniform or push constant block. |
250 | */ |
251 | |
252 | /*! |
253 | \class QShaderDescription::UniformBlock |
254 | \internal |
255 | \inmodule QtGui |
256 | |
257 | \brief Describes a uniform block. |
258 | |
259 | \note When translating to shading languages without uniform block support |
260 | (like GLSL 120 or GLSL/ES 100), uniform blocks are replaced with ordinary |
261 | uniforms in a struct. The name of the struct, and so the prefix for the |
262 | uniforms generated from the block members, is given by structName. |
263 | */ |
264 | |
265 | /*! |
266 | \class QShaderDescription::PushConstantBlock |
267 | \internal |
268 | \inmodule QtGui |
269 | |
270 | \brief Describes a push constant block. |
271 | */ |
272 | |
273 | /*! |
274 | \class QShaderDescription::StorageBlock |
275 | \internal |
276 | \inmodule QtGui |
277 | |
278 | \brief Describes a shader storage block. |
279 | */ |
280 | |
281 | /*! |
282 | Constructs a new, empty QShaderDescription. |
283 | |
284 | \note Being empty implies that isValid() returns \c false for the |
285 | newly constructed instance. |
286 | */ |
287 | QShaderDescription::QShaderDescription() |
288 | : d(new QShaderDescriptionPrivate) |
289 | { |
290 | } |
291 | |
292 | /*! |
293 | \internal |
294 | */ |
295 | void QShaderDescription::detach() |
296 | { |
297 | qAtomicDetach(d); |
298 | } |
299 | |
300 | /*! |
301 | \internal |
302 | */ |
303 | QShaderDescription::QShaderDescription(const QShaderDescription &other) |
304 | : d(other.d) |
305 | { |
306 | d->ref.ref(); |
307 | } |
308 | |
309 | /*! |
310 | \internal |
311 | */ |
312 | QShaderDescription &QShaderDescription::operator=(const QShaderDescription &other) |
313 | { |
314 | qAtomicAssign(d, other.d); |
315 | return *this; |
316 | } |
317 | |
318 | /*! |
319 | Destructor. |
320 | */ |
321 | QShaderDescription::~QShaderDescription() |
322 | { |
323 | if (!d->ref.deref()) |
324 | delete d; |
325 | } |
326 | |
327 | /*! |
328 | \return true if the QShaderDescription contains at least one entry in one of |
329 | the variable and block lists. |
330 | */ |
331 | bool QShaderDescription::isValid() const |
332 | { |
333 | return !d->inVars.isEmpty() || !d->outVars.isEmpty() |
334 | || !d->uniformBlocks.isEmpty() || !d->pushConstantBlocks.isEmpty() || !d->storageBlocks.isEmpty() |
335 | || !d->combinedImageSamplers.isEmpty() || !d->storageImages.isEmpty(); |
336 | } |
337 | |
338 | /*! |
339 | \return a serialized JSON text version of the data. |
340 | |
341 | \note There is no deserialization method provided for JSON text. |
342 | |
343 | \sa serialize() |
344 | */ |
345 | QByteArray QShaderDescription::toJson() const |
346 | { |
347 | return d->makeDoc().toJson(); |
348 | } |
349 | |
350 | /*! |
351 | Serializes this QShaderDescription to \a stream. |
352 | |
353 | \sa deserialize(), toJson() |
354 | */ |
355 | void QShaderDescription::serialize(QDataStream *stream) const |
356 | { |
357 | d->writeToStream(stream); |
358 | } |
359 | |
360 | /*! |
361 | \return a new QShaderDescription loaded from \a stream. \a version specifies |
362 | the qsb version. |
363 | |
364 | \sa serialize() |
365 | */ |
366 | QShaderDescription QShaderDescription::deserialize(QDataStream *stream, int version) |
367 | { |
368 | QShaderDescription desc; |
369 | QShaderDescriptionPrivate::get(&desc)->loadFromStream(stream, version); |
370 | return desc; |
371 | } |
372 | |
373 | /*! |
374 | \return the list of input variables. This includes vertex inputs (sometimes |
375 | called attributes) for the vertex stage, and inputs for other stages |
376 | (sometimes called varyings). |
377 | */ |
378 | QList<QShaderDescription::InOutVariable> QShaderDescription::inputVariables() const |
379 | { |
380 | return d->inVars; |
381 | } |
382 | |
383 | /*! |
384 | \return the list of output variables. |
385 | */ |
386 | QList<QShaderDescription::InOutVariable> QShaderDescription::outputVariables() const |
387 | { |
388 | return d->outVars; |
389 | } |
390 | |
391 | /*! |
392 | \return the list of uniform blocks. |
393 | */ |
394 | QList<QShaderDescription::UniformBlock> QShaderDescription::uniformBlocks() const |
395 | { |
396 | return d->uniformBlocks; |
397 | } |
398 | |
399 | /*! |
400 | \return the list of push constant blocks. |
401 | |
402 | \note Avoid relying on push constant blocks for shaders that are to be used |
403 | in combination with the Qt Rendering Hardware Interface since that |
404 | currently has no support for them. |
405 | */ |
406 | QList<QShaderDescription::PushConstantBlock> QShaderDescription::pushConstantBlocks() const |
407 | { |
408 | return d->pushConstantBlocks; |
409 | } |
410 | |
411 | /*! |
412 | \return the list of shader storage blocks. |
413 | |
414 | For example, with GLSL/Vulkan shaders as source, the declaration |
415 | |
416 | \badcode |
417 | struct Stuff { |
418 | vec2 a; |
419 | vec2 b; |
420 | }; |
421 | layout(std140, binding = 0) buffer StuffSsbo { |
422 | vec4 whatever; |
423 | Stuff stuff[]; |
424 | } buf; |
425 | \endcode |
426 | |
427 | generates the following: (shown as textual JSON here) |
428 | |
429 | \badcode |
430 | "storageBlocks": [ { |
431 | "binding": 0, |
432 | "blockName": "StuffSsbo", |
433 | "instanceName": "buf", |
434 | "knownSize": 16, |
435 | "members": [ |
436 | { |
437 | "name": "whatever", |
438 | "offset": 0, |
439 | "size": 16, |
440 | "type": "vec4" |
441 | }, |
442 | { |
443 | "arrayDims": [ |
444 | 0 |
445 | ], |
446 | "name": "stuff", |
447 | "offset": 16, |
448 | "size": 0, |
449 | "structMembers": [ |
450 | { |
451 | "name": "a", |
452 | "offset": 0, |
453 | "size": 8, |
454 | "type": "vec2" |
455 | }, |
456 | { |
457 | "name": "b", |
458 | "offset": 8, |
459 | "size": 8, |
460 | "type": "vec2" |
461 | } |
462 | ], |
463 | "type": "struct" |
464 | } |
465 | ], |
466 | "set": 0 |
467 | } ] |
468 | \endcode |
469 | |
470 | \note The size of the last member in the storage block is undefined. This shows |
471 | up as \c size 0 and an array dimension of \c{[0]}. The storage block's \c knownSize |
472 | excludes the size of the last member since that will only be known at run time. |
473 | |
474 | \note SSBOs are not available with some graphics APIs, such as, OpenGL 2.x or |
475 | OpenGL ES older than 3.1. |
476 | */ |
477 | QList<QShaderDescription::StorageBlock> QShaderDescription::storageBlocks() const |
478 | { |
479 | return d->storageBlocks; |
480 | } |
481 | |
482 | /*! |
483 | \return the list of combined image samplers |
484 | |
485 | With GLSL/Vulkan shaders as source a \c{layout(binding = 1) uniform sampler2D tex;} |
486 | uniform generates the following: (shown as textual JSON here) |
487 | |
488 | \badcode |
489 | "combinedImageSamplers": [ |
490 | { |
491 | "binding": 1, |
492 | "name": "tex", |
493 | "set": 0, |
494 | "type": "sampler2D" |
495 | } |
496 | ] |
497 | \endcode |
498 | |
499 | This does not mean that other language versions of the shader must also use |
500 | a combined image sampler, especially considering that the concept may not |
501 | exist everywhere. For instance, a HLSL version will likely just use a |
502 | Texture2D and SamplerState object with registers t1 and s1, respectively. |
503 | */ |
504 | QList<QShaderDescription::InOutVariable> QShaderDescription::combinedImageSamplers() const |
505 | { |
506 | return d->combinedImageSamplers; |
507 | } |
508 | |
509 | /*! |
510 | \return the list of image variables. |
511 | |
512 | These will likely occur in compute shaders. For example, |
513 | \c{layout (binding = 0, rgba8) uniform readonly image2D inputImage;} |
514 | generates the following: (shown as textual JSON here) |
515 | |
516 | \badcode |
517 | "storageImages": [ |
518 | { |
519 | "binding": 0, |
520 | "imageFormat": "rgba8", |
521 | "name": "inputImage", |
522 | "set": 0, |
523 | "type": "image2D" |
524 | } |
525 | ] |
526 | \endcode |
527 | |
528 | \note Separate image objects are not compatible with some graphics APIs, |
529 | such as, OpenGL 2.x or OpenGL ES older than 3.1. |
530 | */ |
531 | QList<QShaderDescription::InOutVariable> QShaderDescription::storageImages() const |
532 | { |
533 | return d->storageImages; |
534 | } |
535 | |
536 | /*! |
537 | Returns the local size of a compute shader. |
538 | |
539 | For example, for a compute shader with the following declaration the |
540 | function returns { 256, 16, 1}. |
541 | |
542 | \badcode |
543 | layout(local_size_x = 256, local_size_y = 16, local_size_z = 1) in; |
544 | \endcode |
545 | */ |
546 | std::array<uint, 3> QShaderDescription::computeShaderLocalSize() const |
547 | { |
548 | return d->localSize; |
549 | } |
550 | |
551 | static struct TypeTab { |
552 | QString k; |
553 | QShaderDescription::VariableType v; |
554 | } typeTab[] = { |
555 | { QLatin1String("float" ), QShaderDescription::Float }, |
556 | { QLatin1String("vec2" ), QShaderDescription::Vec2 }, |
557 | { QLatin1String("vec3" ), QShaderDescription::Vec3 }, |
558 | { QLatin1String("vec4" ), QShaderDescription::Vec4 }, |
559 | { QLatin1String("mat2" ), QShaderDescription::Mat2 }, |
560 | { QLatin1String("mat3" ), QShaderDescription::Mat3 }, |
561 | { QLatin1String("mat4" ), QShaderDescription::Mat4 }, |
562 | |
563 | { QLatin1String("struct" ), QShaderDescription::Struct }, |
564 | |
565 | { QLatin1String("sampler1D" ), QShaderDescription::Sampler1D }, |
566 | { QLatin1String("sampler2D" ), QShaderDescription::Sampler2D }, |
567 | { QLatin1String("sampler2DMS" ), QShaderDescription::Sampler2DMS }, |
568 | { QLatin1String("sampler3D" ), QShaderDescription::Sampler3D }, |
569 | { QLatin1String("samplerCube" ), QShaderDescription::SamplerCube }, |
570 | { QLatin1String("sampler1DArray" ), QShaderDescription::Sampler1DArray }, |
571 | { QLatin1String("sampler2DArray" ), QShaderDescription::Sampler2DArray }, |
572 | { QLatin1String("sampler2DMSArray" ), QShaderDescription::Sampler2DMSArray }, |
573 | { QLatin1String("sampler3DArray" ), QShaderDescription::Sampler3DArray }, |
574 | { QLatin1String("samplerCubeArray" ), QShaderDescription::SamplerCubeArray }, |
575 | { QLatin1String("samplerRect" ), QShaderDescription::SamplerRect }, |
576 | { QLatin1String("samplerBuffer" ), QShaderDescription::SamplerBuffer }, |
577 | |
578 | { QLatin1String("mat2x3" ), QShaderDescription::Mat2x3 }, |
579 | { QLatin1String("mat2x4" ), QShaderDescription::Mat2x4 }, |
580 | { QLatin1String("mat3x2" ), QShaderDescription::Mat3x2 }, |
581 | { QLatin1String("mat3x4" ), QShaderDescription::Mat3x4 }, |
582 | { QLatin1String("mat4x2" ), QShaderDescription::Mat4x2 }, |
583 | { QLatin1String("mat4x3" ), QShaderDescription::Mat4x3 }, |
584 | |
585 | { QLatin1String("int" ), QShaderDescription::Int }, |
586 | { QLatin1String("ivec2" ), QShaderDescription::Int2 }, |
587 | { QLatin1String("ivec3" ), QShaderDescription::Int3 }, |
588 | { QLatin1String("ivec4" ), QShaderDescription::Int4 }, |
589 | |
590 | { QLatin1String("uint" ), QShaderDescription::Uint }, |
591 | { QLatin1String("uvec2" ), QShaderDescription::Uint2 }, |
592 | { QLatin1String("uvec3" ), QShaderDescription::Uint3 }, |
593 | { QLatin1String("uvec4" ), QShaderDescription::Uint4 }, |
594 | |
595 | { QLatin1String("bool" ), QShaderDescription::Bool }, |
596 | { QLatin1String("bvec2" ), QShaderDescription::Bool2 }, |
597 | { QLatin1String("bvec3" ), QShaderDescription::Bool3 }, |
598 | { QLatin1String("bvec4" ), QShaderDescription::Bool4 }, |
599 | |
600 | { QLatin1String("double" ), QShaderDescription::Double }, |
601 | { QLatin1String("dvec2" ), QShaderDescription::Double2 }, |
602 | { QLatin1String("dvec3" ), QShaderDescription::Double3 }, |
603 | { QLatin1String("dvec4" ), QShaderDescription::Double4 }, |
604 | { QLatin1String("dmat2" ), QShaderDescription::DMat2 }, |
605 | { QLatin1String("dmat3" ), QShaderDescription::DMat3 }, |
606 | { QLatin1String("dmat4" ), QShaderDescription::DMat4 }, |
607 | { QLatin1String("dmat2x3" ), QShaderDescription::DMat2x3 }, |
608 | { QLatin1String("dmat2x4" ), QShaderDescription::DMat2x4 }, |
609 | { QLatin1String("dmat3x2" ), QShaderDescription::DMat3x2 }, |
610 | { QLatin1String("dmat3x4" ), QShaderDescription::DMat3x4 }, |
611 | { QLatin1String("dmat4x2" ), QShaderDescription::DMat4x2 }, |
612 | { QLatin1String("dmat4x3" ), QShaderDescription::DMat4x3 }, |
613 | |
614 | { QLatin1String("image1D" ), QShaderDescription::Image1D }, |
615 | { QLatin1String("image2D" ), QShaderDescription::Image2D }, |
616 | { QLatin1String("image2DMS" ), QShaderDescription::Image2DMS }, |
617 | { QLatin1String("image3D" ), QShaderDescription::Image3D }, |
618 | { QLatin1String("imageCube" ), QShaderDescription::ImageCube }, |
619 | { QLatin1String("image1DArray" ), QShaderDescription::Image1DArray }, |
620 | { QLatin1String("image2DArray" ), QShaderDescription::Image2DArray }, |
621 | { QLatin1String("image2DMSArray" ), QShaderDescription::Image2DMSArray }, |
622 | { QLatin1String("image3DArray" ), QShaderDescription::Image3DArray }, |
623 | { QLatin1String("imageCubeArray" ), QShaderDescription::ImageCubeArray }, |
624 | { QLatin1String("imageRect" ), QShaderDescription::ImageRect }, |
625 | { QLatin1String("imageBuffer" ), QShaderDescription::ImageBuffer } |
626 | }; |
627 | |
628 | static QString typeStr(const QShaderDescription::VariableType &t) |
629 | { |
630 | for (size_t i = 0; i < sizeof(typeTab) / sizeof(TypeTab); ++i) { |
631 | if (typeTab[i].v == t) |
632 | return typeTab[i].k; |
633 | } |
634 | return QString(); |
635 | } |
636 | |
637 | static struct ImageFormatTab { |
638 | QString k; |
639 | QShaderDescription::ImageFormat v; |
640 | } imageFormatTab[] { |
641 | { QLatin1String("unknown" ), QShaderDescription::ImageFormatUnknown }, |
642 | { QLatin1String("rgba32f" ), QShaderDescription::ImageFormatRgba32f }, |
643 | { QLatin1String("rgba16" ), QShaderDescription::ImageFormatRgba16f }, |
644 | { QLatin1String("r32f" ), QShaderDescription::ImageFormatR32f }, |
645 | { QLatin1String("rgba8" ), QShaderDescription::ImageFormatRgba8 }, |
646 | { QLatin1String("rgba8_snorm" ), QShaderDescription::ImageFormatRgba8Snorm }, |
647 | { QLatin1String("rg32f" ), QShaderDescription::ImageFormatRg32f }, |
648 | { QLatin1String("rg16f" ), QShaderDescription::ImageFormatRg16f }, |
649 | { QLatin1String("r11f_g11f_b10f" ), QShaderDescription::ImageFormatR11fG11fB10f }, |
650 | { QLatin1String("r16f" ), QShaderDescription::ImageFormatR16f }, |
651 | { QLatin1String("rgba16" ), QShaderDescription::ImageFormatRgba16 }, |
652 | { QLatin1String("rgb10_a2" ), QShaderDescription::ImageFormatRgb10A2 }, |
653 | { QLatin1String("rg16" ), QShaderDescription::ImageFormatRg16 }, |
654 | { QLatin1String("rg8" ), QShaderDescription::ImageFormatRg8 }, |
655 | { QLatin1String("r16" ), QShaderDescription::ImageFormatR16 }, |
656 | { QLatin1String("r8" ), QShaderDescription::ImageFormatR8 }, |
657 | { QLatin1String("rgba16_snorm" ), QShaderDescription::ImageFormatRgba16Snorm }, |
658 | { QLatin1String("rg16_snorm" ), QShaderDescription::ImageFormatRg16Snorm }, |
659 | { QLatin1String("rg8_snorm" ), QShaderDescription::ImageFormatRg8Snorm }, |
660 | { QLatin1String("r16_snorm" ), QShaderDescription::ImageFormatR16Snorm }, |
661 | { QLatin1String("r8_snorm" ), QShaderDescription::ImageFormatR8Snorm }, |
662 | { QLatin1String("rgba32i" ), QShaderDescription::ImageFormatRgba32i }, |
663 | { QLatin1String("rgba16i" ), QShaderDescription::ImageFormatRgba16i }, |
664 | { QLatin1String("rgba8i" ), QShaderDescription::ImageFormatRgba8i }, |
665 | { QLatin1String("r32i" ), QShaderDescription::ImageFormatR32i }, |
666 | { QLatin1String("rg32i" ), QShaderDescription::ImageFormatRg32i }, |
667 | { QLatin1String("rg16i" ), QShaderDescription::ImageFormatRg16i }, |
668 | { QLatin1String("rg8i" ), QShaderDescription::ImageFormatRg8i }, |
669 | { QLatin1String("r16i" ), QShaderDescription::ImageFormatR16i }, |
670 | { QLatin1String("r8i" ), QShaderDescription::ImageFormatR8i }, |
671 | { QLatin1String("rgba32ui" ), QShaderDescription::ImageFormatRgba32ui }, |
672 | { QLatin1String("rgba16ui" ), QShaderDescription::ImageFormatRgba16ui }, |
673 | { QLatin1String("rgba8ui" ), QShaderDescription::ImageFormatRgba8ui }, |
674 | { QLatin1String("r32ui" ), QShaderDescription::ImageFormatR32ui }, |
675 | { QLatin1String("rgb10_a2ui" ), QShaderDescription::ImageFormatRgb10a2ui }, |
676 | { QLatin1String("rg32ui" ), QShaderDescription::ImageFormatRg32ui }, |
677 | { QLatin1String("rg16ui" ), QShaderDescription::ImageFormatRg16ui }, |
678 | { QLatin1String("rg8ui" ), QShaderDescription::ImageFormatRg8ui }, |
679 | { QLatin1String("r16ui" ), QShaderDescription::ImageFormatR16ui }, |
680 | { QLatin1String("r8ui" ), QShaderDescription::ImageFormatR8ui } |
681 | }; |
682 | |
683 | static QString imageFormatStr(const QShaderDescription::ImageFormat &f) |
684 | { |
685 | for (size_t i = 0; i < sizeof(imageFormatTab) / sizeof(ImageFormatTab); ++i) { |
686 | if (imageFormatTab[i].v == f) |
687 | return imageFormatTab[i].k; |
688 | } |
689 | return QString(); |
690 | } |
691 | |
692 | #ifndef QT_NO_DEBUG_STREAM |
693 | QDebug operator<<(QDebug dbg, const QShaderDescription &sd) |
694 | { |
695 | const QShaderDescriptionPrivate *d = sd.d; |
696 | QDebugStateSaver saver(dbg); |
697 | |
698 | if (sd.isValid()) { |
699 | dbg.nospace() << "QShaderDescription(" |
700 | << "inVars " << d->inVars |
701 | << " outVars " << d->outVars |
702 | << " uniformBlocks " << d->uniformBlocks |
703 | << " pcBlocks " << d->pushConstantBlocks |
704 | << " storageBlocks " << d->storageBlocks |
705 | << " combinedSamplers " << d->combinedImageSamplers |
706 | << " images " << d->storageImages |
707 | << ')'; |
708 | } else { |
709 | dbg.nospace() << "QShaderDescription(null)" ; |
710 | } |
711 | |
712 | return dbg; |
713 | } |
714 | |
715 | QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var) |
716 | { |
717 | QDebugStateSaver saver(dbg); |
718 | dbg.nospace() << "InOutVariable(" << typeStr(var.type) << ' ' << var.name; |
719 | if (var.location >= 0) |
720 | dbg.nospace() << " location=" << var.location; |
721 | if (var.binding >= 0) |
722 | dbg.nospace() << " binding=" << var.binding; |
723 | if (var.descriptorSet >= 0) |
724 | dbg.nospace() << " set=" << var.descriptorSet; |
725 | if (var.imageFormat != QShaderDescription::ImageFormatUnknown) |
726 | dbg.nospace() << " imageFormat=" << imageFormatStr(var.imageFormat); |
727 | if (var.imageFlags) |
728 | dbg.nospace() << " imageFlags=" << var.imageFlags; |
729 | if (!var.arrayDims.isEmpty()) |
730 | dbg.nospace() << " array=" << var.arrayDims; |
731 | dbg.nospace() << ')'; |
732 | return dbg; |
733 | } |
734 | |
735 | QDebug operator<<(QDebug dbg, const QShaderDescription::BlockVariable &var) |
736 | { |
737 | QDebugStateSaver saver(dbg); |
738 | dbg.nospace() << "BlockVariable(" << typeStr(var.type) << ' ' << var.name |
739 | << " offset=" << var.offset << " size=" << var.size; |
740 | if (!var.arrayDims.isEmpty()) |
741 | dbg.nospace() << " array=" << var.arrayDims; |
742 | if (var.arrayStride) |
743 | dbg.nospace() << " arrayStride=" << var.arrayStride; |
744 | if (var.matrixStride) |
745 | dbg.nospace() << " matrixStride=" << var.matrixStride; |
746 | if (var.matrixIsRowMajor) |
747 | dbg.nospace() << " [rowmaj]" ; |
748 | if (!var.structMembers.isEmpty()) |
749 | dbg.nospace() << " structMembers=" << var.structMembers; |
750 | dbg.nospace() << ')'; |
751 | return dbg; |
752 | } |
753 | |
754 | QDebug operator<<(QDebug dbg, const QShaderDescription::UniformBlock &blk) |
755 | { |
756 | QDebugStateSaver saver(dbg); |
757 | dbg.nospace() << "UniformBlock(" << blk.blockName << ' ' << blk.structName |
758 | << " size=" << blk.size; |
759 | if (blk.binding >= 0) |
760 | dbg.nospace() << " binding=" << blk.binding; |
761 | if (blk.descriptorSet >= 0) |
762 | dbg.nospace() << " set=" << blk.descriptorSet; |
763 | dbg.nospace() << ' ' << blk.members << ')'; |
764 | return dbg; |
765 | } |
766 | |
767 | QDebug operator<<(QDebug dbg, const QShaderDescription::PushConstantBlock &blk) |
768 | { |
769 | QDebugStateSaver saver(dbg); |
770 | dbg.nospace() << "PushConstantBlock(" << blk.name << " size=" << blk.size << ' ' << blk.members |
771 | << ')'; |
772 | return dbg; |
773 | } |
774 | |
775 | QDebug operator<<(QDebug dbg, const QShaderDescription::StorageBlock &blk) |
776 | { |
777 | QDebugStateSaver saver(dbg); |
778 | dbg.nospace() << "StorageBlock(" << blk.blockName << ' ' << blk.instanceName |
779 | << " knownSize=" << blk.knownSize; |
780 | if (blk.binding >= 0) |
781 | dbg.nospace() << " binding=" << blk.binding; |
782 | if (blk.descriptorSet >= 0) |
783 | dbg.nospace() << " set=" << blk.descriptorSet; |
784 | dbg.nospace() << ' ' << blk.members << ')'; |
785 | return dbg; |
786 | } |
787 | #endif |
788 | |
789 | static const QString nameKey = QLatin1String("name" ); |
790 | static const QString typeKey = QLatin1String("type" ); |
791 | static const QString locationKey = QLatin1String("location" ); |
792 | static const QString bindingKey = QLatin1String("binding" ); |
793 | static const QString setKey = QLatin1String("set" ); |
794 | static const QString imageFormatKey = QLatin1String("imageFormat" ); |
795 | static const QString imageFlagsKey = QLatin1String("imageFlags" ); |
796 | static const QString offsetKey = QLatin1String("offset" ); |
797 | static const QString arrayDimsKey = QLatin1String("arrayDims" ); |
798 | static const QString arrayStrideKey = QLatin1String("arrayStride" ); |
799 | static const QString matrixStrideKey = QLatin1String("matrixStride" ); |
800 | static const QString matrixRowMajorKey = QLatin1String("matrixRowMajor" ); |
801 | static const QString structMembersKey = QLatin1String("structMembers" ); |
802 | static const QString membersKey = QLatin1String("members" ); |
803 | static const QString inputsKey = QLatin1String("inputs" ); |
804 | static const QString outputsKey = QLatin1String("outputs" ); |
805 | static const QString uniformBlocksKey = QLatin1String("uniformBlocks" ); |
806 | static const QString blockNameKey = QLatin1String("blockName" ); |
807 | static const QString structNameKey = QLatin1String("structName" ); |
808 | static const QString instanceNameKey = QLatin1String("instanceName" ); |
809 | static const QString sizeKey = QLatin1String("size" ); |
810 | static const QString knownSizeKey = QLatin1String("knownSize" ); |
811 | static const QString pushConstantBlocksKey = QLatin1String("pushConstantBlocks" ); |
812 | static const QString storageBlocksKey = QLatin1String("storageBlocks" ); |
813 | static const QString combinedImageSamplersKey = QLatin1String("combinedImageSamplers" ); |
814 | static const QString storageImagesKey = QLatin1String("storageImages" ); |
815 | static const QString localSizeKey = QLatin1String("localSize" ); |
816 | |
817 | static void addDeco(QJsonObject *obj, const QShaderDescription::InOutVariable &v) |
818 | { |
819 | if (v.location >= 0) |
820 | (*obj)[locationKey] = v.location; |
821 | if (v.binding >= 0) |
822 | (*obj)[bindingKey] = v.binding; |
823 | if (v.descriptorSet >= 0) |
824 | (*obj)[setKey] = v.descriptorSet; |
825 | if (v.imageFormat != QShaderDescription::ImageFormatUnknown) |
826 | (*obj)[imageFormatKey] = imageFormatStr(v.imageFormat); |
827 | if (v.imageFlags) |
828 | (*obj)[imageFlagsKey] = int(v.imageFlags); |
829 | if (!v.arrayDims.isEmpty()) { |
830 | QJsonArray dimArr; |
831 | for (int dim : v.arrayDims) |
832 | dimArr.append(dim); |
833 | (*obj)[arrayDimsKey] = dimArr; |
834 | } |
835 | } |
836 | |
837 | static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v) |
838 | { |
839 | (*stream) << v.location; |
840 | (*stream) << v.binding; |
841 | (*stream) << v.descriptorSet; |
842 | (*stream) << int(v.imageFormat); |
843 | (*stream) << int(v.imageFlags); |
844 | (*stream) << int(v.arrayDims.count()); |
845 | for (int dim : v.arrayDims) |
846 | (*stream) << dim; |
847 | } |
848 | |
849 | static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v) |
850 | { |
851 | QJsonObject obj; |
852 | obj[nameKey] = QString::fromUtf8(v.name); |
853 | obj[typeKey] = typeStr(v.type); |
854 | addDeco(&obj, v); |
855 | return obj; |
856 | } |
857 | |
858 | static void serializeInOutVar(QDataStream *stream, const QShaderDescription::InOutVariable &v) |
859 | { |
860 | (*stream) << QString::fromUtf8(v.name); |
861 | (*stream) << int(v.type); |
862 | serializeDecorations(stream, v); |
863 | } |
864 | |
865 | static QJsonObject blockMemberObject(const QShaderDescription::BlockVariable &v) |
866 | { |
867 | QJsonObject obj; |
868 | obj[nameKey] = QString::fromUtf8(v.name); |
869 | obj[typeKey] = typeStr(v.type); |
870 | obj[offsetKey] = v.offset; |
871 | obj[sizeKey] = v.size; |
872 | if (!v.arrayDims.isEmpty()) { |
873 | QJsonArray dimArr; |
874 | for (int dim : v.arrayDims) |
875 | dimArr.append(dim); |
876 | obj[arrayDimsKey] = dimArr; |
877 | } |
878 | if (v.arrayStride) |
879 | obj[arrayStrideKey] = v.arrayStride; |
880 | if (v.matrixStride) |
881 | obj[matrixStrideKey] = v.matrixStride; |
882 | if (v.matrixIsRowMajor) |
883 | obj[matrixRowMajorKey] = true; |
884 | if (!v.structMembers.isEmpty()) { |
885 | QJsonArray arr; |
886 | for (const QShaderDescription::BlockVariable &sv : v.structMembers) |
887 | arr.append(blockMemberObject(sv)); |
888 | obj[structMembersKey] = arr; |
889 | } |
890 | return obj; |
891 | } |
892 | |
893 | static void serializeBlockMemberVar(QDataStream *stream, const QShaderDescription::BlockVariable &v) |
894 | { |
895 | (*stream) << QString::fromUtf8(v.name); |
896 | (*stream) << int(v.type); |
897 | (*stream) << v.offset; |
898 | (*stream) << v.size; |
899 | (*stream) << int(v.arrayDims.count()); |
900 | for (int dim : v.arrayDims) |
901 | (*stream) << dim; |
902 | (*stream) << v.arrayStride; |
903 | (*stream) << v.matrixStride; |
904 | (*stream) << v.matrixIsRowMajor; |
905 | (*stream) << int(v.structMembers.count()); |
906 | for (const QShaderDescription::BlockVariable &sv : v.structMembers) |
907 | serializeBlockMemberVar(stream, sv); |
908 | } |
909 | |
910 | QJsonDocument QShaderDescriptionPrivate::makeDoc() |
911 | { |
912 | QJsonObject root; |
913 | |
914 | QJsonArray jinputs; |
915 | for (const QShaderDescription::InOutVariable &v : qAsConst(inVars)) |
916 | jinputs.append(inOutObject(v)); |
917 | if (!jinputs.isEmpty()) |
918 | root[inputsKey] = jinputs; |
919 | |
920 | QJsonArray joutputs; |
921 | for (const QShaderDescription::InOutVariable &v : qAsConst(outVars)) |
922 | joutputs.append(inOutObject(v)); |
923 | if (!joutputs.isEmpty()) |
924 | root[outputsKey] = joutputs; |
925 | |
926 | QJsonArray juniformBlocks; |
927 | for (const QShaderDescription::UniformBlock &b : uniformBlocks) { |
928 | QJsonObject juniformBlock; |
929 | juniformBlock[blockNameKey] = QString::fromUtf8(b.blockName); |
930 | juniformBlock[structNameKey] = QString::fromUtf8(b.structName); |
931 | juniformBlock[sizeKey] = b.size; |
932 | if (b.binding >= 0) |
933 | juniformBlock[bindingKey] = b.binding; |
934 | if (b.descriptorSet >= 0) |
935 | juniformBlock[setKey] = b.descriptorSet; |
936 | QJsonArray members; |
937 | for (const QShaderDescription::BlockVariable &v : b.members) |
938 | members.append(blockMemberObject(v)); |
939 | juniformBlock[membersKey] = members; |
940 | juniformBlocks.append(juniformBlock); |
941 | } |
942 | if (!juniformBlocks.isEmpty()) |
943 | root[uniformBlocksKey] = juniformBlocks; |
944 | |
945 | QJsonArray jpushConstantBlocks; |
946 | for (const QShaderDescription::PushConstantBlock &b : pushConstantBlocks) { |
947 | QJsonObject jpushConstantBlock; |
948 | jpushConstantBlock[nameKey] = QString::fromUtf8(b.name); |
949 | jpushConstantBlock[sizeKey] = b.size; |
950 | QJsonArray members; |
951 | for (const QShaderDescription::BlockVariable &v : b.members) |
952 | members.append(blockMemberObject(v)); |
953 | jpushConstantBlock[membersKey] = members; |
954 | jpushConstantBlocks.append(jpushConstantBlock); |
955 | } |
956 | if (!jpushConstantBlocks.isEmpty()) |
957 | root[pushConstantBlocksKey] = jpushConstantBlocks; |
958 | |
959 | QJsonArray jstorageBlocks; |
960 | for (const QShaderDescription::StorageBlock &b : storageBlocks) { |
961 | QJsonObject jstorageBlock; |
962 | jstorageBlock[blockNameKey] = QString::fromUtf8(b.blockName); |
963 | jstorageBlock[instanceNameKey] = QString::fromUtf8(b.instanceName); |
964 | jstorageBlock[knownSizeKey] = b.knownSize; |
965 | if (b.binding >= 0) |
966 | jstorageBlock[bindingKey] = b.binding; |
967 | if (b.descriptorSet >= 0) |
968 | jstorageBlock[setKey] = b.descriptorSet; |
969 | QJsonArray members; |
970 | for (const QShaderDescription::BlockVariable &v : b.members) |
971 | members.append(blockMemberObject(v)); |
972 | jstorageBlock[membersKey] = members; |
973 | jstorageBlocks.append(jstorageBlock); |
974 | } |
975 | if (!jstorageBlocks.isEmpty()) |
976 | root[storageBlocksKey] = jstorageBlocks; |
977 | |
978 | QJsonArray jcombinedSamplers; |
979 | for (const QShaderDescription::InOutVariable &v : qAsConst(combinedImageSamplers)) { |
980 | QJsonObject sampler; |
981 | sampler[nameKey] = QString::fromUtf8(v.name); |
982 | sampler[typeKey] = typeStr(v.type); |
983 | addDeco(&sampler, v); |
984 | jcombinedSamplers.append(sampler); |
985 | } |
986 | if (!jcombinedSamplers.isEmpty()) |
987 | root[combinedImageSamplersKey] = jcombinedSamplers; |
988 | |
989 | QJsonArray jstorageImages; |
990 | for (const QShaderDescription::InOutVariable &v : qAsConst(storageImages)) { |
991 | QJsonObject image; |
992 | image[nameKey] = QString::fromUtf8(v.name); |
993 | image[typeKey] = typeStr(v.type); |
994 | addDeco(&image, v); |
995 | jstorageImages.append(image); |
996 | } |
997 | if (!jstorageImages.isEmpty()) |
998 | root[storageImagesKey] = jstorageImages; |
999 | |
1000 | QJsonArray jlocalSize; |
1001 | for (int i = 0; i < 3; ++i) |
1002 | jlocalSize.append(QJsonValue(int(localSize[i]))); |
1003 | root[localSizeKey] = jlocalSize; |
1004 | |
1005 | return QJsonDocument(root); |
1006 | } |
1007 | |
1008 | void QShaderDescriptionPrivate::writeToStream(QDataStream *stream) |
1009 | { |
1010 | (*stream) << int(inVars.count()); |
1011 | for (const QShaderDescription::InOutVariable &v : qAsConst(inVars)) |
1012 | serializeInOutVar(stream, v); |
1013 | |
1014 | (*stream) << int(outVars.count()); |
1015 | for (const QShaderDescription::InOutVariable &v : qAsConst(outVars)) |
1016 | serializeInOutVar(stream, v); |
1017 | |
1018 | (*stream) << int(uniformBlocks.count()); |
1019 | for (const QShaderDescription::UniformBlock &b : uniformBlocks) { |
1020 | (*stream) << QString::fromUtf8(b.blockName); |
1021 | (*stream) << QString::fromUtf8(b.structName); |
1022 | (*stream) << b.size; |
1023 | (*stream) << b.binding; |
1024 | (*stream) << b.descriptorSet; |
1025 | (*stream) << int(b.members.count()); |
1026 | for (const QShaderDescription::BlockVariable &v : b.members) |
1027 | serializeBlockMemberVar(stream, v); |
1028 | } |
1029 | |
1030 | (*stream) << int(pushConstantBlocks.count()); |
1031 | for (const QShaderDescription::PushConstantBlock &b : pushConstantBlocks) { |
1032 | (*stream) << QString::fromUtf8(b.name); |
1033 | (*stream) << b.size; |
1034 | (*stream) << int(b.members.count()); |
1035 | for (const QShaderDescription::BlockVariable &v : b.members) |
1036 | serializeBlockMemberVar(stream, v); |
1037 | } |
1038 | |
1039 | (*stream) << int(storageBlocks.count()); |
1040 | for (const QShaderDescription::StorageBlock &b : storageBlocks) { |
1041 | (*stream) << QString::fromUtf8(b.blockName); |
1042 | (*stream) << QString::fromUtf8(b.instanceName); |
1043 | (*stream) << b.knownSize; |
1044 | (*stream) << b.binding; |
1045 | (*stream) << b.descriptorSet; |
1046 | (*stream) << int(b.members.count()); |
1047 | for (const QShaderDescription::BlockVariable &v : b.members) |
1048 | serializeBlockMemberVar(stream, v); |
1049 | } |
1050 | |
1051 | (*stream) << int(combinedImageSamplers.count()); |
1052 | for (const QShaderDescription::InOutVariable &v : qAsConst(combinedImageSamplers)) { |
1053 | (*stream) << QString::fromUtf8(v.name); |
1054 | (*stream) << int(v.type); |
1055 | serializeDecorations(stream, v); |
1056 | } |
1057 | |
1058 | (*stream) << int(storageImages.count()); |
1059 | for (const QShaderDescription::InOutVariable &v : qAsConst(storageImages)) { |
1060 | (*stream) << QString::fromUtf8(v.name); |
1061 | (*stream) << int(v.type); |
1062 | serializeDecorations(stream, v); |
1063 | } |
1064 | |
1065 | for (size_t i = 0; i < 3; ++i) |
1066 | (*stream) << localSize[i]; |
1067 | } |
1068 | |
1069 | static void deserializeDecorations(QDataStream *stream, int version, QShaderDescription::InOutVariable *v) |
1070 | { |
1071 | (*stream) >> v->location; |
1072 | (*stream) >> v->binding; |
1073 | (*stream) >> v->descriptorSet; |
1074 | int f; |
1075 | (*stream) >> f; |
1076 | v->imageFormat = QShaderDescription::ImageFormat(f); |
1077 | (*stream) >> f; |
1078 | v->imageFlags = QShaderDescription::ImageFlags(f); |
1079 | |
1080 | if (version > QShaderPrivate::QSB_VERSION_WITHOUT_VAR_ARRAYDIMS) { |
1081 | (*stream) >> f; |
1082 | v->arrayDims.resize(f); |
1083 | for (int i = 0; i < f; ++i) |
1084 | (*stream) >> v->arrayDims[i]; |
1085 | } |
1086 | } |
1087 | |
1088 | static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream, int version) |
1089 | { |
1090 | QShaderDescription::InOutVariable var; |
1091 | QString tmp; |
1092 | (*stream) >> tmp; |
1093 | var.name = tmp.toUtf8(); |
1094 | int t; |
1095 | (*stream) >> t; |
1096 | var.type = QShaderDescription::VariableType(t); |
1097 | deserializeDecorations(stream, version, &var); |
1098 | return var; |
1099 | } |
1100 | |
1101 | static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream, int version) |
1102 | { |
1103 | QShaderDescription::BlockVariable var; |
1104 | QString tmp; |
1105 | (*stream) >> tmp; |
1106 | var.name = tmp.toUtf8(); |
1107 | int t; |
1108 | (*stream) >> t; |
1109 | var.type = QShaderDescription::VariableType(t); |
1110 | (*stream) >> var.offset; |
1111 | (*stream) >> var.size; |
1112 | int count; |
1113 | (*stream) >> count; |
1114 | var.arrayDims.resize(count); |
1115 | for (int i = 0; i < count; ++i) |
1116 | (*stream) >> var.arrayDims[i]; |
1117 | (*stream) >> var.arrayStride; |
1118 | (*stream) >> var.matrixStride; |
1119 | (*stream) >> var.matrixIsRowMajor; |
1120 | (*stream) >> count; |
1121 | var.structMembers.resize(count); |
1122 | for (int i = 0; i < count; ++i) |
1123 | var.structMembers[i] = deserializeBlockMemberVar(stream, version); |
1124 | return var; |
1125 | } |
1126 | |
1127 | void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version) |
1128 | { |
1129 | Q_ASSERT(ref.loadRelaxed() == 1); // must be detached |
1130 | |
1131 | int count; |
1132 | (*stream) >> count; |
1133 | inVars.resize(count); |
1134 | for (int i = 0; i < count; ++i) |
1135 | inVars[i] = deserializeInOutVar(stream, version); |
1136 | |
1137 | (*stream) >> count; |
1138 | outVars.resize(count); |
1139 | for (int i = 0; i < count; ++i) |
1140 | outVars[i] = deserializeInOutVar(stream, version); |
1141 | |
1142 | (*stream) >> count; |
1143 | uniformBlocks.resize(count); |
1144 | for (int i = 0; i < count; ++i) { |
1145 | QString tmp; |
1146 | (*stream) >> tmp; |
1147 | uniformBlocks[i].blockName = tmp.toUtf8(); |
1148 | (*stream) >> tmp; |
1149 | uniformBlocks[i].structName = tmp.toUtf8(); |
1150 | (*stream) >> uniformBlocks[i].size; |
1151 | (*stream) >> uniformBlocks[i].binding; |
1152 | (*stream) >> uniformBlocks[i].descriptorSet; |
1153 | int memberCount; |
1154 | (*stream) >> memberCount; |
1155 | uniformBlocks[i].members.resize(memberCount); |
1156 | for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx) |
1157 | uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version); |
1158 | } |
1159 | |
1160 | (*stream) >> count; |
1161 | pushConstantBlocks.resize(count); |
1162 | for (int i = 0; i < count; ++i) { |
1163 | QString tmp; |
1164 | (*stream) >> tmp; |
1165 | pushConstantBlocks[i].name = tmp.toUtf8(); |
1166 | (*stream) >> pushConstantBlocks[i].size; |
1167 | int memberCount; |
1168 | (*stream) >> memberCount; |
1169 | pushConstantBlocks[i].members.resize(memberCount); |
1170 | for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx) |
1171 | pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version); |
1172 | } |
1173 | |
1174 | (*stream) >> count; |
1175 | storageBlocks.resize(count); |
1176 | for (int i = 0; i < count; ++i) { |
1177 | QString tmp; |
1178 | (*stream) >> tmp; |
1179 | storageBlocks[i].blockName = tmp.toUtf8(); |
1180 | (*stream) >> tmp; |
1181 | storageBlocks[i].instanceName = tmp.toUtf8(); |
1182 | (*stream) >> storageBlocks[i].knownSize; |
1183 | (*stream) >> storageBlocks[i].binding; |
1184 | (*stream) >> storageBlocks[i].descriptorSet; |
1185 | int memberCount; |
1186 | (*stream) >> memberCount; |
1187 | storageBlocks[i].members.resize(memberCount); |
1188 | for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx) |
1189 | storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version); |
1190 | } |
1191 | |
1192 | (*stream) >> count; |
1193 | combinedImageSamplers.resize(count); |
1194 | for (int i = 0; i < count; ++i) { |
1195 | QString tmp; |
1196 | (*stream) >> tmp; |
1197 | combinedImageSamplers[i].name = tmp.toUtf8(); |
1198 | int t; |
1199 | (*stream) >> t; |
1200 | combinedImageSamplers[i].type = QShaderDescription::VariableType(t); |
1201 | deserializeDecorations(stream, version, &combinedImageSamplers[i]); |
1202 | } |
1203 | |
1204 | (*stream) >> count; |
1205 | storageImages.resize(count); |
1206 | for (int i = 0; i < count; ++i) { |
1207 | QString tmp; |
1208 | (*stream) >> tmp; |
1209 | storageImages[i].name = tmp.toUtf8(); |
1210 | int t; |
1211 | (*stream) >> t; |
1212 | storageImages[i].type = QShaderDescription::VariableType(t); |
1213 | deserializeDecorations(stream, version, &storageImages[i]); |
1214 | } |
1215 | |
1216 | for (size_t i = 0; i < 3; ++i) |
1217 | (*stream) >> localSize[i]; |
1218 | } |
1219 | |
1220 | /*! |
1221 | Returns \c true if the two QShaderDescription objects \a lhs and \a rhs are |
1222 | equal. |
1223 | |
1224 | \relates QShaderDescription |
1225 | */ |
1226 | bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept |
1227 | { |
1228 | if (lhs.d == rhs.d) |
1229 | return true; |
1230 | |
1231 | return lhs.d->inVars == rhs.d->inVars |
1232 | && lhs.d->outVars == rhs.d->outVars |
1233 | && lhs.d->uniformBlocks == rhs.d->uniformBlocks |
1234 | && lhs.d->pushConstantBlocks == rhs.d->pushConstantBlocks |
1235 | && lhs.d->storageBlocks == rhs.d->storageBlocks |
1236 | && lhs.d->combinedImageSamplers == rhs.d->combinedImageSamplers |
1237 | && lhs.d->storageImages == rhs.d->storageImages |
1238 | && lhs.d->localSize == rhs.d->localSize; |
1239 | } |
1240 | |
1241 | /*! |
1242 | Returns \c true if the two InOutVariable objects \a lhs and \a rhs are |
1243 | equal. |
1244 | |
1245 | \relates QShaderDescription::InOutVariable |
1246 | */ |
1247 | bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescription::InOutVariable &rhs) noexcept |
1248 | { |
1249 | return lhs.name == rhs.name |
1250 | && lhs.type == rhs.type |
1251 | && lhs.location == rhs.location |
1252 | && lhs.binding == rhs.binding |
1253 | && lhs.descriptorSet == rhs.descriptorSet |
1254 | && lhs.imageFormat == rhs.imageFormat |
1255 | && lhs.imageFlags == rhs.imageFlags |
1256 | && lhs.arrayDims == rhs.arrayDims; |
1257 | } |
1258 | |
1259 | /*! |
1260 | Returns \c true if the two BlockVariable objects \a lhs and \a rhs are |
1261 | equal. |
1262 | |
1263 | \relates QShaderDescription::BlockVariable |
1264 | */ |
1265 | bool operator==(const QShaderDescription::BlockVariable &lhs, const QShaderDescription::BlockVariable &rhs) noexcept |
1266 | { |
1267 | return lhs.name == rhs.name |
1268 | && lhs.type == rhs.type |
1269 | && lhs.offset == rhs.offset |
1270 | && lhs.size == rhs.size |
1271 | && lhs.arrayDims == rhs.arrayDims |
1272 | && lhs.arrayStride == rhs.arrayStride |
1273 | && lhs.matrixStride == rhs.matrixStride |
1274 | && lhs.matrixIsRowMajor == rhs.matrixIsRowMajor |
1275 | && lhs.structMembers == rhs.structMembers; |
1276 | } |
1277 | |
1278 | /*! |
1279 | Returns \c true if the two UniformBlock objects \a lhs and \a rhs are |
1280 | equal. |
1281 | |
1282 | \relates QShaderDescription::UniformBlock |
1283 | */ |
1284 | bool operator==(const QShaderDescription::UniformBlock &lhs, const QShaderDescription::UniformBlock &rhs) noexcept |
1285 | { |
1286 | return lhs.blockName == rhs.blockName |
1287 | && lhs.structName == rhs.structName |
1288 | && lhs.size == rhs.size |
1289 | && lhs.binding == rhs.binding |
1290 | && lhs.descriptorSet == rhs.descriptorSet |
1291 | && lhs.members == rhs.members; |
1292 | } |
1293 | |
1294 | /*! |
1295 | Returns \c true if the two PushConstantBlock objects \a lhs and \a rhs are |
1296 | equal. |
1297 | |
1298 | \relates QShaderDescription::PushConstantBlock |
1299 | */ |
1300 | bool operator==(const QShaderDescription::PushConstantBlock &lhs, const QShaderDescription::PushConstantBlock &rhs) noexcept |
1301 | { |
1302 | return lhs.name == rhs.name |
1303 | && lhs.size == rhs.size |
1304 | && lhs.members == rhs.members; |
1305 | } |
1306 | |
1307 | /*! |
1308 | Returns \c true if the two StorageBlock objects \a lhs and \a rhs are |
1309 | equal. |
1310 | |
1311 | \relates QShaderDescription::StorageBlock |
1312 | */ |
1313 | bool operator==(const QShaderDescription::StorageBlock &lhs, const QShaderDescription::StorageBlock &rhs) noexcept |
1314 | { |
1315 | return lhs.blockName == rhs.blockName |
1316 | && lhs.instanceName == rhs.instanceName |
1317 | && lhs.knownSize == rhs.knownSize |
1318 | && lhs.binding == rhs.binding |
1319 | && lhs.descriptorSet == rhs.descriptorSet |
1320 | && lhs.members == rhs.members; |
1321 | } |
1322 | |
1323 | QT_END_NAMESPACE |
1324 | |