Use MemoryProgramCache.

Add the member functions for saving and loading from the binary cache,
and hook them into the Program class. Requires that the Renderer
supports the program binary extension.

BUG=angleproject:1897

Change-Id: I2dc8d21b02da705ded58c5cd1943562c9c97c49b
Reviewed-on: https://chromium-review.googlesource.com/522874
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/MemoryProgramCache.h b/src/libANGLE/MemoryProgramCache.h
index 66b8e2a..faf0b6f 100644
--- a/src/libANGLE/MemoryProgramCache.h
+++ b/src/libANGLE/MemoryProgramCache.h
@@ -10,8 +10,36 @@
 #ifndef LIBANGLE_MEMORY_PROGRAM_CACHE_H_
 #define LIBANGLE_MEMORY_PROGRAM_CACHE_H_
 
+#include <array>
+
 #include "common/MemoryBuffer.h"
 #include "libANGLE/Error.h"
+#include "libANGLE/SizedMRUCache.h"
+
+namespace gl
+{
+// 128-bit program hash key.
+using ProgramHash = std::array<uint8_t, 20>;
+}  // namespace gl
+
+namespace std
+{
+template <>
+struct hash<gl::ProgramHash>
+{
+    // Simple routine to hash four ints.
+    size_t operator()(const gl::ProgramHash &programHash) const
+    {
+        unsigned int hash = 0;
+        for (uint32_t num : programHash)
+        {
+            hash *= 37;
+            hash += num;
+        }
+        return hash;
+    }
+};
+}  // namespace std
 
 namespace gl
 {
@@ -23,6 +51,9 @@
 class MemoryProgramCache final : angle::NonCopyable
 {
   public:
+    MemoryProgramCache(size_t maxCacheSizeBytes);
+    ~MemoryProgramCache();
+
     // Writes a program's binary to the output memory buffer.
     static void Serialize(const Context *context,
                           const Program *program,
@@ -35,6 +66,40 @@
                                   const uint8_t *binary,
                                   size_t length,
                                   InfoLog &infoLog);
+
+    static void ComputeHash(const Context *context, const Program *program, ProgramHash *hashOut);
+
+    // Check if the cache contains a binary matching the specified program.
+    bool get(const ProgramHash &programHash, const angle::MemoryBuffer **programOut);
+
+    // Evict a program from the binary cache.
+    void remove(const ProgramHash &programHash);
+
+    // Helper method that serializes a program.
+    void putProgram(const ProgramHash &programHash, const Context *context, const Program *program);
+
+    // Helper method that copies a user binary.
+    void putBinary(const Context *context,
+                   const Program *program,
+                   const uint8_t *binary,
+                   size_t length);
+
+    // Check the cache, and deserialize and load the program if found. Evict existing hash if load
+    // fails.
+    LinkResult getProgram(const Context *context,
+                          const Program *program,
+                          ProgramState *state,
+                          ProgramHash *hashOut);
+
+    // Empty the cache.
+    void clear();
+
+  private:
+    // Insert or update a binary program. Program contents are transferred.
+    void put(const ProgramHash &programHash, angle::MemoryBuffer &&binaryProgram);
+
+    angle::SizedMRUCache<ProgramHash, angle::MemoryBuffer> mProgramBinaryCache;
+    unsigned int mIssuedWarnings;
 };
 
 }  // namespace gl