diff --git a/Apps/App.Base/App.Base.vcxproj b/Apps/App.Base/App.Base.vcxproj index c9c83e3..ae09fae 100644 --- a/Apps/App.Base/App.Base.vcxproj +++ b/Apps/App.Base/App.Base.vcxproj @@ -39,7 +39,6 @@ - @@ -171,4 +170,4 @@ - + \ No newline at end of file diff --git a/Apps/App.Base/App.Base.vcxproj.filters b/Apps/App.Base/App.Base.vcxproj.filters index d6943b5..2791261 100644 --- a/Apps/App.Base/App.Base.vcxproj.filters +++ b/Apps/App.Base/App.Base.vcxproj.filters @@ -42,9 +42,6 @@ Header Files - - Header Files - Header Files @@ -117,4 +114,4 @@ Source Files\ECS - + \ No newline at end of file diff --git a/Apps/App.Base/Include/App.Base/ECS/Components/CameraComponent.h b/Apps/App.Base/Include/App.Base/ECS/Components/CameraComponent.h index e28e780..251af57 100644 --- a/Apps/App.Base/Include/App.Base/ECS/Components/CameraComponent.h +++ b/Apps/App.Base/Include/App.Base/ECS/Components/CameraComponent.h @@ -2,18 +2,21 @@ #include "Engine.Core/ECS/Component.h" #include +#include "Engine.RendererDX12/D3DHelpers.h" struct CameraComponent : ComponentTag { float FOV; float NearPlane; float FarPlane; + Matrix ViewProj; + Matrix PrevViewProjNoJitter; bool DirtyFlag; CameraComponent() : DirtyFlag(true), _numFramesDirty(0), _CBufferIndex(0), - FOV(60.0f), NearPlane(0.1f), FarPlane(10000.f) + FOV(60.0f), NearPlane(0.1f), FarPlane(10000.f), ViewProj(Identity4x4()), PrevViewProjNoJitter(Identity4x4()) { } diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index 5cf3cad..bd7cc1b 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -2,23 +2,14 @@ #include "Common/GameTimer.h" #include "Common/Module.h" -#include "Engine.RendererDX12/D3DHelpers.h" -#include "Engine.RendererDX12/GDX12Device.h" -#include "Engine.RendererDX12/GDX12DescriptorHeap.h" -#include "Engine.RendererDX12/GDX12FrameConstants.h" -#include "Engine.RendererDX12/GDX12RootSignature.h" -#include "Engine.RendererDX12/GDX12SwapChain.h" -#include "Engine.RendererDX12/GDX12Texture.h" -#include "Engine.RendererDX12/GDX12Material.h" -#include "Engine.RendererDX12/GDX12GeometryBuffer.h" -#include "Engine.RendererDX12/GDX12RenderCommandRecorder.h" - -#include "Engine.Core/Types/TextureTypes.h" + +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" #include "Engine.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" class SceneManagerModule; class World; +class GDX12SwapChain; struct TransformComponent; struct CameraComponent; @@ -30,9 +21,10 @@ using namespace Engine::Core; struct TransformCompGPUData { - UINT CBufferIndex; - UINT NumFramesDirty; - Matrix World; + UINT CBufferIndex = -1; + UINT NumFramesDirty = -1; + Matrix World = Identity4x4(); + Matrix PrevWorld = Identity4x4(); }; class RenderModule final : public Module @@ -44,19 +36,21 @@ class RenderModule final : public Module void Initialize() override; void Uninitialize() override; - void OnResize() const; + void OnResize(); GDX12Material* GetMaterialByName(const std::string& name); //returns a pointer to a fully initialized structure that you can specify in components GDX12Material* CreateMaterial(const std::string& name); - GDX12Texture* GetTextureByName(const std::string& name); + GPUTexture* GetTextureByName(const std::string& name); //returns a pointer to a fully initialized structure that you can specify in materials - GDX12Texture* CreateTexture(const std::string& name, const Texture* texture); + GPUTexture* CreateTexture(const std::string& name, const Texture* texture); //Uploads Mesh geometry to GPU void SubmitMesh(const Mesh* mesh, MeshHandle handle); + + void SetActiveCamera(CameraComponent* camera); struct WorldRenderSubscriptions { @@ -96,10 +90,18 @@ class RenderModule final : public Module void OnRenderComponentUpdated(World& world, Entity entity, StaticMeshRenderComponent& component); const float GetAspectRatio(); - GDX12RenderCommandRecorder* GetCommandRecorder(); - GDX12FrameConstants* GetCurrentFrameConstants(); - const GPUMesh* GetGPUMesh(MeshHandle handle); - GDX12UploadBuffer* GetIndirectCommandsCache(); + GDX12FrameConstants* GetCurrentPrimaryFrameConstants(); + GDX12FrameConstants* GetCurrentSecondaryFrameConstants(); + const GPUMesh* GetPrimaryGPUMesh(MeshHandle handle); + const GPUMesh* GetSecondaryGPUMesh(MeshHandle handle); + GDX12UploadBuffer* GetPrimaryIndirectCommandsCache(); + GDX12UploadBuffer* GetSecondaryIndirectCommandsCache(); + + uint32_t GetPrimaryPipelineFlags(); + uint32_t GetSecondaryPipelineFlags(); + RenderPipelineCommonData* GetRenderPipelineCommonData(); + bool PrimaryPipelineHasFlag(uint32_t flag); + bool SecondaryPipelineHasFlag(uint32_t flag); protected: void OnUpdate() override; @@ -109,19 +111,18 @@ class RenderModule final : public Module bool ShouldRender() override; private: - void BuildDescHeapsAndBackBuffer(); - void BuildRootSignatures(); - void BuildShaders(); - void BuildPSOs(); - void BuildFrameConstants(); - - void UpdateMainCB(); - void UpdateMaterialCB(); + void BuildBackBuffer(); + void ShareFences(); + void ConfigureRenderPipeline(); + void SetupRenderPasses(); + void InitializeRenderPasses(); void SubscribeToSceneManager(); void UnsubscribeFromSceneManager(); void UnsubscribeFromAllWorlds(); + GDX12Texture* CreateDX12Texture(const std::string& name, GDX12DeviceResources* resources, const Texture* texture); + GameTimer* _timer; Window* _window; @@ -130,42 +131,27 @@ class RenderModule final : public Module std::unordered_map _transformGPUData; std::unordered_map _worldSubscriptions; - - GDX12RenderCommandRecorder _commandRecorder; + RenderPipelineCommonData _RPcommonData; std::unique_ptr _primaryDevice; std::unique_ptr _secondaryDevice; bool _dualGPUMode; - std::unordered_map> _inputLayouts; + GDX12DeviceResources _primaryResources; + GDX12DeviceResources _secondaryResources; + std::unordered_map> _textures; std::unordered_map> _materials; - // All of class members below should probably be put into DeviceResources class, and made for each device - // Since all of these resources are currently existing on _primaryDevice only - std::unique_ptr _geometryBuffer; - - // All heaps created in one high-capacity instance - std::unique_ptr _rtvHeap; - std::unique_ptr _srvuavHeap; - std::unique_ptr _dsvHeap; - - std::vector> _frameConstants; - UINT _currFrameConstantsIndex; - - std::unique_ptr> _IndirectCommandsCache; - - std::unordered_map> _shaders; - std::unordered_map> _PSOs; - std::unordered_map> _rootSignatures; - std::unordered_map > _commandSignatures; - - std::unordered_map> _textures; - // These two resources are made on _primaryDevice only std::unique_ptr _backBuffer; std::unique_ptr _depthStencil; - - std::unique_ptr _opaqueAccumTexture; - std::unique_ptr _transparencyAccumTexture; - std::unique_ptr _transparencyRevealageTexture; + + // Sorted in execution order + std::vector> _primaryRenderPassExecutionList; + std::vector> _secondaryRenderPassExecutionList; + + // Flags that are accumulated from every active RenderPass on the device + // Defines which resources should be uploaded onto respective GPU + uint32_t _primaryPipelineFlags; + uint32_t _secondaryPipelineFlags; }; \ No newline at end of file diff --git a/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h b/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h index 066e49c..fc1b204 100644 --- a/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h +++ b/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h @@ -25,6 +25,11 @@ class GPUDataUpdateSystem final : public System ecs.ForEach( [&ecs, &renderModule, &numFrames](Entity entity, TransformComponent& transform, CameraComponent& camera) { + // Active camera requires constant update due to jittering + auto pipelineCommonData = renderModule->GetRenderPipelineCommonData(); + bool isActiveCamera = pipelineCommonData->ActiveCameraCBufferIndex == camera._CBufferIndex; + if (isActiveCamera) { camera.DirtyFlag = true; } + if (camera.DirtyFlag || transform.DirtyFlag) { camera.DirtyFlag = false; @@ -33,6 +38,8 @@ class GPUDataUpdateSystem final : public System if (camera._numFramesDirty > 0) { + GDX12CameraConstants objConstants; + Vector3 CameraLocation = transform.Location; Vector3 CameraRotation = transform.Rotation; float FOV = DirectX::XMConvertToRadians(camera.FOV); @@ -49,21 +56,62 @@ class GPUDataUpdateSystem final : public System Matrix view = Matrix::CreateLookAt(CameraLocation, CameraTarget, Vector3::Up); //reserved-Z proj matrix - Matrix proj = Matrix::CreatePerspectiveFieldOfView(FOV, renderModule->GetAspectRatio(), + Matrix proj = Matrix::CreatePerspectiveFieldOfView(FOV, renderModule->GetAspectRatio(), camera.NearPlane, camera.FarPlane); const float range = camera.NearPlane / (camera.FarPlane - camera.NearPlane); proj._33 = range; proj._43 = range * camera.FarPlane; - GDX12CameraConstants objConstants; + Matrix unjitteredViewProj = view * proj; + + XMStoreFloat4x4(&objConstants.ViewProjNoJitter, XMMatrixTranspose(unjitteredViewProj)); + objConstants.PrevViewProjNoJitter = camera.PrevViewProjNoJitter; + XMStoreFloat4x4(&camera.PrevViewProjNoJitter, XMMatrixTranspose(unjitteredViewProj)); + + + pipelineCommonData->CameraViewToClip = unjitteredViewProj; + pipelineCommonData->ClipToCameraView = pipelineCommonData->CameraViewToClip.Invert(); + + pipelineCommonData->ClipToPrevClip = unjitteredViewProj.Invert() * camera.PrevViewProjNoJitter; + pipelineCommonData->PrevClipToClip = pipelineCommonData->ClipToPrevClip.Invert(); + + // Jitter current camera proj matrix if it is needed + if (isActiveCamera && + (renderModule->PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_JITTER) || + renderModule->SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_JITTER))) + { + static uint32_t frameIndex = 0; + frameIndex++; + + float jitterX = HaltonSequence(frameIndex, 2) - 0.5f; + float jitterY = HaltonSequence(frameIndex, 3) - 0.5f; + float inputWidth = static_cast(pipelineCommonData->DownscaledWidth); + float inputHeight = static_cast(pipelineCommonData->DownscaledHeight); + proj._31 += jitterX * 2.0f / inputWidth; + proj._32 -= jitterY * 2.0f / inputHeight; + pipelineCommonData->ActiveCameraJitterOffsetX = jitterX; + pipelineCommonData->ActiveCameraJitterOffsetY = jitterY; + } + + camera.ViewProj = view * proj; + XMStoreFloat4x4(&objConstants.ViewProj, XMMatrixTranspose(view * proj)); XMStoreFloat4x4(&objConstants.View, XMMatrixTranspose(view)); objConstants.CameraLocation = transform.Location; objConstants.NearPlane = camera.NearPlane; objConstants.FarPlane = camera.FarPlane; - auto& CBuffer = renderModule->GetCurrentFrameConstants()->CameraCB; - CBuffer->CopyData(camera._CBufferIndex, objConstants); + if (renderModule->PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_CAMERAS)) + { + auto& CBuffer = renderModule->GetCurrentPrimaryFrameConstants()->CameraCB; + CBuffer->CopyData(camera._CBufferIndex, objConstants); + } + + if (renderModule->SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_CAMERAS)) + { + auto& CBuffer = renderModule->GetCurrentSecondaryFrameConstants()->CameraCB; + CBuffer->CopyData(camera._CBufferIndex, objConstants); + } camera._numFramesDirty--; } @@ -92,9 +140,20 @@ class GPUDataUpdateSystem final : public System GDX12TransformConstants objConstants; XMStoreFloat4x4(&objConstants.WorldMatrix, XMMatrixTranspose(world)); + XMStoreFloat4x4(&objConstants.PrevWorldMatrix, XMMatrixTranspose(GPUData.PrevWorld)); - auto& CBuffer = renderModule->GetCurrentFrameConstants()->TransformCache; - CBuffer->CopyData(GPUData.CBufferIndex, objConstants); + XMStoreFloat4x4(&GPUData.PrevWorld, world); + + if (renderModule->PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) + { + auto& CBuffer = renderModule->GetCurrentPrimaryFrameConstants()->TransformCache; + CBuffer->CopyData(GPUData.CBufferIndex, objConstants); + } + if (renderModule->SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) + { + auto& CBuffer = renderModule->GetCurrentSecondaryFrameConstants()->TransformCache; + CBuffer->CopyData(GPUData.CBufferIndex, objConstants); + } GPUData.NumFramesDirty--; } @@ -103,9 +162,6 @@ class GPUDataUpdateSystem final : public System ecs.ForEach( [&ecs, &renderModule, &numFrames](Entity entity, TransformComponent& transform, StaticMeshRenderComponent& renderer) { - auto& instanceCache = renderModule->GetCurrentFrameConstants()->InstanceCache; - auto indirectCommandsCache = renderModule->GetIndirectCommandsCache(); - auto gpuMesh = renderModule->GetGPUMesh(renderer.MeshHandler); auto& transformGPUData = renderModule->GetTransformGPUData(entity); if (renderer.DirtyFlag || transform.DirtyFlag) @@ -113,45 +169,113 @@ class GPUDataUpdateSystem final : public System renderer.DirtyFlag = false; renderer._numFramesDirty = numFrames; - gpuMesh->CPUMesh->GetBounds().Transform(renderer.Bounds, XMLoadFloat4x4(&transformGPUData.World)); - - for (int i = 0; i < gpuMesh->SubMeshes.size(); i++) + if (renderModule->GetPrimaryPipelineFlags() & RENDER_PASS_FLAG_USE_INSTANCES) { - const auto& subMesh = gpuMesh->SubMeshes[i]; - - GDX12IndirectDrawArgs drawCommand; - drawCommand.IndexCountPerInstance = subMesh.IndexCount; - drawCommand.InstanceCount = 1; - drawCommand.StartIndexLocation = subMesh.StartIndexLocation; - drawCommand.BaseVertexLocation = subMesh.StartVertexLocation; - drawCommand.StartInstanceLocation = renderer._CBufferIndices[i]; - drawCommand.InstanceID = renderer._CBufferIndices[i]; + auto gpuMesh = renderModule->GetPrimaryGPUMesh(renderer.MeshHandler); + gpuMesh->CPUMesh->GetBounds().Transform(renderer.Bounds, XMLoadFloat4x4(&transformGPUData.World)); + auto indirectCommandsCache = renderModule->GetPrimaryIndirectCommandsCache(); + for (int i = 0; i < gpuMesh->SubMeshes.size(); i++) + { + const auto& subMesh = gpuMesh->SubMeshes[i]; + + GDX12IndirectDrawArgs drawCommand; + drawCommand.IndexCountPerInstance = subMesh.IndexCount; + drawCommand.InstanceCount = 1; + drawCommand.StartIndexLocation = subMesh.StartIndexLocation; + drawCommand.BaseVertexLocation = subMesh.StartVertexLocation; + drawCommand.StartInstanceLocation = renderer._CBufferIndices[i]; + drawCommand.InstanceID = renderer._CBufferIndices[i]; + + indirectCommandsCache->CopyData(renderer._CBufferIndices[i], drawCommand); + } + } - indirectCommandsCache->CopyData(renderer._CBufferIndices[i], drawCommand); + if (renderModule->SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) + { + auto gpuMesh = renderModule->GetSecondaryGPUMesh(renderer.MeshHandler); + gpuMesh->CPUMesh->GetBounds().Transform(renderer.Bounds, XMLoadFloat4x4(&transformGPUData.World)); + auto indirectCommandsCache = renderModule->GetSecondaryIndirectCommandsCache(); + for (int i = 0; i < gpuMesh->SubMeshes.size(); i++) + { + const auto& subMesh = gpuMesh->SubMeshes[i]; + + GDX12IndirectDrawArgs drawCommand; + drawCommand.IndexCountPerInstance = subMesh.IndexCount; + drawCommand.InstanceCount = 1; + drawCommand.StartIndexLocation = subMesh.StartIndexLocation; + drawCommand.BaseVertexLocation = subMesh.StartVertexLocation; + drawCommand.StartInstanceLocation = renderer._CBufferIndices[i]; + drawCommand.InstanceID = renderer._CBufferIndices[i]; + + indirectCommandsCache->CopyData(renderer._CBufferIndices[i], drawCommand); + } } } if (renderer._numFramesDirty > 0) { - for (int i = 0; i < gpuMesh->SubMeshes.size(); i++) + if (renderModule->PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) { - const auto& subMesh = gpuMesh->SubMeshes[i]; - const auto& subMeshBounds = gpuMesh->CPUMesh->GetSubMesh(i).Bounds; - - BoundingBox bounds; - subMeshBounds.Transform(bounds, XMLoadFloat4x4(&transformGPUData.World)); - - GDX12InstanceData instanceData; - instanceData.TransformIndex = transformGPUData.CBufferIndex; - instanceData.MaterialIndex = renderer.Materials[subMesh.MaterialIndex]->_CBufferIndex; - instanceData.BoundingBoxCenter = bounds.Center; - instanceData.BoundingBoxExtents = bounds.Extents; - - instanceCache->CopyData(renderer._CBufferIndices[i], instanceData); + auto& instanceCache = renderModule->GetCurrentPrimaryFrameConstants()->InstanceCache; + auto gpuMesh = renderModule->GetPrimaryGPUMesh(renderer.MeshHandler); + for (int i = 0; i < gpuMesh->SubMeshes.size(); i++) + { + const auto& subMesh = gpuMesh->SubMeshes[i]; + const auto& subMeshBounds = gpuMesh->CPUMesh->GetSubMesh(i).Bounds; + + BoundingBox bounds; + subMeshBounds.Transform(bounds, XMLoadFloat4x4(&transformGPUData.World)); + + GDX12InstanceData instanceData; + instanceData.TransformIndex = transformGPUData.CBufferIndex; + instanceData.MaterialIndex = renderer.Materials[subMesh.MaterialIndex]->_CBufferIndex; + instanceData.BoundingBoxCenter = bounds.Center; + instanceData.BoundingBoxExtents = bounds.Extents; + + instanceCache->CopyData(renderer._CBufferIndices[i], instanceData); + } } + if (renderModule->SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) + { + auto& instanceCache = renderModule->GetCurrentSecondaryFrameConstants()->InstanceCache; + auto gpuMesh = renderModule->GetSecondaryGPUMesh(renderer.MeshHandler); + for (int i = 0; i < gpuMesh->SubMeshes.size(); i++) + { + const auto& subMesh = gpuMesh->SubMeshes[i]; + const auto& subMeshBounds = gpuMesh->CPUMesh->GetSubMesh(i).Bounds; + + BoundingBox bounds; + subMeshBounds.Transform(bounds, XMLoadFloat4x4(&transformGPUData.World)); + + GDX12InstanceData instanceData; + instanceData.TransformIndex = transformGPUData.CBufferIndex; + instanceData.MaterialIndex = renderer.Materials[subMesh.MaterialIndex]->_CBufferIndex; + instanceData.BoundingBoxCenter = bounds.Center; + instanceData.BoundingBoxExtents = bounds.Extents; + + instanceCache->CopyData(renderer._CBufferIndices[i], instanceData); + } + } + renderer._numFramesDirty--; } }); } + +private: + static float HaltonSequence(uint32_t index, uint32_t base) + { + float f = 1.0f; + float result = 0.0f; + + while (index > 0) + { + f /= static_cast(base); + result += f * static_cast(index % base); + index = static_cast(floorf(static_cast(index) / static_cast(base))); + } + + return result; + } }; diff --git a/Apps/App.Base/Include/App.Base/Systems/RenderSubmitSystem.h b/Apps/App.Base/Include/App.Base/Systems/RenderSubmitSystem.h deleted file mode 100644 index 001d241..0000000 --- a/Apps/App.Base/Include/App.Base/Systems/RenderSubmitSystem.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "Engine.Core/System.h" -#include "App.Base/ECS/World.h" - -#include "Engine.Core/BenchmarkEngine.h" -#include "App.Base/Modules/RenderModule.h" - -class RenderSubmitSystem final : public System -{ -public: - void Tick(World& world, float dt) override - { - WorldECS& ecs = world.GetECS(); - auto renderModule = BenchmarkEngine::GetLocator().GetModule(); - - CameraComponent* activeCamera = &ecs.Get(world.ActiveCamera); - - auto commandRecorder = renderModule->GetCommandRecorder(); - - commandRecorder->DrawFromCamera(activeCamera->_CBufferIndex); - } -}; diff --git a/Apps/App.Base/src/App.cpp b/Apps/App.Base/src/App.cpp index ec8f6ab..dd382b4 100644 --- a/Apps/App.Base/src/App.cpp +++ b/Apps/App.Base/src/App.cpp @@ -3,6 +3,8 @@ #include #include +#include "Engine.RendererDX12/GDX12StreamlineSDK.h" + using Microsoft::WRL::ComPtr; using namespace std; using namespace DirectX; @@ -60,7 +62,15 @@ App::App(HINSTANCE hInstance) Instance = this; } -App::~App() = default; +App::~App() +{ + //ordering is important + Locator.UnregisterModule(); + Locator.UnregisterModule(); + // can't be put into RenderModule since it is required + // to call it after all module entities are destroyed + GDX12StreamlineSDK::Get().Shutdown(); +} HINSTANCE App::GetAppHandler() const { diff --git a/Apps/App.Base/src/ECS/WorldLoader.cpp b/Apps/App.Base/src/ECS/WorldLoader.cpp index 3c336fe..9eaa8e2 100644 --- a/Apps/App.Base/src/ECS/WorldLoader.cpp +++ b/Apps/App.Base/src/ECS/WorldLoader.cpp @@ -154,7 +154,7 @@ namespace } /// Creates or retrieves a GPU texture backed by a generated solid-color CPU texture. - GDX12Texture* CreateSolidGpuTexture( + GPUTexture* CreateSolidGpuTexture( RenderModule& renderModule, const std::string& textureName, const std::uint8_t red, @@ -165,7 +165,7 @@ namespace { Engine::Core::Texture texture = CreateSingleColorTexture(red, green, blue, alpha, textureType); - GDX12Texture* gpuTexture = renderModule.CreateTexture(textureName, &texture); + GPUTexture* gpuTexture = renderModule.CreateTexture(textureName, &texture); if (gpuTexture == nullptr) { gpuTexture = renderModule.GetTextureByName(textureName); @@ -182,7 +182,7 @@ namespace } /// Creates or retrieves a generated diffuse texture from the imported material diffuse color. - GDX12Texture* CreateDiffuseColorTexture( + GPUTexture* CreateDiffuseColorTexture( RenderModule& renderModule, const std::string& sceneName, const Engine::Core::MeshMaterial& material) @@ -198,9 +198,9 @@ namespace struct SceneDefaultMaterialTextures { - GDX12Texture* FlatNormal = nullptr; - GDX12Texture* White = nullptr; - GDX12Texture* Black = nullptr; + GPUTexture* FlatNormal = nullptr; + GPUTexture* White = nullptr; + GPUTexture* Black = nullptr; [[nodiscard]] bool IsValid() const { @@ -221,11 +221,11 @@ namespace struct MaterialTextureSet { - GDX12Texture* Diffuse = nullptr; - GDX12Texture* Normal = nullptr; - GDX12Texture* Specular = nullptr; - GDX12Texture* Roughness = nullptr; - GDX12Texture* Emissive = nullptr; + GPUTexture* Diffuse = nullptr; + GPUTexture* Normal = nullptr; + GPUTexture* Specular = nullptr; + GPUTexture* Roughness = nullptr; + GPUTexture* Emissive = nullptr; bool HasNormalMap = false; bool HasSpecularMap = false; bool HasRoughnessMap = false; @@ -348,13 +348,13 @@ namespace /// Loads a texture through AssetManager, creates the corresponding GPU texture and caches it by normalized path and semantic type. /// Returns an already created GPU texture when the same source texture is requested again. - GDX12Texture* LoadSceneGpuTexture( + GPUTexture* LoadSceneGpuTexture( RenderModule& renderModule, Engine::Core::AssetManager& assetManager, const std::filesystem::path& texturePath, const Engine::Core::ETextureType textureType, const std::string& sceneName, - std::unordered_map& gpuTexturesByPath) + std::unordered_map& gpuTexturesByPath) { if (texturePath.empty()) { @@ -376,7 +376,7 @@ namespace const std::string textureName = sceneName + "_Texture_" + std::to_string(gpuTexturesByPath.size()); const Engine::Core::Texture typedTexture = texture->WithType(textureType); - GDX12Texture* gpuTexture = renderModule.CreateTexture(textureName, &typedTexture); + GPUTexture* gpuTexture = renderModule.CreateTexture(textureName, &typedTexture); if (gpuTexture == nullptr) { gpuTexture = renderModule.GetTextureByName(textureName); @@ -392,13 +392,13 @@ namespace /// Loads a diffuse texture and packs an optional opacity mask into its alpha channel before GPU upload. /// Falls back to the original diffuse texture if the opacity texture is missing or cannot be merged. - GDX12Texture* LoadSceneDiffuseGpuTexture( + GPUTexture* LoadSceneDiffuseGpuTexture( RenderModule& renderModule, Engine::Core::AssetManager& assetManager, const std::filesystem::path& diffuseTexturePath, const std::filesystem::path& opacityTexturePath, const std::string& sceneName, - std::unordered_map& gpuTexturesByPath) + std::unordered_map& gpuTexturesByPath) { if (diffuseTexturePath.empty()) { @@ -431,7 +431,7 @@ namespace } const std::string textureName = sceneName + "_Texture_" + std::to_string(gpuTexturesByPath.size()); - GDX12Texture* gpuTexture = renderModule.CreateTexture(textureName, mergedTexture.get()); + GPUTexture* gpuTexture = renderModule.CreateTexture(textureName, mergedTexture.get()); if (gpuTexture == nullptr) { gpuTexture = renderModule.GetTextureByName(textureName); @@ -461,7 +461,7 @@ namespace const std::string textureName = sceneName + "_FallbackTexture"; const std::string materialName = sceneName + "_FallbackMaterial"; - GDX12Texture* gpuTexture = renderModule.CreateTexture(textureName, fallbackTexture); + GPUTexture* gpuTexture = renderModule.CreateTexture(textureName, fallbackTexture); if (gpuTexture == nullptr) { gpuTexture = renderModule.GetTextureByName(textureName); @@ -566,7 +566,7 @@ namespace const std::string& sceneName, GDX12Material* fallbackMaterial, const SceneDefaultMaterialTextures& defaultTextures, - std::unordered_map& gpuTexturesByPath) + std::unordered_map& gpuTexturesByPath) { std::vector materialSlots = BuildFallbackMaterialSlots(mesh, fallbackMaterial); const std::vector& materials = mesh.GetMaterials(); @@ -598,28 +598,28 @@ namespace textures.Roughness = defaultTextures.White; textures.Emissive = defaultTextures.Black; - GDX12Texture* normalTexture = LoadSceneGpuTexture(renderModule, assetManager, materials[materialIndex].NormalTexturePath, Engine::Core::ETextureType::Data, sceneName, gpuTexturesByPath); + GPUTexture* normalTexture = LoadSceneGpuTexture(renderModule, assetManager, materials[materialIndex].NormalTexturePath, Engine::Core::ETextureType::Data, sceneName, gpuTexturesByPath); if (normalTexture != nullptr) { textures.Normal = normalTexture; textures.HasNormalMap = true; } - GDX12Texture* specularTexture = LoadSceneGpuTexture(renderModule, assetManager, materials[materialIndex].SpecularTexturePath, Engine::Core::ETextureType::Data, sceneName, gpuTexturesByPath); + GPUTexture* specularTexture = LoadSceneGpuTexture(renderModule, assetManager, materials[materialIndex].SpecularTexturePath, Engine::Core::ETextureType::Data, sceneName, gpuTexturesByPath); if (specularTexture != nullptr) { textures.Specular = specularTexture; textures.HasSpecularMap = true; } - GDX12Texture* roughnessTexture = LoadSceneGpuTexture(renderModule, assetManager, materials[materialIndex].RoughnessTexturePath, Engine::Core::ETextureType::Data, sceneName, gpuTexturesByPath); + GPUTexture* roughnessTexture = LoadSceneGpuTexture(renderModule, assetManager, materials[materialIndex].RoughnessTexturePath, Engine::Core::ETextureType::Data, sceneName, gpuTexturesByPath); if (roughnessTexture != nullptr) { textures.Roughness = roughnessTexture; textures.HasRoughnessMap = true; } - GDX12Texture* emissiveTexture = LoadSceneGpuTexture(renderModule, assetManager, materials[materialIndex].EmissiveTexturePath, Engine::Core::ETextureType::Color, sceneName, gpuTexturesByPath); + GPUTexture* emissiveTexture = LoadSceneGpuTexture(renderModule, assetManager, materials[materialIndex].EmissiveTexturePath, Engine::Core::ETextureType::Color, sceneName, gpuTexturesByPath); if (emissiveTexture != nullptr) { textures.Emissive = emissiveTexture; @@ -649,7 +649,7 @@ namespace Engine::Core::AssetManager& assetManager, const std::filesystem::path& objPath, const std::string& sceneName, - std::unordered_map& gpuTexturesByPath, + std::unordered_map& gpuTexturesByPath, DirectX::BoundingBox& outBounds) { Engine::Core::MeshHandle sceneMeshHandle = {}; @@ -748,7 +748,7 @@ namespace bool loadedAnyObject = false; DirectX::BoundingBox sceneBounds = {}; - std::unordered_map gpuTexturesByPath; + std::unordered_map gpuTexturesByPath; for (const std::filesystem::path& objPath : objPaths) { @@ -808,7 +808,7 @@ bool WorldLoader::LoadFromFile(World& world, const std::filesystem::path& path) if (IsObjPath(path)) { DirectX::BoundingBox sceneBounds = {}; - std::unordered_map gpuTexturesByPath; + std::unordered_map gpuTexturesByPath; if (!LoadObjSceneEntity( world, *renderModule, @@ -1048,6 +1048,7 @@ bool WorldLoader::LoadFromFile(World& world, const std::filesystem::path& path) ); world.ActiveCamera = camera; + renderModule->SetActiveCamera(&camera.GetComponent()); return true; } diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 50f4331..8271d05 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -2,53 +2,50 @@ #include "App.Base/Window.h" #include "App.Base/App.h" -#include "Common/ConsoleVariables.h" -#include "Engine.RendererDX12/GDX12CommandList.h" -#include "Engine.RendererDX12/GDX12CommandQueue.h" -#include "Engine.RendererDX12/GDX12DeviceFactory.h" -#include "Engine.RendererDX12/GDX12ShaderCompiler.h" -#include "Engine.RendererDX12/GDX12TextureResource.h" -#include "Engine.RendererDX12/GDX12Descriptor.h" -#include "App.Base/Modules/SceneManagerModule.h" - -static UINT _numFrameConstants = 3; -static AutoConsoleVariableRef NumFrameConstantVariable( - L"Render.NumFrames", - _numFrameConstants, - L"How many deferred frames was rendered"); +#include "App.Base/Modules/SceneManagerModule.h" +#include "Common/ConsoleVariables.h" -namespace -{ - ETextureSemantic ConvertTextureSemantic(const Engine::Core::ETextureType textureType) - { - switch (textureType) - { - case Engine::Core::ETextureType::Color: - return ETextureSemantic::Color; - case Engine::Core::ETextureType::Data: - return ETextureSemantic::Data; - default: - return ETextureSemantic::Unknown; - } - } -} +#include "Engine.RendererDX12/GDX12SwapChain.h" +#include "Engine.RendererDX12/RenderPasses/GDX12TextureClearPass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12SyncPass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h" RenderModule::RenderModule(Window* window, GameTimer* timer) : - _dualGPUMode(false), _window(window), - _currFrameConstantsIndex(0), _timer(timer) + _dualGPUMode(false), _window(window), _timer(timer), + _primaryPipelineFlags(0), _secondaryPipelineFlags(0) { + _RPcommonData.GameTimer = _timer; } RenderModule::~RenderModule() { _primaryDevice->GetCommandQueue()->Flush(); + if (_dualGPUMode) { _secondaryDevice->GetCommandQueue()->Flush(); } + + for (auto& renderpass : _primaryRenderPassExecutionList) { renderpass->ClearDenendencies(); } + for (auto& renderpass : _secondaryRenderPassExecutionList) { renderpass->ClearDenendencies(); } GDX12ShaderCompiler::Shutdown(); + GDX12DeviceFactory::Reset(); } void RenderModule::Initialize() { + // This value will be later provided by external pipeline config + bool useStreamlineSDK = false; + // Streamline is initialized on the primary device only + if (useStreamlineSDK) { GDX12StreamlineSDK::Get().Initialize(); } + #if defined(DEBUG) || defined(_DEBUG) // Enable the D3D12 debug layer. ComPtr debugController; @@ -57,32 +54,23 @@ void RenderModule::Initialize() #endif _primaryDevice = std::make_unique(); + _primaryDevice->Role = DEVICE_ROLE_PRIMARY; _primaryDevice->Initialize(GDX12DeviceFactory::GetMostPerformantAdapter().Get()); + _primaryResources.Initialize(_primaryDevice.get()); - // TODO: Add find other adapter and use cvar - // if (secondaryDeviceAdapter) - // { - // _secondaryDevice = std::make_unique(); - // _secondaryDevice->Initialize(secondaryDeviceAdapter.Get()); - // - // _dualGPUMode = true; - // } - - _inputLayouts["Default"] = + if (false) { - { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 36, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } - }; - - BuildDescHeapsAndBackBuffer(); - BuildRootSignatures(); - BuildShaders(); - BuildPSOs(); - BuildFrameConstants(); - - _geometryBuffer = std::make_unique(_primaryDevice.get()); + _secondaryDevice = std::make_unique(); + _secondaryDevice->Role = DEVICE_ROLE_SECONDARY; + _secondaryDevice->Initialize(GDX12DeviceFactory::GetDeviceDescriptors()[1].Adapter.Get()); + _secondaryResources.Initialize(_secondaryDevice.get()); + _dualGPUMode = true; + } + + BuildBackBuffer(); + if (_dualGPUMode) { ShareFences(); } + ConfigureRenderPipeline(); + SubscribeToSceneManager(); } @@ -91,7 +79,7 @@ void RenderModule::Uninitialize() UnsubscribeFromSceneManager(); } -void RenderModule::OnResize() const +void RenderModule::OnResize() { _primaryDevice->GetCommandQueue()->Flush(); @@ -101,9 +89,12 @@ void RenderModule::OnResize() const _backBuffer->Resize(width, height); _depthStencil->Resize(width, height); - _opaqueAccumTexture->Resize(width, height); - _transparencyAccumTexture->Resize(width, height); - _transparencyRevealageTexture->Resize(width, height); + _RPcommonData.WindowWidth = width; + _RPcommonData.WindowHeight = height; + if (_RPcommonData.Upscaler) { _RPcommonData.Upscaler->QueryRenderTargetResolution(); } + + for (auto& renderPass : _primaryRenderPassExecutionList) { renderPass->Resize(); } + for (auto& renderPass : _secondaryRenderPassExecutionList) { renderPass->Resize(); } } GDX12Material* RenderModule::GetMaterialByName(const std::string& name) @@ -128,18 +119,32 @@ GDX12Material* RenderModule::CreateMaterial(const std::string& name) _materials[name] = std::unique_ptr(new GDX12Material()); _materials[name]->Name = name; - _materials[name]->_CBufferIndex = _frameConstants[0]->MaterialCache->GetElementCount(); + + if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_MATERIALS) + { + _materials[name]->_CBufferIndex = _primaryResources.FrameConstants[0]->MaterialCache->GetElementCount(); - for (auto& constants : _frameConstants) + for (auto& constants : _primaryResources.FrameConstants) + { + auto& CBuffer = constants->MaterialCache; + CBuffer->Resize(CBuffer->GetElementCount() + 1); + } + } + if (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_MATERIALS) { - auto& CBuffer = constants->MaterialCache; - CBuffer->Resize(CBuffer->GetElementCount() + 1); + _materials[name]->_CBufferIndex = _secondaryResources.FrameConstants[0]->MaterialCache->GetElementCount(); + + for (auto& constants : _secondaryResources.FrameConstants) + { + auto& CBuffer = constants->MaterialCache; + CBuffer->Resize(CBuffer->GetElementCount() + 1); + } } return _materials[name].get(); } -GDX12Texture* RenderModule::GetTextureByName(const std::string& name) +GPUTexture* RenderModule::GetTextureByName(const std::string& name) { auto it = _textures.find(name); if (it != _textures.end()) { return it->second.get(); } @@ -149,17 +154,29 @@ GDX12Texture* RenderModule::GetTextureByName(const std::string& name) return nullptr; } -GDX12Texture* RenderModule::CreateTexture(const std::string& name, const Texture* texture) +GPUTexture* RenderModule::CreateTexture(const std::string& name, const Texture* texture) { if (_textures.find(name) != _textures.end()) { - std::string errorMsg = "ERROR: Texture with name " + name + " already exists in Textures directory.\n"; + std::string errorMsg = "WARNING: Texture with name " + name + " already exists in Textures directory. Texture creation Skipped\n"; OutputDebugStringA(errorMsg.c_str()); return nullptr; } + _textures[name] = std::make_unique(); + _textures[name]->Name = name; + if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_MATERIALS) + { _textures[name]->PrimaryDeviceTexture = CreateDX12Texture(name, &_primaryResources, texture); } + if (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_MATERIALS) + { _textures[name]->SecondaryDeviceTexture = CreateDX12Texture(name, &_secondaryResources, texture); } + + return _textures[name].get(); +} + +GDX12Texture* RenderModule::CreateDX12Texture(const std::string& name, GDX12DeviceResources* resources, const Texture* texture) +{ GDX12TextureDesc desc; - desc.SRV_UAV_Heap = _srvuavHeap.get(); + desc.SRV_UAV_Heap = resources->SRV_UAV_Heap.get(); desc.Format = desc.SRVDesc.Format = texture->GetFormat(); desc.Semantic = ConvertTextureSemantic(texture->GetType()); desc.Width = texture->GetWidth(); @@ -185,7 +202,7 @@ GDX12Texture* RenderModule::CreateTexture(const std::string& name, const Texture desc.SRVDesc.TextureCube.MipLevels = numMipLevels; desc.SRVDesc.TextureCube.MostDetailedMip = 0; desc.SRVDesc.TextureCube.ResourceMinLODClamp = 0.0f; - desc.SRVHeapIndex = _srvuavHeap->GetAvailableIndex(TextureCube_StartIndex, TextureCube_RangeLength); + desc.SRVHeapIndex = resources->SRV_UAV_Heap->GetAvailableIndex(TextureCube_StartIndex, TextureCube_RangeLength); auto texDesc = CD3DX12_RESOURCE_DESC::Tex2D( desc.Format, desc.Width, desc.Height, @@ -194,7 +211,7 @@ GDX12Texture* RenderModule::CreateTexture(const std::string& name, const Texture D3D12_TEXTURE_LAYOUT_UNKNOWN, D3D12_RESOURCE_DIMENSION_TEXTURE2D); - _primaryDevice->GetDevice()->CreateCommittedResource( + resources->Device->GetDevice()->CreateCommittedResource( &defaultHeap, D3D12_HEAP_FLAG_NONE, &texDesc, @@ -210,13 +227,13 @@ GDX12Texture* RenderModule::CreateTexture(const std::string& name, const Texture desc.SRVDesc.Texture2D.MostDetailedMip = 0; desc.SRVDesc.Texture2D.PlaneSlice = 0; desc.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; - desc.SRVHeapIndex = _srvuavHeap->GetAvailableIndex(Texture2D_StartIndex, Texture2D_RangeLength); + desc.SRVHeapIndex = resources->SRV_UAV_Heap->GetAvailableIndex(Texture2D_StartIndex, Texture2D_RangeLength); auto texDesc = CD3DX12_RESOURCE_DESC::Tex2D( desc.Format, desc.Width, desc.Height, numArraySlices, numMipLevels); - _primaryDevice->GetDevice()->CreateCommittedResource( + resources->Device->GetDevice()->CreateCommittedResource( &defaultHeap, D3D12_HEAP_FLAG_NONE, &texDesc, @@ -234,14 +251,14 @@ GDX12Texture* RenderModule::CreateTexture(const std::string& name, const Texture std::vector rowSizes(totalSubresources); auto texDesc = textureResource->GetDesc(); - _primaryDevice->GetDevice()->GetCopyableFootprints( + resources->Device->GetDevice()->GetCopyableFootprints( &texDesc, 0, totalSubresources, 0, footprints.data(), rowCounts.data(), rowSizes.data(), &totalSize); auto uploadDesc = CD3DX12_RESOURCE_DESC::Buffer(totalSize); ComPtr uploadBuffer; - _primaryDevice->GetDevice()->CreateCommittedResource( + resources->Device->GetDevice()->CreateCommittedResource( &uploadHeap, D3D12_HEAP_FLAG_NONE, &uploadDesc, @@ -274,7 +291,7 @@ GDX12Texture* RenderModule::CreateTexture(const std::string& name, const Texture } uploadBuffer->Unmap(0, nullptr); - auto cmdQueue = _primaryDevice->GetCommandQueue(); + auto cmdQueue = resources->Device->GetCommandQueue(); auto cmdList = cmdQueue->GetCommandList(); for (uint32_t arraySlice = 0; arraySlice < numArraySlices; arraySlice++) @@ -309,14 +326,26 @@ GDX12Texture* RenderModule::CreateTexture(const std::string& name, const Texture desc.ExternalResource = textureResource; - _textures[name] = std::make_unique(desc); + resources->Textures[name] = std::make_unique(); + resources->Textures[name]->Initialize(desc); - return _textures[name].get(); + return resources->Textures[name].get(); } void RenderModule::SubmitMesh(const Mesh* mesh, MeshHandle handle) { - _geometryBuffer->AddMesh(mesh, handle); + if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_GEOMETRY) + { _primaryResources.GeometryBuffer->AddMesh(mesh, handle); } + if (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_GEOMETRY) + { _secondaryResources.GeometryBuffer->AddMesh(mesh, handle); } +} + +void RenderModule::SetActiveCamera(CameraComponent* camera) +{ + _RPcommonData.ActiveCameraCBufferIndex = camera->_CBufferIndex; + _RPcommonData.ActiveCameraFOV = camera->FOV; + _RPcommonData.ActiveCameraNearPlane = camera->NearPlane; + _RPcommonData.ActiveCameraFarPlane = camera->FarPlane; } TransformCompGPUData& RenderModule::GetTransformGPUData(Entity entity) @@ -431,31 +460,84 @@ void RenderModule::UnsubscribeFromWorld(World& world) _worldSubscriptions.erase(it); } -GDX12FrameConstants* RenderModule::GetCurrentFrameConstants() +GDX12FrameConstants* RenderModule::GetCurrentPrimaryFrameConstants() { - return _frameConstants[_currFrameConstantsIndex].get(); + return _primaryResources.FrameConstants[_primaryResources.CurrFrameConstantsIndex].get(); } -const GPUMesh* RenderModule::GetGPUMesh(MeshHandle handle) +GDX12FrameConstants* RenderModule::GetCurrentSecondaryFrameConstants() { - return _geometryBuffer->GetGPUMeshByHandle(handle); + return _secondaryResources.FrameConstants[_secondaryResources.CurrFrameConstantsIndex].get(); } -GDX12UploadBuffer* RenderModule::GetIndirectCommandsCache() +const GPUMesh* RenderModule::GetPrimaryGPUMesh(MeshHandle handle) { - return _IndirectCommandsCache.get(); + return _primaryResources.GeometryBuffer->GetGPUMeshByHandle(handle); +} + +const GPUMesh* RenderModule::GetSecondaryGPUMesh(MeshHandle handle) +{ + return _secondaryResources.GeometryBuffer->GetGPUMeshByHandle(handle); +} + +GDX12UploadBuffer* RenderModule::GetPrimaryIndirectCommandsCache() +{ + return _primaryResources.IndirectCommandsCache.get(); +} + +GDX12UploadBuffer* RenderModule::GetSecondaryIndirectCommandsCache() +{ + return _secondaryResources.IndirectCommandsCache.get(); +} + +uint32_t RenderModule::GetPrimaryPipelineFlags() +{ + return _primaryPipelineFlags; +} + +uint32_t RenderModule::GetSecondaryPipelineFlags() +{ + return _secondaryPipelineFlags; +} + +RenderPipelineCommonData* RenderModule::GetRenderPipelineCommonData() +{ + return &_RPcommonData; +} + +bool RenderModule::PrimaryPipelineHasFlag(uint32_t flag) +{ + return _primaryPipelineFlags & flag; +} + +bool RenderModule::SecondaryPipelineHasFlag(uint32_t flag) +{ + return _secondaryPipelineFlags & flag; } void RenderModule::OnTransformComponentCreated(World& world, Entity entity, TransformComponent& component) { TransformCompGPUData gpuData; - gpuData.CBufferIndex = _frameConstants[0]->TransformCache->GetElementCount(); _transformGPUData[entity] = gpuData; - for (auto& constants : _frameConstants) + if (PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) + { + _transformGPUData[entity].CBufferIndex = _primaryResources.FrameConstants[0]->TransformCache->GetElementCount(); + for (auto& constants : _primaryResources.FrameConstants) + { + auto& CBuffer = constants->TransformCache; + CBuffer->Resize(CBuffer->GetElementCount() + 1); + } + } + + if (SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) { - auto& CBuffer = constants->TransformCache; - CBuffer->Resize(CBuffer->GetElementCount() + 1); + _transformGPUData[entity].CBufferIndex = _secondaryResources.FrameConstants[0]->TransformCache->GetElementCount(); + for (auto& constants : _secondaryResources.FrameConstants) + { + auto& CBuffer = constants->TransformCache; + CBuffer->Resize(CBuffer->GetElementCount() + 1); + } } } @@ -470,13 +552,54 @@ void RenderModule::OnTransformComponentUpdated(World& world, Entity entity, Tran void RenderModule::OnCameraComponentCreated(World& world, Entity entity, CameraComponent& component) { - component._CBufferIndex = _frameConstants[0]->CameraCB->GetElementCount(); + if (PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_CAMERAS)) + { + component._CBufferIndex = _primaryResources.FrameConstants[0]->CameraCB->GetElementCount(); + + for (auto& constants : _primaryResources.FrameConstants) + { + auto& CBuffer = constants->CameraCB; + CBuffer->Resize(CBuffer->GetElementCount() + 1); - for (auto& constants : _frameConstants) + constants->CameraVisibilityCommands.push_back(GDX12VisibilityBuffers()); + + auto& buffers = constants->CameraVisibilityCommands[component._CBufferIndex]; + buffers.VisibleOpaqueCommandsCache = std::make_unique>(_primaryDevice.get(), GetPrimaryIndirectCommandsCache()->GetElementCount(), EBufferType::Default, false); + buffers.OpaqueDrawCounter = std::make_unique>(_primaryDevice.get(), 1, EBufferType::Default, false); + buffers.VisibleTransparentCommandsCache = std::make_unique>(_primaryDevice.get(), GetPrimaryIndirectCommandsCache()->GetElementCount(), EBufferType::Default, false); + buffers.TransparentDrawCounter = std::make_unique>(_primaryDevice.get(), 1, EBufferType::Default, false); + + buffers.VisibleOpaqueCommandsCache->CreateUAV(_primaryResources.SRV_UAV_Heap.get(), _primaryResources.SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + buffers.OpaqueDrawCounter->CreateUAV(_primaryResources.SRV_UAV_Heap.get(), _primaryResources.SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + buffers.VisibleTransparentCommandsCache->CreateUAV(_primaryResources.SRV_UAV_Heap.get(), _primaryResources.SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + buffers.TransparentDrawCounter->CreateUAV(_primaryResources.SRV_UAV_Heap.get(), _primaryResources.SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + } + } + + if (SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_CAMERAS)) { - auto& CBuffer = constants->CameraCB; - CBuffer->Resize(CBuffer->GetElementCount() + 1); + component._CBufferIndex = _secondaryResources.FrameConstants[0]->CameraCB->GetElementCount(); + + for (auto& constants : _secondaryResources.FrameConstants) + { + auto& CBuffer = constants->CameraCB; + CBuffer->Resize(CBuffer->GetElementCount() + 1); + + constants->CameraVisibilityCommands.push_back(GDX12VisibilityBuffers()); + + auto& buffers = constants->CameraVisibilityCommands[component._CBufferIndex]; + buffers.VisibleOpaqueCommandsCache = std::make_unique>(_secondaryDevice.get(), GetSecondaryIndirectCommandsCache()->GetElementCount(), EBufferType::Default, false); + buffers.OpaqueDrawCounter = std::make_unique>(_secondaryDevice.get(), 1, EBufferType::Default, false); + buffers.VisibleTransparentCommandsCache = std::make_unique>(_secondaryDevice.get(), GetSecondaryIndirectCommandsCache()->GetElementCount(), EBufferType::Default, false); + buffers.TransparentDrawCounter = std::make_unique>(_secondaryDevice.get(), 1, EBufferType::Default, false); + + buffers.VisibleOpaqueCommandsCache->CreateUAV(_secondaryResources.SRV_UAV_Heap.get(), _secondaryResources.SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + buffers.OpaqueDrawCounter->CreateUAV(_secondaryResources.SRV_UAV_Heap.get(), _secondaryResources.SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + buffers.VisibleTransparentCommandsCache->CreateUAV(_secondaryResources.SRV_UAV_Heap.get(), _secondaryResources.SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + buffers.TransparentDrawCounter->CreateUAV(_secondaryResources.SRV_UAV_Heap.get(), _secondaryResources.SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + } } + } void RenderModule::OnCameraComponentDestroyed(World& world, Entity entity, CameraComponent& component) @@ -489,21 +612,48 @@ void RenderModule::OnCameraComponentUpdated(World& world, Entity entity, CameraC void RenderModule::OnRenderComponentCreated(World& world, Entity entity, StaticMeshRenderComponent& component) { - auto& MeshGPUData = _geometryBuffer->_meshCache[component.MeshHandler.GetValue()]; - - for (int i = 0; i < MeshGPUData->SubMeshes.size(); i++) + if (PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) { - component._CBufferIndices.push_back(_frameConstants[0]->InstanceCache->GetElementCount()); - _IndirectCommandsCache->Resize(_IndirectCommandsCache->GetElementCount() + 1); - - for (auto& constants : _frameConstants) + auto& MeshGPUData = _primaryResources.GeometryBuffer->_meshCache[component.MeshHandler.GetValue()]; + for (int i = 0; i < MeshGPUData->SubMeshes.size(); i++) { - auto& CBuffer = constants->InstanceCache; - CBuffer->Resize(CBuffer->GetElementCount() + 1); - constants->VisibleOpaqueCommandsCache->Resize(constants->VisibleOpaqueCommandsCache->GetElementCount() + 1); - constants->VisibleTransparentCommandsCache->Resize(constants->VisibleTransparentCommandsCache->GetElementCount() + 1); + component._CBufferIndices.push_back(_primaryResources.FrameConstants[0]->InstanceCache->GetElementCount()); + _primaryResources.IndirectCommandsCache->Resize(_primaryResources.IndirectCommandsCache->GetElementCount() + 1); + + for (auto& constants : _primaryResources.FrameConstants) + { + auto& CBuffer = constants->InstanceCache; + CBuffer->Resize(CBuffer->GetElementCount() + 1); + + for (auto& buffers : constants->CameraVisibilityCommands) + { + buffers.VisibleOpaqueCommandsCache->Resize(buffers.VisibleOpaqueCommandsCache->GetElementCount() + 1); + buffers.VisibleTransparentCommandsCache->Resize(buffers.VisibleTransparentCommandsCache->GetElementCount() + 1); + } + } } + } + + if (SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) + { + auto& MeshGPUData = _secondaryResources.GeometryBuffer->_meshCache[component.MeshHandler.GetValue()]; + for (int i = 0; i < MeshGPUData->SubMeshes.size(); i++) + { + component._CBufferIndices.push_back(_secondaryResources.FrameConstants[0]->InstanceCache->GetElementCount()); + _secondaryResources.IndirectCommandsCache->Resize(_secondaryResources.IndirectCommandsCache->GetElementCount() + 1); + + for (auto& constants : _secondaryResources.FrameConstants) + { + auto& CBuffer = constants->InstanceCache; + CBuffer->Resize(CBuffer->GetElementCount() + 1); + for (auto& buffers : constants->CameraVisibilityCommands) + { + buffers.VisibleOpaqueCommandsCache->Resize(buffers.VisibleOpaqueCommandsCache->GetElementCount() + 1); + buffers.VisibleTransparentCommandsCache->Resize(buffers.VisibleTransparentCommandsCache->GetElementCount() + 1); + } + } + } } } @@ -520,186 +670,104 @@ const float RenderModule::GetAspectRatio() return _window->GetAspectRatio(); } -GDX12RenderCommandRecorder* RenderModule::GetCommandRecorder() -{ - return &_commandRecorder; -} - void RenderModule::OnUpdate() { - _currFrameConstantsIndex = (_currFrameConstantsIndex + 1) % NumFrameConstantVariable.GetValue(); + uint16_t width, height; + _window->GetWindowSize(width, height); + + auto consoleModule = BenchmarkEngine::GetLocator().GetModule(); + IConsoleVariable* ICVNumframes; + consoleModule->TryFindConsoleVariable(L"Render.NumFrames", ICVNumframes); + int numFrames = ICVNumframes->GetInt(); + + //sync & update Primary Device + _primaryResources.CurrFrameConstantsIndex = (_primaryResources.CurrFrameConstantsIndex + 1) % numFrames; auto cmdQueue = _primaryDevice->GetCommandQueue(); - auto& frameConsts = _frameConstants[_currFrameConstantsIndex]; + auto& frameConsts = _primaryResources.FrameConstants[_primaryResources.CurrFrameConstantsIndex]; if (frameConsts->FenceValue > cmdQueue->GetFence()->GetCompletedValue()) { - cmdQueue->WaitForFenceValue(frameConsts->FenceValue); + cmdQueue->CPUWaitForFenceValue(frameConsts->FenceValue); } - UpdateMainCB(); - UpdateMaterialCB(); + _primaryResources.UpdateMainCB(width, height, _timer); + if (PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_MATERIALS)) + { _primaryResources.UpdateMaterialCB(_materials); } + + // same for SecondaryDevice + if (_dualGPUMode) + { + _secondaryResources.CurrFrameConstantsIndex = (_secondaryResources.CurrFrameConstantsIndex + 1) % numFrames; + + auto cmdQueue = _secondaryDevice->GetCommandQueue(); + auto& frameConsts = _secondaryResources.FrameConstants[_secondaryResources.CurrFrameConstantsIndex]; + + if (frameConsts->FenceValue > cmdQueue->GetFence()->GetCompletedValue()) + { + cmdQueue->CPUWaitForFenceValue(frameConsts->FenceValue); + } + + _secondaryResources.UpdateMainCB(width, height, _timer); + if (SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_MATERIALS)) + { _secondaryResources.UpdateMaterialCB(_materials); } + } } void RenderModule::OnRender() { - auto cmdQueue = _primaryDevice->GetCommandQueue(); - - cmdQueue->Flush(); - - auto cmdList = cmdQueue->GetCommandList(); - auto CurrentBackBuffer = _backBuffer->GetCurrentBuffer(); - auto& CurrentFrameConsts = _frameConstants[_currFrameConstantsIndex]; - - cmdList->BeginPixEvent("Clear Back Buffer", Colors::Aqua); - cmdList->SetViewport(_backBuffer->GetViewport()); - cmdList->SetScissorRect(_backBuffer->GetScissorRect()); - cmdList->EnhancedTextureBarrier({ CurrentBackBuffer->GetResource()->GetRenderTargetEnhBarrier() }); - cmdList->ResourceBarrier({ _depthStencil->GetResource()->GetDepthWriteBarrier() }); - cmdList->SetRenderTargets({ CurrentBackBuffer }, _depthStencil.get()); - cmdList->ClearRenderTargetView(CurrentBackBuffer); - cmdList->ClearDepthStencilView(_depthStencil.get()); - cmdList->EndPixEvent(); - - cmdList->BeginPixEvent("GPU Mesh Culling", Colors::Blue); - - cmdList->ResourceBarrier({ - CurrentFrameConsts->VisibleOpaqueCommandsCache->GetResource().GetUnorderedAccessBarrier(), - CurrentFrameConsts->OpaqueDrawCounter->GetResource().GetUnorderedAccessBarrier(), - CurrentFrameConsts->VisibleTransparentCommandsCache->GetResource().GetUnorderedAccessBarrier(), - CurrentFrameConsts->TransparentDrawCounter->GetResource().GetUnorderedAccessBarrier() }); - - cmdList->SetComputeRootSignature(_rootSignatures["BufferClear"].get()); - cmdList->SetPipelineState(_PSOs["BufferClear"]); - cmdList->SetDescriptorHeaps({ _srvuavHeap.get() }); - //should probably make this into a foreach or clear multiple counters per dispatch - cmdList->SetComputeUAV(0, CurrentFrameConsts->OpaqueDrawCounter->GetUAV()->GPUHandle); - cmdList->Dispatch(1, 1, 1); - cmdList->SetComputeUAV(0, CurrentFrameConsts->TransparentDrawCounter->GetUAV()->GPUHandle); - cmdList->Dispatch(1, 1, 1); - - cmdList->SetComputeRootSignature(_rootSignatures["Culling"].get()); - cmdList->SetPipelineState(_PSOs["Culling"]); - cmdList->SetDescriptorHeaps({ _srvuavHeap.get() }); - cmdList->SetComputeRootConstantBufferView(0, CurrentFrameConsts->CameraCB-> - GetElementAddress(_commandRecorder._cameraCBIndex)); - cmdList->SetComputeSRV(0, CurrentFrameConsts->InstanceCache->GetSRV()->GPUHandle); - cmdList->SetComputeSRV(1, _IndirectCommandsCache->GetSRV()->GPUHandle); - cmdList->SetComputeSRV(2, CurrentFrameConsts->MaterialCache->GetSRV()->GPUHandle); - cmdList->SetComputeUAV(0, CurrentFrameConsts->VisibleOpaqueCommandsCache->GetUAV()->GPUHandle); - cmdList->SetComputeUAV(1, CurrentFrameConsts->OpaqueDrawCounter->GetUAV()->GPUHandle); - cmdList->SetComputeUAV(2, CurrentFrameConsts->VisibleTransparentCommandsCache->GetUAV()->GPUHandle); - cmdList->SetComputeUAV(3, CurrentFrameConsts->TransparentDrawCounter->GetUAV()->GPUHandle); - cmdList->Dispatch((_IndirectCommandsCache->GetElementCount() + 63) / 64, 1, 1); - - cmdList->ResourceBarrier({ - CurrentFrameConsts->VisibleOpaqueCommandsCache->GetResource().GetUAVBarrier(), - CurrentFrameConsts->OpaqueDrawCounter->GetResource().GetUAVBarrier(), - CurrentFrameConsts->VisibleOpaqueCommandsCache->GetResource().GetIndirectArgsBarrier(), - CurrentFrameConsts->OpaqueDrawCounter->GetResource().GetIndirectArgsBarrier(), - CurrentFrameConsts->VisibleTransparentCommandsCache->GetResource().GetIndirectArgsBarrier(), - CurrentFrameConsts->TransparentDrawCounter->GetResource().GetIndirectArgsBarrier() }); - cmdList->EndPixEvent(); - - - cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); - cmdList->SetGraphicsRootSignature(_rootSignatures["OpaquePass"].get()); - cmdList->SetPipelineState(_PSOs["OpaquePass"]); - cmdList->SetGraphicsRootConstantBufferView(1, CurrentFrameConsts->MainCB->GetElementAddress(0)); - cmdList->SetGraphicsRootConstantBufferView(2, CurrentFrameConsts->CameraCB-> - GetElementAddress(_commandRecorder._cameraCBIndex)); - cmdList->EnhancedTextureBarrier({ _opaqueAccumTexture->GetResource()->GetRenderTargetEnhBarrier() }); - cmdList->SetRenderTargets({ _opaqueAccumTexture.get() }, _depthStencil.get()); - cmdList->ClearRenderTargetView(_opaqueAccumTexture.get()); - cmdList->SetGeometryBuffer(_geometryBuffer.get()); - cmdList->SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - cmdList->SetDescriptorHeaps({ _srvuavHeap.get() }); - cmdList->SetGraphicsSRV(0, CurrentFrameConsts->MaterialCache->GetSRV()->GPUHandle); - cmdList->SetGraphicsSRV(1, CurrentFrameConsts->TransformCache->GetSRV()->GPUHandle); - cmdList->SetGraphicsSRV(2, CurrentFrameConsts->InstanceCache->GetSRV()->GPUHandle); - cmdList->SetGraphicsSRV(3, _srvuavHeap->GetGPUHandle(Texture2D_StartIndex)); - cmdList->ExecuteIndirect(_commandSignatures["OpaquePass"].Get(), _IndirectCommandsCache->GetElementCount(), - CurrentFrameConsts->VisibleOpaqueCommandsCache->GetResource().D3DResource.Get(), 0, - CurrentFrameConsts->OpaqueDrawCounter->GetResource().D3DResource.Get(), 0); - cmdList->EnhancedTextureBarrier({ _opaqueAccumTexture->GetResource()->GetPixelShaderResourceEnhBarrier() }); - cmdList->EndPixEvent(); - - cmdList->BeginPixEvent("Transparent Render Pass", Colors::Aqua); - cmdList->SetGraphicsRootSignature(_rootSignatures["OpaquePass"].get()); - cmdList->SetPipelineState(_PSOs["TransparentPass"]); - cmdList->SetGraphicsRootConstantBufferView(1, CurrentFrameConsts->MainCB->GetElementAddress(0)); - cmdList->SetGraphicsRootConstantBufferView(2, CurrentFrameConsts->CameraCB-> - GetElementAddress(_commandRecorder._cameraCBIndex)); - cmdList->EnhancedTextureBarrier({ _transparencyAccumTexture->GetResource()->GetRenderTargetEnhBarrier(), - _transparencyRevealageTexture->GetResource()->GetRenderTargetEnhBarrier() }); - - cmdList->SetRenderTargets({ _transparencyAccumTexture.get(), _transparencyRevealageTexture.get() }, - _depthStencil.get()); - cmdList->ClearRenderTargetView(_transparencyAccumTexture.get()); - cmdList->ClearRenderTargetView(_transparencyRevealageTexture.get()); - - cmdList->SetGeometryBuffer(_geometryBuffer.get()); - cmdList->SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - cmdList->SetDescriptorHeaps({ _srvuavHeap.get() }); - cmdList->SetGraphicsSRV(0, CurrentFrameConsts->MaterialCache->GetSRV()->GPUHandle); - cmdList->SetGraphicsSRV(1, CurrentFrameConsts->TransformCache->GetSRV()->GPUHandle); - cmdList->SetGraphicsSRV(2, CurrentFrameConsts->InstanceCache->GetSRV()->GPUHandle); - cmdList->SetGraphicsSRV(3, _srvuavHeap->GetGPUHandle(Texture2D_StartIndex)); - cmdList->ExecuteIndirect(_commandSignatures["OpaquePass"].Get(), _IndirectCommandsCache->GetElementCount(), - CurrentFrameConsts->VisibleTransparentCommandsCache->GetResource().D3DResource.Get(), 0, - CurrentFrameConsts->TransparentDrawCounter->GetResource().D3DResource.Get(), 0); - cmdList->EnhancedTextureBarrier({ _transparencyAccumTexture->GetResource()->GetPixelShaderResourceEnhBarrier(), - _transparencyRevealageTexture->GetResource()->GetPixelShaderResourceEnhBarrier() }); - cmdList->EndPixEvent(); - - - cmdList->BeginPixEvent("Composition Render Pass", Colors::Bisque); - cmdList->SetGraphicsRootSignature(_rootSignatures["CompositionPass"].get()); - cmdList->SetPipelineState(_PSOs["CompositionPass"]); - cmdList->SetRenderTargets({ CurrentBackBuffer }, _depthStencil.get()); - cmdList->SetDescriptorHeaps({ _srvuavHeap.get() }); - cmdList->SetGraphicsSRV(0, _opaqueAccumTexture->GetSRV()->GPUHandle); - cmdList->SetGraphicsSRV(1, _transparencyAccumTexture->GetSRV()->GPUHandle); - cmdList->SetGraphicsSRV(2, _transparencyRevealageTexture->GetSRV()->GPUHandle); - cmdList->GetCommandList()->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - cmdList->GetCommandList()->DrawInstanced(3, 1, 0, 0); - cmdList->EndPixEvent(); - - cmdList->EnhancedTextureBarrier({ CurrentBackBuffer->GetResource()->GetPresentEnhBarrier() }); - cmdList->ResourceBarrier({ _depthStencil->GetResource()->GetCommonBarrier() }); + auto primarycmdQueue = _primaryDevice->GetCommandQueue(); + auto primarycmdList = primarycmdQueue->GetCommandList(); + auto primaryCurrentFrameConsts = GetCurrentPrimaryFrameConstants(); + for (auto& renderPass : _primaryRenderPassExecutionList) + { + if (renderPass->GetFlagValue(RENDER_PASS_FLAG_SYNC_DEVICES) && _dualGPUMode) + { + primarycmdQueue->ExecuteCommandList(primarycmdList); + primarycmdQueue->WaitForOtherFence(primarycmdList->FenceValue); + primarycmdList = primarycmdQueue->GetCommandList(); + } + else { renderPass->Execute(primarycmdList); } + } + primarycmdQueue->ExecuteCommandList(primarycmdList); + primaryCurrentFrameConsts->FenceValue = primarycmdList->FenceValue; - cmdQueue->ExecuteCommandList(cmdList); - CurrentFrameConsts->FenceValue = cmdList->FenceValue; + if (_dualGPUMode) + { + auto secondarycmdQueue = _secondaryDevice->GetCommandQueue(); + auto secondarycmdList = secondarycmdQueue->GetCommandList(); + auto secondaryCurrentFrameConsts = GetCurrentSecondaryFrameConstants(); + for (auto& renderPass : _secondaryRenderPassExecutionList) + { + if (renderPass->GetFlagValue(RENDER_PASS_FLAG_SYNC_DEVICES)) + { + secondarycmdQueue->ExecuteCommandList(secondarycmdList); + secondarycmdQueue->WaitForOtherFence(secondarycmdList->FenceValue); + secondarycmdList = secondarycmdQueue->GetCommandList(); + } + else { renderPass->Execute(secondarycmdList); } + } + secondarycmdQueue->ExecuteCommandList(secondarycmdList); + secondaryCurrentFrameConsts->FenceValue = secondarycmdList->FenceValue; + } _backBuffer->Present(); } -void RenderModule::BuildDescHeapsAndBackBuffer() +void RenderModule::BuildBackBuffer() { - _rtvHeap = std::make_unique(_primaryDevice.get(), - D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1000, - D3D12_DESCRIPTOR_HEAP_FLAG_NONE); - - _srvuavHeap = std::make_unique(_primaryDevice.get(), - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1000000, - D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); - - _dsvHeap = std::make_unique(_primaryDevice.get(), - D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1000, - D3D12_DESCRIPTOR_HEAP_FLAG_NONE); - uint16_t width, height; _window->GetWindowSize(width, height); _backBuffer = std::make_unique(_primaryDevice.get(), _window->GetWindowHandle(), - DXGI_FORMAT_R8G8B8A8_UNORM, 2, width, height, _rtvHeap.get()); + DXGI_FORMAT_R8G8B8A8_UNORM, 2, width, height, _primaryResources.RTVHeap.get()); GDX12TextureDesc desc; desc.CreateSRV = false; - desc.DSVHeap = _dsvHeap.get(); + desc.DSVHeap = _primaryResources.DSVHeap.get(); desc.CreateDSV = true; - desc.DSVHeapIndex = _dsvHeap->GetAvailableIndex(); + desc.DSVHeapIndex = _primaryResources.DSVHeap->GetAvailableIndex(); desc.Format = desc.DSVDesc.Format = DXGI_FORMAT_D32_FLOAT; desc.Width = width; desc.Height = height; @@ -708,292 +776,114 @@ void RenderModule::BuildDescHeapsAndBackBuffer() desc.DSVDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; desc.DSVDesc.Texture2D.MipSlice = 0; - _depthStencil = std::make_unique(desc); - - //MOVE THESE TO RENDER PASSES - GDX12TextureDesc desc2; - desc2.Format = desc2.RTVDesc.Format = desc2.SRVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - desc2.Width = width; - desc2.Height = height; - - desc2.CreateSRV = true; - desc2.SRV_UAV_Heap = _srvuavHeap.get(); - desc2.SRVHeapIndex = _srvuavHeap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); - desc2.SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - desc2.SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - desc2.SRVDesc.Texture2D.MipLevels = 1; - desc2.SRVDesc.Texture2D.MostDetailedMip = 0; - desc2.SRVDesc.Texture2D.PlaneSlice = 0; - desc2.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; - - desc2.CreateRTV = true; - desc2.RTVHeap = _rtvHeap.get(); - desc2.RTVHeapIndex = _rtvHeap->GetAvailableIndex(); - desc2.RTVDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - desc2.RTVDesc.Texture2D.PlaneSlice = 0; - desc2.RTVDesc.Texture2D.MipSlice = 0; - - _opaqueAccumTexture = std::make_unique(desc2); - - desc2.SRVHeapIndex = _srvuavHeap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); - desc2.RTVHeapIndex = _rtvHeap->GetAvailableIndex(); - _transparencyAccumTexture = std::make_unique(desc2); - - desc2.Format = desc2.RTVDesc.Format = desc2.SRVDesc.Format = DXGI_FORMAT_R16_FLOAT; - desc2.SRVHeapIndex = _srvuavHeap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); - desc2.RTVHeapIndex = _rtvHeap->GetAvailableIndex(); - _transparencyRevealageTexture = std::make_unique(desc2); -} + _depthStencil = std::make_unique(); + _depthStencil->Initialize(desc); -void RenderModule::BuildRootSignatures() -{ - GDX12RootSignatureDesc desc; - desc.NumSingleCBVSlots = 2; - desc.NumSingleSRVSlots = 3; - desc.StaticSamplers = GetStaticSamplers(); - desc.SRVRanges.push_back(GDX12RootSignatureRange(Texture2D_RangeLength)); - desc.Constants.push_back(1); - _rootSignatures["OpaquePass"] = std::make_unique(_primaryDevice.get(), desc); - - std::vector args; - D3D12_INDIRECT_ARGUMENT_DESC argConst = {}; - argConst.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT; - argConst.Constant.DestOffsetIn32BitValues = 0; - argConst.Constant.Num32BitValuesToSet = 1; - args.push_back(argConst); - D3D12_INDIRECT_ARGUMENT_DESC argDraw = {}; - argDraw.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED; - args.push_back(argDraw); - D3D12_COMMAND_SIGNATURE_DESC cmdSigDesc = {}; - cmdSigDesc.ByteStride = sizeof(GDX12IndirectDrawArgs); - cmdSigDesc.NumArgumentDescs = args.size(); - cmdSigDesc.pArgumentDescs = args.data(); - cmdSigDesc.NodeMask = 0; - - _primaryDevice->GetDevice()->CreateCommandSignature(&cmdSigDesc, - _rootSignatures["OpaquePass"]->GetRootSignature().Get(), - IID_PPV_ARGS(&_commandSignatures["OpaquePass"])); - - GDX12RootSignatureDesc desc3; - desc3.NumSingleCBVSlots = 1; - desc3.NumSingleSRVSlots = 3; - desc3.NumSingleUAVSlots = 4; - _rootSignatures["Culling"] = std::make_unique(_primaryDevice.get(), desc3); - - GDX12RootSignatureDesc desc4; - desc4.NumSingleUAVSlots = 1; - _rootSignatures["BufferClear"] = std::make_unique(_primaryDevice.get(), desc4); - - GDX12RootSignatureDesc desc5; - desc5.NumSingleSRVSlots = 3; - desc5.StaticSamplers = GetStaticSamplers(); - _rootSignatures["CompositionPass"] = std::make_unique(_primaryDevice.get(), desc5); + _RPcommonData.WindowWidth = width; + _RPcommonData.WindowHeight = height; } -void RenderModule::BuildShaders() +void RenderModule::ShareFences() { - auto& Compiler = GDX12ShaderCompiler::GetInstance(); + HANDLE primaryhandle; + ThrowIfFailed(_primaryDevice->GetDevice()->CreateSharedHandle( + _primaryDevice->GetCommandQueue()->GetFence().Get(), + nullptr, GENERIC_ALL, nullptr, &primaryhandle)); - _shaders["CullingCS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "Culling.hlsl", nullptr, "CS", "cs"); - _shaders["BufferClearCS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "BufferClear.hlsl", nullptr, "CS", "cs"); + ThrowIfFailed(_secondaryDevice->GetDevice()->OpenSharedHandle( + primaryhandle, + IID_PPV_ARGS(&_secondaryDevice->GetCommandQueue()->GetOtherFence()))); - _shaders["OpaquePassVS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "OpaquePass.hlsl", nullptr, "VS", "vs"); - _shaders["OpaquePassPS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "OpaquePass.hlsl", nullptr, "PS", "ps"); + HANDLE secondaryhandle; + ThrowIfFailed(_secondaryDevice->GetDevice()->CreateSharedHandle( + _secondaryDevice->GetCommandQueue()->GetFence().Get(), + nullptr, GENERIC_ALL, nullptr, &secondaryhandle)); - _shaders["TransparentPassVS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "TransparentPass.hlsl", nullptr, "VS", "vs"); - _shaders["TransparentPassPS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "TransparentPass.hlsl", nullptr, "PS", "ps"); - - _shaders["VS_FSQuad"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "FullScreenVS.hlsl", nullptr, "VS", "vs"); - _shaders["CompositionPassPS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "CompositionPass.hlsl", nullptr, "PS", "ps"); + ThrowIfFailed(_primaryDevice->GetDevice()->OpenSharedHandle( + secondaryhandle, + IID_PPV_ARGS(&_primaryDevice->GetCommandQueue()->GetOtherFence()))); } -void RenderModule::BuildPSOs() +void RenderModule::ConfigureRenderPipeline() { - D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {}; - - desc.InputLayout = { _inputLayouts["Default"].data(), (UINT)_inputLayouts["Default"].size() }; - desc.pRootSignature = _rootSignatures["OpaquePass"]->GetRootSignature().Get(); - desc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); - desc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); - desc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); - //reversed-Z - desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; - desc.RasterizerState.FrontCounterClockwise = TRUE; - desc.SampleMask = UINT_MAX; - desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - desc.NumRenderTargets = 1; - desc.RTVFormats[0] = _backBuffer->GetFormat(); - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.DSVFormat = _depthStencil->GetFormat(); - - desc.VS = - { - reinterpret_cast(_shaders["OpaquePassVS"]->GetBufferPointer()), - _shaders["OpaquePassVS"]->GetBufferSize() - }; - desc.PS = - { - reinterpret_cast(_shaders["OpaquePassPS"]->GetBufferPointer()), - _shaders["OpaquePassPS"]->GetBufferSize() - }; - ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_PSOs["OpaquePass"]))); - - desc.InputLayout = { nullptr, 0 }; - desc.pRootSignature = _rootSignatures["CompositionPass"]->GetRootSignature().Get(); - desc.DepthStencilState.DepthEnable = false; - desc.DepthStencilState.StencilEnable = false; - desc.VS = - { - reinterpret_cast(_shaders["VS_FSQuad"]->GetBufferPointer()), - _shaders["VS_FSQuad"]->GetBufferSize() - }; - desc.PS = - { - reinterpret_cast(_shaders["CompositionPassPS"]->GetBufferPointer()), - _shaders["CompositionPassPS"]->GetBufferSize() - }; - ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_PSOs["CompositionPass"]))); - - desc.InputLayout = { _inputLayouts["Default"].data(), (UINT)_inputLayouts["Default"].size() }; - desc.pRootSignature = _rootSignatures["OpaquePass"]->GetRootSignature().Get(); - desc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); - // Accumulation - desc.BlendState.RenderTarget[0].BlendEnable = true; - desc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; - desc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_ONE; - desc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; - desc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; - desc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ONE; - desc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; - desc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; - // Revealage - desc.BlendState.RenderTarget[1].BlendEnable = true; - desc.BlendState.RenderTarget[1].SrcBlend = D3D12_BLEND_ONE; - desc.BlendState.RenderTarget[1].DestBlend = D3D12_BLEND_ONE; - desc.BlendState.RenderTarget[1].BlendOp = D3D12_BLEND_OP_ADD; - desc.BlendState.RenderTarget[1].SrcBlendAlpha = D3D12_BLEND_ONE; - desc.BlendState.RenderTarget[1].DestBlendAlpha = D3D12_BLEND_ONE; - desc.BlendState.RenderTarget[1].BlendOpAlpha = D3D12_BLEND_OP_ADD; - desc.BlendState.RenderTarget[1].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; - // Disable depth write - desc.DepthStencilState.DepthEnable = true; - desc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; - desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; - desc.DepthStencilState.StencilEnable = false; - - desc.NumRenderTargets = 2; - desc.RTVFormats[0] = _transparencyAccumTexture->GetFormat(); - desc.RTVFormats[1] = _transparencyRevealageTexture->GetFormat(); - desc.DSVFormat = _depthStencil->GetFormat(); - desc.VS = - { - reinterpret_cast(_shaders["TransparentPassVS"]->GetBufferPointer()), - _shaders["TransparentPassVS"]->GetBufferSize() - }; - desc.PS = - { - reinterpret_cast(_shaders["TransparentPassPS"]->GetBufferPointer()), - _shaders["TransparentPassPS"]->GetBufferSize() - }; - ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_PSOs["TransparentPass"]))); + // Setup render passes you would like to execute + // Add in execution order + _primaryRenderPassExecutionList.push_back(std::make_unique()); + _primaryRenderPassExecutionList.push_back(std::make_unique()); + _primaryRenderPassExecutionList.push_back(std::make_unique()); + _primaryRenderPassExecutionList.push_back(std::make_unique()); + _primaryRenderPassExecutionList.push_back(std::make_unique()); + _primaryRenderPassExecutionList.push_back(std::make_unique()); + _primaryRenderPassExecutionList.push_back(std::make_unique()); + SetupRenderPasses(); - D3D12_COMPUTE_PIPELINE_STATE_DESC desc2 = {}; - desc2.pRootSignature = _rootSignatures["Culling"]->GetRootSignature().Get(); - desc2.CS = - { - reinterpret_cast(_shaders["CullingCS"]->GetBufferPointer()), - _shaders["CullingCS"]->GetBufferSize() - }; + // Link inputs & outputs for each pass that needs it + GDX12RenderPass* clearPass = _primaryRenderPassExecutionList[0].get(); + GDX12RenderPass* cullingPass = _primaryRenderPassExecutionList[1].get(); + GDX12RenderPass* opaquePass = _primaryRenderPassExecutionList[2].get(); + GDX12RenderPass* transparencyPass = _primaryRenderPassExecutionList[3].get(); + GDX12RenderPass* compositionPass = _primaryRenderPassExecutionList[4].get(); + GDX12RenderPass* upscalePass = _primaryRenderPassExecutionList[5].get(); + GDX12RenderPass* outputPass = _primaryRenderPassExecutionList[6].get(); - ThrowIfFailed(_primaryDevice->GetDevice()->CreateComputePipelineState( - &desc2, IID_PPV_ARGS(&_PSOs["Culling"]))); + clearPass->SetInputs({ _backBuffer.get(), _depthStencil.get() }); + cullingPass->SetInputs({}); + opaquePass->SetInputs({}); + transparencyPass->SetInputs({ opaquePass->GetOutput(2) }); + compositionPass->SetInputs({ opaquePass->GetOutput(0), transparencyPass->GetOutput(0), transparencyPass->GetOutput(1) }); + upscalePass->SetInputs({ opaquePass->GetOutput(2), opaquePass->GetOutput(1), compositionPass->GetOutput(0) }); + outputPass->SetInputs({ upscalePass->GetOutput(0), _backBuffer.get()}); - D3D12_COMPUTE_PIPELINE_STATE_DESC desc3 = {}; - desc3.pRootSignature = _rootSignatures["BufferClear"]->GetRootSignature().Get(); - desc3.CS = - { - reinterpret_cast(_shaders["BufferClearCS"]->GetBufferPointer()), - _shaders["BufferClearCS"]->GetBufferSize() - }; + opaquePass->SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); + transparencyPass->SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); + compositionPass->SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); - ThrowIfFailed(_primaryDevice->GetDevice()->CreateComputePipelineState( - &desc3, IID_PPV_ARGS(&_PSOs["BufferClear"]))); + InitializeRenderPasses(); } -void RenderModule::BuildFrameConstants() +void RenderModule::SetupRenderPasses() { - for (int i = 0; i < NumFrameConstantVariable.GetValue(); i++) + for (auto& pass : _primaryRenderPassExecutionList) { - _frameConstants.push_back(std::make_unique(_primaryDevice.get())); - - _frameConstants[i]->MaterialCache->CreateSRV(_srvuavHeap.get(), _srvuavHeap->GetAvailableIndex(ConstantsResources)); - _frameConstants[i]->TransformCache->CreateSRV(_srvuavHeap.get(), _srvuavHeap->GetAvailableIndex(ConstantsResources)); - _frameConstants[i]->InstanceCache->CreateSRV(_srvuavHeap.get(), _srvuavHeap->GetAvailableIndex(ConstantsResources)); - _frameConstants[i]->VisibleOpaqueCommandsCache->CreateUAV(_srvuavHeap.get(), _srvuavHeap->GetAvailableIndex(ConstantsResources)); - _frameConstants[i]->OpaqueDrawCounter->CreateUAV(_srvuavHeap.get(), _srvuavHeap->GetAvailableIndex(ConstantsResources)); - _frameConstants[i]->VisibleTransparentCommandsCache->CreateUAV(_srvuavHeap.get(), _srvuavHeap->GetAvailableIndex(ConstantsResources)); - _frameConstants[i]->TransparentDrawCounter->CreateUAV(_srvuavHeap.get(), _srvuavHeap->GetAvailableIndex(ConstantsResources)); + pass->Setup(&_primaryResources, &_secondaryResources, &_RPcommonData); + _primaryPipelineFlags |= pass->GetFlags(); } - _IndirectCommandsCache = std::make_unique>(_primaryDevice.get(), 0, EBufferType::Upload, false); - _IndirectCommandsCache->CreateSRV(_srvuavHeap.get(), _srvuavHeap->GetAvailableIndex(ConstantsResources)); -} - -void RenderModule::UpdateMainCB() -{ - auto& frameRes = _frameConstants[_currFrameConstantsIndex]; - - GDX12MainConstants mainConstants; - - uint16_t width, height; - _window->GetWindowSize(width, height); - - mainConstants.RenderTargetSize = { static_cast(width), static_cast(height) }; - mainConstants.TotalTime = _timer->TotalTime(); - mainConstants.DeltaTime = _timer->DeltaTime(); - - frameRes->MainCB->CopyData(0, mainConstants); + for (auto& pass : _secondaryRenderPassExecutionList) + { + pass->Setup(&_secondaryResources, &_primaryResources, &_RPcommonData); + _secondaryPipelineFlags |= pass->GetFlags(); + } } -void RenderModule::UpdateMaterialCB() +void RenderModule::InitializeRenderPasses() { - auto currMaterialCB = _frameConstants[_currFrameConstantsIndex]->MaterialCache.get(); - for (auto& i : _materials) + std::vector allRenderPasses; + for (auto& pass : _primaryRenderPassExecutionList) + allRenderPasses.push_back(pass.get()); + for (auto& pass : _secondaryRenderPassExecutionList) + allRenderPasses.push_back(pass.get()); + const int MAX_ITERATIONS = 100; + int iteration = 0; + while (!allRenderPasses.empty()) { - GDX12Material* material = i.second.get(); - - if (material->DirtyFlag) - { - material->DirtyFlag = false; - material->_numFramesDirty = _numFrameConstants; + if (iteration > MAX_ITERATIONS) + { + OutputDebugStringA("ERROR: RenderPass linking failed after 100 attempts. This can be caused by wrong render pass inputs\n"); + break; } - - if (material->_numFramesDirty > 0) + for (auto it = allRenderPasses.begin(); it != allRenderPasses.end();) { - GDX12MaterialConstants materialConstants; - materialConstants.Roughness = material->Roughness; - materialConstants.Metallic = material->Metallic; - materialConstants.Opacity = material->Opacity; - materialConstants.RenderLayer = UINT(material->Type); - - if (material->Diffuse) + GDX12RenderPass* renderPass = *it; + if (renderPass->ValidateInputs()) { - materialConstants.DiffuseIndex = material->Diffuse->GetSRV()->HeapIndex - Texture2D_StartIndex; + renderPass->Initialize(); + it = allRenderPasses.erase(it); } - if (material->Normal) - { - materialConstants.NormalIndex = material->Normal->GetSRV()->HeapIndex - Texture2D_StartIndex; - } - if (material->Displacement) - { - materialConstants.DisplacementIndex = material->Displacement->GetSRV()->HeapIndex - Texture2D_StartIndex; - } - - currMaterialCB->CopyData(material->_CBufferIndex, materialConstants); - material->_numFramesDirty--; + else { ++it; } } + iteration++; } } diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index 300eb81..ac114bd 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -2,7 +2,6 @@ #include "App.Base/Systems/CircleMovementSystem.h" #include "App.Base/Systems/MovementSystem.h" -#include "App.Base/Systems/RenderSubmitSystem.h" #include "App.Base/Systems/GPUDataUpdateSystem.h" #include "App.Base/Systems/LookAtTargetSystem.h" #include "App.Base/Systems/SplineFollowSystem.h" @@ -57,7 +56,6 @@ void SceneManagerModule::Initialize() AddSystem(world, 2); AddSystem(world, 3); AddSystem(world, 101); - AddSystem(world, 102); } void SceneManagerModule::Uninitialize() diff --git a/Apps/App.Benchmark/App.Benchmark.vcxproj b/Apps/App.Benchmark/App.Benchmark.vcxproj index f7a784a..db4375d 100644 --- a/Apps/App.Benchmark/App.Benchmark.vcxproj +++ b/Apps/App.Benchmark/App.Benchmark.vcxproj @@ -114,12 +114,14 @@ Windows true - Engine.Core.lib;Engine.RendererDX12.lib;Engine.UI.lib;App.Base.lib;External.Libraries.lib;dxcompiler.lib;dxil.lib;WinPixEventRuntime.lib;assimp-vc143-mtd.lib;DirectXTK12.lib;DirectXTex.lib;amd_fidelityfx_dx12.lib;dstorage.lib;DirectXMesh.lib;AkSoundEngine.lib;AkMemoryMgr.lib;AkStreamMgr.lib;CommunicationCentral.lib;%(AdditionalDependencies) + Engine.Core.lib;Engine.RendererDX12.lib;Engine.UI.lib;App.Base.lib;External.Libraries.lib;dxcompiler.lib;dxil.lib;WinPixEventRuntime.lib;assimp-vc143-mtd.lib;DirectXTK12.lib;DirectXTex.lib;amd_fidelityfx_dx12.lib;libxess.lib;dstorage.lib;DirectXMesh.lib;AkSoundEngine.lib;AkMemoryMgr.lib;AkStreamMgr.lib;CommunicationCentral.lib;%(AdditionalDependencies) false - $(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.Core\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.RendererDX12\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.UI\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\App.Base\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\External.Libraries\;$(PEPRepoRoot)External\External.Libraries\dxc\lib\$(Platform)\;$(PEPRepoRoot)External\External.Libraries\pix\lib\;$(PEPRepoRoot)External\External.Libraries\assimp\lib\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtk\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtex\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\ffx-api\lib\;$(PEPRepoRoot)External\External.Libraries\directstorage\lib\;$(PEPRepoRoot)External\External.Libraries\directxmesh\lib\;$(PEPRepoRoot)External\External.Libraries\wwise\lib\;%(AdditionalLibraryDirectories) + $(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.Core\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.RendererDX12\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.UI\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\App.Base\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\External.Libraries\;$(PEPRepoRoot)External\External.Libraries\dxc\lib\$(Platform)\;$(PEPRepoRoot)External\External.Libraries\pix\lib\;$(PEPRepoRoot)External\External.Libraries\assimp\lib\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtk\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtex\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\ffx-api\lib\;$(PEPRepoRoot)External\External.Libraries\xess\lib\;$(PEPRepoRoot)External\External.Libraries\directstorage\lib\;$(PEPRepoRoot)External\External.Libraries\directxmesh\lib\;$(PEPRepoRoot)External\External.Libraries\wwise\lib\;%(AdditionalLibraryDirectories) - xcopy /Y /D "$(PEPRepoRoot)External\Runtime\*.dll" "$(TargetDir)" + xcopy /Y /D "$(PEPRepoRoot)External\Runtime\*.dll" "$(TargetDir)" +if exist "$(PEPRepoRoot)External\Runtime\sl*.dll" xcopy /Y "$(PEPRepoRoot)External\Runtime\sl*.dll" "$(TargetDir)" +if exist "$(PEPRepoRoot)External\Runtime\nvngx*.dll" xcopy /Y "$(PEPRepoRoot)External\Runtime\nvngx*.dll" "$(TargetDir)" @@ -135,11 +137,13 @@ Windows true - $(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.Core\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.RendererDX12\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.UI\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\App.Base\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\External.Libraries\;$(PEPRepoRoot)External\External.Libraries\dxc\lib\$(Platform)\;$(PEPRepoRoot)External\External.Libraries\pix\lib\;$(PEPRepoRoot)External\External.Libraries\assimp\lib\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtk\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtex\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\ffx-api\lib\;$(PEPRepoRoot)External\External.Libraries\directstorage\lib\;$(PEPRepoRoot)External\External.Libraries\directxmesh\lib\;$(PEPRepoRoot)External\External.Libraries\wwise\lib\;%(AdditionalLibraryDirectories) - Engine.Core.lib;Engine.RendererDX12.lib;Engine.UI.lib;App.Base.lib;External.Libraries.lib;dxcompiler.lib;dxil.lib;WinPixEventRuntime.lib;assimp-vc143-mt.lib;DirectXTK12.lib;DirectXTex.lib;amd_fidelityfx_dx12.lib;DirectXMesh.lib;AkSoundEngine.lib;AkMemoryMgr.lib;AkStreamMgr.lib;CommunicationCentral.lib;%(AdditionalDependencies) + $(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.Core\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.RendererDX12\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.UI\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\App.Base\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\External.Libraries\;$(PEPRepoRoot)External\External.Libraries\dxc\lib\$(Platform)\;$(PEPRepoRoot)External\External.Libraries\pix\lib\;$(PEPRepoRoot)External\External.Libraries\assimp\lib\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtk\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtex\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\ffx-api\lib\;$(PEPRepoRoot)External\External.Libraries\xess\lib\;$(PEPRepoRoot)External\External.Libraries\directstorage\lib\;$(PEPRepoRoot)External\External.Libraries\directxmesh\lib\;$(PEPRepoRoot)External\External.Libraries\wwise\lib\;%(AdditionalLibraryDirectories) + Engine.Core.lib;Engine.RendererDX12.lib;Engine.UI.lib;App.Base.lib;External.Libraries.lib;dxcompiler.lib;dxil.lib;WinPixEventRuntime.lib;assimp-vc143-mt.lib;DirectXTK12.lib;DirectXTex.lib;amd_fidelityfx_dx12.lib;libxess.lib;DirectXMesh.lib;AkSoundEngine.lib;AkMemoryMgr.lib;AkStreamMgr.lib;CommunicationCentral.lib;%(AdditionalDependencies) - xcopy /Y /D "$(PEPRepoRoot)External\Runtime\*.dll" "$(TargetDir)" + xcopy /Y /D "$(PEPRepoRoot)External\Runtime\*.dll" "$(TargetDir)" +if exist "$(PEPRepoRoot)External\Runtime\sl*.dll" xcopy /Y "$(PEPRepoRoot)External\Runtime\sl*.dll" "$(TargetDir)" +if exist "$(PEPRepoRoot)External\Runtime\nvngx*.dll" xcopy /Y "$(PEPRepoRoot)External\Runtime\nvngx*.dll" "$(TargetDir)" @@ -148,4 +152,4 @@ - \ No newline at end of file + diff --git a/Apps/App.Editor/App.Editor.vcxproj b/Apps/App.Editor/App.Editor.vcxproj index 4fd5eb3..19dfbde 100644 --- a/Apps/App.Editor/App.Editor.vcxproj +++ b/Apps/App.Editor/App.Editor.vcxproj @@ -114,11 +114,13 @@ Windows true - $(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.Core\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.RendererDX12\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.UI\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\App.Base\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\External.Libraries\;$(PEPRepoRoot)External\External.Libraries\dxc\lib\$(Platform)\;$(PEPRepoRoot)External\External.Libraries\pix\lib\;$(PEPRepoRoot)External\External.Libraries\assimp\lib\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtk\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtex\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\ffx-api\lib\;$(PEPRepoRoot)External\External.Libraries\directstorage\lib\;$(PEPRepoRoot)External\External.Libraries\directxmesh\lib\;$(PEPRepoRoot)External\External.Libraries\wwise\lib\;%(AdditionalLibraryDirectories) - Engine.Core.lib;Engine.RendererDX12.lib;Engine.UI.lib;App.Base.lib;External.Libraries.lib;dxcompiler.lib;dxil.lib;WinPixEventRuntime.lib;assimp-vc143-mtd.lib;DirectXTK12.lib;DirectXTex.lib;amd_fidelityfx_dx12.lib;dstorage.lib;DirectXMesh.lib;AkSoundEngine.lib;AkMemoryMgr.lib;AkStreamMgr.lib;CommunicationCentral.lib;%(AdditionalDependencies) + $(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.Core\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.RendererDX12\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.UI\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\App.Base\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\External.Libraries\;$(PEPRepoRoot)External\External.Libraries\dxc\lib\$(Platform)\;$(PEPRepoRoot)External\External.Libraries\pix\lib\;$(PEPRepoRoot)External\External.Libraries\assimp\lib\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtk\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtex\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\ffx-api\lib\;$(PEPRepoRoot)External\External.Libraries\xess\lib\;$(PEPRepoRoot)External\External.Libraries\directstorage\lib\;$(PEPRepoRoot)External\External.Libraries\directxmesh\lib\;$(PEPRepoRoot)External\External.Libraries\wwise\lib\;%(AdditionalLibraryDirectories) + Engine.Core.lib;Engine.RendererDX12.lib;Engine.UI.lib;App.Base.lib;External.Libraries.lib;dxcompiler.lib;dxil.lib;WinPixEventRuntime.lib;assimp-vc143-mtd.lib;DirectXTK12.lib;DirectXTex.lib;amd_fidelityfx_dx12.lib;libxess.lib;dstorage.lib;DirectXMesh.lib;AkSoundEngine.lib;AkMemoryMgr.lib;AkStreamMgr.lib;CommunicationCentral.lib;%(AdditionalDependencies) - xcopy /Y /D "$(PEPRepoRoot)External\Runtime\*.dll" "$(TargetDir)" + xcopy /Y /D "$(PEPRepoRoot)External\Runtime\*.dll" "$(TargetDir)" +if exist "$(PEPRepoRoot)External\Runtime\sl*.dll" xcopy /Y "$(PEPRepoRoot)External\Runtime\sl*.dll" "$(TargetDir)" +if exist "$(PEPRepoRoot)External\Runtime\nvngx*.dll" xcopy /Y "$(PEPRepoRoot)External\Runtime\nvngx*.dll" "$(TargetDir)" @@ -134,11 +136,13 @@ Windows true - $(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.Core\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.RendererDX12\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.UI\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\App.Base\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\External.Libraries\;$(PEPRepoRoot)External\External.Libraries\dxc\lib\$(Platform)\;$(PEPRepoRoot)External\External.Libraries\pix\lib\;$(PEPRepoRoot)External\External.Libraries\assimp\lib\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtk\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtex\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\ffx-api\lib\;$(PEPRepoRoot)External\External.Libraries\directstorage\lib\;$(PEPRepoRoot)External\External.Libraries\directxmesh\lib\;$(PEPRepoRoot)External\External.Libraries\wwise\lib\;%(AdditionalLibraryDirectories) - Engine.Core.lib;Engine.RendererDX12.lib;Engine.UI.lib;App.Base.lib;External.Libraries.lib;dxcompiler.lib;dxil.lib;WinPixEventRuntime.lib;assimp-vc143-mt.lib;DirectXTK12.lib;DirectXTex.lib;amd_fidelityfx_dx12.lib;dstorage.lib;DirectXMesh.lib;AkSoundEngine.lib;AkMemoryMgr.lib;AkStreamMgr.lib;CommunicationCentral.lib;%(AdditionalDependencies) + $(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.Core\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.RendererDX12\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\Engine.UI\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\App.Base\;$(PEPRepoRoot)Build\bin\$(Platform)\$(Configuration)\External.Libraries\;$(PEPRepoRoot)External\External.Libraries\dxc\lib\$(Platform)\;$(PEPRepoRoot)External\External.Libraries\pix\lib\;$(PEPRepoRoot)External\External.Libraries\assimp\lib\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtk\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\directxtex\lib\$(Platform)\$(Configuration)\;$(PEPRepoRoot)External\External.Libraries\ffx-api\lib\;$(PEPRepoRoot)External\External.Libraries\xess\lib\;$(PEPRepoRoot)External\External.Libraries\directstorage\lib\;$(PEPRepoRoot)External\External.Libraries\directxmesh\lib\;$(PEPRepoRoot)External\External.Libraries\wwise\lib\;%(AdditionalLibraryDirectories) + Engine.Core.lib;Engine.RendererDX12.lib;Engine.UI.lib;App.Base.lib;External.Libraries.lib;dxcompiler.lib;dxil.lib;WinPixEventRuntime.lib;assimp-vc143-mt.lib;DirectXTK12.lib;DirectXTex.lib;amd_fidelityfx_dx12.lib;libxess.lib;dstorage.lib;DirectXMesh.lib;AkSoundEngine.lib;AkMemoryMgr.lib;AkStreamMgr.lib;CommunicationCentral.lib;%(AdditionalDependencies) - xcopy /Y /D "$(PEPRepoRoot)External\Runtime\*.dll" "$(TargetDir)" + xcopy /Y /D "$(PEPRepoRoot)External\Runtime\*.dll" "$(TargetDir)" +if exist "$(PEPRepoRoot)External\Runtime\sl*.dll" xcopy /Y "$(PEPRepoRoot)External\Runtime\sl*.dll" "$(TargetDir)" +if exist "$(PEPRepoRoot)External\Runtime\nvngx*.dll" xcopy /Y "$(PEPRepoRoot)External\Runtime\nvngx*.dll" "$(TargetDir)" @@ -147,4 +151,4 @@ - \ No newline at end of file + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index 3fbd69f..5e82c14 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -21,9 +21,23 @@ + - + + + + + + + + + + + + + + @@ -39,13 +53,16 @@ + + + - + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index f300a89..09f0937 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -66,15 +66,63 @@ Header Files - - Header Files - Header Files Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + @@ -110,6 +158,9 @@ Source Files + + Source Files + Source Files @@ -119,11 +170,20 @@ Source Files - + Source Files - + Source Files + + + + + + + + + \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandList.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandList.h index caf104d..523c00f 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandList.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandList.h @@ -85,7 +85,7 @@ class GDX12CommandList //Misc void BeginPixEvent(const std::string& name, XMVECTOR color); void EndPixEvent(); - + void CopyResource(ID3D12Resource* destResource, ID3D12Resource* sourceResource); void BuildRaytracingAccelerationStructure(const D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC* pDesc); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h index e81c9e6..2382fdb 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h @@ -14,15 +14,18 @@ class GDX12CommandQueue void Reset(); const ComPtr& GetCommandQueue(); + const ComPtr& GetPresentCommandQueue(); const ComPtr& GetFence(); + ComPtr& GetOtherFence(); // Returns a CommandList that you can work with. // If all previously created lists are busy - a new one will be created. GDX12CommandList* GetCommandList(); void ExecuteCommandList(GDX12CommandList* commandList); - void ExecuteCommandLists(GDX12CommandList** lists, UINT count); + void ExecuteCommandLists(std::vector& commandLists); - void WaitForFenceValue(uint64_t fenceValue); + void CPUWaitForFenceValue(uint64_t fenceValue); + void WaitForOtherFence(uint64_t otherFenceValue); //Waits for execution of all active lists void Flush(); @@ -36,7 +39,12 @@ class GDX12CommandQueue void ClearCompletedLists(); ComPtr _commandQueue; + ComPtr _proxyCommandQueue; ComPtr _fence; + //shared fence from another device + //null if _dualGPUMode is false + ComPtr _otherFence; + GDX12Device* _device; // Command Lists can be requested via GetCommandList() @@ -47,4 +55,4 @@ class GDX12CommandQueue std::vector> _availableCommandLists; uint64_t _lastDispatchedFenceValue; -}; \ No newline at end of file +}; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12ConstantStructures.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12ConstantStructures.h index e1bc106..b0c8e95 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12ConstantStructures.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12ConstantStructures.h @@ -12,6 +12,7 @@ struct GDX12MainConstants struct GDX12TransformConstants { XMFLOAT4X4 WorldMatrix = Identity4x4(); + XMFLOAT4X4 PrevWorldMatrix = Identity4x4(); }; struct GDX12MaterialConstants @@ -33,7 +34,9 @@ struct GDX12MaterialConstants struct GDX12CameraConstants { XMFLOAT4X4 ViewProj = Identity4x4(); + XMFLOAT4X4 ViewProjNoJitter = Identity4x4(); XMFLOAT4X4 View = Identity4x4(); + XMFLOAT4X4 PrevViewProjNoJitter = Identity4x4(); XMFLOAT3 CameraLocation = { 0.f, 0.f, 0.f }; float NearPlane; float FarPlane; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h index 1f652f5..f739965 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h @@ -8,16 +8,17 @@ class GDX12CommandQueue; struct DeviceSpecs { D3D_FEATURE_LEVEL MaxFeatureLevel; - D3D_SHADER_MODEL MaxShaderModel; - bool RaytracingSupport; - bool MeshShadersSupport; - bool VariableRateShadingSupport; - bool EnhancedBarriersSupport; - bool CrossAdapterRowMajorTextureSupport; std::string Name; size_t DedicatedVideoMemory; // in bytes size_t DedicatedSystemMemory; // in bytes size_t SharedSystemMemory; // in bytes + CD3DX12FeatureSupport Features; +}; + +enum EDeviceRole +{ + DEVICE_ROLE_PRIMARY, + DEVICE_ROLE_SECONDARY }; class GDX12Device : public std::enable_shared_from_this @@ -30,15 +31,19 @@ class GDX12Device : public std::enable_shared_from_this void Reset(); const ComPtr& GetDevice(); + const ComPtr& GetCommandQueueCreationDevice(); GDX12CommandQueue* GetCommandQueue(); const DeviceSpecs& GetDeviceFeatures(); + LUID GetAdapterLuid() const; const bool IsInitialized(); + EDeviceRole Role; private: void CollectDeviceFeatures(); ComPtr _adapter; ComPtr _device; + ComPtr _proxyDevice; std::unique_ptr _commandQueue; @@ -49,4 +54,4 @@ class GDX12Device : public std::enable_shared_from_this UINT _cbvSrvUavDescriptorSize; DeviceSpecs _specs; -}; \ No newline at end of file +}; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceFactory.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceFactory.h index c5f49da..2df9238 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceFactory.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceFactory.h @@ -45,5 +45,6 @@ class GDX12DeviceFactory GDX12DeviceFactory() = delete; static ComPtr _dxgiFactory; + static ComPtr _dxgiFactoryProxy; static bool _isInitialized; -}; \ No newline at end of file +}; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceResources.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceResources.h new file mode 100644 index 0000000..329b8f7 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceResources.h @@ -0,0 +1,41 @@ +#pragma once +#include "Engine.RendererDX12/D3DHelpers.h" +#include "Engine.RendererDX12/GDX12DescriptorHeap.h" +#include "Engine.RendererDX12/GDX12FrameConstants.h" +#include "Engine.RendererDX12/GDX12RootSignature.h" +#include "Engine.RendererDX12/GDX12Texture.h" +#include "Engine.RendererDX12/GDX12Material.h" +#include "Engine.RendererDX12/GDX12GeometryBuffer.h" + +class GDX12Device; +class GameTimer; + +class GDX12DeviceResources +{ +public: + GDX12DeviceResources() : CurrFrameConstantsIndex(0), Device(nullptr) {} + + std::unordered_map> InputLayouts; + std::unique_ptr GeometryBuffer; + + // All heaps created in one high-capacity instance + std::unique_ptr RTVHeap; + std::unique_ptr SRV_UAV_Heap; + std::unique_ptr DSVHeap; + + std::vector> FrameConstants; + UINT CurrFrameConstantsIndex; + + std::unique_ptr> IndirectCommandsCache; + + std::unordered_map> Shaders; + std::unordered_map> PSOs; + std::unordered_map> RootSignatures; + std::unordered_map > CommandSignatures; + std::unordered_map> Textures; + + GDX12Device* Device; + void Initialize(GDX12Device* device); + void UpdateMainCB(UINT width, UINT height, GameTimer* timer); + void UpdateMaterialCB(std::unordered_map>& materials); +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12FrameConstants.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12FrameConstants.h index 9afdb68..6cc3258 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12FrameConstants.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12FrameConstants.h @@ -8,6 +8,16 @@ class GDX12Device; +// Used for collecting & using GPU culling results +// This structured is used by any object that uses culling(cameras, shadowmaps) +struct GDX12VisibilityBuffers +{ + std::unique_ptr> VisibleOpaqueCommandsCache; + std::unique_ptr> OpaqueDrawCounter; + std::unique_ptr> VisibleTransparentCommandsCache; + std::unique_ptr> TransparentDrawCounter; +}; + class GDX12FrameConstants { public: @@ -25,13 +35,7 @@ class GDX12FrameConstants std::unique_ptr> InstanceCache; std::unique_ptr> LightCB; std::unique_ptr> CameraCB; - - // Append buffer for visible indirect commands - std::unique_ptr> VisibleOpaqueCommandsCache; - std::unique_ptr> OpaqueDrawCounter; - - std::unique_ptr> VisibleTransparentCommandsCache; - std::unique_ptr> TransparentDrawCounter; + std::vector CameraVisibilityCommands; UINT64 FenceValue; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h index f73a4ed..92d7cf3 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h @@ -2,6 +2,8 @@ #include "Engine.RendererDX12/D3DHelpers.h" +#include "Engine.Core/Types/TextureTypes.h" + class GDX12Texture; enum class MaterialType @@ -11,17 +13,24 @@ enum class MaterialType Transparent = 2, }; +struct GPUTexture +{ + std::string Name; + GDX12Texture* PrimaryDeviceTexture = nullptr; + GDX12Texture* SecondaryDeviceTexture = nullptr; +}; + class GDX12Material { public: std::string Name; - GDX12Texture* Diffuse; - GDX12Texture* Normal; - GDX12Texture* Specular; - GDX12Texture* RoughnessMap; - GDX12Texture* Emissive; - GDX12Texture* Displacement; + GPUTexture* Diffuse; + GPUTexture* Normal; + GPUTexture* Specular; + GPUTexture* RoughnessMap; + GPUTexture* Emissive; + GPUTexture* Displacement; float Metallic; float Roughness; @@ -39,6 +48,7 @@ class GDX12Material private: friend class RenderModule; + friend class GDX12DeviceResources; GDX12Material() : Name(""), Diffuse(nullptr), Normal(nullptr), Specular(nullptr), RoughnessMap(nullptr), Emissive(nullptr), Displacement(nullptr), Metallic(0.f), Roughness(1.f), Opacity(1.f), diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12RenderCommandRecorder.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12RenderCommandRecorder.h deleted file mode 100644 index 996e095..0000000 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12RenderCommandRecorder.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "Engine.RendererDX12/D3DHelpers.h" - -#include "Engine.RendererDX12/GDX12GeometryBuffer.h" -#include "Engine.RendererDX12/GDX12Material.h" - -struct RenderCommand -{ - -}; - -struct DrawMeshCommand : RenderCommand -{ - MeshHandle Mesh; - std::vector Materials; - int TransformCBIndex; - - DrawMeshCommand(MeshHandle mesh, std::vector materials, int transformCBIndex) - : Mesh(mesh), Materials(materials), TransformCBIndex(transformCBIndex) - { - - } -}; - -class GDX12RenderCommandRecorder -{ -public: - GDX12RenderCommandRecorder(); - - void DrawFromCamera(int cameraCBIndex); - void ClearCommands(); - -private: - friend class RenderModule; - - int _cameraCBIndex; -}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h index a544a79..bb8d798 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h @@ -23,10 +23,15 @@ class GDX12Resource CD3DX12_RESOURCE_BARRIER GetPresentBarrier(); CD3DX12_RESOURCE_BARRIER GetIndirectArgsBarrier(); CD3DX12_RESOURCE_BARRIER GetUAVBarrier(); + CD3DX12_RESOURCE_BARRIER GetSRVBarrier(); void SetCurrentState(D3D12_RESOURCE_STATES newState); D3D12_RESOURCE_STATES GetCurrentState(); + void Reset(); + + virtual void ResetState(); + ComPtr D3DResource; private: diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h new file mode 100644 index 0000000..a84e7ca --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h @@ -0,0 +1,176 @@ +#pragma once + +#include "Engine.RendererDX12\D3DHelpers.h" + +#include "Engine.Core/Types/TextureTypes.h" +#include "Engine.RendererDX12/IRenderPassLink.h" +#include "Engine.RendererDX12/GDX12Device.h" +#include "Engine.RendererDX12/GDX12TextureResource.h" + +class GDX12SharedTexture : public IRenderPassLink +{ +public: + GDX12SharedTexture() : _width(0) , _height(0), + _format(DXGI_FORMAT_UNKNOWN), _heapSize(0), _transferFromDeivce(nullptr), + _transferToDevice(nullptr), _isInitiliazed(false) + { + } + + ~GDX12SharedTexture() + { + Release(); + } + + GDX12Texture* GetTexture() override + { + OutputDebugStringA("ERROR: Getting texture from SharedTexture via interface is not allowed! Use GetSharedTexture() or get it via CopyFromRenderPass.\n"); + return nullptr; + } + + void Initialize(GDX12Device* transferFromDeivce, GDX12Device* transferToDevice, + UINT width, UINT height, DXGI_FORMAT format) + { + Release(); + + _transferFromDeivce = transferFromDeivce; + _transferToDevice = transferToDevice; + _width = width; + _height = height; + _format = format; + + CreateSharedHeap(); + CreatePlacedResources(); + ShareResources(); + + _isInitiliazed = true; + } + + void Release() + { + _sharedTexturePrimary.Reset(); + _sharedTextureSecondary.Reset(); + _sharedHeap.Reset(); + _width = 0; + _height = 0; + _format = DXGI_FORMAT_UNKNOWN; + _heapSize = 0; + } + + void Resize(UINT width, UINT height) + { + DXGI_FORMAT cachedFormat = _format; + Release(); + Initialize(_transferFromDeivce, _transferToDevice, width, height, cachedFormat); + } + + //Transfer happens from primary to secondary + GDX12Resource* GetPrimaryResource() { return &_sharedTexturePrimary; } + GDX12Resource* GetSecondaryResource() { return &_sharedTextureSecondary; } + UINT GetWidth() { return _width; } + UINT GetHeight() { return _height; } + DXGI_FORMAT GetFormat() { return _format; } + GDX12SharedTexture* GetSharedTexture() override { return this; } + bool IsInitialized() override { return _isInitiliazed; } + +private: + GDX12Device* _transferFromDeivce; + GDX12Device* _transferToDevice; + UINT64 _heapSize; + ComPtr _sharedHeap; + GDX12TextureResource _sharedTexturePrimary; + GDX12TextureResource _sharedTextureSecondary; + DXGI_FORMAT _format; + UINT _width; + UINT _height; + bool _isInitiliazed; + + void CreateSharedHeap() + { + D3D12_RESOURCE_DESC desc = {}; + desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + desc.Alignment = 0; + desc.Width = _width; + desc.Height = _height; + desc.DepthOrArraySize = 1; + desc.MipLevels = 1; + desc.Format = _format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER; + + D3D12_RESOURCE_ALLOCATION_INFO primaryInfo = _transferFromDeivce->GetDevice()->GetResourceAllocationInfo(0, 1, &desc); + D3D12_RESOURCE_ALLOCATION_INFO secondaryInfo = _transferToDevice->GetDevice()->GetResourceAllocationInfo(0, 1, &desc); + + _heapSize = std::max(primaryInfo.SizeInBytes, secondaryInfo.SizeInBytes); + _heapSize = (_heapSize + D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT - 1) & ~(D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT - 1); + + D3D12_HEAP_DESC heapDesc = {}; + heapDesc.SizeInBytes = _heapSize; + heapDesc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT; + heapDesc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapDesc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapDesc.Properties.CreationNodeMask = 1; + heapDesc.Properties.VisibleNodeMask = 1; + heapDesc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; + heapDesc.Flags = D3D12_HEAP_FLAG_SHARED | D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER; + + ThrowIfFailed(_transferFromDeivce->GetDevice()->CreateHeap( + &heapDesc, IID_PPV_ARGS(&_sharedHeap))); + } + + void CreatePlacedResources() + { + D3D12_RESOURCE_DESC desc = {}; + desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + desc.Alignment = 0; + desc.Width = _width; + desc.Height = _height; + desc.DepthOrArraySize = 1; + desc.MipLevels = 1; + desc.Format = _format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER; + + ThrowIfFailed(_transferFromDeivce->GetDevice()->CreatePlacedResource( + _sharedHeap.Get(), 0, &desc, D3D12_RESOURCE_STATE_COMMON, nullptr, + IID_PPV_ARGS(&_sharedTexturePrimary.D3DResource)), "Failed to create placed resource on primary device"); + } + + void ShareResources() + { + HANDLE heapHandle = nullptr; + ThrowIfFailed(_transferFromDeivce->GetDevice()->CreateSharedHandle( + _sharedHeap.Get(), nullptr, GENERIC_ALL, nullptr, + &heapHandle)); + + if (!heapHandle) throw std::runtime_error("Failed to create shared handle (handle is null)"); + + Microsoft::WRL::ComPtr sharedHeapOnSecondary; + HRESULT hr = _transferToDevice->GetDevice()->OpenSharedHandle( + heapHandle, + IID_PPV_ARGS(&sharedHeapOnSecondary)); + + CloseHandle(heapHandle); + ThrowIfFailed(hr); + + D3D12_RESOURCE_DESC desc = {}; + desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + desc.Alignment = 0; + desc.Width = _width; + desc.Height = _height; + desc.DepthOrArraySize = 1; + desc.MipLevels = 1; + desc.Format = _format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER; + + ThrowIfFailed(_transferToDevice->GetDevice()->CreatePlacedResource( + sharedHeapOnSecondary.Get(), 0, &desc, D3D12_RESOURCE_STATE_COMMON, + nullptr, IID_PPV_ARGS(&_sharedTextureSecondary.D3DResource))); + } +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12StreamlineSDK.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12StreamlineSDK.h new file mode 100644 index 0000000..3201c02 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12StreamlineSDK.h @@ -0,0 +1,130 @@ +#pragma once + +#include "Engine.RendererDX12/D3DHelpers.h" + +#include + +#ifdef free +#pragma push_macro("free") +#undef free +#define PEP_RESTORE_FREE_MACRO_STREAMLINE 1 +#endif +#include "nvidia-sdk/sl.h" +#include "nvidia-sdk/sl_consts.h" +#include "nvidia-sdk/sl_dlss.h" +#include "nvidia-sdk/sl_helpers.h" +#ifdef PEP_RESTORE_FREE_MACRO_STREAMLINE +#pragma pop_macro("free") +#undef PEP_RESTORE_FREE_MACRO_STREAMLINE +#endif + +class GDX12StreamlineSDK +{ +public: + static GDX12StreamlineSDK& Get(); + + bool Initialize(); + void Shutdown(); + + bool IsEnabled() const; + + static std::string ResultToString(sl::Result result); + + ComPtr CreateProxyFactory(const ComPtr& nativeFactory) const; + ComPtr CreateProxyDevice(const ComPtr& nativeDevice, bool setAsMainDevice) const; + ComPtr GetNativeFactory(const ComPtr& factory) const; + ComPtr GetNativeDevice(const ComPtr& device) const; + ComPtr GetNativeCommandQueue(const ComPtr& commandQueue) const; + ComPtr GetNativeSwapChain(const ComPtr& swapChain) const; + ComPtr GetNativeResource(const ComPtr& resource) const; + sl::Result IsFeatureSupported(sl::Feature feature, const sl::AdapterInfo& adapterInfo) const; + sl::Result GetNewFrameToken(sl::FrameToken*& token, const uint32_t* frameIndex = nullptr) const; + sl::Result SetTagForFrame(const sl::FrameToken& frame, const sl::ViewportHandle& viewport, const sl::ResourceTag* tags, uint32_t numTags, sl::CommandBuffer* cmdBuffer) const; + sl::Result EvaluateFeature(sl::Feature feature, const sl::FrameToken& frame, const sl::BaseStructure** inputs, uint32_t numInputs, sl::CommandBuffer* cmdBuffer) const; + sl::Result FreeResources(sl::Feature feature, const sl::ViewportHandle& viewport) const; + sl::Result SetConstants(const sl::Constants& values, const sl::FrameToken& frame, const sl::ViewportHandle& viewport) const; + sl::Result DLSSGetOptimalSettings(const sl::DLSSOptions& options, sl::DLSSOptimalSettings& settings) const; + sl::Result DLSSSetOptions(const sl::ViewportHandle& viewport, const sl::DLSSOptions& options) const; + +private: + GDX12StreamlineSDK() = default; + + static void StreamlineLog(sl::LogType type, const char* message); + + std::wstring GetRuntimeDirectory() const; + void LoadInterposer(); + void LoadFunctions(); + sl::Result LoadDLSSFunctions() const; + + void Log(const std::string& message) const; + void LogWarning(const std::string& message) const; + void LogFailure(const char* operation, sl::Result result) const; + + template + sl::Result LoadFeatureFunction(sl::Feature feature, const char* functionName, T*& function) const + { + if (function) { return sl::Result::eOk; } + if (!_initialized || !_slGetFeatureFunction) { return sl::Result::eErrorInvalidState; } + + void* rawFunction = nullptr; + const sl::Result result = _slGetFeatureFunction(feature, functionName, rawFunction); + if (result == sl::Result::eOk) { function = reinterpret_cast(rawFunction); } + + return result; + } + + template + ComPtr UpgradeInterface(const ComPtr& baseInterface, const char* interfaceName) const + { + if (!_initialized || !_slUpgradeInterface || !baseInterface) { return baseInterface; } + + T* upgradedInterface = baseInterface.Get(); + const T* originalInterface = upgradedInterface; + const sl::Result result = _slUpgradeInterface(reinterpret_cast(&upgradedInterface)); + if (result != sl::Result::eOk) + { + LogFailure(interfaceName, result); + return baseInterface; + } + + if (!upgradedInterface || upgradedInterface == originalInterface) { return baseInterface; } + + ComPtr proxyInterface; + proxyInterface.Attach(upgradedInterface); + return proxyInterface; + } + + template + ComPtr UnwrapInterface(const ComPtr& proxyInterface) const + { + if (!_initialized || !_slGetNativeInterface || !proxyInterface) { return proxyInterface; } + + T* nativeInterface = nullptr; + const sl::Result result = _slGetNativeInterface(proxyInterface.Get(), reinterpret_cast(&nativeInterface)); + if (result != sl::Result::eOk || !nativeInterface) { return proxyInterface; } + + ComPtr baseInterface; + baseInterface.Attach(nativeInterface); + return baseInterface; + } + + HMODULE _interposerModule = nullptr; + bool _initialized = false; + bool _mainDeviceWasSet = false; + std::wstring _runtimeDirectory; + + PFun_slInit* _slInit = nullptr; + PFun_slShutdown* _slShutdown = nullptr; + PFun_slUpgradeInterface* _slUpgradeInterface = nullptr; + PFun_slGetNativeInterface* _slGetNativeInterface = nullptr; + PFun_slSetD3DDevice* _slSetD3DDevice = nullptr; + PFun_slIsFeatureSupported* _slIsFeatureSupported = nullptr; + PFun_slGetFeatureFunction* _slGetFeatureFunction = nullptr; + PFun_slEvaluateFeature* _slEvaluateFeature = nullptr; + PFun_slFreeResources* _slFreeResources = nullptr; + PFun_slSetTagForFrame* _slSetTagForFrame = nullptr; + PFun_slSetConstants* _slSetConstants = nullptr; + PFun_slGetNewFrameToken* _slGetNewFrameToken = nullptr; + mutable PFun_slDLSSGetOptimalSettings* _slDLSSGetOptimalSettings = nullptr; + mutable PFun_slDLSSSetOptions* _slDLSSSetOptions = nullptr; +}; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h index 359624c..13e7460 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h @@ -1,12 +1,13 @@ #pragma once #include "Engine.RendererDX12/D3DHelpers.h" +#include "Engine.RendererDX12/IRenderPassLink.h" class GDX12Device; class GDX12Texture; class GDX12DescriptorHeap; -class GDX12SwapChain +class GDX12SwapChain : public IRenderPassLink { public: GDX12SwapChain(GDX12Device* device, HWND hwnd, @@ -25,15 +26,20 @@ class GDX12SwapChain GDX12Texture* GetBuffer(UINT index); D3D12_VIEWPORT GetViewport(); D3D12_RECT GetScissorRect(); - + GDX12Texture* GetTexture() override; + bool IsInitialized() override; const ComPtr& GetSwapChain(); void Reset(); + bool bVSyncEnabled; + private: void CreateBuffers(); + IDXGISwapChain4* GetPresentationSwapChain() const; GDX12Device* _device; + ComPtr _proxySwapChain; ComPtr _swapChain; GDX12DescriptorHeap* _rtvHeap; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h index 74a7805..6bb9693 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h @@ -2,6 +2,9 @@ #include "Engine.RendererDX12\D3DHelpers.h" +#include "Engine.Core/Types/TextureTypes.h" +#include "Engine.RendererDX12/IRenderPassLink.h" + class GDX12Descriptor; class GDX12DescriptorHeap; class GDX12Device; @@ -15,6 +18,22 @@ enum class ETextureSemantic Data, }; +namespace +{ + ETextureSemantic ConvertTextureSemantic(const Engine::Core::ETextureType textureType) + { + switch (textureType) + { + case Engine::Core::ETextureType::Color: + return ETextureSemantic::Color; + case Engine::Core::ETextureType::Data: + return ETextureSemantic::Data; + default: + return ETextureSemantic::Unknown; + } + } +} + struct GDX12TextureDesc { GDX12DescriptorHeap* SRV_UAV_Heap = nullptr; @@ -44,12 +63,14 @@ struct GDX12TextureDesc ComPtr ExternalResource = nullptr; }; -class GDX12Texture +class GDX12Texture : public IRenderPassLink { public: - GDX12Texture(GDX12TextureDesc desc); + GDX12Texture(); ~GDX12Texture(); + void Initialize(GDX12TextureDesc desc); + //Recreates resources with new size and same descriptors //This will wipe all data on said resources, unless ExternalResource is provided void Resize(UINT width, UINT height); @@ -58,11 +79,20 @@ class GDX12Texture GDX12Descriptor* GetRTV(); GDX12Descriptor* GetUAV(); GDX12Descriptor* GetDSV(); + bool HasDSV(); + bool HasSRV(); + bool HasUAV(); + bool HasRTV(); D3D12_CLEAR_VALUE& GetClearValue(); GDX12TextureResource* GetResource(); DXGI_FORMAT GetFormat(); ETextureSemantic GetSemantic() const; - + D3D12_VIEWPORT GetViewport(); + D3D12_RECT GetScissorRect(); + UINT GetWidth(); + UINT GetHeight(); + GDX12Texture* GetTexture() override; + bool IsInitialized() override; private: void CreateResource(); @@ -77,4 +107,9 @@ class GDX12Texture std::unique_ptr _uav; std::unique_ptr _dsv; D3D12_CLEAR_VALUE _clearValue; + + D3D12_VIEWPORT _viewport; + D3D12_RECT _scissorRect; + + bool _isInitialized; }; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12TextureResource.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12TextureResource.h index 34de206..77408ac 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12TextureResource.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12TextureResource.h @@ -7,6 +7,7 @@ class GDX12TextureResource : public GDX12Resource { public: GDX12TextureResource(ComPtr resource); + GDX12TextureResource(); ~GDX12TextureResource(); // Enhanced texture barrier transition getters @@ -28,7 +29,7 @@ class GDX12TextureResource : public GDX12Resource D3D12_BARRIER_ACCESS accessAfter, D3D12_BARRIER_LAYOUT layoutAfter); void SetCurrentState(D3D12_BARRIER_SYNC sync, D3D12_BARRIER_ACCESS access, D3D12_BARRIER_LAYOUT layout); - + void ResetState() override; D3D12_BARRIER_SYNC GetCurrentSync(); D3D12_BARRIER_ACCESS GetCurrentAccess(); D3D12_BARRIER_LAYOUT GetCurrentLayout(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h new file mode 100644 index 0000000..9ec233d --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h @@ -0,0 +1,21 @@ +#pragma once + +class GDX12Texture; +class GDX12SharedTexture; +class RenderPipelineCommonData; + +class IRenderPassLink +{ +public: + virtual GDX12Texture* GetTexture() + { + OutputDebugStringA("ERROR: Forbidden interface call\n"); + return nullptr; + } + virtual GDX12SharedTexture* GetSharedTexture() + { + OutputDebugStringA("ERROR: Forbidden interface call\n"); + return nullptr; + } + virtual bool IsInitialized() { return false; } +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h new file mode 100644 index 0000000..3410e1b --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h @@ -0,0 +1,317 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" +#include "Common/GameTimer.h" + +// HOLY SHIT +// we need this crazy include since SL's free() function conflits with CRT library's free() function +#ifdef free +#pragma push_macro("free") +#undef free +#define PEP_RESTORE_FREE_MACRO_DLSS_PASS 1 +#endif +#include "nvidia-sdk/sl.h" +#include "nvidia-sdk/sl_consts.h" +#include "nvidia-sdk/sl_dlss.h" +#ifdef PEP_RESTORE_FREE_MACRO_DLSS_PASS +#pragma pop_macro("free") +#undef PEP_RESTORE_FREE_MACRO_DLSS_PASS +#endif +#include "Engine.RendererDX12/GDX12StreamlineSDK.h" + +class GDX12DLSSUpscalePass : public GDX12RenderPass +{ +public: + GDX12DLSSUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), _viewportHandle(1337), + _DLSSQualityMode(sl::DLSSMode::eMaxQuality) + { _flags = RENDER_PASS_FLAG_UPSCALER | RENDER_PASS_FLAG_USE_JITTER | RENDER_PASS_FLAG_USE_STREAMLINE; } + + virtual void SetInputs(std::vector inputs) override + { + _inputs = inputs; + _numInputs = 2; + MatchOutputCount(inputs.size() > 2 ? inputs.size() - 2 : 0); + } + + IRenderPassLink* GetOutput(UINT index) override + { + if (_inputs.empty()) { MatchOutputCount(index + 1); } + return GDX12RenderPass::GetOutput(index); + } + + // Input 0 - DepthStencil + // Input 1 - MotionVectors + // Input N - Input Texture + // Output N - UpscaledTexture + void Initialize() override + { + _commonData->Upscaler = this; + + IN_DepthBuffer = _inputs[0]; + IN_MotionVectors = _inputs[1]; + + GDX12TextureDesc TextureDesc1; + TextureDesc1.Width = _commonData->WindowWidth; + TextureDesc1.Height = _commonData->WindowHeight; + + TextureDesc1.CreateSRV = true; + TextureDesc1.SRV_UAV_Heap = _resources->SRV_UAV_Heap.get(); + TextureDesc1.SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + TextureDesc1.SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + TextureDesc1.SRVDesc.Texture2D.MipLevels = 1; + TextureDesc1.SRVDesc.Texture2D.MostDetailedMip = 0; + TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; + TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; + + IN_Textures.resize(_numOutputs); + for (UINT i = 0; i < _numOutputs; i++) + { + IN_Textures[i] = _inputs[i + 2]; + GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = inputTexture->GetFormat(); + TextureDesc1.SRVHeapIndex = _resources->SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + OUT_UpscaledTextures[i]->Initialize(TextureDesc1); + } + + } + + void Setup(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) override + { + GDX12RenderPass::Setup(initOnResources, otherResources, commonData); + + CheckDLSSSupport(); + QueryRenderTargetResolution(); + CreateDLSSFeature(); + } + + void Execute(GDX12CommandList* cmdList) override + { + using namespace sl; + + cmdList->BeginPixEvent("DLSS Upscale Pass", Colors::Blue); + + FrameToken* currentFrame = nullptr; + Result result = GDX12StreamlineSDK::Get().GetNewFrameToken(currentFrame); + if (result != Result::eOk || currentFrame == nullptr) + { + std::string errorMsg = "DLSS: Failed to get a frame token: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + cmdList->EndPixEvent(); + return; + } + + SetConstants(currentFrame); + + GDX12Texture* depthStencil = IN_DepthBuffer->GetTexture(); + GDX12Texture* motionVectors = IN_MotionVectors->GetTexture(); + + Resource depthResource = Resource{ ResourceType::eTex2d, + depthStencil->GetResource()->D3DResource.Get(), + nullptr, nullptr, static_cast(depthStencil->GetResource()->GetCurrentState()) }; + + Resource mvecResource = Resource{ ResourceType::eTex2d, + motionVectors->GetResource()->D3DResource.Get(), + nullptr, nullptr, static_cast(motionVectors->GetResource()->GetCurrentState()) }; + + Extent fullExtent{}; + fullExtent.top = 0; + fullExtent.left = 0; + fullExtent.width = _commonData->DownscaledWidth; + fullExtent.height = _commonData->DownscaledHeight; + + Extent outputExtent{}; + outputExtent.top = 0; + outputExtent.left = 0; + outputExtent.width = _commonData->WindowWidth; + outputExtent.height = _commonData->WindowHeight; + + ResourceTag depthTag{ &depthResource, kBufferTypeDepth, ResourceLifecycle::eValidUntilEvaluate, &fullExtent }; + ResourceTag mvecTag{ &mvecResource, kBufferTypeMotionVectors, ResourceLifecycle::eValidUntilEvaluate, &fullExtent }; + + for (int i = 0; i < _numOutputs; i++) + { + GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); + GDX12Texture* upscaledTexture = OUT_UpscaledTextures[i].get(); + + Resource inputResource = Resource{ ResourceType::eTex2d, + inputTexture->GetResource()->D3DResource.Get(), + nullptr, nullptr, static_cast(inputTexture->GetResource()->GetCurrentState()) }; + + Resource outputResource = Resource{ ResourceType::eTex2d, + upscaledTexture->GetResource()->D3DResource.Get(), + nullptr, nullptr, static_cast(upscaledTexture->GetResource()->GetCurrentState()) }; + + ResourceTag inputTag{ &inputResource, kBufferTypeScalingInputColor, ResourceLifecycle::eValidUntilEvaluate, &fullExtent }; + ResourceTag outputTag{ &outputResource, kBufferTypeScalingOutputColor, ResourceLifecycle::eValidUntilEvaluate, &outputExtent }; + + ResourceTag tags[] = { depthTag, mvecTag, inputTag, outputTag }; + result = GDX12StreamlineSDK::Get().SetTagForFrame(*currentFrame, _viewportHandle, tags, _countof(tags), cmdList->GetCommandList().Get()); + if (result != Result::eOk) + { + std::string errorMsg = "DLSS: Failed to set tags: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + } + + const BaseStructure* inputs[] = { &_viewportHandle }; + result = GDX12StreamlineSDK::Get().EvaluateFeature(kFeatureDLSS, *currentFrame, inputs, _countof(inputs), cmdList->GetCommandList().Get()); + if (result != Result::eOk) + { + std::string errorMsg = "DLSS EVALUATE ERROR: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + } + + } + cmdList->EndPixEvent(); + } + + void Resize() override + { + for (auto& texture : OUT_UpscaledTextures) { texture->Resize(_commonData->WindowWidth, _commonData->WindowHeight); } + GDX12StreamlineSDK::Get().FreeResources(sl::kFeatureDLSS, _viewportHandle); + GDX12StreamlineSDK::Get().DLSSSetOptions(_viewportHandle, sl::DLSSOptions{}); + CreateDLSSFeature(); + } + + void QueryRenderTargetResolution() override + { + using namespace sl; + + DLSSOptions dlssOptions = {}; + dlssOptions.mode = _DLSSQualityMode; + dlssOptions.outputWidth = _commonData->WindowWidth; + dlssOptions.outputHeight = _commonData->WindowHeight; + + DLSSOptimalSettings optimalSettings = {}; + Result result = GDX12StreamlineSDK::Get().DLSSGetOptimalSettings(dlssOptions, optimalSettings); + if (result != Result::eOk) + { + std::string errorMsg = "DLSS: Failed to get optimal settings: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + _commonData->DownscaledWidth = _commonData->WindowWidth; + _commonData->DownscaledHeight = _commonData->WindowHeight; + return; + } + + if (optimalSettings.optimalRenderWidth == 0 || optimalSettings.optimalRenderHeight == 0) + { + OutputDebugStringA("DLSS: Optimal settings returned a zero-sized render resolution, falling back to full-resolution rendering.\n"); + _commonData->DownscaledWidth = _commonData->WindowWidth; + _commonData->DownscaledHeight = _commonData->WindowHeight; + return; + } + + _commonData->DownscaledWidth = optimalSettings.optimalRenderWidth; + _commonData->DownscaledHeight = optimalSettings.optimalRenderHeight; + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + GDX12StreamlineSDK::Get().FreeResources(sl::kFeatureDLSS, _viewportHandle); + IN_DepthBuffer = nullptr; + IN_MotionVectors = nullptr; + IN_Textures.clear(); + OUT_UpscaledTextures.clear(); + } + +private: + IRenderPassLink* IN_DepthBuffer; + IRenderPassLink* IN_MotionVectors; + std::vector IN_Textures; + std::vector> OUT_UpscaledTextures; + sl::ViewportHandle _viewportHandle; + sl::DLSSMode _DLSSQualityMode; + + void MatchOutputCount(UINT outputCount) + { + if (OUT_UpscaledTextures.size() < outputCount) { OUT_UpscaledTextures.resize(outputCount); } + if (_outputs.size() < outputCount) { _outputs.resize(outputCount, nullptr); } + + for (UINT i = 0; i < outputCount; i++) + { + if (!OUT_UpscaledTextures[i]) { OUT_UpscaledTextures[i] = std::make_unique(); } + _outputs[i] = OUT_UpscaledTextures[i].get(); + } + + _numOutputs = outputCount; + } + + bool CheckDLSSSupport() + { + using namespace sl; + + LUID adapterLuid = _resources->Device->GetDevice()->GetAdapterLuid(); + AdapterInfo adapterInfo = {}; + adapterInfo.deviceLUID = reinterpret_cast(&adapterLuid); + adapterInfo.deviceLUIDSizeInBytes = sizeof(adapterLuid); + + Result result = GDX12StreamlineSDK::Get().IsFeatureSupported(kFeatureDLSS, adapterInfo); + if (result == Result::eOk) { return true; } + + std::string errorMsg = "ERROR: DLSS Feature is not supported on the current adapter: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + return false; + } + + void SetConstants(sl::FrameToken* currentFrameToken) + { + using namespace sl; + + Constants constants = {}; + + //expects row major unjittered matrices + constants.cameraViewToClip = *reinterpret_cast(&_commonData->CameraViewToClip); + constants.clipToCameraView = *reinterpret_cast(&_commonData->ClipToCameraView); + constants.clipToPrevClip = *reinterpret_cast(&_commonData->ClipToPrevClip); + constants.prevClipToClip = *reinterpret_cast(&_commonData->PrevClipToClip); + + constants.cameraNear = _commonData->ActiveCameraNearPlane; + constants.cameraFar = _commonData->ActiveCameraFarPlane; + constants.cameraFOV = XMConvertToRadians(_commonData->ActiveCameraFOV); + constants.cameraAspectRatio = static_cast(_commonData->WindowWidth) / _commonData->WindowHeight; + + constants.jitterOffset = { -_commonData->ActiveCameraJitterOffsetX, -_commonData->ActiveCameraJitterOffsetY }; + constants.mvecScale = { 1.f, 1.f }; + + constants.depthInverted = Boolean::eTrue; + constants.cameraMotionIncluded = Boolean::eTrue; + constants.motionVectors3D = Boolean::eFalse; + constants.reset = Boolean::eFalse; + constants.orthographicProjection = Boolean::eFalse; + constants.motionVectorsDilated = Boolean::eFalse; + constants.motionVectorsJittered = Boolean::eFalse; + + Result result = GDX12StreamlineSDK::Get().SetConstants(constants, *currentFrameToken, _viewportHandle); + if (result != Result::eOk) + { + std::string errorMsg = "DLSS: Failed to set constants: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + } + } + + void CreateDLSSFeature() + { + using namespace sl; + + // Create DLSS feature + DLSSOptions dlssOptions = {}; + dlssOptions.mode = _DLSSQualityMode; + dlssOptions.outputWidth = _commonData->WindowWidth; + dlssOptions.outputHeight = _commonData->WindowHeight; + dlssOptions.sharpness = 0.25f; + dlssOptions.colorBuffersHDR = Boolean::eFalse; + + Result result = GDX12StreamlineSDK::Get().DLSSSetOptions(_viewportHandle, dlssOptions); + if (result != Result::eOk) + { + std::string errorMsg = "ERROR: Failed to set DLSS options: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + return; + } + + } + + std::string SLResultToString(sl::Result result) + { + return GDX12StreamlineSDK::ResultToString(result); + } +}; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h new file mode 100644 index 0000000..c047854 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -0,0 +1,222 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" +#include "Common/GameTimer.h" + +#include "ffx-api/ffx_api.h" +#include "ffx-api/ffx_upscale.h" +#include "ffx-api/dx12/ffx_api_dx12.h" + +class GDX12FSRUpscalePass : public GDX12RenderPass +{ +public: + GDX12FSRUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), _FFXContext(nullptr), + _FSRQualityMode(FFX_UPSCALE_QUALITY_MODE_QUALITY) + { _flags = RENDER_PASS_FLAG_UPSCALER | RENDER_PASS_FLAG_USE_JITTER; } + + virtual void SetInputs(std::vector inputs) override + { + _inputs = inputs; + _numInputs = 2; + MatchOutputCount(inputs.size() > 2 ? inputs.size() - 2 : 0); + } + + IRenderPassLink* GetOutput(UINT index) override + { + if (_inputs.empty()) { MatchOutputCount(index + 1); } + return GDX12RenderPass::GetOutput(index); + } + + // Input 0 - DepthStencil + // Input 1 - MotionVectors + // Input N - Input Texture + // Output N - UpscaledTexture + void Initialize() override + { + _commonData->Upscaler = this; + + IN_DepthBuffer = _inputs[0]; + IN_MotionVectors = _inputs[1]; + + GDX12TextureDesc TextureDesc1; + TextureDesc1.Width = _commonData->WindowWidth; + TextureDesc1.Height = _commonData->WindowHeight; + + TextureDesc1.CreateSRV = true; + TextureDesc1.SRV_UAV_Heap = _resources->SRV_UAV_Heap.get(); + TextureDesc1.SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + TextureDesc1.SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + TextureDesc1.SRVDesc.Texture2D.MipLevels = 1; + TextureDesc1.SRVDesc.Texture2D.MostDetailedMip = 0; + TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; + TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; + + IN_Textures.resize(_numOutputs); + for (UINT i = 0; i < _numOutputs; i++) + { + IN_Textures[i] = _inputs[i + 2]; + GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = inputTexture->GetFormat(); + TextureDesc1.SRVHeapIndex = _resources->SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + OUT_UpscaledTextures[i]->Initialize(TextureDesc1); + } + + } + + void Setup(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) override + { + GDX12RenderPass::Setup(initOnResources, otherResources, commonData); + + BuildFSRContext(); + QueryRenderTargetResolution(); + } + + void Execute(GDX12CommandList* cmdList) override + { + GDX12Texture* depthStencil = IN_DepthBuffer->GetTexture(); + GDX12Texture* motionVectors = IN_MotionVectors->GetTexture(); + + cmdList->BeginPixEvent("FSR Upscale Pass", Colors::Blue); + ffxDispatchDescUpscale dispatchDesc; + dispatchDesc.header.type = FFX_API_DISPATCH_DESC_TYPE_UPSCALE; + dispatchDesc.commandList = cmdList->GetCommandList().Get(); + dispatchDesc.depth = ffxApiGetResourceDX12(depthStencil->GetResource()->D3DResource.Get(), FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchDesc.motionVectors = ffxApiGetResourceDX12(motionVectors->GetResource()->D3DResource.Get(), FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ); + // Resolution before upscaling + dispatchDesc.renderSize = { _commonData->DownscaledWidth, _commonData->DownscaledHeight }; + dispatchDesc.motionVectorScale = { static_cast(_commonData->DownscaledWidth), + static_cast(_commonData->DownscaledHeight) }; + dispatchDesc.upscaleSize = { _commonData->WindowWidth, _commonData->WindowHeight }; + // We use inverted depth, this is not a mistake + dispatchDesc.cameraNear = _commonData->ActiveCameraFarPlane; + dispatchDesc.cameraFar = _commonData->ActiveCameraNearPlane; + dispatchDesc.cameraFovAngleVertical = XMConvertToRadians(_commonData->ActiveCameraFOV); + + dispatchDesc.jitterOffset.x = -_commonData->ActiveCameraJitterOffsetX; + dispatchDesc.jitterOffset.y = -_commonData->ActiveCameraJitterOffsetY; + + dispatchDesc.enableSharpening = true; + dispatchDesc.sharpness = 1.f; + // for whatever reason, it doesnt like it when frame time is lower than 1.f + float clampedTime = std::max(_commonData->GameTimer->DeltaTime() * 1000.f, 1.f); + dispatchDesc.frameTimeDelta = clampedTime; //expects milliseconds + dispatchDesc.reset = false; // set to true if camera teleports or moves not smoothly + + dispatchDesc.preExposure = 1.f; + dispatchDesc.viewSpaceToMetersFactor = 1.f; + + dispatchDesc.exposure = ffxApiGetResourceDX12(nullptr, FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchDesc.reactive = ffxApiGetResourceDX12(nullptr, FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchDesc.transparencyAndComposition = ffxApiGetResourceDX12(nullptr, FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ); + //dispatchDesc.flags = FFX_UPSCALE_FLAG_DRAW_DEBUG_VIEW; + dispatchDesc.flags = 0; + for (int i = 0; i < _numOutputs; i++) + { + GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); + GDX12Texture* upscaledTexture = OUT_UpscaledTextures[i].get(); + dispatchDesc.color = ffxApiGetResourceDX12(inputTexture->GetResource()->D3DResource.Get(), FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ); + dispatchDesc.output = ffxApiGetResourceDX12(upscaledTexture->GetResource()->D3DResource.Get(), FFX_API_RESOURCE_STATE_UNORDERED_ACCESS); + + ffxReturnCode_t dispatchError = ffxDispatch(&_FFXContext, &dispatchDesc.header); + if (dispatchError != FFX_API_RETURN_OK) + { + std::string errorMsg = "FSR DISPATCH ERROR: " + std::to_string(dispatchError) + " \n"; + OutputDebugStringA(errorMsg.c_str()); + } + } + cmdList->EndPixEvent(); + } + + void Resize() override + { + for (auto& texture : OUT_UpscaledTextures) { texture->Resize(_commonData->WindowWidth, _commonData->WindowHeight); } + ffxDestroyContext(&_FFXContext, nullptr); + BuildFSRContext(); + } + + void QueryRenderTargetResolution() override + { + ffxQueryDescUpscaleGetRenderResolutionFromQualityMode queryDesc = {}; + queryDesc.header.type = FFX_API_QUERY_DESC_TYPE_UPSCALE_GETRENDERRESOLUTIONFROMQUALITYMODE; + queryDesc.displayHeight = _commonData->WindowHeight; + queryDesc.displayWidth = _commonData->WindowWidth; + queryDesc.qualityMode = _FSRQualityMode; + queryDesc.pOutRenderHeight = &_commonData->DownscaledHeight; + queryDesc.pOutRenderWidth = &_commonData->DownscaledWidth; + ffxQuery(&_FFXContext, &queryDesc.header); + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + + if (_FFXContext) { ffxDestroyContext(&_FFXContext, nullptr); } + IN_DepthBuffer = nullptr; + IN_MotionVectors = nullptr; + IN_Textures.clear(); + OUT_UpscaledTextures.clear(); + } + +private: + IRenderPassLink* IN_DepthBuffer; + IRenderPassLink* IN_MotionVectors; + std::vector IN_Textures; + std::vector> OUT_UpscaledTextures; + ffxContext _FFXContext; + FfxApiUpscaleQualityMode _FSRQualityMode; + + void MatchOutputCount(UINT outputCount) + { + if (OUT_UpscaledTextures.size() < outputCount) { OUT_UpscaledTextures.resize(outputCount); } + if (_outputs.size() < outputCount) { _outputs.resize(outputCount, nullptr); } + + for (UINT i = 0; i < outputCount; i++) + { + if (!OUT_UpscaledTextures[i]) { OUT_UpscaledTextures[i] = std::make_unique(); } + _outputs[i] = OUT_UpscaledTextures[i].get(); + } + + _numOutputs = outputCount; + } + + void BuildFSRContext() + { + ffxCreateBackendDX12Desc backendDesc = {}; + backendDesc.header.type = FFX_API_CREATE_CONTEXT_DESC_TYPE_BACKEND_DX12; + backendDesc.device = _resources->Device->GetDevice().Get(); + + ffxCreateContextDescUpscale upscaleDesc = {}; + upscaleDesc.header.type = FFX_API_CREATE_CONTEXT_DESC_TYPE_UPSCALE; + upscaleDesc.header.pNext = &backendDesc.header; + upscaleDesc.maxRenderSize = { static_cast(_commonData->WindowWidth), static_cast(_commonData->WindowHeight) }; + upscaleDesc.maxUpscaleSize = { static_cast(_commonData->WindowWidth), static_cast(_commonData->WindowHeight) }; + upscaleDesc.flags = FFX_UPSCALE_ENABLE_DEBUG_CHECKING | FFX_UPSCALE_ENABLE_DEPTH_INVERTED; + upscaleDesc.fpMessage = [](uint32_t type, const wchar_t* message) + { + std::wstring wideMessage(message); + std::string narrowMessage(wideMessage.begin(), wideMessage.end()); + + std::string prefix; + switch (type) { + case FFX_API_MESSAGE_TYPE_ERROR: + prefix = "[FFX ERROR] "; + break; + case FFX_API_MESSAGE_TYPE_WARNING: + prefix = "[FFX WARNING] "; + break; + default: + prefix = "[FFX DEBUG] "; + break; + } + + std::string fullMessage = prefix + narrowMessage + "\n"; + OutputDebugStringA(fullMessage.c_str()); + }; + + ffxReturnCode_t errorCode = ffxCreateContext(&_FFXContext, &upscaleDesc.header, nullptr); + if (errorCode != FFX_API_RETURN_OK) + { + std::string errorMsg = "ERROR: FSR3 CONTEXT CREATION FAILED\n"; + OutputDebugStringA(errorMsg.c_str()); + } + } +}; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h new file mode 100644 index 0000000..c19f414 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h @@ -0,0 +1,104 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" + +class GDX12GPUCullingPass : public GDX12RenderPass +{ +public: + GDX12GPUCullingPass() + { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_INSTANCES; } + + void Setup(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) override + { + GDX12RenderPass::Setup(initOnResources, otherResources, commonData); + + // Shaders + auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); + _cullingCS = shaderCompiler.CompileShader(_resources->Device, SHADERS_FOLDER "Culling.hlsl", nullptr, "CS", "cs"); + _bufferClearCS = shaderCompiler.CompileShader(_resources->Device, SHADERS_FOLDER "BufferClear.hlsl", nullptr, "CS", "cs"); + + // Root Signatures + GDX12RootSignatureDesc RSDesc1; + RSDesc1.NumSingleCBVSlots = 1; + RSDesc1.NumSingleSRVSlots = 3; + RSDesc1.NumSingleUAVSlots = 4; + _cullingRS = std::make_unique(_resources->Device, RSDesc1); + + GDX12RootSignatureDesc RSDesc2; + RSDesc2.NumSingleUAVSlots = 2; + _bufferClearRS = std::make_unique(_resources->Device, RSDesc2); + + // Pipeline State Objects + D3D12_COMPUTE_PIPELINE_STATE_DESC PSODesc1 = {}; + PSODesc1.pRootSignature = _cullingRS->GetRootSignature().Get(); + PSODesc1.CS = { reinterpret_cast(_cullingCS->GetBufferPointer()), _cullingCS->GetBufferSize() }; + + ThrowIfFailed(_resources->Device->GetDevice()->CreateComputePipelineState( + &PSODesc1, IID_PPV_ARGS(&_cullingPSO))); + + D3D12_COMPUTE_PIPELINE_STATE_DESC PSODesc2 = {}; + PSODesc2.pRootSignature = _bufferClearRS->GetRootSignature().Get(); + PSODesc2.CS = { reinterpret_cast(_bufferClearCS->GetBufferPointer()), _bufferClearCS->GetBufferSize() }; + + ThrowIfFailed(_resources->Device->GetDevice()->CreateComputePipelineState( + &PSODesc2, IID_PPV_ARGS(&_bufferClearPSO))); + } + + // automatically uses IN_OUT_CameraVisibilityBuffers from cameraCBIndex + void Execute(GDX12CommandList* cmdList) override + { + auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[_commonData->ActiveCameraCBufferIndex]; + + cmdList->BeginPixEvent("GPU Mesh Culling", Colors::Blue); + cmdList->ResourceBarrier({ + currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().GetUnorderedAccessBarrier(), + currentCameraVisBuffers.OpaqueDrawCounter->GetResource().GetUnorderedAccessBarrier(), + currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().GetUnorderedAccessBarrier(), + currentCameraVisBuffers.TransparentDrawCounter->GetResource().GetUnorderedAccessBarrier() }); + + cmdList->SetComputeRootSignature(_bufferClearRS.get()); + cmdList->SetPipelineState(_bufferClearPSO); + cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); + cmdList->SetComputeUAV(0, currentCameraVisBuffers.OpaqueDrawCounter->GetUAV()->GPUHandle); + cmdList->SetComputeUAV(1, currentCameraVisBuffers.TransparentDrawCounter->GetUAV()->GPUHandle); + cmdList->Dispatch(1, 1, 1); + + cmdList->SetComputeRootSignature(_cullingRS.get()); + cmdList->SetPipelineState(_cullingPSO); + cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); + cmdList->SetComputeRootConstantBufferView(0, currentFrameConstants->CameraCB->GetElementAddress(_commonData->ActiveCameraCBufferIndex)); + cmdList->SetComputeSRV(0, currentFrameConstants->InstanceCache->GetSRV()->GPUHandle); + cmdList->SetComputeSRV(1, _resources->IndirectCommandsCache->GetSRV()->GPUHandle); + cmdList->SetComputeSRV(2, currentFrameConstants->MaterialCache->GetSRV()->GPUHandle); + cmdList->SetComputeUAV(0, currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetUAV()->GPUHandle); + cmdList->SetComputeUAV(1, currentCameraVisBuffers.OpaqueDrawCounter->GetUAV()->GPUHandle); + cmdList->SetComputeUAV(2, currentCameraVisBuffers.VisibleTransparentCommandsCache->GetUAV()->GPUHandle); + cmdList->SetComputeUAV(3, currentCameraVisBuffers.TransparentDrawCounter->GetUAV()->GPUHandle); + cmdList->Dispatch((_resources->IndirectCommandsCache->GetElementCount() + 63) / 64, 1, 1); + + cmdList->ResourceBarrier({ + currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().GetUAVBarrier(), + currentCameraVisBuffers.OpaqueDrawCounter->GetResource().GetUAVBarrier() }); + cmdList->EndPixEvent(); + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + + _cullingRS.reset(); + _cullingPSO.Reset(); + _bufferClearCS.Reset(); + _bufferClearRS.reset(); + _bufferClearPSO.Reset(); + } + +private: + ComPtr _cullingCS; + std::unique_ptr _cullingRS; + ComPtr _cullingPSO; + + ComPtr _bufferClearCS; + std::unique_ptr _bufferClearRS; + ComPtr _bufferClearPSO; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h new file mode 100644 index 0000000..4e6cd6a --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -0,0 +1,204 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" + +class GDX12OpaquePass : public GDX12RenderPass +{ +public: + GDX12OpaquePass() + { + _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS + | RENDER_PASS_FLAG_USE_INSTANCES; + _numInputs = 0; + _numOutputs = 3; + OUT_Accumulation = std::make_unique(); + OUT_VelocityBuffer = std::make_unique(); + OUT_DepthStencil = std::make_unique(); + + _outputs.push_back(OUT_Accumulation.get()); + _outputs.push_back(OUT_VelocityBuffer.get()); + _outputs.push_back(OUT_DepthStencil.get()); + } + + // Output 0 - AccumulationTexture + // Output 1 - MotionVectors + // Output 2 - DepthStencil + void Initialize() override + { + GDX12TextureDesc TextureDesc1; + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + TextureDesc1.Width = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledWidth : _commonData->WindowWidth; + TextureDesc1.Height = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledHeight : _commonData->WindowHeight; + + TextureDesc1.CreateSRV = true; + TextureDesc1.SRV_UAV_Heap = _resources->SRV_UAV_Heap.get(); + TextureDesc1.SRVHeapIndex = _resources->SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + TextureDesc1.SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + TextureDesc1.SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + TextureDesc1.SRVDesc.Texture2D.MipLevels = 1; + TextureDesc1.SRVDesc.Texture2D.MostDetailedMip = 0; + TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; + TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; + + TextureDesc1.CreateRTV = true; + TextureDesc1.RTVHeap = _resources->RTVHeap.get(); + TextureDesc1.RTVHeapIndex = _resources->RTVHeap->GetAvailableIndex(); + TextureDesc1.RTVDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + TextureDesc1.RTVDesc.Texture2D.PlaneSlice = 0; + TextureDesc1.RTVDesc.Texture2D.MipSlice = 0; + + OUT_Accumulation->Initialize(TextureDesc1); + + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R16G16_FLOAT; + TextureDesc1.RTVHeapIndex = _resources->RTVHeap->GetAvailableIndex(); + TextureDesc1.SRVHeapIndex = _resources->SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + + OUT_VelocityBuffer->Initialize(TextureDesc1); + + GDX12TextureDesc desc; + desc.CreateSRV = false; + desc.DSVHeap = _resources->DSVHeap.get(); + + desc.CreateDSV = true; + desc.DSVHeapIndex = _resources->DSVHeap->GetAvailableIndex(); + desc.Format = desc.DSVDesc.Format = DXGI_FORMAT_D32_FLOAT; + desc.Width = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledWidth : _commonData->WindowWidth;; + desc.Height = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledHeight : _commonData->WindowHeight;; + desc.ClearValue = { 0.f, 0.f, 0.f, 0.f }; + + desc.DSVDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + desc.DSVDesc.Texture2D.MipSlice = 0; + + OUT_DepthStencil->Initialize(desc); + + // Shaders + auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); + _opaqueVS = shaderCompiler.CompileShader(_resources->Device, SHADERS_FOLDER "OpaquePass.hlsl", nullptr, "VS", "vs"); + _opaquePS = shaderCompiler.CompileShader(_resources->Device, SHADERS_FOLDER "OpaquePass.hlsl", nullptr, "PS", "ps"); + + // Root Signatures + GDX12RootSignatureDesc RSDesc1; + RSDesc1.NumSingleCBVSlots = 2; + RSDesc1.NumSingleSRVSlots = 3; + RSDesc1.StaticSamplers = GetStaticSamplers(); + RSDesc1.SRVRanges.push_back(GDX12RootSignatureRange(Texture2D_RangeLength)); + RSDesc1.Constants.push_back(1); + _opaqueRS = std::make_unique(_resources->Device, RSDesc1); + + //Command Signatures + std::vector args; + D3D12_INDIRECT_ARGUMENT_DESC argConst = {}; + argConst.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT; + argConst.Constant.DestOffsetIn32BitValues = 0; + argConst.Constant.Num32BitValuesToSet = 1; + args.push_back(argConst); + D3D12_INDIRECT_ARGUMENT_DESC argDraw = {}; + argDraw.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED; + args.push_back(argDraw); + + D3D12_COMMAND_SIGNATURE_DESC CSDesc1 = {}; + CSDesc1.ByteStride = sizeof(GDX12IndirectDrawArgs); + CSDesc1.NumArgumentDescs = args.size(); + CSDesc1.pArgumentDescs = args.data(); + CSDesc1.NodeMask = 0; + + _resources->Device->GetDevice()->CreateCommandSignature(&CSDesc1, + _opaqueRS->GetRootSignature().Get(), + IID_PPV_ARGS(&_opaqueCS)); + + // Pipeline State Objects + D3D12_GRAPHICS_PIPELINE_STATE_DESC PSODesc1 = {}; + + PSODesc1.InputLayout = { _resources->InputLayouts["Default"].data(), (UINT)_resources->InputLayouts["Default"].size() }; + PSODesc1.pRootSignature = _opaqueRS->GetRootSignature().Get(); + PSODesc1.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + PSODesc1.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + PSODesc1.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + //reversed-Z + PSODesc1.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; + PSODesc1.RasterizerState.FrontCounterClockwise = TRUE; + PSODesc1.SampleMask = UINT_MAX; + PSODesc1.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + PSODesc1.NumRenderTargets = 2; + PSODesc1.RTVFormats[0] = OUT_Accumulation->GetFormat(); + PSODesc1.RTVFormats[1] = OUT_VelocityBuffer->GetFormat(); + PSODesc1.SampleDesc.Count = 1; + PSODesc1.SampleDesc.Quality = 0; + PSODesc1.DSVFormat = OUT_DepthStencil->GetTexture()->GetFormat(); + PSODesc1.VS = { reinterpret_cast(_opaqueVS->GetBufferPointer()), _opaqueVS->GetBufferSize() }; + PSODesc1.PS = { reinterpret_cast(_opaquePS->GetBufferPointer()), _opaquePS->GetBufferSize() }; + ThrowIfFailed(_resources->Device->GetDevice()->CreateGraphicsPipelineState(&PSODesc1, IID_PPV_ARGS(&_opaquePSO))); + } + + // VisibilityBuffers will automatically be selected from CameraCBIndex + // It requires GPUCullingPass to be executed beforehand + void Execute(GDX12CommandList* cmdList) override + { + auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[_commonData->ActiveCameraCBufferIndex]; + GDX12Texture* depthStencil = OUT_DepthStencil->GetTexture(); + + cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); + cmdList->SetViewport(OUT_Accumulation->GetViewport()); + cmdList->SetScissorRect(OUT_Accumulation->GetScissorRect()); + cmdList->SetGraphicsRootSignature(_opaqueRS.get()); + cmdList->SetPipelineState(_opaquePSO.Get()); + cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); + cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> + GetElementAddress(_commonData->ActiveCameraCBufferIndex)); + cmdList->SetGeometryBuffer(_resources->GeometryBuffer.get()); + cmdList->SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); + cmdList->SetGraphicsSRV(0, currentFrameConstants->MaterialCache->GetSRV()->GPUHandle); + cmdList->SetGraphicsSRV(1, currentFrameConstants->TransformCache->GetSRV()->GPUHandle); + cmdList->SetGraphicsSRV(2, currentFrameConstants->InstanceCache->GetSRV()->GPUHandle); + cmdList->SetGraphicsSRV(3, _resources->SRV_UAV_Heap->GetGPUHandle(Texture2D_StartIndex)); + cmdList->ResourceBarrier({ + currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().GetIndirectArgsBarrier(), + currentCameraVisBuffers.OpaqueDrawCounter->GetResource().GetIndirectArgsBarrier(), + OUT_Accumulation->GetResource()->GetRenderTargetBarrier(), + OUT_VelocityBuffer->GetResource()->GetRenderTargetBarrier(), + depthStencil->GetResource()->GetDepthWriteBarrier() }); + cmdList->SetRenderTargets({ OUT_Accumulation.get(), OUT_VelocityBuffer.get() }, depthStencil); + cmdList->ClearDepthStencilView(depthStencil); + cmdList->ClearRenderTargetView(OUT_Accumulation.get()); + cmdList->ClearRenderTargetView(OUT_VelocityBuffer.get()); + cmdList->ExecuteIndirect(_opaqueCS.Get(), _resources->IndirectCommandsCache->GetElementCount(), + currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().D3DResource.Get(), 0, + currentCameraVisBuffers.OpaqueDrawCounter->GetResource().D3DResource.Get(), 0); + cmdList->EndPixEvent(); + } + + void Resize() override + { + UINT newWidth = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledWidth : _commonData->WindowWidth; + UINT newHeight = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledHeight : _commonData->WindowHeight; + OUT_Accumulation->Resize(newWidth, newHeight); + OUT_VelocityBuffer->Resize(newWidth, newHeight); + OUT_DepthStencil->Resize(newWidth, newHeight); + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + + OUT_Accumulation.reset(); + OUT_VelocityBuffer.reset(); + OUT_DepthStencil.reset(); + _opaqueVS.Reset(); + _opaquePS.Reset(); + _opaqueRS.reset(); + _opaqueCS.Reset(); + _opaquePSO.Reset(); + } + +private: + ComPtr _opaqueVS; + ComPtr _opaquePS; + std::unique_ptr _opaqueRS; + ComPtr _opaqueCS; + ComPtr _opaquePSO; + + std::unique_ptr OUT_Accumulation; + std::unique_ptr OUT_VelocityBuffer; + std::unique_ptr OUT_DepthStencil; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h new file mode 100644 index 0000000..203ad10 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h @@ -0,0 +1,48 @@ +#pragma once + +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" + +class GDX12OutputToScreenPass : public GDX12RenderPass +{ +public: + GDX12OutputToScreenPass() : IN_Texture(nullptr), IN_BackBuffer(nullptr) + { + _flags = RENDER_PASS_FLAG_NONE; + _numInputs = 2; + _numOutputs = 0; + } + + // Input 0 - InputTexture + // Input 1 - BackBuffer + void Initialize() override + { + IN_Texture = _inputs[0]; + IN_BackBuffer = _inputs[1]; + } + + void Execute(GDX12CommandList* cmdList) override + { + GDX12Texture* inputTexture = IN_Texture->GetTexture(); + GDX12Texture* backBuffer = IN_BackBuffer->GetTexture(); + + cmdList->BeginPixEvent("Copy To Screen Pass", Colors::Aqua); + cmdList->ResourceBarrier({ inputTexture->GetResource()->GetCopySourceBarrier() }); + cmdList->ResourceBarrier({ backBuffer->GetResource()->GetCopyDestBarrier() }); + cmdList->CopyResource(backBuffer->GetResource()->D3DResource.Get(), + inputTexture->GetResource()->D3DResource.Get()); + cmdList->ResourceBarrier({ backBuffer->GetResource()->GetPresentBarrier() }); + cmdList->EndPixEvent(); + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + + IN_Texture = nullptr; + IN_BackBuffer = nullptr; + } + +private: + IRenderPassLink* IN_Texture; + IRenderPassLink* IN_BackBuffer; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h new file mode 100644 index 0000000..77efd6a --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -0,0 +1,137 @@ +#pragma once + +#include "Engine.RendererDX12/D3DHelpers.h" +#include "Engine.RendererDX12/GDX12Device.h" +#include "Engine.RendererDX12/GDX12DeviceResources.h" +#include "Engine.RendererDX12/GDX12CommandList.h" +#include "Engine.RendererDX12/GDX12CommandQueue.h" +#include "Engine.RendererDX12/GDX12DeviceFactory.h" +#include "Engine.RendererDX12/GDX12ShaderCompiler.h" +#include "Engine.RendererDX12/GDX12TextureResource.h" +#include "Engine.RendererDX12/GDX12Descriptor.h" +#include "Engine.RendererDX12/IRenderPassLink.h" + +class GameTimer; + +enum ERenderPassFlags : uint32_t +{ + RENDER_PASS_FLAG_NONE = 0, + RENDER_PASS_FLAG_USE_GEOMETRY = 1 << 0, + RENDER_PASS_FLAG_USE_MATERIALS = 1 << 1, + RENDER_PASS_FLAG_USE_CAMERAS = 1 << 2, + RENDER_PASS_FLAG_USE_LIGHTING = 1 << 3, + RENDER_PASS_FLAG_USE_INSTANCES = 1 << 4, + RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION = 1 << 5, + RENDER_PASS_FLAG_UPSCALER = 1 << 6, + RENDER_PASS_FLAG_SYNC_DEVICES = 1 << 7, + RENDER_PASS_FLAG_USE_JITTER = 1 << 8, + RENDER_PASS_FLAG_USE_STREAMLINE = 1 << 9 +}; + +class RenderPipelineCommonData; + +class GDX12RenderPass +{ +public: + GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE), _resources(nullptr), + _otherResources(nullptr), _commonData(nullptr), _numInputs(0), _numOutputs(0) {} + virtual ~GDX12RenderPass() = default; + virtual void Setup(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) + { + _resources = initOnResources; + _otherResources = otherResources; + _commonData = commonData; + }; + virtual void Resize() {}; + virtual void Execute(GDX12CommandList* cmdList) {}; + // Used by upscalers to determine downscaled render target size + // And share it with all other passes + virtual void QueryRenderTargetResolution() {}; + + virtual void ClearDenendencies() + { + _inputs.clear(); + _outputs.clear(); + } + // Called after linking with other passes + virtual void Initialize() {} + + uint32_t GetFlags() { return _flags; } + void SetFlag(uint32_t flag, bool value) + { + if (value) { _flags |= flag; } + else { _flags &= ~flag; } + } + bool GetFlagValue(uint32_t flag) { return _flags & flag; } + + void SetInputs(std::initializer_list inputs) { SetInputs(std::vector(inputs)); } + virtual void SetInputs(std::vector inputs) + { + if (inputs.size() < _numInputs) { OutputDebugStringA("ERROR: Not enough inputs provided into render pass\n"); } + _inputs = inputs; + } + // returns true if all inputs are initialized + bool ValidateInputs() + { + for (auto* input : _inputs) + { + if (!input) + { + OutputDebugStringA("ERROR: Render pass has a null input link\n"); + return false; + } + if (!input->IsInitialized()) { return false; } + } + return true; + } + virtual IRenderPassLink* GetOutput(UINT index) + { + if (index >= _numOutputs || index >= _outputs.size() || _outputs[index] == nullptr) + { + OutputDebugStringA("ERROR: Trying to access unexisting render pass output\n"); + return nullptr; + } + return _outputs[index]; + } + UINT GetNumInputs() { return _numInputs; } + UINT GetNumOutputs() { return _numOutputs; } + +protected: + // This will define which resources will be loaded onto respective GPU + // For example: if no RenderPasses has USE_TEXTURES, then GPU texture upload + // will be skipped entirely for this GPU + uint32_t _flags; + RenderPipelineCommonData* _commonData; + + // These are the resources the pass was initialized on + GDX12DeviceResources* _resources; + // These are the other resources, that might be needed in mGPU passes + // Might be null + GDX12DeviceResources* _otherResources; + + std::vector _inputs; + std::vector _outputs; + UINT _numInputs; + UINT _numOutputs; +}; + +class RenderPipelineCommonData +{ +public: + UINT ActiveCameraCBufferIndex = -1; + float ActiveCameraFOV = 0; + float ActiveCameraNearPlane = 0; + float ActiveCameraFarPlane = 0; + float ActiveCameraJitterOffsetX = 0; + float ActiveCameraJitterOffsetY = 0; + Matrix CameraViewToClip = Identity4x4(); + Matrix ClipToCameraView = Identity4x4(); + Matrix ClipToPrevClip = Identity4x4(); + Matrix PrevClipToClip = Identity4x4(); + GameTimer* GameTimer = nullptr; + UINT WindowWidth = 0; + UINT WindowHeight = 0; + UINT DownscaledWidth = 0; + UINT DownscaledHeight = 0; + GDX12RenderPass* Upscaler = nullptr; +}; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12SyncPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12SyncPass.h new file mode 100644 index 0000000..4411fbe --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12SyncPass.h @@ -0,0 +1,12 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" + +// This pass acts as a breakpoint in the pipeline +// It Doesn't do any GPU commands, but used by Render() function to determine sync points +// It is required to be on both devices +// As a result, devices will wait until both of them reach their respective SyncPass +class GDX12SyncPass : public GDX12RenderPass +{ +public: + GDX12SyncPass() { _flags = RENDER_PASS_FLAG_SYNC_DEVICES; } +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureClearPass.h new file mode 100644 index 0000000..3372647 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureClearPass.h @@ -0,0 +1,59 @@ +#pragma once +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" + +class GDX12TextureClearPass : public GDX12RenderPass +{ +public: + GDX12TextureClearPass() + { _flags = RENDER_PASS_FLAG_NONE; } + + virtual void SetInputs(std::vector inputs) override + { + _inputs = inputs; + _numOutputs = 0; + _numInputs = inputs.size(); + } + + // Input N - TextureToClear + void Initialize() override + { + IN_Textures.resize(_numInputs); + for (int i = 0; i < _numInputs; i++) { IN_Textures[i] = _inputs[i]; } + } + + // Clears all textures if they have either DSVs or RTVs + void Execute(GDX12CommandList* cmdList) override + { + cmdList->BeginPixEvent("Texture clear pass", Colors::ForestGreen); + for (int i = 0; i < _numInputs; i++) + { + GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); + + if (inputTexture->HasRTV()) + { + cmdList->ResourceBarrier({ inputTexture->GetResource()->GetRenderTargetBarrier() }); + cmdList->SetRenderTargets({ inputTexture }, nullptr); + cmdList->ClearRenderTargetView(inputTexture); + continue; + } + if (inputTexture->HasDSV()) + { + cmdList->ResourceBarrier({ inputTexture->GetResource()->GetDepthWriteBarrier() }); + cmdList->SetRenderTargets({}, inputTexture); + cmdList->ClearDepthStencilView(inputTexture); + continue; + } + } + cmdList->EndPixEvent(); + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + IN_Textures.clear(); + } + +private: + std::vector IN_Textures; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h new file mode 100644 index 0000000..1ab81e6 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h @@ -0,0 +1,133 @@ +#pragma once +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" +#include "Engine.RendererDX12/GDX12SharedTexture.h" + +class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass +{ +public: + GDX12TextureCopyFromSharedMemoryPass() + { _flags = RENDER_PASS_FLAG_NONE; } + + virtual void SetInputs(std::vector inputs) override + { + _inputs = inputs; + _numInputs = inputs.size(); + MatchOutputCount(_numInputs); + } + + IRenderPassLink* GetOutput(UINT index) override + { + if (_inputs.empty()) { MatchOutputCount(index + 1); } + return GDX12RenderPass::GetOutput(index); + } + + // Input N - SharedTexture + // Output N - OutputTexture + void Initialize() override + { + IN_SharedTextures.resize(_numInputs); + for (int i = 0; i < _numInputs; i++) + { + IN_SharedTextures[i] = _inputs[i]; + + GDX12SharedTexture* sharedTexture = IN_SharedTextures[i]->GetSharedTexture(); + GDX12TextureDesc textureDesc; + textureDesc.Format = sharedTexture->GetFormat(); + textureDesc.Width = sharedTexture->GetWidth(); + textureDesc.Height = sharedTexture->GetHeight(); + + if (IsDepthFormat(textureDesc.Format)) + { + textureDesc.CreateSRV = false; + textureDesc.CreateDSV = true; + textureDesc.DSVHeap = _resources->DSVHeap.get(); + textureDesc.DSVHeapIndex = _resources->DSVHeap->GetAvailableIndex(); + textureDesc.DSVDesc.Format = textureDesc.Format; + textureDesc.DSVDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + textureDesc.DSVDesc.Texture2D.MipSlice = 0; + } + else + { + textureDesc.CreateSRV = true; + textureDesc.SRV_UAV_Heap = _resources->SRV_UAV_Heap.get(); + textureDesc.SRVHeapIndex = _resources->SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + textureDesc.SRVDesc.Format = textureDesc.Format; + textureDesc.SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + textureDesc.SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + textureDesc.SRVDesc.Texture2D.MipLevels = 1; + textureDesc.SRVDesc.Texture2D.MostDetailedMip = 0; + textureDesc.SRVDesc.Texture2D.PlaneSlice = 0; + textureDesc.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; + } + + OUT_Textures[i]->Initialize(textureDesc); + } + } + + // Copies texture from shared memory onto device the pass was initialized on + // It required CopyFromSharedMemory pass to be executed beforehand on the TransferFrom device + // Resulting texture can be used as SRV or DSV on the device the texture was transferred to + void Execute(GDX12CommandList* cmdList) override + { + cmdList->BeginPixEvent("Texture Transfer From Shared Memory pass", Colors::ForestGreen); + for (int i = 0; i < _numInputs; i++) + { + GDX12SharedTexture* inSharedTexture = IN_SharedTextures[i]->GetSharedTexture(); + GDX12Texture* outTexture = OUT_Textures[i].get(); + + cmdList->ResourceBarrier({ inSharedTexture->GetSecondaryResource()->GetCopySourceBarrier(), + outTexture->GetResource()->GetCopyDestBarrier() }); + cmdList->CopyResource(outTexture->GetResource()->D3DResource.Get(), + inSharedTexture->GetSecondaryResource()->D3DResource.Get()); + cmdList->ResourceBarrier({ inSharedTexture->GetSecondaryResource()->GetCommonBarrier() }); + } + cmdList->EndPixEvent(); + } + + void Resize() override + { + UINT newWidth = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledWidth : _commonData->WindowWidth; + UINT newHeight = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledHeight : _commonData->WindowHeight; + for (auto& texture : OUT_Textures) { texture->Resize(newWidth, newHeight); } + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + IN_SharedTextures.clear(); + OUT_Textures.clear(); + } + +private: + std::vector IN_SharedTextures; + std::vector> OUT_Textures; + + bool IsDepthFormat(DXGI_FORMAT format) const + { + switch (format) + { + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + return true; + default: + return false; + } + } + + void MatchOutputCount(UINT outputCount) + { + if (OUT_Textures.size() < outputCount) { OUT_Textures.resize(outputCount); } + if (_outputs.size() < outputCount) { _outputs.resize(outputCount, nullptr); } + + for (UINT i = 0; i < outputCount; i++) + { + if (!OUT_Textures[i]) { OUT_Textures[i] = std::make_unique(); } + _outputs[i] = OUT_Textures[i].get(); + } + + _numOutputs = outputCount; + } +}; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h new file mode 100644 index 0000000..8a27542 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h @@ -0,0 +1,88 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" +#include "Engine.RendererDX12/GDX12SharedTexture.h" + +class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass +{ +public: + GDX12TextureCopyToSharedMemoryPass() + { _flags = RENDER_PASS_FLAG_NONE; } + + virtual void SetInputs(std::vector inputs) override + { + _inputs = inputs; + _numInputs = inputs.size(); + MatchOutputCount(_numInputs); + } + + IRenderPassLink* GetOutput(UINT index) override + { + if (_inputs.empty()) { MatchOutputCount(index + 1); } + return GDX12RenderPass::GetOutput(index); + } + + // Input N - InputTexture + // Output N - OutputSharedTexture + void Initialize() override + { + IN_Textures.resize(_numInputs); + for (int i = 0; i < _numInputs; i++) + { + IN_Textures[i] = _inputs[i]; + OUT_SharedTextures[i]->Initialize(_resources->Device, _otherResources->Device, + IN_Textures[i]->GetTexture()->GetWidth(), IN_Textures[i]->GetTexture()->GetHeight(), + IN_Textures[i]->GetTexture()->GetFormat()); + } + } + + // Copies textures from device the pass was initialized at to shared memory + // Can be later used to read them on another device with CopyFromSharedMemoryPass + void Execute(GDX12CommandList* cmdList) override + { + cmdList->BeginPixEvent("Texture Transfer To Shared Memory pass", Colors::ForestGreen); + for (int i = 0; i < _numInputs; i++) + { + GDX12Texture* inTexture = IN_Textures[i]->GetTexture(); + GDX12SharedTexture* outSharedTexture = OUT_SharedTextures[i]->GetSharedTexture(); + + cmdList->ResourceBarrier({ inTexture->GetResource()->GetCopySourceBarrier(), + outSharedTexture->GetPrimaryResource()->GetCopyDestBarrier() }); + cmdList->CopyResource(outSharedTexture->GetPrimaryResource()->D3DResource.Get(), + inTexture->GetResource()->D3DResource.Get()); + cmdList->ResourceBarrier({ outSharedTexture->GetPrimaryResource()->GetCommonBarrier() }); + } + cmdList->EndPixEvent(); + } + + void Resize() override + { + UINT newWidth = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledWidth : _commonData->WindowWidth; + UINT newHeight = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledHeight : _commonData->WindowHeight; + for (auto& texture : OUT_SharedTextures) { texture->Resize(newWidth, newHeight); } + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + IN_Textures.clear(); + OUT_SharedTextures.clear(); + } + +private: + std::vector IN_Textures; + std::vector> OUT_SharedTextures; + + void MatchOutputCount(UINT outputCount) + { + if (OUT_SharedTextures.size() < outputCount) { OUT_SharedTextures.resize(outputCount); } + if (_outputs.size() < outputCount) { _outputs.resize(outputCount, nullptr); } + + for (UINT i = 0; i < outputCount; i++) + { + if (!OUT_SharedTextures[i]) { OUT_SharedTextures[i] = std::make_unique(); } + _outputs[i] = OUT_SharedTextures[i].get(); + } + + _numOutputs = outputCount; + } +}; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h new file mode 100644 index 0000000..0138dcb --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h @@ -0,0 +1,143 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" + +class GDX12WBOITCompositionPass : public GDX12RenderPass +{ +public: + GDX12WBOITCompositionPass() : IN_OpaqueScene(nullptr), IN_TransparencyAccum(nullptr), + IN_Revealage(nullptr), OUT_Result(nullptr) + { + _flags = RENDER_PASS_FLAG_NONE; + _numInputs = 3; + _numOutputs = 1; + OUT_Result = std::make_unique(); + _outputs.push_back(OUT_Result.get()); + } + + // Input 0 - OpaqueScene + // Input 1 - TransparencyAccumulation + // Input 2 - RevealageTexture + // Output 0 - CompositionResult + void Initialize() override + { + IN_OpaqueScene = _inputs[0]; + IN_TransparencyAccum = _inputs[1]; + IN_Revealage = _inputs[2]; + + // Textures + GDX12TextureDesc TextureDesc1; + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + TextureDesc1.Width = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledWidth : _commonData->WindowWidth; + TextureDesc1.Height = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledHeight : _commonData->WindowHeight; + + TextureDesc1.CreateSRV = true; + TextureDesc1.SRV_UAV_Heap = _resources->SRV_UAV_Heap.get(); + TextureDesc1.SRVHeapIndex = _resources->SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + TextureDesc1.SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + TextureDesc1.SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + TextureDesc1.SRVDesc.Texture2D.MipLevels = 1; + TextureDesc1.SRVDesc.Texture2D.MostDetailedMip = 0; + TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; + TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; + + TextureDesc1.CreateRTV = true; + TextureDesc1.RTVHeap = _resources->RTVHeap.get(); + TextureDesc1.RTVHeapIndex = _resources->RTVHeap->GetAvailableIndex(); + TextureDesc1.RTVDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + TextureDesc1.RTVDesc.Texture2D.PlaneSlice = 0; + TextureDesc1.RTVDesc.Texture2D.MipSlice = 0; + + OUT_Result->Initialize(TextureDesc1); + + // Shaders + auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); + _compositionVS = shaderCompiler.CompileShader(_resources->Device, SHADERS_FOLDER "FullScreenVS.hlsl", nullptr, "VS", "vs"); + _compositionPS = shaderCompiler.CompileShader(_resources->Device, SHADERS_FOLDER "CompositionPass.hlsl", nullptr, "PS", "ps"); + + // Root Signatures + GDX12RootSignatureDesc RSDesc1; + RSDesc1.NumSingleSRVSlots = 3; + RSDesc1.StaticSamplers = GetStaticSamplers(); + _compositionRS = std::make_unique(_resources->Device, RSDesc1); + + // Pipeline State Objects + D3D12_GRAPHICS_PIPELINE_STATE_DESC PSODesc1 = {}; + PSODesc1.InputLayout = { nullptr, 0 }; + PSODesc1.pRootSignature = _compositionRS->GetRootSignature().Get(); + PSODesc1.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + PSODesc1.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + PSODesc1.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + //reversed-Z + PSODesc1.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; + PSODesc1.RasterizerState.FrontCounterClockwise = TRUE; + PSODesc1.SampleMask = UINT_MAX; + PSODesc1.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + PSODesc1.NumRenderTargets = 1; + PSODesc1.RTVFormats[0] = OUT_Result->GetFormat(); + + PSODesc1.SampleDesc.Count = 1; + PSODesc1.SampleDesc.Quality = 0; + PSODesc1.DepthStencilState.DepthEnable = false; + PSODesc1.DepthStencilState.StencilEnable = false; + PSODesc1.VS = { reinterpret_cast(_compositionVS->GetBufferPointer()), _compositionVS->GetBufferSize() }; + PSODesc1.PS = { reinterpret_cast(_compositionPS->GetBufferPointer()), _compositionPS->GetBufferSize() }; + ThrowIfFailed(_resources->Device->GetDevice()->CreateGraphicsPipelineState(&PSODesc1, IID_PPV_ARGS(&_compositionPSO))); + } + + void Execute(GDX12CommandList* cmdList) override + { + GDX12Texture* opaqueAccum = IN_OpaqueScene->GetTexture(); + GDX12Texture* transparencyAccum = IN_TransparencyAccum->GetTexture(); + GDX12Texture* transparencyRevealage = IN_Revealage->GetTexture(); + + cmdList->BeginPixEvent("Composition Render Pass", Colors::Bisque); + cmdList->SetViewport(OUT_Result->GetViewport()); + cmdList->SetScissorRect(OUT_Result->GetScissorRect()); + cmdList->SetGraphicsRootSignature(_compositionRS.get()); + cmdList->SetPipelineState(_compositionPSO.Get()); + cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); + cmdList->ResourceBarrier({ opaqueAccum->GetResource()->GetSRVBarrier(), + transparencyAccum->GetResource()->GetSRVBarrier(), + transparencyRevealage->GetResource()->GetSRVBarrier(), + OUT_Result->GetResource()->GetRenderTargetBarrier() }); + cmdList->SetRenderTargets({ OUT_Result.get() }, nullptr); + cmdList->ClearRenderTargetView(OUT_Result.get()); + cmdList->SetGraphicsSRV(0, opaqueAccum->GetSRV()->GPUHandle); + cmdList->SetGraphicsSRV(1, transparencyAccum->GetSRV()->GPUHandle); + cmdList->SetGraphicsSRV(2, transparencyRevealage->GetSRV()->GPUHandle); + cmdList->GetCommandList()->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + cmdList->GetCommandList()->DrawInstanced(3, 1, 0, 0); + cmdList->EndPixEvent(); + } + + void Resize() override + { + UINT newWidth = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledWidth : _commonData->WindowWidth; + UINT newHeight = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledHeight : _commonData->WindowHeight; + OUT_Result->Resize(newWidth, newHeight); + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + IN_OpaqueScene = nullptr; + IN_TransparencyAccum = nullptr; + IN_Revealage = nullptr; + OUT_Result.reset(); + _compositionVS.Reset(); + _compositionPS.Reset(); + _compositionRS.reset(); + _compositionPSO.Reset(); + } + +private: + ComPtr _compositionVS; + ComPtr _compositionPS; + std::unique_ptr _compositionRS; + ComPtr _compositionPSO; + + IRenderPassLink* IN_OpaqueScene; + IRenderPassLink* IN_TransparencyAccum; + IRenderPassLink* IN_Revealage; + std::unique_ptr OUT_Result; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h new file mode 100644 index 0000000..f66fdf8 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -0,0 +1,212 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" + +class GDX12WBOITTransparencyPass : public GDX12RenderPass +{ +public: + GDX12WBOITTransparencyPass() : IN_DepthStencil(nullptr) + { + _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS | + RENDER_PASS_FLAG_USE_INSTANCES; + _numInputs = 1; + _numOutputs = 2; + OUT_Accumulation = std::make_unique(); + OUT_Revealage = std::make_unique(); + _outputs.push_back(OUT_Accumulation.get()); + _outputs.push_back(OUT_Revealage.get()); + } + + // Input 0 - DepthStencil + // Output 0 - TransparencyAccumulation + // Output 1 - RevealageTexture + void Initialize() override + { + IN_DepthStencil = _inputs[0]; + + // Textures + GDX12TextureDesc TextureDesc1; + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + TextureDesc1.Width = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledWidth : _commonData->WindowWidth; + TextureDesc1.Height = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledHeight : _commonData->WindowHeight; + + TextureDesc1.CreateSRV = true; + TextureDesc1.SRV_UAV_Heap = _resources->SRV_UAV_Heap.get(); + TextureDesc1.SRVHeapIndex = _resources->SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + TextureDesc1.SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + TextureDesc1.SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + TextureDesc1.SRVDesc.Texture2D.MipLevels = 1; + TextureDesc1.SRVDesc.Texture2D.MostDetailedMip = 0; + TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; + TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; + + TextureDesc1.CreateRTV = true; + TextureDesc1.RTVHeap = _resources->RTVHeap.get(); + TextureDesc1.RTVHeapIndex = _resources->RTVHeap->GetAvailableIndex(); + TextureDesc1.RTVDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + TextureDesc1.RTVDesc.Texture2D.PlaneSlice = 0; + TextureDesc1.RTVDesc.Texture2D.MipSlice = 0; + + OUT_Accumulation->Initialize(TextureDesc1); + + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R16_FLOAT; + TextureDesc1.SRVHeapIndex = _resources->SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + TextureDesc1.RTVHeapIndex = _resources->RTVHeap->GetAvailableIndex(); + + OUT_Revealage->Initialize(TextureDesc1); + + // Shaders + auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); + _transparencyVS = shaderCompiler.CompileShader(_resources->Device, SHADERS_FOLDER "TransparentPass.hlsl", nullptr, "VS", "vs"); + _transparencyPS = shaderCompiler.CompileShader(_resources->Device, SHADERS_FOLDER "TransparentPass.hlsl", nullptr, "PS", "ps"); + + // Root Signatures + GDX12RootSignatureDesc RSDesc1; + RSDesc1.NumSingleCBVSlots = 2; + RSDesc1.NumSingleSRVSlots = 3; + RSDesc1.StaticSamplers = GetStaticSamplers(); + RSDesc1.SRVRanges.push_back(GDX12RootSignatureRange(Texture2D_RangeLength)); + RSDesc1.Constants.push_back(1); + _transparencyRS = std::make_unique(_resources->Device, RSDesc1); + + //Command Signatures + std::vector args; + D3D12_INDIRECT_ARGUMENT_DESC argConst = {}; + argConst.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT; + argConst.Constant.DestOffsetIn32BitValues = 0; + argConst.Constant.Num32BitValuesToSet = 1; + args.push_back(argConst); + D3D12_INDIRECT_ARGUMENT_DESC argDraw = {}; + argDraw.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED; + args.push_back(argDraw); + + D3D12_COMMAND_SIGNATURE_DESC CSDesc1 = {}; + CSDesc1.ByteStride = sizeof(GDX12IndirectDrawArgs); + CSDesc1.NumArgumentDescs = args.size(); + CSDesc1.pArgumentDescs = args.data(); + CSDesc1.NodeMask = 0; + + _resources->Device->GetDevice()->CreateCommandSignature(&CSDesc1, + _transparencyRS->GetRootSignature().Get(), + IID_PPV_ARGS(&_transparencyCS)); + + // Pipeline State Objects + D3D12_GRAPHICS_PIPELINE_STATE_DESC PSODesc1 = {}; + PSODesc1.InputLayout = { _resources->InputLayouts["Default"].data(), (UINT)_resources->InputLayouts["Default"].size() }; + PSODesc1.pRootSignature = _transparencyRS->GetRootSignature().Get(); + PSODesc1.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + PSODesc1.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + PSODesc1.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + //reversed-Z + PSODesc1.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; + PSODesc1.RasterizerState.FrontCounterClockwise = TRUE; + PSODesc1.SampleMask = UINT_MAX; + PSODesc1.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + PSODesc1.SampleDesc.Count = 1; + PSODesc1.SampleDesc.Quality = 0; + PSODesc1.DSVFormat = IN_DepthStencil->GetTexture()->GetFormat(); + + // Accumulation + PSODesc1.BlendState.RenderTarget[0].BlendEnable = true; + PSODesc1.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE; + PSODesc1.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_ONE; + PSODesc1.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; + PSODesc1.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; + PSODesc1.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ONE; + PSODesc1.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; + PSODesc1.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + // Revealage + PSODesc1.BlendState.RenderTarget[1].BlendEnable = true; + PSODesc1.BlendState.RenderTarget[1].SrcBlend = D3D12_BLEND_ONE; + PSODesc1.BlendState.RenderTarget[1].DestBlend = D3D12_BLEND_ONE; + PSODesc1.BlendState.RenderTarget[1].BlendOp = D3D12_BLEND_OP_ADD; + PSODesc1.BlendState.RenderTarget[1].SrcBlendAlpha = D3D12_BLEND_ONE; + PSODesc1.BlendState.RenderTarget[1].DestBlendAlpha = D3D12_BLEND_ONE; + PSODesc1.BlendState.RenderTarget[1].BlendOpAlpha = D3D12_BLEND_OP_ADD; + PSODesc1.BlendState.RenderTarget[1].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + // Disable depth write + PSODesc1.DepthStencilState.DepthEnable = true; + PSODesc1.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; + PSODesc1.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; + PSODesc1.DepthStencilState.StencilEnable = false; + + PSODesc1.NumRenderTargets = 2; + PSODesc1.RTVFormats[0] = OUT_Accumulation->GetFormat(); + PSODesc1.RTVFormats[1] = OUT_Revealage->GetFormat(); + PSODesc1.VS = { reinterpret_cast(_transparencyVS->GetBufferPointer()), _transparencyVS->GetBufferSize() }; + PSODesc1.PS = { reinterpret_cast(_transparencyPS->GetBufferPointer()), _transparencyPS->GetBufferSize() }; + ThrowIfFailed(_resources->Device->GetDevice()->CreateGraphicsPipelineState(&PSODesc1, IID_PPV_ARGS(&_transparencyPSO))); + } + + // VisibilityBuffers will automatically be selected from CameraCBIndex + // It requires GPUCullingPass to be executed beforehand + void Execute(GDX12CommandList* cmdList) override + { + auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[_commonData->ActiveCameraCBufferIndex]; + GDX12Texture* depthStencil = IN_DepthStencil->GetTexture(); + + cmdList->BeginPixEvent("Transparent Render Pass", Colors::Aqua); + cmdList->SetViewport(OUT_Accumulation->GetViewport()); + cmdList->SetScissorRect(OUT_Accumulation->GetScissorRect()); + cmdList->SetGraphicsRootSignature(_transparencyRS.get()); + cmdList->SetPipelineState(_transparencyPSO); + cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); + cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> + GetElementAddress(_commonData->ActiveCameraCBufferIndex)); + cmdList->SetGeometryBuffer(_resources->GeometryBuffer.get()); + cmdList->SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); + cmdList->SetGraphicsSRV(0, currentFrameConstants->MaterialCache->GetSRV()->GPUHandle); + cmdList->SetGraphicsSRV(1, currentFrameConstants->TransformCache->GetSRV()->GPUHandle); + cmdList->SetGraphicsSRV(2, currentFrameConstants->InstanceCache->GetSRV()->GPUHandle); + cmdList->SetGraphicsSRV(3, _resources->SRV_UAV_Heap->GetGPUHandle(Texture2D_StartIndex)); + + cmdList->ResourceBarrier({ currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().GetIndirectArgsBarrier(), + currentCameraVisBuffers.TransparentDrawCounter->GetResource().GetIndirectArgsBarrier(), + OUT_Accumulation->GetResource()->GetRenderTargetBarrier(), + OUT_Revealage->GetResource()->GetRenderTargetBarrier() }); + cmdList->SetRenderTargets({ OUT_Accumulation.get(), OUT_Revealage.get() }, + depthStencil); + cmdList->ClearRenderTargetView(OUT_Accumulation.get()); + cmdList->ClearRenderTargetView(OUT_Revealage.get()); + cmdList->ExecuteIndirect(_transparencyCS.Get(), _resources->IndirectCommandsCache->GetElementCount(), + currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().D3DResource.Get(), 0, + currentCameraVisBuffers.TransparentDrawCounter->GetResource().D3DResource.Get(), 0); + cmdList->ResourceBarrier({ OUT_Accumulation->GetResource()->GetSRVBarrier(), + OUT_Revealage->GetResource()->GetSRVBarrier() }); + cmdList->EndPixEvent(); + } + + void Resize() override + { + UINT newWidth = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledWidth : _commonData->WindowWidth; + UINT newHeight = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledHeight : _commonData->WindowHeight; + OUT_Accumulation->Resize(newWidth, newHeight); + OUT_Revealage->Resize(newWidth, newHeight); + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + OUT_Accumulation.reset(); + OUT_Revealage.reset(); + IN_DepthStencil = nullptr; + _transparencyVS.Reset(); + _transparencyPS.Reset(); + _transparencyRS.reset(); + _transparencyCS.Reset(); + _transparencyPSO.Reset(); + } + +private: + ComPtr _transparencyVS; + ComPtr _transparencyPS; + std::unique_ptr _transparencyRS; + ComPtr _transparencyCS; + ComPtr _transparencyPSO; + + std::unique_ptr OUT_Accumulation; + std::unique_ptr OUT_Revealage; + + IRenderPassLink* IN_DepthStencil; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h new file mode 100644 index 0000000..66e5489 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h @@ -0,0 +1,220 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" +#include "Common/GameTimer.h" + +#include "xess/xess.h" +#include "xess/xess_d3d12.h" + +class GDX12XeSSUpscalePass : public GDX12RenderPass +{ +public: + GDX12XeSSUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), _XeSSContext(nullptr), + _XeSSQualityMode(XESS_QUALITY_SETTING_ULTRA_QUALITY_PLUS) + { _flags = RENDER_PASS_FLAG_UPSCALER | RENDER_PASS_FLAG_USE_JITTER; } + + virtual void SetInputs(std::vector inputs) override + { + _inputs = inputs; + _numInputs = 2; + MatchOutputCount(inputs.size() > 2 ? inputs.size() - 2 : 0); + } + + IRenderPassLink* GetOutput(UINT index) override + { + if (_inputs.empty()) { MatchOutputCount(index + 1); } + return GDX12RenderPass::GetOutput(index); + } + + // Input 0 - DepthStencil + // Input 1 - MotionVectors + // Input N - Input Texture + // Output N - UpscaledTexture + void Initialize() override + { + _commonData->Upscaler = this; + + IN_DepthBuffer = _inputs[0]; + IN_MotionVectors = _inputs[1]; + + GDX12TextureDesc TextureDesc1; + TextureDesc1.Width = _commonData->WindowWidth; + TextureDesc1.Height = _commonData->WindowHeight; + + TextureDesc1.CreateSRV = true; + TextureDesc1.SRV_UAV_Heap = _resources->SRV_UAV_Heap.get(); + TextureDesc1.SRVDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + TextureDesc1.SRVDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + TextureDesc1.SRVDesc.Texture2D.MipLevels = 1; + TextureDesc1.SRVDesc.Texture2D.MostDetailedMip = 0; + TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; + TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; + + IN_Textures.resize(_numOutputs); + for (UINT i = 0; i < _numOutputs; i++) + { + IN_Textures[i] = _inputs[i + 2]; + GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = inputTexture->GetFormat(); + TextureDesc1.SRVHeapIndex = _resources->SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + OUT_UpscaledTextures[i]->Initialize(TextureDesc1); + } + + } + + void Setup(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) override + { + GDX12RenderPass::Setup(initOnResources, otherResources, commonData); + + BuildXeSSContext(); + QueryRenderTargetResolution(); + } + + void Execute(GDX12CommandList* cmdList) override + { + GDX12Texture* depthStencil = IN_DepthBuffer->GetTexture(); + GDX12Texture* motionVectors = IN_MotionVectors->GetTexture(); + + cmdList->BeginPixEvent("XeSS Upscale Pass", Colors::Blue); + + cmdList->ResourceBarrier({ depthStencil->GetResource()->GetNonPixelShaderResourceBarrier(), + motionVectors->GetResource()->GetNonPixelShaderResourceBarrier() }); + + xess_d3d12_execute_params_t execParams = {}; + execParams.pDepthTexture = depthStencil->GetResource()->D3DResource.Get(); + execParams.pVelocityTexture = motionVectors->GetResource()->D3DResource.Get(); + // I have no idea why, but the minus sign fixes bluriness + execParams.jitterOffsetX = -_commonData->ActiveCameraJitterOffsetX; + execParams.jitterOffsetY = -_commonData->ActiveCameraJitterOffsetY; + execParams.inputWidth = _commonData->DownscaledWidth; + execParams.inputHeight = _commonData->DownscaledHeight; + execParams.resetHistory = false; + + execParams.exposureScale = 1; + execParams.inputColorBase = { 0,0 }; + execParams.inputDepthBase = { 0,0 }; + + for (int i = 0; i < _numOutputs; i++) + { + GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); + GDX12Texture* upscaledTexture = OUT_UpscaledTextures[i].get(); + + execParams.pColorTexture = inputTexture->GetResource()->D3DResource.Get(); + execParams.pOutputTexture = upscaledTexture->GetResource()->D3DResource.Get(); + + cmdList->ResourceBarrier({ inputTexture->GetResource()->GetNonPixelShaderResourceBarrier(), + upscaledTexture->GetResource()->GetUnorderedAccessBarrier() }); + + xess_result_t execResult = xessD3D12Execute(_XeSSContext, cmdList->GetCommandList().Get(), &execParams); + if (execResult != XESS_RESULT_SUCCESS) + { + std::string msg = "ERROR: XeSS execute failed: " + XeSSResultToString(execResult) + "\n"; + OutputDebugStringA(msg.c_str()); + } + } + cmdList->EndPixEvent(); + } + + void Resize() override + { + for (auto& texture : OUT_UpscaledTextures) { texture->Resize(_commonData->WindowWidth, _commonData->WindowHeight); } + xessDestroyContext(_XeSSContext); + BuildXeSSContext(); + } + + void QueryRenderTargetResolution() override + { + xess_2d_t targetResolution = { _commonData->WindowWidth, _commonData->WindowHeight } ; + xess_2d_t downscaledResolution; + xess_2d_t minResolution; + xess_2d_t maxResolution; + xess_result_t queryResolutionResult = xessGetOptimalInputResolution(_XeSSContext, + &targetResolution, _XeSSQualityMode, &downscaledResolution, &minResolution, &maxResolution); + if (queryResolutionResult != XESS_RESULT_SUCCESS) + { + std::string msg = "ERROR: XeSS query resolution failed: " + XeSSResultToString(queryResolutionResult) + "\n"; + OutputDebugStringA(msg.c_str()); + } + _commonData->DownscaledWidth = downscaledResolution.x; + _commonData->DownscaledHeight = downscaledResolution.y; + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + xessDestroyContext(_XeSSContext); + IN_DepthBuffer = nullptr; + IN_MotionVectors = nullptr; + IN_Textures.clear(); + OUT_UpscaledTextures.clear(); + } + +private: + IRenderPassLink* IN_DepthBuffer; + IRenderPassLink* IN_MotionVectors; + std::vector IN_Textures; + std::vector> OUT_UpscaledTextures; + xess_context_handle_t _XeSSContext; + xess_quality_settings_t _XeSSQualityMode; + + void MatchOutputCount(UINT outputCount) + { + if (OUT_UpscaledTextures.size() < outputCount) { OUT_UpscaledTextures.resize(outputCount); } + if (_outputs.size() < outputCount) { _outputs.resize(outputCount, nullptr); } + + for (UINT i = 0; i < outputCount; i++) + { + if (!OUT_UpscaledTextures[i]) { OUT_UpscaledTextures[i] = std::make_unique(); } + _outputs[i] = OUT_UpscaledTextures[i].get(); + } + + _numOutputs = outputCount; + } + + void BuildXeSSContext() + { + xess_result_t createContextResult = xessD3D12CreateContext(_resources->Device->GetDevice().Get(), &_XeSSContext); + if (createContextResult != XESS_RESULT_SUCCESS) + { + std::string msg = "ERROR: XeSS context not created: " + XeSSResultToString(createContextResult) + "\n"; + OutputDebugStringA(msg.c_str()); + } + + xess_d3d12_init_params_t initParams = {}; + initParams.outputResolution.x = _commonData->WindowWidth; + initParams.outputResolution.y = _commonData->WindowHeight; + initParams.initFlags = XESS_INIT_FLAG_INVERTED_DEPTH | + XESS_INIT_FLAG_LDR_INPUT_COLOR | XESS_INIT_FLAG_USE_NDC_VELOCITY; + initParams.qualitySetting = _XeSSQualityMode; + + xess_result_t initResult = xessD3D12Init(_XeSSContext, &initParams); + if (initResult != XESS_RESULT_SUCCESS) + { + std::string msg = "ERROR: XeSS context not initialized: " + XeSSResultToString(initResult) + "\n"; + OutputDebugStringA(msg.c_str()); + } + } + + std::string XeSSResultToString(const xess_result_t result) + { + switch (result) + { + case XESS_RESULT_SUCCESS: return "XESS_RESULT_SUCCESS"; + case XESS_RESULT_WARNING_NONEXISTING_FOLDER: return "XESS_RESULT_WARNING_NONEXISTING_FOLDER"; + case XESS_RESULT_WARNING_OLD_DRIVER: return "XESS_RESULT_WARNING_OLD_DRIVER"; + case XESS_RESULT_ERROR_UNSUPPORTED_DEVICE: return "XESS_RESULT_ERROR_UNSUPPORTED_DEVICE"; + case XESS_RESULT_ERROR_UNSUPPORTED_DRIVER: return "XESS_RESULT_ERROR_UNSUPPORTED_DRIVER"; + case XESS_RESULT_ERROR_UNINITIALIZED: return "XESS_RESULT_ERROR_UNINITIALIZED"; + case XESS_RESULT_ERROR_INVALID_ARGUMENT: return "XESS_RESULT_ERROR_INVALID_ARGUMENT"; + case XESS_RESULT_ERROR_DEVICE_OUT_OF_MEMORY: return "XESS_RESULT_ERROR_DEVICE_OUT_OF_MEMORY"; + case XESS_RESULT_ERROR_DEVICE: return "XESS_RESULT_ERROR_DEVICE"; + case XESS_RESULT_ERROR_NOT_IMPLEMENTED: return "XESS_RESULT_ERROR_NOT_IMPLEMENTED"; + case XESS_RESULT_ERROR_INVALID_CONTEXT: return "XESS_RESULT_ERROR_INVALID_CONTEXT"; + case XESS_RESULT_ERROR_OPERATION_IN_PROGRESS: return "XESS_RESULT_ERROR_OPERATION_IN_PROGRESS"; + case XESS_RESULT_ERROR_UNSUPPORTED: return "XESS_RESULT_ERROR_UNSUPPORTED"; + case XESS_RESULT_ERROR_CANT_LOAD_LIBRARY: return "XESS_RESULT_ERROR_CANT_LOAD_LIBRARY"; + case XESS_RESULT_ERROR_WRONG_CALL_ORDER: return "XESS_RESULT_ERROR_WRONG_CALL_ORDER"; + case XESS_RESULT_ERROR_UNKNOWN: return "XESS_RESULT_ERROR_UNKNOWN"; + default: return "XESS_RESULT_UNKNOWN_ENUM"; + } + } +}; diff --git a/Engine/Engine.RendererDX12/Shaders/BufferClear.hlsl b/Engine/Engine.RendererDX12/Shaders/BufferClear.hlsl index 68a8c9a..c9d6617 100644 --- a/Engine/Engine.RendererDX12/Shaders/BufferClear.hlsl +++ b/Engine/Engine.RendererDX12/Shaders/BufferClear.hlsl @@ -1,7 +1,10 @@ -RWStructuredBuffer CounterBuffer : register(u0); +RWStructuredBuffer CounterBuffer1 : register(u0); +RWStructuredBuffer CounterBuffer2 : register(u1); + [numthreads(1, 1, 1)] void CS(uint3 dispatchThreadID : SV_DispatchThreadID) { - CounterBuffer[0] = 0; + CounterBuffer1[0] = 0; + CounterBuffer2[0] = 0; } \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Shaders/CBufferStructures.hlsl b/Engine/Engine.RendererDX12/Shaders/CBufferStructures.hlsl index 521328a..61bafd6 100644 --- a/Engine/Engine.RendererDX12/Shaders/CBufferStructures.hlsl +++ b/Engine/Engine.RendererDX12/Shaders/CBufferStructures.hlsl @@ -13,6 +13,7 @@ struct MainCB struct Transform { float4x4 World; + float4x4 PrevWorld; }; struct Material @@ -34,7 +35,9 @@ struct Material struct CameraCB { float4x4 ViewProj; + float4x4 ViewProjNoJitter; float4x4 View; + float4x4 PrevViewProjNoJitter; float3 CameraLocation; float NearPlane; float FarPlane; diff --git a/Engine/Engine.RendererDX12/Shaders/CompositionPass.hlsl b/Engine/Engine.RendererDX12/Shaders/CompositionPass.hlsl index d67896e..dd4f244 100644 --- a/Engine/Engine.RendererDX12/Shaders/CompositionPass.hlsl +++ b/Engine/Engine.RendererDX12/Shaders/CompositionPass.hlsl @@ -19,7 +19,6 @@ float4 PS(VSOutput input) : SV_TARGET float4 opaqueColor = OpaqueTexture.Sample(samPointClamp, uv); float4 accumColor = AccumTexture.Sample(samPointClamp, uv); float revealage = saturate(RevealageTexture.Sample(samPointClamp, uv)); - float3 finalColor = opaqueColor.rgb * (1.0 - revealage) + accumColor.rgb; float finalAlpha = max(opaqueColor.a, revealage); diff --git a/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl b/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl index c424870..d8d83ee 100644 --- a/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl +++ b/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl @@ -27,7 +27,9 @@ struct VS_INPUT struct VS_OUTPUT_PS_INPUT { float4 PosCS : SV_POSITION; + float4 PrevPosCSNoJitter : TEXCOORD2; float3 PosW : POSITION; + float4 PosCSNoJitter : POSITION2; float2 TexC : TEXCOORD; float3 Normal : NORMAL; float3 Tangent : TANGENT; @@ -39,32 +41,45 @@ VS_OUTPUT_PS_INPUT VS(VS_INPUT vin) VS_OUTPUT_PS_INPUT vout = (VS_OUTPUT_PS_INPUT) 0.0f; InstanceData instance = InstanceCache[CBIndirectConstants.InstanceID]; - float4x4 World = TransformCache[instance.TransformIndex].World; + Transform transform = TransformCache[instance.TransformIndex]; - float4 posW = mul(float4(vin.Pos, 1.0f), World); + float4 posW = mul(float4(vin.Pos, 1.0f), transform.World); vout.PosW = posW.xyz; // Assumes nonuniform scaling; otherwise, need to use inverse-transpose of world matrix. - vout.Normal = normalize(mul(vin.Normal, (float3x3) World)); - vout.Tangent = normalize(mul(vin.Tangent, (float3x3) World)); + vout.Normal = normalize(mul(vin.Normal, (float3x3) transform.World)); + vout.Tangent = normalize(mul(vin.Tangent, (float3x3) transform.World)); vout.PosCS = mul(posW, CBCamera.ViewProj); - vout.TexC = vin.TexC; + vout.PosCSNoJitter = mul(posW, CBCamera.ViewProjNoJitter); + float4 prevPosW = mul(float4(vin.Pos, 1.0f), transform.PrevWorld); + vout.PrevPosCSNoJitter = mul(prevPosW, CBCamera.PrevViewProjNoJitter); + + vout.TexC = vin.TexC; vout.MaterialIndex = instance.MaterialIndex; return vout; } -float4 PS(VS_OUTPUT_PS_INPUT pin) : SV_Target +struct PS_OUTPUT +{ + float4 Color : SV_TARGET0; + float2 Velocity : SV_TARGET1; +}; + +PS_OUTPUT PS(VS_OUTPUT_PS_INPUT pin) { + PS_OUTPUT output; + Material material = MaterialCache[pin.MaterialIndex]; float4 color = Texture2DCache[material.DiffuseIndex].Sample(samAnisotropicWrap, pin.TexC); - if (material.RenderLayer == 1) - { - float alpha = color.a * material.Opacity; - clip(alpha - 0.5f); - } + float2 currentNDC = pin.PosCSNoJitter.xy / pin.PosCSNoJitter.w; + float2 prevNDC = pin.PrevPosCSNoJitter.xy / pin.PrevPosCSNoJitter.w; + float2 velocity = prevNDC - currentNDC; - return float4(color.rgb, 1.0f); + output.Color = float4(color.rgb, 1.0f); + output.Velocity = velocity; + + return output; } \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/src/GDX12CommandList.cpp b/Engine/Engine.RendererDX12/src/GDX12CommandList.cpp index c1a6f2c..c6e7ede 100644 --- a/Engine/Engine.RendererDX12/src/GDX12CommandList.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12CommandList.cpp @@ -274,7 +274,17 @@ void GDX12CommandList::ExecuteIndirect(ID3D12CommandSignature* pCommandSignature void GDX12CommandList::ResourceBarrier(std::initializer_list barriers) { - _commandList->ResourceBarrier(barriers.size(), barriers.begin()); + std::vector filteredBarriers; + for (auto& barrier : barriers) + { + //skip transition with equal before and after states + const D3D12_RESOURCE_BARRIER& baseBarrier = barrier; + if (baseBarrier.Transition.StateBefore != baseBarrier.Transition.StateAfter) + { + filteredBarriers.push_back(barrier); + } + } + if (!filteredBarriers.empty()) { _commandList->ResourceBarrier(filteredBarriers.size(), filteredBarriers.data()); } } void GDX12CommandList::EnhancedTextureBarrier(std::initializer_list textureBarriers) @@ -306,6 +316,11 @@ void GDX12CommandList::EndPixEvent() PIXEndEvent(_commandList.Get()); } +void GDX12CommandList::CopyResource(ID3D12Resource* destResource, ID3D12Resource* sourceResource) +{ + _commandList->CopyResource(destResource, sourceResource); +} + void GDX12CommandList::BuildRaytracingAccelerationStructure(const D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC* pDesc) { _commandList->BuildRaytracingAccelerationStructure(pDesc, 0, nullptr); diff --git a/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp b/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp index 73c382c..ca7aaea 100644 --- a/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp @@ -1,11 +1,10 @@ #include "Engine.RendererDX12/GDX12CommandQueue.h" #include "Engine.RendererDX12/GDX12CommandList.h" +#include "Engine.RendererDX12/GDX12StreamlineSDK.h" GDX12CommandQueue::GDX12CommandQueue(GDX12Device* device) - : FenceValue(0), - _device(device), - _lastDispatchedFenceValue(0) + : FenceValue(0), _device(device), _lastDispatchedFenceValue(0) { D3D12_COMMAND_QUEUE_DESC desc = {}; desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; @@ -13,16 +12,20 @@ GDX12CommandQueue::GDX12CommandQueue(GDX12Device* device) desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; desc.NodeMask = 0; - ThrowIfFailed(device->GetDevice()->CreateCommandQueue(&desc, IID_PPV_ARGS(&_commandQueue))); - ThrowIfFailed(device->GetDevice()->CreateFence(FenceValue, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&_fence))); + ThrowIfFailed(device->GetCommandQueueCreationDevice()->CreateCommandQueue(&desc, IID_PPV_ARGS(&_proxyCommandQueue))); + _commandQueue = GDX12StreamlineSDK::Get().GetNativeCommandQueue(_proxyCommandQueue); + ThrowIfFailed(device->GetDevice()->CreateFence(FenceValue, + D3D12_FENCE_FLAG_SHARED | D3D12_FENCE_FLAG_SHARED_CROSS_ADAPTER, IID_PPV_ARGS(&_fence))); } void GDX12CommandQueue::Reset() { + _proxyCommandQueue.Reset(); _commandQueue.Reset(); _fence.Reset(); _workingCommandLists.clear(); _availableCommandLists.clear(); + _otherFence.Reset(); } GDX12CommandQueue::~GDX12CommandQueue() @@ -35,6 +38,11 @@ const ComPtr& GDX12CommandQueue::GetCommandQueue() return _commandQueue; } +const ComPtr& GDX12CommandQueue::GetPresentCommandQueue() +{ + return _proxyCommandQueue ? _proxyCommandQueue : _commandQueue; +} + GDX12CommandList* GDX12CommandQueue::GetCommandList() { GDX12CommandList* rawPtr; @@ -67,23 +75,24 @@ void GDX12CommandQueue::ExecuteCommandList(GDX12CommandList* commandList) _lastDispatchedFenceValue = FenceValue; } -void GDX12CommandQueue::ExecuteCommandLists(GDX12CommandList** commandLists, UINT count) +void GDX12CommandQueue::ExecuteCommandLists(std::vector& commandLists) { std::vector ppLists; - ppLists.reserve(count); + UINT commandListCount = commandLists.size(); + ppLists.reserve(commandListCount); - for (UINT i = 0; i < count; ++i) + for (UINT i = 0; i < commandListCount; ++i) { commandLists[i]->GetCommandList()->Close(); ppLists.push_back(commandLists[i]->GetCommandList().Get()); } - _commandQueue->ExecuteCommandLists(count, ppLists.data()); + _commandQueue->ExecuteCommandLists(commandListCount, ppLists.data()); FenceValue++; _commandQueue->Signal(_fence.Get(), FenceValue); - for (UINT i = 0; i < count; ++i) { commandLists[i]->FenceValue = FenceValue; } + for (UINT i = 0; i < commandListCount; ++i) { commandLists[i]->FenceValue = FenceValue; } _lastDispatchedFenceValue = FenceValue; } @@ -92,7 +101,12 @@ const ComPtr& GDX12CommandQueue::GetFence() return _fence; } -void GDX12CommandQueue::WaitForFenceValue(uint64_t fenceValue) +ComPtr& GDX12CommandQueue::GetOtherFence() +{ + return _otherFence; +} + +void GDX12CommandQueue::CPUWaitForFenceValue(uint64_t fenceValue) { if (_fence->GetCompletedValue() >= fenceValue) { return; } @@ -102,11 +116,16 @@ void GDX12CommandQueue::WaitForFenceValue(uint64_t fenceValue) CloseHandle(event); } +void GDX12CommandQueue::WaitForOtherFence(uint64_t otherFenceValue) +{ + _commandQueue->Wait(_otherFence.Get(), otherFenceValue); +} + void GDX12CommandQueue::Flush() { FenceValue++; _commandQueue->Signal(_fence.Get(), FenceValue); - if (_lastDispatchedFenceValue > 0) { WaitForFenceValue(_lastDispatchedFenceValue); } + if (_lastDispatchedFenceValue > 0) { CPUWaitForFenceValue(_lastDispatchedFenceValue); } } void GDX12CommandQueue::ClearCompletedLists() diff --git a/Engine/Engine.RendererDX12/src/GDX12Descriptor.cpp b/Engine/Engine.RendererDX12/src/GDX12Descriptor.cpp index e3d6b3b..2f28554 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Descriptor.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Descriptor.cpp @@ -14,7 +14,7 @@ GDX12Descriptor::GDX12Descriptor() : GDX12Descriptor::~GDX12Descriptor() { - if (HeapIndex != -1) _heap->_occupanceRegistry[HeapIndex] = false; + if (HeapIndex != -1) { _heap->_occupanceRegistry[HeapIndex] = false; } } void GDX12Descriptor::InitAsSRV(ID3D12Resource* resource, D3D12_SHADER_RESOURCE_VIEW_DESC* srvDesc, GDX12DescriptorHeap* inHeap, UINT heapIndex) diff --git a/Engine/Engine.RendererDX12/src/GDX12Device.cpp b/Engine/Engine.RendererDX12/src/GDX12Device.cpp index edbd102..d71d293 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Device.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Device.cpp @@ -1,12 +1,14 @@ #include "Engine.RendererDX12/GDX12Device.h" #include "Engine.RendererDX12/GDX12CommandQueue.h" +#include "Engine.RendererDX12/GDX12StreamlineSDK.h" GDX12Device::GDX12Device() : _isInitialized(false), _rtvDescriptorSize(0), _dsvDescriptorSize(0), - _cbvSrvUavDescriptorSize(0) + _cbvSrvUavDescriptorSize(0), + Role(DEVICE_ROLE_PRIMARY) { } @@ -39,6 +41,8 @@ HRESULT GDX12Device::Initialize(ComPtr adapter) } if (FAILED(hr)) { OutputDebugStringA("ERROR: FAILED TO CREATE DX12DEVICE\n"); } + _proxyDevice = GDX12StreamlineSDK::Get().CreateProxyDevice(_device, Role == DEVICE_ROLE_PRIMARY); + _device = GDX12StreamlineSDK::Get().GetNativeDevice(_proxyDevice ? _proxyDevice : _device); CollectDeviceFeatures(); _commandQueue = std::make_unique(this); @@ -54,6 +58,8 @@ void GDX12Device::CollectDeviceFeatures() _dsvDescriptorSize = _device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV); _cbvSrvUavDescriptorSize = _device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + _specs.Features.Init(_device.Get()); + DXGI_ADAPTER_DESC1 adapterDesc; _adapter.Get()->GetDesc1(&adapterDesc); @@ -61,78 +67,14 @@ void GDX12Device::CollectDeviceFeatures() _specs.DedicatedVideoMemory = adapterDesc.DedicatedVideoMemory; _specs.DedicatedSystemMemory = adapterDesc.DedicatedSystemMemory; _specs.SharedSystemMemory = adapterDesc.SharedSystemMemory; - - // Query shader model support - D3D12_FEATURE_DATA_SHADER_MODEL shaderModel; - D3D_SHADER_MODEL testModels[] = - { - D3D_SHADER_MODEL_6_10, // these two versions - D3D_SHADER_MODEL_6_9, // may not be compilable by DXC, so we might ditch them later - D3D_SHADER_MODEL_6_8, - D3D_SHADER_MODEL_6_7, - D3D_SHADER_MODEL_6_6, - D3D_SHADER_MODEL_6_5, - D3D_SHADER_MODEL_6_4, - D3D_SHADER_MODEL_6_3, - D3D_SHADER_MODEL_6_2, - D3D_SHADER_MODEL_6_1, - D3D_SHADER_MODEL_6_0, - D3D_SHADER_MODEL_5_1 }; - - for (auto model : testModels) - { - shaderModel.HighestShaderModel = model; - if (SUCCEEDED(_device->CheckFeatureSupport( - D3D12_FEATURE_SHADER_MODEL, - &shaderModel, - sizeof(shaderModel)))) - { - _specs.MaxShaderModel = model; - break; - } - } - - // Query raytracing support - D3D12_FEATURE_DATA_D3D12_OPTIONS5 options5 = {}; - if (SUCCEEDED(_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &options5, sizeof(options5)))) - { - _specs.RaytracingSupport = (options5.RaytracingTier != D3D12_RAYTRACING_TIER_NOT_SUPPORTED); - } - - // Query mesh shaders support - D3D12_FEATURE_DATA_D3D12_OPTIONS7 options7 = {}; - if (SUCCEEDED(_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, &options7, sizeof(options7)))) - { - _specs.MeshShadersSupport = (options7.MeshShaderTier != D3D12_MESH_SHADER_TIER_NOT_SUPPORTED); - } - - // Query variable rate shading support - D3D12_FEATURE_DATA_D3D12_OPTIONS6 options6 = {}; - if (SUCCEEDED(_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS6, &options6, sizeof(options6)))) - { - _specs.VariableRateShadingSupport = (options6.VariableShadingRateTier != D3D12_VARIABLE_SHADING_RATE_TIER_NOT_SUPPORTED); - } - - // Query enhanced barriers support - D3D12_FEATURE_DATA_D3D12_OPTIONS12 options12 = {}; - if (SUCCEEDED(_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS12, &options12, sizeof(options12)))) - { - _specs.EnhancedBarriersSupport = options12.EnhancedBarriersSupported; - } - - // Query cross adapter row-major texture support - D3D12_FEATURE_DATA_D3D12_OPTIONS options = {}; - if (SUCCEEDED(_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)))) - { - _specs.CrossAdapterRowMajorTextureSupport = options.CrossAdapterRowMajorTextureSupported; - } } void GDX12Device::Reset() { + _commandQueue.reset(); + _proxyDevice.Reset(); _device.Reset(); _adapter.Reset(); - _commandQueue.reset(); _isInitialized = false; } @@ -141,6 +83,11 @@ const ComPtr& GDX12Device::GetDevice() return _device; } +const ComPtr& GDX12Device::GetCommandQueueCreationDevice() +{ + return _proxyDevice ? _proxyDevice : _device; +} + GDX12CommandQueue* GDX12Device::GetCommandQueue() { return _commandQueue.get(); @@ -151,7 +98,18 @@ const DeviceSpecs& GDX12Device::GetDeviceFeatures() return _specs; } +LUID GDX12Device::GetAdapterLuid() const +{ + LUID luid = {}; + if (!_adapter) { return luid; } + + DXGI_ADAPTER_DESC1 adapterDesc = {}; + if (FAILED(_adapter->GetDesc1(&adapterDesc))) { return luid; } + + return adapterDesc.AdapterLuid; +} + const bool GDX12Device::IsInitialized() { return _isInitialized; -} \ No newline at end of file +} diff --git a/Engine/Engine.RendererDX12/src/GDX12DeviceFactory.cpp b/Engine/Engine.RendererDX12/src/GDX12DeviceFactory.cpp index 0fdf340..23df9cc 100644 --- a/Engine/Engine.RendererDX12/src/GDX12DeviceFactory.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12DeviceFactory.cpp @@ -2,17 +2,32 @@ #include "Engine.RendererDX12/GDX12Device.h" #include "Engine.RendererDX12/GDX12CommandQueue.h" +#include "Engine.RendererDX12/GDX12StreamlineSDK.h" ComPtr GDX12DeviceFactory::_dxgiFactory = nullptr; +ComPtr GDX12DeviceFactory::_dxgiFactoryProxy = nullptr; bool GDX12DeviceFactory::_isInitialized = false; HRESULT GDX12DeviceFactory::Initialize() { - if (_isInitialized) { return S_OK; } + if (_isInitialized) + { + if (!_dxgiFactoryProxy && GDX12StreamlineSDK::Get().IsEnabled()) + { + _dxgiFactoryProxy = GDX12StreamlineSDK::Get().CreateProxyFactory(_dxgiFactory); + } + return S_OK; + } - HRESULT hr = CreateDXGIFactory2(D3D12_DEVICE_FACTORY_FLAG_ALLOW_RETURNING_EXISTING_DEVICE, IID_PPV_ARGS(&_dxgiFactory)); + ComPtr createdFactory; + HRESULT hr = CreateDXGIFactory2(D3D12_DEVICE_FACTORY_FLAG_ALLOW_RETURNING_EXISTING_DEVICE, IID_PPV_ARGS(&createdFactory)); - if (SUCCEEDED(hr)) { _isInitialized = true; } + if (SUCCEEDED(hr)) + { + _dxgiFactoryProxy = GDX12StreamlineSDK::Get().CreateProxyFactory(createdFactory); + _dxgiFactory = GDX12StreamlineSDK::Get().GetNativeFactory(_dxgiFactoryProxy ? _dxgiFactoryProxy : createdFactory); + _isInitialized = true; + } return hr; } @@ -24,6 +39,7 @@ const ComPtr& GDX12DeviceFactory::GetFactory() void GDX12DeviceFactory::Reset() { + _dxgiFactoryProxy.Reset(); _dxgiFactory.Reset(); _isInitialized = false; } @@ -88,9 +104,10 @@ ComPtr GDX12DeviceFactory::GetMostPerformantAdapter() ComPtr GDX12DeviceFactory::CreateSwapChain(GDX12Device* device, DXGI_SWAP_CHAIN_DESC1& desc, HWND hwnd) { ComPtr swapChain4; + const ComPtr& factory = _dxgiFactoryProxy ? _dxgiFactoryProxy : _dxgiFactory; ComPtr swapChain1; - ThrowIfFailed(_dxgiFactory->CreateSwapChainForHwnd(device->GetCommandQueue()->GetCommandQueue().Get(), + ThrowIfFailed(factory->CreateSwapChainForHwnd(device->GetCommandQueue()->GetPresentCommandQueue().Get(), hwnd, &desc, nullptr, nullptr, &swapChain1)); ThrowIfFailed(swapChain1.As(&swapChain4)); diff --git a/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp b/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp new file mode 100644 index 0000000..993abf1 --- /dev/null +++ b/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp @@ -0,0 +1,104 @@ +#include "Engine.RendererDX12/GDX12DeviceResources.h" + +#include "Common/ConsoleVariables.h" +#include "Engine.RendererDX12/GDX12Device.h" + +#include "Common/GameTimer.h" + +static UINT _numFrameConstants = 3; + +static AutoConsoleVariableRef NumFrameConstantVariable( + L"Render.NumFrames", + _numFrameConstants, + L"How many deferred frames was rendered"); + +void GDX12DeviceResources::Initialize(GDX12Device* device) +{ + Device = device; + InputLayouts["Default"] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 36, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } + }; + + RTVHeap = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1000, + D3D12_DESCRIPTOR_HEAP_FLAG_NONE); + + SRV_UAV_Heap = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1000000, + D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); + + DSVHeap = std::make_unique(device, + D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1000, + D3D12_DESCRIPTOR_HEAP_FLAG_NONE); + + GeometryBuffer = std::make_unique(device); + + for (int i = 0; i < NumFrameConstantVariable.GetValue(); i++) + { + FrameConstants.push_back(std::make_unique(device)); + + FrameConstants[i]->MaterialCache->CreateSRV(SRV_UAV_Heap.get(), SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + FrameConstants[i]->TransformCache->CreateSRV(SRV_UAV_Heap.get(), SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + FrameConstants[i]->InstanceCache->CreateSRV(SRV_UAV_Heap.get(), SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + } + + IndirectCommandsCache = std::make_unique>(device, 0, EBufferType::Upload, false); + IndirectCommandsCache->CreateSRV(SRV_UAV_Heap.get(), SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); +} + +void GDX12DeviceResources::UpdateMainCB(UINT width, UINT height, GameTimer* timer) +{ + auto& frameRes = FrameConstants[CurrFrameConstantsIndex]; + + GDX12MainConstants mainConstants; + + mainConstants.RenderTargetSize = { static_cast(width), static_cast(height) }; + mainConstants.TotalTime = timer->TotalTime(); + mainConstants.DeltaTime = timer->DeltaTime(); + + frameRes->MainCB->CopyData(0, mainConstants); +} + +void GDX12DeviceResources::UpdateMaterialCB(std::unordered_map>& materials) +{ + auto currMaterialCB = FrameConstants[CurrFrameConstantsIndex]->MaterialCache.get(); + for (auto& i : materials) + { + GDX12Material* material = i.second.get(); + + if (material->DirtyFlag) + { + material->DirtyFlag = false; + material->_numFramesDirty = _numFrameConstants; + } + + if (material->_numFramesDirty > 0) + { + GDX12MaterialConstants materialConstants; + materialConstants.Roughness = material->Roughness; + materialConstants.Metallic = material->Metallic; + materialConstants.Opacity = material->Opacity; + materialConstants.RenderLayer = UINT(material->Type); + + if (Device->Role == DEVICE_ROLE_PRIMARY) + { + if (material->Diffuse && material->Diffuse->PrimaryDeviceTexture) { materialConstants.DiffuseIndex = material->Diffuse->PrimaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + if (material->Normal && material->Normal->PrimaryDeviceTexture) { materialConstants.NormalIndex = material->Normal->PrimaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + if (material->Displacement && material->Displacement->PrimaryDeviceTexture) { materialConstants.DisplacementIndex = material->Displacement->PrimaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + currMaterialCB->CopyData(material->_CBufferIndex, materialConstants); + } + else + { + if (material->Diffuse && material->Diffuse->SecondaryDeviceTexture) { materialConstants.DiffuseIndex = material->Diffuse->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + if (material->Normal && material->Normal->SecondaryDeviceTexture) { materialConstants.NormalIndex = material->Normal->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + if (material->Displacement && material->Displacement->SecondaryDeviceTexture) { materialConstants.DisplacementIndex = material->Displacement->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + currMaterialCB->CopyData(material->_CBufferIndex, materialConstants); + } + material->_numFramesDirty--; + } + } +} diff --git a/Engine/Engine.RendererDX12/src/GDX12FrameConstants.cpp b/Engine/Engine.RendererDX12/src/GDX12FrameConstants.cpp index 9878250..3cc7f7c 100644 --- a/Engine/Engine.RendererDX12/src/GDX12FrameConstants.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12FrameConstants.cpp @@ -12,10 +12,6 @@ GDX12FrameConstants::GDX12FrameConstants(GDX12Device* device) MaterialCache = std::make_unique>(device, 0, EBufferType::Upload, false); LightCB = std::make_unique>(device, 0, EBufferType::Upload, true); CameraCB = std::make_unique>(device, 0, EBufferType::Upload, true); - VisibleOpaqueCommandsCache = std::make_unique>(device, 0, EBufferType::Default, false); - OpaqueDrawCounter = std::make_unique>(device, 1, EBufferType::Default, false); - VisibleTransparentCommandsCache = std::make_unique>(device, 0, EBufferType::Default, false); - TransparentDrawCounter = std::make_unique>(device, 1, EBufferType::Default, false); } GDX12FrameConstants::~GDX12FrameConstants() diff --git a/Engine/Engine.RendererDX12/src/GDX12RenderCommandRecorder.cpp b/Engine/Engine.RendererDX12/src/GDX12RenderCommandRecorder.cpp deleted file mode 100644 index 37168d7..0000000 --- a/Engine/Engine.RendererDX12/src/GDX12RenderCommandRecorder.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "Engine.RendererDX12/GDX12RenderCommandRecorder.h" - -GDX12RenderCommandRecorder::GDX12RenderCommandRecorder() : _cameraCBIndex(0) -{ -} - -void GDX12RenderCommandRecorder::DrawFromCamera(int cameraCBIndex) -{ - _cameraCBIndex = cameraCBIndex; -} - -void GDX12RenderCommandRecorder::ClearCommands() -{ - _cameraCBIndex = 0; -} - - diff --git a/Engine/Engine.RendererDX12/src/GDX12Resource.cpp b/Engine/Engine.RendererDX12/src/GDX12Resource.cpp index f9b9282..9269c04 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Resource.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Resource.cpp @@ -123,6 +123,14 @@ CD3DX12_RESOURCE_BARRIER GDX12Resource::GetUAVBarrier() return barrier; } +CD3DX12_RESOURCE_BARRIER GDX12Resource::GetSRVBarrier() +{ + auto transition = CD3DX12_RESOURCE_BARRIER::Transition(D3DResource.Get(), + _currentState, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + _currentState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + return transition; +} + void GDX12Resource::SetCurrentState(D3D12_RESOURCE_STATES newState) { _currentState = newState; @@ -132,3 +140,14 @@ D3D12_RESOURCE_STATES GDX12Resource::GetCurrentState() { return _currentState; } + +void GDX12Resource::Reset() +{ + D3DResource.Reset(); + _currentState = D3D12_RESOURCE_STATE_COMMON; +} + +void GDX12Resource::ResetState() +{ + _currentState = D3D12_RESOURCE_STATE_COMMON; +} diff --git a/Engine/Engine.RendererDX12/src/GDX12ShaderCompiler.cpp b/Engine/Engine.RendererDX12/src/GDX12ShaderCompiler.cpp index 15b4c18..49fbb6a 100644 --- a/Engine/Engine.RendererDX12/src/GDX12ShaderCompiler.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12ShaderCompiler.cpp @@ -36,7 +36,7 @@ ComPtr GDX12ShaderCompiler::CompileShader(GDX12Device* device, const s { std::string target = GetShaderTargetForModel(device, shaderType); - if (device->GetDeviceFeatures().MaxShaderModel == D3D_SHADER_MODEL_5_1) + if (device->GetDeviceFeatures().Features.HighestShaderModel() == D3D_SHADER_MODEL_5_1) { return CompileShaderFXC(filename, defines, entrypoint, target); } @@ -57,7 +57,7 @@ void GDX12ShaderCompiler::Shutdown() std::string GDX12ShaderCompiler::GetShaderTargetForModel(GDX12Device* device, const std::string& shaderType) { - D3D_SHADER_MODEL targetModel = device->GetDeviceFeatures().MaxShaderModel; + D3D_SHADER_MODEL targetModel = device->GetDeviceFeatures().Features.HighestShaderModel(); UINT modelMajor = (targetModel >> 4) & 0xF; UINT modelMinor = targetModel & 0xF; @@ -66,7 +66,9 @@ std::string GDX12ShaderCompiler::GetShaderTargetForModel(GDX12Device* device, co switch (modelMajor) { case 6: - if (modelMinor >= 8 && targetModel >= D3D_SHADER_MODEL_6_8) { targetVersion = "6_8"; } + if (modelMinor >= 10 && targetModel >= D3D_SHADER_MODEL_6_10) { targetVersion = "6_10"; } + else if (modelMinor >= 9 && targetModel >= D3D_SHADER_MODEL_6_9) { targetVersion = "6_9"; } + else if (modelMinor >= 8 && targetModel >= D3D_SHADER_MODEL_6_8) { targetVersion = "6_8"; } else if (modelMinor >= 7 && targetModel >= D3D_SHADER_MODEL_6_7) { targetVersion = "6_7"; } else if (modelMinor >= 6 && targetModel >= D3D_SHADER_MODEL_6_6) { targetVersion = "6_6"; } else if (modelMinor >= 5 && targetModel >= D3D_SHADER_MODEL_6_5) { targetVersion = "6_5"; } diff --git a/Engine/Engine.RendererDX12/src/GDX12StreamlineSDK.cpp b/Engine/Engine.RendererDX12/src/GDX12StreamlineSDK.cpp new file mode 100644 index 0000000..2276e1d --- /dev/null +++ b/Engine/Engine.RendererDX12/src/GDX12StreamlineSDK.cpp @@ -0,0 +1,301 @@ +#include "Engine.RendererDX12/GDX12StreamlineSDK.h" + +#include + +#ifdef free +#pragma push_macro("free") +#undef free +#define PEP_RESTORE_FREE_MACRO_STREAMLINE_CPP 1 +#endif +#include "nvidia-sdk/sl_security.h" +#ifdef PEP_RESTORE_FREE_MACRO_STREAMLINE_CPP +#pragma pop_macro("free") +#undef PEP_RESTORE_FREE_MACRO_STREAMLINE_CPP +#endif + +GDX12StreamlineSDK& GDX12StreamlineSDK::Get() +{ + static GDX12StreamlineSDK instance; + return instance; +} + +bool GDX12StreamlineSDK::Initialize() +{ + if (_initialized) { return true; } + + _runtimeDirectory = GetRuntimeDirectory(); + LoadInterposer(); + LoadFunctions(); + + const wchar_t* pluginPaths[] = { _runtimeDirectory.c_str() }; + + sl::Preferences preferences{}; + preferences.showConsole = false; + preferences.logLevel = sl::LogLevel::eOff; + preferences.pathsToPlugins = pluginPaths; + preferences.numPathsToPlugins = static_cast(std::size(pluginPaths)); + preferences.pathToLogsAndData = _runtimeDirectory.c_str(); + preferences.logMessageCallback = &GDX12StreamlineSDK::StreamlineLog; + preferences.flags = sl::PreferenceFlags::eDisableCLStateTracking + | sl::PreferenceFlags::eUseManualHooking + | sl::PreferenceFlags::eUseDXGIFactoryProxy + | sl::PreferenceFlags::eUseFrameBasedResourceTagging; + + sl::Feature FeaturestoLoad[] = { sl::kFeatureDLSS }; + preferences.featuresToLoad = FeaturestoLoad; + preferences.numFeaturesToLoad = _countof(FeaturestoLoad); + preferences.engine = sl::EngineType::eCustom; + preferences.engineVersion = "1.0.0"; + preferences.projectId = "c9202a3c-8f89-4cf2-952d-65427c52041d"; + preferences.renderAPI = sl::RenderAPI::eD3D12; + + const sl::Result initResult = _slInit(preferences, sl::kSDKVersion); + if (initResult != sl::Result::eOk) + { + LogFailure("slInit", initResult); + Shutdown(); + return false; + } + + _initialized = true; + Log("initialized in manual hooking mode."); + return true; +} + +void GDX12StreamlineSDK::Shutdown() +{ + if (_initialized && _slShutdown) + { + const sl::Result shutdownResult = _slShutdown(); + if (shutdownResult != sl::Result::eOk) { LogFailure("slShutdown", shutdownResult); } + } + + _initialized = false; + _mainDeviceWasSet = false; + + _slInit = nullptr; + _slShutdown = nullptr; + _slUpgradeInterface = nullptr; + _slGetNativeInterface = nullptr; + _slSetD3DDevice = nullptr; + _slIsFeatureSupported = nullptr; + _slGetFeatureFunction = nullptr; + _slEvaluateFeature = nullptr; + _slFreeResources = nullptr; + _slSetTagForFrame = nullptr; + _slSetConstants = nullptr; + _slGetNewFrameToken = nullptr; + _slDLSSGetOptimalSettings = nullptr; + _slDLSSSetOptions = nullptr; + + if (_interposerModule) + { + FreeLibrary(_interposerModule); + _interposerModule = nullptr; + } +} + +bool GDX12StreamlineSDK::IsEnabled() const +{ + return _initialized; +} + +std::string GDX12StreamlineSDK::ResultToString(sl::Result result) +{ + const char* name = sl::getResultAsStr(result); + return name ? name : "UNKNOWN_RESULT"; +} + +ComPtr GDX12StreamlineSDK::CreateProxyFactory(const ComPtr& nativeFactory) const +{ + const ComPtr resolvedNativeFactory = UnwrapInterface(nativeFactory); + if (resolvedNativeFactory && resolvedNativeFactory.Get() != nativeFactory.Get()) + { return nativeFactory; } + + return UpgradeInterface(nativeFactory, "slUpgradeInterface(IDXGIFactory7)"); +} + +ComPtr GDX12StreamlineSDK::CreateProxyDevice(const ComPtr& nativeDevice, bool setAsMainDevice) const +{ + if (!_initialized || !nativeDevice) + { + return nativeDevice; + } + + const ComPtr resolvedNativeDevice = UnwrapInterface(nativeDevice); + const bool inputAlreadyProxy = resolvedNativeDevice && resolvedNativeDevice.Get() != nativeDevice.Get(); + const ComPtr& deviceToRegister = inputAlreadyProxy ? resolvedNativeDevice : nativeDevice; + + if (setAsMainDevice && !_mainDeviceWasSet) + { + const sl::Result setDeviceResult = _slSetD3DDevice(deviceToRegister.Get()); + if (setDeviceResult != sl::Result::eOk) + { + LogFailure("slSetD3DDevice", setDeviceResult); + return nativeDevice; + } + + const_cast(this)->_mainDeviceWasSet = true; + } + + if (inputAlreadyProxy) + { + return nativeDevice; + } + + return UpgradeInterface(nativeDevice, "slUpgradeInterface(ID3D12Device14)"); +} + +ComPtr GDX12StreamlineSDK::GetNativeFactory(const ComPtr& factory) const +{ + return UnwrapInterface(factory); +} + +ComPtr GDX12StreamlineSDK::GetNativeDevice(const ComPtr& device) const +{ + return UnwrapInterface(device); +} + +ComPtr GDX12StreamlineSDK::GetNativeCommandQueue(const ComPtr& commandQueue) const +{ + return UnwrapInterface(commandQueue); +} + +ComPtr GDX12StreamlineSDK::GetNativeSwapChain(const ComPtr& swapChain) const +{ + return UnwrapInterface(swapChain); +} + +ComPtr GDX12StreamlineSDK::GetNativeResource(const ComPtr& resource) const +{ + return UnwrapInterface(resource); +} + +sl::Result GDX12StreamlineSDK::IsFeatureSupported(sl::Feature feature, const sl::AdapterInfo& adapterInfo) const +{ + return _slIsFeatureSupported(feature, adapterInfo); +} + +sl::Result GDX12StreamlineSDK::GetNewFrameToken(sl::FrameToken*& token, const uint32_t* frameIndex) const +{ + return _slGetNewFrameToken(token, frameIndex); +} + +sl::Result GDX12StreamlineSDK::SetTagForFrame(const sl::FrameToken& frame, const sl::ViewportHandle& viewport, const sl::ResourceTag* tags, uint32_t numTags, sl::CommandBuffer* cmdBuffer) const +{ + return _slSetTagForFrame(frame, viewport, tags, numTags, cmdBuffer); +} + +sl::Result GDX12StreamlineSDK::EvaluateFeature(sl::Feature feature, const sl::FrameToken& frame, const sl::BaseStructure** inputs, uint32_t numInputs, sl::CommandBuffer* cmdBuffer) const +{ + return _slEvaluateFeature(feature, frame, inputs, numInputs, cmdBuffer); +} + +sl::Result GDX12StreamlineSDK::FreeResources(sl::Feature feature, const sl::ViewportHandle& viewport) const +{ + return _slFreeResources(feature, viewport); +} + +sl::Result GDX12StreamlineSDK::SetConstants(const sl::Constants& values, const sl::FrameToken& frame, const sl::ViewportHandle& viewport) const +{ + return _slSetConstants(values, frame, viewport); +} + +sl::Result GDX12StreamlineSDK::DLSSGetOptimalSettings(const sl::DLSSOptions& options, sl::DLSSOptimalSettings& settings) const +{ + const sl::Result loadResult = LoadDLSSFunctions(); + if (loadResult != sl::Result::eOk || !_slDLSSGetOptimalSettings) + { + return loadResult; + } + + return _slDLSSGetOptimalSettings(options, settings); +} + +sl::Result GDX12StreamlineSDK::DLSSSetOptions(const sl::ViewportHandle& viewport, const sl::DLSSOptions& options) const +{ + const sl::Result loadResult = LoadDLSSFunctions(); + if (loadResult != sl::Result::eOk || !_slDLSSSetOptions) + { + return loadResult; + } + + return _slDLSSSetOptions(viewport, options); +} + +void GDX12StreamlineSDK::StreamlineLog(sl::LogType type, const char* message) +{ + const char* level = "INFO"; + if (type == sl::LogType::eWarn) { level = "WARNING"; } + else if (type == sl::LogType::eError) { level = "ERROR"; } + + std::string formattedMessage = std::string("Streamline ") + '[' + level + "] " + (message ? message : "") + '\n'; + OutputDebugStringA(formattedMessage.c_str()); +} + +std::wstring GDX12StreamlineSDK::GetRuntimeDirectory() const +{ + wchar_t executablePath[MAX_PATH] = {}; + const DWORD pathLength = GetModuleFileNameW(nullptr, executablePath, MAX_PATH); + + return std::filesystem::path(std::wstring(executablePath, executablePath + pathLength)).parent_path().wstring(); +} + +void GDX12StreamlineSDK::LoadInterposer() +{ + const std::filesystem::path interposerPath = std::filesystem::path(_runtimeDirectory) / L"sl.interposer.dll"; + if (!std::filesystem::exists(interposerPath)) { LogWarning("sl.interposer.dll was not found"); } + if (!sl::security::verifyEmbeddedSignature(interposerPath.c_str())) + { LogWarning("sl.interposer.dll signature check failed"); } + _interposerModule = LoadLibraryW(interposerPath.c_str()); + if (!_interposerModule) { LogWarning("sl.interposer.dll LoadLibraryW failed"); } +} + +void GDX12StreamlineSDK::LoadFunctions() +{ + _slInit = reinterpret_cast(GetProcAddress(_interposerModule, "slInit")); + _slShutdown = reinterpret_cast(GetProcAddress(_interposerModule, "slShutdown")); + _slUpgradeInterface = reinterpret_cast(GetProcAddress(_interposerModule, "slUpgradeInterface")); + _slGetNativeInterface = reinterpret_cast(GetProcAddress(_interposerModule, "slGetNativeInterface")); + _slSetD3DDevice = reinterpret_cast(GetProcAddress(_interposerModule, "slSetD3DDevice")); + _slIsFeatureSupported = reinterpret_cast(GetProcAddress(_interposerModule, "slIsFeatureSupported")); + _slGetFeatureFunction = reinterpret_cast(GetProcAddress(_interposerModule, "slGetFeatureFunction")); + _slEvaluateFeature = reinterpret_cast(GetProcAddress(_interposerModule, "slEvaluateFeature")); + _slFreeResources = reinterpret_cast(GetProcAddress(_interposerModule, "slFreeResources")); + _slSetTagForFrame = reinterpret_cast(GetProcAddress(_interposerModule, "slSetTagForFrame")); + _slSetConstants = reinterpret_cast(GetProcAddress(_interposerModule, "slSetConstants")); + _slGetNewFrameToken = reinterpret_cast(GetProcAddress(_interposerModule, "slGetNewFrameToken")); + + if (!_slInit || !_slShutdown || !_slUpgradeInterface || !_slGetNativeInterface || !_slSetD3DDevice + || !_slIsFeatureSupported + || !_slGetFeatureFunction || !_slEvaluateFeature || !_slFreeResources || !_slSetTagForFrame + || !_slSetConstants || !_slGetNewFrameToken) + { LogWarning("Required Streamline exports are missing, Streamline is disabled."); } +} + +sl::Result GDX12StreamlineSDK::LoadDLSSFunctions() const +{ + sl::Result result = LoadFeatureFunction(sl::kFeatureDLSS, "slDLSSGetOptimalSettings", _slDLSSGetOptimalSettings); + if (result != sl::Result::eOk) { return result; } + + result = LoadFeatureFunction(sl::kFeatureDLSS, "slDLSSSetOptions", _slDLSSSetOptions); + return result; +} + +void GDX12StreamlineSDK::Log(const std::string& message) const +{ + std::string formattedMessage = std::string("Streamline INFO: ") + message + '\n'; + OutputDebugStringA(formattedMessage.c_str()); +} + +void GDX12StreamlineSDK::LogWarning(const std::string& message) const +{ + std::string formattedMessage = std::string("Streamline WARNING: ") + message + '\n'; + OutputDebugStringA(formattedMessage.c_str()); +} + +void GDX12StreamlineSDK::LogFailure(const char* operation, sl::Result result) const +{ + std::string formattedMessage = std::string("Streamline ERROR: ") + operation + " failed: " + ResultToString(result) + '\n'; + OutputDebugStringA(formattedMessage.c_str()); +} diff --git a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp index 5fffdf7..7fb2ef9 100644 --- a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp @@ -4,17 +4,13 @@ #include #include #include +#include GDX12SwapChain::GDX12SwapChain(GDX12Device* device, HWND hwnd, DXGI_FORMAT format, UINT bufferCount, UINT width, UINT height, GDX12DescriptorHeap* rtvHeap) - : _device(device) - , _hwnd(hwnd) - , _format(format) - , _bufferCount(bufferCount) - , _currentBufferIndex(0) - , _width(width) - , _height(height) - , _rtvHeap(rtvHeap) + : _device(device), _hwnd(hwnd), + _format(format), _bufferCount(bufferCount), _currentBufferIndex(0), + _width(width), _height(height), _rtvHeap(rtvHeap), bVSyncEnabled(false) { Reset(); @@ -32,9 +28,10 @@ GDX12SwapChain::GDX12SwapChain(GDX12Device* device, HWND hwnd, swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH | DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; - _swapChain = GDX12DeviceFactory::CreateSwapChain(_device, swapChainDesc, _hwnd); - + _proxySwapChain = GDX12DeviceFactory::CreateSwapChain(_device, swapChainDesc, _hwnd); + _swapChain = GDX12StreamlineSDK::Get().GetNativeSwapChain(_proxySwapChain); CreateBuffers(); + _currentBufferIndex = GetPresentationSwapChain()->GetCurrentBackBufferIndex(); _screenViewport.TopLeftX = 0; _screenViewport.TopLeftY = 0; @@ -59,7 +56,8 @@ void GDX12SwapChain::CreateBuffers() for (UINT i = 0; i < _bufferCount; i++) { ComPtr backBuffer; - _swapChain->GetBuffer(i, IID_PPV_ARGS(&backBuffer)); + GetPresentationSwapChain()->GetBuffer(i, IID_PPV_ARGS(&backBuffer)); + backBuffer = GDX12StreamlineSDK::Get().GetNativeResource(backBuffer); GDX12TextureDesc textureDesc; textureDesc.RTVHeap = _rtvHeap; @@ -78,7 +76,8 @@ void GDX12SwapChain::CreateBuffers() textureDesc.ExternalResource = backBuffer; - _buffers.push_back(std::make_unique(textureDesc)); + _buffers.push_back(std::make_unique()); + _buffers[i]->Initialize(textureDesc); } } @@ -92,14 +91,14 @@ void GDX12SwapChain::Resize(UINT width, UINT height) _buffers.clear(); DXGI_SWAP_CHAIN_DESC desc; - _swapChain->GetDesc(&desc); + GetPresentationSwapChain()->GetDesc(&desc); - _swapChain->ResizeBuffers( + GetPresentationSwapChain()->ResizeBuffers( _bufferCount, _width, _height, desc.BufferDesc.Format, desc.Flags); CreateBuffers(); - _currentBufferIndex = _swapChain->GetCurrentBackBufferIndex(); + _currentBufferIndex = GetPresentationSwapChain()->GetCurrentBackBufferIndex(); _screenViewport.TopLeftX = 0; _screenViewport.TopLeftY = 0; @@ -113,8 +112,10 @@ void GDX12SwapChain::Resize(UINT width, UINT height) void GDX12SwapChain::Present() { - _swapChain->Present(0u, DXGI_PRESENT_ALLOW_TEARING); - _currentBufferIndex = (_currentBufferIndex + 1) % _bufferCount; + UINT syncInterval = bVSyncEnabled ? 1 : 0; + UINT presentFlags = bVSyncEnabled ? 0 : DXGI_PRESENT_ALLOW_TEARING; + GetPresentationSwapChain()->Present(syncInterval, presentFlags); + _currentBufferIndex = GetPresentationSwapChain()->GetCurrentBackBufferIndex(); } D3D12_VIEWPORT GDX12SwapChain::GetViewport() @@ -127,6 +128,16 @@ D3D12_RECT GDX12SwapChain::GetScissorRect() return _screenScissorRect; } +GDX12Texture* GDX12SwapChain::GetTexture() +{ + return GetCurrentBuffer(); +} + +bool GDX12SwapChain::IsInitialized() +{ + return true; +} + DXGI_FORMAT GDX12SwapChain::GetFormat() { return _format; @@ -166,6 +177,12 @@ const ComPtr& GDX12SwapChain::GetSwapChain() void GDX12SwapChain::Reset() { _buffers.clear(); + _proxySwapChain.Reset(); _swapChain.Reset(); _currentBufferIndex = 0; } + +IDXGISwapChain4* GDX12SwapChain::GetPresentationSwapChain() const +{ + return (_proxySwapChain ? _proxySwapChain : _swapChain).Get(); +} diff --git a/Engine/Engine.RendererDX12/src/GDX12Texture.cpp b/Engine/Engine.RendererDX12/src/GDX12Texture.cpp index 1fd474a..8c2dc79 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Texture.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Texture.cpp @@ -6,45 +6,10 @@ #include "Engine.RendererDX12/GDX12CommandList.h" #include "Engine.RendererDX12/GDX12TextureResource.h" -GDX12Texture::GDX12Texture(GDX12TextureDesc desc) : - _desc(desc), - _srv(nullptr), - _rtv(nullptr), - _uav(nullptr), - _dsv(nullptr), - _resourceFlags(D3D12_RESOURCE_FLAG_NONE) +GDX12Texture::GDX12Texture() : + _srv(nullptr), _rtv(nullptr), _uav(nullptr), _dsv(nullptr), + _resourceFlags(D3D12_RESOURCE_FLAG_NONE), _isInitialized(false), _device(nullptr) { - if (_desc.CreateRTV && _desc.CreateDSV) { OutputDebugStringA("ERROR: It is impossible to create RTV and DSV on the same texture.\n"); } - if (_desc.CreateUAV && _desc.CreateDSV) { OutputDebugStringA("ERROR: It is impossible to create DSV and UAV on the same texture.\n"); } - - //grab device pointer from any avalible heap - if (_desc.SRV_UAV_Heap) { _device = _desc.SRV_UAV_Heap->_device; } - if (_desc.RTVHeap) { _device = _desc.RTVHeap->_device; } - if (_desc.DSVHeap) { _device = _desc.DSVHeap->_device; } - - if (_desc.CreateRTV) { _resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; } - if (_desc.CreateDSV) { _resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; } - if (_desc.CreateUAV) { _resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; } - - if (_desc.CreateRTV) - { - _clearValue.Color[0] = _desc.ClearValue.x; - _clearValue.Color[1] = _desc.ClearValue.y; - _clearValue.Color[2] = _desc.ClearValue.z; - _clearValue.Color[3] = _desc.ClearValue.w; - } - else if (_desc.CreateDSV) - { - _clearValue.DepthStencil.Depth = _desc.ClearValue.x; - _clearValue.DepthStencil.Stencil = _desc.ClearValue.y; - } - - _clearValue.Format = _desc.Format; - - if (_desc.ExternalResource != nullptr) { _resource = std::make_unique(_desc.ExternalResource); } - else { CreateResource(); } - - CreateViews(); } void GDX12Texture::Resize(UINT width, UINT height) @@ -53,32 +18,61 @@ void GDX12Texture::Resize(UINT width, UINT height) _desc.Height = height; if (_desc.ExternalResource == nullptr) { CreateResource(); } CreateViews(); + + _viewport.TopLeftX = 0; + _viewport.TopLeftY = 0; + _viewport.Width = static_cast(width); + _viewport.Height = static_cast(height); + _viewport.MinDepth = 0.0f; + _viewport.MaxDepth = 1.0f; + + _scissorRect = { 0, 0, static_cast(width), static_cast(height) }; } GDX12Descriptor* GDX12Texture::GetSRV() { - if (!_desc.CreateSRV) { OutputDebugStringA("ERROR: Can't get Texture SRV: SRV not created.\n"); } + if (!HasSRV()) { OutputDebugStringA("ERROR: Can't get Texture SRV: SRV not created.\n"); } return _srv.get(); } GDX12Descriptor* GDX12Texture::GetRTV() { - if (!_desc.CreateRTV) { OutputDebugStringA("ERROR: Can't get Texture RTV: RTV not created.\n"); } + if (!HasRTV()) { OutputDebugStringA("ERROR: Can't get Texture RTV: RTV not created.\n"); } return _rtv.get(); } GDX12Descriptor* GDX12Texture::GetUAV() { - if (!_desc.CreateUAV) { OutputDebugStringA("ERROR: Can't get Texture UAV: UAV not created.\n"); } + if (!HasUAV()) { OutputDebugStringA("ERROR: Can't get Texture UAV: UAV not created.\n"); } return _uav.get(); } GDX12Descriptor* GDX12Texture::GetDSV() { - if (!_desc.CreateDSV) { OutputDebugStringA("ERROR: Can't get Texture DSV: DSV not created.\n"); } + if (!HasDSV()) { OutputDebugStringA("ERROR: Can't get Texture DSV: DSV not created.\n"); } return _dsv.get(); } +bool GDX12Texture::HasDSV() +{ + return _desc.CreateDSV; +} + +bool GDX12Texture::HasSRV() +{ + return _desc.CreateSRV; +} + +bool GDX12Texture::HasUAV() +{ + return _desc.CreateUAV; +} + +bool GDX12Texture::HasRTV() +{ + return _desc.CreateRTV; +} + D3D12_CLEAR_VALUE& GDX12Texture::GetClearValue() { return _clearValue; @@ -99,6 +93,36 @@ ETextureSemantic GDX12Texture::GetSemantic() const return _desc.Semantic; } +D3D12_VIEWPORT GDX12Texture::GetViewport() +{ + return _viewport; +} + +D3D12_RECT GDX12Texture::GetScissorRect() +{ + return _scissorRect; +} + +UINT GDX12Texture::GetWidth() +{ + return _desc.Width; +} + +UINT GDX12Texture::GetHeight() +{ + return _desc.Height; +} + +GDX12Texture* GDX12Texture::GetTexture() +{ + return this; +} + +bool GDX12Texture::IsInitialized() +{ + return _isInitialized; +} + void GDX12Texture::CreateResource() { D3D12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D( @@ -122,6 +146,7 @@ void GDX12Texture::CreateResource() if (!_resource) { _resource = std::make_unique(d3dResource); } else { _resource->D3DResource = d3dResource; } + _resource->ResetState(); } void GDX12Texture::CreateViews() @@ -171,3 +196,51 @@ GDX12Texture::~GDX12Texture() _uav.reset(); _dsv.reset(); } + +void GDX12Texture::Initialize(GDX12TextureDesc desc) +{ + _desc = desc; + if (_desc.CreateRTV && _desc.CreateDSV) { OutputDebugStringA("ERROR: It is impossible to create RTV and DSV on the same texture.\n"); } + if (_desc.CreateUAV && _desc.CreateDSV) { OutputDebugStringA("ERROR: It is impossible to create DSV and UAV on the same texture.\n"); } + + //grab device pointer from any avalible heap + if (_desc.SRV_UAV_Heap) { _device = _desc.SRV_UAV_Heap->_device; } + if (_desc.RTVHeap) { _device = _desc.RTVHeap->_device; } + if (_desc.DSVHeap) { _device = _desc.DSVHeap->_device; } + + if (_desc.CreateRTV) { _resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; } + if (_desc.CreateDSV) { _resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; } + if (_desc.CreateUAV) { _resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; } + if (_desc.CreateSRV) { _resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; } + + if (_desc.CreateRTV) + { + _clearValue.Color[0] = _desc.ClearValue.x; + _clearValue.Color[1] = _desc.ClearValue.y; + _clearValue.Color[2] = _desc.ClearValue.z; + _clearValue.Color[3] = _desc.ClearValue.w; + } + else if (_desc.CreateDSV) + { + _clearValue.DepthStencil.Depth = _desc.ClearValue.x; + _clearValue.DepthStencil.Stencil = _desc.ClearValue.y; + } + + _clearValue.Format = _desc.Format; + + if (_desc.ExternalResource != nullptr) { _resource = std::make_unique(_desc.ExternalResource); } + else { CreateResource(); } + + CreateViews(); + + _viewport.TopLeftX = 0; + _viewport.TopLeftY = 0; + _viewport.Width = static_cast(_desc.Width); + _viewport.Height = static_cast(_desc.Height); + _viewport.MinDepth = 0.0f; + _viewport.MaxDepth = 1.0f; + + _scissorRect = { 0, 0, static_cast(_desc.Width), static_cast(_desc.Height) }; + + _isInitialized = true; +} diff --git a/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp b/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp index baa4d25..672e65c 100644 --- a/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp @@ -9,6 +9,11 @@ GDX12TextureResource::GDX12TextureResource(ComPtr resource) : _desc = D3DResource->GetDesc(); } +GDX12TextureResource::GDX12TextureResource() : _currentAccess(D3D12_BARRIER_ACCESS_COMMON), + _currentLayout(D3D12_BARRIER_LAYOUT_COMMON), _currentSync(D3D12_BARRIER_SYNC_ALL), _desc({}) +{ +} + GDX12TextureResource::~GDX12TextureResource() { } @@ -30,6 +35,15 @@ void GDX12TextureResource::SetCurrentState(D3D12_BARRIER_SYNC sync, D3D12_BARRIE _currentLayout = layout; } +void GDX12TextureResource::ResetState() +{ + GDX12Resource::ResetState(); + + _currentSync = D3D12_BARRIER_SYNC_NONE; + _currentAccess = D3D12_BARRIER_ACCESS_COMMON; + _currentLayout = D3D12_BARRIER_LAYOUT_COMMON; +} + D3D12_BARRIER_SYNC GDX12TextureResource::GetCurrentSync() { return _currentSync; diff --git a/External/External.Libraries/xess/Include/xell/xell.h b/External/External.Libraries/xess/Include/xell/xell.h new file mode 100644 index 0000000..c91b351 --- /dev/null +++ b/External/External.Libraries/xess/Include/xell/xell.h @@ -0,0 +1,245 @@ +/******************************************************************************* + * Copyright (C) 2024 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, and + * your use of them is governed by the express license under which they were + * provided to you ("License"). Unless the License provides otherwise, you may + * not use, modify, copy, publish, distribute, disclose or transmit this + * software or the related documents without Intel's prior written permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + ******************************************************************************/ +#pragma once +#include + +#if defined (_WIN32) +#if defined(XELL_EXPORT_API) +#define XELL_EXPORT __declspec(dllexport) +#else +#define XELL_EXPORT __declspec(dllimport) +#endif /* XELL_EXPORT_API */ +#else /* !defined (_WIN32) */ +#define XELL_EXPORT +#endif + +#if !defined _MSC_VER || (_MSC_VER >= 1929) +#define XELL_PRAGMA(x) _Pragma(#x) +#else +#define XELL_PRAGMA(x) __pragma(x) +#endif +#define XELL_PACK_B_X(x) XELL_PRAGMA(pack(push, x)) +#define XELL_PACK_E() XELL_PRAGMA(pack(pop)) +#define XELL_PACK_B() XELL_PACK_B_X(8) + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @brief XeLL return codes. +*/ +typedef enum _xell_result_t +{ + /** XeLL operation was successful. */ + XELL_RESULT_SUCCESS = 0, + /** XeLL not supported on the GPU. */ + XELL_RESULT_ERROR_UNSUPPORTED_DEVICE = -1, + /** An unsupported driver. */ + XELL_RESULT_ERROR_UNSUPPORTED_DRIVER = -2, + /** Execute called without initialization. */ + XELL_RESULT_ERROR_UNINITIALIZED = -3, + /** Invalid argument. */ + XELL_RESULT_ERROR_INVALID_ARGUMENT = -4, + /** Device function. */ + XELL_RESULT_ERROR_DEVICE = -6, + /** The function is not implemented. */ + XELL_RESULT_ERROR_NOT_IMPLEMENTED = -7, + /** Invalid context. */ + XELL_RESULT_ERROR_INVALID_CONTEXT = -8, + /** Operation not supported in current configuration. */ + XELL_RESULT_ERROR_UNSUPPORTED = -10, + /** Unknown internal failure. */ + XELL_RESULT_ERROR_UNKNOWN = -1000, +} xell_result_t; + +/** + * @brief XeLL markers. + * + * XeLL markers for game instrumentation. + */ +typedef enum _xell_latency_marker_type_t +{ + XELL_SIMULATION_START = 0, // required + XELL_SIMULATION_END = 1, // required + XELL_RENDERSUBMIT_START = 2, // required + XELL_RENDERSUBMIT_END = 3, // required + XELL_PRESENT_START = 4, // required + XELL_PRESENT_END = 5, // required + XELL_INPUT_SAMPLE = 6, + + XELL_MARKER_COUNT = 7 +} xell_latency_marker_type_t; +XELL_PACK_B() + +typedef struct _xell_sleep_params_t +{ + /** Minimum interval expressed in microseconds. + * If != 0 it will enable fps capping to that value. + */ + uint32_t minimumIntervalUs; //us + /** Enables latency reduction feature. */ + uint32_t bLowLatencyMode : 1; + /** Boost is not supported as of now. */ + uint32_t bLowLatencyBoost : 1; + + /** Reserved for future use. */ + uint32_t reserved : 30; +} xell_sleep_params_t; +XELL_PACK_E() + +/** + * @brief XeLL logging level + */ +typedef enum _xell_logging_level_t +{ + XELL_LOGGING_LEVEL_DEBUG = 0, + XELL_LOGGING_LEVEL_INFO = 1, + XELL_LOGGING_LEVEL_WARNING = 2, + XELL_LOGGING_LEVEL_ERROR = 3 +} xell_logging_level_t; + +/** + * A logging callback provided by the application. This callback can be called from other threads. + * Message pointer are only valid inside function and may be invalid right after return call. + * Message is a null-terminated utf-8 string +*/ +typedef void (*xell_app_log_callback_t)(const char* message, xell_logging_level_t loggingLevel); + +XELL_PACK_B() +/** +* @brief XeLL version. +* +* XeLL uses major.minor.patch version format and Numeric 90+ scheme for development stage builds. +*/ +typedef struct _xell_version_t +{ + /** A major version increment indicates a new API and potentially a + * break in functionality. + */ + uint16_t major; + /** A minor version increment indicates incremental changes such as + * optional inputs or flags. This does not break existing functionality. + */ + uint16_t minor; + /** A patch version increment may include performance or quality tweaks or fixes for known issues. + * There's no change in the interfaces. + * Versions beyond 90 used for development builds to change the interface for the next release. + */ + uint16_t patch; + /** Reserved for future use. */ + uint16_t reserved; +} xell_version_t; +XELL_PACK_E() + +typedef struct _xell_context_handle_t* xell_context_handle_t; + +/** + * @brief Destroy the XeLL context. + * @param context: The XeLL context handle. + * @return XeLL return status code. + */ +XELL_EXPORT xell_result_t xellDestroyContext(xell_context_handle_t context); + +/** + * @brief Setup how XeLL operate. + * @param context: The XeLL context handle. + * @param param: Initialization parameters. + * @return XeLL return status code. + */ +XELL_EXPORT xell_result_t xellSetSleepMode(xell_context_handle_t context, const xell_sleep_params_t* param); + +/** + * @brief Get current XeLL parameters. + * @param context: The XeLL context handle. + * @param param: Returned parameters. + * @return XeLL return status code. + */ +XELL_EXPORT xell_result_t xellGetSleepMode(xell_context_handle_t context, xell_sleep_params_t* param); + +/** + * @brief XeLL will sleep here for the simulation start. + * @param context: The XeLL context handle. + * @param frame_id: The incremental frame counter from the game. + * @return XeLL return status code. + */ +XELL_EXPORT xell_result_t xellSleep(xell_context_handle_t context, uint32_t frame_id); + +/** + * @brief Pass markers to inform XeLL how long the game simulation, render and present time are. + * @param context: The XeLL context handle. + * @param frame_id: The incremental frame counter from the game. + * @param marker: Marker type. + * @return XeLL return status code. + */ +XELL_EXPORT xell_result_t xellAddMarkerData(xell_context_handle_t context, uint32_t frame_id, xell_latency_marker_type_t marker); + +/** + * @brief Gets the XeLL version. This is baked into the XeLL SDK release. + * @param[out] pVersion Returned XeLL version. + * @return XeLL return status code. + */ +XELL_EXPORT xell_result_t xellGetVersion(xell_version_t* pVersion); + +/** + * @brief Sets logging callback + * + * @param hContext The XeLL context handle. + * @param loggingLevel Minimum logging level for logging callback. + * @param loggingCallback Logging callback + * @return XeLL return status code. + */ +XELL_EXPORT xell_result_t xellSetLoggingCallback(xell_context_handle_t hContext, xell_logging_level_t loggingLevel, xell_app_log_callback_t loggingCallback); + +XELL_PACK_B() +/** + * @brief XeLL frame stats. + * + * XeLL frame timestamps. + */ +typedef struct _xell_frame_report_t +{ + uint32_t m_frame_id; //frame id + uint64_t m_sim_start_ts; //ns + uint64_t m_sim_end_ts; //ns + uint64_t m_render_submit_start_ts; //ns + uint64_t m_render_submit_end_ts; //ns + uint64_t m_present_start_ts; //ns + uint64_t m_present_end_ts; //ns + + /** Reserved for future use. */ + uint64_t reserved1; + uint64_t reserved2; + uint64_t reserved3; + uint64_t reserved4; + uint64_t reserved5; +} xell_frame_report_t; +XELL_PACK_E() + +/** + * @brief Get frame stats for debugging purpose. + * @param context: The XeLL context handle. + * @param[out] outdata: Last 64 frames reports. + * @return XeLL return status code. +*/ +XELL_EXPORT xell_result_t xellGetFramesReports(xell_context_handle_t context, xell_frame_report_t* outdata); + + +// Enum size checks. All enums must be 4 bytes +typedef char sizecheck__LINE__[(sizeof(xell_result_t) == 4) ? 1 : -1]; +typedef char sizecheck__LINE__[(sizeof(_xell_latency_marker_type_t) == 4) ? 1 : -1]; + +#ifdef __cplusplus +} +#endif diff --git a/External/External.Libraries/xess/Include/xell/xell_d3d12.h b/External/External.Libraries/xess/Include/xell/xell_d3d12.h new file mode 100644 index 0000000..e9970fe --- /dev/null +++ b/External/External.Libraries/xess/Include/xell/xell_d3d12.h @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (C) 2024 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, and + * your use of them is governed by the express license under which they were + * provided to you ("License"). Unless the License provides otherwise, you may + * not use, modify, copy, publish, distribute, disclose or transmit this + * software or the related documents without Intel's prior written permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + ******************************************************************************/ +#pragma once +#include +#include "xell.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Create the XeLL DX12 context . + * @param[in] device: DX12 device + * @param[out] out_context: Returned XeLL context handle. + * @return XeLL return status code. + */ +XELL_EXPORT xell_result_t xellD3D12CreateContext(ID3D12Device* device, xell_context_handle_t* out_context); + +#ifdef __cplusplus +} +#endif diff --git a/External/External.Libraries/xess/Include/xess/xess.h b/External/External.Libraries/xess/Include/xess/xess.h new file mode 100644 index 0000000..def1596 --- /dev/null +++ b/External/External.Libraries/xess/Include/xess/xess.h @@ -0,0 +1,434 @@ +/******************************************************************************* + * Copyright (C) 2021 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, and + * your use of them is governed by the express license under which they were + * provided to you ("License"). Unless the License provides otherwise, you may + * not use, modify, copy, publish, distribute, disclose or transmit this + * software or the related documents without Intel's prior written permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + ******************************************************************************/ + +#ifndef XESS_H +#define XESS_H + +#ifdef XESS_SHARED_LIB +#ifdef _WIN32 +#ifdef XESS_EXPORT_API +#define XESS_API __declspec(dllexport) +#else +#define XESS_API __declspec(dllimport) +#endif +#else +#define XESS_API __attribute__((visibility("default"))) +#endif +#else +#define XESS_API +#endif + +#if !defined _MSC_VER || (_MSC_VER >= 1929) +#define XESS_PRAGMA(x) _Pragma(#x) +#else +#define XESS_PRAGMA(x) __pragma(x) +#endif +#define XESS_PACK_B_X(x) XESS_PRAGMA(pack(push, x)) +#define XESS_PACK_E() XESS_PRAGMA(pack(pop)) +#define XESS_PACK_B() XESS_PACK_B_X(8) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _xess_context_handle_t* xess_context_handle_t; + +XESS_PACK_B() +/** + * @brief XeSS version. + * + * XeSS uses major.minor.patch version format and Numeric 90+ scheme for development stage builds. + */ +typedef struct _xess_version_t +{ + /** A major version increment indicates a new API and potentially a + * break in functionality. */ + uint16_t major; + /** A minor version increment indicates incremental changes such as + * optional inputs or flags. This does not break existing functionality. */ + uint16_t minor; + /** A patch version increment may include performance or quality tweaks or fixes for known issues. + * There's no change in the interfaces. + * Versions beyond 90 used for development builds to change the interface for the next release. + */ + uint16_t patch; + /** Reserved for future use. */ + uint16_t reserved; +} xess_version_t; +XESS_PACK_E() + +XESS_PACK_B() +/** + * @brief 2D variable. + */ +typedef struct _xess_2d_t +{ + uint32_t x; + uint32_t y; +} xess_2d_t; +XESS_PACK_E() + +/** + * @brief 2D coordinates. + */ +typedef xess_2d_t xess_coord_t; + +/** + * @brief XeSS quality settings. + */ +typedef enum _xess_quality_settings_t +{ + XESS_QUALITY_SETTING_ULTRA_PERFORMANCE = 100, + XESS_QUALITY_SETTING_PERFORMANCE = 101, + XESS_QUALITY_SETTING_BALANCED = 102, + XESS_QUALITY_SETTING_QUALITY = 103, + XESS_QUALITY_SETTING_ULTRA_QUALITY = 104, + XESS_QUALITY_SETTING_ULTRA_QUALITY_PLUS = 105, + XESS_QUALITY_SETTING_AA = 106, +} xess_quality_settings_t; + +/** + * @brief XeSS initialization flags. + */ +typedef enum _xess_init_flags_t +{ + XESS_INIT_FLAG_NONE = 0, + /** Use motion vectors at target resolution. */ + XESS_INIT_FLAG_HIGH_RES_MV = 1 << 0, + /** Use inverted (increased precision) depth encoding */ + XESS_INIT_FLAG_INVERTED_DEPTH = 1 << 1, + /** Use exposure texture to scale input color. */ + XESS_INIT_FLAG_EXPOSURE_SCALE_TEXTURE = 1 << 2, + /** Use responsive pixel mask texture. */ + XESS_INIT_FLAG_RESPONSIVE_PIXEL_MASK = 1 << 3, + /** Use velocity in NDC */ + XESS_INIT_FLAG_USE_NDC_VELOCITY = 1 << 4, + /** Use external descriptor heap */ + XESS_INIT_FLAG_EXTERNAL_DESCRIPTOR_HEAP = 1 << 5, + /** Disable tonemapping for input and output */ + XESS_INIT_FLAG_LDR_INPUT_COLOR = 1 << 6, + /** Remove jitter from input velocity*/ + XESS_INIT_FLAG_JITTERED_MV = 1 << 7, + /** Enable automatic exposure calculation. */ + XESS_INIT_FLAG_ENABLE_AUTOEXPOSURE = 1 << 8 +} xess_init_flags_t; + +XESS_PACK_B() +/** + * @brief Properties for internal XeSS resources. + */ +typedef struct _xess_properties_t +{ + /** Required amount of descriptors for XeSS */ + uint32_t requiredDescriptorCount; + /** The heap size required by XeSS for temporary buffer storage. */ + uint64_t tempBufferHeapSize; + /** The heap size required by XeSS for temporary texture storage. */ + uint64_t tempTextureHeapSize; +} xess_properties_t; +XESS_PACK_E() + +/** + * @brief XeSS return codes. + */ +typedef enum _xess_result_t +{ + /** Warning. Folder to store dump data doesn't exist. Write operation skipped.*/ + XESS_RESULT_WARNING_NONEXISTING_FOLDER = 1, + /** An old or outdated driver. */ + XESS_RESULT_WARNING_OLD_DRIVER = 2, + /** XeSS operation was successful. */ + XESS_RESULT_SUCCESS = 0, + /** XeSS not supported on the GPU. An SM 6.4 capable GPU is required. */ + XESS_RESULT_ERROR_UNSUPPORTED_DEVICE = -1, + /** An unsupported driver. */ + XESS_RESULT_ERROR_UNSUPPORTED_DRIVER = -2, + /** Execute called without initialization. */ + XESS_RESULT_ERROR_UNINITIALIZED = -3, + /** Invalid argument such as descriptor handles. */ + XESS_RESULT_ERROR_INVALID_ARGUMENT = -4, + /** Not enough available GPU memory. */ + XESS_RESULT_ERROR_DEVICE_OUT_OF_MEMORY = -5, + /** Device function such as resource or descriptor creation. */ + XESS_RESULT_ERROR_DEVICE = -6, + /** The function is not implemented */ + XESS_RESULT_ERROR_NOT_IMPLEMENTED = -7, + /** Invalid context. */ + XESS_RESULT_ERROR_INVALID_CONTEXT = -8, + /** Operation not finished yet. */ + XESS_RESULT_ERROR_OPERATION_IN_PROGRESS = -9, + /** Operation not supported in current configuration. */ + XESS_RESULT_ERROR_UNSUPPORTED = -10, + /** The library cannot be loaded. */ + XESS_RESULT_ERROR_CANT_LOAD_LIBRARY = -11, + /** Call to function done in invalid order. */ + XESS_RESULT_ERROR_WRONG_CALL_ORDER = -12, + + /** Unknown internal failure */ + XESS_RESULT_ERROR_UNKNOWN = -1000, +} xess_result_t; + +/** + * @brief XeSS logging level + */ +typedef enum _xess_logging_level_t +{ + XESS_LOGGING_LEVEL_DEBUG = 0, + XESS_LOGGING_LEVEL_INFO = 1, + XESS_LOGGING_LEVEL_WARNING = 2, + XESS_LOGGING_LEVEL_ERROR = 3 +} xess_logging_level_t; + +/** + * A logging callback provided by the application. This callback can be called from other threads. + * Message pointer are only valid inside function and may be invalid right after return call. + * Message is a null-terminated utf-8 string + */ + typedef void (*xess_app_log_callback_t)(const char *message, xess_logging_level_t loggingLevel); + +#ifndef XESS_TYPES_ONLY + +/** @addtogroup xess XeSS API exports + * @{ + */ + +/** + * @brief Gets the XeSS version. This is baked into the XeSS SDK release. + * @param[out] pVersion Returned XeSS version. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetVersion(xess_version_t* pVersion); + +/** + * @brief Gets the version of the loaded Intel XeFX library. When running on Intel platforms + * this function will return the version of the loaded Intel XeFX library, for other + * platforms 0.0.0 will be returned. + * @param hContext The XeSS context handle. + * @param[out] pVersion Returned Intel XeFX library version. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetIntelXeFXVersion(xess_context_handle_t hContext, + xess_version_t* pVersion); + +/** + * @brief Gets XeSS internal resources properties. + * @param hContext The XeSS context handle. + * @param pOutputResolution Output resolution to calculate properties for. + * @param[out] pBindingProperties Returned properties. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetProperties(xess_context_handle_t hContext, + const xess_2d_t* pOutputResolution, xess_properties_t* pBindingProperties); + +/** + * @brief Get the input resolution for a specified output resolution for a given quality setting. + * XeSS expects all the input buffers except motion vectors to be in the returned resolution. + * Motion vectors can be either in output resolution (XESS_INIT_FLAG_HIGH_RES_MV) or + * returned resolution (default). + * + * @param hContext The XeSS context handle. + * @param pOutputResolution Output resolution to calculate input resolution for. + * @param qualitySettings Desired quality setting. + * @param[out] pInputResolution Required input resolution. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetInputResolution(xess_context_handle_t hContext, + const xess_2d_t* pOutputResolution, xess_quality_settings_t qualitySettings, + xess_2d_t* pInputResolution); + +/** + * @brief Get the optimal input resolution and possible range for a specified output resolution for a given quality setting. + * XeSS expects all the input buffers except motion vectors to be in the returned resolution range + * and all input buffers to be in the same resolution. + * Motion vectors can be either in output resolution (XESS_INIT_FLAG_HIGH_RES_MV) or + * in the same resolution as other input buffers (by default). + * + * @note Aspect ratio of the input resolution must be the same as for the output resolution. + * + * @param hContext The XeSS context handle. + * @param pOutputResolution Output resolution to calculate input resolution for. + * @param qualitySettings Desired quality setting. + * @param[out] pInputResolutionOptimal Optimal input resolution. + * @param[out] pInputResolutionMin Required minimal input resolution. + * @param[out] pInputResolutionMax Required maximal input resolution. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetOptimalInputResolution(xess_context_handle_t hContext, + const xess_2d_t* pOutputResolution, xess_quality_settings_t qualitySettings, + xess_2d_t* pInputResolutionOptimal, xess_2d_t* pInputResolutionMin, xess_2d_t* pInputResolutionMax); + +/** + * @brief Gets jitter scale value. + * @param hContext The XeSS context handle. + * @param[out] pX Jitter scale pointer for the X axis. + * @param[out] pY Jitter scale pointer for the Y axis. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetJitterScale(xess_context_handle_t hContext, float* pX, float* pY); + +/** + * @brief Gets velocity scale value. + * @param hContext The XeSS context handle. + * @param[out] pX Velocity scale pointer for the X axis. + * @param[out] pY Velocity scale pointer for the Y axis. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetVelocityScale(xess_context_handle_t hContext, float* pX, float* pY); + +/** + * @brief Destroys the XeSS context. + * The user must ensure that any pending command lists are completed before destroying the context. + * @param hContext: The XeSS context handle. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessDestroyContext(xess_context_handle_t hContext); + +/** + * @brief Sets jitter scale value + * + * @param hContext The XeSS context handle. + * @param x scale for the X axis + * @param y scale for the Y axis + * @return XeSS return status code. + */ +XESS_API xess_result_t xessSetJitterScale(xess_context_handle_t hContext, float x, float y); + +/** + * @brief Sets velocity scale value + * + * @param hContext The XeSS context handle. + * @param x scale for the X axis + * @param y scale for the Y axis + * @return XeSS return status code. + */ +XESS_API xess_result_t xessSetVelocityScale(xess_context_handle_t hContext, float x, float y); + +/** + * @brief Sets exposure scale value + * + * This value will be applied on top of any passed exposure value or automatically calculated exposure. + * + * @param hContext The XeSS context handle. + * @param scale scale value. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessSetExposureMultiplier(xess_context_handle_t hContext, float scale); + +/** + * @brief Gets exposure scale value + * + * @param hContext The XeSS context handle. + * @param[out] pScale Exposure scale pointer. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetExposureMultiplier(xess_context_handle_t hContext, float *pScale); + +/** + * @brief Sets maximum value for responsive mask + * + * This value used to clip responsive mask values. Final responsive mask value calculated as + * clip(responsive_mask, 0.0, max_value). Value must be within range [0.0; 1.0] + * + * @param hContext The XeSS context handle. + * @param value maximum clip value. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessSetMaxResponsiveMaskValue(xess_context_handle_t hContext, float value); + +/** + * @brief Gets maximum value for responsive mask + * + * @param hContext The XeSS context handle. + * @param[out] pValue maximum clip value pointer. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetMaxResponsiveMaskValue(xess_context_handle_t hContext, float *pValue); + +/** + * @brief Sets logging callback + * + * @param hContext The XeSS context handle. + * @param loggingLevel Minimum logging level for logging callback. + * @param loggingCallback Logging callback + * @return XeSS return status code. + */ +XESS_API xess_result_t xessSetLoggingCallback(xess_context_handle_t hContext, + xess_logging_level_t loggingLevel, xess_app_log_callback_t loggingCallback); + +/** + * @brief Indicates if the installed driver supports best XeSS experience. + * + * @param hContext The XeSS context handle. + * @return xessIsOptimalDriver returns XESS_RESULT_SUCCESS, or XESS_RESULT_WARNING_OLD_DRIVER + * if installed driver may result in degraded performance or visual quality. + * xessD3D12CreateContext(..) will return XESS_RESULT_ERROR_UNSUPPORTED_DRIVER if driver does + * not support XeSS at all. + */ +XESS_API xess_result_t xessIsOptimalDriver(xess_context_handle_t hContext); + +/** + * @brief Forces usage of legacy (pre 1.3.0) scale factors + * + * Following scale factors will be applied: + * @li XESS_QUALITY_SETTING_ULTRA_PERFORMANCE: 3.0 + * @li XESS_QUALITY_SETTING_PERFORMANCE: 2.0 + * @li XESS_QUALITY_SETTING_BALANCED: 1.7 + * @li XESS_QUALITY_SETTING_QUALITY: 1.5 + * @li XESS_QUALITY_SETTING_ULTRA_QUALITY: 1.3 + * @li XESS_QUALITY_SETTING_AA: 1.0 + * In order to apply new scale factors application should call xessGetOptimalInputResolution and + * initialization function (xess*Init) + * + * @param hContext The XeSS context handle. + * @param force if set to true legacy scale factors will be forced, if set to false - scale factors + * will be selected by XeSS + * + * @return XeSS return status code. + */ +XESS_API xess_result_t xessForceLegacyScaleFactors(xess_context_handle_t hContext, bool force); + +/** + * @brief Returns current state of pipeline build + * This function can only be called after xess*BuildPipelines and + * before corresponding xess*Init. + * This call returns XESS_RESULT_SUCCESS if pipelines already built, and + * XESS_RESULT_ERROR_OPERATION_IN_PROGRESS if pipline build is in progress. + * If function called before @ref xess*BuildPipelines or after @ref xess*Init - + * XESS_RESULT_ERROR_WRONG_CALL_ORDER will be returned. + * + * @param hContext The XeSS context handle. + * @return XESS_RESULT_SUCCESS if pipelines already built. + * XESS_RESULT_ERROR_OPERATION_IN_PROGRESS if pipeline build are in progress. + * XESS_RESULT_ERROR_WRONG_CALL_ORDER if the function is called out of order. + */ +XESS_API xess_result_t xessGetPipelineBuildStatus(xess_context_handle_t hContext); + +/** @}*/ + +#endif + +// Enum size checks. All enums must be 4 bytes +typedef char sizecheck__LINE__[ (sizeof(xess_quality_settings_t) == 4) ? 1 : -1]; +typedef char sizecheck__LINE__[ (sizeof(xess_init_flags_t) == 4) ? 1 : -1]; +typedef char sizecheck__LINE__[ (sizeof(xess_result_t) == 4) ? 1 : -1]; +typedef char sizecheck__LINE__[ (sizeof(xess_logging_level_t) == 4) ? 1 : -1]; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/External/External.Libraries/xess/Include/xess/xess_d3d11.h b/External/External.Libraries/xess/Include/xess/xess_d3d11.h new file mode 100644 index 0000000..6d4cd9e --- /dev/null +++ b/External/External.Libraries/xess/Include/xess/xess_d3d11.h @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (C) 2024 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, and + * your use of them is governed by the express license under which they were + * provided to you ("License"). Unless the License provides otherwise, you may + * not use, modify, copy, publish, distribute, disclose or transmit this + * software or the related documents without Intel's prior written permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + ******************************************************************************/ + + +#ifndef XESS_DX11_H +#define XESS_DX11_H + +#include + +#include "xess.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @note XeSS D3D11 version only works on Intel Hardware. +*/ + +XESS_PACK_B() +/** + * @brief Execution parameters for XeSS D3D11. + */ +typedef struct _xess_d3d11_execute_params_t +{ + /** Input color texture. */ + ID3D11Resource *pColorTexture; + /** Input motion vector texture. */ + ID3D11Resource *pVelocityTexture; + /** Optional depth texture. Required if XESS_INIT_FLAG_HIGH_RES_MV has not been specified. */ + ID3D11Resource *pDepthTexture; + /** Optional 1x1 exposure scale texture. Required if XESS_INIT_FLAG_EXPOSURE_TEXTURE has been + * specified. */ + ID3D11Resource *pExposureScaleTexture; + /** Optional responsive pixel mask texture. Required if XESS_INIT_FLAG_RESPONSIVE_PIXEL_MASK + * has been specified. */ + ID3D11Resource *pResponsivePixelMaskTexture; + /** Output texture in target resolution. */ + ID3D11Resource *pOutputTexture; + + /** Jitter X coordinate in the range [-0.5, 0.5]. */ + float jitterOffsetX; + /** Jitter Y coordinate in the range [-0.5, 0.5]. */ + float jitterOffsetY; + /** Optional input color scaling. Default is 1. */ + float exposureScale; + /** Resets the history accumulation in this frame. */ + uint32_t resetHistory; + /** Input color width. */ + uint32_t inputWidth; + /** Input color height. */ + uint32_t inputHeight; + /** Base coordinate for the input color in the texture. Default is (0,0). */ + xess_coord_t inputColorBase; + /** Base coordinate for the input motion vector in the texture. Default is (0,0). */ + xess_coord_t inputMotionVectorBase; + /** Base coordinate for the input depth in the texture. Default is (0,0). */ + xess_coord_t inputDepthBase; + /** Base coordinate for the input responsive pixel mask in the texture. Default is (0,0). */ + xess_coord_t inputResponsiveMaskBase; + /** Reserved parameter. */ + xess_coord_t reserved0; + /** Base coordinate for the output color. Default is (0,0). */ + xess_coord_t outputColorBase; +} xess_d3d11_execute_params_t; +XESS_PACK_E() + +XESS_PACK_B() +/** + * @brief Initialization parameters for XeSS VK. + */ +typedef struct _xess_d3d11_init_params_t +{ + /** Output width and height. */ + xess_2d_t outputResolution; + /** Quality setting */ + xess_quality_settings_t qualitySetting; + /** Initialization flags. */ + uint32_t initFlags; +} xess_d3d11_init_params_t; +XESS_PACK_E() + +/** @addtogroup xess-d3d11 XeSS D3D11 API exports + * @{ + */ +/** + * @brief Create an XeSS D3D11 context. + * @param device A D3D11 device created by the user. + * @param[out] phContext Returned xess context handle. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessD3D11CreateContext(ID3D11Device* device, xess_context_handle_t* phContext); + +/** + * @brief Initialize XeSS D3D11. + * This is a blocking call that initializes XeSS and triggers internal + * resources allocation and JIT for the XeSS kernels. The user must ensure that + * any pending command lists are completed before re-initialization. When + * During initialization, XeSS can create staging buffers and copy queues to + * upload internal data. These will be destroyed at the end of initialization. + * + * @param hContext: The XeSS context handle. + * @param pInitParams: Initialization parameters. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessD3D11Init( + xess_context_handle_t hContext, const xess_d3d11_init_params_t* pInitParams); + +/** + * @brief Get XeSS D3D11 initialization parameters. + * + * @note This function will return @ref XESS_RESULT_ERROR_UNINITIALIZED if @ref xessD3D11Init has not been called. + * + * @param hContext: The XeSS context handle. + * @param[out] pInitParams: Returned initialization parameters. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessD3D11GetInitParams( + xess_context_handle_t hContext, xess_d3d11_init_params_t* pInitParams); + +/** + * @brief Record XeSS upscaling commands into the command list. + * @param hContext: The XeSS context handle. + * @param pExecParams: Execution parameters. + * @return XeSS return status code. + */ + +XESS_API xess_result_t xessD3D11Execute( + xess_context_handle_t hContext, const xess_d3d11_execute_params_t* pExecParams); + +/** @}*/ + +#ifdef __cplusplus +} +#endif + + +#endif // XESS_DX11_H diff --git a/External/External.Libraries/xess/Include/xess/xess_d3d12.h b/External/External.Libraries/xess/Include/xess/xess_d3d12.h new file mode 100644 index 0000000..e7cb092 --- /dev/null +++ b/External/External.Libraries/xess/Include/xess/xess_d3d12.h @@ -0,0 +1,193 @@ +/******************************************************************************* + * Copyright (C) 2021 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, and + * your use of them is governed by the express license under which they were + * provided to you ("License"). Unless the License provides otherwise, you may + * not use, modify, copy, publish, distribute, disclose or transmit this + * software or the related documents without Intel's prior written permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + ******************************************************************************/ + + +#ifndef XESS_D3D12_H +#define XESS_D3D12_H + +#include + +#include "xess.h" + +#ifdef __cplusplus +extern "C" { +#endif + +XESS_PACK_B() +/** + * @brief Execution parameters for XeSS D3D12. + */ +typedef struct _xess_d3d12_execute_params_t +{ + /** Input color texture. Must be in NON_PIXEL_SHADER_RESOURCE state.*/ + ID3D12Resource *pColorTexture; + /** Input motion vector texture. Must be in NON_PIXEL_SHADER_RESOURCE state.*/ + ID3D12Resource *pVelocityTexture; + /** Optional depth texture. Required if XESS_INIT_FLAG_HIGH_RES_MV has not been specified. + * Must be in NON_PIXEL_SHADER_RESOURCE state.*/ + ID3D12Resource *pDepthTexture; + /** Optional 1x1 exposure scale texture. Required if XESS_INIT_FLAG_EXPOSURE_TEXTURE has been + * specified. Must be in NON_PIXEL_SHADER_RESOURCE state */ + ID3D12Resource *pExposureScaleTexture; + /** Optional responsive pixel mask texture. Required if XESS_INIT_FLAG_RESPONSIVE_PIXEL_MASK + * has been specified. Must be in NON_PIXEL_SHADER_RESOURCE state */ + ID3D12Resource *pResponsivePixelMaskTexture; + /** Output texture in target resolution. Must be in UNORDERED_ACCESS state.*/ + ID3D12Resource *pOutputTexture; + + /** Jitter X coordinate in the range [-0.5, 0.5]. */ + float jitterOffsetX; + /** Jitter Y coordinate in the range [-0.5, 0.5]. */ + float jitterOffsetY; + /** Optional input color scaling. Default is 1. */ + float exposureScale; + /** Resets the history accumulation in this frame. */ + uint32_t resetHistory; + /** Input color width. */ + uint32_t inputWidth; + /** Input color height. */ + uint32_t inputHeight; + /** Base coordinate for the input color in the texture. Default is (0,0). */ + xess_coord_t inputColorBase; + /** Base coordinate for the input motion vector in the texture. Default is (0,0). */ + xess_coord_t inputMotionVectorBase; + /** Base coordinate for the input depth in the texture. Default is (0,0). */ + xess_coord_t inputDepthBase; + /** Base coordinate for the input responsive pixel mask in the texture. Default is (0,0). */ + xess_coord_t inputResponsiveMaskBase; + /** Reserved parameter. */ + xess_coord_t reserved0; + /** Base coordinate for the output color. Default is (0,0). */ + xess_coord_t outputColorBase; + /** Optional external descriptor heap. */ + ID3D12DescriptorHeap* pDescriptorHeap; + /** Offset in external descriptor heap in bytes.*/ + uint32_t descriptorHeapOffset; +} xess_d3d12_execute_params_t; +XESS_PACK_E() + +XESS_PACK_B() +/** + * @brief Initialization parameters for XeSS D3D12. + */ +typedef struct _xess_d3d12_init_params_t +{ + /** Output width and height. */ + xess_2d_t outputResolution; + /** Quality setting */ + xess_quality_settings_t qualitySetting; + /** Initialization flags. */ + uint32_t initFlags; + /** Specifies the node mask for internally created resources on + * multi-adapter systems. */ + uint32_t creationNodeMask; + /** Specifies the node visibility mask for internally created resources + * on multi-adapter systems. */ + uint32_t visibleNodeMask; + /** Optional externally allocated buffer storage for XeSS. If NULL the + * storage is allocated internally. If allocated, the heap type must be + * D3D12_HEAP_TYPE_DEFAULT. This heap is not accessed by the CPU. */ + ID3D12Heap* pTempBufferHeap; + /** Offset in the externally allocated heap for temporary buffer storage. */ + uint64_t bufferHeapOffset; + /** Optional externally allocated texture storage for XeSS. If NULL the + * storage is allocated internally. If allocated, the heap type must be + * D3D12_HEAP_TYPE_DEFAULT. This heap is not accessed by the CPU. */ + ID3D12Heap* pTempTextureHeap; + /** Offset in the externally allocated heap for temporary texture storage. */ + uint64_t textureHeapOffset; + /** Pointer to pipeline library. If not NULL will be used for pipeline caching. */ + ID3D12PipelineLibrary *pPipelineLibrary; +} xess_d3d12_init_params_t; +XESS_PACK_E() + +/** @addtogroup xess-d3d12 XeSS D3D12 API exports + * @{ + */ +/** + * @brief Create an XeSS D3D12 context. + * @param pDevice: A D3D12 device created by the user. + * @param[out] phContext: Returned xess context handle. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessD3D12CreateContext( + ID3D12Device* pDevice, xess_context_handle_t* phContext); + +/** + * @brief Initiates pipeline build process + * This function can only be called between @ref xessD3D12CreateContext and + * @ref xessD3D12Init + * This call initiates build of DX12 pipelines and kernel compilation + * This call can be blocking (if @p blocking set to true) or non-blocking. + * In case of non-blocking call library will wait for pipeline build on call to + * @ref xessD3D12Init + * If @p pPipelineLibrary passed to this call - same pipeline library must be passed + * to @ref xessD3D12Init + * + * @param hContext The XeSS context handle. + * @param pPipelineLibrary Optional pointer to pipeline library for pipeline caching. + * @param blocking Wait for kernel compilation and pipeline creation to finish or not + * @param initFlags Initialization flags. *Must* be identical to flags passed to @ref xessD3D12Init + */ +XESS_API xess_result_t xessD3D12BuildPipelines(xess_context_handle_t hContext, + ID3D12PipelineLibrary *pPipelineLibrary, bool blocking, uint32_t initFlags); + +/** + * @brief Initialize XeSS D3D12. + * This is a blocking call that initializes XeSS and triggers internal + * resources allocation and JIT for the XeSS kernels. The user must ensure that + * any pending command lists are completed before re-initialization. When + * During initialization, XeSS can create staging buffers and copy queues to + * upload internal data. These will be destroyed at the end of initialization. + * + * @note XeSS supports devices starting from D3D12_RESOURCE_HEAP_TIER_1, which means + * that buffers and textures can not live in the same resource heap. + * + * @param hContext: The XeSS context handle. + * @param pInitParams: Initialization parameters. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessD3D12Init( + xess_context_handle_t hContext, const xess_d3d12_init_params_t* pInitParams); + +/** + * @brief Get XeSS D3D12 initialization parameters. + * + * @note This function will return @ref XESS_RESULT_ERROR_UNINITIALIZED if @ref xessD3D12Init has not been called. + * + * @param hContext: The XeSS context handle. + * @param[out] pInitParams: Returned initialization parameters. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessD3D12GetInitParams( + xess_context_handle_t hContext, xess_d3d12_init_params_t* pInitParams); + +/** + * @brief Record XeSS upscaling commands into the command list. + * @param hContext: The XeSS context handle. + * @param pCommandList: The command list for XeSS commands. + * @param pExecParams: Execution parameters. + * @return XeSS return status code. + */ + +XESS_API xess_result_t xessD3D12Execute(xess_context_handle_t hContext, + ID3D12GraphicsCommandList* pCommandList, const xess_d3d12_execute_params_t* pExecParams); +/** @}*/ + +#ifdef __cplusplus +} +#endif + + +#endif // XESS_D3D12_H diff --git a/External/External.Libraries/xess/Include/xess/xess_d3d12_debug.h b/External/External.Libraries/xess/Include/xess/xess_d3d12_debug.h new file mode 100644 index 0000000..55a7f6a --- /dev/null +++ b/External/External.Libraries/xess/Include/xess/xess_d3d12_debug.h @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (C) 2021 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, and + * your use of them is governed by the express license under which they were + * provided to you ("License"). Unless the License provides otherwise, you may + * not use, modify, copy, publish, distribute, disclose or transmit this + * software or the related documents without Intel's prior written permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + ******************************************************************************/ + + +#ifndef XESS_D3D12_DEBUG_H +#define XESS_D3D12_DEBUG_H + +#include + +#include "xess.h" +#include "xess_debug.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define XESS_D3D12_DEBUG_ENABLE_PROFILING for backwards compatibility with previous XeSS versions*/ +#ifndef XESS_D3D12_DEBUG_ENABLE_PROFILING +#define XESS_D3D12_DEBUG_ENABLE_PROFILING XESS_DEBUG_ENABLE_PROFILING +#endif + +XESS_PACK_B() +typedef struct _xess_resources_to_dump_t +{ + /** Total resource count. In case it equal to zero content of other structure members is undefined.*/ + uint32_t resource_count; + /** Pointer to an internal array of D3D12 resources. Array length is `resource_count`.*/ + ID3D12Resource* const* resources; + /** Pointer to an internal array of D3D12 resource names. Array length is `resource_count`.*/ + const char* const* resource_names; + /* Pointer to an internal array of suggested resource dump modes. Array length is `resource_count.` + * If as_tensor is 0 (FALSE), then it is suggested to dump resource as RGBA texture.*/ + const uint32_t* as_tensor; // 0 = false + /* Pointer to an internal array of paddings to be used during resource dump. Array length is `resource_count`. + * Padding is assumed to be symmetrical across spatial dimensions and has same value for both borders in each dimension.*/ + const uint32_t* border_pixels_to_skip_count; + /* Pointer to an internal array of channel count for each resource. If resource dimension is "buffer" value is non zero, + * count is zero otherwise. Array length is `resource_count`.*/ + const uint32_t* tensor_channel_count; + /* Pointer to an internal array of tensor width for each resource. Width must include padding on both sides. + * If resource dimension is "buffer" value is non zero, * count is zero otherwise. Array length is `resource_count`.*/ + const uint32_t* tensor_width; + /* Pointer to an internal array of tensor width for each resource. Height must include padding on both sides. + * If resource dimension is "buffer" value is non zero, * count is zero otherwise. Array length is `resource_count`.*/ + const uint32_t* tensor_height; +} xess_resources_to_dump_t; +XESS_PACK_E() + +/** @addtogroup xess-d3d12-debug XeSS D3D12 API debug exports + * @{ + */ +/** + * @brief Query XeSS model to retrieve internal resources marked for dumping for further + * debug and inspection. + * @param hContext: The XeSS context handle. + * @param pResourcesToDump: Pointer to user-provided pointer to structure to be filled with + * debug resource array, their names and recommended dumping parameters. pResourcesToDump must not be null, + * In case of failure (xess_result_t is not equal to XESS_RESULT_SUCCESS) **pResourcesToDump contents is undefined and must not be used. + * In case of success, *pResourcesToDump may still be null, if no internal resources were added to dumping queue. + * Build configuration for certain implementations may have dumping functionality compiled-out and XESS_RESULT_ERROR_NOT_IMPLEMENTED return code. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessD3D12GetResourcesToDump(xess_context_handle_t hContext, xess_resources_to_dump_t** pResourcesToDump); + +/** + * @brief Query XeSS model performance data for past executions. + * This function is provided for backwards compatibility with previous XeSS versions and + * and it's currently deprecated. Same functionality is provided by xessGetProfilingData + * function from xess_debug.h. To enable performance collection, + * context must be initialized with XESS_DEBUG_ENABLE_PROFILING flag added to xess_d3d12_init_params_t::initFlags. + * If profiling is enabled, user must poll for profiling data after executing one or more command lists, otherwise + * implementation will keep growing internal CPU buffers to accommodate all profiling data available. + * Due to async nature of execution on GPU, data may not be available after submitting command lists to device queue. + * It is advised to check `any_profiling_data_in_flight` flag in case all workloads has been submitted, but profiling + * data for some frames is still not available. + * Data pointed to by pProfilingData item(s) belongs to context instance and + * is valid until next call to xessD3D12GetProfilingData or xessGetProfilingData for owning context. + * @param hContext: The XeSS context handle. + * @param pProfilingData: pointer to profiling data structure to be filled by implementation. + * @return XeSS return status code. +*/ +XESS_API xess_result_t xessD3D12GetProfilingData(xess_context_handle_t hContext, xess_profiling_data_t** pProfilingData); + + +/** @}*/ + +#ifdef __cplusplus +} +#endif + + +#endif // XESS_D3D12_H diff --git a/External/External.Libraries/xess/Include/xess/xess_debug.h b/External/External.Libraries/xess/Include/xess/xess_debug.h new file mode 100644 index 0000000..e147fc0 --- /dev/null +++ b/External/External.Libraries/xess/Include/xess/xess_debug.h @@ -0,0 +1,179 @@ +/******************************************************************************* + * Copyright (C) 2021 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, and + * your use of them is governed by the express license under which they were + * provided to you ("License"). Unless the License provides otherwise, you may + * not use, modify, copy, publish, distribute, disclose or transmit this + * software or the related documents without Intel's prior written permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + ******************************************************************************/ + + +#ifndef XESS_DEBUG_H +#define XESS_DEBUG_H + +#include "xess.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef XESS_DEBUG_ENABLE_PROFILING +#define XESS_DEBUG_ENABLE_PROFILING (1U << 30) +#endif + +/** + * @brief XeSS network type. + */ +typedef enum _xess_network_model_t +{ + XESS_NETWORK_MODEL_KPSS = 0, + XESS_NETWORK_MODEL_SPLAT = 1, + XESS_NETWORK_MODEL_3 = 2, + XESS_NETWORK_MODEL_4 = 3, + XESS_NETWORK_MODEL_5 = 4, + XESS_NETWORK_MODEL_6 = 5, + XESS_NETWORK_MODEL_UNKNOWN = 0x7FFFFFFF, +} xess_network_model_t; + +typedef enum _xess_dump_element_bits_t +{ + XESS_DUMP_INPUT_COLOR = 0x01, + XESS_DUMP_INPUT_VELOCITY = 0x02, + XESS_DUMP_INPUT_DEPTH = 0x04, + XESS_DUMP_INPUT_EXPOSURE_SCALE = 0x08, + XESS_DUMP_INPUT_RESPONSIVE_PIXEL_MASK = 0x10, + XESS_DUMP_OUTPUT = 0x20, + XESS_DUMP_HISTORY = 0x40, + XESS_DUMP_EXECUTION_PARAMETERS = 0x80, ///< All parameters passed to xessExecute + XESS_DUMP_ALL_INPUTS = XESS_DUMP_INPUT_COLOR | XESS_DUMP_INPUT_VELOCITY | + XESS_DUMP_INPUT_DEPTH | XESS_DUMP_INPUT_EXPOSURE_SCALE | + XESS_DUMP_INPUT_RESPONSIVE_PIXEL_MASK | XESS_DUMP_EXECUTION_PARAMETERS, + XESS_DUMP_ALL = 0x7FFFFFFF, +} xess_dump_element_bits_t; + +typedef uint32_t xess_dump_elements_mask_t; + +XESS_PACK_B() +typedef struct _xess_dump_parameters_t +{ + /** + * NULL-terminated ASCII string to *existing folder* where dump files should be written. + * Library do not create the folder. + * Files in provided folder will be overwritten. + */ + const char *path; + /** Frame index. Will be used as start for frame sequence. */ + uint32_t frame_idx; + /** Frame count to dump. Few frames less may be dumped due to possible frames in flight in + * application + */ + uint32_t frame_count; + /** Bitset showing set of elements that must be dumped. Element will be dumped if it exists + * and corresponding bit is not 0. + * Since it's meaningless to call Dump with empty set value of 0 will mean DUMP_ALL_INPUTS + */ + xess_dump_elements_mask_t dump_elements_mask; + /** In case of depth render target with TYPELESS format it is not always possible + * to interpret depth values during dumping process. + */ +} xess_dump_parameters_t; +XESS_PACK_E() + +XESS_PACK_B() +typedef struct _xess_profiled_frame_data_t +{ + /** Execution index in context's instance. */ + uint64_t frame_index; + /** Total labeled gpu duration records stored in gpu_duration* arrays.*/ + uint64_t gpu_duration_record_count; + /** Pointer to an internal array of duration names.*/ + const char* const* gpu_duration_names; + /** Pointer to an internal array of duration values. [seconds]*/ + const double* gpu_duration_values; +} xess_profiled_frame_data_t; +XESS_PACK_E() + +XESS_PACK_B() +typedef struct _xess_profiling_data_t +{ + /** Total profiled frame records storage in frames/executions array.*/ + uint64_t frame_count; + /** Pointers to an internal storage with per frame/execution data.*/ + xess_profiled_frame_data_t* frames; + /** Flag indicating if more profiling data will be available when GPU finishes + * executing submitted frames. + * Useful to collect profiling data without forcing full CPU-GPU sync. + * Zero value indicates no pending profiling data. + */ + uint32_t any_profiling_data_in_flight; +} xess_profiling_data_t; +XESS_PACK_E() + +/** @addtogroup xess-debug XeSS API debug exports + * @{ + */ + +/** + * @brief Select network to be used by XeSS + * + * Selects network model to use by XeSS. + * After call to this function - XeSS init function *must* be called + */ +XESS_API xess_result_t xessSelectNetworkModel(xess_context_handle_t hContext, xess_network_model_t network); + +/** + * @brief Dumps sequence of frames to the provided folder + * + * Call to this function initiates a dump for selected elements. + * XeSS SDK uses RAM cache to reduce dump overhead. Application should provide reasonable + * value for @ref xess_dump_parameters_t::frame_count frames (about 50 megs needed per cached frame). + * To enable several dumps per run application should provide correct + * @ref xess_dump_parameters_t::frame_idx value. This value used as a start index for frame + * dumping. + * After call to this function - each call to @ref xessD3D12Execute will result in new frame dumped to + * RAM cache. + * After @ref xess_dump_parameters_t::frame_count frames application will be blocked on call to + * @ref xessD3D12Execute in order to save cached frames to disk. This operation can take long time. + * Repetitive calls to this function can result in XESS_RESULT_ERROR_OPERATION_IN_PROGRESS which means that + * frame dump is in progress. + * + * @param hContext XeSS context + * @param dump_parameters dump configuration + * @return operation status + */ +XESS_API xess_result_t xessStartDump(xess_context_handle_t hContext, const xess_dump_parameters_t *dump_parameters); + + +/** + * @brief Query XeSS model performance data for past executions. To enable performance collection, + * context must be initialized with XESS_DEBUG_ENABLE_PROFILING flag added to xess_d3d12_init_params_t::initFlags + * or xess_vk_init_params_t::initFlags. + * If profiling is enabled, user must poll for profiling data after executing one or more command lists, otherwise + * implementation will keep growing internal CPU buffers to accommodate all profiling data available. + * Due to async nature of execution on GPU, data may not be available after submitting command lists to device queue. + * It is advised to check `any_profiling_data_in_flight` flag in case all workloads has been submitted, but profiling + * data for some frames is still not available. + * Data pointed to by pProfilingData item(s) belongs to context instance and + * is valid until next call to xessD3D12GetProfilingData or xessGetProfilingData for owning context. + * @param hContext: The XeSS context handle. + * @param pProfilingData: pointer to profiling data structure to be filled by implementation. + * @return XeSS return status code. +*/ +XESS_API xess_result_t xessGetProfilingData(xess_context_handle_t hContext, xess_profiling_data_t** pProfilingData); + +/** @}*/ + +// Enum size checks. All enums must be 4 bytes +typedef char sizecheck__LINE__[ (sizeof(xess_network_model_t) == 4) ? 1 : -1]; +typedef char sizecheck__LINE__[ (sizeof(xess_dump_element_bits_t) == 4) ? 1 : -1]; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/External/External.Libraries/xess/Include/xess/xess_vk.h b/External/External.Libraries/xess/Include/xess/xess_vk.h new file mode 100644 index 0000000..5285ed8 --- /dev/null +++ b/External/External.Libraries/xess/Include/xess/xess_vk.h @@ -0,0 +1,262 @@ +/******************************************************************************* + * Copyright (C) 2023 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, and + * your use of them is governed by the express license under which they were + * provided to you ("License"). Unless the License provides otherwise, you may + * not use, modify, copy, publish, distribute, disclose or transmit this + * software or the related documents without Intel's prior written permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + ******************************************************************************/ + + +#ifndef XESS_VK_H +#define XESS_VK_H + +#include + +#include "xess.h" + +#ifdef __cplusplus +extern "C" { +#endif + +XESS_PACK_B() + +typedef struct _xess_vk_image_view_info +{ + VkImageView imageView; + VkImage image; + VkImageSubresourceRange subresourceRange; + VkFormat format; + unsigned int width; + unsigned int height; +} xess_vk_image_view_info; + +XESS_PACK_E() + +XESS_PACK_B() +/** + * @brief Execution parameters for XeSS Vulkan. + */ +typedef struct _xess_vk_execute_params_t +{ + /** Input color texture. Must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL state.*/ + xess_vk_image_view_info colorTexture; + /** Input motion vector texture. Must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL state.*/ + xess_vk_image_view_info velocityTexture; + /** Optional depth texture. Required if XESS_INIT_FLAG_HIGH_RES_MV has not been specified. + * Must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL state.*/ + xess_vk_image_view_info depthTexture; + /** Optional 1x1 exposure scale texture. Required if XESS_INIT_FLAG_EXPOSURE_TEXTURE has been + * specified. Must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL state */ + xess_vk_image_view_info exposureScaleTexture; + /** Optional responsive pixel mask texture. Required if XESS_INIT_FLAG_RESPONSIVE_PIXEL_MASK + * has been specified. Must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL state */ + xess_vk_image_view_info responsivePixelMaskTexture; + /** Output texture in target resolution. Must be in VK_IMAGE_LAYOUT_GENERAL state.*/ + xess_vk_image_view_info outputTexture; + + /** Jitter X coordinate in the range [-0.5, 0.5]. */ + float jitterOffsetX; + /** Jitter Y coordinate in the range [-0.5, 0.5]. */ + float jitterOffsetY; + /** Optional input color scaling. Default is 1. */ + float exposureScale; + /** Resets the history accumulation in this frame. */ + uint32_t resetHistory; + /** Input color width. */ + uint32_t inputWidth; + /** Input color height. */ + uint32_t inputHeight; + /** Base coordinate for the input color in the texture. Default is (0,0). */ + xess_coord_t inputColorBase; + /** Base coordinate for the input motion vector in the texture. Default is (0,0). */ + xess_coord_t inputMotionVectorBase; + /** Base coordinate for the input depth in the texture. Default is (0,0). */ + xess_coord_t inputDepthBase; + /** Base coordinate for the input responsive pixel mask in the texture. Default is (0,0). */ + xess_coord_t inputResponsiveMaskBase; + /** Reserved parameter. */ + xess_coord_t reserved0; + /** Base coordinate for the output color. Default is (0,0). */ + xess_coord_t outputColorBase; +} xess_vk_execute_params_t; +XESS_PACK_E() + +XESS_PACK_B() +/** + * @brief Initialization parameters for XeSS VK. + */ +typedef struct _xess_vk_init_params_t +{ + /** Output width and height. */ + xess_2d_t outputResolution; + /** Quality setting */ + xess_quality_settings_t qualitySetting; + /** Initialization flags. */ + uint32_t initFlags; + /** Specifies the node mask for internally created resources on + * multi-adapter systems. */ + uint32_t creationNodeMask; + /** Specifies the node visibility mask for internally created resources + * on multi-adapter systems. */ + uint32_t visibleNodeMask; + /** Optional externally allocated buffer memory for XeSS. If VK_NULL_HANDLE the + * memory is allocated internally. If provided, the memory must be allocated from + * memory type that supports allocating buffers. The memory type should be DEVICE_LOCAL. + * This memory is not accessed by the CPU. */ + VkDeviceMemory tempBufferHeap; + /** Offset in the externally allocated memory for temporary buffer storage. */ + uint64_t bufferHeapOffset; + /** Optional externally allocated texture memory for XeSS. If VK_NULL_HANDLE the + * memory is allocated internally. If provided, the memory must be allocated from + * memory type that supports allocating textures. The memory type should be DEVICE_LOCAL. + * This memory is not accessed by the CPU. */ + VkDeviceMemory tempTextureHeap; + /** Offset in the externally allocated memory for temporary texture storage. */ + uint64_t textureHeapOffset; + /** Optional pipeline cache. If not VK_NULL_HANDLE will be used for pipeline creation. */ + VkPipelineCache pipelineCache; +} xess_vk_init_params_t; +XESS_PACK_E() + +/** @addtogroup xess-vulkan XeSS VK API exports + * @{ + */ + /** + * @brief Get required extensions for Vulkan instance that would run XeSS. + * This function must be called to get instance extensions need by XeSS. These + * extensions must be enabled in subsequent vkCreateInstance call, that would create a VkInstance + * object to be passed to @ref xessVKCreateContext + * @param[out] instanceExtensionsCount returns a count of instance extensions to be enabled in Vulkan instance + * @param[out] instanceExtensions returns a pointer to an array of \p instanceExtensionsCount required extension names. + * The memory used by the array is owned by the XeSS library and should not be freed by the application. + * @param[out] minVkApiVersion The Vulkan API version that XeSS would use. When calling vkCreateInstance, the application + * should set VkApplicationInfo.apiVersion to value greater or equal to \p minVkApiVersion + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKGetRequiredInstanceExtensions(uint32_t* instanceExtensionsCount, const char* const** instanceExtensions, uint32_t* minVkApiVersion); + + + /** + * @brief Get required extensions for Vulkan device that would run XeSS. + * This function must be called to get device extensions need by XeSS. These + * extensions must be enabled in subsequent vkCreateDevice call, that would create a VkDevice + * object to be passed to @ref xessVKCreateContext + * @param instance A VkInstance object created by the user + * @param physicalDevice A VkPhysicalDevice selected by the user from instance + * @param[out] deviceExtensionsCount returns a count of device extensions to be enabled in Vulkan device + * @param[out] deviceExtensions returns a pointer to an array of \p deviceExtensionsCount required extension names + * The memory used by the array is owned by the XeSS library and should not be freed by the application. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKGetRequiredDeviceExtensions(VkInstance instance, VkPhysicalDevice physicalDevice, + uint32_t* deviceExtensionsCount, const char* const** deviceExtensions); + + + /** + * @brief Get required features for Vulkan device that would run XeSS. + * This function must be called to get device features need by XeSS. These + * features must be enabled in subsequent vkCreateDevice call, that would create a VkDevice + * object to be passed to @ref xessVKCreateContext. + * @param instance A VkInstance object created by the user + * @param physicalDevice A VkPhysicalDevice selected by the user from instance + * @param[out] features a pointer to writable chain of feature structures, that this function would patch + * with required features, by filling required fields and attaching new structures to the chain if needed. + * The returned pointer should be passed to vkCreateDevice as pNext chain of VkDeviceCreateInfo structure. + * If null is passed, than the function constructs a new structure chain that should be merged + * into the chain that application would use with VkDeviceCreateInfo, with application responsibility to + * avoid any duplicates with its own structures. + * + * It is an error to chain VkDeviceCreateInfo structure with not null pEnabledFeatures field, as this field is const + * and cannot be patched by this function. VkPhysicalDeviceFeatures2 structure should be used instead. + * + * The memory used by the structures added by this funtion to the chain is owned by the XeSS library and + * should not be freed by the application. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKGetRequiredDeviceFeatures(VkInstance instance, VkPhysicalDevice physicalDevice, void** features); + + +/** + * @brief Create an XeSS VK context. + * @param instance A VkInstance object created by the user + * @param physicalDevice A VkPhysicalDevice selected by the user from instance + * @param device A VK device created by the user from physicalDevice + * @param[out] phContext Returned xess context handle. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKCreateContext(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, + xess_context_handle_t* phContext); + +/** + * @brief Initiates pipeline build process + * This function can only be called between @ref xessVKCreateContext and + * @ref xessVKInit + * This call initiates build of Vulkan pipelines and kernel compilation + * This call can be blocking (if @p blocking set to true) or non-blocking. + * In case of non-blocking call library will wait for pipeline build on call to + * @ref xessVKInit + * If @p pipelineCache passed to this call - same pipeline library must be passed + * to @ref xessVKInit + * + * @param hContext The XeSS context handle. + * @param pipelineCache Optional pointer to pipeline library for pipeline caching. + * @param blocking Wait for kernel compilation and pipeline creation to finish or not + * @param initFlags Initialization flags. *Must* be identical to flags passed to @ref xessVKInit + */ +XESS_API xess_result_t xessVKBuildPipelines(xess_context_handle_t hContext, + VkPipelineCache pipelineCache, bool blocking, uint32_t initFlags); + +/** + * @brief Initialize XeSS VK. + * This is a blocking call that initializes XeSS and triggers internal + * resources allocation and JIT for the XeSS kernels. The user must ensure that + * any pending command lists are completed before re-initialization. When + * During initialization, XeSS can create staging buffers and copy queues to + * upload internal data. These will be destroyed at the end of initialization. + * + * @note XeSS supports devices starting from VK_RESOURCE_HEAP_TIER_1, which means + * that buffers and textures can not live in the same resource heap. + * + * @param hContext: The XeSS context handle. + * @param pInitParams: Initialization parameters. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKInit( + xess_context_handle_t hContext, const xess_vk_init_params_t* pInitParams); + +/** + * @brief Get XeSS VK initialization parameters. + * + * @note This function will return @ref XESS_RESULT_ERROR_UNINITIALIZED if @ref xessVKInit has not been called. + * + * @param hContext: The XeSS context handle. + * @param[out] pInitParams: Returned initialization parameters. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKGetInitParams( + xess_context_handle_t hContext, xess_vk_init_params_t* pInitParams); + +/** + * @brief Record XeSS upscaling commands into the command list. + * @param hContext: The XeSS context handle. + * @param commandBuffer: The command bufgfer for XeSS commands. + * @param pExecParams: Execution parameters. + * @return XeSS return status code. + */ + +XESS_API xess_result_t xessVKExecute(xess_context_handle_t hContext, + VkCommandBuffer commandBuffer, const xess_vk_execute_params_t* pExecParams); +/** @}*/ + +#ifdef __cplusplus +} +#endif + + +#endif // XESS_VK_H diff --git a/External/External.Libraries/xess/Include/xess/xess_vk_debug.h b/External/External.Libraries/xess/Include/xess/xess_vk_debug.h new file mode 100644 index 0000000..fcd7cff --- /dev/null +++ b/External/External.Libraries/xess/Include/xess/xess_vk_debug.h @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (C) 2021 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, and + * your use of them is governed by the express license under which they were + * provided to you ("License"). Unless the License provides otherwise, you may + * not use, modify, copy, publish, distribute, disclose or transmit this + * software or the related documents without Intel's prior written permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + ******************************************************************************/ + + +#ifndef XESS_VK_DEBUG_H +#define XESS_VK_DEBUG_H + +#include "xess_vk.h" +#include "xess_debug.h" + +#ifdef __cplusplus +extern "C" { +#endif + +XESS_PACK_B() +typedef struct _xess_vk_resource_to_dump_desc_t +{ + VkImage image; + VkBuffer buffer; + VkFormat image_format; + uint64_t width; + uint32_t height; + VkImageLayout image_layout; + uint32_t image_array_size; + uint32_t image_depth; +} xess_vk_resource_to_dump_desc_t; +XESS_PACK_E() + +XESS_PACK_B() +typedef struct _xess_vk_resources_to_dump_t +{ + /** Total resource count. In case it equal to zero content of other structure members is undefined.*/ + uint32_t resource_count; + /** Pointer to an internal array of Vulkan resource descriptions (VkImage or VkBuffer). Array length is `resource_count`.*/ + _xess_vk_resource_to_dump_desc_t const* resources; + /** Pointer to an internal array of Vulkan resource names. Array length is `resource_count`.*/ + const char* const* resource_names; + /* Pointer to an internal array of suggested resource dump modes. Array length is `resource_count.` + * If as_tensor is 0 (FALSE), then it is suggested to dump resource as RGBA texture.*/ + const uint32_t* as_tensor; // 0 = false + /* Pointer to an internal array of paddings to be used during resource dump. Array length is `resource_count`. + * Padding is assumed to be symmetrical across spatial dimensions and has same value for both borders in each dimension.*/ + const uint32_t* border_pixels_to_skip_count; + /* Pointer to an internal array of channel count for each resource. If resource dimension is "buffer" value is non zero, + * count is zero otherwise. Array length is `resource_count`.*/ + const uint32_t* tensor_channel_count; + /* Pointer to an internal array of tensor width for each resource. Width must include padding on both sides. + * If resource dimension is "buffer" value is non zero, * count is zero otherwise. Array length is `resource_count`.*/ + const uint32_t* tensor_width; + /* Pointer to an internal array of tensor width for each resource. Height must include padding on both sides. + * If resource dimension is "buffer" value is non zero, * count is zero otherwise. Array length is `resource_count`.*/ + const uint32_t* tensor_height; +} xess_vk_resources_to_dump_t; +XESS_PACK_E() + +/** @addtogroup xess-vk-debug XeSS Vulkan API debug exports + * @{ + */ +/** + * @brief Query XeSS model to retrieve internal resources marked for dumping for further + * debug and inspection. + * @param hContext: The XeSS context handle. + * @param pResourcesToDump: Pointer to user-provided pointer to structure to be filled with + * debug resource array, their names and recommended dumping parameters. pResourcesToDump must not be null, + * In case of failure (xess_result_t is not equal to XESS_RESULT_SUCCESS) **pResourcesToDump contents is undefined and must not be used. + * In case of success, *pResourcesToDump may still be null, if no internal resources were added to dumping queue. + * Build configuration for certain implementations may have dumping functionality compiled-out and XESS_RESULT_ERROR_NOT_IMPLEMENTED return code. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKGetResourcesToDump(xess_context_handle_t hContext, xess_vk_resources_to_dump_t** pResourcesToDump); + +/** @}*/ + +#ifdef __cplusplus +} +#endif + + +#endif // XESS_VK_DEBUG_H diff --git a/External/External.Libraries/xess/Include/xess_fg/xefg_swapchain.h b/External/External.Libraries/xess/Include/xess_fg/xefg_swapchain.h new file mode 100644 index 0000000..0a6eb2f --- /dev/null +++ b/External/External.Libraries/xess/Include/xess_fg/xefg_swapchain.h @@ -0,0 +1,528 @@ +/******************************************************************************* + * Copyright (C) 2024 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, and + * your use of them is governed by the express license under which they were + * provided to you ("License"). Unless the License provides otherwise, you may + * not use, modify, copy, publish, distribute, disclose or transmit this + * software or the related documents without Intel's prior written permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + ******************************************************************************/ + +#ifndef XEFG_SWAPCHAIN_H +#define XEFG_SWAPCHAIN_H + +#ifdef _WIN32 + #ifdef XEFG_SWAPCHAIN_EXPORT_API + #define XEFG_SWAPCHAIN_API __declspec(dllexport) + #else + #define XEFG_SWAPCHAIN_API + #endif +#else + #define XEFG_SWAPCHAIN_API __attribute__((visibility("default"))) +#endif + +#if !defined _MSC_VER || (_MSC_VER >= 1929) +#define XEFG_SWAPCHAIN_PRAGMA(x) _Pragma(#x) +#else +#define XEFG_SWAPCHAIN_PRAGMA(x) __pragma(x) +#endif +#define XEFG_SWAPCHAIN_PACK_B_X(x) XEFG_SWAPCHAIN_PRAGMA(pack(push, x)) +#define XEFG_SWAPCHAIN_PACK_E() XEFG_SWAPCHAIN_PRAGMA(pack(pop)) +#define XEFG_SWAPCHAIN_PACK_B() XEFG_SWAPCHAIN_PACK_B_X(8) + +#define XEFG_SWAPCHAIN_CAT_IMPL(a,b) a##b +#define XEFG_SWAPCHAIN_CAT(a,b) XEFG_SWAPCHAIN_CAT_IMPL(a,b) +#define XEFG_SWAPCHAIN_STATIC_ASSERT(cond)\ + typedef int XEFG_SWAPCHAIN_CAT(XEFG_SWAPCHAIN_STATIC_ASSERT_IMPL, __COUNTER__)[(cond) ? 1 : -1] + +#include +#include + +/** + * @brief Use maximum supported number of interpolated frames. + * + * Use this constant during XeSS-FG swap chain initialization to set number + * of interpolated frames to the maximum supported value. + * + * The actual value can be queried later using @ref xefgSwapChainGetProperties + * or by retrieving back the initialization parameters. + * + * @see @ref xefgswapchain-d3d12 + */ +#define XEFG_SWAPCHAIN_USE_MAX_SUPPORTED_INTERPOLATED_FRAMES UINT32_MAX + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _xefg_swapchain_handle_t* xefg_swapchain_handle_t; + +/** +* @brief Informs the library about the lifetime of the +* resource being provided. The library will take appropriate action based +* on this value to either make a copy of the resource or store a reference +* to it. +*/ +typedef enum _xefg_swapchain_resource_validity_t +{ + /** Resource is valid until the next present. */ + XEFG_SWAPCHAIN_RV_UNTIL_NEXT_PRESENT = 0, + /** Resource is only valid now. */ + XEFG_SWAPCHAIN_RV_ONLY_NOW, + XEFG_SWAPCHAIN_RV_COUNT +} xefg_swapchain_resource_validity_t; + +/** + * @brief XeSS-FG Swap Chain initialization flags. + */ +typedef enum _xefg_swapchain_init_flags_t +{ + /** No flags are enabled. */ + XEFG_SWAPCHAIN_INIT_FLAG_NONE = 0, + /** Use inverted (increased precision) depth encoding. */ + XEFG_SWAPCHAIN_INIT_FLAG_INVERTED_DEPTH = 1 << 0, + /** Use external descriptor heap. */ + XEFG_SWAPCHAIN_INIT_FLAG_EXTERNAL_DESCRIPTOR_HEAP = 1 << 1, + /** Deprecated. Setting this flag has no effect. */ + XEFG_SWAPCHAIN_INIT_FLAG_HIGH_RES_MV = 1 << 2, + /** Use velocity in normalized device coordinates (NDC). */ + XEFG_SWAPCHAIN_INIT_FLAG_USE_NDC_VELOCITY = 1 << 3, + /** Remove jitter from input velocity. */ + XEFG_SWAPCHAIN_INIT_FLAG_JITTERED_MV = 1 << 4, + /** UI texture rgb values are not premultiplied by its alpha value */ + XEFG_SWAPCHAIN_INIT_FLAG_UITEXTURE_NOT_PREMUL_ALPHA = 1 << 5 +} xefg_swapchain_init_flags_t; + +/** + * @brief XeSS-FG Swap Chain resources type. + */ +typedef enum _xefg_swapchain_resource_type_t +{ + XEFG_SWAPCHAIN_RES_HUDLESS_COLOR = 0, + XEFG_SWAPCHAIN_RES_DEPTH, + XEFG_SWAPCHAIN_RES_MOTION_VECTOR, + XEFG_SWAPCHAIN_RES_UI, + XEFG_SWAPCHAIN_RES_BACKBUFFER, + XEFG_SWAPCHAIN_RES_COUNT +} xefg_swapchain_resource_type_t; + +XEFG_SWAPCHAIN_PACK_B() +/** +* @brief XeSS-FG Swap Chain version. +* +* XeSS-FG Swap Chain uses major.minor.patch version format and Numeric 90+ scheme for development stage builds. +*/ +typedef struct _xefg_swapchain_version_t +{ + /** A major version increment indicates a new API and potentially a + * break in functionality. */ + uint16_t major; + /** A minor version increment indicates incremental changes such as + * optional inputs or flags. This does not break existing functionality. */ + uint16_t minor; + /** A patch version increment may include performance or quality tweaks or fixes for known issues. + * There's no change in the interfaces. + * Versions beyond 90 are used for development builds to change the interface for the next release. + */ + uint16_t patch; + /** Reserved for future use. */ + uint16_t reserved; +} xefg_swapchain_version_t; +XEFG_SWAPCHAIN_PACK_E() + +XEFG_SWAPCHAIN_PACK_B() +/** + * @brief 2D variable. + */ +typedef struct _xefg_swapchain_2d_t +{ + uint32_t x; + uint32_t y; +} xefg_swapchain_2d_t; +XEFG_SWAPCHAIN_PACK_E() + +XEFG_SWAPCHAIN_PACK_B() +/** + * @brief Contains all constants associated with a frame. + */ +typedef struct _xefg_swapchain_frame_constant_data_t +{ + /** float4x4, row-major convention. */ + float viewMatrix[16]; + /** float4x4, row-major convention. */ + float projectionMatrix[16]; + /** Jitter X coordinate in the range [-0.5, 0.5]. */ + float jitterOffsetX; + /** Jitter Y coordinate in the range [-0.5, 0.5]. */ + float jitterOffsetY; + /** Scale for motion vectors for X coordinate. */ + float motionVectorScaleX; + /** Scale for motion vectors for Y coordinate. */ + float motionVectorScaleY; + /** Tells Interpolation library to reset history. */ + uint32_t resetHistory; + /** Time that was required to render current frame in milliseconds. */ + float frameRenderTime; +} xefg_swapchain_frame_constant_data_t; +XEFG_SWAPCHAIN_PACK_E() + +XEFG_SWAPCHAIN_PACK_B() +/** +* @brief Properties for internal XeSS-FG Swap Chain resources. +*/ +typedef struct _xefg_swapchain_properties_t +{ + /** Required amount of descriptors for XeSS-FG Swap Chain. */ + uint32_t requiredDescriptorCount; + /** The heap size required by XeSS-FG Swap Chain for temporary buffer storage. */ + uint64_t tempBufferHeapSize; + /** The heap size required by XeSS-FG Swap Chain for temporary texture storage. */ + uint64_t tempTextureHeapSize; + /** The size required by XeSS-FG Swap Chain in a constant buffer for temporary storage. */ + uint64_t constantBufferSize; + /** Maximum number of supported interpolations. */ + uint32_t maxSupportedInterpolations; +} xefg_swapchain_properties_t; +XEFG_SWAPCHAIN_PACK_E() + +/** + * @brief XeSS-FG Swap Chain return codes. + */ +typedef enum _xefg_swapchain_result_t +{ + /** An old or outdated driver. */ + XEFG_SWAPCHAIN_RESULT_WARNING_OLD_DRIVER = 2, + /** Warning. Frame ID should be over 0. */ + XEFG_SWAPCHAIN_RESULT_WARNING_TOO_FEW_FRAMES = 3, + /** Warning. Data for interpolation came in wrong order. */ + XEFG_SWAPCHAIN_RESULT_WARNING_FRAMES_ID_MISMATCH = 4, + /** Warning. There is no present status for last present. */ + XEFG_SWAPCHAIN_RESULT_WARNING_MISSING_PRESENT_STATUS = 5, + /** Warning. Resource sizes for the interpolation doesn't match between previous and next frames. + Interpolation skipped. */ + XEFG_SWAPCHAIN_RESULT_WARNING_RESOURCE_SIZES_MISMATCH = 6, + /** Operation was successful. */ + XEFG_SWAPCHAIN_RESULT_SUCCESS = 0, + /** Operation not supported on the GPU. */ + XEFG_SWAPCHAIN_RESULT_ERROR_UNSUPPORTED_DEVICE = -1, + /** An unsupported driver. */ + XEFG_SWAPCHAIN_RESULT_ERROR_UNSUPPORTED_DRIVER = -2, + /** Execute called without initialization. */ + XEFG_SWAPCHAIN_RESULT_ERROR_UNINITIALIZED = -3, + /** Invalid argument were provided to the API call. */ + XEFG_SWAPCHAIN_RESULT_ERROR_INVALID_ARGUMENT = -4, + /** Not enough available GPU memory. */ + XEFG_SWAPCHAIN_RESULT_ERROR_DEVICE_OUT_OF_MEMORY = -5, + /** Device function such as resource or descriptor creation. */ + XEFG_SWAPCHAIN_RESULT_ERROR_DEVICE = -6, + /** The function is not implemented. */ + XEFG_SWAPCHAIN_RESULT_ERROR_NOT_IMPLEMENTED = -7, + /** Invalid context. */ + XEFG_SWAPCHAIN_RESULT_ERROR_INVALID_CONTEXT = -8, + /** Operation not finished yet. */ + XEFG_SWAPCHAIN_RESULT_ERROR_OPERATION_IN_PROGRESS = -9, + /** Operation not supported in current configuration. */ + XEFG_SWAPCHAIN_RESULT_ERROR_UNSUPPORTED = -10, + /** The library cannot be loaded. */ + XEFG_SWAPCHAIN_RESULT_ERROR_CANT_LOAD_LIBRARY = -11, + /** Input resources does not meet requirements based on UI Mode. */ + XEFG_SWAPCHAIN_RESULT_ERROR_MISMATCH_INPUT_RESOURCES = -12, + /** Output resources does not meet requirements. */ + XEFG_SWAPCHAIN_RESULT_ERROR_INCORRECT_OUTPUT_RESOURCES = -13, + /** Input is insufficient to evaluate interpolation. */ + XEFG_SWAPCHAIN_RESULT_ERROR_INCORRECT_INPUT_RESOURCES = -14, + /** Requirements regarding XeLL Latency Reduction are not met. */ + XEFG_SWAPCHAIN_RESULT_ERROR_LATENCY_REDUCTION_UNSUPPORTED = -15, + /** XeLL library does not contains required functions. */ + XEFG_SWAPCHAIN_RESULT_ERROR_LATENCY_REDUCTION_FUNCTION_MISSING = -16, + /** One of the Windows functions has failed. For details, see the logs or debug layer. */ + XEFG_SWAPCHAIN_RESULT_ERROR_HRESULT_FAILURE = -17, + /** DXGI call failed with invalid call error. */ + XEFG_SWAPCHAIN_RESULT_ERROR_DXGI_INVALID_CALL = -18, + /** XeFG SwapChain pointer is still in use during destroy. */ + XEFG_SWAPCHAIN_RESULT_ERROR_POINTER_STILL_IN_USE = -19, + /** Invalid or missing descriptor heap.*/ + XEFG_SWAPCHAIN_RESULT_ERROR_INVALID_DESCRIPTOR_HEAP = -20, + /** Call to function done in invalid order. */ + XEFG_SWAPCHAIN_RESULT_ERROR_WRONG_CALL_ORDER = -21, + + /** Unknown internal failure */ + XEFG_SWAPCHAIN_RESULT_ERROR_UNKNOWN = -1000 +} xefg_swapchain_result_t; + +/** + * @brief XeSS-FG Swap Chain logging level. + */ +typedef enum _xefg_swapchain_logging_level_t +{ + XEFG_SWAPCHAIN_LOGGING_LEVEL_DEBUG = 0, + XEFG_SWAPCHAIN_LOGGING_LEVEL_INFO = 1, + XEFG_SWAPCHAIN_LOGGING_LEVEL_WARNING = 2, + XEFG_SWAPCHAIN_LOGGING_LEVEL_ERROR = 3 +} xefg_swapchain_logging_level_t; + +/** + * @brief XeSS-FG UI composition mode. + * + * XeSS-FG can either interpolate UI (default) or compose a UI texture as-is on top of the interpolated frames. + * The application can provide the UI texture directly or rely on XeSS-FG to extract the texture from + * other available resources. + * + * UI composition can be enabled or disabled by changing the composition state. + * When UI composition is enabled, the UI mode determines which composition method is used. + * + * @see xefgSwapChainSetUiCompositionState for enabling or disabling UI composition. + */ +typedef enum _xefg_swapchain_ui_mode_t +{ + /** Determine UI composition mode automatically, based on provided inputs: hudless color and UI texture. */ + XEFG_SWAPCHAIN_UI_MODE_AUTO = 0, + /** Interpolate back buffer, without any UI composition. */ + XEFG_SWAPCHAIN_UI_MODE_NONE = 1, + /** Interpolate back buffer, refine UI using UI texture + alpha. */ + XEFG_SWAPCHAIN_UI_MODE_BACKBUFFER_UITEXTURE = 2, + /** Interpolate hudless color, blend UI from UI texture + alpha. */ + XEFG_SWAPCHAIN_UI_MODE_HUDLESS_UITEXTURE = 3, + /** Interpolate hudless color, extract UI from backbuffer. */ + XEFG_SWAPCHAIN_UI_MODE_BACKBUFFER_HUDLESS = 4, + /** Interpolate hudless color, blend UI from UI texture + alpha and refine it by extracting from back buffer. */ + XEFG_SWAPCHAIN_UI_MODE_BACKBUFFER_HUDLESS_UITEXTURE = 5 +} xefg_swapchain_ui_mode_t; + +XEFG_SWAPCHAIN_PACK_B() +/** + * @brief Contains status data for the present. + */ +typedef struct _xefg_swapchain_present_status_t +{ + /** Number of frames sent to be presented during the last call. */ + uint32_t framesPresented; + /** Result of the interpolation. */ + xefg_swapchain_result_t frameGenResult; + /** Specifies if frame generation was enabled. */ + uint32_t isFrameGenEnabled; +} xefg_swapchain_present_status_t; +XEFG_SWAPCHAIN_PACK_E() + +/** + * A logging callback provided by the application. This callback can be called from other threads. + * Message pointer is only valid inside the function and may be invalid right after the return call. + * Message is a null-terminated utf-8 string. Pointer to @p userData must remain valid until the call + * to @ref xefgSwapChainDestroy returns. + */ +typedef void (*xefg_swapchain_app_log_callback_t)(const char* message, xefg_swapchain_logging_level_t loggingLevel, void* userData); + +/** + * @addtogroup xefgswapchain XeSS-FG Swap Chain API exports + * The XeSS-FG Swap Chain API is used by applications to generate frames + * when the application does not choose to be responsible for the in-order presentation + * of the generated frames. This utils API wraps the IDXGISwapChain and makes + * calls on behalf of the application to the underlying XeSS-FG API. + * + * @{ + */ + + /** + * @brief Gets the XeSS-FG Swap Chain version. This is baked into the XeSS-FG Swap Chain SDK release. + * @param[out] pVersion Returned XeSS-FG Swap Chain version. + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainGetVersion(xefg_swapchain_version_t* pVersion); + + /** + * @brief Retrieves various XeSS-FG Swap Chain properties. + * + * @note When called before the proxy swap chain initialization, this function will only report + * `pProperties->maxSupportedInterpolations`, all other fields of `pProperties` will be set to zero. + * + * If you need to query the required heap sizes and the descriptor count before the proxy swap chain + * initialization, use @ref xefgSwapChainD3D12GetProperties. + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * + * @param[out] pProperties A pointer to the @ref xefg_swapchain_properties_t structure where the values should be returned. + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainGetProperties(xefg_swapchain_handle_t hSwapChain, xefg_swapchain_properties_t* pProperties); + +/** + * @brief Informs the XeSS-FG swap chain library of the frame constants used to generate a frame + * that will be presented. + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * + * @param presentId The unique frame identifier. + * + * @param pConstants A pointer to the memory location where the values for the constants are located. + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainTagFrameConstants(xefg_swapchain_handle_t hSwapChain, + uint32_t presentId, const xefg_swapchain_frame_constant_data_t* pConstants); + +/** + * @brief Enables or disables the generation and presentation of interpolated frames by the XeSS-FG swap chain library. + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * + * @param enable Non-zero to enable interpolation, zero to disable it. + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainSetEnabled(xefg_swapchain_handle_t hSwapChain, uint32_t enable); + +/** + * @brief Informs the XeSS-FG swap chain library of the unique identifier of the next frame + * to be presented. This allows the application to provide to the swap chain library frames data + * out-of-order with regard to the presentation. + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * + * @param presentId The unique identifier of the frame to be presented by the next IDXGISwapChain::Present call. + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainSetPresentId(xefg_swapchain_handle_t hSwapChain, uint32_t presentId); + +/** + * @brief This function allows you to retrieve status information from the last present. + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * + * @param[out] pPresentStatus A pointer to the @ref xefg_swapchain_present_status_t structure where the values should be returned. + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainGetLastPresentStatus(xefg_swapchain_handle_t hSwapChain, xefg_swapchain_present_status_t* pPresentStatus); + +/** + * @brief Sets logging callback. + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * @param loggingLevel Minimum logging level for logging callback. + * @param loggingCallback Logging callback. + * @param userData User data that will be passed unchanged to the callback when invoked. Can be set to NULL. + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainSetLoggingCallback(xefg_swapchain_handle_t hSwapChain, + xefg_swapchain_logging_level_t loggingLevel, xefg_swapchain_app_log_callback_t loggingCallback, void* userData); + +/** +* @brief Destroys a XeSS-FG Swap Chain context data. DXGI swap chain object will be released as soon as reference count reaches 0, +* so it's recommended to release all outstanding references before calling this function. +* @param hSwapChain: The XeSS-FG Swap Chain context handle. +* @return XeSS-FG Swap Chain return status code. +*/ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainDestroy(xefg_swapchain_handle_t hSwapChain); + +/** + * @brief Sets XeLL context for latency reduction. + * + * @param hSwapChain: The XeSS-FG Swap Chain context handle. + * @param hXeLLContext: The Xe Low Latency context. + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainSetLatencyReduction(xefg_swapchain_handle_t hSwapChain, void* hXeLLContext); + +/** + * @brief Sets scene change detection threshold. + * + * A higher threshold value increases the algorithm's sensitivity, causing it to more readily identify + * scene changes and disable interpolation. A lower threshold value decreases sensitivity, making the algorithm + * less likely to respond to minor changes. The threshold value range is from 0 to 1, where 0 represents the least + * sensitivity to scene changes, and 1 represents the highest sensitivity. + * + * @param hSwapChain: The XeSS-FG Swap Chain context handle. + * @param threshold: Scene change detection threshold value. Default value is 0.7. + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainSetSceneChangeThreshold(xefg_swapchain_handle_t hSwapChain, float threshold); + +/** + * @brief Returns current state of the pipeline build + * + * This function can only be called after @ref xefgSwapChainD3D12BuildPipelines but + * before XeSS-FG swap chain initialization (@ref xefgSwapChainD3D12InitFromSwapChain + * or @ref xefgSwapChainD3D12InitFromSwapChainDesc). + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * @return XEFG_SWAPCHAIN_RESULT_SUCCESS if pipelines are already built. + * XEFG_SWAPCHAIN_RESULT_ERROR_OPERATION_IN_PROGRESS if pipeline build are in progress. + * XEFG_SWAPCHAIN_RESULT_ERROR_WRONG_CALL_ORDER if the function is called out of order. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainGetPipelineBuildStatus(xefg_swapchain_handle_t hSwapChain); + +/** + * @brief Adjust the number of interpolated frames after initialization. + * + * By default, XeSS-FG swap chain will produce the maximum number of interpolated frames + * specified during initialization. Use this function to change the number of interpolated frames + * without reinitializing the swap chain. + * + * The number of interpolated frames must be between 1 and the maximum provided during swap chain + * initialization, otherwise the function returns @ref XEFG_SWAPCHAIN_RESULT_ERROR_INVALID_ARGUMENT. + * + * **Performance Note:** Avoid frequent calls to this function, as changing the number of + * interpolated frames may trigger shader compilation and reallocation of internal resources. + * + * **Error Handling:** If this function fails for any reason other than + * @ref XEFG_SWAPCHAIN_RESULT_ERROR_INVALID_ARGUMENT, reinitialize the swap chain (this is rare). + * Ignoring such errors may lead to unexpected behavior. On non-argument errors, XeSS-FG automatically + * disables frame generation to keep the swap chain operational (e.g., it can still display error messages). + * + * **Thread-Safety:** This function is not thread-safe with regard to calls to + * @ref xefgSwapChainD3D12InitFromSwapChain, @ref xefgSwapChainD3D12InitFromSwapChainDesc, and + * @ref xefgSwapChainDestroy. Do not call @ref xefgSwapChainSetNumInterpolatedFrames if another + * thread might be initializing or destroying the swap chain. + * + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainSetNumInterpolatedFrames( + xefg_swapchain_handle_t hSwapChain, uint32_t numInterpolatedFrames); + +/** + * @brief Controls whether UI composition is enabled or disabled. + */ +typedef enum +{ + /* UI mode set during initialization has no effect. This is the default state. */ + XEFG_SWAPCHAIN_UI_COMPOSITION_STATE_DISABLED, + /* UI is composited on top of the interpolated frame according to the UI mode set during initialization. */ + XEFG_SWAPCHAIN_UI_COMPOSITION_STATE_ENABLED +} xefg_swapchain_ui_composition_state_t; + +/** + * @brief Enable or disable UI composition. + * + * If UI composition is disabled, UI mode will have no effect. + * + * Setting UI mode to `XEFG_SWAPCHAIN_UI_MODE_NONE` and enabling UI composition is the same + * as disabling UI composition. + * + * @note Try no UI composition first (default), then switch to UI composition if you are not happy + * with the no-composition output. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainSetUiCompositionState( + xefg_swapchain_handle_t hSwapChain, xefg_swapchain_ui_composition_state_t state); + +/** @}*/ + +/* Enum size checks. All enums must be 4 bytes. */ +XEFG_SWAPCHAIN_STATIC_ASSERT(sizeof(xefg_swapchain_resource_validity_t) == 4); +XEFG_SWAPCHAIN_STATIC_ASSERT(sizeof(xefg_swapchain_result_t) == 4); +XEFG_SWAPCHAIN_STATIC_ASSERT(sizeof(xefg_swapchain_init_flags_t) == 4); +XEFG_SWAPCHAIN_STATIC_ASSERT(sizeof(xefg_swapchain_logging_level_t) == 4); +XEFG_SWAPCHAIN_STATIC_ASSERT(sizeof(xefg_swapchain_resource_type_t) == 4); +XEFG_SWAPCHAIN_STATIC_ASSERT(sizeof(xefg_swapchain_ui_mode_t) == 4); + +#ifdef __cplusplus +} +#endif + +#endif /* XEFG_SWAPCHAIN_H */ diff --git a/External/External.Libraries/xess/Include/xess_fg/xefg_swapchain_d3d12.h b/External/External.Libraries/xess/Include/xess_fg/xefg_swapchain_d3d12.h new file mode 100644 index 0000000..c53f145 --- /dev/null +++ b/External/External.Libraries/xess/Include/xess_fg/xefg_swapchain_d3d12.h @@ -0,0 +1,328 @@ +/******************************************************************************* + * Copyright (C) 2024 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, and + * your use of them is governed by the express license under which they were + * provided to you ("License"). Unless the License provides otherwise, you may + * not use, modify, copy, publish, distribute, disclose or transmit this + * software or the related documents without Intel's prior written permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + ******************************************************************************/ + +#ifndef XEFG_SWAPCHAIN_D3D12_H +#define XEFG_SWAPCHAIN_D3D12_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include "xefg_swapchain.h" + +XEFG_SWAPCHAIN_PACK_B() +/** +* @brief Initialization parameters. +* Optional external allocations are only available for the internal XeSS-FG resources, +* the Swap Chain API resources will still be managed by the API. +*/ +typedef struct _xefg_swapchain_d3d12_init_params_t +{ + /** Pointer to the application swap chain. */ + IDXGISwapChain* pApplicationSwapChain; + /** Initialization flags. */ + uint32_t initFlags; + /** + * @brief XeSS-FG won't produce more than this number of interpolated frames. + * + * The value must be between one and the maximum supported number of interpolated frames or + * @ref XEFG_SWAPCHAIN_USE_MAX_SUPPORTED_INTERPOLATED_FRAMES. + * + * If the value is set to @ref XEFG_SWAPCHAIN_USE_MAX_SUPPORTED_INTERPOLATED_FRAMES, + * XeSS-FG will automatically pick the maximum supported number. + * + * @see + * - xefgSwapChainGetProperties to query the maximum supported number of interpolated frames, + * works before initialization. + * - xefgSwapChainD3D12GetInitializationParameters to query the value that was applied + * during initialization. + * */ + uint32_t maxInterpolatedFrames; + /** Specifies the node mask for internally created resources on + * multi-adapter systems. */ + uint32_t creationNodeMask; + /** Specifies the node visibility mask for internally created resources + * on multi-adapter systems. */ + uint32_t visibleNodeMask; + /** Optional externally allocated buffer storage for XeSS-FG. If NULL the + * storage is allocated internally. If allocated, the heap type must be + * D3D12_HEAP_TYPE_DEFAULT. This heap is not accessed by the CPU. */ + ID3D12Heap* pTempBufferHeap; + /** Offset in the externally allocated heap for temporary buffer storage. */ + uint64_t bufferHeapOffset; + /** Optional externally allocated texture storage for XeSS-FG. If NULL the + * storage is allocated internally. If allocated, the heap type must be + * D3D12_HEAP_TYPE_DEFAULT. This heap is not accessed by the CPU. */ + ID3D12Heap* pTempTextureHeap; + /** Offset in the externally allocated heap for temporary texture storage. */ + uint64_t textureHeapOffset; + /** Pointer to pipeline library. If not NULL, then it will be used for pipeline caching. */ + ID3D12PipelineLibrary* pPipelineLibrary; + /** Determines UI composition mode when UI composition is enabled. + * Use @ref XEFG_SWAPCHAIN_UI_MODE_AUTO to determine UI composition mode based on the provided inputs. + * @see xefgSwapChainSetUiCompositionState + */ + xefg_swapchain_ui_mode_t uiMode; +} xefg_swapchain_d3d12_init_params_t; +XEFG_SWAPCHAIN_PACK_E() + +XEFG_SWAPCHAIN_PACK_B() +/** + * @brief Contains all fields needed when providing a resource to + * the library, describing its state, lifetime, range and so on. + */ +typedef struct _xefg_swapchain_d3d12_resource_data_t +{ + /** XeSS-FG type of the resource. */ + xefg_swapchain_resource_type_t type; + /** Time period this resource is valid for. */ + xefg_swapchain_resource_validity_t validity; + /** Base offset to the resource data. */ + xefg_swapchain_2d_t resourceBase; + /** Valid extent of the resource. */ + xefg_swapchain_2d_t resourceSize; + /** D3D12Resource object for this resource. */ + ID3D12Resource *pResource; + /** Incoming state of the resource. */ + D3D12_RESOURCE_STATES incomingState; +} xefg_swapchain_d3d12_resource_data_t; +XEFG_SWAPCHAIN_PACK_E() + +/** + * @addtogroup xefgswapchain-d3d12 XeSS-FG Swap Chain D3D12 API exports + * @{ + */ + +/** + * @brief Creates a swap chain handle and checks necessary D3D12 features. + * + * @param pDevice A D3D12 device created by the user. + * + * @param[out] phSwapChain Pointer to a XeSS-FG swap chain context handle. + * + * @return XeSS-FG Swap Chain return status code. + */ + XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainD3D12CreateContext(ID3D12Device* pDevice, xefg_swapchain_handle_t* phSwapChain); + +/** + * @brief Initiates pipeline build process + * This function can only be called between @ref xefgSwapChainD3D12CreateContext and + * any initialization function + * This call initiates build of DX12 pipelines and kernel compilation + * This call can be blocking (if @p blocking set to true) or non-blocking. + * In case of non-blocking call library will wait for pipeline build on call to + * initialization function + * If @p pPipelineLibrary passed to this call - same pipeline library must be passed + * to initialization function + * Pipeline build status can be retrieved using @ref xefgSwapChainGetPipelineBuildStatus + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * @param pPipelineLibrary Optional pointer to pipeline library for pipeline caching. + * @param blocking Wait for kernel compilation and pipeline creation to finish or not + * @param initFlags Initialization flags. *Must* be identical to flags passed to initialization function + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainD3D12BuildPipelines(xefg_swapchain_handle_t hSwapChain, + ID3D12PipelineLibrary* pPipelineLibrary, uint8_t blocking, uint32_t initFlags); + + /** + * @brief Queries properties (including required heap sizes) given desired initialization parameters. + * + * This function can be called before or after the proxy swap chain initialization. + * + * Once the proxy swap chain is initialized, `properties` returned by this function will match + * the properties returned by `xefgSwapChainGetProperties`. + * + * Use this function to determine heap sizes required for successful initialization of the proxy swap chain. + * The heap sizes are valid for any number of interpolated between one and the maximum specified + * via `initParams.maxInterpolatedFrames`. + * + * If you need to query heap sizes required for a resolution change, set `initParams` to `NULL` + * and pass in the new `backBufferWidth` and `backBufferHeight`. + * + * If you don't want to specify the maximum number of interpolated frames, set `initParams.maxInterpolatedFrames` + * to `XEFG_SWAPCHAIN_USE_MAX_SUPPORTED_INTERPOLATED_FRAMES`. + * + * @param context + * @param initParams - pass `NULL` to use the values provided during the proxy swap chain initialization + * @param backBufferWidth - pass 0 to use the value provided during initialization. + * @param backBufferHeight - pass 0 to use the value provided during initialization. + * @param backBufferFormat - pass DXGI_FORMAT_UNKNOWN to use the value provided during initialization. + * @param properties - output, cannot be `NULL` + * @return XEFG_SWAPCHAIN_RESULT_SUCCESS if the operation was successful. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainD3D12GetProperties( + xefg_swapchain_handle_t context, + const xefg_swapchain_d3d12_init_params_t* initParams, + uint32_t backBufferWidth, + uint32_t backBufferHeight, + DXGI_FORMAT backBufferFormat, + xefg_swapchain_properties_t* properties); + +/** + * @brief Initializes the XeSS-FG Swap Chain library for the generation + * and presentation of additional frames. + * The application should call @ref xefgSwapChainD3D12GetSwapChainPtr to retrieve the actual IDXGISwapChain handle. + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * + * @param pCmdQueue Command queue used by the application + * to present frames. This queue must conform to all restrictions of any IDXGISwapChain. + * + * @param pInitParams XeSS-FG Swap Chain API initialization parameters. + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainD3D12InitFromSwapChain(xefg_swapchain_handle_t hSwapChain, + ID3D12CommandQueue* pCmdQueue, const xefg_swapchain_d3d12_init_params_t* pInitParams); + +/** + * @brief Initializes the XeSS-FG Swap Chain library for the generation + * and presentation of additional frames. + * The application should call @ref xefgSwapChainD3D12GetSwapChainPtr to retrieve the actual IDXGISwapChain handle. + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * + * @param hWnd Window handle used to create the swap chain. + * + * @param pSwapChainDesc Swap chain description. + * + * @param pFullscreenDesc Fullscreen swap chain description. Can be set to NULL. + * + * @param pCmdQueue Command queue used by the application + * to present frames. This queue must conform to all restrictions of any IDXGISwapChain. + * + * @param pDxgiFactory IDXGIFactory2 object to be used for the swap chain creation. + * + * @param pInitParams XeSS-FG Swap Chain API initialization parameters. + * @p pApplicationSwapChain field will not be used and must be set to NULL, a swap chain will be created according to @p hWnd, @p pSwapChainDesc and @p pFullscreenDesc. + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainD3D12InitFromSwapChainDesc(xefg_swapchain_handle_t hSwapChain, + HWND hWnd, const DXGI_SWAP_CHAIN_DESC1* pSwapChainDesc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, + ID3D12CommandQueue* pCmdQueue, IDXGIFactory2* pDxgiFactory, const xefg_swapchain_d3d12_init_params_t* pInitParams); + +/** + * @brief Gets a pointer to a DXGI swap chain. The application must use it for + * all presentation in the application. + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * + * @param riid Type of the interface to which the caller wants a pointer. + * + * @param[out] ppSwapChain Pointer to a IDXGISwapChain handle. + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainD3D12GetSwapChainPtr(xefg_swapchain_handle_t hSwapChain, REFIID riid, void** ppSwapChain); + +/** + * @brief Informs the XeSS-FG swap chain library of the frame resources used to generate a frame + * that will be presented. + * + * @attention This function can be used to provide information about the interpolation region within the + * backbuffer by using @p XEFG_SWAPCHAIN_RES_BACKBUFFER resource type. In that case only information about region (size + * and offset) is used from the @p pResData argument. + * + * @param hSwapChain The swap chain associated with the resource being tagged. + * + * @param pCmdList Optional command list utilized to manage the resource + * lifetime. It is only required if the resource is not valid until the next + * present call. + * + * @param presentId The unique frame identifier this resource is associated with. + * + * @param pResData The resource and the information needed to properly + * manage and interpret it. + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainD3D12TagFrameResource(xefg_swapchain_handle_t hSwapChain, + ID3D12CommandList* pCmdList, uint32_t presentId, const xefg_swapchain_d3d12_resource_data_t* pResData); + +/** + * @brief Informs the XeSS-FG swap chain library of the descriptor heap to use during frame generation. This API + * needs to be called before presenting a frame. The descriptor heap must be a D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV. + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * + * @param pDescriptorHeap a pointer to the ID3D12DescriptorHeap object used during interpolation programming. + * + * @param descriptorHeapOffsetInBytes The offset within @p pDescriptorHeap XeSS-FG will start using during interpolation + * programming, in bytes. This value is number of descriptors to skip times GetDescriptorHandleIncrementSize(). + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainD3D12SetDescriptorHeap(xefg_swapchain_handle_t hSwapChain, + ID3D12DescriptorHeap* pDescriptorHeap, uint32_t descriptorHeapOffsetInBytes); + + +/** + * @brief Updates external heap pointers during the next call to ResizeBuffers or ResizeBuffers1 + * + * XeSS-FG won't reference the provided heap pointers until the application calls ResizeBuffers + * or ResizeBuffers1. Once ResizeBuffers or ResizeBuffers1 return control back to the application, + * XeSS-FG is guaranteed to be using the new heaps. + * + * If ResizeBuffers or ResizeBuffers1 fail, XeSS-FG will release the references to the provided + * heaps. + * + * Use @ref xefgSwapChainD3D12GetProperties to get the required heap sizes. + * + * @param hSwapChain + * @param tempBufferHeap + * @param tempBufferHeapOffset - must be zero if @p tempBufferHeap is null + * @param tempTextureHeap + * @param tempTextureHeapOffset - must be zero if @p tempTextureHeap is null + * @return + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainD3D12UpdateExternalHeapOnResize( + xefg_swapchain_handle_t hSwapChain, + ID3D12Heap* tempBufferHeap, + uint64_t tempBufferHeapOffset, + ID3D12Heap* tempTextureHeap, + uint64_t tempTextureHeapOffset); + +/** + * @brief Retrieve initialization parameters if the initialization was successful. + * + * This function is not thread-safe with regards to calls to @ref xefgSwapChainD3D12InitFromSwapChain, + * @ref xefgSwapChainD3D12InitFromSwapChainDesc, and @ref xefgSwapChainDestroy. Do not call + * @ref xefgSwapChainD3D12GetInitializationParameters if another thread might be doing initialization of or + * destroying the same context handle. + * + * @param hSwapChain XeSS-FG swap chain context handle. + * + * @param[out] pParams will contain parameters that were used to initialize the provided swap chain. + * + * @note + * - `pParams->pApplicationSwapChain` will be set to `NULL` to signify that the swap chain was re-created. + * - `pParams->maxInterpolatedFrames` will be set to the actual value that was used during initialization: + * the maximum suppored number if the user requested @ref XEFG_SWAPCHAIN_USE_MAX_SUPPORTED_INTERPOLATED_FRAMES + * or the user-provided value otherwise. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainD3D12GetInitializationParameters( + xefg_swapchain_handle_t hSwapChain, xefg_swapchain_d3d12_init_params_t* pParams); + +/** @}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* XEFG_SWAPCHAIN_D3D12_H */ diff --git a/External/External.Libraries/xess/Include/xess_fg/xefg_swapchain_debug.h b/External/External.Libraries/xess/Include/xess_fg/xefg_swapchain_debug.h new file mode 100644 index 0000000..75b3c3d --- /dev/null +++ b/External/External.Libraries/xess/Include/xess_fg/xefg_swapchain_debug.h @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (C) 2024 Intel Corporation + * + * This software and the related documents are Intel copyrighted materials, and + * your use of them is governed by the express license under which they were + * provided to you ("License"). Unless the License provides otherwise, you may + * not use, modify, copy, publish, distribute, disclose or transmit this + * software or the related documents without Intel's prior written permission. + * + * This software and the related documents are provided as is, with no express + * or implied warranties, other than those that are expressly stated in the + * License. + ******************************************************************************/ + +#ifndef XEFG_SWAPCHAIN_DEBUG_H +#define XEFG_SWAPCHAIN_DEBUG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xefg_swapchain.h" + +/** + * @brief XeSS-FG Swap Chain debug features list. + */ +typedef enum _xefg_swapchain_debug_feature_t +{ + /** Present only interpolated frames. If interpolation fails, current back buffer will be presented. */ + XEFG_SWAPCHAIN_DEBUG_FEATURE_SHOW_ONLY_INTERPOLATION = 0, + /** Adds a quads in the corners of interpolated frame. */ + XEFG_SWAPCHAIN_DEBUG_FEATURE_TAG_INTERPOLATED_FRAMES = 1, + /** Present black image instead of skipping failed interpolation. */ + XEFG_SWAPCHAIN_DEBUG_FEATURE_PRESENT_FAILED_INTERPOLATION = 2, + XEFG_SWAPCHAIN_DEBUG_FEATURE_RES_COUNT +} xefg_swapchain_debug_feature_t; + +/** + * @addtogroup xefgswapchain_debug XeSS-FG Swap Chain debug features + * @{ + */ + +/** + * @brief Controls for debug features of XeSS-FG Swap Chain API library. + * + * @param hSwapChain The XeSS-FG Swap Chain context handle. + * + * @param featureId The debug feature to enable or disable. + * + * @param enable Non-zero to enable the feature, zero to disable it. + * + * @param pArgument Feature-defined arguments. Please refer to the debug feature documentation. + * + * @return XeSS-FG Swap Chain return status code. + */ +XEFG_SWAPCHAIN_API xefg_swapchain_result_t xefgSwapChainEnableDebugFeature(xefg_swapchain_handle_t hSwapChain, + xefg_swapchain_debug_feature_t featureId, uint32_t enable, void* pArgument); + +/** @}*/ + +/* Enum size checks. All enums must be 4 bytes */ +XEFG_SWAPCHAIN_STATIC_ASSERT(sizeof(xefg_swapchain_debug_feature_t) == 4); + +#ifdef __cplusplus +} +#endif + +#endif /* XEFG_SWAPCHAIN_DEBUG_H */ diff --git a/External/External.Libraries/xess/lib/libxess.lib b/External/External.Libraries/xess/lib/libxess.lib new file mode 100644 index 0000000..a48d04e Binary files /dev/null and b/External/External.Libraries/xess/lib/libxess.lib differ diff --git a/External/Runtime/libxess.dll b/External/Runtime/libxess.dll new file mode 100644 index 0000000..c19af98 --- /dev/null +++ b/External/Runtime/libxess.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:251659dd84a3e84de67c886a4186e01f3eca49b00641906fe38bb6b807e5d5b7 +size 77795704 diff --git a/External/Runtime/nvngx_dlss.dll b/External/Runtime/nvngx_dlss.dll new file mode 100644 index 0000000..5e7f52b --- /dev/null +++ b/External/Runtime/nvngx_dlss.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8f23de8116727a160a196f9f43604284cd973d801a62bb68c19c828f78e5f3b +size 54779504 diff --git a/External/Runtime/sl.common.dll b/External/Runtime/sl.common.dll index 7dd462f..9a3a5cd 100644 --- a/External/Runtime/sl.common.dll +++ b/External/Runtime/sl.common.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57c487e8c6f1dd98d4ea2bc57745243b0d393447ddc04be0b07b21e901ba2f32 -size 2963968 +oid sha256:eca8c0f1d4af654103a2f8b315e91fcd54ee4437570ac20c90ab78131c791274 +size 674432 diff --git a/External/Runtime/sl.directsr.dll b/External/Runtime/sl.directsr.dll index e27f945..2eaddf6 100644 --- a/External/Runtime/sl.directsr.dll +++ b/External/Runtime/sl.directsr.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:71aca22c0ff38fc3b7f0bf42ba8239729b93bda3936b2a2509156e73fd51e048 -size 679936 +oid sha256:a28e5fa805d76a9acb7676f88705aa9c7ee507d682d48a1248c888da83812da0 +size 183424 diff --git a/External/Runtime/sl.dlss.dll b/External/Runtime/sl.dlss.dll index 7cded0d..167e4c7 100644 --- a/External/Runtime/sl.dlss.dll +++ b/External/Runtime/sl.dlss.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8265f3660a59c2b02ffab16cc907b3d31aaa6adf8d02ae8db44d3a976266bb19 -size 880640 +oid sha256:164750168cb36a79e7552e7fc74bf5723347f97f69e5d466167aa09623615c03 +size 240256 diff --git a/External/Runtime/sl.interposer.dll b/External/Runtime/sl.interposer.dll index 6c87c38..962c1d7 100644 --- a/External/Runtime/sl.interposer.dll +++ b/External/Runtime/sl.interposer.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5e4efc5e1fc11b5e1315d9975ed79f3492d8c83838e5c70596c2b6326d42a7f5 -size 2082816 +oid sha256:fabb19bb6495d743182c1bc51bcbbdc4481acc3dcaf445403f0b304a31a56ccc +size 569472 diff --git a/External/Runtime/sl.nis.dll b/External/Runtime/sl.nis.dll index 55460ed..d6f6c83 100644 --- a/External/Runtime/sl.nis.dll +++ b/External/Runtime/sl.nis.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4c6b478a10322d9370e0f5f5a9db5301bbc89a7925a7fe1e98b6b314da6c730 -size 1693696 +oid sha256:f8641e13326ede4ace056cbfead7b18b3cd11f696fec07b003b5d295e8588b21 +size 967808 diff --git a/External/Runtime/sl.reflex.dll b/External/Runtime/sl.reflex.dll index 1acfa71..397ec95 100644 --- a/External/Runtime/sl.reflex.dll +++ b/External/Runtime/sl.reflex.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88519126c3c4d8c4917f434071a3cd61d01ff40ac7a237ce1cd9a038751bb744 -size 750592 +oid sha256:2fb1d61aa0b693a2294929ffc91799b70e231b1f22f610bf8b3ff17b911d06a7 +size 198784 diff --git a/MSBuild/Props/PEPEngine.External.NvidiaSDK.props b/MSBuild/Props/PEPEngine.External.NvidiaSDK.props index 459bd96..fc68044 100644 --- a/MSBuild/Props/PEPEngine.External.NvidiaSDK.props +++ b/MSBuild/Props/PEPEngine.External.NvidiaSDK.props @@ -5,5 +5,8 @@ $(PEPExternalNvidiaSDKInclude);%(AdditionalIncludeDirectories) + + $(PEPRepoRoot)External\External.Libraries\nvidia-sdk\lib\;%(AdditionalLibraryDirectories) + diff --git a/MSBuild/Props/PEPEngine.External.Paths.props b/MSBuild/Props/PEPEngine.External.Paths.props index 38a9f45..0361f74 100644 --- a/MSBuild/Props/PEPEngine.External.Paths.props +++ b/MSBuild/Props/PEPEngine.External.Paths.props @@ -12,6 +12,7 @@ $(PEPExternalRoot)debugdrawer\Include $(PEPExternalRoot)ffx-api\Include $(PEPExternalRoot)nvidia-sdk\Include + $(PEPExternalRoot)xess\Include $(PEPExternalRoot)directstorage\Include $(PEPExternalRoot)directxmesh\Include $(PEPExternalRoot)wwise\Include diff --git a/MSBuild/Props/PEPEngine.External.XeSS.props b/MSBuild/Props/PEPEngine.External.XeSS.props new file mode 100644 index 0000000..5974eee --- /dev/null +++ b/MSBuild/Props/PEPEngine.External.XeSS.props @@ -0,0 +1,9 @@ + + + + + + $(PEPExternalXeSSInclude);%(AdditionalIncludeDirectories) + + + diff --git a/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props b/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props index 927100d..6b41c9c 100644 --- a/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props +++ b/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props @@ -1,6 +1,8 @@ + + $(PEPRepoRoot)Engine\Engine.RendererDX12\Include;%(AdditionalIncludeDirectories)