gfxD3D11StateBlock.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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. mRasterizerDesc.DepthBias = mDesc.zBias;
  97. mRasterizerDesc.SlopeScaledDepthBias = mDesc.zSlopeBias;
  98. mRasterizerDesc.AntialiasedLineEnable = FALSE;
  99. mRasterizerDesc.MultisampleEnable = FALSE;
  100. mRasterizerDesc.ScissorEnable = FALSE;
  101. mRasterizerDesc.FrontCounterClockwise = FALSE;
  102. mRasterizerDesc.DepthBiasClamp = D3D11_DEFAULT_DEPTH_BIAS_CLAMP;
  103. if (mDesc.zEnable)
  104. mRasterizerDesc.DepthClipEnable = true;
  105. else
  106. mRasterizerDesc.DepthClipEnable = false;
  107. hr = D3D11DEVICE->CreateRasterizerState(&mRasterizerDesc, &mRasterizerState);
  108. if (FAILED(hr))
  109. {
  110. AssertFatal(false, "GFXD3D11StateBlock::GFXD3D11StateBlock - CreateDepthStencilState call failure.");
  111. }
  112. ZeroMemory(&mSamplerDesc, sizeof(D3D11_SAMPLER_DESC) * 16);
  113. GFXD3D11Device::SamplerMap &dx11SamplerMap = D3D11->getSamplersMap();
  114. for (U32 i = 0; i < GFX->getNumSamplers(); i++)
  115. {
  116. GFXSamplerStateDesc &gfxSamplerState = mDesc.samplers[i];
  117. U32 hash = DictHash::hash(gfxSamplerState);
  118. GFXD3D11Device::SamplerMap::Iterator itr = dx11SamplerMap.find(hash);
  119. if (itr == dx11SamplerMap.end())
  120. {
  121. mSamplerDesc[i].AddressU = GFXD3D11TextureAddress[gfxSamplerState.addressModeU];
  122. mSamplerDesc[i].AddressV = GFXD3D11TextureAddress[gfxSamplerState.addressModeV];
  123. mSamplerDesc[i].AddressW = GFXD3D11TextureAddress[gfxSamplerState.addressModeW];
  124. mSamplerDesc[i].MaxAnisotropy = gfxSamplerState.maxAnisotropy;
  125. mSamplerDesc[i].MipLODBias = gfxSamplerState.mipLODBias;
  126. mSamplerDesc[i].MinLOD = 0;
  127. mSamplerDesc[i].MaxLOD = FLT_MAX;
  128. if (gfxSamplerState.magFilter == GFXTextureFilterPoint && gfxSamplerState.minFilter == GFXTextureFilterPoint && gfxSamplerState.mipFilter == GFXTextureFilterPoint)
  129. mSamplerDesc[i].Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
  130. else if (gfxSamplerState.magFilter == GFXTextureFilterPoint && gfxSamplerState.minFilter == GFXTextureFilterPoint && gfxSamplerState.mipFilter == GFXTextureFilterLinear)
  131. mSamplerDesc[i].Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
  132. else if (gfxSamplerState.magFilter == GFXTextureFilterLinear && gfxSamplerState.minFilter == GFXTextureFilterPoint && gfxSamplerState.mipFilter == GFXTextureFilterPoint)
  133. mSamplerDesc[i].Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
  134. else if (gfxSamplerState.magFilter == GFXTextureFilterLinear && gfxSamplerState.minFilter == GFXTextureFilterPoint && gfxSamplerState.mipFilter == GFXTextureFilterLinear)
  135. mSamplerDesc[i].Filter = D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
  136. else if (gfxSamplerState.magFilter == GFXTextureFilterPoint && gfxSamplerState.minFilter == GFXTextureFilterLinear && gfxSamplerState.mipFilter == GFXTextureFilterPoint)
  137. mSamplerDesc[i].Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
  138. else if (gfxSamplerState.magFilter == GFXTextureFilterPoint && gfxSamplerState.minFilter == GFXTextureFilterLinear && gfxSamplerState.mipFilter == GFXTextureFilterLinear)
  139. mSamplerDesc[i].Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
  140. else if (gfxSamplerState.magFilter == GFXTextureFilterLinear && gfxSamplerState.minFilter == GFXTextureFilterLinear && gfxSamplerState.mipFilter == GFXTextureFilterPoint)
  141. mSamplerDesc[i].Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
  142. else if (gfxSamplerState.magFilter == GFXTextureFilterLinear && gfxSamplerState.minFilter == GFXTextureFilterLinear && mDesc.samplers[i].mipFilter == GFXTextureFilterLinear)
  143. mSamplerDesc[i].Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
  144. else
  145. mSamplerDesc[i].Filter = D3D11_FILTER_ANISOTROPIC;
  146. mSamplerDesc[i].BorderColor[0] = 1.0f;
  147. mSamplerDesc[i].BorderColor[1] = 1.0f;
  148. mSamplerDesc[i].BorderColor[2] = 1.0f;
  149. mSamplerDesc[i].BorderColor[3] = 1.0f;
  150. hr = D3D11DEVICE->CreateSamplerState(&mSamplerDesc[i], &mSamplerStates[i]);
  151. if (FAILED(hr))
  152. {
  153. AssertFatal(false, "GFXD3D11StateBlock::GFXD3D11StateBlock - CreateSamplerState call failure.");
  154. }
  155. // add sampler state to the map
  156. dx11SamplerMap.insert(hash, mSamplerStates[i]);
  157. }
  158. else
  159. {
  160. mSamplerStates[i] = itr->value;
  161. }
  162. }
  163. }
  164. GFXD3D11StateBlock::~GFXD3D11StateBlock()
  165. {
  166. SAFE_RELEASE(mBlendState);
  167. SAFE_RELEASE(mRasterizerState);
  168. SAFE_RELEASE(mDepthStencilState);
  169. for (U32 i = 0; i < 16; ++i)
  170. {
  171. mSamplerStates[i] = NULL;
  172. }
  173. }
  174. /// Returns the hash value of the desc that created this block
  175. U32 GFXD3D11StateBlock::getHashValue() const
  176. {
  177. return mCachedHashValue;
  178. }
  179. /// Returns a GFXStateBlockDesc that this block represents
  180. const GFXStateBlockDesc& GFXD3D11StateBlock::getDesc() const
  181. {
  182. return mDesc;
  183. }
  184. /// Called by D3D11 device to active this state block.
  185. /// @param oldState The current state, used to make sure we don't set redundant states on the device. Pass NULL to reset all states.
  186. void GFXD3D11StateBlock::activate(GFXD3D11StateBlock* oldState)
  187. {
  188. PROFILE_SCOPE(GFXD3D11StateBlock_Activate);
  189. if (!oldState || (mBlendState != oldState->mBlendState))
  190. {
  191. F32 blendFactor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  192. D3D11DEVICECONTEXT->OMSetBlendState(mBlendState, blendFactor, 0xFFFFFFFF);
  193. }
  194. if (!oldState || (mDepthStencilState != oldState->mDepthStencilState))
  195. D3D11DEVICECONTEXT->OMSetDepthStencilState(mDepthStencilState, mDesc.stencilRef);
  196. if (!oldState || (mRasterizerState != oldState->mRasterizerState))
  197. D3D11DEVICECONTEXT->RSSetState(mRasterizerState);
  198. U32 numSamplersChanged = 0;
  199. U32 numSamplers = GFX->getNumSamplers();
  200. U32 samplerUpdateStartSlot = 0;
  201. //figure out which range of samplers changed.
  202. for (U32 samplerSlot = 0; samplerSlot < numSamplers; samplerSlot++)
  203. {
  204. if (oldState && (oldState->mSamplerStates[samplerSlot] == mSamplerStates[samplerSlot]))
  205. {
  206. //only change the update start slot when there hasn't been any samplers changed so far
  207. if (numSamplersChanged == 0) {
  208. samplerUpdateStartSlot++;
  209. }
  210. continue;
  211. }
  212. numSamplersChanged = (samplerSlot - samplerUpdateStartSlot) + 1;
  213. }
  214. //TODO samplers for vertex shader
  215. // Set all the samplers with one call
  216. //D3D11DEVICECONTEXT->VSSetSamplers(0, numSamplers, &mSamplerStates[0]);
  217. if (numSamplersChanged > 0)
  218. D3D11DEVICECONTEXT->PSSetSamplers(samplerUpdateStartSlot, numSamplersChanged, &mSamplerStates[samplerUpdateStartSlot]);
  219. }