diff --git a/Source/Core/VideoCommon/HiresTextures.cpp b/Source/Core/VideoCommon/HiresTextures.cpp index 96b340772f..9636bfe651 100644 --- a/Source/Core/VideoCommon/HiresTextures.cpp +++ b/Source/Core/VideoCommon/HiresTextures.cpp @@ -213,7 +213,7 @@ void HiresTexture::Prefetch() 10000); } -std::string HiresTexture::GenBaseName(TextureInfo& texture_info, bool dump) +std::string HiresTexture::GenBaseName(const TextureInfo& texture_info, bool dump) { if (!dump && s_textureMap.empty()) return ""; @@ -261,7 +261,7 @@ u32 HiresTexture::CalculateMipCount(u32 width, u32 height) return mip_count; } -std::shared_ptr HiresTexture::Search(TextureInfo& texture_info) +std::shared_ptr HiresTexture::Search(const TextureInfo& texture_info) { const std::string base_filename = GenBaseName(texture_info); diff --git a/Source/Core/VideoCommon/HiresTextures.h b/Source/Core/VideoCommon/HiresTextures.h index 78e40460db..bcd889e18c 100644 --- a/Source/Core/VideoCommon/HiresTextures.h +++ b/Source/Core/VideoCommon/HiresTextures.h @@ -25,9 +25,9 @@ public: static void Clear(); static void Shutdown(); - static std::shared_ptr Search(TextureInfo& texture_info); + static std::shared_ptr Search(const TextureInfo& texture_info); - static std::string GenBaseName(TextureInfo& texture_info, bool dump = false); + static std::string GenBaseName(const TextureInfo& texture_info, bool dump = false); static u32 CalculateMipCount(u32 width, u32 height); diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index dbad9711f1..b13f74542c 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -67,6 +67,7 @@ #include "VideoCommon/FramebufferManager.h" #include "VideoCommon/FramebufferShaderGen.h" #include "VideoCommon/FreeLookCamera.h" +#include "VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.h" #include "VideoCommon/NetPlayChatUI.h" #include "VideoCommon/NetPlayGolfUI.h" #include "VideoCommon/OnScreenDisplay.h" @@ -1309,6 +1310,11 @@ void Renderer::Swap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, u6 // behind the renderer. FlushFrameDump(); + if (g_ActiveConfig.bGraphicMods) + { + m_graphics_mod_manager.EndOfFrame(); + } + if (xfb_addr && fb_width && fb_stride && fb_height) { // Get the current XFB from texture cache @@ -1830,3 +1836,8 @@ std::unique_ptr Renderer::CreateAsyncShaderCom { return std::make_unique(); } + +const GraphicsModManager& Renderer::GetGraphicsModManager() const +{ + return m_graphics_mod_manager; +} diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 380225b133..403d028525 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -30,6 +30,7 @@ #include "VideoCommon/BPMemory.h" #include "VideoCommon/FPSCounter.h" #include "VideoCommon/FrameDump.h" +#include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModManager.h" #include "VideoCommon/RenderState.h" #include "VideoCommon/TextureConfig.h" @@ -268,6 +269,8 @@ public: // Will forcibly reload all textures on the next swap void ForceReloadTextures(); + const GraphicsModManager& GetGraphicsModManager() const; + protected: // Bitmask containing information about which configuration has changed for the backend. enum ConfigChangeBits : u32 @@ -447,6 +450,8 @@ private: std::unique_ptr m_netplay_chat_ui; Common::Flag m_force_reload_textures; + + GraphicsModManager m_graphics_mod_manager; }; extern std::unique_ptr g_renderer; diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 195e4f9443..3bd6e2ae52 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -36,6 +36,7 @@ #include "VideoCommon/AbstractStagingTexture.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/FramebufferManager.h" +#include "VideoCommon/GraphicsModSystem/Runtime/FBInfo.h" #include "VideoCommon/HiresTextures.h" #include "VideoCommon/OpcodeDecoding.h" #include "VideoCommon/PixelShaderManager.h" @@ -255,6 +256,7 @@ void TextureCacheBase::SetBackupConfig(const VideoConfig& config) backup_config.gpu_texture_decoding = config.bEnableGPUTextureDecoding; backup_config.disable_vram_copies = config.bDisableCopyToVRAM; backup_config.arbitrary_mipmap_detection = config.bArbitraryMipmapDetection; + backup_config.graphics_mods = config.bGraphicMods; } TextureCacheBase::TCacheEntry* @@ -1205,15 +1207,15 @@ private: std::vector levels; }; -TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) +TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const TextureInfo& texture_info) { // if this stage was not invalidated by changes to texture registers, keep the current texture - if (TMEM::IsValid(stage) && bound_textures[stage]) + if (TMEM::IsValid(texture_info.GetStage()) && bound_textures[texture_info.GetStage()]) { - TCacheEntry* entry = bound_textures[stage]; + TCacheEntry* entry = bound_textures[texture_info.GetStage()]; // If the TMEM configuration is such that this texture is more or less guaranteed to still // be in TMEM, then we know we can reuse the old entry without even hashing the memory - if (TMEM::IsCached(stage)) + if (TMEM::IsCached(texture_info.GetStage())) { return entry; } @@ -1226,26 +1228,29 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage) } } - TextureInfo texture_info = TextureInfo::FromStage(stage); - auto entry = GetTexture(g_ActiveConfig.iSafeTextureCache_ColorSamples, texture_info); if (!entry) return nullptr; entry->frameCount = FRAMECOUNT_INVALID; - bound_textures[stage] = entry; + if (entry->texture_info_name.empty() && g_ActiveConfig.bGraphicMods) + { + entry->texture_info_name = texture_info.CalculateTextureName().GetFullName(); + } + bound_textures[texture_info.GetStage()] = entry; // We need to keep track of invalided textures until they have actually been replaced or // re-loaded - TMEM::Bind(stage, entry->NumBlocksX(), entry->NumBlocksY(), entry->GetNumLevels() > 1, - entry->format == TextureFormat::RGBA8); + TMEM::Bind(texture_info.GetStage(), entry->NumBlocksX(), entry->NumBlocksY(), + entry->GetNumLevels() > 1, entry->format == TextureFormat::RGBA8); return entry; } TextureCacheBase::TCacheEntry* -TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, TextureInfo& texture_info) +TextureCacheBase::GetTexture(const int textureCacheSafetyColorSampleSize, + const TextureInfo& texture_info) { u32 expanded_width = texture_info.GetExpandedWidth(); u32 expanded_height = texture_info.GetExpandedHeight(); @@ -2119,6 +2124,35 @@ void TextureCacheBase::CopyRenderTargetToTexture( const u32 bytes_per_row = num_blocks_x * bytes_per_block; const u32 covered_range = num_blocks_y * dstStride; + if (g_ActiveConfig.bGraphicMods) + { + FBInfo info; + info.m_width = tex_w; + info.m_height = tex_h; + info.m_texture_format = baseFormat; + if (is_xfb_copy) + { + for (const auto action : g_renderer->GetGraphicsModManager().GetXFBActions(info)) + { + action->OnXFB(); + } + } + else + { + bool skip = false; + for (const auto action : g_renderer->GetGraphicsModManager().GetEFBActions(info)) + { + action->OnEFB(&skip, tex_w, tex_h, &scaled_tex_w, &scaled_tex_h); + } + if (skip == true) + { + if (copy_to_ram) + UninitializeEFBMemory(dst, dstStride, bytes_per_row, num_blocks_y); + return; + } + } + } + if (dstStride < bytes_per_row) { // This kind of efb copy results in a scrambled image. diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 3247c9f929..61cc612eed 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -155,6 +155,8 @@ public: u32 pending_efb_copy_height = 0; bool pending_efb_copy_invalidated = false; + std::string texture_info_name = ""; + explicit TCacheEntry(std::unique_ptr tex, std::unique_ptr fb); @@ -239,8 +241,9 @@ public: void Invalidate(); - TCacheEntry* Load(const u32 stage); - TCacheEntry* GetTexture(const int textureCacheSafetyColorSampleSize, TextureInfo& texture_info); + TCacheEntry* Load(const TextureInfo& texture_info); + TCacheEntry* GetTexture(const int textureCacheSafetyColorSampleSize, + const TextureInfo& texture_info); TCacheEntry* GetXFBTexture(u32 address, u32 width, u32 height, u32 stride, MathUtil::Rectangle* display_rect); @@ -374,6 +377,7 @@ private: bool gpu_texture_decoding; bool disable_vram_copies; bool arbitrary_mipmap_detection; + bool graphics_mods; }; BackupConfig backup_config = {}; diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index 72f02927b5..b3d6f86686 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -7,7 +7,6 @@ #include #include -#include "Common/BitSet.h" #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Common/EnumMap.h" @@ -30,6 +29,7 @@ #include "VideoCommon/RenderBase.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/TextureCacheBase.h" +#include "VideoCommon/TextureInfo.h" #include "VideoCommon/VertexLoaderManager.h" #include "VideoCommon/VertexShaderManager.h" #include "VideoCommon/VideoBackendBase.h" @@ -337,7 +337,7 @@ bool VertexManagerBase::UploadTexelBuffer(const void* data, u32 data_size, Texel return false; } -void VertexManagerBase::LoadTextures() +BitSet32 VertexManagerBase::UsedTextures() const { BitSet32 usedtextures; for (u32 i = 0; i < bpmem.genMode.numtevstages + 1u; ++i) @@ -349,10 +349,7 @@ void VertexManagerBase::LoadTextures() if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) usedtextures[bpmem.tevindref.getTexMap(bpmem.tevind[i].bt)] = true; - for (unsigned int i : usedtextures) - g_texture_cache->Load(i); - - g_texture_cache->BindTextures(usedtextures); + return usedtextures; } void VertexManagerBase::Flush() @@ -455,7 +452,30 @@ void VertexManagerBase::Flush() CalculateBinormals(VertexLoaderManager::GetCurrentVertexFormat()); // Calculate ZSlope for zfreeze - VertexShaderManager::SetConstants(); + const auto used_textures = UsedTextures(); + std::vector texture_names; + if (!m_cull_all) + { + if (!g_ActiveConfig.bGraphicMods) + { + for (const u32 i : used_textures) + { + g_texture_cache->Load(TextureInfo::FromStage(i)); + } + } + else + { + for (const u32 i : used_textures) + { + const auto cache_entry = g_texture_cache->Load(TextureInfo::FromStage(i)); + if (cache_entry) + { + texture_names.push_back(cache_entry->texture_info_name); + } + } + } + } + VertexShaderManager::SetConstants(texture_names); if (!bpmem.genMode.zfreeze) { // Must be done after VertexShaderManager::SetConstants() @@ -469,6 +489,18 @@ void VertexManagerBase::Flush() if (!m_cull_all) { + for (const auto& texture_name : texture_names) + { + bool skip = false; + for (const auto action : + g_renderer->GetGraphicsModManager().GetDrawStartedActions(texture_name)) + { + action->OnDrawStarted(&skip); + } + if (skip == true) + return; + } + // Now the vertices can be flushed to the GPU. Everything following the CommitBuffer() call // must be careful to not upload any utility vertices, as the binding will be lost otherwise. const u32 num_indices = m_index_generator.GetIndexLen(); @@ -480,7 +512,7 @@ void VertexManagerBase::Flush() // Texture loading can cause palettes to be applied (-> uniforms -> draws). // Palette application does not use vertices, only a full-screen quad, so this is okay. // Same with GPU texture decoding, which uses compute shaders. - LoadTextures(); + g_texture_cache->BindTextures(used_textures); // Now we can upload uniforms, as nothing else will override them. GeometryShaderManager::SetConstants(); diff --git a/Source/Core/VideoCommon/VertexManagerBase.h b/Source/Core/VideoCommon/VertexManagerBase.h index e4d029e9c7..7efdec2ebd 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.h +++ b/Source/Core/VideoCommon/VertexManagerBase.h @@ -6,6 +6,7 @@ #include #include +#include "Common/BitSet.h" #include "Common/CommonTypes.h" #include "Common/MathUtil.h" #include "VideoCommon/IndexGenerator.h" @@ -173,7 +174,8 @@ protected: void CalculateZSlope(NativeVertexFormat* format); void CalculateBinormals(NativeVertexFormat* format); - void LoadTextures(); + + BitSet32 UsedTextures() const; u8* m_cur_buffer_pointer = nullptr; u8* m_base_buffer_pointer = nullptr; diff --git a/Source/Core/VideoCommon/VertexShaderManager.cpp b/Source/Core/VideoCommon/VertexShaderManager.cpp index 6a7636d587..680d1ad3ee 100644 --- a/Source/Core/VideoCommon/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/VertexShaderManager.cpp @@ -85,7 +85,7 @@ void VertexShaderManager::Dirty() // Syncs the shader constant buffers with xfmem // TODO: A cleaner way to control the matrices without making a mess in the parameters field -void VertexShaderManager::SetConstants() +void VertexShaderManager::SetConstants(const std::vector& textures) { if (constants.missing_color_hex != g_ActiveConfig.iMissingColorValue) { @@ -302,7 +302,27 @@ void VertexShaderManager::SetConstants() g_stats.AddScissorRect(); } - if (bProjectionChanged || g_freelook_camera.GetController()->IsDirty()) + std::vector projection_actions; + if (g_ActiveConfig.bGraphicMods) + { + for (const auto action : + g_renderer->GetGraphicsModManager().GetProjectionActions(xfmem.projection.type)) + { + projection_actions.push_back(action); + } + + for (const auto& texture : textures) + { + for (const auto action : g_renderer->GetGraphicsModManager().GetProjectionTextureActions( + xfmem.projection.type, texture)) + { + projection_actions.push_back(action); + } + } + } + + if (bProjectionChanged || g_freelook_camera.GetController()->IsDirty() || + !projection_actions.empty()) { bProjectionChanged = false; @@ -384,6 +404,11 @@ void VertexShaderManager::SetConstants() if (g_freelook_camera.IsActive() && xfmem.projection.type == ProjectionType::Perspective) corrected_matrix *= g_freelook_camera.GetView(); + for (auto action : projection_actions) + { + action->OnProjection(&corrected_matrix); + } + memcpy(constants.projection.data(), corrected_matrix.data.data(), 4 * sizeof(float4)); g_freelook_camera.GetController()->SetClean(); diff --git a/Source/Core/VideoCommon/VertexShaderManager.h b/Source/Core/VideoCommon/VertexShaderManager.h index 90df8722ac..3bddf28fb0 100644 --- a/Source/Core/VideoCommon/VertexShaderManager.h +++ b/Source/Core/VideoCommon/VertexShaderManager.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include "Common/CommonTypes.h" #include "VideoCommon/ConstantManager.h" @@ -19,7 +20,7 @@ public: static void DoState(PointerWrap& p); // constant management - static void SetConstants(); + static void SetConstants(const std::vector& textures); static void InvalidateXFRange(int start, int end); static void SetTexMatrixChangedA(u32 value);