ae6be10afe
GitOrigin-RevId: 0517756260533d374df93679965ca662d0ec6943
88 lines
3.2 KiB
Plaintext
88 lines
3.2 KiB
Plaintext
// Copyright 2019 The MediaPipe Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#import "mediapipe/gpu/MPPMetalUtil.h"
|
|
|
|
#include "absl/time/clock.h"
|
|
#include "absl/time/time.h"
|
|
|
|
@implementation MPPMetalUtil
|
|
|
|
+ (void)blitMetalBufferTo:(id<MTLBuffer>)destination
|
|
from:(id<MTLBuffer>)source
|
|
blocking:(bool)blocking
|
|
commandBuffer:(id<MTLCommandBuffer>)commandBuffer {
|
|
size_t bytes = MIN(destination.length, source.length);
|
|
[self blitMetalBufferTo:destination
|
|
destinationOffset:0
|
|
from:source
|
|
sourceOffset:0
|
|
bytes:bytes
|
|
blocking:blocking
|
|
commandBuffer:commandBuffer];
|
|
}
|
|
|
|
+ (void)blitMetalBufferTo:(id<MTLBuffer>)destination
|
|
destinationOffset:(int)destinationOffset
|
|
from:(id<MTLBuffer>)source
|
|
sourceOffset:(int)sourceOffset
|
|
bytes:(size_t)bytes
|
|
blocking:(bool)blocking
|
|
commandBuffer:(id<MTLCommandBuffer>)commandBuffer {
|
|
id<MTLBlitCommandEncoder> blit_command = [commandBuffer blitCommandEncoder];
|
|
[blit_command copyFromBuffer:source
|
|
sourceOffset:sourceOffset
|
|
toBuffer:destination
|
|
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];
|
|
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
|