Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
++
  • Loading branch information
jonahwilliams committed Oct 19, 2023
commit c014eba26e0278a9438e08750fc46f6c71f4f536
3 changes: 2 additions & 1 deletion impeller/renderer/backend/gles/context_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

#include "impeller/renderer/backend/gles/context_gles.h"
#include <memory>

#include "impeller/base/config.h"
#include "impeller/base/validation.h"
Expand Down Expand Up @@ -62,7 +63,7 @@ ContextGLES::ContextGLES(std::unique_ptr<ProcTableGLES> gl,
std::shared_ptr<SamplerLibraryGLES>(new SamplerLibraryGLES(
device_capabilities_->SupportsDecalSamplerAddressMode()));
}

gpu_tracer_ = std::make_shared<GPUTracerGLES>(GetReactor()->GetProcTable());
is_valid_ = true;
}

Expand Down
12 changes: 2 additions & 10 deletions impeller/renderer/backend/gles/context_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,7 @@ class ContextGLES final : public Context,
bool RemoveReactorWorker(ReactorGLES::WorkerID id);

std::shared_ptr<GPUTracerGLES> GetGPUTracer() const {
FML_LOG(ERROR) << "Size: " << gpu_tracers_.size();
auto result = gpu_tracers_.find(std::this_thread::get_id());
if (result == gpu_tracers_.end()) {
return gpu_tracers_[std::this_thread::get_id()] =
std::make_shared<GPUTracerGLES>(GetReactor()->GetProcTable());
} else {
return result->second;
}
return gpu_tracer_;
}

private:
Expand All @@ -58,8 +51,7 @@ class ContextGLES final : public Context,
std::shared_ptr<PipelineLibraryGLES> pipeline_library_;
std::shared_ptr<SamplerLibraryGLES> sampler_library_;
std::shared_ptr<AllocatorGLES> resource_allocator_;
mutable std::unordered_map<std::thread::id, std::shared_ptr<GPUTracerGLES>>
gpu_tracers_;
std::shared_ptr<GPUTracerGLES> gpu_tracer_;

// Note: This is stored separately from the ProcTableGLES CapabilitiesGLES
// in order to satisfy the Context::GetCapabilities signature which returns
Expand Down
106 changes: 47 additions & 59 deletions impeller/renderer/backend/gles/gpu_tracer_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,27 @@
// found in the LICENSE file.

#include "impeller/renderer/backend/gles/gpu_tracer_gles.h"
#include "GLES2/gl2ext.h"
#include "GLES3/gl3.h"
#include <thread>
#include "fml/trace_event.h"

namespace impeller {

static const constexpr char* kAngleTimerQuery = "GL_ANGLE_timer_query";
static const constexpr char* kExtTimerQuery = "GL_EXT_timer_query";
static const constexpr char* kExtDisjointTimerQuery =
"GL_EXT_disjoint_timer_query";

GPUTracerGLES::GPUTracerGLES(const ProcTableGLES& gl) {
#ifdef IMPELLER_DEBUG
auto desc = gl.GetDescription();
enabled_ = desc->HasExtension(kAngleTimerQuery) ||
desc->HasExtension(kExtTimerQuery) ||
desc->HasExtension(kExtDisjointTimerQuery);
enabled_ = desc->HasExtension("GL_EXT_disjoint_timer_query");
#endif // IMPELLER_DEBUG
}

void GPUTracerGLES::MarkFrameStart(const ProcTableGLES& gl) {
if (!enabled_ || has_started_frame_) {
if (!enabled_ || has_started_frame_ ||
std::this_thread::get_id() != raster_thread_) {
return;
}
std::stringstream ss;
ss << std::this_thread::get_id();
uint64_t id = std::stoull(ss.str());

FML_LOG(ERROR) << "Start: " << id;
// At the beginning of a frame, check the status of all pending
// previous queries.
ProcessQueries(gl);

uint32_t query = 0;
gl.GenQueriesEXT(1, &query);
Expand All @@ -40,58 +33,53 @@ void GPUTracerGLES::MarkFrameStart(const ProcTableGLES& gl) {

has_started_frame_ = true;

// At the beginning of a frame, check the status of all pending
// previous queries.
if (!pending_traces_.empty()) {
std::vector<uint32_t> pending_traces = pending_traces_;
pending_traces_.clear();

bool done = false;
for (auto query : pending_traces) {
if (done) {
pending_traces_.push_back(query);
continue;
}
// First check if the query is complete without blocking
// on the result. Incomplete results are left in the pending
// trace vector and will not be checked again for another
// frame.
GLuint available = GL_FALSE;
gl.GetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &available);

if (available == GL_TRUE) {
// Return the timer resolution in nanoseconds.
uint64_t duration = 0;
gl.GetQueryObjectui64vEXT(query, GL_QUERY_RESULT_EXT, &duration);
auto gpu_ms = duration / 1000000.0;
FML_LOG(ERROR) << "gpu_ms: " << gpu_ms;
gl.DeleteQueriesEXT(1, &query);
// Only ever check for one query a frame...
done = true;
} else {
done = true;
pending_traces_.push_back(query);
}
}
}

// Allocate a single query object for the start and end of the frame.
FML_CHECK(!active_frame_.has_value());
FML_CHECK(query != 0);
FML_DCHECK(!active_frame_.has_value());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This duplicates the active_frame_.has_value() check above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

FML_DCHECK(query != 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is redundant with the query == 0 check above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

active_frame_ = query;
gl.BeginQueryEXT(GL_TIME_ELAPSED_EXT, query);
}

void GPUTracerGLES::MarkFrameEnd(const ProcTableGLES& gl) {
if (!enabled_ || !active_frame_.has_value() || !has_started_frame_){
void GPUTracerGLES::RecordRasterThread() {
raster_thread_ = std::this_thread::get_id();
}

void GPUTracerGLES::ProcessQueries(const ProcTableGLES& gl) {
if (pending_traces_.empty()) {
return;
}

std::stringstream ss;
ss << std::this_thread::get_id();
uint64_t id = std::stoull(ss.str());
// For reasons unknown to me, querying the state of more than
// on query object per frame causes crashes on a Pixel 6 pro.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: "on" -> "one"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

auto latest_query = pending_traces_.front();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think latest_query implies that this is the most recent query, when it's actually the least recent.

I'd rename this to query

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


// First check if the query is complete without blocking
// on the result. Incomplete results are left in the pending
// trace vector and will not be checked again for another
// frame.
GLuint available = GL_FALSE;
gl.GetQueryObjectuivEXT(latest_query, GL_QUERY_RESULT_AVAILABLE_EXT,
&available);

if (available == GL_TRUE) {
// Return the timer resolution in nanoseconds.
uint64_t duration = 0;
gl.GetQueryObjectui64vEXT(latest_query, GL_QUERY_RESULT_EXT, &duration);
auto gpu_ms = duration / 1000000.0;

FML_TRACE_COUNTER("flutter", "GPUTracer",
reinterpret_cast<int64_t>(this), // Trace Counter ID
"FrameTimeMS", gpu_ms);

gl.DeleteQueriesEXT(1, &latest_query);
pending_traces_.pop_front();
}
}

FML_LOG(ERROR) << "End: " << id;
void GPUTracerGLES::MarkFrameEnd(const ProcTableGLES& gl) {
if (!enabled_ || std::this_thread::get_id() != raster_thread_ ||
!active_frame_.has_value() || !has_started_frame_) {
return;
}

auto query = active_frame_.value();
gl.EndQueryEXT(GL_TIME_ELAPSED_EXT);
Expand Down
14 changes: 10 additions & 4 deletions impeller/renderer/backend/gles/gpu_tracer_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

#pragma once

#include <deque>
#include <thread>

#include "impeller/renderer/backend/gles/proc_table_gles.h"

namespace impeller {
Expand All @@ -15,16 +17,20 @@ class GPUTracerGLES {

~GPUTracerGLES() = default;

bool HasStartedFrame() const {
return has_started_frame_;
}
/// @brief Record the thread id of the raster thread.
void RecordRasterThread();

/// @brief Record the start of a frame workload, if one hasn't already been
/// started.
void MarkFrameStart(const ProcTableGLES& gl);

/// @brief Record the end of a frame workload.
void MarkFrameEnd(const ProcTableGLES& gl);

private:
std::vector<uint32_t> pending_traces_;
void ProcessQueries(const ProcTableGLES& gl);

std::deque<uint32_t> pending_traces_;
std::optional<uint32_t> active_frame_ = std::nullopt;
std::thread::id raster_thread_;
bool has_started_frame_ = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has_started_frame_ can be removed. The code can instead check whether active_frame_ contains a value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Expand Down
5 changes: 1 addition & 4 deletions impeller/renderer/backend/gles/proc_table_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,10 @@ struct GLProc {
PROC(RenderbufferStorageMultisampleEXT); \
PROC(GenQueriesEXT); \
PROC(DeleteQueriesEXT); \
PROC(IsQueryEXT); \
PROC(QueryCounterEXT); \
PROC(GetQueryObjectui64vEXT); \
PROC(BeginQueryEXT); \
PROC(EndQueryEXT); \
PROC(GetQueryObjectuivEXT); \
PROC(GetQueryObjectivEXT);
PROC(GetQueryObjectuivEXT);

enum class DebugResourceType {
kTexture,
Expand Down
8 changes: 5 additions & 3 deletions impeller/renderer/backend/gles/render_pass_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ struct RenderPassData {
}

const auto& gl = reactor.GetProcTable();
if (!tracer->HasStartedFrame()) {
tracer->MarkFrameStart(gl);
}
#ifdef IMPELLER_DEBUG
tracer->MarkFrameStart(gl);
#endif // IMPELLER_DEBUG

fml::ScopedCleanupClosure pop_pass_debug_marker(
[&gl]() { gl.PopDebugGroup(); });
Expand Down Expand Up @@ -498,9 +498,11 @@ struct RenderPassData {
attachments.data() // size
);
}
#ifdef IMPELLER_DEBUG
if (is_default_fbo) {
tracer->MarkFrameEnd(gl);
}
#endif // IMPELLER_DEBUG

return true;
}
Expand Down
4 changes: 4 additions & 0 deletions impeller/renderer/backend/gles/surface_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ std::unique_ptr<Surface> SurfaceGLES::WrapFBO(
render_target_desc.SetColorAttachment(color0, 0u);
render_target_desc.SetStencilAttachment(stencil0);

#ifdef IMPELLER_DEBUG
gl_context.GetGPUTracer()->RecordRasterThread();
#endif // IMPELLER_DEBUG

return std::unique_ptr<SurfaceGLES>(
new SurfaceGLES(std::move(swap_callback), render_target_desc));
}
Expand Down