Torque3D Documentation / _generateds / gfxD3D11StateBlock.cpp

gfxD3D11StateBlock.cpp

Engine/source/gfx/D3D11/gfxD3D11StateBlock.cpp

More...

Namespaces:

namespace

Detailed Description

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