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

Fixed GPU profiling #226

Merged
merged 2 commits into from Mar 4, 2016
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

Add GPU raster time profiling to wr-stats.

  • Loading branch information
gw3583 committed Mar 4, 2016
commit 69a6f89ecc2fa267f79cbaf294c26a75c6fa5c30
@@ -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.