diff --git a/CMakeLists.txt b/CMakeLists.txt index 70e7de829039860afa008da79e7945dc5453848f..41e0e02e9e66622a961346ba4e248b36487d7b39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -706,6 +706,7 @@ message("======================================================================= ${SRC_DIR}/utility/latency.hpp ${SRC_DIR}/utility/latency.cpp ${SRC_DIR}/utility/pass_timer.hpp ${SRC_DIR}/utility/pass_timer.cpp ${SRC_DIR}/utility/shadow_cache.hpp ${SRC_DIR}/utility/shadow_cache.cpp + ${SRC_DIR}/utility/statistic.hpp ${SRC_DIR}/utility/statistic.cpp ${SRC_DIR}/utility/stereo_transform.hpp ${SRC_DIR}/utility/stereo_transform.cpp ) @@ -739,7 +740,7 @@ message("======================================================================= utility/deferred_local_light.vert utility/deferred_local_light.frag - utility/deferred_local_light.vert + utility/deferred_local_light_with_shadow.frag utility/shadow.vert utility/shadow.geom diff --git a/src/utility/pass_timer.cpp b/src/utility/pass_timer.cpp index bc216e68a8d9e2b9cee0f77f601191bdf979690c..c987c3d16a337f1e7e99b55983643cb230e72226 100644 --- a/src/utility/pass_timer.cpp +++ b/src/utility/pass_timer.cpp @@ -68,6 +68,14 @@ void PassTimer::destroy(lava::device_ptr device) this->timestamp_zero = {}; } +void PassTimer::interface() +{ + for (Statistic::Ptr statistic : this->pass_statistcs) + { + statistic->interface(); + } +} + bool PassTimer::write_to_file(lava::device_ptr device) { if (!this->wait_timestamps(device)) @@ -112,7 +120,7 @@ void PassTimer::begin_pass(VkCommandBuffer command_buffer, const std::string& pa this->wait_infos.push_back(wait_info); VkQueryPool current_pool = this->query_pools[this->current_frame]; - vkCmdWriteTimestamp(command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, current_pool, this->current_timestamp); + vkCmdWriteTimestamp(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, current_pool, this->current_timestamp); this->current_timestamp++; } @@ -127,7 +135,7 @@ void PassTimer::end_pass(VkCommandBuffer command_buffer) } VkQueryPool current_pool = this->query_pools[this->current_frame]; - vkCmdWriteTimestamp(command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, current_pool, this->current_timestamp); + vkCmdWriteTimestamp(command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, current_pool, this->current_timestamp); this->current_timestamp++; } @@ -152,7 +160,7 @@ bool PassTimer::load_timestamp_specs(lava::device_ptr device) } this->timestamp_bits = graphics_queue_properties.timestampValidBits; - this->timestamp_period = device_properties.limits.timestampPeriod; + this->timestamp_period = (double)device_properties.limits.timestampPeriod; return true; } @@ -189,9 +197,9 @@ bool PassTimer::evaluate_wating_passes(lava::device_ptr device, lava::index fram //Subtract the end timestamp form the start timestamp and multiply it with timestamp_period. //The result of this computation gives the pass time in nano seconds //In order to get milli seconds divide by 10^6 - double start_time = (double)((timestamps[0] - this->timestamp_zero.value()) * this->timestamp_period) / 1000000.0; - double end_time = (double)((timestamps[1] - this->timestamp_zero.value()) * this->timestamp_period) / 1000000.0; - double delta_time = (double)((timestamps[1] - timestamps[0]) * this->timestamp_period) / 1000000.0; + double start_time = ((double)(timestamps[0] - this->timestamp_zero.value()) * this->timestamp_period) / 1000000.0; + double end_time = ((double)(timestamps[1] - this->timestamp_zero.value()) * this->timestamp_period) / 1000000.0; + double delta_time = ((double)(timestamps[1] - timestamps[0]) * this->timestamp_period) / 1000000.0; PassStatistic pass_statistic; pass_statistic.name = wait_info.name; @@ -205,6 +213,55 @@ bool PassTimer::evaluate_wating_passes(lava::device_ptr device, lava::index fram this->frame_statistics.push_back(frame_statistic); + for (uint32_t index = 0; index < this->pass_statistcs.size();) + { + Statistic::Ptr statistic = this->pass_statistcs[index]; + bool found = false; + + for (const PassStatistic& pass_statistic : frame_statistic) + { + if (statistic->get_name() == pass_statistic.name) + { + statistic->add_sample(pass_statistic.delta_time); + found = true; + + break; + } + } + + if (!found) + { + this->pass_statistcs.erase(this->pass_statistcs.begin() + index); + } + + else + { + index++; + } + } + + for (const PassStatistic& pass_statistic : frame_statistic) + { + bool found = false; + + for (Statistic::Ptr statistic : this->pass_statistcs) + { + if (statistic->get_name() == pass_statistic.name) + { + found = true; + break; + } + } + + if (!found) + { + Statistic::Ptr statistic = make_statistic(pass_statistic.name, 128); + statistic->add_sample(pass_statistic.delta_time); + + this->pass_statistcs.push_back(statistic); + } + } + this->wait_infos.erase(std::remove_if(this->wait_infos.begin(), this->wait_infos.end(), [=](const PassWaitInfo& wait_info) { return wait_info.frame_index == frame; diff --git a/src/utility/pass_timer.hpp b/src/utility/pass_timer.hpp index 292545a94c6356bae8b06b072096da27a7859ba5..20e349337ccb4ea8008bd30a4294420df921aca4 100644 --- a/src/utility/pass_timer.hpp +++ b/src/utility/pass_timer.hpp @@ -18,6 +18,8 @@ #include <optional> #include <memory> +#include "utility/statistic.hpp" + struct PassWaitInfo { std::string name; @@ -45,6 +47,7 @@ public: bool create(lava::device_ptr device, uint32_t frame_count, uint32_t pass_count); void destroy(lava::device_ptr device); + void interface(); bool write_to_file(lava::device_ptr device); @@ -71,13 +74,14 @@ private: uint32_t current_timestamp = 0; uint32_t timestamp_bits = 0; //number of bits used for a timestamp in case of a graphics queue - uint32_t timestamp_period = 0; //one increment of the timestamp in nanoseconds + double timestamp_period = 0; //one increment of the timestamp in nanoseconds std::optional<uint64_t> timestamp_zero; //the timestamp that defines the zero time-point std::vector<VkQueryPool> query_pools; std::vector<PassWaitInfo> wait_infos; std::vector<std::vector<PassStatistic>> frame_statistics; + std::vector<Statistic::Ptr> pass_statistcs; }; PassTimer::Ptr make_pass_timer(const std::string& base_directory); \ No newline at end of file diff --git a/src/utility/statistic.cpp b/src/utility/statistic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9adb0b872b02d55d06e1762a8d30687dbd6ed97e --- /dev/null +++ b/src/utility/statistic.cpp @@ -0,0 +1,102 @@ +#include "statistic.hpp" +#include <array> +#include <imgui.h> + +Statistic::Statistic(const std::string& name, uint32_t sample_count) : name(name) +{ + this->samples.resize(sample_count, 0.0f); +} + +void Statistic::interface() +{ + ImGui::PlotLines(this->name.c_str(), this->samples.data(), this->samples.size(), this->current_index, nullptr, 0.0f, this->get_max(), ImVec2(0, 64)); + + ImVec2 cursor = ImGui::GetCursorPos(); + ImGui::SetWindowFontScale(0.7f); + + ImGui::SetCursorPosX(cursor.x + 5); + ImGui::SetCursorPosY(cursor.y - 22.0f); + ImGui::Text("Avg: %8.4f", this->get_average()); + ImGui::SetCursorPosX(cursor.x + 90); + ImGui::SetCursorPosY(cursor.y - 22.0f); + ImGui::Text("Min: %8.4f", this->get_min()); + ImGui::SetCursorPosX(cursor.x + 175); + ImGui::SetCursorPosY(cursor.y - 22.0f); + ImGui::Text("Max: %8.4f", this->get_max()); + + ImGui::SetCursorPos(cursor); + ImGui::SetWindowFontScale(1.0); +} + +void Statistic::add_sample(float sample) +{ + this->samples[this->current_index] = sample; + this->current_index = (this->current_index + 1) % this->samples.size(); + this->valid_index = std::max(this->valid_index, this->current_index); +} + +float Statistic::get_average() const +{ + if (this->valid_index <= 0) + { + return 0.0f; + } + + float sample_sum = 0.0f; + + for (uint32_t index = 0; index < this->valid_index; index++) + { + sample_sum += this->samples[index]; + } + + return sample_sum / (float)this->valid_index; +} + +float Statistic::get_min() const +{ + if (this->valid_index <= 0) + { + return 0.0f; + } + + float sample_min = this->samples[0]; + + for (uint32_t index = 0; index < this->valid_index; index++) + { + sample_min = std::min(sample_min, this->samples[index]); + } + + return sample_min; +} + +float Statistic::get_max() const +{ + if (this->valid_index <= 0) + { + return 0.0f; + } + + float sample_max = this->samples[0]; + + for (uint32_t index = 0; index < this->valid_index; index++) + { + sample_max = std::max(sample_max, this->samples[index]); + } + + return sample_max; +} + +const std::string& Statistic::get_name() const +{ + return this->name; +} + +const std::vector<float>& Statistic::get_samples() const +{ + return this->samples; +} + +Statistic::Ptr make_statistic(const std::string& name, uint32_t sample_count) +{ + return std::make_shared<Statistic>(name, sample_count); +} \ No newline at end of file diff --git a/src/utility/statistic.hpp b/src/utility/statistic.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e3f0e1ad04f6f01bfff91177d398281fc563ae69 --- /dev/null +++ b/src/utility/statistic.hpp @@ -0,0 +1,41 @@ +/* + TODO + Example: + + TODO +*/ + +#pragma once +#include <memory> +#include <string> +#include <vector> +#include <cstdint> + +class Statistic +{ +public: + typedef std::shared_ptr<Statistic> Ptr; + +private: + std::string name; + std::vector<float> samples; + + uint32_t current_index = 0; + uint32_t valid_index = 0; + +public: + Statistic(const std::string& name, uint32_t sample_count); + + void interface(); + + void add_sample(float sample); + + float get_average() const; + float get_min() const; + float get_max() const; + + const std::string& get_name() const; + const std::vector<float>& get_samples() const; +}; + +Statistic::Ptr make_statistic(const std::string& name, uint32_t sample_count); \ No newline at end of file diff --git a/src/vr_application.cpp b/src/vr_application.cpp index 06da1f2014d904f351070032597838cb94d1f45d..9e1297f103cbe8fa234255ce34d6bac230e88318 100644 --- a/src/vr_application.cpp +++ b/src/vr_application.cpp @@ -386,6 +386,8 @@ bool VRApplication::on_create() return false; } + this->frame_time = make_statistic("Frame Time", 128); + return this->create_config(); } @@ -486,7 +488,8 @@ bool VRApplication::on_interface() ImGui::Checkbox("Frame Capture", &capture_enabled); this->frame_capture->set_enabled(capture_enabled); - ImGui::PlotLines("Frame Time", this->frame_times.data(), this->frame_times.size(), this->frame_time_offset, nullptr, 0.0, 11.11); + this->frame_time->interface(); + this->pass_timer->interface(); this->app->draw_about(true); } @@ -498,8 +501,7 @@ bool VRApplication::on_interface() bool VRApplication::on_update(lava::delta delta_time) { - this->frame_times[this->frame_time_offset] = delta_time; - this->frame_time_offset = (this->frame_time_offset + 1) % this->frame_times.size(); + this->frame_time->add_sample(delta_time); if (this->selected_strategy.has_value()) { diff --git a/src/vr_application.hpp b/src/vr_application.hpp index b23a9b779d0011e0f7bc1eaf379a5f8756b5daab..a66273e357a903703b8312fb9be4c788ed9fd7c1 100644 --- a/src/vr_application.hpp +++ b/src/vr_application.hpp @@ -17,6 +17,7 @@ #include "utility/frame_capture.hpp" #include "utility/pass_timer.hpp" #include "utility/stereo_transform.hpp" +#include "utility/statistic.hpp" class VRApplication { @@ -85,6 +86,5 @@ private: CommandParser command_parser; bool created = false; - std::array<float, 128> frame_times; - uint32_t frame_time_offset = 0; + Statistic::Ptr frame_time; }; \ No newline at end of file