rhi: d3d11: Rework timestamp query logic
For offscreen frames this is a significant improvement since now we will have timings available after endOffscreenFrame() returns, meaning the behavior matches the Vulkan, D3D12, and Metal backends in this regard. It also enables getting timings in frames that have QRhi::finish() or QRhiCommandBuffer::begin/endExternal() calls. Change-Id: I1cc45a47e7215f342df0b1c600cc481088c8135b Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
parent
373c08d03d
commit
02f30f700d
@ -346,11 +346,6 @@ bool QRhiD3D11::create(QRhi::Flags flags)
|
||||
if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation), reinterpret_cast<void **>(&annotations))))
|
||||
annotations = nullptr;
|
||||
|
||||
if (flags.testFlag(QRhi::EnableTimestamps)) {
|
||||
ofr.timestamps.prepare(2, this);
|
||||
// timestamp queries are optional so we can go on even if they failed
|
||||
}
|
||||
|
||||
deviceLost = false;
|
||||
|
||||
nativeHandlesStruct.dev = dev;
|
||||
@ -376,7 +371,16 @@ void QRhiD3D11::destroy()
|
||||
|
||||
clearShaderCache();
|
||||
|
||||
ofr.timestamps.destroy();
|
||||
if (ofr.tsDisjointQuery) {
|
||||
ofr.tsDisjointQuery->Release();
|
||||
ofr.tsDisjointQuery = nullptr;
|
||||
}
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (ofr.tsQueries[i]) {
|
||||
ofr.tsQueries[i]->Release();
|
||||
ofr.tsQueries[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (annotations) {
|
||||
annotations->Release();
|
||||
@ -1258,7 +1262,6 @@ const QRhiNativeHandles *QRhiD3D11::nativeHandles(QRhiCommandBuffer *cb)
|
||||
void QRhiD3D11::beginExternal(QRhiCommandBuffer *cb)
|
||||
{
|
||||
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
|
||||
// no timestampSwapChain, in order to avoid timestamp mess
|
||||
executeCommandBuffer(cbD);
|
||||
cbD->resetCommands();
|
||||
}
|
||||
@ -1281,6 +1284,19 @@ double QRhiD3D11::lastCompletedGpuTime(QRhiCommandBuffer *cb)
|
||||
return cbD->lastGpuTime;
|
||||
}
|
||||
|
||||
static inline QD3D11RenderTargetData *rtData(QRhiRenderTarget *rt)
|
||||
{
|
||||
switch (rt->resourceType()) {
|
||||
case QRhiResource::SwapChainRenderTarget:
|
||||
return &QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
|
||||
case QRhiResource::TextureRenderTarget:
|
||||
return &QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
|
||||
{
|
||||
Q_UNUSED(flags);
|
||||
@ -1297,12 +1313,22 @@ QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginF
|
||||
|
||||
finishActiveReadbacks();
|
||||
|
||||
if (swapChainD->timestamps.active[currentFrameSlot]) {
|
||||
if (swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex]) {
|
||||
double elapsedSec = 0;
|
||||
if (swapChainD->timestamps.tryQueryTimestamps(currentFrameSlot, context, &elapsedSec))
|
||||
if (swapChainD->timestamps.tryQueryTimestamps(swapChainD->currentTimestampPairIndex, context, &elapsedSec))
|
||||
swapChainD->cb.lastGpuTime = elapsedSec;
|
||||
}
|
||||
|
||||
ID3D11Query *tsStart = swapChainD->timestamps.query[swapChainD->currentTimestampPairIndex * 2];
|
||||
ID3D11Query *tsDisjoint = swapChainD->timestamps.disjointQuery[swapChainD->currentTimestampPairIndex];
|
||||
const bool recordTimestamps = tsStart && tsDisjoint && !swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex];
|
||||
|
||||
QD3D11CommandBuffer::Command &cmd(swapChainD->cb.commands.get());
|
||||
cmd.cmd = QD3D11CommandBuffer::Command::BeginFrame;
|
||||
cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart : nullptr;
|
||||
cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint : nullptr;
|
||||
cmd.args.beginFrame.swapchainData = rtData(&swapChainD->rt);
|
||||
|
||||
return QRhi::FrameOpSuccess;
|
||||
}
|
||||
|
||||
@ -1312,17 +1338,13 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
|
||||
Q_ASSERT(contextState.currentSwapChain = swapChainD);
|
||||
const int currentFrameSlot = swapChainD->currentFrameSlot;
|
||||
|
||||
ID3D11Query *tsDisjoint = swapChainD->timestamps.disjointQuery[currentFrameSlot];
|
||||
const int tsIdx = QD3D11SwapChain::BUFFER_COUNT * currentFrameSlot;
|
||||
ID3D11Query *tsStart = swapChainD->timestamps.query[tsIdx];
|
||||
ID3D11Query *tsEnd = swapChainD->timestamps.query[tsIdx + 1];
|
||||
const bool recordTimestamps = tsDisjoint && tsStart && tsEnd && !swapChainD->timestamps.active[currentFrameSlot];
|
||||
QD3D11CommandBuffer::Command &cmd(swapChainD->cb.commands.get());
|
||||
cmd.cmd = QD3D11CommandBuffer::Command::EndFrame;
|
||||
cmd.args.endFrame.tsQuery = nullptr; // done later manually, see below
|
||||
cmd.args.endFrame.tsDisjointQuery = nullptr;
|
||||
|
||||
// send all commands to the context
|
||||
if (recordTimestamps)
|
||||
executeCommandBuffer(&swapChainD->cb, swapChainD);
|
||||
else
|
||||
executeCommandBuffer(&swapChainD->cb);
|
||||
executeCommandBuffer(&swapChainD->cb);
|
||||
|
||||
if (swapChainD->sampleDesc.Count > 1) {
|
||||
context->ResolveSubresource(swapChainD->backBufferTex, 0,
|
||||
@ -1330,11 +1352,15 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
|
||||
swapChainD->colorFormat);
|
||||
}
|
||||
|
||||
// this is here because we want to include the time spent on the resolve as well
|
||||
// this is here because we want to include the time spent on the ResolveSubresource as well
|
||||
ID3D11Query *tsEnd = swapChainD->timestamps.query[swapChainD->currentTimestampPairIndex * 2 + 1];
|
||||
ID3D11Query *tsDisjoint = swapChainD->timestamps.disjointQuery[swapChainD->currentTimestampPairIndex];
|
||||
const bool recordTimestamps = tsEnd && tsDisjoint && !swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex];
|
||||
if (recordTimestamps) {
|
||||
context->End(tsEnd);
|
||||
context->End(tsDisjoint);
|
||||
swapChainD->timestamps.active[currentFrameSlot] = true;
|
||||
swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex] = true;
|
||||
swapChainD->currentTimestampPairIndex = (swapChainD->currentTimestampPairIndex + 1) % QD3D11SwapChainTimestamps::TIMESTAMP_PAIRS;
|
||||
}
|
||||
|
||||
if (!flags.testFlag(QRhi::SkipPresent)) {
|
||||
@ -1375,12 +1401,36 @@ QRhi::FrameOpResult QRhiD3D11::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi:
|
||||
ofr.cbWrapper.resetState();
|
||||
*cb = &ofr.cbWrapper;
|
||||
|
||||
if (ofr.timestamps.active[ofr.timestampIdx]) {
|
||||
double elapsedSec = 0;
|
||||
if (ofr.timestamps.tryQueryTimestamps(ofr.timestampIdx, context, &elapsedSec))
|
||||
ofr.cbWrapper.lastGpuTime = elapsedSec;
|
||||
if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
|
||||
D3D11_QUERY_DESC queryDesc = {};
|
||||
if (!ofr.tsDisjointQuery) {
|
||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
|
||||
HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
|
||||
if (FAILED(hr)) {
|
||||
qWarning("Failed to create timestamp disjoint query: %s",
|
||||
qPrintable(QSystemError::windowsComString(hr)));
|
||||
return QRhi::FrameOpError;
|
||||
}
|
||||
}
|
||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (!ofr.tsQueries[i]) {
|
||||
HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
|
||||
if (FAILED(hr)) {
|
||||
qWarning("Failed to create timestamp query: %s",
|
||||
qPrintable(QSystemError::windowsComString(hr)));
|
||||
return QRhi::FrameOpError;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QD3D11CommandBuffer::Command &cmd(ofr.cbWrapper.commands.get());
|
||||
cmd.cmd = QD3D11CommandBuffer::Command::BeginFrame;
|
||||
cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] : nullptr;
|
||||
cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery : nullptr;
|
||||
cmd.args.beginFrame.swapchainData = nullptr;
|
||||
|
||||
return QRhi::FrameOpSuccess;
|
||||
}
|
||||
|
||||
@ -1389,25 +1439,39 @@ QRhi::FrameOpResult QRhiD3D11::endOffscreenFrame(QRhi::EndFrameFlags flags)
|
||||
Q_UNUSED(flags);
|
||||
ofr.active = false;
|
||||
|
||||
ID3D11Query *tsDisjoint = ofr.timestamps.disjointQuery[ofr.timestampIdx];
|
||||
ID3D11Query *tsStart = ofr.timestamps.query[ofr.timestampIdx * 2];
|
||||
ID3D11Query *tsEnd = ofr.timestamps.query[ofr.timestampIdx * 2 + 1];
|
||||
const bool recordTimestamps = tsDisjoint && tsStart && tsEnd && !ofr.timestamps.active[ofr.timestampIdx];
|
||||
if (recordTimestamps) {
|
||||
context->Begin(tsDisjoint);
|
||||
context->End(tsStart); // record timestamp; no Begin() for D3D11_QUERY_TIMESTAMP
|
||||
}
|
||||
QD3D11CommandBuffer::Command &cmd(ofr.cbWrapper.commands.get());
|
||||
cmd.cmd = QD3D11CommandBuffer::Command::EndFrame;
|
||||
cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] : nullptr;
|
||||
cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery : nullptr;
|
||||
|
||||
executeCommandBuffer(&ofr.cbWrapper);
|
||||
context->Flush();
|
||||
|
||||
finishActiveReadbacks();
|
||||
|
||||
if (recordTimestamps) {
|
||||
context->End(tsEnd);
|
||||
context->End(tsDisjoint);
|
||||
ofr.timestamps.active[ofr.timestampIdx] = true;
|
||||
ofr.timestampIdx = (ofr.timestampIdx + 1) % 2;
|
||||
if (ofr.tsQueries[0]) {
|
||||
quint64 timestamps[2];
|
||||
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
|
||||
HRESULT hr;
|
||||
bool ok = true;
|
||||
do {
|
||||
hr = context->GetData(ofr.tsDisjointQuery, &dj, sizeof(dj), 0);
|
||||
} while (hr == S_FALSE);
|
||||
ok &= hr == S_OK;
|
||||
do {
|
||||
hr = context->GetData(ofr.tsQueries[1], ×tamps[1], sizeof(quint64), 0);
|
||||
} while (hr == S_FALSE);
|
||||
ok &= hr == S_OK;
|
||||
do {
|
||||
hr = context->GetData(ofr.tsQueries[0], ×tamps[0], sizeof(quint64), 0);
|
||||
} while (hr == S_FALSE);
|
||||
ok &= hr == S_OK;
|
||||
if (ok) {
|
||||
if (!dj.Disjoint && dj.Frequency) {
|
||||
const float elapsedMs = (timestamps[1] - timestamps[0]) / float(dj.Frequency) * 1000.0f;
|
||||
ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QRhi::FrameOpSuccess;
|
||||
@ -1550,7 +1614,7 @@ QRhi::FrameOpResult QRhiD3D11::finish()
|
||||
} else {
|
||||
Q_ASSERT(contextState.currentSwapChain);
|
||||
Q_ASSERT(contextState.currentSwapChain->cb.recordingPass == QD3D11CommandBuffer::NoPass);
|
||||
executeCommandBuffer(&contextState.currentSwapChain->cb); // no timestampSwapChain, in order to avoid timestamp mess
|
||||
executeCommandBuffer(&contextState.currentSwapChain->cb);
|
||||
contextState.currentSwapChain->cb.resetCommands();
|
||||
}
|
||||
}
|
||||
@ -1925,19 +1989,6 @@ void QRhiD3D11::finishActiveReadbacks()
|
||||
f();
|
||||
}
|
||||
|
||||
static inline QD3D11RenderTargetData *rtData(QRhiRenderTarget *rt)
|
||||
{
|
||||
switch (rt->resourceType()) {
|
||||
case QRhiResource::SwapChainRenderTarget:
|
||||
return &QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
|
||||
case QRhiResource::TextureRenderTarget:
|
||||
return &QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void QRhiD3D11::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
|
||||
{
|
||||
Q_ASSERT(QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
|
||||
@ -2643,7 +2694,7 @@ void QRhiD3D11::resetShaderResources()
|
||||
currentShaderMask &= ~StageU##MaskBit; \
|
||||
}
|
||||
|
||||
void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain)
|
||||
void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD)
|
||||
{
|
||||
quint32 stencilRef = 0;
|
||||
float blendConstants[] = { 1, 1, 1, 1 };
|
||||
@ -2656,26 +2707,30 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
|
||||
};
|
||||
int currentShaderMask = 0xFF;
|
||||
|
||||
if (timestampSwapChain) {
|
||||
const int currentFrameSlot = timestampSwapChain->currentFrameSlot;
|
||||
ID3D11Query *tsDisjoint = timestampSwapChain->timestamps.disjointQuery[currentFrameSlot];
|
||||
const int tsIdx = QD3D11SwapChain::BUFFER_COUNT * currentFrameSlot;
|
||||
ID3D11Query *tsStart = timestampSwapChain->timestamps.query[tsIdx];
|
||||
if (tsDisjoint && tsStart && !timestampSwapChain->timestamps.active[currentFrameSlot]) {
|
||||
// The timestamps seem to include vsync time with Present(1), except
|
||||
// when running on a non-primary gpu. This is not ideal. So try working
|
||||
// it around by issuing a semi-fake OMSetRenderTargets early and
|
||||
// writing the first timestamp only afterwards.
|
||||
context->Begin(tsDisjoint);
|
||||
QD3D11RenderTargetData *rtD = rtData(×tampSwapChain->rt);
|
||||
context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
|
||||
context->End(tsStart); // just record a timestamp, no Begin needed
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
|
||||
const QD3D11CommandBuffer::Command &cmd(*it);
|
||||
switch (cmd.cmd) {
|
||||
case QD3D11CommandBuffer::Command::BeginFrame:
|
||||
if (cmd.args.beginFrame.tsDisjointQuery)
|
||||
context->Begin(cmd.args.beginFrame.tsDisjointQuery);
|
||||
if (cmd.args.beginFrame.tsQuery) {
|
||||
if (cmd.args.beginFrame.swapchainData) {
|
||||
// The timestamps seem to include vsync time with Present(1), except
|
||||
// when running on a non-primary gpu. This is not ideal. So try working
|
||||
// it around by issuing a semi-fake OMSetRenderTargets early and
|
||||
// writing the first timestamp only afterwards.
|
||||
QD3D11RenderTargetData *rtD = cmd.args.beginFrame.swapchainData;
|
||||
context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
|
||||
}
|
||||
context->End(cmd.args.beginFrame.tsQuery); // no Begin() for D3D11_QUERY_TIMESTAMP
|
||||
}
|
||||
break;
|
||||
case QD3D11CommandBuffer::Command::EndFrame:
|
||||
if (cmd.args.endFrame.tsQuery)
|
||||
context->End(cmd.args.endFrame.tsQuery);
|
||||
if (cmd.args.endFrame.tsDisjointQuery)
|
||||
context->End(cmd.args.endFrame.tsDisjointQuery);
|
||||
break;
|
||||
case QD3D11CommandBuffer::Command::ResetShaderResources:
|
||||
resetShaderResources();
|
||||
break;
|
||||
@ -4694,14 +4749,13 @@ void QD3D11CommandBuffer::destroy()
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
bool QD3D11Timestamps::prepare(int pairCount, QRhiD3D11 *rhiD)
|
||||
bool QD3D11SwapChainTimestamps::prepare(QRhiD3D11 *rhiD)
|
||||
{
|
||||
// Creates the query objects if not yet done, but otherwise calling this
|
||||
// function is expected to be a no-op.
|
||||
|
||||
Q_ASSERT(pairCount <= MAX_TIMESTAMP_PAIRS);
|
||||
D3D11_QUERY_DESC queryDesc = {};
|
||||
for (int i = 0; i < pairCount; ++i) {
|
||||
for (int i = 0; i < TIMESTAMP_PAIRS; ++i) {
|
||||
if (!disjointQuery[i]) {
|
||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
|
||||
HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
|
||||
@ -4713,7 +4767,7 @@ bool QD3D11Timestamps::prepare(int pairCount, QRhiD3D11 *rhiD)
|
||||
}
|
||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP;
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
const int idx = pairCount * i + j;
|
||||
const int idx = 2 * i + j;
|
||||
if (!query[idx]) {
|
||||
HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
|
||||
if (FAILED(hr)) {
|
||||
@ -4724,20 +4778,19 @@ bool QD3D11Timestamps::prepare(int pairCount, QRhiD3D11 *rhiD)
|
||||
}
|
||||
}
|
||||
}
|
||||
this->pairCount = pairCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
void QD3D11Timestamps::destroy()
|
||||
void QD3D11SwapChainTimestamps::destroy()
|
||||
{
|
||||
for (int i = 0; i < MAX_TIMESTAMP_PAIRS; ++i) {
|
||||
for (int i = 0; i < TIMESTAMP_PAIRS; ++i) {
|
||||
active[i] = false;
|
||||
if (disjointQuery[i]) {
|
||||
disjointQuery[i]->Release();
|
||||
disjointQuery[i] = nullptr;
|
||||
}
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
const int idx = MAX_TIMESTAMP_PAIRS * i + j;
|
||||
const int idx = TIMESTAMP_PAIRS * i + j;
|
||||
if (query[idx]) {
|
||||
query[idx]->Release();
|
||||
query[idx] = nullptr;
|
||||
@ -4746,26 +4799,21 @@ void QD3D11Timestamps::destroy()
|
||||
}
|
||||
}
|
||||
|
||||
bool QD3D11Timestamps::tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec)
|
||||
bool QD3D11SwapChainTimestamps::tryQueryTimestamps(int pairIndex, ID3D11DeviceContext *context, double *elapsedSec)
|
||||
{
|
||||
bool result = false;
|
||||
if (!active[idx])
|
||||
if (!active[pairIndex])
|
||||
return result;
|
||||
|
||||
ID3D11Query *tsDisjoint = disjointQuery[idx];
|
||||
const int tsIdx = pairCount * idx;
|
||||
ID3D11Query *tsStart = query[tsIdx];
|
||||
ID3D11Query *tsEnd = query[tsIdx + 1];
|
||||
ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
|
||||
ID3D11Query *tsStart = query[pairIndex * 2];
|
||||
ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
|
||||
quint64 timestamps[2];
|
||||
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
|
||||
|
||||
bool ok = true;
|
||||
ok &= context->GetData(tsDisjoint, &dj, sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
|
||||
ok &= context->GetData(tsEnd, ×tamps[1], sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
|
||||
// this above is often not ready, not even in frame_where_recorded+2,
|
||||
// not clear why. so make the whole thing async and do not touch the
|
||||
// queries until they are finally all available in frame this+2 or
|
||||
// this+4 or ...
|
||||
ok &= context->GetData(tsStart, ×tamps[0], sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
|
||||
|
||||
if (ok) {
|
||||
@ -4774,8 +4822,8 @@ bool QD3D11Timestamps::tryQueryTimestamps(int idx, ID3D11DeviceContext *context,
|
||||
*elapsedSec = elapsedMs / 1000.0;
|
||||
result = true;
|
||||
}
|
||||
active[idx] = false;
|
||||
} // else leave active set, will retry in a subsequent beginFrame or similar
|
||||
active[pairIndex] = false;
|
||||
} // else leave active set, will retry in a subsequent beginFrame
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -5252,7 +5300,7 @@ bool QD3D11SwapChain::createOrResize()
|
||||
}
|
||||
|
||||
if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
|
||||
timestamps.prepare(BUFFER_COUNT, rhiD);
|
||||
timestamps.prepare(rhiD);
|
||||
// timestamp queries are optional so we can go on even if they failed
|
||||
}
|
||||
|
||||
|
@ -356,6 +356,8 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
||||
|
||||
struct Command {
|
||||
enum Cmd {
|
||||
BeginFrame,
|
||||
EndFrame,
|
||||
ResetShaderResources,
|
||||
SetRenderTarget,
|
||||
Clear,
|
||||
@ -385,6 +387,15 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
||||
// QRhi*/QD3D11* references should be kept at minimum (so no
|
||||
// QRhiTexture/Buffer/etc. pointers).
|
||||
union Args {
|
||||
struct {
|
||||
ID3D11Query *tsQuery;
|
||||
ID3D11Query *tsDisjointQuery;
|
||||
QD3D11RenderTargetData *swapchainData;
|
||||
} beginFrame;
|
||||
struct {
|
||||
ID3D11Query *tsQuery;
|
||||
ID3D11Query *tsDisjointQuery;
|
||||
} endFrame;
|
||||
struct {
|
||||
QRhiRenderTarget *rt;
|
||||
} setRenderTarget;
|
||||
@ -556,17 +567,15 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
||||
}
|
||||
};
|
||||
|
||||
static const int QD3D11_SWAPCHAIN_BUFFER_COUNT = 2;
|
||||
|
||||
struct QD3D11Timestamps
|
||||
struct QD3D11SwapChainTimestamps
|
||||
{
|
||||
static const int MAX_TIMESTAMP_PAIRS = QD3D11_SWAPCHAIN_BUFFER_COUNT;
|
||||
bool active[MAX_TIMESTAMP_PAIRS] = {};
|
||||
ID3D11Query *disjointQuery[MAX_TIMESTAMP_PAIRS] = {};
|
||||
ID3D11Query *query[MAX_TIMESTAMP_PAIRS * 2] = {};
|
||||
int pairCount = 0;
|
||||
static const int TIMESTAMP_PAIRS = 2;
|
||||
|
||||
bool prepare(int pairCount, QRhiD3D11 *rhiD);
|
||||
bool active[TIMESTAMP_PAIRS] = {};
|
||||
ID3D11Query *disjointQuery[TIMESTAMP_PAIRS] = {};
|
||||
ID3D11Query *query[TIMESTAMP_PAIRS * 2] = {};
|
||||
|
||||
bool prepare(QRhiD3D11 *rhiD);
|
||||
void destroy();
|
||||
bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec);
|
||||
};
|
||||
@ -604,7 +613,7 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
||||
ID3D11Texture2D *backBufferTex;
|
||||
ID3D11RenderTargetView *backBufferRtv;
|
||||
ID3D11RenderTargetView *backBufferRtvRight = nullptr;
|
||||
static const int BUFFER_COUNT = QD3D11_SWAPCHAIN_BUFFER_COUNT;
|
||||
static const int BUFFER_COUNT = 2;
|
||||
ID3D11Texture2D *msaaTex[BUFFER_COUNT];
|
||||
ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT];
|
||||
DXGI_SAMPLE_DESC sampleDesc;
|
||||
@ -614,7 +623,8 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
||||
UINT swapInterval = 1;
|
||||
IDCompositionTarget *dcompTarget = nullptr;
|
||||
IDCompositionVisual *dcompVisual = nullptr;
|
||||
QD3D11Timestamps timestamps;
|
||||
QD3D11SwapChainTimestamps timestamps;
|
||||
int currentTimestampPairIndex = 0;
|
||||
};
|
||||
|
||||
class QRhiD3D11 : public QRhiImplementation
|
||||
@ -739,7 +749,7 @@ public:
|
||||
const uint *dynOfsPairs, int dynOfsPairCount,
|
||||
bool offsetOnlyChange);
|
||||
void resetShaderResources();
|
||||
void executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain = nullptr);
|
||||
void executeCommandBuffer(QD3D11CommandBuffer *cbD);
|
||||
DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount) const;
|
||||
void finishActiveReadbacks();
|
||||
void reportLiveObjects(ID3D11Device *device);
|
||||
@ -781,8 +791,8 @@ public:
|
||||
OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
|
||||
bool active = false;
|
||||
QD3D11CommandBuffer cbWrapper;
|
||||
QD3D11Timestamps timestamps;
|
||||
int timestampIdx = 0;
|
||||
ID3D11Query *tsQueries[2] = {};
|
||||
ID3D11Query *tsDisjointQuery = nullptr;
|
||||
} ofr;
|
||||
|
||||
struct TextureReadback {
|
||||
|
Loading…
Reference in New Issue
Block a user