f1c79eabde
Branch phase11b-cpp — refactor композитора на ООП.
Что сделано в этом коммите:
- CMakeLists.txt: CMAKE_CXX_STANDARD 17, language=CXX
- include/cuframes_composer/cpp/cuda_raii.hpp: CudaBuffer + CudaStream
как RAII обёртки (cuMemAlloc/cuMemFree, cuStreamCreate/Destroy).
Non-copyable, movable. Zero-copy: handle CUdeviceptr передаётся
идентично C-коду.
- cpp/types.hpp: Rect (pixel coords) + NV12Ref (общий read-write
референс на Y/UV plane'ы output буфера — composer + cells + decorations
делят его без копий).
- cpp/decoration.hpp: абстрактный Decoration с draw(stream, dst, parent_rect).
- cpp/cell.hpp: абстрактный Cell с draw() = draw_content() +
iterate decorations. Композиция через add_decoration().
Что НЕ сделано (следующие коммиты):
- CameraCell, WidgetCell, BlankCell (cell-content реализации)
- LabelDecoration, BorderDecoration (с FreeType/cugrid)
- Layout (контейнер cells + apply_template)
- Composer класс (owner SourcePool + Layout + OutputSurface)
- extern "C" ABI shim для совместимости с control.c, grid_record.c
- Удаление старых composer.c / overlay.c / layouts.c
- Восстановление функционала JSON templates + auto-labels
Производительность: virtual call overhead 1 indirect call per cell per
frame (negligible), никаких heap allocations в hot path, CUDA pipeline
1:1 идентичен C-версии.
Refs: #195 (Phase 11b C++ refactor)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
135 lines
3.9 KiB
C++
135 lines
3.9 KiB
C++
/* RAII обёртки над CUDA Driver/Runtime ресурсами (Phase 11b).
|
|
*
|
|
* Передача handle'ов между объектами по-прежнему zero-copy (CUdeviceptr —
|
|
* это unsigned long long; обмен идентичен plain C-коду). Эти обёртки только
|
|
* автоматизируют lifetime — без них приходилось бы вручную помнить про
|
|
* cuMemFree и закрывать stream'ы в путях ошибок.
|
|
*
|
|
* NB: классы non-copyable (чтобы не вызвать двойной cuMemFree), но movable.
|
|
*
|
|
* Лицензия: LGPL-2.1+
|
|
*/
|
|
|
|
#ifndef CUFRAMES_COMPOSER_CPP_CUDA_RAII_HPP
|
|
#define CUFRAMES_COMPOSER_CPP_CUDA_RAII_HPP
|
|
|
|
#include <cuda.h>
|
|
#include <cuda_runtime.h>
|
|
#include <utility>
|
|
|
|
namespace cfc {
|
|
|
|
/* VMM-allocated NV12 буфер для output / staging. Используется и compose,
|
|
* и NVENC (через тот же CUdeviceptr — zero-copy). */
|
|
class CudaBuffer {
|
|
public:
|
|
CudaBuffer() = default;
|
|
|
|
/* Аллокация в ctor; бросать исключения не хочется — проверяем ok(). */
|
|
explicit CudaBuffer(std::size_t bytes) {
|
|
if (cuMemAlloc(&ptr_, bytes) == CUDA_SUCCESS) {
|
|
size_ = bytes;
|
|
}
|
|
}
|
|
|
|
~CudaBuffer() { reset(); }
|
|
|
|
CudaBuffer(const CudaBuffer&) = delete;
|
|
CudaBuffer& operator=(const CudaBuffer&) = delete;
|
|
|
|
CudaBuffer(CudaBuffer&& other) noexcept
|
|
: ptr_(other.ptr_), size_(other.size_) {
|
|
other.ptr_ = 0;
|
|
other.size_ = 0;
|
|
}
|
|
CudaBuffer& operator=(CudaBuffer&& other) noexcept {
|
|
if (this != &other) {
|
|
reset();
|
|
ptr_ = other.ptr_;
|
|
size_ = other.size_;
|
|
other.ptr_ = 0;
|
|
other.size_ = 0;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
void reset() noexcept {
|
|
if (ptr_) {
|
|
cuMemFree(ptr_);
|
|
ptr_ = 0;
|
|
size_ = 0;
|
|
}
|
|
}
|
|
|
|
CUdeviceptr ptr() const noexcept { return ptr_; }
|
|
std::size_t size() const noexcept { return size_; }
|
|
bool ok() const noexcept { return ptr_ != 0; }
|
|
|
|
private:
|
|
CUdeviceptr ptr_ = 0;
|
|
std::size_t size_ = 0;
|
|
};
|
|
|
|
/* CUDA stream — owner. Композитор использует default stream (Phase 2/3),
|
|
* но обёртка готова к stream-pipelining (Phase 12+). */
|
|
class CudaStream {
|
|
public:
|
|
CudaStream() = default;
|
|
|
|
/* Создать non-default stream. */
|
|
static CudaStream create() {
|
|
CudaStream s;
|
|
cudaStreamCreate(&s.stream_);
|
|
s.owned_ = (s.stream_ != nullptr);
|
|
return s;
|
|
}
|
|
|
|
/* Обёртка над уже существующим stream'ом (не владеет). */
|
|
static CudaStream wrap(cudaStream_t s) noexcept {
|
|
CudaStream w;
|
|
w.stream_ = s;
|
|
w.owned_ = false;
|
|
return w;
|
|
}
|
|
|
|
~CudaStream() { reset(); }
|
|
|
|
CudaStream(const CudaStream&) = delete;
|
|
CudaStream& operator=(const CudaStream&) = delete;
|
|
|
|
CudaStream(CudaStream&& other) noexcept
|
|
: stream_(other.stream_), owned_(other.owned_) {
|
|
other.stream_ = nullptr;
|
|
other.owned_ = false;
|
|
}
|
|
CudaStream& operator=(CudaStream&& other) noexcept {
|
|
if (this != &other) {
|
|
reset();
|
|
stream_ = other.stream_;
|
|
owned_ = other.owned_;
|
|
other.stream_ = nullptr;
|
|
other.owned_ = false;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
void reset() noexcept {
|
|
if (owned_ && stream_) {
|
|
cudaStreamDestroy(stream_);
|
|
}
|
|
stream_ = nullptr;
|
|
owned_ = false;
|
|
}
|
|
|
|
cudaStream_t handle() const noexcept { return stream_; }
|
|
CUstream cu_handle() const noexcept { return reinterpret_cast<CUstream>(stream_); }
|
|
|
|
private:
|
|
cudaStream_t stream_ = nullptr;
|
|
bool owned_ = false;
|
|
};
|
|
|
|
} // namespace cfc
|
|
|
|
#endif /* CUFRAMES_COMPOSER_CPP_CUDA_RAII_HPP */
|