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