• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2012 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 
7 // ShaderCache: Defines rx::ShaderCache, a cache of Direct3D shader objects
8 // keyed by their byte code.
9 
10 #ifndef LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
11 #define LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
12 
13 #include "libANGLE/Error.h"
14 
15 #include "common/debug.h"
16 #include "libANGLE/renderer/d3d/d3d9/Context9.h"
17 
18 #include <cstddef>
19 #include <mutex>
20 #include <string>
21 #include <unordered_map>
22 
23 namespace rx
24 {
25 template <typename ShaderObject>
26 class ShaderCache : angle::NonCopyable
27 {
28   public:
ShaderCache()29     ShaderCache() : mDevice(nullptr) {}
30 
~ShaderCache()31     ~ShaderCache()
32     {
33         // Call clear while the device is still valid.
34         ASSERT(mMap.empty());
35     }
36 
initialize(IDirect3DDevice9 * device)37     void initialize(IDirect3DDevice9 *device) { mDevice = device; }
38 
create(d3d::Context * context,const DWORD * function,size_t length,ShaderObject ** outShaderObject)39     angle::Result create(d3d::Context *context,
40                          const DWORD *function,
41                          size_t length,
42                          ShaderObject **outShaderObject)
43     {
44         std::lock_guard<std::mutex> lock(mMutex);
45 
46         std::string key(reinterpret_cast<const char *>(function), length);
47         typename Map::iterator it = mMap.find(key);
48         if (it != mMap.end())
49         {
50             it->second->AddRef();
51             *outShaderObject = it->second;
52             return angle::Result::Continue;
53         }
54 
55         ShaderObject *shader;
56         HRESULT result = createShader(function, &shader);
57         ANGLE_TRY_HR(context, result, "Failed to create shader");
58 
59         // Random eviction policy.
60         if (mMap.size() >= kMaxMapSize)
61         {
62             SafeRelease(mMap.begin()->second);
63             mMap.erase(mMap.begin());
64         }
65 
66         shader->AddRef();
67         mMap[key] = shader;
68 
69         *outShaderObject = shader;
70         return angle::Result::Continue;
71     }
72 
clear()73     void clear()
74     {
75         std::lock_guard<std::mutex> lock(mMutex);
76 
77         for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it)
78         {
79             SafeRelease(it->second);
80         }
81 
82         mMap.clear();
83     }
84 
85   private:
86     const static size_t kMaxMapSize = 100;
87 
createShader(const DWORD * function,IDirect3DVertexShader9 ** shader)88     HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader)
89     {
90         return mDevice->CreateVertexShader(function, shader);
91     }
92 
createShader(const DWORD * function,IDirect3DPixelShader9 ** shader)93     HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader)
94     {
95         return mDevice->CreatePixelShader(function, shader);
96     }
97 
98     typedef angle::HashMap<std::string, ShaderObject *> Map;
99     Map mMap;
100     std::mutex mMutex;
101 
102     IDirect3DDevice9 *mDevice;
103 };
104 
105 typedef ShaderCache<IDirect3DVertexShader9> VertexShaderCache;
106 typedef ShaderCache<IDirect3DPixelShader9> PixelShaderCache;
107 
108 }  // namespace rx
109 
110 #endif  // LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
111