Commit fbb992e4 authored by Laszlo Agocs's avatar Laszlo Agocs

Keep track of the frame count in swapchains

...and do some naming cleanup (currentFrame -> currentFrameSlot).
parent 191c8f41
......@@ -550,7 +550,7 @@ QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain)
swapChainD->cb.resetState();
swapChainD->rt.d.rtv[0] = swapChainD->sampleDesc.Count > 1 ?
swapChainD->msaaRtv[swapChainD->currentFrame] : swapChainD->rtv[swapChainD->currentFrame];
swapChainD->msaaRtv[swapChainD->currentFrameSlot] : swapChainD->rtv[swapChainD->currentFrameSlot];
swapChainD->rt.d.dsv = swapChainD->ds ? swapChainD->ds->dsv : nullptr;
finishActiveReadbacks();
......@@ -564,11 +564,13 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain)
inFrame = false;
QD3D11SwapChain *swapChainD = QRHI_RES(QD3D11SwapChain, swapChain);
Q_ASSERT(contextState.currentSwapChain = swapChainD);
executeCommandBuffer(&swapChainD->cb);
if (swapChainD->sampleDesc.Count > 1) {
context->ResolveSubresource(swapChainD->tex[swapChainD->currentFrame], 0,
swapChainD->msaaTex[swapChainD->currentFrame], 0,
context->ResolveSubresource(swapChainD->tex[swapChainD->currentFrameSlot], 0,
swapChainD->msaaTex[swapChainD->currentFrameSlot], 0,
swapChainD->colorFormat);
}
......@@ -578,10 +580,10 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain)
if (FAILED(hr))
qWarning("Failed to present: %s", qPrintable(comErrorMessage(hr)));
swapChainD->currentFrame = (swapChainD->currentFrame + 1) % QD3D11SwapChain::BUFFER_COUNT;
swapChainD->currentFrameSlot = (swapChainD->currentFrameSlot + 1) % QD3D11SwapChain::BUFFER_COUNT;
swapChainD->frameCount += 1;
contextState.currentSwapChain = nullptr;
++finishedFrameCount;
return QRhi::FrameOpSuccess;
}
......@@ -606,7 +608,6 @@ QRhi::FrameOpResult QRhiD3D11::endOffscreenFrame()
executeCommandBuffer(&ofr.cbWrapper);
finishActiveReadbacks();
++finishedFrameCount;
return QRhi::FrameOpSuccess;;
}
......@@ -921,14 +922,14 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
// has to be supported. Insert a resolve.
QD3D11CommandBuffer::Command rcmd;
rcmd.cmd = QD3D11CommandBuffer::Command::ResolveSubRes;
rcmd.args.resolveSubRes.dst = swapChainD->tex[swapChainD->currentFrame];
rcmd.args.resolveSubRes.dst = swapChainD->tex[swapChainD->currentFrameSlot];
rcmd.args.resolveSubRes.dstSubRes = 0;
rcmd.args.resolveSubRes.src = swapChainD->msaaTex[swapChainD->currentFrame];
rcmd.args.resolveSubRes.src = swapChainD->msaaTex[swapChainD->currentFrameSlot];
rcmd.args.resolveSubRes.srcSubRes = 0;
rcmd.args.resolveSubRes.format = swapChainD->colorFormat;
cbD->commands.append(rcmd);
}
src = swapChainD->tex[swapChainD->currentFrame];
src = swapChainD->tex[swapChainD->currentFrameSlot];
dxgiFormat = swapChainD->colorFormat;
pixelSize = swapChainD->pixelSize;
format = colorTextureFormatFromDxgiFormat(dxgiFormat, nullptr);
......@@ -2746,7 +2747,8 @@ bool QD3D11SwapChain::buildOrResize()
pixelSize.width(), pixelSize.height());
}
currentFrame = 0;
currentFrameSlot = 0;
frameCount = 0;
ds = m_depthStencil ? QRHI_RES(QD3D11RenderBuffer, m_depthStencil) : nullptr;
QD3D11ReferenceRenderTarget *rtD = QRHI_RES(QD3D11ReferenceRenderTarget, &rt);
......
......@@ -423,7 +423,8 @@ struct QD3D11SwapChain : public QRhiSwapChain
ID3D11Texture2D *msaaTex[BUFFER_COUNT];
ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT];
DXGI_SAMPLE_DESC sampleDesc;
int currentFrame = 0;
int currentFrameSlot = 0;
int frameCount = 0;
QD3D11RenderBuffer *ds = nullptr;
};
......@@ -523,7 +524,6 @@ public:
QRhiD3D11NativeHandles nativeHandlesStruct;
bool inFrame = false;
int finishedFrameCount = 0;
bool inPass = false;
struct {
......
......@@ -517,13 +517,15 @@ QRhi::FrameOpResult QRhiGles2::endFrame(QRhiSwapChain *swapChain)
inFrame = false;
QGles2SwapChain *swapChainD = QRHI_RES(QGles2SwapChain, swapChain);
Q_ASSERT(currentSwapChain == swapChainD);
if (!ensureContext(swapChainD->surface))
return QRhi::FrameOpError;
executeCommandBuffer(&swapChainD->cb);
swapChainD->frameCount += 1;
currentSwapChain = nullptr;
++finishedFrameCount;
if (swapChainD->surface) {
ctx->swapBuffers(swapChainD->surface);
......@@ -561,7 +563,6 @@ QRhi::FrameOpResult QRhiGles2::endOffscreenFrame()
executeCommandBuffer(&ofr.cbWrapper);
++finishedFrameCount;
return QRhi::FrameOpSuccess;;
}
......@@ -2200,6 +2201,8 @@ bool QGles2SwapChain::buildOrResize()
rt.d.dpr = m_window->devicePixelRatio();
rt.d.attCount = m_depthStencil ? 2 : 1;
frameCount = 0;
QRHI_PROF;
// make something up
QRHI_PROF_F(resizeSwapChain(this, 2, m_sampleCount > 1 ? 2 : 0, m_sampleCount));
......
......@@ -434,6 +434,7 @@ struct QGles2SwapChain : public QRhiSwapChain
QSize pixelSize;
QGles2ReferenceRenderTarget rt;
QGles2CommandBuffer cb;
int frameCount = 0;
};
class QRhiGles2 : public QRhiImplementation
......@@ -533,7 +534,6 @@ public:
int maxTextureSize = 2048;
} caps;
bool inFrame = false;
int finishedFrameCount = 0;
bool inPass = false;
QGles2SwapChain *currentSwapChain = nullptr;
QVector<GLint> supportedCompressedFormats;
......
......@@ -670,7 +670,7 @@ QRhi::FrameOpResult QRhiMetal::beginFrame(QRhiSwapChain *swapChain)
// (for this same frame slot) but not sure how to do that in a sane way so
// wait for full cb completion for now.
for (QMetalSwapChain *sc : qAsConst(swapchains)) {
dispatch_semaphore_t sem = sc->d->sem[swapChainD->currentFrame];
dispatch_semaphore_t sem = sc->d->sem[swapChainD->currentFrameSlot];
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
if (sc != swapChainD)
dispatch_semaphore_signal(sem);
......@@ -683,7 +683,7 @@ QRhi::FrameOpResult QRhiMetal::beginFrame(QRhiSwapChain *swapChain)
}
currentSwapChain = swapChainD;
currentFrameSlot = swapChainD->currentFrame;
currentFrameSlot = swapChainD->currentFrameSlot;
if (swapChainD->ds)
swapChainD->ds->lastActiveFrameSlot = currentFrameSlot;
......@@ -716,20 +716,21 @@ QRhi::FrameOpResult QRhiMetal::endFrame(QRhiSwapChain *swapChain)
inFrame = false;
QMetalSwapChain *swapChainD = QRHI_RES(QMetalSwapChain, swapChain);
Q_ASSERT(currentSwapChain == swapChainD);
[swapChainD->cbWrapper.d->cb presentDrawable: swapChainD->d->curDrawable];
__block int thisFrame = currentFrameSlot;
__block int thisFrameSlot = currentFrameSlot;
[swapChainD->cbWrapper.d->cb addCompletedHandler: ^(id<MTLCommandBuffer>) {
dispatch_semaphore_signal(swapChainD->d->sem[thisFrame]);
dispatch_semaphore_signal(swapChainD->d->sem[thisFrameSlot]);
}];
[swapChainD->cbWrapper.d->cb commit];
swapChainD->currentFrame = (swapChainD->currentFrame + 1) % QMTL_FRAMES_IN_FLIGHT;
swapChainD->currentFrameSlot = (swapChainD->currentFrameSlot + 1) % QMTL_FRAMES_IN_FLIGHT;
swapChainD->frameCount += 1;
currentSwapChain = nullptr;
++finishedFrameCount;
return QRhi::FrameOpSuccess;
}
......@@ -772,7 +773,6 @@ QRhi::FrameOpResult QRhiMetal::endOffscreenFrame()
finishActiveReadbacks(true);
++finishedFrameCount;
return QRhi::FrameOpSuccess;
}
......@@ -2558,7 +2558,8 @@ bool QMetalSwapChain::buildOrResize()
d->sem[i] = dispatch_semaphore_create(1);
}
currentFrame = 0;
currentFrameSlot = 0;
frameCount = 0;
ds = m_depthStencil ? QRHI_RES(QMetalRenderBuffer, m_depthStencil) : nullptr;
if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
......
......@@ -240,7 +240,8 @@ struct QMetalSwapChain : public QRhiSwapChain
QWindow *window = nullptr;
QSize pixelSize;
int currentFrame = 0; // 0..QMTL_FRAMES_IN_FLIGHT-1
int currentFrameSlot = 0; // 0..QMTL_FRAMES_IN_FLIGHT-1
int frameCount = 0;
int samples = 1;
QMetalReferenceRenderTarget rtWrapper;
QMetalCommandBuffer cbWrapper;
......@@ -338,7 +339,6 @@ public:
bool importedDevice = false;
bool inFrame = false;
int currentFrameSlot = 0;
int finishedFrameCount = 0;
bool inPass = false;
QMetalSwapChain *currentSwapChain = nullptr;
QSet<QMetalSwapChain *> swapchains;
......
......@@ -1099,7 +1099,7 @@ bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain)
image.cmdFenceWaitable = true; // fence was created in signaled state
}
swapChainD->currentImage = 0;
swapChainD->currentImageIndex = 0;
VkSemaphoreCreateInfo semInfo;
memset(&semInfo, 0, sizeof(semInfo));
......@@ -1118,7 +1118,7 @@ bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain)
df->vkCreateSemaphore(dev, &semInfo, nullptr, &frame.drawSem);
}
swapChainD->currentFrame = 0;
swapChainD->currentFrameSlot = 0;
return true;
}
......@@ -1237,9 +1237,13 @@ QRhi::FrameOpResult QRhiVulkan::beginWrapperFrame(QRhiSwapChain *swapChain)
QRhi::FrameOpResult QRhiVulkan::endWrapperFrame(QRhiSwapChain *swapChain)
{
Q_UNUSED(swapChain);
Q_ASSERT(inFrame);
inFrame = false;
prepareFrameEnd();
QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
Q_ASSERT(currentSwapChain == swapChainD);
swapChainD->frameCount += 1;
currentSwapChain = nullptr;
return QRhi::FrameOpSuccess;
......@@ -1339,7 +1343,7 @@ void QRhiVulkan::waitCommandCompletion(int frameSlot)
QRhi::FrameOpResult QRhiVulkan::beginNonWrapperFrame(QRhiSwapChain *swapChain)
{
QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
QVkSwapChain::FrameResources &frame(swapChainD->frameRes[swapChainD->currentFrame]);
QVkSwapChain::FrameResources &frame(swapChainD->frameRes[swapChainD->currentFrameSlot]);
if (!frame.imageAcquired) {
// Wait if we are too far ahead, i.e. the thread gets throttled based on the presentation rate
......@@ -1354,7 +1358,7 @@ QRhi::FrameOpResult QRhiVulkan::beginNonWrapperFrame(QRhiSwapChain *swapChain)
VkResult err = vkAcquireNextImageKHR(dev, swapChainD->sc, UINT64_MAX,
frame.imageSem, frame.fence, &frame.imageIndex);
if (err == VK_SUCCESS || err == VK_SUBOPTIMAL_KHR) {
swapChainD->currentImage = frame.imageIndex;
swapChainD->currentImageIndex = frame.imageIndex;
frame.imageSemWaitable = true;
frame.imageAcquired = true;
frame.fenceWaitable = true;
......@@ -1379,10 +1383,10 @@ QRhi::FrameOpResult QRhiVulkan::beginNonWrapperFrame(QRhiSwapChain *swapChain)
// will make B wait for A's frame 0 commands, so if a resource is written
// in B's frame or when B checks for pending resource releases, that won't
// mess up A's in-flight commands (as they are not in flight anymore).
waitCommandCompletion(swapChainD->currentFrame);
waitCommandCompletion(swapChainD->currentFrameSlot);
// build new draw command buffer
QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImage]);
QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]);
QRhi::FrameOpResult cbres = startCommandBuffer(&image.cmdBuf);
if (cbres != QRhi::FrameOpSuccess)
return cbres;
......@@ -1391,7 +1395,7 @@ QRhi::FrameOpResult QRhiVulkan::beginNonWrapperFrame(QRhiSwapChain *swapChain)
swapChainD->rtWrapper.d.fb = image.fb;
currentFrameSlot = swapChainD->currentFrame;
currentFrameSlot = swapChainD->currentFrameSlot;
currentSwapChain = swapChainD;
if (swapChainD->ds)
swapChainD->ds->lastActiveFrameSlot = currentFrameSlot;
......@@ -1403,12 +1407,14 @@ QRhi::FrameOpResult QRhiVulkan::beginNonWrapperFrame(QRhiSwapChain *swapChain)
QRhi::FrameOpResult QRhiVulkan::endNonWrapperFrame(QRhiSwapChain *swapChain)
{
QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
Q_ASSERT(inFrame);
inFrame = false;
prepareFrameEnd();
QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
Q_ASSERT(currentSwapChain == swapChainD);
QVkSwapChain::FrameResources &frame(swapChainD->frameRes[swapChainD->currentFrame]);
QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImage]);
QVkSwapChain::FrameResources &frame(swapChainD->frameRes[swapChainD->currentFrameSlot]);
QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]);
if (!image.presentableLayout) {
// was used in a readback as transfer source, go back to presentable layout
......@@ -1447,7 +1453,7 @@ QRhi::FrameOpResult QRhiVulkan::endNonWrapperFrame(QRhiSwapChain *swapChain)
presInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presInfo.swapchainCount = 1;
presInfo.pSwapchains = &swapChainD->sc;
presInfo.pImageIndices = &swapChainD->currentImage;
presInfo.pImageIndices = &swapChainD->currentImageIndex;
presInfo.waitSemaphoreCount = 1;
presInfo.pWaitSemaphores = &frame.drawSem; // gfxQueueFamilyIdx == presQueueFamilyIdx ? &frame.drawSem : &frame.presTransSem;
......@@ -1466,8 +1472,8 @@ QRhi::FrameOpResult QRhiVulkan::endNonWrapperFrame(QRhiSwapChain *swapChain)
frame.imageAcquired = false;
swapChainD->currentFrame = (swapChainD->currentFrame + 1) % QVK_FRAMES_IN_FLIGHT;
swapChainD->currentFrameSlot = (swapChainD->currentFrameSlot + 1) % QVK_FRAMES_IN_FLIGHT;
swapChainD->frameCount += 1;
currentSwapChain = nullptr;
return QRhi::FrameOpSuccess;
......@@ -1501,10 +1507,10 @@ QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb)
QRhi::FrameOpResult QRhiVulkan::endOffscreenFrame()
{
Q_ASSERT(inFrame);
inFrame = false;
Q_ASSERT(ofr.active);
ofr.active = false;
prepareFrameEnd();
if (!ofr.cmdFence) {
VkFenceCreateInfo fenceInfo;
......@@ -1552,7 +1558,7 @@ QRhi::FrameOpResult QRhiVulkan::finish()
qWarning("finish() within a frame is not supported in combination with QVulkanWindow");
return QRhi::FrameOpError;
}
cb = swapChainD->imageRes[swapChainD->currentImage].cmdBuf;
cb = swapChainD->imageRes[swapChainD->currentImageIndex].cmdBuf;
}
QRhi::FrameOpResult submitres = endAndSubmitCommandBuffer(cb, VK_NULL_HANDLE, nullptr, nullptr);
if (submitres != QRhi::FrameOpSuccess)
......@@ -1566,7 +1572,7 @@ QRhi::FrameOpResult QRhiVulkan::finish()
if (ofr.active)
startCommandBuffer(&ofr.cbWrapper.cb);
else
startCommandBuffer(&swapChainD->imageRes[swapChainD->currentImage].cmdBuf);
startCommandBuffer(&swapChainD->imageRes[swapChainD->currentImageIndex].cmdBuf);
}
executeDeferredReleases(true);
......@@ -1640,13 +1646,6 @@ void QRhiVulkan::prepareNewFrame(QRhiCommandBuffer *cb)
finishActiveReadbacks(); // last, in case the readback-completed callback issues rhi calls
}
void QRhiVulkan::prepareFrameEnd()
{
Q_ASSERT(inFrame);
inFrame = false;
++finishedFrameCount;
}
void QRhiVulkan::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
{
Q_ASSERT(inFrame && !inPass);
......@@ -2315,7 +2314,7 @@ void QRhiVulkan::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdat
finishTransferSrc(cb, texD);
} else {
// use the swapchain image
VkImage image = swapChainD->imageRes[swapChainD->currentImage].image;
VkImage image = swapChainD->imageRes[swapChainD->currentImageIndex].image;
VkImageMemoryBarrier barrier;
memset(&barrier, 0, sizeof(barrier));
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
......@@ -2330,7 +2329,7 @@ void QRhiVulkan::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdat
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
0, 0, nullptr, 0, nullptr,
1, &barrier);
swapChainD->imageRes[swapChainD->currentImage].presentableLayout = false;
swapChainD->imageRes[swapChainD->currentImageIndex].presentableLayout = false;
df->vkCmdCopyImageToBuffer(cbD->cb, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, aRb.buf, 1, &copyDesc);
}
......@@ -4451,6 +4450,7 @@ bool QVkSwapChain::buildOrResize()
rtWrapper.d.colorAttCount = 1;
rtWrapper.d.dsAttCount = 1;
rtWrapper.d.resolveAttCount = vkw->sampleCountFlagBits() > VK_SAMPLE_COUNT_1_BIT ? 1 : 0;
frameCount = 0;
wrapWindow = vkw;
return true;
}
......@@ -4532,10 +4532,12 @@ bool QVkSwapChain::buildOrResize()
}
}
frameCount = 0;
wrapWindow = nullptr;
QRHI_PROF;
QRHI_PROF_F(resizeSwapChain(this, QVK_FRAMES_IN_FLIGHT, samples > VK_SAMPLE_COUNT_1_BIT ? QVK_FRAMES_IN_FLIGHT : 0, samples));
wrapWindow = nullptr;
return true;
}
......
......@@ -316,8 +316,9 @@ struct QVkSwapChain : public QRhiSwapChain
quint32 imageIndex = 0;
} frameRes[QVK_FRAMES_IN_FLIGHT];
quint32 currentImage = 0; // index in imageRes
quint32 currentFrame = 0; // index in frameRes
quint32 currentImageIndex = 0; // index in imageRes
quint32 currentFrameSlot = 0; // index in frameRes
int frameCount = 0;
friend class QRhiVulkan;
};
......@@ -435,7 +436,6 @@ public:
QRhi::FrameOpResult beginNonWrapperFrame(QRhiSwapChain *swapChain);
QRhi::FrameOpResult endNonWrapperFrame(QRhiSwapChain *swapChain);
void prepareNewFrame(QRhiCommandBuffer *cb);
void prepareFrameEnd();
void prepareForTransferDest(QRhiCommandBuffer *cb, QVkTexture *texD);
void prepareForTransferSrc(QRhiCommandBuffer *cb, QVkTexture *texD);
void finishTransferDest(QRhiCommandBuffer *cb, QVkTexture *texD);
......@@ -511,7 +511,6 @@ public:
int currentFrameSlot = 0; // 0..FRAMES_IN_FLIGHT-1
bool inFrame = false;
int finishedFrameCount = 0;
bool inPass = false;
QVkSwapChain *currentSwapChain = nullptr;
QSet<QVkSwapChain *> swapchains;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment