GPU: Switch vertex/lookup hashes to XXH3.

This is faster pretty much everywhere.
This commit is contained in:
Unknown W. Brackets 2020-08-27 20:37:49 -07:00
parent 30625225b0
commit 15c25be42b
11 changed files with 22 additions and 41 deletions

View File

@ -8,14 +8,11 @@
#include "Common/CommonFuncs.h"
#include "Common/Log.h"
// Whatever random value.
const uint32_t hashmapSeed = 0x23B58532;
// TODO: Try hardware CRC. Unfortunately not available on older Intels or ARM32.
// Seems to be ubiquitous on ARM64 though.
template<class K>
inline uint32_t HashKey(const K &k) {
return XXH32(&k, sizeof(k), hashmapSeed);
return XXH3_64bits(&k, sizeof(k)) & 0xFFFFFFFF;
}
template<class K>
inline bool KeyEquals(const K &a, const K &b) {

View File

@ -23,7 +23,6 @@
#include "GPU/Common/DrawEngineCommon.h"
#include "GPU/Common/SplineCommon.h"
#include "GPU/Common/VertexDecoderCommon.h"
#include "GPU/Common/TextureDecoder.h" // for ReliableHash
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
@ -607,7 +606,7 @@ inline u32 ComputeMiniHashRange(const void *ptr, size_t sz) {
size_t step = sz / 4;
u32 hash = 0;
for (size_t i = 0; i < sz; i += step) {
hash += DoReliableHash32(p + i, 100, 0x3A44B9C4);
hash += XXH3_64bits(p + i, 100);
}
return hash;
} else {
@ -642,8 +641,8 @@ u32 DrawEngineCommon::ComputeMiniHash() {
return fullhash;
}
ReliableHashType DrawEngineCommon::ComputeHash() {
ReliableHashType fullhash = 0;
uint64_t DrawEngineCommon::ComputeHash() {
uint64_t fullhash = 0;
const int vertexSize = dec_->GetDecVtxFmt().stride;
const int indexSize = IndexSize(dec_->VertexType());
@ -652,7 +651,7 @@ ReliableHashType DrawEngineCommon::ComputeHash() {
for (int i = 0; i < numDrawCalls; i++) {
const DeferredDrawCall &dc = drawCalls[i];
if (!dc.inds) {
fullhash += DoReliableHash((const char *)dc.verts, vertexSize * dc.vertexCount, 0x1DE8CAC4);
fullhash += XXH3_64bits((const char *)dc.verts, vertexSize * dc.vertexCount);
} else {
int indexLowerBound = dc.indexLowerBound, indexUpperBound = dc.indexUpperBound;
int j = i + 1;
@ -667,15 +666,15 @@ ReliableHashType DrawEngineCommon::ComputeHash() {
}
// This could get seriously expensive with sparse indices. Need to combine hashing ranges the same way
// we do when drawing.
fullhash += DoReliableHash((const char *)dc.verts + vertexSize * indexLowerBound,
vertexSize * (indexUpperBound - indexLowerBound), 0x029F3EE1);
fullhash += XXH3_64bits((const char *)dc.verts + vertexSize * indexLowerBound,
vertexSize * (indexUpperBound - indexLowerBound));
// Hm, we will miss some indices when combining above, but meh, it should be fine.
fullhash += DoReliableHash((const char *)dc.inds, indexSize * dc.vertexCount, 0x955FD1CA);
fullhash += XXH3_64bits((const char *)dc.inds, indexSize * dc.vertexCount);
i = lastMatch;
}
}
fullhash += DoReliableHash(&drawCalls[0].uvScale, sizeof(drawCalls[0].uvScale) * numDrawCalls, 0x0123e658);
fullhash += XXH3_64bits(&drawCalls[0].uvScale, sizeof(drawCalls[0].uvScale) * numDrawCalls);
return fullhash;
}

View File

@ -36,13 +36,6 @@ enum {
DECODED_INDEX_BUFFER_SIZE = VERTEX_BUFFER_MAX * 16,
};
// Avoiding the full include of TextureDecoder.h.
#if (defined(_M_SSE) && defined(_M_X64)) || defined(ARM64)
typedef u64 ReliableHashType;
#else
typedef u32 ReliableHashType;
#endif
inline uint32_t GetVertTypeID(uint32_t vertType, int uvGenMode) {
// As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it
// into the top of the verttype where there are unused bits.
@ -115,7 +108,7 @@ protected:
// Utility for vertex caching
u32 ComputeMiniHash();
ReliableHashType ComputeHash();
uint64_t ComputeHash();
// Vertex decoding
void DecodeVertsStep(u8 *dest, int &i, int &decodedVerts);

View File

@ -371,7 +371,7 @@ void DrawEngineD3D11::DoFlush() {
case VertexArrayInfoD3D11::VAI_NEW:
{
// Haven't seen this one before.
ReliableHashType dataHash = ComputeHash();
uint64_t dataHash = ComputeHash();
vai->hash = dataHash;
vai->minihash = ComputeMiniHash();
vai->status = VertexArrayInfoD3D11::VAI_HASHING;
@ -395,7 +395,7 @@ void DrawEngineD3D11::DoFlush() {
if (vai->drawsUntilNextFullHash == 0) {
// Let's try to skip a full hash if mini would fail.
const u32 newMiniHash = ComputeMiniHash();
ReliableHashType newHash = vai->hash;
uint64_t newHash = vai->hash;
if (newMiniHash == vai->minihash) {
newHash = ComputeHash();
}

View File

@ -79,7 +79,7 @@ public:
VAI_UNRELIABLE, // never cache
};
ReliableHashType hash;
uint64_t hash;
u32 minihash;
ID3D11Buffer *vbo;

View File

@ -350,7 +350,7 @@ void DrawEngineDX9::DoFlush() {
case VertexArrayInfoDX9::VAI_NEW:
{
// Haven't seen this one before.
ReliableHashType dataHash = ComputeHash();
uint64_t dataHash = ComputeHash();
vai->hash = dataHash;
vai->minihash = ComputeMiniHash();
vai->status = VertexArrayInfoDX9::VAI_HASHING;
@ -375,7 +375,7 @@ void DrawEngineDX9::DoFlush() {
if (vai->drawsUntilNextFullHash == 0) {
// Let's try to skip a full hash if mini would fail.
const u32 newMiniHash = ComputeMiniHash();
ReliableHashType newHash = vai->hash;
uint64_t newHash = vai->hash;
if (newMiniHash == vai->minihash) {
newHash = ComputeHash();
}

View File

@ -77,7 +77,7 @@ public:
VAI_UNRELIABLE, // never cache
};
ReliableHashType hash;
uint64_t hash;
u32 minihash;
LPDIRECT3DVERTEXBUFFER9 vbo;

View File

@ -365,7 +365,7 @@ void DrawEngineGLES::DoFlush() {
case VertexArrayInfo::VAI_NEW:
{
// Haven't seen this one before.
ReliableHashType dataHash = ComputeHash();
uint64_t dataHash = ComputeHash();
vai->hash = dataHash;
vai->minihash = ComputeMiniHash();
vai->status = VertexArrayInfo::VAI_HASHING;
@ -385,7 +385,7 @@ void DrawEngineGLES::DoFlush() {
if (vai->drawsUntilNextFullHash == 0) {
// Let's try to skip a full hash if mini would fail.
const u32 newMiniHash = ComputeMiniHash();
ReliableHashType newHash = vai->hash;
uint64_t newHash = vai->hash;
if (newMiniHash == vai->minihash) {
newHash = ComputeHash();
}

View File

@ -90,7 +90,7 @@ public:
VAI_UNRELIABLE, // never cache
};
ReliableHashType hash;
uint64_t hash;
u32 minihash;
GLRBuffer *vbo;

View File

@ -35,7 +35,6 @@
#include "Common/Vulkan/VulkanContext.h"
#include "Common/Vulkan/VulkanMemory.h"
#include "GPU/Common/TextureDecoder.h"
#include "GPU/Common/SplineCommon.h"
#include "GPU/Common/TransformCommon.h"
#include "GPU/Common/VertexDecoderCommon.h"
@ -653,7 +652,7 @@ void DrawEngineVulkan::DoFlush() {
case VertexArrayInfoVulkan::VAI_NEW:
{
// Haven't seen this one before. We don't actually upload the vertex data yet.
ReliableHashType dataHash = ComputeHash();
uint64_t dataHash = ComputeHash();
vai->hash = dataHash;
vai->minihash = ComputeMiniHash();
vai->status = VertexArrayInfoVulkan::VAI_HASHING;
@ -678,7 +677,7 @@ void DrawEngineVulkan::DoFlush() {
if (vai->drawsUntilNextFullHash == 0) {
// Let's try to skip a full hash if mini would fail.
const u32 newMiniHash = ComputeMiniHash();
ReliableHashType newHash = vai->hash;
uint64_t newHash = vai->hash;
if (newMiniHash == vai->minihash) {
newHash = ComputeHash();
}

View File

@ -55,13 +55,6 @@ class PipelineManagerVulkan;
class TextureCacheVulkan;
class FramebufferManagerVulkan;
// Avoiding the full include of TextureDecoder.h.
#if (defined(_M_SSE) && defined(_M_X64)) || defined(ARM64)
typedef u64 ReliableHashType;
#else
typedef u32 ReliableHashType;
#endif
class VulkanContext;
class VulkanPushBuffer;
struct VulkanPipeline;
@ -91,7 +84,7 @@ public:
VAI_UNRELIABLE, // never cache
};
ReliableHashType hash;
uint64_t hash;
u32 minihash;
// These will probably always be the same, but whatever.