From f21c9ea82786d4f280e38314a7ba3a5c0309956a Mon Sep 17 00:00:00 2001 From: nouverbe Date: Sat, 3 Feb 2024 13:28:35 +0200 Subject: [PATCH 01/42] Required changes for the new renderer in the main loop --- src/xrEngine/x_ray.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/xrEngine/x_ray.cpp b/src/xrEngine/x_ray.cpp index be3222cb41d..468e65931af 100644 --- a/src/xrEngine/x_ray.cpp +++ b/src/xrEngine/x_ray.cpp @@ -481,7 +481,9 @@ int CApplication::Run() Device.OnWindowActivate(shouldActivate); } - Device.ProcessFrame(); +#pragma message("need to rework:") + if (Device.b_is_InFocus) + Device.ProcessFrame(); UpdateDiscordStatus(); } // while (!SDL_QuitRequested()) From 1c37c401f3acbc66af7eab6980049275afc6ebc7 Mon Sep 17 00:00:00 2001 From: nouverbe Date: Mon, 5 Feb 2024 16:52:19 +0200 Subject: [PATCH 02/42] Added a new render based on DX 12 - Render 5 --- Externals/imgui.vcxproj | 2 + src/Layers/xrRender/Blender_Recorder.cpp | 10 +- src/Layers/xrRender/Blender_Recorder.h | 10 +- src/Layers/xrRender/Blender_Recorder_R2.cpp | 8 +- .../Blender_Recorder_StandartBinding.cpp | 4 +- src/Layers/xrRender/ColorMapManager.cpp | 6 +- src/Layers/xrRender/D3DXRenderBase.cpp | 19 +- src/Layers/xrRender/Debug/dxPixEventWrapper.h | 2 +- src/Layers/xrRender/DetailManager.h | 2 +- src/Layers/xrRender/DetailModel.cpp | 4 +- src/Layers/xrRender/FTreeVisual.cpp | 2 +- src/Layers/xrRender/FVF.h | 2 +- src/Layers/xrRender/HOM.cpp | 2 +- src/Layers/xrRender/Light_Package.cpp | 2 +- src/Layers/xrRender/ParticleEffect.cpp | 2 +- src/Layers/xrRender/QueryHelper.h | 4 +- src/Layers/xrRender/R_Backend.h | 50 +- src/Layers/xrRender/R_Backend_DBG.cpp | 10 +- src/Layers/xrRender/R_Backend_Runtime.cpp | 32 +- src/Layers/xrRender/R_Backend_Runtime.h | 10 +- src/Layers/xrRender/ResourceManager.cpp | 6 +- src/Layers/xrRender/ResourceManager.h | 21 +- src/Layers/xrRender/ResourceManager_Reset.cpp | 4 +- .../xrRender/ResourceManager_Resources.cpp | 8 + src/Layers/xrRender/SH_Atomic.cpp | 22 +- src/Layers/xrRender/SH_Atomic.h | 22 +- src/Layers/xrRender/SH_RT.h | 16 +- src/Layers/xrRender/SH_Texture.h | 18 +- src/Layers/xrRender/Shader.cpp | 4 +- src/Layers/xrRender/Shader.cpp.bak | 167 + src/Layers/xrRender/Shader.h | 4 +- src/Layers/xrRender/ShaderResourceTraits.h | 63 +- src/Layers/xrRender/blenders/Blender_Blur.cpp | 2 +- .../xrRender/blenders/Blender_Lm(EbB).cpp | 2 +- .../blenders/Blender_Particle_deferred.cpp | 4 +- .../xrRender/blenders/blender_deffer_flat.cpp | 4 +- .../blenders/blender_deffer_model.cpp | 2 +- src/Layers/xrRender/blenders/blender_dof.cpp | 2 +- .../xrRender/blenders/blender_nightvision.cpp | 2 +- src/Layers/xrRender/blenders/uber_deffer.cpp | 4 +- src/Layers/xrRender/dxDebugRender.cpp | 2 +- src/Layers/xrRender/dxEnvironmentRender.cpp | 6 +- src/Layers/xrRender/dxImGuiRender.cpp | 31 + src/Layers/xrRender/dxRainRender.cpp | 4 +- src/Layers/xrRender/dxThunderboltRender.cpp | 4 +- src/Layers/xrRender/dxUIRender.cpp | 2 +- src/Layers/xrRender/dxWallMarkArray.cpp | 2 +- src/Layers/xrRender/light.cpp | 16 +- src/Layers/xrRender/light.h | 6 +- src/Layers/xrRender/r__dsgraph_render.cpp | 6 +- src/Layers/xrRender/r__occlusion.cpp | 2 +- src/Layers/xrRender/r__occlusion.cpp.bak | 150 + src/Layers/xrRender/r__occlusion.h | 4 +- src/Layers/xrRender/r__pixel_calculator.cpp | 8 +- src/Layers/xrRender/r__sync_point.cpp | 2 +- src/Layers/xrRender/r_constants.cpp | 6 +- src/Layers/xrRender/r_constants.cpp.bak | 171 + src/Layers/xrRender/r_constants.h | 20 +- src/Layers/xrRender/r_constants_cache.h | 2 +- .../rendertarget_phase_gasmask_drops.cpp | 6 +- .../rendertarget_phase_gasmask_dudv.cpp | 6 +- src/Layers/xrRender/stats_manager.cpp | 14 +- src/Layers/xrRender/stats_manager.h | 2 +- src/Layers/xrRender/tss.h | 2 +- src/Layers/xrRender/tss_def.cpp | 4 +- src/Layers/xrRender/tss_def.h | 2 +- src/Layers/xrRender/xrRender_console.cpp | 24 +- src/Layers/xrRender/xr_effgamma.cpp | 4 +- src/Layers/xrRender/xr_effgamma.h | 2 +- .../xrRenderDX11/Blender_Recorder_R3.cpp | 4 +- .../StateManager/dx11StateManager.cpp | 4 +- .../xrRenderDX11/dx11ConstantBuffer.cpp | 4 +- src/Layers/xrRenderDX11/dx11HW.cpp | 207 +- src/Layers/xrRenderDX11/dx11HW.h | 44 +- .../xrRenderDX11/dx11R_Backend_Runtime.h | 43 +- .../dx11ResourceManager_Resources.cpp | 4 +- src/Layers/xrRenderDX11/dx11SH_RT.cpp | 22 +- src/Layers/xrRenderDX11/dx11SH_Texture.cpp | 9 +- src/Layers/xrRenderDX11/dx11StateUtils.cpp | 8 +- .../xrRenderDX11/dx11r_constants_cache.h | 4 +- src/Layers/xrRenderPC_GL/gl_rendertarget.h | 2 +- src/Layers/xrRenderPC_GL/stdafx.h | 1 + .../FStaticRender_RenderTarget.cpp | 2 +- .../FStaticRender_RenderTarget.h | 2 +- .../FStaticRender_RenderTarget.h.bak | 126 + src/Layers/xrRenderPC_R1/stdafx.h | 1 + src/Layers/xrRenderPC_R2/r2_rendertarget.h | 2 +- .../xrRenderPC_R2/r2_rendertarget.h.bak | 333 ++ src/Layers/xrRenderPC_R2/stdafx.h | 1 + src/Layers/xrRenderPC_R4/r4_rendertarget.h | 4 +- .../xrRenderPC_R4/r4_rendertarget.h.bak | 410 +++ src/Layers/xrRenderPC_R4/stdafx.h | 1 + src/Layers/xrRenderPC_R5/CMakeLists.txt | 57 + src/Layers/xrRenderPC_R5/CMakeLists.txt.bak | 57 + src/Layers/xrRenderPC_R5/CSCompiler.cpp | 207 ++ src/Layers/xrRenderPC_R5/CSCompiler.h | 39 + src/Layers/xrRenderPC_R5/ComputeShader.cpp | 90 + src/Layers/xrRenderPC_R5/ComputeShader.h | 34 + src/Layers/xrRenderPC_R5/DX12/API/DX12.cpp | 210 ++ src/Layers/xrRenderPC_R5/DX12/API/DX12.hpp | 207 ++ .../DX12/API/DX12AsyncCommandQueue.cpp | 203 ++ .../DX12/API/DX12AsyncCommandQueue.hpp | 164 + .../DX12/API/DX12CommandList.cpp | 1324 +++++++ .../DX12/API/DX12CommandList.hpp | 630 ++++ .../DX12/API/DX12CommandListFence.cpp | 155 + .../DX12/API/DX12CommandListFence.hpp | 274 ++ .../DX12/API/DX12DescriptorHeap.cpp | 61 + .../DX12/API/DX12DescriptorHeap.hpp | 179 + .../xrRenderPC_R5/DX12/API/DX12Device.cpp | 516 +++ .../xrRenderPC_R5/DX12/API/DX12Device.hpp | 153 + src/Layers/xrRenderPC_R5/DX12/API/DX12PSO.cpp | 127 + src/Layers/xrRenderPC_R5/DX12/API/DX12PSO.hpp | 117 + .../xrRenderPC_R5/DX12/API/DX12QueryHeap.cpp | 52 + .../xrRenderPC_R5/DX12/API/DX12QueryHeap.hpp | 37 + .../xrRenderPC_R5/DX12/API/DX12Resource.cpp | 192 + .../xrRenderPC_R5/DX12/API/DX12Resource.hpp | 269 ++ .../DX12/API/DX12ResourceBarrierCache.cpp | 168 + .../DX12/API/DX12ResourceBarrierCache.h | 71 + .../DX12/API/DX12RootSignature.cpp | 628 ++++ .../DX12/API/DX12RootSignature.hpp | 158 + .../DX12/API/DX12SamplerState.cpp | 32 + .../DX12/API/DX12SamplerState.hpp | 47 + .../xrRenderPC_R5/DX12/API/DX12Shader.cpp | 235 ++ .../xrRenderPC_R5/DX12/API/DX12Shader.hpp | 179 + .../xrRenderPC_R5/DX12/API/DX12SwapChain.cpp | 123 + .../xrRenderPC_R5/DX12/API/DX12SwapChain.hpp | 96 + .../xrRenderPC_R5/DX12/API/DX12TimerHeap.cpp | 123 + .../xrRenderPC_R5/DX12/API/DX12TimerHeap.h | 97 + .../xrRenderPC_R5/DX12/API/DX12View.cpp | 151 + .../xrRenderPC_R5/DX12/API/DX12View.hpp | 192 + .../xrRenderPC_R5/DX12/CCryDX12Object.cpp | 15 + .../xrRenderPC_R5/DX12/CCryDX12Object.hpp | 199 ++ src/Layers/xrRenderPC_R5/DX12/CryDX12.cpp | 58 + src/Layers/xrRenderPC_R5/DX12/CryDX12.hpp | 50 + src/Layers/xrRenderPC_R5/DX12/CryDX12Guid.hpp | 40 + .../xrRenderPC_R5/DX12/CryDX12Legacy.hpp | 30 + .../DX12/Device/CCryDX12Device.cpp | 904 +++++ .../DX12/Device/CCryDX12Device.hpp | 319 ++ .../DX12/Device/CCryDX12DeviceChild.cpp | 16 + .../DX12/Device/CCryDX12DeviceChild.hpp | 192 + .../DX12/Device/CCryDX12DeviceContext.cpp | 3119 +++++++++++++++++ .../DX12/Device/CCryDX12DeviceContext.hpp | 879 +++++ .../DX12/GI/CCryDX12GIFactory.cpp | 90 + .../DX12/GI/CCryDX12GIFactory.hpp | 180 + .../DX12/GI/CCryDX12SwapChain.cpp | 273 ++ .../DX12/GI/CCryDX12SwapChain.hpp | 279 ++ .../DX12/Includes/concqueue-mpmc-bounded.hpp | 189 + .../DX12/Includes/concqueue-mpsc.hpp | 118 + .../DX12/Includes/concqueue-spsc-bounded.hpp | 123 + .../DX12/Includes/concqueue-spsc.hpp | 121 + .../xrRenderPC_R5/DX12/Includes/concqueue.hpp | 33 + .../xrRenderPC_R5/DX12/Includes/crc32.h | 118 + .../xrRenderPC_R5/DX12/Includes/crc32.inl | 306 ++ .../DX12/Includes/critical_section.h | 134 + .../DX12/Includes/critical_section.h.bak | 4 + .../Includes/d3d11TokenizedProgramFormat.hpp | 2293 ++++++++++++ .../xrRenderPC_R5/DX12/Includes/d3dx12.h | 1657 +++++++++ .../xrRenderPC_R5/DX12/Includes/fasthash.h | 65 + .../xrRenderPC_R5/DX12/Includes/fasthash.inl | 109 + .../xrRenderPC_R5/DX12/Includes/range.h | 107 + .../DX12/Includes/reference_counted.h | 79 + .../xrRenderPC_R5/DX12/Includes/smartptr.h | 380 ++ .../DX12/Misc/SCryDX11PipelineState.cpp | 625 ++++ .../DX12/Misc/SCryDX11PipelineState.hpp | 398 +++ .../DX12/Resource/CCryDX12Asynchronous.cpp | 14 + .../DX12/Resource/CCryDX12Asynchronous.hpp | 49 + .../DX12/Resource/CCryDX12Resource.cpp | 14 + .../DX12/Resource/CCryDX12Resource.hpp | 149 + .../DX12/Resource/CCryDX12View.cpp | 14 + .../DX12/Resource/CCryDX12View.hpp | 120 + .../DX12/Resource/Misc/CCryDX12Buffer.cpp | 208 ++ .../DX12/Resource/Misc/CCryDX12Buffer.hpp | 84 + .../Resource/Misc/CCryDX12InputLayout.cpp | 58 + .../Resource/Misc/CCryDX12InputLayout.hpp | 46 + .../DX12/Resource/Misc/CCryDX12Query.cpp | 111 + .../DX12/Resource/Misc/CCryDX12Query.hpp | 140 + .../DX12/Resource/Misc/CCryDX12Shader.cpp | 57 + .../DX12/Resource/Misc/CCryDX12Shader.hpp | 51 + .../Resource/State/CCryDX12BlendState.cpp | 70 + .../Resource/State/CCryDX12BlendState.hpp | 51 + .../State/CCryDX12DepthStencilState.cpp | 67 + .../State/CCryDX12DepthStencilState.hpp | 50 + .../State/CCryDX12RasterizerState.cpp | 62 + .../State/CCryDX12RasterizerState.hpp | 53 + .../Resource/State/CCryDX12SamplerState.cpp | 48 + .../Resource/State/CCryDX12SamplerState.hpp | 56 + .../Resource/Texture/CCryDX12Texture1D.cpp | 181 + .../Resource/Texture/CCryDX12Texture1D.hpp | 69 + .../Resource/Texture/CCryDX12Texture2D.cpp | 184 + .../Resource/Texture/CCryDX12Texture2D.hpp | 84 + .../Resource/Texture/CCryDX12Texture3D.cpp | 180 + .../Resource/Texture/CCryDX12Texture3D.hpp | 69 + .../View/CCryDX12DepthStencilView.cpp | 147 + .../View/CCryDX12DepthStencilView.hpp | 58 + .../View/CCryDX12RenderTargetView.cpp | 166 + .../View/CCryDX12RenderTargetView.hpp | 64 + .../View/CCryDX12ShaderResourceView.cpp | 133 + .../View/CCryDX12ShaderResourceView.hpp | 49 + .../View/CCryDX12UnorderedAccessView.cpp | 96 + .../View/CCryDX12UnorderedAccessView.hpp | 56 + src/Layers/xrRenderPC_R5/R_Backend_LOD.cpp | 16 + src/Layers/xrRenderPC_R5/R_Backend_LOD.h | 19 + src/Layers/xrRenderPC_R5/packages.config | 7 + src/Layers/xrRenderPC_R5/r2_test_hw.cpp | 45 + src/Layers/xrRenderPC_R5/r5_rendertarget.h | 410 +++ .../r5_rendertarget_accum_direct.cpp | 1354 +++++++ .../r5_rendertarget_build_textures.cpp | 288 ++ .../r5_rendertarget_phase_combine.cpp | 644 ++++ .../r5_rendertarget_phase_hdao.cpp | 37 + .../r5_rendertarget_u_set_rt.cpp | 104 + src/Layers/xrRenderPC_R5/r5_shaders.cpp | 620 ++++ src/Layers/xrRenderPC_R5/stdafx.cpp | 8 + src/Layers/xrRenderPC_R5/stdafx.h | 81 + src/Layers/xrRenderPC_R5/xrRender_R5.cpp | 73 + src/Layers/xrRenderPC_R5/xrRender_R5.vcxproj | 594 ++++ .../xrRenderPC_R5/xrRender_R5.vcxproj.filters | 1679 +++++++++ src/Layers/xrRender_R2/r2.cpp | 54 +- src/Layers/xrRender_R2/r2.h | 15 +- src/Layers/xrRender_R2/r2_R_render.cpp | 12 +- src/Layers/xrRender_R2/r2_loader.cpp | 6 +- src/Layers/xrRender_R2/r2_rendertarget.cpp | 80 +- .../r2_rendertarget_accum_reflected.cpp | 12 +- .../xrRender_R2/r2_rendertarget_phase_PP.cpp | 4 +- .../r2_rendertarget_phase_accumulator.cpp | 4 +- .../r2_rendertarget_phase_bloom.cpp | 8 +- .../r2_rendertarget_phase_luminance.cpp | 6 +- .../r2_rendertarget_phase_smap_S.cpp | 4 +- src/Layers/xrRender_R2/r3_R_rain.cpp | 8 +- .../r3_rendertarget_accum_point.cpp | 4 +- .../r3_rendertarget_accum_spot.cpp | 12 +- .../xrRender_R2/r3_rendertarget_draw_rain.cpp | 10 +- .../r3_rendertarget_mark_msaa_edges.cpp | 4 +- src/engine.sln | 35 + src/xrEngine/Engine.cpp | 2 + src/xrEngine/EngineAPI.cpp | 3 +- src/xrEngine/Render.h | 1 + src/xrEngine/xrSASH.cpp | 2 + 237 files changed, 32359 insertions(+), 478 deletions(-) create mode 100644 src/Layers/xrRender/Shader.cpp.bak create mode 100644 src/Layers/xrRender/r__occlusion.cpp.bak create mode 100644 src/Layers/xrRender/r_constants.cpp.bak create mode 100644 src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.h.bak create mode 100644 src/Layers/xrRenderPC_R2/r2_rendertarget.h.bak create mode 100644 src/Layers/xrRenderPC_R4/r4_rendertarget.h.bak create mode 100644 src/Layers/xrRenderPC_R5/CMakeLists.txt create mode 100644 src/Layers/xrRenderPC_R5/CMakeLists.txt.bak create mode 100644 src/Layers/xrRenderPC_R5/CSCompiler.cpp create mode 100644 src/Layers/xrRenderPC_R5/CSCompiler.h create mode 100644 src/Layers/xrRenderPC_R5/ComputeShader.cpp create mode 100644 src/Layers/xrRenderPC_R5/ComputeShader.h create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12AsyncCommandQueue.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12AsyncCommandQueue.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12CommandList.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12CommandList.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12CommandListFence.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12CommandListFence.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12DescriptorHeap.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12DescriptorHeap.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12Device.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12Device.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12PSO.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12PSO.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12QueryHeap.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12QueryHeap.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12Resource.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12Resource.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12ResourceBarrierCache.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12ResourceBarrierCache.h create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12RootSignature.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12RootSignature.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12SamplerState.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12SamplerState.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12Shader.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12Shader.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12SwapChain.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12SwapChain.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12TimerHeap.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12TimerHeap.h create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12View.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/API/DX12View.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/CCryDX12Object.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/CCryDX12Object.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/CryDX12.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/CryDX12.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/CryDX12Guid.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/CryDX12Legacy.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12Device.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12Device.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceChild.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceChild.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceContext.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceContext.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12GIFactory.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12GIFactory.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12SwapChain.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12SwapChain.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-mpmc-bounded.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-mpsc.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-spsc-bounded.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-spsc.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/concqueue.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/crc32.h create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/crc32.inl create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/critical_section.h create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/critical_section.h.bak create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/d3d11TokenizedProgramFormat.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/d3dx12.h create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/fasthash.h create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/fasthash.inl create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/range.h create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/reference_counted.h create mode 100644 src/Layers/xrRenderPC_R5/DX12/Includes/smartptr.h create mode 100644 src/Layers/xrRenderPC_R5/DX12/Misc/SCryDX11PipelineState.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Misc/SCryDX11PipelineState.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/CCryDX12Asynchronous.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/CCryDX12Asynchronous.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/CCryDX12Resource.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/CCryDX12Resource.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/CCryDX12View.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/CCryDX12View.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Misc/CCryDX12Buffer.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Misc/CCryDX12Buffer.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Misc/CCryDX12InputLayout.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Misc/CCryDX12InputLayout.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Misc/CCryDX12Query.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Misc/CCryDX12Query.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Misc/CCryDX12Shader.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Misc/CCryDX12Shader.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/State/CCryDX12BlendState.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/State/CCryDX12BlendState.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/State/CCryDX12DepthStencilState.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/State/CCryDX12DepthStencilState.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/State/CCryDX12RasterizerState.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/State/CCryDX12RasterizerState.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/State/CCryDX12SamplerState.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/State/CCryDX12SamplerState.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Texture/CCryDX12Texture1D.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Texture/CCryDX12Texture1D.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Texture/CCryDX12Texture2D.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Texture/CCryDX12Texture2D.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Texture/CCryDX12Texture3D.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/Texture/CCryDX12Texture3D.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/View/CCryDX12DepthStencilView.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/View/CCryDX12DepthStencilView.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/View/CCryDX12RenderTargetView.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/View/CCryDX12RenderTargetView.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/View/CCryDX12ShaderResourceView.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/View/CCryDX12ShaderResourceView.hpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/View/CCryDX12UnorderedAccessView.cpp create mode 100644 src/Layers/xrRenderPC_R5/DX12/Resource/View/CCryDX12UnorderedAccessView.hpp create mode 100644 src/Layers/xrRenderPC_R5/R_Backend_LOD.cpp create mode 100644 src/Layers/xrRenderPC_R5/R_Backend_LOD.h create mode 100644 src/Layers/xrRenderPC_R5/packages.config create mode 100644 src/Layers/xrRenderPC_R5/r2_test_hw.cpp create mode 100644 src/Layers/xrRenderPC_R5/r5_rendertarget.h create mode 100644 src/Layers/xrRenderPC_R5/r5_rendertarget_accum_direct.cpp create mode 100644 src/Layers/xrRenderPC_R5/r5_rendertarget_build_textures.cpp create mode 100644 src/Layers/xrRenderPC_R5/r5_rendertarget_phase_combine.cpp create mode 100644 src/Layers/xrRenderPC_R5/r5_rendertarget_phase_hdao.cpp create mode 100644 src/Layers/xrRenderPC_R5/r5_rendertarget_u_set_rt.cpp create mode 100644 src/Layers/xrRenderPC_R5/r5_shaders.cpp create mode 100644 src/Layers/xrRenderPC_R5/stdafx.cpp create mode 100644 src/Layers/xrRenderPC_R5/stdafx.h create mode 100644 src/Layers/xrRenderPC_R5/xrRender_R5.cpp create mode 100644 src/Layers/xrRenderPC_R5/xrRender_R5.vcxproj create mode 100644 src/Layers/xrRenderPC_R5/xrRender_R5.vcxproj.filters diff --git a/Externals/imgui.vcxproj b/Externals/imgui.vcxproj index e1c77ad2fb1..e14bb5f864e 100644 --- a/Externals/imgui.vcxproj +++ b/Externals/imgui.vcxproj @@ -32,6 +32,7 @@ + @@ -42,6 +43,7 @@ + diff --git a/src/Layers/xrRender/Blender_Recorder.cpp b/src/Layers/xrRender/Blender_Recorder.cpp index 8849573af25..21910c88545 100644 --- a/src/Layers/xrRender/Blender_Recorder.cpp +++ b/src/Layers/xrRender/Blender_Recorder.cpp @@ -128,7 +128,7 @@ void CBlender_Compile::_cpp_Compile(ShaderElement* _SH) bUseSteepParallax = true; } */ -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) TessMethod = 0; #endif @@ -210,16 +210,16 @@ void CBlender_Compile::PassSET_Shaders(pcstr _vs, pcstr _ps, pcstr _gs /*= nullp dest.ps = RImplementation.Resources->_CreatePS(_ps); ctable.merge(&dest.ps->constants); u32 flags = 0; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) if (dest.ps->constants.dx9compatibility) flags |= D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY; #endif dest.vs = RImplementation.Resources->_CreateVS(_vs, flags); ctable.merge(&dest.vs->constants); -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) dest.gs = RImplementation.Resources->_CreateGS(_gs); ctable.merge(&dest.gs->constants); -# ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) dest.hs = RImplementation.Resources->_CreateHS(_hs); dest.ds = RImplementation.Resources->_CreateDS(_ds); ctable.merge(&dest.hs->constants); @@ -254,7 +254,7 @@ void CBlender_Compile::PassSET_ablend_mode(BOOL bABlend, u32 abSRC, u32 abDST) RS.SetRS(D3DRS_SRCBLEND, bABlend ? abSRC : D3DBLEND_ONE); RS.SetRS(D3DRS_DESTBLEND, bABlend ? abDST : D3DBLEND_ZERO); -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) // Since in our engine D3DRS_SEPARATEALPHABLENDENABLE state is // always set to false and in DirectX 10 blend functions for // color and alpha are always independent, assign blend options for diff --git a/src/Layers/xrRender/Blender_Recorder.h b/src/Layers/xrRender/Blender_Recorder.h index d4532859b32..c39e7a5551e 100644 --- a/src/Layers/xrRender/Blender_Recorder.h +++ b/src/Layers/xrRender/Blender_Recorder.h @@ -34,7 +34,7 @@ class CBlender_Compile CSimulator RS; IBlender* BT; ShaderElement* SH; -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) enum { NO_TESS = 0, @@ -120,7 +120,7 @@ class CBlender_Compile void i_Filter_Mip(u32 s, u32 f); void i_Filter_Mag(u32 s, u32 f); void i_Filter_Aniso(u32 s, u32 f); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) void i_dx11FilterAnizo(u32 s, BOOL value); #endif void i_Filter(u32 s, u32 _min, u32 _mip, u32 _mag); @@ -131,11 +131,11 @@ class CBlender_Compile D3DBLEND abSRC = D3DBLEND_ONE, D3DBLEND abDST = D3DBLEND_ZERO, BOOL aTest = FALSE, u32 aRef = 0); void r_Constant(LPCSTR name, R_constant_setup* s); -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) void r_Pass(LPCSTR vs, LPCSTR gs, LPCSTR ps, bool bFog, BOOL bZtest = TRUE, BOOL bZwrite = TRUE, BOOL bABlend = FALSE, D3DBLEND abSRC = D3DBLEND_ONE, D3DBLEND abDST = D3DBLEND_ZERO, BOOL aTest = FALSE, u32 aRef = 0); -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) void r_TessPass(LPCSTR vs, LPCSTR hs, LPCSTR ds, LPCSTR gs, LPCSTR ps, bool bFog, BOOL bZtest = TRUE, BOOL bZwrite = TRUE, BOOL bABlend = FALSE, D3DBLEND abSRC = D3DBLEND_ONE, D3DBLEND abDST = D3DBLEND_ZERO, BOOL aTest = FALSE, u32 aRef = 0); @@ -147,7 +147,7 @@ class CBlender_Compile void r_CullMode(D3DCULL Mode); #endif // !USE_DX9 -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) void r_dx11Texture(LPCSTR ResourceName, LPCSTR texture, bool recursive = false); void r_dx11Texture(LPCSTR ResourceName, shared_str texture, bool recursive = false) { diff --git a/src/Layers/xrRender/Blender_Recorder_R2.cpp b/src/Layers/xrRender/Blender_Recorder_R2.cpp index 00e7b12cd13..0f86752ae7d 100644 --- a/src/Layers/xrRender/Blender_Recorder_R2.cpp +++ b/src/Layers/xrRender/Blender_Recorder_R2.cpp @@ -31,15 +31,15 @@ void CBlender_Compile::r_Pass(LPCSTR _vs, LPCSTR _ps, bool bFog, BOOL bZtest, BO dest.ps = RImplementation.Resources->_CreatePS(_ps); ctable.merge(&dest.ps->constants); u32 flags = 0; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) if (dest.ps->constants.dx9compatibility) flags |= D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY; #endif dest.vs = RImplementation.Resources->_CreateVS(_vs, flags); ctable.merge(&dest.vs->constants); -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) dest.gs = RImplementation.Resources->_CreateGS("null"); -# ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) dest.hs = RImplementation.Resources->_CreateHS("null"); dest.ds = RImplementation.Resources->_CreateDS("null"); dest.cs = RImplementation.Resources->_CreateCS("null"); @@ -142,7 +142,7 @@ u32 CBlender_Compile::r_Sampler( dwStage = i_Sampler(_name); if (u32(-1) != dwStage) { -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) r_dx11Texture(_name, texture, true); #elif defined(USE_DX9) || defined(USE_OGL) i_Texture(dwStage, texture); diff --git a/src/Layers/xrRender/Blender_Recorder_StandartBinding.cpp b/src/Layers/xrRender/Blender_Recorder_StandartBinding.cpp index b0c1672f8c2..f7a81484e7e 100644 --- a/src/Layers/xrRender/Blender_Recorder_StandartBinding.cpp +++ b/src/Layers/xrRender/Blender_Recorder_StandartBinding.cpp @@ -78,7 +78,7 @@ class cl_texgen : public R_constant_setup 0.0f, 0.0f, 1.0f, 0.0f, 0.5f + o_w, 0.5f + o_h, 0.0f, 1.0f }; -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) Fmatrix mTexelAdjust = { 0.5f, 0.0f, 0.0f, 0.0f, @@ -122,7 +122,7 @@ class cl_VPtexgen : public R_constant_setup 0.0f, 0.0f, 1.0f, 0.0f, 0.5f + o_w, 0.5f + o_h, 0.0f, 1.0f }; -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) Fmatrix mTexelAdjust = { 0.5f, 0.0f, 0.0f, 0.0f, diff --git a/src/Layers/xrRender/ColorMapManager.cpp b/src/Layers/xrRender/ColorMapManager.cpp index 7f1c9ab3f29..89cf3ebbb7a 100644 --- a/src/Layers/xrRender/ColorMapManager.cpp +++ b/src/Layers/xrRender/ColorMapManager.cpp @@ -26,7 +26,7 @@ void ColorMapManager::UpdateTexture(const shared_str& strTexName, int iTex) if (I != m_TexCache.end()) { -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) ID3DBaseTexture* e0 = I->second->surface_get(); m_CMap[iTex]->surface_set(e0); _RELEASE(e0); @@ -44,7 +44,7 @@ void ColorMapManager::UpdateTexture(const shared_str& strTexName, int iTex) m_TexCache.emplace(strTexName, tmp); -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) ID3DBaseTexture* e0 = tmp->surface_get(); m_CMap[iTex]->surface_set(e0); _RELEASE(e0); @@ -58,7 +58,7 @@ void ColorMapManager::UpdateTexture(const shared_str& strTexName, int iTex) } else { -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) m_CMap[iTex]->surface_set(nullptr); #elif defined(USE_OGL) m_CMap[iTex]->surface_set(GL_TEXTURE_2D, 0); diff --git a/src/Layers/xrRender/D3DXRenderBase.cpp b/src/Layers/xrRender/D3DXRenderBase.cpp index 59627d0da57..47fd3d500df 100644 --- a/src/Layers/xrRender/D3DXRenderBase.cpp +++ b/src/Layers/xrRender/D3DXRenderBase.cpp @@ -51,7 +51,7 @@ void D3DXRenderBase::OnDeviceDestroy(bool bKeepTextures) destroy(); Resources->OnDeviceDestroy(bKeepTextures); -#if RENDER == R_R4 +#if RENDER == R_R4 || RENDER == R_R5 for (int id = 0; id < R__NUM_CONTEXTS; ++id) { contexts_pool[id].cmd_list.OnDeviceDestroy(); @@ -76,13 +76,12 @@ void D3DXRenderBase::Destroy() void D3DXRenderBase::Reset(SDL_Window* hWnd, u32& dwWidth, u32& dwHeight, float& fWidth_2, float& fHeight_2) { -#if defined(DEBUG) && (defined(USE_DX9) || defined(USE_DX11)) +#if defined(DEBUG) && (defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12)) _SHOW_REF("*ref -CRenderDevice::ResetTotal: DeviceREF:", HW.pDevice); #endif // DEBUG reset_begin(); Memory.mem_compact(); - HW.Reset(); std::tie(dwWidth, dwHeight) = HW.GetSurfaceSize(); @@ -98,7 +97,7 @@ void D3DXRenderBase::Reset(SDL_Window* hWnd, u32& dwWidth, u32& dwHeight, float& Resources->Dump(true); #endif -#if defined(DEBUG) && (defined(USE_DX9) || defined(USE_DX11)) +#if defined(DEBUG) && (defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12)) _SHOW_REF("*ref +CRenderDevice::ResetTotal: DeviceREF:", HW.pDevice); #endif } @@ -111,7 +110,7 @@ void D3DXRenderBase::ObtainRequiredWindowFlags(u32& windowFlags) void D3DXRenderBase::SetupStates() { HW.Caps.Update(); -#if RENDER == R_R4 +#if RENDER == R_R4 || RENDER == R_R5 for (int id = 0; id < R__NUM_CONTEXTS; ++id) { contexts_pool[id].cmd_list.SetupStates(); @@ -131,7 +130,7 @@ void D3DXRenderBase::OnDeviceCreate(const char* shName) CreateQuadIB(); -#if RENDER == R_R4 +#if RENDER == R_R4 || RENDER == R_R5 for (int id = 0; id < R__NUM_CONTEXTS; ++id) { contexts_pool[id].cmd_list.context_id = id; @@ -157,7 +156,7 @@ void D3DXRenderBase::OnDeviceCreate(const char* shName) void D3DXRenderBase::Create(SDL_Window* hWnd, u32& dwWidth, u32& dwHeight, float& fWidth_2, float& fHeight_2) { -#if defined(USE_RENDERDOC) && defined(USE_DX11) +#if defined(USE_RENDERDOC) && (defined(USE_DX11) || defined(USE_DX12)) if (!g_renderdoc_api) { HMODULE hModule = GetModuleHandleA("renderdoc.dll"); @@ -257,7 +256,7 @@ u32 D3DXRenderBase::GetCacheStatPolys() void D3DXRenderBase::Begin() { HW.BeginScene(); -#if RENDER == R_R4 +#if RENDER == R_R4 || RENDER == R_R5 for (int id = 0; id < R__NUM_CONTEXTS; ++id) { contexts_pool[id].cmd_list.OnFrameBegin(); @@ -290,7 +289,7 @@ void D3DXRenderBase::End() { if (HW.Caps.SceneMode) overdrawEnd(); - #if RENDER == R_R4 +#if RENDER == R_R4 || RENDER == R_R5 for (int id = 0; id < R__NUM_CONTEXTS; ++id) { contexts_pool[id].cmd_list.OnFrameEnd(); @@ -318,7 +317,7 @@ void D3DXRenderBase::ClearTarget() void D3DXRenderBase::SetCacheXform(Fmatrix& mView, Fmatrix& mProject) { -#if RENDER == R_R4 +#if RENDER == R_R4 || RENDER == R_R5 for (int id = 0; id < R__NUM_CONTEXTS; ++id) { contexts_pool[id].cmd_list.set_xform_view(mView); diff --git a/src/Layers/xrRender/Debug/dxPixEventWrapper.h b/src/Layers/xrRender/Debug/dxPixEventWrapper.h index 87d21c8693c..b639e170752 100644 --- a/src/Layers/xrRender/Debug/dxPixEventWrapper.h +++ b/src/Layers/xrRender/Debug/dxPixEventWrapper.h @@ -4,7 +4,7 @@ # define PIX_EVENT(Name) do { } while (false) # define PIX_EVENT_CTX(C,Name) do { } while (false) #else -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) # define PIX_EVENT(Name) dxPixEventWrapper pixEvent##Name(RCache,L ## #Name) # define PIX_EVENT_CTX(C,Name) dxPixEventWrapper pixEvent##Name(C,L ## #Name) diff --git a/src/Layers/xrRender/DetailManager.h b/src/Layers/xrRender/DetailManager.h index 8038027080b..d020f53d259 100644 --- a/src/Layers/xrRender/DetailManager.h +++ b/src/Layers/xrRender/DetailManager.h @@ -205,7 +205,7 @@ class ECORE_API CDetailManager void hw_Render(CBackend& cmd_list); #if defined(USE_DX9) void hw_Render_dump(CBackend& cmd_list, ref_constant array, u32 var_id, u32 lod_id, u32 c_base); -#elif defined(USE_DX11) || defined(USE_OGL) +#elif defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) void hw_Render_dump(CBackend& cmd_list, const Fvector4& consts, const Fvector4& wave, const Fvector4& wind, u32 var_id, u32 lod_id); #else # error No graphics API selected or enabled! diff --git a/src/Layers/xrRender/DetailModel.cpp b/src/Layers/xrRender/DetailModel.cpp index 9b255fa89aa..abbe2d38f16 100644 --- a/src/Layers/xrRender/DetailModel.cpp +++ b/src/Layers/xrRender/DetailModel.cpp @@ -113,12 +113,12 @@ void CDetail::Load(IReader* S) bv_bb.modify(vertices[i].P); bv_bb.getsphere(bv_sphere.P, bv_sphere.R); -#if !defined(_EDITOR) && (defined(USE_DX9) || defined(USE_DX11)) +#if !defined(_EDITOR) && (defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12)) Optimize(); #endif } -#if !defined(_EDITOR) && (defined(USE_DX9) || defined(USE_DX11)) +#if !defined(_EDITOR) && (defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12)) #include "xrstripify.h" void CDetail::Optimize() diff --git a/src/Layers/xrRender/FTreeVisual.cpp b/src/Layers/xrRender/FTreeVisual.cpp index ea4f4481ff2..917511b6bdb 100644 --- a/src/Layers/xrRender/FTreeVisual.cpp +++ b/src/Layers/xrRender/FTreeVisual.cpp @@ -172,7 +172,7 @@ void FTreeVisual::Render(CBackend& cmd_list, float /*LOD*/, bool use_fast_geo) #endif cmd_list.tree.set_c_sun(s * c_scale.sun, s * c_bias.sun, 0, 0); // sun -#if RENDER == R_R4 +#if RENDER == R_R4 || RENDER == R_R5 if (ps_ssfx_grass_interactive.y > 0) { // Inter grass Settings diff --git a/src/Layers/xrRender/FVF.h b/src/Layers/xrRender/FVF.h index 048c6a86f2c..ed33bd1a8dc 100644 --- a/src/Layers/xrRender/FVF.h +++ b/src/Layers/xrRender/FVF.h @@ -4,7 +4,7 @@ #if defined(USE_DX9) # define FVF_COLOR(c) (c) -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) # define FVF_COLOR(c) ((c & 0xff00ff00) | ((c >> 16) & 0xff) | ((c & 0xff) << 16u)) #elif defined(USE_OGL) //the compiler should know to dedup this, defined explicitly for organization # define FVF_COLOR(c) (c) diff --git a/src/Layers/xrRender/HOM.cpp b/src/Layers/xrRender/HOM.cpp index 8438b10689d..5e1e57e2d3d 100644 --- a/src/Layers/xrRender/HOM.cpp +++ b/src/Layers/xrRender/HOM.cpp @@ -154,7 +154,7 @@ void CHOM::Render_DB(CFrustum& base) { // Update projection matrices on every frame to ensure valid HOM culling float view_dim = occ_dim_0; -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) Fmatrix m_viewport = {view_dim / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, view_dim / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, view_dim / 2.f + 0 + 0, view_dim / 2.f + 0 + 0, 0.0f, 1.0f}; Fmatrix m_viewport_01 = {1.f / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.f / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, diff --git a/src/Layers/xrRender/Light_Package.cpp b/src/Layers/xrRender/Light_Package.cpp index cecdc6c3f59..dfcac5ebc58 100644 --- a/src/Layers/xrRender/Light_Package.cpp +++ b/src/Layers/xrRender/Light_Package.cpp @@ -8,7 +8,7 @@ void light_Package::clear() v_shadowed.clear(); } -#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_GL) +#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) || (RENDER == R_GL) void light_Package::sort() { const auto pred_light_cmp = [](const light* l1, const light* l2) diff --git a/src/Layers/xrRender/ParticleEffect.cpp b/src/Layers/xrRender/ParticleEffect.cpp index d51708ef885..65f72f27509 100644 --- a/src/Layers/xrRender/ParticleEffect.cpp +++ b/src/Layers/xrRender/ParticleEffect.cpp @@ -44,7 +44,7 @@ static void ApplyTexgen(CBackend& cmd_list, const Fmatrix& mVP) 0.0f, 0.0f, 1.0f, 0.0f, 0.5f + o_w, 0.5f + o_h, 0.0f, 1.0f }; -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) Fmatrix mTexelAdjust = { 0.5f, 0.0f, 0.0f, 0.0f, diff --git a/src/Layers/xrRender/QueryHelper.h b/src/Layers/xrRender/QueryHelper.h index c217a4f3bd7..3a5d76771c2 100644 --- a/src/Layers/xrRender/QueryHelper.h +++ b/src/Layers/xrRender/QueryHelper.h @@ -3,7 +3,7 @@ #pragma once // Interface -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) IC HRESULT CreateQuery(ID3DQuery** ppQuery); IC HRESULT GetData(ID3DQuery* pQuery, void* pData, u32 DataSize); IC HRESULT BeginQuery(ID3DQuery* pQuery); @@ -38,7 +38,7 @@ IC HRESULT ReleaseQuery(ID3DQuery* pQuery) return S_OK; } -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) IC HRESULT CreateQuery(ID3DQuery** ppQuery, D3D_QUERY type) { diff --git a/src/Layers/xrRender/R_Backend.h b/src/Layers/xrRender/R_Backend.h index 507aa2aa77d..2d9bf56ba8a 100644 --- a/src/Layers/xrRender/R_Backend.h +++ b/src/Layers/xrRender/R_Backend.h @@ -17,8 +17,13 @@ #include "R_Backend_hemi.h" #include "R_Backend_tree.h" -#ifdef USE_DX11 +#if defined(USE_DX11) #include "Layers/xrRenderPC_R4/r_backend_lod.h" +#elif defined(USE_DX12) +#include "Layers/xrRenderPC_R5/r_backend_lod.h" +#endif + +#if defined(USE_DX11) || defined(USE_DX12) #include "Layers/xrRenderDX11/StateManager/dx11StateManager.h" #include "Layers/xrRenderDX11/StateManager/dx11ShaderResourceStateCache.h" #include "Layers/xrRenderDX11/StateManager/dx11StateCache.h" @@ -71,11 +76,11 @@ class ECORE_API CBackend R_xforms xforms; R_hemi hemi; R_tree tree; -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) R_LOD LOD; #endif -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ref_cbuffer m_aVertexConstants[MaxCBuffers]; ref_cbuffer m_aPixelConstants[MaxCBuffers]; @@ -93,7 +98,10 @@ class ECORE_API CBackend #endif private: // Render-targets -#if defined(USE_DX9) || defined (USE_DX11) +#if defined(USE_DX12) + ID3DRenderTargetView* pRT[8]; + ID3DDepthStencilView* pZB; +#elif defined(USE_DX9) || defined(USE_DX11) ID3DRenderTargetView* pRT[4]; ID3DDepthStencilView* pZB; #elif defined(USE_OGL) @@ -119,7 +127,7 @@ class ECORE_API CBackend #if defined(USE_DX9) ID3DPixelShader* ps; ID3DVertexShader* vs; -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) ID3DPixelShader* ps; ID3DVertexShader* vs; ID3DGeometryShader* gs; @@ -140,7 +148,7 @@ class ECORE_API CBackend LPCSTR vs_name; #ifndef USE_DX9 LPCSTR gs_name; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) LPCSTR hs_name; LPCSTR ds_name; LPCSTR cs_name; @@ -177,7 +185,7 @@ class ECORE_API CBackend CTexture* textures_vs[CTexture::mtMaxVertexShaderTextures]; // 4 vs #ifndef USE_DX9 CTexture* textures_gs[CTexture::mtMaxGeometryShaderTextures]; // 4 vs -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) CTexture* textures_hs[CTexture::mtMaxHullShaderTextures]; // 4 vs CTexture* textures_ds[CTexture::mtMaxDomainShaderTextures]; // 4 vs CTexture* textures_cs[CTexture::mtMaxComputeShaderTextures]; // 4 vs @@ -237,7 +245,7 @@ class ECORE_API CBackend if (stage < CTexture::rstGeometry) return textures_vs[stage - CTexture::rstVertex]; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) if (stage < CTexture::rstHull) return textures_gs[stage - CTexture::rstGeometry]; @@ -263,7 +271,7 @@ class ECORE_API CBackend #if defined(USE_DX9) R_constant_array& get_ConstantCache_Vertex() { return constants.a_vertex; } R_constant_array& get_ConstantCache_Pixel() { return constants.a_pixel; } -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) IC void get_ConstantDirect(const shared_str& n, size_t DataSize, void** pVData, void** pGData, void** pPData); #endif @@ -283,7 +291,7 @@ class ECORE_API CBackend IC void set_pass_targets(const ref_rt& mrt0, const ref_rt& mrt1, const ref_rt& mrt2, const ref_rt& zb); -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) IC void set_RT(ID3DRenderTargetView* RT, u32 ID = 0); IC void set_ZB(ID3DDepthStencilView* ZB); IC ID3DRenderTargetView* get_RT(u32 ID = 0); @@ -299,7 +307,7 @@ class ECORE_API CBackend # error No graphics API selected or enabled! #endif -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) IC void ClearRT(ID3DRenderTargetView* rt, const Fcolor& color); IC void ClearZB(ID3DDepthStencilView* zb, float depth); @@ -332,7 +340,7 @@ class ECORE_API CBackend { return ClearZBRect(zb->pRT, depth, numRects, rects); } -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) ICF void ClearZB(ref_rt& zb, float depth) { ClearZB(zb->pZRT[context_id], depth); } ICF void ClearZB(ref_rt& zb, float depth, u8 stencil) { ClearZB(zb->pZRT[context_id], depth, stencil); } ICF bool ClearZBRect(ref_rt& zb, float depth, size_t numRects, const Irect* rects) @@ -367,7 +375,7 @@ class ECORE_API CBackend ICF void set_Format(SDeclaration* _decl); private: -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) ICF void set_PS(ID3DPixelShader* _ps, LPCSTR _n = nullptr); #elif defined(USE_OGL) ICF void set_PS(GLuint _ps, LPCSTR _n = 0); @@ -380,7 +388,7 @@ class ECORE_API CBackend #ifndef USE_DX9 ICF void set_GS(ref_gs& _gs) { set_GS(_gs->sh, _gs->cName.c_str()); } -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ICF void set_GS(ID3DGeometryShader* _gs, LPCSTR _n = nullptr); ICF void set_HS(ID3D11HullShader* _hs, LPCSTR _n = nullptr); @@ -398,11 +406,11 @@ class ECORE_API CBackend ICF void set_VS(ref_vs& _vs); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ICF void set_VS(SVS* _vs); #endif -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) ICF void set_VS(ID3DVertexShader* _vs, LPCSTR _n = nullptr); #elif defined(USE_OGL) ICF void set_VS(GLuint _vs, LPCSTR _n = 0); @@ -411,7 +419,7 @@ class ECORE_API CBackend #endif public: -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ICF void set_CS(ID3D11ComputeShader* _cs, LPCSTR _n = nullptr); ICF void set_CS(ref_cs& _cs) { set_CS(_cs->sh, _cs->cName.c_str()); } ICF void Compute(u32 ThreadGroupCountX, u32 ThreadGroupCountY, u32 ThreadGroupCountZ); @@ -420,7 +428,7 @@ class ECORE_API CBackend public: #if defined(USE_DX9) || defined(USE_OGL) ICF bool is_TessEnabled() { return false; } -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) ICF bool is_TessEnabled(); #else # error No graphics API selected or enabled! @@ -530,7 +538,7 @@ class ECORE_API CBackend ICF void submit() { -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) VERIFY(context_id != CHW::IMM_CTX_ID); ID3D11CommandList* pCommandList{ nullptr }; CHK_DX(HW.get_context(context_id)->FinishCommandList(false, &pCommandList)); @@ -580,7 +588,7 @@ class ECORE_API CBackend : xforms(*this) , tree(*this) , hemi(*this) -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) , LOD(*this) , constants(*this) , StateManager(*this) @@ -600,7 +608,7 @@ class ECORE_API CBackend ref_geom vs_TL; #endif -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) private: // DirectX 11+ internal functionality // void CreateConstantBuffers(); diff --git a/src/Layers/xrRender/R_Backend_DBG.cpp b/src/Layers/xrRender/R_Backend_DBG.cpp index 4d117f569f0..8cef1a3e6ee 100644 --- a/src/Layers/xrRender/R_Backend_DBG.cpp +++ b/src/Layers/xrRender/R_Backend_DBG.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" #pragma hdrstop -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) extern IC u32 GetIndexCount(D3DPRIMITIVETYPE T, u32 iPrimitiveCount); #endif @@ -258,7 +258,7 @@ void CBackend::dbg_OverdrawEnd() // Draw a rectangle wherever the count equal I #if defined(USE_DX9) CHK_DX(HW.pDevice->SetFVF(FVF::F_TL)); -#elif defined(USE_DX11) || defined(USE_OGL) +#elif defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) set_Geometry(vs_TL); #else # error No graphics API defined or enabled! @@ -277,7 +277,7 @@ void CBackend::dbg_OverdrawEnd() pv[3].set(float(Device.dwWidth), float(0), c, 0, 0); CHK_DX(HW.pDevice->SetRenderState(D3DRS_STENCILREF, I)); CHK_DX(HW.pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pv, sizeof(FVF::TL))); -#elif defined(USE_DX11) || defined(USE_OGL) +#elif defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) u32 vBase; FVF::TL* pv = (FVF::TL*)RImplementation.Vertex.Lock(4, vs_L->vb_stride, vBase); pv[0].set(float(0), float(Device.dwHeight), c, 0, 0); @@ -300,7 +300,7 @@ void CBackend::dbg_SetRS(D3DRENDERSTATETYPE p1, u32 p2) { #ifdef USE_DX9 CHK_DX(HW.pDevice->SetRenderState(p1, p2)); -#elif defined(USE_DX11) || defined(USE_OGL) +#elif defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) VERIFY(!"Not implemented"); #else # error No graphics API defined or enabled! @@ -311,7 +311,7 @@ void CBackend::dbg_SetSS(u32 sampler, D3DSAMPLERSTATETYPE type, u32 value) { #ifdef USE_DX9 CHK_DX(HW.pDevice->SetSamplerState(sampler, type, value)); -#elif defined(USE_DX11) || defined(USE_OGL) +#elif defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) VERIFY(!"Not implemented"); #else # error No graphics API defined or enabled! diff --git a/src/Layers/xrRender/R_Backend_Runtime.cpp b/src/Layers/xrRender/R_Backend_Runtime.cpp index 439699a6789..5a3a59fb011 100644 --- a/src/Layers/xrRender/R_Backend_Runtime.cpp +++ b/src/Layers/xrRender/R_Backend_Runtime.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" #pragma hdrstop -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) #include #endif @@ -68,7 +68,7 @@ void CBackend::Invalidate() ps = 0; vs = 0; DX11_ONLY(gs = NULL); -#ifdef USE_DX11 +#if defined (USE_DX11) || defined(USE_DX12) hs = 0; ds = 0; cs = 0; @@ -98,7 +98,7 @@ void CBackend::Invalidate() // transform setting handlers should be unmapped too. xforms.unmap(); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) m_pInputLayout = NULL; m_PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; m_bChangedRTorZB = false; @@ -172,7 +172,7 @@ void CBackend::set_ClipPlanes(u32 _enable, Fplane* _planes /*=NULL */, u32 count // Enable them u32 e_mask = (1 << count) - 1; CHK_DX(HW.pDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, e_mask)); -#elif defined(USE_DX11) || defined(USE_OGL) +#elif defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) // TODO: DX11: Implement in the corresponding vertex shaders // Use this to set up location, were shader setup code will get data // VERIFY(!"CBackend::set_ClipPlanes not implemented!"); @@ -194,7 +194,7 @@ void CBackend::set_ClipPlanes(u32 _enable, Fmatrix* _xform /*=NULL */, u32 fmask { #if defined(USE_DX9) CHK_DX(HW.pDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, FALSE)); -#elif defined(USE_DX11) || defined(USE_OGL) +#elif defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) // TODO: DX11: Implement in the corresponding vertex shaders // Use this to set up location, were shader setup code will get data // VERIFY(!"CBackend::set_ClipPlanes not implemented!"); @@ -218,7 +218,7 @@ void CBackend::set_Textures(STextureList* textures_list) // If resources weren't set at all we should clear from resource #0. int _last_ps = -1; int _last_vs = -1; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) int _last_gs = -1; int _last_hs = -1; int _last_ds = -1; @@ -255,7 +255,7 @@ void CBackend::set_Textures(STextureList* textures_list) } } else -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) if (load_id < CTexture::rstGeometry) #endif { @@ -279,7 +279,7 @@ void CBackend::set_Textures(STextureList* textures_list) } } } -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) else if (load_id < CTexture::rstHull) { // Set up pixel shader resources @@ -384,7 +384,7 @@ void CBackend::set_Textures(STextureList* textures_list) textures_ps[_last_ps] = nullptr; #if defined(USE_DX9) CHK_DX(HW.pDevice->SetTexture(_last_ps, NULL)); -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) // TODO: DX11: Optimise: set all resources at once ID3DShaderResourceView* pRes = 0; // HW.pDevice->PSSetShaderResources(_last_ps, 1, &pRes); @@ -409,7 +409,7 @@ void CBackend::set_Textures(STextureList* textures_list) textures_vs[_last_vs] = nullptr; #if defined(USE_DX9) CHK_DX(HW.pDevice->SetTexture(_last_vs + CTexture::rstVertex, NULL)); -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) // TODO: DX11: Optimise: set all resources at once ID3DShaderResourceView* pRes = 0; // HW.pDevice->VSSetShaderResources(_last_vs, 1, &pRes); @@ -426,7 +426,7 @@ void CBackend::set_Textures(STextureList* textures_list) #endif } -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) // clear remaining stages (VS) for (++_last_gs; _last_gs < CTexture::mtMaxGeometryShaderTextures; _last_gs++) { @@ -534,7 +534,7 @@ void CBackend::SetupStates() CHK_DX(HW.pDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE)); CHK_DX(HW.pDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR)); } -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) SSManager.SetMaxAnisotropy(ps_r__tf_Anisotropic); SSManager.SetMipLODBias(ps_r__tf_Mipbias); #elif defined(USE_OGL) @@ -548,7 +548,7 @@ void CBackend::SetupStates() // Device dependance void CBackend::OnDeviceCreate() { -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) HW.get_context(context_id)->QueryInterface(__uuidof(ID3DUserDefinedAnnotation), reinterpret_cast(&pAnnotation)); #endif @@ -564,12 +564,12 @@ void CBackend::OnDeviceDestroy() // Debug Draw DestroyDebugDraw(); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) // Destroy state managers StateManager.Reset(); #endif -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) _RELEASE(pAnnotation); #endif } @@ -586,7 +586,7 @@ void CBackend::apply_lmaterial() VERIFY(RC_dest_sampler == C->destination); #if defined(USE_DX9) VERIFY(RC_sampler == C->type); -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) VERIFY(RC_dx11texture == C->type); #elif defined(USE_OGL) VERIFY(RC_sampler == C->type); diff --git a/src/Layers/xrRender/R_Backend_Runtime.h b/src/Layers/xrRender/R_Backend_Runtime.h index 6bb1500cb4c..3bb5df5c7fe 100644 --- a/src/Layers/xrRender/R_Backend_Runtime.h +++ b/src/Layers/xrRender/R_Backend_Runtime.h @@ -11,7 +11,7 @@ #if defined(USE_DX9) #include "Layers/xrRenderDX9/dx9R_Backend_Runtime.h" -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) #include "Layers/xrRenderDX11/dx11R_Backend_Runtime.h" #elif defined(USE_OGL) #include "Layers/xrRenderGL/glR_Backend_Runtime.h" @@ -60,7 +60,7 @@ IC void CBackend::set_xform_project(const Fmatrix& M) { xforms.set_P(M); } IC const Fmatrix& CBackend::get_xform_world() { return xforms.get_W(); } IC const Fmatrix& CBackend::get_xform_view() { return xforms.get_V(); } IC const Fmatrix& CBackend::get_xform_project() { return xforms.get_P(); } -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) IC ID3DRenderTargetView* CBackend::get_RT(u32 ID) #elif defined(USE_OGL) IC GLuint CBackend::get_RT(u32 ID) @@ -73,7 +73,7 @@ IC GLuint CBackend::get_RT(u32 ID) return pRT[ID]; } -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) IC ID3DDepthStencilView* CBackend::get_ZB() #elif defined(USE_OGL) IC GLuint CBackend::get_ZB() @@ -93,7 +93,7 @@ ICF void CBackend::set_States(SState* _state) PGO(Msg("PGO:state_block")); stat.states++; state = _state->state; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) state->Apply(*this); #else state->Apply(); @@ -134,7 +134,7 @@ IC void CBackend::set_Pass(SPass* P) { set_PS(P->ps); set_VS(P->vs); -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) set_GS(P->gs); set_HS(P->hs); set_DS(P->ds); diff --git a/src/Layers/xrRender/ResourceManager.cpp b/src/Layers/xrRender/ResourceManager.cpp index 7cb8c733b22..4bc27836866 100644 --- a/src/Layers/xrRender/ResourceManager.cpp +++ b/src/Layers/xrRender/ResourceManager.cpp @@ -172,7 +172,7 @@ Shader* CResourceManager::_cpp_Create( _ParseList(C.L_constants, s_constants); _ParseList(C.L_matrices, s_matrices); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) if (RImplementation.hud_loading && RImplementation.o.new_shader_support) { C.HudElement = true; @@ -364,7 +364,7 @@ void CResourceManager::DeferredUpload() if (!Device.b_is_Ready) return; -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) xr_parallel_for_each(m_textures, [&](auto m_tex) { m_tex.second->Load(); }); #elif defined(USE_OGL) // XXX: OGL: Set additional contexts for all worker threads? for (auto& texture : m_textures) @@ -379,7 +379,7 @@ void CResourceManager::DeferredUnload() if (!Device.b_is_Ready) return; -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) xr_parallel_for_each(m_textures, [&](auto m_tex) { m_tex.second->Unload(); }); #elif defined(USE_OGL) // XXX: OGL: Set additional contexts for all worker threads? for (auto& texture : m_textures) diff --git a/src/Layers/xrRender/ResourceManager.h b/src/Layers/xrRender/ResourceManager.h index ef5dd5c336b..533c6cdd7b4 100644 --- a/src/Layers/xrRender/ResourceManager.h +++ b/src/Layers/xrRender/ResourceManager.h @@ -38,11 +38,11 @@ class ECORE_API CResourceManager // DX10 cut DEFINE_MAP_PRED(const char*,CRTC*, map_RTC, map_RTCIt, str_pred); using map_VS = xr_map; -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) using map_GS = xr_map; #endif -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) using map_HS = xr_map; using map_DS = xr_map; using map_CS = xr_map; @@ -65,11 +65,11 @@ class ECORE_API CResourceManager map_VS m_vs; map_PS m_ps; -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) map_GS m_gs; #endif -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) map_DS m_ds; map_HS m_hs; map_CS m_cs; @@ -85,7 +85,7 @@ class ECORE_API CResourceManager xr_vector v_geoms; xr_vector v_constant_tables; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) xr_vector v_constant_buffer[R__NUM_CONTEXTS]; xr_vector v_input_signature; #endif @@ -117,6 +117,7 @@ class ECORE_API CResourceManager void LS_Unload(); public: + // Miscelaneous void _ParseList(sh_list& dest, LPCSTR names); IBlender* _GetBlender(LPCSTR Name); @@ -151,7 +152,7 @@ class ECORE_API CResourceManager R_constant_table* _CreateConstantTable(R_constant_table& C); void _DeleteConstantTable(const R_constant_table* C); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) dx11ConstantBuffer* _CreateConstantBuffer(u32 context_id, ID3DShaderReflectionConstantBuffer* pTable); void _DeleteConstantBuffer(u32 context_id, const dx11ConstantBuffer* pBuffer); @@ -159,7 +160,11 @@ class ECORE_API CResourceManager void _DeleteInputSignature(const SInputSignature* pSignature); #endif +#if defined(USE_DX12) + CRT* _CreateRT(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount = 1, u32 slices_num = 1, Flags32 flags = {}, Fcolor color = {0.0f, 0.0f, 0.0f, 0.0f}); +#else CRT* _CreateRT(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount = 1, u32 slices_num = 1, Flags32 flags = {}); +#endif void _DeleteRT(const CRT* RT); // DX10 cut CRTC* _CreateRTC (LPCSTR Name, u32 size, D3DFORMAT f); @@ -171,12 +176,12 @@ class ECORE_API CResourceManager void _DeletePP(const SPP* p); #endif -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) SGS* _CreateGS(LPCSTR Name); void _DeleteGS(const SGS* GS); #endif -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) SHS* _CreateHS(LPCSTR Name); void _DeleteHS(const SHS* HS); diff --git a/src/Layers/xrRender/ResourceManager_Reset.cpp b/src/Layers/xrRender/ResourceManager_Reset.cpp index b99b7733b87..eeb0ebbef68 100644 --- a/src/Layers/xrRender/ResourceManager_Reset.cpp +++ b/src/Layers/xrRender/ResourceManager_Reset.cpp @@ -130,11 +130,11 @@ void CResourceManager::Dump(bool bBrief) Msg("* RM_Dump: ps : %d", m_ps.size()); if (!bBrief) mdump(m_ps); -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) Msg("* RM_Dump: gs : %d", m_gs.size()); if (!bBrief) mdump(m_gs); -# ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) Msg("* RM_Dump: cs : %d", m_cs.size()); if (!bBrief) mdump(m_cs); diff --git a/src/Layers/xrRender/ResourceManager_Resources.cpp b/src/Layers/xrRender/ResourceManager_Resources.cpp index b12e3cb060b..383b2b17c9b 100644 --- a/src/Layers/xrRender/ResourceManager_Resources.cpp +++ b/src/Layers/xrRender/ResourceManager_Resources.cpp @@ -96,7 +96,11 @@ void CResourceManager::_DeleteConstantTable(const R_constant_table* C) Msg("! ERROR: Failed to find compiled constant-table"); } +#if defined(USE_DX12) +CRT* CResourceManager::_CreateRT(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 sampleCount /* = 1 */, u32 slices_num /*=1*/, Flags32 flags /*= {}*/, Fcolor color) +#else CRT* CResourceManager::_CreateRT(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 sampleCount /* = 1 */, u32 slices_num /*=1*/, Flags32 flags /*= {}*/) +#endif { R_ASSERT(Name && Name[0] && w && h); @@ -111,7 +115,11 @@ CRT* CResourceManager::_CreateRT(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 sam RT->dwFlags |= xr_resource_flagged::RF_REGISTERED; m_rtargets.emplace(RT->set_name(Name), RT); if (Device.b_is_Ready) +#if defined(USE_DX12) + RT->create(Name, w, h, f, sampleCount, slices_num, flags, color); +#else RT->create(Name, w, h, f, sampleCount, slices_num, flags); +#endif return RT; } } diff --git a/src/Layers/xrRender/SH_Atomic.cpp b/src/Layers/xrRender/SH_Atomic.cpp index 861418867eb..84ae26e3afb 100644 --- a/src/Layers/xrRender/SH_Atomic.cpp +++ b/src/Layers/xrRender/SH_Atomic.cpp @@ -29,7 +29,7 @@ /////////////////////////////////////////////////////////////////////// // SVS SVS::SVS() : sh(0) -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) // ,signature(0) #endif {} @@ -38,13 +38,13 @@ SVS::~SVS() { RImplementation.Resources->_DeleteVS(this); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) // XXX: check just in case //_RELEASE(signature); // Now it is release automatically #endif -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) _RELEASE(sh); #elif defined(USE_OGL) if (HW.SeparateShaderObjectsSupported) @@ -60,7 +60,7 @@ SVS::~SVS() // SPS SPS::~SPS() { -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) _RELEASE(sh); #elif defined(USE_OGL) if (HW.SeparateShaderObjectsSupported) @@ -74,12 +74,12 @@ SPS::~SPS() RImplementation.Resources->_DeletePS(this); } -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) /////////////////////////////////////////////////////////////////////// // SGS SGS::~SGS() { -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) _RELEASE(sh); # elif defined(USE_OGL) if (HW.SeparateShaderObjectsSupported) @@ -95,7 +95,7 @@ SGS::~SGS() SHS::~SHS() { -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) _RELEASE(sh); # elif defined(USE_OGL) if (HW.SeparateShaderObjectsSupported) @@ -111,7 +111,7 @@ SHS::~SHS() SDS::~SDS() { -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) _RELEASE(sh); # elif defined(USE_OGL) if (HW.SeparateShaderObjectsSupported) @@ -125,7 +125,7 @@ SDS::~SDS() SCS::~SCS() { -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) _RELEASE(sh); # elif defined(USE_OGL) if (HW.SeparateShaderObjectsSupported) @@ -153,7 +153,7 @@ SPP::~SPP() #endif // USE_OGL -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) /////////////////////////////////////////////////////////////////////// // SInputSignature SInputSignature::SInputSignature(ID3DBlob* pBlob) @@ -186,7 +186,7 @@ SDeclaration::~SDeclaration() // Release vertex layout #ifdef USE_OGL glDeleteVertexArrays(1, &dcl); -#elif defined(USE_DX11) || defined(USE_OGL) +#elif defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) xr_map::iterator iLayout; iLayout = vs_to_layout.begin(); for (; iLayout != vs_to_layout.end(); ++iLayout) diff --git a/src/Layers/xrRender/SH_Atomic.h b/src/Layers/xrRender/SH_Atomic.h index a81bc5e5bf2..2561f4b8da9 100644 --- a/src/Layers/xrRender/SH_Atomic.h +++ b/src/Layers/xrRender/SH_Atomic.h @@ -5,7 +5,7 @@ #include "xrCore/xr_resource.h" #include "tss_def.h" -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) #include "Layers/xrRenderDX11/StateManager/dx11State.h" #elif defined(USE_OGL) #include "Layers/xrRenderGL/glState.h" @@ -16,7 +16,7 @@ ////////////////////////////////////////////////////////////////////////// // Atomic resources ////////////////////////////////////////////////////////////////////////// -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) struct ECORE_API SInputSignature : public xr_resource_flagged { ID3DBlob* signature; @@ -28,7 +28,7 @@ typedef resptr_core> ref_input_sig ////////////////////////////////////////////////////////////////////////// struct ECORE_API SVS : public xr_resource_named { -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) ID3DVertexShader* sh; #elif defined(USE_OGL) GLuint sh; @@ -36,7 +36,7 @@ struct ECORE_API SVS : public xr_resource_named # error No graphics API selected or enabled! #endif R_constant_table constants; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ref_input_sign signature; #endif SVS(); @@ -47,7 +47,7 @@ typedef resptr_core> ref_vs; ////////////////////////////////////////////////////////////////////////// struct ECORE_API SPS : public xr_resource_named { -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) ID3DPixelShader* sh; #elif defined(USE_OGL) GLuint sh; @@ -59,11 +59,11 @@ struct ECORE_API SPS : public xr_resource_named }; typedef resptr_core> ref_ps; -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) ////////////////////////////////////////////////////////////////////////// struct ECORE_API SGS : public xr_resource_named { -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ID3DGeometryShader* sh; # elif defined(USE_OGL) GLuint sh; @@ -77,7 +77,7 @@ typedef resptr_core> ref_gs; struct ECORE_API SHS : public xr_resource_named { -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ID3D11HullShader* sh; # elif defined(USE_OGL) GLuint sh; @@ -91,7 +91,7 @@ typedef resptr_core> ref_hs; struct ECORE_API SDS : public xr_resource_named { -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ID3D11DomainShader* sh; # elif defined(USE_OGL) GLuint sh; @@ -105,7 +105,7 @@ typedef resptr_core> ref_ds; struct ECORE_API SCS : public xr_resource_named { -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ID3D11ComputeShader* sh; # elif defined(USE_OGL) GLuint sh; @@ -150,7 +150,7 @@ struct ECORE_API SDeclaration : public xr_resource_flagged #if defined(USE_DX9) // Don't need it: use ID3DInputLayout instead // which is per ( declaration, VS input layout) pair IDirect3DVertexDeclaration9* dcl; -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) // Maps input signature to input layout xr_map vs_to_layout; xr_vector dx11_dcl_code; diff --git a/src/Layers/xrRender/SH_RT.h b/src/Layers/xrRender/SH_RT.h index fa0afb95234..4f95df3ee6f 100644 --- a/src/Layers/xrRender/SH_RT.h +++ b/src/Layers/xrRender/SH_RT.h @@ -16,7 +16,11 @@ class CRT : public xr_resource_named CRT() = default; ~CRT(); +#if defined(USE_DX12) + void create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount = 1, u32 slices_num = 1, Flags32 flags = {}, Fcolor color = {0.0f, 0.0f, 0.0f, 1.0f}); +#else void create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount = 1, u32 slices_num = 1, Flags32 flags = {}); +#endif void destroy(); void reset_begin(); void reset_end(); @@ -28,10 +32,10 @@ class CRT : public xr_resource_named void resolve_into(CRT& destination) const; // only RTs with same format supported public: -#if defined(USE_DX9) || (USE_DX11) +#if defined(USE_DX9) || (USE_DX11) || defined(USE_DX12) ID3DTexture2D* pSurface{}; ID3DRenderTargetView* pRT{}; -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ID3DDepthStencilView* pZRT[R__NUM_CONTEXTS]{}; ID3DDepthStencilView* dsv_all{}; xr_vector dsv_per_slice; @@ -58,11 +62,19 @@ class CRT : public xr_resource_named struct resptrcode_crt : public resptr_base { +#if defined(USE_DX12) + void create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount = 1, Flags32 flags = {}, Fcolor color = {0.0f, 0.0f, 0.0f, 0.0f}) + { + create(Name, w, h, f, SampleCount, 1, flags, color); + } + void create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount, u32 slices_num, Flags32 flags, Fcolor color); +#else void create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount = 1, Flags32 flags = {}) { create(Name, w, h, f, SampleCount, 1, flags); } void create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount, u32 slices_num, Flags32 flags); +#endif void destroy() { _set(nullptr); } }; typedef resptr_core ref_rt; diff --git a/src/Layers/xrRender/SH_Texture.h b/src/Layers/xrRender/SH_Texture.h index 7b1dc12970c..125b53ab8c7 100644 --- a/src/Layers/xrRender/SH_Texture.h +++ b/src/Layers/xrRender/SH_Texture.h @@ -19,14 +19,14 @@ class ECORE_API CTexture : public xr_resource_named mtMaxPixelShaderTextures + mtMaxVertexShaderTextures }; -#elif defined(USE_DX11) || defined(USE_OGL) +#elif defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) enum MaxTextures { // Actually these values are 128 mtMaxPixelShaderTextures = 16, mtMaxVertexShaderTextures = 4, mtMaxGeometryShaderTextures = 16, -# ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) mtMaxHullShaderTextures = 16, mtMaxDomainShaderTextures = 16, mtMaxComputeShaderTextures = 16, @@ -35,7 +35,7 @@ class ECORE_API CTexture : public xr_resource_named mtMaxPixelShaderTextures + mtMaxVertexShaderTextures + mtMaxGeometryShaderTextures -# ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) + mtMaxHullShaderTextures + mtMaxDomainShaderTextures + mtMaxComputeShaderTextures @@ -45,7 +45,7 @@ class ECORE_API CTexture : public xr_resource_named # error No graphics API selected or enabled! #endif -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) // Since DX11 allows up to 128 unique textures, // distance between enum values should be at leas 128 enum ResourceShaderType // Don't change this since it's hardware-dependent @@ -87,7 +87,7 @@ class ECORE_API CTexture : public xr_resource_named void Unload(); // void Apply(u32 dwStage); -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) void surface_set(ID3DBaseTexture* surf); [[nodiscard]] ID3DBaseTexture* surface_get() const; #elif defined(USE_OGL) @@ -123,7 +123,7 @@ class ECORE_API CTexture : public xr_resource_named CTexture(); virtual ~CTexture(); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ID3DShaderResourceView* get_SRView() { return m_pSRView; } #endif @@ -140,7 +140,7 @@ class ECORE_API CTexture : public xr_resource_named } void desc_update(); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) void Apply(CBackend& cmd_list, u32 dwStage) const; D3D_USAGE GetUsage(); #endif @@ -172,7 +172,7 @@ class ECORE_API CTexture : public xr_resource_named int last_slice{ -1 }; private: -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) ID3DBaseTexture* pSurface{}; ID3DBaseTexture* pTempSurface{}; // Sequence data @@ -197,7 +197,7 @@ class ECORE_API CTexture : public xr_resource_named # error No graphics API selected or enabled! #endif -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ID3DShaderResourceView* m_pSRView{ nullptr }; ID3DShaderResourceView* srv_all{ nullptr }; xr_vector srv_per_slice; diff --git a/src/Layers/xrRender/Shader.cpp b/src/Layers/xrRender/Shader.cpp index 3a12aff9535..c5658ab7a0a 100644 --- a/src/Layers/xrRender/Shader.cpp +++ b/src/Layers/xrRender/Shader.cpp @@ -48,10 +48,10 @@ bool SPass::equal(const SPass& other) const return false; if (vs != other.vs) return false; -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) if (gs != other.gs) return false; -# ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) if (hs != other.hs) return false; if (ds != other.ds) diff --git a/src/Layers/xrRender/Shader.cpp.bak b/src/Layers/xrRender/Shader.cpp.bak new file mode 100644 index 00000000000..3a12aff9535 --- /dev/null +++ b/src/Layers/xrRender/Shader.cpp.bak @@ -0,0 +1,167 @@ +// Shader.cpp: implementation of the CShader class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#pragma hdrstop + +#include "Shader.h" +#include "ResourceManager.h" +// XXX: render scripts should call these destructors before resource manager gets destroyed +STextureList::~STextureList() { RImplementation.Resources->_DeleteTextureList(this); } +SMatrixList::~SMatrixList() { RImplementation.Resources->_DeleteMatrixList(this); } +SConstantList::~SConstantList() { RImplementation.Resources->_DeleteConstantList(this); } +SPass::~SPass() { RImplementation.Resources->_DeletePass(this); } +ShaderElement::~ShaderElement() { RImplementation.Resources->_DeleteElement(this); } +SGeometry::~SGeometry() { RImplementation.Resources->DeleteGeom(this); } +Shader::~Shader() { RImplementation.Resources->Delete(this); } +////////////////////////////////////////////////////////////////////////// +void resptrcode_shader::create(LPCSTR s_shader, LPCSTR s_textures, LPCSTR s_constants, LPCSTR s_matrices) +{ + _set(RImplementation.Resources->Create(s_shader, s_textures, s_constants, s_matrices)); +} +void resptrcode_shader::create(IBlender* B, LPCSTR s_shader, LPCSTR s_textures, LPCSTR s_constants, LPCSTR s_matrices) +{ + _set(RImplementation.Resources->Create(B, s_shader, s_textures, s_constants, s_matrices)); +} + +////////////////////////////////////////////////////////////////////////// +void resptrcode_geom::create(u32 FVF, VertexBufferHandle vb, IndexBufferHandle ib) +{ + _set(RImplementation.Resources->CreateGeom(FVF, vb, ib)); +} + +void resptrcode_geom::create(const VertexElement* decl, VertexBufferHandle vb, IndexBufferHandle ib) +{ + _set(RImplementation.Resources->CreateGeom(decl, vb, ib)); +} + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +bool SPass::equal(const SPass& other) const +{ + if (state != other.state) + return false; + if (ps != other.ps) + return false; + if (vs != other.vs) + return false; +#if defined(USE_DX11) || defined(USE_OGL) + if (gs != other.gs) + return false; +# ifdef USE_DX11 + if (hs != other.hs) + return false; + if (ds != other.ds) + return false; + if (cs != other.cs) + return false; +# endif +#endif // USE_DX11 || USE_OGL +#ifdef USE_OGL + if (pp != other.pp) + return false; +#endif + if (constants != other.constants) + return false; // is this nessesary??? (ps+vs already combines) + + if (T != other.T) + return false; + if (C != other.C) + return false; +#ifdef _EDITOR + if (M != other.M) + return false; +#endif + return true; +} + +// +ShaderElement::ShaderElement() +{ + flags.iPriority = 1; + flags.bStrictB2F = FALSE; + flags.bEmissive = FALSE; + flags.bDistort = FALSE; + flags.bWmark = FALSE; +} + +BOOL ShaderElement::equal(ShaderElement& S) +{ + if (flags.iPriority != S.flags.iPriority) + return FALSE; + if (flags.bStrictB2F != S.flags.bStrictB2F) + return FALSE; + if (flags.bEmissive != S.flags.bEmissive) + return FALSE; + if (flags.bWmark != S.flags.bWmark) + return FALSE; + if (flags.bDistort != S.flags.bDistort) + return FALSE; + if (passes.size() != S.passes.size()) + return FALSE; + for (u32 p = 0; p < passes.size(); p++) + if (passes[p] != S.passes[p]) + return FALSE; + return TRUE; +} + +BOOL Shader::equal(Shader* S, int index) +{ + if(nullptr == E[index] && nullptr == S->E[index]) + return TRUE; + if(nullptr == E[index] || nullptr == S->E[index]) + return FALSE; + + return E[index]->equal(*S->E[index]); +} + +BOOL Shader::equal(Shader* S) +{ + for (int i = 0; i < 5; i++) + { + if (!equal(S, i)) + return FALSE; + } + return TRUE; +} + +void STextureList::clear() +{ + iterator it = begin(); + iterator it_e = end(); + for (; it != it_e; ++it) + (*it).second.destroy(); + + erase(begin(), end()); +} + +u32 STextureList::find_texture_stage(const shared_str& TexName, bool warnIfMissing /*= true*/) const +{ + for (const auto& [stage, texture] : *this) + { + if (!texture) + continue; + if (texture->cName == TexName) + return stage; + } + + if (!warnIfMissing) + return u32(-1); + VERIFY3(false, "Couldn't find texture stage", TexName.c_str()); + return 0; +} + +void STextureList::create_texture(u32 stage, pcstr textureName, bool overrideIfExists) +{ + for (auto& loader : *this) + { + if (loader.first == stage && (!loader.second || overrideIfExists)) + { + // Assign correct texture + loader.second.create(textureName); + } + } +} diff --git a/src/Layers/xrRender/Shader.h b/src/Layers/xrRender/Shader.h index 8a7ad24907e..84b0e019436 100644 --- a/src/Layers/xrRender/Shader.h +++ b/src/Layers/xrRender/Shader.h @@ -90,9 +90,9 @@ struct ECORE_API SPass : public xr_resource_flagged ref_state state; // Generic state, like Z-Buffering, samplers, etc ref_ps ps; // may be NULL = FFP, in that case "state" must contain TSS setup ref_vs vs; // may be NULL = FFP, in that case "state" must contain RS setup, *and* FVF-compatible declaration must be used -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) ref_gs gs; // may be NULL = don't use geometry shader at all -# ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) ref_hs hs; // may be NULL = don't use hull shader at all ref_ds ds; // may be NULL = don't use domain shader at all ref_cs cs; // may be NULL = don't use compute shader at all diff --git a/src/Layers/xrRender/ShaderResourceTraits.h b/src/Layers/xrRender/ShaderResourceTraits.h index d09e9adb5c7..7192ca40c28 100644 --- a/src/Layers/xrRender/ShaderResourceTraits.h +++ b/src/Layers/xrRender/ShaderResourceTraits.h @@ -181,7 +181,7 @@ struct ShaderTypeTraits #else #if defined(USE_DX9) using LinkageType = void*; -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) using LinkageType = ID3D11ClassLinkage*; #endif using HWShaderType = ID3DVertexShader*; @@ -226,7 +226,7 @@ struct ShaderTypeTraits #if defined(USE_DX9) res = HW.pDevice->CreateVertexShader(buffer, &sh); UNUSED(linkage, name); -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) res = HW.pDevice->CreateVertexShader(buffer, size, linkage, &sh); UNUSED(name); #elif defined(USE_OGL) @@ -257,7 +257,7 @@ struct ShaderTypeTraits #else #if defined(USE_DX9) using LinkageType = void*; -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) using LinkageType = ID3D11ClassLinkage*; #endif using HWShaderType = ID3DPixelShader*; @@ -316,7 +316,7 @@ struct ShaderTypeTraits #if defined(USE_DX9) res = HW.pDevice->CreatePixelShader(buffer, &sh); UNUSED(linkage, name); -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) res = HW.pDevice->CreatePixelShader(buffer, size, linkage, &sh); UNUSED(name); #elif defined(USE_OGL) @@ -334,13 +334,13 @@ struct ShaderTypeTraits static inline u32 GetShaderDest() { return RC_dest_pixel; } }; -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) template <> struct ShaderTypeTraits { using MapType = CResourceManager::map_GS; -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) using LinkageType = ID3D11ClassLinkage*; using HWShaderType = ID3DGeometryShader*; using BufferType = DWORD const*; @@ -358,7 +358,7 @@ struct ShaderTypeTraits static inline const char* GetCompilationTarget() { -# ifdef USE_DX11 +#if defined (USE_DX11) || defined(USE_DX12) switch (HW.FeatureLevel) { case D3D_FEATURE_LEVEL_10_0: @@ -367,11 +367,18 @@ struct ShaderTypeTraits return "gs_4_1"; case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_11_1: -# ifdef HAS_DX11_3 +#if defined(USE_DX12) + case D3D_FEATURE_LEVEL_12_0: + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_2: + return "gs_5_1"; +#elif defined(USE_DX11) && defined(HAS_DX11_3) case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_12_1: -# endif return "gs_5_0"; +#else + return "gs_5_0"; +#endif // } # endif // USE_DX11 NODEFAULT; @@ -389,7 +396,7 @@ struct ShaderTypeTraits { ResultType res{}; -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) res = HW.pDevice->CreateGeometryShader(buffer, size, linkage, &sh); UNUSED(name); # elif defined(USE_OGL) @@ -412,7 +419,7 @@ struct ShaderTypeTraits { using MapType = CResourceManager::map_HS; -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) using LinkageType = ID3D11ClassLinkage*; using HWShaderType = ID3D11HullShader*; using BufferType = DWORD const*; @@ -430,7 +437,12 @@ struct ShaderTypeTraits static inline const char* GetCompilationTarget() { +#if defined(USE_DX12) + return "hs_5_1"; +#else return "hs_5_0"; +#endif + } static void GetCompilationTarget(const char*& target, const char*& entry, const char* /*data*/) @@ -444,7 +456,7 @@ struct ShaderTypeTraits { ResultType res{}; -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) res = HW.pDevice->CreateHullShader(buffer, size, linkage, &sh); UNUSED(name); # elif defined(USE_OGL) @@ -467,7 +479,7 @@ struct ShaderTypeTraits { using MapType = CResourceManager::map_DS; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) using LinkageType = ID3D11ClassLinkage*; using HWShaderType = ID3D11DomainShader*; using BufferType = DWORD const*; @@ -485,7 +497,11 @@ struct ShaderTypeTraits static inline const char* GetCompilationTarget() { +#if defined(USE_DX12) + return "ds_5_1"; +#else return "ds_5_0"; +#endif } static void GetCompilationTarget(const char*& target, const char*& entry, const char* /*data*/) @@ -499,7 +515,7 @@ struct ShaderTypeTraits { ResultType res{}; -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) res = HW.pDevice->CreateDomainShader(buffer, size, linkage, &sh); UNUSED(name); # elif defined(USE_OGL) @@ -522,7 +538,7 @@ struct ShaderTypeTraits { using MapType = CResourceManager::map_CS; -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) using LinkageType = ID3D11ClassLinkage*; using HWShaderType = ID3D11ComputeShader*; using BufferType = DWORD const*; @@ -540,7 +556,7 @@ struct ShaderTypeTraits static inline const char* GetCompilationTarget() { -# ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) switch (HW.FeatureLevel) { case D3D_FEATURE_LEVEL_10_0: @@ -549,11 +565,18 @@ struct ShaderTypeTraits return "cs_4_1"; case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_11_1: -# ifdef HAS_DX11_3 +#if defined(USE_DX12) + case D3D_FEATURE_LEVEL_12_0: + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_2: + return "cs_5_1"; +#elif defined(USE_DX11) && defined(HAS_DX11_3) case D3D_FEATURE_LEVEL_12_0: case D3D_FEATURE_LEVEL_12_1: -# endif return "cs_5_0"; +#else + return "cs_5_0"; +#endif // } # endif // USE_DX11 @@ -571,7 +594,7 @@ struct ShaderTypeTraits { ResultType res{}; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) res = HW.pDevice->CreateComputeShader(buffer, size, linkage, &sh); UNUSED(name); #elif defined(USE_OGL) @@ -602,7 +625,7 @@ inline CResourceManager::map_VS& CResourceManager::GetShaderMap() return m_vs; } -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) template <> inline CResourceManager::map_GS& CResourceManager::GetShaderMap() { diff --git a/src/Layers/xrRender/blenders/Blender_Blur.cpp b/src/Layers/xrRender/blenders/Blender_Blur.cpp index 4da1576b4e4..aedc8aa82d3 100644 --- a/src/Layers/xrRender/blenders/Blender_Blur.cpp +++ b/src/Layers/xrRender/blenders/Blender_Blur.cpp @@ -18,7 +18,7 @@ LPCSTR CBlender_Blur::getComment() return "INTERNAL: blur"; } -#if RENDER != R_R4 +#if RENDER != R_R4 && RENDER != R_R5 void CBlender_Blur::Compile(CBlender_Compile& C) { IBlender::Compile(C); diff --git a/src/Layers/xrRender/blenders/Blender_Lm(EbB).cpp b/src/Layers/xrRender/blenders/Blender_Lm(EbB).cpp index 9fc10cc44b6..33dec5534a2 100644 --- a/src/Layers/xrRender/blenders/Blender_Lm(EbB).cpp +++ b/src/Layers/xrRender/blenders/Blender_Lm(EbB).cpp @@ -235,7 +235,7 @@ void CBlender_LmEbB::CompileProgrammable(CBlender_Compile& C) const C.r_Pass("lmapE", "lmapE", TRUE, TRUE, FALSE, TRUE, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA, TRUE, 0); else C.r_Pass("lmapE", "lmapE", TRUE); -#if RENDER == R_R3 || RENDER == R_R4 +#if RENDER == R_R3 || RENDER == R_R4 || RENDER == R_R5 C.r_dx11Texture("s_base", C.L_textures[0]); C.r_dx11Sampler("smp_base"); C.r_dx11Texture("s_lmap", C.L_textures[1]); diff --git a/src/Layers/xrRender/blenders/Blender_Particle_deferred.cpp b/src/Layers/xrRender/blenders/Blender_Particle_deferred.cpp index db5706c724c..212af6e8d80 100644 --- a/src/Layers/xrRender/blenders/Blender_Particle_deferred.cpp +++ b/src/Layers/xrRender/blenders/Blender_Particle_deferred.cpp @@ -94,7 +94,7 @@ void CBlender_Particle::Compile(CBlender_Compile& C) C.r_Pass("particle", "particle", FALSE, TRUE, FALSE, TRUE, D3DBLEND_SRCALPHA, D3DBLEND_ONE, TRUE, 0); break; // ALPHA-ADD }; -#if RENDER == R_R3 || RENDER == R_R4 +#if RENDER == R_R3 || RENDER == R_R4 || RENDER == R_R5 { C.r_dx11Texture("s_base", C.L_textures[0]); u32 hSampler = C.r_dx11Sampler("smp_base"); @@ -139,7 +139,7 @@ void CBlender_Particle::Compile(CBlender_Compile& C) TRUE, 0); break; // ALPHA-ADD }; -#if RENDER == R_R3 || RENDER == R_R4 +#if RENDER == R_R3 || RENDER == R_R4 || RENDER == R_R5 { C.r_dx11Texture("s_base", C.L_textures[0]); u32 hSampler = C.r_dx11Sampler("smp_base"); diff --git a/src/Layers/xrRender/blenders/blender_deffer_flat.cpp b/src/Layers/xrRender/blenders/blender_deffer_flat.cpp index 5a1f1c63486..7d01c82aace 100644 --- a/src/Layers/xrRender/blenders/blender_deffer_flat.cpp +++ b/src/Layers/xrRender/blenders/blender_deffer_flat.cpp @@ -91,7 +91,7 @@ void CBlender_deffer_flat::Compile(CBlender_Compile& C) break; } #else -#if RENDER == R_R4 +#if RENDER == R_R4 || RENDER == R_R5 C.TessMethod = oTessellation.IDselected; #endif @@ -117,7 +117,7 @@ void CBlender_deffer_flat::Compile(CBlender_Compile& C) // else C.r_Pass ("shadow_direct_base","shadow_direct_base",FALSE); #if RENDER == R_R3 C.r_Pass("shadow_direct_base", "dumb", FALSE, TRUE, TRUE, FALSE); -#elif RENDER == R_R4 +#elif RENDER == R_R4 || RENDER == R_R5 uber_shadow(C, "base"); #endif // C.r_Sampler ("s_base",C.L_textures[0]); diff --git a/src/Layers/xrRender/blenders/blender_deffer_model.cpp b/src/Layers/xrRender/blenders/blender_deffer_model.cpp index caac90a525b..c0edde9c976 100644 --- a/src/Layers/xrRender/blenders/blender_deffer_model.cpp +++ b/src/Layers/xrRender/blenders/blender_deffer_model.cpp @@ -252,7 +252,7 @@ void CBlender_deffer_model::Compile(CBlender_Compile& C) bool bUseATOC = (bAref && (RImplementation.o.msaa_alphatest == CRender::MSAA_ATEST_DX10_0_ATOC)); -#if RENDER == R_R4 +#if RENDER == R_R4 || RENDER == R_R5 C.TessMethod = oTessellation.IDselected; #endif diff --git a/src/Layers/xrRender/blenders/blender_dof.cpp b/src/Layers/xrRender/blenders/blender_dof.cpp index 485dc6036f0..80797aa8c75 100644 --- a/src/Layers/xrRender/blenders/blender_dof.cpp +++ b/src/Layers/xrRender/blenders/blender_dof.cpp @@ -15,7 +15,7 @@ LPCSTR CBlender_dof::getComment() void CBlender_dof::Compile(CBlender_Compile& C) { IBlender::Compile(C); -#if RENDER == R_R4 +#if RENDER == R_R4 || RENDER == R_R5 switch (C.iElement) { case 0: diff --git a/src/Layers/xrRender/blenders/blender_nightvision.cpp b/src/Layers/xrRender/blenders/blender_nightvision.cpp index fb0320d4dda..aa7e35eeb29 100644 --- a/src/Layers/xrRender/blenders/blender_nightvision.cpp +++ b/src/Layers/xrRender/blenders/blender_nightvision.cpp @@ -15,7 +15,7 @@ LPCSTR CBlender_nightvision::getComment() void CBlender_nightvision::Compile(CBlender_Compile& C) { IBlender::Compile(C); -#if RENDER == R_R4 +#if RENDER == R_R4 || RENDER == R_R5 switch (C.iElement) { case 0: //Dummy shader - because IDK what gonna happen when r2_nightvision will be 0 diff --git a/src/Layers/xrRender/blenders/uber_deffer.cpp b/src/Layers/xrRender/blenders/uber_deffer.cpp index be7fd73fa8a..47cfaccbcce 100644 --- a/src/Layers/xrRender/blenders/uber_deffer.cpp +++ b/src/Layers/xrRender/blenders/uber_deffer.cpp @@ -104,7 +104,7 @@ void uber_deffer(CBlender_Compile& C, bool hq, LPCSTR _vspec, LPCSTR _pspec, BOO } // Uber-construct -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) if (bump && hq && RImplementation.o.tessellation && C.TessMethod != 0) { char hs[256], ds[256]; // = "DX11" DELIMITER "tess", ds[256] = "DX11" DELIMITER "tess"; @@ -242,7 +242,7 @@ void uber_deffer(CBlender_Compile& C, bool hq, LPCSTR _vspec, LPCSTR _pspec, BOO C.r_End(); } -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) void uber_shadow(CBlender_Compile& C, LPCSTR _vspec) { // Uber-parse diff --git a/src/Layers/xrRender/dxDebugRender.cpp b/src/Layers/xrRender/dxDebugRender.cpp index d0a6f532d12..991cdc168ca 100644 --- a/src/Layers/xrRender/dxDebugRender.cpp +++ b/src/Layers/xrRender/dxDebugRender.cpp @@ -100,7 +100,7 @@ void dxDebugRender::SetAmbient(u32 colour) { #if defined(USE_DX9) CHK_DX(HW.pDevice->SetRenderState(D3DRS_AMBIENT, colour)); -#elif defined(USE_DX11) || defined(USE_OGL) +#elif defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) // TODO: DX11: Check if need this for DX11 VERIFY(!"Not implemented for DX11"); UNUSED(colour); diff --git a/src/Layers/xrRender/dxEnvironmentRender.cpp b/src/Layers/xrRender/dxEnvironmentRender.cpp index 907557637aa..3a0848586ee 100644 --- a/src/Layers/xrRender/dxEnvironmentRender.cpp +++ b/src/Layers/xrRender/dxEnvironmentRender.cpp @@ -72,7 +72,7 @@ class CBlender_skybox : public IBlender C.r_Sampler_clf("s_sky0", "$null"); C.r_Sampler_clf("s_sky1", "$null"); C.r_Sampler_rtf("s_tonemap", "$user$tonemap"); //. hack -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) // C.r_Sampler_clf ("s_sky0", "$null" ); // C.r_Sampler_clf ("s_sky1", "$null" ); C.r_dx11Texture("s_sky0", "$null"); @@ -230,7 +230,7 @@ void dxEnvironmentRender::RenderSky(CEnvironment& env) RCache.set_xform_world(mSky); RCache.set_Geometry(sh_2geom); RCache.set_Shader(sh_2sky); -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) RCache.set_Textures(&sky_r_textures); #elif defined(USE_OGL) if (HW.Caps.geometry.bVTF) @@ -369,7 +369,7 @@ void dxEnvironmentRender::OnDeviceDestroy() sky_r_textures.clear(); clouds_r_textures.clear(); -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) tsky0->surface_set(nullptr); tsky1->surface_set(nullptr); t_envmap_0->surface_set(nullptr); diff --git a/src/Layers/xrRender/dxImGuiRender.cpp b/src/Layers/xrRender/dxImGuiRender.cpp index 20ce12931d2..f10a2362942 100644 --- a/src/Layers/xrRender/dxImGuiRender.cpp +++ b/src/Layers/xrRender/dxImGuiRender.cpp @@ -6,6 +6,8 @@ #include #elif defined(USE_DX11) #include +#elif defined(USE_DX12) +#include #elif defined(USE_OGL) #include #endif @@ -42,12 +44,18 @@ void dxImGuiRender::SetState(ImDrawData* data) ctx->RSSetState(bd->pRasterizerState);*/ } +#if defined(USE_DX12) +#include "Layers/xrRenderPC_R5/DX12/CryDX12.hpp" +#endif + void dxImGuiRender::Frame() { #if defined(USE_DX9) ImGui_ImplDX9_NewFrame(); #elif defined(USE_DX11) ImGui_ImplDX11_NewFrame(); +#elif defined(USE_DX12) + ImGui_ImplDX12_NewFrame(); #elif defined(USE_OGL) ImGui_ImplOpenGL3_NewFrame(); #endif @@ -59,6 +67,10 @@ void dxImGuiRender::Render(ImDrawData* data) ImGui_ImplDX9_RenderDrawData(data); #elif defined(USE_DX11) ImGui_ImplDX11_RenderDrawData(data); +#elif defined(USE_DX12) + CCryDX12Device* cry_device = dynamic_cast(HW.pDevice); + R_ASSERT(cry_device); + ImGui_ImplDX12_RenderDrawData(data, cry_device->GetDeviceContext()->GetCoreGraphicsCommandList()->GetD3D12CommandList()); #elif defined(USE_OGL) ImGui_ImplOpenGL3_RenderDrawData(data); #endif @@ -82,6 +94,19 @@ void dxImGuiRender::OnDeviceCreate(ImGuiContext* context) ImGui_ImplDX9_Init(HW.pDevice); #elif defined(USE_DX11) ImGui_ImplDX11_Init(HW.pDevice, HW.get_context(CHW::IMM_CTX_ID)); +#elif defined(USE_DX12) + CCryDX12Device* cry_device = dynamic_cast(HW.pDevice); + R_ASSERT(cry_device); + ID3D12Device* device = cry_device->GetD3D12Device(); + DX12::Device* dx12_device = cry_device->GetDX12Device(); + DX12::DescriptorBlock dx12_desc_block = + dx12_device->GetGlobalDescriptorBlock(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 2); + DX12::DescriptorHeap* dx12_heap = dx12_desc_block.GetDescriptorHeap(); + ImGui_ImplDX12_Init(cry_device->GetD3D12Device(), 2, DXGI_FORMAT_R8G8B8A8_UNORM, + dx12_heap->GetD3D12DescriptorHeap(), + dx12_heap->GetD3D12DescriptorHeap()->GetCPUDescriptorHandleForHeapStart(), + dx12_heap->GetD3D12DescriptorHeap()->GetGPUDescriptorHandleForHeapStart() + ); #elif defined(USE_OGL) ImGui_ImplOpenGL3_Init(); #endif @@ -92,6 +117,8 @@ void dxImGuiRender::OnDeviceDestroy() ImGui_ImplDX9_Shutdown(); #elif defined(USE_DX11) ImGui_ImplDX11_Shutdown(); +#elif defined(USE_DX12) + ImGui_ImplDX12_Shutdown(); #elif defined(USE_OGL) ImGui_ImplOpenGL3_Shutdown(); #endif @@ -103,6 +130,8 @@ void dxImGuiRender::OnDeviceResetBegin() ImGui_ImplDX9_InvalidateDeviceObjects(); #elif defined(USE_DX11) ImGui_ImplDX11_InvalidateDeviceObjects(); +#elif defined(USE_DX12) + ImGui_ImplDX12_InvalidateDeviceObjects(); #elif defined(USE_OGL) ImGui_ImplOpenGL3_DestroyDeviceObjects(); #endif @@ -114,6 +143,8 @@ void dxImGuiRender::OnDeviceResetEnd() ImGui_ImplDX9_CreateDeviceObjects(); #elif defined(USE_DX11) ImGui_ImplDX11_CreateDeviceObjects(); +#elif defined(USE_DX12) + ImGui_ImplDX12_CreateDeviceObjects(); #elif defined(USE_OGL) ImGui_ImplOpenGL3_CreateDeviceObjects(); #endif diff --git a/src/Layers/xrRender/dxRainRender.cpp b/src/Layers/xrRender/dxRainRender.cpp index 30f9a70d5dc..73953bf53ea 100644 --- a/src/Layers/xrRender/dxRainRender.cpp +++ b/src/Layers/xrRender/dxRainRender.cpp @@ -34,7 +34,7 @@ dxRainRender::dxRainRender() hGeom_Rain.create(FVF::F_LIT, RImplementation.Vertex.Buffer(), RImplementation.QuadIB); hGeom_Drops.create(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, RImplementation.Vertex.Buffer(), RImplementation.Index.Buffer()); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) if (RImplementation.o.new_shader_support) SH_Splash.create("effects\\rain_splash", "fx\\fx_rain"); #endif @@ -58,7 +58,7 @@ void dxRainRender::Render(CEffect_Rain& owner) static shared_str s_shader_setup = "ssfx_rain_setup"; // SSS Rain shader is available -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) if (RImplementation.o.new_shader_support) { _drop_len = ps_ssfx_rain_1.x; diff --git a/src/Layers/xrRender/dxThunderboltRender.cpp b/src/Layers/xrRender/dxThunderboltRender.cpp index 796c965fd1a..9c4cd9516e6 100644 --- a/src/Layers/xrRender/dxThunderboltRender.cpp +++ b/src/Layers/xrRender/dxThunderboltRender.cpp @@ -94,7 +94,7 @@ void dxThunderboltRender::Render(CEffect_Thunderbolt& owner) RCache.set_xform_world(Fidentity); RCache.set_Geometry(hGeom_gradient); RCache.set_Shader(((dxFlareRender*)&*owner.current->m_GradientTop->m_pFlare)->hShader); -#if defined(USE_DX11) // XXX: check if it's needed on OGL +#if defined(USE_DX11) || defined(USE_DX12) // XXX: check if it's needed on OGL // Hack. Since lightning gradient uses sun shader override z write settings manually RCache.set_Z(TRUE); RCache.set_ZFunc(D3DCMP_LESSEQUAL); @@ -102,7 +102,7 @@ void dxThunderboltRender::Render(CEffect_Thunderbolt& owner) RCache.Render(D3DPT_TRIANGLELIST, VS_Offset, 0, 4, 0, 2); RCache.set_Shader(((dxFlareRender*)&*owner.current->m_GradientCenter->m_pFlare)->hShader); -#if defined(USE_DX11) // XXX: check if it's needed on OGL +#if defined(USE_DX11) || defined(USE_DX12) // XXX: check if it's needed on OGL // Hack. Since lightning gradient uses sun shader override z write settings manually RCache.set_Z(TRUE); RCache.set_ZFunc(D3DCMP_LESSEQUAL); diff --git a/src/Layers/xrRender/dxUIRender.cpp b/src/Layers/xrRender/dxUIRender.cpp index d83862d03a5..c79c3d94cc5 100644 --- a/src/Layers/xrRender/dxUIRender.cpp +++ b/src/Layers/xrRender/dxUIRender.cpp @@ -139,7 +139,7 @@ void dxUIRender::FlushLineList() */ void dxUIRender::SetScissor(Irect* rect) { -#if (RENDER == R_R3) || (RENDER == R_R4) +#if (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) RCache.set_Scissor(rect); RCache.StateManager.OverrideScissoring(rect ? true : false, TRUE); #else // (RENDER == R_R3) || (RENDER == R_R4) diff --git a/src/Layers/xrRender/dxWallMarkArray.cpp b/src/Layers/xrRender/dxWallMarkArray.cpp index a98016dd62b..908a6f61684 100644 --- a/src/Layers/xrRender/dxWallMarkArray.cpp +++ b/src/Layers/xrRender/dxWallMarkArray.cpp @@ -14,7 +14,7 @@ void dxWallMarkArray::AppendMark(LPCSTR s_textures) { ref_shader s; LPCSTR sh_name = "effects" DELIMITER "wallmark"; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) if (RImplementation.o.new_shader_support) { // Use the blood shader for any texture with the name wm_blood_* diff --git a/src/Layers/xrRender/light.cpp b/src/Layers/xrRender/light.cpp index dd82bd03e46..4ef7b5fd21e 100644 --- a/src/Layers/xrRender/light.cpp +++ b/src/Layers/xrRender/light.cpp @@ -27,7 +27,7 @@ light::light() : SpatialBase(g_pGamePersistent->SpatialSpace) frame_render = 0; -#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_GL) +#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) || (RENDER == R_GL) ZeroMemory(omnipart, sizeof(omnipart)); s_spot = nullptr; s_point = nullptr; @@ -43,21 +43,21 @@ light::light() : SpatialBase(g_pGamePersistent->SpatialSpace) light::~light() { -#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_GL) +#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) || (RENDER == R_GL) for (auto& f : omnipart) xr_delete(f); #endif // (RENDER==R_R2) || (RENDER==R_R3) || (RENDER==R_R4) || (RENDER==R_GL) set_active(false); // remove from Lights_LastFrame -#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_GL) +#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) || (RENDER == R_GL) for (auto& p_light : RImplementation.Lights_LastFrame) if (this == p_light) p_light = nullptr; #endif // (RENDER==R_R2) || (RENDER==R_R3) || (RENDER==R_R4) || (RENDER==R_GL) } -#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_GL) +#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) || (RENDER == R_GL) void light::set_texture(LPCSTR name) { if ((nullptr == name) || (0 == name[0])) @@ -76,7 +76,7 @@ void light::set_texture(LPCSTR name) // strconcat(sizeof(temp),temp,"_nomsaa",name); s_spot.create(RImplementation.Target->b_accum_spot, temp, name); -#if (RENDER != R_R3) && (RENDER != R_R4) && (RENDER != R_GL) +#if (RENDER != R_R3) && (RENDER != R_R4) && (RENDER != R_R5) && (RENDER != R_GL) s_volumetric.create("accum_volumetric", name); #else // (RENDER!=R_R3) && (RENDER!=R_R4) && (RENDER!=R_GL) s_volumetric.create("accum_volumetric_nomsaa", name); @@ -209,7 +209,7 @@ void light::spatial_move() // update spatial DB SpatialBase::spatial_move(); -#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_GL) +#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) || (RENDER == R_GL) if (flags.bActive) gi_generate(); for (int id = 0; id < R__NUM_CONTEXTS; ++id) @@ -228,7 +228,7 @@ vis_data& light::get_homdata() Fvector light::spatial_sector_point() { return position; } ////////////////////////////////////////////////////////////////////////// -#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_GL) +#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) || (RENDER == R_GL) // Xforms void light::xform_calc() { @@ -349,7 +349,7 @@ void light::Export(light_Package& package) L->s_point = s_point; // Holger - do we need to export msaa stuff as well ? -#if (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_GL) +#if (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) || (RENDER == R_GL) if (RImplementation.o.msaa) { int bound = 1; diff --git a/src/Layers/xrRender/light.h b/src/Layers/xrRender/light.h index 85cb5e7ea74..e580a71526c 100644 --- a/src/Layers/xrRender/light.h +++ b/src/Layers/xrRender/light.h @@ -3,7 +3,7 @@ #include "xrCDB/ISpatial.h" -#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER==R_GL) +#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) || (RENDER == R_GL) #include "Light_Package.h" #include "light_smapvis.h" #include "light_gi.h" @@ -55,7 +55,7 @@ class light : public IRender_Light, public SpatialBase ref_shader s_point; ref_shader s_volumetric; -#if (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_GL) +#if (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) || (RENDER == R_GL) ref_shader s_spot_msaa[8]; ref_shader s_point_msaa[8]; ref_shader s_volumetric_msaa[8]; @@ -157,7 +157,7 @@ class light : public IRender_Light, public SpatialBase IRender_Light* dcast_Light() override { return this; } vis_data& get_homdata(); -#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_GL) +#if (RENDER == R_R2) || (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) || (RENDER == R_GL) void gi_generate(); void xform_calc(); void vis_prepare(CBackend& cmd_list); diff --git a/src/Layers/xrRender/r__dsgraph_render.cpp b/src/Layers/xrRender/r__dsgraph_render.cpp index d6f33d8a7d4..8cf55d06fa2 100644 --- a/src/Layers/xrRender/r__dsgraph_render.cpp +++ b/src/Layers/xrRender/r__dsgraph_render.cpp @@ -62,7 +62,7 @@ void R_dsgraph_structure::render_graph(u32 _priority) for (const auto& item : items) { const float LOD = calcLOD(item.ssa, item.pVisual->vis.sphere.R); -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) cmd_list.LOD.set_LOD(LOD); #endif // --#SM+#-- Обновляем шейдерные данные модели [update shader values for this model] @@ -106,7 +106,7 @@ void R_dsgraph_structure::render_graph(u32 _priority) cmd_list.apply_lmaterial(); const float LOD = calcLOD(item.ssa, item.pVisual->vis.sphere.R); -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) cmd_list.LOD.set_LOD(LOD); #endif // --#SM+#-- Обновляем шейдерные данные модели [update shader values for this model] @@ -267,7 +267,7 @@ void R_dsgraph_structure::render_hud_ui() cmd_list.set_RT(0, 2); auto zb = RImplementation.Target->rt_Base_Depth; -#if (RENDER == R_R3) || (RENDER == R_R4) || (RENDER==R_GL) +#if (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) || (RENDER == R_GL) if (RImplementation.o.msaa) zb = RImplementation.Target->rt_MSAADepth; #endif diff --git a/src/Layers/xrRender/r__occlusion.cpp b/src/Layers/xrRender/r__occlusion.cpp index c6e59e01ecc..4fa74f59cbe 100644 --- a/src/Layers/xrRender/r__occlusion.cpp +++ b/src/Layers/xrRender/r__occlusion.cpp @@ -122,7 +122,7 @@ R_occlusion::occq_result R_occlusion::occq_get(u32& ID) } } RImplementation.BasicStats.Wait.End(); -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) if (hr == D3DERR_DEVICELOST) fragments = 0xffffffff; #endif diff --git a/src/Layers/xrRender/r__occlusion.cpp.bak b/src/Layers/xrRender/r__occlusion.cpp.bak new file mode 100644 index 00000000000..1c1538c3b9f --- /dev/null +++ b/src/Layers/xrRender/r__occlusion.cpp.bak @@ -0,0 +1,150 @@ +#include "stdafx.h" +#include "r__occlusion.h" + +#include "QueryHelper.h" + +R_occlusion::R_occlusion(void) { enabled = strstr(Core.Params, "-no_occq") ? FALSE : TRUE; } +R_occlusion::~R_occlusion(void) { occq_destroy(); } +void R_occlusion::occq_create(u32 limit) +{ + pool.reserve(limit); + used.reserve(limit); + fids.reserve(limit); + for (u32 it = 0; it < limit; it++) + { + Query q; + q.order = it; + if (FAILED(CreateQuery(&q.Q, D3D_QUERY_OCCLUSION))) + break; + pool.push_back(q); + } + std::reverse(pool.begin(), pool.end()); +} +void R_occlusion::occq_destroy() +{ + while (!used.empty()) + { + ReleaseQuery(used.back().Q); + used.pop_back(); + } + while (!pool.empty()) + { + ReleaseQuery(pool.back().Q); + pool.pop_back(); + } + used.clear(); + pool.clear(); + fids.clear(); +} + +u32 R_occlusion::occq_begin(u32& ID) +{ + ScopeLock lock{ &render_lock }; + + if (!enabled) + return 0; + + // Igor: prevent release crash if we issue too many queries + if (pool.empty()) + { + if ((Device.dwFrame % 40) == 0) + Msg(" RENDER [Warning]: Too many occlusion queries were issued(>%u)!!!", pool.size()); + ID = iInvalidHandle; + return 0; + } + + RImplementation.BasicStats.OcclusionQueries++; + if (!fids.empty()) + { + ID = fids.back(); + fids.pop_back(); + VERIFY(pool.size()); + used[ID] = pool.back(); + } + else + { + ID = used.size(); + VERIFY(pool.size()); + used.push_back(pool.back()); + } + pool.pop_back(); + // CHK_DX (used[ID].Q->Issue (D3DISSUE_BEGIN)); + CHK_DX(BeginQuery(used[ID].Q)); + + // Msg ("begin: [%2d] - %d", used[ID].order, ID); + + return used[ID].order; +} +void R_occlusion::occq_end(u32& ID) +{ + ScopeLock lock{ &render_lock }; + + if (!enabled) + return; + + // Igor: prevent release crash if we issue too many queries + if (ID == iInvalidHandle) + return; + + // Msg ("end : [%2d] - %d", used[ID].order, ID); + // CHK_DX (used[ID].Q->Issue (D3DISSUE_END)); + CHK_DX(EndQuery(used[ID].Q)); +} +R_occlusion::occq_result R_occlusion::occq_get(u32& ID) +{ + ScopeLock lock{ &render_lock }; + + if (!enabled) + return 0xffffffff; + + // Igor: prevent release crash if we issue too many queries + if (ID == iInvalidHandle) + return 0xFFFFFFFF; + + occq_result fragments = 0; + HRESULT hr; + // CHK_DX (used[ID].Q->GetData(&fragments,sizeof(fragments),D3DGETDATA_FLUSH)); + // Msg ("get : [%2d] - %d => %d", used[ID].order, ID, fragments); + CTimer T; + T.Start(); + RImplementation.BasicStats.Wait.Begin(); + // while ((hr=used[ID].Q->GetData(&fragments,sizeof(fragments),D3DGETDATA_FLUSH))==S_FALSE) { + VERIFY2(ID < used.size(), make_string("_Pos = %d, size() = %d ", ID, used.size())); + while ((hr = GetData(used[ID].Q, &fragments, sizeof(fragments))) == S_FALSE) + { + if (!SwitchToThread()) + Sleep(ps_r2_wait_sleep); + + if (T.GetElapsed_ms() > 500) + { + fragments = (occq_result)-1; // 0xffffffff; + break; + } + } + RImplementation.BasicStats.Wait.End(); +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12 + if (hr == D3DERR_DEVICELOST) + fragments = 0xffffffff; +#endif + + if (0 == fragments) + RImplementation.BasicStats.OcclusionCulled++; + + // insert into pool (sorting in decreasing order) + Query& Q = used[ID]; + if (pool.empty()) + pool.push_back(Q); + else + { + int it = int(pool.size()) - 1; + while ((it >= 0) && (pool[it].order < Q.order)) + it--; + pool.insert(pool.begin() + it + 1, Q); + } + + // remove from used and shrink as nesessary + used[ID].Q = 0; + fids.push_back(ID); + ID = 0; + return fragments; +} diff --git a/src/Layers/xrRender/r__occlusion.h b/src/Layers/xrRender/r__occlusion.h index ceb6039b8f1..ceecfc1cfa9 100644 --- a/src/Layers/xrRender/r__occlusion.h +++ b/src/Layers/xrRender/r__occlusion.h @@ -18,7 +18,7 @@ class R_occlusion struct Query { u32 order; -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) ID3DQuery* Q; #elif defined(USE_OGL) GLuint Q; @@ -36,7 +36,7 @@ class R_occlusion Lock render_lock{}; public: -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) typedef u64 occq_result; #elif defined(USE_DX9) || defined(USE_OGL) typedef u32 occq_result; diff --git a/src/Layers/xrRender/r__pixel_calculator.cpp b/src/Layers/xrRender/r__pixel_calculator.cpp index 0f93e9f2321..78b3067c821 100644 --- a/src/Layers/xrRender/r__pixel_calculator.cpp +++ b/src/Layers/xrRender/r__pixel_calculator.cpp @@ -3,7 +3,7 @@ #include "r__pixel_calculator.h" #include "Layers/xrRender/FBasicVisual.h" -#if defined(USE_DX9) || defined(USE_DX11)// XXX: support pixel calculator on OpenGL +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) // XXX: support pixel calculator on OpenGL # include #endif @@ -15,7 +15,7 @@ void r_pixel_calculator::begin() zb.create("$user$pixel_calculator_zb", rt_dimensions, rt_dimensions, HW.Caps.fDepth, 1, { CRT::CreateSurface }); RCache.set_RT(rt->pRT); -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) RCache.set_ZB(zb->pZRT[RCache.context_id]); #elif defined(USE_DX9) || defined(USE_OGL) RCache.set_ZB(zb->pRT); @@ -35,7 +35,7 @@ void r_pixel_calculator::end() rt = nullptr; } -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) // +X, -X, +Y, -Y, +Z, -Z extern Fvector cmNorm[6]; extern Fvector cmDir [6]; @@ -43,7 +43,7 @@ extern Fvector cmDir [6]; r_aabb_ssa r_pixel_calculator::calculate(dxRender_Visual* V) { -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) using namespace DirectX; r_aabb_ssa result = {0}; diff --git a/src/Layers/xrRender/r__sync_point.cpp b/src/Layers/xrRender/r__sync_point.cpp index c45f87d291c..ef041f51ae1 100644 --- a/src/Layers/xrRender/r__sync_point.cpp +++ b/src/Layers/xrRender/r__sync_point.cpp @@ -43,7 +43,7 @@ void R_sync_point::End() q_sync_count = (q_sync_count + 1) % HW.Caps.iGPUNum; CHK_GL(glDeleteSync((GLsync)q_sync_point[q_sync_count])); } -#elif defined(USE_DX9) || defined(USE_DX11) +#elif defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) void R_sync_point::Create() { for (u32 i = 0; i < HW.Caps.iGPUNum; ++i) diff --git a/src/Layers/xrRender/r_constants.cpp b/src/Layers/xrRender/r_constants.cpp index d9cd6463eab..27f7dcaa087 100644 --- a/src/Layers/xrRender/r_constants.cpp +++ b/src/Layers/xrRender/r_constants.cpp @@ -91,7 +91,7 @@ void R_constant_table::merge(R_constant_table* T) C->vs = src->vs; #ifndef USE_DX9 C->gs = src->gs; -# if defined(USE_DX11) +# if defined(USE_DX11) || defined(USE_DX12) C->hs = src->hs; C->ds = src->ds; C->cs = src->cs; @@ -131,7 +131,7 @@ void R_constant_table::merge(R_constant_table* T) }); } -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) // TODO: DX11: Implement merge with validity check for (int id = 0; id < R__NUM_CONTEXTS; ++id) { @@ -148,7 +148,7 @@ void R_constant_table::clear() for (u32 it = 0; it < table.size(); it++) table[it] = 0; //.g_constant_allocator.destroy(table[it]); table.clear(); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) for (int id = 0; id < R__NUM_CONTEXTS; ++id) { m_CBTable[id].clear(); diff --git a/src/Layers/xrRender/r_constants.cpp.bak b/src/Layers/xrRender/r_constants.cpp.bak new file mode 100644 index 00000000000..627f20d4154 --- /dev/null +++ b/src/Layers/xrRender/r_constants.cpp.bak @@ -0,0 +1,171 @@ +#include "stdafx.h" + +#include "r_constants.h" +#include "ResourceManager.h" + +//.#include "xrCore/xrPool.h" + +// pool +//.static poolSS g_constant_allocator; + +R_constant_table::~R_constant_table() +{ + RImplementation.Resources->_DeleteConstantTable(this); +} + +void R_constant_table::fatal(LPCSTR S) +{ + FATAL(S); +} + +ref_constant R_constant_table::get(pcstr S, u16 type /*= u16(-1)*/) const +{ + // assumption - sorted by name + c_table::const_iterator it; + if (type == u16(-1)) + { + it = std::lower_bound(table.cbegin(), table.cend(), S, [](const ref_constant& C, cpcstr S) + { + return xr_strcmp(*C->name, S) < 0; + }); + } + else + { + it = std::find_if(table.cbegin(), table.cend(), [&](const ref_constant& constant) + { + return 0 == xr_strcmp(constant->name.c_str(), S) && constant->type == type; + }); + } + + if (it == table.cend() || (0 != xr_strcmp((*it)->name.c_str(), S))) + return nullptr; + return *it; +} + +ref_constant R_constant_table::get(const shared_str& S, u16 type /*= u16(-1)*/) const +{ + // linear search, but only ptr-compare + if (type == u16(-1)) + { + for (const ref_constant& C : table) + { + if (C->name.equal(S)) + return C; + } + } + else + { + for (const ref_constant& C : table) + { + if (C->name.equal(S) && C->type == type) + return C; + } + } + + return nullptr; +} + +/// !!!!!!!!FIX THIS FOR DX11!!!!!!!!! +void R_constant_table::merge(R_constant_table* T) +{ + if (nullptr == T) + return; + + if (T->dx9compatibility) + dx9compatibility = true; + + // Real merge + xr_vector table_tmp; + table_tmp.reserve(table.size()); + for (u32 it = 0; it < T->table.size(); it++) + { + ref_constant src = T->table[it]; + ref_constant C = get(*src->name, dx9compatibility ? src->type : u16(-1)); + if (!C || (dx9compatibility && C->type != src->type)) + { + C = xr_new(); //.g_constant_allocator.create(); + C->name = src->name; + C->destination = src->destination; + C->type = src->type; + C->ps = src->ps; + C->vs = src->vs; +#ifndef USE_DX9 + C->gs = src->gs; +# if defined(USE_DX11) || defined(USE_DX12) + C->hs = src->hs; + C->ds = src->ds; + C->cs = src->cs; +# endif +#endif +#ifdef USE_OGL + C->pp = src->pp; +#endif + C->samp = src->samp; + C->handler = src->handler; + table_tmp.push_back(C); + } + else + { + C->destination |= src->destination; + VERIFY(C->type == src->type); + R_constant_load& sL = src->get_load(src->destination); + R_constant_load& dL = C->get_load(src->destination); + dL.index = sL.index; + dL.cls = sL.cls; +#ifdef USE_OGL + dL.location = sL.location; + dL.program = sL.program; +#endif // USE_OGL + } + } + + if (!table_tmp.empty()) + { + // Append + std::move(table_tmp.begin(), table_tmp.end(), std::back_inserter(table)); + + // Sort + std::sort(table.begin(), table.end(), [](const ref_constant& C1, const ref_constant& C2) + { + return xr_strcmp(C1->name, C2->name) < 0; + }); + } + +#if defined(USE_DX11) || defined(USE_DX12) + // TODO: DX11: Implement merge with validity check + for (int id = 0; id < R__NUM_CONTEXTS; ++id) + { + m_CBTable[id].reserve(m_CBTable[id].size() + T->m_CBTable[id].size()); + for (u32 i = 0; i < T->m_CBTable[id].size(); ++i) + m_CBTable[id].push_back((T->m_CBTable[id])[i]); + } +#endif +} + +void R_constant_table::clear() +{ + //. + for (u32 it = 0; it < table.size(); it++) + table[it] = 0; //.g_constant_allocator.destroy(table[it]); + table.clear(); +#if defined(USE_DX11) + for (int id = 0; id < R__NUM_CONTEXTS; ++id) + { + m_CBTable[id].clear(); + } +#endif +} + +BOOL R_constant_table::equal(R_constant_table& C) +{ + if (table.size() != C.table.size()) + return FALSE; + const size_t size = table.size(); + for (size_t it = 0; it < size; it++) + { + if (!table[it]->equal(*C.table[it])) + return FALSE; + } + + return TRUE; +} diff --git a/src/Layers/xrRender/r_constants.h b/src/Layers/xrRender/r_constants.h index 627b82d742a..8950db65a24 100644 --- a/src/Layers/xrRender/r_constants.h +++ b/src/Layers/xrRender/r_constants.h @@ -4,7 +4,7 @@ #include "xrCore/xr_resource.h" -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) #include "Layers/xrRenderDX11/dx11ConstantBuffer.h" #endif @@ -76,7 +76,7 @@ struct ECORE_API R_constant_load u16 index; // linear index (pixel) u16 cls; // element class -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) R_constant_load() : index(u16(-1)), cls(u16(-1)) {}; #elif defined(USE_OGL) GLuint location; @@ -89,7 +89,7 @@ struct ECORE_API R_constant_load BOOL equal(R_constant_load& C) { -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) return (index == C.index) && (cls == C.cls); #elif defined(USE_OGL) return (index == C.index) && (cls == C.cls) && (location == C.location) && (program == C.program); @@ -109,7 +109,7 @@ struct ECORE_API R_constant : public xr_resource R_constant_load vs; #ifndef USE_DX9 R_constant_load gs; -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) R_constant_load hs; R_constant_load ds; R_constant_load cs; @@ -134,7 +134,7 @@ struct ECORE_API R_constant : public xr_resource case RC_dest_sampler: return samp; #ifndef USE_DX9 case RC_dest_geometry: return gs; -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) case RC_dest_hull: return hs; case RC_dest_domain: return ds; case RC_dest_compute: return cs; @@ -155,9 +155,9 @@ struct ECORE_API R_constant : public xr_resource && destination == C.destination && ps.equal(C.ps) && vs.equal(C.vs) -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) && gs.equal(C.gs) -# if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) && hs.equal(C.hs) && ds.equal(C.ds) && cs.equal(C.cs) @@ -189,7 +189,7 @@ class ECORE_API R_constant_table : public xr_resource_flagged typedef xr_vector c_table; c_table table; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) typedef std::pair cb_table_record; typedef xr_vector cb_table; cb_table m_CBTable[R__NUM_CONTEXTS]; @@ -198,7 +198,7 @@ class ECORE_API R_constant_table : public xr_resource_flagged private: void fatal(LPCSTR s); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) BOOL parseConstants(ID3DShaderReflectionConstantBuffer* pTable, u32 destination); BOOL parseResources(ID3DShaderReflection* pReflection, int ResNum, u32 destination); #endif @@ -220,7 +220,7 @@ class ECORE_API R_constant_table : public xr_resource_flagged }; typedef resptr_core> ref_ctable; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) #include "../xrRenderDX11/dx11ConstantBuffer_impl.h" #endif diff --git a/src/Layers/xrRender/r_constants_cache.h b/src/Layers/xrRender/r_constants_cache.h index af75cfb9d8e..ea4d7343bb2 100644 --- a/src/Layers/xrRender/r_constants_cache.h +++ b/src/Layers/xrRender/r_constants_cache.h @@ -6,7 +6,7 @@ #if defined(USE_DX9) #include "Layers/xrRenderDX9/dx9r_constants_cache.h" -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) #include "Layers/xrRenderDX11/dx11r_constants_cache.h" #elif defined(USE_OGL) #include "Layers/xrRenderGL/glr_constants_cache.h" diff --git a/src/Layers/xrRender/rendertarget_phase_gasmask_drops.cpp b/src/Layers/xrRender/rendertarget_phase_gasmask_drops.cpp index 2eee547075b..ef2cfd74c31 100644 --- a/src/Layers/xrRender/rendertarget_phase_gasmask_drops.cpp +++ b/src/Layers/xrRender/rendertarget_phase_gasmask_drops.cpp @@ -12,7 +12,7 @@ void CRenderTarget::phase_gasmask_drops() float h = float(Device.dwHeight); Fvector2 p0, p1; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) p0.set(0.0f, 0.0f); p1.set(1.0f, 1.0f); #else @@ -22,7 +22,7 @@ void CRenderTarget::phase_gasmask_drops() ////////////////////////////////////////////////////////////////////////// //Set MSAA/NonMSAA rendertarget -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ref_rt& dest_rt = RImplementation.o.msaa ? rt_Generic : rt_Color; u_setrt(RCache, dest_rt, nullptr, nullptr, nullptr); #else @@ -51,7 +51,7 @@ void CRenderTarget::phase_gasmask_drops() RCache.set_Geometry(g_combine); RCache.Render(D3DPT_TRIANGLELIST, Offset, 0, 4, 0, 2); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) HW.get_context(CHW::IMM_CTX_ID)->CopyResource(rt_Generic_0->pTexture->surface_get(), dest_rt->pTexture->surface_get()); #endif }; diff --git a/src/Layers/xrRender/rendertarget_phase_gasmask_dudv.cpp b/src/Layers/xrRender/rendertarget_phase_gasmask_dudv.cpp index edaf493ad7b..0b730f996a2 100644 --- a/src/Layers/xrRender/rendertarget_phase_gasmask_dudv.cpp +++ b/src/Layers/xrRender/rendertarget_phase_gasmask_dudv.cpp @@ -12,7 +12,7 @@ void CRenderTarget::phase_gasmask_dudv() float h = float(Device.dwHeight); Fvector2 p0, p1; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) p0.set(0.0f, 0.0f); p1.set(1.0f, 1.0f); #else @@ -22,7 +22,7 @@ void CRenderTarget::phase_gasmask_dudv() ////////////////////////////////////////////////////////////////////////// //Set MSAA/NonMSAA rendertarget -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) ref_rt& dest_rt = RImplementation.o.msaa ? rt_Generic : rt_Color; u_setrt(RCache, dest_rt, nullptr, nullptr, nullptr); #else @@ -54,7 +54,7 @@ void CRenderTarget::phase_gasmask_dudv() RCache.set_Geometry(g_combine); RCache.Render(D3DPT_TRIANGLELIST, Offset, 0, 4, 0, 2); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) HW.get_context(CHW::IMM_CTX_ID)->CopyResource(rt_Generic_0->pTexture->surface_get(), dest_rt->pTexture->surface_get()); #endif }; diff --git a/src/Layers/xrRender/stats_manager.cpp b/src/Layers/xrRender/stats_manager.cpp index 7f573613794..4eaab5e82ef 100644 --- a/src/Layers/xrRender/stats_manager.cpp +++ b/src/Layers/xrRender/stats_manager.cpp @@ -48,7 +48,7 @@ void stats_manager::increment_stats_rtarget(ID3DTexture2D* buff) D3DSURFACE_DESC desc; buff->GetLevelDesc(0, &desc); pool = desc.Pool; -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) D3D_TEXTURE2D_DESC desc; buff->GetDesc(&desc); #else @@ -68,7 +68,7 @@ void stats_manager::increment_stats_vb(ID3DVertexBuffer* buff) D3DVERTEXBUFFER_DESC desc; buff->GetDesc(&desc); increment_stats(desc.Size, enum_stats_buffer_type_vertex, desc.Pool, buff); -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) D3D_BUFFER_DESC desc; buff->GetDesc(&desc); increment_stats(desc.ByteWidth, enum_stats_buffer_type_vertex, D3DPOOL_MANAGED, buff); @@ -86,7 +86,7 @@ void stats_manager::increment_stats_ib(ID3DIndexBuffer* buff) D3DINDEXBUFFER_DESC desc; buff->GetDesc(&desc); increment_stats(desc.Size, enum_stats_buffer_type_index, desc.Pool, buff); -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) D3D_BUFFER_DESC desc; buff->GetDesc(&desc); increment_stats(desc.ByteWidth, enum_stats_buffer_type_index, D3DPOOL_MANAGED, buff); @@ -110,7 +110,7 @@ void stats_manager::decrement_stats_rtarget(ID3DTexture2D* buff) D3DSURFACE_DESC desc; buff->GetLevelDesc(0, &desc); pool = desc.Pool; -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) D3D_TEXTURE2D_DESC desc; buff->GetDesc(&desc); #else @@ -135,7 +135,7 @@ void stats_manager::decrement_stats_vb(ID3DVertexBuffer* buff) D3DVERTEXBUFFER_DESC desc; buff->GetDesc(&desc); decrement_stats(desc.Size, enum_stats_buffer_type_vertex, desc.Pool, buff); -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) D3D_BUFFER_DESC desc; buff->GetDesc(&desc); decrement_stats(desc.ByteWidth, enum_stats_buffer_type_vertex, D3DPOOL_MANAGED, buff); @@ -158,7 +158,7 @@ void stats_manager::decrement_stats_ib(ID3DIndexBuffer* buff) D3DINDEXBUFFER_DESC desc; buff->GetDesc(&desc); decrement_stats(desc.Size, enum_stats_buffer_type_index, desc.Pool, buff); -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) D3D_BUFFER_DESC desc; buff->GetDesc(&desc); decrement_stats(desc.ByteWidth, enum_stats_buffer_type_index, D3DPOOL_MANAGED, buff); @@ -251,7 +251,7 @@ u32 get_format_pixel_size(D3DFORMAT format) } } -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) u32 get_format_pixel_size(DXGI_FORMAT format) { if (format >= DXGI_FORMAT_R32G32B32A32_TYPELESS && format <= DXGI_FORMAT_R32G32B32A32_SINT) diff --git a/src/Layers/xrRender/stats_manager.h b/src/Layers/xrRender/stats_manager.h index 827341531a7..72ab283e754 100644 --- a/src/Layers/xrRender/stats_manager.h +++ b/src/Layers/xrRender/stats_manager.h @@ -51,7 +51,7 @@ class stats_manager u32 get_format_pixel_size(D3DFORMAT format); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) u32 get_format_pixel_size(DXGI_FORMAT format); #endif diff --git a/src/Layers/xrRender/tss.h b/src/Layers/xrRender/tss.h index f7b1dceefe8..e2227180af4 100644 --- a/src/Layers/xrRender/tss.h +++ b/src/Layers/xrRender/tss.h @@ -4,7 +4,7 @@ #include "tss_def.h" -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) enum XRDX11SAMPLERSTATETYPE { XRDX11SAMP_ANISOTROPICFILTER = 256, diff --git a/src/Layers/xrRender/tss_def.cpp b/src/Layers/xrRender/tss_def.cpp index 0faa55f6ea8..f48c9d21797 100644 --- a/src/Layers/xrRender/tss_def.cpp +++ b/src/Layers/xrRender/tss_def.cpp @@ -28,7 +28,7 @@ void SimulatorStates::record(ID3DState*& state) } } CHK_DX(HW.pDevice->EndStateBlock(&state)); -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) // VERIFY(!"SimulatorStates::record not implemented!"); state = ID3DState::Create(*this); #elif defined(USE_OGL) @@ -120,7 +120,7 @@ BOOL SimulatorStates::equal(SimulatorStates& S) void SimulatorStates::clear() { States.clear(); } -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) #include "Layers/xrRenderDX11/dx11StateUtils.h" void SimulatorStates::UpdateState(dx11State& state) const diff --git a/src/Layers/xrRender/tss_def.h b/src/Layers/xrRender/tss_def.h index 078aab874c4..d33f6eecfc0 100644 --- a/src/Layers/xrRender/tss_def.h +++ b/src/Layers/xrRender/tss_def.h @@ -52,7 +52,7 @@ class SimulatorStates BOOL equal(SimulatorStates& S); void clear(); void record(ID3DState*& state); -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) void UpdateState(dx11State& state) const; void UpdateDesc(D3D_RASTERIZER_DESC& desc) const; void UpdateDesc(D3D_DEPTH_STENCIL_DESC& desc) const; diff --git a/src/Layers/xrRender/xrRender_console.cpp b/src/Layers/xrRender/xrRender_console.cpp index 614e020d196..3782958d912 100644 --- a/src/Layers/xrRender/xrRender_console.cpp +++ b/src/Layers/xrRender/xrRender_console.cpp @@ -56,7 +56,7 @@ const xr_token qsmapsize_token[] = { "3072", 3072 }, { "3584", 3584 }, { "4096", 4096 }, -#if defined(USE_DX11) || defined(USE_OGL) // XXX: check if values more than 8192 are supported on OpenGL +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) // XXX: check if values more than 8192 are supported on OpenGL { "5120", 5120 }, { "6144", 6144 }, { "7168", 7168 }, @@ -81,14 +81,14 @@ const xr_token qsun_shafts_token[] = {{"st_opt_off", 0}, {"st_opt_low", 1}, {"st u32 ps_r_ssao = 3; const xr_token qssao_token[] = {{"st_opt_off", 0}, {"st_opt_low", 1}, {"st_opt_medium", 2}, {"st_opt_high", 3}, -#if defined(USE_DX11) || defined(USE_OGL) +#if defined(USE_DX11) || defined(USE_DX12) || defined(USE_OGL) {"st_opt_ultra", 4}, #endif {nullptr, 0}}; u32 ps_r_sun_quality = 1; // = 0; const xr_token qsun_quality_token[] = {{"st_opt_low", 0}, {"st_opt_medium", 1}, {"st_opt_high", 2}, -#if defined(USE_DX11) // TODO: OGL: fix ultra and extreme settings +#if defined(USE_DX11) || defined(USE_DX12) // TODO: OGL: fix ultra and extreme settings {"st_opt_ultra", 3}, {"st_opt_extreme", 4}, #endif // !USE_DX9 {nullptr, 0}}; @@ -329,7 +329,7 @@ float ps_r2_gloss_min = 0.0f; #include "xrEngine/XR_IOConsole.h" #include "xrEngine/xr_ioc_cmd.h" -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) #include "Layers/xrRenderDX11/StateManager/dx11SamplerStateCache.h" #endif @@ -368,7 +368,7 @@ class CCC_tf_Aniso : public CCC_Integer public: void apply() { -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) if (nullptr == HW.pDevice) return; #endif @@ -377,7 +377,7 @@ class CCC_tf_Aniso : public CCC_Integer #if defined(USE_DX9) for (u32 i = 0; i < HW.Caps.raster.dwStages; i++) CHK_DX(HW.pDevice->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, val)); -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) SSManager.SetMaxAnisotropy(val); #elif defined(USE_OGL) // OGL: don't set aniso here because it will be updated after vid restart @@ -402,7 +402,7 @@ class CCC_tf_MipBias : public CCC_Float public: void apply() { -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) if (nullptr == HW.pDevice) return; #endif @@ -410,7 +410,7 @@ class CCC_tf_MipBias : public CCC_Float #if defined(USE_DX9) for (u32 i = 0; i < HW.Caps.raster.dwStages; i++) CHK_DX(HW.pDevice->SetSamplerState(i, D3DSAMP_MIPMAPLODBIAS, *((u32*)value))); -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) SSManager.SetMipLODBias(*value); #endif } @@ -621,7 +621,7 @@ class CCC_memory_stats : public IConsole_Command virtual void Execute(LPCSTR /*args*/) { // TODO: OGL: Implement memory usage statistics. -#if defined(USE_DX9) || defined(USE_DX11) +#if defined(USE_DX9) || defined(USE_DX11) || defined(USE_DX12) u32 m_base = 0; u32 c_base = 0; u32 m_lmaps = 0; @@ -838,7 +838,7 @@ class CCC_SunshaftsIntensity : public CCC_Float #endif // Allow real-time fog config reload -#if (RENDER == R_R3) || (RENDER == R_R4) +#if (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) # ifndef MASTER_GOLD # include "Layers/xrRenderDX11/3DFluid/dx113DFluidManager.h" @@ -1102,7 +1102,7 @@ void xrRender_initconsole() CMD3(CCC_Token, "r3_minmax_sm", &ps_r3_minmax_sm, qminmax_sm_token); // Allow real-time fog config reload -#if (RENDER == R_R3) || (RENDER == R_R4) +#if (RENDER == R_R3) || (RENDER == R_R4) || (RENDER == R_R5) # ifndef MASTER_GOLD CMD1(CCC_Fog_Reload, "r3_fog_reload"); # endif @@ -1119,7 +1119,7 @@ void xrRender_initconsole() //CMD3(CCC_Mask, "r2_sun_ignore_portals", &ps_r2_ls_flags, R2FLAG_SUN_IGNORE_PORTALS); CMD4(CCC_Integer, "r2_mt_calculate", &ps_r2_mt_calculate, 0, 1); -#if RENDER == R_R4 +#if RENDER == R_R4 || RENDER == R_R5 CMD4(CCC_Integer, "r2_mt_render", &ps_r2_mt_render, 0, 1); #endif diff --git a/src/Layers/xrRender/xr_effgamma.cpp b/src/Layers/xrRender/xr_effgamma.cpp index fc9842c38f9..3dc5b594264 100644 --- a/src/Layers/xrRender/xr_effgamma.cpp +++ b/src/Layers/xrRender/xr_effgamma.cpp @@ -23,7 +23,7 @@ void CGammaControl::GenLUT(u16* r, u16* g, u16* b, u16 count) const } } -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) void CGammaControl::GenLUT(const DXGI_GAMMA_CONTROL_CAPABILITIES& GC, DXGI_GAMMA_CONTROL& G) const { constexpr DXGI_RGB Offset = { 0, 0, 0 }; @@ -64,7 +64,7 @@ void CGammaControl::Update() const HW.pDevice->SetGammaRamp(0, D3DSGR_NO_CALIBRATION, &G); return; } -#elif defined(USE_DX11) +#elif defined(USE_DX11) || defined(USE_DX12) if (HW.pDevice) { DXGI_GAMMA_CONTROL_CAPABILITIES GC; diff --git a/src/Layers/xrRender/xr_effgamma.h b/src/Layers/xrRender/xr_effgamma.h index 9eafd336fff..46bf4e0a9b0 100644 --- a/src/Layers/xrRender/xr_effgamma.h +++ b/src/Layers/xrRender/xr_effgamma.h @@ -35,7 +35,7 @@ class CGammaControl private: void GenLUT(u16* r, u16* g, u16* b, u16 count) const; -#if defined(USE_DX11) +#if defined(USE_DX11) || defined(USE_DX12) void GenLUT(const DXGI_GAMMA_CONTROL_CAPABILITIES& GC, DXGI_GAMMA_CONTROL& G) const; #endif }; diff --git a/src/Layers/xrRenderDX11/Blender_Recorder_R3.cpp b/src/Layers/xrRenderDX11/Blender_Recorder_R3.cpp index 9a8adb4fd43..95214964768 100644 --- a/src/Layers/xrRenderDX11/Blender_Recorder_R3.cpp +++ b/src/Layers/xrRenderDX11/Blender_Recorder_R3.cpp @@ -154,7 +154,7 @@ void CBlender_Compile::r_Pass(LPCSTR _vs, LPCSTR _gs, LPCSTR _ps, bool bFog, BOO dest.ps = ps; dest.vs = vs; dest.gs = gs; -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) dest.hs = RImplementation.Resources->_CreateHS("null"); dest.ds = RImplementation.Resources->_CreateDS("null"); dest.cs = RImplementation.Resources->_CreateCS("null"); @@ -171,7 +171,7 @@ void CBlender_Compile::r_Pass(LPCSTR _vs, LPCSTR _gs, LPCSTR _ps, bool bFog, BOO } } -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) void CBlender_Compile::r_TessPass(LPCSTR vs, LPCSTR hs, LPCSTR ds, LPCSTR gs, LPCSTR ps, bool bFog, BOOL bZtest, BOOL bZwrite, BOOL bABlend, D3DBLEND abSRC, D3DBLEND abDST, BOOL aTest, u32 aRef) { diff --git a/src/Layers/xrRenderDX11/StateManager/dx11StateManager.cpp b/src/Layers/xrRenderDX11/StateManager/dx11StateManager.cpp index 40806b7bd3e..576649ab19a 100644 --- a/src/Layers/xrRenderDX11/StateManager/dx11StateManager.cpp +++ b/src/Layers/xrRenderDX11/StateManager/dx11StateManager.cpp @@ -343,7 +343,7 @@ void dx11StateManager::SetColorWriteEnable(u32 WriteMask) bool bNeedUpdate = false; for (int i = 0; i < 4; ++i) { -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) if (m_BDesc.RenderTarget[i].RenderTargetWriteMask != WMask) #else if (m_BDesc.RenderTargetWriteMask[i] != WMask) @@ -355,7 +355,7 @@ void dx11StateManager::SetColorWriteEnable(u32 WriteMask) { m_bBSChanged = true; for (int i = 0; i < 4; ++i) -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) m_BDesc.RenderTarget[i].RenderTargetWriteMask = WMask; #else m_BDesc.RenderTargetWriteMask[i] = WMask; diff --git a/src/Layers/xrRenderDX11/dx11ConstantBuffer.cpp b/src/Layers/xrRenderDX11/dx11ConstantBuffer.cpp index 9bdd1f2d706..9c97f85a0f9 100644 --- a/src/Layers/xrRenderDX11/dx11ConstantBuffer.cpp +++ b/src/Layers/xrRenderDX11/dx11ConstantBuffer.cpp @@ -93,7 +93,7 @@ void dx11ConstantBuffer::Flush(u32 context_id) if (m_bChanged) { void* pData; -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) D3D11_MAPPED_SUBRESOURCE pSubRes; CHK_DX(HW.get_context(context_id)->Map(m_pBuffer, 0, D3D_MAP_WRITE_DISCARD, 0, &pSubRes)); pData = pSubRes.pData; @@ -103,7 +103,7 @@ void dx11ConstantBuffer::Flush(u32 context_id) VERIFY(pData); VERIFY(m_pBufferData); CopyMemory(pData, m_pBufferData, m_uiBufferSize); -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) HW.get_context(context_id)->Unmap(m_pBuffer, 0); #else m_pBuffer->Unmap(); diff --git a/src/Layers/xrRenderDX11/dx11HW.cpp b/src/Layers/xrRenderDX11/dx11HW.cpp index 00c16c2e639..40328d2d737 100644 --- a/src/Layers/xrRenderDX11/dx11HW.cpp +++ b/src/Layers/xrRenderDX11/dx11HW.cpp @@ -32,7 +32,8 @@ void CHW::OnAppActivate() if (m_pSwapChain && !m_ChainDesc.Windowed) { ShowWindow(m_ChainDesc.OutputWindow, SW_RESTORE); - m_pSwapChain->SetFullscreenState(ThisInstanceIsGlobal() ? psDeviceMode.WindowStyle == rsFullscreen : false, NULL); + m_pSwapChain->SetFullscreenState( + ThisInstanceIsGlobal() ? psDeviceMode.WindowStyle == rsFullscreen : false, NULL); } } @@ -52,17 +53,29 @@ void CHW::OnAppDeactivate() void CHW::CreateD3D() { hDXGI = XRay::LoadModule("dxgi"); + +#if defined(USE_DX12) + hD3D = XRay::LoadModule("d3d12"); +#else hD3D = XRay::LoadModule("d3d11"); +#endif // defined(USE_DX12) + if (!hD3D->IsLoaded() || !hDXGI->IsLoaded()) { Valid = false; return; } +#if defined(USE_DX12) // Минимально поддерживаемая версия Windows => Windows Vista SP2 или Windows 7. - const auto createDXGIFactory = static_cast(hDXGI->GetProcAddress("CreateDXGIFactory1")); + DX12CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&m_pFactory)); +#else + // Минимально поддерживаемая версия Windows => Windows Vista SP2 или Windows 7. + const auto createDXGIFactory = + static_cast(hDXGI->GetProcAddress("CreateDXGIFactory1")); if (createDXGIFactory) createDXGIFactory(__uuidof(IDXGIFactory1), (void**)(&m_pFactory)); +#endif if (m_pFactory) m_pFactory->EnumAdapters1(0, &m_pAdapter); @@ -82,7 +95,11 @@ void CHW::DestroyD3D() // To make it work with DXVK, etc. hD3D->Close(); hDXGI->Close(); +#if defined(USE_DX12) + if (auto hModule = GetModuleHandleA("d3d12.dll")) +#else if (auto hModule = GetModuleHandleA("d3d11.dll")) +#endif FreeLibrary(hModule); if (auto hModule = GetModuleHandleA("dxgi.dll")) FreeLibrary(hModule); @@ -115,38 +132,33 @@ void CHW::CreateDevice(SDL_Window* sdlWnd) HRESULT R; - D3D_FEATURE_LEVEL featureLevels[] = - { +#if defined(USE_DX12) + D3D_FEATURE_LEVEL featureLevels[] = {D3D_FEATURE_LEVEL_12_2, D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0}; +#else + D3D_FEATURE_LEVEL featureLevels[] = { #ifdef HAS_DX11_3 - D3D_FEATURE_LEVEL_12_1, - D3D_FEATURE_LEVEL_12_0, + D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, #endif - D3D_FEATURE_LEVEL_11_1, - D3D_FEATURE_LEVEL_11_0, - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0 - }; + D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0}; - D3D_FEATURE_LEVEL featureLevels2[] = - { - D3D_FEATURE_LEVEL_11_0, - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0 - }; + D3D_FEATURE_LEVEL featureLevels2[] = {D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0}; - D3D_FEATURE_LEVEL featureLevels3[] = - { - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0 - }; + D3D_FEATURE_LEVEL featureLevels3[] = {D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0}; +#endif auto& pContext = d3d_contexts_pool[CHW::IMM_CTX_ID]; - const auto createDevice = [&](const D3D_FEATURE_LEVEL* level, const u32 levels) - { - static const auto d3d11CreateDevice = static_cast(hD3D->GetProcAddress("D3D11CreateDevice")); - return d3d11CreateDevice(m_pAdapter, D3D_DRIVER_TYPE_UNKNOWN, - nullptr, createDeviceFlags, level, levels, +#if defined(USE_DX12) + const auto createDevice = [&](const D3D_FEATURE_LEVEL* level, const u32 levels) { + return DX12CreateDevice(m_pAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, createDeviceFlags, level, levels, + D3D12_SDK_VERSION, reinterpret_cast(&pDevice), &FeatureLevel, reinterpret_cast(& pContext)); + }; + R = createDevice(featureLevels, std::size(featureLevels)); +#else + const auto createDevice = [&](const D3D_FEATURE_LEVEL* level, const u32 levels) { + static const auto d3d11CreateDevice = + static_cast(hD3D->GetProcAddress("D3D11CreateDevice")); + return d3d11CreateDevice(m_pAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, createDeviceFlags, level, levels, D3D11_SDK_VERSION, &pDevice, &FeatureLevel, &pContext); }; @@ -158,9 +170,21 @@ void CHW::CreateDevice(SDL_Window* sdlWnd) if (FAILED(R)) R = createDevice(featureLevels2, std::size(featureLevels2)); } +#endif if (SUCCEEDED(R)) { +#if defined(USE_DX12) + D3DCompile = &::D3DCompile; + ComputeShadersSupported = true; + + D3D11_FEATURE_DATA_D3D11_OPTIONS options; + pDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS2, &options, sizeof(options)); + + DoublePrecisionFloatShaderOps = true; + SAD4ShaderInstructions = options.SAD4ShaderInstructions; + ExtendedDoublesShaderInstructions = options.ExtendedDoublesShaderInstructions; +#else pContext->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast(&pContext1)); #ifdef HAS_DX11_3 pDevice->QueryInterface(__uuidof(ID3D11Device3), reinterpret_cast(&pDevice3)); @@ -183,8 +207,7 @@ void CHW::CreateDevice(SDL_Window* sdlWnd) } D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS data; - pDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, - &data, sizeof(data)); + pDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &data, sizeof(data)); ComputeShadersSupported = data.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x; } D3D11_FEATURE_DATA_D3D11_OPTIONS options; @@ -196,6 +219,7 @@ void CHW::CreateDevice(SDL_Window* sdlWnd) DoublePrecisionFloatShaderOps = doubles.DoublePrecisionFloatShaderOps; SAD4ShaderInstructions = options.SAD4ShaderInstructions; ExtendedDoublesShaderInstructions = options.ExtendedDoublesShaderInstructions; +#endif } if (FAILED(R)) @@ -206,7 +230,8 @@ void CHW::CreateDevice(SDL_Window* sdlWnd) // Fatal error! Cannot create rendering device AT STARTUP !!! Msg("Failed to initialize graphics hardware.\n" "Please try to restart the game.\n" - "CreateDevice returned 0x%08x", R); + "CreateDevice returned 0x%08x", + R); xrDebug::DoExit("Failed to initialize graphics hardware.\nPlease try to restart the game."); } @@ -215,7 +240,11 @@ void CHW::CreateDevice(SDL_Window* sdlWnd) // Create deferred contexts for (int id = 0; id < R__NUM_PARALLEL_CONTEXTS; ++id) { +#if defined(USE_DX12) + R = pDevice->CreateDeferredContext(0, reinterpret_cast(&d3d_contexts_pool[id])); +#else R = pDevice->CreateDeferredContext(0, &d3d_contexts_pool[id]); +#endif VERIFY(SUCCEEDED(R)); } @@ -231,16 +260,20 @@ void CHW::CreateDevice(SDL_Window* sdlWnd) const HWND hwnd = info.info.win.window; +#if defined(USE_DX12) + if (!CreateSwapChain(hwnd)) + Valid = false; +#else if (!CreateSwapChain2(hwnd)) { if (!CreateSwapChain(hwnd)) Valid = false; } +#endif // Select depth-stencil format - constexpr DXGI_FORMAT formats[] = - { - //DXGI_FORMAT_D32_FLOAT_S8X24_UINT, + constexpr DXGI_FORMAT formats[] = { + // DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_D24_UNORM_S8_UINT, }; const DXGI_FORMAT selectedFormat = SelectFormat(D3D_FORMAT_SUPPORT_DEPTH_STENCIL, formats); @@ -270,11 +303,13 @@ bool CHW::CreateSwapChain(HWND hwnd) sd.BufferDesc.Width = Device.dwWidth; sd.BufferDesc.Height = Device.dwHeight; + sd.BufferDesc.RefreshRate.Numerator = 0; + sd.BufferDesc.RefreshRate.Denominator = 0; + // TODO: DX11: implement dynamic format selection - constexpr DXGI_FORMAT formats[] = - { - //DXGI_FORMAT_R16G16B16A16_FLOAT, // Do we even need this? - //DXGI_FORMAT_R10G10B10A2_UNORM, // D3DX11SaveTextureToMemory fails on this format + constexpr DXGI_FORMAT formats[] = { + // DXGI_FORMAT_R16G16B16A16_FLOAT, // Do we even need this? + // DXGI_FORMAT_R10G10B10A2_UNORM, // D3DX11SaveTextureToMemory fails on this format DXGI_FORMAT_R8G8B8A8_UNORM, }; @@ -283,7 +318,12 @@ bool CHW::CreateSwapChain(HWND hwnd) Caps.fTarget = dx11TextureUtils::ConvertTextureFormat(sd.BufferDesc.Format); // Buffering +#if defined(USE_DX12) + BackBufferCount = 2; +#else BackBufferCount = 1; +#endif + sd.BufferCount = BackBufferCount; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; @@ -299,18 +339,32 @@ bool CHW::CreateSwapChain(HWND hwnd) XXX: Fix this windoze stuff!!! */ sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - sd.OutputWindow = hwnd; - sd.Windowed = ThisInstanceIsGlobal() ? psDeviceMode.WindowStyle != rsFullscreen : true; // Additional set up +#if defined(USE_DX12) + sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH | DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; +#else sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; +#endif +#if defined(USE_DX11) const auto hr = m_pFactory->CreateSwapChain(pDevice, &sd, &m_pSwapChain); +#else + const auto hr = m_pFactory->CreateSwapChain(pDevice, &sd, reinterpret_cast(& m_pSwapChain)); +#endif + +#if defined(USE_DX12) + m_pSwapChain->SetMaximumFrameLatency(1); + if (ThisInstanceIsGlobal()) + Device.PresentationFinished = m_pSwapChain->GetFrameLatencyWaitableObject(); +#endif + return SUCCEEDED(hr); } +#if defined(USE_DX11) bool CHW::CreateSwapChain2(HWND hwnd) { if (strstr(Core.Params, "-no_dx11_2")) @@ -329,10 +383,9 @@ bool CHW::CreateSwapChain2(HWND hwnd) desc.Width = Device.dwWidth; desc.Height = Device.dwHeight; - constexpr DXGI_FORMAT formats[] = - { - //DXGI_FORMAT_R16G16B16A16_FLOAT, - //DXGI_FORMAT_R10G10B10A2_UNORM, + constexpr DXGI_FORMAT formats[] = { + // DXGI_FORMAT_R16G16B16A16_FLOAT, + // DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, }; @@ -350,7 +403,7 @@ bool CHW::CreateSwapChain2(HWND hwnd) desc.SampleDesc.Quality = 0; // Windoze - //desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; // XXX: tearing glitches with flip presentation model + // desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; // XXX: tearing glitches with flip presentation model desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; desc.Scaling = DXGI_SCALING_STRETCH; @@ -361,8 +414,8 @@ bool CHW::CreateSwapChain2(HWND hwnd) desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; IDXGISwapChain1* swapchain{}; - const HRESULT result = pFactory2->CreateSwapChainForHwnd(pDevice, hwnd, &desc, - fulldesc.Windowed ? nullptr : &fulldesc, nullptr, &swapchain); + const HRESULT result = pFactory2->CreateSwapChainForHwnd( + pDevice, hwnd, &desc, fulldesc.Windowed ? nullptr : &fulldesc, nullptr, &swapchain); _RELEASE(pFactory2); if (FAILED(result)) @@ -387,11 +440,9 @@ bool CHW::CreateSwapChain2(HWND hwnd) return false; } +#endif -bool CHW::ThisInstanceIsGlobal() const -{ - return this == &HW; -} +bool CHW::ThisInstanceIsGlobal() const { return this == &HW; } void CHW::DestroyDevice() { @@ -405,22 +456,30 @@ void CHW::DestroyDevice() // Must switch to windowed mode to release swap chain if (!m_ChainDesc.Windowed && m_pSwapChain) m_pSwapChain->SetFullscreenState(FALSE, NULL); +#if defined(USE_DX11) #ifdef HAS_DX11_2 _RELEASE(m_pSwapChain2); +#endif #endif _SHOW_REF("refCount:m_pSwapChain", m_pSwapChain); _RELEASE(m_pSwapChain); - + +#if defined(USE_DX11) _RELEASE(pContext1); +#endif + for (int id = 0; id < R__NUM_CONTEXTS; ++id) { _SHOW_REF("refCount:pContext", d3d_contexts_pool[id]); _RELEASE(d3d_contexts_pool[id]); } +#if defined(USE_DX11) #ifdef HAS_DX11_3 _RELEASE(pDevice3); #endif +#endif + _SHOW_REF("refCount:pDevice:", pDevice); _RELEASE(pDevice); DestroyD3D(); @@ -438,16 +497,11 @@ void CHW::Reset() DXGI_MODE_DESC& desc = m_ChainDesc.BufferDesc; desc.Width = Device.dwWidth; desc.Height = Device.dwHeight; - CHK_DX(m_pSwapChain->ResizeTarget(&desc)); - CHK_DX(m_pSwapChain->ResizeBuffers( - cd.BufferCount, desc.Width, desc.Height, desc.Format, cd.Flags)); + CHK_DX(m_pSwapChain->ResizeBuffers(cd.BufferCount, desc.Width, desc.Height, desc.Format, cd.Flags)); } -void CHW::SetPrimaryAttributes(u32& /*windowFlags*/) -{ - -} +void CHW::SetPrimaryAttributes(u32& /*windowFlags*/) {} bool CHW::CheckFormatSupport(const DXGI_FORMAT format, const u32 feature) const { @@ -477,26 +531,31 @@ bool CHW::UsingFlipPresentationModel() const #ifdef HAS_DXGI1_4 || m_ChainDesc.SwapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD #endif - ; + ; } std::pair CHW::GetSurfaceSize() const { - return - { - m_ChainDesc.BufferDesc.Width, - m_ChainDesc.BufferDesc.Height - }; + return {m_ChainDesc.BufferDesc.Width, m_ChainDesc.BufferDesc.Height}; } -void CHW::BeginScene() { } -void CHW::EndScene() { } +void CHW::BeginScene() {} +void CHW::EndScene() {} void CHW::Present() { const bool bUseVSync = psDeviceMode.WindowStyle == rsFullscreen && psDeviceFlags.test(rsVSync); // xxx: weird tearing glitches when VSync turned on for windowed mode in DX11 + +#if defined(USE_DX12) + WaitForSingleObjectEx(Device.PresentationFinished.GetHandle(), + 1000, // 1 second timeout (shouldn't ever occur) + true); +#endif + m_pSwapChain->Present(bUseVSync ? 1 : 0, 0); + +#if defined(USE_DX11) #ifdef HAS_DX11_2 if (m_pSwapChain2 && UsingFlipPresentationModel()) { @@ -507,7 +566,20 @@ void CHW::Present() m_pSwapChain2->SetSourceSize(UINT(Device.dwWidth * 0.7f), UINT(Device.dwHeight * 0.7f)); } #endif +#else + if (UsingFlipPresentationModel()) + { + const float fps = Device.GetStats().fFPS; + if (fps < 30) + m_pSwapChain->SetSourceSize(UINT(Device.dwWidth * 0.85f), UINT(Device.dwHeight * 0.85f)); + else if (fps < 15) + m_pSwapChain->SetSourceSize(UINT(Device.dwWidth * 0.7f), UINT(Device.dwHeight * 0.7f)); + } +#endif + +#if !defined(USE_DX12) CurrentBackBuffer = (CurrentBackBuffer + 1) % BackBufferCount; +#endif } DeviceState CHW::GetDeviceState() const @@ -517,8 +589,7 @@ DeviceState CHW::GetDeviceState() const switch (result) { // Check if the device is ready to be reset - case DXGI_ERROR_DEVICE_RESET: - return DeviceState::NeedReset; + case DXGI_ERROR_DEVICE_RESET: return DeviceState::NeedReset; } return DeviceState::Normal; diff --git a/src/Layers/xrRenderDX11/dx11HW.h b/src/Layers/xrRenderDX11/dx11HW.h index 116149d492b..d71cc4ffd05 100644 --- a/src/Layers/xrRenderDX11/dx11HW.h +++ b/src/Layers/xrRenderDX11/dx11HW.h @@ -7,9 +7,7 @@ #include -class CHW - : public pureAppActivate, - public pureAppDeactivate +class CHW : public pureAppActivate, public pureAppDeactivate { public: CHW(); @@ -48,32 +46,50 @@ class CHW private: bool CreateSwapChain(HWND hwnd); +#if defined(USE_DX11) bool CreateSwapChain2(HWND hwnd); - +#endif bool ThisInstanceIsGlobal() const; public: + +#if defined(USE_DX12) + ICF ID3D11DeviceContext1* get_context(u32 context_id) + { + VERIFY(context_id < R__NUM_CONTEXTS); + return d3d_contexts_pool[context_id]; + } +#else ICF ID3DDeviceContext* get_context(u32 context_id) { VERIFY(context_id < R__NUM_CONTEXTS); return d3d_contexts_pool[context_id]; } +#endif public: static constexpr auto IMM_CTX_ID = R__NUM_PARALLEL_CONTEXTS; CHWCaps Caps; - u32 BackBufferCount{}; - u32 CurrentBackBuffer{}; - + u32 BackBufferCount = 0; +#if defined(USE_DX11) + u32 CurrentBackBuffer = 0; +#endif ID3DDevice* pDevice = nullptr; // render device D3D_DRIVER_TYPE m_DriverType; +#if defined(USE_DX12) + IDXGIFactory4* m_pFactory = nullptr; + IDXGIAdapter1* m_pAdapter = nullptr; // pD3D equivalent + IDXGISwapChain3* m_pSwapChain = nullptr; +#else IDXGIFactory1* m_pFactory = nullptr; IDXGIAdapter1* m_pAdapter = nullptr; // pD3D equivalent IDXGISwapChain* m_pSwapChain = nullptr; +#endif + D3D_FEATURE_LEVEL FeatureLevel; bool Valid = true; bool ComputeShadersSupported; @@ -81,8 +97,13 @@ class CHW bool SAD4ShaderInstructions; bool ExtendedDoublesShaderInstructions; +#if defined(USE_DX12) + ID3D11DeviceContext1* d3d_contexts_pool[R__NUM_CONTEXTS]{}; +#else ID3DDeviceContext* d3d_contexts_pool[R__NUM_CONTEXTS]{}; +#endif +#if defined(USE_DX11) bool DX10Only = false; #ifdef HAS_DX11_2 IDXGISwapChain2* m_pSwapChain2 = nullptr; @@ -91,6 +112,15 @@ class CHW ID3D11Device3* pDevice3 = nullptr; #endif ID3D11DeviceContext1* pContext1 = nullptr; +#endif + + IC u32 GetCurrentBackBufferIndex() const { +#if defined(USE_DX11) + return CurrentBackBuffer; +#else + return m_pSwapChain->GetCurrentBackBufferIndex(); +#endif + } using D3DCompileFunc = decltype(&D3DCompile); D3DCompileFunc D3DCompile = nullptr; diff --git a/src/Layers/xrRenderDX11/dx11R_Backend_Runtime.h b/src/Layers/xrRenderDX11/dx11R_Backend_Runtime.h index da4aab34a52..68f64f4379c 100644 --- a/src/Layers/xrRenderDX11/dx11R_Backend_Runtime.h +++ b/src/Layers/xrRenderDX11/dx11R_Backend_Runtime.h @@ -23,7 +23,7 @@ IC void CBackend::set_RT(ID3DRenderTargetView* RT, u32 ID) // HW.pDevice->OMSetRenderTargets(sizeof(pRT)/sizeof(pRT[0]), pRT, pZB); // Reset all RT's here to allow RT to be bounded as input if (!m_bChangedRTorZB) - HW.get_context(context_id)->OMSetRenderTargets(0, 0, 0); + HW.get_context(context_id)->OMSetRenderTargets(0, NULL, NULL); m_bChangedRTorZB = true; } @@ -40,7 +40,7 @@ IC void CBackend::set_ZB(ID3DDepthStencilView* ZB) // HW.pDevice->OMSetRenderTargets(sizeof(pRT)/sizeof(pRT[0]), pRT, pZB); // Reset all RT's here to allow RT to be bounded as input if (!m_bChangedRTorZB) - HW.get_context(context_id)->OMSetRenderTargets(0, 0, 0); + HW.get_context(context_id)->OMSetRenderTargets(0, NULL, NULL); m_bChangedRTorZB = true; } } @@ -62,13 +62,17 @@ IC void CBackend::ClearZB(ID3DDepthStencilView* zb, float depth, u8 stencil) IC bool CBackend::ClearRTRect(ID3DRenderTargetView* rt, const Fcolor& color, size_t numRects, const Irect* rects) { -#ifdef USE_DX11 +#if defined(USE_DX11) if (HW.pContext1) { HW.pContext1->ClearView(rt, reinterpret_cast(&color), reinterpret_cast(rects), numRects); return true; } +#elif defined(USE_DX12) + HW.get_context(context_id)->ClearView( + rt, reinterpret_cast(&color), reinterpret_cast(rects), numRects); + return true; #else UNUSED(numRects); UNUSED(rects); @@ -79,7 +83,7 @@ IC bool CBackend::ClearRTRect(ID3DRenderTargetView* rt, const Fcolor& color, siz IC bool CBackend::ClearZBRect(ID3DDepthStencilView* zb, float depth, size_t numRects, const Irect* rects) { -#ifdef USE_DX11 +#if defined(USE_DX11) if (HW.pContext1) { Fcolor color = { depth, depth, depth, depth }; @@ -87,6 +91,11 @@ IC bool CBackend::ClearZBRect(ID3DDepthStencilView* zb, float depth, size_t numR reinterpret_cast(rects), numRects); return true; } +#elif defined(USE_DX12) + Fcolor color = {depth, depth, depth, depth}; + HW.get_context(context_id)->ClearView(zb, reinterpret_cast(&color), + reinterpret_cast(rects), numRects); + return true; #else UNUSED(numRects); UNUSED(rects); @@ -112,7 +121,7 @@ ICF void CBackend::set_PS(ID3DPixelShader* _ps, LPCSTR _n) PGO(Msg("PGO:Pshader:%x", _ps)); stat.ps++; ps = _ps; -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) HW.get_context(context_id)->PSSetShader(ps, 0, 0); #else HW.pContext->PSSetShader(ps); @@ -131,7 +140,7 @@ ICF void CBackend::set_GS(ID3DGeometryShader* _gs, LPCSTR _n) PGO(Msg("PGO:Gshader:%x", _ps)); stat.gs++; gs = _gs; -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) HW.get_context(context_id)->GSSetShader(gs, 0, 0); #else HW.pContext->GSSetShader(gs); @@ -143,7 +152,7 @@ ICF void CBackend::set_GS(ID3DGeometryShader* _gs, LPCSTR _n) } } -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) ICF void CBackend::set_HS(ID3D11HullShader* _hs, LPCSTR _n) { if (hs != _hs) @@ -199,7 +208,7 @@ ICF void CBackend::set_VS(ID3DVertexShader* _vs, LPCSTR _n) PGO(Msg("PGO:Vshader:%x", _vs)); stat.vs++; vs = _vs; -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) HW.get_context(context_id)->VSSetShader(vs, 0, 0); #else HW.pContext->VSSetShader(vs); @@ -293,7 +302,7 @@ IC void CBackend::ApplyPrimitieTopology(D3D_PRIMITIVE_TOPOLOGY Topology) } } -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) IC void CBackend::Compute(u32 ThreadGroupCountX, u32 ThreadGroupCountY, u32 ThreadGroupCountZ) { stat.compute.calls++; @@ -319,7 +328,7 @@ IC void CBackend::Render(D3DPRIMITIVETYPE T, u32 baseV, u32 startV, u32 countV, u32 iIndexCount = GetIndexCount(T, PC); //!!! HACK !!! -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) if (hs != 0 || ds != 0) { R_ASSERT(Topology == D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); @@ -583,7 +592,7 @@ IC void CBackend::set_Constants(R_constant_table* C) xforms.unmap(); hemi.unmap(); tree.unmap(); -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) LOD.unmap(); #endif StateManager.UnmapConstants(); @@ -597,7 +606,7 @@ IC void CBackend::set_Constants(R_constant_table* C) ref_cbuffer aPixelConstants[MaxCBuffers]; ref_cbuffer aVertexConstants[MaxCBuffers]; ref_cbuffer aGeometryConstants[MaxCBuffers]; -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) ref_cbuffer aHullConstants[MaxCBuffers]; ref_cbuffer aDomainConstants[MaxCBuffers]; ref_cbuffer aComputeConstants[MaxCBuffers]; @@ -609,7 +618,7 @@ IC void CBackend::set_Constants(R_constant_table* C) aVertexConstants[i] = m_aVertexConstants[i]; aGeometryConstants[i] = m_aGeometryConstants[i]; -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) aHullConstants[i] = m_aHullConstants[i]; aDomainConstants[i] = m_aDomainConstants[i]; aComputeConstants[i] = m_aComputeConstants[i]; @@ -619,7 +628,7 @@ IC void CBackend::set_Constants(R_constant_table* C) m_aVertexConstants[i] = 0; m_aGeometryConstants[i] = 0; -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) m_aHullConstants[i] = 0; m_aDomainConstants[i] = 0; m_aComputeConstants[i] = 0; @@ -647,7 +656,7 @@ IC void CBackend::set_Constants(R_constant_table* C) VERIFY((uiBufferIndex & CB_BufferIndexMask) < MaxCBuffers); m_aGeometryConstants[uiBufferIndex & CB_BufferIndexMask] = it->second; } -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) else if ((uiBufferIndex & CB_BufferTypeMask) == CB_BufferHullShader) { VERIFY((uiBufferIndex & CB_BufferIndexMask) < MaxCBuffers); @@ -827,12 +836,16 @@ IC void CBackend::get_ConstantDirect(const shared_str& n, size_t DataSize, void* IC void CBackend::gpu_mark_begin(const wchar_t* name) { +#ifdef USE_DX11 pAnnotation->BeginEvent(name); +#endif // USE_DX11 } IC void CBackend::gpu_mark_end() { +#ifdef USE_DX11 pAnnotation->EndEvent(); +#endif // USE_DX11 } IC void CBackend::set_pass_targets(const ref_rt& _1, const ref_rt& _2, const ref_rt& _3, const ref_rt& zb) diff --git a/src/Layers/xrRenderDX11/dx11ResourceManager_Resources.cpp b/src/Layers/xrRenderDX11/dx11ResourceManager_Resources.cpp index 1c9c57b1153..b900c1b0781 100644 --- a/src/Layers/xrRenderDX11/dx11ResourceManager_Resources.cpp +++ b/src/Layers/xrRenderDX11/dx11ResourceManager_Resources.cpp @@ -22,7 +22,7 @@ SPass* CResourceManager::_CreatePass(const SPass& proto) P->ps = proto.ps; P->vs = proto.vs; P->gs = proto.gs; -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) P->hs = proto.hs; P->ds = proto.ds; P->cs = proto.cs; @@ -123,7 +123,7 @@ void CResourceManager::_DeletePS(const SPS* ps) { DestroyShader(ps); } SGS* CResourceManager::_CreateGS(LPCSTR Name) { return CreateShader(Name); } void CResourceManager::_DeleteGS(const SGS* GS) { DestroyShader(GS); } -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) SHS* CResourceManager::_CreateHS(LPCSTR Name) { return CreateShader(Name); } void CResourceManager::_DeleteHS(const SHS* HS) { DestroyShader(HS); } diff --git a/src/Layers/xrRenderDX11/dx11SH_RT.cpp b/src/Layers/xrRenderDX11/dx11SH_RT.cpp index 51b99f423cc..e6abba0a1b4 100644 --- a/src/Layers/xrRenderDX11/dx11SH_RT.cpp +++ b/src/Layers/xrRenderDX11/dx11SH_RT.cpp @@ -12,7 +12,11 @@ CRT::~CRT() RImplementation.Resources->_DeleteRT(this); } +#if defined(USE_DX12) +void CRT::create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount /*= 1*/, u32 slices_num /*=1*/, Flags32 flags /*= {}*/, Fcolor color) +#else void CRT::create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount /*= 1*/, u32 slices_num /*=1*/, Flags32 flags /*= {}*/) +#endif { if (pSurface) return; @@ -128,7 +132,7 @@ void CRT::create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount /*= 1*/ } } -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) if (flags.test(CreateUAV)) { dwFlags |= CreateUAV; @@ -141,7 +145,12 @@ void CRT::create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount /*= 1*/ } #endif +#if defined(USE_DX12) + const FLOAT cClearValue[4] = {color.r, color.g, color.b, color.a}; + CHK_DX(reinterpret_cast(HW.pDevice)->CreateTexture2D(&desc, cClearValue, NULL, &pSurface)); +#else CHK_DX(HW.pDevice->CreateTexture2D(&desc, NULL, &pSurface)); +#endif } #ifdef DEBUG @@ -232,7 +241,7 @@ void CRT::create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount /*= 1*/ else CHK_DX(HW.pDevice->CreateRenderTargetView(pSurface, 0, &pRT)); -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) if (desc.BindFlags & D3D11_BIND_UNORDERED_ACCESS) { D3D11_UNORDERED_ACCESS_VIEW_DESC UAVDesc{}; @@ -271,7 +280,7 @@ void CRT::destroy() HW.stats_manager.decrement_stats_rtarget(pSurface); _RELEASE(pSurface); -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) _RELEASE(pUAView); #endif } @@ -303,10 +312,17 @@ void CRT::resolve_into(CRT& destination) const // TODO: this should be moved int _RELEASE(destSurf); } +#if defined(USE_DX12) +void resptrcode_crt::create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount /*= 1*/, u32 slices_num /*=1*/, Flags32 flags /*= 0*/, Fcolor color) +{ + _set(RImplementation.Resources->_CreateRT(Name, w, h, f, SampleCount, slices_num, flags, color)); +} +#else void resptrcode_crt::create(LPCSTR Name, u32 w, u32 h, D3DFORMAT f, u32 SampleCount /*= 1*/, u32 slices_num /*=1*/, Flags32 flags /*= 0*/) { _set(RImplementation.Resources->_CreateRT(Name, w, h, f, SampleCount, slices_num, flags)); } +#endif ////////////////////////////////////////////////////////////////////////// /* DX10 cut diff --git a/src/Layers/xrRenderDX11/dx11SH_Texture.cpp b/src/Layers/xrRenderDX11/dx11SH_Texture.cpp index 9e70f5b8d73..4ac146466fb 100644 --- a/src/Layers/xrRenderDX11/dx11SH_Texture.cpp +++ b/src/Layers/xrRenderDX11/dx11SH_Texture.cpp @@ -231,7 +231,8 @@ void CTexture::apply_theora(CBackend& cmd_list, u32 dwStage) u32 _w = pTheora->Width(false); // R_CHK (T2D->LockRect(0,&R,&rect,0)); -#ifdef USE_DX11 + +#if defined(USE_DX11) || defined(USE_DX12) R_CHK(HW.get_context(cmd_list.context_id)->Map(T2D, 0, D3D_MAP_WRITE_DISCARD, 0, &mapData)); #else R_CHK(T2D->Map(0, D3D_MAP_WRITE_DISCARD, 0, &mapData)); @@ -242,7 +243,7 @@ void CTexture::apply_theora(CBackend& cmd_list, u32 dwStage) pTheora->DecompressFrame((u32*)mapData.pData, _w - rect.right, _pos); VERIFY(u32(_pos) == rect.bottom * _w); // R_CHK (T2D->UnlockRect(0)); -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) HW.get_context(cmd_list.context_id)->Unmap(T2D, 0); #else T2D->Unmap(0); @@ -263,7 +264,7 @@ void CTexture::apply_avi(CBackend& cmd_list, u32 dwStage) const // AVI // R_CHK (T2D->LockRect(0,&R,NULL,0)); -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) R_CHK(HW.get_context(CHW::IMM_CTX_ID)->Map(T2D, 0, D3D_MAP_WRITE_DISCARD, 0, &mapData)); #else R_CHK(T2D->Map(0, D3D_MAP_WRITE_DISCARD, 0, &mapData)); @@ -273,7 +274,7 @@ void CTexture::apply_avi(CBackend& cmd_list, u32 dwStage) const pAVI->GetFrame(&ptr); CopyMemory(mapData.pData, ptr, pAVI->m_dwWidth * pAVI->m_dwHeight * 4); // R_CHK (T2D->UnlockRect(0)); -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) HW.get_context(CHW::IMM_CTX_ID)->Unmap(T2D, 0); #else T2D->Unmap(0); diff --git a/src/Layers/xrRenderDX11/dx11StateUtils.cpp b/src/Layers/xrRenderDX11/dx11StateUtils.cpp index 36a5a727d9f..ecaa452ab50 100644 --- a/src/Layers/xrRenderDX11/dx11StateUtils.cpp +++ b/src/Layers/xrRenderDX11/dx11StateUtils.cpp @@ -158,7 +158,7 @@ void ResetDescription(D3D_DEPTH_STENCIL_DESC& desc) desc.BackFace.StencilFunc = D3D_COMPARISON_ALWAYS; } -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) void ResetDescription(D3D_BLEND_DESC& desc) { ZeroMemory(&desc, sizeof(desc)); @@ -289,7 +289,7 @@ bool operator==(const D3D_DEPTH_STENCIL_DESC& desc1, const D3D_DEPTH_STENCIL_DES return true; } -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) bool operator==(const D3D_BLEND_DESC& desc1, const D3D_BLEND_DESC& desc2) { if (desc1.AlphaToCoverageEnable != desc2.AlphaToCoverageEnable) @@ -424,7 +424,7 @@ u32 GetHash(const D3D_DEPTH_STENCIL_DESC& desc) return Hash.GetHash(); } -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) u32 GetHash(const D3D_BLEND_DESC& desc) { dxHashHelper Hash; @@ -521,7 +521,7 @@ void ValidateState(D3D_DEPTH_STENCIL_DESC& desc) } } -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) void ValidateState(D3D_BLEND_DESC& desc) { BOOL bBlendEnable = FALSE; diff --git a/src/Layers/xrRenderDX11/dx11r_constants_cache.h b/src/Layers/xrRenderDX11/dx11r_constants_cache.h index f9f1e0e748a..54ccc29404d 100644 --- a/src/Layers/xrRenderDX11/dx11r_constants_cache.h +++ b/src/Layers/xrRenderDX11/dx11r_constants_cache.h @@ -36,7 +36,7 @@ class ECORE_API R_constants { set(C, C->gs, std::forward(args)...); } // a_vertex.b_dirty=TRUE; } -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) if (C->destination & RC_dest_hull) { set(C, C->hs, std::forward(args)...); @@ -76,7 +76,7 @@ class ECORE_API R_constants { seta(C, C->gs, e, std::forward(args)...); } // a_vertex.b_dirty=TRUE; } -#ifdef USE_DX11 +#if defined(USE_DX11) || defined(USE_DX12) if (C->destination & RC_dest_hull) { seta(C, C->hs, e, std::forward(args)...); diff --git a/src/Layers/xrRenderPC_GL/gl_rendertarget.h b/src/Layers/xrRenderPC_GL/gl_rendertarget.h index c6167b5b216..8b1291aa80c 100644 --- a/src/Layers/xrRenderPC_GL/gl_rendertarget.h +++ b/src/Layers/xrRenderPC_GL/gl_rendertarget.h @@ -210,7 +210,7 @@ class CRenderTarget : public IRender_Target bool m_bHasActiveVolumetric; public: - CRenderTarget(); + CRenderTarget(bool reset = false); ~CRenderTarget() override; void build_textures(); diff --git a/src/Layers/xrRenderPC_GL/stdafx.h b/src/Layers/xrRenderPC_GL/stdafx.h index 9f00421c26e..cbf0a3f1483 100644 --- a/src/Layers/xrRenderPC_GL/stdafx.h +++ b/src/Layers/xrRenderPC_GL/stdafx.h @@ -37,6 +37,7 @@ #define R_R2 2 #define R_R3 3 #define R_R4 4 +#define R_R5 5 #define RENDER R_GL #include "Common/_d3d_extensions.h" diff --git a/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.cpp b/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.cpp index 1514aa46371..13b93513c8b 100644 --- a/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.cpp +++ b/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.cpp @@ -6,7 +6,7 @@ #include "xrEngine/IGame_Persistent.h" -CRenderTarget::CRenderTarget() +CRenderTarget::CRenderTarget(bool reset) : im_noise_time(1.f / 100.0f), param_noise_scale(1.f), param_noise_fps(25.f), diff --git a/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.h b/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.h index 6ae1444044a..48206b83c7a 100644 --- a/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.h +++ b/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.h @@ -80,7 +80,7 @@ class CRenderTarget : public IRender_Target void calc_tc_duality_ss(Fvector2& r0, Fvector2& r1, Fvector2& l0, Fvector2& l1); public: - CRenderTarget(); + CRenderTarget(bool reset = false); void Begin(); void End(); diff --git a/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.h.bak b/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.h.bak new file mode 100644 index 00000000000..6ae1444044a --- /dev/null +++ b/src/Layers/xrRenderPC_R1/FStaticRender_RenderTarget.h.bak @@ -0,0 +1,126 @@ +#pragma once + +#include "Layers/xrRender/ColorMapManager.h" + +class CRenderTarget : public IRender_Target +{ +private: + bool bAvailable; + u32 rtWidth; + u32 rtHeight; + + u32 curWidth; + u32 curHeight; + +public: + // Base targets + xr_vector rt_Base; + ref_rt rt_Base_Depth; + +private: + ref_rt rt_Generic; + ref_rt rt_Depth; + + ref_rt rt_color_map; + ref_rt rt_distort; + + // FFP postprocessing + ref_shader s_set; + ref_shader s_gray; + ref_shader s_blend; + ref_shader s_duality; + ref_shader s_noise; + + // Can't implement in a single pass of a shader since + // should be compiled only for the hardware that supports it. + ref_shader s_postprocess[2]{}; // Igor: 0 - plain, 1 - colormapped + ref_shader s_postprocess_D[2]{}; // Igor: 0 - plain, 1 - colormapped + ref_geom g_postprocess[2]{}; + + float im_noise_time; + u32 im_noise_shift_w{}; + u32 im_noise_shift_h{}; + + float param_blur{}; + float param_gray{}; + float param_duality_h{}; + float param_duality_v{}; + float param_noise{}; + float param_noise_scale; + float param_noise_fps; + + // Color mapping + float param_color_map_influence{}; + float param_color_map_interpolate{}; + ColorMapManager color_map_manager; + + u32 param_color_base; + u32 param_color_gray; + Fvector param_color_add{}; + + u32 frame_distort; + +public: + ref_rt rt_temp_zb; + + // Igor: for async screenshots + ref_rt rt_async_ss; // 32bit (r,g,b,a) is situated in the system memory + +private: + [[nodiscard]] + bool NeedColorMapping() const; + + [[nodiscard]] + bool NeedPostProcess() const; + + [[nodiscard]] + bool Available() const { return bAvailable; } + + void calc_tc_noise(Fvector2& p0, Fvector2& p1); + void calc_tc_duality_ss(Fvector2& r0, Fvector2& r1, Fvector2& l0, Fvector2& l1); + +public: + CRenderTarget(); + + void Begin(); + void End(); + + void DoAsyncScreenshot() const; + [[nodiscard]] + bool Perform() const; + + [[nodiscard]] + ID3DRenderTargetView* get_base_rt() const { return rt_Base[HW.CurrentBackBuffer]->pRT; } + [[nodiscard]] + ID3DDepthStencilView* get_base_zb() const { return rt_Base_Depth->pRT; } + + void set_blur(float f) override { param_blur = f; } + void set_gray(float f) override { param_gray = f; } + void set_duality_h(float f) override { param_duality_h = _abs(f); } + void set_duality_v(float f) override { param_duality_v = _abs(f); } + void set_noise(float f) override { param_noise = f; } + void set_noise_scale(float f) override { param_noise_scale = f; } + void set_noise_fps(float f) override { param_noise_fps = _abs(f) + EPS_S; } + void set_color_base(u32 f) override { param_color_base = f; } + void set_color_gray(u32 f) override { param_color_gray = f; } + void set_color_add(const Fvector& f) override { param_color_add = f; } + void set_cm_imfluence(float f) override { param_color_map_influence = f; } + void set_cm_interpolate(float f) override { param_color_map_interpolate = f; } + + void set_cm_textures(const shared_str& tex0, const shared_str& tex1) override + { + color_map_manager.SetTextures(tex0, tex1); + } + + u32 get_width(CBackend& cmd_list) override { return curWidth; } + u32 get_height(CBackend& cmd_list) override { return curHeight; } + u32 get_rtwidth() const { return rtWidth; } + u32 get_rtheight() const { return rtHeight; } + + void phase_distortion(); + void phase_combine(bool bDistort, bool bCMap); + +private: + void phase_combine_fpp(u32 p_color, u32 p_gray, u32 p_alpha, + Fvector2 n0, Fvector2 n1, Fvector2 r0, Fvector2 r1, Fvector2 l0, Fvector2 l1); +}; diff --git a/src/Layers/xrRenderPC_R1/stdafx.h b/src/Layers/xrRenderPC_R1/stdafx.h index 91ae6bf2e2b..f8e1be5db23 100644 --- a/src/Layers/xrRenderPC_R1/stdafx.h +++ b/src/Layers/xrRenderPC_R1/stdafx.h @@ -34,6 +34,7 @@ #define R_R2 2 #define R_R3 3 #define R_R4 4 +#define R_R5 4 #define RENDER R_R1 #include "Common/_d3d_extensions.h" diff --git a/src/Layers/xrRenderPC_R2/r2_rendertarget.h b/src/Layers/xrRenderPC_R2/r2_rendertarget.h index 79420105091..b56cdffbc20 100644 --- a/src/Layers/xrRenderPC_R2/r2_rendertarget.h +++ b/src/Layers/xrRenderPC_R2/r2_rendertarget.h @@ -175,7 +175,7 @@ class CRenderTarget : public IRender_Target bool m_bHasActiveVolumetric; public: - CRenderTarget(); + CRenderTarget(bool reset = false); ~CRenderTarget() override; void build_textures(); diff --git a/src/Layers/xrRenderPC_R2/r2_rendertarget.h.bak b/src/Layers/xrRenderPC_R2/r2_rendertarget.h.bak new file mode 100644 index 00000000000..05583f836e4 --- /dev/null +++ b/src/Layers/xrRenderPC_R2/r2_rendertarget.h.bak @@ -0,0 +1,333 @@ +#pragma once + +#include "Layers/xrRender/ColorMapManager.h" + +class light; + +//#define DU_SPHERE_NUMVERTEX 92 +//#define DU_SPHERE_NUMFACES 180 +//#define DU_CONE_NUMVERTEX 18 +//#define DU_CONE_NUMFACES 32 +// no less than 2 +#define VOLUMETRIC_SLICES 100 + +class CRenderTarget : public IRender_Target +{ + u32 dwWidth[R__NUM_CONTEXTS]; + u32 dwHeight[R__NUM_CONTEXTS]; + u32 dwAccumulatorClearMark; + +public: + enum eStencilOptimizeMode + { + SO_Light = 0, // Default + SO_Combine, // Default + }; + + u32 dwLightMarkerID; + + IBlender* b_accum_spot{}; + +#ifdef DEBUG + struct dbg_line_t + { + Fvector P0, P1; + u32 color; + }; + xr_vector> dbg_spheres; + xr_vector dbg_lines; + xr_vector dbg_planes; +#endif + + // Base targets + xr_vector rt_Base; + ref_rt rt_Base_Depth; + + // MRT-path + ref_rt rt_Depth; // Z-buffer like - initial depth + ref_rt rt_MSAADepth; // z-buffer for MSAA deferred shading. If MSAA is disabled, points to rt_Base_Depth so we can reduce branching + ref_rt rt_Generic_0_r; // MRT generic 0, if MSAA is disabled, just an alias of rt_Generic_0 + ref_rt rt_Generic_1_r; // MRT generic 1, if MSAA is disabled, just an alias of rt_Generic_1 + ref_rt rt_Position; // 64bit, fat (x,y,z,?) (eye-space) + ref_rt rt_Normal; // 64bit, fat (x,y,z,hemi) (eye-space) + ref_rt rt_Color; // 64/32bit,fat (r,g,b,specular-gloss) (or decompressed MET-8-8-8-8) + + // + ref_rt rt_Accumulator; // 64bit (r,g,b,specular) + ref_rt rt_Accumulator_temp; // only for HW which doesn't feature fp16 blend + ref_rt rt_Generic_0; // 32bit (r,g,b,a) // post-process, intermidiate results, etc. + ref_rt rt_Generic_1; // 32bit (r,g,b,a) // post-process, intermidiate results, etc. + // Igor: for volumetric lights + ref_rt rt_Generic_2; // 32bit (r,g,b,a) // post-process, intermidiate results, etc. + ref_rt rt_Bloom_1; // 32bit, dim/4 (r,g,b,?) + ref_rt rt_Bloom_2; // 32bit, dim/4 (r,g,b,?) + ref_rt rt_LUM_64; // 64bit, 64x64, log-average in all components + ref_rt rt_LUM_8; // 64bit, 8x8, log-average in all components + + // Igor: for async screenshots + ref_rt rt_async_ss; // 32bit (r,g,b,a) is situated in the system memory + + ref_rt rt_LUM_pool[CHWCaps::MAX_GPUS * 2]; // 1xfp32,1x1, exp-result -> scaler + ref_texture t_LUM_src; // source + ref_texture t_LUM_dest; // destination & usage for current frame + + // smap + ref_rt rt_smap_surf; // 32bit, color + ref_rt rt_smap_depth; // 24(32) bit, depth + + // Textures + ref_texture t_material; + ref_texture t_noise[TEX_jitter_count]; + + // Anomaly + ref_rt rt_Generic_temp; + +private: + // OCCq + ref_shader s_occq; + + // Accum + ref_shader s_accum_mask; + ref_shader s_accum_direct; + ref_shader s_accum_direct_volumetric; + ref_shader s_accum_point; + ref_shader s_accum_spot; + ref_shader s_accum_reflected; + ref_shader s_accum_volume; + + ref_geom g_accum_point; + ref_geom g_accum_spot; + ref_geom g_accum_omnipart; + ref_geom g_accum_volumetric; + + VertexStagingBuffer g_accum_point_vb; + IndexStagingBuffer g_accum_point_ib; + + VertexStagingBuffer g_accum_omnip_vb; + IndexStagingBuffer g_accum_omnip_ib; + + VertexStagingBuffer g_accum_spot_vb; + IndexStagingBuffer g_accum_spot_ib; + + VertexStagingBuffer g_accum_volumetric_vb; + IndexStagingBuffer g_accum_volumetric_ib; + + // SSAO + ref_rt rt_ssao_temp; + ref_rt rt_half_depth; + ref_shader s_ssao; + + // Bloom + ref_geom g_bloom_build; + ref_geom g_bloom_filter; + ref_shader s_bloom_dbg_1; + ref_shader s_bloom_dbg_2; + ref_shader s_bloom; + ref_shader s_bloom_msaa; // if MSAA is disabled, just an alias of s_bloom + float f_bloom_factor; + + // Luminance + ref_shader s_luminance; + float f_luminance_adapt; + + // Combine + ref_geom g_combine; + ref_geom g_combine_VP; // xy=p,zw=tc + ref_geom g_combine_2UV; + ref_geom g_combine_cuboid; + ref_geom g_aa_blur; + ref_geom g_aa_AA; + ref_shader s_combine_dbg_0; + ref_shader s_combine_dbg_1; + ref_shader s_combine_dbg_Accumulator; + ref_shader s_combine; + ref_shader s_combine_volumetric; + +public: + ref_shader s_postprocess; + ref_shader s_postprocess_msaa; // if MSAA is disabled, just an alias of s_bloom + ref_geom g_postprocess; + ref_shader s_menu; + ref_geom g_menu; + +private: + float im_noise_time; + u32 im_noise_shift_w; + u32 im_noise_shift_h; + + float param_blur; + float param_gray; + float param_duality_h; + float param_duality_v; + float param_noise; + float param_noise_scale; + float param_noise_fps; + u32 param_color_base; + u32 param_color_gray; + Fvector param_color_add; + + // Color mapping + float param_color_map_influence; + float param_color_map_interpolate; + ColorMapManager color_map_manager; + + // Igor: used for volumetric lights + bool m_bHasActiveVolumetric; + +public: + CRenderTarget(bool reset); + ~CRenderTarget() override; + + void build_textures(); + + void accum_point_geom_create(); + void accum_point_geom_destroy(); + void accum_omnip_geom_create(); + void accum_omnip_geom_destroy(); + void accum_spot_geom_create(); + void accum_spot_geom_destroy(); + // Igor: used for volumetric lights + void accum_volumetric_geom_create(); + void accum_volumetric_geom_destroy(); + + ID3DRenderTargetView* get_base_rt() { return rt_Base[HW.CurrentBackBuffer]->pRT; } + ID3DDepthStencilView* get_base_zb() { return rt_Base_Depth->pRT; } + + void u_setrt(CBackend& cmd_list, const ref_rt& _1, const ref_rt& _2, const ref_rt& _3, IDirect3DSurface9* zb); + void u_setrt(CBackend& cmd_list, const ref_rt& _1, const ref_rt& _2, const ref_rt& _3, const ref_rt& _zb) + { + u_setrt(cmd_list, _1, _2, _3, _zb ? _zb->pRT : nullptr); + } + void u_setrt(CBackend& cmd_list, u32 W, u32 H, IDirect3DSurface9* _1, IDirect3DSurface9* _2, IDirect3DSurface9* _3, + IDirect3DSurface9* zb); + + void u_stencil_optimize(CBackend& cmd_list, BOOL common_stencil = TRUE); + void u_compute_texgen_screen(CBackend& cmd_list, Fmatrix& dest); + void u_compute_texgen_jitter(CBackend& cmd_list, Fmatrix& dest); + void u_calc_tc_noise(Fvector2& p0, Fvector2& p1); + void u_calc_tc_duality_ss(Fvector2& r0, Fvector2& r1, Fvector2& l0, Fvector2& l1); + bool u_need_PP(); + bool u_need_CM(); + bool u_DBT_enable(float zMin, float zMax); + void u_DBT_disable(); + + void phase_scene_prepare(); + void phase_scene_begin(); + void phase_scene_end(); + void phase_occq(); + void phase_ssao(); + void phase_downsamp(); + void phase_wallmarks(); + void phase_smap_direct(CBackend& cmd_list, light* L, u32 sub_phase); + void phase_smap_direct_tsh(CBackend& cmd_list, light* L, u32 sub_phase); + void phase_smap_spot_clear(CBackend& cmd_list); + void phase_smap_spot(CBackend& cmd_list, light* L); + void phase_smap_spot_tsh(CBackend& cmd_list, light* L); + void phase_accumulator(CBackend& cmd_list); + void phase_vol_accumulator(CBackend& cmd_list); + + // Generates min/max sm + void create_minmax_SM(CBackend& cmd_list) {} + bool need_to_render_sunshafts(); + bool use_minmax_sm_this_frame() { return false; } + + bool enable_scissor(light* L); // true if intersects near plane + void enable_dbt_bounds(light* L); + + void disable_aniso(); + + void draw_volume(CBackend& cmd_list, light* L); + void accum_direct(CBackend& cmd_list, u32 sub_phase); + void accum_direct_cascade(CBackend& cmd_list, u32 sub_phase, Fmatrix& xform, Fmatrix& xform_prev, float fBias); + void accum_direct_f(CBackend& cmd_list, u32 sub_phase); + void accum_direct_lum(CBackend& cmd_list); + void accum_direct_blend(CBackend& cmd_list); + void accum_direct_volumetric(CBackend& cmd_list, u32 sub_phase, const u32 Offset, const Fmatrix& mShadow); + void accum_point(CBackend& cmd_list, light* L); + void accum_spot(CBackend& cmd_list, light* L); + void accum_reflected(CBackend& cmd_list, light* L); + // Igor: for volumetric lights + void accum_volumetric(CBackend& cmd_list, light* L); + + void phase_bloom(); + void phase_luminance(); + void phase_combine(); + void phase_combine_volumetric(); + void phase_pp(); + + u32 get_width(CBackend& cmd_list) override { return dwWidth[cmd_list.context_id]; } + u32 get_height(CBackend& cmd_list) override { return dwHeight[cmd_list.context_id]; } + + void set_blur(float f) override { param_blur = f; } + void set_gray(float f) override { param_gray = f; } + void set_duality_h(float f) override { param_duality_h = _abs(f); } + void set_duality_v(float f) override { param_duality_v = _abs(f); } + void set_noise(float f) override { param_noise = f; } + void set_noise_scale(float f) override { param_noise_scale = f; } + void set_noise_fps(float f) override { param_noise_fps = _abs(f) + EPS_S; } + void set_color_base(u32 f) override { param_color_base = f; } + void set_color_gray(u32 f) override { param_color_gray = f; } + void set_color_add(const Fvector& f) override { param_color_add = f; } + void set_cm_imfluence(float f) override { param_color_map_influence = f; } + void set_cm_interpolate(float f) override { param_color_map_interpolate = f; } + void set_cm_textures(const shared_str& tex0, const shared_str& tex1) override + { + color_map_manager.SetTextures(tex0, tex1); + } + + // Need to reset stencil only when marker overflows. + // Don't clear when render for the first time + void reset_light_marker(CBackend& cmd_list, bool bResetStencil = false); + void increment_light_marker(CBackend& cmd_list); + + void DoAsyncScreenshot(); + +#ifdef DEBUG + void dbg_addline(const Fvector& P0, const Fvector& P1, u32 c) + { + dbg_lines.emplace_back(dbg_line_t{ P0, P1, c }); + } + + void dbg_addbox(const Fbox& box, const u32& color) + { + Fvector c, r; + box.getcenter(c); + box.getradius(r); + dbg_addbox(c, r.x, r.y, r.z, color); + } + + void dbg_addbox(const Fvector& c, float rx, float ry, float rz, u32 color) + { + Fvector p1, p2, p3, p4, p5, p6, p7, p8; + + p1.set(c.x + rx, c.y + ry, c.z + rz); + p2.set(c.x + rx, c.y - ry, c.z + rz); + p3.set(c.x - rx, c.y - ry, c.z + rz); + p4.set(c.x - rx, c.y + ry, c.z + rz); + + p5.set(c.x + rx, c.y + ry, c.z - rz); + p6.set(c.x + rx, c.y - ry, c.z - rz); + p7.set(c.x - rx, c.y - ry, c.z - rz); + p8.set(c.x - rx, c.y + ry, c.z - rz); + + dbg_addline(p1, p2, color); + dbg_addline(p2, p3, color); + dbg_addline(p3, p4, color); + dbg_addline(p4, p1, color); + + dbg_addline(p5, p6, color); + dbg_addline(p6, p7, color); + dbg_addline(p7, p8, color); + dbg_addline(p8, p5, color); + + dbg_addline(p1, p5, color); + dbg_addline(p2, p6, color); + dbg_addline(p3, p7, color); + dbg_addline(p4, p8, color); + } + void dbg_addplane(Fplane& P0, u32 /*c*/) { dbg_planes.emplace_back(P0); } +#else + void dbg_addline(Fvector& /*P0*/, Fvector& /*P1*/, u32 /*c*/) {} + void dbg_addplane(Fplane& /*P0*/, u32 /*c*/) {} +#endif +}; diff --git a/src/Layers/xrRenderPC_R2/stdafx.h b/src/Layers/xrRenderPC_R2/stdafx.h index a99ad8281ac..545e6f078ca 100644 --- a/src/Layers/xrRenderPC_R2/stdafx.h +++ b/src/Layers/xrRenderPC_R2/stdafx.h @@ -32,6 +32,7 @@ #define R_R2 2 #define R_R3 3 #define R_R4 4 +#define R_R5 5 #define RENDER R_R2 #include "Common/_d3d_extensions.h" diff --git a/src/Layers/xrRenderPC_R4/r4_rendertarget.h b/src/Layers/xrRenderPC_R4/r4_rendertarget.h index a0cde0c26fc..b76fcb61aa9 100644 --- a/src/Layers/xrRenderPC_R4/r4_rendertarget.h +++ b/src/Layers/xrRenderPC_R4/r4_rendertarget.h @@ -224,7 +224,7 @@ class CRenderTarget : public IRender_Target bool m_bHasActiveVolumetric; public: - CRenderTarget(); + CRenderTarget(bool reset = false); ~CRenderTarget() override; void build_textures(); @@ -239,7 +239,7 @@ class CRenderTarget : public IRender_Target void accum_volumetric_geom_create(); void accum_volumetric_geom_destroy(); - ID3DRenderTargetView* get_base_rt() { return rt_Base[HW.CurrentBackBuffer]->pRT; } + ID3DRenderTargetView* get_base_rt() { return rt_Base[HW.GetCurrentBackBufferIndex()]->pRT; } ID3DDepthStencilView* get_base_zb() { return rt_Base_Depth->pZRT[CHW::IMM_CTX_ID]; } void u_setrt(CBackend& cmd_list, const ref_rt& _1, const ref_rt& _2, const ref_rt& _3, ID3DDepthStencilView* zb); diff --git a/src/Layers/xrRenderPC_R4/r4_rendertarget.h.bak b/src/Layers/xrRenderPC_R4/r4_rendertarget.h.bak new file mode 100644 index 00000000000..a0cde0c26fc --- /dev/null +++ b/src/Layers/xrRenderPC_R4/r4_rendertarget.h.bak @@ -0,0 +1,410 @@ +#pragma once + +#include "Layers/xrRender/ColorMapManager.h" + +class light; + +//#define DU_SPHERE_NUMVERTEX 92 +//#define DU_SPHERE_NUMFACES 180 +//#define DU_CONE_NUMVERTEX 18 +//#define DU_CONE_NUMFACES 32 +// no less than 2 +#define VOLUMETRIC_SLICES 100 + +class CRenderTarget : public IRender_Target +{ + u32 dwWidth[R__NUM_CONTEXTS]; + u32 dwHeight[R__NUM_CONTEXTS]; + u32 dwAccumulatorClearMark; + +public: + enum eStencilOptimizeMode + { + SO_Light = 0, // Default + SO_Combine, // Default + }; + + u32 dwLightMarkerID; + + IBlender* b_accum_spot{}; + IBlender* b_accum_spot_msaa[8]{}; + IBlender* b_accum_volumetric_msaa[8]{}; + +#ifdef DEBUG + struct dbg_line_t + { + Fvector P0, P1; + u32 color; + }; + xr_vector> dbg_spheres; + xr_vector dbg_lines; + xr_vector dbg_planes; +#endif + + // Base targets + xr_vector rt_Base; + ref_rt rt_Base_Depth; + + // MRT-path + ref_rt rt_Depth; // Z-buffer like - initial depth + ref_rt rt_MSAADepth; // z-buffer for MSAA deferred shading. If MSAA is disabled, points to rt_Base_Depth so we can reduce branching + ref_rt rt_Generic_0_r; // MRT generic 0, if MSAA is disabled, just an alias of rt_Generic_0 + ref_rt rt_Generic_1_r; // MRT generic 1, if MSAA is disabled, just an alias of rt_Generic_1 + ref_rt rt_Generic; + ref_rt rt_Position; // 64bit, fat (x,y,z,?) (eye-space) + ref_rt rt_Normal; // 64bit, fat (x,y,z,hemi) (eye-space) + ref_rt rt_Color; // 64/32bit,fat (r,g,b,specular-gloss) (or decompressed MET-8-8-8-8) + + // + ref_rt rt_Accumulator; // 64bit (r,g,b,specular) + ref_rt rt_Accumulator_temp; // only for HW which doesn't feature fp16 blend + ref_rt rt_Generic_0; // 32bit (r,g,b,a) // post-process, intermidiate results, etc. + ref_rt rt_Generic_1; // 32bit (r,g,b,a) // post-process, intermidiate results, etc. + // Igor: for volumetric lights + ref_rt rt_Generic_2; // 32bit (r,g,b,a) // post-process, intermidiate results, etc. + ref_rt rt_Bloom_1; // 32bit, dim/4 (r,g,b,?) + ref_rt rt_Bloom_2; // 32bit, dim/4 (r,g,b,?) + ref_rt rt_LUM_64; // 64bit, 64x64, log-average in all components + ref_rt rt_LUM_8; // 64bit, 8x8, log-average in all components + + ref_rt rt_LUM_pool[CHWCaps::MAX_GPUS * 2]; // 1xfp32,1x1, exp-result -> scaler + ref_texture t_LUM_src; // source + ref_texture t_LUM_dest; // destination & usage for current frame + + // smap + ref_rt rt_smap_surf; // 32bit, color + ref_rt rt_smap_depth; // 24(32) bit, depth + ref_rt rt_smap_rain; + ref_rt rt_smap_depth_minmax; // is used for min/max sm + + // Igor: for async screenshots + ID3DTexture2D* t_ss_async; // 32bit (r,g,b,a) is situated in the system memory + + // Textures + ref_texture t_material; + ref_texture t_noise[TEX_jitter_count]; + ref_texture t_noise_mipped; + + // Anomaly + //Rendertargets + ref_rt rt_Generic_temp; + + ref_rt rt_dof; + + ref_rt rt_blur_h_2; + ref_rt rt_blur_2; + + ref_rt rt_blur_h_4; + ref_rt rt_blur_4; + + ref_rt rt_blur_h_8; + ref_rt rt_blur_8; + +private: + // OCCq + ref_shader s_occq; + + // Accum + ref_shader s_accum_mask; + ref_shader s_accum_mask_msaa[8]; + ref_shader s_accum_direct; + ref_shader s_accum_direct_msaa[8]; + ref_shader s_accum_direct_volumetric; + ref_shader s_accum_direct_volumetric_msaa[8]; + ref_shader s_accum_direct_volumetric_minmax; + ref_shader s_accum_point; + ref_shader s_accum_point_msaa[8]; + ref_shader s_accum_spot; + ref_shader s_accum_spot_msaa[8]; + ref_shader s_accum_reflected; + ref_shader s_accum_reflected_msaa[8]; + ref_shader s_accum_volume; + ref_shader s_accum_volume_msaa[8]; + + //Anomaly + ref_shader s_blur; + ref_shader s_dof; + ref_shader s_gasmask_drops; + ref_shader s_gasmask_dudv; + ref_shader s_nightvision; + + // generate min/max + ref_shader s_create_minmax_sm; + + // DX11 Rain + ref_shader s_rain; + ref_shader s_rain_msaa[8]; // up to 8 shaders for DX10.0 support + + // Mark MSAA-edge pixels + ref_shader s_mark_msaa_edges; + + ref_geom g_accum_point; + ref_geom g_accum_spot; + ref_geom g_accum_omnipart; + ref_geom g_accum_volumetric; + + VertexStagingBuffer g_accum_point_vb; + IndexStagingBuffer g_accum_point_ib; + + VertexStagingBuffer g_accum_omnip_vb; + IndexStagingBuffer g_accum_omnip_ib; + + VertexStagingBuffer g_accum_spot_vb; + IndexStagingBuffer g_accum_spot_ib; + + VertexStagingBuffer g_accum_volumetric_vb; + IndexStagingBuffer g_accum_volumetric_ib; + + // SSAO + ref_rt rt_ssao_temp; + ref_rt rt_half_depth; + ref_shader s_ssao; + ref_shader s_ssao_msaa[8]; + ref_shader s_hdao_cs; // HDAO compute shader + + // Bloom + ref_geom g_bloom_build; + ref_geom g_bloom_filter; + ref_shader s_bloom_dbg_1; + ref_shader s_bloom_dbg_2; + ref_shader s_bloom; + ref_shader s_bloom_msaa; // if MSAA is disabled, just an alias of s_bloom + float f_bloom_factor; + + // Luminance + ref_shader s_luminance; + float f_luminance_adapt; + + // Combine + ref_geom g_combine; + ref_geom g_combine_VP; // xy=p,zw=tc + ref_geom g_combine_2UV; + ref_geom g_combine_cuboid; + ref_geom g_aa_blur; + ref_geom g_aa_AA; + ref_shader s_combine_dbg_0; + ref_shader s_combine_dbg_1; + ref_shader s_combine_dbg_Accumulator; + ref_shader s_combine; + ref_shader s_combine_msaa[8]; + ref_shader s_combine_volumetric; + +public: + ref_shader s_postprocess; + ref_shader s_postprocess_msaa; // if MSAA is disabled, just an alias of s_bloom + ref_geom g_postprocess; + ref_shader s_menu; + ref_geom g_menu; +#if 0 // kept for historical reasons + ref_shader s_flip; + ref_geom g_flip; +#endif +private: + float im_noise_time; + u32 im_noise_shift_w; + u32 im_noise_shift_h; + + float param_blur; + float param_gray; + float param_duality_h; + float param_duality_v; + float param_noise; + float param_noise_scale; + float param_noise_fps; + u32 param_color_base; + u32 param_color_gray; + Fvector param_color_add; + + // Color mapping + float param_color_map_influence; + float param_color_map_interpolate; + ColorMapManager color_map_manager; + + // Igor: used for volumetric lights + bool m_bHasActiveVolumetric; + +public: + CRenderTarget(); + ~CRenderTarget() override; + + void build_textures(); + + void accum_point_geom_create(); + void accum_point_geom_destroy(); + void accum_omnip_geom_create(); + void accum_omnip_geom_destroy(); + void accum_spot_geom_create(); + void accum_spot_geom_destroy(); + // Igor: used for volumetric lights + void accum_volumetric_geom_create(); + void accum_volumetric_geom_destroy(); + + ID3DRenderTargetView* get_base_rt() { return rt_Base[HW.CurrentBackBuffer]->pRT; } + ID3DDepthStencilView* get_base_zb() { return rt_Base_Depth->pZRT[CHW::IMM_CTX_ID]; } + + void u_setrt(CBackend& cmd_list, const ref_rt& _1, const ref_rt& _2, const ref_rt& _3, ID3DDepthStencilView* zb); + void u_setrt(CBackend& cmd_list, const ref_rt& _1, const ref_rt& _2, const ref_rt& _3, const ref_rt& _zb) + { + u_setrt(cmd_list, _1, _2, _3, _zb ? _zb->pZRT[cmd_list.context_id] : nullptr); + } + void u_setrt(CBackend& cmd_list, const ref_rt& _1, const ref_rt& _2, ID3DDepthStencilView* zb); + void u_setrt(CBackend& cmd_list, const ref_rt& _1, const ref_rt& _2, const ref_rt& _zb) + { + u_setrt(cmd_list, _1, _2, _zb ? _zb->pZRT[cmd_list.context_id] : nullptr); + } + void u_setrt(CBackend& cmd_list, u32 W, u32 H, ID3DRenderTargetView* _1, ID3DRenderTargetView* _2, ID3DRenderTargetView* _3, + ID3DDepthStencilView* zb); + void u_setrt(CBackend& cmd_list, u32 W, u32 H, ID3DRenderTargetView* _1, ID3DRenderTargetView* _2, ID3DRenderTargetView* _3, + const ref_rt& _zb) + { + u_setrt(cmd_list, W, H, _1, _2, _3, _zb ? _zb->pZRT[cmd_list.context_id] : nullptr); + } + + void u_stencil_optimize(CBackend& cmd_list, eStencilOptimizeMode eSOM = SO_Light); + void u_compute_texgen_screen(CBackend& cmd_list, Fmatrix& dest); + void u_compute_texgen_jitter(CBackend& cmd_list, Fmatrix& dest); + void u_calc_tc_noise(Fvector2& p0, Fvector2& p1); + void u_calc_tc_duality_ss(Fvector2& r0, Fvector2& r1, Fvector2& l0, Fvector2& l1); + bool u_need_PP(); + bool u_need_CM(); + bool u_DBT_enable(float zMin, float zMax); + void u_DBT_disable(); + + void phase_scene_prepare(); + void phase_scene_begin(); + void phase_scene_end(); + void phase_occq(); + void phase_ssao(); + void phase_hdao(); + void phase_downsamp(); + void phase_wallmarks(); + + void phase_smap_direct(CBackend& cmd_list, light *L, u32 sub_phase); + void phase_smap_direct_tsh(CBackend& cmd_list, light *L, u32 sub_phase); + void phase_smap_spot_clear(CBackend& cmd_list); + void phase_smap_spot(CBackend& cmd_list, light* L); + void phase_smap_spot_tsh(CBackend& cmd_list, light* L); + void phase_accumulator(CBackend& cmd_list); + void phase_vol_accumulator(CBackend& cmd_list); + + //Anomaly renderphases + void phase_blur(); + void phase_dof(); + void phase_gasmask_drops(); + void phase_gasmask_dudv(); + void phase_nightvision(); + + // Generates min/max sm + void create_minmax_SM(CBackend& cmd_list); + + void phase_rain(CBackend& cmd_list); + void draw_rain(CBackend& cmd_list, light& RainSetup); + + void mark_msaa_edges(); + + bool need_to_render_sunshafts(); + bool use_minmax_sm_this_frame(); + + bool enable_scissor(light* L); // true if intersects near plane + void enable_dbt_bounds(light* L); + + void disable_aniso(); + + void draw_volume(CBackend& cmd_list, light* L); + void accum_direct(CBackend& cmd_list, u32 sub_phase); + void accum_direct_cascade(CBackend& cmd_list, u32 sub_phase, Fmatrix& xform, Fmatrix& xform_prev, float fBias); + void accum_direct_f(CBackend& cmd_list, u32 sub_phase); + void accum_direct_lum(CBackend& cmd_list); + void accum_direct_blend(CBackend& cmd_list); + void accum_direct_volumetric(CBackend& cmd_list, u32 sub_phase, const u32 Offset, const Fmatrix& mShadow); + void accum_point(CBackend& cmd_list, light* L); + void accum_spot(CBackend& cmd_list, light* L); + void accum_reflected(CBackend& cmd_list, light* L); + // Igor: for volumetric lights + void accum_volumetric(CBackend& cmd_list, light* L); + + void phase_bloom(); + void phase_luminance(); + void phase_combine(); + void phase_combine_volumetric(); + void phase_pp(); +#if 0 // kept for historical reasons + void phase_flip(); +#endif + + u32 get_width(CBackend& cmd_list) override { return dwWidth[cmd_list.context_id]; } + u32 get_height(CBackend& cmd_list) override { return dwHeight[cmd_list.context_id]; } + + void set_blur(float f) override { param_blur = f; } + void set_gray(float f) override { param_gray = f; } + void set_duality_h(float f) override { param_duality_h = _abs(f); } + void set_duality_v(float f) override { param_duality_v = _abs(f); } + void set_noise(float f) override { param_noise = f; } + void set_noise_scale(float f) override { param_noise_scale = f; } + void set_noise_fps(float f) override { param_noise_fps = _abs(f) + EPS_S; } + void set_color_base(u32 f) override { param_color_base = f; } + void set_color_gray(u32 f) override { param_color_gray = f; } + void set_color_add(const Fvector& f) override { param_color_add = f; } + void set_cm_imfluence(float f) override { param_color_map_influence = f; } + void set_cm_interpolate(float f) override { param_color_map_interpolate = f; } + void set_cm_textures(const shared_str& tex0, const shared_str& tex1) override + { + color_map_manager.SetTextures(tex0, tex1); + } + + // Need to reset stencil only when marker overflows. + // Don't clear when render for the first time + void reset_light_marker(CBackend& cmd_list, bool bResetStencil = false); + void increment_light_marker(CBackend& cmd_list); + + void DoAsyncScreenshot(); + +#ifdef DEBUG + void dbg_addline(const Fvector& P0, const Fvector& P1, u32 c) + { + dbg_lines.emplace_back(dbg_line_t{ P0, P1, c }); + } + + void dbg_addbox(const Fbox& box, const u32& color) + { + Fvector c, r; + box.getcenter(c); + box.getradius(r); + dbg_addbox(c, r.x, r.y, r.z, color); + } + + void dbg_addbox(const Fvector& c, float rx, float ry, float rz, u32 color) + { + Fvector p1, p2, p3, p4, p5, p6, p7, p8; + + p1.set(c.x + rx, c.y + ry, c.z + rz); + p2.set(c.x + rx, c.y - ry, c.z + rz); + p3.set(c.x - rx, c.y - ry, c.z + rz); + p4.set(c.x - rx, c.y + ry, c.z + rz); + + p5.set(c.x + rx, c.y + ry, c.z - rz); + p6.set(c.x + rx, c.y - ry, c.z - rz); + p7.set(c.x - rx, c.y - ry, c.z - rz); + p8.set(c.x - rx, c.y + ry, c.z - rz); + + dbg_addline(p1, p2, color); + dbg_addline(p2, p3, color); + dbg_addline(p3, p4, color); + dbg_addline(p4, p1, color); + + dbg_addline(p5, p6, color); + dbg_addline(p6, p7, color); + dbg_addline(p7, p8, color); + dbg_addline(p8, p5, color); + + dbg_addline(p1, p5, color); + dbg_addline(p2, p6, color); + dbg_addline(p3, p7, color); + dbg_addline(p4, p8, color); + } + void dbg_addplane(Fplane& P0, u32 /*c*/) { dbg_planes.emplace_back(P0); } +#else + void dbg_addline(Fvector& /*P0*/, Fvector& /*P1*/, u32 /*c*/) {} + void dbg_addplane(Fplane& /*P0*/, u32 /*c*/) {} +#endif +}; diff --git a/src/Layers/xrRenderPC_R4/stdafx.h b/src/Layers/xrRenderPC_R4/stdafx.h index 1517620b19e..045ad2e7418 100644 --- a/src/Layers/xrRenderPC_R4/stdafx.h +++ b/src/Layers/xrRenderPC_R4/stdafx.h @@ -50,6 +50,7 @@ #define R_R2 2 #define R_R3 3 #define R_R4 4 +#define R_R5 5 #define RENDER R_R4 #include "Common/_d3d_extensions.h" diff --git a/src/Layers/xrRenderPC_R5/CMakeLists.txt b/src/Layers/xrRenderPC_R5/CMakeLists.txt new file mode 100644 index 00000000000..b1a1c5489b8 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/CMakeLists.txt @@ -0,0 +1,57 @@ +add_library(xrRenderPC_R5 SHARED) + +target_sources(xrRenderPC_R5 PRIVATE + ComputeShader.cpp + ComputeShader.h + CSCompiler.cpp + CSCompiler.h + packages.config + r2_test_hw.cpp + r5_rendertarget.h + r5_rendertarget_accum_direct.cpp + r5_rendertarget_build_textures.cpp + r5_rendertarget_phase_combine.cpp + r5_rendertarget_phase_hdao.cpp + r5_rendertarget_u_set_rt.cpp + r5_shaders.cpp + R_Backend_LOD.cpp + R_Backend_LOD.h + stdafx.cpp + stdafx.h + xrRender_r5.cpp +) + +target_include_directories(xrRenderPC_R5 + PRIVATE + "${CMAKE_SOURCE_DIR}/src" + "${CMAKE_SOURCE_DIR}/sdk/include" +) + +target_link_libraries(xrRenderPC_R5 + PRIVATE + xrCore + xrCDB + xrEngine + xrParticles + xrScriptEngine + xrAPI + xrMiscMath +) + +target_compile_definitions(xrRenderPC_R5 + PRIVATE + XRRENDER_r5_EXPORTS +) + +set_target_properties(xrRenderPC_R5 PROPERTIES + PREFIX "" +) + +target_precompile_headers(xrRenderPC_R5 + PRIVATE + stdafx.h +) + +install(TARGETS xrRenderPC_R5 LIBRARY + DESTINATION "${CMAKE_INSTALL_LIBDIR}" +) diff --git a/src/Layers/xrRenderPC_R5/CMakeLists.txt.bak b/src/Layers/xrRenderPC_R5/CMakeLists.txt.bak new file mode 100644 index 00000000000..efa6bfc49a3 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/CMakeLists.txt.bak @@ -0,0 +1,57 @@ +add_library(xrRenderPC_R5 SHARED) + +target_sources(xrRenderPC_R5 PRIVATE + ComputeShader.cpp + ComputeShader.h + CSCompiler.cpp + CSCompiler.h + packages.config + r2_test_hw.cpp + r4_rendertarget.h + r4_rendertarget_accum_direct.cpp + r4_rendertarget_build_textures.cpp + r4_rendertarget_phase_combine.cpp + r4_rendertarget_phase_hdao.cpp + r4_rendertarget_u_set_rt.cpp + r4_shaders.cpp + R_Backend_LOD.cpp + R_Backend_LOD.h + stdafx.cpp + stdafx.h + xrRender_R4.cpp +) + +target_include_directories(xrRenderPC_R5 + PRIVATE + "${CMAKE_SOURCE_DIR}/src" + "${CMAKE_SOURCE_DIR}/sdk/include" +) + +target_link_libraries(xrRenderPC_R5 + PRIVATE + xrCore + xrCDB + xrEngine + xrParticles + xrScriptEngine + xrAPI + xrMiscMath +) + +target_compile_definitions(xrRenderPC_R5 + PRIVATE + XRRENDER_R4_EXPORTS +) + +set_target_properties(xrRenderPC_R5 PROPERTIES + PREFIX "" +) + +target_precompile_headers(xrRenderPC_R5 + PRIVATE + stdafx.h +) + +install(TARGETS xrRenderPC_R5 LIBRARY + DESTINATION "${CMAKE_INSTALL_LIBDIR}" +) diff --git a/src/Layers/xrRenderPC_R5/CSCompiler.cpp b/src/Layers/xrRenderPC_R5/CSCompiler.cpp new file mode 100644 index 00000000000..4e34504b6fa --- /dev/null +++ b/src/Layers/xrRenderPC_R5/CSCompiler.cpp @@ -0,0 +1,207 @@ +//////////////////////////////////////////////////////////////////////////// +// Created : 22.05.2009 +// Author : Mykhailo Parfeniuk +// Copyright (C) GSC Game World - 2009 +//////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "CSCompiler.h" +#include "ComputeShader.h" + +CSCompiler::CSCompiler(ComputeShader& target) : m_Target(target), m_cs(0) {} +CSCompiler& CSCompiler::begin(const char* name) +{ + compile(name); + return *this; +} + +CSCompiler& CSCompiler::defSampler(LPCSTR ResourceName) +{ + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + + // Use D3DTADDRESS_CLAMP, D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_POINT + if (0 == xr_strcmp(ResourceName, "smp_nofilter")) + { + // i_Address( stage, D3DTADDRESS_CLAMP); + // i_Filter(stage, D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_POINT); + desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + return defSampler(ResourceName, desc); + } + + // Use D3DTADDRESS_CLAMP, D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_LINEAR + if (0 == xr_strcmp(ResourceName, "smp_rtlinear")) + { + // i_Address( stage, D3DTADDRESS_CLAMP); + // i_Filter(stage, D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_LINEAR); + desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + desc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + return defSampler(ResourceName, desc); + } + + // Use D3DTADDRESS_WRAP, D3DTEXF_LINEAR, D3DTEXF_LINEAR, D3DTEXF_LINEAR + if (0 == xr_strcmp(ResourceName, "smp_linear")) + { + // i_Address( stage, D3DTADDRESS_WRAP); + // i_Filter(stage, D3DTEXF_LINEAR, D3DTEXF_LINEAR, D3DTEXF_LINEAR); + desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + return defSampler(ResourceName, desc); + } + + // Use D3DTADDRESS_WRAP, D3DTEXF_ANISOTROPIC, D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC + if (0 == xr_strcmp(ResourceName, "smp_base")) + { + // i_Address( stage, D3DTADDRESS_WRAP); + // i_dx11FilterAnizo( stage, TRUE); + desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.Filter = D3D11_FILTER_ANISOTROPIC; + desc.MaxAnisotropy = 8; + return defSampler(ResourceName, desc); + } + + // Use D3DTADDRESS_CLAMP, D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_LINEAR + if (0 == xr_strcmp(ResourceName, "smp_material")) + { + // i_Address( stage, D3DTADDRESS_CLAMP); + // i_Filter(stage, D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_LINEAR); + // RS.SetSAMP(stage,D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP); + desc.AddressU = desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + return defSampler(ResourceName, desc); + } + + if (0 == xr_strcmp(ResourceName, "smp_smap")) + { + // i_Address( stage, D3DTADDRESS_CLAMP); + // i_Filter(stage, D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_LINEAR); + // RS.SetSAMP(stage, XRDX11SAMP_COMPARISONFILTER, TRUE); + // RS.SetSAMP(stage, XRDX11SAMP_COMPARISONFUNC, D3D_COMPARISON_LESS_EQUAL); + desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + desc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT; + desc.ComparisonFunc = D3D_COMPARISON_LESS_EQUAL; + return defSampler(ResourceName, desc); + } + + if (0 == xr_strcmp(ResourceName, "smp_jitter")) + { + // i_Address( stage, D3DTADDRESS_WRAP); + // i_Filter(stage, D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_POINT); + desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + return defSampler(ResourceName, desc); + } + + VERIFY(0); + + return *this; +} + +CSCompiler& CSCompiler::defSampler(LPCSTR ResourceName, const D3D_SAMPLER_DESC& def) +{ + VERIFY(ResourceName); + + ref_constant C = m_constants.get(ResourceName); + if (!C) + return *this; + + R_ASSERT(C->type == RC_sampler); + u32 stage = C->samp.index; + + if (stage >= m_Samplers.size()) + m_Samplers.resize(stage + 1); + + R_CHK(HW.pDevice->CreateSamplerState(&def, &m_Samplers[stage])); + + return *this; +} + +void fix_texture_name(pstr); + +CSCompiler& CSCompiler::defOutput(LPCSTR ResourceName, const ref_rt& rt) +{ + VERIFY(ResourceName); + if (!rt) + return *this; + + ref_constant C = m_constants.get(ResourceName); + if (!C) + return *this; + + R_ASSERT(C->type == RC_dx11UAV); + u32 stage = C->samp.index; + + if (stage >= m_Textures.size()) + m_Textures.resize(stage + 1); + + m_Outputs[stage] = rt->pUAView; //!!!dangerous view can be deleted + + return *this; +} + +CSCompiler& CSCompiler::defTexture(LPCSTR ResourceName, ref_texture texture) +{ + VERIFY(ResourceName); + if (!texture) + return *this; + + // Find index + ref_constant C = m_constants.get(ResourceName); + if (!C) + return *this; + + R_ASSERT(C->type == RC_dx11texture); + u32 stage = C->samp.index; + + if (stage >= m_Textures.size()) + m_Textures.resize(stage + 1); + + m_Textures[stage] = texture->get_SRView(); //!!!dangerous view can be deleted + + return *this; +} + +void CSCompiler::end() +{ + for (size_t i = 0; i < m_Textures.size(); ++i) + m_Textures[i]->AddRef(); + + for (size_t i = 0; i < m_Outputs.size(); ++i) + m_Outputs[i]->AddRef(); + + // Samplers create by us, thou they should not be AddRef'ed + + m_Target.Construct( + m_cs, RImplementation.Resources->_CreateConstantTable(m_constants), m_Samplers, m_Textures, m_Outputs); +} + +void CSCompiler::compile(const char* name) +{ + if (0 == xr_stricmp(name, "null")) + { + m_cs = 0; + return; + } + + string_path cname; + strconcat(cname, RImplementation.getShaderPath(), name, ".cs"); + FS.update_path(cname, "$game_shaders$", cname); + + IReader* file = FS.r_open(cname); + R_ASSERT2(file, cname); + + // Select target + LPCSTR c_target = "cs_5_0"; + LPCSTR c_entry = "main"; + + HRESULT const _hr = RImplementation.shader_compile(name, file, c_entry, + c_target, D3D10_SHADER_PACK_MATRIX_ROW_MAJOR, (void*&)m_cs); + + FS.r_close(file); + + VERIFY(SUCCEEDED(_hr)); + + CHECK_OR_EXIT(!FAILED(_hr), "Your video card doesn't meet game requirements.\n\nTry to lower game settings."); +} diff --git a/src/Layers/xrRenderPC_R5/CSCompiler.h b/src/Layers/xrRenderPC_R5/CSCompiler.h new file mode 100644 index 00000000000..c389e62879c --- /dev/null +++ b/src/Layers/xrRenderPC_R5/CSCompiler.h @@ -0,0 +1,39 @@ +//////////////////////////////////////////////////////////////////////////// +// Created : 22.05.2009 +// Author : Mykhailo Parfeniuk +// Copyright (C) GSC Game World - 2009 +//////////////////////////////////////////////////////////////////////////// + +#ifndef CSCOMPILER_H_INCLUDED +#define CSCOMPILER_H_INCLUDED + +class ComputeShader; + +class CSCompiler +{ +public: + CSCompiler(ComputeShader& target); + + CSCompiler& begin(const char* name); + CSCompiler& defSampler(LPCSTR ResourceName); + CSCompiler& defSampler(LPCSTR ResourceName, const D3D_SAMPLER_DESC& def); + CSCompiler& defOutput(LPCSTR ResourceName, const ref_rt& rt); + CSCompiler& defTexture(LPCSTR ResourceName, ref_texture texture); + void end(); + +private: + // suppress warning + CSCompiler& operator=(const CSCompiler& other); + + void compile(const char* name); + +private: + ComputeShader& m_Target; + ID3D11ComputeShader* m_cs; + R_constant_table m_constants; + xr_vector m_Samplers; + xr_vector m_Textures; + xr_vector m_Outputs; +}; // class CSCompiler + +#endif // #ifndef CSCOMPILER_H_INCLUDED diff --git a/src/Layers/xrRenderPC_R5/ComputeShader.cpp b/src/Layers/xrRenderPC_R5/ComputeShader.cpp new file mode 100644 index 00000000000..702cbffc499 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/ComputeShader.cpp @@ -0,0 +1,90 @@ +//////////////////////////////////////////////////////////////////////////// +// Created : 21.05.2009 +// Author : Mykhailo Parfeniuk +// Copyright (C) GSC Game World - 2009 +//////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ComputeShader.h" + +void ComputeShader::Construct(ID3D11ComputeShader* cs, const ref_ctable& ctable, xr_vector& Samplers, + xr_vector& Textures, xr_vector& Outputs) +{ + m_cs = cs; + m_ctable = ctable; + m_Textures.swap(Textures); + m_Outputs.swap(Outputs); + m_Samplers.swap(Samplers); +} + +ComputeShader::~ComputeShader() +{ + for (size_t i = 0; i < m_Textures.size(); ++i) + m_Textures[i]->Release(); + + for (size_t i = 0; i < m_Outputs.size(); ++i) + m_Outputs[i]->Release(); + + for (size_t i = 0; i < m_Samplers.size(); ++i) + m_Samplers[i]->Release(); +} + +u32 GetCB(const ref_constant& C) { return (C->destination & RC_dest_pixel_cb_index_mask) >> RC_dest_pixel_cb_index_shift; } +ComputeShader& ComputeShader::set_c(CBackend& cmd_list, shared_str name, const Fvector4& value) +{ + ref_constant c = m_ctable->get(name); + (m_ctable->m_CBTable[cmd_list.context_id])[GetCB(c)].second->set(&*c, c->ps, value); + return *this; +} + +ComputeShader& ComputeShader::set_c(CBackend& cmd_list, shared_str name, float x, float y, float z, float w) +{ + Fvector4 vec; + vec.set(x, y, z, w); + return set_c(cmd_list, name, vec); +} + +void ComputeShader::Dispatch(CBackend& cmd_list, u32 dimx, u32 dimy, u32 dimz) +{ + const auto context_id = cmd_list.context_id; + + u32 count = m_ctable->m_CBTable[cmd_list.context_id].size(); + + for (u32 i = 0; i < count; ++i) + { + (m_ctable->m_CBTable[cmd_list.context_id])[i].second->Flush(context_id); + } + + ID3DBuffer* tempBuffer[CBackend::MaxCBuffers]; + + for (u32 i = 0; i < count; ++i) + { + tempBuffer[i] = (m_ctable->m_CBTable[cmd_list.context_id])[i].second->GetBuffer(); + } + + // process constant-loaders + R_constant_table::c_table::iterator it = m_ctable->table.begin(); + R_constant_table::c_table::iterator end = m_ctable->table.end(); + for (; it != end; ++it) + { + R_constant* Cs = &**it; + if (Cs->handler) + Cs->handler->setup(cmd_list, Cs); + } + + HW.get_context(context_id)->CSSetConstantBuffers(0, count, tempBuffer); + + if (!m_Textures.empty()) + HW.get_context(context_id)->CSSetShaderResources(0, m_Textures.size(), &m_Textures[0]); + + if (!m_Samplers.empty()) + HW.get_context(context_id)->CSSetSamplers(0, m_Samplers.size(), &m_Samplers[0]); + + if (!m_Outputs.empty()) + { + u32 num = 0; + HW.get_context(context_id)->CSSetUnorderedAccessViews(0, m_Outputs.size(), &m_Outputs[0], &num); + } + + HW.get_context(context_id)->Dispatch(dimx, dimy, dimz); +} diff --git a/src/Layers/xrRenderPC_R5/ComputeShader.h b/src/Layers/xrRenderPC_R5/ComputeShader.h new file mode 100644 index 00000000000..7b7d4e97a9a --- /dev/null +++ b/src/Layers/xrRenderPC_R5/ComputeShader.h @@ -0,0 +1,34 @@ +//////////////////////////////////////////////////////////////////////////// +// Created : 21.05.2009 +// Author : Mykhailo Parfeniuk +// Copyright (C) GSC Game World - 2009 +//////////////////////////////////////////////////////////////////////////// + +#ifndef COMPUTESHADER_H_INCLUDED +#define COMPUTESHADER_H_INCLUDED + +class ComputeShader +{ + friend class CSCompiler; + +public: + ~ComputeShader(); + + ComputeShader& set_c(CBackend& cmd_list, shared_str name, const Fvector4& value); + ComputeShader& set_c(CBackend& cmd_list, shared_str name, float x, float y, float z, float w); + + void Dispatch(CBackend& cmd_list, u32 dimx, u32 dimy, u32 dimz); + +private: + void Construct(ID3D11ComputeShader* cs, const ref_ctable& ctable, xr_vector& Samplers, + xr_vector& Textures, xr_vector& Outputs); + +private: + ID3D11ComputeShader* m_cs; + ref_ctable m_ctable; + xr_vector m_Samplers; + xr_vector m_Textures; + xr_vector m_Outputs; +}; // class ComputeShader + +#endif // #ifndef COMPUTESHADER_H_INCLUDED diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12.cpp new file mode 100644 index 00000000000..7434e95006b --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12.cpp @@ -0,0 +1,210 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12.hpp" + +int g_nPrintDX12 = 0; + +namespace DX12 +{ + //--------------------------------------------------------------------------------------------------------------------- + UINT GetDXGIFormatSize(DXGI_FORMAT format) + { + switch (format) + { + case DXGI_FORMAT_UNKNOWN: + return 0; + + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return 16; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return 12; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return 8; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + return 4; + + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_B4G4R4A4_UNORM: + return 2; + + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + return 1; + } + + DX12_NOT_IMPLEMENTED; + return 0; + } + + //--------------------------------------------------------------------------------------------------------------------- + D3D12_CLEAR_VALUE GetDXGIFormatClearValue(DXGI_FORMAT format, bool depth) + { + D3D12_CLEAR_VALUE clearValue; + + clearValue.Color[0] = 0.0f; + clearValue.Color[1] = 0.0f; + clearValue.Color[2] = 0.0f; + clearValue.Color[3] = 0.0f; + + switch (format) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + format = DXGI_FORMAT_R32G32B32A32_FLOAT; + break; + + case DXGI_FORMAT_R32G32B32_TYPELESS: + format = DXGI_FORMAT_R32G32B32_FLOAT; + break; + + case DXGI_FORMAT_R32_TYPELESS: + format = depth ? DXGI_FORMAT_D32_FLOAT : DXGI_FORMAT_R32_FLOAT; + break; + + case DXGI_FORMAT_R16G16_TYPELESS: + format = DXGI_FORMAT_R16G16_FLOAT; + break; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + format = DXGI_FORMAT_R16G16B16A16_FLOAT; + break; + + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + format = DXGI_FORMAT_R32G32_FLOAT; + break; + + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + format = DXGI_FORMAT_D24_UNORM_S8_UINT; + break; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + format = DXGI_FORMAT_R10G10B10A2_UNORM; + break; + + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + format = DXGI_FORMAT_R8G8B8A8_UNORM; + break; + + case DXGI_FORMAT_R8G8_TYPELESS: + format = DXGI_FORMAT_R8G8_UNORM; + break; + + case DXGI_FORMAT_R16_TYPELESS: + format = depth ? DXGI_FORMAT_D16_UNORM : DXGI_FORMAT_R16_FLOAT; + break; + + case DXGI_FORMAT_R8_TYPELESS: + format = DXGI_FORMAT_R8_UNORM; + break; + } + + clearValue.Format = format; + return clearValue; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + //--------------------------------------------------------------------------------------------------------------------- + DeviceObject::DeviceObject(Device* device) + : ReferenceCounted() + , m_Device(device) + , m_IsInitialized(false) + { + } + + //--------------------------------------------------------------------------------------------------------------------- + DeviceObject::~DeviceObject() + { + DX12_LOG("DX12 object destroyed: %p", this); + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12.hpp new file mode 100644 index 00000000000..44977bd3342 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12.hpp @@ -0,0 +1,207 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once + +#include +#include +#include + +#include +//#include +#include + +#include "DX12/Includes/d3dx12.h" + +#include "DX12/Includes/concqueue.hpp" +#include "DX12/Includes/critical_section.h" +#include "DX12/Includes/crc32.h" +#include "DX12/Includes/fasthash.inl" +#include "DX12/Includes/smartptr.h" +#include "DX12/Includes/range.h" +#include "DX12/Includes/reference_counted.h" + +#include + +extern int g_nPrintDX12; + +namespace RendererDX12 +{ +const int CV_r_D3D12SubmissionThread = 0; +const bool CV_r_EnableDebugLayer = false; +}; // namespace RendererDX12 + +#define DX12_NOT_IMPLEMENTED R_ASSERT2(0, "Not implemented!"); +#define DX12_STATS + +#ifndef NDEBUG + +#define DX12_FUNC_LOG do { \ + if (g_nPrintDX12) \ + { Msg("DX12 function call: %s", __func__); } \ +} while (0); + +#define DX12_LOG(...) do { \ +if (g_nPrintDX12) \ + { Msg("DX12 Log: " __VA_ARGS__); } \ +} while (0) +#define DX12_ERROR(...) do { Msg("DX12 Error: " __VA_ARGS__); } while (0) +#define DX12_ASSERT(cond, ...) \ + do { if (!(cond)) { DX12_ERROR(__VA_ARGS__); R_ASSERT(0); __debugbreak(); } } while(0) + +#else +#define DX12_FUNC_LOG do { } while (0); +#define DX12_LOG(...) do { } while (0) +#define DX12_ERROR(...) do { } while (0) +#define DX12_ASSERT(cond, ...) +#endif + +#ifndef DX12_ARRAY_SIZE +/// Return an array size for static arrays. +#define DX12_ARRAY_SIZE(__a) (sizeof(__a) / sizeof(__a[0])) +#endif + +#ifdef DEBUG +#define GFX_DEBUG +#endif + +#define DX12_GPU_VIRTUAL_ADDRESS_NULL 0ULL +#define INVALID_CPU_DESCRIPTOR_HANDLE CD3DX12_CPU_DESCRIPTOR_HANDLE(D3D12_DEFAULT) +#define INVALID_GPU_DESCRIPTOR_HANDLE CD3DX12_GPU_DESCRIPTOR_HANDLE(D3D12_DEFAULT) + +// Define BIT macro for use in enums and bit masks. +#define BIT(x) (1 << (x)) +#define BIT64(x) (1ll << (x)) +#define TYPED_BIT(type, x) (type(1) << (x)) + +namespace DX12 +{ + class CommandList; + class CommandListPool; + class DescriptorHeap; + class Device; + class GraphicsPipelineState; + class PipelineStateCache; + class Resource; + class ResourceView; + + template + static T* PassAddRef(T* ptr) + { + if (ptr) + { + ptr->AddRef(); + } + + return ptr; + } + + template + static T* PassAddRef(const _smart_ptr& ptr) + { + if (ptr) + { + ptr.get()->AddRef(); + } + + return ptr.get(); + } + + typedef uint32_t THash; + template + inline THash ComputeSmallHash(const void* data, UINT seed = 666) + { + return fasthash::fasthash32(data, seed); + } + + UINT GetDXGIFormatSize(DXGI_FORMAT format); + D3D12_CLEAR_VALUE GetDXGIFormatClearValue(DXGI_FORMAT format, bool depth); + + inline bool IsDXGIFormatCompressed(DXGI_FORMAT format) + { + return + (format >= DXGI_FORMAT_BC1_TYPELESS && format <= DXGI_FORMAT_BC5_SNORM) || + (format >= DXGI_FORMAT_BC6H_TYPELESS && format <= DXGI_FORMAT_BC7_UNORM_SRGB); + } + + inline bool IsDXGIFormatCompressed4bpp(DXGI_FORMAT format) + { + return + (format >= DXGI_FORMAT_BC1_TYPELESS && format <= DXGI_FORMAT_BC1_UNORM_SRGB) || + (format >= DXGI_FORMAT_BC4_TYPELESS && format <= DXGI_FORMAT_BC4_SNORM); + } + + inline bool IsDXGIFormatCompressed8bpp(DXGI_FORMAT format) + { + return + (format >= DXGI_FORMAT_BC2_TYPELESS && format <= DXGI_FORMAT_BC3_UNORM_SRGB) || + (format >= DXGI_FORMAT_BC5_TYPELESS && format <= DXGI_FORMAT_BC5_SNORM) || + (format >= DXGI_FORMAT_BC6H_TYPELESS && format <= DXGI_FORMAT_BC7_UNORM_SRGB); + } + + class DeviceObject : public ReferenceCounted + { + public: + inline Device* GetDevice() const + { + return m_Device; + } + + inline bool IsInitialized() const + { + return m_IsInitialized; + } + + protected: + DeviceObject(Device* device); + virtual ~DeviceObject(); + + DeviceObject(DeviceObject&& r) + : ReferenceCounted(std::move(r)) + , m_IsInitialized(std::move(r.m_IsInitialized)) + , m_Device(std::move(r.m_Device)) + {} + + DeviceObject& operator=(DeviceObject&& r) + { + ReferenceCounted::operator=(std::move(r)); + + m_IsInitialized = std::move(r.m_IsInitialized); + m_Device = std::move(r.m_Device); + + return *this; + } + + inline void SetDevice(Device* device) + { + m_Device = device; + } + + inline void IsInitialized(bool is) + { + m_IsInitialized = is; + } + + private: + Device* m_Device; + bool m_IsInitialized; + }; + + static const UINT CONSTANT_BUFFER_ELEMENT_SIZE = 16U; + + enum CommandMode + { + CommandModeCompute = 0, + CommandModeGraphics, + CommandModeCount + }; +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12AsyncCommandQueue.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12AsyncCommandQueue.cpp new file mode 100644 index 00000000000..4c5b082ac51 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12AsyncCommandQueue.cpp @@ -0,0 +1,203 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. + +#include "StdAfx.h" +#include "DX12AsyncCommandQueue.hpp" +#include "DX12CommandList.hpp" +#include "DX12Device.hpp" + +namespace DX12 +{ + void AsyncCommandQueue::SExecuteCommandlist::Process(const STaskArgs& args) + { + args.pCommandQueue->ExecuteCommandLists(1, &pCommandList); + } + + void AsyncCommandQueue::SResetCommandlist::Process(const STaskArgs& args) + { + pCommandList->Reset(); + } + + void AsyncCommandQueue::SSignalFence::Process(const STaskArgs& args) + { + args.pCommandQueue->Signal(pFence, FenceValue); + } + + void AsyncCommandQueue::SWaitForFence::Process(const STaskArgs& args) + { + args.pCommandQueue->Wait(pFence, FenceValue); + } + + void AsyncCommandQueue::SWaitForFences::Process(const STaskArgs& args) + { + if (FenceValues[CMDQUEUE_COPY ]) + { + args.pCommandQueue->Wait(pFences[CMDQUEUE_COPY ], FenceValues[CMDQUEUE_COPY ]); + } + if (FenceValues[CMDQUEUE_GRAPHICS]) + { + args.pCommandQueue->Wait(pFences[CMDQUEUE_GRAPHICS], FenceValues[CMDQUEUE_GRAPHICS]); + } + } + + AsyncCommandQueue::AsyncCommandQueue() + : m_pCmdListPool(NULL) + , m_QueuedFramesCounter(0) + , m_bStopRequested(false) + { + } + + AsyncCommandQueue::~AsyncCommandQueue() + { + SignalStop(); + Flush(); + m_pCmdListPool = nullptr; + } + + void AsyncCommandQueue::Init(CommandListPool* pCommandListPool) + { + m_pCmdListPool = pCommandListPool; + m_QueuedFramesCounter = 0; + m_QueuedTasksCounter = 0; + m_bStopRequested = false; + + if (RendererDX12::CV_r_D3D12SubmissionThread == 0) + return; + + m_asyncThread = std::thread([this] { ThreadEntry(); }); + m_asyncThread.detach(); + } + + + void AsyncCommandQueue::ExecuteCommandLists(UINT NumCommandLists, ID3D12CommandList* const* ppCommandLists) + { + for (int i = 0; i < NumCommandLists; ++i) + { + SSubmissionTask task; + ZeroMemory(&task, sizeof(SSubmissionTask)); + + task.type = eTT_ExecuteCommandList; + task.Data.ExecuteCommandList.pCommandList = ppCommandLists[i]; + + AddTask(task); + } + } + + void AsyncCommandQueue::ResetCommandList(CommandList* pCommandList) + { + SSubmissionTask task; + ZeroMemory(&task, sizeof(SSubmissionTask)); + + task.type = eTT_ResetCommandList; + task.Data.ResetCommandList.pCommandList = pCommandList; + + AddTask(task); + } + + void AsyncCommandQueue::Signal(ID3D12Fence* pFence, const UINT64 FenceValue) + { + SSubmissionTask task; + ZeroMemory(&task, sizeof(SSubmissionTask)); + + task.type = eTT_SignalFence; + task.Data.SignalFence.pFence = pFence; + task.Data.SignalFence.FenceValue = FenceValue; + + AddTask(task); + } + + void AsyncCommandQueue::Wait(ID3D12Fence* pFence, const UINT64 FenceValue) + { + SSubmissionTask task; + ZeroMemory(&task, sizeof(SSubmissionTask)); + + task.type = eTT_WaitForFence; + task.Data.WaitForFence.pFence = pFence; + task.Data.WaitForFence.FenceValue = FenceValue; + + AddTask(task); + } + + void AsyncCommandQueue::Wait(ID3D12Fence** pFences, const UINT64 (&FenceValues)[CMDQUEUE_NUM]) + { + SSubmissionTask task; + ZeroMemory(&task, sizeof(SSubmissionTask)); + + task.type = eTT_WaitForFences; + task.Data.WaitForFences.pFences = pFences; + task.Data.WaitForFences.FenceValues[CMDQUEUE_COPY ] = FenceValues[CMDQUEUE_COPY ]; + task.Data.WaitForFences.FenceValues[CMDQUEUE_GRAPHICS] = FenceValues[CMDQUEUE_GRAPHICS]; + + AddTask(task); + } + + void AsyncCommandQueue::Flush(UINT64 lowerBoundFenceValue) + { + if (lowerBoundFenceValue != (~0ULL)) + { + while (m_QueuedTasksCounter > 0) + { + if (lowerBoundFenceValue <= m_pCmdListPool->GetLastCompletedFenceValue()) + { + break; + } + + std::this_thread::sleep_for(std::chrono::seconds(0)); + } + } + else + { + while (m_QueuedTasksCounter > 0) + { + std::this_thread::sleep_for(std::chrono::seconds(0)); + } + } + } + + AsyncCommandQueue::STaskArgs AsyncCommandQueue::GetTaskArg() + { + return {m_pCmdListPool->GetD3D12CommandQueue(), &m_QueuedFramesCounter}; + } + + void AsyncCommandQueue::ThreadEntry() + { + SSubmissionTask task; + + while (true) + { + // Wait until main() sends data + std::unique_lock lk(m_mutex); + m_cv.wait(lk, [this, &task] { return m_bStopRequested || m_TaskQueue.dequeue(task); }); + + if (m_bStopRequested) + break; + + do + { + switch (task.type) + { + case eTT_ExecuteCommandList: task.Process(GetTaskArg()); break; + case eTT_ResetCommandList: task.Process(GetTaskArg()); break; + case eTT_SignalFence: task.Process(GetTaskArg()); break; + case eTT_WaitForFence: task.Process(GetTaskArg()); break; + case eTT_WaitForFences: task.Process(GetTaskArg()); break; + } + InterlockedDecrement((volatile LONG*)&m_QueuedTasksCounter); + } while (m_TaskQueue.dequeue(task)); + + // Manual unlocking is done before notifying, to avoid waking up + // the waiting thread only to block again (see notify_one for details) + lk.unlock(); + } + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12AsyncCommandQueue.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12AsyncCommandQueue.hpp new file mode 100644 index 00000000000..6f3b47ca637 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12AsyncCommandQueue.hpp @@ -0,0 +1,164 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. + +#pragma once + +#include "DX12/Includes/concqueue.hpp" + +#include "DX12.hpp" +#include "DX12CommandListFence.hpp" + +struct IDXGISwapChain3; + +#include +#include +#include + +namespace DX12 +{ + class CommandListPool; + + class AsyncCommandQueue + { + public: + AsyncCommandQueue(); + ~AsyncCommandQueue(); + + template + static bool IsSynchronous() + { + return RendererDX12::CV_r_D3D12SubmissionThread == 0; + } + + void Init(CommandListPool* pCommandListPool); + void Flush(UINT64 lowerBoundFenceValue = ~0ULL); + void SignalStop() { + std::lock_guard lk(m_mutex); + m_bStopRequested = true; + m_cv.notify_one(); + } + + void ResetCommandList(CommandList* pCommandList); + void ExecuteCommandLists(UINT NumCommandLists, ID3D12CommandList* const* ppCommandLists); + void Signal(ID3D12Fence* pFence, const UINT64 Value); + void Wait(ID3D12Fence* pFence, const UINT64 Value); + void Wait(ID3D12Fence** pFences, const UINT64 (&Values)[CMDQUEUE_NUM]); + + private: + enum eTaskType + { + eTT_ExecuteCommandList, + eTT_ResetCommandList, + eTT_SignalFence, + eTT_WaitForFence, + eTT_WaitForFences + }; + + struct STaskArgs + { + ID3D12CommandQueue* pCommandQueue; + volatile int* QueueFramesCounter; + }; + + struct SExecuteCommandlist + { + ID3D12CommandList* pCommandList; + + void Process(const STaskArgs& args); + }; + + struct SResetCommandlist + { + CommandList* pCommandList; + + void Process(const STaskArgs& args); + }; + + struct SSignalFence + { + ID3D12Fence* pFence; + UINT64 FenceValue; + + void Process(const STaskArgs& args); + }; + + struct SWaitForFence + { + ID3D12Fence* pFence; + UINT64 FenceValue; + + void Process(const STaskArgs& args); + }; + + struct SWaitForFences + { + ID3D12Fence** pFences; + UINT64 FenceValues[CMDQUEUE_NUM]; + + void Process(const STaskArgs& args); + }; + + struct SSubmissionTask + { + eTaskType type; + + union + { + SSignalFence SignalFence; + SWaitForFence WaitForFence; + SWaitForFences WaitForFences; + SExecuteCommandlist ExecuteCommandList; + SResetCommandlist ResetCommandList; + } Data; + + template + void Process(const STaskArgs& args) + { + TaskType* pTask = reinterpret_cast(&Data); + pTask->Process(args); + } + }; + + STaskArgs GetTaskArg(); + + template + void AddTask(SSubmissionTask& task) + { + if (RendererDX12::CV_r_D3D12SubmissionThread) + { + std::lock_guard lk(m_mutex); + InterlockedIncrement((volatile LONG*)&m_QueuedTasksCounter); + m_TaskQueue.enqueue(task); + m_cv.notify_one(); + } + else + { + Flush(); + task.Process(GetTaskArg()); + } + } + + void ThreadEntry(); + + volatile int m_QueuedFramesCounter; + volatile int m_QueuedTasksCounter; + volatile bool m_bStopRequested; + + std::mutex m_mutex; + std::condition_variable m_cv; + std::thread m_asyncThread; + + CommandListPool* m_pCmdListPool; + ConcQueue m_TaskQueue; + }; +}; diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12CommandList.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12CommandList.cpp new file mode 100644 index 00000000000..686363d70ff --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12CommandList.cpp @@ -0,0 +1,1324 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12CommandList.hpp" + +#include "DX12/Device/CCryDX12Device.hpp" +#include "DX12/Device/CCryDX12DeviceContext.hpp" +#include "DX12/GI/CCryDX12SwapChain.hpp" + +#include + +namespace DX12 +{ + const char* StateToString(D3D12_RESOURCE_STATES state) + { + static int buf = 0; + static char str[2][512], *ret; + + ret = str[buf ^= 1]; + *ret = '\0'; + + if (!state) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " Common/Present"); + return ret; + } + + if ((state & D3D12_RESOURCE_STATE_GENERIC_READ) == D3D12_RESOURCE_STATE_GENERIC_READ) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " Generic Read"); + return ret; + } + + if (state & D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " V/C Buffer"); + } + if (state & D3D12_RESOURCE_STATE_INDEX_BUFFER) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " I Buffer"); + } + if (state & D3D12_RESOURCE_STATE_RENDER_TARGET) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " RT"); + } + if (state & D3D12_RESOURCE_STATE_UNORDERED_ACCESS) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " UA"); + } + if (state & D3D12_RESOURCE_STATE_DEPTH_WRITE) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " DepthW"); + } + if (state & D3D12_RESOURCE_STATE_DEPTH_READ) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " DepthR"); + } + if (state & D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " NoPixelR"); + } + if (state & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " PixelR"); + } + if (state & D3D12_RESOURCE_STATE_STREAM_OUT) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " Stream Out"); + } + if (state & D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " Indirect Arg"); + } + if (state & D3D12_RESOURCE_STATE_COPY_DEST) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " CopyD"); + } + if (state & D3D12_RESOURCE_STATE_COPY_SOURCE) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " CopyS"); + } + if (state & D3D12_RESOURCE_STATE_RESOLVE_DEST) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " ResolveD"); + } + if (state & D3D12_RESOURCE_STATE_RESOLVE_SOURCE) + { + strcat_s(ret, DX12_ARRAY_SIZE(ret), " ResolveS"); + } + + return ret; + } + + CommandList::CommandList(CommandListPool& pool) + : DeviceObject(pool.GetDevice()) + , m_rPool(pool) + , m_pCmdQueue{} + , m_pCmdAllocator{} + , m_CommandList{} + , m_pD3D12Device{} + , m_CurrentNumRTVs{} + , m_CurrentNumVertexBuffers{} + , m_CurrentFenceValue{} + , m_eListType(pool.GetD3D12QueueType()) + , m_State(CLSTATE_FREE) + , m_nodeMask{} +#if DX12_GPU_PROFILE_MODE != DX12_GPU_PROFILE_MODE_OFF + , m_Timers{ *GetDevice() } +#endif + , m_DescriptorHeaps + { + { + GetDevice()->GetGlobalDescriptorBlock(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1024) + }, + { + GetDevice()->GetGlobalDescriptorBlock(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, 1024) + }, + { + GetDevice()->GetGlobalDescriptorBlock(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1024) + }, + { + GetDevice()->GetGlobalDescriptorBlock(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1024) + } + } + { + ResetStateTracking(CommandModeCompute); + ResetStateTracking(CommandModeGraphics); + } + + CommandList::~CommandList() + { + } + + bool CommandList::Init(UINT64 currentFenceValue) + { + m_State = CLSTATE_STARTED; + m_Commands = 0; + m_CurrentPipelineState = nullptr; + m_CurrentRootSignature[DX12::CommandModeCompute] = m_CurrentRootSignature[DX12::CommandModeGraphics] = nullptr; + m_pDSV = nullptr; + m_CurrentNumRTVs = 0; + m_CurrentNumVertexBuffers = 0; + + m_CurrentFenceValue = currentFenceValue; + ZeroMemory(m_UsedFenceValues, sizeof(m_UsedFenceValues)); + + m_pD3D12Device = GetDevice()->GetD3D12Device(); + + for (D3D12_DESCRIPTOR_HEAP_TYPE eType = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; eType < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; eType = D3D12_DESCRIPTOR_HEAP_TYPE(eType + 1)) + { + m_DescriptorHeaps[eType].Reset(); + } + + if (!IsInitialized()) + { + m_pCmdQueue = m_rPool.GetD3D12CommandQueue(); + + D3D12_COMMAND_LIST_TYPE eCmdListType = m_pCmdQueue->GetDesc().Type; + + ID3D12CommandAllocator* pCmdAllocator = nullptr; + if (S_OK != m_pD3D12Device->CreateCommandAllocator(eCmdListType, IID_PPV_ARGS(&pCmdAllocator))) + { + DX12_ERROR("Could not create command allocator!"); + return false; + } + + m_pCmdAllocator = pCmdAllocator; + pCmdAllocator->Release(); + + ID3D12GraphicsCommandList* pCmdList = nullptr; + if (S_OK != m_pD3D12Device->CreateCommandList(m_nodeMask, eCmdListType, m_pCmdAllocator, nullptr, IID_PPV_ARGS(&pCmdList))) + { + DX12_ERROR("Could not create command list"); + return false; + } + + m_CommandList = pCmdList; + pCmdList->Release(); + +#if DX12_GPU_PROFILE_MODE != DX12_GPU_PROFILE_MODE_OFF + m_Timers.Init(TimerCountMax); +#endif + + IsInitialized(true); + } + +#ifdef DX12_STATS + m_NumWaitsGPU = 0; + m_NumWaitsCPU = 0; +#endif // DX12_STATS + + return true; + } + + void CommandList::Begin() + { +#if DX12_GPU_PROFILE_MODE != DX12_GPU_PROFILE_MODE_OFF + m_Timers.Begin(); + m_TimerHandle = m_Timers.BeginTimer(*this, "CommandList"); +#endif + } + + void CommandList::End() + { + { + DX12_COMMANDLIST_TIMER("End"); + FlushBarriers(); + } + + if (IsUtilized()) + { +#if DX12_GPU_PROFILE_MODE != DX12_GPU_PROFILE_MODE_OFF + m_Timers.EndTimer(*this, m_TimerHandle); + m_Timers.End(*this); +#endif + + HRESULT res = m_CommandList->Close(); + DX12_ASSERT(res == S_OK, "Could not close command list!"); + } + + m_State = CLSTATE_COMPLETED; + } + + void CommandList::Schedule() + { + if (m_State < CLSTATE_SCHEDULED) + { + m_State = CLSTATE_SCHEDULED; + } + } + + void CommandList::Submit() + { + if (IsUtilized()) + { + // Inject a Wait() into the CommandQueue prior to executing it to wait for all required resources being available either readable or writable +#ifdef DX12_IN_ORDER_SUBMISSION + m_UsedFenceValues[CMDTYPE_ANY][CMDQUEUE_COPY ] = std::max(m_UsedFenceValues[CMDTYPE_READ][CMDQUEUE_COPY ], m_UsedFenceValues[CMDTYPE_WRITE][CMDQUEUE_COPY ]); + m_UsedFenceValues[CMDTYPE_ANY][CMDQUEUE_GRAPHICS] = std::max(m_UsedFenceValues[CMDTYPE_READ][CMDQUEUE_GRAPHICS], m_UsedFenceValues[CMDTYPE_WRITE][CMDQUEUE_GRAPHICS]); +#else + MaxFenceValue(m_UsedFenceValues[CMDTYPE_ANY][CMDQUEUE_COPY ], std::max(m_UsedFenceValues[CMDTYPE_READ][CMDQUEUE_COPY ], m_UsedFenceValues[CMDTYPE_WRITE][CMDQUEUE_COPY ])); + MaxFenceValue(m_UsedFenceValues[CMDTYPE_ANY][CMDQUEUE_GRAPHICS], std::max(m_UsedFenceValues[CMDTYPE_READ][CMDQUEUE_GRAPHICS], m_UsedFenceValues[CMDTYPE_WRITE][CMDQUEUE_GRAPHICS])); +#endif + + m_rPool.WaitForFenceOnGPU(m_UsedFenceValues[CMDTYPE_ANY]); + + // Then inject the Execute() which is possibly blocked by the Wait() + ID3D12CommandList* ppCommandLists[] = { GetD3D12CommandList() }; + m_rPool.GetAsyncCommandQueue().ExecuteCommandLists(1, ppCommandLists); // TODO: allow to submit multiple command-lists in one go + } + + // Inject the signal of the utilized fence to unblock code which picked up the fence of the command-list (even if it doesn't have contents) + m_rPool.SetSubmittedFenceValue(SignalFenceOnGPU()); + m_State = CLSTATE_SUBMITTED; + } + + void CommandList::Clear() + { + m_State = CLSTATE_CLEARING; + FlushBarriers(); + m_rPool.GetAsyncCommandQueue().ResetCommandList(this); + } + + void CommandList::SubmitTimers() + { +#if DX12_GPU_PROFILE_MODE != DX12_GPU_PROFILE_MODE_OFF + m_Timers.ReadbackTimers(); + + for (const Timer& timer : m_Timers.GetTimers()) + { + EBUS_QUEUE_EVENT(Debug::EventTraceDrillerBus, RecordSlice, timer.m_Name, EventTrace::GpuDetailCategory, EventTrace::GpuDetailThreadId, timer.m_Timestamp, timer.m_Duration); + } +#endif + } + + bool CommandList::Reset() + { + if (IsUtilized()) + { + SubmitTimers(); + + HRESULT ret = 0; + + // reset the allocator before the list re-occupies it, otherwise the whole state of the allocator starts leaking + if (m_pCmdAllocator) + { + ret = m_pCmdAllocator->Reset(); + } + // make the list re-occupy this allocator, reseting the list will _not_ reset the allocator + if (m_CommandList) + { + ret = m_CommandList->Reset(m_pCmdAllocator, NULL); + } + } + + m_State = CLSTATE_FREE; + m_Commands = 0; + return true; + } + + void CommandList::ResetStateTracking(CommandMode commandMode) + { + memset(&m_CurrentRootParameters[commandMode], ~0, sizeof(m_CurrentRootParameters[commandMode])); + } + + void CommandList::SetPipelineState(const PipelineState* pso) + { + if (m_CurrentPipelineState != pso) + { + m_CurrentPipelineState = pso; + } + { + DX12_COMMANDLIST_TIMER_DETAIL("SetPipelineState"); + m_CommandList->SetPipelineState(pso->GetD3D12PipelineState()); + m_Commands += CLCOUNT_SETIO; + } + } + + void CommandList::SetRootSignature(CommandMode commandMode, const RootSignature* rootSignature) + { + if (m_CurrentRootSignature[commandMode] != rootSignature) + { + m_CurrentRootSignature[commandMode] = rootSignature; + } + + { + if (rootSignature) + { + ResetStateTracking(commandMode); + DX12_COMMANDLIST_TIMER_DETAIL("SetRootSignature"); + switch (commandMode) + { + case CommandModeGraphics: + m_CommandList->SetGraphicsRootSignature(rootSignature->GetD3D12RootSignature()); + break; + + case CommandModeCompute: + m_CommandList->SetComputeRootSignature(rootSignature->GetD3D12RootSignature()); + break; + } + m_Commands += CLCOUNT_SETIO; + } + } + } + + bool CommandList::IsFull(size_t numResources, size_t numSamplers, size_t numRendertargets, size_t numDepthStencils) const + { + return + (GetResourceHeap().GetCursor() + numResources >= GetResourceHeap().GetCapacity()) || + (GetSamplerHeap().GetCursor() + numSamplers >= GetSamplerHeap().GetCapacity()) || + (GetRenderTargetHeap().GetCursor() + numRendertargets >= GetRenderTargetHeap().GetCapacity()) || + (GetDepthStencilHeap().GetCursor() + numDepthStencils >= GetDepthStencilHeap().GetCapacity()); + } + + void CommandList::SetDescriptorTable(CommandMode commandMode, UINT RootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor) + { + if (m_CurrentRootParameters[commandMode][RootParameterIndex].descriptorHandle.ptr != BaseDescriptor.ptr) + { + DX12_ASSERT(RootParameterIndex < RootParameterCountMax, "Too many root parameters"); + m_CurrentRootParameters[commandMode][RootParameterIndex].descriptorHandle = BaseDescriptor; + + switch (commandMode) + { + case CommandModeGraphics: + m_CommandList->SetGraphicsRootDescriptorTable(RootParameterIndex, BaseDescriptor); + break; + + case CommandModeCompute: + m_CommandList->SetComputeRootDescriptorTable(RootParameterIndex, BaseDescriptor); + break; + } + m_Commands += CLCOUNT_SETIO; + } + } + + void CommandList::SetConstantBufferView(CommandMode commandMode, UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation) + { + if (m_CurrentRootParameters[commandMode][RootParameterIndex].gpuAddress != BufferLocation) + { + DX12_ASSERT(RootParameterIndex < RootParameterCountMax, "Too many root parameters"); + m_CurrentRootParameters[commandMode][RootParameterIndex].gpuAddress = BufferLocation; + switch (commandMode) + { + case CommandModeGraphics: + m_CommandList->SetGraphicsRootConstantBufferView(RootParameterIndex, BufferLocation); + break; + + case CommandModeCompute: + m_CommandList->SetComputeRootConstantBufferView(RootParameterIndex, BufferLocation); + break; + } + m_Commands += CLCOUNT_SETIO; + } + } + + void CommandList::Set32BitConstants(CommandMode commandMode, UINT RootParameterIndex, UINT Num32BitValuesToSet, const void* pSrcData, UINT DestOffsetIn32BitValues) + { + switch (commandMode) + { + case CommandModeGraphics: + m_CommandList->SetGraphicsRoot32BitConstants(RootParameterIndex, Num32BitValuesToSet, pSrcData, DestOffsetIn32BitValues); + break; + + case CommandModeCompute: + m_CommandList->SetComputeRoot32BitConstants(RootParameterIndex, Num32BitValuesToSet, pSrcData, DestOffsetIn32BitValues); + break; + } + m_Commands += CLCOUNT_SETIO; + } + + void CommandList::SetDescriptorTables(CommandMode commandMode, D3D12_DESCRIPTOR_HEAP_TYPE eType) + { + DX12_ASSERT(m_CurrentRootSignature[commandMode]); + + const PipelineLayout& layout = m_CurrentRootSignature[commandMode]->GetPipelineLayout(); + for (u32 rootParameterIdx = 0, tableIdx = 0; rootParameterIdx < layout.m_NumRootParameters; ++rootParameterIdx) + { + const CD3DX12_ROOT_PARAMETER& rootParameter = layout.m_RootParameters[rootParameterIdx]; + + if (rootParameter.ParameterType != D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) + { + continue; + } + + if (layout.m_DescriptorTables[tableIdx].m_Type == eType) + { + switch (commandMode) + { + case CommandModeCompute: + m_CommandList->SetComputeRootDescriptorTable(rootParameterIdx, m_DescriptorHeaps[eType].GetHandleOffsetGPU(layout.m_DescriptorTables[tableIdx].m_Offset)); + break; + + case CommandModeGraphics: + m_CommandList->SetGraphicsRootDescriptorTable(rootParameterIdx, m_DescriptorHeaps[eType].GetHandleOffsetGPU(layout.m_DescriptorTables[tableIdx].m_Offset)); + break; + } + m_Commands += CLCOUNT_SETIO; + } + + ++tableIdx; + } + } + + void CommandList::BindDepthStencilView(const ResourceView& dsv) + { + Resource& resource = dsv.GetDX12Resource(); + const D3D12_CPU_DESCRIPTOR_HANDLE handle = GetDepthStencilHeap().GetHandleOffsetCPU(0); + + if (INVALID_CPU_DESCRIPTOR_HANDLE != dsv.GetDescriptorHandle()) + { + m_pD3D12Device->CopyDescriptorsSimple(1, handle, dsv.GetDescriptorHandle(), D3D12_DESCRIPTOR_HEAP_TYPE_DSV); + } + else + { + m_pD3D12Device->CreateDepthStencilView(resource.GetD3D12Resource(), dsv.HasDesc() ? &(dsv.GetDSVDesc()) : NULL, handle); + } + + if (dsv.GetDSVDesc().Flags & D3D12_DSV_FLAG_READ_ONLY_DEPTH) + { + TrackResourceDRVUsage(resource); + } + else + { + TrackResourceDSVUsage(resource); + } + } + + void CommandList::PresentRenderTargetView(SwapChain* pDX12SwapChain) + { + QueueTransitionBarrier(pDX12SwapChain->GetCurrentBackBuffer(), D3D12_RESOURCE_STATE_PRESENT); + } + + void CommandList::BindRenderTargetView(const ResourceView& renderTargetView) + { + Resource& resource = renderTargetView.GetDX12Resource(); + + const D3D12_CPU_DESCRIPTOR_HANDLE handle = GetRenderTargetHeap().GetHandleOffsetCPU(0); + if (INVALID_CPU_DESCRIPTOR_HANDLE != renderTargetView.GetDescriptorHandle()) + { + m_pD3D12Device->CopyDescriptorsSimple(1, handle, renderTargetView.GetDescriptorHandle(), D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + } + else + { + m_pD3D12Device->CreateRenderTargetView(resource.GetD3D12Resource(), renderTargetView.HasDesc() ? &(renderTargetView.GetRTVDesc()) : NULL, handle); + } + + TrackResourceRTVUsage(resource); + } + + void CommandList::WriteUnorderedAccessDescriptor(const ResourceView* resourceView, INT descriptorOffset) + { + D3D12_CPU_DESCRIPTOR_HANDLE dstHandle = GetResourceHeap().GetHandleOffsetCPU(descriptorOffset); + + if (resourceView) + { + Resource& resource = resourceView->GetDX12Resource(); + + if (INVALID_CPU_DESCRIPTOR_HANDLE != resourceView->GetDescriptorHandle()) + { + m_pD3D12Device->CopyDescriptorsSimple(1, dstHandle, resourceView->GetDescriptorHandle(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + else + { + m_pD3D12Device->CreateUnorderedAccessView(resource.GetD3D12Resource(), nullptr, resourceView->HasDesc() ? &(resourceView->GetUAVDesc()) : NULL, dstHandle); + } + + TrackResourceUAVUsage(resource); + } + else + { + m_pD3D12Device->CopyDescriptorsSimple(1, dstHandle, GetDevice()->GetNullUnorderedAccessView(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + } + + void CommandList::WriteShaderResourceDescriptor(const ResourceView* resourceView, INT descriptorOffset) + { + D3D12_CPU_DESCRIPTOR_HANDLE dstHandle = GetResourceHeap().GetHandleOffsetCPU(descriptorOffset); + + if (resourceView) + { + Resource& resource = resourceView->GetDX12Resource(); + DX12_ASSERT(resource.GetD3D12Resource(), "No resource to create SRV from!"); + + if (INVALID_CPU_DESCRIPTOR_HANDLE != resourceView->GetDescriptorHandle()) + { + m_pD3D12Device->CopyDescriptorsSimple(1, dstHandle, resourceView->GetDescriptorHandle(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + else + { + m_pD3D12Device->CreateShaderResourceView(resource.GetD3D12Resource(), &resourceView->GetSRVDesc(), dstHandle); + } + + TrackResourceSRVUsage(resource); + } + else + { + m_pD3D12Device->CopyDescriptorsSimple(1, dstHandle, GetDevice()->GetNullShaderResourceView(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + } + + void CommandList::WriteConstantBufferDescriptor(const ResourceView* resourceView, INT descriptorOffset, UINT byteOffset, UINT byteCount) + { + D3D12_CPU_DESCRIPTOR_HANDLE dstHandle = GetResourceHeap().GetHandleOffsetCPU(descriptorOffset); + + if (resourceView) + { + if (INVALID_CPU_DESCRIPTOR_HANDLE != resourceView->GetDescriptorHandle()) + { + m_pD3D12Device->CopyDescriptorsSimple(1, dstHandle, resourceView->GetDescriptorHandle(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + else + { + D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc; + cbvDesc = resourceView->GetCBVDesc(); + cbvDesc.BufferLocation += byteOffset; + cbvDesc.SizeInBytes = byteCount ? byteCount : cbvDesc.SizeInBytes - byteOffset; + DX12_ASSERT(byteCount < D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * DX12::CONSTANT_BUFFER_ELEMENT_SIZE, "exceeded allowed size of constant buffer"); + m_pD3D12Device->CreateConstantBufferView(&cbvDesc, dstHandle); + } + + TrackResourceCBVUsage(resourceView->GetDX12Resource()); + } + else + { + D3D12_CONSTANT_BUFFER_VIEW_DESC desc = {}; + m_pD3D12Device->CreateConstantBufferView(&desc, dstHandle); + } + } + + void CommandList::WriteSamplerStateDescriptor(const SamplerState* state, INT descriptorOffset) + { + D3D12_CPU_DESCRIPTOR_HANDLE dstHandle = GetSamplerHeap().GetHandleOffsetCPU(descriptorOffset); + + if (state) + { + if (INVALID_CPU_DESCRIPTOR_HANDLE != state->GetDescriptorHandle()) + { + m_pD3D12Device->CopyDescriptorsSimple(1, dstHandle, state->GetDescriptorHandle(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + } + else + { + m_pD3D12Device->CreateSampler(&state->GetSamplerDesc(), dstHandle); + } + } + else + { + m_pD3D12Device->CopyDescriptorsSimple(1, dstHandle, GetDevice()->GetNullSampler(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + } + } + + void CommandList::SetResourceAndSamplerStateHeaps() + { + DX12_COMMANDLIST_TIMER_DETAIL("SetResourceAndSamplerStateHeaps"); + ID3D12DescriptorHeap* heaps[] = + { + GetResourceHeap().GetDescriptorHeap()->GetD3D12DescriptorHeap(), + GetSamplerHeap().GetDescriptorHeap()->GetD3D12DescriptorHeap() + }; + + m_CommandList->SetDescriptorHeaps(2, heaps); + m_Commands += CLCOUNT_SETIO; + } + + void CommandList::BindAndSetOutputViews(INT numRTVs, const ResourceView** rtv, const ResourceView* dsv) + { + DX12_COMMANDLIST_TIMER_DETAIL("BindAndSetOutputViews"); + if (dsv) + { + BindDepthStencilView(*dsv); + GetDepthStencilHeap().IncrementCursor(); + } + + m_pDSV = dsv; + + for (INT i = 0; i < numRTVs; ++i) + { + BindRenderTargetView(*rtv[i]); + GetRenderTargetHeap().IncrementCursor(); + + m_pRTV[i] = rtv[i]; + } + + m_CurrentNumRTVs = numRTVs; + + D3D12_CPU_DESCRIPTOR_HANDLE RTVDescriptors[] = { GetRenderTargetHeap().GetHandleOffsetCPU(-numRTVs) }; + D3D12_CPU_DESCRIPTOR_HANDLE DSVDescriptors[] = { GetDepthStencilHeap().GetHandleOffsetCPU(-1) }; + + m_CommandList->OMSetRenderTargets(numRTVs, numRTVs ? RTVDescriptors : NULL, true, dsv ? DSVDescriptors : NULL); + m_Commands += CLCOUNT_SETIO; + } + + bool CommandList::IsUsedByOutputViews(const Resource& res) const + { + if (m_pDSV && (&m_pDSV->GetDX12Resource() == &res)) + { + return true; + } + + for (INT i = 0, n = m_CurrentNumRTVs; i < n; ++i) + { + if (m_pRTV[i] && (&m_pRTV[i]->GetDX12Resource() == &res)) + { + return true; + } + } + + return false; + } + + void CommandList::BindVertexBufferView(const ResourceView& view, INT offset, const _range_t& bindRange, UINT bindStride, D3D12_VERTEX_BUFFER_VIEW (&heap)[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]) + { + Resource& resource = view.GetDX12Resource(); + + D3D12_VERTEX_BUFFER_VIEW& vbvDesc = heap[offset]; + vbvDesc = view.GetVBVDesc(); + vbvDesc.BufferLocation += bindRange.start; + vbvDesc.SizeInBytes = bindRange.Length() > 0 ? bindRange.Length() : vbvDesc.SizeInBytes - bindRange.start; + vbvDesc.StrideInBytes = bindStride; + + TrackResourceVBVUsage(resource); + } + + void CommandList::ClearVertexBufferHeap(UINT num) + { + memset(m_VertexBufferHeap, 0, std::max(num, m_CurrentNumVertexBuffers) * sizeof(m_VertexBufferHeap[0])); + } + + void CommandList::SetVertexBufferHeap(UINT num) + { + m_CommandList->IASetVertexBuffers(0, std::max(num, m_CurrentNumVertexBuffers), m_VertexBufferHeap); + m_Commands += CLCOUNT_SETIO; + + m_CurrentNumVertexBuffers = num; + } + + void CommandList::BindAndSetIndexBufferView(const ResourceView& view, DXGI_FORMAT format, UINT offset) + { + Resource& resource = view.GetDX12Resource(); + + D3D12_INDEX_BUFFER_VIEW ibvDesc; + ibvDesc = view.GetIBVDesc(); + ibvDesc.BufferLocation += offset; + ibvDesc.SizeInBytes = ibvDesc.SizeInBytes - offset; + ibvDesc.Format = (format == DXGI_FORMAT_UNKNOWN ? resource.GetDesc().Format : format); + + TrackResourceIBVUsage(resource); + + m_CommandList->IASetIndexBuffer(&ibvDesc); + m_Commands += CLCOUNT_SETIO; + } + + void CommandList::ClearDepthStencilView(const ResourceView& view, D3D12_CLEAR_FLAGS clearFlags, float depthValue, UINT stencilValue, UINT NumRects, const D3D12_RECT* pRect) + { + DX12_ASSERT(INVALID_CPU_DESCRIPTOR_HANDLE != view.GetDescriptorHandle(), "View has no descriptor handle, that is not allowed!"); + DX12_COMMANDLIST_TIMER_DETAIL("ClearDepthStencilView"); + + Resource& resource = view.GetDX12Resource(); + + TrackResourceDSVUsage(resource); + FlushBarriers(); + + m_CommandList->ClearDepthStencilView(view.GetDescriptorHandle(), clearFlags, depthValue, stencilValue, NumRects, pRect); + m_Commands += CLCOUNT_CLEAR; + } + + void CommandList::ClearRenderTargetView(const ResourceView& inputView, const FLOAT rgba[4], UINT NumRects, const D3D12_RECT* pRect) + { + DX12_ASSERT(INVALID_CPU_DESCRIPTOR_HANDLE != inputView.GetDescriptorHandle(), "View has no descriptor handle, that is not allowed!"); + DX12_COMMANDLIST_TIMER_DETAIL("ClearRenderTargetView"); + + TrackResourceRTVUsage(inputView.GetDX12Resource()); + FlushBarriers(); + + D3D12_CLEAR_VALUE clearValue = { DXGI_FORMAT_R32G32B32A32_FLOAT, {rgba[0], rgba[1], rgba[2], rgba[3]}}; + + m_CommandList->ClearRenderTargetView(inputView.GetDescriptorHandle(), rgba, NumRects, pRect); + m_Commands += CLCOUNT_CLEAR; + } + + void CommandList::ClearUnorderedAccessView(const ResourceView& view, const UINT rgba[4], UINT NumRects, const D3D12_RECT* pRect) + { + DX12_ASSERT(INVALID_CPU_DESCRIPTOR_HANDLE != view.GetDescriptorHandle(), "View has no descriptor handle, that is not allowed!"); + DX12_COMMANDLIST_TIMER_DETAIL("ClearUnorderedAccessView"); + + TrackResourceUAVUsage(view.GetDX12Resource()); + FlushBarriers(); + + m_CommandList->ClearUnorderedAccessViewUint(GetResourceHeap().GetHandleGPUFromCPU(view.GetDescriptorHandle()), view.GetDescriptorHandle(), view.GetD3D12Resource(), rgba, NumRects, pRect); + m_Commands += CLCOUNT_CLEAR; + } + + void CommandList::ClearUnorderedAccessView(const ResourceView& view, const FLOAT rgba[4], UINT NumRects, const D3D12_RECT* pRect) + { + DX12_ASSERT(INVALID_CPU_DESCRIPTOR_HANDLE != view.GetDescriptorHandle(), "View has no descriptor handle, that is not allowed!"); + DX12_COMMANDLIST_TIMER_DETAIL("ClearUnorderedAccessView"); + + TrackResourceUAVUsage(view.GetDX12Resource()); + FlushBarriers(); + + m_CommandList->ClearUnorderedAccessViewFloat(GetResourceHeap().GetHandleGPUFromCPU(view.GetDescriptorHandle()), view.GetDescriptorHandle(), view.GetD3D12Resource(), rgba, NumRects, pRect); + m_Commands += CLCOUNT_CLEAR; + } + + void CommandList::ClearView(const ResourceView& view, const FLOAT rgba[4], UINT NumRects, const D3D12_RECT* pRect) + { + DX12_ASSERT(INVALID_CPU_DESCRIPTOR_HANDLE != view.GetDescriptorHandle(), "View has no descriptor handle, that is not allowed!"); + + switch (view.GetType()) + { + case EVT_UnorderedAccessView: + ClearUnorderedAccessView(view, rgba, NumRects, pRect); + break; + + case EVT_DepthStencilView: // Optional implementation under DX11.1 + ClearDepthStencilView(view, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, FLOAT(rgba[0]), UINT(rgba[1]), NumRects, pRect); + break; + + case EVT_RenderTargetView: + ClearRenderTargetView(view, rgba, NumRects, pRect); + break; + + case EVT_ShaderResourceView: + case EVT_ConstantBufferView: + case EVT_VertexBufferView: + default: + DX12_ASSERT(0, "Unsupported resource-type for input!"); + break; + } + } + + void CommandList::CopyResource(Resource& dstResource, Resource& srcResource) + { + if (srcResource.InitHasBeenDeferred()) + { + srcResource.TryStagingUpload(this); + } + + DX12_COMMANDLIST_TIMER_DETAIL("CopyResource"); + MaxResourceFenceValue(dstResource, CMDTYPE_ANY); + MaxResourceFenceValue(srcResource, CMDTYPE_WRITE); + + D3D12_RESOURCE_STATES prevDstState = dstResource.GetCurrentState(); + D3D12_RESOURCE_STATES prevSrcState = srcResource.GetCurrentState(); + QueueTransitionBarrier(dstResource, D3D12_RESOURCE_STATE_COPY_DEST); + QueueTransitionBarrier(srcResource, D3D12_RESOURCE_STATE_COPY_SOURCE); + FlushBarriers(); + + DX12_ASSERT(srcResource.GetDesc().Dimension == dstResource.GetDesc().Dimension, "Can't copy resources of different dimension"); + m_CommandList->CopyResource(dstResource.GetD3D12Resource(), srcResource.GetD3D12Resource()); + m_Commands += CLCOUNT_COPY; + + SetResourceFenceValue(dstResource, m_CurrentFenceValue, CMDTYPE_WRITE); + SetResourceFenceValue(srcResource, m_CurrentFenceValue, CMDTYPE_READ); + } + + void CommandList::CopySubresource(Resource& dstResource, UINT dstSubResource, UINT x, UINT y, UINT z, Resource& srcResource, UINT srcSubResource, const D3D12_BOX* srcBox) + { + if (srcResource.InitHasBeenDeferred()) + { + srcResource.TryStagingUpload(this); + } + + DX12_COMMANDLIST_TIMER_DETAIL("CopySubresource"); + MaxResourceFenceValue(dstResource, CMDTYPE_ANY); + MaxResourceFenceValue(srcResource, CMDTYPE_WRITE); + + // TODO: if we know early that the resource(s) will be DEST and SOURCE we can begin the barrier early and end it here + D3D12_RESOURCE_STATES prevDstState = dstResource.GetCurrentState(); + D3D12_RESOURCE_STATES prevSrcState = srcResource.GetCurrentState(); + QueueTransitionBarrier(dstResource, D3D12_RESOURCE_STATE_COPY_DEST); + QueueTransitionBarrier(srcResource, D3D12_RESOURCE_STATE_COPY_SOURCE); + FlushBarriers(); + + if (srcResource.GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && dstResource.GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + UINT64 offset = 0; + UINT64 length = srcResource.GetDesc().Width; + + if (srcBox) + { + length = srcBox->right - srcBox->left; + offset = srcBox->left; + } + + m_CommandList->CopyBufferRegion(dstResource.GetD3D12Resource(), x, srcResource.GetD3D12Resource(), offset, length); + m_Commands += CLCOUNT_COPY; + } + else if (srcResource.GetDesc().Dimension != D3D12_RESOURCE_DIMENSION_BUFFER && dstResource.GetDesc().Dimension != D3D12_RESOURCE_DIMENSION_BUFFER) + { + CD3DX12_TEXTURE_COPY_LOCATION src(srcResource.GetD3D12Resource(), srcSubResource); + CD3DX12_TEXTURE_COPY_LOCATION dst(dstResource.GetD3D12Resource(), dstSubResource); + + m_CommandList->CopyTextureRegion(&dst, x, y, z, &src, srcBox); + m_Commands += CLCOUNT_COPY; + } + else if (dstResource.GetDesc().Dimension != D3D12_RESOURCE_DIMENSION_BUFFER) + { + // If this assert trips, you may need to increase MAX_SUBRESOURCES. Just be wary of growing the stack too much. + R_ASSERT4(dstSubResource < CCryDX12DeviceContext::MAX_SUBRESOURCES, "Too many sub resources: (sub ID %d requested, %d allowed)", std::to_string(dstSubResource).c_str(), std::to_string(CCryDX12DeviceContext::MAX_SUBRESOURCES).c_str()); + D3D12_PLACED_SUBRESOURCE_FOOTPRINT layouts[CCryDX12DeviceContext::MAX_SUBRESOURCES]; + + // From our "regular" resource, get the offset and description information for the subresource so we can copy the correct + // part of the buffer resource. We need to get Layouts for subresource 0 through dstSubResource so that the offset is set + // correctly. If we just get the Layout for dstSubResource, it will have an offset of 0. + GetDevice()->GetD3D12Device()->GetCopyableFootprints(&dstResource.GetDesc(), 0, dstSubResource + 1, 0, layouts, nullptr, nullptr, nullptr); + + CD3DX12_TEXTURE_COPY_LOCATION src(srcResource.GetD3D12Resource(), layouts[dstSubResource]); + CD3DX12_TEXTURE_COPY_LOCATION dst(dstResource.GetD3D12Resource(), dstSubResource); + + m_CommandList->CopyTextureRegion(&dst, x, y, z, &src, srcBox); + m_Commands += CLCOUNT_COPY; + } + else if (srcResource.GetDesc().Dimension != D3D12_RESOURCE_DIMENSION_BUFFER) + { + // If this assert trips, you may need to increase MAX_SUBRESOURCES. Just be wary of growing the stack too much. + R_ASSERT4(dstSubResource < CCryDX12DeviceContext::MAX_SUBRESOURCES, "Too many sub resources: (sub ID %d requested, %d allowed)", std::to_string(dstSubResource).c_str(), std::to_string(CCryDX12DeviceContext::MAX_SUBRESOURCES).c_str()); + D3D12_PLACED_SUBRESOURCE_FOOTPRINT layouts[CCryDX12DeviceContext::MAX_SUBRESOURCES]; + + // From our "regular" resource, get the offset and description information for the subresource so we can copy the correct + // part of the buffer resource. We need to get Layouts for subresource 0 through dstSubResource so that the offset is set + // correctly. If we just get the Layout for dstSubResource, it will have an offset of 0. + GetDevice()->GetD3D12Device()->GetCopyableFootprints(&srcResource.GetDesc(), 0, srcSubResource + 1, 0, layouts, nullptr, nullptr, nullptr); + + CD3DX12_TEXTURE_COPY_LOCATION src(srcResource.GetD3D12Resource(), srcSubResource); + CD3DX12_TEXTURE_COPY_LOCATION dst(dstResource.GetD3D12Resource(), layouts[srcSubResource]); + + m_CommandList->CopyTextureRegion(&dst, x, y, z, &src, srcBox); + m_Commands += CLCOUNT_COPY; + } + + SetResourceFenceValue(dstResource, m_CurrentFenceValue, CMDTYPE_WRITE); + SetResourceFenceValue(srcResource, m_CurrentFenceValue, CMDTYPE_READ); + } + + void CommandList::UpdateSubresourceRegion(Resource& resource, UINT subResource, const D3D12_BOX* box, const void* data, UINT rowPitch, UINT slicePitch) + { + if (resource.InitHasBeenDeferred()) + { + resource.TryStagingUpload(this); + } + + DX12_COMMANDLIST_TIMER_DETAIL("UpdateSubresourceRegion"); + MaxResourceFenceValue(resource, CMDTYPE_ANY); + + ID3D12Resource* res12 = resource.GetD3D12Resource(); + const D3D12_RESOURCE_DESC& desc = resource.GetDesc(); + + // Determine temporary upload buffer size (mostly only pow2-alignment of textures) + UINT64 uploadBufferSize; + D3D12_RESOURCE_DESC uploadDesc = desc; + + uploadDesc.Width = box ? box->right - box->left : uploadDesc.Width; + uploadDesc.Height = box ? box->bottom - box->top : uploadDesc.Height; + + GetDevice()->GetD3D12Device()->GetCopyableFootprints(&uploadDesc, subResource, 1, 0, nullptr, nullptr, nullptr, &uploadBufferSize); + + DX12_ASSERT((desc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER) || (box == nullptr), "Box used for buffer update, that's not supported!"); + DX12_ASSERT((desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) || (slicePitch != 0), "Slice-pitch is missing for UpdateSubresourceRegion(), this is a required parameter!"); + ID3D12Resource* uploadBuffer; + + D3D12_SUBRESOURCE_DATA subData; + ZeroMemory(&subData, sizeof(D3D12_SUBRESOURCE_DATA)); + subData.pData = data; + subData.RowPitch = rowPitch; + subData.SlicePitch = slicePitch; + assert(subData.pData != nullptr); + + ResourceStates resourceStates; + + CD3DX12_HEAP_PROPERTIES uploadProperty(D3D12_HEAP_TYPE_UPLOAD); + CD3DX12_RESOURCE_DESC buffer = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize); + + if (S_OK != GetDevice()->CreateOrReuseCommittedResource( + &uploadProperty, + D3D12_HEAP_FLAG_NONE, + &buffer, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&uploadBuffer), + resourceStates)) + { + DX12_ERROR("Could not create intermediate upload buffer!"); + return; + } + + // If it is reused resource, we have to transition the recycled state to new state + R_ASSERT2(resourceStates.m_AnnouncedState == -1, "Recycled resource should not be in split state"); + QueueTransitionBarrier(uploadBuffer, resourceStates.m_CurrentState, D3D12_RESOURCE_STATE_GENERIC_READ); + QueueTransitionBarrier(resource, D3D12_RESOURCE_STATE_COPY_DEST); + FlushBarriers(); + + ::UpdateSubresources<1>(m_CommandList, res12, uploadBuffer, 0, subResource, 1, &subData, box); + m_Commands += CLCOUNT_COPY; + + SetResourceFenceValue(resource, m_CurrentFenceValue, CMDTYPE_WRITE); + + uploadBuffer->SetName(L"UpdateSubresourceRegion"); + GetDevice()->ReleaseLater(uploadBuffer, D3D12_RESOURCE_STATE_GENERIC_READ, static_cast(-1)); + } + + void CommandList::UpdateSubresources(Resource& resource, UINT64 uploadBufferSize, UINT subResources, D3D12_SUBRESOURCE_DATA* subResourceData) + { + if (resource.InitHasBeenDeferred()) + { + resource.TryStagingUpload(this); + } + + DX12_COMMANDLIST_TIMER_DETAIL("UpdateSubresources"); + MaxResourceFenceValue(resource, CMDTYPE_ANY); + + ID3D12Resource* res12 = resource.GetD3D12Resource(); + ID3D12Resource* uploadBuffer = NULL; + ResourceStates resourceStates; + + CD3DX12_HEAP_PROPERTIES uploadProperty(D3D12_HEAP_TYPE_UPLOAD); + CD3DX12_RESOURCE_DESC buffer = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize); + + if (S_OK != GetDevice()->CreateOrReuseCommittedResource( + &uploadProperty, + D3D12_HEAP_FLAG_NONE, + &buffer, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&uploadBuffer), + resourceStates)) + { + DX12_ERROR("Could not create intermediate upload buffer!"); + } + + // If it is reused resource, we have to transition the recycled state to new state + R_ASSERT2(resourceStates.m_AnnouncedState == -1, "Recycled resource should not be in split state"); + QueueTransitionBarrier(uploadBuffer, resourceStates.m_CurrentState, D3D12_RESOURCE_STATE_GENERIC_READ); + QueueTransitionBarrier(resource, D3D12_RESOURCE_STATE_COPY_DEST); + FlushBarriers(); + + ::UpdateSubresources(m_CommandList, res12, uploadBuffer, 0, 0, subResources, subResourceData, nullptr); + m_Commands += CLCOUNT_COPY; + + SetResourceFenceValue(resource, m_CurrentFenceValue, CMDTYPE_WRITE); + + uploadBuffer->SetName(L"UpdateSubresources"); + GetDevice()->ReleaseLater(uploadBuffer, D3D12_RESOURCE_STATE_GENERIC_READ, static_cast(-1)); + } + + void CommandList::DiscardResource(Resource& resource, const D3D12_DISCARD_REGION* pRegion) + { + DX12_COMMANDLIST_TIMER_DETAIL("DiscardResource"); + FlushBarriers(); + MaxResourceFenceValue(resource, CMDTYPE_ANY); + + m_CommandList->DiscardResource(resource.GetD3D12Resource(), pRegion); + m_Commands += CLCOUNT_DISCARD; + } + + void CommandList::QueueTransitionBarrier(Resource& resource, D3D12_RESOURCE_STATES finalState) + { + if (resource.IsOffCard()) + { + if (finalState != D3D12_RESOURCE_STATE_COMMON) + { + finalState = resource.GetRequiredResourceState(); + } + } + + D3D12_RESOURCE_STATES currentState = resource.GetCurrentState(); + D3D12_RESOURCE_STATES announcedState = resource.GetAnnouncedState(); + bool bFinishedSplit = false; + + // Finish a split barrier. + if (announcedState != static_cast(-1)) + { + m_Commands += CLCOUNT_BARRIER; + + //AZ_Printf("DX12", "QueueTransitionBarrier: Split END %p %s -> %s", resource.GetD3D12Resource(), StateToString(currentState), StateToString(announcedState)); + + D3D12_RESOURCE_TRANSITION_BARRIER transition; + transition.pResource = resource.GetD3D12Resource(); + transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + transition.StateBefore = currentState; + transition.StateAfter = announcedState; + m_BarrierCache.EnqueueTransition(m_CommandList, D3D12_RESOURCE_BARRIER_FLAG_END_ONLY, transition); + + resource.SetAnnouncedState(static_cast(-1)); + currentState = announcedState; + resource.SetCurrentState(currentState); + bFinishedSplit = true; + } + + // Now check if we still need to transition to final state. + if (currentState != finalState) + { + //AZ_Printf("DX12", "QueueTransitionBarrier: Transition %p %s -> %s", resource.GetD3D12Resource(), StateToString(currentState), StateToString(finalState)); + + m_Commands += CLCOUNT_BARRIER; + + D3D12_RESOURCE_TRANSITION_BARRIER transition; + transition.pResource = resource.GetD3D12Resource(); + transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + transition.StateBefore = currentState; + transition.StateAfter = finalState; + m_BarrierCache.EnqueueTransition(m_CommandList, D3D12_RESOURCE_BARRIER_FLAG_NONE, transition); + + resource.SetCurrentState(finalState); + } + + // Only need UAV barrier if we didn't do a split transition here. + else if (finalState == D3D12_RESOURCE_STATE_UNORDERED_ACCESS && !bFinishedSplit) + { + QueueUAVBarrier(resource); + } + } + + + void CommandList::QueueTransitionBarrierBegin(Resource& resource, D3D12_RESOURCE_STATES finalState) + { + if (resource.IsOffCard()) + { + if (finalState != D3D12_RESOURCE_STATE_COMMON) + { + finalState = resource.GetRequiredResourceState(); + } + } + + if (resource.GetAnnouncedState() != static_cast(-1)) + { + QueueTransitionBarrier(resource, resource.GetAnnouncedState()); + } + + D3D12_RESOURCE_STATES stateInitial = resource.GetCurrentState(); + D3D12_RESOURCE_STATES stateAnnounced = resource.GetAnnouncedState(); + + if (stateInitial != finalState && stateAnnounced != finalState) + { + m_Commands += CLCOUNT_BARRIER; + + //AZ_Printf("DX12", "QueueTransitionBarrierBegin: Split Barrier BEGIN %p %s -> %s", resource.GetD3D12Resource(), StateToString(stateInitial), StateToString(finalState)); + + D3D12_RESOURCE_TRANSITION_BARRIER transition; + transition.pResource = resource.GetD3D12Resource(); + transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + transition.StateBefore = stateInitial; + transition.StateAfter = finalState; + + m_BarrierCache.EnqueueTransition(m_CommandList, D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY, transition); + + resource.SetAnnouncedState(finalState); + } + } + + void CommandList::QueueUAVBarrier(Resource& resource) + { + m_Commands += CLCOUNT_BARRIER; + + m_BarrierCache.EnqueueUAV(m_CommandList, resource); + } + + void CommandList::FlushBarriers() + { + if (m_BarrierCache.IsFlushNeeded()) + { + DX12_COMMANDLIST_TIMER_DETAIL("FlushBarriers"); + m_BarrierCache.Flush(m_CommandList); + } + } + + void CommandList::QueueTransitionBarrier(ID3D12Resource* resource, D3D12_RESOURCE_STATES stateBefore, D3D12_RESOURCE_STATES stateAfter) + { + if (stateBefore == stateAfter) + return; + + D3D12_RESOURCE_TRANSITION_BARRIER transition; + transition.pResource = resource; + transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + transition.StateBefore = stateBefore; + transition.StateAfter = stateAfter; + + m_BarrierCache.EnqueueTransition(m_CommandList, D3D12_RESOURCE_BARRIER_FLAG_NONE, transition); + } + + CommandListPool::CommandListPool(Device* device, CommandListFenceSet& rCmdFence, int nPoolFenceId) + : m_pDevice(device) + , m_rCmdFences(rCmdFence) + , m_nPoolFenceId(nPoolFenceId) + { +#ifdef DX12_STATS + m_PeakNumCommandListsAllocated = 0; + m_PeakNumCommandListsInFlight = 0; + m_NumWaitsGPU = 0; + m_NumWaitsCPU = 0; +#endif // DX12_STATS + } + + CommandListPool::~CommandListPool() + { + } + + bool CommandListPool::Init(D3D12_COMMAND_LIST_TYPE eType) + { + if (!m_pCmdQueue) + { + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = m_ePoolType = eType; + queueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; + queueDesc.NodeMask = 0; // One GPU? + + ID3D12CommandQueue* pCmdQueue = NULL; + if (S_OK != m_pDevice->GetD3D12Device()->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&pCmdQueue))) + { + DX12_ERROR("Could not create command queue"); + return false; + } + + m_pCmdQueue = pCmdQueue; + pCmdQueue->Release(); + + //EBUS_EVENT(Debug::EventTraceDrillerSetupBus, SetThreadName, EventTrace::GpuDetailThreadId, EventTrace::GpuDetailName); + } + + m_AsyncCommandQueue.Init(this); + +#ifdef DX12_STATS + m_PeakNumCommandListsAllocated = 0; + m_PeakNumCommandListsInFlight = 0; +#endif // DX12_STATS + + return true; + } + + void CommandListPool::ScheduleCommandLists() + { + // Remove finished command-lists from the head of the live-list + while (m_LiveCommandLists.size()) + { + _smart_ptr pCmdList = m_LiveCommandLists.front(); + + // free -> complete -> submitted -> finished -> clearing -> free + if (pCmdList->IsFinished() && !pCmdList->IsClearing()) + { + m_LiveCommandLists.pop_front(); + m_BusyCommandLists.push_back(pCmdList); + + pCmdList->Clear(); + } + else + { + break; + } + } + + // Submit completed but not yet submitted command-lists from the head of the live-list + for (uint32_t t = 0; t < m_LiveCommandLists.size(); ++t) + { + _smart_ptr pCmdList = m_LiveCommandLists[t]; + + if (pCmdList->IsScheduled() && !pCmdList->IsSubmitted()) + { + pCmdList->Submit(); + } + + if (!pCmdList->IsSubmitted()) + { + break; + } + } + + // Remove cleared/deallocated command-lists from the head of the busy-list + while (m_BusyCommandLists.size()) + { + _smart_ptr pCmdList = m_BusyCommandLists.front(); + + // free -> complete -> submitted -> finished -> clearing -> free + if (pCmdList->IsFree()) + { + m_BusyCommandLists.pop_front(); + m_FreeCommandLists.push_back(pCmdList); + } + else + { + break; + } + } + } + + void CommandListPool::CreateOrReuseCommandList(_smart_ptr& result) + { + if (m_FreeCommandLists.empty()) + { + result = new CommandList(*this); + } + else + { + result = m_FreeCommandLists.front(); + + m_FreeCommandLists.pop_front(); + } + + // Increment fence value on allocation, this has the effect that + // acquired CommandLists need to be submitted in-order to prevent + // dead-locking + SetCurrentFenceValue(GetCurrentFenceValue() + 1); + + result->Init(GetCurrentFenceValue()); + m_LiveCommandLists.push_back(result); + +#ifdef DX12_STATS + m_PeakNumCommandListsAllocated = std::max(m_PeakNumCommandListsAllocated, m_LiveCommandLists.size() + m_BusyCommandLists.size() + m_FreeCommandLists.size()); + m_PeakNumCommandListsInFlight = std::max(m_PeakNumCommandListsInFlight, m_LiveCommandLists.size()); +#endif // DX12_STATS + } + + void CommandListPool::AcquireCommandList(_smart_ptr& result) + { + static CryCriticalSectionNonRecursive csThreadSafeScope; + CryAutoLock lThreadSafeScope(csThreadSafeScope); + + ScheduleCommandLists(); + + CreateOrReuseCommandList(result); + } + + void CommandListPool::ForfeitCommandList(_smart_ptr& result, bool bWait) + { + static CryCriticalSectionNonRecursive csThreadSafeScope; + CryAutoLock lThreadSafeScope(csThreadSafeScope); + _smart_ptr pWaitable = result; + + DX12_ASSERT(result->IsCompleted(), "It's not possible to forfeit an unclosed command list!"); + result->Schedule(); + result = nullptr; + + ScheduleCommandLists(); + + if (bWait) + { + pWaitable->WaitForFinishOnCPU(); + } + } + + void CommandListPool::AcquireCommandLists(uint32_t numCLs, _smart_ptr* results) + { + static CryCriticalSectionNonRecursive csThreadSafeScope; + CryAutoLock lThreadSafeScope(csThreadSafeScope); + + ScheduleCommandLists(); + + for (uint32_t i = 0; i < numCLs; ++i) + { + CreateOrReuseCommandList(results[i]); + } + } + + void CommandListPool::ForfeitCommandLists(uint32_t numCLs, _smart_ptr* results, bool bWait) + { + static CryCriticalSectionNonRecursive csThreadSafeScope; + CryAutoLock lThreadSafeScope(csThreadSafeScope); + _smart_ptr pWaitable = results[numCLs - 1]; + + for (uint32_t i = 0; i < numCLs; ++i) + { + DX12_ASSERT(results[i]->IsCompleted(), "It's not possible to forfeit an unclosed command list!"); + results[i]->Schedule(); + results[i] = nullptr; + } + + ScheduleCommandLists(); + + if (bWait) + { + pWaitable->WaitForFinishOnCPU(); + } + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12CommandList.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12CommandList.hpp new file mode 100644 index 00000000000..0f680f54dac --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12CommandList.hpp @@ -0,0 +1,630 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once + +#include "DX12PSO.hpp" +#include "DX12DescriptorHeap.hpp" +#include "DX12View.hpp" +#include "DX12SamplerState.hpp" +#include "DX12AsyncCommandQueue.hpp" +#include "DX12Resource.hpp" +#include "DX12ResourceBarrierCache.h" +#include "DX12TimerHeap.h" + +#include +#include + +namespace DX12 +{ + class CommandList; + + class CommandListPool + { + public: + CommandListPool(Device* device, CommandListFenceSet& rCmdFence, int nPoolFenceId); + ~CommandListPool(); + + bool Init(D3D12_COMMAND_LIST_TYPE eType = D3D12_COMMAND_LIST_TYPE_DIRECT); + void AcquireCommandList(_smart_ptr & result); + void ForfeitCommandList(_smart_ptr & result, bool bWait = false); + void AcquireCommandLists(uint32_t numCLs, _smart_ptr * results); + void ForfeitCommandLists(uint32_t numCLs, _smart_ptr * results, bool bWait = false); + + inline ID3D12CommandQueue* GetD3D12CommandQueue() const + { + return m_pCmdQueue; + } + + inline D3D12_COMMAND_LIST_TYPE GetD3D12QueueType() const + { + return m_ePoolType; + } + + inline DX12::AsyncCommandQueue& GetAsyncCommandQueue() + { + return m_AsyncCommandQueue; + } + + inline Device* GetDevice() const + { + return m_pDevice; + } + + inline CommandListFenceSet& GetFences() + { + return m_rCmdFences; + } + + inline ID3D12Fence** GetD3D12Fences() const + { + return m_rCmdFences.GetD3D12Fences(); + } + + inline ID3D12Fence* GetD3D12Fence() const + { + return m_rCmdFences.GetD3D12Fence(m_nPoolFenceId); + } + + inline int GetFenceID() const + { + return m_nPoolFenceId; + } + + inline void SetSubmittedFenceValue(const UINT64 fenceValue) + { + return m_rCmdFences.SetSubmittedValue(fenceValue, m_nPoolFenceId); + } + + inline UINT64 GetSubmittedFenceValue() const + { + return m_rCmdFences.GetSubmittedValue(m_nPoolFenceId); + } + + private: + inline void SetCurrentFenceValue(const UINT64 fenceValue) + { + return m_rCmdFences.SetCurrentValue(fenceValue, m_nPoolFenceId); + } + + public: + inline UINT64 GetLastCompletedFenceValue() const + { + return m_rCmdFences.GetLastCompletedFenceValue(m_nPoolFenceId); + } + + inline UINT64 GetCurrentFenceValue() const + { + return m_rCmdFences.GetCurrentValue(m_nPoolFenceId); + } + + inline void WaitForFenceOnGPU(const std::atomic (&fenceValues)[CMDQUEUE_NUM]) + { + // The pool which waits for the fence can be omitted (in-order-execution) + UINT64 fenceValuesMasked[CMDQUEUE_NUM]; + + fenceValuesMasked[CMDQUEUE_COPY ] = fenceValues[CMDQUEUE_COPY ]; + fenceValuesMasked[CMDQUEUE_GRAPHICS] = fenceValues[CMDQUEUE_GRAPHICS]; + fenceValuesMasked[m_nPoolFenceId ] = 0; + + if (!m_rCmdFences.IsCompleted(fenceValuesMasked)) + { + DX12_LOG("Waiting for GPU fences (type: %d) [%d,%d] -> [%d,%d]", + m_nPoolFenceId, + m_rCmdFences.GetD3D12Fence(CMDQUEUE_COPY)->GetCompletedValue(), + m_rCmdFences.GetD3D12Fence(CMDQUEUE_GRAPHICS)->GetCompletedValue(), + static_cast(fenceValues[CMDQUEUE_COPY ]), + static_cast(fenceValues[CMDQUEUE_GRAPHICS])); +#ifdef DX12_STATS + m_NumWaitsGPU += 2; +#endif // DX12_STATS + + m_AsyncCommandQueue.Wait(m_rCmdFences.GetD3D12Fences(), fenceValuesMasked); + } + } + + inline void WaitForFenceOnGPU(const UINT64 fenceValue, const int id) + { + if (!m_rCmdFences.IsCompleted(fenceValue, id)) + { + DX12_LOG("Waiting for GPU fence %d -> %d", m_rCmdFences.GetD3D12Fence(id)->GetCompletedValue(), fenceValue); + +#ifdef DX12_STATS + m_NumWaitsGPU++; +#endif // DX12_STATS + + m_AsyncCommandQueue.Wait(m_rCmdFences.GetD3D12Fence(id), fenceValue); + } + } + + inline void WaitForFenceOnGPU(const UINT64 fenceValue) + { + return WaitForFenceOnGPU(fenceValue, m_nPoolFenceId); + } + + inline void WaitForFenceOnCPU(const std::atomic (&fenceValues)[CMDQUEUE_NUM]) const + { + + UINT64 fenceValuesCopied[CMDQUEUE_NUM]; + + fenceValuesCopied[CMDQUEUE_COPY ] = fenceValues[CMDQUEUE_COPY ]; + fenceValuesCopied[CMDQUEUE_GRAPHICS] = fenceValues[CMDQUEUE_GRAPHICS]; + + if (!m_rCmdFences.IsCompleted(fenceValuesCopied)) + { +#ifdef DX12_STATS + m_NumWaitsCPU += 2; +#endif // DX12_STATS + + m_rCmdFences.WaitForFence(fenceValuesCopied); + } + } + + inline void WaitForFenceOnCPU(const UINT64 fenceValue, const int id) const + { + if (!m_rCmdFences.IsCompleted(fenceValue, id)) + { +#ifdef DX12_STATS + m_NumWaitsCPU++; +#endif // DX12_STATS + + m_rCmdFences.WaitForFence(fenceValue, id); + } + } + + inline void WaitForFenceOnCPU(const UINT64 fenceValue) const + { + return WaitForFenceOnCPU(fenceValue, m_nPoolFenceId); + } + + inline bool IsCompleted(const std::atomic (&fenceValues)[CMDQUEUE_NUM]) const + { + // The pool which checks for the fence can be omitted (in-order-execution) + UINT64 fenceValuesMasked[CMDQUEUE_NUM]; + + fenceValuesMasked[CMDQUEUE_COPY ] = fenceValues[CMDQUEUE_COPY ]; + fenceValuesMasked[CMDQUEUE_GRAPHICS] = fenceValues[CMDQUEUE_GRAPHICS]; + fenceValuesMasked[m_nPoolFenceId ] = 0; + + return m_rCmdFences.IsCompleted(fenceValuesMasked); + } + + inline bool IsCompleted(const UINT64 fenceValue, const int id) const + { + return m_rCmdFences.IsCompleted(fenceValue, id); + } + + inline bool IsCompleted(const UINT64 fenceValue) const + { + return IsCompleted(fenceValue, m_nPoolFenceId); + } + + private: + void ScheduleCommandLists(); + void CreateOrReuseCommandList(_smart_ptr & result); + + Device* m_pDevice; + CommandListFenceSet& m_rCmdFences; + int m_nPoolFenceId; + D3D12_COMMAND_LIST_TYPE m_ePoolType; + + typedef std::deque<_smart_ptr> TCommandLists; + TCommandLists m_LiveCommandLists; + TCommandLists m_BusyCommandLists; + TCommandLists m_FreeCommandLists; + + _smart_ptr m_pCmdQueue; + DX12::AsyncCommandQueue m_AsyncCommandQueue; + +#ifdef DX12_STATS + size_t m_NumWaitsGPU; + mutable size_t m_NumWaitsCPU; + size_t m_PeakNumCommandListsAllocated; + size_t m_PeakNumCommandListsInFlight; +#endif // DX12_STATS + }; + + class CommandList + : public DeviceObject + { + friend class CommandListPool; + + public: + virtual ~CommandList(); + + bool Init(UINT64 currentFenceValue); + bool Reset(); + + inline ID3D12GraphicsCommandList* GetD3D12CommandList() const + { + return m_CommandList; + } + inline D3D12_COMMAND_LIST_TYPE GetD3D12ListType() const + { + return m_eListType; + } + inline ID3D12CommandAllocator* GetD3D12CommandAllocator() const + { + return m_pCmdAllocator; + } + inline ID3D12CommandQueue* GetD3D12CommandQueue() const + { + return m_pCmdQueue; + } + inline CommandListPool& GetCommandListPool() const + { + return m_rPool; + } + + // Stage 1 + inline bool IsFree() const + { + return m_State == CLSTATE_FREE; + } + + // Stage 2 + void Begin(); + inline bool IsUtilized() const + { +#define CLCOUNT_DRAW 1 +#define CLCOUNT_DISPATCH 1 +#define CLCOUNT_COPY 1 +#define CLCOUNT_CLEAR 1 +#define CLCOUNT_DISCARD 1 +#define CLCOUNT_BARRIER 1 +#define CLCOUNT_QUERY 1 +#define CLCOUNT_QUERY_TIMESTAMP 0 +#define CLCOUNT_RESOLVE 1 +#define CLCOUNT_SETIO 0 +#define CLCOUNT_SETSTATE 0 + + return m_Commands > 0; + } + + void End(); + inline bool IsCompleted() const + { + return m_State >= CLSTATE_COMPLETED; + } + + void Schedule(); + inline bool IsScheduled() const + { + return m_State == CLSTATE_SCHEDULED; + } + + // Stage 3 + UINT64 SignalFenceOnGPU() + { + DX12_LOG("Signaling fence value on GPU (%d) : %d", m_rPool.GetFenceID(), m_CurrentFenceValue); + m_rPool.GetAsyncCommandQueue().Signal(m_rPool.GetD3D12Fence(), m_CurrentFenceValue); + return m_CurrentFenceValue; + } + + UINT64 SignalFenceOnCPU() + { + DX12_LOG("Signaling fence value on CPU: %d", m_CurrentFenceValue); + m_rPool.GetD3D12Fence()->Signal(m_CurrentFenceValue); + return m_CurrentFenceValue; + } + + void Submit(); + inline bool IsSubmitted() const + { + return m_State >= CLSTATE_SUBMITTED; + } + + // Stage 4 + void WaitForFinishOnGPU() + { + DX12_ASSERT(m_State == CLSTATE_SUBMITTED, "GPU fence waits for itself to be complete: deadlock imminent!"); + m_rPool.WaitForFenceOnGPU(m_CurrentFenceValue); + } + + void WaitForFinishOnCPU() const + { + DX12_ASSERT(m_State == CLSTATE_SUBMITTED, "CPU fence waits for itself to be complete: deadlock imminent!"); + m_rPool.WaitForFenceOnCPU(m_CurrentFenceValue); + } + + inline bool IsFinished() const + { + if ((m_State == CLSTATE_SUBMITTED) && m_rPool.IsCompleted(m_CurrentFenceValue)) + { + m_State = CLSTATE_FINISHED; + } + + return m_State == CLSTATE_FINISHED; + } + + inline UINT64 GetCurrentFenceValue() const + { + return m_CurrentFenceValue; + } + + // Stage 5 + void Clear(); + inline bool IsClearing() const + { + return m_State == CLSTATE_CLEARING; + } + + void ClearState() { + if (m_CurrentPipelineState != NULL) + { + m_CommandList->ClearState(m_CurrentPipelineState->GetD3D12PipelineState()); + } + } + + void SetPipelineState(const PipelineState* pso); + void SetRootSignature(CommandMode commandMode, const RootSignature* rootSignature); + + void QueueUAVBarrier(Resource& resource); + + void QueueTransitionBarrier(Resource& resource, D3D12_RESOURCE_STATES desiredState); + + void QueueTransitionBarrierBegin(Resource& resource, D3D12_RESOURCE_STATES desiredState); + + void FlushBarriers(); + + // Collect the highest fenceValues of all given Resource to wait before the command-list is finally submitted + inline void MaxResourceFenceValue(Resource& resource, const int type) + { + resource.MaxFenceValues(m_UsedFenceValues, type); + } + + // Mark resource with desired fence value, returns the previous fence value + inline UINT64 SetResourceFenceValue(Resource& resource, const UINT64 fenceValue, const int type) const + { + return resource.SetFenceValue(fenceValue, m_rPool.GetFenceID(), type); + } + + inline void TrackResourceUsage(Resource& resource, D3D12_RESOURCE_STATES stateUsage, int cmdBlocker = CMDTYPE_WRITE, int cmdUsage = CMDTYPE_READ) + { + resource.TryStagingUpload(this); + MaxResourceFenceValue(resource, cmdBlocker); + QueueTransitionBarrier(resource, stateUsage); + SetResourceFenceValue(resource, m_CurrentFenceValue, cmdUsage); + } + + inline void TrackResourceIBVUsage(Resource& resource) { TrackResourceUsage(resource, D3D12_RESOURCE_STATE_INDEX_BUFFER, CMDTYPE_WRITE, CMDTYPE_READ); } + inline void TrackResourceVBVUsage(Resource& resource) { TrackResourceUsage(resource, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, CMDTYPE_WRITE, CMDTYPE_READ); } + inline void TrackResourceCBVUsage(Resource& resource) { TrackResourceUsage(resource, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, CMDTYPE_WRITE, CMDTYPE_READ); } + inline void TrackResourceSRVUsage(Resource& resource) { TrackResourceUsage(resource, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, CMDTYPE_WRITE, CMDTYPE_READ); } + inline void TrackResourceUAVUsage(Resource& resource) { TrackResourceUsage(resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, CMDTYPE_ANY, CMDTYPE_ANY); } + inline void TrackResourceDSVUsage(Resource& resource) { TrackResourceUsage(resource, D3D12_RESOURCE_STATE_DEPTH_WRITE, CMDTYPE_ANY, CMDTYPE_WRITE); } + inline void TrackResourceDRVUsage(Resource& resource) { TrackResourceUsage(resource, D3D12_RESOURCE_STATE_DEPTH_READ, CMDTYPE_WRITE, CMDTYPE_READ); } + inline void TrackResourceRTVUsage(Resource& resource) { TrackResourceUsage(resource, D3D12_RESOURCE_STATE_RENDER_TARGET, CMDTYPE_ANY, CMDTYPE_WRITE); } + + bool IsFull(size_t numResources, size_t numSamplers, size_t numRendertargets, size_t numDepthStencils) const; + bool IsUsedByOutputViews(const Resource& res) const; + + inline void IncrementInputCursors(size_t numResources, size_t numSamplers) + { + GetResourceHeap().IncrementCursor(numResources); + GetSamplerHeap().IncrementCursor(numSamplers); + } + + inline void IncrementOutputCursors() + { + GetRenderTargetHeap().IncrementCursor(m_CurrentNumRTVs); + if (m_pDSV) + { + GetDepthStencilHeap().IncrementCursor(); + } + } + + void WriteShaderResourceDescriptor(const ResourceView* resourceView, INT descriptorOffset); + void WriteUnorderedAccessDescriptor(const ResourceView* resourceView, INT descriptorOffset); + void WriteConstantBufferDescriptor(const ResourceView* resourceView, INT descriptorOffset, UINT byteOffset, UINT byteCount); + void WriteSamplerStateDescriptor(const SamplerState* state, INT descriptorOffset); + + void BindVertexBufferView(const ResourceView&view, INT offset, const _range_t&bindRange, UINT bindStride, D3D12_VERTEX_BUFFER_VIEW (&heap)[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]); + inline void BindVertexBufferView(const ResourceView& view, INT offset, const _range_t& bindRange, UINT bindStride) + { + BindVertexBufferView(view, offset, bindRange, bindStride, m_VertexBufferHeap); + } + + void SetConstantBufferView(CommandMode commandMode, UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation); + void Set32BitConstants(CommandMode commandMode, UINT RootParameterIndex, UINT Num32BitValuesToSet, const void* pSrcData, UINT DestOffsetIn32BitValues); + void SetDescriptorTable(CommandMode commandMode, UINT RootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor); + + void SetDescriptorTables(CommandMode commandMode, D3D12_DESCRIPTOR_HEAP_TYPE eType); + + void ClearVertexBufferHeap(UINT num); + void SetVertexBufferHeap(UINT num); + void BindAndSetIndexBufferView(const ResourceView& view, DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN, UINT offset = 0); + + void SetResourceAndSamplerStateHeaps(); + void BindAndSetOutputViews(INT numRTVs, const ResourceView** rtv, const ResourceView* dsv); + + void ClearDepthStencilView(const ResourceView& view, D3D12_CLEAR_FLAGS clearFlags, float depthValue, UINT stencilValue, UINT NumRects = 0U, const D3D12_RECT* pRect = nullptr); + void ClearRenderTargetView(const ResourceView& view, const FLOAT rgba[4], UINT NumRects = 0U, const D3D12_RECT* pRect = nullptr); + void ClearUnorderedAccessView(const ResourceView& view, const UINT rgba[4], UINT NumRects = 0U, const D3D12_RECT* pRect = nullptr); + void ClearUnorderedAccessView(const ResourceView& view, const FLOAT rgba[4], UINT NumRects = 0U, const D3D12_RECT* pRect = nullptr); + void ClearView(const ResourceView& view, const FLOAT rgba[4], UINT NumRects = 0U, const D3D12_RECT* pRect = nullptr); + + void CopyResource(Resource& pDstResource, Resource& pSrcResource); + void CopySubresource(Resource& pDestResource, UINT destSubResource, UINT x, UINT y, UINT z, Resource& pSrcResource, UINT srcSubResource, const D3D12_BOX* srcBox); + void UpdateSubresourceRegion(Resource& resource, UINT subResource, const D3D12_BOX* box, const void* data, UINT rowPitch, UINT depthPitch); + void UpdateSubresources(Resource& rResource, UINT64 uploadBufferSize, UINT subResources, D3D12_SUBRESOURCE_DATA* subResourceData); + void DiscardResource(Resource& resource, const D3D12_DISCARD_REGION* pRegion); + + void PresentRenderTargetView(SwapChain* pDX12SwapChain); + + inline void DrawInstanced(UINT vertexCountPerInstance, UINT instanceCount, UINT startVertexLocation, UINT startInstanceLocation) + { + DX12_COMMANDLIST_TIMER_DETAIL("DrawInstanced"); +#ifdef DX12_STATS + m_NumDraws++; +#endif // DX12_STATS + + FlushBarriers(); + m_CommandList->DrawInstanced(vertexCountPerInstance, instanceCount, startVertexLocation, startInstanceLocation); + m_Commands += CLCOUNT_DRAW; + } + + inline void DrawIndexedInstanced(UINT indexCountPerInstance, UINT instanceCount, UINT startIndexLocation, UINT baseVertexLocation, UINT startInstanceLocation) + { + DX12_COMMANDLIST_TIMER_DETAIL("DrawIndexedInstanced"); +#ifdef DX12_STATS + m_NumDraws++; +#endif // DX12_STATS + + FlushBarriers(); + m_CommandList->DrawIndexedInstanced(indexCountPerInstance, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); + m_Commands += CLCOUNT_DRAW; + } + + inline void Dispatch(UINT ThreadGroupCountX, UINT ThreadGroupCountY, UINT ThreadGroupCountZ) + { + DX12_COMMANDLIST_TIMER_DETAIL("Dispatch"); +#ifdef DX12_STATS + m_NumDraws++; +#endif // DX12_STATS + + FlushBarriers(); + m_CommandList->Dispatch(ThreadGroupCountX, ThreadGroupCountY, ThreadGroupCountZ); + m_Commands += CLCOUNT_DISPATCH; + } + + inline void SetPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY topo) + { + m_CommandList->IASetPrimitiveTopology(topo); + m_Commands += CLCOUNT_SETIO; + } + + inline void SetViewports(UINT NumViewports, const D3D12_VIEWPORT* pViewports) + { + m_CommandList->RSSetViewports(NumViewports, pViewports); + m_Commands += CLCOUNT_SETSTATE; + } + + inline void SetScissorRects(UINT NumRects, const D3D12_RECT* pRects) + { + m_CommandList->RSSetScissorRects(NumRects, pRects); + m_Commands += CLCOUNT_SETSTATE; + } + + inline void SetStencilRef(UINT Ref) + { + m_CommandList->OMSetStencilRef(Ref); + m_Commands += CLCOUNT_SETSTATE; + } + + inline void BeginQuery(QueryHeap& queryHeap, D3D12_QUERY_TYPE Type, UINT Index) + { + m_CommandList->BeginQuery(queryHeap.GetD3D12QueryHeap(), Type, Index); + m_Commands += Type == D3D12_QUERY_TYPE_TIMESTAMP ? CLCOUNT_QUERY_TIMESTAMP : CLCOUNT_QUERY; + } + + inline void EndQuery(QueryHeap& queryHeap, D3D12_QUERY_TYPE Type, UINT Index) + { + m_CommandList->EndQuery(queryHeap.GetD3D12QueryHeap(), Type, Index); + m_Commands += Type == D3D12_QUERY_TYPE_TIMESTAMP ? CLCOUNT_QUERY_TIMESTAMP : CLCOUNT_QUERY; + } + + inline void ResolveQueryData(QueryHeap& queryHeap, D3D12_QUERY_TYPE Type, + _In_ UINT StartIndex, + _In_ UINT NumQueries, + _In_ ID3D12Resource* pDestinationBuffer, + _In_ UINT64 AlignedDestinationBufferOffset) + { + m_CommandList->ResolveQueryData(queryHeap.GetD3D12QueryHeap(), Type, StartIndex, NumQueries, pDestinationBuffer, AlignedDestinationBufferOffset); + m_Commands += CLCOUNT_RESOLVE; + } + + private: + CommandList(CommandListPool& pPool); + CommandListPool& m_rPool; + + void ResetStateTracking(CommandMode commandMode); + void BindDepthStencilView(const ResourceView& dsv); + void BindRenderTargetView(const ResourceView& rtv); + + void QueueTransitionBarrier(ID3D12Resource* resource, D3D12_RESOURCE_STATES stateBefore, D3D12_RESOURCE_STATES stateAfter); + void SubmitTimers(); + + ID3D12Device* m_pD3D12Device; + _smart_ptr m_CommandList; + _smart_ptr m_pCmdAllocator; + _smart_ptr m_pCmdQueue; + std::atomic m_UsedFenceValues[CMDTYPE_NUM][CMDQUEUE_NUM]; + + ResourceBarrierCache m_BarrierCache; + + // Only used by IsUsedByOutputViews() + const ResourceView* m_pDSV; + const ResourceView* m_pRTV[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT]; + INT m_CurrentNumRTVs; + + UINT64 m_CurrentFenceValue; + D3D12_COMMAND_LIST_TYPE m_eListType; + + DescriptorBlock m_DescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES]; + + inline DescriptorBlock& GetResourceHeap () { return m_DescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]; } + inline DescriptorBlock& GetSamplerHeap () { return m_DescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER]; } + inline DescriptorBlock& GetRenderTargetHeap() { return m_DescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_RTV]; } + inline DescriptorBlock& GetDepthStencilHeap() { return m_DescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_DSV]; } + + inline const DescriptorBlock& GetResourceHeap () const { return m_DescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]; } + inline const DescriptorBlock& GetSamplerHeap () const { return m_DescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER]; } + inline const DescriptorBlock& GetRenderTargetHeap() const { return m_DescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_RTV]; } + inline const DescriptorBlock& GetDepthStencilHeap() const { return m_DescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_DSV]; } + + UINT m_CurrentNumVertexBuffers; + D3D12_VERTEX_BUFFER_VIEW m_VertexBufferHeap[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; + + static const u32 RootParameterCountMax = 16; + struct RootParameter + { + union + { + D3D12_GPU_VIRTUAL_ADDRESS gpuAddress; + D3D12_GPU_DESCRIPTOR_HANDLE descriptorHandle; + }; + }; + + RootParameter m_CurrentRootParameters[CommandModeCount][RootParameterCountMax]; + const PipelineState* m_CurrentPipelineState; + const RootSignature* m_CurrentRootSignature[CommandModeCount]; + + UINT m_Commands; + mutable enum + { + CLSTATE_FREE, + CLSTATE_STARTED, + CLSTATE_UTILIZED, + CLSTATE_COMPLETED, + CLSTATE_SCHEDULED, + CLSTATE_SUBMITTED, + CLSTATE_FINISHED, + CLSTATE_CLEARING + } + m_State; + + UINT m_nodeMask; + +#ifdef DX12_STATS + size_t m_NumDraws; + size_t m_NumWaitsGPU; + size_t m_NumWaitsCPU; +#endif // DX12_STATS + +#if DX12_GPU_PROFILE_MODE != DX12_GPU_PROFILE_MODE_OFF + TimerHeap m_Timers; + TimerHandle m_TimerHandle; + static const u32 TimerCountMax = 2048; +#endif + }; +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12CommandListFence.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12CommandListFence.cpp new file mode 100644 index 00000000000..229dcec12b8 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12CommandListFence.cpp @@ -0,0 +1,155 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12CommandListFence.hpp" +#include "DX12Device.hpp" + +namespace DX12 +{ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + CommandListFence::CommandListFence(Device* device) + : m_pDevice(device) + , m_LastCompletedValue(0) + , m_CurrentValue(0) + { + } + + //--------------------------------------------------------------------------------------------------------------------- + CommandListFence::~CommandListFence() + { + m_pFence->Release(); + CloseHandle(m_FenceEvent); + } + + //--------------------------------------------------------------------------------------------------------------------- + bool CommandListFence::Init() + { + ID3D12Fence* fence = NULL; + if (S_OK != m_pDevice->GetD3D12Device()->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence))) + { + DX12_ERROR("Could not create fence object!"); + return false; + } + + m_pFence = fence; + m_pFence->Signal(m_LastCompletedValue); + m_FenceEvent = CreateEventEx(NULL, FALSE, FALSE, EVENT_ALL_ACCESS); + + return true; + } + + void CommandListFence::WaitForFence(u64 fenceValue) + { + if (!IsCompleted(fenceValue)) + { + DX12_LOG("Waiting CPU for fence %d -> %d", m_pFence->GetCompletedValue(), fenceValue); + { + m_pFence->SetEventOnCompletion(fenceValue, m_FenceEvent); + + WaitForSingleObject(m_FenceEvent, INFINITE); + } + DX12_LOG("Completed fence value: %d", m_pFence->GetCompletedValue()); + + AdvanceCompletion(); + } + } + + //--------------------------------------------------------------------------------------------------------------------- + CommandListFenceSet::CommandListFenceSet(Device* device) + : m_pDevice(device) + { + m_LastCompletedValues[CMDQUEUE_COPY ] = + m_LastCompletedValues[CMDQUEUE_GRAPHICS] = 0; + m_SubmittedValues[CMDQUEUE_COPY] = + m_SubmittedValues[CMDQUEUE_GRAPHICS] = 0; + m_CurrentValues[CMDQUEUE_COPY ] = + m_CurrentValues[CMDQUEUE_GRAPHICS] = 0; + } + + //--------------------------------------------------------------------------------------------------------------------- + CommandListFenceSet::~CommandListFenceSet() + { + for (int i = 0; i < CMDQUEUE_NUM; ++i) + { + m_pFences[i]->Release(); + + CloseHandle(m_FenceEvents[i]); + } + } + + //--------------------------------------------------------------------------------------------------------------------- + bool CommandListFenceSet::Init() + { + for (int i = 0; i < CMDQUEUE_NUM; ++i) + { + ID3D12Fence* fence = NULL; + if (S_OK != m_pDevice->GetD3D12Device()->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence))) + { + DX12_ERROR("Could not create fence object!"); + return false; + } + + m_pFences[i] = fence; + m_pFences[i]->Signal(m_LastCompletedValues[i]); + m_FenceEvents[i] = CreateEventEx(NULL, FALSE, FALSE, EVENT_ALL_ACCESS); + } + + return true; + } + + void CommandListFenceSet::WaitForFence(const u64 fenceValue, const int id) const + { + DX12_LOG("Waiting CPU for fence %d -> %d", m_pFences[id]->GetCompletedValue(), fenceValue); + + { + m_pFences[id]->SetEventOnCompletion(fenceValue, m_FenceEvents[id]); + + WaitForSingleObject(m_FenceEvents[id], INFINITE); + } + + DX12_LOG("Completed fence value: %d", m_pFences[id]->GetCompletedValue()); + + AdvanceCompletion(id); + } + + void CommandListFenceSet::WaitForFence(const u64 (&fenceValues)[CMDQUEUE_NUM]) const + { + // TODO: the pool which waits for the fence can be omitted (in-order-execution) + DX12_LOG("Waiting for GPU fences [%d,%d] -> [%d,%d]", + m_pFences[CMDQUEUE_COPY ]->GetCompletedValue(), + m_pFences[CMDQUEUE_GRAPHICS]->GetCompletedValue(), + fenceValues[CMDQUEUE_COPY ], + fenceValues[CMDQUEUE_GRAPHICS]); + + { + // NOTE: event does ONLY trigger when the value has been set (it'll lock when trying with 0) + int numObjects = 0; + for (int id = 0; id < CMDQUEUE_NUM; ++id) + { + if (fenceValues[id] && (m_LastCompletedValues[id] < fenceValues[id])) + { + m_pFences[id]->SetEventOnCompletion(fenceValues[id], m_FenceEvents[numObjects++]); + } + } + + WaitForMultipleObjects(numObjects, m_FenceEvents, true, INFINITE); + } + + DX12_LOG("Completed GPU fences [%d,%d]", + m_pFences[CMDQUEUE_COPY ]->GetCompletedValue(), + m_pFences[CMDQUEUE_GRAPHICS]->GetCompletedValue()); + + AdvanceCompletion(); + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12CommandListFence.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12CommandListFence.hpp new file mode 100644 index 00000000000..40827c3ab93 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12CommandListFence.hpp @@ -0,0 +1,274 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once + +#include "DX12.hpp" + +#define CMDQUEUE_GRAPHICS 0 +#define CMDQUEUE_COPY 1 +#define CMDQUEUE_NUM 2 + +#define CMDTYPE_READ 0 +#define CMDTYPE_WRITE 1 +#define CMDTYPE_ANY 2 +#define CMDTYPE_NUM 3 + +namespace std +{ + inline u64 (& max(const u64 (&a)[CMDQUEUE_NUM], const u64 (&b)[CMDQUEUE_NUM], u64 (&c)[CMDQUEUE_NUM]))[CMDQUEUE_NUM] + { + c[CMDQUEUE_COPY ] = max(a[CMDQUEUE_COPY ], b[CMDQUEUE_COPY ]); + c[CMDQUEUE_GRAPHICS] = max(a[CMDQUEUE_GRAPHICS], b[CMDQUEUE_GRAPHICS]); + + return c; + } +} + +namespace DX12 +{ + inline u64 MaxFenceValue(std::atomic& a, const u64& b) + { + u64 utilizedValue = b; + u64 previousValue = a; + while (previousValue < utilizedValue && + !a.compare_exchange_weak(previousValue, utilizedValue)) + { + ; + } + + return previousValue; + } + + inline u64 (& MaxFenceValues(const std::atomic (&a)[CMDQUEUE_NUM], const std::atomic (&b)[CMDQUEUE_NUM], u64 (&c)[CMDQUEUE_NUM]))[CMDQUEUE_NUM] + { + c[CMDQUEUE_COPY ] = std::max(a[CMDQUEUE_COPY ], b[CMDQUEUE_COPY ]); + c[CMDQUEUE_GRAPHICS] = std::max(a[CMDQUEUE_GRAPHICS], b[CMDQUEUE_GRAPHICS]); + + return c; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + class CommandListFence + { + public: + CommandListFence(Device* device); + ~CommandListFence(); + + bool Init(); + + inline ID3D12Fence* GetFence() const + { + return m_pFence; + } + + inline u64 GetCurrentValue() const + { + return m_CurrentValue; + } + + inline void SetCurrentValue(u64 fenceValue) + { +#ifdef DX12_IN_ORDER_ACQUIRATION + DX12_ASSERT(m_CurrentValue <= fenceValue, "Setting new fence value which is older than the current!"); + // We do not allow smaller fences being submitted, and fences always submit in-order, no max() neccessary + m_CurrentValue = fenceValue; +#else + // CLs may submit in any order. Is it higher than last known completed fence? If so, update it! + MaxFenceValue(m_CurrentValue, fenceValue); +#endif // !NDEBUG + } + + inline bool IsCompleted(u64 fenceValue) const + { + // Check against last known completed value first to avoid unnecessary fence read + return + (m_LastCompletedValue >= fenceValue) || (AdvanceCompletion() >= fenceValue); + } + + void WaitForFence(u64 fenceValue); + + inline u64 AdvanceCompletion() const + { + // Check current completed fence + u64 currentCompletedValue = m_pFence->GetCompletedValue(); + + if (m_LastCompletedValue < currentCompletedValue) + { + DX12_LOG("Completed fence value(s): %d to %d", m_LastCompletedValue + 1, currentCompletedValue); + } + +#ifdef DX12_IN_ORDER_TERMINATION + DX12_ASSERT(m_LastCompletedValue <= currentCompletedValue, "Getting new fence value which is older than the last!"); + // We do not allow smaller fences being submitted, and fences always complete in-order, no max() neccessary + m_LastCompletedValue = currentCompletedValue; +#else + // CLs may terminate in any order. Is it higher than last known completed fence? If so, update it! + MaxFenceValue(m_LastCompletedValue, currentCompletedValue); +#endif // !NDEBUG + + return currentCompletedValue; + } + + inline u64 GetLastCompletedFenceValue() const + { + return m_LastCompletedValue; + } + + private: + Device* m_pDevice; + ID3D12Fence* m_pFence; + HANDLE m_FenceEvent; + + std::atomic m_CurrentValue; + mutable std::atomic m_LastCompletedValue; + }; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + class CommandListFenceSet + { + public: + CommandListFenceSet(Device* device); + ~CommandListFenceSet(); + + bool Init(); + + inline ID3D12Fence** GetD3D12Fences() + { + return m_pFences; + } + + inline ID3D12Fence* GetD3D12Fence(const int id) const + { + return m_pFences[id]; + } + + inline u64 GetSubmittedValue(const int id) const + { + return m_SubmittedValues[id]; + } + + inline void SetSubmittedValue(const u64 fenceValue, const int id) + { +#ifdef DX12_IN_ORDER_SUBMISSION + DX12_ASSERT(m_SubmittedValues[id] <= fenceValue, "Setting new fence value which is older than the submitted!"); + // We do not allow smaller fences being submitted, and fences always submit in-order, no max() neccessary + m_SubmittedValues[id] = fenceValue; +#else + // CLs may submit in any order. Is it higher than last known completed fence? If so, update it! + MaxFenceValue(m_SubmittedValues[id], fenceValue); +#endif // !NDEBUG + } + + inline u64 GetCurrentValue(const int id) const + { + return m_CurrentValues[id]; + } + + inline void GetCurrentValues(u64 (&fenceValues)[CMDQUEUE_NUM]) const + { + fenceValues[CMDQUEUE_COPY ] = m_CurrentValues[CMDQUEUE_COPY ]; + fenceValues[CMDQUEUE_GRAPHICS] = m_CurrentValues[CMDQUEUE_GRAPHICS]; + } + + inline const std::atomic (& GetCurrentValues() const)[CMDQUEUE_NUM] + { + return m_CurrentValues; + } + + // thread-save + inline void SetCurrentValue(const u64 fenceValue, const int id) + { +#ifdef DX12_IN_ORDER_ACQUIRATION + DX12_ASSERT(m_CurrentValues[id] <= fenceValue, "Setting new fence value which is older than the current!"); + // We do not allow smaller fences being submitted, and fences always submit in-order, no max() neccessary + m_CurrentValues[id] = fenceValue; +#else + // CLs may submit in any order. Is it higher than last known completed fence? If so, update it! + MaxFenceValue(m_CurrentValues[id], fenceValue); +#endif // !NDEBUG + } + + inline bool IsCompleted(const u64 fenceValue, const int id) const + { + // Check against last known completed value first to avoid unnecessary fence read + return + (m_LastCompletedValues[id] >= fenceValue) || (AdvanceCompletion(id) >= fenceValue); + } + + inline bool IsCompleted(const u64 (&fenceValues)[CMDQUEUE_NUM]) const + { + // Check against last known completed value first to avoid unnecessary fence read + return + // TODO: return mask of completed fences so we don't check all three of them all the time + ((m_LastCompletedValues[CMDQUEUE_COPY ] >= fenceValues[CMDQUEUE_COPY ]) || (AdvanceCompletion(CMDQUEUE_COPY) >= fenceValues[CMDQUEUE_COPY ])) & + ((m_LastCompletedValues[CMDQUEUE_GRAPHICS] >= fenceValues[CMDQUEUE_GRAPHICS]) || (AdvanceCompletion(CMDQUEUE_GRAPHICS) >= fenceValues[CMDQUEUE_GRAPHICS])); + } + + void WaitForFence(const u64 fenceValue, const int id) const; + void WaitForFence(const u64 (&fenceValues)[CMDQUEUE_NUM]) const; + + inline u64 AdvanceCompletion(const int id) const + { + // Check current completed fence + u64 currentCompletedValue = m_pFences[id]->GetCompletedValue(); + + if (m_LastCompletedValues[id] < currentCompletedValue) + { + DX12_LOG("Completed fence value(s): %d to %d", m_LastCompletedValues[id] + 1, currentCompletedValue); + } + +#ifdef DX12_IN_ORDER_TERMINATION + DX12_ASSERT(m_LastCompletedValues[id] <= currentCompletedValue, "Getting new fence value which is older than the last!"); + // We do not allow smaller fences being submitted, and fences always complete in-order, no max() neccessary + m_LastCompletedValues[id] = currentCompletedValue; +#else + // CLs may terminate in any order. Is it higher than last known completed fence? If so, update it! + MaxFenceValue(m_LastCompletedValues[id], currentCompletedValue); +#endif // !NDEBUG + + return currentCompletedValue; + } + + inline void AdvanceCompletion() const + { + AdvanceCompletion(CMDQUEUE_COPY); + AdvanceCompletion(CMDQUEUE_GRAPHICS); + } + + inline u64 GetLastCompletedFenceValue(const int id) const + { + return m_LastCompletedValues[id]; + } + + inline void GetLastCompletedFenceValues(u64 (&fenceValues)[CMDQUEUE_NUM]) const + { + fenceValues[CMDQUEUE_COPY ] = m_LastCompletedValues[CMDQUEUE_COPY ]; + fenceValues[CMDQUEUE_GRAPHICS] = m_LastCompletedValues[CMDQUEUE_GRAPHICS]; + } + + private: + Device* m_pDevice; + ID3D12Fence* m_pFences[CMDQUEUE_NUM]; + HANDLE m_FenceEvents[CMDQUEUE_NUM]; + + // Maximum fence-value of all command-lists currently in flight (allocated, running or free) + std::atomic m_CurrentValues[CMDQUEUE_NUM]; + // Maximum fence-value of all command-lists passed to the driver (running only) + std::atomic m_SubmittedValues[CMDQUEUE_NUM]; + + // Maximum fence-value of all command-lists executed by the driver (free only) + mutable std::atomic m_LastCompletedValues[CMDQUEUE_NUM]; + }; +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12DescriptorHeap.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12DescriptorHeap.cpp new file mode 100644 index 00000000000..81fc29394d5 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12DescriptorHeap.cpp @@ -0,0 +1,61 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12DescriptorHeap.hpp" +#include "DX12Device.hpp" + +namespace DX12 +{ + DescriptorHeap::DescriptorHeap(Device* device) + : DeviceObject(device) + { + } + + DescriptorHeap::~DescriptorHeap() + { + } + + bool DescriptorHeap::Init(const D3D12_DESCRIPTOR_HEAP_DESC& desc) + { + if (!IsInitialized()) + { + ID3D12DescriptorHeap* heap; + GetDevice()->GetD3D12Device()->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&heap)); + + m_pDescriptorHeap = heap; + heap->Release(); + + m_Desc12 = m_pDescriptorHeap->GetDesc(); + m_HeapStartCPU = m_pDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + if (desc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE) + { + m_HeapStartGPU = m_pDescriptorHeap->GetGPUDescriptorHandleForHeapStart(); + } + + m_DescSize = GetDevice()->GetD3D12Device()->GetDescriptorHandleIncrementSize(m_Desc12.Type); + + IsInitialized(true); + } + + Reset(); + return true; + } + + DescriptorBlock::DescriptorBlock(const SDescriptorBlock& block) + { + m_pDescriptorHeap = reinterpret_cast(block.pBuffer); + m_BlockStart = block.offset; + m_Capacity = block.size; + m_Cursor = 0; + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12DescriptorHeap.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12DescriptorHeap.hpp new file mode 100644 index 00000000000..b27252db4f0 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12DescriptorHeap.hpp @@ -0,0 +1,179 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once + +#include "DX12.hpp" + +struct SDescriptorBlock +{ + const uint32_t blockID; + void* pBuffer; + uint32_t size; + uint32_t offset; + + SDescriptorBlock(uint32_t id) : blockID(id), pBuffer(NULL), size(0), offset(~0u) {} +}; + +namespace DX12 +{ + struct Cursor + { + Cursor() : m_Cursor(0) {} + + inline void SetCursor(u32 value) { m_Cursor = value; } + inline u32 GetCursor() const { return m_Cursor; } + inline void IncrementCursor(u32 step = 1) { m_Cursor += step; } + inline void Reset() { m_Cursor = 0; } + + u32 m_Cursor; + }; + + class DescriptorHeap + : public DeviceObject + , public Cursor + { + public: + DescriptorHeap(Device* device); + virtual ~DescriptorHeap(); + + bool Init(const D3D12_DESCRIPTOR_HEAP_DESC& desc); + + inline ID3D12DescriptorHeap* GetD3D12DescriptorHeap() const + { + return m_pDescriptorHeap; + } + + inline u32 GetDescriptorSize() const + { + return m_DescSize; + } + + inline u32 GetCapacity() const + { + return m_Desc12.NumDescriptors; + } + + inline CD3DX12_CPU_DESCRIPTOR_HANDLE GetHandleOffsetCPU(INT offset) const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_HeapStartCPU, m_Cursor + offset, m_DescSize); + } + + inline CD3DX12_CPU_DESCRIPTOR_HANDLE GetHandleOffsetCPU_R(INT offset) const + { + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_HeapStartCPU, offset, m_DescSize); + } + + inline CD3DX12_GPU_DESCRIPTOR_HANDLE GetHandleOffsetGPU(INT offset) const + { + return CD3DX12_GPU_DESCRIPTOR_HANDLE(m_HeapStartGPU, m_Cursor + offset, m_DescSize); + } + + inline CD3DX12_GPU_DESCRIPTOR_HANDLE GetHandleOffsetGPU_R(INT offset) const + { + return CD3DX12_GPU_DESCRIPTOR_HANDLE(m_HeapStartGPU, offset, m_DescSize); + } + + inline D3D12_GPU_DESCRIPTOR_HANDLE GetHandleGPUFromCPU(D3D12_CPU_DESCRIPTOR_HANDLE handle) const + { + R_ASSERT2(GetHandleOffsetCPU(0).ptr <= handle.ptr && handle.ptr < GetHandleOffsetCPU(GetCapacity()).ptr, "Out of bounds"); + D3D12_GPU_DESCRIPTOR_HANDLE rebase; + rebase.ptr = m_HeapStartGPU.ptr + handle.ptr - m_HeapStartCPU.ptr; + return rebase; + } + + inline D3D12_CPU_DESCRIPTOR_HANDLE GetHandleCPUFromGPU(D3D12_GPU_DESCRIPTOR_HANDLE handle) const + { + R_ASSERT2(GetHandleOffsetGPU(0).ptr <= handle.ptr && handle.ptr < GetHandleOffsetGPU(GetCapacity()).ptr, "Out of bounds"); + D3D12_CPU_DESCRIPTOR_HANDLE rebase; + rebase.ptr = m_HeapStartCPU.ptr + handle.ptr - m_HeapStartGPU.ptr; + return rebase; + } + + inline INT GetOffsetFromCPUHandle(D3D12_CPU_DESCRIPTOR_HANDLE handle) + { + return static_cast((handle.ptr - m_HeapStartCPU.ptr) / m_DescSize); + } + + private: + _smart_ptr m_pDescriptorHeap; + D3D12_DESCRIPTOR_HEAP_DESC m_Desc12; + D3D12_CPU_DESCRIPTOR_HANDLE m_HeapStartCPU; + D3D12_GPU_DESCRIPTOR_HANDLE m_HeapStartGPU; + u32 m_DescSize; + }; + + class DescriptorBlock : public Cursor + { + public: + DescriptorBlock() + : m_BlockStart(0) + , m_Capacity(0) + {} + + DescriptorBlock(DescriptorHeap* pHeap, u32 cursor, u32 capacity) + : m_pDescriptorHeap(pHeap) + , m_BlockStart(cursor) + , m_Capacity(capacity) + { + R_ASSERT2(cursor + capacity <= pHeap->GetCapacity(), "Out of bounds"); + } + + DescriptorBlock(const SDescriptorBlock& block); + + inline DescriptorHeap* GetDescriptorHeap() const + { + return m_pDescriptorHeap.get(); + } + + inline u32 GetDescriptorSize() const + { + return m_pDescriptorHeap->GetDescriptorSize(); + } + + inline u32 GetCapacity() const + { + return m_Capacity; + } + + inline D3D12_CPU_DESCRIPTOR_HANDLE GetHandleOffsetCPU(INT offset) const + { + R_ASSERT2((offset < 0) || (m_Cursor + offset < m_Capacity), "Out of bounds"); + return m_pDescriptorHeap->GetHandleOffsetCPU_R(static_cast(m_BlockStart + m_Cursor) + offset); + } + + inline D3D12_GPU_DESCRIPTOR_HANDLE GetHandleOffsetGPU(INT offset) const + { + R_ASSERT2((offset < 0) || (m_Cursor + offset < m_Capacity), "Out of bounds"); + return m_pDescriptorHeap->GetHandleOffsetGPU_R(static_cast(m_BlockStart + m_Cursor) + offset); + } + + inline D3D12_GPU_DESCRIPTOR_HANDLE GetHandleGPUFromCPU(D3D12_CPU_DESCRIPTOR_HANDLE handle) const + { + R_ASSERT2(m_pDescriptorHeap->GetHandleOffsetCPU(m_BlockStart).ptr <= handle.ptr && handle.ptr < m_pDescriptorHeap->GetHandleOffsetCPU(m_BlockStart + GetCapacity()).ptr, "Out of bounds"); + return m_pDescriptorHeap->GetHandleGPUFromCPU(handle); + } + + inline D3D12_CPU_DESCRIPTOR_HANDLE GetHandleCPUFromGPU(D3D12_GPU_DESCRIPTOR_HANDLE handle) const + { + R_ASSERT2(m_pDescriptorHeap->GetHandleOffsetGPU(m_BlockStart).ptr <= handle.ptr && handle.ptr < m_pDescriptorHeap->GetHandleOffsetGPU(m_BlockStart + GetCapacity()).ptr, "Out of bounds"); + return m_pDescriptorHeap->GetHandleCPUFromGPU(handle); + } + + inline u32 GetStartOffset() const { return m_BlockStart; } + + private: + _smart_ptr m_pDescriptorHeap; + u32 m_BlockStart; + u32 m_Capacity; + }; +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12Device.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12Device.cpp new file mode 100644 index 00000000000..594194ee607 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12Device.cpp @@ -0,0 +1,516 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12Device.hpp" +#include "DX12Resource.hpp" + +#define DX12_GLOBALHEAP_RESOURCES (1 << D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) +#define DX12_GLOBALHEAP_SAMPLERS (1 << D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) +#define DX12_GLOBALHEAP_TYPES DX12_GLOBALHEAP_RESOURCES + +namespace DX12 +{ + Device* Device::Create(IDXGIAdapter* pAdapter, D3D_FEATURE_LEVEL* pFeatureLevel) + { + ID3D12Device* pDevice12 = NULL; + + if (RendererDX12::CV_r_EnableDebugLayer) + { + ID3D12Debug* debugInterface; + if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface)))) + { + debugInterface->EnableDebugLayer(); + } +// ID3D12Debug1 is only available after windows 10 anniversary update or windows sdk 14393 +#ifdef __ID3D12Debug1_INTERFACE_DEFINED__ + ID3D12Debug1* debugInterface1; + if (SUCCEEDED(debugInterface->QueryInterface(IID_PPV_ARGS(&debugInterface1)))) + { + debugInterface1->SetEnableGPUBasedValidation(true); + debugInterface1->SetEnableSynchronizedCommandQueueValidation(true); + } +#endif + + } + + D3D_FEATURE_LEVEL level; + HRESULT hr = + (D3D12CreateDevice(pAdapter, level = D3D_FEATURE_LEVEL_12_1, IID_PPV_ARGS(&pDevice12)) == S_OK) || + (D3D12CreateDevice(pAdapter, level = D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(&pDevice12)) == S_OK) || + // (D3D12CreateDevice(pAdapter, level = D3D_FEATURE_LEVEL_11_3, IID_PPV_ARGS(&pDevice12)) == S_OK) || + // (D3D12CreateDevice(pAdapter, level = D3D_FEATURE_LEVEL_11_2, IID_PPV_ARGS(&pDevice12)) == S_OK) || + (D3D12CreateDevice(pAdapter, level = D3D_FEATURE_LEVEL_11_1, IID_PPV_ARGS(&pDevice12)) == S_OK) || + (D3D12CreateDevice(pAdapter, level = D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&pDevice12)) == S_OK) || + (D3D12CreateDevice(pAdapter, level = D3D_FEATURE_LEVEL_10_1, IID_PPV_ARGS(&pDevice12)) == S_OK) || + (D3D12CreateDevice(pAdapter, level = D3D_FEATURE_LEVEL_10_0, IID_PPV_ARGS(&pDevice12)) == S_OK) || + (D3D12CreateDevice(pAdapter, level = D3D_FEATURE_LEVEL_9_3, IID_PPV_ARGS(&pDevice12)) == S_OK) || + (D3D12CreateDevice(pAdapter, level = D3D_FEATURE_LEVEL_9_2, IID_PPV_ARGS(&pDevice12)) == S_OK) || + (D3D12CreateDevice(pAdapter, level = D3D_FEATURE_LEVEL_9_1, IID_PPV_ARGS(&pDevice12)) == S_OK) ? S_OK : S_FALSE; + + if (hr != S_OK) + { + DX12_ASSERT(0, "Failed to create D3D12 Device!"); + return NULL; + } + + if (pFeatureLevel) + { + *pFeatureLevel = level; + } + + Device* result = new Device(pDevice12); + pDevice12->Release(); + + return DX12::PassAddRef(result); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Device::Device(ID3D12Device* d3d12Device) + : m_Device(d3d12Device) + , m_SamplerCache(this) + , m_ShaderResourceDescriptorCache(this) + , m_UnorderedAccessDescriptorCache(this) + , m_DepthStencilDescriptorCache(this) + , m_RenderTargetDescriptorCache(this) + , m_GlobalDescriptorHeaps + { + { this }, + { this }, + { this }, + { this } + } + , m_FrameCounter(0) + , m_CalibratedCpuTimestamp{} + , m_CalibratedCpuTimestampFrequency{} + , m_CalibratedGpuTimestamp{} + , m_CalibratedGpuTimestampFrequency{} + , m_NullSRV{} + , m_NullUAV{} + , m_NullSampler{} + { + // These objects are reference counted, but didn't heap allocate them. We assume ownership. + { + m_SamplerCache.AddRef(); + m_ShaderResourceDescriptorCache.AddRef(); + m_UnorderedAccessDescriptorCache.AddRef(); + m_DepthStencilDescriptorCache.AddRef(); + m_RenderTargetDescriptorCache.AddRef(); + + for (u32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; ++i) + { + m_GlobalDescriptorHeaps[i].AddRef(); + } + } + + m_PipelineStateCache.Init(this); + m_RootSignatureCache.Init(this); + + // init sampler cache + { + D3D12_DESCRIPTOR_HEAP_DESC desc; + ZeroMemory(&desc, sizeof(D3D12_DESCRIPTOR_HEAP_DESC)); + + desc.NumDescriptors = 2048; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + + m_SamplerCache.Init(desc); + } + + // init shader resource descriptor cache + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.NumDescriptors = 65535; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + + m_ShaderResourceDescriptorCache.Init(desc); + } + + // init unordered access descriptor cache + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.NumDescriptors = 4096; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + + m_UnorderedAccessDescriptorCache.Init(desc); + } + + // init depth stencil descriptor cache + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.NumDescriptors = 256; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + + m_DepthStencilDescriptorCache.Init(desc); + } + + // init render target descriptor cache + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.NumDescriptors = 1024; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + + m_RenderTargetDescriptorCache.Init(desc); + } + + // init global descriptor heaps + + static u32 globalHeapSizes[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES] = + { + 1000000, // D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV + 1024, // D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER + 256, // D3D12_DESCRIPTOR_HEAP_TYPE_RTV + 256 // D3D12_DESCRIPTOR_HEAP_TYPE_DSV + }; + + for (D3D12_DESCRIPTOR_HEAP_TYPE eType = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; eType < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; eType = D3D12_DESCRIPTOR_HEAP_TYPE(eType + 1)) + { + if (DX12_GLOBALHEAP_TYPES & (1 << eType)) + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.NumDescriptors = globalHeapSizes[eType]; + desc.Type = eType; + desc.Flags = (eType == D3D12_DESCRIPTOR_HEAP_TYPE_RTV || eType == D3D12_DESCRIPTOR_HEAP_TYPE_DSV ? D3D12_DESCRIPTOR_HEAP_FLAG_NONE : D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); + + m_GlobalDescriptorHeaps[eType].Init(desc); + } + } + + D3D12_SHADER_RESOURCE_VIEW_DESC SRVDesc = {}; + SRVDesc.Format = DXGI_FORMAT_R32_UINT; + SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + m_NullSRV = CacheShaderResourceView(&SRVDesc, nullptr); + + D3D12_UNORDERED_ACCESS_VIEW_DESC UAVDesc = {}; + UAVDesc.Format = DXGI_FORMAT_R32_UINT; + UAVDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + m_NullUAV = CacheUnorderedAccessView(&UAVDesc, nullptr); + + D3D12_SAMPLER_DESC SamplerDesc = {}; + SamplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + SamplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + SamplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + SamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; + SamplerDesc.Filter = D3D12_FILTER_COMPARISON_ANISOTROPIC; + m_NullSampler = CacheSampler(&SamplerDesc); + } + + Device::~Device() + { + // Free all resources in the m_ReleaseHeap and m_RecycleHeap + FlushReleaseHeap(ResourceReleasePolicy::Immediate); + } + + D3D12_CPU_DESCRIPTOR_HANDLE Device::CacheSampler(const D3D12_SAMPLER_DESC* pDesc) + { + static CryCriticalSectionNonRecursive csThreadSafeScope; + CryAutoLock lThreadSafeScope(csThreadSafeScope); + + DX12_ASSERT(m_SamplerCache.GetCursor() < m_SamplerCache.GetCapacity()); + + D3D12_CPU_DESCRIPTOR_HANDLE dstHandle = m_SamplerCache.GetHandleOffsetCPU(0); + GetD3D12Device()->CreateSampler(pDesc, dstHandle); + m_SamplerCache.IncrementCursor(); + + return dstHandle; + } + + D3D12_CPU_DESCRIPTOR_HANDLE Device::CacheShaderResourceView(const D3D12_SHADER_RESOURCE_VIEW_DESC* pDesc, ID3D12Resource* pResource) + { + static CryCriticalSectionNonRecursive csThreadSafeScope; + CryAutoLock lThreadSafeScope(csThreadSafeScope); + + bool useCached = false; + D3D12_CPU_DESCRIPTOR_HANDLE dstHandle; + if (m_DescriptorPools[DescriptorPoolSRV].size()) + { + auto it = m_DescriptorPools[DescriptorPoolSRV].front(); + if (m_FrameCounter > (it.first + AllowedGPUFramesLatency)) + { + useCached = true; + m_DescriptorPools[DescriptorPoolSRV].pop_front(); + dstHandle = m_ShaderResourceDescriptorCache.GetHandleOffsetCPU_R(it.second); + } + } + if(!useCached) + { + DX12_ASSERT(m_ShaderResourceDescriptorCache.GetCursor() < m_ShaderResourceDescriptorCache.GetCapacity()); + dstHandle = m_ShaderResourceDescriptorCache.GetHandleOffsetCPU(0); + m_ShaderResourceDescriptorCache.IncrementCursor(); + } + + GetD3D12Device()->CreateShaderResourceView(pResource, pDesc, dstHandle); + + + return dstHandle; + } + + D3D12_CPU_DESCRIPTOR_HANDLE Device::CacheUnorderedAccessView(const D3D12_UNORDERED_ACCESS_VIEW_DESC* pDesc, ID3D12Resource* pResource) + { + static CryCriticalSectionNonRecursive csThreadSafeScope; + CryAutoLock lThreadSafeScope(csThreadSafeScope); + + bool useCached = false; + D3D12_CPU_DESCRIPTOR_HANDLE dstHandle; + if (m_DescriptorPools[DescriptorPoolUAV].size()) + { + auto it = m_DescriptorPools[DescriptorPoolUAV].front(); + if (m_FrameCounter > (it.first + AllowedGPUFramesLatency)) + { + useCached = true; + m_DescriptorPools[DescriptorPoolUAV].pop_front(); + dstHandle = m_UnorderedAccessDescriptorCache.GetHandleOffsetCPU_R(it.second); + } + } + if (!useCached) + { + DX12_ASSERT(m_UnorderedAccessDescriptorCache.GetCursor() < m_UnorderedAccessDescriptorCache.GetCapacity()); + dstHandle = m_UnorderedAccessDescriptorCache.GetHandleOffsetCPU(0); + m_UnorderedAccessDescriptorCache.IncrementCursor(); + } + GetD3D12Device()->CreateUnorderedAccessView(pResource, nullptr, pDesc, dstHandle); + + return dstHandle; + } + + D3D12_CPU_DESCRIPTOR_HANDLE Device::CacheDepthStencilView(const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc, ID3D12Resource* pResource) + { + static CryCriticalSectionNonRecursive csThreadSafeScope; + CryAutoLock lThreadSafeScope(csThreadSafeScope); + + DX12_ASSERT(m_DepthStencilDescriptorCache.GetCursor() < m_DepthStencilDescriptorCache.GetCapacity()); + + D3D12_CPU_DESCRIPTOR_HANDLE dstHandle = m_DepthStencilDescriptorCache.GetHandleOffsetCPU(0); + GetD3D12Device()->CreateDepthStencilView(pResource, pDesc, dstHandle); + m_DepthStencilDescriptorCache.IncrementCursor(); + + return dstHandle; + } + + D3D12_CPU_DESCRIPTOR_HANDLE Device::CacheRenderTargetView(const D3D12_RENDER_TARGET_VIEW_DESC* pDesc, ID3D12Resource* pResource) + { + static CryCriticalSectionNonRecursive csThreadSafeScope; + CryAutoLock lThreadSafeScope(csThreadSafeScope); + + DX12_ASSERT(m_RenderTargetDescriptorCache.GetCursor() < m_RenderTargetDescriptorCache.GetCapacity()); + + D3D12_CPU_DESCRIPTOR_HANDLE dstHandle = m_RenderTargetDescriptorCache.GetHandleOffsetCPU(0); + GetD3D12Device()->CreateRenderTargetView(pResource, pDesc, dstHandle); + m_RenderTargetDescriptorCache.IncrementCursor(); + + return dstHandle; + } + + void Device::RecycleDescriptorHandle(DescriptorPoolType poolType, D3D12_CPU_DESCRIPTOR_HANDLE handle) + { + u32 offset; + switch (poolType) + { + case DescriptorPoolSRV: + offset = m_ShaderResourceDescriptorCache.GetOffsetFromCPUHandle(handle); + break; + case DescriptorPoolUAV: + offset = m_UnorderedAccessDescriptorCache.GetOffsetFromCPUHandle(handle); + break; + default: + R_ASSERT2(0, "DescriptorPoolType not supported!"); + } + + m_DescriptorPools[poolType].push_back(std::pair(m_FrameCounter, offset)); + } + + void Device::FinishFrame() + { + m_FrameCounter++; + } + + HRESULT STDMETHODCALLTYPE Device::CreateOrReuseCommittedResource( + _In_ const D3D12_HEAP_PROPERTIES* pHeapProperties, + D3D12_HEAP_FLAGS HeapFlags, + _In_ const D3D12_RESOURCE_DESC* pResourceDesc, + D3D12_RESOURCE_STATES InitialResourceState, + _In_opt_ const D3D12_CLEAR_VALUE* pOptimizedClearValue, + REFIID riidResource, + _COM_Outptr_opt_ void** ppvResource, + ResourceStates& resourceStates) + { + + + struct + { + D3D12_HEAP_FLAGS sHeapFlags; + D3D12_HEAP_PROPERTIES sHeapProperties; + D3D12_RESOURCE_DESC sResourceDesc; + } + hashableBlob; + + hashableBlob.sHeapProperties = *pHeapProperties; + hashableBlob.sResourceDesc = *pResourceDesc; + hashableBlob.sHeapFlags = HeapFlags; + + // Clear spaces from alignment of members + void* ptr1 = ((char*)&hashableBlob.sResourceDesc.Dimension) + sizeof(hashableBlob.sResourceDesc.Dimension); + ZeroMemory(ptr1, offsetof(D3D12_RESOURCE_DESC, Alignment) - sizeof(hashableBlob.sResourceDesc.Dimension)); + void* ptr2 = ((char*)&hashableBlob.sResourceDesc.Flags) + sizeof(hashableBlob.sResourceDesc.Flags); + ZeroMemory(ptr2, sizeof(hashableBlob.sResourceDesc) - offsetof(D3D12_RESOURCE_DESC, Flags) - sizeof(hashableBlob.sResourceDesc.Flags)); + + THash hHash = ComputeSmallHash(&hashableBlob); + + auto result = m_RecycleHeap.find(hHash); + if (result != m_RecycleHeap.end()) + { + if (ppvResource) + { + *ppvResource = result->second.resource; + resourceStates = result->second.resourceStates; + m_RecycleHeap.erase(result); + } + + return S_OK; + } + + auto res = GetD3D12Device()->CreateCommittedResource( + pHeapProperties, HeapFlags, pResourceDesc, InitialResourceState, + pOptimizedClearValue, riidResource, ppvResource); + resourceStates.m_CurrentState = InitialResourceState; + resourceStates.m_AnnouncedState = static_cast(-1); + + return res; + } + + void Device::FlushReleaseHeap(ResourceReleasePolicy releasePolicy) + { + const u32 RESOURCE_RECYCLE_LATENCY = 8; + const u32 RESOURCE_RELEASE_LATENCY = 32; + { + auto it = m_ReleaseHeap.begin(); + while (it != m_ReleaseHeap.end()) + { + u32 resourceFrameNumber = it->second.frameNumber; + ID3D12Resource* resource = it->second.resource; + if (m_FrameCounter > (resourceFrameNumber + RESOURCE_RECYCLE_LATENCY) || releasePolicy == ResourceReleasePolicy::Immediate) + { + m_RecycleHeap.insert(*it); + it = m_ReleaseHeap.erase(it); + } + else + { + it++; + } + } + } + { + auto it = m_RecycleHeap.begin(); + while (it != m_RecycleHeap.end()) + { + u32 resourceFrameNumber = it->second.frameNumber; + if (m_FrameCounter > (resourceFrameNumber + RESOURCE_RELEASE_LATENCY) || releasePolicy == ResourceReleasePolicy::Immediate) + { + it->second.resource->Release(); + it = m_RecycleHeap.erase(it); + } + else + { + it++; + } + } + } + } + + void Device::ReleaseLater(ID3D12Resource* object, D3D12_RESOURCE_STATES currentState, D3D12_RESOURCE_STATES announcedState) + { + if (object) + { + struct + { + D3D12_HEAP_FLAGS sHeapFlags; + D3D12_HEAP_PROPERTIES sHeapProperties; + D3D12_RESOURCE_DESC sResourceDesc; + } + hashableBlob; + + object->GetHeapProperties(&hashableBlob.sHeapProperties, &hashableBlob.sHeapFlags); + hashableBlob.sResourceDesc = object->GetDesc(); + // When creating a committed resource, D3D12_HEAP_FLAGS must not have either D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES, + // D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES, nor D3D12_HEAP_FLAG_DENY_BUFFERS set. These flags will be set automatically + // to correspond with the committed resource type. + hashableBlob.sHeapFlags = D3D12_HEAP_FLAGS(hashableBlob.sHeapFlags & ~(D3D12_HEAP_FLAG_DENY_BUFFERS + D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES + D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES)); + + // Clear spaces from alignment of members + void* ptr1 = ((char*)&hashableBlob.sResourceDesc.Dimension) + sizeof(hashableBlob.sResourceDesc.Dimension); + ZeroMemory(ptr1, offsetof(D3D12_RESOURCE_DESC, Alignment) - sizeof(hashableBlob.sResourceDesc.Dimension)); + void* ptr2 = ((char*)&hashableBlob.sResourceDesc.Flags) + sizeof(hashableBlob.sResourceDesc.Flags); + ZeroMemory(ptr2, sizeof(hashableBlob.sResourceDesc) - offsetof(D3D12_RESOURCE_DESC, Flags) - sizeof(hashableBlob.sResourceDesc.Flags)); + + ReleaseInfo releaseInfo; + + THash hash = ComputeSmallHash(&hashableBlob); + + releaseInfo.resource = object; + releaseInfo.resourceStates.m_CurrentState = currentState; + releaseInfo.resourceStates.m_AnnouncedState = announcedState; + releaseInfo.frameNumber = m_FrameCounter; + + m_ReleaseHeap.insert(std::make_pair(hash, std::move(releaseInfo))); + } + } + + DescriptorBlock Device::GetGlobalDescriptorBlock(D3D12_DESCRIPTOR_HEAP_TYPE eType, u32 size) + { + if (DX12_GLOBALHEAP_TYPES & (1 << eType)) + { + R_ASSERT2(m_GlobalDescriptorHeaps[eType].GetCapacity() - m_GlobalDescriptorHeaps[eType].GetCursor() >= size, "Exceeded capacity"); + DescriptorBlock result(&m_GlobalDescriptorHeaps[eType], m_GlobalDescriptorHeaps[eType].GetCursor(), size); + m_GlobalDescriptorHeaps[eType].IncrementCursor(size); + return result; + } + + DescriptorHeap* pResourceHeap = DX12::PassAddRef(new DescriptorHeap(this)); + + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.NumDescriptors = size; + desc.Type = eType; + desc.Flags = (eType == D3D12_DESCRIPTOR_HEAP_TYPE_RTV || eType == D3D12_DESCRIPTOR_HEAP_TYPE_DSV ? D3D12_DESCRIPTOR_HEAP_FLAG_NONE : D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); + pResourceHeap->Init(desc); + + DescriptorBlock result(pResourceHeap, pResourceHeap->GetCursor(), size); + pResourceHeap->Release(); + return result; + } + + void Device::CalibrateClocks(ID3D12CommandQueue* presentQueue) + { + presentQueue->GetClockCalibration(&m_CalibratedGpuTimestamp, &m_CalibratedCpuTimestamp); + presentQueue->GetTimestampFrequency(&m_CalibratedGpuTimestampFrequency); + + QueryPerformanceFrequency((LARGE_INTEGER*)&m_CalibratedCpuTimestampFrequency); + } + + u64 Device::MakeCpuTimestamp(u64 gpuTimestamp) const + { + INT64 timestampDelta = ((INT64)gpuTimestamp - (INT64)m_CalibratedGpuTimestamp); + INT64 calibratedTimestampDelta = (timestampDelta * (INT64)m_CalibratedCpuTimestampFrequency) / (INT64)m_CalibratedGpuTimestampFrequency; + return m_CalibratedCpuTimestamp + calibratedTimestampDelta; + } + + u64 Device::MakeCpuTimestampMicroseconds(u64 gpuTimestamp) const + { + return (MakeCpuTimestamp(gpuTimestamp) * 1000) / (m_CalibratedCpuTimestampFrequency / 1000); + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12Device.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12Device.hpp new file mode 100644 index 00000000000..ce39b3afc5a --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12Device.hpp @@ -0,0 +1,153 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once + +#include "DX12CommandList.hpp" + +#include + +namespace DX12 +{ + enum DescriptorPoolType + { + DescriptorPoolSRV, + DescriptorPoolUAV, + DescriptorPoolNum + }; + class Device : public ReferenceCounted + { + public: + enum class ResourceReleasePolicy + { + Immediate, + Deferred + }; + + static Device* Create(IDXGIAdapter* adapter, D3D_FEATURE_LEVEL* pFeatureLevel); + virtual ~Device(); + + inline ID3D12Device* GetD3D12Device() const + { + return m_Device; + } + + inline PipelineStateCache& GetPSOCache() + { + return m_PipelineStateCache; + } + + inline const PipelineStateCache& GetPSOCache() const + { + return m_PipelineStateCache; + } + + inline RootSignatureCache& GetRootSignatureCache() + { + return m_RootSignatureCache; + } + + inline const RootSignatureCache& GetRootSignatureCache() const + { + return m_RootSignatureCache; + } + + DescriptorBlock GetGlobalDescriptorBlock(D3D12_DESCRIPTOR_HEAP_TYPE eType, u32 size); + + D3D12_CPU_DESCRIPTOR_HANDLE CacheSampler(const D3D12_SAMPLER_DESC* pDesc); + D3D12_CPU_DESCRIPTOR_HANDLE CacheShaderResourceView(const D3D12_SHADER_RESOURCE_VIEW_DESC* pDesc, ID3D12Resource* pResource); + D3D12_CPU_DESCRIPTOR_HANDLE CacheUnorderedAccessView(const D3D12_UNORDERED_ACCESS_VIEW_DESC* pDesc, ID3D12Resource* pResource); + D3D12_CPU_DESCRIPTOR_HANDLE CacheDepthStencilView(const D3D12_DEPTH_STENCIL_VIEW_DESC* pDesc, ID3D12Resource* pResource); + D3D12_CPU_DESCRIPTOR_HANDLE CacheRenderTargetView(const D3D12_RENDER_TARGET_VIEW_DESC* pDesc, ID3D12Resource* pResource); + + void RecycleDescriptorHandle(DescriptorPoolType poolType, D3D12_CPU_DESCRIPTOR_HANDLE handle); + + HRESULT STDMETHODCALLTYPE CreateOrReuseCommittedResource( + _In_ const D3D12_HEAP_PROPERTIES* pHeapProperties, + D3D12_HEAP_FLAGS HeapFlags, + _In_ const D3D12_RESOURCE_DESC* pResourceDesc, + D3D12_RESOURCE_STATES InitialResourceState, + _In_opt_ const D3D12_CLEAR_VALUE* pOptimizedClearValue, + REFIID riidResource, + _COM_Outptr_opt_ void** ppvResource, + ResourceStates& resourceStates); + + void FlushReleaseHeap(ResourceReleasePolicy releasePolicy); + void ReleaseLater(ID3D12Resource* pObject, D3D12_RESOURCE_STATES currentState, D3D12_RESOURCE_STATES announcedState); + + void FinishFrame(); + void CalibrateClocks(ID3D12CommandQueue* presentQueue); + + u64 MakeCpuTimestamp(u64 gpuTimestamp) const; + u64 MakeCpuTimestampMicroseconds(u64 gpuTimestamp) const; + + inline u64 GetGpuTimestampFrequency() const + { + return m_CalibratedGpuTimestampFrequency; + } + + inline D3D12_CPU_DESCRIPTOR_HANDLE GetNullShaderResourceView() const + { + return m_NullSRV; + } + + inline D3D12_CPU_DESCRIPTOR_HANDLE GetNullUnorderedAccessView() const + { + return m_NullUAV; + } + + inline D3D12_CPU_DESCRIPTOR_HANDLE GetNullSampler() const + { + return m_NullSampler; + } + + private: + Device(ID3D12Device* d3d12Device); + + _smart_ptr m_Device; + + PipelineStateCache m_PipelineStateCache; + RootSignatureCache m_RootSignatureCache; + + DescriptorHeap m_SamplerCache; + DescriptorHeap m_ShaderResourceDescriptorCache; + DescriptorHeap m_UnorderedAccessDescriptorCache; + DescriptorHeap m_DepthStencilDescriptorCache; + DescriptorHeap m_RenderTargetDescriptorCache; + DescriptorHeap m_GlobalDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES]; + + D3D12_CPU_DESCRIPTOR_HANDLE m_NullSRV; + D3D12_CPU_DESCRIPTOR_HANDLE m_NullUAV; + D3D12_CPU_DESCRIPTOR_HANDLE m_NullSampler; + + // Free pool of descriptor handler offset + std::list> m_DescriptorPools[DescriptorPoolNum]; + + struct ReleaseInfo + { + ID3D12Resource *resource; + ResourceStates resourceStates; + s32 frameNumber; + }; + + std::unordered_multimap m_ReleaseHeap; + std::unordered_multimap m_RecycleHeap; + + u32 m_FrameCounter; + const u32 AllowedGPUFramesLatency = 5; + + u64 m_CalibratedGpuTimestampFrequency; + u64 m_CalibratedGpuTimestamp; + u64 m_CalibratedCpuTimestampFrequency; + u64 m_CalibratedCpuTimestamp; + }; +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12PSO.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12PSO.cpp new file mode 100644 index 00000000000..950ccaeff37 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12PSO.cpp @@ -0,0 +1,127 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12PSO.hpp" +#include "DX12Device.hpp" + +namespace DX12 +{ + bool PipelineState::Init(const RootSignature* rootSignature, ID3D12PipelineState* pipelineState) + { + m_RootSignature = rootSignature; + m_PipelineState = pipelineState; + + return true; + } + + bool GraphicsPipelineState::Init(const InitParams& params) + { + + m_Desc = params.desc; + m_Desc.pRootSignature = params.rootSignature->GetD3D12RootSignature(); + + ID3D12PipelineState* pipelineState12 = nullptr; + HRESULT result = GetDevice()->GetD3D12Device()->CreateGraphicsPipelineState(&m_Desc, IID_PPV_ARGS(&pipelineState12)); + + if (result != S_OK) + { + DX12_ERROR("Could not create graphics pipeline state!"); + return false; + } + + PipelineState::Init(params.rootSignature, pipelineState12); + pipelineState12->Release(); + + return true; + } + + bool ComputePipelineState::Init(const InitParams& params) + { + + m_Desc = params.desc; + m_Desc.pRootSignature = params.rootSignature->GetD3D12RootSignature(); + + ID3D12PipelineState* pipelineState12 = nullptr; + HRESULT result = GetDevice()->GetD3D12Device()->CreateComputePipelineState(&m_Desc, IID_PPV_ARGS(&pipelineState12)); + + if (result != S_OK) + { + DX12_ERROR("Could not create graphics pipeline state!"); + return false; + } + + PipelineState::Init(params.rootSignature, pipelineState12); + pipelineState12->Release(); + + return true; + } + + PipelineStateCache::PipelineStateCache() + : m_Device(nullptr) + { + } + + PipelineStateCache::~PipelineStateCache() + { + } + + bool PipelineStateCache::Init(Device* device) + { + m_Device = device; + return true; + } + + GraphicsPipelineState* PipelineStateCache::AcquirePipelineState(const GraphicsPipelineState::InitParams& params) + { + // LSB cleared marks graphics pipeline states, in case graphics and compute hashes collide + THash hash = (~1) & ComputeSmallHash(¶ms.desc); + auto iter = m_Cache.find(hash); + + if (iter != m_Cache.end()) + { + return static_cast(iter->second.get()); + } + + GraphicsPipelineState* result = new GraphicsPipelineState(m_Device); + if (!result->Init(params)) + { + DX12_ERROR("Could not create PSO!"); + return nullptr; + } + + m_Cache[hash] = result; + return result; + } + + ComputePipelineState* PipelineStateCache::AcquirePipelineState(const ComputePipelineState::InitParams& params) + { + // LSB filled marks compute pipeline states, in case graphics and compute hashes collide + THash hash = (1) | ComputeSmallHash(¶ms.desc); + auto iter = m_Cache.find(hash); + + if (iter != m_Cache.end()) + { + return static_cast(iter->second.get()); + } + + ComputePipelineState* result = new ComputePipelineState(m_Device); + if (!result->Init(params)) + { + DX12_ERROR("Could not create PSO!"); + return nullptr; + } + + m_Cache[hash] = result; + return result; + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12PSO.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12PSO.hpp new file mode 100644 index 00000000000..86ebc7b314b --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12PSO.hpp @@ -0,0 +1,117 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once + +#include "DX12RootSignature.hpp" +#include + +namespace DX12 +{ + class PipelineState : public DeviceObject + { + public: + PipelineState(Device* device) : DeviceObject(device) {} + ~PipelineState() {} + + bool Init(const RootSignature* rootSignature, ID3D12PipelineState* pipelineState); + + THash GetHash() const + { + return m_Hash; + } + + ID3D12PipelineState* GetD3D12PipelineState() const + { + return m_PipelineState; + } + + private: + THash m_Hash; + _smart_ptr m_PipelineState; + const RootSignature* m_RootSignature; + }; + + class GraphicsPipelineState : public PipelineState + { + public: + GraphicsPipelineState(Device* device) : PipelineState(device) {} + ~GraphicsPipelineState() {} + + struct InitParams + { + const RootSignature* rootSignature; + D3D12_GRAPHICS_PIPELINE_STATE_DESC desc; + }; + + bool Init(const InitParams& params); + + inline D3D12_GRAPHICS_PIPELINE_STATE_DESC& GetDesc() + { + return m_Desc; + } + + inline const D3D12_GRAPHICS_PIPELINE_STATE_DESC& GetDesc() const + { + return m_Desc; + } + + private: + D3D12_GRAPHICS_PIPELINE_STATE_DESC m_Desc; + }; + + class ComputePipelineState : public PipelineState + { + public: + ComputePipelineState(Device* device) : PipelineState(device) {} + ~ComputePipelineState() {} + + struct InitParams + { + const RootSignature* rootSignature; + D3D12_COMPUTE_PIPELINE_STATE_DESC desc; + }; + + bool Init(const InitParams& params); + + inline D3D12_COMPUTE_PIPELINE_STATE_DESC& GetDesc() + { + return m_Desc; + } + + inline const D3D12_COMPUTE_PIPELINE_STATE_DESC& GetDesc() const + { + return m_Desc; + } + + private: + D3D12_COMPUTE_PIPELINE_STATE_DESC m_Desc; + }; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + class PipelineStateCache + { + public: + PipelineStateCache(); + ~PipelineStateCache(); + + bool Init(Device* device); + + GraphicsPipelineState* AcquirePipelineState(const GraphicsPipelineState::InitParams& params); + ComputePipelineState* AcquirePipelineState(const ComputePipelineState::InitParams& params); + + private: + Device* m_Device; + std::unordered_map> m_Cache; + }; +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12QueryHeap.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12QueryHeap.cpp new file mode 100644 index 00000000000..4cf0b03574c --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12QueryHeap.cpp @@ -0,0 +1,52 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12QueryHeap.hpp" +#include "DX12Device.hpp" + +namespace DX12 +{ + QueryHeap::QueryHeap(Device* device) + : DeviceObject(device) + { + } + + QueryHeap::~QueryHeap() + { + } + + bool QueryHeap::Init(Device* device, const D3D12_QUERY_HEAP_DESC& desc) + { + if (!IsInitialized()) + { + SetDevice(device); + + ID3D12QueryHeap* heap; + GetDevice()->GetD3D12Device()->CreateQueryHeap(&desc, IID_PPV_ARGS(&heap)); + + m_QueryHeap = heap; + heap->Release(); + + m_Desc12 = desc; + + IsInitialized(true); + } + + Reset(); + return true; + } + + void QueryHeap::Reset() + { + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12QueryHeap.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12QueryHeap.hpp new file mode 100644 index 00000000000..35ba906a17d --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12QueryHeap.hpp @@ -0,0 +1,37 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once + +#include "DX12.hpp" + +namespace DX12 +{ + class QueryHeap : public DeviceObject + { + public: + QueryHeap(Device* device); + virtual ~QueryHeap(); + + bool Init(Device* device, const D3D12_QUERY_HEAP_DESC& desc); + void Reset(); + + ID3D12QueryHeap* GetD3D12QueryHeap() const { return /*PassAddRef*/ (m_QueryHeap); } + + UINT GetType() const { return m_Desc12.Type; } + UINT GetCapacity() const { return m_Desc12.Count; } + + private: + _smart_ptr m_QueryHeap; + D3D12_QUERY_HEAP_DESC m_Desc12; + }; +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12Resource.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12Resource.cpp new file mode 100644 index 00000000000..21c3fcdfe76 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12Resource.cpp @@ -0,0 +1,192 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12Resource.hpp" +#include "DX12Device.hpp" + +namespace DX12 +{ + Resource::Resource(Device* pDevice) + : DeviceObject(pDevice) + , m_HeapType(D3D12_HEAP_TYPE_DEFAULT) + , m_GPUVirtualAddress(DX12_GPU_VIRTUAL_ADDRESS_NULL) + , m_pD3D12Resource(nullptr) + , m_States(D3D12_RESOURCE_STATE_COMMON, static_cast(-1)) + , m_pSwapChainOwner(NULL) + { + memset(&m_FenceValues, 0, sizeof(m_FenceValues)); + } + + Resource::Resource(Resource&& r) + : DeviceObject(std::move(r)) + , m_HeapType(std::move(r.m_HeapType)) + , m_GPUVirtualAddress(std::move(r.m_GPUVirtualAddress)) + , m_pD3D12Resource(std::move(r.m_pD3D12Resource)) + , m_States(std::move(r.m_States)) + , m_InitialData(std::move(r.m_InitialData)) + , m_pSwapChainOwner(std::move(r.m_pSwapChainOwner)) + { + memcpy(&m_FenceValues, &r.m_FenceValues, sizeof(m_FenceValues)); + + r.m_pD3D12Resource = nullptr; + r.m_pSwapChainOwner = nullptr; + } + + Resource& Resource::operator=(Resource&& r) + { + DeviceObject::operator=(std::move(r)); + + m_HeapType = std::move(r.m_HeapType); + m_GPUVirtualAddress = std::move(r.m_GPUVirtualAddress); + m_pD3D12Resource = std::move(r.m_pD3D12Resource); + m_States = std::move(r.m_States); + m_InitialData = std::move(r.m_InitialData); + m_pSwapChainOwner = std::move(r.m_pSwapChainOwner); + + memcpy(&m_FenceValues, &r.m_FenceValues, sizeof(m_FenceValues)); + + r.m_pD3D12Resource = nullptr; + r.m_pSwapChainOwner = nullptr; + + return *this; + } + + Resource::~Resource() + { + auto refCount = m_pD3D12Resource->AddRef(); + GetDevice()->ReleaseLater(m_pD3D12Resource, GetCurrentState(), GetAnnouncedState()); + } + + UINT64 Resource::GetRequiredUploadSize(UINT FirstSubresource, UINT NumSubresources) const + { + UINT64 Size; + GetDevice()->GetD3D12Device()->GetCopyableFootprints(&m_Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &Size); + return Size; + } + + bool Resource::IsUsed(CommandListPool& commandListPool, const int type) + { + return !commandListPool.IsCompleted(m_FenceValues[type]); + } + + void Resource::WaitForUnused(CommandListPool& commandListPool, const int type) + { + commandListPool.WaitForFenceOnCPU(m_FenceValues[type]); + } + + bool Resource::Init(ID3D12Resource* pResource, D3D12_RESOURCE_STATES eInitialState, const D3D12_RESOURCE_DESC& desc) + { + m_pD3D12Resource = pResource; + m_Desc = desc; + + D3D12_HEAP_PROPERTIES sHeap; + + if (m_pD3D12Resource->GetHeapProperties(&sHeap, nullptr) == S_OK) + { + m_HeapType = sHeap.Type; + + if (m_HeapType == D3D12_HEAP_TYPE_UPLOAD) + { + SetCurrentState(D3D12_RESOURCE_STATE_GENERIC_READ); + } + else if (m_HeapType == D3D12_HEAP_TYPE_READBACK) + { + SetCurrentState(D3D12_RESOURCE_STATE_COPY_DEST); + } + else + { + SetCurrentState(eInitialState); + } + } + + if (pResource && desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + m_GPUVirtualAddress = m_pD3D12Resource->GetGPUVirtualAddress(); + } + + m_pSwapChainOwner = NULL; + + return true; + } + + void Resource::TryStagingUpload(CommandList* commandList) + { + if (m_InitialData) + { + DX12_LOG("Uploading initial data"); + DX12_ASSERT(!IsUsed(commandList->GetCommandListPool()), "Resource is used prior to initialization!"); + + std::unique_ptr initialData = std::move(m_InitialData); + + commandList->UpdateSubresources(*this, + initialData->m_UploadSize, + static_cast(initialData->m_SubResourceData.size()), + &(initialData->m_SubResourceData[0])); + } + } + + Resource::InitialData* Resource::GetOrCreateInitialData() + { + if (!m_InitialData) + { + m_InitialData.reset(new InitialData()); + } + + return m_InitialData.get(); + } + + void Resource::MapDiscard(CommandList* pCmdList) + { + m_pD3D12Resource->AddRef(); + + GetDevice()->ReleaseLater(m_pD3D12Resource, GetCurrentState(), GetAnnouncedState()); + + D3D12_RESOURCE_STATES usage = D3D12_RESOURCE_STATE_GENERIC_READ; + D3D12_HEAP_TYPE heapType = D3D12_HEAP_TYPE_UPLOAD; + ID3D12Resource* resource = NULL; + + ResourceStates resourceStates; + + CD3DX12_HEAP_PROPERTIES heapProperty(heapType); + + if (S_OK != GetDevice()->CreateOrReuseCommittedResource( + &heapProperty, + D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES, + &m_Desc, + usage, + NULL, + IID_PPV_ARGS(&resource), + resourceStates + )) + { + DX12_ASSERT(0, "Could not create buffer resource!"); + return; + } + + m_pD3D12Resource = resource; + + resource->Release(); + + if (m_pD3D12Resource && m_Desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + m_GPUVirtualAddress = m_pD3D12Resource->GetGPUVirtualAddress(); + } + + SetCurrentState(usage); + SetAnnouncedState(static_cast(-1)); + + // If it is reused resource, we have to transition the state to new state + if(m_States != resourceStates) + pCmdList->QueueTransitionBarrier(*this, resourceStates.m_CurrentState); + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12Resource.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12Resource.hpp new file mode 100644 index 00000000000..a8e4154ef8e --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12Resource.hpp @@ -0,0 +1,269 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once +#ifndef __DX12RESOURCE__ +#define __DX12RESOURCE__ + +#include "DX12.hpp" +#include "DX12CommandListFence.hpp" + +#include +#include + +namespace DX12 +{ + class CommandList; + class SwapChain; + + struct ResourceStates + { + ResourceStates() + :m_CurrentState(static_cast(-1)), + m_AnnouncedState(static_cast(-1)) + {} + ResourceStates(D3D12_RESOURCE_STATES currentState, D3D12_RESOURCE_STATES announcedState) + :m_CurrentState(currentState), + m_AnnouncedState(announcedState) + {} + + bool operator ==(const ResourceStates& states) const + { + return m_CurrentState == states.m_CurrentState && m_AnnouncedState == states.m_AnnouncedState; + } + bool operator !=(const ResourceStates& states) const + { + return !(*this == states); + } + D3D12_RESOURCE_STATES m_CurrentState; + D3D12_RESOURCE_STATES m_AnnouncedState; + }; + + class Resource : public DeviceObject + { + public: + Resource(Device* pDevice); + virtual ~Resource(); + + Resource(Resource&& r); + Resource& operator=(Resource&& r); + + void TryStagingUpload(CommandList* pCmdList); + bool Init(ID3D12Resource* pResource, D3D12_RESOURCE_STATES eInitialState, const D3D12_RESOURCE_DESC& desc); + bool Init(ID3D12Resource* pResource, D3D12_RESOURCE_STATES eInitialState) + { + return Init(pResource, eInitialState, pResource->GetDesc()); + } + + // Initialization of contents + struct InitialData + { + std::vector m_SubResourceData; + UINT64 m_Size; + UINT64 m_UploadSize; + + InitialData() + : m_Size(0) + , m_UploadSize(0) + { + } + + ~InitialData() + { + for (D3D12_SUBRESOURCE_DATA& data : m_SubResourceData) + { + if (data.pData) + { + delete[] data.pData; + } + } + } + }; + + InitialData* GetOrCreateInitialData(); + + inline bool InitHasBeenDeferred() const + { + return m_InitialData != nullptr; + } + + // Swap-chain associativity + inline void SetDX12SwapChain(SwapChain* pOwner) + { + m_pSwapChainOwner = pOwner; + } + + inline SwapChain* GetDX12SwapChain() const + { + return m_pSwapChainOwner; + } + + inline bool IsBackBuffer() const + { + return m_pSwapChainOwner != NULL; + } + + inline bool IsOffCard() const + { + return m_HeapType == D3D12_HEAP_TYPE_READBACK || m_HeapType == D3D12_HEAP_TYPE_UPLOAD; + } + + inline D3D12_RESOURCE_STATES GetRequiredResourceState() const + { + return m_HeapType == D3D12_HEAP_TYPE_READBACK ? D3D12_RESOURCE_STATE_COPY_DEST : D3D12_RESOURCE_STATE_GENERIC_READ; + } + + inline bool IsTarget() const + { + return !!(GetCurrentState() & (D3D12_RESOURCE_STATE_RENDER_TARGET | D3D12_RESOURCE_STATE_DEPTH_READ | D3D12_RESOURCE_STATE_DEPTH_WRITE)); + } + + inline bool IsGeneric() const + { + return !!(GetCurrentState() & (D3D12_RESOURCE_STATE_UNORDERED_ACCESS | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); + } + + inline D3D12_RESOURCE_DESC& GetDesc() + { + return m_Desc; + } + + inline const D3D12_RESOURCE_DESC& GetDesc() const + { + return m_Desc; + } + + UINT64 GetRequiredUploadSize(UINT FirstSubresource, UINT NumSubresources) const; + + inline ID3D12Resource* GetD3D12Resource() const + { + return m_pD3D12Resource; + } + inline D3D12_GPU_VIRTUAL_ADDRESS GetGPUVirtualAddress() const + { + return m_GPUVirtualAddress; + } + + // Get current known resource barrier state + inline D3D12_RESOURCE_STATES GetCurrentState() const + { + return m_States.m_CurrentState; + } + + inline D3D12_RESOURCE_STATES GetAnnouncedState() const + { + return m_States.m_AnnouncedState; + } + + inline void SetCurrentState(D3D12_RESOURCE_STATES state) + { + m_States.m_CurrentState = state; + } + + inline void SetAnnouncedState(D3D12_RESOURCE_STATES state) + { + m_States.m_AnnouncedState = state; + } + + UINT64 SetFenceValue(UINT64 fenceValue, const int id, const int type) + { + // Check submitted completed fence + UINT64 utilizedValue = fenceValue; + UINT64 previousValue = m_FenceValues[type][id]; + +#define DX12_FREETHREADED_RESOURCES +#ifndef DX12_FREETHREADED_RESOURCES + m_FenceValues[type][id] = (previousValue > fenceValue ? previousValue : fenceValue); + + if (type == CMDTYPE_ANY) + { + m_FenceValues[CMDTYPE_READ ][id] = + m_FenceValues[CMDTYPE_WRITE][id] = + m_FenceValues[CMDTYPE_ANY][id]; + } + else + { + m_FenceValues[CMDTYPE_ANY ][id] = std::max( + m_FenceValues[CMDTYPE_READ ][id], + m_FenceValues[CMDTYPE_WRITE][id]); + } +#else + // CLs may submit in any order. Is it higher than last known completed fence? If so, update it! + MaxFenceValue(m_FenceValues[type][id], fenceValue); + + if (type == CMDTYPE_ANY) + { + MaxFenceValue(m_FenceValues[CMDTYPE_READ ][id], m_FenceValues[CMDTYPE_ANY][id]); + MaxFenceValue(m_FenceValues[CMDTYPE_WRITE][id], m_FenceValues[CMDTYPE_ANY][id]); + } + else + { + MaxFenceValue(m_FenceValues[CMDTYPE_ANY ][id], std::max(m_FenceValues[CMDTYPE_READ][id], m_FenceValues[CMDTYPE_WRITE][id])); + } +#endif // !NDEBUG + + return previousValue; + } + + inline UINT64 GetFenceValue(const int id, const int type) + { + return m_FenceValues[type][id]; + } + + inline const std::atomic (& GetFenceValues(const int type))[CMDQUEUE_NUM] + { + return m_FenceValues[type]; + } + + inline void MaxFenceValues(std::atomic (&rFenceValues)[CMDTYPE_NUM][CMDQUEUE_NUM], const int type) + { + if ((type == CMDTYPE_READ) || (type == CMDTYPE_ANY)) + { + MaxFenceValue(rFenceValues[CMDTYPE_READ ][CMDQUEUE_COPY ], m_FenceValues[CMDTYPE_READ ][CMDQUEUE_COPY ]); + MaxFenceValue(rFenceValues[CMDTYPE_READ ][CMDQUEUE_GRAPHICS], m_FenceValues[CMDTYPE_READ ][CMDQUEUE_GRAPHICS]); + } + + if ((type == CMDTYPE_WRITE) || (type == CMDTYPE_ANY)) + { + MaxFenceValue(rFenceValues[CMDTYPE_WRITE][CMDQUEUE_COPY ], m_FenceValues[CMDTYPE_WRITE][CMDQUEUE_COPY ]); + MaxFenceValue(rFenceValues[CMDTYPE_WRITE][CMDQUEUE_GRAPHICS], m_FenceValues[CMDTYPE_WRITE][CMDQUEUE_GRAPHICS]); + } + } + + bool IsUsed(CommandListPool& pCmdListPool, const int type = CMDTYPE_ANY); + void WaitForUnused(CommandListPool& pCmdListPool, const int type = CMDTYPE_ANY); + + void MapDiscard(CommandList* pCmdList); + + protected: + friend class CommandList; + + void DiscardInitialData(); + + // Never changes after construction + D3D12_RESOURCE_DESC m_Desc; + D3D12_HEAP_TYPE m_HeapType; + D3D12_GPU_VIRTUAL_ADDRESS m_GPUVirtualAddress; + _smart_ptr m_pD3D12Resource; // can be replaced by MAP_DISCARD, which is deprecated + + SwapChain* m_pSwapChainOwner; + + // Potentially changes on every resource-use + ResourceStates m_States; + mutable std::atomic m_FenceValues[CMDTYPE_NUM][CMDQUEUE_NUM]; + + // Used when using the resource the first time + std::unique_ptr m_InitialData; + }; +} + +#endif // __DX12RESOURCE__ diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12ResourceBarrierCache.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12ResourceBarrierCache.cpp new file mode 100644 index 00000000000..756b9e61fd6 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12ResourceBarrierCache.cpp @@ -0,0 +1,168 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12ResourceBarrierCache.h" +#include "DX12Device.hpp" + +namespace DX12 +{ + const char* BarrierFlagsToString(D3D12_RESOURCE_BARRIER_FLAGS flags) + { + if (flags & D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY) + { + return "BEGIN_ONLY"; + } + else if (flags & D3D12_RESOURCE_BARRIER_FLAG_END_ONLY) + { + return "END_ONLY"; + } + + return "NONE"; + } + + void ResourceBarrierCache::EnqueueTransition( + ID3D12GraphicsCommandList* commandList, + const D3D12_RESOURCE_BARRIER_FLAGS flags, + const D3D12_RESOURCE_TRANSITION_BARRIER& transition) + { + bool bFoundChain = false; + + for (TransitionChainRoot& chain : m_TransitionChains) + { + if (chain.resource == transition.pResource) + { + TransitionNode& prevNode = m_TransitionNodes[chain.tailIdx]; + + // We can collapse split barriers right here if we find them. We know the previous + // barrier must be a BEGIN_ONLY because we've seen this resource before. Therefore + // we assert that they match and simply remove the split. This simplifies the flattening + // process later on. + if (flags == D3D12_RESOURCE_BARRIER_FLAG_END_ONLY) + { + D3D12_RESOURCE_BARRIER& prevBarrier = m_TransitionBarriers[prevNode.barrierIdx]; + + R_ASSERT2( + prevBarrier.Flags == D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY && + prevBarrier.Transition.StateBefore == transition.StateBefore && + prevBarrier.Transition.StateAfter == transition.StateAfter, + "Split barrier not properly closed"); + + prevBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + return; + } + + TransitionNode self; + self.barrierIdx = u8(m_TransitionBarriers.size()); + self.selfIdx = u8(m_TransitionNodes.size()); + self.nextIdx = InvalidNodeIndex; + prevNode.nextIdx = self.selfIdx; + + m_TransitionNodes.push_back(self); + + // Reset the tail of the list to the new node. + chain.tailIdx = self.selfIdx; + + bFoundChain = true; + break; + } + } + + if (!bFoundChain) + { + TransitionNode self; + self.barrierIdx = u8(m_TransitionBarriers.size()); + self.selfIdx = u8(m_TransitionNodes.size()); + self.nextIdx = InvalidNodeIndex; + m_TransitionNodes.push_back(self); + + TransitionChainRoot root; + root.resource = transition.pResource; + root.tailIdx = self.selfIdx; + root.headIdx = self.selfIdx; + m_TransitionChains.push_back(root); + } + + m_TransitionBarriers.emplace_back(); + + D3D12_RESOURCE_BARRIER& barrier = m_TransitionBarriers.back(); + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = flags; + barrier.Transition = transition; + + TryCapacityFlush(commandList); + } + + void ResourceBarrierCache::EnqueueUAV(ID3D12GraphicsCommandList* commandList, Resource& resource) + { + m_Barriers.emplace_back(); + + D3D12_RESOURCE_BARRIER& barrierDesc = m_Barriers.back(); + barrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrierDesc.UAV.pResource = resource.GetD3D12Resource(); + + TryCapacityFlush(commandList); + } + + void ResourceBarrierCache::Flush(ID3D12GraphicsCommandList* commandList) + { + + for (TransitionChainRoot& chain : m_TransitionChains) + { + TransitionNode* node = &m_TransitionNodes[chain.headIdx]; + + m_Barriers.emplace_back(); + D3D12_RESOURCE_BARRIER* pendingBarrier = &m_Barriers.back(); + *pendingBarrier = m_TransitionBarriers[node->barrierIdx]; + + while (node->nextIdx != InvalidNodeIndex) + { + node = &m_TransitionNodes[node->nextIdx]; + D3D12_RESOURCE_BARRIER& nextBarrier = m_TransitionBarriers[node->barrierIdx]; + + bool bFlattenable = + nextBarrier.Flags == D3D12_RESOURCE_BARRIER_FLAG_NONE && + pendingBarrier->Flags == D3D12_RESOURCE_BARRIER_FLAG_NONE; + + // If we can flatten, we don't need to emit a new barrier, we just fix up the pending one. + if (bFlattenable) + { + pendingBarrier->Transition.StateAfter = nextBarrier.Transition.StateAfter; + } + else + { + // Emit current barrier and reset. + m_Barriers.emplace_back(); + pendingBarrier = &m_Barriers.back(); + *pendingBarrier = nextBarrier; + } + } + + // Remove barrier if it ended up as a noop. + if (pendingBarrier->Transition.StateBefore == pendingBarrier->Transition.StateAfter) + { + m_Barriers.pop_back(); + } + } + + if (m_Barriers.size()) + { + commandList->ResourceBarrier((UINT)m_Barriers.size(), m_Barriers.data()); + m_Barriers.clear(); + } + + m_TransitionBarriers.clear(); + m_TransitionChains.clear(); + m_TransitionNodes.clear(); + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12ResourceBarrierCache.h b/src/Layers/xrRenderPC_R5/DX12/API/DX12ResourceBarrierCache.h new file mode 100644 index 00000000000..4b953ffd4f5 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12ResourceBarrierCache.h @@ -0,0 +1,71 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once + +#include "DX12.hpp" +#include + +namespace DX12 +{ + class ResourceBarrierCache + { + public: + ResourceBarrierCache() + { + m_Barriers.reserve(BarrierCountMax); + m_TransitionChains.reserve(BarrierCountMax); + m_TransitionNodes.reserve(BarrierCountMax); + m_TransitionBarriers.reserve(BarrierCountMax); + } + + void EnqueueTransition(ID3D12GraphicsCommandList* commandList, const D3D12_RESOURCE_BARRIER_FLAGS flags, const D3D12_RESOURCE_TRANSITION_BARRIER& barrier); + void EnqueueUAV(ID3D12GraphicsCommandList* commandList, Resource& resource); + void Flush(ID3D12GraphicsCommandList* commandList); + + inline bool IsFlushNeeded() const + { + return m_TransitionBarriers.size() || m_Barriers.size(); + } + + private: + static const u32 BarrierCountMax = 32; + static const u8 InvalidNodeIndex = -1; + + struct TransitionNode + { + u8 selfIdx; + u8 nextIdx; + u8 barrierIdx; + }; + + struct TransitionChainRoot + { + ID3D12Resource* resource; + u8 headIdx; + u8 tailIdx; + }; + + inline void TryCapacityFlush(ID3D12GraphicsCommandList* commandList) + { + if (u32(m_Barriers.size() + m_TransitionBarriers.size()) >= BarrierCountMax) + { + Flush(commandList); + } + } + + std::vector m_TransitionChains; + std::vector m_TransitionNodes; + std::vector m_TransitionBarriers; + std::vector m_Barriers; + }; +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12RootSignature.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12RootSignature.cpp new file mode 100644 index 00000000000..ad3a30081dc --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12RootSignature.cpp @@ -0,0 +1,628 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12RootSignature.hpp" +#include "DX12Device.hpp" + +#define DX12_DESCRIPTORTABLE_MERGERANGES_CBV 1 +#define DX12_DESCRIPTORTABLE_MERGERANGES_SRV 2 +#define DX12_DESCRIPTORTABLE_MERGERANGES_UAV 4 +#define DX12_DESCRIPTORTABLE_MERGERANGES_SMP 8 +#define DX12_DESCRIPTORTABLE_MERGERANGES_ALL (DX12_DESCRIPTORTABLE_MERGERANGES_SRV | DX12_DESCRIPTORTABLE_MERGERANGES_UAV | DX12_DESCRIPTORTABLE_MERGERANGES_SMP) +#define DX12_DESCRIPTORTABLE_MERGERANGES_MODE DX12_DESCRIPTORTABLE_MERGERANGES_ALL + +namespace DX12 +{ + PipelineLayout::PipelineLayout() + { + Clear(); + } + + void PipelineLayout::Build(Shader* vs, Shader* hs, Shader* ds, Shader* gs, Shader* ps) + { + Clear(); + + Shader* shaders[] = { ps, vs, hs, ds, gs }; + EShaderStage shaderStages[] = { ESS_Pixel, ESS_Vertex, ESS_Hull, ESS_Domain, ESS_Geometry }; + + for (size_t stageIdx = 0; stageIdx < DX12_ARRAY_SIZE(shaders); ++stageIdx) + { + if (shaders[stageIdx]) + { + u32 parameterCount = m_NumRootParameters; + AppendRootConstantBuffers(shaders[stageIdx], shaderStages[stageIdx]); + if (parameterCount != m_NumRootParameters) + { + m_ShaderStageAccess |= BIT(shaderStages[stageIdx]); + } + } + } + + for (size_t stageIdx = 0; stageIdx < DX12_ARRAY_SIZE(shaders); ++stageIdx) + { + if (shaders[stageIdx]) + { + u32 parameterCount = m_NumRootParameters; + AppendDescriptorTables(shaders[stageIdx], shaderStages[stageIdx]); + if (parameterCount != m_NumRootParameters) + { + m_ShaderStageAccess |= BIT(shaderStages[stageIdx]); + } + } + } + } + + void PipelineLayout::Build(Shader* cs) + { + Clear(); + + if (cs) + { + AppendRootConstantBuffers(cs, ESS_Compute); + AppendDescriptorTables(cs, ESS_Compute); + m_ShaderStageAccess |= ESS_Compute; + } + } + + void PipelineLayout::Clear() + { + m_ConstantViews.clear(); + m_TableResources.clear(); + m_Samplers.clear(); + + m_DescRangeCursor = 0; + m_NumDescriptors = 0; + m_NumDynamicSamplers = 0; + m_NumDescriptorTables = 0; + m_NumRootParameters = 0; + m_NumStaticSamplers = 0; + + m_ShaderStageAccess = ESS_None; + } + + void PipelineLayout::MakeDescriptorTable( + u32 rangeCursorEnd, + u32& rangeCursorBegin, + u32 offsetEnd, + u32& offsetBegin, + D3D12_DESCRIPTOR_HEAP_TYPE eHeap, + D3D12_SHADER_VISIBILITY visibility) + { + const u32 numRanges = rangeCursorEnd - rangeCursorBegin; + if (numRanges > 0) + { + PipelineLayout::DescriptorTableInfo tableInfo; + tableInfo.m_Type = eHeap; + tableInfo.m_Offset = offsetBegin; + m_DescriptorTables[m_NumDescriptorTables++] = tableInfo; + + // Setup the configuration of the root signature entry (a descriptor table range in this case) + m_RootParameters[m_NumRootParameters++].InitAsDescriptorTable(numRanges, m_DescRanges + rangeCursorBegin, visibility); + + rangeCursorBegin = rangeCursorEnd; + offsetBegin = offsetEnd; + } + } + + static D3D12_SHADER_VISIBILITY ToShaderVisibility(EShaderStage stage) + { + static const D3D12_SHADER_VISIBILITY visibility[] = + { + D3D12_SHADER_VISIBILITY_VERTEX, + D3D12_SHADER_VISIBILITY_HULL, + D3D12_SHADER_VISIBILITY_DOMAIN, + D3D12_SHADER_VISIBILITY_GEOMETRY, + D3D12_SHADER_VISIBILITY_PIXEL, + D3D12_SHADER_VISIBILITY_ALL + }; + + return visibility[stage]; + } + + static bool IsRootConstantBuffer(const ReflectedBindingRange& range) + { + return !range.m_bUsed || range.m_Count == 1; + } + + void PipelineLayout::AppendRootConstantBuffers(Shader* shader, EShaderStage shaderStage) + { + const D3D12_SHADER_VISIBILITY visibility = ToShaderVisibility(shaderStage); + + const ReflectedBindings& bindings = shader->GetReflectedBindings(); + + if (bindings.m_ConstantBuffers.m_DescriptorCount) + { + auto& ranges = bindings.m_ConstantBuffers.m_Ranges; + for (size_t rangeIdx = 0; rangeIdx < ranges.size(); ++rangeIdx) + { + const ReflectedBindingRange range = ranges[rangeIdx]; + + u32 rangeBegin = range.m_ShaderRegister; + u32 rangeEnd = range.m_ShaderRegister + range.m_Count; + + if (!IsRootConstantBuffer(range)) + { + continue; + } + + if (range.m_bShared) + { + bool bFound = false; + + // only pick up the first occurrence + for (const ConstantBufferLayoutBinding& binding : m_ConstantViews) + { + if (binding.ShaderSlot == rangeBegin) + { + bFound = true; + break; + } + } + + if (!bFound) + { + ConstantBufferLayoutBinding constant; + constant.ShaderStage = shaderStage; + constant.ShaderSlot = rangeBegin; + constant.RootParameterIndex = m_NumRootParameters; + m_ConstantViews.push_back(constant); + + m_RootParameters[m_NumRootParameters++].InitAsConstantBufferView(rangeBegin, 0, D3D12_SHADER_VISIBILITY_ALL); + } + } + else if (!range.m_bUsed) + { + // Setup the configuration of the root signature entry (a constant dummy CBV in this case) + for (u32 rootParameterIdx = rangeBegin; rootParameterIdx < rangeEnd; ++rootParameterIdx) + { + m_RootParameters[m_NumRootParameters++].InitAsConstantBufferView(rootParameterIdx, 0, visibility); + } + } + else + { + ConstantBufferLayoutBinding constant; + constant.ShaderStage = shaderStage; + constant.ShaderSlot = rangeBegin; + constant.RootParameterIndex = m_NumRootParameters; + m_ConstantViews.push_back(constant); + + m_RootParameters[m_NumRootParameters++].InitAsConstantBufferView(rangeBegin, 0, visibility); + } + } + } + } + + void PipelineLayout::AppendDescriptorTables(Shader* pShader, EShaderStage shaderStage) + { + const D3D12_SHADER_VISIBILITY visibility = ToShaderVisibility(shaderStage); + + const ReflectedBindings& bindings = pShader->GetReflectedBindings(); + + u32 rangeCursorBegin = m_DescRangeCursor; + u32 rangeCursorEnd = m_DescRangeCursor; + u32 descriptorBegin = m_NumDescriptors; + u32 descriptorEnd = m_NumDescriptors; + + if (bindings.m_ConstantBuffers.m_DescriptorCount) + { + auto& ranges = bindings.m_ConstantBuffers.m_Ranges; + for (size_t rangeIdx = 0; rangeIdx < ranges.size(); ++rangeIdx) + { + const ReflectedBindingRange range = ranges[rangeIdx]; + + u32 rangeBegin = range.m_ShaderRegister; + u32 rangeEnd = range.m_ShaderRegister + range.m_Count; + + if (IsRootConstantBuffer(range)) + { + continue; + } + + // Setup the configuration of the descriptor table range (a number of CBVs in this case) + m_DescRanges[rangeCursorEnd++].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, range.m_Count, range.m_ShaderRegister); + + for (size_t shaderRegister = rangeBegin; shaderRegister < rangeEnd; ++shaderRegister) + { + ResourceLayoutBinding bindingLayout; + ZeroMemory(&bindingLayout, sizeof(ResourceLayoutBinding)); + + bindingLayout.ViewType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; + bindingLayout.ShaderStage = shaderStage; + bindingLayout.ShaderSlot = shaderRegister; + +#ifdef GFX_DEBUG + bindingLayout.DescriptorOffset = descriptorEnd; +#endif + + m_TableResources.push_back(bindingLayout); + ++descriptorEnd; + } + + if (!(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_CBV)) + { + MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, descriptorEnd, descriptorBegin, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, visibility); + } + } + } + + if (!(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_SRV)) + { + MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, descriptorEnd, descriptorBegin, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, visibility); + } + + if (bindings.m_InputResources.m_DescriptorCount) + { + auto& ranges = bindings.m_InputResources.m_Ranges; + for (size_t rangeIdx = 0; rangeIdx < ranges.size(); ++rangeIdx) + { + const ReflectedBindingRange range = ranges[rangeIdx]; + u32 rangeBegin = range.m_ShaderRegister; + u32 rangeEnd = range.m_ShaderRegister + range.m_Count; + + if (!range.m_bUsed) + { + // Setup the configuration of the root signature entry (a constant dummy SRV in this case) + for (u32 rootParameterIdx = rangeBegin; rootParameterIdx < rangeEnd; ++rootParameterIdx) + { + m_RootParameters[m_NumRootParameters++].InitAsShaderResourceView(rootParameterIdx, 0, visibility); + } + + continue; + } + + // Setup the configuration of the descriptor table range (a number of SRVs in this case) + m_DescRanges[rangeCursorEnd++].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, range.m_Count, range.m_ShaderRegister); + + for (size_t shaderRegister = rangeBegin; shaderRegister < rangeEnd; ++shaderRegister) + { + ResourceLayoutBinding bindingLayout; + ZeroMemory(&bindingLayout, sizeof(ResourceLayoutBinding)); + + bindingLayout.ViewType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + bindingLayout.ShaderStage = shaderStage; + bindingLayout.ShaderSlot = shaderRegister; +#ifdef GFX_DEBUG + bindingLayout.DescriptorOffset = descriptorEnd; +#endif + m_TableResources.push_back(bindingLayout); + ++descriptorEnd; + } + + if (!(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_SRV)) + { + MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, descriptorEnd, descriptorBegin, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, visibility); + } + } + } + + if (!(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_UAV)) + { + MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, descriptorEnd, descriptorBegin, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, visibility); + } + + if (bindings.m_OutputResources.m_DescriptorCount) + { + auto& ranges = bindings.m_OutputResources.m_Ranges; + for (size_t rangeIdx = 0; rangeIdx < ranges.size(); ++rangeIdx) + { + const ReflectedBindingRange range = ranges[rangeIdx]; + u32 rangeBegin = range.m_ShaderRegister; + u32 rangeEnd = range.m_ShaderRegister + range.m_Count; + + if (!range.m_bUsed) + { + // Setup the configuration of the root signature entry (a constant dummy UAV in this case) + for (u32 rootParameterIdx = rangeBegin; rootParameterIdx < rangeEnd; ++rootParameterIdx) + { + m_RootParameters[m_NumRootParameters++].InitAsUnorderedAccessView(rootParameterIdx, 0, visibility); + } + + continue; + } + + // Setup the configuration of the descriptor table range (a number of UAVs in this case) + m_DescRanges[rangeCursorEnd++].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, range.m_Count, range.m_ShaderRegister); + + for (size_t shaderRegister = rangeBegin; shaderRegister < rangeEnd; ++shaderRegister) + { + ResourceLayoutBinding bindingLayout; + ZeroMemory(&bindingLayout, sizeof(ResourceLayoutBinding)); + + bindingLayout.ViewType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + bindingLayout.ShaderStage = shaderStage; + bindingLayout.ShaderSlot = shaderRegister; +#ifdef GFX_DEBUG + bindingLayout.DescriptorOffset = descriptorEnd; +#endif + m_TableResources.push_back(bindingLayout); + ++descriptorEnd; + } + + if (!(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_UAV)) + { + MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, descriptorEnd, descriptorBegin, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, visibility); + } + } + } + + if (DX12_DESCRIPTORTABLE_MERGERANGES_MODE != 0) + { + MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, descriptorEnd, descriptorBegin, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, visibility); + } + + m_NumDescriptors = descriptorEnd; + + u32 lastSamplers = m_NumDynamicSamplers; + u32 currentSamplers = m_NumDynamicSamplers; + + if (bindings.m_Samplers.m_DescriptorCount) + { + auto& ranges = bindings.m_Samplers.m_Ranges; + for (size_t rangeIdx = 0; rangeIdx < ranges.size(); ++rangeIdx) + { + const ReflectedBindingRange range = ranges[rangeIdx]; + u32 rangeBegin = range.m_ShaderRegister; + u32 rangeEnd = range.m_ShaderRegister + range.m_Count; + + if (!range.m_bUsed) + { + // Setup the configuration of the root signature entry (a constant dummy UAV in this case) + for (u32 rootParameterIdx = rangeBegin; rootParameterIdx < rangeEnd; ++rootParameterIdx) + { + __debugbreak(); + // m_StaticSamplers[m_NumStaticSamplers++].Init(rj, 0, ..., static_cast((stage + 1) % (D3D12_SHADER_VISIBILITY_PIXEL + 1))); + } + + continue; + } + + // Setup the configuration of the descriptor table range (a number of Samplers in this case) + m_DescRanges[rangeCursorEnd++].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, range.m_Count, range.m_ShaderRegister); + + for (size_t shaderRegister = rangeBegin; shaderRegister < rangeEnd; ++shaderRegister) + { + ResourceLayoutBinding bindingLayout; + ZeroMemory(&bindingLayout, sizeof(ResourceLayoutBinding)); + + bindingLayout.ViewType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; + bindingLayout.ShaderStage = shaderStage; + bindingLayout.ShaderSlot = shaderRegister; +#ifdef GFX_DEBUG + bindingLayout.DescriptorOffset = currentSamplers; +#endif + m_Samplers.push_back(bindingLayout); + ++currentSamplers; + } + + if (!(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_SMP)) + { + MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, currentSamplers, lastSamplers, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, visibility); + } + } + } + + if ((DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_SMP)) + { + MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, currentSamplers, lastSamplers, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, visibility); + } + + m_NumDynamicSamplers = currentSamplers; + m_DescRangeCursor = rangeCursorEnd; + } + + void PipelineLayout::DebugPrint() const + { + DX12_LOG("Root Signature:"); + for (u32 p = 0, r = 0; p < m_NumRootParameters; ++p) + { + DX12_LOG(" %s: %c [%2d to %2d] -> %s [%2d to %2d]", + m_RootParameters[p].ShaderVisibility == D3D12_SHADER_VISIBILITY_ALL ? "Every shader stage" : + m_RootParameters[p].ShaderVisibility == D3D12_SHADER_VISIBILITY_VERTEX ? "Vertex shader stage" : + m_RootParameters[p].ShaderVisibility == D3D12_SHADER_VISIBILITY_HULL ? "Hull shader stage" : + m_RootParameters[p].ShaderVisibility == D3D12_SHADER_VISIBILITY_DOMAIN ? "Domain shader stage" : + m_RootParameters[p].ShaderVisibility == D3D12_SHADER_VISIBILITY_GEOMETRY ? "Geometry shader stage" : + m_RootParameters[p].ShaderVisibility == D3D12_SHADER_VISIBILITY_PIXEL ? "Pixel shader stage" : "Unknown shader stage", + m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && m_RootParameters[p].DescriptorTable.pDescriptorRanges->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV ? 'C' : + m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && m_RootParameters[p].DescriptorTable.pDescriptorRanges->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV ? 'T' : + m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && m_RootParameters[p].DescriptorTable.pDescriptorRanges->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV ? 'U' : + m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && m_RootParameters[p].DescriptorTable.pDescriptorRanges->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER ? 'S' : + m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV ? 'c' : + m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV ? 't' : + m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV ? 'u' : '?', + m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE ? m_RootParameters[p].DescriptorTable.pDescriptorRanges->BaseShaderRegister : m_RootParameters[p].Descriptor.ShaderRegister, + m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE ? m_RootParameters[p].DescriptorTable.pDescriptorRanges->BaseShaderRegister + m_RootParameters[p].DescriptorTable.pDescriptorRanges->NumDescriptors : 1, + m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE ? "descriptor table" : + m_RootParameters[p].ParameterType != D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS ? "descriptor" : "32bit constant", + m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE ? m_DescriptorTables[r].m_Offset : -1, + m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE ? m_DescriptorTables[r].m_Offset + m_RootParameters[p].DescriptorTable.pDescriptorRanges->NumDescriptors : -1); + + r += m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + } + } + + RootSignature::RootSignature(Device* device) + : DeviceObject(device) + , m_nodeMask(0) + { + } + + RootSignature::~RootSignature() + { + } + + bool RootSignature::Init(const ComputeInitParams& params) + { + m_PipelineLayout.Build(params.m_ComputeShader); + return Init(CommandModeCompute); + } + + bool RootSignature::Init(const GraphicsInitParams& params) + { + m_PipelineLayout.Build( + params.m_VertexShader, + params.m_HullShader , + params.m_DomainShader, + params.m_GeometryShader, + params.m_PixelShader); + + return Init(CommandModeGraphics); + } + + bool RootSignature::Init(PipelineLayout& pipelineLayout, CommandMode commandType) + { + m_PipelineLayout = pipelineLayout; + return Init(commandType); + } + + bool RootSignature::Init(CommandMode commandType) + { + ID3D12RootSignature* rootSign = NULL; + CD3DX12_ROOT_SIGNATURE_DESC descRootSignature; + + if (commandType == CommandModeGraphics) + { + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; + flags |= (m_PipelineLayout.m_ShaderStageAccess & BIT(ESS_Vertex)) == 0 ? D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS : D3D12_ROOT_SIGNATURE_FLAG_NONE; + flags |= (m_PipelineLayout.m_ShaderStageAccess & BIT(ESS_Hull)) == 0 ? D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS : D3D12_ROOT_SIGNATURE_FLAG_NONE; + flags |= (m_PipelineLayout.m_ShaderStageAccess & BIT(ESS_Domain)) == 0 ? D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS : D3D12_ROOT_SIGNATURE_FLAG_NONE; + flags |= (m_PipelineLayout.m_ShaderStageAccess & BIT(ESS_Geometry)) == 0 ? D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS : D3D12_ROOT_SIGNATURE_FLAG_NONE; + flags |= (m_PipelineLayout.m_ShaderStageAccess & BIT(ESS_Pixel)) == 0 ? D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS : D3D12_ROOT_SIGNATURE_FLAG_NONE; + + descRootSignature.Init( + m_PipelineLayout.m_NumRootParameters, + m_PipelineLayout.m_RootParameters, + m_PipelineLayout.m_NumStaticSamplers, + m_PipelineLayout.m_StaticSamplers, + flags); + } + else + { + descRootSignature.Init( + m_PipelineLayout.m_NumRootParameters, + m_PipelineLayout.m_RootParameters, + 0, NULL, + D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS); + } + + { + ID3DBlob* pOutBlob = NULL; + ID3DBlob* pErrorBlob = NULL; + + if (S_OK != D3D12SerializeRootSignature(&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, &pOutBlob, &pErrorBlob)) + { + DX12_ERROR("Could not serialize root signature!"); + return false; + } + + if (S_OK != GetDevice()->GetD3D12Device()->CreateRootSignature(m_nodeMask, pOutBlob->GetBufferPointer(), pOutBlob->GetBufferSize(), IID_PPV_ARGS(&rootSign))) + { + DX12_ERROR("Could not create root signature!"); + return false; + } + + if (pOutBlob) + { + pOutBlob->Release(); + } + + if (pErrorBlob) + { + pErrorBlob->Release(); + } + } + + m_pRootSignature = rootSign; + rootSign->Release(); + return true; + } + + RootSignatureCache::RootSignatureCache() + { + } + + RootSignatureCache::~RootSignatureCache() + { + } + + bool RootSignatureCache::Init(Device* device) + { + m_pDevice = device; + return true; + } + + static const THash ComputeBit = 1; + + RootSignature* RootSignatureCache::AcquireRootSignature(const RootSignature::GraphicsInitParams& params) + { + struct HashKey + { + u32 vs; + u32 hs; + u32 ds; + u32 gs; + u32 ps; + } hashKey; + + hashKey.vs = params.m_VertexShader ? params.m_VertexShader->GetReflectedBindingHash() : 0; + hashKey.hs = params.m_HullShader ? params.m_HullShader->GetReflectedBindingHash() : 0; + hashKey.ds = params.m_DomainShader ? params.m_DomainShader->GetReflectedBindingHash() : 0; + hashKey.gs = params.m_GeometryShader ? params.m_GeometryShader->GetReflectedBindingHash() : 0; + hashKey.ps = params.m_PixelShader ? params.m_PixelShader->GetReflectedBindingHash() : 0; + + // LSB filled marks compute pipeline states, in case graphics and compute hashes collide + THash hash = ~ComputeBit & ComputeSmallHash(&hashKey); + { + auto iter = m_RootSignatureMap.find(hash); + if (iter != m_RootSignatureMap.end()) + { + return iter->second.get(); + } + } + + RootSignature* result = new RootSignature(m_pDevice); + if (!result->Init(params)) + { + DX12_ERROR("Could not create root signature!"); + return nullptr; + } + + m_RootSignatureMap[hash] = result; + return result; + } + + RootSignature* RootSignatureCache::AcquireRootSignature(const RootSignature::ComputeInitParams& params) + { + THash hash = ComputeBit | params.m_ComputeShader->GetReflectedBindingHash(); + { + auto iter = m_RootSignatureMap.find(hash); + if (iter != m_RootSignatureMap.end()) + { + return iter->second; + } + } + + RootSignature* result = new RootSignature(m_pDevice); + if (!result->Init(params)) + { + DX12_ERROR("Could not create root signature!"); + return nullptr; + } + + m_RootSignatureMap[hash] = result; + return result; + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12RootSignature.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12RootSignature.hpp new file mode 100644 index 00000000000..4f9cc322e47 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12RootSignature.hpp @@ -0,0 +1,158 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. + +#ifndef __DX12ROOTSIGNATURE__ +#define __DX12ROOTSIGNATURE__ + +#include "DX12Shader.hpp" + +namespace DX12 +{ + // Map of all pairs to descriptor-tables offsets (the CBV+SRV+UAV/SMP index is the offset) + struct ResourceLayoutBinding + { + D3D12_DESCRIPTOR_RANGE_TYPE ViewType; + EShaderStage ShaderStage; + uint8_t ShaderSlot; +#ifdef GFX_DEBUG + uint8_t DescriptorOffset; +#endif // !NDEBUG + }; + + struct ConstantBufferLayoutBinding + { + EShaderStage ShaderStage; + uint8_t ShaderSlot; + uint8_t RootParameterIndex; + }; + + struct PipelineLayout + { + std::vector m_ConstantViews; + std::vector m_TableResources; + std::vector m_Samplers; + + u32 m_ShaderStageAccess; + + // Memory holding all descriptor-ranges which will be added to the root-signature (basically a heap) + CD3DX12_DESCRIPTOR_RANGE m_DescRanges[256]; + u32 m_DescRangeCursor; + + // Consecutive list of all root-parameter descriptions of all types (points to m_DescRanges) + CD3DX12_ROOT_PARAMETER m_RootParameters[256]; + u32 m_NumRootParameters; + + // Static samplers, directly embedded in the shaders once PSO is created with correspondig root signature + D3D12_STATIC_SAMPLER_DESC m_StaticSamplers[16]; + u32 m_NumStaticSamplers; + + // Consecutive list of all descriptor-tables which are in the root-signature (without holes) + struct DescriptorTableInfo + { + D3D12_DESCRIPTOR_HEAP_TYPE m_Type; + u32 m_Offset; + }; + + DescriptorTableInfo m_DescriptorTables[256]; + u32 m_NumDescriptorTables; + + // Total number of resources bound to all shader stages (CBV+SRV+UAV) + size_t m_NumDescriptors; + + // Total number of samplers bound to all shader stages + size_t m_NumDynamicSamplers; + + PipelineLayout(); + + void Build(Shader* vs, Shader* hs, Shader* ds, Shader* gs, Shader* ps); + void Build(Shader* cs); + + void Clear(); + void DebugPrint() const; + + private: + void AppendDescriptorTables(Shader* pShader, EShaderStage eStage); + void AppendRootConstantBuffers(Shader* pShader, EShaderStage eStage); + void MakeDescriptorTable(u32 currentRangeCursor, u32& lastRangeCursor, u32 currentOffset, u32& lastOffset, D3D12_DESCRIPTOR_HEAP_TYPE eHeap, D3D12_SHADER_VISIBILITY eVisibility); + }; + + class RootSignature + : public DeviceObject + { + public: + struct GraphicsInitParams + { + Shader* m_VertexShader; + Shader* m_HullShader; + Shader* m_DomainShader; + Shader* m_GeometryShader; + Shader* m_PixelShader; + }; + + struct ComputeInitParams + { + Shader* m_ComputeShader; + }; + + RootSignature(Device* device); + ~RootSignature(); + + bool Init(const GraphicsInitParams& params); + bool Init(const ComputeInitParams& params); + bool Init(PipelineLayout& resourceMappings, CommandMode commandType); + + inline THash GetHash() const + { + return m_Hash; + } + + inline const PipelineLayout& GetPipelineLayout() const + { + return m_PipelineLayout; + } + + inline ID3D12RootSignature* GetD3D12RootSignature() const + { + return /*PassAddRef*/ (m_pRootSignature); + } + + private: + bool Init(CommandMode commandType); + + PipelineLayout m_PipelineLayout; + _smart_ptr m_pRootSignature; + u32 m_nodeMask; + THash m_Hash; + }; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + class RootSignatureCache + { + public: + RootSignatureCache(); + ~RootSignatureCache(); + + bool Init(Device* device); + + RootSignature* AcquireRootSignature(const RootSignature::ComputeInitParams& params); + RootSignature* AcquireRootSignature(const RootSignature::GraphicsInitParams& params); + + private: + Device* m_pDevice; + + std::unordered_map> m_RootSignatureMap; + }; +} + +#endif // __DX12ROOTSIGNATURE__ diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12SamplerState.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12SamplerState.cpp new file mode 100644 index 00000000000..a46f56f88d4 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12SamplerState.cpp @@ -0,0 +1,32 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or +* a third party where indicated. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12SamplerState.hpp" + +namespace DX12 +{ + //--------------------------------------------------------------------------------------------------------------------- + SamplerState::SamplerState() + : ReferenceCounted() + , m_DescriptorHandle(INVALID_CPU_DESCRIPTOR_HANDLE) + { + // clear before use + memset(&m_unSamplerDesc, 0, sizeof(m_unSamplerDesc)); + } + + //--------------------------------------------------------------------------------------------------------------------- + SamplerState::~SamplerState() + { + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12SamplerState.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12SamplerState.hpp new file mode 100644 index 00000000000..be81b773419 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12SamplerState.hpp @@ -0,0 +1,47 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once + +#include "DX12.hpp" + +namespace DX12 +{ + class SamplerState : public ReferenceCounted + { + public: + SamplerState(); + virtual ~SamplerState(); + + D3D12_SAMPLER_DESC& GetSamplerDesc() + { + // DX12_ASSERT(m_pResource && (m_pResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)); + return m_unSamplerDesc; + } + const D3D12_SAMPLER_DESC& GetSamplerDesc() const + { + // DX12_ASSERT(m_pResource && (m_pResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)); + return m_unSamplerDesc; + } + + void SetDescriptorHandle(const D3D12_CPU_DESCRIPTOR_HANDLE& descriptorHandle) { m_DescriptorHandle = descriptorHandle; } + D3D12_CPU_DESCRIPTOR_HANDLE GetDescriptorHandle() const { return m_DescriptorHandle; } + + private: + D3D12_CPU_DESCRIPTOR_HANDLE m_DescriptorHandle; + + union + { + D3D12_SAMPLER_DESC m_unSamplerDesc; + }; + }; +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12Shader.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12Shader.cpp new file mode 100644 index 00000000000..7c2991d6a50 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12Shader.cpp @@ -0,0 +1,235 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12Shader.hpp" + +#include +#include + +namespace DX12 +{ + namespace + { + + u32 MakeHash(ReflectedBindings& bindings) + { + const ReflectedBindingRangeList* lists[] = + { + &bindings.m_ConstantBuffers, + &bindings.m_InputResources, + &bindings.m_OutputResources, + &bindings.m_Samplers + }; + + hash::crc32 hash = 0; + + for (u32 i = 0; i < DX12_ARRAY_SIZE(lists); ++i) + { + const ReflectedBindingRangeList& list = *lists[i]; + if (list.m_DescriptorCount) + { + hash.Add(&i, sizeof(u32)); + hash.Add(list.m_Ranges.data(), list.m_Ranges.size() * sizeof(ReflectedBindingRange)); + } + } + + return hash; + } + + void AppendResourceToRanges( + ReflectedBindingRangeList& bindings, + u8 shaderRegister, + u8 count, + u8 type, + u8 dimension, + bool bUsed = true, + bool bShared = false, + bool bMergeable = true) + { + u32 rangeIdx = 0; + u32 rangeCount = bindings.m_Ranges.size(); + + // Attempts to merge a resource into an existing range. We can do this if + // the resource is marked as mergeable, and it's not shared across different + // shader stages. + bool bMerged = false; + + if (bMergeable && !bShared) + { + for (; rangeIdx < rangeCount; ++rangeIdx) + { + ReflectedBindingRange& r = bindings.m_Ranges[rangeIdx]; + if (r.m_bMergeable || r.m_bShared || (r.m_bUsed != bUsed)) + { + continue; // Non-Mergeable + } + + // Can we join new range with an existing one? + if (r.m_ShaderRegister + r.m_Count == shaderRegister) + { +#ifdef GFX_DEBUG + for (size_t j = 0; j < count; ++j) + { + r.m_Types[r.m_Count + j] = type; + r.m_Dimensions[r.m_Count + j] = dimension; + } +#endif + + r.m_Count += count; + bMerged = true; + break; + } + } + } + + if (!bMerged) + { + bindings.m_Ranges.push_back(ReflectedBindingRange(shaderRegister, count, type, dimension, bUsed, bShared, bMergeable)); + } + + bindings.m_DescriptorCount += count; + } + } + + Shader::Shader(Device* device) + : DeviceObject(device) + {} + + Shader::~Shader() + {} + + Shader* Shader::CreateFromD3D11(Device* device, const D3D12_SHADER_BYTECODE& byteCode) + { + ID3D11ShaderReflection* shaderReflection = NULL; + + // Reflect shader internals + if (S_OK != D3DReflect(byteCode.pShaderBytecode, byteCode.BytecodeLength, IID_ID3D11ShaderReflection, (void**)&shaderReflection)) + { + DX12_ASSERT(0, "Could not do a shader reflection!"); + return NULL; + } + + D3D11_SHADER_DESC desc11; + shaderReflection->GetDesc(&desc11); + + Shader* result = DX12::PassAddRef(new Shader(device)); + result->m_Bytecode = byteCode; + + for (UINT i = 0; i < desc11.BoundResources; ++i) + { + D3D11_SHADER_INPUT_BIND_DESC bindDesc11; + shaderReflection->GetResourceBindingDesc(i, &bindDesc11); + + bool bBindPointUsed = true; + bool bBindingSharable = + bindDesc11.BindPoint == eConstantBufferShaderSlot_PerMaterial || + bindDesc11.BindPoint == eConstantBufferShaderSlot_PerPass || + bindDesc11.BindPoint == eConstantBufferShaderSlot_PerView || + bindDesc11.BindPoint == eConstantBufferShaderSlot_PerFrame; + + bool bBindingMergeable = bindDesc11.BindPoint > eConstantBufferShaderSlot_PerInstanceLegacy; + + switch (bindDesc11.Type) + { + case D3D10_SIT_CBUFFER: + DX12_ASSERT(bindDesc11.BindCount == 1, "Arrays of ConstantBuffers are not allowed!"); + + if (bindDesc11.BindCount == 1) + { + ID3D11ShaderReflectionConstantBuffer* constantBuffer = shaderReflection->GetConstantBufferByName(bindDesc11.Name); + D3D11_SHADER_BUFFER_DESC constantBufferDesc; + UINT variableUsedCount = 0; + + constantBuffer->GetDesc(&constantBufferDesc); + for (UINT j = 0; j < constantBufferDesc.Variables; j++) + { + ID3D11ShaderReflectionVariable* variable = constantBuffer->GetVariableByIndex(j); + D3D11_SHADER_VARIABLE_DESC variableDesc; + variable->GetDesc(&variableDesc); + + variableUsedCount += (variableDesc.uFlags & D3D10_SVF_USED); + } + + bBindPointUsed = (variableUsedCount > 0); + } + + // We need separate descriptor tables for dynamic CB's + AppendResourceToRanges( + result->m_Bindings.m_ConstantBuffers, + bindDesc11.BindPoint, + bindDesc11.BindCount, + static_cast(bindDesc11.Type), + static_cast(bindDesc11.Dimension), + bBindPointUsed, + bBindingSharable, + bBindingMergeable); + break; + + // ID3D12Device::CreateGraphicsPipelineState: SRV or UAV root descriptors can only be Raw or Structured buffers. + case D3D10_SIT_TEXTURE: + case D3D10_SIT_TBUFFER: + AppendResourceToRanges( + result->m_Bindings.m_InputResources, + bindDesc11.BindPoint, + bindDesc11.BindCount, + static_cast(bindDesc11.Type), + static_cast(bindDesc11.Dimension)); + break; + case D3D11_SIT_STRUCTURED: + case D3D11_SIT_BYTEADDRESS: + AppendResourceToRanges( + result->m_Bindings.m_InputResources, + bindDesc11.BindPoint, + bindDesc11.BindCount, + static_cast(bindDesc11.Type), + static_cast(bindDesc11.Dimension), + bBindPointUsed); + break; + + case D3D11_SIT_UAV_RWTYPED: + AppendResourceToRanges( + result->m_Bindings.m_OutputResources, + bindDesc11.BindPoint, + bindDesc11.BindCount, + static_cast(bindDesc11.Type), + static_cast(bindDesc11.Dimension)); + break; + case D3D11_SIT_UAV_RWSTRUCTURED: + case D3D11_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: + case D3D11_SIT_UAV_RWBYTEADDRESS: + case D3D11_SIT_UAV_APPEND_STRUCTURED: + case D3D11_SIT_UAV_CONSUME_STRUCTURED: + AppendResourceToRanges(result->m_Bindings.m_OutputResources, + bindDesc11.BindPoint, + bindDesc11.BindCount, + static_cast(bindDesc11.Type), + static_cast(bindDesc11.Dimension), + bBindPointUsed); + break; + + case D3D10_SIT_SAMPLER: + DX12_ASSERT(bindDesc11.BindCount == 1, "Arrays of SamplerStates are not allowed!"); + AppendResourceToRanges( + result->m_Bindings.m_Samplers, + bindDesc11.BindPoint, + bindDesc11.BindCount, + static_cast(bindDesc11.Type), + static_cast(bindDesc11.Dimension)); + break; + } + } + + result->m_BindingHash = MakeHash(result->m_Bindings); + return result; + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12Shader.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12Shader.hpp new file mode 100644 index 00000000000..ce8fb2b33de --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12Shader.hpp @@ -0,0 +1,179 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once +#ifndef __DX12SHADER__ +#define __DX12SHADER__ + +#include "DX12.hpp" + +namespace DX12 +{ + enum EShaderStage : int8_t + { + // Graphics pipeline + ESS_Vertex, + ESS_Hull, + ESS_Domain, + ESS_Geometry, + ESS_Pixel, + + // Compute pipeline + ESS_Compute, + + // Complete pipeline + ESS_All = ESS_Compute, + + ESS_LastWithoutCompute = ESS_Compute, + ESS_Num = ESS_Compute + 1, + ESS_None = -1, + ESS_First = ESS_Vertex + }; + + enum EConstantBufferShaderSlot : uint8_t + { + // Reflected constant buffers: + // These are built by the shader system using the parameter system at + // shader compilation time and their format varies based on the permutation. + // + // These are deprecated and are being replaced by well-defined constant buffer definitions in HLSL. + eConstantBufferShaderSlot_PerBatch = 0, + eConstantBufferShaderSlot_PerInstanceLegacy = 1, + eConstantBufferShaderSlot_PerMaterial = 2, + eConstantBufferShaderSlot_ReflectedCount = + eConstantBufferShaderSlot_PerMaterial + 1, // This slot is used only for counting. It's not a real binding + // value. !Reflected constant buffers + + eConstantBufferShaderSlot_SPIIndex = 3, + eConstantBufferShaderSlot_PerInstance = 4, + eConstantBufferShaderSlot_SPI = 5, + eConstantBufferShaderSlot_SkinQuat = 6, + eConstantBufferShaderSlot_SkinQuatPrev = 7, + eConstantBufferShaderSlot_PerSubPass = 8, + eConstantBufferShaderSlot_PerPass = 9, + eConstantBufferShaderSlot_PerView = 10, + eConstantBufferShaderSlot_PerFrame = 11, + // OpenGLES 3.X guarantees only 12 uniform slots for VS and PS. + eConstantBufferShaderSlot_Count + }; + + struct ReflectedBindingRange + { + u8 m_ShaderRegister; + u8 m_Count; + + // Whether the bind point is actually used in the shader. Ideally, this is compiled out, but in order to support + // lower tier hardware we have to define a root parameter and bind a null descriptor for it. + u8 m_bUsed : 1; + + // Shared bindings are marked as visible across all shader stages. Practically, this means the binding + // is not merged and will be de-duplicated when the final layout is built. Candidates for sharing are constant + // buffers that are accessed by every stage and have a well-defined layout across all stages. + u8 m_bShared : 1; + + // We currently merge any range where the layout contents aren't reflected by the shader. Practically, + // this means that any constant buffer that's reflected gets placed into a root constant buffer parameter. + u8 m_bMergeable : 1; + +#ifdef GFX_DEBUG + u8 m_Types[56]; + u8 m_Dimensions[56]; +#endif + + ReflectedBindingRange() + : m_ShaderRegister(0) + , m_Count(0) + , m_bUsed(true) + , m_bShared(false) + , m_bMergeable(true) + {} + + ReflectedBindingRange( + u8 shaderRegister, + u8 count, + u8 type, + u8 dimension, + bool bUsed, + bool bShared, + bool bMergeable) + : m_ShaderRegister(shaderRegister) + , m_Count(count) + , m_bUsed(bUsed) + , m_bShared(bShared) + , m_bMergeable(bMergeable) + { +#ifdef GFX_DEBUG + for (u32 i = 0; i < count; ++i) + { + m_Types[i] = type; + m_Dimensions[i] = dimension; + } +#endif + } + }; + + struct ReflectedBindingRangeList + { + std::vector m_Ranges; + u32 m_DescriptorCount; + + ReflectedBindingRangeList() + : m_DescriptorCount(0) + {} + }; + + //////////////////////////////////////////////////////////////////////////// + + struct ReflectedBindings + { + ReflectedBindingRangeList m_ConstantBuffers; // CBV + ReflectedBindingRangeList m_InputResources; // SRV + ReflectedBindingRangeList m_OutputResources; // UAV + ReflectedBindingRangeList m_Samplers; // SMP + }; + + //////////////////////////////////////////////////////////////////////////// + + class Shader : public DeviceObject + { + public: + // Create new shader using DX11 reflection interface + static Shader* CreateFromD3D11(Device* device, const D3D12_SHADER_BYTECODE& byteCode); + + Shader(Device* device); + + const D3D12_SHADER_BYTECODE& GetBytecode() const + { + return m_Bytecode; + } + + const ReflectedBindings& GetReflectedBindings() const + { + return m_Bindings; + } + + const u32 GetReflectedBindingHash() const + { + return m_BindingHash; + } + + protected: + virtual ~Shader(); + + private: + D3D12_SHADER_BYTECODE m_Bytecode; + ReflectedBindings m_Bindings; + u32 m_BindingHash; + }; +} + +#endif // __DX12SHADER__ diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12SwapChain.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12SwapChain.cpp new file mode 100644 index 00000000000..fd4cf940d98 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12SwapChain.cpp @@ -0,0 +1,123 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12SwapChain.hpp" + +namespace DX12 +{ + SwapChain* SwapChain::Create( + CommandList* commandList, + IDXGIFactory4* pFactory, + DXGI_SWAP_CHAIN_DESC* pDesc) + { + IDXGISwapChain* dxgiSwapChain = NULL; + IDXGISwapChain3* dxgiSwapChain3 = NULL; + ID3D12CommandQueue* commandQueue = commandList->GetD3D12CommandQueue(); + + // If discard isn't implemented/supported/fails, try the newer swap-types + // - flip_discard is win 10 + // - flip_sequentially is win 8 + HRESULT hr; + if (pDesc->SwapEffect == DXGI_SWAP_EFFECT_DISCARD) + { + pDesc->SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + pDesc->BufferCount = std::max(2U, pDesc->BufferCount); + hr = pFactory->CreateSwapChain(commandQueue, pDesc, &dxgiSwapChain); + } + else if (pDesc->SwapEffect == DXGI_SWAP_EFFECT_SEQUENTIAL) + { + pDesc->SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + pDesc->BufferCount = std::max(2U, pDesc->BufferCount); + hr = pFactory->CreateSwapChain(commandQueue, pDesc, &dxgiSwapChain); + } + else + { + hr = pFactory->CreateSwapChain(commandQueue, pDesc, &dxgiSwapChain); + } + + if (hr == S_OK && dxgiSwapChain) + { + hr = dxgiSwapChain->QueryInterface(IID_PPV_ARGS(&dxgiSwapChain3)); + dxgiSwapChain->Release(); + + if (hr == S_OK && dxgiSwapChain3) + { + return DX12::PassAddRef(new SwapChain(commandList, dxgiSwapChain3, pDesc)); + } + } + + return nullptr; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + SwapChain::SwapChain(CommandList* commandList, IDXGISwapChain3* dxgiSwapChain, DXGI_SWAP_CHAIN_DESC* pDesc) + : ReferenceCounted() + , m_CommandList(commandList) + , m_AsyncQueue(commandList->GetCommandListPool().GetAsyncCommandQueue()) + { + if (pDesc) + { + m_Desc = *pDesc; + } + else + { + dxgiSwapChain->GetDesc(&m_Desc); + } + + m_NativeSwapChain = dxgiSwapChain; + dxgiSwapChain->Release(); + } + + SwapChain::~SwapChain() + { + //m_NativeSwapChain->Release(); + ForfeitBuffers(); + } + + HRESULT SwapChain::Present(u32 SyncInterval, u32 Flags) + { + m_AsyncQueue.Flush(); + + HRESULT hr = m_NativeSwapChain->Present(SyncInterval, Flags); + return hr; + } + + HRESULT SwapChain::Present1(u32 SyncInterval, u32 Flags, + const DXGI_PRESENT_PARAMETERS* pPresentParameters) + { + m_AsyncQueue.Flush(); + + HRESULT hr = m_NativeSwapChain->Present1(SyncInterval, Flags, pPresentParameters); + return hr; + } + + void SwapChain::AcquireBuffers(std::vector&& buffers) + { + R_ASSERT2(m_BackBuffers.empty(), "must forfeit buffers before assigning"); + + m_BackBuffers = std::move(buffers); + m_BackBufferViews.reserve(buffers.size()); + for (Resource* buffer : m_BackBuffers) + { + m_BackBufferViews.emplace_back(); + m_BackBufferViews.back().Init(*buffer, EVT_RenderTargetView); + } + } + + void SwapChain::ForfeitBuffers() + { + m_BackBuffers.clear(); + m_BackBufferViews.clear(); + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12SwapChain.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12SwapChain.hpp new file mode 100644 index 00000000000..1d829b6f245 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12SwapChain.hpp @@ -0,0 +1,96 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once +#ifndef __DX12SWAPCHAIN__ +#define __DX12SWAPCHAIN__ + +#include "DX12.hpp" +#include "DX12Device.hpp" +#include "DX12CommandList.hpp" +#include "DX12AsyncCommandQueue.hpp" + +#include + +namespace DX12 +{ + class SwapChain : public ReferenceCounted + { + public: + static SwapChain* Create(CommandList* pDevice, IDXGIFactory4* factory, DXGI_SWAP_CHAIN_DESC* pDesc); + + protected: + SwapChain(CommandList* pDevice, IDXGISwapChain3* dxgiSwapChain, DXGI_SWAP_CHAIN_DESC* pDesc); + + virtual ~SwapChain(); + + public: + inline IDXGISwapChain3* GetDXGISwapChain() const + { + return m_NativeSwapChain; + } + + inline Resource& GetBackBuffer(u32 index) + { + Resource* resource = m_BackBuffers[index]; + R_ASSERT2(resource, "null backbuffer"); + return *resource; + } + inline Resource& GetCurrentBackBuffer() + { + Resource* resource = m_BackBuffers[m_NativeSwapChain->GetCurrentBackBufferIndex()]; + R_ASSERT2(resource, "Resource is null"); + return *resource; + } + + inline ResourceView& GetBackBufferView(u32 index) + { + return m_BackBufferViews[index]; + } + + inline ResourceView& GetCurrentBackBufferView() + { + return m_BackBufferViews[m_NativeSwapChain->GetCurrentBackBufferIndex()]; + } + + inline u32 GetCurrentBackBufferIndex() const + { + return m_NativeSwapChain->GetCurrentBackBufferIndex(); + } + + inline const DXGI_SWAP_CHAIN_DESC& GetDesc() const + { + return m_Desc; + } + + HRESULT Present(u32 SyncInterval, u32 Flags); + + HRESULT Present1(u32 SyncInterval, u32 Flags, const DXGI_PRESENT_PARAMETERS* pPresentParameters); + + private: + friend class CCryDX12SwapChain; + void AcquireBuffers(std::vector&& resource); + void ForfeitBuffers(); + + AsyncCommandQueue& m_AsyncQueue; + CommandList* m_CommandList; + + DXGI_SWAP_CHAIN_DESC m_Desc; + + _smart_ptr m_NativeSwapChain; + + std::vector m_BackBuffers; + std::vector m_BackBufferViews; + }; +} + +#endif // __DX12SWAPCHAIN__ diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12TimerHeap.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12TimerHeap.cpp new file mode 100644 index 00000000000..a75dacea9bc --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12TimerHeap.cpp @@ -0,0 +1,123 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12TimerHeap.h" +#include "DX12Device.hpp" +#include "DX12CommandList.hpp" + +namespace DX12 +{ + TimerHeap::TimerHeap(Device& device) + : m_TimerCountMax{} + , m_TimestampDownloadBuffer{} + , m_TimestampHeap{ &device } + {} + + void TimerHeap::Init(u32 timerCountMax) + { + Shutdown(); + + D3D12_QUERY_HEAP_DESC m_Desc; + m_Desc.NodeMask = 1; + m_Desc.Type = D3D12_QUERY_HEAP_TYPE_TIMESTAMP; + m_Desc.Count = timerCountMax * 2; + + Device& device = *m_TimestampHeap.GetDevice(); + + m_TimerCountMax = timerCountMax; + m_TimestampHeap.Init(m_TimestampHeap.GetDevice(), m_Desc); + + CD3DX12_HEAP_PROPERTIES propertyReadback(D3D12_HEAP_TYPE_READBACK); + CD3DX12_RESOURCE_DESC buffer = CD3DX12_RESOURCE_DESC::Buffer(sizeof(UINT64) * m_TimestampHeap.GetCapacity()); + + ID3D12Resource* resource = nullptr; + if (S_OK != device.GetD3D12Device()->CreateCommittedResource(&propertyReadback, + D3D12_HEAP_FLAG_NONE, + &buffer, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&resource))) + { + DX12_ERROR("Could not create intermediate timestamp download buffer!"); + } + + m_TimestampDownloadBuffer.attach(resource); + m_Timers.reserve(timerCountMax); + } + + void TimerHeap::Shutdown() + { + m_TimestampHeap.Reset(); + m_TimestampDownloadBuffer.reset(); + m_Timers.clear(); + m_TimerCountMax = 0; + } + + void TimerHeap::Begin() + { + m_Timers.clear(); + } + + void TimerHeap::End(CommandList& commandList) + { + commandList.ResolveQueryData(m_TimestampHeap, D3D12_QUERY_TYPE_TIMESTAMP, 0, m_TimestampHeap.GetCapacity(), m_TimestampDownloadBuffer, 0); + } + + TimerHandle TimerHeap::BeginTimer(CommandList& commandList, const char* name) + { + if (m_Timers.size() < m_TimerCountMax) + { + TimerHandle handle = TimerHandle(m_Timers.size()); + + m_Timers.emplace_back(); + + Timer& timer = m_Timers.back(); + timer.m_Name = name; + timer.m_Duration = 0; + timer.m_Timestamp = 0; + + commandList.EndQuery(m_TimestampHeap, D3D12_QUERY_TYPE_TIMESTAMP, handle * 2); + return handle; + } + + return TimerHandle(-1); + } + + void TimerHeap::EndTimer(CommandList& commandList, TimerHandle handle) + { + if (handle != TimerHandle(-1)) + { + commandList.EndQuery(m_TimestampHeap, D3D12_QUERY_TYPE_TIMESTAMP, handle * 2 + 1); + } + } + + void TimerHeap::ReadbackTimers() + { + u64* timestamps = nullptr; + const D3D12_RANGE readRange = { 0, sizeof(UINT64) * m_TimestampHeap.GetCapacity() }; + m_TimestampDownloadBuffer->Map(0, &readRange, (void**)×tamps); + + Device& device = *m_TimestampHeap.GetDevice(); + + for (u64 i = 0; i < m_Timers.size(); ++i) + { + u64 timestampBegin = device.MakeCpuTimestampMicroseconds(timestamps[i * 2]); + u64 timestampEnd = device.MakeCpuTimestampMicroseconds(timestamps[i * 2 + 1]); + + m_Timers[i].m_Timestamp = timestampBegin; + m_Timers[i].m_Duration = u32(timestampEnd - timestampBegin); + } + + m_TimestampDownloadBuffer->Unmap(0, nullptr); + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12TimerHeap.h b/src/Layers/xrRenderPC_R5/DX12/API/DX12TimerHeap.h new file mode 100644 index 00000000000..e6f8d0c728f --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12TimerHeap.h @@ -0,0 +1,97 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once + +#include "DX12QueryHeap.hpp" + +#include + +#define DX12_GPU_PROFILE_MODE_OFF 0 // Turn off profiling +#define DX12_GPU_PROFILE_MODE_BASIC 1 // Profiles command list lifetime +#define DX12_GPU_PROFILE_MODE_DETAIL 2 // Profiles draw call state changes +#define DX12_GPU_PROFILE_MODE DX12_GPU_PROFILE_MODE_OFF + +namespace DX12 +{ + struct Timer + { + const char* m_Name; + u64 m_Timestamp; + u32 m_Duration; + }; + + class CommandList; + + using TimerHandle = u32; + + class TimerHeap + { + public: + TimerHeap(Device& device); + + void Init(u32 timerCountMax); + void Shutdown(); + + void Begin(); + void End(CommandList& commandList); + + TimerHandle BeginTimer(CommandList& commandList, const char* name); + void EndTimer(CommandList& commandList, TimerHandle handle); + + void ReadbackTimers(); + + const std::vector& GetTimers() const + { + return m_Timers; + } + + private: + QueryHeap m_TimestampHeap; + _smart_ptr m_TimestampDownloadBuffer; + std::vector m_Timers; + u32 m_TimerCountMax; + }; + + class ScopedTimer + { + public: + ScopedTimer(TimerHeap& timers, CommandList& commandList, const char* name) + : m_Timers(timers) + , m_CommandList(commandList) + { + m_Handle = timers.BeginTimer(commandList, name); + } + + ~ScopedTimer() + { + m_Timers.EndTimer(m_CommandList, m_Handle); + } + + private: + TimerHeap& m_Timers; + CommandList& m_CommandList; + TimerHandle m_Handle; + }; +} + + // Conditionally disable timing at compile-time based on profile policy +#if DX12_GPU_PROFILE_MODE == DX12_GPU_PROFILE_MODE_DETAIL +#define DX12_COMMANDLIST_TIMER(name) DX12::ScopedTimer timer__(m_Timers, *this, name); +#define DX12_COMMANDLIST_TIMER_DETAIL(name) DX12_COMMANDLIST_TIMER(name) +#elif DX12_GPU_PROFILE_MODE == DX12_GPU_PROFILE_MODE_BASIC +#define DX12_COMMANDLIST_TIMER(name) DX12::ScopedTimer timer__(m_Timers, *this, name); +#define DX12_COMMANDLIST_TIMER_DETAIL(name) +#else +#define DX12_COMMANDLIST_TIMER(name) +#define DX12_COMMANDLIST_TIMER_DETAIL(name) +#endif diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12View.cpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12View.cpp new file mode 100644 index 00000000000..1704893c17e --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12View.cpp @@ -0,0 +1,151 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "DX12View.hpp" +#include "DX12Device.hpp" +#include "DX12Resource.hpp" +#include "DX12SwapChain.hpp" + +namespace DX12 +{ + //--------------------------------------------------------------------------------------------------------------------- + ResourceView::ResourceView() + : ReferenceCounted() + , m_pResource(nullptr) + , m_DescriptorHandle(INVALID_CPU_DESCRIPTOR_HANDLE) + , m_Type(EVT_Unknown) + , m_HasDesc(true) + , m_Size(0) + { + // clear before use + memset(&m_unDSVDesc, 0, sizeof(m_unDSVDesc)); + memset(&m_unRTVDesc, 0, sizeof(m_unRTVDesc)); + memset(&m_unVBVDesc, 0, sizeof(m_unVBVDesc)); + memset(&m_unCBVDesc, 0, sizeof(m_unCBVDesc)); + memset(&m_unSRVDesc, 0, sizeof(m_unSRVDesc)); + memset(&m_unUAVDesc, 0, sizeof(m_unUAVDesc)); + } + + ResourceView::ResourceView(ResourceView&& v) + : m_pResource(std::move(v.m_pResource)) + , m_DescriptorHandle(std::move(v.m_DescriptorHandle)) + , m_Type(std::move(v.m_Type)) + , m_HasDesc(std::move(v.m_HasDesc)) + , m_Size(std::move(v.m_Size)) + { + m_unDSVDesc = std::move(v.m_unDSVDesc); + m_unRTVDesc = std::move(v.m_unRTVDesc); + m_unVBVDesc = std::move(v.m_unVBVDesc); + m_unCBVDesc = std::move(v.m_unCBVDesc); + m_unSRVDesc = std::move(v.m_unSRVDesc); + m_unUAVDesc = std::move(v.m_unUAVDesc); + + v.m_pResource = nullptr; + v.m_DescriptorHandle = INVALID_CPU_DESCRIPTOR_HANDLE; + } + + ResourceView& ResourceView::operator=(ResourceView&& v) + { + m_pResource = std::move(v.m_pResource); + m_DescriptorHandle = std::move(v.m_DescriptorHandle); + m_Type = std::move(v.m_Type); + m_HasDesc = std::move(v.m_HasDesc); + m_Size = std::move(v.m_Size); + + m_unDSVDesc = std::move(v.m_unDSVDesc); + m_unRTVDesc = std::move(v.m_unRTVDesc); + m_unVBVDesc = std::move(v.m_unVBVDesc); + m_unCBVDesc = std::move(v.m_unCBVDesc); + m_unSRVDesc = std::move(v.m_unSRVDesc); + m_unUAVDesc = std::move(v.m_unUAVDesc); + + v.m_pResource = nullptr; + v.m_DescriptorHandle = INVALID_CPU_DESCRIPTOR_HANDLE; + + return *this; + } + + //--------------------------------------------------------------------------------------------------------------------- + ResourceView::~ResourceView() + { + } + + //--------------------------------------------------------------------------------------------------------------------- + //template + ID3D12Resource* ResourceView::GetD3D12Resource() const + { + return m_pResource->GetD3D12Resource(); + } + + //--------------------------------------------------------------------------------------------------------------------- + bool ResourceView::Init(Resource& resource, EViewType type, UINT64 size) + { + DX12_ASSERT(type != EVT_Unknown); + const D3D12_RESOURCE_DESC& desc = resource.GetDesc(); + + m_pResource = &resource; + m_Type = type; + m_Size = size; + + switch (type) + { + case EVT_VertexBufferView: + m_unVBVDesc.BufferLocation = resource.GetGPUVirtualAddress(); + m_unVBVDesc.SizeInBytes = static_cast(m_Size); + break; + + case EVT_IndexBufferView: + m_unIBVDesc.BufferLocation = resource.GetGPUVirtualAddress(); + m_unIBVDesc.SizeInBytes = static_cast(m_Size); + break; + + case EVT_ConstantBufferView: + // Align to 256 bytes as required by DX12 + m_Size = (m_Size + 255) & ~255; + + m_unCBVDesc.BufferLocation = resource.GetGPUVirtualAddress(); + m_unCBVDesc.SizeInBytes = static_cast(m_Size); + break; + + // The *View descriptions have all the same structure and identical enums + case EVT_ShaderResourceView: + case EVT_UnorderedAccessView: + case EVT_DepthStencilView: + case EVT_RenderTargetView: + m_unSRVDesc.Format = desc.Format; + + switch (desc.Dimension) + { + case D3D12_RESOURCE_DIMENSION_BUFFER: + m_unSRVDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + break; + case D3D12_RESOURCE_DIMENSION_TEXTURE1D: + m_unSRVDesc.ViewDimension = desc.DepthOrArraySize <= 1 ? D3D12_SRV_DIMENSION_TEXTURE1D : D3D12_SRV_DIMENSION_TEXTURE1DARRAY; + break; + case D3D12_RESOURCE_DIMENSION_TEXTURE2D: + m_unSRVDesc.ViewDimension = desc.DepthOrArraySize <= 1 ? (desc.SampleDesc.Count <= 1 ? D3D12_SRV_DIMENSION_TEXTURE2D : D3D12_SRV_DIMENSION_TEXTURE2DMS) : (desc.SampleDesc.Count <= 1 ? D3D12_SRV_DIMENSION_TEXTURE2DARRAY : D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY); + break; + case D3D12_RESOURCE_DIMENSION_TEXTURE3D: + m_unSRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; + break; + + default: + DX12_NOT_IMPLEMENTED; + break; + } + break; + } + + return true; + } +} diff --git a/src/Layers/xrRenderPC_R5/DX12/API/DX12View.hpp b/src/Layers/xrRenderPC_R5/DX12/API/DX12View.hpp new file mode 100644 index 00000000000..386d16d85c1 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/API/DX12View.hpp @@ -0,0 +1,192 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once +#ifndef __DX12VIEW__ +#define __DX12VIEW__ + +#include "DX12.hpp" + +namespace DX12 +{ + class SwapChain; + + enum EViewType + { + EVT_Unknown = 0, + EVT_VertexBufferView, + EVT_IndexBufferView, + EVT_ConstantBufferView, + EVT_ShaderResourceView, + EVT_UnorderedAccessView, + EVT_DepthStencilView, + EVT_RenderTargetView + }; + + class ResourceView + : public ReferenceCounted + { + public: + ResourceView(); + virtual ~ResourceView(); + + ResourceView(ResourceView&& r); + ResourceView& operator=(ResourceView&& r); + + bool Init(Resource& resource, EViewType type, UINT64 size = 0); + + //template + ID3D12Resource* GetD3D12Resource() const; + + IC Resource& GetDX12Resource() const + { + return *m_pResource; + } + + IC void SetType(EViewType evt) + { + m_Type = evt; + } + IC EViewType GetType() const + { + return m_Type; + } + + IC void HasDesc(bool has) + { + m_HasDesc = has; + } + IC bool HasDesc() const + { + return m_HasDesc; + } + + IC void SetSize(UINT64 size) + { + m_Size = size; + } + IC UINT64 GetSize() const + { + return m_Size; + } + + IC D3D12_DEPTH_STENCIL_VIEW_DESC& GetDSVDesc() + { + // DX12_ASSERT(m_pResource && (m_pResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)); + return m_unDSVDesc; + } + IC const D3D12_DEPTH_STENCIL_VIEW_DESC& GetDSVDesc() const + { + // DX12_ASSERT(m_pResource && (m_pResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)); + return m_unDSVDesc; + } + + IC D3D12_RENDER_TARGET_VIEW_DESC& GetRTVDesc() + { + // DX12_ASSERT(m_pResource && (m_pResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)); + return m_unRTVDesc; + } + IC const D3D12_RENDER_TARGET_VIEW_DESC& GetRTVDesc() const + { + // DX12_ASSERT(m_pResource && (m_pResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)); + return m_unRTVDesc; + } + + IC D3D12_VERTEX_BUFFER_VIEW& GetVBVDesc() + { + // DX12_ASSERT(m_pResource && true); + return m_unVBVDesc; + } + IC const D3D12_VERTEX_BUFFER_VIEW& GetVBVDesc() const + { + // DX12_ASSERT(m_pResource && true); + return m_unVBVDesc; + } + + IC D3D12_INDEX_BUFFER_VIEW& GetIBVDesc() + { + // DX12_ASSERT(m_pResource && true); + return m_unIBVDesc; + } + IC const D3D12_INDEX_BUFFER_VIEW& GetIBVDesc() const + { + // DX12_ASSERT(m_pResource && true); + return m_unIBVDesc; + } + + IC D3D12_CONSTANT_BUFFER_VIEW_DESC& GetCBVDesc() + { + // DX12_ASSERT(m_pResource && true); + return m_unCBVDesc; + } + IC const D3D12_CONSTANT_BUFFER_VIEW_DESC& GetCBVDesc() const + { + // DX12_ASSERT(m_pResource && true); + return m_unCBVDesc; + } + + IC D3D12_SHADER_RESOURCE_VIEW_DESC& GetSRVDesc() + { + // DX12_ASSERT(m_pResource && true); + return m_unSRVDesc; + } + IC const D3D12_SHADER_RESOURCE_VIEW_DESC& GetSRVDesc() const + { + // DX12_ASSERT(m_pResource && true); + return m_unSRVDesc; + } + + IC D3D12_UNORDERED_ACCESS_VIEW_DESC& GetUAVDesc() + { + // DX12_ASSERT(m_pResource && (m_pResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)); + return m_unUAVDesc; + } + IC const D3D12_UNORDERED_ACCESS_VIEW_DESC& GetUAVDesc() const + { + // DX12_ASSERT(m_pResource && (m_pResource->GetDesc().Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)); + return m_unUAVDesc; + } + + IC void SetDescriptorHandle(const D3D12_CPU_DESCRIPTOR_HANDLE& descriptorHandle) + { + m_DescriptorHandle = descriptorHandle; + } + IC D3D12_CPU_DESCRIPTOR_HANDLE GetDescriptorHandle() const + { + return m_DescriptorHandle; + } + + private: + Resource* m_pResource; + EViewType m_Type; + D3D12_CPU_DESCRIPTOR_HANDLE m_DescriptorHandle; + + union + { + D3D12_VERTEX_BUFFER_VIEW m_unVBVDesc; + D3D12_INDEX_BUFFER_VIEW m_unIBVDesc; + D3D12_CONSTANT_BUFFER_VIEW_DESC m_unCBVDesc; + D3D12_SHADER_RESOURCE_VIEW_DESC m_unSRVDesc; + D3D12_UNORDERED_ACCESS_VIEW_DESC m_unUAVDesc; + D3D12_DEPTH_STENCIL_VIEW_DESC m_unDSVDesc; + D3D12_RENDER_TARGET_VIEW_DESC m_unRTVDesc; + }; + + // Some views can be created without descriptor (DSV) + bool m_HasDesc; + + // View size in bytes + UINT64 m_Size; + }; +} + +#endif // __DX12VIEW__ diff --git a/src/Layers/xrRenderPC_R5/DX12/CCryDX12Object.cpp b/src/Layers/xrRenderPC_R5/DX12/CCryDX12Object.cpp new file mode 100644 index 00000000000..4393f61ca3b --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/CCryDX12Object.cpp @@ -0,0 +1,15 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or +* a third party where indicated. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "CCryDX12Object.hpp" diff --git a/src/Layers/xrRenderPC_R5/DX12/CCryDX12Object.hpp b/src/Layers/xrRenderPC_R5/DX12/CCryDX12Object.hpp new file mode 100644 index 00000000000..9328bd4cfaa --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/CCryDX12Object.hpp @@ -0,0 +1,199 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once +#ifndef __CCRYDX12OBJECT__ +#define __CCRYDX12OBJECT__ + +#include "API/DX12.hpp" + +#define DX12_BASE_OBJECT(DerivedType, InterfaceType) \ + typedef DerivedType Class; \ + typedef _smart_ptr Ptr; \ + typedef _smart_ptr ConstPtr; \ + typedef InterfaceType Super; \ + typedef InterfaceType Interface; \ + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) \ + { \ + if (riid == __uuidof(Super)) \ + { \ + if (ppvObject) \ + { \ + *reinterpret_cast(ppvObject) = static_cast(this); \ + static_cast(this)->AddRef(); \ + } \ + return S_OK; \ + } \ + return E_NOINTERFACE; \ + } \ + +#define DX12_OBJECT(DerivedType, SuperType) \ + typedef DerivedType Class; \ + typedef _smart_ptr Ptr; \ + typedef _smart_ptr ConstPtr; \ + typedef SuperType Super; \ + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) \ + { \ + if (riid == __uuidof(DerivedType)) \ + { \ + if (ppvObject) \ + { \ + *reinterpret_cast(ppvObject) = static_cast(this); \ + static_cast(this)->AddRef(); \ + } \ + return S_OK; \ + } \ + return Super::QueryInterface(riid, ppvObject); \ + } \ + +#include "CryDX12Guid.hpp" + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +class CCryDX12Buffer; +class CCryDX12DepthStencilView; +class CCryDX12Device; +class CCryDX12DeviceContext; +class CCryDX12MemoryManager; +class CCryDX12Query; +class CCryDX12RenderTargetView; +class CCryDX12SamplerState; +class CCryDX12Shader; +class CCryDX12ShaderResourceView; +class CCryDX12SwapChain; +class CCryDX12Texture1D; +class CCryDX12Texture2D; +class CCryDX12Texture3D; +class CCryDX12UnorderedAccessView; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template +class CCryDX12Object + : public T +{ +public: + DX12_BASE_OBJECT(CCryDX12Object, T); + + CCryDX12Object() + : m_RefCount(0) + { + } + + virtual ~CCryDX12Object() + { + DX12_LOG("CCryDX12 object destroyed: %p", this); + } + + #pragma region /* IUnknown implementation */ + + virtual ULONG STDMETHODCALLTYPE AddRef() + { + return InterlockedIncrement((volatile LONG*)&m_RefCount); + } + + virtual ULONG STDMETHODCALLTYPE Release() + { + ULONG RefCount; + if (!(RefCount = InterlockedDecrement((volatile LONG*)&m_RefCount))) + { + delete this; + return 0; + } + + return RefCount; + } + + #pragma endregion + +private: + int m_RefCount; +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template +class CCryDX12GIObject + : public T +{ +public: + DX12_BASE_OBJECT(CCryDX12GIObject, T); + + CCryDX12GIObject() + : m_RefCount(0) + { + } + + virtual ~CCryDX12GIObject() + { + } + + #pragma region /* IUnknown implementation */ + + virtual ULONG STDMETHODCALLTYPE AddRef() + { + return InterlockedIncrement((volatile LONG*)&m_RefCount); + } + + virtual ULONG STDMETHODCALLTYPE Release() + { + ULONG RefCount; + if (!(RefCount = InterlockedDecrement((volatile LONG*)&m_RefCount))) + { + delete this; + return 0; + } + + return RefCount; + } + + #pragma endregion + + #pragma region /* IDXGIObject implementation */ + + virtual HRESULT STDMETHODCALLTYPE SetPrivateData( + _In_ REFGUID Name, + UINT DataSize, + _In_reads_bytes_(DataSize) const void* pData) + { + return -1; + } + + virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + _In_ REFGUID Name, + _In_ const IUnknown* pUnknown) + { + return -1; + } + + virtual HRESULT STDMETHODCALLTYPE GetPrivateData( + _In_ REFGUID Name, + _Inout_ UINT* pDataSize, + _Out_writes_bytes_(*pDataSize) void* pData) + { + return -1; + } + + virtual HRESULT STDMETHODCALLTYPE GetParent( + _In_ REFIID riid, + _Out_ void** ppParent) + { + return -1; + } + + #pragma endregion + +private: + int m_RefCount; +}; + +#endif // __CCRYDX12OBJECT__ diff --git a/src/Layers/xrRenderPC_R5/DX12/CryDX12.cpp b/src/Layers/xrRenderPC_R5/DX12/CryDX12.cpp new file mode 100644 index 00000000000..63dfd783130 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/CryDX12.cpp @@ -0,0 +1,58 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "CryDX12.hpp" + +#include "GI/CCryDX12GIFactory.hpp" +#include "Device/CCryDX12Device.hpp" +#include "Device/CCryDX12DeviceContext.hpp" + +#ifdef WIN32 +#pragma comment(lib, "d3d12.lib") +#pragma comment(lib, "dxgi.lib") +#endif + +HRESULT WINAPI DX12CreateDXGIFactory1(REFIID riid, void** ppFactory) +{ + *ppFactory = CCryDX12GIFactory::Create(); + return *ppFactory ? 0 : -1; +} + +HRESULT WINAPI DX12CreateDevice( + IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + CONST D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext) +{ + *ppDevice = CCryDX12Device::Create(pAdapter, pFeatureLevel); + + if (!*ppDevice) + { + return -1; + } + + (*ppDevice)->GetImmediateContext(ppImmediateContext); + + if (!*ppImmediateContext) + { + return -1; + } + + return 0; +} diff --git a/src/Layers/xrRenderPC_R5/DX12/CryDX12.hpp b/src/Layers/xrRenderPC_R5/DX12/CryDX12.hpp new file mode 100644 index 00000000000..9694b97f16e --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/CryDX12.hpp @@ -0,0 +1,50 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once + +#include "CryDX12Legacy.hpp" + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "DX12/API/DX12.hpp" +#include "DX12/API/DX12PSO.hpp" +#include "DX12/Misc/SCryDX11PipelineState.hpp" + +#include "DX12/GI/CCryDX12GIFactory.hpp" +#include "DX12/GI/CCryDX12SwapChain.hpp" +#include "DX12/Device/CCryDX12Device.hpp" +#include "DX12/Device/CCryDX12DeviceContext.hpp" + +typedef IDXGIDevice3 DXGIDevice; +typedef IDXGIAdapter3 DXGIAdapter; +typedef CCryDX12GIFactory DXGIFactory; +typedef IDXGIOutput4 DXGIOutput; +typedef CCryDX12SwapChain DXGISwapChain; +typedef CCryDX12Device D3DDevice; +typedef CCryDX12DeviceContext D3DDeviceContext; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +HRESULT WINAPI DX12CreateDXGIFactory1(REFIID riid, void** ppFactory); + +HRESULT WINAPI DX12CreateDevice( + IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + CONST D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext); diff --git a/src/Layers/xrRenderPC_R5/DX12/CryDX12Guid.hpp b/src/Layers/xrRenderPC_R5/DX12/CryDX12Guid.hpp new file mode 100644 index 00000000000..d48d064c2ae --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/CryDX12Guid.hpp @@ -0,0 +1,40 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once + +#define DX12_DEFINE_TYPE_GUID(_CLASS, _TYPE, X) \ + _CLASS __declspec(uuid(X)) _TYPE; + +DX12_DEFINE_TYPE_GUID(class, CCryDX12GIAdapter, "59e4cc3a-87bb-4b7b-a1e3-06787231384a"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12GIFactory, "af688514-87ba-4c1c-9927-5a349ede6d74"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12GIOutput, "038b29e3-2d4b-49c0-a726-494675697b76"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12SwapChain, "d9e49be8-2651-4bc7-bfaa-303cb964a76e"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12Device, "f9c01631-d950-444c-a480-68bbb85fb28c"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12DeviceContext, "23ec965a-a01c-4862-b8b8-f53cf8cd7dcc"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12Texture1D, "dd8eb017-6cdb-4790-a767-52817c222d57"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12Texture2D, "4dff2102-e08a-497e-b519-1c07124b36b3"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12Texture3D, "003527af-f60d-4d93-b5d8-6370964e7692"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12DepthStencilView, "4fdfce9f-c7c9-44e7-99c5-64c24e5ed31a"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12RenderTargetView, "8b1d7ea0-0313-4eaa-8ddb-6e25b7eb7a7c"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12UnorderedAccessView, "ce7c421a-b6a5-42b2-a8cd-7a34bf23426b"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12ShaderResourceView, "b4639da3-fc4e-4907-942a-dae7e86e9eeb"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12Query, "3dd1b810-4a04-4719-bb8b-14f5936479f9"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12BlendState, "3bb119a1-5c56-4251-8fbf-c874d5d3f101"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12RasterizerState, "4c3c2198-2011-4dbd-a310-7dabca10e55d"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12DepthStencilState, "f28f8fb4-e55d-4f98-88ed-fa3aab12be7b"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12InputLayout, "3b74fa4e-c2b6-4167-a014-bf2f91f16ddd"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12Buffer, "06b2a225-e1aa-4509-b5da-f0fd1d846ba6"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12Shader, "7052b765-cc86-42e8-b116-36dc3bf4cfee"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12SamplerState, "a841545b-c5a6-4481-9383-a46ec1c2c380"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12EventQuery, "0d8f741f-4051-4935-a50d-58353f825e45"); +DX12_DEFINE_TYPE_GUID(class, CCryDX12ResourceQuery, "6f1c2c43-3da7-489a-b1df-0c27362addbe"); diff --git a/src/Layers/xrRenderPC_R5/DX12/CryDX12Legacy.hpp b/src/Layers/xrRenderPC_R5/DX12/CryDX12Legacy.hpp new file mode 100644 index 00000000000..9f570c386ce --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/CryDX12Legacy.hpp @@ -0,0 +1,30 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. + +#pragma once + +#if defined(WIN32) + #include + #include + #include + #include + #include +#endif + +#if !defined(D3D_OK) +#define D3D_OK 0 +#endif + +#if !defined(S_OK) +#define S_OK 0 +#endif diff --git a/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12Device.cpp b/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12Device.cpp new file mode 100644 index 00000000000..a75ecc017c4 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12Device.cpp @@ -0,0 +1,904 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "CCryDX12Device.hpp" + +#include "CCryDX12DeviceContext.hpp" + +#include "DX12/Resource/Misc/CCryDX12Buffer.hpp" +#include "DX12/Resource/Misc/CCryDX12InputLayout.hpp" +#include "DX12/Resource/Misc/CCryDX12Query.hpp" +#include "DX12/Resource/Misc/CCryDX12Shader.hpp" + +#include "DX12/Resource/State/CCryDX12BlendState.hpp" +#include "DX12/Resource/State/CCryDX12DepthStencilState.hpp" +#include "DX12/Resource/State/CCryDX12RasterizerState.hpp" +#include "DX12/Resource/State/CCryDX12SamplerState.hpp" + +#include "DX12/Resource/Texture/CCryDX12Texture1D.hpp" +#include "DX12/Resource/Texture/CCryDX12Texture2D.hpp" +#include "DX12/Resource/Texture/CCryDX12Texture3D.hpp" + +#include "DX12/Resource/View/CCryDX12DepthStencilView.hpp" +#include "DX12/Resource/View/CCryDX12RenderTargetView.hpp" +#include "DX12/Resource/View/CCryDX12ShaderResourceView.hpp" +#include "DX12/Resource/View/CCryDX12UnorderedAccessView.hpp" + +CCryDX12Device* CCryDX12Device::Create(IDXGIAdapter* pAdapter, D3D_FEATURE_LEVEL* pFeatureLevel) +{ + _smart_ptr device; + device.attach(DX12::Device::Create(pAdapter, pFeatureLevel)); + + if (!device) + { + DX12_ERROR("Could not create DX12 Device!"); + return NULL; + } + + return DX12::PassAddRef(new CCryDX12Device(device)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +CCryDX12Device::CCryDX12Device(DX12::Device* device) + : Super() + , m_pDevice(device) +{ + DX12_FUNC_LOG + m_pContext.attach(CCryDX12DeviceContext::Create(this, false)); +} + +CCryDX12Device::~CCryDX12Device() +{ + DX12_FUNC_LOG +} + +#pragma region /* ID3D11Device implementation */ + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateBuffer( + _In_ const D3D11_BUFFER_DESC* pDesc, + _In_opt_ const D3D11_SUBRESOURCE_DATA* pInitialData, + _Out_opt_ ID3D11Buffer** ppBuffer) +{ + + *ppBuffer = CCryDX12Buffer::Create(this, pDesc, pInitialData); + return *ppBuffer ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateTexture1D( + _In_ const D3D11_TEXTURE1D_DESC* pDesc, + _In_reads_opt_(_Inexpressible_(pDesc->MipLevels * pDesc->ArraySize)) const D3D11_SUBRESOURCE_DATA* pInitialData, + _Out_opt_ ID3D11Texture1D** ppTexture1D) +{ + DX12_FUNC_LOG + + * ppTexture1D = CCryDX12Texture1D::Create(this, nullptr, pDesc, pInitialData); + return *ppTexture1D ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateTexture2D( + _In_ const D3D11_TEXTURE2D_DESC* pDesc, + _In_reads_opt_(_Inexpressible_(pDesc->MipLevels * pDesc->ArraySize)) const D3D11_SUBRESOURCE_DATA* pInitialData, + _Out_opt_ ID3D11Texture2D** ppTexture2D) +{ + DX12_FUNC_LOG + + * ppTexture2D = CCryDX12Texture2D::Create(this, nullptr, pDesc, pInitialData); + return *ppTexture2D ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateTexture3D( + _In_ const D3D11_TEXTURE3D_DESC* pDesc, + _In_reads_opt_(_Inexpressible_(pDesc->MipLevels)) const D3D11_SUBRESOURCE_DATA* pInitialData, + _Out_opt_ ID3D11Texture3D** ppTexture3D) +{ + DX12_FUNC_LOG + + * ppTexture3D = CCryDX12Texture3D::Create(this, nullptr, pDesc, pInitialData); + return *ppTexture3D ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateShaderResourceView( + _In_ ID3D11Resource* pResource, + _In_opt_ const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, + _Out_opt_ ID3D11ShaderResourceView** ppSRView) +{ + DX12_FUNC_LOG + + * ppSRView = NULL; + + D3D11_SHADER_RESOURCE_VIEW_DESC* pCreatedDesc = NULL; + if (!pDesc) + { + D3D11_RESOURCE_DIMENSION type; + pResource->GetType(&type); + + if (type == D3D11_RESOURCE_DIMENSION_TEXTURE1D) + { + D3D11_TEXTURE1D_DESC ptr_desc; + DX12_EXTRACT_TEXTURE1D(pResource)->GetDesc(&ptr_desc); + + pCreatedDesc = new D3D11_SHADER_RESOURCE_VIEW_DESC{}; + pCreatedDesc->Format = ptr_desc.Format; + pCreatedDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; + pCreatedDesc->Texture1D.MipLevels = ptr_desc.MipLevels; + pCreatedDesc->Texture1D.MostDetailedMip = 0; // ptr_desc->MostDetailedMip; + } + else if (type == D3D11_RESOURCE_DIMENSION_TEXTURE2D) + { + D3D11_TEXTURE2D_DESC ptr_desc; + DX12_EXTRACT_TEXTURE2D(pResource)->GetDesc(&ptr_desc); + + pCreatedDesc = new D3D11_SHADER_RESOURCE_VIEW_DESC{}; + pCreatedDesc->Format = ptr_desc.Format; + + if (ptr_desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) + { + pCreatedDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + pCreatedDesc->TextureCube.MipLevels = ptr_desc.MipLevels; + pCreatedDesc->TextureCube.MostDetailedMip = 0; // ptr_desc->MostDetailedMip; + } + else + { + const bool isArray = ptr_desc.ArraySize > 1; + if (ptr_desc.SampleDesc.Count <= 1) + { + pCreatedDesc->ViewDimension = + isArray ? D3D11_SRV_DIMENSION_TEXTURE2DARRAY : D3D11_SRV_DIMENSION_TEXTURE2D; + if (isArray) + { + pCreatedDesc->Texture2DArray.MipLevels = ptr_desc.MipLevels; + pCreatedDesc->Texture2DArray.ArraySize = ptr_desc.ArraySize; + } + else + { + pCreatedDesc->Texture2D.MipLevels = ptr_desc.MipLevels; + pCreatedDesc->Texture2D.MostDetailedMip = 0; // ptr_desc->MostDetailedMip; + } + } + else + { + pCreatedDesc->ViewDimension = + isArray ? D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY : D3D11_SRV_DIMENSION_TEXTURE2DMS; + if (isArray) + { + pCreatedDesc->Texture2DMSArray.ArraySize = ptr_desc.ArraySize; + } + } + } + } + else if (type == D3D11_RESOURCE_DIMENSION_TEXTURE3D) + { + D3D11_TEXTURE3D_DESC ptr_desc; + DX12_EXTRACT_TEXTURE3D(pResource)->GetDesc(&ptr_desc); + + pCreatedDesc = new D3D11_SHADER_RESOURCE_VIEW_DESC{}; + pCreatedDesc->Format = ptr_desc.Format; + pCreatedDesc->ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + pCreatedDesc->Texture3D.MipLevels = ptr_desc.MipLevels; + pCreatedDesc->Texture3D.MostDetailedMip = 0; // ptr_desc->MostDetailedMip; + } + } + + if (CCryDX12ShaderResourceView* pResult = CCryDX12ShaderResourceView::Create(this, pResource, pDesc ? pDesc : pCreatedDesc)) + { + auto descriptorHandle = GetDX12Device()->CacheShaderResourceView(&pResult->GetDX12View().GetSRVDesc(), DX12_EXTRACT_D3D12RESOURCE(pResource)); + pResult->GetDX12View().SetDescriptorHandle(descriptorHandle); + + if (INVALID_CPU_DESCRIPTOR_HANDLE == descriptorHandle) + { + SAFE_RELEASE(pResult); + } + + *ppSRView = pResult; + } + + if (pCreatedDesc) + delete pCreatedDesc; + + return *ppSRView ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateUnorderedAccessView( + _In_ ID3D11Resource* pResource, + _In_opt_ const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, + _Out_opt_ ID3D11UnorderedAccessView** ppUAView) +{ + DX12_FUNC_LOG + + * ppUAView = NULL; + + if (CCryDX12UnorderedAccessView* pResult = CCryDX12UnorderedAccessView::Create(this, pResource, pDesc)) + { + auto descriptorHandle = GetDX12Device()->CacheUnorderedAccessView(&pResult->GetDX12View().GetUAVDesc(), DX12_EXTRACT_D3D12RESOURCE(pResource)); + pResult->GetDX12View().SetDescriptorHandle(descriptorHandle); + + if (INVALID_CPU_DESCRIPTOR_HANDLE == descriptorHandle) + { + SAFE_RELEASE(pResult); + } + + *ppUAView = pResult; + } + + return *ppUAView ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateRenderTargetView( + _In_ ID3D11Resource* pResource, + _In_opt_ const D3D11_RENDER_TARGET_VIEW_DESC* pDesc, + _Out_opt_ ID3D11RenderTargetView** ppRTView) +{ + DX12_FUNC_LOG + + * ppRTView = NULL; + + D3D11_RENDER_TARGET_VIEW_DESC* pCreatedDesc = NULL; + + if (!pDesc) + { + D3D11_RESOURCE_DIMENSION type; + pResource->GetType(&type); + + if (type == D3D11_RESOURCE_DIMENSION_TEXTURE2D) + { + D3D11_TEXTURE2D_DESC ptr_desc; + DX12_EXTRACT_TEXTURE2D(pResource)->GetDesc(&ptr_desc); + + pCreatedDesc = new D3D11_RENDER_TARGET_VIEW_DESC{}; + pCreatedDesc->Format = ptr_desc.Format; + + const bool isArray = ptr_desc.ArraySize > 1; + + if (ptr_desc.SampleDesc.Count <= 1) + { + pCreatedDesc->ViewDimension = + isArray ? D3D11_RTV_DIMENSION_TEXTURE2DARRAY : D3D11_RTV_DIMENSION_TEXTURE2D; + if (isArray) + { + pCreatedDesc->Texture2DArray.ArraySize = ptr_desc.ArraySize; + } + } + else + { + pCreatedDesc->ViewDimension = + isArray ? D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY : D3D11_RTV_DIMENSION_TEXTURE2DMS; + if (isArray) + { + pCreatedDesc->Texture2DMSArray.ArraySize = ptr_desc.ArraySize; + } + } + } + } + + if (CCryDX12RenderTargetView* pResult = CCryDX12RenderTargetView::Create(this, pResource, pDesc ? pDesc : pCreatedDesc)) + { + auto descriptorHandle = GetDX12Device()->CacheRenderTargetView(&pResult->GetDX12View().GetRTVDesc(), DX12_EXTRACT_D3D12RESOURCE(pResource)); + pResult->GetDX12View().SetDescriptorHandle(descriptorHandle); + + if (INVALID_CPU_DESCRIPTOR_HANDLE == descriptorHandle) + { + SAFE_RELEASE(pResult); + } + + *ppRTView = pResult; + } + + if (pCreatedDesc) + delete pCreatedDesc; + + return *ppRTView ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateDepthStencilView( + _In_ ID3D11Resource* pResource, + _In_opt_ const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc, + _Out_opt_ ID3D11DepthStencilView** ppDSView) +{ + DX12_FUNC_LOG + + * ppDSView = NULL; + + if (CCryDX12DepthStencilView* pResult = CCryDX12DepthStencilView::Create(this, pResource, pDesc)) + { + auto descriptorHandle = GetDX12Device()->CacheDepthStencilView(&pResult->GetDX12View().GetDSVDesc(), DX12_EXTRACT_D3D12RESOURCE(pResource)); + pResult->GetDX12View().SetDescriptorHandle(descriptorHandle); + + if (INVALID_CPU_DESCRIPTOR_HANDLE == descriptorHandle) + { + SAFE_RELEASE(pResult); + } + + *ppDSView = pResult; + } + + return *ppDSView ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateInputLayout( + _In_reads_(NumElements) const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs, + _In_range_(0, D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT) UINT NumElements, + _In_ const void* pShaderBytecodeWithInputSignature, + _In_ SIZE_T BytecodeLength, + _Out_opt_ ID3D11InputLayout** ppInputLayout) +{ + DX12_FUNC_LOG + * ppInputLayout = CCryDX12InputLayout::Create(this, pInputElementDescs, NumElements, pShaderBytecodeWithInputSignature, BytecodeLength); + return *ppInputLayout ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateVertexShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11VertexShader** ppVertexShader) +{ + DX12_FUNC_LOG + * ppVertexShader = reinterpret_cast(CCryDX12Shader::Create(this, pShaderBytecode, BytecodeLength, pClassLinkage)); + return *ppVertexShader ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateGeometryShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11GeometryShader** ppGeometryShader) +{ + DX12_FUNC_LOG + * ppGeometryShader = reinterpret_cast(CCryDX12Shader::Create(this, pShaderBytecode, BytecodeLength, pClassLinkage)); + return *ppGeometryShader ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateGeometryShaderWithStreamOutput( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_reads_opt_(NumEntries) const D3D11_SO_DECLARATION_ENTRY* pSODeclaration, + _In_range_(0, D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT) UINT NumEntries, + _In_reads_opt_(NumStrides) const UINT* pBufferStrides, + _In_range_(0, D3D11_SO_BUFFER_SLOT_COUNT) UINT NumStrides, + _In_ UINT RasterizedStream, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11GeometryShader** ppGeometryShader) +{ + DX12_FUNC_LOG + return -1; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreatePixelShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11PixelShader** ppPixelShader) +{ + DX12_FUNC_LOG + * ppPixelShader = reinterpret_cast(CCryDX12Shader::Create(this, pShaderBytecode, BytecodeLength, pClassLinkage)); + return *ppPixelShader ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateHullShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11HullShader** ppHullShader) +{ + DX12_FUNC_LOG + * ppHullShader = reinterpret_cast(CCryDX12Shader::Create(this, pShaderBytecode, BytecodeLength, pClassLinkage)); + return *ppHullShader ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateDomainShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11DomainShader** ppDomainShader) +{ + DX12_FUNC_LOG + * ppDomainShader = reinterpret_cast(CCryDX12Shader::Create(this, pShaderBytecode, BytecodeLength, pClassLinkage)); + return *ppDomainShader ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateComputeShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11ComputeShader** ppComputeShader) +{ + DX12_FUNC_LOG + * ppComputeShader = reinterpret_cast(CCryDX12Shader::Create(this, pShaderBytecode, BytecodeLength, pClassLinkage)); + return *ppComputeShader ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateClassLinkage( + _Out_ ID3D11ClassLinkage** ppLinkage) +{ + DX12_FUNC_LOG + return -1; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateBlendState( + _In_ const D3D11_BLEND_DESC* pBlendStateDesc, + _Out_opt_ ID3D11BlendState** ppBlendState) +{ + DX12_FUNC_LOG + * ppBlendState = CCryDX12BlendState::Create(pBlendStateDesc); + return *ppBlendState ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateDepthStencilState( + _In_ const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc, + _Out_opt_ ID3D11DepthStencilState** ppDepthStencilState) +{ + DX12_FUNC_LOG + * ppDepthStencilState = CCryDX12DepthStencilState::Create(pDepthStencilDesc); + return *ppDepthStencilState ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateRasterizerState( + _In_ const D3D11_RASTERIZER_DESC* pRasterizerDesc, + _Out_opt_ ID3D11RasterizerState** ppRasterizerState) +{ + DX12_FUNC_LOG + * ppRasterizerState = CCryDX12RasterizerState::Create(pRasterizerDesc); + return *ppRasterizerState ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateSamplerState( + _In_ const D3D11_SAMPLER_DESC* pSamplerDesc, + _Out_opt_ ID3D11SamplerState** ppSamplerState) +{ + DX12_FUNC_LOG + * ppSamplerState = NULL; + + if (CCryDX12SamplerState* pResult = CCryDX12SamplerState::Create(pSamplerDesc)) + { + auto descriptorHandle = GetDX12Device()->CacheSampler(&pResult->GetDX12SamplerState().GetSamplerDesc()); + pResult->GetDX12SamplerState().SetDescriptorHandle(descriptorHandle); + + if (INVALID_CPU_DESCRIPTOR_HANDLE == descriptorHandle) + { + SAFE_RELEASE(pResult); + } + + *ppSamplerState = pResult; + } + + return *ppSamplerState ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateQuery( + _In_ const D3D11_QUERY_DESC* pQueryDesc, + _Out_opt_ ID3D11Query** ppQuery) +{ + *ppQuery = CCryDX12Query::Create(GetD3D12Device(), pQueryDesc); + return *ppQuery ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreatePredicate( + _In_ const D3D11_QUERY_DESC* pPredicateDesc, + _Out_opt_ ID3D11Predicate** ppPredicate) +{ + DX12_FUNC_LOG + return -1; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateCounter( + _In_ const D3D11_COUNTER_DESC* pCounterDesc, + _Out_opt_ ID3D11Counter** ppCounter) +{ + DX12_FUNC_LOG + return -1; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateDeferredContext( + UINT ContextFlags, + _Out_opt_ ID3D11DeviceContext** ppDeferredContext) +{ + DX12_FUNC_LOG + + if (ppDeferredContext) + { + *ppDeferredContext = CCryDX12DeviceContext::Create(this, true); + return S_OK; + } + return -1; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::OpenSharedResource( + _In_ HANDLE hResource, + _In_ REFIID ReturnedInterface, + _Out_opt_ void** ppResource) +{ + DX12_FUNC_LOG + return -1; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CheckFormatSupport( + _In_ DXGI_FORMAT Format, + _Out_ UINT* pFormatSupport) +{ + DX12_FUNC_LOG + D3D12_FEATURE_DATA_FORMAT_SUPPORT data; + data.Format = Format; + + if (S_OK != m_pDevice->GetD3D12Device()->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &data, sizeof(D3D12_FEATURE_DATA_FORMAT_SUPPORT))) + { + return S_FALSE; + } + + *pFormatSupport = data.Support1; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CheckMultisampleQualityLevels( + _In_ DXGI_FORMAT Format, + _In_ UINT SampleCount, + _Out_ UINT* pNumQualityLevels) +{ + DX12_FUNC_LOG + return -1; +} + +void STDMETHODCALLTYPE CCryDX12Device::CheckCounterInfo( + _Out_ D3D11_COUNTER_INFO* pCounterInfo) +{ + DX12_FUNC_LOG +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CheckCounter( + _In_ const D3D11_COUNTER_DESC* pDesc, + _Out_ D3D11_COUNTER_TYPE* pType, + _Out_ UINT* pActiveCounters, + _Out_writes_opt_(*pNameLength) LPSTR szName, + _Inout_opt_ UINT* pNameLength, + _Out_writes_opt_(*pUnitsLength) LPSTR szUnits, + _Inout_opt_ UINT* pUnitsLength, + _Out_writes_opt_(*pDescriptionLength) LPSTR szDescription, + _Inout_opt_ UINT* pDescriptionLength) +{ + DX12_FUNC_LOG + return -1; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CheckFeatureSupport( + D3D11_FEATURE Feature, + _Out_writes_bytes_(FeatureSupportDataSize) void* pFeatureSupportData, + UINT FeatureSupportDataSize) +{ + DX12_FUNC_LOG + + switch (Feature) + { + case D3D11_FEATURE_D3D11_OPTIONS2: + { + D3D11_FEATURE_DATA_D3D11_OPTIONS2* dx11FeatureDataOptions2 = static_cast(pFeatureSupportData); + HRESULT result; + + D3D12_FEATURE_DATA_D3D12_OPTIONS dx12FeatureDataOptions; + result = m_pDevice->GetD3D12Device()->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &dx12FeatureDataOptions, sizeof(dx12FeatureDataOptions)); + if (result == S_OK) + { + dx11FeatureDataOptions2->PSSpecifiedStencilRefSupported = dx12FeatureDataOptions.PSSpecifiedStencilRefSupported; + dx11FeatureDataOptions2->TypedUAVLoadAdditionalFormats = dx12FeatureDataOptions.TypedUAVLoadAdditionalFormats; + dx11FeatureDataOptions2->ROVsSupported = dx12FeatureDataOptions.ROVsSupported; + dx11FeatureDataOptions2->MapOnDefaultTextures = true; // Assumed true in DX12 + dx11FeatureDataOptions2->StandardSwizzle = dx12FeatureDataOptions.StandardSwizzle64KBSupported; + + switch (dx12FeatureDataOptions.ConservativeRasterizationTier) + { + case D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED: + dx11FeatureDataOptions2->ConservativeRasterizationTier = D3D11_CONSERVATIVE_RASTERIZATION_NOT_SUPPORTED; + break; + case D3D12_CONSERVATIVE_RASTERIZATION_TIER_1: + dx11FeatureDataOptions2->ConservativeRasterizationTier = D3D11_CONSERVATIVE_RASTERIZATION_TIER_1; + break; + case D3D12_CONSERVATIVE_RASTERIZATION_TIER_2: + dx11FeatureDataOptions2->ConservativeRasterizationTier = D3D11_CONSERVATIVE_RASTERIZATION_TIER_2; + break; + case D3D12_CONSERVATIVE_RASTERIZATION_TIER_3: + dx11FeatureDataOptions2->ConservativeRasterizationTier = D3D11_CONSERVATIVE_RASTERIZATION_TIER_3; + break; + } + + switch (dx12FeatureDataOptions.TiledResourcesTier) + { + case D3D12_TILED_RESOURCES_TIER_NOT_SUPPORTED: + dx11FeatureDataOptions2->TiledResourcesTier = D3D11_TILED_RESOURCES_NOT_SUPPORTED; + break; + case D3D12_TILED_RESOURCES_TIER_1: + dx11FeatureDataOptions2->TiledResourcesTier = D3D11_TILED_RESOURCES_TIER_1; + break; + case D3D12_TILED_RESOURCES_TIER_2: + dx11FeatureDataOptions2->TiledResourcesTier = D3D11_TILED_RESOURCES_TIER_2; + break; + case D3D12_TILED_RESOURCES_TIER_3: + dx11FeatureDataOptions2->TiledResourcesTier = D3D11_TILED_RESOURCES_TIER_3; + break; + } + } + else + { + return E_INVALIDARG; + } + + + D3D12_FEATURE_DATA_ARCHITECTURE dx12FeatureDataArchitecture; + dx12FeatureDataArchitecture.NodeIndex = 0; + result = m_pDevice->GetD3D12Device()->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &dx12FeatureDataArchitecture, sizeof(dx12FeatureDataArchitecture)); + if (result == S_OK) + { + dx11FeatureDataOptions2->UnifiedMemoryArchitecture = dx12FeatureDataArchitecture.UMA; + } + else + { + return E_INVALIDARG; + } + + break; + } + default: + R_ASSERT2(false, "No conversion to DX12 has been written for this feature support check."); + return E_INVALIDARG; + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::GetPrivateData( + _In_ REFGUID guid, + _Inout_ UINT* pDataSize, + _Out_writes_bytes_opt_(*pDataSize) void* pData) +{ + DX12_FUNC_LOG + return -1; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::SetPrivateData( + _In_ REFGUID guid, + _In_ UINT DataSize, + _In_reads_bytes_opt_(DataSize) const void* pData) +{ + DX12_FUNC_LOG + return -1; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::SetPrivateDataInterface( + _In_ REFGUID guid, + _In_opt_ const IUnknown* pData) +{ + DX12_FUNC_LOG + return -1; +} + +D3D_FEATURE_LEVEL STDMETHODCALLTYPE CCryDX12Device::GetFeatureLevel() +{ + DX12_FUNC_LOG + return D3D_FEATURE_LEVEL_11_1; +} + +UINT STDMETHODCALLTYPE CCryDX12Device::GetCreationFlags() +{ + DX12_FUNC_LOG + return 0; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::GetDeviceRemovedReason() +{ + DX12_FUNC_LOG + return -1; +} + +void STDMETHODCALLTYPE CCryDX12Device::GetImmediateContext( + _Out_ ID3D11DeviceContext** ppImmediateContext) +{ + DX12_FUNC_LOG + if (ppImmediateContext) + { + *ppImmediateContext = m_pContext; + (*ppImmediateContext)->AddRef(); + } +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::SetExceptionMode( + UINT RaiseFlags) +{ + DX12_FUNC_LOG + return -1; +} + +UINT STDMETHODCALLTYPE CCryDX12Device::GetExceptionMode() +{ + DX12_FUNC_LOG + return 0; +} + +#pragma endregion + +#pragma region /* ID3D11Device1 implementation */ + +void STDMETHODCALLTYPE CCryDX12Device::GetImmediateContext1( + _Out_ ID3D11DeviceContext1** ppImmediateContext) +{ + DX12_FUNC_LOG + + if (ppImmediateContext) + { + *ppImmediateContext = m_pContext; + (*ppImmediateContext)->AddRef(); + } +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateDeferredContext1( + UINT ContextFlags, + /* [annotation] */ + _COM_Outptr_opt_ ID3D11DeviceContext1** ppDeferredContext) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateBlendState1( + /* [annotation] */ + _In_ const D3D11_BLEND_DESC1* pBlendStateDesc, + /* [annotation] */ + _COM_Outptr_opt_ ID3D11BlendState1** ppBlendState) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateRasterizerState1( + /* [annotation] */ + _In_ const D3D11_RASTERIZER_DESC1* pRasterizerDesc, + /* [annotation] */ + _COM_Outptr_opt_ ID3D11RasterizerState1** ppRasterizerState) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateDeviceContextState( + UINT Flags, + /* [annotation] */ + _In_reads_(FeatureLevels) const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + REFIID EmulatedInterface, + /* [annotation] */ + _Out_opt_ D3D_FEATURE_LEVEL* pChosenFeatureLevel, + /* [annotation] */ + _Out_opt_ ID3DDeviceContextState** ppContextState) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::OpenSharedResource1( + /* [annotation] */ + _In_ HANDLE hResource, + /* [annotation] */ + _In_ REFIID returnedInterface, + /* [annotation] */ + _COM_Outptr_ void** ppResource) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::OpenSharedResourceByName( + /* [annotation] */ + _In_ LPCWSTR lpName, + /* [annotation] */ + _In_ DWORD dwDesiredAccess, + /* [annotation] */ + _In_ REFIID returnedInterface, + /* [annotation] */ + _COM_Outptr_ void** ppResource) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED + return E_FAIL; +} + +#pragma endregion + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateTexture1D( + _In_ const D3D11_TEXTURE1D_DESC* pDesc, + _In_ const FLOAT cClearValue[4], + _In_reads_opt_(_Inexpressible_(pDesc->MipLevels * pDesc->ArraySize)) const D3D11_SUBRESOURCE_DATA* pInitialData, + _Out_opt_ ID3D11Texture1D** ppTexture1D) +{ + DX12_FUNC_LOG + * ppTexture1D = CCryDX12Texture1D::Create(this, cClearValue, pDesc, pInitialData); + return *ppTexture1D ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateTexture2D( + _In_ const D3D11_TEXTURE2D_DESC* pDesc, + _In_ const FLOAT cClearValue[4], + _In_reads_opt_(_Inexpressible_(pDesc->MipLevels * pDesc->ArraySize)) const D3D11_SUBRESOURCE_DATA* pInitialData, + _Out_opt_ ID3D11Texture2D** ppTexture2D) +{ + DX12_FUNC_LOG + * ppTexture2D = CCryDX12Texture2D::Create(this, cClearValue, pDesc, pInitialData); + return *ppTexture2D ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateTexture3D( + _In_ const D3D11_TEXTURE3D_DESC* pDesc, + _In_ const FLOAT cClearValue[4], + _In_reads_opt_(_Inexpressible_(pDesc->MipLevels)) const D3D11_SUBRESOURCE_DATA* pInitialData, + _Out_opt_ ID3D11Texture3D** ppTexture3D) +{ + DX12_FUNC_LOG + * ppTexture3D = CCryDX12Texture3D::Create(this, cClearValue, pDesc, pInitialData); + return *ppTexture3D ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::CreateStagingResource( + _In_ ID3D11Resource* pInputResource, + _Out_ ID3D11Resource** ppStagingResource, + _In_ BOOL Upload) +{ + ICryDX12Resource* dx12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pInputResource); + DX12::Resource& rResource = dx12Resource->GetDX12Resource(); + + D3D12_RESOURCE_DESC resourceDesc = rResource.GetDesc(); + UINT64 requiredSize; + UINT numSubResources = resourceDesc.MipLevels * (resourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? 1 : resourceDesc.DepthOrArraySize); + GetD3D12Device()->GetCopyableFootprints(&resourceDesc, 0, numSubResources, 0, nullptr, nullptr, nullptr, &requiredSize); + + D3D12_RESOURCE_STATES initialState = Upload ? D3D12_RESOURCE_STATE_GENERIC_READ : D3D12_RESOURCE_STATE_COPY_DEST; + D3D12_HEAP_TYPE heapType = Upload ? D3D12_HEAP_TYPE_UPLOAD : D3D12_HEAP_TYPE_READBACK; + + CD3DX12_HEAP_PROPERTIES stagingProperty(heapType); + CD3DX12_RESOURCE_DESC stagingBuffer = CD3DX12_RESOURCE_DESC::Buffer(requiredSize); + + ID3D12Resource* stagingResource = NULL; + HRESULT result = GetDX12Device()->GetD3D12Device()->CreateCommittedResource( + &stagingProperty, + D3D12_HEAP_FLAG_NONE, + &stagingBuffer, + initialState, + nullptr, + IID_PPV_ARGS(&stagingResource)); + + if (result == S_OK && stagingResource != nullptr) + { + *ppStagingResource = CCryDX12Buffer::Create(this, stagingResource, initialState); + stagingResource->Release(); + + return S_OK; + } + + return result; +} + +HRESULT STDMETHODCALLTYPE CCryDX12Device::ReleaseStagingResource( + _In_ ID3D11Resource* pStagingResource) +{ + ICryDX12Resource* dx12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pStagingResource); + DX12::Resource& rResource = dx12Resource->GetDX12Resource(); + ID3D12Resource* d3d12Resource = rResource.GetD3D12Resource(); + + d3d12Resource->AddRef(); + d3d12Resource->SetName(L"StagingResource"); + GetDX12Device()->ReleaseLater(d3d12Resource, rResource.GetCurrentState(), rResource.GetAnnouncedState()); + + pStagingResource->Release(); + return S_OK; +} diff --git a/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12Device.hpp b/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12Device.hpp new file mode 100644 index 00000000000..208ef4a11f6 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12Device.hpp @@ -0,0 +1,319 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once +#ifndef __CCRYDX12DEVICE__ +#define __CCRYDX12DEVICE__ + +#include "DX12/CCryDX12Object.hpp" +#include "DX12/API/DX12Device.hpp" + +class CCryDX12Device + : public CCryDX12Object +{ +public: + DX12_OBJECT(CCryDX12Device, CCryDX12Object); + + static CCryDX12Device* Create(IDXGIAdapter* pAdapter, D3D_FEATURE_LEVEL* pFeatureLevel); + + CCryDX12Device(DX12::Device* device); + + virtual ~CCryDX12Device(); + + DX12::Device* GetDX12Device() const { return m_pDevice; } + + ID3D12Device* GetD3D12Device() const { return m_pDevice->GetD3D12Device(); } + + CCryDX12DeviceContext* GetDeviceContext() const { return m_pContext; } + + #pragma region /* ID3D11Device implementation */ + + virtual HRESULT STDMETHODCALLTYPE CreateBuffer( + _In_ const D3D11_BUFFER_DESC* pDesc, + _In_opt_ const D3D11_SUBRESOURCE_DATA* pInitialData, + _Out_opt_ ID3D11Buffer** ppBuffer) final; + + virtual HRESULT STDMETHODCALLTYPE CreateTexture1D( + _In_ const D3D11_TEXTURE1D_DESC * pDesc, + _In_reads_opt_(_Inexpressible_(pDesc->MipLevels * pDesc->ArraySize)) const D3D11_SUBRESOURCE_DATA * pInitialData, + _Out_opt_ ID3D11Texture1D * *ppTexture1D) final; + + virtual HRESULT STDMETHODCALLTYPE CreateTexture2D( + _In_ const D3D11_TEXTURE2D_DESC * pDesc, + _In_reads_opt_(_Inexpressible_(pDesc->MipLevels * pDesc->ArraySize)) const D3D11_SUBRESOURCE_DATA * pInitialData, + _Out_opt_ ID3D11Texture2D * *ppTexture2D) final; + + virtual HRESULT STDMETHODCALLTYPE CreateTexture3D( + _In_ const D3D11_TEXTURE3D_DESC * pDesc, + _In_reads_opt_(_Inexpressible_(pDesc->MipLevels)) const D3D11_SUBRESOURCE_DATA * pInitialData, + _Out_opt_ ID3D11Texture3D * *ppTexture3D) final; + + virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView( + _In_ ID3D11Resource* pResource, + _In_opt_ const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, + _Out_opt_ ID3D11ShaderResourceView** ppSRView) final; + + virtual HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView( + _In_ ID3D11Resource* pResource, + _In_opt_ const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, + _Out_opt_ ID3D11UnorderedAccessView** ppUAView) final; + + virtual HRESULT STDMETHODCALLTYPE CreateRenderTargetView( + _In_ ID3D11Resource* pResource, + _In_opt_ const D3D11_RENDER_TARGET_VIEW_DESC* pDesc, + _Out_opt_ ID3D11RenderTargetView** ppRTView) final; + + virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilView( + _In_ ID3D11Resource* pResource, + _In_opt_ const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc, + _Out_opt_ ID3D11DepthStencilView** ppDepthStencilView) final; + + virtual HRESULT STDMETHODCALLTYPE CreateInputLayout( + _In_reads_(NumElements) const D3D11_INPUT_ELEMENT_DESC * pInputElementDescs, + _In_range_(0, D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT) UINT NumElements, + _In_ const void* pShaderBytecodeWithInputSignature, + _In_ SIZE_T BytecodeLength, + _Out_opt_ ID3D11InputLayout * *ppInputLayout) final; + + virtual HRESULT STDMETHODCALLTYPE CreateVertexShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11VertexShader** ppVertexShader) final; + + virtual HRESULT STDMETHODCALLTYPE CreateGeometryShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11GeometryShader** ppGeometryShader) final; + + virtual HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_reads_opt_(NumEntries) const D3D11_SO_DECLARATION_ENTRY * pSODeclaration, + _In_range_(0, D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT) UINT NumEntries, + _In_reads_opt_(NumStrides) const UINT * pBufferStrides, + _In_range_(0, D3D11_SO_BUFFER_SLOT_COUNT) UINT NumStrides, + _In_ UINT RasterizedStream, + _In_opt_ ID3D11ClassLinkage * pClassLinkage, + _Out_opt_ ID3D11GeometryShader * *ppGeometryShader) final; + + virtual HRESULT STDMETHODCALLTYPE CreatePixelShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11PixelShader** ppPixelShader) final; + + virtual HRESULT STDMETHODCALLTYPE CreateHullShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11HullShader** ppHullShader) final; + + virtual HRESULT STDMETHODCALLTYPE CreateDomainShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11DomainShader** ppDomainShader) final; + + virtual HRESULT STDMETHODCALLTYPE CreateComputeShader( + _In_ const void* pShaderBytecode, + _In_ SIZE_T BytecodeLength, + _In_opt_ ID3D11ClassLinkage* pClassLinkage, + _Out_opt_ ID3D11ComputeShader** ppComputeShader) final; + + virtual HRESULT STDMETHODCALLTYPE CreateClassLinkage( + _Out_ ID3D11ClassLinkage** ppLinkage) final; + + virtual HRESULT STDMETHODCALLTYPE CreateBlendState( + _In_ const D3D11_BLEND_DESC* pBlendStateDesc, + _Out_opt_ ID3D11BlendState** ppBlendState) final; + + virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilState( + _In_ const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc, + _Out_opt_ ID3D11DepthStencilState** ppDepthStencilState) final; + + virtual HRESULT STDMETHODCALLTYPE CreateRasterizerState( + _In_ const D3D11_RASTERIZER_DESC* pRasterizerDesc, + _Out_opt_ ID3D11RasterizerState** ppRasterizerState) final; + + virtual HRESULT STDMETHODCALLTYPE CreateSamplerState( + _In_ const D3D11_SAMPLER_DESC* pSamplerDesc, + _Out_opt_ ID3D11SamplerState** ppSamplerState) final; + + virtual HRESULT STDMETHODCALLTYPE CreateQuery( + _In_ const D3D11_QUERY_DESC* pQueryDesc, + _Out_opt_ ID3D11Query** ppQuery) final; + + virtual HRESULT STDMETHODCALLTYPE CreatePredicate( + _In_ const D3D11_QUERY_DESC* pPredicateDesc, + _Out_opt_ ID3D11Predicate** ppPredicate) final; + + virtual HRESULT STDMETHODCALLTYPE CreateCounter( + _In_ const D3D11_COUNTER_DESC* pCounterDesc, + _Out_opt_ ID3D11Counter** ppCounter) final; + + virtual HRESULT STDMETHODCALLTYPE CreateDeferredContext( + UINT ContextFlags, + _Out_opt_ ID3D11DeviceContext** ppDeferredContext) final; + + virtual HRESULT STDMETHODCALLTYPE OpenSharedResource( + _In_ HANDLE hResource, + _In_ REFIID ReturnedInterface, + _Out_opt_ void** ppResource) final; + + virtual HRESULT STDMETHODCALLTYPE CheckFormatSupport( + _In_ DXGI_FORMAT Format, + _Out_ UINT* pFormatSupport) final; + + virtual HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels( + _In_ DXGI_FORMAT Format, + _In_ UINT SampleCount, + _Out_ UINT* pNumQualityLevels) final; + + virtual void STDMETHODCALLTYPE CheckCounterInfo( + _Out_ D3D11_COUNTER_INFO* pCounterInfo) final; + + virtual HRESULT STDMETHODCALLTYPE CheckCounter( + _In_ const D3D11_COUNTER_DESC* pDesc, + _Out_ D3D11_COUNTER_TYPE* pType, + _Out_ UINT* pActiveCounters, + _Out_writes_opt_(*pNameLength) LPSTR szName, + _Inout_opt_ UINT* pNameLength, + _Out_writes_opt_(*pUnitsLength) LPSTR szUnits, + _Inout_opt_ UINT* pUnitsLength, + _Out_writes_opt_(*pDescriptionLength) LPSTR szDescription, + _Inout_opt_ UINT* pDescriptionLength) final; + + virtual HRESULT STDMETHODCALLTYPE CheckFeatureSupport( + D3D11_FEATURE Feature, + _Out_writes_bytes_(FeatureSupportDataSize) void* pFeatureSupportData, + UINT FeatureSupportDataSize) final; + + virtual HRESULT STDMETHODCALLTYPE GetPrivateData( + _In_ REFGUID guid, + _Inout_ UINT* pDataSize, + _Out_writes_bytes_opt_(*pDataSize) void* pData) final; + + virtual HRESULT STDMETHODCALLTYPE SetPrivateData( + _In_ REFGUID guid, + _In_ UINT DataSize, + _In_reads_bytes_opt_(DataSize) const void* pData) final; + + virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + _In_ REFGUID guid, + _In_opt_ const IUnknown* pData) final; + + virtual D3D_FEATURE_LEVEL STDMETHODCALLTYPE GetFeatureLevel() final; + + virtual UINT STDMETHODCALLTYPE GetCreationFlags() final; + + virtual HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason() final; + + virtual void STDMETHODCALLTYPE GetImmediateContext( + _Out_ ID3D11DeviceContext** ppImmediateContext) final; + + virtual HRESULT STDMETHODCALLTYPE SetExceptionMode( + UINT RaiseFlags) final; + + virtual UINT STDMETHODCALLTYPE GetExceptionMode() final; + + #pragma endregion + + #pragma region /* ID3D11Device1 implementation */ + + virtual void STDMETHODCALLTYPE GetImmediateContext1( + /* [annotation] */ + _Outptr_ ID3D11DeviceContext1** ppImmediateContext) final; + + virtual HRESULT STDMETHODCALLTYPE CreateDeferredContext1( + UINT ContextFlags, + /* [annotation] */ + _COM_Outptr_opt_ ID3D11DeviceContext1** ppDeferredContext) final; + + virtual HRESULT STDMETHODCALLTYPE CreateBlendState1( + /* [annotation] */ + _In_ const D3D11_BLEND_DESC1* pBlendStateDesc, + /* [annotation] */ + _COM_Outptr_opt_ ID3D11BlendState1** ppBlendState) final; + + virtual HRESULT STDMETHODCALLTYPE CreateRasterizerState1( + /* [annotation] */ + _In_ const D3D11_RASTERIZER_DESC1* pRasterizerDesc, + /* [annotation] */ + _COM_Outptr_opt_ ID3D11RasterizerState1** ppRasterizerState) final; + + virtual HRESULT STDMETHODCALLTYPE CreateDeviceContextState( + UINT Flags, + /* [annotation] */ + _In_reads_(FeatureLevels) const D3D_FEATURE_LEVEL * pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + REFIID EmulatedInterface, + /* [annotation] */ + _Out_opt_ D3D_FEATURE_LEVEL * pChosenFeatureLevel, + /* [annotation] */ + _Out_opt_ ID3DDeviceContextState * *ppContextState) final; + + virtual HRESULT STDMETHODCALLTYPE OpenSharedResource1( + /* [annotation] */ + _In_ HANDLE hResource, + /* [annotation] */ + _In_ REFIID returnedInterface, + /* [annotation] */ + _COM_Outptr_ void** ppResource) final; + + virtual HRESULT STDMETHODCALLTYPE OpenSharedResourceByName( + /* [annotation] */ + _In_ LPCWSTR lpName, + /* [annotation] */ + _In_ DWORD dwDesiredAccess, + /* [annotation] */ + _In_ REFIID returnedInterface, + /* [annotation] */ + _COM_Outptr_ void** ppResource) final; + + #pragma endregion + + HRESULT STDMETHODCALLTYPE CreateTexture1D( + _In_ const D3D11_TEXTURE1D_DESC * pDesc, + _In_ const FLOAT cClearValue[4], + _In_reads_opt_(_Inexpressible_(pDesc->MipLevels * pDesc->ArraySize)) const D3D11_SUBRESOURCE_DATA * pInitialData, + _Out_opt_ ID3D11Texture1D * *ppTexture1D); + + HRESULT STDMETHODCALLTYPE CreateTexture2D( + _In_ const D3D11_TEXTURE2D_DESC * pDesc, + _In_ const FLOAT cClearValue[4], + _In_reads_opt_(_Inexpressible_(pDesc->MipLevels * pDesc->ArraySize)) const D3D11_SUBRESOURCE_DATA * pInitialData, + _Out_opt_ ID3D11Texture2D * *ppTexture2D); + + HRESULT STDMETHODCALLTYPE CreateTexture3D( + _In_ const D3D11_TEXTURE3D_DESC * pDesc, + _In_ const FLOAT cClearValue[4], + _In_reads_opt_(_Inexpressible_(pDesc->MipLevels)) const D3D11_SUBRESOURCE_DATA * pInitialData, + _Out_opt_ ID3D11Texture3D * *ppTexture3D); + + HRESULT STDMETHODCALLTYPE CreateStagingResource( + _In_ ID3D11Resource* pInputResource, + _Out_ ID3D11Resource** ppStagingResource, + _In_ BOOL Upload); + + HRESULT STDMETHODCALLTYPE ReleaseStagingResource( + _In_ ID3D11Resource* pStagingResource); + +private: + _smart_ptr m_pDevice; + + _smart_ptr m_pContext; +}; + +#endif // __CCRYDX12DEVICE__ diff --git a/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceChild.cpp b/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceChild.cpp new file mode 100644 index 00000000000..4bd44ffaf4f --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceChild.cpp @@ -0,0 +1,16 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or +* a third party where indicated. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" + +EXTERN_C const GUID DECLSPEC_SELECTANY WKPDID_D3DDebugClearValue = { 0x01234567, 0x0123, 0x0123, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 } }; diff --git a/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceChild.hpp b/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceChild.hpp new file mode 100644 index 00000000000..e2f7e320916 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceChild.hpp @@ -0,0 +1,192 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once +#ifndef __CCRYDX12DEVICECHILD__ +#define __CCRYDX12DEVICECHILD__ + +#include "DX12/CCryDX12Object.hpp" + +DEFINE_GUID(WKPDID_D3DDebugObjectName, 0x429b8c22, 0x9188, 0x4b0c, 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00); +DEFINE_GUID(WKPDID_D3DDebugObjectNameW, 0x4cca5fd8, 0x921f, 0x42c8, 0x85, 0x66, 0x70, 0xca, 0xf2, 0xa9, 0xb7, 0x41); +DEFINE_GUID(WKPDID_D3DDebugClearValue, 0x01234567, 0x0123, 0x0123, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01); + +// Specialize std::hash +namespace std { + template<> + struct hash + { + size_t operator()(const GUID& guid) const /*noexcept*/ + { + // RPC_STATUS status; + // return UuidHash((UUID*)&guid, &status); + + const uint64_t* p = reinterpret_cast(&guid); + std::hash hash; + return hash(p[0]) ^ hash(p[1]); + } + }; +} + +template +class CCryDX12DeviceChild + : public CCryDX12Object +{ +public: + DX12_OBJECT(CCryDX12DeviceChild, CCryDX12Object); + + virtual ~CCryDX12DeviceChild() + { + } + +#if !defined(RELEASE) + std::string GetName() + { + UINT len = 512; + char str[512] = "-"; + + GetPrivateData(WKPDID_D3DDebugObjectName, &len, str); + + return str; + } + + HRESULT STDMETHODCALLTYPE GetPrivateCustomData( + _In_ REFGUID guid, + _Inout_ UINT* pDataSize, + _Out_writes_bytes_opt_(*pDataSize) void* pData) + { + TDatas::iterator elm = m_Data.find(guid); + if (elm != m_Data.end()) + { + void* Blob = (*elm).second.second; + UINT nCopied = std::min(*pDataSize, (*elm).second.first); + + *pDataSize = nCopied; + if (pData) + { + memcpy(pData, Blob, nCopied); + } + + return S_OK; + } + + return E_FAIL; + } + + HRESULT STDMETHODCALLTYPE SetPrivateCustomData( + _In_ REFGUID guid, + _In_ UINT DataSize, + _In_reads_bytes_opt_(DataSize) const void* pData) + { + TDatas::iterator elm = m_Data.find(guid); + if (elm != m_Data.end()) + { + Memory.mem_free((*elm).second.second); + } + + if (pData) + { + void* Blob = Memory.mem_alloc(DataSize); + m_Data[guid] = std::make_pair(DataSize, Blob); + memcpy(Blob, pData, DataSize); + } + else + { + m_Data.erase(elm); + } + + return S_OK; + } +#endif + + #pragma region /* ID3D11DeviceChild implementation */ + + virtual void STDMETHODCALLTYPE GetDevice( + _Out_ ID3D11Device** ppDevice) + { + *ppDevice = m_Device; + } + + virtual HRESULT STDMETHODCALLTYPE GetPrivateData( + _In_ REFGUID guid, + _Inout_ UINT* pDataSize, + _Out_writes_bytes_opt_(*pDataSize) void* pData) + { +#if !defined(RELEASE) + if (m_pChild) + { + return m_pChild->GetPrivateData(guid, pDataSize, pData); + } + + return GetPrivateCustomData(guid, pDataSize, pData); +#else + return E_FAIL; +#endif + } + + virtual HRESULT STDMETHODCALLTYPE SetPrivateData( + _In_ REFGUID guid, + _In_ UINT DataSize, + _In_reads_bytes_opt_(DataSize) const void* pData) + { +#if !defined(RELEASE) + if (m_pChild) + { + return m_pChild->SetPrivateData(guid, DataSize, pData); + } + + return SetPrivateCustomData(guid, DataSize, pData); +#else + return E_FAIL; +#endif + } + + virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + _In_ REFGUID guid, + _In_opt_ const IUnknown* pData) + { +#if !defined(RELEASE) + if (m_pChild) + { + return m_pChild->SetPrivateDataInterface(guid, pData); + } +#endif + + return E_FAIL; + } + + #pragma endregion + + CCryDX12Device* GetDevice() + { + return m_Device; + } + +protected: + CCryDX12DeviceChild(CCryDX12Device* pDevice, ID3D12DeviceChild* pChild) + { + m_Device = pDevice; +#if !defined(RELEASE) + m_pChild = pChild; +#endif + } + +private: + CCryDX12Device* m_Device; +#if !defined(RELEASE) + typedef std::unordered_map > TDatas; + TDatas m_Data; + ID3D12DeviceChild* m_pChild; +#endif +}; + +#endif diff --git a/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceContext.cpp b/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceContext.cpp new file mode 100644 index 00000000000..6edc21114f9 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceContext.cpp @@ -0,0 +1,3119 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "CCryDX12DeviceContext.hpp" +#include "CCryDX12Device.hpp" + +#include "DX12/Resource/CCryDX12Resource.hpp" + +#include "DX12/Resource/Misc/CCryDX12Buffer.hpp" +#include "DX12/Resource/Misc/CCryDX12Shader.hpp" +#include "DX12/Resource/Misc/CCryDX12Query.hpp" + +#include "DX12/Resource/State/CCryDX12SamplerState.hpp" + +#include "DX12/Resource/Texture/CCryDX12Texture1D.hpp" +#include "DX12/Resource/Texture/CCryDX12Texture2D.hpp" +#include "DX12/Resource/Texture/CCryDX12Texture3D.hpp" + +#include "DX12/Resource/View/CCryDX12DepthStencilView.hpp" +#include "DX12/Resource/View/CCryDX12RenderTargetView.hpp" +#include "DX12/Resource/View/CCryDX12ShaderResourceView.hpp" +#include "DX12/Resource/View/CCryDX12UnorderedAccessView.hpp" + +#include "DX12/API/DX12Device.hpp" + +#define DX12_SUBMISSION_UNBOUND 3 // never commit, only when the heaps overflow, or on present +#define DX12_SUBMISSION_PERPSO 2 // commit whenever the PSO changes +#define DX12_SUBMISSION_PERDRAW 1 // commit whenever a new draw is requested +#define DX12_SUBMISSION_SYNC 0 // commit always and wait as well + +#define DX12_SUBMISSION_MODE DX12_SUBMISSION_UNBOUND + +CCryDX12DeviceContext* CCryDX12DeviceContext::Create(CCryDX12Device* pDeviced, bool isDeferred) +{ + return DX12::PassAddRef(new CCryDX12DeviceContext(pDeviced, isDeferred)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +CCryDX12DeviceContext::CCryDX12DeviceContext(CCryDX12Device* pDevice, bool isDeferred) + : Super() + , m_bDeferred(isDeferred) + , m_pDevice(pDevice) + , m_pDX12Device(pDevice->GetDX12Device()) + , m_CmdFenceSet(pDevice->GetDX12Device()) + , m_DirectListPool(pDevice->GetDX12Device(), m_CmdFenceSet, CMDQUEUE_GRAPHICS) + , m_CopyListPool(pDevice->GetDX12Device(), m_CmdFenceSet, CMDQUEUE_COPY) + , m_TimestampHeap(pDevice->GetDX12Device()) + , m_PipelineHeap(pDevice->GetDX12Device()) + , m_OcclusionHeap(pDevice->GetDX12Device()) + , m_CurrentRootSignature{} + , m_CurrentPSO{} + , m_OutstandingQueries{} + , m_TimestampIndex{} + , m_OcclusionIndex{} + , m_bInCopyRegion{} +{ + DX12_FUNC_LOG + + // Timer query heap + { + D3D12_QUERY_HEAP_DESC desc = {}; + desc.Count = 1024; + desc.Type = D3D12_QUERY_HEAP_TYPE_TIMESTAMP; + + m_TimestampHeap.Init(m_pDX12Device, desc); + } + + // Occlusion query heap + { + D3D12_QUERY_HEAP_DESC desc = {}; + desc.Count = 64; + desc.Type = D3D12_QUERY_HEAP_TYPE_OCCLUSION; + + m_OcclusionHeap.Init(m_pDX12Device, desc); + } + + // Pipeline query heap + { + D3D12_QUERY_HEAP_DESC desc = {}; + desc.Count = 16; + desc.Type = D3D12_QUERY_HEAP_TYPE_PIPELINE_STATISTICS; + + m_PipelineHeap.Init(m_pDX12Device, desc); + } + + CD3DX12_HEAP_PROPERTIES heapReadback(D3D12_HEAP_TYPE_READBACK); + + CD3DX12_RESOURCE_DESC bufferTimeStamp = + CD3DX12_RESOURCE_DESC::Buffer(sizeof(UINT64) * m_TimestampHeap.GetCapacity()); + + if(S_OK != m_pDX12Device->GetD3D12Device()->CreateCommittedResource( + &heapReadback, + D3D12_HEAP_FLAG_NONE, + &bufferTimeStamp, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&m_TimestampDownloadBuffer))) + { + DX12_ERROR("Could not create intermediate timestamp download buffer!"); + } + + CD3DX12_RESOURCE_DESC bufferOcclusion = + CD3DX12_RESOURCE_DESC::Buffer(sizeof(UINT64) * m_OcclusionHeap.GetCapacity()); + + if (S_OK != m_pDX12Device->GetD3D12Device()->CreateCommittedResource( + &heapReadback, + D3D12_HEAP_FLAG_NONE, + &bufferOcclusion, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&m_OcclusionDownloadBuffer))) + { + DX12_ERROR("Could not create intermediate occlusion download buffer!"); + } + + m_pSamplerHeap = NULL; + m_pResourceHeap = NULL; + m_bCurrentNative = false; + m_nResDynOffset = 0; + m_nFrame = 0; + m_nStencilRef = -1; + + m_TimestampMemory = nullptr; + m_OcclusionMemory = nullptr; + m_TimestampMapValid = false; + m_OcclusionMapValid = false; + + m_CmdFenceSet.Init(); + + m_DirectListPool.Init(); + m_CopyListPool.Init(D3D12_COMMAND_LIST_TYPE_COPY); + + m_DirectListPool.AcquireCommandList(m_DirectCommandList); + m_CopyListPool.AcquireCommandList(m_CopyCommandList); + + m_DirectCommandList->Begin(); + m_DirectCommandList->SetResourceAndSamplerStateHeaps(); + + m_CopyCommandList->Begin(); + + m_pDX12Device->CalibrateClocks(m_DirectCommandList->GetD3D12CommandQueue()); +} + +CCryDX12DeviceContext::~CCryDX12DeviceContext() +{ + DX12_FUNC_LOG + + D3D12_RANGE sNoWrite = { 0, 0 }; + if (m_TimestampMemory) + { + m_TimestampDownloadBuffer->Unmap(0, &sNoWrite); + } + if (m_OcclusionMemory) + { + m_OcclusionDownloadBuffer->Unmap(0, &sNoWrite); + } + + m_TimestampDownloadBuffer->Release(); + m_OcclusionDownloadBuffer->Release(); +} + +bool CCryDX12DeviceContext::PreparePSO(DX12::CommandMode commandMode) +{ + DX12::Device* device = m_pDevice->GetDX12Device(); + + auto& state = m_PipelineState[commandMode]; + const DX12::RootSignature* newRootSignature = m_CurrentRootSignature[commandMode]; + const DX12::PipelineState* newPipelineState = m_CurrentPSO; + + bool bForceFlush = false; + + if (state.m_StateFlags & EPSPB_PipelineState) + { + if (commandMode == DX12::CommandModeGraphics) + { + DX12::RootSignature::GraphicsInitParams rootSignatureParams; + state.MakeInitParams(rootSignatureParams); + newRootSignature = device->GetRootSignatureCache().AcquireRootSignature(rootSignatureParams); + + DX12::GraphicsPipelineState::InitParams psoParams; + psoParams.rootSignature = newRootSignature; + state.MakeInitParams(psoParams); + newPipelineState = device->GetPSOCache().AcquirePipelineState(psoParams); + } + else + { + DX12::RootSignature::ComputeInitParams rootSignatureParams; + state.MakeInitParams(rootSignatureParams); + newRootSignature = device->GetRootSignatureCache().AcquireRootSignature(rootSignatureParams); + + DX12::ComputePipelineState::InitParams psoParams; + psoParams.rootSignature = newRootSignature; + state.MakeInitParams(psoParams); + newPipelineState = device->GetPSOCache().AcquirePipelineState(psoParams); + } + + if (!newPipelineState) + { + return false; + } + + if (DX12_SUBMISSION_MODE == DX12_SUBMISSION_PERPSO && m_OutstandingQueries == 0) + { + bForceFlush = true; + } + } + + // check for overflow and submit early + if (bForceFlush || m_DirectCommandList->IsFull( + /* 256, */ newRootSignature->GetPipelineLayout().m_NumDescriptors, + /* 16, */ newRootSignature->GetPipelineLayout().m_NumDynamicSamplers, + /* 8, */ state.OutputMerger.NumRenderTargets.Get(), + /* 1, */ state.OutputMerger.DepthStencilView ? 1 : 0)) + { + const bool bWait = false; + SubmitDirectCommands(bWait); + +#ifdef DX12_STATS + m_NumCommandListOverflows++; +#endif // DX12_STATS + + ResetCachedState(); + } + + if (state.m_StateFlags & EPSPB_PipelineState) + { + //if (newPipelineState != m_CurrentPSO) + { +#ifdef DX12_STATS + m_NumPSOs += 1; +#endif + m_DirectCommandList->SetPipelineState(newPipelineState); + m_CurrentPSO = newPipelineState; + } + + //if (newRootSignature != m_CurrentRootSignature[commandMode]) + { +#ifdef DX12_STATS + m_NumRootSignatures += 1; +#endif + m_DirectCommandList->SetRootSignature(commandMode, newRootSignature); + m_CurrentRootSignature[commandMode] = newRootSignature; + state.m_StateFlags |= EPSPB_InputResources; + } + } + + return true; +} + +void CCryDX12DeviceContext::PrepareGraphicsFF() +{ + auto& state = m_PipelineState[DX12::CommandModeGraphics]; + const UINT& stateFlags = state.m_StateFlags; + + if (stateFlags & EPSPB_IndexBuffer & (state.InputAssembler.IndexBuffer ? ~0 : 0)) + { + R_ASSERT2(state.InputAssembler.IndexBuffer, "IndexBuffer is required by the Draw but has not been set!"); + m_DirectCommandList->BindAndSetIndexBufferView(state.InputAssembler.IndexBuffer->GetDX12View(), state.InputAssembler.IndexBufferFormat.Get(), state.InputAssembler.IndexBufferOffset.Get()); + } + + if (stateFlags & EPSPB_PrimitiveTopology) + { + m_DirectCommandList->SetPrimitiveTopology(static_cast (state.InputAssembler.PrimitiveTopology.Get())); + } + + if (stateFlags & EPSPB_VertexBuffers) + { + m_DirectCommandList->ClearVertexBufferHeap(state.InputAssembler.NumVertexBuffers.Get()); + + for (UINT i = 0, S = state.InputAssembler.NumVertexBuffers.Get(); i < S; ++i) + { + CCryDX12Buffer* buffer = state.InputAssembler.VertexBuffers.Get(i); + + if (buffer) + { + _range_t bindRange = _range_t (state.InputAssembler.Offsets.Get(i), state.InputAssembler.Offsets.Get(i)); + UINT bindStride = state.InputAssembler.Strides.Get(i); + R_ASSERT2(buffer, "VertexBuffer is required by the PSO but has not been set!"); + m_DirectCommandList->BindVertexBufferView(buffer->GetDX12View(), i, bindRange, bindStride); + } + } + + m_DirectCommandList->SetVertexBufferHeap(state.InputAssembler.NumVertexBuffers.Get()); + } + + if (stateFlags & EPSPB_Viewports) + { + UINT numScissors = state.Rasterizer.ScissorEnabled.Get() ? state.Rasterizer.NumScissors.Get() : 0; + if (state.Rasterizer.NumViewports.Get() >= numScissors) + { + D3D12_VIEWPORT viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D12_RECT scissors[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + + for (UINT i = 0, S = state.Rasterizer.NumViewports.Get(); i < S; ++i) + { + const D3D11_VIEWPORT& v = state.Rasterizer.Viewports.Get(i); + viewports[i].TopLeftX = v.TopLeftX; + viewports[i].TopLeftY = v.TopLeftY; + viewports[i].Width = v.Width; + viewports[i].Height = v.Height; + viewports[i].MinDepth = v.MinDepth; + viewports[i].MaxDepth = v.MaxDepth; + + if (i < numScissors) + { + const D3D11_RECT& s = state.Rasterizer.Scissors.Get(i); + + scissors[i].bottom = s.bottom; + scissors[i].left = s.left; + scissors[i].right = s.right; + scissors[i].top = s.top; + } + else + { + scissors[i].top = static_cast(v.TopLeftY); + scissors[i].left = static_cast(v.TopLeftX); + scissors[i].right = static_cast(v.TopLeftX + v.Width); + scissors[i].bottom = static_cast(v.TopLeftY + v.Height); + } + } + + m_DirectCommandList->SetViewports(state.Rasterizer.NumViewports.Get(), viewports); + m_DirectCommandList->SetScissorRects(state.Rasterizer.NumViewports.Get(), scissors); + } + else + { + // This should not happen, ever! + DX12_NOT_IMPLEMENTED; + } + } + + if (stateFlags & EPSPB_StencilRef) + { + m_DirectCommandList->SetStencilRef(state.OutputMerger.StencilRef.Get()); + } + + if (stateFlags & EPSPB_OutputResources) + { + BindOutputViews(); + } +} + +bool CCryDX12DeviceContext::PrepareGraphicsState() +{ + if (!m_PipelineState[DX12::CommandModeGraphics].AreShadersBound() || m_PipelineState[DX12::CommandModeGraphics].InputAssembler.InputLayout.m_Value == NULL) + { + return false; + } + + if (!PreparePSO(DX12::CommandModeGraphics)) + { + return false; + } + + PrepareGraphicsFF(); + BindResources(DX12::CommandModeGraphics); + + m_PipelineState[DX12::CommandModeGraphics].m_StateFlags = 0; + return true; +} + +bool CCryDX12DeviceContext::PrepareComputeState() +{ + if (!m_PipelineState[DX12::CommandModeCompute].AreShadersBound()) + { + return false; + } + + if (!PreparePSO(DX12::CommandModeCompute)) + { + return false; + } + + BindResources(DX12::CommandModeCompute); + + m_PipelineState[DX12::CommandModeCompute].m_StateFlags = 0; + return true; +} + +void CCryDX12DeviceContext::BindResources(DX12::CommandMode commandMode) +{ + const auto& state = m_PipelineState[commandMode]; + const auto stateFlags = state.m_StateFlags; + + if ((stateFlags & EPSPB_InputResources) == 0) + { + return; + } + DX12_ASSERT(stateFlags & (BIT(EPSP_ConstantBuffers) | BIT(EPSP_Resources) | BIT(EPSP_Samplers)), "Redundant BindResources() called without state-changes"); + + const DX12::PipelineLayout& layout = m_CurrentRootSignature[commandMode]->GetPipelineLayout(); + u32 resourceDescriptorOffset = 0; + u32 samplerDescriptorOffset = 0; + + if (stateFlags & (EPSPB_ConstantBuffers | EPSPB_Resources)) + { + for (const DX12::ResourceLayoutBinding& resourceBinding : layout.m_TableResources) + { + auto& stage = state.Stages[resourceBinding.ShaderStage]; + + switch (resourceBinding.ViewType) + { + case D3D12_DESCRIPTOR_RANGE_TYPE_CBV: + { + CCryDX12Buffer* buffer = stage.ConstantBufferViews.Get(resourceBinding.ShaderSlot); + _range_t bindRange = stage.ConstBufferBindRange.Get(resourceBinding.ShaderSlot); +#ifdef GFX_DEBUG + DX12_ASSERT(resourceDescriptorOffset == resourceBinding.DescriptorOffset, "ConstantBuffer offset has shifted: resource mapping invalid!"); +#endif + m_DirectCommandList->WriteConstantBufferDescriptor(buffer ? &buffer->GetDX12View() : nullptr, resourceDescriptorOffset++, bindRange.start, bindRange.Length()); + break; + } + case D3D12_DESCRIPTOR_RANGE_TYPE_SRV: + { + CCryDX12ShaderResourceView* resource = stage.ShaderResourceViews.Get(resourceBinding.ShaderSlot); +#ifdef GFX_DEBUG + DX12_ASSERT(resourceDescriptorOffset == resourceBinding.DescriptorOffset, "ShaderResourceView offset has shifted: resource mapping invalid!"); +#endif + m_DirectCommandList->WriteShaderResourceDescriptor(resource ? &resource->GetDX12View() : nullptr, resourceDescriptorOffset++); + break; + } + case D3D12_DESCRIPTOR_RANGE_TYPE_UAV: + { + CCryDX12UnorderedAccessView* resource = stage.UnorderedAccessViews.Get(resourceBinding.ShaderSlot); +#ifdef GFX_DEBUG + DX12_ASSERT(resourceDescriptorOffset == resourceBinding.DescriptorOffset, "UnorderedAccessView offset has shifted: resource mapping invalid!"); +#endif + m_DirectCommandList->WriteUnorderedAccessDescriptor(resource ? &resource->GetDX12View() : nullptr, resourceDescriptorOffset++); + break; + } + } + } + + if (stateFlags & EPSPB_ConstantBuffers) + { + for (const DX12::ConstantBufferLayoutBinding& constantBufferBinding : layout.m_ConstantViews) + { + auto& stage = state.Stages[constantBufferBinding.ShaderStage]; + + CCryDX12Buffer* buffer = stage.ConstantBufferViews.Get(constantBufferBinding.ShaderSlot); + _range_t bindRange = stage.ConstBufferBindRange.Get(constantBufferBinding.ShaderSlot); + + D3D12_GPU_VIRTUAL_ADDRESS gpuAddress = { 0ull }; + if (buffer) + { + gpuAddress = buffer->GetDX12View().GetCBVDesc().BufferLocation + bindRange.start; + } + m_DirectCommandList->SetConstantBufferView(commandMode, constantBufferBinding.RootParameterIndex, gpuAddress); + } + } + } + + // Bind samplers + if (stateFlags & EPSPB_Samplers) + { + for (const DX12::ResourceLayoutBinding& samplerBinding : layout.m_Samplers) + { + const DX12::EShaderStage i = samplerBinding.ShaderStage; + DX12_ASSERT(samplerBinding.ViewType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, ""); + { + CCryDX12SamplerState* sampler = state.Stages[i].SamplerState.Get(samplerBinding.ShaderSlot); +#ifdef GFX_DEBUG + DX12_ASSERT(samplerDescriptorOffset == samplerBinding.DescriptorOffset, "Sampler offset has shifted: resource mapping invalid!"); +#endif + m_DirectCommandList->WriteSamplerStateDescriptor(sampler ? &sampler->GetDX12SamplerState() : nullptr, samplerDescriptorOffset++); + } + } + } + + if (stateFlags & (BIT(EPSP_ConstantBuffers) | BIT(EPSP_Resources))) + { + m_DirectCommandList->SetDescriptorTables(commandMode, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + m_DirectCommandList->IncrementInputCursors(layout.m_NumDescriptors, 0); + } + + if (stateFlags & (BIT(EPSP_Samplers))) + { + m_DirectCommandList->SetDescriptorTables(commandMode, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + m_DirectCommandList->IncrementInputCursors(0, layout.m_NumDynamicSamplers); + } +} + +void CCryDX12DeviceContext::BindOutputViews() +{ + const DX12::ResourceView* dsv = NULL; + const DX12::ResourceView* rtv[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT]; + size_t numRTVs = 0; + + auto& outputMerger = m_PipelineState[DX12::CommandModeGraphics].OutputMerger; + + // Get current depth stencil views + { + CCryDX12DepthStencilView* view = outputMerger.DepthStencilView; + if (view) + { + dsv = &view->GetDX12View(); + } + } + + // Get current render target views + for (UINT i = 0, S = outputMerger.NumRenderTargets.Get(); i < S; ++i) + { + CCryDX12RenderTargetView* view = outputMerger.RenderTargetViews.Get(i); + if (view) + { + rtv[numRTVs++] = &view->GetDX12View(); + } + } + + m_DirectCommandList->BindAndSetOutputViews(numRTVs, rtv, dsv); +#ifdef DX12_STATS + m_NumberSettingOutputViews++; +#endif +} + +namespace DX12 +{ + const char* StateToString(D3D12_RESOURCE_STATES state); +} + +void CCryDX12DeviceContext::DebugPrintResources(DX12::CommandMode commandMode) +{ + const DX12::PipelineLayout& layout = m_CurrentRootSignature[commandMode]->GetPipelineLayout(); + + DX12_LOG("Resource Heap Descriptor Tables:"); + + auto& state = m_PipelineState[commandMode]; + UINT stateFlags = state.m_StateFlags; + UINT resourceDescriptorOffset = 0; + UINT samplerDescriptorOffset = 0; + + // Bind constant buffers + for (const DX12::ResourceLayoutBinding& resourceBinding : layout.m_TableResources) + { + const DX12::EShaderStage i = resourceBinding.ShaderStage; + if (resourceBinding.ViewType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV) + { + CCryDX12Buffer* buffer = state.Stages[i].ConstantBufferViews.Get(resourceBinding.ShaderSlot); + auto bindRange = state.Stages[i].ConstBufferBindRange.Get(resourceBinding.ShaderSlot); +#ifdef GFX_DEBUG + R_ASSERT2(buffer, "ConstantBuffer is required by the PSO but has not been set!"); + R_ASSERT2(resourceDescriptorOffset == resourceBinding.DescriptorOffset, "ConstantBuffer offset has shifted: resource mapping invalid!"); +#endif + DX12_LOG(" %s: C %2d -> %2d %s [%s]", + i == DX12::ESS_Compute ? "Every shader stage" : + i == DX12::ESS_Vertex ? "Vertex shader stage" : + i == DX12::ESS_Hull ? "Hull shader stage" : + i == DX12::ESS_Domain ? "Domain shader stage" : + i == DX12::ESS_Geometry ? "Geometry shader stage" : + i == DX12::ESS_Pixel ? "Pixel shader stage" : "Unknown shader stage", + resourceBinding.ShaderSlot, + resourceDescriptorOffset++, + buffer ? buffer->GetName().c_str() : "nullptr", + buffer ? DX12::StateToString(buffer->GetDX12Resource().GetCurrentState()) : "-"); + } + else if (resourceBinding.ViewType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV) + { + CCryDX12ShaderResourceView* resource = state.Stages[i].ShaderResourceViews.Get(resourceBinding.ShaderSlot); +#ifdef GFX_DEBUG + R_ASSERT2(resource, "ShaderResourceView is required by the PSO but has not been set!"); + R_ASSERT2(resourceDescriptorOffset == resourceBinding.DescriptorOffset, "ShaderResourceView offset has shifted: resource mapping invalid!"); +#endif + DX12_LOG(" %s: T %2d -> %2d %s [%s]", + i == DX12::ESS_Compute ? "Every shader stage" : + i == DX12::ESS_Vertex ? "Vertex shader stage" : + i == DX12::ESS_Hull ? "Hull shader stage" : + i == DX12::ESS_Domain ? "Domain shader stage" : + i == DX12::ESS_Geometry ? "Geometry shader stage" : + i == DX12::ESS_Pixel ? "Pixel shader stage" : "Unknown shader stage", + resourceBinding.ShaderSlot, + resourceDescriptorOffset++, + resource ? resource->GetResourceName().c_str() : "nullptr", + resource ? DX12::StateToString(resource->GetDX12Resource().GetCurrentState()) : "-"); + } + else if (resourceBinding.ViewType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV) + { + CCryDX12UnorderedAccessView* resource = state.Stages[i].UnorderedAccessViews.Get(resourceBinding.ShaderSlot); +#ifdef GFX_DEBUG + R_ASSERT2(resource, "UnorderedAccessView is required by the PSO but has not been set!"); + R_ASSERT2(resourceDescriptorOffset == resourceBinding.DescriptorOffset, "UnorderedAccessView offset has shifted: resource mapping invalid!"); +#endif + DX12_LOG(" %s: U %2d -> %2d %s [%s]", + i == DX12::ESS_Compute ? "Every shader stage" : + i == DX12::ESS_Vertex ? "Vertex shader stage" : + i == DX12::ESS_Hull ? "Hull shader stage" : + i == DX12::ESS_Domain ? "Domain shader stage" : + i == DX12::ESS_Geometry ? "Geometry shader stage" : + i == DX12::ESS_Pixel ? "Pixel shader stage" : "Unknown shader stage", + resourceBinding.ShaderSlot, + resourceDescriptorOffset++, + resource ? resource->GetResourceName().c_str() : "nullptr", + resource ? DX12::StateToString(resource->GetDX12Resource().GetCurrentState()) : "-"); + } + } + + // Bind samplers + for (const DX12::ResourceLayoutBinding& samplerBinding : layout.m_Samplers) + { + const DX12::EShaderStage i = samplerBinding.ShaderStage; + R_ASSERT2(samplerBinding.ViewType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, ""); + { + CCryDX12SamplerState* sampler = state.Stages[i].SamplerState.Get(samplerBinding.ShaderSlot); +#ifdef GFX_DEBUG + R_ASSERT2(sampler, "Sampler is required by the PSO but has not been set!"); + R_ASSERT2(samplerDescriptorOffset == samplerBinding.DescriptorOffset, "Sampler offset has shifted: resource mapping invalid!"); +#endif + DX12_LOG(" %s: S %2d -> %2d", + i == DX12::ESS_Compute ? "Every shader stage" : + i == DX12::ESS_Vertex ? "Vertex shader stage" : + i == DX12::ESS_Hull ? "Hull shader stage" : + i == DX12::ESS_Domain ? "Domain shader stage" : + i == DX12::ESS_Geometry ? "Geometry shader stage" : + i == DX12::ESS_Pixel ? "Pixel shader stage" : "Unknown shader stage", + samplerBinding.ShaderSlot, + samplerDescriptorOffset++); + } + } +} + +void CCryDX12DeviceContext::CeaseDirectCommandQueue(bool wait) +{ + + R_ASSERT2(m_DirectCommandList != nullptr, "CommandList hasn't been allocated!"); + R_ASSERT2(m_OutstandingQueries == 0, "Flushing command list with outstanding queries!"); + + m_DirectCommandList->End(); + m_DirectListPool.ForfeitCommandList(m_DirectCommandList, wait); +} + +void CCryDX12DeviceContext::ResumeDirectCommandQueue() +{ + + R_ASSERT2(m_DirectCommandList == nullptr, "CommandList hasn't been submitted!"); + m_DirectListPool.AcquireCommandList(m_DirectCommandList); + + m_DirectCommandList->Begin(); + m_DirectCommandList->SetResourceAndSamplerStateHeaps(); + + ResetCachedState(); +} + +void CCryDX12DeviceContext::CeaseCopyCommandQueue(bool wait) +{ + + R_ASSERT2(m_CopyCommandList != nullptr, "CommandList hasn't been allocated!"); + + m_CopyCommandList->End(); + m_CopyListPool.ForfeitCommandList(m_CopyCommandList, wait); +} + +void CCryDX12DeviceContext::ResumeCopyCommandQueue() +{ + + R_ASSERT2(m_CopyCommandList == nullptr, "CommandList hasn't been submitted!"); + m_CopyListPool.AcquireCommandList(m_CopyCommandList); + + m_CopyCommandList->Begin(); +} + +void CCryDX12DeviceContext::CeaseAllCommandQueues(bool wait) +{ + + CeaseDirectCommandQueue(wait); + CeaseCopyCommandQueue(wait); +} + +void CCryDX12DeviceContext::ResumeAllCommandQueues() +{ + + ResumeDirectCommandQueue(); + ResumeCopyCommandQueue(); +} + +void CCryDX12DeviceContext::SubmitDirectCommands(bool wait) +{ + if (m_DirectCommandList->IsUtilized()) + { + + CeaseDirectCommandQueue(wait); + ResumeDirectCommandQueue(); + } +} + +void CCryDX12DeviceContext::SubmitCopyCommands(bool wait) +{ + if (m_CopyCommandList->IsUtilized()) + { + + CeaseCopyCommandQueue(wait); + ResumeCopyCommandQueue(); + } +} + +void CCryDX12DeviceContext::SubmitDirectCommands(bool wait, const UINT64 fenceValue) +{ + if (m_DirectCommandList->IsUtilized() && (m_CmdFenceSet.GetCurrentValue(CMDQUEUE_GRAPHICS) == fenceValue)) + { +#ifdef DX12_STATS + m_NumCommandListSplits++; +#endif // DX12_STATS + + SubmitDirectCommands(wait); + } +} + +void CCryDX12DeviceContext::SubmitCopyCommands(bool wait, const UINT64 fenceValue) +{ + if (m_CopyCommandList->IsUtilized() && (m_CmdFenceSet.GetCurrentValue(CMDQUEUE_COPY) == fenceValue)) + { +#ifdef DX12_STATS + m_NumCommandListSplits++; +#endif // DX12_STATS + + SubmitCopyCommands(wait); + } +} + +void CCryDX12DeviceContext::SubmitAllCommands(bool bWaitForGpu) +{ + SubmitAllCommands(bWaitForGpu, m_CmdFenceSet.GetCurrentValues()); +} + +void CCryDX12DeviceContext::SubmitAllCommands(bool wait, const UINT64 (&fenceValues)[CMDQUEUE_NUM]) +{ + SubmitDirectCommands(wait, fenceValues[CMDQUEUE_GRAPHICS]); + SubmitCopyCommands(wait, fenceValues[CMDQUEUE_COPY]); +} + + +void CCryDX12DeviceContext::SubmitAllCommands(bool wait, const UINT64(&fenceValues)[CMDQUEUE_NUM], int fenceId) +{ + u64 fenceValuesMasked[CMDQUEUE_NUM]; + fenceValuesMasked[CMDQUEUE_GRAPHICS] = fenceValues[CMDQUEUE_GRAPHICS]; + fenceValuesMasked[CMDQUEUE_COPY] = fenceValues[CMDQUEUE_COPY]; + fenceValuesMasked[fenceId] = 0; + + SubmitDirectCommands(wait, fenceValuesMasked[CMDQUEUE_GRAPHICS]); + SubmitCopyCommands(wait, fenceValuesMasked[CMDQUEUE_COPY]); +} + +void CCryDX12DeviceContext::SubmitAllCommands(bool wait, const std::atomic(&fenceValues)[CMDQUEUE_NUM]) +{ + SubmitDirectCommands(wait, fenceValues[CMDQUEUE_GRAPHICS]); + SubmitCopyCommands(wait, fenceValues[CMDQUEUE_COPY]); +} + +void CCryDX12DeviceContext::SubmitAllCommands(bool wait, const std::atomic(&fenceValues)[CMDQUEUE_NUM], int fenceId) +{ + u64 fenceValuesMasked[CMDQUEUE_NUM]; + fenceValuesMasked[CMDQUEUE_GRAPHICS] = fenceValues[CMDQUEUE_GRAPHICS]; + fenceValuesMasked[CMDQUEUE_COPY] = fenceValues[CMDQUEUE_COPY]; + fenceValuesMasked[fenceId] = 0; + + SubmitDirectCommands(wait, fenceValuesMasked[CMDQUEUE_GRAPHICS]); + SubmitCopyCommands(wait, fenceValuesMasked[CMDQUEUE_COPY]); +} + +void CCryDX12DeviceContext::Finish(DX12::SwapChain* pDX12SwapChain) +{ + + m_DirectCommandList->PresentRenderTargetView(pDX12SwapChain); + + SubmitAllCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, m_CmdFenceSet.GetCurrentValues()); + + // Release resource after pass fence and FRAME_FENCE_LATENCY later + m_pDX12Device->FlushReleaseHeap(DX12::Device::ResourceReleasePolicy::Deferred); + + m_pDX12Device->FinishFrame(); + m_pDX12Device->CalibrateClocks(m_DirectListPool.GetD3D12CommandQueue()); + +#ifdef DX12_STATS + m_NumMapDiscardSkips = 0; + m_NumMapDiscards = 0; + + m_NumCommandListOverflows = 0; + m_NumCommandListSplits = 0; + m_NumPSOs = 0; + m_NumRootSignatures = 0; + m_NumberSettingOutputViews = 0; +#endif // DX12_STATS +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +UINT CCryDX12DeviceContext::TimestampIndex(DX12::CommandList* pCmdList) +{ + UINT index = m_TimestampIndex; + m_TimestampIndex = (m_TimestampIndex + 1) % m_TimestampHeap.GetCapacity(); + return index; +} + +ID3D12Resource* CCryDX12DeviceContext::QueryTimestamp(DX12::CommandList* pCmdList, UINT index) +{ + pCmdList->EndQuery(m_TimestampHeap, D3D12_QUERY_TYPE_TIMESTAMP, index); + + m_TimestampMapValid = false; + if (m_TimestampMemory) + { + const D3D12_RANGE sNoWrite = { 0, 0 }; + m_TimestampDownloadBuffer->Unmap(0, &sNoWrite); + m_TimestampMemory = nullptr; + } + + return m_TimestampDownloadBuffer; +} + +void CCryDX12DeviceContext::ResolveTimestamp(DX12::CommandList* pCmdList, UINT index, void* mem) +{ + if (mem) + { + if (!m_TimestampMapValid) + { + if (m_TimestampMemory) + { + const D3D12_RANGE sNoWrite = { 0, 0 }; + m_TimestampDownloadBuffer->Unmap(0, &sNoWrite); + m_TimestampMemory = nullptr; + } + + pCmdList->ResolveQueryData(m_TimestampHeap, D3D12_QUERY_TYPE_TIMESTAMP, 0, m_TimestampHeap.GetCapacity(), m_TimestampDownloadBuffer, 0); + + // Resources on D3D12_HEAP_TYPE_READBACK heaps do not support persistent map. + const D3D12_RANGE sFullRead = { 0, sizeof(UINT64) * m_TimestampHeap.GetCapacity() }; + m_TimestampDownloadBuffer->Map(0, &sFullRead, &m_TimestampMemory); + m_TimestampMapValid = true; + } + + memcpy(mem, (char*)m_TimestampMemory + index * 8, 8); + } +} + +UINT64 CCryDX12DeviceContext::MakeCpuTimestamp(UINT64 gpuTimestamp) const +{ + return m_pDX12Device->MakeCpuTimestamp(gpuTimestamp); +} + +UINT64 CCryDX12DeviceContext::MakeCpuTimestampMicroseconds(UINT64 gpuTimestamp) const +{ + return m_pDX12Device->MakeCpuTimestampMicroseconds(gpuTimestamp); +} + +UINT CCryDX12DeviceContext::OcclusionIndex(DX12::CommandList* pCmdList, bool counter) +{ + UINT index = m_OcclusionIndex; + m_OcclusionIndex = (m_OcclusionIndex + 1) % m_OcclusionHeap.GetCapacity(); + pCmdList->BeginQuery(m_OcclusionHeap, counter ? D3D12_QUERY_TYPE_OCCLUSION : D3D12_QUERY_TYPE_BINARY_OCCLUSION, index); + return index; +} + +ID3D12Resource* CCryDX12DeviceContext::QueryOcclusion(DX12::CommandList* pCmdList, UINT index, bool counter) +{ + pCmdList->EndQuery(m_OcclusionHeap, counter ? D3D12_QUERY_TYPE_OCCLUSION : D3D12_QUERY_TYPE_BINARY_OCCLUSION, index); + + m_OcclusionMapValid = false; + if (m_OcclusionMemory) + { + const D3D12_RANGE sNoWrite = { 0, 0 }; + m_OcclusionDownloadBuffer->Unmap(0, &sNoWrite); + m_OcclusionMemory = nullptr; + } + + return m_OcclusionDownloadBuffer; +} + +void CCryDX12DeviceContext::ResolveOcclusion(DX12::CommandList* pCmdList, UINT index, void* mem) +{ + if (mem) + { + if (!m_OcclusionMapValid) + { + if (m_OcclusionMemory) + { + const D3D12_RANGE sNoWrite = { 0, 0 }; + m_OcclusionDownloadBuffer->Unmap(0, &sNoWrite); + m_OcclusionMemory = nullptr; + } + + pCmdList->ResolveQueryData(m_OcclusionHeap, D3D12_QUERY_TYPE_OCCLUSION, 0, m_OcclusionHeap.GetCapacity(), m_OcclusionDownloadBuffer, 0); + + // Resources on D3D12_HEAP_TYPE_READBACK heaps do not support persistent map. + const D3D12_RANGE sFullRead = { 0, sizeof(UINT64) * m_OcclusionHeap.GetCapacity() }; + m_OcclusionDownloadBuffer->Map(0, &sFullRead, &m_OcclusionMemory); + m_OcclusionMapValid = true; + } + + memcpy(mem, (char*)m_OcclusionMemory + index * 8, 8); + } +} + +void CCryDX12DeviceContext::WaitForIdle() +{ + DX12::CommandListFence fence(m_pDX12Device); + fence.Init(); + + m_DirectListPool.GetD3D12CommandQueue()->Signal(fence.GetFence(), 1); + + fence.WaitForFence(1); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma region /* ID3D11DeviceChild implementation */ + +void STDMETHODCALLTYPE CCryDX12DeviceContext::GetDevice( + _Out_ ID3D11Device** ppDevice) +{ + DX12_FUNC_LOG +} + +HRESULT STDMETHODCALLTYPE CCryDX12DeviceContext::GetPrivateData( + _In_ REFGUID guid, + _Inout_ UINT* pDataSize, + _Out_writes_bytes_opt_(*pDataSize) void* pData) +{ + DX12_FUNC_LOG + return -1; +} + +HRESULT STDMETHODCALLTYPE CCryDX12DeviceContext::SetPrivateData( + _In_ REFGUID guid, + _In_ UINT DataSize, + _In_reads_bytes_opt_(DataSize) const void* pData) +{ + DX12_FUNC_LOG + return -1; +} + +HRESULT STDMETHODCALLTYPE CCryDX12DeviceContext::SetPrivateDataInterface( + _In_ REFGUID guid, + _In_opt_ const IUnknown* pData) +{ + DX12_FUNC_LOG + return -1; +} + +#pragma endregion + +#pragma region /* ID3D11DeviceContext implementation */ + +void STDMETHODCALLTYPE CCryDX12DeviceContext::VSSetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer* const* ppConstantBuffers) +{ + VSSetConstantBuffers1(StartSlot, NumBuffers, ppConstantBuffers, NULL, NULL); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::PSSetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11ShaderResourceView* const* ppShaderResourceViews) +{ + DX12_FUNC_LOG + for (UINT i = StartSlot, S = StartSlot + NumViews; i < S; ++i, ++ppShaderResourceViews) + { + CCryDX12ShaderResourceView* srv = reinterpret_cast(*ppShaderResourceViews); + if (m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Pixel].ShaderResourceViews.Set(i, srv) && srv) + { + srv->BeginResourceStateTransition(m_DirectCommandList.get()); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::PSSetShader( + _In_opt_ ID3D11PixelShader* pPixelShader, + _In_reads_opt_(NumClassInstances) ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances) +{ + DX12_FUNC_LOG + m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Pixel].Shader.Set(reinterpret_cast(pPixelShader)); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::PSSetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _In_reads_opt_(NumSamplers) ID3D11SamplerState* const* ppSamplers) +{ + DX12_FUNC_LOG + for (UINT i = StartSlot, S = StartSlot + NumSamplers; i < S; ++i, ++ppSamplers) + { + m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Pixel].SamplerState.Set(i, reinterpret_cast(*ppSamplers)); + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::VSSetShader( + _In_opt_ ID3D11VertexShader* pVertexShader, + _In_reads_opt_(NumClassInstances) ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances) +{ + DX12_FUNC_LOG + m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Vertex].Shader.Set(reinterpret_cast(pVertexShader)); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DrawIndexed( + _In_ UINT IndexCount, + _In_ UINT StartIndexLocation, + _In_ INT BaseVertexLocation) +{ + DX12_FUNC_LOG + + SubmitCopyCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + + if (PrepareGraphicsState()) + { + m_DirectCommandList->DrawIndexedInstanced(IndexCount, 1, StartIndexLocation, BaseVertexLocation, 0); +#ifdef DEBUG_BUILD + m_PipelineState[DX12::CommandModeGraphics].DebugPrint(); +#endif + if (DX12_SUBMISSION_MODE <= DX12_SUBMISSION_PERDRAW && m_OutstandingQueries == 0) + { + SubmitDirectCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::Draw( + _In_ UINT VertexCount, + _In_ UINT StartVertexLocation) +{ + DX12_FUNC_LOG + + SubmitCopyCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + + if (PrepareGraphicsState()) + { + m_DirectCommandList->DrawInstanced(VertexCount, 1, StartVertexLocation, 0); +#ifdef DEBUG_BUILD + m_PipelineState[DX12::CommandModeGraphics].DebugPrint(); +#endif + if (DX12_SUBMISSION_MODE <= DX12_SUBMISSION_PERDRAW && m_OutstandingQueries == 0) + { + SubmitDirectCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + } + } +} + +#include + +HRESULT STDMETHODCALLTYPE CCryDX12DeviceContext::Map( + _In_ ID3D11Resource* pResource, + _In_ UINT Subresource, + _In_ D3D11_MAP MapType, + _In_ UINT MapFlags, + _Out_ D3D11_MAPPED_SUBRESOURCE* pMappedResource) +{ + DX12_FUNC_LOG + + ZeroMemory(pMappedResource, sizeof(D3D11_MAPPED_SUBRESOURCE)); + + DX12_LOG(" Mapping resource: %p (%d)", pResource, Subresource); + ICryDX12Resource* dx12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pResource); + DX12::Resource& resource = dx12Resource->GetDX12Resource(); + + if (!resource.IsOffCard()) + { + D3D12_RESOURCE_DESC textureDesc = resource.GetDesc(); + if (textureDesc.Dimension == D3D12_RESOURCE_DIMENSION::D3D12_RESOURCE_DIMENSION_TEXTURE2D) + { + Microsoft::WRL::ComPtr pStagingResource; + HRESULT hr = m_pDevice->CreateStagingResource(pResource, pStagingResource.GetAddressOf(), TRUE); + hr = hr == S_OK && CopyStagingResource(pStagingResource.Get(), pResource, Subresource, TRUE); + hr = hr == S_OK && MapStagingResource(pResource, pStagingResource.Get(), Subresource, TRUE, &pMappedResource->pData, + &pMappedResource->RowPitch); + + if (S_OK != hr) + { + R_ASSERT2(0, "Could not map resource!"); + return hr; + } + + CCryDX12Texture2D* dx12Tex2dResource = DX12_EXTRACT_TEXTURE2D(pResource); + dx12Tex2dResource->AttachStagingResource(pStagingResource.Get()); + return hr; + } + + return S_FALSE; + } + + switch (MapType) + { + case D3D11_MAP_READ: + // Ensure the command-list using the resource is executed + SubmitAllCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, resource.GetFenceValues(CMDTYPE_WRITE)); + + // Block the CPU-thread until the resource is safe to map + resource.WaitForUnused(m_DirectListPool, CMDTYPE_WRITE); + break; + case D3D11_MAP_WRITE: + case D3D11_MAP_READ_WRITE: + // Ensure the command-list using the resource is executed + SubmitAllCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, resource.GetFenceValues(CMDTYPE_ANY)); + + // Block the CPU-thread until the resource is safe to map + resource.WaitForUnused(m_DirectListPool, CMDTYPE_ANY); + break; + case D3D11_MAP_WRITE_DISCARD: + DX12_LOG("Using D3D11_MAP_WRITE_DISCARD on old ID3D12Resource: %p", DX12_EXTRACT_D3D12RESOURCE(pResource)); + +#ifdef DX12_STATS + m_NumMapDiscardSkips += !resource.IsUsed(m_DirectListPool); + m_NumMapDiscards++; +#endif // DX12_STATS + + // If the resource is not currently used, we do not need to discard the memory + if (resource.IsUsed(m_DirectListPool)) + { + dx12Resource->MapDiscard(m_DirectCommandList); + } + + DX12_LOG("New ID3D12Resource: %p", DX12_EXTRACT_D3D12RESOURCE(pResource)); + break; + case D3D11_MAP_WRITE_NO_OVERWRITE: + break; + default: + break; + } + + static D3D12_RANGE sRg[] = + { + { 0, 0 }, // It is valid to specify the CPU won't read any data by passing a range where End is less than or equal to Begin + { 0, 0 } // It is valid to specify the CPU didn't write any data by passing a range where End is less than or equal to Begin. + }; + + static D3D12_RANGE* pRanges[] = + { + nullptr, // D3D11_MAP_READ = 1, + nullptr, // D3D11_MAP_WRITE = 2, + nullptr, // D3D11_MAP_READ_WRITE = 3, + &sRg[0], // D3D11_MAP_WRITE_DISCARD = 4, + &sRg[0], // D3D11_MAP_WRITE_NO_OVERWRITE = 5 + }; + R_ASSERT2((MapType - 1) < DX12_ARRAY_SIZE(pRanges), "Invalid map type"); + + R_ASSERT2(!D3D12IsLayoutOpaque(resource.GetDesc().Layout), "Opaque layouts are unmappable until 12.2!"); + HRESULT hr = dx12Resource->GetD3D12Resource()->Map(Subresource, pRanges[MapType - 1], &(pMappedResource->pData)); + + if (S_OK != hr) + { + R_ASSERT2(0, "Could not map resource!"); + return hr; + } + + return S_OK; +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::Unmap( + _In_ ID3D11Resource* pResource, + _In_ UINT Subresource) +{ + DX12_FUNC_LOG + + DX12_LOG("Unmapping resource: %p (%d)", pResource, Subresource); + ICryDX12Resource* dx12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pResource); + DX12::Resource& resource = dx12Resource->GetDX12Resource(); + + if (!resource.IsOffCard()) + { + D3D12_RESOURCE_DESC textureDesc = resource.GetDesc(); + if (textureDesc.Dimension == D3D12_RESOURCE_DIMENSION::D3D12_RESOURCE_DIMENSION_TEXTURE2D) + { + CCryDX12Texture2D* dx12Tex2dResource = DX12_EXTRACT_TEXTURE2D(pResource); + Microsoft::WRL::ComPtr pStagingResource; + if (dx12Tex2dResource->GetStagingResource(pStagingResource.GetAddressOf())) + { + UnmapStagingResource(pStagingResource.Get(), TRUE); + m_pDevice->ReleaseStagingResource(pStagingResource.Get()); + return; + } + } + } + + // NOTE: Don't know MapType, can't optimize writeRange! + R_ASSERT2(!D3D12IsLayoutOpaque(resource.GetDesc().Layout), "Opaque layouts are unmappable until 12.2!"); + dx12Resource->GetD3D12Resource()->Unmap(Subresource, NULL); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::PSSetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer* const* ppConstantBuffers) +{ + PSSetConstantBuffers1(StartSlot, NumBuffers, ppConstantBuffers, NULL, NULL); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::IASetInputLayout( + _In_opt_ ID3D11InputLayout* pInputLayout) +{ + DX12_FUNC_LOG + + m_PipelineState[DX12::CommandModeGraphics].InputAssembler.InputLayout.Set(reinterpret_cast(pInputLayout)); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::IASetVertexBuffers( + _In_range_(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer* const* ppVertexBuffers, + _In_reads_opt_(NumBuffers) const UINT* pStrides, + _In_reads_opt_(NumBuffers) const UINT* pOffsets) +{ + DX12_FUNC_LOG + + auto& inputAssembler = m_PipelineState[DX12::CommandModeGraphics].InputAssembler; + for (UINT i = StartSlot, S = StartSlot + NumBuffers; i < S; ++i, ++ppVertexBuffers, ++pStrides, ++pOffsets) + { + CCryDX12Buffer* vb = reinterpret_cast(*ppVertexBuffers); + + inputAssembler.Strides.Set(i, *pStrides); + inputAssembler.Offsets.Set(i, *pOffsets); + if (inputAssembler.VertexBuffers.Set(i, vb) && vb) + { + vb->BeginResourceStateTransition(m_DirectCommandList.get(), D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); + } + } + + UINT numVertexBuffers = 0; + for (UINT i = 0; i < D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; ++i) + { + if (inputAssembler.VertexBuffers.Get(i)) + { + numVertexBuffers = i + 1; + } + } + + inputAssembler.NumVertexBuffers.Set(numVertexBuffers); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::IASetIndexBuffer( + _In_opt_ ID3D11Buffer* pIndexBuffer, + _In_ DXGI_FORMAT Format, + _In_ UINT Offset) +{ + DX12_FUNC_LOG + + auto& inputAssembler = m_PipelineState[DX12::CommandModeGraphics].InputAssembler; + CCryDX12Buffer* ib = reinterpret_cast(pIndexBuffer); + + inputAssembler.IndexBufferFormat.Set(Format); + inputAssembler.IndexBufferOffset.Set(Offset); + if (inputAssembler.IndexBuffer.Set(ib) && ib) + { + ib->BeginResourceStateTransition(m_DirectCommandList.get(), D3D12_RESOURCE_STATE_INDEX_BUFFER); + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DrawIndexedInstanced( + _In_ UINT IndexCountPerInstance, + _In_ UINT InstanceCount, + _In_ UINT StartIndexLocation, + _In_ INT BaseVertexLocation, + _In_ UINT StartInstanceLocation) +{ + DX12_FUNC_LOG + + SubmitCopyCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + + if (PrepareGraphicsState()) + { + m_DirectCommandList->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation); +#ifdef DEBUG_BUILD + m_PipelineState[DX12::CommandModeGraphics].DebugPrint(); +#endif + if (DX12_SUBMISSION_MODE <= DX12_SUBMISSION_PERDRAW && m_OutstandingQueries == 0) + { + SubmitDirectCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DrawInstanced( + _In_ UINT VertexCountPerInstance, + _In_ UINT InstanceCount, + _In_ UINT StartVertexLocation, + _In_ UINT StartInstanceLocation) +{ + DX12_FUNC_LOG + + SubmitCopyCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + + if (PrepareGraphicsState()) + { + m_DirectCommandList->DrawInstanced(VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation); +#ifdef DEBUG_BUILD + m_PipelineState[DX12::CommandModeGraphics].DebugPrint(); +#endif + if (DX12_SUBMISSION_MODE <= DX12_SUBMISSION_PERDRAW && m_OutstandingQueries == 0) + { + SubmitDirectCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::GSSetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer* const* ppConstantBuffers) +{ + GSSetConstantBuffers1(StartSlot, NumBuffers, ppConstantBuffers, NULL, NULL); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::GSSetShader( + _In_opt_ ID3D11GeometryShader* pShader, + _In_reads_opt_(NumClassInstances) ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances) +{ + DX12_FUNC_LOG + m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Geometry].Shader.Set(reinterpret_cast(pShader)); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::IASetPrimitiveTopology( + _In_ D3D11_PRIMITIVE_TOPOLOGY Topology) +{ + DX12_FUNC_LOG + m_PipelineState[DX12::CommandModeGraphics].InputAssembler.PrimitiveTopology.Set(Topology); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::VSSetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11ShaderResourceView* const* ppShaderResourceViews) +{ + DX12_FUNC_LOG + for (UINT i = StartSlot, S = StartSlot + NumViews; i < S; ++i, ++ppShaderResourceViews) + { + CCryDX12ShaderResourceView* srv = reinterpret_cast(*ppShaderResourceViews); + if (m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Vertex].ShaderResourceViews.Set(i, srv) && srv) + { + srv->BeginResourceStateTransition(m_DirectCommandList.get()); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::VSSetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _In_reads_opt_(NumSamplers) ID3D11SamplerState* const* ppSamplers) +{ + DX12_FUNC_LOG + for (UINT i = StartSlot, S = StartSlot + NumSamplers; i < S; ++i, ++ppSamplers) + { + m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Vertex].SamplerState.Set(i, reinterpret_cast(*ppSamplers)); + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::Begin( + _In_ ID3D11Asynchronous* pAsync) +{ + DX12_FUNC_LOG + auto pQuery = reinterpret_cast(pAsync); + + D3D11_QUERY_DESC desc; + pQuery->GetDesc(&desc); + + if (desc.Query == D3D11_QUERY_EVENT) + { + return; + } + else if (desc.Query == D3D11_QUERY_TIMESTAMP_DISJOINT) + { + return; + } + else if (desc.Query == D3D11_QUERY_TIMESTAMP) + { + return; + } + else if (desc.Query == D3D11_QUERY_OCCLUSION || desc.Query == D3D11_QUERY_OCCLUSION_PREDICATE) + { + auto pOcclusionQuery = reinterpret_cast(pAsync); + pOcclusionQuery->SetFenceValue(m_CmdFenceSet.GetCurrentValue(CMDQUEUE_GRAPHICS)); + pOcclusionQuery->SetQueryIndex(OcclusionIndex(m_DirectCommandList, desc.Query == D3D11_QUERY_OCCLUSION)); + ++m_OutstandingQueries; + } + else + { + __debugbreak(); + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::End( + _In_ ID3D11Asynchronous* pAsync) +{ + DX12_FUNC_LOG + auto pQuery = reinterpret_cast(pAsync); + + D3D11_QUERY_DESC desc; + pQuery->GetDesc(&desc); + + if (desc.Query == D3D11_QUERY_EVENT) + { + // Record fence of commands prior to this point + auto pEventQuery = reinterpret_cast(pAsync); + pEventQuery->SetFenceValue(InsertFence()); + } + else if (desc.Query == D3D11_QUERY_TIMESTAMP_DISJOINT) + { + return; + } + else if (desc.Query == D3D11_QUERY_TIMESTAMP) + { + // Record fence of commands following at this point + auto pTimestampQuery = reinterpret_cast(pAsync); + pTimestampQuery->SetFenceValue(InsertFence()); + pTimestampQuery->SetQueryIndex(TimestampIndex(m_DirectCommandList)); + pTimestampQuery->SetQueryResource(QueryTimestamp(m_DirectCommandList, pTimestampQuery->GetQueryIndex())); + } + else if (desc.Query == D3D11_QUERY_OCCLUSION) + { + auto pOcclusionQuery = reinterpret_cast(pAsync); + pOcclusionQuery->SetFenceValue(InsertFence()); + pOcclusionQuery->SetQueryResource(QueryOcclusion(m_DirectCommandList, pOcclusionQuery->GetQueryIndex(), desc.Query == D3D11_QUERY_OCCLUSION)); + + R_ASSERT2(m_OutstandingQueries != 0, "End without a Start"); + --m_OutstandingQueries; + } + else // || desc.Query == D3D11_QUERY_OCCLUSION_PREDICATE) + { + __debugbreak(); + } +} + +HRESULT STDMETHODCALLTYPE CCryDX12DeviceContext::GetData( + _In_ ID3D11Asynchronous* pAsync, + _Out_writes_bytes_opt_(DataSize) void* pData, + _In_ UINT DataSize, + _In_ UINT GetDataFlags) +{ + DX12_FUNC_LOG + auto pQuery = reinterpret_cast(pAsync); + + D3D11_QUERY_DESC desc; + pQuery->GetDesc(&desc); + + if (desc.Query == D3D11_QUERY_EVENT) + { + R_ASSERT2(DataSize >= sizeof(BOOL), "Invalid data size"); + + auto pEventQuery = reinterpret_cast(pAsync); + bool bComplete = TestForFence(pEventQuery->GetFenceValue()) == S_OK; + + if (!bComplete && !(GetDataFlags & D3D11_ASYNC_GETDATA_DONOTFLUSH)) + { + // Ensure the command-list issuing the query is executed + SubmitDirectCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, pEventQuery->GetFenceValue()); + FlushToFence(pEventQuery->GetFenceValue()); + } + + return (*reinterpret_cast(pData) = bComplete) ? S_OK : S_FALSE; + } + else if (desc.Query == D3D11_QUERY_TIMESTAMP_DISJOINT) + { + R_ASSERT2(DataSize >= sizeof(D3D11_QUERY_DATA_TIMESTAMP_DISJOINT), "Invalid data size"); + D3D11_QUERY_DATA_TIMESTAMP_DISJOINT sData; + + // D3D12 WARNING: ID3D12CommandQueue::ID3D12CommandQueue::GetTimestampFrequency: Use + // ID3D12Device::SetStablePowerstate for reliable timestamp queries [ EXECUTION WARNING #736: UNSTABLE_POWER_STATE] + sData.Disjoint = FALSE; + sData.Frequency = m_pDX12Device->GetGpuTimestampFrequency(); + + *reinterpret_cast(pData) = sData; + + return S_OK; + } + else if (desc.Query == D3D11_QUERY_TIMESTAMP) + { + R_ASSERT2(DataSize >= sizeof(UINT64), "Invalid data size"); + + auto pTimestampQuery = reinterpret_cast(pAsync); + bool bComplete = TestForFence(pTimestampQuery->GetFenceValue()) == S_OK; + + if (!bComplete && !(GetDataFlags & D3D11_ASYNC_GETDATA_DONOTFLUSH)) + { + // Ensure the command-list issuing the timestamp is executed + SubmitDirectCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, pTimestampQuery->GetFenceValue()); + FlushToFence(pTimestampQuery->GetFenceValue()); + } + + // Since we do FlushToFence if not completed, it will be completed now. + ResolveTimestamp(m_DirectCommandList, pTimestampQuery->GetQueryIndex(), pData); + + return S_OK; + } + else if (desc.Query == D3D11_QUERY_OCCLUSION) + { + R_ASSERT2(DataSize >= sizeof(UINT64), "Invalid data size"); + + auto pOcclusionQuery = reinterpret_cast(pAsync); + bool bComplete = TestForFence(pOcclusionQuery->GetFenceValue()) == S_OK; + + if (!bComplete && !(GetDataFlags & D3D11_ASYNC_GETDATA_DONOTFLUSH)) + { + // Ensure the command-list issuing the query is executed + SubmitDirectCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, pOcclusionQuery->GetFenceValue()); + FlushToFence(pOcclusionQuery->GetFenceValue()); + } + + if (bComplete) + { + ResolveOcclusion(m_DirectCommandList, pOcclusionQuery->GetQueryIndex(), pData); + } + + return (bComplete) ? S_OK : S_FALSE; + } + else // || desc.Query == D3D11_QUERY_OCCLUSION_PREDICATE + { + __debugbreak(); + } + + return S_OK; +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::SetPredication( + _In_opt_ ID3D11Predicate* pPredicate, + _In_ BOOL PredicateValue) +{ + DX12_FUNC_LOG +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::GSSetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11ShaderResourceView* const* ppShaderResourceViews) +{ + DX12_FUNC_LOG + auto& geometry = m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Geometry]; + for (UINT i = StartSlot, S = StartSlot + NumViews; i < S; ++i, ++ppShaderResourceViews) + { + CCryDX12ShaderResourceView* srv = reinterpret_cast(*ppShaderResourceViews); + if (geometry.ShaderResourceViews.Set(i, srv) && srv) + { + srv->BeginResourceStateTransition(m_DirectCommandList.get()); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::GSSetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _In_reads_opt_(NumSamplers) ID3D11SamplerState* const* ppSamplers) +{ + DX12_FUNC_LOG + auto& geometry = m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Geometry]; + for (UINT i = StartSlot, S = StartSlot + NumSamplers; i < S; ++i, ++ppSamplers) + { + geometry.SamplerState.Set(i, reinterpret_cast(*ppSamplers)); + } +} + +#include "DX12/API/DX12SwapChain.hpp" + +static void ValidateSwapChain(CCryDX12RenderTargetView& rtv) +{ +#if defined(DEBUG) + if (DX12::SwapChain* swapChain = rtv.GetDX12Resource().GetDX12SwapChain()) + { + R_ASSERT2(swapChain->GetCurrentBackBuffer().GetD3D12Resource() == rtv.GetDX12Resource().GetD3D12Resource(), "invalid swap chain buffer"); + } +#endif +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::OMSetRenderTargets( + _In_range_(0, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11RenderTargetView* const* ppRenderTargetViews, + _In_opt_ ID3D11DepthStencilView* pDepthStencilView) +{ + DX12_FUNC_LOG + auto& outputMerger = m_PipelineState[DX12::CommandModeGraphics].OutputMerger; + + outputMerger.NumRenderTargets.Set(NumViews); + for (UINT i = 0; i < NumViews; ++i) + { + CCryDX12RenderTargetView* rtv = reinterpret_cast(ppRenderTargetViews[i]); + if (outputMerger.RenderTargetViews.Set(i, rtv)) + { + if (!rtv) + { + outputMerger.RTVFormats.Set(i, DXGI_FORMAT_UNKNOWN); + continue; + } + + ValidateSwapChain(*rtv); + + DX12_LOG("Setting render target: %p (%d)", rtv, i); + + // TODO: this might not be the earliest moment when it is known that the resource is used as render-target + D3D11_RENDER_TARGET_VIEW_DESC desc; + rtv->GetDesc(&desc); + rtv->BeginResourceStateTransition(m_DirectCommandList.get()); + + outputMerger.RTVFormats.Set(i, desc.Format); + } + } + + for (UINT i = NumViews; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) + { + outputMerger.RenderTargetViews.Set(i, nullptr); + outputMerger.RTVFormats.Set(i, DXGI_FORMAT_UNKNOWN); + } + + { + CCryDX12DepthStencilView* dsv = reinterpret_cast(pDepthStencilView); + if (outputMerger.DepthStencilView.Set(dsv)) + { + if (!dsv) + { + outputMerger.DSVFormat.Set(DXGI_FORMAT_UNKNOWN); + return; + } + + DX12_LOG("Setting depth stencil view: %p", dsv); + + // TODO: this might not be the earliest moment when it is known that the resource is used as depth-stencil + D3D11_DEPTH_STENCIL_VIEW_DESC desc; + dsv->GetDesc(&desc); + dsv->BeginResourceStateTransition(m_DirectCommandList.get()); + + outputMerger.DSVFormat.Set(desc.Format); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews( + _In_ UINT NumRTVs, + _In_reads_opt_(NumRTVs) ID3D11RenderTargetView* const* ppRenderTargetViews, + _In_opt_ ID3D11DepthStencilView* pDepthStencilView, + _In_range_(0, D3D11_1_UAV_SLOT_COUNT - 1) UINT UAVStartSlot, + _In_ UINT NumUAVs, + _In_reads_opt_(NumUAVs) ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, + _In_reads_opt_(NumUAVs) const UINT* pUAVInitialCounts) +{ + DX12_FUNC_LOG + if (NumRTVs > 0 && NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) + { + DX12_NOT_IMPLEMENTED //@TODO: Only the Unordered Access View portion of this function is implemented. + } + + auto& graphicsStage = m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Pixel]; + for (UINT i = UAVStartSlot, S = UAVStartSlot + NumUAVs; i < S; ++i, ++ppUnorderedAccessViews) + { + CCryDX12UnorderedAccessView* uav = reinterpret_cast(*ppUnorderedAccessViews); + if (graphicsStage.UnorderedAccessViews.Set(i, uav) && uav) + { + uav->BeginResourceStateTransition(m_DirectCommandList.get()); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::OMSetBlendState( + _In_opt_ ID3D11BlendState* pBlendState, + _In_opt_ const FLOAT BlendFactor[4], + _In_ UINT SampleMask) +{ + DX12_FUNC_LOG + + auto& outputMerger = m_PipelineState[DX12::CommandModeGraphics].OutputMerger; + outputMerger.BlendState.Set(reinterpret_cast(pBlendState)); + outputMerger.SampleMask.Set(SampleMask); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::OMSetDepthStencilState( + _In_opt_ ID3D11DepthStencilState* pDepthStencilState, + _In_ UINT StencilRef) +{ + DX12_FUNC_LOG + + auto& state = m_PipelineState[DX12::CommandModeGraphics]; + state.Rasterizer.DepthStencilState.Set(reinterpret_cast(pDepthStencilState)); + state.OutputMerger.StencilRef.Set(StencilRef); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::SOSetTargets( + _In_range_(0, D3D11_SO_BUFFER_SLOT_COUNT) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer* const* ppSOTargets, + _In_reads_opt_(NumBuffers) const UINT* pOffsets) +{ + DX12_FUNC_LOG +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DrawAuto() +{ + DX12_FUNC_LOG +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DrawIndexedInstancedIndirect( + _In_ ID3D11Buffer* pBufferForArgs, + _In_ UINT AlignedByteOffsetForArgs) +{ + DX12_FUNC_LOG + DX12_ASSERT(false, "unimplemented"); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DrawInstancedIndirect( + _In_ ID3D11Buffer* pBufferForArgs, + _In_ UINT AlignedByteOffsetForArgs) +{ + DX12_FUNC_LOG + DX12_ASSERT(false, "unimplemented"); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::Dispatch( + _In_ UINT ThreadGroupCountX, + _In_ UINT ThreadGroupCountY, + _In_ UINT ThreadGroupCountZ) +{ + DX12_FUNC_LOG + + SubmitCopyCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + + if (PrepareComputeState()) + { + m_DirectCommandList->Dispatch(ThreadGroupCountX, ThreadGroupCountY, ThreadGroupCountZ); +#ifdef DEBUG_BUILD + m_PipelineState[DX12::CommandModeCompute].DebugPrint(); +#endif + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DispatchIndirect( + _In_ ID3D11Buffer* pBufferForArgs, + _In_ UINT AlignedByteOffsetForArgs) +{ + DX12_FUNC_LOG + DX12_ASSERT(false, "unimplemented"); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::RSSetState( + _In_opt_ ID3D11RasterizerState* pRasterizerState) +{ + DX12_FUNC_LOG + + auto& rasterizer = m_PipelineState[DX12::CommandModeGraphics].Rasterizer; + rasterizer.RasterizerState.Set(reinterpret_cast(pRasterizerState)); + if (pRasterizerState) + { + const D3D11_RASTERIZER_DESC& d3d11Desc = rasterizer.RasterizerState->GetD3D11RasterizerDesc(); + rasterizer.ScissorEnabled.Set(d3d11Desc.ScissorEnable); + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::RSSetViewports( + _In_range_(0, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) UINT NumViewports, + _In_reads_opt_(NumViewports) const D3D11_VIEWPORT* pViewports) +{ + DX12_FUNC_LOG + + auto& rasterizer = m_PipelineState[DX12::CommandModeGraphics].Rasterizer; + rasterizer.NumViewports.Set(NumViewports); + if (NumViewports) + { + for (UINT i = 0; i < NumViewports; ++i, ++pViewports) + { + rasterizer.Viewports.Set(i, *pViewports); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::RSSetScissorRects( + _In_range_(0, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) UINT NumRects, + _In_reads_opt_(NumRects) const D3D11_RECT* pRects) +{ + DX12_FUNC_LOG + + auto& rasterizer = m_PipelineState[DX12::CommandModeGraphics].Rasterizer; + rasterizer.NumScissors.Set(NumRects); + if (NumRects) + { + for (UINT i = 0; i < NumRects; ++i, ++pRects) + { + rasterizer.Scissors.Set(i, *pRects); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CopySubresourceRegion( + _In_ ID3D11Resource* pDstResource, + _In_ UINT DstSubresource, + _In_ UINT DstX, + _In_ UINT DstY, + _In_ UINT DstZ, + _In_ ID3D11Resource* pSrcResource, + _In_ UINT SrcSubresource, + _In_opt_ const D3D11_BOX* pSrcBox) +{ + DX12_FUNC_LOG + + CopySubresourceRegion1( + pDstResource, + DstSubresource, + DstX, + DstY, + DstZ, + pSrcResource, + SrcSubresource, + pSrcBox, + 0); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CopyResource( + _In_ ID3D11Resource* pDstResource, + _In_ ID3D11Resource* pSrcResource) +{ + DX12_FUNC_LOG + + CopyResource1( + pDstResource, + pSrcResource, + 0); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::UploadResource( + _In_ ICryDX12Resource* pDstResource, + _In_ const D3D11_SUBRESOURCE_DATA* pInitialData, + _In_ size_t numInitialData) +{ + DX12_FUNC_LOG + + + ID3D12Resource* pDstResource12 = pDstResource->GetD3D12Resource(); + DX12::Resource& dstResource = pDstResource->GetDX12Resource(); + DX12::Resource::InitialData* id = dstResource.GetOrCreateInitialData(); + + + D3D12_RESOURCE_DESC desc = dstResource.GetDesc(); + const UINT maxSubResource = 64; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT layouts[maxSubResource]; + UINT nRows[maxSubResource]; + UINT64 rowSizes[maxSubResource]; + R_ASSERT(numInitialData <= maxSubResource); + + dstResource.GetDevice()->GetD3D12Device()->GetCopyableFootprints(&desc, 0, numInitialData, 0, layouts, nRows, rowSizes, &id->m_UploadSize); + + id->m_SubResourceData.resize(numInitialData); + + //Manually compute id->m_Size. This number is used to figure out the size of the intermediate CPU/GPU buffer into which the texture data is copied. + //The reason for doing this manually is because pTotalBytes (set by GetCopyableFootprints) is not completely accurate. For some reason it + //seems like it doesnt take into account the 256 byte alignment padding of the last mip of a texture. Hence manually calculating the size + //using the pNumRows (in this case nRows) and pRowSizeInBytes (in this case rowSizes). + UINT64 totalBufferSize = 0; + + for (UINT i = 0; i < numInitialData; ++i) + { + D3D12_SUBRESOURCE_DATA initialDestData; + + initialDestData.RowPitch = pInitialData[i].SysMemPitch; + initialDestData.SlicePitch = pInitialData[i].SysMemSlicePitch; + + UINT64 slicePitchSize = 0; + slicePitchSize = pInitialData[i].SysMemSlicePitch * desc.DepthOrArraySize; // Exact size of the texture data. No padding. + //TODO: pInitialData[i].SysMemSlicePitch can be 0 if the texture loading code doesnt set it. Fix this. For now we just query the GPU for the size (which is padded and wastes memory). + if (slicePitchSize == 0) + { + slicePitchSize = dstResource.GetRequiredUploadSize(i, 1); + } + + BYTE* destMemory = new uint8_t[slicePitchSize]; + UINT gpuSlicePitchSize = layouts[i].Footprint.RowPitch * nRows[i]; + D3D12_MEMCPY_DEST destData = { destMemory, layouts[i].Footprint.RowPitch, gpuSlicePitchSize }; + + const BYTE* pSrc = static_cast (pInitialData[i].pSysMem); + + for (UINT z = 0; z < layouts[i].Footprint.Depth; ++z) + { + BYTE* pDestSlice = static_cast (destData.pData) + pInitialData[i].SysMemSlicePitch * z; + const BYTE* pSrcSlice = pSrc + pInitialData[i].SysMemSlicePitch * z; + for (UINT y = 0; y < nRows[i]; ++y) + { + memcpy(pDestSlice + pInitialData[i].SysMemPitch * y, + pSrcSlice + pInitialData[i].SysMemPitch * y, + pInitialData[i].SysMemPitch); + } + } + initialDestData.pData = destMemory; + id->m_SubResourceData[i] = initialDestData; + totalBufferSize += gpuSlicePitchSize; + } + id->m_Size = totalBufferSize; + UploadResource(&dstResource, id); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::UploadResource( + _In_ DX12::Resource* pDstResource, + _In_ const DX12::Resource::InitialData* pSrcData) +{ + DX12_FUNC_LOG + + // TODO: This needs to be thread-safe + // pDstResource->InitDeferred(m_pGraphicsCmdList); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::UpdateSubresource( + _In_ ID3D11Resource* pDstResource, + _In_ UINT DstSubresource, + _In_opt_ const D3D11_BOX* pDstBox, + _In_ const void* pSrcData, + _In_ UINT SrcRowPitch, + _In_ UINT SrcDepthPitch) +{ + DX12_FUNC_LOG + + UpdateSubresource1( + pDstResource, + DstSubresource, + pDstBox, + pSrcData, + SrcRowPitch, + SrcDepthPitch, + 0); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CopyStructureCount( + _In_ ID3D11Buffer* pDstBuffer, + _In_ UINT DstAlignedByteOffset, + _In_ ID3D11UnorderedAccessView* pSrcView) +{ + DX12_FUNC_LOG +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::ClearRenderTargetView( + _In_ ID3D11RenderTargetView* pRenderTargetView, + _In_ const FLOAT ColorRGBA[4]) +{ + DX12_FUNC_LOG + + DX12::ResourceView* view = DX12_EXTRACT_DX12VIEW(pRenderTargetView); + CCryDX12RenderTargetView* rtv = reinterpret_cast(pRenderTargetView); + DX12_LOG("Clearing render target view: %p %s", pRenderTargetView, rtv->GetResourceName().c_str()); + + ValidateSwapChain(*rtv); + m_DirectCommandList->ClearRenderTargetView(*view, ColorRGBA); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::ClearUnorderedAccessViewUint( + _In_ ID3D11UnorderedAccessView* pUnorderedAccessView, + _In_ const UINT Values[4]) +{ + DX12_FUNC_LOG + + DX12::ResourceView* view = DX12_EXTRACT_DX12VIEW(pUnorderedAccessView); + CCryDX12UnorderedAccessView* uav = reinterpret_cast(pUnorderedAccessView); + DX12_LOG("Clearing unordered access view [int]: %p %s", pUnorderedAccessView, uav->GetResourceName().c_str()); + + m_DirectCommandList->ClearUnorderedAccessView(*view, Values); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::ClearUnorderedAccessViewFloat( + _In_ ID3D11UnorderedAccessView* pUnorderedAccessView, + _In_ const FLOAT Values[4]) +{ + DX12_FUNC_LOG + + DX12::ResourceView* view = DX12_EXTRACT_DX12VIEW(pUnorderedAccessView); + CCryDX12UnorderedAccessView* uav = reinterpret_cast(pUnorderedAccessView); + DX12_LOG("Clearing unordered access view [float]: %p %s", pUnorderedAccessView, uav->GetResourceName().c_str()); + + m_DirectCommandList->ClearUnorderedAccessView(*view, Values); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::ClearDepthStencilView( + _In_ ID3D11DepthStencilView* pDepthStencilView, + _In_ UINT ClearFlags, // DX11 and DX12 clear flags are identical + _In_ FLOAT Depth, + _In_ UINT8 Stencil) +{ + DX12_FUNC_LOG + + DX12::ResourceView* view = DX12_EXTRACT_DX12VIEW(pDepthStencilView); + CCryDX12DepthStencilView* dsv = reinterpret_cast(pDepthStencilView); + DX12_LOG("Clearing depth stencil view: %p %s", pDepthStencilView, dsv->GetResourceName().c_str()); + + m_DirectCommandList->ClearDepthStencilView(*view, D3D12_CLEAR_FLAGS(ClearFlags), Depth, Stencil); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::GenerateMips( + _In_ ID3D11ShaderResourceView* pShaderResourceView) +{ + DX12_FUNC_LOG +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::SetResourceMinLOD( + _In_ ID3D11Resource* pResource, + FLOAT MinLOD) +{ + DX12_FUNC_LOG +} + +FLOAT STDMETHODCALLTYPE CCryDX12DeviceContext::GetResourceMinLOD( + _In_ ID3D11Resource* pResource) +{ + DX12_FUNC_LOG + return 0.0f; +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::ResolveSubresource( + _In_ ID3D11Resource* pDstResource, + _In_ UINT DstSubresource, + _In_ ID3D11Resource* pSrcResource, + _In_ UINT SrcSubresource, + _In_ DXGI_FORMAT Format) +{ + DX12_FUNC_LOG +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::HSSetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11ShaderResourceView* const* ppShaderResourceViews) +{ + DX12_FUNC_LOG + for (UINT i = StartSlot, S = StartSlot + NumViews; i < S; ++i, ++ppShaderResourceViews) + { + CCryDX12ShaderResourceView* srv = reinterpret_cast(*ppShaderResourceViews); + if (m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Hull].ShaderResourceViews.Set(i, srv) && srv) + { + srv->BeginResourceStateTransition(m_DirectCommandList.get()); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::HSSetShader( + _In_opt_ ID3D11HullShader* pHullShader, + _In_reads_opt_(NumClassInstances) ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances) +{ + DX12_FUNC_LOG + m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Hull].Shader.Set(reinterpret_cast(pHullShader)); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::HSSetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _In_reads_opt_(NumSamplers) ID3D11SamplerState* const* ppSamplers) +{ + DX12_FUNC_LOG + for (UINT i = StartSlot, S = StartSlot + NumSamplers; i < S; ++i, ++ppSamplers) + { + m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Hull].SamplerState.Set(i, reinterpret_cast(*ppSamplers)); + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::HSSetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer* const* ppConstantBuffers) +{ + HSSetConstantBuffers1(StartSlot, NumBuffers, ppConstantBuffers, NULL, NULL); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DSSetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11ShaderResourceView* const* ppShaderResourceViews) +{ + DX12_FUNC_LOG + for (UINT i = StartSlot, S = StartSlot + NumViews; i < S; ++i, ++ppShaderResourceViews) + { + CCryDX12ShaderResourceView* srv = reinterpret_cast(*ppShaderResourceViews); + if (m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Domain].ShaderResourceViews.Set(i, srv) && srv) + { + srv->BeginResourceStateTransition(m_DirectCommandList.get()); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DSSetShader( + _In_opt_ ID3D11DomainShader* pDomainShader, + _In_reads_opt_(NumClassInstances) ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances) +{ + DX12_FUNC_LOG + m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Domain].Shader.Set(reinterpret_cast(pDomainShader)); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DSSetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _In_reads_opt_(NumSamplers) ID3D11SamplerState* const* ppSamplers) +{ + DX12_FUNC_LOG + for (UINT i = StartSlot, S = StartSlot + NumSamplers; i < S; ++i, ++ppSamplers) + { + m_PipelineState[DX12::CommandModeGraphics].Stages[DX12::ESS_Domain].SamplerState.Set(i, reinterpret_cast(*ppSamplers)); + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DSSetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer* const* ppConstantBuffers) +{ + DSSetConstantBuffers1(StartSlot, NumBuffers, ppConstantBuffers, NULL, NULL); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CSSetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11ShaderResourceView* const* ppShaderResourceViews) +{ + DX12_FUNC_LOG + auto& compute = m_PipelineState[DX12::CommandModeCompute].Stages[DX12::ESS_Compute]; + for (UINT i = StartSlot, S = StartSlot + NumViews; i < S; ++i, ++ppShaderResourceViews) + { + CCryDX12ShaderResourceView* srv = reinterpret_cast(*ppShaderResourceViews); + if (compute.ShaderResourceViews.Set(i, srv) && srv) + { + srv->BeginResourceStateTransition(m_DirectCommandList.get()); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CSSetUnorderedAccessViews( + _In_range_(0, D3D11_1_UAV_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_1_UAV_SLOT_COUNT - StartSlot) UINT NumUAVs, + _In_reads_opt_(NumUAVs) ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, + _In_reads_opt_(NumUAVs) const UINT* pUAVInitialCounts) +{ + DX12_FUNC_LOG + auto& compute = m_PipelineState[DX12::CommandModeCompute].Stages[DX12::ESS_Compute]; + for (UINT i = StartSlot, S = StartSlot + NumUAVs; i < S; ++i, ++ppUnorderedAccessViews) + { + CCryDX12UnorderedAccessView* uav = reinterpret_cast(*ppUnorderedAccessViews); + if (compute.UnorderedAccessViews.Set(i, uav) && uav) + { + uav->BeginResourceStateTransition(m_DirectCommandList.get()); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CSSetShader( + _In_opt_ ID3D11ComputeShader* pComputeShader, + _In_reads_opt_(NumClassInstances) ID3D11ClassInstance* const* ppClassInstances, + UINT NumClassInstances) +{ + DX12_FUNC_LOG + m_PipelineState[DX12::CommandModeCompute].Stages[DX12::ESS_Compute].Shader.Set(reinterpret_cast(pComputeShader)); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CSSetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _In_reads_opt_(NumSamplers) ID3D11SamplerState* const* ppSamplers) +{ + DX12_FUNC_LOG + for (UINT i = StartSlot, S = StartSlot + NumSamplers; i < S; ++i, ++ppSamplers) + { + m_PipelineState[DX12::CommandModeCompute].Stages[DX12::ESS_Compute].SamplerState.Set(i, reinterpret_cast(*ppSamplers)); + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CSSetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer* const* ppConstantBuffers) +{ + CSSetConstantBuffers1(StartSlot, NumBuffers, ppConstantBuffers, NULL, NULL); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::VSGetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer** ppConstantBuffers) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::PSGetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11ShaderResourceView** ppShaderResourceViews) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::PSGetShader( + _Out_ ID3D11PixelShader** ppPixelShader, + _Out_writes_opt_(*pNumClassInstances) ID3D11ClassInstance** ppClassInstances, + _Inout_opt_ UINT* pNumClassInstances) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::PSGetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _Out_writes_opt_(NumSamplers) ID3D11SamplerState** ppSamplers) +{ + DX12_FUNC_LOG +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::VSGetShader( + _Out_ ID3D11VertexShader** ppVertexShader, + _Out_writes_opt_(*pNumClassInstances) ID3D11ClassInstance** ppClassInstances, + _Inout_opt_ UINT* pNumClassInstances) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::PSGetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer** ppConstantBuffers) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::IAGetInputLayout( + _Out_ ID3D11InputLayout** ppInputLayout) +{ + DX12_FUNC_LOG + *ppInputLayout = m_PipelineState[DX12::CommandModeGraphics].InputAssembler.InputLayout; + if (*ppInputLayout) + { + (*ppInputLayout)->AddRef(); + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::IAGetVertexBuffers( + _In_range_(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer** ppVertexBuffers, + _Out_writes_opt_(NumBuffers) UINT* pStrides, + _Out_writes_opt_(NumBuffers) UINT* pOffsets) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::IAGetIndexBuffer( + _Out_opt_ ID3D11Buffer** pIndexBuffer, + _Out_opt_ DXGI_FORMAT* Format, + _Out_opt_ UINT* Offset) +{ + DX12_FUNC_LOG + auto& inputAssembler = m_PipelineState[DX12::CommandModeGraphics].InputAssembler; + * pIndexBuffer = inputAssembler.IndexBuffer; + if (*pIndexBuffer) + { + (*pIndexBuffer)->AddRef(); + } + + *Format = inputAssembler.IndexBufferFormat.Get(); + *Offset = inputAssembler.IndexBufferOffset.Get(); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::GSGetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer** ppConstantBuffers) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::GSGetShader( + _Out_ ID3D11GeometryShader** ppGeometryShader, + _Out_writes_opt_(*pNumClassInstances) ID3D11ClassInstance** ppClassInstances, + _Inout_opt_ UINT* pNumClassInstances) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::IAGetPrimitiveTopology( + _Out_ D3D11_PRIMITIVE_TOPOLOGY* pTopology) +{ + DX12_FUNC_LOG + *pTopology = m_PipelineState[DX12::CommandModeGraphics].InputAssembler.PrimitiveTopology.Get(); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::VSGetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11ShaderResourceView** ppShaderResourceViews) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::VSGetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _Out_writes_opt_(NumSamplers) ID3D11SamplerState** ppSamplers) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::GetPredication( + _Out_opt_ ID3D11Predicate** ppPredicate, + _Out_opt_ BOOL* pPredicateValue) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::GSGetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11ShaderResourceView** ppShaderResourceViews) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::GSGetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _Out_writes_opt_(NumSamplers) ID3D11SamplerState** ppSamplers) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::OMGetRenderTargets( + _In_range_(0, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11RenderTargetView** ppRenderTargetViews, + _Out_opt_ ID3D11DepthStencilView** ppDepthStencilView) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::OMGetRenderTargetsAndUnorderedAccessViews( + _In_range_(0, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT) UINT NumRTVs, + _Out_writes_opt_(NumRTVs) ID3D11RenderTargetView** ppRenderTargetViews, + _Out_opt_ ID3D11DepthStencilView** ppDepthStencilView, + _In_range_(0, D3D11_PS_CS_UAV_REGISTER_COUNT - 1) UINT UAVStartSlot, + _In_range_(0, D3D11_PS_CS_UAV_REGISTER_COUNT - UAVStartSlot) UINT NumUAVs, + _Out_writes_opt_(NumUAVs) ID3D11UnorderedAccessView** ppUnorderedAccessViews) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::OMGetBlendState( + _Out_opt_ ID3D11BlendState** ppBlendState, + _Out_opt_ FLOAT BlendFactor[4], + _Out_opt_ UINT* pSampleMask) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::OMGetDepthStencilState( + _Out_opt_ ID3D11DepthStencilState** ppDepthStencilState, + _Out_opt_ UINT* pStencilRef) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::SOGetTargets( + _In_range_(0, D3D11_SO_BUFFER_SLOT_COUNT) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer** ppSOTargets) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::RSGetState( + _Out_ ID3D11RasterizerState** ppRasterizerState) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::RSGetViewports( + _Inout_ UINT* pNumViewports, + _Out_writes_opt_(*pNumViewports) D3D11_VIEWPORT* pViewports) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::RSGetScissorRects( + _Inout_ UINT* pNumRects, + _Out_writes_opt_(*pNumRects) D3D11_RECT* pRects) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::HSGetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11ShaderResourceView** ppShaderResourceViews) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::HSGetShader( + _Out_ ID3D11HullShader** ppHullShader, + _Out_writes_opt_(*pNumClassInstances) ID3D11ClassInstance** ppClassInstances, + _Inout_opt_ UINT* pNumClassInstances) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::HSGetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _Out_writes_opt_(NumSamplers) ID3D11SamplerState** ppSamplers) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::HSGetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer** ppConstantBuffers) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DSGetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11ShaderResourceView** ppShaderResourceViews) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DSGetShader( + _Out_ ID3D11DomainShader** ppDomainShader, + _Out_writes_opt_(*pNumClassInstances) ID3D11ClassInstance** ppClassInstances, + _Inout_opt_ UINT* pNumClassInstances) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DSGetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _Out_writes_opt_(NumSamplers) ID3D11SamplerState** ppSamplers) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::DSGetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer** ppConstantBuffers) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CSGetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11ShaderResourceView** ppShaderResourceViews) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CSGetUnorderedAccessViews( + _In_range_(0, D3D11_PS_CS_UAV_REGISTER_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_PS_CS_UAV_REGISTER_COUNT - StartSlot) UINT NumUAVs, + _Out_writes_opt_(NumUAVs) ID3D11UnorderedAccessView** ppUnorderedAccessViews) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CSGetShader( + _Out_ ID3D11ComputeShader** ppComputeShader, + _Out_writes_opt_(*pNumClassInstances) ID3D11ClassInstance** ppClassInstances, + _Inout_opt_ UINT* pNumClassInstances) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CSGetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _Out_writes_opt_(NumSamplers) ID3D11SamplerState** ppSamplers) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CSGetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer** ppConstantBuffers) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::ClearState() +{ + DX12_FUNC_LOG + + IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED); + + ResetCachedState(); + + CSSetShader(NULL, NULL, 0); + DSSetShader(NULL, NULL, 0); + GSSetShader(NULL, NULL, 0); + PSSetShader(NULL, NULL, 0); + HSSetShader(NULL, NULL, 0); + VSSetShader(NULL, NULL, 0); + + RSSetViewports(0, NULL); + RSSetScissorRects(0, NULL); + + OMSetRenderTargets(0, NULL, NULL); + + OMSetBlendState(NULL, NULL, 0); + OMSetDepthStencilState(NULL, 0); + + SubmitAllCommands(true); + WaitForIdle(); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::Flush() +{ + DX12_FUNC_LOG + + SubmitAllCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, m_CmdFenceSet.GetCurrentValues()); +} + +D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE CCryDX12DeviceContext::GetType() +{ + DX12_FUNC_LOG + return D3D11_DEVICE_CONTEXT_IMMEDIATE; +} + +UINT STDMETHODCALLTYPE CCryDX12DeviceContext::GetContextFlags() +{ + DX12_FUNC_LOG + return 0; +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::ExecuteCommandList( + _In_ ID3D11CommandList* pCommandList, + _In_ BOOL RestoreContextState) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +HRESULT STDMETHODCALLTYPE CCryDX12DeviceContext::FinishCommandList( + BOOL RestoreDeferredContextState, + _Out_opt_ ID3D11CommandList** ppCommandList) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED + return E_FAIL; +} + +#pragma endregion + +#pragma region /* D3D 11.1 specific functions */ + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CopySubresourceRegion1( + _In_ ID3D11Resource* pDstResource, + _In_ UINT DstSubresource, + _In_ UINT DstX, + _In_ UINT DstY, + _In_ UINT DstZ, + _In_ ID3D11Resource* pSrcResource, + _In_ UINT SrcSubresource, + _In_opt_ const D3D11_BOX* pSrcBox, + _In_ UINT CopyFlags) +{ + DX12_FUNC_LOG + + ICryDX12Resource* dstDX12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pDstResource); + ICryDX12Resource* srcDX12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pSrcResource); + DX12::Resource& dstResource = dstDX12Resource->GetDX12Resource(); + DX12::Resource& srcResource = srcDX12Resource->GetDX12Resource(); + + // TODO: copy command on the swap chain are special (can't execute on any other queue), make an API for that + const bool bDirect = !m_bInCopyRegion; + + DX12::CommandListPool& rCmdListPool = bDirect ? m_DirectListPool : m_CopyListPool; + DX12::CommandList* pCmdList = bDirect ? m_DirectCommandList : m_CopyCommandList; + + // TODO: move into the command-list function + UINT64 maxFenceValues[CMDQUEUE_NUM]; + switch (CopyFlags) + { + case D3D11_COPY_NO_OVERWRITE: + // If the resource is currently used, the flag lied! + R_ASSERT2(!dstResource.IsUsed(rCmdListPool), "Destination resource is in use for non-discard copy!"); + + SubmitAllCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, + srcResource.GetFenceValues(CMDTYPE_WRITE), + rCmdListPool.GetFenceID()); + break; + default: + SubmitAllCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, DX12::MaxFenceValues( + srcResource.GetFenceValues(CMDTYPE_WRITE), + dstResource.GetFenceValues(CMDTYPE_ANY), + maxFenceValues), + rCmdListPool.GetFenceID()); + + // Block the GPU-thread until the resource is safe to be updated (unlike Map() we stage the copy and don't need to block the CPU) + break; + } + + D3D12_BOX box; + if (pSrcBox) + { + box.top = pSrcBox->top; + box.bottom = pSrcBox->bottom; + box.left = pSrcBox->left; + box.right = pSrcBox->right; + box.front = pSrcBox->front; + box.back = pSrcBox->back; + } + + // TODO: copy from active render-target should be more elegant + if (m_DirectCommandList->IsUsedByOutputViews(srcResource) || + m_DirectCommandList->IsUsedByOutputViews(dstResource)) + { + // Make the render-targets rebind, so the resource-barrier is closed + m_PipelineState[DX12::CommandModeGraphics].m_StateFlags |= EPSPB_OutputResources; + } + + R_ASSERT2(dstResource.GetDX12SwapChain() == nullptr, "Can't copy to swap chain buffer"); + pCmdList->CopySubresource(dstResource, DstSubresource, DstX, DstY, DstZ, srcResource, SrcSubresource, pSrcBox ? &box : NULL); + + if (DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC) + { + if (!bDirect) + { + SubmitCopyCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + } + else + { + SubmitDirectCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::CopyResource1( + _In_ ID3D11Resource* pDstResource, + _In_ ID3D11Resource* pSrcResource, + _In_ UINT CopyFlags) +{ + DX12_FUNC_LOG + + + ICryDX12Resource* dstDX12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pDstResource); + ICryDX12Resource* srcDX12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pSrcResource); + DX12::Resource& dstResource = dstDX12Resource->GetDX12Resource(); + DX12::Resource& srcResource = srcDX12Resource->GetDX12Resource(); + + const bool bDirect = !m_bInCopyRegion; + DX12::CommandListPool& rCmdListPool = bDirect ? m_DirectListPool : m_CopyListPool; + DX12::CommandList* pCmdList = bDirect ? m_DirectCommandList : m_CopyCommandList; + + // TODO: move into the command-list function + UINT64 maxFenceValues[CMDQUEUE_NUM]; + switch (CopyFlags) + { + case D3D11_COPY_NO_OVERWRITE: + // If the resource is currently used, the flag lied! + R_ASSERT2(!dstResource.IsUsed(rCmdListPool), "Destination resource is in use for non-discard copy!"); + SubmitAllCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, + srcResource.GetFenceValues(CMDTYPE_WRITE), + rCmdListPool.GetFenceID()); + break; + default: + SubmitAllCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, DX12::MaxFenceValues( + srcResource.GetFenceValues(CMDTYPE_WRITE), + dstResource.GetFenceValues(CMDTYPE_ANY), + maxFenceValues), + rCmdListPool.GetFenceID()); + + // Block the GPU-thread until the resource is safe to be updated (unlike Map() we stage the update and don't need to block the CPU) + break; + } + + // TODO: copy from active render-target should be more elegant + if (m_DirectCommandList->IsUsedByOutputViews(srcResource) || + m_DirectCommandList->IsUsedByOutputViews(dstResource)) + { + // Make the render-targets rebind, so the resource-barrier is closed + m_PipelineState[DX12::CommandModeGraphics].m_StateFlags |= EPSPB_OutputResources; + } + + R_ASSERT2(dstResource.GetDX12SwapChain() == nullptr, "Can't copy to swap chain buffer"); + pCmdList->CopyResource(dstResource, srcResource); + if (DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC) + { + if (!bDirect) + { + SubmitCopyCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + } + else + { + SubmitDirectCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + } + } +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::UpdateSubresource1( + _In_ ID3D11Resource* pDstResource, + _In_ UINT DstSubresource, + _In_opt_ const D3D11_BOX* pDstBox, + _In_ const void* pSrcData, + _In_ UINT SrcRowPitch, + _In_ UINT SrcDepthPitch, + _In_ UINT CopyFlags) +{ + DX12_FUNC_LOG + + + ICryDX12Resource* dx12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pDstResource); + DX12::Resource& resource = dx12Resource->GetDX12Resource(); + + // TODO: copy command on the swap chain are special (can't execute on any other queue), make an API for that + const bool bDirect = !m_bInCopyRegion; + + DX12::CommandListPool& rCmdListPool = bDirect ? m_DirectListPool : m_CopyListPool; + DX12::CommandList* pCmdList = bDirect ? m_DirectCommandList : m_CopyCommandList; + + // TODO: move into the command-list function + switch (CopyFlags) + { + case D3D11_COPY_NO_OVERWRITE: + // If the resource is currently used, the flag lied! + R_ASSERT2(!resource.IsUsed(rCmdListPool), "Destination resource is in use for non-discard copy!"); + break; + default: + SubmitAllCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, resource.GetFenceValues(CMDTYPE_ANY), rCmdListPool.GetFenceID()); + + // Block the GPU-thread until the resource is safe to be updated (unlike Map() we stage the update and don't need to block the CPU) + break; + } + + D3D12_BOX box; + if (pDstBox) + { + box.top = pDstBox->top; + box.bottom = pDstBox->bottom; + box.left = pDstBox->left; + box.right = pDstBox->right; + box.front = pDstBox->front; + box.back = pDstBox->back; + } + + // TODO: copy from active render-target should be more elegant + if (m_DirectCommandList->IsUsedByOutputViews(resource)) + { + // Make the render-targets rebind, so the resource-barrier is closed + m_PipelineState[DX12::CommandModeGraphics].m_StateFlags |= EPSPB_OutputResources; + } + + R_ASSERT2(resource.GetDX12SwapChain() == nullptr, "Can't copy to swap chain buffer"); + pCmdList->UpdateSubresourceRegion(resource, DstSubresource, pDstBox ? &box : NULL, pSrcData, SrcRowPitch, SrcDepthPitch); + + if (DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC) + { + if (!bDirect) + { + SubmitCopyCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + } + else + { + SubmitDirectCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); + } + } +} + +void CCryDX12DeviceContext::DiscardResource(ID3D11Resource* pResource) +{ + DX12_FUNC_LOG + + ICryDX12Resource* dx12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pResource); + DX12::Resource& resource = dx12Resource->GetDX12Resource(); + + // Ensure the command-list using the resource is executed + SubmitDirectCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC, + resource.GetFenceValue(CMDQUEUE_GRAPHICS, CMDTYPE_ANY) + ); + + m_CopyCommandList->DiscardResource(resource, nullptr); + SubmitCopyCommands(DX12_SUBMISSION_MODE == DX12_SUBMISSION_SYNC); +} + +void CCryDX12DeviceContext::DiscardView(ID3D11View* pResourceView) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void CCryDX12DeviceContext::VSSetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers, const UINT* pFirstConstant, const UINT* pNumConstants) +{ + DX12_FUNC_LOG + SetConstantBuffers1(DX12::ESS_Vertex, StartSlot, NumBuffers, ppConstantBuffers, pFirstConstant, pNumConstants, DX12::CommandModeGraphics); +} + +void CCryDX12DeviceContext::HSSetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers, const UINT* pFirstConstant, const UINT* pNumConstants) +{ + DX12_FUNC_LOG + SetConstantBuffers1(DX12::ESS_Hull, StartSlot, NumBuffers, ppConstantBuffers, pFirstConstant, pNumConstants, DX12::CommandModeGraphics); +} + +void CCryDX12DeviceContext::DSSetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers, const UINT* pFirstConstant, const UINT* pNumConstants) +{ + DX12_FUNC_LOG + SetConstantBuffers1(DX12::ESS_Domain, StartSlot, NumBuffers, ppConstantBuffers, pFirstConstant, pNumConstants, DX12::CommandModeGraphics); +} + +void CCryDX12DeviceContext::GSSetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers, const UINT* pFirstConstant, const UINT* pNumConstants) +{ + DX12_FUNC_LOG + SetConstantBuffers1(DX12::ESS_Geometry, StartSlot, NumBuffers, ppConstantBuffers, pFirstConstant, pNumConstants, DX12::CommandModeGraphics); +} + +void CCryDX12DeviceContext::PSSetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers, const UINT* pFirstConstant, const UINT* pNumConstants) +{ + DX12_FUNC_LOG + SetConstantBuffers1(DX12::ESS_Pixel, StartSlot, NumBuffers, ppConstantBuffers, pFirstConstant, pNumConstants, DX12::CommandModeGraphics); +} + +void CCryDX12DeviceContext::CSSetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers, const UINT* pFirstConstant, const UINT* pNumConstants) +{ + DX12_FUNC_LOG + SetConstantBuffers1(DX12::ESS_Compute, StartSlot, NumBuffers, ppConstantBuffers, pFirstConstant, pNumConstants, DX12::CommandModeCompute); +} + +void CCryDX12DeviceContext::SetConstantBuffers1( + DX12::EShaderStage shaderStage, + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants, + DX12::CommandMode commandMode) +{ + auto& stage = m_PipelineState[commandMode].Stages[shaderStage]; + for (UINT i = StartSlot, S = StartSlot + NumBuffers, j = 0; i < S; ++i, ++ppConstantBuffers, ++j) + { + CCryDX12Buffer* cb = reinterpret_cast(*ppConstantBuffers); + + _range_t < UINT > bindRange; + if (pFirstConstant) + { + bindRange.start = pFirstConstant[j] * DX12::CONSTANT_BUFFER_ELEMENT_SIZE; + bindRange.end = bindRange.start + pNumConstants[j] * DX12::CONSTANT_BUFFER_ELEMENT_SIZE; + } + + stage.ConstBufferBindRange.Set(i, bindRange); + if (stage.ConstantBufferViews.Set(i, cb) && cb) + { + cb->BeginResourceStateTransition(m_DirectCommandList, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); + } + } +} + +void CCryDX12DeviceContext::VSGetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer** ppConstantBuffers, UINT* pFirstConstant, UINT* pNumConstants) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void CCryDX12DeviceContext::HSGetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer** ppConstantBuffers, UINT* pFirstConstant, UINT* pNumConstants) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void CCryDX12DeviceContext::DSGetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer** ppConstantBuffers, UINT* pFirstConstant, UINT* pNumConstants) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void CCryDX12DeviceContext::GSGetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer** ppConstantBuffers, UINT* pFirstConstant, UINT* pNumConstants) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void CCryDX12DeviceContext::PSGetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer** ppConstantBuffers, UINT* pFirstConstant, UINT* pNumConstants) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void CCryDX12DeviceContext::CSGetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer** ppConstantBuffers, UINT* pFirstConstant, UINT* pNumConstants) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void CCryDX12DeviceContext::SwapDeviceContextState(ID3DDeviceContextState* pState, ID3DDeviceContextState** ppPreviousState) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void CCryDX12DeviceContext::ClearView(ID3D11View* pView, const FLOAT Color[4], const D3D11_RECT* pRect, UINT NumRects) +{ + DX12_FUNC_LOG + DX12_LOG("Clearing view: %p", pView); + + DX12::ResourceView* view = DX12_EXTRACT_DX12VIEW(pView); + + m_DirectCommandList->ClearView(*view, Color, NumRects, pRect); +} + +void CCryDX12DeviceContext::DiscardView1(ID3D11View* pResourceView, const D3D11_RECT* pRects, UINT NumRects) +{ + DX12_FUNC_LOG + DX12_NOT_IMPLEMENTED +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::ClearRectsRenderTargetView( + _In_ ID3D11RenderTargetView* pRenderTargetView, + _In_ const FLOAT ColorRGBA[4], + _In_ UINT NumRects, + _In_reads_opt_(NumRects) const D3D11_RECT* pRects) +{ + DX12_FUNC_LOG + + DX12::ResourceView* view = DX12_EXTRACT_DX12VIEW(pRenderTargetView); + CCryDX12RenderTargetView* rtv = reinterpret_cast(pRenderTargetView); + DX12_LOG("Clearing render target view: %p %s", pRenderTargetView, rtv->GetResourceName().c_str()); + + m_DirectCommandList->ClearRenderTargetView(*view, ColorRGBA, NumRects, pRects); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::ClearRectsUnorderedAccessViewUint( + _In_ ID3D11UnorderedAccessView* pUnorderedAccessView, + _In_ const UINT Values[4], + _In_ UINT NumRects, + _In_reads_opt_(NumRects) const D3D11_RECT* pRects) +{ + DX12_FUNC_LOG + + DX12::ResourceView* view = DX12_EXTRACT_DX12VIEW(pUnorderedAccessView); + CCryDX12UnorderedAccessView* uav = reinterpret_cast(pUnorderedAccessView); + DX12_LOG("Clearing unordered access view [int]: %p %s", pUnorderedAccessView, uav->GetResourceName().c_str()); + + m_DirectCommandList->ClearUnorderedAccessView(*view, Values, NumRects, pRects); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::ClearRectsUnorderedAccessViewFloat( + _In_ ID3D11UnorderedAccessView* pUnorderedAccessView, + _In_ const FLOAT Values[4], + _In_ UINT NumRects, + _In_reads_opt_(NumRects) const D3D11_RECT* pRects) +{ + DX12_FUNC_LOG + + DX12::ResourceView* view = DX12_EXTRACT_DX12VIEW(pUnorderedAccessView); + CCryDX12UnorderedAccessView* uav = reinterpret_cast(pUnorderedAccessView); + DX12_LOG("Clearing unordered access view [float]: %p %s", pUnorderedAccessView, uav->GetResourceName().c_str()); + + m_DirectCommandList->ClearUnorderedAccessView(*view, Values, NumRects, pRects); +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::ClearRectsDepthStencilView( + _In_ ID3D11DepthStencilView* pDepthStencilView, + _In_ UINT ClearFlags, // DX11 and DX12 clear flags are identical + _In_ FLOAT Depth, + _In_ UINT8 Stencil, + _In_ UINT NumRects, + _In_reads_opt_(NumRects) const D3D11_RECT* pRects) +{ + DX12_FUNC_LOG + + DX12::ResourceView* view = DX12_EXTRACT_DX12VIEW(pDepthStencilView); + CCryDX12DepthStencilView* dsv = reinterpret_cast(pDepthStencilView); + DX12_LOG("Clearing depth stencil view: %p %s", pDepthStencilView, dsv->GetResourceName().c_str()); + + m_DirectCommandList->ClearDepthStencilView(*view, D3D12_CLEAR_FLAGS(ClearFlags), Depth, Stencil, NumRects, pRects); +} + +HRESULT STDMETHODCALLTYPE CCryDX12DeviceContext::CopyStagingResource( + _In_ ID3D11Resource* pStagingResource, + _In_ ID3D11Resource* pSourceResource, + _In_ UINT SubResource, + _In_ BOOL Upload) +{ + DX12_FUNC_LOG + + if (Upload) + { + CopySubresourceRegion1(pSourceResource, SubResource, 0, 0, 0, pStagingResource, 0, nullptr, D3D11_COPY_NO_OVERWRITE); + } + else + { + CopySubresourceRegion1(pStagingResource, 0, 0, 0, 0, pSourceResource, SubResource, nullptr, D3D11_COPY_NO_OVERWRITE); + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CCryDX12DeviceContext::MapStagingResource( + _In_ ID3D11Resource* pTextureResource, + _In_ ID3D11Resource* pStagingResource, + _In_ UINT SubResource, + _In_ BOOL Upload, + _Out_ void** ppStagingMemory, + _Out_ uint32_t* pRowPitch) +{ + DX12_FUNC_LOG + + ICryDX12Resource* dx12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pStagingResource); + DX12::Resource& rResource = dx12Resource->GetDX12Resource(); + + ICryDX12Resource* dx12TextureResource = DX12_EXTRACT_ICRYDX12RESOURCE(pTextureResource); + DX12::Resource& rTextureResource = dx12TextureResource->GetDX12Resource(); + + // If this assert trips, you may need to increase MAX_SUBRESOURCES. Just be wary of growing the stack too much. + R_ASSERT4(SubResource < MAX_SUBRESOURCES, "Too many sub resources: (sub ID %d requested, %d allowed)", std::to_string(SubResource).c_str(), std::to_string(MAX_SUBRESOURCES).c_str()); + D3D12_PLACED_SUBRESOURCE_FOOTPRINT layouts[MAX_SUBRESOURCES]; + + // From our source texture resource, get the offset and description information for all the subresources up through the one we're trying + // to map. Our staging resource will contain a buffer large enough for *all* the subresources, so we need to get the correct offset + // into this buffer. If we just get the Layout for the one SubResource, it will come back with an offset of 0, which is incorrect. + GetDevice()->GetD3D12Device()->GetCopyableFootprints(&rTextureResource.GetDesc(), 0, SubResource + 1, 0, layouts, nullptr, nullptr, nullptr); + + const D3D12_RANGE sNoRead = { 0, 0 }; // It is valid to specify the CPU won't read any data by passing a range where End is less than or equal to Begin + const D3D12_RANGE sFullRead = { 0, rResource.GetRequiredUploadSize(0, 1) }; // Our buffer only has 1 subresource, so get the full size of it to map. + + HRESULT result = rResource.GetD3D12Resource()->Map(0, Upload ? &sNoRead : &sFullRead, ppStagingMemory); + + // Map() will return a pointer to the start of our buffer. Adjust the pointer to the offset of the desired mapped subresource within the buffer. + *ppStagingMemory = *reinterpret_cast(ppStagingMemory) + layouts[SubResource].Offset; + + *pRowPitch = layouts[SubResource].Footprint.RowPitch; + + return result; +} + +void STDMETHODCALLTYPE CCryDX12DeviceContext::UnmapStagingResource( + _In_ ID3D11Resource* pStagingResource, + _In_ BOOL Upload) +{ + DX12_FUNC_LOG + + ICryDX12Resource* dx12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pStagingResource); + DX12::Resource& rResource = dx12Resource->GetDX12Resource(); + + const D3D12_RANGE sNoWrite = { 0, 0 }; // It is valid to specify the CPU didn't write any data by passing a range where End is less than or equal to Begin. + const D3D12_RANGE sFullWrite = { 0, rResource.GetRequiredUploadSize(0, 1) }; + + rResource.GetD3D12Resource()->Unmap(0, Upload ? &sFullWrite : &sNoWrite); +} + +HRESULT STDMETHODCALLTYPE CCryDX12DeviceContext::TestStagingResource( + _In_ ID3D11Resource* pStagingResource) +{ + DX12_FUNC_LOG + + ICryDX12Resource* dx12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pStagingResource); + DX12::Resource& rResource = dx12Resource->GetDX12Resource(); + + return + TestForFence(rResource.GetFenceValue(CMDQUEUE_GRAPHICS, CMDTYPE_ANY)) && + TestForFence(rResource.GetFenceValue(CMDQUEUE_COPY, CMDTYPE_ANY)); +} + +HRESULT STDMETHODCALLTYPE CCryDX12DeviceContext::WaitStagingResource( + _In_ ID3D11Resource* pStagingResource) +{ + DX12_FUNC_LOG + + ICryDX12Resource* dx12Resource = DX12_EXTRACT_ICRYDX12RESOURCE(pStagingResource); + DX12::Resource& rResource = dx12Resource->GetDX12Resource(); + + if (rResource.GetFenceValue(CMDQUEUE_GRAPHICS, CMDTYPE_WRITE) == m_DirectListPool.GetCurrentFenceValue()) + { + SubmitDirectCommands(false); + } + + if (rResource.GetFenceValue(CMDQUEUE_COPY, CMDTYPE_WRITE) == m_CopyListPool.GetCurrentFenceValue()) + { + SubmitCopyCommands(false); + } + + rResource.WaitForUnused(m_DirectListPool, CMDTYPE_ANY); + rResource.WaitForUnused(m_CopyListPool, CMDTYPE_ANY); + + return S_OK; +} + +void CCryDX12DeviceContext::ResetCachedState() +{ + m_PipelineState[DX12::CommandModeGraphics].Invalidate(); + m_PipelineState[DX12::CommandModeCompute].Invalidate(); + + m_CurrentPSO = nullptr; + m_CurrentRootSignature[DX12::CommandModeGraphics] = m_CurrentRootSignature[DX12::CommandModeCompute] = nullptr; +} + +#pragma endregion diff --git a/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceContext.hpp b/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceContext.hpp new file mode 100644 index 00000000000..4b8872c2ef9 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/Device/CCryDX12DeviceContext.hpp @@ -0,0 +1,879 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once +#ifndef __CCRYDX12DEVICECONTEXT__ +#define __CCRYDX12DEVICECONTEXT__ + +#include "DX12/CCryDX12Object.hpp" +#include "DX12/Misc/SCryDX11PipelineState.hpp" + +#include "DX12/API/DX12.hpp" +#include "DX12/API/DX12CommandList.hpp" + +#include +class CCryDX12Device; + +class CCryDX12DeviceContext + : public CCryDX12Object +{ + friend class CDeviceManager; + friend class CDeviceObjectFactory; + +public: + DX12_OBJECT(CCryDX12DeviceContext, CCryDX12Object); + + static CCryDX12DeviceContext* Create(CCryDX12Device* pDevice, bool isDeferred); + + CCryDX12DeviceContext(CCryDX12Device* pDevice, bool isDeferred); + + virtual ~CCryDX12DeviceContext(); + + IC bool IsDeferred() const { return m_bDeferred; } + + IC void CeaseCoreCommandList(uint32_t nPoolId) + { + if (nPoolId == CMDQUEUE_GRAPHICS) + { + CeaseDirectCommandQueue(false); + } + else if (nPoolId == CMDQUEUE_COPY) + { + CeaseCopyCommandQueue(false); + } + } + + IC void ResumeCoreCommandList(uint32_t nPoolId) + { + if (nPoolId == CMDQUEUE_GRAPHICS) + { + ResumeDirectCommandQueue(); + } + else if (nPoolId == CMDQUEUE_COPY) + { + ResumeCopyCommandQueue(); + } + } + + IC DX12::CommandListPool& GetCoreCommandListPool(int nPoolId) + { + if (nPoolId == CMDQUEUE_GRAPHICS) + { + return m_DirectListPool; + } + else if (nPoolId == CMDQUEUE_COPY) + { + return m_CopyListPool; + } + + __debugbreak(); + abort(); + } + + IC DX12::CommandListPool& GetCoreGraphicsCommandListPool() + { + return m_DirectListPool; + } + + IC DX12::CommandList* GetCoreGraphicsCommandList() const + { + return m_DirectCommandList; + } + + IC CCryDX12Device* GetDevice() const + { + return m_pDevice; + } + + IC ID3D12Device* GetD3D12Device() const + { + return m_pDevice->GetD3D12Device(); + } + + void Finish(DX12::SwapChain* pDX12SwapChain); + + #pragma region /* ID3D11DeviceChild implementation */ + + virtual void STDMETHODCALLTYPE GetDevice( + _Out_ ID3D11Device** ppDevice) final; + + virtual HRESULT STDMETHODCALLTYPE GetPrivateData( + _In_ REFGUID guid, + _Inout_ UINT* pDataSize, + _Out_writes_bytes_opt_(*pDataSize) void* pData) final; + + virtual HRESULT STDMETHODCALLTYPE SetPrivateData( + _In_ REFGUID guid, + _In_ UINT DataSize, + _In_reads_bytes_opt_(DataSize) const void* pData) final; + + virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( + _In_ REFGUID guid, + _In_opt_ const IUnknown* pData) final; + + #pragma endregion + + #pragma region /* ID3D11DeviceContext implementation */ + + virtual void STDMETHODCALLTYPE VSSetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer * const* ppConstantBuffers) final; + + virtual void STDMETHODCALLTYPE PSSetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11ShaderResourceView * const* ppShaderResourceViews) final; + + virtual void STDMETHODCALLTYPE PSSetShader( + _In_opt_ ID3D11PixelShader * pPixelShader, + _In_reads_opt_(NumClassInstances) ID3D11ClassInstance * const* ppClassInstances, + UINT NumClassInstances) final; + + virtual void STDMETHODCALLTYPE PSSetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _In_reads_opt_(NumSamplers) ID3D11SamplerState * const* ppSamplers) final; + + virtual void STDMETHODCALLTYPE VSSetShader( + _In_opt_ ID3D11VertexShader * pVertexShader, + _In_reads_opt_(NumClassInstances) ID3D11ClassInstance * const* ppClassInstances, + UINT NumClassInstances) final; + + virtual void STDMETHODCALLTYPE DrawIndexed( + _In_ UINT IndexCount, + _In_ UINT StartIndexLocation, + _In_ INT BaseVertexLocation) final; + + virtual void STDMETHODCALLTYPE Draw( + _In_ UINT VertexCount, + _In_ UINT StartVertexLocation) final; + + virtual HRESULT STDMETHODCALLTYPE Map( + _In_ ID3D11Resource* pResource, + _In_ UINT Subresource, + _In_ D3D11_MAP MapType, + _In_ UINT MapFlags, + _Out_ D3D11_MAPPED_SUBRESOURCE* pMappedResource) final; + + virtual void STDMETHODCALLTYPE Unmap( + _In_ ID3D11Resource* pResource, + _In_ UINT Subresource) final; + + virtual void STDMETHODCALLTYPE PSSetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer * const* ppConstantBuffers) final; + + virtual void STDMETHODCALLTYPE IASetInputLayout( + _In_opt_ ID3D11InputLayout* pInputLayout) final; + + virtual void STDMETHODCALLTYPE IASetVertexBuffers( + _In_range_(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer * const* ppVertexBuffers, + _In_reads_opt_(NumBuffers) const UINT * pStrides, + _In_reads_opt_(NumBuffers) const UINT * pOffsets) final; + + virtual void STDMETHODCALLTYPE IASetIndexBuffer( + _In_opt_ ID3D11Buffer* pIndexBuffer, + _In_ DXGI_FORMAT Format, + _In_ UINT Offset) final; + + virtual void STDMETHODCALLTYPE DrawIndexedInstanced( + _In_ UINT IndexCountPerInstance, + _In_ UINT InstanceCount, + _In_ UINT StartIndexLocation, + _In_ INT BaseVertexLocation, + _In_ UINT StartInstanceLocation) final; + + virtual void STDMETHODCALLTYPE DrawInstanced( + _In_ UINT VertexCountPerInstance, + _In_ UINT InstanceCount, + _In_ UINT StartVertexLocation, + _In_ UINT StartInstanceLocation) final; + + virtual void STDMETHODCALLTYPE GSSetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer * const* ppConstantBuffers) final; + + virtual void STDMETHODCALLTYPE GSSetShader( + _In_opt_ ID3D11GeometryShader * pShader, + _In_reads_opt_(NumClassInstances) ID3D11ClassInstance * const* ppClassInstances, + UINT NumClassInstances) final; + + virtual void STDMETHODCALLTYPE IASetPrimitiveTopology( + _In_ D3D11_PRIMITIVE_TOPOLOGY Topology) final; + + virtual void STDMETHODCALLTYPE VSSetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11ShaderResourceView * const* ppShaderResourceViews) final; + + virtual void STDMETHODCALLTYPE VSSetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _In_reads_opt_(NumSamplers) ID3D11SamplerState * const* ppSamplers) final; + + virtual void STDMETHODCALLTYPE Begin( + _In_ ID3D11Asynchronous* pAsync) final; + + virtual void STDMETHODCALLTYPE End( + _In_ ID3D11Asynchronous* pAsync) final; + + virtual HRESULT STDMETHODCALLTYPE GetData( + _In_ ID3D11Asynchronous * pAsync, + _Out_writes_bytes_opt_(DataSize) void* pData, + _In_ UINT DataSize, + _In_ UINT GetDataFlags) final; + + virtual void STDMETHODCALLTYPE SetPredication( + _In_opt_ ID3D11Predicate* pPredicate, + _In_ BOOL PredicateValue) final; + + virtual void STDMETHODCALLTYPE GSSetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11ShaderResourceView * const* ppShaderResourceViews) final; + + virtual void STDMETHODCALLTYPE GSSetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _In_reads_opt_(NumSamplers) ID3D11SamplerState * const* ppSamplers) final; + + virtual void STDMETHODCALLTYPE OMSetRenderTargets( + _In_range_(0, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11RenderTargetView * const* ppRenderTargetViews, + _In_opt_ ID3D11DepthStencilView * pDepthStencilView) final; + + virtual void STDMETHODCALLTYPE OMSetRenderTargetsAndUnorderedAccessViews( + _In_ UINT NumRTVs, + _In_reads_opt_(NumRTVs) ID3D11RenderTargetView * const* ppRenderTargetViews, + _In_opt_ ID3D11DepthStencilView * pDepthStencilView, + _In_range_(0, D3D11_1_UAV_SLOT_COUNT - 1) UINT UAVStartSlot, + _In_ UINT NumUAVs, + _In_reads_opt_(NumUAVs) ID3D11UnorderedAccessView * const* ppUnorderedAccessViews, + _In_reads_opt_(NumUAVs) const UINT * pUAVInitialCounts) final; + + virtual void STDMETHODCALLTYPE OMSetBlendState( + _In_opt_ ID3D11BlendState* pBlendState, + _In_opt_ const FLOAT BlendFactor[4], + _In_ UINT SampleMask) final; + + virtual void STDMETHODCALLTYPE OMSetDepthStencilState( + _In_opt_ ID3D11DepthStencilState* pDepthStencilState, + _In_ UINT StencilRef) final; + + virtual void STDMETHODCALLTYPE SOSetTargets( + _In_range_(0, D3D11_SO_BUFFER_SLOT_COUNT) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer * const* ppSOTargets, + _In_reads_opt_(NumBuffers) const UINT * pOffsets) final; + + virtual void STDMETHODCALLTYPE DrawAuto() final; + + virtual void STDMETHODCALLTYPE DrawIndexedInstancedIndirect( + _In_ ID3D11Buffer* pBufferForArgs, + _In_ UINT AlignedByteOffsetForArgs) final; + + virtual void STDMETHODCALLTYPE DrawInstancedIndirect( + _In_ ID3D11Buffer* pBufferForArgs, + _In_ UINT AlignedByteOffsetForArgs) final; + + virtual void STDMETHODCALLTYPE Dispatch( + _In_ UINT ThreadGroupCountX, + _In_ UINT ThreadGroupCountY, + _In_ UINT ThreadGroupCountZ) final; + + virtual void STDMETHODCALLTYPE DispatchIndirect( + _In_ ID3D11Buffer* pBufferForArgs, + _In_ UINT AlignedByteOffsetForArgs) final; + + virtual void STDMETHODCALLTYPE RSSetState( + _In_opt_ ID3D11RasterizerState* pRasterizerState) final; + + virtual void STDMETHODCALLTYPE RSSetViewports( + _In_range_(0, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) UINT NumViewports, + _In_reads_opt_(NumViewports) const D3D11_VIEWPORT * pViewports) final; + + virtual void STDMETHODCALLTYPE RSSetScissorRects( + _In_range_(0, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) UINT NumRects, + _In_reads_opt_(NumRects) const D3D11_RECT * pRects) final; + + virtual void STDMETHODCALLTYPE CopySubresourceRegion( + _In_ ID3D11Resource* pDstResource, + _In_ UINT DstSubresource, + _In_ UINT DstX, + _In_ UINT DstY, + _In_ UINT DstZ, + _In_ ID3D11Resource* pSrcResource, + _In_ UINT SrcSubresource, + _In_opt_ const D3D11_BOX* pSrcBox) final; + + virtual void STDMETHODCALLTYPE CopyResource( + _In_ ID3D11Resource* pDstResource, + _In_ ID3D11Resource* pSrcResource) final; + + virtual void STDMETHODCALLTYPE UpdateSubresource( + _In_ ID3D11Resource* pDstResource, + _In_ UINT DstSubresource, + _In_opt_ const D3D11_BOX* pDstBox, + _In_ const void* pSrcData, + _In_ UINT SrcRowPitch, + _In_ UINT SrcDepthPitch) final; + + virtual void STDMETHODCALLTYPE CopyStructureCount( + _In_ ID3D11Buffer* pDstBuffer, + _In_ UINT DstAlignedByteOffset, + _In_ ID3D11UnorderedAccessView* pSrcView) final; + + virtual void STDMETHODCALLTYPE ClearRenderTargetView( + _In_ ID3D11RenderTargetView* pRenderTargetView, + _In_ const FLOAT ColorRGBA[4]) final; + + virtual void STDMETHODCALLTYPE ClearUnorderedAccessViewUint( + _In_ ID3D11UnorderedAccessView* pUnorderedAccessView, + _In_ const UINT Values[4]) final; + + virtual void STDMETHODCALLTYPE ClearUnorderedAccessViewFloat( + _In_ ID3D11UnorderedAccessView* pUnorderedAccessView, + _In_ const FLOAT Values[4]) final; + + virtual void STDMETHODCALLTYPE ClearDepthStencilView( + _In_ ID3D11DepthStencilView* pDepthStencilView, + _In_ UINT ClearFlags, + _In_ FLOAT Depth, + _In_ UINT8 Stencil) final; + + virtual void STDMETHODCALLTYPE GenerateMips( + _In_ ID3D11ShaderResourceView* pShaderResourceView) final; + + virtual void STDMETHODCALLTYPE SetResourceMinLOD( + _In_ ID3D11Resource* pResource, + FLOAT MinLOD) final; + + virtual FLOAT STDMETHODCALLTYPE GetResourceMinLOD( + _In_ ID3D11Resource* pResource) final; + + virtual void STDMETHODCALLTYPE ResolveSubresource( + _In_ ID3D11Resource* pDstResource, + _In_ UINT DstSubresource, + _In_ ID3D11Resource* pSrcResource, + _In_ UINT SrcSubresource, + _In_ DXGI_FORMAT Format) final; + + virtual void STDMETHODCALLTYPE HSSetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11ShaderResourceView * const* ppShaderResourceViews) final; + + virtual void STDMETHODCALLTYPE HSSetShader( + _In_opt_ ID3D11HullShader * pHullShader, + _In_reads_opt_(NumClassInstances) ID3D11ClassInstance * const* ppClassInstances, + UINT NumClassInstances) final; + + virtual void STDMETHODCALLTYPE HSSetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _In_reads_opt_(NumSamplers) ID3D11SamplerState * const* ppSamplers) final; + + virtual void STDMETHODCALLTYPE HSSetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer * const* ppConstantBuffers) final; + + virtual void STDMETHODCALLTYPE DSSetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11ShaderResourceView * const* ppShaderResourceViews) final; + + virtual void STDMETHODCALLTYPE DSSetShader( + _In_opt_ ID3D11DomainShader * pDomainShader, + _In_reads_opt_(NumClassInstances) ID3D11ClassInstance * const* ppClassInstances, + UINT NumClassInstances) final; + + virtual void STDMETHODCALLTYPE DSSetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _In_reads_opt_(NumSamplers) ID3D11SamplerState * const* ppSamplers) final; + + virtual void STDMETHODCALLTYPE DSSetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer * const* ppConstantBuffers) final; + + virtual void STDMETHODCALLTYPE CSSetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _In_reads_opt_(NumViews) ID3D11ShaderResourceView * const* ppShaderResourceViews) final; + + virtual void STDMETHODCALLTYPE CSSetUnorderedAccessViews( + _In_range_(0, D3D11_1_UAV_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_1_UAV_SLOT_COUNT - StartSlot) UINT NumUAVs, + _In_reads_opt_(NumUAVs) ID3D11UnorderedAccessView * const* ppUnorderedAccessViews, + _In_reads_opt_(NumUAVs) const UINT * pUAVInitialCounts) final; + + virtual void STDMETHODCALLTYPE CSSetShader( + _In_opt_ ID3D11ComputeShader * pComputeShader, + _In_reads_opt_(NumClassInstances) ID3D11ClassInstance * const* ppClassInstances, + UINT NumClassInstances) final; + + virtual void STDMETHODCALLTYPE CSSetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _In_reads_opt_(NumSamplers) ID3D11SamplerState * const* ppSamplers) final; + + virtual void STDMETHODCALLTYPE CSSetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _In_reads_opt_(NumBuffers) ID3D11Buffer * const* ppConstantBuffers) final; + + virtual void STDMETHODCALLTYPE VSGetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer * *ppConstantBuffers) final; + + virtual void STDMETHODCALLTYPE PSGetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11ShaderResourceView * *ppShaderResourceViews) final; + + virtual void STDMETHODCALLTYPE PSGetShader( + _Out_ ID3D11PixelShader** ppPixelShader, + _Out_writes_opt_(*pNumClassInstances) ID3D11ClassInstance** ppClassInstances, + _Inout_opt_ UINT* pNumClassInstances) final; + + virtual void STDMETHODCALLTYPE PSGetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _Out_writes_opt_(NumSamplers) ID3D11SamplerState * *ppSamplers) final; + + virtual void STDMETHODCALLTYPE VSGetShader( + _Out_ ID3D11VertexShader** ppVertexShader, + _Out_writes_opt_(*pNumClassInstances) ID3D11ClassInstance** ppClassInstances, + _Inout_opt_ UINT* pNumClassInstances) final; + + virtual void STDMETHODCALLTYPE PSGetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer * *ppConstantBuffers) final; + + virtual void STDMETHODCALLTYPE IAGetInputLayout( + _Out_ ID3D11InputLayout** ppInputLayout) final; + + virtual void STDMETHODCALLTYPE IAGetVertexBuffers( + _In_range_(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer * *ppVertexBuffers, + _Out_writes_opt_(NumBuffers) UINT * pStrides, + _Out_writes_opt_(NumBuffers) UINT * pOffsets) final; + + virtual void STDMETHODCALLTYPE IAGetIndexBuffer( + _Out_opt_ ID3D11Buffer** pIndexBuffer, + _Out_opt_ DXGI_FORMAT* Format, + _Out_opt_ UINT* Offset) final; + + virtual void STDMETHODCALLTYPE GSGetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer * *ppConstantBuffers) final; + + virtual void STDMETHODCALLTYPE GSGetShader( + _Out_ ID3D11GeometryShader** ppGeometryShader, + _Out_writes_opt_(*pNumClassInstances) ID3D11ClassInstance** ppClassInstances, + _Inout_opt_ UINT* pNumClassInstances) final; + + virtual void STDMETHODCALLTYPE IAGetPrimitiveTopology( + _Out_ D3D11_PRIMITIVE_TOPOLOGY* pTopology) final; + + virtual void STDMETHODCALLTYPE VSGetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11ShaderResourceView * *ppShaderResourceViews) final; + + virtual void STDMETHODCALLTYPE VSGetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _Out_writes_opt_(NumSamplers) ID3D11SamplerState * *ppSamplers) final; + + virtual void STDMETHODCALLTYPE GetPredication( + _Out_opt_ ID3D11Predicate** ppPredicate, + _Out_opt_ BOOL* pPredicateValue) final; + + virtual void STDMETHODCALLTYPE GSGetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11ShaderResourceView * *ppShaderResourceViews) final; + + virtual void STDMETHODCALLTYPE GSGetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _Out_writes_opt_(NumSamplers) ID3D11SamplerState * *ppSamplers) final; + + virtual void STDMETHODCALLTYPE OMGetRenderTargets( + _In_range_(0, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11RenderTargetView * *ppRenderTargetViews, + _Out_opt_ ID3D11DepthStencilView * *ppDepthStencilView) final; + + virtual void STDMETHODCALLTYPE OMGetRenderTargetsAndUnorderedAccessViews( + _In_range_(0, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT) UINT NumRTVs, + _Out_writes_opt_(NumRTVs) ID3D11RenderTargetView * *ppRenderTargetViews, + _Out_opt_ ID3D11DepthStencilView * *ppDepthStencilView, + _In_range_(0, D3D11_PS_CS_UAV_REGISTER_COUNT - 1) UINT UAVStartSlot, + _In_range_(0, D3D11_PS_CS_UAV_REGISTER_COUNT - UAVStartSlot) UINT NumUAVs, + _Out_writes_opt_(NumUAVs) ID3D11UnorderedAccessView * *ppUnorderedAccessViews) final; + + virtual void STDMETHODCALLTYPE OMGetBlendState( + _Out_opt_ ID3D11BlendState * *ppBlendState, + _Out_opt_ FLOAT BlendFactor[4], + _Out_opt_ UINT * pSampleMask) final; + + virtual void STDMETHODCALLTYPE OMGetDepthStencilState( + _Out_opt_ ID3D11DepthStencilState** ppDepthStencilState, + _Out_opt_ UINT* pStencilRef) final; + + virtual void STDMETHODCALLTYPE SOGetTargets( + _In_range_(0, D3D11_SO_BUFFER_SLOT_COUNT) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer * *ppSOTargets) final; + + virtual void STDMETHODCALLTYPE RSGetState( + _Out_ ID3D11RasterizerState** ppRasterizerState) final; + + virtual void STDMETHODCALLTYPE RSGetViewports( + _Inout_ UINT* pNumViewports, + _Out_writes_opt_(*pNumViewports) D3D11_VIEWPORT* pViewports) final; + + virtual void STDMETHODCALLTYPE RSGetScissorRects( + _Inout_ UINT* pNumRects, + _Out_writes_opt_(*pNumRects) D3D11_RECT* pRects) final; + + virtual void STDMETHODCALLTYPE HSGetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11ShaderResourceView * *ppShaderResourceViews) final; + + virtual void STDMETHODCALLTYPE HSGetShader( + _Out_ ID3D11HullShader** ppHullShader, + _Out_writes_opt_(*pNumClassInstances) ID3D11ClassInstance** ppClassInstances, + _Inout_opt_ UINT* pNumClassInstances) final; + + virtual void STDMETHODCALLTYPE HSGetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _Out_writes_opt_(NumSamplers) ID3D11SamplerState * *ppSamplers) final; + + virtual void STDMETHODCALLTYPE HSGetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer * *ppConstantBuffers) final; + + virtual void STDMETHODCALLTYPE DSGetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11ShaderResourceView * *ppShaderResourceViews) final; + + virtual void STDMETHODCALLTYPE DSGetShader( + _Out_ ID3D11DomainShader** ppDomainShader, + _Out_writes_opt_(*pNumClassInstances) ID3D11ClassInstance** ppClassInstances, + _Inout_opt_ UINT* pNumClassInstances) final; + + virtual void STDMETHODCALLTYPE DSGetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _Out_writes_opt_(NumSamplers) ID3D11SamplerState * *ppSamplers) final; + + virtual void STDMETHODCALLTYPE DSGetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer * *ppConstantBuffers) final; + + virtual void STDMETHODCALLTYPE CSGetShaderResources( + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) UINT NumViews, + _Out_writes_opt_(NumViews) ID3D11ShaderResourceView * *ppShaderResourceViews) final; + + virtual void STDMETHODCALLTYPE CSGetUnorderedAccessViews( + _In_range_(0, D3D11_PS_CS_UAV_REGISTER_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_PS_CS_UAV_REGISTER_COUNT - StartSlot) UINT NumUAVs, + _Out_writes_opt_(NumUAVs) ID3D11UnorderedAccessView * *ppUnorderedAccessViews) final; + + virtual void STDMETHODCALLTYPE CSGetShader( + _Out_ ID3D11ComputeShader** ppComputeShader, + _Out_writes_opt_(*pNumClassInstances) ID3D11ClassInstance** ppClassInstances, + _Inout_opt_ UINT* pNumClassInstances) final; + + virtual void STDMETHODCALLTYPE CSGetSamplers( + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) UINT NumSamplers, + _Out_writes_opt_(NumSamplers) ID3D11SamplerState * *ppSamplers) final; + + virtual void STDMETHODCALLTYPE CSGetConstantBuffers( + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) UINT StartSlot, + _In_range_(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) UINT NumBuffers, + _Out_writes_opt_(NumBuffers) ID3D11Buffer * *ppConstantBuffers) final; + + virtual void STDMETHODCALLTYPE ClearState() final; + + virtual void STDMETHODCALLTYPE Flush() final; + + virtual D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE GetType() final; + + virtual UINT STDMETHODCALLTYPE GetContextFlags() final; + + virtual void STDMETHODCALLTYPE ExecuteCommandList( + _In_ ID3D11CommandList* pCommandList, + BOOL RestoreContextState) final; + + virtual HRESULT STDMETHODCALLTYPE FinishCommandList( + _In_ BOOL RestoreDeferredContextState, + _Out_opt_ ID3D11CommandList** ppCommandList) final; + + #pragma endregion + + #pragma region /* D3D 11.1 specific functions */ + + virtual void STDMETHODCALLTYPE CopySubresourceRegion1(ID3D11Resource* pDstResource, UINT DstSubresource, UINT DstX, UINT DstY, UINT DstZ, ID3D11Resource* pSrcResource, UINT SrcSubresource, const D3D11_BOX* pSrcBox, UINT CopyFlags) final; + virtual void STDMETHODCALLTYPE CopyResource1(ID3D11Resource* pDstResource, ID3D11Resource* pSrcResource, UINT CopyFlags) final; + virtual void STDMETHODCALLTYPE UpdateSubresource1(ID3D11Resource* pDstResource, UINT DstSubresource, const D3D11_BOX* pDstBox, const void* pSrcData, UINT SrcRowPitch, UINT SrcDepthPitch, UINT CopyFlags) final; + virtual void STDMETHODCALLTYPE DiscardResource(ID3D11Resource* pResource) final; + virtual void STDMETHODCALLTYPE DiscardView(ID3D11View* pResourceView) final; + + virtual void STDMETHODCALLTYPE VSSetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers, const UINT* pFirstConstant, const UINT* pNumConstants) final; + virtual void STDMETHODCALLTYPE HSSetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers, const UINT* pFirstConstant, const UINT* pNumConstants) final; + virtual void STDMETHODCALLTYPE DSSetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers, const UINT* pFirstConstant, const UINT* pNumConstants) final; + virtual void STDMETHODCALLTYPE GSSetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers, const UINT* pFirstConstant, const UINT* pNumConstants) final; + virtual void STDMETHODCALLTYPE PSSetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers, const UINT* pFirstConstant, const UINT* pNumConstants) final; + virtual void STDMETHODCALLTYPE CSSetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers, const UINT* pFirstConstant, const UINT* pNumConstants) final; + + virtual void STDMETHODCALLTYPE VSGetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer** ppConstantBuffers, UINT* pFirstConstant, UINT* pNumConstants) final; + virtual void STDMETHODCALLTYPE HSGetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer** ppConstantBuffers, UINT* pFirstConstant, UINT* pNumConstants) final; + virtual void STDMETHODCALLTYPE DSGetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer** ppConstantBuffers, UINT* pFirstConstant, UINT* pNumConstants) final; + virtual void STDMETHODCALLTYPE GSGetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer** ppConstantBuffers, UINT* pFirstConstant, UINT* pNumConstants) final; + virtual void STDMETHODCALLTYPE PSGetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer** ppConstantBuffers, UINT* pFirstConstant, UINT* pNumConstants) final; + virtual void STDMETHODCALLTYPE CSGetConstantBuffers1(UINT StartSlot, UINT NumBuffers, ID3D11Buffer** ppConstantBuffers, UINT* pFirstConstant, UINT* pNumConstants) final; + + virtual void STDMETHODCALLTYPE SwapDeviceContextState(ID3DDeviceContextState* pState, ID3DDeviceContextState** ppPreviousState) final; + virtual void STDMETHODCALLTYPE ClearView(ID3D11View* pView, const FLOAT Color[4], const D3D11_RECT* pRect, UINT NumRects) final; + virtual void STDMETHODCALLTYPE DiscardView1(ID3D11View* pResourceView, const D3D11_RECT* pRects, UINT NumRects) final; + + #pragma endregion + + virtual void STDMETHODCALLTYPE ClearRectsRenderTargetView( + _In_ ID3D11RenderTargetView * pRenderTargetView, + _In_ const FLOAT ColorRGBA[4], + _In_ UINT NumRects, + _In_reads_opt_(NumRects) const D3D11_RECT * pRects); + + virtual void STDMETHODCALLTYPE ClearRectsUnorderedAccessViewUint( + _In_ ID3D11UnorderedAccessView * pUnorderedAccessView, + _In_ const UINT Values[4], + _In_ UINT NumRects, + _In_reads_opt_(NumRects) const D3D11_RECT * pRects); + + virtual void STDMETHODCALLTYPE ClearRectsUnorderedAccessViewFloat( + _In_ ID3D11UnorderedAccessView * pUnorderedAccessView, + _In_ const FLOAT Values[4], + _In_ UINT NumRects, + _In_reads_opt_(NumRects) const D3D11_RECT * pRects); + + virtual void STDMETHODCALLTYPE ClearRectsDepthStencilView( + _In_ ID3D11DepthStencilView * pDepthStencilView, + _In_ UINT ClearFlags, + _In_ FLOAT Depth, + _In_ UINT8 Stencil, + _In_ UINT NumRects, + _In_reads_opt_(NumRects) const D3D11_RECT * pRects); + + HRESULT STDMETHODCALLTYPE CopyStagingResource( + _In_ ID3D11Resource* pStagingResource, + _In_ ID3D11Resource* pSourceResource, + _In_ UINT SubResource, + _In_ BOOL Upload); + + HRESULT STDMETHODCALLTYPE TestStagingResource( + _In_ ID3D11Resource* pStagingResource); + + HRESULT STDMETHODCALLTYPE WaitStagingResource( + _In_ ID3D11Resource* pStagingResource); + + HRESULT STDMETHODCALLTYPE MapStagingResource( + _In_ ID3D11Resource* pTextureResource, + _In_ ID3D11Resource* pStagingResource, + _In_ UINT SubResource, + _In_ BOOL Upload, + _Out_ void** ppStagingMemory, + _Out_ uint32_t* pRowPitch); + + void STDMETHODCALLTYPE UnmapStagingResource( + _In_ ID3D11Resource* pStagingResource, + _In_ BOOL Upload); + + void STDMETHODCALLTYPE UploadResource( + _In_ ICryDX12Resource* pDstResource, + _In_ const D3D11_SUBRESOURCE_DATA* pInitialData, + _In_ size_t numInitialData); + + void STDMETHODCALLTYPE UploadResource( + _In_ DX12::Resource* pDstResource, + _In_ const DX12::Resource::InitialData* pSrcData); + + IC UINT64 InsertFence() + { + return m_CmdFenceSet.GetCurrentValue(CMDQUEUE_GRAPHICS) - !m_DirectCommandList->IsUtilized(); + } + + IC HRESULT FlushToFence(UINT64 fenceValue) + { + m_DirectListPool.GetAsyncCommandQueue().Flush(fenceValue); + return S_OK; + } + + IC HRESULT TestForFence(UINT64 fenceValue) + { + return m_CmdFenceSet.IsCompleted(fenceValue, CMDQUEUE_GRAPHICS) ? S_OK : S_FALSE; + } + + IC HRESULT WaitForFence(UINT64 fenceValue) + { + m_CmdFenceSet.WaitForFence(fenceValue, CMDQUEUE_GRAPHICS); + return S_OK; + } + + void WaitForIdle(); + + void ResetCachedState(); + + void PushMarker(const char* name) + { + PIXBeginEvent(m_DirectCommandList->GetD3D12CommandList(), 0, name); + } + + void PopMarker() + { + PIXEndEvent(m_DirectCommandList->GetD3D12CommandList()); + } + + UINT64 MakeCpuTimestamp(UINT64 gpuTimestamp) const; + UINT64 MakeCpuTimestampMicroseconds(UINT64 gpuTimestamp) const; + + void BeginCopyRegion() + { + m_bInCopyRegion = true; + } + + void EndCopyRegion() + { + m_bInCopyRegion = false; + } + + void SubmitAllCommands(bool wait); + + UINT TimestampIndex(DX12::CommandList* pCmdList); + ID3D12Resource* QueryTimestamp(DX12::CommandList* pCmdList, UINT index); + void ResolveTimestamp(DX12::CommandList* pCmdList, UINT index, void* mem); + + UINT OcclusionIndex(DX12::CommandList* pCmdList, bool counter); + ID3D12Resource* QueryOcclusion(DX12::CommandList* pCmdList, UINT index, bool counter); + void ResolveOcclusion(DX12::CommandList* pCmdList, UINT index, void* mem); + + // This is a somewhat arbitrary number that affects stack usage for methods that get subresource descriptors. + static constexpr int MAX_SUBRESOURCES = 64; + +private: + bool PreparePSO(DX12::CommandMode commandMode); + void PrepareGraphicsFF(); + + bool PrepareGraphicsState(); + bool PrepareComputeState(); + + void CeaseDirectCommandQueue(bool wait); + void ResumeDirectCommandQueue(); + void CeaseCopyCommandQueue(bool wait); + void ResumeCopyCommandQueue(); + void CeaseAllCommandQueues(bool wait); + void ResumeAllCommandQueues(); + + void SubmitDirectCommands(bool wait); + void SubmitDirectCommands(bool wait, const UINT64 fenceValue); + void SubmitCopyCommands(bool wait); + void SubmitCopyCommands(bool wait, const UINT64 fenceValue); + void SubmitAllCommands(bool wait, const UINT64(&fenceValues)[CMDQUEUE_NUM]); + void SubmitAllCommands(bool wait, const UINT64(&fenceValues)[CMDQUEUE_NUM], int fenceId); + void SubmitAllCommands(bool wait, const std::atomic(&fenceValues)[CMDQUEUE_NUM]); + void SubmitAllCommands(bool wait, const std::atomic(&fenceValues)[CMDQUEUE_NUM], int fenceId); + + void BindResources(DX12::CommandMode commandMode); + void BindOutputViews(); + + void DebugPrintResources(DX12::CommandMode commandMode); + + void SetConstantBuffers1( + DX12::EShaderStage shaderStage, + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers, + const UINT* pFirstConstant, + const UINT* pNumConstants, + DX12::CommandMode commandMode); + + bool m_bInCopyRegion; + bool m_bDeferred; + + CCryDX12Device* m_pDevice; + DX12::Device* m_pDX12Device; + + DX12::CommandListFenceSet m_CmdFenceSet; + + DX12::CommandListPool m_DirectListPool; + DX12::CommandListPool m_CopyListPool; + + _smart_ptr m_DirectCommandList; + _smart_ptr m_CopyCommandList; + + const DX12::PipelineState* m_CurrentPSO; + const DX12::RootSignature* m_CurrentRootSignature[DX12::CommandModeCount]; + SCryDX11PipelineState m_PipelineState[DX12::CommandModeCount]; + + UINT m_OutstandingQueries; + + ID3D12Resource* m_TimestampDownloadBuffer; + ID3D12Resource* m_OcclusionDownloadBuffer; + UINT m_TimestampIndex; + UINT m_OcclusionIndex; + void* m_TimestampMemory; + void* m_OcclusionMemory; + bool m_TimestampMapValid; + bool m_OcclusionMapValid; + DX12::DescriptorHeap* m_pResourceHeap; + DX12::DescriptorHeap* m_pSamplerHeap; + bool m_bCurrentNative; + int m_nResDynOffset; + int m_nFrame; + uint32_t m_nStencilRef; + + DX12::QueryHeap m_TimestampHeap; + DX12::QueryHeap m_OcclusionHeap; + DX12::QueryHeap m_PipelineHeap; + +#ifdef DX12_STATS + size_t m_NumMapDiscardSkips; + size_t m_NumMapDiscards; + + size_t m_NumCommandListOverflows; + size_t m_NumCommandListSplits; + size_t m_NumPSOs; + size_t m_NumRootSignatures; + size_t m_NumberSettingOutputViews; +#endif // DX12_STATS +}; + +#endif // __CCRYDX12DEVICECONTEXT__ diff --git a/src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12GIFactory.cpp b/src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12GIFactory.cpp new file mode 100644 index 00000000000..0586c9d1282 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12GIFactory.cpp @@ -0,0 +1,90 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "CCryDX12GIFactory.hpp" +#include "CCryDX12SwapChain.hpp" + +#include "DX12/Device/CCryDX12Device.hpp" +#include "DX12/Device/CCryDX12DeviceContext.hpp" + +#include "DX12/API/DX12SwapChain.hpp" + +CCryDX12GIFactory* CCryDX12GIFactory::Create() +{ + IDXGIFactory4* pDXGIFactory4 = NULL; + + if (S_OK != CreateDXGIFactory1(IID_PPV_ARGS(&pDXGIFactory4))) + { + DX12_ASSERT("Failed to create underlying DXGI factory!"); + return NULL; + } + + return DX12::PassAddRef(new CCryDX12GIFactory(pDXGIFactory4)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +CCryDX12GIFactory::CCryDX12GIFactory(IDXGIFactory4* pDXGIFactory4) + : Super() + , m_pDXGIFactory4(pDXGIFactory4) +{ + DX12_FUNC_LOG +} + +CCryDX12GIFactory::~CCryDX12GIFactory() +{ + DX12_FUNC_LOG +} + +HRESULT STDMETHODCALLTYPE CCryDX12GIFactory::EnumAdapters(UINT Adapter, _Out_ IDXGIAdapter** ppAdapter) +{ + DX12_FUNC_LOG + return m_pDXGIFactory4->EnumAdapters(Adapter, ppAdapter); +} + +HRESULT STDMETHODCALLTYPE CCryDX12GIFactory::MakeWindowAssociation(HWND WindowHandle, UINT Flags) +{ + DX12_FUNC_LOG + return m_pDXGIFactory4->MakeWindowAssociation(WindowHandle, Flags); +} + +HRESULT STDMETHODCALLTYPE CCryDX12GIFactory::GetWindowAssociation(_Out_ HWND* pWindowHandle) +{ + DX12_FUNC_LOG + return m_pDXGIFactory4->GetWindowAssociation(pWindowHandle); +} + +HRESULT STDMETHODCALLTYPE CCryDX12GIFactory::CreateSwapChain(_In_ IUnknown* pDevice, _In_ DXGI_SWAP_CHAIN_DESC* pDesc, _Out_ IDXGISwapChain** ppSwapChain) +{ + DX12_FUNC_LOG + * ppSwapChain = CCryDX12SwapChain::Create(static_cast(pDevice), m_pDXGIFactory4, pDesc); + return ppSwapChain ? S_OK : E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CCryDX12GIFactory::CreateSoftwareAdapter(HMODULE Module, _Out_ IDXGIAdapter** ppAdapter) +{ + DX12_FUNC_LOG + return m_pDXGIFactory4->CreateSoftwareAdapter(Module, ppAdapter); +} + +HRESULT STDMETHODCALLTYPE CCryDX12GIFactory::EnumAdapters1(UINT Adapter, _Out_ IDXGIAdapter1** ppAdapter) +{ + DX12_FUNC_LOG + return m_pDXGIFactory4->EnumAdapters1(Adapter, ppAdapter); +} + +BOOL STDMETHODCALLTYPE CCryDX12GIFactory::IsCurrent() +{ + DX12_FUNC_LOG + return m_pDXGIFactory4->IsCurrent(); +} diff --git a/src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12GIFactory.hpp b/src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12GIFactory.hpp new file mode 100644 index 00000000000..7da6e7b7698 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12GIFactory.hpp @@ -0,0 +1,180 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#pragma once +#ifndef __CCRYDX12GIFACTORY__ +#define __CCRYDX12GIFACTORY__ + +#include "DX12/CCryDX12Object.hpp" + +class CCryDX12GIFactory + : public CCryDX12GIObject +{ +public: + DX12_OBJECT(CCryDX12GIFactory, CCryDX12GIObject); + + static CCryDX12GIFactory* Create(); + + virtual ~CCryDX12GIFactory(); + + IDXGIFactory4* GetDXGIFactory() const { return m_pDXGIFactory4; } + + #pragma region /* IDXGIFactory implementation */ + + virtual HRESULT STDMETHODCALLTYPE EnumAdapters( + UINT Adapter, + _Out_ IDXGIAdapter** ppAdapter) final; + + virtual HRESULT STDMETHODCALLTYPE MakeWindowAssociation( + HWND WindowHandle, + UINT Flags) final; + + virtual HRESULT STDMETHODCALLTYPE GetWindowAssociation( + _Out_ HWND* pWindowHandle) final; + + virtual HRESULT STDMETHODCALLTYPE CreateSwapChain( + _In_ IUnknown* pDevice, + _In_ DXGI_SWAP_CHAIN_DESC* pDesc, + _Out_ IDXGISwapChain** ppSwapChain) final; + + virtual HRESULT STDMETHODCALLTYPE CreateSoftwareAdapter( + HMODULE Module, + _Out_ IDXGIAdapter** ppAdapter) final; + + #pragma endregion + + #pragma region /* IDXGIFactory1 implementation */ + + virtual HRESULT STDMETHODCALLTYPE EnumAdapters1( + UINT Adapter, + _Out_ IDXGIAdapter1** ppAdapter) final; + + virtual BOOL STDMETHODCALLTYPE IsCurrent() final; + + #pragma endregion + + #pragma region /* IDXGIFactory2 implementation */ + + virtual BOOL STDMETHODCALLTYPE IsWindowedStereoEnabled() final { abort(); return FALSE; } + + virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForHwnd( + /* [annotation][in] */ + _In_ IUnknown* pDevice, + /* [annotation][in] */ + _In_ HWND hWnd, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC1* pDesc, + /* [annotation][in] */ + _In_opt_ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput* pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain1** ppSwapChain) final { abort(); return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForCoreWindow( + /* [annotation][in] */ + _In_ IUnknown* pDevice, + /* [annotation][in] */ + _In_ IUnknown* pWindow, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC1* pDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput* pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain1** ppSwapChain) final { abort(); return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE GetSharedResourceAdapterLuid( + /* [annotation] */ + _In_ HANDLE hResource, + /* [annotation] */ + _Out_ LUID* pLuid) final { abort(); return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE RegisterStereoStatusWindow( + /* [annotation][in] */ + _In_ HWND WindowHandle, + /* [annotation][in] */ + _In_ UINT wMsg, + /* [annotation][out] */ + _Out_ DWORD* pdwCookie) final { abort(); return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE RegisterStereoStatusEvent( + /* [annotation][in] */ + _In_ HANDLE hEvent, + /* [annotation][out] */ + _Out_ DWORD* pdwCookie) final { abort(); return S_OK; } + + virtual void STDMETHODCALLTYPE UnregisterStereoStatus( + /* [annotation][in] */ + _In_ DWORD dwCookie) final { abort(); } + + virtual HRESULT STDMETHODCALLTYPE RegisterOcclusionStatusWindow( + /* [annotation][in] */ + _In_ HWND WindowHandle, + /* [annotation][in] */ + _In_ UINT wMsg, + /* [annotation][out] */ + _Out_ DWORD* pdwCookie) final { abort(); return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE RegisterOcclusionStatusEvent( + /* [annotation][in] */ + _In_ HANDLE hEvent, + /* [annotation][out] */ + _Out_ DWORD* pdwCookie) final { abort(); return S_OK; } + + virtual void STDMETHODCALLTYPE UnregisterOcclusionStatus( + /* [annotation][in] */ + _In_ DWORD dwCookie) final { abort(); } + + virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForComposition( + /* [annotation][in] */ + _In_ IUnknown* pDevice, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC1* pDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput* pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain1** ppSwapChain) final { abort(); return S_OK; } + + #pragma endregion + + #pragma region /* IDXGIFactory3 implementation */ + + virtual UINT STDMETHODCALLTYPE GetCreationFlags(void) final { abort(); return 0; } + + #pragma endregion + + #pragma region /* IDXGIFactory4 implementation */ + + virtual HRESULT STDMETHODCALLTYPE EnumAdapterByLuid( + /* [annotation] */ + _In_ LUID AdapterLuid, + /* [annotation] */ + _In_ REFIID riid, + /* [annotation] */ + _COM_Outptr_ void** ppvAdapter) final { abort(); return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE EnumWarpAdapter( + /* [annotation] */ + _In_ REFIID riid, + /* [annotation] */ + _COM_Outptr_ void** ppvAdapter) final { abort(); return S_OK; } + + #pragma endregion + +protected: + CCryDX12GIFactory(IDXGIFactory4* pDXGIFactory4); + +private: + _smart_ptr m_pDXGIFactory4; +}; + +#endif // __CRYDX12GIFACTORY__ diff --git a/src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12SwapChain.cpp b/src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12SwapChain.cpp new file mode 100644 index 00000000000..c4c3f5bafe7 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12SwapChain.cpp @@ -0,0 +1,273 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#include "StdAfx.h" +#include "CCryDX12SwapChain.hpp" + +#include "DX12/Device/CCryDX12Device.hpp" +#include "DX12/Device/CCryDX12DeviceContext.hpp" +#include "DX12/Resource/CCryDX12Resource.hpp" +#include "DX12/Resource/Texture/CCryDX12Texture1D.hpp" +#include "DX12/Resource/Texture/CCryDX12Texture2D.hpp" +#include "DX12/Resource/Texture/CCryDX12Texture3D.hpp" + +#include "DX12/API/DX12Device.hpp" +#include "DX12/API/DX12SwapChain.hpp" +#include "DX12/API/DX12Resource.hpp" +#include "Dx12/API/DX12AsyncCommandQueue.hpp" + +#ifdef WIN32 +#include +#pragma comment(lib, "dwmapi.lib") +#endif + +CCryDX12SwapChain* CCryDX12SwapChain::Create(CCryDX12Device* device, IDXGIFactory4* factory, DXGI_SWAP_CHAIN_DESC* pDesc) +{ + CCryDX12DeviceContext* deviceContext = device->GetDeviceContext(); + DX12::SwapChain* swapChain = DX12::SwapChain::Create(deviceContext->GetCoreGraphicsCommandList(), factory, pDesc); + + return DX12::PassAddRef(new CCryDX12SwapChain(device, swapChain)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +CCryDX12SwapChain::CCryDX12SwapChain(CCryDX12Device* device, DX12::SwapChain* swapChain) + : Super() + , m_Device(device) + , m_SwapChain(swapChain) +{ + DX12_FUNC_LOG + AcquireBuffers(); +} + +CCryDX12SwapChain::~CCryDX12SwapChain() +{ + DX12_FUNC_LOG + ForfeitBuffers(); + + SAFE_RELEASE(m_SwapChain); +} + +void CCryDX12SwapChain::AcquireBuffers() +{ + const DXGI_SWAP_CHAIN_DESC& desc = m_SwapChain->GetDesc(); + IDXGISwapChain* swapChain = m_SwapChain->GetDXGISwapChain(); + + std::vector resources; + m_BackBuffers.reserve(desc.BufferCount); + resources.reserve(desc.BufferCount); + + for (int i = 0; i < desc.BufferCount; ++i) + { + ID3D12Resource* resource12 = NULL; + if (S_OK == swapChain->GetBuffer(i, IID_PPV_ARGS(&resource12))) + { + m_BackBuffers.emplace_back(); + m_BackBuffers.back().attach(CCryDX12Texture2D::Create(GetDevice(), this, resource12)); + resources.emplace_back(&m_BackBuffers.back()->GetDX12Resource()); + resource12->Release(); + } + } + + m_SwapChain->AcquireBuffers(std::move(resources)); +} + +void CCryDX12SwapChain::ForfeitBuffers() +{ + m_SwapChain->ForfeitBuffers(); + m_BackBuffers.clear(); +} + +/* IDXGIDeviceSubObject implementation */ + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::GetDevice( + _In_ REFIID riid, + _Out_ void** ppDevice) +{ + DX12_FUNC_LOG + return m_SwapChain->GetDXGISwapChain()->GetDevice(riid, ppDevice); +} + +/* IDXGISwapChain implementation */ + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::Present( + UINT SyncInterval, + UINT Flags) +{ + DX12_FUNC_LOG + m_Device->GetDeviceContext()->Finish(m_SwapChain); + + DX12_LOG("------------------------------------------------ PRESENT ------------------------------------------------"); + HRESULT hr = m_SwapChain->Present(SyncInterval, Flags); + return hr; +} + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::GetBuffer( + UINT Buffer, + _In_ REFIID riid, + _Out_ void** ppSurface) +{ + DX12_FUNC_LOG + if (riid == __uuidof(ID3D11Texture2D)) + { + R_ASSERT2(Buffer < m_BackBuffers.size(), "Invalid buffer index"); + CCryDX12Texture2D* texture = m_BackBuffers[Buffer]; + texture->AddRef(); + *ppSurface = texture; + } + else + { + DX12_ASSERT(0, "Not implemented!"); + return -1; + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::SetFullscreenState( + BOOL Fullscreen, + _In_opt_ IDXGIOutput* pTarget) +{ + DX12_FUNC_LOG + m_Device->GetDeviceContext()->SubmitAllCommands(true); + return m_SwapChain->GetDXGISwapChain()->SetFullscreenState(Fullscreen, pTarget); +} + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::GetFullscreenState( + _Out_opt_ BOOL* pFullscreen, + _Out_opt_ IDXGIOutput** ppTarget) +{ + DX12_FUNC_LOG + return m_SwapChain->GetDXGISwapChain()->GetFullscreenState(pFullscreen, ppTarget); +} + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::GetDesc( + _Out_ DXGI_SWAP_CHAIN_DESC* pDesc) +{ + DX12_FUNC_LOG + return m_SwapChain->GetDXGISwapChain()->GetDesc(pDesc); +} + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::ResizeBuffers( + UINT BufferCount, + UINT Width, + UINT Height, + DXGI_FORMAT NewFormat, + UINT SwapChainFlags) +{ + DX12_FUNC_LOG + + ID3D11RenderTargetView* views[8] = {}; + + m_Device->GetDeviceContext()->OMSetRenderTargets(8, views, nullptr); + m_Device->GetDeviceContext()->SubmitAllCommands(true); + m_Device->GetDeviceContext()->WaitForIdle(); + + ForfeitBuffers(); + + m_Device->GetDX12Device()->FlushReleaseHeap(DX12::Device::ResourceReleasePolicy::Immediate); + + HRESULT res = m_SwapChain->GetDXGISwapChain()->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags); + if (res == S_OK) + { + AcquireBuffers(); + } + + return res; +} + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::ResizeTarget( + _In_ const DXGI_MODE_DESC* pNewTargetParameters) +{ + DX12_FUNC_LOG + + //ID3D11RenderTargetView* views[8] = {}; + + //m_Device->GetDeviceContext()->OMSetRenderTargets(8, views, nullptr); + //m_Device->GetDeviceContext()->SubmitAllCommands(true); + //m_Device->GetDeviceContext()->WaitForIdle(); + + //ForfeitBuffers(); + + HRESULT hr = m_SwapChain->GetDXGISwapChain()->ResizeTarget(pNewTargetParameters); + return hr; +} + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::GetContainingOutput( + _Out_ IDXGIOutput** ppOutput) +{ + DX12_FUNC_LOG + return m_SwapChain->GetDXGISwapChain()->GetContainingOutput(ppOutput); +} + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::GetFrameStatistics( + _Out_ DXGI_FRAME_STATISTICS* pStats) +{ + DX12_FUNC_LOG + return m_SwapChain->GetDXGISwapChain()->GetFrameStatistics(pStats); +} + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::GetLastPresentCount( + _Out_ UINT* pLastPresentCount) +{ + DX12_FUNC_LOG + return m_SwapChain->GetDXGISwapChain()->GetLastPresentCount(pLastPresentCount); +} + +/* IDXGISwapChain1 implementation */ + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::Present1( + UINT SyncInterval, UINT Flags, const DXGI_PRESENT_PARAMETERS* pPresentParameters) +{ + DX12_FUNC_LOG + + m_Device->GetDeviceContext()->Finish(m_SwapChain); + + DX12_LOG( + "------------------------------------------------ PRESENT ------------------------------------------------"); + return m_SwapChain->Present1(SyncInterval, Flags, pPresentParameters); +} + +/* IDXGISwapChain2 implementation */ + +/* IDXGISwapChain3 implementation */ + +UINT STDMETHODCALLTYPE CCryDX12SwapChain::GetCurrentBackBufferIndex(void) +{ + DX12_FUNC_LOG + return m_SwapChain->GetCurrentBackBufferIndex(); +} + +HRESULT STDMETHODCALLTYPE CCryDX12SwapChain::ResizeBuffers1(UINT BufferCount, UINT Width, UINT Height, + DXGI_FORMAT NewFormat, UINT SwapChainFlags, + const UINT* pCreationNodeMask, IUnknown* const* ppPresentQueue) +{ + DX12_FUNC_LOG + + ID3D11RenderTargetView* views[8] = {}; + + m_Device->GetDeviceContext()->OMSetRenderTargets(8, views, nullptr); + m_Device->GetDeviceContext()->SubmitAllCommands(true); + m_Device->GetDeviceContext()->WaitForIdle(); + + ForfeitBuffers(); + + m_Device->GetDX12Device()->FlushReleaseHeap(DX12::Device::ResourceReleasePolicy::Immediate); + + HRESULT res = m_SwapChain->GetDXGISwapChain()->ResizeBuffers1(BufferCount, Width, Height, NewFormat, SwapChainFlags, pCreationNodeMask, ppPresentQueue); + if (res == S_OK) + { + AcquireBuffers(); + } + + return res; +} diff --git a/src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12SwapChain.hpp b/src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12SwapChain.hpp new file mode 100644 index 00000000000..b0d5b31cdf2 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/GI/CCryDX12SwapChain.hpp @@ -0,0 +1,279 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. + +#pragma once +#ifndef __CCRYDX12GISWAPCHAIN__ +#define __CCRYDX12GISWAPCHAIN__ + +#include "DX12/CCryDX12Object.hpp" +#include "DX12/Resource/Texture/CCryDX12Texture2D.hpp" + +#include "DX12/API/DX12SwapChain.hpp" + +#include + +class CCryDX12SwapChain + : public CCryDX12GIObject +{ +public: + DX12_OBJECT(CCryDX12SwapChain, CCryDX12GIObject); + + static CCryDX12SwapChain* Create(CCryDX12Device* pDevice, IDXGIFactory4* factory, DXGI_SWAP_CHAIN_DESC* pDesc); + + virtual ~CCryDX12SwapChain(); + + IC CCryDX12Device* GetDevice() const + { + return m_Device; + } + + IC IDXGISwapChain3* GetDXGISwapChain() const + { + return m_SwapChain->GetDXGISwapChain(); + } + + IC DX12::SwapChain* GetDX12SwapChain() + { + return m_SwapChain; + } + + #pragma region /* IDXGIDeviceSubObject implementation */ + + virtual HRESULT STDMETHODCALLTYPE GetDevice( + _In_ REFIID riid, + _Out_ void** ppDevice) final; + + #pragma endregion + + #pragma region /* IDXGISwapChain implementation */ + + virtual HRESULT STDMETHODCALLTYPE Present( + UINT SyncInterval, + UINT Flags) final; + + virtual HRESULT STDMETHODCALLTYPE GetBuffer( + UINT Buffer, + _In_ REFIID riid, + _Out_ void** ppSurface) final; + + virtual HRESULT STDMETHODCALLTYPE SetFullscreenState( + BOOL Fullscreen, + _In_opt_ IDXGIOutput* pTarget) final; + + virtual HRESULT STDMETHODCALLTYPE GetFullscreenState( + _Out_opt_ BOOL* pFullscreen, + _Out_opt_ IDXGIOutput** ppTarget) final; + + virtual HRESULT STDMETHODCALLTYPE GetDesc( + _Out_ DXGI_SWAP_CHAIN_DESC* pDesc) final; + + virtual HRESULT STDMETHODCALLTYPE ResizeBuffers( + UINT BufferCount, + UINT Width, + UINT Height, + DXGI_FORMAT NewFormat, + UINT SwapChainFlags) final; + + virtual HRESULT STDMETHODCALLTYPE ResizeTarget( + _In_ const DXGI_MODE_DESC* pNewTargetParameters) final; + + virtual HRESULT STDMETHODCALLTYPE GetContainingOutput( + _Out_ IDXGIOutput** ppOutput) final; + + virtual HRESULT STDMETHODCALLTYPE GetFrameStatistics( + _Out_ DXGI_FRAME_STATISTICS* pStats) final; + + virtual HRESULT STDMETHODCALLTYPE GetLastPresentCount( + _Out_ UINT* pLastPresentCount) final; + + #pragma endregion + +#pragma region /* IDXGISwapChain1 implementation */ + + virtual HRESULT STDMETHODCALLTYPE GetDesc1( + /* [annotation][out] */ + _Out_ DXGI_SWAP_CHAIN_DESC1* pDesc) final + { + return m_SwapChain->GetDXGISwapChain()->GetDesc1(pDesc); + } + + virtual HRESULT STDMETHODCALLTYPE GetFullscreenDesc( + /* [annotation][out] */ + _Out_ DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc) final + { + return m_SwapChain->GetDXGISwapChain()->GetFullscreenDesc(pDesc); + } + + virtual HRESULT STDMETHODCALLTYPE GetHwnd( + /* [annotation][out] */ + _Out_ HWND* pHwnd) final + { + return m_SwapChain->GetDXGISwapChain()->GetHwnd(pHwnd); + } + + virtual HRESULT STDMETHODCALLTYPE GetCoreWindow( + /* [annotation][in] */ + _In_ REFIID refiid, + /* [annotation][out] */ + _COM_Outptr_ void** ppUnk) final + { + return m_SwapChain->GetDXGISwapChain()->GetCoreWindow(refiid, ppUnk); + } + + virtual HRESULT STDMETHODCALLTYPE Present1( + /* [in] */ UINT SyncInterval, + /* [in] */ UINT PresentFlags, + /* [annotation][in] */ + _In_ const DXGI_PRESENT_PARAMETERS* pPresentParameters) final; + + virtual BOOL STDMETHODCALLTYPE IsTemporaryMonoSupported() final + { + return m_SwapChain->GetDXGISwapChain()->IsTemporaryMonoSupported(); + } + + virtual HRESULT STDMETHODCALLTYPE GetRestrictToOutput( + /* [annotation][out] */ + _Out_ IDXGIOutput** ppRestrictToOutput) final + { + return m_SwapChain->GetDXGISwapChain()->GetRestrictToOutput(ppRestrictToOutput); + } + + virtual HRESULT STDMETHODCALLTYPE SetBackgroundColor( + /* [annotation][in] */ + _In_ const DXGI_RGBA* pColor) final + { + return m_SwapChain->GetDXGISwapChain()->SetBackgroundColor(pColor); + } + + virtual HRESULT STDMETHODCALLTYPE GetBackgroundColor( + /* [annotation][out] */ + _Out_ DXGI_RGBA* pColor) final + { + return m_SwapChain->GetDXGISwapChain()->GetBackgroundColor(pColor); + } + + virtual HRESULT STDMETHODCALLTYPE SetRotation( + /* [annotation][in] */ + _In_ DXGI_MODE_ROTATION Rotation) final + { + return m_SwapChain->GetDXGISwapChain()->SetRotation(Rotation); + } + + virtual HRESULT STDMETHODCALLTYPE GetRotation( + /* [annotation][out] */ + _Out_ DXGI_MODE_ROTATION* pRotation) final + { + return m_SwapChain->GetDXGISwapChain()->GetRotation(pRotation); + } + +#pragma endregion + +#pragma region /* IDXGISwapChain2 implementation */ + + virtual HRESULT STDMETHODCALLTYPE SetSourceSize(UINT Width, UINT Height) final + { + return m_SwapChain->GetDXGISwapChain()->SetSourceSize(Width, Height); + } + + virtual HRESULT STDMETHODCALLTYPE GetSourceSize( + /* [annotation][out] */ + _Out_ UINT* pWidth, + /* [annotation][out] */ + _Out_ UINT* pHeight) final + { + return m_SwapChain->GetDXGISwapChain()->GetSourceSize(pWidth, pHeight); + } + + virtual HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(UINT MaxLatency) final + { + return m_SwapChain->GetDXGISwapChain()->SetMaximumFrameLatency(MaxLatency); + } + + virtual HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency( + /* [annotation][out] */ + _Out_ UINT* pMaxLatency) final + { + return m_SwapChain->GetDXGISwapChain()->GetMaximumFrameLatency(pMaxLatency); + } + + virtual HANDLE STDMETHODCALLTYPE GetFrameLatencyWaitableObject() final + { + return m_SwapChain->GetDXGISwapChain()->GetFrameLatencyWaitableObject(); + } + + virtual HRESULT STDMETHODCALLTYPE SetMatrixTransform(const DXGI_MATRIX_3X2_F* pMatrix) final + { + return m_SwapChain->GetDXGISwapChain()->SetMatrixTransform(pMatrix); + } + + virtual HRESULT STDMETHODCALLTYPE GetMatrixTransform( + /* [annotation][out] */ + _Out_ DXGI_MATRIX_3X2_F* pMatrix) final + { + return m_SwapChain->GetDXGISwapChain()->GetMatrixTransform(pMatrix); + } + +#pragma endregion + +#pragma region /* IDXGISwapChain3 implementation */ + + virtual UINT STDMETHODCALLTYPE GetCurrentBackBufferIndex() final; + + virtual HRESULT STDMETHODCALLTYPE CheckColorSpaceSupport( + /* [annotation][in] */ + _In_ DXGI_COLOR_SPACE_TYPE ColorSpace, + /* [annotation][out] */ + _Out_ UINT* pColorSpaceSupport) final + { + return m_SwapChain->GetDXGISwapChain()->CheckColorSpaceSupport(ColorSpace, pColorSpaceSupport); + } + + virtual HRESULT STDMETHODCALLTYPE SetColorSpace1( + /* [annotation][in] */ + _In_ DXGI_COLOR_SPACE_TYPE ColorSpace) final + { + return m_SwapChain->GetDXGISwapChain()->SetColorSpace1(ColorSpace); + } + + virtual HRESULT STDMETHODCALLTYPE ResizeBuffers1( + /* [annotation][in] */ + _In_ UINT BufferCount, + /* [annotation][in] */ + _In_ UINT Width, + /* [annotation][in] */ + _In_ UINT Height, + /* [annotation][in] */ + _In_ DXGI_FORMAT Format, + /* [annotation][in] */ + _In_ UINT SwapChainFlags, + /* [annotation][in] */ + _In_reads_(BufferCount) const UINT* pCreationNodeMask, + /* [annotation][in] */ + _In_reads_(BufferCount) IUnknown* const* ppPresentQueue) final; + +#pragma endregion + +protected: + CCryDX12SwapChain(CCryDX12Device* pDevice, DX12::SwapChain* pSwapChain); + +private: + void AcquireBuffers(); + void ForfeitBuffers(); + + CCryDX12Device* m_Device; + + DX12::SwapChain* m_SwapChain; + std::vector<_smart_ptr> m_BackBuffers; +}; + +#endif // __CCRYDX12GISWAPCHAIN__ diff --git a/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-mpmc-bounded.hpp b/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-mpmc-bounded.hpp new file mode 100644 index 00000000000..f051a0abd6f --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-mpmc-bounded.hpp @@ -0,0 +1,189 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +// This is free and unencumbered software released into the public domain. + +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. + +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +// For more information, please refer to + +// Implementation of Dmitry Vyukov's MPMC algorithm +// http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue + + +#ifndef __MPMC_BOUNDED_QUEUE_INCLUDED__ +#define __MPMC_BOUNDED_QUEUE_INCLUDED__ + +#include +#include + +namespace concqueue +{ + template + class mpmc_bounded_queue_t + { + public: + + mpmc_bounded_queue_t(size_t size) + : _size(size) + , _mask(size - 1) + , _buffer(reinterpret_cast(new aligned_node_t[_size])) + , _head_seq(0) + , _tail_seq(0) + { + // make sure it's a power of 2 + assert((_size != 0) && ((_size & (~_size + 1)) == _size)); + + // populate the sequence initial values + for (size_t i = 0; i < _size; ++i) + { + _buffer[i].seq.store(i, std::memory_order_relaxed); + } + } + + ~mpmc_bounded_queue_t() + { + delete[] _buffer; + } + + bool enqueue(const T& data) + { + // _head_seq only wraps at MAX(_head_seq) instead we use a mask to convert the sequence to an array index + // this is why the ring buffer must be a size which is a power of 2. this also allows the sequence to double as a ticket/lock. + size_t head_seq = _head_seq.load(std::memory_order_relaxed); + + for (;; ) + { + node_t* node = &_buffer[head_seq & _mask]; + size_t node_seq = node->seq.load(std::memory_order_acquire); + intptr_t dif = (intptr_t)node_seq - (intptr_t)head_seq; + + // if seq and head_seq are the same then it means this slot is empty + if (dif == 0) + { + // claim our spot by moving head + // if head isn't the same as we last checked then that means someone beat us to the punch + // weak compare is faster, but can return spurious results + // which in this instance is OK, because it's in the loop + if (_head_seq.compare_exchange_weak(head_seq, head_seq + 1, std::memory_order_relaxed)) + { + // set the data + node->data = data; + // increment the sequence so that the tail knows it's accessible + node->seq.store(head_seq + 1, std::memory_order_release); + return true; + } + } + else if (dif < 0) + { + // if seq is less than head seq then it means this slot is full and therefore the buffer is full + return false; + } + else + { + // under normal circumstances this branch should never be taken + head_seq = _head_seq.load(std::memory_order_relaxed); + } + } + + // never taken + return false; + } + + bool dequeue(T& data) + { + size_t tail_seq = _tail_seq.load(std::memory_order_relaxed); + + for (;; ) + { + node_t* node = &_buffer[tail_seq & _mask]; + size_t node_seq = node->seq.load(std::memory_order_acquire); + intptr_t dif = (intptr_t)node_seq - (intptr_t)(tail_seq + 1); + + // if seq and head_seq are the same then it means this slot is empty + if (dif == 0) + { + // claim our spot by moving head + // if head isn't the same as we last checked then that means someone beat us to the punch + // weak compare is faster, but can return spurious results + // which in this instance is OK, because it's in the loop + if (_tail_seq.compare_exchange_weak(tail_seq, tail_seq + 1, std::memory_order_relaxed)) + { + // set the output + data = node->data; + // set the sequence to what the head sequence should be next time around + node->seq.store(tail_seq + _mask + 1, std::memory_order_release); + return true; + } + } + else if (dif < 0) + { + // if seq is less than head seq then it means this slot is full and therefore the buffer is full + return false; + } + else + { + // under normal circumstances this branch should never be taken + tail_seq = _tail_seq.load(std::memory_order_relaxed); + } + } + + // never taken + return false; + } + + private: + + struct node_t + { + T data; + std::atomic seq; + }; + + typedef typename std::aligned_storage::value>::type aligned_node_t; + typedef char cache_line_pad_t[64]; // it's either 32 or 64 so 64 is good enough + + cache_line_pad_t _pad0; + const size_t _size; + const size_t _mask; + node_t* const _buffer; + cache_line_pad_t _pad1; + std::atomic _head_seq; + cache_line_pad_t _pad2; + std::atomic _tail_seq; + cache_line_pad_t _pad3; + + mpmc_bounded_queue_t(const mpmc_bounded_queue_t&) {} + void operator=(const mpmc_bounded_queue_t&) {} + }; +} + +#endif diff --git a/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-mpsc.hpp b/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-mpsc.hpp new file mode 100644 index 00000000000..d36700440a0 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-mpsc.hpp @@ -0,0 +1,118 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +// This is free and unencumbered software released into the public domain. + +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. + +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +// For more information, please refer to + +// C++ implementation of Dmitry Vyukov's non-intrusive lock free unbound MPSC queue +// http://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue + +#ifndef __MPSC_BOUNDED_QUEUE_INCLUDED__ +#define __MPSC_BOUNDED_QUEUE_INCLUDED__ + +#include +#include + +namespace concqueue +{ + template + class mpsc_queue_t + { + public: + + mpsc_queue_t() + : _head(reinterpret_cast(new buffer_node_aligned_t)) + , _tail(_head.load(std::memory_order_relaxed)) + { + buffer_node_t* front = _head.load(std::memory_order_relaxed); + front->next.store(NULL, std::memory_order_relaxed); + } + + ~mpsc_queue_t() + { + T output; + while (this->dequeue(output)) + { + } + buffer_node_t* front = _head.load(std::memory_order_relaxed); + delete front; + } + + bool enqueue(const T& input) + { + buffer_node_t* node = reinterpret_cast(new buffer_node_aligned_t); + node->data = input; + node->next.store(NULL, std::memory_order_relaxed); + + buffer_node_t* prev_head = _head.exchange(node, std::memory_order_acq_rel); + prev_head->next.store(node, std::memory_order_release); + return true; + } + + bool dequeue(T& output) + { + buffer_node_t* tail = _tail.load(std::memory_order_relaxed); + buffer_node_t* next = tail->next.load(std::memory_order_acquire); + + if (next == NULL) + { + return false; + } + + output = next->data; + _tail.store(next, std::memory_order_release); + delete tail; + return true; + } + + + private: + + struct buffer_node_t + { + T data; + std::atomic next; + }; + + typedef typename std::aligned_storage::value>::type buffer_node_aligned_t; + + std::atomic _head; + std::atomic _tail; + + mpsc_queue_t(const mpsc_queue_t&) {} + void operator=(const mpsc_queue_t&) {} + }; +} + +#endif diff --git a/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-spsc-bounded.hpp b/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-spsc-bounded.hpp new file mode 100644 index 00000000000..77ac6ad0c54 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-spsc-bounded.hpp @@ -0,0 +1,123 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +// This is free and unencumbered software released into the public domain. + +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. + +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +// For more information, please refer to + +// Note: +// A combination of the algorithms described by the circular buffers +// documentation found in the Linux kernel, and the bounded MPMC queue +// by Dmitry Vyukov[1]. Implemented in pure C++11. Should work across +// most CPU architectures. +// +// [1] http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue + +#ifndef __SPSC_BOUNDED_QUEUE_INCLUDED__ +#define __SPSC_BOUNDED_QUEUE_INCLUDED__ + +#include +#include + +namespace concqueue +{ + template + class spsc_bounded_queue_t + { + public: + + spsc_bounded_queue_t(size_t size) + : _size(size) + , _mask(size - 1) + , _buffer(reinterpret_cast(new aligned_t[_size + 1])) // need one extra element for a guard + , _head(0) + , _tail(0) + { + // make sure it's a power of 2 + assert((_size != 0) && ((_size & (~_size + 1)) == _size)); + } + + ~spsc_bounded_queue_t() + { + delete[] _buffer; + } + + bool enqueue(T& input) + { + const size_t head = _head.load(std::memory_order_relaxed); + + if (((_tail.load(std::memory_order_acquire) - (head + 1)) & _mask) >= 1) + { + _buffer[head & _mask] = input; + _head.store(head + 1, std::memory_order_release); + return true; + } + return false; + } + + bool dequeue(T& output) + { + const size_t tail = _tail.load(std::memory_order_relaxed); + + if (((_head.load(std::memory_order_acquire) - tail) & _mask) >= 1) + { + output = _buffer[_tail & _mask]; + _tail.store(tail + 1, std::memory_order_release); + return true; + } + return false; + } + + + private: + + typedef typename std::aligned_storage::value>::type aligned_t; + typedef char cache_line_pad_t[64]; + + cache_line_pad_t _pad0; + const size_t _size; + const size_t _mask; + T* const _buffer; + + cache_line_pad_t _pad1; + std::atomic _head; + + cache_line_pad_t _pad2; + std::atomic _tail; + + spsc_bounded_queue_t(const spsc_bounded_queue_t&) {} + void operator=(const spsc_bounded_queue_t&) {} + }; +} + +#endif diff --git a/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-spsc.hpp b/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-spsc.hpp new file mode 100644 index 00000000000..880b53f0848 --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue-spsc.hpp @@ -0,0 +1,121 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. +// This is free and unencumbered software released into the public domain. + +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. + +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +// For more information, please refer to + + +// non-intrusive lock free unbounded SPSC queue +// the algorithm was taken from the blog post below, and converted to C++11 +// http://cbloomrants.blogspot.com/2009/02/02-26-09-low-level-threading-part-51.html + +#ifndef __SPSC_QUEUE_INCLUDED__ +#define __SPSC_QUEUE_INCLUDED__ + +#include + +namespace concqueue +{ + template + class spsc_queue_t + { + public: + + spsc_queue_t() + : _head(reinterpret_cast(new node_aligned_t)) + , _tail(_head) + { + _head->next = NULL; + } + + ~spsc_queue_t() + { + T output; + while (this->dequeue(output)) + { + } + delete _head; + } + + bool enqueue(const T& input) + { + node_t* node = reinterpret_cast(new node_aligned_t); + node->data = input; + node->next = NULL; + + std::atomic_thread_fence(std::memory_order_acq_rel); + _head->next = node; + _head = node; + return true; + } + + bool dequeue(T& output) + { + std::atomic_thread_fence(std::memory_order_consume); + if (!_tail->next) + { + return false; + } + + output = _tail->next->data; + std::atomic_thread_fence(std::memory_order_acq_rel); + _back = _tail; + _tail = _back->next; + + delete _back; + return true; + } + + + private: + + struct node_t + { + node_t* next; + T data; + }; + + typedef typename std::aligned_storage::value>::type node_aligned_t; + + node_t* _head; + char _cache_line[64]; + node_t* _tail; + node_t* _back; + + spsc_queue_t(const spsc_queue_t&) {} + void operator=(const spsc_queue_t&) {} + }; +} + +#endif diff --git a/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue.hpp b/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue.hpp new file mode 100644 index 00000000000..be39e36bd9c --- /dev/null +++ b/src/Layers/xrRenderPC_R5/DX12/Includes/concqueue.hpp @@ -0,0 +1,33 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or +* a third party where indicated. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +// Original file Copyright Crytek GMBH or its affiliates, used under license. +#ifndef __CONC_QUEUE_INCLUDED__ +#define __CONC_QUEUE_INCLUDED__ + +#include "concqueue-mpmc-bounded.hpp" +#include "concqueue-mpsc.hpp" +#include "concqueue-spsc.hpp" +#include "concqueue-spsc-bounded.hpp" + +#define BoundMPMC concqueue::mpmc_bounded_queue_t +#define BoundSPSC concqueue::spsc_bounded_queue_t +#define UnboundMPSC concqueue::mpsc_queue_t +#define UnboundSPSC concqueue::spsc_queue_t + +template