diff --git a/DdsToXet/DdsToXet_vs2022.vcxproj b/DdsToXet/DdsToXet_vs2022.vcxproj new file mode 100644 index 0000000..c08587c --- /dev/null +++ b/DdsToXet/DdsToXet_vs2022.vcxproj @@ -0,0 +1,91 @@ + + + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {369039e2-4c18-40d9-a7fe-e3d87ba23149} + DssToXet + 10.0 + DdsToXet + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + \ No newline at end of file diff --git a/DdsToXet/DdsToXet_vs2022.vcxproj.filters b/DdsToXet/DdsToXet_vs2022.vcxproj.filters new file mode 100644 index 0000000..6875de2 --- /dev/null +++ b/DdsToXet/DdsToXet_vs2022.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/DirectXTK12/DXSampleHelper.h b/DirectXTK12/DXSampleHelper.h deleted file mode 100644 index 9ff5791..0000000 --- a/DirectXTK12/DXSampleHelper.h +++ /dev/null @@ -1,253 +0,0 @@ -//********************************************************* -// -// Copyright (c) Microsoft. All rights reserved. -// This code is licensed under the MIT License (MIT). -// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF -// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY -// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR -// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. -// -//********************************************************* - -#pragma once -#include - -// Note that while ComPtr is used to manage the lifetime of resources on the CPU, -// it has no understanding of the lifetime of resources on the GPU. Apps must account -// for the GPU lifetime of resources to avoid destroying objects that may still be -// referenced by the GPU. -//using Microsoft::WRL::ComPtr; - -inline std::string HrToString(HRESULT hr) -{ - char s_str[64] = {}; - sprintf_s(s_str, "HRESULT of 0x%08X", static_cast(hr)); - return std::string(s_str); -} - -class HrException : public std::runtime_error -{ -public: - HrException(HRESULT hr) : std::runtime_error(HrToString(hr)), m_hr(hr) {} - HRESULT Error() const { return m_hr; } -private: - const HRESULT m_hr; -}; - -#define SAFE_RELEASE(p) if (p) (p)->Release() - -inline void ThrowIfFailed(HRESULT hr) -{ - if (FAILED(hr)) - { - throw HrException(hr); - } -} - -inline void GetAssetsPath(_Out_writes_(pathSize) WCHAR* path, UINT pathSize) -{ - if (path == nullptr) - { - throw std::exception(); - } - - DWORD size = GetModuleFileName(nullptr, path, pathSize); - if (size == 0 || size == pathSize) - { - // Method failed or path was truncated. - throw std::exception(); - } - - WCHAR* lastSlash = wcsrchr(path, L'\\'); - if (lastSlash) - { - *(lastSlash + 1) = L'\0'; - } -} - -inline HRESULT ReadDataFromFile(LPCWSTR filename, byte** data, UINT* size) -{ - using namespace Microsoft::WRL; - -#if WINVER >= _WIN32_WINNT_WIN8 - CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {}; - extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); - extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; - extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN; - extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS; - extendedParams.lpSecurityAttributes = nullptr; - extendedParams.hTemplateFile = nullptr; - - Wrappers::FileHandle file(CreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, &extendedParams)); -#else - Wrappers::FileHandle file(CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS, nullptr)); -#endif - if (file.Get() == INVALID_HANDLE_VALUE) - { - throw std::exception(); - } - - FILE_STANDARD_INFO fileInfo = {}; - if (!GetFileInformationByHandleEx(file.Get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) - { - throw std::exception(); - } - - if (fileInfo.EndOfFile.HighPart != 0) - { - throw std::exception(); - } - - *data = reinterpret_cast(malloc(fileInfo.EndOfFile.LowPart)); - *size = fileInfo.EndOfFile.LowPart; - - if (!ReadFile(file.Get(), *data, fileInfo.EndOfFile.LowPart, nullptr, nullptr)) - { - throw std::exception(); - } - - return S_OK; -} - -inline HRESULT ReadDataFromDDSFile(LPCWSTR filename, byte** data, UINT* offset, UINT* size) -{ - if (FAILED(ReadDataFromFile(filename, data, size))) - { - return E_FAIL; - } - - // DDS files always start with the same magic number. - static const UINT DDS_MAGIC = 0x20534444; - UINT magicNumber = *reinterpret_cast(*data); - if (magicNumber != DDS_MAGIC) - { - return E_FAIL; - } - - struct DDS_PIXELFORMAT - { - UINT size; - UINT flags; - UINT fourCC; - UINT rgbBitCount; - UINT rBitMask; - UINT gBitMask; - UINT bBitMask; - UINT aBitMask; - }; - - struct DDS_HEADER - { - UINT size; - UINT flags; - UINT height; - UINT width; - UINT pitchOrLinearSize; - UINT depth; - UINT mipMapCount; - UINT reserved1[11]; - DDS_PIXELFORMAT ddsPixelFormat; - UINT caps; - UINT caps2; - UINT caps3; - UINT caps4; - UINT reserved2; - }; - - auto ddsHeader = reinterpret_cast(*data + sizeof(UINT)); - if (ddsHeader->size != sizeof(DDS_HEADER) || ddsHeader->ddsPixelFormat.size != sizeof(DDS_PIXELFORMAT)) - { - return E_FAIL; - } - - const ptrdiff_t ddsDataOffset = sizeof(UINT) + sizeof(DDS_HEADER); - *offset = ddsDataOffset; - *size = *size - ddsDataOffset; - - return S_OK; -} - -// Assign a name to the object to aid with debugging. -#if defined(_DEBUG) || defined(DBG) -inline void SetName(ID3D12Object* pObject, LPCWSTR name) -{ - pObject->SetName(name); -} -inline void SetNameIndexed(ID3D12Object* pObject, LPCWSTR name, UINT index) -{ - WCHAR fullName[50]; - if (swprintf_s(fullName, L"%s[%u]", name, index) > 0) - { - pObject->SetName(fullName); - } -} -#else -inline void SetName(ID3D12Object*, LPCWSTR) -{ -} -inline void SetNameIndexed(ID3D12Object*, LPCWSTR, UINT) -{ -} -#endif - -// Naming helper for ComPtr. -// Assigns the name of the variable as the name of the object. -// The indexed variant will include the index in the name of the object. -#define NAME_D3D12_OBJECT(x) SetName((x).Get(), L#x) -#define NAME_D3D12_OBJECT_INDEXED(x, n) SetNameIndexed((x)[n].Get(), L#x, n) - -inline UINT CalculateConstantBufferByteSize(UINT byteSize) -{ - // Constant buffer size is required to be aligned. - return (byteSize + (D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1)) & ~(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1); -} - -#ifdef D3D_COMPILE_STANDARD_FILE_INCLUDE -inline Microsoft::WRL::ComPtr CompileShader( - const std::wstring& filename, - const D3D_SHADER_MACRO* defines, - const std::string& entrypoint, - const std::string& target) -{ - UINT compileFlags = 0; -#if defined(_DEBUG) || defined(DBG) - compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; -#endif - - HRESULT hr; - - Microsoft::WRL::ComPtr byteCode = nullptr; - Microsoft::WRL::ComPtr errors; - hr = D3DCompileFromFile(filename.c_str(), defines, D3D_COMPILE_STANDARD_FILE_INCLUDE, - entrypoint.c_str(), target.c_str(), compileFlags, 0, &byteCode, &errors); - - if (errors != nullptr) - { - OutputDebugStringA((char*)errors->GetBufferPointer()); - } - ThrowIfFailed(hr); - - return byteCode; -} -#endif - -// Resets all elements in a ComPtr array. -template -void ResetComPtrArray(T* comPtrArray) -{ - for (auto &i : *comPtrArray) - { - i.Reset(); - } -} - - -// Resets all elements in a unique_ptr array. -template -void ResetUniquePtrArray(T* uniquePtrArray) -{ - for (auto &i : *uniquePtrArray) - { - i.reset(); - } -} diff --git a/README.md b/README.md index 8e31ede..e26c2b7 100644 --- a/README.md +++ b/README.md @@ -28,20 +28,14 @@ Test textures are provided, as is a mechanism to convert from BCx format DDS fil Download the source. Build the solution file [SamplerFeedbackStreaming.sln](SamplerFeedbackStreaming.sln) (tested with Visual Studio 2019). -All executables, scripts, configurations, and media files will be found in the x64/Release or x64/Debug directories. - -To run within Visual Studio, change the working directory to $(TargetDir) under Properties/Debugging: - -![set working directory to $(TargetDir)](./readme-images/project-settings.png "set Working Directory to \$(TargetDir)") - -Or cd to the build directory (x64/Release or x64/Debug) and run from the command line: +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. ![default startup](./readme-images/default-startup.jpg "default startup") -The batch file _demo.bat_ loads the maximum number of planets (number specified in the config file). Keyboard controls are inactive while _Camera_ animation 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 _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. c:\SamplerFeedbackStreaming\x64\Release> demo.bat @@ -297,6 +291,8 @@ ID3D12CommandList* pCommandLists[] = { commandLists.m_beforeDrawCommands, m_comm - 2021-12-03: added BC1 asset collection as "release 2." All texture assets (.xet files) can reside in the same directory despite format differences, and can co-exist in the same GPU heap. Also minor source tweaks, including fix to not cull base "terrain" object. - 2021-12-15: "-addAliasingBarriers" command line option to add an aliasing barrier to assist PIX analysis. Can also be enabled in config.json. - 2022-01-19: eliminated aliasing barrier perf cost (still requires command line/config to enable). config file parser fixes. terrain texture not applied to planets for prettier out-of-box demo experience. +- 2022-03-14: DirectStorage integrated into mainline +- 2022-05-05: Workaround for rare race condition. Many tweaks and improvements. ## License diff --git a/SamplerFeedbackStreaming_vs2022.sln b/SamplerFeedbackStreaming_vs2022.sln new file mode 100644 index 0000000..358aeb8 --- /dev/null +++ b/SamplerFeedbackStreaming_vs2022.sln @@ -0,0 +1,52 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32228.430 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imgui", "imgui\imgui_vs2022.vcxproj", "{45087328-C272-4BB6-BB09-95D899D2276A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TileUpdateManager", "TileUpdateManager\TileUpdateManager_vs2022.vcxproj", "{12A36A45-4A15-48E3-B886-257E81FD57C6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{EB9EA81E-AD7B-4F2F-B8A9-AFC9282303C9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DdsToXet", "DdsToXet\DdsToXet_vs2022.vcxproj", "{369039E2-4C18-40D9-A7FE-E3D87BA23149}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Expanse", "src\Expanse_vs2022.vcxproj", "{E9BCC846-C1E9-402F-AC99-0E72195202AC}" + ProjectSection(ProjectDependencies) = postProject + {45087328-C272-4BB6-BB09-95D899D2276A} = {45087328-C272-4BB6-BB09-95D899D2276A} + {12A36A45-4A15-48E3-B886-257E81FD57C6} = {12A36A45-4A15-48E3-B886-257E81FD57C6} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {45087328-C272-4BB6-BB09-95D899D2276A}.Debug|x64.ActiveCfg = Debug|x64 + {45087328-C272-4BB6-BB09-95D899D2276A}.Debug|x64.Build.0 = Debug|x64 + {45087328-C272-4BB6-BB09-95D899D2276A}.Release|x64.ActiveCfg = Release|x64 + {45087328-C272-4BB6-BB09-95D899D2276A}.Release|x64.Build.0 = Release|x64 + {12A36A45-4A15-48E3-B886-257E81FD57C6}.Debug|x64.ActiveCfg = Debug|x64 + {12A36A45-4A15-48E3-B886-257E81FD57C6}.Debug|x64.Build.0 = Debug|x64 + {12A36A45-4A15-48E3-B886-257E81FD57C6}.Release|x64.ActiveCfg = Release|x64 + {12A36A45-4A15-48E3-B886-257E81FD57C6}.Release|x64.Build.0 = Release|x64 + {369039E2-4C18-40D9-A7FE-E3D87BA23149}.Debug|x64.ActiveCfg = Debug|x64 + {369039E2-4C18-40D9-A7FE-E3D87BA23149}.Debug|x64.Build.0 = Debug|x64 + {369039E2-4C18-40D9-A7FE-E3D87BA23149}.Release|x64.ActiveCfg = Release|x64 + {369039E2-4C18-40D9-A7FE-E3D87BA23149}.Release|x64.Build.0 = Release|x64 + {E9BCC846-C1E9-402F-AC99-0E72195202AC}.Debug|x64.ActiveCfg = Debug|x64 + {E9BCC846-C1E9-402F-AC99-0E72195202AC}.Debug|x64.Build.0 = Debug|x64 + {E9BCC846-C1E9-402F-AC99-0E72195202AC}.Release|x64.ActiveCfg = Release|x64 + {E9BCC846-C1E9-402F-AC99-0E72195202AC}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {369039E2-4C18-40D9-A7FE-E3D87BA23149} = {EB9EA81E-AD7B-4F2F-B8A9-AFC9282303C9} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CECC8215-A95C-44A3-94DC-6A6AEE5A841B} + EndGlobalSection +EndGlobal diff --git a/TileUpdateManager/DataUploader.cpp b/TileUpdateManager/DataUploader.cpp index b294cce..508c909 100644 --- a/TileUpdateManager/DataUploader.cpp +++ b/TileUpdateManager/DataUploader.cpp @@ -49,7 +49,6 @@ Streaming::DataUploader::DataUploader( , m_updateListFreeCount(in_maxCopyBatches) , m_gpuTimer(in_pDevice, in_maxCopyBatches, D3D12GpuTimer::TimerType::Copy) , m_mappingUpdater(in_maxTileMappingUpdatesPerApiCall) - , m_device(in_pDevice) { // copy queue just for UpdateTileMappings() on reserved resources { @@ -65,6 +64,8 @@ Streaming::DataUploader::DataUploader( m_mappingFenceValue++; } + InitDirectStorage(in_pDevice); + //NOTE: TileUpdateManager must call SetStreamer() to start streaming //SetStreamer(StreamerType::Reference); } @@ -77,6 +78,63 @@ Streaming::DataUploader::~DataUploader() StopThreads(); } +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void Streaming::DataUploader::InitDirectStorage(ID3D12Device* in_pDevice) +{ + // initialize to default values + DSTORAGE_CONFIGURATION dsConfig{}; + DStorageSetConfiguration(&dsConfig); + + ThrowIfFailed(DStorageGetFactory(IID_PPV_ARGS(&m_dsFactory))); + + DSTORAGE_DEBUG debugFlags = DSTORAGE_DEBUG_NONE; +#ifdef _DEBUG + debugFlags = DSTORAGE_DEBUG_SHOW_ERRORS; +#endif + m_dsFactory->SetDebugFlags(debugFlags); + + m_dsFactory->SetStagingBufferSize(DSTORAGE_STAGING_BUFFER_SIZE_32MB); + + DSTORAGE_QUEUE_DESC queueDesc{}; + queueDesc.Capacity = DSTORAGE_MAX_QUEUE_CAPACITY; + queueDesc.Priority = DSTORAGE_PRIORITY_NORMAL; + queueDesc.SourceType = DSTORAGE_REQUEST_SOURCE_MEMORY; + queueDesc.Device = in_pDevice; + ThrowIfFailed(m_dsFactory->CreateQueue(&queueDesc, IID_PPV_ARGS(&m_memoryQueue))); + + ThrowIfFailed(in_pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_memoryFence))); +} + +//----------------------------------------------------------------------------- +// handle request to load a texture from cpu memory +// used for packed mips, which don't participate in fine-grained streaming +//----------------------------------------------------------------------------- +UINT64 Streaming::DataUploader::LoadTexture(ID3D12Resource* in_pResource, + const std::vector& in_paddedData, UINT in_firstSubresource) +{ + DSTORAGE_REQUEST request = {}; + request.Options.SourceType = DSTORAGE_REQUEST_SOURCE_MEMORY; + request.Options.DestinationType = DSTORAGE_REQUEST_DESTINATION_MULTIPLE_SUBRESOURCES; + request.Source.Memory.Source = in_paddedData.data(); + request.Source.Memory.Size = (UINT32)in_paddedData.size(); + request.UncompressedSize = (UINT32)in_paddedData.size(); + request.Destination.MultipleSubresources.Resource = in_pResource; + request.Destination.MultipleSubresources.FirstSubresource = in_firstSubresource; + + m_memoryQueue->EnqueueRequest(&request); + return m_memoryFenceValue; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void Streaming::DataUploader::SubmitTextureLoads() +{ + m_memoryQueue->EnqueueSignal(m_memoryFence.Get(), m_memoryFenceValue); + m_memoryQueue->Submit(); + m_memoryFenceValue++; +} + //----------------------------------------------------------------------------- // releases ownership of and returns the old streamer // calling function may need to delete some other resources before deleting the streamer @@ -102,7 +160,7 @@ Streaming::FileStreamer* Streaming::DataUploader::SetStreamer(StreamerType in_st } else { - m_pFileStreamer = std::make_unique(device.Get()); + m_pFileStreamer = std::make_unique(device.Get(), m_dsFactory.Get()); } StartThreads(); @@ -274,7 +332,7 @@ void Streaming::DataUploader::SubmitUpdateList(Streaming::UpdateList& in_updateL //----------------------------------------------------------------------------- void Streaming::DataUploader::FenceMonitorThread() { - bool signalUpload = false; + bool loadTextures = false; for (auto& updateList : m_updateLists) { switch (updateList.m_executionState) @@ -285,21 +343,40 @@ void Streaming::DataUploader::FenceMonitorThread() // wait for mapping complete before streaming packed tiles if (updateList.m_mappingFenceValue <= m_mappingFence->GetCompletedValue()) { - updateList.m_executionState = UpdateList::State::STATE_UPLOADING; - m_pFileStreamer->StreamPackedMips(updateList); + updateList.m_copyFenceValue = LoadTexture(updateList.m_pStreamingResource->GetTiledResource(), + updateList.m_pStreamingResource->GetPaddedPackedMips(), + updateList.m_pStreamingResource->GetPackedMipInfo().NumStandardMips); + updateList.m_executionState = UpdateList::State::STATE_PACKED_COPY_PENDING; + + loadTextures = true; + } + break; + + case UpdateList::State::STATE_PACKED_COPY_PENDING: + ASSERT(0 == updateList.GetNumStandardUpdates()); + ASSERT(0 == updateList.GetNumEvictions()); + ASSERT(updateList.GetNumPackedUpdates()); + + if (m_memoryFence->GetCompletedValue() >= updateList.m_copyFenceValue) + { + updateList.m_pStreamingResource->NotifyPackedMips(); + FreeUpdateList(updateList); } break; case UpdateList::State::STATE_UPLOADING: + // there can be a race where mapping completes before the CPU has written the copy fence + // if the copy fence has been set, there may be a pending copy, so signal the FileStreamer. if (updateList.m_copyFenceValid) { - signalUpload = true; updateList.m_executionState = UpdateList::State::STATE_COPY_PENDING; } break; case UpdateList::State::STATE_COPY_PENDING: { + ASSERT(0 == updateList.GetNumPackedUpdates()); + // standard updates? check if copy complete if (updateList.GetNumStandardUpdates()) { @@ -311,25 +388,11 @@ void Streaming::DataUploader::FenceMonitorThread() } // standard updates or mapping only? check if mapping complete - if (0 == updateList.GetNumPackedUpdates()) - { - // when there are copies, if copies are complete mapping is almost certainly complete - if (updateList.m_mappingFenceValue > m_mappingFence->GetCompletedValue()) - { - break; - } - } - else // packed updates? check if copy complete + if (updateList.m_mappingFenceValue > m_mappingFence->GetCompletedValue()) { - if (!m_pFileStreamer->GetCompleted(updateList)) - { - break; - } + break; } - // The UpdateList is complete - // notify all tiles, evictions, and packed mips - // notify evictions if (updateList.GetNumEvictions()) { @@ -348,14 +411,7 @@ void Streaming::DataUploader::FenceMonitorThread() updateList.m_pStreamingResource->NotifyCopyComplete(updateList.m_coords); } - // notify packed mips - if (updateList.GetNumPackedUpdates()) - { - ASSERT(0 == updateList.GetNumStandardUpdates()); - ASSERT(0 == updateList.GetNumEvictions()); - - updateList.m_pStreamingResource->NotifyPackedMips(); - } + // UpdateList complete FreeUpdateList(updateList); } break; @@ -365,19 +421,18 @@ void Streaming::DataUploader::FenceMonitorThread() } } // end loop over updatelists - // signal filestreamer that it should submit work (if it hasn't already) - if (signalUpload) + if (loadTextures) { - m_pFileStreamer->Signal(); + SubmitTextureLoads(); } } //----------------------------------------------------------------------------- // Submit Thread // On submission, all updatelists need mapping -// then set state as appropriate depending on the task -// FIXME: QueryPerformanceCounter() needs to be called from the same CPU for values to be compared (deltas) -// capture start time here +// set next state depending on the task +// Note: QueryPerformanceCounter() needs to be called from the same CPU for values to be compared, +// but this thread starts work while a different thread handles completion //----------------------------------------------------------------------------- void Streaming::DataUploader::SubmitThread() { @@ -387,10 +442,6 @@ void Streaming::DataUploader::SubmitThread() { switch (updateList.m_executionState) { - //---------------------------------------- - // STATE_SUBMITTED - // statistics: get start time - //---------------------------------------- case UpdateList::State::STATE_SUBMITTED: { // all UpdateLists require mapping diff --git a/TileUpdateManager/DataUploader.h b/TileUpdateManager/DataUploader.h index 9638af6..c57fcb4 100644 --- a/TileUpdateManager/DataUploader.h +++ b/TileUpdateManager/DataUploader.h @@ -26,6 +26,8 @@ #pragma once +#include // single creation point for factory. internal q for packed mips. + #include "UpdateList.h" #include "MappingUpdater.h" #include "FileStreamer.h" @@ -64,8 +66,12 @@ namespace Streaming // may return null. called by StreamingResource. UpdateList* AllocateUpdateList(StreamingResourceBase* in_pStreamingResource); + // StreamingResource requests tiles to be uploaded void SubmitUpdateList(Streaming::UpdateList& in_updateList); + // TUM requests file streamer to signal its fence after StreamingResources have queued tile uploads + void SignalFileStreamer() { m_pFileStreamer->Signal(); } + // free updatelist after processing // Streaming resource may call this (via TUM) if it allocates but doesn't use an updatelist void FreeUpdateList(Streaming::UpdateList& in_updateList); @@ -91,7 +97,6 @@ namespace Streaming const UINT m_maxTileCopiesInFlight{ 0 }; const UINT m_maxBatchSize{ 0 }; - ComPtr m_device; D3D12GpuTimer m_gpuTimer; RawCpuTimer m_cpuTimer; @@ -134,6 +139,16 @@ namespace Streaming void StopThreads(); std::atomic m_threadsRunning{ false }; + // DS memory queue used just for loading packed mips when the file doesn't include padding + // separate memory queue means needing a second fence - can't wait across DS queues + void InitDirectStorage(ID3D12Device* in_pDevice); + ComPtr m_dsFactory; + ComPtr m_memoryQueue; + ComPtr m_memoryFence; + UINT64 m_memoryFenceValue{ 1 }; + UINT64 LoadTexture(ID3D12Resource* in_pResource, const std::vector& in_paddedData, UINT in_firstSubresource); + void SubmitTextureLoads(); + //------------------------------------------- // statistics //------------------------------------------- diff --git a/TileUpdateManager/FileStreamer.h b/TileUpdateManager/FileStreamer.h index 9c293b2..9223def 100644 --- a/TileUpdateManager/FileStreamer.h +++ b/TileUpdateManager/FileStreamer.h @@ -48,7 +48,6 @@ namespace Streaming virtual FileHandle* OpenFile(const std::wstring& in_path) = 0; virtual void StreamTexture(Streaming::UpdateList& in_updateList) = 0; - virtual void StreamPackedMips(Streaming::UpdateList& in_updateList) = 0; virtual void Signal() = 0; diff --git a/TileUpdateManager/FileStreamerDS.cpp b/TileUpdateManager/FileStreamerDS.cpp index 23a35f5..805ff62 100644 --- a/TileUpdateManager/FileStreamerDS.cpp +++ b/TileUpdateManager/FileStreamerDS.cpp @@ -3,7 +3,6 @@ #include "pch.h" #include "FileStreamerDS.h" -#include "DXSampleHelper.h" #include "StreamingResourceDU.h" #include "XeTexture.h" @@ -19,33 +18,24 @@ Streaming::FileStreamerDS::FileHandleDS::FileHandleDS(IDStorageFactory* in_pFact //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -Streaming::FileStreamerDS::FileStreamerDS(ID3D12Device* in_pDevice) : +Streaming::FileStreamerDS::FileStreamerDS(ID3D12Device* in_pDevice, IDStorageFactory* in_pDSfactory) : + m_pFactory(in_pDSfactory), Streaming::FileStreamer(in_pDevice) { - ThrowIfFailed(DStorageGetFactory(IID_PPV_ARGS(&m_factory))); - -#ifdef _DEBUG - m_factory->SetDebugFlags(DSTORAGE_DEBUG_SHOW_ERRORS); -#endif - DSTORAGE_QUEUE_DESC queueDesc{}; queueDesc.Capacity = DSTORAGE_MAX_QUEUE_CAPACITY; queueDesc.Priority = DSTORAGE_PRIORITY_NORMAL; queueDesc.SourceType = DSTORAGE_REQUEST_SOURCE_FILE; queueDesc.Device = in_pDevice; - ThrowIfFailed(m_factory->CreateQueue(&queueDesc, IID_PPV_ARGS(&m_fileQueue))); + ThrowIfFailed(in_pDSfactory->CreateQueue(&queueDesc, IID_PPV_ARGS(&m_fileQueue))); queueDesc.SourceType = DSTORAGE_REQUEST_SOURCE_MEMORY; - ThrowIfFailed(m_factory->CreateQueue(&queueDesc, IID_PPV_ARGS(&m_memoryQueue))); - m_memoryFenceEvent = ::CreateEvent(nullptr, FALSE, FALSE, nullptr); - - ThrowIfFailed(in_pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_memoryFence))); + ThrowIfFailed(in_pDSfactory->CreateQueue(&queueDesc, IID_PPV_ARGS(&m_memoryQueue))); } Streaming::FileStreamerDS::~FileStreamerDS() { - ::CloseHandle(m_memoryFenceEvent); } //----------------------------------------------------------------------------- @@ -59,36 +49,7 @@ IDStorageFile* Streaming::FileStreamerDS::GetFileHandle(const Streaming::FileHan //----------------------------------------------------------------------------- Streaming::FileHandle* Streaming::FileStreamerDS::OpenFile(const std::wstring& in_path) { - return new FileHandleDS(m_factory.Get(), in_path); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void Streaming::FileStreamerDS::StreamPackedMips(Streaming::UpdateList& in_updateList) -{ - ASSERT(in_updateList.GetNumPackedUpdates()); - ASSERT(0 == in_updateList.GetNumStandardUpdates()); - - ID3D12Resource* pDstResource = in_updateList.m_pStreamingResource->GetTiledResource(); - - UINT firstSubresource = in_updateList.m_pStreamingResource->GetPackedMipInfo().NumStandardMips; - - UINT numBytes = 0; - void* pBytes = (void*)in_updateList.m_pStreamingResource->GetPaddedPackedMips(numBytes); - - DSTORAGE_REQUEST request = {}; - request.UncompressedSize = numBytes; - request.Options.SourceType = DSTORAGE_REQUEST_SOURCE_MEMORY; - request.Options.DestinationType = DSTORAGE_REQUEST_DESTINATION_MULTIPLE_SUBRESOURCES; - request.Source.Memory.Source = pBytes; - request.Source.Memory.Size = numBytes; - request.Destination.MultipleSubresources.Resource = pDstResource; - request.Destination.MultipleSubresources.FirstSubresource = firstSubresource; - - m_memoryQueue->EnqueueRequest(&request); - in_updateList.m_copyFenceValue = m_copyFenceValue; - m_haveMemoryRequests = true; - in_updateList.m_copyFenceValid = true; + return new FileHandleDS(m_pFactory, in_path); } //----------------------------------------------------------------------------- @@ -98,8 +59,9 @@ void Streaming::FileStreamerDS::StreamTexture(Streaming::UpdateList& in_updateLi ASSERT(0 == in_updateList.GetNumPackedUpdates()); ASSERT(in_updateList.GetNumStandardUpdates()); - auto pTextureStreamer = in_updateList.m_pStreamingResource->GetTextureStreamer(); - DXGI_FORMAT textureFormat = pTextureStreamer->GetFormat(); + auto pTextureFileInfo = in_updateList.m_pStreamingResource->GetTextureFileInfo(); + DXGI_FORMAT textureFormat = pTextureFileInfo->GetFormat(); + auto pDstHeap = in_updateList.m_pStreamingResource->GetHeap(); DSTORAGE_REQUEST request = {}; request.Options.DestinationType = DSTORAGE_REQUEST_DESTINATION_TILES; @@ -115,10 +77,11 @@ void Streaming::FileStreamerDS::StreamTexture(Streaming::UpdateList& in_updateLi UINT numCoords = (UINT)in_updateList.m_coords.size(); for (UINT i = 0; i < numCoords; i++) { + request.Source.File.Offset = pTextureFileInfo->GetFileOffset(in_updateList.m_coords[i]); + D3D12_TILED_RESOURCE_COORDINATE coord; - ID3D12Resource* pAtlas = in_updateList.m_pStreamingResource->GetHeap()->ComputeCoordFromTileIndex(coord, in_updateList.m_heapIndices[i], textureFormat); + ID3D12Resource* pAtlas = pDstHeap->ComputeCoordFromTileIndex(coord, in_updateList.m_heapIndices[i], textureFormat); - request.Source.File.Offset = pTextureStreamer->GetFileOffset(in_updateList.m_coords[i]); request.Destination.Tiles.Resource = pAtlas; request.Destination.Tiles.TiledRegionStartCoordinate = coord; @@ -137,13 +100,12 @@ void Streaming::FileStreamerDS::StreamTexture(Streaming::UpdateList& in_updateLi request.Source.Memory.Source = GetVisualizationData(in_updateList.m_coords[i], textureFormat); D3D12_TILED_RESOURCE_COORDINATE coord; - ID3D12Resource* pAtlas = in_updateList.m_pStreamingResource->GetHeap()->ComputeCoordFromTileIndex(coord, in_updateList.m_heapIndices[i], textureFormat); + ID3D12Resource* pAtlas = pDstHeap->ComputeCoordFromTileIndex(coord, in_updateList.m_heapIndices[i], textureFormat); request.Destination.Tiles.Resource = pAtlas; request.Destination.Tiles.TiledRegionStartCoordinate = coord; m_memoryQueue->EnqueueRequest(&request); - m_haveMemoryRequests = true; } } @@ -155,16 +117,9 @@ void Streaming::FileStreamerDS::StreamTexture(Streaming::UpdateList& in_updateLi //----------------------------------------------------------------------------- inline bool Streaming::FileStreamerDS::GetCompleted(const Streaming::UpdateList& in_updateList) const { - bool completed = false; - if ((VisualizationMode::DATA_VIZ_NONE == m_visualizationMode) && (0 == in_updateList.GetNumPackedUpdates())) - { - completed = in_updateList.m_copyFenceValue <= m_copyFence->GetCompletedValue(); - } - else - { - completed = in_updateList.m_copyFenceValue <= m_memoryFence->GetCompletedValue(); - } - return completed; + ASSERT(0 == in_updateList.GetNumPackedUpdates()); + + return in_updateList.m_copyFenceValue <= m_copyFence->GetCompletedValue();; } //----------------------------------------------------------------------------- @@ -173,16 +128,16 @@ inline bool Streaming::FileStreamerDS::GetCompleted(const Streaming::UpdateList& //----------------------------------------------------------------------------- void Streaming::FileStreamerDS::Signal() { - // might end up signaling two fences, but, we can live with that. - if (m_haveMemoryRequests) + if (VisualizationMode::DATA_VIZ_NONE == m_visualizationMode) { - m_haveMemoryRequests = false; - - m_memoryQueue->EnqueueSignal(m_memoryFence.Get(), m_copyFenceValue); + m_fileQueue->EnqueueSignal(m_copyFence.Get(), m_copyFenceValue); + m_fileQueue->Submit(); + } + else + { + m_memoryQueue->EnqueueSignal(m_copyFence.Get(), m_copyFenceValue); m_memoryQueue->Submit(); } - m_fileQueue->EnqueueSignal(m_copyFence.Get(), m_copyFenceValue); - m_fileQueue->Submit(); m_copyFenceValue++; } diff --git a/TileUpdateManager/FileStreamerDS.h b/TileUpdateManager/FileStreamerDS.h index b6b006f..d486cad 100644 --- a/TileUpdateManager/FileStreamerDS.h +++ b/TileUpdateManager/FileStreamerDS.h @@ -10,12 +10,11 @@ namespace Streaming class FileStreamerDS : public FileStreamer { public: - FileStreamerDS(ID3D12Device* in_pDevice); + FileStreamerDS(ID3D12Device* in_pDevice, IDStorageFactory* in_pFactory); virtual ~FileStreamerDS(); virtual FileHandle* OpenFile(const std::wstring& in_path) override; virtual void StreamTexture(Streaming::UpdateList& in_updateList) override; - virtual void StreamPackedMips(Streaming::UpdateList& in_updateList) override; static IDStorageFile* GetFileHandle(const FileHandle* in_pHandle); @@ -36,15 +35,11 @@ namespace Streaming private: ComPtr m_file; }; - ComPtr m_factory; + IDStorageFactory* m_pFactory{ nullptr }; ComPtr m_fileQueue; - // separate memory queue means needing a second fence - can't wait across DS queues + // memory queue when for visualization modes, which copy from cpu memory ComPtr m_memoryQueue; - ComPtr m_memoryFence; - HANDLE m_memoryFenceEvent{ nullptr }; - UINT64 m_memoryFenceValue{ 1 }; - bool m_haveMemoryRequests{ false }; }; }; diff --git a/TileUpdateManager/FileStreamerReference.cpp b/TileUpdateManager/FileStreamerReference.cpp index 40a6692..1e7d073 100644 --- a/TileUpdateManager/FileStreamerReference.cpp +++ b/TileUpdateManager/FileStreamerReference.cpp @@ -30,7 +30,6 @@ #include "UpdateList.h" #include "XeTexture.h" #include "StreamingResourceDU.h" -#include "DXSampleHelper.h" #include "StreamingHeap.h" //----------------------------------------------------------------------------- @@ -197,16 +196,6 @@ void Streaming::FileStreamerReference::AllocateCopyBatch(Streaming::UpdateList& } } -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void Streaming::FileStreamerReference::StreamPackedMips(Streaming::UpdateList& in_updateList) -{ - ASSERT(in_updateList.GetNumPackedUpdates()); - ASSERT(0 == in_updateList.GetNumStandardUpdates()); - - AllocateCopyBatch(in_updateList, CopyBatch::State::LOAD_PACKEDMIPS); -} - //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void Streaming::FileStreamerReference::StreamTexture(Streaming::UpdateList& in_updateList) @@ -217,48 +206,6 @@ void Streaming::FileStreamerReference::StreamTexture(Streaming::UpdateList& in_u AllocateCopyBatch(in_updateList, CopyBatch::State::LOAD_TILES); } -//----------------------------------------------------------------------------- -// stream and copy a packed mip -//----------------------------------------------------------------------------- -void Streaming::FileStreamerReference::InitPackedMips(ID3D12GraphicsCommandList* out_pCmdList, const CopyBatch& in_copyBatch) -{ - UpdateList* pUpdateList = in_copyBatch.m_pUpdateList; - ID3D12Resource* pDstResource = pUpdateList->m_pStreamingResource->GetTiledResource(); - - const UINT firstSubresource = pUpdateList->m_pStreamingResource->GetPackedMipInfo().NumStandardMips; - const UINT numSubresources = pUpdateList->m_pStreamingResource->GetPackedMipInfo().NumPackedMips; - - D3D12_RESOURCE_DESC desc = pDstResource->GetDesc(); - - std::vector srcLayout(numSubresources); - - ComPtr device; - m_copyCommandQueue->GetDevice(IID_PPV_ARGS(&device)); - - device->GetCopyableFootprints(&desc, firstSubresource, numSubresources, - 0, // NOTE: the offset will be replaced; each mip has its own tile-sized upload location - srcLayout.data(), - //&numRows, &rowSizeBytes, &totalBytes); - nullptr, nullptr, nullptr); - - BYTE* pDst = (BYTE*)m_uploadAllocator.GetBuffer().m_pData; - - for (UINT i = 0; i < numSubresources; i++) - { - // each mip has its own tile-sized upload location - // this way, we don't have to have consecutive upload buffer destinations - srcLayout[i].Offset = in_copyBatch.m_uploadIndices[i] * D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES; - - pUpdateList->m_pStreamingResource->GetTextureStreamer()->WritePackedBits( - &pDst[srcLayout[i].Offset], - firstSubresource + i, srcLayout[i].Footprint.RowPitch); - - D3D12_TEXTURE_COPY_LOCATION srcLocation = CD3DX12_TEXTURE_COPY_LOCATION(m_uploadAllocator.GetBuffer().m_resource.Get(), srcLayout[i]); - D3D12_TEXTURE_COPY_LOCATION dstLocation = CD3DX12_TEXTURE_COPY_LOCATION(pUpdateList->m_pStreamingResource->GetTiledResource(), firstSubresource + i); - out_pCmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, nullptr); - } -} - //----------------------------------------------------------------------------- // Generate ReadFile()s for each tile in the texture //----------------------------------------------------------------------------- @@ -274,12 +221,12 @@ void Streaming::FileStreamerReference::LoadTexture(Streaming::FileStreamerRefere if (VisualizationMode::DATA_VIZ_NONE == m_visualizationMode) { - auto pTextureStreamer = pUpdateList->m_pStreamingResource->GetTextureStreamer(); + auto pTextureFileInfo = pUpdateList->m_pStreamingResource->GetTextureFileInfo(); auto pFileHandle = FileStreamerReference::GetFileHandle(pUpdateList->m_pStreamingResource->GetFileHandle()); for (UINT i = 0; i < numReads; i++) { // get file offset to tile - UINT fileOffset = pTextureStreamer->GetFileOffset(pUpdateList->m_coords[i]); + UINT fileOffset = pTextureFileInfo->GetFileOffset(pUpdateList->m_coords[i]); // convert tile index into byte offset UINT byteOffset = D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES * in_copyBatch.m_uploadIndices[i]; @@ -299,7 +246,7 @@ void Streaming::FileStreamerReference::LoadTexture(Streaming::FileStreamerRefere // add to base address of upload buffer BYTE* pDst = pStagingBaseAddress + byteOffset; - void* pSrc = GetVisualizationData(pUpdateList->m_coords[i], in_copyBatch.m_pUpdateList->m_pStreamingResource->GetTextureStreamer()->GetFormat()); + void* pSrc = GetVisualizationData(pUpdateList->m_coords[i], in_copyBatch.m_pUpdateList->m_pStreamingResource->GetTextureFileInfo()->GetFormat()); memcpy(pDst, pSrc, D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES); } } @@ -313,7 +260,7 @@ void Streaming::FileStreamerReference::CopyTiles(ID3D12GraphicsCommandList* out_ { // generate copy command list D3D12_TILE_REGION_SIZE tileRegionSize{ 1, FALSE, 0, 0, 0 }; - DXGI_FORMAT textureFormat = in_pUpdateList->m_pStreamingResource->GetTextureStreamer()->GetFormat(); + DXGI_FORMAT textureFormat = in_pUpdateList->m_pStreamingResource->GetTextureFileInfo()->GetFormat(); UINT numTiles = (UINT)in_indices.size(); for (UINT i = 0; i < numTiles; i++) { @@ -358,26 +305,6 @@ void Streaming::FileStreamerReference::CopyThread() { switch (c.m_state) { - case CopyBatch::State::LOAD_PACKEDMIPS: - ASSERT(0 == c.m_pUpdateList->GetNumStandardUpdates()); - ASSERT(c.m_pUpdateList->GetNumPackedUpdates()); - if (m_uploadAllocator.Allocate(c.m_uploadIndices, c.m_pUpdateList->GetNumPackedUpdates())) - { - c.m_copyFenceValue = m_copyFenceValue; - - if (!submitCopyCommands) - { - submitCopyCommands = true; - m_copyCommandList->Reset(c.GetCommandAllocator(), nullptr); - } - InitPackedMips(m_copyCommandList.Get(), c); - - c.m_pUpdateList->m_copyFenceValue = c.m_copyFenceValue; - c.m_pUpdateList->m_copyFenceValid = true; - c.m_state = CopyBatch::State::WAIT_COMPLETE; - } - break; - case CopyBatch::State::LOAD_TILES: ASSERT(c.m_pUpdateList->GetNumStandardUpdates()); ASSERT(0 == c.m_pUpdateList->GetNumPackedUpdates()); diff --git a/TileUpdateManager/FileStreamerReference.h b/TileUpdateManager/FileStreamerReference.h index 89f3f78..9089b26 100644 --- a/TileUpdateManager/FileStreamerReference.h +++ b/TileUpdateManager/FileStreamerReference.h @@ -46,7 +46,6 @@ namespace Streaming virtual FileHandle* OpenFile(const std::wstring& in_path) override; virtual void StreamTexture(Streaming::UpdateList& in_updateList) override; - virtual void StreamPackedMips(Streaming::UpdateList& in_updateList) override; virtual void Signal() override {} // reference auto-submits @@ -79,7 +78,6 @@ namespace Streaming { FREE = 0, ALLOCATED, - LOAD_PACKEDMIPS, LOAD_TILES, COPY_TILES, WAIT_COMPLETE, @@ -134,6 +132,5 @@ namespace Streaming void LoadTexture(CopyBatch& in_copyBatch); void CopyTiles(ID3D12GraphicsCommandList* out_pCopyCmdList, ID3D12Resource* in_pSrcResource, const UpdateList* in_pUpdateList, const std::vector& in_indices); - void InitPackedMips(ID3D12GraphicsCommandList* out_pCmdList, const CopyBatch& in_copyBatch); }; } diff --git a/TileUpdateManager/HeapAllocator.cpp b/TileUpdateManager/HeapAllocator.cpp index 9453d9f..31adb95 100644 --- a/TileUpdateManager/HeapAllocator.cpp +++ b/TileUpdateManager/HeapAllocator.cpp @@ -27,7 +27,6 @@ #include "pch.h" #include "HeapAllocator.h" -#include "DXSampleHelper.h" //============================================================================= // Internal class that allocates tiles from a heap diff --git a/TileUpdateManager/InternalResources.cpp b/TileUpdateManager/InternalResources.cpp index e0a1b12..dc09847 100644 --- a/TileUpdateManager/InternalResources.cpp +++ b/TileUpdateManager/InternalResources.cpp @@ -27,14 +27,13 @@ #include "pch.h" #include "InternalResources.h" -#include "DXSampleHelper.h" #include "XeTexture.h" //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- Streaming::InternalResources::InternalResources( ID3D12Device8* in_pDevice, - XeTexture* in_pTextureStreamer, + XeTexture* m_pTextureFileInfo, // need the swap chain count so we can create per-frame upload buffers UINT in_swapChainBufferCount) : m_packedMipInfo{}, m_tileShape{}, m_numTilesTotal(0) @@ -42,10 +41,10 @@ Streaming::InternalResources::InternalResources( // create reserved resource { D3D12_RESOURCE_DESC rd = CD3DX12_RESOURCE_DESC::Tex2D( - in_pTextureStreamer->GetFormat(), - in_pTextureStreamer->GetImageWidth(), - in_pTextureStreamer->GetImageHeight(), 1, - (UINT16)in_pTextureStreamer->GetMipCount() + m_pTextureFileInfo->GetFormat(), + m_pTextureFileInfo->GetImageWidth(), + m_pTextureFileInfo->GetImageHeight(), 1, + (UINT16)m_pTextureFileInfo->GetMipCount() ); // Layout must be D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE when creating reserved resources diff --git a/TileUpdateManager/InternalResources.h b/TileUpdateManager/InternalResources.h index c16f31a..848620b 100644 --- a/TileUpdateManager/InternalResources.h +++ b/TileUpdateManager/InternalResources.h @@ -40,7 +40,7 @@ namespace Streaming class InternalResources { public: - InternalResources(ID3D12Device8* in_pDevice, class XeTexture* in_pTextureStreamer, + InternalResources(ID3D12Device8* in_pDevice, class XeTexture* m_pTextureFileInfo, // need the swap chain count so we can create per-frame upload buffers UINT in_swapChainBufferCount); diff --git a/TileUpdateManager/Streaming.h b/TileUpdateManager/Streaming.h index 9a1d02c..e9f6d27 100644 --- a/TileUpdateManager/Streaming.h +++ b/TileUpdateManager/Streaming.h @@ -32,6 +32,8 @@ #include #pragma comment(lib, "Synchronization.lib") +#include "DebugHelper.h" + namespace Streaming { template using ComPtr = Microsoft::WRL::ComPtr; @@ -76,28 +78,6 @@ namespace Streaming const UINT m_alignment; }; - //================================================== - // auto t = AutoString::Concat("test: ", 3, "*", 2.75f, "\n"); - //================================================== - class AutoString - { - public: - template static std::wstring Concat(Ts...ts) - { - std::wstringstream w; - Expander(w, ts...); - return w.str(); - } - private: - static void Expander(std::wstringstream&) { } - - template static void Expander(std::wstringstream& in_w, const T& t, Ts...ts) - { - in_w << t; - Expander(in_w, ts...); - } - }; - //================================================== // a single thread may wait on this flag, which may be set by any number of threads //================================================== diff --git a/TileUpdateManager/StreamingHeap.cpp b/TileUpdateManager/StreamingHeap.cpp index 0e434ea..ef59f5b 100644 --- a/TileUpdateManager/StreamingHeap.cpp +++ b/TileUpdateManager/StreamingHeap.cpp @@ -27,7 +27,6 @@ #include "pch.h" #include "StreamingHeap.h" -#include "DXSampleHelper.h" //----------------------------------------------------------------------------- // create an "atlas" texture that covers the entire heap diff --git a/TileUpdateManager/StreamingResource.cpp b/TileUpdateManager/StreamingResource.cpp index 66eedc8..4225eaa 100644 --- a/TileUpdateManager/StreamingResource.cpp +++ b/TileUpdateManager/StreamingResource.cpp @@ -63,8 +63,8 @@ Streaming::StreamingResourceBase::StreamingResourceBase( , m_pFileHandle(in_pFileHandle) , m_filename(in_filename) { - m_pTextureStreamer = std::make_unique(in_filename); - m_resources = std::make_unique(in_pTileUpdateManager->GetDevice(), m_pTextureStreamer.get(), in_pTileUpdateManager->GetNumSwapBuffers()); + m_pTextureFileInfo = std::make_unique(in_filename); + m_resources = std::make_unique(in_pTileUpdateManager->GetDevice(), m_pTextureFileInfo.get(), in_pTileUpdateManager->GetNumSwapBuffers()); m_tileMappingState.Init(m_resources->GetPackedMipInfo().NumStandardMips, m_resources->GetTiling()); // no packed mips. odd, but possible. no need to check/update this variable again. @@ -86,10 +86,10 @@ Streaming::StreamingResourceBase::StreamingResourceBase( m_minMipMap.resize(m_tileReferences.size(), m_maxMip); // make sure my heap has an atlas corresponding to my format - m_pHeap->AllocateAtlas(in_pTileUpdateManager->GetMappingQueue(), m_pTextureStreamer->GetFormat()); + m_pHeap->AllocateAtlas(in_pTileUpdateManager->GetMappingQueue(), m_pTextureFileInfo->GetFormat()); - // For easy upload, pad the packed mips - PadPackedMips(in_pTileUpdateManager->GetDevice()); + // Load packed mips. packed mips are not streamed or evicted. + LoadPackedMips(); } //----------------------------------------------------------------------------- @@ -494,8 +494,10 @@ void Streaming::StreamingResourceBase::AbandonPendingLoads() // // note: queues as many new tiles as possible //----------------------------------------------------------------------------- -void Streaming::StreamingResourceBase::QueueTiles() +bool Streaming::StreamingResourceBase::QueueTiles() { + bool uploadRequested = false; + UINT numEvictions = (UINT)m_pendingEvictions.GetReadyToEvict().size(); UINT numLoads = (UINT)m_pendingTileLoads.size(); @@ -515,6 +517,7 @@ void Streaming::StreamingResourceBase::QueueTiles() // queue as many new tiles as possible if (numLoads && m_pHeap->GetAllocator().GetNumFree()) { + uploadRequested = true; QueuePendingTileLoads(pUpdateList); numLoads = (UINT)m_pendingTileLoads.size(); } @@ -541,6 +544,7 @@ void Streaming::StreamingResourceBase::QueueTiles() break; } } + return uploadRequested; } /*----------------------------------------------------------------------------- @@ -725,7 +729,7 @@ void Streaming::StreamingResourceBase::UpdateMinMipMap() // a simple optimization that's especially effective for large textures // and harmless for smaller ones: // find the minimum fully-resident mip - UINT8 minResidentMip = m_tileMappingState.GetMinResidentMip(); + const UINT8 minResidentMip = m_tileMappingState.GetMinResidentMip(); #endif // Search bottom up for best mip // tiles that have refcounts may still have pending copies, so we have to check residency (can't just memcpy m_tileReferences) @@ -842,7 +846,7 @@ void Streaming::StreamingResourceBase::EvictionDelay::Rescue(const Streaming::St //----------------------------------------------------------------------------- // pad packed mips according to copyable footprint requirements //----------------------------------------------------------------------------- -void Streaming::StreamingResourceBase::PadPackedMips(ID3D12Device* in_pDevice) +void Streaming::StreamingResourceBase::PadPackedMips() { UINT firstSubresource = m_resources->GetPackedMipInfo().NumStandardMips; UINT numSubresources = m_resources->GetPackedMipInfo().NumPackedMips; @@ -853,14 +857,13 @@ void Streaming::StreamingResourceBase::PadPackedMips(ID3D12Device* in_pDevice) std::vector numRows(numSubresources); std::vector rowSizeBytes(numSubresources); - in_pDevice->GetCopyableFootprints(&desc, firstSubresource, numSubresources, + m_pTileUpdateManager->GetDevice()->GetCopyableFootprints(&desc, firstSubresource, numSubresources, 0, srcLayout.data(), numRows.data(), rowSizeBytes.data(), &totalBytes); - m_paddedPackedMips.resize(totalBytes); + std::vector paddedPackedMips(totalBytes); - BYTE* pDst = m_paddedPackedMips.data(); - UINT numBytes = 0; - const BYTE* pSrc = m_pTextureStreamer->GetPackedBits(numBytes); + BYTE* pDst = paddedPackedMips.data(); + BYTE* pSrc = m_packedMips.data(); for (UINT i = 0; i < numSubresources; i++) { @@ -871,6 +874,23 @@ void Streaming::StreamingResourceBase::PadPackedMips(ID3D12Device* in_pDevice) pSrc += rowSizeBytes[i]; } } + m_packedMips.swap(paddedPackedMips); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void Streaming::StreamingResourceBase::LoadPackedMips() +{ + // FIXME: future file format should contain padded packed mips to allow DS to load directly from disk to GPU + + UINT numBytes = 0; + UINT offset = m_pTextureFileInfo->GetPackedMipFileOffset(&numBytes); + m_packedMips.resize(numBytes); + std::ifstream inFile(m_filename.c_str(), std::ios::binary); + inFile.seekg(offset); + inFile.read((char*)m_packedMips.data(), numBytes); + inFile.close(); + PadPackedMips(); } //----------------------------------------------------------------------------- diff --git a/TileUpdateManager/StreamingResource.h b/TileUpdateManager/StreamingResource.h index 5ab148e..940488a 100644 --- a/TileUpdateManager/StreamingResource.h +++ b/TileUpdateManager/StreamingResource.h @@ -26,10 +26,7 @@ /*============================================================================= -Usage: - -After creating a TileUpdateManager, a TextureStreamer, and a Streaming::Heap, -use TileUpdateManager::CreateStreamingResource() +Base class for StreamingResource =============================================================================*/ #pragma once @@ -119,7 +116,8 @@ namespace Streaming void ProcessFeedback(UINT64 in_frameFenceCompletedValue); // try to load/evict tiles. only queue evictions once per frame. - void QueueTiles(); + // return true if tile upload requested + bool QueueTiles(); bool IsStale() { @@ -136,7 +134,7 @@ namespace Streaming protected: // object that streams data from a file - std::unique_ptr m_pTextureStreamer; + std::unique_ptr m_pTextureFileInfo; std::unique_ptr m_resources; std::unique_ptr m_pFileHandle; const std::wstring m_filename; @@ -265,8 +263,6 @@ namespace Streaming std::vector m_pendingTileLoads; - std::vector m_paddedPackedMips; - //-------------------------------------------------------- // for public interface //-------------------------------------------------------- @@ -286,6 +282,8 @@ namespace Streaming UINT8 m_maxMip; std::vector> m_minMipMap; // local version of min mip map, rectified in UpdateMinMipMap() + // bytes for packed mips + std::vector m_packedMips; private: // non-packed mip copy complete notification std::atomic m_tileResidencyChanged{ false }; @@ -319,7 +317,8 @@ namespace Streaming void QueuePendingTileLoads(Streaming::UpdateList* out_pUpdateList); // returns # tiles queued - void PadPackedMips(ID3D12Device* in_pDevice); + void LoadPackedMips(); + void PadPackedMips(); // used by QueueEviction() bool m_refCountsZero{ true }; diff --git a/TileUpdateManager/StreamingResourceDU.cpp b/TileUpdateManager/StreamingResourceDU.cpp index 7034fed..a4a179b 100644 --- a/TileUpdateManager/StreamingResourceDU.cpp +++ b/TileUpdateManager/StreamingResourceDU.cpp @@ -104,5 +104,5 @@ void Streaming::StreamingResourceDU::NotifyPackedMips() // don't need to hold on to packed mips any longer. std::vector empty; - m_paddedPackedMips.swap(empty); + GetPaddedPackedMips().swap(empty); } diff --git a/TileUpdateManager/StreamingResourceDU.h b/TileUpdateManager/StreamingResourceDU.h index c5699d2..c490519 100644 --- a/TileUpdateManager/StreamingResourceDU.h +++ b/TileUpdateManager/StreamingResourceDU.h @@ -27,6 +27,7 @@ #pragma once #include "StreamingResource.h" +#include "XeTexture.h" //----------------------------------------------------------------- // custom StreamingResource interface for DataUploader @@ -36,7 +37,7 @@ namespace Streaming class StreamingResourceDU : private StreamingResourceBase { public: - XeTexture* GetTextureStreamer() const { return m_pTextureStreamer.get(); } + XeTexture* GetTextureFileInfo() const { return m_pTextureFileInfo.get(); } Streaming::Heap* GetHeap() const { return m_pHeap; } // just for packed mips @@ -50,7 +51,7 @@ namespace Streaming const FileHandle* GetFileHandle() const { return m_pFileHandle.get(); } - const BYTE* GetPaddedPackedMips(UINT& out_numBytes) const { out_numBytes = (UINT)m_paddedPackedMips.size(); return m_paddedPackedMips.data(); } + std::vector& GetPaddedPackedMips() { return m_packedMips; } // packed mips are treated differently from regular tiles: they aren't tracked by the data structure, and share heap indices void MapPackedMips(ID3D12CommandQueue* in_pCommandQueue); diff --git a/TileUpdateManager/TileUpdateManager.cpp b/TileUpdateManager/TileUpdateManager.cpp index f910800..ea5c63b 100644 --- a/TileUpdateManager/TileUpdateManager.cpp +++ b/TileUpdateManager/TileUpdateManager.cpp @@ -129,7 +129,7 @@ void Streaming::TileUpdateManagerBase::StartThreads() UINT64 previousFrameFenceValue = m_frameFenceValue; while (m_threadsRunning) { - // if there are packed mips waiting to load, prioritize that over everything + // prioritize loading packed mips, as objects shouldn't be displayed until packed mips load bool expected = true; if (m_havePackedMipsToLoad.compare_exchange_weak(expected, false)) { @@ -178,6 +178,7 @@ void Streaming::TileUpdateManagerBase::StartThreads() } // continuously push uploads and evictions + bool uploadRequested = false; for (UINT i = 0; i < staleResources.size(); i++) { if (!m_threadsRunning) @@ -187,7 +188,7 @@ void Streaming::TileUpdateManagerBase::StartThreads() UINT resourceIndex = staleResources[i]; auto p = m_streamingResources[resourceIndex]; - p->QueueTiles(); + uploadRequested = (uploadRequested || p->QueueTiles()); // if all loads/evictions handled, remove from staleResource list if (!p->IsStale()) @@ -199,6 +200,12 @@ void Streaming::TileUpdateManagerBase::StartThreads() } } + // if uploads were queued, tell the file streamer to signal the corresponding fence + if (uploadRequested) + { + m_pDataUploader->SignalFileStreamer(); + } + // nothing to do? wait for next frame if ((0 == staleResources.size()) && m_threadsRunning) { diff --git a/TileUpdateManager/TileUpdateManager.h b/TileUpdateManager/TileUpdateManager.h index 902d2bf..4831a74 100644 --- a/TileUpdateManager/TileUpdateManager.h +++ b/TileUpdateManager/TileUpdateManager.h @@ -46,6 +46,7 @@ Draw loop: #include #include #include +#include #include "D3D12GpuTimer.h" #include "Timer.h" diff --git a/TileUpdateManager/TileUpdateManagerExt.cpp b/TileUpdateManager/TileUpdateManagerExt.cpp index e64be55..c1ffaf6 100644 --- a/TileUpdateManager/TileUpdateManagerExt.cpp +++ b/TileUpdateManager/TileUpdateManagerExt.cpp @@ -174,7 +174,11 @@ float TileUpdateManager::GetGpuStreamingTime() const { return m_pDataUploader->G float TileUpdateManager::GetGpuTime() const { return m_gpuTimerResolve.GetTimes()[m_renderFrameIndex].first; } UINT TileUpdateManager::GetTotalNumUploads() const { return m_pDataUploader->GetTotalNumUploads(); } UINT TileUpdateManager::GetTotalNumEvictions() const { return m_pDataUploader->GetTotalNumEvictions(); } -void TileUpdateManager::SetVisualizationMode(UINT in_mode) { m_pDataUploader->SetVisualizationMode(in_mode); } +void TileUpdateManager::SetVisualizationMode(UINT in_mode) +{ + Finish(); + m_pDataUploader->SetVisualizationMode(in_mode); +} //----------------------------------------------------------------------------- // Call this method once for each TileUpdateManager that shares heap/upload buffers diff --git a/TileUpdateManager/TileUpdateManager_vs2022.vcxproj b/TileUpdateManager/TileUpdateManager_vs2022.vcxproj new file mode 100644 index 0000000..2fce60c --- /dev/null +++ b/TileUpdateManager/TileUpdateManager_vs2022.vcxproj @@ -0,0 +1,147 @@ + + + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {12a36a45-4a15-48e3-b886-257e81fd57c6} + TileUpdateManager + 10.0 + TileUpdateManager + + + + StaticLibrary + true + v143 + Unicode + + + StaticLibrary + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + Level4 + true + _DEBUG;_LIB;%(PreprocessorDefinitions) + true + stdcpp17 + + + + + true + + + + + Level4 + true + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + true + Use + pch.h + /Ob3 %(AdditionalOptions) + Speed + AdvancedVectorExtensions2 + stdcpp17 + true + + + + + true + true + true + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/TileUpdateManager/TileUpdateManager_vs2022.vcxproj.filters b/TileUpdateManager/TileUpdateManager_vs2022.vcxproj.filters new file mode 100644 index 0000000..05a90ca --- /dev/null +++ b/TileUpdateManager/TileUpdateManager_vs2022.vcxproj.filters @@ -0,0 +1,123 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + + \ No newline at end of file diff --git a/TileUpdateManager/UpdateList.h b/TileUpdateManager/UpdateList.h index 70c3857..41e80d4 100644 --- a/TileUpdateManager/UpdateList.h +++ b/TileUpdateManager/UpdateList.h @@ -51,11 +51,13 @@ namespace Streaming // statistics are gathered on a common thread STATE_SUBMITTED, // start file i/o (DS) if necessary. if mapping only, go directly to notify - STATE_PACKED_MAPPING, - STATE_UPLOADING, // Start loading from file (ownership transitioned to FileStreamer) + + STATE_UPLOADING, // make sure the copy fence is valid, since copying and mapping can be concurrent STATE_COPY_PENDING, // check for gpu complete (copy fence value is valid) - STATE_NOTIFY_COMPLETE // the update is complete, notify. + STATE_PACKED_MAPPING, // wait for packed mips to be mapped before uploading + STATE_PACKED_COPY_PENDING // wait for upload of packed mips to complete + }; // initialize to ready diff --git a/TileUpdateManager/XeTexture.cpp b/TileUpdateManager/XeTexture.cpp index 0e00bc5..4095094 100644 --- a/TileUpdateManager/XeTexture.cpp +++ b/TileUpdateManager/XeTexture.cpp @@ -60,44 +60,20 @@ Streaming::XeTexture::XeTexture(const std::wstring& in_fileName) if (!inFile.good()) { Error(in_fileName + L"Unexpected Error"); } inFile.seekg(0, std::ios::end); - size_t fileSize = inFile.tellg(); - - // file offset to first packed mip - size_t packedOffset = m_fileHeader.m_subresourceInfo[m_fileHeader.m_mipInfo.m_numStandardMips].m_packedMipInfo.m_fileOffset; - size_t packedNumBytes = fileSize - packedOffset; - - size_t alignment = D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1; - packedNumBytes = (packedNumBytes + alignment) & (~alignment); - - m_packedMips.resize(packedNumBytes); - - inFile.seekg(packedOffset); - inFile.read((char*)m_packedMips.data(), packedNumBytes); + m_fileSize = inFile.tellg(); inFile.close(); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -void Streaming::XeTexture::WritePackedBits(void* out_pBits, UINT in_mip, UINT64 in_dstStrideBytes) +UINT Streaming::XeTexture::GetPackedMipFileOffset(UINT* out_pNumBytesTotal) { - UINT h = std::max(1, GetImageHeight() >> in_mip); - - // XeT is strictly intended for BCn formats that are multiples of 4 rows - UINT numRows = std::max(1, (h + 3) / 4); - - BYTE* pDst = (BYTE*)out_pBits; - - UINT fileOffsetBase = m_fileHeader.m_subresourceInfo[m_fileHeader.m_mipInfo.m_numStandardMips].m_packedMipInfo.m_fileOffset; - UINT byteOffset = m_fileHeader.m_subresourceInfo[in_mip].m_packedMipInfo.m_fileOffset - fileOffsetBase; - UINT rowPitch = m_fileHeader.m_subresourceInfo[in_mip].m_packedMipInfo.m_rowPitch; - - for (UINT i = 0; i < numRows; i++) + UINT packedOffset = m_fileHeader.m_subresourceInfo[m_fileHeader.m_mipInfo.m_numStandardMips].m_packedMipInfo.m_fileOffset; + if (out_pNumBytesTotal) { - memcpy(pDst, &m_packedMips[byteOffset], rowPitch); - - pDst += in_dstStrideBytes; - byteOffset += rowPitch; + *out_pNumBytesTotal = UINT(m_fileSize - packedOffset); } + return packedOffset; } //----------------------------------------------------------------------------- diff --git a/TileUpdateManager/XeTexture.h b/TileUpdateManager/XeTexture.h index 3624df3..cc9e766 100644 --- a/TileUpdateManager/XeTexture.h +++ b/TileUpdateManager/XeTexture.h @@ -47,15 +47,11 @@ namespace Streaming UINT GetImageHeight() const { return m_fileHeader.m_ddsHeader.height; } UINT GetMipCount() const { return m_fileHeader.m_ddsHeader.mipMapCount; } - const BYTE* GetPackedBits(UINT& out_numBytes) const { out_numBytes = (UINT)m_packedMips.size(); return m_packedMips.data(); } - - // WritePackedBits() is for the packed portion of the mip map, populated at startup. - // The pointer will be to a footprint for copying, with destination stride likely larger than mip contents. - void WritePackedBits(void* out_pBits, UINT in_mip, UINT64 in_dstStrideBytes); - // return value is # bytes. out_offset is byte offset into file UINT GetFileOffset(const D3D12_TILED_RESOURCE_COORDINATE& in_coord) const; + UINT GetPackedMipFileOffset(UINT* out_pNumBytesTotal = nullptr); + XeTexture(const std::wstring& in_filename); protected: XeTexture(const XeTexture&) = delete; @@ -66,16 +62,12 @@ namespace Streaming static const UINT MIN_STRIDE_BYTES{ 256 }; static const UINT NUM_BYTES_PER_TILE{ D3D12_TILED_RESOURCE_TILE_SIZE_IN_BYTES }; // tiles are always 64KB in size - Timer m_cpuTimer; - XetFileHeader m_fileHeader; + size_t m_fileSize{ 0 }; std::vector m_tileOffsets; std::vector m_metadataOffsets; - // bytes for packed mip are read at creation time - std::vector m_packedMips; - UINT GetLinearIndex(const D3D12_TILED_RESOURCE_COORDINATE& in_coord) const; }; } diff --git a/TileUpdateManager/pch.h b/TileUpdateManager/pch.h index a9311de..3d5f633 100644 --- a/TileUpdateManager/pch.h +++ b/TileUpdateManager/pch.h @@ -32,35 +32,19 @@ #include #include -#include #include #include -#include // Be sure to link with dxcompiler.lib. -#include // Shader reflection. - #include #include #include // for unique_ptr #include #include #include -#include #include #include -#include -#include #include -#include #include -#include -#include "d3dx12.h" +#include -#ifdef _DEBUG -#include -#define ASSERT(X) assert(X) -#define DebugPrint(...) OutputDebugString(Streaming::AutoString::Concat(__VA_ARGS__).c_str()); -#else -#define ASSERT(X) -#define DebugPrint(...) -#endif +#include "d3dx12.h" diff --git a/imgui/imgui_vs2022.vcxproj b/imgui/imgui_vs2022.vcxproj new file mode 100644 index 0000000..20f6d5e --- /dev/null +++ b/imgui/imgui_vs2022.vcxproj @@ -0,0 +1,103 @@ + + + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {45087328-C272-4BB6-BB09-95D899D2276A} + Win32Proj + imgui + 10.0 + imgui + + + + StaticLibrary + true + v143 + Unicode + + + StaticLibrary + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + false + + + true + + + + NotUsing + Level3 + MaxSpeed + true + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + true + pch.h + true + AdvancedVectorExtensions + + + Windows + true + true + true + + + + + NotUsing + Level3 + Disabled + true + _DEBUG;_LIB;%(PreprocessorDefinitions) + true + pch.h + true + + + Windows + true + + + + + + + + + + + + + + \ No newline at end of file diff --git a/imgui/imgui_vs2022.vcxproj.filters b/imgui/imgui_vs2022.vcxproj.filters new file mode 100644 index 0000000..7a7d6ff --- /dev/null +++ b/imgui/imgui_vs2022.vcxproj.filters @@ -0,0 +1,40 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/include/ArgParser.h b/include/ArgParser.h index 3520ea4..1bfc322 100644 --- a/include/ArgParser.h +++ b/include/ArgParser.h @@ -67,6 +67,7 @@ after running, m_float=20.27 and m_flipGravity=true #include #include #include +#include //----------------------------------------------------------------------------- // parse command line @@ -135,7 +136,7 @@ void ArgParser::AddArg(std::wstring token, ArgFunction f) inline void ArgParser::AddArg(std::wstring s, std::wstring description, ArgParser::ArgFunction f) { m_args.push_back(ArgPair(s, f)); - m_help << s << description << std::endl; + m_help << s << ": " << description << std::endl; } //----------------------------------------------------------------------------- @@ -147,7 +148,21 @@ inline void ArgParser::Parse() if ((2 == numArgs) && (std::wstring(L"?") == cmdLine[1])) { - MessageBox(0, m_help.str().c_str(), L"Command Line Args", MB_OK); + BOOL allocConsole = AllocConsole(); // returns false for console applications + if (allocConsole) + { + FILE* pOutStream; + ::freopen_s(&pOutStream, "CONOUT$", "w", stdout); + std::wcout.clear(); + } + + std::wcout << m_help.str(); + + if (allocConsole) + { + ::system("pause"); + } + exit(0); } diff --git a/include/D3D12GpuTimer.h b/include/D3D12GpuTimer.h index 0d21e90..aef2a8c 100644 --- a/include/D3D12GpuTimer.h +++ b/include/D3D12GpuTimer.h @@ -35,7 +35,7 @@ #include #include "d3dx12.h" -#include "DXSampleHelper.h" +#include "DebugHelper.h" class D3D12GpuTimer { diff --git a/include/DebugHelper.h b/include/DebugHelper.h new file mode 100644 index 0000000..d2a1c02 --- /dev/null +++ b/include/DebugHelper.h @@ -0,0 +1,88 @@ +//********************************************************* +// +// 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. +// +//********************************************************* + +/*----------------------------------------------------------------------------- +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 + +#ifdef _DEBUG +#include +#define ASSERT(X) assert(X) +inline void ThrowIfFailed(HRESULT hr) { assert(SUCCEEDED(hr)); } + +//================================================== +// auto t = AutoString::Concat("test: ", 3, "*", 2.75f, "\n"); +//================================================== +class AutoString +{ +public: + template static std::wstring Concat(Ts...ts) + { + std::wstringstream w; + Expander(w, ts...); + return w.str(); + } +private: + static void Expander(std::wstringstream&) { } + + template static void Expander(std::wstringstream& in_w, const T& t, Ts...ts) + { + in_w << t; + Expander(in_w, ts...); + } +}; +#define DebugPrint(...) OutputDebugString(AutoString::Concat(__VA_ARGS__).c_str()); + +#else +#define ASSERT(X) +#define DebugPrint(...) +#define ThrowIfFailed +#endif diff --git a/include/WindowCapture.h b/include/WindowCapture.h index 819f1bb..e4218ae 100644 --- a/include/WindowCapture.h +++ b/include/WindowCapture.h @@ -33,7 +33,6 @@ #include #include #include "d3dx12.h" -#include "DXSampleHelper.h" #pragma warning(push, 0) #include diff --git a/readme-images/project-settings.png b/readme-images/project-settings.png deleted file mode 100644 index da97918..0000000 Binary files a/readme-images/project-settings.png and /dev/null differ diff --git a/src/AssetUploader.cpp b/src/AssetUploader.cpp new file mode 100644 index 0000000..6102054 --- /dev/null +++ b/src/AssetUploader.cpp @@ -0,0 +1,150 @@ +//********************************************************* +// +// Copyright 2022 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. +// +//********************************************************* +#include "pch.h" + +#include "AssetUploader.h" +#include "DebugHelper.h" +#include "d3dx12.h" + +using Microsoft::WRL::ComPtr; + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void AssetUploader::Init(ID3D12Device* in_pDevice) +{ + ComPtr factory; + ThrowIfFailed(DStorageGetFactory(IID_PPV_ARGS(&factory))); + + DSTORAGE_QUEUE_DESC queueDesc{}; + queueDesc.Capacity = DSTORAGE_MAX_QUEUE_CAPACITY; + queueDesc.Priority = DSTORAGE_PRIORITY_NORMAL; + queueDesc.SourceType = DSTORAGE_REQUEST_SOURCE_MEMORY; + queueDesc.Device = in_pDevice; + ThrowIfFailed(factory->CreateQueue(&queueDesc, IID_PPV_ARGS(&m_memoryQueue))); + + in_pDevice->CreateFence(m_fenceValue, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)); + m_event = ::CreateEvent(nullptr, FALSE, FALSE, nullptr); +} + +//----------------------------------------------------------------------------- +// FIXME? only buffers supported. +//----------------------------------------------------------------------------- +AssetUploader::Request::Request(ID3D12Resource* in_pDstResource, + D3D12_RESOURCE_STATES in_before, D3D12_RESOURCE_STATES in_after) : + m_before(in_before), m_after(in_after) +{ + m_pResource = in_pDstResource; + + auto desc = in_pDstResource->GetDesc(); + ASSERT(D3D12_RESOURCE_DIMENSION_BUFFER == desc.Dimension); + + m_data.resize(GetRequiredIntermediateSize(in_pDstResource, 0, desc.MipLevels)); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void AssetUploader::SubmitRequest(Request* in_pRequest) +{ + ASSERT(D3D12_RESOURCE_DIMENSION_BUFFER == in_pRequest->GetResource()->GetDesc().Dimension); + m_requests.push_back(in_pRequest); + + DSTORAGE_REQUEST request = {}; + request.UncompressedSize = (UINT32)in_pRequest->GetBuffer().size(); + request.Options.SourceType = DSTORAGE_REQUEST_SOURCE_MEMORY; + request.Options.DestinationType = DSTORAGE_REQUEST_DESTINATION_BUFFER; + request.Source.Memory.Source = in_pRequest->GetBuffer().data(); + request.Source.Memory.Size = request.UncompressedSize; // uncompressed upload + request.Destination.Buffer.Offset = 0; + request.Destination.Buffer.Size = request.Source.Memory.Size; + request.Destination.Buffer.Resource = in_pRequest->GetResource(); + + m_memoryQueue->EnqueueRequest(&request); +} + +//----------------------------------------------------------------------------- +// wait for any in-flight uploads to complete, then free scratch data +//----------------------------------------------------------------------------- +void AssetUploader::WaitForInFlight() +{ + if (m_inFlight.size()) + { + // wait for previous command to complete before freeing that scratch memory + if (m_fence->GetCompletedValue() < m_fenceValue) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValue, m_event)); + WaitForSingleObject(m_event, INFINITE); + } + + // free scratch space + for (auto p : m_inFlight) + { + delete p; + } + m_inFlight.clear(); + } +} + +//----------------------------------------------------------------------------- +// waits for previous call to complete +// enqueues fence. submits DS work. +// adds Wait() on fence to queue. adds transition barriers to command list. +//----------------------------------------------------------------------------- +void AssetUploader::WaitForUploads(ID3D12CommandQueue* in_pDependentQueue, ID3D12GraphicsCommandList* in_pCommandList) +{ + WaitForInFlight(); + + // submit current work and set up cross-queue fence/wait + if (m_requests.size()) + { + m_fenceValue++; + m_memoryQueue->EnqueueSignal(m_fence.Get(), m_fenceValue); + m_memoryQueue->Submit(); + + in_pDependentQueue->Wait(m_fence.Get(), m_fenceValue); + + std::vector barriers; + + // free scratch space + for (auto p : m_requests) + { + barriers.push_back(CD3DX12_RESOURCE_BARRIER::Transition(p->GetResource(), p->GetBefore(), p->GetAfter())); + } + in_pCommandList->ResourceBarrier((UINT)barriers.size(), barriers.data()); + + // don't delete in-flight scratch data until commands complete + m_inFlight.swap(m_requests); + } +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +AssetUploader::~AssetUploader() +{ + WaitForInFlight(); + + ASSERT(0 == m_requests.size()); + CloseHandle(m_event); +} diff --git a/src/AssetUploader.h b/src/AssetUploader.h new file mode 100644 index 0000000..2f81e0a --- /dev/null +++ b/src/AssetUploader.h @@ -0,0 +1,74 @@ +//********************************************************* +// +// Copyright 2022 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 + +// Basic asset loader. gather all the things to upload, then upload them all at once +// Buffers only. Textures TBD. 32MB limit (unenforced) + +#include +#include +#include +#include "d3dx12.h" + +class AssetUploader +{ +public: + void Init(ID3D12Device* in_pDevice); + ~AssetUploader(); + + class Request + { + public: + Request(ID3D12Resource* m_pResource, D3D12_RESOURCE_STATES in_before, D3D12_RESOURCE_STATES in_after); + std::vector& GetBuffer() { return m_data; } + ID3D12Resource* GetResource() { return m_pResource; } + D3D12_RESOURCE_STATES GetBefore() const { return m_before; } + D3D12_RESOURCE_STATES GetAfter() const { return m_after; } + private: + std::vector m_data; // data to be uploaded + ID3D12Resource* m_pResource; // destination for request + + // need state transition barriers after upload completion + const D3D12_RESOURCE_STATES m_before; + const D3D12_RESOURCE_STATES m_after; + }; + + // hands off ownership of in_pRequest + void SubmitRequest(Request* in_pRequest); + + // submits outstanding data. Will block if previous call hasn't completed yet. + void WaitForUploads(ID3D12CommandQueue* in_pDependentQueue, ID3D12GraphicsCommandList* in_pCommandList); +private: + std::vector m_requests; + Microsoft::WRL::ComPtr m_memoryQueue; + Microsoft::WRL::ComPtr m_fence; + HANDLE m_event{ nullptr }; + UINT64 m_fenceValue{ 0 }; + + std::vector m_inFlight; + + void WaitForInFlight(); +}; diff --git a/src/Expanse.vcxproj b/src/Expanse.vcxproj index 254765a..a14fa5c 100644 --- a/src/Expanse.vcxproj +++ b/src/Expanse.vcxproj @@ -12,11 +12,10 @@ 16.0 - {E9BCC846-C1E9-402F-AC99-0E72195202AC} Win32Proj + {a92a871f-fff6-4a14-a3a2-ea583c0ea015} Expanse 10.0 - Expanse @@ -36,7 +35,6 @@ - @@ -59,16 +57,13 @@ true _DEBUG;_WINDOWS;%(PreprocessorDefinitions) true + stdcpp17 Use pch.h - $(SolutionDir)DirectXTK12;%(AdditionalIncludeDirectories) - true - stdcpp17 Windows true - %(AdditionalLibraryDirectories) @@ -79,84 +74,120 @@ true NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true + stdcpp17 Use pch.h - $(SolutionDir)DirectXTK12;%(AdditionalIncludeDirectories) - true - stdcpp17 - AdvancedVectorExtensions2 Windows true true true - %(AdditionalLibraryDirectories) + + Document + + + Document + + + + - - - stdcpp17 - Create Create - pch.h - pch.h - + + + - + + - - - - - + + + + + - + Document + $(OutDir)media + $(OutDir)media + + + Document + $(OutDir)media + $(OutDir)media + + + Document + $(OutDir)media + $(OutDir)media + + Document + + + Document + + + Document + + + Document + + + Document + + + + + Document + psFB + Pixel 6.0 psFB + Pixel 6.0 /T ps_6_5 -Qembed_debug %(AdditionalOptions) /T ps_6_5 %(AdditionalOptions) ps + Pixel 6.0 ps - 6.0 - Pixel Pixel + 6.0 -Qembed_debug %(AdditionalOptions) @@ -169,94 +200,34 @@ -Qembed_debug %(AdditionalOptions) + psFB Pixel 6.0 + psFB Pixel 6.0 /T ps_6_5 -Qembed_debug %(AdditionalOptions) /T ps_6_5 %(AdditionalOptions) - psFB - psFB - Pixel - Pixel - Document - dxc.exe %(FullPath) -I $(OutDir) -E ps -T ps_6_5 -Fo $(OutDir)\%(Filename).dxbc - $(OutDir)\%(Filename).dxbc - dxc.exe %(FullPath) -I $(OutDir) -E ps -T ps_6_5 -Fo $(OutDir)\%(Filename).dxbc - $(OutDir)\%(Filename).dxbc - Compile PS - Compile PS ps + Pixel 6.0 ps + Pixel 6.0 -Qembed_debug %(AdditionalOptions) - - - Document - dxc.exe %(FullPath) -I $(OutDir) -E vs -T vs_6_0 -Fo $(OutDir)\%(Filename).dxbc - dxc.exe %(FullPath) -I $(OutDir) -E vs -T vs_6_0 -Fo $(OutDir)\%(Filename).dxbc - Compile VS - $(OutDir)\%(Filename).dxbc - Compile VS - $(OutDir)\%(Filename).dxbc + vs Vertex 6.0 + vs Vertex 6.0 - vs - vs -Qembed_debug %(AdditionalOptions) - - - - Document - - - - - Document - $(OutDir)media - $(OutDir)media - - - - - Document - - - Document - - - Document - - - - - Document - - - Document - - - Document - $(OutDir)media - $(OutDir)media - - - Document - $(OutDir)media - $(OutDir)media - - - Document - - + Document @@ -264,6 +235,9 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. diff --git a/src/Expanse.vcxproj.filters b/src/Expanse.vcxproj.filters index ddac531..f3e8943 100644 --- a/src/Expanse.vcxproj.filters +++ b/src/Expanse.vcxproj.filters @@ -3,40 +3,75 @@ {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - {c80bf9a2-2a5d-406d-beeb-997ae6e827db} - - - {40b1771a-863e-4864-820c-3d1a70c5a936} + + {7ee799ba-1694-4f14-9791-b724227461dd} - - {00601a48-65a5-449b-a20f-ec9af2c06540} + + {bcb9e86a-bb53-4591-9f4d-4b4750c97c11} - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {95fee67b-a66c-49dd-a19f-43e22f6ef6fb} - - {ba988a2d-807e-4833-955f-d42faa25cf06} + + {62863df4-8463-4043-82e4-00ee2fa92921} - - {f29a7327-9407-45f2-9513-75028df51d0d} + + {a6225a17-0520-4935-87c2-0655029df274} - + + + + + config + + + media + + + scripts + + + shaders + + + shaders + + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files - + Source Files - + + Source Files + + Source Files @@ -45,146 +80,105 @@ Source Files - + Source Files - + Source Files - + Source Files - + Source Files + + Header Files + Header Files - - DirectXTK12 + + Header Files - + Header Files - + Header Files - - DirectXTK12 + + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - - include + + Header Files - - include + + Header Files - + include - + include - - DirectXTK12 - include include - - Header Files + + include - - Header Files + + include - - Header Files + + include - - Header Files + + include + + + include - - Shaders - - - Scripts - - - Scripts - - - Scripts - - - media - - - Scripts - - - config - - - media - - - media - - - Scripts - - - Shaders - - - Shaders - - - config - - - - - Shaders + + shaders - - Shaders + + shaders - - Shaders + + shaders - - Shaders + + shaders - - Shaders + + shaders - - Shaders + + shaders - - - \ No newline at end of file diff --git a/src/Expanse_vs2022.vcxproj b/src/Expanse_vs2022.vcxproj new file mode 100644 index 0000000..33b183e --- /dev/null +++ b/src/Expanse_vs2022.vcxproj @@ -0,0 +1,241 @@ + + + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {E9BCC846-C1E9-402F-AC99-0E72195202AC} + expanse + 10.0 + Expanse + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + Level4 + true + _DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + stdcpp17 + Use + pch.h + + + Windows + true + + + + + Level4 + true + true + true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + stdcpp17 + Use + pch.h + + + Windows + true + true + true + + + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + $(OutDir)media + $(OutDir)media + + + Document + $(OutDir)media + $(OutDir)media + + + Document + $(OutDir)media + $(OutDir)media + + + Document + + + Document + + + + + + + + + + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Document + + + psFB + Pixel + 6.5 + -Qembed_debug %(AdditionalOptions) + psFB + Pixel + 6.5 + + + ps + Pixel + 6.0 + -Qembed_debug %(AdditionalOptions) + ps + Pixel + 6.0 + + + vs + Vertex + 6.0 + -Qembed_debug %(AdditionalOptions) + vs + Vertex + 6.0 + + + psFB + Pixel + 6.5 + -Qembed_debug %(AdditionalOptions) + psFB + Pixel + 6.5 + + + ps + Pixel + 6.0 + -Qembed_debug %(AdditionalOptions) + ps + Pixel + 6.0 + + + vs + Vertex + 6.0 + -Qembed_debug %(AdditionalOptions) + vs + Vertex + 6.0 + + + Document + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/Expanse_vs2022.vcxproj.filters b/src/Expanse_vs2022.vcxproj.filters new file mode 100644 index 0000000..c8346ee --- /dev/null +++ b/src/Expanse_vs2022.vcxproj.filters @@ -0,0 +1,195 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {b85f76f3-fe1c-4329-8013-cdabe12d5fd8} + + + {23f41b89-5d6f-48b1-8016-ea5107d4976f} + + + {6e46226a-0c46-4bfa-a464-5190adf0fe4e} + + + {aca759ef-33ea-4723-8a6f-84302ce25d77} + + + {71df60be-5005-472b-a6c3-c52100ccae2b} + + + + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + include + + + Header Files + + + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + Shaders + + + + + Shaders + + + Shaders + + + Shaders + + + scripts + + + media + + + config + + + config + + + media + + + media + + + scripts + + + scripts + + + scripts + + + scripts + + + \ No newline at end of file diff --git a/src/FrustumViewer.cpp b/src/FrustumViewer.cpp index 90280d8..5364cda 100644 --- a/src/FrustumViewer.cpp +++ b/src/FrustumViewer.cpp @@ -25,8 +25,9 @@ //********************************************************* #include "pch.h" -#include "DXSampleHelper.h" #include "FrustumViewer.h" +#include "DebugHelper.h" +#include "AssetUploader.h" using namespace DirectX; @@ -36,9 +37,7 @@ FrustumViewer::FrustumViewer(ID3D12Device* in_pDevice, const DXGI_FORMAT in_swapChainFormat, const DXGI_FORMAT in_depthFormat, UINT in_sampleCount, - std::function in_initializeBuffer) : + AssetUploader& in_assetUploader) : m_world(XMMatrixIdentity()) , m_frustumConstants{} , m_numIndices(0) @@ -77,7 +76,9 @@ FrustumViewer::FrustumViewer(ID3D12Device* in_pDevice, nullptr, IID_PPV_ARGS(&m_vertexBuffer))); - in_initializeBuffer(m_vertexBuffer.Get(), vertices, vertexBufferSize, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); + auto pRequest = new AssetUploader::Request(m_vertexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); + memcpy(pRequest->GetBuffer().data(), vertices, vertexBufferSize); + in_assetUploader.SubmitRequest(pRequest); m_vertexBufferView.SizeInBytes = vertexBufferSize; m_vertexBufferView.StrideInBytes = sizeof(Vertex); @@ -109,7 +110,9 @@ FrustumViewer::FrustumViewer(ID3D12Device* in_pDevice, nullptr, IID_PPV_ARGS(&m_indexBuffer))); - in_initializeBuffer(m_indexBuffer.Get(), indices, indexBufferSize, D3D12_RESOURCE_STATE_INDEX_BUFFER); + auto pRequest = new AssetUploader::Request(m_indexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_INDEX_BUFFER); + memcpy(pRequest->GetBuffer().data(), indices, indexBufferSize); + in_assetUploader.SubmitRequest(pRequest); m_indexBufferView.SizeInBytes = indexBufferSize; m_indexBufferView.Format = DXGI_FORMAT_R16_UINT; diff --git a/src/FrustumViewer.h b/src/FrustumViewer.h index 80af06b..6c4f17f 100644 --- a/src/FrustumViewer.h +++ b/src/FrustumViewer.h @@ -38,9 +38,7 @@ class FrustumViewer const DXGI_FORMAT in_swapChainFormat, const DXGI_FORMAT in_depthFormat, UINT in_sampleCount, - std::function in_initializeBuffer); + class AssetUploader& in_assetUploader); void Draw(ID3D12GraphicsCommandList* in_pCL, const DirectX::XMMATRIX& in_combinedTransform, diff --git a/src/MinMipMapWA.cpp b/src/MinMipMapWA.cpp deleted file mode 100644 index 606a224..0000000 --- a/src/MinMipMapWA.cpp +++ /dev/null @@ -1,324 +0,0 @@ -#include "pch.h" -#include "MinMipMapWA.h" -#include "DXSampleHelper.h" - -// Interlocked* only works on int or uint 32b types - -struct WAConstants -{ - UINT32 g_numLevels; - UINT32 g_feedbackWidth; - UINT32 g_feedbackHeight; - float g_renderWidth; - float g_renderHeight; -}; - -ComPtr MinMipMapWA::g_vertexShader; -ComPtr MinMipMapWA::g_pixelShader; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -MinMipMapWA::MinMipMapWA(ID3D12Device* in_pDevice, UINT64 in_imageWidth, UINT in_imageHeight) -{ - - UINT64 resolveWidth = UINT64(std::ceil(float(in_imageWidth) / float(m_hardwareRegionDim))); - UINT resolveHeight = UINT(std::ceil(float(in_imageHeight) / float(m_hardwareRegionDim))); - - //--------------------------------------------- - // Create root signature - //--------------------------------------------- - { - D3D12_FEATURE_DATA_ROOT_SIGNATURE featureData = {}; - - // This is the highest version the sample supports. If CheckFeatureSupport succeeds, the HighestVersion returned will not be greater than this. - featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1; - - D3D12_DESCRIPTOR_RANGE1 ranges[2]; - ranges[0] = CD3DX12_DESCRIPTOR_RANGE1( - D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0, 0, - D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE, 0); - ranges[1] = CD3DX12_DESCRIPTOR_RANGE1( - D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 1, 0, - D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE | D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE, 1); - - CD3DX12_ROOT_PARAMETER1 rootParameters[3] = {}; - UINT num32BitValues = sizeof(WAConstants) / 4; - rootParameters[0].InitAsConstants(num32BitValues, 0, D3D12_ROOT_DESCRIPTOR_FLAG_NONE, D3D12_SHADER_VISIBILITY_PIXEL); - rootParameters[1].InitAsDescriptorTable(_countof(ranges), ranges, D3D12_SHADER_VISIBILITY_PIXEL); - - D3D12_STATIC_SAMPLER_DESC staticSampler = {}; - staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; - staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER; - staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_BORDER; - staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_BORDER; - staticSampler.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; - staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; - staticSampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - staticSampler.ShaderRegister = 0; - staticSampler.MaxLOD = 0xff; - - CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc; - rootSignatureDesc.Init_1_1(_countof(rootParameters), rootParameters, - 1, &staticSampler, - D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); - - ComPtr signature; - ComPtr error; - ThrowIfFailed(D3DX12SerializeVersionedRootSignature(&rootSignatureDesc, featureData.HighestVersion, &signature, &error)); - ThrowIfFailed(in_pDevice->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature))); - } - - //--------------------------------------------- - // Create shaders & pso - //--------------------------------------------- - { - const char shader[] = "\ - struct VS_OUT \ - { \ - float4 pos : SV_POSITION; \ - float2 uv : TEXCOORD0; \ - }; \ - \ - cbuffer cb0 : register(b0) \ - { \ - uint g_numLevels; \ - uint2 g_feedbackDim; \ - float g_renderWidth; \ - float g_renderHeight; \ - }; \ - \ - VS_OUT vs(uint vertexID : SV_VertexID) \ - { \ - VS_OUT output; \ - float2 grid = float2((vertexID & 1) << 1, vertexID & 2); \ - output.pos = float4(grid + float2(-1.0f, -1.0), 0.0f, 1.0f); \ - output.uv.xy = 0.5f * grid; \ - output.uv.y = 1-output.uv.y; \ - return output; \ - } \ - Texture2D feedback : register(t0); \ - RWTexture2D minmip : register(u1); \ - SamplerState g_samPoint : register(s0); \ - uint psTypeConvert(VS_OUT input) : SV_Target \ - { \ - uint2 uv = input.uv * g_feedbackDim; \ - return minmip[uv]; \ - } \ - void ps(VS_OUT input) \ - { \ - float2 uv = input.uv; \ - uint2 destTilePos = uv * g_feedbackDim; \ - uint2 srcTilePos = destTilePos; \ - uint2 screenDim = uint2(g_renderWidth, g_renderHeight); \ - uint2 screenPos = uv * screenDim; \ - uint2 regionDim = screenDim / g_feedbackDim; \ - uint2 offset = screenPos - (srcTilePos * regionDim); \ - for (uint i = 0; i < g_numLevels; i++) { \ - if (0!=feedback.SampleLevel(g_samPoint, uv, i).x) \ - { InterlockedMin(minmip[destTilePos], i); return;} \ - srcTilePos >>= 1; screenDim /= 2; \ - screenPos = (srcTilePos * regionDim) + offset; \ - uv = float2(screenPos) / screenDim; \ - } \ - }"; - // screenpos is say [0..255] - // feedbackDim is say 8 - // regionDim then is 256/8 = 32, which is # texels per tile - // tilePos will be 0,1,2,3,4,5,6,7 - // (tilePos * regionDim) + offset should equal screenpos for mip0 - // offset should be [0..31] - - // Load and compile shaders. - ID3DBlob* pErrorMsgs = 0; - HRESULT hr = 0; - - if (nullptr == g_vertexShader) - { - hr = D3DCompile(shader, strlen(shader), NULL, NULL, NULL, "vs", "vs_5_0", 0, 0, &g_vertexShader, &pErrorMsgs); - if (FAILED(hr) && (pErrorMsgs)) - { - char* pMsgs = (char*)pErrorMsgs->GetBufferPointer(); - pErrorMsgs->Release(); - } - hr = D3DCompile(shader, strlen(shader), NULL, NULL, NULL, "ps", "ps_5_0", 0, 0, &g_pixelShader, &pErrorMsgs); - if (FAILED(hr) && (pErrorMsgs)) - { - char* pMsgs = (char*)pErrorMsgs->GetBufferPointer(); - pErrorMsgs->Release(); - } - } - - D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = - { - { "SV_Position", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, - }; - - // Describe and create the graphics pipeline state object (PSO). - D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc{}; - - psoDesc.pRootSignature = m_rootSignature.Get(); - psoDesc.VS = CD3DX12_SHADER_BYTECODE(g_vertexShader.Get()); - psoDesc.PS = CD3DX12_SHADER_BYTECODE(g_pixelShader.Get()); - psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); - psoDesc.SampleMask = UINT_MAX; - psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); - psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; - - CD3DX12_DEPTH_STENCIL_DESC depthStencilDesc(D3D12_DEFAULT); - depthStencilDesc.DepthEnable = FALSE; - depthStencilDesc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; - depthStencilDesc.DepthFunc = D3D12_COMPARISON_FUNC_NEVER; - psoDesc.DepthStencilState = depthStencilDesc; - - psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) }; - psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - psoDesc.NumRenderTargets = 0; - psoDesc.SampleDesc.Count = 1; - - ThrowIfFailed(in_pDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState))); - - ComPtr psTypeConvert; - hr = D3DCompile(shader, strlen(shader), NULL, NULL, NULL, "psTypeConvert", "ps_5_0", 0, 0, &psTypeConvert, &pErrorMsgs); - if (FAILED(hr) && (pErrorMsgs)) - { - char* pMsgs = (char*)pErrorMsgs->GetBufferPointer(); - pErrorMsgs->Release(); - } - psoDesc.PS = CD3DX12_SHADER_BYTECODE(psTypeConvert.Get()); - psoDesc.NumRenderTargets = 1; - psoDesc.RTVFormats[0] = DXGI_FORMAT_R8_UINT; - ThrowIfFailed(in_pDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_convertPSO))); - } - - D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {}; - srvHeapDesc.NumDescriptors = 2; - srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - ThrowIfFailed(in_pDevice->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&m_srvHeap))); - m_srvHeap->SetName(L"m_srvHeap"); - - ThrowIfFailed(in_pDevice->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), - D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8_UINT, resolveWidth, resolveHeight), - D3D12_RESOURCE_STATE_RESOLVE_DEST, nullptr, - IID_PPV_ARGS(&m_manualMinMipResolve))); - m_manualMinMipResolve->SetName(L"m_manualMinMipResolve"); - - D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc{}; - srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = -1; - // Can't sample UINT, so use unorm. only care about 0 or not 0 - srvDesc.Format = DXGI_FORMAT_R8_UNORM; - srvDesc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(0, 0, 0, 0); - in_pDevice->CreateShaderResourceView(m_manualMinMipResolve.Get(), &srvDesc, - m_srvHeap->GetCPUDescriptorHandleForHeapStart()); - - // CPU heap used for ClearUnorderedAccessView on feedback map - { - D3D12_DESCRIPTOR_HEAP_DESC desc = {}; - desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - desc.NumDescriptors = 1; // only need the one for the single feedback map - desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - ThrowIfFailed(in_pDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_clearUavHeap))); - m_clearUavHeap->SetName(L"SFB m_clearUavHeap"); - } - - // will render to final min mip map (type conversion only) - { - D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; - rtvHeapDesc.NumDescriptors = 1; - rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - ThrowIfFailed(in_pDevice->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void MinMipMapWA::WA(ID3D12Resource* out_pMinMipMap, ID3D12GraphicsCommandList* in_pCmdList) -{ - { - ComPtr device; - in_pCmdList->GetDevice(IID_PPV_ARGS(&device)); - - if (m_firstFrame) - { - m_firstFrame = false; - - D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_rtvHeap->GetCPUDescriptorHandleForHeapStart(); - device->CreateRenderTargetView(out_pMinMipMap, nullptr, rtvHandle); - - auto desc = out_pMinMipMap->GetDesc(); - desc.Format = DXGI_FORMAT_R32_UINT; - desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; - ThrowIfFailed(device->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), - D3D12_HEAP_FLAG_NONE, - &desc, - D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, - IID_PPV_ARGS(&m_mipResolve32b))); - m_mipResolve32b->SetName(L"m_mipResolve32b"); - - D3D12_UNORDERED_ACCESS_VIEW_DESC vd = {}; - vd.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; - vd.Format = m_mipResolve32b->GetDesc().Format; - - D3D12_CPU_DESCRIPTOR_HANDLE secondHeapCPU = m_clearUavHeap->GetCPUDescriptorHandleForHeapStart(); - - device->CreateUnorderedAccessView(m_mipResolve32b.Get(), nullptr, &vd, secondHeapCPU); - - device->CopyDescriptorsSimple(1, - CD3DX12_CPU_DESCRIPTOR_HANDLE( - m_srvHeap->GetCPUDescriptorHandleForHeapStart(), - 1, device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)), - secondHeapCPU, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - } - - UINT clearValue[4]{ UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX }; - in_pCmdList->ClearUnorderedAccessViewUint( - CD3DX12_GPU_DESCRIPTOR_HANDLE(m_srvHeap->GetGPUDescriptorHandleForHeapStart(), - 1, device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)), - m_clearUavHeap->GetCPUDescriptorHandleForHeapStart(), - m_mipResolve32b.Get(), - clearValue, 0, nullptr); - } - - in_pCmdList->SetGraphicsRootSignature(m_rootSignature.Get()); - - ID3D12DescriptorHeap* ppHeaps[] = { m_srvHeap.Get() }; - in_pCmdList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps); - - D3D12_VIEWPORT viewport = CD3DX12_VIEWPORT(m_manualMinMipResolve.Get()); - D3D12_RECT scissor = CD3DX12_RECT(0, 0, (LONG)m_manualMinMipResolve->GetDesc().Width, m_manualMinMipResolve->GetDesc().Height); - - UINT num32BitValues = sizeof(WAConstants) / 4; - auto desc = out_pMinMipMap->GetDesc(); - WAConstants waConstants{ m_manualMinMipResolve->GetDesc().MipLevels, - (UINT32)desc.Width, desc.Height, viewport.Width, viewport.Height }; - in_pCmdList->SetGraphicsRoot32BitConstants(0, num32BitValues, &waConstants, 0); - - in_pCmdList->SetGraphicsRootDescriptorTable(1, m_srvHeap->GetGPUDescriptorHandleForHeapStart()); - - in_pCmdList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - - in_pCmdList->RSSetViewports(1, &viewport); - in_pCmdList->RSSetScissorRects(1, &scissor); - in_pCmdList->IASetIndexBuffer(nullptr); - in_pCmdList->IASetVertexBuffers(0, 0, nullptr); - - in_pCmdList->SetPipelineState(m_pipelineState.Get()); - in_pCmdList->DrawInstanced(4, 1, 0, 0); - - { - viewport = CD3DX12_VIEWPORT(out_pMinMipMap); - scissor = CD3DX12_RECT(0, 0, (LONG)viewport.Width, (LONG)viewport.Height); - in_pCmdList->RSSetViewports(1, &viewport); - in_pCmdList->RSSetScissorRects(1, &scissor); - - in_pCmdList->SetPipelineState(m_convertPSO.Get()); - D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_rtvHeap->GetCPUDescriptorHandleForHeapStart(); - in_pCmdList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr); - in_pCmdList->DrawInstanced(4, 1, 0, 0); - } -} diff --git a/src/MinMipMapWA.h b/src/MinMipMapWA.h deleted file mode 100644 index 32860db..0000000 --- a/src/MinMipMapWA.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include - -#define MIN_MIP_MAP_WA_REGION_SIZE 128 - -class MinMipMapWA -{ -public: - MinMipMapWA(ID3D12Device* in_pDevice, UINT64 in_imageWidth, UINT in_imageHeight); - - ComPtr& GetResource() { return m_manualMinMipResolve; } - - void WA(ID3D12Resource* out_pMinMipMap, ID3D12GraphicsCommandList* in_pCmdList); - -private: - static const UINT m_hardwareRegionDim{ MIN_MIP_MAP_WA_REGION_SIZE }; - - ComPtr m_rootSignature; - ComPtr m_pipelineState; - - ComPtr m_convertPSO; - - ComPtr m_manualMinMipResolve; - ComPtr m_mipResolve32b; - - ComPtr m_srvHeap; - ComPtr m_clearUavHeap; - ComPtr m_rtvHeap; - - static ComPtr g_vertexShader; - static ComPtr g_pixelShader; - - bool m_firstFrame{ true }; -}; diff --git a/src/Scene.cpp b/src/Scene.cpp index a5c8402..43a1410 100644 --- a/src/Scene.cpp +++ b/src/Scene.cpp @@ -34,7 +34,7 @@ #include "TextureViewer.h" #include "BufferViewer.h" #include "FrustumViewer.h" - +#include "DebugHelper.h" #include "WindowCapture.h" #pragma comment(lib, "d3d12.lib") @@ -95,18 +95,18 @@ Scene::Scene(const CommandLineArgs& in_args, HWND in_hwnd) : , m_pGpuTimer(nullptr) { m_windowInfo.cbSize = sizeof(WINDOWINFO); -#if ENABLE_DEBUG_LAYER - InitDebugLayer(); -#endif - UINT flags = 0; + UINT factoryFlags = 0; + #ifdef _DEBUG - flags |= DXGI_CREATE_FACTORY_DEBUG; + factoryFlags |= DXGI_CREATE_FACTORY_DEBUG; + InitDebugLayer(); #endif - if (FAILED(CreateDXGIFactory2(flags, IID_PPV_ARGS(&m_factory)))) + + if (FAILED(CreateDXGIFactory2(factoryFlags, IID_PPV_ARGS(&m_factory)))) { - flags &= ~DXGI_CREATE_FACTORY_DEBUG; - ThrowIfFailed(CreateDXGIFactory2(flags, IID_PPV_ARGS(&m_factory))); + factoryFlags &= ~DXGI_CREATE_FACTORY_DEBUG; + ThrowIfFailed(CreateDXGIFactory2(factoryFlags, IID_PPV_ARGS(&m_factory))); } ComPtr adapter; @@ -195,14 +195,13 @@ Scene::Scene(const CommandLineArgs& in_args, HWND in_hwnd) : m_pGui = new Gui(m_hwnd, m_device.Get(), m_srvHeap.Get(), (UINT)DescriptorHeapOffsets::GUI, m_swapBufferCount, SharedConstants::SWAP_CHAIN_FORMAT, adapterDescription, m_args); + m_assetUploader.Init(m_device.Get()); + m_pFrustumViewer = new FrustumViewer(m_device.Get(), SharedConstants::SWAP_CHAIN_FORMAT, SharedConstants::DEPTH_FORMAT, m_args.m_sampleCount, - [&](ID3D12Resource* out_pBuffer, const void* in_pBytes, size_t in_numBytes, D3D12_RESOURCE_STATES in_finalState) - { - SceneObjects::InitializeBuffer(out_pBuffer, in_pBytes, in_numBytes, in_finalState); - }); + m_assetUploader); // statistics gathering if (m_args.m_timingFrameFileName.size() && (m_args.m_timingStopFrame >= m_args.m_timingStartFrame)) @@ -478,7 +477,7 @@ void Scene::CreateDescriptorHeaps() srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(m_device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&m_srvHeap))); - NAME_D3D12_OBJECT(m_srvHeap); + m_srvHeap->SetName(L"m_srvHeap"); // render target view heap // NOTE: we have an MSAA target plus a swap chain, so m_swapBufferCount + 1 @@ -486,13 +485,14 @@ void Scene::CreateDescriptorHeaps() rtvHeapDesc.NumDescriptors = m_swapBufferCount + 1; rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap))); + m_srvHeap->SetName(L"m_rtvHeap"); // depth buffer view heap D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {}; dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; dsvHeapDesc.NumDescriptors = 1; ThrowIfFailed(m_device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap))); - NAME_D3D12_OBJECT(m_dsvHeap); + m_srvHeap->SetName(L"m_dsvHeap"); } //----------------------------------------------------------------------------- @@ -804,13 +804,13 @@ void Scene::LoadSpheres() if ((nullptr == m_pSky) && (m_args.m_skyTexture.size())) // only 1 sky { auto tf = m_args.m_mediaDir + L"\\\\" + m_args.m_skyTexture; - m_pSky = new SceneObjects::Sky(tf, m_pTileUpdateManager.get(), pHeap, m_device.Get(), m_args.m_sampleCount, descCPU); + m_pSky = new SceneObjects::Sky(tf, m_pTileUpdateManager.get(), pHeap, m_device.Get(), m_assetUploader, m_args.m_sampleCount, descCPU); o = m_pSky; } else if (nullptr == m_pTerrainSceneObject) { - m_pTerrainSceneObject = new SceneObjects::Terrain(m_args.m_terrainTexture, m_pTileUpdateManager.get(), pHeap, m_device.Get(), m_args.m_sampleCount, descCPU, m_args); + m_pTerrainSceneObject = new SceneObjects::Terrain(m_args.m_terrainTexture, m_pTileUpdateManager.get(), pHeap, m_device.Get(), m_args.m_sampleCount, descCPU, m_args, m_assetUploader); m_terrainObjectIndex = objectIndex; o = m_pTerrainSceneObject; } @@ -821,7 +821,7 @@ void Scene::LoadSpheres() if (nullptr == m_pEarth) { sphereProperties.m_mirrorU = false; - o = new SceneObjects::Planet(textureFilename, m_pTileUpdateManager.get(), pHeap, m_device.Get(), m_args.m_sampleCount, descCPU, sphereProperties); + o = new SceneObjects::Planet(textureFilename, m_pTileUpdateManager.get(), pHeap, m_device.Get(), m_assetUploader, m_args.m_sampleCount, descCPU, sphereProperties); m_pEarth = o; } else @@ -844,7 +844,7 @@ void Scene::LoadSpheres() if (nullptr == m_pFirstSphere) { sphereProperties.m_mirrorU = true; - o = new SceneObjects::Planet(textureFilename, m_pTileUpdateManager.get(), pHeap, m_device.Get(), m_args.m_sampleCount, descCPU, sphereProperties); + o = new SceneObjects::Planet(textureFilename, m_pTileUpdateManager.get(), pHeap, m_device.Get(), m_assetUploader, m_args.m_sampleCount, descCPU, sphereProperties); m_pFirstSphere = o; } else @@ -898,6 +898,9 @@ void Scene::LoadSpheres() m_numSpheresLoaded--; } } + + // check the non-streaming uploader to see if anything needs to be uploaded or any memory can be freed + m_assetUploader.WaitForUploads(m_commandQueue.Get(), m_commandList.Get()); } //----------------------------------------------------------------------------- @@ -1619,6 +1622,10 @@ bool Scene::Draw() DrainTiles(); + // prepare for new commands (need an open command list for LoadSpheres) + m_commandAllocators[m_frameIndex]->Reset(); + m_commandList->Reset((ID3D12CommandAllocator*)m_commandAllocators[m_frameIndex].Get(), nullptr); + // load more spheres? // SceneResource destruction/creation must be done outside of BeginFrame/EndFrame LoadSpheres(); @@ -1672,8 +1679,6 @@ bool Scene::Draw() //------------------------------------------- // draw everything //------------------------------------------- - m_commandAllocators[m_frameIndex]->Reset(); - m_commandList->Reset((ID3D12CommandAllocator*)m_commandAllocators[m_frameIndex].Get(), nullptr); { GpuScopeTimer gpuScopeTimer(m_pGpuTimer, m_commandList.Get(), "GPU Frame Time"); diff --git a/src/Scene.h b/src/Scene.h index 139b945..fad4a98 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -27,11 +27,10 @@ #pragma once #include "CommandLineArgs.h" -#include "DXSampleHelper.h" #include "SharedConstants.h" #include "SceneObject.h" - #include "FrameEventTracing.h" +#include "AssetUploader.h" class Scene { @@ -253,4 +252,6 @@ class Scene void StartScene(); void DrawUI(float in_cpuProcessFeedbackTime); + + AssetUploader m_assetUploader; }; diff --git a/src/SceneObject.cpp b/src/SceneObject.cpp index 976fa7b..1023553 100644 --- a/src/SceneObject.cpp +++ b/src/SceneObject.cpp @@ -38,8 +38,8 @@ #include "SceneObject.h" #include "SharedConstants.h" #include "Scene.h" - #include "TerrainGenerator.h" +#include "AssetUploader.h" //------------------------------------------------------------------------- // constructor @@ -234,11 +234,12 @@ void SceneObjects::BaseObject::CreatePipelineState( //------------------------------------------------------------------------- std::wstring SceneObjects::BaseObject::GetAssetFullPath(const std::wstring& in_filename) { - constexpr size_t PATHBUFFERSIZE = MAX_PATH * 4; - TCHAR buffer[PATHBUFFERSIZE]; - GetAssetsPath(buffer, PATHBUFFERSIZE); - std::wstring directory = buffer; - return directory + in_filename; + WCHAR buffer[MAX_PATH]; + GetModuleFileName(nullptr, buffer, MAX_PATH); + std::wstring exePath(buffer); + exePath.resize(exePath.rfind('\\') + 1); + std::wstring path = exePath + in_filename; + return path; } //------------------------------------------------------------------------- @@ -430,39 +431,12 @@ class Staging D3D12_RESOURCE_STATES m_finalState; }; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void SceneObjects::InitializeBuffer(ID3D12Resource* out_pBuffer, - const void* in_pBytes, size_t in_numBytes, D3D12_RESOURCE_STATES in_finalState) -{ - D3D12_RESOURCE_DESC desc = out_pBuffer->GetDesc(); - - Staging staging(out_pBuffer, desc, in_finalState); - - D3D12_SUBRESOURCE_DATA data{ in_pBytes, LONG_PTR(in_numBytes), LONG_PTR(in_numBytes) }; - - UpdateSubresources<1>(staging.GetCommandList(), out_pBuffer, staging.GetResource(), 0, 0, 1, &data); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void SceneObjects::InitializeTexture(ID3D12Resource* out_pTexture, - size_t in_numSubResources, const D3D12_SUBRESOURCE_DATA* in_pSubresources, D3D12_RESOURCE_STATES in_finalState) -{ - UINT64 nStageSize = GetRequiredIntermediateSize(out_pTexture, 0, static_cast(in_numSubResources)); - D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(nStageSize); - - Staging staging(out_pTexture, desc, in_finalState); - - UpdateSubresources(staging.GetCommandList(), out_pTexture, staging.GetResource(), 0, 0, static_cast(in_numSubResources), in_pSubresources); -} - //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void SceneObjects::CreateSphereResources( ID3D12Resource** out_ppVertexBuffer, ID3D12Resource** out_ppIndexBuffer, - ID3D12Device* in_pDevice, const SphereGen::Properties& in_sphereProperties) + ID3D12Device* in_pDevice, const SphereGen::Properties& in_sphereProperties, + AssetUploader& in_assetUploader) { std::vector sphereVerts; std::vector sphereIndices; @@ -483,8 +457,9 @@ void SceneObjects::CreateSphereResources( nullptr, IID_PPV_ARGS(out_ppVertexBuffer))); - InitializeBuffer(*out_ppVertexBuffer, sphereVerts.data(), - vertexBufferSize, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); + auto* pRequest = new AssetUploader::Request(*out_ppVertexBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); + memcpy(pRequest->GetBuffer().data(), sphereVerts.data(), vertexBufferSize); + in_assetUploader.SubmitRequest(pRequest); } // build index buffer @@ -501,15 +476,16 @@ void SceneObjects::CreateSphereResources( nullptr, IID_PPV_ARGS(out_ppIndexBuffer))); - InitializeBuffer(*out_ppIndexBuffer, sphereIndices.data(), - indexBufferSize, D3D12_RESOURCE_STATE_INDEX_BUFFER); + auto* pRequest = new AssetUploader::Request(*out_ppIndexBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_INDEX_BUFFER); + memcpy(pRequest->GetBuffer().data(), sphereIndices.data(), indexBufferSize); + in_assetUploader.SubmitRequest(pRequest); } } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void SceneObjects::CreateSphere(SceneObjects::BaseObject* out_pObject, - ID3D12Device* in_pDevice, + ID3D12Device* in_pDevice, AssetUploader& in_assetUploader, const SphereGen::Properties& in_sphereProperties, UINT in_numLods) { @@ -530,7 +506,7 @@ void SceneObjects::CreateSphere(SceneObjects::BaseObject* out_pObject, ID3D12Resource* pVertexBuffer{ nullptr }; ID3D12Resource* pIndexBuffer{ nullptr }; - CreateSphereResources(&pVertexBuffer, &pIndexBuffer, in_pDevice, sphereProperties); + CreateSphereResources(&pVertexBuffer, &pIndexBuffer, in_pDevice, sphereProperties, in_assetUploader); out_pObject->SetGeometry( pVertexBuffer, (UINT)sphereVerts.size(), (UINT)sizeof(SphereGen::Vertex), @@ -546,7 +522,8 @@ SceneObjects::Terrain::Terrain(const std::wstring& in_filename, ID3D12Device* in_pDevice, UINT in_sampleCount, D3D12_CPU_DESCRIPTOR_HANDLE in_srvBaseCPU, - const CommandLineArgs& in_args) : + const CommandLineArgs& in_args, + AssetUploader& in_assetUploader) : BaseObject(in_filename, in_pTileUpdateManager, in_pStreamingHeap, in_pDevice, in_srvBaseCPU, nullptr) { @@ -581,14 +558,15 @@ SceneObjects::Terrain::Terrain(const std::wstring& in_filename, nullptr, IID_PPV_ARGS(&pVertexBuffer))); - InitializeBuffer(pVertexBuffer, vertices.data(), vertexBufferSize, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); + AssetUploader::Request* pRequest = new AssetUploader::Request(pVertexBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); + // mesh generator contains an array. would have been nice to swap, but it doesn't work that way + memcpy(pRequest->GetBuffer().data(), mesh.GetVertices().data(), vertexBufferSize); + in_assetUploader.SubmitRequest(pRequest); } // build index buffer { - std::vector indices(numIndices); - mesh.GenerateIndices(&(indices[0])); - UINT indexBufferSize = numIndices * sizeof(indices[0]); + UINT indexBufferSize = numIndices * sizeof(UINT); const auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); const auto resourceDesc = CD3DX12_RESOURCE_DESC::Buffer(indexBufferSize); @@ -600,7 +578,9 @@ SceneObjects::Terrain::Terrain(const std::wstring& in_filename, nullptr, IID_PPV_ARGS(&pIndexBuffer))); - InitializeBuffer(pIndexBuffer, indices.data(), indexBufferSize, D3D12_RESOURCE_STATE_INDEX_BUFFER); + AssetUploader::Request* pRequest = new AssetUploader::Request(pIndexBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_INDEX_BUFFER); + mesh.GenerateIndices((UINT*)pRequest->GetBuffer().data()); + in_assetUploader.SubmitRequest(pRequest); } SetGeometry(pVertexBuffer, (UINT)mesh.GetVertices().size(), (UINT)sizeof(TerrainGenerator::Vertex), @@ -614,7 +594,7 @@ SceneObjects::Terrain::Terrain(const std::wstring& in_filename, SceneObjects::Planet::Planet(const std::wstring& in_filename, TileUpdateManager* in_pTileUpdateManager, StreamingHeap* in_pStreamingHeap, - ID3D12Device* in_pDevice, + ID3D12Device* in_pDevice, AssetUploader& in_assetUploader, UINT in_sampleCount, D3D12_CPU_DESCRIPTOR_HANDLE in_srvBaseCPU, const SphereGen::Properties& in_sphereProperties) : @@ -626,7 +606,7 @@ SceneObjects::Planet::Planet(const std::wstring& in_filename, CreatePipelineState(L"terrainPS.cso", L"terrainPS-FB.cso", L"terrainVS.cso", in_pDevice, in_sampleCount, rasterizerDesc, depthStencilDesc); const UINT numLevelsOfDetail = SharedConstants::NUM_SPHERE_LEVELS_OF_DETAIL; - CreateSphere(this, in_pDevice, in_sphereProperties, numLevelsOfDetail); + CreateSphere(this, in_pDevice, in_assetUploader, in_sphereProperties, numLevelsOfDetail); float d = SharedConstants::SPHERE_SCALE * 200; GetModelMatrix() = DirectX::XMMatrixScaling(d, d, d); @@ -655,7 +635,7 @@ SceneObjects::Planet::Planet(const std::wstring& in_filename, SceneObjects::Sky::Sky(const std::wstring& in_filename, TileUpdateManager* in_pTileUpdateManager, StreamingHeap* in_pStreamingHeap, - ID3D12Device* in_pDevice, + ID3D12Device* in_pDevice, AssetUploader& in_assetUploader, UINT in_sampleCount, D3D12_CPU_DESCRIPTOR_HANDLE in_srvBaseCPU) : BaseObject(in_filename, in_pTileUpdateManager, in_pStreamingHeap, @@ -672,7 +652,7 @@ SceneObjects::Sky::Sky(const std::wstring& in_filename, sphereProperties.m_numLong = 80; sphereProperties.m_numLat = 81; sphereProperties.m_mirrorU = true; - CreateSphere(this, in_pDevice, sphereProperties); + CreateSphere(this, in_pDevice, in_assetUploader, sphereProperties); float d = SharedConstants::SPHERE_SCALE * 200; GetModelMatrix() = DirectX::XMMatrixScaling(d, d, d); } diff --git a/src/SceneObject.h b/src/SceneObject.h index 27c58df..c5dbc10 100644 --- a/src/SceneObject.h +++ b/src/SceneObject.h @@ -31,6 +31,8 @@ #include "SamplerFeedbackStreaming.h" #include "CreateSphere.h" +class AssetUploader; + namespace SceneObjects { enum class Descriptors @@ -171,38 +173,39 @@ namespace SceneObjects UINT m_srvUavCbvDescriptorSize; }; - void InitializeBuffer(ID3D12Resource* out_pBuffer, const void* in_pBytes, size_t in_numBytes, D3D12_RESOURCE_STATES in_finalState); - void InitializeTexture(ID3D12Resource* pTexture, size_t in_numSubResources, const D3D12_SUBRESOURCE_DATA* in_pSubresources, D3D12_RESOURCE_STATES in_finalState); - void CreateSphere(SceneObjects::BaseObject* out_pObject, - ID3D12Device* in_pDevice, const SphereGen::Properties& in_sphereProperties, UINT in_numLods = 1); + ID3D12Device* in_pDevice, AssetUploader& in_assetUploader, + const SphereGen::Properties& in_sphereProperties, UINT in_numLods = 1); + void CreateSphereResources(ID3D12Resource** out_ppVertexBuffer, ID3D12Resource** out_ppIndexBuffer, - ID3D12Device* in_pDevice, const SphereGen::Properties& in_sphereProperties); + ID3D12Device* in_pDevice, const SphereGen::Properties& in_sphereProperties, + AssetUploader& in_assetUploader); class Terrain : public BaseObject { public: - Terrain(const std::wstring& in_filename, // this class takes ownership and deletes in destructor + Terrain(const std::wstring& in_filename, TileUpdateManager* in_pTileUpdateManager, StreamingHeap* in_pStreamingHeap, ID3D12Device* in_pDevice, UINT in_sampleCount, D3D12_CPU_DESCRIPTOR_HANDLE in_srvBaseCPU, - const CommandLineArgs& in_args); + const CommandLineArgs& in_args, + AssetUploader& in_assetUploader); }; class Planet : public BaseObject { public: - Planet(const std::wstring& in_filename, // this class takes ownership and deletes in destructor + Planet(const std::wstring& in_filename, TileUpdateManager* in_pTileUpdateManager, StreamingHeap* in_pStreamingHeap, - ID3D12Device* in_pDevice, + ID3D12Device* in_pDevice, AssetUploader& in_assetUploader, UINT in_sampleCount, D3D12_CPU_DESCRIPTOR_HANDLE in_srvBaseCPU, const SphereGen::Properties& in_properties); - Planet(const std::wstring& in_filename, // this class takes ownership and deletes in destructor + Planet(const std::wstring& in_filename, TileUpdateManager* in_pTileUpdateManager, StreamingHeap* in_pStreamingHeap, ID3D12Device* in_pDevice, @@ -215,10 +218,10 @@ namespace SceneObjects class Sky : public BaseObject { public: - Sky(const std::wstring& in_filename, // this class takes ownership and deletes in destructor + Sky(const std::wstring& in_filename, TileUpdateManager* in_pTileUpdateManager, StreamingHeap* in_pStreamingHeap, - ID3D12Device* in_pDevice, + ID3D12Device* in_pDevice, AssetUploader& in_assetUploader, UINT in_sampleCount, D3D12_CPU_DESCRIPTOR_HANDLE in_srvBaseCPU); diff --git a/src/SharedConstants.h b/src/SharedConstants.h index 809f9cf..b2dfd21 100644 --- a/src/SharedConstants.h +++ b/src/SharedConstants.h @@ -30,21 +30,6 @@ class SharedConstants { public: -#ifdef _DEBUG - - // Enable better shader debugging with the graphics debugging tools. - static const UINT COMPILE_FLAGS = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; - -#define ENABLE_DEBUG_LAYER 1 -#define DebugPrint(...) OutputDebugString(Streaming::AutoString::Concat(__VA_ARGS__).c_str()); - -#else - static const UINT COMPILE_FLAGS = 0; - -#define ENABLE_DEBUG_LAYER 0 -#define DebugPrint(...) -#endif - // rendering properties static const DXGI_FORMAT SWAP_CHAIN_FORMAT = DXGI_FORMAT_R8G8B8A8_UNORM; static const DXGI_FORMAT DEPTH_FORMAT = DXGI_FORMAT_D32_FLOAT; diff --git a/src/TerrainGenerator.cpp b/src/TerrainGenerator.cpp index ea6406e..d3c330b 100644 --- a/src/TerrainGenerator.cpp +++ b/src/TerrainGenerator.cpp @@ -129,7 +129,7 @@ void TerrainGenerator::GenerateVertices() const float frac = 1.0f / static_cast(m_args.m_terrainSideSize - 1); - concurrency::parallel_for(UINT(0), m_args.m_terrainSideSize, [&](UINT y) + for (UINT y = 0; y < m_args.m_terrainSideSize; y++) { for (UINT x = 0; x < m_args.m_terrainSideSize; x++) { @@ -165,7 +165,7 @@ void TerrainGenerator::GenerateVertices() // FIXME? the terrain is shown upside down! vtx.tex.x = 1.f - vtx.tex.x; } - }); + } // // Compute normals @@ -179,7 +179,7 @@ void TerrainGenerator::GenerateVertices() m_args.m_terrainSideSize * m_args.m_terrainSideSize, XMVectorSet(0.f, 0.f, 0.f, 0.f)); - concurrency::parallel_for(UINT(0), m_args.m_terrainSideSize - 1, [&](UINT y) + for (UINT y = 0; y < m_args.m_terrainSideSize - 1; y++) { for (UINT x = 0; x < m_args.m_terrainSideSize - 1; x++) { @@ -205,7 +205,7 @@ void TerrainGenerator::GenerateVertices() normals[vtx2] += n; } } - }); + } for (size_t i = 0; i < normals.size(); i++) { diff --git a/src/TextureViewer.cpp b/src/TextureViewer.cpp index 66ed520..2333df4 100644 --- a/src/TextureViewer.cpp +++ b/src/TextureViewer.cpp @@ -27,7 +27,7 @@ #include "pch.h" #include "TextureViewer.h" -#include "DXSampleHelper.h" +#include "DebugHelper.h" using namespace DirectX; using Microsoft::WRL::ComPtr; @@ -51,14 +51,17 @@ struct ConstantBuffer }; //----------------------------------------------------------------------------- + + +// expect hlsl files to be next to the exe //----------------------------------------------------------------------------- inline std::wstring GetAssetFullPath(const std::wstring in_filename) { - constexpr size_t PATHBUFFERSIZE = MAX_PATH * 4; - TCHAR buffer[PATHBUFFERSIZE]; - GetCurrentDirectory(_countof(buffer), buffer); - std::wstring directory = buffer; - return directory + L"\\\\" + in_filename; + WCHAR buffer[MAX_PATH]; + GetModuleFileName(nullptr, buffer, MAX_PATH); + std::wstring exePath(buffer); + exePath.resize(exePath.rfind('\\') + 1); + return (exePath + in_filename); } //----------------------------------------------------------------------------- diff --git a/src/pch.h b/src/pch.h index 116083d..fac00df 100644 --- a/src/pch.h +++ b/src/pch.h @@ -39,35 +39,20 @@ #include #include -#include // Be sure to link with dxcompiler.lib. -#include // Shader reflection. - #include #include #include #include #include -#include #include #include -#include #include #include #include #include #include -#ifdef _DEBUG -#include -#define ASSERT(X) assert(X) -#else -#define ASSERT(X) -#endif - // DirectXTK12 -#include -#include -#include #include "d3dx12.h" // Imgui diff --git a/src/BufferViewer.hlsl b/src/shaders/BufferViewer.hlsl similarity index 100% rename from src/BufferViewer.hlsl rename to src/shaders/BufferViewer.hlsl diff --git a/src/TextureViewer.hlsl b/src/shaders/TextureViewer.hlsl similarity index 100% rename from src/TextureViewer.hlsl rename to src/shaders/TextureViewer.hlsl diff --git a/src/winMain.cpp b/src/winMain.cpp index b018c2b..8902466 100644 --- a/src/winMain.cpp +++ b/src/winMain.cpp @@ -114,6 +114,16 @@ void AdjustArguments(CommandLineArgs& out_args) out_args.m_mediaDir += L'\\'; } + // if the desired media path doesn't exist, try looking relative to the current directory + if (!std::filesystem::exists(out_args.m_mediaDir)) + { + WCHAR buffer[MAX_PATH]; + GetModuleFileName(nullptr, buffer, MAX_PATH); + std::wstring exePath(buffer); + exePath.resize(exePath.rfind('\\') + 1); + out_args.m_mediaDir = exePath + out_args.m_mediaDir; + } + if (std::filesystem::exists(out_args.m_mediaDir)) { for (const auto& filename : std::filesystem::directory_iterator(out_args.m_mediaDir))