1 | // Copyright (C) 2023 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QRHIGLES2_P_H |
5 | #define QRHIGLES2_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include "qrhi_p.h" |
19 | #include <rhi/qshaderdescription.h> |
20 | #include <qopengl.h> |
21 | #include <QByteArray> |
22 | #include <QWindow> |
23 | #include <QPointer> |
24 | #include <QtCore/private/qduplicatetracker_p.h> |
25 | #include <optional> |
26 | |
27 | QT_BEGIN_NAMESPACE |
28 | |
29 | class QOpenGLExtensions; |
30 | class QRhiGles2; |
31 | |
32 | struct QGles2Buffer : public QRhiBuffer |
33 | { |
34 | QGles2Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size); |
35 | ~QGles2Buffer(); |
36 | void destroy() override; |
37 | bool create() override; |
38 | QRhiBuffer::NativeBuffer nativeBuffer() override; |
39 | char *beginFullDynamicBufferUpdateForCurrentFrame() override; |
40 | void endFullDynamicBufferUpdateForCurrentFrame() override; |
41 | void fullDynamicBufferUpdateForCurrentFrame(const void *data, quint32 size) override; |
42 | |
43 | quint32 nonZeroSize = 0; |
44 | GLuint buffer = 0; |
45 | GLenum targetForDataOps; |
46 | QByteArray data; |
47 | enum Access { |
48 | AccessNone, |
49 | AccessVertex, |
50 | AccessIndex, |
51 | AccessUniform, |
52 | AccessStorageRead, |
53 | AccessStorageWrite, |
54 | AccessStorageReadWrite, |
55 | AccessUpdate |
56 | }; |
57 | struct UsageState { |
58 | Access access; |
59 | }; |
60 | UsageState usageState; |
61 | friend class QRhiGles2; |
62 | }; |
63 | |
64 | struct QGles2RenderBuffer : public QRhiRenderBuffer |
65 | { |
66 | QGles2RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize, |
67 | int sampleCount, QRhiRenderBuffer::Flags flags, |
68 | QRhiTexture::Format backingFormatHint); |
69 | ~QGles2RenderBuffer(); |
70 | void destroy() override; |
71 | bool create() override; |
72 | bool createFrom(NativeRenderBuffer src) override; |
73 | QRhiTexture::Format backingFormat() const override; |
74 | |
75 | GLuint renderbuffer = 0; |
76 | GLuint stencilRenderbuffer = 0; // when packed depth-stencil not supported |
77 | int samples; |
78 | bool owns = true; |
79 | uint generation = 0; |
80 | friend class QRhiGles2; |
81 | }; |
82 | |
83 | struct QGles2SamplerData |
84 | { |
85 | GLenum glminfilter = 0; |
86 | GLenum glmagfilter = 0; |
87 | GLenum glwraps = 0; |
88 | GLenum glwrapt = 0; |
89 | GLenum glwrapr = 0; |
90 | GLenum gltexcomparefunc = 0; |
91 | }; |
92 | |
93 | inline bool operator==(const QGles2SamplerData &a, const QGles2SamplerData &b) |
94 | { |
95 | return a.glminfilter == b.glminfilter |
96 | && a.glmagfilter == b.glmagfilter |
97 | && a.glwraps == b.glwraps |
98 | && a.glwrapt == b.glwrapt |
99 | && a.glwrapr == b.glwrapr |
100 | && a.gltexcomparefunc == b.gltexcomparefunc; |
101 | } |
102 | |
103 | inline bool operator!=(const QGles2SamplerData &a, const QGles2SamplerData &b) |
104 | { |
105 | return !(a == b); |
106 | } |
107 | |
108 | struct QGles2Texture : public QRhiTexture |
109 | { |
110 | QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth, |
111 | int arraySize, int sampleCount, Flags flags); |
112 | ~QGles2Texture(); |
113 | void destroy() override; |
114 | bool create() override; |
115 | bool createFrom(NativeTexture src) override; |
116 | NativeTexture nativeTexture() override; |
117 | |
118 | bool prepareCreate(QSize *adjustedSize = nullptr); |
119 | |
120 | GLuint texture = 0; |
121 | bool owns = true; |
122 | GLenum target; |
123 | GLenum glintformat; |
124 | GLenum glsizedintformat; |
125 | GLenum glformat; |
126 | GLenum gltype; |
127 | QGles2SamplerData samplerState; |
128 | bool specified = false; |
129 | bool zeroInitialized = false; |
130 | int mipLevelCount = 0; |
131 | |
132 | enum Access { |
133 | AccessNone, |
134 | AccessSample, |
135 | AccessFramebuffer, |
136 | AccessStorageRead, |
137 | AccessStorageWrite, |
138 | AccessStorageReadWrite, |
139 | AccessUpdate, |
140 | AccessRead |
141 | }; |
142 | struct UsageState { |
143 | Access access; |
144 | }; |
145 | UsageState usageState; |
146 | |
147 | uint generation = 0; |
148 | friend class QRhiGles2; |
149 | }; |
150 | |
151 | struct QGles2Sampler : public QRhiSampler |
152 | { |
153 | QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, |
154 | AddressMode u, AddressMode v, AddressMode w); |
155 | ~QGles2Sampler(); |
156 | void destroy() override; |
157 | bool create() override; |
158 | |
159 | QGles2SamplerData d; |
160 | uint generation = 0; |
161 | friend class QRhiGles2; |
162 | }; |
163 | |
164 | struct QGles2RenderPassDescriptor : public QRhiRenderPassDescriptor |
165 | { |
166 | QGles2RenderPassDescriptor(QRhiImplementation *rhi); |
167 | ~QGles2RenderPassDescriptor(); |
168 | void destroy() override; |
169 | bool isCompatible(const QRhiRenderPassDescriptor *other) const override; |
170 | QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override; |
171 | QVector<quint32> serializedFormat() const override; |
172 | }; |
173 | |
174 | struct QGles2RenderTargetData |
175 | { |
176 | QGles2RenderTargetData(QRhiImplementation *) { } |
177 | |
178 | bool isValid() const { return rp != nullptr; } |
179 | |
180 | QGles2RenderPassDescriptor *rp = nullptr; |
181 | QSize pixelSize; |
182 | float dpr = 1; |
183 | int sampleCount = 1; |
184 | int colorAttCount = 0; |
185 | int dsAttCount = 0; |
186 | bool srgbUpdateAndBlend = false; |
187 | QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList; |
188 | std::optional<QRhiSwapChain::StereoTargetBuffer> stereoTarget; |
189 | }; |
190 | |
191 | struct QGles2SwapChainRenderTarget : public QRhiSwapChainRenderTarget |
192 | { |
193 | QGles2SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain); |
194 | ~QGles2SwapChainRenderTarget(); |
195 | void destroy() override; |
196 | |
197 | QSize pixelSize() const override; |
198 | float devicePixelRatio() const override; |
199 | int sampleCount() const override; |
200 | |
201 | QGles2RenderTargetData d; |
202 | }; |
203 | |
204 | struct QGles2TextureRenderTarget : public QRhiTextureRenderTarget |
205 | { |
206 | QGles2TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags); |
207 | ~QGles2TextureRenderTarget(); |
208 | void destroy() override; |
209 | |
210 | QSize pixelSize() const override; |
211 | float devicePixelRatio() const override; |
212 | int sampleCount() const override; |
213 | |
214 | QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; |
215 | bool create() override; |
216 | |
217 | QGles2RenderTargetData d; |
218 | GLuint framebuffer = 0; |
219 | GLuint nonMsaaThrowawayDepthTexture = 0; |
220 | friend class QRhiGles2; |
221 | }; |
222 | |
223 | struct QGles2ShaderResourceBindings : public QRhiShaderResourceBindings |
224 | { |
225 | QGles2ShaderResourceBindings(QRhiImplementation *rhi); |
226 | ~QGles2ShaderResourceBindings(); |
227 | void destroy() override; |
228 | bool create() override; |
229 | void updateResources(UpdateFlags flags) override; |
230 | |
231 | bool hasDynamicOffset = false; |
232 | uint generation = 0; |
233 | friend class QRhiGles2; |
234 | }; |
235 | |
236 | struct QGles2UniformDescription |
237 | { |
238 | QShaderDescription::VariableType type; |
239 | int glslLocation; |
240 | int binding; |
241 | quint32 offset; |
242 | quint32 size; |
243 | int arrayDim; |
244 | }; |
245 | |
246 | Q_DECLARE_TYPEINFO(QGles2UniformDescription, Q_RELOCATABLE_TYPE); |
247 | |
248 | struct QGles2SamplerDescription |
249 | { |
250 | int glslLocation; |
251 | int combinedBinding; |
252 | int tbinding; |
253 | int sbinding; |
254 | }; |
255 | |
256 | Q_DECLARE_TYPEINFO(QGles2SamplerDescription, Q_RELOCATABLE_TYPE); |
257 | |
258 | using QGles2UniformDescriptionVector = QVarLengthArray<QGles2UniformDescription, 8>; |
259 | using QGles2SamplerDescriptionVector = QVarLengthArray<QGles2SamplerDescription, 4>; |
260 | |
261 | struct QGles2UniformState |
262 | { |
263 | static constexpr int MAX_TRACKED_LOCATION = 1023; |
264 | int componentCount; |
265 | float v[4]; |
266 | }; |
267 | |
268 | struct QGles2GraphicsPipeline : public QRhiGraphicsPipeline |
269 | { |
270 | QGles2GraphicsPipeline(QRhiImplementation *rhi); |
271 | ~QGles2GraphicsPipeline(); |
272 | void destroy() override; |
273 | bool create() override; |
274 | |
275 | GLuint program = 0; |
276 | GLenum drawMode = GL_TRIANGLES; |
277 | QGles2UniformDescriptionVector uniforms; |
278 | QGles2SamplerDescriptionVector samplers; |
279 | QGles2UniformState uniformState[QGles2UniformState::MAX_TRACKED_LOCATION + 1]; |
280 | QRhiShaderResourceBindings *currentSrb = nullptr; |
281 | uint currentSrbGeneration = 0; |
282 | uint generation = 0; |
283 | friend class QRhiGles2; |
284 | }; |
285 | |
286 | struct QGles2ComputePipeline : public QRhiComputePipeline |
287 | { |
288 | QGles2ComputePipeline(QRhiImplementation *rhi); |
289 | ~QGles2ComputePipeline(); |
290 | void destroy() override; |
291 | bool create() override; |
292 | |
293 | GLuint program = 0; |
294 | QGles2UniformDescriptionVector uniforms; |
295 | QGles2SamplerDescriptionVector samplers; |
296 | QGles2UniformState uniformState[QGles2UniformState::MAX_TRACKED_LOCATION + 1]; |
297 | QRhiShaderResourceBindings *currentSrb = nullptr; |
298 | uint currentSrbGeneration = 0; |
299 | uint generation = 0; |
300 | friend class QRhiGles2; |
301 | }; |
302 | |
303 | struct QGles2CommandBuffer : public QRhiCommandBuffer |
304 | { |
305 | QGles2CommandBuffer(QRhiImplementation *rhi); |
306 | ~QGles2CommandBuffer(); |
307 | void destroy() override; |
308 | |
309 | // keep at a reasonably low value otherwise sizeof Command explodes |
310 | static const int MAX_DYNAMIC_OFFSET_COUNT = 8; |
311 | |
312 | struct Command { |
313 | enum Cmd { |
314 | BeginFrame, |
315 | EndFrame, |
316 | ResetFrame, |
317 | Viewport, |
318 | Scissor, |
319 | BlendConstants, |
320 | StencilRef, |
321 | BindVertexBuffer, |
322 | BindIndexBuffer, |
323 | Draw, |
324 | DrawIndexed, |
325 | BindGraphicsPipeline, |
326 | BindShaderResources, |
327 | BindFramebuffer, |
328 | Clear, |
329 | BufferSubData, |
330 | GetBufferSubData, |
331 | CopyTex, |
332 | ReadPixels, |
333 | SubImage, |
334 | CompressedImage, |
335 | CompressedSubImage, |
336 | BlitFromRenderbuffer, |
337 | BlitFromTexture, |
338 | GenMip, |
339 | BindComputePipeline, |
340 | Dispatch, |
341 | BarriersForPass, |
342 | Barrier, |
343 | InvalidateFramebuffer |
344 | }; |
345 | Cmd cmd; |
346 | |
347 | // QRhi*/QGles2* references should be kept at minimum (so no |
348 | // QRhiTexture/Buffer/etc. pointers). |
349 | union Args { |
350 | struct { |
351 | GLuint timestampQuery; |
352 | } beginFrame; |
353 | struct { |
354 | GLuint timestampQuery; |
355 | } endFrame; |
356 | struct { |
357 | float x, y, w, h; |
358 | float d0, d1; |
359 | } viewport; |
360 | struct { |
361 | int x, y, w, h; |
362 | } scissor; |
363 | struct { |
364 | float r, g, b, a; |
365 | } blendConstants; |
366 | struct { |
367 | quint32 ref; |
368 | QRhiGraphicsPipeline *ps; |
369 | } stencilRef; |
370 | struct { |
371 | QRhiGraphicsPipeline *ps; |
372 | GLuint buffer; |
373 | quint32 offset; |
374 | int binding; |
375 | } bindVertexBuffer; |
376 | struct { |
377 | GLuint buffer; |
378 | quint32 offset; |
379 | GLenum type; |
380 | } bindIndexBuffer; |
381 | struct { |
382 | QRhiGraphicsPipeline *ps; |
383 | quint32 vertexCount; |
384 | quint32 firstVertex; |
385 | quint32 instanceCount; |
386 | quint32 baseInstance; |
387 | } draw; |
388 | struct { |
389 | QRhiGraphicsPipeline *ps; |
390 | quint32 indexCount; |
391 | quint32 firstIndex; |
392 | quint32 instanceCount; |
393 | quint32 baseInstance; |
394 | qint32 baseVertex; |
395 | } drawIndexed; |
396 | struct { |
397 | QRhiGraphicsPipeline *ps; |
398 | } bindGraphicsPipeline; |
399 | struct { |
400 | QRhiGraphicsPipeline *maybeGraphicsPs; |
401 | QRhiComputePipeline *maybeComputePs; |
402 | QRhiShaderResourceBindings *srb; |
403 | int dynamicOffsetCount; |
404 | uint dynamicOffsetPairs[MAX_DYNAMIC_OFFSET_COUNT * 2]; // binding, offset |
405 | } bindShaderResources; |
406 | struct { |
407 | GLbitfield mask; |
408 | float c[4]; |
409 | float d; |
410 | quint32 s; |
411 | } clear; |
412 | struct { |
413 | GLuint fbo; |
414 | bool srgb; |
415 | int colorAttCount; |
416 | bool stereo; |
417 | QRhiSwapChain::StereoTargetBuffer stereoTarget; |
418 | } bindFramebuffer; |
419 | struct { |
420 | GLenum target; |
421 | GLuint buffer; |
422 | int offset; |
423 | int size; |
424 | const void *data; // must come from retainData() |
425 | } bufferSubData; |
426 | struct { |
427 | QRhiReadbackResult *result; |
428 | GLenum target; |
429 | GLuint buffer; |
430 | int offset; |
431 | int size; |
432 | } getBufferSubData; |
433 | struct { |
434 | GLenum srcTarget; |
435 | GLenum srcFaceTarget; |
436 | GLuint srcTexture; |
437 | int srcLevel; |
438 | int srcX; |
439 | int srcY; |
440 | int srcZ; |
441 | GLenum dstTarget; |
442 | GLuint dstTexture; |
443 | GLenum dstFaceTarget; |
444 | int dstLevel; |
445 | int dstX; |
446 | int dstY; |
447 | int dstZ; |
448 | int w; |
449 | int h; |
450 | } copyTex; |
451 | struct { |
452 | QRhiReadbackResult *result; |
453 | GLuint texture; |
454 | int w; |
455 | int h; |
456 | QRhiTexture::Format format; |
457 | GLenum readTarget; |
458 | int level; |
459 | int slice3D; |
460 | } readPixels; |
461 | struct { |
462 | GLenum target; |
463 | GLuint texture; |
464 | GLenum faceTarget; |
465 | int level; |
466 | int dx; |
467 | int dy; |
468 | int dz; |
469 | int w; |
470 | int h; |
471 | GLenum glformat; |
472 | GLenum gltype; |
473 | int rowStartAlign; |
474 | int rowLength; |
475 | const void *data; // must come from retainImage() |
476 | } subImage; |
477 | struct { |
478 | GLenum target; |
479 | GLuint texture; |
480 | GLenum faceTarget; |
481 | int level; |
482 | GLenum glintformat; |
483 | int w; |
484 | int h; |
485 | int depth; |
486 | int size; |
487 | const void *data; // must come from retainData() |
488 | } compressedImage; |
489 | struct { |
490 | GLenum target; |
491 | GLuint texture; |
492 | GLenum faceTarget; |
493 | int level; |
494 | int dx; |
495 | int dy; |
496 | int dz; |
497 | int w; |
498 | int h; |
499 | GLenum glintformat; |
500 | int size; |
501 | const void *data; // must come from retainData() |
502 | } compressedSubImage; |
503 | struct { |
504 | GLuint renderbuffer; |
505 | int w; |
506 | int h; |
507 | GLenum target; |
508 | GLuint dstTexture; |
509 | int dstLevel; |
510 | int dstLayer; |
511 | bool isDepthStencil; |
512 | } blitFromRenderbuffer; |
513 | struct { |
514 | GLenum srcTarget; |
515 | GLuint srcTexture; |
516 | int srcLevel; |
517 | int srcLayer; |
518 | int w; |
519 | int h; |
520 | GLenum dstTarget; |
521 | GLuint dstTexture; |
522 | int dstLevel; |
523 | int dstLayer; |
524 | bool isDepthStencil; |
525 | } blitFromTexture; |
526 | struct { |
527 | GLenum target; |
528 | GLuint texture; |
529 | } genMip; |
530 | struct { |
531 | QRhiComputePipeline *ps; |
532 | } bindComputePipeline; |
533 | struct { |
534 | GLuint x; |
535 | GLuint y; |
536 | GLuint z; |
537 | } dispatch; |
538 | struct { |
539 | int trackerIndex; |
540 | } barriersForPass; |
541 | struct { |
542 | GLbitfield barriers; |
543 | } barrier; |
544 | struct { |
545 | int attCount; |
546 | GLenum att[3]; |
547 | } invalidateFramebuffer; |
548 | } args; |
549 | }; |
550 | |
551 | enum PassType { |
552 | NoPass, |
553 | RenderPass, |
554 | ComputePass |
555 | }; |
556 | |
557 | QRhiBackendCommandList<Command> commands; |
558 | QVarLengthArray<QRhiPassResourceTracker, 8> passResTrackers; |
559 | int currentPassResTrackerIndex; |
560 | |
561 | PassType recordingPass; |
562 | bool passNeedsResourceTracking; |
563 | double lastGpuTime = 0; |
564 | QRhiRenderTarget *currentTarget; |
565 | QRhiGraphicsPipeline *currentGraphicsPipeline; |
566 | QRhiComputePipeline *currentComputePipeline; |
567 | uint currentPipelineGeneration; |
568 | QRhiShaderResourceBindings *currentGraphicsSrb; |
569 | QRhiShaderResourceBindings *currentComputeSrb; |
570 | uint currentSrbGeneration; |
571 | |
572 | struct GraphicsPassState { |
573 | bool valid = false; |
574 | bool scissor; |
575 | bool cullFace; |
576 | GLenum cullMode; |
577 | GLenum frontFace; |
578 | bool blendEnabled; |
579 | struct ColorMask { bool r, g, b, a; } colorMask; |
580 | struct Blend { |
581 | GLenum srcColor; |
582 | GLenum dstColor; |
583 | GLenum srcAlpha; |
584 | GLenum dstAlpha; |
585 | GLenum opColor; |
586 | GLenum opAlpha; |
587 | } blend; |
588 | bool depthTest; |
589 | bool depthWrite; |
590 | GLenum depthFunc; |
591 | bool stencilTest; |
592 | GLuint stencilReadMask; |
593 | GLuint stencilWriteMask; |
594 | struct StencilFace { |
595 | GLenum func; |
596 | GLenum failOp; |
597 | GLenum zfailOp; |
598 | GLenum zpassOp; |
599 | } stencil[2]; // front, back |
600 | bool polyOffsetFill; |
601 | float polyOffsetFactor; |
602 | float polyOffsetUnits; |
603 | float lineWidth; |
604 | int cpCount; |
605 | GLenum polygonMode; |
606 | void reset() { valid = false; } |
607 | struct { |
608 | // not part of QRhiGraphicsPipeline but used by setGraphicsPipeline() |
609 | GLint stencilRef = 0; |
610 | } dynamic; |
611 | } graphicsPassState; |
612 | |
613 | struct ComputePassState { |
614 | enum Access { |
615 | Read = 0x01, |
616 | Write = 0x02 |
617 | }; |
618 | QHash<QRhiResource *, QPair<int, bool> > writtenResources; |
619 | void reset() { |
620 | writtenResources.clear(); |
621 | } |
622 | } computePassState; |
623 | |
624 | struct TextureUnitState { |
625 | void *ps; |
626 | uint psGeneration; |
627 | uint texture; |
628 | } textureUnitState[16]; |
629 | |
630 | QVarLengthArray<QByteArray, 4> dataRetainPool; |
631 | QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool; |
632 | QVarLengthArray<QImage, 4> imageRetainPool; |
633 | |
634 | // relies heavily on implicit sharing (no copies of the actual data will be made) |
635 | const void *retainData(const QByteArray &data) { |
636 | dataRetainPool.append(t: data); |
637 | return dataRetainPool.last().constData(); |
638 | } |
639 | const uchar *retainBufferData(const QRhiBufferData &data) { |
640 | bufferDataRetainPool.append(t: data); |
641 | return reinterpret_cast<const uchar *>(bufferDataRetainPool.last().constData()); |
642 | } |
643 | const void *retainImage(const QImage &image) { |
644 | imageRetainPool.append(t: image); |
645 | return imageRetainPool.last().constBits(); |
646 | } |
647 | void resetCommands() { |
648 | commands.reset(); |
649 | dataRetainPool.clear(); |
650 | bufferDataRetainPool.clear(); |
651 | imageRetainPool.clear(); |
652 | |
653 | passResTrackers.clear(); |
654 | currentPassResTrackerIndex = -1; |
655 | } |
656 | void resetState() { |
657 | recordingPass = NoPass; |
658 | passNeedsResourceTracking = true; |
659 | // do not zero lastGpuTime |
660 | currentTarget = nullptr; |
661 | resetCommands(); |
662 | resetCachedState(); |
663 | } |
664 | void resetCachedState() { |
665 | currentGraphicsPipeline = nullptr; |
666 | currentComputePipeline = nullptr; |
667 | currentPipelineGeneration = 0; |
668 | currentGraphicsSrb = nullptr; |
669 | currentComputeSrb = nullptr; |
670 | currentSrbGeneration = 0; |
671 | graphicsPassState.reset(); |
672 | computePassState.reset(); |
673 | memset(s: textureUnitState, c: 0, n: sizeof(textureUnitState)); |
674 | } |
675 | }; |
676 | |
677 | inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a, |
678 | const QGles2CommandBuffer::GraphicsPassState::StencilFace &b) |
679 | { |
680 | return a.func == b.func |
681 | && a.failOp == b.failOp |
682 | && a.zfailOp == b.zfailOp |
683 | && a.zpassOp == b.zpassOp; |
684 | } |
685 | |
686 | inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a, |
687 | const QGles2CommandBuffer::GraphicsPassState::StencilFace &b) |
688 | { |
689 | return !(a == b); |
690 | } |
691 | |
692 | inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a, |
693 | const QGles2CommandBuffer::GraphicsPassState::ColorMask &b) |
694 | { |
695 | return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a; |
696 | } |
697 | |
698 | inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a, |
699 | const QGles2CommandBuffer::GraphicsPassState::ColorMask &b) |
700 | { |
701 | return !(a == b); |
702 | } |
703 | |
704 | inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::Blend &a, |
705 | const QGles2CommandBuffer::GraphicsPassState::Blend &b) |
706 | { |
707 | return a.srcColor == b.srcColor |
708 | && a.dstColor == b.dstColor |
709 | && a.srcAlpha == b.srcAlpha |
710 | && a.dstAlpha == b.dstAlpha |
711 | && a.opColor == b.opColor |
712 | && a.opAlpha == b.opAlpha; |
713 | } |
714 | |
715 | inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::Blend &a, |
716 | const QGles2CommandBuffer::GraphicsPassState::Blend &b) |
717 | { |
718 | return !(a == b); |
719 | } |
720 | |
721 | struct QGles2SwapChainTimestamps |
722 | { |
723 | static const int TIMESTAMP_PAIRS = 2; |
724 | |
725 | bool active[TIMESTAMP_PAIRS] = {}; |
726 | GLuint query[TIMESTAMP_PAIRS * 2] = {}; |
727 | |
728 | void prepare(QRhiGles2 *rhiD); |
729 | void destroy(QRhiGles2 *rhiD); |
730 | bool tryQueryTimestamps(int pairIndex, QRhiGles2 *rhiD, double *elapsedSec); |
731 | }; |
732 | |
733 | struct QGles2SwapChain : public QRhiSwapChain |
734 | { |
735 | QGles2SwapChain(QRhiImplementation *rhi); |
736 | ~QGles2SwapChain(); |
737 | void destroy() override; |
738 | |
739 | QRhiCommandBuffer *currentFrameCommandBuffer() override; |
740 | QRhiRenderTarget *currentFrameRenderTarget() override; |
741 | QRhiRenderTarget *currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override; |
742 | |
743 | QSize surfacePixelSize() override; |
744 | bool isFormatSupported(Format f) override; |
745 | |
746 | QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; |
747 | bool createOrResize() override; |
748 | |
749 | void initSwapChainRenderTarget(QGles2SwapChainRenderTarget *rt); |
750 | |
751 | QSurface *surface = nullptr; |
752 | QSize pixelSize; |
753 | QGles2SwapChainRenderTarget rt; |
754 | QGles2SwapChainRenderTarget rtLeft; |
755 | QGles2SwapChainRenderTarget rtRight; |
756 | QGles2CommandBuffer cb; |
757 | int frameCount = 0; |
758 | QGles2SwapChainTimestamps timestamps; |
759 | int currentTimestampPairIndex = 0; |
760 | }; |
761 | |
762 | class QRhiGles2 : public QRhiImplementation |
763 | { |
764 | public: |
765 | QRhiGles2(QRhiGles2InitParams *params, QRhiGles2NativeHandles *importDevice = nullptr); |
766 | |
767 | bool create(QRhi::Flags flags) override; |
768 | void destroy() override; |
769 | |
770 | QRhiGraphicsPipeline *createGraphicsPipeline() override; |
771 | QRhiComputePipeline *createComputePipeline() override; |
772 | QRhiShaderResourceBindings *createShaderResourceBindings() override; |
773 | QRhiBuffer *createBuffer(QRhiBuffer::Type type, |
774 | QRhiBuffer::UsageFlags usage, |
775 | quint32 size) override; |
776 | QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type, |
777 | const QSize &pixelSize, |
778 | int sampleCount, |
779 | QRhiRenderBuffer::Flags flags, |
780 | QRhiTexture::Format backingFormatHint) override; |
781 | QRhiTexture *createTexture(QRhiTexture::Format format, |
782 | const QSize &pixelSize, |
783 | int depth, |
784 | int arraySize, |
785 | int sampleCount, |
786 | QRhiTexture::Flags flags) override; |
787 | QRhiSampler *createSampler(QRhiSampler::Filter magFilter, |
788 | QRhiSampler::Filter minFilter, |
789 | QRhiSampler::Filter mipmapMode, |
790 | QRhiSampler:: AddressMode u, |
791 | QRhiSampler::AddressMode v, |
792 | QRhiSampler::AddressMode w) override; |
793 | |
794 | QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, |
795 | QRhiTextureRenderTarget::Flags flags) override; |
796 | |
797 | QRhiSwapChain *createSwapChain() override; |
798 | QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override; |
799 | QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override; |
800 | QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override; |
801 | QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override; |
802 | QRhi::FrameOpResult finish() override; |
803 | |
804 | void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; |
805 | |
806 | void beginPass(QRhiCommandBuffer *cb, |
807 | QRhiRenderTarget *rt, |
808 | const QColor &colorClearValue, |
809 | const QRhiDepthStencilClearValue &depthStencilClearValue, |
810 | QRhiResourceUpdateBatch *resourceUpdates, |
811 | QRhiCommandBuffer::BeginPassFlags flags) override; |
812 | void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; |
813 | |
814 | void setGraphicsPipeline(QRhiCommandBuffer *cb, |
815 | QRhiGraphicsPipeline *ps) override; |
816 | |
817 | void setShaderResources(QRhiCommandBuffer *cb, |
818 | QRhiShaderResourceBindings *srb, |
819 | int dynamicOffsetCount, |
820 | const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override; |
821 | |
822 | void setVertexInput(QRhiCommandBuffer *cb, |
823 | int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings, |
824 | QRhiBuffer *indexBuf, quint32 indexOffset, |
825 | QRhiCommandBuffer::IndexFormat indexFormat) override; |
826 | |
827 | void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override; |
828 | void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override; |
829 | void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override; |
830 | void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override; |
831 | |
832 | void draw(QRhiCommandBuffer *cb, quint32 vertexCount, |
833 | quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override; |
834 | |
835 | void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, |
836 | quint32 instanceCount, quint32 firstIndex, |
837 | qint32 vertexOffset, quint32 firstInstance) override; |
838 | |
839 | void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override; |
840 | void debugMarkEnd(QRhiCommandBuffer *cb) override; |
841 | void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override; |
842 | |
843 | void beginComputePass(QRhiCommandBuffer *cb, |
844 | QRhiResourceUpdateBatch *resourceUpdates, |
845 | QRhiCommandBuffer::BeginPassFlags flags) override; |
846 | void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override; |
847 | void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override; |
848 | void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override; |
849 | |
850 | const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override; |
851 | void beginExternal(QRhiCommandBuffer *cb) override; |
852 | void endExternal(QRhiCommandBuffer *cb) override; |
853 | double lastCompletedGpuTime(QRhiCommandBuffer *cb) override; |
854 | |
855 | QList<int> supportedSampleCounts() const override; |
856 | int ubufAlignment() const override; |
857 | bool isYUpInFramebuffer() const override; |
858 | bool isYUpInNDC() const override; |
859 | bool isClipDepthZeroToOne() const override; |
860 | QMatrix4x4 clipSpaceCorrMatrix() const override; |
861 | bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override; |
862 | bool isFeatureSupported(QRhi::Feature feature) const override; |
863 | int resourceLimit(QRhi::ResourceLimit limit) const override; |
864 | const QRhiNativeHandles *nativeHandles() override; |
865 | QRhiDriverInfo driverInfo() const override; |
866 | QRhiStats statistics() override; |
867 | bool makeThreadLocalNativeContextCurrent() override; |
868 | void releaseCachedResources() override; |
869 | bool isDeviceLost() const override; |
870 | |
871 | QByteArray pipelineCacheData() override; |
872 | void setPipelineCacheData(const QByteArray &data) override; |
873 | |
874 | bool ensureContext(QSurface *surface = nullptr) const; |
875 | QSurface *evaluateFallbackSurface() const; |
876 | void executeDeferredReleases(); |
877 | void trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access); |
878 | void trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Texture::Access access); |
879 | void enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD, |
880 | int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc); |
881 | void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates); |
882 | void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker, |
883 | QGles2Buffer *bufD, |
884 | QRhiPassResourceTracker::BufferAccess access, |
885 | QRhiPassResourceTracker::BufferStage stage); |
886 | void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker, |
887 | QGles2Texture *texD, |
888 | QRhiPassResourceTracker::TextureAccess access, |
889 | QRhiPassResourceTracker::TextureStage stage); |
890 | void executeCommandBuffer(QRhiCommandBuffer *cb); |
891 | void executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2GraphicsPipeline *psD); |
892 | void bindCombinedSampler(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Sampler *samplerD, |
893 | void *ps, uint psGeneration, int glslLocation, |
894 | int *texUnit, bool *activeTexUnitAltered); |
895 | void bindShaderResources(QGles2CommandBuffer *cbD, |
896 | QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs, |
897 | QRhiShaderResourceBindings *srb, |
898 | const uint *dynOfsPairs, int dynOfsCount); |
899 | QGles2RenderTargetData *enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD, |
900 | bool *wantsColorClear = nullptr, bool *wantsDsClear = nullptr); |
901 | void enqueueBarriersForPass(QGles2CommandBuffer *cbD); |
902 | QByteArray shaderSource(const QRhiShaderStage &shaderStage, QShaderVersion *shaderVersion); |
903 | bool compileShader(GLuint program, const QRhiShaderStage &shaderStage, QShaderVersion *shaderVersion); |
904 | bool linkProgram(GLuint program); |
905 | using ActiveUniformLocationTracker = QDuplicateTracker<int, 32>; |
906 | void registerUniformIfActive(const QShaderDescription::BlockVariable &var, |
907 | const QByteArray &namePrefix, int binding, int baseOffset, |
908 | GLuint program, |
909 | ActiveUniformLocationTracker *activeUniformLocations, |
910 | QGles2UniformDescriptionVector *dst); |
911 | void gatherUniforms(GLuint program, const QShaderDescription::UniformBlock &ub, |
912 | ActiveUniformLocationTracker *activeUniformLocations, QGles2UniformDescriptionVector *dst); |
913 | void gatherSamplers(GLuint program, const QShaderDescription::InOutVariable &v, |
914 | QGles2SamplerDescriptionVector *dst); |
915 | void gatherGeneratedSamplers(GLuint program, |
916 | const QShader::SeparateToCombinedImageSamplerMapping &mapping, |
917 | QGles2SamplerDescriptionVector *dst); |
918 | void sanityCheckVertexFragmentInterface(const QShaderDescription &vsDesc, const QShaderDescription &fsDesc); |
919 | bool isProgramBinaryDiskCacheEnabled() const; |
920 | |
921 | enum ProgramCacheResult { |
922 | ProgramCacheHit, |
923 | ProgramCacheMiss, |
924 | ProgramCacheError |
925 | }; |
926 | ProgramCacheResult tryLoadFromDiskOrPipelineCache(const QRhiShaderStage *stages, |
927 | int stageCount, |
928 | GLuint program, |
929 | const QVector<QShaderDescription::InOutVariable> &inputVars, |
930 | QByteArray *cacheKey); |
931 | void trySaveToDiskCache(GLuint program, const QByteArray &cacheKey); |
932 | void trySaveToPipelineCache(GLuint program, const QByteArray &cacheKey, bool force = false); |
933 | |
934 | QRhi::Flags rhiFlags; |
935 | QOpenGLContext *ctx = nullptr; |
936 | bool importedContext = false; |
937 | QSurfaceFormat requestedFormat; |
938 | QSurface *fallbackSurface = nullptr; |
939 | QPointer<QWindow> maybeWindow = nullptr; |
940 | QOpenGLContext *maybeShareContext = nullptr; |
941 | mutable bool needsMakeCurrentDueToSwap = false; |
942 | QOpenGLExtensions *f = nullptr; |
943 | void (QOPENGLF_APIENTRYP glPolygonMode) (GLenum, GLenum) = nullptr; |
944 | void(QOPENGLF_APIENTRYP glTexImage1D)(GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, |
945 | const void *) = nullptr; |
946 | void(QOPENGLF_APIENTRYP glTexStorage1D)(GLenum, GLint, GLenum, GLsizei) = nullptr; |
947 | void(QOPENGLF_APIENTRYP glTexSubImage1D)(GLenum, GLint, GLint, GLsizei, GLenum, GLenum, |
948 | const GLvoid *) = nullptr; |
949 | void(QOPENGLF_APIENTRYP glCopyTexSubImage1D)(GLenum, GLint, GLint, GLint, GLint, |
950 | GLsizei) = nullptr; |
951 | void(QOPENGLF_APIENTRYP glCompressedTexImage1D)(GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, |
952 | const GLvoid *) = nullptr; |
953 | void(QOPENGLF_APIENTRYP glCompressedTexSubImage1D)(GLenum, GLint, GLint, GLsizei, GLenum, |
954 | GLsizei, const GLvoid *) = nullptr; |
955 | void(QOPENGLF_APIENTRYP glFramebufferTexture1D)(GLenum, GLenum, GLenum, GLuint, |
956 | GLint) = nullptr; |
957 | void(QOPENGLF_APIENTRYP glFramebufferTextureMultiviewOVR)(GLenum, GLenum, GLuint, GLint, |
958 | GLint, GLsizei) = nullptr; |
959 | void (QOPENGLF_APIENTRYP glQueryCounter)(GLuint, GLenum) = nullptr; |
960 | void (QOPENGLF_APIENTRYP glGetQueryObjectui64v)(GLuint, GLenum, quint64 *) = nullptr; |
961 | void (QOPENGLF_APIENTRYP glObjectLabel)(GLenum, GLuint, GLsizei, const GLchar *) = nullptr; |
962 | void (QOPENGLF_APIENTRYP glFramebufferTexture2DMultisampleEXT)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei) = nullptr; |
963 | void (QOPENGLF_APIENTRYP glFramebufferTextureMultisampleMultiviewOVR)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei) = nullptr; |
964 | uint vao = 0; |
965 | struct Caps { |
966 | Caps() |
967 | : ctxMajor(2), |
968 | ctxMinor(0), |
969 | maxTextureSize(2048), |
970 | maxDrawBuffers(4), |
971 | maxSamples(16), |
972 | maxTextureArraySize(0), |
973 | maxThreadGroupsPerDimension(0), |
974 | maxThreadsPerThreadGroup(0), |
975 | maxThreadGroupsX(0), |
976 | maxThreadGroupsY(0), |
977 | maxThreadGroupsZ(0), |
978 | maxUniformVectors(4096), |
979 | maxVertexInputs(8), |
980 | maxVertexOutputs(8), |
981 | msaaRenderBuffer(false), |
982 | multisampledTexture(false), |
983 | npotTextureFull(true), |
984 | gles(false), |
985 | fixedIndexPrimitiveRestart(false), |
986 | bgraExternalFormat(false), |
987 | bgraInternalFormat(false), |
988 | r8Format(false), |
989 | r16Format(false), |
990 | floatFormats(false), |
991 | rgb10Formats(false), |
992 | depthTexture(false), |
993 | packedDepthStencil(false), |
994 | needsDepthStencilCombinedAttach(false), |
995 | srgbWriteControl(false), |
996 | coreProfile(false), |
997 | uniformBuffers(false), |
998 | elementIndexUint(false), |
999 | depth24(false), |
1000 | rgba8Format(false), |
1001 | instancing(false), |
1002 | baseVertex(false), |
1003 | compute(false), |
1004 | textureCompareMode(false), |
1005 | properMapBuffer(false), |
1006 | nonBaseLevelFramebufferTexture(false), |
1007 | texelFetch(false), |
1008 | intAttributes(true), |
1009 | screenSpaceDerivatives(false), |
1010 | programBinary(false), |
1011 | texture3D(false), |
1012 | tessellation(false), |
1013 | geometryShader(false), |
1014 | texture1D(false), |
1015 | hasDrawBuffersFunc(false), |
1016 | halfAttributes(false), |
1017 | multiView(false), |
1018 | timestamps(false), |
1019 | objectLabel(false), |
1020 | glesMultisampleRenderToTexture(false), |
1021 | glesMultiviewMultisampleRenderToTexture(false), |
1022 | unpackRowLength(false) |
1023 | { } |
1024 | int ctxMajor; |
1025 | int ctxMinor; |
1026 | int maxTextureSize; |
1027 | int maxDrawBuffers; |
1028 | int maxSamples; |
1029 | int maxTextureArraySize; |
1030 | int maxThreadGroupsPerDimension; |
1031 | int maxThreadsPerThreadGroup; |
1032 | int maxThreadGroupsX; |
1033 | int maxThreadGroupsY; |
1034 | int maxThreadGroupsZ; |
1035 | int maxUniformVectors; |
1036 | int maxVertexInputs; |
1037 | int maxVertexOutputs; |
1038 | // Multisample fb and blit are supported (GLES 3.0 or OpenGL 3.x). Not |
1039 | // the same as multisample textures! |
1040 | uint msaaRenderBuffer : 1; |
1041 | uint multisampledTexture : 1; |
1042 | uint npotTextureFull : 1; |
1043 | uint gles : 1; |
1044 | uint fixedIndexPrimitiveRestart : 1; |
1045 | uint bgraExternalFormat : 1; |
1046 | uint bgraInternalFormat : 1; |
1047 | uint r8Format : 1; |
1048 | uint r16Format : 1; |
1049 | uint floatFormats : 1; |
1050 | uint rgb10Formats : 1; |
1051 | uint depthTexture : 1; |
1052 | uint packedDepthStencil : 1; |
1053 | uint needsDepthStencilCombinedAttach : 1; |
1054 | uint srgbWriteControl : 1; |
1055 | uint coreProfile : 1; |
1056 | uint uniformBuffers : 1; |
1057 | uint elementIndexUint : 1; |
1058 | uint depth24 : 1; |
1059 | uint rgba8Format : 1; |
1060 | uint instancing : 1; |
1061 | uint baseVertex : 1; |
1062 | uint compute : 1; |
1063 | uint textureCompareMode : 1; |
1064 | uint properMapBuffer : 1; |
1065 | uint nonBaseLevelFramebufferTexture : 1; |
1066 | uint texelFetch : 1; |
1067 | uint intAttributes : 1; |
1068 | uint screenSpaceDerivatives : 1; |
1069 | uint programBinary : 1; |
1070 | uint texture3D : 1; |
1071 | uint tessellation : 1; |
1072 | uint geometryShader : 1; |
1073 | uint texture1D : 1; |
1074 | uint hasDrawBuffersFunc : 1; |
1075 | uint halfAttributes : 1; |
1076 | uint multiView : 1; |
1077 | uint timestamps : 1; |
1078 | uint objectLabel : 1; |
1079 | uint glesMultisampleRenderToTexture : 1; |
1080 | uint glesMultiviewMultisampleRenderToTexture : 1; |
1081 | uint unpackRowLength : 1; |
1082 | } caps; |
1083 | QGles2SwapChain *currentSwapChain = nullptr; |
1084 | QSet<GLint> supportedCompressedFormats; |
1085 | mutable QList<int> supportedSampleCountList; |
1086 | QRhiGles2NativeHandles nativeHandlesStruct; |
1087 | QRhiDriverInfo driverInfoStruct; |
1088 | mutable bool contextLost = false; |
1089 | |
1090 | struct DeferredReleaseEntry { |
1091 | enum Type { |
1092 | Buffer, |
1093 | Pipeline, |
1094 | Texture, |
1095 | RenderBuffer, |
1096 | TextureRenderTarget |
1097 | }; |
1098 | Type type; |
1099 | union { |
1100 | struct { |
1101 | GLuint buffer; |
1102 | } buffer; |
1103 | struct { |
1104 | GLuint program; |
1105 | } pipeline; |
1106 | struct { |
1107 | GLuint texture; |
1108 | } texture; |
1109 | struct { |
1110 | GLuint renderbuffer; |
1111 | GLuint renderbuffer2; |
1112 | } renderbuffer; |
1113 | struct { |
1114 | GLuint framebuffer; |
1115 | GLuint nonMsaaThrowawayDepthTexture; |
1116 | } textureRenderTarget; |
1117 | }; |
1118 | }; |
1119 | QList<DeferredReleaseEntry> releaseQueue; |
1120 | |
1121 | struct OffscreenFrame { |
1122 | OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { } |
1123 | bool active = false; |
1124 | QGles2CommandBuffer cbWrapper; |
1125 | GLuint tsQueries[2] = {}; |
1126 | } ofr; |
1127 | |
1128 | QHash<QRhiShaderStage, uint> m_shaderCache; |
1129 | |
1130 | struct PipelineCacheData { |
1131 | quint32 format; |
1132 | QByteArray data; |
1133 | }; |
1134 | QHash<QByteArray, PipelineCacheData> m_pipelineCache; |
1135 | |
1136 | struct Scratch { |
1137 | union data32_t { |
1138 | float f; |
1139 | qint32 i; |
1140 | }; |
1141 | QVarLengthArray<data32_t, 128> packedArray; |
1142 | struct SeparateTexture { |
1143 | QGles2Texture *texture; |
1144 | int binding; |
1145 | int elem; |
1146 | }; |
1147 | QVarLengthArray<SeparateTexture, 8> separateTextureBindings; |
1148 | struct SeparateSampler { |
1149 | QGles2Sampler *sampler; |
1150 | int binding; |
1151 | }; |
1152 | QVarLengthArray<SeparateSampler, 4> separateSamplerBindings; |
1153 | } m_scratch; |
1154 | }; |
1155 | |
1156 | Q_DECLARE_TYPEINFO(QRhiGles2::DeferredReleaseEntry, Q_RELOCATABLE_TYPE); |
1157 | |
1158 | QT_END_NAMESPACE |
1159 | |
1160 | #endif |
1161 |
Definitions
- QGles2Buffer
- Access
- UsageState
- QGles2RenderBuffer
- QGles2SamplerData
- operator==
- operator!=
- QGles2Texture
- Access
- UsageState
- QGles2Sampler
- QGles2RenderPassDescriptor
- QGles2RenderTargetData
- QGles2RenderTargetData
- isValid
- QGles2SwapChainRenderTarget
- QGles2TextureRenderTarget
- QGles2ShaderResourceBindings
- QGles2UniformDescription
- QGles2SamplerDescription
- QGles2UniformState
- MAX_TRACKED_LOCATION
- QGles2GraphicsPipeline
- QGles2ComputePipeline
- QGles2CommandBuffer
- Command
- Cmd
- Args
- PassType
- GraphicsPassState
- ColorMask
- Blend
- StencilFace
- reset
- ComputePassState
- Access
- reset
- TextureUnitState
- retainData
- retainBufferData
- retainImage
- resetCommands
- resetState
- resetCachedState
- operator==
- operator!=
- operator==
- operator!=
- operator==
- operator!=
- QGles2SwapChainTimestamps
- QGles2SwapChain
- QRhiGles2
- ProgramCacheResult
- Caps
- Caps
- DeferredReleaseEntry
- Type
- OffscreenFrame
- OffscreenFrame
- PipelineCacheData
- Scratch
- data32_t
- SeparateTexture
Learn Advanced QML with KDAB
Find out more