Project import generated by Copybara.

GitOrigin-RevId: 612e50bb8db2ec3dc1c30049372d87a80c3848db
This commit is contained in:
MediaPipe Team
2020-08-30 19:52:55 -04:00
committed by chuoling
parent a7225b938a
commit c0124fb83c
248 changed files with 5225 additions and 1914 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ load("//mediapipe/gpu:metal.bzl", "metal_library")
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test")
load("//mediapipe/framework/port:build_config.bzl", "mediapipe_cc_proto_library")
licenses(["notice"]) # Apache 2.0
licenses(["notice"])
package(default_visibility = ["//visibility:public"])
+34 -41
View File
@@ -343,6 +343,7 @@ GlContext::~GlContext() {
#error This file must be built with ARC.
#endif
#endif // __OBJC__
if (thread_) {
auto status = thread_->Run([this] {
if (profiling_helper_) {
@@ -350,9 +351,8 @@ GlContext::~GlContext() {
}
return ExitContext(nullptr);
});
if (!status.ok()) {
LOG(ERROR) << "Failed to deactivate context on thread: " << status;
}
LOG_IF(ERROR, !status.ok())
<< "Failed to deactivate context on thread: " << status;
if (thread_->IsCurrentThread()) {
thread_.release()->SelfDestruct();
}
@@ -368,40 +368,38 @@ void GlContext::SetProfilingContext(
}
}
::mediapipe::Status GlContext::SwitchContextAndRun(GlStatusFunction gl_func) {
ContextBinding saved_context;
MP_RETURN_IF_ERROR(EnterContext(&saved_context)) << " (entering GL context)";
auto status = gl_func();
LogUncheckedGlErrors(CheckForGlErrors());
MP_RETURN_IF_ERROR(ExitContext(&saved_context)) << " (exiting GL context)";
return status;
}
::mediapipe::Status GlContext::Run(GlStatusFunction gl_func, int node_id,
Timestamp input_timestamp) {
::mediapipe::Status status;
if (thread_) {
bool had_gl_errors = false;
status = thread_->Run(
[this, gl_func, node_id, &input_timestamp, &had_gl_errors] {
if (profiling_helper_) {
profiling_helper_->MarkTimestamp(node_id, input_timestamp,
/*is_finish=*/false);
}
auto status = gl_func();
if (profiling_helper_) {
profiling_helper_->MarkTimestamp(node_id, input_timestamp,
/*is_finish=*/true);
}
had_gl_errors = CheckForGlErrors();
return status;
});
LogUncheckedGlErrors(had_gl_errors);
} else {
ContextBinding saved_context;
MP_RETURN_IF_ERROR(EnterContext(&saved_context));
if (profiling_helper_) {
if (profiling_helper_) {
gl_func = [=] {
profiling_helper_->MarkTimestamp(node_id, input_timestamp,
/*is_finish=*/false);
}
status = gl_func();
if (profiling_helper_) {
auto status = gl_func();
profiling_helper_->MarkTimestamp(node_id, input_timestamp,
/*is_finish=*/true);
}
LogUncheckedGlErrors(CheckForGlErrors());
MP_RETURN_IF_ERROR(ExitContext(&saved_context));
return status;
};
}
if (thread_) {
bool had_gl_errors = false;
status = thread_->Run([this, gl_func, &had_gl_errors] {
auto status = gl_func();
had_gl_errors = CheckForGlErrors();
return status;
});
LogUncheckedGlErrors(had_gl_errors);
} else {
status = SwitchContextAndRun(gl_func);
}
return status;
}
@@ -416,17 +414,12 @@ void GlContext::RunWithoutWaiting(GlVoidFunction gl_func) {
});
} else {
// TODO: queue up task instead.
ContextBinding saved_context;
auto status = EnterContext(&saved_context);
auto status = SwitchContextAndRun([gl_func] {
gl_func();
return ::mediapipe::OkStatus();
});
if (!status.ok()) {
LOG(ERROR) << "Failed to enter context: " << status;
return;
}
gl_func();
LogUncheckedGlErrors(CheckForGlErrors());
status = ExitContext(&saved_context);
if (!status.ok()) {
LOG(ERROR) << "Failed to exit context: " << status;
LOG(ERROR) << "Error in RunWithoutWaiting: " << status;
}
}
}
@@ -589,7 +582,7 @@ class GlFenceSyncPoint : public GlSyncPoint {
void GlMultiSyncPoint::Add(std::shared_ptr<GlSyncPoint> new_sync) {
for (auto& sync : syncs_) {
if (&sync->GetContext() == &new_sync->GetContext()) {
if (sync->GetContext() == new_sync->GetContext()) {
sync = std::move(new_sync);
return;
}
+6 -1
View File
@@ -91,7 +91,7 @@ class GlSyncPoint {
// Returns whether the sync point has been reached. Does not block.
virtual bool IsReady() = 0;
const GlContext& GetContext() { return *gl_context_; }
const std::shared_ptr<GlContext>& GetContext() { return gl_context_; }
protected:
std::shared_ptr<GlContext> gl_context_;
@@ -366,6 +366,11 @@ class GlContext : public std::enable_shared_from_this<GlContext> {
::mediapipe::Status GetGlExtensions();
::mediapipe::Status GetGlExtensionsCompat();
// Make the context current, run gl_func, and restore the previous context.
// Internal helper only; callers should use Run or RunWithoutWaiting instead,
// which delegates to the dedicated thread if required.
::mediapipe::Status SwitchContextAndRun(GlStatusFunction gl_func);
// The following ContextBinding functions have platform-specific
// implementations.
+12
View File
@@ -191,6 +191,18 @@ void GlContext::DestroyContext() {
.IgnoreError();
}
#ifdef __ANDROID__
if (HasContext()) {
// Detach the current program to work around b/166322604.
if (eglMakeCurrent(display_, surface_, surface_, context_)) {
glUseProgram(0);
} else {
LOG(ERROR) << "eglMakeCurrent() returned error " << std::showbase
<< std::hex << eglGetError();
}
}
#endif // __ANDROID__
// Destroy the context and surface.
if (IsCurrent()) {
if (!eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
+6 -6
View File
@@ -72,23 +72,23 @@ GlContext::StatusOrGlContext GlContext::Create(
// multithreading options, like the special-case combination of USE_PTHREADS
// and OFFSCREEN_FRAMEBUFFER)
EM_ASM(let init_once = true; if (init_once) {
const __cachedFindCanvasEventTarget = __findCanvasEventTarget;
const cachedFindCanvasEventTarget = findCanvasEventTarget;
if (typeof __cachedFindCanvasEventTarget != = 'function') {
if (typeof cachedFindCanvasEventTarget != = 'function') {
if (typeof console != = 'undefined') {
console.error(
'Expected Emscripten global function ' +
'"__findCanvasEventTarget" not found. WebGL context creation ' +
'"findCanvasEventTarget" not found. WebGL context creation ' +
'may fail.');
}
return;
}
__findCanvasEventTarget = function(target) {
findCanvasEventTarget = function(target) {
if (Module && Module.canvas) {
return Module.canvas;
} else if (Module && Module.canvasCssSelector) {
return __cachedFindCanvasEventTarget(Module.canvasCssSelector);
return cachedFindCanvasEventTarget(Module.canvasCssSelector);
} else {
if (typeof console != = 'undefined') {
console.warn('Module properties canvas and canvasCssSelector not ' +
@@ -97,7 +97,7 @@ GlContext::StatusOrGlContext GlContext::Create(
// We still go through with the find attempt, although for most use
// cases it will not succeed, just in case the user does want to fall-
// back.
return __cachedFindCanvasEventTarget(target);
return cachedFindCanvasEventTarget(target);
}
}; // NOLINT: Necessary semicolon.
init_once = false;
+14 -2
View File
@@ -23,6 +23,13 @@ std::unique_ptr<GlTextureBuffer> GlTextureBuffer::Wrap(
deletion_callback);
}
std::unique_ptr<GlTextureBuffer> GlTextureBuffer::Wrap(
GLenum target, GLuint name, int width, int height, GpuBufferFormat format,
std::shared_ptr<GlContext> context, DeletionCallback deletion_callback) {
return absl::make_unique<GlTextureBuffer>(target, name, width, height, format,
deletion_callback, context);
}
std::unique_ptr<GlTextureBuffer> GlTextureBuffer::Create(int width, int height,
GpuBufferFormat format,
const void* data) {
@@ -36,18 +43,22 @@ std::unique_ptr<GlTextureBuffer> GlTextureBuffer::Create(int width, int height,
GlTextureBuffer::GlTextureBuffer(GLenum target, GLuint name, int width,
int height, GpuBufferFormat format,
DeletionCallback deletion_callback)
DeletionCallback deletion_callback,
std::shared_ptr<GlContext> producer_context)
: name_(name),
width_(width),
height_(height),
format_(format),
target_(target),
deletion_callback_(deletion_callback) {}
deletion_callback_(deletion_callback),
producer_context_(producer_context) {}
bool GlTextureBuffer::CreateInternal(const void* data) {
auto context = GlContext::GetCurrent();
if (!context) return false;
producer_context_ = context; // Save creation GL context.
glGenTextures(1, &name_);
if (!name_) return false;
@@ -106,6 +117,7 @@ void GlTextureBuffer::Updated(std::shared_ptr<GlSyncPoint> prod_token) {
CHECK(!producer_sync_)
<< "Updated existing texture which had not been marked for reuse!";
producer_sync_ = std::move(prod_token);
producer_context_ = producer_sync_->GetContext();
}
void GlTextureBuffer::DidRead(std::shared_ptr<GlSyncPoint> cons_token) {
+13 -1
View File
@@ -50,6 +50,11 @@ class GlTextureBuffer {
GLenum target, GLuint name, int width, int height, GpuBufferFormat format,
DeletionCallback deletion_callback);
// Same as Wrap above, but saves the given context for future use.
static std::unique_ptr<GlTextureBuffer> Wrap(
GLenum target, GLuint name, int width, int height, GpuBufferFormat format,
std::shared_ptr<GlContext> context, DeletionCallback deletion_callback);
// Creates a texture of dimensions width x height and allocates space for it.
// If data is provided, it is uploaded to the texture; otherwise, it can be
// provided later via glTexSubImage2D.
@@ -63,7 +68,8 @@ class GlTextureBuffer {
// The commands producing the texture are assumed to be completed at the
// time of this call. If not, call Updated on the result.
GlTextureBuffer(GLenum target, GLuint name, int width, int height,
GpuBufferFormat format, DeletionCallback deletion_callback);
GpuBufferFormat format, DeletionCallback deletion_callback,
std::shared_ptr<GlContext> producer_context = nullptr);
~GlTextureBuffer();
// Included to support nativeGetGpuBuffer* in Java.
@@ -111,6 +117,11 @@ class GlTextureBuffer {
void WaitForConsumers();
void WaitForConsumersOnGpu();
// Returns the GL context this buffer was created with.
const std::shared_ptr<GlContext>& GetProducerContext() {
return producer_context_;
}
private:
// Creates a texture of dimensions width x height and allocates space for it.
// If data is provided, it is uploaded to the texture; otherwise, it can be
@@ -132,6 +143,7 @@ class GlTextureBuffer {
std::unique_ptr<GlMultiSyncPoint> consumer_multi_sync_ ABSL_GUARDED_BY(
consumer_sync_mutex_) = absl::make_unique<GlMultiSyncPoint>();
DeletionCallback deletion_callback_;
std::shared_ptr<GlContext> producer_context_;
};
using GlTextureBufferSharedPtr = std::shared_ptr<GlTextureBuffer>;
+37 -28
View File
@@ -206,10 +206,11 @@ void GpuBufferMultiPool::EntryList::InsertAfter(Entry* entry, Entry* after) {
Prepend(entry);
}
void GpuBufferMultiPool::Evict() {
void GpuBufferMultiPool::Evict(std::vector<SimplePool>* evicted) {
// Remove excess entries.
while (entry_list_.size() > kMaxPoolCount) {
Entry* victim = entry_list_.tail();
evicted->emplace_back(std::move(victim->pool));
entry_list_.Remove(victim);
pools_.erase(victim->spec);
}
@@ -230,6 +231,7 @@ void GpuBufferMultiPool::Evict() {
entry->request_count /= 2;
Entry* next = entry->next;
if (entry->request_count == 0) {
evicted->emplace_back(std::move(entry->pool));
entry_list_.Remove(entry);
pools_.erase(entry->spec);
}
@@ -240,36 +242,43 @@ void GpuBufferMultiPool::Evict() {
GpuBufferMultiPool::SimplePool GpuBufferMultiPool::RequestPool(
const BufferSpec& key) {
absl::MutexLock lock(&mutex_);
auto pool_it = pools_.find(key);
Entry* entry;
if (pool_it == pools_.end()) {
std::tie(pool_it, std::ignore) =
pools_.emplace(std::piecewise_construct, std::forward_as_tuple(key),
std::forward_as_tuple(key));
entry = &pool_it->second;
CHECK_EQ(entry->request_count, 0);
entry->request_count = 1;
entry_list_.Append(entry);
if (entry->prev != nullptr) CHECK_GE(entry->prev->request_count, 1);
} else {
entry = &pool_it->second;
++entry->request_count;
Entry* larger = entry->prev;
while (larger != nullptr && larger->request_count < entry->request_count) {
larger = larger->prev;
SimplePool pool;
std::vector<SimplePool> evicted;
{
absl::MutexLock lock(&mutex_);
auto pool_it = pools_.find(key);
Entry* entry;
if (pool_it == pools_.end()) {
std::tie(pool_it, std::ignore) =
pools_.emplace(std::piecewise_construct, std::forward_as_tuple(key),
std::forward_as_tuple(key));
entry = &pool_it->second;
CHECK_EQ(entry->request_count, 0);
entry->request_count = 1;
entry_list_.Append(entry);
if (entry->prev != nullptr) CHECK_GE(entry->prev->request_count, 1);
} else {
entry = &pool_it->second;
++entry->request_count;
Entry* larger = entry->prev;
while (larger != nullptr &&
larger->request_count < entry->request_count) {
larger = larger->prev;
}
if (larger != entry->prev) {
entry_list_.Remove(entry);
entry_list_.InsertAfter(entry, larger);
}
}
if (larger != entry->prev) {
entry_list_.Remove(entry);
entry_list_.InsertAfter(entry, larger);
if (!entry->pool && entry->request_count >= kMinRequestsBeforePool) {
entry->pool = MakeSimplePool(key);
}
pool = entry->pool;
++total_request_count_;
Evict(&evicted);
}
if (!entry->pool && entry->request_count >= kMinRequestsBeforePool) {
entry->pool = MakeSimplePool(key);
}
SimplePool pool = entry->pool;
++total_request_count_;
Evict();
// Evicted pools, and their buffers, will be released without holding the
// lock.
return pool;
}
+2 -1
View File
@@ -160,7 +160,8 @@ class GpuBufferMultiPool {
SimplePool RequestPool(const BufferSpec& key);
GpuBuffer GetBufferFromSimplePool(BufferSpec spec, const SimplePool& pool);
GpuBuffer GetBufferWithoutPool(const BufferSpec& spec);
void Evict() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void Evict(std::vector<SimplePool>* evicted)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
absl::Mutex mutex_;
std::unordered_map<BufferSpec, Entry, BufferSpecHash> pools_