gfxD3D11StateBlock.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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 = false;
  55. mBlendDesc.RenderTarget[0].BlendEnable = mDesc.blendEnable;
  56. //color
  57. mBlendDesc.RenderTarget[0].BlendOp = GFXD3D11BlendOp[mDesc.blendOp];
  58. mBlendDesc.RenderTarget[0].DestBlend = GFXD3D11Blend[mDesc.blendDest];
  59. mBlendDesc.RenderTarget[0].SrcBlend = GFXD3D11Blend[mDesc.blendSrc];
  60. //alpha
  61. if (mDesc.separateAlphaBlendEnable)
  62. {
  63. mBlendDesc.RenderTarget[0].BlendOpAlpha = GFXD3D11BlendOp[mDesc.separateAlphaBlendOp];
  64. mBlendDesc.RenderTarget[0].SrcBlendAlpha = GFXD3D11Blend[mDesc.separateAlphaBlendSrc];
  65. mBlendDesc.RenderTarget[0].DestBlendAlpha = GFXD3D11Blend[mDesc.separateAlphaBlendDest];
  66. }
  67. else
  68. {
  69. mBlendDesc.RenderTarget[0].BlendOpAlpha = mBlendDesc.RenderTarget[0].BlendOp;
  70. mBlendDesc.RenderTarget[0].SrcBlendAlpha = GFXD3D11BlendAlpha[mDesc.blendSrc];
  71. mBlendDesc.RenderTarget[0].DestBlendAlpha = GFXD3D11BlendAlpha[mDesc.blendDest];
  72. }
  73. //target write mask
  74. mBlendDesc.RenderTarget[0].RenderTargetWriteMask = mColorMask;
  75. HRESULT hr = D3D11DEVICE->CreateBlendState(&mBlendDesc, &mBlendState);
  76. if (FAILED(hr))
  77. {
  78. AssertFatal(false, avar("GFXD3D11StateBlock::GFXD3D11StateBlock - CreateBlendState call failure: %s.", GFX->interpretDebugResult(hr)));
  79. }
  80. ZeroMemory(&mDepthStencilDesc, sizeof(D3D11_DEPTH_STENCIL_DESC));
  81. mDepthStencilDesc.DepthWriteMask = mDesc.zWriteEnable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
  82. mDepthStencilDesc.DepthEnable = mDesc.zEnable;
  83. mDepthStencilDesc.DepthFunc = GFXD3D11CmpFunc[mDesc.zFunc];
  84. mDepthStencilDesc.StencilWriteMask = mDesc.stencilWriteMask;
  85. mDepthStencilDesc.StencilReadMask = mDesc.stencilMask;
  86. mDepthStencilDesc.StencilEnable = mDesc.stencilEnable;
  87. mDepthStencilDesc.FrontFace.StencilFunc = GFXD3D11CmpFunc[mDesc.stencilFunc];
  88. mDepthStencilDesc.FrontFace.StencilFailOp = GFXD3D11StencilOp[mDesc.stencilFailOp];
  89. mDepthStencilDesc.FrontFace.StencilDepthFailOp = GFXD3D11StencilOp[mDesc.stencilZFailOp];
  90. mDepthStencilDesc.FrontFace.StencilPassOp = GFXD3D11StencilOp[mDesc.stencilPassOp];
  91. if (mDesc.stencilEnable)
  92. mDepthStencilDesc.BackFace = mDepthStencilDesc.FrontFace;
  93. else
  94. {
  95. mDepthStencilDesc.BackFace.StencilFunc = GFXD3D11CmpFunc[GFXCmpAlways];
  96. mDepthStencilDesc.BackFace.StencilFailOp = GFXD3D11StencilOp[GFXStencilOpKeep];
  97. mDepthStencilDesc.BackFace.StencilDepthFailOp = GFXD3D11StencilOp[GFXStencilOpKeep];
  98. mDepthStencilDesc.BackFace.StencilPassOp = GFXD3D11StencilOp[GFXStencilOpKeep];
  99. }
  100. hr = D3D11DEVICE->CreateDepthStencilState(&mDepthStencilDesc, &mDepthStencilState);
  101. if (FAILED(hr))
  102. {
  103. AssertFatal(false, "GFXD3D11StateBlock::GFXD3D11StateBlock - CreateDepthStencilState call failure.");
  104. }
  105. ZeroMemory(&mRasterizerDesc, sizeof(D3D11_RASTERIZER_DESC));
  106. mRasterizerDesc.CullMode = GFXD3D11CullMode[mDesc.cullMode];
  107. mRasterizerDesc.FillMode = GFXD3D11FillMode[mDesc.fillMode];
  108. //this assumes 24bit depth
  109. const INT depthMul = INT((1 << 24) - 1);
  110. mRasterizerDesc.DepthBias = mDesc.zBias * depthMul;
  111. mRasterizerDesc.SlopeScaledDepthBias = mDesc.zSlopeBias;
  112. mRasterizerDesc.AntialiasedLineEnable = FALSE;
  113. mRasterizerDesc.MultisampleEnable = FALSE;
  114. mRasterizerDesc.ScissorEnable = FALSE;
  115. mRasterizerDesc.FrontCounterClockwise = FALSE;
  116. mRasterizerDesc.DepthBiasClamp = D3D11_DEFAULT_DEPTH_BIAS_CLAMP;
  117. if (mDesc.zEnable)
  118. mRasterizerDesc.DepthClipEnable = true;
  119. else
  120. mRasterizerDesc.DepthClipEnable = false;
  121. hr = D3D11DEVICE->CreateRasterizerState(&mRasterizerDesc, &mRasterizerState);
  122. if (FAILED(hr))
  123. {
  124. AssertFatal(false, "GFXD3D11StateBlock::GFXD3D11StateBlock - CreateDepthStencilState call failure.");
  125. }
  126. ZeroMemory(&mSamplerDesc, sizeof(D3D11_SAMPLER_DESC) * 16);
  127. GFXD3D11Device::SamplerMap &dx11SamplerMap = D3D11->getSamplersMap();
  128. for (U32 i = 0; i < GFX->getNumSamplers(); i++)
  129. {
  130. GFXSamplerStateDesc &gfxSamplerState = mDesc.samplers[i];
  131. U32 hash = DictHash::hash(gfxSamplerState);
  132. GFXD3D11Device::SamplerMap::Iterator itr = dx11SamplerMap.find(hash);
  133. if (itr == dx11SamplerMap.end())
  134. {
  135. mSamplerDesc[i].AddressU = GFXD3D11TextureAddress[gfxSamplerState.addressModeU];
  136. mSamplerDesc[i].AddressV = GFXD3D11TextureAddress[gfxSamplerState.addressModeV];
  137. mSamplerDesc[i].AddressW = GFXD3D11TextureAddress[gfxSamplerState.addressModeW];
  138. mSamplerDesc[i].MaxAnisotropy = gfxSamplerState.maxAnisotropy;
  139. mSamplerDesc[i].MipLODBias = gfxSamplerState.mipLODBias;
  140. mSamplerDesc[i].MinLOD = 0;
  141. mSamplerDesc[i].MaxLOD = FLT_MAX;
  142. const bool comparison = gfxSamplerState.samplerFunc != GFXCmpNever;
  143. if (gfxSamplerState.magFilter == GFXTextureFilterPoint && gfxSamplerState.minFilter == GFXTextureFilterPoint && gfxSamplerState.mipFilter == GFXTextureFilterPoint)
  144. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_MIP_POINT;
  145. else if (gfxSamplerState.magFilter == GFXTextureFilterPoint && gfxSamplerState.minFilter == GFXTextureFilterPoint && gfxSamplerState.mipFilter == GFXTextureFilterLinear)
  146. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR : D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
  147. else if (gfxSamplerState.magFilter == GFXTextureFilterLinear && gfxSamplerState.minFilter == GFXTextureFilterPoint && gfxSamplerState.mipFilter == GFXTextureFilterPoint)
  148. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT : D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
  149. else if (gfxSamplerState.magFilter == GFXTextureFilterLinear && gfxSamplerState.minFilter == GFXTextureFilterPoint && gfxSamplerState.mipFilter == GFXTextureFilterLinear)
  150. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR : D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
  151. else if (gfxSamplerState.magFilter == GFXTextureFilterPoint && gfxSamplerState.minFilter == GFXTextureFilterLinear && gfxSamplerState.mipFilter == GFXTextureFilterPoint)
  152. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT : D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
  153. else if (gfxSamplerState.magFilter == GFXTextureFilterPoint && gfxSamplerState.minFilter == GFXTextureFilterLinear && gfxSamplerState.mipFilter == GFXTextureFilterLinear)
  154. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR : D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
  155. else if (gfxSamplerState.magFilter == GFXTextureFilterLinear && gfxSamplerState.minFilter == GFXTextureFilterLinear && gfxSamplerState.mipFilter == GFXTextureFilterPoint)
  156. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT : D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
  157. else if (gfxSamplerState.magFilter == GFXTextureFilterLinear && gfxSamplerState.minFilter == GFXTextureFilterLinear && mDesc.samplers[i].mipFilter == GFXTextureFilterLinear)
  158. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
  159. else
  160. mSamplerDesc[i].Filter = comparison ? D3D11_FILTER_COMPARISON_ANISOTROPIC : D3D11_FILTER_ANISOTROPIC;
  161. mSamplerDesc[i].BorderColor[0] = 1.0f;
  162. mSamplerDesc[i].BorderColor[1] = 1.0f;
  163. mSamplerDesc[i].BorderColor[2] = 1.0f;
  164. mSamplerDesc[i].BorderColor[3] = 1.0f;
  165. mSamplerDesc[i].ComparisonFunc = GFXD3D11CmpFunc[gfxSamplerState.samplerFunc];
  166. hr = D3D11DEVICE->CreateSamplerState(&mSamplerDesc[i], &mSamplerStates[i]);
  167. if (FAILED(hr))
  168. {
  169. AssertFatal(false, "GFXD3D11StateBlock::GFXD3D11StateBlock - CreateSamplerState call failure.");
  170. }
  171. // add sampler state to the map
  172. dx11SamplerMap.insert(hash, mSamplerStates[i]);
  173. }
  174. else
  175. {
  176. mSamplerStates[i] = itr->value;
  177. }
  178. }
  179. }
  180. GFXD3D11StateBlock::~GFXD3D11StateBlock()
  181. {
  182. SAFE_RELEASE(mBlendState);
  183. SAFE_RELEASE(mRasterizerState);
  184. SAFE_RELEASE(mDepthStencilState);
  185. for (U32 i = 0; i < 16; ++i)
  186. {
  187. mSamplerStates[i] = NULL;
  188. }
  189. }
  190. /// Returns the hash value of the desc that created this block
  191. U32 GFXD3D11StateBlock::getHashValue() const
  192. {
  193. return mCachedHashValue;
  194. }
  195. /// Returns a GFXStateBlockDesc that this block represents
  196. const GFXStateBlockDesc& GFXD3D11StateBlock::getDesc() const
  197. {
  198. return mDesc;
  199. }
  200. /// Called by D3D11 device to active this state block.
  201. /// @param oldState The current state, used to make sure we don't set redundant states on the device. Pass NULL to reset all states.
  202. void GFXD3D11StateBlock::activate(GFXD3D11StateBlock* oldState)
  203. {
  204. PROFILE_SCOPE(GFXD3D11StateBlock_Activate);
  205. if (!oldState || (mBlendState != oldState->mBlendState))
  206. {
  207. F32 blendFactor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  208. D3D11DEVICECONTEXT->OMSetBlendState(mBlendState, blendFactor, 0xFFFFFFFF);
  209. }
  210. if (!oldState || (mDepthStencilState != oldState->mDepthStencilState))
  211. D3D11DEVICECONTEXT->OMSetDepthStencilState(mDepthStencilState, mDesc.stencilRef);
  212. if (!oldState || (mRasterizerState != oldState->mRasterizerState))
  213. D3D11DEVICECONTEXT->RSSetState(mRasterizerState);
  214. U32 numSamplersChanged = 0;
  215. U32 numSamplers = GFX->getNumSamplers();
  216. U32 samplerUpdateStartSlot = 0;
  217. //figure out which range of samplers changed.
  218. for (U32 samplerSlot = 0; samplerSlot < numSamplers; samplerSlot++)
  219. {
  220. if (oldState && (oldState->mSamplerStates[samplerSlot] == mSamplerStates[samplerSlot]))
  221. {
  222. //only change the update start slot when there hasn't been any samplers changed so far
  223. if (numSamplersChanged == 0) {
  224. samplerUpdateStartSlot++;
  225. }
  226. continue;
  227. }
  228. numSamplersChanged = (samplerSlot - samplerUpdateStartSlot) + 1;
  229. }
  230. //TODO samplers for vertex shader
  231. // Set all the samplers with one call
  232. //D3D11DEVICECONTEXT->VSSetSamplers(0, numSamplers, &mSamplerStates[0]);
  233. if (numSamplersChanged > 0)
  234. D3D11DEVICECONTEXT->PSSetSamplers(samplerUpdateStartSlot, numSamplersChanged, &mSamplerStates[samplerUpdateStartSlot]);
  235. }