Draw the client's scene in the renderer process

The adapter records everything the client draws (state, transforms, lights, fog, textures and buffers) as a command stream, sent in chunks through the shared memory channel, while IMVU's Direct3D renderer still draws the whole view. The renderer process draws it with Diligent, with shaders reproducing IMVU's Direct3D 9 fixed-function setup, over the right half of the 3D view to compare. It skips to the newest frame when it falls behind, and logs its errors and frame times.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-10-28 05:52:15 -07:00
1 parent 5c35c8b63a
commit 42fc55cb91
23 files changed
+2121 -472

No files matched your search

+114
View File
@@ -0,0 +1,114 @@
#pragma once
// Carries out the command stream (include/t5de/protocol/commands.hpp) with Diligent, reproducing IMVU's Direct3D 9
// look (shaders/fixed_function.hlsl): the client's textures and buffers by id, its state as it sets it, a pipeline
// for each combination of states it draws with.
#include <cstddef>
#include <cstdint>
#include <span>
#include <unordered_map>
#include "EngineFactoryD3D11.h"
#include "RefCntAutoPtr.hpp"
#include "t5de/protocol/commands.hpp"
namespace t5de {
class Scene {
public:
Scene(Diligent::IRenderDevice* device, Diligent::IDeviceContext* context, Diligent::ISwapChain* swapChain);
// Carries out one frame's commands. offsetX is where the window starts within the client's 3D view; without draw,
// only the frame's changes are made (textures, buffers, state). True if the frame was drawn into the window (to
// present).
bool execute(std::span<const std::byte> commands, int offsetX, bool draw);
private:
struct Texture {
Diligent::RefCntAutoPtr<Diligent::ITexture> texture;
std::uint32_t width = 0;
std::uint32_t height = 0;
std::uint32_t flags = 0;
};
struct Buffer {
Diligent::RefCntAutoPtr<Diligent::IBuffer> buffer;
protocol::BufferKind kind = protocol::BufferKind::Vertex;
std::uint32_t elementSize = 0;
std::uint32_t count = 0;
};
struct Pipeline {
Diligent::RefCntAutoPtr<Diligent::IPipelineState> state;
Diligent::RefCntAutoPtr<Diligent::IShaderResourceBinding> bindings;
Diligent::IShaderResourceVariable* texture0 = nullptr;
Diligent::IShaderResourceVariable* texture1 = nullptr;
};
struct Shaders {
Diligent::RefCntAutoPtr<Diligent::IShader> vertex;
Diligent::RefCntAutoPtr<Diligent::IShader> pixel;
};
// Mirrors the shader's constant buffer.
struct Constants {
float world[16];
float view[16];
float projection[16];
float texTransform0[8];
float texTransform1[8];
float ambient[4];
float lightColor[8][4];
float lightVector[8][4];
float fogColor[4];
float fog[4];
float flags[4];
};
// What a draw needs from the state, as set by the client.
struct State {
bool depthTest = true;
bool depthWrite = true;
bool blending = false;
std::uint32_t blendMode = 1;
bool culling = true;
bool normalInverting = false;
std::uint32_t texture0 = 0;
std::uint32_t texture1 = 0;
};
void createTexture(const protocol::Command& command);
void updateTexture(const protocol::Command& command);
void createBuffer(const protocol::Command& command);
void updateBuffer(const protocol::Command& command);
void setProjection(const protocol::SetProjection& projection);
void setState(const protocol::SetState& state);
void drawTriangles(const protocol::DrawTriangles& draw);
void drawArrays(const protocol::Command& command);
// Draws indexCount indices from index, with vertex streams (positions required, the others may be null).
void draw(Diligent::IBuffer* indices, std::uint32_t indexCount, Diligent::IBuffer* positions,
Diligent::IBuffer* normals, Diligent::IBuffer* texCoords, Diligent::IBuffer* colors);
Pipeline* pipeline(std::uint32_t streams, std::uint32_t textures);
const Shaders& shaders(std::uint32_t streams, std::uint32_t textures);
Diligent::ITextureView* textureView(std::uint32_t id);
Diligent::RefCntAutoPtr<Diligent::IRenderDevice> device_;
Diligent::RefCntAutoPtr<Diligent::IDeviceContext> context_;
Diligent::RefCntAutoPtr<Diligent::ISwapChain> swapChain_;
Diligent::RefCntAutoPtr<Diligent::IBuffer> constantBuffer_;
Diligent::RefCntAutoPtr<Diligent::ISampler> samplers_[4]; // by wrap u (1) and wrap v (2)
std::unordered_map<std::uint32_t, Texture> textures_;
std::unordered_map<std::uint32_t, Buffer> buffers_;
std::unordered_map<std::uint32_t, Shaders> shaders_;
std::unordered_map<std::uint32_t, Pipeline> pipelines_;
Constants constants_{};
State state_;
bool onscreen_ = false; // in a frame drawn into the window
bool draw_ = true;
int offsetX_ = 0;
};
} // namespace t5de