Move find-modified-range function out of D3D11 driver to common

This commit is contained in:
Baldur Karlsson committed 2014-06-24 15:44:47 +01:00
1 parent 90ffbf6537
commit 1b5a68382c
3 files changed
+140 -138

No files matched your search

+138
View File
@@ -56,6 +56,144 @@ void rdcassert(const char *condition, const char *file, unsigned int line, const
rdclog_int(RDCLog_Error, file, line, "Assertion failed: '%hs'", condition, file, line);
}
static __m128 zero = {0};
// assumes a and b both point to 16-byte aligned 16-byte chunks of memory.
// Returns if they're equal or different
bool Vec16NotEqual(void *a, void *b)
{
// disabled SSE version as it's acting dodgy
#if 0
__m128 avec = _mm_load_ps(aflt);
__m128 bvec = _mm_load_ps(bflt);
__m128 diff = _mm_xor_ps(avec, bvec);
__m128 eq = _mm_cmpeq_ps(diff, zero);
int mask = _mm_movemask_ps(eq);
int signMask = _mm_movemask_ps(diff);
// first check ensures that diff is floatequal to zero (ie. avec bitwise equal to bvec).
// HOWEVER -0 is floatequal to 0, so we ensure no sign bits are set on diff
if((mask^0xf) || signMask != 0)
{
return true;
}
return false;
#elif defined(WIN64)
uint64_t *a64 = (uint64_t *)a;
uint64_t *b64 = (uint64_t *)b;
return a64[0] != b64[0] ||
a64[1] != b64[1];
#else
uint32_t *a32 = (uint32_t *)a;
uint32_t *b32 = (uint32_t *)b;
return a32[0] != b32[0] ||
a32[1] != b32[1] ||
a32[2] != b32[2] ||
a32[3] != b32[3];
#endif
}
bool FindDiffRange(void *a, void *b, size_t bufSize, size_t &diffStart, size_t &diffEnd)
{
RDCASSERT(((unsigned long)a)%16 == 0);
RDCASSERT(((unsigned long)b)%16 == 0);
diffStart = bufSize+1;
diffEnd = 0;
size_t alignedSize = bufSize&(~0xf);
size_t numVecs = alignedSize/16;
size_t offs = 0;
float *aflt = (float *)a;
float *bflt = (float *)b;
// init a vector to 0
__m128 zero = {0};
// sweep to find the start of differences
for(size_t v=0; v < numVecs; v++)
{
if(Vec16NotEqual(aflt, bflt))
{
diffStart = offs;
break;
}
aflt+=4;bflt+=4;offs+=4*sizeof(float);
}
// make sure we're byte-accurate, to comply with WRITE_NO_OVERWRITE
while(diffStart < bufSize && *((byte *)a + diffStart) == *((byte *)b + diffStart)) diffStart++;
// do we have some unaligned bytes at the end of the buffer?
if(bufSize > alignedSize)
{
size_t numBytes = alignedSize-bufSize;
// if we haven't even found a start, check in these bytes
if(diffStart > bufSize)
{
offs = bufSize;
for(size_t by=0; by < numBytes; by++)
{
if(*((byte *)a + alignedSize + by) != *((byte *)b + alignedSize + by))
{
diffStart = offs;
break;
}
offs++;
}
}
// sweep from the last byte to find the end
for(size_t by=0; by < numBytes; by++)
{
if(*((byte *)a + bufSize-1 - by) != *((byte *)b + bufSize-1 - by))
{
diffEnd = bufSize-by;
break;
}
}
}
// if we haven't found a start, or we've found a start AND and end,
// then we're done.
if(diffStart > bufSize || diffEnd > 0)
return diffStart < bufSize;
offs = alignedSize;
// sweep from the last __m128
aflt = (float *)a + offs/sizeof(float) - 4;
bflt = (float *)b + offs/sizeof(float) - 4;
for(size_t v=0; v < numVecs; v++)
{
if(Vec16NotEqual(aflt, bflt))
{
diffEnd = offs;
break;
}
aflt-=4;bflt-=4;offs-=16;
}
// make sure we're byte-accurate, to comply with WRITE_NO_OVERWRITE
while(diffEnd > 0 && *((byte *)a + diffEnd - 1) == *((byte *)b + diffEnd - 1)) diffEnd--;
// if we found a start then we necessarily found an end
return diffStart < bufSize;
}
static wstring &logfile()
{
static wstring fn;