Progress on Animation Queue Pipeline

This commit is contained in:
2023-09-15 00:01:41 -04:00
parent 7b58dea692
commit afa0cfbe6d
15 changed files with 342 additions and 30 deletions

View File

@@ -83,3 +83,147 @@ FString FAnimStepDecoder::DebugString(const FAnimStep& step) {
return result;
}
//// Our own copy of the animation queue. We only
//// store the hashes, not the steps. The First element
//// of the queue is the oldest item.
////
//TDeque<FAnimStoredStep> AQ;
//// The sequence number of the first item in AQ.
////
//int32 FirstSeqno;
//// Map from hash to sequence number.
////
//TMap<uint64, int32> HashToSeqno;
//// The sequence number of the first unstarted animation.
////
//int32 UnstartedSeqno;
//// Array of recently-aborted hash values.
//TArray<uint64> AbortedHashes;
FAnimTracker::FAnimTracker() {
AQ.Empty();
FirstSeqno = 0;
HashToSeqno.Empty();
UnstartedSeqno = 0;
AbortedHashes.Empty();
}
void FAnimTracker::Update(std::string_view encqueue) {
// Check for an exact match. If the most recent entry
// in encqueue has the same hash as the most recent
// entry in AQ, then that's an exact match. Or,
// if both are empty, that's also an exact match.
// In case of exact match, abort early, there's no
// further work needed.
//
if (encqueue.empty()) {
if (AQ.IsEmpty()) {
return;
}
} else {
if (!AQ.IsEmpty()) {
FStringDecoder qdecoder(encqueue);
uint64 hash = qdecoder.read_uint64();
if (hash == AQ.Last().Hash) {
return;
}
}
}
// Search for a Luprex animation record that matches
// something that we already have. Yields the sequence
// number of the most recent matching record.
//
// At the same time, push all non-matching records
// after the matching record onto a stack of new records.
//
FAnimQueueDecoder decoder(encqueue);
TArray<FAnimStep> newsteps;
int32 matchingseqno = -1;
while (!decoder.AtEOF()) {
FAnimStep step = decoder.ReadStep();
int32* stepseq = HashToSeqno.Find(step.Hash);
if (stepseq == nullptr) {
newsteps.Emplace(step);
} else {
matchingseqno = *stepseq;
break;
}
}
// Abort all animations after the most recent matching
// record. Animations are aborted in most-recent-first order.
//
int32 nabort = (FirstSeqno + AQ.Num()) - (matchingseqno + 1);
check((nabort >= 0) && (nabort <= AQ.Num()));
for (int32 i = 0; i < nabort; i++) {
uint64 lasthash = AQ.Last().Hash;
HashToSeqno.Remove(lasthash);
AbortedHashes.Emplace(lasthash);
AQ.PopLast();
}
// Transfer the new animations onto the queue.
//
while (!newsteps.IsEmpty()) {
FAnimStep step = newsteps.Pop();
int32 seqno = FirstSeqno + AQ.Num();
AQ.EmplaceLast(step.Hash, step.Body);
HashToSeqno.Emplace(step.Hash, seqno);
}
// Move back the Unstarted pointer, so that the
// unstarted range includes all the new animations.
//
if (UnstartedSeqno > matchingseqno + 1) {
UnstartedSeqno = matchingseqno + 1;
}
// If there are too many animations in AQ, discard
// any very old ones.
//
if (AQ.Num() > 10) {
int ndiscard = AQ.Num() - 10;
for (int i = 0; i < ndiscard; i++) {
uint64 hash = AQ.First().Hash;
HashToSeqno.Remove(hash);
AQ.PopFirst();
}
FirstSeqno += ndiscard;
if (UnstartedSeqno < FirstSeqno) {
UnstartedSeqno = FirstSeqno;
}
}
}
TArray<uint64> FAnimTracker::GetAborted() {
TArray<uint64> result;
result = std::move(AbortedHashes);
AbortedHashes.Empty();
return result;
}
bool FAnimTracker::AnyUnstarted() {
int offset = UnstartedSeqno - FirstSeqno;
return (offset < AQ.Num());
}
FAnimStoredStep FAnimTracker::GetUnstarted() {
int offset = UnstartedSeqno - FirstSeqno;
check(offset < AQ.Num());
return AQ[offset];
}
void FAnimTracker::Started(uint64 hash) {
int offset = UnstartedSeqno - FirstSeqno;
check(offset < AQ.Num());
check(AQ[offset].Hash == hash);
UnstartedSeqno += 1;
}