diff --git a/game/graphics/opengl_renderer/BucketRenderer.cpp b/game/graphics/opengl_renderer/BucketRenderer.cpp index e6e5b8dfb5..7edc882e65 100644 --- a/game/graphics/opengl_renderer/BucketRenderer.cpp +++ b/game/graphics/opengl_renderer/BucketRenderer.cpp @@ -81,6 +81,7 @@ RenderMux::RenderMux(const std::string& name, void RenderMux::render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) { + m_renderers[m_render_idx]->enabled() = m_enabled; m_renderers[m_render_idx]->render(dma, render_state, prof); } diff --git a/game/graphics/opengl_renderer/BucketRenderer.h b/game/graphics/opengl_renderer/BucketRenderer.h index 23f588b588..bc991d7268 100644 --- a/game/graphics/opengl_renderer/BucketRenderer.h +++ b/game/graphics/opengl_renderer/BucketRenderer.h @@ -66,6 +66,7 @@ struct LevelVis { u8 data[2048]; }; +class EyeRenderer; /*! * The main renderer will contain a single SharedRenderState that's passed to all bucket renderers. * This allows bucket renders to share textures and shaders. @@ -99,6 +100,8 @@ struct SharedRenderState { LevelVis occlusion_vis[2]; math::Vector4f camera_planes[4]; + EyeRenderer* eye_renderer = nullptr; + std::string load_status_debug; }; diff --git a/game/graphics/opengl_renderer/EyeRenderer.h b/game/graphics/opengl_renderer/EyeRenderer.h index 29f9a984f7..5486ff1cff 100644 --- a/game/graphics/opengl_renderer/EyeRenderer.h +++ b/game/graphics/opengl_renderer/EyeRenderer.h @@ -22,7 +22,7 @@ class EyeRenderer : public BucketRenderer { std::string m_debug; float m_average_time_ms = 0; - bool m_use_bilinear = false; + bool m_use_bilinear = true; bool m_alpha_hack = true; u32 m_left[SINGLE_EYE_SIZE * SINGLE_EYE_SIZE]; diff --git a/game/graphics/opengl_renderer/OpenGLRenderer.cpp b/game/graphics/opengl_renderer/OpenGLRenderer.cpp index e332b09051..fffc7b6017 100644 --- a/game/graphics/opengl_renderer/OpenGLRenderer.cpp +++ b/game/graphics/opengl_renderer/OpenGLRenderer.cpp @@ -181,9 +181,11 @@ void OpenGLRenderer::init_bucket_renderers() { init_bucket_renderer("l1-pris-merc", BucketId::MERC_PRIS_LEVEL1); // 52 init_bucket_renderer("l1-pris-generic", BucketId::GENERIC_PRIS_LEVEL1); // 53 - init_bucket_renderer("common-pris-eyes", BucketId::MERC_EYES_AFTER_PRIS); // 54 - init_bucket_renderer("common-pris-merc", BucketId::MERC_AFTER_PRIS); // 55 - init_bucket_renderer("common-pris-generic", BucketId::GENERIC_PRIS); // 56 + // other renderers may output to the eye renderer + m_render_state.eye_renderer = + init_bucket_renderer("common-pris-eyes", BucketId::MERC_EYES_AFTER_PRIS); // 54 + init_bucket_renderer("common-pris-merc", BucketId::MERC_AFTER_PRIS); // 55 + init_bucket_renderer("common-pris-generic", BucketId::GENERIC_PRIS); // 56 //----------------------- // LEVEL 0 water texture diff --git a/game/graphics/opengl_renderer/OpenGLRenderer.h b/game/graphics/opengl_renderer/OpenGLRenderer.h index 025338b025..be7cd6459a 100644 --- a/game/graphics/opengl_renderer/OpenGLRenderer.h +++ b/game/graphics/opengl_renderer/OpenGLRenderer.h @@ -36,8 +36,11 @@ class OpenGLRenderer { void finish_screenshot(const std::string& output_name, int px, int py, int x, int y); template - void init_bucket_renderer(const std::string& name, BucketId id, Args&&... args) { - m_bucket_renderers.at((int)id) = std::make_unique(name, id, std::forward(args)...); + T* init_bucket_renderer(const std::string& name, BucketId id, Args&&... args) { + auto renderer = std::make_unique(name, id, std::forward(args)...); + T* ret = renderer.get(); + m_bucket_renderers.at((int)id) = std::move(renderer); + return ret; } SharedRenderState m_render_state; diff --git a/game/graphics/opengl_renderer/TextureUploadHandler.cpp b/game/graphics/opengl_renderer/TextureUploadHandler.cpp index 7edb4bdcb9..ec170635de 100644 --- a/game/graphics/opengl_renderer/TextureUploadHandler.cpp +++ b/game/graphics/opengl_renderer/TextureUploadHandler.cpp @@ -3,24 +3,28 @@ #include "TextureUploadHandler.h" #include "game/graphics/pipelines/opengl.h" +#include "game/graphics/opengl_renderer/EyeRenderer.h" TextureUploadHandler::TextureUploadHandler(const std::string& name, BucketId my_id) : BucketRenderer(name, my_id) {} void TextureUploadHandler::render(DmaFollower& dma, SharedRenderState* render_state, - ScopedProfilerNode& /*prof*/) { + ScopedProfilerNode& prof) { // this is the data we get from the PC Port modification. - struct TextureUpload { - u64 page; - s64 mode; - }; - std::vector uploads; // loop through all data, grabbing buckets while (dma.current_tag_offset() != render_state->next_bucket) { auto dma_tag = dma.current_tag(); + + // does it look like data to do eye rendering? + if (dma_tag.qwc == (128 / 16)) { + // note: these uploads may have texture that we need for eye rendering. + flush_uploads(uploads, render_state); + render_state->eye_renderer->handle_eye_dma2(dma, render_state, prof); + } + auto data = dma.read_and_advance(); if (data.size_bytes == 0 && data.vif0() == 0 && data.vif1() == 0) { continue; @@ -44,37 +48,46 @@ void TextureUploadHandler::render(DmaFollower& dma, } } - // NOTE: we don't actually copy the textures in the dma chain copying because they aren't - // reference by DMA tag. So there's the potential for race conditions if the game gets messed - // up and corrupts the texture memory. - const u8* ee_mem = (const u8*)render_state->ee_main_memory; - - if (uploads.size() == 2 && uploads[0].mode == 2 && uploads[1].mode == -2 && - uploads[0].page == uploads[1].page) { - render_state->texture_pool->handle_upload_now(ee_mem + uploads[0].page, -2, ee_mem, - render_state->offset_of_s7); - render_state->texture_pool->handle_upload_now(ee_mem + uploads[0].page, 2, ee_mem, - render_state->offset_of_s7); - } else if (uploads.size() == 1 && uploads[0].mode == -1) { - render_state->texture_pool->handle_upload_now(ee_mem + uploads[0].page, -1, ee_mem, - render_state->offset_of_s7); - } else if (uploads.size() == 1 && uploads[0].mode == -2) { - render_state->texture_pool->handle_upload_now(ee_mem + uploads[0].page, -2, ee_mem, - render_state->offset_of_s7); - } else if (uploads.size() == 1 && uploads[0].mode == 0) { - render_state->texture_pool->handle_upload_now(ee_mem + uploads[0].page, 0, ee_mem, - render_state->offset_of_s7); - } - - else if (uploads.empty()) { - // do nothing. - } else { - fmt::print("unhandled upload sequence in {}:\n", m_name); - for (auto& upload : uploads) { - fmt::print(" page: 0x{:x} mode: {}\n", upload.page, upload.mode); - } - ASSERT(false); - } + flush_uploads(uploads, render_state); } -void TextureUploadHandler::draw_debug_window() {} +void TextureUploadHandler::flush_uploads(std::vector& uploads, + SharedRenderState* render_state) { + if (m_fake_uploads) { + uploads.clear(); + } else { + // NOTE: we don't actually copy the textures in the dma chain copying because they aren't + // reference by DMA tag. So there's the potential for race conditions if the game gets messed + // up and corrupts the texture memory. + const u8* ee_mem = (const u8*)render_state->ee_main_memory; + if (uploads.size() == 2 && uploads[0].mode == 2 && uploads[1].mode == -2 && + uploads[0].page == uploads[1].page) { + render_state->texture_pool->handle_upload_now(ee_mem + uploads[0].page, -2, ee_mem, + render_state->offset_of_s7); + render_state->texture_pool->handle_upload_now(ee_mem + uploads[0].page, 2, ee_mem, + render_state->offset_of_s7); + } else if (uploads.size() == 1 && uploads[0].mode == -1) { + render_state->texture_pool->handle_upload_now(ee_mem + uploads[0].page, -1, ee_mem, + render_state->offset_of_s7); + } else if (uploads.size() == 1 && uploads[0].mode == -2) { + render_state->texture_pool->handle_upload_now(ee_mem + uploads[0].page, -2, ee_mem, + render_state->offset_of_s7); + } else if (uploads.size() == 1 && uploads[0].mode == 0) { + render_state->texture_pool->handle_upload_now(ee_mem + uploads[0].page, 0, ee_mem, + render_state->offset_of_s7); + } + + else if (uploads.empty()) { + // do nothing. + } else { + fmt::print("unhandled upload sequence in {}:\n", m_name); + for (auto& upload : uploads) { + fmt::print(" page: 0x{:x} mode: {}\n", upload.page, upload.mode); + } + ASSERT(false); + } + } +} +void TextureUploadHandler::draw_debug_window() { + ImGui::Checkbox("Fake Uploads", &m_fake_uploads); +} diff --git a/game/graphics/opengl_renderer/TextureUploadHandler.h b/game/graphics/opengl_renderer/TextureUploadHandler.h index 4e1e45d928..02e5ca8086 100644 --- a/game/graphics/opengl_renderer/TextureUploadHandler.h +++ b/game/graphics/opengl_renderer/TextureUploadHandler.h @@ -5,15 +5,20 @@ /*! * The TextureUploadHandler receives textures uploads in the DMA chain and updates the TexturePool. - * It will attempt to cache textures when possible as converting and uploading them to the GPU is - * pretty expensive. - * - * Note that the PC Port sends a somewhat simplified texture upload message and this can't handle - * any arbitrary PS2 texture transfer. We rely on the texture metadata in GOAL to simplify this. + * The actual textures are preconverted and provided by the loader, so this just updates tables that + * tell the renderers which OpenGL texture goes with PS2 VRAM addresses. */ class TextureUploadHandler : public BucketRenderer { public: TextureUploadHandler(const std::string& name, BucketId my_id); void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override; void draw_debug_window() override; + + private: + struct TextureUpload { + u64 page; + s64 mode; + }; + void flush_uploads(std::vector& uploads, SharedRenderState* render_state); + bool m_fake_uploads = false; }; diff --git a/game/graphics/texture/TexturePool.cpp b/game/graphics/texture/TexturePool.cpp index b0c4ddadbb..bdb9684826 100644 --- a/game/graphics/texture/TexturePool.cpp +++ b/game/graphics/texture/TexturePool.cpp @@ -322,7 +322,7 @@ void TexturePool::draw_debug_window() { void TexturePool::draw_debug_for_tex(const std::string& name, GpuTexture* tex, u32 slot) { if (tex->is_placeholder) { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8, 0.3, 0.3, 1.0)); - } else if (tex->slots.size() == 1) { + } else if (tex->gpu_textures.size() == 1) { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.3, 0.8, 0.3, 1.0)); } else { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8, 0.8, 0.3, 1.0)); diff --git a/goal_src/engine/gfx/eye.gc b/goal_src/engine/gfx/eye.gc index 8548e0e88f..e5f39fe7d7 100644 --- a/goal_src/engine/gfx/eye.gc +++ b/goal_src/engine/gfx/eye.gc @@ -894,12 +894,11 @@ ) (dma-bucket-insert-tag (-> *display* frames (-> *display* on-screen) frame bucket-group) - (bucket-id merc-eyes) - ; (the-as bucket-id (if (zero? (-> s5-3 level)) - ; 48 - ; 51 - ; ) - ; ) + (the-as bucket-id (if (zero? (-> s5-3 level)) + (bucket-id pris-tex0) + (bucket-id pris-tex1) + ) + ) s4-0 (the-as (pointer dma-tag) a3-6) )