vk_shader_cache: Small cleanup
This commit is contained in:
parent
93db0625f6
commit
dbb9e457ea
|
@ -161,16 +161,17 @@ void PipelineCache::RefreshGraphicsKey() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto stage = Shader::Stage{i};
|
const auto stage = Shader::Stage{i};
|
||||||
|
const GuestProgram guest_pgm{pgm, stage};
|
||||||
std::tie(infos[i], modules[i], key.stage_hashes[i]) =
|
std::tie(infos[i], modules[i], key.stage_hashes[i]) =
|
||||||
shader_cache->GetProgram(pgm, stage, binding);
|
shader_cache->GetProgram(guest_pgm, binding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipelineCache::RefreshComputeKey() {
|
void PipelineCache::RefreshComputeKey() {
|
||||||
u32 binding{};
|
u32 binding{};
|
||||||
const auto* cs_pgm = &liverpool->regs.cs_program;
|
const auto* cs_pgm = &liverpool->regs.cs_program;
|
||||||
std::tie(infos[0], modules[0], compute_key) =
|
const GuestProgram guest_pgm{cs_pgm, Shader::Stage::Compute};
|
||||||
shader_cache->GetProgram(cs_pgm, Shader::Stage::Compute, binding);
|
std::tie(infos[0], modules[0], compute_key) = shader_cache->GetProgram(guest_pgm, binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -59,14 +59,13 @@ void BuildVsOutputs(Shader::Info& info, const AmdGpu::Liverpool::VsOutputControl
|
||||||
: (ctl.IsCullDistEnabled(7) ? VsOutput::CullDist7 : VsOutput::None));
|
: (ctl.IsCullDistEnabled(7) ? VsOutput::CullDist7 : VsOutput::None));
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader::Info MakeShaderInfo(Shader::Stage stage, std::span<const u32, 16> user_data, u64 pgm_base,
|
Shader::Info MakeShaderInfo(const GuestProgram& pgm, const AmdGpu::Liverpool::Regs& regs) {
|
||||||
u64 hash, const AmdGpu::Liverpool::Regs& regs) {
|
|
||||||
Shader::Info info{};
|
Shader::Info info{};
|
||||||
info.user_data = user_data;
|
info.user_data = pgm.user_data;
|
||||||
info.pgm_base = pgm_base;
|
info.pgm_base = VAddr(pgm.code.data());
|
||||||
info.pgm_hash = hash;
|
info.pgm_hash = pgm.hash;
|
||||||
info.stage = stage;
|
info.stage = pgm.stage;
|
||||||
switch (stage) {
|
switch (pgm.stage) {
|
||||||
case Shader::Stage::Vertex: {
|
case Shader::Stage::Vertex: {
|
||||||
info.num_user_data = regs.vs_program.settings.num_user_regs;
|
info.num_user_data = regs.vs_program.settings.num_user_regs;
|
||||||
info.num_input_vgprs = regs.vs_program.settings.vgpr_comp_cnt;
|
info.num_input_vgprs = regs.vs_program.settings.vgpr_comp_cnt;
|
||||||
|
@ -101,6 +100,10 @@ Shader::Info MakeShaderInfo(Shader::Stage stage, std::span<const u32, 16> user_d
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline u64 HashCombine(const u64 seed, const u64 hash) {
|
||||||
|
return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2));
|
||||||
|
}
|
||||||
|
|
||||||
ShaderCache::ShaderCache(const Instance& instance_, AmdGpu::Liverpool* liverpool_)
|
ShaderCache::ShaderCache(const Instance& instance_, AmdGpu::Liverpool* liverpool_)
|
||||||
: instance{instance_}, liverpool{liverpool_}, inst_pool{8192}, block_pool{512} {
|
: instance{instance_}, liverpool{liverpool_}, inst_pool{8192}, block_pool{512} {
|
||||||
profile = Shader::Profile{
|
profile = Shader::Profile{
|
||||||
|
@ -137,6 +140,43 @@ vk::ShaderModule ShaderCache::CompileModule(Shader::Info& info, std::span<const
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Program* ShaderCache::CreateProgram(const GuestProgram& pgm, u32& binding) {
|
||||||
|
Program* program = program_pool.Create(MakeShaderInfo(pgm, liverpool->regs));
|
||||||
|
u32 start_binding = binding;
|
||||||
|
const auto module = CompileModule(program->info, pgm.code, 0, binding);
|
||||||
|
program->modules.emplace_back(module, StageSpecialization{program->info, start_binding});
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<const Shader::Info*, vk::ShaderModule, u64> ShaderCache::GetProgram(
|
||||||
|
const GuestProgram& pgm, u32& binding) {
|
||||||
|
auto [it_pgm, new_program] = program_cache.try_emplace(pgm.hash);
|
||||||
|
if (new_program) {
|
||||||
|
auto program = CreateProgram(pgm, binding);
|
||||||
|
const auto module = program->modules.back().module;
|
||||||
|
it_pgm.value() = program;
|
||||||
|
return std::make_tuple(&program->info, module, HashCombine(pgm.hash, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
Program* program = it_pgm->second;
|
||||||
|
const auto& info = program->info;
|
||||||
|
size_t perm_idx = program->modules.size();
|
||||||
|
StageSpecialization spec{info, binding};
|
||||||
|
vk::ShaderModule module{};
|
||||||
|
|
||||||
|
const auto it = std::ranges::find(program->modules, spec, &Program::Module::spec);
|
||||||
|
if (it == program->modules.end()) {
|
||||||
|
auto new_info = MakeShaderInfo(pgm, liverpool->regs);
|
||||||
|
module = CompileModule(new_info, pgm.code, perm_idx, binding);
|
||||||
|
program->modules.emplace_back(module, std::move(spec));
|
||||||
|
} else {
|
||||||
|
binding += info.NumBindings();
|
||||||
|
module = it->module;
|
||||||
|
perm_idx = std::distance(program->modules.begin(), it);
|
||||||
|
}
|
||||||
|
return std::make_tuple(&info, module, HashCombine(pgm.hash, perm_idx));
|
||||||
|
}
|
||||||
|
|
||||||
void ShaderCache::DumpShader(std::span<const u32> code, u64 hash, Shader::Stage stage,
|
void ShaderCache::DumpShader(std::span<const u32> code, u64 hash, Shader::Stage stage,
|
||||||
size_t perm_idx, std::string_view ext) {
|
size_t perm_idx, std::string_view ext) {
|
||||||
using namespace Common::FS;
|
using namespace Common::FS;
|
||||||
|
|
|
@ -111,65 +111,37 @@ struct Program {
|
||||||
|
|
||||||
Shader::Info info;
|
Shader::Info info;
|
||||||
boost::container::small_vector<Module, 8> modules;
|
boost::container::small_vector<Module, 8> modules;
|
||||||
|
|
||||||
|
explicit Program(const Shader::Info& info_) : info{info_} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
Shader::Info MakeShaderInfo(Shader::Stage stage, std::span<const u32, 16> user_data, u64 pgm_base,
|
struct GuestProgram {
|
||||||
u64 hash, const AmdGpu::Liverpool::Regs& regs);
|
Shader::Stage stage;
|
||||||
|
std::span<const u32, AmdGpu::Liverpool::NumShaderUserData> user_data;
|
||||||
|
std::span<const u32> code;
|
||||||
|
u64 hash;
|
||||||
|
|
||||||
[[nodiscard]] inline u64 HashCombine(const u64 seed, const u64 hash) {
|
explicit GuestProgram(const auto* pgm, Shader::Stage stage_)
|
||||||
return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2));
|
: stage{stage_}, user_data{pgm->user_data}, code{pgm->Code()} {
|
||||||
}
|
const auto* bininfo = AmdGpu::Liverpool::GetBinaryInfo(*pgm);
|
||||||
|
hash = bininfo->shader_hash;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ShaderCache {
|
class ShaderCache {
|
||||||
public:
|
public:
|
||||||
explicit ShaderCache(const Instance& instance, AmdGpu::Liverpool* liverpool);
|
explicit ShaderCache(const Instance& instance, AmdGpu::Liverpool* liverpool);
|
||||||
~ShaderCache() = default;
|
~ShaderCache() = default;
|
||||||
|
|
||||||
void DumpShader(std::span<const u32> code, u64 hash, Shader::Stage stage, size_t perm_idx,
|
std::tuple<const Shader::Info*, vk::ShaderModule, u64> GetProgram(const GuestProgram& pgm,
|
||||||
std::string_view ext);
|
|
||||||
|
|
||||||
vk::ShaderModule CompileModule(Shader::Info& info, std::span<const u32> code, size_t perm_idx,
|
|
||||||
u32& binding);
|
u32& binding);
|
||||||
|
|
||||||
std::tuple<const Shader::Info*, vk::ShaderModule, u64> GetProgram(const auto* pgm,
|
private:
|
||||||
Shader::Stage stage,
|
void DumpShader(std::span<const u32> code, u64 hash, Shader::Stage stage, size_t perm_idx,
|
||||||
u32& binding) {
|
std::string_view ext);
|
||||||
// Fetch program for binaryinfo hash.
|
vk::ShaderModule CompileModule(Shader::Info& info, std::span<const u32> code, size_t perm_idx,
|
||||||
const auto* bininfo = AmdGpu::Liverpool::GetBinaryInfo(*pgm);
|
u32& binding);
|
||||||
const u64 hash = bininfo->shader_hash;
|
Program* CreateProgram(const GuestProgram& pgm, u32& binding);
|
||||||
auto [it_pgm, new_program] = program_cache.try_emplace(hash);
|
|
||||||
u64 stage_key{};
|
|
||||||
if (new_program) {
|
|
||||||
const VAddr pgm_base = pgm->template Address<VAddr>();
|
|
||||||
auto program = program_pool.Create();
|
|
||||||
program->info = MakeShaderInfo(stage, pgm->user_data, pgm_base, hash, liverpool->regs);
|
|
||||||
u32 start_binding = binding;
|
|
||||||
const auto module = CompileModule(program->info, pgm->Code(), 0, binding);
|
|
||||||
program->modules.emplace_back(module,
|
|
||||||
StageSpecialization{program->info, start_binding});
|
|
||||||
it_pgm.value() = program;
|
|
||||||
return std::make_tuple(&program->info, module, HashCombine(hash, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
Program* program = it_pgm->second;
|
|
||||||
const auto& info = program->info;
|
|
||||||
size_t perm_idx = program->modules.size();
|
|
||||||
StageSpecialization spec{info, binding};
|
|
||||||
vk::ShaderModule module{};
|
|
||||||
|
|
||||||
const auto it = std::ranges::find(program->modules, spec, &Program::Module::spec);
|
|
||||||
if (it == program->modules.end()) {
|
|
||||||
auto new_info = MakeShaderInfo(stage, pgm->user_data, info.pgm_base, info.pgm_hash,
|
|
||||||
liverpool->regs);
|
|
||||||
module = CompileModule(new_info, pgm->Code(), perm_idx, binding);
|
|
||||||
program->modules.emplace_back(module, std::move(spec));
|
|
||||||
} else {
|
|
||||||
binding += info.NumBindings();
|
|
||||||
module = it->module;
|
|
||||||
perm_idx = std::distance(program->modules.begin(), it);
|
|
||||||
}
|
|
||||||
return std::make_tuple(&info, module, HashCombine(hash, perm_idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Instance& instance;
|
const Instance& instance;
|
||||||
|
|
Loading…
Reference in New Issue