Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GPU raster time profiling to wr-stats. #225

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Some generated files are not rendered by default. Learn more.

@@ -697,6 +697,56 @@ pub struct VBOId(gl::GLuint);
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
struct IBOId(gl::GLuint);

pub struct GpuProfile {
active_query: usize,
gl_queries: Vec<gl::GLuint>,
}

impl GpuProfile {
pub fn new() -> GpuProfile {
let queries = gl::gen_queries(4);

// Kick initial queries off so that when we wait for the prev
// query it doesn't block on the first run through.
for qid in &queries {
gl::query_counter(*qid, gl::TIMESTAMP);
}

GpuProfile {
active_query: 0,
gl_queries: queries,
}
}

pub fn begin(&mut self) {
let qid = self.gl_queries[self.active_query * 2 + 0];
gl::query_counter(qid, gl::TIMESTAMP);
}

pub fn end(&mut self) -> u64 {
let qid = self.gl_queries[self.active_query * 2 + 1];
gl::query_counter(qid, gl::TIMESTAMP);

self.active_query = 1 - self.active_query;

// Wait until the previous results are available
let qid_prev_start = self.gl_queries[self.active_query * 2 + 0];
let qid_prev_end = self.gl_queries[self.active_query * 2 + 1];
while gl::get_query_object_iv(qid_prev_end, gl::QUERY_RESULT_AVAILABLE) == 0 {}

let start_time = gl::get_query_object_ui64v(qid_prev_start, gl::QUERY_RESULT);
let end_time = gl::get_query_object_ui64v(qid_prev_end, gl::QUERY_RESULT);

end_time - start_time
}
}

impl Drop for GpuProfile {
fn drop(&mut self) {
gl::delete_queries(&self.gl_queries);
}
}

#[derive(Debug, Copy, Clone)]
pub enum VertexUsageHint {
Static,
@@ -171,7 +171,8 @@ pub struct RendererProfileCounters {
}

pub struct RendererProfileTimers {
pub total_time: TimeProfileCounter,
pub cpu_time: TimeProfileCounter,
pub gpu_time: TimeProfileCounter,
}

impl RendererProfileCounters {
@@ -194,7 +195,8 @@ impl RendererProfileCounters {
impl RendererProfileTimers {
pub fn new() -> RendererProfileTimers {
RendererProfileTimers {
total_time: TimeProfileCounter::new("Compositor CPU Time", false),
cpu_time: TimeProfileCounter::new("Compositor CPU Time", false),
gpu_time: TimeProfileCounter::new("GPU Time", false),
}
}
}
@@ -324,29 +326,39 @@ impl ProfileGraph {
}

pub struct Profiler {
x: f32,
y: f32,
x_left: f32,
y_left: f32,
x_right: f32,
y_right: f32,
backend_time: ProfileGraph,
render_time: ProfileGraph,
compositor_time: ProfileGraph,
gpu_time: ProfileGraph,
}

impl Profiler {
pub fn new() -> Profiler {
Profiler {
x: 0.0,
y: 0.0,
x_left: 0.0,
y_left: 0.0,
x_right: 0.0,
y_right: 0.0,
backend_time: ProfileGraph::new(600),
render_time: ProfileGraph::new(600),
compositor_time: ProfileGraph::new(600),
gpu_time: ProfileGraph::new(600),
}
}

fn draw_counters(&mut self,
counters: &[&ProfileCounter],
debug_renderer: &mut DebugRenderer) {
debug_renderer: &mut DebugRenderer,
left: bool) {
let mut label_rect = Rect::zero();
let mut value_rect = Rect::zero();
let mut current_x = self.x;
let mut current_y = self.y;
let (mut current_x, mut current_y) = if left {
(self.x_left, self.y_left)
} else {
(self.x_right, self.y_right)
};
let mut color_index = 0;
let line_height = debug_renderer.line_height();

@@ -368,7 +380,11 @@ impl Profiler {

color_index = 0;
current_x = label_rect.origin.x + label_rect.size.width + 60.0;
current_y = self.y;
current_y = if left {
self.y_left
} else {
self.y_right
};

for counter in counters {
let rect = debug_renderer.add_text(current_x,
@@ -388,43 +404,54 @@ impl Profiler {
total_rect.origin.y + total_rect.size.height,
&ColorF::new(0.1, 0.1, 0.1, 0.8),
&ColorF::new(0.2, 0.2, 0.2, 0.8));
self.y = total_rect.origin.y + total_rect.size.height + 30.0;
let new_y = total_rect.origin.y + total_rect.size.height + 30.0;
if left {
self.y_left = new_y;
} else {
self.y_right = new_y;
}
}

pub fn draw_profile(&mut self,
backend_profile: &BackendProfileCounters,
renderer_profile: &RendererProfileCounters,
renderer_timers: &RendererProfileTimers,
debug_renderer: &mut DebugRenderer) {
self.x = 20.0;
self.y = 40.0;
self.x_left = 20.0;
self.y_left = 40.0;
self.x_right = 400.0;
self.y_right = 40.0;

self.draw_counters(&[
&renderer_profile.frame_counter,
&renderer_profile.frame_time,
], debug_renderer);
], debug_renderer, true);

self.draw_counters(&[
&backend_profile.font_templates,
&backend_profile.image_templates,
], debug_renderer);
], debug_renderer, true);

self.draw_counters(&[
&backend_profile.total_time,
&renderer_timers.total_time,
], debug_renderer);
&renderer_timers.cpu_time,
&renderer_timers.gpu_time,
], debug_renderer, false);

self.draw_counters(&[
&renderer_profile.draw_calls,
&renderer_profile.vertices,
], debug_renderer);
], debug_renderer, false);

self.backend_time.push(backend_profile.total_time.nanoseconds);
self.render_time.push(renderer_timers.total_time.nanoseconds);

let rect = self.backend_time.draw_graph(self.x, self.y, "CPU (backend)", debug_renderer);
self.y += rect.size.height + 10.0;
let rect = self.render_time.draw_graph(self.x, self.y, "CPU (compositor)", debug_renderer);
self.y += rect.size.height + 10.0;
self.compositor_time.push(renderer_timers.cpu_time.nanoseconds);
self.gpu_time.push(renderer_timers.gpu_time.nanoseconds);

let rect = self.backend_time.draw_graph(self.x_left, self.y_left, "CPU (backend)", debug_renderer);
self.y_left += rect.size.height + 10.0;
let rect = self.compositor_time.draw_graph(self.x_left, self.y_left, "CPU (compositor)", debug_renderer);
self.y_left += rect.size.height + 10.0;
let rect = self.gpu_time.draw_graph(self.x_left, self.y_left, "GPU", debug_renderer);
self.y_left += rect.size.height + 10.0;
}
}
@@ -4,7 +4,7 @@

use batch::{RasterBatch, VertexBufferId};
use debug_render::DebugRenderer;
use device::{Device, ProgramId, TextureId, UniformLocation, VertexFormat};
use device::{Device, ProgramId, TextureId, UniformLocation, VertexFormat, GpuProfile};
use device::{TextureFilter, VAOId, VBOId, VertexUsageHint, FileWatcherHandler};
use euclid::{Rect, Matrix4, Point2D, Size2D};
use fnv::FnvHasher;
@@ -161,6 +161,8 @@ pub struct Renderer {
raster_op_target_a8: TextureId,
raster_op_target_rgba8: TextureId,
temporary_fb_texture: TextureId,

gpu_profile: GpuProfile,
}

impl Renderer {
@@ -311,6 +313,7 @@ impl Renderer {
raster_op_target_rgba8: raster_op_target_rgba8,
temporary_fb_texture: temporary_fb_texture,
max_raster_op_size: max_raster_op_size,
gpu_profile: GpuProfile::new(),
};

renderer.update_uniform_locations();
@@ -379,7 +382,9 @@ impl Renderer {
pub fn render(&mut self, framebuffer_size: Size2D<u32>) {
let mut profile_timers = RendererProfileTimers::new();

profile_timers.total_time.profile(|| {
self.gpu_profile.begin();

profile_timers.cpu_time.profile(|| {
self.device.begin_frame();

gl::disable(gl::SCISSOR_TEST);
@@ -396,6 +401,9 @@ impl Renderer {
let ns = current_time - self.last_time;
self.profile_counters.frame_time.set(ns);

let gpu_ns = self.gpu_profile.end();
profile_timers.gpu_time.set(gpu_ns);

if self.enable_profiler {
self.profiler.draw_profile(&self.backend_profile_counters,
&self.profile_counters,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.