diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp index f195befda..cf6352467 100644 --- a/WickedEngine/wiEmittedParticle.cpp +++ b/WickedEngine/wiEmittedParticle.cpp @@ -313,12 +313,8 @@ namespace wi std::swap(aliveList[0], aliveList[1]); // Read back statistics (with GPU delay): - if (statisticsReadBackIndex > arraysize(statisticsReadbackBuffer)) - { - const uint32_t oldest_stat_index = (statisticsReadBackIndex + 1) % arraysize(statisticsReadbackBuffer); - memcpy(&statistics, statisticsReadbackBuffer[oldest_stat_index].mapped_data, sizeof(statistics)); - } - statisticsReadBackIndex++; + const uint32_t oldest_stat_index = wi::graphics::GetDevice()->GetBufferIndex(); + memcpy(&statistics, statisticsReadbackBuffer[oldest_stat_index].mapped_data, sizeof(statistics)); } void EmittedParticleSystem::Burst(int num) { @@ -679,7 +675,8 @@ namespace wi } // Statistics is copied to readback: - device->CopyResource(&statisticsReadbackBuffer[(statisticsReadBackIndex - 1) % arraysize(statisticsReadbackBuffer)], &counterBuffer, cmd); + const uint32_t oldest_stat_index = wi::graphics::GetDevice()->GetBufferIndex(); + device->CopyResource(&statisticsReadbackBuffer[oldest_stat_index], &counterBuffer, cmd); { const GPUBarrier barriers[] = { diff --git a/WickedEngine/wiEmittedParticle.h b/WickedEngine/wiEmittedParticle.h index 4519d695f..385a2d9b3 100644 --- a/WickedEngine/wiEmittedParticle.h +++ b/WickedEngine/wiEmittedParticle.h @@ -31,7 +31,7 @@ namespace wi }; ParticleCounters statistics = {}; - wi::graphics::GPUBuffer statisticsReadbackBuffer[wi::graphics::GraphicsDevice::GetBufferCount() + 1]; + wi::graphics::GPUBuffer statisticsReadbackBuffer[wi::graphics::GraphicsDevice::GetBufferCount()]; wi::graphics::GPUBuffer particleBuffer; wi::graphics::GPUBuffer aliveList[2]; @@ -129,7 +129,6 @@ namespace wi // Non-serialized attributes: XMFLOAT3 center; - uint32_t statisticsReadBackIndex = 0; uint32_t layerMask = ~0u; inline bool IsDebug() const { return _flags & FLAG_DEBUG; } diff --git a/WickedEngine/wiGraphicsDevice.h b/WickedEngine/wiGraphicsDevice.h index 146188bc2..00f998112 100644 --- a/WickedEngine/wiGraphicsDevice.h +++ b/WickedEngine/wiGraphicsDevice.h @@ -49,7 +49,7 @@ namespace wi::graphics class GraphicsDevice { protected: - static const uint32_t BUFFERCOUNT = 2; + static constexpr uint32_t BUFFERCOUNT = 2; uint64_t FRAMECOUNT = 0; ValidationMode validationMode = ValidationMode::Disabled; GraphicsDeviceCapability capabilities = GraphicsDeviceCapability::NONE; @@ -57,8 +57,8 @@ namespace wi::graphics size_t TOPLEVEL_ACCELERATION_STRUCTURE_INSTANCE_SIZE = 0; uint32_t VARIABLE_RATE_SHADING_TILE_SIZE = 0; uint64_t TIMESTAMP_FREQUENCY = 0; - uint32_t vendorId; - uint32_t deviceId; + uint32_t vendorId = 0; + uint32_t deviceId = 0; std::string adapterName; std::string driverDescription; AdapterType adapterType = AdapterType::Other; @@ -119,7 +119,7 @@ namespace wi::graphics // Returns the buffer count, which is the array size of buffered resources used by both the CPU and GPU static constexpr uint32_t GetBufferCount() { return BUFFERCOUNT; } // Returns the current buffer index, which is in range [0, GetBufferCount() - 1] - constexpr uint32_t GetBufferIndex() const { return GetFrameCount() % BUFFERCOUNT; } + constexpr uint32_t GetBufferIndex() const { return GetFrameCount() % GetBufferCount(); } // Returns whether the graphics debug layer is enabled. It can be enabled when creating the device. constexpr bool IsDebugDevice() const { return validationMode != ValidationMode::Disabled; } diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index 5a276d51c..ebf64b260 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -5072,24 +5072,22 @@ using namespace dx12_internal; // From here, we begin a new frame, this affects GetBufferIndex()! FRAMECOUNT++; - // Begin next frame: + // Initiate stalling CPU when GPU is not yet finished with next frame: + const uint32_t bufferindex = GetBufferIndex(); + for (int queue = 0; queue < QUEUE_COUNT; ++queue) { - // Initiate stalling CPU when GPU is not yet finished with next frame: - for (int queue = 0; queue < QUEUE_COUNT; ++queue) + if (FRAMECOUNT >= BUFFERCOUNT && frame_fence[bufferindex][queue]->GetCompletedValue() < 1) { - if (FRAMECOUNT >= BUFFERCOUNT && frame_fence[GetBufferIndex()][queue]->GetCompletedValue() < 1) - { - // NULL event handle will simply wait immediately: - // https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12fence-seteventoncompletion#remarks - hr = frame_fence[GetBufferIndex()][queue]->SetEventOnCompletion(1, NULL); - assert(SUCCEEDED(hr)); - } - hr = frame_fence[GetBufferIndex()][queue]->Signal(0); + // NULL event handle will simply wait immediately: + // https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12fence-seteventoncompletion#remarks + hr = frame_fence[bufferindex][queue]->SetEventOnCompletion(1, NULL); + assert(SUCCEEDED(hr)); } - assert(SUCCEEDED(hr)); - - allocationhandler->Update(FRAMECOUNT, BUFFERCOUNT); + hr = frame_fence[bufferindex][queue]->Signal(0); } + assert(SUCCEEDED(hr)); + + allocationhandler->Update(FRAMECOUNT, BUFFERCOUNT); } void GraphicsDevice_DX12::OnDeviceRemoved() diff --git a/WickedEngine/wiProfiler.cpp b/WickedEngine/wiProfiler.cpp index 1d85187ca..487a06036 100644 --- a/WickedEngine/wiProfiler.cpp +++ b/WickedEngine/wiProfiler.cpp @@ -32,9 +32,9 @@ namespace wi::profiler range_id cpu_frame; range_id gpu_frame; GPUQueryHeap queryHeap; - GPUBuffer queryResultBuffer[GraphicsDevice::GetBufferCount() + 1]; + GPUBuffer queryResultBuffer[GraphicsDevice::GetBufferCount()]; std::atomic nextQuery{ 0 }; - int queryheap_idx = 0; + uint32_t queryheap_idx = 0; bool drawn_this_frame = false; wi::Color background_color = wi::Color(20, 20, 20, 230); wi::Color text_color = wi::Color::White(); @@ -58,6 +58,9 @@ namespace wi::profiler int gpuBegin[arraysize(queryResultBuffer)]; int gpuEnd[arraysize(queryResultBuffer)]; + int gpuBegin_current = -1; + int gpuEnd_current = -1; + bool IsCPURange() const { return !cmd.IsValid(); } }; wi::unordered_map ranges; @@ -110,6 +113,7 @@ namespace wi::profiler GraphicsDevice* device = wi::graphics::GetDevice(); CommandList cmd = device->BeginCommandList(); + queryheap_idx = device->GetBufferIndex(); device->QueryReset( &queryHeap, @@ -130,6 +134,7 @@ namespace wi::profiler // note: read the GPU Frame end range manually because it will be on a separate command list than start point: auto& gpu_range = ranges[gpu_frame]; + gpu_range.gpuEnd_current = gpu_range.gpuEnd[queryheap_idx]; gpu_range.gpuEnd[queryheap_idx] = nextQuery.fetch_add(1); device->QueryEnd(&queryHeap, gpu_range.gpuEnd[queryheap_idx], cmd); @@ -147,25 +152,22 @@ namespace wi::profiler ); nextQuery.store(0); - queryheap_idx = (queryheap_idx + 1) % arraysize(queryResultBuffer); - uint64_t* queryResults = (uint64_t*)queryResultBuffer[queryheap_idx].mapped_data; + const uint64_t* queryResults = (const uint64_t*)queryResultBuffer[queryheap_idx].mapped_data; for (auto& x : ranges) { auto& range = x.second; + if (!range.in_use) + continue; if (!range.IsCPURange()) { - int begin_query = range.gpuBegin[queryheap_idx]; - int end_query = range.gpuEnd[queryheap_idx]; - if (queryResultBuffer[queryheap_idx].mapped_data != nullptr && begin_query >= 0 && end_query >= 0) + if (queryResults != nullptr && range.gpuBegin_current >= 0 && range.gpuEnd_current >= 0) { - uint64_t begin_result = queryResults[begin_query]; - uint64_t end_result = queryResults[end_query]; + const uint64_t begin_result = queryResults[range.gpuBegin_current]; + const uint64_t end_result = queryResults[range.gpuEnd_current]; range.time = (float)abs((double)(end_result - begin_result) / gpu_frequency); } - range.gpuBegin[queryheap_idx] = -1; - range.gpuEnd[queryheap_idx] = -1; } range.times[range.avg_counter++ % arraysize(range.times)] = range.time; @@ -232,8 +234,10 @@ namespace wi::profiler ranges[id].name = name; ranges[id].cmd = cmd; + GraphicsDevice* device = wi::graphics::GetDevice(); + ranges[id].gpuBegin_current = ranges[id].gpuBegin[queryheap_idx]; ranges[id].gpuBegin[queryheap_idx] = nextQuery.fetch_add(1); - wi::graphics::GetDevice()->QueryEnd(&queryHeap, ranges[id].gpuBegin[queryheap_idx], cmd); + device->QueryEnd(&queryHeap, ranges[id].gpuBegin[queryheap_idx], cmd); lock.unlock(); @@ -262,8 +266,10 @@ namespace wi::profiler } else { + GraphicsDevice* device = wi::graphics::GetDevice(); + ranges[id].gpuEnd_current = ranges[id].gpuEnd[queryheap_idx]; ranges[id].gpuEnd[queryheap_idx] = nextQuery.fetch_add(1); - wi::graphics::GetDevice()->QueryEnd(&queryHeap, it->second.gpuEnd[queryheap_idx], it->second.cmd); + device->QueryEnd(&queryHeap, it->second.gpuEnd[queryheap_idx], it->second.cmd); } } else @@ -330,6 +336,8 @@ namespace wi::profiler for (auto& x : ranges) { + if (!x.second.in_use) + continue; if (x.second.IsCPURange()) { if (x.first == cpu_frame) @@ -354,7 +362,7 @@ namespace wi::profiler { ss << "\t" << x.first << " (" << x.second.num_hits << "x)" << ": " << std::fixed << x.second.total_time << " ms" << std::endl; } - else + else if(x.second.num_hits == 1) { ss << "\t" << x.first << ": " << std::fixed << x.second.total_time << " ms" << std::endl; } @@ -371,7 +379,7 @@ namespace wi::profiler { ss << "\t" << x.first << " (" << x.second.num_hits << "x)" << ": " << std::fixed << x.second.total_time << " ms" << std::endl; } - else + else if (x.second.num_hits == 1) { ss << "\t" << x.first << ": " << std::fixed << x.second.total_time << " ms" << std::endl; } diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index ecd2b3078..1621c1eaf 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -151,7 +151,7 @@ namespace wi::scene } // Advance to next query result buffer to use (this will be the oldest one that was written) - queryheap_idx = (queryheap_idx + 1) % arraysize(queryResultBuffer); + queryheap_idx = device->GetBufferIndex(); // Clear query allocation state: queryAllocator.store(0); diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index ee7451e66..3590faf0d 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -125,7 +125,7 @@ namespace wi::scene // Occlusion query state: struct OcclusionResult { - int occlusionQueries[wi::graphics::GraphicsDevice::GetBufferCount() + 1]; + int occlusionQueries[wi::graphics::GraphicsDevice::GetBufferCount()]; // occlusion result history bitfield (32 bit->32 frame history) uint32_t occlusionHistory = ~0u; @@ -142,7 +142,7 @@ namespace wi::scene wi::graphics::GPUQueryHeap queryHeap; wi::graphics::GPUBuffer queryResultBuffer[arraysize(OcclusionResult::occlusionQueries)]; wi::graphics::GPUBuffer queryPredicationBuffer; - int queryheap_idx = 0; + uint32_t queryheap_idx = 0; mutable std::atomic queryAllocator{ 0 }; // Surfel GI resources: diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index ebcf623e5..f1ad04253 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 176; + const int revision = 177; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);