blob: 9dac6039a8831e9791c3406fdf8040bdd9b5b4ce [file] [log] [blame]
Jamie Madill4f86d052017-06-05 12:59:26 -04001//
2// Copyright 2017 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// MemoryProgramCache: Stores compiled and linked programs in memory so they don't
7// always have to be re-compiled. Can be used in conjunction with the platform
8// layer to warm up the cache from disk.
9
10#include "libANGLE/MemoryProgramCache.h"
11
12#include <GLSLANG/ShaderVars.h>
Jamie Madill32447362017-06-28 14:53:52 -040013#include <anglebase/sha1.h>
Jamie Madill4f86d052017-06-05 12:59:26 -040014
15#include "common/version.h"
16#include "libANGLE/BinaryStream.h"
17#include "libANGLE/Context.h"
18#include "libANGLE/Uniform.h"
19#include "libANGLE/renderer/ProgramImpl.h"
Jamie Madill360daee2017-06-29 10:36:19 -040020#include "platform/Platform.h"
Jamie Madill4f86d052017-06-05 12:59:26 -040021
22namespace gl
23{
24
25namespace
26{
Jamie Madill32447362017-06-28 14:53:52 -040027constexpr unsigned int kWarningLimit = 3;
Jamie Madill4f86d052017-06-05 12:59:26 -040028
29void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
30{
31 stream->writeInt(var.type);
32 stream->writeInt(var.precision);
33 stream->writeString(var.name);
34 stream->writeString(var.mappedName);
35 stream->writeInt(var.arraySize);
36 stream->writeInt(var.staticUse);
37 stream->writeString(var.structName);
38 ASSERT(var.fields.empty());
39}
40
41void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
42{
43 var->type = stream->readInt<GLenum>();
44 var->precision = stream->readInt<GLenum>();
45 var->name = stream->readString();
46 var->mappedName = stream->readString();
47 var->arraySize = stream->readInt<unsigned int>();
48 var->staticUse = stream->readBool();
49 var->structName = stream->readString();
50}
51
jchen10eaef1e52017-06-13 10:44:11 +080052void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var)
53{
54 stream->writeInt(var.binding);
55 stream->writeInt(var.dataSize);
56
57 stream->writeInt(var.vertexStaticUse);
58 stream->writeInt(var.fragmentStaticUse);
59 stream->writeInt(var.computeStaticUse);
60
61 stream->writeInt(var.memberIndexes.size());
62 for (unsigned int memberCounterIndex : var.memberIndexes)
63 {
64 stream->writeInt(memberCounterIndex);
65 }
66}
67
68void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var)
69{
70 var->binding = stream->readInt<int>();
71 var->dataSize = stream->readInt<unsigned int>();
72 var->vertexStaticUse = stream->readBool();
73 var->fragmentStaticUse = stream->readBool();
74 var->computeStaticUse = stream->readBool();
75
76 unsigned int numMembers = stream->readInt<unsigned int>();
77 for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
78 {
79 var->memberIndexes.push_back(stream->readInt<unsigned int>());
80 }
81}
82
Jamie Madill32447362017-06-28 14:53:52 -040083class HashStream final : angle::NonCopyable
84{
85 public:
86 std::string str() { return mStringStream.str(); }
87
88 template <typename T>
89 HashStream &operator<<(T value)
90 {
91 mStringStream << value << kSeparator;
92 return *this;
93 }
94
95 private:
96 static constexpr char kSeparator = ':';
97 std::ostringstream mStringStream;
98};
99
100HashStream &operator<<(HashStream &stream, const Shader *shader)
101{
102 if (shader)
103 {
104 stream << shader->getSourceString().c_str() << shader->getSourceString().length()
105 << shader->getCompilerResourcesString().c_str();
106 }
107 return stream;
108}
109
110HashStream &operator<<(HashStream &stream, const Program::Bindings &bindings)
111{
112 for (const auto &binding : bindings)
113 {
114 stream << binding.first << binding.second;
115 }
116 return stream;
117}
118
119HashStream &operator<<(HashStream &stream, const std::vector<std::string> &strings)
120{
121 for (const auto &str : strings)
122 {
123 stream << str;
124 }
125 return stream;
126}
127
Jamie Madill4f86d052017-06-05 12:59:26 -0400128} // anonymous namespace
129
Jamie Madill32447362017-06-28 14:53:52 -0400130MemoryProgramCache::MemoryProgramCache(size_t maxCacheSizeBytes)
131 : mProgramBinaryCache(maxCacheSizeBytes), mIssuedWarnings(0)
132{
133}
134
135MemoryProgramCache::~MemoryProgramCache()
136{
137}
138
Jamie Madill4f86d052017-06-05 12:59:26 -0400139// static
140LinkResult MemoryProgramCache::Deserialize(const Context *context,
141 const Program *program,
142 ProgramState *state,
143 const uint8_t *binary,
144 size_t length,
145 InfoLog &infoLog)
146{
147 BinaryInputStream stream(binary, length);
148
149 unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
150 stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
151 if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) !=
152 0)
153 {
154 infoLog << "Invalid program binary version.";
155 return false;
156 }
157
158 int majorVersion = stream.readInt<int>();
159 int minorVersion = stream.readInt<int>();
160 if (majorVersion != context->getClientMajorVersion() ||
161 minorVersion != context->getClientMinorVersion())
162 {
163 infoLog << "Cannot load program binaries across different ES context versions.";
164 return false;
165 }
166
167 state->mComputeShaderLocalSize[0] = stream.readInt<int>();
168 state->mComputeShaderLocalSize[1] = stream.readInt<int>();
169 state->mComputeShaderLocalSize[2] = stream.readInt<int>();
170
171 static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8,
172 "Too many vertex attribs for mask");
173 state->mActiveAttribLocationsMask = stream.readInt<unsigned long>();
174
175 unsigned int attribCount = stream.readInt<unsigned int>();
176 ASSERT(state->mAttributes.empty());
177 for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
178 {
179 sh::Attribute attrib;
180 LoadShaderVar(&stream, &attrib);
181 attrib.location = stream.readInt<int>();
182 state->mAttributes.push_back(attrib);
183 }
184
185 unsigned int uniformCount = stream.readInt<unsigned int>();
186 ASSERT(state->mUniforms.empty());
187 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
188 {
189 LinkedUniform uniform;
190 LoadShaderVar(&stream, &uniform);
191
jchen10eaef1e52017-06-13 10:44:11 +0800192 uniform.bufferIndex = stream.readInt<int>();
Jamie Madill4f86d052017-06-05 12:59:26 -0400193 uniform.blockInfo.offset = stream.readInt<int>();
194 uniform.blockInfo.arrayStride = stream.readInt<int>();
195 uniform.blockInfo.matrixStride = stream.readInt<int>();
196 uniform.blockInfo.isRowMajorMatrix = stream.readBool();
197
198 state->mUniforms.push_back(uniform);
199 }
200
201 const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
202 ASSERT(state->mUniformLocations.empty());
203 for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount;
204 uniformIndexIndex++)
205 {
206 VariableLocation variable;
207 stream.readString(&variable.name);
208 stream.readInt(&variable.element);
209 stream.readInt(&variable.index);
210 stream.readBool(&variable.used);
211 stream.readBool(&variable.ignored);
212
213 state->mUniformLocations.push_back(variable);
214 }
215
216 unsigned int uniformBlockCount = stream.readInt<unsigned int>();
217 ASSERT(state->mUniformBlocks.empty());
218 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount;
219 ++uniformBlockIndex)
220 {
221 UniformBlock uniformBlock;
222 stream.readString(&uniformBlock.name);
223 stream.readBool(&uniformBlock.isArray);
224 stream.readInt(&uniformBlock.arrayElement);
Jamie Madill4f86d052017-06-05 12:59:26 -0400225
jchen10eaef1e52017-06-13 10:44:11 +0800226 LoadShaderVariableBuffer(&stream, &uniformBlock);
Jamie Madill4f86d052017-06-05 12:59:26 -0400227
228 state->mUniformBlocks.push_back(uniformBlock);
Jamie Madill4f86d052017-06-05 12:59:26 -0400229
jchen107a20b972017-06-13 14:25:26 +0800230 state->mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0);
Jamie Madill4f86d052017-06-05 12:59:26 -0400231 }
jchen10eaef1e52017-06-13 10:44:11 +0800232 unsigned int atomicCounterBufferCount = stream.readInt<unsigned int>();
233 ASSERT(state->mAtomicCounterBuffers.empty());
234 for (unsigned int bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
235 {
236 AtomicCounterBuffer atomicCounterBuffer;
237 LoadShaderVariableBuffer(&stream, &atomicCounterBuffer);
238
239 state->mAtomicCounterBuffers.push_back(atomicCounterBuffer);
240 }
Jamie Madill4f86d052017-06-05 12:59:26 -0400241
242 unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
Jamie Madillffe00c02017-06-27 16:26:55 -0400243
244 // Reject programs that use transform feedback varyings if the hardware cannot support them.
245 if (transformFeedbackVaryingCount > 0 &&
246 context->getWorkarounds().disableProgramCachingForTransformFeedback)
247 {
248 infoLog << "Current driver does not support transform feedback in binary programs.";
249 return false;
250 }
251
Jamie Madill4f86d052017-06-05 12:59:26 -0400252 ASSERT(state->mLinkedTransformFeedbackVaryings.empty());
253 for (unsigned int transformFeedbackVaryingIndex = 0;
254 transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
255 ++transformFeedbackVaryingIndex)
256 {
257 sh::Varying varying;
258 stream.readInt(&varying.arraySize);
259 stream.readInt(&varying.type);
260 stream.readString(&varying.name);
261
262 GLuint arrayIndex = stream.readInt<GLuint>();
263
264 state->mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex);
265 }
266
267 stream.readInt(&state->mTransformFeedbackBufferMode);
268
269 unsigned int outputCount = stream.readInt<unsigned int>();
270 ASSERT(state->mOutputVariables.empty());
271 for (unsigned int outputIndex = 0; outputIndex < outputCount; ++outputIndex)
272 {
273 sh::OutputVariable output;
274 LoadShaderVar(&stream, &output);
275 output.location = stream.readInt<int>();
276 state->mOutputVariables.push_back(output);
277 }
278
279 unsigned int outputVarCount = stream.readInt<unsigned int>();
280 for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
281 {
282 int locationIndex = stream.readInt<int>();
283 VariableLocation locationData;
284 stream.readInt(&locationData.element);
285 stream.readInt(&locationData.index);
286 stream.readString(&locationData.name);
287 state->mOutputLocations[locationIndex] = locationData;
288 }
289
290 unsigned int outputTypeCount = stream.readInt<unsigned int>();
291 for (unsigned int outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
292 {
293 state->mOutputVariableTypes.push_back(stream.readInt<GLenum>());
294 }
295 static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS < 8 * sizeof(uint32_t),
296 "All bits of DrawBufferMask can be contained in an uint32_t");
297 state->mActiveOutputVariables = stream.readInt<uint32_t>();
298
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800299 unsigned int samplerRangeLow = stream.readInt<unsigned int>();
300 unsigned int samplerRangeHigh = stream.readInt<unsigned int>();
301 state->mSamplerUniformRange = RangeUI(samplerRangeLow, samplerRangeHigh);
Jamie Madill4f86d052017-06-05 12:59:26 -0400302 unsigned int samplerCount = stream.readInt<unsigned int>();
303 for (unsigned int samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
304 {
305 GLenum textureType = stream.readInt<GLenum>();
306 size_t bindingCount = stream.readInt<size_t>();
307 state->mSamplerBindings.emplace_back(SamplerBinding(textureType, bindingCount));
308 }
309
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800310 unsigned int imageRangeLow = stream.readInt<unsigned int>();
311 unsigned int imageRangeHigh = stream.readInt<unsigned int>();
312 state->mImageUniformRange = RangeUI(imageRangeLow, imageRangeHigh);
Xinghua Cao0328b572017-06-26 15:51:36 +0800313 unsigned int imageBindingCount = stream.readInt<unsigned int>();
314 for (unsigned int imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800315 {
Xinghua Cao0328b572017-06-26 15:51:36 +0800316 unsigned int elementCount = stream.readInt<unsigned int>();
317 ImageBinding imageBinding(elementCount);
318 for (unsigned int i = 0; i < elementCount; ++i)
319 {
320 imageBinding.boundImageUnits[i] = stream.readInt<unsigned int>();
321 }
322 state->mImageBindings.emplace_back(imageBinding);
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800323 }
324
jchen10eaef1e52017-06-13 10:44:11 +0800325 unsigned int atomicCounterRangeLow = stream.readInt<unsigned int>();
326 unsigned int atomicCounterRangeHigh = stream.readInt<unsigned int>();
327 state->mAtomicCounterUniformRange = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
328
Jamie Madill4f86d052017-06-05 12:59:26 -0400329 return program->getImplementation()->load(context, infoLog, &stream);
330}
331
332// static
333void MemoryProgramCache::Serialize(const Context *context,
334 const gl::Program *program,
335 angle::MemoryBuffer *binaryOut)
336{
337 BinaryOutputStream stream;
338
339 stream.writeBytes(reinterpret_cast<const unsigned char *>(ANGLE_COMMIT_HASH),
340 ANGLE_COMMIT_HASH_SIZE);
341
342 // nullptr context is supported when computing binary length.
343 if (context)
344 {
345 stream.writeInt(context->getClientVersion().major);
346 stream.writeInt(context->getClientVersion().minor);
347 }
348 else
349 {
350 stream.writeInt(2);
351 stream.writeInt(0);
352 }
353
354 const auto &state = program->getState();
355
356 const auto &computeLocalSize = state.getComputeShaderLocalSize();
357
358 stream.writeInt(computeLocalSize[0]);
359 stream.writeInt(computeLocalSize[1]);
360 stream.writeInt(computeLocalSize[2]);
361
362 stream.writeInt(state.getActiveAttribLocationsMask().to_ulong());
363
364 stream.writeInt(state.getAttributes().size());
365 for (const sh::Attribute &attrib : state.getAttributes())
366 {
367 WriteShaderVar(&stream, attrib);
368 stream.writeInt(attrib.location);
369 }
370
371 stream.writeInt(state.getUniforms().size());
372 for (const LinkedUniform &uniform : state.getUniforms())
373 {
374 WriteShaderVar(&stream, uniform);
375
376 // FIXME: referenced
377
jchen10eaef1e52017-06-13 10:44:11 +0800378 stream.writeInt(uniform.bufferIndex);
Jamie Madill4f86d052017-06-05 12:59:26 -0400379 stream.writeInt(uniform.blockInfo.offset);
380 stream.writeInt(uniform.blockInfo.arrayStride);
381 stream.writeInt(uniform.blockInfo.matrixStride);
382 stream.writeInt(uniform.blockInfo.isRowMajorMatrix);
383 }
384
385 stream.writeInt(state.getUniformLocations().size());
386 for (const auto &variable : state.getUniformLocations())
387 {
388 stream.writeString(variable.name);
389 stream.writeInt(variable.element);
390 stream.writeInt(variable.index);
391 stream.writeInt(variable.used);
392 stream.writeInt(variable.ignored);
393 }
394
395 stream.writeInt(state.getUniformBlocks().size());
396 for (const UniformBlock &uniformBlock : state.getUniformBlocks())
397 {
398 stream.writeString(uniformBlock.name);
399 stream.writeInt(uniformBlock.isArray);
400 stream.writeInt(uniformBlock.arrayElement);
Jamie Madill4f86d052017-06-05 12:59:26 -0400401
jchen10eaef1e52017-06-13 10:44:11 +0800402 WriteShaderVariableBuffer(&stream, uniformBlock);
403 }
Jamie Madill4f86d052017-06-05 12:59:26 -0400404
jchen10eaef1e52017-06-13 10:44:11 +0800405 stream.writeInt(state.mAtomicCounterBuffers.size());
406 for (const auto &atomicCounterBuffer : state.mAtomicCounterBuffers)
407 {
408 WriteShaderVariableBuffer(&stream, atomicCounterBuffer);
Jamie Madill4f86d052017-06-05 12:59:26 -0400409 }
410
Jamie Madillffe00c02017-06-27 16:26:55 -0400411 // Warn the app layer if saving a binary with unsupported transform feedback.
412 if (!state.getLinkedTransformFeedbackVaryings().empty() &&
413 context->getWorkarounds().disableProgramCachingForTransformFeedback)
414 {
415 WARN() << "Saving program binary with transform feedback, which is not supported on this "
416 "driver.";
417 }
418
Jamie Madill4f86d052017-06-05 12:59:26 -0400419 stream.writeInt(state.getLinkedTransformFeedbackVaryings().size());
420 for (const auto &var : state.getLinkedTransformFeedbackVaryings())
421 {
422 stream.writeInt(var.arraySize);
423 stream.writeInt(var.type);
424 stream.writeString(var.name);
425
426 stream.writeIntOrNegOne(var.arrayIndex);
427 }
428
429 stream.writeInt(state.getTransformFeedbackBufferMode());
430
431 stream.writeInt(state.getOutputVariables().size());
432 for (const sh::OutputVariable &output : state.getOutputVariables())
433 {
434 WriteShaderVar(&stream, output);
435 stream.writeInt(output.location);
436 }
437
438 stream.writeInt(state.getOutputLocations().size());
439 for (const auto &outputPair : state.getOutputLocations())
440 {
441 stream.writeInt(outputPair.first);
442 stream.writeIntOrNegOne(outputPair.second.element);
443 stream.writeInt(outputPair.second.index);
444 stream.writeString(outputPair.second.name);
445 }
446
447 stream.writeInt(state.mOutputVariableTypes.size());
448 for (const auto &outputVariableType : state.mOutputVariableTypes)
449 {
450 stream.writeInt(outputVariableType);
451 }
452
453 static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS < 8 * sizeof(uint32_t),
454 "All bits of DrawBufferMask can be contained in an uint32_t");
455 stream.writeInt(static_cast<uint32_t>(state.mActiveOutputVariables.to_ulong()));
456
457 stream.writeInt(state.getSamplerUniformRange().low());
458 stream.writeInt(state.getSamplerUniformRange().high());
459
460 stream.writeInt(state.getSamplerBindings().size());
461 for (const auto &samplerBinding : state.getSamplerBindings())
462 {
463 stream.writeInt(samplerBinding.textureType);
464 stream.writeInt(samplerBinding.boundTextureUnits.size());
465 }
466
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800467 stream.writeInt(state.getImageUniformRange().low());
468 stream.writeInt(state.getImageUniformRange().high());
469
470 stream.writeInt(state.getImageBindings().size());
471 for (const auto &imageBinding : state.getImageBindings())
472 {
Xinghua Cao0328b572017-06-26 15:51:36 +0800473 stream.writeInt(imageBinding.boundImageUnits.size());
474 for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i)
475 {
476 stream.writeInt(imageBinding.boundImageUnits[i]);
477 }
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800478 }
479
jchen10eaef1e52017-06-13 10:44:11 +0800480 stream.writeInt(state.getAtomicCounterUniformRange().low());
481 stream.writeInt(state.getAtomicCounterUniformRange().high());
482
Jamie Madill27a60632017-06-30 15:12:01 -0400483 program->getImplementation()->save(context, &stream);
Jamie Madill4f86d052017-06-05 12:59:26 -0400484
485 ASSERT(binaryOut);
486 binaryOut->resize(stream.length());
487 memcpy(binaryOut->data(), stream.data(), stream.length());
488}
489
Jamie Madill32447362017-06-28 14:53:52 -0400490// static
491void MemoryProgramCache::ComputeHash(const Context *context,
492 const Program *program,
493 ProgramHash *hashOut)
494{
495 auto vertexShader = program->getAttachedVertexShader();
496 auto fragmentShader = program->getAttachedFragmentShader();
497 auto computeShader = program->getAttachedComputeShader();
498
499 // Compute the program hash. Start with the shader hashes and resource strings.
500 HashStream hashStream;
501 hashStream << vertexShader << fragmentShader << computeShader;
502
503 // Add some ANGLE metadata and Context properties, such as version and back-end.
504 hashStream << ANGLE_COMMIT_HASH << context->getClientMajorVersion()
505 << context->getClientMinorVersion() << context->getString(GL_RENDERER);
506
507 // Hash pre-link program properties.
508 hashStream << program->getAttributeBindings() << program->getUniformLocationBindings()
509 << program->getFragmentInputBindings()
510 << program->getState().getTransformFeedbackVaryingNames()
511 << program->getState().getTransformFeedbackBufferMode();
512
513 // Call the secure SHA hashing function.
514 const std::string &programKey = hashStream.str();
515 angle::base::SHA1HashBytes(reinterpret_cast<const unsigned char *>(programKey.c_str()),
516 programKey.length(), hashOut->data());
517}
518
519LinkResult MemoryProgramCache::getProgram(const Context *context,
520 const Program *program,
521 ProgramState *state,
522 ProgramHash *hashOut)
523{
524 ComputeHash(context, program, hashOut);
525 const angle::MemoryBuffer *binaryProgram = nullptr;
526 LinkResult result(false);
527 if (get(*hashOut, &binaryProgram))
528 {
529 InfoLog infoLog;
530 ANGLE_TRY_RESULT(Deserialize(context, program, state, binaryProgram->data(),
531 binaryProgram->size(), infoLog),
532 result);
533 if (!result.getResult())
534 {
535 // Cache load failed, evict.
536 if (mIssuedWarnings++ < kWarningLimit)
537 {
538 WARN() << "Failed to load binary from cache: " << infoLog.str();
539
540 if (mIssuedWarnings == kWarningLimit)
541 {
542 WARN() << "Reaching warning limit for cache load failures, silencing "
543 "subsequent warnings.";
544 }
545 }
546 remove(*hashOut);
547 }
548 }
549 return result;
550}
551
552bool MemoryProgramCache::get(const ProgramHash &programHash, const angle::MemoryBuffer **programOut)
553{
554 return mProgramBinaryCache.get(programHash, programOut);
555}
556
Jamie Madillc43be722017-07-13 16:22:14 -0400557bool MemoryProgramCache::getAt(size_t index,
558 ProgramHash *hashOut,
559 const angle::MemoryBuffer **programOut)
560{
561 return mProgramBinaryCache.getAt(index, hashOut, programOut);
562}
563
Jamie Madill32447362017-06-28 14:53:52 -0400564void MemoryProgramCache::remove(const ProgramHash &programHash)
565{
566 bool result = mProgramBinaryCache.eraseByKey(programHash);
567 ASSERT(result);
568}
569
Jamie Madill360daee2017-06-29 10:36:19 -0400570void MemoryProgramCache::put(const ProgramHash &program,
Jamie Madill360daee2017-06-29 10:36:19 -0400571 angle::MemoryBuffer &&binaryProgram)
Jamie Madill32447362017-06-28 14:53:52 -0400572{
Jamie Madill360daee2017-06-29 10:36:19 -0400573 const angle::MemoryBuffer *result =
574 mProgramBinaryCache.put(program, std::move(binaryProgram), binaryProgram.size());
575 if (!result)
Jamie Madill32447362017-06-28 14:53:52 -0400576 {
577 ERR() << "Failed to store binary program in memory cache, program is too large.";
578 }
Jamie Madill360daee2017-06-29 10:36:19 -0400579 else
580 {
581 auto *platform = ANGLEPlatformCurrent();
582 platform->cacheProgram(platform, program, result->size(), result->data());
583 }
Jamie Madill32447362017-06-28 14:53:52 -0400584}
585
586void MemoryProgramCache::putProgram(const ProgramHash &programHash,
587 const Context *context,
588 const Program *program)
589{
590 angle::MemoryBuffer binaryProgram;
591 Serialize(context, program, &binaryProgram);
Jamie Madillc43be722017-07-13 16:22:14 -0400592 put(programHash, std::move(binaryProgram));
Jamie Madill32447362017-06-28 14:53:52 -0400593}
594
Jamie Madill4c19a8a2017-07-24 11:46:06 -0400595void MemoryProgramCache::updateProgram(const Context *context, const Program *program)
596{
597 gl::ProgramHash programHash;
598 ComputeHash(context, program, &programHash);
599 putProgram(programHash, context, program);
600}
601
Jamie Madillc43be722017-07-13 16:22:14 -0400602void MemoryProgramCache::putBinary(const ProgramHash &programHash,
Jamie Madill32447362017-06-28 14:53:52 -0400603 const uint8_t *binary,
604 size_t length)
605{
606 // Copy the binary.
607 angle::MemoryBuffer binaryProgram;
608 binaryProgram.resize(length);
609 memcpy(binaryProgram.data(), binary, length);
610
Jamie Madill32447362017-06-28 14:53:52 -0400611 // Store the binary.
Jamie Madillc43be722017-07-13 16:22:14 -0400612 const angle::MemoryBuffer *result =
613 mProgramBinaryCache.put(programHash, std::move(binaryProgram), binaryProgram.size());
614 if (!result)
615 {
616 ERR() << "Failed to store binary program in memory cache, program is too large.";
617 }
Jamie Madill32447362017-06-28 14:53:52 -0400618}
619
620void MemoryProgramCache::clear()
621{
622 mProgramBinaryCache.clear();
623 mIssuedWarnings = 0;
624}
625
Jamie Madillc43be722017-07-13 16:22:14 -0400626void MemoryProgramCache::resize(size_t maxCacheSizeBytes)
627{
628 mProgramBinaryCache.resize(maxCacheSizeBytes);
629}
630
631size_t MemoryProgramCache::entryCount() const
632{
633 return mProgramBinaryCache.entryCount();
634}
635
636size_t MemoryProgramCache::trim(size_t limit)
637{
638 return mProgramBinaryCache.shrinkToSize(limit);
639}
640
641size_t MemoryProgramCache::size() const
642{
643 return mProgramBinaryCache.size();
644}
645
646size_t MemoryProgramCache::maxSize() const
647{
648 return mProgramBinaryCache.maxSize();
649}
650
Jamie Madill4f86d052017-06-05 12:59:26 -0400651} // namespace gl