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