835 Q_ASSERT(fallbackSurface);
839 ctx =
new QOpenGLContext;
840 ctx->setFormat(requestedFormat);
841 if (maybeShareContext) {
842 ctx->setShareContext(maybeShareContext);
844 ctx->setScreen(maybeWindow->screen());
846 ctx->setScreen(maybeShareContext->screen());
847 }
else if (QOpenGLContext *shareContext = QOpenGLContext::globalShareContext()) {
848 ctx->setShareContext(shareContext);
850 ctx->setScreen(maybeWindow->screen());
852 ctx->setScreen(shareContext->screen());
853 }
else if (maybeWindow) {
854 ctx->setScreen(maybeWindow->screen());
856 if (!ctx->create()) {
857 qWarning(
"QRhiGles2: Failed to create context");
862 qCDebug(QRHI_LOG_INFO) <<
"Created OpenGL context" << ctx->format();
865 if (!ensureContext(maybeWindow ? maybeWindow : fallbackSurface))
868 f =
static_cast<QOpenGLExtensions *>(ctx->extraFunctions());
869 const QSurfaceFormat actualFormat = ctx->format();
870 caps.gles = actualFormat.renderableType() == QSurfaceFormat::OpenGLES;
874 ctx->getProcAddress(QByteArrayLiteral(
"glPolygonMode")));
877 GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum,
const void *)>(
878 ctx->getProcAddress(QByteArrayLiteral(
"glTexImage1D")));
880 glTexStorage1D =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei)>(
881 ctx->getProcAddress(QByteArrayLiteral(
"glTexStorage1D")));
884 GLenum, GLint, GLint, GLsizei, GLenum, GLenum,
const GLvoid *)>(
885 ctx->getProcAddress(QByteArrayLiteral(
"glTexSubImage1D")));
887 glCopyTexSubImage1D =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint,
889 ctx->getProcAddress(QByteArrayLiteral(
"glCopyTexSubImage1D")));
892 GLenum, GLint, GLenum, GLsizei, GLint, GLsizei,
const GLvoid *)>(
893 ctx->getProcAddress(QByteArrayLiteral(
"glCompressedTexImage1D")));
896 GLenum, GLint, GLint, GLsizei, GLenum, GLsizei,
const GLvoid *)>(
897 ctx->getProcAddress(QByteArrayLiteral(
"glCompressedTexSubImage1D")));
899 glFramebufferTexture1D =
901 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture1D")));
904 const char *vendor =
reinterpret_cast<
const char *>(
f->glGetString(GL_VENDOR));
905 const char *renderer =
reinterpret_cast<
const char *>(
f->glGetString(GL_RENDERER));
906 const char *version =
reinterpret_cast<
const char *>(
f->glGetString(GL_VERSION));
907 if (vendor && renderer && version)
908 qCDebug(QRHI_LOG_INFO,
"OpenGL VENDOR: %s RENDERER: %s VERSION: %s", vendor, renderer, version);
911 driverInfoStruct.deviceName += QByteArray(vendor);
912 driverInfoStruct.deviceName +=
' ';
915 driverInfoStruct.deviceName += QByteArray(renderer);
916 driverInfoStruct.deviceName +=
' ';
919 driverInfoStruct.deviceName += QByteArray(version);
921 caps
.ctxMajor = actualFormat.majorVersion();
922 caps
.ctxMinor = actualFormat.minorVersion();
925 caps.srgbTextureFormat = caps.ctxMajor >= 3 || ctx->hasExtension(
"GL_EXT_sRGB");
926 caps.srgbGenerateMipmap = caps.ctxMajor >= 3
927 || ctx->hasExtension(
"GL_NV_generate_mipmap_sRGB");
930 const bool hasCoreSrgbTexture = caps
.ctxMajor > 2
932 caps.srgbTextureFormat = hasCoreSrgbTexture
933 || ctx->hasExtension(
"GL_EXT_texture_sRGB");
943 QVarLengthArray<GLint, 16> compressedTextureFormats(n);
945 for (GLint format : compressedTextureFormats)
946 supportedCompressedFormats.insert(format);
959 std::array<QRhiTexture::Flags, 2> textureVariantFlags;
960 textureVariantFlags[0] = {};
961 textureVariantFlags[1] = QRhiTexture::sRGB;
962 if (
f->hasOpenGLExtension(QOpenGLExtensions::DDSTextureCompression)) {
963 for (QRhiTexture::Flags f : textureVariantFlags) {
964 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC1, f));
965 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC2, f));
966 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC3, f));
969 if (
f->hasOpenGLExtension(QOpenGLExtensions::ETC2TextureCompression)) {
970 for (QRhiTexture::Flags f : textureVariantFlags) {
971 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8, f));
972 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8A1, f));
973 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGBA8, f));
976 if (
f->hasOpenGLExtension(QOpenGLExtensions::ASTCTextureCompression)) {
977 for (QRhiTexture::Flags f : textureVariantFlags) {
978 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_4x4, f));
979 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x4, f));
980 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x5, f));
981 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x5, f));
982 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x6, f));
983 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x5, f));
984 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x6, f));
985 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x8, f));
986 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x5, f));
987 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x8, f));
988 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x10, f));
989 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x10, f));
990 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x12, f));
1011 caps
.msaaRenderBuffer =
f->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
1012 &&
f->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
1015 &&
f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
1034 caps
.r8Format =
f->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats);
1046 caps
.r16Format =
f->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats);
1052 caps.needsDepthStencilCombinedAttach =
true;
1062 caps.srgbWriteControl = ctx->hasExtension(
"GL_EXT_sRGB_write_control");
1064 const bool hasCoreSrgbWriteControl = caps
.ctxMajor >= 3;
1065 caps.srgbWriteControl = hasCoreSrgbWriteControl
1066 || ctx->hasExtension(
"GL_ARB_framebuffer_sRGB")
1067 || ctx->hasExtension(
"GL_EXT_framebuffer_sRGB");
1070 caps.coreProfile = actualFormat.profile() == QSurfaceFormat::CoreProfile;
1083 caps
.depth24 = !caps
.gles ||
f->hasOpenGLExtension(QOpenGLExtensions::Depth24);
1084 caps
.rgba8Format =
f->hasOpenGLExtension(QOpenGLExtensions::Sized8Formats);
1099 GLint ssboBindings = 0;
1122 if (!caps.depthClamp)
1123 caps.depthClamp = ctx->hasExtension(
"GL_EXT_depth_clamp") || ctx->hasExtension(
"GL_ARB_depth_clamp");
1132 caps
.properMapBuffer =
f->hasOpenGLExtension(QOpenGLExtensions::MapBufferRange);
1180 GLint maxArraySize = 0;
1191 GLint maxVertexUniformVectors = 0;
1193 GLint maxFragmentUniformVectors = 0;
1197 GLint maxVertexUniformComponents = 0;
1199 GLint maxFragmentUniformComponents = 0;
1201 caps
.maxUniformVectors = qMin(maxVertexUniformComponents, maxFragmentUniformComponents) / 4;
1209 GLint components = 0;
1215 GLint components = 0;
1233 caps
.halfAttributes =
f->hasOpenGLExtension(QOpenGLExtensions::HalfFloatVertex);
1236 caps
.multiView =
f->hasOpenGLExtension(QOpenGLExtensions::MultiView)
1237 &&
f->hasOpenGLExtension(QOpenGLExtensions::MultiViewExtended);
1239 glFramebufferTextureMultiviewOVR =
1240 reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei)>(
1241 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultiviewOVR")));
1248 ctx->getProcAddress(QByteArrayLiteral(
"glQueryCounter")));
1249 glGetQueryObjectui64v =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLuint, GLenum, quint64 *)>(
1250 ctx->getProcAddress(QByteArrayLiteral(
"glGetQueryObjectui64v")));
1261 glObjectLabel =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLuint, GLsizei,
const GLchar *)>(
1262 ctx->getProcAddress(QByteArrayLiteral(
"glObjectLabel")));
1272 caps.glesMultisampleRenderToTexture = ctx->hasExtension(
"GL_EXT_multisampled_render_to_texture");
1274 glFramebufferTexture2DMultisampleEXT =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei)>(
1275 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture2DMultisampleEXT")));
1276 glRenderbufferStorageMultisampleEXT =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)>(
1277 ctx->getProcAddress(QByteArrayLiteral(
"glRenderbufferStorageMultisampleEXT")));
1279 caps.glesMultiviewMultisampleRenderToTexture = ctx->hasExtension(
"GL_OVR_multiview_multisampled_render_to_texture");
1281 glFramebufferTextureMultisampleMultiviewOVR =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei)>(
1282 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultisampleMultiviewOVR")));
1298 caps.sampleVariables = ctx->hasExtension(
"GL_OES_sample_variables");
1310 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_draw_indirect")))
1321 caps.baseInstance = caps.instancing
1322 && (caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 2)
1323 || ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_base_instance")));
1327 glDrawArraysInstancedBaseInstance =
reinterpret_cast<
decltype(glDrawArraysInstancedBaseInstance)>(
1328 ctx->getProcAddress(QByteArrayLiteral(
"glDrawArraysInstancedBaseInstance")));
1329 glDrawElementsInstancedBaseInstance =
reinterpret_cast<
decltype(glDrawElementsInstancedBaseInstance)>(
1330 ctx->getProcAddress(QByteArrayLiteral(
"glDrawElementsInstancedBaseInstance")));
1331 glDrawElementsInstancedBaseVertexBaseInstance =
reinterpret_cast<
decltype(glDrawElementsInstancedBaseVertexBaseInstance)>(
1332 ctx->getProcAddress(QByteArrayLiteral(
"glDrawElementsInstancedBaseVertexBaseInstance")));
1336 qWarning(
"Failed to resolve glDraw{Arrays,Elements}InstancedBaseInstance{,BaseVertex}; disabling base instance support.");
1345 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_multi_draw_indirect")) ||
1346 ctx->hasExtension(QByteArrayLiteral(
"GL_EXT_multi_draw_indirect")))
1350 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1351 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirect")));
1352 if (!glMultiDrawArraysIndirect)
1353 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1354 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectARB")));
1355 if (!glMultiDrawArraysIndirect)
1356 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1357 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectEXT")));
1358 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1359 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirect")));
1360 if (!glMultiDrawElementsIndirect)
1361 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1362 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectARB")));
1363 if (!glMultiDrawElementsIndirect)
1364 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1365 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectEXT")));
1367 qWarning(
"Failed to resolve glMultiDrawArraysIndirect or glMultiDrawElementsIndirect.");
1376 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_shader_draw_parameters")))
1391 if (!caps.copyBuffer && ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_copy_buffer")))
1392 caps.copyBuffer = ctx->getProcAddress(QByteArrayLiteral(
"glCopyBufferSubData")) !=
nullptr;
1395 && (caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3)
1396 || ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_clear_buffer_object"))))
1398 glClearBufferSubData =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLintptr, GLsizeiptr,
1399 GLenum, GLenum,
const void *)>(
1400 ctx->getProcAddress(QByteArrayLiteral(
"glClearBufferSubData")));
1410 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_indirect_parameters")))
1414 glMultiDrawArraysIndirectCount =
reinterpret_cast<
decltype(glMultiDrawArraysIndirectCount)>(
1415 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectCount")));
1416 if (!glMultiDrawArraysIndirectCount)
1417 glMultiDrawArraysIndirectCount =
reinterpret_cast<
decltype(glMultiDrawArraysIndirectCount)>(
1418 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectCountARB")));
1419 glMultiDrawElementsIndirectCount =
reinterpret_cast<
decltype(glMultiDrawElementsIndirectCount)>(
1420 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectCount")));
1421 if (!glMultiDrawElementsIndirectCount)
1422 glMultiDrawElementsIndirectCount =
reinterpret_cast<
decltype(glMultiDrawElementsIndirectCount)>(
1423 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectCountARB")));
1425 qWarning(
"Failed to resolve glMultiDrawArraysIndirectCount or glMultiDrawElementsIndirectCount.");
1430 nativeHandlesStruct.context = ctx;
2999 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
3002 const bool isCompressed = isCompressedFormat(texD->m_format);
3003 const bool isCubeMap = texD->m_flags.testFlag(QRhiTexture::CubeMap);
3004 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
3005 const bool is1D = texD->m_flags.testFlag(QRhiTexture::OneDimensional);
3006 const bool isArray = texD->m_flags.testFlag(QRhiTexture::TextureArray);
3008 const GLenum effectiveTarget = faceTargetBase + (isCubeMap ? uint(layer) : 0u);
3009 const QPoint dp = subresDesc.destinationTopLeft();
3010 const QByteArray rawData = subresDesc.data();
3012 auto setCmdByNotCompressedData = [&](
const void* data, QSize size, quint32 dataStride)
3014 quint32 bytesPerLine = 0;
3015 quint32 bytesPerPixel = 0;
3016 textureFormatInfo(texD->m_format, size, &bytesPerLine,
nullptr, &bytesPerPixel);
3020 cmd.args.subImage.target = texD->target;
3021 cmd.args.subImage.texture = texD->texture;
3022 cmd.args.subImage.faceTarget = effectiveTarget;
3023 cmd.args.subImage.level = level;
3024 cmd.args.subImage.dx = dp.x();
3025 cmd.args.subImage.dy = is1D && isArray ? layer : dp.y();
3026 cmd.args.subImage.dz = is3D || isArray ? layer : 0;
3027 cmd.args.subImage.w = size.width();
3028 cmd.args.subImage.h = size.height();
3029 cmd.args.subImage.glformat = texD->glformat;
3030 cmd.args.subImage.gltype = texD->gltype;
3032 if (dataStride == 0)
3033 dataStride = bytesPerLine;
3035 cmd.args.subImage.rowStartAlign = (dataStride & 3) ? 1 : 4;
3036 cmd.args.subImage.rowLength = caps
.unpackRowLength ? (bytesPerPixel ? dataStride / bytesPerPixel : 0) : 0;
3038 cmd.args.subImage.data = data;
3041 if (!subresDesc.image().isNull()) {
3042 QImage img = subresDesc.image();
3043 QSize size = img.size();
3044 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
3045 const QPoint sp = subresDesc.sourceTopLeft();
3046 if (!subresDesc.sourceSize().isEmpty())
3047 size = subresDesc.sourceSize();
3048 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
3050 cbD->retainImage(img);
3052 const uchar *data = img.constBits() + sp.y() * img.bytesPerLine() + sp.x() * (qMax(1, img.depth() / 8));
3053 img = QImage(data, size.width(), size.height(), img.bytesPerLine(), img.format());
3055 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
3058 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
3061 setCmdByNotCompressedData(cbD->retainImage(img), size, img.bytesPerLine());
3062 }
else if (!rawData.isEmpty() && isCompressed) {
3063 const int depth = qMax(1, texD->m_depth);
3064 const int arraySize = qMax(0, texD->m_arraySize);
3065 if ((texD->flags().testFlag(QRhiTexture::UsedAsCompressedAtlas) || is3D || isArray)
3073 quint32 levelByteSize = 0;
3074 compressedFormatInfo(texD->m_format, texD->m_pixelSize,
nullptr, &levelByteSize,
nullptr);
3075 quint64 byteSize = levelByteSize;
3077 byteSize *= quint64(depth);
3079 byteSize *= quint64(arraySize);
3080 if (byteSize > quint64(
std::numeric_limits<
int>::max())) {
3081 qWarning(
"Compressed texture zero-initialization would need %llu bytes "
3082 "which is too large; skipping", byteSize);
3085 QByteArray zeroBuf(qsizetype(byteSize), 0);
3088 cmd.args.compressedImage.target = texD->target;
3089 cmd.args.compressedImage.texture = texD->texture;
3090 cmd.args.compressedImage.faceTarget = effectiveTarget;
3091 cmd.args.compressedImage.level = level;
3092 cmd.args.compressedImage.glintformat = texD->glintformat;
3093 cmd.args.compressedImage.w = texD->m_pixelSize.width();
3094 cmd.args.compressedImage.h = is1D && isArray ? arraySize : texD->m_pixelSize.height();
3095 cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
3096 cmd.args.compressedImage.size =
int(byteSize);
3097 cmd.args.compressedImage.data = cbD->retainData(zeroBuf);
3101 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
3102 : subresDesc.sourceSize();
3106 cmd.args.compressedSubImage.target = texD->target;
3107 cmd.args.compressedSubImage.texture = texD->texture;
3108 cmd.args.compressedSubImage.faceTarget = effectiveTarget;
3109 cmd.args.compressedSubImage.level = level;
3110 cmd.args.compressedSubImage.dx = dp.x();
3111 cmd.args.compressedSubImage.dy = is1D && isArray ? layer : dp.y();
3112 cmd.args.compressedSubImage.dz = is3D || isArray ? layer : 0;
3113 cmd.args.compressedSubImage.w = size.width();
3114 cmd.args.compressedSubImage.h = size.height();
3115 cmd.args.compressedSubImage.glintformat = texD->glintformat;
3116 cmd.args.compressedSubImage.size = rawData.size();
3117 cmd.args.compressedSubImage.data = cbD->retainData(rawData);
3121 cmd.args.compressedImage.target = texD->target;
3122 cmd.args.compressedImage.texture = texD->texture;
3123 cmd.args.compressedImage.faceTarget = effectiveTarget;
3124 cmd.args.compressedImage.level = level;
3125 cmd.args.compressedImage.glintformat = texD->glintformat;
3126 cmd.args.compressedImage.w = size.width();
3127 cmd.args.compressedImage.h = is1D && isArray ? arraySize : size.height();
3128 cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
3129 cmd.args.compressedImage.size = rawData.size();
3130 cmd.args.compressedImage.data = cbD->retainData(rawData);
3132 }
else if (!rawData.isEmpty()) {
3133 QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
3134 : subresDesc.sourceSize();
3135 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
3136 quint32 bytesPerPixel = 0;
3137 textureFormatInfo(texD->m_format, size,
nullptr,
nullptr, &bytesPerPixel);
3138 size = clampedSubResourceUploadSizeForSourceData(size, subresDesc.dataStride(),
3139 bytesPerPixel, rawData.size());
3143 setCmdByNotCompressedData(cbD->retainData(rawData), size, subresDesc.dataStride());
3145 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
3723 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
3727 if (cmd.args.beginFrame.timestampQuery)
3731 f->glGenVertexArrays(1, &
vao);
3732 f->glBindVertexArray(
vao);
3739 f->glVertexAttribDivisor(GLuint(i), 0);
3742 f->glVertexAttribDivisor(GLuint(i), 0);
3749 f->glDisableVertexAttribArray(GLuint(i));
3754 f->glBindVertexArray(0);
3755 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
3756 if (cmd.args.endFrame.timestampQuery)
3761 f->glBindVertexArray(
vao);
3764 f->glViewport(GLint(cmd.args.viewport.x), GLint(cmd.args.viewport.y), GLsizei(cmd.args.viewport.w), GLsizei(cmd.args.viewport.h));
3765 f->glDepthRangef(cmd.args.viewport.d0, cmd.args.viewport.d1);
3768 f->glScissor(cmd.args.scissor.x, cmd.args.scissor.y, cmd.args.scissor.w, cmd.args.scissor.h);
3771 f->glBlendColor(cmd.args.blendConstants.r, cmd.args.blendConstants.g, cmd.args.blendConstants.b, cmd.args.blendConstants.a);
3777 const GLint ref = GLint(cmd.args.stencilRef.ref);
3778 f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), ref, psD->m_stencilReadMask);
3779 f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), ref, psD->m_stencilReadMask);
3780 cbD->graphicsPassState.dynamic.stencilRef = ref;
3782 qWarning(
"No graphics pipeline active for setStencilRef; ignored");
3790 if (state.lastBindVertexBuffer.ps == psD
3791 && state.lastBindVertexBuffer.buffer == cmd.args.bindVertexBuffer.buffer
3792 && state.lastBindVertexBuffer.offset == cmd.args.bindVertexBuffer.offset
3793 && state.lastBindVertexBuffer.binding == cmd.args.bindVertexBuffer.binding)
3800 state.lastBindVertexBuffer.ps = psD;
3801 state.lastBindVertexBuffer.buffer = cmd.args.bindVertexBuffer.buffer;
3802 state.lastBindVertexBuffer.offset = cmd.args.bindVertexBuffer.offset;
3803 state.lastBindVertexBuffer.binding = cmd.args.bindVertexBuffer.binding;
3805 if (cmd.args.bindVertexBuffer.buffer != state.currentArrayBuffer) {
3806 state.currentArrayBuffer = cmd.args.bindVertexBuffer.buffer;
3808 f->glBindBuffer(GL_ARRAY_BUFFER, state.currentArrayBuffer);
3810 for (
auto it = psD->m_vertexInputLayout.cbeginAttributes(), itEnd = psD->m_vertexInputLayout.cendAttributes();
3813 const int bindingIdx = it->binding();
3814 if (bindingIdx != cmd.args.bindVertexBuffer.binding)
3817 const QRhiVertexInputBinding *inputBinding = psD->m_vertexInputLayout.bindingAt(bindingIdx);
3818 const int stride =
int(inputBinding->stride());
3821 bool normalize =
false;
3822 switch (it->format()) {
3823 case QRhiVertexInputAttribute::Float4:
3827 case QRhiVertexInputAttribute::Float3:
3831 case QRhiVertexInputAttribute::Float2:
3835 case QRhiVertexInputAttribute::Float:
3839 case QRhiVertexInputAttribute::UNormByte4:
3844 case QRhiVertexInputAttribute::UNormByte2:
3849 case QRhiVertexInputAttribute::UNormByte:
3854 case QRhiVertexInputAttribute::UInt4:
3855 type = GL_UNSIGNED_INT;
3858 case QRhiVertexInputAttribute::UInt3:
3859 type = GL_UNSIGNED_INT;
3862 case QRhiVertexInputAttribute::UInt2:
3863 type = GL_UNSIGNED_INT;
3866 case QRhiVertexInputAttribute::UInt:
3867 type = GL_UNSIGNED_INT;
3870 case QRhiVertexInputAttribute::SInt4:
3874 case QRhiVertexInputAttribute::SInt3:
3878 case QRhiVertexInputAttribute::SInt2:
3882 case QRhiVertexInputAttribute::SInt:
3886 case QRhiVertexInputAttribute::Half4:
3890 case QRhiVertexInputAttribute::Half3:
3894 case QRhiVertexInputAttribute::Half2:
3898 case QRhiVertexInputAttribute::Half:
3902 case QRhiVertexInputAttribute::UShort4:
3903 type = GL_UNSIGNED_SHORT;
3906 case QRhiVertexInputAttribute::UShort3:
3907 type = GL_UNSIGNED_SHORT;
3910 case QRhiVertexInputAttribute::UShort2:
3911 type = GL_UNSIGNED_SHORT;
3914 case QRhiVertexInputAttribute::UShort:
3915 type = GL_UNSIGNED_SHORT;
3918 case QRhiVertexInputAttribute::SShort4:
3922 case QRhiVertexInputAttribute::SShort3:
3926 case QRhiVertexInputAttribute::SShort2:
3930 case QRhiVertexInputAttribute::SShort:
3938 const int locationIdx = it->location();
3939 quint32 ofs = it->offset() + cmd.args.bindVertexBuffer.offset;
3940 if (type == GL_UNSIGNED_INT || type == GL_INT) {
3942 f->glVertexAttribIPointer(GLuint(locationIdx), size, type, stride,
3943 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3945 qWarning(
"Current RHI backend does not support IntAttributes. Check supported features.");
3951 f->glVertexAttribPointer(GLuint(locationIdx), size, type, normalize, stride,
3952 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3957 f->glEnableVertexAttribArray(GLuint(locationIdx));
3959 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance && caps.instancing) {
3960 f->glVertexAttribDivisor(GLuint(locationIdx), inputBinding->instanceStepRate());
3971 f->glVertexAttribDivisor(GLuint(locationIdx), 0);
3977 qWarning(
"No graphics pipeline active for setVertexInput; ignored");
3982 state.indexType = cmd.args.bindIndexBuffer.type;
3983 state.indexStride = state.indexType == GL_UNSIGNED_SHORT ?
sizeof(quint16) :
sizeof(quint32);
3984 state.indexOffset = cmd.args.bindIndexBuffer.offset;
3985 if (state.currentElementArrayBuffer != cmd.args.bindIndexBuffer.buffer) {
3986 state.currentElementArrayBuffer = cmd.args.bindIndexBuffer.buffer;
3987 f->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state.currentElementArrayBuffer);
3994 const bool useBaseInstance = (cmd.args.draw.baseInstance != 0 && caps
.baseInstance);
3997 && (cmd.args.draw.instanceCount != 1 || useBaseInstance);
3999 if (!needsInstancedPath) {
4000 f->glDrawArrays(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount));
4001 }
else if (useBaseInstance) {
4003 GLint(cmd.args.draw.firstVertex)
,
4004 GLsizei(cmd.args.draw.vertexCount)
,
4005 GLsizei(cmd.args.draw.instanceCount)
,
4006 cmd.args.draw.baseInstance
);
4008 f->glDrawArraysInstanced(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount),
4009 GLsizei(cmd.args.draw.instanceCount));
4012 qWarning(
"No graphics pipeline active for draw; ignored");
4020 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4021 quintptr(cmd.args.drawIndexed.firstIndex * state.indexStride + state.indexOffset));
4022 const bool useBaseVertex = (cmd.args.drawIndexed.baseVertex != 0 && caps
.baseVertex);
4023 const bool useBaseInstance = (cmd.args.drawIndexed.baseInstance != 0 && caps
.baseInstance);
4028 && (cmd.args.drawIndexed.instanceCount != 1 || useBaseInstance);
4030 if (!needsInstancedPath) {
4031 if (useBaseVertex) {
4032 f->glDrawElementsBaseVertex(psD->drawMode,
4033 GLsizei(cmd.args.drawIndexed.indexCount),
4036 cmd.args.drawIndexed.baseVertex);
4038 f->glDrawElements(psD->drawMode,
4039 GLsizei(cmd.args.drawIndexed.indexCount),
4043 }
else if (useBaseInstance && useBaseVertex) {
4045 GLsizei(cmd.args.drawIndexed.indexCount)
,
4048 GLsizei(cmd.args.drawIndexed.instanceCount)
,
4049 cmd.args.drawIndexed.baseVertex
,
4050 cmd.args.drawIndexed.baseInstance
);
4051 }
else if (useBaseInstance) {
4053 GLsizei(cmd.args.drawIndexed.indexCount)
,
4056 GLsizei(cmd.args.drawIndexed.instanceCount)
,
4057 cmd.args.drawIndexed.baseInstance
);
4058 }
else if (useBaseVertex) {
4059 f->glDrawElementsInstancedBaseVertex(psD->drawMode,
4060 GLsizei(cmd.args.drawIndexed.indexCount),
4063 GLsizei(cmd.args.drawIndexed.instanceCount),
4064 cmd.args.drawIndexed.baseVertex);
4066 f->glDrawElementsInstanced(psD->drawMode,
4067 GLsizei(cmd.args.drawIndexed.indexCount),
4070 GLsizei(cmd.args.drawIndexed.instanceCount));
4073 qWarning(
"No graphics pipeline active for drawIndexed; ignored");
4083 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4084 quintptr(cmd.args.drawIndirect.offset));
4087 cmd.args.drawIndirect.drawCount
,
4088 cmd.args.drawIndirect.stride
);
4090 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
4091 const quintptr indirectOffset = quintptr(cmd.args.drawIndirect.offset)
4092 + quintptr(i) * cmd.args.drawIndirect.stride;
4093 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(indirectOffset);
4094 f->glDrawArraysIndirect(psD->drawMode,
4100 qWarning(
"No graphics pipeline active for drawIndirect; ignored");
4110 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4111 quintptr(cmd.args.drawIndexedIndirect.offset));
4115 cmd.args.drawIndexedIndirect.drawCount
,
4116 cmd.args.drawIndexedIndirect.stride
);
4118 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
4119 const quintptr indirectOffset = quintptr(cmd.args.drawIndexedIndirect.offset)
4120 + quintptr(i) * cmd.args.drawIndexedIndirect.stride;
4121 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(indirectOffset);
4122 f->glDrawElementsIndirect(psD->drawMode,
4129 qWarning(
"No graphics pipeline active for drawIndexedIndirect; ignored");
4139 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4140 quintptr(cmd.args.drawIndirectCount.offset));
4143 GLintptr(cmd.args.drawIndirectCount.countOffset)
,
4144 cmd.args.drawIndirectCount.maxDrawCount
,
4145 cmd.args.drawIndirectCount.stride
);
4149 qWarning(
"No graphics pipeline active or glMultiDrawArraysIndirectCount unavailable; ignored");
4159 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4160 quintptr(cmd.args.drawIndexedIndirectCount.offset));
4164 GLintptr(cmd.args.drawIndexedIndirectCount.countOffset)
,
4165 cmd.args.drawIndexedIndirectCount.maxDrawCount
,
4166 cmd.args.drawIndexedIndirectCount.stride
);
4170 qWarning(
"No graphics pipeline active or glMultiDrawElementsIndirectCount unavailable; ignored");
4177 case QGles2CommandBuffer::Command::BindShaderResources:
4178 bindShaderResources(cbD,
4179 cmd.args.bindShaderResources.maybeGraphicsPs,
4180 cmd.args.bindShaderResources.maybeComputePs,
4181 cmd.args.bindShaderResources.srb,
4182 cbD->dynamicOffsetPool.constData() + cmd.args.bindShaderResources.dynamicOffsetPoolOffset,
4183 cmd.args.bindShaderResources.dynamicOffsetCount);
4187 QRhiGraphicsPipeline *maybeGraphicsPs = cmd.args.setPushConstants.maybeGraphicsPs;
4188 QRhiComputePipeline *maybeComputePs = cmd.args.setPushConstants.maybeComputePs;
4189 const QGles2UniformDescriptionVector &uniforms(maybeGraphicsPs
4190 ?
QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->pushConstantUniforms
4191 :
QRHI_RES(QGles2ComputePipeline, maybeComputePs)->pushConstantUniforms);
4193 ?
QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->uniformState.data()
4194 :
QRHI_RES(QGles2ComputePipeline, maybeComputePs)->uniformState.data();
4195 setUniformsFromBlock(uniforms, -1,
4196 cbD->pushConstantPool.constData() + cmd.args.setPushConstants.dataOffset,
4197 cmd.args.setPushConstants.size, 0, uniformState);
4202 QVarLengthArray<GLenum, 8> bufs;
4203 GLuint fbo = cmd.args.bindFramebuffer.fbo;
4205 fbo = ctx->defaultFramebufferObject();
4206 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4208 const int colorAttCount = cmd.args.bindFramebuffer.colorAttCount;
4209 bufs.append(colorAttCount > 0 ? GL_COLOR_ATTACHMENT0 : GL_NONE);
4211 for (
int i = 1; i < colorAttCount; ++i)
4212 bufs.append(GL_COLOR_ATTACHMENT0 + uint(i));
4215 if (cmd.args.bindFramebuffer.stereo && cmd.args.bindFramebuffer.stereoTarget == QRhiSwapChain::RightBuffer)
4221 f->glDrawBuffers(bufs.count(), bufs.constData());
4223 if (cmd.args.bindFramebuffer.srgb)
4231 f->glDisable(GL_SCISSOR_TEST);
4232 if (cmd.args.clear.mask & GL_COLOR_BUFFER_BIT) {
4233 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4234 f->glClearColor(cmd.args.clear.c[0], cmd.args.clear.c[1], cmd.args.clear.c[2], cmd.args.clear.c[3]);
4236 if (cmd.args.clear.mask & GL_DEPTH_BUFFER_BIT) {
4237 f->glDepthMask(GL_TRUE);
4238 f->glClearDepthf(cmd.args.clear.d);
4240 if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT) {
4241 f->glStencilMask(0xFF);
4242 f->glClearStencil(GLint(cmd.args.clear.s));
4244 f->glClear(cmd.args.clear.mask);
4245 cbD->graphicsPassState.reset();
4248 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.bufferSubData.target, cmd.args.bufferSubData.buffer);
4249 f->glBufferSubData(cmd.args.bufferSubData.target, cmd.args.bufferSubData.offset, cmd.args.bufferSubData.size,
4250 cmd.args.bufferSubData.data);
4253 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.clearBufferSubData.target, cmd.args.clearBufferSubData.buffer);
4255 cmd.args.clearBufferSubData.offset
, cmd.args.clearBufferSubData.size
,
4260 QRhiReadbackResult *result = cmd.args.getBufferSubData.result;
4261 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.getBufferSubData.target, cmd.args.getBufferSubData.buffer);
4264 void *p =
f->glMapBufferRange(cmd.args.getBufferSubData.target,
4265 cmd.args.getBufferSubData.offset,
4266 cmd.args.getBufferSubData.size,
4269 result->data.resize(cmd.args.getBufferSubData.size);
4270 memcpy(result->data.data(), p, size_t(cmd.args.getBufferSubData.size));
4271 f->glUnmapBuffer(cmd.args.getBufferSubData.target);
4275 result->data.resize(cmd.args.getBufferSubData.size);
4276 f->glGetBufferSubData(cmd.args.getBufferSubData.target,
4277 cmd.args.getBufferSubData.offset,
4278 cmd.args.getBufferSubData.size,
4279 result->data.data());
4281 if (result->completed)
4282 result->completed();
4289 cmd.args.copyBuf.srcOffset, cmd.args.copyBuf.dstOffset,
4290 cmd.args.copyBuf.size);
4297 f->glGenFramebuffers(1, &fbo);
4298 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4302 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.copyTex.srcTexture,
4303 cmd.args.copyTex.srcLevel, cmd.args.copyTex.srcZ);
4306 cmd.args.copyTex.srcTarget, cmd.args.copyTex.srcTexture,
4307 cmd.args.copyTex.srcLevel);
4309 f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4310 cmd.args.copyTex.srcFaceTarget, cmd.args.copyTex.srcTexture, cmd.args.copyTex.srcLevel);
4312 f->glBindTexture(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstTexture);
4314 f->glCopyTexSubImage3D(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstLevel,
4315 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY, cmd.args.copyTex.dstZ,
4316 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
4317 cmd.args.copyTex.w, cmd.args.copyTex.h);
4320 cmd.args.copyTex.dstX
, cmd.args.copyTex.srcX
,
4321 cmd.args.copyTex.srcY
, cmd.args.copyTex.w
);
4323 f->glCopyTexSubImage2D(cmd.args.copyTex.dstFaceTarget, cmd.args.copyTex.dstLevel,
4324 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY,
4325 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
4326 cmd.args.copyTex.w, cmd.args.copyTex.h);
4328 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4329 f->glDeleteFramebuffers(1, &fbo);
4334 QRhiReadbackResult *result = cmd.args.readPixels.result;
4335 GLuint tex = cmd.args.readPixels.texture;
4338 result->pixelSize = QSize(cmd.args.readPixels.w, cmd.args.readPixels.h);
4340 result->format = cmd.args.readPixels.format;
4341 mipLevel = cmd.args.readPixels.level;
4343 f->glGenFramebuffers(1, &fbo);
4344 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4345 const auto attach = [&](GLenum attachment) {
4346 if (cmd.args.readPixels.slice3D >= 0) {
4347 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment,
4348 tex, mipLevel, cmd.args.readPixels.slice3D);
4349 }
else if (cmd.args.readPixels.readTarget ==
GL_TEXTURE_1D) {
4351 cmd.args.readPixels.readTarget, tex, mipLevel);
4353 f->glFramebufferTexture2D(GL_FRAMEBUFFER, attachment,
4354 cmd.args.readPixels.readTarget, tex, mipLevel);
4358 if (isDepthTextureFormat(result->format)) {
4359 attach(GL_DEPTH_ATTACHMENT);
4360 if (isStencilSupportingFormat(result->format))
4361 attach(GL_STENCIL_ATTACHMENT);
4365 f->glReadBuffer(GL_NONE);
4367 attach(GL_COLOR_ATTACHMENT0);
4371 result->format = QRhiTexture::RGBA8;
4374 const int x = cmd.args.readPixels.x;
4375 const int y = cmd.args.readPixels.y;
4376 const int w = cmd.args.readPixels.w;
4377 const int h = cmd.args.readPixels.h;
4381 if (result->format == QRhiTexture::R8 || result->format == QRhiTexture::RED_OR_ALPHA8) {
4382 result->data.resizeForOverwrite(w * h);
4384 tmpBuf.resizeForOverwrite(w * h * 4);
4386 const quint8 *srcBase =
reinterpret_cast<
const quint8 *>(tmpBuf.constData());
4387 quint8 *dstBase =
reinterpret_cast<quint8 *>(result->data.data());
4388 const int componentIndex = result->format == QRhiTexture::R8
4389 || isFeatureSupported(QRhi::RedOrAlpha8IsRed)
4392 for (
int y = 0; y < h; ++y) {
4393 const quint8 *src = srcBase + y * w * 4;
4394 quint8 *dst = dstBase + y * w;
4396 while (count-- > 0) {
4397 *dst++ = src[componentIndex];
4404 [[maybe_unused]] GLenum glintformat;
4405 [[maybe_unused]] GLenum glsizedintformat;
4408 toGlTextureFormat(result->format, {}, caps,
4409 &glintformat, &glsizedintformat, &glformat, &gltype);
4411 textureFormatInfo(result->format, result->pixelSize,
nullptr, &byteSize,
nullptr);
4412 result->data.resizeForOverwrite(byteSize);
4414 f->glPixelStorei(GL_PACK_ALIGNMENT, 1);
4415 f->glReadPixels(x, y, w, h, glformat, gltype, result->data.data());
4416 f->glPixelStorei(GL_PACK_ALIGNMENT, 4);
4420 if (result->format == QRhiTexture::D24 || result->format == QRhiTexture::D32FS8) {
4421 const bool isD24 = result->format == QRhiTexture::D24;
4422 const quint32 mask = isD24 ? 0xFFFFFF00u : 0xFFu;
4423 char *p = result->data.data();
4424 for (qsizetype i = isD24 ? 0 : 1, count = result->data.size() / 4; i < count; i += isD24 ? 1 : 2)
4425 qToUnaligned(qFromUnaligned<quint32>(p + i * 4) & mask, p + i * 4);
4430 quint32 byteSize = 0;
4431 textureFormatInfo(result->format, result->pixelSize,
nullptr, &byteSize,
nullptr);
4432 result->data.fill(
'\0', byteSize);
4435 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4436 f->glDeleteFramebuffers(1, &fbo);
4438 if (result->completed)
4439 result->completed();
4443 f->glBindTexture(cmd.args.subImage.target, cmd.args.subImage.texture);
4444 if (cmd.args.subImage.rowStartAlign != 4)
4445 f->glPixelStorei(GL_UNPACK_ALIGNMENT, cmd.args.subImage.rowStartAlign);
4446 if (cmd.args.subImage.rowLength != 0)
4449 f->glTexSubImage3D(cmd.args.subImage.target, cmd.args.subImage.level,
4450 cmd.args.subImage.dx, cmd.args.subImage.dy, cmd.args.subImage.dz,
4451 cmd.args.subImage.w, cmd.args.subImage.h, 1,
4452 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
4453 cmd.args.subImage.data);
4456 cmd.args.subImage.dx
, cmd.args.subImage.w
,
4457 cmd.args.subImage.glformat
, cmd.args.subImage.gltype
,
4458 cmd.args.subImage.data
);
4460 f->glTexSubImage2D(cmd.args.subImage.faceTarget, cmd.args.subImage.level,
4461 cmd.args.subImage.dx, cmd.args.subImage.dy,
4462 cmd.args.subImage.w, cmd.args.subImage.h,
4463 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
4464 cmd.args.subImage.data);
4466 if (cmd.args.subImage.rowStartAlign != 4)
4467 f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
4468 if (cmd.args.subImage.rowLength != 0)
4472 f->glBindTexture(cmd.args.compressedImage.target, cmd.args.compressedImage.texture);
4474 f->glCompressedTexImage3D(cmd.args.compressedImage.target, cmd.args.compressedImage.level,
4475 cmd.args.compressedImage.glintformat,
4476 cmd.args.compressedImage.w, cmd.args.compressedImage.h, cmd.args.compressedImage.depth,
4477 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
4478 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
4480 cmd.args.compressedImage.target
, cmd.args.compressedImage.level
,
4481 cmd.args.compressedImage.glintformat
, cmd.args.compressedImage.w
, 0
,
4482 cmd.args.compressedImage.size
, cmd.args.compressedImage.data
);
4484 f->glCompressedTexImage2D(cmd.args.compressedImage.faceTarget, cmd.args.compressedImage.level,
4485 cmd.args.compressedImage.glintformat,
4486 cmd.args.compressedImage.w, cmd.args.compressedImage.h,
4487 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
4491 f->glBindTexture(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.texture);
4493 f->glCompressedTexSubImage3D(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.level,
4494 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy, cmd.args.compressedSubImage.dz,
4495 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h, 1,
4496 cmd.args.compressedSubImage.glintformat,
4497 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
4498 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
4500 cmd.args.compressedSubImage.target
, cmd.args.compressedSubImage.level
,
4501 cmd.args.compressedSubImage.dx
, cmd.args.compressedSubImage.w
,
4502 cmd.args.compressedSubImage.glintformat
, cmd.args.compressedSubImage.size
,
4503 cmd.args.compressedSubImage.data
);
4505 f->glCompressedTexSubImage2D(cmd.args.compressedSubImage.faceTarget, cmd.args.compressedSubImage.level,
4506 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy,
4507 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h,
4508 cmd.args.compressedSubImage.glintformat,
4509 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
4516 cbD->graphicsPassState.reset();
4517 f->glDisable(GL_SCISSOR_TEST);
4519 f->glGenFramebuffers(2, fbo);
4521 const bool ds = cmd.args.blitFromRenderbuffer.isDepthStencil;
4522 const bool hasStencil = ds && cmd.args.blitFromRenderbuffer.hasStencil;
4525 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4528 const GLuint srcStencilRb = cmd.args.blitFromRenderbuffer.stencilRenderbuffer
4529 ? cmd.args.blitFromRenderbuffer.stencilRenderbuffer
4530 : cmd.args.blitFromRenderbuffer.renderbuffer;
4532 GL_RENDERBUFFER, srcStencilRb);
4536 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4542 cmd.args.blitFromRenderbuffer.dstTexture,
4543 cmd.args.blitFromRenderbuffer.dstLevel,
4544 cmd.args.blitFromRenderbuffer.dstLayer);
4547 cmd.args.blitFromRenderbuffer.dstTexture,
4548 cmd.args.blitFromRenderbuffer.dstLevel,
4549 cmd.args.blitFromRenderbuffer.dstLayer);
4553 cmd.args.blitFromRenderbuffer.dstTexture,
4554 cmd.args.blitFromRenderbuffer.dstLevel,
4555 cmd.args.blitFromRenderbuffer.dstLayer);
4559 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
4560 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4562 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
4563 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4566 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromRenderbuffer.target,
4567 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4570 if (ds && !caps
.gles) {
4571 f->glReadBuffer(GL_NONE);
4572 const GLenum noBuf = GL_NONE;
4573 f->glDrawBuffers(1, &noBuf);
4575 const GLbitfield rbBlitMask = ds ? (GL_DEPTH_BUFFER_BIT | (hasStencil ? GL_STENCIL_BUFFER_BIT : 0))
4576 : GL_COLOR_BUFFER_BIT;
4577 f->glBlitFramebuffer(0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
4578 0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
4581 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4582 f->glDeleteFramebuffers(2, fbo);
4589 cbD->graphicsPassState.reset();
4590 f->glDisable(GL_SCISSOR_TEST);
4592 f->glGenFramebuffers(2, fbo);
4594 const bool ds = cmd.args.blitFromTexture.isDepthStencil;
4595 const bool hasStencil = ds && cmd.args.blitFromTexture.hasStencil;
4599 cmd.args.blitFromTexture.srcTexture,
4600 cmd.args.blitFromTexture.srcLevel,
4601 cmd.args.blitFromTexture.srcLayer);
4604 cmd.args.blitFromTexture.srcTexture,
4605 cmd.args.blitFromTexture.srcLevel,
4606 cmd.args.blitFromTexture.srcLayer);
4610 cmd.args.blitFromTexture.srcTexture,
4611 cmd.args.blitFromTexture.srcLevel,
4612 cmd.args.blitFromTexture.srcLayer);
4616 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
4617 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4619 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
4620 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4623 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.srcTarget,
4624 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4631 cmd.args.blitFromTexture.dstTexture,
4632 cmd.args.blitFromTexture.dstLevel,
4633 cmd.args.blitFromTexture.dstLayer);
4636 cmd.args.blitFromTexture.dstTexture,
4637 cmd.args.blitFromTexture.dstLevel,
4638 cmd.args.blitFromTexture.dstLayer);
4642 cmd.args.blitFromTexture.dstTexture,
4643 cmd.args.blitFromTexture.dstLevel,
4644 cmd.args.blitFromTexture.dstLayer);
4648 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
4649 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4651 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
4652 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4655 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.dstTarget,
4656 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4659 if (ds && !caps
.gles) {
4660 f->glReadBuffer(GL_NONE);
4661 const GLenum noBuf = GL_NONE;
4662 f->glDrawBuffers(1, &noBuf);
4664 const GLbitfield texBlitMask = ds ? (GL_DEPTH_BUFFER_BIT | (hasStencil ? GL_STENCIL_BUFFER_BIT : 0))
4665 : GL_COLOR_BUFFER_BIT;
4666 f->glBlitFramebuffer(0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
4667 0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
4670 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4671 f->glDeleteFramebuffers(2, fbo);
4675 f->glBindTexture(cmd.args.genMip.target, cmd.args.genMip.texture);
4676 f->glGenerateMipmap(cmd.args.genMip.target);
4681 f->glUseProgram(psD->program);
4685 f->glDispatchCompute(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
4690 f->glDispatchComputeIndirect(GLintptr(cmd.args.dispatchIndirect.offset));
4698 GLbitfield barriers = 0;
4707 for (
const auto &[rhiB, trackedB]: tracker.buffers()) {
4709 QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(trackedB.stateAtPassBegin.access);
4710 if (bufferAccessIsWrite(accessBeforePass))
4711 barriers |= barriersForBuffer();
4713 for (
const auto &[rhiT, trackedT]: tracker.textures()) {
4715 QGles2Texture::Access accessBeforePass = QGles2Texture::Access(trackedT.stateAtPassBegin.access);
4716 if (textureAccessIsWrite(accessBeforePass))
4717 barriers |= barriersForTexture();
4720 f->glMemoryBarrier(barriers);
4725 f->glMemoryBarrier(cmd.args.barrier.barriers);
4729 f->glBindFramebuffer(GL_FRAMEBUFFER, cmd.args.invalidateFramebuffer.fbo);
4731 cmd.args.invalidateFramebuffer.attCount,
4732 cmd.args.invalidateFramebuffer.att);
4742 f->glVertexAttribDivisor(GLuint(i), 0);
4745 f->glVertexAttribDivisor(GLuint(i), 0);
4752 const bool forceUpdate = !state
.valid;
4755 const bool scissor = psD->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor);
4756 if (forceUpdate || scissor != state
.scissor) {
4759 f->glEnable(GL_SCISSOR_TEST);
4761 f->glDisable(GL_SCISSOR_TEST);
4764 const bool cullFace = psD->m_cullMode != QRhiGraphicsPipeline::None;
4765 const GLenum cullMode = cullFace ? toGlCullMode(psD->m_cullMode) : GL_NONE;
4766 if (forceUpdate || cullFace != state
.cullFace || cullMode != state.cullMode) {
4768 state.cullMode = cullMode;
4770 f->glEnable(GL_CULL_FACE);
4771 f->glCullFace(cullMode);
4773 f->glDisable(GL_CULL_FACE);
4777 const GLenum frontFace = toGlFrontFace(psD->m_frontFace);
4778 if (forceUpdate || frontFace != state.frontFace) {
4779 state.frontFace = frontFace;
4780 f->glFrontFace(frontFace);
4783 const GLenum polygonMode = toGlPolygonMode(psD->m_polygonMode);
4784 if (
glPolygonMode && (forceUpdate || polygonMode != state.polygonMode)) {
4785 state.polygonMode = polygonMode;
4789 if (!psD->m_targetBlends.isEmpty()) {
4791 bool anyBlendEnabled =
false;
4792 for (
const auto targetBlend : psD->m_targetBlends) {
4793 const QGles2CommandBuffer::GraphicsPassState::ColorMask colorMask = {
4794 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::R),
4795 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::G),
4796 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::B),
4797 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::A)
4799 if (forceUpdate || colorMask != state.colorMask[buffer]) {
4800 state.colorMask[buffer] = colorMask;
4801 if (caps.perRenderTargetBlending)
4802 f->glColorMaski(buffer, colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4804 f->glColorMask(colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4807 const bool blendEnabled = targetBlend.enable;
4808 const QGles2CommandBuffer::GraphicsPassState::Blend blend = {
4809 toGlBlendFactor(targetBlend.srcColor),
4810 toGlBlendFactor(targetBlend.dstColor),
4811 toGlBlendFactor(targetBlend.srcAlpha),
4812 toGlBlendFactor(targetBlend.dstAlpha),
4813 toGlBlendOp(targetBlend.opColor),
4814 toGlBlendOp(targetBlend.opAlpha)
4816 anyBlendEnabled |= blendEnabled;
4817 if (forceUpdate || blendEnabled != state.blendEnabled[buffer] || (blendEnabled && blend != state.blend[buffer])) {
4818 state.blendEnabled[buffer] = blendEnabled;
4820 state.blend[buffer] = blend;
4821 if (caps.perRenderTargetBlending) {
4822 f->glBlendFuncSeparatei(buffer, blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4823 f->glBlendEquationSeparatei(buffer, blend.opColor, blend.opAlpha);
4825 f->glBlendFuncSeparate(blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4826 f->glBlendEquationSeparate(blend.opColor, blend.opAlpha);
4831 if (!caps.perRenderTargetBlending)
4834 if (anyBlendEnabled)
4835 f->glEnable(GL_BLEND);
4837 f->glDisable(GL_BLEND);
4840 if (forceUpdate || colorMask
!= state.colorMask[0]) {
4841 state.colorMask[0] = colorMask;
4842 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4844 const bool blendEnabled =
false;
4847 f->glDisable(GL_BLEND);
4851 const bool depthTest = psD->m_depthTest;
4852 if (forceUpdate || depthTest != state
.depthTest) {
4855 f->glEnable(GL_DEPTH_TEST);
4857 f->glDisable(GL_DEPTH_TEST);
4860 const bool depthWrite = psD->m_depthWrite;
4861 if (forceUpdate || depthWrite != state
.depthWrite) {
4863 f->glDepthMask(depthWrite);
4866 const bool depthClamp = psD->m_depthClamp;
4875 const GLenum depthFunc = toGlCompareOp(psD->m_depthOp);
4876 if (forceUpdate || depthFunc != state.depthFunc) {
4877 state.depthFunc = depthFunc;
4878 f->glDepthFunc(depthFunc);
4881 const bool stencilTest = psD->m_stencilTest;
4882 const GLuint stencilReadMask = psD->m_stencilReadMask;
4883 const GLuint stencilWriteMask = psD->m_stencilWriteMask;
4885 toGlCompareOp(psD->m_stencilFront.compareOp),
4886 toGlStencilOp(psD->m_stencilFront.failOp),
4887 toGlStencilOp(psD->m_stencilFront.depthFailOp),
4888 toGlStencilOp(psD->m_stencilFront.passOp)
4891 toGlCompareOp(psD->m_stencilBack.compareOp),
4892 toGlStencilOp(psD->m_stencilBack.failOp),
4893 toGlStencilOp(psD->m_stencilBack.depthFailOp),
4894 toGlStencilOp(psD->m_stencilBack.passOp)
4898 && (stencilReadMask != state.stencilReadMask || stencilWriteMask != state.stencilWriteMask
4899 || stencilFront != state.stencil[0] || stencilBack != state.stencil[1])))
4903 state.stencilReadMask = stencilReadMask;
4904 state.stencilWriteMask = stencilWriteMask;
4905 state.stencil[0] = stencilFront;
4906 state.stencil[1] = stencilBack;
4908 f->glEnable(GL_STENCIL_TEST);
4910 f->glStencilFuncSeparate(GL_FRONT, stencilFront.func, state.dynamic.stencilRef, stencilReadMask);
4911 f->glStencilOpSeparate(GL_FRONT, stencilFront.failOp, stencilFront.zfailOp, stencilFront.zpassOp);
4912 f->glStencilMaskSeparate(GL_FRONT, stencilWriteMask);
4914 f->glStencilFuncSeparate(GL_BACK, stencilBack.func, state.dynamic.stencilRef, stencilReadMask);
4915 f->glStencilOpSeparate(GL_BACK, stencilBack.failOp, stencilBack.zfailOp, stencilBack.zpassOp);
4916 f->glStencilMaskSeparate(GL_BACK, stencilWriteMask);
4918 f->glDisable(GL_STENCIL_TEST);
4922 const bool polyOffsetFill = psD->m_depthBias != 0 || !qFuzzyIsNull(psD->m_slopeScaledDepthBias);
4923 const float polyOffsetFactor = psD->m_slopeScaledDepthBias;
4924 const float polyOffsetUnits = psD->m_depthBias;
4931 if (polyOffsetFill) {
4932 f->glPolygonOffset(polyOffsetFactor, polyOffsetUnits);
4933 f->glEnable(GL_POLYGON_OFFSET_FILL);
4935 f->glDisable(GL_POLYGON_OFFSET_FILL);
4939 if (psD->m_topology == QRhiGraphicsPipeline::Lines || psD->m_topology == QRhiGraphicsPipeline::LineStrip) {
4940 const float lineWidth = psD->m_lineWidth;
4941 if (forceUpdate || lineWidth != state
.lineWidth) {
4943 f->glLineWidth(lineWidth);
4947 if (psD->m_topology == QRhiGraphicsPipeline::Patches) {
4948 const int cpCount = psD->m_patchControlPointCount;
4949 if (forceUpdate || cpCount != state
.cpCount) {
4955 f->glUseProgram(psD->program);
7288bool QGles2TextureRenderTarget::create()
7295 const bool hasColorAttachments = m_desc.colorAttachmentCount() > 0;
7296 Q_ASSERT(hasColorAttachments || m_desc.depthTexture());
7297 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
7298 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
7300 if (hasColorAttachments) {
7301 const int count =
int(m_desc.colorAttachmentCount());
7302 if (count > rhiD->caps.maxDrawBuffers) {
7303 qWarning(
"QGles2TextureRenderTarget: Too many color attachments (%d, max is %d)",
7304 count, rhiD->caps.maxDrawBuffers);
7307 if (m_desc.depthTexture() && !rhiD->caps.depthTexture)
7308 qWarning(
"QGles2TextureRenderTarget: Depth texture is not supported and will be ignored");
7310 if (!rhiD->ensureContext())
7313 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments();
7314 it != itEnd; ++it) {
7315 const QRhiColorAttachment &colorAtt(*it);
7316 const QRhiTexture *resolveTexture = colorAtt.resolveTexture();
7317 if (!resolveTexture)
7320 const QRhiTexture *texture = colorAtt.texture();
7321 const QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer();
7322 Q_ASSERT(texture || renderBuffer);
7323 const QRhiTexture::Format sourceFormat = texture ? texture->format()
7324 : renderBuffer->backingFormat();
7325 const bool sourceIsSrgb = texture && texture->flags().testFlag(QRhiTexture::sRGB);
7326 const bool resolveIsSrgb = resolveTexture->flags().testFlag(QRhiTexture::sRGB);
7327 if (sourceFormat != resolveTexture->format() || sourceIsSrgb != resolveIsSrgb) {
7328 qWarning(
"Multisample resolve between different formats "
7329 "(%d, sRGB %d) and (%d, sRGB %d) is not supported.",
7330 int(sourceFormat),
int(sourceIsSrgb),
7331 int(resolveTexture->format()),
int(resolveIsSrgb));
7336 rhiD->f->glGenFramebuffers(1, &framebuffer);
7337 rhiD->f->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
7339 d.colorAttCount = 0;
7340 d.srgbUpdateAndBlend =
false;
7342 int multiViewCount = 0;
7343 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
7344 d.colorAttCount += 1;
7345 const QRhiColorAttachment &colorAtt(*it);
7346 QRhiTexture *texture = colorAtt.texture();
7347 QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer();
7348 Q_ASSERT(texture || renderBuffer);
7350 QGles2Texture *texD =
QRHI_RES(QGles2Texture, texture);
7351 Q_ASSERT(texD->texture && texD->specified);
7352 d.srgbUpdateAndBlend |= texD->flags().testFlag(QRhiTexture::sRGB);
7353 if (colorAtt.resolveTexture())
7354 d.srgbUpdateAndBlend |= colorAtt.resolveTexture()->flags().testFlag(QRhiTexture::sRGB);
7355 if (texD->flags().testFlag(QRhiTexture::ThreeDimensional) || texD->flags().testFlag(QRhiTexture::TextureArray)) {
7356 if (colorAtt.multiViewCount() < 2) {
7357 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture,
7358 colorAtt.level(), colorAtt.layer());
7360 multiViewCount = colorAtt.multiViewCount();
7361 if (texD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture && colorAtt.resolveTexture()) {
7366 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
7367 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7368 GL_COLOR_ATTACHMENT0 + uint(attIndex),
7369 resolveTexD->texture,
7370 colorAtt.resolveLevel(),
7372 colorAtt.resolveLayer(),
7375 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER,
7376 GL_COLOR_ATTACHMENT0 + uint(attIndex),
7383 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
7384 rhiD->glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex),
7385 texD->target + uint(colorAtt.layer()), texD->texture,
7388 if (texD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
7393 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
7395 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
7396 resolveTexD->texture, colorAtt.level(), texD->samples);
7399 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.layer()),
7400 texD->texture, colorAtt.level());
7403 if (attIndex == 0) {
7404 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
7405 d.sampleCount = texD->samples;
7407 }
else if (renderBuffer) {
7408 QGles2RenderBuffer *rbD =
QRHI_RES(QGles2RenderBuffer, renderBuffer);
7409 if (colorAtt.resolveTexture())
7410 d.srgbUpdateAndBlend |= colorAtt.resolveTexture()->flags().testFlag(QRhiTexture::sRGB);
7411 if (rbD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
7416 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
7418 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
7419 resolveTexD->texture, colorAtt.level(), rbD->samples);
7421 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), GL_RENDERBUFFER, rbD->renderbuffer);
7423 if (attIndex == 0) {
7424 d.pixelSize = rbD->pixelSize();
7425 d.sampleCount = rbD->samples;
7430 if (hasDepthStencil && m_desc.depthResolveTexture()) {
7431 const QRhiTexture::Format dstFormat = m_desc.depthResolveTexture()->format();
7432 QRhiTexture::Format srcFormat = QRhiTexture::UnknownFormat;
7433 if (m_desc.depthStencilBuffer())
7434 srcFormat = QRhiTexture::D24S8;
7435 else if (!rhiD->caps.glesMultisampleRenderToTexture)
7436 srcFormat = m_desc.depthTexture()->format();
7438 if (srcFormat != QRhiTexture::UnknownFormat && srcFormat != dstFormat) {
7439 qWarning(
"Multisample depth-stencil source format %d does not match the "
7440 "depthResolveTexture format %d. OpenGL cannot blit between different depth formats; "
7441 "the depth contents will not be resolved.",
7442 int(srcFormat),
int(dstFormat));
7446 if (hasDepthStencil) {
7447 if (m_desc.depthStencilBuffer()) {
7448 QGles2RenderBuffer *depthRbD =
QRHI_RES(QGles2RenderBuffer, m_desc.depthStencilBuffer());
7449 if (rhiD->caps.needsDepthStencilCombinedAttach) {
7451 depthRbD->renderbuffer);
7453 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
7454 depthRbD->renderbuffer);
7455 if (depthRbD->stencilRenderbuffer) {
7456 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7457 depthRbD->stencilRenderbuffer);
7460 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7461 depthRbD->renderbuffer);
7464 if (d.colorAttCount == 0) {
7465 d.pixelSize = depthRbD->pixelSize();
7466 d.sampleCount = depthRbD->samples;
7469 QGles2Texture *depthTexD =
QRHI_RES(QGles2Texture, m_desc.depthTexture());
7470 if (multiViewCount < 2) {
7471 if (depthTexD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && m_desc.depthResolveTexture()) {
7475 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
7476 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthResolveTexD->target,
7477 depthResolveTexD->texture, 0, depthTexD->samples);
7478 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
7479 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthResolveTexD->target,
7480 depthResolveTexD->texture, 0, depthTexD->samples);
7482 }
else if (rhiD->caps.ctxMajor >= 3 && depthTexD->flags().testFlag(QRhiTexture::TextureArray) && m_desc.depthLayer() >= 0) {
7483 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
7484 0, m_desc.depthLayer());
7485 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
7486 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
7487 0, m_desc.depthLayer());
7490 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->target,
7491 depthTexD->texture, 0);
7492 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
7493 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->target,
7494 depthTexD->texture, 0);
7498 if (depthTexD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture) {
7516 if (!m_flags.testFlag(DoNotStoreDepthStencilContents) && !m_desc.depthResolveTexture()) {
7517 qWarning(
"Attempted to create a multiview+multisample QRhiTextureRenderTarget, but DoNotStoreDepthStencilContents was not set."
7518 " This path has no choice but to behave as if DoNotStoreDepthStencilContents was set, because QRhi is forced to create"
7519 " a throwaway non-multisample depth texture here. Set the flag to silence this warning, or set a depthResolveTexture.");
7521 if (m_desc.depthResolveTexture()) {
7522 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
7523 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7524 GL_DEPTH_ATTACHMENT,
7525 depthResolveTexD->texture,
7530 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
7531 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7532 GL_STENCIL_ATTACHMENT,
7533 depthResolveTexD->texture,
7540 if (!nonMsaaThrowawayDepthTexture) {
7541 rhiD->f->glGenTextures(1, &nonMsaaThrowawayDepthTexture);
7544 depthTexD->pixelSize().width(), depthTexD->pixelSize().height(), multiViewCount);
7546 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7547 GL_DEPTH_ATTACHMENT,
7548 nonMsaaThrowawayDepthTexture,
7553 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7554 GL_STENCIL_ATTACHMENT,
7555 nonMsaaThrowawayDepthTexture,
7565 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
7566 0, 0, multiViewCount);
7567 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
7568 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
7569 0, 0, multiViewCount);
7573 if (d.colorAttCount == 0) {
7574 d.pixelSize = depthTexD->pixelSize();
7575 d.sampleCount = depthTexD->samples;
7584 d.rp =
QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
7586 GLenum status = rhiD->f->glCheckFramebufferStatus(GL_FRAMEBUFFER);
7587 if (status != GL_NO_ERROR && status != GL_FRAMEBUFFER_COMPLETE) {
7588 qWarning(
"Framebuffer incomplete: 0x%x", status);
7592 if (rhiD->glObjectLabel)
7593 rhiD->glObjectLabel(GL_FRAMEBUFFER, framebuffer, -1, m_objectName.constData());
7595 QRhiRenderTargetAttachmentTracker::updateResIdList<QGles2Texture, QGles2RenderBuffer>(m_desc, &d.currentResIdList);
7597 rhiD->registerResource(
this);