mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-10-11 22:49:50 +00:00
Merge pull request #14908 from iwubcode/vertex_manager_remove_custom_shaders
VideoCommon: remove remnants of old custom shader feature
This commit is contained in:
@@ -99,8 +99,6 @@ add_library(videocommon
|
|||||||
GraphicsModSystem/Runtime/Actions/SkipAction.h
|
GraphicsModSystem/Runtime/Actions/SkipAction.h
|
||||||
GraphicsModSystem/Runtime/CustomPipeline.cpp
|
GraphicsModSystem/Runtime/CustomPipeline.cpp
|
||||||
GraphicsModSystem/Runtime/CustomPipeline.h
|
GraphicsModSystem/Runtime/CustomPipeline.h
|
||||||
GraphicsModSystem/Runtime/CustomShaderCache.cpp
|
|
||||||
GraphicsModSystem/Runtime/CustomShaderCache.h
|
|
||||||
GraphicsModSystem/Runtime/FBInfo.cpp
|
GraphicsModSystem/Runtime/FBInfo.cpp
|
||||||
GraphicsModSystem/Runtime/FBInfo.h
|
GraphicsModSystem/Runtime/FBInfo.h
|
||||||
GraphicsModSystem/Runtime/GraphicsModAction.h
|
GraphicsModSystem/Runtime/GraphicsModAction.h
|
||||||
|
|||||||
@@ -1,387 +0,0 @@
|
|||||||
// Copyright 2022 Dolphin Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.h"
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "VideoCommon/AbstractGfx.h"
|
|
||||||
#include "VideoCommon/VideoConfig.h"
|
|
||||||
#include "VideoCommon/VideoEvents.h"
|
|
||||||
|
|
||||||
CustomShaderCache::CustomShaderCache()
|
|
||||||
{
|
|
||||||
m_api_type = g_backend_info.api_type;
|
|
||||||
m_host_config.bits = ShaderHostConfig::GetCurrent().bits;
|
|
||||||
|
|
||||||
m_async_shader_compiler = g_gfx->CreateAsyncShaderCompiler();
|
|
||||||
m_async_shader_compiler->StartWorkerThreads(1); // TODO
|
|
||||||
|
|
||||||
m_async_uber_shader_compiler = g_gfx->CreateAsyncShaderCompiler();
|
|
||||||
m_async_uber_shader_compiler->StartWorkerThreads(1); // TODO
|
|
||||||
|
|
||||||
m_frame_end_handler = GetVideoEvents().after_frame_event.Register(
|
|
||||||
[this](Core::System&) { RetrieveAsyncShaders(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomShaderCache::~CustomShaderCache()
|
|
||||||
{
|
|
||||||
if (m_async_shader_compiler)
|
|
||||||
{
|
|
||||||
m_async_shader_compiler->StopWorkerThreads();
|
|
||||||
m_async_shader_compiler->ClearAllWork();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_async_uber_shader_compiler)
|
|
||||||
{
|
|
||||||
m_async_uber_shader_compiler->StopWorkerThreads();
|
|
||||||
m_async_uber_shader_compiler->ClearAllWork();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomShaderCache::RetrieveAsyncShaders()
|
|
||||||
{
|
|
||||||
m_async_shader_compiler->RetrieveWorkItems();
|
|
||||||
m_async_uber_shader_compiler->RetrieveWorkItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomShaderCache::Reload()
|
|
||||||
{
|
|
||||||
while (m_async_shader_compiler->HasPendingWork() || m_async_shader_compiler->HasCompletedWork())
|
|
||||||
{
|
|
||||||
m_async_shader_compiler->RetrieveWorkItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (m_async_uber_shader_compiler->HasPendingWork() ||
|
|
||||||
m_async_uber_shader_compiler->HasCompletedWork())
|
|
||||||
{
|
|
||||||
m_async_uber_shader_compiler->RetrieveWorkItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ps_cache = {};
|
|
||||||
m_uber_ps_cache = {};
|
|
||||||
m_pipeline_cache = {};
|
|
||||||
m_uber_pipeline_cache = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<const AbstractPipeline*>
|
|
||||||
CustomShaderCache::GetPipelineAsync(const VideoCommon::GXPipelineUid& uid,
|
|
||||||
const CustomShaderInstance& custom_shaders,
|
|
||||||
const AbstractPipelineConfig& pipeline_config)
|
|
||||||
{
|
|
||||||
if (auto holder = m_pipeline_cache.GetHolder(uid, custom_shaders))
|
|
||||||
{
|
|
||||||
if (holder->pending)
|
|
||||||
return std::nullopt;
|
|
||||||
return holder->value.get();
|
|
||||||
}
|
|
||||||
AsyncCreatePipeline(uid, custom_shaders, pipeline_config);
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<const AbstractPipeline*>
|
|
||||||
CustomShaderCache::GetPipelineAsync(const VideoCommon::GXUberPipelineUid& uid,
|
|
||||||
const CustomShaderInstance& custom_shaders,
|
|
||||||
const AbstractPipelineConfig& pipeline_config)
|
|
||||||
{
|
|
||||||
if (auto holder = m_uber_pipeline_cache.GetHolder(uid, custom_shaders))
|
|
||||||
{
|
|
||||||
if (holder->pending)
|
|
||||||
return std::nullopt;
|
|
||||||
return holder->value.get();
|
|
||||||
}
|
|
||||||
AsyncCreatePipeline(uid, custom_shaders, pipeline_config);
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomShaderCache::AsyncCreatePipeline(const VideoCommon::GXPipelineUid& uid,
|
|
||||||
|
|
||||||
const CustomShaderInstance& custom_shaders,
|
|
||||||
const AbstractPipelineConfig& pipeline_config)
|
|
||||||
{
|
|
||||||
class PipelineWorkItem final : public VideoCommon::AsyncShaderCompiler::WorkItem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PipelineWorkItem(CustomShaderCache* shader_cache, VideoCommon::GXPipelineUid uid,
|
|
||||||
CustomShaderInstance custom_shaders, PipelineIterator iterator,
|
|
||||||
AbstractPipelineConfig pipeline_config)
|
|
||||||
: m_shader_cache(shader_cache), m_uid(std::move(uid)), m_iterator(iterator),
|
|
||||||
m_config(std::move(pipeline_config)), m_custom_shaders(std::move(custom_shaders))
|
|
||||||
{
|
|
||||||
SetStagesReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetStagesReady()
|
|
||||||
{
|
|
||||||
m_stages_ready = true;
|
|
||||||
|
|
||||||
PixelShaderUid ps_uid = m_uid.ps_uid;
|
|
||||||
ClearUnusedPixelShaderUidBits(m_shader_cache->m_api_type, m_shader_cache->m_host_config,
|
|
||||||
&ps_uid);
|
|
||||||
|
|
||||||
if (auto holder = m_shader_cache->m_ps_cache.GetHolder(ps_uid, m_custom_shaders))
|
|
||||||
{
|
|
||||||
// If the pixel shader is no longer pending compilation
|
|
||||||
// and the shader compilation succeeded, set
|
|
||||||
// the pipeline to use the new pixel shader.
|
|
||||||
// Otherwise, use the existing shader.
|
|
||||||
if (!holder->pending && holder->value.get())
|
|
||||||
{
|
|
||||||
m_config.pixel_shader = holder->value.get();
|
|
||||||
}
|
|
||||||
m_stages_ready &= !holder->pending;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_stages_ready &= false;
|
|
||||||
m_shader_cache->QueuePixelShaderCompile(ps_uid, m_custom_shaders);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Compile() override
|
|
||||||
{
|
|
||||||
if (m_stages_ready)
|
|
||||||
{
|
|
||||||
m_pipeline = g_gfx->CreatePipeline(m_config);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Retrieve() override
|
|
||||||
{
|
|
||||||
if (m_stages_ready)
|
|
||||||
{
|
|
||||||
m_shader_cache->NotifyPipelineFinished(m_iterator, std::move(m_pipeline));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Re-queue for next frame.
|
|
||||||
auto wi = m_shader_cache->m_async_shader_compiler->CreateWorkItem<PipelineWorkItem>(
|
|
||||||
m_shader_cache, m_uid, m_custom_shaders, m_iterator, m_config);
|
|
||||||
m_shader_cache->m_async_shader_compiler->QueueWorkItem(std::move(wi), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
CustomShaderCache* m_shader_cache;
|
|
||||||
std::unique_ptr<AbstractPipeline> m_pipeline;
|
|
||||||
VideoCommon::GXPipelineUid m_uid;
|
|
||||||
PipelineIterator m_iterator;
|
|
||||||
AbstractPipelineConfig m_config;
|
|
||||||
CustomShaderInstance m_custom_shaders;
|
|
||||||
bool m_stages_ready;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto list_iter = m_pipeline_cache.InsertElement(uid, custom_shaders);
|
|
||||||
auto work_item = m_async_shader_compiler->CreateWorkItem<PipelineWorkItem>(
|
|
||||||
this, uid, custom_shaders, list_iter, pipeline_config);
|
|
||||||
m_async_shader_compiler->QueueWorkItem(std::move(work_item), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomShaderCache::AsyncCreatePipeline(const VideoCommon::GXUberPipelineUid& uid,
|
|
||||||
|
|
||||||
const CustomShaderInstance& custom_shaders,
|
|
||||||
const AbstractPipelineConfig& pipeline_config)
|
|
||||||
{
|
|
||||||
class PipelineWorkItem final : public VideoCommon::AsyncShaderCompiler::WorkItem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PipelineWorkItem(CustomShaderCache* shader_cache, VideoCommon::GXUberPipelineUid uid,
|
|
||||||
CustomShaderInstance custom_shaders, UberPipelineIterator iterator,
|
|
||||||
AbstractPipelineConfig pipeline_config)
|
|
||||||
: m_shader_cache(shader_cache), m_uid(std::move(uid)), m_iterator(iterator),
|
|
||||||
m_config(std::move(pipeline_config)), m_custom_shaders(std::move(custom_shaders))
|
|
||||||
{
|
|
||||||
SetStagesReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetStagesReady()
|
|
||||||
{
|
|
||||||
m_stages_ready = true;
|
|
||||||
|
|
||||||
UberShader::PixelShaderUid ps_uid = m_uid.ps_uid;
|
|
||||||
ClearUnusedPixelShaderUidBits(m_shader_cache->m_api_type, m_shader_cache->m_host_config,
|
|
||||||
&ps_uid);
|
|
||||||
|
|
||||||
if (auto holder = m_shader_cache->m_uber_ps_cache.GetHolder(ps_uid, m_custom_shaders))
|
|
||||||
{
|
|
||||||
if (!holder->pending && holder->value.get())
|
|
||||||
{
|
|
||||||
m_config.pixel_shader = holder->value.get();
|
|
||||||
}
|
|
||||||
m_stages_ready &= !holder->pending;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_stages_ready &= false;
|
|
||||||
m_shader_cache->QueuePixelShaderCompile(ps_uid, m_custom_shaders);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Compile() override
|
|
||||||
{
|
|
||||||
if (m_stages_ready)
|
|
||||||
{
|
|
||||||
if (m_config.pixel_shader == nullptr || m_config.vertex_shader == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_pipeline = g_gfx->CreatePipeline(m_config);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Retrieve() override
|
|
||||||
{
|
|
||||||
if (m_stages_ready)
|
|
||||||
{
|
|
||||||
m_shader_cache->NotifyPipelineFinished(m_iterator, std::move(m_pipeline));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Re-queue for next frame.
|
|
||||||
auto wi = m_shader_cache->m_async_uber_shader_compiler->CreateWorkItem<PipelineWorkItem>(
|
|
||||||
m_shader_cache, m_uid, m_custom_shaders, m_iterator, m_config);
|
|
||||||
m_shader_cache->m_async_uber_shader_compiler->QueueWorkItem(std::move(wi), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
CustomShaderCache* m_shader_cache;
|
|
||||||
std::unique_ptr<AbstractPipeline> m_pipeline;
|
|
||||||
VideoCommon::GXUberPipelineUid m_uid;
|
|
||||||
UberPipelineIterator m_iterator;
|
|
||||||
AbstractPipelineConfig m_config;
|
|
||||||
CustomShaderInstance m_custom_shaders;
|
|
||||||
bool m_stages_ready;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto list_iter = m_uber_pipeline_cache.InsertElement(uid, custom_shaders);
|
|
||||||
auto work_item = m_async_uber_shader_compiler->CreateWorkItem<PipelineWorkItem>(
|
|
||||||
this, uid, custom_shaders, list_iter, pipeline_config);
|
|
||||||
m_async_uber_shader_compiler->QueueWorkItem(std::move(work_item), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomShaderCache::NotifyPipelineFinished(PipelineIterator iterator,
|
|
||||||
std::unique_ptr<AbstractPipeline> pipeline)
|
|
||||||
{
|
|
||||||
iterator->second.pending = false;
|
|
||||||
iterator->second.value = std::move(pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomShaderCache::NotifyPipelineFinished(UberPipelineIterator iterator,
|
|
||||||
std::unique_ptr<AbstractPipeline> pipeline)
|
|
||||||
{
|
|
||||||
iterator->second.pending = false;
|
|
||||||
iterator->second.value = std::move(pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomShaderCache::QueuePixelShaderCompile(const PixelShaderUid& uid,
|
|
||||||
|
|
||||||
const CustomShaderInstance& custom_shaders)
|
|
||||||
{
|
|
||||||
class PixelShaderWorkItem final : public VideoCommon::AsyncShaderCompiler::WorkItem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PixelShaderWorkItem(CustomShaderCache* shader_cache, const PixelShaderUid& uid,
|
|
||||||
CustomShaderInstance custom_shaders, PixelShaderIterator iter)
|
|
||||||
: m_shader_cache(shader_cache), m_uid(uid), m_custom_shaders(std::move(custom_shaders)),
|
|
||||||
m_iter(iter)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Compile() override
|
|
||||||
{
|
|
||||||
m_shader = m_shader_cache->CompilePixelShader(m_uid, m_custom_shaders);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Retrieve() override
|
|
||||||
{
|
|
||||||
m_shader_cache->NotifyPixelShaderFinished(m_iter, std::move(m_shader));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
CustomShaderCache* m_shader_cache;
|
|
||||||
std::unique_ptr<AbstractShader> m_shader;
|
|
||||||
PixelShaderUid m_uid;
|
|
||||||
CustomShaderInstance m_custom_shaders;
|
|
||||||
PixelShaderIterator m_iter;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto list_iter = m_ps_cache.InsertElement(uid, custom_shaders);
|
|
||||||
auto work_item = m_async_shader_compiler->CreateWorkItem<PixelShaderWorkItem>(
|
|
||||||
this, uid, custom_shaders, list_iter);
|
|
||||||
m_async_shader_compiler->QueueWorkItem(std::move(work_item), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomShaderCache::QueuePixelShaderCompile(const UberShader::PixelShaderUid& uid,
|
|
||||||
|
|
||||||
const CustomShaderInstance& custom_shaders)
|
|
||||||
{
|
|
||||||
class PixelShaderWorkItem final : public VideoCommon::AsyncShaderCompiler::WorkItem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PixelShaderWorkItem(CustomShaderCache* shader_cache, const UberShader::PixelShaderUid& uid,
|
|
||||||
CustomShaderInstance custom_shaders, UberPixelShaderIterator iter)
|
|
||||||
: m_shader_cache(shader_cache), m_uid(uid), m_custom_shaders(std::move(custom_shaders)),
|
|
||||||
m_iter(iter)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Compile() override
|
|
||||||
{
|
|
||||||
m_shader = m_shader_cache->CompilePixelShader(m_uid, m_custom_shaders);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Retrieve() override
|
|
||||||
{
|
|
||||||
m_shader_cache->NotifyPixelShaderFinished(m_iter, std::move(m_shader));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
CustomShaderCache* m_shader_cache;
|
|
||||||
std::unique_ptr<AbstractShader> m_shader;
|
|
||||||
UberShader::PixelShaderUid m_uid;
|
|
||||||
CustomShaderInstance m_custom_shaders;
|
|
||||||
UberPixelShaderIterator m_iter;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto list_iter = m_uber_ps_cache.InsertElement(uid, custom_shaders);
|
|
||||||
auto work_item = m_async_uber_shader_compiler->CreateWorkItem<PixelShaderWorkItem>(
|
|
||||||
this, uid, custom_shaders, list_iter);
|
|
||||||
m_async_uber_shader_compiler->QueueWorkItem(std::move(work_item), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<AbstractShader>
|
|
||||||
CustomShaderCache::CompilePixelShader(const PixelShaderUid& uid,
|
|
||||||
const CustomShaderInstance& custom_shaders) const
|
|
||||||
{
|
|
||||||
const ShaderCode source_code =
|
|
||||||
GeneratePixelShaderCode(m_api_type, m_host_config, uid.GetUidData(), {});
|
|
||||||
return g_gfx->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer(), nullptr,
|
|
||||||
"Custom Pixel Shader");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<AbstractShader>
|
|
||||||
CustomShaderCache::CompilePixelShader(const UberShader::PixelShaderUid& uid,
|
|
||||||
const CustomShaderInstance& custom_shaders) const
|
|
||||||
{
|
|
||||||
const ShaderCode source_code = GenPixelShader(m_api_type, m_host_config, uid.GetUidData());
|
|
||||||
return g_gfx->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer(), nullptr,
|
|
||||||
"Custom Uber Pixel Shader");
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomShaderCache::NotifyPixelShaderFinished(PixelShaderIterator iterator,
|
|
||||||
std::unique_ptr<AbstractShader> shader)
|
|
||||||
{
|
|
||||||
iterator->second.pending = false;
|
|
||||||
iterator->second.value = std::move(shader);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CustomShaderCache::NotifyPixelShaderFinished(UberPixelShaderIterator iterator,
|
|
||||||
std::unique_ptr<AbstractShader> shader)
|
|
||||||
{
|
|
||||||
iterator->second.pending = false;
|
|
||||||
iterator->second.value = std::move(shader);
|
|
||||||
}
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
// Copyright 2022 Dolphin Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#include "Common/HookableEvent.h"
|
|
||||||
|
|
||||||
#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"
|
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
@@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
#include <span>
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -13,7 +11,6 @@
|
|||||||
#include "Common/SmallVector.h"
|
#include "Common/SmallVector.h"
|
||||||
#include "VideoCommon/Assets/TextureAsset.h"
|
#include "VideoCommon/Assets/TextureAsset.h"
|
||||||
#include "VideoCommon/Resources/MaterialResource.h"
|
#include "VideoCommon/Resources/MaterialResource.h"
|
||||||
#include "VideoCommon/ShaderGenCommon.h"
|
|
||||||
|
|
||||||
namespace GraphicsModActionData
|
namespace GraphicsModActionData
|
||||||
{
|
{
|
||||||
@@ -21,8 +18,6 @@ struct DrawStarted
|
|||||||
{
|
{
|
||||||
const Common::SmallVector<u32, 8>& texture_units;
|
const Common::SmallVector<u32, 8>& texture_units;
|
||||||
bool* skip;
|
bool* skip;
|
||||||
std::optional<CustomPixelShader>* custom_pixel_shader;
|
|
||||||
std::span<u8>* material_uniform_buffer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PreEFB
|
struct PreEFB
|
||||||
|
|||||||
@@ -328,20 +328,3 @@ static const char s_geometry_shader_uniforms[] = "\tfloat4 " I_STEREOPARAMS ";\n
|
|||||||
"\tfloat4 " I_LINEPTPARAMS ";\n"
|
"\tfloat4 " I_LINEPTPARAMS ";\n"
|
||||||
"\tint4 " I_TEXOFFSET ";\n"
|
"\tint4 " I_TEXOFFSET ";\n"
|
||||||
"\tuint vs_expand;\n";
|
"\tuint vs_expand;\n";
|
||||||
|
|
||||||
constexpr std::string_view CUSTOM_PIXELSHADER_COLOR_FUNC = "customShaderColor";
|
|
||||||
|
|
||||||
struct CustomPixelShader
|
|
||||||
{
|
|
||||||
std::string custom_shader;
|
|
||||||
std::string material_uniform_block;
|
|
||||||
|
|
||||||
bool operator==(const CustomPixelShader& other) const = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CustomPixelShaderContents
|
|
||||||
{
|
|
||||||
std::vector<CustomPixelShader> shaders;
|
|
||||||
|
|
||||||
bool operator==(const CustomPixelShaderContents& other) const = default;
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
#include "VideoCommon/DataReader.h"
|
#include "VideoCommon/DataReader.h"
|
||||||
#include "VideoCommon/FramebufferManager.h"
|
#include "VideoCommon/FramebufferManager.h"
|
||||||
#include "VideoCommon/GeometryShaderManager.h"
|
#include "VideoCommon/GeometryShaderManager.h"
|
||||||
#include "VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.h"
|
|
||||||
#include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModActionData.h"
|
#include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModActionData.h"
|
||||||
#include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModManager.h"
|
#include "VideoCommon/GraphicsModSystem/Runtime/GraphicsModManager.h"
|
||||||
#include "VideoCommon/IndexGenerator.h"
|
#include "VideoCommon/IndexGenerator.h"
|
||||||
@@ -124,7 +123,6 @@ bool VertexManagerBase::Initialize()
|
|||||||
m_after_present_event = video_events.after_present_event.Register(
|
m_after_present_event = video_events.after_present_event.Register(
|
||||||
[this](const PresentInfo& pi) { m_ticks_elapsed = pi.emulated_timestamp; });
|
[this](const PresentInfo& pi) { m_ticks_elapsed = pi.emulated_timestamp; });
|
||||||
m_index_generator.Init();
|
m_index_generator.Init();
|
||||||
m_custom_shader_cache = std::make_unique<CustomShaderCache>();
|
|
||||||
m_cpu_cull.Init();
|
m_cpu_cull.Init();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -610,25 +608,12 @@ void VertexManagerBase::Flush()
|
|||||||
|
|
||||||
if (!m_cull_all)
|
if (!m_cull_all)
|
||||||
{
|
{
|
||||||
CustomPixelShaderContents custom_pixel_shader_contents;
|
|
||||||
std::optional<CustomPixelShader> custom_pixel_shader;
|
|
||||||
std::vector<std::string> custom_pixel_texture_names;
|
|
||||||
std::span<u8> custom_pixel_shader_uniforms;
|
|
||||||
bool skip = false;
|
bool skip = false;
|
||||||
for (size_t i = 0; i < texture_names.size(); i++)
|
for (const std::string& texture_name : texture_names)
|
||||||
{
|
{
|
||||||
GraphicsModActionData::DrawStarted draw_started{texture_units, &skip, &custom_pixel_shader,
|
GraphicsModActionData::DrawStarted draw_started{texture_units, &skip};
|
||||||
&custom_pixel_shader_uniforms};
|
for (const auto& action : g_graphics_mod_manager->GetDrawStartedActions(texture_name))
|
||||||
for (const auto& action : g_graphics_mod_manager->GetDrawStartedActions(texture_names[i]))
|
|
||||||
{
|
|
||||||
action->OnDrawStarted(&draw_started);
|
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_names[i]);
|
|
||||||
}
|
|
||||||
custom_pixel_shader = std::nullopt;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now the vertices can be flushed to the GPU. Everything following the CommitBuffer() call
|
// Now the vertices can be flushed to the GPU. Everything following the CommitBuffer() call
|
||||||
@@ -648,18 +633,8 @@ void VertexManagerBase::Flush()
|
|||||||
UpdatePipelineObject();
|
UpdatePipelineObject();
|
||||||
if (m_current_pipeline_object)
|
if (m_current_pipeline_object)
|
||||||
{
|
{
|
||||||
const AbstractPipeline* pipeline_object = m_current_pipeline_object;
|
RenderDrawCall(pixel_shader_manager, geometry_shader_manager, m_current_primitive_type,
|
||||||
if (!custom_pixel_shader_contents.shaders.empty())
|
m_current_pipeline_object);
|
||||||
{
|
|
||||||
if (const auto custom_pipeline =
|
|
||||||
GetCustomPipeline(custom_pixel_shader_contents, m_current_pipeline_config,
|
|
||||||
m_current_uber_pipeline_config, m_current_pipeline_object))
|
|
||||||
{
|
|
||||||
pipeline_object = custom_pipeline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RenderDrawCall(pixel_shader_manager, geometry_shader_manager, custom_pixel_shader_contents,
|
|
||||||
custom_pixel_shader_uniforms, m_current_primitive_type, pipeline_object);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1048,27 +1023,14 @@ void VertexManagerBase::OnEndFrame()
|
|||||||
InvalidatePipelineObject();
|
InvalidatePipelineObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexManagerBase::NotifyCustomShaderCacheOfHostChange(const ShaderHostConfig& host_config)
|
void VertexManagerBase::RenderDrawCall(PixelShaderManager& pixel_shader_manager,
|
||||||
{
|
GeometryShaderManager& geometry_shader_manager,
|
||||||
m_custom_shader_cache->SetHostConfig(host_config);
|
PrimitiveType primitive_type,
|
||||||
m_custom_shader_cache->Reload();
|
const AbstractPipeline* current_pipeline)
|
||||||
}
|
|
||||||
|
|
||||||
void VertexManagerBase::RenderDrawCall(
|
|
||||||
PixelShaderManager& pixel_shader_manager, GeometryShaderManager& geometry_shader_manager,
|
|
||||||
const CustomPixelShaderContents& custom_pixel_shader_contents,
|
|
||||||
std::span<u8> custom_pixel_shader_uniforms, PrimitiveType primitive_type,
|
|
||||||
const AbstractPipeline* current_pipeline)
|
|
||||||
{
|
{
|
||||||
// Now we can upload uniforms, as nothing else will override them.
|
// Now we can upload uniforms, as nothing else will override them.
|
||||||
geometry_shader_manager.SetConstants(primitive_type);
|
geometry_shader_manager.SetConstants(primitive_type);
|
||||||
pixel_shader_manager.SetConstants();
|
pixel_shader_manager.SetConstants();
|
||||||
if (!custom_pixel_shader_uniforms.empty() &&
|
|
||||||
pixel_shader_manager.custom_constants.data() != custom_pixel_shader_uniforms.data())
|
|
||||||
{
|
|
||||||
pixel_shader_manager.custom_constants_dirty = true;
|
|
||||||
}
|
|
||||||
pixel_shader_manager.custom_constants = custom_pixel_shader_uniforms;
|
|
||||||
UploadUniforms();
|
UploadUniforms();
|
||||||
|
|
||||||
g_gfx->SetPipeline(current_pipeline);
|
g_gfx->SetPipeline(current_pipeline);
|
||||||
@@ -1098,70 +1060,3 @@ void VertexManagerBase::RenderDrawCall(
|
|||||||
if (PerfQueryBase::ShouldEmulate())
|
if (PerfQueryBase::ShouldEmulate())
|
||||||
g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
|
g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
const AbstractPipeline* VertexManagerBase::GetCustomPipeline(
|
|
||||||
const CustomPixelShaderContents& custom_pixel_shader_contents,
|
|
||||||
const VideoCommon::GXPipelineUid& current_pipeline_config,
|
|
||||||
const VideoCommon::GXUberPipelineUid& current_uber_pipeline_config,
|
|
||||||
const AbstractPipeline* current_pipeline) const
|
|
||||||
{
|
|
||||||
if (current_pipeline)
|
|
||||||
{
|
|
||||||
if (!custom_pixel_shader_contents.shaders.empty())
|
|
||||||
{
|
|
||||||
CustomShaderInstance custom_shaders;
|
|
||||||
custom_shaders.pixel_contents = custom_pixel_shader_contents;
|
|
||||||
switch (g_ActiveConfig.iShaderCompilationMode)
|
|
||||||
{
|
|
||||||
case ShaderCompilationMode::Synchronous:
|
|
||||||
case ShaderCompilationMode::AsynchronousSkipRendering:
|
|
||||||
{
|
|
||||||
if (auto pipeline = m_custom_shader_cache->GetPipelineAsync(
|
|
||||||
current_pipeline_config, custom_shaders, current_pipeline->m_config))
|
|
||||||
{
|
|
||||||
return *pipeline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ShaderCompilationMode::SynchronousUberShaders:
|
|
||||||
{
|
|
||||||
// D3D has issues compiling large custom ubershaders
|
|
||||||
// use specialized shaders instead
|
|
||||||
if (g_backend_info.api_type == APIType::D3D)
|
|
||||||
{
|
|
||||||
if (auto pipeline = m_custom_shader_cache->GetPipelineAsync(
|
|
||||||
current_pipeline_config, custom_shaders, current_pipeline->m_config))
|
|
||||||
{
|
|
||||||
return *pipeline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (auto pipeline = m_custom_shader_cache->GetPipelineAsync(
|
|
||||||
current_uber_pipeline_config, custom_shaders, current_pipeline->m_config))
|
|
||||||
{
|
|
||||||
return *pipeline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ShaderCompilationMode::AsynchronousUberShaders:
|
|
||||||
{
|
|
||||||
if (auto pipeline = m_custom_shader_cache->GetPipelineAsync(
|
|
||||||
current_pipeline_config, custom_shaders, current_pipeline->m_config))
|
|
||||||
{
|
|
||||||
return *pipeline;
|
|
||||||
}
|
|
||||||
else if (auto uber_pipeline = m_custom_shader_cache->GetPipelineAsync(
|
|
||||||
current_uber_pipeline_config, custom_shaders, current_pipeline->m_config))
|
|
||||||
{
|
|
||||||
return *uber_pipeline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -15,8 +15,6 @@
|
|||||||
#include "VideoCommon/ShaderCache.h"
|
#include "VideoCommon/ShaderCache.h"
|
||||||
#include "VideoCommon/VideoEvents.h"
|
#include "VideoCommon/VideoEvents.h"
|
||||||
|
|
||||||
struct CustomPixelShaderContents;
|
|
||||||
class CustomShaderCache;
|
|
||||||
class DataReader;
|
class DataReader;
|
||||||
class GeometryShaderManager;
|
class GeometryShaderManager;
|
||||||
class NativeVertexFormat;
|
class NativeVertexFormat;
|
||||||
@@ -134,7 +132,6 @@ public:
|
|||||||
m_current_pipeline_object = nullptr;
|
m_current_pipeline_object = nullptr;
|
||||||
m_pipeline_config_changed = true;
|
m_pipeline_config_changed = true;
|
||||||
}
|
}
|
||||||
void NotifyCustomShaderCacheOfHostChange(const ShaderHostConfig& host_config);
|
|
||||||
|
|
||||||
// Utility pipeline drawing (e.g. EFB copies, post-processing, UI).
|
// Utility pipeline drawing (e.g. EFB copies, post-processing, UI).
|
||||||
virtual void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size);
|
virtual void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size);
|
||||||
@@ -224,19 +221,11 @@ private:
|
|||||||
static constexpr u32 MINIMUM_DRAW_CALLS_PER_COMMAND_BUFFER_FOR_READBACK = 10;
|
static constexpr u32 MINIMUM_DRAW_CALLS_PER_COMMAND_BUFFER_FOR_READBACK = 10;
|
||||||
|
|
||||||
void RenderDrawCall(PixelShaderManager& pixel_shader_manager,
|
void RenderDrawCall(PixelShaderManager& pixel_shader_manager,
|
||||||
GeometryShaderManager& geometry_shader_manager,
|
GeometryShaderManager& geometry_shader_manager, PrimitiveType primitive_type,
|
||||||
const CustomPixelShaderContents& custom_pixel_shader_contents,
|
|
||||||
std::span<u8> custom_pixel_shader_uniforms, PrimitiveType primitive_type,
|
|
||||||
const AbstractPipeline* current_pipeline);
|
const AbstractPipeline* current_pipeline);
|
||||||
void UpdatePipelineConfig();
|
void UpdatePipelineConfig();
|
||||||
void UpdatePipelineObject();
|
void UpdatePipelineObject();
|
||||||
|
|
||||||
const AbstractPipeline*
|
|
||||||
GetCustomPipeline(const CustomPixelShaderContents& custom_pixel_shader_contents,
|
|
||||||
const VideoCommon::GXPipelineUid& current_pipeline_config,
|
|
||||||
const VideoCommon::GXUberPipelineUid& current_uber_pipeline_confi,
|
|
||||||
const AbstractPipeline* current_pipeline) const;
|
|
||||||
|
|
||||||
bool m_is_flushed = true;
|
bool m_is_flushed = true;
|
||||||
FlushStatistics m_flush_statistics = {};
|
FlushStatistics m_flush_statistics = {};
|
||||||
|
|
||||||
@@ -248,7 +237,6 @@ private:
|
|||||||
std::vector<u32> m_scheduled_command_buffer_kicks;
|
std::vector<u32> m_scheduled_command_buffer_kicks;
|
||||||
bool m_allow_background_execution = true;
|
bool m_allow_background_execution = true;
|
||||||
|
|
||||||
std::unique_ptr<CustomShaderCache> m_custom_shader_cache;
|
|
||||||
u64 m_ticks_elapsed = 0;
|
u64 m_ticks_elapsed = 0;
|
||||||
|
|
||||||
Common::EventHook m_frame_end_event;
|
Common::EventHook m_frame_end_event;
|
||||||
|
|||||||
@@ -390,7 +390,6 @@ void CheckForConfigChanges()
|
|||||||
OSD::AddMessage("Video config changed, reloading shaders.", OSD::Duration::NORMAL);
|
OSD::AddMessage("Video config changed, reloading shaders.", OSD::Duration::NORMAL);
|
||||||
g_gfx->WaitForGPUIdle();
|
g_gfx->WaitForGPUIdle();
|
||||||
g_vertex_manager->InvalidatePipelineObject();
|
g_vertex_manager->InvalidatePipelineObject();
|
||||||
g_vertex_manager->NotifyCustomShaderCacheOfHostChange(new_host_config);
|
|
||||||
g_shader_cache->SetHostConfig(new_host_config);
|
g_shader_cache->SetHostConfig(new_host_config);
|
||||||
g_shader_cache->Reload();
|
g_shader_cache->Reload();
|
||||||
g_framebuffer_manager->RecompileShaders();
|
g_framebuffer_manager->RecompileShaders();
|
||||||
|
|||||||
Reference in New Issue
Block a user