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
16 #include "PostEffects.h"
18 #include "CommandContext.h"
19 #include "RootSignature.h"
20 #include "PipelineState.h"
21 #include "GraphicsCore.h"
22 #include "BufferManager.h"
23 #include "MotionBlur.h"
24 #include "DepthOfField.h"
27 #include "compiled_shaders/ToneMapCS.h"
28 #include "compiled_shaders/ToneMap2CS.h"
29 #include "compiled_shaders/ToneMapHDRCS.h"
30 #include "compiled_shaders/ToneMapHDR2CS.h"
31 #include "compiled_shaders/ApplyBloomCS.h"
32 #include "compiled_shaders/ApplyBloom2CS.h"
33 #include "compiled_shaders/DebugLuminanceHdrCS.h"
34 #include "compiled_shaders/DebugLuminanceHdr2CS.h"
35 #include "compiled_shaders/DebugLuminanceLdrCS.h"
36 #include "compiled_shaders/DebugLuminanceLdr2CS.h"
37 #include "compiled_shaders/GenerateHistogramCS.h"
38 #include "compiled_shaders/DebugDrawHistogramCS.h"
39 #include "compiled_shaders/AdaptExposureCS.h"
40 #include "compiled_shaders/DownsampleBloomCS.h"
41 #include "compiled_shaders/DownsampleBloomAllCS.h"
42 #include "compiled_shaders/UpsampleAndBlurCS.h"
43 #include "compiled_shaders/BlurCS.h"
44 #include "compiled_shaders/BloomExtractAndDownsampleHdrCS.h"
45 #include "compiled_shaders/BloomExtractAndDownsampleLdrCS.h"
46 #include "compiled_shaders/ExtractLumaCS.h"
47 #include "compiled_shaders/AverageLumaCS.h"
48 #include "compiled_shaders/CopyBackPostBufferCS.h"
50 using namespace Graphics
;
54 extern BoolVar DebugDraw
;
59 extern BoolVar DebugDraw
;
62 namespace DepthOfField
64 extern BoolVar Enable
;
65 extern EnumVar DebugMode
;
70 const float kInitialMinLog
= -12.0f
;
71 const float kInitialMaxLog
= 4.0f
;
73 BoolVar
EnableHDR("Graphics/HDR/Enable", true);
74 BoolVar
EnableAdaptation("Graphics/HDR/Adaptive Exposure", true);
75 ExpVar
MinExposure("Graphics/HDR/Min Exposure", 1.0f
/ 64.0f
, -8.0f
, 0.0f
, 0.25f
);
76 ExpVar
MaxExposure("Graphics/HDR/Max Exposure", 64.0f
, 0.0f
, 8.0f
, 0.25f
);
77 NumVar
TargetLuminance("Graphics/HDR/Key", 0.08f
, 0.01f
, 0.99f
, 0.01f
);
78 NumVar
AdaptationRate("Graphics/HDR/Adaptation Rate", 0.05f
, 0.01f
, 1.0f
, 0.01f
);
79 ExpVar
Exposure("Graphics/HDR/Exposure", 2.0f
, -8.0f
, 8.0f
, 0.25f
);
80 BoolVar
DrawHistogram("Graphics/HDR/Draw Histogram", false);
82 BoolVar
BloomEnable("Graphics/Bloom/Enable", true);
83 NumVar
BloomThreshold("Graphics/Bloom/Threshold", 4.0f
, 0.0f
, 8.0f
, 0.1f
); // The threshold luminance above which a pixel will start to bloom
84 NumVar
BloomStrength("Graphics/Bloom/Strength", 0.1f
, 0.0f
, 2.0f
, 0.05f
); // A modulator controlling how much bloom is added back into the image
85 NumVar
BloomUpsampleFactor("Graphics/Bloom/Scatter", 0.65f
, 0.0f
, 1.0f
, 0.05f
); // Controls the "focus" of the blur. High values spread out more causing a haze.
86 BoolVar
HighQualityBloom("Graphics/Bloom/High Quality", true); // High quality blurs 5 octaves of bloom; low quality only blurs 3.
88 RootSignature PostEffectsRS
;
90 ComputePSO ToneMapHDRCS
;
91 ComputePSO ApplyBloomCS
;
92 ComputePSO DebugLuminanceHdrCS
;
93 ComputePSO DebugLuminanceLdrCS
;
94 ComputePSO GenerateHistogramCS
;
95 ComputePSO DrawHistogramCS
;
96 ComputePSO AdaptExposureCS
;
97 ComputePSO DownsampleBloom2CS
;
98 ComputePSO DownsampleBloom4CS
;
99 ComputePSO UpsampleAndBlurCS
;
101 ComputePSO BloomExtractAndDownsampleHdrCS
;
102 ComputePSO BloomExtractAndDownsampleLdrCS
;
103 ComputePSO ExtractLumaCS
;
104 ComputePSO AverageLumaCS
;
105 ComputePSO CopyBackPostBufferCS
;
107 StructuredBuffer g_Exposure
;
109 void UpdateExposure(ComputeContext
&);
110 void BlurBuffer(ComputeContext
&, ColorBuffer buffer
[2], const ColorBuffer
& lowerResBuf
, float upsampleBlendFactor
);
111 void GenerateBloom(ComputeContext
&);
112 void ExtractLuma(ComputeContext
&);
113 void ProcessHDR(ComputeContext
&);
114 void ProcessLDR(CommandContext
&);
117 void PostEffects::Initialize( void )
119 PostEffectsRS
.Reset(4, 2);
120 PostEffectsRS
.InitStaticSampler(0, SamplerLinearClampDesc
);
121 PostEffectsRS
.InitStaticSampler(1, SamplerLinearBorderDesc
);
122 PostEffectsRS
[0].InitAsConstants(0, 4);
123 PostEffectsRS
[1].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV
, 0, 4);
124 PostEffectsRS
[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV
, 0, 4);
125 PostEffectsRS
[3].InitAsConstantBuffer(1);
126 PostEffectsRS
.Finalize(L
"Post Effects");
128 #define CreatePSO( ObjName, ShaderByteCode ) \
129 ObjName.SetRootSignature(PostEffectsRS); \
130 ObjName.SetComputeShader(ShaderByteCode, sizeof(ShaderByteCode) ); \
133 if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT
)
135 CreatePSO(ToneMapCS
, g_pToneMap2CS
);
136 CreatePSO(ToneMapHDRCS
, g_pToneMapHDR2CS
);
137 CreatePSO(ApplyBloomCS
, g_pApplyBloom2CS
);
138 CreatePSO(DebugLuminanceHdrCS
, g_pDebugLuminanceHdr2CS
);
139 CreatePSO(DebugLuminanceLdrCS
, g_pDebugLuminanceLdr2CS
);
143 CreatePSO(ToneMapCS
, g_pToneMapCS
);
144 CreatePSO(ToneMapHDRCS
, g_pToneMapHDRCS
);
145 CreatePSO(ApplyBloomCS
, g_pApplyBloomCS
);
146 CreatePSO(DebugLuminanceHdrCS
, g_pDebugLuminanceHdrCS
);
147 CreatePSO(DebugLuminanceLdrCS
, g_pDebugLuminanceLdrCS
);
149 CreatePSO( GenerateHistogramCS
, g_pGenerateHistogramCS
);
150 CreatePSO( DrawHistogramCS
, g_pDebugDrawHistogramCS
);
151 CreatePSO( AdaptExposureCS
, g_pAdaptExposureCS
);
152 CreatePSO( DownsampleBloom2CS
, g_pDownsampleBloomCS
);
153 CreatePSO( DownsampleBloom4CS
, g_pDownsampleBloomAllCS
);
154 CreatePSO( UpsampleAndBlurCS
, g_pUpsampleAndBlurCS
);
155 CreatePSO( BlurCS
, g_pBlurCS
);
156 CreatePSO( BloomExtractAndDownsampleHdrCS
, g_pBloomExtractAndDownsampleHdrCS
);
157 CreatePSO( BloomExtractAndDownsampleLdrCS
, g_pBloomExtractAndDownsampleLdrCS
);
158 CreatePSO( ExtractLumaCS
, g_pExtractLumaCS
);
159 CreatePSO( AverageLumaCS
, g_pAverageLumaCS
);
160 CreatePSO( CopyBackPostBufferCS
, g_pCopyBackPostBufferCS
);
165 float DECLSPEC_ALIGN(16) initExposure
[] =
167 Exposure
, 1.0f
/ Exposure
, Exposure
, 0.0f
,
168 kInitialMinLog
, kInitialMaxLog
, kInitialMaxLog
- kInitialMinLog
, 1.0f
/ (kInitialMaxLog
- kInitialMinLog
)
170 g_Exposure
.Create(L
"Exposure", 8, 4, initExposure
);
173 MotionBlur::Initialize();
174 DepthOfField::Initialize();
177 void PostEffects::Shutdown( void )
179 g_Exposure
.Destroy();
182 MotionBlur::Shutdown();
183 DepthOfField::Shutdown();
186 void PostEffects::BlurBuffer( ComputeContext
& Context
, ColorBuffer buffer
[2], const ColorBuffer
& lowerResBuf
, float upsampleBlendFactor
)
188 // Set the shader constants
189 uint32_t bufferWidth
= buffer
[0].GetWidth();
190 uint32_t bufferHeight
= buffer
[0].GetHeight();
191 Context
.SetConstants(0, 1.0f
/ bufferWidth
, 1.0f
/ bufferHeight
, upsampleBlendFactor
);
193 // Set the input textures and output UAV
194 Context
.TransitionResource( buffer
[1], D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
195 Context
.SetDynamicDescriptor(1, 0, buffer
[1].GetUAV());
196 D3D12_CPU_DESCRIPTOR_HANDLE SRVs
[2] = { buffer
[0].GetSRV(), lowerResBuf
.GetSRV() };
197 Context
.SetDynamicDescriptors(2, 0, 2, SRVs
);
199 // Set the shader: upsample and blur or just blur
200 Context
.SetPipelineState(&buffer
[0] == &lowerResBuf
? BlurCS
: UpsampleAndBlurCS
);
202 // Dispatch the compute shader with default 8x8 thread groups
203 Context
.Dispatch2D(bufferWidth
, bufferHeight
);
205 Context
.TransitionResource( buffer
[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
208 //--------------------------------------------------------------------------------------
209 // Bloom effect in CS path
210 //--------------------------------------------------------------------------------------
211 void PostEffects::GenerateBloom( ComputeContext
& Context
)
213 ScopedTimer
_prof(L
"Generate Bloom", Context
);
215 // We can generate a bloom buffer up to 1/4 smaller in each dimension without undersampling. If only downsizing by 1/2 or less, a faster
216 // shader can be used which only does one bilinear sample.
218 uint32_t kBloomWidth
= g_LumaLR
.GetWidth();
219 uint32_t kBloomHeight
= g_LumaLR
.GetHeight();
221 // These bloom buffer dimensions were chosen for their impressive divisibility by 128 and because they are roughly 16:9.
222 // The blurring algorithm is exactly 9 pixels by 9 pixels, so if the aspect ratio of each pixel is not square, the blur
223 // will be oval in appearance rather than circular. Coincidentally, they are close to 1/2 of a 720p buffer and 1/3 of
224 // 1080p. This is a common size for a bloom buffer on consoles.
225 ASSERT(kBloomWidth
% 16 == 0 && kBloomHeight
% 16 == 0, "Bloom buffer dimensions must be multiples of 16");
228 Context
.SetConstants(0, 1.0f
/ kBloomWidth
, 1.0f
/ kBloomHeight
, (float)BloomThreshold
);
229 Context
.TransitionResource(g_aBloomUAV1
[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
230 Context
.TransitionResource(g_LumaLR
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
231 Context
.TransitionResource(g_SceneColorBuffer
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
232 Context
.TransitionResource(g_Exposure
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
236 Context
.SetDynamicDescriptor(1, 0, g_aBloomUAV1
[0].GetUAV());
237 Context
.SetDynamicDescriptor(1, 1, g_LumaLR
.GetUAV());
238 Context
.SetDynamicDescriptor(2, 0, g_SceneColorBuffer
.GetSRV());
239 Context
.SetDynamicDescriptor(2, 1, g_Exposure
.GetSRV());
241 Context
.SetPipelineState(EnableHDR
? BloomExtractAndDownsampleHdrCS
: BloomExtractAndDownsampleLdrCS
);
242 Context
.Dispatch2D(kBloomWidth
, kBloomHeight
);
245 Context
.TransitionResource(g_aBloomUAV1
[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
246 Context
.SetDynamicDescriptor(2, 0, g_aBloomUAV1
[0].GetSRV());
248 // The difference between high and low quality bloom is that high quality sums 5 octaves with a 2x frequency scale, and the low quality
249 // sums 3 octaves with a 4x frequency scale.
250 if (HighQualityBloom
)
252 Context
.TransitionResource(g_aBloomUAV2
[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
253 Context
.TransitionResource(g_aBloomUAV3
[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
254 Context
.TransitionResource(g_aBloomUAV4
[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
255 Context
.TransitionResource(g_aBloomUAV5
[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
258 D3D12_CPU_DESCRIPTOR_HANDLE UAVs
[4] = {
259 g_aBloomUAV2
[0].GetUAV(), g_aBloomUAV3
[0].GetUAV(), g_aBloomUAV4
[0].GetUAV(), g_aBloomUAV5
[0].GetUAV() };
260 Context
.SetDynamicDescriptors(1, 0, 4, UAVs
);
262 // Each dispatch group is 8x8 threads, but each thread reads in 2x2 source texels (bilinear filter).
263 Context
.SetPipelineState(DownsampleBloom4CS
);
264 Context
.Dispatch2D(kBloomWidth
/ 2, kBloomHeight
/ 2);
266 Context
.TransitionResource(g_aBloomUAV2
[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
267 Context
.TransitionResource(g_aBloomUAV3
[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
268 Context
.TransitionResource(g_aBloomUAV4
[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
269 Context
.TransitionResource(g_aBloomUAV5
[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
271 float upsampleBlendFactor
= BloomUpsampleFactor
;
273 // Blur then upsample and blur four times
274 BlurBuffer( Context
, g_aBloomUAV5
, g_aBloomUAV5
[0], 1.0f
);
275 BlurBuffer( Context
, g_aBloomUAV4
, g_aBloomUAV5
[1], upsampleBlendFactor
);
276 BlurBuffer( Context
, g_aBloomUAV3
, g_aBloomUAV4
[1], upsampleBlendFactor
);
277 BlurBuffer( Context
, g_aBloomUAV2
, g_aBloomUAV3
[1], upsampleBlendFactor
);
278 BlurBuffer( Context
, g_aBloomUAV1
, g_aBloomUAV2
[1], upsampleBlendFactor
);
283 D3D12_CPU_DESCRIPTOR_HANDLE UAVs
[2] = { g_aBloomUAV3
[0].GetUAV(), g_aBloomUAV5
[0].GetUAV() };
284 Context
.SetDynamicDescriptors(1, 0, 2, UAVs
);
286 Context
.TransitionResource(g_aBloomUAV3
[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
287 Context
.TransitionResource(g_aBloomUAV5
[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
289 // Each dispatch group is 8x8 threads, but each thread reads in 2x2 source texels (bilinear filter).
290 Context
.SetPipelineState(DownsampleBloom2CS
);
291 Context
.Dispatch2D(kBloomWidth
/ 2, kBloomHeight
/ 2);
293 Context
.TransitionResource(g_aBloomUAV3
[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
294 Context
.TransitionResource(g_aBloomUAV5
[0], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
296 float upsampleBlendFactor
= BloomUpsampleFactor
* 2.0f
/ 3.0f
;
298 // Blur then upsample and blur two times
299 BlurBuffer( Context
, g_aBloomUAV5
, g_aBloomUAV5
[0], 1.0f
);
300 BlurBuffer( Context
, g_aBloomUAV3
, g_aBloomUAV5
[1], upsampleBlendFactor
);
301 BlurBuffer( Context
, g_aBloomUAV1
, g_aBloomUAV3
[1], upsampleBlendFactor
);
305 void PostEffects::ExtractLuma( ComputeContext
& Context
)
307 ScopedTimer
_prof(L
"Extract Luma", Context
);
309 Context
.TransitionResource(g_LumaLR
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
310 Context
.TransitionResource(g_Exposure
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
311 Context
.SetConstants(0, 1.0f
/ g_LumaLR
.GetWidth(), 1.0f
/ g_LumaLR
.GetHeight());
312 Context
.SetDynamicDescriptor(1, 0, g_LumaLR
.GetUAV());
313 Context
.SetDynamicDescriptor(2, 0, g_SceneColorBuffer
.GetSRV());
314 Context
.SetDynamicDescriptor(2, 1, g_Exposure
.GetSRV());
315 Context
.SetPipelineState(ExtractLumaCS
);
316 Context
.Dispatch2D(g_LumaLR
.GetWidth(), g_LumaLR
.GetHeight());
319 void PostEffects::UpdateExposure( ComputeContext
& Context
)
321 ScopedTimer
_prof(L
"Update Exposure", Context
);
323 if (!EnableAdaptation
)
325 float DECLSPEC_ALIGN(16) initExposure
[] =
327 Exposure
, 1.0f
/ Exposure
, Exposure
, 0.0f
,
328 kInitialMinLog
, kInitialMaxLog
, kInitialMaxLog
- kInitialMinLog
, 1.0f
/ (kInitialMaxLog
- kInitialMinLog
)
330 Context
.WriteBuffer(g_Exposure
, 0, initExposure
, sizeof(initExposure
));
331 Context
.TransitionResource(g_Exposure
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
336 // Generate an HDR histogram
337 Context
.TransitionResource(g_Histogram
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
, true);
338 Context
.ClearUAV(g_Histogram
);
339 Context
.TransitionResource(g_LumaLR
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
340 Context
.SetDynamicDescriptor(1, 0, g_Histogram
.GetUAV() );
341 Context
.SetDynamicDescriptor(2, 0, g_LumaLR
.GetSRV() );
342 Context
.SetPipelineState(GenerateHistogramCS
);
343 Context
.Dispatch2D(g_LumaLR
.GetWidth(), g_LumaLR
.GetHeight(), 16, 384);
345 struct DECLSPEC_ALIGN(16)
347 float TargetLuminance
;
348 float AdaptationRate
;
354 TargetLuminance
, AdaptationRate
, MinExposure
, MaxExposure
,
355 g_LumaLR
.GetWidth() * g_LumaLR
.GetHeight()
357 Context
.TransitionResource(g_Histogram
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
358 Context
.TransitionResource(g_Exposure
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
359 Context
.SetDynamicDescriptor(1, 0, g_Exposure
.GetUAV());
360 Context
.SetDynamicDescriptor(2, 0, g_Histogram
.GetSRV());
361 Context
.SetDynamicConstantBufferView(3, sizeof(constants
), &constants
);
362 Context
.SetPipelineState(AdaptExposureCS
);
364 Context
.TransitionResource(g_Exposure
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
367 void PostEffects::ProcessHDR( ComputeContext
& Context
)
369 ScopedTimer
_prof(L
"HDR Tone Mapping", Context
);
373 GenerateBloom(Context
);
374 Context
.TransitionResource(g_aBloomUAV1
[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
376 else if (EnableAdaptation
)
377 ExtractLuma(Context
);
379 if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT
)
380 Context
.TransitionResource(g_SceneColorBuffer
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
382 Context
.TransitionResource(g_PostEffectsBuffer
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
384 Context
.TransitionResource(g_LumaBuffer
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
385 Context
.TransitionResource(g_Exposure
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
387 Context
.SetPipelineState(FXAA::DebugDraw
? DebugLuminanceHdrCS
: (g_bEnableHDROutput
? ToneMapHDRCS
: ToneMapCS
));
390 Context
.SetConstants(0, 1.0f
/ g_SceneColorBuffer
.GetWidth(), 1.0f
/ g_SceneColorBuffer
.GetHeight(),
391 (float)BloomStrength
);
393 // Separate out SDR result from its perceived luminance
394 if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT
)
395 Context
.SetDynamicDescriptor(1, 0, g_SceneColorBuffer
.GetUAV());
398 Context
.SetDynamicDescriptor(1, 0, g_PostEffectsBuffer
.GetUAV());
399 Context
.SetDynamicDescriptor(2, 2, g_SceneColorBuffer
.GetSRV());
401 Context
.SetDynamicDescriptor(1, 1, g_LumaBuffer
.GetUAV());
403 // Read in original HDR value and blurred bloom buffer
404 Context
.SetDynamicDescriptor(2, 0, g_Exposure
.GetSRV());
405 Context
.SetDynamicDescriptor(2, 1, BloomEnable
? g_aBloomUAV1
[1].GetSRV() : TextureManager::GetBlackTex2D().GetSRV());
407 Context
.Dispatch2D(g_SceneColorBuffer
.GetWidth(), g_SceneColorBuffer
.GetHeight());
409 // Do this last so that the bright pass uses the same exposure as tone mapping
410 UpdateExposure(Context
);
413 void PostEffects::ProcessLDR(CommandContext
& BaseContext
)
415 ScopedTimer
_prof(L
"SDR Processing", BaseContext
);
417 ComputeContext
& Context
= BaseContext
.GetComputeContext();
419 bool bGenerateBloom
= BloomEnable
&& !SSAO::DebugDraw
;
421 GenerateBloom(Context
);
423 if (bGenerateBloom
|| FXAA::DebugDraw
|| SSAO::DebugDraw
|| !g_bTypedUAVLoadSupport_R11G11B10_FLOAT
)
425 if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT
)
426 Context
.TransitionResource(g_SceneColorBuffer
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
428 Context
.TransitionResource(g_PostEffectsBuffer
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
430 Context
.TransitionResource(g_aBloomUAV1
[1], D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
431 Context
.TransitionResource(g_LumaBuffer
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
434 Context
.SetConstants(0, 1.0f
/ g_SceneColorBuffer
.GetWidth(), 1.0f
/ g_SceneColorBuffer
.GetHeight(),
435 (float)BloomStrength
);
437 // Separate out SDR result from its perceived luminance
438 if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT
)
439 Context
.SetDynamicDescriptor(1, 0, g_SceneColorBuffer
.GetUAV());
442 Context
.SetDynamicDescriptor(1, 0, g_PostEffectsBuffer
.GetUAV());
443 Context
.SetDynamicDescriptor(2, 2, g_SceneColorBuffer
.GetSRV());
445 Context
.SetDynamicDescriptor(1, 1, g_LumaBuffer
.GetUAV());
447 // Read in original SDR value and blurred bloom buffer
448 Context
.SetDynamicDescriptor(2, 0, bGenerateBloom
? g_aBloomUAV1
[1].GetSRV() : TextureManager::GetBlackTex2D().GetSRV());
450 Context
.SetPipelineState(FXAA::DebugDraw
? DebugLuminanceLdrCS
: ApplyBloomCS
);
451 Context
.Dispatch2D(g_SceneColorBuffer
.GetWidth(), g_SceneColorBuffer
.GetHeight());
453 Context
.TransitionResource(g_LumaBuffer
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
457 void PostEffects::CopyBackPostBuffer( ComputeContext
& Context
)
459 ScopedTimer
_prof(L
"Copy Post back to Scene", Context
);
460 Context
.SetRootSignature(PostEffectsRS
);
461 Context
.SetPipelineState(CopyBackPostBufferCS
);
462 Context
.TransitionResource(g_SceneColorBuffer
, D3D12_RESOURCE_STATE_UNORDERED_ACCESS
);
463 Context
.TransitionResource(g_PostEffectsBuffer
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
464 Context
.SetDynamicDescriptor(1, 0, g_SceneColorBuffer
.GetUAV());
465 Context
.SetDynamicDescriptor(2, 0, g_PostEffectsBuffer
.GetSRV());
466 Context
.Dispatch2D(g_SceneColorBuffer
.GetWidth(), g_SceneColorBuffer
.GetHeight());
469 void PostEffects::Render( void )
471 ComputeContext
& Context
= ComputeContext::Begin(L
"Post Effects");
473 Context
.SetRootSignature(PostEffectsRS
);
475 Context
.TransitionResource(g_SceneColorBuffer
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
| D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
);
477 if (EnableHDR
&& !SSAO::DebugDraw
&& !(DepthOfField::Enable
&& DepthOfField::DebugMode
>= 3))
482 bool bGeneratedLumaBuffer
= EnableHDR
|| FXAA::DebugDraw
|| BloomEnable
;
484 FXAA::Render(Context
, bGeneratedLumaBuffer
);
486 // In the case where we've been doing post processing in a separate buffer, we need to copy it
487 // back to the original buffer. It is possible to skip this step if the next shader knows to
488 // do the manual format decode from UINT, but there are several code paths that need to be
489 // changed, and some of them rely on texture filtering, which won't work with UINT. Since this
490 // is only to support legacy hardware and a single buffer copy isn't that big of a deal, this
491 // is the most economical solution.
492 if (!g_bTypedUAVLoadSupport_R11G11B10_FLOAT
)
493 CopyBackPostBuffer(Context
);
497 ScopedTimer
_prof(L
"Draw Debug Histogram", Context
);
498 Context
.SetRootSignature(PostEffectsRS
);
499 Context
.SetPipelineState(DrawHistogramCS
);
500 Context
.InsertUAVBarrier(g_SceneColorBuffer
);
501 Context
.TransitionResource(g_Histogram
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
502 Context
.TransitionResource(g_Exposure
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);
503 Context
.SetDynamicDescriptor(1, 0, g_SceneColorBuffer
.GetUAV());
504 D3D12_CPU_DESCRIPTOR_HANDLE SRVs
[2] = { g_Histogram
.GetSRV(), g_Exposure
.GetSRV() };
505 Context
.SetDynamicDescriptors(2, 0, 2, SRVs
);
506 Context
.Dispatch(1, 32);
507 Context
.TransitionResource(g_SceneColorBuffer
, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
);