EffectRuntime.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. //--------------------------------------------------------------------------------------
  2. // File: EffectRuntime.cpp
  3. //
  4. // Direct3D 11 Effect runtime routines (performance critical)
  5. // These functions are expected to be called at high frequency
  6. // (when applying a pass).
  7. //
  8. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  9. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  10. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  11. // PARTICULAR PURPOSE.
  12. //
  13. // Copyright (c) Microsoft Corporation. All rights reserved.
  14. //
  15. // http://go.microsoft.com/fwlink/p/?LinkId=271568
  16. //--------------------------------------------------------------------------------------
  17. #include "pchfx.h"
  18. namespace D3DX11Effects
  19. {
  20. // D3D11_KEEP_UNORDERED_ACCESS_VIEWS == (uint32_t)-1
  21. uint32_t g_pNegativeOnes[8] = { D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS,
  22. D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS,
  23. D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS };
  24. bool SBaseBlock::ApplyAssignments(CEffect *pEffect)
  25. {
  26. SAssignment *pAssignment = pAssignments;
  27. SAssignment *pLastAssn = pAssignments + AssignmentCount;
  28. bool bRecreate = false;
  29. for(; pAssignment < pLastAssn; pAssignment++)
  30. {
  31. bRecreate |= pEffect->EvaluateAssignment(pAssignment);
  32. }
  33. return bRecreate;
  34. }
  35. void SPassBlock::ApplyPassAssignments()
  36. {
  37. SAssignment *pAssignment = pAssignments;
  38. SAssignment *pLastAssn = pAssignments + AssignmentCount;
  39. pEffect->IncrementTimer();
  40. for(; pAssignment < pLastAssn; pAssignment++)
  41. {
  42. pEffect->EvaluateAssignment(pAssignment);
  43. }
  44. }
  45. // Returns true if the shader uses global interfaces (since these interfaces can be updated through SetClassInstance)
  46. bool SPassBlock::CheckShaderDependencies( _In_ const SShaderBlock* pBlock )
  47. {
  48. if( pBlock->InterfaceDepCount > 0 )
  49. {
  50. assert( pBlock->InterfaceDepCount == 1 );
  51. for( size_t i=0; i < pBlock->pInterfaceDeps[0].Count; i++ )
  52. {
  53. SInterface* pInterfaceDep = pBlock->pInterfaceDeps[0].ppFXPointers[i];
  54. if( pInterfaceDep > pEffect->m_pInterfaces && pInterfaceDep < (pEffect->m_pInterfaces + pEffect->m_InterfaceCount) )
  55. {
  56. // This is a global interface pointer (as opposed to an SInterface created in a BindInterface call
  57. return true;
  58. }
  59. }
  60. }
  61. return false;
  62. }
  63. // Returns true if the pass (and sets HasDependencies) if the pass sets objects whose backing stores can be updated
  64. #pragma warning(push)
  65. #pragma warning(disable: 4616 6282)
  66. bool SPassBlock::CheckDependencies()
  67. {
  68. if( HasDependencies )
  69. return true;
  70. for( size_t i=0; i < AssignmentCount; i++ )
  71. {
  72. if( pAssignments[i].DependencyCount > 0 )
  73. return HasDependencies = true;
  74. }
  75. if( BackingStore.pBlendBlock && BackingStore.pBlendBlock->AssignmentCount > 0 )
  76. {
  77. for( size_t i=0; i < BackingStore.pBlendBlock->AssignmentCount; i++ )
  78. {
  79. if( BackingStore.pBlendBlock->pAssignments[i].DependencyCount > 0 )
  80. return HasDependencies = true;
  81. }
  82. }
  83. if( BackingStore.pDepthStencilBlock && BackingStore.pDepthStencilBlock->AssignmentCount > 0 )
  84. {
  85. for( size_t i=0; i < BackingStore.pDepthStencilBlock->AssignmentCount; i++ )
  86. {
  87. if( BackingStore.pDepthStencilBlock->pAssignments[i].DependencyCount > 0 )
  88. return HasDependencies = true;
  89. }
  90. }
  91. if( BackingStore.pRasterizerBlock && BackingStore.pRasterizerBlock->AssignmentCount > 0 )
  92. {
  93. for( size_t i=0; i < BackingStore.pRasterizerBlock->AssignmentCount; i++ )
  94. {
  95. if( BackingStore.pRasterizerBlock->pAssignments[i].DependencyCount > 0 )
  96. return HasDependencies = true;
  97. }
  98. }
  99. if( BackingStore.pVertexShaderBlock && CheckShaderDependencies( BackingStore.pVertexShaderBlock ) )
  100. {
  101. return HasDependencies = true;
  102. }
  103. if( BackingStore.pGeometryShaderBlock && CheckShaderDependencies( BackingStore.pGeometryShaderBlock ) )
  104. {
  105. return HasDependencies = true;
  106. }
  107. if( BackingStore.pPixelShaderBlock && CheckShaderDependencies( BackingStore.pPixelShaderBlock ) )
  108. {
  109. return HasDependencies = true;
  110. }
  111. if( BackingStore.pHullShaderBlock && CheckShaderDependencies( BackingStore.pHullShaderBlock ) )
  112. {
  113. return HasDependencies = true;
  114. }
  115. if( BackingStore.pDomainShaderBlock && CheckShaderDependencies( BackingStore.pDomainShaderBlock ) )
  116. {
  117. return HasDependencies = true;
  118. }
  119. if( BackingStore.pComputeShaderBlock && CheckShaderDependencies( BackingStore.pComputeShaderBlock ) )
  120. {
  121. return HasDependencies = true;
  122. }
  123. return HasDependencies;
  124. }
  125. #pragma warning(pop)
  126. // Update constant buffer contents if necessary
  127. inline void CheckAndUpdateCB_FX(ID3D11DeviceContext *pContext, SConstantBuffer *pCB)
  128. {
  129. if (pCB->IsDirty && !pCB->IsNonUpdatable)
  130. {
  131. // CB out of date; rebuild it
  132. pContext->UpdateSubresource(pCB->pD3DObject, 0, nullptr, pCB->pBackingStore, pCB->Size, pCB->Size);
  133. pCB->IsDirty = false;
  134. }
  135. }
  136. //--------------------------------------------------------------------------------------
  137. //--------------------------------------------------------------------------------------
  138. // Set the shader and dependent state (SRVs, samplers, UAVs, interfaces)
  139. void CEffect::ApplyShaderBlock(_In_ SShaderBlock *pBlock)
  140. {
  141. SD3DShaderVTable *pVT = pBlock->pVT;
  142. // Apply constant buffers first (tbuffers are done later)
  143. SShaderCBDependency *pCBDep = pBlock->pCBDeps;
  144. SShaderCBDependency *pLastCBDep = pBlock->pCBDeps + pBlock->CBDepCount;
  145. for (; pCBDep<pLastCBDep; pCBDep++)
  146. {
  147. assert(pCBDep->ppFXPointers);
  148. for (size_t i = 0; i < pCBDep->Count; ++ i)
  149. {
  150. CheckAndUpdateCB_FX(m_pContext, (SConstantBuffer*)pCBDep->ppFXPointers[i]);
  151. }
  152. (m_pContext->*(pVT->pSetConstantBuffers))(pCBDep->StartIndex, pCBDep->Count, pCBDep->ppD3DObjects);
  153. }
  154. // Next, apply samplers
  155. SShaderSamplerDependency *pSampDep = pBlock->pSampDeps;
  156. SShaderSamplerDependency *pLastSampDep = pBlock->pSampDeps + pBlock->SampDepCount;
  157. for (; pSampDep<pLastSampDep; pSampDep++)
  158. {
  159. assert(pSampDep->ppFXPointers);
  160. for (size_t i=0; i<pSampDep->Count; i++)
  161. {
  162. if ( ApplyRenderStateBlock(pSampDep->ppFXPointers[i]) )
  163. {
  164. // If the sampler was updated, its pointer will have changed
  165. pSampDep->ppD3DObjects[i] = pSampDep->ppFXPointers[i]->pD3DObject;
  166. }
  167. }
  168. (m_pContext->*(pVT->pSetSamplers))(pSampDep->StartIndex, pSampDep->Count, pSampDep->ppD3DObjects);
  169. }
  170. // Set the UAVs
  171. // UAV ranges were combined in EffectLoad. This code remains unchanged, however, so that ranges can be easily split
  172. assert( pBlock->UAVDepCount < 2 );
  173. if( pBlock->UAVDepCount > 0 )
  174. {
  175. SUnorderedAccessViewDependency *pUAVDep = pBlock->pUAVDeps;
  176. assert(pUAVDep->ppFXPointers != 0);
  177. _Analysis_assume_(pUAVDep->ppFXPointers != 0);
  178. for (size_t i=0; i<pUAVDep->Count; i++)
  179. {
  180. pUAVDep->ppD3DObjects[i] = pUAVDep->ppFXPointers[i]->pUnorderedAccessView;
  181. }
  182. if( EOT_ComputeShader5 == pBlock->GetShaderType() )
  183. {
  184. m_pContext->CSSetUnorderedAccessViews( pUAVDep->StartIndex, pUAVDep->Count, pUAVDep->ppD3DObjects, g_pNegativeOnes );
  185. }
  186. else
  187. {
  188. // This call could be combined with the call to set render targets if both exist in the pass
  189. m_pContext->OMSetRenderTargetsAndUnorderedAccessViews( D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, pUAVDep->StartIndex, pUAVDep->Count, pUAVDep->ppD3DObjects, g_pNegativeOnes );
  190. }
  191. }
  192. // TBuffers are funny:
  193. // We keep two references to them. One is in as a standard texture dep, and that gets used for all sets
  194. // The other is as a part of the TBufferDeps array, which tells us to rebuild the matching CBs.
  195. // These two refs could be rolled into one, but then we would have to predicate on each CB or each texture.
  196. SConstantBuffer **ppTB = pBlock->ppTbufDeps;
  197. SConstantBuffer **ppLastTB = ppTB + pBlock->TBufferDepCount;
  198. for (; ppTB<ppLastTB; ppTB++)
  199. {
  200. CheckAndUpdateCB_FX(m_pContext, (SConstantBuffer*)*ppTB);
  201. }
  202. // Set the textures
  203. SShaderResourceDependency *pResourceDep = pBlock->pResourceDeps;
  204. SShaderResourceDependency *pLastResourceDep = pBlock->pResourceDeps + pBlock->ResourceDepCount;
  205. for (; pResourceDep<pLastResourceDep; pResourceDep++)
  206. {
  207. assert(pResourceDep->ppFXPointers != 0);
  208. _Analysis_assume_(pResourceDep->ppFXPointers != 0);
  209. for (size_t i=0; i<pResourceDep->Count; i++)
  210. {
  211. pResourceDep->ppD3DObjects[i] = pResourceDep->ppFXPointers[i]->pShaderResource;
  212. }
  213. (m_pContext->*(pVT->pSetShaderResources))(pResourceDep->StartIndex, pResourceDep->Count, pResourceDep->ppD3DObjects);
  214. }
  215. // Update Interface dependencies
  216. uint32_t Interfaces = 0;
  217. ID3D11ClassInstance** ppClassInstances = nullptr;
  218. assert( pBlock->InterfaceDepCount < 2 );
  219. if( pBlock->InterfaceDepCount > 0 )
  220. {
  221. SInterfaceDependency *pInterfaceDep = pBlock->pInterfaceDeps;
  222. assert(pInterfaceDep->ppFXPointers);
  223. ppClassInstances = pInterfaceDep->ppD3DObjects;
  224. Interfaces = pInterfaceDep->Count;
  225. for (size_t i=0; i<pInterfaceDep->Count; i++)
  226. {
  227. assert(pInterfaceDep->ppFXPointers != 0);
  228. _Analysis_assume_(pInterfaceDep->ppFXPointers != 0);
  229. SClassInstanceGlobalVariable* pCI = pInterfaceDep->ppFXPointers[i]->pClassInstance;
  230. if( pCI )
  231. {
  232. assert( pCI->pMemberData != 0 );
  233. _Analysis_assume_( pCI->pMemberData != 0 );
  234. pInterfaceDep->ppD3DObjects[i] = pCI->pMemberData->Data.pD3DClassInstance;
  235. }
  236. else
  237. {
  238. pInterfaceDep->ppD3DObjects[i] = nullptr;
  239. }
  240. }
  241. }
  242. // Now set the shader
  243. (m_pContext->*(pVT->pSetShader))(pBlock->pD3DObject, ppClassInstances, Interfaces);
  244. }
  245. // Returns true if the block D3D data was recreated
  246. bool CEffect::ApplyRenderStateBlock(_In_ SBaseBlock *pBlock)
  247. {
  248. if( pBlock->IsUserManaged )
  249. {
  250. return false;
  251. }
  252. bool bRecreate = pBlock->ApplyAssignments(this);
  253. if (bRecreate)
  254. {
  255. switch (pBlock->BlockType)
  256. {
  257. case EBT_Sampler:
  258. {
  259. SSamplerBlock *pSBlock = pBlock->AsSampler();
  260. assert(pSBlock->pD3DObject != 0);
  261. _Analysis_assume_(pSBlock->pD3DObject != 0);
  262. pSBlock->pD3DObject->Release();
  263. HRESULT hr = m_pDevice->CreateSamplerState( &pSBlock->BackingStore.SamplerDesc, &pSBlock->pD3DObject );
  264. if ( SUCCEEDED(hr) )
  265. {
  266. SetDebugObjectName(pSBlock->pD3DObject, "D3DX11Effect");
  267. }
  268. }
  269. break;
  270. case EBT_DepthStencil:
  271. {
  272. SDepthStencilBlock *pDSBlock = pBlock->AsDepthStencil();
  273. assert(nullptr != pDSBlock->pDSObject);
  274. SAFE_RELEASE( pDSBlock->pDSObject );
  275. if( SUCCEEDED( m_pDevice->CreateDepthStencilState( &pDSBlock->BackingStore, &pDSBlock->pDSObject ) ) )
  276. {
  277. pDSBlock->IsValid = true;
  278. SetDebugObjectName( pDSBlock->pDSObject, "D3DX11Effect" );
  279. }
  280. else
  281. pDSBlock->IsValid = false;
  282. }
  283. break;
  284. case EBT_Blend:
  285. {
  286. SBlendBlock *pBBlock = pBlock->AsBlend();
  287. assert(nullptr != pBBlock->pBlendObject);
  288. SAFE_RELEASE( pBBlock->pBlendObject );
  289. if( SUCCEEDED( m_pDevice->CreateBlendState( &pBBlock->BackingStore, &pBBlock->pBlendObject ) ) )
  290. {
  291. pBBlock->IsValid = true;
  292. SetDebugObjectName( pBBlock->pBlendObject, "D3DX11Effect" );
  293. }
  294. else
  295. pBBlock->IsValid = false;
  296. }
  297. break;
  298. case EBT_Rasterizer:
  299. {
  300. SRasterizerBlock *pRBlock = pBlock->AsRasterizer();
  301. assert(nullptr != pRBlock->pRasterizerObject);
  302. SAFE_RELEASE( pRBlock->pRasterizerObject );
  303. if( SUCCEEDED( m_pDevice->CreateRasterizerState( &pRBlock->BackingStore, &pRBlock->pRasterizerObject ) ) )
  304. {
  305. pRBlock->IsValid = true;
  306. SetDebugObjectName( pRBlock->pRasterizerObject, "D3DX11Effect" );
  307. }
  308. else
  309. pRBlock->IsValid = false;
  310. }
  311. break;
  312. default:
  313. assert(0);
  314. }
  315. }
  316. return bRecreate;
  317. }
  318. void CEffect::ValidateIndex(_In_ uint32_t Elements)
  319. {
  320. if (m_FXLIndex >= Elements)
  321. {
  322. DPF(0, "ID3DX11Effect: Overindexing variable array (size: %u, index: %u), using index = 0 instead", Elements, m_FXLIndex);
  323. m_FXLIndex = 0;
  324. }
  325. }
  326. // Returns true if the assignment was changed
  327. bool CEffect::EvaluateAssignment(_Inout_ SAssignment *pAssignment)
  328. {
  329. bool bNeedUpdate = false;
  330. SGlobalVariable *pVarDep0, *pVarDep1;
  331. switch (pAssignment->AssignmentType)
  332. {
  333. case ERAT_NumericVariable:
  334. assert(pAssignment->DependencyCount == 1);
  335. if (pAssignment->pDependencies[0].pVariable->LastModifiedTime >= pAssignment->LastRecomputedTime)
  336. {
  337. memcpy(pAssignment->Destination.pNumeric, pAssignment->Source.pNumeric, pAssignment->DataSize);
  338. bNeedUpdate = true;
  339. }
  340. break;
  341. case ERAT_NumericVariableIndex:
  342. assert(pAssignment->DependencyCount == 2);
  343. pVarDep0 = pAssignment->pDependencies[0].pVariable;
  344. pVarDep1 = pAssignment->pDependencies[1].pVariable;
  345. if (pVarDep0->LastModifiedTime >= pAssignment->LastRecomputedTime)
  346. {
  347. m_FXLIndex = *pVarDep0->Data.pNumericDword;
  348. ValidateIndex(pVarDep1->pType->Elements);
  349. // Array index variable is dirty, update the pointer
  350. pAssignment->Source.pNumeric = pVarDep1->Data.pNumeric + pVarDep1->pType->Stride * m_FXLIndex;
  351. // Copy the new data
  352. memcpy(pAssignment->Destination.pNumeric, pAssignment->Source.pNumeric, pAssignment->DataSize);
  353. bNeedUpdate = true;
  354. }
  355. else if (pVarDep1->LastModifiedTime >= pAssignment->LastRecomputedTime)
  356. {
  357. // Only the array variable is dirty, copy the new data
  358. memcpy(pAssignment->Destination.pNumeric, pAssignment->Source.pNumeric, pAssignment->DataSize);
  359. bNeedUpdate = true;
  360. }
  361. break;
  362. case ERAT_ObjectVariableIndex:
  363. assert(pAssignment->DependencyCount == 1);
  364. pVarDep0 = pAssignment->pDependencies[0].pVariable;
  365. if (pVarDep0->LastModifiedTime >= pAssignment->LastRecomputedTime)
  366. {
  367. m_FXLIndex = *pVarDep0->Data.pNumericDword;
  368. ValidateIndex(pAssignment->MaxElements);
  369. // Array index variable is dirty, update the destination pointer
  370. *((void **)pAssignment->Destination.pGeneric) = pAssignment->Source.pNumeric +
  371. pAssignment->DataSize * m_FXLIndex;
  372. bNeedUpdate = true;
  373. }
  374. break;
  375. default:
  376. //case ERAT_Constant: -- These are consumed and discarded
  377. //case ERAT_ObjectVariable: -- These are consumed and discarded
  378. //case ERAT_ObjectConstIndex: -- These are consumed and discarded
  379. //case ERAT_ObjectInlineShader: -- These are consumed and discarded
  380. //case ERAT_NumericConstIndex: -- ERAT_NumericVariable should be generated instead
  381. assert(0);
  382. break;
  383. }
  384. // Mark the assignment as not dirty
  385. pAssignment->LastRecomputedTime = m_LocalTimer;
  386. return bNeedUpdate;
  387. }
  388. // Returns false if this shader has interface dependencies which are nullptr (SetShader will fail).
  389. bool CEffect::ValidateShaderBlock( _Inout_ SShaderBlock* pBlock )
  390. {
  391. if( !pBlock->IsValid )
  392. return false;
  393. if( pBlock->InterfaceDepCount > 0 )
  394. {
  395. assert( pBlock->InterfaceDepCount == 1 );
  396. for( size_t i=0; i < pBlock->pInterfaceDeps[0].Count; i++ )
  397. {
  398. SInterface* pInterfaceDep = pBlock->pInterfaceDeps[0].ppFXPointers[i];
  399. assert( pInterfaceDep != 0 );
  400. _Analysis_assume_( pInterfaceDep != 0 );
  401. if( pInterfaceDep->pClassInstance == nullptr )
  402. {
  403. return false;
  404. }
  405. }
  406. }
  407. return true;
  408. }
  409. // Returns false if any state in the pass is invalid
  410. bool CEffect::ValidatePassBlock( _Inout_ SPassBlock* pBlock )
  411. {
  412. pBlock->ApplyPassAssignments();
  413. if (nullptr != pBlock->BackingStore.pBlendBlock)
  414. {
  415. ApplyRenderStateBlock(pBlock->BackingStore.pBlendBlock);
  416. pBlock->BackingStore.pBlendState = pBlock->BackingStore.pBlendBlock->pBlendObject;
  417. if( !pBlock->BackingStore.pBlendBlock->IsValid )
  418. return false;
  419. }
  420. if( nullptr != pBlock->BackingStore.pDepthStencilBlock )
  421. {
  422. ApplyRenderStateBlock( pBlock->BackingStore.pDepthStencilBlock );
  423. pBlock->BackingStore.pDepthStencilState = pBlock->BackingStore.pDepthStencilBlock->pDSObject;
  424. if( !pBlock->BackingStore.pDepthStencilBlock->IsValid )
  425. return false;
  426. }
  427. if( nullptr != pBlock->BackingStore.pRasterizerBlock )
  428. {
  429. ApplyRenderStateBlock( pBlock->BackingStore.pRasterizerBlock );
  430. if( !pBlock->BackingStore.pRasterizerBlock->IsValid )
  431. return false;
  432. }
  433. if( nullptr != pBlock->BackingStore.pVertexShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pVertexShaderBlock) )
  434. return false;
  435. if( nullptr != pBlock->BackingStore.pGeometryShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pGeometryShaderBlock) )
  436. return false;
  437. if( nullptr != pBlock->BackingStore.pPixelShaderBlock )
  438. {
  439. if( !ValidateShaderBlock(pBlock->BackingStore.pPixelShaderBlock) )
  440. return false;
  441. else if( pBlock->BackingStore.pPixelShaderBlock->UAVDepCount > 0 &&
  442. pBlock->BackingStore.RenderTargetViewCount > pBlock->BackingStore.pPixelShaderBlock->pUAVDeps[0].StartIndex )
  443. {
  444. return false;
  445. }
  446. }
  447. if( nullptr != pBlock->BackingStore.pHullShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pHullShaderBlock) )
  448. return false;
  449. if( nullptr != pBlock->BackingStore.pDomainShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pDomainShaderBlock) )
  450. return false;
  451. if( nullptr != pBlock->BackingStore.pComputeShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pComputeShaderBlock) )
  452. return false;
  453. return true;
  454. }
  455. // Set all state defined in the pass
  456. void CEffect::ApplyPassBlock(_Inout_ SPassBlock *pBlock)
  457. {
  458. pBlock->ApplyPassAssignments();
  459. if (nullptr != pBlock->BackingStore.pBlendBlock)
  460. {
  461. ApplyRenderStateBlock(pBlock->BackingStore.pBlendBlock);
  462. #ifdef FXDEBUG
  463. if( !pBlock->BackingStore.pBlendBlock->IsValid )
  464. DPF( 0, "Pass::Apply - warning: applying invalid BlendState." );
  465. #endif
  466. pBlock->BackingStore.pBlendState = pBlock->BackingStore.pBlendBlock->pBlendObject;
  467. m_pContext->OMSetBlendState(pBlock->BackingStore.pBlendState,
  468. pBlock->BackingStore.BlendFactor,
  469. pBlock->BackingStore.SampleMask);
  470. }
  471. if (nullptr != pBlock->BackingStore.pDepthStencilBlock)
  472. {
  473. ApplyRenderStateBlock(pBlock->BackingStore.pDepthStencilBlock);
  474. #ifdef FXDEBUG
  475. if( !pBlock->BackingStore.pDepthStencilBlock->IsValid )
  476. DPF( 0, "Pass::Apply - warning: applying invalid DepthStencilState." );
  477. #endif
  478. pBlock->BackingStore.pDepthStencilState = pBlock->BackingStore.pDepthStencilBlock->pDSObject;
  479. m_pContext->OMSetDepthStencilState(pBlock->BackingStore.pDepthStencilState,
  480. pBlock->BackingStore.StencilRef);
  481. }
  482. if (nullptr != pBlock->BackingStore.pRasterizerBlock)
  483. {
  484. ApplyRenderStateBlock(pBlock->BackingStore.pRasterizerBlock);
  485. #ifdef FXDEBUG
  486. if( !pBlock->BackingStore.pRasterizerBlock->IsValid )
  487. DPF( 0, "Pass::Apply - warning: applying invalid RasterizerState." );
  488. #endif
  489. m_pContext->RSSetState(pBlock->BackingStore.pRasterizerBlock->pRasterizerObject);
  490. }
  491. if (nullptr != pBlock->BackingStore.pRenderTargetViews[0])
  492. {
  493. // Grab all render targets
  494. ID3D11RenderTargetView *pRTV[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
  495. assert(pBlock->BackingStore.RenderTargetViewCount <= D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
  496. _Analysis_assume_(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT >= pBlock->BackingStore.RenderTargetViewCount);
  497. for (uint32_t i=0; i<pBlock->BackingStore.RenderTargetViewCount; i++)
  498. {
  499. pRTV[i] = pBlock->BackingStore.pRenderTargetViews[i]->pRenderTargetView;
  500. }
  501. // This call could be combined with the call to set PS UAVs if both exist in the pass
  502. m_pContext->OMSetRenderTargetsAndUnorderedAccessViews( pBlock->BackingStore.RenderTargetViewCount, pRTV, pBlock->BackingStore.pDepthStencilView->pDepthStencilView, 7, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, nullptr, nullptr );
  503. }
  504. if (nullptr != pBlock->BackingStore.pVertexShaderBlock)
  505. {
  506. #ifdef FXDEBUG
  507. if( !pBlock->BackingStore.pVertexShaderBlock->IsValid )
  508. DPF( 0, "Pass::Apply - warning: applying invalid vertex shader." );
  509. #endif
  510. ApplyShaderBlock(pBlock->BackingStore.pVertexShaderBlock);
  511. }
  512. if (nullptr != pBlock->BackingStore.pPixelShaderBlock)
  513. {
  514. #ifdef FXDEBUG
  515. if( !pBlock->BackingStore.pPixelShaderBlock->IsValid )
  516. DPF( 0, "Pass::Apply - warning: applying invalid pixel shader." );
  517. #endif
  518. ApplyShaderBlock(pBlock->BackingStore.pPixelShaderBlock);
  519. }
  520. if (nullptr != pBlock->BackingStore.pGeometryShaderBlock)
  521. {
  522. #ifdef FXDEBUG
  523. if( !pBlock->BackingStore.pGeometryShaderBlock->IsValid )
  524. DPF( 0, "Pass::Apply - warning: applying invalid geometry shader." );
  525. #endif
  526. ApplyShaderBlock(pBlock->BackingStore.pGeometryShaderBlock);
  527. }
  528. if (nullptr != pBlock->BackingStore.pHullShaderBlock)
  529. {
  530. #ifdef FXDEBUG
  531. if( !pBlock->BackingStore.pHullShaderBlock->IsValid )
  532. DPF( 0, "Pass::Apply - warning: applying invalid hull shader." );
  533. #endif
  534. ApplyShaderBlock(pBlock->BackingStore.pHullShaderBlock);
  535. }
  536. if (nullptr != pBlock->BackingStore.pDomainShaderBlock)
  537. {
  538. #ifdef FXDEBUG
  539. if( !pBlock->BackingStore.pDomainShaderBlock->IsValid )
  540. DPF( 0, "Pass::Apply - warning: applying invalid domain shader." );
  541. #endif
  542. ApplyShaderBlock(pBlock->BackingStore.pDomainShaderBlock);
  543. }
  544. if (nullptr != pBlock->BackingStore.pComputeShaderBlock)
  545. {
  546. #ifdef FXDEBUG
  547. if( !pBlock->BackingStore.pComputeShaderBlock->IsValid )
  548. DPF( 0, "Pass::Apply - warning: applying invalid compute shader." );
  549. #endif
  550. ApplyShaderBlock(pBlock->BackingStore.pComputeShaderBlock);
  551. }
  552. }
  553. void CEffect::IncrementTimer()
  554. {
  555. m_LocalTimer++;
  556. #ifndef _M_X64
  557. #if _DEBUG
  558. if (m_LocalTimer > g_TimerRolloverCount)
  559. {
  560. DPF(0, "Rolling over timer (current time: %u, rollover cap: %u).", m_LocalTimer, g_TimerRolloverCount);
  561. #else
  562. if (m_LocalTimer >= 0x80000000) // check to see if we've exceeded ~2 billion
  563. {
  564. #endif
  565. HandleLocalTimerRollover();
  566. m_LocalTimer = 1;
  567. }
  568. #endif // _M_X64
  569. }
  570. // This function resets all timers, rendering all assignments dirty
  571. // This is clearly bad for performance, but should only happen every few billion ticks
  572. void CEffect::HandleLocalTimerRollover()
  573. {
  574. uint32_t i, j, k;
  575. // step 1: update variables
  576. for (i = 0; i < m_VariableCount; ++ i)
  577. {
  578. m_pVariables[i].LastModifiedTime = 0;
  579. }
  580. // step 2: update assignments on all blocks (pass, depth stencil, rasterizer, blend, sampler)
  581. for (uint32_t iGroup = 0; iGroup < m_GroupCount; ++ iGroup)
  582. {
  583. for (i = 0; i < m_pGroups[iGroup].TechniqueCount; ++ i)
  584. {
  585. for (j = 0; j < m_pGroups[iGroup].pTechniques[i].PassCount; ++ j)
  586. {
  587. for (k = 0; k < m_pGroups[iGroup].pTechniques[i].pPasses[j].AssignmentCount; ++ k)
  588. {
  589. m_pGroups[iGroup].pTechniques[i].pPasses[j].pAssignments[k].LastRecomputedTime = 0;
  590. }
  591. }
  592. }
  593. }
  594. for (i = 0; i < m_DepthStencilBlockCount; ++ i)
  595. {
  596. for (j = 0; j < m_pDepthStencilBlocks[i].AssignmentCount; ++ j)
  597. {
  598. m_pDepthStencilBlocks[i].pAssignments[j].LastRecomputedTime = 0;
  599. }
  600. }
  601. for (i = 0; i < m_RasterizerBlockCount; ++ i)
  602. {
  603. for (j = 0; j < m_pRasterizerBlocks[i].AssignmentCount; ++ j)
  604. {
  605. m_pRasterizerBlocks[i].pAssignments[j].LastRecomputedTime = 0;
  606. }
  607. }
  608. for (i = 0; i < m_BlendBlockCount; ++ i)
  609. {
  610. for (j = 0; j < m_pBlendBlocks[i].AssignmentCount; ++ j)
  611. {
  612. m_pBlendBlocks[i].pAssignments[j].LastRecomputedTime = 0;
  613. }
  614. }
  615. for (i = 0; i < m_SamplerBlockCount; ++ i)
  616. {
  617. for (j = 0; j < m_pSamplerBlocks[i].AssignmentCount; ++ j)
  618. {
  619. m_pSamplerBlocks[i].pAssignments[j].LastRecomputedTime = 0;
  620. }
  621. }
  622. }
  623. }