1// Copyright (C) 2018 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#include "graphicshelperes3_1_p.h"
5#include <qgraphicsutils_p.h>
6#include <QOpenGLExtraFunctions>
7
8QT_BEGIN_NAMESPACE
9
10// ES 3.1+
11#ifndef GL_SAMPLER_2D_MULTISAMPLE
12#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
13#endif
14#ifndef GL_INT_SAMPLER_2D_MULTISAMPLE
15#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
16#endif
17#ifndef GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE
18#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
19#endif
20#ifndef GL_ACTIVE_RESOURCES
21#define GL_ACTIVE_RESOURCES 0x92F5
22#endif
23#ifndef GL_BUFFER_BINDING
24#define GL_BUFFER_BINDING 0x9302
25#endif
26#ifndef GL_BUFFER_DATA_SIZE
27#define GL_BUFFER_DATA_SIZE 0x9303
28#endif
29#ifndef GL_NUM_ACTIVE_VARIABLES
30#define GL_NUM_ACTIVE_VARIABLES 0x9304
31#endif
32#ifndef GL_SHADER_STORAGE_BLOCK
33#define GL_SHADER_STORAGE_BLOCK 0x92E6
34#endif
35#ifndef GL_ALL_BARRIER_BITS
36#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
37#endif
38#ifndef GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT
39#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
40#endif
41#ifndef GL_ELEMENT_ARRAY_BARRIER_BIT
42#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
43#endif
44#ifndef GL_UNIFORM_BARRIER_BIT
45#define GL_UNIFORM_BARRIER_BIT 0x00000004
46#endif
47#ifndef GL_TEXTURE_FETCH_BARRIER_BIT
48#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
49#endif
50#ifndef GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
51#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
52#endif
53#ifndef GL_COMMAND_BARRIER_BIT
54#define GL_COMMAND_BARRIER_BIT 0x00000040
55#endif
56#ifndef GL_PIXEL_BUFFER_BARRIER_BIT
57#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
58#endif
59#ifndef GL_TEXTURE_UPDATE_BARRIER_BIT
60#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
61#endif
62#ifndef GL_BUFFER_UPDATE_BARRIER_BIT
63#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
64#endif
65#ifndef GL_FRAMEBUFFER_BARRIER_BIT
66#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
67#endif
68#ifndef GL_TRANSFORM_FEEDBACK_BARRIER_BIT
69#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
70#endif
71#ifndef GL_ATOMIC_COUNTER_BARRIER_BIT
72#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
73#endif
74#ifndef GL_SHADER_STORAGE_BARRIER_BIT
75#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
76#endif
77#ifndef GL_IMAGE_2D
78#define GL_IMAGE_2D 0x904D
79#endif
80#ifndef GL_IMAGE_3D
81#define GL_IMAGE_3D 0x904E
82#endif
83#ifndef GL_IMAGE_CUBE
84#define GL_IMAGE_CUBE 0x9050
85#endif
86#ifndef GL_IMAGE_2D_ARRAY
87#define GL_IMAGE_2D_ARRAY 0x9053
88#endif
89#ifndef GL_INT_IMAGE_2D
90#define GL_INT_IMAGE_2D 0x9058
91#endif
92#ifndef GL_INT_IMAGE_3D
93#define GL_INT_IMAGE_3D 0x9059
94#endif
95#ifndef GL_INT_IMAGE_CUBE
96#define GL_INT_IMAGE_CUBE 0x905B
97#endif
98#ifndef GL_INT_IMAGE_2D_ARRAY
99#define GL_INT_IMAGE_2D_ARRAY 0x905E
100#endif
101#ifndef GL_UNSIGNED_INT_IMAGE_2D
102#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
103#endif
104#ifndef GL_UNSIGNED_INT_IMAGE_3D
105#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
106#endif
107#ifndef GL_UNSIGNED_INT_IMAGE_CUBE
108#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
109#endif
110#ifndef GL_UNSIGNED_INT_IMAGE_2D_ARRAY
111#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
112#endif
113
114
115namespace Qt3DRender {
116namespace Render {
117namespace OpenGL {
118
119namespace {
120
121GLbitfield memoryBarrierGL3Bitfield(QMemoryBarrier::Operations barriers)
122{
123 GLbitfield bits = 0;
124
125 if (barriers.testFlag(flag: QMemoryBarrier::All)) {
126 bits |= GL_ALL_BARRIER_BITS;
127 return bits;
128 }
129
130 if (barriers.testFlag(flag: QMemoryBarrier::VertexAttributeArray))
131 bits |= GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
132 if (barriers.testFlag(flag: QMemoryBarrier::ElementArray))
133 bits |= GL_ELEMENT_ARRAY_BARRIER_BIT;
134 if (barriers.testFlag(flag: QMemoryBarrier::Uniform))
135 bits |= GL_UNIFORM_BARRIER_BIT;
136 if (barriers.testFlag(flag: QMemoryBarrier::TextureFetch))
137 bits |= GL_TEXTURE_FETCH_BARRIER_BIT;
138 if (barriers.testFlag(flag: QMemoryBarrier::ShaderImageAccess))
139 bits |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
140 if (barriers.testFlag(flag: QMemoryBarrier::Command))
141 bits |= GL_COMMAND_BARRIER_BIT;
142 if (barriers.testFlag(flag: QMemoryBarrier::PixelBuffer))
143 bits |= GL_PIXEL_BUFFER_BARRIER_BIT;
144 if (barriers.testFlag(flag: QMemoryBarrier::TextureUpdate))
145 bits |= GL_TEXTURE_UPDATE_BARRIER_BIT;
146 if (barriers.testFlag(flag: QMemoryBarrier::BufferUpdate))
147 bits |= GL_BUFFER_UPDATE_BARRIER_BIT;
148 if (barriers.testFlag(flag: QMemoryBarrier::FrameBuffer))
149 bits |= GL_FRAMEBUFFER_BARRIER_BIT;
150 if (barriers.testFlag(flag: QMemoryBarrier::TransformFeedback))
151 bits |= GL_TRANSFORM_FEEDBACK_BARRIER_BIT;
152 if (barriers.testFlag(flag: QMemoryBarrier::AtomicCounter))
153 bits |= GL_ATOMIC_COUNTER_BARRIER_BIT;
154 if (barriers.testFlag(flag: QMemoryBarrier::ShaderStorage))
155 bits |= GL_SHADER_STORAGE_BARRIER_BIT;
156 if (barriers.testFlag(flag: QMemoryBarrier::QueryBuffer))
157 qWarning() << "QueryBuffer barrier not supported by ES 3.1";
158
159 return bits;
160}
161
162} // anonymous
163
164
165GraphicsHelperES3_1::GraphicsHelperES3_1()
166{
167}
168
169GraphicsHelperES3_1::~GraphicsHelperES3_1()
170{
171}
172
173bool GraphicsHelperES3_1::supportsFeature(GraphicsHelperInterface::Feature feature) const
174{
175 switch (feature) {
176 case GraphicsHelperInterface::Compute:
177 case GraphicsHelperInterface::ShaderStorageObject:
178 case GraphicsHelperInterface::IndirectDrawing:
179 case GraphicsHelperInterface::ShaderImage:
180 return true;
181 default:
182 break;
183 }
184 return GraphicsHelperES3::supportsFeature(feature);
185}
186
187void GraphicsHelperES3_1::bindImageTexture(GLuint imageUnit, GLuint texture,
188 GLint mipLevel, GLboolean layered,
189 GLint layer, GLenum access, GLenum format)
190{
191 m_extraFuncs->glBindImageTexture(unit: imageUnit,
192 texture,
193 level: mipLevel,
194 layered,
195 layer,
196 access,
197 format);
198}
199
200void GraphicsHelperES3_1::dispatchCompute(GLuint wx, GLuint wy, GLuint wz)
201{
202 m_extraFuncs->glDispatchCompute(num_groups_x: wx, num_groups_y: wy, num_groups_z: wz);
203}
204
205void GraphicsHelperES3_1::memoryBarrier(QMemoryBarrier::Operations barriers)
206{
207 m_extraFuncs->glMemoryBarrier(barriers: memoryBarrierGL3Bitfield(barriers));
208}
209
210void GraphicsHelperES3_1::drawArraysIndirect(GLenum mode, void *indirect)
211{
212 m_extraFuncs->glDrawArraysIndirect(mode, indirect);
213}
214
215void GraphicsHelperES3_1::drawElementsIndirect(GLenum mode, GLenum type, void *indirect)
216{
217 m_extraFuncs->glDrawElementsIndirect(mode, type, indirect);
218}
219
220void GraphicsHelperES3_1::bindShaderStorageBlock(GLuint , GLuint , GLuint )
221{
222 // ES 3.1 has no API for that, bindings have to be specified directly in the shader
223 // with layout(std430, binding = 3)
224 qWarning() << "ES 3.1 has no bindShaderStorageBlock API, it uses binding declaration from the shader storage block";
225}
226
227std::vector<ShaderStorageBlock> GraphicsHelperES3_1::programShaderStorageBlocks(GLuint programId)
228{
229 std::vector<ShaderStorageBlock> blocks;
230 GLint nbrActiveShaderStorageBlocks = 0;
231 m_extraFuncs->glGetProgramInterfaceiv(program: programId, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, params: &nbrActiveShaderStorageBlocks);
232 blocks.reserve(n: nbrActiveShaderStorageBlocks);
233 for (GLint i = 0; i < nbrActiveShaderStorageBlocks; ++i) {
234 QByteArray storageBlockName(256, '\0');
235 GLsizei length = 0;
236 ShaderStorageBlock storageBlock;
237 m_extraFuncs->glGetProgramResourceName(program: programId, GL_SHADER_STORAGE_BLOCK, index: i, bufSize: 256, length: &length, name: storageBlockName.data());
238 storageBlock.m_index = i;
239 storageBlock.m_name = QString::fromUtf8(ba: storageBlockName.left(len: length));
240 GLenum prop = GL_BUFFER_BINDING;
241 m_extraFuncs->glGetProgramResourceiv(program: programId, GL_SHADER_STORAGE_BLOCK, index: i, propCount: 1, props: &prop, bufSize: 4, NULL, params: &storageBlock.m_binding);
242 prop = GL_BUFFER_DATA_SIZE;
243 m_extraFuncs->glGetProgramResourceiv(program: programId, GL_SHADER_STORAGE_BLOCK, index: i, propCount: 1, props: &prop, bufSize: 4, NULL, params: &storageBlock.m_size);
244 prop = GL_NUM_ACTIVE_VARIABLES;
245 m_extraFuncs->glGetProgramResourceiv(program: programId, GL_SHADER_STORAGE_BLOCK, index: i, propCount: 1, props: &prop, bufSize: 4, NULL, params: &storageBlock.m_activeVariablesCount);
246 blocks.push_back(x: storageBlock);
247 }
248 return blocks;
249}
250
251UniformType GraphicsHelperES3_1::uniformTypeFromGLType(GLenum glType)
252{
253 switch (glType) {
254 case GL_SAMPLER_2D_MULTISAMPLE:
255 case GL_INT_SAMPLER_2D_MULTISAMPLE:
256 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
257 return UniformType::Sampler;
258 case GL_IMAGE_2D:
259 case GL_IMAGE_3D:
260 case GL_IMAGE_CUBE:
261 case GL_IMAGE_2D_ARRAY:
262 case GL_INT_IMAGE_2D:
263 case GL_INT_IMAGE_3D:
264 case GL_INT_IMAGE_CUBE:
265 case GL_INT_IMAGE_2D_ARRAY:
266 case GL_UNSIGNED_INT_IMAGE_2D:
267 case GL_UNSIGNED_INT_IMAGE_3D:
268 case GL_UNSIGNED_INT_IMAGE_CUBE:
269 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
270 return UniformType::Image;
271
272 default:
273 return GraphicsHelperES3::uniformTypeFromGLType(glType);
274 }
275}
276
277uint GraphicsHelperES3_1::uniformByteSize(const ShaderUniform &description)
278{
279 uint rawByteSize = 0;
280
281 switch (description.m_type) {
282 case GL_SAMPLER_2D_MULTISAMPLE:
283 case GL_INT_SAMPLER_2D_MULTISAMPLE:
284 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
285 case GL_IMAGE_2D:
286 case GL_IMAGE_3D:
287 case GL_IMAGE_CUBE:
288 case GL_IMAGE_2D_ARRAY:
289 case GL_INT_IMAGE_2D:
290 case GL_INT_IMAGE_3D:
291 case GL_INT_IMAGE_CUBE:
292 case GL_INT_IMAGE_2D_ARRAY:
293 case GL_UNSIGNED_INT_IMAGE_2D:
294 case GL_UNSIGNED_INT_IMAGE_3D:
295 case GL_UNSIGNED_INT_IMAGE_CUBE:
296 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
297 rawByteSize = 4;
298 break;
299
300 default:
301 rawByteSize = GraphicsHelperES3::uniformByteSize(description);
302 break;
303 }
304
305 return rawByteSize;
306}
307
308void GraphicsHelperES3_1::buildUniformBuffer(const QVariant &v, const ShaderUniform &description, QByteArray &buffer)
309{
310 char *bufferData = buffer.data();
311
312 switch (description.m_type) {
313 case GL_SAMPLER_2D_MULTISAMPLE:
314 case GL_INT_SAMPLER_2D_MULTISAMPLE:
315 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
316 {
317 Q_ASSERT(description.m_size == 1);
318 int value = v.toInt();
319 QGraphicsUtils::fillDataArray<GLint>(buffer: bufferData, data: &value, description, tupleSize: 1);
320 break;
321 }
322
323 default:
324 GraphicsHelperES3::buildUniformBuffer(v, description, buffer);
325 break;
326 }
327}
328
329} // namespace OpenGL
330} // namespace Render
331} // namespace Qt3DRender
332
333QT_END_NAMESPACE
334

source code of qt3d/src/plugins/renderers/opengl/graphicshelpers/graphicshelperes3_1.cpp