[graphics] hook up visibility data for jak 2 (#1938)

It works!

Visibility off:

![image](https://user-images.githubusercontent.com/48171810/193422627-c5560519-6d20-4645-baa5-5236c7969d6e.png)

On:

![image](https://user-images.githubusercontent.com/48171810/193422631-716fff10-9ad7-486f-ad35-9ddcddf2c4eb.png)

Overall the visibility data looks a lot better than in jak 1.
This commit is contained in:
water111
2022-10-01 17:12:12 -04:00
committed by GitHub
parent d52739226c
commit f1682867af
8 changed files with 178 additions and 14 deletions
+1
View File
@@ -143,6 +143,7 @@ set(RUNTIME_SOURCE
graphics/opengl_renderer/Sprite3.cpp
graphics/opengl_renderer/SpriteRenderer.cpp
graphics/opengl_renderer/TextureUploadHandler.cpp
graphics/opengl_renderer/VisDataHandler.cpp
graphics/opengl_renderer/DepthCue.cpp
graphics/texture/jak1_tpage_dir.cpp
graphics/texture/jak2_tpage_dir.cpp
@@ -39,7 +39,6 @@ struct SharedRenderState {
bool use_sky_cpu = true;
bool use_occlusion_culling = true;
bool enable_merc_xgkick = true;
math::Vector<u8, 4> fog_color = math::Vector<u8, 4>{0, 0, 0, 0};
float fog_intensity = 1.f;
bool no_multidraw = false;
@@ -77,6 +76,7 @@ struct SharedRenderState {
int draw_offset_y = 0;
int bucket_for_vis_copy = 0;
int num_vis_to_copy = 0;
GameVersion version;
};
@@ -11,6 +11,7 @@
#include "game/graphics/opengl_renderer/Sprite3.h"
#include "game/graphics/opengl_renderer/SpriteRenderer.h"
#include "game/graphics/opengl_renderer/TextureUploadHandler.h"
#include "game/graphics/opengl_renderer/VisDataHandler.h"
#include "game/graphics/opengl_renderer/background/Shrub.h"
#include "game/graphics/opengl_renderer/background/TFragment.h"
#include "game/graphics/opengl_renderer/background/Tie3.h"
@@ -87,7 +88,7 @@ void OpenGLRenderer::init_bucket_renderers_jak2() {
using namespace jak2;
m_bucket_renderers.resize((int)BucketId::MAX_BUCKETS);
m_bucket_categories.resize((int)BucketId::MAX_BUCKETS, BucketCategory::OTHER);
init_bucket_renderer<VisDataHandler>("vis", BucketCategory::OTHER, BucketId::SPECIAL_BUCKET_2);
init_bucket_renderer<TFragment>("tfrag-l0-tfrag", BucketCategory::TFRAG, BucketId::TFRAG_L0_TFRAG,
std::vector{tfrag3::TFragmentTreeKind::NORMAL}, false, 0);
init_bucket_renderer<Tie3>("tie-l0-tfrag", BucketCategory::TIE, BucketId::TIE_L0_TFRAG, 0);
@@ -455,7 +456,6 @@ void OpenGLRenderer::draw_renderer_selection_window() {
ImGui::SliderFloat("Fog Adjust", &m_render_state.fog_intensity, 0, 10);
ImGui::Checkbox("Sky CPU", &m_render_state.use_sky_cpu);
ImGui::Checkbox("Occlusion Cull", &m_render_state.use_occlusion_culling);
ImGui::Checkbox("Merc XGKICK", &m_render_state.enable_merc_xgkick);
ImGui::Checkbox("Blackout Loads", &m_enable_fast_blackout_loads);
for (size_t i = 0; i < m_bucket_renderers.size(); i++) {
@@ -697,6 +697,7 @@ void OpenGLRenderer::dispatch_buckets_jak1(DmaFollower dma,
dma.current_tag_offset() + 16; // offset by 1 qw for the initial call
m_render_state.next_bucket = m_render_state.buckets_base;
m_render_state.bucket_for_vis_copy = (int)jak1::BucketId::TFRAG_LEVEL0;
m_render_state.num_vis_to_copy = 2;
// Find the default regs buffer
auto initial_call_tag = dma.current_tag();
@@ -759,7 +760,8 @@ void OpenGLRenderer::dispatch_buckets_jak2(DmaFollower dma,
m_render_state.buckets_base = dma.current_tag_offset(); // starts at 0 in jak 2
m_render_state.next_bucket = m_render_state.buckets_base + 16;
m_render_state.bucket_for_vis_copy = 0; // TODO
m_render_state.bucket_for_vis_copy = (int)jak2::BucketId::SPECIAL_BUCKET_2;
m_render_state.num_vis_to_copy = 6;
for (size_t bucket_id = 0; bucket_id < m_bucket_renderers.size(); bucket_id++) {
auto& renderer = m_bucket_renderers[bucket_id];
@@ -0,0 +1,82 @@
#include "VisDataHandler.h"
#include "third-party/imgui/imgui.h"
VisDataHandler::VisDataHandler(const std::string& name, int my_id) : BucketRenderer(name, my_id) {}
void VisDataHandler::draw_debug_window() {
ImGui::Checkbox("Count Visible?", &m_count_vis);
for (int i = 0; i < kMaxLevels; i++) {
const auto& stats = m_stats[i];
if (stats.has_vis) {
if (m_count_vis) {
ImGui::Text("[%d] %d visible", i, stats.num_visible);
} else {
ImGui::Text("[%d] has vis", i);
}
}
}
}
int bitcount(const u8* data) {
int result = 0;
for (int byte = 0; byte < 16 * 128; byte++) {
u8 val = data[byte];
for (int i = 0; i < 8; i++) {
if (val & 1) {
result++;
}
val >>= 1;
}
}
return result;
}
void VisDataHandler::render(DmaFollower& dma,
SharedRenderState* render_state,
ScopedProfilerNode& /*prof*/) {
// reset stats
for (auto& stats : m_stats) {
stats = LevelStats();
}
if (dma.current_tag_offset() == render_state->next_bucket) {
return;
}
// skip bucket start
dma.read_and_advance();
if (dma.current_tag_offset() == render_state->next_bucket) {
return;
}
for (int i = 0; i < render_state->num_vis_to_copy; i++) {
auto vis_data = dma.read_and_advance();
ASSERT(vis_data.vif0() == 0);
if (vis_data.vifcode1().kind != VifCode::Kind::PC_PORT) {
break;
}
if (vis_data.size_bytes == 128 * 16 && render_state->use_occlusion_culling) {
memcpy(render_state->occlusion_vis[i].data, vis_data.data, 128 * 16);
render_state->occlusion_vis[i].valid = true;
m_stats[i].has_vis = true;
if (m_count_vis) {
m_stats[i].num_visible = bitcount(render_state->occlusion_vis[i].data);
} else {
m_stats[i].num_visible = -1;
}
} else {
m_stats[i].has_vis = false;
m_stats[i].num_visible = -1;
}
auto next = dma.read_and_advance();
ASSERT(next.size_bytes == 0);
}
while (dma.current_tag_offset() != render_state->next_bucket) {
auto x = dma.read_and_advance();
fmt::print("{} {}\n", x.vifcode0().print(), x.vifcode1().print());
ASSERT(false);
}
}
@@ -0,0 +1,23 @@
#pragma once
#include "game/graphics/opengl_renderer/BucketRenderer.h"
/*!
* The VisDataHandler copies visibility data from add-pc-port-background-data for the background
* renderers.
*/
class VisDataHandler : public BucketRenderer {
public:
VisDataHandler(const std::string& name, int my_id);
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
void draw_debug_window() override;
private:
struct LevelStats {
bool has_vis = false;
int num_visible = 0;
};
static constexpr int kMaxLevels = 10;
LevelStats m_stats[kMaxLevels];
bool m_count_vis = false;
};
@@ -60,17 +60,17 @@ void TFragment::render(DmaFollower& dma,
return;
}
if (m_my_id == render_state->bucket_for_vis_copy) {
DmaTransfer transfers[2];
if (m_my_id == render_state->bucket_for_vis_copy &&
dma.current_tag_vifcode1().kind == VifCode::Kind::PC_PORT) {
DmaTransfer transfers[20];
transfers[0] = dma.read_and_advance();
auto next0 = dma.read_and_advance();
ASSERT(next0.size_bytes == 0);
transfers[1] = dma.read_and_advance();
auto next1 = dma.read_and_advance();
ASSERT(next1.size_bytes == 0);
for (int i = 0; i < render_state->num_vis_to_copy; i++) {
transfers[i] = dma.read_and_advance();
auto next0 = dma.read_and_advance();
ASSERT(next0.size_bytes == 0);
}
for (int i = 0; i < 2; i++) {
for (int i = 0; i < render_state->num_vis_to_copy; i++) {
if (transfers[i].size_bytes == 128 * 16) {
if (render_state->use_occlusion_culling) {
render_state->occlusion_vis[i].valid = true;
+1
View File
@@ -81,6 +81,7 @@ enum class BucketId {
namespace jak2 {
enum class BucketId {
SPECIAL_BUCKET_2 = 2,
TFRAG_L0_TFRAG = 8,
TIE_L0_TFRAG = 9,
TFRAG_L1_TFRAG = 19,
@@ -229,13 +229,68 @@
(none)
)
(defun add-pc-port-background-data ((dma-buf dma-buffer))
"PC Port added"
;; loop over levels
(dotimes (lev-idx 6)
(let ((lev (-> *level* draw-level lev-idx))
(dma-start (-> dma-buf base)))
(cond
((and lev (= (-> lev status) 'active))
;; the level is active.
(let ((packet (the-as dma-packet (-> dma-buf base))))
(set! (-> packet dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc 128))
(set! (-> packet vif0) (new 'static 'vif-tag))
(set! (-> packet vif1) (new 'static 'vif-tag :cmd (vif-cmd pc-port)))
(set! (-> dma-buf base) (the pointer (&+ packet 16)))
)
(quad-copy! (-> dma-buf base) (-> lev vis-bits) 128)
(&+! (-> dma-buf base) (* 16 128))
)
(else
(let ((packet (the-as dma-packet (-> dma-buf base))))
(set! (-> packet dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc 1))
(set! (-> packet vif0) (new 'static 'vif-tag))
(set! (-> packet vif1) (new 'static 'vif-tag :cmd (vif-cmd pc-port)))
(set! (-> dma-buf base) (the pointer (&+ packet 16)))
)
(set! (-> (the (pointer uint128) (-> dma-buf base))) (the uint128 0))
(&+! (-> dma-buf base) (* 16 1))
)
)
(let ((a3-3 (-> dma-buf base)))
(let ((v1-38 (the-as object (-> dma-buf base))))
(set! (-> (the-as dma-packet v1-38) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
(set! (-> (the-as dma-packet v1-38) vif0) (new 'static 'vif-tag))
(set! (-> (the-as dma-packet v1-38) vif1) (new 'static 'vif-tag))
(set! (-> dma-buf base) (&+ (the-as pointer v1-38) 16))
)
(dma-bucket-insert-tag (-> *display* frames (-> *display* on-screen) bucket-group)
(bucket-id bucket-2)
dma-start
(the-as (pointer dma-tag) a3-3)
)
)
)
)
)
(defun finish-background ()
"Main function for drawing the background (wind, shrub, tie, tfrag)"
(#when PC_PORT
(add-pc-port-background-data
(-> *display* frames (-> *display* on-screen) global-buf)
)
)
(if (-> *blit-displays-work* menu-mode)
(return #f)
)
;; update wind!
(when (not (paused?))
(flush-cache 0)