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

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