1 /****************************************************************************
2 **
3 ** Copyright (C) 2008-2012 NVIDIA Corporation.
4 ** Copyright (C) 2019 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of Qt Quick 3D.
8 **
9 ** $QT_BEGIN_LICENSE:GPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU
20 ** General Public License version 3 or (at your option) any later version
21 ** approved by the KDE Free Qt Foundation. The licenses are as published by
22 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
23 ** included in the packaging of this file. Please review the following
24 ** information to ensure the GNU General Public License requirements will
25 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26 **
27 ** $QT_END_LICENSE$
28 **
29 ****************************************************************************/
30
31 #include <QtQuick3DRender/private/qssgrenderbackendgl4_p.h>
32 #include <QtQuick3DRender/private/qssgrenderbackendinputassemblergl_p.h>
33 #include <QtQuick3DRender/private/qssgrenderbackendshaderprogramgl_p.h>
34
35 #include <QtQuick3DRender/private/qssgopenglextensions_p.h>
36
37 QT_BEGIN_NAMESPACE
38
39 #ifdef RENDER_BACKEND_LOG_GL_ERRORS
40 #define RENDER_LOG_ERROR_PARAMS(x) checkGLError(#x, __FILE__, __LINE__)
41 #else
42 #define RENDER_LOG_ERROR_PARAMS(x) checkGLError()
43 #endif
44
45 #define GL_CALL_EXTRA_FUNCTION(x) \
46 m_glExtraFunctions->x; \
47 RENDER_LOG_ERROR_PARAMS(x);
48
49 #if defined(QT_OPENGL_ES)
50 #define GL_CALL_QSSG_EXT(x) \
51 m_QSSGExtensions->x; \
52 RENDER_LOG_ERROR_PARAMS(x);
53 #else
54 #define GL_CALL_DIRECTSTATE_EXT(x) \
55 m_directStateAccess->x; \
56 RENDER_LOG_ERROR_PARAMS(x);
57 #define GL_CALL_QSSG_EXT(x) \
58 m_QSSGExtensions->x; \
59 RENDER_LOG_ERROR_PARAMS(x);
60 #endif
61
62 #ifndef GL_GEOMETRY_SHADER_EXT
63 #define GL_GEOMETRY_SHADER_EXT 0x8DD9
64 #endif
65
66 namespace QSSGGlExtStrings {
extTess()67 QByteArray extTess()
68 {
69 return QByteArrayLiteral("GL_ARB_tessellation_shader");
70 }
extGeometry()71 QByteArray extGeometry()
72 {
73 return QByteArrayLiteral("GL_EXT_geometry_shader4");
74 }
arbCompute()75 QByteArray arbCompute()
76 {
77 return QByteArrayLiteral("GL_ARB_compute_shader");
78 }
arbStorageBuffer()79 QByteArray arbStorageBuffer()
80 {
81 return QByteArrayLiteral("GL_ARB_shader_storage_buffer_object");
82 }
arbProgInterface()83 QByteArray arbProgInterface()
84 {
85 return QByteArrayLiteral("GL_ARB_program_interface_query");
86 }
arbShaderImageLoadStore()87 QByteArray arbShaderImageLoadStore()
88 {
89 return QByteArrayLiteral("GL_ARB_shader_image_load_store");
90 }
nvBlendAdvanced()91 QByteArray nvBlendAdvanced()
92 {
93 return QByteArrayLiteral("GL_NV_blend_equation_advanced");
94 }
khrBlendAdvanced()95 QByteArray khrBlendAdvanced()
96 {
97 return QByteArrayLiteral("GL_KHR_blend_equation_advanced");
98 }
nvBlendAdvancedCoherent()99 QByteArray nvBlendAdvancedCoherent()
100 {
101 return QByteArrayLiteral("GL_NV_blend_equation_advanced_coherent");
102 }
khrBlendAdvancedCoherent()103 QByteArray khrBlendAdvancedCoherent()
104 {
105 return QByteArrayLiteral("GL_KHR_blend_equation_advanced_coherent");
106 }
107 }
108
109 /// constructor
QSSGRenderBackendGL4Impl(const QSurfaceFormat & format)110 QSSGRenderBackendGL4Impl::QSSGRenderBackendGL4Impl(const QSurfaceFormat &format)
111 : QSSGRenderBackendGL3Impl(format)
112 {
113 // get extension count
114 GLint numExtensions = 0;
115 GL_CALL_EXTRA_FUNCTION(glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions));
116
117 for (qint32 i = 0; i < numExtensions; i++) {
118 const GLubyte *glExt = GL_CALL_EXTRA_FUNCTION(glGetStringi(GL_EXTENSIONS, GLuint(i)));
119 const QByteArray extensionString(reinterpret_cast<const char *>(glExt));
120
121 // search for extension
122 if (!m_backendSupport.caps.bits.bTessellationSupported && QSSGGlExtStrings::extTess().compare(extensionString) == 0) {
123 m_backendSupport.caps.bits.bTessellationSupported = true;
124 } else if (!m_backendSupport.caps.bits.bComputeSupported && QSSGGlExtStrings::arbCompute().compare(extensionString) == 0) {
125 m_backendSupport.caps.bits.bComputeSupported = true;
126 } else if (!m_backendSupport.caps.bits.bGeometrySupported
127 && QSSGGlExtStrings::extGeometry().compare(extensionString) == 0) {
128 m_backendSupport.caps.bits.bGeometrySupported = true;
129 } else if (!m_backendSupport.caps.bits.bStorageBufferSupported
130 && QSSGGlExtStrings::arbStorageBuffer().compare(extensionString) == 0) {
131 m_backendSupport.caps.bits.bStorageBufferSupported = true;
132 } else if (!m_backendSupport.caps.bits.bProgramInterfaceSupported
133 && QSSGGlExtStrings::arbProgInterface().compare(extensionString) == 0) {
134 m_backendSupport.caps.bits.bProgramInterfaceSupported = true;
135 } else if (!m_backendSupport.caps.bits.bShaderImageLoadStoreSupported
136 && QSSGGlExtStrings::arbShaderImageLoadStore().compare(extensionString) == 0) {
137 m_backendSupport.caps.bits.bShaderImageLoadStoreSupported = true;
138 } else if (!m_backendSupport.caps.bits.bNVAdvancedBlendSupported
139 && QSSGGlExtStrings::nvBlendAdvanced().compare(extensionString) == 0) {
140 m_backendSupport.caps.bits.bNVAdvancedBlendSupported = true;
141 } else if (!m_backendSupport.caps.bits.bNVBlendCoherenceSupported
142 && QSSGGlExtStrings::nvBlendAdvancedCoherent().compare(extensionString) == 0) {
143 m_backendSupport.caps.bits.bNVBlendCoherenceSupported = true;
144 } else if (!m_backendSupport.caps.bits.bKHRAdvancedBlendSupported
145 && QSSGGlExtStrings::khrBlendAdvanced().compare(extensionString) == 0) {
146 m_backendSupport.caps.bits.bKHRAdvancedBlendSupported = true;
147 } else if (!m_backendSupport.caps.bits.bKHRBlendCoherenceSupported
148 && QSSGGlExtStrings::khrBlendAdvancedCoherent().compare(extensionString) == 0) {
149 m_backendSupport.caps.bits.bKHRBlendCoherenceSupported = true;
150 }
151 }
152
153 // always true for GL4.1 and GLES 3.1 devices
154 m_backendSupport.caps.bits.bMsTextureSupported = true;
155 m_backendSupport.caps.bits.bProgramPipelineSupported = true;
156
157 if (!isESCompatible()) {
158 // TODO: investigate GL 4.0 support
159 // we expect minimum GL 4.1 context anything beyond is handeled via extensions
160 // Tessellation is always supported on none ES systems which support >=GL4
161 m_backendSupport.caps.bits.bTessellationSupported = true;
162 // geometry shader is always supported on none ES systems which support >=GL4 ( actually
163 // 3.2 already )
164 m_backendSupport.caps.bits.bGeometrySupported = true;
165 } else {
166 // always true for GLES 3.1 devices
167 m_backendSupport.caps.bits.bComputeSupported = true;
168 m_backendSupport.caps.bits.bProgramInterfaceSupported = true;
169 m_backendSupport.caps.bits.bStorageBufferSupported = true;
170 m_backendSupport.caps.bits.bShaderImageLoadStoreSupported = true;
171 }
172
173 #if !defined(QT_OPENGL_ES)
174 // Initialize extensions
175 m_directStateAccess = new QOpenGLExtension_EXT_direct_state_access();
176 m_directStateAccess->initializeOpenGLFunctions();
177 #endif
178 }
179
180 /// destructor
~QSSGRenderBackendGL4Impl()181 QSSGRenderBackendGL4Impl::~QSSGRenderBackendGL4Impl()
182 {
183 #if !defined(QT_OPENGL_ES)
184 delete m_directStateAccess;
185 #endif
186 }
187
getShadingLanguageVersion()188 QByteArray QSSGRenderBackendGL4Impl::getShadingLanguageVersion()
189 {
190 // Re-use the implementation from the GL3 backend if the surface is GL ES 3
191 // (should only be the case for 3.1 and greater).
192 if (m_format.renderableType() == QSurfaceFormat::OpenGLES && m_format.majorVersion() == 3)
193 return QSSGRenderBackendGL3Impl::getShadingLanguageVersion();
194
195 Q_ASSERT(m_format.majorVersion() >= 4);
196 QByteArray ver("#version 400\n");
197 if (m_format.majorVersion() == 4)
198 ver[10] = '0' + char(m_format.minorVersion());
199
200 return ver;
201 }
202
getRenderContextType() const203 QSSGRenderContextType QSSGRenderBackendGL4Impl::getRenderContextType() const
204 {
205 // Re-use the implementation from the GL3 backend if the surface is GL ES 3
206 // (should only be the case for 3.1 and greater).
207 if (m_format.renderableType() == QSurfaceFormat::OpenGLES && m_format.majorVersion() == 3)
208 return QSSGRenderBackendGL3Impl::getRenderContextType();
209
210 Q_ASSERT(m_format.majorVersion() >= 4);
211 return QSSGRenderContextType::GL4;
212 }
213
createTextureStorage2D(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 levels,QSSGRenderTextureFormat internalFormat,qint32 width,qint32 height)214 void QSSGRenderBackendGL4Impl::createTextureStorage2D(QSSGRenderBackendTextureObject to,
215 QSSGRenderTextureTargetType target,
216 qint32 levels,
217 QSSGRenderTextureFormat internalFormat,
218 qint32 width,
219 qint32 height)
220 {
221 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
222 GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
223 setActiveTexture(GL_TEXTURE0);
224 GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID));
225
226 // up to now compressed is not supported
227 Q_ASSERT(internalFormat.isUncompressedTextureFormat());
228
229 GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
230 GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), internalFormat, glformat, gltype, glInternalFormat);
231
232 GL_CALL_EXTRA_FUNCTION(glTexStorage2D(glTarget, levels, glInternalFormat, GLsizei(width), GLsizei(height)));
233
234 GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0));
235 }
236
setMultisampledTextureData2D(QSSGRenderBackendTextureObject to,QSSGRenderTextureTargetType target,qint32 samples,QSSGRenderTextureFormat internalFormat,qint32 width,qint32 height,bool fixedsamplelocations)237 void QSSGRenderBackendGL4Impl::setMultisampledTextureData2D(QSSGRenderBackendTextureObject to,
238 QSSGRenderTextureTargetType target,
239 qint32 samples,
240 QSSGRenderTextureFormat internalFormat,
241 qint32 width,
242 qint32 height,
243 bool fixedsamplelocations)
244 {
245 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
246 GLenum glTarget = GLConversion::fromTextureTargetToGL(target);
247 setActiveTexture(GL_TEXTURE0);
248 GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, texID));
249
250 QSSGRenderTextureSwizzleMode swizzleMode = QSSGRenderTextureSwizzleMode::NoSwizzle;
251 internalFormat = GLConversion::replaceDeprecatedTextureFormat(getRenderContextType(), internalFormat, swizzleMode);
252
253 GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
254
255 if (internalFormat.isUncompressedTextureFormat())
256 GLConversion::fromUncompressedTextureFormatToGL(getRenderContextType(), internalFormat, glformat, gltype, glInternalFormat);
257 else if (internalFormat.isDepthTextureFormat())
258 GLConversion::fromDepthTextureFormatToGL(getRenderContextType(), internalFormat, glformat, gltype, glInternalFormat);
259 GL_CALL_EXTRA_FUNCTION(
260 glTexStorage2DMultisample(glTarget, GLsizei(samples), glInternalFormat, GLsizei(width), GLsizei(height), fixedsamplelocations));
261
262 GL_CALL_EXTRA_FUNCTION(glBindTexture(glTarget, 0));
263 }
264
createTessControlShader(QSSGByteView source,QByteArray & errorMessage,bool binary)265 QSSGRenderBackend::QSSGRenderBackendTessControlShaderObject QSSGRenderBackendGL4Impl::createTessControlShader(
266 QSSGByteView source,
267 QByteArray &errorMessage,
268 bool binary)
269 {
270 #if !defined(QT_OPENGL_ES)
271 GLuint shaderID = GL_CALL_EXTRA_FUNCTION(glCreateShader(GL_TESS_CONTROL_SHADER));
272 #else
273 GLuint shaderID = 0;
274 #endif
275 if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) {
276 GL_CALL_EXTRA_FUNCTION(glDeleteShader(shaderID));
277 shaderID = 0;
278 }
279
280 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendTessControlShaderObject>(quintptr(shaderID));
281 }
282
createTessEvaluationShader(QSSGByteView source,QByteArray & errorMessage,bool binary)283 QSSGRenderBackend::QSSGRenderBackendTessEvaluationShaderObject QSSGRenderBackendGL4Impl::createTessEvaluationShader(
284 QSSGByteView source,
285 QByteArray &errorMessage,
286 bool binary)
287 {
288 #if !defined(QT_OPENGL_ES)
289 GLuint shaderID = GL_CALL_EXTRA_FUNCTION(glCreateShader(GL_TESS_EVALUATION_SHADER));
290 #else
291 GLuint shaderID = 0;
292 #endif
293
294 if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) {
295 GL_CALL_EXTRA_FUNCTION(glDeleteShader(shaderID));
296 shaderID = 0;
297 }
298
299 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendTessEvaluationShaderObject>(quintptr(shaderID));
300 }
301
createGeometryShader(QSSGByteView source,QByteArray & errorMessage,bool binary)302 QSSGRenderBackend::QSSGRenderBackendGeometryShaderObject QSSGRenderBackendGL4Impl::createGeometryShader(QSSGByteView source,
303 QByteArray &errorMessage,
304 bool binary)
305 {
306 #if defined(QT_OPENGL_ES)
307 GLuint shaderID = GL_CALL_EXTRA_FUNCTION(glCreateShader(GL_GEOMETRY_SHADER_EXT));
308 #else
309 GLuint shaderID = GL_CALL_EXTRA_FUNCTION(glCreateShader(GL_GEOMETRY_SHADER));
310 #endif
311 if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) {
312 GL_CALL_EXTRA_FUNCTION(glDeleteShader(shaderID));
313 shaderID = 0;
314 }
315
316 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendGeometryShaderObject>(quintptr(shaderID));
317 }
318
setPatchVertexCount(QSSGRenderBackendInputAssemblerObject iao,quint32 count)319 void QSSGRenderBackendGL4Impl::setPatchVertexCount(QSSGRenderBackendInputAssemblerObject iao, quint32 count)
320 {
321 Q_ASSERT(iao);
322 Q_ASSERT(count);
323 QSSGRenderBackendInputAssemblerGL *inputAssembler = reinterpret_cast<QSSGRenderBackendInputAssemblerGL *>(iao);
324 inputAssembler->m_patchVertexCount = count;
325 }
326
setMemoryBarrier(QSSGRenderBufferBarrierFlags barriers)327 void QSSGRenderBackendGL4Impl::setMemoryBarrier(QSSGRenderBufferBarrierFlags barriers)
328 {
329 GL_CALL_EXTRA_FUNCTION(glMemoryBarrier(m_conversion.fromMemoryBarrierFlagsToGL(barriers)));
330 }
331
bindImageTexture(QSSGRenderBackendTextureObject to,quint32 unit,qint32 level,bool layered,qint32 layer,QSSGRenderImageAccessType access,QSSGRenderTextureFormat format)332 void QSSGRenderBackendGL4Impl::bindImageTexture(QSSGRenderBackendTextureObject to,
333 quint32 unit,
334 qint32 level,
335 bool layered,
336 qint32 layer,
337 QSSGRenderImageAccessType access,
338 QSSGRenderTextureFormat format)
339 {
340 GLuint texID = HandleToID_cast(GLuint, quintptr, to);
341
342 GL_CALL_EXTRA_FUNCTION(glBindImageTexture(unit,
343 texID,
344 level,
345 layered,
346 layer,
347 m_conversion.fromImageAccessToGL(access),
348 m_conversion.fromImageFormatToGL(format)));
349 }
350
getStorageBufferCount(QSSGRenderBackendShaderProgramObject po)351 qint32 QSSGRenderBackendGL4Impl::getStorageBufferCount(QSSGRenderBackendShaderProgramObject po)
352 {
353 GLint numStorageBuffers = 0;
354
355 // The static, compile time condition is not ideal (it all should be run
356 // time checks), but will be replaced in the future anyway.
357 #if defined(GL_VERSION_4_3) || defined(QT_OPENGL_ES_3_1)
358 Q_ASSERT(po);
359 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
360 GLuint programID = static_cast<GLuint>(pProgram->m_programID);
361 if (m_backendSupport.caps.bits.bProgramInterfaceSupported)
362 GL_CALL_EXTRA_FUNCTION(glGetProgramInterfaceiv(programID, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numStorageBuffers));
363 #else
364 Q_UNUSED(po);
365 #endif
366 return numStorageBuffers;
367 }
368
getStorageBufferInfoByID(QSSGRenderBackendShaderProgramObject po,quint32 id,quint32 nameBufSize,qint32 * paramCount,qint32 * bufferSize,qint32 * length,char * nameBuf)369 qint32 QSSGRenderBackendGL4Impl::getStorageBufferInfoByID(QSSGRenderBackendShaderProgramObject po,
370 quint32 id,
371 quint32 nameBufSize,
372 qint32 *paramCount,
373 qint32 *bufferSize,
374 qint32 *length,
375 char *nameBuf)
376 {
377 GLint bufferIndex = GL_INVALID_INDEX;
378
379 // The static, compile time condition is not ideal (it all should be run
380 // time checks), but will be replaced in the future anyway.
381 #if defined(GL_VERSION_4_3) || defined(QT_OPENGL_ES_3_1)
382 Q_ASSERT(po);
383 Q_ASSERT(length);
384 Q_ASSERT(nameBuf);
385 Q_ASSERT(bufferSize);
386 Q_ASSERT(paramCount);
387 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
388 GLuint programID = static_cast<GLuint>(pProgram->m_programID);
389 if (m_backendSupport.caps.bits.bProgramInterfaceSupported) {
390 GL_CALL_EXTRA_FUNCTION(glGetProgramResourceName(programID, GL_SHADER_STORAGE_BLOCK, id, nameBufSize, length, nameBuf));
391
392 if (*length > 0) {
393 #define QUERY_COUNT 3
394 GLsizei actualCount;
395 GLenum props[QUERY_COUNT] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE, GL_NUM_ACTIVE_VARIABLES };
396 GLint params[QUERY_COUNT];
397 GL_CALL_EXTRA_FUNCTION(
398 glGetProgramResourceiv(programID, GL_SHADER_STORAGE_BLOCK, id, QUERY_COUNT, props, QUERY_COUNT, &actualCount, params));
399
400 Q_ASSERT(actualCount == QUERY_COUNT);
401
402 bufferIndex = params[0];
403 *bufferSize = params[1];
404 *paramCount = params[2];
405 }
406 }
407 #else
408 Q_UNUSED(po);
409 Q_UNUSED(id);
410 Q_UNUSED(nameBufSize);
411 Q_UNUSED(paramCount);
412 Q_UNUSED(bufferSize);
413 Q_UNUSED(length);
414 Q_UNUSED(nameBuf);
415 #endif
416 return bufferIndex;
417 }
418
programSetStorageBuffer(quint32 index,QSSGRenderBackendBufferObject bo)419 void QSSGRenderBackendGL4Impl::programSetStorageBuffer(quint32 index, QSSGRenderBackendBufferObject bo)
420 {
421 // The static, compile time condition is not ideal (it all should be run
422 // time checks), but will be replaced in the future anyway.
423 #if defined(GL_VERSION_4_3) || defined(QT_OPENGL_ES_3_1)
424 GL_CALL_EXTRA_FUNCTION(glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, HandleToID_cast(GLuint, quintptr, bo)));
425 #else
426 Q_UNUSED(index);
427 Q_UNUSED(bo);
428 #endif
429 }
430
setConstantValue(QSSGRenderBackendShaderProgramObject po,quint32 id,QSSGRenderShaderDataType type,qint32 count,const void * value,bool transpose)431 void QSSGRenderBackendGL4Impl::setConstantValue(QSSGRenderBackendShaderProgramObject po,
432 quint32 id,
433 QSSGRenderShaderDataType type,
434 qint32 count,
435 const void *value,
436 bool transpose)
437 {
438 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
439 GLuint programID = static_cast<GLuint>(pProgram->m_programID);
440
441 GLenum glType = GLConversion::fromPropertyDataTypesToShaderGL(type);
442
443 switch (glType) {
444 case GL_FLOAT:
445 GL_CALL_EXTRA_FUNCTION(glProgramUniform1fv(programID, GLint(id), count, static_cast<const GLfloat *>(value)));
446 break;
447 case GL_FLOAT_VEC2:
448 GL_CALL_EXTRA_FUNCTION(glProgramUniform2fv(programID, GLint(id), count, static_cast<const GLfloat *>(value)));
449 break;
450 case GL_FLOAT_VEC3:
451 GL_CALL_EXTRA_FUNCTION(glProgramUniform3fv(programID, GLint(id), count, static_cast<const GLfloat *>(value)));
452 break;
453 case GL_FLOAT_VEC4:
454 GL_CALL_EXTRA_FUNCTION(glProgramUniform4fv(programID, GLint(id), count, static_cast<const GLfloat *>(value)));
455 break;
456 case GL_INT:
457 GL_CALL_EXTRA_FUNCTION(glProgramUniform1iv(programID, GLint(id), count, static_cast<const GLint *>(value)));
458 break;
459 case GL_BOOL: {
460 const GLint boolValue = value ? *reinterpret_cast<const bool *>(value) : false;
461 GL_CALL_EXTRA_FUNCTION(glProgramUniform1iv(programID, GLint(id), count, &boolValue));
462 } break;
463 case GL_INT_VEC2:
464 case GL_BOOL_VEC2:
465 GL_CALL_EXTRA_FUNCTION(glProgramUniform2iv(programID, GLint(id), count, static_cast<const GLint *>(value)));
466 break;
467 case GL_INT_VEC3:
468 case GL_BOOL_VEC3:
469 GL_CALL_EXTRA_FUNCTION(glProgramUniform3iv(programID, GLint(id), count, static_cast<const GLint *>(value)));
470 break;
471 case GL_INT_VEC4:
472 case GL_BOOL_VEC4:
473 GL_CALL_EXTRA_FUNCTION(glProgramUniform4iv(programID, GLint(id), count, static_cast<const GLint *>(value)));
474 break;
475 case GL_FLOAT_MAT3:
476 GL_CALL_EXTRA_FUNCTION(glProgramUniformMatrix3fv(programID, GLint(id), count, transpose, static_cast<const GLfloat *>(value)));
477 break;
478 case GL_FLOAT_MAT4:
479 GL_CALL_EXTRA_FUNCTION(glProgramUniformMatrix4fv(programID, GLint(id), count, transpose, static_cast<const GLfloat *>(value)));
480 break;
481 case GL_IMAGE_2D:
482 case GL_SAMPLER_2D:
483 case GL_SAMPLER_2D_SHADOW:
484 case GL_SAMPLER_CUBE: {
485 if (count <= 1) {
486 GLint sampler = *static_cast<const GLint *>(value);
487 GL_CALL_EXTRA_FUNCTION(glProgramUniform1i(programID, GLint(id), sampler));
488 } else {
489 const GLint *sampler = static_cast<const GLint *>(value);
490 GL_CALL_EXTRA_FUNCTION(glProgramUniform1iv(programID, GLint(id), count, sampler));
491 }
492 } break;
493 default:
494 qCCritical(RENDER_INTERNAL_ERROR, "Unknown shader type format %d", int(type));
495 Q_ASSERT(false);
496 break;
497 }
498 }
499
createComputeShader(QSSGByteView source,QByteArray & errorMessage,bool binary)500 QSSGRenderBackend::QSSGRenderBackendComputeShaderObject QSSGRenderBackendGL4Impl::createComputeShader(QSSGByteView source,
501 QByteArray &errorMessage,
502 bool binary)
503 {
504 GLuint shaderID = 0;
505 shaderID = m_glExtraFunctions->glCreateShader(GL_COMPUTE_SHADER);
506
507 if (shaderID && !compileSource(shaderID, source, errorMessage, binary)) {
508 GL_CALL_EXTRA_FUNCTION(glDeleteShader(shaderID));
509 shaderID = 0;
510 }
511 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendComputeShaderObject>(quintptr(shaderID));
512 }
513
dispatchCompute(QSSGRenderBackendShaderProgramObject,quint32 numGroupsX,quint32 numGroupsY,quint32 numGroupsZ)514 void QSSGRenderBackendGL4Impl::dispatchCompute(QSSGRenderBackendShaderProgramObject, quint32 numGroupsX, quint32 numGroupsY, quint32 numGroupsZ)
515 {
516 GL_CALL_EXTRA_FUNCTION(glDispatchCompute(numGroupsX, numGroupsY, numGroupsZ));
517 }
518
createProgramPipeline()519 QSSGRenderBackend::QSSGRenderBackendProgramPipeline QSSGRenderBackendGL4Impl::createProgramPipeline()
520 {
521 GLuint pipeline;
522 GL_CALL_EXTRA_FUNCTION(glGenProgramPipelines(1, &pipeline));
523
524 return reinterpret_cast<QSSGRenderBackend::QSSGRenderBackendProgramPipeline>(quintptr(pipeline));
525 }
526
releaseProgramPipeline(QSSGRenderBackendProgramPipeline ppo)527 void QSSGRenderBackendGL4Impl::releaseProgramPipeline(QSSGRenderBackendProgramPipeline ppo)
528 {
529 GLuint pipeline = HandleToID_cast(GLuint, quintptr, ppo);
530 GL_CALL_EXTRA_FUNCTION(glDeleteProgramPipelines(1, &pipeline));
531 }
532
setActiveProgramPipeline(QSSGRenderBackendProgramPipeline ppo)533 void QSSGRenderBackendGL4Impl::setActiveProgramPipeline(QSSGRenderBackendProgramPipeline ppo)
534 {
535 GLuint pipeline = HandleToID_cast(GLuint, quintptr, ppo);
536
537 GL_CALL_EXTRA_FUNCTION(glBindProgramPipeline(pipeline));
538 }
539
setProgramStages(QSSGRenderBackendProgramPipeline ppo,QSSGRenderShaderTypeFlags flags,QSSGRenderBackendShaderProgramObject po)540 void QSSGRenderBackendGL4Impl::setProgramStages(QSSGRenderBackendProgramPipeline ppo,
541 QSSGRenderShaderTypeFlags flags,
542 QSSGRenderBackendShaderProgramObject po)
543 {
544 GLuint pipeline = HandleToID_cast(GLuint, quintptr, ppo);
545 GLuint programID = 0;
546
547 if (po) {
548 QSSGRenderBackendShaderProgramGL *pProgram = reinterpret_cast<QSSGRenderBackendShaderProgramGL *>(po);
549 programID = static_cast<GLuint>(pProgram->m_programID);
550 }
551
552 GL_CALL_EXTRA_FUNCTION(glUseProgramStages(pipeline, m_conversion.fromShaderTypeFlagsToGL(flags), programID));
553 }
554
setBlendEquation(const QSSGRenderBlendEquationArgument & pBlendEquArg)555 void QSSGRenderBackendGL4Impl::setBlendEquation(const QSSGRenderBlendEquationArgument &pBlendEquArg)
556 {
557 if (m_backendSupport.caps.bits.bNVAdvancedBlendSupported || m_backendSupport.caps.bits.bKHRAdvancedBlendSupported)
558 GL_CALL_EXTRA_FUNCTION(
559 glBlendEquation(m_conversion.fromBlendEquationToGL(pBlendEquArg.m_rgbEquation,
560 m_backendSupport.caps.bits.bNVAdvancedBlendSupported,
561 m_backendSupport.caps.bits.bKHRAdvancedBlendSupported)));
562 }
563
setBlendBarrier(void)564 void QSSGRenderBackendGL4Impl::setBlendBarrier(void)
565 {
566 if (m_backendSupport.caps.bits.bNVAdvancedBlendSupported)
567 GL_CALL_QSSG_EXT(glBlendBarrierNV());
568 }
569
570 QT_END_NAMESPACE
571