Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(330)

Unified Diff: src/gpu/gl/GrGpuGL_program.cpp

Issue 15252004: Make GrGLProgramDesc's key variable length by compacting the effect key array (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: address comments, fix unit test Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/gl/GrGpuGL.h ('k') | tests/GLProgramsTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/gl/GrGpuGL_program.cpp
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 833d811588555dc354e2a7ae903ec6d2dea87e71..b017d5de40b68580b097a844dfd8224ec16bbb7f 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -9,12 +9,32 @@
#include "GrEffect.h"
#include "GrGLEffect.h"
+#include "SkTSearch.h"
typedef GrGLUniformManager::UniformHandle UniformHandle;
static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
-#define SKIP_CACHE_CHECK true
-#define GR_UINT32_MAX static_cast<uint32_t>(-1)
+struct GrGpuGL::ProgramCache::Entry {
+ SK_DECLARE_INST_COUNT_ROOT(Entry);
+ Entry() : fProgram(NULL), fLRUStamp(0) {}
+
+ SkAutoTUnref<GrGLProgram> fProgram;
+ unsigned int fLRUStamp;
+};
+
+SK_DEFINE_INST_COUNT(GrGpuGL::ProgramCache::Entry);
+
+struct GrGpuGL::ProgramCache::ProgDescLess {
+ bool operator() (const GrGLProgramDesc& desc, const Entry* entry) {
+ GrAssert(NULL != entry->fProgram.get());
+ return GrGLProgramDesc::Less(desc, entry->fProgram->getDesc());
+ }
+
+ bool operator() (const Entry* entry, const GrGLProgramDesc& desc) {
+ GrAssert(NULL != entry->fProgram.get());
+ return GrGLProgramDesc::Less(entry->fProgram->getDesc(), desc);
+ }
+};
GrGpuGL::ProgramCache::ProgramCache(const GrGLContext& gl)
: fCount(0)
@@ -23,70 +43,147 @@ GrGpuGL::ProgramCache::ProgramCache(const GrGLContext& gl)
#ifdef PROGRAM_CACHE_STATS
, fTotalRequests(0)
, fCacheMisses(0)
+ , fHashMisses(0)
#endif
{
+ for (int i = 0; i < 1 << kHashBits; ++i) {
+ fHashTable[i] = NULL;
+ }
}
GrGpuGL::ProgramCache::~ProgramCache() {
+ for (int i = 0; i < fCount; ++i){
+ SkDELETE(fEntries[i]);
+ }
// dump stats
#ifdef PROGRAM_CACHE_STATS
SkDebugf("--- Program Cache ---\n");
SkDebugf("Total requests: %d\n", fTotalRequests);
SkDebugf("Cache misses: %d\n", fCacheMisses);
- SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0)
- ? (float)fCacheMisses/(float)fTotalRequests : 0.0f);
+ 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 GrGpuGL::ProgramCache::abandon() {
for (int i = 0; i < fCount; ++i) {
- GrAssert(NULL != fEntries[i].fProgram.get());
- fEntries[i].fProgram->abandon();
- fEntries[i].fProgram.reset(NULL);
+ GrAssert(NULL != fEntries[i]->fProgram.get());
+ fEntries[i]->fProgram->abandon();
+ fEntries[i]->fProgram.reset(NULL);
}
fCount = 0;
}
+int GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const {
+ ProgDescLess less;
+ return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less);
+}
+
GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc,
const GrEffectStage* stages[]) {
- Entry newEntry;
- newEntry.fKey.setKeyData(desc.asKey());
#ifdef PROGRAM_CACHE_STATS
++fTotalRequests;
#endif
- Entry* entry = fHashCache.find(newEntry.fKey);
+ Entry* entry = NULL;
+
+ uint32_t hashIdx = desc.getChecksum();
+ hashIdx ^= hashIdx >> 16;
+ if (kHashBits <= 8) {
+ hashIdx ^= hashIdx >> 8;
+ }
+ hashIdx &=((1 << kHashBits) - 1);
+ Entry* hashedEntry = fHashTable[hashIdx];
+ if (NULL != hashedEntry && hashedEntry->fProgram->getDesc() == desc) {
+ GrAssert(NULL != hashedEntry->fProgram);
+ entry = hashedEntry;
+ }
+
+ int entryIdx;
+ if (NULL == entry) {
+ entryIdx = this->search(desc);
+ if (entryIdx >= 0) {
+ entry = fEntries[entryIdx];
+#ifdef PROGRAM_CACHE_STATS
+ ++fHashMisses;
+#endif
+ }
+ }
+
if (NULL == entry) {
+ // We have a cache miss
#ifdef PROGRAM_CACHE_STATS
++fCacheMisses;
#endif
- newEntry.fProgram.reset(GrGLProgram::Create(fGL, desc, stages));
- if (NULL == newEntry.fProgram.get()) {
+ GrGLProgram* program = GrGLProgram::Create(fGL, desc, stages);
+ if (NULL == program) {
return NULL;
}
+ int purgeIdx = 0;
if (fCount < kMaxEntries) {
- entry = fEntries + fCount;
- ++fCount;
+ entry = SkNEW(Entry);
+ purgeIdx = fCount++;
+ fEntries[purgeIdx] = entry;
} else {
- GrAssert(kMaxEntries == fCount);
- entry = fEntries;
+ GrAssert(fCount == kMaxEntries);
+ purgeIdx = 0;
for (int i = 1; i < kMaxEntries; ++i) {
- if (fEntries[i].fLRUStamp < entry->fLRUStamp) {
- entry = fEntries + i;
+ if (fEntries[i]->fLRUStamp < fEntries[purgeIdx]->fLRUStamp) {
+ purgeIdx = i;
}
}
- fHashCache.remove(entry->fKey, entry);
+ entry = fEntries[purgeIdx];
+ int purgedHashIdx = entry->fProgram->getDesc().getChecksum() & ((1 << kHashBits) - 1);
+ if (fHashTable[purgedHashIdx] == entry) {
+ fHashTable[purgedHashIdx] = NULL;
+ }
}
- *entry = newEntry;
- fHashCache.insert(entry->fKey, entry);
+ GrAssert(fEntries[purgeIdx] == entry);
+ entry->fProgram.reset(program);
+ // 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;
+ }
+#if GR_DEBUG
+ GrAssert(NULL != fEntries[0]->fProgram.get());
+ for (int i = 0; i < fCount - 1; ++i) {
+ GrAssert(NULL != fEntries[i + 1]->fProgram.get());
+ const GrGLProgramDesc& a = fEntries[i]->fProgram->getDesc();
+ const GrGLProgramDesc& b = fEntries[i + 1]->fProgram->getDesc();
+ GrAssert(GrGLProgramDesc::Less(a, b));
+ GrAssert(!GrGLProgramDesc::Less(b, a));
+ }
+#endif
}
+ fHashTable[hashIdx] = entry;
entry->fLRUStamp = fCurrLRUStamp;
- if (GR_UINT32_MAX == 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;
+ fEntries[i]->fLRUStamp = 0;
}
}
++fCurrLRUStamp;
@@ -177,9 +274,6 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
}
const GrEffectStage* stages[GrDrawState::kNumStages];
- for (int i = 0; i < GrDrawState::kNumStages; ++i) {
- stages[i] = drawState.isStageEnabled(i) ? &drawState.getStage(i) : NULL;
- }
GrGLProgramDesc desc;
GrGLProgramDesc::Build(this->getDrawState(),
kDrawPoints_DrawType == type,
@@ -188,6 +282,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
dstCoeff,
this,
dstCopy,
+ stages,
&desc);
fCurrentProgram.reset(fProgramCache->getProgram(desc, stages));
@@ -206,19 +301,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
- GrColor color;
- GrColor coverage;
- if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
- color = 0;
- coverage = 0;
- } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
- color = 0xffffffff;
- coverage = drawState.getCoverage();
- } else {
- color = drawState.getColor();
- coverage = drawState.getCoverage();
- }
- fCurrentProgram->setData(this, color, coverage, dstCopy, &fSharedGLProgramState);
+ fCurrentProgram->setData(this, blendOpts, stages, dstCopy, &fSharedGLProgramState);
}
this->flushStencil(type);
this->flushScissor();
« no previous file with comments | « src/gpu/gl/GrGpuGL.h ('k') | tests/GLProgramsTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698