776 Q_ASSERT(fallbackSurface);
780 ctx =
new QOpenGLContext;
781 ctx->setFormat(requestedFormat);
782 if (maybeShareContext) {
783 ctx->setShareContext(maybeShareContext);
785 ctx->setScreen(maybeWindow->screen());
787 ctx->setScreen(maybeShareContext->screen());
788 }
else if (QOpenGLContext *shareContext = QOpenGLContext::globalShareContext()) {
789 ctx->setShareContext(shareContext);
791 ctx->setScreen(maybeWindow->screen());
793 ctx->setScreen(shareContext->screen());
794 }
else if (maybeWindow) {
795 ctx->setScreen(maybeWindow->screen());
797 if (!ctx->create()) {
798 qWarning(
"QRhiGles2: Failed to create context");
803 qCDebug(QRHI_LOG_INFO) <<
"Created OpenGL context" << ctx->format();
806 if (!ensureContext(maybeWindow ? maybeWindow : fallbackSurface))
809 f =
static_cast<QOpenGLExtensions *>(ctx->extraFunctions());
810 const QSurfaceFormat actualFormat = ctx->format();
811 caps.gles = actualFormat.renderableType() == QSurfaceFormat::OpenGLES;
815 ctx->getProcAddress(QByteArrayLiteral(
"glPolygonMode")));
818 GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum,
const void *)>(
819 ctx->getProcAddress(QByteArrayLiteral(
"glTexImage1D")));
821 glTexStorage1D =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei)>(
822 ctx->getProcAddress(QByteArrayLiteral(
"glTexStorage1D")));
825 GLenum, GLint, GLint, GLsizei, GLenum, GLenum,
const GLvoid *)>(
826 ctx->getProcAddress(QByteArrayLiteral(
"glTexSubImage1D")));
828 glCopyTexSubImage1D =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint,
830 ctx->getProcAddress(QByteArrayLiteral(
"glCopyTexSubImage1D")));
833 GLenum, GLint, GLenum, GLsizei, GLint, GLsizei,
const GLvoid *)>(
834 ctx->getProcAddress(QByteArrayLiteral(
"glCompressedTexImage1D")));
837 GLenum, GLint, GLint, GLsizei, GLenum, GLsizei,
const GLvoid *)>(
838 ctx->getProcAddress(QByteArrayLiteral(
"glCompressedTexSubImage1D")));
840 glFramebufferTexture1D =
842 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture1D")));
845 const char *vendor =
reinterpret_cast<
const char *>(
f->glGetString(GL_VENDOR));
846 const char *renderer =
reinterpret_cast<
const char *>(
f->glGetString(GL_RENDERER));
847 const char *version =
reinterpret_cast<
const char *>(
f->glGetString(GL_VERSION));
848 if (vendor && renderer && version)
849 qCDebug(QRHI_LOG_INFO,
"OpenGL VENDOR: %s RENDERER: %s VERSION: %s", vendor, renderer, version);
852 driverInfoStruct.deviceName += QByteArray(vendor);
853 driverInfoStruct.deviceName +=
' ';
856 driverInfoStruct.deviceName += QByteArray(renderer);
857 driverInfoStruct.deviceName +=
' ';
860 driverInfoStruct.deviceName += QByteArray(version);
862 caps.ctxMajor = actualFormat.majorVersion();
863 caps.ctxMinor = actualFormat.minorVersion();
868 QVarLengthArray<GLint, 16> compressedTextureFormats(n);
870 for (GLint format : compressedTextureFormats)
871 supportedCompressedFormats.insert(format);
884 std::array<QRhiTexture::Flags, 2> textureVariantFlags;
885 textureVariantFlags[0] = {};
886 textureVariantFlags[1] = QRhiTexture::sRGB;
887 if (
f->hasOpenGLExtension(QOpenGLExtensions::DDSTextureCompression)) {
888 for (QRhiTexture::Flags f : textureVariantFlags) {
889 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC1, f));
890 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC2, f));
891 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC3, f));
894 if (
f->hasOpenGLExtension(QOpenGLExtensions::ETC2TextureCompression)) {
895 for (QRhiTexture::Flags f : textureVariantFlags) {
896 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8, f));
897 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8A1, f));
898 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGBA8, f));
901 if (
f->hasOpenGLExtension(QOpenGLExtensions::ASTCTextureCompression)) {
902 for (QRhiTexture::Flags f : textureVariantFlags) {
903 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_4x4, f));
904 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x4, f));
905 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x5, f));
906 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x5, f));
907 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x6, f));
908 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x5, f));
909 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x6, f));
910 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x8, f));
911 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x5, f));
912 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x8, f));
913 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x10, f));
914 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x10, f));
915 supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x12, f));
919 f->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.maxTextureSize);
921 if (!caps.gles || caps.ctxMajor >= 3) {
924 caps.hasDrawBuffersFunc =
true;
926 caps.maxSamples = qMax(1, caps.maxSamples);
929 caps.maxDrawBuffers = 1;
930 caps.hasDrawBuffersFunc =
false;
936 caps.msaaRenderBuffer = f->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
937 && f->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
939 caps.npotTextureFull = f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)
940 && f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
943 caps.fixedIndexPrimitiveRestart = caps.ctxMajor >= 3;
945 caps.fixedIndexPrimitiveRestart = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
947 if (caps.fixedIndexPrimitiveRestart) {
957 caps.bgraExternalFormat = f->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat);
958 caps.bgraInternalFormat = caps.bgraExternalFormat && caps.gles;
959 caps.r8Format = f->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats);
962 caps.r32uiFormat = (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1)) && caps.r8Format;
964 caps.r32uiFormat =
true;
966 caps.r16Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats);
967 caps.floatFormats = caps.ctxMajor >= 3;
968 caps.rgb10Formats = caps.ctxMajor >= 3;
969 caps.depthTexture = caps.ctxMajor >= 3;
970 caps.packedDepthStencil = f->hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil);
972 caps.needsDepthStencilCombinedAttach =
true;
974 caps.needsDepthStencilCombinedAttach =
false;
981 caps.srgbWriteControl = ctx->hasExtension(
"GL_EXT_framebuffer_sRGB") || ctx->hasExtension(
"GL_EXT_sRGB_write_control");
983 caps.coreProfile = actualFormat.profile() == QSurfaceFormat::CoreProfile;
986 caps.uniformBuffers = caps.ctxMajor >= 3;
988 caps.uniformBuffers = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
990 caps.elementIndexUint = f->hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint);
991 caps.depth24 = f->hasOpenGLExtension(QOpenGLExtensions::Depth24);
992 caps.rgba8Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized8Formats);
995 caps.instancing = caps.ctxMajor >= 3;
997 caps.instancing = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 3);
999 caps.baseVertex = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1002 caps.compute = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1004 caps.compute = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1012 caps.maxThreadGroupsPerDimension = qMin(tgPerDim[0], qMin(tgPerDim[1], tgPerDim[2]));
1019 caps.depthClamp =
false;
1021 caps.depthClamp = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1022 if (!caps.depthClamp)
1023 caps.depthClamp = ctx->hasExtension(
"GL_EXT_depth_clamp") || ctx->hasExtension(
"GL_ARB_depth_clamp");
1026 caps.textureCompareMode = caps.ctxMajor >= 3;
1028 caps.textureCompareMode =
true;
1032 caps.properMapBuffer = f->hasOpenGLExtension(QOpenGLExtensions::MapBufferRange);
1035 caps.nonBaseLevelFramebufferTexture = caps.ctxMajor >= 3;
1037 caps.nonBaseLevelFramebufferTexture =
true;
1039 caps.texelFetch = caps.ctxMajor >= 3;
1040 caps.intAttributes = caps.ctxMajor >= 3;
1041 caps.screenSpaceDerivatives = f->hasOpenGLExtension(QOpenGLExtensions::StandardDerivatives);
1044 caps.multisampledTexture = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 1);
1046 caps.multisampledTexture = caps.ctxMajor >= 3;
1051 caps.programBinary = caps.ctxMajor >= 3;
1053 caps.programBinary = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 1);
1055 if (caps.programBinary) {
1059 caps.programBinary =
false;
1062 caps.texture3D = caps.ctxMajor >= 3;
1065 caps.texture1D =
false;
1067 caps.texture1D = glTexImage1D && (caps.ctxMajor >= 2);
1070 caps.tessellation = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1072 caps.tessellation = caps.ctxMajor >= 4;
1075 caps.geometryShader = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1077 caps.geometryShader = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1079 if (caps.ctxMajor >= 3) {
1080 GLint maxArraySize = 0;
1082 caps.maxTextureArraySize = maxArraySize;
1084 caps.maxTextureArraySize = 0;
1091 GLint maxVertexUniformVectors = 0;
1093 GLint maxFragmentUniformVectors = 0;
1095 caps.maxUniformVectors = qMin(maxVertexUniformVectors, maxFragmentUniformVectors);
1097 GLint maxVertexUniformComponents = 0;
1099 GLint maxFragmentUniformComponents = 0;
1101 caps.maxUniformVectors = qMin(maxVertexUniformComponents, maxFragmentUniformComponents) / 4;
1104 f->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.maxVertexInputs);
1108 }
else if (caps.ctxMajor >= 3) {
1109 GLint components = 0;
1111 caps.maxVertexOutputs = components / 4;
1115 GLint components = 0;
1118 caps.maxVertexOutputs = components / 4;
1123 if (!caps.coreProfile)
1130 if (!caps.gles && (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2)))
1133 caps.halfAttributes = f->hasOpenGLExtension(QOpenGLExtensions::HalfFloatVertex);
1136 caps.multiView = f->hasOpenGLExtension(QOpenGLExtensions::MultiView)
1137 && f->hasOpenGLExtension(QOpenGLExtensions::MultiViewExtended);
1138 if (caps.multiView) {
1139 glFramebufferTextureMultiviewOVR =
1140 reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei)>(
1141 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultiviewOVR")));
1145 caps.timestamps = !caps.gles && (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 3));
1146 if (caps.timestamps) {
1148 ctx->getProcAddress(QByteArrayLiteral(
"glQueryCounter")));
1149 glGetQueryObjectui64v =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLuint, GLenum, quint64 *)>(
1150 ctx->getProcAddress(QByteArrayLiteral(
"glGetQueryObjectui64v")));
1151 if (!glQueryCounter || !glGetQueryObjectui64v)
1152 caps.timestamps =
false;
1157 caps.objectLabel = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1159 caps.objectLabel = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
1160 if (caps.objectLabel) {
1161 glObjectLabel =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLuint, GLsizei,
const GLchar *)>(
1162 ctx->getProcAddress(QByteArrayLiteral(
"glObjectLabel")));
1172 caps.glesMultisampleRenderToTexture = ctx->hasExtension(
"GL_EXT_multisampled_render_to_texture");
1173 if (caps.glesMultisampleRenderToTexture) {
1174 glFramebufferTexture2DMultisampleEXT =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei)>(
1175 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTexture2DMultisampleEXT")));
1176 glRenderbufferStorageMultisampleEXT =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLsizei, GLenum, GLsizei, GLsizei)>(
1177 ctx->getProcAddress(QByteArrayLiteral(
"glRenderbufferStorageMultisampleEXT")));
1179 caps.glesMultiviewMultisampleRenderToTexture = ctx->hasExtension(
"GL_OVR_multiview_multisampled_render_to_texture");
1180 if (caps.glesMultiviewMultisampleRenderToTexture) {
1181 glFramebufferTextureMultisampleMultiviewOVR =
reinterpret_cast<
void(
QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei)>(
1182 ctx->getProcAddress(QByteArrayLiteral(
"glFramebufferTextureMultisampleMultiviewOVR")));
1185 caps.glesMultisampleRenderToTexture =
false;
1186 caps.glesMultiviewMultisampleRenderToTexture =
false;
1189 caps.unpackRowLength = !caps.gles || caps.ctxMajor >= 3;
1192 caps.perRenderTargetBlending = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1194 caps.perRenderTargetBlending = caps.ctxMajor >= 4;
1197 if (caps.ctxMajor == 3 && caps.ctxMinor < 2) {
1198 caps.sampleVariables = ctx->hasExtension(
"GL_OES_sample_variables");
1200 caps.sampleVariables = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
1203 caps.sampleVariables = caps.ctxMajor >= 4;
1206 nativeHandlesStruct.context = ctx;
2549 int layer,
int level,
const QRhiTextureSubresourceUploadDescription &subresDesc)
2552 const bool isCompressed = isCompressedFormat(texD->m_format);
2553 const bool isCubeMap = texD->m_flags.testFlag(QRhiTexture::CubeMap);
2554 const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
2555 const bool is1D = texD->m_flags.testFlag(QRhiTexture::OneDimensional);
2556 const bool isArray = texD->m_flags.testFlag(QRhiTexture::TextureArray);
2558 const GLenum effectiveTarget = faceTargetBase + (isCubeMap ? uint(layer) : 0u);
2559 const QPoint dp = subresDesc.destinationTopLeft();
2560 const QByteArray rawData = subresDesc.data();
2562 auto setCmdByNotCompressedData = [&](
const void* data, QSize size, quint32 dataStride)
2564 quint32 bytesPerLine = 0;
2565 quint32 bytesPerPixel = 0;
2566 textureFormatInfo(texD->m_format, size, &bytesPerLine,
nullptr, &bytesPerPixel);
2570 cmd.args.subImage.target = texD->target;
2571 cmd.args.subImage.texture = texD->texture;
2572 cmd.args.subImage.faceTarget = effectiveTarget;
2573 cmd.args.subImage.level = level;
2574 cmd.args.subImage.dx = dp.x();
2575 cmd.args.subImage.dy = is1D && isArray ? layer : dp.y();
2576 cmd.args.subImage.dz = is3D || isArray ? layer : 0;
2577 cmd.args.subImage.w = size.width();
2578 cmd.args.subImage.h = size.height();
2579 cmd.args.subImage.glformat = texD->glformat;
2580 cmd.args.subImage.gltype = texD->gltype;
2582 if (dataStride == 0)
2583 dataStride = bytesPerLine;
2585 cmd.args.subImage.rowStartAlign = (dataStride & 3) ? 1 : 4;
2586 cmd.args.subImage.rowLength = caps.unpackRowLength ? (bytesPerPixel ? dataStride / bytesPerPixel : 0) : 0;
2588 cmd.args.subImage.data = data;
2591 if (!subresDesc.image().isNull()) {
2592 QImage img = subresDesc.image();
2593 QSize size = img.size();
2594 if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
2595 const QPoint sp = subresDesc.sourceTopLeft();
2596 if (!subresDesc.sourceSize().isEmpty())
2597 size = subresDesc.sourceSize();
2598 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2599 if (caps.unpackRowLength) {
2600 cbD->retainImage(img);
2602 const uchar *data = img.constBits() + sp.y() * img.bytesPerLine() + sp.x() * (qMax(1, img.depth() / 8));
2603 img = QImage(data, size.width(), size.height(), img.bytesPerLine(), img.format());
2605 img = img.copy(sp.x(), sp.y(), size.width(), size.height());
2608 size = clampedSubResourceUploadSize(size, dp, level, texD->m_pixelSize);
2611 setCmdByNotCompressedData(cbD->retainImage(img), size, img.bytesPerLine());
2612 }
else if (!rawData.isEmpty() && isCompressed) {
2613 const int depth = qMax(1, texD->m_depth);
2614 const int arraySize = qMax(0, texD->m_arraySize);
2615 if ((texD->flags().testFlag(QRhiTexture::UsedAsCompressedAtlas) || is3D || isArray)
2623 quint32 byteSize = 0;
2624 compressedFormatInfo(texD->m_format, texD->m_pixelSize,
nullptr, &byteSize,
nullptr);
2628 byteSize *= arraySize;
2629 QByteArray zeroBuf(byteSize, 0);
2632 cmd.args.compressedImage.target = texD->target;
2633 cmd.args.compressedImage.texture = texD->texture;
2634 cmd.args.compressedImage.faceTarget = effectiveTarget;
2635 cmd.args.compressedImage.level = level;
2636 cmd.args.compressedImage.glintformat = texD->glintformat;
2637 cmd.args.compressedImage.w = texD->m_pixelSize.width();
2638 cmd.args.compressedImage.h = is1D && isArray ? arraySize : texD->m_pixelSize.height();
2639 cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
2640 cmd.args.compressedImage.size = byteSize;
2641 cmd.args.compressedImage.data = cbD->retainData(zeroBuf);
2645 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2646 : subresDesc.sourceSize();
2650 cmd.args.compressedSubImage.target = texD->target;
2651 cmd.args.compressedSubImage.texture = texD->texture;
2652 cmd.args.compressedSubImage.faceTarget = effectiveTarget;
2653 cmd.args.compressedSubImage.level = level;
2654 cmd.args.compressedSubImage.dx = dp.x();
2655 cmd.args.compressedSubImage.dy = is1D && isArray ? layer : dp.y();
2656 cmd.args.compressedSubImage.dz = is3D || isArray ? layer : 0;
2657 cmd.args.compressedSubImage.w = size.width();
2658 cmd.args.compressedSubImage.h = size.height();
2659 cmd.args.compressedSubImage.glintformat = texD->glintformat;
2660 cmd.args.compressedSubImage.size = rawData.size();
2661 cmd.args.compressedSubImage.data = cbD->retainData(rawData);
2665 cmd.args.compressedImage.target = texD->target;
2666 cmd.args.compressedImage.texture = texD->texture;
2667 cmd.args.compressedImage.faceTarget = effectiveTarget;
2668 cmd.args.compressedImage.level = level;
2669 cmd.args.compressedImage.glintformat = texD->glintformat;
2670 cmd.args.compressedImage.w = size.width();
2671 cmd.args.compressedImage.h = is1D && isArray ? arraySize : size.height();
2672 cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
2673 cmd.args.compressedImage.size = rawData.size();
2674 cmd.args.compressedImage.data = cbD->retainData(rawData);
2676 }
else if (!rawData.isEmpty()) {
2677 const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
2678 : subresDesc.sourceSize();
2680 setCmdByNotCompressedData(cbD->retainData(rawData), size, subresDesc.dataStride());
2682 qWarning(
"Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
3219 for (
auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
3223 if (cmd.args.beginFrame.timestampQuery)
3225 if (caps.coreProfile) {
3227 f->glGenVertexArrays(1, &vao);
3228 f->glBindVertexArray(vao);
3235 f->glVertexAttribDivisor(GLuint(i), 0);
3238 f->glVertexAttribDivisor(GLuint(i), 0);
3242 for (
int i = 0; i < CommandBufferExecTrackedState::TRACKED_ATTRIB_COUNT; ++i) {
3243 if (state.enabledAttribArrays[i]) {
3244 f->glDisableVertexAttribArray(GLuint(i));
3245 state.enabledAttribArrays[i] =
false;
3250 f->glBindVertexArray(0);
3251 if (cmd.args.endFrame.timestampQuery)
3256 f->glBindVertexArray(vao);
3259 f->glViewport(GLint(cmd.args.viewport.x), GLint(cmd.args.viewport.y), GLsizei(cmd.args.viewport.w), GLsizei(cmd.args.viewport.h));
3260 f->glDepthRangef(cmd.args.viewport.d0, cmd.args.viewport.d1);
3263 f->glScissor(cmd.args.scissor.x, cmd.args.scissor.y, cmd.args.scissor.w, cmd.args.scissor.h);
3266 f->glBlendColor(cmd.args.blendConstants.r, cmd.args.blendConstants.g, cmd.args.blendConstants.b, cmd.args.blendConstants.a);
3272 const GLint ref = GLint(cmd.args.stencilRef.ref);
3273 f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), ref, psD->m_stencilReadMask);
3274 f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), ref, psD->m_stencilReadMask);
3275 cbD->graphicsPassState.dynamic.stencilRef = ref;
3277 qWarning(
"No graphics pipeline active for setStencilRef; ignored");
3285 if (state.lastBindVertexBuffer.ps == psD
3286 && state.lastBindVertexBuffer.buffer == cmd.args.bindVertexBuffer.buffer
3287 && state.lastBindVertexBuffer.offset == cmd.args.bindVertexBuffer.offset
3288 && state.lastBindVertexBuffer.binding == cmd.args.bindVertexBuffer.binding)
3295 state.lastBindVertexBuffer.ps = psD;
3296 state.lastBindVertexBuffer.buffer = cmd.args.bindVertexBuffer.buffer;
3297 state.lastBindVertexBuffer.offset = cmd.args.bindVertexBuffer.offset;
3298 state.lastBindVertexBuffer.binding = cmd.args.bindVertexBuffer.binding;
3300 if (cmd.args.bindVertexBuffer.buffer != state.currentArrayBuffer) {
3301 state.currentArrayBuffer = cmd.args.bindVertexBuffer.buffer;
3303 f->glBindBuffer(GL_ARRAY_BUFFER, state.currentArrayBuffer);
3305 for (
auto it = psD->m_vertexInputLayout.cbeginAttributes(), itEnd = psD->m_vertexInputLayout.cendAttributes();
3308 const int bindingIdx = it->binding();
3309 if (bindingIdx != cmd.args.bindVertexBuffer.binding)
3312 const QRhiVertexInputBinding *inputBinding = psD->m_vertexInputLayout.bindingAt(bindingIdx);
3313 const int stride =
int(inputBinding->stride());
3316 bool normalize =
false;
3317 switch (it->format()) {
3318 case QRhiVertexInputAttribute::Float4:
3322 case QRhiVertexInputAttribute::Float3:
3326 case QRhiVertexInputAttribute::Float2:
3330 case QRhiVertexInputAttribute::Float:
3334 case QRhiVertexInputAttribute::UNormByte4:
3339 case QRhiVertexInputAttribute::UNormByte2:
3344 case QRhiVertexInputAttribute::UNormByte:
3349 case QRhiVertexInputAttribute::UInt4:
3350 type = GL_UNSIGNED_INT;
3353 case QRhiVertexInputAttribute::UInt3:
3354 type = GL_UNSIGNED_INT;
3357 case QRhiVertexInputAttribute::UInt2:
3358 type = GL_UNSIGNED_INT;
3361 case QRhiVertexInputAttribute::UInt:
3362 type = GL_UNSIGNED_INT;
3365 case QRhiVertexInputAttribute::SInt4:
3369 case QRhiVertexInputAttribute::SInt3:
3373 case QRhiVertexInputAttribute::SInt2:
3377 case QRhiVertexInputAttribute::SInt:
3381 case QRhiVertexInputAttribute::Half4:
3385 case QRhiVertexInputAttribute::Half3:
3389 case QRhiVertexInputAttribute::Half2:
3393 case QRhiVertexInputAttribute::Half:
3397 case QRhiVertexInputAttribute::UShort4:
3398 type = GL_UNSIGNED_SHORT;
3401 case QRhiVertexInputAttribute::UShort3:
3402 type = GL_UNSIGNED_SHORT;
3405 case QRhiVertexInputAttribute::UShort2:
3406 type = GL_UNSIGNED_SHORT;
3409 case QRhiVertexInputAttribute::UShort:
3410 type = GL_UNSIGNED_SHORT;
3413 case QRhiVertexInputAttribute::SShort4:
3417 case QRhiVertexInputAttribute::SShort3:
3421 case QRhiVertexInputAttribute::SShort2:
3425 case QRhiVertexInputAttribute::SShort:
3433 const int locationIdx = it->location();
3434 quint32 ofs = it->offset() + cmd.args.bindVertexBuffer.offset;
3435 if (type == GL_UNSIGNED_INT || type == GL_INT) {
3436 if (caps.intAttributes) {
3437 f->glVertexAttribIPointer(GLuint(locationIdx), size, type, stride,
3438 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3440 qWarning(
"Current RHI backend does not support IntAttributes. Check supported features.");
3446 f->glVertexAttribPointer(GLuint(locationIdx), size, type, normalize, stride,
3447 reinterpret_cast<
const GLvoid *>(quintptr(ofs)));
3452 f->glEnableVertexAttribArray(GLuint(locationIdx));
3454 if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance && caps.instancing) {
3455 f->glVertexAttribDivisor(GLuint(locationIdx), inputBinding->instanceStepRate());
3466 f->glVertexAttribDivisor(GLuint(locationIdx), 0);
3472 qWarning(
"No graphics pipeline active for setVertexInput; ignored");
3477 state.indexType = cmd.args.bindIndexBuffer.type;
3478 state.indexStride = state.indexType == GL_UNSIGNED_SHORT ?
sizeof(quint16) :
sizeof(quint32);
3479 state.indexOffset = cmd.args.bindIndexBuffer.offset;
3480 if (state.currentElementArrayBuffer != cmd.args.bindIndexBuffer.buffer) {
3481 state.currentElementArrayBuffer = cmd.args.bindIndexBuffer.buffer;
3482 f->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state.currentElementArrayBuffer);
3489 if (cmd.args.draw.instanceCount == 1 || !caps.instancing) {
3490 f->glDrawArrays(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount));
3492 f->glDrawArraysInstanced(psD->drawMode, GLint(cmd.args.draw.firstVertex), GLsizei(cmd.args.draw.vertexCount),
3493 GLsizei(cmd.args.draw.instanceCount));
3496 qWarning(
"No graphics pipeline active for draw; ignored");
3504 const GLvoid *ofs =
reinterpret_cast<
const GLvoid *>(
3505 quintptr(cmd.args.drawIndexed.firstIndex * state.indexStride + state.indexOffset));
3506 if (cmd.args.drawIndexed.instanceCount == 1 || !caps.instancing) {
3507 if (cmd.args.drawIndexed.baseVertex != 0 && caps.baseVertex) {
3508 f->glDrawElementsBaseVertex(psD->drawMode,
3509 GLsizei(cmd.args.drawIndexed.indexCount),
3512 cmd.args.drawIndexed.baseVertex);
3514 f->glDrawElements(psD->drawMode,
3515 GLsizei(cmd.args.drawIndexed.indexCount),
3520 if (cmd.args.drawIndexed.baseVertex != 0 && caps.baseVertex) {
3521 f->glDrawElementsInstancedBaseVertex(psD->drawMode,
3522 GLsizei(cmd.args.drawIndexed.indexCount),
3525 GLsizei(cmd.args.drawIndexed.instanceCount),
3526 cmd.args.drawIndexed.baseVertex);
3528 f->glDrawElementsInstanced(psD->drawMode,
3529 GLsizei(cmd.args.drawIndexed.indexCount),
3532 GLsizei(cmd.args.drawIndexed.instanceCount));
3536 qWarning(
"No graphics pipeline active for drawIndexed; ignored");
3543 case QGles2CommandBuffer::Command::BindShaderResources:
3544 bindShaderResources(cbD,
3545 cmd.args.bindShaderResources.maybeGraphicsPs,
3546 cmd.args.bindShaderResources.maybeComputePs,
3547 cmd.args.bindShaderResources.srb,
3548 cmd.args.bindShaderResources.dynamicOffsetPairs,
3549 cmd.args.bindShaderResources.dynamicOffsetCount);
3553 QVarLengthArray<GLenum, 8> bufs;
3554 GLuint fbo = cmd.args.bindFramebuffer.fbo;
3556 fbo = ctx->defaultFramebufferObject();
3557 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3559 const int colorAttCount = cmd.args.bindFramebuffer.colorAttCount;
3560 bufs.append(colorAttCount > 0 ? GL_COLOR_ATTACHMENT0 : GL_NONE);
3561 if (caps.maxDrawBuffers > 1) {
3562 for (
int i = 1; i < colorAttCount; ++i)
3563 bufs.append(GL_COLOR_ATTACHMENT0 + uint(i));
3566 if (cmd.args.bindFramebuffer.stereo && cmd.args.bindFramebuffer.stereoTarget == QRhiSwapChain::RightBuffer)
3571 if (caps.hasDrawBuffersFunc)
3572 f->glDrawBuffers(bufs.count(), bufs.constData());
3573 if (caps.srgbWriteControl) {
3574 if (cmd.args.bindFramebuffer.srgb)
3582 f->glDisable(GL_SCISSOR_TEST);
3583 if (cmd.args.clear.mask & GL_COLOR_BUFFER_BIT) {
3584 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3585 f->glClearColor(cmd.args.clear.c[0], cmd.args.clear.c[1], cmd.args.clear.c[2], cmd.args.clear.c[3]);
3587 if (cmd.args.clear.mask & GL_DEPTH_BUFFER_BIT) {
3588 f->glDepthMask(GL_TRUE);
3589 f->glClearDepthf(cmd.args.clear.d);
3591 if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT) {
3592 f->glStencilMask(0xFF);
3593 f->glClearStencil(GLint(cmd.args.clear.s));
3595 f->glClear(cmd.args.clear.mask);
3596 cbD->graphicsPassState.reset();
3599 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.bufferSubData.target, cmd.args.bufferSubData.buffer);
3600 f->glBufferSubData(cmd.args.bufferSubData.target, cmd.args.bufferSubData.offset, cmd.args.bufferSubData.size,
3601 cmd.args.bufferSubData.data);
3605 QRhiReadbackResult *result = cmd.args.getBufferSubData.result;
3606 bindVertexIndexBufferWithStateReset(&state,
f, cmd.args.getBufferSubData.target, cmd.args.getBufferSubData.buffer);
3608 if (caps.properMapBuffer) {
3609 void *p =
f->glMapBufferRange(cmd.args.getBufferSubData.target,
3610 cmd.args.getBufferSubData.offset,
3611 cmd.args.getBufferSubData.size,
3614 result->data.resize(cmd.args.getBufferSubData.size);
3615 memcpy(result->data.data(), p, size_t(cmd.args.getBufferSubData.size));
3616 f->glUnmapBuffer(cmd.args.getBufferSubData.target);
3620 result->data.resize(cmd.args.getBufferSubData.size);
3621 f->glGetBufferSubData(cmd.args.getBufferSubData.target,
3622 cmd.args.getBufferSubData.offset,
3623 cmd.args.getBufferSubData.size,
3624 result->data.data());
3626 if (result->completed)
3627 result->completed();
3633 f->glGenFramebuffers(1, &fbo);
3634 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3638 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.copyTex.srcTexture,
3639 cmd.args.copyTex.srcLevel, cmd.args.copyTex.srcZ);
3642 cmd.args.copyTex.srcTarget, cmd.args.copyTex.srcTexture,
3643 cmd.args.copyTex.srcLevel);
3645 f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
3646 cmd.args.copyTex.srcFaceTarget, cmd.args.copyTex.srcTexture, cmd.args.copyTex.srcLevel);
3648 f->glBindTexture(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstTexture);
3650 f->glCopyTexSubImage3D(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstLevel,
3651 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY, cmd.args.copyTex.dstZ,
3652 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
3653 cmd.args.copyTex.w, cmd.args.copyTex.h);
3656 cmd.args.copyTex.dstX
, cmd.args.copyTex.srcX
,
3657 cmd.args.copyTex.srcY
, cmd.args.copyTex.w
);
3659 f->glCopyTexSubImage2D(cmd.args.copyTex.dstFaceTarget, cmd.args.copyTex.dstLevel,
3660 cmd.args.copyTex.dstX, cmd.args.copyTex.dstY,
3661 cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
3662 cmd.args.copyTex.w, cmd.args.copyTex.h);
3664 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
3665 f->glDeleteFramebuffers(1, &fbo);
3670 QRhiReadbackResult *result = cmd.args.readPixels.result;
3671 GLuint tex = cmd.args.readPixels.texture;
3674 result->pixelSize = QSize(cmd.args.readPixels.w, cmd.args.readPixels.h);
3676 result->format = cmd.args.readPixels.format;
3677 mipLevel = cmd.args.readPixels.level;
3678 if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
3679 f->glGenFramebuffers(1, &fbo);
3680 f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3681 if (cmd.args.readPixels.slice3D >= 0) {
3682 f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
3683 tex, mipLevel, cmd.args.readPixels.slice3D);
3684 }
else if (cmd.args.readPixels.readTarget ==
GL_TEXTURE_1D) {
3686 cmd.args.readPixels.readTarget, tex, mipLevel);
3688 f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
3689 cmd.args.readPixels.readTarget, tex, mipLevel);
3693 result->format = QRhiTexture::RGBA8;
3696 const int x = cmd.args.readPixels.x;
3697 const int y = cmd.args.readPixels.y;
3698 const int w = cmd.args.readPixels.w;
3699 const int h = cmd.args.readPixels.h;
3700 if (mipLevel == 0 || caps.nonBaseLevelFramebufferTexture) {
3703 if (result->format == QRhiTexture::R8 || result->format == QRhiTexture::RED_OR_ALPHA8) {
3704 result->data.resizeForOverwrite(w * h);
3706 tmpBuf.resizeForOverwrite(w * h * 4);
3708 const quint8 *srcBase =
reinterpret_cast<
const quint8 *>(tmpBuf.constData());
3709 quint8 *dstBase =
reinterpret_cast<quint8 *>(result->data.data());
3710 const int componentIndex = isFeatureSupported(QRhi::RedOrAlpha8IsRed) ? 0 : 3;
3711 for (
int y = 0; y < h; ++y) {
3712 const quint8 *src = srcBase + y * w * 4;
3713 quint8 *dst = dstBase + y * w;
3715 while (count-- > 0) {
3716 *dst++ = src[componentIndex];
3723 [[maybe_unused]] GLenum glintformat;
3724 [[maybe_unused]] GLenum glsizedintformat;
3727 toGlTextureFormat(result->format, caps, &glintformat, &glsizedintformat, &glformat, &gltype);
3729 textureFormatInfo(result->format, result->pixelSize,
nullptr, &byteSize,
nullptr);
3730 result->data.resizeForOverwrite(byteSize);
3731 f->glReadPixels(x, y, w, h, glformat, gltype, result->data.data());
3734 result->data.resizeForOverwrite(w * h * 4);
3735 result->data.fill(
'\0');
3738 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
3739 f->glDeleteFramebuffers(1, &fbo);
3741 if (result->completed)
3742 result->completed();
3746 f->glBindTexture(cmd.args.subImage.target, cmd.args.subImage.texture);
3747 if (cmd.args.subImage.rowStartAlign != 4)
3748 f->glPixelStorei(GL_UNPACK_ALIGNMENT, cmd.args.subImage.rowStartAlign);
3749 if (cmd.args.subImage.rowLength != 0)
3752 f->glTexSubImage3D(cmd.args.subImage.target, cmd.args.subImage.level,
3753 cmd.args.subImage.dx, cmd.args.subImage.dy, cmd.args.subImage.dz,
3754 cmd.args.subImage.w, cmd.args.subImage.h, 1,
3755 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
3756 cmd.args.subImage.data);
3759 cmd.args.subImage.dx
, cmd.args.subImage.w
,
3760 cmd.args.subImage.glformat
, cmd.args.subImage.gltype
,
3761 cmd.args.subImage.data
);
3763 f->glTexSubImage2D(cmd.args.subImage.faceTarget, cmd.args.subImage.level,
3764 cmd.args.subImage.dx, cmd.args.subImage.dy,
3765 cmd.args.subImage.w, cmd.args.subImage.h,
3766 cmd.args.subImage.glformat, cmd.args.subImage.gltype,
3767 cmd.args.subImage.data);
3769 if (cmd.args.subImage.rowStartAlign != 4)
3770 f->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
3771 if (cmd.args.subImage.rowLength != 0)
3775 f->glBindTexture(cmd.args.compressedImage.target, cmd.args.compressedImage.texture);
3777 f->glCompressedTexImage3D(cmd.args.compressedImage.target, cmd.args.compressedImage.level,
3778 cmd.args.compressedImage.glintformat,
3779 cmd.args.compressedImage.w, cmd.args.compressedImage.h, cmd.args.compressedImage.depth,
3780 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
3781 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
3783 cmd.args.compressedImage.target
, cmd.args.compressedImage.level
,
3784 cmd.args.compressedImage.glintformat
, cmd.args.compressedImage.w
, 0
,
3785 cmd.args.compressedImage.size
, cmd.args.compressedImage.data
);
3787 f->glCompressedTexImage2D(cmd.args.compressedImage.faceTarget, cmd.args.compressedImage.level,
3788 cmd.args.compressedImage.glintformat,
3789 cmd.args.compressedImage.w, cmd.args.compressedImage.h,
3790 0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
3794 f->glBindTexture(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.texture);
3796 f->glCompressedTexSubImage3D(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.level,
3797 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy, cmd.args.compressedSubImage.dz,
3798 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h, 1,
3799 cmd.args.compressedSubImage.glintformat,
3800 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
3801 }
else if (cmd.args.compressedImage.target ==
GL_TEXTURE_1D) {
3803 cmd.args.compressedSubImage.target
, cmd.args.compressedSubImage.level
,
3804 cmd.args.compressedSubImage.dx
, cmd.args.compressedSubImage.w
,
3805 cmd.args.compressedSubImage.glintformat
, cmd.args.compressedSubImage.size
,
3806 cmd.args.compressedSubImage.data
);
3808 f->glCompressedTexSubImage2D(cmd.args.compressedSubImage.faceTarget, cmd.args.compressedSubImage.level,
3809 cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy,
3810 cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h,
3811 cmd.args.compressedSubImage.glintformat,
3812 cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
3819 cbD->graphicsPassState.reset();
3820 f->glDisable(GL_SCISSOR_TEST);
3822 f->glGenFramebuffers(2, fbo);
3824 const bool ds = cmd.args.blitFromRenderbuffer.isDepthStencil;
3827 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
3829 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
3832 GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
3838 cmd.args.blitFromRenderbuffer.dstTexture,
3839 cmd.args.blitFromRenderbuffer.dstLevel,
3840 cmd.args.blitFromRenderbuffer.dstLayer);
3842 cmd.args.blitFromRenderbuffer.dstTexture,
3843 cmd.args.blitFromRenderbuffer.dstLevel,
3844 cmd.args.blitFromRenderbuffer.dstLayer);
3847 cmd.args.blitFromRenderbuffer.dstTexture,
3848 cmd.args.blitFromRenderbuffer.dstLevel,
3849 cmd.args.blitFromRenderbuffer.dstLayer);
3853 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
3854 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
3855 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
3856 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
3858 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromRenderbuffer.target,
3859 cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
3862 f->glBlitFramebuffer(0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
3863 0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
3864 ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT,
3866 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
3867 f->glDeleteFramebuffers(2, fbo);
3874 cbD->graphicsPassState.reset();
3875 f->glDisable(GL_SCISSOR_TEST);
3877 f->glGenFramebuffers(2, fbo);
3879 const bool ds = cmd.args.blitFromTexture.isDepthStencil;
3883 cmd.args.blitFromTexture.srcTexture,
3884 cmd.args.blitFromTexture.srcLevel,
3885 cmd.args.blitFromTexture.srcLayer);
3887 cmd.args.blitFromTexture.srcTexture,
3888 cmd.args.blitFromTexture.srcLevel,
3889 cmd.args.blitFromTexture.srcLayer);
3892 cmd.args.blitFromTexture.srcTexture,
3893 cmd.args.blitFromTexture.srcLevel,
3894 cmd.args.blitFromTexture.srcLayer);
3898 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
3899 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
3900 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
3901 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
3903 f->glFramebufferTexture2D(
GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.srcTarget,
3904 cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
3911 cmd.args.blitFromTexture.dstTexture,
3912 cmd.args.blitFromTexture.dstLevel,
3913 cmd.args.blitFromTexture.dstLayer);
3915 cmd.args.blitFromTexture.dstTexture,
3916 cmd.args.blitFromTexture.dstLevel,
3917 cmd.args.blitFromTexture.dstLayer);
3920 cmd.args.blitFromTexture.dstTexture,
3921 cmd.args.blitFromTexture.dstLevel,
3922 cmd.args.blitFromTexture.dstLayer);
3926 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
3927 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
3928 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
3929 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
3931 f->glFramebufferTexture2D(
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.dstTarget,
3932 cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
3935 f->glBlitFramebuffer(0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
3936 0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
3937 ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT,
3939 f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
3940 f->glDeleteFramebuffers(2, fbo);
3944 f->glBindTexture(cmd.args.genMip.target, cmd.args.genMip.texture);
3945 f->glGenerateMipmap(cmd.args.genMip.target);
3950 f->glUseProgram(psD->program);
3954 f->glDispatchCompute(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
3960 GLbitfield barriers = 0;
3969 for (
const auto &[rhiB, trackedB]: tracker.buffers()) {
3971 QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(trackedB.stateAtPassBegin.access);
3972 if (bufferAccessIsWrite(accessBeforePass))
3973 barriers |= barriersForBuffer();
3975 for (
const auto &[rhiT, trackedT]: tracker.textures()) {
3977 QGles2Texture::Access accessBeforePass = QGles2Texture::Access(trackedT.stateAtPassBegin.access);
3978 if (textureAccessIsWrite(accessBeforePass))
3979 barriers |= barriersForTexture();
3982 f->glMemoryBarrier(barriers);
3987 f->glMemoryBarrier(cmd.args.barrier.barriers);
3990 if (caps.gles && caps.ctxMajor >= 3) {
3991 f->glBindFramebuffer(GL_FRAMEBUFFER, cmd.args.invalidateFramebuffer.fbo);
3993 cmd.args.invalidateFramebuffer.attCount,
3994 cmd.args.invalidateFramebuffer.att);
4004 f->glVertexAttribDivisor(GLuint(i), 0);
4007 f->glVertexAttribDivisor(GLuint(i), 0);
4014 const bool forceUpdate = !state
.valid;
4017 const bool scissor = psD->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor);
4018 if (forceUpdate || scissor != state
.scissor) {
4021 f->glEnable(GL_SCISSOR_TEST);
4023 f->glDisable(GL_SCISSOR_TEST);
4026 const bool cullFace = psD->m_cullMode != QRhiGraphicsPipeline::None;
4027 const GLenum cullMode = cullFace ? toGlCullMode(psD->m_cullMode) : GL_NONE;
4028 if (forceUpdate || cullFace != state
.cullFace || cullMode != state.cullMode) {
4030 state.cullMode = cullMode;
4032 f->glEnable(GL_CULL_FACE);
4033 f->glCullFace(cullMode);
4035 f->glDisable(GL_CULL_FACE);
4039 const GLenum frontFace = toGlFrontFace(psD->m_frontFace);
4040 if (forceUpdate || frontFace != state.frontFace) {
4041 state.frontFace = frontFace;
4042 f->glFrontFace(frontFace);
4045 const GLenum polygonMode = toGlPolygonMode(psD->m_polygonMode);
4046 if (
glPolygonMode && (forceUpdate || polygonMode != state.polygonMode)) {
4047 state.polygonMode = polygonMode;
4051 if (!psD->m_targetBlends.isEmpty()) {
4053 bool anyBlendEnabled =
false;
4054 for (
const auto targetBlend : psD->m_targetBlends) {
4055 const QGles2CommandBuffer::GraphicsPassState::ColorMask colorMask = {
4056 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::R),
4057 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::G),
4058 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::B),
4059 targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::A)
4061 if (forceUpdate || colorMask != state.colorMask[buffer]) {
4062 state.colorMask[buffer] = colorMask;
4063 if (caps.perRenderTargetBlending)
4064 f->glColorMaski(buffer, colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4066 f->glColorMask(colorMask.r, colorMask.g, colorMask.b, colorMask.a);
4069 const bool blendEnabled = targetBlend.enable;
4070 const QGles2CommandBuffer::GraphicsPassState::Blend blend = {
4071 toGlBlendFactor(targetBlend.srcColor),
4072 toGlBlendFactor(targetBlend.dstColor),
4073 toGlBlendFactor(targetBlend.srcAlpha),
4074 toGlBlendFactor(targetBlend.dstAlpha),
4075 toGlBlendOp(targetBlend.opColor),
4076 toGlBlendOp(targetBlend.opAlpha)
4078 anyBlendEnabled |= blendEnabled;
4079 if (forceUpdate || blendEnabled != state.blendEnabled[buffer] || (blendEnabled && blend != state.blend[buffer])) {
4080 state.blendEnabled[buffer] = blendEnabled;
4082 state.blend[buffer] = blend;
4083 if (caps.perRenderTargetBlending) {
4084 f->glBlendFuncSeparatei(buffer, blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4085 f->glBlendEquationSeparatei(buffer, blend.opColor, blend.opAlpha);
4087 f->glBlendFuncSeparate(blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha);
4088 f->glBlendEquationSeparate(blend.opColor, blend.opAlpha);
4093 if (!caps.perRenderTargetBlending)
4096 if (anyBlendEnabled)
4097 f->glEnable(GL_BLEND);
4099 f->glDisable(GL_BLEND);
4102 if (forceUpdate || colorMask
!= state.colorMask[0]) {
4103 state.colorMask[0] = colorMask;
4104 f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4106 const bool blendEnabled =
false;
4109 f->glDisable(GL_BLEND);
4113 const bool depthTest = psD->m_depthTest;
4114 if (forceUpdate || depthTest != state
.depthTest) {
4117 f->glEnable(GL_DEPTH_TEST);
4119 f->glDisable(GL_DEPTH_TEST);
4122 const bool depthWrite = psD->m_depthWrite;
4123 if (forceUpdate || depthWrite != state
.depthWrite) {
4125 f->glDepthMask(depthWrite);
4128 const bool depthClamp = psD->m_depthClamp;
4129 if (caps.depthClamp && (forceUpdate || depthClamp != state.depthClamp)) {
4137 const GLenum depthFunc = toGlCompareOp(psD->m_depthOp);
4138 if (forceUpdate || depthFunc != state.depthFunc) {
4139 state.depthFunc = depthFunc;
4140 f->glDepthFunc(depthFunc);
4143 const bool stencilTest = psD->m_stencilTest;
4144 const GLuint stencilReadMask = psD->m_stencilReadMask;
4145 const GLuint stencilWriteMask = psD->m_stencilWriteMask;
4147 toGlCompareOp(psD->m_stencilFront.compareOp),
4148 toGlStencilOp(psD->m_stencilFront.failOp),
4149 toGlStencilOp(psD->m_stencilFront.depthFailOp),
4150 toGlStencilOp(psD->m_stencilFront.passOp)
4153 toGlCompareOp(psD->m_stencilBack.compareOp),
4154 toGlStencilOp(psD->m_stencilBack.failOp),
4155 toGlStencilOp(psD->m_stencilBack.depthFailOp),
4156 toGlStencilOp(psD->m_stencilBack.passOp)
4160 && (stencilReadMask != state.stencilReadMask || stencilWriteMask != state.stencilWriteMask
4161 || stencilFront != state.stencil[0] || stencilBack != state.stencil[1])))
4165 state.stencilReadMask = stencilReadMask;
4166 state.stencilWriteMask = stencilWriteMask;
4167 state.stencil[0] = stencilFront;
4168 state.stencil[1] = stencilBack;
4170 f->glEnable(GL_STENCIL_TEST);
4172 f->glStencilFuncSeparate(GL_FRONT, stencilFront.func, state.dynamic.stencilRef, stencilReadMask);
4173 f->glStencilOpSeparate(GL_FRONT, stencilFront.failOp, stencilFront.zfailOp, stencilFront.zpassOp);
4174 f->glStencilMaskSeparate(GL_FRONT, stencilWriteMask);
4176 f->glStencilFuncSeparate(GL_BACK, stencilBack.func, state.dynamic.stencilRef, stencilReadMask);
4177 f->glStencilOpSeparate(GL_BACK, stencilBack.failOp, stencilBack.zfailOp, stencilBack.zpassOp);
4178 f->glStencilMaskSeparate(GL_BACK, stencilWriteMask);
4180 f->glDisable(GL_STENCIL_TEST);
4184 const bool polyOffsetFill = psD->m_depthBias != 0 || !qFuzzyIsNull(psD->m_slopeScaledDepthBias);
4185 const float polyOffsetFactor = psD->m_slopeScaledDepthBias;
4186 const float polyOffsetUnits = psD->m_depthBias;
4193 if (polyOffsetFill) {
4194 f->glPolygonOffset(polyOffsetFactor, polyOffsetUnits);
4195 f->glEnable(GL_POLYGON_OFFSET_FILL);
4197 f->glDisable(GL_POLYGON_OFFSET_FILL);
4201 if (psD->m_topology == QRhiGraphicsPipeline::Lines || psD->m_topology == QRhiGraphicsPipeline::LineStrip) {
4202 const float lineWidth = psD->m_lineWidth;
4203 if (forceUpdate || lineWidth != state
.lineWidth) {
4205 f->glLineWidth(lineWidth);
4209 if (psD->m_topology == QRhiGraphicsPipeline::Patches) {
4210 const int cpCount = psD->m_patchControlPointCount;
4211 if (forceUpdate || cpCount != state
.cpCount) {
4217 f->glUseProgram(psD->program);
4285 QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs,
4286 QRhiShaderResourceBindings *srb,
4287 const uint *dynOfsPairs,
int dynOfsCount)
4291 bool activeTexUnitAltered =
false;
4296 m_scratch.separateTextureBindings.clear();
4297 m_scratch.separateSamplerBindings.clear();
4299 for (
int i = 0, ie = srbD->m_bindings.size(); i != ie; ++i) {
4300 const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->m_bindings.at(i));
4303 case QRhiShaderResourceBinding::UniformBuffer:
4305 int viewOffset = b->u.ubuf.offset;
4306 for (
int j = 0; j < dynOfsCount; ++j) {
4307 if (dynOfsPairs[2 * j] == uint(b->binding)) {
4308 viewOffset =
int(dynOfsPairs[2 * j + 1]);
4313 const char *bufView = bufD->data.constData() + viewOffset;
4314 for (
const QGles2UniformDescription &uniform : std::as_const(uniforms)) {
4315 if (uniform.binding == b->binding) {
4318 const void *src = bufView + uniform.offset;
4321 if (uniform.arrayDim > 0
4322 && uniform.type != QShaderDescription::Float
4323 && uniform.type != QShaderDescription::Vec2
4324 && uniform.type != QShaderDescription::Vec3
4325 && uniform.type != QShaderDescription::Vec4
4326 && uniform.type != QShaderDescription::Int
4327 && uniform.type != QShaderDescription::Int2
4328 && uniform.type != QShaderDescription::Int3
4329 && uniform.type != QShaderDescription::Int4
4330 && uniform.type != QShaderDescription::Mat3
4331 && uniform.type != QShaderDescription::Mat4)
4333 qWarning(
"Uniform with buffer binding %d, buffer offset %d, type %d is an array, "
4334 "but arrays are only supported for float, vec2, vec3, vec4, int, "
4335 "ivec2, ivec3, ivec4, mat3 and mat4. "
4336 "Only the first element will be set.",
4337 uniform.binding, uniform.offset, uniform.type);
4347 switch (uniform.type) {
4348 case QShaderDescription::Float:
4350 const int elemCount = uniform.arrayDim;
4351 if (elemCount < 1) {
4352 const float v = *
reinterpret_cast<
const float *>(src);
4353 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4354 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4355 if (thisUniformState.componentCount != 1 || thisUniformState.v[0] != v) {
4356 thisUniformState.componentCount = 1;
4357 thisUniformState.v[0] = v;
4358 f->glUniform1f(uniform.glslLocation, v);
4361 f->glUniform1f(uniform.glslLocation, v);
4365 m_scratch.packedArray.resize(elemCount);
4366 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 1, elemCount, src);
4367 f->glUniform1fv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->f);
4371 case QShaderDescription::Vec2:
4373 const int elemCount = uniform.arrayDim;
4374 if (elemCount < 1) {
4375 const float *v =
reinterpret_cast<
const float *>(src);
4376 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4377 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4378 if (thisUniformState.componentCount != 2
4379 || thisUniformState.v[0] != v[0]
4380 || thisUniformState.v[1] != v[1])
4382 thisUniformState.componentCount = 2;
4383 thisUniformState.v[0] = v[0];
4384 thisUniformState.v[1] = v[1];
4385 f->glUniform2fv(uniform.glslLocation, 1, v);
4388 f->glUniform2fv(uniform.glslLocation, 1, v);
4391 m_scratch.packedArray.resize(elemCount * 2);
4392 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 2, elemCount, src);
4393 f->glUniform2fv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->f);
4397 case QShaderDescription::Vec3:
4399 const int elemCount = uniform.arrayDim;
4400 if (elemCount < 1) {
4401 const float *v =
reinterpret_cast<
const float *>(src);
4402 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4403 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4404 if (thisUniformState.componentCount != 3
4405 || thisUniformState.v[0] != v[0]
4406 || thisUniformState.v[1] != v[1]
4407 || thisUniformState.v[2] != v[2])
4409 thisUniformState.componentCount = 3;
4410 thisUniformState.v[0] = v[0];
4411 thisUniformState.v[1] = v[1];
4412 thisUniformState.v[2] = v[2];
4413 f->glUniform3fv(uniform.glslLocation, 1, v);
4416 f->glUniform3fv(uniform.glslLocation, 1, v);
4419 m_scratch.packedArray.resize(elemCount * 3);
4420 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 3, elemCount, src);
4421 f->glUniform3fv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->f);
4425 case QShaderDescription::Vec4:
4427 const int elemCount = uniform.arrayDim;
4428 if (elemCount < 1) {
4429 const float *v =
reinterpret_cast<
const float *>(src);
4430 if (uniform.glslLocation <= QGles2UniformState::MAX_TRACKED_LOCATION) {
4431 QGles2UniformState &thisUniformState(uniformState[uniform.glslLocation]);
4432 if (thisUniformState.componentCount != 4
4433 || thisUniformState.v[0] != v[0]
4434 || thisUniformState.v[1] != v[1]
4435 || thisUniformState.v[2] != v[2]
4436 || thisUniformState.v[3] != v[3])
4438 thisUniformState.componentCount = 4;
4439 thisUniformState.v[0] = v[0];
4440 thisUniformState.v[1] = v[1];
4441 thisUniformState.v[2] = v[2];
4442 thisUniformState.v[3] = v[3];
4443 f->glUniform4fv(uniform.glslLocation, 1, v);
4446 f->glUniform4fv(uniform.glslLocation, 1, v);
4449 f->glUniform4fv(uniform.glslLocation, elemCount,
reinterpret_cast<
const float *>(src));
4453 case QShaderDescription::Mat2:
4454 f->glUniformMatrix2fv(uniform.glslLocation, 1, GL_FALSE,
reinterpret_cast<
const float *>(src));
4456 case QShaderDescription::Mat3:
4458 const int elemCount = uniform.arrayDim;
4459 if (elemCount < 1) {
4462 const float *srcMat =
reinterpret_cast<
const float *>(src);
4463 memcpy(mat, srcMat, 3 *
sizeof(
float));
4464 memcpy(mat + 3, srcMat + 4, 3 *
sizeof(
float));
4465 memcpy(mat + 6, srcMat + 8, 3 *
sizeof(
float));
4466 f->glUniformMatrix3fv(uniform.glslLocation, 1, GL_FALSE, mat);
4468 m_scratch.packedArray.resize(elemCount * 9);
4469 qrhi_std140_to_packed(&m_scratch.packedArray.data()->f, 3, elemCount * 3, src);
4470 f->glUniformMatrix3fv(uniform.glslLocation, elemCount, GL_FALSE, &m_scratch.packedArray.constData()->f);
4474 case QShaderDescription::Mat4:
4475 f->glUniformMatrix4fv(uniform.glslLocation, qMax(1, uniform.arrayDim), GL_FALSE,
reinterpret_cast<
const float *>(src));
4477 case QShaderDescription::Int:
4479 const int elemCount = uniform.arrayDim;
4480 if (elemCount < 1) {
4481 f->glUniform1i(uniform.glslLocation, *
reinterpret_cast<
const qint32 *>(src));
4483 m_scratch.packedArray.resize(elemCount);
4484 qrhi_std140_to_packed(&m_scratch.packedArray.data()->i, 1, elemCount, src);
4485 f->glUniform1iv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->i);
4489 case QShaderDescription::Int2:
4491 const int elemCount = uniform.arrayDim;
4492 if (elemCount < 1) {
4493 f->glUniform2iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4495 m_scratch.packedArray.resize(elemCount * 2);
4496 qrhi_std140_to_packed(&m_scratch.packedArray.data()->i, 2, elemCount, src);
4497 f->glUniform2iv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->i);
4501 case QShaderDescription::Int3:
4503 const int elemCount = uniform.arrayDim;
4504 if (elemCount < 1) {
4505 f->glUniform3iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4507 m_scratch.packedArray.resize(elemCount * 3);
4508 qrhi_std140_to_packed(&m_scratch.packedArray.data()->i, 3, elemCount, src);
4509 f->glUniform3iv(uniform.glslLocation, elemCount, &m_scratch.packedArray.constData()->i);
4513 case QShaderDescription::Int4:
4514 f->glUniform4iv(uniform.glslLocation, qMax(1, uniform.arrayDim),
reinterpret_cast<
const qint32 *>(src));
4516 case QShaderDescription::Uint:
4517 f->glUniform1ui(uniform.glslLocation, *
reinterpret_cast<
const quint32 *>(src));
4519 case QShaderDescription::Uint2:
4520 f->glUniform2uiv(uniform.glslLocation, 1,
reinterpret_cast<
const quint32 *>(src));
4522 case QShaderDescription::Uint3:
4523 f->glUniform3uiv(uniform.glslLocation, 1,
reinterpret_cast<
const quint32 *>(src));
4525 case QShaderDescription::Uint4:
4526 f->glUniform4uiv(uniform.glslLocation, 1,
reinterpret_cast<
const quint32 *>(src));
4528 case QShaderDescription::Bool:
4529 f->glUniform1i(uniform.glslLocation, *
reinterpret_cast<
const qint32 *>(src));
4531 case QShaderDescription::Bool2:
4532 f->glUniform2iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4534 case QShaderDescription::Bool3:
4535 f->glUniform3iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4537 case QShaderDescription::Bool4:
4538 f->glUniform4iv(uniform.glslLocation, 1,
reinterpret_cast<
const qint32 *>(src));
4541 qWarning(
"Uniform with buffer binding %d, buffer offset %d has unsupported type %d",
4542 uniform.binding, uniform.offset, uniform.type);
4549 case QRhiShaderResourceBinding::SampledTexture:
4555 if (maybeGraphicsPs) {
4556 ps = maybeGraphicsPs;
4559 ps = maybeComputePs;
4562 for (
int elem = 0; elem < b->u.stex.count; ++elem) {
4565 for (
const QGles2SamplerDescription &shaderSampler : samplers) {
4566 if (shaderSampler.combinedBinding == b->binding) {
4567 const int loc = shaderSampler.glslLocation + elem;
4568 bindCombinedSampler(cbD, texD, samplerD, ps, psGeneration, loc, &texUnit, &activeTexUnitAltered);
4575 case QRhiShaderResourceBinding::Texture:
4576 for (
int elem = 0; elem < b->u.stex.count; ++elem) {
4578 m_scratch.separateTextureBindings.append({ texD, b->binding, elem });
4581 case QRhiShaderResourceBinding::Sampler:
4584 m_scratch.separateSamplerBindings.append({ samplerD, b->binding });
4587 case QRhiShaderResourceBinding::ImageLoad:
4588 case QRhiShaderResourceBinding::ImageStore:
4589 case QRhiShaderResourceBinding::ImageLoadStore:
4592 Q_ASSERT(texD->m_flags.testFlag(QRhiTexture::UsedWithLoadStore));
4594 const bool layered = texD->m_flags.testFlag(QRhiTexture::CubeMap)
4595 || texD->m_flags.testFlag(QRhiTexture::ThreeDimensional)
4596 || texD->m_flags.testFlag(QRhiTexture::TextureArray);
4598 if (b->type == QRhiShaderResourceBinding::ImageLoad)
4600 else if (b->type == QRhiShaderResourceBinding::ImageStore)
4602 f->glBindImageTexture(GLuint(b->binding), texD->texture,
4603 b->u.simage.level, layered, 0,
4604 access, texD->glsizedintformat);
4607 case QRhiShaderResourceBinding::BufferLoad:
4608 case QRhiShaderResourceBinding::BufferStore:
4609 case QRhiShaderResourceBinding::BufferLoadStore:
4612 Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer));
4613 if (b->u.sbuf.offset == 0 && b->u.sbuf.maybeSize == 0)
4617 b->u.sbuf.offset, b->u.sbuf.maybeSize ? b->u.sbuf.maybeSize : bufD->m_size);
4626 if (!m_scratch.separateTextureBindings.isEmpty() || !m_scratch.separateSamplerBindings.isEmpty()) {
4631 if (maybeGraphicsPs) {
4632 ps = maybeGraphicsPs;
4635 ps = maybeComputePs;
4638 for (
const QGles2SamplerDescription &shaderSampler : samplers) {
4639 if (shaderSampler.combinedBinding >= 0)
4641 for (
const Scratch::SeparateSampler &sepSampler : std::as_const(m_scratch.separateSamplerBindings)) {
4642 if (sepSampler.binding != shaderSampler.sbinding)
4644 for (
const Scratch::SeparateTexture &sepTex : std::as_const(m_scratch.separateTextureBindings)) {
4645 if (sepTex.binding != shaderSampler.tbinding)
4647 const int loc = shaderSampler.glslLocation + sepTex.elem;
4648 bindCombinedSampler(cbD, sepTex.texture, sepSampler.sampler, ps, psGeneration,
4649 loc, &texUnit, &activeTexUnitAltered);
4655 if (activeTexUnitAltered)
4800 if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
4802 for (
auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
4805 const QRhiColorAttachment &colorAtt(*it);
4806 if (!colorAtt.resolveTexture())
4810 const QSize size = resolveTexD->pixelSize();
4811 if (colorAtt.renderBuffer()) {
4813 if (rbD->pixelSize() != size) {
4814 qWarning(
"Resolve source (%dx%d) and target (%dx%d) size does not match",
4815 rbD->pixelSize().width(), rbD->pixelSize().height(), size.width(), size.height());
4817 if (caps.glesMultisampleRenderToTexture) {
4823 cmd.args.blitFromRenderbuffer.renderbuffer = rbD->renderbuffer;
4824 cmd.args.blitFromRenderbuffer.w = size.width();
4825 cmd.args.blitFromRenderbuffer.h = size.height();
4826 if (resolveTexD->m_flags.testFlag(QRhiTexture::CubeMap))
4829 cmd.args.blitFromRenderbuffer.target = resolveTexD->target;
4830 cmd.args.blitFromRenderbuffer.dstTexture = resolveTexD->texture;
4831 cmd.args.blitFromRenderbuffer.dstLevel = colorAtt.resolveLevel();
4832 const bool hasZ = resolveTexD->m_flags.testFlag(QRhiTexture::ThreeDimensional)
4833 || resolveTexD->m_flags.testFlag(QRhiTexture::TextureArray);
4834 cmd.args.blitFromRenderbuffer.dstLayer = hasZ ? colorAtt.resolveLayer() : 0;
4835 cmd.args.blitFromRenderbuffer.isDepthStencil =
false;
4837 }
else if (caps.glesMultisampleRenderToTexture) {
4841 Q_ASSERT(colorAtt.texture());
4843 if (texD->pixelSize() != size) {
4844 qWarning(
"Resolve source (%dx%d) and target (%dx%d) size does not match",
4845 texD->pixelSize().width(), texD->pixelSize().height(), size.width(), size.height());
4847 const int resolveCount = colorAtt.multiViewCount() >= 2 ? colorAtt.multiViewCount() : 1;
4848 for (
int resolveIdx = 0; resolveIdx < resolveCount; ++resolveIdx) {
4849 const int srcLayer = colorAtt.layer() + resolveIdx;
4850 const int dstLayer = colorAtt.resolveLayer() + resolveIdx;
4853 if (texD->m_flags.testFlag(QRhiTexture::CubeMap))
4856 cmd.args.blitFromTexture.srcTarget = texD->target;
4857 cmd.args.blitFromTexture.srcTexture = texD->texture;
4858 cmd.args.blitFromTexture.srcLevel = colorAtt.level();
4859 cmd.args.blitFromTexture.srcLayer = 0;
4860 if (texD->m_flags.testFlag(QRhiTexture::ThreeDimensional) || texD->m_flags.testFlag(QRhiTexture::TextureArray))
4861 cmd.args.blitFromTexture.srcLayer = srcLayer;
4862 cmd.args.blitFromTexture.w = size.width();
4863 cmd.args.blitFromTexture.h = size.height();
4864 if (resolveTexD->m_flags.testFlag(QRhiTexture::CubeMap))
4867 cmd.args.blitFromTexture.dstTarget = resolveTexD->target;
4868 cmd.args.blitFromTexture.dstTexture = resolveTexD->texture;
4869 cmd.args.blitFromTexture.dstLevel = colorAtt.resolveLevel();
4870 cmd.args.blitFromTexture.dstLayer = 0;
4871 if (resolveTexD->m_flags.testFlag(QRhiTexture::ThreeDimensional) || resolveTexD->m_flags.testFlag(QRhiTexture::TextureArray))
4872 cmd.args.blitFromTexture.dstLayer = dstLayer;
4873 cmd.args.blitFromTexture.isDepthStencil =
false;
4878 if (rtTex->m_desc.depthResolveTexture()) {
4880 const QSize size = depthResolveTexD->pixelSize();
4881 if (rtTex->m_desc.depthStencilBuffer()) {
4885 cmd.args.blitFromRenderbuffer.renderbuffer = rbD->renderbuffer;
4886 cmd.args.blitFromRenderbuffer.w = size.width();
4887 cmd.args.blitFromRenderbuffer.h = size.height();
4888 cmd.args.blitFromRenderbuffer.target = depthResolveTexD->target;
4889 cmd.args.blitFromRenderbuffer.dstTexture = depthResolveTexD->texture;
4890 cmd.args.blitFromRenderbuffer.dstLevel = 0;
4891 cmd.args.blitFromRenderbuffer.dstLayer = 0;
4892 cmd.args.blitFromRenderbuffer.isDepthStencil =
true;
4893 }
else if (caps.glesMultisampleRenderToTexture) {
4897 const int resolveCount = depthTexD->arraySize() >= 2 ? depthTexD->arraySize() : 1;
4898 for (
int resolveIdx = 0; resolveIdx < resolveCount; ++resolveIdx) {
4901 cmd.args.blitFromTexture.srcTarget = depthTexD->target;
4902 cmd.args.blitFromTexture.srcTexture = depthTexD->texture;
4903 cmd.args.blitFromTexture.srcLevel = 0;
4904 cmd.args.blitFromTexture.srcLayer = resolveIdx;
4905 cmd.args.blitFromTexture.w = size.width();
4906 cmd.args.blitFromTexture.h = size.height();
4907 cmd.args.blitFromTexture.dstTarget = depthResolveTexD->target;
4908 cmd.args.blitFromTexture.dstTexture = depthResolveTexD->texture;
4909 cmd.args.blitFromTexture.dstLevel = 0;
4910 cmd.args.blitFromTexture.dstLayer = resolveIdx;
4911 cmd.args.blitFromTexture.isDepthStencil =
true;
4916 const bool mayDiscardDepthStencil =
4917 (rtTex->m_desc.depthStencilBuffer()
4918 || (rtTex->m_desc.depthTexture() && rtTex->m_flags.testFlag(QRhiTextureRenderTarget::DoNotStoreDepthStencilContents)))
4919 && !rtTex->m_desc.depthResolveTexture();
4920 if (mayDiscardDepthStencil) {
4923 cmd.args.invalidateFramebuffer.fbo = rtTex->framebuffer;
4924 if (caps.needsDepthStencilCombinedAttach) {
4925 cmd.args.invalidateFramebuffer.attCount = 1;
4928 cmd.args.invalidateFramebuffer.attCount = 2;
4929 cmd.args.invalidateFramebuffer.att[0] = GL_DEPTH_ATTACHMENT;
4930 cmd.args.invalidateFramebuffer.att[1] = GL_STENCIL_ATTACHMENT;
4936 cbD->currentTarget =
nullptr;
4938 if (resourceUpdates)
6206bool QGles2TextureRenderTarget::create()
6213 const bool hasColorAttachments = m_desc.colorAttachmentCount() > 0;
6214 Q_ASSERT(hasColorAttachments || m_desc.depthTexture());
6215 Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
6216 const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
6218 if (hasColorAttachments) {
6219 const int count =
int(m_desc.colorAttachmentCount());
6220 if (count > rhiD->caps.maxDrawBuffers) {
6221 qWarning(
"QGles2TextureRenderTarget: Too many color attachments (%d, max is %d)",
6222 count, rhiD->caps.maxDrawBuffers);
6225 if (m_desc.depthTexture() && !rhiD->caps.depthTexture)
6226 qWarning(
"QGles2TextureRenderTarget: Depth texture is not supported and will be ignored");
6228 if (!rhiD->ensureContext())
6231 rhiD->f->glGenFramebuffers(1, &framebuffer);
6232 rhiD->f->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6234 d.colorAttCount = 0;
6236 int multiViewCount = 0;
6237 for (
auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
6238 d.colorAttCount += 1;
6239 const QRhiColorAttachment &colorAtt(*it);
6240 QRhiTexture *texture = colorAtt.texture();
6241 QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer();
6242 Q_ASSERT(texture || renderBuffer);
6244 QGles2Texture *texD =
QRHI_RES(QGles2Texture, texture);
6245 Q_ASSERT(texD->texture && texD->specified);
6246 if (texD->flags().testFlag(QRhiTexture::ThreeDimensional) || texD->flags().testFlag(QRhiTexture::TextureArray)) {
6247 if (colorAtt.multiViewCount() < 2) {
6248 rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture,
6249 colorAtt.level(), colorAtt.layer());
6251 multiViewCount = colorAtt.multiViewCount();
6252 if (texD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture && colorAtt.resolveTexture()) {
6257 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
6258 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6259 GL_COLOR_ATTACHMENT0 + uint(attIndex),
6260 resolveTexD->texture,
6261 colorAtt.resolveLevel(),
6263 colorAtt.resolveLayer(),
6266 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER,
6267 GL_COLOR_ATTACHMENT0 + uint(attIndex),
6274 }
else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
6275 rhiD->glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex),
6276 texD->target + uint(colorAtt.layer()), texD->texture,
6279 if (texD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
6284 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
6286 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
6287 resolveTexD->texture, colorAtt.level(), texD->samples);
6290 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.layer()),
6291 texD->texture, colorAtt.level());
6294 if (attIndex == 0) {
6295 d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
6296 d.sampleCount = texD->samples;
6298 }
else if (renderBuffer) {
6299 QGles2RenderBuffer *rbD =
QRHI_RES(QGles2RenderBuffer, renderBuffer);
6300 if (rbD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
6305 QGles2Texture *resolveTexD =
QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
6307 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
6308 resolveTexD->texture, colorAtt.level(), rbD->samples);
6310 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), GL_RENDERBUFFER, rbD->renderbuffer);
6312 if (attIndex == 0) {
6313 d.pixelSize = rbD->pixelSize();
6314 d.sampleCount = rbD->samples;
6319 if (hasDepthStencil) {
6320 if (m_desc.depthStencilBuffer()) {
6321 QGles2RenderBuffer *depthRbD =
QRHI_RES(QGles2RenderBuffer, m_desc.depthStencilBuffer());
6322 if (rhiD->caps.needsDepthStencilCombinedAttach) {
6324 depthRbD->renderbuffer);
6326 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
6327 depthRbD->renderbuffer);
6328 if (depthRbD->stencilRenderbuffer) {
6329 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
6330 depthRbD->stencilRenderbuffer);
6333 rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
6334 depthRbD->renderbuffer);
6337 if (d.colorAttCount == 0) {
6338 d.pixelSize = depthRbD->pixelSize();
6339 d.sampleCount = depthRbD->samples;
6342 QGles2Texture *depthTexD =
QRHI_RES(QGles2Texture, m_desc.depthTexture());
6343 if (multiViewCount < 2) {
6344 if (depthTexD->samples > 1 && rhiD->caps.glesMultisampleRenderToTexture && m_desc.depthResolveTexture()) {
6348 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
6349 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthResolveTexD->target,
6350 depthResolveTexD->texture, 0, depthTexD->samples);
6351 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
6352 rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthResolveTexD->target,
6353 depthResolveTexD->texture, 0, depthTexD->samples);
6356 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->target,
6357 depthTexD->texture, 0);
6358 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
6359 rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->target,
6360 depthTexD->texture, 0);
6364 if (depthTexD->samples > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture) {
6382 if (!m_flags.testFlag(DoNotStoreDepthStencilContents) && !m_desc.depthResolveTexture()) {
6383 qWarning(
"Attempted to create a multiview+multisample QRhiTextureRenderTarget, but DoNotStoreDepthStencilContents was not set."
6384 " This path has no choice but to behave as if DoNotStoreDepthStencilContents was set, because QRhi is forced to create"
6385 " a throwaway non-multisample depth texture here. Set the flag to silence this warning, or set a depthResolveTexture.");
6387 if (m_desc.depthResolveTexture()) {
6388 QGles2Texture *depthResolveTexD =
QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
6389 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6390 GL_DEPTH_ATTACHMENT,
6391 depthResolveTexD->texture,
6396 if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
6397 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6398 GL_STENCIL_ATTACHMENT,
6399 depthResolveTexD->texture,
6406 if (!nonMsaaThrowawayDepthTexture) {
6407 rhiD->f->glGenTextures(1, &nonMsaaThrowawayDepthTexture);
6410 depthTexD->pixelSize().width(), depthTexD->pixelSize().height(), multiViewCount);
6412 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6413 GL_DEPTH_ATTACHMENT,
6414 nonMsaaThrowawayDepthTexture,
6419 rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
6420 GL_STENCIL_ATTACHMENT,
6421 nonMsaaThrowawayDepthTexture,
6431 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
6432 0, 0, multiViewCount);
6433 if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
6434 rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
6435 0, 0, multiViewCount);
6439 if (d.colorAttCount == 0) {
6440 d.pixelSize = depthTexD->pixelSize();
6441 d.sampleCount = depthTexD->samples;
6450 d.rp =
QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
6452 GLenum status = rhiD->f->glCheckFramebufferStatus(GL_FRAMEBUFFER);
6453 if (status != GL_NO_ERROR && status != GL_FRAMEBUFFER_COMPLETE) {
6454 qWarning(
"Framebuffer incomplete: 0x%x", status);
6458 if (rhiD->glObjectLabel)
6459 rhiD->glObjectLabel(GL_FRAMEBUFFER, framebuffer, -1, m_objectName.constData());
6461 QRhiRenderTargetAttachmentTracker::updateResIdList<QGles2Texture, QGles2RenderBuffer>(m_desc, &d.currentResIdList);
6463 rhiD->registerResource(
this);