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

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