|
|
|
@ -21,7 +21,6 @@ struct
|
|
|
|
LatteIndexType lastIndexType;
|
|
|
|
LatteIndexType lastIndexType;
|
|
|
|
uint64 lastUsed;
|
|
|
|
uint64 lastUsed;
|
|
|
|
// output
|
|
|
|
// output
|
|
|
|
uint32 indexMin;
|
|
|
|
|
|
|
|
uint32 indexMax;
|
|
|
|
uint32 indexMax;
|
|
|
|
Renderer::INDEX_TYPE renderIndexType;
|
|
|
|
Renderer::INDEX_TYPE renderIndexType;
|
|
|
|
uint32 outputCount;
|
|
|
|
uint32 outputCount;
|
|
|
|
@ -140,7 +139,7 @@ uint32 LatteIndices_calculateIndexOutputSize(LattePrimitiveMode primitiveMode, L
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
template<typename T>
|
|
|
|
void LatteIndices_convertBE(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_convertBE(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const betype<T>* src = (betype<T>*)indexDataInput;
|
|
|
|
const betype<T>* src = (betype<T>*)indexDataInput;
|
|
|
|
T* dst = (T*)indexDataOutput;
|
|
|
|
T* dst = (T*)indexDataOutput;
|
|
|
|
@ -148,7 +147,6 @@ void LatteIndices_convertBE(const void* indexDataInput, void* indexDataOutput, u
|
|
|
|
{
|
|
|
|
{
|
|
|
|
T v = *src;
|
|
|
|
T v = *src;
|
|
|
|
*dst = v;
|
|
|
|
*dst = v;
|
|
|
|
indexMin = std::min(indexMin, (uint32)v);
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)v);
|
|
|
|
indexMax = std::max(indexMax, (uint32)v);
|
|
|
|
dst++;
|
|
|
|
dst++;
|
|
|
|
src++;
|
|
|
|
src++;
|
|
|
|
@ -156,7 +154,7 @@ void LatteIndices_convertBE(const void* indexDataInput, void* indexDataOutput, u
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
template<typename T>
|
|
|
|
void LatteIndices_convertLE(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_convertLE(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const T* src = (T*)indexDataInput;
|
|
|
|
const T* src = (T*)indexDataInput;
|
|
|
|
T* dst = (T*)indexDataOutput;
|
|
|
|
T* dst = (T*)indexDataOutput;
|
|
|
|
@ -164,7 +162,6 @@ void LatteIndices_convertLE(const void* indexDataInput, void* indexDataOutput, u
|
|
|
|
{
|
|
|
|
{
|
|
|
|
T v = *src;
|
|
|
|
T v = *src;
|
|
|
|
*dst = v;
|
|
|
|
*dst = v;
|
|
|
|
indexMin = std::min(indexMin, (uint32)v);
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)v);
|
|
|
|
indexMax = std::max(indexMax, (uint32)v);
|
|
|
|
dst++;
|
|
|
|
dst++;
|
|
|
|
src++;
|
|
|
|
src++;
|
|
|
|
@ -172,7 +169,7 @@ void LatteIndices_convertLE(const void* indexDataInput, void* indexDataOutput, u
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
template<typename T>
|
|
|
|
void LatteIndices_unpackQuadsAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_unpackQuadsAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sint32 numQuads = count / 4;
|
|
|
|
sint32 numQuads = count / 4;
|
|
|
|
const betype<T>* src = (betype<T>*)indexDataInput;
|
|
|
|
const betype<T>* src = (betype<T>*)indexDataInput;
|
|
|
|
@ -183,13 +180,9 @@ void LatteIndices_unpackQuadsAndConvert(const void* indexDataInput, void* indexD
|
|
|
|
T idx1 = src[1];
|
|
|
|
T idx1 = src[1];
|
|
|
|
T idx2 = src[2];
|
|
|
|
T idx2 = src[2];
|
|
|
|
T idx3 = src[3];
|
|
|
|
T idx3 = src[3];
|
|
|
|
indexMin = std::min(indexMin, (uint32)idx0);
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx0);
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx0);
|
|
|
|
indexMin = std::min(indexMin, (uint32)idx1);
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx1);
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx1);
|
|
|
|
indexMin = std::min(indexMin, (uint32)idx2);
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx2);
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx2);
|
|
|
|
indexMin = std::min(indexMin, (uint32)idx3);
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx3);
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx3);
|
|
|
|
dst[0] = idx0;
|
|
|
|
dst[0] = idx0;
|
|
|
|
dst[1] = idx1;
|
|
|
|
dst[1] = idx1;
|
|
|
|
@ -203,7 +196,7 @@ void LatteIndices_unpackQuadsAndConvert(const void* indexDataInput, void* indexD
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
template<typename T>
|
|
|
|
void LatteIndices_generateAutoQuadIndices(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_generateAutoQuadIndices(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sint32 numQuads = count / 4;
|
|
|
|
sint32 numQuads = count / 4;
|
|
|
|
const betype<T>* src = (betype<T>*)indexDataInput;
|
|
|
|
const betype<T>* src = (betype<T>*)indexDataInput;
|
|
|
|
@ -223,12 +216,11 @@ void LatteIndices_generateAutoQuadIndices(const void* indexDataInput, void* inde
|
|
|
|
src += 4;
|
|
|
|
src += 4;
|
|
|
|
dst += 6;
|
|
|
|
dst += 6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
indexMin = 0;
|
|
|
|
|
|
|
|
indexMax = std::max(count, 1u) - 1;
|
|
|
|
indexMax = std::max(count, 1u) - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
template<typename T>
|
|
|
|
void LatteIndices_unpackQuadStripAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_unpackQuadStripAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (count <= 3)
|
|
|
|
if (count <= 3)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
@ -241,13 +233,9 @@ void LatteIndices_unpackQuadStripAndConvert(const void* indexDataInput, void* in
|
|
|
|
T idx1 = src[1];
|
|
|
|
T idx1 = src[1];
|
|
|
|
T idx2 = src[2];
|
|
|
|
T idx2 = src[2];
|
|
|
|
T idx3 = src[3];
|
|
|
|
T idx3 = src[3];
|
|
|
|
indexMin = std::min(indexMin, (uint32)idx0);
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx0);
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx0);
|
|
|
|
indexMin = std::min(indexMin, (uint32)idx1);
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx1);
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx1);
|
|
|
|
indexMin = std::min(indexMin, (uint32)idx2);
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx2);
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx2);
|
|
|
|
indexMin = std::min(indexMin, (uint32)idx3);
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx3);
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx3);
|
|
|
|
dst[0] = idx0;
|
|
|
|
dst[0] = idx0;
|
|
|
|
dst[1] = idx1;
|
|
|
|
dst[1] = idx1;
|
|
|
|
@ -261,7 +249,7 @@ void LatteIndices_unpackQuadStripAndConvert(const void* indexDataInput, void* in
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
template<typename T>
|
|
|
|
void LatteIndices_unpackLineLoopAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_unpackLineLoopAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (count <= 0)
|
|
|
|
if (count <= 0)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
@ -271,7 +259,6 @@ void LatteIndices_unpackLineLoopAndConvert(const void* indexDataInput, void* ind
|
|
|
|
for (sint32 i = 0; i < (sint32)count; i++)
|
|
|
|
for (sint32 i = 0; i < (sint32)count; i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
T idx = *src;
|
|
|
|
T idx = *src;
|
|
|
|
indexMin = std::min(indexMin, (uint32)idx);
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx);
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx);
|
|
|
|
*dst = idx;
|
|
|
|
*dst = idx;
|
|
|
|
src++;
|
|
|
|
src++;
|
|
|
|
@ -281,7 +268,7 @@ void LatteIndices_unpackLineLoopAndConvert(const void* indexDataInput, void* ind
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
template<typename T>
|
|
|
|
void LatteIndices_generateAutoQuadStripIndices(void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_generateAutoQuadStripIndices(void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (count <= 3)
|
|
|
|
if (count <= 3)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
@ -301,13 +288,12 @@ void LatteIndices_generateAutoQuadStripIndices(void* indexDataOutput, uint32 cou
|
|
|
|
dst[5] = idx3;
|
|
|
|
dst[5] = idx3;
|
|
|
|
dst += 6;
|
|
|
|
dst += 6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
indexMin = 0;
|
|
|
|
|
|
|
|
indexMax = std::max(count, 1u) - 1;
|
|
|
|
indexMax = std::max(count, 1u) - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
template<typename T>
|
|
|
|
void LatteIndices_generateAutoLineLoopIndices(void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_generateAutoLineLoopIndices(void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (count == 0)
|
|
|
|
if (count == 0)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
@ -319,12 +305,11 @@ void LatteIndices_generateAutoLineLoopIndices(void* indexDataOutput, uint32 coun
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*dst = 0;
|
|
|
|
*dst = 0;
|
|
|
|
dst++;
|
|
|
|
dst++;
|
|
|
|
indexMin = 0;
|
|
|
|
|
|
|
|
indexMax = std::max(count, 1u) - 1;
|
|
|
|
indexMax = std::max(count, 1u) - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
template<typename T>
|
|
|
|
void LatteIndices_unpackTriangleFanAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_unpackTriangleFanAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const betype<T>* src = (betype<T>*)indexDataInput;
|
|
|
|
const betype<T>* src = (betype<T>*)indexDataInput;
|
|
|
|
T* dst = (T*)indexDataOutput;
|
|
|
|
T* dst = (T*)indexDataOutput;
|
|
|
|
@ -337,14 +322,13 @@ void LatteIndices_unpackTriangleFanAndConvert(const void* indexDataInput, void*
|
|
|
|
else
|
|
|
|
else
|
|
|
|
i0 = count - 1 - i / 2;
|
|
|
|
i0 = count - 1 - i / 2;
|
|
|
|
T idx = src[i0];
|
|
|
|
T idx = src[i0];
|
|
|
|
indexMin = std::min(indexMin, (uint32)idx);
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx);
|
|
|
|
indexMax = std::max(indexMax, (uint32)idx);
|
|
|
|
dst[i] = idx;
|
|
|
|
dst[i] = idx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
template<typename T>
|
|
|
|
void LatteIndices_generateAutoTriangleFanIndices(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_generateAutoTriangleFanIndices(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const betype<T>* src = (betype<T>*)indexDataInput;
|
|
|
|
const betype<T>* src = (betype<T>*)indexDataInput;
|
|
|
|
T* dst = (T*)indexDataOutput;
|
|
|
|
T* dst = (T*)indexDataOutput;
|
|
|
|
@ -357,13 +341,12 @@ void LatteIndices_generateAutoTriangleFanIndices(const void* indexDataInput, voi
|
|
|
|
idx = count - 1 - idx / 2;
|
|
|
|
idx = count - 1 - idx / 2;
|
|
|
|
dst[i] = idx;
|
|
|
|
dst[i] = idx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
indexMin = 0;
|
|
|
|
|
|
|
|
indexMax = std::max(count, 1u) - 1;
|
|
|
|
indexMax = std::max(count, 1u) - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(ARCH_X86_64)
|
|
|
|
#if defined(ARCH_X86_64)
|
|
|
|
ATTRIBUTE_AVX2
|
|
|
|
ATTRIBUTE_AVX2
|
|
|
|
void LatteIndices_fastConvertU16_AVX2(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_fastConvertU16_AVX2(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// using AVX + AVX2 we can process 16 indices at a time
|
|
|
|
// using AVX + AVX2 we can process 16 indices at a time
|
|
|
|
const uint16* indicesU16BE = (const uint16*)indexDataInput;
|
|
|
|
const uint16* indicesU16BE = (const uint16*)indexDataInput;
|
|
|
|
@ -385,33 +368,23 @@ void LatteIndices_fastConvertU16_AVX2(const void* indexDataInput, void* indexDat
|
|
|
|
// endian swap
|
|
|
|
// endian swap
|
|
|
|
mIndexData = _mm256_shuffle_epi8(mIndexData, mShuffle16Swap);
|
|
|
|
mIndexData = _mm256_shuffle_epi8(mIndexData, mShuffle16Swap);
|
|
|
|
_mm256_store_si256((__m256i*)indexOutput, mIndexData);
|
|
|
|
_mm256_store_si256((__m256i*)indexOutput, mIndexData);
|
|
|
|
mMin = _mm256_min_epu16(mIndexData, mMin);
|
|
|
|
|
|
|
|
mMax = _mm256_max_epu16(mIndexData, mMax);
|
|
|
|
mMax = _mm256_max_epu16(mIndexData, mMax);
|
|
|
|
indexOutput += 16;
|
|
|
|
indexOutput += 16;
|
|
|
|
} while (--count16);
|
|
|
|
} while (--count16);
|
|
|
|
|
|
|
|
|
|
|
|
// fold 32 to 16 byte
|
|
|
|
// fold 32 to 16 byte
|
|
|
|
mMin = _mm256_min_epu16(mMin, _mm256_permute2x128_si256(mMin, mMin, 1));
|
|
|
|
|
|
|
|
mMax = _mm256_max_epu16(mMax, _mm256_permute2x128_si256(mMax, mMax, 1));
|
|
|
|
mMax = _mm256_max_epu16(mMax, _mm256_permute2x128_si256(mMax, mMax, 1));
|
|
|
|
// fold 16 to 8 byte
|
|
|
|
// fold 16 to 8 byte
|
|
|
|
mMin = _mm256_min_epu16(mMin, _mm256_shuffle_epi32(mMin, (2 << 0) | (3 << 2) | (2 << 4) | (3 << 6)));
|
|
|
|
|
|
|
|
mMax = _mm256_max_epu16(mMax, _mm256_shuffle_epi32(mMax, (2 << 0) | (3 << 2) | (2 << 4) | (3 << 6)));
|
|
|
|
mMax = _mm256_max_epu16(mMax, _mm256_shuffle_epi32(mMax, (2 << 0) | (3 << 2) | (2 << 4) | (3 << 6)));
|
|
|
|
|
|
|
|
|
|
|
|
uint16* mMinU16 = (uint16*)&mMin;
|
|
|
|
|
|
|
|
uint16* mMaxU16 = (uint16*)&mMax;
|
|
|
|
uint16* mMaxU16 = (uint16*)&mMax;
|
|
|
|
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[0]);
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[1]);
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[2]);
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[3]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[0]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[0]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[1]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[1]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[2]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[2]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[3]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[3]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// process remaining indices
|
|
|
|
// process remaining indices
|
|
|
|
uint32 _minIndex = 0xFFFFFFFF;
|
|
|
|
|
|
|
|
uint32 _maxIndex = 0;
|
|
|
|
uint32 _maxIndex = 0;
|
|
|
|
for (sint32 i = countRemaining; (--i) >= 0;)
|
|
|
|
for (sint32 i = countRemaining; (--i) >= 0;)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -420,15 +393,13 @@ void LatteIndices_fastConvertU16_AVX2(const void* indexDataInput, void* indexDat
|
|
|
|
indexOutput++;
|
|
|
|
indexOutput++;
|
|
|
|
indicesU16BE++;
|
|
|
|
indicesU16BE++;
|
|
|
|
_maxIndex = std::max(_maxIndex, (uint32)idx);
|
|
|
|
_maxIndex = std::max(_maxIndex, (uint32)idx);
|
|
|
|
_minIndex = std::min(_minIndex, (uint32)idx);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// update min/max
|
|
|
|
// update max
|
|
|
|
indexMax = std::max(indexMax, _maxIndex);
|
|
|
|
indexMax = std::max(indexMax, _maxIndex);
|
|
|
|
indexMin = std::min(indexMin, _minIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ATTRIBUTE_SSE41
|
|
|
|
ATTRIBUTE_SSE41
|
|
|
|
void LatteIndices_fastConvertU16_SSE41(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_fastConvertU16_SSE41(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// SSSE3 & SSE4.1 optimized decoding
|
|
|
|
// SSSE3 & SSE4.1 optimized decoding
|
|
|
|
const uint16* indicesU16BE = (const uint16*)indexDataInput;
|
|
|
|
const uint16* indicesU16BE = (const uint16*)indexDataInput;
|
|
|
|
@ -437,7 +408,6 @@ void LatteIndices_fastConvertU16_SSE41(const void* indexDataInput, void* indexDa
|
|
|
|
sint32 countRemaining = count & 7;
|
|
|
|
sint32 countRemaining = count & 7;
|
|
|
|
if (count8)
|
|
|
|
if (count8)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
__m128i mMin = _mm_set_epi16((short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF);
|
|
|
|
|
|
|
|
__m128i mMax = _mm_set_epi16(0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000);
|
|
|
|
__m128i mMax = _mm_set_epi16(0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000);
|
|
|
|
__m128i mTemp;
|
|
|
|
__m128i mTemp;
|
|
|
|
__m128i* mRawIndices = (__m128i*)indicesU16BE;
|
|
|
|
__m128i* mRawIndices = (__m128i*)indicesU16BE;
|
|
|
|
@ -450,14 +420,12 @@ void LatteIndices_fastConvertU16_SSE41(const void* indexDataInput, void* indexDa
|
|
|
|
mTemp = _mm_loadu_si128(mRawIndices);
|
|
|
|
mTemp = _mm_loadu_si128(mRawIndices);
|
|
|
|
mRawIndices++;
|
|
|
|
mRawIndices++;
|
|
|
|
mTemp = _mm_shuffle_epi8(mTemp, shufmask);
|
|
|
|
mTemp = _mm_shuffle_epi8(mTemp, shufmask);
|
|
|
|
mMin = _mm_min_epu16(mMin, mTemp);
|
|
|
|
|
|
|
|
mMax = _mm_max_epu16(mMax, mTemp);
|
|
|
|
mMax = _mm_max_epu16(mMax, mTemp);
|
|
|
|
_mm_store_si128(mOutputIndices, mTemp);
|
|
|
|
_mm_store_si128(mOutputIndices, mTemp);
|
|
|
|
mOutputIndices++;
|
|
|
|
mOutputIndices++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint16* mMaxU16 = (uint16*)&mMax;
|
|
|
|
uint16* mMaxU16 = (uint16*)&mMax;
|
|
|
|
uint16* mMinU16 = (uint16*)&mMin;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[0]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[0]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[1]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[1]);
|
|
|
|
@ -467,16 +435,7 @@ void LatteIndices_fastConvertU16_SSE41(const void* indexDataInput, void* indexDa
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[5]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[5]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[6]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[6]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[7]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[7]);
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[0]);
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[1]);
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[2]);
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[3]);
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[4]);
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[5]);
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[6]);
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[7]);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint32 _minIndex = 0xFFFFFFFF;
|
|
|
|
|
|
|
|
uint32 _maxIndex = 0;
|
|
|
|
uint32 _maxIndex = 0;
|
|
|
|
for (sint32 i = countRemaining; (--i) >= 0;)
|
|
|
|
for (sint32 i = countRemaining; (--i) >= 0;)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -485,14 +444,12 @@ void LatteIndices_fastConvertU16_SSE41(const void* indexDataInput, void* indexDa
|
|
|
|
indexOutput++;
|
|
|
|
indexOutput++;
|
|
|
|
indicesU16BE++;
|
|
|
|
indicesU16BE++;
|
|
|
|
_maxIndex = std::max(_maxIndex, (uint32)idx);
|
|
|
|
_maxIndex = std::max(_maxIndex, (uint32)idx);
|
|
|
|
_minIndex = std::min(_minIndex, (uint32)idx);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
indexMax = std::max(indexMax, _maxIndex);
|
|
|
|
indexMax = std::max(indexMax, _maxIndex);
|
|
|
|
indexMin = std::min(indexMin, _minIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ATTRIBUTE_AVX2
|
|
|
|
ATTRIBUTE_AVX2
|
|
|
|
void LatteIndices_fastConvertU32_AVX2(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_fastConvertU32_AVX2(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// using AVX + AVX2 we can process 8 indices at a time
|
|
|
|
// using AVX + AVX2 we can process 8 indices at a time
|
|
|
|
const uint32* indicesU32BE = (const uint32*)indexDataInput;
|
|
|
|
const uint32* indicesU32BE = (const uint32*)indexDataInput;
|
|
|
|
@ -501,7 +458,6 @@ void LatteIndices_fastConvertU32_AVX2(const void* indexDataInput, void* indexDat
|
|
|
|
sint32 countRemaining = count & 7;
|
|
|
|
sint32 countRemaining = count & 7;
|
|
|
|
if (count8)
|
|
|
|
if (count8)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
__m256i mMin = _mm256_set_epi32((sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF);
|
|
|
|
|
|
|
|
__m256i mMax = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
__m256i mMax = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
__m256i mShuffle32Swap = _mm256_set_epi8(28,29,30,31,
|
|
|
|
__m256i mShuffle32Swap = _mm256_set_epi8(28,29,30,31,
|
|
|
|
24,25,26,27,
|
|
|
|
24,25,26,27,
|
|
|
|
@ -520,29 +476,20 @@ void LatteIndices_fastConvertU32_AVX2(const void* indexDataInput, void* indexDat
|
|
|
|
// endian swap
|
|
|
|
// endian swap
|
|
|
|
mIndexData = _mm256_shuffle_epi8(mIndexData, mShuffle32Swap);
|
|
|
|
mIndexData = _mm256_shuffle_epi8(mIndexData, mShuffle32Swap);
|
|
|
|
_mm256_store_si256((__m256i*)indexOutput, mIndexData);
|
|
|
|
_mm256_store_si256((__m256i*)indexOutput, mIndexData);
|
|
|
|
mMin = _mm256_min_epu32(mIndexData, mMin);
|
|
|
|
|
|
|
|
mMax = _mm256_max_epu32(mIndexData, mMax);
|
|
|
|
mMax = _mm256_max_epu32(mIndexData, mMax);
|
|
|
|
indexOutput += 8;
|
|
|
|
indexOutput += 8;
|
|
|
|
} while (--count8);
|
|
|
|
} while (--count8);
|
|
|
|
|
|
|
|
|
|
|
|
// fold 32 to 16 byte
|
|
|
|
// fold 32 to 16 byte
|
|
|
|
mMin = _mm256_min_epu32(mMin, _mm256_permute2x128_si256(mMin, mMin, 1));
|
|
|
|
|
|
|
|
mMax = _mm256_max_epu32(mMax, _mm256_permute2x128_si256(mMax, mMax, 1));
|
|
|
|
mMax = _mm256_max_epu32(mMax, _mm256_permute2x128_si256(mMax, mMax, 1));
|
|
|
|
// fold 16 to 8 byte
|
|
|
|
// fold 16 to 8 byte
|
|
|
|
mMin = _mm256_min_epu32(mMin, _mm256_shuffle_epi32(mMin, (2 << 0) | (3 << 2) | (2 << 4) | (3 << 6)));
|
|
|
|
|
|
|
|
mMax = _mm256_max_epu32(mMax, _mm256_shuffle_epi32(mMax, (2 << 0) | (3 << 2) | (2 << 4) | (3 << 6)));
|
|
|
|
mMax = _mm256_max_epu32(mMax, _mm256_shuffle_epi32(mMax, (2 << 0) | (3 << 2) | (2 << 4) | (3 << 6)));
|
|
|
|
|
|
|
|
|
|
|
|
uint32* mMinU32 = (uint32*)&mMin;
|
|
|
|
|
|
|
|
uint32* mMaxU32 = (uint32*)&mMax;
|
|
|
|
uint32* mMaxU32 = (uint32*)&mMax;
|
|
|
|
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU32[0]);
|
|
|
|
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU32[1]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU32[0]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU32[0]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU32[1]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU32[1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// process remaining indices
|
|
|
|
// process remaining indices
|
|
|
|
uint32 _minIndex = 0xFFFFFFFF;
|
|
|
|
|
|
|
|
uint32 _maxIndex = 0;
|
|
|
|
uint32 _maxIndex = 0;
|
|
|
|
for (sint32 i = countRemaining; (--i) >= 0;)
|
|
|
|
for (sint32 i = countRemaining; (--i) >= 0;)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -551,15 +498,13 @@ void LatteIndices_fastConvertU32_AVX2(const void* indexDataInput, void* indexDat
|
|
|
|
indexOutput++;
|
|
|
|
indexOutput++;
|
|
|
|
indicesU32BE++;
|
|
|
|
indicesU32BE++;
|
|
|
|
_maxIndex = std::max(_maxIndex, (uint32)idx);
|
|
|
|
_maxIndex = std::max(_maxIndex, (uint32)idx);
|
|
|
|
_minIndex = std::min(_minIndex, (uint32)idx);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// update min/max
|
|
|
|
// update min/max
|
|
|
|
indexMax = std::max(indexMax, _maxIndex);
|
|
|
|
indexMax = std::max(indexMax, _maxIndex);
|
|
|
|
indexMin = std::min(indexMin, _minIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#elif defined(__aarch64__)
|
|
|
|
#elif defined(__aarch64__)
|
|
|
|
|
|
|
|
|
|
|
|
void LatteIndices_fastConvertU16_NEON(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_fastConvertU16_NEON(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const uint16* indicesU16BE = (const uint16*)indexDataInput;
|
|
|
|
const uint16* indicesU16BE = (const uint16*)indexDataInput;
|
|
|
|
uint16* indexOutput = (uint16*)indexDataOutput;
|
|
|
|
uint16* indexOutput = (uint16*)indexDataOutput;
|
|
|
|
@ -568,7 +513,6 @@ void LatteIndices_fastConvertU16_NEON(const void* indexDataInput, void* indexDat
|
|
|
|
|
|
|
|
|
|
|
|
if (count8)
|
|
|
|
if (count8)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint16x8_t mMin = vdupq_n_u16(0xFFFF);
|
|
|
|
|
|
|
|
uint16x8_t mMax = vdupq_n_u16(0x0000);
|
|
|
|
uint16x8_t mMax = vdupq_n_u16(0x0000);
|
|
|
|
uint16x8_t mTemp;
|
|
|
|
uint16x8_t mTemp;
|
|
|
|
uint16x8_t* mRawIndices = (uint16x8_t*) indicesU16BE;
|
|
|
|
uint16x8_t* mRawIndices = (uint16x8_t*) indicesU16BE;
|
|
|
|
@ -581,22 +525,18 @@ void LatteIndices_fastConvertU16_NEON(const void* indexDataInput, void* indexDat
|
|
|
|
mTemp = vld1q_u16((uint16*)mRawIndices);
|
|
|
|
mTemp = vld1q_u16((uint16*)mRawIndices);
|
|
|
|
mRawIndices++;
|
|
|
|
mRawIndices++;
|
|
|
|
mTemp = vrev16q_u8(mTemp);
|
|
|
|
mTemp = vrev16q_u8(mTemp);
|
|
|
|
mMin = vminq_u16(mMin, mTemp);
|
|
|
|
|
|
|
|
mMax = vmaxq_u16(mMax, mTemp);
|
|
|
|
mMax = vmaxq_u16(mMax, mTemp);
|
|
|
|
vst1q_u16((uint16*)mOutputIndices, mTemp);
|
|
|
|
vst1q_u16((uint16*)mOutputIndices, mTemp);
|
|
|
|
mOutputIndices++;
|
|
|
|
mOutputIndices++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint16* mMaxU16 = (uint16*)&mMax;
|
|
|
|
uint16* mMaxU16 = (uint16*)&mMax;
|
|
|
|
uint16* mMinU16 = (uint16*)&mMin;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 8; ++i) {
|
|
|
|
for (int i = 0; i < 8; ++i) {
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[i]);
|
|
|
|
indexMax = std::max(indexMax, (uint32)mMaxU16[i]);
|
|
|
|
indexMin = std::min(indexMin, (uint32)mMinU16[i]);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// process remaining indices
|
|
|
|
// process remaining indices
|
|
|
|
uint32 _minIndex = 0xFFFFFFFF;
|
|
|
|
|
|
|
|
uint32 _maxIndex = 0;
|
|
|
|
uint32 _maxIndex = 0;
|
|
|
|
for (sint32 i = countRemaining; (--i) >= 0;)
|
|
|
|
for (sint32 i = countRemaining; (--i) >= 0;)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -605,14 +545,12 @@ void LatteIndices_fastConvertU16_NEON(const void* indexDataInput, void* indexDat
|
|
|
|
indexOutput++;
|
|
|
|
indexOutput++;
|
|
|
|
indicesU16BE++;
|
|
|
|
indicesU16BE++;
|
|
|
|
_maxIndex = std::max(_maxIndex, (uint32)idx);
|
|
|
|
_maxIndex = std::max(_maxIndex, (uint32)idx);
|
|
|
|
_minIndex = std::min(_minIndex, (uint32)idx);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// update min/max
|
|
|
|
// update min/max
|
|
|
|
indexMax = std::max(indexMax, _maxIndex);
|
|
|
|
indexMax = std::max(indexMax, _maxIndex);
|
|
|
|
indexMin = std::min(indexMin, _minIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void LatteIndices_fastConvertU32_NEON(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_fastConvertU32_NEON(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const uint32* indicesU32BE = (const uint32*)indexDataInput;
|
|
|
|
const uint32* indicesU32BE = (const uint32*)indexDataInput;
|
|
|
|
uint32* indexOutput = (uint32*)indexDataOutput;
|
|
|
|
uint32* indexOutput = (uint32*)indexDataOutput;
|
|
|
|
@ -621,7 +559,6 @@ void LatteIndices_fastConvertU32_NEON(const void* indexDataInput, void* indexDat
|
|
|
|
|
|
|
|
|
|
|
|
if (count8)
|
|
|
|
if (count8)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint32x4_t mMin = vdupq_n_u32(0xFFFFFFFF);
|
|
|
|
|
|
|
|
uint32x4_t mMax = vdupq_n_u32(0x00000000);
|
|
|
|
uint32x4_t mMax = vdupq_n_u32(0x00000000);
|
|
|
|
uint32x4_t mTemp;
|
|
|
|
uint32x4_t mTemp;
|
|
|
|
uint32x4_t* mRawIndices = (uint32x4_t*) indicesU32BE;
|
|
|
|
uint32x4_t* mRawIndices = (uint32x4_t*) indicesU32BE;
|
|
|
|
@ -634,22 +571,18 @@ void LatteIndices_fastConvertU32_NEON(const void* indexDataInput, void* indexDat
|
|
|
|
mTemp = vld1q_u32((uint32*)mRawIndices);
|
|
|
|
mTemp = vld1q_u32((uint32*)mRawIndices);
|
|
|
|
mRawIndices++;
|
|
|
|
mRawIndices++;
|
|
|
|
mTemp = vrev32q_u8(mTemp);
|
|
|
|
mTemp = vrev32q_u8(mTemp);
|
|
|
|
mMin = vminq_u32(mMin, mTemp);
|
|
|
|
|
|
|
|
mMax = vmaxq_u32(mMax, mTemp);
|
|
|
|
mMax = vmaxq_u32(mMax, mTemp);
|
|
|
|
vst1q_u32((uint32*)mOutputIndices, mTemp);
|
|
|
|
vst1q_u32((uint32*)mOutputIndices, mTemp);
|
|
|
|
mOutputIndices++;
|
|
|
|
mOutputIndices++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32* mMaxU32 = (uint32*)&mMax;
|
|
|
|
uint32* mMaxU32 = (uint32*)&mMax;
|
|
|
|
uint32* mMinU32 = (uint32*)&mMin;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
indexMax = std::max(indexMax, mMaxU32[i]);
|
|
|
|
indexMax = std::max(indexMax, mMaxU32[i]);
|
|
|
|
indexMin = std::min(indexMin, mMinU32[i]);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// process remaining indices
|
|
|
|
// process remaining indices
|
|
|
|
uint32 _minIndex = 0xFFFFFFFF;
|
|
|
|
|
|
|
|
uint32 _maxIndex = 0;
|
|
|
|
uint32 _maxIndex = 0;
|
|
|
|
for (sint32 i = countRemaining; (--i) >= 0;)
|
|
|
|
for (sint32 i = countRemaining; (--i) >= 0;)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -658,21 +591,18 @@ void LatteIndices_fastConvertU32_NEON(const void* indexDataInput, void* indexDat
|
|
|
|
indexOutput++;
|
|
|
|
indexOutput++;
|
|
|
|
indicesU32BE++;
|
|
|
|
indicesU32BE++;
|
|
|
|
_maxIndex = std::max(_maxIndex, idx);
|
|
|
|
_maxIndex = std::max(_maxIndex, idx);
|
|
|
|
_minIndex = std::min(_minIndex, idx);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// update min/max
|
|
|
|
// update min/max
|
|
|
|
indexMax = std::max(indexMax, _maxIndex);
|
|
|
|
indexMax = std::max(indexMax, _maxIndex);
|
|
|
|
indexMin = std::min(indexMin, _minIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
template<typename T>
|
|
|
|
void _LatteIndices_alternativeCalculateIndexMinMax(const void* indexData, uint32 count, uint32 primitiveRestartIndex, uint32& indexMin, uint32& indexMax)
|
|
|
|
void _LatteIndices_alternativeCalculateIndexMax(const void* indexData, uint32 count, uint32 primitiveRestartIndex, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
cemu_assert_debug(count != 0);
|
|
|
|
cemu_assert_debug(count != 0);
|
|
|
|
const betype<T>* idxPtrT = (betype<T>*)indexData;
|
|
|
|
const betype<T>* idxPtrT = (betype<T>*)indexData;
|
|
|
|
T _indexMin = *idxPtrT;
|
|
|
|
|
|
|
|
T _indexMax = *idxPtrT;
|
|
|
|
T _indexMax = *idxPtrT;
|
|
|
|
cemu_assert_debug(primitiveRestartIndex <= std::numeric_limits<T>::max());
|
|
|
|
cemu_assert_debug(primitiveRestartIndex <= std::numeric_limits<T>::max());
|
|
|
|
T restartIndexT = (T)primitiveRestartIndex;
|
|
|
|
T restartIndexT = (T)primitiveRestartIndex;
|
|
|
|
@ -681,23 +611,20 @@ void _LatteIndices_alternativeCalculateIndexMinMax(const void* indexData, uint32
|
|
|
|
T idx = *idxPtrT;
|
|
|
|
T idx = *idxPtrT;
|
|
|
|
if (idx != restartIndexT)
|
|
|
|
if (idx != restartIndexT)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_indexMin = std::min(_indexMin, idx);
|
|
|
|
|
|
|
|
_indexMax = std::max(_indexMax, idx);
|
|
|
|
_indexMax = std::max(_indexMax, idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
idxPtrT++;
|
|
|
|
idxPtrT++;
|
|
|
|
count--;
|
|
|
|
count--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
indexMin = _indexMin;
|
|
|
|
|
|
|
|
indexMax = _indexMax;
|
|
|
|
indexMax = _indexMax;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// calculate min and max index while taking primitive restart into account
|
|
|
|
// calculate min and max index while taking primitive restart into account
|
|
|
|
// fallback implementation in case the fast path gives us invalid results
|
|
|
|
// fallback implementation in case the fast path gives us invalid results
|
|
|
|
void LatteIndices_alternativeCalculateIndexMinMax(const void* indexData, LatteIndexType indexType, uint32 count, uint32& indexMin, uint32& indexMax)
|
|
|
|
void LatteIndices_alternativeCalculateIndexMax(const void* indexData, LatteIndexType indexType, uint32 count, uint32& indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (count == 0)
|
|
|
|
if (count == 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
indexMin = 0;
|
|
|
|
|
|
|
|
indexMax = 0;
|
|
|
|
indexMax = 0;
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -705,11 +632,11 @@ void LatteIndices_alternativeCalculateIndexMinMax(const void* indexData, LatteIn
|
|
|
|
|
|
|
|
|
|
|
|
if (indexType == LatteIndexType::U16_BE)
|
|
|
|
if (indexType == LatteIndexType::U16_BE)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_LatteIndices_alternativeCalculateIndexMinMax<uint16>(indexData, count, primitiveRestartIndex, indexMin, indexMax);
|
|
|
|
_LatteIndices_alternativeCalculateIndexMax<uint16>(indexData, count, primitiveRestartIndex, indexMax);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (indexType == LatteIndexType::U32_BE)
|
|
|
|
else if (indexType == LatteIndexType::U32_BE)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_LatteIndices_alternativeCalculateIndexMinMax<uint32>(indexData, count, primitiveRestartIndex, indexMin, indexMax);
|
|
|
|
_LatteIndices_alternativeCalculateIndexMax<uint32>(indexData, count, primitiveRestartIndex, indexMax);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -717,7 +644,7 @@ void LatteIndices_alternativeCalculateIndexMinMax(const void* indexData, LatteIn
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 count, LattePrimitiveMode primitiveMode, uint32& indexMin, uint32& indexMax, Renderer::INDEX_TYPE& renderIndexType, uint32& outputCount, Renderer::IndexAllocation& indexAllocation)
|
|
|
|
void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 count, LattePrimitiveMode primitiveMode, uint32& indexMax, Renderer::INDEX_TYPE& renderIndexType, uint32& outputCount, Renderer::IndexAllocation& indexAllocation)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// what this should do:
|
|
|
|
// what this should do:
|
|
|
|
// [x] use fast SIMD-based index decoding
|
|
|
|
// [x] use fast SIMD-based index decoding
|
|
|
|
@ -733,7 +660,6 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
|
|
|
});
|
|
|
|
});
|
|
|
|
if (cacheEntry != LatteIndexCache.entry.end())
|
|
|
|
if (cacheEntry != LatteIndexCache.entry.end())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
indexMin = cacheEntry->indexMin;
|
|
|
|
|
|
|
|
indexMax = cacheEntry->indexMax;
|
|
|
|
indexMax = cacheEntry->indexMax;
|
|
|
|
renderIndexType = cacheEntry->renderIndexType;
|
|
|
|
renderIndexType = cacheEntry->renderIndexType;
|
|
|
|
outputCount = cacheEntry->outputCount;
|
|
|
|
outputCount = cacheEntry->outputCount;
|
|
|
|
@ -759,7 +685,6 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
|
|
|
if (indexOutputSize == 0)
|
|
|
|
if (indexOutputSize == 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
outputCount = count;
|
|
|
|
outputCount = count;
|
|
|
|
indexMin = 0;
|
|
|
|
|
|
|
|
indexMax = std::max(count, 1u)-1;
|
|
|
|
indexMax = std::max(count, 1u)-1;
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::NONE;
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::NONE;
|
|
|
|
indexAllocation = {};
|
|
|
|
indexAllocation = {};
|
|
|
|
@ -770,7 +695,6 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
|
|
|
void* indexOutputPtr = indexAllocation.mem;
|
|
|
|
void* indexOutputPtr = indexAllocation.mem;
|
|
|
|
|
|
|
|
|
|
|
|
// decode indices
|
|
|
|
// decode indices
|
|
|
|
indexMin = std::numeric_limits<uint32>::max();
|
|
|
|
|
|
|
|
indexMax = std::numeric_limits<uint32>::min();
|
|
|
|
indexMax = std::numeric_limits<uint32>::min();
|
|
|
|
if (primitiveMode == LattePrimitiveMode::QUADS)
|
|
|
|
if (primitiveMode == LattePrimitiveMode::QUADS)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -779,19 +703,19 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (count <= 0xFFFF)
|
|
|
|
if (count <= 0xFFFF)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LatteIndices_generateAutoQuadIndices<uint16>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_generateAutoQuadIndices<uint16>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U16;
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LatteIndices_generateAutoQuadIndices<uint32>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_generateAutoQuadIndices<uint32>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U32;
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (indexType == LatteIndexType::U16_BE)
|
|
|
|
else if (indexType == LatteIndexType::U16_BE)
|
|
|
|
LatteIndices_unpackQuadsAndConvert<uint16>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_unpackQuadsAndConvert<uint16>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
else if (indexType == LatteIndexType::U32_BE)
|
|
|
|
else if (indexType == LatteIndexType::U32_BE)
|
|
|
|
LatteIndices_unpackQuadsAndConvert<uint32>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_unpackQuadsAndConvert<uint32>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
cemu_assert_debug(false);
|
|
|
|
cemu_assert_debug(false);
|
|
|
|
outputCount = count / 4 * 6;
|
|
|
|
outputCount = count / 4 * 6;
|
|
|
|
@ -803,19 +727,19 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (count <= 0xFFFF)
|
|
|
|
if (count <= 0xFFFF)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LatteIndices_generateAutoQuadStripIndices<uint16>(indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_generateAutoQuadStripIndices<uint16>(indexOutputPtr, count, indexMax);
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U16;
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LatteIndices_generateAutoQuadStripIndices<uint32>(indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_generateAutoQuadStripIndices<uint32>(indexOutputPtr, count, indexMax);
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U32;
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (indexType == LatteIndexType::U16_BE)
|
|
|
|
else if (indexType == LatteIndexType::U16_BE)
|
|
|
|
LatteIndices_unpackQuadStripAndConvert<uint16>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_unpackQuadStripAndConvert<uint16>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
else if (indexType == LatteIndexType::U32_BE)
|
|
|
|
else if (indexType == LatteIndexType::U32_BE)
|
|
|
|
LatteIndices_unpackQuadStripAndConvert<uint32>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_unpackQuadStripAndConvert<uint32>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
cemu_assert_debug(false);
|
|
|
|
cemu_assert_debug(false);
|
|
|
|
if (count >= 2)
|
|
|
|
if (count >= 2)
|
|
|
|
@ -830,19 +754,19 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (count <= 0xFFFF)
|
|
|
|
if (count <= 0xFFFF)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LatteIndices_generateAutoLineLoopIndices<uint16>(indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_generateAutoLineLoopIndices<uint16>(indexOutputPtr, count, indexMax);
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U16;
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LatteIndices_generateAutoLineLoopIndices<uint32>(indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_generateAutoLineLoopIndices<uint32>(indexOutputPtr, count, indexMax);
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U32;
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (indexType == LatteIndexType::U16_BE)
|
|
|
|
else if (indexType == LatteIndexType::U16_BE)
|
|
|
|
LatteIndices_unpackLineLoopAndConvert<uint16>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_unpackLineLoopAndConvert<uint16>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
else if (indexType == LatteIndexType::U32_BE)
|
|
|
|
else if (indexType == LatteIndexType::U32_BE)
|
|
|
|
LatteIndices_unpackLineLoopAndConvert<uint32>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_unpackLineLoopAndConvert<uint32>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
cemu_assert_debug(false);
|
|
|
|
cemu_assert_debug(false);
|
|
|
|
outputCount = count + 1;
|
|
|
|
outputCount = count + 1;
|
|
|
|
@ -853,19 +777,19 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (count <= 0xFFFF)
|
|
|
|
if (count <= 0xFFFF)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LatteIndices_generateAutoTriangleFanIndices<uint16>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_generateAutoTriangleFanIndices<uint16>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U16;
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LatteIndices_generateAutoTriangleFanIndices<uint32>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_generateAutoTriangleFanIndices<uint32>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U32;
|
|
|
|
renderIndexType = Renderer::INDEX_TYPE::U32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (indexType == LatteIndexType::U16_BE)
|
|
|
|
else if (indexType == LatteIndexType::U16_BE)
|
|
|
|
LatteIndices_unpackTriangleFanAndConvert<uint16>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_unpackTriangleFanAndConvert<uint16>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
else if (indexType == LatteIndexType::U32_BE)
|
|
|
|
else if (indexType == LatteIndexType::U32_BE)
|
|
|
|
LatteIndices_unpackTriangleFanAndConvert<uint32>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_unpackTriangleFanAndConvert<uint32>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
cemu_assert_debug(false);
|
|
|
|
cemu_assert_debug(false);
|
|
|
|
outputCount = count;
|
|
|
|
outputCount = count;
|
|
|
|
@ -876,48 +800,48 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
|
|
|
{
|
|
|
|
{
|
|
|
|
#if defined(ARCH_X86_64)
|
|
|
|
#if defined(ARCH_X86_64)
|
|
|
|
if (g_CPUFeatures.x86.avx2)
|
|
|
|
if (g_CPUFeatures.x86.avx2)
|
|
|
|
LatteIndices_fastConvertU16_AVX2(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_fastConvertU16_AVX2(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
else if (g_CPUFeatures.x86.sse4_1 && g_CPUFeatures.x86.ssse3)
|
|
|
|
else if (g_CPUFeatures.x86.sse4_1 && g_CPUFeatures.x86.ssse3)
|
|
|
|
LatteIndices_fastConvertU16_SSE41(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_fastConvertU16_SSE41(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
LatteIndices_convertBE<uint16>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_convertBE<uint16>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
#elif defined(__aarch64__)
|
|
|
|
#elif defined(__aarch64__)
|
|
|
|
LatteIndices_fastConvertU16_NEON(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_fastConvertU16_NEON(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
LatteIndices_convertBE<uint16>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_convertBE<uint16>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (indexType == LatteIndexType::U32_BE)
|
|
|
|
else if (indexType == LatteIndexType::U32_BE)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
#if defined(ARCH_X86_64)
|
|
|
|
#if defined(ARCH_X86_64)
|
|
|
|
if (g_CPUFeatures.x86.avx2)
|
|
|
|
if (g_CPUFeatures.x86.avx2)
|
|
|
|
LatteIndices_fastConvertU32_AVX2(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_fastConvertU32_AVX2(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
LatteIndices_convertBE<uint32>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_convertBE<uint32>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
#elif defined(__aarch64__)
|
|
|
|
#elif defined(__aarch64__)
|
|
|
|
LatteIndices_fastConvertU32_NEON(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_fastConvertU32_NEON(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
LatteIndices_convertBE<uint32>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_convertBE<uint32>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (indexType == LatteIndexType::U16_LE)
|
|
|
|
else if (indexType == LatteIndexType::U16_LE)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LatteIndices_convertLE<uint16>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_convertLE<uint16>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (indexType == LatteIndexType::U32_LE)
|
|
|
|
else if (indexType == LatteIndexType::U32_LE)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LatteIndices_convertLE<uint32>(indexData, indexOutputPtr, count, indexMin, indexMax);
|
|
|
|
LatteIndices_convertLE<uint32>(indexData, indexOutputPtr, count, indexMax);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
cemu_assert_debug(false);
|
|
|
|
cemu_assert_debug(false);
|
|
|
|
outputCount = count;
|
|
|
|
outputCount = count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// the above algorithms use a simplistic approach to get indexMin/indexMax
|
|
|
|
// the above algorithms use a fast approach to get indexMax which does not filter out indices matching primitiveRestartIndex
|
|
|
|
// here we make sure primitive restart indices dont influence the index range
|
|
|
|
// here we use a fallback in case the determined index equals the primitive restart index
|
|
|
|
if (primitiveRestartIndex == indexMin || primitiveRestartIndex == indexMax)
|
|
|
|
if (primitiveRestartIndex == indexMax)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// recalculate index range but filter out primitive restart index
|
|
|
|
// recalculate index range but filter out primitive restart index
|
|
|
|
LatteIndices_alternativeCalculateIndexMinMax(indexData, indexType, count, indexMin, indexMax);
|
|
|
|
LatteIndices_alternativeCalculateIndexMax(indexData, indexType, count, indexMax);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_renderer->indexData_uploadIndexMemory(indexAllocation);
|
|
|
|
g_renderer->indexData_uploadIndexMemory(indexAllocation);
|
|
|
|
performanceMonitor.cycle[performanceMonitor.cycleIndex].indexDataUploaded += indexOutputSize;
|
|
|
|
performanceMonitor.cycle[performanceMonitor.cycleIndex].indexDataUploaded += indexOutputSize;
|
|
|
|
@ -934,7 +858,6 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
|
|
|
lruEntry->lastCount = count;
|
|
|
|
lruEntry->lastCount = count;
|
|
|
|
lruEntry->lastPrimitiveMode = primitiveMode;
|
|
|
|
lruEntry->lastPrimitiveMode = primitiveMode;
|
|
|
|
lruEntry->lastIndexType = indexType;
|
|
|
|
lruEntry->lastIndexType = indexType;
|
|
|
|
lruEntry->indexMin = indexMin;
|
|
|
|
|
|
|
|
lruEntry->indexMax = indexMax;
|
|
|
|
lruEntry->indexMax = indexMax;
|
|
|
|
lruEntry->renderIndexType = renderIndexType;
|
|
|
|
lruEntry->renderIndexType = renderIndexType;
|
|
|
|
lruEntry->outputCount = outputCount;
|
|
|
|
lruEntry->outputCount = outputCount;
|
|
|
|
|