mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-09 00:31:31 +00:00
[common] kvmfr: report cadence hold and lead timing
This commit is contained in:
@@ -104,6 +104,8 @@ typedef struct LG_TransportFrameTiming
|
|||||||
uint64_t postProcessTime;
|
uint64_t postProcessTime;
|
||||||
uint64_t copyTime;
|
uint64_t copyTime;
|
||||||
uint64_t readyTime;
|
uint64_t readyTime;
|
||||||
|
uint64_t holdTime;
|
||||||
|
uint64_t readyLeadTime;
|
||||||
}
|
}
|
||||||
LG_TransportFrameTiming;
|
LG_TransportFrameTiming;
|
||||||
|
|
||||||
|
|||||||
@@ -1085,6 +1085,8 @@ static void lgmp_getFrameTiming(LG_Transport * this,
|
|||||||
timing->postProcessTime = lease->frame->postProcessTime;
|
timing->postProcessTime = lease->frame->postProcessTime;
|
||||||
timing->copyTime = lease->frame->copyTime;
|
timing->copyTime = lease->frame->copyTime;
|
||||||
timing->readyTime = lease->frame->readyTime;
|
timing->readyTime = lease->frame->readyTime;
|
||||||
|
timing->holdTime = lease->frame->holdTime;
|
||||||
|
timing->readyLeadTime = lease->frame->readyLeadTime;
|
||||||
LG_UNLOCK(this->frameLock);
|
LG_UNLOCK(this->frameLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
#include "LGMPConfig.h"
|
#include "LGMPConfig.h"
|
||||||
|
|
||||||
#define KVMFR_MAGIC "KVMFR---"
|
#define KVMFR_MAGIC "KVMFR---"
|
||||||
#define KVMFR_VERSION 28
|
#define KVMFR_VERSION 29
|
||||||
|
|
||||||
// Fallback used by producers that cannot report the source display's SDR
|
// Fallback used by producers that cannot report the source display's SDR
|
||||||
// white level. IDD frames override this with IDDCX_METADATA2::SdrWhiteLevel.
|
// white level. IDD frames override this with IDDCX_METADATA2::SdrWhiteLevel.
|
||||||
@@ -210,24 +210,23 @@ typedef struct KVMFRFrame
|
|||||||
uint64_t captureTime;
|
uint64_t captureTime;
|
||||||
uint64_t postProcessTime;
|
uint64_t postProcessTime;
|
||||||
uint64_t copyTime;
|
uint64_t copyTime;
|
||||||
// Time from copy completion until FrameBuffer::wp publishes readiness.
|
// Non-copy preparation and publication time, excluding cadence hold time.
|
||||||
uint64_t readyTime;
|
uint64_t readyTime;
|
||||||
|
// Time a prepared frame waited for its cadence publication target.
|
||||||
|
uint64_t holdTime;
|
||||||
|
// Time remaining until the cadence deadline when the frame was published.
|
||||||
|
uint64_t readyLeadTime;
|
||||||
|
|
||||||
// Published after the timing fields and matched against frameSerial by the
|
// Published after the timing fields and matched against frameSerial by the
|
||||||
// client. timingValid is written last by the producer.
|
// client. timingValid is written last by the producer.
|
||||||
uint32_t timingSerial;
|
uint32_t timingSerial;
|
||||||
uint32_t timingValid;
|
uint32_t timingValid;
|
||||||
|
|
||||||
// Producer cadence identity. Phase feedback is permitted only when the
|
|
||||||
// matching frame has KVMFR_FRAME_TIMING_PHASE_VALID set.
|
|
||||||
KVMFRFrameTimingFlags timingFlags;
|
KVMFRFrameTimingFlags timingFlags;
|
||||||
uint32_t scheduleGeneration;
|
|
||||||
uint32_t scheduleEpoch;
|
|
||||||
uint32_t scheduleDeadlineSerial;
|
|
||||||
|
|
||||||
// Keep the conditional HDR block and damage rectangles on separate cache
|
// Keep the conditional HDR block and damage rectangles on separate cache
|
||||||
// lines from the producer timing fields.
|
// lines from the producer timing fields.
|
||||||
uint8_t timingReserved[8];
|
uint8_t timingReserved[4];
|
||||||
|
|
||||||
// HDR static metadata (valid when FRAME_FLAG_HDR_METADATA is set)
|
// HDR static metadata (valid when FRAME_FLAG_HDR_METADATA is set)
|
||||||
// Display color primaries in 0.00002 units (SMPTE ST 2086 format)
|
// Display color primaries in 0.00002 units (SMPTE ST 2086 format)
|
||||||
@@ -242,7 +241,13 @@ typedef struct KVMFRFrame
|
|||||||
uint32_t hdrMaxContentLightLevel; // MaxCLL (cd/m²)
|
uint32_t hdrMaxContentLightLevel; // MaxCLL (cd/m²)
|
||||||
uint32_t hdrMaxFrameAverageLightLevel; // MaxFALL (cd/m²)
|
uint32_t hdrMaxFrameAverageLightLevel; // MaxFALL (cd/m²)
|
||||||
|
|
||||||
uint8_t hdrReserved[32];
|
// Producer cadence identity. Phase feedback is permitted only when the
|
||||||
|
// matching frame has KVMFR_FRAME_TIMING_PHASE_VALID set.
|
||||||
|
uint32_t scheduleGeneration;
|
||||||
|
uint32_t scheduleEpoch;
|
||||||
|
uint32_t scheduleDeadlineSerial;
|
||||||
|
|
||||||
|
uint8_t hdrReserved[20];
|
||||||
|
|
||||||
FrameDamageRect damageRects[KVMFR_MAX_DAMAGE_RECTS];
|
FrameDamageRect damageRects[KVMFR_MAX_DAMAGE_RECTS];
|
||||||
}
|
}
|
||||||
@@ -251,9 +256,15 @@ KVMFRFrame;
|
|||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
static_assert(offsetof(KVMFRFrame, captureTime) == 64,
|
static_assert(offsetof(KVMFRFrame, captureTime) == 64,
|
||||||
"KVMFRFrame hot fields must fit in one cache line");
|
"KVMFRFrame hot fields must fit in one cache line");
|
||||||
static_assert(offsetof(KVMFRFrame, timingFlags) == 104,
|
static_assert(offsetof(KVMFRFrame, holdTime) == 96,
|
||||||
|
"KVMFRFrame hold timing layout changed");
|
||||||
|
static_assert(offsetof(KVMFRFrame, readyLeadTime) == 104,
|
||||||
|
"KVMFRFrame ready lead timing layout changed");
|
||||||
|
static_assert(offsetof(KVMFRFrame, timingSerial) == 112,
|
||||||
|
"KVMFRFrame timing publication layout changed");
|
||||||
|
static_assert(offsetof(KVMFRFrame, timingFlags) == 120,
|
||||||
"KVMFRFrame timing flags layout changed");
|
"KVMFRFrame timing flags layout changed");
|
||||||
static_assert(offsetof(KVMFRFrame, scheduleDeadlineSerial) == 116,
|
static_assert(offsetof(KVMFRFrame, scheduleDeadlineSerial) == 168,
|
||||||
"KVMFRFrame schedule identity layout changed");
|
"KVMFRFrame schedule identity layout changed");
|
||||||
static_assert(offsetof(KVMFRFrame, hdrDisplayPrimary) == 128,
|
static_assert(offsetof(KVMFRFrame, hdrDisplayPrimary) == 128,
|
||||||
"KVMFRFrame HDR metadata must be cache-line aligned");
|
"KVMFRFrame HDR metadata must be cache-line aligned");
|
||||||
@@ -262,9 +273,15 @@ static_assert(offsetof(KVMFRFrame, damageRects) == 192,
|
|||||||
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||||
_Static_assert(offsetof(KVMFRFrame, captureTime) == 64,
|
_Static_assert(offsetof(KVMFRFrame, captureTime) == 64,
|
||||||
"KVMFRFrame hot fields must fit in one cache line");
|
"KVMFRFrame hot fields must fit in one cache line");
|
||||||
_Static_assert(offsetof(KVMFRFrame, timingFlags) == 104,
|
_Static_assert(offsetof(KVMFRFrame, holdTime) == 96,
|
||||||
|
"KVMFRFrame hold timing layout changed");
|
||||||
|
_Static_assert(offsetof(KVMFRFrame, readyLeadTime) == 104,
|
||||||
|
"KVMFRFrame ready lead timing layout changed");
|
||||||
|
_Static_assert(offsetof(KVMFRFrame, timingSerial) == 112,
|
||||||
|
"KVMFRFrame timing publication layout changed");
|
||||||
|
_Static_assert(offsetof(KVMFRFrame, timingFlags) == 120,
|
||||||
"KVMFRFrame timing flags layout changed");
|
"KVMFRFrame timing flags layout changed");
|
||||||
_Static_assert(offsetof(KVMFRFrame, scheduleDeadlineSerial) == 116,
|
_Static_assert(offsetof(KVMFRFrame, scheduleDeadlineSerial) == 168,
|
||||||
"KVMFRFrame schedule identity layout changed");
|
"KVMFRFrame schedule identity layout changed");
|
||||||
_Static_assert(offsetof(KVMFRFrame, hdrDisplayPrimary) == 128,
|
_Static_assert(offsetof(KVMFRFrame, hdrDisplayPrimary) == 128,
|
||||||
"KVMFRFrame HDR metadata must be cache-line aligned");
|
"KVMFRFrame HDR metadata must be cache-line aligned");
|
||||||
|
|||||||
@@ -403,6 +403,8 @@ static bool sendFrame(CaptureResult result, bool * restart)
|
|||||||
fi->postProcessTime = 0;
|
fi->postProcessTime = 0;
|
||||||
fi->copyTime = 0;
|
fi->copyTime = 0;
|
||||||
fi->readyTime = 0;
|
fi->readyTime = 0;
|
||||||
|
fi->holdTime = 0;
|
||||||
|
fi->readyLeadTime = 0;
|
||||||
fi->timingSerial = 0;
|
fi->timingSerial = 0;
|
||||||
fi->timingFlags = 0;
|
fi->timingFlags = 0;
|
||||||
fi->scheduleGeneration = 0;
|
fi->scheduleGeneration = 0;
|
||||||
|
|||||||
@@ -1973,6 +1973,8 @@ CIndirectDeviceContext::PreparedFrameBuffer CIndirectDeviceContext::PrepareFrame
|
|||||||
fi->postProcessTime = 0;
|
fi->postProcessTime = 0;
|
||||||
fi->copyTime = 0;
|
fi->copyTime = 0;
|
||||||
fi->readyTime = 0;
|
fi->readyTime = 0;
|
||||||
|
fi->holdTime = 0;
|
||||||
|
fi->readyLeadTime = 0;
|
||||||
fi->timingSerial = 0;
|
fi->timingSerial = 0;
|
||||||
fi->timingFlags = 0;
|
fi->timingFlags = 0;
|
||||||
fi->scheduleGeneration = 0;
|
fi->scheduleGeneration = 0;
|
||||||
@@ -2343,8 +2345,8 @@ void CIndirectDeviceContext::CompleteFrameBuffer(
|
|||||||
|
|
||||||
void CIndirectDeviceContext::SetFrameTiming(unsigned frameIndex,
|
void CIndirectDeviceContext::SetFrameTiming(unsigned frameIndex,
|
||||||
uint64_t captureTime, uint64_t postProcessTime, uint64_t copyTime,
|
uint64_t captureTime, uint64_t postProcessTime, uint64_t copyTime,
|
||||||
uint64_t readyTime, const CFrameScheduler::Schedule& schedule,
|
uint64_t readyTime, uint64_t holdTime,
|
||||||
uint64_t completedAt)
|
const CFrameScheduler::Schedule& schedule, uint64_t completedAt)
|
||||||
{
|
{
|
||||||
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
|
if (frameIndex >= LGMP_Q_FRAME_BUFFER_LEN)
|
||||||
return;
|
return;
|
||||||
@@ -2357,6 +2359,10 @@ void CIndirectDeviceContext::SetFrameTiming(unsigned frameIndex,
|
|||||||
frame->postProcessTime = postProcessTime;
|
frame->postProcessTime = postProcessTime;
|
||||||
frame->copyTime = copyTime;
|
frame->copyTime = copyTime;
|
||||||
frame->readyTime = readyTime;
|
frame->readyTime = readyTime;
|
||||||
|
frame->holdTime = holdTime;
|
||||||
|
frame->readyLeadTime = phaseValid &&
|
||||||
|
schedule.deadline >= completedAt ?
|
||||||
|
schedule.deadline - completedAt : 0;
|
||||||
frame->timingFlags = phaseValid ?
|
frame->timingFlags = phaseValid ?
|
||||||
KVMFR_FRAME_TIMING_PHASE_VALID : 0;
|
KVMFR_FRAME_TIMING_PHASE_VALID : 0;
|
||||||
frame->timingSerial = frame->frameSerial;
|
frame->timingSerial = frame->frameSerial;
|
||||||
|
|||||||
@@ -299,7 +299,8 @@ public:
|
|||||||
void CompleteFrameBuffer(unsigned frameIndex, bool succeeded);
|
void CompleteFrameBuffer(unsigned frameIndex, bool succeeded);
|
||||||
void SetFrameTiming(unsigned frameIndex, uint64_t captureTime,
|
void SetFrameTiming(unsigned frameIndex, uint64_t captureTime,
|
||||||
uint64_t postProcessTime, uint64_t copyTime, uint64_t readyTime,
|
uint64_t postProcessTime, uint64_t copyTime, uint64_t readyTime,
|
||||||
const CFrameScheduler::Schedule& schedule, uint64_t completedAt);
|
uint64_t holdTime, const CFrameScheduler::Schedule& schedule,
|
||||||
|
uint64_t completedAt);
|
||||||
void WriteFrameBuffer(unsigned frameIndex, void* src, size_t offset, size_t len, bool setWritePos) const;
|
void WriteFrameBuffer(unsigned frameIndex, void* src, size_t offset, size_t len, bool setWritePos) const;
|
||||||
void FinalizeFrameBuffer(unsigned frameIndex) const;
|
void FinalizeFrameBuffer(unsigned frameIndex) const;
|
||||||
|
|
||||||
|
|||||||
@@ -766,12 +766,21 @@ void CSwapChainProcessor::CompletionFunction(
|
|||||||
// discarded.
|
// discarded.
|
||||||
sc->m_devContext->FinalizeFrameBuffer(fbRes->GetFrameIndex());
|
sc->m_devContext->FinalizeFrameBuffer(fbRes->GetFrameIndex());
|
||||||
const uint64_t publishedAt = CFrameScheduler::Nanotime();
|
const uint64_t publishedAt = CFrameScheduler::Nanotime();
|
||||||
const uint64_t elapsed = publishedAt - postProcessStart;
|
const uint64_t prepareElapsed = prepareReady >= postProcessStart ?
|
||||||
const uint64_t measured = postProcessTime + copyTime;
|
prepareReady - postProcessStart : 0;
|
||||||
const uint64_t readyTime = elapsed > measured ? elapsed - measured : 0;
|
const uint64_t prepareMeasured = postProcessTime + prepareCopyTime;
|
||||||
|
const uint64_t prepareReadyTime = prepareElapsed > prepareMeasured ?
|
||||||
|
prepareElapsed - prepareMeasured : 0;
|
||||||
|
const uint64_t publishElapsed = publishedAt >= publishStart ?
|
||||||
|
publishedAt - publishStart : 0;
|
||||||
|
const uint64_t publishReadyTime = publishElapsed > publishCopyTime ?
|
||||||
|
publishElapsed - publishCopyTime : 0;
|
||||||
|
const uint64_t readyTime = prepareReadyTime + publishReadyTime;
|
||||||
|
const uint64_t holdTime = publishStart >= prepareReady ?
|
||||||
|
publishStart - prepareReady : 0;
|
||||||
|
|
||||||
sc->m_devContext->SetFrameTiming(fbRes->GetFrameIndex(),
|
sc->m_devContext->SetFrameTiming(fbRes->GetFrameIndex(),
|
||||||
fbRes->GetCaptureTime(), postProcessTime, copyTime, readyTime,
|
fbRes->GetCaptureTime(), postProcessTime, copyTime, readyTime, holdTime,
|
||||||
fbRes->GetSchedule(), publishedAt);
|
fbRes->GetSchedule(), publishedAt);
|
||||||
sc->m_devContext->TryRecordFrameTiming(
|
sc->m_devContext->TryRecordFrameTiming(
|
||||||
publishedAt - publishStart);
|
publishedAt - publishStart);
|
||||||
|
|||||||
Reference in New Issue
Block a user