From 6cd5849b12805b3e588effcfcc788b552ae85f4a Mon Sep 17 00:00:00 2001 From: AMorunov Date: Thu, 25 Jun 2026 13:30:41 +0300 Subject: [PATCH 01/46] Batched device resources into a separate class --- .../Include/App.Base/Modules/RenderModule.h | 54 +-- .../App.Base/Systems/GPUDataUpdateSystem.h | 12 +- Apps/App.Base/src/ECS/WorldLoader.cpp | 52 +-- Apps/App.Base/src/RenderModule.cpp | 431 ++++++++---------- .../Engine.RendererDX12.vcxproj | 2 + .../Engine.RendererDX12.vcxproj.filters | 15 + .../Include/Engine.RendererDX12/GDX12Device.h | 7 + .../GDX12DeviceResources.h | 41 ++ .../Engine.RendererDX12/GDX12Material.h | 27 +- .../Engine.RendererDX12/GDX12Texture.h | 18 + .../Engine.RendererDX12/src/GDX12Device.cpp | 3 +- .../src/GDX12DeviceResources.cpp | 108 +++++ 12 files changed, 448 insertions(+), 322 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceResources.h create mode 100644 Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index 5cf3cad..f8fa835 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -4,16 +4,10 @@ #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/GDX12DeviceResources.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.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" @@ -51,9 +45,9 @@ class RenderModule final : public Module //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); @@ -97,9 +91,12 @@ class RenderModule final : public Module 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(); protected: void OnUpdate() override; @@ -109,19 +106,17 @@ class RenderModule final : public Module bool ShouldRender() override; private: - void BuildDescHeapsAndBackBuffer(); + void BuildBackBuffer(); void BuildRootSignatures(); void BuildShaders(); void BuildPSOs(); - void BuildFrameConstants(); - - void UpdateMainCB(); - void UpdateMaterialCB(); void SubscribeToSceneManager(); void UnsubscribeFromSceneManager(); void UnsubscribeFromAllWorlds(); + GDX12Texture* CreateDX12Texture(const std::string& name, GDX12DeviceResources* resources, const Texture* texture); + GameTimer* _timer; Window* _window; @@ -137,30 +132,11 @@ class RenderModule final : public Module 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; diff --git a/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h b/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h index 066e49c..97903f2 100644 --- a/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h +++ b/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h @@ -62,7 +62,7 @@ class GPUDataUpdateSystem final : public System objConstants.NearPlane = camera.NearPlane; objConstants.FarPlane = camera.FarPlane; - auto& CBuffer = renderModule->GetCurrentFrameConstants()->CameraCB; + auto& CBuffer = renderModule->GetCurrentPrimaryFrameConstants()->CameraCB; CBuffer->CopyData(camera._CBufferIndex, objConstants); camera._numFramesDirty--; @@ -93,7 +93,7 @@ class GPUDataUpdateSystem final : public System GDX12TransformConstants objConstants; XMStoreFloat4x4(&objConstants.WorldMatrix, XMMatrixTranspose(world)); - auto& CBuffer = renderModule->GetCurrentFrameConstants()->TransformCache; + auto& CBuffer = renderModule->GetCurrentPrimaryFrameConstants()->TransformCache; CBuffer->CopyData(GPUData.CBufferIndex, objConstants); GPUData.NumFramesDirty--; @@ -103,9 +103,9 @@ 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& instanceCache = renderModule->GetCurrentPrimaryFrameConstants()->InstanceCache; + auto indirectCommandsCache = renderModule->GetPrimaryIndirectCommandsCache(); + auto gpuMesh = renderModule->GetPrimaryGPUMesh(renderer.MeshHandler); auto& transformGPUData = renderModule->GetTransformGPUData(entity); if (renderer.DirtyFlag || transform.DirtyFlag) @@ -143,7 +143,7 @@ class GPUDataUpdateSystem final : public System GDX12InstanceData instanceData; instanceData.TransformIndex = transformGPUData.CBufferIndex; - instanceData.MaterialIndex = renderer.Materials[subMesh.MaterialIndex]->_CBufferIndex; + instanceData.MaterialIndex = renderer.Materials[subMesh.MaterialIndex]->_PrimaryCBufferIndex; instanceData.BoundingBoxCenter = bounds.Center; instanceData.BoundingBoxExtents = bounds.Extents; diff --git a/Apps/App.Base/src/ECS/WorldLoader.cpp b/Apps/App.Base/src/ECS/WorldLoader.cpp index 3c336fe..07bb4c0 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, diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 50f4331..fd076a1 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -2,7 +2,6 @@ #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" @@ -10,33 +9,10 @@ #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"); - -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 "Common/ConsoleVariables.h" RenderModule::RenderModule(Window* window, GameTimer* timer) : - _dualGPUMode(false), _window(window), - _currFrameConstantsIndex(0), _timer(timer) + _dualGPUMode(false), _window(window), _timer(timer) { } @@ -58,31 +34,24 @@ void RenderModule::Initialize() _primaryDevice = std::make_unique(); _primaryDevice->Initialize(GDX12DeviceFactory::GetMostPerformantAdapter().Get()); + _primaryDevice->Role = DEVICE_ROLE_PRIMARY; + _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 } - }; + _secondaryDevice = std::make_unique(); + _secondaryDevice->Initialize(GDX12DeviceFactory::GetMostPerformantAdapter().Get()); + _secondaryDevice->Role = DEVICE_ROLE_SECONDARY; + _secondaryResources.Initialize(_primaryDevice.get()); + _dualGPUMode = true; + } + + BuildBackBuffer(); - BuildDescHeapsAndBackBuffer(); BuildRootSignatures(); BuildShaders(); BuildPSOs(); - BuildFrameConstants(); - _geometryBuffer = std::make_unique(_primaryDevice.get()); SubscribeToSceneManager(); } @@ -128,9 +97,9 @@ 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(); + _materials[name]->_PrimaryCBufferIndex = _primaryResources.FrameConstants[0]->MaterialCache->GetElementCount(); - for (auto& constants : _frameConstants) + for (auto& constants : _primaryResources.FrameConstants) { auto& CBuffer = constants->MaterialCache; CBuffer->Resize(CBuffer->GetElementCount() + 1); @@ -139,7 +108,7 @@ GDX12Material* RenderModule::CreateMaterial(const std::string& name) 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,7 +118,7 @@ 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()) { @@ -158,8 +127,16 @@ GDX12Texture* RenderModule::CreateTexture(const std::string& name, const Texture return nullptr; } + _textures[name] = std::make_unique(); + _textures[name]->Name = name; + _textures[name]->PrimaryDeviceTexture = CreateDX12Texture(name, &_primaryResources, texture); + if (_secondaryDevice) { _textures[name]->SecondaryDeviceTexture = CreateDX12Texture(name, &_secondaryResources, texture); } +} + +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 +162,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 +171,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 +187,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 +211,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 +251,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 +286,15 @@ GDX12Texture* RenderModule::CreateTexture(const std::string& name, const Texture desc.ExternalResource = textureResource; - _textures[name] = std::make_unique(desc); + resources->Textures[name] = std::make_unique(desc); - return _textures[name].get(); + return resources->Textures[name].get(); } void RenderModule::SubmitMesh(const Mesh* mesh, MeshHandle handle) { - _geometryBuffer->AddMesh(mesh, handle); + _primaryResources.GeometryBuffer->AddMesh(mesh, handle); + if (_secondaryDevice) _secondaryResources.GeometryBuffer->AddMesh(mesh, handle); } TransformCompGPUData& RenderModule::GetTransformGPUData(Entity entity) @@ -431,32 +409,52 @@ void RenderModule::UnsubscribeFromWorld(World& world) _worldSubscriptions.erase(it); } -GDX12FrameConstants* RenderModule::GetCurrentFrameConstants() +GDX12FrameConstants* RenderModule::GetCurrentPrimaryFrameConstants() +{ + return _primaryResources.FrameConstants[_primaryResources.CurrFrameConstantsIndex].get(); +} + +GDX12FrameConstants* RenderModule::GetCurrentSecondaryFrameConstants() { - return _frameConstants[_currFrameConstantsIndex].get(); + return _secondaryResources.FrameConstants[_secondaryResources.CurrFrameConstantsIndex].get(); } -const GPUMesh* RenderModule::GetGPUMesh(MeshHandle handle) +const GPUMesh* RenderModule::GetPrimaryGPUMesh(MeshHandle handle) { - return _geometryBuffer->GetGPUMeshByHandle(handle); + return _primaryResources.GeometryBuffer->GetGPUMeshByHandle(handle); } -GDX12UploadBuffer* RenderModule::GetIndirectCommandsCache() +const GPUMesh* RenderModule::GetSecondaryGPUMesh(MeshHandle handle) { - return _IndirectCommandsCache.get(); + return _secondaryResources.GeometryBuffer->GetGPUMeshByHandle(handle); +} + +GDX12UploadBuffer* RenderModule::GetPrimaryIndirectCommandsCache() +{ + return _primaryResources.IndirectCommandsCache.get(); +} + +GDX12UploadBuffer* RenderModule::GetSecondaryIndirectCommandsCache() +{ + return _secondaryResources.IndirectCommandsCache.get(); } void RenderModule::OnTransformComponentCreated(World& world, Entity entity, TransformComponent& component) { TransformCompGPUData gpuData; - gpuData.CBufferIndex = _frameConstants[0]->TransformCache->GetElementCount(); + gpuData.CBufferIndex = _primaryResources.FrameConstants[0]->TransformCache->GetElementCount(); _transformGPUData[entity] = gpuData; - for (auto& constants : _frameConstants) + for (auto& constants : _primaryResources.FrameConstants) { auto& CBuffer = constants->TransformCache; CBuffer->Resize(CBuffer->GetElementCount() + 1); } + + if (_secondaryDevice) + { + + } } void RenderModule::OnTransformComponentDestroyed(World& world, Entity entity, TransformComponent& component) @@ -470,13 +468,18 @@ void RenderModule::OnTransformComponentUpdated(World& world, Entity entity, Tran void RenderModule::OnCameraComponentCreated(World& world, Entity entity, CameraComponent& component) { - component._CBufferIndex = _frameConstants[0]->CameraCB->GetElementCount(); + component._CBufferIndex = _primaryResources.FrameConstants[0]->CameraCB->GetElementCount(); - for (auto& constants : _frameConstants) + for (auto& constants : _primaryResources.FrameConstants) { auto& CBuffer = constants->CameraCB; CBuffer->Resize(CBuffer->GetElementCount() + 1); } + + if (_secondaryDevice) + { + + } } void RenderModule::OnCameraComponentDestroyed(World& world, Entity entity, CameraComponent& component) @@ -489,14 +492,14 @@ void RenderModule::OnCameraComponentUpdated(World& world, Entity entity, CameraC void RenderModule::OnRenderComponentCreated(World& world, Entity entity, StaticMeshRenderComponent& component) { - auto& MeshGPUData = _geometryBuffer->_meshCache[component.MeshHandler.GetValue()]; + auto& MeshGPUData = _primaryResources.GeometryBuffer->_meshCache[component.MeshHandler.GetValue()]; for (int i = 0; i < MeshGPUData->SubMeshes.size(); i++) { - component._CBufferIndices.push_back(_frameConstants[0]->InstanceCache->GetElementCount()); - _IndirectCommandsCache->Resize(_IndirectCommandsCache->GetElementCount() + 1); + component._CBufferIndices.push_back(_primaryResources.FrameConstants[0]->InstanceCache->GetElementCount()); + _primaryResources.IndirectCommandsCache->Resize(_primaryResources.IndirectCommandsCache->GetElementCount() + 1); - for (auto& constants : _frameConstants) + for (auto& constants : _primaryResources.FrameConstants) { auto& CBuffer = constants->InstanceCache; CBuffer->Resize(CBuffer->GetElementCount() + 1); @@ -505,6 +508,11 @@ void RenderModule::OnRenderComponentCreated(World& world, Entity entity, StaticM } } + + if (_secondaryDevice) + { + + } } void RenderModule::OnRenderComponentDestroyed(World& world, Entity entity, StaticMeshRenderComponent& component) @@ -527,18 +535,44 @@ GDX12RenderCommandRecorder* RenderModule::GetCommandRecorder() 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); } - UpdateMainCB(); - UpdateMaterialCB(); + _primaryResources.UpdateMainCB(width, height, _timer); + _primaryResources.UpdateMaterialCB(_materials); + + //SecondaryDevice + if (_secondaryDevice) + { + _secondaryResources.CurrFrameConstantsIndex = (_secondaryResources.CurrFrameConstantsIndex + 1) % numFrames; + + auto cmdQueue = _primaryDevice->GetCommandQueue(); + auto& frameConsts = _secondaryResources.FrameConstants[_secondaryResources.CurrFrameConstantsIndex]; + + if (frameConsts->FenceValue > cmdQueue->GetFence()->GetCompletedValue()) + { + cmdQueue->WaitForFenceValue(frameConsts->FenceValue); + } + + _secondaryResources.UpdateMainCB(width, height, _timer); + _secondaryResources.UpdateMaterialCB(_materials); + } } void RenderModule::OnRender() @@ -549,7 +583,7 @@ void RenderModule::OnRender() auto cmdList = cmdQueue->GetCommandList(); auto CurrentBackBuffer = _backBuffer->GetCurrentBuffer(); - auto& CurrentFrameConsts = _frameConstants[_currFrameConstantsIndex]; + auto CurrentFrameConsts = GetCurrentPrimaryFrameConstants(); cmdList->BeginPixEvent("Clear Back Buffer", Colors::Aqua); cmdList->SetViewport(_backBuffer->GetViewport()); @@ -569,28 +603,28 @@ void RenderModule::OnRender() CurrentFrameConsts->VisibleTransparentCommandsCache->GetResource().GetUnorderedAccessBarrier(), CurrentFrameConsts->TransparentDrawCounter->GetResource().GetUnorderedAccessBarrier() }); - cmdList->SetComputeRootSignature(_rootSignatures["BufferClear"].get()); - cmdList->SetPipelineState(_PSOs["BufferClear"]); - cmdList->SetDescriptorHeaps({ _srvuavHeap.get() }); + cmdList->SetComputeRootSignature(_primaryResources.RootSignatures["BufferClear"].get()); + cmdList->SetPipelineState(_primaryResources.PSOs["BufferClear"]); + cmdList->SetDescriptorHeaps({ _primaryResources.SRV_UAV_Heap.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->SetComputeRootSignature(_primaryResources.RootSignatures["Culling"].get()); + cmdList->SetPipelineState(_primaryResources.PSOs["Culling"]); + cmdList->SetDescriptorHeaps({ _primaryResources.SRV_UAV_Heap.get() }); cmdList->SetComputeRootConstantBufferView(0, CurrentFrameConsts->CameraCB-> GetElementAddress(_commandRecorder._cameraCBIndex)); cmdList->SetComputeSRV(0, CurrentFrameConsts->InstanceCache->GetSRV()->GPUHandle); - cmdList->SetComputeSRV(1, _IndirectCommandsCache->GetSRV()->GPUHandle); + cmdList->SetComputeSRV(1, _primaryResources.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->Dispatch((_primaryResources.IndirectCommandsCache->GetElementCount() + 63) / 64, 1, 1); cmdList->ResourceBarrier({ CurrentFrameConsts->VisibleOpaqueCommandsCache->GetResource().GetUAVBarrier(), @@ -603,30 +637,30 @@ void RenderModule::OnRender() cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); - cmdList->SetGraphicsRootSignature(_rootSignatures["OpaquePass"].get()); - cmdList->SetPipelineState(_PSOs["OpaquePass"]); + cmdList->SetGraphicsRootSignature(_primaryResources.RootSignatures["OpaquePass"].get()); + cmdList->SetPipelineState(_primaryResources.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->SetGeometryBuffer(_primaryResources.GeometryBuffer.get()); cmdList->SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - cmdList->SetDescriptorHeaps({ _srvuavHeap.get() }); + cmdList->SetDescriptorHeaps({ _primaryResources.SRV_UAV_Heap.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(), + cmdList->SetGraphicsSRV(3, _primaryResources.SRV_UAV_Heap->GetGPUHandle(Texture2D_StartIndex)); + cmdList->ExecuteIndirect(_primaryResources.CommandSignatures["OpaquePass"].Get(), _primaryResources.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->SetGraphicsRootSignature(_primaryResources.RootSignatures["OpaquePass"].get()); + cmdList->SetPipelineState(_primaryResources.PSOs["TransparentPass"]); cmdList->SetGraphicsRootConstantBufferView(1, CurrentFrameConsts->MainCB->GetElementAddress(0)); cmdList->SetGraphicsRootConstantBufferView(2, CurrentFrameConsts->CameraCB-> GetElementAddress(_commandRecorder._cameraCBIndex)); @@ -638,14 +672,14 @@ void RenderModule::OnRender() cmdList->ClearRenderTargetView(_transparencyAccumTexture.get()); cmdList->ClearRenderTargetView(_transparencyRevealageTexture.get()); - cmdList->SetGeometryBuffer(_geometryBuffer.get()); + cmdList->SetGeometryBuffer(_primaryResources.GeometryBuffer.get()); cmdList->SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - cmdList->SetDescriptorHeaps({ _srvuavHeap.get() }); + cmdList->SetDescriptorHeaps({ _primaryResources.SRV_UAV_Heap.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(), + cmdList->SetGraphicsSRV(3, _primaryResources.SRV_UAV_Heap->GetGPUHandle(Texture2D_StartIndex)); + cmdList->ExecuteIndirect(_primaryResources.CommandSignatures["OpaquePass"].Get(), _primaryResources.IndirectCommandsCache->GetElementCount(), CurrentFrameConsts->VisibleTransparentCommandsCache->GetResource().D3DResource.Get(), 0, CurrentFrameConsts->TransparentDrawCounter->GetResource().D3DResource.Get(), 0); cmdList->EnhancedTextureBarrier({ _transparencyAccumTexture->GetResource()->GetPixelShaderResourceEnhBarrier(), @@ -654,10 +688,10 @@ void RenderModule::OnRender() cmdList->BeginPixEvent("Composition Render Pass", Colors::Bisque); - cmdList->SetGraphicsRootSignature(_rootSignatures["CompositionPass"].get()); - cmdList->SetPipelineState(_PSOs["CompositionPass"]); + cmdList->SetGraphicsRootSignature(_primaryResources.RootSignatures["CompositionPass"].get()); + cmdList->SetPipelineState(_primaryResources.PSOs["CompositionPass"]); cmdList->SetRenderTargets({ CurrentBackBuffer }, _depthStencil.get()); - cmdList->SetDescriptorHeaps({ _srvuavHeap.get() }); + cmdList->SetDescriptorHeaps({ _primaryResources.SRV_UAV_Heap.get() }); cmdList->SetGraphicsSRV(0, _opaqueAccumTexture->GetSRV()->GPUHandle); cmdList->SetGraphicsSRV(1, _transparencyAccumTexture->GetSRV()->GPUHandle); cmdList->SetGraphicsSRV(2, _transparencyRevealageTexture->GetSRV()->GPUHandle); @@ -674,32 +708,20 @@ void RenderModule::OnRender() _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; @@ -717,8 +739,8 @@ void RenderModule::BuildDescHeapsAndBackBuffer() desc2.Height = height; desc2.CreateSRV = true; - desc2.SRV_UAV_Heap = _srvuavHeap.get(); - desc2.SRVHeapIndex = _srvuavHeap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + desc2.SRV_UAV_Heap = _primaryResources.SRV_UAV_Heap.get(); + desc2.SRVHeapIndex = _primaryResources.SRV_UAV_Heap->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; @@ -727,21 +749,21 @@ void RenderModule::BuildDescHeapsAndBackBuffer() desc2.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; desc2.CreateRTV = true; - desc2.RTVHeap = _rtvHeap.get(); - desc2.RTVHeapIndex = _rtvHeap->GetAvailableIndex(); + desc2.RTVHeap = _primaryResources.RTVHeap.get(); + desc2.RTVHeapIndex = _primaryResources.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(); + desc2.SRVHeapIndex = _primaryResources.SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + desc2.RTVHeapIndex = _primaryResources.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(); + desc2.SRVHeapIndex = _primaryResources.SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + desc2.RTVHeapIndex = _primaryResources.RTVHeap->GetAvailableIndex(); _transparencyRevealageTexture = std::make_unique(desc2); } @@ -753,7 +775,7 @@ void RenderModule::BuildRootSignatures() desc.StaticSamplers = GetStaticSamplers(); desc.SRVRanges.push_back(GDX12RootSignatureRange(Texture2D_RangeLength)); desc.Constants.push_back(1); - _rootSignatures["OpaquePass"] = std::make_unique(_primaryDevice.get(), desc); + _primaryResources.RootSignatures["OpaquePass"] = std::make_unique(_primaryDevice.get(), desc); std::vector args; D3D12_INDIRECT_ARGUMENT_DESC argConst = {}; @@ -771,48 +793,48 @@ void RenderModule::BuildRootSignatures() cmdSigDesc.NodeMask = 0; _primaryDevice->GetDevice()->CreateCommandSignature(&cmdSigDesc, - _rootSignatures["OpaquePass"]->GetRootSignature().Get(), - IID_PPV_ARGS(&_commandSignatures["OpaquePass"])); + _primaryResources.RootSignatures["OpaquePass"]->GetRootSignature().Get(), + IID_PPV_ARGS(&_primaryResources.CommandSignatures["OpaquePass"])); GDX12RootSignatureDesc desc3; desc3.NumSingleCBVSlots = 1; desc3.NumSingleSRVSlots = 3; desc3.NumSingleUAVSlots = 4; - _rootSignatures["Culling"] = std::make_unique(_primaryDevice.get(), desc3); + _primaryResources.RootSignatures["Culling"] = std::make_unique(_primaryDevice.get(), desc3); GDX12RootSignatureDesc desc4; desc4.NumSingleUAVSlots = 1; - _rootSignatures["BufferClear"] = std::make_unique(_primaryDevice.get(), desc4); + _primaryResources.RootSignatures["BufferClear"] = std::make_unique(_primaryDevice.get(), desc4); GDX12RootSignatureDesc desc5; desc5.NumSingleSRVSlots = 3; desc5.StaticSamplers = GetStaticSamplers(); - _rootSignatures["CompositionPass"] = std::make_unique(_primaryDevice.get(), desc5); + _primaryResources.RootSignatures["CompositionPass"] = std::make_unique(_primaryDevice.get(), desc5); } void RenderModule::BuildShaders() { auto& Compiler = GDX12ShaderCompiler::GetInstance(); - _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"); + _primaryResources.Shaders["CullingCS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "Culling.hlsl", nullptr, "CS", "cs"); + _primaryResources.Shaders["BufferClearCS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "BufferClear.hlsl", nullptr, "CS", "cs"); - _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"); + _primaryResources.Shaders["OpaquePassVS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "OpaquePass.hlsl", nullptr, "VS", "vs"); + _primaryResources.Shaders["OpaquePassPS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "OpaquePass.hlsl", nullptr, "PS", "ps"); - _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"); + _primaryResources.Shaders["TransparentPassVS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "TransparentPass.hlsl", nullptr, "VS", "vs"); + _primaryResources.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"); + _primaryResources.Shaders["VS_FSQuad"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "FullScreenVS.hlsl", nullptr, "VS", "vs"); + _primaryResources.Shaders["CompositionPassPS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "CompositionPass.hlsl", nullptr, "PS", "ps"); } void RenderModule::BuildPSOs() { D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {}; - desc.InputLayout = { _inputLayouts["Default"].data(), (UINT)_inputLayouts["Default"].size() }; - desc.pRootSignature = _rootSignatures["OpaquePass"]->GetRootSignature().Get(); + desc.InputLayout = { _primaryResources.InputLayouts["Default"].data(), (UINT)_primaryResources.InputLayouts["Default"].size() }; + desc.pRootSignature = _primaryResources.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); @@ -829,34 +851,34 @@ void RenderModule::BuildPSOs() desc.VS = { - reinterpret_cast(_shaders["OpaquePassVS"]->GetBufferPointer()), - _shaders["OpaquePassVS"]->GetBufferSize() + reinterpret_cast(_primaryResources.Shaders["OpaquePassVS"]->GetBufferPointer()), + _primaryResources.Shaders["OpaquePassVS"]->GetBufferSize() }; desc.PS = { - reinterpret_cast(_shaders["OpaquePassPS"]->GetBufferPointer()), - _shaders["OpaquePassPS"]->GetBufferSize() + reinterpret_cast(_primaryResources.Shaders["OpaquePassPS"]->GetBufferPointer()), + _primaryResources.Shaders["OpaquePassPS"]->GetBufferSize() }; - ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_PSOs["OpaquePass"]))); + ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_primaryResources.PSOs["OpaquePass"]))); desc.InputLayout = { nullptr, 0 }; - desc.pRootSignature = _rootSignatures["CompositionPass"]->GetRootSignature().Get(); + desc.pRootSignature = _primaryResources.RootSignatures["CompositionPass"]->GetRootSignature().Get(); desc.DepthStencilState.DepthEnable = false; desc.DepthStencilState.StencilEnable = false; desc.VS = { - reinterpret_cast(_shaders["VS_FSQuad"]->GetBufferPointer()), - _shaders["VS_FSQuad"]->GetBufferSize() + reinterpret_cast(_primaryResources.Shaders["VS_FSQuad"]->GetBufferPointer()), + _primaryResources.Shaders["VS_FSQuad"]->GetBufferSize() }; desc.PS = { - reinterpret_cast(_shaders["CompositionPassPS"]->GetBufferPointer()), - _shaders["CompositionPassPS"]->GetBufferSize() + reinterpret_cast(_primaryResources.Shaders["CompositionPassPS"]->GetBufferPointer()), + _primaryResources.Shaders["CompositionPassPS"]->GetBufferSize() }; - ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_PSOs["CompositionPass"]))); + ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_primaryResources.PSOs["CompositionPass"]))); - desc.InputLayout = { _inputLayouts["Default"].data(), (UINT)_inputLayouts["Default"].size() }; - desc.pRootSignature = _rootSignatures["OpaquePass"]->GetRootSignature().Get(); + desc.InputLayout = { _primaryResources.InputLayouts["Default"].data(), (UINT)_primaryResources.InputLayouts["Default"].size() }; + desc.pRootSignature = _primaryResources.RootSignatures["OpaquePass"]->GetRootSignature().Get(); desc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); // Accumulation desc.BlendState.RenderTarget[0].BlendEnable = true; @@ -888,113 +910,38 @@ void RenderModule::BuildPSOs() desc.DSVFormat = _depthStencil->GetFormat(); desc.VS = { - reinterpret_cast(_shaders["TransparentPassVS"]->GetBufferPointer()), - _shaders["TransparentPassVS"]->GetBufferSize() + reinterpret_cast(_primaryResources.Shaders["TransparentPassVS"]->GetBufferPointer()), + _primaryResources.Shaders["TransparentPassVS"]->GetBufferSize() }; desc.PS = { - reinterpret_cast(_shaders["TransparentPassPS"]->GetBufferPointer()), - _shaders["TransparentPassPS"]->GetBufferSize() + reinterpret_cast(_primaryResources.Shaders["TransparentPassPS"]->GetBufferPointer()), + _primaryResources.Shaders["TransparentPassPS"]->GetBufferSize() }; - ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_PSOs["TransparentPass"]))); + ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_primaryResources.PSOs["TransparentPass"]))); D3D12_COMPUTE_PIPELINE_STATE_DESC desc2 = {}; - desc2.pRootSignature = _rootSignatures["Culling"]->GetRootSignature().Get(); + desc2.pRootSignature = _primaryResources.RootSignatures["Culling"]->GetRootSignature().Get(); desc2.CS = { - reinterpret_cast(_shaders["CullingCS"]->GetBufferPointer()), - _shaders["CullingCS"]->GetBufferSize() + reinterpret_cast(_primaryResources.Shaders["CullingCS"]->GetBufferPointer()), + _primaryResources.Shaders["CullingCS"]->GetBufferSize() }; ThrowIfFailed(_primaryDevice->GetDevice()->CreateComputePipelineState( - &desc2, IID_PPV_ARGS(&_PSOs["Culling"]))); + &desc2, IID_PPV_ARGS(&_primaryResources.PSOs["Culling"]))); D3D12_COMPUTE_PIPELINE_STATE_DESC desc3 = {}; - desc3.pRootSignature = _rootSignatures["BufferClear"]->GetRootSignature().Get(); + desc3.pRootSignature = _primaryResources.RootSignatures["BufferClear"]->GetRootSignature().Get(); desc3.CS = { - reinterpret_cast(_shaders["BufferClearCS"]->GetBufferPointer()), - _shaders["BufferClearCS"]->GetBufferSize() + reinterpret_cast(_primaryResources.Shaders["BufferClearCS"]->GetBufferPointer()), + _primaryResources.Shaders["BufferClearCS"]->GetBufferSize() }; ThrowIfFailed(_primaryDevice->GetDevice()->CreateComputePipelineState( - &desc3, IID_PPV_ARGS(&_PSOs["BufferClear"]))); -} - -void RenderModule::BuildFrameConstants() -{ - for (int i = 0; i < NumFrameConstantVariable.GetValue(); i++) - { - _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)); - } - - _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); -} - -void RenderModule::UpdateMaterialCB() -{ - 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 (material->Diffuse) - { - materialConstants.DiffuseIndex = material->Diffuse->GetSRV()->HeapIndex - Texture2D_StartIndex; - } - 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--; - } - } + &desc3, IID_PPV_ARGS(&_primaryResources.PSOs["BufferClear"]))); } void RenderModule::SubscribeToSceneManager() diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index 3fbd69f..79cac1c 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -21,6 +21,7 @@ + @@ -42,6 +43,7 @@ + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index f300a89..cbb1bc0 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -75,6 +75,9 @@ Header Files + + Header Files + @@ -125,5 +128,17 @@ Source Files + + Source Files + + + + + + + + + + \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h index 1f652f5..d432bff 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h @@ -20,6 +20,12 @@ struct DeviceSpecs size_t SharedSystemMemory; // in bytes }; +enum EDeviceRole +{ + DEVICE_ROLE_PRIMARY, + DEVICE_ROLE_SECONDARY +}; + class GDX12Device : public std::enable_shared_from_this { public: @@ -34,6 +40,7 @@ class GDX12Device : public std::enable_shared_from_this const DeviceSpecs& GetDeviceFeatures(); const bool IsInitialized(); + EDeviceRole Role; private: void CollectDeviceFeatures(); 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/GDX12Material.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h index f73a4ed..8c1b25e 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; + GDX12Texture* SecondaryDeviceTexture; +}; + 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; @@ -35,16 +44,18 @@ class GDX12Material bool UseBakedLighting; MaterialType Type; bool DirtyFlag; - UINT _CBufferIndex; + UINT _PrimaryCBufferIndex; + UINT _SecondaryCBufferIndex; 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), SpecularColor(0.0f, 0.0f, 0.0f), EmissiveColor(0.0f, 0.0f, 0.0f), HasNormalMap(false), HasSpecularMap(false), HasRoughnessMap(false), HasEmissiveMap(false), - UseBakedLighting(false), DirtyFlag(true), _CBufferIndex(0), _numFramesDirty(0), Type(MaterialType::Opaque) + UseBakedLighting(false), DirtyFlag(true), _PrimaryCBufferIndex(0), _SecondaryCBufferIndex(0), _numFramesDirty(0), Type(MaterialType::Opaque) { } diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h index 74a7805..569cfbf 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h @@ -2,6 +2,8 @@ #include "Engine.RendererDX12\D3DHelpers.h" +#include "Engine.Core/Types/TextureTypes.h" + class GDX12Descriptor; class GDX12DescriptorHeap; class GDX12Device; @@ -15,6 +17,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; diff --git a/Engine/Engine.RendererDX12/src/GDX12Device.cpp b/Engine/Engine.RendererDX12/src/GDX12Device.cpp index edbd102..5a29201 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Device.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Device.cpp @@ -6,7 +6,8 @@ GDX12Device::GDX12Device() : _isInitialized(false), _rtvDescriptorSize(0), _dsvDescriptorSize(0), - _cbvSrvUavDescriptorSize(0) + _cbvSrvUavDescriptorSize(0), + Role(DEVICE_ROLE_PRIMARY) { } diff --git a/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp b/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp new file mode 100644 index 0000000..f69b2b3 --- /dev/null +++ b/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp @@ -0,0 +1,108 @@ +#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)); + FrameConstants[i]->VisibleOpaqueCommandsCache->CreateUAV(SRV_UAV_Heap.get(), SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + FrameConstants[i]->OpaqueDrawCounter->CreateUAV(SRV_UAV_Heap.get(), SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + FrameConstants[i]->VisibleTransparentCommandsCache->CreateUAV(SRV_UAV_Heap.get(), SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); + FrameConstants[i]->TransparentDrawCounter->CreateUAV(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) { materialConstants.DiffuseIndex = material->Diffuse->PrimaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + if (material->Normal) { materialConstants.NormalIndex = material->Normal->PrimaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + if (material->Displacement) { materialConstants.DisplacementIndex = material->Displacement->PrimaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + currMaterialCB->CopyData(material->_PrimaryCBufferIndex, materialConstants); + } + else + { + if (material->Diffuse) { materialConstants.DiffuseIndex = material->Diffuse->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + if (material->Normal) { materialConstants.NormalIndex = material->Normal->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + if (material->Displacement) { materialConstants.DisplacementIndex = material->Displacement->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + currMaterialCB->CopyData(material->_SecondaryCBufferIndex, materialConstants); + } + material->_numFramesDirty--; + } + } +} From eef969c0c91ba1b498fff89dee6a523d41fc7bcd Mon Sep 17 00:00:00 2001 From: AMorunov Date: Thu, 25 Jun 2026 14:16:08 +0300 Subject: [PATCH 02/46] Removed unnecessary systems --- Apps/App.Base/App.Base.vcxproj | 3 +- Apps/App.Base/App.Base.vcxproj.filters | 5 +-- .../Include/App.Base/Modules/RenderModule.h | 7 ++-- .../App.Base/Systems/RenderSubmitSystem.h | 23 ----------- Apps/App.Base/src/ECS/WorldLoader.cpp | 1 + Apps/App.Base/src/RenderModule.cpp | 18 ++++----- Apps/App.Base/src/SceneManagerModule.cpp | 2 - .../Engine.RendererDX12.vcxproj | 2 - .../Engine.RendererDX12.vcxproj.filters | 6 --- .../GDX12RenderCommandRecorder.h | 38 ------------------- .../src/GDX12RenderCommandRecorder.cpp | 17 --------- 11 files changed, 15 insertions(+), 107 deletions(-) delete mode 100644 Apps/App.Base/Include/App.Base/Systems/RenderSubmitSystem.h delete mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12RenderCommandRecorder.h delete mode 100644 Engine/Engine.RendererDX12/src/GDX12RenderCommandRecorder.cpp 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/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index f8fa835..89e78cc 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -6,7 +6,6 @@ #include "Engine.RendererDX12/GDX12Device.h" #include "Engine.RendererDX12/GDX12DeviceResources.h" #include "Engine.RendererDX12/GDX12SwapChain.h" -#include "Engine.RendererDX12/GDX12RenderCommandRecorder.h" #include "Engine.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" @@ -51,6 +50,8 @@ class RenderModule final : public Module //Uploads Mesh geometry to GPU void SubmitMesh(const Mesh* mesh, MeshHandle handle); + + void SetActiveCamera(CameraComponent& camera); struct WorldRenderSubscriptions { @@ -90,7 +91,6 @@ class RenderModule final : public Module void OnRenderComponentUpdated(World& world, Entity entity, StaticMeshRenderComponent& component); const float GetAspectRatio(); - GDX12RenderCommandRecorder* GetCommandRecorder(); GDX12FrameConstants* GetCurrentPrimaryFrameConstants(); GDX12FrameConstants* GetCurrentSecondaryFrameConstants(); const GPUMesh* GetPrimaryGPUMesh(MeshHandle handle); @@ -125,8 +125,7 @@ class RenderModule final : public Module std::unordered_map _transformGPUData; std::unordered_map _worldSubscriptions; - - GDX12RenderCommandRecorder _commandRecorder; + UINT _activeCameraCBIndex; std::unique_ptr _primaryDevice; std::unique_ptr _secondaryDevice; 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/ECS/WorldLoader.cpp b/Apps/App.Base/src/ECS/WorldLoader.cpp index 07bb4c0..1cf5981 100644 --- a/Apps/App.Base/src/ECS/WorldLoader.cpp +++ b/Apps/App.Base/src/ECS/WorldLoader.cpp @@ -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 fd076a1..8ed78d6 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -12,7 +12,7 @@ #include "Common/ConsoleVariables.h" RenderModule::RenderModule(Window* window, GameTimer* timer) : - _dualGPUMode(false), _window(window), _timer(timer) + _dualGPUMode(false), _window(window), _timer(timer), _activeCameraCBIndex(0) { } @@ -297,6 +297,11 @@ void RenderModule::SubmitMesh(const Mesh* mesh, MeshHandle handle) if (_secondaryDevice) _secondaryResources.GeometryBuffer->AddMesh(mesh, handle); } +void RenderModule::SetActiveCamera(CameraComponent& camera) +{ + _activeCameraCBIndex = camera._CBufferIndex; +} + TransformCompGPUData& RenderModule::GetTransformGPUData(Entity entity) { return _transformGPUData.at(entity); @@ -528,11 +533,6 @@ const float RenderModule::GetAspectRatio() return _window->GetAspectRatio(); } -GDX12RenderCommandRecorder* RenderModule::GetCommandRecorder() -{ - return &_commandRecorder; -} - void RenderModule::OnUpdate() { uint16_t width, height; @@ -616,7 +616,7 @@ void RenderModule::OnRender() cmdList->SetPipelineState(_primaryResources.PSOs["Culling"]); cmdList->SetDescriptorHeaps({ _primaryResources.SRV_UAV_Heap.get() }); cmdList->SetComputeRootConstantBufferView(0, CurrentFrameConsts->CameraCB-> - GetElementAddress(_commandRecorder._cameraCBIndex)); + GetElementAddress(_activeCameraCBIndex)); cmdList->SetComputeSRV(0, CurrentFrameConsts->InstanceCache->GetSRV()->GPUHandle); cmdList->SetComputeSRV(1, _primaryResources.IndirectCommandsCache->GetSRV()->GPUHandle); cmdList->SetComputeSRV(2, CurrentFrameConsts->MaterialCache->GetSRV()->GPUHandle); @@ -641,7 +641,7 @@ void RenderModule::OnRender() cmdList->SetPipelineState(_primaryResources.PSOs["OpaquePass"]); cmdList->SetGraphicsRootConstantBufferView(1, CurrentFrameConsts->MainCB->GetElementAddress(0)); cmdList->SetGraphicsRootConstantBufferView(2, CurrentFrameConsts->CameraCB-> - GetElementAddress(_commandRecorder._cameraCBIndex)); + GetElementAddress(_activeCameraCBIndex)); cmdList->EnhancedTextureBarrier({ _opaqueAccumTexture->GetResource()->GetRenderTargetEnhBarrier() }); cmdList->SetRenderTargets({ _opaqueAccumTexture.get() }, _depthStencil.get()); cmdList->ClearRenderTargetView(_opaqueAccumTexture.get()); @@ -663,7 +663,7 @@ void RenderModule::OnRender() cmdList->SetPipelineState(_primaryResources.PSOs["TransparentPass"]); cmdList->SetGraphicsRootConstantBufferView(1, CurrentFrameConsts->MainCB->GetElementAddress(0)); cmdList->SetGraphicsRootConstantBufferView(2, CurrentFrameConsts->CameraCB-> - GetElementAddress(_commandRecorder._cameraCBIndex)); + GetElementAddress(_activeCameraCBIndex)); cmdList->EnhancedTextureBarrier({ _transparencyAccumTexture->GetResource()->GetRenderTargetEnhBarrier(), _transparencyRevealageTexture->GetResource()->GetRenderTargetEnhBarrier() }); 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/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index 79cac1c..e1f8344 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -24,7 +24,6 @@ - @@ -45,7 +44,6 @@ - diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index cbb1bc0..4b48d5d 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -66,9 +66,6 @@ Header Files - - Header Files - Header Files @@ -122,9 +119,6 @@ Source Files - - Source Files - Source Files 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/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; -} - - From 4d7677b479a04be21678b91dfc6fe2799033d735 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Thu, 25 Jun 2026 15:01:06 +0300 Subject: [PATCH 03/46] Fixed incorrect device feature collecting --- .../Include/App.Base/Modules/RenderModule.h | 5 +- Apps/App.Base/src/RenderModule.cpp | 7 +- Apps/App.Base/src/SceneManagerModule.cpp | 16 ++--- .../Engine.RendererDX12.vcxproj | 1 + .../Engine.RendererDX12.vcxproj.filters | 3 + .../Include/Engine.RendererDX12/GDX12Device.h | 7 +- .../Engine.RendererDX12/GDX12RenderPass.h | 39 +++++++++++ .../Engine.RendererDX12/src/GDX12Device.cpp | 67 +------------------ .../src/GDX12ShaderCompiler.cpp | 8 ++- 9 files changed, 62 insertions(+), 91 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12RenderPass.h diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index 89e78cc..ceb4c66 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -2,10 +2,9 @@ #include "Common/GameTimer.h" #include "Common/Module.h" -#include "Engine.RendererDX12/D3DHelpers.h" -#include "Engine.RendererDX12/GDX12Device.h" -#include "Engine.RendererDX12/GDX12DeviceResources.h" + #include "Engine.RendererDX12/GDX12SwapChain.h" +#include "Engine.RendererDX12/GDX12RenderPass.h" #include "Engine.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 8ed78d6..a188b52 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -2,12 +2,7 @@ #include "App.Base/Window.h" #include "App.Base/App.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" #include "Common/ConsoleVariables.h" diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index ac114bd..409979e 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - //if (!LoadWorld("world1.yaml")) - //{ - // // todo runtime error or log - //} + if (!LoadWorld("world1.yaml")) + { + // todo runtime error or log + } /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - if (!LoadWorld(scenePath)) - { - // todo runtime error or log - } + //if (!LoadWorld(scenePath)) + //{ + // // todo runtime error or log + //} World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index e1f8344..5ce41cd 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -24,6 +24,7 @@ + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index 4b48d5d..e2fba25 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -75,6 +75,9 @@ Header Files + + Header Files + diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h index d432bff..949ed50 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h @@ -8,16 +8,11 @@ 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 diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12RenderPass.h new file mode 100644 index 0000000..1e461f9 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12RenderPass.h @@ -0,0 +1,39 @@ +#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" + +enum ERenderPassFlags : uint32_t +{ + RENDER_PASS_FLAG_NONE = 0, + RENDER_PASS_FLAG_USE_TEXTURES = 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_PRESENTING = 1 << 4 +}; + +class GDX12RenderPass +{ +public: + GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE) {} + + virtual void Initialize(GDX12Device* device); + virtual void Execute(GDX12CommandList* cmdList); + virtual void Resize(UINT width, UINT height); + + ERenderPassFlags GetFlags() { return _flags; } + +private: + // This will define what resources will be loaded onto respective GPU + // For example: if no RenderPasses use USE_TEXTURES, then GPU texture upload + // will be skipped entirely for this GPU + ERenderPassFlags _flags; +}; diff --git a/Engine/Engine.RendererDX12/src/GDX12Device.cpp b/Engine/Engine.RendererDX12/src/GDX12Device.cpp index 5a29201..faa33f3 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Device.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Device.cpp @@ -55,6 +55,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); @@ -62,71 +64,6 @@ 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() 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"; } From 1713e4dcc561390f3fdfc0b4910dd2f7b5c7a9a6 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Fri, 26 Jun 2026 13:55:54 +0300 Subject: [PATCH 04/46] small fixes --- .../Include/App.Base/Modules/RenderModule.h | 6 +++--- Apps/App.Base/src/App.cpp | 7 ++++++- Apps/App.Base/src/ECS/WorldLoader.cpp | 2 +- Apps/App.Base/src/RenderModule.cpp | 12 ++++++------ .../Engine.RendererDX12.vcxproj | 2 +- .../Engine.RendererDX12.vcxproj.filters | 2 +- .../{ => RenderPasses}/GDX12RenderPass.h | 16 ++++++++-------- .../Engine.RendererDX12/src/GDX12Descriptor.cpp | 2 +- 8 files changed, 27 insertions(+), 22 deletions(-) rename Engine/Engine.RendererDX12/Include/Engine.RendererDX12/{ => RenderPasses}/GDX12RenderPass.h (71%) diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index ceb4c66..0a4f14e 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -4,7 +4,7 @@ #include "Common/Module.h" #include "Engine.RendererDX12/GDX12SwapChain.h" -#include "Engine.RendererDX12/GDX12RenderPass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" #include "Engine.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" @@ -50,7 +50,7 @@ class RenderModule final : public Module //Uploads Mesh geometry to GPU void SubmitMesh(const Mesh* mesh, MeshHandle handle); - void SetActiveCamera(CameraComponent& camera); + void SetActiveCamera(CameraComponent* camera); struct WorldRenderSubscriptions { @@ -124,7 +124,7 @@ class RenderModule final : public Module std::unordered_map _transformGPUData; std::unordered_map _worldSubscriptions; - UINT _activeCameraCBIndex; + CameraComponent* _activeCamera; std::unique_ptr _primaryDevice; std::unique_ptr _secondaryDevice; diff --git a/Apps/App.Base/src/App.cpp b/Apps/App.Base/src/App.cpp index ec8f6ab..a1579ed 100644 --- a/Apps/App.Base/src/App.cpp +++ b/Apps/App.Base/src/App.cpp @@ -60,7 +60,12 @@ App::App(HINSTANCE hInstance) Instance = this; } -App::~App() = default; +App::~App() +{ + //ordering is important + Locator.UnregisterModule(); + Locator.UnregisterModule(); +} HINSTANCE App::GetAppHandler() const { diff --git a/Apps/App.Base/src/ECS/WorldLoader.cpp b/Apps/App.Base/src/ECS/WorldLoader.cpp index 1cf5981..9eaa8e2 100644 --- a/Apps/App.Base/src/ECS/WorldLoader.cpp +++ b/Apps/App.Base/src/ECS/WorldLoader.cpp @@ -1048,7 +1048,7 @@ bool WorldLoader::LoadFromFile(World& world, const std::filesystem::path& path) ); world.ActiveCamera = camera; - renderModule->SetActiveCamera(camera.GetComponent()); + renderModule->SetActiveCamera(&camera.GetComponent()); return true; } diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index a188b52..c2fdb9b 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -7,7 +7,7 @@ #include "Common/ConsoleVariables.h" RenderModule::RenderModule(Window* window, GameTimer* timer) : - _dualGPUMode(false), _window(window), _timer(timer), _activeCameraCBIndex(0) + _dualGPUMode(false), _window(window), _timer(timer), _activeCamera(nullptr) { } @@ -292,9 +292,9 @@ void RenderModule::SubmitMesh(const Mesh* mesh, MeshHandle handle) if (_secondaryDevice) _secondaryResources.GeometryBuffer->AddMesh(mesh, handle); } -void RenderModule::SetActiveCamera(CameraComponent& camera) +void RenderModule::SetActiveCamera(CameraComponent* camera) { - _activeCameraCBIndex = camera._CBufferIndex; + _activeCamera = camera; } TransformCompGPUData& RenderModule::GetTransformGPUData(Entity entity) @@ -611,7 +611,7 @@ void RenderModule::OnRender() cmdList->SetPipelineState(_primaryResources.PSOs["Culling"]); cmdList->SetDescriptorHeaps({ _primaryResources.SRV_UAV_Heap.get() }); cmdList->SetComputeRootConstantBufferView(0, CurrentFrameConsts->CameraCB-> - GetElementAddress(_activeCameraCBIndex)); + GetElementAddress(_activeCamera->_CBufferIndex)); cmdList->SetComputeSRV(0, CurrentFrameConsts->InstanceCache->GetSRV()->GPUHandle); cmdList->SetComputeSRV(1, _primaryResources.IndirectCommandsCache->GetSRV()->GPUHandle); cmdList->SetComputeSRV(2, CurrentFrameConsts->MaterialCache->GetSRV()->GPUHandle); @@ -636,7 +636,7 @@ void RenderModule::OnRender() cmdList->SetPipelineState(_primaryResources.PSOs["OpaquePass"]); cmdList->SetGraphicsRootConstantBufferView(1, CurrentFrameConsts->MainCB->GetElementAddress(0)); cmdList->SetGraphicsRootConstantBufferView(2, CurrentFrameConsts->CameraCB-> - GetElementAddress(_activeCameraCBIndex)); + GetElementAddress(_activeCamera->_CBufferIndex)); cmdList->EnhancedTextureBarrier({ _opaqueAccumTexture->GetResource()->GetRenderTargetEnhBarrier() }); cmdList->SetRenderTargets({ _opaqueAccumTexture.get() }, _depthStencil.get()); cmdList->ClearRenderTargetView(_opaqueAccumTexture.get()); @@ -658,7 +658,7 @@ void RenderModule::OnRender() cmdList->SetPipelineState(_primaryResources.PSOs["TransparentPass"]); cmdList->SetGraphicsRootConstantBufferView(1, CurrentFrameConsts->MainCB->GetElementAddress(0)); cmdList->SetGraphicsRootConstantBufferView(2, CurrentFrameConsts->CameraCB-> - GetElementAddress(_activeCameraCBIndex)); + GetElementAddress(_activeCamera->_CBufferIndex)); cmdList->EnhancedTextureBarrier({ _transparencyAccumTexture->GetResource()->GetRenderTargetEnhBarrier(), _transparencyRevealageTexture->GetResource()->GetRenderTargetEnhBarrier() }); diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index 5ce41cd..d4faeb8 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -24,7 +24,7 @@ - + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index e2fba25..1da643c 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -75,7 +75,7 @@ Header Files - + Header Files diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h similarity index 71% rename from Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12RenderPass.h rename to Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h index 1e461f9..9b4c8f0 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -25,15 +25,15 @@ class GDX12RenderPass public: GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE) {} - virtual void Initialize(GDX12Device* device); - virtual void Execute(GDX12CommandList* cmdList); - virtual void Resize(UINT width, UINT height); + virtual void Initialize(GDX12Device* device) {}; + virtual void Execute(GDX12CommandList* cmdList) {}; + virtual void Resize(UINT width, UINT height) {}; - ERenderPassFlags GetFlags() { return _flags; } + uint32_t GetFlags() { return _flags; } private: - // This will define what resources will be loaded onto respective GPU - // For example: if no RenderPasses use USE_TEXTURES, then GPU texture upload + // 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 - ERenderPassFlags _flags; -}; + uint32_t _flags; +}; \ No newline at end of file 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) From 62f497251a7a264337bdf4bbb65e53e716105ef7 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Fri, 26 Jun 2026 15:30:40 +0300 Subject: [PATCH 05/46] Moved GPU Culling to a separate pass --- .../Include/App.Base/Modules/RenderModule.h | 10 +- Apps/App.Base/src/RenderModule.cpp | 119 ++++++------------ Apps/App.Base/src/SceneManagerModule.cpp | 16 +-- .../Engine.RendererDX12.vcxproj | 1 + .../Engine.RendererDX12.vcxproj.filters | 3 + .../Engine.RendererDX12/GDX12FrameConstants.h | 18 +-- .../RenderPasses/GDX12GPUCullingPass.h | 90 +++++++++++++ .../RenderPasses/GDX12RenderPass.h | 11 +- .../Shaders/BufferClear.hlsl | 7 +- .../src/GDX12DeviceResources.cpp | 4 - .../src/GDX12FrameConstants.cpp | 4 - 11 files changed, 167 insertions(+), 116 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index 0a4f14e..96be333 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -5,6 +5,7 @@ #include "Engine.RendererDX12/GDX12SwapChain.h" #include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h" #include "Engine.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" @@ -22,9 +23,9 @@ using namespace Engine::Core; struct TransformCompGPUData { - UINT CBufferIndex; - UINT NumFramesDirty; - Matrix World; + UINT CBufferIndex = -1; + UINT NumFramesDirty = -1; + Matrix World = Identity4x4(); }; class RenderModule final : public Module @@ -109,6 +110,7 @@ class RenderModule final : public Module void BuildRootSignatures(); void BuildShaders(); void BuildPSOs(); + void ConfigureRenderPipeline(); void SubscribeToSceneManager(); void UnsubscribeFromSceneManager(); @@ -142,4 +144,6 @@ class RenderModule final : public Module std::unique_ptr _opaqueAccumTexture; std::unique_ptr _transparencyAccumTexture; std::unique_ptr _transparencyRevealageTexture; + + GDX12GPUCullingPass _gpuCullingPass; }; \ No newline at end of file diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index c2fdb9b..5dfcc7a 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -48,6 +48,8 @@ void RenderModule::Initialize() BuildPSOs(); SubscribeToSceneManager(); + + ConfigureRenderPipeline(); } void RenderModule::Uninitialize() @@ -474,12 +476,22 @@ void RenderModule::OnCameraComponentCreated(World& world, Entity entity, CameraC { auto& CBuffer = constants->CameraCB; CBuffer->Resize(CBuffer->GetElementCount() + 1); - } - if (_secondaryDevice) - { + 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)); } + + } void RenderModule::OnCameraComponentDestroyed(World& world, Entity entity, CameraComponent& component) @@ -503,8 +515,12 @@ void RenderModule::OnRenderComponentCreated(World& world, Entity entity, StaticM { auto& CBuffer = constants->InstanceCache; CBuffer->Resize(CBuffer->GetElementCount() + 1); - constants->VisibleOpaqueCommandsCache->Resize(constants->VisibleOpaqueCommandsCache->GetElementCount() + 1); - constants->VisibleTransparentCommandsCache->Resize(constants->VisibleTransparentCommandsCache->GetElementCount() + 1); + + for (auto& buffers : constants->CameraVisibilityCommands) + { + buffers.VisibleOpaqueCommandsCache->Resize(buffers.VisibleOpaqueCommandsCache->GetElementCount() + 1); + buffers.VisibleTransparentCommandsCache->Resize(buffers.VisibleTransparentCommandsCache->GetElementCount() + 1); + } } } @@ -590,48 +606,16 @@ void RenderModule::OnRender() 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(_primaryResources.RootSignatures["BufferClear"].get()); - cmdList->SetPipelineState(_primaryResources.PSOs["BufferClear"]); - cmdList->SetDescriptorHeaps({ _primaryResources.SRV_UAV_Heap.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(_primaryResources.RootSignatures["Culling"].get()); - cmdList->SetPipelineState(_primaryResources.PSOs["Culling"]); - cmdList->SetDescriptorHeaps({ _primaryResources.SRV_UAV_Heap.get() }); - cmdList->SetComputeRootConstantBufferView(0, CurrentFrameConsts->CameraCB-> - GetElementAddress(_activeCamera->_CBufferIndex)); - cmdList->SetComputeSRV(0, CurrentFrameConsts->InstanceCache->GetSRV()->GPUHandle); - cmdList->SetComputeSRV(1, _primaryResources.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((_primaryResources.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(); + _gpuCullingPass.Execute(cmdList, _activeCamera->_CBufferIndex); + auto& currentCameraVisBuffers = CurrentFrameConsts->CameraVisibilityCommands[_activeCamera->_CBufferIndex]; cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); + cmdList->ResourceBarrier({ + currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().GetIndirectArgsBarrier(), + currentCameraVisBuffers.OpaqueDrawCounter->GetResource().GetIndirectArgsBarrier(), + currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().GetIndirectArgsBarrier(), + currentCameraVisBuffers.TransparentDrawCounter->GetResource().GetIndirectArgsBarrier() }); cmdList->SetGraphicsRootSignature(_primaryResources.RootSignatures["OpaquePass"].get()); cmdList->SetPipelineState(_primaryResources.PSOs["OpaquePass"]); cmdList->SetGraphicsRootConstantBufferView(1, CurrentFrameConsts->MainCB->GetElementAddress(0)); @@ -648,8 +632,8 @@ void RenderModule::OnRender() cmdList->SetGraphicsSRV(2, CurrentFrameConsts->InstanceCache->GetSRV()->GPUHandle); cmdList->SetGraphicsSRV(3, _primaryResources.SRV_UAV_Heap->GetGPUHandle(Texture2D_StartIndex)); cmdList->ExecuteIndirect(_primaryResources.CommandSignatures["OpaquePass"].Get(), _primaryResources.IndirectCommandsCache->GetElementCount(), - CurrentFrameConsts->VisibleOpaqueCommandsCache->GetResource().D3DResource.Get(), 0, - CurrentFrameConsts->OpaqueDrawCounter->GetResource().D3DResource.Get(), 0); + currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().D3DResource.Get(), 0, + currentCameraVisBuffers.OpaqueDrawCounter->GetResource().D3DResource.Get(), 0); cmdList->EnhancedTextureBarrier({ _opaqueAccumTexture->GetResource()->GetPixelShaderResourceEnhBarrier() }); cmdList->EndPixEvent(); @@ -675,8 +659,8 @@ void RenderModule::OnRender() cmdList->SetGraphicsSRV(2, CurrentFrameConsts->InstanceCache->GetSRV()->GPUHandle); cmdList->SetGraphicsSRV(3, _primaryResources.SRV_UAV_Heap->GetGPUHandle(Texture2D_StartIndex)); cmdList->ExecuteIndirect(_primaryResources.CommandSignatures["OpaquePass"].Get(), _primaryResources.IndirectCommandsCache->GetElementCount(), - CurrentFrameConsts->VisibleTransparentCommandsCache->GetResource().D3DResource.Get(), 0, - CurrentFrameConsts->TransparentDrawCounter->GetResource().D3DResource.Get(), 0); + currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().D3DResource.Get(), 0, + currentCameraVisBuffers.TransparentDrawCounter->GetResource().D3DResource.Get(), 0); cmdList->EnhancedTextureBarrier({ _transparencyAccumTexture->GetResource()->GetPixelShaderResourceEnhBarrier(), _transparencyRevealageTexture->GetResource()->GetPixelShaderResourceEnhBarrier() }); cmdList->EndPixEvent(); @@ -791,16 +775,6 @@ void RenderModule::BuildRootSignatures() _primaryResources.RootSignatures["OpaquePass"]->GetRootSignature().Get(), IID_PPV_ARGS(&_primaryResources.CommandSignatures["OpaquePass"])); - GDX12RootSignatureDesc desc3; - desc3.NumSingleCBVSlots = 1; - desc3.NumSingleSRVSlots = 3; - desc3.NumSingleUAVSlots = 4; - _primaryResources.RootSignatures["Culling"] = std::make_unique(_primaryDevice.get(), desc3); - - GDX12RootSignatureDesc desc4; - desc4.NumSingleUAVSlots = 1; - _primaryResources.RootSignatures["BufferClear"] = std::make_unique(_primaryDevice.get(), desc4); - GDX12RootSignatureDesc desc5; desc5.NumSingleSRVSlots = 3; desc5.StaticSamplers = GetStaticSamplers(); @@ -811,9 +785,6 @@ void RenderModule::BuildShaders() { auto& Compiler = GDX12ShaderCompiler::GetInstance(); - _primaryResources.Shaders["CullingCS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "Culling.hlsl", nullptr, "CS", "cs"); - _primaryResources.Shaders["BufferClearCS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "BufferClear.hlsl", nullptr, "CS", "cs"); - _primaryResources.Shaders["OpaquePassVS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "OpaquePass.hlsl", nullptr, "VS", "vs"); _primaryResources.Shaders["OpaquePassPS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "OpaquePass.hlsl", nullptr, "PS", "ps"); @@ -914,29 +885,11 @@ void RenderModule::BuildPSOs() _primaryResources.Shaders["TransparentPassPS"]->GetBufferSize() }; ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_primaryResources.PSOs["TransparentPass"]))); +} - - D3D12_COMPUTE_PIPELINE_STATE_DESC desc2 = {}; - desc2.pRootSignature = _primaryResources.RootSignatures["Culling"]->GetRootSignature().Get(); - desc2.CS = - { - reinterpret_cast(_primaryResources.Shaders["CullingCS"]->GetBufferPointer()), - _primaryResources.Shaders["CullingCS"]->GetBufferSize() - }; - - ThrowIfFailed(_primaryDevice->GetDevice()->CreateComputePipelineState( - &desc2, IID_PPV_ARGS(&_primaryResources.PSOs["Culling"]))); - - D3D12_COMPUTE_PIPELINE_STATE_DESC desc3 = {}; - desc3.pRootSignature = _primaryResources.RootSignatures["BufferClear"]->GetRootSignature().Get(); - desc3.CS = - { - reinterpret_cast(_primaryResources.Shaders["BufferClearCS"]->GetBufferPointer()), - _primaryResources.Shaders["BufferClearCS"]->GetBufferSize() - }; - - ThrowIfFailed(_primaryDevice->GetDevice()->CreateComputePipelineState( - &desc3, IID_PPV_ARGS(&_primaryResources.PSOs["BufferClear"]))); +void RenderModule::ConfigureRenderPipeline() +{ + _gpuCullingPass.Initialize(&_primaryResources); } void RenderModule::SubscribeToSceneManager() diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index 409979e..ac114bd 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - if (!LoadWorld("world1.yaml")) - { - // todo runtime error or log - } + //if (!LoadWorld("world1.yaml")) + //{ + // // todo runtime error or log + //} /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - //if (!LoadWorld(scenePath)) - //{ - // // todo runtime error or log - //} + if (!LoadWorld(scenePath)) + { + // todo runtime error or log + } World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index d4faeb8..38f7229 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -24,6 +24,7 @@ + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index 1da643c..094dbd1 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -78,6 +78,9 @@ Header Files + + Header Files + 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/RenderPasses/GDX12GPUCullingPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h new file mode 100644 index 0000000..4581534 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h @@ -0,0 +1,90 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" + +class GDX12GPUCullingPass : public GDX12RenderPass +{ +public: + GDX12GPUCullingPass() {} + + void Initialize(GDX12DeviceResources* resources) override + { + _resources = resources; + + // 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 desc1; + desc1.NumSingleCBVSlots = 1; + desc1.NumSingleSRVSlots = 3; + desc1.NumSingleUAVSlots = 4; + _cullingRS = std::make_unique(resources->Device, desc1); + + GDX12RootSignatureDesc desc2; + desc2.NumSingleUAVSlots = 2; + _bufferClearRS = std::make_unique(resources->Device, desc2); + + // Pipeline State Objects + D3D12_COMPUTE_PIPELINE_STATE_DESC desc3 = {}; + desc3.pRootSignature = _cullingRS->GetRootSignature().Get(); + desc3.CS = { reinterpret_cast(_cullingCS->GetBufferPointer()), _cullingCS->GetBufferSize() }; + + ThrowIfFailed(resources->Device->GetDevice()->CreateComputePipelineState( + &desc3, IID_PPV_ARGS(&_cullingPSO))); + + desc3.pRootSignature = _bufferClearRS->GetRootSignature().Get(); + desc3.CS = { reinterpret_cast(_bufferClearCS->GetBufferPointer()), _bufferClearCS->GetBufferSize() }; + + ThrowIfFailed(resources->Device->GetDevice()->CreateComputePipelineState( + &desc3, IID_PPV_ARGS(&_bufferClearPSO))); + } + + void Execute(GDX12CommandList* cmdList, UINT cameraCBIndex) + { + auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[cameraCBIndex]; + + 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(cameraCBIndex)); + 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(); + } + +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/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h index 9b4c8f0..a0177b6 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -13,7 +13,7 @@ enum ERenderPassFlags : uint32_t { RENDER_PASS_FLAG_NONE = 0, - RENDER_PASS_FLAG_USE_TEXTURES = 1 << 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, @@ -23,17 +23,18 @@ enum ERenderPassFlags : uint32_t class GDX12RenderPass { public: - GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE) {} + GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE), _resources(nullptr) {} - virtual void Initialize(GDX12Device* device) {}; - virtual void Execute(GDX12CommandList* cmdList) {}; + virtual void Initialize(GDX12DeviceResources* resources) {}; virtual void Resize(UINT width, UINT height) {}; uint32_t GetFlags() { return _flags; } -private: +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; + + GDX12DeviceResources* _resources; }; \ No newline at end of file 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/src/GDX12DeviceResources.cpp b/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp index f69b2b3..92a4489 100644 --- a/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp @@ -44,10 +44,6 @@ void GDX12DeviceResources::Initialize(GDX12Device* 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)); - FrameConstants[i]->VisibleOpaqueCommandsCache->CreateUAV(SRV_UAV_Heap.get(), SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); - FrameConstants[i]->OpaqueDrawCounter->CreateUAV(SRV_UAV_Heap.get(), SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); - FrameConstants[i]->VisibleTransparentCommandsCache->CreateUAV(SRV_UAV_Heap.get(), SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); - FrameConstants[i]->TransparentDrawCounter->CreateUAV(SRV_UAV_Heap.get(), SRV_UAV_Heap->GetAvailableIndex(ConstantsResources)); } IndirectCommandsCache = std::make_unique>(device, 0, EBufferType::Upload, false); 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() From 16a101ef37f83477d06ae87df44880a538f411dd Mon Sep 17 00:00:00 2001 From: AMorunov Date: Sat, 27 Jun 2026 13:39:31 +0300 Subject: [PATCH 06/46] =?UTF-8?q?Moved=20part=20of=20RenderPasses=20to=20s?= =?UTF-8?q?eparate=20class=20=E2=84=961?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Include/App.Base/Modules/RenderModule.h | 4 ++ Apps/App.Base/src/RenderModule.cpp | 55 ++------------- .../Engine.RendererDX12.vcxproj | 2 + .../Engine.RendererDX12.vcxproj.filters | 6 ++ .../Engine.RendererDX12/GDX12Texture.h | 5 ++ .../RenderPasses/GDX12BackBufferClearPass.h | 26 +++++++ .../RenderPasses/GDX12GPUCullingPass.h | 36 +++++----- .../RenderPasses/GDX12RenderPass.h | 1 - .../RenderPasses/GDX12WBOITCompositionPass.h | 69 +++++++++++++++++++ .../Engine.RendererDX12/src/GDX12Texture.cpp | 28 ++++++++ 10 files changed, 165 insertions(+), 67 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index 96be333..cd88b7c 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -6,6 +6,8 @@ #include "Engine.RendererDX12/GDX12SwapChain.h" #include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" #include "Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h" +#include "Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h" #include "Engine.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" @@ -146,4 +148,6 @@ class RenderModule final : public Module std::unique_ptr _transparencyRevealageTexture; GDX12GPUCullingPass _gpuCullingPass; + GDX12BackBufferClearPass _backBufferClearPass; + GDX12WBOITCompositionPass _WBOITCompositionPass; }; \ No newline at end of file diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 5dfcc7a..8a3ff7b 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -42,14 +42,12 @@ void RenderModule::Initialize() } BuildBackBuffer(); - BuildRootSignatures(); BuildShaders(); BuildPSOs(); + ConfigureRenderPipeline(); SubscribeToSceneManager(); - - ConfigureRenderPipeline(); } void RenderModule::Uninitialize() @@ -596,16 +594,7 @@ void RenderModule::OnRender() auto CurrentBackBuffer = _backBuffer->GetCurrentBuffer(); auto CurrentFrameConsts = GetCurrentPrimaryFrameConstants(); - 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(); - + _backBufferClearPass.Execute(cmdList, CurrentBackBuffer, _depthStencil.get()); _gpuCullingPass.Execute(cmdList, _activeCamera->_CBufferIndex); auto& currentCameraVisBuffers = CurrentFrameConsts->CameraVisibilityCommands[_activeCamera->_CBufferIndex]; @@ -665,18 +654,8 @@ void RenderModule::OnRender() _transparencyRevealageTexture->GetResource()->GetPixelShaderResourceEnhBarrier() }); cmdList->EndPixEvent(); - - cmdList->BeginPixEvent("Composition Render Pass", Colors::Bisque); - cmdList->SetGraphicsRootSignature(_primaryResources.RootSignatures["CompositionPass"].get()); - cmdList->SetPipelineState(_primaryResources.PSOs["CompositionPass"]); - cmdList->SetRenderTargets({ CurrentBackBuffer }, _depthStencil.get()); - cmdList->SetDescriptorHeaps({ _primaryResources.SRV_UAV_Heap.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(); + _WBOITCompositionPass.Execute(cmdList, _opaqueAccumTexture.get(), _transparencyAccumTexture.get(), + _transparencyRevealageTexture.get(), CurrentBackBuffer); cmdList->EnhancedTextureBarrier({ CurrentBackBuffer->GetResource()->GetPresentEnhBarrier() }); cmdList->ResourceBarrier({ _depthStencil->GetResource()->GetCommonBarrier() }); @@ -774,11 +753,6 @@ void RenderModule::BuildRootSignatures() _primaryDevice->GetDevice()->CreateCommandSignature(&cmdSigDesc, _primaryResources.RootSignatures["OpaquePass"]->GetRootSignature().Get(), IID_PPV_ARGS(&_primaryResources.CommandSignatures["OpaquePass"])); - - GDX12RootSignatureDesc desc5; - desc5.NumSingleSRVSlots = 3; - desc5.StaticSamplers = GetStaticSamplers(); - _primaryResources.RootSignatures["CompositionPass"] = std::make_unique(_primaryDevice.get(), desc5); } void RenderModule::BuildShaders() @@ -790,9 +764,6 @@ void RenderModule::BuildShaders() _primaryResources.Shaders["TransparentPassVS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "TransparentPass.hlsl", nullptr, "VS", "vs"); _primaryResources.Shaders["TransparentPassPS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "TransparentPass.hlsl", nullptr, "PS", "ps"); - - _primaryResources.Shaders["VS_FSQuad"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "FullScreenVS.hlsl", nullptr, "VS", "vs"); - _primaryResources.Shaders["CompositionPassPS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "CompositionPass.hlsl", nullptr, "PS", "ps"); } void RenderModule::BuildPSOs() @@ -827,22 +798,6 @@ void RenderModule::BuildPSOs() }; ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_primaryResources.PSOs["OpaquePass"]))); - desc.InputLayout = { nullptr, 0 }; - desc.pRootSignature = _primaryResources.RootSignatures["CompositionPass"]->GetRootSignature().Get(); - desc.DepthStencilState.DepthEnable = false; - desc.DepthStencilState.StencilEnable = false; - desc.VS = - { - reinterpret_cast(_primaryResources.Shaders["VS_FSQuad"]->GetBufferPointer()), - _primaryResources.Shaders["VS_FSQuad"]->GetBufferSize() - }; - desc.PS = - { - reinterpret_cast(_primaryResources.Shaders["CompositionPassPS"]->GetBufferPointer()), - _primaryResources.Shaders["CompositionPassPS"]->GetBufferSize() - }; - ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_primaryResources.PSOs["CompositionPass"]))); - desc.InputLayout = { _primaryResources.InputLayouts["Default"].data(), (UINT)_primaryResources.InputLayouts["Default"].size() }; desc.pRootSignature = _primaryResources.RootSignatures["OpaquePass"]->GetRootSignature().Get(); desc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); @@ -890,6 +845,8 @@ void RenderModule::BuildPSOs() void RenderModule::ConfigureRenderPipeline() { _gpuCullingPass.Initialize(&_primaryResources); + _backBufferClearPass.Initialize(&_primaryResources); + _WBOITCompositionPass.Initialize(&_primaryResources, _backBuffer->GetFormat()); } void RenderModule::SubscribeToSceneManager() diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index 38f7229..dfd771b 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -24,6 +24,7 @@ + @@ -41,6 +42,7 @@ + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index 094dbd1..18bf8a7 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -81,6 +81,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h index 569cfbf..8d75b88 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h @@ -80,6 +80,8 @@ class GDX12Texture GDX12TextureResource* GetResource(); DXGI_FORMAT GetFormat(); ETextureSemantic GetSemantic() const; + D3D12_VIEWPORT GetViewport(); + D3D12_RECT GetScissorRect(); private: @@ -95,4 +97,7 @@ class GDX12Texture std::unique_ptr _uav; std::unique_ptr _dsv; D3D12_CLEAR_VALUE _clearValue; + + D3D12_VIEWPORT _viewport; + D3D12_RECT _scissorRect; }; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h new file mode 100644 index 0000000..4284575 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h @@ -0,0 +1,26 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" + +class GDX12BackBufferClearPass : public GDX12RenderPass +{ +public: + GDX12BackBufferClearPass() { _flags = RENDER_PASS_FLAG_PRESENTING; } + + void Initialize(GDX12DeviceResources* resources) + { + _resources = resources; + } + + void Execute(GDX12CommandList* cmdList, GDX12Texture* IN_OUT_currentBackBuffer, GDX12Texture* IN_OUT_depthStencil) + { + cmdList->BeginPixEvent("Clear Back Buffer", Colors::Aqua); + cmdList->SetViewport(IN_OUT_currentBackBuffer->GetViewport()); + cmdList->SetScissorRect(IN_OUT_currentBackBuffer->GetScissorRect()); + cmdList->EnhancedTextureBarrier({ IN_OUT_currentBackBuffer->GetResource()->GetRenderTargetEnhBarrier() }); + cmdList->ResourceBarrier({ IN_OUT_depthStencil->GetResource()->GetDepthWriteBarrier() }); + cmdList->SetRenderTargets({ IN_OUT_currentBackBuffer }, IN_OUT_depthStencil); + cmdList->ClearRenderTargetView(IN_OUT_currentBackBuffer); + cmdList->ClearDepthStencilView(IN_OUT_depthStencil); + cmdList->EndPixEvent(); + } +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h index 4581534..5166910 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h @@ -4,9 +4,9 @@ class GDX12GPUCullingPass : public GDX12RenderPass { public: - GDX12GPUCullingPass() {} + GDX12GPUCullingPass() { _flags = RENDER_PASS_FLAG_USE_CAMERAS; } - void Initialize(GDX12DeviceResources* resources) override + void Initialize(GDX12DeviceResources* resources) { _resources = resources; @@ -16,31 +16,33 @@ class GDX12GPUCullingPass : public GDX12RenderPass _bufferClearCS = shaderCompiler.CompileShader(resources->Device, SHADERS_FOLDER "BufferClear.hlsl", nullptr, "CS", "cs"); // Root Signatures - GDX12RootSignatureDesc desc1; - desc1.NumSingleCBVSlots = 1; - desc1.NumSingleSRVSlots = 3; - desc1.NumSingleUAVSlots = 4; - _cullingRS = std::make_unique(resources->Device, desc1); + GDX12RootSignatureDesc RSDesc1; + RSDesc1.NumSingleCBVSlots = 1; + RSDesc1.NumSingleSRVSlots = 3; + RSDesc1.NumSingleUAVSlots = 4; + _cullingRS = std::make_unique(resources->Device, RSDesc1); - GDX12RootSignatureDesc desc2; - desc2.NumSingleUAVSlots = 2; - _bufferClearRS = std::make_unique(resources->Device, desc2); + GDX12RootSignatureDesc RSDesc2; + RSDesc2.NumSingleUAVSlots = 2; + _bufferClearRS = std::make_unique(resources->Device, RSDesc2); // Pipeline State Objects - D3D12_COMPUTE_PIPELINE_STATE_DESC desc3 = {}; - desc3.pRootSignature = _cullingRS->GetRootSignature().Get(); - desc3.CS = { reinterpret_cast(_cullingCS->GetBufferPointer()), _cullingCS->GetBufferSize() }; + D3D12_COMPUTE_PIPELINE_STATE_DESC PSODesc1 = {}; + PSODesc1.pRootSignature = _cullingRS->GetRootSignature().Get(); + PSODesc1.CS = { reinterpret_cast(_cullingCS->GetBufferPointer()), _cullingCS->GetBufferSize() }; ThrowIfFailed(resources->Device->GetDevice()->CreateComputePipelineState( - &desc3, IID_PPV_ARGS(&_cullingPSO))); + &PSODesc1, IID_PPV_ARGS(&_cullingPSO))); - desc3.pRootSignature = _bufferClearRS->GetRootSignature().Get(); - desc3.CS = { reinterpret_cast(_bufferClearCS->GetBufferPointer()), _bufferClearCS->GetBufferSize() }; + D3D12_COMPUTE_PIPELINE_STATE_DESC PSODesc2 = {}; + PSODesc2.pRootSignature = _bufferClearRS->GetRootSignature().Get(); + PSODesc2.CS = { reinterpret_cast(_bufferClearCS->GetBufferPointer()), _bufferClearCS->GetBufferSize() }; ThrowIfFailed(resources->Device->GetDevice()->CreateComputePipelineState( - &desc3, IID_PPV_ARGS(&_bufferClearPSO))); + &PSODesc2, IID_PPV_ARGS(&_bufferClearPSO))); } + // automatically uses IN_OUT_CameraVisibilityBuffers from cameraCBIndex void Execute(GDX12CommandList* cmdList, UINT cameraCBIndex) { auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h index a0177b6..8dedff3 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -25,7 +25,6 @@ class GDX12RenderPass public: GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE), _resources(nullptr) {} - virtual void Initialize(GDX12DeviceResources* resources) {}; virtual void Resize(UINT width, UINT height) {}; uint32_t GetFlags() { return _flags; } 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..7de453e --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h @@ -0,0 +1,69 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" + +class GDX12WBOITCompositionPass : public GDX12RenderPass +{ +public: + GDX12WBOITCompositionPass() { _flags = RENDER_PASS_FLAG_NONE; } + + void Initialize(GDX12DeviceResources* resources, DXGI_FORMAT OUT_Format) + { + _resources = resources; + + // 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_Format; + 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, GDX12Texture* IN_OpaqueScene, GDX12Texture* IN_TransparencyAccum, + GDX12Texture* IN_Revealage, GDX12Texture* OUT_Result) + { + 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->SetRenderTargets({ OUT_Result }, nullptr); + cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); + cmdList->SetGraphicsSRV(0, IN_OpaqueScene->GetSRV()->GPUHandle); + cmdList->SetGraphicsSRV(1, IN_TransparencyAccum->GetSRV()->GPUHandle); + cmdList->SetGraphicsSRV(2, IN_Revealage->GetSRV()->GPUHandle); + cmdList->GetCommandList()->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + cmdList->GetCommandList()->DrawInstanced(3, 1, 0, 0); + cmdList->EndPixEvent(); + } +private: + ComPtr _compositionVS; + ComPtr _compositionPS; + std::unique_ptr _compositionRS; + ComPtr _compositionPSO; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/src/GDX12Texture.cpp b/Engine/Engine.RendererDX12/src/GDX12Texture.cpp index 1fd474a..6dba5d5 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Texture.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Texture.cpp @@ -45,6 +45,15 @@ GDX12Texture::GDX12Texture(GDX12TextureDesc desc) : 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) }; } void GDX12Texture::Resize(UINT width, UINT height) @@ -53,6 +62,15 @@ 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() @@ -99,6 +117,16 @@ ETextureSemantic GDX12Texture::GetSemantic() const return _desc.Semantic; } +D3D12_VIEWPORT GDX12Texture::GetViewport() +{ + return _viewport; +} + +D3D12_RECT GDX12Texture::GetScissorRect() +{ + return _scissorRect; +} + void GDX12Texture::CreateResource() { D3D12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D( From 7f7a3d985298a9061cc6df895252378c2e017183 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Sat, 27 Jun 2026 21:43:31 +0300 Subject: [PATCH 07/46] Moved all render passes to separate classes --- .../Include/App.Base/Modules/RenderModule.h | 19 +- Apps/App.Base/src/RenderModule.cpp | 235 ++---------------- .../Engine.RendererDX12.vcxproj | 2 + .../Engine.RendererDX12.vcxproj.filters | 6 + .../Engine.RendererDX12/GDX12Resource.h | 1 + .../RenderPasses/GDX12GPUCullingPass.h | 6 +- .../RenderPasses/GDX12OpaquePass.h | 148 +++++++++++ .../RenderPasses/GDX12WBOITCompositionPass.h | 8 +- .../RenderPasses/GDX12WBOITTransparencyPass.h | 189 ++++++++++++++ .../Engine.RendererDX12/src/GDX12Resource.cpp | 8 + 10 files changed, 389 insertions(+), 233 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index cd88b7c..0ac5869 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -5,8 +5,10 @@ #include "Engine.RendererDX12/GDX12SwapChain.h" #include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" -#include "Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h" #include "Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.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.Core/ECS/Entity.h" @@ -109,9 +111,6 @@ class RenderModule final : public Module private: void BuildBackBuffer(); - void BuildRootSignatures(); - void BuildShaders(); - void BuildPSOs(); void ConfigureRenderPipeline(); void SubscribeToSceneManager(); @@ -143,11 +142,13 @@ class RenderModule final : public Module std::unique_ptr _backBuffer; std::unique_ptr _depthStencil; - std::unique_ptr _opaqueAccumTexture; - std::unique_ptr _transparencyAccumTexture; - std::unique_ptr _transparencyRevealageTexture; - - GDX12GPUCullingPass _gpuCullingPass; GDX12BackBufferClearPass _backBufferClearPass; + GDX12GPUCullingPass _gpuCullingPass; + GDX12OpaquePass _opaquePass; + GDX12WBOITTransparencyPass _WBOITTransparencyPass; GDX12WBOITCompositionPass _WBOITCompositionPass; + + // in case we need a foreach + std::vector _renderPassPtrs = { &_backBufferClearPass, &_gpuCullingPass, &_opaquePass, + &_WBOITTransparencyPass, &_WBOITCompositionPass }; }; \ No newline at end of file diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 8a3ff7b..a81ca70 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -42,9 +42,6 @@ void RenderModule::Initialize() } BuildBackBuffer(); - BuildRootSignatures(); - BuildShaders(); - BuildPSOs(); ConfigureRenderPipeline(); SubscribeToSceneManager(); @@ -65,9 +62,7 @@ void RenderModule::OnResize() const _backBuffer->Resize(width, height); _depthStencil->Resize(width, height); - _opaqueAccumTexture->Resize(width, height); - _transparencyAccumTexture->Resize(width, height); - _transparencyRevealageTexture->Resize(width, height); + for (auto& renderPass : _renderPassPtrs) { renderPass->Resize(width, height); } } GDX12Material* RenderModule::GetMaterialByName(const std::string& name) @@ -597,65 +592,17 @@ void RenderModule::OnRender() _backBufferClearPass.Execute(cmdList, CurrentBackBuffer, _depthStencil.get()); _gpuCullingPass.Execute(cmdList, _activeCamera->_CBufferIndex); - auto& currentCameraVisBuffers = CurrentFrameConsts->CameraVisibilityCommands[_activeCamera->_CBufferIndex]; - - cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); - cmdList->ResourceBarrier({ - currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().GetIndirectArgsBarrier(), - currentCameraVisBuffers.OpaqueDrawCounter->GetResource().GetIndirectArgsBarrier(), - currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().GetIndirectArgsBarrier(), - currentCameraVisBuffers.TransparentDrawCounter->GetResource().GetIndirectArgsBarrier() }); - cmdList->SetGraphicsRootSignature(_primaryResources.RootSignatures["OpaquePass"].get()); - cmdList->SetPipelineState(_primaryResources.PSOs["OpaquePass"]); - cmdList->SetGraphicsRootConstantBufferView(1, CurrentFrameConsts->MainCB->GetElementAddress(0)); - cmdList->SetGraphicsRootConstantBufferView(2, CurrentFrameConsts->CameraCB-> - GetElementAddress(_activeCamera->_CBufferIndex)); - cmdList->EnhancedTextureBarrier({ _opaqueAccumTexture->GetResource()->GetRenderTargetEnhBarrier() }); - cmdList->SetRenderTargets({ _opaqueAccumTexture.get() }, _depthStencil.get()); - cmdList->ClearRenderTargetView(_opaqueAccumTexture.get()); - cmdList->SetGeometryBuffer(_primaryResources.GeometryBuffer.get()); - cmdList->SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - cmdList->SetDescriptorHeaps({ _primaryResources.SRV_UAV_Heap.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, _primaryResources.SRV_UAV_Heap->GetGPUHandle(Texture2D_StartIndex)); - cmdList->ExecuteIndirect(_primaryResources.CommandSignatures["OpaquePass"].Get(), _primaryResources.IndirectCommandsCache->GetElementCount(), - currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().D3DResource.Get(), 0, - currentCameraVisBuffers.OpaqueDrawCounter->GetResource().D3DResource.Get(), 0); - cmdList->EnhancedTextureBarrier({ _opaqueAccumTexture->GetResource()->GetPixelShaderResourceEnhBarrier() }); - cmdList->EndPixEvent(); - - cmdList->BeginPixEvent("Transparent Render Pass", Colors::Aqua); - cmdList->SetGraphicsRootSignature(_primaryResources.RootSignatures["OpaquePass"].get()); - cmdList->SetPipelineState(_primaryResources.PSOs["TransparentPass"]); - cmdList->SetGraphicsRootConstantBufferView(1, CurrentFrameConsts->MainCB->GetElementAddress(0)); - cmdList->SetGraphicsRootConstantBufferView(2, CurrentFrameConsts->CameraCB-> - GetElementAddress(_activeCamera->_CBufferIndex)); - 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(_primaryResources.GeometryBuffer.get()); - cmdList->SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - cmdList->SetDescriptorHeaps({ _primaryResources.SRV_UAV_Heap.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, _primaryResources.SRV_UAV_Heap->GetGPUHandle(Texture2D_StartIndex)); - cmdList->ExecuteIndirect(_primaryResources.CommandSignatures["OpaquePass"].Get(), _primaryResources.IndirectCommandsCache->GetElementCount(), - currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().D3DResource.Get(), 0, - currentCameraVisBuffers.TransparentDrawCounter->GetResource().D3DResource.Get(), 0); - cmdList->EnhancedTextureBarrier({ _transparencyAccumTexture->GetResource()->GetPixelShaderResourceEnhBarrier(), - _transparencyRevealageTexture->GetResource()->GetPixelShaderResourceEnhBarrier() }); - cmdList->EndPixEvent(); - - _WBOITCompositionPass.Execute(cmdList, _opaqueAccumTexture.get(), _transparencyAccumTexture.get(), - _transparencyRevealageTexture.get(), CurrentBackBuffer); + GDX12Texture* opaqueAccum; + _opaquePass.Execute(cmdList, _activeCamera->_CBufferIndex, _depthStencil.get(), + opaqueAccum); + + GDX12Texture* transparencyAccum; + GDX12Texture* transparencyRevealage; + _WBOITTransparencyPass.Execute(cmdList, _activeCamera->_CBufferIndex, _depthStencil.get(), + transparencyAccum, transparencyRevealage); + + _WBOITCompositionPass.Execute(cmdList, opaqueAccum, transparencyAccum, + transparencyRevealage, CurrentBackBuffer); cmdList->EnhancedTextureBarrier({ CurrentBackBuffer->GetResource()->GetPresentEnhBarrier() }); cmdList->ResourceBarrier({ _depthStencil->GetResource()->GetCommonBarrier() }); @@ -689,163 +636,17 @@ void RenderModule::BuildBackBuffer() 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 = _primaryResources.SRV_UAV_Heap.get(); - desc2.SRVHeapIndex = _primaryResources.SRV_UAV_Heap->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 = _primaryResources.RTVHeap.get(); - desc2.RTVHeapIndex = _primaryResources.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 = _primaryResources.SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); - desc2.RTVHeapIndex = _primaryResources.RTVHeap->GetAvailableIndex(); - _transparencyAccumTexture = std::make_unique(desc2); - - desc2.Format = desc2.RTVDesc.Format = desc2.SRVDesc.Format = DXGI_FORMAT_R16_FLOAT; - desc2.SRVHeapIndex = _primaryResources.SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); - desc2.RTVHeapIndex = _primaryResources.RTVHeap->GetAvailableIndex(); - _transparencyRevealageTexture = std::make_unique(desc2); -} - -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); - _primaryResources.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, - _primaryResources.RootSignatures["OpaquePass"]->GetRootSignature().Get(), - IID_PPV_ARGS(&_primaryResources.CommandSignatures["OpaquePass"])); -} - -void RenderModule::BuildShaders() -{ - auto& Compiler = GDX12ShaderCompiler::GetInstance(); - - _primaryResources.Shaders["OpaquePassVS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "OpaquePass.hlsl", nullptr, "VS", "vs"); - _primaryResources.Shaders["OpaquePassPS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "OpaquePass.hlsl", nullptr, "PS", "ps"); - - _primaryResources.Shaders["TransparentPassVS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "TransparentPass.hlsl", nullptr, "VS", "vs"); - _primaryResources.Shaders["TransparentPassPS"] = Compiler.CompileShader(_primaryDevice.get(), SHADERS_FOLDER "TransparentPass.hlsl", nullptr, "PS", "ps"); -} - -void RenderModule::BuildPSOs() -{ - D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {}; - - desc.InputLayout = { _primaryResources.InputLayouts["Default"].data(), (UINT)_primaryResources.InputLayouts["Default"].size() }; - desc.pRootSignature = _primaryResources.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(_primaryResources.Shaders["OpaquePassVS"]->GetBufferPointer()), - _primaryResources.Shaders["OpaquePassVS"]->GetBufferSize() - }; - desc.PS = - { - reinterpret_cast(_primaryResources.Shaders["OpaquePassPS"]->GetBufferPointer()), - _primaryResources.Shaders["OpaquePassPS"]->GetBufferSize() - }; - ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_primaryResources.PSOs["OpaquePass"]))); - - desc.InputLayout = { _primaryResources.InputLayouts["Default"].data(), (UINT)_primaryResources.InputLayouts["Default"].size() }; - desc.pRootSignature = _primaryResources.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(_primaryResources.Shaders["TransparentPassVS"]->GetBufferPointer()), - _primaryResources.Shaders["TransparentPassVS"]->GetBufferSize() - }; - desc.PS = - { - reinterpret_cast(_primaryResources.Shaders["TransparentPassPS"]->GetBufferPointer()), - _primaryResources.Shaders["TransparentPassPS"]->GetBufferSize() - }; - ThrowIfFailed(_primaryDevice->GetDevice()->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&_primaryResources.PSOs["TransparentPass"]))); } void RenderModule::ConfigureRenderPipeline() { - _gpuCullingPass.Initialize(&_primaryResources); + uint16_t width, height; + _window->GetWindowSize(width, height); + _backBufferClearPass.Initialize(&_primaryResources); + _gpuCullingPass.Initialize(&_primaryResources); + _opaquePass.Initialize(&_primaryResources, _backBuffer->GetFormat(), _depthStencil->GetFormat(), width, height); + _WBOITTransparencyPass.Initialize(&_primaryResources, _backBuffer->GetFormat(), _depthStencil->GetFormat(), width, height); _WBOITCompositionPass.Initialize(&_primaryResources, _backBuffer->GetFormat()); } diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index dfd771b..b720d6d 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -24,6 +24,8 @@ + + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index 18bf8a7..3057c75 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -87,6 +87,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h index a544a79..b1efe47 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h @@ -23,6 +23,7 @@ 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(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h index 5166910..f1ae73d 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h @@ -43,10 +43,10 @@ class GDX12GPUCullingPass : public GDX12RenderPass } // automatically uses IN_OUT_CameraVisibilityBuffers from cameraCBIndex - void Execute(GDX12CommandList* cmdList, UINT cameraCBIndex) + void Execute(GDX12CommandList* cmdList, UINT IN_CameraCBIndex) { auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; - auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[cameraCBIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[IN_CameraCBIndex]; cmdList->BeginPixEvent("GPU Mesh Culling", Colors::Blue); cmdList->ResourceBarrier({ @@ -65,7 +65,7 @@ class GDX12GPUCullingPass : public GDX12RenderPass cmdList->SetComputeRootSignature(_cullingRS.get()); cmdList->SetPipelineState(_cullingPSO); cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); - cmdList->SetComputeRootConstantBufferView(0, currentFrameConstants->CameraCB->GetElementAddress(cameraCBIndex)); + cmdList->SetComputeRootConstantBufferView(0, currentFrameConstants->CameraCB->GetElementAddress(IN_CameraCBIndex)); cmdList->SetComputeSRV(0, currentFrameConstants->InstanceCache->GetSRV()->GPUHandle); cmdList->SetComputeSRV(1, _resources->IndirectCommandsCache->GetSRV()->GPUHandle); cmdList->SetComputeSRV(2, currentFrameConstants->MaterialCache->GetSRV()->GPUHandle); 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..dd8dcbf --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -0,0 +1,148 @@ +#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; + } + + void Initialize(GDX12DeviceResources* resources, DXGI_FORMAT outRTVformat, DXGI_FORMAT outDSVFormat, UINT outWidth, UINT outHeight) + { + _resources = resources; + + // Textures + GDX12TextureDesc TextureDesc1; + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + TextureDesc1.Width = outWidth; + TextureDesc1.Height = outHeight; + + 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; + + _accumulationTexture = std::make_unique(TextureDesc1); + + // 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 = 1; + PSODesc1.RTVFormats[0] = outRTVformat; + PSODesc1.SampleDesc.Count = 1; + PSODesc1.SampleDesc.Quality = 0; + PSODesc1.DSVFormat = outDSVFormat; + 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, UINT IN_CameraCBIndex, GDX12Texture* IN_DepthStencil, + GDX12Texture*& OUT_Accumulation) + { + auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[IN_CameraCBIndex]; + + cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); + cmdList->ResourceBarrier({ + currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().GetIndirectArgsBarrier(), + currentCameraVisBuffers.OpaqueDrawCounter->GetResource().GetIndirectArgsBarrier() }); + cmdList->SetGraphicsRootSignature(_opaqueRS.get()); + cmdList->SetPipelineState(_opaquePSO.Get()); + cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); + cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> + GetElementAddress(IN_CameraCBIndex)); + cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier() }); + cmdList->SetRenderTargets({ _accumulationTexture.get() }, IN_DepthStencil); + cmdList->ClearRenderTargetView(_accumulationTexture.get()); + 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->ExecuteIndirect(_opaqueCS.Get(), _resources->IndirectCommandsCache->GetElementCount(), + currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().D3DResource.Get(), 0, + currentCameraVisBuffers.OpaqueDrawCounter->GetResource().D3DResource.Get(), 0); + cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetSRVBarrier() }); + cmdList->EndPixEvent(); + + OUT_Accumulation = _accumulationTexture.get(); + } + + void Resize(UINT width, UINT height) override + { + _accumulationTexture->Resize(width, height); + } + +private: + ComPtr _opaqueVS; + ComPtr _opaquePS; + std::unique_ptr _opaqueRS; + ComPtr _opaqueCS; + ComPtr _opaquePSO; + + std::unique_ptr _accumulationTexture; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h index 7de453e..2f71bc3 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h @@ -45,14 +45,14 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass } void Execute(GDX12CommandList* cmdList, GDX12Texture* IN_OpaqueScene, GDX12Texture* IN_TransparencyAccum, - GDX12Texture* IN_Revealage, GDX12Texture* OUT_Result) + GDX12Texture* IN_Revealage, GDX12Texture* IN_OUT_Result) { cmdList->BeginPixEvent("Composition Render Pass", Colors::Bisque); - cmdList->SetViewport(OUT_Result->GetViewport()); - cmdList->SetScissorRect(OUT_Result->GetScissorRect()); + cmdList->SetViewport(IN_OUT_Result->GetViewport()); + cmdList->SetScissorRect(IN_OUT_Result->GetScissorRect()); cmdList->SetGraphicsRootSignature(_compositionRS.get()); cmdList->SetPipelineState(_compositionPSO.Get()); - cmdList->SetRenderTargets({ OUT_Result }, nullptr); + cmdList->SetRenderTargets({ IN_OUT_Result }, nullptr); cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); cmdList->SetGraphicsSRV(0, IN_OpaqueScene->GetSRV()->GPUHandle); cmdList->SetGraphicsSRV(1, IN_TransparencyAccum->GetSRV()->GPUHandle); 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..b6d63ac --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -0,0 +1,189 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" + +class GDX12WBOITTransparencyPass : public GDX12RenderPass +{ +public: + GDX12WBOITTransparencyPass() + { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS; } + + void Initialize(GDX12DeviceResources* resources, DXGI_FORMAT outRTVformat, DXGI_FORMAT outDSVFormat, UINT outWidth, UINT outHeight) + { + _resources = resources; + + // Textures + GDX12TextureDesc TextureDesc1; + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + TextureDesc1.Width = outWidth; + TextureDesc1.Height = outHeight; + + 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; + + _accumulationTexture = std::make_unique(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(); + _revealageTexture = std::make_unique(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.NumRenderTargets = 1; + PSODesc1.RTVFormats[0] = outRTVformat; + PSODesc1.SampleDesc.Count = 1; + PSODesc1.SampleDesc.Quality = 0; + PSODesc1.DSVFormat = outDSVFormat; + + // 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] = _accumulationTexture->GetFormat(); + PSODesc1.RTVFormats[1] = _revealageTexture->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, UINT IN_CameraCBIndex, GDX12Texture* IN_DepthStencil, + GDX12Texture*& OUT_Accumulation, GDX12Texture*& OUT_Revealage) + { + auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[IN_CameraCBIndex]; + + cmdList->BeginPixEvent("Transparent Render Pass", Colors::Aqua); + cmdList->SetViewport(IN_DepthStencil->GetViewport()); + cmdList->SetScissorRect(IN_DepthStencil->GetScissorRect()); + cmdList->ResourceBarrier({ + currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().GetIndirectArgsBarrier(), + currentCameraVisBuffers.TransparentDrawCounter->GetResource().GetIndirectArgsBarrier() }); + cmdList->SetGraphicsRootSignature(_transparencyRS.get()); + cmdList->SetPipelineState(_transparencyPSO); + cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); + cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> + GetElementAddress(IN_CameraCBIndex)); + cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier(), + _revealageTexture->GetResource()->GetRenderTargetBarrier() }); + + cmdList->SetRenderTargets({ _accumulationTexture.get(), _revealageTexture.get() }, + IN_DepthStencil); + cmdList->ClearRenderTargetView(_accumulationTexture.get()); + cmdList->ClearRenderTargetView(_revealageTexture.get()); + + 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->ExecuteIndirect(_transparencyCS.Get(), _resources->IndirectCommandsCache->GetElementCount(), + currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().D3DResource.Get(), 0, + currentCameraVisBuffers.TransparentDrawCounter->GetResource().D3DResource.Get(), 0); + cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetSRVBarrier(), + _revealageTexture->GetResource()->GetSRVBarrier() }); + cmdList->EndPixEvent(); + + OUT_Accumulation = _accumulationTexture.get(); + OUT_Revealage = _revealageTexture.get(); + } + + void Resize(UINT width, UINT height) override + { + _accumulationTexture->Resize(width, height); + _revealageTexture->Resize(width, height); + } + +private: + ComPtr _transparencyVS; + ComPtr _transparencyPS; + std::unique_ptr _transparencyRS; + ComPtr _transparencyCS; + ComPtr _transparencyPSO; + + std::unique_ptr _accumulationTexture; + std::unique_ptr _revealageTexture; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/src/GDX12Resource.cpp b/Engine/Engine.RendererDX12/src/GDX12Resource.cpp index f9b9282..015bf22 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; From 496496ee36970b51e34975865238c1745d44042c Mon Sep 17 00:00:00 2001 From: AMorunov Date: Mon, 29 Jun 2026 13:45:42 +0300 Subject: [PATCH 08/46] Added motion vector calculation --- .../App.Base/ECS/Components/CameraComponent.h | 3 ++ .../Include/App.Base/Modules/RenderModule.h | 1 + .../App.Base/Systems/GPUDataUpdateSystem.h | 7 ++++ Apps/App.Base/src/RenderModule.cpp | 10 +++-- .../GDX12ConstantStructures.h | 2 + .../RenderPasses/GDX12BackBufferClearPass.h | 2 - .../RenderPasses/GDX12OpaquePass.h | 27 ++++++++++---- .../Shaders/CBufferStructures.hlsl | 2 + .../Shaders/OpaquePass.hlsl | 37 +++++++++++++------ 9 files changed, 66 insertions(+), 25 deletions(-) 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..6f026e0 100644 --- a/Apps/App.Base/Include/App.Base/ECS/Components/CameraComponent.h +++ b/Apps/App.Base/Include/App.Base/ECS/Components/CameraComponent.h @@ -2,12 +2,15 @@ #include "Engine.Core/ECS/Component.h" #include +#include "Engine.RendererDX12/D3DHelpers.h" struct CameraComponent : ComponentTag { float FOV; float NearPlane; float FarPlane; + XMFLOAT4X4 ViewProj; + XMFLOAT4X4 PrevViewProj; bool DirtyFlag; diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index 0ac5869..a209aed 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -30,6 +30,7 @@ struct TransformCompGPUData UINT CBufferIndex = -1; UINT NumFramesDirty = -1; Matrix World = Identity4x4(); + Matrix PrevWorld = Identity4x4(); }; class RenderModule final : public Module diff --git a/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h b/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h index 97903f2..7714f0e 100644 --- a/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h +++ b/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h @@ -55,12 +55,16 @@ class GPUDataUpdateSystem final : public System proj._33 = range; proj._43 = range * camera.FarPlane; + camera.ViewProj = view * proj; + GDX12CameraConstants objConstants; XMStoreFloat4x4(&objConstants.ViewProj, XMMatrixTranspose(view * proj)); XMStoreFloat4x4(&objConstants.View, XMMatrixTranspose(view)); objConstants.CameraLocation = transform.Location; objConstants.NearPlane = camera.NearPlane; objConstants.FarPlane = camera.FarPlane; + objConstants.PrevViewProj = camera.PrevViewProj; + XMStoreFloat4x4(&camera.PrevViewProj, XMMatrixTranspose(view * proj)); auto& CBuffer = renderModule->GetCurrentPrimaryFrameConstants()->CameraCB; CBuffer->CopyData(camera._CBufferIndex, objConstants); @@ -92,6 +96,9 @@ class GPUDataUpdateSystem final : public System GDX12TransformConstants objConstants; XMStoreFloat4x4(&objConstants.WorldMatrix, XMMatrixTranspose(world)); + XMStoreFloat4x4(&objConstants.PrevWorldMatrix, XMMatrixTranspose(GPUData.PrevWorld)); + + XMStoreFloat4x4(&GPUData.PrevWorld, world); auto& CBuffer = renderModule->GetCurrentPrimaryFrameConstants()->TransformCache; CBuffer->CopyData(GPUData.CBufferIndex, objConstants); diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index a81ca70..b575d5d 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -589,12 +589,15 @@ void RenderModule::OnRender() auto CurrentBackBuffer = _backBuffer->GetCurrentBuffer(); auto CurrentFrameConsts = GetCurrentPrimaryFrameConstants(); + cmdList->EnhancedTextureBarrier({ CurrentBackBuffer->GetResource()->GetRenderTargetEnhBarrier() }); + cmdList->ResourceBarrier({ _depthStencil->GetResource()->GetDepthWriteBarrier() }); _backBufferClearPass.Execute(cmdList, CurrentBackBuffer, _depthStencil.get()); - _gpuCullingPass.Execute(cmdList, _activeCamera->_CBufferIndex); + _gpuCullingPass.Execute(cmdList, _activeCamera->_CBufferIndex); GDX12Texture* opaqueAccum; + GDX12Texture* velocityBuf; _opaquePass.Execute(cmdList, _activeCamera->_CBufferIndex, _depthStencil.get(), - opaqueAccum); + opaqueAccum, velocityBuf); GDX12Texture* transparencyAccum; GDX12Texture* transparencyRevealage; @@ -642,10 +645,9 @@ void RenderModule::ConfigureRenderPipeline() { uint16_t width, height; _window->GetWindowSize(width, height); - _backBufferClearPass.Initialize(&_primaryResources); _gpuCullingPass.Initialize(&_primaryResources); - _opaquePass.Initialize(&_primaryResources, _backBuffer->GetFormat(), _depthStencil->GetFormat(), width, height); + _opaquePass.Initialize(&_primaryResources, _depthStencil->GetFormat(), width, height); _WBOITTransparencyPass.Initialize(&_primaryResources, _backBuffer->GetFormat(), _depthStencil->GetFormat(), width, height); _WBOITCompositionPass.Initialize(&_primaryResources, _backBuffer->GetFormat()); } diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12ConstantStructures.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12ConstantStructures.h index e1bc106..450ef71 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 @@ -34,6 +35,7 @@ struct GDX12CameraConstants { XMFLOAT4X4 ViewProj = Identity4x4(); XMFLOAT4X4 View = Identity4x4(); + XMFLOAT4X4 PrevViewProj = Identity4x4(); XMFLOAT3 CameraLocation = { 0.f, 0.f, 0.f }; float NearPlane; float FarPlane; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h index 4284575..a051bb7 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h @@ -16,8 +16,6 @@ class GDX12BackBufferClearPass : public GDX12RenderPass cmdList->BeginPixEvent("Clear Back Buffer", Colors::Aqua); cmdList->SetViewport(IN_OUT_currentBackBuffer->GetViewport()); cmdList->SetScissorRect(IN_OUT_currentBackBuffer->GetScissorRect()); - cmdList->EnhancedTextureBarrier({ IN_OUT_currentBackBuffer->GetResource()->GetRenderTargetEnhBarrier() }); - cmdList->ResourceBarrier({ IN_OUT_depthStencil->GetResource()->GetDepthWriteBarrier() }); cmdList->SetRenderTargets({ IN_OUT_currentBackBuffer }, IN_OUT_depthStencil); cmdList->ClearRenderTargetView(IN_OUT_currentBackBuffer); cmdList->ClearDepthStencilView(IN_OUT_depthStencil); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h index dd8dcbf..9b6cacd 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -9,7 +9,7 @@ class GDX12OpaquePass : public GDX12RenderPass _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS; } - void Initialize(GDX12DeviceResources* resources, DXGI_FORMAT outRTVformat, DXGI_FORMAT outDSVFormat, UINT outWidth, UINT outHeight) + void Initialize(GDX12DeviceResources* resources, DXGI_FORMAT outDSVFormat, UINT outWidth, UINT outHeight) { _resources = resources; @@ -38,6 +38,12 @@ class GDX12OpaquePass : public GDX12RenderPass _accumulationTexture = std::make_unique(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); + + _velocityBuffer = std::make_unique(TextureDesc1); + // Shaders auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); _opaqueVS = shaderCompiler.CompileShader(resources->Device, SHADERS_FOLDER "OpaquePass.hlsl", nullptr, "VS", "vs"); @@ -86,8 +92,9 @@ class GDX12OpaquePass : public GDX12RenderPass PSODesc1.RasterizerState.FrontCounterClockwise = TRUE; PSODesc1.SampleMask = UINT_MAX; PSODesc1.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - PSODesc1.NumRenderTargets = 1; - PSODesc1.RTVFormats[0] = outRTVformat; + PSODesc1.NumRenderTargets = 2; + PSODesc1.RTVFormats[0] = _accumulationTexture->GetFormat(); + PSODesc1.RTVFormats[1] = _velocityBuffer->GetFormat(); PSODesc1.SampleDesc.Count = 1; PSODesc1.SampleDesc.Quality = 0; PSODesc1.DSVFormat = outDSVFormat; @@ -99,7 +106,7 @@ class GDX12OpaquePass : public GDX12RenderPass // VisibilityBuffers will automatically be selected from CameraCBIndex // It requires GPUCullingPass to be executed beforehand void Execute(GDX12CommandList* cmdList, UINT IN_CameraCBIndex, GDX12Texture* IN_DepthStencil, - GDX12Texture*& OUT_Accumulation) + GDX12Texture*& OUT_Accumulation, GDX12Texture*& OUT_Velocity) { auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[IN_CameraCBIndex]; @@ -113,9 +120,11 @@ class GDX12OpaquePass : public GDX12RenderPass cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> GetElementAddress(IN_CameraCBIndex)); - cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier() }); - cmdList->SetRenderTargets({ _accumulationTexture.get() }, IN_DepthStencil); + cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier(), + _velocityBuffer->GetResource()->GetRenderTargetBarrier() }); + cmdList->SetRenderTargets({ _accumulationTexture.get(), _velocityBuffer.get() }, IN_DepthStencil); cmdList->ClearRenderTargetView(_accumulationTexture.get()); + cmdList->ClearRenderTargetView(_velocityBuffer.get()); cmdList->SetGeometryBuffer(_resources->GeometryBuffer.get()); cmdList->SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); @@ -126,15 +135,18 @@ class GDX12OpaquePass : public GDX12RenderPass cmdList->ExecuteIndirect(_opaqueCS.Get(), _resources->IndirectCommandsCache->GetElementCount(), currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().D3DResource.Get(), 0, currentCameraVisBuffers.OpaqueDrawCounter->GetResource().D3DResource.Get(), 0); - cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetSRVBarrier() }); + cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetSRVBarrier(), + _velocityBuffer->GetResource()->GetSRVBarrier() }); cmdList->EndPixEvent(); OUT_Accumulation = _accumulationTexture.get(); + OUT_Velocity = _velocityBuffer.get(); } void Resize(UINT width, UINT height) override { _accumulationTexture->Resize(width, height); + _velocityBuffer->Resize(width, height); } private: @@ -145,4 +157,5 @@ class GDX12OpaquePass : public GDX12RenderPass ComPtr _opaquePSO; std::unique_ptr _accumulationTexture; + std::unique_ptr _velocityBuffer; }; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Shaders/CBufferStructures.hlsl b/Engine/Engine.RendererDX12/Shaders/CBufferStructures.hlsl index 521328a..a34f311 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 @@ -35,6 +36,7 @@ struct CameraCB { float4x4 ViewProj; float4x4 View; + float4x4 PrevViewProj; float3 CameraLocation; float NearPlane; float FarPlane; diff --git a/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl b/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl index c424870..7b4afe7 100644 --- a/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl +++ b/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl @@ -27,6 +27,7 @@ struct VS_INPUT struct VS_OUTPUT_PS_INPUT { float4 PosCS : SV_POSITION; + float4 PrevPosCS : TEXCOORD2; float3 PosW : POSITION; float2 TexC : TEXCOORD; float3 Normal : NORMAL; @@ -39,32 +40,44 @@ 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; + float4 prevPosW = mul(float4(vin.Pos, 1.0f), transform.PrevWorld); + vout.PrevPosCS = mul(prevPosW, CBCamera.PrevViewProj); + + 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.PosCS.xy / pin.PosCS.w; + float2 prevNDC = pin.PrevPosCS.xy / pin.PrevPosCS.w; + float2 velocity = currentNDC - prevNDC; - return float4(color.rgb, 1.0f); + output.Color = float4(color.rgb, 1.0f); + output.Velocity = velocity; + + return output; } \ No newline at end of file From c94fc7abeaa2cb399c78aca6b07a48a399362060 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Mon, 29 Jun 2026 17:54:51 +0300 Subject: [PATCH 09/46] Added customizable render pipeline --- .../Include/App.Base/Modules/RenderModule.h | 7 +- Apps/App.Base/src/RenderModule.cpp | 51 ++++--- .../Engine.RendererDX12.vcxproj | 1 + .../Engine.RendererDX12.vcxproj.filters | 3 + .../Engine.RendererDX12/GDX12SwapChain.h | 4 +- .../Engine.RendererDX12/GDX12Texture.h | 7 +- .../Engine.RendererDX12/IRenderPassLink.h | 9 ++ .../RenderPasses/GDX12BackBufferClearPass.h | 31 +++-- .../RenderPasses/GDX12GPUCullingPass.h | 18 ++- .../RenderPasses/GDX12OpaquePass.h | 85 +++++++----- .../RenderPasses/GDX12RenderPass.h | 4 +- .../RenderPasses/GDX12WBOITCompositionPass.h | 70 +++++++--- .../RenderPasses/GDX12WBOITTransparencyPass.h | 131 ++++++++++-------- .../src/GDX12SwapChain.cpp | 16 +-- .../Engine.RendererDX12/src/GDX12Texture.cpp | 15 ++ 15 files changed, 283 insertions(+), 169 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index a209aed..f6714e7 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -128,7 +128,7 @@ class RenderModule final : public Module std::unordered_map _transformGPUData; std::unordered_map _worldSubscriptions; - CameraComponent* _activeCamera; + UINT _activeCamera; std::unique_ptr _primaryDevice; std::unique_ptr _secondaryDevice; @@ -149,7 +149,6 @@ class RenderModule final : public Module GDX12WBOITTransparencyPass _WBOITTransparencyPass; GDX12WBOITCompositionPass _WBOITCompositionPass; - // in case we need a foreach - std::vector _renderPassPtrs = { &_backBufferClearPass, &_gpuCullingPass, &_opaquePass, - &_WBOITTransparencyPass, &_WBOITCompositionPass }; + // sorted in execution order + std::vector _renderPassExecutionList; }; \ No newline at end of file diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index b575d5d..4a6fd63 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -7,7 +7,7 @@ #include "Common/ConsoleVariables.h" RenderModule::RenderModule(Window* window, GameTimer* timer) : - _dualGPUMode(false), _window(window), _timer(timer), _activeCamera(nullptr) + _dualGPUMode(false), _window(window), _timer(timer), _activeCamera(0) { } @@ -62,7 +62,7 @@ void RenderModule::OnResize() const _backBuffer->Resize(width, height); _depthStencil->Resize(width, height); - for (auto& renderPass : _renderPassPtrs) { renderPass->Resize(width, height); } + for (auto& renderPass : _renderPassExecutionList) { renderPass->Resize(width, height); } } GDX12Material* RenderModule::GetMaterialByName(const std::string& name) @@ -289,7 +289,7 @@ void RenderModule::SubmitMesh(const Mesh* mesh, MeshHandle handle) void RenderModule::SetActiveCamera(CameraComponent* camera) { - _activeCamera = camera; + _activeCamera = camera->_CBufferIndex; } TransformCompGPUData& RenderModule::GetTransformGPUData(Entity entity) @@ -591,21 +591,8 @@ void RenderModule::OnRender() cmdList->EnhancedTextureBarrier({ CurrentBackBuffer->GetResource()->GetRenderTargetEnhBarrier() }); cmdList->ResourceBarrier({ _depthStencil->GetResource()->GetDepthWriteBarrier() }); - _backBufferClearPass.Execute(cmdList, CurrentBackBuffer, _depthStencil.get()); - - _gpuCullingPass.Execute(cmdList, _activeCamera->_CBufferIndex); - GDX12Texture* opaqueAccum; - GDX12Texture* velocityBuf; - _opaquePass.Execute(cmdList, _activeCamera->_CBufferIndex, _depthStencil.get(), - opaqueAccum, velocityBuf); - - GDX12Texture* transparencyAccum; - GDX12Texture* transparencyRevealage; - _WBOITTransparencyPass.Execute(cmdList, _activeCamera->_CBufferIndex, _depthStencil.get(), - transparencyAccum, transparencyRevealage); - - _WBOITCompositionPass.Execute(cmdList, opaqueAccum, transparencyAccum, - transparencyRevealage, CurrentBackBuffer); + + for (auto& renderPass : _renderPassExecutionList) { renderPass->Execute(cmdList); } cmdList->EnhancedTextureBarrier({ CurrentBackBuffer->GetResource()->GetPresentEnhBarrier() }); cmdList->ResourceBarrier({ _depthStencil->GetResource()->GetCommonBarrier() }); @@ -645,11 +632,29 @@ void RenderModule::ConfigureRenderPipeline() { uint16_t width, height; _window->GetWindowSize(width, height); - _backBufferClearPass.Initialize(&_primaryResources); - _gpuCullingPass.Initialize(&_primaryResources); - _opaquePass.Initialize(&_primaryResources, _depthStencil->GetFormat(), width, height); - _WBOITTransparencyPass.Initialize(&_primaryResources, _backBuffer->GetFormat(), _depthStencil->GetFormat(), width, height); - _WBOITCompositionPass.Initialize(&_primaryResources, _backBuffer->GetFormat()); + + _backBufferClearPass.Initialize(&_primaryResources, width, height); + _backBufferClearPass.LinkDependancies(_backBuffer.get(), _depthStencil.get()); + + _gpuCullingPass.Initialize(&_primaryResources, width, height); + _gpuCullingPass.LinkDependancies(&_activeCamera); + + IRenderPassLink* opaqueAccum; + IRenderPassLink* opaqueVelocity; + _opaquePass.Initialize(&_primaryResources, width, height); + _opaquePass.LinkDependancies(&_activeCamera, _depthStencil.get(), opaqueAccum, opaqueVelocity); + + IRenderPassLink* transparencyAccum; + IRenderPassLink* transparencyRevealage; + _WBOITTransparencyPass.Initialize(&_primaryResources, width, height); + _WBOITTransparencyPass.LinkDependancies(&_activeCamera, _depthStencil.get(), + transparencyAccum, transparencyRevealage); + + _WBOITCompositionPass.Initialize(&_primaryResources, width, height); + _WBOITCompositionPass.LinkDependancies(opaqueAccum, transparencyAccum, transparencyRevealage, _backBuffer.get()); + + _renderPassExecutionList = { &_backBufferClearPass, &_gpuCullingPass, &_opaquePass, + &_WBOITTransparencyPass, &_WBOITCompositionPass }; } void RenderModule::SubscribeToSceneManager() diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index b720d6d..488d759 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -24,6 +24,7 @@ + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index 3057c75..9e6030a 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -93,6 +93,9 @@ Header Files + + Header Files + diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h index 359624c..8d7f80f 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,6 +26,7 @@ class GDX12SwapChain GDX12Texture* GetBuffer(UINT index); D3D12_VIEWPORT GetViewport(); D3D12_RECT GetScissorRect(); + GDX12Texture* GetTexture() override; const ComPtr& GetSwapChain(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h index 8d75b88..fb4f759 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h @@ -3,6 +3,7 @@ #include "Engine.RendererDX12\D3DHelpers.h" #include "Engine.Core/Types/TextureTypes.h" +#include "Engine.RendererDX12/IRenderPassLink.h" class GDX12Descriptor; class GDX12DescriptorHeap; @@ -62,7 +63,7 @@ struct GDX12TextureDesc ComPtr ExternalResource = nullptr; }; -class GDX12Texture +class GDX12Texture : public IRenderPassLink { public: GDX12Texture(GDX12TextureDesc desc); @@ -82,7 +83,9 @@ class GDX12Texture ETextureSemantic GetSemantic() const; D3D12_VIEWPORT GetViewport(); D3D12_RECT GetScissorRect(); - + UINT GetWidth(); + UINT GetHeight(); + GDX12Texture* GetTexture() override; private: void CreateResource(); 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..bfbd2b1 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h @@ -0,0 +1,9 @@ +#pragma once + +class GDX12Texture; + +class IRenderPassLink +{ +public: + virtual GDX12Texture* GetTexture() = 0; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h index a051bb7..88942e8 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h @@ -4,21 +4,36 @@ class GDX12BackBufferClearPass : public GDX12RenderPass { public: - GDX12BackBufferClearPass() { _flags = RENDER_PASS_FLAG_PRESENTING; } + GDX12BackBufferClearPass() : IN_OUT_currentBackBuffer(nullptr), IN_OUT_depthStencil(nullptr) + { _flags = RENDER_PASS_FLAG_PRESENTING; } - void Initialize(GDX12DeviceResources* resources) + void LinkDependancies(IRenderPassLink* IN_OUT_currentBackBuffer, + IRenderPassLink* IN_OUT_depthStencil) + { + this->IN_OUT_currentBackBuffer = IN_OUT_currentBackBuffer; + this->IN_OUT_depthStencil = IN_OUT_depthStencil; + } + + void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override { _resources = resources; } - void Execute(GDX12CommandList* cmdList, GDX12Texture* IN_OUT_currentBackBuffer, GDX12Texture* IN_OUT_depthStencil) + void Execute(GDX12CommandList* cmdList) override { + GDX12Texture* currentBackBuffer = IN_OUT_currentBackBuffer->GetTexture(); + GDX12Texture* depthStencil = IN_OUT_depthStencil->GetTexture(); + cmdList->BeginPixEvent("Clear Back Buffer", Colors::Aqua); - cmdList->SetViewport(IN_OUT_currentBackBuffer->GetViewport()); - cmdList->SetScissorRect(IN_OUT_currentBackBuffer->GetScissorRect()); - cmdList->SetRenderTargets({ IN_OUT_currentBackBuffer }, IN_OUT_depthStencil); - cmdList->ClearRenderTargetView(IN_OUT_currentBackBuffer); - cmdList->ClearDepthStencilView(IN_OUT_depthStencil); + cmdList->SetViewport(currentBackBuffer->GetViewport()); + cmdList->SetScissorRect(currentBackBuffer->GetScissorRect()); + cmdList->SetRenderTargets({ currentBackBuffer }, depthStencil); + cmdList->ClearRenderTargetView(currentBackBuffer); + cmdList->ClearDepthStencilView(depthStencil); cmdList->EndPixEvent(); } + +private: + IRenderPassLink* IN_OUT_currentBackBuffer; + IRenderPassLink* IN_OUT_depthStencil; }; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h index f1ae73d..3813915 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h @@ -4,9 +4,15 @@ class GDX12GPUCullingPass : public GDX12RenderPass { public: - GDX12GPUCullingPass() { _flags = RENDER_PASS_FLAG_USE_CAMERAS; } + GDX12GPUCullingPass() : IN_CameraCBIndex(nullptr) + { _flags = RENDER_PASS_FLAG_USE_CAMERAS; } - void Initialize(GDX12DeviceResources* resources) + void LinkDependancies(UINT* IN_CameraCBIndex) + { + this->IN_CameraCBIndex = IN_CameraCBIndex; + } + + void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override { _resources = resources; @@ -43,10 +49,10 @@ class GDX12GPUCullingPass : public GDX12RenderPass } // automatically uses IN_OUT_CameraVisibilityBuffers from cameraCBIndex - void Execute(GDX12CommandList* cmdList, UINT IN_CameraCBIndex) + void Execute(GDX12CommandList* cmdList) override { auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; - auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[IN_CameraCBIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[*IN_CameraCBIndex]; cmdList->BeginPixEvent("GPU Mesh Culling", Colors::Blue); cmdList->ResourceBarrier({ @@ -65,7 +71,7 @@ class GDX12GPUCullingPass : public GDX12RenderPass cmdList->SetComputeRootSignature(_cullingRS.get()); cmdList->SetPipelineState(_cullingPSO); cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); - cmdList->SetComputeRootConstantBufferView(0, currentFrameConstants->CameraCB->GetElementAddress(IN_CameraCBIndex)); + cmdList->SetComputeRootConstantBufferView(0, currentFrameConstants->CameraCB->GetElementAddress(*IN_CameraCBIndex)); cmdList->SetComputeSRV(0, currentFrameConstants->InstanceCache->GetSRV()->GPUHandle); cmdList->SetComputeSRV(1, _resources->IndirectCommandsCache->GetSRV()->GPUHandle); cmdList->SetComputeSRV(2, currentFrameConstants->MaterialCache->GetSRV()->GPUHandle); @@ -89,4 +95,6 @@ class GDX12GPUCullingPass : public GDX12RenderPass ComPtr _bufferClearCS; std::unique_ptr _bufferClearRS; ComPtr _bufferClearPSO; + + UINT* IN_CameraCBIndex; }; \ 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 index 9b6cacd..9105190 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -4,20 +4,30 @@ class GDX12OpaquePass : public GDX12RenderPass { public: - GDX12OpaquePass() + GDX12OpaquePass() : IN_DepthStencil(nullptr), IN_CameraCBIndex(nullptr) + { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS; } + + void LinkDependancies(UINT* IN_CameraCBIndex, IRenderPassLink* IN_DepthStencil, + IRenderPassLink*& OUT_Accumulation, IRenderPassLink*& OUT_Velocity) { - _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS; + this->IN_CameraCBIndex = IN_CameraCBIndex; + this->IN_DepthStencil = IN_DepthStencil; + + PostLinkInitialize(); + + OUT_Accumulation = _accumulationTexture.get(); + OUT_Velocity = _velocityBuffer.get(); } - void Initialize(GDX12DeviceResources* resources, DXGI_FORMAT outDSVFormat, UINT outWidth, UINT outHeight) + void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override { _resources = resources; // Textures GDX12TextureDesc TextureDesc1; TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - TextureDesc1.Width = outWidth; - TextureDesc1.Height = outHeight; + TextureDesc1.Width = width; + TextureDesc1.Height = height; TextureDesc1.CreateSRV = true; TextureDesc1.SRV_UAV_Heap = _resources->SRV_UAV_Heap.get(); @@ -78,38 +88,15 @@ class GDX12OpaquePass : public GDX12RenderPass 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] = _accumulationTexture->GetFormat(); - PSODesc1.RTVFormats[1] = _velocityBuffer->GetFormat(); - PSODesc1.SampleDesc.Count = 1; - PSODesc1.SampleDesc.Quality = 0; - PSODesc1.DSVFormat = outDSVFormat; - 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, UINT IN_CameraCBIndex, GDX12Texture* IN_DepthStencil, - GDX12Texture*& OUT_Accumulation, GDX12Texture*& OUT_Velocity) + void Execute(GDX12CommandList* cmdList) { auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; - auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[IN_CameraCBIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[*IN_CameraCBIndex]; + GDX12Texture* depthStencil = IN_DepthStencil->GetTexture(); cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); cmdList->ResourceBarrier({ @@ -119,10 +106,10 @@ class GDX12OpaquePass : public GDX12RenderPass cmdList->SetPipelineState(_opaquePSO.Get()); cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> - GetElementAddress(IN_CameraCBIndex)); + GetElementAddress(*IN_CameraCBIndex)); cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier(), _velocityBuffer->GetResource()->GetRenderTargetBarrier() }); - cmdList->SetRenderTargets({ _accumulationTexture.get(), _velocityBuffer.get() }, IN_DepthStencil); + cmdList->SetRenderTargets({ _accumulationTexture.get(), _velocityBuffer.get() }, depthStencil); cmdList->ClearRenderTargetView(_accumulationTexture.get()); cmdList->ClearRenderTargetView(_velocityBuffer.get()); cmdList->SetGeometryBuffer(_resources->GeometryBuffer.get()); @@ -138,9 +125,6 @@ class GDX12OpaquePass : public GDX12RenderPass cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetSRVBarrier(), _velocityBuffer->GetResource()->GetSRVBarrier() }); cmdList->EndPixEvent(); - - OUT_Accumulation = _accumulationTexture.get(); - OUT_Velocity = _velocityBuffer.get(); } void Resize(UINT width, UINT height) override @@ -150,6 +134,32 @@ class GDX12OpaquePass : public GDX12RenderPass } private: + void PostLinkInitialize() + { + // 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] = _accumulationTexture->GetFormat(); + PSODesc1.RTVFormats[1] = _velocityBuffer->GetFormat(); + PSODesc1.SampleDesc.Count = 1; + PSODesc1.SampleDesc.Quality = 0; + PSODesc1.DSVFormat = IN_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))); + } + ComPtr _opaqueVS; ComPtr _opaquePS; std::unique_ptr _opaqueRS; @@ -158,4 +168,7 @@ class GDX12OpaquePass : public GDX12RenderPass std::unique_ptr _accumulationTexture; std::unique_ptr _velocityBuffer; + + UINT* IN_CameraCBIndex; + IRenderPassLink* IN_DepthStencil; }; \ 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 index 8dedff3..63a28d5 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -9,6 +9,7 @@ #include "Engine.RendererDX12/GDX12ShaderCompiler.h" #include "Engine.RendererDX12/GDX12TextureResource.h" #include "Engine.RendererDX12/GDX12Descriptor.h" +#include "Engine.RendererDX12/IRenderPassLink.h" enum ERenderPassFlags : uint32_t { @@ -24,8 +25,9 @@ class GDX12RenderPass { public: GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE), _resources(nullptr) {} - + virtual void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) {}; virtual void Resize(UINT width, UINT height) {}; + virtual void Execute(GDX12CommandList* cmdList) {}; uint32_t GetFlags() { return _flags; } diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h index 2f71bc3..e2d119c 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h @@ -4,9 +4,22 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass { public: - GDX12WBOITCompositionPass() { _flags = RENDER_PASS_FLAG_NONE; } + GDX12WBOITCompositionPass() : IN_OpaqueScene(nullptr), IN_TransparencyAccum(nullptr), + IN_Revealage(nullptr), IN_OUT_Result(nullptr) + { _flags = RENDER_PASS_FLAG_NONE; } - void Initialize(GDX12DeviceResources* resources, DXGI_FORMAT OUT_Format) + void LinkDependancies(IRenderPassLink* IN_OpaqueScene, IRenderPassLink* IN_TransparencyAccum, + IRenderPassLink* IN_Revealage, IRenderPassLink* IN_OUT_Result) + { + this->IN_OpaqueScene = IN_OpaqueScene; + this->IN_TransparencyAccum = IN_TransparencyAccum; + this->IN_Revealage = IN_Revealage; + this->IN_OUT_Result = IN_OUT_Result; + + PostLinkInitialize(); + } + + void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override { _resources = resources; @@ -20,7 +33,32 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass RSDesc1.NumSingleSRVSlots = 3; RSDesc1.StaticSamplers = GetStaticSamplers(); _compositionRS = std::make_unique(resources->Device, RSDesc1); + } + + void Execute(GDX12CommandList* cmdList) override + { + GDX12Texture* opaqueAccum = IN_OpaqueScene->GetTexture(); + GDX12Texture* transparencyAccum = IN_TransparencyAccum->GetTexture(); + GDX12Texture* transparencyRevealage = IN_Revealage->GetTexture(); + GDX12Texture* output = IN_OUT_Result->GetTexture(); + cmdList->BeginPixEvent("Composition Render Pass", Colors::Bisque); + cmdList->SetViewport(output->GetViewport()); + cmdList->SetScissorRect(output->GetScissorRect()); + cmdList->SetGraphicsRootSignature(_compositionRS.get()); + cmdList->SetPipelineState(_compositionPSO.Get()); + cmdList->SetRenderTargets({ output }, nullptr); + cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.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(); + } +private: + void PostLinkInitialize() + { // Pipeline State Objects D3D12_GRAPHICS_PIPELINE_STATE_DESC PSODesc1 = {}; PSODesc1.InputLayout = { nullptr, 0 }; @@ -34,36 +72,24 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass PSODesc1.SampleMask = UINT_MAX; PSODesc1.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; PSODesc1.NumRenderTargets = 1; - PSODesc1.RTVFormats[0] = OUT_Format; + PSODesc1.RTVFormats[0] = IN_OUT_Result->GetTexture()->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))); + ThrowIfFailed(_resources->Device->GetDevice()->CreateGraphicsPipelineState(&PSODesc1, IID_PPV_ARGS(&_compositionPSO))); } - void Execute(GDX12CommandList* cmdList, GDX12Texture* IN_OpaqueScene, GDX12Texture* IN_TransparencyAccum, - GDX12Texture* IN_Revealage, GDX12Texture* IN_OUT_Result) - { - cmdList->BeginPixEvent("Composition Render Pass", Colors::Bisque); - cmdList->SetViewport(IN_OUT_Result->GetViewport()); - cmdList->SetScissorRect(IN_OUT_Result->GetScissorRect()); - cmdList->SetGraphicsRootSignature(_compositionRS.get()); - cmdList->SetPipelineState(_compositionPSO.Get()); - cmdList->SetRenderTargets({ IN_OUT_Result }, nullptr); - cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); - cmdList->SetGraphicsSRV(0, IN_OpaqueScene->GetSRV()->GPUHandle); - cmdList->SetGraphicsSRV(1, IN_TransparencyAccum->GetSRV()->GPUHandle); - cmdList->SetGraphicsSRV(2, IN_Revealage->GetSRV()->GPUHandle); - cmdList->GetCommandList()->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - cmdList->GetCommandList()->DrawInstanced(3, 1, 0, 0); - cmdList->EndPixEvent(); - } -private: ComPtr _compositionVS; ComPtr _compositionPS; std::unique_ptr _compositionRS; ComPtr _compositionPSO; + + IRenderPassLink* IN_OpaqueScene; + IRenderPassLink* IN_TransparencyAccum; + IRenderPassLink* IN_Revealage; + IRenderPassLink* IN_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 index b6d63ac..0891fa3 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -4,18 +4,30 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass { public: - GDX12WBOITTransparencyPass() + GDX12WBOITTransparencyPass() : IN_DepthStencil(nullptr), IN_CameraCBIndex(nullptr) { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS; } - void Initialize(GDX12DeviceResources* resources, DXGI_FORMAT outRTVformat, DXGI_FORMAT outDSVFormat, UINT outWidth, UINT outHeight) + void LinkDependancies(UINT* IN_CameraCBIndex, IRenderPassLink* IN_DepthStencil, + IRenderPassLink*& OUT_Accumulation, IRenderPassLink*& OUT_Revealage) + { + this->IN_CameraCBIndex = IN_CameraCBIndex; + this->IN_DepthStencil = IN_DepthStencil; + + PostLinkInitialize(); + + OUT_Accumulation = _accumulationTexture.get(); + OUT_Revealage = _revealageTexture.get(); + } + + void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override { _resources = resources; // Textures GDX12TextureDesc TextureDesc1; TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - TextureDesc1.Width = outWidth; - TextureDesc1.Height = outHeight; + TextureDesc1.Width = width; + TextureDesc1.Height = height; TextureDesc1.CreateSRV = true; TextureDesc1.SRV_UAV_Heap = _resources->SRV_UAV_Heap.get(); @@ -75,7 +87,59 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass resources->Device->GetDevice()->CreateCommandSignature(&CSDesc1, _transparencyRS->GetRootSignature().Get(), IID_PPV_ARGS(&_transparencyCS)); + } + + // VisibilityBuffers will automatically be selected from CameraCBIndex + // It requires GPUCullingPass to be executed beforehand + void Execute(GDX12CommandList* cmdList) + { + auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[*IN_CameraCBIndex]; + GDX12Texture* depthStencil = IN_DepthStencil->GetTexture(); + + cmdList->BeginPixEvent("Transparent Render Pass", Colors::Aqua); + cmdList->SetViewport(depthStencil->GetViewport()); + cmdList->SetScissorRect(depthStencil->GetScissorRect()); + cmdList->ResourceBarrier({ + currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().GetIndirectArgsBarrier(), + currentCameraVisBuffers.TransparentDrawCounter->GetResource().GetIndirectArgsBarrier() }); + cmdList->SetGraphicsRootSignature(_transparencyRS.get()); + cmdList->SetPipelineState(_transparencyPSO); + cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); + cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> + GetElementAddress(*IN_CameraCBIndex)); + cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier(), + _revealageTexture->GetResource()->GetRenderTargetBarrier() }); + + cmdList->SetRenderTargets({ _accumulationTexture.get(), _revealageTexture.get() }, + depthStencil); + cmdList->ClearRenderTargetView(_accumulationTexture.get()); + cmdList->ClearRenderTargetView(_revealageTexture.get()); + + 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->ExecuteIndirect(_transparencyCS.Get(), _resources->IndirectCommandsCache->GetElementCount(), + currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().D3DResource.Get(), 0, + currentCameraVisBuffers.TransparentDrawCounter->GetResource().D3DResource.Get(), 0); + cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetSRVBarrier(), + _revealageTexture->GetResource()->GetSRVBarrier() }); + cmdList->EndPixEvent(); + } + + void Resize(UINT width, UINT height) override + { + _accumulationTexture->Resize(width, height); + _revealageTexture->Resize(width, height); + } +private: + void PostLinkInitialize() + { // Pipeline State Objects D3D12_GRAPHICS_PIPELINE_STATE_DESC PSODesc1 = {}; PSODesc1.InputLayout = { _resources->InputLayouts["Default"].data(), (UINT)_resources->InputLayouts["Default"].size() }; @@ -88,11 +152,9 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass PSODesc1.RasterizerState.FrontCounterClockwise = TRUE; PSODesc1.SampleMask = UINT_MAX; PSODesc1.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - PSODesc1.NumRenderTargets = 1; - PSODesc1.RTVFormats[0] = outRTVformat; PSODesc1.SampleDesc.Count = 1; PSODesc1.SampleDesc.Quality = 0; - PSODesc1.DSVFormat = outDSVFormat; + PSODesc1.DSVFormat = IN_DepthStencil->GetTexture()->GetFormat(); // Accumulation PSODesc1.BlendState.RenderTarget[0].BlendEnable = true; @@ -126,58 +188,6 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass 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, UINT IN_CameraCBIndex, GDX12Texture* IN_DepthStencil, - GDX12Texture*& OUT_Accumulation, GDX12Texture*& OUT_Revealage) - { - auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; - auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[IN_CameraCBIndex]; - - cmdList->BeginPixEvent("Transparent Render Pass", Colors::Aqua); - cmdList->SetViewport(IN_DepthStencil->GetViewport()); - cmdList->SetScissorRect(IN_DepthStencil->GetScissorRect()); - cmdList->ResourceBarrier({ - currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().GetIndirectArgsBarrier(), - currentCameraVisBuffers.TransparentDrawCounter->GetResource().GetIndirectArgsBarrier() }); - cmdList->SetGraphicsRootSignature(_transparencyRS.get()); - cmdList->SetPipelineState(_transparencyPSO); - cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); - cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> - GetElementAddress(IN_CameraCBIndex)); - cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier(), - _revealageTexture->GetResource()->GetRenderTargetBarrier() }); - - cmdList->SetRenderTargets({ _accumulationTexture.get(), _revealageTexture.get() }, - IN_DepthStencil); - cmdList->ClearRenderTargetView(_accumulationTexture.get()); - cmdList->ClearRenderTargetView(_revealageTexture.get()); - - 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->ExecuteIndirect(_transparencyCS.Get(), _resources->IndirectCommandsCache->GetElementCount(), - currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().D3DResource.Get(), 0, - currentCameraVisBuffers.TransparentDrawCounter->GetResource().D3DResource.Get(), 0); - cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetSRVBarrier(), - _revealageTexture->GetResource()->GetSRVBarrier() }); - cmdList->EndPixEvent(); - - OUT_Accumulation = _accumulationTexture.get(); - OUT_Revealage = _revealageTexture.get(); - } - - void Resize(UINT width, UINT height) override - { - _accumulationTexture->Resize(width, height); - _revealageTexture->Resize(width, height); - } - -private: ComPtr _transparencyVS; ComPtr _transparencyPS; std::unique_ptr _transparencyRS; @@ -186,4 +196,7 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass std::unique_ptr _accumulationTexture; std::unique_ptr _revealageTexture; + + UINT* IN_CameraCBIndex; + IRenderPassLink* IN_DepthStencil; }; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp index 5fffdf7..65f870d 100644 --- a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp @@ -7,14 +7,9 @@ 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) { Reset(); @@ -127,6 +122,11 @@ D3D12_RECT GDX12SwapChain::GetScissorRect() return _screenScissorRect; } +GDX12Texture* GDX12SwapChain::GetTexture() +{ + return GetCurrentBuffer(); +} + DXGI_FORMAT GDX12SwapChain::GetFormat() { return _format; diff --git a/Engine/Engine.RendererDX12/src/GDX12Texture.cpp b/Engine/Engine.RendererDX12/src/GDX12Texture.cpp index 6dba5d5..4859755 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Texture.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Texture.cpp @@ -127,6 +127,21 @@ D3D12_RECT GDX12Texture::GetScissorRect() return _scissorRect; } +UINT GDX12Texture::GetWidth() +{ + return _desc.Width; +} + +UINT GDX12Texture::GetHeight() +{ + return _desc.Height; +} + +GDX12Texture* GDX12Texture::GetTexture() +{ + return this; +} + void GDX12Texture::CreateResource() { D3D12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D( From 04402f885ab2e1593ec6c5990143878aaa86bc8c Mon Sep 17 00:00:00 2001 From: AMorunov Date: Mon, 29 Jun 2026 18:01:34 +0300 Subject: [PATCH 10/46] Added sync flag to swapchain --- Apps/App.Base/src/RenderModule.cpp | 2 +- .../Include/Engine.RendererDX12/GDX12SwapChain.h | 3 ++- Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp | 8 +++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 4a6fd63..fac8a2f 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -609,7 +609,7 @@ void RenderModule::BuildBackBuffer() _window->GetWindowSize(width, height); _backBuffer = std::make_unique(_primaryDevice.get(), _window->GetWindowHandle(), - DXGI_FORMAT_R8G8B8A8_UNORM, 2, width, height, _primaryResources.RTVHeap.get()); + DXGI_FORMAT_R8G8B8A8_UNORM, 2, width, height, _primaryResources.RTVHeap.get(), false); GDX12TextureDesc desc; desc.CreateSRV = false; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h index 8d7f80f..34797bd 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h @@ -12,7 +12,7 @@ class GDX12SwapChain : public IRenderPassLink public: GDX12SwapChain(GDX12Device* device, HWND hwnd, DXGI_FORMAT format, UINT bufferCount, UINT width, UINT height, - GDX12DescriptorHeap* rtvHeap); + GDX12DescriptorHeap* rtvHeap, bool VSync); ~GDX12SwapChain(); void Resize(UINT width, UINT height); @@ -50,4 +50,5 @@ class GDX12SwapChain : public IRenderPassLink D3D12_VIEWPORT _screenViewport; D3D12_RECT _screenScissorRect; + bool _VSync; }; diff --git a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp index 65f870d..f280ebf 100644 --- a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp @@ -6,10 +6,10 @@ #include GDX12SwapChain::GDX12SwapChain(GDX12Device* device, HWND hwnd, - DXGI_FORMAT format, UINT bufferCount, UINT width, UINT height, GDX12DescriptorHeap* rtvHeap) + DXGI_FORMAT format, UINT bufferCount, UINT width, UINT height, GDX12DescriptorHeap* rtvHeap, bool vSync) : _device(device), _hwnd(hwnd), _format(format), _bufferCount(bufferCount), _currentBufferIndex(0), - _width(width), _height(height), _rtvHeap(rtvHeap) + _width(width), _height(height), _rtvHeap(rtvHeap), _VSync(vSync) { Reset(); @@ -108,7 +108,9 @@ void GDX12SwapChain::Resize(UINT width, UINT height) void GDX12SwapChain::Present() { - _swapChain->Present(0u, DXGI_PRESENT_ALLOW_TEARING); + UINT syncInterval = _VSync ? 1 : 0; + UINT presentFlags = _VSync ? 0 : DXGI_PRESENT_ALLOW_TEARING; + _swapChain->Present(syncInterval, presentFlags); _currentBufferIndex = (_currentBufferIndex + 1) % _bufferCount; } From f443518d112f7b997c58b965f428b8f787de7ca6 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Mon, 29 Jun 2026 18:59:09 +0300 Subject: [PATCH 11/46] small fixes --- Apps/App.Base/src/RenderModule.cpp | 2 +- .../Include/Engine.RendererDX12/GDX12SwapChain.h | 5 +++-- Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index fac8a2f..4a6fd63 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -609,7 +609,7 @@ void RenderModule::BuildBackBuffer() _window->GetWindowSize(width, height); _backBuffer = std::make_unique(_primaryDevice.get(), _window->GetWindowHandle(), - DXGI_FORMAT_R8G8B8A8_UNORM, 2, width, height, _primaryResources.RTVHeap.get(), false); + DXGI_FORMAT_R8G8B8A8_UNORM, 2, width, height, _primaryResources.RTVHeap.get()); GDX12TextureDesc desc; desc.CreateSRV = false; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h index 34797bd..d392d62 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h @@ -12,7 +12,7 @@ class GDX12SwapChain : public IRenderPassLink public: GDX12SwapChain(GDX12Device* device, HWND hwnd, DXGI_FORMAT format, UINT bufferCount, UINT width, UINT height, - GDX12DescriptorHeap* rtvHeap, bool VSync); + GDX12DescriptorHeap* rtvHeap); ~GDX12SwapChain(); void Resize(UINT width, UINT height); @@ -32,6 +32,8 @@ class GDX12SwapChain : public IRenderPassLink void Reset(); + bool bVSyncEnabled; + private: void CreateBuffers(); @@ -50,5 +52,4 @@ class GDX12SwapChain : public IRenderPassLink D3D12_VIEWPORT _screenViewport; D3D12_RECT _screenScissorRect; - bool _VSync; }; diff --git a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp index f280ebf..80dfc0c 100644 --- a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp @@ -6,10 +6,10 @@ #include GDX12SwapChain::GDX12SwapChain(GDX12Device* device, HWND hwnd, - DXGI_FORMAT format, UINT bufferCount, UINT width, UINT height, GDX12DescriptorHeap* rtvHeap, bool vSync) + 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), _VSync(vSync) + _width(width), _height(height), _rtvHeap(rtvHeap), bVSyncEnabled(false) { Reset(); @@ -108,8 +108,8 @@ void GDX12SwapChain::Resize(UINT width, UINT height) void GDX12SwapChain::Present() { - UINT syncInterval = _VSync ? 1 : 0; - UINT presentFlags = _VSync ? 0 : DXGI_PRESENT_ALLOW_TEARING; + UINT syncInterval = bVSyncEnabled ? 1 : 0; + UINT presentFlags = bVSyncEnabled ? 0 : DXGI_PRESENT_ALLOW_TEARING; _swapChain->Present(syncInterval, presentFlags); _currentBufferIndex = (_currentBufferIndex + 1) % _bufferCount; } From f60099c779acb572145ca5d83a9d45f196fb919a Mon Sep 17 00:00:00 2001 From: AMorunov Date: Tue, 30 Jun 2026 14:20:48 +0300 Subject: [PATCH 12/46] Added secondary GPU data upload --- .../App.Base/ECS/Components/CameraComponent.h | 2 +- .../Include/App.Base/Modules/RenderModule.h | 10 +- .../App.Base/Systems/GPUDataUpdateSystem.h | 2 +- Apps/App.Base/src/RenderModule.cpp | 110 +++++++++++++----- Apps/App.Base/src/SceneManagerModule.cpp | 16 +-- .../Engine.RendererDX12/GDX12Material.h | 5 +- .../RenderPasses/GDX12BackBufferClearPass.h | 2 +- .../RenderPasses/GDX12GPUCullingPass.h | 2 +- .../RenderPasses/GDX12OpaquePass.h | 3 +- .../RenderPasses/GDX12RenderPass.h | 2 +- .../RenderPasses/GDX12WBOITTransparencyPass.h | 3 +- .../src/GDX12DeviceResources.cpp | 4 +- 12 files changed, 109 insertions(+), 52 deletions(-) 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 6f026e0..a49b45f 100644 --- a/Apps/App.Base/Include/App.Base/ECS/Components/CameraComponent.h +++ b/Apps/App.Base/Include/App.Base/ECS/Components/CameraComponent.h @@ -16,7 +16,7 @@ struct CameraComponent : ComponentTag 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()), PrevViewProj(Identity4x4()) { } diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index f6714e7..9120a85 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -149,6 +149,12 @@ class RenderModule final : public Module GDX12WBOITTransparencyPass _WBOITTransparencyPass; GDX12WBOITCompositionPass _WBOITCompositionPass; - // sorted in execution order - std::vector _renderPassExecutionList; + // 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 7714f0e..2b3ebb8 100644 --- a/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h +++ b/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h @@ -150,7 +150,7 @@ class GPUDataUpdateSystem final : public System GDX12InstanceData instanceData; instanceData.TransformIndex = transformGPUData.CBufferIndex; - instanceData.MaterialIndex = renderer.Materials[subMesh.MaterialIndex]->_PrimaryCBufferIndex; + instanceData.MaterialIndex = renderer.Materials[subMesh.MaterialIndex]->_CBufferIndex; instanceData.BoundingBoxCenter = bounds.Center; instanceData.BoundingBoxExtents = bounds.Extents; diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 4a6fd63..7f078bb 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -7,7 +7,8 @@ #include "Common/ConsoleVariables.h" RenderModule::RenderModule(Window* window, GameTimer* timer) : - _dualGPUMode(false), _window(window), _timer(timer), _activeCamera(0) + _dualGPUMode(false), _window(window), _timer(timer), _activeCamera(0), + _primaryPipelineFlags(0), _secondaryPipelineFlags(0) { } @@ -62,7 +63,7 @@ void RenderModule::OnResize() const _backBuffer->Resize(width, height); _depthStencil->Resize(width, height); - for (auto& renderPass : _renderPassExecutionList) { renderPass->Resize(width, height); } + for (auto& renderPass : _primaryRenderPassExecutionList) { renderPass->Resize(width, height); } } GDX12Material* RenderModule::GetMaterialByName(const std::string& name) @@ -87,12 +88,26 @@ GDX12Material* RenderModule::CreateMaterial(const std::string& name) _materials[name] = std::unique_ptr(new GDX12Material()); _materials[name]->Name = name; - _materials[name]->_PrimaryCBufferIndex = _primaryResources.FrameConstants[0]->MaterialCache->GetElementCount(); + + if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_MATERIALS) + { + _materials[name]->_CBufferIndex = _primaryResources.FrameConstants[0]->MaterialCache->GetElementCount(); - for (auto& constants : _primaryResources.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(); @@ -119,8 +134,10 @@ GPUTexture* RenderModule::CreateTexture(const std::string& name, const Texture* _textures[name] = std::make_unique(); _textures[name]->Name = name; - _textures[name]->PrimaryDeviceTexture = CreateDX12Texture(name, &_primaryResources, texture); - if (_secondaryDevice) { _textures[name]->SecondaryDeviceTexture = CreateDX12Texture(name, &_secondaryResources, texture); } + 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); } } GDX12Texture* RenderModule::CreateDX12Texture(const std::string& name, GDX12DeviceResources* resources, const Texture* texture) @@ -283,8 +300,10 @@ GDX12Texture* RenderModule::CreateDX12Texture(const std::string& name, GDX12Devi void RenderModule::SubmitMesh(const Mesh* mesh, MeshHandle handle) { - _primaryResources.GeometryBuffer->AddMesh(mesh, handle); - if (_secondaryDevice) _secondaryResources.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) @@ -437,18 +456,26 @@ GDX12UploadBuffer* RenderModule::GetSecondaryIndirectComm void RenderModule::OnTransformComponentCreated(World& world, Entity entity, TransformComponent& component) { TransformCompGPUData gpuData; - gpuData.CBufferIndex = _primaryResources.FrameConstants[0]->TransformCache->GetElementCount(); _transformGPUData[entity] = gpuData; - for (auto& constants : _primaryResources.FrameConstants) + if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_INSTANCES) { - auto& CBuffer = constants->TransformCache; - CBuffer->Resize(CBuffer->GetElementCount() + 1); + _transformGPUData[entity].CBufferIndex = _primaryResources.FrameConstants[0]->TransformCache->GetElementCount(); + for (auto& constants : _primaryResources.FrameConstants) + { + auto& CBuffer = constants->TransformCache; + CBuffer->Resize(CBuffer->GetElementCount() + 1); + } } - if (_secondaryDevice) + if (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_INSTANCES) { - + _transformGPUData[entity].CBufferIndex = _secondaryResources.FrameConstants[0]->TransformCache->GetElementCount(); + for (auto& constants : _secondaryResources.FrameConstants) + { + auto& CBuffer = constants->TransformCache; + CBuffer->Resize(CBuffer->GetElementCount() + 1); + } } } @@ -499,28 +526,46 @@ void RenderModule::OnRenderComponentCreated(World& world, Entity entity, StaticM { auto& MeshGPUData = _primaryResources.GeometryBuffer->_meshCache[component.MeshHandler.GetValue()]; - for (int i = 0; i < MeshGPUData->SubMeshes.size(); i++) + if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_INSTANCES) { - component._CBufferIndices.push_back(_primaryResources.FrameConstants[0]->InstanceCache->GetElementCount()); - _primaryResources.IndirectCommandsCache->Resize(_primaryResources.IndirectCommandsCache->GetElementCount() + 1); - - for (auto& constants : _primaryResources.FrameConstants) + for (int i = 0; i < MeshGPUData->SubMeshes.size(); i++) { - auto& CBuffer = constants->InstanceCache; - CBuffer->Resize(CBuffer->GetElementCount() + 1); + component._CBufferIndices.push_back(_primaryResources.FrameConstants[0]->InstanceCache->GetElementCount()); + _primaryResources.IndirectCommandsCache->Resize(_primaryResources.IndirectCommandsCache->GetElementCount() + 1); - for (auto& buffers : constants->CameraVisibilityCommands) + for (auto& constants : _primaryResources.FrameConstants) { - buffers.VisibleOpaqueCommandsCache->Resize(buffers.VisibleOpaqueCommandsCache->GetElementCount() + 1); - buffers.VisibleTransparentCommandsCache->Resize(buffers.VisibleTransparentCommandsCache->GetElementCount() + 1); + 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 (_secondaryDevice) + if (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_INSTANCES) { + for (int i = 0; i < MeshGPUData->SubMeshes.size(); i++) + { + component._CBufferIndices.push_back(_secondaryResources.FrameConstants[0]->InstanceCache->GetElementCount()); + _secondaryResources.IndirectCommandsCache->Resize(_primaryResources.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); + } + } + } } } @@ -592,7 +637,7 @@ void RenderModule::OnRender() cmdList->EnhancedTextureBarrier({ CurrentBackBuffer->GetResource()->GetRenderTargetEnhBarrier() }); cmdList->ResourceBarrier({ _depthStencil->GetResource()->GetDepthWriteBarrier() }); - for (auto& renderPass : _renderPassExecutionList) { renderPass->Execute(cmdList); } + for (auto& renderPass : _primaryRenderPassExecutionList) { renderPass->Execute(cmdList); } cmdList->EnhancedTextureBarrier({ CurrentBackBuffer->GetResource()->GetPresentEnhBarrier() }); cmdList->ResourceBarrier({ _depthStencil->GetResource()->GetCommonBarrier() }); @@ -635,25 +680,30 @@ void RenderModule::ConfigureRenderPipeline() _backBufferClearPass.Initialize(&_primaryResources, width, height); _backBufferClearPass.LinkDependancies(_backBuffer.get(), _depthStencil.get()); + _primaryPipelineFlags |= _backBufferClearPass.GetFlags(); _gpuCullingPass.Initialize(&_primaryResources, width, height); _gpuCullingPass.LinkDependancies(&_activeCamera); + _primaryPipelineFlags |= _gpuCullingPass.GetFlags(); IRenderPassLink* opaqueAccum; IRenderPassLink* opaqueVelocity; _opaquePass.Initialize(&_primaryResources, width, height); _opaquePass.LinkDependancies(&_activeCamera, _depthStencil.get(), opaqueAccum, opaqueVelocity); + _primaryPipelineFlags |= _opaquePass.GetFlags(); IRenderPassLink* transparencyAccum; IRenderPassLink* transparencyRevealage; _WBOITTransparencyPass.Initialize(&_primaryResources, width, height); _WBOITTransparencyPass.LinkDependancies(&_activeCamera, _depthStencil.get(), transparencyAccum, transparencyRevealage); + _primaryPipelineFlags |= _WBOITTransparencyPass.GetFlags(); _WBOITCompositionPass.Initialize(&_primaryResources, width, height); _WBOITCompositionPass.LinkDependancies(opaqueAccum, transparencyAccum, transparencyRevealage, _backBuffer.get()); + _primaryPipelineFlags |= _WBOITCompositionPass.GetFlags(); - _renderPassExecutionList = { &_backBufferClearPass, &_gpuCullingPass, &_opaquePass, + _primaryRenderPassExecutionList = { &_backBufferClearPass, &_gpuCullingPass, &_opaquePass, &_WBOITTransparencyPass, &_WBOITCompositionPass }; } diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index ac114bd..409979e 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - //if (!LoadWorld("world1.yaml")) - //{ - // // todo runtime error or log - //} + if (!LoadWorld("world1.yaml")) + { + // todo runtime error or log + } /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - if (!LoadWorld(scenePath)) - { - // todo runtime error or log - } + //if (!LoadWorld(scenePath)) + //{ + // // todo runtime error or log + //} World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h index 8c1b25e..69ce30d 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h @@ -44,8 +44,7 @@ class GDX12Material bool UseBakedLighting; MaterialType Type; bool DirtyFlag; - UINT _PrimaryCBufferIndex; - UINT _SecondaryCBufferIndex; + UINT _CBufferIndex; private: friend class RenderModule; @@ -55,7 +54,7 @@ class GDX12Material Emissive(nullptr), Displacement(nullptr), Metallic(0.f), Roughness(1.f), Opacity(1.f), SpecularColor(0.0f, 0.0f, 0.0f), EmissiveColor(0.0f, 0.0f, 0.0f), HasNormalMap(false), HasSpecularMap(false), HasRoughnessMap(false), HasEmissiveMap(false), - UseBakedLighting(false), DirtyFlag(true), _PrimaryCBufferIndex(0), _SecondaryCBufferIndex(0), _numFramesDirty(0), Type(MaterialType::Opaque) + UseBakedLighting(false), DirtyFlag(true), _CBufferIndex(0), _numFramesDirty(0), Type(MaterialType::Opaque) { } diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h index 88942e8..6d862e0 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h @@ -5,7 +5,7 @@ class GDX12BackBufferClearPass : public GDX12RenderPass { public: GDX12BackBufferClearPass() : IN_OUT_currentBackBuffer(nullptr), IN_OUT_depthStencil(nullptr) - { _flags = RENDER_PASS_FLAG_PRESENTING; } + { _flags = RENDER_PASS_FLAG_NONE; } void LinkDependancies(IRenderPassLink* IN_OUT_currentBackBuffer, IRenderPassLink* IN_OUT_depthStencil) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h index 3813915..087e393 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h @@ -5,7 +5,7 @@ class GDX12GPUCullingPass : public GDX12RenderPass { public: GDX12GPUCullingPass() : IN_CameraCBIndex(nullptr) - { _flags = RENDER_PASS_FLAG_USE_CAMERAS; } + { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_INSTANCES; } void LinkDependancies(UINT* IN_CameraCBIndex) { diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h index 9105190..a219097 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -5,7 +5,8 @@ class GDX12OpaquePass : public GDX12RenderPass { public: GDX12OpaquePass() : IN_DepthStencil(nullptr), IN_CameraCBIndex(nullptr) - { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS; } + { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS + | RENDER_PASS_FLAG_USE_INSTANCES; } void LinkDependancies(UINT* IN_CameraCBIndex, IRenderPassLink* IN_DepthStencil, IRenderPassLink*& OUT_Accumulation, IRenderPassLink*& OUT_Velocity) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h index 63a28d5..1dea83c 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -18,7 +18,7 @@ enum ERenderPassFlags : uint32_t RENDER_PASS_FLAG_USE_MATERIALS = 1 << 1, RENDER_PASS_FLAG_USE_CAMERAS = 1 << 2, RENDER_PASS_FLAG_USE_LIGHTING = 1 << 3, - RENDER_PASS_FLAG_PRESENTING = 1 << 4 + RENDER_PASS_FLAG_USE_INSTANCES = 1 << 4 }; class GDX12RenderPass diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h index 0891fa3..53f8e07 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -5,7 +5,8 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass { public: GDX12WBOITTransparencyPass() : IN_DepthStencil(nullptr), IN_CameraCBIndex(nullptr) - { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS; } + { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS | + RENDER_PASS_FLAG_USE_INSTANCES; } void LinkDependancies(UINT* IN_CameraCBIndex, IRenderPassLink* IN_DepthStencil, IRenderPassLink*& OUT_Accumulation, IRenderPassLink*& OUT_Revealage) diff --git a/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp b/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp index 92a4489..a15e036 100644 --- a/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp @@ -89,14 +89,14 @@ void GDX12DeviceResources::UpdateMaterialCB(std::unordered_mapDiffuse) { materialConstants.DiffuseIndex = material->Diffuse->PrimaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } if (material->Normal) { materialConstants.NormalIndex = material->Normal->PrimaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } if (material->Displacement) { materialConstants.DisplacementIndex = material->Displacement->PrimaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } - currMaterialCB->CopyData(material->_PrimaryCBufferIndex, materialConstants); + currMaterialCB->CopyData(material->_CBufferIndex, materialConstants); } else { if (material->Diffuse) { materialConstants.DiffuseIndex = material->Diffuse->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } if (material->Normal) { materialConstants.NormalIndex = material->Normal->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } if (material->Displacement) { materialConstants.DisplacementIndex = material->Displacement->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } - currMaterialCB->CopyData(material->_SecondaryCBufferIndex, materialConstants); + currMaterialCB->CopyData(material->_CBufferIndex, materialConstants); } material->_numFramesDirty--; } From dad1408b85e1af1f6be38f8a7600f3ee3d6ddbf9 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Wed, 1 Jul 2026 22:22:28 +0300 Subject: [PATCH 13/46] Added texture transfering between GPUs --- .../Include/App.Base/Modules/RenderModule.h | 8 + .../App.Base/Systems/GPUDataUpdateSystem.h | 134 ++++++++++---- Apps/App.Base/src/RenderModule.cpp | 36 +++- Apps/App.Base/src/SceneManagerModule.cpp | 16 +- .../Engine.RendererDX12.vcxproj | 3 + .../Engine.RendererDX12.vcxproj.filters | 9 + .../Engine.RendererDX12/GDX12CommandList.h | 2 +- .../Engine.RendererDX12/GDX12Resource.h | 2 + .../Engine.RendererDX12/GDX12SharedTexture.h | 172 ++++++++++++++++++ .../GDX12TextureResource.h | 1 + .../Engine.RendererDX12/IRenderPassLink.h | 2 + .../GDX12TextureCopyFromSharedMemoryPass.h | 66 +++++++ .../GDX12TextureCopyToSharedMemoryPass.h | 54 ++++++ .../src/GDX12CommandList.cpp | 5 + .../Engine.RendererDX12/src/GDX12Resource.cpp | 6 + .../src/GDX12TextureResource.cpp | 4 + 16 files changed, 471 insertions(+), 49 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index 9120a85..c4470eb 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -10,6 +10,8 @@ #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.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" @@ -103,6 +105,9 @@ class RenderModule final : public Module GDX12UploadBuffer* GetPrimaryIndirectCommandsCache(); GDX12UploadBuffer* GetSecondaryIndirectCommandsCache(); + uint32_t GetPrimaryPipelineFlags(); + uint32_t GetSecondaryPipelineFlags(); + protected: void OnUpdate() override; void OnRender() override; @@ -148,6 +153,9 @@ class RenderModule final : public Module GDX12OpaquePass _opaquePass; GDX12WBOITTransparencyPass _WBOITTransparencyPass; GDX12WBOITCompositionPass _WBOITCompositionPass; + GDX12TextureCopyFromSharedMemoryPass _textureCopyFromSharedMemoryPass; + GDX12TextureCopyToSharedMemoryPass _textureCopyToSharedMemoryPass; + // Sorted in execution order std::vector _primaryRenderPassExecutionList; diff --git a/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h b/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h index 2b3ebb8..fda2b8c 100644 --- a/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h +++ b/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h @@ -66,8 +66,17 @@ class GPUDataUpdateSystem final : public System objConstants.PrevViewProj = camera.PrevViewProj; XMStoreFloat4x4(&camera.PrevViewProj, XMMatrixTranspose(view * proj)); - auto& CBuffer = renderModule->GetCurrentPrimaryFrameConstants()->CameraCB; - CBuffer->CopyData(camera._CBufferIndex, objConstants); + if (renderModule->GetPrimaryPipelineFlags() & RENDER_PASS_FLAG_USE_CAMERAS) + { + auto& CBuffer = renderModule->GetCurrentPrimaryFrameConstants()->CameraCB; + CBuffer->CopyData(camera._CBufferIndex, objConstants); + } + + if (renderModule->GetSecondaryPipelineFlags() & RENDER_PASS_FLAG_USE_CAMERAS) + { + auto& CBuffer = renderModule->GetCurrentSecondaryFrameConstants()->CameraCB; + CBuffer->CopyData(camera._CBufferIndex, objConstants); + } camera._numFramesDirty--; } @@ -100,8 +109,16 @@ class GPUDataUpdateSystem final : public System XMStoreFloat4x4(&GPUData.PrevWorld, world); - auto& CBuffer = renderModule->GetCurrentPrimaryFrameConstants()->TransformCache; - CBuffer->CopyData(GPUData.CBufferIndex, objConstants); + if (renderModule->GetPrimaryPipelineFlags() & RENDER_PASS_FLAG_USE_INSTANCES) + { + auto& CBuffer = renderModule->GetCurrentPrimaryFrameConstants()->TransformCache; + CBuffer->CopyData(GPUData.CBufferIndex, objConstants); + } + if (renderModule->GetSecondaryPipelineFlags() & RENDER_PASS_FLAG_USE_INSTANCES) + { + auto& CBuffer = renderModule->GetCurrentSecondaryFrameConstants()->TransformCache; + CBuffer->CopyData(GPUData.CBufferIndex, objConstants); + } GPUData.NumFramesDirty--; } @@ -110,9 +127,6 @@ class GPUDataUpdateSystem final : public System ecs.ForEach( [&ecs, &renderModule, &numFrames](Entity entity, TransformComponent& transform, StaticMeshRenderComponent& renderer) { - auto& instanceCache = renderModule->GetCurrentPrimaryFrameConstants()->InstanceCache; - auto indirectCommandsCache = renderModule->GetPrimaryIndirectCommandsCache(); - auto gpuMesh = renderModule->GetPrimaryGPUMesh(renderer.MeshHandler); auto& transformGPUData = renderModule->GetTransformGPUData(entity); if (renderer.DirtyFlag || transform.DirtyFlag) @@ -120,42 +134,94 @@ 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->GetSecondaryPipelineFlags() & 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->GetPrimaryPipelineFlags() & 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->GetSecondaryPipelineFlags() & 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--; } }); diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 7f078bb..150d3e4 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -15,6 +15,7 @@ RenderModule::RenderModule(Window* window, GameTimer* timer) : RenderModule::~RenderModule() { _primaryDevice->GetCommandQueue()->Flush(); + if (_dualGPUMode) { _secondaryDevice->GetCommandQueue()->Flush(); } GDX12ShaderCompiler::Shutdown(); } @@ -33,12 +34,12 @@ void RenderModule::Initialize() _primaryDevice->Role = DEVICE_ROLE_PRIMARY; _primaryResources.Initialize(_primaryDevice.get()); - if (false) + if (true) { _secondaryDevice = std::make_unique(); - _secondaryDevice->Initialize(GDX12DeviceFactory::GetMostPerformantAdapter().Get()); + _secondaryDevice->Initialize(GDX12DeviceFactory::GetDeviceDescriptors()[1].Adapter.Get()); _secondaryDevice->Role = DEVICE_ROLE_SECONDARY; - _secondaryResources.Initialize(_primaryDevice.get()); + _secondaryResources.Initialize(_secondaryDevice.get()); _dualGPUMode = true; } @@ -453,6 +454,16 @@ GDX12UploadBuffer* RenderModule::GetSecondaryIndirectComm return _secondaryResources.IndirectCommandsCache.get(); } +uint32_t RenderModule::GetPrimaryPipelineFlags() +{ + return _primaryPipelineFlags; +} + +uint32_t RenderModule::GetSecondaryPipelineFlags() +{ + return _secondaryPipelineFlags; +} + void RenderModule::OnTransformComponentCreated(World& world, Entity entity, TransformComponent& component) { TransformCompGPUData gpuData; @@ -604,10 +615,11 @@ void RenderModule::OnUpdate() } _primaryResources.UpdateMainCB(width, height, _timer); - _primaryResources.UpdateMaterialCB(_materials); + if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_MATERIALS) + { _primaryResources.UpdateMaterialCB(_materials); } //SecondaryDevice - if (_secondaryDevice) + if (_dualGPUMode) { _secondaryResources.CurrFrameConstantsIndex = (_secondaryResources.CurrFrameConstantsIndex + 1) % numFrames; @@ -620,7 +632,8 @@ void RenderModule::OnUpdate() } _secondaryResources.UpdateMainCB(width, height, _timer); - _secondaryResources.UpdateMaterialCB(_materials); + if (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_MATERIALS) + { _secondaryResources.UpdateMaterialCB(_materials); } } } @@ -703,6 +716,17 @@ void RenderModule::ConfigureRenderPipeline() _WBOITCompositionPass.LinkDependancies(opaqueAccum, transparencyAccum, transparencyRevealage, _backBuffer.get()); _primaryPipelineFlags |= _WBOITCompositionPass.GetFlags(); + // Texture transfer example + //IRenderPassLink* sharedMemoryVelocityBuffer; + //_textureCopyToSharedMemoryPass.Initialize(&_primaryResources, width, height); + //_textureCopyToSharedMemoryPass.LinkDependancies(&_secondaryResources, opaqueVelocity, sharedMemoryVelocityBuffer); + //_primaryPipelineFlags |= _textureCopyToSharedMemoryPass.GetFlags(); + + //IRenderPassLink* transferredVelocityBuffer; + //_textureCopyFromSharedMemoryPass.Initialize(&_secondaryResources, width, height); + //_textureCopyFromSharedMemoryPass.LinkDependancies(sharedMemoryVelocityBuffer, transferredVelocityBuffer); + //_secondaryPipelineFlags |= _textureCopyFromSharedMemoryPass.GetFlags(); + _primaryRenderPassExecutionList = { &_backBufferClearPass, &_gpuCullingPass, &_opaquePass, &_WBOITTransparencyPass, &_WBOITCompositionPass }; } diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index 409979e..ac114bd 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - if (!LoadWorld("world1.yaml")) - { - // todo runtime error or log - } + //if (!LoadWorld("world1.yaml")) + //{ + // // todo runtime error or log + //} /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - //if (!LoadWorld(scenePath)) - //{ - // // todo runtime error or log - //} + if (!LoadWorld(scenePath)) + { + // todo runtime error or log + } World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index 488d759..cee32df 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -24,8 +24,11 @@ + + + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index 9e6030a..562f056 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -96,6 +96,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + 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/GDX12Resource.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h index b1efe47..cc22845 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h @@ -28,6 +28,8 @@ class GDX12Resource void SetCurrentState(D3D12_RESOURCE_STATES newState); D3D12_RESOURCE_STATES GetCurrentState(); + void Reset(); + 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..f6d1d22 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h @@ -0,0 +1,172 @@ +#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) + { + } + + ~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(); + } + + void Release() + { + _sharedTexturePrimary.Reset(); + _sharedTextureSecondary.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; } + +private: + GDX12Device* _transferFromDeivce; + GDX12Device* _transferToDevice; + UINT64 _heapSize; + ComPtr _sharedHeap; + GDX12TextureResource _sharedTexturePrimary; + GDX12TextureResource _sharedTextureSecondary; + DXGI_FORMAT _format; + UINT _width; + UINT _height; + + 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 = 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)), + "Failed to create shared heap for cross-adapter texture"); + } + + 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), "Failed to create shared handle for heap"); + + 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, "Failed to open shared heap handle on secondary device"); + + 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)), + "Failed to create placed resource on secondary device"); + } +}; \ 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..e923964 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 diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h index bfbd2b1..9fadee6 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h @@ -1,9 +1,11 @@ #pragma once class GDX12Texture; +class GDX12SharedTexture; class IRenderPassLink { public: virtual GDX12Texture* GetTexture() = 0; + virtual GDX12SharedTexture* GetSharedTexture() { return nullptr; } }; \ 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..2c97fa7 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h @@ -0,0 +1,66 @@ +#pragma once +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" +#include "Engine.RendererDX12/GDX12SharedTexture.h" + +class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass +{ +public: + GDX12TextureCopyFromSharedMemoryPass() : IN_SharedTexture(nullptr), OUT_Texture(nullptr) + { _flags = RENDER_PASS_FLAG_NONE; } + + void LinkDependancies(IRenderPassLink* IN_SharedTexture, + IRenderPassLink*& OUT_Texture) + { + GDX12SharedTexture* sharedTexture = IN_SharedTexture->GetSharedTexture(); + + GDX12TextureDesc TextureDesc1; + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = sharedTexture->GetFormat(); + TextureDesc1.Width = sharedTexture->GetWidth(); + TextureDesc1.Height = sharedTexture->GetHeight(); + + 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; + + this->OUT_Texture = std::make_unique(TextureDesc1); + + OUT_Texture = this->OUT_Texture.get(); + } + + void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override + { + _resources = resources; + } + + // 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 on the device the texture was transferred to + void Execute(GDX12CommandList* cmdList) override + { + GDX12SharedTexture* inTexture = IN_SharedTexture->GetSharedTexture(); + + cmdList->BeginPixEvent("Texture Transfer From Shared Memory pass", Colors::ForestGreen); + cmdList->ResourceBarrier({ inTexture->GetSecondaryResource()->GetCopySourceBarrier(), + OUT_Texture->GetResource()->GetCopyDestBarrier() }); + cmdList->CopyResource(OUT_Texture->GetResource()->D3DResource.Get(), + inTexture->GetSecondaryResource()->D3DResource.Get()); + cmdList->ResourceBarrier({ inTexture->GetSecondaryResource()->GetCommonBarrier() }); + cmdList->EndPixEvent(); + } + + void Resize(UINT width, UINT height) override + { + OUT_Texture->Resize(width, height); + } + +private: + IRenderPassLink* IN_SharedTexture; + std::unique_ptr OUT_Texture; +}; \ No newline at end of file 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..037742a --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h @@ -0,0 +1,54 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" +#include "Engine.RendererDX12/GDX12SharedTexture.h" + +class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass +{ +public: + GDX12TextureCopyToSharedMemoryPass() : IN_Texture(nullptr) , _transferToResources(nullptr) + { _flags = RENDER_PASS_FLAG_NONE; } + + void LinkDependancies(GDX12DeviceResources* transferToResources, IRenderPassLink* IN_Texture, + IRenderPassLink*& OUT_SharedTexture) + { + _transferToResources = transferToResources; + this->IN_Texture = IN_Texture; + + this->OUT_SharedTexture = std::make_unique(); + this->OUT_SharedTexture->Initialize(_resources->Device, _transferToResources->Device, + IN_Texture->GetTexture()->GetWidth(), IN_Texture->GetTexture()->GetHeight(), + IN_Texture->GetTexture()->GetFormat()); + + OUT_SharedTexture = this->OUT_SharedTexture.get(); + } + + void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override + { + _resources = resources; + } + + // Copies texture from device the pass was initialized at to shared memory + // Can be later used to read it on another device with CopyFromSharedMemoryPass + void Execute(GDX12CommandList* cmdList) override + { + GDX12Texture* inTexture = IN_Texture->GetTexture(); + + cmdList->BeginPixEvent("Texture Transfer To Shared Memory pass", Colors::ForestGreen); + cmdList->ResourceBarrier({ inTexture->GetResource()->GetCopySourceBarrier(), + OUT_SharedTexture->GetPrimaryResource()->GetCopyDestBarrier() }); + cmdList->CopyResource(OUT_SharedTexture->GetPrimaryResource()->D3DResource.Get(), + inTexture->GetResource()->D3DResource.Get()); + cmdList->ResourceBarrier({ OUT_SharedTexture->GetPrimaryResource()->GetCommonBarrier() }); + cmdList->EndPixEvent(); + } + + void Resize(UINT width, UINT height) override + { + OUT_SharedTexture->Resize(width, height); + } + +private: + GDX12DeviceResources* _transferToResources; + IRenderPassLink* IN_Texture; + std::unique_ptr OUT_SharedTexture; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/src/GDX12CommandList.cpp b/Engine/Engine.RendererDX12/src/GDX12CommandList.cpp index c1a6f2c..dec71a8 100644 --- a/Engine/Engine.RendererDX12/src/GDX12CommandList.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12CommandList.cpp @@ -306,6 +306,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/GDX12Resource.cpp b/Engine/Engine.RendererDX12/src/GDX12Resource.cpp index 015bf22..db8390b 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Resource.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Resource.cpp @@ -140,3 +140,9 @@ D3D12_RESOURCE_STATES GDX12Resource::GetCurrentState() { return _currentState; } + +void GDX12Resource::Reset() +{ + D3DResource.Reset(); + _currentState = D3D12_RESOURCE_STATE_COMMON; +} diff --git a/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp b/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp index baa4d25..237adfc 100644 --- a/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp @@ -9,6 +9,10 @@ GDX12TextureResource::GDX12TextureResource(ComPtr resource) : _desc = D3DResource->GetDesc(); } +GDX12TextureResource::GDX12TextureResource() +{ +} + GDX12TextureResource::~GDX12TextureResource() { } From 1e9bef8e0ccaa13083601652fa366386ba8b1f24 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Thu, 2 Jul 2026 14:30:12 +0300 Subject: [PATCH 14/46] Upscaling pass preparations --- .../Include/App.Base/Modules/RenderModule.h | 4 +- Apps/App.Base/src/RenderModule.cpp | 23 ++- Apps/App.Base/src/SceneManagerModule.cpp | 16 +- .../Engine.RendererDX12.vcxproj | 1 + .../Engine.RendererDX12.vcxproj.filters | 3 + .../Engine.RendererDX12/IRenderPassLink.h | 18 +- .../RenderPasses/GDX12FSRUpscalePass.h | 182 ++++++++++++++++++ .../RenderPasses/GDX12GPUCullingPass.h | 13 +- .../RenderPasses/GDX12OpaquePass.h | 14 +- .../RenderPasses/GDX12RenderPass.h | 28 ++- .../RenderPasses/GDX12WBOITTransparencyPass.h | 13 +- 11 files changed, 275 insertions(+), 40 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index c4470eb..c59c518 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -44,7 +44,7 @@ class RenderModule final : public Module void Initialize() override; void Uninitialize() override; - void OnResize() const; + void OnResize(); GDX12Material* GetMaterialByName(const std::string& name); @@ -133,7 +133,7 @@ class RenderModule final : public Module std::unordered_map _transformGPUData; std::unordered_map _worldSubscriptions; - UINT _activeCamera; + RenderPipelineCommonData _RPcommonData; std::unique_ptr _primaryDevice; std::unique_ptr _secondaryDevice; diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 150d3e4..ae432f1 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -7,9 +7,10 @@ #include "Common/ConsoleVariables.h" RenderModule::RenderModule(Window* window, GameTimer* timer) : - _dualGPUMode(false), _window(window), _timer(timer), _activeCamera(0), + _dualGPUMode(false), _window(window), _timer(timer), _primaryPipelineFlags(0), _secondaryPipelineFlags(0) { + _RPcommonData.GameTimer = _timer; } RenderModule::~RenderModule() @@ -34,7 +35,7 @@ void RenderModule::Initialize() _primaryDevice->Role = DEVICE_ROLE_PRIMARY; _primaryResources.Initialize(_primaryDevice.get()); - if (true) + if (false) { _secondaryDevice = std::make_unique(); _secondaryDevice->Initialize(GDX12DeviceFactory::GetDeviceDescriptors()[1].Adapter.Get()); @@ -54,7 +55,7 @@ void RenderModule::Uninitialize() UnsubscribeFromSceneManager(); } -void RenderModule::OnResize() const +void RenderModule::OnResize() { _primaryDevice->GetCommandQueue()->Flush(); @@ -64,6 +65,9 @@ void RenderModule::OnResize() const _backBuffer->Resize(width, height); _depthStencil->Resize(width, height); + _RPcommonData.WindowWidth = width; + _RPcommonData.WindowHeight = height; + for (auto& renderPass : _primaryRenderPassExecutionList) { renderPass->Resize(width, height); } } @@ -309,7 +313,10 @@ void RenderModule::SubmitMesh(const Mesh* mesh, MeshHandle handle) void RenderModule::SetActiveCamera(CameraComponent* camera) { - _activeCamera = camera->_CBufferIndex; + _RPcommonData.ActiveCameraCBufferIndex = camera->_CBufferIndex; + _RPcommonData.ActiveCameraFOV = camera->FOV; + _RPcommonData.ActiveCameraNearPlane = camera->NearPlane; + _RPcommonData.ActiveCameraFarPlane = camera->FarPlane; } TransformCompGPUData& RenderModule::GetTransformGPUData(Entity entity) @@ -641,7 +648,7 @@ void RenderModule::OnRender() { auto cmdQueue = _primaryDevice->GetCommandQueue(); - cmdQueue->Flush(); + //cmdQueue->Flush(); auto cmdList = cmdQueue->GetCommandList(); auto CurrentBackBuffer = _backBuffer->GetCurrentBuffer(); @@ -696,19 +703,19 @@ void RenderModule::ConfigureRenderPipeline() _primaryPipelineFlags |= _backBufferClearPass.GetFlags(); _gpuCullingPass.Initialize(&_primaryResources, width, height); - _gpuCullingPass.LinkDependancies(&_activeCamera); + _gpuCullingPass.LinkDependancies(&_RPcommonData); _primaryPipelineFlags |= _gpuCullingPass.GetFlags(); IRenderPassLink* opaqueAccum; IRenderPassLink* opaqueVelocity; _opaquePass.Initialize(&_primaryResources, width, height); - _opaquePass.LinkDependancies(&_activeCamera, _depthStencil.get(), opaqueAccum, opaqueVelocity); + _opaquePass.LinkDependancies(&_RPcommonData, _depthStencil.get(), opaqueAccum, opaqueVelocity); _primaryPipelineFlags |= _opaquePass.GetFlags(); IRenderPassLink* transparencyAccum; IRenderPassLink* transparencyRevealage; _WBOITTransparencyPass.Initialize(&_primaryResources, width, height); - _WBOITTransparencyPass.LinkDependancies(&_activeCamera, _depthStencil.get(), + _WBOITTransparencyPass.LinkDependancies(&_RPcommonData, _depthStencil.get(), transparencyAccum, transparencyRevealage); _primaryPipelineFlags |= _WBOITTransparencyPass.GetFlags(); diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index ac114bd..409979e 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - //if (!LoadWorld("world1.yaml")) - //{ - // // todo runtime error or log - //} + if (!LoadWorld("world1.yaml")) + { + // todo runtime error or log + } /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - if (!LoadWorld(scenePath)) - { - // todo runtime error or log - } + //if (!LoadWorld(scenePath)) + //{ + // // todo runtime error or log + //} World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index cee32df..7356305 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -26,6 +26,7 @@ + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index 562f056..bfdae77 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -105,6 +105,9 @@ Header Files + + Header Files + diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h index 9fadee6..378bde8 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h @@ -2,10 +2,24 @@ class GDX12Texture; class GDX12SharedTexture; +class RenderPipelineCommonData; class IRenderPassLink { public: - virtual GDX12Texture* GetTexture() = 0; - virtual GDX12SharedTexture* GetSharedTexture() { return nullptr; } + virtual GDX12Texture* GetTexture() + { + OutputDebugStringA("ERROR: Forbidden interface call\n"); + return nullptr; + } + virtual GDX12SharedTexture* GetSharedTexture() + { + OutputDebugStringA("ERROR: Forbidden interface call\n"); + return nullptr; + } + virtual RenderPipelineCommonData* GetCommonData() + { + OutputDebugStringA("ERROR: Forbidden interface call\n"); + return nullptr; + } }; \ No newline at end of file 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..a9838d3 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -0,0 +1,182 @@ +#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 +{ + GDX12FSRUpscalePass() : IN_Texture(nullptr), IN_DepthBuffer(nullptr), + IN_MotionVectors(nullptr), OUT_UpscaledTexture(nullptr), _FFXContext(nullptr) + { _flags = RENDER_PASS_FLAG_NONE; } + + ~GDX12FSRUpscalePass() { ffxDestroyContext(&_FFXContext, nullptr); } + + void LinkDependancies(IRenderPassLink* IN_CommonData, IRenderPassLink* IN_Texture, IRenderPassLink* IN_DepthBuffer, + IRenderPassLink* IN_MotionVectors, IRenderPassLink*& OUT_UpscaledTexture) + { + this->IN_CommonData = IN_CommonData; + this->IN_Texture = IN_Texture; + this->IN_DepthBuffer = IN_DepthBuffer; + this->IN_MotionVectors = IN_MotionVectors; + + GDX12Texture* inputTexture = IN_Texture->GetTexture(); + + GDX12TextureDesc TextureDesc1; + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = inputTexture->GetFormat(); + TextureDesc1.Width = inputTexture->GetWidth(); + TextureDesc1.Height = inputTexture->GetHeight(); + + 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; + + this->OUT_UpscaledTexture = std::make_unique(TextureDesc1); + + OUT_UpscaledTexture = this->OUT_UpscaledTexture.get(); + } + + // Init with window size + void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override + { + _resources = resources; + + BuildFSRContext(); + } + + void Execute(GDX12CommandList* cmdList) override + { + RenderPipelineCommonData* commonData = IN_CommonData->GetCommonData(); + GDX12Texture* inputTexture = IN_Texture->GetTexture(); + GDX12Texture* depthStencil = IN_DepthBuffer->GetTexture(); + GDX12Texture* motionVectors = IN_MotionVectors->GetTexture(); + + ffxDispatchDescUpscale dispatchDesc; + dispatchDesc.header.type = FFX_API_DISPATCH_DESC_TYPE_UPSCALE; + dispatchDesc.commandList = cmdList->GetCommandList().Get(); + dispatchDesc.color = ffxApiGetResourceDX12(inputTexture->GetResource()->D3DResource.Get(), FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ); + 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->DownscaledResX, commonData->DownscaledResY }; + dispatchDesc.motionVectorScale = { 1.f, 1.f }; + dispatchDesc.upscaleSize = { commonData->WindowWidth, commonData->WindowHeight }; + dispatchDesc.cameraNear = commonData->ActiveCameraNearPlane; + dispatchDesc.cameraFar = commonData->ActiveCameraFarPlane; + dispatchDesc.cameraFovAngleVertical = commonData->ActiveCameraFOV; + + dispatchDesc.jitterOffset.x = 0; + dispatchDesc.jitterOffset.y = 0; + + dispatchDesc.enableSharpening = false; + dispatchDesc.sharpness = 0.8f; + dispatchDesc.frameTimeDelta = commonData->GameTimer->DeltaTime() * 1000.f; //expects milliseconds + dispatchDesc.reset = false; // set to true if camera teleports or moves not smoothly + + dispatchDesc.preExposure = 1.f; + dispatchDesc.viewSpaceToMetersFactor = 1.f; + + dispatchDesc.output = ffxApiGetResourceDX12(OUT_UpscaledTexture->GetResource()->D3DResource.Get(), FFX_API_RESOURCE_STATE_UNORDERED_ACCESS); + + 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; + + + 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()); + } + } + + // Resize with window size + void Resize(UINT width, UINT height) override + { + OUT_UpscaledTexture->Resize(width, height); + + ffxDestroyContext(&_FFXContext, nullptr); + BuildFSRContext(); + } + + void BuildFSRContext() + { + RenderPipelineCommonData* commonData = IN_CommonData->GetCommonData(); + + 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; + 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()); + } + + QueryRenderTargetResolution(&commonData->DownscaledResX, &commonData->DownscaledResY); + } + + // Function requires the pass to be initialized + // Returns renderTarget resolution based on internal FSRQualityMode parameter + void QueryRenderTargetResolution(UINT* ResolutionX, UINT* ResolutionY) + { + RenderPipelineCommonData* commonData = IN_CommonData->GetCommonData(); + + 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 = ResolutionX; + queryDesc.pOutRenderWidth = ResolutionY; + ffxQuery(&_FFXContext, &queryDesc.header); + } + + FfxApiUpscaleQualityMode FSRQualityMode = FFX_UPSCALE_QUALITY_MODE_QUALITY; +private: + IRenderPassLink* IN_CommonData; + IRenderPassLink* IN_Texture; + IRenderPassLink* IN_DepthBuffer; + IRenderPassLink* IN_MotionVectors; + ffxContext _FFXContext; + std::unique_ptr OUT_UpscaledTexture; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h index 087e393..5738f94 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h @@ -4,12 +4,12 @@ class GDX12GPUCullingPass : public GDX12RenderPass { public: - GDX12GPUCullingPass() : IN_CameraCBIndex(nullptr) + GDX12GPUCullingPass() : IN_CommonData(nullptr) { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_INSTANCES; } - void LinkDependancies(UINT* IN_CameraCBIndex) + void LinkDependancies(IRenderPassLink* IN_CommonData) { - this->IN_CameraCBIndex = IN_CameraCBIndex; + this->IN_CommonData = IN_CommonData; } void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override @@ -51,8 +51,9 @@ class GDX12GPUCullingPass : public GDX12RenderPass // automatically uses IN_OUT_CameraVisibilityBuffers from cameraCBIndex void Execute(GDX12CommandList* cmdList) override { + UINT cameraCBIndex = IN_CommonData->GetCommonData()->ActiveCameraCBufferIndex; auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; - auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[*IN_CameraCBIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[cameraCBIndex]; cmdList->BeginPixEvent("GPU Mesh Culling", Colors::Blue); cmdList->ResourceBarrier({ @@ -71,7 +72,7 @@ class GDX12GPUCullingPass : public GDX12RenderPass cmdList->SetComputeRootSignature(_cullingRS.get()); cmdList->SetPipelineState(_cullingPSO); cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); - cmdList->SetComputeRootConstantBufferView(0, currentFrameConstants->CameraCB->GetElementAddress(*IN_CameraCBIndex)); + cmdList->SetComputeRootConstantBufferView(0, currentFrameConstants->CameraCB->GetElementAddress(cameraCBIndex)); cmdList->SetComputeSRV(0, currentFrameConstants->InstanceCache->GetSRV()->GPUHandle); cmdList->SetComputeSRV(1, _resources->IndirectCommandsCache->GetSRV()->GPUHandle); cmdList->SetComputeSRV(2, currentFrameConstants->MaterialCache->GetSRV()->GPUHandle); @@ -96,5 +97,5 @@ class GDX12GPUCullingPass : public GDX12RenderPass std::unique_ptr _bufferClearRS; ComPtr _bufferClearPSO; - UINT* IN_CameraCBIndex; + IRenderPassLink* IN_CommonData; }; \ 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 index a219097..63a0307 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -4,14 +4,14 @@ class GDX12OpaquePass : public GDX12RenderPass { public: - GDX12OpaquePass() : IN_DepthStencil(nullptr), IN_CameraCBIndex(nullptr) + GDX12OpaquePass() : IN_DepthStencil(nullptr), IN_CommonData(nullptr) { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS | RENDER_PASS_FLAG_USE_INSTANCES; } - void LinkDependancies(UINT* IN_CameraCBIndex, IRenderPassLink* IN_DepthStencil, + void LinkDependancies(IRenderPassLink* IN_CommonData, IRenderPassLink* IN_DepthStencil, IRenderPassLink*& OUT_Accumulation, IRenderPassLink*& OUT_Velocity) { - this->IN_CameraCBIndex = IN_CameraCBIndex; + this->IN_CommonData = IN_CommonData; this->IN_DepthStencil = IN_DepthStencil; PostLinkInitialize(); @@ -95,8 +95,10 @@ class GDX12OpaquePass : public GDX12RenderPass // It requires GPUCullingPass to be executed beforehand void Execute(GDX12CommandList* cmdList) { + UINT cameraCBIndex = IN_CommonData->GetCommonData()->ActiveCameraCBufferIndex; + auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; - auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[*IN_CameraCBIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[cameraCBIndex]; GDX12Texture* depthStencil = IN_DepthStencil->GetTexture(); cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); @@ -107,7 +109,7 @@ class GDX12OpaquePass : public GDX12RenderPass cmdList->SetPipelineState(_opaquePSO.Get()); cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> - GetElementAddress(*IN_CameraCBIndex)); + GetElementAddress(cameraCBIndex)); cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier(), _velocityBuffer->GetResource()->GetRenderTargetBarrier() }); cmdList->SetRenderTargets({ _accumulationTexture.get(), _velocityBuffer.get() }, depthStencil); @@ -170,6 +172,6 @@ class GDX12OpaquePass : public GDX12RenderPass std::unique_ptr _accumulationTexture; std::unique_ptr _velocityBuffer; - UINT* IN_CameraCBIndex; + IRenderPassLink* IN_CommonData; IRenderPassLink* IN_DepthStencil; }; \ 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 index 1dea83c..165adda 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -11,6 +11,24 @@ #include "Engine.RendererDX12/GDX12Descriptor.h" #include "Engine.RendererDX12/IRenderPassLink.h" +class GameTimer; + +class RenderPipelineCommonData : public IRenderPassLink +{ +public: + virtual RenderPipelineCommonData* GetCommonData() override { return this; } + + UINT ActiveCameraCBufferIndex = -1; + float ActiveCameraFOV = 0; + float ActiveCameraNearPlane = 0; + float ActiveCameraFarPlane = 0; + GameTimer* GameTimer = nullptr; + UINT WindowWidth = 0; + UINT WindowHeight = 0; + UINT DownscaledResX = 0; + UINT DownscaledResY = 0; +}; + enum ERenderPassFlags : uint32_t { RENDER_PASS_FLAG_NONE = 0, @@ -18,7 +36,8 @@ enum ERenderPassFlags : uint32_t 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_INSTANCES = 1 << 4, + RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION = 1 << 5 }; class GDX12RenderPass @@ -30,12 +49,17 @@ class GDX12RenderPass virtual void Execute(GDX12CommandList* cmdList) {}; 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; } 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; - GDX12DeviceResources* _resources; }; \ 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 index 53f8e07..8b1e230 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -4,14 +4,14 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass { public: - GDX12WBOITTransparencyPass() : IN_DepthStencil(nullptr), IN_CameraCBIndex(nullptr) + GDX12WBOITTransparencyPass() : IN_DepthStencil(nullptr), IN_CommonData(nullptr) { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS | RENDER_PASS_FLAG_USE_INSTANCES; } - void LinkDependancies(UINT* IN_CameraCBIndex, IRenderPassLink* IN_DepthStencil, + void LinkDependancies(IRenderPassLink* IN_CommonData, IRenderPassLink* IN_DepthStencil, IRenderPassLink*& OUT_Accumulation, IRenderPassLink*& OUT_Revealage) { - this->IN_CameraCBIndex = IN_CameraCBIndex; + this->IN_CommonData = IN_CommonData; this->IN_DepthStencil = IN_DepthStencil; PostLinkInitialize(); @@ -94,8 +94,9 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass // It requires GPUCullingPass to be executed beforehand void Execute(GDX12CommandList* cmdList) { + UINT cameraCBIndex = IN_CommonData->GetCommonData()->ActiveCameraCBufferIndex; auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; - auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[*IN_CameraCBIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[cameraCBIndex]; GDX12Texture* depthStencil = IN_DepthStencil->GetTexture(); cmdList->BeginPixEvent("Transparent Render Pass", Colors::Aqua); @@ -108,7 +109,7 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass cmdList->SetPipelineState(_transparencyPSO); cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> - GetElementAddress(*IN_CameraCBIndex)); + GetElementAddress(cameraCBIndex)); cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier(), _revealageTexture->GetResource()->GetRenderTargetBarrier() }); @@ -198,6 +199,6 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass std::unique_ptr _accumulationTexture; std::unique_ptr _revealageTexture; - UINT* IN_CameraCBIndex; + IRenderPassLink* IN_CommonData; IRenderPassLink* IN_DepthStencil; }; \ No newline at end of file From 63aaf59afdfaef965f32354a664d46dc0b5e9c70 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Thu, 2 Jul 2026 14:53:38 +0300 Subject: [PATCH 15/46] Better RenderPass Data distribution --- Apps/App.Base/src/RenderModule.cpp | 27 +++++++------ Apps/App.Base/src/SceneManagerModule.cpp | 16 ++++---- .../Engine.RendererDX12/IRenderPassLink.h | 5 --- .../RenderPasses/GDX12BackBufferClearPass.h | 4 +- .../RenderPasses/GDX12FSRUpscalePass.h | 39 ++++++++----------- .../RenderPasses/GDX12GPUCullingPass.h | 18 +++------ .../RenderPasses/GDX12OpaquePass.h | 28 +++++++------ .../RenderPasses/GDX12RenderPass.h | 19 +++++---- .../GDX12TextureCopyFromSharedMemoryPass.h | 10 +++-- .../GDX12TextureCopyToSharedMemoryPass.h | 10 +++-- .../RenderPasses/GDX12WBOITCompositionPass.h | 4 +- .../RenderPasses/GDX12WBOITTransparencyPass.h | 29 +++++++------- 12 files changed, 96 insertions(+), 113 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index ae432f1..925ec27 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -68,7 +68,7 @@ void RenderModule::OnResize() _RPcommonData.WindowWidth = width; _RPcommonData.WindowHeight = height; - for (auto& renderPass : _primaryRenderPassExecutionList) { renderPass->Resize(width, height); } + for (auto& renderPass : _primaryRenderPassExecutionList) { renderPass->Resize(); } } GDX12Material* RenderModule::GetMaterialByName(const std::string& name) @@ -691,46 +691,45 @@ void RenderModule::BuildBackBuffer() desc.DSVDesc.Texture2D.MipSlice = 0; _depthStencil = std::make_unique(desc); + + _RPcommonData.WindowWidth = width; + _RPcommonData.WindowHeight = height; } void RenderModule::ConfigureRenderPipeline() { - uint16_t width, height; - _window->GetWindowSize(width, height); - - _backBufferClearPass.Initialize(&_primaryResources, width, height); + _backBufferClearPass.Initialize(&_primaryResources, &_RPcommonData); _backBufferClearPass.LinkDependancies(_backBuffer.get(), _depthStencil.get()); _primaryPipelineFlags |= _backBufferClearPass.GetFlags(); - _gpuCullingPass.Initialize(&_primaryResources, width, height); - _gpuCullingPass.LinkDependancies(&_RPcommonData); + _gpuCullingPass.Initialize(&_primaryResources, &_RPcommonData); _primaryPipelineFlags |= _gpuCullingPass.GetFlags(); IRenderPassLink* opaqueAccum; IRenderPassLink* opaqueVelocity; - _opaquePass.Initialize(&_primaryResources, width, height); - _opaquePass.LinkDependancies(&_RPcommonData, _depthStencil.get(), opaqueAccum, opaqueVelocity); + _opaquePass.Initialize(&_primaryResources, &_RPcommonData); + _opaquePass.LinkDependancies(_depthStencil.get(), opaqueAccum, opaqueVelocity); _primaryPipelineFlags |= _opaquePass.GetFlags(); IRenderPassLink* transparencyAccum; IRenderPassLink* transparencyRevealage; - _WBOITTransparencyPass.Initialize(&_primaryResources, width, height); - _WBOITTransparencyPass.LinkDependancies(&_RPcommonData, _depthStencil.get(), + _WBOITTransparencyPass.Initialize(&_primaryResources, &_RPcommonData); + _WBOITTransparencyPass.LinkDependancies(_depthStencil.get(), transparencyAccum, transparencyRevealage); _primaryPipelineFlags |= _WBOITTransparencyPass.GetFlags(); - _WBOITCompositionPass.Initialize(&_primaryResources, width, height); + _WBOITCompositionPass.Initialize(&_primaryResources, &_RPcommonData); _WBOITCompositionPass.LinkDependancies(opaqueAccum, transparencyAccum, transparencyRevealage, _backBuffer.get()); _primaryPipelineFlags |= _WBOITCompositionPass.GetFlags(); // Texture transfer example //IRenderPassLink* sharedMemoryVelocityBuffer; - //_textureCopyToSharedMemoryPass.Initialize(&_primaryResources, width, height); + //_textureCopyToSharedMemoryPass.Initialize(&_primaryResources, &_RPcommonData); //_textureCopyToSharedMemoryPass.LinkDependancies(&_secondaryResources, opaqueVelocity, sharedMemoryVelocityBuffer); //_primaryPipelineFlags |= _textureCopyToSharedMemoryPass.GetFlags(); //IRenderPassLink* transferredVelocityBuffer; - //_textureCopyFromSharedMemoryPass.Initialize(&_secondaryResources, width, height); + //_textureCopyFromSharedMemoryPass.Initialize(&_secondaryResources, &_RPcommonData); //_textureCopyFromSharedMemoryPass.LinkDependancies(sharedMemoryVelocityBuffer, transferredVelocityBuffer); //_secondaryPipelineFlags |= _textureCopyFromSharedMemoryPass.GetFlags(); diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index 409979e..ac114bd 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - if (!LoadWorld("world1.yaml")) - { - // todo runtime error or log - } + //if (!LoadWorld("world1.yaml")) + //{ + // // todo runtime error or log + //} /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - //if (!LoadWorld(scenePath)) - //{ - // // todo runtime error or log - //} + if (!LoadWorld(scenePath)) + { + // todo runtime error or log + } World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h index 378bde8..4f7fb6e 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h @@ -17,9 +17,4 @@ class IRenderPassLink OutputDebugStringA("ERROR: Forbidden interface call\n"); return nullptr; } - virtual RenderPipelineCommonData* GetCommonData() - { - OutputDebugStringA("ERROR: Forbidden interface call\n"); - return nullptr; - } }; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h index 6d862e0..93f9afc 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h @@ -14,9 +14,9 @@ class GDX12BackBufferClearPass : public GDX12RenderPass this->IN_OUT_depthStencil = IN_OUT_depthStencil; } - void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override + void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override { - _resources = resources; + GDX12RenderPass::Initialize(resources, commonData); } void Execute(GDX12CommandList* cmdList) override diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index a9838d3..6a7c5b4 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -14,10 +14,9 @@ class GDX12FSRUpscalePass : public GDX12RenderPass ~GDX12FSRUpscalePass() { ffxDestroyContext(&_FFXContext, nullptr); } - void LinkDependancies(IRenderPassLink* IN_CommonData, IRenderPassLink* IN_Texture, IRenderPassLink* IN_DepthBuffer, + void LinkDependancies(IRenderPassLink* IN_Texture, IRenderPassLink* IN_DepthBuffer, IRenderPassLink* IN_MotionVectors, IRenderPassLink*& OUT_UpscaledTexture) { - this->IN_CommonData = IN_CommonData; this->IN_Texture = IN_Texture; this->IN_DepthBuffer = IN_DepthBuffer; this->IN_MotionVectors = IN_MotionVectors; @@ -45,16 +44,15 @@ class GDX12FSRUpscalePass : public GDX12RenderPass } // Init with window size - void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override + void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override { - _resources = resources; + GDX12RenderPass::Initialize(resources, commonData); BuildFSRContext(); } void Execute(GDX12CommandList* cmdList) override { - RenderPipelineCommonData* commonData = IN_CommonData->GetCommonData(); GDX12Texture* inputTexture = IN_Texture->GetTexture(); GDX12Texture* depthStencil = IN_DepthBuffer->GetTexture(); GDX12Texture* motionVectors = IN_MotionVectors->GetTexture(); @@ -66,19 +64,19 @@ class GDX12FSRUpscalePass : public GDX12RenderPass 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->DownscaledResX, commonData->DownscaledResY }; + dispatchDesc.renderSize = { _commonData->DownscaledWidth, _commonData->DownscaledHeight }; dispatchDesc.motionVectorScale = { 1.f, 1.f }; - dispatchDesc.upscaleSize = { commonData->WindowWidth, commonData->WindowHeight }; - dispatchDesc.cameraNear = commonData->ActiveCameraNearPlane; - dispatchDesc.cameraFar = commonData->ActiveCameraFarPlane; - dispatchDesc.cameraFovAngleVertical = commonData->ActiveCameraFOV; + dispatchDesc.upscaleSize = { _commonData->WindowWidth, _commonData->WindowHeight }; + dispatchDesc.cameraNear = _commonData->ActiveCameraNearPlane; + dispatchDesc.cameraFar = _commonData->ActiveCameraFarPlane; + dispatchDesc.cameraFovAngleVertical = _commonData->ActiveCameraFOV; dispatchDesc.jitterOffset.x = 0; dispatchDesc.jitterOffset.y = 0; dispatchDesc.enableSharpening = false; dispatchDesc.sharpness = 0.8f; - dispatchDesc.frameTimeDelta = commonData->GameTimer->DeltaTime() * 1000.f; //expects milliseconds + dispatchDesc.frameTimeDelta = _commonData->GameTimer->DeltaTime() * 1000.f; //expects milliseconds dispatchDesc.reset = false; // set to true if camera teleports or moves not smoothly dispatchDesc.preExposure = 1.f; @@ -101,9 +99,9 @@ class GDX12FSRUpscalePass : public GDX12RenderPass } // Resize with window size - void Resize(UINT width, UINT height) override + void Resize() override { - OUT_UpscaledTexture->Resize(width, height); + OUT_UpscaledTexture->Resize(_commonData->WindowWidth, _commonData->WindowHeight); ffxDestroyContext(&_FFXContext, nullptr); BuildFSRContext(); @@ -111,8 +109,6 @@ class GDX12FSRUpscalePass : public GDX12RenderPass void BuildFSRContext() { - RenderPipelineCommonData* commonData = IN_CommonData->GetCommonData(); - ffxCreateBackendDX12Desc backendDesc = {}; backendDesc.header.type = FFX_API_CREATE_CONTEXT_DESC_TYPE_BACKEND_DX12; backendDesc.device = _resources->Device->GetDevice().Get(); @@ -120,8 +116,8 @@ class GDX12FSRUpscalePass : public GDX12RenderPass 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.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; upscaleDesc.fpMessage = [](uint32_t type, const wchar_t* message) { @@ -152,19 +148,17 @@ class GDX12FSRUpscalePass : public GDX12RenderPass OutputDebugStringA(errorMsg.c_str()); } - QueryRenderTargetResolution(&commonData->DownscaledResX, &commonData->DownscaledResY); + QueryRenderTargetResolution(&_commonData->DownscaledWidth, &_commonData->DownscaledHeight); } // Function requires the pass to be initialized // Returns renderTarget resolution based on internal FSRQualityMode parameter void QueryRenderTargetResolution(UINT* ResolutionX, UINT* ResolutionY) { - RenderPipelineCommonData* commonData = IN_CommonData->GetCommonData(); - ffxQueryDescUpscaleGetRenderResolutionFromQualityMode queryDesc = {}; queryDesc.header.type = FFX_API_QUERY_DESC_TYPE_UPSCALE_GETRENDERRESOLUTIONFROMQUALITYMODE; - queryDesc.displayHeight = commonData->WindowHeight; - queryDesc.displayWidth = commonData->WindowWidth; + queryDesc.displayHeight = _commonData->WindowHeight; + queryDesc.displayWidth = _commonData->WindowWidth; queryDesc.qualityMode = FSRQualityMode; queryDesc.pOutRenderHeight = ResolutionX; queryDesc.pOutRenderWidth = ResolutionY; @@ -173,7 +167,6 @@ class GDX12FSRUpscalePass : public GDX12RenderPass FfxApiUpscaleQualityMode FSRQualityMode = FFX_UPSCALE_QUALITY_MODE_QUALITY; private: - IRenderPassLink* IN_CommonData; IRenderPassLink* IN_Texture; IRenderPassLink* IN_DepthBuffer; IRenderPassLink* IN_MotionVectors; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h index 5738f94..2146597 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h @@ -4,17 +4,12 @@ class GDX12GPUCullingPass : public GDX12RenderPass { public: - GDX12GPUCullingPass() : IN_CommonData(nullptr) + GDX12GPUCullingPass() { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_INSTANCES; } - void LinkDependancies(IRenderPassLink* IN_CommonData) + void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override { - this->IN_CommonData = IN_CommonData; - } - - void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override - { - _resources = resources; + GDX12RenderPass::Initialize(resources, commonData); // Shaders auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); @@ -51,9 +46,8 @@ class GDX12GPUCullingPass : public GDX12RenderPass // automatically uses IN_OUT_CameraVisibilityBuffers from cameraCBIndex void Execute(GDX12CommandList* cmdList) override { - UINT cameraCBIndex = IN_CommonData->GetCommonData()->ActiveCameraCBufferIndex; auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; - auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[cameraCBIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[_commonData->ActiveCameraCBufferIndex]; cmdList->BeginPixEvent("GPU Mesh Culling", Colors::Blue); cmdList->ResourceBarrier({ @@ -72,7 +66,7 @@ class GDX12GPUCullingPass : public GDX12RenderPass cmdList->SetComputeRootSignature(_cullingRS.get()); cmdList->SetPipelineState(_cullingPSO); cmdList->SetDescriptorHeaps({ _resources->SRV_UAV_Heap.get() }); - cmdList->SetComputeRootConstantBufferView(0, currentFrameConstants->CameraCB->GetElementAddress(cameraCBIndex)); + 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); @@ -96,6 +90,4 @@ class GDX12GPUCullingPass : public GDX12RenderPass ComPtr _bufferClearCS; std::unique_ptr _bufferClearRS; ComPtr _bufferClearPSO; - - IRenderPassLink* IN_CommonData; }; \ 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 index 63a0307..8830687 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -4,14 +4,13 @@ class GDX12OpaquePass : public GDX12RenderPass { public: - GDX12OpaquePass() : IN_DepthStencil(nullptr), IN_CommonData(nullptr) + GDX12OpaquePass() : IN_DepthStencil(nullptr) { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS | RENDER_PASS_FLAG_USE_INSTANCES; } - void LinkDependancies(IRenderPassLink* IN_CommonData, IRenderPassLink* IN_DepthStencil, + void LinkDependancies(IRenderPassLink* IN_DepthStencil, IRenderPassLink*& OUT_Accumulation, IRenderPassLink*& OUT_Velocity) { - this->IN_CommonData = IN_CommonData; this->IN_DepthStencil = IN_DepthStencil; PostLinkInitialize(); @@ -20,15 +19,15 @@ class GDX12OpaquePass : public GDX12RenderPass OUT_Velocity = _velocityBuffer.get(); } - void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override + void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override { - _resources = resources; + GDX12RenderPass::Initialize(resources, commonData); // Textures GDX12TextureDesc TextureDesc1; TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - TextureDesc1.Width = width; - TextureDesc1.Height = height; + 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(); @@ -95,10 +94,8 @@ class GDX12OpaquePass : public GDX12RenderPass // It requires GPUCullingPass to be executed beforehand void Execute(GDX12CommandList* cmdList) { - UINT cameraCBIndex = IN_CommonData->GetCommonData()->ActiveCameraCBufferIndex; - auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; - auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[cameraCBIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[_commonData->ActiveCameraCBufferIndex]; GDX12Texture* depthStencil = IN_DepthStencil->GetTexture(); cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); @@ -109,7 +106,7 @@ class GDX12OpaquePass : public GDX12RenderPass cmdList->SetPipelineState(_opaquePSO.Get()); cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> - GetElementAddress(cameraCBIndex)); + GetElementAddress(_commonData->ActiveCameraCBufferIndex)); cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier(), _velocityBuffer->GetResource()->GetRenderTargetBarrier() }); cmdList->SetRenderTargets({ _accumulationTexture.get(), _velocityBuffer.get() }, depthStencil); @@ -130,10 +127,12 @@ class GDX12OpaquePass : public GDX12RenderPass cmdList->EndPixEvent(); } - void Resize(UINT width, UINT height) override + void Resize() override { - _accumulationTexture->Resize(width, height); - _velocityBuffer->Resize(width, height); + 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; + _accumulationTexture->Resize(newWidth, newHeight); + _velocityBuffer->Resize(newWidth, newHeight); } private: @@ -172,6 +171,5 @@ class GDX12OpaquePass : public GDX12RenderPass std::unique_ptr _accumulationTexture; std::unique_ptr _velocityBuffer; - IRenderPassLink* IN_CommonData; IRenderPassLink* IN_DepthStencil; }; \ 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 index 165adda..810e718 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -13,11 +13,9 @@ class GameTimer; -class RenderPipelineCommonData : public IRenderPassLink +class RenderPipelineCommonData { public: - virtual RenderPipelineCommonData* GetCommonData() override { return this; } - UINT ActiveCameraCBufferIndex = -1; float ActiveCameraFOV = 0; float ActiveCameraNearPlane = 0; @@ -25,8 +23,8 @@ class RenderPipelineCommonData : public IRenderPassLink GameTimer* GameTimer = nullptr; UINT WindowWidth = 0; UINT WindowHeight = 0; - UINT DownscaledResX = 0; - UINT DownscaledResY = 0; + UINT DownscaledWidth = 0; + UINT DownscaledHeight = 0; }; enum ERenderPassFlags : uint32_t @@ -43,9 +41,13 @@ enum ERenderPassFlags : uint32_t class GDX12RenderPass { public: - GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE), _resources(nullptr) {} - virtual void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) {}; - virtual void Resize(UINT width, UINT height) {}; + GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE), _resources(nullptr), _commonData(nullptr) {} + virtual void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) + { + _resources = resources; + _commonData = commonData; + }; + virtual void Resize() {}; virtual void Execute(GDX12CommandList* cmdList) {}; uint32_t GetFlags() { return _flags; } @@ -61,5 +63,6 @@ class GDX12RenderPass // For example: if no RenderPasses has USE_TEXTURES, then GPU texture upload // will be skipped entirely for this GPU uint32_t _flags; + RenderPipelineCommonData* _commonData; GDX12DeviceResources* _resources; }; \ 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 index 2c97fa7..9ae958c 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h @@ -34,9 +34,9 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass OUT_Texture = this->OUT_Texture.get(); } - void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override + void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override { - _resources = resources; + GDX12RenderPass::Initialize(resources, commonData); } // Copies texture from shared memory onto device the pass was initialized on @@ -55,9 +55,11 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass cmdList->EndPixEvent(); } - void Resize(UINT width, UINT height) override + void Resize() override { - OUT_Texture->Resize(width, height); + 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_Texture->Resize(newWidth, newHeight); } private: diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h index 037742a..9da4b96 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h @@ -22,9 +22,9 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass OUT_SharedTexture = this->OUT_SharedTexture.get(); } - void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override + void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override { - _resources = resources; + GDX12RenderPass::Initialize(resources, commonData); } // Copies texture from device the pass was initialized at to shared memory @@ -42,9 +42,11 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass cmdList->EndPixEvent(); } - void Resize(UINT width, UINT height) override + void Resize() override { - OUT_SharedTexture->Resize(width, height); + 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_SharedTexture->Resize(newWidth, newHeight); } private: diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h index e2d119c..6733ae3 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h @@ -19,9 +19,9 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass PostLinkInitialize(); } - void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override + void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override { - _resources = resources; + GDX12RenderPass::Initialize(resources, commonData); // Shaders auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h index 8b1e230..6c72986 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -4,14 +4,13 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass { public: - GDX12WBOITTransparencyPass() : IN_DepthStencil(nullptr), IN_CommonData(nullptr) + 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; } - void LinkDependancies(IRenderPassLink* IN_CommonData, IRenderPassLink* IN_DepthStencil, - IRenderPassLink*& OUT_Accumulation, IRenderPassLink*& OUT_Revealage) + void LinkDependancies(IRenderPassLink* IN_DepthStencil, IRenderPassLink*& OUT_Accumulation, + IRenderPassLink*& OUT_Revealage) { - this->IN_CommonData = IN_CommonData; this->IN_DepthStencil = IN_DepthStencil; PostLinkInitialize(); @@ -20,15 +19,15 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass OUT_Revealage = _revealageTexture.get(); } - void Initialize(GDX12DeviceResources* resources, UINT width, UINT height) override + void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override { - _resources = resources; + GDX12RenderPass::Initialize(resources, commonData); // Textures GDX12TextureDesc TextureDesc1; TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - TextureDesc1.Width = width; - TextureDesc1.Height = height; + 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(); @@ -94,9 +93,8 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass // It requires GPUCullingPass to be executed beforehand void Execute(GDX12CommandList* cmdList) { - UINT cameraCBIndex = IN_CommonData->GetCommonData()->ActiveCameraCBufferIndex; auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; - auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[cameraCBIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[_commonData->ActiveCameraCBufferIndex]; GDX12Texture* depthStencil = IN_DepthStencil->GetTexture(); cmdList->BeginPixEvent("Transparent Render Pass", Colors::Aqua); @@ -109,7 +107,7 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass cmdList->SetPipelineState(_transparencyPSO); cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> - GetElementAddress(cameraCBIndex)); + GetElementAddress(_commonData->ActiveCameraCBufferIndex)); cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier(), _revealageTexture->GetResource()->GetRenderTargetBarrier() }); @@ -133,10 +131,12 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass cmdList->EndPixEvent(); } - void Resize(UINT width, UINT height) override + void Resize() override { - _accumulationTexture->Resize(width, height); - _revealageTexture->Resize(width, height); + 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; + _accumulationTexture->Resize(newWidth, newHeight); + _revealageTexture->Resize(newWidth, newHeight); } private: @@ -199,6 +199,5 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass std::unique_ptr _accumulationTexture; std::unique_ptr _revealageTexture; - IRenderPassLink* IN_CommonData; IRenderPassLink* IN_DepthStencil; }; \ No newline at end of file From 4f384902a0d76ba159a24f4fa3f1e804f2f6b8c6 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Thu, 2 Jul 2026 18:01:39 +0300 Subject: [PATCH 16/46] FSR Upscaling pass implementation --- .../Include/App.Base/Modules/RenderModule.h | 6 + Apps/App.Base/src/RenderModule.cpp | 52 +++++--- .../Engine.RendererDX12.vcxproj | 1 + .../Engine.RendererDX12.vcxproj.filters | 3 + .../Engine.RendererDX12/GDX12Resource.h | 2 + .../GDX12TextureResource.h | 2 +- .../RenderPasses/GDX12BackBufferClearPass.h | 5 - .../RenderPasses/GDX12FSRUpscalePass.h | 63 +++++----- .../RenderPasses/GDX12OpaquePass.h | 106 ++++++++-------- .../RenderPasses/GDX12OutputToScreenPass.h | 39 ++++++ .../RenderPasses/GDX12RenderPass.h | 6 +- .../GDX12TextureCopyFromSharedMemoryPass.h | 5 - .../GDX12TextureCopyToSharedMemoryPass.h | 5 - .../RenderPasses/GDX12WBOITCompositionPass.h | 98 ++++++++++----- .../RenderPasses/GDX12WBOITTransparencyPass.h | 117 ++++++++---------- .../src/GDX12CommandList.cpp | 12 +- .../Engine.RendererDX12/src/GDX12Resource.cpp | 5 + .../Engine.RendererDX12/src/GDX12Texture.cpp | 4 +- .../src/GDX12TextureResource.cpp | 9 ++ 19 files changed, 323 insertions(+), 217 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index c59c518..395e572 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -12,6 +12,8 @@ #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.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" @@ -155,7 +157,11 @@ class RenderModule final : public Module GDX12WBOITCompositionPass _WBOITCompositionPass; GDX12TextureCopyFromSharedMemoryPass _textureCopyFromSharedMemoryPass; GDX12TextureCopyToSharedMemoryPass _textureCopyToSharedMemoryPass; + GDX12FSRUpscalePass _FSRUpscalePass; + GDX12OutputToScreenPass _outputPass; + // To be able to know where to get render target resolution when resizing + GDX12RenderPass* _upscaler; // Sorted in execution order std::vector _primaryRenderPassExecutionList; diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 925ec27..92d6684 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -8,7 +8,7 @@ RenderModule::RenderModule(Window* window, GameTimer* timer) : _dualGPUMode(false), _window(window), _timer(timer), - _primaryPipelineFlags(0), _secondaryPipelineFlags(0) + _primaryPipelineFlags(0), _secondaryPipelineFlags(0), _upscaler(nullptr) { _RPcommonData.GameTimer = _timer; } @@ -67,6 +67,7 @@ void RenderModule::OnResize() _RPcommonData.WindowWidth = width; _RPcommonData.WindowHeight = height; + if (_upscaler) { _upscaler->QueryRenderTargetResolution(); } for (auto& renderPass : _primaryRenderPassExecutionList) { renderPass->Resize(); } } @@ -132,7 +133,7 @@ GPUTexture* RenderModule::CreateTexture(const std::string& name, const 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; } @@ -698,29 +699,51 @@ void RenderModule::BuildBackBuffer() void RenderModule::ConfigureRenderPipeline() { - _backBufferClearPass.Initialize(&_primaryResources, &_RPcommonData); + std::vector _primaryRenderPassList = + { &_backBufferClearPass, &_gpuCullingPass, &_opaquePass, &_WBOITTransparencyPass, + &_WBOITCompositionPass, &_outputPass, &_FSRUpscalePass }; + + std::vector _secondaryRenderPassList = + { }; + + for (auto& primaryRenderPass : _primaryRenderPassList) + { + primaryRenderPass->Initialize(&_primaryResources, &_RPcommonData); + _primaryPipelineFlags |= primaryRenderPass->GetFlags(); + } + + _upscaler = &_FSRUpscalePass; + _upscaler->QueryRenderTargetResolution(); + _backBufferClearPass.LinkDependancies(_backBuffer.get(), _depthStencil.get()); - _primaryPipelineFlags |= _backBufferClearPass.GetFlags(); + _primaryRenderPassExecutionList.push_back(&_backBufferClearPass); - _gpuCullingPass.Initialize(&_primaryResources, &_RPcommonData); - _primaryPipelineFlags |= _gpuCullingPass.GetFlags(); + _primaryRenderPassExecutionList.push_back(&_gpuCullingPass); IRenderPassLink* opaqueAccum; IRenderPassLink* opaqueVelocity; - _opaquePass.Initialize(&_primaryResources, &_RPcommonData); + //_opaquePass.SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); _opaquePass.LinkDependancies(_depthStencil.get(), opaqueAccum, opaqueVelocity); - _primaryPipelineFlags |= _opaquePass.GetFlags(); + _primaryRenderPassExecutionList.push_back(&_opaquePass); IRenderPassLink* transparencyAccum; IRenderPassLink* transparencyRevealage; - _WBOITTransparencyPass.Initialize(&_primaryResources, &_RPcommonData); + //_WBOITTransparencyPass.SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); _WBOITTransparencyPass.LinkDependancies(_depthStencil.get(), transparencyAccum, transparencyRevealage); - _primaryPipelineFlags |= _WBOITTransparencyPass.GetFlags(); + _primaryRenderPassExecutionList.push_back(&_WBOITTransparencyPass); + + IRenderPassLink* composition; + //_WBOITCompositionPass.SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); + _WBOITCompositionPass.LinkDependancies(opaqueAccum, transparencyAccum, transparencyRevealage, composition); + _primaryRenderPassExecutionList.push_back(&_WBOITCompositionPass); - _WBOITCompositionPass.Initialize(&_primaryResources, &_RPcommonData); - _WBOITCompositionPass.LinkDependancies(opaqueAccum, transparencyAccum, transparencyRevealage, _backBuffer.get()); - _primaryPipelineFlags |= _WBOITCompositionPass.GetFlags(); + //IRenderPassLink* upscaledOutput; + //_FSRUpscalePass.LinkDependancies(composition, _depthStencil.get(), opaqueVelocity, upscaledOutput); + //_primaryRenderPassExecutionList.push_back(&_FSRUpscalePass); + + _outputPass.LinkDependancies(composition, _backBuffer.get()); + _primaryRenderPassExecutionList.push_back(&_outputPass); // Texture transfer example //IRenderPassLink* sharedMemoryVelocityBuffer; @@ -732,9 +755,6 @@ void RenderModule::ConfigureRenderPipeline() //_textureCopyFromSharedMemoryPass.Initialize(&_secondaryResources, &_RPcommonData); //_textureCopyFromSharedMemoryPass.LinkDependancies(sharedMemoryVelocityBuffer, transferredVelocityBuffer); //_secondaryPipelineFlags |= _textureCopyFromSharedMemoryPass.GetFlags(); - - _primaryRenderPassExecutionList = { &_backBufferClearPass, &_gpuCullingPass, &_opaquePass, - &_WBOITTransparencyPass, &_WBOITCompositionPass }; } void RenderModule::SubscribeToSceneManager() diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index 7356305..721be00 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -28,6 +28,7 @@ + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index bfdae77..4decf2c 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -108,6 +108,9 @@ Header Files + + Header Files + diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h index cc22845..bb8d798 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Resource.h @@ -30,6 +30,8 @@ class GDX12Resource void Reset(); + virtual void ResetState(); + ComPtr D3DResource; private: diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12TextureResource.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12TextureResource.h index e923964..77408ac 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12TextureResource.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12TextureResource.h @@ -29,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/RenderPasses/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h index 93f9afc..bf9b999 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h @@ -14,11 +14,6 @@ class GDX12BackBufferClearPass : public GDX12RenderPass this->IN_OUT_depthStencil = IN_OUT_depthStencil; } - void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override - { - GDX12RenderPass::Initialize(resources, commonData); - } - void Execute(GDX12CommandList* cmdList) override { GDX12Texture* currentBackBuffer = IN_OUT_currentBackBuffer->GetTexture(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index 6a7c5b4..6233adf 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -8,11 +8,12 @@ class GDX12FSRUpscalePass : public GDX12RenderPass { +public: GDX12FSRUpscalePass() : IN_Texture(nullptr), IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), OUT_UpscaledTexture(nullptr), _FFXContext(nullptr) - { _flags = RENDER_PASS_FLAG_NONE; } + { _flags = RENDER_PASS_FLAG_UPSCALER; } - ~GDX12FSRUpscalePass() { ffxDestroyContext(&_FFXContext, nullptr); } + ~GDX12FSRUpscalePass() { if (_FFXContext) { ffxDestroyContext(&_FFXContext, nullptr); } } void LinkDependancies(IRenderPassLink* IN_Texture, IRenderPassLink* IN_DepthBuffer, IRenderPassLink* IN_MotionVectors, IRenderPassLink*& OUT_UpscaledTexture) @@ -25,8 +26,8 @@ class GDX12FSRUpscalePass : public GDX12RenderPass GDX12TextureDesc TextureDesc1; TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = inputTexture->GetFormat(); - TextureDesc1.Width = inputTexture->GetWidth(); - TextureDesc1.Height = inputTexture->GetHeight(); + TextureDesc1.Width = _commonData->WindowWidth; + TextureDesc1.Height = _commonData->WindowHeight; TextureDesc1.CreateSRV = true; TextureDesc1.SRV_UAV_Heap = _resources->SRV_UAV_Heap.get(); @@ -49,6 +50,7 @@ class GDX12FSRUpscalePass : public GDX12RenderPass GDX12RenderPass::Initialize(resources, commonData); BuildFSRContext(); + QueryRenderTargetResolution(); } void Execute(GDX12CommandList* cmdList) override @@ -57,6 +59,7 @@ class GDX12FSRUpscalePass : public GDX12RenderPass 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(); @@ -69,14 +72,16 @@ class GDX12FSRUpscalePass : public GDX12RenderPass dispatchDesc.upscaleSize = { _commonData->WindowWidth, _commonData->WindowHeight }; dispatchDesc.cameraNear = _commonData->ActiveCameraNearPlane; dispatchDesc.cameraFar = _commonData->ActiveCameraFarPlane; - dispatchDesc.cameraFovAngleVertical = _commonData->ActiveCameraFOV; + dispatchDesc.cameraFovAngleVertical = XMConvertToRadians(_commonData->ActiveCameraFOV); dispatchDesc.jitterOffset.x = 0; dispatchDesc.jitterOffset.y = 0; dispatchDesc.enableSharpening = false; dispatchDesc.sharpness = 0.8f; - dispatchDesc.frameTimeDelta = _commonData->GameTimer->DeltaTime() * 1000.f; //expects milliseconds + // for whatever reason, it doesnt like it when frame time is lower than 1.f + float clampedTime = 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; @@ -96,9 +101,9 @@ class GDX12FSRUpscalePass : public GDX12RenderPass std::string errorMsg = "FSR DISPATCH ERROR: " + std::to_string(dispatchError) + " \n"; OutputDebugStringA(errorMsg.c_str()); } + cmdList->EndPixEvent(); } - // Resize with window size void Resize() override { OUT_UpscaledTexture->Resize(_commonData->WindowWidth, _commonData->WindowHeight); @@ -107,6 +112,26 @@ class GDX12FSRUpscalePass : public GDX12RenderPass 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); + } + + FfxApiUpscaleQualityMode FSRQualityMode = FFX_UPSCALE_QUALITY_MODE_QUALITY; +private: + IRenderPassLink* IN_Texture; + IRenderPassLink* IN_DepthBuffer; + IRenderPassLink* IN_MotionVectors; + ffxContext _FFXContext; + std::unique_ptr OUT_UpscaledTexture; + void BuildFSRContext() { ffxCreateBackendDX12Desc backendDesc = {}; @@ -147,29 +172,5 @@ class GDX12FSRUpscalePass : public GDX12RenderPass std::string errorMsg = "ERROR: FSR3 CONTEXT CREATION FAILED\n"; OutputDebugStringA(errorMsg.c_str()); } - - QueryRenderTargetResolution(&_commonData->DownscaledWidth, &_commonData->DownscaledHeight); } - - // Function requires the pass to be initialized - // Returns renderTarget resolution based on internal FSRQualityMode parameter - void QueryRenderTargetResolution(UINT* ResolutionX, UINT* ResolutionY) - { - 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 = ResolutionX; - queryDesc.pOutRenderWidth = ResolutionY; - ffxQuery(&_FFXContext, &queryDesc.header); - } - - FfxApiUpscaleQualityMode FSRQualityMode = FFX_UPSCALE_QUALITY_MODE_QUALITY; -private: - IRenderPassLink* IN_Texture; - IRenderPassLink* IN_DepthBuffer; - IRenderPassLink* IN_MotionVectors; - ffxContext _FFXContext; - std::unique_ptr OUT_UpscaledTexture; }; \ 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 index 8830687..4b7104c 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -19,11 +19,54 @@ class GDX12OpaquePass : public GDX12RenderPass OUT_Velocity = _velocityBuffer.get(); } - void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override + // VisibilityBuffers will automatically be selected from CameraCBIndex + // It requires GPUCullingPass to be executed beforehand + void Execute(GDX12CommandList* cmdList) { - GDX12RenderPass::Initialize(resources, commonData); + auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; + auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[_commonData->ActiveCameraCBufferIndex]; + GDX12Texture* depthStencil = IN_DepthStencil->GetTexture(); - // Textures + cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); + cmdList->SetViewport(_accumulationTexture->GetViewport()); + cmdList->SetScissorRect(_accumulationTexture->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(), + _accumulationTexture->GetResource()->GetRenderTargetBarrier(), + _velocityBuffer->GetResource()->GetRenderTargetBarrier() }); + cmdList->SetRenderTargets({ _accumulationTexture.get(), _velocityBuffer.get() }, depthStencil); + cmdList->ClearRenderTargetView(_accumulationTexture.get()); + cmdList->ClearRenderTargetView(_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; + _accumulationTexture->Resize(newWidth, newHeight); + _velocityBuffer->Resize(newWidth, newHeight); + } + +private: + void PostLinkInitialize() + { 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; @@ -56,8 +99,8 @@ class GDX12OpaquePass : public GDX12RenderPass // 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"); + _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; @@ -66,7 +109,7 @@ class GDX12OpaquePass : public GDX12RenderPass RSDesc1.StaticSamplers = GetStaticSamplers(); RSDesc1.SRVRanges.push_back(GDX12RootSignatureRange(Texture2D_RangeLength)); RSDesc1.Constants.push_back(1); - _opaqueRS = std::make_unique(resources->Device, RSDesc1); + _opaqueRS = std::make_unique(_resources->Device, RSDesc1); //Command Signatures std::vector args; @@ -85,59 +128,10 @@ class GDX12OpaquePass : public GDX12RenderPass CSDesc1.pArgumentDescs = args.data(); CSDesc1.NodeMask = 0; - resources->Device->GetDevice()->CreateCommandSignature(&CSDesc1, + _resources->Device->GetDevice()->CreateCommandSignature(&CSDesc1, _opaqueRS->GetRootSignature().Get(), IID_PPV_ARGS(&_opaqueCS)); - } - // VisibilityBuffers will automatically be selected from CameraCBIndex - // It requires GPUCullingPass to be executed beforehand - void Execute(GDX12CommandList* cmdList) - { - auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; - auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[_commonData->ActiveCameraCBufferIndex]; - GDX12Texture* depthStencil = IN_DepthStencil->GetTexture(); - - cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); - cmdList->ResourceBarrier({ - currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().GetIndirectArgsBarrier(), - currentCameraVisBuffers.OpaqueDrawCounter->GetResource().GetIndirectArgsBarrier() }); - cmdList->SetGraphicsRootSignature(_opaqueRS.get()); - cmdList->SetPipelineState(_opaquePSO.Get()); - cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); - cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> - GetElementAddress(_commonData->ActiveCameraCBufferIndex)); - cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier(), - _velocityBuffer->GetResource()->GetRenderTargetBarrier() }); - cmdList->SetRenderTargets({ _accumulationTexture.get(), _velocityBuffer.get() }, depthStencil); - cmdList->ClearRenderTargetView(_accumulationTexture.get()); - cmdList->ClearRenderTargetView(_velocityBuffer.get()); - 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->ExecuteIndirect(_opaqueCS.Get(), _resources->IndirectCommandsCache->GetElementCount(), - currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().D3DResource.Get(), 0, - currentCameraVisBuffers.OpaqueDrawCounter->GetResource().D3DResource.Get(), 0); - cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetSRVBarrier(), - _velocityBuffer->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; - _accumulationTexture->Resize(newWidth, newHeight); - _velocityBuffer->Resize(newWidth, newHeight); - } - -private: - void PostLinkInitialize() - { // Pipeline State Objects D3D12_GRAPHICS_PIPELINE_STATE_DESC PSODesc1 = {}; 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..83eab33 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h @@ -0,0 +1,39 @@ +#pragma once + +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" + +class GDX12OutputToScreenPass : public GDX12RenderPass +{ +public: + GDX12OutputToScreenPass() : IN_Texture(nullptr), IN_OUT_BackBuffer(nullptr) + { _flags = RENDER_PASS_FLAG_NONE; } + + void LinkDependancies(IRenderPassLink* IN_Texture, IRenderPassLink* IN_OUT_BackBuffer) + { + this->IN_Texture = IN_Texture; + this->IN_OUT_BackBuffer = IN_OUT_BackBuffer; + } + + void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override + { + GDX12RenderPass::Initialize(resources, commonData); + } + + void Execute(GDX12CommandList* cmdList) + { + GDX12Texture* inputTexture = IN_Texture->GetTexture(); + GDX12Texture* backBuffer = IN_OUT_BackBuffer->GetTexture(); + + cmdList->BeginPixEvent("Copy To Screen Pass", Colors::Aqua); + cmdList->ResourceBarrier({ inputTexture->GetResource()->GetCopySourceBarrier() }); + cmdList->EnhancedTextureBarrier({ backBuffer->GetResource()->GetCopyDestEnhBarrier() }); + + cmdList->CopyResource(backBuffer->GetResource()->D3DResource.Get(), + inputTexture->GetResource()->D3DResource.Get()); + cmdList->EndPixEvent(); + } + +private: + IRenderPassLink* IN_Texture; + IRenderPassLink* IN_OUT_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 index 810e718..3344863 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -35,7 +35,8 @@ enum ERenderPassFlags : uint32_t 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_USE_DOWNSCALED_RESOLUTION = 1 << 5, + RENDER_PASS_FLAG_UPSCALER = 1 << 6 }; class GDX12RenderPass @@ -49,6 +50,9 @@ class GDX12RenderPass }; 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() {}; uint32_t GetFlags() { return _flags; } void SetFlag(uint32_t flag, bool value) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h index 9ae958c..c032b23 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h @@ -34,11 +34,6 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass OUT_Texture = this->OUT_Texture.get(); } - void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override - { - GDX12RenderPass::Initialize(resources, commonData); - } - // 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 on the device the texture was transferred to diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h index 9da4b96..0b87d23 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h @@ -22,11 +22,6 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass OUT_SharedTexture = this->OUT_SharedTexture.get(); } - void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override - { - GDX12RenderPass::Initialize(resources, commonData); - } - // Copies texture from device the pass was initialized at to shared memory // Can be later used to read it on another device with CopyFromSharedMemoryPass void Execute(GDX12CommandList* cmdList) override diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h index 6733ae3..dc96f4d 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h @@ -5,34 +5,19 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass { public: GDX12WBOITCompositionPass() : IN_OpaqueScene(nullptr), IN_TransparencyAccum(nullptr), - IN_Revealage(nullptr), IN_OUT_Result(nullptr) + IN_Revealage(nullptr), OUT_Result(nullptr) { _flags = RENDER_PASS_FLAG_NONE; } void LinkDependancies(IRenderPassLink* IN_OpaqueScene, IRenderPassLink* IN_TransparencyAccum, - IRenderPassLink* IN_Revealage, IRenderPassLink* IN_OUT_Result) + IRenderPassLink* IN_Revealage, IRenderPassLink*& OUT_Result) { this->IN_OpaqueScene = IN_OpaqueScene; this->IN_TransparencyAccum = IN_TransparencyAccum; this->IN_Revealage = IN_Revealage; - this->IN_OUT_Result = IN_OUT_Result; PostLinkInitialize(); - } - - void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override - { - GDX12RenderPass::Initialize(resources, commonData); - - // 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); + OUT_Result = this->OUT_Result.get(); } void Execute(GDX12CommandList* cmdList) override @@ -40,15 +25,19 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass GDX12Texture* opaqueAccum = IN_OpaqueScene->GetTexture(); GDX12Texture* transparencyAccum = IN_TransparencyAccum->GetTexture(); GDX12Texture* transparencyRevealage = IN_Revealage->GetTexture(); - GDX12Texture* output = IN_OUT_Result->GetTexture(); cmdList->BeginPixEvent("Composition Render Pass", Colors::Bisque); - cmdList->SetViewport(output->GetViewport()); - cmdList->SetScissorRect(output->GetScissorRect()); + cmdList->SetViewport(OUT_Result->GetViewport()); + cmdList->SetScissorRect(OUT_Result->GetScissorRect()); cmdList->SetGraphicsRootSignature(_compositionRS.get()); cmdList->SetPipelineState(_compositionPSO.Get()); - cmdList->SetRenderTargets({ output }, nullptr); 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); @@ -56,9 +45,62 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass 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); + } 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; + void PostLinkInitialize() { + // 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 = std::make_unique(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 }; @@ -72,7 +114,7 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass PSODesc1.SampleMask = UINT_MAX; PSODesc1.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; PSODesc1.NumRenderTargets = 1; - PSODesc1.RTVFormats[0] = IN_OUT_Result->GetTexture()->GetFormat(); + PSODesc1.RTVFormats[0] = OUT_Result->GetFormat(); PSODesc1.SampleDesc.Count = 1; PSODesc1.SampleDesc.Quality = 0; @@ -82,14 +124,4 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass PSODesc1.PS = { reinterpret_cast(_compositionPS->GetBufferPointer()), _compositionPS->GetBufferSize() }; ThrowIfFailed(_resources->Device->GetDevice()->CreateGraphicsPipelineState(&PSODesc1, IID_PPV_ARGS(&_compositionPSO))); } - - ComPtr _compositionVS; - ComPtr _compositionPS; - std::unique_ptr _compositionRS; - ComPtr _compositionPSO; - - IRenderPassLink* IN_OpaqueScene; - IRenderPassLink* IN_TransparencyAccum; - IRenderPassLink* IN_Revealage; - IRenderPassLink* IN_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 index 6c72986..4f50552 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -19,15 +19,62 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass OUT_Revealage = _revealageTexture.get(); } - void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override + // VisibilityBuffers will automatically be selected from CameraCBIndex + // It requires GPUCullingPass to be executed beforehand + void Execute(GDX12CommandList* cmdList) + { + 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(_accumulationTexture->GetViewport()); + cmdList->SetScissorRect(_accumulationTexture->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(), + _accumulationTexture->GetResource()->GetRenderTargetBarrier(), + _revealageTexture->GetResource()->GetRenderTargetBarrier() }); + cmdList->SetRenderTargets({ _accumulationTexture.get(), _revealageTexture.get() }, + depthStencil); + cmdList->ClearRenderTargetView(_accumulationTexture.get()); + cmdList->ClearRenderTargetView(_revealageTexture.get()); + cmdList->ExecuteIndirect(_transparencyCS.Get(), _resources->IndirectCommandsCache->GetElementCount(), + currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().D3DResource.Get(), 0, + currentCameraVisBuffers.TransparentDrawCounter->GetResource().D3DResource.Get(), 0); + cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetSRVBarrier(), + _revealageTexture->GetResource()->GetSRVBarrier() }); + cmdList->EndPixEvent(); + } + + void Resize() override { - GDX12RenderPass::Initialize(resources, commonData); + 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; + _accumulationTexture->Resize(newWidth, newHeight); + _revealageTexture->Resize(newWidth, newHeight); + } +private: + void PostLinkInitialize() + { // 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.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(); @@ -55,8 +102,8 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass // 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"); + _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; @@ -65,7 +112,7 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass RSDesc1.StaticSamplers = GetStaticSamplers(); RSDesc1.SRVRanges.push_back(GDX12RootSignatureRange(Texture2D_RangeLength)); RSDesc1.Constants.push_back(1); - _transparencyRS = std::make_unique(resources->Device, RSDesc1); + _transparencyRS = std::make_unique(_resources->Device, RSDesc1); //Command Signatures std::vector args; @@ -84,64 +131,10 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass CSDesc1.pArgumentDescs = args.data(); CSDesc1.NodeMask = 0; - resources->Device->GetDevice()->CreateCommandSignature(&CSDesc1, + _resources->Device->GetDevice()->CreateCommandSignature(&CSDesc1, _transparencyRS->GetRootSignature().Get(), IID_PPV_ARGS(&_transparencyCS)); - } - - // VisibilityBuffers will automatically be selected from CameraCBIndex - // It requires GPUCullingPass to be executed beforehand - void Execute(GDX12CommandList* cmdList) - { - 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(depthStencil->GetViewport()); - cmdList->SetScissorRect(depthStencil->GetScissorRect()); - cmdList->ResourceBarrier({ - currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().GetIndirectArgsBarrier(), - currentCameraVisBuffers.TransparentDrawCounter->GetResource().GetIndirectArgsBarrier() }); - cmdList->SetGraphicsRootSignature(_transparencyRS.get()); - cmdList->SetPipelineState(_transparencyPSO); - cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); - cmdList->SetGraphicsRootConstantBufferView(2, currentFrameConstants->CameraCB-> - GetElementAddress(_commonData->ActiveCameraCBufferIndex)); - cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetRenderTargetBarrier(), - _revealageTexture->GetResource()->GetRenderTargetBarrier() }); - - cmdList->SetRenderTargets({ _accumulationTexture.get(), _revealageTexture.get() }, - depthStencil); - cmdList->ClearRenderTargetView(_accumulationTexture.get()); - cmdList->ClearRenderTargetView(_revealageTexture.get()); - - 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->ExecuteIndirect(_transparencyCS.Get(), _resources->IndirectCommandsCache->GetElementCount(), - currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().D3DResource.Get(), 0, - currentCameraVisBuffers.TransparentDrawCounter->GetResource().D3DResource.Get(), 0); - cmdList->ResourceBarrier({ _accumulationTexture->GetResource()->GetSRVBarrier(), - _revealageTexture->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; - _accumulationTexture->Resize(newWidth, newHeight); - _revealageTexture->Resize(newWidth, newHeight); - } - -private: - void PostLinkInitialize() - { // Pipeline State Objects D3D12_GRAPHICS_PIPELINE_STATE_DESC PSODesc1 = {}; PSODesc1.InputLayout = { _resources->InputLayouts["Default"].data(), (UINT)_resources->InputLayouts["Default"].size() }; diff --git a/Engine/Engine.RendererDX12/src/GDX12CommandList.cpp b/Engine/Engine.RendererDX12/src/GDX12CommandList.cpp index dec71a8..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) diff --git a/Engine/Engine.RendererDX12/src/GDX12Resource.cpp b/Engine/Engine.RendererDX12/src/GDX12Resource.cpp index db8390b..9269c04 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Resource.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Resource.cpp @@ -146,3 +146,8 @@ 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/GDX12Texture.cpp b/Engine/Engine.RendererDX12/src/GDX12Texture.cpp index 4859755..75813f5 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Texture.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Texture.cpp @@ -22,9 +22,10 @@ GDX12Texture::GDX12Texture(GDX12TextureDesc desc) : 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.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) { @@ -165,6 +166,7 @@ void GDX12Texture::CreateResource() if (!_resource) { _resource = std::make_unique(d3dResource); } else { _resource->D3DResource = d3dResource; } + _resource->ResetState(); } void GDX12Texture::CreateViews() diff --git a/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp b/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp index 237adfc..c18d4f3 100644 --- a/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp @@ -34,6 +34,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; From 90bc7fe8bfe3b8b49252c8e86a193108d101e337 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Fri, 3 Jul 2026 13:38:01 +0300 Subject: [PATCH 17/46] Better render pass linking --- Apps/App.Base/src/RenderModule.cpp | 28 ++++++----- .../RenderPasses/GDX12BackBufferClearPass.h | 14 ++++-- .../RenderPasses/GDX12FSRUpscalePass.h | 21 +++++---- .../RenderPasses/GDX12GPUCullingPass.h | 16 +++---- .../RenderPasses/GDX12OpaquePass.h | 42 +++++++++-------- .../RenderPasses/GDX12OutputToScreenPass.h | 13 ++---- .../RenderPasses/GDX12RenderPass.h | 14 ++++-- .../GDX12TextureCopyFromSharedMemoryPass.h | 9 ++-- .../GDX12TextureCopyToSharedMemoryPass.h | 17 ++++--- .../RenderPasses/GDX12WBOITCompositionPass.h | 15 +++--- .../RenderPasses/GDX12WBOITTransparencyPass.h | 46 ++++++++++--------- 11 files changed, 131 insertions(+), 104 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 92d6684..499d565 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -708,41 +708,45 @@ void RenderModule::ConfigureRenderPipeline() for (auto& primaryRenderPass : _primaryRenderPassList) { - primaryRenderPass->Initialize(&_primaryResources, &_RPcommonData); + primaryRenderPass->Initialize(&_primaryResources, &_secondaryResources, &_RPcommonData); _primaryPipelineFlags |= primaryRenderPass->GetFlags(); } _upscaler = &_FSRUpscalePass; _upscaler->QueryRenderTargetResolution(); - _backBufferClearPass.LinkDependancies(_backBuffer.get(), _depthStencil.get()); + std::vector clearPassInputs = { _backBuffer.get(), _depthStencil.get() }; + std::vector clearPassOutputs; + _backBufferClearPass.LinkDependancies(clearPassInputs, &clearPassOutputs); _primaryRenderPassExecutionList.push_back(&_backBufferClearPass); _primaryRenderPassExecutionList.push_back(&_gpuCullingPass); - IRenderPassLink* opaqueAccum; - IRenderPassLink* opaqueVelocity; + std::vector opaquePassInputs = { _depthStencil.get() }; + std::vector opaquePassOutputs; //_opaquePass.SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); - _opaquePass.LinkDependancies(_depthStencil.get(), opaqueAccum, opaqueVelocity); + _opaquePass.LinkDependancies(opaquePassInputs, &opaquePassOutputs); _primaryRenderPassExecutionList.push_back(&_opaquePass); - IRenderPassLink* transparencyAccum; - IRenderPassLink* transparencyRevealage; + std::vector transparencyPassInputs = { _depthStencil.get() }; + std::vector transparencyPassOutputs; //_WBOITTransparencyPass.SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); - _WBOITTransparencyPass.LinkDependancies(_depthStencil.get(), - transparencyAccum, transparencyRevealage); + _WBOITTransparencyPass.LinkDependancies(transparencyPassInputs, &transparencyPassOutputs); _primaryRenderPassExecutionList.push_back(&_WBOITTransparencyPass); - IRenderPassLink* composition; + std::vector compositionPassInputs = + { opaquePassOutputs[0], transparencyPassOutputs[0], transparencyPassOutputs[1] }; + std::vector compositionPassOutputs; //_WBOITCompositionPass.SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); - _WBOITCompositionPass.LinkDependancies(opaqueAccum, transparencyAccum, transparencyRevealage, composition); + _WBOITCompositionPass.LinkDependancies(compositionPassInputs, &compositionPassOutputs); _primaryRenderPassExecutionList.push_back(&_WBOITCompositionPass); //IRenderPassLink* upscaledOutput; //_FSRUpscalePass.LinkDependancies(composition, _depthStencil.get(), opaqueVelocity, upscaledOutput); //_primaryRenderPassExecutionList.push_back(&_FSRUpscalePass); - _outputPass.LinkDependancies(composition, _backBuffer.get()); + std::vector outputPassInputs = { compositionPassOutputs[0], _backBuffer.get() }; + _outputPass.LinkDependancies(outputPassInputs, nullptr); _primaryRenderPassExecutionList.push_back(&_outputPass); // Texture transfer example diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h index bf9b999..4428dc8 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h @@ -7,11 +7,17 @@ class GDX12BackBufferClearPass : public GDX12RenderPass GDX12BackBufferClearPass() : IN_OUT_currentBackBuffer(nullptr), IN_OUT_depthStencil(nullptr) { _flags = RENDER_PASS_FLAG_NONE; } - void LinkDependancies(IRenderPassLink* IN_OUT_currentBackBuffer, - IRenderPassLink* IN_OUT_depthStencil) + // Input 0 - back buffer + // Input 1 - depth stencil + // Output 0 - back buffer + // Output 1 - depth stencil + void LinkDependancies(std::vector inputs, std::vector* outputs) override { - this->IN_OUT_currentBackBuffer = IN_OUT_currentBackBuffer; - this->IN_OUT_depthStencil = IN_OUT_depthStencil; + IN_OUT_currentBackBuffer = inputs[0]; + IN_OUT_depthStencil = inputs[1]; + + outputs->push_back(IN_OUT_currentBackBuffer); + outputs->push_back(IN_OUT_depthStencil); } void Execute(GDX12CommandList* cmdList) override diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index 6233adf..23dbd99 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -15,12 +15,15 @@ class GDX12FSRUpscalePass : public GDX12RenderPass ~GDX12FSRUpscalePass() { if (_FFXContext) { ffxDestroyContext(&_FFXContext, nullptr); } } - void LinkDependancies(IRenderPassLink* IN_Texture, IRenderPassLink* IN_DepthBuffer, - IRenderPassLink* IN_MotionVectors, IRenderPassLink*& OUT_UpscaledTexture) + // Input 0 - InputTexture + // Input 1 - DepthStencil + // Input 2 - MotionVectors + // Output 0 - UpscaledTexture + void LinkDependancies(std::vector inputs, std::vector* outputs) override { - this->IN_Texture = IN_Texture; - this->IN_DepthBuffer = IN_DepthBuffer; - this->IN_MotionVectors = IN_MotionVectors; + IN_Texture = inputs[0]; + IN_DepthBuffer = inputs[1]; + IN_MotionVectors = inputs[2]; GDX12Texture* inputTexture = IN_Texture->GetTexture(); @@ -39,15 +42,15 @@ class GDX12FSRUpscalePass : public GDX12RenderPass TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; - this->OUT_UpscaledTexture = std::make_unique(TextureDesc1); + OUT_UpscaledTexture = std::make_unique(TextureDesc1); - OUT_UpscaledTexture = this->OUT_UpscaledTexture.get(); + outputs->push_back(OUT_UpscaledTexture.get()); } // Init with window size - void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override + void Initialize(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) override { - GDX12RenderPass::Initialize(resources, commonData); + GDX12RenderPass::Initialize(initOnResources, otherResources, commonData); BuildFSRContext(); QueryRenderTargetResolution(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h index 2146597..38cd35c 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h @@ -7,39 +7,39 @@ class GDX12GPUCullingPass : public GDX12RenderPass GDX12GPUCullingPass() { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_INSTANCES; } - void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override + void Initialize(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) override { - GDX12RenderPass::Initialize(resources, commonData); + GDX12RenderPass::Initialize(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"); + _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); + _cullingRS = std::make_unique(_resources->Device, RSDesc1); GDX12RootSignatureDesc RSDesc2; RSDesc2.NumSingleUAVSlots = 2; - _bufferClearRS = std::make_unique(resources->Device, RSDesc2); + _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( + 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( + ThrowIfFailed(_resources->Device->GetDevice()->CreateComputePipelineState( &PSODesc2, IID_PPV_ARGS(&_bufferClearPSO))); } diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h index 4b7104c..3d36f80 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -8,15 +8,17 @@ class GDX12OpaquePass : public GDX12RenderPass { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS | RENDER_PASS_FLAG_USE_INSTANCES; } - void LinkDependancies(IRenderPassLink* IN_DepthStencil, - IRenderPassLink*& OUT_Accumulation, IRenderPassLink*& OUT_Velocity) + // Input 0 - DepthStencil + // Output 0 - AccumulationTexture + // Output 1 - MotionVectors + void LinkDependancies(std::vector inputs, std::vector* outputs) override { - this->IN_DepthStencil = IN_DepthStencil; + IN_DepthStencil = inputs[0]; PostLinkInitialize(); - OUT_Accumulation = _accumulationTexture.get(); - OUT_Velocity = _velocityBuffer.get(); + outputs->push_back(OUT_Accumulation.get()); + outputs->push_back(OUT_VelocityBuffer.get()); } // VisibilityBuffers will automatically be selected from CameraCBIndex @@ -28,8 +30,8 @@ class GDX12OpaquePass : public GDX12RenderPass GDX12Texture* depthStencil = IN_DepthStencil->GetTexture(); cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); - cmdList->SetViewport(_accumulationTexture->GetViewport()); - cmdList->SetScissorRect(_accumulationTexture->GetScissorRect()); + 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)); @@ -45,11 +47,11 @@ class GDX12OpaquePass : public GDX12RenderPass cmdList->ResourceBarrier({ currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().GetIndirectArgsBarrier(), currentCameraVisBuffers.OpaqueDrawCounter->GetResource().GetIndirectArgsBarrier(), - _accumulationTexture->GetResource()->GetRenderTargetBarrier(), - _velocityBuffer->GetResource()->GetRenderTargetBarrier() }); - cmdList->SetRenderTargets({ _accumulationTexture.get(), _velocityBuffer.get() }, depthStencil); - cmdList->ClearRenderTargetView(_accumulationTexture.get()); - cmdList->ClearRenderTargetView(_velocityBuffer.get()); + OUT_Accumulation->GetResource()->GetRenderTargetBarrier(), + OUT_VelocityBuffer->GetResource()->GetRenderTargetBarrier() }); + cmdList->SetRenderTargets({ OUT_Accumulation.get(), OUT_VelocityBuffer.get() }, 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); @@ -60,8 +62,8 @@ class GDX12OpaquePass : public GDX12RenderPass { 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; - _accumulationTexture->Resize(newWidth, newHeight); - _velocityBuffer->Resize(newWidth, newHeight); + OUT_Accumulation->Resize(newWidth, newHeight); + OUT_VelocityBuffer->Resize(newWidth, newHeight); } private: @@ -89,13 +91,13 @@ class GDX12OpaquePass : public GDX12RenderPass TextureDesc1.RTVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.RTVDesc.Texture2D.MipSlice = 0; - _accumulationTexture = std::make_unique(TextureDesc1); + OUT_Accumulation = std::make_unique(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); - _velocityBuffer = std::make_unique(TextureDesc1); + OUT_VelocityBuffer = std::make_unique(TextureDesc1); // Shaders auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); @@ -146,8 +148,8 @@ class GDX12OpaquePass : public GDX12RenderPass PSODesc1.SampleMask = UINT_MAX; PSODesc1.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; PSODesc1.NumRenderTargets = 2; - PSODesc1.RTVFormats[0] = _accumulationTexture->GetFormat(); - PSODesc1.RTVFormats[1] = _velocityBuffer->GetFormat(); + PSODesc1.RTVFormats[0] = OUT_Accumulation->GetFormat(); + PSODesc1.RTVFormats[1] = OUT_VelocityBuffer->GetFormat(); PSODesc1.SampleDesc.Count = 1; PSODesc1.SampleDesc.Quality = 0; PSODesc1.DSVFormat = IN_DepthStencil->GetTexture()->GetFormat(); @@ -162,8 +164,8 @@ class GDX12OpaquePass : public GDX12RenderPass ComPtr _opaqueCS; ComPtr _opaquePSO; - std::unique_ptr _accumulationTexture; - std::unique_ptr _velocityBuffer; + std::unique_ptr OUT_Accumulation; + std::unique_ptr OUT_VelocityBuffer; IRenderPassLink* IN_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 index 83eab33..c08fb8a 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h @@ -8,15 +8,12 @@ class GDX12OutputToScreenPass : public GDX12RenderPass GDX12OutputToScreenPass() : IN_Texture(nullptr), IN_OUT_BackBuffer(nullptr) { _flags = RENDER_PASS_FLAG_NONE; } - void LinkDependancies(IRenderPassLink* IN_Texture, IRenderPassLink* IN_OUT_BackBuffer) + // Input 0 - InputTexture + // Input 1 - BackBuffer + void LinkDependancies(std::vector inputs, std::vector* outputs) override { - this->IN_Texture = IN_Texture; - this->IN_OUT_BackBuffer = IN_OUT_BackBuffer; - } - - void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) override - { - GDX12RenderPass::Initialize(resources, commonData); + IN_Texture = inputs[0]; + IN_OUT_BackBuffer = inputs[1]; } void Execute(GDX12CommandList* cmdList) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h index 3344863..0952536 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -42,10 +42,11 @@ enum ERenderPassFlags : uint32_t class GDX12RenderPass { public: - GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE), _resources(nullptr), _commonData(nullptr) {} - virtual void Initialize(GDX12DeviceResources* resources, RenderPipelineCommonData* commonData) + GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE), _resources(nullptr), _otherResources(nullptr), _commonData(nullptr) {} + virtual void Initialize(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) { - _resources = resources; + _resources = initOnResources; + _otherResources = otherResources; _commonData = commonData; }; virtual void Resize() {}; @@ -53,6 +54,8 @@ class GDX12RenderPass // Used by upscalers to determine downscaled render target size // And share it with all other passes virtual void QueryRenderTargetResolution() {}; + // Used by all passes to link inputs and outputs with other passes + virtual void LinkDependancies(std::vector inputs, std::vector* outputs) {}; uint32_t GetFlags() { return _flags; } void SetFlag(uint32_t flag, bool value) @@ -68,5 +71,10 @@ class GDX12RenderPass // 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; }; \ 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 index c032b23..6509de0 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h @@ -9,9 +9,12 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass GDX12TextureCopyFromSharedMemoryPass() : IN_SharedTexture(nullptr), OUT_Texture(nullptr) { _flags = RENDER_PASS_FLAG_NONE; } - void LinkDependancies(IRenderPassLink* IN_SharedTexture, - IRenderPassLink*& OUT_Texture) + // Input 0 - SharedTexture + // Output 0 - OutputTexture + void LinkDependancies(std::vector inputs, std::vector* outputs) override { + IN_SharedTexture = inputs[0]; + GDX12SharedTexture* sharedTexture = IN_SharedTexture->GetSharedTexture(); GDX12TextureDesc TextureDesc1; @@ -31,7 +34,7 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass this->OUT_Texture = std::make_unique(TextureDesc1); - OUT_Texture = this->OUT_Texture.get(); + outputs->push_back(OUT_Texture.get()); } // Copies texture from shared memory onto device the pass was initialized on diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h index 0b87d23..6ab1941 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h @@ -5,21 +5,21 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass { public: - GDX12TextureCopyToSharedMemoryPass() : IN_Texture(nullptr) , _transferToResources(nullptr) + GDX12TextureCopyToSharedMemoryPass() : IN_Texture(nullptr) { _flags = RENDER_PASS_FLAG_NONE; } - void LinkDependancies(GDX12DeviceResources* transferToResources, IRenderPassLink* IN_Texture, - IRenderPassLink*& OUT_SharedTexture) + // Input 0 - InputTexture + // Output 0 - SharedTexture + void LinkDependancies(std::vector inputs, std::vector* outputs) override { - _transferToResources = transferToResources; - this->IN_Texture = IN_Texture; + IN_Texture = inputs[0]; - this->OUT_SharedTexture = std::make_unique(); - this->OUT_SharedTexture->Initialize(_resources->Device, _transferToResources->Device, + OUT_SharedTexture = std::make_unique(); + OUT_SharedTexture->Initialize(_resources->Device, _otherResources->Device, IN_Texture->GetTexture()->GetWidth(), IN_Texture->GetTexture()->GetHeight(), IN_Texture->GetTexture()->GetFormat()); - OUT_SharedTexture = this->OUT_SharedTexture.get(); + outputs->push_back(OUT_SharedTexture.get()); } // Copies texture from device the pass was initialized at to shared memory @@ -45,7 +45,6 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass } private: - GDX12DeviceResources* _transferToResources; IRenderPassLink* IN_Texture; std::unique_ptr OUT_SharedTexture; }; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h index dc96f4d..c59feb1 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h @@ -8,16 +8,19 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass IN_Revealage(nullptr), OUT_Result(nullptr) { _flags = RENDER_PASS_FLAG_NONE; } - void LinkDependancies(IRenderPassLink* IN_OpaqueScene, IRenderPassLink* IN_TransparencyAccum, - IRenderPassLink* IN_Revealage, IRenderPassLink*& OUT_Result) + // Input 0 - OpaqueScene + // Input 1 - TransparencyAccumulation + // Input 2 - RevealageTexture + // Output 0 - CompositionResult + void LinkDependancies(std::vector inputs, std::vector* outputs) override { - this->IN_OpaqueScene = IN_OpaqueScene; - this->IN_TransparencyAccum = IN_TransparencyAccum; - this->IN_Revealage = IN_Revealage; + IN_OpaqueScene = inputs[0]; + IN_TransparencyAccum = inputs[1]; + IN_Revealage = inputs[2]; PostLinkInitialize(); - OUT_Result = this->OUT_Result.get(); + outputs->push_back(OUT_Result.get()); } void Execute(GDX12CommandList* cmdList) override diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h index 4f50552..822672c 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -8,15 +8,17 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS | RENDER_PASS_FLAG_USE_INSTANCES; } - void LinkDependancies(IRenderPassLink* IN_DepthStencil, IRenderPassLink*& OUT_Accumulation, - IRenderPassLink*& OUT_Revealage) + // Input 0 - DepthStencil + // Output 0 - TransparencyAccumulation + // Output 1 - RevealageTexture + void LinkDependancies(std::vector inputs, std::vector* outputs) override { - this->IN_DepthStencil = IN_DepthStencil; + IN_DepthStencil = inputs[0]; PostLinkInitialize(); - OUT_Accumulation = _accumulationTexture.get(); - OUT_Revealage = _revealageTexture.get(); + outputs->push_back(OUT_Accumulation.get()); + outputs->push_back(OUT_Revealage.get()); } // VisibilityBuffers will automatically be selected from CameraCBIndex @@ -28,8 +30,8 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass GDX12Texture* depthStencil = IN_DepthStencil->GetTexture(); cmdList->BeginPixEvent("Transparent Render Pass", Colors::Aqua); - cmdList->SetViewport(_accumulationTexture->GetViewport()); - cmdList->SetScissorRect(_accumulationTexture->GetScissorRect()); + cmdList->SetViewport(OUT_Accumulation->GetViewport()); + cmdList->SetScissorRect(OUT_Accumulation->GetScissorRect()); cmdList->SetGraphicsRootSignature(_transparencyRS.get()); cmdList->SetPipelineState(_transparencyPSO); cmdList->SetGraphicsRootConstantBufferView(1, currentFrameConstants->MainCB->GetElementAddress(0)); @@ -45,17 +47,17 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass cmdList->ResourceBarrier({ currentCameraVisBuffers.VisibleTransparentCommandsCache->GetResource().GetIndirectArgsBarrier(), currentCameraVisBuffers.TransparentDrawCounter->GetResource().GetIndirectArgsBarrier(), - _accumulationTexture->GetResource()->GetRenderTargetBarrier(), - _revealageTexture->GetResource()->GetRenderTargetBarrier() }); - cmdList->SetRenderTargets({ _accumulationTexture.get(), _revealageTexture.get() }, + OUT_Accumulation->GetResource()->GetRenderTargetBarrier(), + OUT_Revealage->GetResource()->GetRenderTargetBarrier() }); + cmdList->SetRenderTargets({ OUT_Accumulation.get(), OUT_Revealage.get() }, depthStencil); - cmdList->ClearRenderTargetView(_accumulationTexture.get()); - cmdList->ClearRenderTargetView(_revealageTexture.get()); + 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({ _accumulationTexture->GetResource()->GetSRVBarrier(), - _revealageTexture->GetResource()->GetSRVBarrier() }); + cmdList->ResourceBarrier({ OUT_Accumulation->GetResource()->GetSRVBarrier(), + OUT_Revealage->GetResource()->GetSRVBarrier() }); cmdList->EndPixEvent(); } @@ -63,8 +65,8 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass { 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; - _accumulationTexture->Resize(newWidth, newHeight); - _revealageTexture->Resize(newWidth, newHeight); + OUT_Accumulation->Resize(newWidth, newHeight); + OUT_Revealage->Resize(newWidth, newHeight); } private: @@ -93,12 +95,12 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass TextureDesc1.RTVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.RTVDesc.Texture2D.MipSlice = 0; - _accumulationTexture = std::make_unique(TextureDesc1); + OUT_Accumulation = std::make_unique(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(); - _revealageTexture = std::make_unique(TextureDesc1); + OUT_Revealage = std::make_unique(TextureDesc1); // Shaders auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); @@ -176,8 +178,8 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass PSODesc1.DepthStencilState.StencilEnable = false; PSODesc1.NumRenderTargets = 2; - PSODesc1.RTVFormats[0] = _accumulationTexture->GetFormat(); - PSODesc1.RTVFormats[1] = _revealageTexture->GetFormat(); + 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))); @@ -189,8 +191,8 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass ComPtr _transparencyCS; ComPtr _transparencyPSO; - std::unique_ptr _accumulationTexture; - std::unique_ptr _revealageTexture; + std::unique_ptr OUT_Accumulation; + std::unique_ptr OUT_Revealage; IRenderPassLink* IN_DepthStencil; }; \ No newline at end of file From b7c783da7d2dceb36f8e3e22a4e2e25794161d4d Mon Sep 17 00:00:00 2001 From: AMorunov Date: Fri, 3 Jul 2026 17:24:58 +0300 Subject: [PATCH 18/46] Device sync pass & bug fixes --- .../Include/App.Base/Modules/RenderModule.h | 4 + Apps/App.Base/src/RenderModule.cpp | 103 +++++++++++++----- Apps/App.Base/src/SceneManagerModule.cpp | 16 +-- .../Engine.RendererDX12.vcxproj | 1 + .../Engine.RendererDX12.vcxproj.filters | 3 + .../Engine.RendererDX12/GDX12CommandQueue.h | 10 +- .../RenderPasses/GDX12BackBufferClearPass.h | 2 + .../RenderPasses/GDX12OpaquePass.h | 2 +- .../RenderPasses/GDX12OutputToScreenPass.h | 4 +- .../RenderPasses/GDX12RenderPass.h | 3 +- .../RenderPasses/GDX12SyncPass.h | 12 ++ .../RenderPasses/GDX12WBOITTransparencyPass.h | 2 +- .../src/GDX12CommandQueue.cpp | 33 ++++-- 13 files changed, 143 insertions(+), 52 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12SyncPass.h diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index 395e572..7de7991 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -14,6 +14,7 @@ #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.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" @@ -119,6 +120,7 @@ class RenderModule final : public Module private: void BuildBackBuffer(); + void ShareFences(); void ConfigureRenderPipeline(); void SubscribeToSceneManager(); @@ -159,6 +161,8 @@ class RenderModule final : public Module GDX12TextureCopyToSharedMemoryPass _textureCopyToSharedMemoryPass; GDX12FSRUpscalePass _FSRUpscalePass; GDX12OutputToScreenPass _outputPass; + GDX12SyncPass _primarySyncPass; + GDX12SyncPass _secondarySyncPass; // To be able to know where to get render target resolution when resizing GDX12RenderPass* _upscaler; diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 499d565..9aa6549 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -35,7 +35,7 @@ void RenderModule::Initialize() _primaryDevice->Role = DEVICE_ROLE_PRIMARY; _primaryResources.Initialize(_primaryDevice.get()); - if (false) + if (true) { _secondaryDevice = std::make_unique(); _secondaryDevice->Initialize(GDX12DeviceFactory::GetDeviceDescriptors()[1].Adapter.Get()); @@ -45,6 +45,7 @@ void RenderModule::Initialize() } BuildBackBuffer(); + if (_dualGPUMode) { ShareFences(); } ConfigureRenderPipeline(); SubscribeToSceneManager(); @@ -619,14 +620,14 @@ void RenderModule::OnUpdate() if (frameConsts->FenceValue > cmdQueue->GetFence()->GetCompletedValue()) { - cmdQueue->WaitForFenceValue(frameConsts->FenceValue); + cmdQueue->CPUWaitForFenceValue(frameConsts->FenceValue); } _primaryResources.UpdateMainCB(width, height, _timer); if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_MATERIALS) { _primaryResources.UpdateMaterialCB(_materials); } - //SecondaryDevice + // same for SecondaryDevice if (_dualGPUMode) { _secondaryResources.CurrFrameConstantsIndex = (_secondaryResources.CurrFrameConstantsIndex + 1) % numFrames; @@ -636,7 +637,7 @@ void RenderModule::OnUpdate() if (frameConsts->FenceValue > cmdQueue->GetFence()->GetCompletedValue()) { - cmdQueue->WaitForFenceValue(frameConsts->FenceValue); + cmdQueue->CPUWaitForFenceValue(frameConsts->FenceValue); } _secondaryResources.UpdateMainCB(width, height, _timer); @@ -647,24 +648,46 @@ void RenderModule::OnUpdate() void RenderModule::OnRender() { - auto cmdQueue = _primaryDevice->GetCommandQueue(); - - //cmdQueue->Flush(); - - auto cmdList = cmdQueue->GetCommandList(); - auto CurrentBackBuffer = _backBuffer->GetCurrentBuffer(); - auto CurrentFrameConsts = GetCurrentPrimaryFrameConstants(); - - cmdList->EnhancedTextureBarrier({ CurrentBackBuffer->GetResource()->GetRenderTargetEnhBarrier() }); - cmdList->ResourceBarrier({ _depthStencil->GetResource()->GetDepthWriteBarrier() }); - - for (auto& renderPass : _primaryRenderPassExecutionList) { renderPass->Execute(cmdList); } - - 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(); } @@ -697,23 +720,48 @@ void RenderModule::BuildBackBuffer() _RPcommonData.WindowHeight = height; } +void RenderModule::ShareFences() +{ + HANDLE primaryhandle; + ThrowIfFailed(_primaryDevice->GetDevice()->CreateSharedHandle( + _primaryDevice->GetCommandQueue()->GetFence().Get(), + nullptr, GENERIC_ALL, nullptr, &primaryhandle)); + + ThrowIfFailed(_secondaryDevice->GetDevice()->OpenSharedHandle( + primaryhandle, + IID_PPV_ARGS(&_secondaryDevice->GetCommandQueue()->GetOtherFence()))); + + HANDLE secondaryhandle; + ThrowIfFailed(_secondaryDevice->GetDevice()->CreateSharedHandle( + _secondaryDevice->GetCommandQueue()->GetFence().Get(), + nullptr, GENERIC_ALL, nullptr, &secondaryhandle)); + + ThrowIfFailed(_primaryDevice->GetDevice()->OpenSharedHandle( + secondaryhandle, + IID_PPV_ARGS(&_primaryDevice->GetCommandQueue()->GetOtherFence()))); +} + void RenderModule::ConfigureRenderPipeline() { + // Primary device pipeline std::vector _primaryRenderPassList = { &_backBufferClearPass, &_gpuCullingPass, &_opaquePass, &_WBOITTransparencyPass, &_WBOITCompositionPass, &_outputPass, &_FSRUpscalePass }; - std::vector _secondaryRenderPassList = - { }; - for (auto& primaryRenderPass : _primaryRenderPassList) { primaryRenderPass->Initialize(&_primaryResources, &_secondaryResources, &_RPcommonData); _primaryPipelineFlags |= primaryRenderPass->GetFlags(); } - _upscaler = &_FSRUpscalePass; - _upscaler->QueryRenderTargetResolution(); + std::vector _secondaryRenderPassList = + { }; + + for (auto& secondaryRenderPass : _secondaryRenderPassList) + { + secondaryRenderPass->Initialize(&_secondaryResources, &_primaryResources, &_RPcommonData); + _secondaryPipelineFlags |= secondaryRenderPass->GetFlags(); + } std::vector clearPassInputs = { _backBuffer.get(), _depthStencil.get() }; std::vector clearPassOutputs; @@ -744,11 +792,14 @@ void RenderModule::ConfigureRenderPipeline() //IRenderPassLink* upscaledOutput; //_FSRUpscalePass.LinkDependancies(composition, _depthStencil.get(), opaqueVelocity, upscaledOutput); //_primaryRenderPassExecutionList.push_back(&_FSRUpscalePass); + //_upscaler = &_FSRUpscalePass; std::vector outputPassInputs = { compositionPassOutputs[0], _backBuffer.get() }; _outputPass.LinkDependancies(outputPassInputs, nullptr); _primaryRenderPassExecutionList.push_back(&_outputPass); + // SecondaryDevice pipeline + // Texture transfer example //IRenderPassLink* sharedMemoryVelocityBuffer; //_textureCopyToSharedMemoryPass.Initialize(&_primaryResources, &_RPcommonData); diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index ac114bd..409979e 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - //if (!LoadWorld("world1.yaml")) - //{ - // // todo runtime error or log - //} + if (!LoadWorld("world1.yaml")) + { + // todo runtime error or log + } /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - if (!LoadWorld(scenePath)) - { - // todo runtime error or log - } + //if (!LoadWorld(scenePath)) + //{ + // // todo runtime error or log + //} World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index 721be00..fcd44b5 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -29,6 +29,7 @@ + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index 4decf2c..fc16d71 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -111,6 +111,9 @@ Header Files + + Header Files + diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h index e81c9e6..b89e3ef 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h @@ -15,14 +15,16 @@ class GDX12CommandQueue const ComPtr& GetCommandQueue(); 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(); @@ -37,6 +39,10 @@ class GDX12CommandQueue ComPtr _commandQueue; ComPtr _fence; + //shared fence from another device + //null if _dualGPUMode is false + ComPtr _otherFence; + GDX12Device* _device; // Command Lists can be requested via GetCommandList() diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h index 4428dc8..cf15982 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h @@ -28,6 +28,8 @@ class GDX12BackBufferClearPass : public GDX12RenderPass cmdList->BeginPixEvent("Clear Back Buffer", Colors::Aqua); cmdList->SetViewport(currentBackBuffer->GetViewport()); cmdList->SetScissorRect(currentBackBuffer->GetScissorRect()); + cmdList->EnhancedTextureBarrier({ currentBackBuffer->GetResource()->GetRenderTargetEnhBarrier() }); + cmdList->ResourceBarrier({ depthStencil->GetResource()->GetDepthWriteBarrier() }); cmdList->SetRenderTargets({ currentBackBuffer }, depthStencil); cmdList->ClearRenderTargetView(currentBackBuffer); cmdList->ClearDepthStencilView(depthStencil); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h index 3d36f80..be018f2 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -23,7 +23,7 @@ class GDX12OpaquePass : public GDX12RenderPass // VisibilityBuffers will automatically be selected from CameraCBIndex // It requires GPUCullingPass to be executed beforehand - void Execute(GDX12CommandList* cmdList) + void Execute(GDX12CommandList* cmdList) override { auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[_commonData->ActiveCameraCBufferIndex]; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h index c08fb8a..83be198 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h @@ -16,7 +16,7 @@ class GDX12OutputToScreenPass : public GDX12RenderPass IN_OUT_BackBuffer = inputs[1]; } - void Execute(GDX12CommandList* cmdList) + void Execute(GDX12CommandList* cmdList) override { GDX12Texture* inputTexture = IN_Texture->GetTexture(); GDX12Texture* backBuffer = IN_OUT_BackBuffer->GetTexture(); @@ -24,9 +24,9 @@ class GDX12OutputToScreenPass : public GDX12RenderPass cmdList->BeginPixEvent("Copy To Screen Pass", Colors::Aqua); cmdList->ResourceBarrier({ inputTexture->GetResource()->GetCopySourceBarrier() }); cmdList->EnhancedTextureBarrier({ backBuffer->GetResource()->GetCopyDestEnhBarrier() }); - cmdList->CopyResource(backBuffer->GetResource()->D3DResource.Get(), inputTexture->GetResource()->D3DResource.Get()); + cmdList->EnhancedTextureBarrier({ backBuffer->GetResource()->GetPresentEnhBarrier() }); cmdList->EndPixEvent(); } diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h index 0952536..4d526d1 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -36,7 +36,8 @@ enum ERenderPassFlags : uint32_t 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_UPSCALER = 1 << 6, + RENDER_PASS_FLAG_SYNC_DEVICES = 1 << 7 }; class GDX12RenderPass 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/GDX12WBOITTransparencyPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h index 822672c..e089ea3 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -23,7 +23,7 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass // VisibilityBuffers will automatically be selected from CameraCBIndex // It requires GPUCullingPass to be executed beforehand - void Execute(GDX12CommandList* cmdList) + void Execute(GDX12CommandList* cmdList) override { auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[_commonData->ActiveCameraCBufferIndex]; diff --git a/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp b/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp index 73c382c..14f9686 100644 --- a/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp @@ -3,9 +3,7 @@ #include "Engine.RendererDX12/GDX12CommandList.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; @@ -14,7 +12,8 @@ GDX12CommandQueue::GDX12CommandQueue(GDX12Device* device) 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->GetDevice()->CreateFence(FenceValue, + D3D12_FENCE_FLAG_SHARED | D3D12_FENCE_FLAG_SHARED_CROSS_ADAPTER, IID_PPV_ARGS(&_fence))); } void GDX12CommandQueue::Reset() @@ -23,6 +22,7 @@ void GDX12CommandQueue::Reset() _fence.Reset(); _workingCommandLists.clear(); _availableCommandLists.clear(); + _otherFence.Reset(); } GDX12CommandQueue::~GDX12CommandQueue() @@ -67,23 +67,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 +93,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 +108,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() From f506b759dba44bebba477fd1abcd66fa0c925bb7 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Fri, 3 Jul 2026 18:03:58 +0300 Subject: [PATCH 19/46] Better RenderPass creation --- .../Include/App.Base/Modules/RenderModule.h | 16 +----- Apps/App.Base/src/RenderModule.cpp | 51 +++++++++---------- .../RenderPasses/GDX12FSRUpscalePass.h | 1 + .../RenderPasses/GDX12WBOITCompositionPass.h | 1 + .../RenderPasses/GDX12WBOITTransparencyPass.h | 22 ++++---- 5 files changed, 38 insertions(+), 53 deletions(-) diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index 7de7991..6a037e0 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -152,24 +152,12 @@ class RenderModule final : public Module std::unique_ptr _backBuffer; std::unique_ptr _depthStencil; - GDX12BackBufferClearPass _backBufferClearPass; - GDX12GPUCullingPass _gpuCullingPass; - GDX12OpaquePass _opaquePass; - GDX12WBOITTransparencyPass _WBOITTransparencyPass; - GDX12WBOITCompositionPass _WBOITCompositionPass; - GDX12TextureCopyFromSharedMemoryPass _textureCopyFromSharedMemoryPass; - GDX12TextureCopyToSharedMemoryPass _textureCopyToSharedMemoryPass; - GDX12FSRUpscalePass _FSRUpscalePass; - GDX12OutputToScreenPass _outputPass; - GDX12SyncPass _primarySyncPass; - GDX12SyncPass _secondarySyncPass; - // To be able to know where to get render target resolution when resizing GDX12RenderPass* _upscaler; // Sorted in execution order - std::vector _primaryRenderPassExecutionList; - std::vector _secondaryRenderPassExecutionList; + 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 diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 9aa6549..92d17c4 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -18,6 +18,10 @@ RenderModule::~RenderModule() _primaryDevice->GetCommandQueue()->Flush(); if (_dualGPUMode) { _secondaryDevice->GetCommandQueue()->Flush(); } + + while (!_primaryRenderPassExecutionList.empty()) { _primaryRenderPassExecutionList.pop_back(); } + while (!_secondaryRenderPassExecutionList.empty()) { _secondaryRenderPassExecutionList.pop_back(); } + GDX12ShaderCompiler::Shutdown(); } @@ -743,60 +747,51 @@ void RenderModule::ShareFences() void RenderModule::ConfigureRenderPipeline() { - // Primary device pipeline - std::vector _primaryRenderPassList = - { &_backBufferClearPass, &_gpuCullingPass, &_opaquePass, &_WBOITTransparencyPass, - &_WBOITCompositionPass, &_outputPass, &_FSRUpscalePass }; + _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()); - for (auto& primaryRenderPass : _primaryRenderPassList) + for (auto& primaryRenderPass : _primaryRenderPassExecutionList) { primaryRenderPass->Initialize(&_primaryResources, &_secondaryResources, &_RPcommonData); _primaryPipelineFlags |= primaryRenderPass->GetFlags(); } - std::vector _secondaryRenderPassList = - { }; + //add secondary passes here - for (auto& secondaryRenderPass : _secondaryRenderPassList) + for (auto& secondaryRenderPass : _secondaryRenderPassExecutionList) { secondaryRenderPass->Initialize(&_secondaryResources, &_primaryResources, &_RPcommonData); _secondaryPipelineFlags |= secondaryRenderPass->GetFlags(); } + GDX12RenderPass* clearPass = _primaryRenderPassExecutionList[0].get(); std::vector clearPassInputs = { _backBuffer.get(), _depthStencil.get() }; std::vector clearPassOutputs; - _backBufferClearPass.LinkDependancies(clearPassInputs, &clearPassOutputs); - _primaryRenderPassExecutionList.push_back(&_backBufferClearPass); - - _primaryRenderPassExecutionList.push_back(&_gpuCullingPass); + clearPass->LinkDependancies(clearPassInputs, &clearPassOutputs); + GDX12RenderPass* opaquePass = _primaryRenderPassExecutionList[2].get(); std::vector opaquePassInputs = { _depthStencil.get() }; std::vector opaquePassOutputs; - //_opaquePass.SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); - _opaquePass.LinkDependancies(opaquePassInputs, &opaquePassOutputs); - _primaryRenderPassExecutionList.push_back(&_opaquePass); + opaquePass->LinkDependancies(opaquePassInputs, &opaquePassOutputs); + GDX12RenderPass* transparencyPass = _primaryRenderPassExecutionList[3].get(); std::vector transparencyPassInputs = { _depthStencil.get() }; std::vector transparencyPassOutputs; - //_WBOITTransparencyPass.SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); - _WBOITTransparencyPass.LinkDependancies(transparencyPassInputs, &transparencyPassOutputs); - _primaryRenderPassExecutionList.push_back(&_WBOITTransparencyPass); + transparencyPass->LinkDependancies(transparencyPassInputs, &transparencyPassOutputs); + GDX12RenderPass* compositionPass = _primaryRenderPassExecutionList[4].get(); std::vector compositionPassInputs = { opaquePassOutputs[0], transparencyPassOutputs[0], transparencyPassOutputs[1] }; std::vector compositionPassOutputs; - //_WBOITCompositionPass.SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); - _WBOITCompositionPass.LinkDependancies(compositionPassInputs, &compositionPassOutputs); - _primaryRenderPassExecutionList.push_back(&_WBOITCompositionPass); - - //IRenderPassLink* upscaledOutput; - //_FSRUpscalePass.LinkDependancies(composition, _depthStencil.get(), opaqueVelocity, upscaledOutput); - //_primaryRenderPassExecutionList.push_back(&_FSRUpscalePass); - //_upscaler = &_FSRUpscalePass; + compositionPass->LinkDependancies(compositionPassInputs, &compositionPassOutputs); + GDX12RenderPass* outputPass = _primaryRenderPassExecutionList[5].get(); std::vector outputPassInputs = { compositionPassOutputs[0], _backBuffer.get() }; - _outputPass.LinkDependancies(outputPassInputs, nullptr); - _primaryRenderPassExecutionList.push_back(&_outputPass); + outputPass->LinkDependancies(outputPassInputs, nullptr); // SecondaryDevice pipeline diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index 23dbd99..dd8d1ba 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -128,6 +128,7 @@ class GDX12FSRUpscalePass : public GDX12RenderPass } FfxApiUpscaleQualityMode FSRQualityMode = FFX_UPSCALE_QUALITY_MODE_QUALITY; + private: IRenderPassLink* IN_Texture; IRenderPassLink* IN_DepthBuffer; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h index c59feb1..5f4b84c 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h @@ -55,6 +55,7 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass UINT newHeight = GetFlagValue(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION) ? _commonData->DownscaledHeight : _commonData->WindowHeight; OUT_Result->Resize(newWidth, newHeight); } + private: ComPtr _compositionVS; ComPtr _compositionPS; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h index e089ea3..f838708 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -70,6 +70,17 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass } 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; + void PostLinkInitialize() { // Textures @@ -184,15 +195,4 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass PSODesc1.PS = { reinterpret_cast(_transparencyPS->GetBufferPointer()), _transparencyPS->GetBufferSize() }; ThrowIfFailed(_resources->Device->GetDevice()->CreateGraphicsPipelineState(&PSODesc1, IID_PPV_ARGS(&_transparencyPSO))); } - - 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 From 3b9b118cdee4222429f8e02b97397d26d0369e7d Mon Sep 17 00:00:00 2001 From: AMorunov Date: Fri, 3 Jul 2026 18:34:31 +0300 Subject: [PATCH 20/46] fixed memory leaks --- Apps/App.Base/src/RenderModule.cpp | 15 ++++---- .../RenderPasses/GDX12BackBufferClearPass.h | 8 ++++- .../RenderPasses/GDX12FSRUpscalePass.h | 13 +++++-- .../RenderPasses/GDX12GPUCullingPass.h | 9 +++++ .../RenderPasses/GDX12OpaquePass.h | 36 ++++++++++++------- .../RenderPasses/GDX12OutputToScreenPass.h | 8 ++++- .../RenderPasses/GDX12RenderPass.h | 3 +- .../GDX12TextureCopyFromSharedMemoryPass.h | 8 ++++- .../GDX12TextureCopyToSharedMemoryPass.h | 8 ++++- .../RenderPasses/GDX12WBOITCompositionPass.h | 14 +++++++- .../RenderPasses/GDX12WBOITTransparencyPass.h | 14 +++++++- 11 files changed, 106 insertions(+), 30 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 92d17c4..edc4f45 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -18,9 +18,8 @@ RenderModule::~RenderModule() _primaryDevice->GetCommandQueue()->Flush(); if (_dualGPUMode) { _secondaryDevice->GetCommandQueue()->Flush(); } - - while (!_primaryRenderPassExecutionList.empty()) { _primaryRenderPassExecutionList.pop_back(); } - while (!_secondaryRenderPassExecutionList.empty()) { _secondaryRenderPassExecutionList.pop_back(); } + for (auto& renderpass : _primaryRenderPassExecutionList) { renderpass->ClearDenendencies(); } + for (auto& renderpass : _secondaryRenderPassExecutionList) { renderpass->ClearDenendencies(); } GDX12ShaderCompiler::Shutdown(); } @@ -771,27 +770,27 @@ void RenderModule::ConfigureRenderPipeline() GDX12RenderPass* clearPass = _primaryRenderPassExecutionList[0].get(); std::vector clearPassInputs = { _backBuffer.get(), _depthStencil.get() }; std::vector clearPassOutputs; - clearPass->LinkDependancies(clearPassInputs, &clearPassOutputs); + clearPass->LinkDependencies(clearPassInputs, &clearPassOutputs); GDX12RenderPass* opaquePass = _primaryRenderPassExecutionList[2].get(); std::vector opaquePassInputs = { _depthStencil.get() }; std::vector opaquePassOutputs; - opaquePass->LinkDependancies(opaquePassInputs, &opaquePassOutputs); + opaquePass->LinkDependencies(opaquePassInputs, &opaquePassOutputs); GDX12RenderPass* transparencyPass = _primaryRenderPassExecutionList[3].get(); std::vector transparencyPassInputs = { _depthStencil.get() }; std::vector transparencyPassOutputs; - transparencyPass->LinkDependancies(transparencyPassInputs, &transparencyPassOutputs); + transparencyPass->LinkDependencies(transparencyPassInputs, &transparencyPassOutputs); GDX12RenderPass* compositionPass = _primaryRenderPassExecutionList[4].get(); std::vector compositionPassInputs = { opaquePassOutputs[0], transparencyPassOutputs[0], transparencyPassOutputs[1] }; std::vector compositionPassOutputs; - compositionPass->LinkDependancies(compositionPassInputs, &compositionPassOutputs); + compositionPass->LinkDependencies(compositionPassInputs, &compositionPassOutputs); GDX12RenderPass* outputPass = _primaryRenderPassExecutionList[5].get(); std::vector outputPassInputs = { compositionPassOutputs[0], _backBuffer.get() }; - outputPass->LinkDependancies(outputPassInputs, nullptr); + outputPass->LinkDependencies(outputPassInputs, nullptr); // SecondaryDevice pipeline diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h index cf15982..f99a16a 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h @@ -11,7 +11,7 @@ class GDX12BackBufferClearPass : public GDX12RenderPass // Input 1 - depth stencil // Output 0 - back buffer // Output 1 - depth stencil - void LinkDependancies(std::vector inputs, std::vector* outputs) override + void LinkDependencies(std::vector inputs, std::vector* outputs) override { IN_OUT_currentBackBuffer = inputs[0]; IN_OUT_depthStencil = inputs[1]; @@ -36,6 +36,12 @@ class GDX12BackBufferClearPass : public GDX12RenderPass cmdList->EndPixEvent(); } + void ClearDenendencies() override + { + IN_OUT_currentBackBuffer = nullptr; + IN_OUT_depthStencil = nullptr; + } + private: IRenderPassLink* IN_OUT_currentBackBuffer; IRenderPassLink* IN_OUT_depthStencil; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index dd8d1ba..6586d54 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -12,14 +12,12 @@ class GDX12FSRUpscalePass : public GDX12RenderPass GDX12FSRUpscalePass() : IN_Texture(nullptr), IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), OUT_UpscaledTexture(nullptr), _FFXContext(nullptr) { _flags = RENDER_PASS_FLAG_UPSCALER; } - - ~GDX12FSRUpscalePass() { if (_FFXContext) { ffxDestroyContext(&_FFXContext, nullptr); } } // Input 0 - InputTexture // Input 1 - DepthStencil // Input 2 - MotionVectors // Output 0 - UpscaledTexture - void LinkDependancies(std::vector inputs, std::vector* outputs) override + void LinkDependencies(std::vector inputs, std::vector* outputs) override { IN_Texture = inputs[0]; IN_DepthBuffer = inputs[1]; @@ -129,6 +127,15 @@ class GDX12FSRUpscalePass : public GDX12RenderPass FfxApiUpscaleQualityMode FSRQualityMode = FFX_UPSCALE_QUALITY_MODE_QUALITY; + void ClearDenendencies() override + { + if (_FFXContext) { ffxDestroyContext(&_FFXContext, nullptr); } + IN_Texture = nullptr; + IN_DepthBuffer = nullptr; + IN_MotionVectors = nullptr; + OUT_UpscaledTexture.reset(); + } + private: IRenderPassLink* IN_Texture; IRenderPassLink* IN_DepthBuffer; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h index 38cd35c..975f1aa 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h @@ -82,6 +82,15 @@ class GDX12GPUCullingPass : public GDX12RenderPass cmdList->EndPixEvent(); } + void ClearDenendencies() override + { + _cullingRS.reset(); + _cullingPSO.Reset(); + _bufferClearCS.Reset(); + _bufferClearRS.reset(); + _bufferClearPSO.Reset(); + } + private: ComPtr _cullingCS; std::unique_ptr _cullingRS; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h index be018f2..a6cdb5e 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -11,7 +11,7 @@ class GDX12OpaquePass : public GDX12RenderPass // Input 0 - DepthStencil // Output 0 - AccumulationTexture // Output 1 - MotionVectors - void LinkDependancies(std::vector inputs, std::vector* outputs) override + void LinkDependencies(std::vector inputs, std::vector* outputs) override { IN_DepthStencil = inputs[0]; @@ -66,7 +66,30 @@ class GDX12OpaquePass : public GDX12RenderPass OUT_VelocityBuffer->Resize(newWidth, newHeight); } + void ClearDenendencies() override + { + OUT_Accumulation.reset(); + OUT_VelocityBuffer.reset(); + IN_DepthStencil = nullptr; + _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; + + IRenderPassLink* IN_DepthStencil; + void PostLinkInitialize() { GDX12TextureDesc TextureDesc1; @@ -157,15 +180,4 @@ class GDX12OpaquePass : public GDX12RenderPass PSODesc1.PS = { reinterpret_cast(_opaquePS->GetBufferPointer()), _opaquePS->GetBufferSize() }; ThrowIfFailed(_resources->Device->GetDevice()->CreateGraphicsPipelineState(&PSODesc1, IID_PPV_ARGS(&_opaquePSO))); } - - ComPtr _opaqueVS; - ComPtr _opaquePS; - std::unique_ptr _opaqueRS; - ComPtr _opaqueCS; - ComPtr _opaquePSO; - - std::unique_ptr OUT_Accumulation; - std::unique_ptr OUT_VelocityBuffer; - - IRenderPassLink* IN_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 index 83be198..a6db1a1 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h @@ -10,7 +10,7 @@ class GDX12OutputToScreenPass : public GDX12RenderPass // Input 0 - InputTexture // Input 1 - BackBuffer - void LinkDependancies(std::vector inputs, std::vector* outputs) override + void LinkDependencies(std::vector inputs, std::vector* outputs) override { IN_Texture = inputs[0]; IN_OUT_BackBuffer = inputs[1]; @@ -30,6 +30,12 @@ class GDX12OutputToScreenPass : public GDX12RenderPass cmdList->EndPixEvent(); } + void ClearDenendencies() override + { + IN_Texture = nullptr; + IN_OUT_BackBuffer = nullptr; + } + private: IRenderPassLink* IN_Texture; IRenderPassLink* IN_OUT_BackBuffer; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h index 4d526d1..2816dcc 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -56,7 +56,8 @@ class GDX12RenderPass // And share it with all other passes virtual void QueryRenderTargetResolution() {}; // Used by all passes to link inputs and outputs with other passes - virtual void LinkDependancies(std::vector inputs, std::vector* outputs) {}; + virtual void LinkDependencies(std::vector inputs, std::vector* outputs) {}; + virtual void ClearDenendencies() {} uint32_t GetFlags() { return _flags; } void SetFlag(uint32_t flag, bool value) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h index 6509de0..cd9b0ef 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h @@ -11,7 +11,7 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass // Input 0 - SharedTexture // Output 0 - OutputTexture - void LinkDependancies(std::vector inputs, std::vector* outputs) override + void LinkDependencies(std::vector inputs, std::vector* outputs) override { IN_SharedTexture = inputs[0]; @@ -60,6 +60,12 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass OUT_Texture->Resize(newWidth, newHeight); } + void ClearDenendencies() override + { + IN_SharedTexture = nullptr; + OUT_Texture.reset(); + } + private: IRenderPassLink* IN_SharedTexture; std::unique_ptr OUT_Texture; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h index 6ab1941..5060059 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h @@ -10,7 +10,7 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass // Input 0 - InputTexture // Output 0 - SharedTexture - void LinkDependancies(std::vector inputs, std::vector* outputs) override + void LinkDependencies(std::vector inputs, std::vector* outputs) override { IN_Texture = inputs[0]; @@ -44,6 +44,12 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass OUT_SharedTexture->Resize(newWidth, newHeight); } + void ClearDenendencies() override + { + IN_Texture = nullptr; + OUT_SharedTexture.reset(); + } + private: IRenderPassLink* IN_Texture; std::unique_ptr OUT_SharedTexture; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h index 5f4b84c..c98fc2f 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h @@ -12,7 +12,7 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass // Input 1 - TransparencyAccumulation // Input 2 - RevealageTexture // Output 0 - CompositionResult - void LinkDependancies(std::vector inputs, std::vector* outputs) override + void LinkDependencies(std::vector inputs, std::vector* outputs) override { IN_OpaqueScene = inputs[0]; IN_TransparencyAccum = inputs[1]; @@ -56,6 +56,18 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass OUT_Result->Resize(newWidth, newHeight); } + void ClearDenendencies() override + { + 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; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h index f838708..c559b1d 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -11,7 +11,7 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass // Input 0 - DepthStencil // Output 0 - TransparencyAccumulation // Output 1 - RevealageTexture - void LinkDependancies(std::vector inputs, std::vector* outputs) override + void LinkDependencies(std::vector inputs, std::vector* outputs) override { IN_DepthStencil = inputs[0]; @@ -69,6 +69,18 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass OUT_Revealage->Resize(newWidth, newHeight); } + void ClearDenendencies() override + { + OUT_Accumulation.reset(); + OUT_Revealage.reset(); + IN_DepthStencil = nullptr; + _transparencyVS.Reset(); + _transparencyPS.Reset(); + _transparencyRS.reset(); + _transparencyCS.Reset(); + _transparencyPSO.Reset(); + } + private: ComPtr _transparencyVS; ComPtr _transparencyPS; From e22621f487ead0c8548942b07694220a78286b6b Mon Sep 17 00:00:00 2001 From: AMorunov Date: Fri, 3 Jul 2026 22:56:15 +0300 Subject: [PATCH 21/46] FIX OR REVERT: mGPU render pipeline --- Apps/App.Base/src/RenderModule.cpp | 133 +++++++++++------- Apps/App.Base/src/SceneManagerModule.cpp | 16 +-- .../Engine.RendererDX12/GDX12Material.h | 4 +- .../RenderPasses/GDX12OpaquePass.h | 37 +++-- .../Shaders/CompositionPass.hlsl | 1 - .../src/GDX12DeviceResources.cpp | 12 +- 6 files changed, 128 insertions(+), 75 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index edc4f45..f8015fb 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -74,6 +74,7 @@ void RenderModule::OnResize() if (_upscaler) { _upscaler->QueryRenderTargetResolution(); } for (auto& renderPass : _primaryRenderPassExecutionList) { renderPass->Resize(); } + for (auto& renderPass : _secondaryRenderPassExecutionList) { renderPass->Resize(); } } GDX12Material* RenderModule::GetMaterialByName(const std::string& name) @@ -513,27 +514,53 @@ void RenderModule::OnTransformComponentUpdated(World& world, Entity entity, Tran void RenderModule::OnCameraComponentCreated(World& world, Entity entity, CameraComponent& component) { - component._CBufferIndex = _primaryResources.FrameConstants[0]->CameraCB->GetElementCount(); - - for (auto& constants : _primaryResources.FrameConstants) + if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_CAMERAS) { - auto& CBuffer = constants->CameraCB; - CBuffer->Resize(CBuffer->GetElementCount() + 1); + component._CBufferIndex = _primaryResources.FrameConstants[0]->CameraCB->GetElementCount(); - constants->CameraVisibilityCommands.push_back(GDX12VisibilityBuffers()); + for (auto& constants : _primaryResources.FrameConstants) + { + auto& CBuffer = constants->CameraCB; + CBuffer->Resize(CBuffer->GetElementCount() + 1); - 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); + constants->CameraVisibilityCommands.push_back(GDX12VisibilityBuffers()); - 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)); + 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 (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_CAMERAS) + { + 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)); + } + } } @@ -572,6 +599,7 @@ void RenderModule::OnRenderComponentCreated(World& world, Entity entity, StaticM if (_secondaryPipelineFlags & 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()); @@ -635,7 +663,7 @@ void RenderModule::OnUpdate() { _secondaryResources.CurrFrameConstantsIndex = (_secondaryResources.CurrFrameConstantsIndex + 1) % numFrames; - auto cmdQueue = _primaryDevice->GetCommandQueue(); + auto cmdQueue = _secondaryDevice->GetCommandQueue(); auto& frameConsts = _secondaryResources.FrameConstants[_secondaryResources.CurrFrameConstantsIndex]; if (frameConsts->FenceValue > cmdQueue->GetFence()->GetCompletedValue()) @@ -747,63 +775,72 @@ void RenderModule::ShareFences() void RenderModule::ConfigureRenderPipeline() { _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()); - for (auto& primaryRenderPass : _primaryRenderPassExecutionList) + _secondaryRenderPassExecutionList.push_back(std::make_unique()); + _secondaryRenderPassExecutionList.push_back(std::make_unique()); + _secondaryRenderPassExecutionList.push_back(std::make_unique()); + _secondaryRenderPassExecutionList.push_back(std::make_unique()); + _secondaryRenderPassExecutionList.push_back(std::make_unique()); + + for (auto& pass : _primaryRenderPassExecutionList) { - primaryRenderPass->Initialize(&_primaryResources, &_secondaryResources, &_RPcommonData); - _primaryPipelineFlags |= primaryRenderPass->GetFlags(); + pass->Initialize(&_primaryResources, &_secondaryResources, &_RPcommonData); + _primaryPipelineFlags |= pass->GetFlags(); } - //add secondary passes here - - for (auto& secondaryRenderPass : _secondaryRenderPassExecutionList) + for (auto& pass : _secondaryRenderPassExecutionList) { - secondaryRenderPass->Initialize(&_secondaryResources, &_primaryResources, &_RPcommonData); - _secondaryPipelineFlags |= secondaryRenderPass->GetFlags(); + pass->Initialize(&_secondaryResources, &_primaryResources, &_RPcommonData); + _secondaryPipelineFlags |= pass->GetFlags(); } GDX12RenderPass* clearPass = _primaryRenderPassExecutionList[0].get(); + GDX12RenderPass* copyFromShared = _primaryRenderPassExecutionList[1].get(); + GDX12RenderPass* outputPass = _primaryRenderPassExecutionList[2].get(); + + GDX12RenderPass* cullingPass = _secondaryRenderPassExecutionList[0].get(); + GDX12RenderPass* opaquePass = _secondaryRenderPassExecutionList[1].get(); + GDX12RenderPass* transparencyPass = _secondaryRenderPassExecutionList[2].get(); + GDX12RenderPass* compositionPass = _secondaryRenderPassExecutionList[3].get(); + GDX12RenderPass* copyToShared = _secondaryRenderPassExecutionList[4].get(); + std::vector clearPassInputs = { _backBuffer.get(), _depthStencil.get() }; std::vector clearPassOutputs; clearPass->LinkDependencies(clearPassInputs, &clearPassOutputs); - GDX12RenderPass* opaquePass = _primaryRenderPassExecutionList[2].get(); - std::vector opaquePassInputs = { _depthStencil.get() }; + std::vector copyFromInputs; + std::vector copyFromOutputs; + + std::vector outputPassInputs; + + std::vector cullingPassInputs; + std::vector cullingPassOutputs; + cullingPass->LinkDependencies(cullingPassInputs, &cullingPassOutputs); + + std::vector opaquePassInputs; std::vector opaquePassOutputs; opaquePass->LinkDependencies(opaquePassInputs, &opaquePassOutputs); - GDX12RenderPass* transparencyPass = _primaryRenderPassExecutionList[3].get(); - std::vector transparencyPassInputs = { _depthStencil.get() }; + std::vector transparencyPassInputs = { opaquePassOutputs[2] }; std::vector transparencyPassOutputs; transparencyPass->LinkDependencies(transparencyPassInputs, &transparencyPassOutputs); - GDX12RenderPass* compositionPass = _primaryRenderPassExecutionList[4].get(); std::vector compositionPassInputs = - { opaquePassOutputs[0], transparencyPassOutputs[0], transparencyPassOutputs[1] }; + { opaquePassOutputs[0], transparencyPassOutputs[0], transparencyPassOutputs[1] }; std::vector compositionPassOutputs; compositionPass->LinkDependencies(compositionPassInputs, &compositionPassOutputs); - GDX12RenderPass* outputPass = _primaryRenderPassExecutionList[5].get(); - std::vector outputPassInputs = { compositionPassOutputs[0], _backBuffer.get() }; - outputPass->LinkDependencies(outputPassInputs, nullptr); - - // SecondaryDevice pipeline + std::vector copyToInputs = { compositionPassOutputs[0] }; + std::vector copyToOutputs; + copyToShared->LinkDependencies(copyToInputs, ©ToOutputs); - // Texture transfer example - //IRenderPassLink* sharedMemoryVelocityBuffer; - //_textureCopyToSharedMemoryPass.Initialize(&_primaryResources, &_RPcommonData); - //_textureCopyToSharedMemoryPass.LinkDependancies(&_secondaryResources, opaqueVelocity, sharedMemoryVelocityBuffer); - //_primaryPipelineFlags |= _textureCopyToSharedMemoryPass.GetFlags(); + copyFromInputs = { copyToOutputs[0] }; + copyFromShared->LinkDependencies(copyFromInputs, ©FromOutputs); - //IRenderPassLink* transferredVelocityBuffer; - //_textureCopyFromSharedMemoryPass.Initialize(&_secondaryResources, &_RPcommonData); - //_textureCopyFromSharedMemoryPass.LinkDependancies(sharedMemoryVelocityBuffer, transferredVelocityBuffer); - //_secondaryPipelineFlags |= _textureCopyFromSharedMemoryPass.GetFlags(); + outputPassInputs = { copyFromOutputs[0], _backBuffer.get() }; + outputPass->LinkDependencies(outputPassInputs, nullptr); } void RenderModule::SubscribeToSceneManager() diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index 409979e..ac114bd 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - if (!LoadWorld("world1.yaml")) - { - // todo runtime error or log - } + //if (!LoadWorld("world1.yaml")) + //{ + // // todo runtime error or log + //} /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - //if (!LoadWorld(scenePath)) - //{ - // // todo runtime error or log - //} + if (!LoadWorld(scenePath)) + { + // todo runtime error or log + } World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h index 69ce30d..92d7cf3 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Material.h @@ -16,8 +16,8 @@ enum class MaterialType struct GPUTexture { std::string Name; - GDX12Texture* PrimaryDeviceTexture; - GDX12Texture* SecondaryDeviceTexture; + GDX12Texture* PrimaryDeviceTexture = nullptr; + GDX12Texture* SecondaryDeviceTexture = nullptr; }; class GDX12Material diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h index a6cdb5e..53c9369 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -4,21 +4,20 @@ class GDX12OpaquePass : public GDX12RenderPass { public: - GDX12OpaquePass() : IN_DepthStencil(nullptr) + GDX12OpaquePass() { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_GEOMETRY | RENDER_PASS_FLAG_USE_MATERIALS | RENDER_PASS_FLAG_USE_INSTANCES; } - // Input 0 - DepthStencil // Output 0 - AccumulationTexture // Output 1 - MotionVectors + // Output 2 - DepthStencil void LinkDependencies(std::vector inputs, std::vector* outputs) override { - IN_DepthStencil = inputs[0]; - PostLinkInitialize(); outputs->push_back(OUT_Accumulation.get()); outputs->push_back(OUT_VelocityBuffer.get()); + outputs->push_back(OUT_DepthStencil.get()); } // VisibilityBuffers will automatically be selected from CameraCBIndex @@ -27,7 +26,7 @@ class GDX12OpaquePass : public GDX12RenderPass { auto& currentFrameConstants = _resources->FrameConstants[_resources->CurrFrameConstantsIndex]; auto& currentCameraVisBuffers = currentFrameConstants->CameraVisibilityCommands[_commonData->ActiveCameraCBufferIndex]; - GDX12Texture* depthStencil = IN_DepthStencil->GetTexture(); + GDX12Texture* depthStencil = OUT_DepthStencil->GetTexture(); cmdList->BeginPixEvent("Opaque Render Pass", Colors::ForestGreen); cmdList->SetViewport(OUT_Accumulation->GetViewport()); @@ -48,8 +47,10 @@ class GDX12OpaquePass : public GDX12RenderPass currentCameraVisBuffers.VisibleOpaqueCommandsCache->GetResource().GetIndirectArgsBarrier(), currentCameraVisBuffers.OpaqueDrawCounter->GetResource().GetIndirectArgsBarrier(), OUT_Accumulation->GetResource()->GetRenderTargetBarrier(), - OUT_VelocityBuffer->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(), @@ -64,13 +65,14 @@ class GDX12OpaquePass : public GDX12RenderPass 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 { OUT_Accumulation.reset(); OUT_VelocityBuffer.reset(); - IN_DepthStencil = nullptr; + OUT_DepthStencil.reset(); _opaqueVS.Reset(); _opaquePS.Reset(); _opaqueRS.reset(); @@ -87,8 +89,7 @@ class GDX12OpaquePass : public GDX12RenderPass std::unique_ptr OUT_Accumulation; std::unique_ptr OUT_VelocityBuffer; - - IRenderPassLink* IN_DepthStencil; + std::unique_ptr OUT_DepthStencil; void PostLinkInitialize() { @@ -122,6 +123,22 @@ class GDX12OpaquePass : public GDX12RenderPass OUT_VelocityBuffer = std::make_unique(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 = std::make_unique(desc); + // Shaders auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); _opaqueVS = shaderCompiler.CompileShader(_resources->Device, SHADERS_FOLDER "OpaquePass.hlsl", nullptr, "VS", "vs"); @@ -175,7 +192,7 @@ class GDX12OpaquePass : public GDX12RenderPass PSODesc1.RTVFormats[1] = OUT_VelocityBuffer->GetFormat(); PSODesc1.SampleDesc.Count = 1; PSODesc1.SampleDesc.Quality = 0; - PSODesc1.DSVFormat = IN_DepthStencil->GetTexture()->GetFormat(); + 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))); 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/src/GDX12DeviceResources.cpp b/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp index a15e036..d1f0e62 100644 --- a/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp @@ -86,16 +86,16 @@ void GDX12DeviceResources::UpdateMaterialCB(std::unordered_mapRole == DEVICE_ROLE_PRIMARY) { - if (material->Diffuse) { materialConstants.DiffuseIndex = material->Diffuse->PrimaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } - if (material->Normal) { materialConstants.NormalIndex = material->Normal->PrimaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } - if (material->Displacement) { materialConstants.DisplacementIndex = material->Displacement->PrimaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + 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) { materialConstants.DiffuseIndex = material->Diffuse->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } - if (material->Normal) { materialConstants.NormalIndex = material->Normal->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } - if (material->Displacement) { materialConstants.DisplacementIndex = material->Displacement->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + if (material->Diffuse && material->Diffuse->PrimaryDeviceTexture) { materialConstants.DiffuseIndex = material->Diffuse->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + if (material->Normal && material->Normal->PrimaryDeviceTexture) { materialConstants.NormalIndex = material->Normal->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + if (material->Displacement && material->Displacement->PrimaryDeviceTexture) { materialConstants.DisplacementIndex = material->Displacement->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } currMaterialCB->CopyData(material->_CBufferIndex, materialConstants); } material->_numFramesDirty--; From fddf96615a7eb6b114af7ee4ab6fecede29e7b77 Mon Sep 17 00:00:00 2001 From: DvornikovArtem Date: Fri, 3 Jul 2026 23:32:08 +0300 Subject: [PATCH 22/46] some fixes --- Apps/App.Base/src/RenderModule.cpp | 30 +++++++++++++++++-- .../src/GDX12DeviceResources.cpp | 6 ++-- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index f8015fb..66ffa60 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -149,6 +149,8 @@ GPUTexture* RenderModule::CreateTexture(const std::string& name, const Texture* { _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) @@ -574,7 +576,30 @@ void RenderModule::OnCameraComponentUpdated(World& world, Entity entity, CameraC void RenderModule::OnRenderComponentCreated(World& world, Entity entity, StaticMeshRenderComponent& component) { - auto& MeshGPUData = _primaryResources.GeometryBuffer->_meshCache[component.MeshHandler.GetValue()]; + const GPUMesh* MeshGPUData = nullptr; + + if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_GEOMETRY) + { + auto it = _primaryResources.GeometryBuffer->_meshCache.find(component.MeshHandler.GetValue()); + if (it != _primaryResources.GeometryBuffer->_meshCache.end()) + { + MeshGPUData = it->second.get(); + } + } + + if (MeshGPUData == nullptr && (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_GEOMETRY)) + { + auto it = _secondaryResources.GeometryBuffer->_meshCache.find(component.MeshHandler.GetValue()); + if (it != _secondaryResources.GeometryBuffer->_meshCache.end()) + { + MeshGPUData = it->second.get(); + } + } + + if (MeshGPUData == nullptr) + { + return; + } if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_INSTANCES) { @@ -599,11 +624,10 @@ void RenderModule::OnRenderComponentCreated(World& world, Entity entity, StaticM if (_secondaryPipelineFlags & 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(_primaryResources.IndirectCommandsCache->GetElementCount() + 1); + _secondaryResources.IndirectCommandsCache->Resize(_secondaryResources.IndirectCommandsCache->GetElementCount() + 1); for (auto& constants : _secondaryResources.FrameConstants) { diff --git a/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp b/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp index d1f0e62..993abf1 100644 --- a/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12DeviceResources.cpp @@ -93,9 +93,9 @@ void GDX12DeviceResources::UpdateMaterialCB(std::unordered_mapDiffuse && material->Diffuse->PrimaryDeviceTexture) { materialConstants.DiffuseIndex = material->Diffuse->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } - if (material->Normal && material->Normal->PrimaryDeviceTexture) { materialConstants.NormalIndex = material->Normal->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } - if (material->Displacement && material->Displacement->PrimaryDeviceTexture) { materialConstants.DisplacementIndex = material->Displacement->SecondaryDeviceTexture->GetSRV()->HeapIndex - Texture2D_StartIndex; } + 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--; From 511cf2368742420662657fff5e69aa5e4388dab8 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Fri, 3 Jul 2026 23:41:50 +0300 Subject: [PATCH 23/46] cleanup --- Apps/App.Base/src/RenderModule.cpp | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 66ffa60..01edee6 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -576,33 +576,9 @@ void RenderModule::OnCameraComponentUpdated(World& world, Entity entity, CameraC void RenderModule::OnRenderComponentCreated(World& world, Entity entity, StaticMeshRenderComponent& component) { - const GPUMesh* MeshGPUData = nullptr; - - if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_GEOMETRY) - { - auto it = _primaryResources.GeometryBuffer->_meshCache.find(component.MeshHandler.GetValue()); - if (it != _primaryResources.GeometryBuffer->_meshCache.end()) - { - MeshGPUData = it->second.get(); - } - } - - if (MeshGPUData == nullptr && (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_GEOMETRY)) - { - auto it = _secondaryResources.GeometryBuffer->_meshCache.find(component.MeshHandler.GetValue()); - if (it != _secondaryResources.GeometryBuffer->_meshCache.end()) - { - MeshGPUData = it->second.get(); - } - } - - if (MeshGPUData == nullptr) - { - return; - } - if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_INSTANCES) { + auto& MeshGPUData = _primaryResources.GeometryBuffer->_meshCache[component.MeshHandler.GetValue()]; for (int i = 0; i < MeshGPUData->SubMeshes.size(); i++) { component._CBufferIndices.push_back(_primaryResources.FrameConstants[0]->InstanceCache->GetElementCount()); @@ -624,6 +600,7 @@ void RenderModule::OnRenderComponentCreated(World& world, Entity entity, StaticM if (_secondaryPipelineFlags & 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()); From 43ad114c3d2be0104138e3201ed1abdadb86ed7f Mon Sep 17 00:00:00 2001 From: AMorunov Date: Sat, 4 Jul 2026 13:49:12 +0300 Subject: [PATCH 24/46] Easier, order-independent render pass linking --- .../Include/App.Base/Modules/RenderModule.h | 2 + Apps/App.Base/src/RenderModule.cpp | 115 +++++++----- .../Engine.RendererDX12/GDX12SharedTexture.h | 7 +- .../Engine.RendererDX12/GDX12SwapChain.h | 2 +- .../Engine.RendererDX12/GDX12Texture.h | 7 +- .../Engine.RendererDX12/IRenderPassLink.h | 1 + .../RenderPasses/GDX12BackBufferClearPass.h | 33 ++-- .../RenderPasses/GDX12FSRUpscalePass.h | 28 ++- .../RenderPasses/GDX12GPUCullingPass.h | 6 +- .../RenderPasses/GDX12OpaquePass.h | 176 +++++++++--------- .../RenderPasses/GDX12OutputToScreenPass.h | 24 ++- .../RenderPasses/GDX12RenderPass.h | 27 ++- .../GDX12TextureCopyFromSharedMemoryPass.h | 19 +- .../GDX12TextureCopyToSharedMemoryPass.h | 18 +- .../RenderPasses/GDX12WBOITCompositionPass.h | 138 +++++++------- .../RenderPasses/GDX12WBOITTransparencyPass.h | 174 ++++++++--------- .../src/GDX12SwapChain.cpp | 8 +- .../Engine.RendererDX12/src/GDX12Texture.cpp | 104 ++++++----- 18 files changed, 503 insertions(+), 386 deletions(-) diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index 6a037e0..74d7065 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -122,6 +122,8 @@ class RenderModule final : public Module void BuildBackBuffer(); void ShareFences(); void ConfigureRenderPipeline(); + void SetupRenderPasses(); + void InitializeRenderPasses(); void SubscribeToSceneManager(); void UnsubscribeFromSceneManager(); diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 01edee6..f22c86c 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -306,7 +306,8 @@ GDX12Texture* RenderModule::CreateDX12Texture(const std::string& name, GDX12Devi desc.ExternalResource = textureResource; - resources->Textures[name] = std::make_unique(desc); + resources->Textures[name] = std::make_unique(); + resources->Textures[name]->Initialize(desc); return resources->Textures[name].get(); } @@ -746,7 +747,8 @@ void RenderModule::BuildBackBuffer() desc.DSVDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; desc.DSVDesc.Texture2D.MipSlice = 0; - _depthStencil = std::make_unique(desc); + _depthStencil = std::make_unique(); + _depthStencil->Initialize(desc); _RPcommonData.WindowWidth = width; _RPcommonData.WindowHeight = height; @@ -775,6 +777,8 @@ void RenderModule::ShareFences() void RenderModule::ConfigureRenderPipeline() { + // 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()); @@ -785,18 +789,9 @@ void RenderModule::ConfigureRenderPipeline() _secondaryRenderPassExecutionList.push_back(std::make_unique()); _secondaryRenderPassExecutionList.push_back(std::make_unique()); - for (auto& pass : _primaryRenderPassExecutionList) - { - pass->Initialize(&_primaryResources, &_secondaryResources, &_RPcommonData); - _primaryPipelineFlags |= pass->GetFlags(); - } - - for (auto& pass : _secondaryRenderPassExecutionList) - { - pass->Initialize(&_secondaryResources, &_primaryResources, &_RPcommonData); - _secondaryPipelineFlags |= pass->GetFlags(); - } + SetupRenderPasses(); + // Link inputs & outputs for each pass that needs it GDX12RenderPass* clearPass = _primaryRenderPassExecutionList[0].get(); GDX12RenderPass* copyFromShared = _primaryRenderPassExecutionList[1].get(); GDX12RenderPass* outputPass = _primaryRenderPassExecutionList[2].get(); @@ -807,41 +802,73 @@ void RenderModule::ConfigureRenderPipeline() GDX12RenderPass* compositionPass = _secondaryRenderPassExecutionList[3].get(); GDX12RenderPass* copyToShared = _secondaryRenderPassExecutionList[4].get(); - std::vector clearPassInputs = { _backBuffer.get(), _depthStencil.get() }; - std::vector clearPassOutputs; - clearPass->LinkDependencies(clearPassInputs, &clearPassOutputs); - - std::vector copyFromInputs; - std::vector copyFromOutputs; - - std::vector outputPassInputs; + clearPass->Inputs = { _backBuffer.get(), _depthStencil.get() }; + cullingPass->Inputs = {}; + opaquePass->Inputs = {}; + transparencyPass->Inputs = { opaquePass->Outputs[2] }; + compositionPass->Inputs = { opaquePass->Outputs[0], transparencyPass->Outputs[0], transparencyPass->Outputs[1] }; + copyToShared->Inputs = { compositionPass->Outputs[0] }; + copyFromShared->Inputs = { copyToShared->Outputs[0] }; + outputPass->Inputs = { copyFromShared->Outputs[0], _backBuffer.get() }; - std::vector cullingPassInputs; - std::vector cullingPassOutputs; - cullingPass->LinkDependencies(cullingPassInputs, &cullingPassOutputs); - - std::vector opaquePassInputs; - std::vector opaquePassOutputs; - opaquePass->LinkDependencies(opaquePassInputs, &opaquePassOutputs); - - std::vector transparencyPassInputs = { opaquePassOutputs[2] }; - std::vector transparencyPassOutputs; - transparencyPass->LinkDependencies(transparencyPassInputs, &transparencyPassOutputs); - - std::vector compositionPassInputs = - { opaquePassOutputs[0], transparencyPassOutputs[0], transparencyPassOutputs[1] }; - std::vector compositionPassOutputs; - compositionPass->LinkDependencies(compositionPassInputs, &compositionPassOutputs); + InitializeRenderPasses(); +} - std::vector copyToInputs = { compositionPassOutputs[0] }; - std::vector copyToOutputs; - copyToShared->LinkDependencies(copyToInputs, ©ToOutputs); +void RenderModule::SetupRenderPasses() +{ + for (auto& pass : _primaryRenderPassExecutionList) + { + pass->Setup(&_primaryResources, &_secondaryResources, &_RPcommonData); + _primaryPipelineFlags |= pass->GetFlags(); + } - copyFromInputs = { copyToOutputs[0] }; - copyFromShared->LinkDependencies(copyFromInputs, ©FromOutputs); + for (auto& pass : _secondaryRenderPassExecutionList) + { + pass->Setup(&_secondaryResources, &_primaryResources, &_RPcommonData); + _secondaryPipelineFlags |= pass->GetFlags(); + } +} - outputPassInputs = { copyFromOutputs[0], _backBuffer.get() }; - outputPass->LinkDependencies(outputPassInputs, nullptr); +void RenderModule::InitializeRenderPasses() +{ + 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()) + { + if (iteration > MAX_ITERATIONS) + { + OutputDebugStringA("ERROR: RenderPassLinking failed after 100 attempts.\n"); + break; + } + for (auto it = allRenderPasses.begin(); it != allRenderPasses.end();) + { + GDX12RenderPass* renderPass = *it; + bool allInputsInitialized = true; + for (auto* input : renderPass->Inputs) + { + if (!input->IsInitialized()) + { + allInputsInitialized = false; + break; + } + } + if (allInputsInitialized) + { + renderPass->Initialize(); + it = allRenderPasses.erase(it); + } + else + { + ++it; + } + } + iteration++; + } } void RenderModule::SubscribeToSceneManager() diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h index f6d1d22..949d396 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h @@ -11,7 +11,8 @@ class GDX12SharedTexture : public IRenderPassLink { public: GDX12SharedTexture() : _width(0) , _height(0), - _format(DXGI_FORMAT_UNKNOWN), _heapSize(0), _transferFromDeivce(nullptr), _transferToDevice(nullptr) + _format(DXGI_FORMAT_UNKNOWN), _heapSize(0), _transferFromDeivce(nullptr), + _transferToDevice(nullptr), _isInitiliazed(false) { } @@ -40,6 +41,8 @@ class GDX12SharedTexture : public IRenderPassLink CreateSharedHeap(); CreatePlacedResources(); ShareResources(); + + _isInitiliazed = true; } void Release() @@ -66,6 +69,7 @@ class GDX12SharedTexture : public IRenderPassLink UINT GetHeight() { return _height; } DXGI_FORMAT GetFormat() { return _format; } GDX12SharedTexture* GetSharedTexture() override { return this; } + bool IsInitialized() override { return _isInitiliazed; } private: GDX12Device* _transferFromDeivce; @@ -77,6 +81,7 @@ class GDX12SharedTexture : public IRenderPassLink DXGI_FORMAT _format; UINT _width; UINT _height; + bool _isInitiliazed; void CreateSharedHeap() { diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h index d392d62..224af52 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h @@ -27,7 +27,7 @@ class GDX12SwapChain : public IRenderPassLink D3D12_VIEWPORT GetViewport(); D3D12_RECT GetScissorRect(); GDX12Texture* GetTexture() override; - + bool IsInitialized() override; const ComPtr& GetSwapChain(); void Reset(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h index fb4f759..c7262f6 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h @@ -66,9 +66,11 @@ struct GDX12TextureDesc 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); @@ -86,6 +88,7 @@ class GDX12Texture : public IRenderPassLink UINT GetWidth(); UINT GetHeight(); GDX12Texture* GetTexture() override; + bool IsInitialized() override; private: void CreateResource(); @@ -103,4 +106,6 @@ class GDX12Texture : public IRenderPassLink D3D12_VIEWPORT _viewport; D3D12_RECT _scissorRect; + + bool _isInitialized; }; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h index 4f7fb6e..9ec233d 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/IRenderPassLink.h @@ -17,4 +17,5 @@ class IRenderPassLink 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/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h index f99a16a..e6753c7 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h @@ -4,26 +4,27 @@ class GDX12BackBufferClearPass : public GDX12RenderPass { public: - GDX12BackBufferClearPass() : IN_OUT_currentBackBuffer(nullptr), IN_OUT_depthStencil(nullptr) - { _flags = RENDER_PASS_FLAG_NONE; } + GDX12BackBufferClearPass() : IN_currentBackBuffer(nullptr), IN_depthStencil(nullptr) + { + _flags = RENDER_PASS_FLAG_NONE; + _numInputs = 2; + _numOutputs = 0; + } // Input 0 - back buffer // Input 1 - depth stencil - // Output 0 - back buffer - // Output 1 - depth stencil - void LinkDependencies(std::vector inputs, std::vector* outputs) override + void Initialize() override { - IN_OUT_currentBackBuffer = inputs[0]; - IN_OUT_depthStencil = inputs[1]; + GDX12RenderPass::Initialize(); - outputs->push_back(IN_OUT_currentBackBuffer); - outputs->push_back(IN_OUT_depthStencil); + IN_currentBackBuffer = Inputs[0]; + IN_depthStencil = Inputs[1]; } void Execute(GDX12CommandList* cmdList) override { - GDX12Texture* currentBackBuffer = IN_OUT_currentBackBuffer->GetTexture(); - GDX12Texture* depthStencil = IN_OUT_depthStencil->GetTexture(); + GDX12Texture* currentBackBuffer = IN_currentBackBuffer->GetTexture(); + GDX12Texture* depthStencil = IN_depthStencil->GetTexture(); cmdList->BeginPixEvent("Clear Back Buffer", Colors::Aqua); cmdList->SetViewport(currentBackBuffer->GetViewport()); @@ -38,11 +39,13 @@ class GDX12BackBufferClearPass : public GDX12RenderPass void ClearDenendencies() override { - IN_OUT_currentBackBuffer = nullptr; - IN_OUT_depthStencil = nullptr; + GDX12RenderPass::ClearDenendencies(); + + IN_currentBackBuffer = nullptr; + IN_depthStencil = nullptr; } private: - IRenderPassLink* IN_OUT_currentBackBuffer; - IRenderPassLink* IN_OUT_depthStencil; + IRenderPassLink* IN_currentBackBuffer; + IRenderPassLink* IN_depthStencil; }; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index 6586d54..a91c284 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -11,17 +11,25 @@ class GDX12FSRUpscalePass : public GDX12RenderPass public: GDX12FSRUpscalePass() : IN_Texture(nullptr), IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), OUT_UpscaledTexture(nullptr), _FFXContext(nullptr) - { _flags = RENDER_PASS_FLAG_UPSCALER; } + { + _flags = RENDER_PASS_FLAG_UPSCALER; + _numInputs = 3; + _numOutputs = 1; + OUT_UpscaledTexture = std::make_unique(); + Outputs.push_back(OUT_UpscaledTexture.get()); + } // Input 0 - InputTexture // Input 1 - DepthStencil // Input 2 - MotionVectors // Output 0 - UpscaledTexture - void LinkDependencies(std::vector inputs, std::vector* outputs) override + void Initialize() override { - IN_Texture = inputs[0]; - IN_DepthBuffer = inputs[1]; - IN_MotionVectors = inputs[2]; + GDX12RenderPass::Initialize(); + + IN_Texture = Inputs[0]; + IN_DepthBuffer = Inputs[1]; + IN_MotionVectors = Inputs[2]; GDX12Texture* inputTexture = IN_Texture->GetTexture(); @@ -40,15 +48,13 @@ class GDX12FSRUpscalePass : public GDX12RenderPass TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; - OUT_UpscaledTexture = std::make_unique(TextureDesc1); - - outputs->push_back(OUT_UpscaledTexture.get()); + OUT_UpscaledTexture->Initialize(TextureDesc1); } // Init with window size - void Initialize(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) override + void Setup(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) override { - GDX12RenderPass::Initialize(initOnResources, otherResources, commonData); + GDX12RenderPass::Setup(initOnResources, otherResources, commonData); BuildFSRContext(); QueryRenderTargetResolution(); @@ -129,6 +135,8 @@ class GDX12FSRUpscalePass : public GDX12RenderPass void ClearDenendencies() override { + GDX12RenderPass::ClearDenendencies(); + if (_FFXContext) { ffxDestroyContext(&_FFXContext, nullptr); } IN_Texture = nullptr; IN_DepthBuffer = nullptr; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h index 975f1aa..c19f414 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12GPUCullingPass.h @@ -7,9 +7,9 @@ class GDX12GPUCullingPass : public GDX12RenderPass GDX12GPUCullingPass() { _flags = RENDER_PASS_FLAG_USE_CAMERAS | RENDER_PASS_FLAG_USE_INSTANCES; } - void Initialize(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) override + void Setup(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) override { - GDX12RenderPass::Initialize(initOnResources, otherResources, commonData); + GDX12RenderPass::Setup(initOnResources, otherResources, commonData); // Shaders auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); @@ -84,6 +84,8 @@ class GDX12GPUCullingPass : public GDX12RenderPass void ClearDenendencies() override { + GDX12RenderPass::ClearDenendencies(); + _cullingRS.reset(); _cullingPSO.Reset(); _bufferClearCS.Reset(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h index 53c9369..cdfad57 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -5,94 +5,27 @@ 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; } + { + _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 LinkDependencies(std::vector inputs, std::vector* outputs) override - { - PostLinkInitialize(); - - outputs->push_back(OUT_Accumulation.get()); - outputs->push_back(OUT_VelocityBuffer.get()); - outputs->push_back(OUT_DepthStencil.get()); - } - - // 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 + void Initialize() 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 - { - 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; + GDX12RenderPass::Initialize(); - void PostLinkInitialize() - { 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; @@ -115,13 +48,13 @@ class GDX12OpaquePass : public GDX12RenderPass TextureDesc1.RTVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.RTVDesc.Texture2D.MipSlice = 0; - OUT_Accumulation = std::make_unique(TextureDesc1); + 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 = std::make_unique(TextureDesc1); + OUT_VelocityBuffer->Initialize(TextureDesc1); GDX12TextureDesc desc; desc.CreateSRV = false; @@ -137,7 +70,7 @@ class GDX12OpaquePass : public GDX12RenderPass desc.DSVDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; desc.DSVDesc.Texture2D.MipSlice = 0; - OUT_DepthStencil = std::make_unique(desc); + OUT_DepthStencil->Initialize(desc); // Shaders auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); @@ -197,4 +130,77 @@ class GDX12OpaquePass : public GDX12RenderPass 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 index a6db1a1..dc3babd 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h @@ -5,21 +5,27 @@ class GDX12OutputToScreenPass : public GDX12RenderPass { public: - GDX12OutputToScreenPass() : IN_Texture(nullptr), IN_OUT_BackBuffer(nullptr) - { _flags = RENDER_PASS_FLAG_NONE; } + GDX12OutputToScreenPass() : IN_Texture(nullptr), IN_BackBuffer(nullptr) + { + _flags = RENDER_PASS_FLAG_NONE; + _numInputs = 2; + _numOutputs = 0; + } // Input 0 - InputTexture // Input 1 - BackBuffer - void LinkDependencies(std::vector inputs, std::vector* outputs) override + void Initialize() override { - IN_Texture = inputs[0]; - IN_OUT_BackBuffer = inputs[1]; + GDX12RenderPass::Initialize(); + + IN_Texture = Inputs[0]; + IN_BackBuffer = Inputs[1]; } void Execute(GDX12CommandList* cmdList) override { GDX12Texture* inputTexture = IN_Texture->GetTexture(); - GDX12Texture* backBuffer = IN_OUT_BackBuffer->GetTexture(); + GDX12Texture* backBuffer = IN_BackBuffer->GetTexture(); cmdList->BeginPixEvent("Copy To Screen Pass", Colors::Aqua); cmdList->ResourceBarrier({ inputTexture->GetResource()->GetCopySourceBarrier() }); @@ -32,11 +38,13 @@ class GDX12OutputToScreenPass : public GDX12RenderPass void ClearDenendencies() override { + GDX12RenderPass::ClearDenendencies(); + IN_Texture = nullptr; - IN_OUT_BackBuffer = nullptr; + IN_BackBuffer = nullptr; } private: IRenderPassLink* IN_Texture; - IRenderPassLink* IN_OUT_BackBuffer; + 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 index 2816dcc..dd692ac 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -43,8 +43,9 @@ enum ERenderPassFlags : uint32_t class GDX12RenderPass { public: - GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE), _resources(nullptr), _otherResources(nullptr), _commonData(nullptr) {} - virtual void Initialize(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) + GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE), _resources(nullptr), + _otherResources(nullptr), _commonData(nullptr), _numInputs(0), _numOutputs(0) {} + virtual void Setup(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) { _resources = initOnResources; _otherResources = otherResources; @@ -55,9 +56,17 @@ class GDX12RenderPass // Used by upscalers to determine downscaled render target size // And share it with all other passes virtual void QueryRenderTargetResolution() {}; - // Used by all passes to link inputs and outputs with other passes - virtual void LinkDependencies(std::vector inputs, std::vector* outputs) {}; - virtual void ClearDenendencies() {} + + virtual void ClearDenendencies() + { + Inputs.clear(); + Outputs.clear(); + } + // Called after linking with other passes + virtual void Initialize() + { + if (Inputs.size() < _numInputs) { OutputDebugStringA("ERROR: Not enough inputs provided into render pass\n"); } + } uint32_t GetFlags() { return _flags; } void SetFlag(uint32_t flag, bool value) @@ -67,6 +76,11 @@ class GDX12RenderPass } bool GetFlagValue(uint32_t flag) { return _flags & flag; } + std::vector Inputs; + std::vector Outputs; + 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 @@ -79,4 +93,7 @@ class GDX12RenderPass // These are the other resources, that might be needed in mGPU passes // Might be null GDX12DeviceResources* _otherResources; + + UINT _numInputs; + UINT _numOutputs; }; \ 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 index cd9b0ef..806977b 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h @@ -7,13 +7,21 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass { public: GDX12TextureCopyFromSharedMemoryPass() : IN_SharedTexture(nullptr), OUT_Texture(nullptr) - { _flags = RENDER_PASS_FLAG_NONE; } + { + _flags = RENDER_PASS_FLAG_NONE; + _numInputs = 1; + _numOutputs = 1; + OUT_Texture = std::make_unique(); + Outputs.push_back(OUT_Texture.get()); + } // Input 0 - SharedTexture // Output 0 - OutputTexture - void LinkDependencies(std::vector inputs, std::vector* outputs) override + void Initialize() override { - IN_SharedTexture = inputs[0]; + GDX12RenderPass::Initialize(); + + IN_SharedTexture = Inputs[0]; GDX12SharedTexture* sharedTexture = IN_SharedTexture->GetSharedTexture(); @@ -32,9 +40,7 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; - this->OUT_Texture = std::make_unique(TextureDesc1); - - outputs->push_back(OUT_Texture.get()); + OUT_Texture->Initialize(TextureDesc1); } // Copies texture from shared memory onto device the pass was initialized on @@ -62,6 +68,7 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass void ClearDenendencies() override { + GDX12RenderPass::ClearDenendencies(); IN_SharedTexture = nullptr; OUT_Texture.reset(); } diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h index 5060059..adec6f8 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h @@ -6,20 +6,25 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass { public: GDX12TextureCopyToSharedMemoryPass() : IN_Texture(nullptr) - { _flags = RENDER_PASS_FLAG_NONE; } + { + _flags = RENDER_PASS_FLAG_NONE; + _numInputs = 1; + _numOutputs = 1; + OUT_SharedTexture = std::make_unique(); + Outputs.push_back(OUT_SharedTexture.get()); + } // Input 0 - InputTexture // Output 0 - SharedTexture - void LinkDependencies(std::vector inputs, std::vector* outputs) override + void Initialize() override { - IN_Texture = inputs[0]; + GDX12RenderPass::Initialize(); + + IN_Texture = Inputs[0]; - OUT_SharedTexture = std::make_unique(); OUT_SharedTexture->Initialize(_resources->Device, _otherResources->Device, IN_Texture->GetTexture()->GetWidth(), IN_Texture->GetTexture()->GetHeight(), IN_Texture->GetTexture()->GetFormat()); - - outputs->push_back(OUT_SharedTexture.get()); } // Copies texture from device the pass was initialized at to shared memory @@ -46,6 +51,7 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass void ClearDenendencies() override { + GDX12RenderPass::ClearDenendencies(); IN_Texture = nullptr; OUT_SharedTexture.reset(); } diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h index c98fc2f..8de9cc4 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h @@ -6,81 +6,26 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass public: GDX12WBOITCompositionPass() : IN_OpaqueScene(nullptr), IN_TransparencyAccum(nullptr), IN_Revealage(nullptr), OUT_Result(nullptr) - { _flags = RENDER_PASS_FLAG_NONE; } + { + _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 LinkDependencies(std::vector inputs, std::vector* outputs) override - { - IN_OpaqueScene = inputs[0]; - IN_TransparencyAccum = inputs[1]; - IN_Revealage = inputs[2]; - - PostLinkInitialize(); - - outputs->push_back(OUT_Result.get()); - } - - 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 + void Initialize() 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); - } + GDX12RenderPass::Initialize(); - void ClearDenendencies() override - { - 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; + IN_OpaqueScene = Inputs[0]; + IN_TransparencyAccum = Inputs[1]; + IN_Revealage = Inputs[2]; - void PostLinkInitialize() - { // Textures GDX12TextureDesc TextureDesc1; TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; @@ -104,7 +49,7 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass TextureDesc1.RTVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.RTVDesc.Texture2D.MipSlice = 0; - OUT_Result = std::make_unique(TextureDesc1); + OUT_Result->Initialize(TextureDesc1); // Shaders auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); @@ -140,4 +85,61 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass 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 index c559b1d..b111706 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -5,96 +5,26 @@ 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; } + { + _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 LinkDependencies(std::vector inputs, std::vector* outputs) override - { - IN_DepthStencil = inputs[0]; - - PostLinkInitialize(); - - outputs->push_back(OUT_Accumulation.get()); - outputs->push_back(OUT_Revealage.get()); - } - - // VisibilityBuffers will automatically be selected from CameraCBIndex - // It requires GPUCullingPass to be executed beforehand - void Execute(GDX12CommandList* cmdList) override + void Initialize() 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)); + GDX12RenderPass::Initialize(); - 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 - { - 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; + IN_DepthStencil = Inputs[0]; - void PostLinkInitialize() - { // Textures GDX12TextureDesc TextureDesc1; TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; @@ -118,12 +48,13 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass TextureDesc1.RTVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.RTVDesc.Texture2D.MipSlice = 0; - OUT_Accumulation = std::make_unique(TextureDesc1); + 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 = std::make_unique(TextureDesc1); + + OUT_Revealage->Initialize(TextureDesc1); // Shaders auto& shaderCompiler = GDX12ShaderCompiler::GetInstance(); @@ -207,4 +138,77 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass 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/src/GDX12SwapChain.cpp b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp index 80dfc0c..3e0b27c 100644 --- a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp @@ -73,7 +73,8 @@ void GDX12SwapChain::CreateBuffers() textureDesc.ExternalResource = backBuffer; - _buffers.push_back(std::make_unique(textureDesc)); + _buffers.push_back(std::make_unique()); + _buffers[i]->Initialize(textureDesc); } } @@ -129,6 +130,11 @@ GDX12Texture* GDX12SwapChain::GetTexture() return GetCurrentBuffer(); } +bool GDX12SwapChain::IsInitialized() +{ + return true; +} + DXGI_FORMAT GDX12SwapChain::GetFormat() { return _format; diff --git a/Engine/Engine.RendererDX12/src/GDX12Texture.cpp b/Engine/Engine.RendererDX12/src/GDX12Texture.cpp index 75813f5..67db712 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Texture.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Texture.cpp @@ -6,55 +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 | 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) }; } void GDX12Texture::Resize(UINT width, UINT height) @@ -143,6 +98,11 @@ GDX12Texture* GDX12Texture::GetTexture() return this; } +bool GDX12Texture::IsInitialized() +{ + return _isInitialized; +} + void GDX12Texture::CreateResource() { D3D12_RESOURCE_DESC resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D( @@ -216,3 +176,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; +} From d64c2d0f89eeb4a78e5af346d76227af4b78059b Mon Sep 17 00:00:00 2001 From: AMorunov Date: Sat, 4 Jul 2026 16:30:45 +0300 Subject: [PATCH 25/46] wrapped inputs&outputs into functions --- Apps/App.Base/src/RenderModule.cpp | 34 ++++++------------- Apps/App.Base/src/SceneManagerModule.cpp | 16 ++++----- .../RenderPasses/GDX12BackBufferClearPass.h | 4 +-- .../RenderPasses/GDX12FSRUpscalePass.h | 8 ++--- .../RenderPasses/GDX12OpaquePass.h | 6 ++-- .../RenderPasses/GDX12OutputToScreenPass.h | 4 +-- .../RenderPasses/GDX12RenderPass.h | 29 +++++++++++----- .../GDX12TextureCopyFromSharedMemoryPass.h | 4 +-- .../GDX12TextureCopyToSharedMemoryPass.h | 4 +-- .../RenderPasses/GDX12WBOITCompositionPass.h | 8 ++--- .../RenderPasses/GDX12WBOITTransparencyPass.h | 6 ++-- 11 files changed, 62 insertions(+), 61 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index f22c86c..c60cba0 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -802,14 +802,14 @@ void RenderModule::ConfigureRenderPipeline() GDX12RenderPass* compositionPass = _secondaryRenderPassExecutionList[3].get(); GDX12RenderPass* copyToShared = _secondaryRenderPassExecutionList[4].get(); - clearPass->Inputs = { _backBuffer.get(), _depthStencil.get() }; - cullingPass->Inputs = {}; - opaquePass->Inputs = {}; - transparencyPass->Inputs = { opaquePass->Outputs[2] }; - compositionPass->Inputs = { opaquePass->Outputs[0], transparencyPass->Outputs[0], transparencyPass->Outputs[1] }; - copyToShared->Inputs = { compositionPass->Outputs[0] }; - copyFromShared->Inputs = { copyToShared->Outputs[0] }; - outputPass->Inputs = { copyFromShared->Outputs[0], _backBuffer.get() }; + clearPass->SetInputs({ _backBuffer.get(), _depthStencil.get() }); + cullingPass->SetInputs({}); + opaquePass->SetInputs({}); + transparencyPass->SetInputs({ opaquePass->GetOutputs()[2] }); + compositionPass->SetInputs({ opaquePass->GetOutputs()[0], transparencyPass->GetOutputs()[0], transparencyPass->GetOutputs()[1] }); + copyToShared->SetInputs({ compositionPass->GetOutputs()[0] }); + copyFromShared->SetInputs({ copyToShared->GetOutputs()[0] }); + outputPass->SetInputs({ copyFromShared->GetOutputs()[0], _backBuffer.get() }); InitializeRenderPasses(); } @@ -842,30 +842,18 @@ void RenderModule::InitializeRenderPasses() { if (iteration > MAX_ITERATIONS) { - OutputDebugStringA("ERROR: RenderPassLinking failed after 100 attempts.\n"); + OutputDebugStringA("ERROR: RenderPass linking failed after 100 attempts. This can be caused by wrong render pass inputs\n"); break; } for (auto it = allRenderPasses.begin(); it != allRenderPasses.end();) { GDX12RenderPass* renderPass = *it; - bool allInputsInitialized = true; - for (auto* input : renderPass->Inputs) - { - if (!input->IsInitialized()) - { - allInputsInitialized = false; - break; - } - } - if (allInputsInitialized) + if (renderPass->ValidateInputs()) { renderPass->Initialize(); it = allRenderPasses.erase(it); } - else - { - ++it; - } + else { ++it; } } iteration++; } diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index ac114bd..409979e 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - //if (!LoadWorld("world1.yaml")) - //{ - // // todo runtime error or log - //} + if (!LoadWorld("world1.yaml")) + { + // todo runtime error or log + } /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - if (!LoadWorld(scenePath)) - { - // todo runtime error or log - } + //if (!LoadWorld(scenePath)) + //{ + // // todo runtime error or log + //} World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h index e6753c7..8399d5c 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h @@ -17,8 +17,8 @@ class GDX12BackBufferClearPass : public GDX12RenderPass { GDX12RenderPass::Initialize(); - IN_currentBackBuffer = Inputs[0]; - IN_depthStencil = Inputs[1]; + IN_currentBackBuffer = _inputs[0]; + IN_depthStencil = _inputs[1]; } void Execute(GDX12CommandList* cmdList) override diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index a91c284..c104854 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -16,7 +16,7 @@ class GDX12FSRUpscalePass : public GDX12RenderPass _numInputs = 3; _numOutputs = 1; OUT_UpscaledTexture = std::make_unique(); - Outputs.push_back(OUT_UpscaledTexture.get()); + _outputs.push_back(OUT_UpscaledTexture.get()); } // Input 0 - InputTexture @@ -27,9 +27,9 @@ class GDX12FSRUpscalePass : public GDX12RenderPass { GDX12RenderPass::Initialize(); - IN_Texture = Inputs[0]; - IN_DepthBuffer = Inputs[1]; - IN_MotionVectors = Inputs[2]; + IN_Texture = _inputs[0]; + IN_DepthBuffer = _inputs[1]; + IN_MotionVectors = _inputs[2]; GDX12Texture* inputTexture = IN_Texture->GetTexture(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h index cdfad57..7c88810 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -14,9 +14,9 @@ class GDX12OpaquePass : public GDX12RenderPass 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()); + _outputs.push_back(OUT_Accumulation.get()); + _outputs.push_back(OUT_VelocityBuffer.get()); + _outputs.push_back(OUT_DepthStencil.get()); } // Output 0 - AccumulationTexture diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h index dc3babd..27f4ac4 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h @@ -18,8 +18,8 @@ class GDX12OutputToScreenPass : public GDX12RenderPass { GDX12RenderPass::Initialize(); - IN_Texture = Inputs[0]; - IN_BackBuffer = Inputs[1]; + IN_Texture = _inputs[0]; + IN_BackBuffer = _inputs[1]; } void Execute(GDX12CommandList* cmdList) override diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h index dd692ac..aeef803 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -59,14 +59,11 @@ class GDX12RenderPass virtual void ClearDenendencies() { - Inputs.clear(); - Outputs.clear(); + _inputs.clear(); + _outputs.clear(); } // Called after linking with other passes - virtual void Initialize() - { - if (Inputs.size() < _numInputs) { OutputDebugStringA("ERROR: Not enough inputs provided into render pass\n"); } - } + virtual void Initialize() {} uint32_t GetFlags() { return _flags; } void SetFlag(uint32_t flag, bool value) @@ -76,8 +73,22 @@ class GDX12RenderPass } bool GetFlagValue(uint32_t flag) { return _flags & flag; } - std::vector Inputs; - std::vector Outputs; + 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->IsInitialized()) { return false; } + } + return true; + } + std::vector& GetOutputs() { return _outputs; } UINT GetNumInputs() { return _numInputs; } UINT GetNumOutputs() { return _numOutputs; } @@ -94,6 +105,8 @@ class GDX12RenderPass // Might be null GDX12DeviceResources* _otherResources; + std::vector _inputs; + std::vector _outputs; UINT _numInputs; UINT _numOutputs; }; \ 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 index 806977b..1480c12 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h @@ -12,7 +12,7 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass _numInputs = 1; _numOutputs = 1; OUT_Texture = std::make_unique(); - Outputs.push_back(OUT_Texture.get()); + _outputs.push_back(OUT_Texture.get()); } // Input 0 - SharedTexture @@ -21,7 +21,7 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass { GDX12RenderPass::Initialize(); - IN_SharedTexture = Inputs[0]; + IN_SharedTexture = _inputs[0]; GDX12SharedTexture* sharedTexture = IN_SharedTexture->GetSharedTexture(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h index adec6f8..96554d9 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h @@ -11,7 +11,7 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass _numInputs = 1; _numOutputs = 1; OUT_SharedTexture = std::make_unique(); - Outputs.push_back(OUT_SharedTexture.get()); + _outputs.push_back(OUT_SharedTexture.get()); } // Input 0 - InputTexture @@ -20,7 +20,7 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass { GDX12RenderPass::Initialize(); - IN_Texture = Inputs[0]; + IN_Texture = _inputs[0]; OUT_SharedTexture->Initialize(_resources->Device, _otherResources->Device, IN_Texture->GetTexture()->GetWidth(), IN_Texture->GetTexture()->GetHeight(), diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h index 8de9cc4..560d9cf 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h @@ -11,7 +11,7 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass _numInputs = 3; _numOutputs = 1; OUT_Result = std::make_unique(); - Outputs.push_back(OUT_Result.get()); + _outputs.push_back(OUT_Result.get()); } // Input 0 - OpaqueScene @@ -22,9 +22,9 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass { GDX12RenderPass::Initialize(); - IN_OpaqueScene = Inputs[0]; - IN_TransparencyAccum = Inputs[1]; - IN_Revealage = Inputs[2]; + IN_OpaqueScene = _inputs[0]; + IN_TransparencyAccum = _inputs[1]; + IN_Revealage = _inputs[2]; // Textures GDX12TextureDesc TextureDesc1; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h index b111706..e75a079 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -12,8 +12,8 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass _numOutputs = 2; OUT_Accumulation = std::make_unique(); OUT_Revealage = std::make_unique(); - Outputs.push_back(OUT_Accumulation.get()); - Outputs.push_back(OUT_Revealage.get()); + _outputs.push_back(OUT_Accumulation.get()); + _outputs.push_back(OUT_Revealage.get()); } // Input 0 - DepthStencil @@ -23,7 +23,7 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass { GDX12RenderPass::Initialize(); - IN_DepthStencil = Inputs[0]; + IN_DepthStencil = _inputs[0]; // Textures GDX12TextureDesc TextureDesc1; From 51db3a824f6d6cf9f555d30b3b91adc9799826dc Mon Sep 17 00:00:00 2001 From: AMorunov Date: Sat, 4 Jul 2026 17:51:05 +0300 Subject: [PATCH 26/46] FIX OR REVERT: leaking render passes --- .../Engine.RendererDX12/GDX12SharedTexture.h | 1 + .../RenderPasses/GDX12RenderPass.h | 3 +- .../GDX12TextureCopyToSharedMemoryPass.h | 75 ++++++++++++------- 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h index 949d396..27bfb8b 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h @@ -49,6 +49,7 @@ class GDX12SharedTexture : public IRenderPassLink { _sharedTexturePrimary.Reset(); _sharedTextureSecondary.Reset(); + _sharedHeap.Reset(); _width = 0; _height = 0; _format = DXGI_FORMAT_UNKNOWN; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h index aeef803..96efbf4 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -45,6 +45,7 @@ class GDX12RenderPass public: GDX12RenderPass() : _flags(RENDER_PASS_FLAG_NONE), _resources(nullptr), _otherResources(nullptr), _commonData(nullptr), _numInputs(0), _numOutputs(0) {} + virtual void Setup(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) { _resources = initOnResources; @@ -76,7 +77,7 @@ class GDX12RenderPass 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"); } + if (inputs.size() < _numInputs) { OutputDebugStringA("ERROR: Not enough inputs provided into render pass\n"); } _inputs = inputs; } // returns true if all inputs are initialized diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h index 96554d9..934d92f 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h @@ -5,40 +5,59 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass { public: - GDX12TextureCopyToSharedMemoryPass() : IN_Texture(nullptr) - { - _flags = RENDER_PASS_FLAG_NONE; - _numInputs = 1; - _numOutputs = 1; - OUT_SharedTexture = std::make_unique(); - _outputs.push_back(OUT_SharedTexture.get()); + GDX12TextureCopyToSharedMemoryPass() + { + _flags = RENDER_PASS_FLAG_NONE; + } + + virtual void SetInputs(std::vector inputs) override + { + _inputs = inputs; + _numInputs = _numOutputs = inputs.size(); + + OUT_SharedTextures.clear(); + _outputs.clear(); + OUT_SharedTextures.resize(_numOutputs); + _outputs.resize(_numOutputs); + for (int i = 0; i < _numInputs; i++) + { + OUT_SharedTextures[i] = std::make_unique(); + _outputs[i] = OUT_SharedTextures[i].get(); + } } - // Input 0 - InputTexture - // Output 0 - SharedTexture + // Input N - InputTexture + // Output N - OutputSharedTexture void Initialize() override { GDX12RenderPass::Initialize(); - IN_Texture = _inputs[0]; - - OUT_SharedTexture->Initialize(_resources->Device, _otherResources->Device, - IN_Texture->GetTexture()->GetWidth(), IN_Texture->GetTexture()->GetHeight(), - IN_Texture->GetTexture()->GetFormat()); + 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 texture from device the pass was initialized at to shared memory - // Can be later used to read it on another device with CopyFromSharedMemoryPass + // 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 { - GDX12Texture* inTexture = IN_Texture->GetTexture(); - cmdList->BeginPixEvent("Texture Transfer To Shared Memory pass", Colors::ForestGreen); - cmdList->ResourceBarrier({ inTexture->GetResource()->GetCopySourceBarrier(), - OUT_SharedTexture->GetPrimaryResource()->GetCopyDestBarrier() }); - cmdList->CopyResource(OUT_SharedTexture->GetPrimaryResource()->D3DResource.Get(), - inTexture->GetResource()->D3DResource.Get()); - cmdList->ResourceBarrier({ OUT_SharedTexture->GetPrimaryResource()->GetCommonBarrier() }); + 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(); } @@ -46,17 +65,17 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass { 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_SharedTexture->Resize(newWidth, newHeight); + for (auto& texture : OUT_SharedTextures) { texture->Resize(newWidth, newHeight); } } void ClearDenendencies() override { GDX12RenderPass::ClearDenendencies(); - IN_Texture = nullptr; - OUT_SharedTexture.reset(); + IN_Textures.clear(); + OUT_SharedTextures.clear(); } private: - IRenderPassLink* IN_Texture; - std::unique_ptr OUT_SharedTexture; + std::vector IN_Textures; + std::vector> OUT_SharedTextures; }; \ No newline at end of file From 4f8c80bdc93616e33208e98ca5ee973d16b7fe82 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Sat, 4 Jul 2026 20:12:49 +0300 Subject: [PATCH 27/46] Fixed memory leaks --- .../Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h index 96efbf4..bd67b8e 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -45,7 +45,7 @@ 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; From 073097baca58da1d84f62b32b707db00b9f9dd37 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Sat, 4 Jul 2026 20:32:26 +0300 Subject: [PATCH 28/46] Added N inputs support for render passes --- Apps/App.Base/src/SceneManagerModule.cpp | 16 ++-- .../RenderPasses/GDX12BackBufferClearPass.h | 2 - .../RenderPasses/GDX12FSRUpscalePass.h | 87 +++++++++++-------- .../RenderPasses/GDX12OpaquePass.h | 2 - .../RenderPasses/GDX12OutputToScreenPass.h | 2 - .../GDX12TextureCopyFromSharedMemoryPass.h | 80 ++++++++++------- .../GDX12TextureCopyToSharedMemoryPass.h | 8 +- .../RenderPasses/GDX12WBOITCompositionPass.h | 2 - .../RenderPasses/GDX12WBOITTransparencyPass.h | 2 - 9 files changed, 107 insertions(+), 94 deletions(-) diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index 409979e..ac114bd 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - if (!LoadWorld("world1.yaml")) - { - // todo runtime error or log - } + //if (!LoadWorld("world1.yaml")) + //{ + // // todo runtime error or log + //} /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - //if (!LoadWorld(scenePath)) - //{ - // // todo runtime error or log - //} + if (!LoadWorld(scenePath)) + { + // todo runtime error or log + } World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h index 8399d5c..172bae8 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h @@ -15,8 +15,6 @@ class GDX12BackBufferClearPass : public GDX12RenderPass // Input 1 - depth stencil void Initialize() override { - GDX12RenderPass::Initialize(); - IN_currentBackBuffer = _inputs[0]; IN_depthStencil = _inputs[1]; } diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index c104854..053931a 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -9,38 +9,41 @@ class GDX12FSRUpscalePass : public GDX12RenderPass { public: - GDX12FSRUpscalePass() : IN_Texture(nullptr), IN_DepthBuffer(nullptr), - IN_MotionVectors(nullptr), OUT_UpscaledTexture(nullptr), _FFXContext(nullptr) - { - _flags = RENDER_PASS_FLAG_UPSCALER; - _numInputs = 3; - _numOutputs = 1; - OUT_UpscaledTexture = std::make_unique(); - _outputs.push_back(OUT_UpscaledTexture.get()); + GDX12FSRUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), _FFXContext(nullptr) + { _flags = RENDER_PASS_FLAG_UPSCALER; } + + virtual void SetInputs(std::vector inputs) override + { + _inputs = inputs; + _numInputs = 2; + _numOutputs = inputs.size() - 2; + + OUT_UpscaledTextures.clear(); + _outputs.clear(); + OUT_UpscaledTextures.resize(_numOutputs); + _outputs.resize(_numOutputs); + for (int i = 0; i < _numOutputs; i++) + { + OUT_UpscaledTextures[i] = std::make_unique(); + _outputs[i] = OUT_UpscaledTextures[i].get(); + } } - // Input 0 - InputTexture - // Input 1 - DepthStencil - // Input 2 - MotionVectors - // Output 0 - UpscaledTexture + // Input 0 - DepthStencil + // Input 1 - MotionVectors + // Input N - Input Texture + // Output N - UpscaledTexture void Initialize() override { - GDX12RenderPass::Initialize(); - - IN_Texture = _inputs[0]; - IN_DepthBuffer = _inputs[1]; - IN_MotionVectors = _inputs[2]; - - GDX12Texture* inputTexture = IN_Texture->GetTexture(); + IN_DepthBuffer = _inputs[0]; + IN_MotionVectors = _inputs[1]; GDX12TextureDesc TextureDesc1; - TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = inputTexture->GetFormat(); TextureDesc1.Width = _commonData->WindowWidth; TextureDesc1.Height = _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; @@ -48,7 +51,15 @@ class GDX12FSRUpscalePass : public GDX12RenderPass TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; - OUT_UpscaledTexture->Initialize(TextureDesc1); + for (int 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); + } + } // Init with window size @@ -62,7 +73,6 @@ class GDX12FSRUpscalePass : public GDX12RenderPass void Execute(GDX12CommandList* cmdList) override { - GDX12Texture* inputTexture = IN_Texture->GetTexture(); GDX12Texture* depthStencil = IN_DepthBuffer->GetTexture(); GDX12Texture* motionVectors = IN_MotionVectors->GetTexture(); @@ -70,7 +80,6 @@ class GDX12FSRUpscalePass : public GDX12RenderPass ffxDispatchDescUpscale dispatchDesc; dispatchDesc.header.type = FFX_API_DISPATCH_DESC_TYPE_UPSCALE; dispatchDesc.commandList = cmdList->GetCommandList().Get(); - dispatchDesc.color = ffxApiGetResourceDX12(inputTexture->GetResource()->D3DResource.Get(), FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ); 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 @@ -94,27 +103,31 @@ class GDX12FSRUpscalePass : public GDX12RenderPass dispatchDesc.preExposure = 1.f; dispatchDesc.viewSpaceToMetersFactor = 1.f; - dispatchDesc.output = ffxApiGetResourceDX12(OUT_UpscaledTexture->GetResource()->D3DResource.Get(), FFX_API_RESOURCE_STATE_UNORDERED_ACCESS); - 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; - - ffxReturnCode_t dispatchError = ffxDispatch(&_FFXContext, &dispatchDesc.header); - if (dispatchError != FFX_API_RETURN_OK) + for (int i = 0; i < _numOutputs; i++) { - std::string errorMsg = "FSR DISPATCH ERROR: " + std::to_string(dispatchError) + " \n"; - OutputDebugStringA(errorMsg.c_str()); + 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 { - OUT_UpscaledTexture->Resize(_commonData->WindowWidth, _commonData->WindowHeight); - + for (auto& texture : OUT_UpscaledTextures) { texture->Resize(_commonData->WindowWidth, _commonData->WindowHeight); } ffxDestroyContext(&_FFXContext, nullptr); BuildFSRContext(); } @@ -138,18 +151,18 @@ class GDX12FSRUpscalePass : public GDX12RenderPass GDX12RenderPass::ClearDenendencies(); if (_FFXContext) { ffxDestroyContext(&_FFXContext, nullptr); } - IN_Texture = nullptr; IN_DepthBuffer = nullptr; IN_MotionVectors = nullptr; - OUT_UpscaledTexture.reset(); + IN_Textures.clear(); + OUT_UpscaledTextures.clear(); } private: - IRenderPassLink* IN_Texture; IRenderPassLink* IN_DepthBuffer; IRenderPassLink* IN_MotionVectors; + std::vector IN_Textures; + std::vector> OUT_UpscaledTextures; ffxContext _FFXContext; - std::unique_ptr OUT_UpscaledTexture; void BuildFSRContext() { diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h index 7c88810..4e6cd6a 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OpaquePass.h @@ -24,8 +24,6 @@ class GDX12OpaquePass : public GDX12RenderPass // Output 2 - DepthStencil void Initialize() override { - GDX12RenderPass::Initialize(); - 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; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h index 27f4ac4..1e06e12 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h @@ -16,8 +16,6 @@ class GDX12OutputToScreenPass : public GDX12RenderPass // Input 1 - BackBuffer void Initialize() override { - GDX12RenderPass::Initialize(); - IN_Texture = _inputs[0]; IN_BackBuffer = _inputs[1]; } diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h index 1480c12..a720a7d 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h @@ -6,33 +6,32 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass { public: - GDX12TextureCopyFromSharedMemoryPass() : IN_SharedTexture(nullptr), OUT_Texture(nullptr) - { - _flags = RENDER_PASS_FLAG_NONE; - _numInputs = 1; - _numOutputs = 1; - OUT_Texture = std::make_unique(); - _outputs.push_back(OUT_Texture.get()); - } + GDX12TextureCopyFromSharedMemoryPass() + { _flags = RENDER_PASS_FLAG_NONE; } - // Input 0 - SharedTexture - // Output 0 - OutputTexture - void Initialize() override + virtual void SetInputs(std::vector inputs) override { - GDX12RenderPass::Initialize(); - - IN_SharedTexture = _inputs[0]; + _inputs = inputs; + _numInputs = _numOutputs = inputs.size(); - GDX12SharedTexture* sharedTexture = IN_SharedTexture->GetSharedTexture(); + OUT_Textures.clear(); + _outputs.clear(); + OUT_Textures.resize(_numOutputs); + _outputs.resize(_numOutputs); + for (int i = 0; i < _numInputs; i++) + { + OUT_Textures[i] = std::make_unique(); + _outputs[i] = OUT_Textures[i].get(); + } + } + // Input N - SharedTexture + // Output N - OutputTexture + void Initialize() override + { GDX12TextureDesc TextureDesc1; - TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = sharedTexture->GetFormat(); - TextureDesc1.Width = sharedTexture->GetWidth(); - TextureDesc1.Height = sharedTexture->GetHeight(); - 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; @@ -40,7 +39,18 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; - OUT_Texture->Initialize(TextureDesc1); + IN_SharedTextures.resize(_numInputs); + for (int i = 0; i < _numInputs; i++) + { + IN_SharedTextures[i] = _inputs[i]; + + GDX12SharedTexture* sharedTexture = IN_SharedTextures[i]->GetSharedTexture(); + TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = sharedTexture->GetFormat(); + TextureDesc1.Width = sharedTexture->GetWidth(); + TextureDesc1.Height = sharedTexture->GetHeight(); + TextureDesc1.SRVHeapIndex = _resources->SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); + OUT_Textures[i]->Initialize(TextureDesc1); + } } // Copies texture from shared memory onto device the pass was initialized on @@ -48,14 +58,18 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass // Resulting texture can be used as SRV on the device the texture was transferred to void Execute(GDX12CommandList* cmdList) override { - GDX12SharedTexture* inTexture = IN_SharedTexture->GetSharedTexture(); - cmdList->BeginPixEvent("Texture Transfer From Shared Memory pass", Colors::ForestGreen); - cmdList->ResourceBarrier({ inTexture->GetSecondaryResource()->GetCopySourceBarrier(), - OUT_Texture->GetResource()->GetCopyDestBarrier() }); - cmdList->CopyResource(OUT_Texture->GetResource()->D3DResource.Get(), - inTexture->GetSecondaryResource()->D3DResource.Get()); - cmdList->ResourceBarrier({ inTexture->GetSecondaryResource()->GetCommonBarrier() }); + 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(); } @@ -63,17 +77,17 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass { 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_Texture->Resize(newWidth, newHeight); + for (auto& texture : OUT_Textures) { texture->Resize(newWidth, newHeight); } } void ClearDenendencies() override { GDX12RenderPass::ClearDenendencies(); - IN_SharedTexture = nullptr; - OUT_Texture.reset(); + IN_SharedTextures.clear(); + OUT_Textures.clear(); } private: - IRenderPassLink* IN_SharedTexture; - std::unique_ptr OUT_Texture; + std::vector IN_SharedTextures; + std::vector> OUT_Textures; }; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h index 934d92f..2bfbe03 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h @@ -6,9 +6,7 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass { public: GDX12TextureCopyToSharedMemoryPass() - { - _flags = RENDER_PASS_FLAG_NONE; - } + { _flags = RENDER_PASS_FLAG_NONE; } virtual void SetInputs(std::vector inputs) override { @@ -19,7 +17,7 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass _outputs.clear(); OUT_SharedTextures.resize(_numOutputs); _outputs.resize(_numOutputs); - for (int i = 0; i < _numInputs; i++) + for (int i = 0; i < _numOutputs; i++) { OUT_SharedTextures[i] = std::make_unique(); _outputs[i] = OUT_SharedTextures[i].get(); @@ -30,8 +28,6 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass // Output N - OutputSharedTexture void Initialize() override { - GDX12RenderPass::Initialize(); - IN_Textures.resize(_numInputs); for (int i = 0; i < _numInputs; i++) { diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h index 560d9cf..0138dcb 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITCompositionPass.h @@ -20,8 +20,6 @@ class GDX12WBOITCompositionPass : public GDX12RenderPass // Output 0 - CompositionResult void Initialize() override { - GDX12RenderPass::Initialize(); - IN_OpaqueScene = _inputs[0]; IN_TransparencyAccum = _inputs[1]; IN_Revealage = _inputs[2]; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h index e75a079..f66fdf8 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12WBOITTransparencyPass.h @@ -21,8 +21,6 @@ class GDX12WBOITTransparencyPass : public GDX12RenderPass // Output 1 - RevealageTexture void Initialize() override { - GDX12RenderPass::Initialize(); - IN_DepthStencil = _inputs[0]; // Textures From b38ab2588943f21e477d9af081704b6daba30d4e Mon Sep 17 00:00:00 2001 From: DvornikovArtem Date: Sun, 5 Jul 2026 00:49:32 +0300 Subject: [PATCH 29/46] Add xess --- Apps/App.Benchmark/App.Benchmark.vcxproj | 8 +- Apps/App.Editor/App.Editor.vcxproj | 8 +- .../xess/Include/xell/xell.h | 245 ++++++++ .../xess/Include/xell/xell_d3d12.h | 32 ++ .../xess/Include/xess/xess.h | 434 ++++++++++++++ .../xess/Include/xess/xess_d3d11.h | 149 +++++ .../xess/Include/xess/xess_d3d12.h | 193 +++++++ .../xess/Include/xess/xess_d3d12_debug.h | 103 ++++ .../xess/Include/xess/xess_debug.h | 179 ++++++ .../xess/Include/xess/xess_vk.h | 262 +++++++++ .../xess/Include/xess/xess_vk_debug.h | 90 +++ .../xess/Include/xess_fg/xefg_swapchain.h | 528 ++++++++++++++++++ .../Include/xess_fg/xefg_swapchain_d3d12.h | 328 +++++++++++ .../Include/xess_fg/xefg_swapchain_debug.h | 68 +++ .../External.Libraries/xess/lib/libxess.lib | Bin 0 -> 20004 bytes External/Runtime/libxess.dll | 3 + MSBuild/Props/PEPEngine.External.Paths.props | 1 + MSBuild/Props/PEPEngine.External.XeSS.props | 9 + ...ne.Module.Engine.RendererDX12.Public.props | 1 + 19 files changed, 2633 insertions(+), 8 deletions(-) create mode 100644 External/External.Libraries/xess/Include/xell/xell.h create mode 100644 External/External.Libraries/xess/Include/xell/xell_d3d12.h create mode 100644 External/External.Libraries/xess/Include/xess/xess.h create mode 100644 External/External.Libraries/xess/Include/xess/xess_d3d11.h create mode 100644 External/External.Libraries/xess/Include/xess/xess_d3d12.h create mode 100644 External/External.Libraries/xess/Include/xess/xess_d3d12_debug.h create mode 100644 External/External.Libraries/xess/Include/xess/xess_debug.h create mode 100644 External/External.Libraries/xess/Include/xess/xess_vk.h create mode 100644 External/External.Libraries/xess/Include/xess/xess_vk_debug.h create mode 100644 External/External.Libraries/xess/Include/xess_fg/xefg_swapchain.h create mode 100644 External/External.Libraries/xess/Include/xess_fg/xefg_swapchain_d3d12.h create mode 100644 External/External.Libraries/xess/Include/xess_fg/xefg_swapchain_debug.h create mode 100644 External/External.Libraries/xess/lib/libxess.lib create mode 100644 External/Runtime/libxess.dll create mode 100644 MSBuild/Props/PEPEngine.External.XeSS.props diff --git a/Apps/App.Benchmark/App.Benchmark.vcxproj b/Apps/App.Benchmark/App.Benchmark.vcxproj index f7a784a..455a8bd 100644 --- a/Apps/App.Benchmark/App.Benchmark.vcxproj +++ b/Apps/App.Benchmark/App.Benchmark.vcxproj @@ -114,9 +114,9 @@ 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)" @@ -135,8 +135,8 @@ 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)" diff --git a/Apps/App.Editor/App.Editor.vcxproj b/Apps/App.Editor/App.Editor.vcxproj index 4fd5eb3..ef02c95 100644 --- a/Apps/App.Editor/App.Editor.vcxproj +++ b/Apps/App.Editor/App.Editor.vcxproj @@ -114,8 +114,8 @@ 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)" @@ -134,8 +134,8 @@ 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)" 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 0000000000000000000000000000000000000000..a48d04ec39f6d1a59c3bd5232ea3ed63541c468e GIT binary patch literal 20004 zcmcIr3vgA%8U6vEJTxLI@(joul8}&_5D1XRP2iFQm=GhQ)^JG<;g*}+>&*$qj;$@D zPRHpu9qc$l9jwmiv@>+1GjwW4O7T(DO68#zsul2sv>>gt4zzYA{rBv7?AiVI-g8L2 zGk?xGyZ`>*zW#sz{dY5^GM;JQv~+k;zW-NH?EiMY=G!lk`Na$Q>-ymU@HoKCeE_r1 z0L+~PP&9f9!AkEoR&^Q`ACZ%vuPYY zkt$I(qs3{PP}X9k$~!qN{uIBFDzNU18V_)4I0(R~aV4jfTLCP>K3Iv=w3kx@)|1i7 z3!Iv;ZH!_&Z5oSDq!puWdIFzF%b(&juMfZ?EI$va1Th&Ep5|1L1YlIs%BkoCfJN)^ zi8TMXP50mvsrY?Pr7r?7itOf8T87_9g&mwCC76!1pwcGfU4T@~WFQrs;wmG(@Wp#5~GO?l0=;?vBwpF(`HmVHp zpv}SaTUOk@s-Z1f-BOJu5?$#wR(QE#wi=n9M5-I4PajXL+cc8vjQVvFvy$#BwI-8F z8yPcU^fgmlGO}$AokxnLzj8z?kAacBtI4_8NyKjjcuOv!tiud7Irc>QLi7iG`yk~Q3 zJlV^;SfA@jKhDPnl>2Yt4H}PV>0y zQ<-+7(ddk~^BGYeZ#PpJKF@V|UTJK@nnc=2Cc2H9-bAuvtr<6aJtZNsys~SJq|t7! zGR*r@naxe94kKx|O-UBYnDLAm?d?i)R`<)}U^U95HYTu2ozb`%w-}W~kH0$Bh`FLQ z@TYj3I2N`ZtchphT?T4gy)znWhF1>7%h_w3TB#Xcx#)suaY=2)h?|DZW|bn6r83q? zIK#pR!zv`DOQmAn30uJ#uJt8xU_)54)p|j!KUpeM*Jrf%np|b9N;nA;9|~bsvll00 zPfN-jVXFv{rjvDO=ch!)RJl@s@s}lG2CNf4xth>jIcefjLeWrny z0j+~IFu8a%(xS$eM0QyUM^;JoIAPFC5_RHo+mRqJf5wb~inG|{c=^@DQXT(;u)V48IEN)weHTP$7p;=j^Ow#+v&LiatGmy%W z(r|=@=}Fet&mxugPf<;#l#BwM^+*TkS`lO|X0zqU4>_(wBPKoeQy%IO7*8l+fW&)g<4KQgg zz>Hdehn8X7tp*?upC4BNT*Bub{H|OAu%QlMKgO)iMFDm!q$a56aw_({`$a8l! zz);LDSq|_nzVE64*n;2FkpHno0OOF3Vk{}W82OOy#P?6}S&4iH8UYSsrB>o|E5_6E zkoGpAOia6g@Ade;GX^jgY4i$!Cy<^(oIZ>-T|hdBajMgW0LcP?R(wBE1h5|I_*fays0VE!pAyVs6k&BHj@^GLJGu?!N1K%oQ{KpE6Q z6-1x{7Q$j!1W~AjawvrwsD)*)1gc>vtbiD-ga%j+^)Lj6URJr=;8vIj6CfWZ!&I08 zlVAjlf$?xXTn$&kwQvJm12@4~xC(~D6>uZm4CCNB7zv{x4@SW)Pz*&d9}1xWX2DFD z3v*yP%z$Yy4`#zRDSH^WbDr||q)f?~lX4x`NlMn)Nr^4ciiAvpcc)6o?bs;pmMTQ_ z4b)tXXQVRvml!oat80J_)wqn7J1j|)mscs9SUD9A%5zYevUCmMEU4u*Z7ylU_R5Qk zTiVJU_-Y`^)2#!Jsn+uPmr{XEzj|Lr_*`1@Da|BVB>g0L94#d?b-GG2(;BN|74%lm z5_J0_oeAg!iqlocqtRy_yI-qyT>g2k=i=udWWJ^6bdD4+CYcDG*YHuAuVc;Gp@bFC z$;#SCq(zVs-RcC= z>exk9&9E~x2TDHCS#6Ll$2lLc2G~Bf@d?q510N#iIMi2!Qb8L|onEq&;Yrfk8YT-Z zf;=kq_Rh@C*2XOCe7bA3mc}lXv)@sGuKn1(_NkTENIQh9)1bkP@G7u4h|PxfG{a+W zZP1#HtPy`*vsxQetB@_;FVr(jgxh!W!ug1}wU3K9!x39;;rfrG#B9sRu!$k{j+f-j zca}mKQa9b-Q*N@;O>P3#NN{o5-e&u@FX#Co4VZ9wKXc z5DkmmC4{lEg=gt0#Xwm_T+_t9NTVcVWK+j%Y_2xaOoTErM#cE>M9C%LiK-fTriOE< z3gj~gig|HMIfha)EK0t%6;`kLjR`MosiF36lYQr@up^nYLVdYz?Uhz6uC$ERgk}bC_YDH%!>U+2#uNvH|AZ9X@{*G!1&b!FwN0T ziS|sYC$-VcpVd4&zcIFo#VVB_17j6o1Q-HiZ+ZClO6yHPfvWaYR~qYTnnQ;4WBt4m z$co`PMoyEfFv`hNHaRI)<2a7ZQ_6Ud#p8*1DJ(so{jq;c7G4^(zu03aG~?gFy#zO0 zXl|gHQW9})da{`^6uN%#ov(gtRgP7W-TqT&N(aw!{|Yk&+>-pHhJ_ipjHze#H#Ic-emLb zCIwk@&?{CTw7!)SzFX>7q7Ct{@e&K(0SQ(Q=lDsi zi0~fB0#JVC!wtv&&iu-;+3LYVDpVChj|t`7+;v~=r_8&#)n5nQS((u6@T+@-@G8g5 zn)v6*h(8YTS;R+*77q;1*}@B}>dSkee-h%2_u)CAXc10$4>ZCNVy6A)>&%g9h&I7S zqr%(*PH5{!?U4R9ciDNiLz*aJ`eT10WawE`O4ybkd^r7oERZls#2l3U7}Y}K;+Zd5 z3nzM&Jth)>!nc;1wJ+^xdxy>186IkmP=Qc|U~MJV`KNyU$$qAv zGd&q}f1wt^<`S{8{I|R4-I<6y&qJn8D+Q>_&>Ui4 zy0c~KD^n1+K*04Kg$@jnuuOT6zI2LtCWSsk=bTl96W)XME786eJ{j{hYhRIvrr-F4 zp1q}n1svZ0?Ah^%IA26mgBYQ)BE-(N=&jfPm5*4(HdeM!Lg?NkEZ%pY?LNmWUWtvD zBYY6PjYNMwbKk-b*ov~i#Z*?5dQtf=LobM^)W&0HKVmCNsfRk)D+*z0Z@8o2B(t;; z4|UKiE#+aJYkKWtHlAf3Ubdh_=<%d%?2d{b9%VMR+{63^tb2s81(iRW@&{%M7JA5o zX$uJd^6DQqoMZlFg@fo`u@JOToV>y89HAxWkKEDEv}BQuL|)$zK|_xvwX=WV!OzdJ zo&91zDms1sn-apm#}B9uRDAL2joU7=cu!@HI=B~422=y;{NUxcPakFH2TQayAnt<< zs20@hek1+;H`wf6YS%)!GBfCiuN|KLHbY$IB1-ph28KwicO(D!oE5dNauM|#egQm? zR#E%I_x5!iV)|R{;!&IZut?NO{#o(vPx29|#zoR^^uyv&k?HT98QISw)3qXAAf*kB zPMkMQ{rp$2v&eK*k4~y$(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..fa1ee3b 100644 --- a/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props +++ b/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props @@ -1,6 +1,7 @@ + $(PEPRepoRoot)Engine\Engine.RendererDX12\Include;%(AdditionalIncludeDirectories) From 890ca85acd9461af5a1bb9478ed8109dc11ae91f Mon Sep 17 00:00:00 2001 From: DvornikovArtem Date: Sun, 5 Jul 2026 03:47:42 +0300 Subject: [PATCH 30/46] Add nvidia streamline --- Apps/App.Base/src/RenderModule.cpp | 8 +- .../Engine.RendererDX12.vcxproj | 2 + .../Engine.RendererDX12.vcxproj.filters | 6 + .../Engine.RendererDX12/GDX12CommandQueue.h | 2 + .../Include/Engine.RendererDX12/GDX12Device.h | 2 + .../Engine.RendererDX12/GDX12DeviceFactory.h | 1 + .../Engine.RendererDX12/GDX12Streamline.h | 95 +++++++ .../Engine.RendererDX12/GDX12SwapChain.h | 4 +- .../src/GDX12CommandQueue.cpp | 10 +- .../Engine.RendererDX12/src/GDX12Device.cpp | 9 + .../src/GDX12DeviceFactory.cpp | 21 +- .../src/GDX12Streamline.cpp | 244 ++++++++++++++++++ .../src/GDX12SwapChain.cpp | 24 +- ...ne.Module.Engine.RendererDX12.Public.props | 1 + 14 files changed, 415 insertions(+), 14 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Streamline.h create mode 100644 Engine/Engine.RendererDX12/src/GDX12Streamline.cpp diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index c60cba0..37a7566 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -5,6 +5,7 @@ #include "App.Base/Modules/SceneManagerModule.h" #include "Common/ConsoleVariables.h" +#include "Engine.RendererDX12/GDX12Streamline.h" RenderModule::RenderModule(Window* window, GameTimer* timer) : _dualGPUMode(false), _window(window), _timer(timer), @@ -21,11 +22,14 @@ RenderModule::~RenderModule() for (auto& renderpass : _primaryRenderPassExecutionList) { renderpass->ClearDenendencies(); } for (auto& renderpass : _secondaryRenderPassExecutionList) { renderpass->ClearDenendencies(); } + GDX12Streamline::Get().Shutdown(); GDX12ShaderCompiler::Shutdown(); } void RenderModule::Initialize() { + GDX12Streamline::Get().Initialize(); + #if defined(DEBUG) || defined(_DEBUG) // Enable the D3D12 debug layer. ComPtr debugController; @@ -34,15 +38,15 @@ void RenderModule::Initialize() #endif _primaryDevice = std::make_unique(); - _primaryDevice->Initialize(GDX12DeviceFactory::GetMostPerformantAdapter().Get()); _primaryDevice->Role = DEVICE_ROLE_PRIMARY; + _primaryDevice->Initialize(GDX12DeviceFactory::GetMostPerformantAdapter().Get()); _primaryResources.Initialize(_primaryDevice.get()); if (true) { _secondaryDevice = std::make_unique(); - _secondaryDevice->Initialize(GDX12DeviceFactory::GetDeviceDescriptors()[1].Adapter.Get()); _secondaryDevice->Role = DEVICE_ROLE_SECONDARY; + _secondaryDevice->Initialize(GDX12DeviceFactory::GetDeviceDescriptors()[1].Adapter.Get()); _secondaryResources.Initialize(_secondaryDevice.get()); _dualGPUMode = true; } diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index fcd44b5..86b24f3 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -25,6 +25,7 @@ + @@ -58,6 +59,7 @@ + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index fc16d71..3a42f88 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -102,6 +102,9 @@ Header Files + + Header Files + Header Files @@ -164,6 +167,9 @@ Source Files + + Source Files + diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h index b89e3ef..49b6b85 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h @@ -14,6 +14,7 @@ class GDX12CommandQueue void Reset(); const ComPtr& GetCommandQueue(); + const ComPtr& GetPresentCommandQueue(); const ComPtr& GetFence(); ComPtr& GetOtherFence(); @@ -38,6 +39,7 @@ class GDX12CommandQueue void ClearCompletedLists(); ComPtr _commandQueue; + ComPtr _proxyCommandQueue; ComPtr _fence; //shared fence from another device //null if _dualGPUMode is false diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h index 949ed50..918d7c9 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h @@ -31,6 +31,7 @@ class GDX12Device : public std::enable_shared_from_this void Reset(); const ComPtr& GetDevice(); + const ComPtr& GetCommandQueueCreationDevice(); GDX12CommandQueue* GetCommandQueue(); const DeviceSpecs& GetDeviceFeatures(); const bool IsInitialized(); @@ -41,6 +42,7 @@ class GDX12Device : public std::enable_shared_from_this ComPtr _adapter; ComPtr _device; + ComPtr _proxyDevice; std::unique_ptr _commandQueue; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceFactory.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceFactory.h index c5f49da..ce73c2f 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/GDX12Streamline.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Streamline.h new file mode 100644 index 0000000..a7bd9f7 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Streamline.h @@ -0,0 +1,95 @@ +#pragma once + +#include "Engine.RendererDX12/D3DHelpers.h" + +#include "nvidia-sdk/sl.h" +#include "nvidia-sdk/sl_helpers.h" + +class GDX12Streamline +{ +public: + static GDX12Streamline& Get(); + + bool Initialize(); + void Shutdown(); + + bool IsEnabled() const; + + ComPtr CreateProxyFactory(const ComPtr& nativeFactory) const; + ComPtr CreateProxyDevice(const ComPtr& nativeDevice, bool setAsMainDevice) const; + ComPtr GetNativeCommandQueue(const ComPtr& commandQueue) const; + ComPtr GetNativeSwapChain(const ComPtr& swapChain) const; + ComPtr GetNativeResource(const ComPtr& resource) const; + +private: + GDX12Streamline() = default; + + static void StreamlineLog(sl::LogType type, const char* message); + + std::wstring GetRuntimeDirectory(); + bool LoadInterposer(); + bool LoadFunctions(); + + void Log(const std::string& message) const; + void LogWarning(const std::string& message) const; + void LogFailure(const char* operation, sl::Result result) const; + + 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 _initializationAttempted = false; + 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; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h index 224af52..96db6da 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h @@ -36,9 +36,11 @@ class GDX12SwapChain : public IRenderPassLink private: void CreateBuffers(); + IDXGISwapChain4* GetPresentationSwapChain() const; GDX12Device* _device; ComPtr _swapChain; + ComPtr _proxySwapChain; GDX12DescriptorHeap* _rtvHeap; DXGI_FORMAT _format; @@ -52,4 +54,4 @@ class GDX12SwapChain : public IRenderPassLink D3D12_VIEWPORT _screenViewport; D3D12_RECT _screenScissorRect; -}; +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp b/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp index 14f9686..6e52dd1 100644 --- a/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp @@ -1,6 +1,7 @@ #include "Engine.RendererDX12/GDX12CommandQueue.h" #include "Engine.RendererDX12/GDX12CommandList.h" +#include "Engine.RendererDX12/GDX12Streamline.h" GDX12CommandQueue::GDX12CommandQueue(GDX12Device* device) : FenceValue(0), _device(device), _lastDispatchedFenceValue(0) @@ -11,13 +12,15 @@ 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->GetCommandQueueCreationDevice()->CreateCommandQueue(&desc, IID_PPV_ARGS(&_proxyCommandQueue))); + _commandQueue = GDX12Streamline::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(); @@ -35,6 +38,11 @@ const ComPtr& GDX12CommandQueue::GetCommandQueue() return _commandQueue; } +const ComPtr& GDX12CommandQueue::GetPresentCommandQueue() +{ + return _proxyCommandQueue ? _proxyCommandQueue : _commandQueue; +} + GDX12CommandList* GDX12CommandQueue::GetCommandList() { GDX12CommandList* rawPtr; diff --git a/Engine/Engine.RendererDX12/src/GDX12Device.cpp b/Engine/Engine.RendererDX12/src/GDX12Device.cpp index faa33f3..59103d7 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Device.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Device.cpp @@ -1,6 +1,7 @@ #include "Engine.RendererDX12/GDX12Device.h" #include "Engine.RendererDX12/GDX12CommandQueue.h" +#include "Engine.RendererDX12/GDX12Streamline.h" GDX12Device::GDX12Device() : _isInitialized(false), @@ -42,6 +43,8 @@ HRESULT GDX12Device::Initialize(ComPtr adapter) CollectDeviceFeatures(); + _proxyDevice = GDX12Streamline::Get().CreateProxyDevice(_device, Role == DEVICE_ROLE_PRIMARY); + _commandQueue = std::make_unique(this); _isInitialized = true; @@ -68,6 +71,7 @@ void GDX12Device::CollectDeviceFeatures() void GDX12Device::Reset() { + _proxyDevice.Reset(); _device.Reset(); _adapter.Reset(); _commandQueue.reset(); @@ -79,6 +83,11 @@ const ComPtr& GDX12Device::GetDevice() return _device; } +const ComPtr& GDX12Device::GetCommandQueueCreationDevice() +{ + return _proxyDevice ? _proxyDevice : _device; +} + GDX12CommandQueue* GDX12Device::GetCommandQueue() { return _commandQueue.get(); diff --git a/Engine/Engine.RendererDX12/src/GDX12DeviceFactory.cpp b/Engine/Engine.RendererDX12/src/GDX12DeviceFactory.cpp index 0fdf340..9ca00d7 100644 --- a/Engine/Engine.RendererDX12/src/GDX12DeviceFactory.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12DeviceFactory.cpp @@ -2,17 +2,30 @@ #include "Engine.RendererDX12/GDX12Device.h" #include "Engine.RendererDX12/GDX12CommandQueue.h" +#include "Engine.RendererDX12/GDX12Streamline.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 && GDX12Streamline::Get().IsEnabled()) + { + _dxgiFactoryProxy = GDX12Streamline::Get().CreateProxyFactory(_dxgiFactory); + } + return S_OK; + } HRESULT hr = CreateDXGIFactory2(D3D12_DEVICE_FACTORY_FLAG_ALLOW_RETURNING_EXISTING_DEVICE, IID_PPV_ARGS(&_dxgiFactory)); - if (SUCCEEDED(hr)) { _isInitialized = true; } + if (SUCCEEDED(hr)) + { + _dxgiFactoryProxy = GDX12Streamline::Get().CreateProxyFactory(_dxgiFactory); + _isInitialized = true; + } return hr; } @@ -24,6 +37,7 @@ const ComPtr& GDX12DeviceFactory::GetFactory() void GDX12DeviceFactory::Reset() { + _dxgiFactoryProxy.Reset(); _dxgiFactory.Reset(); _isInitialized = false; } @@ -88,9 +102,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/GDX12Streamline.cpp b/Engine/Engine.RendererDX12/src/GDX12Streamline.cpp new file mode 100644 index 0000000..512f179 --- /dev/null +++ b/Engine/Engine.RendererDX12/src/GDX12Streamline.cpp @@ -0,0 +1,244 @@ +#include "Engine.RendererDX12/GDX12Streamline.h" + +#include + +#include "nvidia-sdk/sl_security.h" + +namespace +{ + constexpr sl::Feature kRequestedFeatures[] = + { + sl::kFeatureNIS, + sl::kFeatureReflex, + sl::kFeatureDirectSR + }; + + constexpr const char* kLogPrefix = "Streamline: "; +} + +GDX12Streamline& GDX12Streamline::Get() +{ + static GDX12Streamline instance; + return instance; +} + +bool GDX12Streamline::Initialize() +{ + if (_initialized) + { + return true; + } + + if (_initializationAttempted) + { + return false; + } + + _initializationAttempted = true; + _runtimeDirectory = GetRuntimeDirectory(); + + if (_runtimeDirectory.empty()) + { + LogWarning("Failed to resolve executable directory, Streamline is disabled."); + return false; + } + + if (!LoadInterposer() || !LoadFunctions()) + { + Shutdown(); + return false; + } + + const wchar_t* pluginPaths[] = { _runtimeDirectory.c_str() }; + + sl::Preferences preferences{}; + preferences.showConsole = false; + preferences.logLevel = sl::LogLevel::eDefault; + preferences.pathsToPlugins = pluginPaths; + preferences.numPathsToPlugins = static_cast(std::size(pluginPaths)); + preferences.pathToLogsAndData = _runtimeDirectory.c_str(); + preferences.logMessageCallback = &GDX12Streamline::StreamlineLog; + preferences.flags = sl::PreferenceFlags::eDisableCLStateTracking + | sl::PreferenceFlags::eUseManualHooking + | sl::PreferenceFlags::eUseDXGIFactoryProxy; + preferences.featuresToLoad = kRequestedFeatures; + preferences.numFeaturesToLoad = static_cast(std::size(kRequestedFeatures)); + preferences.engine = sl::EngineType::eCustom; + preferences.engineVersion = "PEPEngine2"; + preferences.projectId = "8f52d4be-6cce-4e1a-b95f-31a43fc25369"; + 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 GDX12Streamline::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; + + if (_interposerModule) + { + FreeLibrary(_interposerModule); + _interposerModule = nullptr; + } +} + +bool GDX12Streamline::IsEnabled() const +{ + return _initialized; +} + +ComPtr GDX12Streamline::CreateProxyFactory(const ComPtr& nativeFactory) const +{ + return UpgradeInterface(nativeFactory, "slUpgradeInterface(IDXGIFactory7)"); +} + +ComPtr GDX12Streamline::CreateProxyDevice(const ComPtr& nativeDevice, bool setAsMainDevice) const +{ + if (!_initialized || !nativeDevice) + { + return nativeDevice; + } + + if (setAsMainDevice && !_mainDeviceWasSet) + { + const sl::Result setDeviceResult = _slSetD3DDevice(nativeDevice.Get()); + if (setDeviceResult != sl::Result::eOk) + { + LogFailure("slSetD3DDevice", setDeviceResult); + return nativeDevice; + } + + const_cast(this)->_mainDeviceWasSet = true; + } + + return UpgradeInterface(nativeDevice, "slUpgradeInterface(ID3D12Device14)"); +} + +ComPtr GDX12Streamline::GetNativeCommandQueue(const ComPtr& commandQueue) const +{ + return UnwrapInterface(commandQueue); +} + +ComPtr GDX12Streamline::GetNativeSwapChain(const ComPtr& swapChain) const +{ + return UnwrapInterface(swapChain); +} + +ComPtr GDX12Streamline::GetNativeResource(const ComPtr& resource) const +{ + return UnwrapInterface(resource); +} + +void GDX12Streamline::StreamlineLog(sl::LogType type, const char* message) +{ + const char* level = "INFO"; + if (type == sl::LogType::eWarn) + { + level = "WARN"; + } + else if (type == sl::LogType::eError) + { + level = "ERROR"; + } + + std::string formattedMessage = std::string(kLogPrefix) + '[' + level + "] " + (message ? message : "") + '\n'; + OutputDebugStringA(formattedMessage.c_str()); +} + +std::wstring GDX12Streamline::GetRuntimeDirectory() +{ + wchar_t executablePath[MAX_PATH] = {}; + const DWORD pathLength = GetModuleFileNameW(nullptr, executablePath, MAX_PATH); + if (pathLength == 0 || pathLength == MAX_PATH) + { + return {}; + } + + return std::filesystem::path(std::wstring(executablePath, executablePath + pathLength)).parent_path().wstring(); +} + +bool GDX12Streamline::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 next to the executable, Streamline is disabled."); + return false; + } + + if (!sl::security::verifyEmbeddedSignature(interposerPath.c_str())) + { + LogWarning("sl.interposer.dll signature check failed, continuing because development Streamline DLLs can be unsigned."); + } + + _interposerModule = LoadLibraryW(interposerPath.c_str()); + if (!_interposerModule) + { + LogWarning("LoadLibraryW failed for sl.interposer.dll, Streamline is disabled."); + return false; + } + + return true; +} + +bool GDX12Streamline::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")); + + if (!_slInit || !_slShutdown || !_slUpgradeInterface || !_slGetNativeInterface || !_slSetD3DDevice) + { + LogWarning("Required Streamline exports are missing, Streamline is disabled."); + return false; + } + + return true; +} + +void GDX12Streamline::Log(const std::string& message) const +{ + std::string formattedMessage = std::string(kLogPrefix) + message + '\n'; + OutputDebugStringA(formattedMessage.c_str()); +} + +void GDX12Streamline::LogWarning(const std::string& message) const +{ + std::string formattedMessage = std::string(kLogPrefix) + "WARN: " + message + '\n'; + OutputDebugStringA(formattedMessage.c_str()); +} + +void GDX12Streamline::LogFailure(const char* operation, sl::Result result) const +{ + const char* resultName = sl::getResultAsStr(result); + std::string formattedMessage = std::string(kLogPrefix) + operation + " failed: " + (resultName ? resultName : "Unknown") + '\n'; + OutputDebugStringA(formattedMessage.c_str()); +} \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp index 3e0b27c..867bd9d 100644 --- a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp @@ -4,6 +4,7 @@ #include #include #include +#include GDX12SwapChain::GDX12SwapChain(GDX12Device* device, HWND hwnd, DXGI_FORMAT format, UINT bufferCount, UINT width, UINT height, GDX12DescriptorHeap* rtvHeap) @@ -27,9 +28,11 @@ 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 = GDX12Streamline::Get().GetNativeSwapChain(_proxySwapChain); CreateBuffers(); + _currentBufferIndex = GetPresentationSwapChain()->GetCurrentBackBufferIndex(); _screenViewport.TopLeftX = 0; _screenViewport.TopLeftY = 0; @@ -54,7 +57,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 = GDX12Streamline::Get().GetNativeResource(backBuffer); GDX12TextureDesc textureDesc; textureDesc.RTVHeap = _rtvHeap; @@ -88,14 +92,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; @@ -111,8 +115,8 @@ void GDX12SwapChain::Present() { UINT syncInterval = bVSyncEnabled ? 1 : 0; UINT presentFlags = bVSyncEnabled ? 0 : DXGI_PRESENT_ALLOW_TEARING; - _swapChain->Present(syncInterval, presentFlags); - _currentBufferIndex = (_currentBufferIndex + 1) % _bufferCount; + GetPresentationSwapChain()->Present(syncInterval, presentFlags); + _currentBufferIndex = GetPresentationSwapChain()->GetCurrentBackBufferIndex(); } D3D12_VIEWPORT GDX12SwapChain::GetViewport() @@ -174,6 +178,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/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props b/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props index fa1ee3b..6b41c9c 100644 --- a/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props +++ b/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props @@ -1,6 +1,7 @@ + From fff6a73300d29e9c118d4fe0d27bcd2b1effd002 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Sun, 5 Jul 2026 12:08:45 +0300 Subject: [PATCH 31/46] Revert "Add nvidia streamline" This reverts commit 890ca85acd9461af5a1bb9478ed8109dc11ae91f. --- Apps/App.Base/src/RenderModule.cpp | 8 +- .../Engine.RendererDX12.vcxproj | 2 - .../Engine.RendererDX12.vcxproj.filters | 6 - .../Engine.RendererDX12/GDX12CommandQueue.h | 2 - .../Include/Engine.RendererDX12/GDX12Device.h | 2 - .../Engine.RendererDX12/GDX12DeviceFactory.h | 1 - .../Engine.RendererDX12/GDX12Streamline.h | 95 ------- .../Engine.RendererDX12/GDX12SwapChain.h | 4 +- .../src/GDX12CommandQueue.cpp | 10 +- .../Engine.RendererDX12/src/GDX12Device.cpp | 9 - .../src/GDX12DeviceFactory.cpp | 21 +- .../src/GDX12Streamline.cpp | 244 ------------------ .../src/GDX12SwapChain.cpp | 24 +- ...ne.Module.Engine.RendererDX12.Public.props | 1 - 14 files changed, 14 insertions(+), 415 deletions(-) delete mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Streamline.h delete mode 100644 Engine/Engine.RendererDX12/src/GDX12Streamline.cpp diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 37a7566..c60cba0 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -5,7 +5,6 @@ #include "App.Base/Modules/SceneManagerModule.h" #include "Common/ConsoleVariables.h" -#include "Engine.RendererDX12/GDX12Streamline.h" RenderModule::RenderModule(Window* window, GameTimer* timer) : _dualGPUMode(false), _window(window), _timer(timer), @@ -22,14 +21,11 @@ RenderModule::~RenderModule() for (auto& renderpass : _primaryRenderPassExecutionList) { renderpass->ClearDenendencies(); } for (auto& renderpass : _secondaryRenderPassExecutionList) { renderpass->ClearDenendencies(); } - GDX12Streamline::Get().Shutdown(); GDX12ShaderCompiler::Shutdown(); } void RenderModule::Initialize() { - GDX12Streamline::Get().Initialize(); - #if defined(DEBUG) || defined(_DEBUG) // Enable the D3D12 debug layer. ComPtr debugController; @@ -38,15 +34,15 @@ void RenderModule::Initialize() #endif _primaryDevice = std::make_unique(); - _primaryDevice->Role = DEVICE_ROLE_PRIMARY; _primaryDevice->Initialize(GDX12DeviceFactory::GetMostPerformantAdapter().Get()); + _primaryDevice->Role = DEVICE_ROLE_PRIMARY; _primaryResources.Initialize(_primaryDevice.get()); if (true) { _secondaryDevice = std::make_unique(); - _secondaryDevice->Role = DEVICE_ROLE_SECONDARY; _secondaryDevice->Initialize(GDX12DeviceFactory::GetDeviceDescriptors()[1].Adapter.Get()); + _secondaryDevice->Role = DEVICE_ROLE_SECONDARY; _secondaryResources.Initialize(_secondaryDevice.get()); _dualGPUMode = true; } diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index 86b24f3..fcd44b5 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -25,7 +25,6 @@ - @@ -59,7 +58,6 @@ - diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index 3a42f88..fc16d71 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -102,9 +102,6 @@ Header Files - - Header Files - Header Files @@ -167,9 +164,6 @@ Source Files - - Source Files - diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h index 49b6b85..b89e3ef 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h @@ -14,7 +14,6 @@ class GDX12CommandQueue void Reset(); const ComPtr& GetCommandQueue(); - const ComPtr& GetPresentCommandQueue(); const ComPtr& GetFence(); ComPtr& GetOtherFence(); @@ -39,7 +38,6 @@ class GDX12CommandQueue void ClearCompletedLists(); ComPtr _commandQueue; - ComPtr _proxyCommandQueue; ComPtr _fence; //shared fence from another device //null if _dualGPUMode is false diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h index 918d7c9..949ed50 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h @@ -31,7 +31,6 @@ class GDX12Device : public std::enable_shared_from_this void Reset(); const ComPtr& GetDevice(); - const ComPtr& GetCommandQueueCreationDevice(); GDX12CommandQueue* GetCommandQueue(); const DeviceSpecs& GetDeviceFeatures(); const bool IsInitialized(); @@ -42,7 +41,6 @@ class GDX12Device : public std::enable_shared_from_this ComPtr _adapter; ComPtr _device; - ComPtr _proxyDevice; std::unique_ptr _commandQueue; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceFactory.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceFactory.h index ce73c2f..c5f49da 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceFactory.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12DeviceFactory.h @@ -45,6 +45,5 @@ 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/GDX12Streamline.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Streamline.h deleted file mode 100644 index a7bd9f7..0000000 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Streamline.h +++ /dev/null @@ -1,95 +0,0 @@ -#pragma once - -#include "Engine.RendererDX12/D3DHelpers.h" - -#include "nvidia-sdk/sl.h" -#include "nvidia-sdk/sl_helpers.h" - -class GDX12Streamline -{ -public: - static GDX12Streamline& Get(); - - bool Initialize(); - void Shutdown(); - - bool IsEnabled() const; - - ComPtr CreateProxyFactory(const ComPtr& nativeFactory) const; - ComPtr CreateProxyDevice(const ComPtr& nativeDevice, bool setAsMainDevice) const; - ComPtr GetNativeCommandQueue(const ComPtr& commandQueue) const; - ComPtr GetNativeSwapChain(const ComPtr& swapChain) const; - ComPtr GetNativeResource(const ComPtr& resource) const; - -private: - GDX12Streamline() = default; - - static void StreamlineLog(sl::LogType type, const char* message); - - std::wstring GetRuntimeDirectory(); - bool LoadInterposer(); - bool LoadFunctions(); - - void Log(const std::string& message) const; - void LogWarning(const std::string& message) const; - void LogFailure(const char* operation, sl::Result result) const; - - 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 _initializationAttempted = false; - 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; -}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h index 96db6da..224af52 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h @@ -36,11 +36,9 @@ class GDX12SwapChain : public IRenderPassLink private: void CreateBuffers(); - IDXGISwapChain4* GetPresentationSwapChain() const; GDX12Device* _device; ComPtr _swapChain; - ComPtr _proxySwapChain; GDX12DescriptorHeap* _rtvHeap; DXGI_FORMAT _format; @@ -54,4 +52,4 @@ class GDX12SwapChain : public IRenderPassLink D3D12_VIEWPORT _screenViewport; D3D12_RECT _screenScissorRect; -}; \ No newline at end of file +}; diff --git a/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp b/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp index 6e52dd1..14f9686 100644 --- a/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp @@ -1,7 +1,6 @@ #include "Engine.RendererDX12/GDX12CommandQueue.h" #include "Engine.RendererDX12/GDX12CommandList.h" -#include "Engine.RendererDX12/GDX12Streamline.h" GDX12CommandQueue::GDX12CommandQueue(GDX12Device* device) : FenceValue(0), _device(device), _lastDispatchedFenceValue(0) @@ -12,15 +11,13 @@ GDX12CommandQueue::GDX12CommandQueue(GDX12Device* device) desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; desc.NodeMask = 0; - ThrowIfFailed(device->GetCommandQueueCreationDevice()->CreateCommandQueue(&desc, IID_PPV_ARGS(&_proxyCommandQueue))); - _commandQueue = GDX12Streamline::Get().GetNativeCommandQueue(_proxyCommandQueue); + ThrowIfFailed(device->GetDevice()->CreateCommandQueue(&desc, IID_PPV_ARGS(&_commandQueue))); 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(); @@ -38,11 +35,6 @@ const ComPtr& GDX12CommandQueue::GetCommandQueue() return _commandQueue; } -const ComPtr& GDX12CommandQueue::GetPresentCommandQueue() -{ - return _proxyCommandQueue ? _proxyCommandQueue : _commandQueue; -} - GDX12CommandList* GDX12CommandQueue::GetCommandList() { GDX12CommandList* rawPtr; diff --git a/Engine/Engine.RendererDX12/src/GDX12Device.cpp b/Engine/Engine.RendererDX12/src/GDX12Device.cpp index 59103d7..faa33f3 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Device.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Device.cpp @@ -1,7 +1,6 @@ #include "Engine.RendererDX12/GDX12Device.h" #include "Engine.RendererDX12/GDX12CommandQueue.h" -#include "Engine.RendererDX12/GDX12Streamline.h" GDX12Device::GDX12Device() : _isInitialized(false), @@ -43,8 +42,6 @@ HRESULT GDX12Device::Initialize(ComPtr adapter) CollectDeviceFeatures(); - _proxyDevice = GDX12Streamline::Get().CreateProxyDevice(_device, Role == DEVICE_ROLE_PRIMARY); - _commandQueue = std::make_unique(this); _isInitialized = true; @@ -71,7 +68,6 @@ void GDX12Device::CollectDeviceFeatures() void GDX12Device::Reset() { - _proxyDevice.Reset(); _device.Reset(); _adapter.Reset(); _commandQueue.reset(); @@ -83,11 +79,6 @@ const ComPtr& GDX12Device::GetDevice() return _device; } -const ComPtr& GDX12Device::GetCommandQueueCreationDevice() -{ - return _proxyDevice ? _proxyDevice : _device; -} - GDX12CommandQueue* GDX12Device::GetCommandQueue() { return _commandQueue.get(); diff --git a/Engine/Engine.RendererDX12/src/GDX12DeviceFactory.cpp b/Engine/Engine.RendererDX12/src/GDX12DeviceFactory.cpp index 9ca00d7..0fdf340 100644 --- a/Engine/Engine.RendererDX12/src/GDX12DeviceFactory.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12DeviceFactory.cpp @@ -2,30 +2,17 @@ #include "Engine.RendererDX12/GDX12Device.h" #include "Engine.RendererDX12/GDX12CommandQueue.h" -#include "Engine.RendererDX12/GDX12Streamline.h" ComPtr GDX12DeviceFactory::_dxgiFactory = nullptr; -ComPtr GDX12DeviceFactory::_dxgiFactoryProxy = nullptr; bool GDX12DeviceFactory::_isInitialized = false; HRESULT GDX12DeviceFactory::Initialize() { - if (_isInitialized) - { - if (!_dxgiFactoryProxy && GDX12Streamline::Get().IsEnabled()) - { - _dxgiFactoryProxy = GDX12Streamline::Get().CreateProxyFactory(_dxgiFactory); - } - return S_OK; - } + if (_isInitialized) { return S_OK; } HRESULT hr = CreateDXGIFactory2(D3D12_DEVICE_FACTORY_FLAG_ALLOW_RETURNING_EXISTING_DEVICE, IID_PPV_ARGS(&_dxgiFactory)); - if (SUCCEEDED(hr)) - { - _dxgiFactoryProxy = GDX12Streamline::Get().CreateProxyFactory(_dxgiFactory); - _isInitialized = true; - } + if (SUCCEEDED(hr)) { _isInitialized = true; } return hr; } @@ -37,7 +24,6 @@ const ComPtr& GDX12DeviceFactory::GetFactory() void GDX12DeviceFactory::Reset() { - _dxgiFactoryProxy.Reset(); _dxgiFactory.Reset(); _isInitialized = false; } @@ -102,10 +88,9 @@ 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(factory->CreateSwapChainForHwnd(device->GetCommandQueue()->GetPresentCommandQueue().Get(), + ThrowIfFailed(_dxgiFactory->CreateSwapChainForHwnd(device->GetCommandQueue()->GetCommandQueue().Get(), hwnd, &desc, nullptr, nullptr, &swapChain1)); ThrowIfFailed(swapChain1.As(&swapChain4)); diff --git a/Engine/Engine.RendererDX12/src/GDX12Streamline.cpp b/Engine/Engine.RendererDX12/src/GDX12Streamline.cpp deleted file mode 100644 index 512f179..0000000 --- a/Engine/Engine.RendererDX12/src/GDX12Streamline.cpp +++ /dev/null @@ -1,244 +0,0 @@ -#include "Engine.RendererDX12/GDX12Streamline.h" - -#include - -#include "nvidia-sdk/sl_security.h" - -namespace -{ - constexpr sl::Feature kRequestedFeatures[] = - { - sl::kFeatureNIS, - sl::kFeatureReflex, - sl::kFeatureDirectSR - }; - - constexpr const char* kLogPrefix = "Streamline: "; -} - -GDX12Streamline& GDX12Streamline::Get() -{ - static GDX12Streamline instance; - return instance; -} - -bool GDX12Streamline::Initialize() -{ - if (_initialized) - { - return true; - } - - if (_initializationAttempted) - { - return false; - } - - _initializationAttempted = true; - _runtimeDirectory = GetRuntimeDirectory(); - - if (_runtimeDirectory.empty()) - { - LogWarning("Failed to resolve executable directory, Streamline is disabled."); - return false; - } - - if (!LoadInterposer() || !LoadFunctions()) - { - Shutdown(); - return false; - } - - const wchar_t* pluginPaths[] = { _runtimeDirectory.c_str() }; - - sl::Preferences preferences{}; - preferences.showConsole = false; - preferences.logLevel = sl::LogLevel::eDefault; - preferences.pathsToPlugins = pluginPaths; - preferences.numPathsToPlugins = static_cast(std::size(pluginPaths)); - preferences.pathToLogsAndData = _runtimeDirectory.c_str(); - preferences.logMessageCallback = &GDX12Streamline::StreamlineLog; - preferences.flags = sl::PreferenceFlags::eDisableCLStateTracking - | sl::PreferenceFlags::eUseManualHooking - | sl::PreferenceFlags::eUseDXGIFactoryProxy; - preferences.featuresToLoad = kRequestedFeatures; - preferences.numFeaturesToLoad = static_cast(std::size(kRequestedFeatures)); - preferences.engine = sl::EngineType::eCustom; - preferences.engineVersion = "PEPEngine2"; - preferences.projectId = "8f52d4be-6cce-4e1a-b95f-31a43fc25369"; - 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 GDX12Streamline::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; - - if (_interposerModule) - { - FreeLibrary(_interposerModule); - _interposerModule = nullptr; - } -} - -bool GDX12Streamline::IsEnabled() const -{ - return _initialized; -} - -ComPtr GDX12Streamline::CreateProxyFactory(const ComPtr& nativeFactory) const -{ - return UpgradeInterface(nativeFactory, "slUpgradeInterface(IDXGIFactory7)"); -} - -ComPtr GDX12Streamline::CreateProxyDevice(const ComPtr& nativeDevice, bool setAsMainDevice) const -{ - if (!_initialized || !nativeDevice) - { - return nativeDevice; - } - - if (setAsMainDevice && !_mainDeviceWasSet) - { - const sl::Result setDeviceResult = _slSetD3DDevice(nativeDevice.Get()); - if (setDeviceResult != sl::Result::eOk) - { - LogFailure("slSetD3DDevice", setDeviceResult); - return nativeDevice; - } - - const_cast(this)->_mainDeviceWasSet = true; - } - - return UpgradeInterface(nativeDevice, "slUpgradeInterface(ID3D12Device14)"); -} - -ComPtr GDX12Streamline::GetNativeCommandQueue(const ComPtr& commandQueue) const -{ - return UnwrapInterface(commandQueue); -} - -ComPtr GDX12Streamline::GetNativeSwapChain(const ComPtr& swapChain) const -{ - return UnwrapInterface(swapChain); -} - -ComPtr GDX12Streamline::GetNativeResource(const ComPtr& resource) const -{ - return UnwrapInterface(resource); -} - -void GDX12Streamline::StreamlineLog(sl::LogType type, const char* message) -{ - const char* level = "INFO"; - if (type == sl::LogType::eWarn) - { - level = "WARN"; - } - else if (type == sl::LogType::eError) - { - level = "ERROR"; - } - - std::string formattedMessage = std::string(kLogPrefix) + '[' + level + "] " + (message ? message : "") + '\n'; - OutputDebugStringA(formattedMessage.c_str()); -} - -std::wstring GDX12Streamline::GetRuntimeDirectory() -{ - wchar_t executablePath[MAX_PATH] = {}; - const DWORD pathLength = GetModuleFileNameW(nullptr, executablePath, MAX_PATH); - if (pathLength == 0 || pathLength == MAX_PATH) - { - return {}; - } - - return std::filesystem::path(std::wstring(executablePath, executablePath + pathLength)).parent_path().wstring(); -} - -bool GDX12Streamline::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 next to the executable, Streamline is disabled."); - return false; - } - - if (!sl::security::verifyEmbeddedSignature(interposerPath.c_str())) - { - LogWarning("sl.interposer.dll signature check failed, continuing because development Streamline DLLs can be unsigned."); - } - - _interposerModule = LoadLibraryW(interposerPath.c_str()); - if (!_interposerModule) - { - LogWarning("LoadLibraryW failed for sl.interposer.dll, Streamline is disabled."); - return false; - } - - return true; -} - -bool GDX12Streamline::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")); - - if (!_slInit || !_slShutdown || !_slUpgradeInterface || !_slGetNativeInterface || !_slSetD3DDevice) - { - LogWarning("Required Streamline exports are missing, Streamline is disabled."); - return false; - } - - return true; -} - -void GDX12Streamline::Log(const std::string& message) const -{ - std::string formattedMessage = std::string(kLogPrefix) + message + '\n'; - OutputDebugStringA(formattedMessage.c_str()); -} - -void GDX12Streamline::LogWarning(const std::string& message) const -{ - std::string formattedMessage = std::string(kLogPrefix) + "WARN: " + message + '\n'; - OutputDebugStringA(formattedMessage.c_str()); -} - -void GDX12Streamline::LogFailure(const char* operation, sl::Result result) const -{ - const char* resultName = sl::getResultAsStr(result); - std::string formattedMessage = std::string(kLogPrefix) + operation + " failed: " + (resultName ? resultName : "Unknown") + '\n'; - OutputDebugStringA(formattedMessage.c_str()); -} \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp index 867bd9d..3e0b27c 100644 --- a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp @@ -4,7 +4,6 @@ #include #include #include -#include GDX12SwapChain::GDX12SwapChain(GDX12Device* device, HWND hwnd, DXGI_FORMAT format, UINT bufferCount, UINT width, UINT height, GDX12DescriptorHeap* rtvHeap) @@ -28,11 +27,9 @@ 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; - _proxySwapChain = GDX12DeviceFactory::CreateSwapChain(_device, swapChainDesc, _hwnd); - _swapChain = GDX12Streamline::Get().GetNativeSwapChain(_proxySwapChain); + _swapChain = GDX12DeviceFactory::CreateSwapChain(_device, swapChainDesc, _hwnd); CreateBuffers(); - _currentBufferIndex = GetPresentationSwapChain()->GetCurrentBackBufferIndex(); _screenViewport.TopLeftX = 0; _screenViewport.TopLeftY = 0; @@ -57,8 +54,7 @@ void GDX12SwapChain::CreateBuffers() for (UINT i = 0; i < _bufferCount; i++) { ComPtr backBuffer; - GetPresentationSwapChain()->GetBuffer(i, IID_PPV_ARGS(&backBuffer)); - backBuffer = GDX12Streamline::Get().GetNativeResource(backBuffer); + _swapChain->GetBuffer(i, IID_PPV_ARGS(&backBuffer)); GDX12TextureDesc textureDesc; textureDesc.RTVHeap = _rtvHeap; @@ -92,14 +88,14 @@ void GDX12SwapChain::Resize(UINT width, UINT height) _buffers.clear(); DXGI_SWAP_CHAIN_DESC desc; - GetPresentationSwapChain()->GetDesc(&desc); + _swapChain->GetDesc(&desc); - GetPresentationSwapChain()->ResizeBuffers( + _swapChain->ResizeBuffers( _bufferCount, _width, _height, desc.BufferDesc.Format, desc.Flags); CreateBuffers(); - _currentBufferIndex = GetPresentationSwapChain()->GetCurrentBackBufferIndex(); + _currentBufferIndex = _swapChain->GetCurrentBackBufferIndex(); _screenViewport.TopLeftX = 0; _screenViewport.TopLeftY = 0; @@ -115,8 +111,8 @@ void GDX12SwapChain::Present() { UINT syncInterval = bVSyncEnabled ? 1 : 0; UINT presentFlags = bVSyncEnabled ? 0 : DXGI_PRESENT_ALLOW_TEARING; - GetPresentationSwapChain()->Present(syncInterval, presentFlags); - _currentBufferIndex = GetPresentationSwapChain()->GetCurrentBackBufferIndex(); + _swapChain->Present(syncInterval, presentFlags); + _currentBufferIndex = (_currentBufferIndex + 1) % _bufferCount; } D3D12_VIEWPORT GDX12SwapChain::GetViewport() @@ -178,12 +174,6 @@ 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/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props b/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props index 6b41c9c..fa1ee3b 100644 --- a/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props +++ b/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props @@ -1,7 +1,6 @@ - From 4f181ba3c172473242bce120e0e1f2f4867cd360 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Sun, 5 Jul 2026 13:03:30 +0300 Subject: [PATCH 32/46] XeSS upscaling preparations --- .../Include/App.Base/Modules/RenderModule.h | 1 + Apps/App.Base/src/RenderModule.cpp | 30 ++-- Apps/App.Base/src/SceneManagerModule.cpp | 16 +- Apps/App.Benchmark/App.Benchmark.vcxproj | 6 +- Apps/App.Editor/App.Editor.vcxproj | 6 +- .../Engine.RendererDX12.vcxproj | 1 + .../Engine.RendererDX12.vcxproj.filters | 3 + .../RenderPasses/GDX12FSRUpscalePass.h | 2 +- .../RenderPasses/GDX12XeSSUpscalePass.h | 165 ++++++++++++++++++ .../Props/PEPEngine.External.NvidiaSDK.props | 3 + 10 files changed, 199 insertions(+), 34 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index 74d7065..d4d44e4 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -15,6 +15,7 @@ #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.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index c60cba0..03c70c4 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -38,7 +38,7 @@ void RenderModule::Initialize() _primaryDevice->Role = DEVICE_ROLE_PRIMARY; _primaryResources.Initialize(_primaryDevice.get()); - if (true) + if (false) { _secondaryDevice = std::make_unique(); _secondaryDevice->Initialize(GDX12DeviceFactory::GetDeviceDescriptors()[1].Adapter.Get()); @@ -780,36 +780,28 @@ void RenderModule::ConfigureRenderPipeline() // 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()); - _secondaryRenderPassExecutionList.push_back(std::make_unique()); - _secondaryRenderPassExecutionList.push_back(std::make_unique()); - _secondaryRenderPassExecutionList.push_back(std::make_unique()); - _secondaryRenderPassExecutionList.push_back(std::make_unique()); - _secondaryRenderPassExecutionList.push_back(std::make_unique()); - SetupRenderPasses(); // Link inputs & outputs for each pass that needs it GDX12RenderPass* clearPass = _primaryRenderPassExecutionList[0].get(); - GDX12RenderPass* copyFromShared = _primaryRenderPassExecutionList[1].get(); - GDX12RenderPass* outputPass = _primaryRenderPassExecutionList[2].get(); - - GDX12RenderPass* cullingPass = _secondaryRenderPassExecutionList[0].get(); - GDX12RenderPass* opaquePass = _secondaryRenderPassExecutionList[1].get(); - GDX12RenderPass* transparencyPass = _secondaryRenderPassExecutionList[2].get(); - GDX12RenderPass* compositionPass = _secondaryRenderPassExecutionList[3].get(); - GDX12RenderPass* copyToShared = _secondaryRenderPassExecutionList[4].get(); + GDX12RenderPass* cullingPass = _primaryRenderPassExecutionList[1].get(); + GDX12RenderPass* opaquePass = _primaryRenderPassExecutionList[2].get(); + GDX12RenderPass* transparencyPass = _primaryRenderPassExecutionList[3].get(); + GDX12RenderPass* compositionPass = _primaryRenderPassExecutionList[4].get(); + GDX12RenderPass* outputPass = _primaryRenderPassExecutionList[5].get(); clearPass->SetInputs({ _backBuffer.get(), _depthStencil.get() }); cullingPass->SetInputs({}); opaquePass->SetInputs({}); transparencyPass->SetInputs({ opaquePass->GetOutputs()[2] }); compositionPass->SetInputs({ opaquePass->GetOutputs()[0], transparencyPass->GetOutputs()[0], transparencyPass->GetOutputs()[1] }); - copyToShared->SetInputs({ compositionPass->GetOutputs()[0] }); - copyFromShared->SetInputs({ copyToShared->GetOutputs()[0] }); - outputPass->SetInputs({ copyFromShared->GetOutputs()[0], _backBuffer.get() }); + outputPass->SetInputs({ compositionPass->GetOutputs()[0], _backBuffer.get() }); InitializeRenderPasses(); } diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index ac114bd..409979e 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - //if (!LoadWorld("world1.yaml")) - //{ - // // todo runtime error or log - //} + if (!LoadWorld("world1.yaml")) + { + // todo runtime error or log + } /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - if (!LoadWorld(scenePath)) - { - // todo runtime error or log - } + //if (!LoadWorld(scenePath)) + //{ + // // todo runtime error or log + //} World* world = GetWorld(0); if (!world) diff --git a/Apps/App.Benchmark/App.Benchmark.vcxproj b/Apps/App.Benchmark/App.Benchmark.vcxproj index 455a8bd..99c62d7 100644 --- a/Apps/App.Benchmark/App.Benchmark.vcxproj +++ b/Apps/App.Benchmark/App.Benchmark.vcxproj @@ -114,7 +114,7 @@ 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;libxess.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;sl.interposer.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\xess\lib\;$(PEPRepoRoot)External\External.Libraries\directstorage\lib\;$(PEPRepoRoot)External\External.Libraries\directxmesh\lib\;$(PEPRepoRoot)External\External.Libraries\wwise\lib\;%(AdditionalLibraryDirectories) @@ -136,7 +136,7 @@ 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\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) + 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;sl.interposer.lib;DirectXMesh.lib;AkSoundEngine.lib;AkMemoryMgr.lib;AkStreamMgr.lib;CommunicationCentral.lib;%(AdditionalDependencies) xcopy /Y /D "$(PEPRepoRoot)External\Runtime\*.dll" "$(TargetDir)" @@ -148,4 +148,4 @@ - \ No newline at end of file + diff --git a/Apps/App.Editor/App.Editor.vcxproj b/Apps/App.Editor/App.Editor.vcxproj index ef02c95..fcae8bb 100644 --- a/Apps/App.Editor/App.Editor.vcxproj +++ b/Apps/App.Editor/App.Editor.vcxproj @@ -115,7 +115,7 @@ 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\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) + 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;sl.interposer.lib;dstorage.lib;DirectXMesh.lib;AkSoundEngine.lib;AkMemoryMgr.lib;AkStreamMgr.lib;CommunicationCentral.lib;%(AdditionalDependencies) xcopy /Y /D "$(PEPRepoRoot)External\Runtime\*.dll" "$(TargetDir)" @@ -135,7 +135,7 @@ 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\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) + 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;sl.interposer.lib;dstorage.lib;DirectXMesh.lib;AkSoundEngine.lib;AkMemoryMgr.lib;AkStreamMgr.lib;CommunicationCentral.lib;%(AdditionalDependencies) xcopy /Y /D "$(PEPRepoRoot)External\Runtime\*.dll" "$(TargetDir)" @@ -147,4 +147,4 @@ - \ No newline at end of file + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index fcd44b5..e02b325 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -52,6 +52,7 @@ + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index fc16d71..45e6d9d 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -114,6 +114,9 @@ Header Files + + Header Files + diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index 053931a..aeac8ec 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -175,7 +175,7 @@ class GDX12FSRUpscalePass : public GDX12RenderPass 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; + 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); 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..bcaf486 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h @@ -0,0 +1,165 @@ +#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) + { _flags = RENDER_PASS_FLAG_UPSCALER; } + + virtual void SetInputs(std::vector inputs) override + { + _inputs = inputs; + _numInputs = 2; + _numOutputs = inputs.size() - 2; + + OUT_UpscaledTextures.clear(); + _outputs.clear(); + OUT_UpscaledTextures.resize(_numOutputs); + _outputs.resize(_numOutputs); + for (int i = 0; i < _numOutputs; i++) + { + OUT_UpscaledTextures[i] = std::make_unique(); + _outputs[i] = OUT_UpscaledTextures[i].get(); + } + } + + // Input 0 - DepthStencil + // Input 1 - MotionVectors + // Input N - Input Texture + // Output N - UpscaledTexture + void Initialize() override + { + 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; + + for (int 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); + } + + } + + // Init with window size + 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); + + for (int i = 0; i < _numOutputs; i++) + { + GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); + GDX12Texture* upscaledTexture = OUT_UpscaledTextures[i].get(); + + } + cmdList->EndPixEvent(); + } + + void Resize() override + { + for (auto& texture : OUT_UpscaledTextures) { texture->Resize(_commonData->WindowWidth, _commonData->WindowHeight); } + } + + void QueryRenderTargetResolution() override + { + xess_2d_t targetResolution = { _commonData->WindowWidth, _commonData->WindowHeight } ; + xess_2d_t downscaledResolution; + xessGetOptimalInputResolution(_XeSSContext, &targetResolution, XeSSQualityMode, &downscaledResolution); + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + + IN_DepthBuffer = nullptr; + IN_MotionVectors = nullptr; + IN_Textures.clear(); + OUT_UpscaledTextures.clear(); + } + + xess_quality_settings_t XeSSQualityMode = XESS_QUALITY_SETTING_QUALITY; + +private: + IRenderPassLink* IN_DepthBuffer; + IRenderPassLink* IN_MotionVectors; + std::vector IN_Textures; + std::vector> OUT_UpscaledTextures; + xess_context_handle_t _XeSSContext; + + 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_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"; + } + } +}; \ No newline at end of file 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) + From f6928b91c15bc5ccf339f49862b1b12983fe7d2c Mon Sep 17 00:00:00 2001 From: DvornikovArtem Date: Sun, 5 Jul 2026 13:15:53 +0300 Subject: [PATCH 33/46] Fix nvidia sdk --- .../Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h | 2 +- MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h index bcaf486..d1aaa6a 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h @@ -95,7 +95,7 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass { xess_2d_t targetResolution = { _commonData->WindowWidth, _commonData->WindowHeight } ; xess_2d_t downscaledResolution; - xessGetOptimalInputResolution(_XeSSContext, &targetResolution, XeSSQualityMode, &downscaledResolution); + //xessGetOptimalInputResolution(_XeSSContext, &targetResolution, XeSSQualityMode, &downscaledResolution); } void ClearDenendencies() override diff --git a/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props b/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props index fa1ee3b..6b41c9c 100644 --- a/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props +++ b/MSBuild/Props/PEPEngine.Module.Engine.RendererDX12.Public.props @@ -1,6 +1,7 @@ + From 90e11dec4ab7bcda3940b768508cceb621eb6e15 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Sun, 5 Jul 2026 14:09:52 +0300 Subject: [PATCH 34/46] XeSS upscaling pass implementation --- Apps/App.Base/src/RenderModule.cpp | 13 ++++- Apps/App.Base/src/SceneManagerModule.cpp | 16 +++---- .../RenderPasses/GDX12FSRUpscalePass.h | 5 +- .../RenderPasses/GDX12XeSSUpscalePass.h | 48 +++++++++++++++++-- 4 files changed, 67 insertions(+), 15 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 03c70c4..9c698e2 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -784,6 +784,7 @@ void RenderModule::ConfigureRenderPipeline() _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(); @@ -794,14 +795,22 @@ void RenderModule::ConfigureRenderPipeline() GDX12RenderPass* opaquePass = _primaryRenderPassExecutionList[2].get(); GDX12RenderPass* transparencyPass = _primaryRenderPassExecutionList[3].get(); GDX12RenderPass* compositionPass = _primaryRenderPassExecutionList[4].get(); - GDX12RenderPass* outputPass = _primaryRenderPassExecutionList[5].get(); + GDX12RenderPass* upscalePass = _primaryRenderPassExecutionList[5].get(); + GDX12RenderPass* outputPass = _primaryRenderPassExecutionList[6].get(); + + _upscaler = upscalePass; clearPass->SetInputs({ _backBuffer.get(), _depthStencil.get() }); cullingPass->SetInputs({}); opaquePass->SetInputs({}); transparencyPass->SetInputs({ opaquePass->GetOutputs()[2] }); compositionPass->SetInputs({ opaquePass->GetOutputs()[0], transparencyPass->GetOutputs()[0], transparencyPass->GetOutputs()[1] }); - outputPass->SetInputs({ compositionPass->GetOutputs()[0], _backBuffer.get() }); + upscalePass->SetInputs({ opaquePass->GetOutputs()[2], opaquePass->GetOutputs()[1], compositionPass->GetOutputs()[0] }); + outputPass->SetInputs({ upscalePass->GetOutputs()[0], _backBuffer.get()}); + + 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); InitializeRenderPasses(); } diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index 409979e..ac114bd 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - if (!LoadWorld("world1.yaml")) - { - // todo runtime error or log - } + //if (!LoadWorld("world1.yaml")) + //{ + // // todo runtime error or log + //} /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - //if (!LoadWorld(scenePath)) - //{ - // // todo runtime error or log - //} + if (!LoadWorld(scenePath)) + { + // todo runtime error or log + } World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index aeac8ec..7412552 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -51,6 +51,7 @@ class GDX12FSRUpscalePass : public GDX12RenderPass TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; + IN_Textures.resize(_numInputs); for (int i = 0; i < _numOutputs; i++) { IN_Textures[i] = _inputs[i + 2]; @@ -86,8 +87,8 @@ class GDX12FSRUpscalePass : public GDX12RenderPass dispatchDesc.renderSize = { _commonData->DownscaledWidth, _commonData->DownscaledHeight }; dispatchDesc.motionVectorScale = { 1.f, 1.f }; dispatchDesc.upscaleSize = { _commonData->WindowWidth, _commonData->WindowHeight }; - dispatchDesc.cameraNear = _commonData->ActiveCameraNearPlane; - dispatchDesc.cameraFar = _commonData->ActiveCameraFarPlane; + dispatchDesc.cameraNear = _commonData->ActiveCameraFarPlane; + dispatchDesc.cameraFar = _commonData->ActiveCameraNearPlane; dispatchDesc.cameraFovAngleVertical = XMConvertToRadians(_commonData->ActiveCameraFOV); dispatchDesc.jitterOffset.x = 0; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h index d1aaa6a..e294864 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h @@ -8,7 +8,7 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass { public: - GDX12XeSSUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr) + GDX12XeSSUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), _XeSSContext(nullptr) { _flags = RENDER_PASS_FLAG_UPSCALER; } virtual void SetInputs(std::vector inputs) override @@ -50,6 +50,7 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; + IN_Textures.resize(_numInputs); for (int i = 0; i < _numOutputs; i++) { IN_Textures[i] = _inputs[i + 2]; @@ -77,11 +78,39 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass 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(); + execParams.jitterOffsetX = 0.f; + execParams.jitterOffsetY = 0.f; + 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(); } @@ -89,19 +118,31 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass 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; - //xessGetOptimalInputResolution(_XeSSContext, &targetResolution, XeSSQualityMode, &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(); @@ -130,6 +171,7 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass initParams.outputResolution.x = _commonData->WindowWidth; initParams.outputResolution.y = _commonData->WindowHeight; initParams.initFlags = XESS_INIT_FLAG_INVERTED_DEPTH; + initParams.qualitySetting = XeSSQualityMode; xess_result_t initResult = xessD3D12Init(_XeSSContext, &initParams); if (initResult != XESS_RESULT_SUCCESS) From ad14a0d7aa8d98b899f04dbe4af68857262c2fef Mon Sep 17 00:00:00 2001 From: AMorunov Date: Sun, 5 Jul 2026 16:05:35 +0300 Subject: [PATCH 35/46] DLSS upscaling preparations --- .../Include/App.Base/Modules/RenderModule.h | 2 +- Apps/App.Base/src/SceneManagerModule.cpp | 16 +- .../Engine.RendererDX12.vcxproj | 1 + .../Engine.RendererDX12.vcxproj.filters | 3 + .../Engine.RendererDX12/GDX12SharedTexture.h | 10 +- .../RenderPasses/GDX12DLSSUpscalePass.h | 246 ++++++++++++++++++ .../RenderPasses/GDX12FSRUpscalePass.h | 2 +- .../RenderPasses/GDX12XeSSUpscalePass.h | 1 - 8 files changed, 264 insertions(+), 17 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index d4d44e4..7106367 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -16,7 +16,7 @@ #include "Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h" #include "Engine.RendererDX12/RenderPasses/GDX12SyncPass.h" #include "Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h" - +#include "Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h" #include "Engine.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index ac114bd..409979e 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - //if (!LoadWorld("world1.yaml")) - //{ - // // todo runtime error or log - //} + if (!LoadWorld("world1.yaml")) + { + // todo runtime error or log + } /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - if (!LoadWorld(scenePath)) - { - // todo runtime error or log - } + //if (!LoadWorld(scenePath)) + //{ + // // todo runtime error or log + //} World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index e02b325..c7bcee1 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -26,6 +26,7 @@ + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index 45e6d9d..9043556 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -117,6 +117,9 @@ Header Files + + Header Files + diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h index 27bfb8b..4f63219 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h @@ -116,8 +116,7 @@ class GDX12SharedTexture : public IRenderPassLink heapDesc.Flags = D3D12_HEAP_FLAG_SHARED | D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER; ThrowIfFailed(_transferFromDeivce->GetDevice()->CreateHeap( - &heapDesc, IID_PPV_ARGS(&_sharedHeap)), - "Failed to create shared heap for cross-adapter texture"); + &heapDesc, IID_PPV_ARGS(&_sharedHeap))); } void CreatePlacedResources() @@ -145,7 +144,7 @@ class GDX12SharedTexture : public IRenderPassLink HANDLE heapHandle = nullptr; ThrowIfFailed(_transferFromDeivce->GetDevice()->CreateSharedHandle( _sharedHeap.Get(), nullptr, GENERIC_ALL, nullptr, - &heapHandle), "Failed to create shared handle for heap"); + &heapHandle)); if (!heapHandle) throw std::runtime_error("Failed to create shared handle (handle is null)"); @@ -155,7 +154,7 @@ class GDX12SharedTexture : public IRenderPassLink IID_PPV_ARGS(&sharedHeapOnSecondary)); CloseHandle(heapHandle); - ThrowIfFailed(hr, "Failed to open shared heap handle on secondary device"); + ThrowIfFailed(hr); D3D12_RESOURCE_DESC desc = {}; desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; @@ -172,7 +171,6 @@ class GDX12SharedTexture : public IRenderPassLink ThrowIfFailed(_transferToDevice->GetDevice()->CreatePlacedResource( sharedHeapOnSecondary.Get(), 0, &desc, D3D12_RESOURCE_STATE_COMMON, - nullptr, IID_PPV_ARGS(&_sharedTextureSecondary.D3DResource)), - "Failed to create placed resource on secondary device"); + nullptr, IID_PPV_ARGS(&_sharedTextureSecondary.D3DResource))); } }; \ 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..c5c5eb3 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h @@ -0,0 +1,246 @@ +#pragma once +#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" +#include "Common/GameTimer.h" + +#include "nvidia-sdk/sl.h" +#include "nvidia-sdk/sl_consts.h" +#include "nvidia-sdk/sl_dlss.h" + +class GDX12DLSSUpscalePass : public GDX12RenderPass +{ +public: + GDX12DLSSUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), _viewportHandle(1337) + { _flags = RENDER_PASS_FLAG_UPSCALER; } + + virtual void SetInputs(std::vector inputs) override + { + _inputs = inputs; + _numInputs = 2; + _numOutputs = inputs.size() - 2; + + OUT_UpscaledTextures.clear(); + _outputs.clear(); + OUT_UpscaledTextures.resize(_numOutputs); + _outputs.resize(_numOutputs); + for (int i = 0; i < _numOutputs; i++) + { + OUT_UpscaledTextures[i] = std::make_unique(); + _outputs[i] = OUT_UpscaledTextures[i].get(); + } + } + + // Input 0 - DepthStencil + // Input 1 - MotionVectors + // Input N - Input Texture + // Output N - UpscaledTexture + void Initialize() override + { + 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(_numInputs); + for (int 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); + + // CREATE CONTEXT HERE + QueryRenderTargetResolution(); + } + + void Execute(GDX12CommandList* cmdList) override + { + GDX12Texture* depthStencil = IN_DepthBuffer->GetTexture(); + GDX12Texture* motionVectors = IN_MotionVectors->GetTexture(); + + cmdList->BeginPixEvent("XeSS Upscale Pass", Colors::Blue); + + for (int i = 0; i < _numOutputs; i++) + { + GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); + GDX12Texture* upscaledTexture = OUT_UpscaledTextures[i].get(); + + } + cmdList->EndPixEvent(); + } + + void Resize() override + { + for (auto& texture : OUT_UpscaledTextures) { texture->Resize(_commonData->WindowWidth, _commonData->WindowHeight); } + // DESTROY AND BUILD CONTEXT HERE + } + + void QueryRenderTargetResolution() override + { + _commonData->DownscaledWidth = 0; + _commonData->DownscaledHeight = 0; + } + + void ClearDenendencies() override + { + GDX12RenderPass::ClearDenendencies(); + // DESTROY CONTEXT HERE + IN_DepthBuffer = nullptr; + IN_MotionVectors = nullptr; + IN_Textures.clear(); + OUT_UpscaledTextures.clear(); + } + + sl::DLSSMode DLSSQualityMode; + +private: + IRenderPassLink* IN_DepthBuffer; + IRenderPassLink* IN_MotionVectors; + std::vector IN_Textures; + std::vector> OUT_UpscaledTextures; + sl::ViewportHandle _viewportHandle; + + void InitSreamline() + { + using namespace sl; + // Init streamline + Preferences preferences{}; + preferences.showConsole = false; + preferences.logLevel = LogLevel::eVerbose; + preferences.engine = EngineType::eCustom; + preferences.renderAPI = RenderAPI::eD3D12; + Feature myFeatures[] = { kFeatureDLSS }; + preferences.featuresToLoad = myFeatures; + preferences.numFeaturesToLoad = _countof(myFeatures); + + preferences.logMessageCallback = [](LogType type, const char* msg) + { + std::string prefix; + switch (type) { + case LogType::eError: prefix = "SL ERROR: "; break; + case LogType::eWarn: prefix = "SL WARNING: "; break; + default: prefix = "SL INFO: "; break; + } + OutputDebugStringA((prefix + msg + "\n").c_str()); + }; + + Result result = slInit(preferences, sl::kSDKVersion); + if (result != sl::Result::eOk) + { + std::string msg = "ERROR: Streamline initialization failed: " + SLResultToString(result) + "\n"; + OutputDebugStringA(msg.c_str()); + } + + // Check DLSS support on device + AdapterInfo adapterInfo = {}; + _resources->Device->GetDevice()->GetAdapterLuid(); + LUID luid = _resources->Device->GetDevice()->GetAdapterLuid(); + adapterInfo.deviceLUID = (uint8_t*)&luid; + adapterInfo.deviceLUIDSizeInBytes = sizeof(LUID); + + result = slIsFeatureSupported(kFeatureDLSS, adapterInfo); + if (result != Result::eOk) + { + std::string errorMsg = "ERROR: DLSS is not supported: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + } + + // Set Device + result = slSetD3DDevice(_resources->Device->GetDevice().Get()); + if (result != Result::eOk) + { + std::string errorMsg = "ERROR: Failed to set D3D12 device: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + } + + // 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 = slDLSSSetOptions(_viewportHandle, dlssOptions); + if (result != Result::eOk) + { + std::string errorMsg = "ERROR: Failed to set DLSS options: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + return; + } + + result = slAllocateResources(nullptr, kFeatureDLSS, _viewportHandle); + if (result != Result::eOk) + { + std::string errorMsg = "ERROR: Failed to allocate DLSS resources: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + return; + } + } + + std::string SLResultToString(sl::Result result) + { + switch (result) + { + case sl::Result::eOk: return "OK"; + case sl::Result::eErrorIO: return "ERROR_IO"; + case sl::Result::eErrorDriverOutOfDate: return "ERROR_DRIVER_OUT_OF_DATE"; + case sl::Result::eErrorOSOutOfDate: return "ERROR_OS_OUT_OF_DATE"; + case sl::Result::eErrorOSDisabledHWS: return "ERROR_OS_DISABLED_HWS"; + case sl::Result::eErrorDeviceNotCreated: return "ERROR_DEVICE_NOT_CREATED"; + case sl::Result::eErrorNoSupportedAdapterFound: return "ERROR_NO_SUPPORTED_ADAPTER_FOUND"; + case sl::Result::eErrorAdapterNotSupported: return "ERROR_ADAPTER_NOT_SUPPORTED"; + case sl::Result::eErrorNoPlugins: return "ERROR_NO_PLUGINS"; + case sl::Result::eErrorVulkanAPI: return "ERROR_VULKAN_API"; + case sl::Result::eErrorDXGIAPI: return "ERROR_DXGI_API"; + case sl::Result::eErrorD3DAPI: return "ERROR_D3D_API"; + case sl::Result::eErrorNRDAPI: return "ERROR_NRD_API"; + case sl::Result::eErrorNVAPI: return "ERROR_NV_API"; + case sl::Result::eErrorReflexAPI: return "ERROR_REFLEX_API"; + case sl::Result::eErrorNGXFailed: return "ERROR_NGX_FAILED"; + case sl::Result::eErrorJSONParsing: return "ERROR_JSON_PARSING"; + case sl::Result::eErrorMissingProxy: return "ERROR_MISSING_PROXY"; + case sl::Result::eErrorMissingResourceState: return "ERROR_MISSING_RESOURCE_STATE"; + case sl::Result::eErrorInvalidIntegration: return "ERROR_INVALID_INTEGRATION"; + case sl::Result::eErrorMissingInputParameter: return "ERROR_MISSING_INPUT_PARAMETER"; + case sl::Result::eErrorNotInitialized: return "ERROR_NOT_INITIALIZED"; + case sl::Result::eErrorComputeFailed: return "ERROR_COMPUTE_FAILED"; + case sl::Result::eErrorInitNotCalled: return "ERROR_INIT_NOT_CALLED"; + case sl::Result::eErrorExceptionHandler: return "ERROR_EXCEPTION_HANDLER"; + case sl::Result::eErrorInvalidParameter: return "ERROR_INVALID_PARAMETER"; + case sl::Result::eErrorMissingConstants: return "ERROR_MISSING_CONSTANTS"; + case sl::Result::eErrorDuplicatedConstants: return "ERROR_DUPLICATED_CONSTANTS"; + case sl::Result::eErrorMissingOrInvalidAPI: return "ERROR_MISSING_OR_INVALID_API"; + case sl::Result::eErrorCommonConstantsMissing: return "ERROR_COMMON_CONSTANTS_MISSING"; + case sl::Result::eErrorUnsupportedInterface: return "ERROR_UNSUPPORTED_INTERFACE"; + case sl::Result::eErrorFeatureMissing: return "ERROR_FEATURE_MISSING"; + case sl::Result::eErrorFeatureNotSupported: return "ERROR_FEATURE_NOT_SUPPORTED"; + case sl::Result::eErrorFeatureMissingHooks: return "ERROR_FEATURE_MISSING_HOOKS"; + case sl::Result::eErrorFeatureFailedToLoad: return "ERROR_FEATURE_FAILED_TO_LOAD"; + case sl::Result::eErrorFeatureWrongPriority: return "ERROR_FEATURE_WRONG_PRIORITY"; + case sl::Result::eErrorFeatureMissingDependency: return "ERROR_FEATURE_MISSING_DEPENDENCY"; + case sl::Result::eErrorFeatureManagerInvalidState: return "ERROR_FEATURE_MANAGER_INVALID_STATE"; + case sl::Result::eErrorInvalidState: return "ERROR_INVALID_STATE"; + case sl::Result::eWarnOutOfVRAM: return "WARN_OUT_OF_VRAM"; + default: return "UNKNOWN_RESULT"; + } + } +}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index 7412552..e2d5257 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -63,7 +63,6 @@ class GDX12FSRUpscalePass : public GDX12RenderPass } - // Init with window size void Setup(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) override { GDX12RenderPass::Setup(initOnResources, otherResources, commonData); @@ -87,6 +86,7 @@ class GDX12FSRUpscalePass : public GDX12RenderPass dispatchDesc.renderSize = { _commonData->DownscaledWidth, _commonData->DownscaledHeight }; dispatchDesc.motionVectorScale = { 1.f, 1.f }; 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); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h index e294864..b215df6 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h @@ -62,7 +62,6 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass } - // Init with window size void Setup(GDX12DeviceResources* initOnResources, GDX12DeviceResources* otherResources, RenderPipelineCommonData* commonData) override { GDX12RenderPass::Setup(initOnResources, otherResources, commonData); From b155bde50337efb0964a7597796cc6947d734aab Mon Sep 17 00:00:00 2001 From: AMorunov Date: Sun, 5 Jul 2026 18:40:03 +0300 Subject: [PATCH 36/46] Active camera jittering implementation --- .../App.Base/ECS/Components/CameraComponent.h | 4 +- .../Include/App.Base/Modules/RenderModule.h | 4 +- .../App.Base/Systems/GPUDataUpdateSystem.h | 59 ++++++- Apps/App.Base/src/RenderModule.cpp | 11 +- Apps/App.Base/src/SceneManagerModule.cpp | 16 +- .../GDX12ConstantStructures.h | 3 +- .../RenderPasses/GDX12DLSSUpscalePass.h | 160 ++++++++++++++++-- .../RenderPasses/GDX12FSRUpscalePass.h | 16 +- .../RenderPasses/GDX12RenderPass.h | 40 +++-- .../RenderPasses/GDX12XeSSUpscalePass.h | 18 +- .../Shaders/CBufferStructures.hlsl | 3 +- .../Shaders/OpaquePass.hlsl | 10 +- 12 files changed, 271 insertions(+), 73 deletions(-) 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 a49b45f..3f43fa1 100644 --- a/Apps/App.Base/Include/App.Base/ECS/Components/CameraComponent.h +++ b/Apps/App.Base/Include/App.Base/ECS/Components/CameraComponent.h @@ -10,13 +10,13 @@ struct CameraComponent : ComponentTag float NearPlane; float FarPlane; XMFLOAT4X4 ViewProj; - XMFLOAT4X4 PrevViewProj; + XMFLOAT4X4 PrevViewProjNoJitter; bool DirtyFlag; CameraComponent() : DirtyFlag(true), _numFramesDirty(0), _CBufferIndex(0), - FOV(60.0f), NearPlane(0.1f), FarPlane(10000.f), ViewProj(Identity4x4()), PrevViewProj(Identity4x4()) + 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 7106367..4e3e0ee 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -111,6 +111,7 @@ class RenderModule final : public Module uint32_t GetPrimaryPipelineFlags(); uint32_t GetSecondaryPipelineFlags(); + RenderPipelineCommonData* GetRenderPipelineCommonData(); protected: void OnUpdate() override; @@ -154,9 +155,6 @@ class RenderModule final : public Module // These two resources are made on _primaryDevice only std::unique_ptr _backBuffer; std::unique_ptr _depthStencil; - - // To be able to know where to get render target resolution when resizing - GDX12RenderPass* _upscaler; // Sorted in execution order std::vector> _primaryRenderPassExecutionList; diff --git a/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h b/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h index fda2b8c..1021aaf 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,22 +56,50 @@ 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; + 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->GetPrimaryPipelineFlags() & RENDER_PASS_FLAG_USE_JITTER) || + (renderModule->GetSecondaryPipelineFlags() & 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; - GDX12CameraConstants objConstants; XMStoreFloat4x4(&objConstants.ViewProj, XMMatrixTranspose(view * proj)); XMStoreFloat4x4(&objConstants.View, XMMatrixTranspose(view)); objConstants.CameraLocation = transform.Location; objConstants.NearPlane = camera.NearPlane; objConstants.FarPlane = camera.FarPlane; - objConstants.PrevViewProj = camera.PrevViewProj; - XMStoreFloat4x4(&camera.PrevViewProj, XMMatrixTranspose(view * proj)); if (renderModule->GetPrimaryPipelineFlags() & RENDER_PASS_FLAG_USE_CAMERAS) { @@ -227,4 +262,20 @@ class GPUDataUpdateSystem final : public System }); } + +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/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 9c698e2..1799fd6 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -8,7 +8,7 @@ RenderModule::RenderModule(Window* window, GameTimer* timer) : _dualGPUMode(false), _window(window), _timer(timer), - _primaryPipelineFlags(0), _secondaryPipelineFlags(0), _upscaler(nullptr) + _primaryPipelineFlags(0), _secondaryPipelineFlags(0) { _RPcommonData.GameTimer = _timer; } @@ -71,7 +71,7 @@ void RenderModule::OnResize() _RPcommonData.WindowWidth = width; _RPcommonData.WindowHeight = height; - if (_upscaler) { _upscaler->QueryRenderTargetResolution(); } + if (_RPcommonData.Upscaler) { _RPcommonData.Upscaler->QueryRenderTargetResolution(); } for (auto& renderPass : _primaryRenderPassExecutionList) { renderPass->Resize(); } for (auto& renderPass : _secondaryRenderPassExecutionList) { renderPass->Resize(); } @@ -480,6 +480,11 @@ uint32_t RenderModule::GetSecondaryPipelineFlags() return _secondaryPipelineFlags; } +RenderPipelineCommonData* RenderModule::GetRenderPipelineCommonData() +{ + return &_RPcommonData; +} + void RenderModule::OnTransformComponentCreated(World& world, Entity entity, TransformComponent& component) { TransformCompGPUData gpuData; @@ -798,8 +803,6 @@ void RenderModule::ConfigureRenderPipeline() GDX12RenderPass* upscalePass = _primaryRenderPassExecutionList[5].get(); GDX12RenderPass* outputPass = _primaryRenderPassExecutionList[6].get(); - _upscaler = upscalePass; - clearPass->SetInputs({ _backBuffer.get(), _depthStencil.get() }); cullingPass->SetInputs({}); opaquePass->SetInputs({}); diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index 409979e..ac114bd 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - if (!LoadWorld("world1.yaml")) - { - // todo runtime error or log - } + //if (!LoadWorld("world1.yaml")) + //{ + // // todo runtime error or log + //} /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - //if (!LoadWorld(scenePath)) - //{ - // // todo runtime error or log - //} + if (!LoadWorld(scenePath)) + { + // todo runtime error or log + } World* world = GetWorld(0); if (!world) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12ConstantStructures.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12ConstantStructures.h index 450ef71..b0c8e95 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12ConstantStructures.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12ConstantStructures.h @@ -34,8 +34,9 @@ struct GDX12MaterialConstants struct GDX12CameraConstants { XMFLOAT4X4 ViewProj = Identity4x4(); + XMFLOAT4X4 ViewProjNoJitter = Identity4x4(); XMFLOAT4X4 View = Identity4x4(); - XMFLOAT4X4 PrevViewProj = 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/RenderPasses/GDX12DLSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h index c5c5eb3..2f78161 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h @@ -2,15 +2,27 @@ #include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" #include "Common/GameTimer.h" +// HOLY SHIT +// we need this cray 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 class GDX12DLSSUpscalePass : public GDX12RenderPass { public: - GDX12DLSSUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), _viewportHandle(1337) - { _flags = RENDER_PASS_FLAG_UPSCALER; } + GDX12DLSSUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), _viewportHandle(1337), + _DLSSQualityMode(sl::DLSSMode::eMaxQuality) + { _flags = RENDER_PASS_FLAG_UPSCALER | RENDER_PASS_FLAG_USE_JITTER; } virtual void SetInputs(std::vector inputs) override { @@ -35,6 +47,8 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass // Output N - UpscaledTexture void Initialize() override { + _commonData->Upscaler = this; + IN_DepthBuffer = _inputs[0]; IN_MotionVectors = _inputs[1]; @@ -67,22 +81,79 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass { GDX12RenderPass::Setup(initOnResources, otherResources, commonData); - // CREATE CONTEXT HERE + InitSreamline(); + CreateDLSSFeature(); QueryRenderTargetResolution(); } void Execute(GDX12CommandList* cmdList) override { + using namespace sl; + + cmdList->BeginPixEvent("DLSS Upscale Pass", Colors::Blue); + + FrameToken* currentFrame = nullptr; + Result result = slGetNewFrameToken(currentFrame); + SetFrameConstants(currentFrame); + GDX12Texture* depthStencil = IN_DepthBuffer->GetTexture(); GDX12Texture* motionVectors = IN_MotionVectors->GetTexture(); - cmdList->BeginPixEvent("XeSS Upscale Pass", Colors::Blue); + cmdList->ResourceBarrier({ depthStencil->GetResource()->GetDepthReadBarrier(), + motionVectors->GetResource()->GetPixelShaderResourceBarrier() }); + + Resource depthResource = Resource{ ResourceType::eTex2d, + depthStencil->GetResource()->D3DResource.Get(), + nullptr, nullptr, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_DEPTH_READ }; + + Resource mvecResource = Resource{ ResourceType::eTex2d, + motionVectors->GetResource()->D3DResource.Get(), + nullptr, nullptr, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE }; + + Extent fullExtent{}; + fullExtent.top = 0; + fullExtent.left = 0; + fullExtent.width = _commonData->DownscaledWidth; + fullExtent.height = _commonData->DownscaledHeight; + + ResourceTag depthTag{ &depthResource, kBufferTypeDepth, ResourceLifecycle::eValidUntilPresent, &fullExtent }; + ResourceTag mvecTag{ &mvecResource, kBufferTypeMotionVectors, ResourceLifecycle::eValidUntilPresent, &fullExtent }; for (int i = 0; i < _numOutputs; i++) { GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); GDX12Texture* upscaledTexture = OUT_UpscaledTextures[i].get(); + cmdList->ResourceBarrier({ inputTexture->GetResource()->GetPixelShaderResourceBarrier(), + upscaledTexture->GetResource()->GetUnorderedAccessBarrier() }); + + Resource inputResource = Resource{ ResourceType::eTex2d, + inputTexture->GetResource()->D3DResource.Get(), + nullptr, nullptr, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE }; + + Resource outputResource = Resource{ ResourceType::eTex2d, + upscaledTexture->GetResource()->D3DResource.Get(), + nullptr, nullptr, D3D12_RESOURCE_STATE_UNORDERED_ACCESS }; + + ResourceTag inputTag{ &inputResource, kBufferTypeScalingInputColor, ResourceLifecycle::eValidUntilPresent, nullptr }; + ResourceTag outputTag{ &outputResource, kBufferTypeScalingOutputColor, ResourceLifecycle::eValidUntilPresent, nullptr }; + + ResourceTag tags[] = { depthTag, mvecTag, inputTag, outputTag }; + result = slSetTagForFrame(*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 = slEvaluateFeature(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(); } @@ -90,33 +161,49 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass void Resize() override { for (auto& texture : OUT_UpscaledTextures) { texture->Resize(_commonData->WindowWidth, _commonData->WindowHeight); } - // DESTROY AND BUILD CONTEXT HERE + slFreeResources(sl::kFeatureDLSS, _viewportHandle); + slDLSSSetOptions(_viewportHandle, sl::DLSSOptions{}); + CreateDLSSFeature(); } void QueryRenderTargetResolution() override { - _commonData->DownscaledWidth = 0; - _commonData->DownscaledHeight = 0; + using namespace sl; + + DLSSOptions dlssOptions = {}; + dlssOptions.mode = _DLSSQualityMode; + dlssOptions.outputWidth = _commonData->WindowWidth; + dlssOptions.outputHeight = _commonData->WindowHeight; + + DLSSOptimalSettings optimalSettings = {}; + Result result = slDLSSGetOptimalSettings(dlssOptions, optimalSettings); + if (result != Result::eOk) + { + std::string errorMsg = "DLSS: Failed to get optimal settings: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + } + + _commonData->DownscaledWidth = optimalSettings.optimalRenderWidth; + _commonData->DownscaledHeight = optimalSettings.optimalRenderHeight; } void ClearDenendencies() override { GDX12RenderPass::ClearDenendencies(); - // DESTROY CONTEXT HERE + slFreeResources(sl::kFeatureDLSS, _viewportHandle); IN_DepthBuffer = nullptr; IN_MotionVectors = nullptr; IN_Textures.clear(); OUT_UpscaledTextures.clear(); } - sl::DLSSMode DLSSQualityMode; - private: IRenderPassLink* IN_DepthBuffer; IRenderPassLink* IN_MotionVectors; std::vector IN_Textures; std::vector> OUT_UpscaledTextures; sl::ViewportHandle _viewportHandle; + sl::DLSSMode _DLSSQualityMode; void InitSreamline() { @@ -130,6 +217,7 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass Feature myFeatures[] = { kFeatureDLSS }; preferences.featuresToLoad = myFeatures; preferences.numFeaturesToLoad = _countof(myFeatures); + preferences.flags = PreferenceFlags::eUseFrameBasedResourceTagging; preferences.logMessageCallback = [](LogType type, const char* msg) { @@ -149,6 +237,14 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass OutputDebugStringA(msg.c_str()); } + // Set Device + result = slSetD3DDevice(_resources->Device->GetDevice().Get()); + if (result != Result::eOk) + { + std::string errorMsg = "ERROR: Failed to set D3D12 device: " + SLResultToString(result) + "\n"; + OutputDebugStringA(errorMsg.c_str()); + } + // Check DLSS support on device AdapterInfo adapterInfo = {}; _resources->Device->GetDevice()->GetAdapterLuid(); @@ -162,24 +258,56 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass std::string errorMsg = "ERROR: DLSS is not supported: " + SLResultToString(result) + "\n"; OutputDebugStringA(errorMsg.c_str()); } + } - // Set Device - result = slSetD3DDevice(_resources->Device->GetDevice().Get()); + void SetFrameConstants(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::eFalse; + constants.motionVectors3D = Boolean::eFalse; + constants.reset = Boolean::eFalse; + constants.orthographicProjection = Boolean::eFalse; + constants.motionVectorsDilated = Boolean::eFalse; + constants.motionVectorsJittered = Boolean::eFalse; + + Result result = slSetConstants(constants, *currentFrameToken, _viewportHandle); if (result != Result::eOk) { - std::string errorMsg = "ERROR: Failed to set D3D12 device: " + SLResultToString(result) + "\n"; + 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.mode = _DLSSQualityMode; dlssOptions.outputWidth = _commonData->WindowWidth; dlssOptions.outputHeight = _commonData->WindowHeight; dlssOptions.sharpness = 0.25f; dlssOptions.colorBuffersHDR = Boolean::eFalse; - result = slDLSSSetOptions(_viewportHandle, dlssOptions); + Result result = slDLSSSetOptions(_viewportHandle, dlssOptions); if (result != Result::eOk) { std::string errorMsg = "ERROR: Failed to set DLSS options: " + SLResultToString(result) + "\n"; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index e2d5257..4aa4778 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -9,8 +9,9 @@ class GDX12FSRUpscalePass : public GDX12RenderPass { public: - GDX12FSRUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), _FFXContext(nullptr) - { _flags = RENDER_PASS_FLAG_UPSCALER; } + 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 { @@ -35,6 +36,8 @@ class GDX12FSRUpscalePass : public GDX12RenderPass // Output N - UpscaledTexture void Initialize() override { + _commonData->Upscaler = this; + IN_DepthBuffer = _inputs[0]; IN_MotionVectors = _inputs[1]; @@ -91,8 +94,8 @@ class GDX12FSRUpscalePass : public GDX12RenderPass dispatchDesc.cameraFar = _commonData->ActiveCameraNearPlane; dispatchDesc.cameraFovAngleVertical = XMConvertToRadians(_commonData->ActiveCameraFOV); - dispatchDesc.jitterOffset.x = 0; - dispatchDesc.jitterOffset.y = 0; + dispatchDesc.jitterOffset.x = _commonData->ActiveCameraJitterOffsetX; + dispatchDesc.jitterOffset.y = _commonData->ActiveCameraJitterOffsetY; dispatchDesc.enableSharpening = false; dispatchDesc.sharpness = 0.8f; @@ -139,14 +142,12 @@ class GDX12FSRUpscalePass : public GDX12RenderPass queryDesc.header.type = FFX_API_QUERY_DESC_TYPE_UPSCALE_GETRENDERRESOLUTIONFROMQUALITYMODE; queryDesc.displayHeight = _commonData->WindowHeight; queryDesc.displayWidth = _commonData->WindowWidth; - queryDesc.qualityMode = FSRQualityMode; + queryDesc.qualityMode = _FSRQualityMode; queryDesc.pOutRenderHeight = &_commonData->DownscaledHeight; queryDesc.pOutRenderWidth = &_commonData->DownscaledWidth; ffxQuery(&_FFXContext, &queryDesc.header); } - FfxApiUpscaleQualityMode FSRQualityMode = FFX_UPSCALE_QUALITY_MODE_QUALITY; - void ClearDenendencies() override { GDX12RenderPass::ClearDenendencies(); @@ -164,6 +165,7 @@ class GDX12FSRUpscalePass : public GDX12RenderPass std::vector IN_Textures; std::vector> OUT_UpscaledTextures; ffxContext _FFXContext; + FfxApiUpscaleQualityMode _FSRQualityMode; void BuildFSRContext() { diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h index bd67b8e..fc6b993 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -13,20 +13,6 @@ class GameTimer; -class RenderPipelineCommonData -{ -public: - UINT ActiveCameraCBufferIndex = -1; - float ActiveCameraFOV = 0; - float ActiveCameraNearPlane = 0; - float ActiveCameraFarPlane = 0; - GameTimer* GameTimer = nullptr; - UINT WindowWidth = 0; - UINT WindowHeight = 0; - UINT DownscaledWidth = 0; - UINT DownscaledHeight = 0; -}; - enum ERenderPassFlags : uint32_t { RENDER_PASS_FLAG_NONE = 0, @@ -37,9 +23,12 @@ enum ERenderPassFlags : uint32_t 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_SYNC_DEVICES = 1 << 7, + RENDER_PASS_FLAG_USE_JITTER = 1 << 8 }; +class RenderPipelineCommonData; + class GDX12RenderPass { public: @@ -110,4 +99,25 @@ class GDX12RenderPass 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; }; \ 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 index b215df6..ffe0775 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h @@ -8,8 +8,9 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass { public: - GDX12XeSSUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), _XeSSContext(nullptr) - { _flags = RENDER_PASS_FLAG_UPSCALER; } + GDX12XeSSUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), _XeSSContext(nullptr), + _XeSSQualityMode(XESS_QUALITY_SETTING_QUALITY) + { _flags = RENDER_PASS_FLAG_UPSCALER | RENDER_PASS_FLAG_USE_JITTER; } virtual void SetInputs(std::vector inputs) override { @@ -34,6 +35,8 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass // Output N - UpscaledTexture void Initialize() override { + _commonData->Upscaler = this; + IN_DepthBuffer = _inputs[0]; IN_MotionVectors = _inputs[1]; @@ -83,8 +86,8 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass xess_d3d12_execute_params_t execParams = {}; execParams.pDepthTexture = depthStencil->GetResource()->D3DResource.Get(); execParams.pVelocityTexture = motionVectors->GetResource()->D3DResource.Get(); - execParams.jitterOffsetX = 0.f; - execParams.jitterOffsetY = 0.f; + execParams.jitterOffsetX = _commonData->ActiveCameraJitterOffsetX; + execParams.jitterOffsetY = _commonData->ActiveCameraJitterOffsetY; execParams.inputWidth = _commonData->DownscaledWidth; execParams.inputHeight = _commonData->DownscaledHeight; execParams.resetHistory = false; @@ -128,7 +131,7 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass xess_2d_t minResolution; xess_2d_t maxResolution; xess_result_t queryResolutionResult = xessGetOptimalInputResolution(_XeSSContext, - &targetResolution, XeSSQualityMode, &downscaledResolution, &minResolution, &maxResolution); + &targetResolution, _XeSSQualityMode, &downscaledResolution, &minResolution, &maxResolution); if (queryResolutionResult != XESS_RESULT_SUCCESS) { std::string msg = "ERROR: XeSS query resolution failed: " + XeSSResultToString(queryResolutionResult) + "\n"; @@ -148,14 +151,13 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass OUT_UpscaledTextures.clear(); } - xess_quality_settings_t XeSSQualityMode = XESS_QUALITY_SETTING_QUALITY; - 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 BuildXeSSContext() { @@ -170,7 +172,7 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass initParams.outputResolution.x = _commonData->WindowWidth; initParams.outputResolution.y = _commonData->WindowHeight; initParams.initFlags = XESS_INIT_FLAG_INVERTED_DEPTH; - initParams.qualitySetting = XeSSQualityMode; + initParams.qualitySetting = _XeSSQualityMode; xess_result_t initResult = xessD3D12Init(_XeSSContext, &initParams); if (initResult != XESS_RESULT_SUCCESS) diff --git a/Engine/Engine.RendererDX12/Shaders/CBufferStructures.hlsl b/Engine/Engine.RendererDX12/Shaders/CBufferStructures.hlsl index a34f311..61bafd6 100644 --- a/Engine/Engine.RendererDX12/Shaders/CBufferStructures.hlsl +++ b/Engine/Engine.RendererDX12/Shaders/CBufferStructures.hlsl @@ -35,8 +35,9 @@ struct Material struct CameraCB { float4x4 ViewProj; + float4x4 ViewProjNoJitter; float4x4 View; - float4x4 PrevViewProj; + float4x4 PrevViewProjNoJitter; float3 CameraLocation; float NearPlane; float FarPlane; diff --git a/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl b/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl index 7b4afe7..e86e83e 100644 --- a/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl +++ b/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl @@ -27,8 +27,9 @@ struct VS_INPUT struct VS_OUTPUT_PS_INPUT { float4 PosCS : SV_POSITION; - float4 PrevPosCS : TEXCOORD2; + float4 PrevPosCSNoJitter : TEXCOORD2; float3 PosW : POSITION; + float4 PosCSNoJitter : POSITION2; float2 TexC : TEXCOORD; float3 Normal : NORMAL; float3 Tangent : TANGENT; @@ -50,8 +51,9 @@ VS_OUTPUT_PS_INPUT VS(VS_INPUT vin) vout.Tangent = normalize(mul(vin.Tangent, (float3x3) transform.World)); vout.PosCS = mul(posW, CBCamera.ViewProj); + vout.PosCSNoJitter = mul(posW, CBCamera.ViewProjNoJitter); float4 prevPosW = mul(float4(vin.Pos, 1.0f), transform.PrevWorld); - vout.PrevPosCS = mul(prevPosW, CBCamera.PrevViewProj); + vout.PrevPosCSNoJitter = mul(prevPosW, CBCamera.PrevViewProjNoJitter); vout.TexC = vin.TexC; vout.MaterialIndex = instance.MaterialIndex; @@ -72,8 +74,8 @@ PS_OUTPUT PS(VS_OUTPUT_PS_INPUT pin) Material material = MaterialCache[pin.MaterialIndex]; float4 color = Texture2DCache[material.DiffuseIndex].Sample(samAnisotropicWrap, pin.TexC); - float2 currentNDC = pin.PosCS.xy / pin.PosCS.w; - float2 prevNDC = pin.PrevPosCS.xy / pin.PrevPosCS.w; + float2 currentNDC = pin.PosCSNoJitter.xy / pin.PosCSNoJitter.w; + float2 prevNDC = pin.PrevPosCSNoJitter.xy / pin.PrevPosCSNoJitter.w; float2 velocity = currentNDC - prevNDC; output.Color = float4(color.rgb, 1.0f); From ecf424dffdaca43b30b23b634803cee01711b9d3 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Mon, 6 Jul 2026 11:00:23 +0300 Subject: [PATCH 37/46] FSR & XeSS-SR quality improvements --- Apps/App.Base/src/RenderModule.cpp | 2 +- .../RenderPasses/GDX12FSRUpscalePass.h | 10 +++++----- .../RenderPasses/GDX12XeSSUpscalePass.h | 11 +++++++---- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 1799fd6..7a3d9b5 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -789,7 +789,7 @@ void RenderModule::ConfigureRenderPipeline() _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(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index 4aa4778..ea604b6 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -94,11 +94,11 @@ class GDX12FSRUpscalePass : public GDX12RenderPass dispatchDesc.cameraFar = _commonData->ActiveCameraNearPlane; dispatchDesc.cameraFovAngleVertical = XMConvertToRadians(_commonData->ActiveCameraFOV); - dispatchDesc.jitterOffset.x = _commonData->ActiveCameraJitterOffsetX; - dispatchDesc.jitterOffset.y = _commonData->ActiveCameraJitterOffsetY; + dispatchDesc.jitterOffset.x = -_commonData->ActiveCameraJitterOffsetX; + dispatchDesc.jitterOffset.y = -_commonData->ActiveCameraJitterOffsetY; - dispatchDesc.enableSharpening = false; - dispatchDesc.sharpness = 0.8f; + dispatchDesc.enableSharpening = true; + dispatchDesc.sharpness = 1.f; // for whatever reason, it doesnt like it when frame time is lower than 1.f float clampedTime = max(_commonData->GameTimer->DeltaTime() * 1000.f, 1.f); dispatchDesc.frameTimeDelta = clampedTime; //expects milliseconds @@ -111,7 +111,7 @@ class GDX12FSRUpscalePass : public GDX12RenderPass 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(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h index ffe0775..f144c96 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h @@ -9,7 +9,7 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass { public: GDX12XeSSUpscalePass() : IN_DepthBuffer(nullptr), IN_MotionVectors(nullptr), _XeSSContext(nullptr), - _XeSSQualityMode(XESS_QUALITY_SETTING_QUALITY) + _XeSSQualityMode(XESS_QUALITY_SETTING_ULTRA_QUALITY_PLUS) { _flags = RENDER_PASS_FLAG_UPSCALER | RENDER_PASS_FLAG_USE_JITTER; } virtual void SetInputs(std::vector inputs) override @@ -86,8 +86,9 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass xess_d3d12_execute_params_t execParams = {}; execParams.pDepthTexture = depthStencil->GetResource()->D3DResource.Get(); execParams.pVelocityTexture = motionVectors->GetResource()->D3DResource.Get(); - execParams.jitterOffsetX = _commonData->ActiveCameraJitterOffsetX; - execParams.jitterOffsetY = _commonData->ActiveCameraJitterOffsetY; + // 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; @@ -95,6 +96,7 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass execParams.exposureScale = 1; execParams.inputColorBase = { 0,0 }; execParams.inputDepthBase = { 0,0 }; + for (int i = 0; i < _numOutputs; i++) { @@ -171,7 +173,8 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass xess_d3d12_init_params_t initParams = {}; initParams.outputResolution.x = _commonData->WindowWidth; initParams.outputResolution.y = _commonData->WindowHeight; - initParams.initFlags = XESS_INIT_FLAG_INVERTED_DEPTH; + 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); From d1de5596e2a853da36e7717cc287a77c50d57a05 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Mon, 6 Jul 2026 19:19:50 +0300 Subject: [PATCH 38/46] Streamline SDK integration & DLSS upscaling --- Apps/App.Base/src/RenderModule.cpp | 10 +- Apps/App.Base/src/SceneManagerModule.cpp | 16 +- Apps/App.Benchmark/App.Benchmark.vcxproj | 12 +- Apps/App.Editor/App.Editor.vcxproj | 12 +- .../Engine.RendererDX12.vcxproj | 2 + .../Engine.RendererDX12.vcxproj.filters | 6 + .../Engine.RendererDX12/GDX12CommandQueue.h | 4 +- .../Include/Engine.RendererDX12/GDX12Device.h | 4 +- .../Engine.RendererDX12/GDX12DeviceFactory.h | 3 +- .../Engine.RendererDX12/GDX12StreamlineSDK.h | 128 +++++++ .../Engine.RendererDX12/GDX12SwapChain.h | 2 + .../RenderPasses/GDX12DLSSUpscalePass.h | 173 +++------- .../src/GDX12CommandQueue.cpp | 10 +- .../Engine.RendererDX12/src/GDX12Device.cpp | 11 +- .../src/GDX12DeviceFactory.cpp | 25 +- .../src/GDX12StreamlineSDK.cpp | 320 ++++++++++++++++++ .../src/GDX12SwapChain.cpp | 25 +- External/Runtime/nvngx_dlss.dll | 3 + External/Runtime/sl.common.dll | 4 +- External/Runtime/sl.directsr.dll | 4 +- External/Runtime/sl.dlss.dll | 4 +- External/Runtime/sl.interposer.dll | 4 +- External/Runtime/sl.nis.dll | 4 +- External/Runtime/sl.reflex.dll | 4 +- 24 files changed, 616 insertions(+), 174 deletions(-) create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12StreamlineSDK.h create mode 100644 Engine/Engine.RendererDX12/src/GDX12StreamlineSDK.cpp create mode 100644 External/Runtime/nvngx_dlss.dll diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 7a3d9b5..6b72fd1 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -5,6 +5,7 @@ #include "App.Base/Modules/SceneManagerModule.h" #include "Common/ConsoleVariables.h" +#include "Engine.RendererDX12/GDX12StreamlineSDK.h" RenderModule::RenderModule(Window* window, GameTimer* timer) : _dualGPUMode(false), _window(window), _timer(timer), @@ -21,11 +22,14 @@ RenderModule::~RenderModule() for (auto& renderpass : _primaryRenderPassExecutionList) { renderpass->ClearDenendencies(); } for (auto& renderpass : _secondaryRenderPassExecutionList) { renderpass->ClearDenendencies(); } + GDX12StreamlineSDK::Get().Shutdown(); GDX12ShaderCompiler::Shutdown(); } void RenderModule::Initialize() { + GDX12StreamlineSDK::Get().Initialize(); + #if defined(DEBUG) || defined(_DEBUG) // Enable the D3D12 debug layer. ComPtr debugController; @@ -34,15 +38,15 @@ void RenderModule::Initialize() #endif _primaryDevice = std::make_unique(); - _primaryDevice->Initialize(GDX12DeviceFactory::GetMostPerformantAdapter().Get()); _primaryDevice->Role = DEVICE_ROLE_PRIMARY; + _primaryDevice->Initialize(GDX12DeviceFactory::GetMostPerformantAdapter().Get()); _primaryResources.Initialize(_primaryDevice.get()); if (false) { _secondaryDevice = std::make_unique(); - _secondaryDevice->Initialize(GDX12DeviceFactory::GetDeviceDescriptors()[1].Adapter.Get()); _secondaryDevice->Role = DEVICE_ROLE_SECONDARY; + _secondaryDevice->Initialize(GDX12DeviceFactory::GetDeviceDescriptors()[1].Adapter.Get()); _secondaryResources.Initialize(_secondaryDevice.get()); _dualGPUMode = true; } @@ -789,7 +793,7 @@ void RenderModule::ConfigureRenderPipeline() _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(); diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index ac114bd..409979e 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - //if (!LoadWorld("world1.yaml")) - //{ - // // todo runtime error or log - //} + if (!LoadWorld("world1.yaml")) + { + // todo runtime error or log + } /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - if (!LoadWorld(scenePath)) - { - // todo runtime error or log - } + //if (!LoadWorld(scenePath)) + //{ + // // todo runtime error or log + //} World* world = GetWorld(0); if (!world) diff --git a/Apps/App.Benchmark/App.Benchmark.vcxproj b/Apps/App.Benchmark/App.Benchmark.vcxproj index 99c62d7..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;libxess.lib;sl.interposer.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\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)" @@ -136,10 +138,12 @@ 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\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;sl.interposer.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-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)" diff --git a/Apps/App.Editor/App.Editor.vcxproj b/Apps/App.Editor/App.Editor.vcxproj index fcae8bb..19dfbde 100644 --- a/Apps/App.Editor/App.Editor.vcxproj +++ b/Apps/App.Editor/App.Editor.vcxproj @@ -115,10 +115,12 @@ 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\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;sl.interposer.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) - 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,10 +137,12 @@ 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\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;sl.interposer.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-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)" diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index c7bcee1..4632daa 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -25,6 +25,7 @@ + @@ -61,6 +62,7 @@ + diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index 9043556..2eff34d 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -102,6 +102,9 @@ Header Files + + Header Files + Header Files @@ -155,6 +158,9 @@ Source Files + + Source Files + Source Files diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h index b89e3ef..2382fdb 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12CommandQueue.h @@ -14,6 +14,7 @@ class GDX12CommandQueue void Reset(); const ComPtr& GetCommandQueue(); + const ComPtr& GetPresentCommandQueue(); const ComPtr& GetFence(); ComPtr& GetOtherFence(); @@ -38,6 +39,7 @@ class GDX12CommandQueue void ClearCompletedLists(); ComPtr _commandQueue; + ComPtr _proxyCommandQueue; ComPtr _fence; //shared fence from another device //null if _dualGPUMode is false @@ -53,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/GDX12Device.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h index 949ed50..5a010a9 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h @@ -31,6 +31,7 @@ class GDX12Device : public std::enable_shared_from_this void Reset(); const ComPtr& GetDevice(); + const ComPtr& GetCommandQueueCreationDevice(); GDX12CommandQueue* GetCommandQueue(); const DeviceSpecs& GetDeviceFeatures(); const bool IsInitialized(); @@ -41,6 +42,7 @@ class GDX12Device : public std::enable_shared_from_this ComPtr _adapter; ComPtr _device; + ComPtr _proxyDevice; std::unique_ptr _commandQueue; @@ -51,4 +53,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/GDX12StreamlineSDK.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12StreamlineSDK.h new file mode 100644 index 0000000..a20ca25 --- /dev/null +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12StreamlineSDK.h @@ -0,0 +1,128 @@ +#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 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_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 224af52..13e7460 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SwapChain.h @@ -36,8 +36,10 @@ class GDX12SwapChain : public IRenderPassLink private: void CreateBuffers(); + IDXGISwapChain4* GetPresentationSwapChain() const; GDX12Device* _device; + ComPtr _proxySwapChain; ComPtr _swapChain; GDX12DescriptorHeap* _rtvHeap; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h index 2f78161..4be61c5 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h @@ -3,7 +3,7 @@ #include "Common/GameTimer.h" // HOLY SHIT -// we need this cray include since SL's free() function conflits with CRT library's free() function +// 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 @@ -16,6 +16,7 @@ #pragma pop_macro("free") #undef PEP_RESTORE_FREE_MACRO_DLSS_PASS #endif +#include "Engine.RendererDX12/GDX12StreamlineSDK.h" class GDX12DLSSUpscalePass : public GDX12RenderPass { @@ -81,9 +82,8 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass { GDX12RenderPass::Setup(initOnResources, otherResources, commonData); - InitSreamline(); - CreateDLSSFeature(); QueryRenderTargetResolution(); + CreateDLSSFeature(); } void Execute(GDX12CommandList* cmdList) override @@ -93,8 +93,16 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass cmdList->BeginPixEvent("DLSS Upscale Pass", Colors::Blue); FrameToken* currentFrame = nullptr; - Result result = slGetNewFrameToken(currentFrame); - SetFrameConstants(currentFrame); + 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(); @@ -116,8 +124,14 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass fullExtent.width = _commonData->DownscaledWidth; fullExtent.height = _commonData->DownscaledHeight; - ResourceTag depthTag{ &depthResource, kBufferTypeDepth, ResourceLifecycle::eValidUntilPresent, &fullExtent }; - ResourceTag mvecTag{ &mvecResource, kBufferTypeMotionVectors, ResourceLifecycle::eValidUntilPresent, &fullExtent }; + 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++) { @@ -135,11 +149,11 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass upscaledTexture->GetResource()->D3DResource.Get(), nullptr, nullptr, D3D12_RESOURCE_STATE_UNORDERED_ACCESS }; - ResourceTag inputTag{ &inputResource, kBufferTypeScalingInputColor, ResourceLifecycle::eValidUntilPresent, nullptr }; - ResourceTag outputTag{ &outputResource, kBufferTypeScalingOutputColor, ResourceLifecycle::eValidUntilPresent, nullptr }; + ResourceTag inputTag{ &inputResource, kBufferTypeScalingInputColor, ResourceLifecycle::eValidUntilEvaluate, &fullExtent }; + ResourceTag outputTag{ &outputResource, kBufferTypeScalingOutputColor, ResourceLifecycle::eValidUntilEvaluate, &outputExtent }; ResourceTag tags[] = { depthTag, mvecTag, inputTag, outputTag }; - result = slSetTagForFrame(*currentFrame, _viewportHandle, tags, _countof(tags), cmdList->GetCommandList().Get()); + 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"; @@ -147,7 +161,7 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass } const BaseStructure* inputs[] = { &_viewportHandle }; - result = slEvaluateFeature(kFeatureDLSS, *currentFrame, inputs, _countof(inputs), cmdList->GetCommandList().Get()); + 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"; @@ -161,8 +175,8 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass void Resize() override { for (auto& texture : OUT_UpscaledTextures) { texture->Resize(_commonData->WindowWidth, _commonData->WindowHeight); } - slFreeResources(sl::kFeatureDLSS, _viewportHandle); - slDLSSSetOptions(_viewportHandle, sl::DLSSOptions{}); + GDX12StreamlineSDK::Get().FreeResources(sl::kFeatureDLSS, _viewportHandle); + GDX12StreamlineSDK::Get().DLSSSetOptions(_viewportHandle, sl::DLSSOptions{}); CreateDLSSFeature(); } @@ -176,11 +190,22 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass dlssOptions.outputHeight = _commonData->WindowHeight; DLSSOptimalSettings optimalSettings = {}; - Result result = slDLSSGetOptimalSettings(dlssOptions, 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; @@ -190,7 +215,7 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass void ClearDenendencies() override { GDX12RenderPass::ClearDenendencies(); - slFreeResources(sl::kFeatureDLSS, _viewportHandle); + GDX12StreamlineSDK::Get().FreeResources(sl::kFeatureDLSS, _viewportHandle); IN_DepthBuffer = nullptr; IN_MotionVectors = nullptr; IN_Textures.clear(); @@ -205,62 +230,7 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass sl::ViewportHandle _viewportHandle; sl::DLSSMode _DLSSQualityMode; - void InitSreamline() - { - using namespace sl; - // Init streamline - Preferences preferences{}; - preferences.showConsole = false; - preferences.logLevel = LogLevel::eVerbose; - preferences.engine = EngineType::eCustom; - preferences.renderAPI = RenderAPI::eD3D12; - Feature myFeatures[] = { kFeatureDLSS }; - preferences.featuresToLoad = myFeatures; - preferences.numFeaturesToLoad = _countof(myFeatures); - preferences.flags = PreferenceFlags::eUseFrameBasedResourceTagging; - - preferences.logMessageCallback = [](LogType type, const char* msg) - { - std::string prefix; - switch (type) { - case LogType::eError: prefix = "SL ERROR: "; break; - case LogType::eWarn: prefix = "SL WARNING: "; break; - default: prefix = "SL INFO: "; break; - } - OutputDebugStringA((prefix + msg + "\n").c_str()); - }; - - Result result = slInit(preferences, sl::kSDKVersion); - if (result != sl::Result::eOk) - { - std::string msg = "ERROR: Streamline initialization failed: " + SLResultToString(result) + "\n"; - OutputDebugStringA(msg.c_str()); - } - - // Set Device - result = slSetD3DDevice(_resources->Device->GetDevice().Get()); - if (result != Result::eOk) - { - std::string errorMsg = "ERROR: Failed to set D3D12 device: " + SLResultToString(result) + "\n"; - OutputDebugStringA(errorMsg.c_str()); - } - - // Check DLSS support on device - AdapterInfo adapterInfo = {}; - _resources->Device->GetDevice()->GetAdapterLuid(); - LUID luid = _resources->Device->GetDevice()->GetAdapterLuid(); - adapterInfo.deviceLUID = (uint8_t*)&luid; - adapterInfo.deviceLUIDSizeInBytes = sizeof(LUID); - - result = slIsFeatureSupported(kFeatureDLSS, adapterInfo); - if (result != Result::eOk) - { - std::string errorMsg = "ERROR: DLSS is not supported: " + SLResultToString(result) + "\n"; - OutputDebugStringA(errorMsg.c_str()); - } - } - - void SetFrameConstants(sl::FrameToken* currentFrameToken) + void SetConstants(sl::FrameToken* currentFrameToken) { using namespace sl; @@ -277,7 +247,7 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass constants.cameraFOV = XMConvertToRadians(_commonData->ActiveCameraFOV); constants.cameraAspectRatio = static_cast(_commonData->WindowWidth) / _commonData->WindowHeight; - constants.jitterOffset = { _commonData->ActiveCameraJitterOffsetX, _commonData->ActiveCameraJitterOffsetY }; + constants.jitterOffset = { -_commonData->ActiveCameraJitterOffsetX, -_commonData->ActiveCameraJitterOffsetY }; constants.mvecScale = { 1.f, 1.f }; constants.depthInverted = Boolean::eTrue; @@ -288,7 +258,7 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass constants.motionVectorsDilated = Boolean::eFalse; constants.motionVectorsJittered = Boolean::eFalse; - Result result = slSetConstants(constants, *currentFrameToken, _viewportHandle); + Result result = GDX12StreamlineSDK::Get().SetConstants(constants, *currentFrameToken, _viewportHandle); if (result != Result::eOk) { std::string errorMsg = "DLSS: Failed to set constants: " + SLResultToString(result) + "\n"; @@ -299,6 +269,7 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass void CreateDLSSFeature() { using namespace sl; + // Create DLSS feature DLSSOptions dlssOptions = {}; dlssOptions.mode = _DLSSQualityMode; @@ -307,7 +278,7 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass dlssOptions.sharpness = 0.25f; dlssOptions.colorBuffersHDR = Boolean::eFalse; - Result result = slDLSSSetOptions(_viewportHandle, dlssOptions); + Result result = GDX12StreamlineSDK::Get().DLSSSetOptions(_viewportHandle, dlssOptions); if (result != Result::eOk) { std::string errorMsg = "ERROR: Failed to set DLSS options: " + SLResultToString(result) + "\n"; @@ -315,60 +286,10 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass return; } - result = slAllocateResources(nullptr, kFeatureDLSS, _viewportHandle); - if (result != Result::eOk) - { - std::string errorMsg = "ERROR: Failed to allocate DLSS resources: " + SLResultToString(result) + "\n"; - OutputDebugStringA(errorMsg.c_str()); - return; - } } std::string SLResultToString(sl::Result result) { - switch (result) - { - case sl::Result::eOk: return "OK"; - case sl::Result::eErrorIO: return "ERROR_IO"; - case sl::Result::eErrorDriverOutOfDate: return "ERROR_DRIVER_OUT_OF_DATE"; - case sl::Result::eErrorOSOutOfDate: return "ERROR_OS_OUT_OF_DATE"; - case sl::Result::eErrorOSDisabledHWS: return "ERROR_OS_DISABLED_HWS"; - case sl::Result::eErrorDeviceNotCreated: return "ERROR_DEVICE_NOT_CREATED"; - case sl::Result::eErrorNoSupportedAdapterFound: return "ERROR_NO_SUPPORTED_ADAPTER_FOUND"; - case sl::Result::eErrorAdapterNotSupported: return "ERROR_ADAPTER_NOT_SUPPORTED"; - case sl::Result::eErrorNoPlugins: return "ERROR_NO_PLUGINS"; - case sl::Result::eErrorVulkanAPI: return "ERROR_VULKAN_API"; - case sl::Result::eErrorDXGIAPI: return "ERROR_DXGI_API"; - case sl::Result::eErrorD3DAPI: return "ERROR_D3D_API"; - case sl::Result::eErrorNRDAPI: return "ERROR_NRD_API"; - case sl::Result::eErrorNVAPI: return "ERROR_NV_API"; - case sl::Result::eErrorReflexAPI: return "ERROR_REFLEX_API"; - case sl::Result::eErrorNGXFailed: return "ERROR_NGX_FAILED"; - case sl::Result::eErrorJSONParsing: return "ERROR_JSON_PARSING"; - case sl::Result::eErrorMissingProxy: return "ERROR_MISSING_PROXY"; - case sl::Result::eErrorMissingResourceState: return "ERROR_MISSING_RESOURCE_STATE"; - case sl::Result::eErrorInvalidIntegration: return "ERROR_INVALID_INTEGRATION"; - case sl::Result::eErrorMissingInputParameter: return "ERROR_MISSING_INPUT_PARAMETER"; - case sl::Result::eErrorNotInitialized: return "ERROR_NOT_INITIALIZED"; - case sl::Result::eErrorComputeFailed: return "ERROR_COMPUTE_FAILED"; - case sl::Result::eErrorInitNotCalled: return "ERROR_INIT_NOT_CALLED"; - case sl::Result::eErrorExceptionHandler: return "ERROR_EXCEPTION_HANDLER"; - case sl::Result::eErrorInvalidParameter: return "ERROR_INVALID_PARAMETER"; - case sl::Result::eErrorMissingConstants: return "ERROR_MISSING_CONSTANTS"; - case sl::Result::eErrorDuplicatedConstants: return "ERROR_DUPLICATED_CONSTANTS"; - case sl::Result::eErrorMissingOrInvalidAPI: return "ERROR_MISSING_OR_INVALID_API"; - case sl::Result::eErrorCommonConstantsMissing: return "ERROR_COMMON_CONSTANTS_MISSING"; - case sl::Result::eErrorUnsupportedInterface: return "ERROR_UNSUPPORTED_INTERFACE"; - case sl::Result::eErrorFeatureMissing: return "ERROR_FEATURE_MISSING"; - case sl::Result::eErrorFeatureNotSupported: return "ERROR_FEATURE_NOT_SUPPORTED"; - case sl::Result::eErrorFeatureMissingHooks: return "ERROR_FEATURE_MISSING_HOOKS"; - case sl::Result::eErrorFeatureFailedToLoad: return "ERROR_FEATURE_FAILED_TO_LOAD"; - case sl::Result::eErrorFeatureWrongPriority: return "ERROR_FEATURE_WRONG_PRIORITY"; - case sl::Result::eErrorFeatureMissingDependency: return "ERROR_FEATURE_MISSING_DEPENDENCY"; - case sl::Result::eErrorFeatureManagerInvalidState: return "ERROR_FEATURE_MANAGER_INVALID_STATE"; - case sl::Result::eErrorInvalidState: return "ERROR_INVALID_STATE"; - case sl::Result::eWarnOutOfVRAM: return "WARN_OUT_OF_VRAM"; - default: return "UNKNOWN_RESULT"; - } + return GDX12StreamlineSDK::ResultToString(result); } -}; \ No newline at end of file +}; diff --git a/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp b/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp index 14f9686..ca7aaea 100644 --- a/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12CommandQueue.cpp @@ -1,6 +1,7 @@ #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) @@ -11,13 +12,15 @@ 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->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(); @@ -35,6 +38,11 @@ const ComPtr& GDX12CommandQueue::GetCommandQueue() return _commandQueue; } +const ComPtr& GDX12CommandQueue::GetPresentCommandQueue() +{ + return _proxyCommandQueue ? _proxyCommandQueue : _commandQueue; +} + GDX12CommandList* GDX12CommandQueue::GetCommandList() { GDX12CommandList* rawPtr; diff --git a/Engine/Engine.RendererDX12/src/GDX12Device.cpp b/Engine/Engine.RendererDX12/src/GDX12Device.cpp index faa33f3..62586ca 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Device.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Device.cpp @@ -1,6 +1,7 @@ #include "Engine.RendererDX12/GDX12Device.h" #include "Engine.RendererDX12/GDX12CommandQueue.h" +#include "Engine.RendererDX12/GDX12StreamlineSDK.h" GDX12Device::GDX12Device() : _isInitialized(false), @@ -40,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); @@ -68,6 +71,7 @@ void GDX12Device::CollectDeviceFeatures() void GDX12Device::Reset() { + _proxyDevice.Reset(); _device.Reset(); _adapter.Reset(); _commandQueue.reset(); @@ -79,6 +83,11 @@ const ComPtr& GDX12Device::GetDevice() return _device; } +const ComPtr& GDX12Device::GetCommandQueueCreationDevice() +{ + return _proxyDevice ? _proxyDevice : _device; +} + GDX12CommandQueue* GDX12Device::GetCommandQueue() { return _commandQueue.get(); @@ -92,4 +101,4 @@ const DeviceSpecs& GDX12Device::GetDeviceFeatures() 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/GDX12StreamlineSDK.cpp b/Engine/Engine.RendererDX12/src/GDX12StreamlineSDK.cpp new file mode 100644 index 0000000..56667dd --- /dev/null +++ b/Engine/Engine.RendererDX12/src/GDX12StreamlineSDK.cpp @@ -0,0 +1,320 @@ +#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; + _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::GetNewFrameToken(sl::FrameToken*& token, const uint32_t* frameIndex) const +{ + if (!_initialized || !_slGetNewFrameToken) + { + return sl::Result::eErrorInvalidState; + } + + 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 +{ + if (!_initialized || !_slSetTagForFrame) + { + return sl::Result::eErrorInvalidState; + } + + 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 +{ + if (!_initialized || !_slEvaluateFeature) + { + return sl::Result::eErrorInvalidState; + } + + return _slEvaluateFeature(feature, frame, inputs, numInputs, cmdBuffer); +} + +sl::Result GDX12StreamlineSDK::FreeResources(sl::Feature feature, const sl::ViewportHandle& viewport) const +{ + if (!_initialized || !_slFreeResources) + { + return sl::Result::eErrorInvalidState; + } + + return _slFreeResources(feature, viewport); +} + +sl::Result GDX12StreamlineSDK::SetConstants(const sl::Constants& values, const sl::FrameToken& frame, const sl::ViewportHandle& viewport) const +{ + if (!_initialized || !_slSetConstants) + { + return sl::Result::eErrorInvalidState; + } + + 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")); + _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 + || !_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 3e0b27c..7fb2ef9 100644 --- a/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12SwapChain.cpp @@ -4,6 +4,7 @@ #include #include #include +#include GDX12SwapChain::GDX12SwapChain(GDX12Device* device, HWND hwnd, DXGI_FORMAT format, UINT bufferCount, UINT width, UINT height, GDX12DescriptorHeap* rtvHeap) @@ -27,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; @@ -54,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; @@ -88,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; @@ -111,8 +114,8 @@ void GDX12SwapChain::Present() { UINT syncInterval = bVSyncEnabled ? 1 : 0; UINT presentFlags = bVSyncEnabled ? 0 : DXGI_PRESENT_ALLOW_TEARING; - _swapChain->Present(syncInterval, presentFlags); - _currentBufferIndex = (_currentBufferIndex + 1) % _bufferCount; + GetPresentationSwapChain()->Present(syncInterval, presentFlags); + _currentBufferIndex = GetPresentationSwapChain()->GetCurrentBackBufferIndex(); } D3D12_VIEWPORT GDX12SwapChain::GetViewport() @@ -174,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/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 From 596950ccf7c0348d72b0e050f69d606b8a0d3d87 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Mon, 6 Jul 2026 19:44:47 +0300 Subject: [PATCH 39/46] Bug fixes --- Apps/App.Base/src/App.cpp | 5 ++- Apps/App.Base/src/RenderModule.cpp | 3 +- .../Include/Engine.RendererDX12/GDX12Device.h | 1 + .../Engine.RendererDX12/GDX12StreamlineSDK.h | 2 + .../RenderPasses/GDX12DLSSUpscalePass.h | 32 +++++++++++----- .../Engine.RendererDX12/src/GDX12Device.cpp | 13 ++++++- .../src/GDX12StreamlineSDK.cpp | 37 +++++-------------- 7 files changed, 51 insertions(+), 42 deletions(-) diff --git a/Apps/App.Base/src/App.cpp b/Apps/App.Base/src/App.cpp index a1579ed..d5333ad 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; @@ -64,7 +66,8 @@ App::~App() { //ordering is important Locator.UnregisterModule(); - Locator.UnregisterModule(); + Locator.UnregisterModule(); + GDX12StreamlineSDK::Get().Shutdown(); } HINSTANCE App::GetAppHandler() const diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 6b72fd1..30c6317 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -5,7 +5,6 @@ #include "App.Base/Modules/SceneManagerModule.h" #include "Common/ConsoleVariables.h" -#include "Engine.RendererDX12/GDX12StreamlineSDK.h" RenderModule::RenderModule(Window* window, GameTimer* timer) : _dualGPUMode(false), _window(window), _timer(timer), @@ -22,8 +21,8 @@ RenderModule::~RenderModule() for (auto& renderpass : _primaryRenderPassExecutionList) { renderpass->ClearDenendencies(); } for (auto& renderpass : _secondaryRenderPassExecutionList) { renderpass->ClearDenendencies(); } - GDX12StreamlineSDK::Get().Shutdown(); GDX12ShaderCompiler::Shutdown(); + GDX12DeviceFactory::Reset(); } void RenderModule::Initialize() diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h index 5a010a9..f739965 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Device.h @@ -34,6 +34,7 @@ class GDX12Device : public std::enable_shared_from_this const ComPtr& GetCommandQueueCreationDevice(); GDX12CommandQueue* GetCommandQueue(); const DeviceSpecs& GetDeviceFeatures(); + LUID GetAdapterLuid() const; const bool IsInitialized(); EDeviceRole Role; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12StreamlineSDK.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12StreamlineSDK.h index a20ca25..3201c02 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12StreamlineSDK.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12StreamlineSDK.h @@ -37,6 +37,7 @@ class GDX12StreamlineSDK 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; @@ -117,6 +118,7 @@ class GDX12StreamlineSDK 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; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h index 4be61c5..d9fc927 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h @@ -82,6 +82,7 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass { GDX12RenderPass::Setup(initOnResources, otherResources, commonData); + CheckDLSSSupport(); QueryRenderTargetResolution(); CreateDLSSFeature(); } @@ -107,16 +108,13 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass GDX12Texture* depthStencil = IN_DepthBuffer->GetTexture(); GDX12Texture* motionVectors = IN_MotionVectors->GetTexture(); - cmdList->ResourceBarrier({ depthStencil->GetResource()->GetDepthReadBarrier(), - motionVectors->GetResource()->GetPixelShaderResourceBarrier() }); - Resource depthResource = Resource{ ResourceType::eTex2d, depthStencil->GetResource()->D3DResource.Get(), - nullptr, nullptr, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_DEPTH_READ }; + nullptr, nullptr, static_cast(depthStencil->GetResource()->GetCurrentState()) }; Resource mvecResource = Resource{ ResourceType::eTex2d, motionVectors->GetResource()->D3DResource.Get(), - nullptr, nullptr, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE }; + nullptr, nullptr, static_cast(motionVectors->GetResource()->GetCurrentState()) }; Extent fullExtent{}; fullExtent.top = 0; @@ -138,16 +136,13 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); GDX12Texture* upscaledTexture = OUT_UpscaledTextures[i].get(); - cmdList->ResourceBarrier({ inputTexture->GetResource()->GetPixelShaderResourceBarrier(), - upscaledTexture->GetResource()->GetUnorderedAccessBarrier() }); - Resource inputResource = Resource{ ResourceType::eTex2d, inputTexture->GetResource()->D3DResource.Get(), - nullptr, nullptr, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE }; + nullptr, nullptr, static_cast(inputTexture->GetResource()->GetCurrentState()) }; Resource outputResource = Resource{ ResourceType::eTex2d, upscaledTexture->GetResource()->D3DResource.Get(), - nullptr, nullptr, D3D12_RESOURCE_STATE_UNORDERED_ACCESS }; + nullptr, nullptr, static_cast(upscaledTexture->GetResource()->GetCurrentState()) }; ResourceTag inputTag{ &inputResource, kBufferTypeScalingInputColor, ResourceLifecycle::eValidUntilEvaluate, &fullExtent }; ResourceTag outputTag{ &outputResource, kBufferTypeScalingOutputColor, ResourceLifecycle::eValidUntilEvaluate, &outputExtent }; @@ -230,6 +225,23 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass sl::ViewportHandle _viewportHandle; sl::DLSSMode _DLSSQualityMode; + 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; diff --git a/Engine/Engine.RendererDX12/src/GDX12Device.cpp b/Engine/Engine.RendererDX12/src/GDX12Device.cpp index 62586ca..d71d293 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Device.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Device.cpp @@ -71,10 +71,10 @@ void GDX12Device::CollectDeviceFeatures() void GDX12Device::Reset() { + _commandQueue.reset(); _proxyDevice.Reset(); _device.Reset(); _adapter.Reset(); - _commandQueue.reset(); _isInitialized = false; } @@ -98,6 +98,17 @@ 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; diff --git a/Engine/Engine.RendererDX12/src/GDX12StreamlineSDK.cpp b/Engine/Engine.RendererDX12/src/GDX12StreamlineSDK.cpp index 56667dd..2276e1d 100644 --- a/Engine/Engine.RendererDX12/src/GDX12StreamlineSDK.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12StreamlineSDK.cpp @@ -78,6 +78,7 @@ void GDX12StreamlineSDK::Shutdown() _slUpgradeInterface = nullptr; _slGetNativeInterface = nullptr; _slSetD3DDevice = nullptr; + _slIsFeatureSupported = nullptr; _slGetFeatureFunction = nullptr; _slEvaluateFeature = nullptr; _slFreeResources = nullptr; @@ -109,9 +110,7 @@ ComPtr GDX12StreamlineSDK::CreateProxyFactory(const ComPtr resolvedNativeFactory = UnwrapInterface(nativeFactory); if (resolvedNativeFactory && resolvedNativeFactory.Get() != nativeFactory.Get()) - { - return nativeFactory; - } + { return nativeFactory; } return UpgradeInterface(nativeFactory, "slUpgradeInterface(IDXGIFactory7)"); } @@ -172,53 +171,33 @@ ComPtr GDX12StreamlineSDK::GetNativeResource(const ComPtr(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")); @@ -287,6 +267,7 @@ void GDX12StreamlineSDK::LoadFunctions() _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."); } From 6b2f41221eedbb992f9e1e9c7d289915619bf060 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Mon, 6 Jul 2026 21:29:01 +0300 Subject: [PATCH 40/46] QoL fixes --- Apps/App.Base/src/App.cpp | 2 ++ Apps/App.Base/src/RenderModule.cpp | 11 +++-------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Apps/App.Base/src/App.cpp b/Apps/App.Base/src/App.cpp index d5333ad..dd382b4 100644 --- a/Apps/App.Base/src/App.cpp +++ b/Apps/App.Base/src/App.cpp @@ -67,6 +67,8 @@ 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(); } diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 30c6317..0c7e394 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -27,6 +27,7 @@ RenderModule::~RenderModule() void RenderModule::Initialize() { + // Streamline is initialized on the primary device only GDX12StreamlineSDK::Get().Initialize(); #if defined(DEBUG) || defined(_DEBUG) @@ -700,10 +701,7 @@ void RenderModule::OnRender() primarycmdQueue->WaitForOtherFence(primarycmdList->FenceValue); primarycmdList = primarycmdQueue->GetCommandList(); } - else - { - renderPass->Execute(primarycmdList); - } + else { renderPass->Execute(primarycmdList); } } primarycmdQueue->ExecuteCommandList(primarycmdList); primaryCurrentFrameConsts->FenceValue = primarycmdList->FenceValue; @@ -721,10 +719,7 @@ void RenderModule::OnRender() secondarycmdQueue->WaitForOtherFence(secondarycmdList->FenceValue); secondarycmdList = secondarycmdQueue->GetCommandList(); } - else - { - renderPass->Execute(secondarycmdList); - } + else { renderPass->Execute(secondarycmdList); } } secondarycmdQueue->ExecuteCommandList(secondarycmdList); secondaryCurrentFrameConsts->FenceValue = secondarycmdList->FenceValue; From 9dff79c19a70f47d115c553ce17f42c039d785ae Mon Sep 17 00:00:00 2001 From: AMorunov Date: Mon, 6 Jul 2026 21:34:27 +0300 Subject: [PATCH 41/46] added back scene loading --- Apps/App.Base/src/SceneManagerModule.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Apps/App.Base/src/SceneManagerModule.cpp b/Apps/App.Base/src/SceneManagerModule.cpp index 409979e..ac114bd 100644 --- a/Apps/App.Base/src/SceneManagerModule.cpp +++ b/Apps/App.Base/src/SceneManagerModule.cpp @@ -23,10 +23,10 @@ void SceneManagerModule::Initialize() { Uninitialize(); - if (!LoadWorld("world1.yaml")) - { - // todo runtime error or log - } + //if (!LoadWorld("world1.yaml")) + //{ + // // todo runtime error or log + //} /*const std::filesystem::path scenePath = std::filesystem::path(ASSETS_FOLDER) / @@ -40,10 +40,10 @@ void SceneManagerModule::Initialize() "Interior" / "interior.obj"; - //if (!LoadWorld(scenePath)) - //{ - // // todo runtime error or log - //} + if (!LoadWorld(scenePath)) + { + // todo runtime error or log + } World* world = GetWorld(0); if (!world) From 9a9d69f8f5c0fdd8fb7ba1402c809fbc6e9a587a Mon Sep 17 00:00:00 2001 From: AMorunov Date: Tue, 7 Jul 2026 13:11:33 +0300 Subject: [PATCH 42/46] QoL refactorings --- .../App.Base/ECS/Components/CameraComponent.h | 4 +- .../Include/App.Base/Modules/RenderModule.h | 16 +---- .../App.Base/Systems/GPUDataUpdateSystem.h | 18 +++--- Apps/App.Base/src/RenderModule.cpp | 42 ++++++++++--- .../Engine.RendererDX12.vcxproj | 2 +- .../Engine.RendererDX12.vcxproj.filters | 6 +- .../Engine.RendererDX12/GDX12SharedTexture.h | 2 +- .../Engine.RendererDX12/GDX12Texture.h | 4 ++ .../RenderPasses/GDX12BackBufferClearPass.h | 49 --------------- .../RenderPasses/GDX12FSRUpscalePass.h | 2 +- .../RenderPasses/GDX12OutputToScreenPass.h | 4 +- .../RenderPasses/GDX12TextureClearPass.h | 59 +++++++++++++++++++ .../Engine.RendererDX12/src/GDX12Texture.cpp | 28 +++++++-- 13 files changed, 142 insertions(+), 94 deletions(-) delete mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h create mode 100644 Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureClearPass.h 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 3f43fa1..251af57 100644 --- a/Apps/App.Base/Include/App.Base/ECS/Components/CameraComponent.h +++ b/Apps/App.Base/Include/App.Base/ECS/Components/CameraComponent.h @@ -9,8 +9,8 @@ struct CameraComponent : ComponentTag float FOV; float NearPlane; float FarPlane; - XMFLOAT4X4 ViewProj; - XMFLOAT4X4 PrevViewProjNoJitter; + Matrix ViewProj; + Matrix PrevViewProjNoJitter; bool DirtyFlag; diff --git a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h index 4e3e0ee..bd7cc1b 100644 --- a/Apps/App.Base/Include/App.Base/Modules/RenderModule.h +++ b/Apps/App.Base/Include/App.Base/Modules/RenderModule.h @@ -3,25 +3,13 @@ #include "Common/GameTimer.h" #include "Common/Module.h" -#include "Engine.RendererDX12/GDX12SwapChain.h" #include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" -#include "Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.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" #include "Engine.Core/ECS/Entity.h" #include "Engine.Core/ECS/Event.h" class SceneManagerModule; class World; +class GDX12SwapChain; struct TransformComponent; struct CameraComponent; @@ -112,6 +100,8 @@ class RenderModule final : public Module uint32_t GetPrimaryPipelineFlags(); uint32_t GetSecondaryPipelineFlags(); RenderPipelineCommonData* GetRenderPipelineCommonData(); + bool PrimaryPipelineHasFlag(uint32_t flag); + bool SecondaryPipelineHasFlag(uint32_t flag); protected: void OnUpdate() override; diff --git a/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h b/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h index 1021aaf..fc1b204 100644 --- a/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h +++ b/Apps/App.Base/Include/App.Base/Systems/GPUDataUpdateSystem.h @@ -77,8 +77,8 @@ class GPUDataUpdateSystem final : public System // Jitter current camera proj matrix if it is needed if (isActiveCamera && - ((renderModule->GetPrimaryPipelineFlags() & RENDER_PASS_FLAG_USE_JITTER) || - (renderModule->GetSecondaryPipelineFlags() & RENDER_PASS_FLAG_USE_JITTER))) + (renderModule->PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_JITTER) || + renderModule->SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_JITTER))) { static uint32_t frameIndex = 0; frameIndex++; @@ -101,13 +101,13 @@ class GPUDataUpdateSystem final : public System objConstants.NearPlane = camera.NearPlane; objConstants.FarPlane = camera.FarPlane; - if (renderModule->GetPrimaryPipelineFlags() & RENDER_PASS_FLAG_USE_CAMERAS) + if (renderModule->PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_CAMERAS)) { auto& CBuffer = renderModule->GetCurrentPrimaryFrameConstants()->CameraCB; CBuffer->CopyData(camera._CBufferIndex, objConstants); } - if (renderModule->GetSecondaryPipelineFlags() & RENDER_PASS_FLAG_USE_CAMERAS) + if (renderModule->SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_CAMERAS)) { auto& CBuffer = renderModule->GetCurrentSecondaryFrameConstants()->CameraCB; CBuffer->CopyData(camera._CBufferIndex, objConstants); @@ -144,12 +144,12 @@ class GPUDataUpdateSystem final : public System XMStoreFloat4x4(&GPUData.PrevWorld, world); - if (renderModule->GetPrimaryPipelineFlags() & RENDER_PASS_FLAG_USE_INSTANCES) + if (renderModule->PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) { auto& CBuffer = renderModule->GetCurrentPrimaryFrameConstants()->TransformCache; CBuffer->CopyData(GPUData.CBufferIndex, objConstants); } - if (renderModule->GetSecondaryPipelineFlags() & RENDER_PASS_FLAG_USE_INSTANCES) + if (renderModule->SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) { auto& CBuffer = renderModule->GetCurrentSecondaryFrameConstants()->TransformCache; CBuffer->CopyData(GPUData.CBufferIndex, objConstants); @@ -190,7 +190,7 @@ class GPUDataUpdateSystem final : public System } } - if (renderModule->GetSecondaryPipelineFlags() & RENDER_PASS_FLAG_USE_INSTANCES) + if (renderModule->SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) { auto gpuMesh = renderModule->GetSecondaryGPUMesh(renderer.MeshHandler); gpuMesh->CPUMesh->GetBounds().Transform(renderer.Bounds, XMLoadFloat4x4(&transformGPUData.World)); @@ -214,7 +214,7 @@ class GPUDataUpdateSystem final : public System if (renderer._numFramesDirty > 0) { - if (renderModule->GetPrimaryPipelineFlags() & RENDER_PASS_FLAG_USE_INSTANCES) + if (renderModule->PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) { auto& instanceCache = renderModule->GetCurrentPrimaryFrameConstants()->InstanceCache; auto gpuMesh = renderModule->GetPrimaryGPUMesh(renderer.MeshHandler); @@ -235,7 +235,7 @@ class GPUDataUpdateSystem final : public System instanceCache->CopyData(renderer._CBufferIndices[i], instanceData); } } - if (renderModule->GetSecondaryPipelineFlags() & RENDER_PASS_FLAG_USE_INSTANCES) + if (renderModule->SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) { auto& instanceCache = renderModule->GetCurrentSecondaryFrameConstants()->InstanceCache; auto gpuMesh = renderModule->GetSecondaryGPUMesh(renderer.MeshHandler); diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 0c7e394..724af19 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -6,6 +6,20 @@ #include "App.Base/Modules/SceneManagerModule.h" #include "Common/ConsoleVariables.h" +#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), _timer(timer), _primaryPipelineFlags(0), _secondaryPipelineFlags(0) @@ -489,12 +503,22 @@ 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; _transformGPUData[entity] = gpuData; - if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_INSTANCES) + if (PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) { _transformGPUData[entity].CBufferIndex = _primaryResources.FrameConstants[0]->TransformCache->GetElementCount(); for (auto& constants : _primaryResources.FrameConstants) @@ -504,7 +528,7 @@ void RenderModule::OnTransformComponentCreated(World& world, Entity entity, Tran } } - if (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_INSTANCES) + if (SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) { _transformGPUData[entity].CBufferIndex = _secondaryResources.FrameConstants[0]->TransformCache->GetElementCount(); for (auto& constants : _secondaryResources.FrameConstants) @@ -526,7 +550,7 @@ void RenderModule::OnTransformComponentUpdated(World& world, Entity entity, Tran void RenderModule::OnCameraComponentCreated(World& world, Entity entity, CameraComponent& component) { - if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_CAMERAS) + if (PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_CAMERAS)) { component._CBufferIndex = _primaryResources.FrameConstants[0]->CameraCB->GetElementCount(); @@ -550,7 +574,7 @@ void RenderModule::OnCameraComponentCreated(World& world, Entity entity, CameraC } } - if (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_CAMERAS) + if (SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_CAMERAS)) { component._CBufferIndex = _secondaryResources.FrameConstants[0]->CameraCB->GetElementCount(); @@ -586,7 +610,7 @@ void RenderModule::OnCameraComponentUpdated(World& world, Entity entity, CameraC void RenderModule::OnRenderComponentCreated(World& world, Entity entity, StaticMeshRenderComponent& component) { - if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_INSTANCES) + if (PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) { auto& MeshGPUData = _primaryResources.GeometryBuffer->_meshCache[component.MeshHandler.GetValue()]; for (int i = 0; i < MeshGPUData->SubMeshes.size(); i++) @@ -608,7 +632,7 @@ void RenderModule::OnRenderComponentCreated(World& world, Entity entity, StaticM } } - if (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_INSTANCES) + if (SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_INSTANCES)) { auto& MeshGPUData = _secondaryResources.GeometryBuffer->_meshCache[component.MeshHandler.GetValue()]; for (int i = 0; i < MeshGPUData->SubMeshes.size(); i++) @@ -666,7 +690,7 @@ void RenderModule::OnUpdate() } _primaryResources.UpdateMainCB(width, height, _timer); - if (_primaryPipelineFlags & RENDER_PASS_FLAG_USE_MATERIALS) + if (PrimaryPipelineHasFlag(RENDER_PASS_FLAG_USE_MATERIALS)) { _primaryResources.UpdateMaterialCB(_materials); } // same for SecondaryDevice @@ -683,7 +707,7 @@ void RenderModule::OnUpdate() } _secondaryResources.UpdateMainCB(width, height, _timer); - if (_secondaryPipelineFlags & RENDER_PASS_FLAG_USE_MATERIALS) + if (SecondaryPipelineHasFlag(RENDER_PASS_FLAG_USE_MATERIALS)) { _secondaryResources.UpdateMaterialCB(_materials); } } } @@ -782,7 +806,7 @@ void RenderModule::ConfigureRenderPipeline() { // 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()); diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj index 4632daa..5e82c14 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj @@ -32,10 +32,10 @@ + - diff --git a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters index 2eff34d..09f0937 100644 --- a/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters +++ b/Engine/Engine.RendererDX12/Engine.RendererDX12.vcxproj.filters @@ -81,9 +81,6 @@ Header Files - - Header Files - Header Files @@ -123,6 +120,9 @@ Header Files + + Header Files + diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h index 4f63219..a84e7ca 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12SharedTexture.h @@ -102,7 +102,7 @@ class GDX12SharedTexture : public IRenderPassLink D3D12_RESOURCE_ALLOCATION_INFO primaryInfo = _transferFromDeivce->GetDevice()->GetResourceAllocationInfo(0, 1, &desc); D3D12_RESOURCE_ALLOCATION_INFO secondaryInfo = _transferToDevice->GetDevice()->GetResourceAllocationInfo(0, 1, &desc); - _heapSize = max(primaryInfo.SizeInBytes, secondaryInfo.SizeInBytes); + _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 = {}; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h index c7262f6..6bb9693 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/GDX12Texture.h @@ -79,6 +79,10 @@ class GDX12Texture : public IRenderPassLink GDX12Descriptor* GetRTV(); GDX12Descriptor* GetUAV(); GDX12Descriptor* GetDSV(); + bool HasDSV(); + bool HasSRV(); + bool HasUAV(); + bool HasRTV(); D3D12_CLEAR_VALUE& GetClearValue(); GDX12TextureResource* GetResource(); DXGI_FORMAT GetFormat(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h deleted file mode 100644 index 172bae8..0000000 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12BackBufferClearPass.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once -#include "Engine.RendererDX12/RenderPasses/GDX12RenderPass.h" - -class GDX12BackBufferClearPass : public GDX12RenderPass -{ -public: - GDX12BackBufferClearPass() : IN_currentBackBuffer(nullptr), IN_depthStencil(nullptr) - { - _flags = RENDER_PASS_FLAG_NONE; - _numInputs = 2; - _numOutputs = 0; - } - - // Input 0 - back buffer - // Input 1 - depth stencil - void Initialize() override - { - IN_currentBackBuffer = _inputs[0]; - IN_depthStencil = _inputs[1]; - } - - void Execute(GDX12CommandList* cmdList) override - { - GDX12Texture* currentBackBuffer = IN_currentBackBuffer->GetTexture(); - GDX12Texture* depthStencil = IN_depthStencil->GetTexture(); - - cmdList->BeginPixEvent("Clear Back Buffer", Colors::Aqua); - cmdList->SetViewport(currentBackBuffer->GetViewport()); - cmdList->SetScissorRect(currentBackBuffer->GetScissorRect()); - cmdList->EnhancedTextureBarrier({ currentBackBuffer->GetResource()->GetRenderTargetEnhBarrier() }); - cmdList->ResourceBarrier({ depthStencil->GetResource()->GetDepthWriteBarrier() }); - cmdList->SetRenderTargets({ currentBackBuffer }, depthStencil); - cmdList->ClearRenderTargetView(currentBackBuffer); - cmdList->ClearDepthStencilView(depthStencil); - cmdList->EndPixEvent(); - } - - void ClearDenendencies() override - { - GDX12RenderPass::ClearDenendencies(); - - IN_currentBackBuffer = nullptr; - IN_depthStencil = nullptr; - } - -private: - IRenderPassLink* IN_currentBackBuffer; - IRenderPassLink* IN_depthStencil; -}; \ No newline at end of file diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index ea604b6..1c9e1cd 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -100,7 +100,7 @@ class GDX12FSRUpscalePass : public GDX12RenderPass dispatchDesc.enableSharpening = true; dispatchDesc.sharpness = 1.f; // for whatever reason, it doesnt like it when frame time is lower than 1.f - float clampedTime = max(_commonData->GameTimer->DeltaTime() * 1000.f, 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 diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h index 1e06e12..203ad10 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12OutputToScreenPass.h @@ -27,10 +27,10 @@ class GDX12OutputToScreenPass : public GDX12RenderPass cmdList->BeginPixEvent("Copy To Screen Pass", Colors::Aqua); cmdList->ResourceBarrier({ inputTexture->GetResource()->GetCopySourceBarrier() }); - cmdList->EnhancedTextureBarrier({ backBuffer->GetResource()->GetCopyDestEnhBarrier() }); + cmdList->ResourceBarrier({ backBuffer->GetResource()->GetCopyDestBarrier() }); cmdList->CopyResource(backBuffer->GetResource()->D3DResource.Get(), inputTexture->GetResource()->D3DResource.Get()); - cmdList->EnhancedTextureBarrier({ backBuffer->GetResource()->GetPresentEnhBarrier() }); + cmdList->ResourceBarrier({ backBuffer->GetResource()->GetPresentBarrier() }); cmdList->EndPixEvent(); } 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/src/GDX12Texture.cpp b/Engine/Engine.RendererDX12/src/GDX12Texture.cpp index 67db712..8c2dc79 100644 --- a/Engine/Engine.RendererDX12/src/GDX12Texture.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12Texture.cpp @@ -31,28 +31,48 @@ void GDX12Texture::Resize(UINT width, UINT 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; From bcbf1995d1d822b556e260c985ad515d76bf3ed9 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Tue, 7 Jul 2026 14:03:40 +0300 Subject: [PATCH 43/46] XeSS ghosting fixes --- Apps/App.Base/src/RenderModule.cpp | 9 ++++++--- .../RenderPasses/GDX12DLSSUpscalePass.h | 2 +- .../Engine.RendererDX12/RenderPasses/GDX12RenderPass.h | 3 ++- Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 724af19..644d982 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -41,8 +41,11 @@ RenderModule::~RenderModule() void RenderModule::Initialize() { + // This value will later be provided from external pipeline config + bool useStreamlineSDK = false; + // Streamline is initialized on the primary device only - GDX12StreamlineSDK::Get().Initialize(); + if (useStreamlineSDK) { GDX12StreamlineSDK::Get().Initialize(); } #if defined(DEBUG) || defined(_DEBUG) // Enable the D3D12 debug layer. @@ -53,7 +56,7 @@ void RenderModule::Initialize() _primaryDevice = std::make_unique(); _primaryDevice->Role = DEVICE_ROLE_PRIMARY; - _primaryDevice->Initialize(GDX12DeviceFactory::GetMostPerformantAdapter().Get()); + _primaryDevice->Initialize(GDX12DeviceFactory::GetDeviceDescriptors()[1].Adapter.Get()); _primaryResources.Initialize(_primaryDevice.get()); if (false) @@ -811,7 +814,7 @@ void RenderModule::ConfigureRenderPipeline() _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(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h index d9fc927..af415bc 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h @@ -23,7 +23,7 @@ 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; } + { _flags = RENDER_PASS_FLAG_UPSCALER | RENDER_PASS_FLAG_USE_JITTER | RENDER_PASS_FLAG_USE_STREAMLINE; } virtual void SetInputs(std::vector inputs) override { diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h index fc6b993..1aacae7 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -24,7 +24,8 @@ enum ERenderPassFlags : uint32_t 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_JITTER = 1 << 8, + RENDER_PASS_FLAG_USE_STREAMLINE = 1 << 9 }; class RenderPipelineCommonData; diff --git a/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl b/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl index e86e83e..d8d83ee 100644 --- a/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl +++ b/Engine/Engine.RendererDX12/Shaders/OpaquePass.hlsl @@ -76,7 +76,7 @@ PS_OUTPUT PS(VS_OUTPUT_PS_INPUT pin) float2 currentNDC = pin.PosCSNoJitter.xy / pin.PosCSNoJitter.w; float2 prevNDC = pin.PrevPosCSNoJitter.xy / pin.PrevPosCSNoJitter.w; - float2 velocity = currentNDC - prevNDC; + float2 velocity = prevNDC - currentNDC; output.Color = float4(color.rgb, 1.0f); output.Velocity = velocity; From a73551185983518a1535b5684a6f385f54122145 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Tue, 7 Jul 2026 14:35:10 +0300 Subject: [PATCH 44/46] Other upscalers quality improvements --- Apps/App.Base/src/RenderModule.cpp | 7 +++---- .../RenderPasses/GDX12DLSSUpscalePass.h | 2 +- .../Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h | 3 ++- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 644d982..84791f0 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -41,9 +41,8 @@ RenderModule::~RenderModule() void RenderModule::Initialize() { - // This value will later be provided from external pipeline config + // 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(); } @@ -56,7 +55,7 @@ void RenderModule::Initialize() _primaryDevice = std::make_unique(); _primaryDevice->Role = DEVICE_ROLE_PRIMARY; - _primaryDevice->Initialize(GDX12DeviceFactory::GetDeviceDescriptors()[1].Adapter.Get()); + _primaryDevice->Initialize(GDX12DeviceFactory::GetMostPerformantAdapter().Get()); _primaryResources.Initialize(_primaryDevice.get()); if (false) @@ -814,7 +813,7 @@ void RenderModule::ConfigureRenderPipeline() _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(); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h index af415bc..309e160 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h @@ -263,7 +263,7 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass constants.mvecScale = { 1.f, 1.f }; constants.depthInverted = Boolean::eTrue; - constants.cameraMotionIncluded = Boolean::eFalse; + constants.cameraMotionIncluded = Boolean::eTrue; constants.motionVectors3D = Boolean::eFalse; constants.reset = Boolean::eFalse; constants.orthographicProjection = Boolean::eFalse; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index 1c9e1cd..2f8ab57 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -87,7 +87,8 @@ class GDX12FSRUpscalePass : public GDX12RenderPass 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 = { 1.f, 1.f }; + 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; From b973e2ea15373a6f938eb7279880238602227239 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Tue, 7 Jul 2026 15:30:29 +0300 Subject: [PATCH 45/46] RenderPass linking bug fixes --- Apps/App.Base/src/RenderModule.cpp | 8 ++-- .../RenderPasses/GDX12DLSSUpscalePass.h | 34 +++++++++++------ .../RenderPasses/GDX12FSRUpscalePass.h | 36 +++++++++++------- .../RenderPasses/GDX12RenderPass.h | 17 ++++++++- .../GDX12TextureCopyFromSharedMemoryPass.h | 33 +++++++++++------ .../GDX12TextureCopyToSharedMemoryPass.h | 33 +++++++++++------ .../RenderPasses/GDX12XeSSUpscalePass.h | 37 ++++++++++++------- 7 files changed, 131 insertions(+), 67 deletions(-) diff --git a/Apps/App.Base/src/RenderModule.cpp b/Apps/App.Base/src/RenderModule.cpp index 84791f0..8271d05 100644 --- a/Apps/App.Base/src/RenderModule.cpp +++ b/Apps/App.Base/src/RenderModule.cpp @@ -830,10 +830,10 @@ void RenderModule::ConfigureRenderPipeline() clearPass->SetInputs({ _backBuffer.get(), _depthStencil.get() }); cullingPass->SetInputs({}); opaquePass->SetInputs({}); - transparencyPass->SetInputs({ opaquePass->GetOutputs()[2] }); - compositionPass->SetInputs({ opaquePass->GetOutputs()[0], transparencyPass->GetOutputs()[0], transparencyPass->GetOutputs()[1] }); - upscalePass->SetInputs({ opaquePass->GetOutputs()[2], opaquePass->GetOutputs()[1], compositionPass->GetOutputs()[0] }); - outputPass->SetInputs({ upscalePass->GetOutputs()[0], _backBuffer.get()}); + 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()}); opaquePass->SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); transparencyPass->SetFlag(RENDER_PASS_FLAG_USE_DOWNSCALED_RESOLUTION, true); diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h index 309e160..3410e1b 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12DLSSUpscalePass.h @@ -29,17 +29,13 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass { _inputs = inputs; _numInputs = 2; - _numOutputs = inputs.size() - 2; + MatchOutputCount(inputs.size() > 2 ? inputs.size() - 2 : 0); + } - OUT_UpscaledTextures.clear(); - _outputs.clear(); - OUT_UpscaledTextures.resize(_numOutputs); - _outputs.resize(_numOutputs); - for (int i = 0; i < _numOutputs; i++) - { - OUT_UpscaledTextures[i] = std::make_unique(); - _outputs[i] = OUT_UpscaledTextures[i].get(); - } + IRenderPassLink* GetOutput(UINT index) override + { + if (_inputs.empty()) { MatchOutputCount(index + 1); } + return GDX12RenderPass::GetOutput(index); } // Input 0 - DepthStencil @@ -66,8 +62,8 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; - IN_Textures.resize(_numInputs); - for (int i = 0; i < _numOutputs; i++) + IN_Textures.resize(_numOutputs); + for (UINT i = 0; i < _numOutputs; i++) { IN_Textures[i] = _inputs[i + 2]; GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); @@ -225,6 +221,20 @@ class GDX12DLSSUpscalePass : public GDX12RenderPass 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; diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h index 2f8ab57..c047854 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12FSRUpscalePass.h @@ -17,17 +17,13 @@ class GDX12FSRUpscalePass : public GDX12RenderPass { _inputs = inputs; _numInputs = 2; - _numOutputs = inputs.size() - 2; + MatchOutputCount(inputs.size() > 2 ? inputs.size() - 2 : 0); + } - OUT_UpscaledTextures.clear(); - _outputs.clear(); - OUT_UpscaledTextures.resize(_numOutputs); - _outputs.resize(_numOutputs); - for (int i = 0; i < _numOutputs; i++) - { - OUT_UpscaledTextures[i] = std::make_unique(); - _outputs[i] = OUT_UpscaledTextures[i].get(); - } + IRenderPassLink* GetOutput(UINT index) override + { + if (_inputs.empty()) { MatchOutputCount(index + 1); } + return GDX12RenderPass::GetOutput(index); } // Input 0 - DepthStencil @@ -54,8 +50,8 @@ class GDX12FSRUpscalePass : public GDX12RenderPass TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; - IN_Textures.resize(_numInputs); - for (int i = 0; i < _numOutputs; i++) + IN_Textures.resize(_numOutputs); + for (UINT i = 0; i < _numOutputs; i++) { IN_Textures[i] = _inputs[i + 2]; GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); @@ -168,6 +164,20 @@ class GDX12FSRUpscalePass : public GDX12RenderPass 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 = {}; @@ -209,4 +219,4 @@ class GDX12FSRUpscalePass : public GDX12RenderPass OutputDebugStringA(errorMsg.c_str()); } } -}; \ 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 index 1aacae7..77efd6a 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12RenderPass.h @@ -75,11 +75,24 @@ class GDX12RenderPass { 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; } - std::vector& GetOutputs() { return _outputs; } + 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; } @@ -121,4 +134,4 @@ class RenderPipelineCommonData UINT DownscaledWidth = 0; UINT DownscaledHeight = 0; GDX12RenderPass* Upscaler = nullptr; -}; \ 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 index a720a7d..f63561b 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h @@ -12,17 +12,14 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass virtual void SetInputs(std::vector inputs) override { _inputs = inputs; - _numInputs = _numOutputs = inputs.size(); + _numInputs = inputs.size(); + MatchOutputCount(_numInputs); + } - OUT_Textures.clear(); - _outputs.clear(); - OUT_Textures.resize(_numOutputs); - _outputs.resize(_numOutputs); - for (int i = 0; i < _numInputs; i++) - { - OUT_Textures[i] = std::make_unique(); - _outputs[i] = OUT_Textures[i].get(); - } + IRenderPassLink* GetOutput(UINT index) override + { + if (_inputs.empty()) { MatchOutputCount(index + 1); } + return GDX12RenderPass::GetOutput(index); } // Input N - SharedTexture @@ -90,4 +87,18 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass private: std::vector IN_SharedTextures; std::vector> OUT_Textures; -}; \ No newline at end of file + + 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 index 2bfbe03..8a27542 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyToSharedMemoryPass.h @@ -11,17 +11,14 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass virtual void SetInputs(std::vector inputs) override { _inputs = inputs; - _numInputs = _numOutputs = inputs.size(); + _numInputs = inputs.size(); + MatchOutputCount(_numInputs); + } - OUT_SharedTextures.clear(); - _outputs.clear(); - OUT_SharedTextures.resize(_numOutputs); - _outputs.resize(_numOutputs); - for (int i = 0; i < _numOutputs; i++) - { - OUT_SharedTextures[i] = std::make_unique(); - _outputs[i] = OUT_SharedTextures[i].get(); - } + IRenderPassLink* GetOutput(UINT index) override + { + if (_inputs.empty()) { MatchOutputCount(index + 1); } + return GDX12RenderPass::GetOutput(index); } // Input N - InputTexture @@ -74,4 +71,18 @@ class GDX12TextureCopyToSharedMemoryPass : public GDX12RenderPass private: std::vector IN_Textures; std::vector> OUT_SharedTextures; -}; \ No newline at end of file + + 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/GDX12XeSSUpscalePass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h index f144c96..66e5489 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12XeSSUpscalePass.h @@ -16,17 +16,13 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass { _inputs = inputs; _numInputs = 2; - _numOutputs = inputs.size() - 2; + MatchOutputCount(inputs.size() > 2 ? inputs.size() - 2 : 0); + } - OUT_UpscaledTextures.clear(); - _outputs.clear(); - OUT_UpscaledTextures.resize(_numOutputs); - _outputs.resize(_numOutputs); - for (int i = 0; i < _numOutputs; i++) - { - OUT_UpscaledTextures[i] = std::make_unique(); - _outputs[i] = OUT_UpscaledTextures[i].get(); - } + IRenderPassLink* GetOutput(UINT index) override + { + if (_inputs.empty()) { MatchOutputCount(index + 1); } + return GDX12RenderPass::GetOutput(index); } // Input 0 - DepthStencil @@ -53,8 +49,8 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass TextureDesc1.SRVDesc.Texture2D.PlaneSlice = 0; TextureDesc1.SRVDesc.Texture2D.ResourceMinLODClamp = 0.0f; - IN_Textures.resize(_numInputs); - for (int i = 0; i < _numOutputs; i++) + IN_Textures.resize(_numOutputs); + for (UINT i = 0; i < _numOutputs; i++) { IN_Textures[i] = _inputs[i + 2]; GDX12Texture* inputTexture = IN_Textures[i]->GetTexture(); @@ -96,7 +92,6 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass execParams.exposureScale = 1; execParams.inputColorBase = { 0,0 }; execParams.inputDepthBase = { 0,0 }; - for (int i = 0; i < _numOutputs; i++) { @@ -161,6 +156,20 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass 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); @@ -208,4 +217,4 @@ class GDX12XeSSUpscalePass : public GDX12RenderPass default: return "XESS_RESULT_UNKNOWN_ENUM"; } } -}; \ No newline at end of file +}; From 30d520bfb59e3dda5c63c3ad6de4da4eadb25a31 Mon Sep 17 00:00:00 2001 From: AMorunov Date: Tue, 7 Jul 2026 16:01:08 +0300 Subject: [PATCH 46/46] Cross-GPU transferring bug fixes --- .../GDX12TextureCopyFromSharedMemoryPass.h | 61 ++++++++++++++----- .../src/GDX12TextureResource.cpp | 3 +- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h index f63561b..1ab81e6 100644 --- a/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h +++ b/Engine/Engine.RendererDX12/Include/Engine.RendererDX12/RenderPasses/GDX12TextureCopyFromSharedMemoryPass.h @@ -26,33 +26,48 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass // Output N - OutputTexture void Initialize() override { - GDX12TextureDesc TextureDesc1; - 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_SharedTextures.resize(_numInputs); for (int i = 0; i < _numInputs; i++) { IN_SharedTextures[i] = _inputs[i]; GDX12SharedTexture* sharedTexture = IN_SharedTextures[i]->GetSharedTexture(); - TextureDesc1.Format = TextureDesc1.RTVDesc.Format = TextureDesc1.SRVDesc.Format = sharedTexture->GetFormat(); - TextureDesc1.Width = sharedTexture->GetWidth(); - TextureDesc1.Height = sharedTexture->GetHeight(); - TextureDesc1.SRVHeapIndex = _resources->SRV_UAV_Heap->GetAvailableIndex(TextureResources_StartIndex, TextureResources_RangeLength); - OUT_Textures[i]->Initialize(TextureDesc1); + 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 on the device the texture was transferred to + // 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); @@ -88,6 +103,20 @@ class GDX12TextureCopyFromSharedMemoryPass : public GDX12RenderPass 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); } diff --git a/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp b/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp index c18d4f3..672e65c 100644 --- a/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp +++ b/Engine/Engine.RendererDX12/src/GDX12TextureResource.cpp @@ -9,7 +9,8 @@ GDX12TextureResource::GDX12TextureResource(ComPtr resource) : _desc = D3DResource->GetDesc(); } -GDX12TextureResource::GDX12TextureResource() +GDX12TextureResource::GDX12TextureResource() : _currentAccess(D3D12_BARRIER_ACCESS_COMMON), + _currentLayout(D3D12_BARRIER_LAYOUT_COMMON), _currentSync(D3D12_BARRIER_SYNC_ALL), _desc({}) { }