Files
cuframes-composer/include/cuframes_composer/cpp/cuda_raii.hpp
T
gx f1c79eabde Phase 11b A: CMake C++17 + базовые headers
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>
2026-06-03 21:27:44 +01:00

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 */