aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Stratiienko <roman.stratiienko@globallogic.com>2019-11-28 17:51:16 +0200
committerRoman Stratiienko <roman.stratiienko@globallogic.com>2019-12-04 17:04:34 +0200
commit0d1a2cdbdf1fa126735f49f07f709a6a501aea52 (patch)
tree87a59234db66d25817e324e74456202d1ae6b937
parentc56eede3396a4a8aa26126e20bf6d174a6a75f7c (diff)
downloaddrm_hwcomposer-0d1a2cdbdf1fa126735f49f07f709a6a501aea52.tar.gz
drm_hwcomposer: Introduce dumpsys metrics
To make optimal performance/power consumption ratio we want to use composing by dedicated hardware to merge as much as possible composition cases. We are going to continuously optimize and improve drm_hwcomposer HAL, that makes high demand on formal validation process. Introduce "pixel operation" definition. It should be in direct ratio with power consumption, but currently it roughly calculated as sum of pixels merged by each layer. In some future we should apply some average gains depending of operation type to calculate pixops more precisely. (e.g. scaling should take more pixops than blending, and blending should take more that copying, etc.). Using pixops could be very helpful when drm_hwc HAL have a choice which layer sets to merge by GPU, making possible minimal energy model based planning. Create statistics of the following events: 1. Total frames count 2. Total pixel operations 3. Pixel operations validated to use GPU (CLIENT) 4. Calculate composer efficiency: DEVICE/TOTAL operations ratio 5. Failed atomic validation commits count 6. Failed atomic presenting commits count Usage: - $ adb shell dumpsys SurfaceFlinger Statistics will be shown at the end of the dump in 2 forms: 1. Since system launched 2. Since last dumpsys command called Using statistics for the regression slope monitoring example: 1. Boot the board without the change 2. Use touch or keyboard (avoid using of mouse pointer) to do some predefined actions (open application, start video, etc.) 3. Save the metrics 4. Boot the board with the change 5. Do exactly the same actions as in (2) 6. Save the metrics 7. Use metrics before and after change to indicate regression slope Signed-off-by: Roman Stratiienko <roman.stratiienko@globallogic.com>
-rw-r--r--drmhwctwo.cpp74
-rw-r--r--include/drmhwctwo.h26
2 files changed, 95 insertions, 5 deletions
diff --git a/drmhwctwo.cpp b/drmhwctwo.cpp
index ffc5fcd..c34c0b7 100644
--- a/drmhwctwo.cpp
+++ b/drmhwctwo.cpp
@@ -128,9 +128,58 @@ HWC2::Error DrmHwcTwo::DestroyVirtualDisplay(hwc2_display_t display) {
return unsupported(__func__, display);
}
-void DrmHwcTwo::Dump(uint32_t *size, char *buffer) {
- // TODO: Implement dump
- unsupported(__func__, size, buffer);
+std::string DrmHwcTwo::HwcDisplay::DumpDelta(
+ DrmHwcTwo::HwcDisplay::Stats delta) {
+ if (delta.total_pixops_ == 0)
+ return "No stats yet";
+ double Ratio = 1.0 - double(delta.gpu_pixops_) / double(delta.total_pixops_);
+
+ return (std::stringstream()
+ << " Total frames count: " << delta.total_frames_ << "\n"
+ << " Failed to test commit frames: " << delta.failed_kms_validate_
+ << "\n"
+ << " Failed to commit frames: " << delta.failed_kms_present_ << "\n"
+ << ((delta.failed_kms_present_ > 0)
+ ? " !!! Internal failure, FIX it please\n"
+ : "")
+ << " Pixel operations (free units)"
+ << " : [TOTAL: " << delta.total_pixops_
+ << " / GPU: " << delta.gpu_pixops_ << "]\n"
+ << " Composition efficiency: " << Ratio)
+ .str();
+}
+
+std::string DrmHwcTwo::HwcDisplay::Dump() {
+ auto out = (std::stringstream()
+ << "- Display on: " << connector_->name() << "\n"
+ << "Statistics since system boot:\n"
+ << DumpDelta(total_stats_) << "\n\n"
+ << "Statistics since last dumpsys request:\n"
+ << DumpDelta(total_stats_.minus(prev_stats_)) << "\n\n")
+ .str();
+
+ memcpy(&prev_stats_, &total_stats_, sizeof(Stats));
+ return out;
+}
+
+void DrmHwcTwo::Dump(uint32_t *outSize, char *outBuffer) {
+ supported(__func__);
+
+ if (outBuffer != nullptr) {
+ auto copiedBytes = mDumpString.copy(outBuffer, *outSize);
+ *outSize = static_cast<uint32_t>(copiedBytes);
+ return;
+ }
+
+ std::stringstream output;
+
+ output << "-- drm_hwcomposer --\n\n";
+
+ for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &dp : displays_)
+ output << dp.second.Dump();
+
+ mDumpString = output.str();
+ *outSize = static_cast<uint32_t>(mDumpString.size());
}
uint32_t DrmHwcTwo::GetMaxVirtualDisplayCount() {
@@ -657,7 +706,12 @@ HWC2::Error DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *present_fence) {
supported(__func__);
HWC2::Error ret;
+ ++total_stats_.total_frames_;
+
ret = CreateComposition(false);
+ if (ret != HWC2::Error::None)
+ ++total_stats_.failed_kms_present_;
+
if (ret == HWC2::Error::BadLayer) {
// Can we really have no client or device layers?
*present_fence = -1;
@@ -803,24 +857,36 @@ HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types,
for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_)
z_map.emplace(std::make_pair(l.second.z_order(), &l.second));
+ uint32_t total_pixops = 0, gpu_pixops = 0;
+
bool gpu_block = false;
for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
+ hwc_rect_t df = l.second->display_frame();
+ uint32_t pixops = (df.right - df.left) * (df.bottom - df.top);
if (gpu_block || avail_planes == 0 ||
!HardwareSupportsLayerType(l.second->sf_type()) ||
!importer_->CanImportBuffer(l.second->buffer())) {
gpu_block = true;
+ gpu_pixops += pixops;
++*num_types;
} else {
avail_planes--;
}
+ total_pixops += pixops;
l.second->set_validated_type(gpu_block ? HWC2::Composition::Client
: HWC2::Composition::Device);
}
- if (CreateComposition(true) != HWC2::Error::None)
+ if (CreateComposition(true) != HWC2::Error::None) {
+ ++total_stats_.failed_kms_validate_;
+ gpu_pixops = total_pixops;
for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_)
l.second.set_validated_type(HWC2::Composition::Client);
+ }
+
+ total_stats_.gpu_pixops_ += gpu_pixops;
+ total_stats_.total_pixops_ += total_pixops;
return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None;
}
diff --git a/include/drmhwctwo.h b/include/drmhwctwo.h
index c6ce640..90cffa4 100644
--- a/include/drmhwctwo.h
+++ b/include/drmhwctwo.h
@@ -86,6 +86,10 @@ class DrmHwcTwo : public hwc2_device_t {
return OutputFd(&release_fence_raw_);
}
+ hwc_rect_t display_frame() {
+ return display_frame_;
+ }
+
void PopulateDrmLayer(DrmHwcLayer *layer);
// Layer hooks
@@ -145,6 +149,8 @@ class DrmHwcTwo : public hwc2_device_t {
hwc2_function_pointer_t func);
void ClearDisplay();
+ std::string Dump();
+
// HWC Hooks
HWC2::Error AcceptDisplayChanges();
HWC2::Error CreateLayer(hwc2_layer_t *layer);
@@ -216,6 +222,22 @@ class DrmHwcTwo : public hwc2_device_t {
int32_t color_mode_;
uint32_t frame_no_ = 0;
+ /* Statistics */
+ struct Stats {
+ Stats minus(Stats b) {
+ return {total_frames_ - b.total_frames_,
+ total_pixops_ - b.total_pixops_, gpu_pixops_ - b.gpu_pixops_,
+ failed_kms_validate_ - b.failed_kms_validate_,
+ failed_kms_present_ - b.failed_kms_present_};
+ }
+
+ uint32_t total_frames_ = 0;
+ uint64_t total_pixops_ = 0;
+ uint64_t gpu_pixops_ = 0;
+ uint32_t failed_kms_validate_ = 0;
+ uint32_t failed_kms_present_ = 0;
+ } total_stats_, prev_stats_;
+ std::string DumpDelta(DrmHwcTwo::HwcDisplay::Stats delta);
};
class DrmHotplugHandler : public DrmEventHandler {
@@ -289,7 +311,7 @@ class DrmHwcTwo : public hwc2_device_t {
HWC2::Error CreateVirtualDisplay(uint32_t width, uint32_t height,
int32_t *format, hwc2_display_t *display);
HWC2::Error DestroyVirtualDisplay(hwc2_display_t display);
- void Dump(uint32_t *size, char *buffer);
+ void Dump(uint32_t *outSize, char *outBuffer);
uint32_t GetMaxVirtualDisplayCount();
HWC2::Error RegisterCallback(int32_t descriptor, hwc2_callback_data_t data,
hwc2_function_pointer_t function);
@@ -300,5 +322,7 @@ class DrmHwcTwo : public hwc2_device_t {
ResourceManager resource_manager_;
std::map<hwc2_display_t, HwcDisplay> displays_;
std::map<HWC2::Callback, HwcCallback> callbacks_;
+
+ std::string mDumpString;
};
} // namespace android