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