205 lines
6.2 KiB
C++
205 lines
6.2 KiB
C++
/* Copyright (c) 2018-2025, Arm Limited and Contributors
|
|
* Copyright (c) 2020-2025, Broadcom Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 the "License";
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <ctime>
|
|
#include <future>
|
|
#include <map>
|
|
#include <set>
|
|
#include <vector>
|
|
|
|
#include "stats_common.h"
|
|
#include "stats_provider.h"
|
|
#include "timer.h"
|
|
|
|
namespace vkb
|
|
{
|
|
class RenderContext;
|
|
|
|
namespace core
|
|
{
|
|
template <vkb::BindingType bindingType>
|
|
class CommandBuffer;
|
|
using CommandBufferC = CommandBuffer<vkb::BindingType::C>;
|
|
} // namespace core
|
|
|
|
/*
|
|
* @brief Helper class for querying statistics about the CPU and the GPU
|
|
*/
|
|
class Stats
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Constructs a Stats object
|
|
* @param render_context The RenderContext for this sample
|
|
* @param buffer_size Size of the circular buffers
|
|
*/
|
|
explicit Stats(RenderContext &render_context, size_t buffer_size = 16);
|
|
|
|
/**
|
|
* @brief Destroys the Stats object
|
|
*/
|
|
~Stats();
|
|
|
|
/**
|
|
* @brief Request specific set of stats to be collected
|
|
* @param requested_stats Set of stats to be collected if available
|
|
* @param sampling_config Sampling mode configuration (polling or continuous)
|
|
*/
|
|
void request_stats(const std::set<StatIndex> &requested_stats,
|
|
CounterSamplingConfig sampling_config = {CounterSamplingMode::Polling});
|
|
|
|
/**
|
|
* @brief Resizes the stats buffers according to the width of the screen
|
|
* @param width The width of the screen
|
|
*/
|
|
void resize(size_t width);
|
|
|
|
/**
|
|
* @brief Checks if an enabled stat is available in the current platform
|
|
* @param index The stat index
|
|
* @return True if the stat is available, false otherwise
|
|
*/
|
|
bool is_available(StatIndex index) const;
|
|
|
|
/**
|
|
* @brief Returns data relevant for graphing a specific statistic
|
|
* @param index The stat index of the data requested
|
|
* @return The data of the specified stat
|
|
*/
|
|
const StatGraphData &get_graph_data(StatIndex index) const;
|
|
|
|
/**
|
|
* @brief Returns the collected data for a specific statistic
|
|
* @param index The stat index of the data requested
|
|
* @return The data of the specified stat
|
|
*/
|
|
const std::vector<float> &get_data(StatIndex index) const
|
|
{
|
|
return counters.at(index);
|
|
};
|
|
|
|
/**
|
|
* @return The requested stats
|
|
*/
|
|
const std::set<StatIndex> &get_requested_stats() const
|
|
{
|
|
return requested_stats;
|
|
}
|
|
|
|
/**
|
|
* @brief Update statistics, must be called after every frame
|
|
* @param delta_time Time since last update
|
|
*/
|
|
void update(float delta_time);
|
|
|
|
/**
|
|
* @brief A command buffer that we want to collect stats about has just begun
|
|
*
|
|
* Some stats providers (like the Vulkan extension one) can only collect stats
|
|
* about the execution of a specific command buffer. In those cases we need to
|
|
* know when a command buffer has begun and when it's about to end so that we
|
|
* can inject some extra commands into the command buffer to control the stats
|
|
* collection. This method tells the stats provider that a command buffer has
|
|
* begun so that can happen. The command buffer must be in a recording state
|
|
* when this method is called.
|
|
* @param cb The command buffer
|
|
*/
|
|
void begin_sampling(vkb::core::CommandBufferC &cb);
|
|
|
|
/**
|
|
* @brief A command buffer that we want to collect stats about is about to be ended
|
|
*
|
|
* Some stats providers (like the Vulkan extension one) can only collect stats
|
|
* about the execution of a specific command buffer. In those cases we need to
|
|
* know when a command buffer has begun and when it's about to end so that we
|
|
* can inject some extra commands into the command buffer to control the stats
|
|
* collection. This method tells the stats provider that a command buffer is
|
|
* about to be ended so that can happen. The command buffer must be in a recording
|
|
* state when this method is called.
|
|
* @param cb The command buffer
|
|
*/
|
|
void end_sampling(vkb::core::CommandBufferC &cb);
|
|
|
|
private:
|
|
/// The render context
|
|
RenderContext &render_context;
|
|
|
|
/// Stats that were requested - they may not all be available
|
|
std::set<StatIndex> requested_stats;
|
|
|
|
/// Provider that tracks frame times
|
|
StatsProvider *frame_time_provider;
|
|
|
|
/// A list of stats providers to use in priority order
|
|
std::vector<std::unique_ptr<StatsProvider>> providers;
|
|
|
|
/// Counter sampling configuration
|
|
CounterSamplingConfig sampling_config;
|
|
|
|
/// Size of the circular buffers
|
|
size_t buffer_size;
|
|
|
|
/// Timer used in the main thread to compute delta time
|
|
Timer main_timer;
|
|
|
|
/// Timer used by the worker thread to throttle counter sampling
|
|
Timer worker_timer;
|
|
|
|
/// Alpha smoothing for running average
|
|
float alpha_smoothing{0.2f};
|
|
|
|
/// Circular buffers for counter data
|
|
std::map<StatIndex, std::vector<float>> counters{};
|
|
|
|
/// Worker thread for continuous sampling
|
|
std::thread worker_thread;
|
|
|
|
/// Promise to stop the worker thread
|
|
std::unique_ptr<std::promise<void>> stop_worker;
|
|
|
|
/// A mutex for accessing measurements during continuous sampling
|
|
std::mutex continuous_sampling_mutex;
|
|
|
|
/// The samples read during continuous sampling
|
|
std::vector<StatsProvider::Counters> continuous_samples;
|
|
|
|
/// A flag specifying if the worker thread should add entries to continuous_samples
|
|
bool should_add_to_continuous_samples{false};
|
|
|
|
/// The samples waiting to be displayed
|
|
std::vector<StatsProvider::Counters> pending_samples;
|
|
|
|
/// A value which helps keep a steady pace of continuous samples output.
|
|
float fractional_pending_samples{0.0f};
|
|
|
|
/// The worker thread function for continuous sampling;
|
|
/// it adds a new entry to continuous_samples at every interval
|
|
void continuous_sampling_worker(std::future<void> should_terminate);
|
|
|
|
/// Updates circular buffers for CPU and GPU counters
|
|
void push_sample(const StatsProvider::Counters &sample);
|
|
|
|
// Push counters to external profilers
|
|
void profile_counters() const;
|
|
};
|
|
|
|
} // namespace vkb
|