gfxD3D11StateBlock.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2015 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "gfx/gfxDevice.h"
  23. #include "gfx/D3D11/gfxD3D11StateBlock.h"
  24. #include "gfx/D3D11/gfxD3D11EnumTranslate.h"
  25. #include "core/crc.h"
  26. namespace DictHash
  27. {
  28. inline U32 hash(const GFXSamplerStateDesc &data)
  29. {
  30. return CRC::calculateCRC(&data, sizeof(GFXSamplerStateDesc));;
  31. }
  32. }
  33. GFXD3D11StateBlock::GFXD3D11StateBlock(const GFXStateBlockDesc& desc)
  34. {
  35. AssertFatal(D3D11DEVICE, "Invalid D3DDevice!");
  36. PROFILE_SCOPE(GFXD3D11StateBlock_CreateStateBlock);
  37. mDesc = desc;
  38. mCachedHashValue = desc.getHashValue();
  39. // Color writes
  40. mColorMask = 0;
  41. mColorMask |= (mDesc.colorWriteRed ? D3D11_COLOR_WRITE_ENABLE_RED : 0);
  42. mColorMask |= (mDesc.colorWriteGreen ? D3D11_COLOR_WRITE_ENABLE_GREEN : 0);
  43. mColorMask |= (mDesc.colorWriteBlue ? D3D11_COLOR_WRITE_ENABLE_BLUE : 0);
  44. mColorMask |= (mDesc.colorWriteAlpha ? D3D11_COLOR_WRITE_ENABLE_ALPHA : 0);
  45. mBlendState = NULL;
  46. for (U32 i = 0; i < 16; i++)
  47. {
  48. mSamplerStates[i] = NULL;
  49. }
  50. mDepthStencilState = NULL;
  51. mRasterizerState = NULL;
  52. ZeroMemory(&mBlendDesc, sizeof(D3D11_BLEND_DESC));
  53. mBlendDesc.AlphaToCoverageEnable = false;
  54. mBlendDesc.IndependentBlendEnable = mDesc.separateAlphaBlendEnable;
  55. mBlendDesc.RenderTarget[0].BlendEnable = mDesc.blendEnable;
  56. mBlendDesc.RenderTarget[0].BlendOp = GFXD3D11BlendOp[mDesc.blendOp];
  57. mBlendDesc.RenderTarget[0].BlendOpAlpha = GFXD3D11BlendOp[mDesc.separateAlphaBlendOp];
  58. mBlendDesc.RenderTarget[0].DestBlend = GFXD3D11Blend[mDesc.blendDest];
  59. mBlendDesc.RenderTarget[0].DestBlendAlpha = GFXD3D11Blend[mDesc.separateAlphaBlendDest];
  60. mBlendDesc.RenderTarget[0].SrcBlend = GFXD3D11Blend[mDesc.blendSrc];
  61. mBlendDesc.RenderTarget[0].SrcBlendAlpha = GFXD3D11Blend[mDesc.separateAlphaBlendSrc];
  62. mBlendDesc.RenderTarget[0].RenderTargetWriteMask = mColorMask;
  63. HRESULT hr = D3D11DEVICE->CreateBlendState(&mBlendDesc, &mBlendState);
  64. if (FAILED(hr))
  65. {
  66. AssertFatal(false, "GFXD3D11StateBlock::GFXD3D11StateBlock - CreateBlendState call failure.");
  67. }
  68. ZeroMemory(&mDepthStencilDesc, sizeof(D3D11_DEPTH_STENCIL_DESC));
  69. mDepthStencilDesc.DepthWriteMask = mDesc.zWriteEnable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
  70. mDepthStencilDesc.DepthEnable = mDesc.zEnable;
  71. mDepthStencilDesc.DepthFunc = GFXD3D11CmpFunc[mDesc.zFunc];
  72. mDepthStencilDesc.StencilWriteMask = mDesc.stencilWriteMask;
  73. mDepthStencilDesc.StencilReadMask = mDesc.stencilMask;
  74. mDepthStencilDesc.StencilEnable = mDesc.stencilEnable;
  75. mDepthStencilDesc.FrontFace.StencilFunc = GFXD3D11CmpFunc[mDesc.stencilFunc];
  76. mDepthStencilDesc.FrontFace.StencilFailOp = GFXD3D11StencilOp[mDesc.stencilFailOp];
  77. mDepthStencilDesc.FrontFace.StencilDepthFailOp = GFXD3D11StencilOp[mDesc.stencilZFailOp];
  78. mDepthStencilDesc.FrontFace.StencilPassOp = GFXD3D11StencilOp[mDesc.stencilPassOp];
  79. if (mDesc.stencilEnable)
  80. mDepthStencilDesc.BackFace = mDepthStencilDesc.FrontFace;
  81. else
  82. {
  83. mDepthStencilDesc.BackFace.StencilFunc = GFXD3D11CmpFunc[GFXCmpAlways];
  84. mDepthStencilDesc.BackFace.StencilFailOp = GFXD3D11StencilOp[GFXStencilOpKeep];
  85. mDepthStencilDesc.BackFace.StencilDepthFailOp = GFXD3D11StencilOp[GFXStencilOpKeep];
  86. mDepthStencilDesc.BackFace.StencilPassOp = GFXD3D11StencilOp[GFXStencilOpKeep];
  87. }
  88. hr = D3D11DEVICE->CreateDepthStencilState(&mDepthStencilDesc, &mDepthStencilState);
  89. if (FAILED(hr))
  90. {
  91. AssertFatal(false, "GFXD3D11StateBlock::GFXD3D11StateBlock - CreateDepthStencilState call failure.");
  92. }
  93. ZeroMemory(&mRasterizerDesc, sizeof(D3D11_RASTERIZER_DESC));
  94. mRasterizerDesc.CullMode = GFXD3D11CullMode[mDesc.cullMode];
  95. mRasterizerDesc.FillMode = GFXD3D11FillMode[mDesc.fillMode];
  96. //this assumes 24bit depth
  97. const INT depthMul = INT((1 << 24) - 1);
  98. mRasterizerDesc.DepthBias = mDesc.zBias * depthMul;
  99. mRasterizerDesc.SlopeScaledDepthBias = mDesc.zSlopeBias;
  100. mRasterizerDesc.AntialiasedLineEnable = FALSE;
  101. mRasterizerDesc.MultisampleEnable = FALSE;
  102. mRasterizerDesc.ScissorEnable = FALSE;
  103. mRasterizerDesc.FrontCounterClockwise = FALSE;
  104. mRasterizerDesc.DepthBiasClamp = D3D11_DEFAULT_DEPTH_BIAS_CLAMP;
  105. if (mDesc.zEnable)
  106. mRasterizerDesc.DepthClipEnable = true;
  107. else
  108. mRasterizerDesc.DepthClipEnable = false;
  109. hr = D3D11DEVICE->CreateRasterizerState(&mRasterizerDesc, &mRasterizerState);
  110. if (FAILED(hr))
  111. {
  112. AssertFatal(false, "GFXD3D11StateBlock::GFXD3D11StateBlock - CreateDepthStencilState call failure.");
  113. }
  114. ZeroMemory(&mSamplerDesc, sizeof(D3D11_SAMPLER_DESC) * 16);
  115. GFXD3D11Device::SamplerMap &dx11SamplerMap = D3D11->getSamplersMap();
  116. for (U32 i = 0; i < GFX->getNumSamplers(); i++)
  117. {
  118. GFXSamplerStateDesc &gfxSamplerState = mDesc.samplers[i];
  119. U32 hash = DictHash::hash(gfxSamplerState);
  120. GFXD3D11Device::SamplerMap::Iterator itr = dx11SamplerMap.find(hash);
  121. if (itr == dx11SamplerMap.end())
  122. {
  123. mSamplerDesc[i].AddressU = GFXD3D11TextureAddress[gfxSamplerState.addressModeU];
  124. mSamplerDesc[i].AddressV = GFXD3D11TextureAddress[gfxSamplerState.addressModeV];
  125. mSamplerDesc[i].AddressW = GFXD3D11TextureAddress[gfxSamplerState.addressModeW];
  126. mSamplerDesc[i].MaxAnisotropy = gfxSamplerState.maxAnisotropy;
  127. mSamplerDesc[i].MipLODBias = gfxSamplerState.mipLODBias;
  128. mSamplerDesc[i].MinLOD = 0;
  129. mSamplerDesc[i].MaxLOD = FLT_MAX;
  130. const bool comparison = gfxSamplerState.samplerFunc != GFXCmpNever;
  131. if (gfxSamplerState.magFilter == GFXTextureFilterPoint && gfxSamplerState.minFilter == GFXTextureFilterPoint && gfxSamplerState.mipFilter == GFXTextureFilterPoint)
  132. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_POINT;
  133. else if (gfxSamplerState.magFilter == GFXTextureFilterPoint && gfxSamplerState.minFilter == GFXTextureFilterPoint && gfxSamplerState.mipFilter == GFXTextureFilterLinear)
  134. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR : D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
  135. else if (gfxSamplerState.magFilter == GFXTextureFilterLinear && gfxSamplerState.minFilter == GFXTextureFilterPoint && gfxSamplerState.mipFilter == GFXTextureFilterPoint)
  136. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT : D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
  137. else if (gfxSamplerState.magFilter == GFXTextureFilterLinear && gfxSamplerState.minFilter == GFXTextureFilterPoint && gfxSamplerState.mipFilter == GFXTextureFilterLinear)
  138. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR : D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
  139. else if (gfxSamplerState.magFilter == GFXTextureFilterPoint && gfxSamplerState.minFilter == GFXTextureFilterLinear && gfxSamplerState.mipFilter == GFXTextureFilterPoint)
  140. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT : D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
  141. else if (gfxSamplerState.magFilter == GFXTextureFilterPoint && gfxSamplerState.minFilter == GFXTextureFilterLinear && gfxSamplerState.mipFilter == GFXTextureFilterLinear)
  142. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR : D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
  143. else if (gfxSamplerState.magFilter == GFXTextureFilterLinear && gfxSamplerState.minFilter == GFXTextureFilterLinear && gfxSamplerState.mipFilter == GFXTextureFilterPoint)
  144. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT : D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
  145. else if (gfxSamplerState.magFilter == GFXTextureFilterLinear && gfxSamplerState.minFilter == GFXTextureFilterLinear && mDesc.samplers[i].mipFilter == GFXTextureFilterLinear)
  146. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
  147. else
  148. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_ANISOTROPIC : D3D11_FILTER_ANISOTROPIC;
  149. mSamplerDesc[i].BorderColor[0] = 1.0f;
  150. mSamplerDesc[i].BorderColor[1] = 1.0f;
  151. mSamplerDesc[i].BorderColor[2] = 1.0f;
  152. mSamplerDesc[i].BorderColor[3] = 1.0f;
  153. mSamplerDesc[i].ComparisonFunc = GFXD3D11CmpFunc[gfxSamplerState.samplerFunc];
  154. hr = D3D11DEVICE->CreateSamplerState(&mSamplerDesc[i], &mSamplerStates[i]);
  155. if (FAILED(hr))
  156. {
  157. AssertFatal(false, "GFXD3D11StateBlock::GFXD3D11StateBlock - CreateSamplerState call failure.");
  158. }
  159. // add sampler state to the map
  160. dx11SamplerMap.insert(hash, mSamplerStates[i]);
  161. }
  162. else
  163. {
  164. mSamplerStates[i] = itr->value;
  165. }
  166. }
  167. }
  168. GFXD3D11StateBlock::~GFXD3D11StateBlock()
  169. {
  170. SAFE_RELEASE(mBlendState);
  171. SAFE_RELEASE(mRasterizerState);
  172. SAFE_RELEASE(mDepthStencilState);
  173. for (U32 i = 0; i < 16; ++i)
  174. {
  175. mSamplerStates[i] = NULL;
  176. }
  177. }
  178. /// Returns the hash value of the desc that created this block
  179. U32 GFXD3D11StateBlock::getHashValue() const
  180. {
  181. return mCachedHashValue;
  182. }
  183. /// Returns a GFXStateBlockDesc that this block represents
  184. const GFXStateBlockDesc& GFXD3D11StateBlock::getDesc() const
  185. {
  186. return mDesc;
  187. }
  188. /// Called by D3D11 device to active this state block.
  189. /// @param oldState The current state, used to make sure we don't set redundant states on the device. Pass NULL to reset all states.
  190. void GFXD3D11StateBlock::activate(GFXD3D11StateBlock* oldState)
  191. {
  192. PROFILE_SCOPE(GFXD3D11StateBlock_Activate);
  193. if (!oldState || (mBlendState != oldState->mBlendState))
  194. {
  195. F32 blendFactor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  196. D3D11DEVICECONTEXT->OMSetBlendState(mBlendState, blendFactor, 0xFFFFFFFF);
  197. }
  198. if (!oldState || (mDepthStencilState != oldState->mDepthStencilState))
  199. D3D11DEVICECONTEXT->OMSetDepthStencilState(mDepthStencilState, mDesc.stencilRef);
  200. if (!oldState || (mRasterizerState != oldState->mRasterizerState))
  201. D3D11DEVICECONTEXT->RSSetState(mRasterizerState);
  202. U32 numSamplersChanged = 0;
  203. U32 numSamplers = GFX->getNumSamplers();
  204. U32 samplerUpdateStartSlot = 0;
  205. //figure out which range of samplers changed.
  206. for (U32 samplerSlot = 0; samplerSlot < numSamplers; samplerSlot++)
  207. {
  208. if (oldState && (oldState->mSamplerStates[samplerSlot] == mSamplerStates[samplerSlot]))
  209. {
  210. //only change the update start slot when there hasn't been any samplers changed so far
  211. if (numSamplersChanged == 0) {
  212. samplerUpdateStartSlot++;
  213. }
  214. continue;
  215. }
  216. numSamplersChanged = (samplerSlot - samplerUpdateStartSlot) + 1;
  217. }
  218. //TODO samplers for vertex shader
  219. // Set all the samplers with one call
  220. //D3D11DEVICECONTEXT->VSSetSamplers(0, numSamplers, &mSamplerStates[0]);
  221. if (numSamplersChanged > 0)
  222. D3D11DEVICECONTEXT->PSSetSamplers(samplerUpdateStartSlot, numSamplersChanged, &mSamplerStates[samplerUpdateStartSlot]);
  223. }