CI / build (push) Successful in 1m31s
The frame pacer repaints the client's 3D windows at the user's frame rate (HKCU\Software\T5DE\Graphics\FrameRate: 30, the default, adds nothing; 60, 120, 240, 360; 0 uncapped), so the client draws frames between its 30-per-second steps. Only when affordable: a window is asked once its last frame is drawn, and only if its frames take under three quarters of the interval; uncapped, the client is left idle a third of a frame between frames. The engine's stats now log frames per second. The extra frames show the same scene for now. Co-Authored-By: Claude Opus 5.5 <[email protected]>
100 lines
5.7 KiB
C++
100 lines
5.7 KiB
C++
#pragma once
|
|
// The adapter's engine: what the client draws with. Everything is recorded for the renderer process, which draws the
|
|
// 3D view and the render targets it makes. The client's own Direct3D renderer gets state and resources too (as a
|
|
// fallback, and for reading textures back), but while the renderer process covers the whole view, the client's
|
|
// renderer skips its frames' clears and draws. When the renderer process doesn't cover it (it failed, or shows only
|
|
// part of the view, for comparing) the client's renderer draws everything, from the next frame on.
|
|
|
|
#include <windows.h>
|
|
|
|
#include <cstdint>
|
|
#include <memory>
|
|
|
|
#include "recorder.hpp"
|
|
#include "t5de/imvu/render_engine.hpp"
|
|
|
|
namespace t5de {
|
|
|
|
class Engine final : public imvu::PiRenderEngine {
|
|
public:
|
|
// recorder may be inactive (no renderer process); window is the 3D window drawn into (frame_pacer.hpp), or null.
|
|
Engine(imvu::SharedPtr<imvu::PiRenderEngine> inner, std::shared_ptr<Recorder> recorder, HWND window);
|
|
~Engine() override;
|
|
|
|
void resizeFrameBuffer(imvu::Vec2i size) override;
|
|
void enable2dFrameBuffer() override;
|
|
void clear(std::uint32_t flags, imvu::Color color) override;
|
|
void setProjection(imvu::Vec2i viewport, const imvu::Mat4f& projection) override;
|
|
void setModelSpace(const imvu::Transform& model) override;
|
|
void setViewSpace(const imvu::Transform& view) override;
|
|
void setTextures(imvu::PiRenderTexture* texture0, imvu::PiRenderTexture* texture1) override;
|
|
void setDepthTestingOn(bool on) override;
|
|
void setDepthWritingOn(bool on) override;
|
|
void setBlendMode(imvu::RenderBlendMode mode) override;
|
|
void setAlphaTestingOn(bool on) override;
|
|
void setAlphaTestValue(float value) override;
|
|
void setBlendingOn(bool on) override;
|
|
void setBackFaceCullingOn(bool on) override;
|
|
void setNormalInvertingOn(bool on) override;
|
|
void setLightingOn(bool on) override;
|
|
void setLightProperties(std::uint32_t index, const imvu::LightProperties& light) override;
|
|
void setFogOn(bool on) override;
|
|
void setFogAttributes(float start, float end, imvu::Color color) override;
|
|
void setTextureTransformMatrixIdentity(std::uint32_t stage) override;
|
|
void setTextureTransformMatrix(std::uint32_t stage, const imvu::TextureTransform& transform) override;
|
|
void setEnvironmentAmbient(imvu::Color color) override;
|
|
imvu::PiRenderTexture* newRenderTexture(const imvu::Pixmap& pixmap, std::uint32_t flags) override;
|
|
imvu::PiInternalIndexBuffer* newIndexBuffer(std::uint32_t count, const std::uint16_t* indices) override;
|
|
imvu::PiInternalVertexBuffer* newStaticVertexBuffer(const void* data, std::uint32_t stride,
|
|
std::uint32_t elementSize,
|
|
std::uint32_t elementCount) override;
|
|
imvu::PiInternalVertexBuffer* newDynamicVertexBuffer(std::uint32_t elementSize,
|
|
std::uint32_t elementCount) override;
|
|
imvu::SharedPtr<imvu::PiPixmapRenderTarget> newPixmapRenderTarget(imvu::Vec2i size) override;
|
|
imvu::SharedPtr<imvu::PiTextureRenderTarget> newTextureRenderTarget(imvu::Vec2i size) override;
|
|
void beginRendering(imvu::PiRenderTarget* target) override;
|
|
void endRendering() override;
|
|
void drawTriangles(imvu::PiInternalIndexBuffer* indices, imvu::PiInternalVertexBuffer* positions,
|
|
imvu::PiInternalVertexBuffer* normals, imvu::PiInternalVertexBuffer* texCoords,
|
|
imvu::PiInternalVertexBuffer* colors) override;
|
|
void drawLine(imvu::Vec3f from, imvu::Vec3f to, imvu::Color color) override;
|
|
void drawPointSprites(const imvu::PointSpriteVector& sprites) override;
|
|
void drawTrianglesFromMemory(std::uint32_t vertexCount, std::uint32_t indexCount, const std::uint16_t* indices,
|
|
const imvu::VertexAttributeArray<imvu::Vec3f>& positions,
|
|
const imvu::VertexAttributeArray<imvu::Vec3f>& normals,
|
|
const imvu::VertexAttributeArray<imvu::Vec2f>& texCoords,
|
|
const imvu::VertexAttributeArray<imvu::Color>& colors) override;
|
|
|
|
private:
|
|
void setState(protocol::State state, std::uint32_t value);
|
|
// Whether the client's renderer should draw this frame's clears and draws.
|
|
[[nodiscard]] bool innerDraws() const { return !takenOver_; }
|
|
|
|
imvu::SharedPtr<imvu::PiRenderEngine> inner_;
|
|
std::shared_ptr<Recorder> recorder_;
|
|
HWND window_;
|
|
std::uint64_t frames_ = 0;
|
|
bool takenOver_ = false; // this frame is drawn by the renderer process only
|
|
imvu::PiRenderTarget* ourTarget_ = nullptr; // this frame's render target, if it's one of ours
|
|
int foreignLogged_ = 0; // diagnostics: textures the client renderer made, render targets
|
|
|
|
// Diagnostics: what the client draws, summed over 300 frames and logged (the first few times).
|
|
struct Stats {
|
|
std::uint32_t triangles = 0; // drawTriangles with our buffers
|
|
std::uint32_t foreignTriangles = 0; // drawTriangles with buffers that aren't ours (not drawn)
|
|
std::uint32_t indexed = 0; // drawTrianglesFromMemory with indices
|
|
std::uint32_t unindexed = 0; // drawTrianglesFromMemory without
|
|
std::uint32_t sprites = 0;
|
|
std::uint32_t lines = 0;
|
|
std::uint32_t flat = 0; // setProjection with an orthographic projection (2D)
|
|
};
|
|
Stats stats_;
|
|
LARGE_INTEGER statsStart_{}; // when the stats' 300 frames started
|
|
LARGE_INTEGER frameStart_{}; // when the current frame began
|
|
bool windowFrame_ = false; // the current frame is drawn into the window
|
|
int statsLogged_ = 0;
|
|
|
|
};
|
|
|
|
} // namespace t5de
|