core: Define VK_USE_PLATFORM_XCB_KHR before including vkd3d_utils.h.
[vkmodelviewer.git] / Core / MotionBlur.cpp
blob810634f1683a650cb8adb40fd22b99200a60bb5f
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"
15 #include "MotionBlur.h"
16 #include "Camera.h"
17 #include "BufferManager.h"
18 #include "GraphicsCore.h"
19 #include "CommandContext.h"
20 #include "Camera.h"
21 #include "PostEffects.h"
22 #include "SystemTime.h"
24 #include "compiled_shaders/ScreenQuadVS.h"
25 #include "compiled_shaders/CameraMotionBlurPrePassCS.h"
26 #include "compiled_shaders/CameraMotionBlurPrePassLinearZCS.h"
27 #include "compiled_shaders/MotionBlurPrePassCS.h"
28 #include "compiled_shaders/MotionBlurFinalPassCS.h"
29 #include "compiled_shaders/MotionBlurFinalPassPS.h"
30 #include "compiled_shaders/CameraVelocityCS.h"
31 #include "compiled_shaders/TemporalBlendCS.h"
32 #include "compiled_shaders/BoundNeighborhoodCS.h"
34 using namespace Graphics;
35 using namespace Math;
37 namespace MotionBlur
39 BoolVar Enable("Graphics/Motion Blur/Enable", false);
41 RootSignature s_RootSignature;
42 ComputePSO s_CameraMotionBlurPrePassCS[2];
43 ComputePSO s_MotionBlurPrePassCS;
44 ComputePSO s_MotionBlurFinalPassCS;
45 GraphicsPSO s_MotionBlurFinalPassPS;
46 ComputePSO s_CameraVelocityCS[2];
49 void MotionBlur::Initialize( void )
51 s_RootSignature.Reset(4, 1);
52 s_RootSignature.InitStaticSampler(0, SamplerLinearBorderDesc);
53 s_RootSignature[0].InitAsConstants(0, 4);
54 s_RootSignature[1].InitAsConstantBuffer(1);
55 s_RootSignature[2].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 8);
56 s_RootSignature[3].InitAsDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 8);
57 s_RootSignature.Finalize(L"Motion Blur");
59 #define CreatePSO( ObjName, ShaderByteCode ) \
60 ObjName.SetRootSignature(s_RootSignature); \
61 ObjName.SetComputeShader(ShaderByteCode, sizeof(ShaderByteCode) ); \
62 ObjName.Finalize();
64 if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)
66 CreatePSO(s_MotionBlurFinalPassCS, g_pMotionBlurFinalPassCS);
68 else
70 s_MotionBlurFinalPassPS.SetRootSignature(s_RootSignature);
71 s_MotionBlurFinalPassPS.SetRasterizerState( RasterizerTwoSided );
72 s_MotionBlurFinalPassPS.SetBlendState( BlendPreMultiplied );
73 s_MotionBlurFinalPassPS.SetDepthStencilState( DepthStateDisabled );
74 s_MotionBlurFinalPassPS.SetSampleMask(0xFFFFFFFF);
75 s_MotionBlurFinalPassPS.SetInputLayout(0, nullptr);
76 s_MotionBlurFinalPassPS.SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE);
77 s_MotionBlurFinalPassPS.SetVertexShader( g_pScreenQuadVS, sizeof(g_pScreenQuadVS) );
78 s_MotionBlurFinalPassPS.SetPixelShader( g_pMotionBlurFinalPassPS, sizeof(g_pMotionBlurFinalPassPS) );
79 s_MotionBlurFinalPassPS.SetRenderTargetFormat(g_SceneColorBuffer.GetFormat(), DXGI_FORMAT_UNKNOWN);
80 s_MotionBlurFinalPassPS.Finalize();
83 CreatePSO( s_CameraMotionBlurPrePassCS[0], g_pCameraMotionBlurPrePassCS );
84 CreatePSO( s_CameraMotionBlurPrePassCS[1], g_pCameraMotionBlurPrePassLinearZCS );
85 CreatePSO( s_MotionBlurPrePassCS, g_pMotionBlurPrePassCS );
86 CreatePSO( s_CameraVelocityCS[0], g_pCameraVelocityCS );
87 CreatePSO( s_CameraVelocityCS[1], g_pCameraVelocityCS );
89 #undef CreatePSO
92 void MotionBlur::Shutdown( void )
96 // Linear Z ends up being faster since we haven't officially decompressed the depth buffer. You
97 // would think that it might be slower to use linear Z because we have to convert it back to
98 // hyperbolic Z for the reprojection. Nevertheless, the reduced bandwidth and decompress eliminate
99 // make Linear Z the better choice. (The choice also lets you evict the depth buffer from ESRAM.)
101 void MotionBlur::GenerateCameraVelocityBuffer( CommandContext& BaseContext, const Camera& camera, bool UseLinearZ )
103 GenerateCameraVelocityBuffer(BaseContext, camera.GetReprojectionMatrix(), camera.GetNearClip(), camera.GetFarClip(), UseLinearZ);
106 void MotionBlur::GenerateCameraVelocityBuffer( CommandContext& BaseContext, const Matrix4& reprojectionMatrix, float nearClip, float farClip, bool UseLinearZ)
108 ScopedTimer _prof(L"Generate Camera Velocity", BaseContext);
110 ComputeContext& Context = BaseContext.GetComputeContext();
112 Context.SetRootSignature(s_RootSignature);
114 uint32_t Width = g_SceneColorBuffer.GetWidth();
115 uint32_t Height = g_SceneColorBuffer.GetHeight();
117 float RcpHalfDimX = 2.0f / Width;
118 float RcpHalfDimY = 2.0f / Height;
119 float RcpZMagic = nearClip / (farClip - nearClip);
121 Matrix4 preMult = Matrix4(
122 Vector4( RcpHalfDimX, 0.0f, 0.0f, 0.0f ),
123 Vector4( 0.0f, -RcpHalfDimY, 0.0f, 0.0f),
124 Vector4( 0.0f, 0.0f, UseLinearZ ? RcpZMagic : 1.0f, 0.0f ),
125 Vector4( -1.0f, 1.0f, UseLinearZ ? -RcpZMagic : 0.0f, 1.0f )
128 Matrix4 postMult = Matrix4(
129 Vector4( 1.0f / RcpHalfDimX, 0.0f, 0.0f, 0.0f ),
130 Vector4( 0.0f, -1.0f / RcpHalfDimY, 0.0f, 0.0f ),
131 Vector4( 0.0f, 0.0f, 1.0f, 0.0f ),
132 Vector4( 1.0f / RcpHalfDimX, 1.0f / RcpHalfDimY, 0.0f, 1.0f ) );
135 Matrix4 CurToPrevXForm = postMult * reprojectionMatrix * preMult;
137 Context.SetDynamicConstantBufferView(1, sizeof(CurToPrevXForm), &CurToPrevXForm);
138 Context.TransitionResource(g_VelocityBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
140 ColorBuffer& LinearDepth = g_LinearDepth[ Graphics::GetFrameCount() % 2 ];
141 if (UseLinearZ)
142 Context.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
143 else
144 Context.TransitionResource(g_SceneDepthBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
146 Context.SetPipelineState(s_CameraVelocityCS[UseLinearZ ? 1 : 0]);
147 Context.SetDynamicDescriptor(3, 0, UseLinearZ ? LinearDepth.GetSRV() : g_SceneDepthBuffer.GetDepthSRV());
148 Context.SetDynamicDescriptor(2, 0, g_VelocityBuffer.GetUAV());
149 Context.Dispatch2D(Width, Height);
153 void MotionBlur::RenderCameraBlur( CommandContext& BaseContext, const Camera& camera, bool UseLinearZ )
155 RenderCameraBlur(BaseContext, camera.GetReprojectionMatrix(), camera.GetNearClip(), camera.GetFarClip(), UseLinearZ);
158 void MotionBlur::RenderCameraBlur( CommandContext& BaseContext, const Matrix4& reprojectionMatrix, float nearClip, float farClip, bool UseLinearZ)
160 ScopedTimer _prof(L"MotionBlur", BaseContext);
162 if (!Enable)
163 return;
165 ComputeContext& Context = BaseContext.GetComputeContext();
167 Context.SetRootSignature(s_RootSignature);
169 uint32_t Width = g_SceneColorBuffer.GetWidth();
170 uint32_t Height = g_SceneColorBuffer.GetHeight();
172 float RcpHalfDimX = 2.0f / Width;
173 float RcpHalfDimY = 2.0f / Height;
174 float RcpZMagic = nearClip / (farClip - nearClip);
176 Matrix4 preMult = Matrix4(
177 Vector4( RcpHalfDimX, 0.0f, 0.0f, 0.0f ),
178 Vector4( 0.0f, -RcpHalfDimY, 0.0f, 0.0f),
179 Vector4( 0.0f, 0.0f, UseLinearZ ? RcpZMagic : 1.0f, 0.0f ),
180 Vector4( -1.0f, 1.0f, UseLinearZ ? -RcpZMagic : 0.0f, 1.0f )
183 Matrix4 postMult = Matrix4(
184 Vector4( 1.0f / RcpHalfDimX, 0.0f, 0.0f, 0.0f ),
185 Vector4( 0.0f, -1.0f / RcpHalfDimY, 0.0f, 0.0f ),
186 Vector4( 0.0f, 0.0f, 1.0f, 0.0f ),
187 Vector4( 1.0f / RcpHalfDimX, 1.0f / RcpHalfDimY, 0.0f, 1.0f ) );
189 Matrix4 CurToPrevXForm = postMult * reprojectionMatrix * preMult;
191 Context.SetDynamicConstantBufferView(1, sizeof(CurToPrevXForm), &CurToPrevXForm);
193 ColorBuffer& LinearDepth = g_LinearDepth[ Graphics::GetFrameCount() % 2 ];
194 if (UseLinearZ)
195 Context.TransitionResource(LinearDepth, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
196 else
197 Context.TransitionResource(g_SceneDepthBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
199 if (Enable)
201 Context.TransitionResource(g_VelocityBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
202 Context.TransitionResource(g_MotionPrepBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
203 Context.TransitionResource(g_SceneColorBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
205 Context.SetPipelineState(s_CameraMotionBlurPrePassCS[UseLinearZ ? 1 : 0]);
206 Context.SetDynamicDescriptor(3, 0, g_SceneColorBuffer.GetSRV());
207 Context.SetDynamicDescriptor(3, 1, UseLinearZ ? LinearDepth.GetSRV() : g_SceneDepthBuffer.GetDepthSRV());
208 Context.SetDynamicDescriptor(2, 0, g_MotionPrepBuffer.GetUAV());
209 Context.SetDynamicDescriptor(2, 1, g_VelocityBuffer.GetUAV());
210 Context.Dispatch2D(g_MotionPrepBuffer.GetWidth(), g_MotionPrepBuffer.GetHeight());
212 if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)
214 Context.SetPipelineState(s_MotionBlurFinalPassCS);
215 Context.SetConstants(0, 1.0f / Width, 1.0f / Height);
217 Context.TransitionResource(g_SceneColorBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
218 Context.TransitionResource(g_VelocityBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
219 Context.TransitionResource(g_MotionPrepBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
220 Context.SetDynamicDescriptor(2, 0, g_SceneColorBuffer.GetUAV());
221 Context.SetDynamicDescriptor(3, 0, g_VelocityBuffer.GetSRV());
222 Context.SetDynamicDescriptor(3, 1, g_MotionPrepBuffer.GetSRV());
224 Context.Dispatch2D(Width, Height);
226 Context.InsertUAVBarrier(g_SceneColorBuffer);
228 else
230 GraphicsContext& GrContext = BaseContext.GetGraphicsContext();
231 GrContext.SetRootSignature(s_RootSignature);
232 GrContext.SetPipelineState(s_MotionBlurFinalPassPS);
233 GrContext.TransitionResource(g_SceneColorBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET);
234 GrContext.TransitionResource(g_VelocityBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
235 GrContext.TransitionResource(g_MotionPrepBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
236 GrContext.SetDynamicDescriptor(3, 0, g_VelocityBuffer.GetSRV());
237 GrContext.SetDynamicDescriptor(3, 1, g_MotionPrepBuffer.GetSRV());
238 GrContext.SetConstants(0, 1.0f / Width, 1.0f / Height);
239 GrContext.SetRenderTarget(g_SceneColorBuffer.GetRTV());
240 GrContext.SetViewportAndScissor(0, 0, Width, Height);
241 GrContext.Draw(3);
244 else
246 Context.SetPipelineState(s_CameraVelocityCS[UseLinearZ ? 1 : 0]);
247 Context.SetDynamicDescriptor(3, 0, UseLinearZ ? LinearDepth.GetSRV() : g_SceneDepthBuffer.GetDepthSRV());
248 Context.SetDynamicDescriptor(2, 0, g_VelocityBuffer.GetUAV());
249 Context.Dispatch2D(Width, Height);
253 void MotionBlur::RenderObjectBlur( CommandContext& BaseContext, ColorBuffer& velocityBuffer )
255 ScopedTimer _prof(L"MotionBlur", BaseContext);
257 if (!Enable)
258 return;
260 uint32_t Width = g_SceneColorBuffer.GetWidth();
261 uint32_t Height = g_SceneColorBuffer.GetHeight();
263 ComputeContext& Context = BaseContext.GetComputeContext();
265 Context.SetRootSignature(s_RootSignature);
267 Context.TransitionResource(g_MotionPrepBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
268 Context.TransitionResource(g_SceneColorBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
269 Context.TransitionResource(velocityBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
271 Context.SetDynamicDescriptor(2, 0, g_MotionPrepBuffer.GetUAV());
272 Context.SetDynamicDescriptor(3, 0, g_SceneColorBuffer.GetSRV());
273 Context.SetDynamicDescriptor(3, 1, velocityBuffer.GetSRV());
275 Context.SetPipelineState(s_MotionBlurPrePassCS);
276 Context.Dispatch2D(g_MotionPrepBuffer.GetWidth(), g_MotionPrepBuffer.GetHeight());
278 if (g_bTypedUAVLoadSupport_R11G11B10_FLOAT)
280 Context.SetPipelineState(s_MotionBlurFinalPassCS);
282 Context.TransitionResource(g_SceneColorBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
283 Context.TransitionResource(velocityBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
284 Context.TransitionResource(g_MotionPrepBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
286 Context.SetDynamicDescriptor(2, 0, g_SceneColorBuffer.GetUAV());
287 Context.SetDynamicDescriptor(3, 0, velocityBuffer.GetSRV());
288 Context.SetDynamicDescriptor(3, 1, g_MotionPrepBuffer.GetSRV());
289 Context.SetConstants(0, 1.0f / Width, 1.0f / Height);
291 Context.Dispatch2D(Width, Height);
293 Context.InsertUAVBarrier(g_SceneColorBuffer);
295 else
297 GraphicsContext& GrContext = BaseContext.GetGraphicsContext();
298 GrContext.SetRootSignature(s_RootSignature);
299 GrContext.SetPipelineState(s_MotionBlurFinalPassPS);
301 GrContext.TransitionResource(g_SceneColorBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET);
302 GrContext.TransitionResource(velocityBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
303 GrContext.TransitionResource(g_MotionPrepBuffer, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
305 GrContext.SetDynamicDescriptor(3, 0, velocityBuffer.GetSRV());
306 GrContext.SetDynamicDescriptor(3, 1, g_MotionPrepBuffer.GetSRV());
307 GrContext.SetConstants(0, 1.0f / Width, 1.0f / Height);
308 GrContext.SetRenderTarget(g_SceneColorBuffer.GetRTV());
309 GrContext.SetViewportAndScissor(0, 0, Width, Height);
311 GrContext.Draw(3);