834 Q_ASSERT(fallbackSurface);
838 ctx =
new QOpenGLContext;
839 ctx->setFormat(requestedFormat);
840 if (maybeShareContext) {
841 ctx->setShareContext(maybeShareContext);
843 ctx->setScreen(maybeWindow->screen());
845 ctx->setScreen(maybeShareContext->screen());
846 }
else if (QOpenGLContext *shareContext = QOpenGLContext::globalShareContext()) {
847 ctx->setShareContext(shareContext);
849 ctx->setScreen(maybeWindow->screen());
851 ctx->setScreen(shareContext->screen());
852 }
else if (maybeWindow) {
853 ctx->setScreen(maybeWindow->screen());
855 if (!ctx->create()) {
856 qWarning(
"QRhiGles2: Failed to create context");
861 qCDebug(QRHI_LOG_INFO) <<
"Created OpenGL context" << ctx->format();
864 if (!ensureContext(maybeWindow ? maybeWindow : fallbackSurface))
867 f =
static_cast<QOpenGLExtensions *>(ctx->extraFunctions());
868 const QSurfaceFormat actualFormat = ctx->format();
869 caps.gles = actualFormat.renderableType() == QSurfaceFormat::OpenGLES;
873 ctx->getProcAddress(QByteArrayLiteral(
"glPolygonMode")));
876 GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum,
const void *)>(
877 ctx->getProcAddress(QByteArrayLiteral(
"glTexImage1D")));
879 glTexStorage1D =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei)>(
880 ctx->getProcAddress(QByteArrayLiteral(
"glTexStorage1D")));
883 GLenum, GLint, GLint, GLsizei, GLenum, GLenum,
const GLvoid *)>(
884 ctx->getProcAddress(QByteArrayLiteral(
"glTexSubImage1D")));
886 glCopyTexSubImage1D =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint,
888 ctx->getProcAddress(QByteArrayLiteral(
"glCopyTexSubImage1D")));
891 GLenum, GLint, GLenum, GLsizei, GLint, GLsizei,
const GLvoid *)>(
892 ctx->getProcAddress(QByteArrayLiteral(
"glCompressedTexImage1D")));
895 GLenum, GLint, GLint, GLsizei, GLenum, GLsizei,
const GLvoid *)>(
896 ctx->getProcAddress(QByteArrayLiteral(
"glCompressedTexSubImage1D")));
898 glFramebufferTexture1D =
900 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture1D")));
903 const char *vendor =
reinterpret_cast<
const char *>(
f->glGetString(GL_VENDOR));
904 const char *renderer =
reinterpret_cast<
const char *>(
f->glGetString(GL_RENDERER));
905 const char *version =
reinterpret_cast<
const char *>(
f->glGetString(GL_VERSION));
906 if (vendor && renderer && version)
907 qCDebug(QRHI_LOG_INFO,
"OpenGL VENDOR: %s RENDERER: %s VERSION: %s", vendor, renderer, version);
910 driverInfoStruct.deviceName += QByteArray(vendor);
911 driverInfoStruct.deviceName +=
' ';
914 driverInfoStruct.deviceName += QByteArray(renderer);
915 driverInfoStruct.deviceName +=
' ';
918 driverInfoStruct.deviceName += QByteArray(version);
920 caps.ctxMajor = actualFormat.majorVersion();
921 caps.ctxMinor = actualFormat.minorVersion();
924 caps.srgbTextureFormat = caps.ctxMajor >= 3 || ctx->hasExtension(
"GL_EXT_sRGB");
925 caps.srgbGenerateMipmap = caps.ctxMajor >= 3
926 || ctx->hasExtension(
"GL_NV_generate_mipmap_sRGB");
927 caps.srgbTextureRenderTarget = caps.srgbTextureFormat;
929 const bool hasCoreSrgbTexture = caps.ctxMajor > 2
930 || (caps.ctxMajor == 2 && caps.ctxMinor >= 1);
931 caps.srgbTextureFormat = hasCoreSrgbTexture
932 || ctx->hasExtension(
"GL_EXT_texture_sRGB");
933 caps.srgbGenerateMipmap = caps.srgbTextureFormat;
936 caps.srgbTextureRenderTarget = caps.ctxMajor >= 3;
942 QVarLengthArray<GLint, 16> compressedTextureFormats(n);
944 for (GLint format : compressedTextureFormats)
945 supportedCompressedFormats.insert(format);
958 std::array<QRhiTexture::Flags, 2> textureVariantFlags;
959 textureVariantFlags[0] = {};
960 textureVariantFlags[1] = QRhiTexture::sRGB;
961 if (
f->hasOpenGLExtension(QOpenGLExtensions::DDSTextureCompression)) {
962 for (QRhiTexture::Flags f : textureVariantFlags) {
963 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC1, f));
964 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC2, f));
965 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC3, f));
968 if (
f->hasOpenGLExtension(QOpenGLExtensions::ETC2TextureCompression)) {
969 for (QRhiTexture::Flags f : textureVariantFlags) {
970 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8, f));
971 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8A1, f));
972 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGBA8, f));
975 if (
f->hasOpenGLExtension(QOpenGLExtensions::ASTCTextureCompression)) {
976 for (QRhiTexture::Flags f : textureVariantFlags) {
977 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_4x4, f));
978 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x4, f));
979 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x5, f));
980 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x5, f));
981 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x6, f));
982 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x5, f));
983 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x6, f));
984 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x8, f));
985 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x5, f));
986 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x8, f));
987 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x10, f));
988 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x10, f));
989 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x12, f));
993 f->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.maxTextureSize);
995 if (!caps.gles || caps.ctxMajor >= 3) {
998 caps.hasDrawBuffersFunc =
true;
1000 caps.maxSamples = qMax(1, caps.maxSamples);
1003 caps.maxDrawBuffers = 1;
1004 caps.hasDrawBuffersFunc =
false;
1007 caps.maxSamples = 4;
1010 caps.msaaRenderBuffer = f->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
1011 && f->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
1013 caps.npotTextureFull = f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)
1014 && f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
1017 caps.fixedIndexPrimitiveRestart = caps.ctxMajor >= 3;
1019 caps.fixedIndexPrimitiveRestart = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1021 if (caps.fixedIndexPrimitiveRestart) {
1031 caps.bgraExternalFormat = f->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat);
1032 caps.bgraInternalFormat = caps.bgraExternalFormat && caps.gles;
1033 caps.r8Format = f->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats);
1036 caps.r32uiFormat = (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1)) && caps.r8Format;
1038 caps.r32uiFormat =
true;
1041 caps.imageLoadStore = caps.r32uiFormat;
1043 caps.imageLoadStore = (caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 2));
1045 caps.r16Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats);
1046 caps.floatFormats = caps.ctxMajor >= 3;
1047 caps.rgb10Formats = caps.ctxMajor >= 3;
1048 caps.depthTexture = caps.ctxMajor >= 3;
1049 caps.packedDepthStencil = f->hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil);
1051 caps.needsDepthStencilCombinedAttach =
true;
1053 caps.needsDepthStencilCombinedAttach =
false;
1061 caps.srgbWriteControl = ctx->hasExtension(
"GL_EXT_sRGB_write_control");
1063 const bool hasCoreSrgbWriteControl = caps.ctxMajor >= 3;
1064 caps.srgbWriteControl = hasCoreSrgbWriteControl
1065 || ctx->hasExtension(
"GL_ARB_framebuffer_sRGB")
1066 || ctx->hasExtension(
"GL_EXT_framebuffer_sRGB");
1069 caps.coreProfile = actualFormat.profile() == QSurfaceFormat::CoreProfile;
1074 caps.vertexArrayObject = caps.coreProfile || (caps.gles && caps.ctxMajor >= 3);
1077 caps.uniformBuffers = caps.ctxMajor >= 3;
1079 caps.uniformBuffers = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1081 caps.elementIndexUint = f->hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint);
1082 caps.depth24 = !caps.gles || f->hasOpenGLExtension(QOpenGLExtensions::Depth24);
1083 caps.rgba8Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized8Formats);
1086 caps.instancing = caps.ctxMajor >= 3;
1088 caps.instancing = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 3);
1090 caps.baseVertex = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1093 caps.compute = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1095 caps.compute = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1098 GLint ssboBindings = 0;
1102 caps.maxVertexStorageBuffers = qMin(blocks, ssboBindings);
1105 caps.maxFragmentStorageBuffers = qMin(blocks, ssboBindings);
1111 caps.maxThreadGroupsPerDimension = qMin(tgPerDim[0], qMin(tgPerDim[1], tgPerDim[2]));
1118 caps.depthClamp =
false;
1120 caps.depthClamp = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1121 if (!caps.depthClamp)
1122 caps.depthClamp = ctx->hasExtension(
"GL_EXT_depth_clamp") || ctx->hasExtension(
"GL_ARB_depth_clamp");
1125 caps.textureCompareMode = caps.ctxMajor >= 3;
1127 caps.textureCompareMode =
true;
1131 caps.properMapBuffer = f->hasOpenGLExtension(QOpenGLExtensions::MapBufferRange);
1134 caps.nonBaseLevelFramebufferTexture = caps.ctxMajor >= 3;
1136 caps.nonBaseLevelFramebufferTexture =
true;
1138 caps.texelFetch = caps.ctxMajor >= 3;
1139 caps.intAttributes = caps.ctxMajor >= 3;
1140 caps.screenSpaceDerivatives = f->hasOpenGLExtension(QOpenGLExtensions::StandardDerivatives);
1143 caps.multisampledTexture = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1145 caps.multisampledTexture = caps.ctxMajor >= 3;
1150 caps.programBinary = caps.ctxMajor >= 3;
1152 caps.programBinary = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 1);
1154 if (caps.programBinary) {
1158 caps.programBinary =
false;
1161 caps.texture3D = caps.ctxMajor >= 3;
1164 caps.texture1D =
false;
1166 caps.texture1D = glTexImage1D && (caps.ctxMajor >= 2);
1169 caps.tessellation = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1171 caps.tessellation = caps.ctxMajor >= 4;
1174 caps.geometryShader = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1176 caps.geometryShader = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1178 if (caps.ctxMajor >= 3) {
1179 GLint maxArraySize = 0;
1181 caps.maxTextureArraySize = maxArraySize;
1183 caps.maxTextureArraySize = 0;
1190 GLint maxVertexUniformVectors = 0;
1192 GLint maxFragmentUniformVectors = 0;
1194 caps.maxUniformVectors = qMin(maxVertexUniformVectors, maxFragmentUniformVectors);
1196 GLint maxVertexUniformComponents = 0;
1198 GLint maxFragmentUniformComponents = 0;
1200 caps.maxUniformVectors = qMin(maxVertexUniformComponents, maxFragmentUniformComponents) / 4;
1203 f->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.maxVertexInputs);
1207 }
else if (caps.ctxMajor >= 3) {
1208 GLint components = 0;
1210 caps.maxVertexOutputs = components / 4;
1214 GLint components = 0;
1217 caps.maxVertexOutputs = components / 4;
1222 if (!caps.coreProfile)
1229 if (!caps.gles && (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2)))
1232 caps.halfAttributes = f->hasOpenGLExtension(QOpenGLExtensions::HalfFloatVertex);
1235 caps.multiView = f->hasOpenGLExtension(QOpenGLExtensions::MultiView)
1236 && f->hasOpenGLExtension(QOpenGLExtensions::MultiViewExtended);
1237 if (caps.multiView) {
1238 glFramebufferTextureMultiviewOVR =
1239 reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei)>(
1240 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultiviewOVR")));
1244 caps.timestamps = !caps.gles && (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 3));
1245 if (caps.timestamps) {
1247 ctx->getProcAddress(QByteArrayLiteral(
"glQueryCounter")));
1248 glGetQueryObjectui64v =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLuint, GLenum, quint64 *)>(
1249 ctx->getProcAddress(QByteArrayLiteral(
"glGetQueryObjectui64v")));
1250 if (!glQueryCounter || !glGetQueryObjectui64v)
1251 caps.timestamps =
false;
1256 caps.objectLabel = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1258 caps.objectLabel = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1259 if (caps.objectLabel) {
1260 glObjectLabel =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLuint, GLsizei,
const GLchar *)>(
1261 ctx->getProcAddress(QByteArrayLiteral(
"glObjectLabel")));
1271 caps.glesMultisampleRenderToTexture = ctx->hasExtension(
"GL_EXT_multisampled_render_to_texture");
1272 if (caps.glesMultisampleRenderToTexture) {
1273 glFramebufferTexture2DMultisampleEXT =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei)>(
1274 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture2DMultisampleEXT")));
1275 glRenderbufferStorageMultisampleEXT =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)>(
1276 ctx->getProcAddress(QByteArrayLiteral(
"glRenderbufferStorageMultisampleEXT")));
1278 caps.glesMultiviewMultisampleRenderToTexture = ctx->hasExtension(
"GL_OVR_multiview_multisampled_render_to_texture");
1279 if (caps.glesMultiviewMultisampleRenderToTexture) {
1280 glFramebufferTextureMultisampleMultiviewOVR =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei)>(
1281 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultisampleMultiviewOVR")));
1284 caps.glesMultisampleRenderToTexture =
false;
1285 caps.glesMultiviewMultisampleRenderToTexture =
false;
1288 caps.unpackRowLength = !caps.gles || caps.ctxMajor >= 3;
1291 caps.perRenderTargetBlending = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1293 caps.perRenderTargetBlending = caps.ctxMajor >= 4;
1296 if (caps.ctxMajor == 3 && caps.ctxMinor < 2) {
1297 caps.sampleVariables = ctx->hasExtension(
"GL_OES_sample_variables");
1299 caps.sampleVariables = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1302 caps.sampleVariables = caps.ctxMajor >= 4;
1306 caps.drawIndirect = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1308 caps.drawIndirect = caps.ctxMajor >= 4;
1309 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_draw_indirect")))
1310 caps.drawIndirect =
true;
1318 caps.baseInstance =
false;
1320 caps.baseInstance = caps.instancing
1321 && (caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 2)
1322 || ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_base_instance")));
1325 if (caps.baseInstance) {
1326 glDrawArraysInstancedBaseInstance =
reinterpret_cast<
decltype(glDrawArraysInstancedBaseInstance)>(
1327 ctx->getProcAddress(QByteArrayLiteral(
"glDrawArraysInstancedBaseInstance")));
1328 glDrawElementsInstancedBaseInstance =
reinterpret_cast<
decltype(glDrawElementsInstancedBaseInstance)>(
1329 ctx->getProcAddress(QByteArrayLiteral(
"glDrawElementsInstancedBaseInstance")));
1330 glDrawElementsInstancedBaseVertexBaseInstance =
reinterpret_cast<
decltype(glDrawElementsInstancedBaseVertexBaseInstance)>(
1331 ctx->getProcAddress(QByteArrayLiteral(
"glDrawElementsInstancedBaseVertexBaseInstance")));
1335 qWarning(
"Failed to resolve glDraw{Arrays,Elements}InstancedBaseInstance{,BaseVertex}; disabling base instance support.");
1336 caps.baseInstance =
false;
1341 caps.drawIndirectMulti =
false;
1343 caps.drawIndirectMulti = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1344 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_multi_draw_indirect")) ||
1345 ctx->hasExtension(QByteArrayLiteral(
"GL_EXT_multi_draw_indirect")))
1346 caps.drawIndirectMulti =
true;
1348 if (caps.drawIndirectMulti) {
1349 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1350 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirect")));
1351 if (!glMultiDrawArraysIndirect)
1352 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1353 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectARB")));
1354 if (!glMultiDrawArraysIndirect)
1355 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1356 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectEXT")));
1357 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1358 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirect")));
1359 if (!glMultiDrawElementsIndirect)
1360 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1361 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectARB")));
1362 if (!glMultiDrawElementsIndirect)
1363 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1364 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectEXT")));
1366 qWarning(
"Failed to resolve glMultiDrawArraysIndirect or glMultiDrawElementsIndirect.");
1367 caps.drawIndirectMulti =
false;
1372 caps.shaderDrawParameters =
false;
1374 caps.shaderDrawParameters = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 6);
1375 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_shader_draw_parameters")))
1376 caps.shaderDrawParameters =
true;
1380 caps.dispatchIndirect = caps.compute;
1387 caps.copyBuffer = caps.ctxMajor >= 3;
1389 caps.copyBuffer = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1390 if (!caps.copyBuffer && ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_copy_buffer")))
1391 caps.copyBuffer = ctx->getProcAddress(QByteArrayLiteral(
"glCopyBufferSubData")) !=
nullptr;
1396 caps.drawIndirectCount =
false;
1398 caps.drawIndirectCount = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 6);
1399 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_indirect_parameters")))
1400 caps.drawIndirectCount =
true;
1402 if (caps.drawIndirectCount) {
1403 glMultiDrawArraysIndirectCount =
reinterpret_cast<
decltype(glMultiDrawArraysIndirectCount)>(
1404 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectCount")));
1405 if (!glMultiDrawArraysIndirectCount)
1406 glMultiDrawArraysIndirectCount =
reinterpret_cast<
decltype(glMultiDrawArraysIndirectCount)>(
1407 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectCountARB")));
1408 glMultiDrawElementsIndirectCount =
reinterpret_cast<
decltype(glMultiDrawElementsIndirectCount)>(
1409 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectCount")));
1410 if (!glMultiDrawElementsIndirectCount)
1411 glMultiDrawElementsIndirectCount =
reinterpret_cast<
decltype(glMultiDrawElementsIndirectCount)>(
1412 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectCountARB")));
1414 qWarning(
"Failed to resolve glMultiDrawArraysIndirectCount or glMultiDrawElementsIndirectCount.");
1415 caps.drawIndirectCount =
false;
1419 nativeHandlesStruct.context = ctx;
2974 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
2977 const bool isCompressed = isCompressedFormat(texD->m_format);
2978 const bool isCubeMap = texD->m_flags.testFlag(QRhiTexture::CubeMap);
2979 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2980 const bool is1D = texD->m_flags.testFlag(QRhiTexture::OneDimensional);
2981 const bool isArray = texD->m_flags.testFlag(QRhiTexture::TextureArray);
2983 const GLenum effectiveTarget = faceTargetBase + (isCubeMap ? uint(layer) : 0u);
2984 const QPoint dp = subresDesc.destinationTopLeft();
2985 const QByteArray rawData = subresDesc.data();
2987 auto setCmdByNotCompressedData = [&](
const void* data, QSize size, quint32 dataStride)
2989 quint32 bytesPerLine = 0;
2990 quint32 bytesPerPixel = 0;
2991 textureFormatInfo(texD->m_format, size, &bytesPerLine,
nullptr, &bytesPerPixel);
2995 cmd.args.subImage.target = texD->target;
2996 cmd.args.subImage.texture = texD->texture;
2997 cmd.args.subImage.faceTarget = effectiveTarget;
2998 cmd.args.subImage.level = level;
2999 cmd.args.subImage.dx = dp.x();
3000 cmd.args.subImage.dy = is1D && isArray ? layer : dp.y();
3001 cmd.args.subImage.dz = is3D || isArray ? layer : 0;
3002 cmd.args.subImage.w = size.width();
3003 cmd.args.subImage.h = size.height();
3004 cmd.args.subImage.glformat = texD->glformat;
3005 cmd.args.subImage.gltype = texD->gltype;
3007 if (dataStride == 0)
3008 dataStride = bytesPerLine;
3010 cmd.args.subImage.rowStartAlign = (dataStride & 3) ? 1 : 4;
3011 cmd.args.subImage.rowLength = caps.unpackRowLength ? (bytesPerPixel ? dataStride / bytesPerPixel : 0) : 0;
3013 cmd.args.subImage.data = data;
3016 if (!subresDesc.image().isNull()) {
3017 QImage img = subresDesc.image();
3018 QSize size = img.size();
3019 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
3020 const QPoint sp = subresDesc.sourceTopLeft();
3021 if (!subresDesc.sourceSize().isEmpty())
3022 size = subresDesc.sourceSize();
3023 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
3024 if (caps.unpackRowLength) {
3025 cbD->retainImage(img);
3027 const uchar *data = img.constBits() + sp.y() * img.bytesPerLine() + sp.x() * (qMax(1, img.depth() / 8));
3028 img = QImage(data, size.width(), size.height(), img.bytesPerLine(), img.format());
3030 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
3033 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
3036 setCmdByNotCompressedData(cbD->retainImage(img), size, img.bytesPerLine());
3037 }
else if (!rawData.isEmpty() && isCompressed) {
3038 const int depth = qMax(1, texD->m_depth);
3039 const int arraySize = qMax(0, texD->m_arraySize);
3040 if ((texD->flags().testFlag(QRhiTexture::UsedAsCompressedAtlas) || is3D || isArray)
3048 quint32 levelByteSize = 0;
3049 compressedFormatInfo(texD->m_format, texD->m_pixelSize,
nullptr, &levelByteSize,
nullptr);
3050 quint64 byteSize = levelByteSize;
3052 byteSize *= quint64(depth);
3054 byteSize *= quint64(arraySize);
3055 if (byteSize > quint64(
std::numeric_limits<
int>::max())) {
3056 qWarning(
"Compressed texture zero-initialization would need %llu bytes "
3057 "which is too large; skipping", byteSize);
3060 QByteArray zeroBuf(qsizetype(byteSize), 0);
3063 cmd.args.compressedImage.target = texD->target;
3064 cmd.args.compressedImage.texture = texD->texture;
3065 cmd.args.compressedImage.faceTarget = effectiveTarget;
3066 cmd.args.compressedImage.level = level;
3067 cmd.args.compressedImage.glintformat = texD->glintformat;
3068 cmd.args.compressedImage.w = texD->m_pixelSize.width();
3069 cmd.args.compressedImage.h = is1D && isArray ? arraySize : texD->m_pixelSize.height();
3070 cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
3071 cmd.args.compressedImage.size =
int(byteSize);
3072 cmd.args.compressedImage.data = cbD->retainData(zeroBuf);
3076 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
3077 : subresDesc.sourceSize();
3081 cmd.args.compressedSubImage.target = texD->target;
3082 cmd.args.compressedSubImage.texture = texD->texture;
3083 cmd.args.compressedSubImage.faceTarget = effectiveTarget;
3084 cmd.args.compressedSubImage.level = level;
3085 cmd.args.compressedSubImage.dx = dp.x();
3086 cmd.args.compressedSubImage.dy = is1D && isArray ? layer : dp.y();
3087 cmd.args.compressedSubImage.dz = is3D || isArray ? layer : 0;
3088 cmd.args.compressedSubImage.w = size.width();
3089 cmd.args.compressedSubImage.h = size.height();
3090 cmd.args.compressedSubImage.glintformat = texD->glintformat;
3091 cmd.args.compressedSubImage.size = rawData.size();
3092 cmd.args.compressedSubImage.data = cbD->retainData(rawData);
3096 cmd.args.compressedImage.target = texD->target;
3097 cmd.args.compressedImage.texture = texD->texture;
3098 cmd.args.compressedImage.faceTarget = effectiveTarget;
3099 cmd.args.compressedImage.level = level;
3100 cmd.args.compressedImage.glintformat = texD->glintformat;
3101 cmd.args.compressedImage.w = size.width();
3102 cmd.args.compressedImage.h = is1D && isArray ? arraySize : size.height();
3103 cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
3104 cmd.args.compressedImage.size = rawData.size();
3105 cmd.args.compressedImage.data = cbD->retainData(rawData);
3107 }
else if (!rawData.isEmpty()) {
3108 QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
3109 : subresDesc.sourceSize();
3110 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
3111 quint32 bytesPerPixel = 0;
3112 textureFormatInfo(texD->m_format, size,
nullptr,
nullptr, &bytesPerPixel);
3113 size = clampedSubResourceUploadSizeForSourceData(size, subresDesc.dataStride(),
3114 bytesPerPixel, rawData.size());
3118 setCmdByNotCompressedData(cbD->retainData(rawData), size, subresDesc.dataStride());
3120 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
3678 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
3682 if (cmd.args.beginFrame.timestampQuery)
3684 if (caps.vertexArrayObject) {
3686 f->glGenVertexArrays(1, &vao);
3687 f->glBindVertexArray(vao);
3694 f->glVertexAttribDivisor(GLuint(i), 0);
3697 f->glVertexAttribDivisor(GLuint(i), 0);
3704 f->glDisableVertexAttribArray(GLuint(i));
3709 f->glBindVertexArray(0);
3710 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
3711 if (cmd.args.endFrame.timestampQuery)
3716 f->glBindVertexArray(vao);
3719 f->glViewport(GLint(cmd.args.viewport.x), GLint(cmd.args.viewport.y), GLsizei(cmd.args.viewport.w), GLsizei(cmd.args.viewport.h));
3720 f->glDepthRangef(cmd.args.viewport.d0, cmd.args.viewport.d1);
3723 f->glScissor(cmd.args.scissor.x, cmd.args.scissor.y, cmd.args.scissor.w, cmd.args.scissor.h);
3726 f->glBlendColor(cmd.args.blendConstants.r, cmd.args.blendConstants.g, cmd.args.blendConstants.b, cmd.args.blendConstants.a);
3732 const GLint ref = GLint(cmd.args.stencilRef.ref);
3733 f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), ref, psD->m_stencilReadMask);
3734 f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), ref, psD->m_stencilReadMask);
3735 cbD->graphicsPassState.dynamic.stencilRef = ref;
3737 qWarning(
"No graphics pipeline active for setStencilRef; ignored");
3745 if (state.lastBindVertexBuffer.ps == psD
3746 && state.lastBindVertexBuffer.buffer == cmd.args.bindVertexBuffer.buffer
3747 && state.lastBindVertexBuffer.offset == cmd.args.bindVertexBuffer.offset
3748 && state.lastBindVertexBuffer.binding == cmd.args.bindVertexBuffer.binding)
3755 state.lastBindVertexBuffer.ps = psD;
3756 state.lastBindVertexBuffer.buffer = cmd.args.bindVertexBuffer.buffer;
3757 state.lastBindVertexBuffer.offset = cmd.args.bindVertexBuffer.offset;
3758 state.lastBindVertexBuffer.binding = cmd.args.bindVertexBuffer.binding;
3760 if (cmd.args.bindVertexBuffer.buffer != state.currentArrayBuffer) {
3761 state.currentArrayBuffer = cmd.args.bindVertexBuffer.buffer;
3763 f->glBindBuffer(GL_ARRAY_BUFFER, state.currentArrayBuffer);
3765 for (
auto it = psD->m_vertexInputLayout.cbeginAttributes(), itEnd = psD->m_vertexInputLayout.cendAttributes();
3768 const int bindingIdx = it->binding();
3769 if (bindingIdx != cmd.args.bindVertexBuffer.binding)
3772 const QRhiVertexInputBinding *inputBinding = psD->m_vertexInputLayout.bindingAt(bindingIdx);
3773 const int stride =
int(inputBinding->stride());
3776 bool normalize =
false;
3777 switch (it->format()) {
3778 case QRhiVertexInputAttribute::Float4:
3782 case QRhiVertexInputAttribute::Float3:
3786 case QRhiVertexInputAttribute::Float2:
3790 case QRhiVertexInputAttribute::Float:
3794 case QRhiVertexInputAttribute::UNormByte4:
3799 case QRhiVertexInputAttribute::UNormByte2:
3804 case QRhiVertexInputAttribute::UNormByte:
3809 case QRhiVertexInputAttribute::UInt4:
3810 type = GL_UNSIGNED_INT;
3813 case QRhiVertexInputAttribute::UInt3:
3814 type = GL_UNSIGNED_INT;
3817 case QRhiVertexInputAttribute::UInt2:
3818 type = GL_UNSIGNED_INT;
3821 case QRhiVertexInputAttribute::UInt:
3822 type = GL_UNSIGNED_INT;
3825 case QRhiVertexInputAttribute::SInt4:
3829 case QRhiVertexInputAttribute::SInt3:
3833 case QRhiVertexInputAttribute::SInt2:
3837 case QRhiVertexInputAttribute::SInt:
3841 case QRhiVertexInputAttribute::Half4:
3845 case QRhiVertexInputAttribute::Half3:
3849 case QRhiVertexInputAttribute::Half2:
3853 case QRhiVertexInputAttribute::Half:
3857 case QRhiVertexInputAttribute::UShort4:
3858 type = GL_UNSIGNED_SHORT;
3861 case QRhiVertexInputAttribute::UShort3:
3862 type = GL_UNSIGNED_SHORT;
3865 case QRhiVertexInputAttribute::UShort2:
3866 type = GL_UNSIGNED_SHORT;
3869 case QRhiVertexInputAttribute::UShort:
3870 type = GL_UNSIGNED_SHORT;
3873 case QRhiVertexInputAttribute::SShort4:
3877 case QRhiVertexInputAttribute::SShort3:
3881 case QRhiVertexInputAttribute::SShort2:
3885 case QRhiVertexInputAttribute::SShort:
3893 const int locationIdx = it->location();
3894 quint32 ofs = it->offset() + cmd.args.bindVertexBuffer.offset;
3895 if (type == GL_UNSIGNED_INT || type == GL_INT) {
3896 if (caps.intAttributes) {
3897 f->glVertexAttribIPointer(GLuint(locationIdx), size, type, stride,
3898 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3900 qWarning(
"Current RHI backend does not support IntAttributes. Check supported features.");
3906 f->glVertexAttribPointer(GLuint(locationIdx), size, type, normalize, stride,
3907 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3912 f->glEnableVertexAttribArray(GLuint(locationIdx));
3914 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance && caps.instancing) {
3915 f->glVertexAttribDivisor(GLuint(locationIdx), inputBinding->instanceStepRate());
3926 f->glVertexAttribDivisor(GLuint(locationIdx), 0);
3932 qWarning(
"No graphics pipeline active for setVertexInput; ignored");
3937 state.indexType = cmd.args.bindIndexBuffer.type;
3938 state.indexStride = state.indexType == GL_UNSIGNED_SHORT ?
sizeof(quint16) :
sizeof(quint32);
3939 state.indexOffset = cmd.args.bindIndexBuffer.offset;
3940 if (state.currentElementArrayBuffer != cmd.args.bindIndexBuffer.buffer) {
3941 state.currentElementArrayBuffer = cmd.args.bindIndexBuffer.buffer;
3942 f->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state.currentElementArrayBuffer);
3949 const bool useBaseInstance = (cmd.args.draw.baseInstance != 0 && caps.baseInstance);
3951 const bool needsInstancedPath = caps.instancing
3952 && (cmd.args.draw.instanceCount != 1 || useBaseInstance);
3954 if (!needsInstancedPath) {
3955 f->glDrawArrays(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount));
3956 }
else if (useBaseInstance) {
3958 GLint(cmd.args.draw.firstVertex)
,
3959 GLsizei(cmd.args.draw.vertexCount)
,
3960 GLsizei(cmd.args.draw.instanceCount)
,
3961 cmd.args.draw.baseInstance
);
3963 f->glDrawArraysInstanced(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount),
3964 GLsizei(cmd.args.draw.instanceCount));
3967 qWarning(
"No graphics pipeline active for draw; ignored");
3975 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3976 quintptr(cmd.args.drawIndexed.firstIndex * state.indexStride + state.indexOffset));
3977 const bool useBaseVertex = (cmd.args.drawIndexed.baseVertex != 0 && caps.baseVertex);
3978 const bool useBaseInstance = (cmd.args.drawIndexed.baseInstance != 0 && caps.baseInstance);
3982 const bool needsInstancedPath = caps.instancing
3983 && (cmd.args.drawIndexed.instanceCount != 1 || useBaseInstance);
3985 if (!needsInstancedPath) {
3986 if (useBaseVertex) {
3987 f->glDrawElementsBaseVertex(psD->drawMode,
3988 GLsizei(cmd.args.drawIndexed.indexCount),
3991 cmd.args.drawIndexed.baseVertex);
3993 f->glDrawElements(psD->drawMode,
3994 GLsizei(cmd.args.drawIndexed.indexCount),
3998 }
else if (useBaseInstance && useBaseVertex) {
4000 GLsizei(cmd.args.drawIndexed.indexCount)
,
4003 GLsizei(cmd.args.drawIndexed.instanceCount)
,
4004 cmd.args.drawIndexed.baseVertex
,
4005 cmd.args.drawIndexed.baseInstance
);
4006 }
else if (useBaseInstance) {
4008 GLsizei(cmd.args.drawIndexed.indexCount)
,
4011 GLsizei(cmd.args.drawIndexed.instanceCount)
,
4012 cmd.args.drawIndexed.baseInstance
);
4013 }
else if (useBaseVertex) {
4014 f->glDrawElementsInstancedBaseVertex(psD->drawMode,
4015 GLsizei(cmd.args.drawIndexed.indexCount),
4018 GLsizei(cmd.args.drawIndexed.instanceCount),
4019 cmd.args.drawIndexed.baseVertex);
4021 f->glDrawElementsInstanced(psD->drawMode,
4022 GLsizei(cmd.args.drawIndexed.indexCount),
4025 GLsizei(cmd.args.drawIndexed.instanceCount));
4028 qWarning(
"No graphics pipeline active for drawIndexed; ignored");
4038 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4039 quintptr(cmd.args.drawIndirect.offset));
4042 cmd.args.drawIndirect.drawCount
,
4043 cmd.args.drawIndirect.stride
);
4045 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
4046 const quintptr indirectOffset = quintptr(cmd.args.drawIndirect.offset)
4047 + quintptr(i) * cmd.args.drawIndirect.stride;
4048 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(indirectOffset);
4049 f->glDrawArraysIndirect(psD->drawMode,
4055 qWarning(
"No graphics pipeline active for drawIndirect; ignored");
4065 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4066 quintptr(cmd.args.drawIndexedIndirect.offset));
4070 cmd.args.drawIndexedIndirect.drawCount
,
4071 cmd.args.drawIndexedIndirect.stride
);
4073 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
4074 const quintptr indirectOffset = quintptr(cmd.args.drawIndexedIndirect.offset)
4075 + quintptr(i) * cmd.args.drawIndexedIndirect.stride;
4076 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(indirectOffset);
4077 f->glDrawElementsIndirect(psD->drawMode,
4084 qWarning(
"No graphics pipeline active for drawIndexedIndirect; ignored");
4094 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4095 quintptr(cmd.args.drawIndirectCount.offset));
4098 GLintptr(cmd.args.drawIndirectCount.countOffset)
,
4099 cmd.args.drawIndirectCount.maxDrawCount
,
4100 cmd.args.drawIndirectCount.stride
);
4104 qWarning(
"No graphics pipeline active or glMultiDrawArraysIndirectCount unavailable; ignored");
4114 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4115 quintptr(cmd.args.drawIndexedIndirectCount.offset));
4119 GLintptr(cmd.args.drawIndexedIndirectCount.countOffset)
,
4120 cmd.args.drawIndexedIndirectCount.maxDrawCount
,
4121 cmd.args.drawIndexedIndirectCount.stride
);
4125 qWarning(
"No graphics pipeline active or glMultiDrawElementsIndirectCount unavailable; ignored");
4132 case QGles2CommandBuffer::Command::BindShaderResources:
4133 bindShaderResources(cbD,
4134 cmd.args.bindShaderResources.maybeGraphicsPs,
4135 cmd.args.bindShaderResources.maybeComputePs,
4136 cmd.args.bindShaderResources.srb,
4137 cbD->dynamicOffsetPool.constData() + cmd.args.bindShaderResources.dynamicOffsetPoolOffset,
4138 cmd.args.bindShaderResources.dynamicOffsetCount);
4142 QRhiGraphicsPipeline *maybeGraphicsPs = cmd.args.setPushConstants.maybeGraphicsPs;
4143 QRhiComputePipeline *maybeComputePs = cmd.args.setPushConstants.maybeComputePs;
4144 const QGles2UniformDescriptionVector &uniforms(maybeGraphicsPs
4145 ?
QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->pushConstantUniforms
4146 :
QRHI_RES(QGles2ComputePipeline, maybeComputePs)->pushConstantUniforms);
4148 ?
QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->uniformState.data()
4149 :
QRHI_RES(QGles2ComputePipeline, maybeComputePs)->uniformState.data();
4150 setUniformsFromBlock(uniforms, -1,
4151 cbD->pushConstantPool.constData() + cmd.args.setPushConstants.dataOffset,
4152 cmd.args.setPushConstants.size, 0, uniformState);
4157 QVarLengthArray<GLenum, 8> bufs;
4158 GLuint fbo = cmd.args.bindFramebuffer.fbo;
4160 fbo = ctx->defaultFramebufferObject();
4161 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4163 const int colorAttCount = cmd.args.bindFramebuffer.colorAttCount;
4164 bufs.append(colorAttCount > 0 ? GL_COLOR_ATTACHMENT0 : GL_NONE);
4165 if (caps.maxDrawBuffers > 1) {
4166 for (
int i = 1; i < colorAttCount; ++i)
4167 bufs.append(GL_COLOR_ATTACHMENT0 + uint(i));
4170 if (cmd.args.bindFramebuffer.stereo && cmd.args.bindFramebuffer.stereoTarget == QRhiSwapChain::RightBuffer)
4175 if (caps.hasDrawBuffersFunc)
4176 f->glDrawBuffers(bufs.count(), bufs.constData());
4177 if (caps.srgbWriteControl) {
4178 if (cmd.args.bindFramebuffer.srgb)
4186 f->glDisable(GL_SCISSOR_TEST);
4187 if (cmd.args.clear.mask & GL_COLOR_BUFFER_BIT) {
4188 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4189 f->glClearColor(cmd.args.clear.c[0], cmd.args.clear.c[1], cmd.args.clear.c[2], cmd.args.clear.c[3]);
4191 if (cmd.args.clear.mask & GL_DEPTH_BUFFER_BIT) {
4192 f->glDepthMask(GL_TRUE);
4193 f->glClearDepthf(cmd.args.clear.d);
4195 if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT) {
4196 f->glStencilMask(0xFF);
4197 f->glClearStencil(GLint(cmd.args.clear.s));
4199 f->glClear(cmd.args.clear.mask);
4200 cbD->graphicsPassState.reset();
4203 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.bufferSubData.target, cmd.args.bufferSubData.buffer);
4204 f->glBufferSubData(cmd.args.bufferSubData.target, cmd.args.bufferSubData.offset, cmd.args.bufferSubData.size,
4205 cmd.args.bufferSubData.data);
4209 QRhiReadbackResult *result = cmd.args.getBufferSubData.result;
4210 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.getBufferSubData.target, cmd.args.getBufferSubData.buffer);
4212 if (caps.properMapBuffer) {
4213 void *p =
f->glMapBufferRange(cmd.args.getBufferSubData.target,
4214 cmd.args.getBufferSubData.offset,
4215 cmd.args.getBufferSubData.size,
4218 result->data.resize(cmd.args.getBufferSubData.size);
4219 memcpy(result->data.data(), p, size_t(cmd.args.getBufferSubData.size));
4220 f->glUnmapBuffer(cmd.args.getBufferSubData.target);
4224 result->data.resize(cmd.args.getBufferSubData.size);
4225 f->glGetBufferSubData(cmd.args.getBufferSubData.target,
4226 cmd.args.getBufferSubData.offset,
4227 cmd.args.getBufferSubData.size,
4228 result->data.data());
4230 if (result->completed)
4231 result->completed();
4238 cmd.args.copyBuf.srcOffset, cmd.args.copyBuf.dstOffset,
4239 cmd.args.copyBuf.size);
4246 f->glGenFramebuffers(1, &fbo);
4247 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4251 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.copyTex.srcTexture,
4252 cmd.args.copyTex.srcLevel, cmd.args.copyTex.srcZ);
4255 cmd.args.copyTex.srcTarget, cmd.args.copyTex.srcTexture,
4256 cmd.args.copyTex.srcLevel);
4258 f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4259 cmd.args.copyTex.srcFaceTarget, cmd.args.copyTex.srcTexture, cmd.args.copyTex.srcLevel);
4261 f->glBindTexture(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstTexture);
4263 f->glCopyTexSubImage3D(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstLevel,
4264 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY, cmd.args.copyTex.dstZ,
4265 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
4266 cmd.args.copyTex.w, cmd.args.copyTex.h);
4269 cmd.args.copyTex.dstX
, cmd.args.copyTex.srcX
,
4270 cmd.args.copyTex.srcY
, cmd.args.copyTex.w
);
4272 f->glCopyTexSubImage2D(cmd.args.copyTex.dstFaceTarget, cmd.args.copyTex.dstLevel,
4273 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY,
4274 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
4275 cmd.args.copyTex.w, cmd.args.copyTex.h);
4277 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4278 f->glDeleteFramebuffers(1, &fbo);
4283 QRhiReadbackResult *result = cmd.args.readPixels.result;
4284 GLuint tex = cmd.args.readPixels.texture;
4287 result->pixelSize = QSize(cmd.args.readPixels.w, cmd.args.readPixels.h);
4289 result->format = cmd.args.readPixels.format;
4290 mipLevel = cmd.args.readPixels.level;
4291 if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
4292 f->glGenFramebuffers(1, &fbo);
4293 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4294 if (cmd.args.readPixels.slice3D >= 0) {
4295 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4296 tex, mipLevel, cmd.args.readPixels.slice3D);
4297 }
else if (cmd.args.readPixels.readTarget ==
GL_TEXTURE_1D) {
4299 cmd.args.readPixels.readTarget, tex, mipLevel);
4301 f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4302 cmd.args.readPixels.readTarget, tex, mipLevel);
4306 result->format = QRhiTexture::RGBA8;
4309 const int x = cmd.args.readPixels.x;
4310 const int y = cmd.args.readPixels.y;
4311 const int w = cmd.args.readPixels.w;
4312 const int h = cmd.args.readPixels.h;
4313 if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
4316 if (result->format == QRhiTexture::R8 || result->format == QRhiTexture::RED_OR_ALPHA8) {
4317 result->data.resizeForOverwrite(w * h);
4319 tmpBuf.resizeForOverwrite(w * h * 4);
4321 const quint8 *srcBase =
reinterpret_cast<
const quint8 *>(tmpBuf.constData());
4322 quint8 *dstBase =
reinterpret_cast<quint8 *>(result->data.data());
4323 const int componentIndex = result->format == QRhiTexture::R8
4324 || isFeatureSupported(QRhi::RedOrAlpha8IsRed)
4327 for (
int y = 0; y < h; ++y) {
4328 const quint8 *src = srcBase + y * w * 4;
4329 quint8 *dst = dstBase + y * w;
4331 while (count-- > 0) {
4332 *dst++ = src[componentIndex];
4339 [[maybe_unused]] GLenum glintformat;
4340 [[maybe_unused]] GLenum glsizedintformat;
4343 toGlTextureFormat(result->format, {}, caps,
4344 &glintformat, &glsizedintformat, &glformat, &gltype);
4346 textureFormatInfo(result->format, result->pixelSize,
nullptr, &byteSize,
nullptr);
4347 result->data.resizeForOverwrite(byteSize);
4348 f->glReadPixels(x, y, w, h, glformat, gltype, result->data.data());
4352 quint32 byteSize = 0;
4353 textureFormatInfo(result->format, result->pixelSize,
nullptr, &byteSize,
nullptr);
4354 result->data.fill(
'\0', byteSize);
4357 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4358 f->glDeleteFramebuffers(1, &fbo);
4360 if (result->completed)
4361 result->completed();
4365 f->glBindTexture(cmd.args.subImage.target, cmd.args.subImage.texture);
4366 if (cmd.args.subImage.rowStartAlign != 4)
4367 f->glPixelStorei(GL_UNPACK_ALIGNMENT, cmd.args.subImage.rowStartAlign);
4368 if (cmd.args.subImage.rowLength != 0)
4371 f->glTexSubImage3D(cmd.args.subImage.target, cmd.args.subImage.level,
4372 cmd.args.subImage.dx, cmd.args.subImage.dy, cmd.args.subImage.dz,
4373 cmd.args.subImage.w, cmd.args.subImage.h, 1,
4374 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
4375 cmd.args.subImage.data);
4378 cmd.args.subImage.dx
, cmd.args.subImage.w
,
4379 cmd.args.subImage.glformat
, cmd.args.subImage.gltype
,
4380 cmd.args.subImage.data
);
4382 f->glTexSubImage2D(cmd.args.subImage.faceTarget, cmd.args.subImage.level,
4383 cmd.args.subImage.dx, cmd.args.subImage.dy,
4384 cmd.args.subImage.w, cmd.args.subImage.h,
4385 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
4386 cmd.args.subImage.data);
4388 if (cmd.args.subImage.rowStartAlign != 4)
4389 f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
4390 if (cmd.args.subImage.rowLength != 0)
4394 f->glBindTexture(cmd.args.compressedImage.target, cmd.args.compressedImage.texture);
4396 f->glCompressedTexImage3D(cmd.args.compressedImage.target, cmd.args.compressedImage.level,
4397 cmd.args.compressedImage.glintformat,
4398 cmd.args.compressedImage.w, cmd.args.compressedImage.h, cmd.args.compressedImage.depth,
4399 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
4400 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
4402 cmd.args.compressedImage.target
, cmd.args.compressedImage.level
,
4403 cmd.args.compressedImage.glintformat
, cmd.args.compressedImage.w
, 0
,
4404 cmd.args.compressedImage.size
, cmd.args.compressedImage.data
);
4406 f->glCompressedTexImage2D(cmd.args.compressedImage.faceTarget, cmd.args.compressedImage.level,
4407 cmd.args.compressedImage.glintformat,
4408 cmd.args.compressedImage.w, cmd.args.compressedImage.h,
4409 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
4413 f->glBindTexture(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.texture);
4415 f->glCompressedTexSubImage3D(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.level,
4416 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy, cmd.args.compressedSubImage.dz,
4417 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h, 1,
4418 cmd.args.compressedSubImage.glintformat,
4419 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
4420 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
4422 cmd.args.compressedSubImage.target
, cmd.args.compressedSubImage.level
,
4423 cmd.args.compressedSubImage.dx
, cmd.args.compressedSubImage.w
,
4424 cmd.args.compressedSubImage.glintformat
, cmd.args.compressedSubImage.size
,
4425 cmd.args.compressedSubImage.data
);
4427 f->glCompressedTexSubImage2D(cmd.args.compressedSubImage.faceTarget, cmd.args.compressedSubImage.level,
4428 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy,
4429 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h,
4430 cmd.args.compressedSubImage.glintformat,
4431 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
4438 cbD->graphicsPassState.reset();
4439 f->glDisable(GL_SCISSOR_TEST);
4441 f->glGenFramebuffers(2, fbo);
4443 const bool ds = cmd.args.blitFromRenderbuffer.isDepthStencil;
4444 const bool hasStencil = ds && cmd.args.blitFromRenderbuffer.hasStencil;
4447 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4450 const GLuint srcStencilRb = cmd.args.blitFromRenderbuffer.stencilRenderbuffer
4451 ? cmd.args.blitFromRenderbuffer.stencilRenderbuffer
4452 : cmd.args.blitFromRenderbuffer.renderbuffer;
4454 GL_RENDERBUFFER, srcStencilRb);
4458 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4464 cmd.args.blitFromRenderbuffer.dstTexture,
4465 cmd.args.blitFromRenderbuffer.dstLevel,
4466 cmd.args.blitFromRenderbuffer.dstLayer);
4469 cmd.args.blitFromRenderbuffer.dstTexture,
4470 cmd.args.blitFromRenderbuffer.dstLevel,
4471 cmd.args.blitFromRenderbuffer.dstLayer);
4475 cmd.args.blitFromRenderbuffer.dstTexture,
4476 cmd.args.blitFromRenderbuffer.dstLevel,
4477 cmd.args.blitFromRenderbuffer.dstLayer);
4481 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
4482 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4484 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
4485 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4488 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromRenderbuffer.target,
4489 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4492 if (ds && !caps.gles) {
4493 f->glReadBuffer(GL_NONE);
4494 const GLenum noBuf = GL_NONE;
4495 f->glDrawBuffers(1, &noBuf);
4497 const GLbitfield rbBlitMask = ds ? (GL_DEPTH_BUFFER_BIT | (hasStencil ? GL_STENCIL_BUFFER_BIT : 0))
4498 : GL_COLOR_BUFFER_BIT;
4499 f->glBlitFramebuffer(0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
4500 0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
4503 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4504 f->glDeleteFramebuffers(2, fbo);
4511 cbD->graphicsPassState.reset();
4512 f->glDisable(GL_SCISSOR_TEST);
4514 f->glGenFramebuffers(2, fbo);
4516 const bool ds = cmd.args.blitFromTexture.isDepthStencil;
4517 const bool hasStencil = ds && cmd.args.blitFromTexture.hasStencil;
4521 cmd.args.blitFromTexture.srcTexture,
4522 cmd.args.blitFromTexture.srcLevel,
4523 cmd.args.blitFromTexture.srcLayer);
4526 cmd.args.blitFromTexture.srcTexture,
4527 cmd.args.blitFromTexture.srcLevel,
4528 cmd.args.blitFromTexture.srcLayer);
4532 cmd.args.blitFromTexture.srcTexture,
4533 cmd.args.blitFromTexture.srcLevel,
4534 cmd.args.blitFromTexture.srcLayer);
4538 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
4539 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4541 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
4542 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4545 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.srcTarget,
4546 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4553 cmd.args.blitFromTexture.dstTexture,
4554 cmd.args.blitFromTexture.dstLevel,
4555 cmd.args.blitFromTexture.dstLayer);
4558 cmd.args.blitFromTexture.dstTexture,
4559 cmd.args.blitFromTexture.dstLevel,
4560 cmd.args.blitFromTexture.dstLayer);
4564 cmd.args.blitFromTexture.dstTexture,
4565 cmd.args.blitFromTexture.dstLevel,
4566 cmd.args.blitFromTexture.dstLayer);
4570 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
4571 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4573 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
4574 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4577 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.dstTarget,
4578 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4581 if (ds && !caps.gles) {
4582 f->glReadBuffer(GL_NONE);
4583 const GLenum noBuf = GL_NONE;
4584 f->glDrawBuffers(1, &noBuf);
4586 const GLbitfield texBlitMask = ds ? (GL_DEPTH_BUFFER_BIT | (hasStencil ? GL_STENCIL_BUFFER_BIT : 0))
4587 : GL_COLOR_BUFFER_BIT;
4588 f->glBlitFramebuffer(0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
4589 0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
4592 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4593 f->glDeleteFramebuffers(2, fbo);
4597 f->glBindTexture(cmd.args.genMip.target, cmd.args.genMip.texture);
4598 f->glGenerateMipmap(cmd.args.genMip.target);
4603 f->glUseProgram(psD->program);
4607 f->glDispatchCompute(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
4612 f->glDispatchComputeIndirect(GLintptr(cmd.args.dispatchIndirect.offset));
4620 GLbitfield barriers = 0;
4629 for (
const auto &[rhiB, trackedB]: tracker.buffers()) {
4631 QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(trackedB.stateAtPassBegin.access);
4632 if (bufferAccessIsWrite(accessBeforePass))
4633 barriers |= barriersForBuffer();
4635 for (
const auto &[rhiT, trackedT]: tracker.textures()) {
4637 QGles2Texture::Access accessBeforePass = QGles2Texture::Access(trackedT.stateAtPassBegin.access);
4638 if (textureAccessIsWrite(accessBeforePass))
4639 barriers |= barriersForTexture();
4642 f->glMemoryBarrier(barriers);
4647 f->glMemoryBarrier(cmd.args.barrier.barriers);
4650 if (caps.gles && caps.ctxMajor >= 3) {
4651 f->glBindFramebuffer(GL_FRAMEBUFFER, cmd.args.invalidateFramebuffer.fbo);
4653 cmd.args.invalidateFramebuffer.attCount,
4654 cmd.args.invalidateFramebuffer.att);
4664 f->glVertexAttribDivisor(GLuint(i), 0);
4667 f->glVertexAttribDivisor(GLuint(i), 0);
4674 const bool forceUpdate = !state
.valid;
4677 const bool scissor = psD->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor);
4678 if (forceUpdate || scissor != state
.scissor) {
4681 f->glEnable(GL_SCISSOR_TEST);
4683 f->glDisable(GL_SCISSOR_TEST);
4686 const bool cullFace = psD->m_cullMode != QRhiGraphicsPipeline::None;
4687 const GLenum cullMode = cullFace ? toGlCullMode(psD->m_cullMode) : GL_NONE;
4688 if (forceUpdate || cullFace != state
.cullFace || cullMode != state.cullMode) {
4690 state.cullMode = cullMode;
4692 f->glEnable(GL_CULL_FACE);
4693 f->glCullFace(cullMode);
4695 f->glDisable(GL_CULL_FACE);
4699 const GLenum frontFace = toGlFrontFace(psD->m_frontFace);
4700 if (forceUpdate || frontFace != state.frontFace) {
4701 state.frontFace = frontFace;
4702 f->glFrontFace(frontFace);
4705 const GLenum polygonMode = toGlPolygonMode(psD->m_polygonMode);
4706 if (
glPolygonMode && (forceUpdate || polygonMode != state.polygonMode)) {
4707 state.polygonMode = polygonMode;
4711 if (!psD->m_targetBlends.isEmpty()) {
4713 bool anyBlendEnabled =
false;
4714 for (
const auto targetBlend : psD->m_targetBlends) {
4715 const QGles2CommandBuffer::GraphicsPassState::ColorMask colorMask = {
4716 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::R),
4717 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::G),
4718 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::B),
4719 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::A)
4721 if (forceUpdate || colorMask != state.colorMask[buffer]) {
4722 state.colorMask[buffer] = colorMask;
4723 if (caps.perRenderTargetBlending)
4724 f->glColorMaski(buffer, colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4726 f->glColorMask(colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4729 const bool blendEnabled = targetBlend.enable;
4730 const QGles2CommandBuffer::GraphicsPassState::Blend blend = {
4731 toGlBlendFactor(targetBlend.srcColor),
4732 toGlBlendFactor(targetBlend.dstColor),
4733 toGlBlendFactor(targetBlend.srcAlpha),
4734 toGlBlendFactor(targetBlend.dstAlpha),
4735 toGlBlendOp(targetBlend.opColor),
4736 toGlBlendOp(targetBlend.opAlpha)
4738 anyBlendEnabled |= blendEnabled;
4739 if (forceUpdate || blendEnabled != state.blendEnabled[buffer] || (blendEnabled && blend != state.blend[buffer])) {
4740 state.blendEnabled[buffer] = blendEnabled;
4742 state.blend[buffer] = blend;
4743 if (caps.perRenderTargetBlending) {
4744 f->glBlendFuncSeparatei(buffer, blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4745 f->glBlendEquationSeparatei(buffer, blend.opColor, blend.opAlpha);
4747 f->glBlendFuncSeparate(blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4748 f->glBlendEquationSeparate(blend.opColor, blend.opAlpha);
4753 if (!caps.perRenderTargetBlending)
4756 if (anyBlendEnabled)
4757 f->glEnable(GL_BLEND);
4759 f->glDisable(GL_BLEND);
4762 if (forceUpdate || colorMask
!= state.colorMask[0]) {
4763 state.colorMask[0] = colorMask;
4764 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4766 const bool blendEnabled =
false;
4769 f->glDisable(GL_BLEND);
4773 const bool depthTest = psD->m_depthTest;
4774 if (forceUpdate || depthTest != state
.depthTest) {
4777 f->glEnable(GL_DEPTH_TEST);
4779 f->glDisable(GL_DEPTH_TEST);
4782 const bool depthWrite = psD->m_depthWrite;
4783 if (forceUpdate || depthWrite != state
.depthWrite) {
4785 f->glDepthMask(depthWrite);
4788 const bool depthClamp = psD->m_depthClamp;
4789 if (caps.depthClamp && (forceUpdate || depthClamp != state.depthClamp)) {
4797 const GLenum depthFunc = toGlCompareOp(psD->m_depthOp);
4798 if (forceUpdate || depthFunc != state.depthFunc) {
4799 state.depthFunc = depthFunc;
4800 f->glDepthFunc(depthFunc);
4803 const bool stencilTest = psD->m_stencilTest;
4804 const GLuint stencilReadMask = psD->m_stencilReadMask;
4805 const GLuint stencilWriteMask = psD->m_stencilWriteMask;
4807 toGlCompareOp(psD->m_stencilFront.compareOp),
4808 toGlStencilOp(psD->m_stencilFront.failOp),
4809 toGlStencilOp(psD->m_stencilFront.depthFailOp),
4810 toGlStencilOp(psD->m_stencilFront.passOp)
4813 toGlCompareOp(psD->m_stencilBack.compareOp),
4814 toGlStencilOp(psD->m_stencilBack.failOp),
4815 toGlStencilOp(psD->m_stencilBack.depthFailOp),
4816 toGlStencilOp(psD->m_stencilBack.passOp)
4820 && (stencilReadMask != state.stencilReadMask || stencilWriteMask != state.stencilWriteMask
4821 || stencilFront != state.stencil[0] || stencilBack != state.stencil[1])))
4825 state.stencilReadMask = stencilReadMask;
4826 state.stencilWriteMask = stencilWriteMask;
4827 state.stencil[0] = stencilFront;
4828 state.stencil[1] = stencilBack;
4830 f->glEnable(GL_STENCIL_TEST);
4832 f->glStencilFuncSeparate(GL_FRONT, stencilFront.func, state.dynamic.stencilRef, stencilReadMask);
4833 f->glStencilOpSeparate(GL_FRONT, stencilFront.failOp, stencilFront.zfailOp, stencilFront.zpassOp);
4834 f->glStencilMaskSeparate(GL_FRONT, stencilWriteMask);
4836 f->glStencilFuncSeparate(GL_BACK, stencilBack.func, state.dynamic.stencilRef, stencilReadMask);
4837 f->glStencilOpSeparate(GL_BACK, stencilBack.failOp, stencilBack.zfailOp, stencilBack.zpassOp);
4838 f->glStencilMaskSeparate(GL_BACK, stencilWriteMask);
4840 f->glDisable(GL_STENCIL_TEST);
4844 const bool polyOffsetFill = psD->m_depthBias != 0 || !qFuzzyIsNull(psD->m_slopeScaledDepthBias);
4845 const float polyOffsetFactor = psD->m_slopeScaledDepthBias;
4846 const float polyOffsetUnits = psD->m_depthBias;
4853 if (polyOffsetFill) {
4854 f->glPolygonOffset(polyOffsetFactor, polyOffsetUnits);
4855 f->glEnable(GL_POLYGON_OFFSET_FILL);
4857 f->glDisable(GL_POLYGON_OFFSET_FILL);
4861 if (psD->m_topology == QRhiGraphicsPipeline::Lines || psD->m_topology == QRhiGraphicsPipeline::LineStrip) {
4862 const float lineWidth = psD->m_lineWidth;
4863 if (forceUpdate || lineWidth != state
.lineWidth) {
4865 f->glLineWidth(lineWidth);
4869 if (psD->m_topology == QRhiGraphicsPipeline::Patches) {
4870 const int cpCount = psD->m_patchControlPointCount;
4871 if (forceUpdate || cpCount != state
.cpCount) {
4877 f->glUseProgram(psD->program);
7210bool QGles2TextureRenderTarget::create()
7217 const bool hasColorAttachments = m_desc.colorAttachmentCount() > 0;
7218 Q_ASSERT(hasColorAttachments || m_desc.depthTexture());
7219 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
7220 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
7222 if (hasColorAttachments) {
7223 const int count =
int(m_desc.colorAttachmentCount());
7224 if (count > rhiD->caps.maxDrawBuffers) {
7225 qWarning(
"QGles2TextureRenderTarget: Too many color attachments (%d, max is %d)",
7226 count, rhiD->caps.maxDrawBuffers);
7229 if (m_desc.depthTexture() && !rhiD->caps.depthTexture)
7230 qWarning(
"QGles2TextureRenderTarget: Depth texture is not supported and will be ignored");
7232 if (!rhiD->ensureContext())
7235 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments();
7236 it != itEnd; ++it) {
7237 const QRhiColorAttachment &colorAtt(*it);
7238 const QRhiTexture *resolveTexture = colorAtt.resolveTexture();
7239 if (!resolveTexture)
7242 const QRhiTexture *texture = colorAtt.texture();
7243 const QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer();
7244 Q_ASSERT(texture || renderBuffer);
7245 const QRhiTexture::Format sourceFormat = texture ? texture->format()
7246 : renderBuffer->backingFormat();
7247 const bool sourceIsSrgb = texture && texture->flags().testFlag(QRhiTexture::sRGB);
7248 const bool resolveIsSrgb = resolveTexture->flags().testFlag(QRhiTexture::sRGB);
7249 if (sourceFormat != resolveTexture->format() || sourceIsSrgb != resolveIsSrgb) {
7250 qWarning(
"Multisample resolve between different formats "
7251 "(%d, sRGB %d) and (%d, sRGB %d) is not supported.",
7252 int(sourceFormat),
int(sourceIsSrgb),
7253 int(resolveTexture->format()),
int(resolveIsSrgb));
7258 rhiD->f->glGenFramebuffers(1, &framebuffer);
7259 rhiD->f->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
7261 d.colorAttCount = 0;
7262 d.srgbUpdateAndBlend =
false;
7264 int multiViewCount = 0;
7265 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
7266 d.colorAttCount += 1;
7267 const QRhiColorAttachment &colorAtt(*it);
7268 QRhiTexture *texture = colorAtt.texture();
7269 QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer();
7270 Q_ASSERT(texture || renderBuffer);
7272 QGles2Texture *texD =
QRHI_RES(QGles2Texture, texture);
7273 Q_ASSERT(texD->texture && texD->specified);
7274 d.srgbUpdateAndBlend |= texD->flags().testFlag(QRhiTexture::sRGB);
7275 if (colorAtt.resolveTexture())
7276 d.srgbUpdateAndBlend |= colorAtt.resolveTexture()->flags().testFlag(QRhiTexture::sRGB);
7277 if (texD->flags().testFlag(QRhiTexture::ThreeDimensional) || texD->flags().testFlag(QRhiTexture::TextureArray)) {
7278 if (colorAtt.multiViewCount() < 2) {
7279 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture,
7280 colorAtt.level(), colorAtt.layer());
7282 multiViewCount = colorAtt.multiViewCount();
7283 if (texD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture && colorAtt.resolveTexture()) {
7288 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
7289 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7290 GL_COLOR_ATTACHMENT0 + uint(attIndex),
7291 resolveTexD->texture,
7292 colorAtt.resolveLevel(),
7294 colorAtt.resolveLayer(),
7297 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER,
7298 GL_COLOR_ATTACHMENT0 + uint(attIndex),
7305 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
7306 rhiD->glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex),
7307 texD->target + uint(colorAtt.layer()), texD->texture,
7310 if (texD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
7315 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
7317 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
7318 resolveTexD->texture, colorAtt.level(), texD->samples);
7321 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.layer()),
7322 texD->texture, colorAtt.level());
7325 if (attIndex == 0) {
7326 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
7327 d.sampleCount = texD->samples;
7329 }
else if (renderBuffer) {
7330 QGles2RenderBuffer *rbD =
QRHI_RES(QGles2RenderBuffer, renderBuffer);
7331 if (colorAtt.resolveTexture())
7332 d.srgbUpdateAndBlend |= colorAtt.resolveTexture()->flags().testFlag(QRhiTexture::sRGB);
7333 if (rbD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
7338 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
7340 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
7341 resolveTexD->texture, colorAtt.level(), rbD->samples);
7343 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), GL_RENDERBUFFER, rbD->renderbuffer);
7345 if (attIndex == 0) {
7346 d.pixelSize = rbD->pixelSize();
7347 d.sampleCount = rbD->samples;
7352 if (hasDepthStencil && m_desc.depthResolveTexture()) {
7353 const QRhiTexture::Format dstFormat = m_desc.depthResolveTexture()->format();
7354 QRhiTexture::Format srcFormat = QRhiTexture::UnknownFormat;
7355 if (m_desc.depthStencilBuffer())
7356 srcFormat = QRhiTexture::D24S8;
7357 else if (!rhiD->caps.glesMultisampleRenderToTexture)
7358 srcFormat = m_desc.depthTexture()->format();
7360 if (srcFormat != QRhiTexture::UnknownFormat && srcFormat != dstFormat) {
7361 qWarning(
"Multisample depth-stencil source format %d does not match the "
7362 "depthResolveTexture format %d. OpenGL cannot blit between different depth formats; "
7363 "the depth contents will not be resolved.",
7364 int(srcFormat),
int(dstFormat));
7368 if (hasDepthStencil) {
7369 if (m_desc.depthStencilBuffer()) {
7370 QGles2RenderBuffer *depthRbD =
QRHI_RES(QGles2RenderBuffer, m_desc.depthStencilBuffer());
7371 if (rhiD->caps.needsDepthStencilCombinedAttach) {
7373 depthRbD->renderbuffer);
7375 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
7376 depthRbD->renderbuffer);
7377 if (depthRbD->stencilRenderbuffer) {
7378 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7379 depthRbD->stencilRenderbuffer);
7382 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7383 depthRbD->renderbuffer);
7386 if (d.colorAttCount == 0) {
7387 d.pixelSize = depthRbD->pixelSize();
7388 d.sampleCount = depthRbD->samples;
7391 QGles2Texture *depthTexD =
QRHI_RES(QGles2Texture, m_desc.depthTexture());
7392 if (multiViewCount < 2) {
7393 if (depthTexD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && m_desc.depthResolveTexture()) {
7397 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
7398 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthResolveTexD->target,
7399 depthResolveTexD->texture, 0, depthTexD->samples);
7400 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
7401 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthResolveTexD->target,
7402 depthResolveTexD->texture, 0, depthTexD->samples);
7404 }
else if (rhiD->caps.ctxMajor >= 3 && depthTexD->flags().testFlag(QRhiTexture::TextureArray) && m_desc.depthLayer() >= 0) {
7405 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
7406 0, m_desc.depthLayer());
7407 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
7408 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
7409 0, m_desc.depthLayer());
7412 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->target,
7413 depthTexD->texture, 0);
7414 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
7415 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->target,
7416 depthTexD->texture, 0);
7420 if (depthTexD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture) {
7438 if (!m_flags.testFlag(DoNotStoreDepthStencilContents) && !m_desc.depthResolveTexture()) {
7439 qWarning(
"Attempted to create a multiview+multisample QRhiTextureRenderTarget, but DoNotStoreDepthStencilContents was not set."
7440 " This path has no choice but to behave as if DoNotStoreDepthStencilContents was set, because QRhi is forced to create"
7441 " a throwaway non-multisample depth texture here. Set the flag to silence this warning, or set a depthResolveTexture.");
7443 if (m_desc.depthResolveTexture()) {
7444 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
7445 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7446 GL_DEPTH_ATTACHMENT,
7447 depthResolveTexD->texture,
7452 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
7453 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7454 GL_STENCIL_ATTACHMENT,
7455 depthResolveTexD->texture,
7462 if (!nonMsaaThrowawayDepthTexture) {
7463 rhiD->f->glGenTextures(1, &nonMsaaThrowawayDepthTexture);
7466 depthTexD->pixelSize().width(), depthTexD->pixelSize().height(), multiViewCount);
7468 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7469 GL_DEPTH_ATTACHMENT,
7470 nonMsaaThrowawayDepthTexture,
7475 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7476 GL_STENCIL_ATTACHMENT,
7477 nonMsaaThrowawayDepthTexture,
7487 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
7488 0, 0, multiViewCount);
7489 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
7490 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
7491 0, 0, multiViewCount);
7495 if (d.colorAttCount == 0) {
7496 d.pixelSize = depthTexD->pixelSize();
7497 d.sampleCount = depthTexD->samples;
7506 d.rp =
QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
7508 GLenum status = rhiD->f->glCheckFramebufferStatus(GL_FRAMEBUFFER);
7509 if (status != GL_NO_ERROR && status != GL_FRAMEBUFFER_COMPLETE) {
7510 qWarning(
"Framebuffer incomplete: 0x%x", status);
7514 if (rhiD->glObjectLabel)
7515 rhiD->glObjectLabel(GL_FRAMEBUFFER, framebuffer, -1, m_objectName.constData());
7517 QRhiRenderTargetAttachmentTracker::updateResIdList<QGles2Texture, QGles2RenderBuffer>(m_desc, &d.currentResIdList);
7519 rhiD->registerResource(
this);