summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/VertexManagerBase.cpp
diff options
context:
space:
mode:
authoriwubcode <iwubcode@users.noreply.github.com>2022-09-18 01:00:42 -0500
committeriwubcode <iwubcode@users.noreply.github.com>2023-08-20 18:53:27 -0500
commitd32036695483583b0aa17ad454972f8a01222682 (patch)
tree5e2e9040159cc07e1d9b10c0a94e6d52a8bb32a8 /Source/Core/VideoCommon/VertexManagerBase.cpp
parentbedbf2b8c6fbf5485ba773b3ff96aa632c2780d2 (diff)
VideoCommon: add custom shader cache to VertexManagerBase, supporting custom pixel shaders by replacing the existing pipeline with a modified one
Diffstat (limited to 'Source/Core/VideoCommon/VertexManagerBase.cpp')
-rw-r--r--Source/Core/VideoCommon/VertexManagerBase.cpp92
1 files changed, 88 insertions, 4 deletions
diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp
index 0b184e1da9..92e5be9952 100644
--- a/Source/Core/VideoCommon/VertexManagerBase.cpp
+++ b/Source/Core/VideoCommon/VertexManagerBase.cpp
@@ -23,12 +23,14 @@
#include "VideoCommon/DataReader.h"
#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/GeometryShaderManager.h"
+#include "VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.h"
#include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModActionData.h"
#include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModManager.h"
#include "VideoCommon/IndexGenerator.h"
#include "VideoCommon/NativeVertexFormat.h"
#include "VideoCommon/OpcodeDecoding.h"
#include "VideoCommon/PerfQueryBase.h"
+#include "VideoCommon/PixelShaderGen.h"
#include "VideoCommon/PixelShaderManager.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/TextureCacheBase.h"
@@ -106,6 +108,7 @@ bool VertexManagerBase::Initialize()
{
m_frame_end_event = AfterFrameEvent::Register([this] { OnEndFrame(); }, "VertexManagerBase");
m_index_generator.Init();
+ m_custom_shader_cache = std::make_unique<CustomShaderCache>();
m_cpu_cull.Init();
return true;
}
@@ -527,6 +530,7 @@ void VertexManagerBase::Flush()
// Calculate ZSlope for zfreeze
const auto used_textures = UsedTextures();
std::vector<std::string> texture_names;
+ std::vector<u32> texture_units;
if (!m_cull_all)
{
if (!g_ActiveConfig.bGraphicMods)
@@ -543,7 +547,12 @@ void VertexManagerBase::Flush()
const auto cache_entry = g_texture_cache->Load(TextureInfo::FromStage(i));
if (cache_entry)
{
- texture_names.push_back(cache_entry->texture_info_name);
+ if (std::find(texture_names.begin(), texture_names.end(),
+ cache_entry->texture_info_name) == texture_names.end())
+ {
+ texture_names.push_back(cache_entry->texture_info_name);
+ texture_units.push_back(i);
+ }
}
}
}
@@ -562,13 +571,24 @@ void VertexManagerBase::Flush()
if (!m_cull_all)
{
- for (const auto& texture_name : texture_names)
+ CustomPixelShaderContents custom_pixel_shader_contents;
+ std::optional<CustomPixelShader> custom_pixel_shader;
+ std::vector<std::string> custom_pixel_texture_names;
+ for (int i = 0; i < texture_names.size(); i++)
{
+ const std::string& texture_name = texture_names[i];
+ const u32 texture_unit = texture_units[i];
bool skip = false;
- GraphicsModActionData::DrawStarted draw_started{&skip};
+ GraphicsModActionData::DrawStarted draw_started{texture_unit, &skip, &custom_pixel_shader};
for (const auto& action : g_graphics_mod_manager->GetDrawStartedActions(texture_name))
{
action->OnDrawStarted(&draw_started);
+ if (custom_pixel_shader)
+ {
+ custom_pixel_shader_contents.shaders.push_back(*custom_pixel_shader);
+ custom_pixel_texture_names.push_back(texture_name);
+ }
+ custom_pixel_shader = std::nullopt;
}
if (skip == true)
return;
@@ -610,7 +630,65 @@ void VertexManagerBase::Flush()
UpdatePipelineObject();
if (m_current_pipeline_object)
{
- g_gfx->SetPipeline(m_current_pipeline_object);
+ const AbstractPipeline* current_pipeline = m_current_pipeline_object;
+ if (!custom_pixel_shader_contents.shaders.empty())
+ {
+ CustomShaderInstance custom_shaders;
+ custom_shaders.pixel_contents = std::move(custom_pixel_shader_contents);
+
+ switch (g_ActiveConfig.iShaderCompilationMode)
+ {
+ case ShaderCompilationMode::Synchronous:
+ case ShaderCompilationMode::AsynchronousSkipRendering:
+ {
+ if (auto pipeline = m_custom_shader_cache->GetPipelineAsync(
+ m_current_pipeline_config, custom_shaders, m_current_pipeline_object->m_config))
+ {
+ current_pipeline = *pipeline;
+ }
+ }
+ break;
+ case ShaderCompilationMode::SynchronousUberShaders:
+ {
+ // D3D has issues compiling large custom ubershaders
+ // use specialized shaders instead
+ if (g_ActiveConfig.backend_info.api_type == APIType::D3D)
+ {
+ if (auto pipeline = m_custom_shader_cache->GetPipelineAsync(
+ m_current_pipeline_config, custom_shaders, m_current_pipeline_object->m_config))
+ {
+ current_pipeline = *pipeline;
+ }
+ }
+ else
+ {
+ if (auto pipeline = m_custom_shader_cache->GetPipelineAsync(
+ m_current_uber_pipeline_config, custom_shaders,
+ m_current_pipeline_object->m_config))
+ {
+ current_pipeline = *pipeline;
+ }
+ }
+ }
+ break;
+ case ShaderCompilationMode::AsynchronousUberShaders:
+ {
+ if (auto pipeline = m_custom_shader_cache->GetPipelineAsync(
+ m_current_pipeline_config, custom_shaders, m_current_pipeline_object->m_config))
+ {
+ current_pipeline = *pipeline;
+ }
+ else if (auto uber_pipeline = m_custom_shader_cache->GetPipelineAsync(
+ m_current_uber_pipeline_config, custom_shaders,
+ m_current_pipeline_object->m_config))
+ {
+ current_pipeline = *uber_pipeline;
+ }
+ }
+ break;
+ };
+ }
+ g_gfx->SetPipeline(current_pipeline);
if (PerfQueryBase::ShouldEmulate())
g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
@@ -1006,3 +1084,9 @@ void VertexManagerBase::OnEndFrame()
// state changes the specialized shader will not take over.
InvalidatePipelineObject();
}
+
+void VertexManagerBase::NotifyCustomShaderCacheOfHostChange(const ShaderHostConfig& host_config)
+{
+ m_custom_shader_cache->SetHostConfig(host_config);
+ m_custom_shader_cache->Reload();
+}