Chromium Code Reviews| 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 |