gfxD3D11StateBlock.cpp
Engine/source/gfx/D3D11/gfxD3D11StateBlock.cpp
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