780 Q_ASSERT(fallbackSurface);
784 ctx =
new QOpenGLContext;
785 ctx->setFormat(requestedFormat);
786 if (maybeShareContext) {
787 ctx->setShareContext(maybeShareContext);
789 ctx->setScreen(maybeWindow->screen());
791 ctx->setScreen(maybeShareContext->screen());
792 }
else if (QOpenGLContext *shareContext = QOpenGLContext::globalShareContext()) {
793 ctx->setShareContext(shareContext);
795 ctx->setScreen(maybeWindow->screen());
797 ctx->setScreen(shareContext->screen());
798 }
else if (maybeWindow) {
799 ctx->setScreen(maybeWindow->screen());
801 if (!ctx->create()) {
802 qWarning(
"QRhiGles2: Failed to create context");
807 qCDebug(QRHI_LOG_INFO) <<
"Created OpenGL context" << ctx->format();
810 if (!ensureContext(maybeWindow ? maybeWindow : fallbackSurface))
813 f =
static_cast<QOpenGLExtensions *>(ctx->extraFunctions());
814 const QSurfaceFormat actualFormat = ctx->format();
815 caps.gles = actualFormat.renderableType() == QSurfaceFormat::OpenGLES;
819 ctx->getProcAddress(QByteArrayLiteral(
"glPolygonMode")));
822 GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum,
const void *)>(
823 ctx->getProcAddress(QByteArrayLiteral(
"glTexImage1D")));
825 glTexStorage1D =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei)>(
826 ctx->getProcAddress(QByteArrayLiteral(
"glTexStorage1D")));
829 GLenum, GLint, GLint, GLsizei, GLenum, GLenum,
const GLvoid *)>(
830 ctx->getProcAddress(QByteArrayLiteral(
"glTexSubImage1D")));
832 glCopyTexSubImage1D =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint,
834 ctx->getProcAddress(QByteArrayLiteral(
"glCopyTexSubImage1D")));
837 GLenum, GLint, GLenum, GLsizei, GLint, GLsizei,
const GLvoid *)>(
838 ctx->getProcAddress(QByteArrayLiteral(
"glCompressedTexImage1D")));
841 GLenum, GLint, GLint, GLsizei, GLenum, GLsizei,
const GLvoid *)>(
842 ctx->getProcAddress(QByteArrayLiteral(
"glCompressedTexSubImage1D")));
844 glFramebufferTexture1D =
846 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture1D")));
849 const char *vendor =
reinterpret_cast<
const char *>(
f->glGetString(GL_VENDOR));
850 const char *renderer =
reinterpret_cast<
const char *>(
f->glGetString(GL_RENDERER));
851 const char *version =
reinterpret_cast<
const char *>(
f->glGetString(GL_VERSION));
852 if (vendor && renderer && version)
853 qCDebug(QRHI_LOG_INFO,
"OpenGL VENDOR: %s RENDERER: %s VERSION: %s", vendor, renderer, version);
856 driverInfoStruct.deviceName += QByteArray(vendor);
857 driverInfoStruct.deviceName +=
' ';
860 driverInfoStruct.deviceName += QByteArray(renderer);
861 driverInfoStruct.deviceName +=
' ';
864 driverInfoStruct.deviceName += QByteArray(version);
866 caps.ctxMajor = actualFormat.majorVersion();
867 caps.ctxMinor = actualFormat.minorVersion();
872 QVarLengthArray<GLint, 16> compressedTextureFormats(n);
874 for (GLint format : compressedTextureFormats)
875 supportedCompressedFormats.insert(format);
888 std::array<QRhiTexture::Flags, 2> textureVariantFlags;
889 textureVariantFlags[0] = {};
890 textureVariantFlags[1] = QRhiTexture::sRGB;
891 if (
f->hasOpenGLExtension(QOpenGLExtensions::DDSTextureCompression)) {
892 for (QRhiTexture::Flags f : textureVariantFlags) {
893 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC1, f));
894 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC2, f));
895 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC3, f));
898 if (
f->hasOpenGLExtension(QOpenGLExtensions::ETC2TextureCompression)) {
899 for (QRhiTexture::Flags f : textureVariantFlags) {
900 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8, f));
901 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8A1, f));
902 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGBA8, f));
905 if (
f->hasOpenGLExtension(QOpenGLExtensions::ASTCTextureCompression)) {
906 for (QRhiTexture::Flags f : textureVariantFlags) {
907 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_4x4, f));
908 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x4, f));
909 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x5, f));
910 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x5, f));
911 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x6, f));
912 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x5, f));
913 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x6, f));
914 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x8, f));
915 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x5, f));
916 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x8, f));
917 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x10, f));
918 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x10, f));
919 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x12, f));
923 f->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.maxTextureSize);
925 if (!caps.gles || caps.ctxMajor >= 3) {
928 caps.hasDrawBuffersFunc =
true;
930 caps.maxSamples = qMax(1, caps.maxSamples);
933 caps.maxDrawBuffers = 1;
934 caps.hasDrawBuffersFunc =
false;
940 caps.msaaRenderBuffer = f->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
941 && f->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
943 caps.npotTextureFull = f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)
944 && f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
947 caps.fixedIndexPrimitiveRestart = caps.ctxMajor >= 3;
949 caps.fixedIndexPrimitiveRestart = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
951 if (caps.fixedIndexPrimitiveRestart) {
961 caps.bgraExternalFormat = f->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat);
962 caps.bgraInternalFormat = caps.bgraExternalFormat && caps.gles;
963 caps.r8Format = f->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats);
966 caps.r32uiFormat = (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1)) && caps.r8Format;
968 caps.r32uiFormat =
true;
971 caps.imageLoadStore = caps.r32uiFormat;
973 caps.imageLoadStore = (caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 2));
975 caps.r16Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats);
976 caps.floatFormats = caps.ctxMajor >= 3;
977 caps.rgb10Formats = caps.ctxMajor >= 3;
978 caps.depthTexture = caps.ctxMajor >= 3;
979 caps.packedDepthStencil = f->hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil);
981 caps.needsDepthStencilCombinedAttach =
true;
983 caps.needsDepthStencilCombinedAttach =
false;
990 caps.srgbWriteControl = ctx->hasExtension(
"GL_EXT_framebuffer_sRGB") || ctx->hasExtension(
"GL_EXT_sRGB_write_control");
992 caps.coreProfile = actualFormat.profile() == QSurfaceFormat::CoreProfile;
995 caps.uniformBuffers = caps.ctxMajor >= 3;
997 caps.uniformBuffers = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
999 caps.elementIndexUint = f->hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint);
1000 caps.depth24 = f->hasOpenGLExtension(QOpenGLExtensions::Depth24);
1001 caps.rgba8Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized8Formats);
1004 caps.instancing = caps.ctxMajor >= 3;
1006 caps.instancing = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 3);
1008 caps.baseVertex = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1011 caps.compute = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1013 caps.compute = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1021 caps.maxThreadGroupsPerDimension = qMin(tgPerDim[0], qMin(tgPerDim[1], tgPerDim[2]));
1028 caps.depthClamp =
false;
1030 caps.depthClamp = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1031 if (!caps.depthClamp)
1032 caps.depthClamp = ctx->hasExtension(
"GL_EXT_depth_clamp") || ctx->hasExtension(
"GL_ARB_depth_clamp");
1035 caps.textureCompareMode = caps.ctxMajor >= 3;
1037 caps.textureCompareMode =
true;
1041 caps.properMapBuffer = f->hasOpenGLExtension(QOpenGLExtensions::MapBufferRange);
1044 caps.nonBaseLevelFramebufferTexture = caps.ctxMajor >= 3;
1046 caps.nonBaseLevelFramebufferTexture =
true;
1048 caps.texelFetch = caps.ctxMajor >= 3;
1049 caps.intAttributes = caps.ctxMajor >= 3;
1050 caps.screenSpaceDerivatives = f->hasOpenGLExtension(QOpenGLExtensions::StandardDerivatives);
1053 caps.multisampledTexture = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1055 caps.multisampledTexture = caps.ctxMajor >= 3;
1060 caps.programBinary = caps.ctxMajor >= 3;
1062 caps.programBinary = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 1);
1064 if (caps.programBinary) {
1068 caps.programBinary =
false;
1071 caps.texture3D = caps.ctxMajor >= 3;
1074 caps.texture1D =
false;
1076 caps.texture1D = glTexImage1D && (caps.ctxMajor >= 2);
1079 caps.tessellation = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1081 caps.tessellation = caps.ctxMajor >= 4;
1084 caps.geometryShader = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1086 caps.geometryShader = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1088 if (caps.ctxMajor >= 3) {
1089 GLint maxArraySize = 0;
1091 caps.maxTextureArraySize = maxArraySize;
1093 caps.maxTextureArraySize = 0;
1100 GLint maxVertexUniformVectors = 0;
1102 GLint maxFragmentUniformVectors = 0;
1104 caps.maxUniformVectors = qMin(maxVertexUniformVectors, maxFragmentUniformVectors);
1106 GLint maxVertexUniformComponents = 0;
1108 GLint maxFragmentUniformComponents = 0;
1110 caps.maxUniformVectors = qMin(maxVertexUniformComponents, maxFragmentUniformComponents) / 4;
1113 f->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.maxVertexInputs);
1117 }
else if (caps.ctxMajor >= 3) {
1118 GLint components = 0;
1120 caps.maxVertexOutputs = components / 4;
1124 GLint components = 0;
1127 caps.maxVertexOutputs = components / 4;
1132 if (!caps.coreProfile)
1139 if (!caps.gles && (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2)))
1142 caps.halfAttributes = f->hasOpenGLExtension(QOpenGLExtensions::HalfFloatVertex);
1145 caps.multiView = f->hasOpenGLExtension(QOpenGLExtensions::MultiView)
1146 && f->hasOpenGLExtension(QOpenGLExtensions::MultiViewExtended);
1147 if (caps.multiView) {
1148 glFramebufferTextureMultiviewOVR =
1149 reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei)>(
1150 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultiviewOVR")));
1154 caps.timestamps = !caps.gles && (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 3));
1155 if (caps.timestamps) {
1157 ctx->getProcAddress(QByteArrayLiteral(
"glQueryCounter")));
1158 glGetQueryObjectui64v =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLuint, GLenum, quint64 *)>(
1159 ctx->getProcAddress(QByteArrayLiteral(
"glGetQueryObjectui64v")));
1160 if (!glQueryCounter || !glGetQueryObjectui64v)
1161 caps.timestamps =
false;
1166 caps.objectLabel = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1168 caps.objectLabel = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1169 if (caps.objectLabel) {
1170 glObjectLabel =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLuint, GLsizei,
const GLchar *)>(
1171 ctx->getProcAddress(QByteArrayLiteral(
"glObjectLabel")));
1181 caps.glesMultisampleRenderToTexture = ctx->hasExtension(
"GL_EXT_multisampled_render_to_texture");
1182 if (caps.glesMultisampleRenderToTexture) {
1183 glFramebufferTexture2DMultisampleEXT =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei)>(
1184 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture2DMultisampleEXT")));
1185 glRenderbufferStorageMultisampleEXT =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)>(
1186 ctx->getProcAddress(QByteArrayLiteral(
"glRenderbufferStorageMultisampleEXT")));
1188 caps.glesMultiviewMultisampleRenderToTexture = ctx->hasExtension(
"GL_OVR_multiview_multisampled_render_to_texture");
1189 if (caps.glesMultiviewMultisampleRenderToTexture) {
1190 glFramebufferTextureMultisampleMultiviewOVR =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei)>(
1191 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultisampleMultiviewOVR")));
1194 caps.glesMultisampleRenderToTexture =
false;
1195 caps.glesMultiviewMultisampleRenderToTexture =
false;
1198 caps.unpackRowLength = !caps.gles || caps.ctxMajor >= 3;
1201 caps.perRenderTargetBlending = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1203 caps.perRenderTargetBlending = caps.ctxMajor >= 4;
1206 if (caps.ctxMajor == 3 && caps.ctxMinor < 2) {
1207 caps.sampleVariables = ctx->hasExtension(
"GL_OES_sample_variables");
1209 caps.sampleVariables = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1212 caps.sampleVariables = caps.ctxMajor >= 4;
1216 caps.drawIndirect = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1218 caps.drawIndirect = caps.ctxMajor >= 4;
1219 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_draw_indirect")))
1220 caps.drawIndirect =
true;
1223 caps.drawIndirectMulti =
false;
1225 caps.drawIndirectMulti = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1226 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_multi_draw_indirect")) ||
1227 ctx->hasExtension(QByteArrayLiteral(
"GL_EXT_multi_draw_indirect")))
1228 caps.drawIndirectMulti =
true;
1230 if (caps.drawIndirectMulti) {
1231 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1232 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirect")));
1233 if (!glMultiDrawArraysIndirect)
1234 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1235 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectARB")));
1236 if (!glMultiDrawArraysIndirect)
1237 glMultiDrawArraysIndirect =
reinterpret_cast<
decltype(glMultiDrawArraysIndirect)>(
1238 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawArraysIndirectEXT")));
1239 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1240 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirect")));
1241 if (!glMultiDrawElementsIndirect)
1242 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1243 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectARB")));
1244 if (!glMultiDrawElementsIndirect)
1245 glMultiDrawElementsIndirect =
reinterpret_cast<
decltype(glMultiDrawElementsIndirect)>(
1246 ctx->getProcAddress(QByteArrayLiteral(
"glMultiDrawElementsIndirectEXT")));
1248 qWarning(
"Failed to resolve glMultiDrawArraysIndirect or glMultiDrawElementsIndirect.");
1249 caps.drawIndirectMulti =
false;
1254 caps.shaderDrawParameters =
false;
1256 caps.shaderDrawParameters = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 6);
1257 if (ctx->hasExtension(QByteArrayLiteral(
"GL_ARB_shader_draw_parameters")))
1258 caps.shaderDrawParameters =
true;
1260 nativeHandlesStruct.context = ctx;
2656 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
2659 const bool isCompressed = isCompressedFormat(texD->m_format);
2660 const bool isCubeMap = texD->m_flags.testFlag(QRhiTexture::CubeMap);
2661 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2662 const bool is1D = texD->m_flags.testFlag(QRhiTexture::OneDimensional);
2663 const bool isArray = texD->m_flags.testFlag(QRhiTexture::TextureArray);
2665 const GLenum effectiveTarget = faceTargetBase + (isCubeMap ? uint(layer) : 0u);
2666 const QPoint dp = subresDesc.destinationTopLeft();
2667 const QByteArray rawData = subresDesc.data();
2669 auto setCmdByNotCompressedData = [&](
const void* data, QSize size, quint32 dataStride)
2671 quint32 bytesPerLine = 0;
2672 quint32 bytesPerPixel = 0;
2673 textureFormatInfo(texD->m_format, size, &bytesPerLine,
nullptr, &bytesPerPixel);
2677 cmd.args.subImage.target = texD->target;
2678 cmd.args.subImage.texture = texD->texture;
2679 cmd.args.subImage.faceTarget = effectiveTarget;
2680 cmd.args.subImage.level = level;
2681 cmd.args.subImage.dx = dp.x();
2682 cmd.args.subImage.dy = is1D && isArray ? layer : dp.y();
2683 cmd.args.subImage.dz = is3D || isArray ? layer : 0;
2684 cmd.args.subImage.w = size.width();
2685 cmd.args.subImage.h = size.height();
2686 cmd.args.subImage.glformat = texD->glformat;
2687 cmd.args.subImage.gltype = texD->gltype;
2689 if (dataStride == 0)
2690 dataStride = bytesPerLine;
2692 cmd.args.subImage.rowStartAlign = (dataStride & 3) ? 1 : 4;
2693 cmd.args.subImage.rowLength = caps.unpackRowLength ? (bytesPerPixel ? dataStride / bytesPerPixel : 0) : 0;
2695 cmd.args.subImage.data = data;
2698 if (!subresDesc.image().isNull()) {
2699 QImage img = subresDesc.image();
2700 QSize size = img.size();
2701 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
2702 const QPoint sp = subresDesc.sourceTopLeft();
2703 if (!subresDesc.sourceSize().isEmpty())
2704 size = subresDesc.sourceSize();
2705 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2706 if (caps.unpackRowLength) {
2707 cbD->retainImage(img);
2709 const uchar *data = img.constBits() + sp.y() * img.bytesPerLine() + sp.x() * (qMax(1, img.depth() / 8));
2710 img = QImage(data, size.width(), size.height(), img.bytesPerLine(), img.format());
2712 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
2715 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2718 setCmdByNotCompressedData(cbD->retainImage(img), size, img.bytesPerLine());
2719 }
else if (!rawData.isEmpty() && isCompressed) {
2720 const int depth = qMax(1, texD->m_depth);
2721 const int arraySize = qMax(0, texD->m_arraySize);
2722 if ((texD->flags().testFlag(QRhiTexture::UsedAsCompressedAtlas) || is3D || isArray)
2730 quint32 byteSize = 0;
2731 compressedFormatInfo(texD->m_format, texD->m_pixelSize,
nullptr, &byteSize,
nullptr);
2735 byteSize *= arraySize;
2736 QByteArray zeroBuf(byteSize, 0);
2739 cmd.args.compressedImage.target = texD->target;
2740 cmd.args.compressedImage.texture = texD->texture;
2741 cmd.args.compressedImage.faceTarget = effectiveTarget;
2742 cmd.args.compressedImage.level = level;
2743 cmd.args.compressedImage.glintformat = texD->glintformat;
2744 cmd.args.compressedImage.w = texD->m_pixelSize.width();
2745 cmd.args.compressedImage.h = is1D && isArray ? arraySize : texD->m_pixelSize.height();
2746 cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
2747 cmd.args.compressedImage.size = byteSize;
2748 cmd.args.compressedImage.data = cbD->retainData(zeroBuf);
2752 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2753 : subresDesc.sourceSize();
2757 cmd.args.compressedSubImage.target = texD->target;
2758 cmd.args.compressedSubImage.texture = texD->texture;
2759 cmd.args.compressedSubImage.faceTarget = effectiveTarget;
2760 cmd.args.compressedSubImage.level = level;
2761 cmd.args.compressedSubImage.dx = dp.x();
2762 cmd.args.compressedSubImage.dy = is1D && isArray ? layer : dp.y();
2763 cmd.args.compressedSubImage.dz = is3D || isArray ? layer : 0;
2764 cmd.args.compressedSubImage.w = size.width();
2765 cmd.args.compressedSubImage.h = size.height();
2766 cmd.args.compressedSubImage.glintformat = texD->glintformat;
2767 cmd.args.compressedSubImage.size = rawData.size();
2768 cmd.args.compressedSubImage.data = cbD->retainData(rawData);
2772 cmd.args.compressedImage.target = texD->target;
2773 cmd.args.compressedImage.texture = texD->texture;
2774 cmd.args.compressedImage.faceTarget = effectiveTarget;
2775 cmd.args.compressedImage.level = level;
2776 cmd.args.compressedImage.glintformat = texD->glintformat;
2777 cmd.args.compressedImage.w = size.width();
2778 cmd.args.compressedImage.h = is1D && isArray ? arraySize : size.height();
2779 cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
2780 cmd.args.compressedImage.size = rawData.size();
2781 cmd.args.compressedImage.data = cbD->retainData(rawData);
2783 }
else if (!rawData.isEmpty()) {
2784 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2785 : subresDesc.sourceSize();
2787 setCmdByNotCompressedData(cbD->retainData(rawData), size, subresDesc.dataStride());
2789 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
3326 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
3330 if (cmd.args.beginFrame.timestampQuery)
3332 if (caps.coreProfile) {
3334 f->glGenVertexArrays(1, &vao);
3335 f->glBindVertexArray(vao);
3342 f->glVertexAttribDivisor(GLuint(i), 0);
3345 f->glVertexAttribDivisor(GLuint(i), 0);
3349 for (
int i = 0; i < CommandBufferExecTrackedState::TRACKED_ATTRIB_COUNT; ++i) {
3350 if (state.enabledAttribArrays[i]) {
3351 f->glDisableVertexAttribArray(GLuint(i));
3352 state.enabledAttribArrays[i] =
false;
3357 f->glBindVertexArray(0);
3358 if (cmd.args.endFrame.timestampQuery)
3363 f->glBindVertexArray(vao);
3366 f->glViewport(GLint(cmd.args.viewport.x), GLint(cmd.args.viewport.y), GLsizei(cmd.args.viewport.w), GLsizei(cmd.args.viewport.h));
3367 f->glDepthRangef(cmd.args.viewport.d0, cmd.args.viewport.d1);
3370 f->glScissor(cmd.args.scissor.x, cmd.args.scissor.y, cmd.args.scissor.w, cmd.args.scissor.h);
3373 f->glBlendColor(cmd.args.blendConstants.r, cmd.args.blendConstants.g, cmd.args.blendConstants.b, cmd.args.blendConstants.a);
3379 const GLint ref = GLint(cmd.args.stencilRef.ref);
3380 f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), ref, psD->m_stencilReadMask);
3381 f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), ref, psD->m_stencilReadMask);
3382 cbD->graphicsPassState.dynamic.stencilRef = ref;
3384 qWarning(
"No graphics pipeline active for setStencilRef; ignored");
3392 if (state.lastBindVertexBuffer.ps == psD
3393 && state.lastBindVertexBuffer.buffer == cmd.args.bindVertexBuffer.buffer
3394 && state.lastBindVertexBuffer.offset == cmd.args.bindVertexBuffer.offset
3395 && state.lastBindVertexBuffer.binding == cmd.args.bindVertexBuffer.binding)
3402 state.lastBindVertexBuffer.ps = psD;
3403 state.lastBindVertexBuffer.buffer = cmd.args.bindVertexBuffer.buffer;
3404 state.lastBindVertexBuffer.offset = cmd.args.bindVertexBuffer.offset;
3405 state.lastBindVertexBuffer.binding = cmd.args.bindVertexBuffer.binding;
3407 if (cmd.args.bindVertexBuffer.buffer != state.currentArrayBuffer) {
3408 state.currentArrayBuffer = cmd.args.bindVertexBuffer.buffer;
3410 f->glBindBuffer(GL_ARRAY_BUFFER, state.currentArrayBuffer);
3412 for (
auto it = psD->m_vertexInputLayout.cbeginAttributes(), itEnd = psD->m_vertexInputLayout.cendAttributes();
3415 const int bindingIdx = it->binding();
3416 if (bindingIdx != cmd.args.bindVertexBuffer.binding)
3419 const QRhiVertexInputBinding *inputBinding = psD->m_vertexInputLayout.bindingAt(bindingIdx);
3420 const int stride =
int(inputBinding->stride());
3423 bool normalize =
false;
3424 switch (it->format()) {
3425 case QRhiVertexInputAttribute::Float4:
3429 case QRhiVertexInputAttribute::Float3:
3433 case QRhiVertexInputAttribute::Float2:
3437 case QRhiVertexInputAttribute::Float:
3441 case QRhiVertexInputAttribute::UNormByte4:
3446 case QRhiVertexInputAttribute::UNormByte2:
3451 case QRhiVertexInputAttribute::UNormByte:
3456 case QRhiVertexInputAttribute::UInt4:
3457 type = GL_UNSIGNED_INT;
3460 case QRhiVertexInputAttribute::UInt3:
3461 type = GL_UNSIGNED_INT;
3464 case QRhiVertexInputAttribute::UInt2:
3465 type = GL_UNSIGNED_INT;
3468 case QRhiVertexInputAttribute::UInt:
3469 type = GL_UNSIGNED_INT;
3472 case QRhiVertexInputAttribute::SInt4:
3476 case QRhiVertexInputAttribute::SInt3:
3480 case QRhiVertexInputAttribute::SInt2:
3484 case QRhiVertexInputAttribute::SInt:
3488 case QRhiVertexInputAttribute::Half4:
3492 case QRhiVertexInputAttribute::Half3:
3496 case QRhiVertexInputAttribute::Half2:
3500 case QRhiVertexInputAttribute::Half:
3504 case QRhiVertexInputAttribute::UShort4:
3505 type = GL_UNSIGNED_SHORT;
3508 case QRhiVertexInputAttribute::UShort3:
3509 type = GL_UNSIGNED_SHORT;
3512 case QRhiVertexInputAttribute::UShort2:
3513 type = GL_UNSIGNED_SHORT;
3516 case QRhiVertexInputAttribute::UShort:
3517 type = GL_UNSIGNED_SHORT;
3520 case QRhiVertexInputAttribute::SShort4:
3524 case QRhiVertexInputAttribute::SShort3:
3528 case QRhiVertexInputAttribute::SShort2:
3532 case QRhiVertexInputAttribute::SShort:
3540 const int locationIdx = it->location();
3541 quint32 ofs = it->offset() + cmd.args.bindVertexBuffer.offset;
3542 if (type == GL_UNSIGNED_INT || type == GL_INT) {
3543 if (caps.intAttributes) {
3544 f->glVertexAttribIPointer(GLuint(locationIdx), size, type, stride,
3545 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3547 qWarning(
"Current RHI backend does not support IntAttributes. Check supported features.");
3553 f->glVertexAttribPointer(GLuint(locationIdx), size, type, normalize, stride,
3554 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3559 f->glEnableVertexAttribArray(GLuint(locationIdx));
3561 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance && caps.instancing) {
3562 f->glVertexAttribDivisor(GLuint(locationIdx), inputBinding->instanceStepRate());
3573 f->glVertexAttribDivisor(GLuint(locationIdx), 0);
3579 qWarning(
"No graphics pipeline active for setVertexInput; ignored");
3584 state.indexType = cmd.args.bindIndexBuffer.type;
3585 state.indexStride = state.indexType == GL_UNSIGNED_SHORT ?
sizeof(quint16) :
sizeof(quint32);
3586 state.indexOffset = cmd.args.bindIndexBuffer.offset;
3587 if (state.currentElementArrayBuffer != cmd.args.bindIndexBuffer.buffer) {
3588 state.currentElementArrayBuffer = cmd.args.bindIndexBuffer.buffer;
3589 f->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state.currentElementArrayBuffer);
3596 if (cmd.args.draw.instanceCount == 1 || !caps.instancing) {
3597 f->glDrawArrays(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount));
3599 f->glDrawArraysInstanced(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount),
3600 GLsizei(cmd.args.draw.instanceCount));
3603 qWarning(
"No graphics pipeline active for draw; ignored");
3611 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3612 quintptr(cmd.args.drawIndexed.firstIndex * state.indexStride + state.indexOffset));
3613 if (cmd.args.drawIndexed.instanceCount == 1 || !caps.instancing) {
3614 if (cmd.args.drawIndexed.baseVertex != 0 && caps.baseVertex) {
3615 f->glDrawElementsBaseVertex(psD->drawMode,
3616 GLsizei(cmd.args.drawIndexed.indexCount),
3619 cmd.args.drawIndexed.baseVertex);
3621 f->glDrawElements(psD->drawMode,
3622 GLsizei(cmd.args.drawIndexed.indexCount),
3627 if (cmd.args.drawIndexed.baseVertex != 0 && caps.baseVertex) {
3628 f->glDrawElementsInstancedBaseVertex(psD->drawMode,
3629 GLsizei(cmd.args.drawIndexed.indexCount),
3632 GLsizei(cmd.args.drawIndexed.instanceCount),
3633 cmd.args.drawIndexed.baseVertex);
3635 f->glDrawElementsInstanced(psD->drawMode,
3636 GLsizei(cmd.args.drawIndexed.indexCount),
3639 GLsizei(cmd.args.drawIndexed.instanceCount));
3643 qWarning(
"No graphics pipeline active for drawIndexed; ignored");
3653 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3654 quintptr(cmd.args.drawIndirect.offset));
3657 cmd.args.drawIndirect.drawCount
,
3658 cmd.args.drawIndirect.stride
);
3660 for (quint32 i = 0; i < cmd.args.drawIndirect.drawCount; ++i) {
3661 const quintptr indirectOffset = quintptr(cmd.args.drawIndirect.offset)
3662 + quintptr(i) * cmd.args.drawIndirect.stride;
3663 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(indirectOffset);
3664 f->glDrawArraysIndirect(psD->drawMode,
3670 qWarning(
"No graphics pipeline active for drawIndirect; ignored");
3680 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3681 quintptr(cmd.args.drawIndexedIndirect.offset));
3685 cmd.args.drawIndexedIndirect.drawCount
,
3686 cmd.args.drawIndexedIndirect.stride
);
3688 for (quint32 i = 0; i < cmd.args.drawIndexedIndirect.drawCount; ++i) {
3689 const quintptr indirectOffset = quintptr(cmd.args.drawIndexedIndirect.offset)
3690 + quintptr(i) * cmd.args.drawIndexedIndirect.stride;
3691 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(indirectOffset);
3692 f->glDrawElementsIndirect(psD->drawMode,
3699 qWarning(
"No graphics pipeline active for drawIndexedIndirect; ignored");
3706 case QGles2CommandBuffer::Command::BindShaderResources:
3707 bindShaderResources(cbD,
3708 cmd.args.bindShaderResources.maybeGraphicsPs,
3709 cmd.args.bindShaderResources.maybeComputePs,
3710 cmd.args.bindShaderResources.srb,
3711 cmd.args.bindShaderResources.dynamicOffsetPairs,
3712 cmd.args.bindShaderResources.dynamicOffsetCount);
3716 QVarLengthArray<GLenum, 8> bufs;
3717 GLuint fbo = cmd.args.bindFramebuffer.fbo;
3719 fbo = ctx->defaultFramebufferObject();
3720 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3722 const int colorAttCount = cmd.args.bindFramebuffer.colorAttCount;
3723 bufs.append(colorAttCount > 0 ? GL_COLOR_ATTACHMENT0 : GL_NONE);
3724 if (caps.maxDrawBuffers > 1) {
3725 for (
int i = 1; i < colorAttCount; ++i)
3726 bufs.append(GL_COLOR_ATTACHMENT0 + uint(i));
3729 if (cmd.args.bindFramebuffer.stereo && cmd.args.bindFramebuffer.stereoTarget == QRhiSwapChain::RightBuffer)
3734 if (caps.hasDrawBuffersFunc)
3735 f->glDrawBuffers(bufs.count(), bufs.constData());
3736 if (caps.srgbWriteControl) {
3737 if (cmd.args.bindFramebuffer.srgb)
3745 f->glDisable(GL_SCISSOR_TEST);
3746 if (cmd.args.clear.mask & GL_COLOR_BUFFER_BIT) {
3747 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3748 f->glClearColor(cmd.args.clear.c[0], cmd.args.clear.c[1], cmd.args.clear.c[2], cmd.args.clear.c[3]);
3750 if (cmd.args.clear.mask & GL_DEPTH_BUFFER_BIT) {
3751 f->glDepthMask(GL_TRUE);
3752 f->glClearDepthf(cmd.args.clear.d);
3754 if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT) {
3755 f->glStencilMask(0xFF);
3756 f->glClearStencil(GLint(cmd.args.clear.s));
3758 f->glClear(cmd.args.clear.mask);
3759 cbD->graphicsPassState.reset();
3762 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.bufferSubData.target, cmd.args.bufferSubData.buffer);
3763 f->glBufferSubData(cmd.args.bufferSubData.target, cmd.args.bufferSubData.offset, cmd.args.bufferSubData.size,
3764 cmd.args.bufferSubData.data);
3768 QRhiReadbackResult *result = cmd.args.getBufferSubData.result;
3769 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.getBufferSubData.target, cmd.args.getBufferSubData.buffer);
3771 if (caps.properMapBuffer) {
3772 void *p =
f->glMapBufferRange(cmd.args.getBufferSubData.target,
3773 cmd.args.getBufferSubData.offset,
3774 cmd.args.getBufferSubData.size,
3777 result->data.resize(cmd.args.getBufferSubData.size);
3778 memcpy(result->data.data(), p, size_t(cmd.args.getBufferSubData.size));
3779 f->glUnmapBuffer(cmd.args.getBufferSubData.target);
3783 result->data.resize(cmd.args.getBufferSubData.size);
3784 f->glGetBufferSubData(cmd.args.getBufferSubData.target,
3785 cmd.args.getBufferSubData.offset,
3786 cmd.args.getBufferSubData.size,
3787 result->data.data());
3789 if (result->completed)
3790 result->completed();
3796 f->glGenFramebuffers(1, &fbo);
3797 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3801 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.copyTex.srcTexture,
3802 cmd.args.copyTex.srcLevel, cmd.args.copyTex.srcZ);
3805 cmd.args.copyTex.srcTarget, cmd.args.copyTex.srcTexture,
3806 cmd.args.copyTex.srcLevel);
3808 f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
3809 cmd.args.copyTex.srcFaceTarget, cmd.args.copyTex.srcTexture, cmd.args.copyTex.srcLevel);
3811 f->glBindTexture(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstTexture);
3813 f->glCopyTexSubImage3D(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstLevel,
3814 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY, cmd.args.copyTex.dstZ,
3815 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
3816 cmd.args.copyTex.w, cmd.args.copyTex.h);
3819 cmd.args.copyTex.dstX
, cmd.args.copyTex.srcX
,
3820 cmd.args.copyTex.srcY
, cmd.args.copyTex.w
);
3822 f->glCopyTexSubImage2D(cmd.args.copyTex.dstFaceTarget, cmd.args.copyTex.dstLevel,
3823 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY,
3824 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
3825 cmd.args.copyTex.w, cmd.args.copyTex.h);
3827 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
3828 f->glDeleteFramebuffers(1, &fbo);
3833 QRhiReadbackResult *result = cmd.args.readPixels.result;
3834 GLuint tex = cmd.args.readPixels.texture;
3837 result->pixelSize = QSize(cmd.args.readPixels.w, cmd.args.readPixels.h);
3839 result->format = cmd.args.readPixels.format;
3840 mipLevel = cmd.args.readPixels.level;
3841 if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
3842 f->glGenFramebuffers(1, &fbo);
3843 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3844 if (cmd.args.readPixels.slice3D >= 0) {
3845 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
3846 tex, mipLevel, cmd.args.readPixels.slice3D);
3847 }
else if (cmd.args.readPixels.readTarget ==
GL_TEXTURE_1D) {
3849 cmd.args.readPixels.readTarget, tex, mipLevel);
3851 f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
3852 cmd.args.readPixels.readTarget, tex, mipLevel);
3856 result->format = QRhiTexture::RGBA8;
3859 const int x = cmd.args.readPixels.x;
3860 const int y = cmd.args.readPixels.y;
3861 const int w = cmd.args.readPixels.w;
3862 const int h = cmd.args.readPixels.h;
3863 if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
3866 if (result->format == QRhiTexture::R8 || result->format == QRhiTexture::RED_OR_ALPHA8) {
3867 result->data.resizeForOverwrite(w * h);
3869 tmpBuf.resizeForOverwrite(w * h * 4);
3871 const quint8 *srcBase =
reinterpret_cast<
const quint8 *>(tmpBuf.constData());
3872 quint8 *dstBase =
reinterpret_cast<quint8 *>(result->data.data());
3873 const int componentIndex = isFeatureSupported(QRhi::RedOrAlpha8IsRed) ? 0 : 3;
3874 for (
int y = 0; y < h; ++y) {
3875 const quint8 *src = srcBase + y * w * 4;
3876 quint8 *dst = dstBase + y * w;
3878 while (count-- > 0) {
3879 *dst++ = src[componentIndex];
3886 [[maybe_unused]] GLenum glintformat;
3887 [[maybe_unused]] GLenum glsizedintformat;
3890 toGlTextureFormat(result->format, caps, &glintformat, &glsizedintformat, &glformat, &gltype);
3892 textureFormatInfo(result->format, result->pixelSize,
nullptr, &byteSize,
nullptr);
3893 result->data.resizeForOverwrite(byteSize);
3894 f->glReadPixels(x, y, w, h, glformat, gltype, result->data.data());
3897 result->data.resizeForOverwrite(w * h * 4);
3898 result->data.fill(
'\0');
3901 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
3902 f->glDeleteFramebuffers(1, &fbo);
3904 if (result->completed)
3905 result->completed();
3909 f->glBindTexture(cmd.args.subImage.target, cmd.args.subImage.texture);
3910 if (cmd.args.subImage.rowStartAlign != 4)
3911 f->glPixelStorei(GL_UNPACK_ALIGNMENT, cmd.args.subImage.rowStartAlign);
3912 if (cmd.args.subImage.rowLength != 0)
3915 f->glTexSubImage3D(cmd.args.subImage.target, cmd.args.subImage.level,
3916 cmd.args.subImage.dx, cmd.args.subImage.dy, cmd.args.subImage.dz,
3917 cmd.args.subImage.w, cmd.args.subImage.h, 1,
3918 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
3919 cmd.args.subImage.data);
3922 cmd.args.subImage.dx
, cmd.args.subImage.w
,
3923 cmd.args.subImage.glformat
, cmd.args.subImage.gltype
,
3924 cmd.args.subImage.data
);
3926 f->glTexSubImage2D(cmd.args.subImage.faceTarget, cmd.args.subImage.level,
3927 cmd.args.subImage.dx, cmd.args.subImage.dy,
3928 cmd.args.subImage.w, cmd.args.subImage.h,
3929 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
3930 cmd.args.subImage.data);
3932 if (cmd.args.subImage.rowStartAlign != 4)
3933 f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
3934 if (cmd.args.subImage.rowLength != 0)
3938 f->glBindTexture(cmd.args.compressedImage.target, cmd.args.compressedImage.texture);
3940 f->glCompressedTexImage3D(cmd.args.compressedImage.target, cmd.args.compressedImage.level,
3941 cmd.args.compressedImage.glintformat,
3942 cmd.args.compressedImage.w, cmd.args.compressedImage.h, cmd.args.compressedImage.depth,
3943 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
3944 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
3946 cmd.args.compressedImage.target
, cmd.args.compressedImage.level
,
3947 cmd.args.compressedImage.glintformat
, cmd.args.compressedImage.w
, 0
,
3948 cmd.args.compressedImage.size
, cmd.args.compressedImage.data
);
3950 f->glCompressedTexImage2D(cmd.args.compressedImage.faceTarget, cmd.args.compressedImage.level,
3951 cmd.args.compressedImage.glintformat,
3952 cmd.args.compressedImage.w, cmd.args.compressedImage.h,
3953 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
3957 f->glBindTexture(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.texture);
3959 f->glCompressedTexSubImage3D(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.level,
3960 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy, cmd.args.compressedSubImage.dz,
3961 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h, 1,
3962 cmd.args.compressedSubImage.glintformat,
3963 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
3964 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
3966 cmd.args.compressedSubImage.target
, cmd.args.compressedSubImage.level
,
3967 cmd.args.compressedSubImage.dx
, cmd.args.compressedSubImage.w
,
3968 cmd.args.compressedSubImage.glintformat
, cmd.args.compressedSubImage.size
,
3969 cmd.args.compressedSubImage.data
);
3971 f->glCompressedTexSubImage2D(cmd.args.compressedSubImage.faceTarget, cmd.args.compressedSubImage.level,
3972 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy,
3973 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h,
3974 cmd.args.compressedSubImage.glintformat,
3975 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
3982 cbD->graphicsPassState.reset();
3983 f->glDisable(GL_SCISSOR_TEST);
3985 f->glGenFramebuffers(2, fbo);
3987 const bool ds = cmd.args.blitFromRenderbuffer.isDepthStencil;
3990 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
3992 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
3995 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
4001 cmd.args.blitFromRenderbuffer.dstTexture,
4002 cmd.args.blitFromRenderbuffer.dstLevel,
4003 cmd.args.blitFromRenderbuffer.dstLayer);
4005 cmd.args.blitFromRenderbuffer.dstTexture,
4006 cmd.args.blitFromRenderbuffer.dstLevel,
4007 cmd.args.blitFromRenderbuffer.dstLayer);
4010 cmd.args.blitFromRenderbuffer.dstTexture,
4011 cmd.args.blitFromRenderbuffer.dstLevel,
4012 cmd.args.blitFromRenderbuffer.dstLayer);
4016 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
4017 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4018 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
4019 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4021 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromRenderbuffer.target,
4022 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
4025 f->glBlitFramebuffer(0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
4026 0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
4027 ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT,
4029 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4030 f->glDeleteFramebuffers(2, fbo);
4037 cbD->graphicsPassState.reset();
4038 f->glDisable(GL_SCISSOR_TEST);
4040 f->glGenFramebuffers(2, fbo);
4042 const bool ds = cmd.args.blitFromTexture.isDepthStencil;
4046 cmd.args.blitFromTexture.srcTexture,
4047 cmd.args.blitFromTexture.srcLevel,
4048 cmd.args.blitFromTexture.srcLayer);
4050 cmd.args.blitFromTexture.srcTexture,
4051 cmd.args.blitFromTexture.srcLevel,
4052 cmd.args.blitFromTexture.srcLayer);
4055 cmd.args.blitFromTexture.srcTexture,
4056 cmd.args.blitFromTexture.srcLevel,
4057 cmd.args.blitFromTexture.srcLayer);
4061 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
4062 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4063 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
4064 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4066 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.srcTarget,
4067 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
4074 cmd.args.blitFromTexture.dstTexture,
4075 cmd.args.blitFromTexture.dstLevel,
4076 cmd.args.blitFromTexture.dstLayer);
4078 cmd.args.blitFromTexture.dstTexture,
4079 cmd.args.blitFromTexture.dstLevel,
4080 cmd.args.blitFromTexture.dstLayer);
4083 cmd.args.blitFromTexture.dstTexture,
4084 cmd.args.blitFromTexture.dstLevel,
4085 cmd.args.blitFromTexture.dstLayer);
4089 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
4090 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4091 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
4092 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4094 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.dstTarget,
4095 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
4098 f->glBlitFramebuffer(0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
4099 0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
4100 ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT,
4102 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
4103 f->glDeleteFramebuffers(2, fbo);
4107 f->glBindTexture(cmd.args.genMip.target, cmd.args.genMip.texture);
4108 f->glGenerateMipmap(cmd.args.genMip.target);
4113 f->glUseProgram(psD->program);
4117 f->glDispatchCompute(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
4123 GLbitfield barriers = 0;
4132 for (
const auto &[rhiB, trackedB]: tracker.buffers()) {
4134 QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(trackedB.stateAtPassBegin.access);
4135 if (bufferAccessIsWrite(accessBeforePass))
4136 barriers |= barriersForBuffer();
4138 for (
const auto &[rhiT, trackedT]: tracker.textures()) {
4140 QGles2Texture::Access accessBeforePass = QGles2Texture::Access(trackedT.stateAtPassBegin.access);
4141 if (textureAccessIsWrite(accessBeforePass))
4142 barriers |= barriersForTexture();
4145 f->glMemoryBarrier(barriers);
4150 f->glMemoryBarrier(cmd.args.barrier.barriers);
4153 if (caps.gles && caps.ctxMajor >= 3) {
4154 f->glBindFramebuffer(GL_FRAMEBUFFER, cmd.args.invalidateFramebuffer.fbo);
4156 cmd.args.invalidateFramebuffer.attCount,
4157 cmd.args.invalidateFramebuffer.att);
4167 f->glVertexAttribDivisor(GLuint(i), 0);
4170 f->glVertexAttribDivisor(GLuint(i), 0);
4177 const bool forceUpdate = !state
.valid;
4180 const bool scissor = psD->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor);
4181 if (forceUpdate || scissor != state
.scissor) {
4184 f->glEnable(GL_SCISSOR_TEST);
4186 f->glDisable(GL_SCISSOR_TEST);
4189 const bool cullFace = psD->m_cullMode != QRhiGraphicsPipeline::None;
4190 const GLenum cullMode = cullFace ? toGlCullMode(psD->m_cullMode) : GL_NONE;
4191 if (forceUpdate || cullFace != state
.cullFace || cullMode != state.cullMode) {
4193 state.cullMode = cullMode;
4195 f->glEnable(GL_CULL_FACE);
4196 f->glCullFace(cullMode);
4198 f->glDisable(GL_CULL_FACE);
4202 const GLenum frontFace = toGlFrontFace(psD->m_frontFace);
4203 if (forceUpdate || frontFace != state.frontFace) {
4204 state.frontFace = frontFace;
4205 f->glFrontFace(frontFace);
4208 const GLenum polygonMode = toGlPolygonMode(psD->m_polygonMode);
4209 if (
glPolygonMode && (forceUpdate || polygonMode != state.polygonMode)) {
4210 state.polygonMode = polygonMode;
4214 if (!psD->m_targetBlends.isEmpty()) {
4216 bool anyBlendEnabled =
false;
4217 for (
const auto targetBlend : psD->m_targetBlends) {
4218 const QGles2CommandBuffer::GraphicsPassState::ColorMask colorMask = {
4219 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::R),
4220 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::G),
4221 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::B),
4222 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::A)
4224 if (forceUpdate || colorMask != state.colorMask[buffer]) {
4225 state.colorMask[buffer] = colorMask;
4226 if (caps.perRenderTargetBlending)
4227 f->glColorMaski(buffer, colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4229 f->glColorMask(colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4232 const bool blendEnabled = targetBlend.enable;
4233 const QGles2CommandBuffer::GraphicsPassState::Blend blend = {
4234 toGlBlendFactor(targetBlend.srcColor),
4235 toGlBlendFactor(targetBlend.dstColor),
4236 toGlBlendFactor(targetBlend.srcAlpha),
4237 toGlBlendFactor(targetBlend.dstAlpha),
4238 toGlBlendOp(targetBlend.opColor),
4239 toGlBlendOp(targetBlend.opAlpha)
4241 anyBlendEnabled |= blendEnabled;
4242 if (forceUpdate || blendEnabled != state.blendEnabled[buffer] || (blendEnabled && blend != state.blend[buffer])) {
4243 state.blendEnabled[buffer] = blendEnabled;
4245 state.blend[buffer] = blend;
4246 if (caps.perRenderTargetBlending) {
4247 f->glBlendFuncSeparatei(buffer, blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4248 f->glBlendEquationSeparatei(buffer, blend.opColor, blend.opAlpha);
4250 f->glBlendFuncSeparate(blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4251 f->glBlendEquationSeparate(blend.opColor, blend.opAlpha);
4256 if (!caps.perRenderTargetBlending)
4259 if (anyBlendEnabled)
4260 f->glEnable(GL_BLEND);
4262 f->glDisable(GL_BLEND);
4265 if (forceUpdate || colorMask
!= state.colorMask[0]) {
4266 state.colorMask[0] = colorMask;
4267 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4269 const bool blendEnabled =
false;
4272 f->glDisable(GL_BLEND);
4276 const bool depthTest = psD->m_depthTest;
4277 if (forceUpdate || depthTest != state
.depthTest) {
4280 f->glEnable(GL_DEPTH_TEST);
4282 f->glDisable(GL_DEPTH_TEST);
4285 const bool depthWrite = psD->m_depthWrite;
4286 if (forceUpdate || depthWrite != state
.depthWrite) {
4288 f->glDepthMask(depthWrite);
4291 const bool depthClamp = psD->m_depthClamp;
4292 if (caps.depthClamp && (forceUpdate || depthClamp != state.depthClamp)) {
4300 const GLenum depthFunc = toGlCompareOp(psD->m_depthOp);
4301 if (forceUpdate || depthFunc != state.depthFunc) {
4302 state.depthFunc = depthFunc;
4303 f->glDepthFunc(depthFunc);
4306 const bool stencilTest = psD->m_stencilTest;
4307 const GLuint stencilReadMask = psD->m_stencilReadMask;
4308 const GLuint stencilWriteMask = psD->m_stencilWriteMask;
4310 toGlCompareOp(psD->m_stencilFront.compareOp),
4311 toGlStencilOp(psD->m_stencilFront.failOp),
4312 toGlStencilOp(psD->m_stencilFront.depthFailOp),
4313 toGlStencilOp(psD->m_stencilFront.passOp)
4316 toGlCompareOp(psD->m_stencilBack.compareOp),
4317 toGlStencilOp(psD->m_stencilBack.failOp),
4318 toGlStencilOp(psD->m_stencilBack.depthFailOp),
4319 toGlStencilOp(psD->m_stencilBack.passOp)
4323 && (stencilReadMask != state.stencilReadMask || stencilWriteMask != state.stencilWriteMask
4324 || stencilFront != state.stencil[0] || stencilBack != state.stencil[1])))
4328 state.stencilReadMask = stencilReadMask;
4329 state.stencilWriteMask = stencilWriteMask;
4330 state.stencil[0] = stencilFront;
4331 state.stencil[1] = stencilBack;
4333 f->glEnable(GL_STENCIL_TEST);
4335 f->glStencilFuncSeparate(GL_FRONT, stencilFront.func, state.dynamic.stencilRef, stencilReadMask);
4336 f->glStencilOpSeparate(GL_FRONT, stencilFront.failOp, stencilFront.zfailOp, stencilFront.zpassOp);
4337 f->glStencilMaskSeparate(GL_FRONT, stencilWriteMask);
4339 f->glStencilFuncSeparate(GL_BACK, stencilBack.func, state.dynamic.stencilRef, stencilReadMask);
4340 f->glStencilOpSeparate(GL_BACK, stencilBack.failOp, stencilBack.zfailOp, stencilBack.zpassOp);
4341 f->glStencilMaskSeparate(GL_BACK, stencilWriteMask);
4343 f->glDisable(GL_STENCIL_TEST);
4347 const bool polyOffsetFill = psD->m_depthBias != 0 || !qFuzzyIsNull(psD->m_slopeScaledDepthBias);
4348 const float polyOffsetFactor = psD->m_slopeScaledDepthBias;
4349 const float polyOffsetUnits = psD->m_depthBias;
4356 if (polyOffsetFill) {
4357 f->glPolygonOffset(polyOffsetFactor, polyOffsetUnits);
4358 f->glEnable(GL_POLYGON_OFFSET_FILL);
4360 f->glDisable(GL_POLYGON_OFFSET_FILL);
4364 if (psD->m_topology == QRhiGraphicsPipeline::Lines || psD->m_topology == QRhiGraphicsPipeline::LineStrip) {
4365 const float lineWidth = psD->m_lineWidth;
4366 if (forceUpdate || lineWidth != state
.lineWidth) {
4368 f->glLineWidth(lineWidth);
4372 if (psD->m_topology == QRhiGraphicsPipeline::Patches) {
4373 const int cpCount = psD->m_patchControlPointCount;
4374 if (forceUpdate || cpCount != state
.cpCount) {
4380 f->glUseProgram(psD->program);
4448 QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs,
4449 QRhiShaderResourceBindings *srb,
4450 const uint *dynOfsPairs,
int dynOfsCount)
4454 bool activeTexUnitAltered =
false;
4459 m_scratch.separateTextureBindings.clear();
4460 m_scratch.separateSamplerBindings.clear();
4462 for (
int i = 0, ie = srbD->m_bindings.size(); i != ie; ++i) {
4463 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->m_bindings.at(i));
4466 case QRhiShaderResourceBinding::UniformBuffer:
4468 int viewOffset = b->u.ubuf.offset;
4469 for (
int j = 0; j < dynOfsCount; ++j) {
4470 if (dynOfsPairs[2 * j] == uint(b->binding)) {
4471 viewOffset =
int(dynOfsPairs[2 * j + 1]);
4476 const char *bufView = bufD->data.constData() + viewOffset;
4477 for (
const QGles2UniformDescription &uniform : std::as_const(uniforms)) {
4478 if (uniform.binding == b->binding) {
4481 const void *src = bufView + uniform.offset;
4484 if (uniform.arrayDim > 0
4485 && uniform.type != QShaderDescription::Float
4486 && uniform.type != QShaderDescription::Vec2
4487 && uniform.type != QShaderDescription::Vec3
4488 && uniform.type != QShaderDescription::Vec4
4489 && uniform.type != QShaderDescription::Int
4490 && uniform.type != QShaderDescription::Int2
4491 && uniform.type != QShaderDescription::Int3
4492 && uniform.type != QShaderDescription::Int4
4493 && uniform.type != QShaderDescription::Mat3
4494 && uniform.type != QShaderDescription::Mat4)
4496 qWarning(
"Uniform with buffer binding %d, buffer offset %d, type %d is an array, "
4497 "but arrays are only supported for float, vec2, vec3, vec4, int, "
4498 "ivec2, ivec3, ivec4, mat3 and mat4. "
4499 "Only the first element will be set.",
4500 uniform.binding, uniform.offset, uniform.type);
4510 switch (uniform.type) {
4511 case QShaderDescription::Float:
4513 const int elemCount = uniform.arrayDim;
4514 if (elemCount < 1) {
4515 const float v = *
reinterpret_cast<
const float *>(src);
4516 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4517 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4518 if (thisUniformState.componentCount != 1 || thisUniformState.v[0] != v) {
4519 thisUniformState.componentCount = 1;
4520 thisUniformState.v[0] = v;
4521 f->glUniform1f(uniform.glslLocation, v);
4524 f->glUniform1f(uniform.glslLocation, v);
4528 m_scratch.packedArray.resize(elemCount);
4529 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 1, elemCount, src);
4530 f->glUniform1fv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->f);
4534 case QShaderDescription::Vec2:
4536 const int elemCount = uniform.arrayDim;
4537 if (elemCount < 1) {
4538 const float *v =
reinterpret_cast<
const float *>(src);
4539 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4540 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4541 if (thisUniformState.componentCount != 2
4542 || thisUniformState.v[0] != v[0]
4543 || thisUniformState.v[1] != v[1])
4545 thisUniformState.componentCount = 2;
4546 thisUniformState.v[0] = v[0];
4547 thisUniformState.v[1] = v[1];
4548 f->glUniform2fv(uniform.glslLocation, 1, v);
4551 f->glUniform2fv(uniform.glslLocation, 1, v);
4554 m_scratch.packedArray.resize(elemCount * 2);
4555 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 2, elemCount, src);
4556 f->glUniform2fv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->f);
4560 case QShaderDescription::Vec3:
4562 const int elemCount = uniform.arrayDim;
4563 if (elemCount < 1) {
4564 const float *v =
reinterpret_cast<
const float *>(src);
4565 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4566 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4567 if (thisUniformState.componentCount != 3
4568 || thisUniformState.v[0] != v[0]
4569 || thisUniformState.v[1] != v[1]
4570 || thisUniformState.v[2] != v[2])
4572 thisUniformState.componentCount = 3;
4573 thisUniformState.v[0] = v[0];
4574 thisUniformState.v[1] = v[1];
4575 thisUniformState.v[2] = v[2];
4576 f->glUniform3fv(uniform.glslLocation, 1, v);
4579 f->glUniform3fv(uniform.glslLocation, 1, v);
4582 m_scratch.packedArray.resize(elemCount * 3);
4583 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 3, elemCount, src);
4584 f->glUniform3fv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->f);
4588 case QShaderDescription::Vec4:
4590 const int elemCount = uniform.arrayDim;
4591 if (elemCount < 1) {
4592 const float *v =
reinterpret_cast<
const float *>(src);
4593 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4594 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4595 if (thisUniformState.componentCount != 4
4596 || thisUniformState.v[0] != v[0]
4597 || thisUniformState.v[1] != v[1]
4598 || thisUniformState.v[2] != v[2]
4599 || thisUniformState.v[3] != v[3])
4601 thisUniformState.componentCount = 4;
4602 thisUniformState.v[0] = v[0];
4603 thisUniformState.v[1] = v[1];
4604 thisUniformState.v[2] = v[2];
4605 thisUniformState.v[3] = v[3];
4606 f->glUniform4fv(uniform.glslLocation, 1, v);
4609 f->glUniform4fv(uniform.glslLocation, 1, v);
4612 f->glUniform4fv(uniform.glslLocation, elemCount,
reinterpret_cast<
const float *>(src));
4616 case QShaderDescription::Mat2:
4617 f->glUniformMatrix2fv(uniform.glslLocation, 1, GL_FALSE,
reinterpret_cast<
const float *>(src));
4619 case QShaderDescription::Mat3:
4621 const int elemCount = uniform.arrayDim;
4622 if (elemCount < 1) {
4625 const float *srcMat =
reinterpret_cast<
const float *>(src);
4626 memcpy(mat, srcMat, 3 *
sizeof(
float));
4627 memcpy(mat + 3, srcMat + 4, 3 *
sizeof(
float));
4628 memcpy(mat + 6, srcMat + 8, 3 *
sizeof(
float));
4629 f->glUniformMatrix3fv(uniform.glslLocation, 1, GL_FALSE, mat);
4631 m_scratch.packedArray.resize(elemCount * 9);
4632 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 3, elemCount * 3, src);
4633 f->glUniformMatrix3fv(uniform.glslLocation, elemCount, GL_FALSE, &m_scratch.packedArray.constData()->f);
4637 case QShaderDescription::Mat4:
4638 f->glUniformMatrix4fv(uniform.glslLocation, qMax(1, uniform.arrayDim), GL_FALSE,
reinterpret_cast<
const float *>(src));
4640 case QShaderDescription::Int:
4642 const int elemCount = uniform.arrayDim;
4643 if (elemCount < 1) {
4644 f->glUniform1i(uniform.glslLocation, *
reinterpret_cast<
const qint32 *>(src));
4646 m_scratch.packedArray.resize(elemCount);
4647 qrhi_std140_to_packed(&m_scratch.packedArray.data()->i, 1, elemCount, src);
4648 f->glUniform1iv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->i);
4652 case QShaderDescription::Int2:
4654 const int elemCount = uniform.arrayDim;
4655 if (elemCount < 1) {
4656 f->glUniform2iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4658 m_scratch.packedArray.resize(elemCount * 2);
4659 qrhi_std140_to_packed(&m_scratch.packedArray.data()->i, 2, elemCount, src);
4660 f->glUniform2iv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->i);
4664 case QShaderDescription::Int3:
4666 const int elemCount = uniform.arrayDim;
4667 if (elemCount < 1) {
4668 f->glUniform3iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4670 m_scratch.packedArray.resize(elemCount * 3);
4671 qrhi_std140_to_packed(&m_scratch.packedArray.data()->i, 3, elemCount, src);
4672 f->glUniform3iv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->i);
4676 case QShaderDescription::Int4:
4677 f->glUniform4iv(uniform.glslLocation, qMax(1, uniform.arrayDim),
reinterpret_cast<
const qint32 *>(src));
4679 case QShaderDescription::Uint:
4680 f->glUniform1ui(uniform.glslLocation, *
reinterpret_cast<
const quint32 *>(src));
4682 case QShaderDescription::Uint2:
4683 f->glUniform2uiv(uniform.glslLocation, 1,
reinterpret_cast<
const quint32 *>(src));
4685 case QShaderDescription::Uint3:
4686 f->glUniform3uiv(uniform.glslLocation, 1,
reinterpret_cast<
const quint32 *>(src));
4688 case QShaderDescription::Uint4:
4689 f->glUniform4uiv(uniform.glslLocation, 1,
reinterpret_cast<
const quint32 *>(src));
4691 case QShaderDescription::Bool:
4692 f->glUniform1i(uniform.glslLocation, *
reinterpret_cast<
const qint32 *>(src));
4694 case QShaderDescription::Bool2:
4695 f->glUniform2iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4697 case QShaderDescription::Bool3:
4698 f->glUniform3iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4700 case QShaderDescription::Bool4:
4701 f->glUniform4iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4704 qWarning(
"Uniform with buffer binding %d, buffer offset %d has unsupported type %d",
4705 uniform.binding, uniform.offset, uniform.type);
4712 case QRhiShaderResourceBinding::SampledTexture:
4718 if (maybeGraphicsPs) {
4719 ps = maybeGraphicsPs;
4722 ps = maybeComputePs;
4725 for (
int elem = 0; elem < b->u.stex.count; ++elem) {
4728 for (
const QGles2SamplerDescription &shaderSampler : samplers) {
4729 if (shaderSampler.combinedBinding == b->binding) {
4730 const int loc = shaderSampler.glslLocation + elem;
4731 bindCombinedSampler(cbD, texD, samplerD, ps, psGeneration, loc, &texUnit, &activeTexUnitAltered);
4738 case QRhiShaderResourceBinding::Texture:
4739 for (
int elem = 0; elem < b->u.stex.count; ++elem) {
4741 m_scratch.separateTextureBindings.append({ texD, b->binding, elem });
4744 case QRhiShaderResourceBinding::Sampler:
4747 m_scratch.separateSamplerBindings.append({ samplerD, b->binding });
4750 case QRhiShaderResourceBinding::ImageLoad:
4751 case QRhiShaderResourceBinding::ImageStore:
4752 case QRhiShaderResourceBinding::ImageLoadStore:
4755 Q_ASSERT(texD->m_flags.testFlag(QRhiTexture::UsedWithLoadStore));
4757 const bool layered = texD->m_flags.testFlag(QRhiTexture::CubeMap)
4758 || texD->m_flags.testFlag(QRhiTexture::ThreeDimensional)
4759 || texD->m_flags.testFlag(QRhiTexture::TextureArray);
4761 if (b->type == QRhiShaderResourceBinding::ImageLoad)
4763 else if (b->type == QRhiShaderResourceBinding::ImageStore)
4765 f->glBindImageTexture(GLuint(b->binding), texD->texture,
4766 b->u.simage.level, layered, 0,
4767 access, texD->glsizedintformat);
4770 case QRhiShaderResourceBinding::BufferLoad:
4771 case QRhiShaderResourceBinding::BufferStore:
4772 case QRhiShaderResourceBinding::BufferLoadStore:
4775 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer));
4776 if (b->u.sbuf.offset == 0 && b->u.sbuf.maybeSize == 0)
4780 b->u.sbuf.offset, b->u.sbuf.maybeSize ? b->u.sbuf.maybeSize : bufD->m_size);
4789 if (!m_scratch.separateTextureBindings.isEmpty() || !m_scratch.separateSamplerBindings.isEmpty()) {
4794 if (maybeGraphicsPs) {
4795 ps = maybeGraphicsPs;
4798 ps = maybeComputePs;
4801 for (
const QGles2SamplerDescription &shaderSampler : samplers) {
4802 if (shaderSampler.combinedBinding >= 0)
4804 for (
const Scratch::SeparateSampler &sepSampler : std::as_const(m_scratch.separateSamplerBindings)) {
4805 if (sepSampler.binding != shaderSampler.sbinding)
4807 for (
const Scratch::SeparateTexture &sepTex : std::as_const(m_scratch.separateTextureBindings)) {
4808 if (sepTex.binding != shaderSampler.tbinding)
4810 const int loc = shaderSampler.glslLocation + sepTex.elem;
4811 bindCombinedSampler(cbD, sepTex.texture, sepSampler.sampler, ps, psGeneration,
4812 loc, &texUnit, &activeTexUnitAltered);
4818 if (activeTexUnitAltered)
6373bool QGles2TextureRenderTarget::create()
6380 const bool hasColorAttachments = m_desc.colorAttachmentCount() > 0;
6381 Q_ASSERT(hasColorAttachments || m_desc.depthTexture());
6382 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
6383 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
6385 if (hasColorAttachments) {
6386 const int count =
int(m_desc.colorAttachmentCount());
6387 if (count > rhiD->caps.maxDrawBuffers) {
6388 qWarning(
"QGles2TextureRenderTarget: Too many color attachments (%d, max is %d)",
6389 count, rhiD->caps.maxDrawBuffers);
6392 if (m_desc.depthTexture() && !rhiD->caps.depthTexture)
6393 qWarning(
"QGles2TextureRenderTarget: Depth texture is not supported and will be ignored");
6395 if (!rhiD->ensureContext())
6398 rhiD->f->glGenFramebuffers(1, &framebuffer);
6399 rhiD->f->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6401 d.colorAttCount = 0;
6403 int multiViewCount = 0;
6404 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
6405 d.colorAttCount += 1;
6406 const QRhiColorAttachment &colorAtt(*it);
6407 QRhiTexture *texture = colorAtt.texture();
6408 QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer();
6409 Q_ASSERT(texture || renderBuffer);
6411 QGles2Texture *texD =
QRHI_RES(QGles2Texture, texture);
6412 Q_ASSERT(texD->texture && texD->specified);
6413 if (texD->flags().testFlag(QRhiTexture::ThreeDimensional) || texD->flags().testFlag(QRhiTexture::TextureArray)) {
6414 if (colorAtt.multiViewCount() < 2) {
6415 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture,
6416 colorAtt.level(), colorAtt.layer());
6418 multiViewCount = colorAtt.multiViewCount();
6419 if (texD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture && colorAtt.resolveTexture()) {
6424 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
6425 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6426 GL_COLOR_ATTACHMENT0 + uint(attIndex),
6427 resolveTexD->texture,
6428 colorAtt.resolveLevel(),
6430 colorAtt.resolveLayer(),
6433 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER,
6434 GL_COLOR_ATTACHMENT0 + uint(attIndex),
6441 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
6442 rhiD->glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex),
6443 texD->target + uint(colorAtt.layer()), texD->texture,
6446 if (texD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
6451 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
6453 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
6454 resolveTexD->texture, colorAtt.level(), texD->samples);
6457 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.layer()),
6458 texD->texture, colorAtt.level());
6461 if (attIndex == 0) {
6462 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
6463 d.sampleCount = texD->samples;
6465 }
else if (renderBuffer) {
6466 QGles2RenderBuffer *rbD =
QRHI_RES(QGles2RenderBuffer, renderBuffer);
6467 if (rbD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
6472 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
6474 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
6475 resolveTexD->texture, colorAtt.level(), rbD->samples);
6477 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), GL_RENDERBUFFER, rbD->renderbuffer);
6479 if (attIndex == 0) {
6480 d.pixelSize = rbD->pixelSize();
6481 d.sampleCount = rbD->samples;
6486 if (hasDepthStencil) {
6487 if (m_desc.depthStencilBuffer()) {
6488 QGles2RenderBuffer *depthRbD =
QRHI_RES(QGles2RenderBuffer, m_desc.depthStencilBuffer());
6489 if (rhiD->caps.needsDepthStencilCombinedAttach) {
6491 depthRbD->renderbuffer);
6493 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
6494 depthRbD->renderbuffer);
6495 if (depthRbD->stencilRenderbuffer) {
6496 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
6497 depthRbD->stencilRenderbuffer);
6500 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
6501 depthRbD->renderbuffer);
6504 if (d.colorAttCount == 0) {
6505 d.pixelSize = depthRbD->pixelSize();
6506 d.sampleCount = depthRbD->samples;
6509 QGles2Texture *depthTexD =
QRHI_RES(QGles2Texture, m_desc.depthTexture());
6510 if (multiViewCount < 2) {
6511 if (depthTexD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && m_desc.depthResolveTexture()) {
6515 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
6516 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthResolveTexD->target,
6517 depthResolveTexD->texture, 0, depthTexD->samples);
6518 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
6519 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthResolveTexD->target,
6520 depthResolveTexD->texture, 0, depthTexD->samples);
6522 }
else if (rhiD->caps.ctxMajor >= 3 && depthTexD->flags().testFlag(QRhiTexture::TextureArray) && m_desc.depthLayer() >= 0) {
6523 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
6524 0, m_desc.depthLayer());
6525 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
6526 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
6527 0, m_desc.depthLayer());
6530 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->target,
6531 depthTexD->texture, 0);
6532 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
6533 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->target,
6534 depthTexD->texture, 0);
6538 if (depthTexD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture) {
6556 if (!m_flags.testFlag(DoNotStoreDepthStencilContents) && !m_desc.depthResolveTexture()) {
6557 qWarning(
"Attempted to create a multiview+multisample QRhiTextureRenderTarget, but DoNotStoreDepthStencilContents was not set."
6558 " This path has no choice but to behave as if DoNotStoreDepthStencilContents was set, because QRhi is forced to create"
6559 " a throwaway non-multisample depth texture here. Set the flag to silence this warning, or set a depthResolveTexture.");
6561 if (m_desc.depthResolveTexture()) {
6562 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
6563 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6564 GL_DEPTH_ATTACHMENT,
6565 depthResolveTexD->texture,
6570 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
6571 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6572 GL_STENCIL_ATTACHMENT,
6573 depthResolveTexD->texture,
6580 if (!nonMsaaThrowawayDepthTexture) {
6581 rhiD->f->glGenTextures(1, &nonMsaaThrowawayDepthTexture);
6584 depthTexD->pixelSize().width(), depthTexD->pixelSize().height(), multiViewCount);
6586 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6587 GL_DEPTH_ATTACHMENT,
6588 nonMsaaThrowawayDepthTexture,
6593 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6594 GL_STENCIL_ATTACHMENT,
6595 nonMsaaThrowawayDepthTexture,
6605 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
6606 0, 0, multiViewCount);
6607 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
6608 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
6609 0, 0, multiViewCount);
6613 if (d.colorAttCount == 0) {
6614 d.pixelSize = depthTexD->pixelSize();
6615 d.sampleCount = depthTexD->samples;
6624 d.rp =
QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
6626 GLenum status = rhiD->f->glCheckFramebufferStatus(GL_FRAMEBUFFER);
6627 if (status != GL_NO_ERROR && status != GL_FRAMEBUFFER_COMPLETE) {
6628 qWarning(
"Framebuffer incomplete: 0x%x", status);
6632 if (rhiD->glObjectLabel)
6633 rhiD->glObjectLabel(GL_FRAMEBUFFER, framebuffer, -1, m_objectName.constData());
6635 QRhiRenderTargetAttachmentTracker::updateResIdList<QGles2Texture, QGles2RenderBuffer>(m_desc, &d.currentResIdList);
6637 rhiD->registerResource(
this);