mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 02:00:14 +02:00
Implement Bullet Bill model visibility and cockpit recentering improvements
- Added support for hiding model arrays in the rendering pipeline to optimize performance during VR gameplay. - Introduced new functions in `gx_model_visibility` to manage hidden model arrays and their visibility based on game state. - Enhanced cockpit recentering logic to ensure accurate seat measurements and eye positioning during gameplay. - Updated `FirstPersonState` to track cockpit height and forward direction, improving VR experience. - Added tests for Bullet Bill model visibility and cockpit height adjustments to ensure functionality and stability. - Refactored existing code to accommodate new features and improve overall code organization.
This commit is contained in:
1 parent
8c5a7126da
commit
3c20f677eb
17 files changed
+592
-38
No files matched your search
@@ -342,6 +342,11 @@ void aurora_clear_native_wheel_vertices(void);
|
||||
void aurora_set_native_wheel_vertices(const void* source, const void* replacement, uint32_t size,
|
||||
const float* modelView);
|
||||
uint32_t aurora_native_wheel_draw_count(void);
|
||||
// GX thread, ordered with draws. Hide only rigid draws binding this array at
|
||||
// this instance's model-view transform. Clear at the end of each guest frame.
|
||||
void aurora_clear_hidden_model_arrays(void);
|
||||
void aurora_hide_model_array(const void* source, const float* modelView);
|
||||
uint32_t aurora_hidden_model_draw_count(void);
|
||||
typedef void (*AuroraFrameWorkerWaitCallback)();
|
||||
// Called from the producer thread at bounded intervals while Aurora waits for
|
||||
// the asynchronous frame worker. The callback must not enter Aurora.
|
||||
|
||||
@@ -11,6 +11,23 @@
|
||||
#include "../../gfx/common.hpp"
|
||||
#include "../../gx/fifo.hpp"
|
||||
#include "../../gx/native_wheel.hpp"
|
||||
#include "../../gx/model_visibility.hpp"
|
||||
|
||||
extern "C" void aurora_clear_hidden_model_arrays() {
|
||||
if (aurora::gx::hiddenModelArrays.empty()) return;
|
||||
aurora::gx::fifo::drain();
|
||||
aurora::gx::hiddenModelLastDraws.store(aurora::gx::hiddenModelDraws);
|
||||
aurora::gx::hiddenModelDraws = 0;
|
||||
aurora::gx::hiddenModelArrays.clear();
|
||||
}
|
||||
extern "C" void aurora_hide_model_array(const void* source, const float* modelView) {
|
||||
if (!source || !modelView) return;
|
||||
aurora::gx::fifo::drain();
|
||||
aurora::gx::HiddenModelArray hidden{source, {}};
|
||||
std::memcpy(hidden.modelView.data(), modelView, sizeof(float) * 12);
|
||||
aurora::gx::hiddenModelArrays.push_back(hidden);
|
||||
}
|
||||
extern "C" uint32_t aurora_hidden_model_draw_count() { return aurora::gx::hiddenModelLastDraws.load(); }
|
||||
|
||||
// GX-thread entry points for the VR native steering wheel (native_wheel.hpp).
|
||||
// The runtime posts these in order with the frame's draws.
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "dolphin/gx/GXAurora.h"
|
||||
#include "gx.hpp"
|
||||
#include "native_wheel.hpp"
|
||||
#include "model_visibility.hpp"
|
||||
#include "gx_fmt.hpp"
|
||||
#include "pipeline.hpp"
|
||||
#include "shader_info.hpp"
|
||||
@@ -2367,6 +2368,7 @@ bool submit_raw_draw(GXPrimitive prim, GXVtxFmt fmt, const uint8_t* vertices, ui
|
||||
|
||||
// This entry point bypasses process(), so it owns the renderer lock itself.
|
||||
std::lock_guard gpuLock(aurora::renderer_gpu_mutex());
|
||||
if (model_array_hidden()) return true;
|
||||
const gfx::Range vertRange = push_draw_vertices(vertices, vtxCount, vtxSize);
|
||||
const bool interpolationIdentityActive = frame_interpolation_identity_needed();
|
||||
const PnMtxUsage matrixUsage = interpolationIdentityActive ? pn_mtx_usage(vertices, vtxCount, vtxSize) : PnMtxUsage{};
|
||||
@@ -2401,6 +2403,11 @@ static bool handle_draw(u8 cmd, const u8* data, u32& pos, u32 size, bool bigEndi
|
||||
return false;
|
||||
}
|
||||
|
||||
if (model_array_hidden()) {
|
||||
pos += totalVtxBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Push raw vertex data to buffer
|
||||
const uint8_t* vertices = data + pos;
|
||||
gfx::Range vertRange = push_draw_vertices(vertices, vtxCount, vtxSize);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#pragma once
|
||||
#include "gx.hpp"
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
namespace aurora::gx {
|
||||
struct HiddenModelArray {
|
||||
const void* source = nullptr;
|
||||
std::array<float, 12> modelView{};
|
||||
};
|
||||
inline std::vector<HiddenModelArray> hiddenModelArrays;
|
||||
inline uint32_t hiddenModelDraws = 0;
|
||||
inline std::atomic<uint32_t> hiddenModelLastDraws{0};
|
||||
|
||||
// Called before uploading vertices or merging draws. Matrix-indexed shapes
|
||||
// are deliberately excluded: Bullet Bill's arms have their own animated joints.
|
||||
inline bool model_array_hidden() {
|
||||
if (hiddenModelArrays.empty() || g_gxState.projType != GX_PERSPECTIVE ||
|
||||
(g_gxState.vtxDesc[GX_VA_POS] != GX_INDEX8 && g_gxState.vtxDesc[GX_VA_POS] != GX_INDEX16) ||
|
||||
g_gxState.vtxDesc[GX_VA_PNMTXIDX] != GX_NONE || g_gxState.currentPnMtx >= MaxPnMtx)
|
||||
return false;
|
||||
const auto* matrix = reinterpret_cast<const float*>(&g_gxState.pnMtx[g_gxState.currentPnMtx].pos);
|
||||
for (const auto& hidden : hiddenModelArrays) {
|
||||
if (g_gxState.arrays[GX_VA_POS].data != hidden.source) continue;
|
||||
bool matches = true;
|
||||
for (int i = 0; i < 12; ++i) {
|
||||
uint32_t actual, expected;
|
||||
std::memcpy(&actual, &matrix[i], 4);
|
||||
std::memcpy(&expected, &hidden.modelView[i], 4);
|
||||
if ((actual & 0x7f800000u) == 0x7f800000u || (expected & 0x7f800000u) == 0x7f800000u ||
|
||||
std::abs(matrix[i] - hidden.modelView[i]) > (i % 4 == 3 ? 0.1f : 0.002f)) {
|
||||
matches = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (matches) {
|
||||
++hiddenModelDraws;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace aurora::gx
|
||||
@@ -64,6 +64,7 @@ if (AURORA_ENABLE_GX)
|
||||
eye_pass_plan_test.cpp
|
||||
foveation_test.cpp
|
||||
native_wheel_test.cpp
|
||||
model_visibility_test.cpp
|
||||
cockpit_geometry_test.cpp
|
||||
texture_bind_group_cache_key_test.cpp
|
||||
../lib/gfx/efb_ram_encoder.cpp
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#include "gx_test_common.hpp"
|
||||
#include "gx/model_visibility.hpp"
|
||||
#include <aurora/aurora.h>
|
||||
|
||||
namespace {
|
||||
class HiddenModelTest : public GXFifoTest {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
GXFifoTest::SetUp();
|
||||
flush_and_capture();
|
||||
aurora::gx::hiddenModelArrays.clear();
|
||||
aurora::gx::hiddenModelDraws = 0;
|
||||
aurora::gx::hiddenModelLastDraws = 0;
|
||||
auto& state = gxState();
|
||||
state.lastVtxFmt = GX_VTXFMT0;
|
||||
state.lastVtxSize = 1;
|
||||
state.projType = GX_PERSPECTIVE;
|
||||
state.vtxDesc[GX_VA_POS] = GX_INDEX8;
|
||||
state.arrays[GX_VA_POS].data = source.data();
|
||||
state.arrays[GX_VA_POS].size = source.size();
|
||||
state.arrays[GX_VA_POS].stride = 12;
|
||||
std::memcpy(pos(), matrix.data(), sizeof(float) * 12);
|
||||
state.stateDirty = true;
|
||||
aurora_hide_model_array(source.data(), matrix.data());
|
||||
}
|
||||
void TearDown() override { aurora_clear_hidden_model_arrays(); }
|
||||
float* pos() { return reinterpret_cast<float*>(&gxState().pnMtx[0].pos); }
|
||||
void draw() { decode_fifo({static_cast<u8>(GX_TRIANGLES), 0, 3, 0, 1, 2}); }
|
||||
std::array<uint8_t, 36> source{};
|
||||
std::array<float, 12> matrix{1, 0, 0, 10, 0, 1, 0, 20, 0, 0, 1, 30};
|
||||
};
|
||||
|
||||
TEST_F(HiddenModelTest, LocalBodyIsSkippedBeforeVertexUploadAndClearRestoresIt) {
|
||||
draw();
|
||||
EXPECT_TRUE(aurora::gfx::testing::last_pushed_vertices().empty());
|
||||
aurora_clear_hidden_model_arrays();
|
||||
EXPECT_EQ(aurora_hidden_model_draw_count(), 1u);
|
||||
draw();
|
||||
EXPECT_FALSE(aurora::gfx::testing::last_pushed_vertices().empty());
|
||||
}
|
||||
|
||||
TEST_F(HiddenModelTest, OpponentUsingSameArrayIsDrawn) {
|
||||
pos()[3] += 100;
|
||||
draw();
|
||||
EXPECT_FALSE(aurora::gfx::testing::last_pushed_vertices().empty());
|
||||
EXPECT_EQ(aurora::gx::hiddenModelDraws, 0u);
|
||||
}
|
||||
|
||||
TEST_F(HiddenModelTest, ArmsAndIndexedJointsAreKept) {
|
||||
std::array<uint8_t, 36> arms{};
|
||||
gxState().arrays[GX_VA_POS].data = arms.data();
|
||||
EXPECT_FALSE(aurora::gx::model_array_hidden());
|
||||
gxState().arrays[GX_VA_POS].data = source.data();
|
||||
gxState().vtxDesc[GX_VA_PNMTXIDX] = GX_DIRECT;
|
||||
EXPECT_FALSE(aurora::gx::model_array_hidden());
|
||||
}
|
||||
|
||||
TEST_F(HiddenModelTest, DirectPositionsOrthographicAndInvalidMatricesAreKept) {
|
||||
gxState().vtxDesc[GX_VA_POS] = GX_DIRECT;
|
||||
EXPECT_FALSE(aurora::gx::model_array_hidden());
|
||||
gxState().vtxDesc[GX_VA_POS] = GX_INDEX8;
|
||||
gxState().projType = GX_ORTHOGRAPHIC;
|
||||
EXPECT_FALSE(aurora::gx::model_array_hidden());
|
||||
gxState().projType = GX_PERSPECTIVE;
|
||||
pos()[0] = __builtin_nanf("");
|
||||
EXPECT_FALSE(aurora::gx::model_array_hidden());
|
||||
}
|
||||
|
||||
TEST_F(HiddenModelTest, RawBridgeDrawAlsoSkipsLocalBody) {
|
||||
const std::array<uint8_t, 3> vertices{0, 1, 2};
|
||||
ASSERT_TRUE(aurora::gx::fifo::submit_raw_draw(GX_TRIANGLES, GX_VTXFMT0, vertices.data(), 3, vertices.size()));
|
||||
EXPECT_TRUE(aurora::gfx::testing::last_pushed_vertices().empty());
|
||||
EXPECT_EQ(aurora::gx::hiddenModelDraws, 1u);
|
||||
}
|
||||
} // namespace
|
||||
Reference in new issue
Block a user