[Omega] Release RC1
[xbmc.git] / lib / win32 / Effects11 / EffectRuntime.cpp
blob90a41947946551be74e2e77781e7f51f8c5132aa
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 // Copyright (c) Microsoft Corporation.
9 // Licensed under the MIT License.
11 // http://go.microsoft.com/fwlink/p/?LinkId=271568
12 //--------------------------------------------------------------------------------------
14 #include "pchfx.h"
16 namespace D3DX11Effects
18 // D3D11_KEEP_UNORDERED_ACCESS_VIEWS == (uint32_t)-1
19 uint32_t g_pNegativeOnes[8] = { D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS,
20 D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS,
21 D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS };
23 bool SBaseBlock::ApplyAssignments(CEffect *pEffect)
25 SAssignment *pAssignment = pAssignments;
26 SAssignment *pLastAssn = pAssignments + AssignmentCount;
27 bool bRecreate = false;
29 for(; pAssignment < pLastAssn; pAssignment++)
31 bRecreate |= pEffect->EvaluateAssignment(pAssignment);
34 return bRecreate;
37 void SPassBlock::ApplyPassAssignments()
39 SAssignment *pAssignment = pAssignments;
40 SAssignment *pLastAssn = pAssignments + AssignmentCount;
42 pEffect->IncrementTimer();
44 for(; pAssignment < pLastAssn; pAssignment++)
46 pEffect->EvaluateAssignment(pAssignment);
50 // Returns true if the shader uses global interfaces (since these interfaces can be updated through SetClassInstance)
51 bool SPassBlock::CheckShaderDependencies( _In_ const SShaderBlock* pBlock )
53 if( pBlock->InterfaceDepCount > 0 )
55 assert( pBlock->InterfaceDepCount == 1 );
56 for( size_t i=0; i < pBlock->pInterfaceDeps[0].Count; i++ )
58 SInterface* pInterfaceDep = pBlock->pInterfaceDeps[0].ppFXPointers[i];
59 if( pInterfaceDep > pEffect->m_pInterfaces && pInterfaceDep < (pEffect->m_pInterfaces + pEffect->m_InterfaceCount) )
61 // This is a global interface pointer (as opposed to an SInterface created in a BindInterface call
62 return true;
66 return false;
69 // Returns true if the pass (and sets HasDependencies) if the pass sets objects whose backing stores can be updated
70 #pragma warning(push)
71 #pragma warning(disable: 4616 6282)
72 bool SPassBlock::CheckDependencies()
74 if( HasDependencies )
75 return true;
77 for( size_t i=0; i < AssignmentCount; i++ )
79 if( pAssignments[i].DependencyCount > 0 )
80 return HasDependencies = true;
82 if( BackingStore.pBlendBlock && BackingStore.pBlendBlock->AssignmentCount > 0 )
84 for( size_t i=0; i < BackingStore.pBlendBlock->AssignmentCount; i++ )
86 if( BackingStore.pBlendBlock->pAssignments[i].DependencyCount > 0 )
87 return HasDependencies = true;
90 if( BackingStore.pDepthStencilBlock && BackingStore.pDepthStencilBlock->AssignmentCount > 0 )
92 for( size_t i=0; i < BackingStore.pDepthStencilBlock->AssignmentCount; i++ )
94 if( BackingStore.pDepthStencilBlock->pAssignments[i].DependencyCount > 0 )
95 return HasDependencies = true;
98 if( BackingStore.pRasterizerBlock && BackingStore.pRasterizerBlock->AssignmentCount > 0 )
100 for( size_t i=0; i < BackingStore.pRasterizerBlock->AssignmentCount; i++ )
102 if( BackingStore.pRasterizerBlock->pAssignments[i].DependencyCount > 0 )
103 return HasDependencies = true;
106 if( BackingStore.pVertexShaderBlock && CheckShaderDependencies( BackingStore.pVertexShaderBlock ) )
108 return HasDependencies = true;
110 if( BackingStore.pGeometryShaderBlock && CheckShaderDependencies( BackingStore.pGeometryShaderBlock ) )
112 return HasDependencies = true;
114 if( BackingStore.pPixelShaderBlock && CheckShaderDependencies( BackingStore.pPixelShaderBlock ) )
116 return HasDependencies = true;
118 if( BackingStore.pHullShaderBlock && CheckShaderDependencies( BackingStore.pHullShaderBlock ) )
120 return HasDependencies = true;
122 if( BackingStore.pDomainShaderBlock && CheckShaderDependencies( BackingStore.pDomainShaderBlock ) )
124 return HasDependencies = true;
126 if( BackingStore.pComputeShaderBlock && CheckShaderDependencies( BackingStore.pComputeShaderBlock ) )
128 return HasDependencies = true;
131 return HasDependencies;
133 #pragma warning(pop)
135 // Update constant buffer contents if necessary
136 inline void CheckAndUpdateCB_FX(ID3D11DeviceContext *pContext, SConstantBuffer *pCB)
138 if (pCB->IsDirty && !pCB->IsNonUpdatable)
140 // CB out of date; rebuild it
141 pContext->UpdateSubresource(pCB->pD3DObject, 0, nullptr, pCB->pBackingStore, pCB->Size, pCB->Size);
142 pCB->IsDirty = false;
147 //--------------------------------------------------------------------------------------
148 //--------------------------------------------------------------------------------------
150 // Set the shader and dependent state (SRVs, samplers, UAVs, interfaces)
151 void CEffect::ApplyShaderBlock(_In_ SShaderBlock *pBlock)
153 SD3DShaderVTable *pVT = pBlock->pVT;
155 // Apply constant buffers first (tbuffers are done later)
156 SShaderCBDependency *pCBDep = pBlock->pCBDeps;
157 SShaderCBDependency *pLastCBDep = pBlock->pCBDeps + pBlock->CBDepCount;
159 for (; pCBDep<pLastCBDep; pCBDep++)
161 assert(pCBDep->ppFXPointers);
163 for (size_t i = 0; i < pCBDep->Count; ++ i)
165 CheckAndUpdateCB_FX(m_pContext, (SConstantBuffer*)pCBDep->ppFXPointers[i]);
168 (m_pContext->*(pVT->pSetConstantBuffers))(pCBDep->StartIndex, pCBDep->Count, pCBDep->ppD3DObjects);
171 // Next, apply samplers
172 SShaderSamplerDependency *pSampDep = pBlock->pSampDeps;
173 SShaderSamplerDependency *pLastSampDep = pBlock->pSampDeps + pBlock->SampDepCount;
175 for (; pSampDep<pLastSampDep; pSampDep++)
177 assert(pSampDep->ppFXPointers);
179 for (size_t i=0; i<pSampDep->Count; i++)
181 if ( ApplyRenderStateBlock(pSampDep->ppFXPointers[i]) )
183 // If the sampler was updated, its pointer will have changed
184 pSampDep->ppD3DObjects[i] = pSampDep->ppFXPointers[i]->pD3DObject;
187 (m_pContext->*(pVT->pSetSamplers))(pSampDep->StartIndex, pSampDep->Count, pSampDep->ppD3DObjects);
190 // Set the UAVs
191 // UAV ranges were combined in EffectLoad. This code remains unchanged, however, so that ranges can be easily split
192 assert( pBlock->UAVDepCount < 2 );
193 if( pBlock->UAVDepCount > 0 )
195 SUnorderedAccessViewDependency *pUAVDep = pBlock->pUAVDeps;
196 assert(pUAVDep->ppFXPointers != 0);
197 _Analysis_assume_(pUAVDep->ppFXPointers != 0);
199 for (size_t i=0; i<pUAVDep->Count; i++)
201 pUAVDep->ppD3DObjects[i] = pUAVDep->ppFXPointers[i]->pUnorderedAccessView;
204 if( EOT_ComputeShader5 == pBlock->GetShaderType() )
206 m_pContext->CSSetUnorderedAccessViews( pUAVDep->StartIndex, pUAVDep->Count, pUAVDep->ppD3DObjects, g_pNegativeOnes );
208 else
210 // This call could be combined with the call to set render targets if both exist in the pass
211 m_pContext->OMSetRenderTargetsAndUnorderedAccessViews( D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, pUAVDep->StartIndex, pUAVDep->Count, pUAVDep->ppD3DObjects, g_pNegativeOnes );
215 // TBuffers are funny:
216 // We keep two references to them. One is in as a standard texture dep, and that gets used for all sets
217 // The other is as a part of the TBufferDeps array, which tells us to rebuild the matching CBs.
218 // These two refs could be rolled into one, but then we would have to predicate on each CB or each texture.
219 SConstantBuffer **ppTB = pBlock->ppTbufDeps;
220 SConstantBuffer **ppLastTB = ppTB + pBlock->TBufferDepCount;
222 for (; ppTB<ppLastTB; ppTB++)
224 CheckAndUpdateCB_FX(m_pContext, (SConstantBuffer*)*ppTB);
227 // Set the textures
228 SShaderResourceDependency *pResourceDep = pBlock->pResourceDeps;
229 SShaderResourceDependency *pLastResourceDep = pBlock->pResourceDeps + pBlock->ResourceDepCount;
231 for (; pResourceDep<pLastResourceDep; pResourceDep++)
233 assert(pResourceDep->ppFXPointers != 0);
234 _Analysis_assume_(pResourceDep->ppFXPointers != 0);
236 for (size_t i=0; i<pResourceDep->Count; i++)
238 pResourceDep->ppD3DObjects[i] = pResourceDep->ppFXPointers[i]->pShaderResource;
241 (m_pContext->*(pVT->pSetShaderResources))(pResourceDep->StartIndex, pResourceDep->Count, pResourceDep->ppD3DObjects);
244 // Update Interface dependencies
245 uint32_t Interfaces = 0;
246 ID3D11ClassInstance** ppClassInstances = nullptr;
247 assert( pBlock->InterfaceDepCount < 2 );
248 if( pBlock->InterfaceDepCount > 0 )
250 SInterfaceDependency *pInterfaceDep = pBlock->pInterfaceDeps;
251 assert(pInterfaceDep->ppFXPointers);
253 ppClassInstances = pInterfaceDep->ppD3DObjects;
254 Interfaces = pInterfaceDep->Count;
255 for (size_t i=0; i<pInterfaceDep->Count; i++)
257 assert(pInterfaceDep->ppFXPointers != 0);
258 _Analysis_assume_(pInterfaceDep->ppFXPointers != 0);
259 SClassInstanceGlobalVariable* pCI = pInterfaceDep->ppFXPointers[i]->pClassInstance;
260 if( pCI )
262 assert( pCI->pMemberData != 0 );
263 _Analysis_assume_( pCI->pMemberData != 0 );
264 pInterfaceDep->ppD3DObjects[i] = pCI->pMemberData->Data.pD3DClassInstance;
266 else
268 pInterfaceDep->ppD3DObjects[i] = nullptr;
273 // Now set the shader
274 (m_pContext->*(pVT->pSetShader))(pBlock->pD3DObject, ppClassInstances, Interfaces);
277 // Returns true if the block D3D data was recreated
278 bool CEffect::ApplyRenderStateBlock(_In_ SBaseBlock *pBlock)
280 if( pBlock->IsUserManaged )
282 return false;
285 bool bRecreate = pBlock->ApplyAssignments(this);
287 if (bRecreate)
289 switch (pBlock->BlockType)
291 case EBT_Sampler:
293 SSamplerBlock *pSBlock = pBlock->AsSampler();
295 assert(pSBlock->pD3DObject != 0);
296 _Analysis_assume_(pSBlock->pD3DObject != 0);
297 pSBlock->pD3DObject->Release();
299 HRESULT hr = m_pDevice->CreateSamplerState( &pSBlock->BackingStore.SamplerDesc, &pSBlock->pD3DObject );
300 if ( SUCCEEDED(hr) )
302 SetDebugObjectName(pSBlock->pD3DObject, "D3DX11Effect");
305 break;
307 case EBT_DepthStencil:
309 SDepthStencilBlock *pDSBlock = pBlock->AsDepthStencil();
311 assert(nullptr != pDSBlock->pDSObject);
312 SAFE_RELEASE( pDSBlock->pDSObject );
313 if( SUCCEEDED( m_pDevice->CreateDepthStencilState( &pDSBlock->BackingStore, &pDSBlock->pDSObject ) ) )
315 pDSBlock->IsValid = true;
316 SetDebugObjectName( pDSBlock->pDSObject, "D3DX11Effect" );
318 else
319 pDSBlock->IsValid = false;
321 break;
323 case EBT_Blend:
325 SBlendBlock *pBBlock = pBlock->AsBlend();
327 assert(nullptr != pBBlock->pBlendObject);
328 SAFE_RELEASE( pBBlock->pBlendObject );
329 if( SUCCEEDED( m_pDevice->CreateBlendState( &pBBlock->BackingStore, &pBBlock->pBlendObject ) ) )
331 pBBlock->IsValid = true;
332 SetDebugObjectName( pBBlock->pBlendObject, "D3DX11Effect" );
334 else
335 pBBlock->IsValid = false;
337 break;
339 case EBT_Rasterizer:
341 SRasterizerBlock *pRBlock = pBlock->AsRasterizer();
343 assert(nullptr != pRBlock->pRasterizerObject);
345 SAFE_RELEASE( pRBlock->pRasterizerObject );
346 if( SUCCEEDED( m_pDevice->CreateRasterizerState( &pRBlock->BackingStore, &pRBlock->pRasterizerObject ) ) )
348 pRBlock->IsValid = true;
349 SetDebugObjectName( pRBlock->pRasterizerObject, "D3DX11Effect" );
351 else
352 pRBlock->IsValid = false;
354 break;
356 default:
357 assert(0);
361 return bRecreate;
364 void CEffect::ValidateIndex(_In_ uint32_t Elements)
366 if (m_FXLIndex >= Elements)
368 DPF(0, "ID3DX11Effect: Overindexing variable array (size: %u, index: %u), using index = 0 instead", Elements, m_FXLIndex);
369 m_FXLIndex = 0;
373 // Returns true if the assignment was changed
374 bool CEffect::EvaluateAssignment(_Inout_ SAssignment *pAssignment)
376 bool bNeedUpdate = false;
377 SGlobalVariable *pVarDep0, *pVarDep1;
379 switch (pAssignment->AssignmentType)
381 case ERAT_NumericVariable:
382 assert(pAssignment->DependencyCount == 1);
383 if (pAssignment->pDependencies[0].pVariable->LastModifiedTime >= pAssignment->LastRecomputedTime)
385 memcpy(pAssignment->Destination.pNumeric, pAssignment->Source.pNumeric, pAssignment->DataSize);
386 bNeedUpdate = true;
388 break;
390 case ERAT_NumericVariableIndex:
391 assert(pAssignment->DependencyCount == 2);
392 pVarDep0 = pAssignment->pDependencies[0].pVariable;
393 pVarDep1 = pAssignment->pDependencies[1].pVariable;
395 if (pVarDep0->LastModifiedTime >= pAssignment->LastRecomputedTime)
397 m_FXLIndex = *pVarDep0->Data.pNumericDword;
399 ValidateIndex(pVarDep1->pType->Elements);
401 // Array index variable is dirty, update the pointer
402 pAssignment->Source.pNumeric = pVarDep1->Data.pNumeric + pVarDep1->pType->Stride * m_FXLIndex;
404 // Copy the new data
405 memcpy(pAssignment->Destination.pNumeric, pAssignment->Source.pNumeric, pAssignment->DataSize);
406 bNeedUpdate = true;
408 else if (pVarDep1->LastModifiedTime >= pAssignment->LastRecomputedTime)
410 // Only the array variable is dirty, copy the new data
411 memcpy(pAssignment->Destination.pNumeric, pAssignment->Source.pNumeric, pAssignment->DataSize);
412 bNeedUpdate = true;
414 break;
416 case ERAT_ObjectVariableIndex:
417 assert(pAssignment->DependencyCount == 1);
418 pVarDep0 = pAssignment->pDependencies[0].pVariable;
419 if (pVarDep0->LastModifiedTime >= pAssignment->LastRecomputedTime)
421 m_FXLIndex = *pVarDep0->Data.pNumericDword;
422 ValidateIndex(pAssignment->MaxElements);
424 // Array index variable is dirty, update the destination pointer
425 *((void **)pAssignment->Destination.pGeneric) = pAssignment->Source.pNumeric +
426 pAssignment->DataSize * m_FXLIndex;
427 bNeedUpdate = true;
429 break;
431 default:
432 //case ERAT_Constant: -- These are consumed and discarded
433 //case ERAT_ObjectVariable: -- These are consumed and discarded
434 //case ERAT_ObjectConstIndex: -- These are consumed and discarded
435 //case ERAT_ObjectInlineShader: -- These are consumed and discarded
436 //case ERAT_NumericConstIndex: -- ERAT_NumericVariable should be generated instead
437 assert(0);
438 break;
441 // Mark the assignment as not dirty
442 pAssignment->LastRecomputedTime = m_LocalTimer;
444 return bNeedUpdate;
447 // Returns false if this shader has interface dependencies which are nullptr (SetShader will fail).
448 bool CEffect::ValidateShaderBlock( _Inout_ SShaderBlock* pBlock )
450 if( !pBlock->IsValid )
451 return false;
452 if( pBlock->InterfaceDepCount > 0 )
454 assert( pBlock->InterfaceDepCount == 1 );
455 for( size_t i=0; i < pBlock->pInterfaceDeps[0].Count; i++ )
457 SInterface* pInterfaceDep = pBlock->pInterfaceDeps[0].ppFXPointers[i];
458 assert( pInterfaceDep != 0 );
459 _Analysis_assume_( pInterfaceDep != 0 );
460 if( pInterfaceDep->pClassInstance == nullptr )
462 return false;
466 return true;
469 // Returns false if any state in the pass is invalid
470 bool CEffect::ValidatePassBlock( _Inout_ SPassBlock* pBlock )
472 pBlock->ApplyPassAssignments();
474 if (nullptr != pBlock->BackingStore.pBlendBlock)
476 ApplyRenderStateBlock(pBlock->BackingStore.pBlendBlock);
477 pBlock->BackingStore.pBlendState = pBlock->BackingStore.pBlendBlock->pBlendObject;
478 if( !pBlock->BackingStore.pBlendBlock->IsValid )
479 return false;
482 if( nullptr != pBlock->BackingStore.pDepthStencilBlock )
484 ApplyRenderStateBlock( pBlock->BackingStore.pDepthStencilBlock );
485 pBlock->BackingStore.pDepthStencilState = pBlock->BackingStore.pDepthStencilBlock->pDSObject;
486 if( !pBlock->BackingStore.pDepthStencilBlock->IsValid )
487 return false;
490 if( nullptr != pBlock->BackingStore.pRasterizerBlock )
492 ApplyRenderStateBlock( pBlock->BackingStore.pRasterizerBlock );
493 if( !pBlock->BackingStore.pRasterizerBlock->IsValid )
494 return false;
497 if( nullptr != pBlock->BackingStore.pVertexShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pVertexShaderBlock) )
498 return false;
500 if( nullptr != pBlock->BackingStore.pGeometryShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pGeometryShaderBlock) )
501 return false;
503 if( nullptr != pBlock->BackingStore.pPixelShaderBlock )
505 if( !ValidateShaderBlock(pBlock->BackingStore.pPixelShaderBlock) )
506 return false;
507 else if( pBlock->BackingStore.pPixelShaderBlock->UAVDepCount > 0 &&
508 pBlock->BackingStore.RenderTargetViewCount > pBlock->BackingStore.pPixelShaderBlock->pUAVDeps[0].StartIndex )
510 return false;
514 if( nullptr != pBlock->BackingStore.pHullShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pHullShaderBlock) )
515 return false;
517 if( nullptr != pBlock->BackingStore.pDomainShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pDomainShaderBlock) )
518 return false;
520 if( nullptr != pBlock->BackingStore.pComputeShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pComputeShaderBlock) )
521 return false;
523 return true;
526 // Set all state defined in the pass
527 void CEffect::ApplyPassBlock(_Inout_ SPassBlock *pBlock)
529 pBlock->ApplyPassAssignments();
531 if (nullptr != pBlock->BackingStore.pBlendBlock)
533 ApplyRenderStateBlock(pBlock->BackingStore.pBlendBlock);
534 #ifdef FXDEBUG
535 if( !pBlock->BackingStore.pBlendBlock->IsValid )
536 DPF( 0, "Pass::Apply - warning: applying invalid BlendState." );
537 #endif
538 pBlock->BackingStore.pBlendState = pBlock->BackingStore.pBlendBlock->pBlendObject;
539 m_pContext->OMSetBlendState(pBlock->BackingStore.pBlendState,
540 pBlock->BackingStore.BlendFactor,
541 pBlock->BackingStore.SampleMask);
544 if (nullptr != pBlock->BackingStore.pDepthStencilBlock)
546 ApplyRenderStateBlock(pBlock->BackingStore.pDepthStencilBlock);
547 #ifdef FXDEBUG
548 if( !pBlock->BackingStore.pDepthStencilBlock->IsValid )
549 DPF( 0, "Pass::Apply - warning: applying invalid DepthStencilState." );
550 #endif
551 pBlock->BackingStore.pDepthStencilState = pBlock->BackingStore.pDepthStencilBlock->pDSObject;
552 m_pContext->OMSetDepthStencilState(pBlock->BackingStore.pDepthStencilState,
553 pBlock->BackingStore.StencilRef);
556 if (nullptr != pBlock->BackingStore.pRasterizerBlock)
558 ApplyRenderStateBlock(pBlock->BackingStore.pRasterizerBlock);
559 #ifdef FXDEBUG
560 if( !pBlock->BackingStore.pRasterizerBlock->IsValid )
561 DPF( 0, "Pass::Apply - warning: applying invalid RasterizerState." );
562 #endif
563 m_pContext->RSSetState(pBlock->BackingStore.pRasterizerBlock->pRasterizerObject);
566 if (nullptr != pBlock->BackingStore.pRenderTargetViews[0])
568 // Grab all render targets
569 ID3D11RenderTargetView *pRTV[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
571 assert(pBlock->BackingStore.RenderTargetViewCount <= D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
572 _Analysis_assume_(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT >= pBlock->BackingStore.RenderTargetViewCount);
574 for (uint32_t i=0; i<pBlock->BackingStore.RenderTargetViewCount; i++)
576 pRTV[i] = pBlock->BackingStore.pRenderTargetViews[i]->pRenderTargetView;
579 // This call could be combined with the call to set PS UAVs if both exist in the pass
580 m_pContext->OMSetRenderTargetsAndUnorderedAccessViews( pBlock->BackingStore.RenderTargetViewCount, pRTV, pBlock->BackingStore.pDepthStencilView->pDepthStencilView, 7, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, nullptr, nullptr );
583 if (nullptr != pBlock->BackingStore.pVertexShaderBlock)
585 #ifdef FXDEBUG
586 if( !pBlock->BackingStore.pVertexShaderBlock->IsValid )
587 DPF( 0, "Pass::Apply - warning: applying invalid vertex shader." );
588 #endif
589 ApplyShaderBlock(pBlock->BackingStore.pVertexShaderBlock);
592 if (nullptr != pBlock->BackingStore.pPixelShaderBlock)
594 #ifdef FXDEBUG
595 if( !pBlock->BackingStore.pPixelShaderBlock->IsValid )
596 DPF( 0, "Pass::Apply - warning: applying invalid pixel shader." );
597 #endif
598 ApplyShaderBlock(pBlock->BackingStore.pPixelShaderBlock);
601 if (nullptr != pBlock->BackingStore.pGeometryShaderBlock)
603 #ifdef FXDEBUG
604 if( !pBlock->BackingStore.pGeometryShaderBlock->IsValid )
605 DPF( 0, "Pass::Apply - warning: applying invalid geometry shader." );
606 #endif
607 ApplyShaderBlock(pBlock->BackingStore.pGeometryShaderBlock);
610 if (nullptr != pBlock->BackingStore.pHullShaderBlock)
612 #ifdef FXDEBUG
613 if( !pBlock->BackingStore.pHullShaderBlock->IsValid )
614 DPF( 0, "Pass::Apply - warning: applying invalid hull shader." );
615 #endif
616 ApplyShaderBlock(pBlock->BackingStore.pHullShaderBlock);
619 if (nullptr != pBlock->BackingStore.pDomainShaderBlock)
621 #ifdef FXDEBUG
622 if( !pBlock->BackingStore.pDomainShaderBlock->IsValid )
623 DPF( 0, "Pass::Apply - warning: applying invalid domain shader." );
624 #endif
625 ApplyShaderBlock(pBlock->BackingStore.pDomainShaderBlock);
628 if (nullptr != pBlock->BackingStore.pComputeShaderBlock)
630 #ifdef FXDEBUG
631 if( !pBlock->BackingStore.pComputeShaderBlock->IsValid )
632 DPF( 0, "Pass::Apply - warning: applying invalid compute shader." );
633 #endif
634 ApplyShaderBlock(pBlock->BackingStore.pComputeShaderBlock);
638 void CEffect::IncrementTimer()
640 m_LocalTimer++;
642 #if !defined(_M_X64) && !defined(_M_ARM64)
643 #ifdef _DEBUG
644 if (m_LocalTimer > g_TimerRolloverCount)
646 DPF(0, "Rolling over timer (current time: %zu, rollover cap: %u).", m_LocalTimer, g_TimerRolloverCount);
647 #else
648 if (m_LocalTimer >= 0x80000000) // check to see if we've exceeded ~2 billion
650 #endif
651 HandleLocalTimerRollover();
653 m_LocalTimer = 1;
655 #endif // _M_X64
658 // This function resets all timers, rendering all assignments dirty
659 // This is clearly bad for performance, but should only happen every few billion ticks
660 void CEffect::HandleLocalTimerRollover()
662 uint32_t i, j, k;
664 // step 1: update variables
665 for (i = 0; i < m_VariableCount; ++ i)
667 m_pVariables[i].LastModifiedTime = 0;
670 // step 2: update assignments on all blocks (pass, depth stencil, rasterizer, blend, sampler)
671 for (uint32_t iGroup = 0; iGroup < m_GroupCount; ++ iGroup)
673 for (i = 0; i < m_pGroups[iGroup].TechniqueCount; ++ i)
675 for (j = 0; j < m_pGroups[iGroup].pTechniques[i].PassCount; ++ j)
677 for (k = 0; k < m_pGroups[iGroup].pTechniques[i].pPasses[j].AssignmentCount; ++ k)
679 m_pGroups[iGroup].pTechniques[i].pPasses[j].pAssignments[k].LastRecomputedTime = 0;
685 for (i = 0; i < m_DepthStencilBlockCount; ++ i)
687 for (j = 0; j < m_pDepthStencilBlocks[i].AssignmentCount; ++ j)
689 m_pDepthStencilBlocks[i].pAssignments[j].LastRecomputedTime = 0;
693 for (i = 0; i < m_RasterizerBlockCount; ++ i)
695 for (j = 0; j < m_pRasterizerBlocks[i].AssignmentCount; ++ j)
697 m_pRasterizerBlocks[i].pAssignments[j].LastRecomputedTime = 0;
701 for (i = 0; i < m_BlendBlockCount; ++ i)
703 for (j = 0; j < m_pBlendBlocks[i].AssignmentCount; ++ j)
705 m_pBlendBlocks[i].pAssignments[j].LastRecomputedTime = 0;
709 for (i = 0; i < m_SamplerBlockCount; ++ i)
711 for (j = 0; j < m_pSamplerBlocks[i].AssignmentCount; ++ j)
713 m_pSamplerBlocks[i].pAssignments[j].LastRecomputedTime = 0;