diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 67f46c74bc..c1eae73e24 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -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 diff --git a/game/graphics/opengl_renderer/BucketRenderer.h b/game/graphics/opengl_renderer/BucketRenderer.h index 4a0def8def..4e09832036 100644 --- a/game/graphics/opengl_renderer/BucketRenderer.h +++ b/game/graphics/opengl_renderer/BucketRenderer.h @@ -39,7 +39,6 @@ struct SharedRenderState { bool use_sky_cpu = true; bool use_occlusion_culling = true; - bool enable_merc_xgkick = true; math::Vector fog_color = math::Vector{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; }; diff --git a/game/graphics/opengl_renderer/OpenGLRenderer.cpp b/game/graphics/opengl_renderer/OpenGLRenderer.cpp index d3c0c6baea..352c24091f 100644 --- a/game/graphics/opengl_renderer/OpenGLRenderer.cpp +++ b/game/graphics/opengl_renderer/OpenGLRenderer.cpp @@ -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("vis", BucketCategory::OTHER, BucketId::SPECIAL_BUCKET_2); init_bucket_renderer("tfrag-l0-tfrag", BucketCategory::TFRAG, BucketId::TFRAG_L0_TFRAG, std::vector{tfrag3::TFragmentTreeKind::NORMAL}, false, 0); init_bucket_renderer("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]; diff --git a/game/graphics/opengl_renderer/VisDataHandler.cpp b/game/graphics/opengl_renderer/VisDataHandler.cpp new file mode 100644 index 0000000000..146d0e51df --- /dev/null +++ b/game/graphics/opengl_renderer/VisDataHandler.cpp @@ -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); + } +} diff --git a/game/graphics/opengl_renderer/VisDataHandler.h b/game/graphics/opengl_renderer/VisDataHandler.h new file mode 100644 index 0000000000..d371ef8849 --- /dev/null +++ b/game/graphics/opengl_renderer/VisDataHandler.h @@ -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; +}; diff --git a/game/graphics/opengl_renderer/background/TFragment.cpp b/game/graphics/opengl_renderer/background/TFragment.cpp index 3285bf40d1..1e08ba7496 100644 --- a/game/graphics/opengl_renderer/background/TFragment.cpp +++ b/game/graphics/opengl_renderer/background/TFragment.cpp @@ -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; diff --git a/game/graphics/opengl_renderer/buckets.h b/game/graphics/opengl_renderer/buckets.h index d52e26ed01..d525ef0974 100644 --- a/game/graphics/opengl_renderer/buckets.h +++ b/game/graphics/opengl_renderer/buckets.h @@ -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, diff --git a/goal_src/jak2/engine/gfx/background/background.gc b/goal_src/jak2/engine/gfx/background/background.gc index 40a7fbb150..526ca690b7 100644 --- a/goal_src/jak2/engine/gfx/background/background.gc +++ b/goal_src/jak2/engine/gfx/background/background.gc @@ -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)