#pragma once // Records what the client draws as commands (include/t5de/protocol/commands.hpp) and sends them to the renderer // process. Shared by an engine and the resources it creates (which can outlive it); once the renderer process is // gone, it records nothing. #include #include #include #include #include "renderer_process.hpp" #include "t5de/imvu/types.hpp" #include "t5de/protocol/commands.hpp" namespace t5de { class Recorder { public: explicit Recorder(std::unique_ptr process); [[nodiscard]] bool active() const { return process_ && process_->alive(); } // Whether the renderer process draws the whole 3D view, so the client's renderer needn't. [[nodiscard]] bool covering() const { return process_ && process_->covering(); } // Records a command (if active); returns its payload to fill, or null. template std::byte* add(protocol::Op op, const Body& body, std::size_t payloadSize = 0) { if (!active()) { return nullptr; } std::byte* payload = writer_.add(op, body, payloadSize); return payload; } // Sends what's recorded: at the end of each frame, and between frames when a lot is waiting (resources). void flush(bool endsFrame); void flushIfLarge(); std::uint32_t createTexture(const imvu::Pixmap& pixmap, std::uint32_t flags); // Destroyed with destroyTexture. std::uint32_t createRenderTarget(std::uint32_t width, std::uint32_t height); // After flushing a frame that reads its render target back: its pixels (RendererProcess::readBack). std::span readBack(); void updateTexture(std::uint32_t id, const imvu::Pixmap& pixmap); void destroyTexture(std::uint32_t id); // Copies count elements of elementSize bytes, stride bytes apart (0: packed), from data (null: none yet). std::uint32_t createBuffer(protocol::BufferKind kind, const void* data, std::uint32_t stride, std::uint32_t elementSize, std::uint32_t count); void updateBuffer(std::uint32_t id, const void* data, std::uint32_t stride, std::uint32_t elementSize, std::uint32_t count); void destroyBuffer(std::uint32_t id); // Diagnostics: what's been sent, and the time spent sending (waiting for the renderer process to take it). struct Counters { std::uint64_t bytes = 0; double sendSeconds = 0; std::uint32_t bufferUpdates = 0; std::uint64_t bufferBytes = 0; }; // Returns the counters since the last call. Counters takeCounters() { return std::exchange(counters_, {}); } private: void addPixels(protocol::Op op, std::uint32_t id, const imvu::Pixmap& pixmap, std::uint32_t flags); std::unique_ptr process_; protocol::Writer writer_; std::uint32_t nextId_ = 1; Counters counters_; }; // Copies count elements of elementSize bytes, stride bytes apart (0: packed), into destination, packed. void pack(std::byte* destination, const void* source, std::uint32_t stride, std::uint32_t elementSize, std::uint32_t count); } // namespace t5de