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")));
881 ctx->getProcAddress(QByteArrayLiteral(
"glTexStorage1D")));
884 GLenum, GLint, GLint, GLsizei, GLenum, GLenum,
const GLvoid *)>(
885 ctx->getProcAddress(QByteArrayLiteral(
"glTexSubImage1D")));
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")));
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();
927 || ctx->hasExtension(
"GL_NV_generate_mipmap_sRGB");
930 const bool hasCoreSrgbTexture = caps
.ctxMajor > 2
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;
1064 const bool hasCoreSrgbWriteControl = caps
.ctxMajor >= 3;
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;
1123 caps
.depthClamp = ctx->hasExtension(
"GL_EXT_depth_clamp") || ctx->hasExtension(
"GL_ARB_depth_clamp");
1132 caps
.properMapBuffer =
f->hasOpenGLExtension(QOpenGLExtensions::MapBufferRange);
1170 || ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_texture_storage"));
1188 GLint maxArraySize = 0;
1199 GLint maxVertexUniformVectors = 0;
1201 GLint maxFragmentUniformVectors = 0;
1205 GLint maxVertexUniformComponents = 0;
1207 GLint maxFragmentUniformComponents = 0;
1209 caps
.maxUniformVectors = qMin(maxVertexUniformComponents, maxFragmentUniformComponents) / 4;
1217 GLint components = 0;
1223 GLint components = 0;
1241 caps
.halfAttributes =
f->hasOpenGLExtension(QOpenGLExtensions::HalfFloatVertex);
1244 caps
.multiView =
f->hasOpenGLExtension(QOpenGLExtensions::MultiView)
1245 &&
f->hasOpenGLExtension(QOpenGLExtensions::MultiViewExtended);
1248 reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei)>(
1249 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultiviewOVR")));
1256 ctx->getProcAddress(QByteArrayLiteral(
"glQueryCounter")));
1258 ctx->getProcAddress(QByteArrayLiteral(
"glGetQueryObjectui64v")));
1270 ctx->getProcAddress(QByteArrayLiteral(
"glObjectLabel")));
1283 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture2DMultisampleEXT")));
1285 ctx->getProcAddress(QByteArrayLiteral(
"glRenderbufferStorageMultisampleEXT")));
1290 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultisampleMultiviewOVR")));
1318 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_draw_indirect")))
1330 && (caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 2)
1331 || ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_base_instance")));
1336 ctx->getProcAddress(QByteArrayLiteral(
"glDrawArraysInstancedBaseInstance")));
1338 ctx->getProcAddress(QByteArrayLiteral(
"glDrawElementsInstancedBaseInstance")));
1340 ctx->getProcAddress(QByteArrayLiteral(
"glDrawElementsInstancedBaseVertexBaseInstance")));
1344 qWarning(
"Failed to resolve glDraw{Arrays,Elements}InstancedBaseInstance{,BaseVertex}; disabling base instance support.");
1353 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_multi_draw_indirect")) ||
1354 ctx->hasExtension(QByteArrayLiteral(
"GL_EXT_multi_draw_indirect")))
1359 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirect")));
1362 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectARB")));
1365 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectEXT")));
1367 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirect")));
1370 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectARB")));
1373 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectEXT")));
1375 qWarning(
"Failed to resolve glMultiDrawArraysIndirect or glMultiDrawElementsIndirect.");
1384 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_shader_draw_parameters")))
1399 if (!caps.copyBuffer && ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_copy_buffer")))
1400 caps
.copyBuffer = ctx->getProcAddress(QByteArrayLiteral(
"glCopyBufferSubData")) !=
nullptr;
1403 && (caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3)
1404 || ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_clear_buffer_object"))))
1407 GLenum, GLenum,
const void *)>(
1408 ctx->getProcAddress(QByteArrayLiteral(
"glClearBufferSubData")));
1418 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_indirect_parameters")))
1423 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectCount")));
1426 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectCountARB")));
1428 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectCount")));
1431 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectCountARB")));
1433 qWarning(
"Failed to resolve glMultiDrawArraysIndirectCount or glMultiDrawElementsIndirectCount.");
1438 nativeHandlesStruct.context = ctx;
3032 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
3035 const bool isCompressed = isCompressedFormat(texD->m_format);
3036 const bool isCubeMap = texD->m_flags.testFlag(QRhiTexture::CubeMap);
3037 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
3038 const bool is1D = texD->m_flags.testFlag(QRhiTexture::OneDimensional);
3039 const bool isArray = texD->m_flags.testFlag(QRhiTexture::TextureArray);
3041 const GLenum effectiveTarget = faceTargetBase + (isCubeMap ? uint(layer) : 0u);
3042 const QPoint dp = subresDesc.destinationTopLeft();
3043 const QByteArray rawData = subresDesc.data();
3045 auto setCmdByNotCompressedData = [&](
const void* data, QSize size, quint32 dataStride)
3047 quint32 bytesPerLine = 0;
3048 quint32 bytesPerPixel = 0;
3049 textureFormatInfo(texD->m_format, size, &bytesPerLine,
nullptr, &bytesPerPixel);
3053 cmd.args.subImage.target = texD->target;
3054 cmd.args.subImage.texture = texD->texture;
3055 cmd.args.subImage.faceTarget = effectiveTarget;
3056 cmd.args.subImage.level = level;
3057 cmd.args.subImage.dx = dp.x();
3058 cmd.args.subImage.dy = is1D && isArray ? layer : dp.y();
3059 cmd.args.subImage.dz = is3D || isArray ? layer : 0;
3060 cmd.args.subImage.w = size.width();
3061 cmd.args.subImage.h = size.height();
3062 cmd.args.subImage.glformat = texD->glformat;
3063 cmd.args.subImage.gltype = texD->gltype;
3065 if (dataStride == 0)
3066 dataStride = bytesPerLine;
3068 cmd.args.subImage.rowStartAlign = (dataStride & 3) ? 1 : 4;
3069 cmd.args.subImage.rowLength = caps
.unpackRowLength ? (bytesPerPixel ? dataStride / bytesPerPixel : 0) : 0;
3071 cmd.args.subImage.data = data;
3074 if (!subresDesc.image().isNull()) {
3075 QImage img = subresDesc.image();
3076 QSize size = img.size();
3077 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
3078 const QPoint sp = subresDesc.sourceTopLeft();
3079 if (!subresDesc.sourceSize().isEmpty())
3080 size = subresDesc.sourceSize();
3081 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
3083 cbD->retainImage(img);
3085 const uchar *data = img.constBits() + sp.y() * img.bytesPerLine() + sp.x() * (qMax(1, img.depth() / 8));
3086 img = QImage(data, size.width(), size.height(), img.bytesPerLine(), img.format());
3088 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
3091 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
3094 setCmdByNotCompressedData(cbD->retainImage(img), size, img.bytesPerLine());
3095 }
else if (!rawData.isEmpty() && isCompressed) {
3096 const int depth = qMax(1, texD->m_depth);
3097 const int arraySize = qMax(0, texD->m_arraySize);
3101 const int face = isCubeMap ? qBound(0, layer, 5) : 0;
3102 const QSize subresSize = q->sizeForMipLevel(level, texD->m_pixelSize);
3103 QSize size = subresDesc.sourceSize().isEmpty() ? subresSize : subresDesc.sourceSize();
3104 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
3111 const bool coversWholeSubres = !is3D && !isArray && dp.isNull() && size == subresSize;
3120 const int mipDepth = is3D ? q->sizeForMipLevel(level, QSize(depth, depth)).width() : 1;
3121 quint32 levelByteSize = 0;
3122 if (!compressedFormatInfo(texD->m_format, subresSize,
nullptr, &levelByteSize,
nullptr))
3124 quint64 byteSize = levelByteSize;
3126 byteSize *= quint64(mipDepth);
3128 byteSize *= quint64(arraySize);
3129 if (byteSize > quint64(
std::numeric_limits<
int>::max())) {
3130 qWarning(
"Compressed texture zero-initialization would need %llu bytes "
3131 "which is too large; skipping", byteSize);
3134 QByteArray zeroBuf(qsizetype(byteSize), 0);
3137 cmd.args.compressedImage.target = texD->target;
3138 cmd.args.compressedImage.texture = texD->texture;
3139 cmd.args.compressedImage.faceTarget = effectiveTarget;
3140 cmd.args.compressedImage.level = level;
3141 cmd.args.compressedImage.glintformat = texD->glintformat;
3142 cmd.args.compressedImage.w = subresSize.width();
3143 cmd.args.compressedImage.h = is1D && isArray ? arraySize : subresSize.height();
3144 cmd.args.compressedImage.depth = is3D ? mipDepth : (isArray ? arraySize : 0);
3145 cmd.args.compressedImage.size =
int(byteSize);
3146 cmd.args.compressedImage.data = cbD->retainData(zeroBuf);
3147 texD->allocatedLevels[face] |= 1u << uint(level);
3153 cmd.args.compressedSubImage.target = texD->target;
3154 cmd.args.compressedSubImage.texture = texD->texture;
3155 cmd.args.compressedSubImage.faceTarget = effectiveTarget;
3156 cmd.args.compressedSubImage.level = level;
3157 cmd.args.compressedSubImage.dx = dp.x();
3158 cmd.args.compressedSubImage.dy = is1D && isArray ? layer : dp.y();
3159 cmd.args.compressedSubImage.dz = is3D || isArray ? layer : 0;
3160 cmd.args.compressedSubImage.w = size.width();
3161 cmd.args.compressedSubImage.h = size.height();
3162 cmd.args.compressedSubImage.glintformat = texD->glintformat;
3163 cmd.args.compressedSubImage.size = rawData.size();
3164 cmd.args.compressedSubImage.data = cbD->retainData(rawData);
3169 cmd.args.compressedImage.target = texD->target;
3170 cmd.args.compressedImage.texture = texD->texture;
3171 cmd.args.compressedImage.faceTarget = effectiveTarget;
3172 cmd.args.compressedImage.level = level;
3173 cmd.args.compressedImage.glintformat = texD->glintformat;
3174 cmd.args.compressedImage.w = size.width();
3175 cmd.args.compressedImage.h = size.height();
3176 cmd.args.compressedImage.depth = 0;
3177 cmd.args.compressedImage.size = rawData.size();
3178 cmd.args.compressedImage.data = cbD->retainData(rawData);
3179 texD->allocatedLevels[face] |= 1u << uint(level);
3181 }
else if (!rawData.isEmpty()) {
3182 QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
3183 : subresDesc.sourceSize();
3184 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
3185 quint32 bytesPerPixel = 0;
3186 textureFormatInfo(texD->m_format, size,
nullptr,
nullptr, &bytesPerPixel);
3187 size = clampedSubResourceUploadSizeForSourceData(size, subresDesc.dataStride(),
3188 bytesPerPixel, rawData.size());
3192 setCmdByNotCompressedData(cbD->retainData(rawData), size, subresDesc.dataStride());
3194 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
3771 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
3775 if (cmd.args.beginFrame.timestampQuery)
3779 f->glGenVertexArrays(1, &
vao);
3780 f->glBindVertexArray(
vao);
3787 f->glVertexAttribDivisor(GLuint(i), 0);
3790 f->glVertexAttribDivisor(GLuint(i), 0);
3797 f->glDisableVertexAttribArray(GLuint(i));
3802 f->glBindVertexArray(0);
3803 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
3804 if (cmd.args.endFrame.timestampQuery)
3809 f->glBindVertexArray(
vao);
3812 f->glViewport(GLint(cmd.args.viewport.x), GLint(cmd.args.viewport.y), GLsizei(cmd.args.viewport.w), GLsizei(cmd.args.viewport.h));
3813 f->glDepthRangef(cmd.args.viewport.d0, cmd.args.viewport.d1);
3816 f->glScissor(cmd.args.scissor.x, cmd.args.scissor.y, cmd.args.scissor.w, cmd.args.scissor.h);
3819 f->glBlendColor(cmd.args.blendConstants.r, cmd.args.blendConstants.g, cmd.args.blendConstants.b, cmd.args.blendConstants.a);
3825 const GLint ref = GLint(cmd.args.stencilRef.ref);
3826 f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), ref, psD->m_stencilReadMask);
3827 f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), ref, psD->m_stencilReadMask);
3828 cbD->graphicsPassState.dynamic.stencilRef = ref;
3829 cbD->graphicsPassState.stencilRef = ref;
3831 qWarning(
"No graphics pipeline active for setStencilRef; ignored");
3839 if (state.lastBindVertexBuffer.ps == psD
3840 && state.lastBindVertexBuffer.buffer == cmd.args.bindVertexBuffer.buffer
3841 && state.lastBindVertexBuffer.offset == cmd.args.bindVertexBuffer.offset
3842 && state.lastBindVertexBuffer.binding == cmd.args.bindVertexBuffer.binding)
3849 state.lastBindVertexBuffer.ps = psD;
3850 state.lastBindVertexBuffer.buffer = cmd.args.bindVertexBuffer.buffer;
3851 state.lastBindVertexBuffer.offset = cmd.args.bindVertexBuffer.offset;
3852 state.lastBindVertexBuffer.binding = cmd.args.bindVertexBuffer.binding;
3854 if (cmd.args.bindVertexBuffer.buffer != state.currentArrayBuffer) {
3855 state.currentArrayBuffer = cmd.args.bindVertexBuffer.buffer;
3857 f->glBindBuffer(GL_ARRAY_BUFFER, state.currentArrayBuffer);
3859 for (
auto it = psD->m_vertexInputLayout.cbeginAttributes(), itEnd = psD->m_vertexInputLayout.cendAttributes();
3862 const int bindingIdx = it->binding();
3863 if (bindingIdx != cmd.args.bindVertexBuffer.binding)
3866 const QRhiVertexInputBinding *inputBinding = psD->m_vertexInputLayout.bindingAt(bindingIdx);
3867 const int stride =
int(inputBinding->stride());
3870 bool normalize =
false;
3871 switch (it->format()) {
3872 case QRhiVertexInputAttribute::Float4:
3876 case QRhiVertexInputAttribute::Float3:
3880 case QRhiVertexInputAttribute::Float2:
3884 case QRhiVertexInputAttribute::Float:
3888 case QRhiVertexInputAttribute::UNormByte4:
3893 case QRhiVertexInputAttribute::UNormByte2:
3898 case QRhiVertexInputAttribute::UNormByte:
3903 case QRhiVertexInputAttribute::UInt4:
3904 type = GL_UNSIGNED_INT;
3907 case QRhiVertexInputAttribute::UInt3:
3908 type = GL_UNSIGNED_INT;
3911 case QRhiVertexInputAttribute::UInt2:
3912 type = GL_UNSIGNED_INT;
3915 case QRhiVertexInputAttribute::UInt:
3916 type = GL_UNSIGNED_INT;
3919 case QRhiVertexInputAttribute::SInt4:
3923 case QRhiVertexInputAttribute::SInt3:
3927 case QRhiVertexInputAttribute::SInt2:
3931 case QRhiVertexInputAttribute::SInt:
3935 case QRhiVertexInputAttribute::Half4:
3939 case QRhiVertexInputAttribute::Half3:
3943 case QRhiVertexInputAttribute::Half2:
3947 case QRhiVertexInputAttribute::Half:
3951 case QRhiVertexInputAttribute::UShort4:
3952 type = GL_UNSIGNED_SHORT;
3955 case QRhiVertexInputAttribute::UShort3:
3956 type = GL_UNSIGNED_SHORT;
3959 case QRhiVertexInputAttribute::UShort2:
3960 type = GL_UNSIGNED_SHORT;
3963 case QRhiVertexInputAttribute::UShort:
3964 type = GL_UNSIGNED_SHORT;
3967 case QRhiVertexInputAttribute::SShort4:
3971 case QRhiVertexInputAttribute::SShort3:
3975 case QRhiVertexInputAttribute::SShort2:
3979 case QRhiVertexInputAttribute::SShort:
3987 const int locationIdx = it->location();
3988 quint32 ofs = it->offset() + cmd.args.bindVertexBuffer.offset;
3989 if (type == GL_UNSIGNED_INT || type == GL_INT) {
3991 f->glVertexAttribIPointer(GLuint(locationIdx), size, type, stride,
3992 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3994 qWarning(
"Current RHI backend does not support IntAttributes. Check supported features.");
4000 f->glVertexAttribPointer(GLuint(locationIdx), size, type, normalize, stride,
4001 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
4006 f->glEnableVertexAttribArray(GLuint(locationIdx));
4008 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance && caps.instancing) {
4009 f->glVertexAttribDivisor(GLuint(locationIdx), inputBinding->instanceStepRate());
4020 f->glVertexAttribDivisor(GLuint(locationIdx), 0);
4026 qWarning(
"No graphics pipeline active for setVertexInput; ignored");
4031 state.indexType = cmd.args.bindIndexBuffer.type;
4032 state.indexStride = state.indexType == GL_UNSIGNED_SHORT ?
sizeof(quint16) :
sizeof(quint32);
4033 state.indexOffset = cmd.args.bindIndexBuffer.offset;
4034 if (state.currentElementArrayBuffer != cmd.args.bindIndexBuffer.buffer) {
4035 state.currentElementArrayBuffer = cmd.args.bindIndexBuffer.buffer;
4036 f->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state.currentElementArrayBuffer);
4043 const bool useBaseInstance = (cmd.args.draw.baseInstance != 0 && caps
.baseInstance);
4046 && (cmd.args.draw.instanceCount != 1 || useBaseInstance);
4048 if (!needsInstancedPath) {
4049 f->glDrawArrays(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount));
4050 }
else if (useBaseInstance) {
4052 GLint(cmd.args.draw.firstVertex)
,
4053 GLsizei(cmd.args.draw.vertexCount)
,
4054 GLsizei(cmd.args.draw.instanceCount)
,
4055 cmd.args.draw.baseInstance
);
4057 f->glDrawArraysInstanced(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount),
4058 GLsizei(cmd.args.draw.instanceCount));
4061 qWarning(
"No graphics pipeline active for draw; ignored");
4069 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4070 quintptr(cmd.args.drawIndexed.firstIndex * state.indexStride + state.indexOffset));
4071 const bool useBaseVertex = (cmd.args.drawIndexed.baseVertex != 0 && caps
.baseVertex);
4072 const bool useBaseInstance = (cmd.args.drawIndexed.baseInstance != 0 && caps
.baseInstance);
4077 && (cmd.args.drawIndexed.instanceCount != 1 || useBaseInstance);
4079 if (!needsInstancedPath) {
4080 if (useBaseVertex) {
4081 f->glDrawElementsBaseVertex(psD->drawMode,
4082 GLsizei(cmd.args.drawIndexed.indexCount),
4085 cmd.args.drawIndexed.baseVertex);
4087 f->glDrawElements(psD->drawMode,
4088 GLsizei(cmd.args.drawIndexed.indexCount),
4092 }
else if (useBaseInstance && useBaseVertex) {
4094 GLsizei(cmd.args.drawIndexed.indexCount)
,
4097 GLsizei(cmd.args.drawIndexed.instanceCount)
,
4098 cmd.args.drawIndexed.baseVertex
,
4099 cmd.args.drawIndexed.baseInstance
);
4100 }
else if (useBaseInstance) {
4102 GLsizei(cmd.args.drawIndexed.indexCount)
,
4105 GLsizei(cmd.args.drawIndexed.instanceCount)
,
4106 cmd.args.drawIndexed.baseInstance
);
4107 }
else if (useBaseVertex) {
4108 f->glDrawElementsInstancedBaseVertex(psD->drawMode,
4109 GLsizei(cmd.args.drawIndexed.indexCount),
4112 GLsizei(cmd.args.drawIndexed.instanceCount),
4113 cmd.args.drawIndexed.baseVertex);
4115 f->glDrawElementsInstanced(psD->drawMode,
4116 GLsizei(cmd.args.drawIndexed.indexCount),
4119 GLsizei(cmd.args.drawIndexed.instanceCount));
4122 qWarning(
"No graphics pipeline active for drawIndexed; ignored");
4132 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4133 quintptr(cmd.args.drawIndirect.offset));
4136 cmd.args.drawIndirect.drawCount
,
4137 cmd.args.drawIndirect.stride
);
4139 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
4140 const quintptr indirectOffset = quintptr(cmd.args.drawIndirect.offset)
4141 + quintptr(i) * cmd.args.drawIndirect.stride;
4142 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(indirectOffset);
4143 f->glDrawArraysIndirect(psD->drawMode,
4149 qWarning(
"No graphics pipeline active for drawIndirect; ignored");
4159 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4160 quintptr(cmd.args.drawIndexedIndirect.offset));
4164 cmd.args.drawIndexedIndirect.drawCount
,
4165 cmd.args.drawIndexedIndirect.stride
);
4167 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
4168 const quintptr indirectOffset = quintptr(cmd.args.drawIndexedIndirect.offset)
4169 + quintptr(i) * cmd.args.drawIndexedIndirect.stride;
4170 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(indirectOffset);
4171 f->glDrawElementsIndirect(psD->drawMode,
4178 qWarning(
"No graphics pipeline active for drawIndexedIndirect; ignored");
4188 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4189 quintptr(cmd.args.drawIndirectCount.offset));
4192 GLintptr(cmd.args.drawIndirectCount.countOffset)
,
4193 cmd.args.drawIndirectCount.maxDrawCount
,
4194 cmd.args.drawIndirectCount.stride
);
4198 qWarning(
"No graphics pipeline active or glMultiDrawArraysIndirectCount unavailable; ignored");
4208 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
4209 quintptr(cmd.args.drawIndexedIndirectCount.offset));
4213 GLintptr(cmd.args.drawIndexedIndirectCount.countOffset)
,
4214 cmd.args.drawIndexedIndirectCount.maxDrawCount
,
4215 cmd.args.drawIndexedIndirectCount.stride
);
4219 qWarning(
"No graphics pipeline active or glMultiDrawElementsIndirectCount unavailable; ignored");
4226 case QGles2CommandBuffer::Command::BindShaderResources:
4227 bindShaderResources(cbD,
4228 cmd.args.bindShaderResources.maybeGraphicsPs,
4229 cmd.args.bindShaderResources.maybeComputePs,
4230 cmd.args.bindShaderResources.srb,
4231 cbD->dynamicOffsetPool.constData() + cmd.args.bindShaderResources.dynamicOffsetPoolOffset,
4232 cmd.args.bindShaderResources.dynamicOffsetCount);
4236 QRhiGraphicsPipeline *maybeGraphicsPs = cmd.args.setPushConstants.maybeGraphicsPs;
4237 QRhiComputePipeline *maybeComputePs = cmd.args.setPushConstants.maybeComputePs;
4238 const QGles2UniformDescriptionVector &uniforms(maybeGraphicsPs
4239 ?
QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->pushConstantUniforms
4240 :
QRHI_RES(QGles2ComputePipeline, maybeComputePs)->pushConstantUniforms);
4242 ?
QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->uniformState.data()
4243 :
QRHI_RES(QGles2ComputePipeline, maybeComputePs)->uniformState.data();
4244 setUniformsFromBlock(uniforms, -1,
4245 cbD->pushConstantPool.constData() + cmd.args.setPushConstants.dataOffset,
4246 cmd.args.setPushConstants.size, 0, uniformState);
4253 cbD->graphicsPassState.dynamic.stencilRef = 0;
4254 QVarLengthArray<GLenum, 8> bufs;
4255 GLuint fbo = cmd.args.bindFramebuffer.fbo;
4257 fbo = ctx->defaultFramebufferObject();
4258 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4260 const int colorAttCount = cmd.args.bindFramebuffer.colorAttCount;
4261 bufs.append(colorAttCount > 0 ? GL_COLOR_ATTACHMENT0 : GL_NONE);
4263 for (
int i = 1; i < colorAttCount; ++i)
4264 bufs.append(GL_COLOR_ATTACHMENT0 + uint(i));
4267 if (cmd.args.bindFramebuffer.stereo && cmd.args.bindFramebuffer.stereoTarget == QRhiSwapChain::RightBuffer)
4273 f->glDrawBuffers(bufs.count(), bufs.constData());
4275 if (cmd.args.bindFramebuffer.srgb)
4283 f->glDisable(GL_SCISSOR_TEST);
4284 if (cmd.args.clear.mask & GL_COLOR_BUFFER_BIT) {
4285 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4286 f->glClearColor(cmd.args.clear.c[0], cmd.args.clear.c[1], cmd.args.clear.c[2], cmd.args.clear.c[3]);
4288 if (cmd.args.clear.mask & GL_DEPTH_BUFFER_BIT) {
4289 f->glDepthMask(GL_TRUE);
4290 f->glClearDepthf(cmd.args.clear.d);
4292 if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT) {
4293 f->glStencilMask(0xFF);
4294 f->glClearStencil(GLint(cmd.args.clear.s));
4296 f->glClear(cmd.args.clear.mask);
4297 cbD->graphicsPassState.reset();
4300 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.bufferSubData.target, cmd.args.bufferSubData.buffer);
4301 f->glBufferSubData(cmd.args.bufferSubData.target, cmd.args.bufferSubData.offset, cmd.args.bufferSubData.size,
4302 cmd.args.bufferSubData.data);
4305 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.clearBufferSubData.target, cmd.args.clearBufferSubData.buffer);
4307 cmd.args.clearBufferSubData.offset
, cmd.args.clearBufferSubData.size
,
4312 QRhiReadbackResult *result = cmd.args.getBufferSubData.result;
4313 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.getBufferSubData.target, cmd.args.getBufferSubData.buffer);
4316 void *p =
f->glMapBufferRange(cmd.args.getBufferSubData.target,
4317 cmd.args.getBufferSubData.offset,
4318 cmd.args.getBufferSubData.size,
4321 result->data.resize(cmd.args.getBufferSubData.size);
4322 memcpy(result->data.data(), p, size_t(cmd.args.getBufferSubData.size));
4323 f->glUnmapBuffer(cmd.args.getBufferSubData.target);
4327 result->data.resize(cmd.args.getBufferSubData.size);
4328 f->glGetBufferSubData(cmd.args.getBufferSubData.target,
4329 cmd.args.getBufferSubData.offset,
4330 cmd.args.getBufferSubData.size,
4331 result->data.data());
4333 if (result->completed)
4334 result->completed();
4341 cmd.args.copyBuf.srcOffset, cmd.args.copyBuf.dstOffset,
4342 cmd.args.copyBuf.size);
4349 f->glGenFramebuffers(1, &fbo);
4350 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4354 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.copyTex.srcTexture,
4355 cmd.args.copyTex.srcLevel, cmd.args.copyTex.srcZ);
4358 cmd.args.copyTex.srcTarget, cmd.args.copyTex.srcTexture,
4359 cmd.args.copyTex.srcLevel);
4361 f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4362 cmd.args.copyTex.srcFaceTarget, cmd.args.copyTex.srcTexture, cmd.args.copyTex.srcLevel);
4364 f->glBindTexture(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstTexture);
4366 f->glCopyTexSubImage3D(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstLevel,
4367 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY, cmd.args.copyTex.dstZ,
4368 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
4369 cmd.args.copyTex.w, cmd.args.copyTex.h);
4372 cmd.args.copyTex.dstX
, cmd.args.copyTex.srcX
,
4373 cmd.args.copyTex.srcY
, cmd.args.copyTex.w
);
4375 f->glCopyTexSubImage2D(cmd.args.copyTex.dstFaceTarget, cmd.args.copyTex.dstLevel,
4376 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY,
4377 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
4378 cmd.args.copyTex.w, cmd.args.copyTex.h);
4380 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4381 f->glDeleteFramebuffers(1, &fbo);
4386 QRhiReadbackResult *result = cmd.args.readPixels.result;
4387 GLuint tex = cmd.args.readPixels.texture;
4390 result->pixelSize = QSize(cmd.args.readPixels.w, cmd.args.readPixels.h);
4392 result->format = cmd.args.readPixels.format;
4393 mipLevel = cmd.args.readPixels.level;
4395 f->glGenFramebuffers(1, &fbo);
4396 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4397 const auto attach = [&](GLenum attachment) {
4398 if (cmd.args.readPixels.slice3D >= 0) {
4399 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment,
4400 tex, mipLevel, cmd.args.readPixels.slice3D);
4401 }
else if (cmd.args.readPixels.readTarget ==
GL_TEXTURE_1D) {
4403 cmd.args.readPixels.readTarget, tex, mipLevel);
4405 f->glFramebufferTexture2D(GL_FRAMEBUFFER, attachment,
4406 cmd.args.readPixels.readTarget, tex, mipLevel);
4410 if (isDepthTextureFormat(result->format)) {
4411 attach(GL_DEPTH_ATTACHMENT);
4412 if (isStencilSupportingFormat(result->format))
4413 attach(GL_STENCIL_ATTACHMENT);
4417 f->glReadBuffer(GL_NONE);
4419 attach(GL_COLOR_ATTACHMENT0);
4423 result->format = QRhiTexture::RGBA8;
4426 const int x = cmd.args.readPixels.x;
4427 const int y = cmd.args.readPixels.y;
4428 const int w = cmd.args.readPixels.w;
4429 const int h = cmd.args.readPixels.h;
4433 if (result->format == QRhiTexture::R8 || result->format == QRhiTexture::RED_OR_ALPHA8) {
4434 result->data.resizeForOverwrite(w * h);
4436 tmpBuf.resizeForOverwrite(w * h * 4);
4438 const quint8 *srcBase =
reinterpret_cast<
const quint8 *>(tmpBuf.constData());
4439 quint8 *dstBase =
reinterpret_cast<quint8 *>(result->data.data());
4440 const int componentIndex = result->format == QRhiTexture::R8
4441 || isFeatureSupported(QRhi::RedOrAlpha8IsRed)
4444 for (
int y = 0; y < h; ++y) {
4445 const quint8 *src = srcBase + y * w * 4;
4446 quint8 *dst = dstBase + y * w;
4448 while (count-- > 0) {
4449 *dst++ = src[componentIndex];
4456 [[maybe_unused]] GLenum glintformat;
4457 [[maybe_unused]] GLenum glsizedintformat;
4460 toGlTextureFormat(result->format, {}, caps,
4461 &glintformat, &glsizedintformat, &glformat, &gltype);
4463 textureFormatInfo(result->format, result->pixelSize,
nullptr, &byteSize,
nullptr);
4464 result->data.resizeForOverwrite(byteSize);
4466 f->glPixelStorei(GL_PACK_ALIGNMENT, 1);
4467 f->glReadPixels(x, y, w, h, glformat, gltype, result->data.data());
4468 f->glPixelStorei(GL_PACK_ALIGNMENT, 4);
4472 if (result->format == QRhiTexture::D24 || result->format == QRhiTexture::D32FS8) {
4473 const bool isD24 = result->format == QRhiTexture::D24;
4474 const quint32 mask = isD24 ? 0xFFFFFF00u : 0xFFu;
4475 char *p = result->data.data();
4476 for (qsizetype i = isD24 ? 0 : 1, count = result->data.size() / 4; i < count; i += isD24 ? 1 : 2)
4477 qToUnaligned(qFromUnaligned<quint32>(p + i * 4) & mask, p + i * 4);
4482 quint32 byteSize = 0;
4483 textureFormatInfo(result->format, result->pixelSize,
nullptr, &byteSize,
nullptr);
4484 result->data.fill(
'\0', byteSize);
4487 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4488 f->glDeleteFramebuffers(1, &fbo);
4490 if (result->completed)
4491 result->completed();
4495 f->glBindTexture(cmd.args.subImage.target, cmd.args.subImage.texture);
4496 if (cmd.args.subImage.rowStartAlign != 4)
4497 f->glPixelStorei(GL_UNPACK_ALIGNMENT, cmd.args.subImage.rowStartAlign);
4498 if (cmd.args.subImage.rowLength != 0)
4501 f->glTexSubImage3D(cmd.args.subImage.target, cmd.args.subImage.level,
4502 cmd.args.subImage.dx, cmd.args.subImage.dy, cmd.args.subImage.dz,
4503 cmd.args.subImage.w, cmd.args.subImage.h, 1,
4504 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
4505 cmd.args.subImage.data);
4508 cmd.args.subImage.dx
, cmd.args.subImage.w
,
4509 cmd.args.subImage.glformat
, cmd.args.subImage.gltype
,
4510 cmd.args.subImage.data
);
4512 f->glTexSubImage2D(cmd.args.subImage.faceTarget, cmd.args.subImage.level,
4513 cmd.args.subImage.dx, cmd.args.subImage.dy,
4514 cmd.args.subImage.w, cmd.args.subImage.h,
4515 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
4516 cmd.args.subImage.data);
4518 if (cmd.args.subImage.rowStartAlign != 4)
4519 f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
4520 if (cmd.args.subImage.rowLength != 0)
4524 f->glBindTexture(cmd.args.compressedImage.target, cmd.args.compressedImage.texture);
4526 f->glCompressedTexImage3D(cmd.args.compressedImage.target, cmd.args.compressedImage.level,
4527 cmd.args.compressedImage.glintformat,
4528 cmd.args.compressedImage.w, cmd.args.compressedImage.h, cmd.args.compressedImage.depth,
4529 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
4530 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
4532 cmd.args.compressedImage.target
, cmd.args.compressedImage.level
,
4533 cmd.args.compressedImage.glintformat
, cmd.args.compressedImage.w
, 0
,
4534 cmd.args.compressedImage.size
, cmd.args.compressedImage.data
);
4536 f->glCompressedTexImage2D(cmd.args.compressedImage.faceTarget, cmd.args.compressedImage.level,
4537 cmd.args.compressedImage.glintformat,
4538 cmd.args.compressedImage.w, cmd.args.compressedImage.h,
4539 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
4543 f->glBindTexture(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.texture);
4545 f->glCompressedTexSubImage3D(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.level,
4546 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy, cmd.args.compressedSubImage.dz,
4547 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h, 1,
4548 cmd.args.compressedSubImage.glintformat,
4549 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
4550 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
4552 cmd.args.compressedSubImage.target
, cmd.args.compressedSubImage.level
,
4553 cmd.args.compressedSubImage.dx
, cmd.args.compressedSubImage.w
,
4554 cmd.args.compressedSubImage.glintformat
, cmd.args.compressedSubImage.size
,
4555 cmd.args.compressedSubImage.data
);
4557 f->glCompressedTexSubImage2D(cmd.args.compressedSubImage.faceTarget, cmd.args.compressedSubImage.level,
4558 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy,
4559 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h,
4560 cmd.args.compressedSubImage.glintformat,
4561 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
4568 cbD->graphicsPassState.reset();
4569 f->glDisable(GL_SCISSOR_TEST);
4571 f->glGenFramebuffers(2, fbo);
4573 const bool ds = cmd.args.blitFromRenderbuffer.isDepthStencil;
4574 const bool hasStencil = ds && cmd.args.blitFromRenderbuffer.hasStencil;
4577 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4580 const GLuint srcStencilRb = cmd.args.blitFromRenderbuffer.stencilRenderbuffer
4581 ? cmd.args.blitFromRenderbuffer.stencilRenderbuffer
4582 : cmd.args.blitFromRenderbuffer.renderbuffer;
4584 GL_RENDERBUFFER, srcStencilRb);
4588 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4594 cmd.args.blitFromRenderbuffer.dstTexture,
4595 cmd.args.blitFromRenderbuffer.dstLevel,
4596 cmd.args.blitFromRenderbuffer.dstLayer);
4599 cmd.args.blitFromRenderbuffer.dstTexture,
4600 cmd.args.blitFromRenderbuffer.dstLevel,
4601 cmd.args.blitFromRenderbuffer.dstLayer);
4605 cmd.args.blitFromRenderbuffer.dstTexture,
4606 cmd.args.blitFromRenderbuffer.dstLevel,
4607 cmd.args.blitFromRenderbuffer.dstLayer);
4611 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
4612 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4614 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
4615 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4618 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromRenderbuffer.target,
4619 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4622 if (ds && !caps
.gles) {
4623 f->glReadBuffer(GL_NONE);
4624 const GLenum noBuf = GL_NONE;
4625 f->glDrawBuffers(1, &noBuf);
4627 const GLbitfield rbBlitMask = ds ? (GL_DEPTH_BUFFER_BIT | (hasStencil ? GL_STENCIL_BUFFER_BIT : 0))
4628 : GL_COLOR_BUFFER_BIT;
4629 f->glBlitFramebuffer(0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
4630 0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
4633 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4634 f->glDeleteFramebuffers(2, fbo);
4641 cbD->graphicsPassState.reset();
4642 f->glDisable(GL_SCISSOR_TEST);
4644 f->glGenFramebuffers(2, fbo);
4646 const bool ds = cmd.args.blitFromTexture.isDepthStencil;
4647 const bool hasStencil = ds && cmd.args.blitFromTexture.hasStencil;
4651 cmd.args.blitFromTexture.srcTexture,
4652 cmd.args.blitFromTexture.srcLevel,
4653 cmd.args.blitFromTexture.srcLayer);
4656 cmd.args.blitFromTexture.srcTexture,
4657 cmd.args.blitFromTexture.srcLevel,
4658 cmd.args.blitFromTexture.srcLayer);
4662 cmd.args.blitFromTexture.srcTexture,
4663 cmd.args.blitFromTexture.srcLevel,
4664 cmd.args.blitFromTexture.srcLayer);
4668 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
4669 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4671 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
4672 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4675 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.srcTarget,
4676 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4683 cmd.args.blitFromTexture.dstTexture,
4684 cmd.args.blitFromTexture.dstLevel,
4685 cmd.args.blitFromTexture.dstLayer);
4688 cmd.args.blitFromTexture.dstTexture,
4689 cmd.args.blitFromTexture.dstLevel,
4690 cmd.args.blitFromTexture.dstLayer);
4694 cmd.args.blitFromTexture.dstTexture,
4695 cmd.args.blitFromTexture.dstLevel,
4696 cmd.args.blitFromTexture.dstLayer);
4700 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
4701 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4703 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
4704 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4707 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.dstTarget,
4708 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4711 if (ds && !caps
.gles) {
4712 f->glReadBuffer(GL_NONE);
4713 const GLenum noBuf = GL_NONE;
4714 f->glDrawBuffers(1, &noBuf);
4716 const GLbitfield texBlitMask = ds ? (GL_DEPTH_BUFFER_BIT | (hasStencil ? GL_STENCIL_BUFFER_BIT : 0))
4717 : GL_COLOR_BUFFER_BIT;
4718 f->glBlitFramebuffer(0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
4719 0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
4722 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4723 f->glDeleteFramebuffers(2, fbo);
4727 f->glBindTexture(cmd.args.genMip.target, cmd.args.genMip.texture);
4728 f->glGenerateMipmap(cmd.args.genMip.target);
4733 f->glUseProgram(psD->program);
4737 f->glDispatchCompute(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
4742 f->glDispatchComputeIndirect(GLintptr(cmd.args.dispatchIndirect.offset));
4750 GLbitfield barriers = 0;
4759 for (
const auto &[rhiB, trackedB]: tracker.buffers()) {
4761 QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(trackedB.stateAtPassBegin.access);
4762 if (bufferAccessIsWrite(accessBeforePass))
4763 barriers |= barriersForBuffer();
4765 for (
const auto &[rhiT, trackedT]: tracker.textures()) {
4767 QGles2Texture::Access accessBeforePass = QGles2Texture::Access(trackedT.stateAtPassBegin.access);
4768 if (textureAccessIsWrite(accessBeforePass))
4769 barriers |= barriersForTexture();
4772 f->glMemoryBarrier(barriers);
4777 f->glMemoryBarrier(cmd.args.barrier.barriers);
4781 f->glBindFramebuffer(GL_FRAMEBUFFER, cmd.args.invalidateFramebuffer.fbo);
4783 cmd.args.invalidateFramebuffer.attCount,
4784 cmd.args.invalidateFramebuffer.att);
4794 f->glVertexAttribDivisor(GLuint(i), 0);
4797 f->glVertexAttribDivisor(GLuint(i), 0);
4804 const bool forceUpdate = !state
.valid;
4807 const bool scissor = psD->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor);
4808 if (forceUpdate || scissor != state
.scissor) {
4811 f->glEnable(GL_SCISSOR_TEST);
4813 f->glDisable(GL_SCISSOR_TEST);
4816 const bool cullFace = psD->m_cullMode != QRhiGraphicsPipeline::None;
4817 const GLenum cullMode = cullFace ? toGlCullMode(psD->m_cullMode) : GL_NONE;
4818 if (forceUpdate || cullFace != state
.cullFace || cullMode != state.cullMode) {
4820 state.cullMode = cullMode;
4822 f->glEnable(GL_CULL_FACE);
4823 f->glCullFace(cullMode);
4825 f->glDisable(GL_CULL_FACE);
4829 const GLenum frontFace = toGlFrontFace(psD->m_frontFace);
4830 if (forceUpdate || frontFace != state.frontFace) {
4831 state.frontFace = frontFace;
4832 f->glFrontFace(frontFace);
4835 const GLenum polygonMode = toGlPolygonMode(psD->m_polygonMode);
4836 if (
glPolygonMode && (forceUpdate || polygonMode != state.polygonMode)) {
4837 state.polygonMode = polygonMode;
4841 if (!psD->m_targetBlends.isEmpty()) {
4843 bool anyBlendEnabled =
false;
4844 for (
const auto targetBlend : psD->m_targetBlends) {
4845 const QGles2CommandBuffer::GraphicsPassState::ColorMask colorMask = {
4846 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::R),
4847 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::G),
4848 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::B),
4849 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::A)
4851 if (forceUpdate || colorMask != state.colorMask[buffer]) {
4852 state.colorMask[buffer] = colorMask;
4853 if (caps.perRenderTargetBlending)
4854 f->glColorMaski(buffer, colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4856 f->glColorMask(colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4859 const bool blendEnabled = targetBlend.enable;
4860 const QGles2CommandBuffer::GraphicsPassState::Blend blend = {
4861 toGlBlendFactor(targetBlend.srcColor),
4862 toGlBlendFactor(targetBlend.dstColor),
4863 toGlBlendFactor(targetBlend.srcAlpha),
4864 toGlBlendFactor(targetBlend.dstAlpha),
4865 toGlBlendOp(targetBlend.opColor),
4866 toGlBlendOp(targetBlend.opAlpha)
4868 anyBlendEnabled |= blendEnabled;
4869 if (forceUpdate || blendEnabled != state.blendEnabled[buffer] || (blendEnabled && blend != state.blend[buffer])) {
4870 state.blendEnabled[buffer] = blendEnabled;
4872 state.blend[buffer] = blend;
4873 if (caps.perRenderTargetBlending) {
4874 f->glBlendFuncSeparatei(buffer, blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4875 f->glBlendEquationSeparatei(buffer, blend.opColor, blend.opAlpha);
4877 f->glBlendFuncSeparate(blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4878 f->glBlendEquationSeparate(blend.opColor, blend.opAlpha);
4883 if (!caps.perRenderTargetBlending)
4886 if (anyBlendEnabled)
4887 f->glEnable(GL_BLEND);
4889 f->glDisable(GL_BLEND);
4892 if (forceUpdate || colorMask
!= state.colorMask[0]) {
4893 state.colorMask[0] = colorMask;
4894 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4896 const bool blendEnabled =
false;
4899 f->glDisable(GL_BLEND);
4903 const bool depthTest = psD->m_depthTest;
4904 if (forceUpdate || depthTest != state
.depthTest) {
4907 f->glEnable(GL_DEPTH_TEST);
4909 f->glDisable(GL_DEPTH_TEST);
4912 const bool depthWrite = psD->m_depthWrite;
4913 if (forceUpdate || depthWrite != state
.depthWrite) {
4915 f->glDepthMask(depthWrite);
4918 const bool depthClamp = psD->m_depthClamp;
4927 const GLenum depthFunc = toGlCompareOp(psD->m_depthOp);
4928 if (forceUpdate || depthFunc != state.depthFunc) {
4929 state.depthFunc = depthFunc;
4930 f->glDepthFunc(depthFunc);
4933 const bool stencilTest = psD->m_stencilTest;
4934 const GLuint stencilReadMask = psD->m_stencilReadMask;
4935 const GLuint stencilWriteMask = psD->m_stencilWriteMask;
4938 const GLint stencilRef = psD->m_flags.testFlag(QRhiGraphicsPipeline::UsesStencilRef)
4939 ? state.dynamic.stencilRef : 0;
4941 toGlCompareOp(psD->m_stencilFront.compareOp),
4942 toGlStencilOp(psD->m_stencilFront.failOp),
4943 toGlStencilOp(psD->m_stencilFront.depthFailOp),
4944 toGlStencilOp(psD->m_stencilFront.passOp)
4947 toGlCompareOp(psD->m_stencilBack.compareOp),
4948 toGlStencilOp(psD->m_stencilBack.failOp),
4949 toGlStencilOp(psD->m_stencilBack.depthFailOp),
4950 toGlStencilOp(psD->m_stencilBack.passOp)
4954 && (stencilReadMask != state.stencilReadMask || stencilWriteMask != state.stencilWriteMask
4955 || stencilRef != state.stencilRef
4956 || stencilFront != state.stencil[0] || stencilBack != state.stencil[1])))
4960 state.stencilReadMask = stencilReadMask;
4961 state.stencilWriteMask = stencilWriteMask;
4962 state.stencilRef = stencilRef;
4963 state.stencil[0] = stencilFront;
4964 state.stencil[1] = stencilBack;
4966 f->glEnable(GL_STENCIL_TEST);
4968 f->glStencilFuncSeparate(GL_FRONT, stencilFront.func, stencilRef, stencilReadMask);
4969 f->glStencilOpSeparate(GL_FRONT, stencilFront.failOp, stencilFront.zfailOp, stencilFront.zpassOp);
4970 f->glStencilMaskSeparate(GL_FRONT, stencilWriteMask);
4972 f->glStencilFuncSeparate(GL_BACK, stencilBack.func, stencilRef, stencilReadMask);
4973 f->glStencilOpSeparate(GL_BACK, stencilBack.failOp, stencilBack.zfailOp, stencilBack.zpassOp);
4974 f->glStencilMaskSeparate(GL_BACK, stencilWriteMask);
4976 f->glDisable(GL_STENCIL_TEST);
4980 const bool polyOffsetFill = psD->m_depthBias != 0 || !qFuzzyIsNull(psD->m_slopeScaledDepthBias);
4981 const float polyOffsetFactor = psD->m_slopeScaledDepthBias;
4982 const float polyOffsetUnits = psD->m_depthBias;
4989 if (polyOffsetFill) {
4990 f->glPolygonOffset(polyOffsetFactor, polyOffsetUnits);
4991 f->glEnable(GL_POLYGON_OFFSET_FILL);
4993 f->glDisable(GL_POLYGON_OFFSET_FILL);
4997 if (psD->m_topology == QRhiGraphicsPipeline::Lines || psD->m_topology == QRhiGraphicsPipeline::LineStrip) {
4998 const float lineWidth = psD->m_lineWidth;
4999 if (forceUpdate || lineWidth != state
.lineWidth) {
5001 f->glLineWidth(lineWidth);
5005 if (psD->m_topology == QRhiGraphicsPipeline::Patches) {
5006 const int cpCount = psD->m_patchControlPointCount;
5007 if (forceUpdate || cpCount != state
.cpCount) {
5013 f->glUseProgram(psD->program);
7375bool QGles2TextureRenderTarget::create()
7382 const bool hasColorAttachments = m_desc.colorAttachmentCount() > 0;
7383 Q_ASSERT(hasColorAttachments || m_desc.depthTexture());
7384 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
7385 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
7387 if (hasColorAttachments) {
7388 const int count =
int(m_desc.colorAttachmentCount());
7389 if (count > rhiD->caps.maxDrawBuffers) {
7390 qWarning(
"QGles2TextureRenderTarget: Too many color attachments (%d, max is %d)",
7391 count, rhiD->caps.maxDrawBuffers);
7394 if (m_desc.depthTexture() && !rhiD->caps.depthTexture)
7395 qWarning(
"QGles2TextureRenderTarget: Depth texture is not supported and will be ignored");
7397 if (!rhiD->ensureContext())
7400 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments();
7401 it != itEnd; ++it) {
7402 const QRhiColorAttachment &colorAtt(*it);
7403 const QRhiTexture *resolveTexture = colorAtt.resolveTexture();
7404 if (!resolveTexture)
7407 const QRhiTexture *texture = colorAtt.texture();
7408 const QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer();
7409 Q_ASSERT(texture || renderBuffer);
7410 const QRhiTexture::Format sourceFormat = texture ? texture->format()
7411 : renderBuffer->backingFormat();
7412 const bool sourceIsSrgb = texture && texture->flags().testFlag(QRhiTexture::sRGB);
7413 const bool resolveIsSrgb = resolveTexture->flags().testFlag(QRhiTexture::sRGB);
7414 if (sourceFormat != resolveTexture->format() || sourceIsSrgb != resolveIsSrgb) {
7415 qWarning(
"Multisample resolve between different formats "
7416 "(%d, sRGB %d) and (%d, sRGB %d) is not supported.",
7417 int(sourceFormat),
int(sourceIsSrgb),
7418 int(resolveTexture->format()),
int(resolveIsSrgb));
7423 rhiD->f->glGenFramebuffers(1, &framebuffer);
7424 rhiD->f->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
7426 d.colorAttCount = 0;
7427 d.srgbUpdateAndBlend =
false;
7429 int multiViewCount = 0;
7430 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
7431 d.colorAttCount += 1;
7432 const QRhiColorAttachment &colorAtt(*it);
7433 QRhiTexture *texture = colorAtt.texture();
7434 QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer();
7435 Q_ASSERT(texture || renderBuffer);
7437 QGles2Texture *texD =
QRHI_RES(QGles2Texture, texture);
7438 Q_ASSERT(texD->texture && texD->specified);
7439 d.srgbUpdateAndBlend |= texD->flags().testFlag(QRhiTexture::sRGB);
7440 if (colorAtt.resolveTexture())
7441 d.srgbUpdateAndBlend |= colorAtt.resolveTexture()->flags().testFlag(QRhiTexture::sRGB);
7442 if (texD->flags().testFlag(QRhiTexture::ThreeDimensional) || texD->flags().testFlag(QRhiTexture::TextureArray)) {
7443 if (colorAtt.multiViewCount() < 2) {
7444 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture,
7445 colorAtt.level(), colorAtt.layer());
7447 multiViewCount = colorAtt.multiViewCount();
7448 if (texD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture && colorAtt.resolveTexture()) {
7453 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
7454 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7455 GL_COLOR_ATTACHMENT0 + uint(attIndex),
7456 resolveTexD->texture,
7457 colorAtt.resolveLevel(),
7459 colorAtt.resolveLayer(),
7462 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER,
7463 GL_COLOR_ATTACHMENT0 + uint(attIndex),
7470 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
7471 rhiD->glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex),
7472 texD->target + uint(colorAtt.layer()), texD->texture,
7475 if (texD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
7480 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
7482 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
7483 resolveTexD->texture, colorAtt.level(), texD->samples);
7486 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.layer()),
7487 texD->texture, colorAtt.level());
7490 if (attIndex == 0) {
7491 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
7492 d.sampleCount = texD->samples;
7494 }
else if (renderBuffer) {
7495 QGles2RenderBuffer *rbD =
QRHI_RES(QGles2RenderBuffer, renderBuffer);
7496 if (colorAtt.resolveTexture())
7497 d.srgbUpdateAndBlend |= colorAtt.resolveTexture()->flags().testFlag(QRhiTexture::sRGB);
7498 if (rbD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
7503 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
7505 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
7506 resolveTexD->texture, colorAtt.level(), rbD->samples);
7508 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), GL_RENDERBUFFER, rbD->renderbuffer);
7510 if (attIndex == 0) {
7511 d.pixelSize = rbD->pixelSize();
7512 d.sampleCount = rbD->samples;
7517 if (hasDepthStencil && m_desc.depthResolveTexture()) {
7518 const QRhiTexture::Format dstFormat = m_desc.depthResolveTexture()->format();
7519 QRhiTexture::Format srcFormat = QRhiTexture::UnknownFormat;
7520 if (m_desc.depthStencilBuffer())
7521 srcFormat = QRhiTexture::D24S8;
7522 else if (!rhiD->caps.glesMultisampleRenderToTexture)
7523 srcFormat = m_desc.depthTexture()->format();
7525 if (srcFormat != QRhiTexture::UnknownFormat && srcFormat != dstFormat) {
7526 qWarning(
"Multisample depth-stencil source format %d does not match the "
7527 "depthResolveTexture format %d. OpenGL cannot blit between different depth formats; "
7528 "the depth contents will not be resolved.",
7529 int(srcFormat),
int(dstFormat));
7533 if (hasDepthStencil) {
7534 if (m_desc.depthStencilBuffer()) {
7535 QGles2RenderBuffer *depthRbD =
QRHI_RES(QGles2RenderBuffer, m_desc.depthStencilBuffer());
7536 if (rhiD->caps.needsDepthStencilCombinedAttach) {
7538 depthRbD->renderbuffer);
7540 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
7541 depthRbD->renderbuffer);
7542 if (depthRbD->stencilRenderbuffer) {
7543 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7544 depthRbD->stencilRenderbuffer);
7547 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7548 depthRbD->renderbuffer);
7551 if (d.colorAttCount == 0) {
7552 d.pixelSize = depthRbD->pixelSize();
7553 d.sampleCount = depthRbD->samples;
7556 QGles2Texture *depthTexD =
QRHI_RES(QGles2Texture, m_desc.depthTexture());
7557 if (multiViewCount < 2) {
7558 if (depthTexD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && m_desc.depthResolveTexture()) {
7562 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
7563 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthResolveTexD->target,
7564 depthResolveTexD->texture, 0, depthTexD->samples);
7565 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
7566 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthResolveTexD->target,
7567 depthResolveTexD->texture, 0, depthTexD->samples);
7569 }
else if (rhiD->caps.ctxMajor >= 3 && depthTexD->flags().testFlag(QRhiTexture::TextureArray) && m_desc.depthLayer() >= 0) {
7570 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
7571 0, m_desc.depthLayer());
7572 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
7573 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
7574 0, m_desc.depthLayer());
7577 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->target,
7578 depthTexD->texture, 0);
7579 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
7580 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->target,
7581 depthTexD->texture, 0);
7585 if (depthTexD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture) {
7603 if (!m_flags.testFlag(DoNotStoreDepthStencilContents) && !m_desc.depthResolveTexture()) {
7604 qWarning(
"Attempted to create a multiview+multisample QRhiTextureRenderTarget, but DoNotStoreDepthStencilContents was not set."
7605 " This path has no choice but to behave as if DoNotStoreDepthStencilContents was set, because QRhi is forced to create"
7606 " a throwaway non-multisample depth texture here. Set the flag to silence this warning, or set a depthResolveTexture.");
7608 if (m_desc.depthResolveTexture()) {
7609 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
7610 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7611 GL_DEPTH_ATTACHMENT,
7612 depthResolveTexD->texture,
7617 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
7618 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7619 GL_STENCIL_ATTACHMENT,
7620 depthResolveTexD->texture,
7627 if (!nonMsaaThrowawayDepthTexture) {
7628 rhiD->f->glGenTextures(1, &nonMsaaThrowawayDepthTexture);
7631 depthTexD->pixelSize().width(), depthTexD->pixelSize().height(), multiViewCount);
7633 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7634 GL_DEPTH_ATTACHMENT,
7635 nonMsaaThrowawayDepthTexture,
7640 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7641 GL_STENCIL_ATTACHMENT,
7642 nonMsaaThrowawayDepthTexture,
7652 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
7653 0, 0, multiViewCount);
7654 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
7655 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
7656 0, 0, multiViewCount);
7660 if (d.colorAttCount == 0) {
7661 d.pixelSize = depthTexD->pixelSize();
7662 d.sampleCount = depthTexD->samples;
7671 d.rp =
QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
7673 GLenum status = rhiD->f->glCheckFramebufferStatus(GL_FRAMEBUFFER);
7674 if (status != GL_NO_ERROR && status != GL_FRAMEBUFFER_COMPLETE) {
7675 qWarning(
"Framebuffer incomplete: 0x%x", status);
7679 if (rhiD->glObjectLabel)
7680 rhiD->glObjectLabel(GL_FRAMEBUFFER, framebuffer, -1, m_objectName.constData());
7682 QRhiRenderTargetAttachmentTracker::updateResIdList<QGles2Texture, QGles2RenderBuffer>(m_desc, &d.currentResIdList);
7684 rhiD->registerResource(
this);