1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/command_buffer/service/program_cache.h"
#include <string>
#include "base/memory/scoped_ptr.h"
#include "gpu/command_buffer/service/shader_manager.h"
namespace gpu {
namespace gles2 {
ProgramCache::ProgramCache() {}
ProgramCache::~ProgramCache() {}
void ProgramCache::Clear() {
ClearBackend();
link_status_.clear();
}
ProgramCache::LinkedProgramStatus ProgramCache::GetLinkedProgramStatus(
const std::string& untranslated_a,
const ShaderTranslatorInterface* translator_a,
const std::string& untranslated_b,
const ShaderTranslatorInterface* translator_b,
const std::map<std::string, GLint>* bind_attrib_location_map) const {
char a_sha[kHashLength];
char b_sha[kHashLength];
ComputeShaderHash(untranslated_a, translator_a, a_sha);
ComputeShaderHash(untranslated_b, translator_b, b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
b_sha,
bind_attrib_location_map,
sha);
const std::string sha_string(sha, kHashLength);
LinkStatusMap::const_iterator found = link_status_.find(sha_string);
if (found == link_status_.end()) {
return ProgramCache::LINK_UNKNOWN;
} else {
return found->second;
}
}
void ProgramCache::LinkedProgramCacheSuccess(
const std::string& shader_a,
const ShaderTranslatorInterface* translator_a,
const std::string& shader_b,
const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map) {
char a_sha[kHashLength];
char b_sha[kHashLength];
ComputeShaderHash(shader_a, translator_a, a_sha);
ComputeShaderHash(shader_b, translator_b, b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
b_sha,
bind_attrib_location_map,
sha);
const std::string sha_string(sha, kHashLength);
LinkedProgramCacheSuccess(sha_string);
}
void ProgramCache::LinkedProgramCacheSuccess(const std::string& program_hash) {
link_status_[program_hash] = LINK_SUCCEEDED;
}
void ProgramCache::ComputeShaderHash(
const std::string& str,
const ShaderTranslatorInterface* translator,
char* result) const {
std::string s((
translator ? translator->GetStringForOptionsThatWouldEffectCompilation() :
std::string()) + str);
base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(s.c_str()),
s.length(), reinterpret_cast<unsigned char*>(result));
}
void ProgramCache::Evict(const std::string& program_hash) {
link_status_.erase(program_hash);
}
namespace {
size_t CalculateMapSize(const std::map<std::string, GLint>* map) {
if (!map) {
return 0;
}
std::map<std::string, GLint>::const_iterator it;
size_t total = 0;
for (it = map->begin(); it != map->end(); ++it) {
total += 4 + it->first.length();
}
return total;
}
} // anonymous namespace
void ProgramCache::ComputeProgramHash(
const char* hashed_shader_0,
const char* hashed_shader_1,
const std::map<std::string, GLint>* bind_attrib_location_map,
char* result) const {
const size_t shader0_size = kHashLength;
const size_t shader1_size = kHashLength;
const size_t map_size = CalculateMapSize(bind_attrib_location_map);
const size_t total_size = shader0_size + shader1_size + map_size;
scoped_ptr<unsigned char[]> buffer(new unsigned char[total_size]);
memcpy(buffer.get(), hashed_shader_0, shader0_size);
memcpy(&buffer[shader0_size], hashed_shader_1, shader1_size);
if (map_size != 0) {
// copy our map
size_t current_pos = shader0_size + shader1_size;
std::map<std::string, GLint>::const_iterator it;
for (it = bind_attrib_location_map->begin();
it != bind_attrib_location_map->end();
++it) {
const size_t name_size = it->first.length();
memcpy(&buffer.get()[current_pos], it->first.c_str(), name_size);
current_pos += name_size;
const GLint value = it->second;
buffer[current_pos++] = value >> 24;
buffer[current_pos++] = value >> 16;
buffer[current_pos++] = value >> 8;
buffer[current_pos++] = value;
}
}
base::SHA1HashBytes(buffer.get(),
total_size, reinterpret_cast<unsigned char*>(result));
}
} // namespace gles2
} // namespace gpu
|