blob: bd46886d682f1de0315425338d41011ba874671c [file] [log] [blame]
daniel@transgaming.com0673d792012-11-28 19:37:44 +00001//
2// Copyright (c) 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// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render
8// state objects.
9
10#include "libGLESv2/renderer/RenderStateCache.h"
11#include "libGLESv2/renderer/renderer11_utils.h"
12
13#include "common/debug.h"
14#include "third_party/murmurhash/MurmurHash3.h"
15
16namespace rx
17{
18
19RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0),
20 mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates)
21{
22}
23
24RenderStateCache::~RenderStateCache()
25{
26 clear();
27}
28
29void RenderStateCache::initialize(ID3D11Device* device)
30{
31 clear();
32 mDevice = device;
33}
34
35void RenderStateCache::clear()
36{
37 for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++)
38 {
39 i->second.first->Release();
40 }
41 mBlendStateCache.clear();
42}
43
44std::size_t RenderStateCache::hashBlendState(const gl::BlendState &blendState)
45{
46 static const unsigned int seed = 0xABCDEF98;
47
48 std::size_t hash = 0;
49 MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash);
50 return hash;
51}
52
53bool RenderStateCache::compareBlendStates(const gl::BlendState &a, const gl::BlendState &b)
54{
55 return memcmp(&a, &b, sizeof(gl::BlendState)) == 0;
56}
57
58// MSDN's documentation of ID3D11Device::CreateBlendState claims the maximum number of
59// unique blend states an application can create is 4096
60const unsigned int RenderStateCache::kMaxBlendStates = 4096;
61
62ID3D11BlendState *RenderStateCache::getBlendState(const gl::BlendState &blendState)
63{
64 if (!mDevice)
65 {
66 ERR("RenderStateCache is not initialized.");
67 return NULL;
68 }
69
70 BlendStateMap::iterator i = mBlendStateCache.find(blendState);
71 if (i != mBlendStateCache.end())
72 {
73 BlendStateCounterPair &state = i->second;
74 state.first->AddRef();
75 state.second = mCounter++;
76 return state.first;
77 }
78 else
79 {
80 if (mBlendStateCache.size() >= kMaxBlendStates)
81 {
82 TRACE("Overflowed the limit of %u blend states, removing the least recently used "
83 "to make room.", kMaxBlendStates);
84
85 BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin();
86 for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++)
87 {
88 if (i->second.second < leastRecentlyUsed->second.second)
89 {
90 leastRecentlyUsed = i;
91 }
92 }
93 leastRecentlyUsed->second.first->Release();
94 mBlendStateCache.erase(leastRecentlyUsed);
95 }
96
97 // Create a new blend state and insert it into the cache
98 D3D11_BLEND_DESC blendDesc = { 0 };
99 blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage;
100 blendDesc.IndependentBlendEnable = FALSE;
101
102 for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
103 {
104 D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i];
105
106 rtBlend.BlendEnable = blendState.blend;
107 if (blendState.blend)
108 {
109 rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB);
110 rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB);
111 rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB);
112
113 rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha);
114 rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha);
115 rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha);
116
117 rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendState.colorMaskRed,
118 blendState.colorMaskGreen,
119 blendState.colorMaskBlue,
120 blendState.colorMaskAlpha);
121 }
122 }
123
124 ID3D11BlendState* dx11BlendState = NULL;
125 HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState);
126 if (FAILED(result) || !dx11BlendState)
127 {
128 ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
129 return NULL;
130 }
131
132 mBlendStateCache.insert(std::make_pair(blendState, std::make_pair(dx11BlendState, mCounter++)));
133
134 dx11BlendState->AddRef();
135 return dx11BlendState;
136 }
137}
138
139}