Files
dhkatzandClaude Opus 5.5 42fc55cb91 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]>
2026-10-28 05:52:15 -07:00

62 lines
2.0 KiB
C++

// The command stream: what the adapter writes, the renderer process reads back the same.
#include <cstdio>
#include <cstring>
#include "t5de/protocol/commands.hpp"
using namespace t5de::protocol;
namespace {
int failures = 0;
void check(bool ok, const char* what)
{
if (!ok) {
std::printf("FAIL: %s\n", what);
++failures;
}
}
} // namespace
int main()
{
Writer writer;
writer.add(Op::Clear, Clear{3, 0xff131313});
const unsigned char pixels[] = {1, 2, 3, 4, 5, 6, 7, 8};
std::memcpy(writer.add(Op::CreateTexture, CreateTexture{7, 2, 1, 6}, sizeof(pixels)), pixels, sizeof(pixels));
std::byte* odd = writer.add(Op::UpdateBuffer, UpdateBuffer{9, 1, 3}, 3); // padded to 4
std::memset(odd, 0xab, 3);
writer.add(Op::EndFrame, EndFrame{});
check(writer.size() % 4 == 0, "commands stay 4-byte aligned");
Reader reader(writer.bytes());
auto clear = reader.next();
check(clear && clear->op() == Op::Clear && clear->body<Clear>()->color == 0xff131313, "clear");
auto texture = reader.next();
check(texture && texture->op() == Op::CreateTexture && texture->body<CreateTexture>()->id == 7, "texture");
check(texture && texture->payload<CreateTexture>().size() == sizeof(pixels)
&& std::memcmp(texture->payload<CreateTexture>().data(), pixels, sizeof(pixels)) == 0,
"texture pixels");
auto update = reader.next();
check(update && update->payload<UpdateBuffer>().size() == 4, "payload padded");
auto end = reader.next();
check(end && end->op() == Op::EndFrame, "end of frame");
check(!reader.next(), "nothing after");
// A truncated stream (a chunk cut short) yields only whole commands.
Reader truncated(writer.bytes().first(writer.size() - 2));
int count = 0;
while (truncated.next()) {
++count;
}
check(count == 3, "truncated: whole commands only");
if (failures == 0) {
std::printf("ok\n");
}
return failures == 0 ? 0 : 1;
}