diff --git a/TileUpdateManager/DataUploader.cpp b/TileUpdateManager/DataUploader.cpp index cb27ef9..66cee2e 100644 --- a/TileUpdateManager/DataUploader.cpp +++ b/TileUpdateManager/DataUploader.cpp @@ -239,12 +239,15 @@ void Streaming::DataUploader::StopThreads() //----------------------------------------------------------------------------- void Streaming::DataUploader::FlushCommands() { - DebugPrint("DataUploader waiting on ", m_updateListAllocator.GetAllocated(), " tasks to complete\n"); - while (m_updateListAllocator.GetAllocated()) // wait so long as there is outstanding work + if (m_updateListAllocator.GetAllocated()) { - m_submitFlag.Set(); // (paranoia) - m_fenceMonitorFlag.Set(); // (paranoia) - _mm_pause(); + DebugPrint("DataUploader waiting on ", m_updateListAllocator.GetAllocated(), " tasks to complete\n"); + while (m_updateListAllocator.GetAllocated()) // wait so long as there is outstanding work + { + m_submitFlag.Set(); // (paranoia) + m_fenceMonitorFlag.Set(); // (paranoia) + _mm_pause(); + } } // if this loop doesn't exit, then a race condition occurred while allocating/freeing updatelists @@ -276,7 +279,7 @@ Streaming::UpdateList* Streaming::DataUploader::AllocateUpdateList(Streaming::St // start fence polling thread now { - m_monitorTasks[m_monitorTaskAlloc.GetWriteIndex()] = index; + m_monitorTasks[m_monitorTaskAlloc.GetWriteIndex()] = pUpdateList; m_monitorTaskAlloc.Allocate(); m_fenceMonitorFlag.Set(); } @@ -316,7 +319,7 @@ void Streaming::DataUploader::SubmitUpdateList(Streaming::UpdateList& in_updateL // add to submit task queue { - m_submitTasks[m_submitTaskAlloc.GetWriteIndex()] = UINT(&in_updateList - m_updateLists.data()); + m_submitTasks[m_submitTaskAlloc.GetWriteIndex()] = &in_updateList; m_submitTaskAlloc.Allocate(); m_submitFlag.Set(); } @@ -345,7 +348,7 @@ void Streaming::DataUploader::FenceMonitorThread() for (UINT i = startIndex; i < (startIndex + numTasks); i++) { ASSERT(numTasks != 0); - auto& updateList = m_updateLists[m_monitorTasks[i % m_monitorTasks.size()]]; + auto& updateList = *m_monitorTasks[i % m_monitorTasks.size()]; bool freeUpdateList = false; @@ -461,11 +464,9 @@ void Streaming::DataUploader::SubmitThread() { signalMap = true; - UINT index = m_submitTasks[m_submitTaskAlloc.GetReadIndex()]; // get the next task + auto& updateList = *m_submitTasks[m_submitTaskAlloc.GetReadIndex()]; // get the next task m_submitTaskAlloc.Free(); // consume this task - auto& updateList = m_updateLists[index]; - ASSERT(UpdateList::State::STATE_SUBMITTED == updateList.m_executionState); // set to the fence value to be signaled next diff --git a/TileUpdateManager/DataUploader.h b/TileUpdateManager/DataUploader.h index 03ca414..f2ac232 100644 --- a/TileUpdateManager/DataUploader.h +++ b/TileUpdateManager/DataUploader.h @@ -109,7 +109,6 @@ namespace Streaming ComPtr m_mappingCommandQueue; // pool of all updatelists - // copy thread loops over these std::vector m_updateLists; Streaming::AllocatorMT m_updateListAllocator; @@ -125,8 +124,8 @@ namespace Streaming // thread to handle UpdateList submissions void SubmitThread(); std::thread m_submitThread; - Streaming::SynchronizationFlag m_submitFlag; - std::vector m_submitTasks; + Streaming::SynchronizationFlag m_submitFlag; // sleeps until flag set + std::vector m_submitTasks; RingBuffer m_submitTaskAlloc; // thread to poll copy and mapping fences @@ -134,9 +133,9 @@ namespace Streaming // compromise solution is to keep this thread awake so long as there are live UpdateLists. void FenceMonitorThread(); std::thread m_fenceMonitorThread; - Streaming::SynchronizationFlag m_fenceMonitorFlag; + Streaming::SynchronizationFlag m_fenceMonitorFlag; // sleeps until flag set RawCpuTimer* m_pFenceThreadTimer{ nullptr }; // init timer on the thread that uses it. can't really worry about thread migration. - std::vector m_monitorTasks; + std::vector m_monitorTasks; RingBuffer m_monitorTaskAlloc; void StartThreads(); diff --git a/TileUpdateManager/FileStreamerDS.cpp b/TileUpdateManager/FileStreamerDS.cpp index b42a1e1..2bd4070 100644 --- a/TileUpdateManager/FileStreamerDS.cpp +++ b/TileUpdateManager/FileStreamerDS.cpp @@ -99,7 +99,9 @@ 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], request.Source.File.Size); + auto fileOffset = pTextureFileInfo->GetFileOffset(in_updateList.m_coords[i]); + request.Source.File.Offset = fileOffset.offset; + request.Source.File.Size = fileOffset.numBytes; D3D12_TILED_RESOURCE_COORDINATE coord{}; ID3D12Resource* pAtlas = pDstHeap->ComputeCoordFromTileIndex(coord, in_updateList.m_heapIndices[i], textureFormat); diff --git a/TileUpdateManager/FileStreamerReference.cpp b/TileUpdateManager/FileStreamerReference.cpp index ce76067..afb2b23 100644 --- a/TileUpdateManager/FileStreamerReference.cpp +++ b/TileUpdateManager/FileStreamerReference.cpp @@ -189,8 +189,7 @@ void Streaming::FileStreamerReference::LoadTexture(Streaming::FileStreamerRefere for (UINT i = startIndex; i < endIndex; i++) { // get file offset to tile - UINT32 numBytes = 0; - UINT fileOffset = pTextureFileInfo->GetFileOffset(pUpdateList->m_coords[i], numBytes); + auto 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]; @@ -204,11 +203,11 @@ void Streaming::FileStreamerReference::LoadTexture(Streaming::FileStreamerRefere o.Internal = 0; o.InternalHigh = 0; o.OffsetHigh = 0; - o.Offset = fileOffset; + o.Offset = fileOffset.offset; // align # bytes read UINT alignment = FileStreamerReference::MEDIA_SECTOR_SIZE - 1; - numBytes = (numBytes + alignment) & ~(alignment); + UINT numBytes = (fileOffset.numBytes + alignment) & ~(alignment); o.Offset &= ~alignment; // rewind the offset to alignment ::ReadFile(pFileHandle, pDst, numBytes, nullptr, &o); diff --git a/TileUpdateManager/InternalResources.cpp b/TileUpdateManager/InternalResources.cpp index dc09847..39a9ed1 100644 --- a/TileUpdateManager/InternalResources.cpp +++ b/TileUpdateManager/InternalResources.cpp @@ -33,7 +33,7 @@ //----------------------------------------------------------------------------- Streaming::InternalResources::InternalResources( ID3D12Device8* in_pDevice, - XeTexture* m_pTextureFileInfo, + const XeTexture& m_textureFileInfo, // need the swap chain count so we can create per-frame upload buffers UINT in_swapChainBufferCount) : m_packedMipInfo{}, m_tileShape{}, m_numTilesTotal(0) @@ -41,10 +41,10 @@ Streaming::InternalResources::InternalResources( // create reserved resource { D3D12_RESOURCE_DESC rd = CD3DX12_RESOURCE_DESC::Tex2D( - m_pTextureFileInfo->GetFormat(), - m_pTextureFileInfo->GetImageWidth(), - m_pTextureFileInfo->GetImageHeight(), 1, - (UINT16)m_pTextureFileInfo->GetMipCount() + m_textureFileInfo.GetFormat(), + m_textureFileInfo.GetImageWidth(), + m_textureFileInfo.GetImageHeight(), 1, + (UINT16)m_textureFileInfo.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 2389315..b17ae95 100644 --- a/TileUpdateManager/InternalResources.h +++ b/TileUpdateManager/InternalResources.h @@ -37,7 +37,7 @@ namespace Streaming class InternalResources { public: - InternalResources(ID3D12Device8* in_pDevice, class XeTexture* m_pTextureFileInfo, + InternalResources(ID3D12Device8* in_pDevice, const class XeTexture& m_textureFileInfo, // need the swap chain count so we can create per-frame upload buffers UINT in_swapChainBufferCount); diff --git a/TileUpdateManager/StreamingResourceBase.cpp b/TileUpdateManager/StreamingResourceBase.cpp index 8e33f53..d1171a8 100644 --- a/TileUpdateManager/StreamingResourceBase.cpp +++ b/TileUpdateManager/StreamingResourceBase.cpp @@ -28,7 +28,6 @@ #include "StreamingResourceBase.h" #include "TileUpdateManagerSR.h" -#include "XeTexture.h" #include "UpdateList.h" @@ -61,9 +60,9 @@ Streaming::StreamingResourceBase::StreamingResourceBase( , m_pHeap(in_pHeap) , m_pFileHandle(in_pFileHandle) , m_filename(in_filename) + , m_textureFileInfo(in_filename) { - m_pTextureFileInfo = std::make_unique(in_filename); - m_resources = std::make_unique(in_pTileUpdateManager->GetDevice(), m_pTextureFileInfo.get(), (UINT)m_queuedFeedback.size()); + m_resources = std::make_unique(in_pTileUpdateManager->GetDevice(), m_textureFileInfo, (UINT)m_queuedFeedback.size()); m_tileMappingState.Init(m_resources->GetPackedMipInfo().NumStandardMips, m_resources->GetTiling()); // no packed mips. odd, but possible. no need to check/update this variable again. @@ -85,7 +84,7 @@ 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_pTextureFileInfo->GetFormat()); + m_pHeap->AllocateAtlas(in_pTileUpdateManager->GetMappingQueue(), m_textureFileInfo.GetFormat()); // Load packed mips. packed mips are not streamed or evicted. LoadPackedMips(); @@ -837,7 +836,7 @@ void Streaming::StreamingResourceBase::EvictionDelay::Rescue(const Streaming::St void Streaming::StreamingResourceBase::LoadPackedMips() { UINT numBytes = 0; - UINT offset = m_pTextureFileInfo->GetPackedMipFileOffset(&numBytes, &m_packedMipsUncompressedSize); + UINT offset = m_textureFileInfo.GetPackedMipFileOffset(&numBytes, &m_packedMipsUncompressedSize); m_packedMips.resize(numBytes); std::ifstream inFile(m_filename.c_str(), std::ios::binary); inFile.seekg(offset); diff --git a/TileUpdateManager/StreamingResourceBase.h b/TileUpdateManager/StreamingResourceBase.h index d95ff01..35d8b1a 100644 --- a/TileUpdateManager/StreamingResourceBase.h +++ b/TileUpdateManager/StreamingResourceBase.h @@ -37,12 +37,12 @@ Base class for StreamingResource #include "SamplerFeedbackStreaming.h" #include "InternalResources.h" +#include "XeTexture.h" namespace Streaming { class TileUpdateManagerSR; struct UpdateList; - class XeTexture; class Heap; class FileHandle; @@ -161,7 +161,7 @@ namespace Streaming const std::wstring m_filename; // object that streams data from a file - std::unique_ptr m_pTextureFileInfo; + const Streaming::XeTexture m_textureFileInfo; std::unique_ptr m_resources; std::unique_ptr m_pFileHandle; Streaming::Heap* m_pHeap{ nullptr }; diff --git a/TileUpdateManager/StreamingResourceDU.h b/TileUpdateManager/StreamingResourceDU.h index 53b4a94..bb863f1 100644 --- a/TileUpdateManager/StreamingResourceDU.h +++ b/TileUpdateManager/StreamingResourceDU.h @@ -37,7 +37,7 @@ namespace Streaming class StreamingResourceDU : private StreamingResourceBase { public: - XeTexture* GetTextureFileInfo() const { return m_pTextureFileInfo.get(); } + const XeTexture* GetTextureFileInfo() const { return &m_textureFileInfo; } Streaming::Heap* GetHeap() const { return m_pHeap; } // just for packed mips diff --git a/TileUpdateManager/TileUpdateManager.cpp b/TileUpdateManager/TileUpdateManager.cpp index 7f21677..20689dd 100644 --- a/TileUpdateManager/TileUpdateManager.cpp +++ b/TileUpdateManager/TileUpdateManager.cpp @@ -57,7 +57,7 @@ void Streaming::TileUpdateManagerBase::Destroy() //-------------------------------------------- StreamingHeap* Streaming::TileUpdateManagerBase::CreateStreamingHeap(UINT in_maxNumTilesHeap) { - auto pStreamingHeap = new Streaming::Heap(m_pDataUploader->GetMappingQueue(), in_maxNumTilesHeap); + auto pStreamingHeap = new Streaming::Heap(m_dataUploader.GetMappingQueue(), in_maxNumTilesHeap); return (StreamingHeap*)pStreamingHeap; } @@ -69,7 +69,7 @@ StreamingResource* Streaming::TileUpdateManagerBase::CreateStreamingResource(con // if threads are running, stop them. they have state that depends on knowing the # of StreamingResources Finish(); - Streaming::FileHandle* pFileHandle = m_pDataUploader->OpenFile(in_filename); + Streaming::FileHandle* pFileHandle = m_dataUploader.OpenFile(in_filename); auto pRsrc = new Streaming::StreamingResourceBase(in_filename, pFileHandle, (Streaming::TileUpdateManagerSR*)this, (Streaming::Heap*)in_pHeap); m_streamingResources.push_back(pRsrc); m_numStreamingResourcesChanged = true; @@ -92,11 +92,11 @@ void Streaming::TileUpdateManagerBase::UseDirectStorage(bool in_useDS) streamerType = Streaming::DataUploader::StreamerType::DirectStorage; } - auto pOldStreamer = m_pDataUploader->SetStreamer(streamerType); + auto pOldStreamer = m_dataUploader.SetStreamer(streamerType); for (auto& s : m_streamingResources) { - s->SetFileHandle(m_pDataUploader.get()); + s->SetFileHandle(&m_dataUploader); } delete pOldStreamer; @@ -142,13 +142,13 @@ float Streaming::TileUpdateManagerBase::GetCpuProcessFeedbackTime() //----------------------------------------------------------------------------- // performance and visualization //----------------------------------------------------------------------------- -float Streaming::TileUpdateManagerBase::GetGpuStreamingTime() const { return m_pDataUploader->GetGpuStreamingTime(); } -float Streaming::TileUpdateManagerBase::GetTotalTileCopyLatency() const { return m_pDataUploader->GetApproximateTileCopyLatency(); } +float Streaming::TileUpdateManagerBase::GetGpuStreamingTime() const { return m_dataUploader.GetGpuStreamingTime(); } +float Streaming::TileUpdateManagerBase::GetTotalTileCopyLatency() const { return m_dataUploader.GetApproximateTileCopyLatency(); } // the total time the GPU spent resolving feedback during the previous frame float Streaming::TileUpdateManagerBase::GetGpuTime() const { return m_gpuTimerResolve.GetTimes()[m_renderFrameIndex].first; } -UINT Streaming::TileUpdateManagerBase::GetTotalNumUploads() const { return m_pDataUploader->GetTotalNumUploads(); } -UINT Streaming::TileUpdateManagerBase::GetTotalNumEvictions() const { return m_pDataUploader->GetTotalNumEvictions(); } +UINT Streaming::TileUpdateManagerBase::GetTotalNumUploads() const { return m_dataUploader.GetTotalNumUploads(); } +UINT Streaming::TileUpdateManagerBase::GetTotalNumEvictions() const { return m_dataUploader.GetTotalNumEvictions(); } UINT Streaming::TileUpdateManagerBase::GetTotalNumSubmits() const { return m_numTotalSubmits; } void Streaming::TileUpdateManagerBase::SetVisualizationMode(UINT in_mode) @@ -160,12 +160,12 @@ void Streaming::TileUpdateManagerBase::SetVisualizationMode(UINT in_mode) o->ClearAllocations(); } - m_pDataUploader->SetVisualizationMode(in_mode); + m_dataUploader.SetVisualizationMode(in_mode); } void Streaming::TileUpdateManagerBase::CaptureTraceFile(bool in_captureTrace) { - m_pDataUploader->CaptureTraceFile(in_captureTrace); + m_dataUploader.CaptureTraceFile(in_captureTrace); } //----------------------------------------------------------------------------- diff --git a/TileUpdateManager/TileUpdateManagerBase.cpp b/TileUpdateManager/TileUpdateManagerBase.cpp index 808f464..ccc2fed 100644 --- a/TileUpdateManager/TileUpdateManagerBase.cpp +++ b/TileUpdateManager/TileUpdateManagerBase.cpp @@ -27,7 +27,6 @@ #include "pch.h" #include "TileUpdateManagerBase.h" -#include "DataUploader.h" #include "StreamingResourceBase.h" #include "XeTexture.h" #include "StreamingHeap.h" @@ -47,19 +46,13 @@ m_numSwapBuffers(in_desc.m_swapChainBufferCount) , m_addAliasingBarriers(in_desc.m_addAliasingBarriers) , m_minNumUploadRequests(in_desc.m_minNumUploadRequests) , m_threadPriority((int)in_desc.m_threadPriority) +, m_dataUploader(in_pDevice, in_desc.m_maxNumCopyBatches, in_desc.m_stagingBufferSizeMB, in_desc.m_maxTileMappingUpdatesPerApiCall, m_threadPriority) { ASSERT(D3D12_COMMAND_LIST_TYPE_DIRECT == m_directCommandQueue->GetDesc().Type); ThrowIfFailed(in_pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_frameFence))); m_frameFence->SetName(L"Streaming::TileUpdateManagerBase::m_frameFence"); - m_pDataUploader = std::make_unique( - in_pDevice, - in_desc.m_maxNumCopyBatches, - in_desc.m_stagingBufferSizeMB, - in_desc.m_maxTileMappingUpdatesPerApiCall, - m_threadPriority); - const UINT numAllocators = m_numSwapBuffers; for (UINT c = 0; c < (UINT)CommandListName::Num; c++) { @@ -137,7 +130,7 @@ void Streaming::TileUpdateManagerBase::StartThreads() //----------------------------------------------------------------------------- void Streaming::TileUpdateManagerBase::SignalFileStreamer() { - m_pDataUploader->SignalFileStreamer(); + m_dataUploader.SignalFileStreamer(); m_numTotalSubmits.fetch_add(1, std::memory_order_relaxed); } void Streaming::TileUpdateManagerBase::ProcessFeedbackThread() @@ -206,7 +199,14 @@ void Streaming::TileUpdateManagerBase::ProcessFeedbackThread() UINT newStaleSize = 0; // track number of stale resources, then resize the array to the updated number for (auto resourceIndex : staleResources) { - if (m_pDataUploader->GetNumUpdateListsAvailable() && m_threadsRunning) + if (m_dataUploader.GetNumUpdateListsAvailable() + // with DirectStorage Queue::EnqueueRequest() can block. + // when there are many pending uploads, there can be multiple frames of waiting. + // if we wait too long in this loop, we miss calling ProcessFeedback() above which adds pending uploads & evictions + // this is a vicious feedback cycle that leads to even more pending requests, and even longer delays. + // the following check avoids enqueueing more uploads if the frame has changed: + && (m_frameFence->GetCompletedValue() == previousFrameFenceValue) + && m_threadsRunning) // don't add work while exiting { uploadsRequested += m_streamingResources[resourceIndex]->QueueTiles(); } @@ -227,7 +227,7 @@ void Streaming::TileUpdateManagerBase::ProcessFeedbackThread() } } staleResources.resize(newStaleSize); // compact array - if (numEvictions) { m_pDataUploader->AddEvictions(numEvictions); } + if (numEvictions) { m_dataUploader.AddEvictions(numEvictions); } } // if there are uploads, maybe signal depending on heuristic to minimize # signals @@ -238,7 +238,7 @@ void Streaming::TileUpdateManagerBase::ProcessFeedbackThread() (0 == staleResources.size()) || // flush because there's no more work to be done (no stale resources, all feedback has been processed) // if we need updatelists and there is a minimum amount of pending work, go ahead and submit // this minimum heuristic prevents "storms" of submits with too few tiles to sustain good throughput - ((0 == m_pDataUploader->GetNumUpdateListsAvailable()) && (uploadsRequested > m_minNumUploadRequests))) + ((0 == m_dataUploader.GetNumUpdateListsAvailable()) && (uploadsRequested > m_minNumUploadRequests))) { SignalFileStreamer(); uploadsRequested = 0; @@ -286,10 +286,9 @@ void Streaming::TileUpdateManagerBase::Finish() { m_updateResidencyThread.join(); } - - // now we are no longer producing work for the DataUploader, so its commands can be drained - m_pDataUploader->FlushCommands(); } + // now we are no longer producing work for the DataUploader, so its commands can be drained + m_dataUploader.FlushCommands(); } //----------------------------------------------------------------------------- diff --git a/TileUpdateManager/TileUpdateManagerBase.h b/TileUpdateManager/TileUpdateManagerBase.h index c979760..245f3d8 100644 --- a/TileUpdateManager/TileUpdateManagerBase.h +++ b/TileUpdateManager/TileUpdateManagerBase.h @@ -52,6 +52,7 @@ Draw loop: #include "D3D12GpuTimer.h" #include "Timer.h" #include "Streaming.h" // for ComPtr +#include "DataUploader.h" #define COPY_RESIDENCY_MAPS 0 @@ -115,7 +116,7 @@ namespace Streaming std::vector m_streamingResources; UINT64 m_frameFenceValue{ 0 }; - std::unique_ptr m_pDataUploader; + Streaming::DataUploader m_dataUploader; // each StreamingResource writes current uploaded tile state to min mip map, separate data for each frame // internally, use a single buffer containing all the residency maps @@ -211,7 +212,7 @@ namespace Streaming // the min mip map is shared. it must be created (at least) every time a StreamingResource is created/destroyed void CreateMinMipMapView(D3D12_CPU_DESCRIPTOR_HANDLE in_descriptor); - std::vector m_residencyMapOffsets; // one for each StreamingResource sized for numswapbuffers min mip maps each + std::vector m_residencyMapOffsets; // one min mip map for each StreamingResource //------------------------------------------- // statistics diff --git a/TileUpdateManager/TileUpdateManagerSR.h b/TileUpdateManager/TileUpdateManagerSR.h index c27faba..b7ebc3f 100644 --- a/TileUpdateManager/TileUpdateManagerSR.h +++ b/TileUpdateManager/TileUpdateManagerSR.h @@ -78,12 +78,12 @@ namespace Streaming Streaming::UpdateList* AllocateUpdateList(StreamingResourceBase* in_pStreamingResource) { - return m_pDataUploader->AllocateUpdateList((Streaming::StreamingResourceDU*)in_pStreamingResource); + return m_dataUploader.AllocateUpdateList((Streaming::StreamingResourceDU*)in_pStreamingResource); } void SubmitUpdateList(Streaming::UpdateList& in_updateList) { - m_pDataUploader->SubmitUpdateList(in_updateList); + m_dataUploader.SubmitUpdateList(in_updateList); } // a fence on the render (direct) queue used to determine when feedback has been written & resolved @@ -93,7 +93,7 @@ namespace Streaming ID3D12CommandQueue* GetMappingQueue() const { - return m_pDataUploader->GetMappingQueue(); + return m_dataUploader.GetMappingQueue(); } void SetResidencyChanged() { m_residencyChangedFlag.Set(); } diff --git a/TileUpdateManager/XeTexture.cpp b/TileUpdateManager/XeTexture.cpp index fbc5eff..bcc5b2b 100644 --- a/TileUpdateManager/XeTexture.cpp +++ b/TileUpdateManager/XeTexture.cpp @@ -64,7 +64,7 @@ Streaming::XeTexture::XeTexture(const std::wstring& in_fileName) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -UINT Streaming::XeTexture::GetPackedMipFileOffset(UINT* out_pNumBytesTotal, UINT* out_pNumBytesUncompressed) +UINT Streaming::XeTexture::GetPackedMipFileOffset(UINT* out_pNumBytesTotal, UINT* out_pNumBytesUncompressed) const { UINT packedOffset = m_tileOffsets[m_fileHeader.m_mipInfo.m_numTilesForStandardMips].m_offset; *out_pNumBytesTotal = m_tileOffsets[m_fileHeader.m_mipInfo.m_numTilesForStandardMips].m_numBytes; @@ -84,11 +84,12 @@ UINT Streaming::XeTexture::GetLinearIndex(const D3D12_TILED_RESOURCE_COORDINATE& //----------------------------------------------------------------------------- // return value is byte offset into file //----------------------------------------------------------------------------- -UINT Streaming::XeTexture::GetFileOffset(const D3D12_TILED_RESOURCE_COORDINATE& in_coord, UINT32& out_numBytes) const +Streaming::XeTexture::FileOffset Streaming::XeTexture::GetFileOffset(const D3D12_TILED_RESOURCE_COORDINATE& in_coord) const { - UINT index = GetLinearIndex(in_coord); - // use index to look up file offset and number of bytes - out_numBytes = m_tileOffsets[index].m_numBytes; - return m_tileOffsets[index].m_offset; + UINT index = GetLinearIndex(in_coord); + FileOffset fileOffset; + fileOffset.numBytes = m_tileOffsets[index].m_numBytes; + fileOffset.offset = m_tileOffsets[index].m_offset; + return fileOffset; } diff --git a/TileUpdateManager/XeTexture.h b/TileUpdateManager/XeTexture.h index f818a73..0c0261a 100644 --- a/TileUpdateManager/XeTexture.h +++ b/TileUpdateManager/XeTexture.h @@ -49,9 +49,10 @@ namespace Streaming UINT32 GetCompressionFormat() const { return m_fileHeader.m_compressionFormat; } // return value is # bytes. out_offset is byte offset into file - UINT GetFileOffset(const D3D12_TILED_RESOURCE_COORDINATE& in_coord, UINT32& out_numBytes) const; + struct FileOffset { UINT offset{ 0 }; UINT numBytes{ 0 }; }; + FileOffset GetFileOffset(const D3D12_TILED_RESOURCE_COORDINATE& in_coord) const; - UINT GetPackedMipFileOffset(UINT* out_pNumBytesTotal, UINT* out_pNumBytesUncompressed); + UINT GetPackedMipFileOffset(UINT* out_pNumBytesTotal, UINT* out_pNumBytesUncompressed) const; XeTexture(const std::wstring& in_filename); protected: diff --git a/config/config.json b/config/config.json index 2257021..0df01de 100644 --- a/config/config.json +++ b/config/config.json @@ -11,12 +11,12 @@ "stagingSizeMB": 128, // size of the staging buffer for DirectStorage or reference streaming code // maximum number of in-flight batches of uploads - "numStreamingBatches": 128, - "minNumUploadRequests": 1999, // # tiles. heuristic to reduce frequency of Submit() calls + "numStreamingBatches": 1280, + "minNumUploadRequests": 2000, // # tiles. heuristic to reduce frequency of Submit() calls "addAliasingBarriers": false, //// adds a barrier for each streaming resource: alias(nullptr, pResource) - "adapter": "", // in a multi-adapter system, searches description for substring ignoring case e.g. "intel" + "adapter": "", // create device on adapter with description containig substring ignoring case e.g. "intel" "animationrate": 0, // rotation of individual objects "cameraRate": 0, // camera motion rate diff --git a/src/Gui.cpp b/src/Gui.cpp index 8b3eb46..b87e4a6 100644 --- a/src/Gui.cpp +++ b/src/Gui.cpp @@ -357,7 +357,7 @@ void Gui::Draw(ID3D12GraphicsCommandList* in_pCommandList, //--------------------------------------------------------------------- // number of objects. affects heap occupancy //--------------------------------------------------------------------- - ImGui::SliderInt("Num Objects", &in_args.m_numSpheres, 0, (int)in_args.m_maxNumObjects); + ImGui::SliderInt("Num Objects", &in_args.m_numSpheres, 1, (int)in_args.m_maxNumObjects); //--------------------------------------------------------------------- // terrain feedback viewer diff --git a/src/Scene.cpp b/src/Scene.cpp index f8afa33..9e6a5c3 100644 --- a/src/Scene.cpp +++ b/src/Scene.cpp @@ -780,15 +780,11 @@ XMMATRIX Scene::SetSphereMatrix() //----------------------------------------------------------------------------- void Scene::LoadSpheres() { - if (m_numSpheresLoaded < (UINT)m_args.m_numSpheres) + if (m_objects.size() < (UINT)m_args.m_numSpheres) { - // sphere descriptors start after the terrain descriptor - CD3DX12_CPU_DESCRIPTOR_HANDLE descCPU = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_srvHeap->GetCPUDescriptorHandleForHeapStart(), (UINT)DescriptorHeapOffsets::NumEntries, m_srvUavCbvDescriptorSize); - - // offset by all the spheres that have been loaded so far - descCPU.Offset(m_numSpheresLoaded * (UINT)SceneObjects::Descriptors::NumEntries, m_srvUavCbvDescriptorSize); - - const UINT numSpheresToLoad = m_args.m_numSpheres - m_numSpheresLoaded; + // offset by all the objects that have been loaded so far + UINT descriptorOffset = (UINT)DescriptorHeapOffsets::NumEntries + UINT(m_objects.size()) * (UINT)SceneObjects::Descriptors::NumEntries; + CD3DX12_CPU_DESCRIPTOR_HANDLE descCPU = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_srvHeap->GetCPUDescriptorHandleForHeapStart(), descriptorOffset, m_srvUavCbvDescriptorSize); // is there a sky? std::wstring skyTexture; @@ -805,7 +801,7 @@ void Scene::LoadSpheres() } UINT textureIndex = 0; - for (UINT i = 0; i < numSpheresToLoad; i++) + while (m_objects.size() < (UINT)m_args.m_numSpheres) { // this object's index-to-be UINT objectIndex = (UINT)m_objects.size(); @@ -866,7 +862,6 @@ void Scene::LoadSpheres() // if there are textures other than the terrain texture, skip this one else if ((std::wstring::npos != textureFilename.find(m_args.m_terrainTexture)) && (m_args.m_textures.size() > 1)) { - i--; continue; } @@ -886,25 +881,18 @@ void Scene::LoadSpheres() o->GetModelMatrix() = SetSphereMatrix(); } m_objects.push_back(o); - m_numSpheresLoaded++; // offset to the next sphere descCPU.Offset((UINT)SceneObjects::Descriptors::NumEntries, m_srvUavCbvDescriptorSize); } } // evict spheres? - else if (m_numSpheresLoaded > (UINT)m_args.m_numSpheres) + else if (m_objects.size() > (UINT)m_args.m_numSpheres) { WaitForGpu(); - while (m_numSpheresLoaded > (UINT)m_args.m_numSpheres) + while (m_objects.size() > (UINT)m_args.m_numSpheres) { - auto i = m_objects.end(); - i--; - - SceneObjects::BaseObject* pObject = *i; - - delete pObject; - m_objects.erase(i); + SceneObjects::BaseObject* pObject = m_objects.back(); if (m_pTerrainSceneObject == pObject) { @@ -927,7 +915,8 @@ void Scene::LoadSpheres() m_pSky = nullptr; } - m_numSpheresLoaded--; + delete pObject; + m_objects.resize(m_objects.size() - 1); } } } diff --git a/src/Scene.h b/src/Scene.h index f5f8ee9..ba5c46a 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -212,7 +212,6 @@ class Scene AssetUploader m_assetUploader; std::vector m_objects; - UINT m_numSpheresLoaded{ 0 }; UINT m_terrainObjectIndex{ 0 }; SceneObjects::BaseObject* m_pTerrainSceneObject{ nullptr }; // convenience pointer, do not delete or draw, this is also in m_objects.