diff options
Diffstat (limited to 'src/gui/rhi')
-rw-r--r-- | src/gui/rhi/qrhigles2.cpp | 30 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2_p_p.h | 4 | ||||
-rw-r--r-- | src/gui/rhi/qrhimetal.mm | 64 |
3 files changed, 82 insertions, 16 deletions
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 5fdd3b7179..53e47b027c 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -1149,7 +1149,29 @@ void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind } } - const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb); + bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb); + + // The Command::BindShaderResources command generated below is what will + // cause uniforms to be set (glUniformNxx). This needs some special + // handling here in this backend without real uniform buffers, because, + // like in other backends, we optimize out the setShaderResources when the + // srb that was set before is attempted to be set again on the command + // buffer, but that is incorrect if the same srb is now used with another + // pipeline. (because that could mean a glUseProgram not followed by + // up-to-date glUniform calls, i.e. with GL we have a strong dependency + // between the pipeline (== program) and the srb, unlike other APIs) This + // is the reason there is a second level of srb(+generation) tracking in + // the pipeline objects. + if (gfxPsD && (gfxPsD->currentSrb != srb || gfxPsD->currentSrbGeneration != srbD->generation)) { + srbChanged = true; + gfxPsD->currentSrb = srb; + gfxPsD->currentSrbGeneration = srbD->generation; + } else if (compPsD && (compPsD->currentSrb != srb || compPsD->currentSrbGeneration != srbD->generation)) { + srbChanged = true; + compPsD->currentSrb = srb; + compPsD->currentSrbGeneration = srbD->generation; + } + if (srbChanged || cbD->currentSrbGeneration != srbD->generation || srbD->hasDynamicOffset) { if (gfxPsD) { cbD->currentGraphicsSrb = srb; @@ -4580,6 +4602,9 @@ bool QGles2GraphicsPipeline::create() memset(uniformState, 0, sizeof(uniformState)); + currentSrb = nullptr; + currentSrbGeneration = 0; + generation += 1; rhiD->registerResource(this); return true; @@ -4653,6 +4678,9 @@ bool QGles2ComputePipeline::create() memset(uniformState, 0, sizeof(uniformState)); + currentSrb = nullptr; + currentSrbGeneration = 0; + generation += 1; rhiD->registerResource(this); return true; diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index a336497b63..49ab684363 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -290,6 +290,8 @@ struct QGles2GraphicsPipeline : public QRhiGraphicsPipeline QGles2UniformDescriptionVector uniforms; QGles2SamplerDescriptionVector samplers; QGles2UniformState uniformState[QGles2UniformState::MAX_TRACKED_LOCATION + 1]; + QRhiShaderResourceBindings *currentSrb = nullptr; + uint currentSrbGeneration = 0; uint generation = 0; friend class QRhiGles2; }; @@ -305,6 +307,8 @@ struct QGles2ComputePipeline : public QRhiComputePipeline QGles2UniformDescriptionVector uniforms; QGles2SamplerDescriptionVector samplers; QGles2UniformState uniformState[QGles2UniformState::MAX_TRACKED_LOCATION + 1]; + QRhiShaderResourceBindings *currentSrb = nullptr; + uint currentSrbGeneration = 0; uint generation = 0; friend class QRhiGles2; }; diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index 9e0655ef06..71f6eabb4c 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -224,7 +224,11 @@ struct QMetalBufferData bool managed; bool slotted; id<MTLBuffer> buf[QMTL_FRAMES_IN_FLIGHT]; - QVarLengthArray<QRhiResourceUpdateBatchPrivate::BufferOp, 16> pendingUpdates[QMTL_FRAMES_IN_FLIGHT]; + struct BufferUpdate { + int offset; + QRhiBufferData data; + }; + QVarLengthArray<BufferUpdate, 16> pendingUpdates[QMTL_FRAMES_IN_FLIGHT]; }; struct QMetalRenderBufferData @@ -1699,8 +1703,11 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::DynamicUpdate) { QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, u.buf); Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic); - for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) - bufD->d->pendingUpdates[i].append(u); + for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) { + if (u.offset == 0 && u.data.size() == bufD->m_size) + bufD->d->pendingUpdates[i].clear(); + bufD->d->pendingUpdates[i].append({ u.offset, u.data }); + } } else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload) { // Due to the Metal API the handling of static and dynamic buffers is // basically the same. So go through the same pendingUpdates machinery. @@ -1708,8 +1715,7 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic); Q_ASSERT(u.offset + u.data.size() <= bufD->m_size); for (int i = 0, ie = bufD->d->slotted ? QMTL_FRAMES_IN_FLIGHT : 1; i != ie; ++i) - bufD->d->pendingUpdates[i].append( - QRhiResourceUpdateBatchPrivate::BufferOp::dynamicUpdate(u.buf, u.offset, u.data.size(), u.data.constData())); + bufD->d->pendingUpdates[i].append({ u.offset, u.data }); } else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) { QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, u.buf); executeBufferHostWritesForCurrentFrame(bufD); @@ -1869,8 +1875,7 @@ void QRhiMetal::executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot) void *p = [bufD->d->buf[slot] contents]; int changeBegin = -1; int changeEnd = -1; - for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->d->pendingUpdates[slot])) { - Q_ASSERT(bufD == QRHI_RES(QMetalBuffer, u.buf)); + for (const QMetalBufferData::BufferUpdate &u : qAsConst(bufD->d->pendingUpdates[slot])) { memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size())); if (changeBegin == -1 || u.offset < changeBegin) changeBegin = u.offset; @@ -2285,6 +2290,9 @@ void QMetalBuffer::endFullDynamicBufferUpdateForCurrentFrame() static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags, const QRhiMetalData *d) { +#ifndef Q_OS_MACOS + Q_UNUSED(d); +#endif const bool srgb = flags.testFlag(QRhiTexture::sRGB); switch (format) { case QRhiTexture::RGBA8: @@ -3787,10 +3795,42 @@ QRhiRenderTarget *QMetalSwapChain::currentFrameRenderTarget() return &rtWrapper; } +#ifdef TARGET_IPHONE_SIMULATOR +API_AVAILABLE(ios(13.0)) +#endif +static inline CAMetalLayer *layerForWindow(QWindow *window) +{ + Q_ASSERT(window); +#ifdef Q_OS_MACOS + NSView *view = reinterpret_cast<NSView *>(window->winId()); +#else + UIView *view = reinterpret_cast<UIView *>(window->winId()); +#endif + Q_ASSERT(view); + return static_cast<CAMetalLayer *>(view.layer); +} + QSize QMetalSwapChain::surfacePixelSize() { +#ifdef TARGET_IPHONE_SIMULATOR + if (@available(ios 13.0, *)) { +#endif + Q_ASSERT(m_window); - return m_window->size() * m_window->devicePixelRatio(); + CAMetalLayer *layer = d->layer; + if (!layer) + layer = layerForWindow(m_window); + + CGSize layerSize = layer.bounds.size; + layerSize.width *= layer.contentsScale; + layerSize.height *= layer.contentsScale; + return QSizeF::fromCGSize(layerSize).toSize(); + +#ifdef TARGET_IPHONE_SIMULATOR + } else { + return QSize(); + } +#endif } QRhiRenderPassDescriptor *QMetalSwapChain::newCompatibleRenderPassDescriptor() @@ -3849,13 +3889,7 @@ bool QMetalSwapChain::createOrResize() return false; } -#ifdef Q_OS_MACOS - NSView *view = reinterpret_cast<NSView *>(window->winId()); -#else - UIView *view = reinterpret_cast<UIView *>(window->winId()); -#endif - Q_ASSERT(view); - d->layer = static_cast<CAMetalLayer *>(view.layer); + d->layer = layerForWindow(window); Q_ASSERT(d->layer); chooseFormats(); |