| // |
| // Copyright 2012 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| // ShaderCache: Defines rx::ShaderCache, a cache of Direct3D shader objects |
| // keyed by their byte code. |
| |
| #ifndef LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_ |
| #define LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_ |
| |
| #include "libANGLE/Error.h" |
| |
| #include "common/debug.h" |
| #include "libANGLE/renderer/d3d/d3d9/Context9.h" |
| |
| #include <cstddef> |
| #include <mutex> |
| #include <string> |
| #include <unordered_map> |
| |
| namespace rx |
| { |
| template <typename ShaderObject> |
| class ShaderCache : angle::NonCopyable |
| { |
| public: |
| ShaderCache() : mDevice(nullptr) {} |
| |
| ~ShaderCache() |
| { |
| // Call clear while the device is still valid. |
| ASSERT(mMap.empty()); |
| } |
| |
| void initialize(IDirect3DDevice9 *device) { mDevice = device; } |
| |
| angle::Result create(d3d::Context *context, |
| const DWORD *function, |
| size_t length, |
| ShaderObject **outShaderObject) |
| { |
| std::lock_guard<std::mutex> lock(mMutex); |
| |
| std::string key(reinterpret_cast<const char *>(function), length); |
| typename Map::iterator it = mMap.find(key); |
| if (it != mMap.end()) |
| { |
| it->second->AddRef(); |
| *outShaderObject = it->second; |
| return angle::Result::Continue; |
| } |
| |
| ShaderObject *shader; |
| HRESULT result = createShader(function, &shader); |
| ANGLE_TRY_HR(context, result, "Failed to create shader"); |
| |
| // Random eviction policy. |
| if (mMap.size() >= kMaxMapSize) |
| { |
| SafeRelease(mMap.begin()->second); |
| mMap.erase(mMap.begin()); |
| } |
| |
| shader->AddRef(); |
| mMap[key] = shader; |
| |
| *outShaderObject = shader; |
| return angle::Result::Continue; |
| } |
| |
| void clear() |
| { |
| std::lock_guard<std::mutex> lock(mMutex); |
| |
| for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it) |
| { |
| SafeRelease(it->second); |
| } |
| |
| mMap.clear(); |
| } |
| |
| private: |
| const static size_t kMaxMapSize = 100; |
| |
| HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader) |
| { |
| return mDevice->CreateVertexShader(function, shader); |
| } |
| |
| HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader) |
| { |
| return mDevice->CreatePixelShader(function, shader); |
| } |
| |
| typedef std::unordered_map<std::string, ShaderObject *> Map; |
| Map mMap; |
| std::mutex mMutex; |
| |
| IDirect3DDevice9 *mDevice; |
| }; |
| |
| typedef ShaderCache<IDirect3DVertexShader9> VertexShaderCache; |
| typedef ShaderCache<IDirect3DPixelShader9> PixelShaderCache; |
| |
| } // namespace rx |
| |
| #endif // LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_ |