diff --git a/mediapipe/gpu/BUILD b/mediapipe/gpu/BUILD index 9c2f47469..93527b565 100644 --- a/mediapipe/gpu/BUILD +++ b/mediapipe/gpu/BUILD @@ -344,6 +344,18 @@ cc_library( ], ) +cc_library( + name = "cv_texture_cache_manager", + srcs = ["cv_texture_cache_manager.cc"], + hdrs = ["cv_texture_cache_manager.h"], + deps = [ + ":pixel_buffer_pool_util", + "//mediapipe/framework/port:logging", + "//mediapipe/objc:CFHolder", + "@com_google_absl//absl/synchronization", + ], +) + cc_library( name = "gpu_buffer_storage_image_frame", hdrs = ["gpu_buffer_storage_image_frame.h"], @@ -440,6 +452,7 @@ objc_library( ":gpu_buffer_multi_pool", ":gpu_shared_data_header", ":graph_support", + ":cv_texture_cache_manager", "//mediapipe/gpu:gl_context_options_cc_proto", "//mediapipe/framework:calculator_context", "//mediapipe/framework/port:ret_check", @@ -555,6 +568,7 @@ cc_library( "//conditions:default": [], "//mediapipe:apple": [ ":MPPGraphGPUData", + ":cv_texture_cache_manager", ], }), ) @@ -617,11 +631,13 @@ cc_library( ":gl_texture_buffer_pool", ], "//mediapipe:ios": [ + ":cv_texture_cache_manager", ":pixel_buffer_pool_util", "//mediapipe/objc:CFHolder", "//mediapipe/objc:util", ], "//mediapipe:macos": [ + ":cv_texture_cache_manager", ":pixel_buffer_pool_util", ":gl_texture_buffer", ":gl_texture_buffer_pool", diff --git a/mediapipe/gpu/cv_texture_cache_manager.cc b/mediapipe/gpu/cv_texture_cache_manager.cc new file mode 100644 index 000000000..b977a8993 --- /dev/null +++ b/mediapipe/gpu/cv_texture_cache_manager.cc @@ -0,0 +1,55 @@ +// 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. + +#include "mediapipe/gpu/cv_texture_cache_manager.h" + +#include "mediapipe/framework/port/logging.h" + +namespace mediapipe { + +void CvTextureCacheManager::FlushTextureCaches() { + absl::MutexLock lock(&mutex_); + for (const auto& cache : texture_caches_) { +#if TARGET_OS_OSX + CVOpenGLTextureCacheFlush(*cache, 0); +#else + CVOpenGLESTextureCacheFlush(*cache, 0); +#endif // TARGET_OS_OSX + } +} + +void CvTextureCacheManager::RegisterTextureCache(CVTextureCacheType cache) { + absl::MutexLock lock(&mutex_); + + CHECK(std::find(texture_caches_.begin(), texture_caches_.end(), cache) == + texture_caches_.end()) + << "Attempting to register a texture cache twice"; + texture_caches_.emplace_back(cache); +} + +void CvTextureCacheManager::UnregisterTextureCache(CVTextureCacheType cache) { + absl::MutexLock lock(&mutex_); + + auto it = std::find(texture_caches_.begin(), texture_caches_.end(), cache); + CHECK(it != texture_caches_.end()) + << "Attempting to unregister an unknown texture cache"; + texture_caches_.erase(it); +} + +CvTextureCacheManager::~CvTextureCacheManager() { + CHECK_EQ(texture_caches_.size(), 0) + << "Failed to unregister texture caches before deleting manager"; +} + +} // namespace mediapipe diff --git a/mediapipe/gpu/cv_texture_cache_manager.h b/mediapipe/gpu/cv_texture_cache_manager.h new file mode 100644 index 000000000..17e44fc6e --- /dev/null +++ b/mediapipe/gpu/cv_texture_cache_manager.h @@ -0,0 +1,49 @@ +// 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. + +#ifndef MEDIAPIPE_GPU_CV_TEXTURE_CACHE_MANAGER_H_ +#define MEDIAPIPE_GPU_CV_TEXTURE_CACHE_MANAGER_H_ + +#include + +#include "absl/synchronization/mutex.h" +#include "mediapipe/gpu/pixel_buffer_pool_util.h" +#include "mediapipe/objc/CFHolder.h" + +namespace mediapipe { + +class CvTextureCacheManager { + public: + ~CvTextureCacheManager(); + + // TODO: add tests for the texture cache registration. + + // Inform the pool of a cache that should be flushed when it is low on + // reusable buffers. + void RegisterTextureCache(CVTextureCacheType cache); + + // Remove a texture cache from the list of caches to be flushed. + void UnregisterTextureCache(CVTextureCacheType cache); + + void FlushTextureCaches(); + + private: + absl::Mutex mutex_; + std::vector> texture_caches_ + ABSL_GUARDED_BY(mutex_); +}; + +} // namespace mediapipe + +#endif // MEDIAPIPE_GPU_CV_TEXTURE_CACHE_MANAGER_H_ diff --git a/mediapipe/gpu/gpu_buffer_multi_pool.cc b/mediapipe/gpu/gpu_buffer_multi_pool.cc index 2bceb1c05..f76833f24 100644 --- a/mediapipe/gpu/gpu_buffer_multi_pool.cc +++ b/mediapipe/gpu/gpu_buffer_multi_pool.cc @@ -106,20 +106,9 @@ GpuBuffer GpuBufferMultiPool::GetBufferWithoutPool(const BufferSpec& spec) { return GpuBuffer(MakeCFHolderAdopting(buffer)); } -void GpuBufferMultiPool::FlushTextureCaches() { - absl::MutexLock lock(&mutex_); - for (const auto& cache : texture_caches_) { -#if TARGET_OS_OSX - CVOpenGLTextureCacheFlush(*cache, 0); -#else - CVOpenGLESTextureCacheFlush(*cache, 0); -#endif // TARGET_OS_OSX - } -} - GpuBuffer GpuBufferMultiPool::GetBufferFromSimplePool( BufferSpec spec, GpuBufferMultiPool::SimplePool& pool) { - return pool.GetBuffer([this]() { FlushTextureCaches(); }); + return pool.GetBuffer(flush_platform_caches_); } #else @@ -173,31 +162,4 @@ GpuBuffer GpuBufferMultiPool::GetBuffer(int width, int height, } } -GpuBufferMultiPool::~GpuBufferMultiPool() { -#ifdef __APPLE__ - CHECK_EQ(texture_caches_.size(), 0) - << "Failed to unregister texture caches before deleting pool"; -#endif // defined(__APPLE__) -} - -#ifdef __APPLE__ -void GpuBufferMultiPool::RegisterTextureCache(CVTextureCacheType cache) { - absl::MutexLock lock(&mutex_); - - CHECK(std::find(texture_caches_.begin(), texture_caches_.end(), cache) == - texture_caches_.end()) - << "Attempting to register a texture cache twice"; - texture_caches_.emplace_back(cache); -} - -void GpuBufferMultiPool::UnregisterTextureCache(CVTextureCacheType cache) { - absl::MutexLock lock(&mutex_); - - auto it = std::find(texture_caches_.begin(), texture_caches_.end(), cache); - CHECK(it != texture_caches_.end()) - << "Attempting to unregister an unknown texture cache"; - texture_caches_.erase(it); -} -#endif // defined(__APPLE__) - } // namespace mediapipe diff --git a/mediapipe/gpu/gpu_buffer_multi_pool.h b/mediapipe/gpu/gpu_buffer_multi_pool.h index 287b3b2a7..7317ac60e 100644 --- a/mediapipe/gpu/gpu_buffer_multi_pool.h +++ b/mediapipe/gpu/gpu_buffer_multi_pool.h @@ -43,25 +43,14 @@ class CvPixelBufferPoolWrapper; class GpuBufferMultiPool { public: GpuBufferMultiPool() {} - explicit GpuBufferMultiPool(void* ignored) {} - ~GpuBufferMultiPool(); // Obtains a buffer. May either be reused or created anew. GpuBuffer GetBuffer(int width, int height, GpuBufferFormat format = GpuBufferFormat::kBGRA32); -#ifdef __APPLE__ - // TODO: add tests for the texture cache registration. - - // Inform the pool of a cache that should be flushed when it is low on - // reusable buffers. - void RegisterTextureCache(CVTextureCacheType cache); - - // Remove a texture cache from the list of caches to be flushed. - void UnregisterTextureCache(CVTextureCacheType cache); - - void FlushTextureCaches(); -#endif // defined(__APPLE__) + void SetFlushPlatformCaches(std::function flush_platform_caches) { + flush_platform_caches_ = flush_platform_caches; + } // This class is not intended as part of the public api of this class. It is // public only because it is used as a map key type, and the map @@ -98,15 +87,10 @@ class GpuBufferMultiPool { GpuBuffer GetBufferWithoutPool(const BufferSpec& spec); absl::Mutex mutex_; - mediapipe::ResourceCache, - absl::Hash> - cache_ ABSL_GUARDED_BY(mutex_); - -#ifdef __APPLE__ - // Texture caches used with this pool. - std::vector> texture_caches_ + mediapipe::ResourceCache> cache_ ABSL_GUARDED_BY(mutex_); -#endif // defined(__APPLE__) + // This is used to hook up the TextureCacheManager on Apple platforms. + std::function flush_platform_caches_; }; #if MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER diff --git a/mediapipe/gpu/gpu_shared_data_internal.cc b/mediapipe/gpu/gpu_shared_data_internal.cc index a8bf0c3a3..457b04fd3 100644 --- a/mediapipe/gpu/gpu_shared_data_internal.cc +++ b/mediapipe/gpu/gpu_shared_data_internal.cc @@ -85,7 +85,12 @@ GpuResources::GpuResources(std::shared_ptr gl_context) { named_executors_[kGpuExecutorName] = std::make_shared(gl_context.get()); #if __APPLE__ - gpu_buffer_pool().RegisterTextureCache(gl_context->cv_texture_cache()); + texture_caches_ = std::make_shared(); + gpu_buffer_pool().SetFlushPlatformCaches( + [tc = texture_caches_] { tc->FlushTextureCaches(); }); +#if MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER + texture_caches_->RegisterTextureCache(gl_context->cv_texture_cache()); +#endif // MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER ios_gpu_data_ = [[MPPGraphGPUData alloc] initWithContext:gl_context.get() multiPool:&gpu_buffer_pool_]; #endif // __APPLE__ @@ -98,10 +103,12 @@ GpuResources::~GpuResources() { #if !__has_feature(objc_arc) #error This file must be built with ARC. #endif +#if MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER for (auto& kv : gl_key_context_) { - gpu_buffer_pool().UnregisterTextureCache(kv.second->cv_texture_cache()); + texture_caches_->UnregisterTextureCache(kv.second->cv_texture_cache()); } -#endif +#endif // MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER +#endif // __APPLE__ } absl::Status GpuResources::PrepareGpuNode(CalculatorNode* node) { @@ -174,9 +181,9 @@ GlContext::StatusOrGlContext GpuResources::GetOrCreateGlContext( GlContext::Create(*gl_key_context_[SharedContextKey()], kGlContextUseDedicatedThread)); it = gl_key_context_.emplace(key, new_context).first; -#if __APPLE__ - gpu_buffer_pool_.RegisterTextureCache(it->second->cv_texture_cache()); -#endif +#if MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER + texture_caches_->RegisterTextureCache(it->second->cv_texture_cache()); +#endif // MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER } return it->second; } diff --git a/mediapipe/gpu/gpu_shared_data_internal.h b/mediapipe/gpu/gpu_shared_data_internal.h index 62d6bb27e..12a7a1296 100644 --- a/mediapipe/gpu/gpu_shared_data_internal.h +++ b/mediapipe/gpu/gpu_shared_data_internal.h @@ -30,6 +30,7 @@ #include "mediapipe/gpu/gpu_buffer_multi_pool.h" #ifdef __APPLE__ +#include "mediapipe/gpu/cv_texture_cache_manager.h" #ifdef __OBJC__ @class MPPGraphGPUData; #else @@ -91,6 +92,8 @@ class GpuResources { GpuBufferMultiPool gpu_buffer_pool_; #ifdef __APPLE__ + std::shared_ptr texture_caches_; + // Note that this is an Objective-C object. MPPGraphGPUData* ios_gpu_data_; #endif // defined(__APPLE__)