818 Q_ASSERT(fallbackSurface);
822 ctx =
new QOpenGLContext;
823 ctx->setFormat(requestedFormat);
824 if (maybeShareContext) {
825 ctx->setShareContext(maybeShareContext);
827 ctx->setScreen(maybeWindow->screen());
829 ctx->setScreen(maybeShareContext->screen());
830 }
else if (QOpenGLContext *shareContext = QOpenGLContext::globalShareContext()) {
831 ctx->setShareContext(shareContext);
833 ctx->setScreen(maybeWindow->screen());
835 ctx->setScreen(shareContext->screen());
836 }
else if (maybeWindow) {
837 ctx->setScreen(maybeWindow->screen());
839 if (!ctx->create()) {
840 qWarning(
"QRhiGles2: Failed to create context");
845 qCDebug(QRHI_LOG_INFO) <<
"Created OpenGL context" << ctx->format();
848 if (!ensureContext(maybeWindow ? maybeWindow : fallbackSurface))
851 f =
static_cast<QOpenGLExtensions *>(ctx->extraFunctions());
852 const QSurfaceFormat actualFormat = ctx->format();
853 caps.gles = actualFormat.renderableType() == QSurfaceFormat::OpenGLES;
857 ctx->getProcAddress(QByteArrayLiteral(
"glPolygonMode")));
860 GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum,
const void *)>(
861 ctx->getProcAddress(QByteArrayLiteral(
"glTexImage1D")));
863 glTexStorage1D =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei)>(
864 ctx->getProcAddress(QByteArrayLiteral(
"glTexStorage1D")));
867 GLenum, GLint, GLint, GLsizei, GLenum, GLenum,
const GLvoid *)>(
868 ctx->getProcAddress(QByteArrayLiteral(
"glTexSubImage1D")));
870 glCopyTexSubImage1D =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint,
872 ctx->getProcAddress(QByteArrayLiteral(
"glCopyTexSubImage1D")));
875 GLenum, GLint, GLenum, GLsizei, GLint, GLsizei,
const GLvoid *)>(
876 ctx->getProcAddress(QByteArrayLiteral(
"glCompressedTexImage1D")));
879 GLenum, GLint, GLint, GLsizei, GLenum, GLsizei,
const GLvoid *)>(
880 ctx->getProcAddress(QByteArrayLiteral(
"glCompressedTexSubImage1D")));
882 glFramebufferTexture1D =
884 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture1D")));
887 const char *vendor =
reinterpret_cast<
const char *>(
f->glGetString(GL_VENDOR));
888 const char *renderer =
reinterpret_cast<
const char *>(
f->glGetString(GL_RENDERER));
889 const char *version =
reinterpret_cast<
const char *>(
f->glGetString(GL_VERSION));
890 if (vendor && renderer && version)
891 qCDebug(QRHI_LOG_INFO,
"OpenGL VENDOR: %s RENDERER: %s VERSION: %s", vendor, renderer, version);
894 driverInfoStruct.deviceName += QByteArray(vendor);
895 driverInfoStruct.deviceName +=
' ';
898 driverInfoStruct.deviceName += QByteArray(renderer);
899 driverInfoStruct.deviceName +=
' ';
902 driverInfoStruct.deviceName += QByteArray(version);
904 caps.ctxMajor = actualFormat.majorVersion();
905 caps.ctxMinor = actualFormat.minorVersion();
910 QVarLengthArray<GLint, 16> compressedTextureFormats(n);
912 for (GLint format : compressedTextureFormats)
913 supportedCompressedFormats.insert(format);
926 std::array<QRhiTexture::Flags, 2> textureVariantFlags;
927 textureVariantFlags[0] = {};
928 textureVariantFlags[1] = QRhiTexture::sRGB;
929 if (
f->hasOpenGLExtension(QOpenGLExtensions::DDSTextureCompression)) {
930 for (QRhiTexture::Flags f : textureVariantFlags) {
931 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC1, f));
932 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC2, f));
933 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC3, f));
936 if (
f->hasOpenGLExtension(QOpenGLExtensions::ETC2TextureCompression)) {
937 for (QRhiTexture::Flags f : textureVariantFlags) {
938 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8, f));
939 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8A1, f));
940 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGBA8, f));
943 if (
f->hasOpenGLExtension(QOpenGLExtensions::ASTCTextureCompression)) {
944 for (QRhiTexture::Flags f : textureVariantFlags) {
945 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_4x4, f));
946 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x4, f));
947 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x5, f));
948 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x5, f));
949 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x6, f));
950 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x5, f));
951 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x6, f));
952 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x8, f));
953 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x5, f));
954 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x8, f));
955 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x10, f));
956 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x10, f));
957 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x12, f));
961 f->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.maxTextureSize);
963 if (!caps.gles || caps.ctxMajor >= 3) {
966 caps.hasDrawBuffersFunc =
true;
968 caps.maxSamples = qMax(1, caps.maxSamples);
971 caps.maxDrawBuffers = 1;
972 caps.hasDrawBuffersFunc =
false;
978 caps.msaaRenderBuffer = f->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
979 && f->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
981 caps.npotTextureFull = f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)
982 && f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
985 caps.fixedIndexPrimitiveRestart = caps.ctxMajor >= 3;
987 caps.fixedIndexPrimitiveRestart = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
989 if (caps.fixedIndexPrimitiveRestart) {
999 caps.bgraExternalFormat = f->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat);
1000 caps.bgraInternalFormat = caps.bgraExternalFormat && caps.gles;
1001 caps.r8Format = f->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats);
1004 caps.r32uiFormat = (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1)) && caps.r8Format;
1006 caps.r32uiFormat =
true;
1009 caps.imageLoadStore = caps.r32uiFormat;
1011 caps.imageLoadStore = (caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 2));
1013 caps.r16Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats);
1014 caps.floatFormats = caps.ctxMajor >= 3;
1015 caps.rgb10Formats = caps.ctxMajor >= 3;
1016 caps.depthTexture = caps.ctxMajor >= 3;
1017 caps.packedDepthStencil = f->hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil);
1019 caps.needsDepthStencilCombinedAttach =
true;
1021 caps.needsDepthStencilCombinedAttach =
false;
1028 caps.srgbWriteControl = ctx->hasExtension(
"GL_EXT_framebuffer_sRGB") || ctx->hasExtension(
"GL_EXT_sRGB_write_control");
1030 caps.coreProfile = actualFormat.profile() == QSurfaceFormat::CoreProfile;
1035 caps.vertexArrayObject = caps.coreProfile || (caps.gles && caps.ctxMajor >= 3);
1038 caps.uniformBuffers = caps.ctxMajor >= 3;
1040 caps.uniformBuffers = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1042 caps.elementIndexUint = f->hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint);
1043 caps.depth24 = !caps.gles || f->hasOpenGLExtension(QOpenGLExtensions::Depth24);
1044 caps.rgba8Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized8Formats);
1047 caps.instancing = caps.ctxMajor >= 3;
1049 caps.instancing = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 3);
1051 caps.baseVertex = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1054 caps.compute = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1056 caps.compute = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1059 GLint ssboBindings = 0;
1063 caps.maxVertexStorageBuffers = qMin(blocks, ssboBindings);
1066 caps.maxFragmentStorageBuffers = qMin(blocks, ssboBindings);
1072 caps.maxThreadGroupsPerDimension = qMin(tgPerDim[0], qMin(tgPerDim[1], tgPerDim[2]));
1079 caps.depthClamp =
false;
1081 caps.depthClamp = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1082 if (!caps.depthClamp)
1083 caps.depthClamp = ctx->hasExtension(
"GL_EXT_depth_clamp") || ctx->hasExtension(
"GL_ARB_depth_clamp");
1086 caps.textureCompareMode = caps.ctxMajor >= 3;
1088 caps.textureCompareMode =
true;
1092 caps.properMapBuffer = f->hasOpenGLExtension(QOpenGLExtensions::MapBufferRange);
1095 caps.nonBaseLevelFramebufferTexture = caps.ctxMajor >= 3;
1097 caps.nonBaseLevelFramebufferTexture =
true;
1099 caps.texelFetch = caps.ctxMajor >= 3;
1100 caps.intAttributes = caps.ctxMajor >= 3;
1101 caps.screenSpaceDerivatives = f->hasOpenGLExtension(QOpenGLExtensions::StandardDerivatives);
1104 caps.multisampledTexture = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1106 caps.multisampledTexture = caps.ctxMajor >= 3;
1111 caps.programBinary = caps.ctxMajor >= 3;
1113 caps.programBinary = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 1);
1115 if (caps.programBinary) {
1119 caps.programBinary =
false;
1122 caps.texture3D = caps.ctxMajor >= 3;
1125 caps.texture1D =
false;
1127 caps.texture1D = glTexImage1D && (caps.ctxMajor >= 2);
1130 caps.tessellation = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1132 caps.tessellation = caps.ctxMajor >= 4;
1135 caps.geometryShader = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1137 caps.geometryShader = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1139 if (caps.ctxMajor >= 3) {
1140 GLint maxArraySize = 0;
1142 caps.maxTextureArraySize = maxArraySize;
1144 caps.maxTextureArraySize = 0;
1151 GLint maxVertexUniformVectors = 0;
1153 GLint maxFragmentUniformVectors = 0;
1155 caps.maxUniformVectors = qMin(maxVertexUniformVectors, maxFragmentUniformVectors);
1157 GLint maxVertexUniformComponents = 0;
1159 GLint maxFragmentUniformComponents = 0;
1161 caps.maxUniformVectors = qMin(maxVertexUniformComponents, maxFragmentUniformComponents) / 4;
1164 f->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.maxVertexInputs);
1168 }
else if (caps.ctxMajor >= 3) {
1169 GLint components = 0;
1171 caps.maxVertexOutputs = components / 4;
1175 GLint components = 0;
1178 caps.maxVertexOutputs = components / 4;
1183 if (!caps.coreProfile)
1190 if (!caps.gles && (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2)))
1193 caps.halfAttributes = f->hasOpenGLExtension(QOpenGLExtensions::HalfFloatVertex);
1196 caps.multiView = f->hasOpenGLExtension(QOpenGLExtensions::MultiView)
1197 && f->hasOpenGLExtension(QOpenGLExtensions::MultiViewExtended);
1198 if (caps.multiView) {
1199 glFramebufferTextureMultiviewOVR =
1200 reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei)>(
1201 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultiviewOVR")));
1205 caps.timestamps = !caps.gles && (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 3));
1206 if (caps.timestamps) {
1208 ctx->getProcAddress(QByteArrayLiteral(
"glQueryCounter")));
1209 glGetQueryObjectui64v =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLuint, GLenum, quint64 *)>(
1210 ctx->getProcAddress(QByteArrayLiteral(
"glGetQueryObjectui64v")));
1211 if (!glQueryCounter || !glGetQueryObjectui64v)
1212 caps.timestamps =
false;
1217 caps.objectLabel = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1219 caps.objectLabel = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1220 if (caps.objectLabel) {
1221 glObjectLabel =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLuint, GLsizei,
const GLchar *)>(
1222 ctx->getProcAddress(QByteArrayLiteral(
"glObjectLabel")));
1232 caps.glesMultisampleRenderToTexture = ctx->hasExtension(
"GL_EXT_multisampled_render_to_texture");
1233 if (caps.glesMultisampleRenderToTexture) {
1234 glFramebufferTexture2DMultisampleEXT =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei)>(
1235 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture2DMultisampleEXT")));
1236 glRenderbufferStorageMultisampleEXT =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)>(
1237 ctx->getProcAddress(QByteArrayLiteral(
"glRenderbufferStorageMultisampleEXT")));
1239 caps.glesMultiviewMultisampleRenderToTexture = ctx->hasExtension(
"GL_OVR_multiview_multisampled_render_to_texture");
1240 if (caps.glesMultiviewMultisampleRenderToTexture) {
1241 glFramebufferTextureMultisampleMultiviewOVR =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei)>(
1242 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultisampleMultiviewOVR")));
1245 caps.glesMultisampleRenderToTexture =
false;
1246 caps.glesMultiviewMultisampleRenderToTexture =
false;
1249 caps.unpackRowLength = !caps.gles || caps.ctxMajor >= 3;
1252 caps.perRenderTargetBlending = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1254 caps.perRenderTargetBlending = caps.ctxMajor >= 4;
1257 if (caps.ctxMajor == 3 && caps.ctxMinor < 2) {
1258 caps.sampleVariables = ctx->hasExtension(
"GL_OES_sample_variables");
1260 caps.sampleVariables = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1263 caps.sampleVariables = caps.ctxMajor >= 4;
1267 caps.drawIndirect = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1269 caps.drawIndirect = caps.ctxMajor >= 4;
1270 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_draw_indirect")))
1271 caps.drawIndirect =
true;
1279 caps.baseInstance =
false;
1281 caps.baseInstance = caps.instancing
1282 && (caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 2)
1283 || ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_base_instance")));
1286 if (caps.baseInstance) {
1287 glDrawArraysInstancedBaseInstance =
reinterpret_cast<
decltype(glDrawArraysInstancedBaseInstance)>(
1288 ctx->getProcAddress(QByteArrayLiteral(
"glDrawArraysInstancedBaseInstance")));
1289 glDrawElementsInstancedBaseInstance =
reinterpret_cast<
decltype(glDrawElementsInstancedBaseInstance)>(
1290 ctx->getProcAddress(QByteArrayLiteral(
"glDrawElementsInstancedBaseInstance")));
1291 glDrawElementsInstancedBaseVertexBaseInstance =
reinterpret_cast<
decltype(glDrawElementsInstancedBaseVertexBaseInstance)>(
1292 ctx->getProcAddress(QByteArrayLiteral(
"glDrawElementsInstancedBaseVertexBaseInstance")));
1296 qWarning(
"Failed to resolve glDraw{Arrays,Elements}InstancedBaseInstance{,BaseVertex}; disabling base instance support.");
1297 caps.baseInstance =
false;
1302 caps.drawIndirectMulti =
false;
1304 caps.drawIndirectMulti = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1305 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_multi_draw_indirect")) ||
1306 ctx->hasExtension(QByteArrayLiteral(
"GL_EXT_multi_draw_indirect")))
1307 caps.drawIndirectMulti =
true;
1309 if (caps.drawIndirectMulti) {
1310 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1311 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirect")));
1312 if (!glMultiDrawArraysIndirect)
1313 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1314 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectARB")));
1315 if (!glMultiDrawArraysIndirect)
1316 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1317 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectEXT")));
1318 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1319 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirect")));
1320 if (!glMultiDrawElementsIndirect)
1321 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1322 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectARB")));
1323 if (!glMultiDrawElementsIndirect)
1324 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1325 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectEXT")));
1327 qWarning(
"Failed to resolve glMultiDrawArraysIndirect or glMultiDrawElementsIndirect.");
1328 caps.drawIndirectMulti =
false;
1333 caps.shaderDrawParameters =
false;
1335 caps.shaderDrawParameters = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 6);
1336 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_shader_draw_parameters")))
1337 caps.shaderDrawParameters =
true;
1341 caps.dispatchIndirect = caps.compute;
1346 caps.drawIndirectCount =
false;
1348 caps.drawIndirectCount = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 6);
1349 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_indirect_parameters")))
1350 caps.drawIndirectCount =
true;
1352 if (caps.drawIndirectCount) {
1353 glMultiDrawArraysIndirectCount =
reinterpret_cast<
decltype(glMultiDrawArraysIndirectCount)>(
1354 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectCount")));
1355 if (!glMultiDrawArraysIndirectCount)
1356 glMultiDrawArraysIndirectCount =
reinterpret_cast<
decltype(glMultiDrawArraysIndirectCount)>(
1357 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectCountARB")));
1358 glMultiDrawElementsIndirectCount =
reinterpret_cast<
decltype(glMultiDrawElementsIndirectCount)>(
1359 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectCount")));
1360 if (!glMultiDrawElementsIndirectCount)
1361 glMultiDrawElementsIndirectCount =
reinterpret_cast<
decltype(glMultiDrawElementsIndirectCount)>(
1362 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectCountARB")));
1364 qWarning(
"Failed to resolve glMultiDrawArraysIndirectCount or glMultiDrawElementsIndirectCount.");
1365 caps.drawIndirectCount =
false;
1369 nativeHandlesStruct.context = ctx;
2851 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
2854 const bool isCompressed = isCompressedFormat(texD->m_format);
2855 const bool isCubeMap = texD->m_flags.testFlag(QRhiTexture::CubeMap);
2856 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2857 const bool is1D = texD->m_flags.testFlag(QRhiTexture::OneDimensional);
2858 const bool isArray = texD->m_flags.testFlag(QRhiTexture::TextureArray);
2860 const GLenum effectiveTarget = faceTargetBase + (isCubeMap ? uint(layer) : 0u);
2861 const QPoint dp = subresDesc.destinationTopLeft();
2862 const QByteArray rawData = subresDesc.data();
2864 auto setCmdByNotCompressedData = [&](
const void* data, QSize size, quint32 dataStride)
2866 quint32 bytesPerLine = 0;
2867 quint32 bytesPerPixel = 0;
2868 textureFormatInfo(texD->m_format, size, &bytesPerLine,
nullptr, &bytesPerPixel);
2872 cmd.args.subImage.target = texD->target;
2873 cmd.args.subImage.texture = texD->texture;
2874 cmd.args.subImage.faceTarget = effectiveTarget;
2875 cmd.args.subImage.level = level;
2876 cmd.args.subImage.dx = dp.x();
2877 cmd.args.subImage.dy = is1D && isArray ? layer : dp.y();
2878 cmd.args.subImage.dz = is3D || isArray ? layer : 0;
2879 cmd.args.subImage.w = size.width();
2880 cmd.args.subImage.h = size.height();
2881 cmd.args.subImage.glformat = texD->glformat;
2882 cmd.args.subImage.gltype = texD->gltype;
2884 if (dataStride == 0)
2885 dataStride = bytesPerLine;
2887 cmd.args.subImage.rowStartAlign = (dataStride & 3) ? 1 : 4;
2888 cmd.args.subImage.rowLength = caps.unpackRowLength ? (bytesPerPixel ? dataStride / bytesPerPixel : 0) : 0;
2890 cmd.args.subImage.data = data;
2893 if (!subresDesc.image().isNull()) {
2894 QImage img = subresDesc.image();
2895 QSize size = img.size();
2896 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
2897 const QPoint sp = subresDesc.sourceTopLeft();
2898 if (!subresDesc.sourceSize().isEmpty())
2899 size = subresDesc.sourceSize();
2900 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2901 if (caps.unpackRowLength) {
2902 cbD->retainImage(img);
2904 const uchar *data = img.constBits() + sp.y() * img.bytesPerLine() + sp.x() * (qMax(1, img.depth() / 8));
2905 img = QImage(data, size.width(), size.height(), img.bytesPerLine(), img.format());
2907 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
2910 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2913 setCmdByNotCompressedData(cbD->retainImage(img), size, img.bytesPerLine());
2914 }
else if (!rawData.isEmpty() && isCompressed) {
2915 const int depth = qMax(1, texD->m_depth);
2916 const int arraySize = qMax(0, texD->m_arraySize);
2917 if ((texD->flags().testFlag(QRhiTexture::UsedAsCompressedAtlas) || is3D || isArray)
2925 quint32 levelByteSize = 0;
2926 compressedFormatInfo(texD->m_format, texD->m_pixelSize,
nullptr, &levelByteSize,
nullptr);
2927 quint64 byteSize = levelByteSize;
2929 byteSize *= quint64(depth);
2931 byteSize *= quint64(arraySize);
2932 if (byteSize > quint64(
std::numeric_limits<
int>::max())) {
2933 qWarning(
"Compressed texture zero-initialization would need %llu bytes "
2934 "which is too large; skipping", byteSize);
2937 QByteArray zeroBuf(qsizetype(byteSize), 0);
2940 cmd.args.compressedImage.target = texD->target;
2941 cmd.args.compressedImage.texture = texD->texture;
2942 cmd.args.compressedImage.faceTarget = effectiveTarget;
2943 cmd.args.compressedImage.level = level;
2944 cmd.args.compressedImage.glintformat = texD->glintformat;
2945 cmd.args.compressedImage.w = texD->m_pixelSize.width();
2946 cmd.args.compressedImage.h = is1D && isArray ? arraySize : texD->m_pixelSize.height();
2947 cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
2948 cmd.args.compressedImage.size =
int(byteSize);
2949 cmd.args.compressedImage.data = cbD->retainData(zeroBuf);
2953 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2954 : subresDesc.sourceSize();
2958 cmd.args.compressedSubImage.target = texD->target;
2959 cmd.args.compressedSubImage.texture = texD->texture;
2960 cmd.args.compressedSubImage.faceTarget = effectiveTarget;
2961 cmd.args.compressedSubImage.level = level;
2962 cmd.args.compressedSubImage.dx = dp.x();
2963 cmd.args.compressedSubImage.dy = is1D && isArray ? layer : dp.y();
2964 cmd.args.compressedSubImage.dz = is3D || isArray ? layer : 0;
2965 cmd.args.compressedSubImage.w = size.width();
2966 cmd.args.compressedSubImage.h = size.height();
2967 cmd.args.compressedSubImage.glintformat = texD->glintformat;
2968 cmd.args.compressedSubImage.size = rawData.size();
2969 cmd.args.compressedSubImage.data = cbD->retainData(rawData);
2973 cmd.args.compressedImage.target = texD->target;
2974 cmd.args.compressedImage.texture = texD->texture;
2975 cmd.args.compressedImage.faceTarget = effectiveTarget;
2976 cmd.args.compressedImage.level = level;
2977 cmd.args.compressedImage.glintformat = texD->glintformat;
2978 cmd.args.compressedImage.w = size.width();
2979 cmd.args.compressedImage.h = is1D && isArray ? arraySize : size.height();
2980 cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
2981 cmd.args.compressedImage.size = rawData.size();
2982 cmd.args.compressedImage.data = cbD->retainData(rawData);
2984 }
else if (!rawData.isEmpty()) {
2985 QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2986 : subresDesc.sourceSize();
2987 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2988 quint32 bytesPerPixel = 0;
2989 textureFormatInfo(texD->m_format, size,
nullptr,
nullptr, &bytesPerPixel);
2990 size = clampedSubResourceUploadSizeForSourceData(size, subresDesc.dataStride(),
2991 bytesPerPixel, rawData.size());
2995 setCmdByNotCompressedData(cbD->retainData(rawData), size, subresDesc.dataStride());
2997 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
3537 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
3541 if (cmd.args.beginFrame.timestampQuery)
3543 if (caps.vertexArrayObject) {
3545 f->glGenVertexArrays(1, &vao);
3546 f->glBindVertexArray(vao);
3553 f->glVertexAttribDivisor(GLuint(i), 0);
3556 f->glVertexAttribDivisor(GLuint(i), 0);
3563 f->glDisableVertexAttribArray(GLuint(i));
3568 f->glBindVertexArray(0);
3569 if (cmd.args.endFrame.timestampQuery)
3574 f->glBindVertexArray(vao);
3577 f->glViewport(GLint(cmd.args.viewport.x), GLint(cmd.args.viewport.y), GLsizei(cmd.args.viewport.w), GLsizei(cmd.args.viewport.h));
3578 f->glDepthRangef(cmd.args.viewport.d0, cmd.args.viewport.d1);
3581 f->glScissor(cmd.args.scissor.x, cmd.args.scissor.y, cmd.args.scissor.w, cmd.args.scissor.h);
3584 f->glBlendColor(cmd.args.blendConstants.r, cmd.args.blendConstants.g, cmd.args.blendConstants.b, cmd.args.blendConstants.a);
3590 const GLint ref = GLint(cmd.args.stencilRef.ref);
3591 f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), ref, psD->m_stencilReadMask);
3592 f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), ref, psD->m_stencilReadMask);
3593 cbD->graphicsPassState.dynamic.stencilRef = ref;
3595 qWarning(
"No graphics pipeline active for setStencilRef; ignored");
3603 if (state.lastBindVertexBuffer.ps == psD
3604 && state.lastBindVertexBuffer.buffer == cmd.args.bindVertexBuffer.buffer
3605 && state.lastBindVertexBuffer.offset == cmd.args.bindVertexBuffer.offset
3606 && state.lastBindVertexBuffer.binding == cmd.args.bindVertexBuffer.binding)
3613 state.lastBindVertexBuffer.ps = psD;
3614 state.lastBindVertexBuffer.buffer = cmd.args.bindVertexBuffer.buffer;
3615 state.lastBindVertexBuffer.offset = cmd.args.bindVertexBuffer.offset;
3616 state.lastBindVertexBuffer.binding = cmd.args.bindVertexBuffer.binding;
3618 if (cmd.args.bindVertexBuffer.buffer != state.currentArrayBuffer) {
3619 state.currentArrayBuffer = cmd.args.bindVertexBuffer.buffer;
3621 f->glBindBuffer(GL_ARRAY_BUFFER, state.currentArrayBuffer);
3623 for (
auto it = psD->m_vertexInputLayout.cbeginAttributes(), itEnd = psD->m_vertexInputLayout.cendAttributes();
3626 const int bindingIdx = it->binding();
3627 if (bindingIdx != cmd.args.bindVertexBuffer.binding)
3630 const QRhiVertexInputBinding *inputBinding = psD->m_vertexInputLayout.bindingAt(bindingIdx);
3631 const int stride =
int(inputBinding->stride());
3634 bool normalize =
false;
3635 switch (it->format()) {
3636 case QRhiVertexInputAttribute::Float4:
3640 case QRhiVertexInputAttribute::Float3:
3644 case QRhiVertexInputAttribute::Float2:
3648 case QRhiVertexInputAttribute::Float:
3652 case QRhiVertexInputAttribute::UNormByte4:
3657 case QRhiVertexInputAttribute::UNormByte2:
3662 case QRhiVertexInputAttribute::UNormByte:
3667 case QRhiVertexInputAttribute::UInt4:
3668 type = GL_UNSIGNED_INT;
3671 case QRhiVertexInputAttribute::UInt3:
3672 type = GL_UNSIGNED_INT;
3675 case QRhiVertexInputAttribute::UInt2:
3676 type = GL_UNSIGNED_INT;
3679 case QRhiVertexInputAttribute::UInt:
3680 type = GL_UNSIGNED_INT;
3683 case QRhiVertexInputAttribute::SInt4:
3687 case QRhiVertexInputAttribute::SInt3:
3691 case QRhiVertexInputAttribute::SInt2:
3695 case QRhiVertexInputAttribute::SInt:
3699 case QRhiVertexInputAttribute::Half4:
3703 case QRhiVertexInputAttribute::Half3:
3707 case QRhiVertexInputAttribute::Half2:
3711 case QRhiVertexInputAttribute::Half:
3715 case QRhiVertexInputAttribute::UShort4:
3716 type = GL_UNSIGNED_SHORT;
3719 case QRhiVertexInputAttribute::UShort3:
3720 type = GL_UNSIGNED_SHORT;
3723 case QRhiVertexInputAttribute::UShort2:
3724 type = GL_UNSIGNED_SHORT;
3727 case QRhiVertexInputAttribute::UShort:
3728 type = GL_UNSIGNED_SHORT;
3731 case QRhiVertexInputAttribute::SShort4:
3735 case QRhiVertexInputAttribute::SShort3:
3739 case QRhiVertexInputAttribute::SShort2:
3743 case QRhiVertexInputAttribute::SShort:
3751 const int locationIdx = it->location();
3752 quint32 ofs = it->offset() + cmd.args.bindVertexBuffer.offset;
3753 if (type == GL_UNSIGNED_INT || type == GL_INT) {
3754 if (caps.intAttributes) {
3755 f->glVertexAttribIPointer(GLuint(locationIdx), size, type, stride,
3756 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3758 qWarning(
"Current RHI backend does not support IntAttributes. Check supported features.");
3764 f->glVertexAttribPointer(GLuint(locationIdx), size, type, normalize, stride,
3765 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3770 f->glEnableVertexAttribArray(GLuint(locationIdx));
3772 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance && caps.instancing) {
3773 f->glVertexAttribDivisor(GLuint(locationIdx), inputBinding->instanceStepRate());
3784 f->glVertexAttribDivisor(GLuint(locationIdx), 0);
3790 qWarning(
"No graphics pipeline active for setVertexInput; ignored");
3795 state.indexType = cmd.args.bindIndexBuffer.type;
3796 state.indexStride = state.indexType == GL_UNSIGNED_SHORT ?
sizeof(quint16) :
sizeof(quint32);
3797 state.indexOffset = cmd.args.bindIndexBuffer.offset;
3798 if (state.currentElementArrayBuffer != cmd.args.bindIndexBuffer.buffer) {
3799 state.currentElementArrayBuffer = cmd.args.bindIndexBuffer.buffer;
3800 f->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state.currentElementArrayBuffer);
3807 const bool useBaseInstance = (cmd.args.draw.baseInstance != 0 && caps.baseInstance);
3809 const bool needsInstancedPath = caps.instancing
3810 && (cmd.args.draw.instanceCount != 1 || useBaseInstance);
3812 if (!needsInstancedPath) {
3813 f->glDrawArrays(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount));
3814 }
else if (useBaseInstance) {
3816 GLint(cmd.args.draw.firstVertex)
,
3817 GLsizei(cmd.args.draw.vertexCount)
,
3818 GLsizei(cmd.args.draw.instanceCount)
,
3819 cmd.args.draw.baseInstance
);
3821 f->glDrawArraysInstanced(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount),
3822 GLsizei(cmd.args.draw.instanceCount));
3825 qWarning(
"No graphics pipeline active for draw; ignored");
3833 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3834 quintptr(cmd.args.drawIndexed.firstIndex * state.indexStride + state.indexOffset));
3835 const bool useBaseVertex = (cmd.args.drawIndexed.baseVertex != 0 && caps.baseVertex);
3836 const bool useBaseInstance = (cmd.args.drawIndexed.baseInstance != 0 && caps.baseInstance);
3840 const bool needsInstancedPath = caps.instancing
3841 && (cmd.args.drawIndexed.instanceCount != 1 || useBaseInstance);
3843 if (!needsInstancedPath) {
3844 if (useBaseVertex) {
3845 f->glDrawElementsBaseVertex(psD->drawMode,
3846 GLsizei(cmd.args.drawIndexed.indexCount),
3849 cmd.args.drawIndexed.baseVertex);
3851 f->glDrawElements(psD->drawMode,
3852 GLsizei(cmd.args.drawIndexed.indexCount),
3856 }
else if (useBaseInstance && useBaseVertex) {
3858 GLsizei(cmd.args.drawIndexed.indexCount)
,
3861 GLsizei(cmd.args.drawIndexed.instanceCount)
,
3862 cmd.args.drawIndexed.baseVertex
,
3863 cmd.args.drawIndexed.baseInstance
);
3864 }
else if (useBaseInstance) {
3866 GLsizei(cmd.args.drawIndexed.indexCount)
,
3869 GLsizei(cmd.args.drawIndexed.instanceCount)
,
3870 cmd.args.drawIndexed.baseInstance
);
3871 }
else if (useBaseVertex) {
3872 f->glDrawElementsInstancedBaseVertex(psD->drawMode,
3873 GLsizei(cmd.args.drawIndexed.indexCount),
3876 GLsizei(cmd.args.drawIndexed.instanceCount),
3877 cmd.args.drawIndexed.baseVertex);
3879 f->glDrawElementsInstanced(psD->drawMode,
3880 GLsizei(cmd.args.drawIndexed.indexCount),
3883 GLsizei(cmd.args.drawIndexed.instanceCount));
3886 qWarning(
"No graphics pipeline active for drawIndexed; ignored");
3896 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3897 quintptr(cmd.args.drawIndirect.offset));
3900 cmd.args.drawIndirect.drawCount
,
3901 cmd.args.drawIndirect.stride
);
3903 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
3904 const quintptr indirectOffset = quintptr(cmd.args.drawIndirect.offset)
3905 + quintptr(i) * cmd.args.drawIndirect.stride;
3906 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(indirectOffset);
3907 f->glDrawArraysIndirect(psD->drawMode,
3913 qWarning(
"No graphics pipeline active for drawIndirect; ignored");
3923 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3924 quintptr(cmd.args.drawIndexedIndirect.offset));
3928 cmd.args.drawIndexedIndirect.drawCount
,
3929 cmd.args.drawIndexedIndirect.stride
);
3931 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
3932 const quintptr indirectOffset = quintptr(cmd.args.drawIndexedIndirect.offset)
3933 + quintptr(i) * cmd.args.drawIndexedIndirect.stride;
3934 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(indirectOffset);
3935 f->glDrawElementsIndirect(psD->drawMode,
3942 qWarning(
"No graphics pipeline active for drawIndexedIndirect; ignored");
3952 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3953 quintptr(cmd.args.drawIndirectCount.offset));
3956 GLintptr(cmd.args.drawIndirectCount.countOffset)
,
3957 cmd.args.drawIndirectCount.maxDrawCount
,
3958 cmd.args.drawIndirectCount.stride
);
3962 qWarning(
"No graphics pipeline active or glMultiDrawArraysIndirectCount unavailable; ignored");
3972 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3973 quintptr(cmd.args.drawIndexedIndirectCount.offset));
3977 GLintptr(cmd.args.drawIndexedIndirectCount.countOffset)
,
3978 cmd.args.drawIndexedIndirectCount.maxDrawCount
,
3979 cmd.args.drawIndexedIndirectCount.stride
);
3983 qWarning(
"No graphics pipeline active or glMultiDrawElementsIndirectCount unavailable; ignored");
3990 case QGles2CommandBuffer::Command::BindShaderResources:
3991 bindShaderResources(cbD,
3992 cmd.args.bindShaderResources.maybeGraphicsPs,
3993 cmd.args.bindShaderResources.maybeComputePs,
3994 cmd.args.bindShaderResources.srb,
3995 cmd.args.bindShaderResources.dynamicOffsetPairs,
3996 cmd.args.bindShaderResources.dynamicOffsetCount);
4000 QVarLengthArray<GLenum, 8> bufs;
4001 GLuint fbo = cmd.args.bindFramebuffer.fbo;
4003 fbo = ctx->defaultFramebufferObject();
4004 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4006 const int colorAttCount = cmd.args.bindFramebuffer.colorAttCount;
4007 bufs.append(colorAttCount > 0 ? GL_COLOR_ATTACHMENT0 : GL_NONE);
4008 if (caps.maxDrawBuffers > 1) {
4009 for (
int i = 1; i < colorAttCount; ++i)
4010 bufs.append(GL_COLOR_ATTACHMENT0 + uint(i));
4013 if (cmd.args.bindFramebuffer.stereo && cmd.args.bindFramebuffer.stereoTarget == QRhiSwapChain::RightBuffer)
4018 if (caps.hasDrawBuffersFunc)
4019 f->glDrawBuffers(bufs.count(), bufs.constData());
4020 if (caps.srgbWriteControl) {
4021 if (cmd.args.bindFramebuffer.srgb)
4029 f->glDisable(GL_SCISSOR_TEST);
4030 if (cmd.args.clear.mask & GL_COLOR_BUFFER_BIT) {
4031 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4032 f->glClearColor(cmd.args.clear.c[0], cmd.args.clear.c[1], cmd.args.clear.c[2], cmd.args.clear.c[3]);
4034 if (cmd.args.clear.mask & GL_DEPTH_BUFFER_BIT) {
4035 f->glDepthMask(GL_TRUE);
4036 f->glClearDepthf(cmd.args.clear.d);
4038 if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT) {
4039 f->glStencilMask(0xFF);
4040 f->glClearStencil(GLint(cmd.args.clear.s));
4042 f->glClear(cmd.args.clear.mask);
4043 cbD->graphicsPassState.reset();
4046 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.bufferSubData.target, cmd.args.bufferSubData.buffer);
4047 f->glBufferSubData(cmd.args.bufferSubData.target, cmd.args.bufferSubData.offset, cmd.args.bufferSubData.size,
4048 cmd.args.bufferSubData.data);
4052 QRhiReadbackResult *result = cmd.args.getBufferSubData.result;
4053 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.getBufferSubData.target, cmd.args.getBufferSubData.buffer);
4055 if (caps.properMapBuffer) {
4056 void *p =
f->glMapBufferRange(cmd.args.getBufferSubData.target,
4057 cmd.args.getBufferSubData.offset,
4058 cmd.args.getBufferSubData.size,
4061 result->data.resize(cmd.args.getBufferSubData.size);
4062 memcpy(result->data.data(), p, size_t(cmd.args.getBufferSubData.size));
4063 f->glUnmapBuffer(cmd.args.getBufferSubData.target);
4067 result->data.resize(cmd.args.getBufferSubData.size);
4068 f->glGetBufferSubData(cmd.args.getBufferSubData.target,
4069 cmd.args.getBufferSubData.offset,
4070 cmd.args.getBufferSubData.size,
4071 result->data.data());
4073 if (result->completed)
4074 result->completed();
4080 f->glGenFramebuffers(1, &fbo);
4081 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4085 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.copyTex.srcTexture,
4086 cmd.args.copyTex.srcLevel, cmd.args.copyTex.srcZ);
4089 cmd.args.copyTex.srcTarget, cmd.args.copyTex.srcTexture,
4090 cmd.args.copyTex.srcLevel);
4092 f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4093 cmd.args.copyTex.srcFaceTarget, cmd.args.copyTex.srcTexture, cmd.args.copyTex.srcLevel);
4095 f->glBindTexture(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstTexture);
4097 f->glCopyTexSubImage3D(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstLevel,
4098 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY, cmd.args.copyTex.dstZ,
4099 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
4100 cmd.args.copyTex.w, cmd.args.copyTex.h);
4103 cmd.args.copyTex.dstX
, cmd.args.copyTex.srcX
,
4104 cmd.args.copyTex.srcY
, cmd.args.copyTex.w
);
4106 f->glCopyTexSubImage2D(cmd.args.copyTex.dstFaceTarget, cmd.args.copyTex.dstLevel,
4107 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY,
4108 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
4109 cmd.args.copyTex.w, cmd.args.copyTex.h);
4111 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4112 f->glDeleteFramebuffers(1, &fbo);
4117 QRhiReadbackResult *result = cmd.args.readPixels.result;
4118 GLuint tex = cmd.args.readPixels.texture;
4121 result->pixelSize = QSize(cmd.args.readPixels.w, cmd.args.readPixels.h);
4123 result->format = cmd.args.readPixels.format;
4124 mipLevel = cmd.args.readPixels.level;
4125 if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
4126 f->glGenFramebuffers(1, &fbo);
4127 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4128 if (cmd.args.readPixels.slice3D >= 0) {
4129 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4130 tex, mipLevel, cmd.args.readPixels.slice3D);
4131 }
else if (cmd.args.readPixels.readTarget ==
GL_TEXTURE_1D) {
4133 cmd.args.readPixels.readTarget, tex, mipLevel);
4135 f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
4136 cmd.args.readPixels.readTarget, tex, mipLevel);
4140 result->format = QRhiTexture::RGBA8;
4143 const int x = cmd.args.readPixels.x;
4144 const int y = cmd.args.readPixels.y;
4145 const int w = cmd.args.readPixels.w;
4146 const int h = cmd.args.readPixels.h;
4147 if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
4150 if (result->format == QRhiTexture::R8 || result->format == QRhiTexture::RED_OR_ALPHA8) {
4151 result->data.resizeForOverwrite(w * h);
4153 tmpBuf.resizeForOverwrite(w * h * 4);
4155 const quint8 *srcBase =
reinterpret_cast<
const quint8 *>(tmpBuf.constData());
4156 quint8 *dstBase =
reinterpret_cast<quint8 *>(result->data.data());
4157 const int componentIndex = isFeatureSupported(QRhi::RedOrAlpha8IsRed) ? 0 : 3;
4158 for (
int y = 0; y < h; ++y) {
4159 const quint8 *src = srcBase + y * w * 4;
4160 quint8 *dst = dstBase + y * w;
4162 while (count-- > 0) {
4163 *dst++ = src[componentIndex];
4170 [[maybe_unused]] GLenum glintformat;
4171 [[maybe_unused]] GLenum glsizedintformat;
4174 toGlTextureFormat(result->format, caps, &glintformat, &glsizedintformat, &glformat, &gltype);
4176 textureFormatInfo(result->format, result->pixelSize,
nullptr, &byteSize,
nullptr);
4177 result->data.resizeForOverwrite(byteSize);
4178 f->glReadPixels(x, y, w, h, glformat, gltype, result->data.data());
4181 result->data.resizeForOverwrite(w * h * 4);
4182 result->data.fill(
'\0');
4185 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4186 f->glDeleteFramebuffers(1, &fbo);
4188 if (result->completed)
4189 result->completed();
4193 f->glBindTexture(cmd.args.subImage.target, cmd.args.subImage.texture);
4194 if (cmd.args.subImage.rowStartAlign != 4)
4195 f->glPixelStorei(GL_UNPACK_ALIGNMENT, cmd.args.subImage.rowStartAlign);
4196 if (cmd.args.subImage.rowLength != 0)
4199 f->glTexSubImage3D(cmd.args.subImage.target, cmd.args.subImage.level,
4200 cmd.args.subImage.dx, cmd.args.subImage.dy, cmd.args.subImage.dz,
4201 cmd.args.subImage.w, cmd.args.subImage.h, 1,
4202 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
4203 cmd.args.subImage.data);
4206 cmd.args.subImage.dx
, cmd.args.subImage.w
,
4207 cmd.args.subImage.glformat
, cmd.args.subImage.gltype
,
4208 cmd.args.subImage.data
);
4210 f->glTexSubImage2D(cmd.args.subImage.faceTarget, cmd.args.subImage.level,
4211 cmd.args.subImage.dx, cmd.args.subImage.dy,
4212 cmd.args.subImage.w, cmd.args.subImage.h,
4213 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
4214 cmd.args.subImage.data);
4216 if (cmd.args.subImage.rowStartAlign != 4)
4217 f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
4218 if (cmd.args.subImage.rowLength != 0)
4222 f->glBindTexture(cmd.args.compressedImage.target, cmd.args.compressedImage.texture);
4224 f->glCompressedTexImage3D(cmd.args.compressedImage.target, cmd.args.compressedImage.level,
4225 cmd.args.compressedImage.glintformat,
4226 cmd.args.compressedImage.w, cmd.args.compressedImage.h, cmd.args.compressedImage.depth,
4227 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
4228 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
4230 cmd.args.compressedImage.target
, cmd.args.compressedImage.level
,
4231 cmd.args.compressedImage.glintformat
, cmd.args.compressedImage.w
, 0
,
4232 cmd.args.compressedImage.size
, cmd.args.compressedImage.data
);
4234 f->glCompressedTexImage2D(cmd.args.compressedImage.faceTarget, cmd.args.compressedImage.level,
4235 cmd.args.compressedImage.glintformat,
4236 cmd.args.compressedImage.w, cmd.args.compressedImage.h,
4237 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
4241 f->glBindTexture(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.texture);
4243 f->glCompressedTexSubImage3D(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.level,
4244 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy, cmd.args.compressedSubImage.dz,
4245 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h, 1,
4246 cmd.args.compressedSubImage.glintformat,
4247 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
4248 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
4250 cmd.args.compressedSubImage.target
, cmd.args.compressedSubImage.level
,
4251 cmd.args.compressedSubImage.dx
, cmd.args.compressedSubImage.w
,
4252 cmd.args.compressedSubImage.glintformat
, cmd.args.compressedSubImage.size
,
4253 cmd.args.compressedSubImage.data
);
4255 f->glCompressedTexSubImage2D(cmd.args.compressedSubImage.faceTarget, cmd.args.compressedSubImage.level,
4256 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy,
4257 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h,
4258 cmd.args.compressedSubImage.glintformat,
4259 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
4266 cbD->graphicsPassState.reset();
4267 f->glDisable(GL_SCISSOR_TEST);
4269 f->glGenFramebuffers(2, fbo);
4271 const bool ds = cmd.args.blitFromRenderbuffer.isDepthStencil;
4274 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4276 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4279 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4285 cmd.args.blitFromRenderbuffer.dstTexture,
4286 cmd.args.blitFromRenderbuffer.dstLevel,
4287 cmd.args.blitFromRenderbuffer.dstLayer);
4289 cmd.args.blitFromRenderbuffer.dstTexture,
4290 cmd.args.blitFromRenderbuffer.dstLevel,
4291 cmd.args.blitFromRenderbuffer.dstLayer);
4294 cmd.args.blitFromRenderbuffer.dstTexture,
4295 cmd.args.blitFromRenderbuffer.dstLevel,
4296 cmd.args.blitFromRenderbuffer.dstLayer);
4300 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
4301 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4302 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
4303 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4305 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromRenderbuffer.target,
4306 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4309 if (ds && !caps.gles) {
4310 f->glReadBuffer(GL_NONE);
4311 const GLenum noBuf = GL_NONE;
4312 f->glDrawBuffers(1, &noBuf);
4314 f->glBlitFramebuffer(0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
4315 0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
4316 ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT,
4318 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4319 f->glDeleteFramebuffers(2, fbo);
4326 cbD->graphicsPassState.reset();
4327 f->glDisable(GL_SCISSOR_TEST);
4329 f->glGenFramebuffers(2, fbo);
4331 const bool ds = cmd.args.blitFromTexture.isDepthStencil;
4335 cmd.args.blitFromTexture.srcTexture,
4336 cmd.args.blitFromTexture.srcLevel,
4337 cmd.args.blitFromTexture.srcLayer);
4339 cmd.args.blitFromTexture.srcTexture,
4340 cmd.args.blitFromTexture.srcLevel,
4341 cmd.args.blitFromTexture.srcLayer);
4344 cmd.args.blitFromTexture.srcTexture,
4345 cmd.args.blitFromTexture.srcLevel,
4346 cmd.args.blitFromTexture.srcLayer);
4350 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
4351 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4352 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
4353 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4355 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.srcTarget,
4356 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4363 cmd.args.blitFromTexture.dstTexture,
4364 cmd.args.blitFromTexture.dstLevel,
4365 cmd.args.blitFromTexture.dstLayer);
4367 cmd.args.blitFromTexture.dstTexture,
4368 cmd.args.blitFromTexture.dstLevel,
4369 cmd.args.blitFromTexture.dstLayer);
4372 cmd.args.blitFromTexture.dstTexture,
4373 cmd.args.blitFromTexture.dstLevel,
4374 cmd.args.blitFromTexture.dstLayer);
4378 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
4379 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4380 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
4381 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4383 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.dstTarget,
4384 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4387 if (ds && !caps.gles) {
4388 f->glReadBuffer(GL_NONE);
4389 const GLenum noBuf = GL_NONE;
4390 f->glDrawBuffers(1, &noBuf);
4392 f->glBlitFramebuffer(0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
4393 0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
4394 ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT,
4396 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4397 f->glDeleteFramebuffers(2, fbo);
4401 f->glBindTexture(cmd.args.genMip.target, cmd.args.genMip.texture);
4402 f->glGenerateMipmap(cmd.args.genMip.target);
4407 f->glUseProgram(psD->program);
4411 f->glDispatchCompute(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
4416 f->glDispatchComputeIndirect(GLintptr(cmd.args.dispatchIndirect.offset));
4424 GLbitfield barriers = 0;
4433 for (
const auto &[rhiB, trackedB]: tracker.buffers()) {
4435 QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(trackedB.stateAtPassBegin.access);
4436 if (bufferAccessIsWrite(accessBeforePass))
4437 barriers |= barriersForBuffer();
4439 for (
const auto &[rhiT, trackedT]: tracker.textures()) {
4441 QGles2Texture::Access accessBeforePass = QGles2Texture::Access(trackedT.stateAtPassBegin.access);
4442 if (textureAccessIsWrite(accessBeforePass))
4443 barriers |= barriersForTexture();
4446 f->glMemoryBarrier(barriers);
4451 f->glMemoryBarrier(cmd.args.barrier.barriers);
4454 if (caps.gles && caps.ctxMajor >= 3) {
4455 f->glBindFramebuffer(GL_FRAMEBUFFER, cmd.args.invalidateFramebuffer.fbo);
4457 cmd.args.invalidateFramebuffer.attCount,
4458 cmd.args.invalidateFramebuffer.att);
4468 f->glVertexAttribDivisor(GLuint(i), 0);
4471 f->glVertexAttribDivisor(GLuint(i), 0);
4478 const bool forceUpdate = !state
.valid;
4481 const bool scissor = psD->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor);
4482 if (forceUpdate || scissor != state
.scissor) {
4485 f->glEnable(GL_SCISSOR_TEST);
4487 f->glDisable(GL_SCISSOR_TEST);
4490 const bool cullFace = psD->m_cullMode != QRhiGraphicsPipeline::None;
4491 const GLenum cullMode = cullFace ? toGlCullMode(psD->m_cullMode) : GL_NONE;
4492 if (forceUpdate || cullFace != state
.cullFace || cullMode != state.cullMode) {
4494 state.cullMode = cullMode;
4496 f->glEnable(GL_CULL_FACE);
4497 f->glCullFace(cullMode);
4499 f->glDisable(GL_CULL_FACE);
4503 const GLenum frontFace = toGlFrontFace(psD->m_frontFace);
4504 if (forceUpdate || frontFace != state.frontFace) {
4505 state.frontFace = frontFace;
4506 f->glFrontFace(frontFace);
4509 const GLenum polygonMode = toGlPolygonMode(psD->m_polygonMode);
4510 if (
glPolygonMode && (forceUpdate || polygonMode != state.polygonMode)) {
4511 state.polygonMode = polygonMode;
4515 if (!psD->m_targetBlends.isEmpty()) {
4517 bool anyBlendEnabled =
false;
4518 for (
const auto targetBlend : psD->m_targetBlends) {
4519 const QGles2CommandBuffer::GraphicsPassState::ColorMask colorMask = {
4520 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::R),
4521 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::G),
4522 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::B),
4523 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::A)
4525 if (forceUpdate || colorMask != state.colorMask[buffer]) {
4526 state.colorMask[buffer] = colorMask;
4527 if (caps.perRenderTargetBlending)
4528 f->glColorMaski(buffer, colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4530 f->glColorMask(colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4533 const bool blendEnabled = targetBlend.enable;
4534 const QGles2CommandBuffer::GraphicsPassState::Blend blend = {
4535 toGlBlendFactor(targetBlend.srcColor),
4536 toGlBlendFactor(targetBlend.dstColor),
4537 toGlBlendFactor(targetBlend.srcAlpha),
4538 toGlBlendFactor(targetBlend.dstAlpha),
4539 toGlBlendOp(targetBlend.opColor),
4540 toGlBlendOp(targetBlend.opAlpha)
4542 anyBlendEnabled |= blendEnabled;
4543 if (forceUpdate || blendEnabled != state.blendEnabled[buffer] || (blendEnabled && blend != state.blend[buffer])) {
4544 state.blendEnabled[buffer] = blendEnabled;
4546 state.blend[buffer] = blend;
4547 if (caps.perRenderTargetBlending) {
4548 f->glBlendFuncSeparatei(buffer, blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4549 f->glBlendEquationSeparatei(buffer, blend.opColor, blend.opAlpha);
4551 f->glBlendFuncSeparate(blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4552 f->glBlendEquationSeparate(blend.opColor, blend.opAlpha);
4557 if (!caps.perRenderTargetBlending)
4560 if (anyBlendEnabled)
4561 f->glEnable(GL_BLEND);
4563 f->glDisable(GL_BLEND);
4566 if (forceUpdate || colorMask
!= state.colorMask[0]) {
4567 state.colorMask[0] = colorMask;
4568 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4570 const bool blendEnabled =
false;
4573 f->glDisable(GL_BLEND);
4577 const bool depthTest = psD->m_depthTest;
4578 if (forceUpdate || depthTest != state
.depthTest) {
4581 f->glEnable(GL_DEPTH_TEST);
4583 f->glDisable(GL_DEPTH_TEST);
4586 const bool depthWrite = psD->m_depthWrite;
4587 if (forceUpdate || depthWrite != state
.depthWrite) {
4589 f->glDepthMask(depthWrite);
4592 const bool depthClamp = psD->m_depthClamp;
4593 if (caps.depthClamp && (forceUpdate || depthClamp != state.depthClamp)) {
4601 const GLenum depthFunc = toGlCompareOp(psD->m_depthOp);
4602 if (forceUpdate || depthFunc != state.depthFunc) {
4603 state.depthFunc = depthFunc;
4604 f->glDepthFunc(depthFunc);
4607 const bool stencilTest = psD->m_stencilTest;
4608 const GLuint stencilReadMask = psD->m_stencilReadMask;
4609 const GLuint stencilWriteMask = psD->m_stencilWriteMask;
4611 toGlCompareOp(psD->m_stencilFront.compareOp),
4612 toGlStencilOp(psD->m_stencilFront.failOp),
4613 toGlStencilOp(psD->m_stencilFront.depthFailOp),
4614 toGlStencilOp(psD->m_stencilFront.passOp)
4617 toGlCompareOp(psD->m_stencilBack.compareOp),
4618 toGlStencilOp(psD->m_stencilBack.failOp),
4619 toGlStencilOp(psD->m_stencilBack.depthFailOp),
4620 toGlStencilOp(psD->m_stencilBack.passOp)
4624 && (stencilReadMask != state.stencilReadMask || stencilWriteMask != state.stencilWriteMask
4625 || stencilFront != state.stencil[0] || stencilBack != state.stencil[1])))
4629 state.stencilReadMask = stencilReadMask;
4630 state.stencilWriteMask = stencilWriteMask;
4631 state.stencil[0] = stencilFront;
4632 state.stencil[1] = stencilBack;
4634 f->glEnable(GL_STENCIL_TEST);
4636 f->glStencilFuncSeparate(GL_FRONT, stencilFront.func, state.dynamic.stencilRef, stencilReadMask);
4637 f->glStencilOpSeparate(GL_FRONT, stencilFront.failOp, stencilFront.zfailOp, stencilFront.zpassOp);
4638 f->glStencilMaskSeparate(GL_FRONT, stencilWriteMask);
4640 f->glStencilFuncSeparate(GL_BACK, stencilBack.func, state.dynamic.stencilRef, stencilReadMask);
4641 f->glStencilOpSeparate(GL_BACK, stencilBack.failOp, stencilBack.zfailOp, stencilBack.zpassOp);
4642 f->glStencilMaskSeparate(GL_BACK, stencilWriteMask);
4644 f->glDisable(GL_STENCIL_TEST);
4648 const bool polyOffsetFill = psD->m_depthBias != 0 || !qFuzzyIsNull(psD->m_slopeScaledDepthBias);
4649 const float polyOffsetFactor = psD->m_slopeScaledDepthBias;
4650 const float polyOffsetUnits = psD->m_depthBias;
4657 if (polyOffsetFill) {
4658 f->glPolygonOffset(polyOffsetFactor, polyOffsetUnits);
4659 f->glEnable(GL_POLYGON_OFFSET_FILL);
4661 f->glDisable(GL_POLYGON_OFFSET_FILL);
4665 if (psD->m_topology == QRhiGraphicsPipeline::Lines || psD->m_topology == QRhiGraphicsPipeline::LineStrip) {
4666 const float lineWidth = psD->m_lineWidth;
4667 if (forceUpdate || lineWidth != state
.lineWidth) {
4669 f->glLineWidth(lineWidth);
4673 if (psD->m_topology == QRhiGraphicsPipeline::Patches) {
4674 const int cpCount = psD->m_patchControlPointCount;
4675 if (forceUpdate || cpCount != state
.cpCount) {
4681 f->glUseProgram(psD->program);
4804 QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs,
4805 QRhiShaderResourceBindings *srb,
4806 const uint *dynOfsPairs,
int dynOfsCount)
4810 bool activeTexUnitAltered =
false;
4815 m_scratch.separateTextureBindings.clear();
4816 m_scratch.separateSamplerBindings.clear();
4818 for (
int i = 0, ie = srbD->m_bindings.size(); i != ie; ++i) {
4819 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->m_bindings.at(i));
4822 case QRhiShaderResourceBinding::UniformBuffer:
4824 int viewOffset = b->u.ubuf.offset;
4825 for (
int j = 0; j < dynOfsCount; ++j) {
4826 if (dynOfsPairs[2 * j] == uint(b->binding)) {
4827 viewOffset =
int(dynOfsPairs[2 * j + 1]);
4832 const char *bufView = bufD->data.constData() + viewOffset;
4833 for (
const QGles2UniformDescription &uniform : std::as_const(uniforms)) {
4834 if (uniform.binding == b->binding) {
4835 const qint64 readOffset = qint64(viewOffset) + uniform.offset;
4836 const qint64 readSize = qrhi_std140_read_size(uniform.type, uniform.arrayDim);
4837 if (readOffset < 0 || readOffset + readSize > bufD->data.size()) {
4838 qWarning(
"Uniform with buffer binding %d, buffer offset %u, type %d, array "
4839 "dimension %d would read outside of the uniform buffer of size %lld. "
4841 uniform.binding, uniform.offset, uniform.type, uniform.arrayDim,
4842 qint64(bufD->data.size()));
4848 const void *src = bufView + uniform.offset;
4851 if (uniform.arrayDim > 0
4852 && uniform.type != QShaderDescription::Float
4853 && uniform.type != QShaderDescription::Vec2
4854 && uniform.type != QShaderDescription::Vec3
4855 && uniform.type != QShaderDescription::Vec4
4856 && uniform.type != QShaderDescription::Int
4857 && uniform.type != QShaderDescription::Int2
4858 && uniform.type != QShaderDescription::Int3
4859 && uniform.type != QShaderDescription::Int4
4860 && uniform.type != QShaderDescription::Uint
4861 && uniform.type != QShaderDescription::Uint2
4862 && uniform.type != QShaderDescription::Uint3
4863 && uniform.type != QShaderDescription::Uint4
4864 && uniform.type != QShaderDescription::Mat2
4865 && uniform.type != QShaderDescription::Mat3
4866 && uniform.type != QShaderDescription::Mat4)
4868 qWarning(
"Uniform with buffer binding %d, buffer offset %d, type %d is an array, "
4869 "but arrays are only supported for float, vec2, vec3, vec4, int, "
4870 "ivec2, ivec3, ivec4, uint, uvec2, uvec3, uvec4, mat2, mat3 "
4872 "Only the first element will be set.",
4873 uniform.binding, uniform.offset, uniform.type);
4883 switch (uniform.type) {
4884 case QShaderDescription::Float:
4886 const int elemCount = uniform.arrayDim;
4887 if (elemCount < 1) {
4888 const float v = *
reinterpret_cast<
const float *>(src);
4889 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4890 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4891 if (thisUniformState.componentCount != 1 || thisUniformState.v[0] != v) {
4892 thisUniformState.componentCount = 1;
4893 thisUniformState.v[0] = v;
4894 f->glUniform1f(uniform.glslLocation, v);
4897 f->glUniform1f(uniform.glslLocation, v);
4901 m_scratch.packedArray.resize(elemCount);
4902 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 1, elemCount, src);
4903 f->glUniform1fv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->f);
4907 case QShaderDescription::Vec2:
4909 const int elemCount = uniform.arrayDim;
4910 if (elemCount < 1) {
4911 const float *v =
reinterpret_cast<
const float *>(src);
4912 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4913 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4914 if (thisUniformState.componentCount != 2
4915 || thisUniformState.v[0] != v[0]
4916 || thisUniformState.v[1] != v[1])
4918 thisUniformState.componentCount = 2;
4919 thisUniformState.v[0] = v[0];
4920 thisUniformState.v[1] = v[1];
4921 f->glUniform2fv(uniform.glslLocation, 1, v);
4924 f->glUniform2fv(uniform.glslLocation, 1, v);
4927 m_scratch.packedArray.resize(elemCount * 2);
4928 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 2, elemCount, src);
4929 f->glUniform2fv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->f);
4933 case QShaderDescription::Vec3:
4935 const int elemCount = uniform.arrayDim;
4936 if (elemCount < 1) {
4937 const float *v =
reinterpret_cast<
const float *>(src);
4938 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4939 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4940 if (thisUniformState.componentCount != 3
4941 || thisUniformState.v[0] != v[0]
4942 || thisUniformState.v[1] != v[1]
4943 || thisUniformState.v[2] != v[2])
4945 thisUniformState.componentCount = 3;
4946 thisUniformState.v[0] = v[0];
4947 thisUniformState.v[1] = v[1];
4948 thisUniformState.v[2] = v[2];
4949 f->glUniform3fv(uniform.glslLocation, 1, v);
4952 f->glUniform3fv(uniform.glslLocation, 1, v);
4955 m_scratch.packedArray.resize(elemCount * 3);
4956 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 3, elemCount, src);
4957 f->glUniform3fv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->f);
4961 case QShaderDescription::Vec4:
4963 const int elemCount = uniform.arrayDim;
4964 if (elemCount < 1) {
4965 const float *v =
reinterpret_cast<
const float *>(src);
4966 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4967 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4968 if (thisUniformState.componentCount != 4
4969 || thisUniformState.v[0] != v[0]
4970 || thisUniformState.v[1] != v[1]
4971 || thisUniformState.v[2] != v[2]
4972 || thisUniformState.v[3] != v[3])
4974 thisUniformState.componentCount = 4;
4975 thisUniformState.v[0] = v[0];
4976 thisUniformState.v[1] = v[1];
4977 thisUniformState.v[2] = v[2];
4978 thisUniformState.v[3] = v[3];
4979 f->glUniform4fv(uniform.glslLocation, 1, v);
4982 f->glUniform4fv(uniform.glslLocation, 1, v);
4985 f->glUniform4fv(uniform.glslLocation, elemCount,
reinterpret_cast<
const float *>(src));
4989 case QShaderDescription::Mat2:
4991 const int elemCount = uniform.arrayDim;
4992 if (elemCount < 1) {
4995 const float *srcMat =
reinterpret_cast<
const float *>(src);
4996 memcpy(mat, srcMat, 2 *
sizeof(
float));
4997 memcpy(mat + 2, srcMat + 4, 2 *
sizeof(
float));
4998 f->glUniformMatrix2fv(uniform.glslLocation, 1, GL_FALSE, mat);
5000 m_scratch.packedArray.resize(elemCount * 4);
5001 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 2, elemCount * 2, src);
5002 f->glUniformMatrix2fv(uniform.glslLocation, elemCount, GL_FALSE, &m_scratch.packedArray.constData()->f);
5006 case QShaderDescription::Mat3:
5008 const int elemCount = uniform.arrayDim;
5009 if (elemCount < 1) {
5012 const float *srcMat =
reinterpret_cast<
const float *>(src);
5013 memcpy(mat, srcMat, 3 *
sizeof(
float));
5014 memcpy(mat + 3, srcMat + 4, 3 *
sizeof(
float));
5015 memcpy(mat + 6, srcMat + 8, 3 *
sizeof(
float));
5016 f->glUniformMatrix3fv(uniform.glslLocation, 1, GL_FALSE, mat);
5018 m_scratch.packedArray.resize(elemCount * 9);
5019 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 3, elemCount * 3, src);
5020 f->glUniformMatrix3fv(uniform.glslLocation, elemCount, GL_FALSE, &m_scratch.packedArray.constData()->f);
5024 case QShaderDescription::Mat4:
5025 f->glUniformMatrix4fv(uniform.glslLocation, qMax(1, uniform.arrayDim), GL_FALSE,
reinterpret_cast<
const float *>(src));
5027 case QShaderDescription::Int:
5029 const int elemCount = uniform.arrayDim;
5030 if (elemCount < 1) {
5031 f->glUniform1i(uniform.glslLocation, *
reinterpret_cast<
const qint32 *>(src));
5033 m_scratch.packedArray.resize(elemCount);
5034 qrhi_std140_to_packed(&m_scratch.packedArray.data()->i, 1, elemCount, src);
5035 f->glUniform1iv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->i);
5039 case QShaderDescription::Int2:
5041 const int elemCount = uniform.arrayDim;
5042 if (elemCount < 1) {
5043 f->glUniform2iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
5045 m_scratch.packedArray.resize(elemCount * 2);
5046 qrhi_std140_to_packed(&m_scratch.packedArray.data()->i, 2, elemCount, src);
5047 f->glUniform2iv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->i);
5051 case QShaderDescription::Int3:
5053 const int elemCount = uniform.arrayDim;
5054 if (elemCount < 1) {
5055 f->glUniform3iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
5057 m_scratch.packedArray.resize(elemCount * 3);
5058 qrhi_std140_to_packed(&m_scratch.packedArray.data()->i, 3, elemCount, src);
5059 f->glUniform3iv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->i);
5063 case QShaderDescription::Int4:
5064 f->glUniform4iv(uniform.glslLocation, qMax(1, uniform.arrayDim),
reinterpret_cast<
const qint32 *>(src));
5066 case QShaderDescription::Uint:
5068 const int elemCount = uniform.arrayDim;
5069 if (elemCount < 1) {
5070 f->glUniform1ui(uniform.glslLocation, *
reinterpret_cast<
const quint32 *>(src));
5072 m_scratch.packedArray.resize(elemCount);
5073 qrhi_std140_to_packed(&m_scratch.packedArray.data()->u, 1, elemCount, src);
5074 f->glUniform1uiv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->u);
5078 case QShaderDescription::Uint2:
5080 const int elemCount = uniform.arrayDim;
5081 if (elemCount < 1) {
5082 f->glUniform2uiv(uniform.glslLocation, 1,
reinterpret_cast<
const quint32 *>(src));
5084 m_scratch.packedArray.resize(elemCount * 2);
5085 qrhi_std140_to_packed(&m_scratch.packedArray.data()->u, 2, elemCount, src);
5086 f->glUniform2uiv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->u);
5090 case QShaderDescription::Uint3:
5092 const int elemCount = uniform.arrayDim;
5093 if (elemCount < 1) {
5094 f->glUniform3uiv(uniform.glslLocation, 1,
reinterpret_cast<
const quint32 *>(src));
5096 m_scratch.packedArray.resize(elemCount * 3);
5097 qrhi_std140_to_packed(&m_scratch.packedArray.data()->u, 3, elemCount, src);
5098 f->glUniform3uiv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->u);
5102 case QShaderDescription::Uint4:
5103 f->glUniform4uiv(uniform.glslLocation, qMax(1, uniform.arrayDim),
reinterpret_cast<
const quint32 *>(src));
5105 case QShaderDescription::Bool:
5106 f->glUniform1i(uniform.glslLocation, *
reinterpret_cast<
const qint32 *>(src));
5108 case QShaderDescription::Bool2:
5109 f->glUniform2iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
5111 case QShaderDescription::Bool3:
5112 f->glUniform3iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
5114 case QShaderDescription::Bool4:
5115 f->glUniform4iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
5118 qWarning(
"Uniform with buffer binding %d, buffer offset %d has unsupported type %d",
5119 uniform.binding, uniform.offset, uniform.type);
5126 case QRhiShaderResourceBinding::SampledTexture:
5132 if (maybeGraphicsPs) {
5133 ps = maybeGraphicsPs;
5136 ps = maybeComputePs;
5139 for (
int elem = 0; elem < b->u.stex.count; ++elem) {
5142 for (
const QGles2SamplerDescription &shaderSampler : samplers) {
5143 if (shaderSampler.combinedBinding == b->binding) {
5144 const int loc = shaderSampler.glslLocation + elem;
5145 bindCombinedSampler(cbD, texD, samplerD, ps, psGeneration, loc, &texUnit, &activeTexUnitAltered);
5152 case QRhiShaderResourceBinding::Texture:
5153 for (
int elem = 0; elem < b->u.stex.count; ++elem) {
5155 m_scratch.separateTextureBindings.append({ texD, b->binding, elem });
5158 case QRhiShaderResourceBinding::Sampler:
5161 m_scratch.separateSamplerBindings.append({ samplerD, b->binding });
5164 case QRhiShaderResourceBinding::ImageLoad:
5165 case QRhiShaderResourceBinding::ImageStore:
5166 case QRhiShaderResourceBinding::ImageLoadStore:
5169 Q_ASSERT(texD->m_flags.testFlag(QRhiTexture::UsedWithLoadStore));
5171 const bool layered = texD->m_flags.testFlag(QRhiTexture::CubeMap)
5172 || texD->m_flags.testFlag(QRhiTexture::ThreeDimensional)
5173 || texD->m_flags.testFlag(QRhiTexture::TextureArray);
5175 if (b->type == QRhiShaderResourceBinding::ImageLoad)
5177 else if (b->type == QRhiShaderResourceBinding::ImageStore)
5179 f->glBindImageTexture(GLuint(b->binding), texD->texture,
5180 b->u.simage.level, layered, 0,
5181 access, texD->glsizedintformat);
5184 case QRhiShaderResourceBinding::BufferLoad:
5185 case QRhiShaderResourceBinding::BufferStore:
5186 case QRhiShaderResourceBinding::BufferLoadStore:
5189 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer));
5190 if (b->u.sbuf.offset == 0 && b->u.sbuf.maybeSize == 0)
5194 b->u.sbuf.offset, b->u.sbuf.maybeSize ? b->u.sbuf.maybeSize : bufD->m_size);
5203 if (!m_scratch.separateTextureBindings.isEmpty() || !m_scratch.separateSamplerBindings.isEmpty()) {
5208 if (maybeGraphicsPs) {
5209 ps = maybeGraphicsPs;
5212 ps = maybeComputePs;
5215 for (
const QGles2SamplerDescription &shaderSampler : samplers) {
5216 if (shaderSampler.combinedBinding >= 0)
5218 for (
const Scratch::SeparateSampler &sepSampler : std::as_const(m_scratch.separateSamplerBindings)) {
5219 if (sepSampler.binding != shaderSampler.sbinding)
5221 for (
const Scratch::SeparateTexture &sepTex : std::as_const(m_scratch.separateTextureBindings)) {
5222 if (sepTex.binding != shaderSampler.tbinding)
5224 const int loc = shaderSampler.glslLocation + sepTex.elem;
5225 bindCombinedSampler(cbD, sepTex.texture, sepSampler.sampler, ps, psGeneration,
5226 loc, &texUnit, &activeTexUnitAltered);
5232 if (activeTexUnitAltered)
6908bool QGles2TextureRenderTarget::create()
6915 const bool hasColorAttachments = m_desc.colorAttachmentCount() > 0;
6916 Q_ASSERT(hasColorAttachments || m_desc.depthTexture());
6917 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
6918 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
6920 if (hasColorAttachments) {
6921 const int count =
int(m_desc.colorAttachmentCount());
6922 if (count > rhiD->caps.maxDrawBuffers) {
6923 qWarning(
"QGles2TextureRenderTarget: Too many color attachments (%d, max is %d)",
6924 count, rhiD->caps.maxDrawBuffers);
6927 if (m_desc.depthTexture() && !rhiD->caps.depthTexture)
6928 qWarning(
"QGles2TextureRenderTarget: Depth texture is not supported and will be ignored");
6930 if (!rhiD->ensureContext())
6933 rhiD->f->glGenFramebuffers(1, &framebuffer);
6934 rhiD->f->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6936 d.colorAttCount = 0;
6938 int multiViewCount = 0;
6939 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
6940 d.colorAttCount += 1;
6941 const QRhiColorAttachment &colorAtt(*it);
6942 QRhiTexture *texture = colorAtt.texture();
6943 QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer();
6944 Q_ASSERT(texture || renderBuffer);
6946 QGles2Texture *texD =
QRHI_RES(QGles2Texture, texture);
6947 Q_ASSERT(texD->texture && texD->specified);
6948 if (texD->flags().testFlag(QRhiTexture::ThreeDimensional) || texD->flags().testFlag(QRhiTexture::TextureArray)) {
6949 if (colorAtt.multiViewCount() < 2) {
6950 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture,
6951 colorAtt.level(), colorAtt.layer());
6953 multiViewCount = colorAtt.multiViewCount();
6954 if (texD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture && colorAtt.resolveTexture()) {
6959 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
6960 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6961 GL_COLOR_ATTACHMENT0 + uint(attIndex),
6962 resolveTexD->texture,
6963 colorAtt.resolveLevel(),
6965 colorAtt.resolveLayer(),
6968 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER,
6969 GL_COLOR_ATTACHMENT0 + uint(attIndex),
6976 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
6977 rhiD->glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex),
6978 texD->target + uint(colorAtt.layer()), texD->texture,
6981 if (texD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
6986 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
6988 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
6989 resolveTexD->texture, colorAtt.level(), texD->samples);
6992 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.layer()),
6993 texD->texture, colorAtt.level());
6996 if (attIndex == 0) {
6997 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
6998 d.sampleCount = texD->samples;
7000 }
else if (renderBuffer) {
7001 QGles2RenderBuffer *rbD =
QRHI_RES(QGles2RenderBuffer, renderBuffer);
7002 if (rbD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
7007 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
7009 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
7010 resolveTexD->texture, colorAtt.level(), rbD->samples);
7012 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), GL_RENDERBUFFER, rbD->renderbuffer);
7014 if (attIndex == 0) {
7015 d.pixelSize = rbD->pixelSize();
7016 d.sampleCount = rbD->samples;
7021 if (hasDepthStencil) {
7022 if (m_desc.depthStencilBuffer()) {
7023 QGles2RenderBuffer *depthRbD =
QRHI_RES(QGles2RenderBuffer, m_desc.depthStencilBuffer());
7024 if (rhiD->caps.needsDepthStencilCombinedAttach) {
7026 depthRbD->renderbuffer);
7028 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
7029 depthRbD->renderbuffer);
7030 if (depthRbD->stencilRenderbuffer) {
7031 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7032 depthRbD->stencilRenderbuffer);
7035 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
7036 depthRbD->renderbuffer);
7039 if (d.colorAttCount == 0) {
7040 d.pixelSize = depthRbD->pixelSize();
7041 d.sampleCount = depthRbD->samples;
7044 QGles2Texture *depthTexD =
QRHI_RES(QGles2Texture, m_desc.depthTexture());
7045 if (multiViewCount < 2) {
7046 if (depthTexD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && m_desc.depthResolveTexture()) {
7050 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
7051 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthResolveTexD->target,
7052 depthResolveTexD->texture, 0, depthTexD->samples);
7053 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
7054 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthResolveTexD->target,
7055 depthResolveTexD->texture, 0, depthTexD->samples);
7057 }
else if (rhiD->caps.ctxMajor >= 3 && depthTexD->flags().testFlag(QRhiTexture::TextureArray) && m_desc.depthLayer() >= 0) {
7058 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
7059 0, m_desc.depthLayer());
7060 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
7061 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
7062 0, m_desc.depthLayer());
7065 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->target,
7066 depthTexD->texture, 0);
7067 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
7068 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->target,
7069 depthTexD->texture, 0);
7073 if (depthTexD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture) {
7091 if (!m_flags.testFlag(DoNotStoreDepthStencilContents) && !m_desc.depthResolveTexture()) {
7092 qWarning(
"Attempted to create a multiview+multisample QRhiTextureRenderTarget, but DoNotStoreDepthStencilContents was not set."
7093 " This path has no choice but to behave as if DoNotStoreDepthStencilContents was set, because QRhi is forced to create"
7094 " a throwaway non-multisample depth texture here. Set the flag to silence this warning, or set a depthResolveTexture.");
7096 if (m_desc.depthResolveTexture()) {
7097 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
7098 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7099 GL_DEPTH_ATTACHMENT,
7100 depthResolveTexD->texture,
7105 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
7106 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7107 GL_STENCIL_ATTACHMENT,
7108 depthResolveTexD->texture,
7115 if (!nonMsaaThrowawayDepthTexture) {
7116 rhiD->f->glGenTextures(1, &nonMsaaThrowawayDepthTexture);
7119 depthTexD->pixelSize().width(), depthTexD->pixelSize().height(), multiViewCount);
7121 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7122 GL_DEPTH_ATTACHMENT,
7123 nonMsaaThrowawayDepthTexture,
7128 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
7129 GL_STENCIL_ATTACHMENT,
7130 nonMsaaThrowawayDepthTexture,
7140 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
7141 0, 0, multiViewCount);
7142 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
7143 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
7144 0, 0, multiViewCount);
7148 if (d.colorAttCount == 0) {
7149 d.pixelSize = depthTexD->pixelSize();
7150 d.sampleCount = depthTexD->samples;
7159 d.rp =
QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
7161 GLenum status = rhiD->f->glCheckFramebufferStatus(GL_FRAMEBUFFER);
7162 if (status != GL_NO_ERROR && status != GL_FRAMEBUFFER_COMPLETE) {
7163 qWarning(
"Framebuffer incomplete: 0x%x", status);
7167 if (rhiD->glObjectLabel)
7168 rhiD->glObjectLabel(GL_FRAMEBUFFER, framebuffer, -1, m_objectName.constData());
7170 QRhiRenderTargetAttachmentTracker::updateResIdList<QGles2Texture, QGles2RenderBuffer>(m_desc, &d.currentResIdList);
7172 rhiD->registerResource(
this);