From 1b753fe1c4b0929b7515d8f85fc918e1ded2de0c Mon Sep 17 00:00:00 2001 From: allen hux Date: Mon, 14 Nov 2022 09:16:29 -0800 Subject: [PATCH] readme changes. misc. --- README.md | 23 ++++--- TileUpdateManager/BitVector.h | 61 +++++++++++++++++++ TileUpdateManager/TileUpdateManagerBase.cpp | 3 +- .../TileUpdateManager_vs2022.vcxproj | 1 + .../TileUpdateManager_vs2022.vcxproj.filters | 3 + config/config.json | 2 +- src/Gui.cpp | 38 ++++++++++-- src/Gui.h | 2 + src/Scene.cpp | 45 ++++++++++---- src/Scene.h | 12 ++-- 10 files changed, 156 insertions(+), 34 deletions(-) create mode 100644 TileUpdateManager/BitVector.h diff --git a/README.md b/README.md index f7c5b17..bc1f2b2 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,30 @@ -# Sampler Feedback Streaming +# Sampler Feedback Streaming With DirectStorage ## Introduction This repository contains an [MIT licensed](LICENSE) demo of _DirectX12 Sampler Feedback Streaming_, a technique using [DirectX12 Sampler Feedback](https://microsoft.github.io/DirectX-Specs/d3d/SamplerFeedback.html) to guide continuous loading and eviction of small regions (tiles) of textures - in other words, virtual texture streaming. Sampler Feedback Streaming can dramatically improve visual quality by enabling scenes consisting of 100s of gigabytes of resources to be drawn on GPUs containing much less physical memory. The scene below uses just ~200MB of a 1GB heap, despite over 350GB of total texture resources. It also uses DirectStorage for Windows for maximum file upload performance. New: incorporated DirectStorage for Windows v1.1.0 with GPU decompression. Be sure to update your GPU drivers to access your vendor's optimized GPU decompression capabilities. See also: -- [Intel's blog](https://www.intel.com/content/www/us/en/developer/articles/news/directstorage-on-intel-gpus.html) -- [Microsoft's blog](https://devblogs.microsoft.com/directx/directstorage-1-1-now-available/) +- [Intel's 1.1 announcement blog](https://www.intel.com/content/www/us/en/developer/articles/news/directstorage-on-intel-gpus.html) +- [Microsoft's 1.1 announcement blog](https://devblogs.microsoft.com/directx/directstorage-1-1-now-available/) +See also: + +- [GDC 2021 video](https://software.intel.com/content/www/us/en/develop/events/gdc.html?videoid=6264595860001) [(alternate link)](https://www.youtube.com/watch?v=VDDbrfZucpQ) which provides an overview of Sampler Feedback and discusses this sample [starting at about 15:30.](https://www.youtube.com/watch?v=VDDbrfZucpQ&t=936s) +- [GDC 2021 presentation](https://software.intel.com/content/dam/develop/external/us/en/documents/pdf/july-gdc-2021-sampler-feedback-texture-space-shading-direct-storage.pdf) in PDF form +- [Microsoft DirectStorage Landing Page](https://devblogs.microsoft.com/directx/directstorage-api-downloads/) ![Sample screenshot](./readme-images/sampler-feedback-streaming.jpg "Sample screenshot") Textures derived from [Hubble Images](https://www.nasa.gov/mission_pages/hubble/multimedia/index.html), see the [Hubble Copyright](https://hubblesite.org/copyright) Notes: - while multiple objects can share the same DX texture and source file, this sample aims to demonstrate the possibility of every object having a unique resource. Hence, every texture is treated as though unique, though the same source file may be used multiple times. -- not all textures shown above, which total over 13GB, are not part of the repo. A few 16k x 16k textures are available as [release 1](https://github.com/GameTechDev/SamplerFeedbackStreaming/releases/tag/1) and [release 2](https://github.com/GameTechDev/SamplerFeedbackStreaming/releases/tag/2) +- the repo does not include all textures shown above (they total over 13GB). A few 16k x 16k textures are available as [release 1](https://github.com/GameTechDev/SamplerFeedbackStreaming/releases/tag/1) and [release 2](https://github.com/GameTechDev/SamplerFeedbackStreaming/releases/tag/2) - the file format has changed since large textures were provided as "releases." See the [log](#log) below. -- this repository has been updated with DirectStorage 1.0.2 for Windows® from https://www.nuget.org/packages/Microsoft.Direct3D.DirectStorage/ +- this repository depends on DirectStorage for Windows® version 1.1.0 from https://www.nuget.org/packages/Microsoft.Direct3D.DirectStorage/ - at build time, BCx textures (BC7 and BC1 tested) in the dds/ directory are converted into the custom .XET format and placed in the ($TargetDir)/media directory (e.g. x64/Release/media). A few dds files are included. -Requirements: +## Requirements: - minimum: - Windows 10 20H1 (aka May 2020 Update, build 19041) - GPU with D3D12 Sampler Feedback Support such as Intel Iris Xe Graphics as found in 11th Generation Intel® Core™ processors and discrete GPUs (driver version **[30.0.100.9667](https://downloadcenter.intel.com/product/80939/Graphics) or later**) @@ -28,12 +33,6 @@ Requirements: - nvme SSD with PCIe gen4 or later - Intel Arc A770 discrete GPU or later -See also: - -* [GDC 2021 video](https://software.intel.com/content/www/us/en/develop/events/gdc.html?videoid=6264595860001) [(alternate link)](https://www.youtube.com/watch?v=VDDbrfZucpQ) which provides an overview of Sampler Feedback and discusses this sample starting at about 15:30. - -* [GDC 2021 presentation](https://software.intel.com/content/dam/develop/external/us/en/documents/pdf/july-gdc-2021-sampler-feedback-texture-space-shading-direct-storage.pdf) in PDF form - ## Build Instructions Download the source. Build the appropriate solution file diff --git a/TileUpdateManager/BitVector.h b/TileUpdateManager/BitVector.h new file mode 100644 index 0000000..21c2c3d --- /dev/null +++ b/TileUpdateManager/BitVector.h @@ -0,0 +1,61 @@ +//********************************************************* +// +// Copyright 2020 Intel Corporation +// +// Permission is hereby granted, free of charge, to any +// person obtaining a copy of this software and associated +// documentation files(the "Software"), to deal in the Software +// without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to +// whom the Software is furnished to do so, subject to the +// following conditions : +// The above copyright notice and this permission notice shall +// be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//********************************************************* +#pragma once + +//================================================== +// vector of bits packed into standard type +// expected types: UINT64, UINT32, UINT16, UINT8 +//================================================== +template class BitVector +{ +public: + BitVector(size_t in_size, UINT in_initialValue = 0) : m_size(in_size), m_bits((in_size + BIT_MASK) >> BIT_SHIFT, in_initialValue ? T(-1) : 0) {} + UINT Get(UINT i) { return GetVector(i) & GetBit(i); } + void Set(UINT i) { GetVector(i) |= GetBit(i); } + void Clear(UINT i) { GetVector(i) &= ~GetBit(i); } + size_t size() { return m_size; } + + class Accessor // helper class so we can replace std::vector<> + { + public: + operator UINT() const { return m_b.Get(m_i); } + void operator=(UINT b) { b ? m_b.Set(m_i) : m_b.Clear(m_i); } + private: + Accessor(BitVector& b, UINT i) : m_b(b), m_i(i) {} + BitVector& m_b; + const UINT m_i{ 0 }; + friend class BitVector; + }; + Accessor operator[](UINT i) { return Accessor(*this, i); } +private: + const size_t m_size{ 0 }; + // use the upper bits of the incoming index to get the array index (shift by log2, e.g. byte type is 3 bits) + static constexpr UINT BIT_SHIFT = (8 == sizeof(T)) ? 6 : (4 == sizeof(T)) ? 5 : (2 == sizeof(T)) ? 4 : 3; + static constexpr UINT BIT_MASK = (T(1) << BIT_SHIFT) - 1; + std::vector m_bits; + UINT GetBit(UINT i) { return T(1) << (i & BIT_MASK); } + T& GetVector(UINT i) { return m_bits[i >> BIT_SHIFT]; } +}; diff --git a/TileUpdateManager/TileUpdateManagerBase.cpp b/TileUpdateManager/TileUpdateManagerBase.cpp index e82eb9e..3e92e76 100644 --- a/TileUpdateManager/TileUpdateManagerBase.cpp +++ b/TileUpdateManager/TileUpdateManagerBase.cpp @@ -31,6 +31,7 @@ #include "StreamingResourceBase.h" #include "XeTexture.h" #include "StreamingHeap.h" +#include "BitVector.h" //============================================================================= // constructor for streaming library base class @@ -156,7 +157,7 @@ void Streaming::TileUpdateManagerBase::ProcessFeedbackThread() staleResources.reserve(m_streamingResources.size()); // flags to prevent duplicates in the staleResources array - std::vector pending(m_streamingResources.size(), 0); + BitVector pending(m_streamingResources.size(), 0); UINT uploadsRequested = 0; // remember if any work was queued so we can signal afterwards UINT64 previousFrameFenceValue = m_frameFenceValue; diff --git a/TileUpdateManager/TileUpdateManager_vs2022.vcxproj b/TileUpdateManager/TileUpdateManager_vs2022.vcxproj index 1973b53..5bea3b1 100644 --- a/TileUpdateManager/TileUpdateManager_vs2022.vcxproj +++ b/TileUpdateManager/TileUpdateManager_vs2022.vcxproj @@ -111,6 +111,7 @@ + diff --git a/TileUpdateManager/TileUpdateManager_vs2022.vcxproj.filters b/TileUpdateManager/TileUpdateManager_vs2022.vcxproj.filters index 84c22f2..fd7c43e 100644 --- a/TileUpdateManager/TileUpdateManager_vs2022.vcxproj.filters +++ b/TileUpdateManager/TileUpdateManager_vs2022.vcxproj.filters @@ -63,6 +63,9 @@ Header Files + + Header Files + diff --git a/config/config.json b/config/config.json index fc1dcf9..2257021 100644 --- a/config/config.json +++ b/config/config.json @@ -34,7 +34,7 @@ "maxFeedbackTime": 5.0, // maximum milliseconds for GPU to resolve feedback "visualizeMinMip": false, // color overlayed onto texture by PS corresponding to mip level - "hideFeedback": true, // hide the terrain feedback windows + "hideFeedback": false, // hide the terrain feedback windows "hideUI": false, // hide the UI "miniUI": false, // use "lite" UI (bandwidth & heap occupancy only) diff --git a/src/Gui.cpp b/src/Gui.cpp index 0eae980..8b3eb46 100644 --- a/src/Gui.cpp +++ b/src/Gui.cpp @@ -238,12 +238,22 @@ void Gui::ToggleDemoMode(CommandLineArgs& in_args) static float bias = 0; static float cameraRate = 0.4f; static float animationRate = 0.4f; + static int numSpheres = (int)m_initialArgs.m_maxNumObjects; + + if (m_demoMode) + { + bias = 0; + cameraRate = 0.4f; + animationRate = 0.4f; + numSpheres = (int)m_initialArgs.m_maxNumObjects; + } std::swap(bias, in_args.m_lodBias); std::swap(cameraRate, in_args.m_cameraAnimationRate); std::swap(animationRate, in_args.m_animationRate); + std::swap(numSpheres, in_args.m_numSpheres); + in_args.m_showFeedbackMaps = false; - in_args.m_numSpheres = (int)m_initialArgs.m_maxNumObjects; } //----------------------------------------------------------------------------- @@ -256,13 +266,24 @@ void Gui::ToggleBenchmarkMode(CommandLineArgs& in_args) static float bias = -2; static float cameraRate = 2; static float animationRate = 2; + static int numSpheres = (int)m_initialArgs.m_maxNumObjects; + + if (m_benchmarkMode) + { + paintmixer = true; + bias = -2; + cameraRate = 2; + animationRate = 2; + numSpheres = (int)m_initialArgs.m_maxNumObjects; + } std::swap(paintmixer, in_args.m_cameraPaintMixer); std::swap(bias, in_args.m_lodBias); std::swap(cameraRate, in_args.m_cameraAnimationRate); std::swap(animationRate, in_args.m_animationRate); + std::swap(numSpheres, in_args.m_numSpheres); + in_args.m_showFeedbackMaps = false; - in_args.m_numSpheres = (int)m_initialArgs.m_maxNumObjects; } //----------------------------------------------------------------------------- @@ -341,7 +362,12 @@ void Gui::Draw(ID3D12GraphicsCommandList* in_pCommandList, //--------------------------------------------------------------------- // terrain feedback viewer //--------------------------------------------------------------------- - in_args.m_showFeedbackMaps = ImGui::CollapsingHeader("Terrain Object Feedback Viewer"); + ImGuiTreeNodeFlags feedbackNodeFlags = ImGuiTreeNodeFlags_None; + if (in_args.m_showFeedbackMaps) + { + feedbackNodeFlags = ImGuiTreeNodeFlags_DefaultOpen; + } + in_args.m_showFeedbackMaps = ImGui::CollapsingHeader("Terrain Object Feedback Viewer", feedbackNodeFlags); if (in_args.m_showFeedbackMaps) { in_args.m_cameraUpLock = true; @@ -400,7 +426,8 @@ void Gui::Draw(ID3D12GraphicsCommandList* in_pCommandList, //--------------------------------------------------------------------- // demo mode //--------------------------------------------------------------------- - if (ImGui::Button("DEMO MODE", ImVec2(-1, 0))) + out_buttonChanges.m_toggleDemoMode = ImGui::Button("DEMO MODE", ImVec2(-1, 0)); + if (out_buttonChanges.m_toggleDemoMode) { if (m_benchmarkMode) { ToggleBenchmarkMode(in_args); } ToggleDemoMode(in_args); @@ -409,7 +436,8 @@ void Gui::Draw(ID3D12GraphicsCommandList* in_pCommandList, //--------------------------------------------------------------------- // benchmark mode //--------------------------------------------------------------------- - if (ImGui::Button("BENCHMARK MODE", ImVec2(-1, 0))) + out_buttonChanges.m_toggleBenchmarkMode = ImGui::Button("BENCHMARK MODE", ImVec2(-1, 0)); + if (out_buttonChanges.m_toggleBenchmarkMode) { if (m_demoMode) { ToggleDemoMode(in_args); } ToggleBenchmarkMode(in_args); diff --git a/src/Gui.h b/src/Gui.h index cd6dc1a..206b24d 100644 --- a/src/Gui.h +++ b/src/Gui.h @@ -59,6 +59,8 @@ class Gui bool m_directStorageToggle{ false }; bool m_frustumToggle{ false }; bool m_visualizationChange{ false }; + bool m_toggleDemoMode{ false }; + bool m_toggleBenchmarkMode{ false }; }; void Draw(ID3D12GraphicsCommandList* in_pCommandList, diff --git a/src/Scene.cpp b/src/Scene.cpp index e599b70..eb85e55 100644 --- a/src/Scene.cpp +++ b/src/Scene.cpp @@ -204,8 +204,7 @@ Scene::Scene(const CommandLineArgs& in_args, HWND in_hwnd) : XMVECTOR lookAt = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f); XMVECTOR vUpVec = XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f); - m_viewMatrix = XMMatrixLookAtLH(vEyePt, lookAt, vUpVec); - m_viewMatrixInverse = XMMatrixInverse(nullptr, m_viewMatrix); + SetViewMatrix(XMMatrixLookAtLH(vEyePt, lookAt, vUpVec)); m_pGui = new Gui(m_hwnd, m_device.Get(), m_srvHeap.Get(), (UINT)DescriptorHeapOffsets::GUI, m_swapBufferCount, SharedConstants::SWAP_CHAIN_FORMAT, adapterDescription, m_args); @@ -284,8 +283,7 @@ void Scene::MoveView(int in_x, int in_y, int in_z) float z = in_z * -translationRate; XMMATRIX translation = XMMatrixTranslation(x, y, z); - m_viewMatrix = XMMatrixMultiply(m_viewMatrix, translation); - m_viewMatrixInverse = XMMatrixInverse(nullptr, m_viewMatrix); + SetViewMatrix(XMMatrixMultiply(m_viewMatrix, translation)); } //----------------------------------------------------------------------------- @@ -314,9 +312,7 @@ void Scene::RotateView(float in_x, float in_y, float in_z) rotation = XMMatrixRotationRollPitchYaw(in_x, in_y, in_z); } - m_viewMatrix = XMMatrixMultiply(m_viewMatrix, rotation); - - m_viewMatrixInverse = XMMatrixInverse(nullptr, m_viewMatrix); + SetViewMatrix(XMMatrixMultiply(m_viewMatrix, rotation)); } @@ -1365,17 +1361,15 @@ void Scene::Animate() XMVECTOR vUpVec = XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f); - m_viewMatrix = XMMatrixLookToLH(pos, lookTo, vUpVec); + SetViewMatrix(XMMatrixLookToLH(pos, lookTo, vUpVec)); previous = pos; } else { XMVECTOR pos = XMVectorSet(x, y, z, 1); - m_viewMatrix = XMMatrixLookAtLH(pos, XMVectorSet(0, 0, 0, 0), XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f)); + SetViewMatrix(XMMatrixLookAtLH(pos, XMVectorSet(0, 0, 0, 0), XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f))); } - - m_viewMatrixInverse = XMMatrixInverse(nullptr, m_viewMatrix); } // spin objects @@ -1638,6 +1632,22 @@ void Scene::HandleUiToggleFrustum() } } +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- +void Scene::SwapCameraForDemo(bool in_capture) +{ + static XMMATRIX previousView = XMMatrixIdentity(); + + if (in_capture) + { + previousView = m_viewMatrix; + } + else + { + SetViewMatrix(previousView); + } +} + //------------------------------------------------------------------------- // handle UI changes (outside of begin/end frame) //------------------------------------------------------------------------- @@ -1658,6 +1668,19 @@ void Scene::HandleUIchanges() m_pTileUpdateManager->SetVisualizationMode((UINT)m_args.m_dataVisualizationMode); } + if (m_uiButtonChanges.m_toggleBenchmarkMode) + { + m_benchmarkMode = !m_benchmarkMode; + if (!m_demoMode) { SwapCameraForDemo(m_benchmarkMode); } + else { m_demoMode = false; } + } + if (m_uiButtonChanges.m_toggleDemoMode) + { + m_demoMode = !m_demoMode; + if (!m_benchmarkMode) { SwapCameraForDemo(m_demoMode); } + else { m_benchmarkMode = false; } + } + m_uiButtonChanges = Gui::ButtonChanges(); // reset } } diff --git a/src/Scene.h b/src/Scene.h index 4d7deac..f5f8ee9 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -142,6 +142,8 @@ class Scene DirectX::XMMATRIX m_projection; DirectX::XMMATRIX m_viewMatrix; DirectX::XMMATRIX m_viewMatrixInverse; + void SetViewMatrix(const DirectX::XMMATRIX& m) { m_viewMatrix = m; m_viewMatrixInverse = XMMatrixInverse(nullptr, m_viewMatrix); } + float m_aspectRatio{ 0 }; const float m_fieldOfView{ DirectX::XM_PI / 6.0f }; @@ -183,6 +185,7 @@ class Scene // startup sequence (constructor) //------------------------------- void InitDebugLayer(); + void CreateDeviceWithName(std::wstring& out_adapterDescription); void CreateDescriptorHeaps(); void CreateCommandQueue(); void CreateSwapChain(); @@ -206,6 +209,8 @@ class Scene //----------------------------------- // scene graph //----------------------------------- + AssetUploader m_assetUploader; + std::vector m_objects; UINT m_numSpheresLoaded{ 0 }; @@ -252,12 +257,11 @@ class Scene void HandleUIchanges(); bool WaitForAssetLoad(); - void StartScene(); void DrawUI(); void HandleUiToggleFrustum(); - void CreateDeviceWithName(std::wstring& out_adapterDescription); - - AssetUploader m_assetUploader; + bool m_demoMode{ false }; + bool m_benchmarkMode{ false }; + void SwapCameraForDemo(bool in_capture); };