From 15c25be42bd8c7526487a10a9f400f19cf17fadd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 27 Aug 2020 20:37:49 -0700 Subject: [PATCH] GPU: Switch vertex/lookup hashes to XXH3. This is faster pretty much everywhere. --- Common/Hashmaps.h | 5 +---- GPU/Common/DrawEngineCommon.cpp | 17 ++++++++--------- GPU/Common/DrawEngineCommon.h | 9 +-------- GPU/D3D11/DrawEngineD3D11.cpp | 4 ++-- GPU/D3D11/DrawEngineD3D11.h | 2 +- GPU/Directx9/DrawEngineDX9.cpp | 4 ++-- GPU/Directx9/DrawEngineDX9.h | 2 +- GPU/GLES/DrawEngineGLES.cpp | 4 ++-- GPU/GLES/DrawEngineGLES.h | 2 +- GPU/Vulkan/DrawEngineVulkan.cpp | 5 ++--- GPU/Vulkan/DrawEngineVulkan.h | 9 +-------- 11 files changed, 22 insertions(+), 41 deletions(-) diff --git a/Common/Hashmaps.h b/Common/Hashmaps.h index 04d88067bd..4c6664277c 100644 --- a/Common/Hashmaps.h +++ b/Common/Hashmaps.h @@ -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 inline uint32_t HashKey(const K &k) { - return XXH32(&k, sizeof(k), hashmapSeed); + return XXH3_64bits(&k, sizeof(k)) & 0xFFFFFFFF; } template inline bool KeyEquals(const K &a, const K &b) { diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index bcd8a41e29..8285191699 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -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; } diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 6bc34f10ac..0aa5f36b42 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -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); diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 0e5b8444a7..0c08c49ae0 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -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(); } diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index 3511f760f5..88d27c6bc1 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -79,7 +79,7 @@ public: VAI_UNRELIABLE, // never cache }; - ReliableHashType hash; + uint64_t hash; u32 minihash; ID3D11Buffer *vbo; diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index 376339c7d4..66f269ff58 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -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(); } diff --git a/GPU/Directx9/DrawEngineDX9.h b/GPU/Directx9/DrawEngineDX9.h index 2d01617b40..22cb6a7a4e 100644 --- a/GPU/Directx9/DrawEngineDX9.h +++ b/GPU/Directx9/DrawEngineDX9.h @@ -77,7 +77,7 @@ public: VAI_UNRELIABLE, // never cache }; - ReliableHashType hash; + uint64_t hash; u32 minihash; LPDIRECT3DVERTEXBUFFER9 vbo; diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index b07e819d43..cd8a7910a9 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -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(); } diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 70159d7e2e..f484034e11 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -90,7 +90,7 @@ public: VAI_UNRELIABLE, // never cache }; - ReliableHashType hash; + uint64_t hash; u32 minihash; GLRBuffer *vbo; diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index db98dcca5c..4a9b9a29fb 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -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(); } diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 8ea60dec73..0cb4a5bdcd 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -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.