gfx/angle/src/libGLESv2/renderer/RenderStateCache.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 #include "precompiled.h"
michael@0 2 //
michael@0 3 // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
michael@0 4 // Use of this source code is governed by a BSD-style license that can be
michael@0 5 // found in the LICENSE file.
michael@0 6 //
michael@0 7
michael@0 8 // RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render
michael@0 9 // state objects.
michael@0 10
michael@0 11 #include "libGLESv2/renderer/RenderStateCache.h"
michael@0 12 #include "libGLESv2/renderer/renderer11_utils.h"
michael@0 13
michael@0 14 #include "common/debug.h"
michael@0 15 #include "third_party/murmurhash/MurmurHash3.h"
michael@0 16
michael@0 17 namespace rx
michael@0 18 {
michael@0 19
michael@0 20 // MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState,
michael@0 21 // ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum
michael@0 22 // number of unique states of each type an application can create is 4096
michael@0 23 const unsigned int RenderStateCache::kMaxBlendStates = 4096;
michael@0 24 const unsigned int RenderStateCache::kMaxRasterizerStates = 4096;
michael@0 25 const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096;
michael@0 26 const unsigned int RenderStateCache::kMaxSamplerStates = 4096;
michael@0 27
michael@0 28 RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0),
michael@0 29 mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates),
michael@0 30 mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates),
michael@0 31 mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates),
michael@0 32 mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates)
michael@0 33 {
michael@0 34 }
michael@0 35
michael@0 36 RenderStateCache::~RenderStateCache()
michael@0 37 {
michael@0 38 clear();
michael@0 39 }
michael@0 40
michael@0 41 void RenderStateCache::initialize(ID3D11Device *device)
michael@0 42 {
michael@0 43 clear();
michael@0 44 mDevice = device;
michael@0 45 }
michael@0 46
michael@0 47 void RenderStateCache::clear()
michael@0 48 {
michael@0 49 for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++)
michael@0 50 {
michael@0 51 i->second.first->Release();
michael@0 52 }
michael@0 53 mBlendStateCache.clear();
michael@0 54
michael@0 55 for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++)
michael@0 56 {
michael@0 57 i->second.first->Release();
michael@0 58 }
michael@0 59 mRasterizerStateCache.clear();
michael@0 60
michael@0 61 for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
michael@0 62 {
michael@0 63 i->second.first->Release();
michael@0 64 }
michael@0 65 mDepthStencilStateCache.clear();
michael@0 66
michael@0 67 for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++)
michael@0 68 {
michael@0 69 i->second.first->Release();
michael@0 70 }
michael@0 71 mSamplerStateCache.clear();
michael@0 72 }
michael@0 73
michael@0 74 std::size_t RenderStateCache::hashBlendState(const gl::BlendState &blendState)
michael@0 75 {
michael@0 76 static const unsigned int seed = 0xABCDEF98;
michael@0 77
michael@0 78 std::size_t hash = 0;
michael@0 79 MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash);
michael@0 80 return hash;
michael@0 81 }
michael@0 82
michael@0 83 bool RenderStateCache::compareBlendStates(const gl::BlendState &a, const gl::BlendState &b)
michael@0 84 {
michael@0 85 return memcmp(&a, &b, sizeof(gl::BlendState)) == 0;
michael@0 86 }
michael@0 87
michael@0 88 ID3D11BlendState *RenderStateCache::getBlendState(const gl::BlendState &blendState)
michael@0 89 {
michael@0 90 if (!mDevice)
michael@0 91 {
michael@0 92 ERR("RenderStateCache is not initialized.");
michael@0 93 return NULL;
michael@0 94 }
michael@0 95
michael@0 96 BlendStateMap::iterator i = mBlendStateCache.find(blendState);
michael@0 97 if (i != mBlendStateCache.end())
michael@0 98 {
michael@0 99 BlendStateCounterPair &state = i->second;
michael@0 100 state.second = mCounter++;
michael@0 101 return state.first;
michael@0 102 }
michael@0 103 else
michael@0 104 {
michael@0 105 if (mBlendStateCache.size() >= kMaxBlendStates)
michael@0 106 {
michael@0 107 TRACE("Overflowed the limit of %u blend states, removing the least recently used "
michael@0 108 "to make room.", kMaxBlendStates);
michael@0 109
michael@0 110 BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin();
michael@0 111 for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++)
michael@0 112 {
michael@0 113 if (i->second.second < leastRecentlyUsed->second.second)
michael@0 114 {
michael@0 115 leastRecentlyUsed = i;
michael@0 116 }
michael@0 117 }
michael@0 118 leastRecentlyUsed->second.first->Release();
michael@0 119 mBlendStateCache.erase(leastRecentlyUsed);
michael@0 120 }
michael@0 121
michael@0 122 // Create a new blend state and insert it into the cache
michael@0 123 D3D11_BLEND_DESC blendDesc = { 0 };
michael@0 124 blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage;
michael@0 125 blendDesc.IndependentBlendEnable = FALSE;
michael@0 126
michael@0 127 for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
michael@0 128 {
michael@0 129 D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i];
michael@0 130
michael@0 131 rtBlend.BlendEnable = blendState.blend;
michael@0 132 if (blendState.blend)
michael@0 133 {
michael@0 134 rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false);
michael@0 135 rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false);
michael@0 136 rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB);
michael@0 137
michael@0 138 rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true);
michael@0 139 rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true);
michael@0 140 rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha);
michael@0 141 }
michael@0 142
michael@0 143 rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendState.colorMaskRed,
michael@0 144 blendState.colorMaskGreen,
michael@0 145 blendState.colorMaskBlue,
michael@0 146 blendState.colorMaskAlpha);
michael@0 147 }
michael@0 148
michael@0 149 ID3D11BlendState *dx11BlendState = NULL;
michael@0 150 HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState);
michael@0 151 if (FAILED(result) || !dx11BlendState)
michael@0 152 {
michael@0 153 ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
michael@0 154 return NULL;
michael@0 155 }
michael@0 156
michael@0 157 mBlendStateCache.insert(std::make_pair(blendState, std::make_pair(dx11BlendState, mCounter++)));
michael@0 158
michael@0 159 return dx11BlendState;
michael@0 160 }
michael@0 161 }
michael@0 162
michael@0 163 std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState)
michael@0 164 {
michael@0 165 static const unsigned int seed = 0xABCDEF98;
michael@0 166
michael@0 167 std::size_t hash = 0;
michael@0 168 MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash);
michael@0 169 return hash;
michael@0 170 }
michael@0 171
michael@0 172 bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b)
michael@0 173 {
michael@0 174 return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
michael@0 175 }
michael@0 176
michael@0 177 ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState,
michael@0 178 bool scissorEnabled, unsigned int depthSize)
michael@0 179 {
michael@0 180 if (!mDevice)
michael@0 181 {
michael@0 182 ERR("RenderStateCache is not initialized.");
michael@0 183 return NULL;
michael@0 184 }
michael@0 185
michael@0 186 RasterizerStateKey key;
michael@0 187 key.rasterizerState = rasterState;
michael@0 188 key.scissorEnabled = scissorEnabled;
michael@0 189 key.depthSize = depthSize;
michael@0 190
michael@0 191 RasterizerStateMap::iterator i = mRasterizerStateCache.find(key);
michael@0 192 if (i != mRasterizerStateCache.end())
michael@0 193 {
michael@0 194 RasterizerStateCounterPair &state = i->second;
michael@0 195 state.second = mCounter++;
michael@0 196 return state.first;
michael@0 197 }
michael@0 198 else
michael@0 199 {
michael@0 200 if (mRasterizerStateCache.size() >= kMaxRasterizerStates)
michael@0 201 {
michael@0 202 TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used "
michael@0 203 "to make room.", kMaxRasterizerStates);
michael@0 204
michael@0 205 RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin();
michael@0 206 for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++)
michael@0 207 {
michael@0 208 if (i->second.second < leastRecentlyUsed->second.second)
michael@0 209 {
michael@0 210 leastRecentlyUsed = i;
michael@0 211 }
michael@0 212 }
michael@0 213 leastRecentlyUsed->second.first->Release();
michael@0 214 mRasterizerStateCache.erase(leastRecentlyUsed);
michael@0 215 }
michael@0 216
michael@0 217 D3D11_CULL_MODE cullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode);
michael@0 218
michael@0 219 // Disable culling if drawing points
michael@0 220 if (rasterState.pointDrawMode)
michael@0 221 {
michael@0 222 cullMode = D3D11_CULL_NONE;
michael@0 223 }
michael@0 224
michael@0 225 D3D11_RASTERIZER_DESC rasterDesc;
michael@0 226 rasterDesc.FillMode = D3D11_FILL_SOLID;
michael@0 227 rasterDesc.CullMode = cullMode;
michael@0 228 rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE;
michael@0 229 rasterDesc.DepthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(depthSize));
michael@0 230 rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though.
michael@0 231 rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor;
michael@0 232 rasterDesc.DepthClipEnable = TRUE;
michael@0 233 rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE;
michael@0 234 rasterDesc.MultisampleEnable = rasterState.multiSample;
michael@0 235 rasterDesc.AntialiasedLineEnable = FALSE;
michael@0 236
michael@0 237 ID3D11RasterizerState *dx11RasterizerState = NULL;
michael@0 238 HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState);
michael@0 239 if (FAILED(result) || !dx11RasterizerState)
michael@0 240 {
michael@0 241 ERR("Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result);
michael@0 242 return NULL;
michael@0 243 }
michael@0 244
michael@0 245 mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++)));
michael@0 246
michael@0 247 return dx11RasterizerState;
michael@0 248 }
michael@0 249 }
michael@0 250
michael@0 251 std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState)
michael@0 252 {
michael@0 253 static const unsigned int seed = 0xABCDEF98;
michael@0 254
michael@0 255 std::size_t hash = 0;
michael@0 256 MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash);
michael@0 257 return hash;
michael@0 258 }
michael@0 259
michael@0 260 bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b)
michael@0 261 {
michael@0 262 return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0;
michael@0 263 }
michael@0 264
michael@0 265 ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState)
michael@0 266 {
michael@0 267 if (!mDevice)
michael@0 268 {
michael@0 269 ERR("RenderStateCache is not initialized.");
michael@0 270 return NULL;
michael@0 271 }
michael@0 272
michael@0 273 DepthStencilStateMap::iterator i = mDepthStencilStateCache.find(dsState);
michael@0 274 if (i != mDepthStencilStateCache.end())
michael@0 275 {
michael@0 276 DepthStencilStateCounterPair &state = i->second;
michael@0 277 state.second = mCounter++;
michael@0 278 return state.first;
michael@0 279 }
michael@0 280 else
michael@0 281 {
michael@0 282 if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates)
michael@0 283 {
michael@0 284 TRACE("Overflowed the limit of %u depth stencil states, removing the least recently used "
michael@0 285 "to make room.", kMaxDepthStencilStates);
michael@0 286
michael@0 287 DepthStencilStateMap::iterator leastRecentlyUsed = mDepthStencilStateCache.begin();
michael@0 288 for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
michael@0 289 {
michael@0 290 if (i->second.second < leastRecentlyUsed->second.second)
michael@0 291 {
michael@0 292 leastRecentlyUsed = i;
michael@0 293 }
michael@0 294 }
michael@0 295 leastRecentlyUsed->second.first->Release();
michael@0 296 mDepthStencilStateCache.erase(leastRecentlyUsed);
michael@0 297 }
michael@0 298
michael@0 299 D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 };
michael@0 300 dsDesc.DepthEnable = dsState.depthTest ? TRUE : FALSE;
michael@0 301 dsDesc.DepthWriteMask = gl_d3d11::ConvertDepthMask(dsState.depthMask);
michael@0 302 dsDesc.DepthFunc = gl_d3d11::ConvertComparison(dsState.depthFunc);
michael@0 303 dsDesc.StencilEnable = dsState.stencilTest ? TRUE : FALSE;
michael@0 304 dsDesc.StencilReadMask = gl_d3d11::ConvertStencilMask(dsState.stencilMask);
michael@0 305 dsDesc.StencilWriteMask = gl_d3d11::ConvertStencilMask(dsState.stencilWritemask);
michael@0 306 dsDesc.FrontFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilFail);
michael@0 307 dsDesc.FrontFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthFail);
michael@0 308 dsDesc.FrontFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthPass);
michael@0 309 dsDesc.FrontFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilFunc);
michael@0 310 dsDesc.BackFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackFail);
michael@0 311 dsDesc.BackFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthFail);
michael@0 312 dsDesc.BackFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthPass);
michael@0 313 dsDesc.BackFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilBackFunc);
michael@0 314
michael@0 315 ID3D11DepthStencilState *dx11DepthStencilState = NULL;
michael@0 316 HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState);
michael@0 317 if (FAILED(result) || !dx11DepthStencilState)
michael@0 318 {
michael@0 319 ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
michael@0 320 return NULL;
michael@0 321 }
michael@0 322
michael@0 323 mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++)));
michael@0 324
michael@0 325 return dx11DepthStencilState;
michael@0 326 }
michael@0 327 }
michael@0 328
michael@0 329 std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState)
michael@0 330 {
michael@0 331 static const unsigned int seed = 0xABCDEF98;
michael@0 332
michael@0 333 std::size_t hash = 0;
michael@0 334 MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash);
michael@0 335 return hash;
michael@0 336 }
michael@0 337
michael@0 338 bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b)
michael@0 339 {
michael@0 340 return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0;
michael@0 341 }
michael@0 342
michael@0 343 ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &samplerState)
michael@0 344 {
michael@0 345 if (!mDevice)
michael@0 346 {
michael@0 347 ERR("RenderStateCache is not initialized.");
michael@0 348 return NULL;
michael@0 349 }
michael@0 350
michael@0 351 SamplerStateMap::iterator i = mSamplerStateCache.find(samplerState);
michael@0 352 if (i != mSamplerStateCache.end())
michael@0 353 {
michael@0 354 SamplerStateCounterPair &state = i->second;
michael@0 355 state.second = mCounter++;
michael@0 356 return state.first;
michael@0 357 }
michael@0 358 else
michael@0 359 {
michael@0 360 if (mSamplerStateCache.size() >= kMaxSamplerStates)
michael@0 361 {
michael@0 362 TRACE("Overflowed the limit of %u sampler states, removing the least recently used "
michael@0 363 "to make room.", kMaxSamplerStates);
michael@0 364
michael@0 365 SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin();
michael@0 366 for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++)
michael@0 367 {
michael@0 368 if (i->second.second < leastRecentlyUsed->second.second)
michael@0 369 {
michael@0 370 leastRecentlyUsed = i;
michael@0 371 }
michael@0 372 }
michael@0 373 leastRecentlyUsed->second.first->Release();
michael@0 374 mSamplerStateCache.erase(leastRecentlyUsed);
michael@0 375 }
michael@0 376
michael@0 377 D3D11_SAMPLER_DESC samplerDesc;
michael@0 378 samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, samplerState.maxAnisotropy);
michael@0 379 samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS);
michael@0 380 samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT);
michael@0 381 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
michael@0 382 samplerDesc.MipLODBias = static_cast<float>(samplerState.lodOffset);
michael@0 383 samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy;
michael@0 384 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
michael@0 385 samplerDesc.BorderColor[0] = 0.0f;
michael@0 386 samplerDesc.BorderColor[1] = 0.0f;
michael@0 387 samplerDesc.BorderColor[2] = 0.0f;
michael@0 388 samplerDesc.BorderColor[3] = 0.0f;
michael@0 389 samplerDesc.MinLOD = gl_d3d11::ConvertMinLOD(samplerState.minFilter, samplerState.lodOffset);
michael@0 390 samplerDesc.MaxLOD = gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset);
michael@0 391
michael@0 392 ID3D11SamplerState *dx11SamplerState = NULL;
michael@0 393 HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState);
michael@0 394 if (FAILED(result) || !dx11SamplerState)
michael@0 395 {
michael@0 396 ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
michael@0 397 return NULL;
michael@0 398 }
michael@0 399
michael@0 400 mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++)));
michael@0 401
michael@0 402 return dx11SamplerState;
michael@0 403 }
michael@0 404 }
michael@0 405
michael@0 406 }

mercurial