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

source code of qtbase/src/gui/rhi/qrhigles2_p.h