OSDN Git Service

d069c6e188924b7ca8ecc9828be43af5432eb35f
[dtxmania/dtxmania.git] / SlimDXc_Jun2010(VC++2008) / external / Effects11 / EffectRuntime.cpp
1 //////////////////////////////////////////////////////////////////////////////\r
2 //\r
3 //  Copyright (C) Microsoft Corporation.  All Rights Reserved.\r
4 //\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
9 //\r
10 //////////////////////////////////////////////////////////////////////////////\r
11 \r
12 #include "pchfx.h"\r
13 \r
14 namespace D3DX11Effects\r
15 {\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
20 \r
21 BOOL SBaseBlock::ApplyAssignments(CEffect *pEffect)\r
22 {\r
23     SAssignment *pAssignment = pAssignments;\r
24     SAssignment *pLastAssn = pAssignments + AssignmentCount;\r
25     BOOL bRecreate = FALSE;\r
26 \r
27     for(; pAssignment < pLastAssn; pAssignment++)\r
28     {\r
29         bRecreate |= pEffect->EvaluateAssignment(pAssignment);\r
30     }\r
31 \r
32     return bRecreate;\r
33 }\r
34 \r
35 void SPassBlock::ApplyPassAssignments()\r
36 {\r
37     SAssignment *pAssignment = pAssignments;\r
38     SAssignment *pLastAssn = pAssignments + AssignmentCount;\r
39 \r
40     pEffect->IncrementTimer();\r
41 \r
42     for(; pAssignment < pLastAssn; pAssignment++)\r
43     {\r
44         pEffect->EvaluateAssignment(pAssignment);\r
45     }\r
46 }\r
47 \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
50 {\r
51     if( pBlock->InterfaceDepCount > 0 )\r
52     {\r
53         D3DXASSERT( pBlock->InterfaceDepCount == 1 );\r
54         for( UINT i=0; i < pBlock->pInterfaceDeps[0].Count; i++ )\r
55         {\r
56             SInterface* pInterfaceDep = pBlock->pInterfaceDeps[0].ppFXPointers[i];\r
57             if( pInterfaceDep > pEffect->m_pInterfaces && pInterfaceDep < (pEffect->m_pInterfaces + pEffect->m_InterfaceCount) )\r
58             {\r
59                 // This is a global interface pointer (as opposed to an SInterface created in a BindInterface call\r
60                 return TRUE;\r
61             }\r
62         }\r
63     }\r
64     return FALSE;\r
65 }\r
66 \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
69 {\r
70     if( HasDependencies )\r
71         return TRUE;\r
72 \r
73     for( UINT i=0; i < AssignmentCount; i++ )\r
74     {\r
75         if( pAssignments[i].DependencyCount > 0 )\r
76             return HasDependencies = TRUE;\r
77     }\r
78     if( BackingStore.pBlendBlock && BackingStore.pBlendBlock->AssignmentCount > 0 )\r
79     {\r
80         for( UINT i=0; i < BackingStore.pBlendBlock->AssignmentCount; i++ )\r
81         {\r
82             if( BackingStore.pBlendBlock->pAssignments[i].DependencyCount > 0 )\r
83                 return HasDependencies = TRUE;\r
84         }\r
85     }\r
86     if( BackingStore.pDepthStencilBlock && BackingStore.pDepthStencilBlock->AssignmentCount > 0 )\r
87     {\r
88         for( UINT i=0; i < BackingStore.pDepthStencilBlock->AssignmentCount; i++ )\r
89         {\r
90             if( BackingStore.pDepthStencilBlock->pAssignments[i].DependencyCount > 0 )\r
91                 return HasDependencies = TRUE;\r
92         }\r
93     }\r
94     if( BackingStore.pRasterizerBlock && BackingStore.pRasterizerBlock->AssignmentCount > 0 )\r
95     {\r
96         for( UINT i=0; i < BackingStore.pRasterizerBlock->AssignmentCount; i++ )\r
97         {\r
98             if( BackingStore.pRasterizerBlock->pAssignments[i].DependencyCount > 0 )\r
99                 return HasDependencies = TRUE;\r
100         }\r
101     }\r
102     if( BackingStore.pVertexShaderBlock && CheckShaderDependencies( BackingStore.pVertexShaderBlock ) )\r
103     {\r
104         return HasDependencies = TRUE;\r
105     }\r
106     if( BackingStore.pGeometryShaderBlock && CheckShaderDependencies( BackingStore.pGeometryShaderBlock ) )\r
107     {\r
108         return HasDependencies = TRUE;\r
109     }\r
110     if( BackingStore.pPixelShaderBlock && CheckShaderDependencies( BackingStore.pPixelShaderBlock ) )\r
111     {\r
112         return HasDependencies = TRUE;\r
113     }\r
114     if( BackingStore.pHullShaderBlock && CheckShaderDependencies( BackingStore.pHullShaderBlock ) )\r
115     {\r
116         return HasDependencies = TRUE;\r
117     }\r
118     if( BackingStore.pDomainShaderBlock && CheckShaderDependencies( BackingStore.pDomainShaderBlock ) )\r
119     {\r
120         return HasDependencies = TRUE;\r
121     }\r
122     if( BackingStore.pComputeShaderBlock && CheckShaderDependencies( BackingStore.pComputeShaderBlock ) )\r
123     {\r
124         return HasDependencies = TRUE;\r
125     }\r
126 \r
127     return HasDependencies;\r
128 }\r
129 \r
130 \r
131 // Update constant buffer contents if necessary\r
132 D3DX11INLINE void CheckAndUpdateCB_FX(ID3D11DeviceContext *pContext, SConstantBuffer *pCB)\r
133 {\r
134     if (pCB->IsDirty && !pCB->IsNonUpdatable)\r
135     {\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
139     }\r
140 }\r
141 \r
142 \r
143 // Set the shader and dependent state (SRVs, samplers, UAVs, interfaces)\r
144 void CEffect::ApplyShaderBlock(SShaderBlock *pBlock)\r
145 {\r
146     UINT i;\r
147 \r
148     SD3DShaderVTable *pVT = pBlock->pVT;\r
149 \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
153 \r
154     for (; pCBDep<pLastCBDep; pCBDep++)\r
155     {\r
156         D3DXASSERT(pCBDep->ppFXPointers);\r
157 \r
158         for (i = 0; i < pCBDep->Count; ++ i)\r
159         {\r
160             CheckAndUpdateCB_FX(m_pContext, (SConstantBuffer*)pCBDep->ppFXPointers[i]);\r
161         }\r
162 \r
163         (m_pContext->*(pVT->pSetConstantBuffers))(pCBDep->StartIndex, pCBDep->Count, pCBDep->ppD3DObjects);\r
164     }\r
165 \r
166     // Next, apply samplers\r
167     SShaderSamplerDependency *pSampDep = pBlock->pSampDeps;\r
168     SShaderSamplerDependency *pLastSampDep = pBlock->pSampDeps + pBlock->SampDepCount;\r
169 \r
170     for (; pSampDep<pLastSampDep; pSampDep++)\r
171     {\r
172         D3DXASSERT(pSampDep->ppFXPointers);\r
173 \r
174         for (i=0; i<pSampDep->Count; i++)\r
175         {\r
176             if ( ApplyRenderStateBlock(pSampDep->ppFXPointers[i]) )\r
177             {\r
178                 // If the sampler was updated, its pointer will have changed\r
179                 pSampDep->ppD3DObjects[i] = pSampDep->ppFXPointers[i]->pD3DObject;\r
180             }\r
181         }\r
182         (m_pContext->*(pVT->pSetSamplers))(pSampDep->StartIndex, pSampDep->Count, pSampDep->ppD3DObjects);\r
183     }\r
184  \r
185     // Set the UAVs\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
189     {\r
190         SUnorderedAccessViewDependency *pUAVDep = pBlock->pUAVDeps;\r
191         D3DXASSERT(pUAVDep->ppFXPointers);\r
192 \r
193         for (i=0; i<pUAVDep->Count; i++)\r
194         {\r
195             pUAVDep->ppD3DObjects[i] = pUAVDep->ppFXPointers[i]->pUnorderedAccessView;\r
196         }\r
197 \r
198         if( EOT_ComputeShader5 == pBlock->GetShaderType() )\r
199         {\r
200             m_pContext->CSSetUnorderedAccessViews( pUAVDep->StartIndex, pUAVDep->Count, pUAVDep->ppD3DObjects, g_pNegativeOnes );\r
201         }\r
202         else\r
203         {\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
206         }\r
207     }\r
208 \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
215 \r
216     for (; ppTB<ppLastTB; ppTB++)\r
217     {\r
218         CheckAndUpdateCB_FX(m_pContext, (SConstantBuffer*)*ppTB);\r
219     }\r
220 \r
221     // Set the textures\r
222     SShaderResourceDependency *pResourceDep = pBlock->pResourceDeps;\r
223     SShaderResourceDependency *pLastResourceDep = pBlock->pResourceDeps + pBlock->ResourceDepCount;\r
224 \r
225     for (; pResourceDep<pLastResourceDep; pResourceDep++)\r
226     {\r
227         D3DXASSERT(pResourceDep->ppFXPointers);\r
228 \r
229         for (i=0; i<pResourceDep->Count; i++)\r
230         {\r
231             pResourceDep->ppD3DObjects[i] = pResourceDep->ppFXPointers[i]->pShaderResource;\r
232         }\r
233 \r
234         (m_pContext->*(pVT->pSetShaderResources))(pResourceDep->StartIndex, pResourceDep->Count, pResourceDep->ppD3DObjects);\r
235     }\r
236 \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
242     {\r
243         SInterfaceDependency *pInterfaceDep = pBlock->pInterfaceDeps;\r
244         D3DXASSERT(pInterfaceDep->ppFXPointers);\r
245 \r
246         ppClassInstances = pInterfaceDep->ppD3DObjects;\r
247         Interfaces = pInterfaceDep->Count;\r
248         for (i=0; i<pInterfaceDep->Count; i++)\r
249         {\r
250             SClassInstanceGlobalVariable* pCI = pInterfaceDep->ppFXPointers[i]->pClassInstance;\r
251             if( pCI )\r
252             {\r
253                 D3DXASSERT( pCI->pMemberData != NULL );\r
254                 pInterfaceDep->ppD3DObjects[i] = pCI->pMemberData->Data.pD3DClassInstance;\r
255             }\r
256             else\r
257             {\r
258                 pInterfaceDep->ppD3DObjects[i] = NULL;\r
259             }\r
260         }\r
261     }\r
262 \r
263     // Now set the shader\r
264     (m_pContext->*(pVT->pSetShader))(pBlock->pD3DObject, ppClassInstances, Interfaces);\r
265 }\r
266 \r
267 // Returns TRUE if the block D3D data was recreated\r
268 BOOL CEffect::ApplyRenderStateBlock(SBaseBlock *pBlock)\r
269 {\r
270     if( pBlock->IsUserManaged )\r
271     {\r
272         return FALSE;\r
273     }\r
274 \r
275     BOOL bRecreate = pBlock->ApplyAssignments(this);\r
276 \r
277     if (bRecreate)\r
278     {\r
279         switch (pBlock->BlockType)\r
280         {\r
281         case EBT_Sampler:\r
282             {\r
283                 SSamplerBlock *pSBlock = pBlock->AsSampler();\r
284 \r
285                 D3DXASSERT(NULL != pSBlock->pD3DObject);\r
286                 pSBlock->pD3DObject->Release();\r
287 \r
288                 m_pDevice->CreateSamplerState( &pSBlock->BackingStore.SamplerDesc, &pSBlock->pD3DObject );\r
289 \r
290             }\r
291             break;\r
292 \r
293         case EBT_DepthStencil:\r
294             {\r
295                 SDepthStencilBlock *pDSBlock = pBlock->AsDepthStencil();\r
296 \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
301                 else\r
302                     pDSBlock->IsValid = FALSE;\r
303             }\r
304             break;\r
305         \r
306         case EBT_Blend:\r
307             {\r
308                 SBlendBlock *pBBlock = pBlock->AsBlend();\r
309 \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
314                 else\r
315                     pBBlock->IsValid = FALSE;\r
316             }\r
317             break;\r
318 \r
319         case EBT_Rasterizer:\r
320             {\r
321                 SRasterizerBlock *pRBlock = pBlock->AsRasterizer();\r
322 \r
323                 D3DXASSERT(NULL != pRBlock->pRasterizerObject);\r
324 \r
325                 SAFE_RELEASE( pRBlock->pRasterizerObject );\r
326                 if( SUCCEEDED( m_pDevice->CreateRasterizerState( &pRBlock->BackingStore, &pRBlock->pRasterizerObject ) ) )\r
327                     pRBlock->IsValid = TRUE;\r
328                 else\r
329                     pRBlock->IsValid = FALSE;\r
330             }\r
331             break;\r
332         \r
333         default:\r
334             D3DXASSERT(0);\r
335         }\r
336     }\r
337 \r
338     return bRecreate;\r
339 }\r
340 \r
341 void CEffect::ValidateIndex(UINT  Elements)\r
342 {\r
343     if (m_FXLIndex >= Elements)\r
344     {\r
345         DPF(0, "ID3DX11Effect: Overindexing variable array (size: %d, index: %d), using index = 0 instead", Elements, m_FXLIndex);\r
346         m_FXLIndex = 0;\r
347     }\r
348 }\r
349 \r
350 // Returns TRUE if the assignment was changed\r
351 BOOL CEffect::EvaluateAssignment(SAssignment *pAssignment)\r
352 {\r
353     BOOL bNeedUpdate = FALSE;\r
354     SGlobalVariable *pVarDep0, *pVarDep1;\r
355     \r
356     switch (pAssignment->AssignmentType)\r
357     {\r
358     case ERAT_NumericVariable:\r
359         D3DXASSERT(pAssignment->DependencyCount == 1);\r
360         if (pAssignment->pDependencies[0].pVariable->LastModifiedTime >= pAssignment->LastRecomputedTime)\r
361         {\r
362             dwordMemcpy(pAssignment->Destination.pNumeric, pAssignment->Source.pNumeric, pAssignment->DataSize);\r
363             bNeedUpdate = TRUE;\r
364         }\r
365         break;\r
366 \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
371 \r
372         if (pVarDep0->LastModifiedTime >= pAssignment->LastRecomputedTime)\r
373         {\r
374             m_FXLIndex = *pVarDep0->Data.pNumericDword;\r
375 \r
376             ValidateIndex(pVarDep1->pType->Elements);\r
377 \r
378             // Array index variable is dirty, update the pointer\r
379             pAssignment->Source.pNumeric = pVarDep1->Data.pNumeric + pVarDep1->pType->Stride * m_FXLIndex;\r
380             \r
381             // Copy the new data\r
382             dwordMemcpy(pAssignment->Destination.pNumeric, pAssignment->Source.pNumeric, pAssignment->DataSize);\r
383             bNeedUpdate = TRUE;\r
384         }\r
385         else if (pVarDep1->LastModifiedTime >= pAssignment->LastRecomputedTime)\r
386         {\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
390         }\r
391         break;\r
392 \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
397         {\r
398             m_FXLIndex = *pVarDep0->Data.pNumericDword;\r
399             ValidateIndex(pAssignment->MaxElements);\r
400 \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
405         }\r
406         break;\r
407 \r
408     default:\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
414         D3DXASSERT(0);\r
415         break;\r
416     }\r
417     \r
418     // Mark the assignment as not dirty\r
419     pAssignment->LastRecomputedTime = m_LocalTimer;\r
420 \r
421     return bNeedUpdate;\r
422 }\r
423 \r
424 // Returns FALSE if this shader has interface dependencies which are NULL (SetShader will fail).\r
425 BOOL CEffect::ValidateShaderBlock( SShaderBlock* pBlock )\r
426 {\r
427     if( !pBlock->IsValid )\r
428         return FALSE;\r
429     if( pBlock->InterfaceDepCount > 0 )\r
430     {\r
431         D3DXASSERT( pBlock->InterfaceDepCount == 1 );\r
432         for( UINT i=0; i < pBlock->pInterfaceDeps[0].Count; i++ )\r
433         {\r
434             SInterface* pInterfaceDep = pBlock->pInterfaceDeps[0].ppFXPointers[i];\r
435             D3DXASSERT( pInterfaceDep != NULL );\r
436             if( pInterfaceDep->pClassInstance == NULL )\r
437             {\r
438                 return FALSE;\r
439             }\r
440         }\r
441     }\r
442     return TRUE;\r
443 }\r
444 \r
445 // Returns FALSE if any state in the pass is invalid\r
446 BOOL CEffect::ValidatePassBlock( SPassBlock* pBlock )\r
447 {\r
448     pBlock->ApplyPassAssignments();\r
449 \r
450     if (NULL != pBlock->BackingStore.pBlendBlock)\r
451     {\r
452         ApplyRenderStateBlock(pBlock->BackingStore.pBlendBlock);\r
453         pBlock->BackingStore.pBlendState = pBlock->BackingStore.pBlendBlock->pBlendObject;\r
454         if( !pBlock->BackingStore.pBlendBlock->IsValid )\r
455             return FALSE;\r
456     }\r
457 \r
458     if( NULL != pBlock->BackingStore.pDepthStencilBlock )\r
459     {\r
460         ApplyRenderStateBlock( pBlock->BackingStore.pDepthStencilBlock );\r
461         pBlock->BackingStore.pDepthStencilState = pBlock->BackingStore.pDepthStencilBlock->pDSObject;\r
462         if( !pBlock->BackingStore.pDepthStencilBlock->IsValid )\r
463             return FALSE;\r
464     }\r
465 \r
466     if( NULL != pBlock->BackingStore.pRasterizerBlock )\r
467     {\r
468         ApplyRenderStateBlock( pBlock->BackingStore.pRasterizerBlock );\r
469         if( !pBlock->BackingStore.pRasterizerBlock->IsValid )\r
470             return FALSE;\r
471     }\r
472 \r
473     if( NULL != pBlock->BackingStore.pVertexShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pVertexShaderBlock) )\r
474         return FALSE;\r
475 \r
476     if( NULL != pBlock->BackingStore.pGeometryShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pGeometryShaderBlock) )\r
477         return FALSE;\r
478 \r
479     if( NULL != pBlock->BackingStore.pPixelShaderBlock )\r
480     {\r
481         if( !ValidateShaderBlock(pBlock->BackingStore.pPixelShaderBlock) )\r
482             return FALSE;\r
483         else if( pBlock->BackingStore.pPixelShaderBlock->UAVDepCount > 0 && \r
484                  pBlock->BackingStore.RenderTargetViewCount > pBlock->BackingStore.pPixelShaderBlock->pUAVDeps[0].StartIndex )\r
485         {\r
486             return FALSE;\r
487         }\r
488     }\r
489 \r
490     if( NULL != pBlock->BackingStore.pHullShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pHullShaderBlock) )\r
491         return FALSE;\r
492 \r
493     if( NULL != pBlock->BackingStore.pDomainShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pDomainShaderBlock) )\r
494         return FALSE;\r
495 \r
496     if( NULL != pBlock->BackingStore.pComputeShaderBlock && !ValidateShaderBlock(pBlock->BackingStore.pComputeShaderBlock) )\r
497         return FALSE;\r
498 \r
499     return TRUE;\r
500 }\r
501 \r
502 // Set all state defined in the pass\r
503 void CEffect::ApplyPassBlock(SPassBlock *pBlock)\r
504 {\r
505     pBlock->ApplyPassAssignments();\r
506 \r
507     if (NULL != pBlock->BackingStore.pBlendBlock)\r
508     {\r
509         ApplyRenderStateBlock(pBlock->BackingStore.pBlendBlock);\r
510 #ifdef FXDEBUG\r
511         if( !pBlock->BackingStore.pBlendBlock->IsValid )\r
512             DPF( 0, "Pass::Apply - warning: applying invalid BlendState." );\r
513 #endif\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
518     }\r
519 \r
520     if (NULL != pBlock->BackingStore.pDepthStencilBlock)\r
521     {\r
522         ApplyRenderStateBlock(pBlock->BackingStore.pDepthStencilBlock);\r
523 #ifdef FXDEBUG\r
524         if( !pBlock->BackingStore.pDepthStencilBlock->IsValid )\r
525             DPF( 0, "Pass::Apply - warning: applying invalid DepthStencilState." );\r
526 #endif\r
527         pBlock->BackingStore.pDepthStencilState = pBlock->BackingStore.pDepthStencilBlock->pDSObject;\r
528         m_pContext->OMSetDepthStencilState(pBlock->BackingStore.pDepthStencilState,\r
529             pBlock->BackingStore.StencilRef);\r
530     }\r
531 \r
532     if (NULL != pBlock->BackingStore.pRasterizerBlock)\r
533     {\r
534         ApplyRenderStateBlock(pBlock->BackingStore.pRasterizerBlock);\r
535 #ifdef FXDEBUG\r
536         if( !pBlock->BackingStore.pRasterizerBlock->IsValid )\r
537             DPF( 0, "Pass::Apply - warning: applying invalid RasterizerState." );\r
538 #endif\r
539         m_pContext->RSSetState(pBlock->BackingStore.pRasterizerBlock->pRasterizerObject);\r
540     }\r
541 \r
542     if (NULL != pBlock->BackingStore.pRenderTargetViews[0])\r
543     {\r
544         // Grab all render targets\r
545         ID3D11RenderTargetView *pRTV[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];\r
546 \r
547         D3DXASSERT(pBlock->BackingStore.RenderTargetViewCount <= D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT);\r
548         __analysis_assume(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT >= pBlock->BackingStore.RenderTargetViewCount);\r
549 \r
550         for (UINT i=0; i<pBlock->BackingStore.RenderTargetViewCount; i++)\r
551         {\r
552             pRTV[i] = pBlock->BackingStore.pRenderTargetViews[i]->pRenderTargetView;\r
553         }\r
554 \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
557     }\r
558 \r
559     if (NULL != pBlock->BackingStore.pVertexShaderBlock)\r
560     {\r
561 #ifdef FXDEBUG\r
562         if( !pBlock->BackingStore.pVertexShaderBlock->IsValid )\r
563             DPF( 0, "Pass::Apply - warning: applying invalid vertex shader." );\r
564 #endif\r
565         ApplyShaderBlock(pBlock->BackingStore.pVertexShaderBlock);\r
566     }\r
567 \r
568     if (NULL != pBlock->BackingStore.pPixelShaderBlock)\r
569     {\r
570 #ifdef FXDEBUG\r
571         if( !pBlock->BackingStore.pPixelShaderBlock->IsValid )\r
572             DPF( 0, "Pass::Apply - warning: applying invalid pixel shader." );\r
573 #endif\r
574         ApplyShaderBlock(pBlock->BackingStore.pPixelShaderBlock);\r
575     }\r
576 \r
577     if (NULL != pBlock->BackingStore.pGeometryShaderBlock)\r
578     {\r
579 #ifdef FXDEBUG\r
580         if( !pBlock->BackingStore.pGeometryShaderBlock->IsValid )\r
581             DPF( 0, "Pass::Apply - warning: applying invalid geometry shader." );\r
582 #endif\r
583         ApplyShaderBlock(pBlock->BackingStore.pGeometryShaderBlock);\r
584     }\r
585 \r
586     if (NULL != pBlock->BackingStore.pHullShaderBlock)\r
587     {\r
588 #ifdef FXDEBUG\r
589         if( !pBlock->BackingStore.pHullShaderBlock->IsValid )\r
590             DPF( 0, "Pass::Apply - warning: applying invalid hull shader." );\r
591 #endif\r
592         ApplyShaderBlock(pBlock->BackingStore.pHullShaderBlock);\r
593     }\r
594 \r
595     if (NULL != pBlock->BackingStore.pDomainShaderBlock)\r
596     {\r
597 #ifdef FXDEBUG\r
598         if( !pBlock->BackingStore.pDomainShaderBlock->IsValid )\r
599             DPF( 0, "Pass::Apply - warning: applying invalid domain shader." );\r
600 #endif\r
601         ApplyShaderBlock(pBlock->BackingStore.pDomainShaderBlock);\r
602     }\r
603 \r
604     if (NULL != pBlock->BackingStore.pComputeShaderBlock)\r
605     {\r
606 #ifdef FXDEBUG\r
607         if( !pBlock->BackingStore.pComputeShaderBlock->IsValid )\r
608             DPF( 0, "Pass::Apply - warning: applying invalid compute shader." );\r
609 #endif\r
610         ApplyShaderBlock(pBlock->BackingStore.pComputeShaderBlock);\r
611     }\r
612 }\r
613 \r
614 void CEffect::IncrementTimer()\r
615 {\r
616     m_LocalTimer++;\r
617 \r
618 #ifndef _WIN64\r
619 #if _DEBUG && FXDEBUG\r
620     if (m_LocalTimer > g_TimerRolloverCount)\r
621     {\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
625     {\r
626 #endif // _DEBUG && FXDEBUG\r
627         HandleLocalTimerRollover();\r
628 \r
629         m_LocalTimer = 1;\r
630     }\r
631 #endif // _WIN64\r
632 }\r
633 \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
637 {\r
638     UINT  i, j, k;\r
639     \r
640     // step 1: update variables\r
641     for (i = 0; i < m_VariableCount; ++ i)\r
642     {\r
643         m_pVariables[i].LastModifiedTime = 0;\r
644     }\r
645 \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
648     {\r
649         for (i = 0; i < m_pGroups[iGroup].TechniqueCount; ++ i)\r
650         {\r
651             for (j = 0; j < m_pGroups[iGroup].pTechniques[i].PassCount; ++ j)\r
652             {\r
653                 for (k = 0; k < m_pGroups[iGroup].pTechniques[i].pPasses[j].AssignmentCount; ++ k)\r
654                 {\r
655                     m_pGroups[iGroup].pTechniques[i].pPasses[j].pAssignments[k].LastRecomputedTime = 0;\r
656                 }\r
657             }\r
658         }\r
659     }\r
660 \r
661     for (i = 0; i < m_DepthStencilBlockCount; ++ i)\r
662     {\r
663         for (j = 0; j < m_pDepthStencilBlocks[i].AssignmentCount; ++ j)\r
664         {\r
665             m_pDepthStencilBlocks[i].pAssignments[j].LastRecomputedTime = 0;\r
666         }\r
667     }\r
668 \r
669     for (i = 0; i < m_RasterizerBlockCount; ++ i)\r
670     {\r
671         for (j = 0; j < m_pRasterizerBlocks[i].AssignmentCount; ++ j)\r
672         {\r
673             m_pRasterizerBlocks[i].pAssignments[j].LastRecomputedTime = 0;\r
674         }\r
675     }\r
676 \r
677     for (i = 0; i < m_BlendBlockCount; ++ i)\r
678     {\r
679         for (j = 0; j < m_pBlendBlocks[i].AssignmentCount; ++ j)\r
680         {\r
681             m_pBlendBlocks[i].pAssignments[j].LastRecomputedTime = 0;\r
682         }\r
683     }\r
684 \r
685     for (i = 0; i < m_SamplerBlockCount; ++ i)\r
686     {\r
687         for (j = 0; j < m_pSamplerBlocks[i].AssignmentCount; ++ j)\r
688         {\r
689             m_pSamplerBlocks[i].pAssignments[j].LastRecomputedTime = 0;\r
690         }\r
691     }\r
692 }\r
693 \r
694 }\r