1 //--------------------------------------------------------------------------------------
2 // File: EffectRuntime.cpp
4 // Direct3D 11 Effect runtime routines (performance critical)
5 // These functions are expected to be called at high frequency
6 // (when applying a pass).
8 // Copyright (c) Microsoft Corporation.
9 // Licensed under the MIT License.
11 // http://go.microsoft.com/fwlink/p/?LinkId=271568
12 //--------------------------------------------------------------------------------------
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
);
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
69 // Returns true if the pass (and sets HasDependencies) if the pass sets objects whose backing stores can be updated
71 #pragma warning(disable: 4616 6282)
72 bool SPassBlock::CheckDependencies()
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
;
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
);
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
);
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
);
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
;
262 assert( pCI
->pMemberData
!= 0 );
263 _Analysis_assume_( pCI
->pMemberData
!= 0 );
264 pInterfaceDep
->ppD3DObjects
[i
] = pCI
->pMemberData
->Data
.pD3DClassInstance
;
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
)
285 bool bRecreate
= pBlock
->ApplyAssignments(this);
289 switch (pBlock
->BlockType
)
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
);
302 SetDebugObjectName(pSBlock
->pD3DObject
, "D3DX11Effect");
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" );
319 pDSBlock
->IsValid
= false;
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" );
335 pBBlock
->IsValid
= false;
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" );
352 pRBlock
->IsValid
= false;
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
);
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
);
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
;
405 memcpy(pAssignment
->Destination
.pNumeric
, pAssignment
->Source
.pNumeric
, pAssignment
->DataSize
);
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
);
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
;
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
441 // Mark the assignment as not dirty
442 pAssignment
->LastRecomputedTime
= m_LocalTimer
;
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
)
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 )
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
)
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
)
490 if( nullptr != pBlock
->BackingStore
.pRasterizerBlock
)
492 ApplyRenderStateBlock( pBlock
->BackingStore
.pRasterizerBlock
);
493 if( !pBlock
->BackingStore
.pRasterizerBlock
->IsValid
)
497 if( nullptr != pBlock
->BackingStore
.pVertexShaderBlock
&& !ValidateShaderBlock(pBlock
->BackingStore
.pVertexShaderBlock
) )
500 if( nullptr != pBlock
->BackingStore
.pGeometryShaderBlock
&& !ValidateShaderBlock(pBlock
->BackingStore
.pGeometryShaderBlock
) )
503 if( nullptr != pBlock
->BackingStore
.pPixelShaderBlock
)
505 if( !ValidateShaderBlock(pBlock
->BackingStore
.pPixelShaderBlock
) )
507 else if( pBlock
->BackingStore
.pPixelShaderBlock
->UAVDepCount
> 0 &&
508 pBlock
->BackingStore
.RenderTargetViewCount
> pBlock
->BackingStore
.pPixelShaderBlock
->pUAVDeps
[0].StartIndex
)
514 if( nullptr != pBlock
->BackingStore
.pHullShaderBlock
&& !ValidateShaderBlock(pBlock
->BackingStore
.pHullShaderBlock
) )
517 if( nullptr != pBlock
->BackingStore
.pDomainShaderBlock
&& !ValidateShaderBlock(pBlock
->BackingStore
.pDomainShaderBlock
) )
520 if( nullptr != pBlock
->BackingStore
.pComputeShaderBlock
&& !ValidateShaderBlock(pBlock
->BackingStore
.pComputeShaderBlock
) )
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
);
535 if( !pBlock
->BackingStore
.pBlendBlock
->IsValid
)
536 DPF( 0, "Pass::Apply - warning: applying invalid BlendState." );
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
);
548 if( !pBlock
->BackingStore
.pDepthStencilBlock
->IsValid
)
549 DPF( 0, "Pass::Apply - warning: applying invalid DepthStencilState." );
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
);
560 if( !pBlock
->BackingStore
.pRasterizerBlock
->IsValid
)
561 DPF( 0, "Pass::Apply - warning: applying invalid RasterizerState." );
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
)
586 if( !pBlock
->BackingStore
.pVertexShaderBlock
->IsValid
)
587 DPF( 0, "Pass::Apply - warning: applying invalid vertex shader." );
589 ApplyShaderBlock(pBlock
->BackingStore
.pVertexShaderBlock
);
592 if (nullptr != pBlock
->BackingStore
.pPixelShaderBlock
)
595 if( !pBlock
->BackingStore
.pPixelShaderBlock
->IsValid
)
596 DPF( 0, "Pass::Apply - warning: applying invalid pixel shader." );
598 ApplyShaderBlock(pBlock
->BackingStore
.pPixelShaderBlock
);
601 if (nullptr != pBlock
->BackingStore
.pGeometryShaderBlock
)
604 if( !pBlock
->BackingStore
.pGeometryShaderBlock
->IsValid
)
605 DPF( 0, "Pass::Apply - warning: applying invalid geometry shader." );
607 ApplyShaderBlock(pBlock
->BackingStore
.pGeometryShaderBlock
);
610 if (nullptr != pBlock
->BackingStore
.pHullShaderBlock
)
613 if( !pBlock
->BackingStore
.pHullShaderBlock
->IsValid
)
614 DPF( 0, "Pass::Apply - warning: applying invalid hull shader." );
616 ApplyShaderBlock(pBlock
->BackingStore
.pHullShaderBlock
);
619 if (nullptr != pBlock
->BackingStore
.pDomainShaderBlock
)
622 if( !pBlock
->BackingStore
.pDomainShaderBlock
->IsValid
)
623 DPF( 0, "Pass::Apply - warning: applying invalid domain shader." );
625 ApplyShaderBlock(pBlock
->BackingStore
.pDomainShaderBlock
);
628 if (nullptr != pBlock
->BackingStore
.pComputeShaderBlock
)
631 if( !pBlock
->BackingStore
.pComputeShaderBlock
->IsValid
)
632 DPF( 0, "Pass::Apply - warning: applying invalid compute shader." );
634 ApplyShaderBlock(pBlock
->BackingStore
.pComputeShaderBlock
);
638 void CEffect::IncrementTimer()
642 #if !defined(_M_X64) && !defined(_M_ARM64)
644 if (m_LocalTimer
> g_TimerRolloverCount
)
646 DPF(0, "Rolling over timer (current time: %zu, rollover cap: %u).", m_LocalTimer
, g_TimerRolloverCount
);
648 if (m_LocalTimer
>= 0x80000000) // check to see if we've exceeded ~2 billion
651 HandleLocalTimerRollover();
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()
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;