mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 18:25:28 +03:00
Implement Shader IR Cache
This implements the first step of a full shader cache with caching any IR by treating the shared pointer as a handle and key for an associative map alongside hashing the Maxwell shader bytecode, it supports both single shader program and dual vertex program caching.
This commit is contained in:
parent
0baa90d641
commit
76d8172a35
@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
|
||||||
|
#include <boost/functional/hash.hpp>
|
||||||
#include <gpu.h>
|
#include <gpu.h>
|
||||||
#include <shader_compiler/common/settings.h>
|
#include <shader_compiler/common/settings.h>
|
||||||
#include <shader_compiler/common/log.h>
|
#include <shader_compiler/common/log.h>
|
||||||
@ -168,17 +169,32 @@ namespace skyline::gpu {
|
|||||||
ShaderManager::DualVertexShaderProgram::DualVertexShaderProgram(Shader::IR::Program ir, std::shared_ptr<ShaderProgram> vertexA, std::shared_ptr<ShaderProgram> vertexB) : ShaderProgram{std::move(ir)}, vertexA(std::move(vertexA)), vertexB(std::move(vertexB)) {}
|
ShaderManager::DualVertexShaderProgram::DualVertexShaderProgram(Shader::IR::Program ir, std::shared_ptr<ShaderProgram> vertexA, std::shared_ptr<ShaderProgram> vertexB) : ShaderProgram{std::move(ir)}, vertexA(std::move(vertexA)), vertexB(std::move(vertexB)) {}
|
||||||
|
|
||||||
std::shared_ptr<ShaderManager::ShaderProgram> ShaderManager::ParseGraphicsShader(Shader::Stage stage, span<u8> binary, u32 baseOffset, u32 bindlessTextureConstantBufferIndex) {
|
std::shared_ptr<ShaderManager::ShaderProgram> ShaderManager::ParseGraphicsShader(Shader::Stage stage, span<u8> binary, u32 baseOffset, u32 bindlessTextureConstantBufferIndex) {
|
||||||
auto program{std::make_shared<SingleShaderProgram>()};
|
auto &program{programCache[binary]};
|
||||||
|
if (program)
|
||||||
|
return program;
|
||||||
|
|
||||||
|
program = std::make_shared<SingleShaderProgram>();
|
||||||
GraphicsEnvironment environment{stage, binary, baseOffset, bindlessTextureConstantBufferIndex};
|
GraphicsEnvironment environment{stage, binary, baseOffset, bindlessTextureConstantBufferIndex};
|
||||||
Shader::Maxwell::Flow::CFG cfg(environment, program->flowBlockPool, Shader::Maxwell::Location{static_cast<u32>(baseOffset + sizeof(Shader::ProgramHeader))});
|
Shader::Maxwell::Flow::CFG cfg(environment, program->flowBlockPool, Shader::Maxwell::Location{static_cast<u32>(baseOffset + sizeof(Shader::ProgramHeader))});
|
||||||
|
|
||||||
program->program = Shader::Maxwell::TranslateProgram(program->instructionPool, program->blockPool, environment, cfg, hostTranslateInfo);
|
program->program = Shader::Maxwell::TranslateProgram(program->instructionPool, program->blockPool, environment, cfg, hostTranslateInfo);
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr size_t ShaderManager::DualVertexProgramsHash::operator()(const std::pair<std::shared_ptr<ShaderProgram>, std::shared_ptr<ShaderProgram>> &p) const {
|
||||||
|
size_t hash{};
|
||||||
|
boost::hash_combine(hash, p.first);
|
||||||
|
boost::hash_combine(hash, p.second);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<ShaderManager::ShaderProgram> ShaderManager::CombineVertexShaders(const std::shared_ptr<ShaderManager::ShaderProgram> &vertexA, const std::shared_ptr<ShaderManager::ShaderProgram> &vertexB, span<u8> vertexBBinary) {
|
std::shared_ptr<ShaderManager::ShaderProgram> ShaderManager::CombineVertexShaders(const std::shared_ptr<ShaderManager::ShaderProgram> &vertexA, const std::shared_ptr<ShaderManager::ShaderProgram> &vertexB, span<u8> vertexBBinary) {
|
||||||
|
auto &program{dualProgramCache[DualVertexPrograms{vertexA, vertexB}]};
|
||||||
|
if (program)
|
||||||
|
return program;
|
||||||
|
|
||||||
VertexBEnvironment vertexBEnvironment{vertexBBinary};
|
VertexBEnvironment vertexBEnvironment{vertexBBinary};
|
||||||
return std::make_shared<DualVertexShaderProgram>(Shader::Maxwell::MergeDualVertexPrograms(vertexA->program, vertexB->program, vertexBEnvironment), vertexA, vertexB);
|
program = std::make_shared<DualVertexShaderProgram>(Shader::Maxwell::MergeDualVertexPrograms(vertexA->program, vertexB->program, vertexBEnvironment), vertexA, vertexB);
|
||||||
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::raii::ShaderModule ShaderManager::CompileShader(Shader::RuntimeInfo &runtimeInfo, const std::shared_ptr<ShaderProgram> &program, Shader::Backend::Bindings &bindings) {
|
vk::raii::ShaderModule ShaderManager::CompileShader(Shader::RuntimeInfo &runtimeInfo, const std::shared_ptr<ShaderProgram> &program, Shader::Backend::Bindings &bindings) {
|
||||||
|
@ -43,6 +43,8 @@ namespace skyline::gpu {
|
|||||||
SingleShaderProgram &operator=(const SingleShaderProgram &) = delete;
|
SingleShaderProgram &operator=(const SingleShaderProgram &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::unordered_map<span<u8>, std::shared_ptr<SingleShaderProgram>, SpanHash<u8>, SpanEqual<u8>> programCache; //!< A map from Maxwell bytecode to the corresponding shader program
|
||||||
|
|
||||||
struct DualVertexShaderProgram : ShaderProgram {
|
struct DualVertexShaderProgram : ShaderProgram {
|
||||||
std::shared_ptr<ShaderProgram> vertexA;
|
std::shared_ptr<ShaderProgram> vertexA;
|
||||||
std::shared_ptr<ShaderProgram> vertexB;
|
std::shared_ptr<ShaderProgram> vertexB;
|
||||||
@ -54,16 +56,24 @@ namespace skyline::gpu {
|
|||||||
DualVertexShaderProgram &operator=(const DualVertexShaderProgram &) = delete;
|
DualVertexShaderProgram &operator=(const DualVertexShaderProgram &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using DualVertexPrograms = std::pair<std::shared_ptr<ShaderProgram>, std::shared_ptr<ShaderProgram>>;
|
||||||
|
|
||||||
|
struct DualVertexProgramsHash {
|
||||||
|
constexpr size_t operator()(const std::pair<std::shared_ptr<ShaderProgram>, std::shared_ptr<ShaderProgram>> &p) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_map<DualVertexPrograms, std::shared_ptr<DualVertexShaderProgram>, DualVertexProgramsHash> dualProgramCache; //!< A map from Vertex A and Vertex B shader programs to the corresponding dual vertex shader program
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShaderManager(const DeviceState &state, GPU &gpu);
|
ShaderManager(const DeviceState &state, GPU &gpu);
|
||||||
|
|
||||||
std::shared_ptr<ShaderManager::ShaderProgram> ParseGraphicsShader(Shader::Stage stage, span <u8> binary, u32 baseOffset, u32 bindlessTextureConstantBufferIndex);
|
std::shared_ptr<ShaderManager::ShaderProgram> ParseGraphicsShader(Shader::Stage stage, span<u8> binary, u32 baseOffset, u32 bindlessTextureConstantBufferIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Combines the VertexA and VertexB shader programs into a single program
|
* @brief Combines the VertexA and VertexB shader programs into a single program
|
||||||
* @note VertexA/VertexB shader programs must be SingleShaderProgram and not DualVertexShaderProgram
|
* @note VertexA/VertexB shader programs must be SingleShaderProgram and not DualVertexShaderProgram
|
||||||
*/
|
*/
|
||||||
static std::shared_ptr<ShaderManager::ShaderProgram> CombineVertexShaders(const std::shared_ptr<ShaderProgram> &vertexA, const std::shared_ptr<ShaderProgram> &vertexB, span <u8> vertexBBinary);
|
std::shared_ptr<ShaderManager::ShaderProgram> CombineVertexShaders(const std::shared_ptr<ShaderProgram> &vertexA, const std::shared_ptr<ShaderProgram> &vertexB, span<u8> vertexBBinary);
|
||||||
|
|
||||||
vk::raii::ShaderModule CompileShader(Shader::RuntimeInfo &runtimeInfo, const std::shared_ptr<ShaderProgram> &program, Shader::Backend::Bindings &bindings);
|
vk::raii::ShaderModule CompileShader(Shader::RuntimeInfo &runtimeInfo, const std::shared_ptr<ShaderProgram> &program, Shader::Backend::Bindings &bindings);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user