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