summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.h
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2023-08-22 02:18:40 +0200
committerGitHub <noreply@github.com>2023-08-22 02:18:40 +0200
commitdbe6a5f7e4caca71de9d9ba86916f82c0bc21683 (patch)
tree84fd8c6f664f1df62350f9d7b5aa9d110b6aee02 /Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.h
parent3451cb1ca2583f9c2b02d0d216355047787c134b (diff)
parent55061216855af89f21eee1174fa81d927bc94991 (diff)
Merge pull request #11300 from iwubcode/custom-shaders
VideoCommon: add a graphics mod action that allows you to modify the game's base rendering
Diffstat (limited to 'Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.h')
-rw-r--r--Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.h144
1 files changed, 144 insertions, 0 deletions
diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.h b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.h
new file mode 100644
index 0000000000..ff2aba2823
--- /dev/null
+++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.h
@@ -0,0 +1,144 @@
+// Copyright 2022 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <array>
+#include <list>
+#include <map>
+#include <memory>
+#include <optional>
+#include <string>
+#include <string_view>
+
+#include "VideoCommon/AbstractPipeline.h"
+#include "VideoCommon/AbstractShader.h"
+#include "VideoCommon/AsyncShaderCompiler.h"
+#include "VideoCommon/GXPipelineTypes.h"
+#include "VideoCommon/PixelShaderGen.h"
+#include "VideoCommon/ShaderGenCommon.h"
+#include "VideoCommon/UberShaderPixel.h"
+#include "VideoCommon/VideoEvents.h"
+
+struct CustomShaderInstance
+{
+ CustomPixelShaderContents pixel_contents;
+
+ bool operator==(const CustomShaderInstance& other) const = default;
+};
+
+class CustomShaderCache
+{
+public:
+ CustomShaderCache();
+ ~CustomShaderCache();
+ CustomShaderCache(const CustomShaderCache&) = delete;
+ CustomShaderCache(CustomShaderCache&&) = delete;
+ CustomShaderCache& operator=(const CustomShaderCache&) = delete;
+ CustomShaderCache& operator=(CustomShaderCache&&) = delete;
+
+ // Changes the shader host config. Shaders should be reloaded afterwards.
+ void SetHostConfig(const ShaderHostConfig& host_config) { m_host_config.bits = host_config.bits; }
+
+ // Retrieves all pending shaders/pipelines from the async compiler.
+ void RetrieveAsyncShaders();
+
+ // Reloads/recreates all shaders and pipelines.
+ void Reload();
+
+ // The optional will be empty if this pipeline is now background compiling.
+ std::optional<const AbstractPipeline*>
+ GetPipelineAsync(const VideoCommon::GXPipelineUid& uid,
+ const CustomShaderInstance& custom_shaders,
+ const AbstractPipelineConfig& pipeline_config);
+ std::optional<const AbstractPipeline*>
+ GetPipelineAsync(const VideoCommon::GXUberPipelineUid& uid,
+ const CustomShaderInstance& custom_shaders,
+ const AbstractPipelineConfig& pipeline_config);
+
+private:
+ // Configuration bits.
+ APIType m_api_type = APIType::Nothing;
+ ShaderHostConfig m_host_config = {};
+ std::unique_ptr<VideoCommon::AsyncShaderCompiler> m_async_shader_compiler;
+ std::unique_ptr<VideoCommon::AsyncShaderCompiler> m_async_uber_shader_compiler;
+
+ void AsyncCreatePipeline(const VideoCommon::GXPipelineUid& uid,
+ const CustomShaderInstance& custom_shaders,
+ const AbstractPipelineConfig& pipeline_config);
+ void AsyncCreatePipeline(const VideoCommon::GXUberPipelineUid& uid,
+ const CustomShaderInstance& custom_shaders,
+ const AbstractPipelineConfig& pipeline_config);
+
+ // Shader/Pipeline cache helper
+ template <typename Uid, typename ValueType>
+ struct Cache
+ {
+ struct CacheHolder
+ {
+ std::unique_ptr<ValueType> value = nullptr;
+ bool pending = true;
+ };
+ using CacheElement = std::pair<CustomShaderInstance, CacheHolder>;
+ using CacheList = std::list<CacheElement>;
+ std::map<Uid, CacheList> uid_to_cachelist;
+
+ const CacheHolder* GetHolder(const Uid& uid, const CustomShaderInstance& custom_shaders) const
+ {
+ if (auto uuid_it = uid_to_cachelist.find(uid); uuid_it != uid_to_cachelist.end())
+ {
+ for (const auto& [custom_shader_val, holder] : uuid_it->second)
+ {
+ if (custom_shaders == custom_shader_val)
+ {
+ return &holder;
+ }
+ }
+ }
+
+ return nullptr;
+ }
+
+ typename CacheList::iterator InsertElement(const Uid& uid,
+ const CustomShaderInstance& custom_shaders)
+ {
+ CacheList& cachelist = uid_to_cachelist[uid];
+ CacheElement e{custom_shaders, CacheHolder{}};
+ return cachelist.emplace(cachelist.begin(), std::move(e));
+ }
+ };
+
+ Cache<PixelShaderUid, AbstractShader> m_ps_cache;
+ Cache<UberShader::PixelShaderUid, AbstractShader> m_uber_ps_cache;
+ Cache<VideoCommon::GXPipelineUid, AbstractPipeline> m_pipeline_cache;
+ Cache<VideoCommon::GXUberPipelineUid, AbstractPipeline> m_uber_pipeline_cache;
+
+ using PipelineIterator = Cache<VideoCommon::GXPipelineUid, AbstractPipeline>::CacheList::iterator;
+ using UberPipelineIterator =
+ Cache<VideoCommon::GXUberPipelineUid, AbstractPipeline>::CacheList::iterator;
+ using PixelShaderIterator = Cache<PixelShaderUid, AbstractShader>::CacheList::iterator;
+ using UberPixelShaderIterator =
+ Cache<UberShader::PixelShaderUid, AbstractShader>::CacheList::iterator;
+
+ void NotifyPipelineFinished(PipelineIterator iterator,
+ std::unique_ptr<AbstractPipeline> pipeline);
+ void NotifyPipelineFinished(UberPipelineIterator iterator,
+ std::unique_ptr<AbstractPipeline> pipeline);
+
+ std::unique_ptr<AbstractShader>
+ CompilePixelShader(const PixelShaderUid& uid, const CustomShaderInstance& custom_shaders) const;
+ void NotifyPixelShaderFinished(PixelShaderIterator iterator,
+ std::unique_ptr<AbstractShader> shader);
+ std::unique_ptr<AbstractShader>
+ CompilePixelShader(const UberShader::PixelShaderUid& uid,
+ const CustomShaderInstance& custom_shaders) const;
+ void NotifyPixelShaderFinished(UberPixelShaderIterator iterator,
+ std::unique_ptr<AbstractShader> shader);
+
+ void QueuePixelShaderCompile(const PixelShaderUid& uid,
+ const CustomShaderInstance& custom_shaders);
+ void QueuePixelShaderCompile(const UberShader::PixelShaderUid& uid,
+ const CustomShaderInstance& custom_shaders);
+
+ Common::EventHook m_frame_end_handler;
+};