Test out experimental gEXMatrix command.

This commit is contained in:
Dario 2024-11-25 21:48:30 -03:00
parent 67422c3b64
commit 4c0ec59da4
11 changed files with 90 additions and 29 deletions

View File

@ -291,6 +291,12 @@ namespace RT64 {
state->setExtendedRDRAM(extended);
}
void matrixV1(State *state, DisplayList **dl) {
uint32_t params = (*dl)->w0;
*dl = *dl + 1;
state->rsp->matrix((*dl)->w1, params, (*dl)->w0);
}
void noOpHook(State *state, DisplayList **dl) {
uint32_t magicNumber = (*dl)->p0(0, 24);
if (magicNumber == RT64_HOOK_MAGIC_NUMBER) {
@ -392,6 +398,7 @@ namespace RT64 {
Map[G_EX_POPGEOMETRYMODE_V1] = &popGeometryModeV1;
Map[G_EX_SETDITHERNOISESTRENGTH_V1] = &setDitherNoiseStrengthV1;
Map[G_EX_SETRDRAMEXTENDED_V1] = &setRDRAMExtendedV1;
Map[G_EX_MATRIX_V1] = &matrixV1;
MapInitialized = true;
}
}

View File

@ -15,7 +15,7 @@
namespace RT64 {
namespace GBI_F3D {
void matrix(State *state, DisplayList **dl) {
state->rsp->matrix((*dl)->w1, (*dl)->p0(16, 8));
state->rsp->matrix((*dl)->w1, (*dl)->p0(16, 8), 0);
}
void popMatrix(State *state, DisplayList **dl) {

View File

@ -94,7 +94,7 @@ namespace RT64 {
}
void matrix(State *state, DisplayList **dl) {
state->rsp->matrix((*dl)->w1, (*dl)->p0(0, 8) ^ state->rsp->pushMask);
state->rsp->matrix((*dl)->w1, (*dl)->p0(0, 8) ^ state->rsp->pushMask, 0);
}
void popMatrix(State *state, DisplayList **dl) {

View File

@ -317,8 +317,9 @@ namespace RT64 {
for (uint32_t curIt : curWorkload.transformIgnoredIds) {
GameFrameMap::TransformMap &curTransformMap = curWorkloadMap.transforms[curIt];
curTransformMap.rigidBody = RigidBody();
curTransformMap.prevTransformIndex = 0;
curTransformMap.transformIndex = 0;
curTransformMap.mapped = false;
curTransformMap.previousIndexOverriden = false;
}
}
@ -662,16 +663,18 @@ namespace RT64 {
curTransformMap.rigidBody = prevWorkloadMap->transforms[prevTransformIndex].rigidBody;
}
const uint32_t previousIndex = curWorkload.drawData.worldTransformPreviousIndices[curTransformIndex];
const hlslpp::float4x4 &curTransform = curWorkload.drawData.worldTransforms[curTransformIndex];
const hlslpp::float4x4 &prevTransform = prevWorkload.drawData.worldTransforms[prevTransformIndex];
const hlslpp::float4x4 &prevTransform = (previousIndex > 0) ? curWorkload.drawData.worldTransformPrevious[previousIndex] : prevWorkload.drawData.worldTransforms[prevTransformIndex];
const uint32_t curGroupIndex = curWorkload.drawData.worldTransformGroups[curTransformIndex];
const TransformGroup &curGroup = curWorkload.drawData.transformGroups[curGroupIndex];
curTransformMap.rigidBody.updateLinear(prevTransform, curTransform, curGroup.positionInterpolation);
curTransformMap.rigidBody.updateAngular(prevTransform, curTransform, curGroup.rotationInterpolation, curGroup.scaleInterpolation, curGroup.skewInterpolation);
curTransformMap.rigidBody.updatePerspective(prevTransform, curTransform, curGroup.perspectiveInterpolation);
curTransformMap.rigidBody.updateDecomposition(curTransform, curGroup.decompose);
curTransformMap.prevTransformIndex = prevTransformIndex;
curTransformMap.transformIndex = (previousIndex > 0) ? previousIndex : prevTransformIndex;
curTransformMap.mapped = true;
curTransformMap.previousIndexOverriden = (previousIndex > 0);
curWorkloadMap.prevTransformsMapped[prevTransformIndex] = true;
uint32_t curVertexIndex = curWorkload.drawData.worldTransformVertexIndices[curTransformIndex];

View File

@ -51,8 +51,9 @@ namespace RT64 {
struct TransformMap {
RigidBody rigidBody;
uint32_t prevTransformIndex = 0;
uint32_t transformIndex = 0;
bool mapped = false;
bool previousIndexOverriden = false;
};
struct TileMap {

View File

@ -46,6 +46,8 @@ namespace RT64 {
modelMatrixStack.fill(hlslpp::float4x4(0.0f));
modelMatrixSegmentedAddressStack.fill(0);
modelMatrixPhysicalAddressStack.fill(0);
prevModelMatrixStack.fill(hlslpp::float4x4(0.0f));
prevModelMatrixAssignedStack.reset();
viewMatrixStack[0] = hlslpp::float4x4(0.0f);
projMatrixStack[0] = hlslpp::float4x4(0.0f);
viewProjMatrixStack[0] = hlslpp::float4x4(0.0f);
@ -121,10 +123,19 @@ namespace RT64 {
segments[seg] = address;
}
void RSP::matrix(uint32_t address, uint8_t params) {
void RSP::matrix(uint32_t address, uint32_t params, uint32_t prevAddress) {
const uint32_t rdramAddress = fromSegmentedMasked(address);
const FixedMatrix *fixedMatrix = reinterpret_cast<FixedMatrix *>(state->fromRDRAM(rdramAddress));
const hlslpp::float4x4 floatMatrix = fixedMatrix->toMatrix4x4();
const bool prevAddressValid = (params & G_EX_MTX_PREVIOUS);
// Load previous matrix as well if it was specified.
hlslpp::float4x4 prevFloatMatrix;
if (prevAddressValid) {
const uint32_t prevRdramAddress = fromSegmentedMasked(prevAddress);
const FixedMatrix *prevFixedMatrix = reinterpret_cast<FixedMatrix *>(state->fromRDRAM(prevRdramAddress));
prevFloatMatrix = prevFixedMatrix->toMatrix4x4();
}
// Projection matrix.
hlslpp::float4x4 &viewMatrix = viewMatrixStack[projectionMatrixStackSize - 1];
@ -133,6 +144,8 @@ namespace RT64 {
uint32_t &projectionMatrixSegmentedAddress = projectionMatrixSegmentedAddressStack[projectionMatrixStackSize - 1];
uint32_t &projectionMatrixPhysicalAddress = projectionMatrixPhysicalAddressStack[projectionMatrixStackSize - 1];
if (params & projMask) {
assert(!prevAddressValid && "Not implemented yet.");
if (params & loadMask) {
viewProjMatrix = floatMatrix;
@ -165,13 +178,32 @@ namespace RT64 {
if ((params & pushMask) && (modelMatrixStackSize < RSP_MATRIX_STACK_SIZE)) {
modelMatrixStackSize++;
modelMatrixStack[modelMatrixStackSize - 1] = modelMatrixStack[modelMatrixStackSize - 2];
if (prevModelMatrixAssignedStack[modelMatrixStackSize - 2]) {
prevModelMatrixStack[modelMatrixStackSize - 1] = prevModelMatrixStack[modelMatrixStackSize - 2];
prevModelMatrixAssignedStack[modelMatrixStackSize - 1] = true;
}
else {
prevModelMatrixAssignedStack[modelMatrixStackSize - 1] = false;
}
}
if (params & loadMask) {
modelMatrixStack[modelMatrixStackSize - 1] = floatMatrix;
prevModelMatrixAssignedStack[modelMatrixStackSize - 1] = prevAddressValid;
if (prevAddressValid) {
prevModelMatrixStack[modelMatrixStackSize - 1] = prevFloatMatrix;
}
}
else {
modelMatrixStack[modelMatrixStackSize - 1] = hlslpp::mul(floatMatrix, modelMatrixStack[modelMatrixStackSize - 1]);
if (prevAddressValid) {
const hlslpp::float4x4 &prevModelMatrix = prevModelMatrixAssignedStack[modelMatrixStackSize - 1] ? prevModelMatrixStack[modelMatrixStackSize - 1] : modelMatrixStack[modelMatrixStackSize - 1];
prevModelMatrixStack[modelMatrixStackSize - 1] = hlslpp::mul(prevFloatMatrix, prevModelMatrix);
prevModelMatrixAssignedStack[modelMatrixStackSize - 1] = true;
}
}
modelMatrixSegmentedAddressStack[modelMatrixStackSize - 1] = address;
@ -310,7 +342,7 @@ namespace RT64 {
modelViewProjChanged = changed;
}
void RSP::setVertex(uint32_t address, uint8_t vtxCount, uint32_t dstIndex) {
void RSP::setVertex(uint32_t address, uint32_t vtxCount, uint32_t dstIndex) {
if ((dstIndex >= RSP_MAX_VERTICES) || ((dstIndex + vtxCount) > RSP_MAX_VERTICES)) {
assert(false && "Vertex indices are not valid. DL is possibly corrupted.");
return;
@ -319,10 +351,10 @@ namespace RT64 {
const uint32_t rdramAddress = fromSegmentedMasked(address);
const Vertex *dlVerts = reinterpret_cast<const Vertex *>(state->fromRDRAM(rdramAddress));
memcpy(&vertices[dstIndex], dlVerts, sizeof(Vertex) * vtxCount);
setVertexCommon<true>(dstIndex, dstIndex + vtxCount);
setVertexCommon<true>(uint8_t(dstIndex), uint8_t(dstIndex + vtxCount));
}
void RSP::setVertexPD(uint32_t address, uint8_t vtxCount, uint32_t dstIndex) {
void RSP::setVertexPD(uint32_t address, uint32_t vtxCount, uint32_t dstIndex) {
if ((dstIndex >= RSP_MAX_VERTICES) || ((dstIndex + vtxCount) > RSP_MAX_VERTICES)) {
assert(false && "Vertex indices are not valid. DL is possibly corrupted.");
return;
@ -345,10 +377,10 @@ namespace RT64 {
dst.color.a = col[0];
}
setVertexCommon<true>(dstIndex, dstIndex + vtxCount);
setVertexCommon<true>(uint8_t(dstIndex), uint8_t(dstIndex + vtxCount));
}
void RSP::setVertexEXV1(uint32_t address, uint8_t vtxCount, uint32_t dstIndex) {
void RSP::setVertexEXV1(uint32_t address, uint32_t vtxCount, uint32_t dstIndex) {
if ((dstIndex >= RSP_MAX_VERTICES) || ((dstIndex + vtxCount) > RSP_MAX_VERTICES)) {
assert(false && "Vertex indices are not valid. DL is possibly corrupted.");
return;
@ -367,7 +399,7 @@ namespace RT64 {
vertices[dstIndex + i] = src.v;
}
setVertexCommon<false>(dstIndex, dstIndex + vtxCount);
setVertexCommon<false>(uint8_t(dstIndex), uint8_t(dstIndex + vtxCount));
}
void RSP::setVertexColorPD(uint32_t address) {
@ -433,6 +465,8 @@ namespace RT64 {
auto &worldTransformSegmentedAddresses = workload.drawData.worldTransformSegmentedAddresses;
auto &worldTransformPhysicalAddresses = workload.drawData.worldTransformPhysicalAddresses;
auto &worldTransformVertexIndices = workload.drawData.worldTransformVertexIndices;
auto &worldTransformPrevious = workload.drawData.worldTransformPrevious;
auto &worldTransformPreviousIndices = workload.drawData.worldTransformPreviousIndices;
bool addWorldTransform = (modelViewProjChanged || modelViewProjInserted);
if (modelViewProjChanged) {
computeModelViewProj();
@ -454,7 +488,7 @@ namespace RT64 {
curTransformIndex = static_cast<uint16_t>(worldTransforms.size());
worldTransforms.emplace_back(hlslpp::mul(modelViewProjMatrix, invViewProjMatrixStack[projectionMatrixStackSize - 1]));
}
if (addWorldTransform) {
uint32_t physicalAddress = modelMatrixPhysicalAddressStack[modelMatrixStackSize - 1];
workload.physicalAddressTransformMap.emplace(physicalAddress, uint32_t(worldTransformGroups.size()));
@ -462,6 +496,14 @@ namespace RT64 {
worldTransformSegmentedAddresses.emplace_back(modelMatrixSegmentedAddressStack[modelMatrixStackSize - 1]);
worldTransformPhysicalAddresses.emplace_back(physicalAddress);
worldTransformVertexIndices.emplace_back(workload.drawData.vertexCount());
if (prevModelMatrixAssignedStack[modelMatrixStackSize - 1]) {
worldTransformPreviousIndices.emplace_back(uint32_t(worldTransformPrevious.size()));
worldTransformPrevious.emplace_back(prevModelMatrixStack[modelMatrixStackSize - 1]);
}
else {
worldTransformPreviousIndices.emplace_back(0);
}
}
// Push a new projection if it's changed.

View File

@ -133,6 +133,8 @@ namespace RT64 {
std::array<hlslpp::float4x4, RSP_MATRIX_STACK_SIZE> modelMatrixStack;
std::array<uint32_t, RSP_MATRIX_STACK_SIZE> modelMatrixSegmentedAddressStack;
std::array<uint32_t, RSP_MATRIX_STACK_SIZE> modelMatrixPhysicalAddressStack;
std::array<hlslpp::float4x4, RSP_MATRIX_STACK_SIZE> prevModelMatrixStack;
std::bitset<RSP_MATRIX_STACK_SIZE> prevModelMatrixAssignedStack;
int modelMatrixStackSize;
std::array<hlslpp::float4x4, RSP_EXTENDED_STACK_SIZE> viewMatrixStack;
std::array<hlslpp::float4x4, RSP_EXTENDED_STACK_SIZE> projMatrixStack;
@ -226,7 +228,7 @@ namespace RT64 {
uint32_t fromSegmentedMasked(uint32_t segAddress);
uint32_t fromSegmentedMaskedPD(uint32_t segAddress);
void setSegment(uint32_t seg, uint32_t address);
void matrix(uint32_t address, uint8_t params);
void matrix(uint32_t address, uint32_t params, uint32_t prevAddress);
void popMatrix(uint32_t count);
void pushProjectionMatrix();
void popProjectionMatrix();
@ -235,9 +237,9 @@ namespace RT64 {
void computeModelViewProj();
void specialComputeModelViewProj();
void setModelViewProjChanged(bool changed);
void setVertex(uint32_t address, uint8_t vtxCount, uint32_t dstIndex);
void setVertexPD(uint32_t address, uint8_t vtxCount, uint32_t dstIndex);
void setVertexEXV1(uint32_t address, uint8_t vtxCount, uint32_t dstIndex);
void setVertex(uint32_t address, uint32_t vtxCount, uint32_t dstIndex);
void setVertexPD(uint32_t address, uint32_t vtxCount, uint32_t dstIndex);
void setVertexEXV1(uint32_t address, uint32_t vtxCount, uint32_t dstIndex);
void setVertexColorPD(uint32_t address);
template<bool addEmptyVelocity>
void setVertexCommon(uint8_t dstIndex, uint8_t dstMax);

View File

@ -81,7 +81,7 @@ namespace RT64 {
drawData.prevProjTransforms.clear();
drawData.prevViewProjTransforms.clear();
drawData.lerpWorldTransforms.clear();
drawData.prevWorldTransforms.clear();
drawData.prevLerpWorldTransforms.clear();
drawData.invTWorldTransforms.clear();
drawData.triPosFloats.clear();
drawData.triTcFloats.clear();
@ -92,6 +92,8 @@ namespace RT64 {
drawData.worldTransformSegmentedAddresses.clear();
drawData.worldTransformPhysicalAddresses.clear();
drawData.worldTransformVertexIndices.clear();
drawData.worldTransformPrevious.clear();
drawData.worldTransformPreviousIndices.clear();
// Push an identity matrix into the transforms by default so rects can use them.
drawData.rspViewports.push_back(interop::RSPViewport::identity());
@ -105,6 +107,8 @@ namespace RT64 {
drawData.worldTransformSegmentedAddresses.push_back(0);
drawData.worldTransformPhysicalAddresses.push_back(0);
drawData.worldTransformVertexIndices.push_back(0);
drawData.worldTransformPrevious.push_back(interop::float4x4::identity());
drawData.worldTransformPreviousIndices.push_back(0);
drawData.viewportOrigins.push_back(0);
}

View File

@ -51,9 +51,9 @@ namespace RT64 {
std::vector<interop::float4x4> prevProjTransforms;
std::vector<interop::float4x4> prevViewProjTransforms;
std::vector<interop::float4x4> worldTransforms;
std::vector<interop::float4x4> prevWorldTransforms;
std::vector<interop::float4x4> invTWorldTransforms;
std::vector<interop::float4x4> lerpWorldTransforms;
std::vector<interop::float4x4> prevLerpWorldTransforms;
std::vector<interop::RDPTile> rdpTiles;
std::vector<interop::RDPTile> lerpRdpTiles;
std::vector<interop::GPUTile> gpuTiles;
@ -73,6 +73,8 @@ namespace RT64 {
std::vector<uint32_t> worldTransformSegmentedAddresses;
std::vector<uint32_t> worldTransformPhysicalAddresses;
std::vector<uint32_t> worldTransformVertexIndices;
std::vector<interop::float4x4> worldTransformPrevious;
std::vector<uint32_t> worldTransformPreviousIndices;
uint32_t vertexCount() const {
return uint32_t(worldIndices.size());
@ -154,7 +156,7 @@ namespace RT64 {
BufferPair rspLookAtBuffer;
BufferPair worldTransformsBuffer;
BufferPair viewProjTransformsBuffer;
BufferPair prevWorldTransformsBuffer;
BufferPair prevLerpWorldTransformsBuffer;
BufferPair invTWorldTransformsBuffer;
BufferPair triPosBuffer;
BufferPair triTcBuffer;

View File

@ -26,10 +26,10 @@ namespace RT64 {
const bool prevFrameValid = (p.prevFrame != nullptr) && p.curFrame->frameMap.workloads[w].mapped;
auto &lerpWorldTransforms = drawData.lerpWorldTransforms;
auto &invTWorldTransforms = drawData.invTWorldTransforms;
auto &prevWorldTransforms = drawData.prevWorldTransforms;
auto &prevLerpWorldTransforms = drawData.prevLerpWorldTransforms;
lerpWorldTransforms.clear();
invTWorldTransforms.clear();
prevWorldTransforms.clear();
prevLerpWorldTransforms.clear();
hlslpp::float4x4 prevMatrix, curMatrix, invMatrix, invTMatrix;
@ -40,7 +40,7 @@ namespace RT64 {
for (size_t t = 0; t < drawData.worldTransforms.size(); t++) {
const GameFrameMap::TransformMap &transformMap = workloadMap.transforms[t];
if (transformMap.mapped) {
const hlslpp::float4x4 &prevTransform = prevDrawData.worldTransforms[workloadMap.transforms[t].prevTransformIndex];
const hlslpp::float4x4 &prevTransform = transformMap.previousIndexOverriden ? drawData.worldTransformPrevious[transformMap.transformIndex] : prevDrawData.worldTransforms[transformMap.transformIndex];
const hlslpp::float4x4 &curTransform = drawData.worldTransforms[t];
prevMatrix = transformMap.rigidBody.lerp(p.prevFrameWeight, prevTransform, curTransform, true);
curMatrix = transformMap.rigidBody.lerp(p.curFrameWeight, prevTransform, curTransform, true);
@ -48,14 +48,14 @@ namespace RT64 {
invTMatrix = hlslpp::transpose(invMatrix);
lerpWorldTransforms.emplace_back(curMatrix);
invTWorldTransforms.emplace_back(invTMatrix);
prevWorldTransforms.emplace_back(prevMatrix);
prevLerpWorldTransforms.emplace_back(prevMatrix);
}
else {
invMatrix = hlslpp::inverse(drawData.worldTransforms[t]);
invTMatrix = hlslpp::transpose(invMatrix);
lerpWorldTransforms.emplace_back(drawData.worldTransforms[t]);
invTWorldTransforms.emplace_back(invTMatrix);
prevWorldTransforms.emplace_back(drawData.worldTransforms[t]);
prevLerpWorldTransforms.emplace_back(drawData.worldTransforms[t]);
}
}
}
@ -79,11 +79,11 @@ namespace RT64 {
const DrawData &drawData = workload.drawData;
DrawBuffers &drawBuffers = workload.drawBuffers;
const interop::float4x4 *worldMatrices = prevFrameValid ? drawData.lerpWorldTransforms.data() : drawData.worldTransforms.data();
const interop::float4x4 *prevWorldMatrices = prevFrameValid ? drawData.prevWorldTransforms.data() : drawData.worldTransforms.data();
const interop::float4x4 *prevWorldMatrices = prevFrameValid ? drawData.prevLerpWorldTransforms.data() : drawData.worldTransforms.data();
const interop::float4x4 *invTWorldMatrices = drawData.invTWorldTransforms.data();
std::pair<size_t, size_t> uploadRange = { 0, drawData.worldTransforms.size() };
uploads.emplace_back(BufferUploader::Upload{ worldMatrices, uploadRange, sizeof(interop::float4x4), RenderBufferFlag::STORAGE, { }, &drawBuffers.worldTransformsBuffer });
uploads.emplace_back(BufferUploader::Upload{ prevWorldMatrices, uploadRange, sizeof(interop::float4x4), RenderBufferFlag::STORAGE, { }, &drawBuffers.prevWorldTransformsBuffer });
uploads.emplace_back(BufferUploader::Upload{ prevWorldMatrices, uploadRange, sizeof(interop::float4x4), RenderBufferFlag::STORAGE, { }, &drawBuffers.prevLerpWorldTransformsBuffer });
uploads.emplace_back(BufferUploader::Upload{ invTWorldMatrices, uploadRange, sizeof(interop::float4x4), RenderBufferFlag::STORAGE, { }, &drawBuffers.invTWorldTransformsBuffer });
}

View File

@ -32,7 +32,7 @@ namespace RT64 {
descriptorSet->setBuffer(descriptorSet->srcIndices, p.drawBuffers->worldIndicesBuffer.get(), p.drawBuffers->worldIndicesBuffer.getView(0));
descriptorSet->setBuffer(descriptorSet->worldMats, p.drawBuffers->worldTransformsBuffer.get(), RenderBufferStructuredView(sizeof(interop::float4x4)));
descriptorSet->setBuffer(descriptorSet->invTWorldMats, p.drawBuffers->invTWorldTransformsBuffer.get(), RenderBufferStructuredView(sizeof(interop::float4x4)));
descriptorSet->setBuffer(descriptorSet->prevWorldMats, p.drawBuffers->prevWorldTransformsBuffer.get(), RenderBufferStructuredView(sizeof(interop::float4x4)));
descriptorSet->setBuffer(descriptorSet->prevWorldMats, p.drawBuffers->prevLerpWorldTransformsBuffer.get(), RenderBufferStructuredView(sizeof(interop::float4x4)));
descriptorSet->setBuffer(descriptorSet->dstPos, p.outputBuffers->worldPosBuffer.buffer.get(), RenderBufferStructuredView(sizeof(float) * 4));
descriptorSet->setBuffer(descriptorSet->dstNorm, p.outputBuffers->worldNormBuffer.buffer.get(), RenderBufferStructuredView(sizeof(float) * 4));
descriptorSet->setBuffer(descriptorSet->dstVel, p.outputBuffers->worldVelBuffer.buffer.get(), RenderBufferStructuredView(sizeof(float) * 4));