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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/gpu/gl/GrGpuGL.h ('k') | tests/GLProgramsTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrGpuGL.h" 8 #include "GrGpuGL.h"
9 9
10 #include "GrEffect.h" 10 #include "GrEffect.h"
11 #include "GrGLEffect.h" 11 #include "GrGLEffect.h"
12 #include "SkTSearch.h"
12 13
13 typedef GrGLUniformManager::UniformHandle UniformHandle; 14 typedef GrGLUniformManager::UniformHandle UniformHandle;
14 static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidU niformHandle; 15 static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidU niformHandle;
15 16
16 #define SKIP_CACHE_CHECK true 17 struct GrGpuGL::ProgramCache::Entry {
17 #define GR_UINT32_MAX static_cast<uint32_t>(-1) 18 SK_DECLARE_INST_COUNT_ROOT(Entry);
19 Entry() : fProgram(NULL), fLRUStamp(0) {}
20
21 SkAutoTUnref<GrGLProgram> fProgram;
22 unsigned int fLRUStamp;
23 };
24
25 SK_DEFINE_INST_COUNT(GrGpuGL::ProgramCache::Entry);
26
27 struct GrGpuGL::ProgramCache::ProgDescLess {
28 bool operator() (const GrGLProgramDesc& desc, const Entry* entry) {
29 GrAssert(NULL != entry->fProgram.get());
30 return GrGLProgramDesc::Less(desc, entry->fProgram->getDesc());
31 }
32
33 bool operator() (const Entry* entry, const GrGLProgramDesc& desc) {
34 GrAssert(NULL != entry->fProgram.get());
35 return GrGLProgramDesc::Less(entry->fProgram->getDesc(), desc);
36 }
37 };
18 38
19 GrGpuGL::ProgramCache::ProgramCache(const GrGLContext& gl) 39 GrGpuGL::ProgramCache::ProgramCache(const GrGLContext& gl)
20 : fCount(0) 40 : fCount(0)
21 , fCurrLRUStamp(0) 41 , fCurrLRUStamp(0)
22 , fGL(gl) 42 , fGL(gl)
23 #ifdef PROGRAM_CACHE_STATS 43 #ifdef PROGRAM_CACHE_STATS
24 , fTotalRequests(0) 44 , fTotalRequests(0)
25 , fCacheMisses(0) 45 , fCacheMisses(0)
46 , fHashMisses(0)
26 #endif 47 #endif
27 { 48 {
49 for (int i = 0; i < 1 << kHashBits; ++i) {
50 fHashTable[i] = NULL;
51 }
28 } 52 }
29 53
30 GrGpuGL::ProgramCache::~ProgramCache() { 54 GrGpuGL::ProgramCache::~ProgramCache() {
55 for (int i = 0; i < fCount; ++i){
56 SkDELETE(fEntries[i]);
57 }
31 // dump stats 58 // dump stats
32 #ifdef PROGRAM_CACHE_STATS 59 #ifdef PROGRAM_CACHE_STATS
33 SkDebugf("--- Program Cache ---\n"); 60 SkDebugf("--- Program Cache ---\n");
34 SkDebugf("Total requests: %d\n", fTotalRequests); 61 SkDebugf("Total requests: %d\n", fTotalRequests);
35 SkDebugf("Cache misses: %d\n", fCacheMisses); 62 SkDebugf("Cache misses: %d\n", fCacheMisses);
36 SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) 63 SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ?
37 ? (float)fCacheMisses/(float)fTotalRequests : 0.0f); 64 100.f * fCacheMisses / fTotalRequests :
65 0.f);
66 int cacheHits = fTotalRequests - fCacheMisses;
67 SkDebugf("Hash miss %%: %f\n", (cacheHits > 0) ? 100.f * fHashMisses / cache Hits : 0.f);
38 SkDebugf("---------------------\n"); 68 SkDebugf("---------------------\n");
39 #endif 69 #endif
40 } 70 }
41 71
42 void GrGpuGL::ProgramCache::abandon() { 72 void GrGpuGL::ProgramCache::abandon() {
43 for (int i = 0; i < fCount; ++i) { 73 for (int i = 0; i < fCount; ++i) {
44 GrAssert(NULL != fEntries[i].fProgram.get()); 74 GrAssert(NULL != fEntries[i]->fProgram.get());
45 fEntries[i].fProgram->abandon(); 75 fEntries[i]->fProgram->abandon();
46 fEntries[i].fProgram.reset(NULL); 76 fEntries[i]->fProgram.reset(NULL);
47 } 77 }
48 fCount = 0; 78 fCount = 0;
49 } 79 }
50 80
81 int GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const {
82 ProgDescLess less;
83 return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less);
84 }
85
51 GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc, 86 GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc,
52 const GrEffectStage* stages[]) { 87 const GrEffectStage* stages[]) {
53 Entry newEntry;
54 newEntry.fKey.setKeyData(desc.asKey());
55 #ifdef PROGRAM_CACHE_STATS 88 #ifdef PROGRAM_CACHE_STATS
56 ++fTotalRequests; 89 ++fTotalRequests;
57 #endif 90 #endif
58 91
59 Entry* entry = fHashCache.find(newEntry.fKey); 92 Entry* entry = NULL;
93
94 uint32_t hashIdx = desc.getChecksum();
95 hashIdx ^= hashIdx >> 16;
96 if (kHashBits <= 8) {
97 hashIdx ^= hashIdx >> 8;
98 }
99 hashIdx &=((1 << kHashBits) - 1);
100 Entry* hashedEntry = fHashTable[hashIdx];
101 if (NULL != hashedEntry && hashedEntry->fProgram->getDesc() == desc) {
102 GrAssert(NULL != hashedEntry->fProgram);
103 entry = hashedEntry;
104 }
105
106 int entryIdx;
60 if (NULL == entry) { 107 if (NULL == entry) {
108 entryIdx = this->search(desc);
109 if (entryIdx >= 0) {
110 entry = fEntries[entryIdx];
111 #ifdef PROGRAM_CACHE_STATS
112 ++fHashMisses;
113 #endif
114 }
115 }
116
117 if (NULL == entry) {
118 // We have a cache miss
61 #ifdef PROGRAM_CACHE_STATS 119 #ifdef PROGRAM_CACHE_STATS
62 ++fCacheMisses; 120 ++fCacheMisses;
63 #endif 121 #endif
64 newEntry.fProgram.reset(GrGLProgram::Create(fGL, desc, stages)); 122 GrGLProgram* program = GrGLProgram::Create(fGL, desc, stages);
65 if (NULL == newEntry.fProgram.get()) { 123 if (NULL == program) {
66 return NULL; 124 return NULL;
67 } 125 }
126 int purgeIdx = 0;
68 if (fCount < kMaxEntries) { 127 if (fCount < kMaxEntries) {
69 entry = fEntries + fCount; 128 entry = SkNEW(Entry);
70 ++fCount; 129 purgeIdx = fCount++;
130 fEntries[purgeIdx] = entry;
71 } else { 131 } else {
72 GrAssert(kMaxEntries == fCount); 132 GrAssert(fCount == kMaxEntries);
73 entry = fEntries; 133 purgeIdx = 0;
74 for (int i = 1; i < kMaxEntries; ++i) { 134 for (int i = 1; i < kMaxEntries; ++i) {
75 if (fEntries[i].fLRUStamp < entry->fLRUStamp) { 135 if (fEntries[i]->fLRUStamp < fEntries[purgeIdx]->fLRUStamp) {
76 entry = fEntries + i; 136 purgeIdx = i;
77 } 137 }
78 } 138 }
79 fHashCache.remove(entry->fKey, entry); 139 entry = fEntries[purgeIdx];
140 int purgedHashIdx = entry->fProgram->getDesc().getChecksum() & ((1 < < kHashBits) - 1);
141 if (fHashTable[purgedHashIdx] == entry) {
142 fHashTable[purgedHashIdx] = NULL;
143 }
80 } 144 }
81 *entry = newEntry; 145 GrAssert(fEntries[purgeIdx] == entry);
82 fHashCache.insert(entry->fKey, entry); 146 entry->fProgram.reset(program);
147 // We need to shift fEntries around so that the entry currently at purge Idx is placed
148 // just before the entry at ~entryIdx (in order to keep fEntries sorted by descriptor).
149 entryIdx = ~entryIdx;
150 if (entryIdx < purgeIdx) {
151 // Let E and P be the entries at index entryIdx and purgeIdx, respe ctively.
152 // If the entries array looks like this:
153 // aaaaEbbbbbPccccc
154 // we rearrange it to look like this:
155 // aaaaPEbbbbbccccc
156 size_t copySize = (purgeIdx - entryIdx) * sizeof(Entry*);
157 memmove(fEntries + entryIdx + 1, fEntries + entryIdx, copySize);
158 fEntries[entryIdx] = entry;
159 } else if (purgeIdx < entryIdx) {
160 // If the entries array looks like this:
161 // aaaaPbbbbbEccccc
162 // we rearrange it to look like this:
163 // aaaabbbbbPEccccc
164 size_t copySize = (entryIdx - purgeIdx - 1) * sizeof(Entry*);
165 memmove(fEntries + purgeIdx, fEntries + purgeIdx + 1, copySize);
166 fEntries[entryIdx - 1] = entry;
167 }
168 #if GR_DEBUG
169 GrAssert(NULL != fEntries[0]->fProgram.get());
170 for (int i = 0; i < fCount - 1; ++i) {
171 GrAssert(NULL != fEntries[i + 1]->fProgram.get());
172 const GrGLProgramDesc& a = fEntries[i]->fProgram->getDesc();
173 const GrGLProgramDesc& b = fEntries[i + 1]->fProgram->getDesc();
174 GrAssert(GrGLProgramDesc::Less(a, b));
175 GrAssert(!GrGLProgramDesc::Less(b, a));
176 }
177 #endif
83 } 178 }
84 179
180 fHashTable[hashIdx] = entry;
85 entry->fLRUStamp = fCurrLRUStamp; 181 entry->fLRUStamp = fCurrLRUStamp;
86 if (GR_UINT32_MAX == fCurrLRUStamp) { 182
183 if (SK_MaxU32 == fCurrLRUStamp) {
87 // wrap around! just trash our LRU, one time hit. 184 // wrap around! just trash our LRU, one time hit.
88 for (int i = 0; i < fCount; ++i) { 185 for (int i = 0; i < fCount; ++i) {
89 fEntries[i].fLRUStamp = 0; 186 fEntries[i]->fLRUStamp = 0;
90 } 187 }
91 } 188 }
92 ++fCurrLRUStamp; 189 ++fCurrLRUStamp;
93 return entry->fProgram; 190 return entry->fProgram;
94 } 191 }
95 192
96 //////////////////////////////////////////////////////////////////////////////// 193 ////////////////////////////////////////////////////////////////////////////////
97 194
98 void GrGpuGL::abandonResources(){ 195 void GrGpuGL::abandonResources(){
99 INHERITED::abandonResources(); 196 INHERITED::abandonResources();
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 this->flushMiscFixedFunctionState(); 267 this->flushMiscFixedFunctionState();
171 268
172 GrBlendCoeff srcCoeff; 269 GrBlendCoeff srcCoeff;
173 GrBlendCoeff dstCoeff; 270 GrBlendCoeff dstCoeff;
174 GrDrawState::BlendOptFlags blendOpts = drawState.getBlendOpts(false, &sr cCoeff, &dstCoeff); 271 GrDrawState::BlendOptFlags blendOpts = drawState.getBlendOpts(false, &sr cCoeff, &dstCoeff);
175 if (GrDrawState::kSkipDraw_BlendOptFlag & blendOpts) { 272 if (GrDrawState::kSkipDraw_BlendOptFlag & blendOpts) {
176 return false; 273 return false;
177 } 274 }
178 275
179 const GrEffectStage* stages[GrDrawState::kNumStages]; 276 const GrEffectStage* stages[GrDrawState::kNumStages];
180 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
181 stages[i] = drawState.isStageEnabled(i) ? &drawState.getStage(i) : N ULL;
182 }
183 GrGLProgramDesc desc; 277 GrGLProgramDesc desc;
184 GrGLProgramDesc::Build(this->getDrawState(), 278 GrGLProgramDesc::Build(this->getDrawState(),
185 kDrawPoints_DrawType == type, 279 kDrawPoints_DrawType == type,
186 blendOpts, 280 blendOpts,
187 srcCoeff, 281 srcCoeff,
188 dstCoeff, 282 dstCoeff,
189 this, 283 this,
190 dstCopy, 284 dstCopy,
285 stages,
191 &desc); 286 &desc);
192 287
193 fCurrentProgram.reset(fProgramCache->getProgram(desc, stages)); 288 fCurrentProgram.reset(fProgramCache->getProgram(desc, stages));
194 if (NULL == fCurrentProgram.get()) { 289 if (NULL == fCurrentProgram.get()) {
195 GrAssert(!"Failed to create program!"); 290 GrAssert(!"Failed to create program!");
196 return false; 291 return false;
197 } 292 }
198 fCurrentProgram.get()->ref(); 293 fCurrentProgram.get()->ref();
199 294
200 GrGLuint programID = fCurrentProgram->programID(); 295 GrGLuint programID = fCurrentProgram->programID();
201 if (fHWProgramID != programID) { 296 if (fHWProgramID != programID) {
202 GL_CALL(UseProgram(programID)); 297 GL_CALL(UseProgram(programID));
203 fHWProgramID = programID; 298 fHWProgramID = programID;
204 } 299 }
205 300
206 fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff); 301 fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
207 this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff); 302 this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
208 303
209 GrColor color; 304 fCurrentProgram->setData(this, blendOpts, stages, dstCopy, &fSharedGLPro gramState);
210 GrColor coverage;
211 if (blendOpts & GrDrawState::kEmitTransBlack_BlendOptFlag) {
212 color = 0;
213 coverage = 0;
214 } else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
215 color = 0xffffffff;
216 coverage = drawState.getCoverage();
217 } else {
218 color = drawState.getColor();
219 coverage = drawState.getCoverage();
220 }
221 fCurrentProgram->setData(this, color, coverage, dstCopy, &fSharedGLProgr amState);
222 } 305 }
223 this->flushStencil(type); 306 this->flushStencil(type);
224 this->flushScissor(); 307 this->flushScissor();
225 this->flushAAState(type); 308 this->flushAAState(type);
226 309
227 GrIRect* devRect = NULL; 310 GrIRect* devRect = NULL;
228 GrIRect devClipBounds; 311 GrIRect devClipBounds;
229 if (drawState.isClipState()) { 312 if (drawState.isClipState()) {
230 this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &dev ClipBounds); 313 this->getClip()->getConservativeBounds(drawState.getRenderTarget(), &dev ClipBounds);
231 devRect = &devClipBounds; 314 devRect = &devClipBounds;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 GrGLAttribTypeToLayout(attribType).fCount, 389 GrGLAttribTypeToLayout(attribType).fCount,
307 GrGLAttribTypeToLayout(attribType).fType, 390 GrGLAttribTypeToLayout(attribType).fType,
308 GrGLAttribTypeToLayout(attribType).fNormalized, 391 GrGLAttribTypeToLayout(attribType).fNormalized,
309 stride, 392 stride,
310 reinterpret_cast<GrGLvoid*>( 393 reinterpret_cast<GrGLvoid*>(
311 vertexOffsetInBytes + vertexAttrib->fOffset)); 394 vertexOffsetInBytes + vertexAttrib->fOffset));
312 } 395 }
313 396
314 attribState->disableUnusedAttribArrays(this, usedAttribArraysMask); 397 attribState->disableUnusedAttribArrays(this, usedAttribArraysMask);
315 } 398 }
OLDNEW
« 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