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