From 39b803fa3d90282cec70e309250a32797ea30890 Mon Sep 17 00:00:00 2001 From: dreamstalker Date: Sat, 23 May 2015 20:05:48 +0400 Subject: [PATCH] Delta encoder tests: refactoring Added prefetches to delta and deltaJit --- rehlds/engine/delta_jit.cpp | 141 ++++++---- rehlds/engine/delta_jit.h | 17 +- rehlds/engine/sv_main.cpp | 12 +- rehlds/public/rehlds/osconfig.h | 1 + rehlds/unittests/delta_tests.cpp | 424 +++++++++++-------------------- 5 files changed, 261 insertions(+), 334 deletions(-) diff --git a/rehlds/engine/delta_jit.cpp b/rehlds/engine/delta_jit.cpp index 6358701..59fab3d 100644 --- a/rehlds/engine/delta_jit.cpp +++ b/rehlds/engine/delta_jit.cpp @@ -3,20 +3,6 @@ CDeltaJitRegistry g_DeltaJitRegistry; -bool deltajit_memblock::isEmpty() const -{ - if (numFields == 0) - return true; - - for (size_t i = 0; i < numFields; i++) - { - if (fields[i].mask != 0) - return false; - } - - return true; -} - uint32 DELTAJIT_CreateMask(int startBit, int endBit) { if (startBit < 0) startBit = 0; if (endBit < 0) endBit = 0; @@ -83,7 +69,7 @@ void DELTAJIT_CreateDescription(delta_t* delta, deltajitdata_t &jitdesc) { jitdesc.numblocks = numMemBlocks; jitdesc.numFields = delta->fieldCount; - //create descriptions (primitive types) + //create descriptions for (int i = 0; i < delta->fieldCount; i++) { delta_description_t* fieldDesc = &delta->pdd[i]; @@ -119,6 +105,25 @@ void DELTAJIT_CreateDescription(delta_t* delta, deltajitdata_t &jitdesc) { } } + //calculate blocks that we should check + for (unsigned int i = 0; i < jitdesc.numblocks; i++) { + if (jitdesc.blocks[i].numFields > 0) { + jitdesc.itrBlocks[jitdesc.numItrBlocks].memblockId = i; + jitdesc.itrBlocks[jitdesc.numItrBlocks].memblock = &jitdesc.blocks[i]; + jitdesc.itrBlocks[jitdesc.numItrBlocks].prefetchBlockId = -1; + jitdesc.numItrBlocks++; + } + } + + //decide which blocks we should prefetch + for (unsigned int i = 0; i < jitdesc.numItrBlocks; i++) { + unsigned int prefetchBlkId = (i + 1) * 4; + if (prefetchBlkId >= jitdesc.numblocks) + break; + + jitdesc.itrBlocks[i].prefetchBlockId = prefetchBlkId; + } + } class CDeltaClearMarkFieldsJIT; @@ -130,7 +135,7 @@ public: int markedFieldsMaskSize; - int marked_fields_mask[2]; + delta_marked_mask_t marked_fields_mask; int sse_highbits[2]; //High 64 bits for manipulating marked_fields_mask via SSE registers CDeltaJit(delta_t* _delta, CDeltaClearMarkFieldsJIT* _cleanMarkCheckFunc); @@ -143,7 +148,7 @@ public: deltajitdata_t *jitdesc; deltajit_marked_count_type_t countType; - XmmReg marked_fields_mask = xmm5; + XmmReg marked_fields_mask = xmm7; CDeltaClearMarkFieldsJIT(deltajitdata_t *_jitdesc, deltajit_marked_count_type_t _countType) @@ -258,43 +263,67 @@ CDeltaClearMarkFieldsJIT::Result CDeltaClearMarkFieldsJIT::main(Addr src, Addr d sub(esp, 12); //some local storage is required for precise DT_TIMEWINDOW marking #endif + /* + Registers usage: + esi = src + edi = dst + xmm0-xmm2: loaded src + xmm3-xmm5: loaded dst + xmm6: temp + xmm7: marked fields mask + */ mov(esi, ptr[src]); mov(edi, ptr[dst]); - for (unsigned int i = 0; i < jitdesc->numblocks; i++) { - if (!jitdesc->blocks[i].isEmpty()) { - movdqu(xmm3, xmmword_ptr[esi + (i * 16)]); - movdqu(xmm4, xmmword_ptr[edi + (i * 16)]); - break; - } + int dataXmmCounter = 0; // from 0 to 2 => 3 pairs of registers + jitasm::Frontend::XmmReg src_xmm[3] = { xmm0, xmm1, xmm2 }; + jitasm::Frontend::XmmReg dst_xmm[3] = { xmm3, xmm4, xmm5 }; + // overall mask is in xmm7 (marked_fields_mask) + auto xmm_tmp = xmm6; + + + if (jitdesc->numItrBlocks > 0) { + movdqu(src_xmm[0], xmmword_ptr[esi + (jitdesc->itrBlocks[0].memblockId * 16)]); + movdqu(dst_xmm[0], xmmword_ptr[edi + (jitdesc->itrBlocks[0].memblockId * 16)]); + } + if (jitdesc->numItrBlocks > 1) { + movdqu(src_xmm[1], xmmword_ptr[esi + (jitdesc->itrBlocks[1].memblockId * 16)]); + movdqu(dst_xmm[1], xmmword_ptr[edi + (jitdesc->itrBlocks[1].memblockId * 16)]); + } + if (jitdesc->numItrBlocks > 2) { + movdqu(src_xmm[2], xmmword_ptr[esi + (jitdesc->itrBlocks[2].memblockId * 16)]); + movdqu(dst_xmm[2], xmmword_ptr[edi + (jitdesc->itrBlocks[2].memblockId * 16)]); } - auto mask = ecx; - xor_(mask, mask); + auto blockMask = ecx; + xor_(blockMask, blockMask); pxor(marked_fields_mask, marked_fields_mask); - for (unsigned int i = 0; i < jitdesc->numblocks; i++) { - auto block = &jitdesc->blocks[i]; + for (unsigned int i = 0; i < jitdesc->numItrBlocks; i++) { + auto block = jitdesc->itrBlocks[i].memblock; + auto itrBlock = &jitdesc->itrBlocks[i]; - if (block->isEmpty()) - continue; - - movdqa(xmm0, xmm3); - movdqa(xmm1, xmm4); - - //prefetch next blocks - for (unsigned int j = i + 1; j < jitdesc->numblocks; j++) { - if (!jitdesc->blocks[j].isEmpty()) { - movdqu(xmm3, xmmword_ptr[esi + (j * 16)]); - movdqu(xmm4, xmmword_ptr[edi + (j * 16)]); - break; - } + //do far prefetch + if (itrBlock->prefetchBlockId != -1) { + prefetcht0(byte_ptr[esi + (itrBlock->prefetchBlockId * 16)]); + prefetcht0(byte_ptr[edi + (itrBlock->prefetchBlockId * 16)]); } - pcmpeqb(xmm0, xmm1); - pmovmskb(mask, xmm0); - not_(mask); + pcmpeqb(src_xmm[dataXmmCounter], dst_xmm[dataXmmCounter]); + pmovmskb(blockMask, src_xmm[dataXmmCounter]); + not_(blockMask); + + //preload next blocks + if (i + 3 < jitdesc->numItrBlocks) { + movdqu(src_xmm[dataXmmCounter], xmmword_ptr[esi + (jitdesc->itrBlocks[i + 3].memblockId * 16)]); + movdqu(dst_xmm[dataXmmCounter], xmmword_ptr[edi + (jitdesc->itrBlocks[i + 3].memblockId * 16)]); + } + + dataXmmCounter++; + if (dataXmmCounter > 2) { + dataXmmCounter -= 3; + } for (unsigned int j = 0; j < block->numFields; j++) { auto jitField = &block->fields[j]; @@ -327,16 +356,16 @@ CDeltaClearMarkFieldsJIT::Result CDeltaClearMarkFieldsJIT::main(Addr src, Addr d continue; } } else { - checkFieldMask(mask, jitField); + checkFieldMask(blockMask, jitField); } #else - checkFieldMask(mask, jitField); + checkFieldMask(blockMask, jitField); #endif // set bit in send mask - movd(xmm0, edx); - psllq(xmm0, jitField->field->id); - por(marked_fields_mask, xmm0); + movd(xmm_tmp, edx); + psllq(xmm_tmp, jitField->field->id); + por(marked_fields_mask, xmm_tmp); } } @@ -470,8 +499,8 @@ NOINLINE int DELTAJit_Fields_Clear_Mark_Check(unsigned char *from, unsigned char void DELTAJit_SetSendFlagBits(delta_t *pFields, int *bits, int *bytecount) { CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields); - bits[0] = deltaJit->marked_fields_mask[0]; - bits[1] = deltaJit->marked_fields_mask[1]; + bits[0] = deltaJit->marked_fields_mask.u32[0]; + bits[1] = deltaJit->marked_fields_mask.u32[1]; *bytecount = deltaJit->markedFieldsMaskSize; } @@ -479,9 +508,9 @@ void DELTAJit_SetFieldByIndex(struct delta_s *pFields, int fieldNumber) { CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields); if (fieldNumber > 31) - deltaJit->marked_fields_mask[1] |= (1 << (fieldNumber & 0x1F)); + deltaJit->marked_fields_mask.u32[1] |= (1 << (fieldNumber & 0x1F)); else - deltaJit->marked_fields_mask[0] |= (1 << fieldNumber); + deltaJit->marked_fields_mask.u32[0] |= (1 << fieldNumber); } @@ -489,18 +518,18 @@ void DELTAJit_UnsetFieldByIndex(struct delta_s *pFields, int fieldNumber) { CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields); if (fieldNumber > 31) - deltaJit->marked_fields_mask[1] &= ~(1 << (fieldNumber & 0x1F)); + deltaJit->marked_fields_mask.u32[1] &= ~(1 << (fieldNumber & 0x1F)); else - deltaJit->marked_fields_mask[0] &= ~(1 << fieldNumber); + deltaJit->marked_fields_mask.u32[0] &= ~(1 << fieldNumber); } qboolean DELTAJit_IsFieldMarked(delta_t* pFields, int fieldNumber) { CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields); if (fieldNumber > 31) - return deltaJit->marked_fields_mask[1] & (1 << (fieldNumber & 0x1F)); + return deltaJit->marked_fields_mask.u32[1] & (1 << (fieldNumber & 0x1F)); - return deltaJit->marked_fields_mask[0] & (1 << fieldNumber); + return deltaJit->marked_fields_mask.u32[0] & (1 << fieldNumber); } void CDeltaJitRegistry::Cleanup() { diff --git a/rehlds/engine/delta_jit.h b/rehlds/engine/delta_jit.h index cdd9c50..0209dac 100644 --- a/rehlds/engine/delta_jit.h +++ b/rehlds/engine/delta_jit.h @@ -23,7 +23,12 @@ struct deltajit_memblock_field { struct deltajit_memblock { unsigned int numFields; deltajit_memblock_field fields[24]; - bool isEmpty() const; +}; + +struct deltajit_memblock_itr_t { + int memblockId; + deltajit_memblock* memblock; + int prefetchBlockId; }; struct deltajitdata_t { @@ -32,6 +37,9 @@ struct deltajitdata_t { unsigned int numFields; deltajit_field fields[DELTAJIT_MAX_FIELDS]; + + unsigned int numItrBlocks; + deltajit_memblock_itr_t itrBlocks[DELTAJIT_MAX_BLOCKS]; }; enum deltajit_marked_count_type_t { @@ -56,6 +64,13 @@ public: void Cleanup(); }; +union delta_marked_mask_t { + uint8 u8[8]; + uint32 u32[2]; + uint64 u64; +}; + + extern CDeltaJitRegistry g_DeltaJitRegistry; extern int DELTAJit_Fields_Clear_Mark_Check(unsigned char *from, unsigned char *to, delta_t *pFields); diff --git a/rehlds/engine/sv_main.cpp b/rehlds/engine/sv_main.cpp index a054931..8255e7e 100644 --- a/rehlds/engine/sv_main.cpp +++ b/rehlds/engine/sv_main.cpp @@ -4156,6 +4156,8 @@ int SV_CreatePacketEntities(sv_delta_t type, client_t *client, packet_entities_t { client_frame_t *fromframe = &client->frames[SV_UPDATE_MASK & client->delta_sequence]; from = &fromframe->entities; + _mm_prefetch((const char*)&from->entities[0], _MM_HINT_T0); + _mm_prefetch(((const char*)&from->entities[0]) + 64, _MM_HINT_T0); oldmax = from->num_entities; MSG_WriteByte(msg, svc_deltapacketentities); MSG_WriteShort(msg, to->num_entities); @@ -4169,8 +4171,8 @@ int SV_CreatePacketEntities(sv_delta_t type, client_t *client, packet_entities_t MSG_WriteShort(msg, to->num_entities); } - newnum = 0; - oldnum = 0; + newnum = 0; //index in to->entities + oldnum = 0; //index in from->entities MSG_StartBitWriting(msg); while (1) { @@ -4201,6 +4203,8 @@ int SV_CreatePacketEntities(sv_delta_t type, client_t *client, packet_entities_t SV_SetCallback(newindex, FALSE, custom, &numbase, FALSE, 0); DELTA_WriteDelta((uint8 *)&from->entities[oldnum], (uint8 *)baseline_, FALSE, custom ? g_pcustomentitydelta : (SV_IsPlayerIndex(newindex) ? g_pplayerdelta : g_pentitydelta), &SV_InvokeCallback); ++oldnum; + _mm_prefetch((const char*)&from->entities[oldnum], _MM_HINT_T0); + _mm_prefetch(((const char*)&from->entities[oldnum]) + 64, _MM_HINT_T0); ++newnum; continue; } @@ -4211,6 +4215,8 @@ int SV_CreatePacketEntities(sv_delta_t type, client_t *client, packet_entities_t { SV_WriteDeltaHeader(oldindex, TRUE, FALSE, &numbase, FALSE, 0, FALSE, 0); ++oldnum; + _mm_prefetch((const char*)&from->entities[oldnum], _MM_HINT_T0); + _mm_prefetch(((const char*)&from->entities[oldnum]) + 64, _MM_HINT_T0); } continue; } @@ -4243,6 +4249,8 @@ int SV_CreatePacketEntities(sv_delta_t type, client_t *client, packet_entities_t if (!from) { int offset = SV_FindBestBaseline(newnum, &baseline_, to->entities, newindex, custom); + _mm_prefetch((const char*)baseline_, _MM_HINT_T0); + _mm_prefetch(((const char*)baseline_) + 64, _MM_HINT_T0); if (offset) SV_SetCallback(newindex, 0, custom, &numbase, 1, offset); } diff --git a/rehlds/public/rehlds/osconfig.h b/rehlds/public/rehlds/osconfig.h index 772d730..da499b2 100644 --- a/rehlds/public/rehlds/osconfig.h +++ b/rehlds/public/rehlds/osconfig.h @@ -45,6 +45,7 @@ #include #include +#include #ifdef _WIN32 // WINDOWS #include diff --git a/rehlds/unittests/delta_tests.cpp b/rehlds/unittests/delta_tests.cpp index 5bfc56d..252e6ea 100644 --- a/rehlds/unittests/delta_tests.cpp +++ b/rehlds/unittests/delta_tests.cpp @@ -26,6 +26,7 @@ struct delta_test_struct_t { uint8 b_61; //20 }; #pragma pack(pop) +typedef delta_test_struct_t dts_t; struct delta_res_t { @@ -73,58 +74,89 @@ NOINLINE qboolean _DoMarkFields(void* src, void* dst, delta_t* delta, bool useJi return sendfields; } -NOINLINE bool _CheckFieldMarked(delta_t* delta, int fieldIdx, int usejit) { - if (usejit) { - return DELTAJit_IsFieldMarked(delta, fieldIdx) != 0; - } else { - return delta->pdd[fieldIdx].flags & FDT_MARK; - } -} -NOINLINE void _EnsureFieldsChanged(const char* callsite, const char* action, int usejit, bool changed, delta_t* delta, ...) { - va_list vargs; - va_start(vargs, delta); - const char* fieldName = va_arg(vargs, const char*); - while (fieldName) { - delta_description_t* field = NULL; - int idx = 0; - for (; idx < delta->fieldCount; idx++) { - if (!strcmp(fieldName, delta->pdd[idx].fieldName)) { - field = &delta->pdd[idx]; - break; +NOINLINE void _MarkAndEnsureCorrectResults(const char* action, delta_t* delta, void* src, void* dst, int useJit, bool changed, const char* szFields) { + delta_description_t* fields[DELTA_MAX_FIELDS]; + int numFields = 0; + + char localFieldsStr[512]; + strcpy(localFieldsStr, szFields); + + //parse fields + int prevEnd = -1; + for (char* pcc = localFieldsStr; *pcc; pcc++) { + if (*pcc == ' ') { + *pcc = 0; + int fIdx = DELTA_FindFieldIndex(delta, &localFieldsStr[prevEnd + 1]); + if (fIdx == -1) { + rehlds_syserror("%s: Coult not find field '%s'", &localFieldsStr[prevEnd + 1]); } + fields[numFields++] = &delta->pdd[fIdx]; + prevEnd = pcc - localFieldsStr; } - - if (field == NULL) { - rehlds_syserror("%s: %s: Could not find delta field '%s'", callsite, action, fieldName); - } - - if (field->flags & 0x80) { - rehlds_syserror("%s: %s: Field '%s' is marked as processed", callsite, action, fieldName); - } - - - if (_CheckFieldMarked(delta, idx, usejit) ^ changed) { - rehlds_syserror("%s: %s: Field '%s' is expected to be marked", callsite, action, fieldName); - } - - field->flags |= 0x80; - - fieldName = va_arg(vargs, const char*); } - for (int i = 0; i < delta->fieldCount; i++) { - delta_description_t* field = &delta->pdd[i]; - if (field->flags & 0x80) - continue; - - if (_CheckFieldMarked(delta, i, usejit) ^ !changed) { - rehlds_syserror("%s: %s: Field '%s' is expected to be unmarked", callsite, action, field->fieldName); + if (localFieldsStr[0] != 0) { + int fIdx = DELTA_FindFieldIndex(delta, &localFieldsStr[prevEnd + 1]); + if (fIdx == -1) { + rehlds_syserror("%s: Coult not find field '%s'", &localFieldsStr[prevEnd + 1]); } - + fields[numFields++] = &delta->pdd[fIdx]; } + + //build expected mask + delta_marked_mask_t expectedMask; expectedMask.u64 = 0; + for (int i = 0; i < numFields; i++) { + delta_description_t* f = fields[i]; + int fieldId = f - delta->pdd; + expectedMask.u8[fieldId >> 3] |= (1 << (fieldId & 0x7)); + } + + if (!changed) { + //invert mask + uint64 existingFieldsMask = 0xFFFFFFFFFFFFFFFF; + existingFieldsMask = existingFieldsMask >> (64 - delta->fieldCount); + + expectedMask.u64 = ~expectedMask.u64; + expectedMask.u64 &= existingFieldsMask; + } + + //calculate expected bytecount + int expectedBytecount = 0; + for (int i = 0; i < ARRAYSIZE(expectedMask.u8); i++) { + if (expectedMask.u8[i]) { + expectedBytecount = i + 1; + } + } + + //do marking + qboolean markResult = _DoMarkFields(src, dst, delta, useJit != 0); + + //check marking result + if ((markResult != 0) != (expectedMask.u64 != 0)) { + rehlds_syserror("%s: DoMarkFields returned invalid value %d, expected %s", action, markResult, (expectedMask.u64 == 0) ? "0" : "!0"); + } + + delta_marked_mask_t returnedMask; + int returnedBytecount; + if (useJit) { + DELTAJit_SetSendFlagBits(delta, (int*)returnedMask.u32, &returnedBytecount); + } else { + DELTA_SetSendFlagBits(delta, (int*)returnedMask.u32, &returnedBytecount); + } + + //check per-field marks + if (returnedMask.u64 != expectedMask.u64) { + rehlds_syserror("%s: DoMarkFields returned invalid mask %llX, expected %llX", action, returnedMask.u64, expectedMask.u64); + } + + //check bytecount + if (returnedBytecount != expectedBytecount) { + rehlds_syserror("%s: DoMarkFields returned invalid bytecount %d, expected %d", action, returnedBytecount, expectedBytecount); + } } + NOINLINE void _GetBitmaskAndBytecount(delta_t* delta, int* bits, int* bytecount, int usejit) { if (usejit) { DELTAJit_SetSendFlagBits(delta, bits, bytecount); @@ -149,7 +181,7 @@ NOINLINE void _CompareDeltaResults(const char* callsite, delta_res_t* def, delta NOINLINE delta_t* _CreateTestDeltaDesc() { static delta_description_t _fields[32]; - delta_test_struct_t d; d; // "use" d variable + delta_test_struct_t d; // "use" d variable _InitDeltaField(&_fields[0], 0x00, DT_BYTE, "b_00", offsetof(delta_test_struct_t, b_00), 1, 8, 1.0f, 1.0f); _InitDeltaField(&_fields[1], 0x01, DT_BYTE, "b_01", offsetof(delta_test_struct_t, b_01), 1, 8, 1.0f, 1.0f); @@ -194,266 +226,108 @@ NOINLINE delta_t* _CreateTestDeltaDesc() { return delta; }; -TEST(MarkFieldsTest_Simple_Primitives, Delta, 1000) { +struct delta_simpletest_data_t { + const char* action; + int fill1, fill2; + bool changed; + const char* fields; + std::function act; +}; +delta_test_struct_t dst1, dst2; + +void _DeltaSimpleTest(delta_simpletest_data_t* t, delta_t* delta, int jit) { + _FillTestDelta(&dst1, t->fill1); _FillTestDelta(&dst2, t->fill2); + t->act(); + _MarkAndEnsureCorrectResults(t->action, delta, &dst1, &dst2, jit, t->changed, t->fields); +} + +void _DeltaSimpleTests(delta_t* delta, delta_simpletest_data_t* tests, int testsCount) { + for (int usejit = 0; usejit <= 1; usejit++) { + for (int i = 0; i < testsCount; i++) { + _DeltaSimpleTest(tests + i, delta, usejit); + } + } +} + + +TEST(MarkFieldsTest_Simple_Primitives, Delta, 1000) { delta_t* delta = _CreateTestDeltaDesc(); - delta_test_struct_t d1; - delta_test_struct_t d2; - delta_res_t res[2][10]; + delta_simpletest_data_t testdata[] = { + { "SimpleUnchangedAll1", 0x71, 0x71, true, "", [](){} }, + { "SimpleUnchangedAll2", 0x71, 0x72, false, "", [](){} }, + { "Byte_0BlockCheck", 0x71, 0x71, true, "b_01", []() { dst2.b_01 = 0; } }, + { "Byte_1BlockCheck", 0x71, 0x71, true, "b_11", []() { dst2.b_11 = 0; } }, + { "Short_0BlockCheck", 0x71, 0x71, true, "s_02", []() { dst2.s_02 = 0; } }, + { "Short_1BlockCheck", 0x71, 0x71, true, "s_12", []() { dst2.s_12 = 0; } }, + { "Int_0BlockCheck", 0x71, 0x71, true, "i_04", []() { dst2.i_04 = 0; } }, + { "Int_1BlockCheck", 0x71, 0x71, true, "i_14", []() { dst2.i_14 = 0; } }, + { "Float_0BlockCheck", 0x71, 0x71, true, "f_08", []() { dst2.f_08 = 0; } }, + { "Float_1BlockCheck", 0x71, 0x71, true, "f_18", []() { dst2.f_18 = 0; } }, + }; + _DeltaSimpleTests(delta, testdata, ARRAYSIZE(testdata)); - memset(res[0], 0xCC, sizeof(res) / 2); - memset(res[1], 0xDD, sizeof(res) / 2); - - for (int usejit = 0; usejit <= 1; usejit++) { - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - res[usejit][0].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][0].bits, &res[usejit][0].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "SimpleUnchangedAll", usejit, true, delta, NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x72); - res[usejit][1].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][1].bits, &res[usejit][1].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "SimpleUnchangedAll", usejit, false, delta, NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.b_01 = 0; - res[usejit][2].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][2].bits, &res[usejit][2].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Byte_0BlockCheck", usejit, true, delta, "b_01", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.b_11 = 0; - res[usejit][3].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][3].bits, &res[usejit][3].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Byte_1BlockCheck", usejit, true, delta, "b_11", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.s_02 = 0; - res[usejit][4].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][4].bits, &res[usejit][4].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Short_0BlockCheck", usejit, true, delta, "s_02", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.s_12 = 0; - res[usejit][5].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][5].bits, &res[usejit][5].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Short_1BlockCheck", usejit, true, delta, "s_12", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.i_04 = 0; - res[usejit][6].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][6].bits, &res[usejit][6].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Int_0BlockCheck", usejit, true, delta, "i_04", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.i_14 = 0; - res[usejit][7].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][7].bits, &res[usejit][7].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Int_1BlockCheck", usejit, true, delta, "i_14", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.f_08 = 0; - res[usejit][8].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][8].bits, &res[usejit][8].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Float_0BlockCheck", usejit, true, delta, "f_08", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.f_18 = 0; - res[usejit][9].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][9].bits, &res[usejit][9].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Float_0BlockCheck", usejit, true, delta, "f_18", NULL); - } - - _CompareDeltaResults(__FUNCTION__, res[0], res[1], 10); SV_Shutdown(); } TEST(MarkFieldsTest_InterBlock, Delta, 1000) { - delta_t* delta = _CreateTestDeltaDesc(); - delta_test_struct_t d1; - delta_test_struct_t d2; - delta_res_t res[2][14]; + delta_simpletest_data_t testdata[] = { + { "Interblock1_guards", 0x71, 0x71, true, "b_4D b_52", []() { dst2.b_4D = dst2.b_52 = 0; } }, + { "Interblock1_guards_and_val", 0x71, 0x71, true, "b_4D b_52 i_4E", []() { dst2.b_4D = dst2.b_52 = 0; dst2.i_4E = 0; } }, + { "Interblock1_val", 0x71, 0x71, true, "i_4E", []() { dst2.i_4E = 0; } }, + { "Interblock1_val_0b", 0x71, 0x71, true, "i_4E", []() { dst2.i_4E &= 0xFFFFFF00; } }, + { "Interblock1_val_1b", 0x71, 0x71, true, "i_4E", []() { dst2.i_4E &= 0xFFFF00FF; } }, + { "Interblock1_val_2b", 0x71, 0x71, true, "i_4E", []() { dst2.i_4E &= 0xFF00FFFF; } }, + { "Interblock1_val_3b", 0x71, 0x71, true, "i_4E", []() { dst2.i_4E &= 0x00FFFFFF; } }, - memset(res[0], 0xCC, sizeof(res) / 2); - memset(res[1], 0xDD, sizeof(res) / 2); + { "Interblock2_guards", 0x71, 0x71, true, "b_5C b_61", []() { dst2.b_5C = dst2.b_61 = 0; } }, + { "Interblock2_guards_and_val", 0x71, 0x71, true, "b_5C b_61 i_5D", []() { dst2.b_5C = dst2.b_61 = 0; dst2.i_5D = 0; } }, + { "Interblock2_val", 0x71, 0x71, true, "i_5D", []() { dst2.i_5D = 0; } }, + { "Interblock2_val_0b", 0x71, 0x71, true, "i_5D", []() { dst2.i_5D &= 0xFFFFFF00; } }, + { "Interblock2_val_1b", 0x71, 0x71, true, "i_5D", []() { dst2.i_5D &= 0xFFFF00FF; } }, + { "Interblock2_val_2b", 0x71, 0x71, true, "i_5D", []() { dst2.i_5D &= 0xFF00FFFF; } }, + { "Interblock2_val_3b", 0x71, 0x71, true, "i_5D", []() { dst2.i_5D &= 0x00FFFFFF; } }, + }; + _DeltaSimpleTests(delta, testdata, ARRAYSIZE(testdata)); - for (int usejit = 0; usejit <= 1; usejit++) { - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.b_4D = d2.b_52 = 0; - res[usejit][0].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][0].bits, &res[usejit][0].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock1_guards", usejit, true, delta, "b_4D", "b_52", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.b_4D = d2.b_52 = 0; - d2.i_4E = 0; - res[usejit][1].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][1].bits, &res[usejit][1].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock1_guards_and_val", usejit, true, delta, "b_4D", "b_52", "i_4E", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.i_4E = 0; - res[usejit][2].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][2].bits, &res[usejit][2].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock1_val", usejit, true, delta, "i_4E", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.i_4E &= 0xFFFFFF00; - res[usejit][3].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][3].bits, &res[usejit][3].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_0b", usejit, true, delta, "i_4E", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.i_4E &= 0xFFFF00FF; - res[usejit][4].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][4].bits, &res[usejit][4].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_1b", usejit, true, delta, "i_4E", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.i_4E &= 0xFF00FFFF; - res[usejit][5].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][5].bits, &res[usejit][5].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_2b", usejit, true, delta, "i_4E", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.i_4E &= 0x00FFFFFF; - res[usejit][6].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][6].bits, &res[usejit][6].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_3b", usejit, true, delta, "i_4E", NULL); - - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.b_5C = d2.b_61 = 0; - res[usejit][7].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][7].bits, &res[usejit][7].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock2_guards", usejit, true, delta, "b_5C", "b_61", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.b_5C = d2.b_61 = 0; - d2.i_5D = 0; - res[usejit][8].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][8].bits, &res[usejit][8].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock2_guards_and_val", usejit, true, delta, "b_5C", "b_61", "i_5D", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.i_5D = 0; - res[usejit][9].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][9].bits, &res[usejit][9].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock2_val", usejit, true, delta, "i_5D", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.i_5D &= 0xFFFFFF00; - res[usejit][10].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][10].bits, &res[usejit][10].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_0b", usejit, true, delta, "i_5D", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.i_5D &= 0xFFFF00FF; - res[usejit][11].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][11].bits, &res[usejit][11].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_1b", usejit, true, delta, "i_5D", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.i_5D &= 0xFF00FFFF; - res[usejit][12].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][12].bits, &res[usejit][12].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_2b", usejit, true, delta, "i_5D", NULL); - - _FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71); - d2.i_5D &= 0x00FFFFFF; - res[usejit][13].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][13].bits, &res[usejit][13].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_3b", usejit, true, delta, "i_5D", NULL); - } - - _CompareDeltaResults(__FUNCTION__, res[0], res[1], 14); SV_Shutdown(); } TEST(MarkFieldsTest_Strings, Delta, 1000) { - delta_t* delta = _CreateTestDeltaDesc(); - delta_test_struct_t d1; - delta_test_struct_t d2; - delta_res_t res[2][4]; + delta_simpletest_data_t testdata[] = { + { "Str_empty", 'c', 'c', true, "s_24", []() { dst2.s_24[0] = 0; } }, + { "Str_empty2", 'c', 'c', true, "s_24", []() { dst1.s_24[0] = 0; } }, + { "Str_both_empty_with_garbage", 'c', 'c', true, "", []() { + dst1.s_24[0] = 0; dst2.s_24[0] = 0; + dst1.s_24[1] = 'd'; dst2.s_24[1] = 'e'; + }}, + { "Str_case_check", 'c', 'c', true, "", []() { dst1.s_24[0] = 'C'; } }, + }; + _DeltaSimpleTests(delta, testdata, ARRAYSIZE(testdata)); - memset(res[0], 0xCC, sizeof(res) / 2); - memset(res[1], 0xDD, sizeof(res) / 2); - - for (int usejit = 0; usejit <= 1; usejit++) { - - _FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c'); - d2.s_24[0] = 0; - res[usejit][0].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][0].bits, &res[usejit][0].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Str_empty", usejit, true, delta, "s_24", NULL); - - _FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c'); - d1.s_24[0] = 0; - res[usejit][1].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][1].bits, &res[usejit][1].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Str_empty2", usejit, true, delta, "s_24", NULL); - - _FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c'); - d1.s_24[0] = d2.s_24[0] = 0; - d1.s_24[1] = 'd'; d2.s_24[1] = 'e'; - res[usejit][2].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][2].bits, &res[usejit][2].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Str_both_empty_with_garbage", usejit, true, delta, NULL); - - _FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c'); - d1.s_24[1] = 'C'; - res[usejit][3].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][3].bits, &res[usejit][3].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "Str_case_check", usejit, true, delta, NULL); - } - - _CompareDeltaResults(__FUNCTION__, res[0], res[1], 4); SV_Shutdown(); } TEST(MarkFieldsTest_TimeWindow, Delta, 1000) { #ifdef REHLDS_FIXES - bool rehds_fixes = true; + bool rehlds_fixes = true; #else - bool rehds_fixes = false; + bool rehlds_fixes = false; #endif delta_t* delta = _CreateTestDeltaDesc(); - delta_test_struct_t d1; - delta_test_struct_t d2; - delta_res_t res[2][3]; + delta_simpletest_data_t testdata[] = { + { "TimeWindow_Below_Precision", 'c', 'c', true, (rehlds_fixes ? "w8_1C" : ""), []() { dst2.w8_1C = 0.001f; dst1.w8_1C = 0.0011f; } }, + { "TimeWindow_Above_Precision1", 'c', 'c', true, (rehlds_fixes ? "w8_1C" : ""), []() { dst2.w8_1C = 0.1f; dst1.w8_1C = 0.11f; } }, //precision check, 0.11f is actually 0.10999 + { "TimeWindow_Above_Precision2", 'c', 'c', true, "w8_1C", []() { dst2.w8_1C = 0.1f; dst1.w8_1C = 0.12f; } }, + }; + _DeltaSimpleTests(delta, testdata, ARRAYSIZE(testdata)); - memset(res[0], 0xCC, sizeof(res) / 2); - memset(res[1], 0xDD, sizeof(res) / 2); - - for (int usejit = 0; usejit <= 1; usejit++) { - - _FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c'); - d2.w8_1C = 0.001f; d1.w8_1C = 0.0011f; - res[usejit][0].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][0].bits, &res[usejit][0].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "TimeWindow_Below_Precision", usejit, true, delta, rehds_fixes ? "w8_1C" : NULL, NULL); - - _FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c'); - d2.w8_1C = 0.1f; d1.w8_1C = 0.11f; //precision check, 0.11f is actually 0.10999 - res[usejit][1].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][1].bits, &res[usejit][1].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "TimeWindow_Above_Precision1", usejit, true, delta, rehds_fixes ? "w8_1C" : NULL, NULL); - - _FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c'); - d2.w8_1C = 0.1f; d1.w8_1C = 0.12f; - res[usejit][2].sendfields = _DoMarkFields(&d1, &d2, delta, usejit != 0); - _GetBitmaskAndBytecount(delta, res[usejit][2].bits, &res[usejit][2].bytecount, usejit); - _EnsureFieldsChanged(__FUNCTION__, "TimeWindow_Above_Precision2", usejit, true, delta, "w8_1C", NULL); - } - - _CompareDeltaResults(__FUNCTION__, res[0], res[1], 3); SV_Shutdown(); }