diff --git a/README.md b/README.md index 6a43816..358689c 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,26 @@ ## 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 portions (tiles) of assets allowing for much higher visual quality than previously possible by making better use of GPU memory capacity. Sampler Feedback Streaming allows 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. (Objects could have shared streaming resources, but the intent of the demo is to show the potential of using many unique textures). +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. -The demo requires ***Windows 10 20H1 (aka May 2020 Update, build 19041)*** or later and a GPU with 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**). - -This repository has been updated with DirectStorage 1.0.2 for Windows® from https://www.nuget.org/packages/Microsoft.Direct3D.DirectStorage/ +![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: -- The file format has changed since large textures were provided as "releases." See the [log](#log) below. -- The legacy streaming code using ReadFile() had sector alignment constraints for the file internals that are not required by DirectStorage for Windows. +- 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 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/ +- 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: +- 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**) +- recommended: + - Windows 11 + - nvme SSD with PCIe gen4 or later + - Intel Arc A770 discrete GPU or later See also: @@ -18,32 +29,28 @@ See also: * [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 -![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) - - -Note the 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) - -Test textures are provided. 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) - ## Build Instructions -Download the source. Build the solution file [SamplerFeedbackStreaming.sln](SamplerFeedbackStreaming.sln) (tested with Visual Studio 2019). +Download the source. Build the appropriate solution file +- Visual Studio 2022: [SamplerFeedbackStreaming_vs2022.sln](SamplerFeedbackStreaming_vs2022.sln) +- Visual Studio 2019: [SamplerFeedbackStreaming.sln](SamplerFeedbackStreaming.sln). All executables, scripts, configurations, and media files will be found in the x64/Release or x64/Debug directories. You can run from within the Visual Studio IDE or from the command line, e.g.: c:\SamplerFeedbackStreaming\x64\Release> expanse.exe -By default (no command line options) there will be a single object, "terrain", which allows for exploring sampler feedback streaming. In the top right find 2 windows: on the left is the raw GPU min mip feedback, on the right is the min mip map "residency map" generated by the application. Across the bottom are the mips of the texture, with mip 0 in the bottom left. Left-click drag the terrain to see sampler feedback streaming in action. +By default (no command line options) there will be a single object, "terrain", which allows for exploring sampler feedback streaming. To explore sampler feedback streaming, expand "Terrain Object Feedback Viewer." In the top right find 2 windows: the raw GPU sampler feedback (min mip map of desired tiles) and to its right the "residency map" generated by the application (min mip map of tiles that have been loaded). Across the bottom are the mips of the texture, with mip 0 in the bottom left. Left-click drag the terrain to see sampler feedback streaming in action. Note that navigation in this mode has the up direction locked, which can be disabled in the UI. ![default startup](./readme-images/default-startup.jpg "default startup") -Press the DEMO MODE button or run the batch file _demo.bat_ to see streaming in action. Press "page up" or to click _Color MinMip_ to toggle a visualization of the tiles loading, best viewed in _Roller Coaster_ mode. Note keyboard controls are inactive while the _Camera_ slider is non-zero. +Press the DEMO MODE button or run the batch file _demo.bat_ to see streaming in action. Press "page up" or to click _Tile Min Mip Overlay_ to toggle a visualization of the tiles loading. Toggle _Roller Coaster_ mode (page up) to fly through the scene. Note keyboard controls are inactive while the _Camera_ slider is non-zero. c:\SamplerFeedbackStreaming\x64\Release> demo.bat ![demo batch file](./readme-images/demo-bat.jpg "demo.bat") -The high-resolution textures in the first "release" package, [hubble-16k.zip](https://github.com/GameTechDev/SamplerFeedbackStreaming/releases/tag/1), work with "demo-hubble.bat", including a sky and earth. Make sure the mediadir in the batch file is set properly, or override it on the command line as follows: +Benchmark mode generates massive disk traffic by cranking up the animation rate, dialing up the sampler bias, and rapidly switching between two camera paths to force eviction of all the current texture tiles. This mode is designed to stress the whole platform, from storage to PCIe interface to CPU and GPU. + +Two sets of high resolution textures are available for use with "demo-hubble.bat": [hubble-16k.zip](https://github.com/GameTechDev/SamplerFeedbackStreaming/releases/tag/1) and [hubble-16k-bc1.zip](https://github.com/GameTechDev/SamplerFeedbackStreaming/releases/tag/2)). BUT they are in an older file format. Simply drop them into the "dds" directory and rebuild DdsToXet, or convert them to the new file format with `convert.bat` (see below). Make sure the mediadir in the batch file is set properly, or override it on the command line as follows: c:\SamplerFeedbackStreaming\x64\Release> demo-hubble.bat -mediadir c:\hubble-16k @@ -51,16 +58,14 @@ The high-resolution textures in the first "release" package, [hubble-16k.zip](ht * `qwe / asd` : strafe left, forward, strafe right / rotate left, back, rotate right * `z c` : levitate up and down -* `x` : toggles "up lock". When hovering over the "terrain" object, locking the up direction "feels right" with mouse navigation. Otherwise, it should be turned off. * `v b` : rotate around the look direction (z axis) * `arrow keys` : rotate left/right, pitch down/up * `shift` : move faster * `mouse left-click drag` : rotate view -* `page up` : toggle the min mip map viewer for the "terrain" geometry in the center of the universe +* `page up` : toggle the min mip map overlay onto every object (visualize tiles loading) * `page down` : while camera animation is non-zero, toggles fly-through "rollercoaster" vs. fly-around "orbit" * `space` : toggles camera animation on/off. * `home` : toggles UI. Hold "shift" while UI is enabled to toggle mini UI mode. -* `end` : toggle overlay of min mip map onto every object * `insert` : toggles frustum visualization * `esc` : while windowed, exit. while full-screen, return to windowed mode @@ -94,6 +99,11 @@ The batch file [convert.bat](scripts/convert.bat) will read all the DDS files in c:> convert c:\myDdsFiles c:\myXetFiles +A new DirectStorage trace capture and playback utility has been added so DirectStorage performance can be analyzed without the overhead of rendering. For example, to capture and play back the DirectStorage requests and submits for 500 "stressful" frames with a staging buffer size of 128MB, cd to the build directory and: +``` +stress.bat -timingstart 200 -timingstop 700 -capturetrace +traceplayer.exe -file uploadTraceFile_1.json -mediadir media -staging 128 +``` ## TileUpdateManager: a library for streaming textures The sample includes a library *TileUpdateManager* with a minimal set of APIs defined in [SamplerFeedbackStreaming.h](TileUpdateManager/SamplerFeedbackStreaming.h). The central object, *TileUpdateManager*, allows for the creation of streaming textures and heaps to contain them. These objects handle all the feedback resource creation, readback, processing, and file/IO. diff --git a/TileUpdateManager/FileStreamer.h b/TileUpdateManager/FileStreamer.h index 85d2006..daec9fa 100644 --- a/TileUpdateManager/FileStreamer.h +++ b/TileUpdateManager/FileStreamer.h @@ -70,7 +70,7 @@ namespace Streaming UINT64 m_copyFenceValue{ 0 }; // Visualization - VisualizationMode m_visualizationMode; + VisualizationMode m_visualizationMode{ VisualizationMode::DATA_VIZ_NONE }; // get visualization colors void* GetVisualizationData(const D3D12_TILED_RESOURCE_COORDINATE& in_coord, DXGI_FORMAT in_format); diff --git a/TileUpdateManager/StreamingHeap.cpp b/TileUpdateManager/StreamingHeap.cpp index 9c24b45..a760196 100644 --- a/TileUpdateManager/StreamingHeap.cpp +++ b/TileUpdateManager/StreamingHeap.cpp @@ -172,7 +172,7 @@ Streaming::Heap::Heap(ID3D12CommandQueue* in_pQueue, UINT in_maxNumTilesHeap) : // create a heap to store streaming tiles // should be smaller than the entire surface - const UINT heapSize = in_maxNumTilesHeap * D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES; + const UINT64 heapSize = UINT64(in_maxNumTilesHeap) * D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES; CD3DX12_HEAP_DESC heapDesc(heapSize, D3D12_HEAP_TYPE_DEFAULT, 0, D3D12_HEAP_FLAG_DENY_BUFFERS | D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES); ThrowIfFailed(device->CreateHeap(&heapDesc, IID_PPV_ARGS(&m_tileHeap))); } diff --git a/config/config.json b/config/config.json index 324f82e..fc1dcf9 100644 --- a/config/config.json +++ b/config/config.json @@ -23,10 +23,10 @@ "rollerCoaster": false, // fly through, vs. orbiting, planets "mediaDir": "media", // media directory - "texture": "", // setting this overrides all textures, invalidates mediadir "skyTexture": "", // add a sky sphere. path relative to mediadir "earthTexture": "earth", // when a texture containing this string is encountered, treat it as a mercator projection (no uv mirror) "terrainTexture": "4kTiles.xet", // use this texture only for the terrain, no planets + "maxNumObjects": 985, // maximum total number of objects in the scene "numSpheres": 0, // number of objects besides the terrain "lightFromView": false, // light direction is look direction diff --git a/include/DebugHelper.h b/include/DebugHelper.h index f3f9787..ec0cc20 100644 --- a/include/DebugHelper.h +++ b/include/DebugHelper.h @@ -23,34 +23,6 @@ // DEALINGS IN THE SOFTWARE. // //********************************************************* - -/*----------------------------------------------------------------------------- -ArgParser - -Parse arguments to a Windows application -On finding a match, calls custom code -Case is ignored while parsing - -example: -This creates the parser, then searches for a few values. -The value is expected to follow the token. - -runprogram.exe gRaVity 20.27 upIsDown dothing - -float m_float = 0; -bool m_flipGravity = false; - -ArgParser argParser; -argParser.AddArg(L"gravity", m_float); -argParser.AddArg(L"upisdown", m_flipGravity); // inverts m_flipGravity -argParser.AddArg(L"downisup", L"whoops!", m_flipGravity); // inverts current value, includes help message -argParser.AddArg(L"dothing", [=](std::wstring) { DoTheThing(); } ); // call custom function to handle param -argParser.AddArg(L"option", L"a function", [=](std::wstring) { DoOption(); } ); // custom function with help message -argParser.Parse(); - -after running, m_float=20.27 and m_flipGravity=true - ------------------------------------------------------------------------------*/ #pragma once //================================================== diff --git a/readme-images/default-startup.jpg b/readme-images/default-startup.jpg index 48c3cd0..b4e0454 100644 Binary files a/readme-images/default-startup.jpg and b/readme-images/default-startup.jpg differ diff --git a/readme-images/demo-bat.jpg b/readme-images/demo-bat.jpg index 5e218c2..d3c2701 100644 Binary files a/readme-images/demo-bat.jpg and b/readme-images/demo-bat.jpg differ diff --git a/src/CommandLineArgs.h b/src/CommandLineArgs.h index c856f82..1f1764f 100644 --- a/src/CommandLineArgs.h +++ b/src/CommandLineArgs.h @@ -33,19 +33,28 @@ struct CommandLineArgs { - UINT m_windowWidth{ 1280 }; - UINT m_windowHeight{ 800 }; - UINT m_sampleCount{ 4 }; - float m_lodBias{ 0 }; + enum class PreferredArchitecture + { + NONE = 0, + DISCRETE, + INTEGRATED + }; + PreferredArchitecture m_preferredArchitecture{ PreferredArchitecture::NONE }; + std::wstring m_adapterDescription; // e.g. "intel", will pick the GPU with this substring in the adapter description (not case sensitive) - std::wstring m_textureFilename; - std::wstring m_mediaDir; - bool m_vsyncEnabled{ false }; + bool m_useDirectStorage{ true }; + UINT m_stagingSizeMB{ 128 }; // size of the staging buffer for DirectStorage or reference streaming code std::wstring m_terrainTexture; std::wstring m_skyTexture; std::wstring m_earthTexture; - std::vector m_textures; // textures for things other than the terrain + std::wstring m_mediaDir; + + bool m_vsyncEnabled{ false }; + UINT m_windowWidth{ 1280 }; + UINT m_windowHeight{ 800 }; + UINT m_sampleCount{ 4 }; + float m_lodBias{ 0 }; bool m_startFullScreen{ false }; bool m_cameraRollerCoaster{ false }; @@ -77,16 +86,13 @@ struct CommandLineArgs UINT m_timingStopFrame{ 0 }; std::wstring m_timingFrameFileName; // where to write per-frame statistics std::wstring m_exitImageFileName; // write an image on exit - bool m_waitForAssetLoad{ false }; // wait for assets to load before progressing frame # - std::wstring m_adapterDescription; // e.g. "intel", will pick the GPU with this substring in the adapter description (not case sensitive) - - bool m_useDirectStorage{ false }; - UINT m_stagingSizeMB{ 64 }; // size of the staging buffer for DirectStorage or reference streaming code //------------------------------------------------------- // state that is not settable from command line: //------------------------------------------------------- + std::vector m_textures; // textures for things other than the terrain + UINT m_maxTileUpdatesPerApiCall{ 512 }; // max #tiles (regions) in call to UpdateTileMappings() bool m_enableTileUpdates{ true }; // toggle enabling tile uploads/evictions int m_visualizationBaseMip{ 0 }; diff --git a/src/CreateSphere.h b/src/CreateSphere.h index b0a1e59..46c732d 100644 --- a/src/CreateSphere.h +++ b/src/CreateSphere.h @@ -61,27 +61,23 @@ namespace SphereGen bool repeatEdge = !in_props.m_mirrorU; std::vector vertices; - // compute sphere vertices // skip top and bottom rows (will just use single points) { float dLat = DirectX::XM_PI * 2.0f / in_props.m_numLong; // the number of vertical segments tells you how many horizontal steps to take - float dz = 1.0f / (in_props.m_numLat - 1); // e.g. NumLat = 3, dv = 0.5, v = {0, .5, 1} + float dz = 2.f / (in_props.m_numLat - 1); // du is uniform float du = 1.0f / float(in_props.m_numLong); // u from 0..1 - if (in_props.m_mirrorU) // when mirroring, u from 0..2 - { - du *= 2; - } + if (in_props.m_mirrorU) { du *= 2; } // when mirroring, u from 0..2 for (UINT longitude = 1; longitude < (in_props.m_numLat - 1); longitude++) { float z = dz * longitude; // logarithmic step in z produces smoother poles - if (z < 0.5f) { z = -1 + std::powf(2 * z, in_props.m_exponent); } - else { z = 1 - std::powf(2 - (2 * z), in_props.m_exponent); } + if (z < 1) { z = -1 + std::powf(z, in_props.m_exponent); } + else { z = 1 - std::powf(2 - z, in_props.m_exponent); } // radius of this latitude in x/y plane float r = std::sqrtf(1 - (z * z)); @@ -89,8 +85,6 @@ namespace SphereGen // v is constant for this latitude float v = std::acosf(-z) / DirectX::XM_PI; - //float zs = 1.f - std::fabsf(z); zs = (1 + zs * zs) / 2;// too big at pole, pretty good along equator - //DebugPrint("<", z, ",", zs, ">") // create row of vertices for (UINT lat = 0; lat < in_props.m_numLong; lat++) { @@ -104,31 +98,27 @@ namespace SphereGen // stretch texture across hemisphere. mirrored on other hemisphere. if (in_props.m_topBottom) { - uv = DirectX::XMFLOAT2{ pos.x, pos.y }; - - float s = std::sqrtf(2); // corners touch the equator - - uv.x *= s; - uv.y *= s; + uv = { pos.x, pos.y }; - if (theta > DirectX::XM_PI) { theta -= DirectX::XM_PI; } + // radial scale + if (theta > DirectX::XM_PI) { theta = DirectX::XM_2PI - theta; } if (theta > DirectX::XM_PIDIV2) { theta = DirectX::XM_PI - theta; } - if (theta < DirectX::XM_PIDIV4) + if (theta > DirectX::XM_PIDIV4) { - s = std::cosf(DirectX::XM_PIDIV4) / std::cosf(theta); - s = std::powf(s, r); - uv.x *= s; + float s = std::cosf(DirectX::XM_PIDIV4) / std::cosf(DirectX::XM_PIDIV2 - theta); + uv.y *= (1 - r) + r * s; } else { - s = std::cosf(DirectX::XM_PIDIV4) / std::cosf(DirectX::XM_PIDIV2 - theta); - s = std::powf(s, r); - uv.y *= s; + float s = std::cosf(DirectX::XM_PIDIV4) / std::cosf(theta); + uv.x *= (1 - r) + r * s; } - uv.x *= std::powf(0.6f, std::fabsf(z)); - uv.y *= std::powf(0.6f, std::fabsf(z)); + // z scale + float s = std::powf(0.5f, std::fabsf(z)) * std::sqrtf(2.f); + uv = { uv.x * s, uv.y * s }; + // -1 .. 1 -> 0 .. 1 uv.x = (1 + uv.x) * .5f; uv.y = (1 + uv.y) * .5f; } diff --git a/src/Gui.cpp b/src/Gui.cpp index 8e916f0..0eae980 100644 --- a/src/Gui.cpp +++ b/src/Gui.cpp @@ -300,6 +300,7 @@ void Gui::Draw(ID3D12GraphicsCommandList* in_pCommandList, ImGui::SliderFloat("Camera", &in_args.m_cameraAnimationRate, 0, 2.0f); ImGui::Indent(indent); ImGui::Checkbox("Roller Coaster", &in_args.m_cameraRollerCoaster); + if (ImGui::IsItemHovered()) ImGui::SetTooltip("hotkey: page down"); ImGui::Unindent(indent); } @@ -388,10 +389,13 @@ void Gui::Draw(ID3D12GraphicsCommandList* in_pCommandList, //--------------------------------------------------------------------- // emphasize this important visualization //--------------------------------------------------------------------- - ImVec4 colorMinMip{ 0.4f, 0.2f, 0.8f, 1.0f }; - ImGui::PushStyleColor(ImGuiCol_Button, colorMinMip); - if (ImGui::Button("Tile Min Mip Overlay", ImVec2(-1, 0))) { in_args.m_visualizeMinMip = !in_args.m_visualizeMinMip; } + ImVec4 colorMinMip{ 0.6f, 0.4f, 0.9f, 1.0f }; + ImGui::Indent(indent); + ImGui::PushStyleColor(ImGuiCol_Text, colorMinMip); + ImGui::Checkbox("Tile Min Mip Overlay", &in_args.m_visualizeMinMip); + ImGui::Unindent(indent); ImGui::PopStyleColor(1); + if (ImGui::IsItemHovered()) ImGui::SetTooltip("hotkey: page up"); //--------------------------------------------------------------------- // demo mode diff --git a/src/Scene.cpp b/src/Scene.cpp index 5a39c4f..eb57773 100644 --- a/src/Scene.cpp +++ b/src/Scene.cpp @@ -58,39 +58,88 @@ enum class DescriptorHeapOffsets NumEntries }; +#define ErrorMessage(...) { MessageBox(0, AutoString::Concat(__VA_ARGS__).c_str(), L"Error", MB_OK); exit(-1); } + +//----------------------------------------------------------------------------- +// create device, optionally checking adapter description for e.g. "intel" +//----------------------------------------------------------------------------- +void Scene::CreateDeviceWithName(std::wstring& out_adapterDescription) +{ + auto preferredArchitecture = m_args.m_preferredArchitecture; + std::wstring lowerCaseAdapterDesc = m_args.m_adapterDescription; + + if (lowerCaseAdapterDesc.size()) + { + for (auto& c : lowerCaseAdapterDesc) { c = ::towlower(c); } + } + + ComPtr adapter; + for (UINT i = 0; m_factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; ++i) + { + DXGI_ADAPTER_DESC1 desc{}; + adapter->GetDesc1(&desc); + + if ((desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) || (std::wstring(L"Microsoft Basic Render Driver") == desc.Description)) + { + continue; + } + + if (lowerCaseAdapterDesc.size()) + { + std::wstring description(desc.Description); + for (auto& c : description) { c = ::towlower(c); } + std::size_t found = description.find(lowerCaseAdapterDesc); + if (found == std::string::npos) + { + continue; + } + } + + D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(&m_device)); + + // if we care about adapter architecture, check that UMA corresponds to integrated vs. discrete + if (CommandLineArgs::PreferredArchitecture::NONE != preferredArchitecture) + { + D3D12_FEATURE_DATA_ARCHITECTURE archFeatures{}; + m_device->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &archFeatures, sizeof(archFeatures)); + + if (((FALSE == archFeatures.UMA) && (CommandLineArgs::PreferredArchitecture::INTEGRATED == preferredArchitecture)) || + ((TRUE == archFeatures.UMA) && (CommandLineArgs::PreferredArchitecture::DISCRETE == preferredArchitecture))) + { + // adapter does not match requirements (name and/or architecture) + m_device = nullptr; + continue; + } + } + + // adapter matches requirements (name and/or architecture), exit loop + break; + } + + // get the description from whichever adapter was used to create the device + if (nullptr != m_device.Get()) + { + DXGI_ADAPTER_DESC1 desc{}; + adapter->GetDesc1(&desc); + out_adapterDescription = desc.Description; + } + else + { + ErrorMessage("No adapter found with name \"", m_args.m_adapterDescription, "\" or architecture \"", + (CommandLineArgs::PreferredArchitecture::NONE == preferredArchitecture ? "none" : + (CommandLineArgs::PreferredArchitecture::DISCRETE == preferredArchitecture ? "discrete" : "integrated")), + "\"\n"); + } +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- Scene::Scene(const CommandLineArgs& in_args, HWND in_hwnd) : - m_args(in_args) - , m_hwnd(in_hwnd) - , m_windowInfo{} - , m_windowedSupportsTearing(false) - , m_deviceRemoved(false) - , m_frameIndex(0) - , m_renderFenceValue(0) - , m_frameFenceValues{} - , m_renderFenceEvent(0) - , m_rtvDescriptorSize(0) - , m_srvUavCbvDescriptorSize(0) - , m_dsvDescriptorSize(0) - , m_aspectRatio(0) - , m_pFrameConstantData(nullptr) - - // visuals - , m_pGui(nullptr) - , m_pTextureViewer(nullptr) - , m_pMinMipMapViewer(nullptr) - , m_pFeedbackViewer(nullptr) - , m_pFrustumViewer(nullptr) - - // thread - , m_queueFeedbackIndex(0) + m_args(in_args), m_hwnd(in_hwnd) + , m_frameFenceValues(m_swapBufferCount, 0) , m_prevNumFeedbackObjects(SharedConstants::SWAP_CHAIN_BUFFER_COUNT, 1) - - // statistics , m_renderThreadTimes(in_args.m_statisticsNumFrames) , m_updateFeedbackTimes(in_args.m_statisticsNumFrames) - , m_pGpuTimer(nullptr) { m_windowInfo.cbSize = sizeof(WINDOWINFO); @@ -107,46 +156,17 @@ Scene::Scene(const CommandLineArgs& in_args, HWND in_hwnd) : ThrowIfFailed(CreateDXGIFactory2(factoryFlags, IID_PPV_ARGS(&m_factory))); } - ComPtr adapter; - DXGI_ADAPTER_DESC1 desc; - if (m_args.m_adapterDescription.size()) - { - std::wstring lowerCaseAdapterDesc = m_args.m_adapterDescription; - for (auto& c : lowerCaseAdapterDesc) { c = ::towlower(c); } + std::wstring adapterDescription = m_args.m_adapterDescription; + CreateDeviceWithName(adapterDescription); - for (UINT i = 0; m_factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; ++i) - { - ThrowIfFailed(adapter->GetDesc1(&desc)); - std::wstring description(desc.Description); - for (auto& c : description) { c = ::towlower(c); } - std::size_t found = description.find(lowerCaseAdapterDesc); - if (found != std::string::npos) - { - break; - } - } - } - else - { - ThrowIfFailed(m_factory->EnumAdapters1(0, &adapter)); - ThrowIfFailed(adapter->GetDesc1(&desc)); - } - std::wstring adapterDescription = desc.Description; // does this device support sampler feedback? D3D12_FEATURE_DATA_D3D12_OPTIONS7 feedbackOptions{}; - HRESULT hr = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(&m_device)); - if (SUCCEEDED(hr)) - { - m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, &feedbackOptions, sizeof(feedbackOptions)); - } + m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, &feedbackOptions, sizeof(feedbackOptions)); if (0 == feedbackOptions.SamplerFeedbackTier) { - std::wstring msg = L"Sampler Feedback not supported by\n"; - msg += adapterDescription; - MessageBox(0, msg.c_str(), L"Error", MB_OK); - exit(-1); + ErrorMessage(L"Sampler Feedback not supported by ", adapterDescription); } D3D12_FEATURE_DATA_D3D12_OPTIONS tileOptions{}; @@ -154,10 +174,7 @@ Scene::Scene(const CommandLineArgs& in_args, HWND in_hwnd) : if (0 == tileOptions.TiledResourcesTier) { - std::wstring msg = L"Tiled Resources not supported by\n"; - msg += adapterDescription; - MessageBox(0, msg.c_str(), L"Error", MB_OK); - exit(-1); + ErrorMessage(L"Tiled Resources not supported by ", adapterDescription); } m_pGpuTimer = new D3D12GpuTimer(m_device.Get(), 8, D3D12GpuTimer::TimerType::Direct); @@ -176,7 +193,7 @@ Scene::Scene(const CommandLineArgs& in_args, HWND in_hwnd) : CreateCommandQueue(); CreateSwapChain(); CreateFence(); - + StartStreamingLibrary(); CreateSampler(); @@ -222,7 +239,7 @@ Scene::~Scene() delete m_pGpuTimer; delete m_pGui; - + DeleteTerrainViewers(); delete m_pFrustumViewer; @@ -666,7 +683,7 @@ void Scene::StartStreamingLibrary() tumDesc.m_useDirectStorage = m_args.m_useDirectStorage; m_pTileUpdateManager = TileUpdateManager::Create(m_device.Get(), m_commandQueue.Get(), tumDesc); - + // create 1 or more heaps to contain our StreamingResources for (UINT i = 0; i < m_args.m_numHeaps; i++) { @@ -701,8 +718,7 @@ XMMATRIX Scene::SetSphereMatrix() } else { - MessageBox(0, L"Failed to fit planet in universe. Universe too small?", L"ERROR", MB_OK); - exit(-1); + ErrorMessage("Failed to fit planet in universe. Universe too small?"); } float sphereScale = scaleDis(gen) * SharedConstants::SPHERE_SCALE; @@ -714,9 +730,9 @@ XMMATRIX Scene::SetSphereMatrix() // position sphere far from terrain x += (MAX_SPHERE_SIZE + 2) * SharedConstants::SPHERE_SCALE; - float rx = (2*XM_PI) * dis(gen); - float ry = (2*XM_PI) * dis(gen); - float rz = (2*XM_PI) * dis(gen); + float rx = (2 * XM_PI) * dis(gen); + float ry = (2 * XM_PI) * dis(gen); + float rz = (2 * XM_PI) * dis(gen); XMMATRIX xlate = XMMatrixTranslation(x, 0, 0); XMMATRIX rtate = XMMatrixRotationRollPitchYaw(rx, ry, rz); @@ -776,6 +792,20 @@ void Scene::LoadSpheres() const UINT numSpheresToLoad = m_args.m_numSpheres - m_numSpheresLoaded; + // is there a sky? + std::wstring skyTexture; + if (m_args.m_skyTexture.size()) + { + for (auto& n : m_args.m_textures) + { + if (std::wstring::npos != n.find(m_args.m_skyTexture)) + { + skyTexture = n; + break; + } + } + } + UINT textureIndex = 0; for (UINT i = 0; i < numSpheresToLoad; i++) { @@ -801,12 +831,13 @@ void Scene::LoadSpheres() // 3 options: sphere, earth, sky - // sky has to be first because it disables depth when drawn - if ((nullptr == m_pSky) && (m_args.m_skyTexture.size())) // only 1 sky + // only 1 sky, and it must be first because it disables depth when drawn + if ((nullptr == m_pSky) && (skyTexture.size())) { - auto tf = m_args.m_mediaDir + L"\\\\" + m_args.m_skyTexture; - m_pSky = new SceneObjects::Sky(tf, m_pTileUpdateManager, pHeap, m_device.Get(), m_assetUploader, m_args.m_sampleCount, descCPU); + m_pSky = new SceneObjects::Sky(skyTexture, m_pTileUpdateManager, pHeap, m_device.Get(), m_assetUploader, m_args.m_sampleCount, descCPU); o = m_pSky; + float scale = SharedConstants::UNIVERSE_SIZE * 2; + o->GetModelMatrix() = DirectX::XMMatrixScaling(scale, scale, scale); } else if (nullptr == m_pTerrainSceneObject) @@ -1000,7 +1031,7 @@ void Scene::CreateConstantBuffers() m_pFrameConstantData->g_lightDir = XMFLOAT4(-0.538732767f, 0.787301660f, 0.299871892f, 0); XMStoreFloat4(&m_pFrameConstantData->g_lightDir, XMVector4Normalize(XMLoadFloat4(&m_pFrameConstantData->g_lightDir))); m_pFrameConstantData->g_lightColor = XMFLOAT4(1, 1, 1, 1); - m_pFrameConstantData->g_specularColor = XMFLOAT4(1, 1, 1, 18.f); + m_pFrameConstantData->g_specularColor = XMFLOAT4(1, 1, 1, 50.f); D3D12_CONSTANT_BUFFER_VIEW_DESC constantBufferView = {}; constantBufferView.SizeInBytes = bufferSize; @@ -1257,12 +1288,13 @@ void Scene::GatherStatistics() m_csvFile->WriteEvents(m_hwnd, m_args); *m_csvFile - << measuredNumUploads + << "bandwidth_MB/s #uploads seconds latency_ms #submits\n" + << mbps + << " " << measuredNumUploads << " " << measuredTime - << " " << mbps << " " << approximatePerTileLatency << " " << m_pTileUpdateManager->GetTotalNumSubmits() - m_startSubmitCount - << " uploads|seconds|bandwidth|latency_ms|#submits\n"; + << "\n"; m_csvFile->close(); m_csvFile = nullptr; } diff --git a/src/Scene.h b/src/Scene.h index f10b47d..0477fa9 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -65,7 +65,6 @@ class Scene void ToggleFrustum() { m_args.m_visualizeFrustum = !m_args.m_visualizeFrustum; HandleUiToggleFrustum(); } - void ToggleUpLock() { m_args.m_cameraUpLock = !m_args.m_cameraUpLock; } void ToggleAnimation() { static float animationRate = 0; @@ -100,24 +99,24 @@ class Scene CommandLineArgs m_args; - const HWND m_hwnd; - WINDOWINFO m_windowInfo; - bool m_windowedSupportsTearing; - bool m_deviceRemoved; // when true, resize and draw immediately exit, returning false if appicable + const HWND m_hwnd{ nullptr }; + WINDOWINFO m_windowInfo{}; + bool m_windowedSupportsTearing{ false }; + bool m_deviceRemoved{ false }; // when true, resize and draw immediately exit, returning false if appicable ComPtr m_factory; ComPtr m_adapter; ComPtr m_device; ComPtr m_commandQueue; - static const UINT m_swapBufferCount = SharedConstants::SWAP_CHAIN_BUFFER_COUNT; + static const UINT m_swapBufferCount{ SharedConstants::SWAP_CHAIN_BUFFER_COUNT }; static const FLOAT m_clearColor[4]; ComPtr m_swapChain; - UINT m_frameIndex; // comes from swap chain - UINT64 m_renderFenceValue; // also serves as a frame count - UINT64 m_frameFenceValues[m_swapBufferCount]; + UINT m_frameIndex{ 0 }; // comes from swap chain + UINT64 m_renderFenceValue{ 0 }; // also serves as a frame count + std::vector m_frameFenceValues; ComPtr m_renderFence; - HANDLE m_renderFenceEvent; + HANDLE m_renderFenceEvent{ NULL }; // used for animation or statistics gathering // e.g. rotate by radians*m_framenumber @@ -136,14 +135,14 @@ class Scene ComPtr m_dsvHeap; ComPtr m_rtvHeap; - UINT m_rtvDescriptorSize; - UINT m_srvUavCbvDescriptorSize; - UINT m_dsvDescriptorSize; + UINT m_rtvDescriptorSize{ 0 }; + UINT m_srvUavCbvDescriptorSize{ 0 }; + UINT m_dsvDescriptorSize{ 0 }; DirectX::XMMATRIX m_projection; DirectX::XMMATRIX m_viewMatrix; DirectX::XMMATRIX m_viewMatrixInverse; - float m_aspectRatio; + float m_aspectRatio{ 0 }; const float m_fieldOfView{ DirectX::XM_PI / 6.0f }; CD3DX12_VIEWPORT m_viewport; @@ -159,16 +158,16 @@ class Scene int g_visualizeFeedback; }; - FrameConstantData* m_pFrameConstantData; // left in the mapped state + FrameConstantData* m_pFrameConstantData{ nullptr }; // left in the mapped state ComPtr m_frameConstantBuffer; - Gui* m_pGui; + Gui* m_pGui{ nullptr }; Gui::ButtonChanges m_uiButtonChanges; // track changes in UI settings - class TextureViewer* m_pTextureViewer; - class BufferViewer* m_pMinMipMapViewer; - class BufferViewer* m_pFeedbackViewer; - class FrustumViewer* m_pFrustumViewer; + class TextureViewer* m_pTextureViewer{ nullptr }; + class BufferViewer* m_pMinMipMapViewer{ nullptr }; + class BufferViewer* m_pFeedbackViewer{ nullptr }; + class FrustumViewer* m_pFrustumViewer{ nullptr }; void MsaaResolve(); @@ -220,7 +219,7 @@ class Scene void LoadSpheres(); // progressively over multiple frames // each frame, update objects until timeout reached - UINT m_queueFeedbackIndex; // index based on number of gpu feedback resolves per frame + UINT m_queueFeedbackIndex{ 0 }; // index based on number of gpu feedback resolves per frame std::vector m_prevNumFeedbackObjects; // to correlate # objects with feedback time //----------------------------------- @@ -228,7 +227,7 @@ class Scene //----------------------------------- FrameEventTracing::RenderEventList m_renderThreadTimes; FrameEventTracing::UpdateEventList m_updateFeedbackTimes; - class D3D12GpuTimer* m_pGpuTimer; + class D3D12GpuTimer* m_pGpuTimer { nullptr }; std::unique_ptr m_csvFile{ nullptr }; float m_gpuProcessFeedbackTime{ 0 }; @@ -258,5 +257,7 @@ class Scene void DrawUI(); void HandleUiToggleFrustum(); + void CreateDeviceWithName(std::wstring& out_adapterDescription); + AssetUploader m_assetUploader; }; diff --git a/src/SceneObject.cpp b/src/SceneObject.cpp index 00c8f9d..012b791 100644 --- a/src/SceneObject.cpp +++ b/src/SceneObject.cpp @@ -533,9 +533,6 @@ SceneObjects::Planet::Planet(const std::wstring& in_filename, const UINT numLevelsOfDetail = SharedConstants::NUM_SPHERE_LEVELS_OF_DETAIL; CreateSphere(this, in_pDevice, in_assetUploader, in_sphereProperties, numLevelsOfDetail); - - float d = SharedConstants::SPHERE_SCALE * 200; - GetModelMatrix() = DirectX::XMMatrixScaling(d, d, d); } //------------------------------------------------------------------------- @@ -580,8 +577,6 @@ SceneObjects::Sky::Sky(const std::wstring& in_filename, sphereProperties.m_mirrorU = true; sphereProperties.m_topBottom = true; CreateSphere(this, in_pDevice, in_assetUploader, sphereProperties); - float d = SharedConstants::SPHERE_SCALE * 200; - GetModelMatrix() = DirectX::XMMatrixScaling(d, d, d); } //------------------------------------------------------------------------- diff --git a/src/shaders/terrainPS.hlsl b/src/shaders/terrainPS.hlsl index 9c12913..80da358 100644 --- a/src/shaders/terrainPS.hlsl +++ b/src/shaders/terrainPS.hlsl @@ -48,9 +48,9 @@ float3 evaluateLight(in float3 normal, in float3 pos) float ambient = 0.1f; - float3 color = (diffuse * g_lightColor.xyz) + (specular * g_specularColor.xyz) + ambient; + float3 color = (.9f * diffuse * g_lightColor.xyz) + (specular * g_specularColor.xyz) + ambient; - color = pow(color, 1.0f / 2.0f); + color = pow(color, 1.0f / 1.5f); return color; } diff --git a/src/winMain.cpp b/src/winMain.cpp index cfbae16..a62fa70 100644 --- a/src/winMain.cpp +++ b/src/winMain.cpp @@ -87,6 +87,24 @@ struct MouseState // load arguments from a config file void LoadConfigFile(std::wstring& in_configFileName, CommandLineArgs& out_args); +//----------------------------------------------------------------------------- +// check an incoming path. if not found, try relative to exe. if found, replace parameter +//----------------------------------------------------------------------------- +void CorrectPath(std::wstring& inout_path) +{ + if (!std::filesystem::exists(inout_path)) + { + WCHAR buffer[MAX_PATH]; + GetModuleFileName(nullptr, buffer, MAX_PATH); + std::filesystem::path exePath(buffer); + exePath.remove_filename().append(inout_path); + if (std::filesystem::exists(exePath)) + { + inout_path = exePath; + } + } +} + //----------------------------------------------------------------------------- // apply limits arguments // e.g. # spheres, path to terrain texture @@ -98,16 +116,6 @@ void AdjustArguments(CommandLineArgs& out_args) out_args.m_sampleCount = std::min(out_args.m_sampleCount, (UINT)D3D12_MAX_MULTISAMPLE_SAMPLE_COUNT); out_args.m_anisotropy = std::min(out_args.m_anisotropy, (UINT)D3D12_REQ_MAXANISOTROPY); - // override: use this texture for everything. no sky. - if (out_args.m_textureFilename.size()) - { - out_args.m_mediaDir.clear(); - out_args.m_skyTexture.clear(); - out_args.m_terrainTexture = out_args.m_textureFilename; - out_args.m_textures.clear(); - out_args.m_textures.push_back(out_args.m_textureFilename); - } - // if there's a media directory, sky and earth are relative to media if (out_args.m_mediaDir.size()) { @@ -117,18 +125,7 @@ void AdjustArguments(CommandLineArgs& out_args) out_args.m_mediaDir += L'\\'; } - // if the desired media path doesn't exist, try looking relative to the executable - if (!std::filesystem::exists(out_args.m_mediaDir)) - { - WCHAR buffer[MAX_PATH]; - GetModuleFileName(nullptr, buffer, MAX_PATH); - std::filesystem::path exePath(buffer); - exePath.remove_filename().append(out_args.m_mediaDir); - if (std::filesystem::exists(exePath)) - { - out_args.m_mediaDir = exePath; - } - } + CorrectPath(out_args.m_mediaDir); if (std::filesystem::exists(out_args.m_mediaDir)) { @@ -144,13 +141,10 @@ void AdjustArguments(CommandLineArgs& out_args) } } - // media directory overrides textureFilename - out_args.m_textureFilename = out_args.m_textures[0]; - // no terrain texture set or not found? set to something. if ((0 == out_args.m_terrainTexture.size()) || (!std::filesystem::exists(out_args.m_terrainTexture))) { - out_args.m_terrainTexture = out_args.m_textureFilename; + out_args.m_terrainTexture = out_args.m_textures[0]; } } else @@ -180,7 +174,16 @@ void ParseCommandLine(CommandLineArgs& out_args) argParser.AddArg(L"-LodBias", out_args.m_lodBias); argParser.AddArg(L"-animationrate", out_args.m_animationRate); - argParser.AddArg(L"-texture", out_args.m_textureFilename); + argParser.AddArg(L"-texture", + [&] { + out_args.m_mediaDir.clear(); + out_args.m_skyTexture.clear(); + out_args.m_textures.clear(); + std::wstring textureFileName = ArgParser::GetNextArg(); + CorrectPath(textureFileName); + out_args.m_terrainTexture = textureFileName; + out_args.m_textures.push_back(textureFileName); + }, "use only one texture, with this name"); argParser.AddArg(L"-vsync", out_args.m_vsyncEnabled); argParser.AddArg(L"-heapSizeTiles", out_args.m_streamingHeapSize); @@ -214,7 +217,9 @@ void ParseCommandLine(CommandLineArgs& out_args) argParser.AddArg(L"-exitImageFile", out_args.m_exitImageFileName); argParser.AddArg(L"-waitForAssetLoad", out_args.m_waitForAssetLoad, L"stall animation & statistics until assets have minimally loaded"); + argParser.AddArg(L"-adapter", out_args.m_adapterDescription, L"find an adapter containing this string in the description, ignoring case"); + argParser.AddArg(L"-arch", (UINT&)out_args.m_preferredArchitecture, L"none (0), discrete (1), integrated (2)"); argParser.AddArg(L"-directStorage", [&]() { out_args.m_useDirectStorage = true; }, L"force enable DirectStorage"); argParser.AddArg(L"-directStorageOff", [&]() { out_args.m_useDirectStorage = false; }, L"force disable DirectStorage"); @@ -354,10 +359,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) g_keyState.key.rotzr = 1; break; - case 'X': - g_pScene->ToggleUpLock(); - break; - case '1': g_pScene->SetVisualizationMode(CommandLineArgs::VisualizationMode::TEXTURE); break; @@ -453,13 +454,12 @@ void LoadConfigFile(std::wstring& in_configFileName, CommandLineArgs& out_args) { bool success = false; - WCHAR buffer[MAX_PATH]; - GetModuleFileName(nullptr, buffer, MAX_PATH); - std::filesystem::path filePath(buffer); - filePath.remove_filename().append(in_configFileName); - if (std::filesystem::exists(filePath)) + CorrectPath(in_configFileName); + + if (std::filesystem::exists(in_configFileName)) { - const ConfigurationParser parser(filePath); + const ConfigurationParser parser(in_configFileName); + success = parser.GetReadSuccess(); if (success) @@ -482,7 +482,6 @@ void LoadConfigFile(std::wstring& in_configFileName, CommandLineArgs& out_args) if (root.isMember("rollerCoaster")) out_args.m_cameraRollerCoaster = root["rollerCoaster"].asBool(); if (root.isMember("paintMixer")) out_args.m_cameraRollerCoaster = root["paintMixer"].asBool(); - if (root.isMember("texture")) out_args.m_textureFilename = StrToWstr(root["texture"].asString()); if (root.isMember("mediaDir")) out_args.m_mediaDir = StrToWstr(root["mediaDir"].asString()); if (root.isMember("terrainTexture")) out_args.m_terrainTexture = StrToWstr(root["terrainTexture"].asString()); if (root.isMember("skyTexture")) out_args.m_skyTexture = StrToWstr(root["skyTexture"].asString()); @@ -532,7 +531,7 @@ void LoadConfigFile(std::wstring& in_configFileName, CommandLineArgs& out_args) if (!success) { std::wstring msg(L"Invalid Configuration file path: "); - msg += filePath; + msg += in_configFileName; MessageBox(0, msg.c_str(), L"ERROR", MB_OK); exit(-1); } @@ -551,9 +550,11 @@ int WINAPI WinMain( _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif + // load default configuration CommandLineArgs args; LoadConfigFile(g_configFileName, args); + // command line can load a different configuration file, overriding part or all of the default config ParseCommandLine(args); // apply limits and other constraints diff --git a/tracePlayer/tracePlayer.cpp b/tracePlayer/tracePlayer.cpp index ff5ea0a..4c82cf3 100644 --- a/tracePlayer/tracePlayer.cpp +++ b/tracePlayer/tracePlayer.cpp @@ -62,25 +62,19 @@ //----------------------------------------------------------------------------- void FindPath(std::wstring& out_path) { - std::wstring inPath = std::filesystem::path(out_path); - - WCHAR buffer[MAX_PATH]; - GetModuleFileName(nullptr, buffer, MAX_PATH); - std::filesystem::path exePath(buffer); - exePath.remove_filename(); - // if the desired media path doesn't exist, try looking relative to the executable - if (!std::filesystem::exists(inPath)) + if (!std::filesystem::exists(out_path)) { - std::filesystem::path testPath = exePath; - testPath.append(inPath); - if (std::filesystem::exists(testPath)) + WCHAR buffer[MAX_PATH]; + GetModuleFileName(nullptr, buffer, _countof(buffer)); + auto path = std::filesystem::path(buffer).remove_filename().append(out_path); + if (std::filesystem::exists(path)) { - out_path = testPath; + out_path = path; } else { - ErrorMessage("Path not found: \"", inPath, "\" also tried: ", testPath); + ErrorMessage("Path not found: \"", out_path, "\" also tried: ", path); } } } @@ -235,8 +229,6 @@ ID3D12Resource* TracePlayer::CreateDestinationResource(UINT& out_numTiles, DXGI_ // this will only ever be a copy dest ID3D12Resource* pResource{ nullptr }; ThrowIfFailed(m_device->CreateReservedResource(&rd, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&pResource))); - - std::vector tiling(in_subresourceCount); m_device->GetResourceTiling(pResource, &out_numTiles, nullptr, nullptr, nullptr, 0, nullptr); return pResource; @@ -295,7 +287,7 @@ void TracePlayer::LoadTraceFile() //--------------------------------- { const auto& resources = traceFile.GetRoot()["resources"]; - UINT numTilesTotal{ 0 }; + UINT64 numTilesTotal{ 0 }; std::vector tilesPerResource; for (const auto& r : resources) { @@ -310,7 +302,7 @@ void TracePlayer::LoadTraceFile() tilesPerResource.push_back(numTiles); } - UINT heapSize = numTilesTotal * D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES; + UINT64 heapSize = numTilesTotal * D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES; CD3DX12_HEAP_DESC heapDesc(heapSize, D3D12_HEAP_TYPE_DEFAULT, 0, D3D12_HEAP_FLAG_DENY_BUFFERS | D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES); ThrowIfFailed(m_device->CreateHeap(&heapDesc, IID_PPV_ARGS(&m_heap))); UINT tileOffset = 0;