1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef GPU_COMMAND_BUFFER_SERVICE_PROGRAM_CACHE_H_
6 #define GPU_COMMAND_BUFFER_SERVICE_PROGRAM_CACHE_H_
7 
8 #include <stddef.h>
9 
10 #include <map>
11 #include <string>
12 #include <unordered_map>
13 #include <unordered_set>
14 
15 #include "base/hash/sha1.h"
16 #include "base/macros.h"
17 #include "base/memory/memory_pressure_listener.h"
18 #include "gpu/command_buffer/common/gl2_types.h"
19 #include "gpu/gpu_gles2_export.h"
20 
21 namespace gpu {
22 
23 class DecoderClient;
24 
25 namespace gles2 {
26 
27 class Shader;
28 
29 // Program cache base class for caching linked gpu programs
30 class GPU_GLES2_EXPORT ProgramCache {
31  public:
32   static const size_t kHashLength = base::kSHA1Length;
33 
34   typedef std::map<std::string, GLint> LocationMap;
35   using CacheProgramCallback =
36       ::base::RepeatingCallback<void(const std::string&, const std::string&)>;
37 
38   enum LinkedProgramStatus {
39     LINK_UNKNOWN,
40     LINK_SUCCEEDED
41   };
42 
43   enum ProgramLoadResult {
44     PROGRAM_LOAD_FAILURE,
45     PROGRAM_LOAD_SUCCESS
46   };
47 
48   class GPU_GLES2_EXPORT ScopedCacheUse {
49    public:
50     ScopedCacheUse(ProgramCache* cache, CacheProgramCallback callback);
51     ~ScopedCacheUse();
52 
53     ScopedCacheUse(ScopedCacheUse&&) = default;
54     ScopedCacheUse& operator=(ScopedCacheUse&& other) = default;
55 
56    private:
57     ProgramCache* cache_;
58   };
59 
60   explicit ProgramCache(size_t max_cache_size_bytes);
61   virtual ~ProgramCache();
62 
63   bool HasSuccessfullyCompiledShader(const std::string& shader_signature) const;
64 
65   LinkedProgramStatus GetLinkedProgramStatus(
66       const std::string& shader_signature_a,
67       const std::string& shader_signature_b,
68       const LocationMap* bind_attrib_location_map,
69       const std::vector<std::string>& transform_feedback_varyings,
70       GLenum transform_feedback_buffer_mode) const;
71 
72   // Loads the linked program from the cache.  If the program is not found or
73   // there was an error, PROGRAM_LOAD_FAILURE should be returned.
74   virtual ProgramLoadResult LoadLinkedProgram(
75       GLuint program,
76       Shader* shader_a,
77       Shader* shader_b,
78       const LocationMap* bind_attrib_location_map,
79       const std::vector<std::string>& transform_feedback_varyings,
80       GLenum transform_feedback_buffer_mode,
81       DecoderClient* client) = 0;
82 
83   // Saves the program into the cache.  If successful, the implementation should
84   // call LinkedProgramCacheSuccess.
85   virtual void SaveLinkedProgram(
86       GLuint program,
87       const Shader* shader_a,
88       const Shader* shader_b,
89       const LocationMap* bind_attrib_location_map,
90       const std::vector<std::string>& transform_feedback_varyings,
91       GLenum transform_feedback_buffer_mode,
92       DecoderClient* client) = 0;
93 
94   virtual void LoadProgram(const std::string& key,
95                            const std::string& program) = 0;
96 
97   // clears the cache
98   void Clear();
99 
100   // Only for testing
101   void LinkedProgramCacheSuccess(const std::string& shader_signature_a,
102        const std::string& shader_signature_b,
103        const LocationMap* bind_attrib_location_map,
104        const std::vector<std::string>& transform_feedback_varyings,
105        GLenum transform_feedback_buffer_mode);
106 
107   // Discards excess cache contents to a fixed upper limit.
108   // Returns the number of bytes of memory freed.
109   virtual size_t Trim(size_t limit) = 0;
110 
111   // Reduces cache usage based on the given MemoryPressureLevel
112   void HandleMemoryPressure(
113       base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
114 
115  protected:
max_size_bytes()116   size_t max_size_bytes() const { return max_size_bytes_; }
117 
118   // called by implementing class after a shader was successfully cached
119   void LinkedProgramCacheSuccess(const std::string& program_hash);
120 
121   void CompiledShaderCacheSuccess(const std::string& shader_hash);
122 
123   // result is not null terminated
124   void ComputeShaderHash(const std::string& shader,
125                          char* result) const;
126 
127   // result is not null terminated.  hashed shaders are expected to be
128   // kHashLength in length
129   void ComputeProgramHash(
130       const char* hashed_shader_0,
131       const char* hashed_shader_1,
132       const LocationMap* bind_attrib_location_map,
133       const std::vector<std::string>& transform_feedback_varyings,
134       GLenum transform_feedback_buffer_mode,
135       char* result) const;
136 
137   void Evict(const std::string& program_hash,
138              const std::string& shader_0_hash,
139              const std::string& shader_1_hash);
140 
141   // Used by the passthrough program cache to notify when a new blob is
142   // inserted.
143   CacheProgramCallback cache_program_callback_;
144 
145  private:
146   typedef std::unordered_map<std::string, LinkedProgramStatus> LinkStatusMap;
147   typedef std::unordered_set<std::string> CachedCompiledShaderSet;
148 
149   // called to clear the backend cache
150   virtual void ClearBackend() = 0;
151 
152   const size_t max_size_bytes_;
153   LinkStatusMap link_status_;
154   // only cache the hash of successfully compiled shaders
155   CachedCompiledShaderSet compiled_shaders_;
156 
157   DISALLOW_COPY_AND_ASSIGN(ProgramCache);
158 };
159 
160 }  // namespace gles2
161 }  // namespace gpu
162 
163 #endif  // GPU_COMMAND_BUFFER_SERVICE_PROGRAM_CACHE_H_
164