mirror of
https://github.com/opencv/opencv.git
synced 2025-06-13 04:52:53 +08:00
Merge pull request #20727 from sivanov-work:merge_vpl_accel_impl
G-API: oneVPL (simplification) added CPU, DX11(fallback CPU) accels & surface pool * Add CPU, DX11(fallback CPU) accels & surface pool * Fix build for surface_pool * Apply some comments * Fix indentation
This commit is contained in:
parent
38b9ec7a18
commit
54386c82fd
@ -171,6 +171,9 @@ set(gapi_srcs
|
|||||||
src/streaming/onevpl/data_provider_interface_exception.cpp
|
src/streaming/onevpl/data_provider_interface_exception.cpp
|
||||||
src/streaming/onevpl/accelerators/surface/cpu_frame_adapter.cpp
|
src/streaming/onevpl/accelerators/surface/cpu_frame_adapter.cpp
|
||||||
src/streaming/onevpl/accelerators/surface/surface.cpp
|
src/streaming/onevpl/accelerators/surface/surface.cpp
|
||||||
|
src/streaming/onevpl/accelerators/surface/surface_pool.cpp
|
||||||
|
src/streaming/onevpl/accelerators/accel_policy_cpu.cpp
|
||||||
|
src/streaming/onevpl/accelerators/accel_policy_dx11.cpp
|
||||||
|
|
||||||
# Utils (ITT tracing)
|
# Utils (ITT tracing)
|
||||||
src/utils/itt.cpp
|
src/utils/itt.cpp
|
||||||
@ -247,6 +250,9 @@ if(HAVE_GAPI_ONEVPL)
|
|||||||
if(TARGET opencv_test_gapi)
|
if(TARGET opencv_test_gapi)
|
||||||
ocv_target_compile_definitions(opencv_test_gapi PRIVATE -DHAVE_ONEVPL)
|
ocv_target_compile_definitions(opencv_test_gapi PRIVATE -DHAVE_ONEVPL)
|
||||||
ocv_target_link_libraries(opencv_test_gapi PRIVATE ${VPL_IMPORTED_TARGETS})
|
ocv_target_link_libraries(opencv_test_gapi PRIVATE ${VPL_IMPORTED_TARGETS})
|
||||||
|
if(HAVE_D3D11 AND HAVE_OPENCL)
|
||||||
|
ocv_target_include_directories(opencv_test_gapi SYSTEM PRIVATE ${OPENCL_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
ocv_target_compile_definitions(${the_module} PRIVATE -DHAVE_ONEVPL)
|
ocv_target_compile_definitions(${the_module} PRIVATE -DHAVE_ONEVPL)
|
||||||
ocv_target_link_libraries(${the_module} PRIVATE ${VPL_IMPORTED_TARGETS})
|
ocv_target_link_libraries(${the_module} PRIVATE ${VPL_IMPORTED_TARGETS})
|
||||||
|
@ -0,0 +1,225 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||||
|
// of this distribution and at http://opencv.org/license.html.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2021 Intel Corporation
|
||||||
|
|
||||||
|
#ifdef HAVE_ONEVPL
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
#include "streaming/onevpl/accelerators/accel_policy_cpu.hpp"
|
||||||
|
#include "streaming/onevpl/accelerators/surface/cpu_frame_adapter.hpp"
|
||||||
|
#include "streaming/onevpl/accelerators/surface/surface.hpp"
|
||||||
|
#include "logger.hpp"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#include <sysinfoapi.h>
|
||||||
|
#endif
|
||||||
|
namespace cv {
|
||||||
|
namespace gapi {
|
||||||
|
namespace wip {
|
||||||
|
|
||||||
|
VPLCPUAccelerationPolicy::VPLCPUAccelerationPolicy() {
|
||||||
|
GAPI_LOG_INFO(nullptr, "created");
|
||||||
|
}
|
||||||
|
|
||||||
|
VPLCPUAccelerationPolicy::~VPLCPUAccelerationPolicy() {
|
||||||
|
for (auto& pair : pool_table) {
|
||||||
|
pair.second.clear();
|
||||||
|
// do not free key here: last surface will release it
|
||||||
|
}
|
||||||
|
GAPI_LOG_INFO(nullptr, "destroyed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void VPLCPUAccelerationPolicy::init(session_t session) {
|
||||||
|
GAPI_LOG_INFO(nullptr, "initialize session: " << session);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VPLCPUAccelerationPolicy::deinit(session_t session) {
|
||||||
|
GAPI_LOG_INFO(nullptr, "deinitialize session: " << session);
|
||||||
|
}
|
||||||
|
|
||||||
|
VPLCPUAccelerationPolicy::pool_key_t
|
||||||
|
VPLCPUAccelerationPolicy::create_surface_pool(size_t pool_size, size_t surface_size_bytes,
|
||||||
|
surface_ptr_ctr_t creator) {
|
||||||
|
GAPI_LOG_DEBUG(nullptr, "pool size: " << pool_size << ", surface size bytes: " << surface_size_bytes);
|
||||||
|
|
||||||
|
// create empty pool
|
||||||
|
pool_t pool;
|
||||||
|
pool.reserve(pool_size);
|
||||||
|
|
||||||
|
// allocate workplace memory area
|
||||||
|
size_t preallocated_raw_bytes = pool_size * surface_size_bytes;
|
||||||
|
size_t page_size_bytes = 4 * 1024;
|
||||||
|
void *preallocated_pool_memory_ptr = nullptr;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
SYSTEM_INFO sysInfo;
|
||||||
|
GetSystemInfo(&sysInfo);
|
||||||
|
page_size_bytes = sysInfo.dwPageSize;
|
||||||
|
|
||||||
|
GAPI_LOG_DEBUG(nullptr, "page size: " << page_size_bytes << ", preallocated_raw_bytes: " << preallocated_raw_bytes);
|
||||||
|
preallocated_pool_memory_ptr = _aligned_malloc(preallocated_raw_bytes, page_size_bytes);
|
||||||
|
#else
|
||||||
|
GAPI_Assert(false && "Compatibility is not tested for systems differ than \"_WIN32\". "
|
||||||
|
"Please feel free to set it up under OPENCV contribution policy");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!preallocated_pool_memory_ptr) {
|
||||||
|
throw std::runtime_error("VPLCPUAccelerationPolicy::create_surface_pool - failed: not enough memory."
|
||||||
|
"Requested surface count: " + std::to_string(pool_size) +
|
||||||
|
", surface bytes: " + std::to_string(surface_size_bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill pool with surfaces
|
||||||
|
std::shared_ptr<void> workspace_mem_owner (preallocated_pool_memory_ptr, [] (void *ptr){
|
||||||
|
GAPI_LOG_INFO(nullptr, "Free workspace memory: " << ptr);
|
||||||
|
#ifdef _WIN32
|
||||||
|
_aligned_free(ptr);
|
||||||
|
GAPI_LOG_INFO(nullptr, "Released workspace memory: " << ptr);
|
||||||
|
ptr = nullptr;
|
||||||
|
#else
|
||||||
|
GAPI_Assert(false && "Not implemented for systems differ than \"_WIN32\". "
|
||||||
|
"Please feel free to set it up under OPENCV contribution policy");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
});
|
||||||
|
size_t i = 0;
|
||||||
|
try {
|
||||||
|
for (; i < pool_size; i++) {
|
||||||
|
size_t preallocated_mem_offset = static_cast<size_t>(i) * surface_size_bytes;
|
||||||
|
|
||||||
|
surface_ptr_t surf_ptr = creator(workspace_mem_owner,
|
||||||
|
preallocated_mem_offset,
|
||||||
|
preallocated_raw_bytes);
|
||||||
|
pool.push_back(std::move(surf_ptr));
|
||||||
|
}
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
throw std::runtime_error(std::string("VPLCPUAccelerationPolicy::create_surface_pool - ") +
|
||||||
|
"cannot construct surface index: " + std::to_string(i) + ", error: " +
|
||||||
|
ex.what() +
|
||||||
|
"Requested surface count: " + std::to_string(pool_size) +
|
||||||
|
", surface bytes: " + std::to_string(surface_size_bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
// remember pool by key
|
||||||
|
GAPI_LOG_INFO(nullptr, "New pool allocated, key: " << preallocated_pool_memory_ptr <<
|
||||||
|
", surface count: " << pool.size() <<
|
||||||
|
", surface size bytes: " << surface_size_bytes);
|
||||||
|
if (!pool_table.emplace(preallocated_pool_memory_ptr, std::move(pool)).second) {
|
||||||
|
GAPI_LOG_WARNING(nullptr, "Cannot insert pool, table size: " + std::to_string(pool_table.size()) <<
|
||||||
|
", key: " << preallocated_pool_memory_ptr << " exists");
|
||||||
|
GAPI_Assert(false && "Cannot create pool in VPLCPUAccelerationPolicy");
|
||||||
|
}
|
||||||
|
|
||||||
|
return preallocated_pool_memory_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
VPLCPUAccelerationPolicy::surface_weak_ptr_t VPLCPUAccelerationPolicy::get_free_surface(pool_key_t key) {
|
||||||
|
auto pool_it = pool_table.find(key);
|
||||||
|
if (pool_it == pool_table.end()) {
|
||||||
|
throw std::runtime_error("VPLCPUAccelerationPolicy::get_free_surface - "
|
||||||
|
"key is not found, table size: " +
|
||||||
|
std::to_string(pool_table.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
pool_t& requested_pool = pool_it->second;
|
||||||
|
#ifdef TEST_PERF
|
||||||
|
return requested_pool.find_free();
|
||||||
|
#else // TEST_PERF
|
||||||
|
auto it =
|
||||||
|
std::find_if(requested_pool.begin(), requested_pool.end(),
|
||||||
|
[](const surface_ptr_t& val) {
|
||||||
|
GAPI_DbgAssert(val && "Pool contains empty surface");
|
||||||
|
return !val->get_locks_count();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Limitation realloc pool might be a future extension
|
||||||
|
if (it == requested_pool.end()) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "cannot get free surface from pool, key: " << key << ", size: " << requested_pool.size();
|
||||||
|
const std::string& str = ss.str();
|
||||||
|
GAPI_LOG_WARNING(nullptr, str);
|
||||||
|
throw std::runtime_error(std::string(__FUNCTION__) + " - " + str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *it;
|
||||||
|
#endif // TEST_PERF
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t VPLCPUAccelerationPolicy::get_free_surface_count(pool_key_t key) const {
|
||||||
|
auto pool_it = pool_table.find(key);
|
||||||
|
if (pool_it == pool_table.end()) {
|
||||||
|
GAPI_LOG_WARNING(nullptr, "key is not found: " << key <<
|
||||||
|
", table size: " << pool_table.size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#ifdef TEST_PERF
|
||||||
|
return 0;
|
||||||
|
#else // TEST_PERF
|
||||||
|
const pool_t& requested_pool = pool_it->second;
|
||||||
|
size_t free_surf_count =
|
||||||
|
std::count_if(requested_pool.begin(), requested_pool.end(),
|
||||||
|
[](const surface_ptr_t& val) {
|
||||||
|
GAPI_Assert(val && "Pool contains empty surface");
|
||||||
|
return !val->get_locks_count();
|
||||||
|
});
|
||||||
|
return free_surf_count;
|
||||||
|
#endif // TEST_PERF
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t VPLCPUAccelerationPolicy::get_surface_count(pool_key_t key) const {
|
||||||
|
auto pool_it = pool_table.find(key);
|
||||||
|
if (pool_it == pool_table.end()) {
|
||||||
|
GAPI_LOG_DEBUG(nullptr, "key is not found: " << key <<
|
||||||
|
", table size: " << pool_table.size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#ifdef TEST_PERF
|
||||||
|
return 0;
|
||||||
|
#else // TEST_PERF
|
||||||
|
return pool_it->second.size();
|
||||||
|
#endif // TEST_PERF
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::MediaFrame::AdapterPtr VPLCPUAccelerationPolicy::create_frame_adapter(pool_key_t key,
|
||||||
|
mfxFrameSurface1* surface) {
|
||||||
|
auto pool_it = pool_table.find(key);
|
||||||
|
if (pool_it == pool_table.end()) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "key is not found: " << key << ", table size: " << pool_table.size();
|
||||||
|
const std::string& str = ss.str();
|
||||||
|
GAPI_LOG_WARNING(nullptr, str);
|
||||||
|
throw std::runtime_error(std::string(__FUNCTION__) + " - " + str);
|
||||||
|
}
|
||||||
|
|
||||||
|
pool_t& requested_pool = pool_it->second;
|
||||||
|
#ifdef TEST_PERF
|
||||||
|
return cv::MediaFrame::AdapterPtr{new VPLMediaFrameCPUAdapter(requested_pool.find_by_handle(surface))};
|
||||||
|
#else // TEST_PERF
|
||||||
|
auto it =
|
||||||
|
std::find_if(requested_pool.begin(), requested_pool.end(),
|
||||||
|
[surface](const surface_ptr_t& val) {
|
||||||
|
GAPI_DbgAssert(val && "Pool contains empty surface");
|
||||||
|
return val->get_handle() == surface;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Limitation realloc pool might be a future extension
|
||||||
|
if (it == requested_pool.end()) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "cannot get requested surface from pool, key: " << key << ", surf: "
|
||||||
|
<< surface << ", pool size: " << requested_pool.size();
|
||||||
|
const std::string& str = ss.str();
|
||||||
|
GAPI_LOG_WARNING(nullptr, str);
|
||||||
|
throw std::runtime_error(std::string(__FUNCTION__) + " - " + str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cv::MediaFrame::AdapterPtr{new VPLMediaFrameCPUAdapter(*it)};
|
||||||
|
#endif // TEST_PERF
|
||||||
|
}
|
||||||
|
} // namespace wip
|
||||||
|
} // namespace gapi
|
||||||
|
} // namespace cv
|
||||||
|
#endif // HAVE_ONEVPL
|
@ -0,0 +1,55 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||||
|
// of this distribution and at http://opencv.org/license.html.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2021 Intel Corporation
|
||||||
|
|
||||||
|
#ifndef GAPI_STREAMING_ONEVPL_ACCELERATORS_ACCEL_POLICY_CPU_HPP
|
||||||
|
#define GAPI_STREAMING_ONEVPL_ACCELERATORS_ACCEL_POLICY_CPU_HPP
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "opencv2/gapi/own/exports.hpp" // GAPI_EXPORTS
|
||||||
|
|
||||||
|
#ifdef HAVE_ONEVPL
|
||||||
|
#include <vpl/mfxvideo.h>
|
||||||
|
#include "streaming/onevpl/accelerators/accel_policy_interface.hpp"
|
||||||
|
#ifdef TEST_PERF
|
||||||
|
#include "streaming/onevpl/accelerators/surface/surface_pool.hpp"
|
||||||
|
#endif // TEST_PERF
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
namespace gapi {
|
||||||
|
namespace wip {
|
||||||
|
|
||||||
|
// GAPI_EXPORTS for tests
|
||||||
|
struct GAPI_EXPORTS VPLCPUAccelerationPolicy final : public VPLAccelerationPolicy
|
||||||
|
{
|
||||||
|
VPLCPUAccelerationPolicy();
|
||||||
|
~VPLCPUAccelerationPolicy();
|
||||||
|
#ifdef TEST_PERF
|
||||||
|
using pool_t = CachedPool;
|
||||||
|
#else // TEST_PERF
|
||||||
|
using pool_t = std::vector<surface_ptr_t>;
|
||||||
|
#endif // TEST_PERF
|
||||||
|
|
||||||
|
void init(session_t session) override;
|
||||||
|
void deinit(session_t session) override;
|
||||||
|
pool_key_t create_surface_pool(size_t pool_size, size_t surface_size_bytes, surface_ptr_ctr_t creator) override;
|
||||||
|
surface_weak_ptr_t get_free_surface(pool_key_t key) override;
|
||||||
|
size_t get_free_surface_count(pool_key_t key) const override;
|
||||||
|
size_t get_surface_count(pool_key_t key) const override;
|
||||||
|
|
||||||
|
cv::MediaFrame::AdapterPtr create_frame_adapter(pool_key_t key,
|
||||||
|
mfxFrameSurface1* surface) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<pool_key_t, pool_t> pool_table;
|
||||||
|
};
|
||||||
|
} // namespace wip
|
||||||
|
} // namespace gapi
|
||||||
|
} // namespace cv
|
||||||
|
|
||||||
|
#endif // HAVE_ONEVPL
|
||||||
|
#endif // GAPI_STREAMING_ONEVPL_ACCELERATORS_ACCEL_POLICY_CPU_HPP
|
@ -0,0 +1,114 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||||
|
// of this distribution and at http://opencv.org/license.html.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2021 Intel Corporation
|
||||||
|
|
||||||
|
#ifdef HAVE_ONEVPL
|
||||||
|
#include "streaming/onevpl/accelerators/accel_policy_dx11.hpp"
|
||||||
|
#include "streaming/onevpl/accelerators/surface/cpu_frame_adapter.hpp"
|
||||||
|
#include "streaming/onevpl/accelerators/surface/surface.hpp"
|
||||||
|
#include "logger.hpp"
|
||||||
|
|
||||||
|
#ifdef HAVE_DIRECTX
|
||||||
|
#ifdef HAVE_D3D11
|
||||||
|
#pragma comment(lib,"d3d11.lib")
|
||||||
|
|
||||||
|
#define D3D11_NO_HELPERS
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <d3d11_4.h>
|
||||||
|
#include <codecvt>
|
||||||
|
#include "opencv2/core/directx.hpp"
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENCL
|
||||||
|
#include <CL/cl_d3d11.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
namespace gapi {
|
||||||
|
namespace wip {
|
||||||
|
VPLDX11AccelerationPolicy::VPLDX11AccelerationPolicy()
|
||||||
|
{
|
||||||
|
#ifdef CPU_ACCEL_ADAPTER
|
||||||
|
adapter.reset(new VPLCPUAccelerationPolicy);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
VPLDX11AccelerationPolicy::~VPLDX11AccelerationPolicy()
|
||||||
|
{
|
||||||
|
if (hw_handle)
|
||||||
|
{
|
||||||
|
GAPI_LOG_INFO(nullptr, "VPLDX11AccelerationPolicy release ID3D11Device");
|
||||||
|
hw_handle->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VPLDX11AccelerationPolicy::init(session_t session) {
|
||||||
|
mfxStatus sts = MFXVideoCORE_GetHandle(session, MFX_HANDLE_D3D11_DEVICE, reinterpret_cast<mfxHDL*>(&hw_handle));
|
||||||
|
if (sts != MFX_ERR_NONE)
|
||||||
|
{
|
||||||
|
throw std::logic_error("Cannot create VPLDX11AccelerationPolicy, MFXVideoCORE_GetHandle error");
|
||||||
|
}
|
||||||
|
|
||||||
|
GAPI_LOG_INFO(nullptr, "VPLDX11AccelerationPolicy initialized, session: " << session);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VPLDX11AccelerationPolicy::deinit(session_t session) {
|
||||||
|
GAPI_LOG_INFO(nullptr, "deinitialize session: " << session);
|
||||||
|
}
|
||||||
|
|
||||||
|
VPLDX11AccelerationPolicy::pool_key_t
|
||||||
|
VPLDX11AccelerationPolicy::create_surface_pool(size_t pool_size, size_t surface_size_bytes,
|
||||||
|
surface_ptr_ctr_t creator) {
|
||||||
|
GAPI_LOG_DEBUG(nullptr, "pool size: " << pool_size << ", surface size bytes: " << surface_size_bytes);
|
||||||
|
|
||||||
|
#ifdef CPU_ACCEL_ADAPTER
|
||||||
|
return adapter->create_surface_pool(pool_size, surface_size_bytes, creator);
|
||||||
|
#endif
|
||||||
|
(void)pool_size;
|
||||||
|
(void)surface_size_bytes;
|
||||||
|
(void)creator;
|
||||||
|
throw std::runtime_error("VPLDX11AccelerationPolicy::create_surface_pool() is not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
VPLDX11AccelerationPolicy::surface_weak_ptr_t VPLDX11AccelerationPolicy::get_free_surface(pool_key_t key)
|
||||||
|
{
|
||||||
|
#ifdef CPU_ACCEL_ADAPTER
|
||||||
|
return adapter->get_free_surface(key);
|
||||||
|
#endif
|
||||||
|
(void)key;
|
||||||
|
throw std::runtime_error("VPLDX11AccelerationPolicy::get_free_surface() is not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t VPLDX11AccelerationPolicy::get_free_surface_count(pool_key_t key) const {
|
||||||
|
#ifdef CPU_ACCEL_ADAPTER
|
||||||
|
return adapter->get_free_surface_count(key);
|
||||||
|
#endif
|
||||||
|
(void)key;
|
||||||
|
throw std::runtime_error("get_free_surface_count() is not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t VPLDX11AccelerationPolicy::get_surface_count(pool_key_t key) const {
|
||||||
|
#ifdef CPU_ACCEL_ADAPTER
|
||||||
|
return adapter->get_surface_count(key);
|
||||||
|
#endif
|
||||||
|
(void)key;
|
||||||
|
throw std::runtime_error("VPLDX11AccelerationPolicy::get_surface_count() is not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::MediaFrame::AdapterPtr VPLDX11AccelerationPolicy::create_frame_adapter(pool_key_t key,
|
||||||
|
mfxFrameSurface1* surface) {
|
||||||
|
|
||||||
|
#ifdef CPU_ACCEL_ADAPTER
|
||||||
|
return adapter->create_frame_adapter(key, surface);
|
||||||
|
#endif
|
||||||
|
(void)key;
|
||||||
|
(void)surface;
|
||||||
|
throw std::runtime_error("VPLDX11AccelerationPolicy::create_frame_adapter() is not implemented");
|
||||||
|
}
|
||||||
|
} // namespace wip
|
||||||
|
} // namespace gapi
|
||||||
|
} // namespace cv
|
||||||
|
#endif // HAVE_D3D11
|
||||||
|
#endif // HAVE_DIRECTX
|
||||||
|
#endif // HAVE_ONEVPL
|
@ -0,0 +1,67 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||||
|
// of this distribution and at http://opencv.org/license.html.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2021 Intel Corporation
|
||||||
|
|
||||||
|
#ifndef GAPI_STREAMING_ONEVPL_ACCELERATORS_ACCEL_POLICY_DX11_HPP
|
||||||
|
#define GAPI_STREAMING_ONEVPL_ACCELERATORS_ACCEL_POLICY_DX11_HPP
|
||||||
|
|
||||||
|
#include "opencv2/gapi/own/exports.hpp" // GAPI_EXPORTS
|
||||||
|
//TODO Remove the next MACRO right after DX11 implementation
|
||||||
|
#define CPU_ACCEL_ADAPTER
|
||||||
|
|
||||||
|
#ifdef HAVE_ONEVPL
|
||||||
|
#include <vpl/mfxvideo.h>
|
||||||
|
#include "streaming/onevpl/accelerators/accel_policy_interface.hpp"
|
||||||
|
|
||||||
|
#ifdef CPU_ACCEL_ADAPTER
|
||||||
|
#include "streaming/onevpl/accelerators/accel_policy_cpu.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_DIRECTX
|
||||||
|
#ifdef HAVE_D3D11
|
||||||
|
#define D3D11_NO_HELPERS
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <codecvt>
|
||||||
|
#include "opencv2/core/directx.hpp"
|
||||||
|
#ifdef HAVE_OPENCL
|
||||||
|
#include <CL/cl_d3d11.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
namespace gapi {
|
||||||
|
namespace wip {
|
||||||
|
|
||||||
|
// GAPI_EXPORTS for tests
|
||||||
|
struct GAPI_EXPORTS VPLDX11AccelerationPolicy final: public VPLAccelerationPolicy
|
||||||
|
{
|
||||||
|
// GAPI_EXPORTS for tests
|
||||||
|
VPLDX11AccelerationPolicy();
|
||||||
|
~VPLDX11AccelerationPolicy();
|
||||||
|
|
||||||
|
void init(session_t session) override;
|
||||||
|
void deinit(session_t session) override;
|
||||||
|
pool_key_t create_surface_pool(size_t pool_size, size_t surface_size_bytes, surface_ptr_ctr_t creator) override;
|
||||||
|
surface_weak_ptr_t get_free_surface(pool_key_t key) override;
|
||||||
|
size_t get_free_surface_count(pool_key_t key) const override;
|
||||||
|
size_t get_surface_count(pool_key_t key) const override;
|
||||||
|
|
||||||
|
cv::MediaFrame::AdapterPtr create_frame_adapter(pool_key_t key,
|
||||||
|
mfxFrameSurface1* surface) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ID3D11Device *hw_handle;
|
||||||
|
|
||||||
|
#ifdef CPU_ACCEL_ADAPTER
|
||||||
|
std::unique_ptr<VPLCPUAccelerationPolicy> adapter;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
} // namespace wip
|
||||||
|
} // namespace gapi
|
||||||
|
} // namespace cv
|
||||||
|
#endif // HAVE_D3D11
|
||||||
|
#endif // HAVE_DIRECTX
|
||||||
|
|
||||||
|
#endif // HAVE_ONEVPL
|
||||||
|
#endif // GAPI_STREAMING_ONEVPL_ACCELERATORS_ACCEL_POLICY_DX11_HPP
|
@ -0,0 +1,69 @@
|
|||||||
|
#include "streaming/onevpl/accelerators/surface/surface_pool.hpp"
|
||||||
|
#include "streaming/onevpl/accelerators/surface/surface.hpp"
|
||||||
|
#include "logger.hpp"
|
||||||
|
|
||||||
|
#ifdef HAVE_ONEVPL
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
namespace gapi {
|
||||||
|
namespace wip {
|
||||||
|
|
||||||
|
void CachedPool::reserve(size_t size) {
|
||||||
|
surfaces.reserve(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CachedPool::size() const {
|
||||||
|
return surfaces.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CachedPool::clear() {
|
||||||
|
surfaces.clear();
|
||||||
|
next_free_it = surfaces.begin();
|
||||||
|
cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CachedPool::push_back(surface_ptr_t &&surf) {
|
||||||
|
cache.insert(std::make_pair(surf->get_handle(), surf));
|
||||||
|
surfaces.push_back(std::move(surf));
|
||||||
|
next_free_it = surfaces.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedPool::surface_ptr_t CachedPool::find_free() {
|
||||||
|
auto it =
|
||||||
|
std::find_if(next_free_it, surfaces.end(),
|
||||||
|
[](const surface_ptr_t& val) {
|
||||||
|
GAPI_DbgAssert(val && "Pool contains empty surface");
|
||||||
|
return !val->get_locks_count();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Limitation realloc pool might be a future extension
|
||||||
|
if (it == surfaces.end()) {
|
||||||
|
it = std::find_if(surfaces.begin(), next_free_it,
|
||||||
|
[](const surface_ptr_t& val) {
|
||||||
|
GAPI_DbgAssert(val && "Pool contains empty surface");
|
||||||
|
return !val->get_locks_count();
|
||||||
|
});
|
||||||
|
if (it == next_free_it) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "cannot get free surface from pool, size: " << surfaces.size();
|
||||||
|
const std::string& str = ss.str();
|
||||||
|
GAPI_LOG_WARNING(nullptr, str);
|
||||||
|
throw std::runtime_error(std::string(__FUNCTION__) + " - " + str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next_free_it = it;
|
||||||
|
++next_free_it;
|
||||||
|
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedPool::surface_ptr_t CachedPool::find_by_handle(mfxFrameSurface1* handle) {
|
||||||
|
auto it = cache.find(handle);
|
||||||
|
GAPI_Assert(it != cache.end() && "Cannot find cached surface from pool. Data corruption is possible");
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
} // namespace wip
|
||||||
|
} // namespace gapi
|
||||||
|
} // namespace cv
|
||||||
|
#endif // HAVE_ONEVPL
|
@ -0,0 +1,45 @@
|
|||||||
|
#ifndef GAPI_STREAMING_ONEVPL_SURFACE_SURFACE_POOL_HPP
|
||||||
|
#define GAPI_STREAMING_ONEVPL_SURFACE_SURFACE_POOL_HPP
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "opencv2/gapi/own/exports.hpp" // GAPI_EXPORTS
|
||||||
|
|
||||||
|
#ifdef HAVE_ONEVPL
|
||||||
|
#if (MFX_VERSION >= 2000)
|
||||||
|
#include <vpl/mfxdispatcher.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <vpl/mfx.h>
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
namespace gapi {
|
||||||
|
namespace wip {
|
||||||
|
|
||||||
|
class Surface;
|
||||||
|
// GAPI_EXPORTS for tests
|
||||||
|
class GAPI_EXPORTS CachedPool {
|
||||||
|
public:
|
||||||
|
using surface_ptr_t = std::shared_ptr<Surface>;
|
||||||
|
using surface_container_t = std::vector<surface_ptr_t>;
|
||||||
|
using free_surface_iterator_t = typename surface_container_t::iterator;
|
||||||
|
using cached_surface_container_t = std::map<mfxFrameSurface1*, surface_ptr_t>;
|
||||||
|
|
||||||
|
void push_back(surface_ptr_t &&surf);
|
||||||
|
void reserve(size_t size);
|
||||||
|
size_t size() const;
|
||||||
|
void clear();
|
||||||
|
surface_ptr_t find_free();
|
||||||
|
surface_ptr_t find_by_handle(mfxFrameSurface1* handle);
|
||||||
|
private:
|
||||||
|
surface_container_t surfaces;
|
||||||
|
free_surface_iterator_t next_free_it;
|
||||||
|
cached_surface_container_t cache;
|
||||||
|
};
|
||||||
|
} // namespace wip
|
||||||
|
} // namespace gapi
|
||||||
|
} // namespace cv
|
||||||
|
#endif // HAVE_ONEVPL
|
||||||
|
#endif // GAPI_STREAMING_ONEVPL_SURFACE_SURFACE_POOL_HPP
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "../common/gapi_tests_common.hpp"
|
#include "../common/gapi_tests_common.hpp"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
|
||||||
#include <opencv2/gapi/cpu/core.hpp>
|
#include <opencv2/gapi/cpu/core.hpp>
|
||||||
@ -30,11 +31,18 @@
|
|||||||
#ifdef HAVE_ONEVPL
|
#ifdef HAVE_ONEVPL
|
||||||
#include "streaming/onevpl/accelerators/surface/surface.hpp"
|
#include "streaming/onevpl/accelerators/surface/surface.hpp"
|
||||||
#include "streaming/onevpl/accelerators/surface/cpu_frame_adapter.hpp"
|
#include "streaming/onevpl/accelerators/surface/cpu_frame_adapter.hpp"
|
||||||
|
#include "streaming/onevpl/accelerators/accel_policy_cpu.hpp"
|
||||||
|
|
||||||
namespace opencv_test
|
namespace opencv_test
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
cv::gapi::wip::surface_ptr_t create_test_surface(std::shared_ptr<void> out_buf_ptr,
|
||||||
|
size_t, size_t) {
|
||||||
|
std::unique_ptr<mfxFrameSurface1> handle(new mfxFrameSurface1{});
|
||||||
|
return cv::gapi::wip::Surface::create_surface(std::move(handle), out_buf_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(OneVPL_Source_Surface, InitSurface)
|
TEST(OneVPL_Source_Surface, InitSurface)
|
||||||
{
|
{
|
||||||
using namespace cv::gapi::wip;
|
using namespace cv::gapi::wip;
|
||||||
@ -160,7 +168,7 @@ TEST(OneVPL_Source_Surface, MemoryLifeTime)
|
|||||||
EXPECT_TRUE(preallocated_memory_ptr.get() == nullptr);
|
EXPECT_TRUE(preallocated_memory_ptr.get() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(OneVPL_Source_CPUFrameAdapter, InitFrameAdapter)
|
TEST(OneVPL_Source_CPU_FrameAdapter, InitFrameAdapter)
|
||||||
{
|
{
|
||||||
using namespace cv::gapi::wip;
|
using namespace cv::gapi::wip;
|
||||||
|
|
||||||
@ -180,6 +188,157 @@ TEST(OneVPL_Source_CPUFrameAdapter, InitFrameAdapter)
|
|||||||
}
|
}
|
||||||
EXPECT_EQ(surf->get_locks_count(), 0);
|
EXPECT_EQ(surf->get_locks_count(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(OneVPL_Source_CPU_Accelerator, InitDestroy)
|
||||||
|
{
|
||||||
|
using cv::gapi::wip::VPLCPUAccelerationPolicy;
|
||||||
|
using cv::gapi::wip::VPLAccelerationPolicy;
|
||||||
|
|
||||||
|
auto acceleration_policy = std::make_shared<VPLCPUAccelerationPolicy>();
|
||||||
|
|
||||||
|
size_t surface_count = 10;
|
||||||
|
size_t surface_size_bytes = 1024;
|
||||||
|
size_t pool_count = 3;
|
||||||
|
std::vector<VPLAccelerationPolicy::pool_key_t> pool_export_keys;
|
||||||
|
pool_export_keys.reserve(pool_count);
|
||||||
|
|
||||||
|
// create several pools
|
||||||
|
for (size_t i = 0; i < pool_count; i++)
|
||||||
|
{
|
||||||
|
VPLAccelerationPolicy::pool_key_t key =
|
||||||
|
acceleration_policy->create_surface_pool(surface_count,
|
||||||
|
surface_size_bytes,
|
||||||
|
create_test_surface);
|
||||||
|
// check consistency
|
||||||
|
EXPECT_EQ(acceleration_policy->get_surface_count(key), surface_count);
|
||||||
|
EXPECT_EQ(acceleration_policy->get_free_surface_count(key), surface_count);
|
||||||
|
|
||||||
|
pool_export_keys.push_back(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(acceleration_policy.reset());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(OneVPL_Source_CPU_Accelerator, PoolProduceConsume)
|
||||||
|
{
|
||||||
|
using cv::gapi::wip::VPLCPUAccelerationPolicy;
|
||||||
|
using cv::gapi::wip::VPLAccelerationPolicy;
|
||||||
|
using cv::gapi::wip::Surface;
|
||||||
|
|
||||||
|
auto acceleration_policy = std::make_shared<VPLCPUAccelerationPolicy>();
|
||||||
|
|
||||||
|
size_t surface_count = 10;
|
||||||
|
size_t surface_size_bytes = 1024;
|
||||||
|
|
||||||
|
VPLAccelerationPolicy::pool_key_t key =
|
||||||
|
acceleration_policy->create_surface_pool(surface_count,
|
||||||
|
surface_size_bytes,
|
||||||
|
create_test_surface);
|
||||||
|
// check consistency
|
||||||
|
EXPECT_EQ(acceleration_policy->get_surface_count(key), surface_count);
|
||||||
|
EXPECT_EQ(acceleration_policy->get_free_surface_count(key), surface_count);
|
||||||
|
|
||||||
|
// consume available surfaces
|
||||||
|
std::vector<std::shared_ptr<Surface>> surfaces;
|
||||||
|
surfaces.reserve(surface_count);
|
||||||
|
for (size_t i = 0; i < surface_count; i++) {
|
||||||
|
std::shared_ptr<Surface> surf = acceleration_policy->get_free_surface(key).lock();
|
||||||
|
EXPECT_TRUE(surf.get() != nullptr);
|
||||||
|
EXPECT_EQ(surf->obtain_lock(), 0);
|
||||||
|
surfaces.push_back(std::move(surf));
|
||||||
|
}
|
||||||
|
|
||||||
|
// check consistency (no free surfaces)
|
||||||
|
EXPECT_EQ(acceleration_policy->get_surface_count(key), surface_count);
|
||||||
|
EXPECT_EQ(acceleration_policy->get_free_surface_count(key), 0);
|
||||||
|
|
||||||
|
// fail consume non-free surfaces
|
||||||
|
for (size_t i = 0; i < surface_count; i++) {
|
||||||
|
EXPECT_THROW(acceleration_policy->get_free_surface(key), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// release surfaces
|
||||||
|
for (auto& surf : surfaces) {
|
||||||
|
EXPECT_EQ(surf->release_lock(), 1);
|
||||||
|
}
|
||||||
|
surfaces.clear();
|
||||||
|
|
||||||
|
// check consistency
|
||||||
|
EXPECT_EQ(acceleration_policy->get_surface_count(key), surface_count);
|
||||||
|
EXPECT_EQ(acceleration_policy->get_free_surface_count(key), surface_count);
|
||||||
|
|
||||||
|
//check availability after release
|
||||||
|
for (size_t i = 0; i < surface_count; i++) {
|
||||||
|
std::shared_ptr<Surface> surf = acceleration_policy->get_free_surface(key).lock();
|
||||||
|
EXPECT_TRUE(surf.get() != nullptr);
|
||||||
|
EXPECT_EQ(surf->obtain_lock(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(OneVPL_Source_CPU_Accelerator, PoolProduceConcurrentConsume)
|
||||||
|
{
|
||||||
|
using cv::gapi::wip::VPLCPUAccelerationPolicy;
|
||||||
|
using cv::gapi::wip::VPLAccelerationPolicy;
|
||||||
|
using cv::gapi::wip::Surface;
|
||||||
|
|
||||||
|
auto acceleration_policy = std::make_shared<VPLCPUAccelerationPolicy>();
|
||||||
|
|
||||||
|
size_t surface_count = 10;
|
||||||
|
size_t surface_size_bytes = 1024;
|
||||||
|
|
||||||
|
VPLAccelerationPolicy::pool_key_t key =
|
||||||
|
acceleration_policy->create_surface_pool(surface_count,
|
||||||
|
surface_size_bytes,
|
||||||
|
create_test_surface);
|
||||||
|
|
||||||
|
// check consistency
|
||||||
|
EXPECT_EQ(acceleration_policy->get_surface_count(key), surface_count);
|
||||||
|
EXPECT_EQ(acceleration_policy->get_free_surface_count(key), surface_count);
|
||||||
|
|
||||||
|
// consume available surfaces
|
||||||
|
std::vector<std::shared_ptr<Surface>> surfaces;
|
||||||
|
surfaces.reserve(surface_count);
|
||||||
|
for (size_t i = 0; i < surface_count; i++) {
|
||||||
|
std::shared_ptr<Surface> surf = acceleration_policy->get_free_surface(key).lock();
|
||||||
|
EXPECT_TRUE(surf.get() != nullptr);
|
||||||
|
EXPECT_EQ(surf->obtain_lock(), 0);
|
||||||
|
surfaces.push_back(std::move(surf));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::promise<void> launch_promise;
|
||||||
|
std::future<void> sync = launch_promise.get_future();
|
||||||
|
std::promise<size_t> surface_released_promise;
|
||||||
|
std::future<size_t> released_result = surface_released_promise.get_future();
|
||||||
|
std::thread worker_thread([&launch_promise, &surface_released_promise, &surfaces] () {
|
||||||
|
launch_promise.set_value();
|
||||||
|
|
||||||
|
// concurrent release surfaces
|
||||||
|
size_t surfaces_count = surfaces.size();
|
||||||
|
for (auto& surf : surfaces) {
|
||||||
|
EXPECT_EQ(surf->release_lock(), 1);
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
}
|
||||||
|
surfaces.clear();
|
||||||
|
|
||||||
|
surface_released_promise.set_value(surfaces_count);
|
||||||
|
});
|
||||||
|
sync.wait();
|
||||||
|
|
||||||
|
// check free surface concurrently
|
||||||
|
std::future_status status;
|
||||||
|
size_t free_surface_count = 0;
|
||||||
|
size_t free_surface_count_prev = 0;
|
||||||
|
do {
|
||||||
|
status = released_result.wait_for(std::chrono::seconds(1));
|
||||||
|
free_surface_count = acceleration_policy->get_free_surface_count(key);
|
||||||
|
EXPECT_TRUE(free_surface_count >= free_surface_count_prev);
|
||||||
|
free_surface_count_prev = free_surface_count;
|
||||||
|
} while (status != std::future_status::ready);
|
||||||
|
std::cerr<< "Ready" << std::endl;
|
||||||
|
free_surface_count = acceleration_policy->get_free_surface_count(key);
|
||||||
|
worker_thread.join();
|
||||||
|
EXPECT_TRUE(free_surface_count >= free_surface_count_prev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace opencv_test
|
} // namespace opencv_test
|
||||||
#endif // HAVE_ONEVPL
|
#endif // HAVE_ONEVPL
|
||||||
|
Loading…
Reference in New Issue
Block a user