core: Define VK_USE_PLATFORM_XCB_KHR before including vkd3d_utils.h.
[vkmodelviewer.git] / Core / PostEffects.cpp
blobcb1c8249502e9003205448f2cf5d8cccfd89e7b4
1 //
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.
8 //
9 // Developed by Minigraph
11 // Author: James Stanard
14 #include "pch.h"
16 #include "PostEffects.h"
17 #include "GameCore.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"
25 #include "FXAA.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;
52 namespace SSAO
54 extern BoolVar DebugDraw;
57 namespace FXAA
59 extern BoolVar DebugDraw;
62 namespace DepthOfField
64 extern BoolVar Enable;
65 extern EnumVar DebugMode;
68 namespace PostEffects
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;
89 ComputePSO ToneMapCS;
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;
100 ComputePSO BlurCS;
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) ); \
131 ObjName.Finalize();
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);
141 else
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 );
163 #undef CreatePSO
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);
172 FXAA::Initialize();
173 MotionBlur::Initialize();
174 DepthOfField::Initialize();
177 void PostEffects::Shutdown( void )
179 g_Exposure.Destroy();
181 FXAA::Shutdown();
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);
257 // Set the UAVs
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 );
280 else
282 // Set the UAVs
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);
333 return;
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;
349 float MinExposure;
350 float MaxExposure;
351 uint32_t PixelCount;
352 } constants =
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);
363 Context.Dispatch();
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);
371 if (BloomEnable)
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);
381 else
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));
389 // Set constants
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());
396 else
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;
420 if (bGenerateBloom)
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);
427 else
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);
433 // Set constants
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());
440 else
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))
478 ProcessHDR(Context);
479 else
480 ProcessLDR(Context);
482 bool bGeneratedLumaBuffer = EnableHDR || FXAA::DebugDraw || BloomEnable;
483 if (FXAA::Enable)
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);
495 if (DrawHistogram)
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);
510 Context.Finish();