798 Q_ASSERT(fallbackSurface);
802 ctx =
new QOpenGLContext;
803 ctx->setFormat(requestedFormat);
804 if (maybeShareContext) {
805 ctx->setShareContext(maybeShareContext);
807 ctx->setScreen(maybeWindow->screen());
809 ctx->setScreen(maybeShareContext->screen());
810 }
else if (QOpenGLContext *shareContext = QOpenGLContext::globalShareContext()) {
811 ctx->setShareContext(shareContext);
813 ctx->setScreen(maybeWindow->screen());
815 ctx->setScreen(shareContext->screen());
816 }
else if (maybeWindow) {
817 ctx->setScreen(maybeWindow->screen());
819 if (!ctx->create()) {
820 qWarning(
"QRhiGles2: Failed to create context");
825 qCDebug(QRHI_LOG_INFO) <<
"Created OpenGL context" << ctx->format();
828 if (!ensureContext(maybeWindow ? maybeWindow : fallbackSurface))
831 f =
static_cast<QOpenGLExtensions *>(ctx->extraFunctions());
832 const QSurfaceFormat actualFormat = ctx->format();
833 caps.gles = actualFormat.renderableType() == QSurfaceFormat::OpenGLES;
837 ctx->getProcAddress(QByteArrayLiteral(
"glPolygonMode")));
840 GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum,
const void *)>(
841 ctx->getProcAddress(QByteArrayLiteral(
"glTexImage1D")));
843 glTexStorage1D =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei)>(
844 ctx->getProcAddress(QByteArrayLiteral(
"glTexStorage1D")));
847 GLenum, GLint, GLint, GLsizei, GLenum, GLenum,
const GLvoid *)>(
848 ctx->getProcAddress(QByteArrayLiteral(
"glTexSubImage1D")));
850 glCopyTexSubImage1D =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint,
852 ctx->getProcAddress(QByteArrayLiteral(
"glCopyTexSubImage1D")));
855 GLenum, GLint, GLenum, GLsizei, GLint, GLsizei,
const GLvoid *)>(
856 ctx->getProcAddress(QByteArrayLiteral(
"glCompressedTexImage1D")));
859 GLenum, GLint, GLint, GLsizei, GLenum, GLsizei,
const GLvoid *)>(
860 ctx->getProcAddress(QByteArrayLiteral(
"glCompressedTexSubImage1D")));
862 glFramebufferTexture1D =
864 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture1D")));
867 const char *vendor =
reinterpret_cast<
const char *>(
f->glGetString(GL_VENDOR));
868 const char *renderer =
reinterpret_cast<
const char *>(
f->glGetString(GL_RENDERER));
869 const char *version =
reinterpret_cast<
const char *>(
f->glGetString(GL_VERSION));
870 if (vendor && renderer && version)
871 qCDebug(QRHI_LOG_INFO,
"OpenGL VENDOR: %s RENDERER: %s VERSION: %s", vendor, renderer, version);
874 driverInfoStruct.deviceName += QByteArray(vendor);
875 driverInfoStruct.deviceName +=
' ';
878 driverInfoStruct.deviceName += QByteArray(renderer);
879 driverInfoStruct.deviceName +=
' ';
882 driverInfoStruct.deviceName += QByteArray(version);
884 caps.ctxMajor = actualFormat.majorVersion();
885 caps.ctxMinor = actualFormat.minorVersion();
890 QVarLengthArray<GLint, 16> compressedTextureFormats(n);
892 for (GLint format : compressedTextureFormats)
893 supportedCompressedFormats.insert(format);
906 std::array<QRhiTexture::Flags, 2> textureVariantFlags;
907 textureVariantFlags[0] = {};
908 textureVariantFlags[1] = QRhiTexture::sRGB;
909 if (
f->hasOpenGLExtension(QOpenGLExtensions::DDSTextureCompression)) {
910 for (QRhiTexture::Flags f : textureVariantFlags) {
911 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC1, f));
912 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC2, f));
913 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC3, f));
916 if (
f->hasOpenGLExtension(QOpenGLExtensions::ETC2TextureCompression)) {
917 for (QRhiTexture::Flags f : textureVariantFlags) {
918 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8, f));
919 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8A1, f));
920 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGBA8, f));
923 if (
f->hasOpenGLExtension(QOpenGLExtensions::ASTCTextureCompression)) {
924 for (QRhiTexture::Flags f : textureVariantFlags) {
925 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_4x4, f));
926 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x4, f));
927 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x5, f));
928 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x5, f));
929 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x6, f));
930 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x5, f));
931 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x6, f));
932 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x8, f));
933 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x5, f));
934 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x8, f));
935 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x10, f));
936 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x10, f));
937 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x12, f));
941 f->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.maxTextureSize);
943 if (!caps.gles || caps.ctxMajor >= 3) {
946 caps.hasDrawBuffersFunc =
true;
948 caps.maxSamples = qMax(1, caps.maxSamples);
951 caps.maxDrawBuffers = 1;
952 caps.hasDrawBuffersFunc =
false;
958 caps.msaaRenderBuffer = f->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
959 && f->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
961 caps.npotTextureFull = f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)
962 && f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
965 caps.fixedIndexPrimitiveRestart = caps.ctxMajor >= 3;
967 caps.fixedIndexPrimitiveRestart = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
969 if (caps.fixedIndexPrimitiveRestart) {
979 caps.bgraExternalFormat = f->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat);
980 caps.bgraInternalFormat = caps.bgraExternalFormat && caps.gles;
981 caps.r8Format = f->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats);
984 caps.r32uiFormat = (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1)) && caps.r8Format;
986 caps.r32uiFormat =
true;
989 caps.imageLoadStore = caps.r32uiFormat;
991 caps.imageLoadStore = (caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 2));
993 caps.r16Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats);
994 caps.floatFormats = caps.ctxMajor >= 3;
995 caps.rgb10Formats = caps.ctxMajor >= 3;
996 caps.depthTexture = caps.ctxMajor >= 3;
997 caps.packedDepthStencil = f->hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil);
999 caps.needsDepthStencilCombinedAttach =
true;
1001 caps.needsDepthStencilCombinedAttach =
false;
1008 caps.srgbWriteControl = ctx->hasExtension(
"GL_EXT_framebuffer_sRGB") || ctx->hasExtension(
"GL_EXT_sRGB_write_control");
1010 caps.coreProfile = actualFormat.profile() == QSurfaceFormat::CoreProfile;
1015 caps.vertexArrayObject = caps.coreProfile || (caps.gles && caps.ctxMajor >= 3);
1018 caps.uniformBuffers = caps.ctxMajor >= 3;
1020 caps.uniformBuffers = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1022 caps.elementIndexUint = f->hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint);
1023 caps.depth24 = f->hasOpenGLExtension(QOpenGLExtensions::Depth24);
1024 caps.rgba8Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized8Formats);
1027 caps.instancing = caps.ctxMajor >= 3;
1029 caps.instancing = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 3);
1031 caps.baseVertex = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1034 caps.compute = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1036 caps.compute = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1044 caps.maxThreadGroupsPerDimension = qMin(tgPerDim[0], qMin(tgPerDim[1], tgPerDim[2]));
1051 caps.depthClamp =
false;
1053 caps.depthClamp = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1054 if (!caps.depthClamp)
1055 caps.depthClamp = ctx->hasExtension(
"GL_EXT_depth_clamp") || ctx->hasExtension(
"GL_ARB_depth_clamp");
1058 caps.textureCompareMode = caps.ctxMajor >= 3;
1060 caps.textureCompareMode =
true;
1064 caps.properMapBuffer = f->hasOpenGLExtension(QOpenGLExtensions::MapBufferRange);
1067 caps.nonBaseLevelFramebufferTexture = caps.ctxMajor >= 3;
1069 caps.nonBaseLevelFramebufferTexture =
true;
1071 caps.texelFetch = caps.ctxMajor >= 3;
1072 caps.intAttributes = caps.ctxMajor >= 3;
1073 caps.screenSpaceDerivatives = f->hasOpenGLExtension(QOpenGLExtensions::StandardDerivatives);
1076 caps.multisampledTexture = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1078 caps.multisampledTexture = caps.ctxMajor >= 3;
1083 caps.programBinary = caps.ctxMajor >= 3;
1085 caps.programBinary = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 1);
1087 if (caps.programBinary) {
1091 caps.programBinary =
false;
1094 caps.texture3D = caps.ctxMajor >= 3;
1097 caps.texture1D =
false;
1099 caps.texture1D = glTexImage1D && (caps.ctxMajor >= 2);
1102 caps.tessellation = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1104 caps.tessellation = caps.ctxMajor >= 4;
1107 caps.geometryShader = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1109 caps.geometryShader = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1111 if (caps.ctxMajor >= 3) {
1112 GLint maxArraySize = 0;
1114 caps.maxTextureArraySize = maxArraySize;
1116 caps.maxTextureArraySize = 0;
1123 GLint maxVertexUniformVectors = 0;
1125 GLint maxFragmentUniformVectors = 0;
1127 caps.maxUniformVectors = qMin(maxVertexUniformVectors, maxFragmentUniformVectors);
1129 GLint maxVertexUniformComponents = 0;
1131 GLint maxFragmentUniformComponents = 0;
1133 caps.maxUniformVectors = qMin(maxVertexUniformComponents, maxFragmentUniformComponents) / 4;
1136 f->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.maxVertexInputs);
1140 }
else if (caps.ctxMajor >= 3) {
1141 GLint components = 0;
1143 caps.maxVertexOutputs = components / 4;
1147 GLint components = 0;
1150 caps.maxVertexOutputs = components / 4;
1155 if (!caps.coreProfile)
1162 if (!caps.gles && (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2)))
1165 caps.halfAttributes = f->hasOpenGLExtension(QOpenGLExtensions::HalfFloatVertex);
1168 caps.multiView = f->hasOpenGLExtension(QOpenGLExtensions::MultiView)
1169 && f->hasOpenGLExtension(QOpenGLExtensions::MultiViewExtended);
1170 if (caps.multiView) {
1171 glFramebufferTextureMultiviewOVR =
1172 reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei)>(
1173 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultiviewOVR")));
1177 caps.timestamps = !caps.gles && (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 3));
1178 if (caps.timestamps) {
1180 ctx->getProcAddress(QByteArrayLiteral(
"glQueryCounter")));
1181 glGetQueryObjectui64v =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLuint, GLenum, quint64 *)>(
1182 ctx->getProcAddress(QByteArrayLiteral(
"glGetQueryObjectui64v")));
1183 if (!glQueryCounter || !glGetQueryObjectui64v)
1184 caps.timestamps =
false;
1189 caps.objectLabel = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1191 caps.objectLabel = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1192 if (caps.objectLabel) {
1193 glObjectLabel =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLuint, GLsizei,
const GLchar *)>(
1194 ctx->getProcAddress(QByteArrayLiteral(
"glObjectLabel")));
1204 caps.glesMultisampleRenderToTexture = ctx->hasExtension(
"GL_EXT_multisampled_render_to_texture");
1205 if (caps.glesMultisampleRenderToTexture) {
1206 glFramebufferTexture2DMultisampleEXT =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei)>(
1207 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture2DMultisampleEXT")));
1208 glRenderbufferStorageMultisampleEXT =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)>(
1209 ctx->getProcAddress(QByteArrayLiteral(
"glRenderbufferStorageMultisampleEXT")));
1211 caps.glesMultiviewMultisampleRenderToTexture = ctx->hasExtension(
"GL_OVR_multiview_multisampled_render_to_texture");
1212 if (caps.glesMultiviewMultisampleRenderToTexture) {
1213 glFramebufferTextureMultisampleMultiviewOVR =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei)>(
1214 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultisampleMultiviewOVR")));
1217 caps.glesMultisampleRenderToTexture =
false;
1218 caps.glesMultiviewMultisampleRenderToTexture =
false;
1221 caps.unpackRowLength = !caps.gles || caps.ctxMajor >= 3;
1224 caps.perRenderTargetBlending = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1226 caps.perRenderTargetBlending = caps.ctxMajor >= 4;
1229 if (caps.ctxMajor == 3 && caps.ctxMinor < 2) {
1230 caps.sampleVariables = ctx->hasExtension(
"GL_OES_sample_variables");
1232 caps.sampleVariables = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1235 caps.sampleVariables = caps.ctxMajor >= 4;
1239 caps.drawIndirect = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1241 caps.drawIndirect = caps.ctxMajor >= 4;
1242 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_draw_indirect")))
1243 caps.drawIndirect =
true;
1246 caps.drawIndirectMulti =
false;
1248 caps.drawIndirectMulti = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1249 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_multi_draw_indirect")) ||
1250 ctx->hasExtension(QByteArrayLiteral(
"GL_EXT_multi_draw_indirect")))
1251 caps.drawIndirectMulti =
true;
1253 if (caps.drawIndirectMulti) {
1254 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1255 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirect")));
1256 if (!glMultiDrawArraysIndirect)
1257 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1258 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectARB")));
1259 if (!glMultiDrawArraysIndirect)
1260 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1261 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectEXT")));
1262 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1263 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirect")));
1264 if (!glMultiDrawElementsIndirect)
1265 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1266 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectARB")));
1267 if (!glMultiDrawElementsIndirect)
1268 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1269 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectEXT")));
1271 qWarning(
"Failed to resolve glMultiDrawArraysIndirect or glMultiDrawElementsIndirect.");
1272 caps.drawIndirectMulti =
false;
1277 caps.shaderDrawParameters =
false;
1279 caps.shaderDrawParameters = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 6);
1280 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_shader_draw_parameters")))
1281 caps.shaderDrawParameters =
true;
1283 nativeHandlesStruct.context = ctx;
2685 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
2688 const bool isCompressed = isCompressedFormat(texD->m_format);
2689 const bool isCubeMap = texD->m_flags.testFlag(QRhiTexture::CubeMap);
2690 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2691 const bool is1D = texD->m_flags.testFlag(QRhiTexture::OneDimensional);
2692 const bool isArray = texD->m_flags.testFlag(QRhiTexture::TextureArray);
2694 const GLenum effectiveTarget = faceTargetBase + (isCubeMap ? uint(layer) : 0u);
2695 const QPoint dp = subresDesc.destinationTopLeft();
2696 const QByteArray rawData = subresDesc.data();
2698 auto setCmdByNotCompressedData = [&](
const void* data, QSize size, quint32 dataStride)
2700 quint32 bytesPerLine = 0;
2701 quint32 bytesPerPixel = 0;
2702 textureFormatInfo(texD->m_format, size, &bytesPerLine,
nullptr, &bytesPerPixel);
2706 cmd.args.subImage.target = texD->target;
2707 cmd.args.subImage.texture = texD->texture;
2708 cmd.args.subImage.faceTarget = effectiveTarget;
2709 cmd.args.subImage.level = level;
2710 cmd.args.subImage.dx = dp.x();
2711 cmd.args.subImage.dy = is1D && isArray ? layer : dp.y();
2712 cmd.args.subImage.dz = is3D || isArray ? layer : 0;
2713 cmd.args.subImage.w = size.width();
2714 cmd.args.subImage.h = size.height();
2715 cmd.args.subImage.glformat = texD->glformat;
2716 cmd.args.subImage.gltype = texD->gltype;
2718 if (dataStride == 0)
2719 dataStride = bytesPerLine;
2721 cmd.args.subImage.rowStartAlign = (dataStride & 3) ? 1 : 4;
2722 cmd.args.subImage.rowLength = caps.unpackRowLength ? (bytesPerPixel ? dataStride / bytesPerPixel : 0) : 0;
2724 cmd.args.subImage.data = data;
2727 if (!subresDesc.image().isNull()) {
2728 QImage img = subresDesc.image();
2729 QSize size = img.size();
2730 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
2731 const QPoint sp = subresDesc.sourceTopLeft();
2732 if (!subresDesc.sourceSize().isEmpty())
2733 size = subresDesc.sourceSize();
2734 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2735 if (caps.unpackRowLength) {
2736 cbD->retainImage(img);
2738 const uchar *data = img.constBits() + sp.y() * img.bytesPerLine() + sp.x() * (qMax(1, img.depth() / 8));
2739 img = QImage(data, size.width(), size.height(), img.bytesPerLine(), img.format());
2741 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
2744 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2747 setCmdByNotCompressedData(cbD->retainImage(img), size, img.bytesPerLine());
2748 }
else if (!rawData.isEmpty() && isCompressed) {
2749 const int depth = qMax(1, texD->m_depth);
2750 const int arraySize = qMax(0, texD->m_arraySize);
2751 if ((texD->flags().testFlag(QRhiTexture::UsedAsCompressedAtlas) || is3D || isArray)
2759 quint32 levelByteSize = 0;
2760 compressedFormatInfo(texD->m_format, texD->m_pixelSize,
nullptr, &levelByteSize,
nullptr);
2761 quint64 byteSize = levelByteSize;
2763 byteSize *= quint64(depth);
2765 byteSize *= quint64(arraySize);
2766 if (byteSize > quint64(
std::numeric_limits<
int>::max())) {
2767 qWarning(
"Compressed texture zero-initialization would need %llu bytes "
2768 "which is too large; skipping", byteSize);
2771 QByteArray zeroBuf(qsizetype(byteSize), 0);
2774 cmd.args.compressedImage.target = texD->target;
2775 cmd.args.compressedImage.texture = texD->texture;
2776 cmd.args.compressedImage.faceTarget = effectiveTarget;
2777 cmd.args.compressedImage.level = level;
2778 cmd.args.compressedImage.glintformat = texD->glintformat;
2779 cmd.args.compressedImage.w = texD->m_pixelSize.width();
2780 cmd.args.compressedImage.h = is1D && isArray ? arraySize : texD->m_pixelSize.height();
2781 cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
2782 cmd.args.compressedImage.size =
int(byteSize);
2783 cmd.args.compressedImage.data = cbD->retainData(zeroBuf);
2787 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2788 : subresDesc.sourceSize();
2792 cmd.args.compressedSubImage.target = texD->target;
2793 cmd.args.compressedSubImage.texture = texD->texture;
2794 cmd.args.compressedSubImage.faceTarget = effectiveTarget;
2795 cmd.args.compressedSubImage.level = level;
2796 cmd.args.compressedSubImage.dx = dp.x();
2797 cmd.args.compressedSubImage.dy = is1D && isArray ? layer : dp.y();
2798 cmd.args.compressedSubImage.dz = is3D || isArray ? layer : 0;
2799 cmd.args.compressedSubImage.w = size.width();
2800 cmd.args.compressedSubImage.h = size.height();
2801 cmd.args.compressedSubImage.glintformat = texD->glintformat;
2802 cmd.args.compressedSubImage.size = rawData.size();
2803 cmd.args.compressedSubImage.data = cbD->retainData(rawData);
2807 cmd.args.compressedImage.target = texD->target;
2808 cmd.args.compressedImage.texture = texD->texture;
2809 cmd.args.compressedImage.faceTarget = effectiveTarget;
2810 cmd.args.compressedImage.level = level;
2811 cmd.args.compressedImage.glintformat = texD->glintformat;
2812 cmd.args.compressedImage.w = size.width();
2813 cmd.args.compressedImage.h = is1D && isArray ? arraySize : size.height();
2814 cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
2815 cmd.args.compressedImage.size = rawData.size();
2816 cmd.args.compressedImage.data = cbD->retainData(rawData);
2818 }
else if (!rawData.isEmpty()) {
2819 QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2820 : subresDesc.sourceSize();
2821 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2822 quint32 bytesPerPixel = 0;
2823 textureFormatInfo(texD->m_format, size,
nullptr,
nullptr, &bytesPerPixel);
2824 size = clampedSubResourceUploadSizeForSourceData(size, subresDesc.dataStride(),
2825 bytesPerPixel, rawData.size());
2829 setCmdByNotCompressedData(cbD->retainData(rawData), size, subresDesc.dataStride());
2831 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
3370 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
3374 if (cmd.args.beginFrame.timestampQuery)
3376 if (caps.vertexArrayObject) {
3378 f->glGenVertexArrays(1, &vao);
3379 f->glBindVertexArray(vao);
3386 f->glVertexAttribDivisor(GLuint(i), 0);
3389 f->glVertexAttribDivisor(GLuint(i), 0);
3396 f->glDisableVertexAttribArray(GLuint(i));
3401 f->glBindVertexArray(0);
3402 if (cmd.args.endFrame.timestampQuery)
3407 f->glBindVertexArray(vao);
3410 f->glViewport(GLint(cmd.args.viewport.x), GLint(cmd.args.viewport.y), GLsizei(cmd.args.viewport.w), GLsizei(cmd.args.viewport.h));
3411 f->glDepthRangef(cmd.args.viewport.d0, cmd.args.viewport.d1);
3414 f->glScissor(cmd.args.scissor.x, cmd.args.scissor.y, cmd.args.scissor.w, cmd.args.scissor.h);
3417 f->glBlendColor(cmd.args.blendConstants.r, cmd.args.blendConstants.g, cmd.args.blendConstants.b, cmd.args.blendConstants.a);
3423 const GLint ref = GLint(cmd.args.stencilRef.ref);
3424 f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), ref, psD->m_stencilReadMask);
3425 f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), ref, psD->m_stencilReadMask);
3426 cbD->graphicsPassState.dynamic.stencilRef = ref;
3428 qWarning(
"No graphics pipeline active for setStencilRef; ignored");
3436 if (state.lastBindVertexBuffer.ps == psD
3437 && state.lastBindVertexBuffer.buffer == cmd.args.bindVertexBuffer.buffer
3438 && state.lastBindVertexBuffer.offset == cmd.args.bindVertexBuffer.offset
3439 && state.lastBindVertexBuffer.binding == cmd.args.bindVertexBuffer.binding)
3446 state.lastBindVertexBuffer.ps = psD;
3447 state.lastBindVertexBuffer.buffer = cmd.args.bindVertexBuffer.buffer;
3448 state.lastBindVertexBuffer.offset = cmd.args.bindVertexBuffer.offset;
3449 state.lastBindVertexBuffer.binding = cmd.args.bindVertexBuffer.binding;
3451 if (cmd.args.bindVertexBuffer.buffer != state.currentArrayBuffer) {
3452 state.currentArrayBuffer = cmd.args.bindVertexBuffer.buffer;
3454 f->glBindBuffer(GL_ARRAY_BUFFER, state.currentArrayBuffer);
3456 for (
auto it = psD->m_vertexInputLayout.cbeginAttributes(), itEnd = psD->m_vertexInputLayout.cendAttributes();
3459 const int bindingIdx = it->binding();
3460 if (bindingIdx != cmd.args.bindVertexBuffer.binding)
3463 const QRhiVertexInputBinding *inputBinding = psD->m_vertexInputLayout.bindingAt(bindingIdx);
3464 const int stride =
int(inputBinding->stride());
3467 bool normalize =
false;
3468 switch (it->format()) {
3469 case QRhiVertexInputAttribute::Float4:
3473 case QRhiVertexInputAttribute::Float3:
3477 case QRhiVertexInputAttribute::Float2:
3481 case QRhiVertexInputAttribute::Float:
3485 case QRhiVertexInputAttribute::UNormByte4:
3490 case QRhiVertexInputAttribute::UNormByte2:
3495 case QRhiVertexInputAttribute::UNormByte:
3500 case QRhiVertexInputAttribute::UInt4:
3501 type = GL_UNSIGNED_INT;
3504 case QRhiVertexInputAttribute::UInt3:
3505 type = GL_UNSIGNED_INT;
3508 case QRhiVertexInputAttribute::UInt2:
3509 type = GL_UNSIGNED_INT;
3512 case QRhiVertexInputAttribute::UInt:
3513 type = GL_UNSIGNED_INT;
3516 case QRhiVertexInputAttribute::SInt4:
3520 case QRhiVertexInputAttribute::SInt3:
3524 case QRhiVertexInputAttribute::SInt2:
3528 case QRhiVertexInputAttribute::SInt:
3532 case QRhiVertexInputAttribute::Half4:
3536 case QRhiVertexInputAttribute::Half3:
3540 case QRhiVertexInputAttribute::Half2:
3544 case QRhiVertexInputAttribute::Half:
3548 case QRhiVertexInputAttribute::UShort4:
3549 type = GL_UNSIGNED_SHORT;
3552 case QRhiVertexInputAttribute::UShort3:
3553 type = GL_UNSIGNED_SHORT;
3556 case QRhiVertexInputAttribute::UShort2:
3557 type = GL_UNSIGNED_SHORT;
3560 case QRhiVertexInputAttribute::UShort:
3561 type = GL_UNSIGNED_SHORT;
3564 case QRhiVertexInputAttribute::SShort4:
3568 case QRhiVertexInputAttribute::SShort3:
3572 case QRhiVertexInputAttribute::SShort2:
3576 case QRhiVertexInputAttribute::SShort:
3584 const int locationIdx = it->location();
3585 quint32 ofs = it->offset() + cmd.args.bindVertexBuffer.offset;
3586 if (type == GL_UNSIGNED_INT || type == GL_INT) {
3587 if (caps.intAttributes) {
3588 f->glVertexAttribIPointer(GLuint(locationIdx), size, type, stride,
3589 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3591 qWarning(
"Current RHI backend does not support IntAttributes. Check supported features.");
3597 f->glVertexAttribPointer(GLuint(locationIdx), size, type, normalize, stride,
3598 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3603 f->glEnableVertexAttribArray(GLuint(locationIdx));
3605 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance && caps.instancing) {
3606 f->glVertexAttribDivisor(GLuint(locationIdx), inputBinding->instanceStepRate());
3617 f->glVertexAttribDivisor(GLuint(locationIdx), 0);
3623 qWarning(
"No graphics pipeline active for setVertexInput; ignored");
3628 state.indexType = cmd.args.bindIndexBuffer.type;
3629 state.indexStride = state.indexType == GL_UNSIGNED_SHORT ?
sizeof(quint16) :
sizeof(quint32);
3630 state.indexOffset = cmd.args.bindIndexBuffer.offset;
3631 if (state.currentElementArrayBuffer != cmd.args.bindIndexBuffer.buffer) {
3632 state.currentElementArrayBuffer = cmd.args.bindIndexBuffer.buffer;
3633 f->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state.currentElementArrayBuffer);
3640 if (cmd.args.draw.instanceCount == 1 || !caps.instancing) {
3641 f->glDrawArrays(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount));
3643 f->glDrawArraysInstanced(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount),
3644 GLsizei(cmd.args.draw.instanceCount));
3647 qWarning(
"No graphics pipeline active for draw; ignored");
3655 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3656 quintptr(cmd.args.drawIndexed.firstIndex * state.indexStride + state.indexOffset));
3657 if (cmd.args.drawIndexed.instanceCount == 1 || !caps.instancing) {
3658 if (cmd.args.drawIndexed.baseVertex != 0 && caps.baseVertex) {
3659 f->glDrawElementsBaseVertex(psD->drawMode,
3660 GLsizei(cmd.args.drawIndexed.indexCount),
3663 cmd.args.drawIndexed.baseVertex);
3665 f->glDrawElements(psD->drawMode,
3666 GLsizei(cmd.args.drawIndexed.indexCount),
3671 if (cmd.args.drawIndexed.baseVertex != 0 && caps.baseVertex) {
3672 f->glDrawElementsInstancedBaseVertex(psD->drawMode,
3673 GLsizei(cmd.args.drawIndexed.indexCount),
3676 GLsizei(cmd.args.drawIndexed.instanceCount),
3677 cmd.args.drawIndexed.baseVertex);
3679 f->glDrawElementsInstanced(psD->drawMode,
3680 GLsizei(cmd.args.drawIndexed.indexCount),
3683 GLsizei(cmd.args.drawIndexed.instanceCount));
3687 qWarning(
"No graphics pipeline active for drawIndexed; ignored");
3697 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3698 quintptr(cmd.args.drawIndirect.offset));
3701 cmd.args.drawIndirect.drawCount
,
3702 cmd.args.drawIndirect.stride
);
3704 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
3705 const quintptr indirectOffset = quintptr(cmd.args.drawIndirect.offset)
3706 + quintptr(i) * cmd.args.drawIndirect.stride;
3707 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(indirectOffset);
3708 f->glDrawArraysIndirect(psD->drawMode,
3714 qWarning(
"No graphics pipeline active for drawIndirect; ignored");
3724 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3725 quintptr(cmd.args.drawIndexedIndirect.offset));
3729 cmd.args.drawIndexedIndirect.drawCount
,
3730 cmd.args.drawIndexedIndirect.stride
);
3732 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
3733 const quintptr indirectOffset = quintptr(cmd.args.drawIndexedIndirect.offset)
3734 + quintptr(i) * cmd.args.drawIndexedIndirect.stride;
3735 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(indirectOffset);
3736 f->glDrawElementsIndirect(psD->drawMode,
3743 qWarning(
"No graphics pipeline active for drawIndexedIndirect; ignored");
3750 case QGles2CommandBuffer::Command::BindShaderResources:
3751 bindShaderResources(cbD,
3752 cmd.args.bindShaderResources.maybeGraphicsPs,
3753 cmd.args.bindShaderResources.maybeComputePs,
3754 cmd.args.bindShaderResources.srb,
3755 cmd.args.bindShaderResources.dynamicOffsetPairs,
3756 cmd.args.bindShaderResources.dynamicOffsetCount);
3760 QVarLengthArray<GLenum, 8> bufs;
3761 GLuint fbo = cmd.args.bindFramebuffer.fbo;
3763 fbo = ctx->defaultFramebufferObject();
3764 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3766 const int colorAttCount = cmd.args.bindFramebuffer.colorAttCount;
3767 bufs.append(colorAttCount > 0 ? GL_COLOR_ATTACHMENT0 : GL_NONE);
3768 if (caps.maxDrawBuffers > 1) {
3769 for (
int i = 1; i < colorAttCount; ++i)
3770 bufs.append(GL_COLOR_ATTACHMENT0 + uint(i));
3773 if (cmd.args.bindFramebuffer.stereo && cmd.args.bindFramebuffer.stereoTarget == QRhiSwapChain::RightBuffer)
3778 if (caps.hasDrawBuffersFunc)
3779 f->glDrawBuffers(bufs.count(), bufs.constData());
3780 if (caps.srgbWriteControl) {
3781 if (cmd.args.bindFramebuffer.srgb)
3789 f->glDisable(GL_SCISSOR_TEST);
3790 if (cmd.args.clear.mask & GL_COLOR_BUFFER_BIT) {
3791 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3792 f->glClearColor(cmd.args.clear.c[0], cmd.args.clear.c[1], cmd.args.clear.c[2], cmd.args.clear.c[3]);
3794 if (cmd.args.clear.mask & GL_DEPTH_BUFFER_BIT) {
3795 f->glDepthMask(GL_TRUE);
3796 f->glClearDepthf(cmd.args.clear.d);
3798 if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT) {
3799 f->glStencilMask(0xFF);
3800 f->glClearStencil(GLint(cmd.args.clear.s));
3802 f->glClear(cmd.args.clear.mask);
3803 cbD->graphicsPassState.reset();
3806 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.bufferSubData.target, cmd.args.bufferSubData.buffer);
3807 f->glBufferSubData(cmd.args.bufferSubData.target, cmd.args.bufferSubData.offset, cmd.args.bufferSubData.size,
3808 cmd.args.bufferSubData.data);
3812 QRhiReadbackResult *result = cmd.args.getBufferSubData.result;
3813 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.getBufferSubData.target, cmd.args.getBufferSubData.buffer);
3815 if (caps.properMapBuffer) {
3816 void *p =
f->glMapBufferRange(cmd.args.getBufferSubData.target,
3817 cmd.args.getBufferSubData.offset,
3818 cmd.args.getBufferSubData.size,
3821 result->data.resize(cmd.args.getBufferSubData.size);
3822 memcpy(result->data.data(), p, size_t(cmd.args.getBufferSubData.size));
3823 f->glUnmapBuffer(cmd.args.getBufferSubData.target);
3827 result->data.resize(cmd.args.getBufferSubData.size);
3828 f->glGetBufferSubData(cmd.args.getBufferSubData.target,
3829 cmd.args.getBufferSubData.offset,
3830 cmd.args.getBufferSubData.size,
3831 result->data.data());
3833 if (result->completed)
3834 result->completed();
3840 f->glGenFramebuffers(1, &fbo);
3841 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3845 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.copyTex.srcTexture,
3846 cmd.args.copyTex.srcLevel, cmd.args.copyTex.srcZ);
3849 cmd.args.copyTex.srcTarget, cmd.args.copyTex.srcTexture,
3850 cmd.args.copyTex.srcLevel);
3852 f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
3853 cmd.args.copyTex.srcFaceTarget, cmd.args.copyTex.srcTexture, cmd.args.copyTex.srcLevel);
3855 f->glBindTexture(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstTexture);
3857 f->glCopyTexSubImage3D(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstLevel,
3858 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY, cmd.args.copyTex.dstZ,
3859 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
3860 cmd.args.copyTex.w, cmd.args.copyTex.h);
3863 cmd.args.copyTex.dstX
, cmd.args.copyTex.srcX
,
3864 cmd.args.copyTex.srcY
, cmd.args.copyTex.w
);
3866 f->glCopyTexSubImage2D(cmd.args.copyTex.dstFaceTarget, cmd.args.copyTex.dstLevel,
3867 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY,
3868 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
3869 cmd.args.copyTex.w, cmd.args.copyTex.h);
3871 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
3872 f->glDeleteFramebuffers(1, &fbo);
3877 QRhiReadbackResult *result = cmd.args.readPixels.result;
3878 GLuint tex = cmd.args.readPixels.texture;
3881 result->pixelSize = QSize(cmd.args.readPixels.w, cmd.args.readPixels.h);
3883 result->format = cmd.args.readPixels.format;
3884 mipLevel = cmd.args.readPixels.level;
3885 if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
3886 f->glGenFramebuffers(1, &fbo);
3887 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3888 if (cmd.args.readPixels.slice3D >= 0) {
3889 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
3890 tex, mipLevel, cmd.args.readPixels.slice3D);
3891 }
else if (cmd.args.readPixels.readTarget ==
GL_TEXTURE_1D) {
3893 cmd.args.readPixels.readTarget, tex, mipLevel);
3895 f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
3896 cmd.args.readPixels.readTarget, tex, mipLevel);
3900 result->format = QRhiTexture::RGBA8;
3903 const int x = cmd.args.readPixels.x;
3904 const int y = cmd.args.readPixels.y;
3905 const int w = cmd.args.readPixels.w;
3906 const int h = cmd.args.readPixels.h;
3907 if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
3910 if (result->format == QRhiTexture::R8 || result->format == QRhiTexture::RED_OR_ALPHA8) {
3911 result->data.resizeForOverwrite(w * h);
3913 tmpBuf.resizeForOverwrite(w * h * 4);
3915 const quint8 *srcBase =
reinterpret_cast<
const quint8 *>(tmpBuf.constData());
3916 quint8 *dstBase =
reinterpret_cast<quint8 *>(result->data.data());
3917 const int componentIndex = isFeatureSupported(QRhi::RedOrAlpha8IsRed) ? 0 : 3;
3918 for (
int y = 0; y < h; ++y) {
3919 const quint8 *src = srcBase + y * w * 4;
3920 quint8 *dst = dstBase + y * w;
3922 while (count-- > 0) {
3923 *dst++ = src[componentIndex];
3930 [[maybe_unused]] GLenum glintformat;
3931 [[maybe_unused]] GLenum glsizedintformat;
3934 toGlTextureFormat(result->format, caps, &glintformat, &glsizedintformat, &glformat, &gltype);
3936 textureFormatInfo(result->format, result->pixelSize,
nullptr, &byteSize,
nullptr);
3937 result->data.resizeForOverwrite(byteSize);
3938 f->glReadPixels(x, y, w, h, glformat, gltype, result->data.data());
3941 result->data.resizeForOverwrite(w * h * 4);
3942 result->data.fill(
'\0');
3945 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
3946 f->glDeleteFramebuffers(1, &fbo);
3948 if (result->completed)
3949 result->completed();
3953 f->glBindTexture(cmd.args.subImage.target, cmd.args.subImage.texture);
3954 if (cmd.args.subImage.rowStartAlign != 4)
3955 f->glPixelStorei(GL_UNPACK_ALIGNMENT, cmd.args.subImage.rowStartAlign);
3956 if (cmd.args.subImage.rowLength != 0)
3959 f->glTexSubImage3D(cmd.args.subImage.target, cmd.args.subImage.level,
3960 cmd.args.subImage.dx, cmd.args.subImage.dy, cmd.args.subImage.dz,
3961 cmd.args.subImage.w, cmd.args.subImage.h, 1,
3962 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
3963 cmd.args.subImage.data);
3966 cmd.args.subImage.dx
, cmd.args.subImage.w
,
3967 cmd.args.subImage.glformat
, cmd.args.subImage.gltype
,
3968 cmd.args.subImage.data
);
3970 f->glTexSubImage2D(cmd.args.subImage.faceTarget, cmd.args.subImage.level,
3971 cmd.args.subImage.dx, cmd.args.subImage.dy,
3972 cmd.args.subImage.w, cmd.args.subImage.h,
3973 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
3974 cmd.args.subImage.data);
3976 if (cmd.args.subImage.rowStartAlign != 4)
3977 f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
3978 if (cmd.args.subImage.rowLength != 0)
3982 f->glBindTexture(cmd.args.compressedImage.target, cmd.args.compressedImage.texture);
3984 f->glCompressedTexImage3D(cmd.args.compressedImage.target, cmd.args.compressedImage.level,
3985 cmd.args.compressedImage.glintformat,
3986 cmd.args.compressedImage.w, cmd.args.compressedImage.h, cmd.args.compressedImage.depth,
3987 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
3988 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
3990 cmd.args.compressedImage.target
, cmd.args.compressedImage.level
,
3991 cmd.args.compressedImage.glintformat
, cmd.args.compressedImage.w
, 0
,
3992 cmd.args.compressedImage.size
, cmd.args.compressedImage.data
);
3994 f->glCompressedTexImage2D(cmd.args.compressedImage.faceTarget, cmd.args.compressedImage.level,
3995 cmd.args.compressedImage.glintformat,
3996 cmd.args.compressedImage.w, cmd.args.compressedImage.h,
3997 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
4001 f->glBindTexture(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.texture);
4003 f->glCompressedTexSubImage3D(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.level,
4004 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy, cmd.args.compressedSubImage.dz,
4005 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h, 1,
4006 cmd.args.compressedSubImage.glintformat,
4007 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
4008 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
4010 cmd.args.compressedSubImage.target
, cmd.args.compressedSubImage.level
,
4011 cmd.args.compressedSubImage.dx
, cmd.args.compressedSubImage.w
,
4012 cmd.args.compressedSubImage.glintformat
, cmd.args.compressedSubImage.size
,
4013 cmd.args.compressedSubImage.data
);
4015 f->glCompressedTexSubImage2D(cmd.args.compressedSubImage.faceTarget, cmd.args.compressedSubImage.level,
4016 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy,
4017 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h,
4018 cmd.args.compressedSubImage.glintformat,
4019 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
4026 cbD->graphicsPassState.reset();
4027 f->glDisable(GL_SCISSOR_TEST);
4029 f->glGenFramebuffers(2, fbo);
4031 const bool ds = cmd.args.blitFromRenderbuffer.isDepthStencil;
4034 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4036 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4039 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4045 cmd.args.blitFromRenderbuffer.dstTexture,
4046 cmd.args.blitFromRenderbuffer.dstLevel,
4047 cmd.args.blitFromRenderbuffer.dstLayer);
4049 cmd.args.blitFromRenderbuffer.dstTexture,
4050 cmd.args.blitFromRenderbuffer.dstLevel,
4051 cmd.args.blitFromRenderbuffer.dstLayer);
4054 cmd.args.blitFromRenderbuffer.dstTexture,
4055 cmd.args.blitFromRenderbuffer.dstLevel,
4056 cmd.args.blitFromRenderbuffer.dstLayer);
4060 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
4061 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4062 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
4063 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4065 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromRenderbuffer.target,
4066 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4069 f->glBlitFramebuffer(0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
4070 0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
4071 ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT,
4073 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4074 f->glDeleteFramebuffers(2, fbo);
4081 cbD->graphicsPassState.reset();
4082 f->glDisable(GL_SCISSOR_TEST);
4084 f->glGenFramebuffers(2, fbo);
4086 const bool ds = cmd.args.blitFromTexture.isDepthStencil;
4090 cmd.args.blitFromTexture.srcTexture,
4091 cmd.args.blitFromTexture.srcLevel,
4092 cmd.args.blitFromTexture.srcLayer);
4094 cmd.args.blitFromTexture.srcTexture,
4095 cmd.args.blitFromTexture.srcLevel,
4096 cmd.args.blitFromTexture.srcLayer);
4099 cmd.args.blitFromTexture.srcTexture,
4100 cmd.args.blitFromTexture.srcLevel,
4101 cmd.args.blitFromTexture.srcLayer);
4105 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
4106 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4107 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
4108 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4110 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.srcTarget,
4111 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4118 cmd.args.blitFromTexture.dstTexture,
4119 cmd.args.blitFromTexture.dstLevel,
4120 cmd.args.blitFromTexture.dstLayer);
4122 cmd.args.blitFromTexture.dstTexture,
4123 cmd.args.blitFromTexture.dstLevel,
4124 cmd.args.blitFromTexture.dstLayer);
4127 cmd.args.blitFromTexture.dstTexture,
4128 cmd.args.blitFromTexture.dstLevel,
4129 cmd.args.blitFromTexture.dstLayer);
4133 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
4134 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4135 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
4136 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4138 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.dstTarget,
4139 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4142 f->glBlitFramebuffer(0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
4143 0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
4144 ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT,
4146 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4147 f->glDeleteFramebuffers(2, fbo);
4151 f->glBindTexture(cmd.args.genMip.target, cmd.args.genMip.texture);
4152 f->glGenerateMipmap(cmd.args.genMip.target);
4157 f->glUseProgram(psD->program);
4161 f->glDispatchCompute(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
4167 GLbitfield barriers = 0;
4176 for (
const auto &[rhiB, trackedB]: tracker.buffers()) {
4178 QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(trackedB.stateAtPassBegin.access);
4179 if (bufferAccessIsWrite(accessBeforePass))
4180 barriers |= barriersForBuffer();
4182 for (
const auto &[rhiT, trackedT]: tracker.textures()) {
4184 QGles2Texture::Access accessBeforePass = QGles2Texture::Access(trackedT.stateAtPassBegin.access);
4185 if (textureAccessIsWrite(accessBeforePass))
4186 barriers |= barriersForTexture();
4189 f->glMemoryBarrier(barriers);
4194 f->glMemoryBarrier(cmd.args.barrier.barriers);
4197 if (caps.gles && caps.ctxMajor >= 3) {
4198 f->glBindFramebuffer(GL_FRAMEBUFFER, cmd.args.invalidateFramebuffer.fbo);
4200 cmd.args.invalidateFramebuffer.attCount,
4201 cmd.args.invalidateFramebuffer.att);
4211 f->glVertexAttribDivisor(GLuint(i), 0);
4214 f->glVertexAttribDivisor(GLuint(i), 0);
4221 const bool forceUpdate = !state
.valid;
4224 const bool scissor = psD->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor);
4225 if (forceUpdate || scissor != state
.scissor) {
4228 f->glEnable(GL_SCISSOR_TEST);
4230 f->glDisable(GL_SCISSOR_TEST);
4233 const bool cullFace = psD->m_cullMode != QRhiGraphicsPipeline::None;
4234 const GLenum cullMode = cullFace ? toGlCullMode(psD->m_cullMode) : GL_NONE;
4235 if (forceUpdate || cullFace != state
.cullFace || cullMode != state.cullMode) {
4237 state.cullMode = cullMode;
4239 f->glEnable(GL_CULL_FACE);
4240 f->glCullFace(cullMode);
4242 f->glDisable(GL_CULL_FACE);
4246 const GLenum frontFace = toGlFrontFace(psD->m_frontFace);
4247 if (forceUpdate || frontFace != state.frontFace) {
4248 state.frontFace = frontFace;
4249 f->glFrontFace(frontFace);
4252 const GLenum polygonMode = toGlPolygonMode(psD->m_polygonMode);
4253 if (
glPolygonMode && (forceUpdate || polygonMode != state.polygonMode)) {
4254 state.polygonMode = polygonMode;
4258 if (!psD->m_targetBlends.isEmpty()) {
4260 bool anyBlendEnabled =
false;
4261 for (
const auto targetBlend : psD->m_targetBlends) {
4262 const QGles2CommandBuffer::GraphicsPassState::ColorMask colorMask = {
4263 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::R),
4264 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::G),
4265 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::B),
4266 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::A)
4268 if (forceUpdate || colorMask != state.colorMask[buffer]) {
4269 state.colorMask[buffer] = colorMask;
4270 if (caps.perRenderTargetBlending)
4271 f->glColorMaski(buffer, colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4273 f->glColorMask(colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4276 const bool blendEnabled = targetBlend.enable;
4277 const QGles2CommandBuffer::GraphicsPassState::Blend blend = {
4278 toGlBlendFactor(targetBlend.srcColor),
4279 toGlBlendFactor(targetBlend.dstColor),
4280 toGlBlendFactor(targetBlend.srcAlpha),
4281 toGlBlendFactor(targetBlend.dstAlpha),
4282 toGlBlendOp(targetBlend.opColor),
4283 toGlBlendOp(targetBlend.opAlpha)
4285 anyBlendEnabled |= blendEnabled;
4286 if (forceUpdate || blendEnabled != state.blendEnabled[buffer] || (blendEnabled && blend != state.blend[buffer])) {
4287 state.blendEnabled[buffer] = blendEnabled;
4289 state.blend[buffer] = blend;
4290 if (caps.perRenderTargetBlending) {
4291 f->glBlendFuncSeparatei(buffer, blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4292 f->glBlendEquationSeparatei(buffer, blend.opColor, blend.opAlpha);
4294 f->glBlendFuncSeparate(blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4295 f->glBlendEquationSeparate(blend.opColor, blend.opAlpha);
4300 if (!caps.perRenderTargetBlending)
4303 if (anyBlendEnabled)
4304 f->glEnable(GL_BLEND);
4306 f->glDisable(GL_BLEND);
4309 if (forceUpdate || colorMask
!= state.colorMask[0]) {
4310 state.colorMask[0] = colorMask;
4311 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4313 const bool blendEnabled =
false;
4316 f->glDisable(GL_BLEND);
4320 const bool depthTest = psD->m_depthTest;
4321 if (forceUpdate || depthTest != state
.depthTest) {
4324 f->glEnable(GL_DEPTH_TEST);
4326 f->glDisable(GL_DEPTH_TEST);
4329 const bool depthWrite = psD->m_depthWrite;
4330 if (forceUpdate || depthWrite != state
.depthWrite) {
4332 f->glDepthMask(depthWrite);
4335 const bool depthClamp = psD->m_depthClamp;
4336 if (caps.depthClamp && (forceUpdate || depthClamp != state.depthClamp)) {
4344 const GLenum depthFunc = toGlCompareOp(psD->m_depthOp);
4345 if (forceUpdate || depthFunc != state.depthFunc) {
4346 state.depthFunc = depthFunc;
4347 f->glDepthFunc(depthFunc);
4350 const bool stencilTest = psD->m_stencilTest;
4351 const GLuint stencilReadMask = psD->m_stencilReadMask;
4352 const GLuint stencilWriteMask = psD->m_stencilWriteMask;
4354 toGlCompareOp(psD->m_stencilFront.compareOp),
4355 toGlStencilOp(psD->m_stencilFront.failOp),
4356 toGlStencilOp(psD->m_stencilFront.depthFailOp),
4357 toGlStencilOp(psD->m_stencilFront.passOp)
4360 toGlCompareOp(psD->m_stencilBack.compareOp),
4361 toGlStencilOp(psD->m_stencilBack.failOp),
4362 toGlStencilOp(psD->m_stencilBack.depthFailOp),
4363 toGlStencilOp(psD->m_stencilBack.passOp)
4367 && (stencilReadMask != state.stencilReadMask || stencilWriteMask != state.stencilWriteMask
4368 || stencilFront != state.stencil[0] || stencilBack != state.stencil[1])))
4372 state.stencilReadMask = stencilReadMask;
4373 state.stencilWriteMask = stencilWriteMask;
4374 state.stencil[0] = stencilFront;
4375 state.stencil[1] = stencilBack;
4377 f->glEnable(GL_STENCIL_TEST);
4379 f->glStencilFuncSeparate(GL_FRONT, stencilFront.func, state.dynamic.stencilRef, stencilReadMask);
4380 f->glStencilOpSeparate(GL_FRONT, stencilFront.failOp, stencilFront.zfailOp, stencilFront.zpassOp);
4381 f->glStencilMaskSeparate(GL_FRONT, stencilWriteMask);
4383 f->glStencilFuncSeparate(GL_BACK, stencilBack.func, state.dynamic.stencilRef, stencilReadMask);
4384 f->glStencilOpSeparate(GL_BACK, stencilBack.failOp, stencilBack.zfailOp, stencilBack.zpassOp);
4385 f->glStencilMaskSeparate(GL_BACK, stencilWriteMask);
4387 f->glDisable(GL_STENCIL_TEST);
4391 const bool polyOffsetFill = psD->m_depthBias != 0 || !qFuzzyIsNull(psD->m_slopeScaledDepthBias);
4392 const float polyOffsetFactor = psD->m_slopeScaledDepthBias;
4393 const float polyOffsetUnits = psD->m_depthBias;
4400 if (polyOffsetFill) {
4401 f->glPolygonOffset(polyOffsetFactor, polyOffsetUnits);
4402 f->glEnable(GL_POLYGON_OFFSET_FILL);
4404 f->glDisable(GL_POLYGON_OFFSET_FILL);
4408 if (psD->m_topology == QRhiGraphicsPipeline::Lines || psD->m_topology == QRhiGraphicsPipeline::LineStrip) {
4409 const float lineWidth = psD->m_lineWidth;
4410 if (forceUpdate || lineWidth != state
.lineWidth) {
4412 f->glLineWidth(lineWidth);
4416 if (psD->m_topology == QRhiGraphicsPipeline::Patches) {
4417 const int cpCount = psD->m_patchControlPointCount;
4418 if (forceUpdate || cpCount != state
.cpCount) {
4424 f->glUseProgram(psD->program);
4544 QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs,
4545 QRhiShaderResourceBindings *srb,
4546 const uint *dynOfsPairs,
int dynOfsCount)
4550 bool activeTexUnitAltered =
false;
4555 m_scratch.separateTextureBindings.clear();
4556 m_scratch.separateSamplerBindings.clear();
4558 for (
int i = 0, ie = srbD->m_bindings.size(); i != ie; ++i) {
4559 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->m_bindings.at(i));
4562 case QRhiShaderResourceBinding::UniformBuffer:
4564 int viewOffset = b->u.ubuf.offset;
4565 for (
int j = 0; j < dynOfsCount; ++j) {
4566 if (dynOfsPairs[2 * j] == uint(b->binding)) {
4567 viewOffset =
int(dynOfsPairs[2 * j + 1]);
4572 const char *bufView = bufD->data.constData() + viewOffset;
4573 for (
const QGles2UniformDescription &uniform : std::as_const(uniforms)) {
4574 if (uniform.binding == b->binding) {
4575 const qint64 readOffset = qint64(viewOffset) + uniform.offset;
4576 const qint64 readSize = qrhi_std140_read_size(uniform.type, uniform.arrayDim);
4577 if (readOffset < 0 || readOffset + readSize > bufD->data.size()) {
4578 qWarning(
"Uniform with buffer binding %d, buffer offset %u, type %d, array "
4579 "dimension %d would read outside of the uniform buffer of size %lld. "
4581 uniform.binding, uniform.offset, uniform.type, uniform.arrayDim,
4582 qint64(bufD->data.size()));
4588 const void *src = bufView + uniform.offset;
4591 if (uniform.arrayDim > 0
4592 && uniform.type != QShaderDescription::Float
4593 && uniform.type != QShaderDescription::Vec2
4594 && uniform.type != QShaderDescription::Vec3
4595 && uniform.type != QShaderDescription::Vec4
4596 && uniform.type != QShaderDescription::Int
4597 && uniform.type != QShaderDescription::Int2
4598 && uniform.type != QShaderDescription::Int3
4599 && uniform.type != QShaderDescription::Int4
4600 && uniform.type != QShaderDescription::Mat3
4601 && uniform.type != QShaderDescription::Mat4)
4603 qWarning(
"Uniform with buffer binding %d, buffer offset %d, type %d is an array, "
4604 "but arrays are only supported for float, vec2, vec3, vec4, int, "
4605 "ivec2, ivec3, ivec4, mat3 and mat4. "
4606 "Only the first element will be set.",
4607 uniform.binding, uniform.offset, uniform.type);
4617 switch (uniform.type) {
4618 case QShaderDescription::Float:
4620 const int elemCount = uniform.arrayDim;
4621 if (elemCount < 1) {
4622 const float v = *
reinterpret_cast<
const float *>(src);
4623 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4624 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4625 if (thisUniformState.componentCount != 1 || thisUniformState.v[0] != v) {
4626 thisUniformState.componentCount = 1;
4627 thisUniformState.v[0] = v;
4628 f->glUniform1f(uniform.glslLocation, v);
4631 f->glUniform1f(uniform.glslLocation, v);
4635 m_scratch.packedArray.resize(elemCount);
4636 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 1, elemCount, src);
4637 f->glUniform1fv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->f);
4641 case QShaderDescription::Vec2:
4643 const int elemCount = uniform.arrayDim;
4644 if (elemCount < 1) {
4645 const float *v =
reinterpret_cast<
const float *>(src);
4646 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4647 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4648 if (thisUniformState.componentCount != 2
4649 || thisUniformState.v[0] != v[0]
4650 || thisUniformState.v[1] != v[1])
4652 thisUniformState.componentCount = 2;
4653 thisUniformState.v[0] = v[0];
4654 thisUniformState.v[1] = v[1];
4655 f->glUniform2fv(uniform.glslLocation, 1, v);
4658 f->glUniform2fv(uniform.glslLocation, 1, v);
4661 m_scratch.packedArray.resize(elemCount * 2);
4662 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 2, elemCount, src);
4663 f->glUniform2fv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->f);
4667 case QShaderDescription::Vec3:
4669 const int elemCount = uniform.arrayDim;
4670 if (elemCount < 1) {
4671 const float *v =
reinterpret_cast<
const float *>(src);
4672 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4673 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4674 if (thisUniformState.componentCount != 3
4675 || thisUniformState.v[0] != v[0]
4676 || thisUniformState.v[1] != v[1]
4677 || thisUniformState.v[2] != v[2])
4679 thisUniformState.componentCount = 3;
4680 thisUniformState.v[0] = v[0];
4681 thisUniformState.v[1] = v[1];
4682 thisUniformState.v[2] = v[2];
4683 f->glUniform3fv(uniform.glslLocation, 1, v);
4686 f->glUniform3fv(uniform.glslLocation, 1, v);
4689 m_scratch.packedArray.resize(elemCount * 3);
4690 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 3, elemCount, src);
4691 f->glUniform3fv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->f);
4695 case QShaderDescription::Vec4:
4697 const int elemCount = uniform.arrayDim;
4698 if (elemCount < 1) {
4699 const float *v =
reinterpret_cast<
const float *>(src);
4700 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4701 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4702 if (thisUniformState.componentCount != 4
4703 || thisUniformState.v[0] != v[0]
4704 || thisUniformState.v[1] != v[1]
4705 || thisUniformState.v[2] != v[2]
4706 || thisUniformState.v[3] != v[3])
4708 thisUniformState.componentCount = 4;
4709 thisUniformState.v[0] = v[0];
4710 thisUniformState.v[1] = v[1];
4711 thisUniformState.v[2] = v[2];
4712 thisUniformState.v[3] = v[3];
4713 f->glUniform4fv(uniform.glslLocation, 1, v);
4716 f->glUniform4fv(uniform.glslLocation, 1, v);
4719 f->glUniform4fv(uniform.glslLocation, elemCount,
reinterpret_cast<
const float *>(src));
4723 case QShaderDescription::Mat2:
4724 f->glUniformMatrix2fv(uniform.glslLocation, 1, GL_FALSE,
reinterpret_cast<
const float *>(src));
4726 case QShaderDescription::Mat3:
4728 const int elemCount = uniform.arrayDim;
4729 if (elemCount < 1) {
4732 const float *srcMat =
reinterpret_cast<
const float *>(src);
4733 memcpy(mat, srcMat, 3 *
sizeof(
float));
4734 memcpy(mat + 3, srcMat + 4, 3 *
sizeof(
float));
4735 memcpy(mat + 6, srcMat + 8, 3 *
sizeof(
float));
4736 f->glUniformMatrix3fv(uniform.glslLocation, 1, GL_FALSE, mat);
4738 m_scratch.packedArray.resize(elemCount * 9);
4739 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 3, elemCount * 3, src);
4740 f->glUniformMatrix3fv(uniform.glslLocation, elemCount, GL_FALSE, &m_scratch.packedArray.constData()->f);
4744 case QShaderDescription::Mat4:
4745 f->glUniformMatrix4fv(uniform.glslLocation, qMax(1, uniform.arrayDim), GL_FALSE,
reinterpret_cast<
const float *>(src));
4747 case QShaderDescription::Int:
4749 const int elemCount = uniform.arrayDim;
4750 if (elemCount < 1) {
4751 f->glUniform1i(uniform.glslLocation, *
reinterpret_cast<
const qint32 *>(src));
4753 m_scratch.packedArray.resize(elemCount);
4754 qrhi_std140_to_packed(&m_scratch.packedArray.data()->i, 1, elemCount, src);
4755 f->glUniform1iv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->i);
4759 case QShaderDescription::Int2:
4761 const int elemCount = uniform.arrayDim;
4762 if (elemCount < 1) {
4763 f->glUniform2iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4765 m_scratch.packedArray.resize(elemCount * 2);
4766 qrhi_std140_to_packed(&m_scratch.packedArray.data()->i, 2, elemCount, src);
4767 f->glUniform2iv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->i);
4771 case QShaderDescription::Int3:
4773 const int elemCount = uniform.arrayDim;
4774 if (elemCount < 1) {
4775 f->glUniform3iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4777 m_scratch.packedArray.resize(elemCount * 3);
4778 qrhi_std140_to_packed(&m_scratch.packedArray.data()->i, 3, elemCount, src);
4779 f->glUniform3iv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->i);
4783 case QShaderDescription::Int4:
4784 f->glUniform4iv(uniform.glslLocation, qMax(1, uniform.arrayDim),
reinterpret_cast<
const qint32 *>(src));
4786 case QShaderDescription::Uint:
4787 f->glUniform1ui(uniform.glslLocation, *
reinterpret_cast<
const quint32 *>(src));
4789 case QShaderDescription::Uint2:
4790 f->glUniform2uiv(uniform.glslLocation, 1,
reinterpret_cast<
const quint32 *>(src));
4792 case QShaderDescription::Uint3:
4793 f->glUniform3uiv(uniform.glslLocation, 1,
reinterpret_cast<
const quint32 *>(src));
4795 case QShaderDescription::Uint4:
4796 f->glUniform4uiv(uniform.glslLocation, 1,
reinterpret_cast<
const quint32 *>(src));
4798 case QShaderDescription::Bool:
4799 f->glUniform1i(uniform.glslLocation, *
reinterpret_cast<
const qint32 *>(src));
4801 case QShaderDescription::Bool2:
4802 f->glUniform2iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4804 case QShaderDescription::Bool3:
4805 f->glUniform3iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4807 case QShaderDescription::Bool4:
4808 f->glUniform4iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4811 qWarning(
"Uniform with buffer binding %d, buffer offset %d has unsupported type %d",
4812 uniform.binding, uniform.offset, uniform.type);
4819 case QRhiShaderResourceBinding::SampledTexture:
4825 if (maybeGraphicsPs) {
4826 ps = maybeGraphicsPs;
4829 ps = maybeComputePs;
4832 for (
int elem = 0; elem < b->u.stex.count; ++elem) {
4835 for (
const QGles2SamplerDescription &shaderSampler : samplers) {
4836 if (shaderSampler.combinedBinding == b->binding) {
4837 const int loc = shaderSampler.glslLocation + elem;
4838 bindCombinedSampler(cbD, texD, samplerD, ps, psGeneration, loc, &texUnit, &activeTexUnitAltered);
4845 case QRhiShaderResourceBinding::Texture:
4846 for (
int elem = 0; elem < b->u.stex.count; ++elem) {
4848 m_scratch.separateTextureBindings.append({ texD, b->binding, elem });
4851 case QRhiShaderResourceBinding::Sampler:
4854 m_scratch.separateSamplerBindings.append({ samplerD, b->binding });
4857 case QRhiShaderResourceBinding::ImageLoad:
4858 case QRhiShaderResourceBinding::ImageStore:
4859 case QRhiShaderResourceBinding::ImageLoadStore:
4862 Q_ASSERT(texD->m_flags.testFlag(QRhiTexture::UsedWithLoadStore));
4864 const bool layered = texD->m_flags.testFlag(QRhiTexture::CubeMap)
4865 || texD->m_flags.testFlag(QRhiTexture::ThreeDimensional)
4866 || texD->m_flags.testFlag(QRhiTexture::TextureArray);
4868 if (b->type == QRhiShaderResourceBinding::ImageLoad)
4870 else if (b->type == QRhiShaderResourceBinding::ImageStore)
4872 f->glBindImageTexture(GLuint(b->binding), texD->texture,
4873 b->u.simage.level, layered, 0,
4874 access, texD->glsizedintformat);
4877 case QRhiShaderResourceBinding::BufferLoad:
4878 case QRhiShaderResourceBinding::BufferStore:
4879 case QRhiShaderResourceBinding::BufferLoadStore:
4882 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer));
4883 if (b->u.sbuf.offset == 0 && b->u.sbuf.maybeSize == 0)
4887 b->u.sbuf.offset, b->u.sbuf.maybeSize ? b->u.sbuf.maybeSize : bufD->m_size);
4896 if (!m_scratch.separateTextureBindings.isEmpty() || !m_scratch.separateSamplerBindings.isEmpty()) {
4901 if (maybeGraphicsPs) {
4902 ps = maybeGraphicsPs;
4905 ps = maybeComputePs;
4908 for (
const QGles2SamplerDescription &shaderSampler : samplers) {
4909 if (shaderSampler.combinedBinding >= 0)
4911 for (
const Scratch::SeparateSampler &sepSampler : std::as_const(m_scratch.separateSamplerBindings)) {
4912 if (sepSampler.binding != shaderSampler.sbinding)
4914 for (
const Scratch::SeparateTexture &sepTex : std::as_const(m_scratch.separateTextureBindings)) {
4915 if (sepTex.binding != shaderSampler.tbinding)
4917 const int loc = shaderSampler.glslLocation + sepTex.elem;
4918 bindCombinedSampler(cbD, sepTex.texture, sepSampler.sampler, ps, psGeneration,
4919 loc, &texUnit, &activeTexUnitAltered);
4925 if (activeTexUnitAltered)
6488bool QGles2TextureRenderTarget::create()
6495 const bool hasColorAttachments = m_desc.colorAttachmentCount() > 0;
6496 Q_ASSERT(hasColorAttachments || m_desc.depthTexture());
6497 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
6498 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
6500 if (hasColorAttachments) {
6501 const int count =
int(m_desc.colorAttachmentCount());
6502 if (count > rhiD->caps.maxDrawBuffers) {
6503 qWarning(
"QGles2TextureRenderTarget: Too many color attachments (%d, max is %d)",
6504 count, rhiD->caps.maxDrawBuffers);
6507 if (m_desc.depthTexture() && !rhiD->caps.depthTexture)
6508 qWarning(
"QGles2TextureRenderTarget: Depth texture is not supported and will be ignored");
6510 if (!rhiD->ensureContext())
6513 rhiD->f->glGenFramebuffers(1, &framebuffer);
6514 rhiD->f->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6516 d.colorAttCount = 0;
6518 int multiViewCount = 0;
6519 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
6520 d.colorAttCount += 1;
6521 const QRhiColorAttachment &colorAtt(*it);
6522 QRhiTexture *texture = colorAtt.texture();
6523 QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer();
6524 Q_ASSERT(texture || renderBuffer);
6526 QGles2Texture *texD =
QRHI_RES(QGles2Texture, texture);
6527 Q_ASSERT(texD->texture && texD->specified);
6528 if (texD->flags().testFlag(QRhiTexture::ThreeDimensional) || texD->flags().testFlag(QRhiTexture::TextureArray)) {
6529 if (colorAtt.multiViewCount() < 2) {
6530 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture,
6531 colorAtt.level(), colorAtt.layer());
6533 multiViewCount = colorAtt.multiViewCount();
6534 if (texD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture && colorAtt.resolveTexture()) {
6539 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
6540 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6541 GL_COLOR_ATTACHMENT0 + uint(attIndex),
6542 resolveTexD->texture,
6543 colorAtt.resolveLevel(),
6545 colorAtt.resolveLayer(),
6548 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER,
6549 GL_COLOR_ATTACHMENT0 + uint(attIndex),
6556 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
6557 rhiD->glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex),
6558 texD->target + uint(colorAtt.layer()), texD->texture,
6561 if (texD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
6566 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
6568 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
6569 resolveTexD->texture, colorAtt.level(), texD->samples);
6572 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.layer()),
6573 texD->texture, colorAtt.level());
6576 if (attIndex == 0) {
6577 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
6578 d.sampleCount = texD->samples;
6580 }
else if (renderBuffer) {
6581 QGles2RenderBuffer *rbD =
QRHI_RES(QGles2RenderBuffer, renderBuffer);
6582 if (rbD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
6587 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
6589 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
6590 resolveTexD->texture, colorAtt.level(), rbD->samples);
6592 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), GL_RENDERBUFFER, rbD->renderbuffer);
6594 if (attIndex == 0) {
6595 d.pixelSize = rbD->pixelSize();
6596 d.sampleCount = rbD->samples;
6601 if (hasDepthStencil) {
6602 if (m_desc.depthStencilBuffer()) {
6603 QGles2RenderBuffer *depthRbD =
QRHI_RES(QGles2RenderBuffer, m_desc.depthStencilBuffer());
6604 if (rhiD->caps.needsDepthStencilCombinedAttach) {
6606 depthRbD->renderbuffer);
6608 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
6609 depthRbD->renderbuffer);
6610 if (depthRbD->stencilRenderbuffer) {
6611 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
6612 depthRbD->stencilRenderbuffer);
6615 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
6616 depthRbD->renderbuffer);
6619 if (d.colorAttCount == 0) {
6620 d.pixelSize = depthRbD->pixelSize();
6621 d.sampleCount = depthRbD->samples;
6624 QGles2Texture *depthTexD =
QRHI_RES(QGles2Texture, m_desc.depthTexture());
6625 if (multiViewCount < 2) {
6626 if (depthTexD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && m_desc.depthResolveTexture()) {
6630 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
6631 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthResolveTexD->target,
6632 depthResolveTexD->texture, 0, depthTexD->samples);
6633 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
6634 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthResolveTexD->target,
6635 depthResolveTexD->texture, 0, depthTexD->samples);
6637 }
else if (rhiD->caps.ctxMajor >= 3 && depthTexD->flags().testFlag(QRhiTexture::TextureArray) && m_desc.depthLayer() >= 0) {
6638 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
6639 0, m_desc.depthLayer());
6640 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
6641 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
6642 0, m_desc.depthLayer());
6645 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->target,
6646 depthTexD->texture, 0);
6647 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
6648 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->target,
6649 depthTexD->texture, 0);
6653 if (depthTexD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture) {
6671 if (!m_flags.testFlag(DoNotStoreDepthStencilContents) && !m_desc.depthResolveTexture()) {
6672 qWarning(
"Attempted to create a multiview+multisample QRhiTextureRenderTarget, but DoNotStoreDepthStencilContents was not set."
6673 " This path has no choice but to behave as if DoNotStoreDepthStencilContents was set, because QRhi is forced to create"
6674 " a throwaway non-multisample depth texture here. Set the flag to silence this warning, or set a depthResolveTexture.");
6676 if (m_desc.depthResolveTexture()) {
6677 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
6678 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6679 GL_DEPTH_ATTACHMENT,
6680 depthResolveTexD->texture,
6685 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
6686 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6687 GL_STENCIL_ATTACHMENT,
6688 depthResolveTexD->texture,
6695 if (!nonMsaaThrowawayDepthTexture) {
6696 rhiD->f->glGenTextures(1, &nonMsaaThrowawayDepthTexture);
6699 depthTexD->pixelSize().width(), depthTexD->pixelSize().height(), multiViewCount);
6701 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6702 GL_DEPTH_ATTACHMENT,
6703 nonMsaaThrowawayDepthTexture,
6708 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6709 GL_STENCIL_ATTACHMENT,
6710 nonMsaaThrowawayDepthTexture,
6720 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
6721 0, 0, multiViewCount);
6722 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
6723 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
6724 0, 0, multiViewCount);
6728 if (d.colorAttCount == 0) {
6729 d.pixelSize = depthTexD->pixelSize();
6730 d.sampleCount = depthTexD->samples;
6739 d.rp =
QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
6741 GLenum status = rhiD->f->glCheckFramebufferStatus(GL_FRAMEBUFFER);
6742 if (status != GL_NO_ERROR && status != GL_FRAMEBUFFER_COMPLETE) {
6743 qWarning(
"Framebuffer incomplete: 0x%x", status);
6747 if (rhiD->glObjectLabel)
6748 rhiD->glObjectLabel(GL_FRAMEBUFFER, framebuffer, -1, m_objectName.constData());
6750 QRhiRenderTargetAttachmentTracker::updateResIdList<QGles2Texture, QGles2RenderBuffer>(m_desc, &d.currentResIdList);
6752 rhiD->registerResource(
this);