Project import generated by Copybara.
GitOrigin-RevId: 0517756260533d374df93679965ca662d0ec6943
This commit is contained in:
committed by
Hadon Nash
parent
38ee2603a7
commit
ae6be10afe
@@ -303,6 +303,7 @@ objc_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//mediapipe/objc:mediapipe_framework_ios",
|
||||
"@com_google_absl//absl/time",
|
||||
"@google_toolbox_for_mac//:GTM_Defines",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -42,6 +42,12 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
blocking:(bool)blocking
|
||||
commandBuffer:(id<MTLCommandBuffer>)commandBuffer;
|
||||
|
||||
/// Commits the command buffer and waits until execution completes. This is
|
||||
/// functionally equivalent to calling commit and waitUntilCompleted on the
|
||||
/// command buffer, but may use different synchronization strategies, such as
|
||||
/// active wait.
|
||||
+ (void)commitCommandBufferAndWait:(id<MTLCommandBuffer>)commandBuffer;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
|
||||
#import "mediapipe/gpu/MPPMetalUtil.h"
|
||||
|
||||
#include "absl/time/clock.h"
|
||||
#include "absl/time/time.h"
|
||||
|
||||
@implementation MPPMetalUtil
|
||||
|
||||
+ (void)blitMetalBufferTo:(id<MTLBuffer>)destination
|
||||
@@ -44,8 +47,41 @@
|
||||
destinationOffset:destinationOffset
|
||||
size:bytes];
|
||||
[blit_command endEncoding];
|
||||
if (blocking) {
|
||||
[MPPMetalUtil commitCommandBufferAndWait:commandBuffer];
|
||||
} else {
|
||||
[commandBuffer commit];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)commitCommandBufferAndWait:(id<MTLCommandBuffer>)commandBuffer {
|
||||
#if !defined(MEDIAPIPE_DISABLE_ACTIVE_WAIT)
|
||||
// The bufferCompleted variable doesn't require atomic access.
|
||||
// std::atomic<> can't be used here because the variable must be captured
|
||||
// with the block. Also std::atomic<> orders changes of the variable but
|
||||
// in this case any kind of out-of-order execution will be serialized.
|
||||
__block volatile bool bufferCompleted = false;
|
||||
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer>) {
|
||||
bufferCompleted = true;
|
||||
}];
|
||||
[commandBuffer commit];
|
||||
if (blocking) [commandBuffer waitUntilCompleted];
|
||||
absl::Time start_time = absl::Now();
|
||||
while (!bufferCompleted) {
|
||||
auto duration = absl::Now() - start_time;
|
||||
// If the spin-lock takes more than 5 ms then go to blocking wait:
|
||||
// - it frees the CPU core for another threads: increase the performance/decrease power
|
||||
// consumption.
|
||||
// - if a driver thread that notifies that the GPU buffer is completed has lower priority then
|
||||
// the CPU core is allocated for the thread.
|
||||
if (duration >= absl::Milliseconds(5)) {
|
||||
[commandBuffer waitUntilCompleted];
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
[commandBuffer commit];
|
||||
[commandBuffer waitUntilCompleted];
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "mediapipe/gpu/gl_context_internal.h"
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
#include <emscripten.h>
|
||||
|
||||
namespace mediapipe {
|
||||
|
||||
@@ -62,8 +63,48 @@ GlContext::StatusOrGlContext GlContext::Create(
|
||||
// pushing resulting texture through MediaPipe pipeline.
|
||||
attrs.preserveDrawingBuffer = 0;
|
||||
|
||||
// We use id of "0" for now to target our webassembly Module.canvas
|
||||
// specifically for all GL contexts.
|
||||
// Since the Emscripten canvas target finding function is visible from here,
|
||||
// we hijack findCanvasEventTarget directly for enforcing old Module.canvas
|
||||
// behavior if the user desires, falling back to the new DOM element CSS
|
||||
// selector behavior next if that is specified, and finally just allowing the
|
||||
// lookup to proceed on a null target.
|
||||
// TODO: Ensure this works with all options (in particular,
|
||||
// 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;
|
||||
|
||||
if (typeof __cachedFindCanvasEventTarget != = 'function') {
|
||||
if (typeof console != = 'undefined') {
|
||||
console.error(
|
||||
'Expected Emscripten global function ' +
|
||||
'"__findCanvasEventTarget" not found. WebGL context creation ' +
|
||||
'may fail.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
__findCanvasEventTarget = function(target) {
|
||||
if (Module && Module.canvas) {
|
||||
return Module.canvas;
|
||||
} else if (Module && Module.canvasCssSelector) {
|
||||
return __cachedFindCanvasEventTarget(Module.canvasCssSelector);
|
||||
} else {
|
||||
if (typeof console != = 'undefined') {
|
||||
console.warn('Module properties canvas and canvasCssSelector not ' +
|
||||
'found during WebGL context creation.');
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
}; // NOLINT: Necessary semicolon.
|
||||
init_once = false;
|
||||
});
|
||||
|
||||
// Note: below id parameter is only actually used if both Module.canvas and
|
||||
// Module.canvasCssSelector are undefined.
|
||||
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context_handle =
|
||||
emscripten_webgl_create_context(0 /* id */, &attrs);
|
||||
|
||||
@@ -73,6 +114,9 @@ GlContext::StatusOrGlContext GlContext::Create(
|
||||
return ::mediapipe::UnknownErrorBuilder(MEDIAPIPE_LOC)
|
||||
<< "emscripten_webgl_create_context() returned error "
|
||||
<< context_handle;
|
||||
} else {
|
||||
emscripten_webgl_get_context_attributes(context_handle, &attrs);
|
||||
webgl_version = attrs.majorVersion;
|
||||
}
|
||||
context_ = context_handle;
|
||||
attrs_ = attrs;
|
||||
|
||||
Reference in New Issue
Block a user