1 //////////////////////////////////////////////////////////////////////////////
\r
3 // Copyright (C) Microsoft Corporation. All Rights Reserved.
\r
5 // File: EffectRuntime.cpp
\r
6 // Content: D3DX11 Effect runtime routines (performance critical)
\r
7 // These functions are expected to be called at high frequency
\r
8 // (when applying a pass).
\r
10 //////////////////////////////////////////////////////////////////////////////
\r
14 namespace D3DX11Effects
\r
16 // D3D11_KEEP_UNORDERED_ACCESS_VIEWS == (UINT)-1
\r
17 UINT g_pNegativeOnes[8] = { D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS,
\r
18 D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS,
\r
19 D3D11_KEEP_UNORDERED_ACCESS_VIEWS, D3D11_KEEP_UNORDERED_ACCESS_VIEWS };
\r
21 BOOL SBaseBlock::ApplyAssignments(CEffect *pEffect)
\r
23 SAssignment *pAssignment = pAssignments;
\r
24 SAssignment *pLastAssn = pAssignments + AssignmentCount;
\r
25 BOOL bRecreate = FALSE;
\r
27 for(; pAssignment < pLastAssn; pAssignment++)
\r
29 bRecreate |= pEffect->EvaluateAssignment(pAssignment);
\r
35 void SPassBlock::ApplyPassAssignments()
\r
37 SAssignment *pAssignment = pAssignments;
\r
38 SAssignment *pLastAssn = pAssignments + AssignmentCount;
\r
40 pEffect->IncrementTimer();
\r
42 for(; pAssignment < pLastAssn; pAssignment++)
\r
44 pEffect->EvaluateAssignment(pAssignment);
\r
48 // Returns TRUE if the shader uses global interfaces (since these interfaces can be updated through SetClassInstance)
\r
49 BOOL SPassBlock::CheckShaderDependencies( SShaderBlock* pBlock )
\r
51 if( pBlock->InterfaceDepCount > 0 )
\r
53 D3DXASSERT( pBlock->InterfaceDepCount == 1 );
\r
54 for( UINT i=0; i < pBlock->pInterfaceDeps[0].Count; i++ )
\r
56 SInterface* pInterfaceDep = pBlock->pInterfaceDeps[0].ppFXPointers[i];
\r
57 if( pInterfaceDep > pEffect->m_pInterfaces && pInterfaceDep < (pEffect->m_pInterfaces + pEffect->m_InterfaceCount) )
\r
59 // This is a global interface pointer (as opposed to an SInterface created in a BindInterface call
\r
67 // Returns TRUE if the pass (and sets HasDependencies) if the pass sets objects whose backing stores can be updated
\r
68 BOOL SPassBlock::CheckDependencies()
\r
70 if( HasDependencies )
\r
73 for( UINT i=0; i < AssignmentCount; i++ )
\r
75 if( pAssignments[i].DependencyCount > 0 )
\r
76 return HasDependencies = TRUE;
\r
78 if( BackingStore.pBlendBlock && BackingStore.pBlendBlock->AssignmentCount > 0 )
\r
80 for( UINT i=0; i < BackingStore.pBlendBlock->AssignmentCount; i++ )
\r
82 if( BackingStore.pBlendBlock->pAssignments[i].DependencyCount > 0 )
\r
83 return HasDependencies = TRUE;
\r
86 if( BackingStore.pDepthStencilBlock && BackingStore.pDepthStencilBlock->AssignmentCount > 0 )
\r
88 for( UINT i=0; i < BackingStore.pDepthStencilBlock->AssignmentCount; i++ )
\r
90 if( BackingStore.pDepthStencilBlock->pAssignments[i].DependencyCount > 0 )
\r
91 return HasDependencies = TRUE;
\r
94 if( BackingStore.pRasterizerBlock && BackingStore.pRasterizerBlock->AssignmentCount > 0 )
\r
96 for( UINT i=0; i < BackingStore.pRasterizerBlock->AssignmentCount; i++ )
\r
98 if( BackingStore.pRasterizerBlock->pAssignments[i].DependencyCount > 0 )
\r
99 return HasDependencies = TRUE;
\r
102 if( BackingStore.pVertexShaderBlock && CheckShaderDependencies( BackingStore.pVertexShaderBlock ) )
\r
104 return HasDependencies = TRUE;
\r
106 if( BackingStore.pGeometryShaderBlock && CheckShaderDependencies( BackingStore.pGeometryShaderBlock ) )
\r
108 return HasDependencies = TRUE;
\r
110 if( BackingStore.pPixelShaderBlock && CheckShaderDependencies( BackingStore.pPixelShaderBlock ) )
\r
112 return HasDependencies = TRUE;
\r
114 if( BackingStore.pHullShaderBlock && CheckShaderDependencies( BackingStore.pHullShaderBlock ) )
\r
116 return HasDependencies = TRUE;
\r
118 if( BackingStore.pDomainShaderBlock && CheckShaderDependencies( BackingStore.pDomainShaderBlock ) )
\r
120 return HasDependencies = TRUE;
\r
122 if( BackingStore.pComputeShaderBlock && CheckShaderDependencies( BackingStore.pComputeShaderBlock ) )
\r
124 return HasDependencies = TRUE;
\r
127 return HasDependencies;
\r
131 // Update constant buffer contents if necessary
\r
132 D3DX11INLINE void CheckAndUpdateCB_FX(ID3D11DeviceContext *pContext, SConstantBuffer *pCB)
\r
134 if (pCB->IsDirty && !pCB->IsNonUpdatable)
\r
136 // CB out of date; rebuild it
\r
137 pContext->UpdateSubresource(pCB->pD3DObject, 0, NULL, pCB->pBackingStore, pCB->Size, pCB->Size);
\r
138 pCB->IsDirty = FALSE;
\r
143 // Set the shader and dependent state (SRVs, samplers, UAVs, interfaces)
\r
144 void CEffect::ApplyShaderBlock(SShaderBlock *pBlock)
\r
148 SD3DShaderVTable *pVT = pBlock->pVT;
\r
150 // Apply constant buffers first (tbuffers are done later)
\r
151 SShaderCBDependency *pCBDep = pBlock->pCBDeps;
\r
152 SShaderCBDependency *pLastCBDep = pBlock->pCBDeps + pBlock->CBDepCount;
\r
154 for (; pCBDep<pLastCBDep; pCBDep++)
\r
156 D3DXASSERT(pCBDep->ppFXPointers);
\r
158 for (i = 0; i < pCBDep->Count; ++ i)
\r
160 CheckAndUpdateCB_FX(m_pContext, (SConstantBuffer*)pCBDep->ppFXPointers[i]);
\r
163 (m_pContext->*(pVT->pSetConstantBuffers))(pCBDep->StartIndex, pCBDep->Count, pCBDep->ppD3DObjects);
\r
166 // Next, apply samplers
\r
167 SShaderSamplerDependency *pSampDep = pBlock->pSampDeps;
\r
168 SShaderSamplerDependency *pLastSampDep = pBlock->pSampDeps + pBlock->SampDepCount;
\r
170 for (; pSampDep<pLastSampDep; pSampDep++)
\r
172 D3DXASSERT(pSampDep->ppFXPointers);
\r
174 for (i=0; i<pSampDep->Count; i++)
\r
176 if ( ApplyRenderStateBlock(pSampDep->ppFXPointers[i]) )
\r
178 // If the sampler was updated, its pointer will have changed
\r
179 pSampDep->ppD3DObjects[i] = pSampDep->ppFXPointers[i]->pD3DObject;
\r
182 (m_pContext->*(pVT->pSetSamplers))(pSampDep->StartIndex, pSampDep->Count, pSampDep->ppD3DObjects);
\r
186 // UAV ranges were combined in EffectLoad. This code remains unchanged, however, so that ranges can be easily split
\r
187 D3DXASSERT( pBlock->UAVDepCount < 2 );
\r
188 if( pBlock->UAVDepCount > 0 )
\r
190 SUnorderedAccessViewDependency *pUAVDep = pBlock->pUAVDeps;
\r
191 D3DXASSERT(pUAVDep->ppFXPointers);
\r
193 for (i=0; i<pUAVDep->Count; i++)
\r
195 pUAVDep->ppD3DObjects[i] = pUAVDep->ppFXPointers[i]->pUnorderedAccessView;
\r
198 if( EOT_ComputeShader5 == pBlock->GetShaderType() )
\r
200 m_pContext->CSSetUnorderedAccessViews( pUAVDep->StartIndex, pUAVDep->Count, pUAVDep->ppD3DObjects, g_pNegativeOnes );
\r
204 // This call could be combined with the call to set render targets if both exist in the pass
\r
205 m_pContext->OMSetRenderTargetsAndUnorderedAccessViews( D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, NULL, NULL, pUAVDep->StartIndex, pUAVDep->Count, pUAVDep->ppD3DObjects, g_pNegativeOnes );
\r
209 // TBuffers are funny:
\r
210 // We keep two references to them. One is in as a standard texture dep, and that gets used for all sets
\r
211 // The other is as a part of the TBufferDeps array, which tells us to rebuild the matching CBs.
\r
212 // These two refs could be rolled into one, but then we would have to predicate on each CB or each texture.
\r
213 SConstantBuffer **ppTB = pBlock->ppTbufDeps;
\r
214 SConstantBuffer **ppLastTB = ppTB + pBlock->TBufferDepCount;
\r
216 for (; ppTB<ppLastTB; ppTB++)
\r
218 CheckAndUpdateCB_FX(m_pContext, (SConstantBuffer*)*ppTB);
\r
221 // Set the textures
\r
222 SShaderResourceDependency *pResourceDep = pBlock->pResourceDeps;
\r
223 SShaderResourceDependency *pLastResourceDep = pBlock->pResourceDeps + pBlock->ResourceDepCount;
\r
225 for (; pResourceDep<pLastResourceDep; pResourceDep++)
\r
227 D3DXASSERT(pResourceDep->ppFXPointers);
\r
229 for (i=0; i<pResourceDep->Count; i++)
\r
231 pResourceDep->ppD3DObjects[i] = pResourceDep->ppFXPointers[i]->pShaderResource;
\r
234 (m_pContext->*(pVT->pSetShaderResources))(pResourceDep->StartIndex, pResourceDep->Count, pResourceDep->ppD3DObjects);
\r
237 // Update Interface dependencies
\r
238 UINT Interfaces = 0;
\r
239 ID3D11ClassInstance** ppClassInstances = NULL;
\r
240 D3DXASSERT( pBlock->InterfaceDepCount < 2 );
\r
241 if( pBlock->InterfaceDepCount > 0 )
\r
243 SInterfaceDependency *pInterfaceDep = pBlock->pInterfaceDeps;
\r
244 D3DXASSERT(pInterfaceDep->ppFXPointers);
\r
246 ppClassInstances = pInterfaceDep->ppD3DObjects;
\r
247 Interfaces = pInterfaceDep->Count;
\r
248 for (i=0; i<pInterfaceDep->Count; i++)
\r
250 SClassInstanceGlobalVariable* pCI = pInterfaceDep->ppFXPointers[i]->pClassInstance;
\r
253 D3DXASSERT( pCI->pMemberData != NULL );
\r
254 pInterfaceDep->ppD3DObjects[i] = pCI->pMemberData->Data.pD3DClassInstance;
\r
258 pInterfaceDep->ppD3DObjects[i] = NULL;
\r
263 // Now set the shader
\r
264 (m_pContext->*(pVT->pSetShader))(pBlock->pD3DObject, ppClassInstances, Interfaces);
\r
267 // Returns TRUE if the block D3D data was recreated
\r
268 BOOL CEffect::ApplyRenderStateBlock(SBaseBlock *pBlock)
\r
270 if( pBlock->IsUserManaged )
\r
275 BOOL bRecreate = pBlock->ApplyAssignments(this);
\r
279 switch (pBlock->BlockType)
\r
283 SSamplerBlock *pSBlock = pBlock->AsSampler();
\r
285 D3DXASSERT(NULL != pSBlock->pD3DObject);
\r
286 pSBlock->pD3DObject->Release();
\r
288 m_pDevice->CreateSamplerState( &pSBlock->BackingStore.SamplerDesc, &pSBlock->pD3DObject );
\r
293 case EBT_DepthStencil:
\r
295 SDepthStencilBlock *pDSBlock = pBlock->AsDepthStencil();
\r
297 D3DXASSERT(NULL != pDSBlock->pDSObject);
\r
298 SAFE_RELEASE( pDSBlock->pDSObject );
\r
299 if( SUCCEEDED( m_pDevice->CreateDepthStencilState( &pDSBlock->BackingStore, &pDSBlock->pDSObject ) ) )
\r
300 pDSBlock->IsValid = TRUE;
\r
302 pDSBlock->IsValid = FALSE;
\r
308 SBlendBlock *pBBlock = pBlock->AsBlend();
\r
310 D3DXASSERT(NULL != pBBlock->pBlendObject);
\r
311 SAFE_RELEASE( pBBlock->pBlendObject );
\r
312 if( SUCCEEDED( m_pDevice->CreateBlendState( &pBBlock->BackingStore, &pBBlock->pBlendObject ) ) )
\r
313 pBBlock->IsValid = TRUE;
\r
315 pBBlock->IsValid = FALSE;
\r
319 case EBT_Rasterizer:
\r
321 SRasterizerBlock *pRBlock = pBlock->AsRasterizer();
\r
323 D3DXASSERT(NULL != pRBlock->pRasterizerObject);
\r
325 SAFE_RELEASE( pRBlock->pRasterizerObject );
\r
326 if( SUCCEEDED( m_pDevice->CreateRasterizerState( &pRBlock->BackingStore, &pRBlock->pRasterizerObject ) ) )
\r
327 pRBlock->IsValid = TRUE;
\r
329 pRBlock->IsValid = FALSE;
\r
341 void CEffect::ValidateIndex(UINT Elements)
\r
343 if (m_FXLIndex >= Elements)
\r
345 DPF(0, "ID3DX11Effect: Overindexing variable array (size: %d, index: %d), using index = 0 instead", Elements, m_FXLIndex);
\r
350 // Returns TRUE if the assignment was changed
\r
351 BOOL CEffect::EvaluateAssignment(SAssignment *pAssignment)
\r
353 BOOL bNeedUpdate = FALSE;
\r
354 SGlobalVariable *pVarDep0, *pVarDep1;
\r
356 switch (pAssignment->AssignmentType)
\r
358 case ERAT_NumericVariable:
\r
359 D3DXASSERT(pAssignment->DependencyCount == 1);
\r
360 if (pAssignment->pDependencies[0].pVariable->LastModifiedTime >= pAssignment->LastRecomputedTime)
\r
362 dwordMemcpy(pAssignment->Destination.pNumeric, pAssignment->Source.pNumeric, pAssignment->DataSize);
\r
363 bNeedUpdate = TRUE;
\r
367 case ERAT_NumericVariableIndex:
\r
368 D3DXASSERT(pAssignment->DependencyCount == 2);
\r
369 pVarDep0 = pAssignment->pDependencies[0].pVariable;
\r
370 pVarDep1 = pAssignment->pDependencies[1].pVariable;
\r
372 if (pVarDep0->LastModifiedTime >= pAssignment->LastRecomputedTime)
\r
374 m_FXLIndex = *pVarDep0->Data.pNumericDword;
\r
376 ValidateIndex(pVarDep1->pType->Elements);
\r
378 // Array index variable is dirty, update the pointer
\r
379 pAssignment->Source.pNumeric = pVarDep1->Data.pNumeric + pVarDep1->pType->Stride * m_FXLIndex;
\r
381 // Copy the new data
\r
382 dwordMemcpy(pAssignment->Destination.pNumeric, pAssignment->Source.pNumeric, pAssignment->DataSize);
\r
383 bNeedUpdate = TRUE;
\r
385 else if (pVarDep1->LastModifiedTime >= pAssignment->LastRecomputedTime)
\r
387 // Only the array variable is dirty, copy the new data
\r
388 dwordMemcpy(pAssignment->Destination.pNumeric, pAssignment->Source.pNumeric, pAssignment->DataSize);
\r
389 bNeedUpdate = TRUE;
\r
393 case ERAT_ObjectVariableIndex:
\r
394 D3DXASSERT(pAssignment->DependencyCount == 1);
\r
395 pVarDep0 = pAssignment->pDependencies[0].pVariable;
\r
396 if (pVarDep0->LastModifiedTime >= pAssignment->LastRecomputedTime)
\r
398 m_FXLIndex = *pVarDep0->Data.pNumericDword;
\r
399 ValidateIndex(pAssignment->MaxElements);
\r
401 // Array index variable is dirty, update the destination pointer
\r
402 *((void **)pAssignment->Destination.pGeneric) = pAssignment->Source.pNumeric +
\r
403 pAssignment->DataSize * m_FXLIndex;
\r
404 bNeedUpdate = TRUE;
\r
409 //case ERAT_Constant: -- These are consumed and discarded
\r
410 //case ERAT_ObjectVariable: -- These are consumed and discarded
\r
411 //case ERAT_ObjectConstIndex: -- These are consumed and discarded
\r
412 //case ERAT_ObjectInlineShader: -- These are consumed and discarded
\r
413 //case ERAT_NumericConstIndex: -- ERAT_NumericVariable should be generated instead
\r
418 // Mark the assignment as not dirty
\r
419 pAssignment->LastRecomputedTime = m_LocalTimer;
\r
421 return bNeedUpdate;
\r
424 // Returns FALSE if this shader has interface dependencies which are NULL (SetShader will fail).
\r
425 BOOL CEffect::ValidateShaderBlock( SShaderBlock* pBlock )
\r
427 if( !pBlock->IsValid )
\r
429 if( pBlock->InterfaceDepCount > 0 )
\r
431 D3DXASSERT( pBlock->InterfaceDepCount == 1 );
\r
432 for( UINT i=0; i < pBlock->pInterfaceDeps[0].Count; i++ )
\r
434 SInterface* pInterfaceDep = pBlock->pInterfaceDeps[0].ppFXPointers[i];
\r
435 D3DXASSERT( pInterfaceDep != NULL );
\r
436 if( pInterfaceDep->pClassInstance == NULL )
\r
445 // Returns FALSE if any state in the pass is invalid
\r
446 BOOL CEffect::ValidatePassBlock( SPassBlock* pBlock )
\r
448 pBlock->ApplyPassAssignments();
\r
450 if (NULL != pBlock->BackingStore.pBlendBlock)
\r
452 ApplyRenderStateBlock(pBlock->BackingStore.pBlendBlock);
\r
453 pBlock->BackingStore.pBlendState = pBlock->BackingStore.pBlendBlock->pBlendObject;
\r
454 if( !pBlock->BackingStore.pBlendBlock->IsValid )
\r
458 if( NULL != pBlock->BackingStore.pDepthStencilBlock )
\r
460 ApplyRenderStateBlock( pBlock->BackingStore.pDepthStencilBlock );
\r
461 pBlock->BackingStore.pDepthStencilState = pBlock->BackingStore.pDepthStencilBlock->pDSObject;
\r
462 if( !pBlock->BackingStore.pDepthStencilBlock->IsValid )
\r
466 if( NULL != pBlock->BackingStore.pRasterizerBlock )
\r
468 ApplyRenderStateBlock( pBlock->BackingStore.pRasterizerBlock );
\r
469 if( !pBlock->BackingStore.pRasterizerBlock->IsValid )
\r
473 if( NULL != pBlock->BackingStore.pVertexShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pVertexShaderBlock) )
\r
476 if( NULL != pBlock->BackingStore.pGeometryShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pGeometryShaderBlock) )
\r
479 if( NULL != pBlock->BackingStore.pPixelShaderBlock )
\r
481 if( !ValidateShaderBlock(pBlock->BackingStore.pPixelShaderBlock) )
\r
483 else if( pBlock->BackingStore.pPixelShaderBlock->UAVDepCount > 0 &&
\r
484 pBlock->BackingStore.RenderTargetViewCount > pBlock->BackingStore.pPixelShaderBlock->pUAVDeps[0].StartIndex )
\r
490 if( NULL != pBlock->BackingStore.pHullShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pHullShaderBlock) )
\r
493 if( NULL != pBlock->BackingStore.pDomainShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pDomainShaderBlock) )
\r
496 if( NULL != pBlock->BackingStore.pComputeShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pComputeShaderBlock) )
\r
502 // Set all state defined in the pass
\r
503 void CEffect::ApplyPassBlock(SPassBlock *pBlock)
\r
505 pBlock->ApplyPassAssignments();
\r
507 if (NULL != pBlock->BackingStore.pBlendBlock)
\r
509 ApplyRenderStateBlock(pBlock->BackingStore.pBlendBlock);
\r
511 if( !pBlock->BackingStore.pBlendBlock->IsValid )
\r
512 DPF( 0, "Pass::Apply - warning: applying invalid BlendState." );
\r
514 pBlock->BackingStore.pBlendState = pBlock->BackingStore.pBlendBlock->pBlendObject;
\r
515 m_pContext->OMSetBlendState(pBlock->BackingStore.pBlendState,
\r
516 pBlock->BackingStore.BlendFactor,
\r
517 pBlock->BackingStore.SampleMask);
\r
520 if (NULL != pBlock->BackingStore.pDepthStencilBlock)
\r
522 ApplyRenderStateBlock(pBlock->BackingStore.pDepthStencilBlock);
\r
524 if( !pBlock->BackingStore.pDepthStencilBlock->IsValid )
\r
525 DPF( 0, "Pass::Apply - warning: applying invalid DepthStencilState." );
\r
527 pBlock->BackingStore.pDepthStencilState = pBlock->BackingStore.pDepthStencilBlock->pDSObject;
\r
528 m_pContext->OMSetDepthStencilState(pBlock->BackingStore.pDepthStencilState,
\r
529 pBlock->BackingStore.StencilRef);
\r
532 if (NULL != pBlock->BackingStore.pRasterizerBlock)
\r
534 ApplyRenderStateBlock(pBlock->BackingStore.pRasterizerBlock);
\r
536 if( !pBlock->BackingStore.pRasterizerBlock->IsValid )
\r
537 DPF( 0, "Pass::Apply - warning: applying invalid RasterizerState." );
\r
539 m_pContext->RSSetState(pBlock->BackingStore.pRasterizerBlock->pRasterizerObject);
\r
542 if (NULL != pBlock->BackingStore.pRenderTargetViews[0])
\r
544 // Grab all render targets
\r
545 ID3D11RenderTargetView *pRTV[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
\r
547 D3DXASSERT(pBlock->BackingStore.RenderTargetViewCount <= D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);
\r
548 __analysis_assume(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT >= pBlock->BackingStore.RenderTargetViewCount);
\r
550 for (UINT i=0; i<pBlock->BackingStore.RenderTargetViewCount; i++)
\r
552 pRTV[i] = pBlock->BackingStore.pRenderTargetViews[i]->pRenderTargetView;
\r
555 // This call could be combined with the call to set PS UAVs if both exist in the pass
\r
556 m_pContext->OMSetRenderTargetsAndUnorderedAccessViews( pBlock->BackingStore.RenderTargetViewCount, pRTV, pBlock->BackingStore.pDepthStencilView->pDepthStencilView, 7, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, NULL, NULL );
\r
559 if (NULL != pBlock->BackingStore.pVertexShaderBlock)
\r
562 if( !pBlock->BackingStore.pVertexShaderBlock->IsValid )
\r
563 DPF( 0, "Pass::Apply - warning: applying invalid vertex shader." );
\r
565 ApplyShaderBlock(pBlock->BackingStore.pVertexShaderBlock);
\r
568 if (NULL != pBlock->BackingStore.pPixelShaderBlock)
\r
571 if( !pBlock->BackingStore.pPixelShaderBlock->IsValid )
\r
572 DPF( 0, "Pass::Apply - warning: applying invalid pixel shader." );
\r
574 ApplyShaderBlock(pBlock->BackingStore.pPixelShaderBlock);
\r
577 if (NULL != pBlock->BackingStore.pGeometryShaderBlock)
\r
580 if( !pBlock->BackingStore.pGeometryShaderBlock->IsValid )
\r
581 DPF( 0, "Pass::Apply - warning: applying invalid geometry shader." );
\r
583 ApplyShaderBlock(pBlock->BackingStore.pGeometryShaderBlock);
\r
586 if (NULL != pBlock->BackingStore.pHullShaderBlock)
\r
589 if( !pBlock->BackingStore.pHullShaderBlock->IsValid )
\r
590 DPF( 0, "Pass::Apply - warning: applying invalid hull shader." );
\r
592 ApplyShaderBlock(pBlock->BackingStore.pHullShaderBlock);
\r
595 if (NULL != pBlock->BackingStore.pDomainShaderBlock)
\r
598 if( !pBlock->BackingStore.pDomainShaderBlock->IsValid )
\r
599 DPF( 0, "Pass::Apply - warning: applying invalid domain shader." );
\r
601 ApplyShaderBlock(pBlock->BackingStore.pDomainShaderBlock);
\r
604 if (NULL != pBlock->BackingStore.pComputeShaderBlock)
\r
607 if( !pBlock->BackingStore.pComputeShaderBlock->IsValid )
\r
608 DPF( 0, "Pass::Apply - warning: applying invalid compute shader." );
\r
610 ApplyShaderBlock(pBlock->BackingStore.pComputeShaderBlock);
\r
614 void CEffect::IncrementTimer()
\r
619 #if _DEBUG && FXDEBUG
\r
620 if (m_LocalTimer > g_TimerRolloverCount)
\r
622 DPF(0, "Rolling over timer (current time: %d, rollover cap: %d).", m_LocalTimer, g_TimerRolloverCount);
\r
623 #else // else !(_DEBUG && FXDEBUG)
\r
624 if (m_LocalTimer >= 0x80000000) // check to see if we've exceeded ~2 billion
\r
626 #endif // _DEBUG && FXDEBUG
\r
627 HandleLocalTimerRollover();
\r
634 // This function resets all timers, rendering all assignments dirty
\r
635 // This is clearly bad for performance, but should only happen every few billion ticks
\r
636 void CEffect::HandleLocalTimerRollover()
\r
640 // step 1: update variables
\r
641 for (i = 0; i < m_VariableCount; ++ i)
\r
643 m_pVariables[i].LastModifiedTime = 0;
\r
646 // step 2: update assignments on all blocks (pass, depth stencil, rasterizer, blend, sampler)
\r
647 for (UINT iGroup = 0; iGroup < m_GroupCount; ++ iGroup)
\r
649 for (i = 0; i < m_pGroups[iGroup].TechniqueCount; ++ i)
\r
651 for (j = 0; j < m_pGroups[iGroup].pTechniques[i].PassCount; ++ j)
\r
653 for (k = 0; k < m_pGroups[iGroup].pTechniques[i].pPasses[j].AssignmentCount; ++ k)
\r
655 m_pGroups[iGroup].pTechniques[i].pPasses[j].pAssignments[k].LastRecomputedTime = 0;
\r
661 for (i = 0; i < m_DepthStencilBlockCount; ++ i)
\r
663 for (j = 0; j < m_pDepthStencilBlocks[i].AssignmentCount; ++ j)
\r
665 m_pDepthStencilBlocks[i].pAssignments[j].LastRecomputedTime = 0;
\r
669 for (i = 0; i < m_RasterizerBlockCount; ++ i)
\r
671 for (j = 0; j < m_pRasterizerBlocks[i].AssignmentCount; ++ j)
\r
673 m_pRasterizerBlocks[i].pAssignments[j].LastRecomputedTime = 0;
\r
677 for (i = 0; i < m_BlendBlockCount; ++ i)
\r
679 for (j = 0; j < m_pBlendBlocks[i].AssignmentCount; ++ j)
\r
681 m_pBlendBlocks[i].pAssignments[j].LastRecomputedTime = 0;
\r
685 for (i = 0; i < m_SamplerBlockCount; ++ i)
\r
687 for (j = 0; j < m_pSamplerBlocks[i].AssignmentCount; ++ j)
\r
689 m_pSamplerBlocks[i].pAssignments[j].LastRecomputedTime = 0;
\r