vk_pipeline_cache: Use generic shader cache
Trivial port the generic shader cache to Vulkan.
This commit is contained in:
parent
b96f65b62b
commit
678f95e4f8
|
@ -195,9 +195,9 @@ std::unordered_set<GLenum> GetSupportedFormats() {
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
Shader::Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry, ShaderEntries entries,
|
Shader::Shader(std::shared_ptr<VideoCommon::Shader::Registry> registry_, ShaderEntries entries_,
|
||||||
ProgramSharedPtr program)
|
ProgramSharedPtr program_)
|
||||||
: registry{std::move(registry)}, entries{std::move(entries)}, program{std::move(program)} {
|
: registry{std::move(registry_)}, entries{std::move(entries_)}, program{std::move(program_)} {
|
||||||
handle = program->assembly_program.handle;
|
handle = program->assembly_program.handle;
|
||||||
if (handle == 0) {
|
if (handle == 0) {
|
||||||
handle = program->source_program.handle;
|
handle = program->source_program.handle;
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "video_core/renderer_vulkan/wrapper.h"
|
#include "video_core/renderer_vulkan/wrapper.h"
|
||||||
#include "video_core/shader/compiler_settings.h"
|
#include "video_core/shader/compiler_settings.h"
|
||||||
#include "video_core/shader/memory_util.h"
|
#include "video_core/shader/memory_util.h"
|
||||||
|
#include "video_core/shader_cache.h"
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
|
@ -130,19 +131,18 @@ bool ComputePipelineCacheKey::operator==(const ComputePipelineCacheKey& rhs) con
|
||||||
return std::memcmp(&rhs, this, sizeof *this) == 0;
|
return std::memcmp(&rhs, this, sizeof *this) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedShader::CachedShader(Core::System& system, Tegra::Engines::ShaderType stage,
|
Shader::Shader(Core::System& system, Tegra::Engines::ShaderType stage, GPUVAddr gpu_addr,
|
||||||
GPUVAddr gpu_addr, VAddr cpu_addr, ProgramCode program_code,
|
VideoCommon::Shader::ProgramCode program_code, u32 main_offset)
|
||||||
u32 main_offset)
|
: gpu_addr{gpu_addr}, program_code{std::move(program_code)},
|
||||||
: RasterizerCacheObject{cpu_addr}, gpu_addr{gpu_addr}, program_code{std::move(program_code)},
|
|
||||||
registry{stage, GetEngine(system, stage)}, shader_ir{this->program_code, main_offset,
|
registry{stage, GetEngine(system, stage)}, shader_ir{this->program_code, main_offset,
|
||||||
compiler_settings, registry},
|
compiler_settings, registry},
|
||||||
entries{GenerateShaderEntries(shader_ir)} {}
|
entries{GenerateShaderEntries(shader_ir)} {}
|
||||||
|
|
||||||
CachedShader::~CachedShader() = default;
|
Shader::~Shader() = default;
|
||||||
|
|
||||||
Tegra::Engines::ConstBufferEngineInterface& CachedShader::GetEngine(
|
Tegra::Engines::ConstBufferEngineInterface& Shader::GetEngine(Core::System& system,
|
||||||
Core::System& system, Tegra::Engines::ShaderType stage) {
|
Tegra::Engines::ShaderType stage) {
|
||||||
if (stage == Tegra::Engines::ShaderType::Compute) {
|
if (stage == ShaderType::Compute) {
|
||||||
return system.GPU().KeplerCompute();
|
return system.GPU().KeplerCompute();
|
||||||
} else {
|
} else {
|
||||||
return system.GPU().Maxwell3D();
|
return system.GPU().Maxwell3D();
|
||||||
|
@ -154,16 +154,16 @@ VKPipelineCache::VKPipelineCache(Core::System& system, RasterizerVulkan& rasteri
|
||||||
VKDescriptorPool& descriptor_pool,
|
VKDescriptorPool& descriptor_pool,
|
||||||
VKUpdateDescriptorQueue& update_descriptor_queue,
|
VKUpdateDescriptorQueue& update_descriptor_queue,
|
||||||
VKRenderPassCache& renderpass_cache)
|
VKRenderPassCache& renderpass_cache)
|
||||||
: RasterizerCache{rasterizer}, system{system}, device{device}, scheduler{scheduler},
|
: VideoCommon::ShaderCache<Shader>{rasterizer}, system{system}, device{device},
|
||||||
descriptor_pool{descriptor_pool}, update_descriptor_queue{update_descriptor_queue},
|
scheduler{scheduler}, descriptor_pool{descriptor_pool},
|
||||||
renderpass_cache{renderpass_cache} {}
|
update_descriptor_queue{update_descriptor_queue}, renderpass_cache{renderpass_cache} {}
|
||||||
|
|
||||||
VKPipelineCache::~VKPipelineCache() = default;
|
VKPipelineCache::~VKPipelineCache() = default;
|
||||||
|
|
||||||
std::array<Shader, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() {
|
std::array<Shader*, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() {
|
||||||
const auto& gpu = system.GPU().Maxwell3D();
|
const auto& gpu = system.GPU().Maxwell3D();
|
||||||
|
|
||||||
std::array<Shader, Maxwell::MaxShaderProgram> shaders;
|
std::array<Shader*, Maxwell::MaxShaderProgram> shaders{};
|
||||||
for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
|
for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
|
||||||
const auto program{static_cast<Maxwell::ShaderProgram>(index)};
|
const auto program{static_cast<Maxwell::ShaderProgram>(index)};
|
||||||
|
|
||||||
|
@ -176,24 +176,28 @@ std::array<Shader, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() {
|
||||||
const GPUVAddr program_addr{GetShaderAddress(system, program)};
|
const GPUVAddr program_addr{GetShaderAddress(system, program)};
|
||||||
const std::optional cpu_addr = memory_manager.GpuToCpuAddress(program_addr);
|
const std::optional cpu_addr = memory_manager.GpuToCpuAddress(program_addr);
|
||||||
ASSERT(cpu_addr);
|
ASSERT(cpu_addr);
|
||||||
auto shader = cpu_addr ? TryGet(*cpu_addr) : null_shader;
|
|
||||||
if (!shader) {
|
Shader* result = cpu_addr ? TryGet(*cpu_addr) : null_shader.get();
|
||||||
|
if (!result) {
|
||||||
const auto host_ptr{memory_manager.GetPointer(program_addr)};
|
const auto host_ptr{memory_manager.GetPointer(program_addr)};
|
||||||
|
|
||||||
// No shader found - create a new one
|
// No shader found - create a new one
|
||||||
constexpr u32 stage_offset = STAGE_MAIN_OFFSET;
|
constexpr u32 stage_offset = STAGE_MAIN_OFFSET;
|
||||||
const auto stage = static_cast<Tegra::Engines::ShaderType>(index == 0 ? 0 : index - 1);
|
const auto stage = static_cast<ShaderType>(index == 0 ? 0 : index - 1);
|
||||||
ProgramCode code = GetShaderCode(memory_manager, program_addr, host_ptr, false);
|
ProgramCode code = GetShaderCode(memory_manager, program_addr, host_ptr, false);
|
||||||
|
const std::size_t size_in_bytes = code.size() * sizeof(u64);
|
||||||
|
|
||||||
|
auto shader = std::make_unique<Shader>(system, stage, program_addr, std::move(code),
|
||||||
|
stage_offset);
|
||||||
|
result = shader.get();
|
||||||
|
|
||||||
shader = std::make_shared<CachedShader>(system, stage, program_addr, *cpu_addr,
|
|
||||||
std::move(code), stage_offset);
|
|
||||||
if (cpu_addr) {
|
if (cpu_addr) {
|
||||||
Register(shader);
|
Register(std::move(shader), *cpu_addr, size_in_bytes);
|
||||||
} else {
|
} else {
|
||||||
null_shader = shader;
|
null_shader = std::move(shader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
shaders[index] = std::move(shader);
|
shaders[index] = result;
|
||||||
}
|
}
|
||||||
return last_shaders = shaders;
|
return last_shaders = shaders;
|
||||||
}
|
}
|
||||||
|
@ -234,19 +238,22 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach
|
||||||
const auto cpu_addr = memory_manager.GpuToCpuAddress(program_addr);
|
const auto cpu_addr = memory_manager.GpuToCpuAddress(program_addr);
|
||||||
ASSERT(cpu_addr);
|
ASSERT(cpu_addr);
|
||||||
|
|
||||||
auto shader = cpu_addr ? TryGet(*cpu_addr) : null_kernel;
|
Shader* shader = cpu_addr ? TryGet(*cpu_addr) : null_kernel.get();
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
// No shader found - create a new one
|
// No shader found - create a new one
|
||||||
const auto host_ptr = memory_manager.GetPointer(program_addr);
|
const auto host_ptr = memory_manager.GetPointer(program_addr);
|
||||||
|
|
||||||
ProgramCode code = GetShaderCode(memory_manager, program_addr, host_ptr, true);
|
ProgramCode code = GetShaderCode(memory_manager, program_addr, host_ptr, true);
|
||||||
shader = std::make_shared<CachedShader>(system, Tegra::Engines::ShaderType::Compute,
|
const std::size_t size_in_bytes = code.size() * sizeof(u64);
|
||||||
program_addr, *cpu_addr, std::move(code),
|
|
||||||
KERNEL_MAIN_OFFSET);
|
auto shader_info = std::make_unique<Shader>(system, ShaderType::Compute, program_addr,
|
||||||
|
std::move(code), KERNEL_MAIN_OFFSET);
|
||||||
|
shader = shader_info.get();
|
||||||
|
|
||||||
if (cpu_addr) {
|
if (cpu_addr) {
|
||||||
Register(shader);
|
Register(std::move(shader_info), *cpu_addr, size_in_bytes);
|
||||||
} else {
|
} else {
|
||||||
null_kernel = shader;
|
null_kernel = std::move(shader_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +269,7 @@ VKComputePipeline& VKPipelineCache::GetComputePipeline(const ComputePipelineCach
|
||||||
return *entry;
|
return *entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKPipelineCache::Unregister(const Shader& shader) {
|
void VKPipelineCache::OnShaderRemoval(Shader* shader) {
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
const auto Finish = [&] {
|
const auto Finish = [&] {
|
||||||
// TODO(Rodrigo): Instead of finishing here, wait for the fences that use this pipeline and
|
// TODO(Rodrigo): Instead of finishing here, wait for the fences that use this pipeline and
|
||||||
|
@ -294,8 +301,6 @@ void VKPipelineCache::Unregister(const Shader& shader) {
|
||||||
Finish();
|
Finish();
|
||||||
it = compute_cache.erase(it);
|
it = compute_cache.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
RasterizerCache::Unregister(shader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>>
|
std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>>
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/engines/const_buffer_engine_interface.h"
|
#include "video_core/engines/const_buffer_engine_interface.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/rasterizer_cache.h"
|
|
||||||
#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
|
#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
|
||||||
#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
|
#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
|
||||||
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
|
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
|
||||||
|
@ -26,6 +25,7 @@
|
||||||
#include "video_core/shader/memory_util.h"
|
#include "video_core/shader/memory_util.h"
|
||||||
#include "video_core/shader/registry.h"
|
#include "video_core/shader/registry.h"
|
||||||
#include "video_core/shader/shader_ir.h"
|
#include "video_core/shader/shader_ir.h"
|
||||||
|
#include "video_core/shader_cache.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
|
@ -41,8 +41,6 @@ class VKFence;
|
||||||
class VKScheduler;
|
class VKScheduler;
|
||||||
class VKUpdateDescriptorQueue;
|
class VKUpdateDescriptorQueue;
|
||||||
|
|
||||||
class CachedShader;
|
|
||||||
using Shader = std::shared_ptr<CachedShader>;
|
|
||||||
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
||||||
|
|
||||||
struct GraphicsPipelineCacheKey {
|
struct GraphicsPipelineCacheKey {
|
||||||
|
@ -102,21 +100,16 @@ struct hash<Vulkan::ComputePipelineCacheKey> {
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
class CachedShader final : public RasterizerCacheObject {
|
class Shader {
|
||||||
public:
|
public:
|
||||||
explicit CachedShader(Core::System& system, Tegra::Engines::ShaderType stage, GPUVAddr gpu_addr,
|
explicit Shader(Core::System& system, Tegra::Engines::ShaderType stage, GPUVAddr gpu_addr,
|
||||||
VAddr cpu_addr, VideoCommon::Shader::ProgramCode program_code,
|
VideoCommon::Shader::ProgramCode program_code, u32 main_offset);
|
||||||
u32 main_offset);
|
~Shader();
|
||||||
~CachedShader();
|
|
||||||
|
|
||||||
GPUVAddr GetGpuAddr() const {
|
GPUVAddr GetGpuAddr() const {
|
||||||
return gpu_addr;
|
return gpu_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t GetSizeInBytes() const override {
|
|
||||||
return program_code.size() * sizeof(u64);
|
|
||||||
}
|
|
||||||
|
|
||||||
VideoCommon::Shader::ShaderIR& GetIR() {
|
VideoCommon::Shader::ShaderIR& GetIR() {
|
||||||
return shader_ir;
|
return shader_ir;
|
||||||
}
|
}
|
||||||
|
@ -144,25 +137,23 @@ private:
|
||||||
ShaderEntries entries;
|
ShaderEntries entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VKPipelineCache final : public RasterizerCache<Shader> {
|
class VKPipelineCache final : public VideoCommon::ShaderCache<Shader> {
|
||||||
public:
|
public:
|
||||||
explicit VKPipelineCache(Core::System& system, RasterizerVulkan& rasterizer,
|
explicit VKPipelineCache(Core::System& system, RasterizerVulkan& rasterizer,
|
||||||
const VKDevice& device, VKScheduler& scheduler,
|
const VKDevice& device, VKScheduler& scheduler,
|
||||||
VKDescriptorPool& descriptor_pool,
|
VKDescriptorPool& descriptor_pool,
|
||||||
VKUpdateDescriptorQueue& update_descriptor_queue,
|
VKUpdateDescriptorQueue& update_descriptor_queue,
|
||||||
VKRenderPassCache& renderpass_cache);
|
VKRenderPassCache& renderpass_cache);
|
||||||
~VKPipelineCache();
|
~VKPipelineCache() override;
|
||||||
|
|
||||||
std::array<Shader, Maxwell::MaxShaderProgram> GetShaders();
|
std::array<Shader*, Maxwell::MaxShaderProgram> GetShaders();
|
||||||
|
|
||||||
VKGraphicsPipeline& GetGraphicsPipeline(const GraphicsPipelineCacheKey& key);
|
VKGraphicsPipeline& GetGraphicsPipeline(const GraphicsPipelineCacheKey& key);
|
||||||
|
|
||||||
VKComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key);
|
VKComputePipeline& GetComputePipeline(const ComputePipelineCacheKey& key);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void Unregister(const Shader& shader) override;
|
void OnShaderRemoval(Shader* shader) final;
|
||||||
|
|
||||||
void FlushObjectInner(const Shader& object) override {}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>> DecompileShaders(
|
std::pair<SPIRVProgram, std::vector<VkDescriptorSetLayoutBinding>> DecompileShaders(
|
||||||
|
@ -175,10 +166,10 @@ private:
|
||||||
VKUpdateDescriptorQueue& update_descriptor_queue;
|
VKUpdateDescriptorQueue& update_descriptor_queue;
|
||||||
VKRenderPassCache& renderpass_cache;
|
VKRenderPassCache& renderpass_cache;
|
||||||
|
|
||||||
Shader null_shader{};
|
std::unique_ptr<Shader> null_shader;
|
||||||
Shader null_kernel{};
|
std::unique_ptr<Shader> null_kernel;
|
||||||
|
|
||||||
std::array<Shader, Maxwell::MaxShaderProgram> last_shaders;
|
std::array<Shader*, Maxwell::MaxShaderProgram> last_shaders{};
|
||||||
|
|
||||||
GraphicsPipelineCacheKey last_graphics_key;
|
GraphicsPipelineCacheKey last_graphics_key;
|
||||||
VKGraphicsPipeline* last_graphics_pipeline = nullptr;
|
VKGraphicsPipeline* last_graphics_pipeline = nullptr;
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
||||||
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
||||||
#include "video_core/renderer_vulkan/wrapper.h"
|
#include "video_core/renderer_vulkan/wrapper.h"
|
||||||
|
#include "video_core/shader_cache.h"
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
|
@ -98,7 +99,7 @@ VkRect2D GetScissorState(const Maxwell& regs, std::size_t index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<GPUVAddr, Maxwell::MaxShaderProgram> GetShaderAddresses(
|
std::array<GPUVAddr, Maxwell::MaxShaderProgram> GetShaderAddresses(
|
||||||
const std::array<Shader, Maxwell::MaxShaderProgram>& shaders) {
|
const std::array<Shader*, Maxwell::MaxShaderProgram>& shaders) {
|
||||||
std::array<GPUVAddr, Maxwell::MaxShaderProgram> addresses;
|
std::array<GPUVAddr, Maxwell::MaxShaderProgram> addresses;
|
||||||
for (std::size_t i = 0; i < std::size(addresses); ++i) {
|
for (std::size_t i = 0; i < std::size(addresses); ++i) {
|
||||||
addresses[i] = shaders[i] ? shaders[i]->GetGpuAddr() : 0;
|
addresses[i] = shaders[i] ? shaders[i]->GetGpuAddr() : 0;
|
||||||
|
@ -775,12 +776,12 @@ RasterizerVulkan::DrawParameters RasterizerVulkan::SetupGeometry(FixedPipelineSt
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::SetupShaderDescriptors(
|
void RasterizerVulkan::SetupShaderDescriptors(
|
||||||
const std::array<Shader, Maxwell::MaxShaderProgram>& shaders) {
|
const std::array<Shader*, Maxwell::MaxShaderProgram>& shaders) {
|
||||||
texture_cache.GuardSamplers(true);
|
texture_cache.GuardSamplers(true);
|
||||||
|
|
||||||
for (std::size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
|
for (std::size_t stage = 0; stage < Maxwell::MaxShaderStage; ++stage) {
|
||||||
// Skip VertexA stage
|
// Skip VertexA stage
|
||||||
const auto& shader = shaders[stage + 1];
|
Shader* const shader = shaders[stage + 1];
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,7 @@ private:
|
||||||
bool is_indexed, bool is_instanced);
|
bool is_indexed, bool is_instanced);
|
||||||
|
|
||||||
/// Setup descriptors in the graphics pipeline.
|
/// Setup descriptors in the graphics pipeline.
|
||||||
void SetupShaderDescriptors(const std::array<Shader, Maxwell::MaxShaderProgram>& shaders);
|
void SetupShaderDescriptors(const std::array<Shader*, Maxwell::MaxShaderProgram>& shaders);
|
||||||
|
|
||||||
void SetupImageTransitions(Texceptions texceptions,
|
void SetupImageTransitions(Texceptions texceptions,
|
||||||
const std::array<View, Maxwell::NumRenderTargets>& color_attachments,
|
const std::array<View, Maxwell::NumRenderTargets>& color_attachments,
|
||||||
|
|
Reference in New Issue