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
parent fa34b340
......@@ -17,7 +17,8 @@ namespace rx
{
RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0),
mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates)
mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates),
mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates)
{
}
......@@ -39,6 +40,12 @@ void RenderStateCache::clear()
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 @@ ID3D11BlendState *RenderStateCache::getBlendState(const gl::BlendState &blendSta
}
}
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
......@@ -30,6 +30,8 @@ class RenderStateCache
// Increments refcount on the returned blend state, Release() must be called.
ID3D11BlendState *getBlendState(const gl::BlendState &blendState);
ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState,
unsigned int depthSize);
private:
DISALLOW_COPY_AND_ASSIGN(RenderStateCache);
......@@ -47,6 +49,22 @@ class RenderStateCache
typedef std::unordered_map<gl::BlendState, BlendStateCounterPair, BlendStateHashFunction, BlendStateEqualityFunction> BlendStateMap;
BlendStateMap mBlendStateCache;
// Rasterizer state cache
struct RasterizerStateKey
{
gl::RasterizerState rasterizerState;
unsigned int depthSize;
};
static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState);
static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b);
static const unsigned int kMaxRasterizerStates;
typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &);
typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &);
typedef std::pair<ID3D11RasterizerState*, unsigned long long> RasterizerStateCounterPair;
typedef std::unordered_map<RasterizerStateKey, RasterizerStateCounterPair, RasterizerStateHashFunction, RasterizerStateEqualityFunction> RasterizerStateMap;
RasterizerStateMap mRasterizerStateCache;
ID3D11Device* mDevice;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment