Added Rasterizer state caching to the RenderStateCache.
TRAC #22043
Signed-off-by: Shannon Woods
Signed-off-by: Daniel Koch
Author: Geoff Lang
git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1435 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/RenderStateCache.cpp b/src/libGLESv2/renderer/RenderStateCache.cpp
index bd46886..170b5cf 100644
--- a/src/libGLESv2/renderer/RenderStateCache.cpp
+++ b/src/libGLESv2/renderer/RenderStateCache.cpp
@@ -17,7 +17,8 @@
{
RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0),
- mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates)
+ mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates),
+ mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates)
{
}
@@ -39,6 +40,12 @@
i->second.first->Release();
}
mBlendStateCache.clear();
+
+ for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++)
+ {
+ i->second.first->Release();
+ }
+ mRasterizerStateCache.clear();
}
std::size_t RenderStateCache::hashBlendState(const gl::BlendState &blendState)
@@ -136,4 +143,89 @@
}
}
+std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState)
+{
+ static const unsigned int seed = 0xABCDEF98;
+
+ std::size_t hash = 0;
+ MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash);
+ return hash;
+}
+
+bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b)
+{
+ return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
+}
+
+// MSDN's documentation of ID3D11Device::CreateRasterizerState claims the maximum number of
+// unique rasterizer states an application can create is 4096
+const unsigned int RenderStateCache::kMaxRasterizerStates = 4096;
+
+ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState,
+ unsigned int depthSize)
+{
+ if (!mDevice)
+ {
+ ERR("RenderStateCache is not initialized.");
+ return NULL;
+ }
+
+ RasterizerStateKey key;
+ key.rasterizerState = rasterState;
+ key.depthSize = depthSize;
+
+ RasterizerStateMap::iterator i = mRasterizerStateCache.find(key);
+ if (i != mRasterizerStateCache.end())
+ {
+ RasterizerStateCounterPair &state = i->second;
+ state.first->AddRef();
+ state.second = mCounter++;
+ return state.first;
+ }
+ else
+ {
+ if (mRasterizerStateCache.size() >= kMaxRasterizerStates)
+ {
+ TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used "
+ "to make room.", kMaxRasterizerStates);
+
+ RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin();
+ for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++)
+ {
+ if (i->second.second < leastRecentlyUsed->second.second)
+ {
+ leastRecentlyUsed = i;
+ }
+ }
+ leastRecentlyUsed->second.first->Release();
+ mRasterizerStateCache.erase(leastRecentlyUsed);
+ }
+
+ D3D11_RASTERIZER_DESC rasterDesc;
+ rasterDesc.FillMode = D3D11_FILL_SOLID;
+ rasterDesc.CullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode);
+ rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? TRUE : FALSE;
+ rasterDesc.DepthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(depthSize));
+ rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though.
+ rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetUnits;
+ rasterDesc.DepthClipEnable = TRUE;
+ rasterDesc.ScissorEnable = rasterState.scissorTest ? TRUE : FALSE;
+ rasterDesc.MultisampleEnable = TRUE;
+ rasterDesc.AntialiasedLineEnable = FALSE;
+
+ ID3D11RasterizerState* dx11RasterizerState = NULL;
+ HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState);
+ if (FAILED(result) || !dx11RasterizerState)
+ {
+ ERR("Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result);
+ return NULL;
+ }
+
+ mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++)));
+
+ dx11RasterizerState->AddRef();
+ return dx11RasterizerState;
+ }
+}
+
}
\ No newline at end of file