OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2016 Google Inc. |
bsalomon
2016/03/22 14:00:33
spaces?
| |
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 "GrGLGpu.h" | 8 #include "GrVkResourceProvider.h" |
9 | 9 |
10 #include "builders/GrGLProgramBuilder.h" | 10 #include "GrVkGpu.h" |
11 #include "GrProcessor.h" | 11 #include "GrProcessor.h" |
12 #include "GrGLPathRendering.h" | 12 #include "GrVkProgram.h" |
13 #include "GrVkProgramBuilder.h" | |
14 #include "SkRTConf.h" | |
15 #include "SkTSearch.h" | |
13 #include "glsl/GrGLSLFragmentProcessor.h" | 16 #include "glsl/GrGLSLFragmentProcessor.h" |
14 #include "glsl/GrGLSLProgramDataManager.h" | 17 #include "glsl/GrGLSLProgramDataManager.h" |
15 #include "SkRTConf.h" | |
16 #include "SkTSearch.h" | |
17 | 18 |
18 #ifdef PROGRAM_CACHE_STATS | 19 #ifdef PROGRAM_CACHE_STATS |
19 SK_CONF_DECLARE(bool, c_DisplayCache, "gpu.displayCache", false, | 20 SK_CONF_DECLARE(bool, c_DisplayCache, "gpu.displayCache", false, |
20 "Display program cache usage."); | 21 "Display program cache usage."); |
21 #endif | 22 #endif |
22 | 23 |
23 typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; | 24 typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; |
24 | 25 |
25 struct GrGLGpu::ProgramCache::Entry { | 26 struct GrVkResourceProvider::ProgramCache::Entry { |
26 | 27 |
27 Entry() : fProgram(nullptr), fLRUStamp(0) {} | 28 Entry() : fProgram(nullptr), fLRUStamp(0) {} |
28 | 29 |
29 SkAutoTUnref<GrGLProgram> fProgram; | 30 SkAutoTUnref<GrVkProgram> fProgram; |
30 unsigned int fLRUStamp; | 31 unsigned int fLRUStamp; |
31 }; | 32 }; |
32 | 33 |
33 struct GrGLGpu::ProgramCache::ProgDescLess { | 34 struct GrVkResourceProvider::ProgramCache::PipelineDescLess { |
34 bool operator() (const GrProgramDesc& desc, const Entry* entry) { | 35 bool operator() (const GrVkProgram::PipelineDesc& desc, const Entry* entry) { |
35 SkASSERT(entry->fProgram.get()); | 36 SkASSERT(entry->fProgram.get()); |
36 return GrProgramDesc::Less(desc, entry->fProgram->getDesc()); | 37 return GrVkProgram::PipelineDesc::Less(desc, entry->fProgram->getDesc()) ; |
37 } | 38 } |
38 | 39 |
39 bool operator() (const Entry* entry, const GrProgramDesc& desc) { | 40 bool operator() (const Entry* entry, const GrVkProgram::PipelineDesc& desc) { |
40 SkASSERT(entry->fProgram.get()); | 41 SkASSERT(entry->fProgram.get()); |
41 return GrProgramDesc::Less(entry->fProgram->getDesc(), desc); | 42 return GrVkProgram::PipelineDesc::Less(entry->fProgram->getDesc(), desc) ; |
42 } | 43 } |
43 }; | 44 }; |
44 | 45 |
45 GrGLGpu::ProgramCache::ProgramCache(GrGLGpu* gpu) | 46 GrVkResourceProvider::ProgramCache::ProgramCache(GrVkGpu* gpu) |
46 : fCount(0) | 47 : fCount(0) |
47 , fCurrLRUStamp(0) | 48 , fCurrLRUStamp(0) |
48 , fGpu(gpu) | 49 , fGpu(gpu) |
49 #ifdef PROGRAM_CACHE_STATS | 50 #ifdef PROGRAM_CACHE_STATS |
50 , fTotalRequests(0) | 51 , fTotalRequests(0) |
51 , fCacheMisses(0) | 52 , fCacheMisses(0) |
52 , fHashMisses(0) | 53 , fHashMisses(0) |
53 #endif | 54 #endif |
54 { | 55 { |
55 for (int i = 0; i < 1 << kHashBits; ++i) { | 56 for (int i = 0; i < 1 << kHashBits; ++i) { |
56 fHashTable[i] = nullptr; | 57 fHashTable[i] = nullptr; |
57 } | 58 } |
58 } | 59 } |
59 | 60 |
60 GrGLGpu::ProgramCache::~ProgramCache() { | 61 GrVkResourceProvider::ProgramCache::~ProgramCache() { |
61 for (int i = 0; i < fCount; ++i){ | 62 SkASSERT(0 == fCount); |
62 delete fEntries[i]; | |
63 } | |
64 // dump stats | 63 // dump stats |
65 #ifdef PROGRAM_CACHE_STATS | 64 #ifdef PROGRAM_CACHE_STATS |
66 if (c_DisplayCache) { | 65 if (c_DisplayCache) { |
67 SkDebugf("--- Program Cache ---\n"); | 66 SkDebugf("--- Program Cache ---\n"); |
68 SkDebugf("Total requests: %d\n", fTotalRequests); | 67 SkDebugf("Total requests: %d\n", fTotalRequests); |
69 SkDebugf("Cache misses: %d\n", fCacheMisses); | 68 SkDebugf("Cache misses: %d\n", fCacheMisses); |
70 SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ? | 69 SkDebugf("Cache miss %%: %f\n", (fTotalRequests > 0) ? |
71 100.f * fCacheMisses / fTotalRequest s : | 70 100.f * fCacheMisses / fTotalRequests : |
72 0.f); | 71 0.f); |
73 int cacheHits = fTotalRequests - fCacheMisses; | 72 int cacheHits = fTotalRequests - fCacheMisses; |
74 SkDebugf("Hash miss %%: %f\n", (cacheHits > 0) ? 100.f * fHashMisses / c acheHits : 0.f); | 73 SkDebugf("Hash miss %%: %f\n", (cacheHits > 0) ? 100.f * fHashMisses / c acheHits : 0.f); |
75 SkDebugf("---------------------\n"); | 74 SkDebugf("---------------------\n"); |
76 } | 75 } |
77 #endif | 76 #endif |
78 } | 77 } |
79 | 78 |
80 void GrGLGpu::ProgramCache::reset() { | 79 void GrVkResourceProvider::ProgramCache::reset() { |
81 for (int i = 0; i < fCount; ++i) { | 80 for (int i = 0; i < fCount; ++i) { |
82 SkASSERT(fEntries[i]->fProgram.get()); | |
83 fEntries[i]->fProgram->abandon(); | |
84 delete fEntries[i]; | 81 delete fEntries[i]; |
85 fEntries[i] = nullptr; | 82 fEntries[i] = nullptr; |
86 } | 83 } |
87 fCount = 0; | 84 fCount = 0; |
88 | 85 |
89 // zero out hash table | 86 // zero out hash table |
90 for (int i = 0; i < 1 << kHashBits; i++) { | 87 for (int i = 0; i < 1 << kHashBits; i++) { |
91 fHashTable[i] = nullptr; | 88 fHashTable[i] = nullptr; |
92 } | 89 } |
93 | 90 |
94 fCurrLRUStamp = 0; | 91 fCurrLRUStamp = 0; |
95 #ifdef PROGRAM_CACHE_STATS | |
96 fTotalRequests = 0; | |
97 fCacheMisses = 0; | |
98 fHashMisses = 0; | |
99 #endif | |
100 } | 92 } |
101 | 93 |
102 void GrGLGpu::ProgramCache::abandon() { | 94 void GrVkResourceProvider::ProgramCache::abandon() { |
95 for (int i = 0; i < fCount; ++i) { | |
96 SkASSERT(fEntries[i]->fProgram.get()); | |
97 fEntries[i]->fProgram->abandonGPUResources(); | |
98 } | |
103 this->reset(); | 99 this->reset(); |
104 } | 100 } |
105 | 101 |
106 int GrGLGpu::ProgramCache::search(const GrProgramDesc& desc) const { | 102 void GrVkResourceProvider::ProgramCache::release() { |
107 ProgDescLess less; | 103 for (int i = 0; i < fCount; ++i) { |
104 SkASSERT(fEntries[i]->fProgram.get()); | |
105 fEntries[i]->fProgram->freeGPUResources(fGpu); | |
106 } | |
107 this->reset(); | |
108 } | |
109 | |
110 int GrVkResourceProvider::ProgramCache::search(const GrVkProgram::PipelineDesc& desc) const { | |
111 PipelineDescLess less; | |
108 return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less); | 112 return SkTSearch(fEntries, fCount, desc, sizeof(Entry*), less); |
109 } | 113 } |
110 | 114 |
111 GrGLProgram* GrGLGpu::ProgramCache::refProgram(const GrGLGpu* gpu, | 115 GrVkProgram* GrVkResourceProvider::ProgramCache::refProgram(const GrPipeline& pi peline, |
112 const GrPipeline& pipeline, | 116 const GrPrimitivePro cessor& primProc, |
113 const GrPrimitiveProcessor& primP roc) { | 117 GrPrimitiveType prim iteType, |
118 const GrVkRenderPass & renderPass) { | |
114 #ifdef PROGRAM_CACHE_STATS | 119 #ifdef PROGRAM_CACHE_STATS |
115 ++fTotalRequests; | 120 ++fTotalRequests; |
116 #endif | 121 #endif |
117 | 122 |
118 // Get GrGLProgramDesc | 123 Entry* entry = nullptr; |
119 GrGLProgramDesc desc; | 124 |
120 if (!GrGLProgramDescBuilder::Build(&desc, primProc, pipeline, *gpu->glCaps() .glslCaps())) { | 125 // Get GrVkProgramDesc |
121 GrCapsDebugf(gpu->caps(), "Failed to gl program descriptor!\n"); | 126 GrVkProgram::PipelineDesc desc; |
122 return nullptr; | 127 if (!GrVkProgramDescBuilder::Build(&desc.fProgramDesc, |
128 primProc, | |
129 pipeline, | |
130 *fGpu->vkCaps().glslCaps())) { | |
131 GrCapsDebugf(fGpu->caps(), "Failed to vk program descriptor!\n"); | |
jvanverth1
2016/03/21 21:16:16
Failed to build?
| |
132 return false; | |
123 } | 133 } |
124 | 134 |
125 Entry* entry = nullptr; | 135 // Get vulkan specific descriptor key |
136 GrVkProgram::BuildVkKey(pipeline, primiteType, &desc.fVkKey); | |
137 // Get checksum of entire PipelineDesc | |
138 int keyLength = desc.fVkKey.count(); | |
139 SkASSERT(0 == (keyLength % 4)); | |
140 // Seed the checksum with the checksome of the programDesc then add the vulk an key to it. | |
jvanverth1
2016/03/21 21:16:16
Checksum (sp)
| |
141 desc.fChecksum = SkChecksum::Murmur3(desc.fVkKey.begin(), keyLength, | |
142 desc.fProgramDesc.getChecksum()); | |
126 | 143 |
127 uint32_t hashIdx = desc.getChecksum(); | 144 uint32_t hashIdx = desc.fChecksum; |
128 hashIdx ^= hashIdx >> 16; | 145 hashIdx ^= hashIdx >> 16; |
129 if (kHashBits <= 8) { | 146 if (kHashBits <= 8) { |
130 hashIdx ^= hashIdx >> 8; | 147 hashIdx ^= hashIdx >> 8; |
131 } | 148 } |
132 hashIdx &=((1 << kHashBits) - 1); | 149 hashIdx &= ((1 << kHashBits) - 1); |
133 Entry* hashedEntry = fHashTable[hashIdx]; | 150 Entry* hashedEntry = fHashTable[hashIdx]; |
134 if (hashedEntry && hashedEntry->fProgram->getDesc() == desc) { | 151 if (hashedEntry && hashedEntry->fProgram->getDesc() == desc) { |
135 SkASSERT(hashedEntry->fProgram); | 152 SkASSERT(hashedEntry->fProgram); |
136 entry = hashedEntry; | 153 entry = hashedEntry; |
137 } | 154 } |
138 | 155 |
139 int entryIdx; | 156 int entryIdx; |
140 if (nullptr == entry) { | 157 if (nullptr == entry) { |
141 entryIdx = this->search(desc); | 158 entryIdx = this->search(desc); |
142 if (entryIdx >= 0) { | 159 if (entryIdx >= 0) { |
143 entry = fEntries[entryIdx]; | 160 entry = fEntries[entryIdx]; |
144 #ifdef PROGRAM_CACHE_STATS | 161 #ifdef PROGRAM_CACHE_STATS |
145 ++fHashMisses; | 162 ++fHashMisses; |
146 #endif | 163 #endif |
147 } | 164 } |
148 } | 165 } |
149 | 166 |
150 if (nullptr == entry) { | 167 if (nullptr == entry) { |
151 // We have a cache miss | 168 // We have a cache miss |
152 #ifdef PROGRAM_CACHE_STATS | 169 #ifdef PROGRAM_CACHE_STATS |
153 ++fCacheMisses; | 170 ++fCacheMisses; |
154 #endif | 171 #endif |
155 GrGLProgram* program = GrGLProgramBuilder::CreateProgram(pipeline, primP roc, desc, fGpu); | 172 GrVkProgram* program = GrVkProgramBuilder::CreateProgram(fGpu, |
173 pipeline, | |
174 primProc, | |
175 primiteType, | |
176 desc, | |
177 renderPass); | |
156 if (nullptr == program) { | 178 if (nullptr == program) { |
157 return nullptr; | 179 return nullptr; |
158 } | 180 } |
159 int purgeIdx = 0; | 181 int purgeIdx = 0; |
160 if (fCount < kMaxEntries) { | 182 if (fCount < kMaxEntries) { |
161 entry = new Entry; | 183 entry = new Entry; |
162 purgeIdx = fCount++; | 184 purgeIdx = fCount++; |
163 fEntries[purgeIdx] = entry; | 185 fEntries[purgeIdx] = entry; |
164 } else { | 186 } else { |
165 SkASSERT(fCount == kMaxEntries); | 187 SkASSERT(fCount == kMaxEntries); |
166 purgeIdx = 0; | 188 purgeIdx = 0; |
167 for (int i = 1; i < kMaxEntries; ++i) { | 189 for (int i = 1; i < kMaxEntries; ++i) { |
168 if (fEntries[i]->fLRUStamp < fEntries[purgeIdx]->fLRUStamp) { | 190 if (fEntries[i]->fLRUStamp < fEntries[purgeIdx]->fLRUStamp) { |
169 purgeIdx = i; | 191 purgeIdx = i; |
170 } | 192 } |
171 } | 193 } |
172 entry = fEntries[purgeIdx]; | 194 entry = fEntries[purgeIdx]; |
173 int purgedHashIdx = entry->fProgram->getDesc().getChecksum() & ((1 < < kHashBits) - 1); | 195 int purgedHashIdx = entry->fProgram->getDesc().fChecksum & ((1 << kH ashBits) - 1); |
174 if (fHashTable[purgedHashIdx] == entry) { | 196 if (fHashTable[purgedHashIdx] == entry) { |
175 fHashTable[purgedHashIdx] = nullptr; | 197 fHashTable[purgedHashIdx] = nullptr; |
176 } | 198 } |
199 entry->fProgram->freeGPUResources(fGpu); | |
177 } | 200 } |
178 SkASSERT(fEntries[purgeIdx] == entry); | 201 SkASSERT(fEntries[purgeIdx] == entry); |
179 entry->fProgram.reset(program); | 202 entry->fProgram.reset(program); |
180 // We need to shift fEntries around so that the entry currently at purge Idx is placed | 203 // We need to shift fEntries around so that the entry currently at purge Idx is placed |
181 // just before the entry at ~entryIdx (in order to keep fEntries sorted by descriptor). | 204 // just before the entry at ~entryIdx (in order to keep fEntries sorted by descriptor). |
182 entryIdx = ~entryIdx; | 205 entryIdx = ~entryIdx; |
183 if (entryIdx < purgeIdx) { | 206 if (entryIdx < purgeIdx) { |
184 // Let E and P be the entries at index entryIdx and purgeIdx, respe ctively. | 207 // Let E and P be the entries at index entryIdx and purgeIdx, respe ctively. |
185 // If the entries array looks like this: | 208 // If the entries array looks like this: |
186 // aaaaEbbbbbPccccc | 209 // aaaaEbbbbbPccccc |
187 // we rearrange it to look like this: | 210 // we rearrange it to look like this: |
188 // aaaaPEbbbbbccccc | 211 // aaaaPEbbbbbccccc |
189 size_t copySize = (purgeIdx - entryIdx) * sizeof(Entry*); | 212 size_t copySize = (purgeIdx - entryIdx) * sizeof(Entry*); |
190 memmove(fEntries + entryIdx + 1, fEntries + entryIdx, copySize); | 213 memmove(fEntries + entryIdx + 1, fEntries + entryIdx, copySize); |
191 fEntries[entryIdx] = entry; | 214 fEntries[entryIdx] = entry; |
192 } else if (purgeIdx < entryIdx) { | 215 } else if (purgeIdx < entryIdx) { |
193 // If the entries array looks like this: | 216 // If the entries array looks like this: |
194 // aaaaPbbbbbEccccc | 217 // aaaaPbbbbbEccccc |
195 // we rearrange it to look like this: | 218 // we rearrange it to look like this: |
196 // aaaabbbbbPEccccc | 219 // aaaabbbbbPEccccc |
197 size_t copySize = (entryIdx - purgeIdx - 1) * sizeof(Entry*); | 220 size_t copySize = (entryIdx - purgeIdx - 1) * sizeof(Entry*); |
198 memmove(fEntries + purgeIdx, fEntries + purgeIdx + 1, copySize); | 221 memmove(fEntries + purgeIdx, fEntries + purgeIdx + 1, copySize); |
199 fEntries[entryIdx - 1] = entry; | 222 fEntries[entryIdx - 1] = entry; |
200 } | 223 } |
201 #ifdef SK_DEBUG | 224 #ifdef SK_DEBUG |
202 SkASSERT(fEntries[0]->fProgram.get()); | 225 SkASSERT(fEntries[0]->fProgram.get()); |
203 for (int i = 0; i < fCount - 1; ++i) { | 226 for (int i = 0; i < fCount - 1; ++i) { |
204 SkASSERT(fEntries[i + 1]->fProgram.get()); | 227 SkASSERT(fEntries[i + 1]->fProgram.get()); |
205 const GrProgramDesc& a = fEntries[i]->fProgram->getDesc(); | 228 const GrVkProgram::PipelineDesc& a = fEntries[i]->fProgram->getDesc( ); |
206 const GrProgramDesc& b = fEntries[i + 1]->fProgram->getDesc(); | 229 const GrVkProgram::PipelineDesc& b = fEntries[i + 1]->fProgram->getD esc(); |
207 SkASSERT(GrProgramDesc::Less(a, b)); | 230 SkASSERT(GrVkProgram::PipelineDesc::Less(a, b)); |
208 SkASSERT(!GrProgramDesc::Less(b, a)); | 231 SkASSERT(!GrVkProgram::PipelineDesc::Less(b, a)); |
209 } | 232 } |
210 #endif | 233 #endif |
211 } | 234 } |
212 | 235 |
213 fHashTable[hashIdx] = entry; | 236 fHashTable[hashIdx] = entry; |
214 entry->fLRUStamp = fCurrLRUStamp; | 237 entry->fLRUStamp = fCurrLRUStamp; |
215 | 238 |
216 if (SK_MaxU32 == fCurrLRUStamp) { | 239 if (SK_MaxU32 == fCurrLRUStamp) { |
217 // wrap around! just trash our LRU, one time hit. | 240 // wrap around! just trash our LRU, one time hit. |
218 for (int i = 0; i < fCount; ++i) { | 241 for (int i = 0; i < fCount; ++i) { |
219 fEntries[i]->fLRUStamp = 0; | 242 fEntries[i]->fLRUStamp = 0; |
220 } | 243 } |
221 } | 244 } |
222 ++fCurrLRUStamp; | 245 ++fCurrLRUStamp; |
223 return SkRef(entry->fProgram.get()); | 246 return SkRef(entry->fProgram.get()); |
224 } | 247 } |
OLD | NEW |