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