Index: src/gpu/vk/GrVkPipelineStateCache.cpp |
diff --git a/src/gpu/vk/GrVkPipelineStateCache.cpp b/src/gpu/vk/GrVkPipelineStateCache.cpp |
index f2092af981c91b73ba5f9593ac0535f8b86d37ad..a250dcac995e4f3826afd6d1b6a82c540a4df9b8 100644 |
--- a/src/gpu/vk/GrVkPipelineStateCache.cpp |
+++ b/src/gpu/vk/GrVkPipelineStateCache.cpp |
@@ -12,117 +12,91 @@ |
#include "GrVkPipelineState.h" |
#include "GrVkPipelineStateBuilder.h" |
#include "SkRTConf.h" |
-#include "SkTSearch.h" |
#include "glsl/GrGLSLFragmentProcessor.h" |
#include "glsl/GrGLSLProgramDataManager.h" |
-#ifdef PIPELINE_STATE_CACHE_STATS |
-SK_CONF_DECLARE(bool, c_DisplayCache, "gpu.displayCache", false, |
+#ifdef GR_PIPELINE_STATE_CACHE_STATS |
+SK_CONF_DECLARE(bool, c_DisplayVkPipelineCache, "gpu.displayyVkPipelineCache", false, |
"Display pipeline state cache usage."); |
#endif |
-typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; |
- |
struct GrVkResourceProvider::PipelineStateCache::Entry { |
- Entry() : fPipelineState(nullptr), fLRUStamp(0) {} |
- |
- SkAutoTUnref<GrVkPipelineState> fPipelineState; |
- unsigned int fLRUStamp; |
-}; |
+ Entry() : fPipelineState(nullptr) {} |
-struct GrVkResourceProvider::PipelineStateCache::PipelineDescLess { |
- bool operator() (const GrVkPipelineState::Desc& desc, const Entry* entry) { |
- SkASSERT(entry->fPipelineState.get()); |
- return GrVkPipelineState::Desc::Less(desc, entry->fPipelineState->getDesc()); |
+ static const GrVkPipelineState::Desc& GetKey(const Entry* entry) { |
+ return entry->fPipelineState->getDesc(); |
} |
- bool operator() (const Entry* entry, const GrVkPipelineState::Desc& desc) { |
- SkASSERT(entry->fPipelineState.get()); |
- return GrVkPipelineState::Desc::Less(entry->fPipelineState->getDesc(), desc); |
+ static uint32_t Hash(const GrVkPipelineState::Desc& key) { |
+ return key.fChecksum; |
} |
+ |
+ sk_sp<GrVkPipelineState> fPipelineState; |
+ |
+private: |
+ SK_DECLARE_INTERNAL_LLIST_INTERFACE(Entry); |
}; |
GrVkResourceProvider::PipelineStateCache::PipelineStateCache(GrVkGpu* gpu) |
: fCount(0) |
- , fCurrLRUStamp(0) |
, fGpu(gpu) |
-#ifdef PIPELINE_STATE_CACHE_STATS |
+#ifdef GR_PIPELINE_STATE_CACHE_STATS |
, fTotalRequests(0) |
, fCacheMisses(0) |
- , fHashMisses(0) |
#endif |
-{ |
- for (int i = 0; i < 1 << kHashBits; ++i) { |
- fHashTable[i] = nullptr; |
- } |
-} |
+{} |
GrVkResourceProvider::PipelineStateCache::~PipelineStateCache() { |
SkASSERT(0 == fCount); |
// dump stats |
-#ifdef PIPELINE_STATE_CACHE_STATS |
- if (c_DisplayCache) { |
+#ifdef GR_PIPELINE_STATE_CACHE_STATS |
+ if (c_DisplayVkPipelineCache) { |
SkDebugf("--- Pipeline State Cache ---\n"); |
SkDebugf("Total requests: %d\n", fTotalRequests); |
SkDebugf("Cache misses: %d\n", fCacheMisses); |
SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ? |
100.f * fCacheMisses / fTotalRequests : |
0.f); |
- int cacheHits = fTotalRequests - fCacheMisses; |
- SkDebugf("Hash miss %%: %f\n", (cacheHits > 0) ? 100.f * fHashMisses / cacheHits : 0.f); |
SkDebugf("---------------------\n"); |
} |
#endif |
} |
void GrVkResourceProvider::PipelineStateCache::reset() { |
- for (int i = 0; i < fCount; ++i) { |
- delete fEntries[i]; |
- fEntries[i] = nullptr; |
- } |
+ fHashTable.foreach([](Entry** entry) { |
+ delete *entry; |
+ }); |
+ fHashTable.reset(); |
fCount = 0; |
- |
- // zero out hash table |
- for (int i = 0; i < 1 << kHashBits; i++) { |
- fHashTable[i] = nullptr; |
- } |
- |
- fCurrLRUStamp = 0; |
} |
void GrVkResourceProvider::PipelineStateCache::abandon() { |
- for (int i = 0; i < fCount; ++i) { |
- SkASSERT(fEntries[i]->fPipelineState.get()); |
- fEntries[i]->fPipelineState->abandonGPUResources(); |
- } |
+ fHashTable.foreach([](Entry** entry) { |
+ SkASSERT((*entry)->fPipelineState.get()); |
+ (*entry)->fPipelineState->abandonGPUResources(); |
+ }); |
+ |
this->reset(); |
} |
void GrVkResourceProvider::PipelineStateCache::release() { |
- for (int i = 0; i < fCount; ++i) { |
- SkASSERT(fEntries[i]->fPipelineState.get()); |
- fEntries[i]->fPipelineState->freeGPUResources(fGpu); |
- } |
- this->reset(); |
-} |
+ fHashTable.foreach([this](Entry** entry) { |
+ SkASSERT((*entry)->fPipelineState.get()); |
+ (*entry)->fPipelineState->freeGPUResources(fGpu); |
+ }); |
-int GrVkResourceProvider::PipelineStateCache::search(const GrVkPipelineState::Desc& desc) const { |
- PipelineDescLess less; |
- return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less); |
+ this->reset(); |
} |
-GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::refPipelineState( |
+sk_sp<GrVkPipelineState> GrVkResourceProvider::PipelineStateCache::refPipelineState( |
const GrPipeline& pipeline, |
const GrPrimitiveProcessor& primProc, |
- GrPrimitiveType primiteType, |
+ GrPrimitiveType primitiveType, |
const GrVkRenderPass& renderPass) { |
-#ifdef PIPELINE_STATE_CACHE_STATS |
+#ifdef GR_PIPELINE_STATE_CACHE_STATS |
++fTotalRequests; |
#endif |
- |
- Entry* entry = nullptr; |
- |
// Get GrVkProgramDesc |
GrVkPipelineState::Desc desc; |
if (!GrVkProgramDescBuilder::Build(&desc.fProgramDesc, |
@@ -134,7 +108,7 @@ GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::refPipelineState( |
} |
// Get vulkan specific descriptor key |
- GrVkPipelineState::BuildStateKey(pipeline, primiteType, &desc.fStateKey); |
+ GrVkPipelineState::BuildStateKey(pipeline, primitiveType, &desc.fStateKey); |
// Get checksum of entire PipelineDesc |
int keyLength = desc.fStateKey.count(); |
SkASSERT(0 == (keyLength % 4)); |
@@ -142,108 +116,42 @@ GrVkPipelineState* GrVkResourceProvider::PipelineStateCache::refPipelineState( |
desc.fChecksum = SkChecksum::Murmur3(desc.fStateKey.begin(), keyLength, |
desc.fProgramDesc.getChecksum()); |
- uint32_t hashIdx = desc.fChecksum; |
- hashIdx ^= hashIdx >> 16; |
- if (kHashBits <= 8) { |
- hashIdx ^= hashIdx >> 8; |
- } |
- hashIdx &= ((1 << kHashBits) - 1); |
- Entry* hashedEntry = fHashTable[hashIdx]; |
- if (hashedEntry && hashedEntry->fPipelineState->getDesc() == desc) { |
- SkASSERT(hashedEntry->fPipelineState); |
- entry = hashedEntry; |
- } |
- |
- int entryIdx; |
- if (nullptr == entry) { |
- entryIdx = this->search(desc); |
- if (entryIdx >= 0) { |
- entry = fEntries[entryIdx]; |
-#ifdef PIPELINE_STATE_CACHE_STATS |
- ++fHashMisses; |
-#endif |
- } |
+ Entry* entry = nullptr; |
+ if (Entry** entryptr = fHashTable.find(desc)) { |
+ SkASSERT(*entryptr); |
+ entry = *entryptr; |
} |
- |
- if (nullptr == entry) { |
- // We have a cache miss |
-#ifdef PIPELINE_STATE_CACHE_STATS |
+ if (!entry) { |
+#ifdef GR_PIPELINE_STATE_CACHE_STATS |
++fCacheMisses; |
#endif |
- GrVkPipelineState* pipelineState = |
+ sk_sp<GrVkPipelineState> pipelineState( |
GrVkPipelineStateBuilder::CreatePipelineState(fGpu, |
pipeline, |
primProc, |
- primiteType, |
+ primitiveType, |
desc, |
- renderPass); |
+ renderPass)); |
if (nullptr == pipelineState) { |
return nullptr; |
} |
- int purgeIdx = 0; |
if (fCount < kMaxEntries) { |
entry = new Entry; |
- purgeIdx = fCount++; |
- fEntries[purgeIdx] = entry; |
+ fCount++; |
} else { |
SkASSERT(fCount == kMaxEntries); |
- purgeIdx = 0; |
- for (int i = 1; i < kMaxEntries; ++i) { |
- if (fEntries[i]->fLRUStamp < fEntries[purgeIdx]->fLRUStamp) { |
- purgeIdx = i; |
- } |
- } |
- entry = fEntries[purgeIdx]; |
- int purgedHashIdx = entry->fPipelineState->getDesc().fChecksum & ((1 << kHashBits) - 1); |
- if (fHashTable[purgedHashIdx] == entry) { |
- fHashTable[purgedHashIdx] = nullptr; |
- } |
+ entry = fLRUList.head(); |
+ fLRUList.remove(entry); |
entry->fPipelineState->freeGPUResources(fGpu); |
+ fHashTable.remove(entry->fPipelineState->getDesc()); |
} |
- SkASSERT(fEntries[purgeIdx] == entry); |
- entry->fPipelineState.reset(pipelineState); |
- // We need to shift fEntries around so that the entry currently at purgeIdx is placed |
- // just before the entry at ~entryIdx (in order to keep fEntries sorted by descriptor). |
- entryIdx = ~entryIdx; |
- if (entryIdx < purgeIdx) { |
- // Let E and P be the entries at index entryIdx and purgeIdx, respectively. |
- // If the entries array looks like this: |
- // aaaaEbbbbbPccccc |
- // we rearrange it to look like this: |
- // aaaaPEbbbbbccccc |
- size_t copySize = (purgeIdx - entryIdx) * sizeof(Entry*); |
- memmove(fEntries + entryIdx + 1, fEntries + entryIdx, copySize); |
- fEntries[entryIdx] = entry; |
- } else if (purgeIdx < entryIdx) { |
- // If the entries array looks like this: |
- // aaaaPbbbbbEccccc |
- // we rearrange it to look like this: |
- // aaaabbbbbPEccccc |
- size_t copySize = (entryIdx - purgeIdx - 1) * sizeof(Entry*); |
- memmove(fEntries + purgeIdx, fEntries + purgeIdx + 1, copySize); |
- fEntries[entryIdx - 1] = entry; |
- } |
-#ifdef SK_DEBUG |
- SkASSERT(fEntries[0]->fPipelineState.get()); |
- for (int i = 0; i < fCount - 1; ++i) { |
- SkASSERT(fEntries[i + 1]->fPipelineState.get()); |
- const GrVkPipelineState::Desc& a = fEntries[i]->fPipelineState->getDesc(); |
- const GrVkPipelineState::Desc& b = fEntries[i + 1]->fPipelineState->getDesc(); |
- SkASSERT(GrVkPipelineState::Desc::Less(a, b)); |
- SkASSERT(!GrVkPipelineState::Desc::Less(b, a)); |
- } |
-#endif |
- } |
- |
- fHashTable[hashIdx] = entry; |
- entry->fLRUStamp = fCurrLRUStamp; |
- |
- if (SK_MaxU32 == fCurrLRUStamp) { |
- // wrap around! just trash our LRU, one time hit. |
- for (int i = 0; i < fCount; ++i) { |
- fEntries[i]->fLRUStamp = 0; |
- } |
+ entry->fPipelineState = std::move(pipelineState); |
+ fHashTable.set(entry); |
+ fLRUList.addToTail(entry); |
+ return entry->fPipelineState; |
+ } else { |
+ fLRUList.remove(entry); |
+ fLRUList.addToTail(entry); |
} |
- ++fCurrLRUStamp; |
- return SkRef(entry->fPipelineState.get()); |
+ return entry->fPipelineState; |
} |