2 // Copyright (c) Microsoft. All rights reserved.
3 // This code is licensed under the MIT License (MIT).
4 // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
5 // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
6 // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
7 // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
9 // Developed by Minigraph
11 // Author: James Stanard
15 #include "TemporalEffects.h"
16 #include "BufferManager.h"
17 #include "GraphicsCore.h"
18 #include "CommandContext.h"
19 #include "SystemTime.h"
20 #include "PostEffects.h"
22 #include "compiled_shaders/TemporalBlendCS.h"
23 #include "compiled_shaders/BoundNeighborhoodCS.h"
24 #include "compiled_shaders/ResolveTAACS.h"
25 #include "compiled_shaders/SharpenTAACS.h"
27 using namespace Graphics
;
29 using namespace TemporalEffects
;
31 namespace TemporalEffects
33 BoolVar
EnableTAA("Graphics/AA/TAA/Enable", false);
34 NumVar
Sharpness("Graphics/AA/TAA/Sharpness", 0.5f
, 0.0f
, 1.0f
, 0.25f
);
35 NumVar
TemporalMaxLerp("Graphics/AA/TAA/Blend Factor", 1.0f
, 0.0f
, 1.0f
, 0.01f
);
36 ExpVar
TemporalSpeedLimit("Graphics/AA/TAA/Speed Limit", 64.0f
, 1.0f
, 1024.0f
, 1.0f
);
37 BoolVar
TriggerReset("Graphics/AA/TAA/Reset", false);
39 RootSignature s_RootSignature
;
41 ComputePSO s_TemporalBlendCS
;
42 ComputePSO s_BoundNeighborhoodCS
;
43 ComputePSO s_SharpenTAACS
;
44 ComputePSO s_ResolveTAACS
;
46 uint32_t s_FrameIndex
= 0;
47 uint32_t s_FrameIndexMod2
= 0;
48 float s_JitterX
= 0.5f
;
49 float s_JitterY
= 0.5f
;
50 float s_JitterDeltaX
= 0.0f
;
51 float s_JitterDeltaY
= 0.0f
;
53 void ApplyTemporalAA(ComputeContext
& Context
);
54 void SharpenImage(ComputeContext
& Context
, ColorBuffer
& TemporalColor
);
57 void TemporalEffects::Initialize( void )
59 s_RootSignature
.Reset(4, 2);
60 s_RootSignature
[0].InitAsConstants(0, 4);
61 s_RootSignature
[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV
, 0, 10);
62 s_RootSignature
[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV
, 0, 10);
63 s_RootSignature
[3].InitAsConstantBuffer(1);
64 s_RootSignature
.InitStaticSampler(0, SamplerLinearBorderDesc
);
65 s_RootSignature
.InitStaticSampler(1, SamplerPointBorderDesc
);
66 s_RootSignature
.Finalize(L
"Temporal RS");
68 #define CreatePSO( ObjName, ShaderByteCode ) \
69 ObjName.SetRootSignature(s_RootSignature); \
70 ObjName.SetComputeShader(ShaderByteCode, sizeof(ShaderByteCode) ); \
73 CreatePSO( s_TemporalBlendCS
, g_pTemporalBlendCS
);
74 CreatePSO( s_BoundNeighborhoodCS
, g_pBoundNeighborhoodCS
);
75 CreatePSO( s_SharpenTAACS
, g_pSharpenTAACS
);
76 CreatePSO( s_ResolveTAACS
, g_pResolveTAACS
);
81 void TemporalEffects::Shutdown( void )
85 void TemporalEffects::Update( uint64_t FrameIndex
)
87 s_FrameIndex
= (uint32_t)FrameIndex
;
88 s_FrameIndexMod2
= s_FrameIndex
% 2;
90 if (EnableTAA
)// && !DepthOfField::Enable)
92 static const float Halton23
[8][2] =
94 { 0.0f
/ 8.0f
, 0.0f
/ 9.0f
}, { 4.0f
/ 8.0f
, 3.0f
/ 9.0f
},
95 { 2.0f
/ 8.0f
, 6.0f
/ 9.0f
}, { 6.0f
/ 8.0f
, 1.0f
/ 9.0f
},
96 { 1.0f
/ 8.0f
, 4.0f
/ 9.0f
}, { 5.0f
/ 8.0f
, 7.0f
/ 9.0f
},
97 { 3.0f
/ 8.0f
, 2.0f
/ 9.0f
}, { 7.0f
/ 8.0f
, 5.0f
/ 9.0f
}
100 const float* Offset
= Halton23
[s_FrameIndex
% 8];
102 s_JitterDeltaX
= s_JitterX
- Offset
[0];
103 s_JitterDeltaY
= s_JitterY
- Offset
[1];
104 s_JitterX
= Offset
[0];
105 s_JitterY
= Offset
[1];
109 s_JitterDeltaX
= s_JitterX
- 0.5f
;
110 s_JitterDeltaY
= s_JitterY
- 0.5f
;
117 uint32_t TemporalEffects::GetFrameIndexMod2( void )
119 return s_FrameIndexMod2
;
122 void TemporalEffects::GetJitterOffset( float& JitterX
, float& JitterY
)
128 void TemporalEffects::ClearHistory( CommandContext
& Context
)
130 GraphicsContext
& gfxContext
= Context
.GetGraphicsContext();
134 gfxContext
.TransitionResource(g_TemporalColor
[0], D3D12_RESOURCE_STATE_RENDER_TARGET
);
135 gfxContext
.TransitionResource(g_TemporalColor
[1], D3D12_RESOURCE_STATE_RENDER_TARGET
, true);
136 gfxContext
.ClearColor(g_TemporalColor
[0]);
137 gfxContext
.ClearColor(g_TemporalColor
[1]);
141 void TemporalEffects::ResolveImage( CommandContext
& BaseContext
)
143 ScopedTimer
_prof(L
"Temporal Resolve", BaseContext
);
145 ComputeContext
& Context
= BaseContext
.GetComputeContext();
147 static bool s_EnableTAA
= false;
149 if (EnableTAA
!= s_EnableTAA
|| TriggerReset
)
151 ClearHistory(Context
);
152 s_EnableTAA
= EnableTAA
;
153 TriggerReset
= false;
156 uint32_t Src
= s_FrameIndexMod2
;
157 uint32_t Dst
= Src
^ 1;
161 ApplyTemporalAA(Context
);
162 SharpenImage(Context
, g_TemporalColor
[Dst
]);
166 void TemporalEffects::ApplyTemporalAA(ComputeContext
& Context
)
168 ScopedTimer
_prof(L
"Resolve Image", Context
);
170 uint32_t Src
= s_FrameIndexMod2
;
171 uint32_t Dst
= Src
^ 1;
173 Context
.SetRootSignature(s_RootSignature
);
174 Context
.SetPipelineState(s_TemporalBlendCS
);
176 struct DECLSPEC_ALIGN(16) ConstantBuffer
178 float RcpBufferDim
[2];
179 float TemporalBlendFactor
;
180 float RcpSeedLimiter
;
181 float CombinedJitter
[2];
183 ConstantBuffer cbv
= {
184 1.0f
/ g_SceneColorBuffer
.GetWidth(), 1.0f
/ g_SceneColorBuffer
.GetHeight(),
185 (float)TemporalMaxLerp
, 1.0f
/ TemporalSpeedLimit
,
186 s_JitterDeltaX
, s_JitterDeltaY
189 Context
.SetDynamicConstantBufferView(3, sizeof(cbv
), &cbv
);
191 Context
.TransitionResource(g_VelocityBuffer
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
192 Context
.TransitionResource(g_SceneColorBuffer
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
193 Context
.TransitionResource(g_TemporalColor
[Src
], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
194 Context
.TransitionResource(g_TemporalColor
[Dst
], D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
195 Context
.TransitionResource(g_LinearDepth
[Src
], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
196 Context
.TransitionResource(g_LinearDepth
[Dst
], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
197 Context
.SetDynamicDescriptor(1, 0, g_VelocityBuffer
.GetSRV());
198 Context
.SetDynamicDescriptor(1, 1, g_SceneColorBuffer
.GetSRV());
199 Context
.SetDynamicDescriptor(1, 2, g_TemporalColor
[Src
].GetSRV());
200 Context
.SetDynamicDescriptor(1, 3, g_LinearDepth
[Src
].GetSRV());
201 Context
.SetDynamicDescriptor(1, 4, g_LinearDepth
[Dst
].GetSRV());
202 Context
.SetDynamicDescriptor(2, 0, g_TemporalColor
[Dst
].GetUAV());
204 Context
.Dispatch2D(g_SceneColorBuffer
.GetWidth(), g_SceneColorBuffer
.GetHeight(), 16, 8);
207 void TemporalEffects::SharpenImage(ComputeContext
& Context
, ColorBuffer
& TemporalColor
)
209 ScopedTimer
_prof(L
"Sharpen or Copy Image", Context
);
211 Context
.TransitionResource(g_SceneColorBuffer
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
212 Context
.TransitionResource(TemporalColor
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
214 Context
.SetPipelineState(Sharpness
>= 0.001f
? s_SharpenTAACS
: s_ResolveTAACS
);
215 Context
.SetConstants(0, 1.0f
+ Sharpness
, 0.25f
* Sharpness
);
216 Context
.SetDynamicDescriptor(1, 0, TemporalColor
.GetSRV());
217 Context
.SetDynamicDescriptor(2, 0, g_SceneColorBuffer
.GetUAV());
218 Context
.Dispatch2D(g_SceneColorBuffer
.GetWidth(), g_SceneColorBuffer
.GetHeight());