gl_shader_cache: Store workers in shader cache object

This commit is contained in:
ReinUsesLisp 2021-06-06 00:35:57 -03:00 committed by ameerj
parent cffd4716c5
commit 12fe7210d2
2 changed files with 74 additions and 54 deletions

View file

@ -239,6 +239,15 @@ void SetXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs
} }
} // Anonymous namespace } // Anonymous namespace
struct ShaderCache::Context {
explicit Context(Core::Frontend::EmuWindow& emu_window)
: gl_context{emu_window.CreateSharedContext()}, scoped{*gl_context} {}
std::unique_ptr<Core::Frontend::GraphicsContext> gl_context;
Core::Frontend::GraphicsContext::Scoped scoped;
ShaderPools pools;
};
ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_,
Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::Engines::Maxwell3D& maxwell3d_,
Tegra::Engines::KeplerCompute& kepler_compute_, Tegra::Engines::KeplerCompute& kepler_compute_,
@ -247,46 +256,49 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
ProgramManager& program_manager_, StateTracker& state_tracker_) ProgramManager& program_manager_, StateTracker& state_tracker_)
: VideoCommon::ShaderCache{rasterizer_, gpu_memory_, maxwell3d_, kepler_compute_}, : VideoCommon::ShaderCache{rasterizer_, gpu_memory_, maxwell3d_, kepler_compute_},
emu_window{emu_window_}, device{device_}, texture_cache{texture_cache_}, emu_window{emu_window_}, device{device_}, texture_cache{texture_cache_},
buffer_cache{buffer_cache_}, program_manager{program_manager_}, state_tracker{ buffer_cache{buffer_cache_}, program_manager{program_manager_}, state_tracker{state_tracker_},
state_tracker_} { use_asynchronous_shaders{device.UseAsynchronousShaders()},
profile = Shader::Profile{ profile{
.supported_spirv = 0x00010000, .supported_spirv = 0x00010000,
.unified_descriptor_binding = false, .unified_descriptor_binding = false,
.support_descriptor_aliasing = false, .support_descriptor_aliasing = false,
.support_int8 = false, .support_int8 = false,
.support_int16 = false, .support_int16 = false,
.support_vertex_instance_id = true, .support_vertex_instance_id = true,
.support_float_controls = false, .support_float_controls = false,
.support_separate_denorm_behavior = false, .support_separate_denorm_behavior = false,
.support_separate_rounding_mode = false, .support_separate_rounding_mode = false,
.support_fp16_denorm_preserve = false, .support_fp16_denorm_preserve = false,
.support_fp32_denorm_preserve = false, .support_fp32_denorm_preserve = false,
.support_fp16_denorm_flush = false, .support_fp16_denorm_flush = false,
.support_fp32_denorm_flush = false, .support_fp32_denorm_flush = false,
.support_fp16_signed_zero_nan_preserve = false, .support_fp16_signed_zero_nan_preserve = false,
.support_fp32_signed_zero_nan_preserve = false, .support_fp32_signed_zero_nan_preserve = false,
.support_fp64_signed_zero_nan_preserve = false, .support_fp64_signed_zero_nan_preserve = false,
.support_explicit_workgroup_layout = false, .support_explicit_workgroup_layout = false,
.support_vote = true, .support_vote = true,
.support_viewport_index_layer_non_geometry = .support_viewport_index_layer_non_geometry =
device.HasNvViewportArray2() || device.HasVertexViewportLayer(), device.HasNvViewportArray2() || device.HasVertexViewportLayer(),
.support_viewport_mask = device.HasNvViewportArray2(), .support_viewport_mask = device.HasNvViewportArray2(),
.support_typeless_image_loads = device.HasImageLoadFormatted(), .support_typeless_image_loads = device.HasImageLoadFormatted(),
.support_demote_to_helper_invocation = false, .support_demote_to_helper_invocation = false,
.support_int64_atomics = false, .support_int64_atomics = false,
.support_derivative_control = device.HasDerivativeControl(), .support_derivative_control = device.HasDerivativeControl(),
.warp_size_potentially_larger_than_guest = true, .warp_size_potentially_larger_than_guest = true,
.lower_left_origin_mode = true, .lower_left_origin_mode = true,
.need_declared_frag_colors = true, .need_declared_frag_colors = true,
.has_broken_spirv_clamp = true, .has_broken_spirv_clamp = true,
.has_broken_unsigned_image_offsets = true, .has_broken_unsigned_image_offsets = true,
.has_broken_signed_operations = true, .has_broken_signed_operations = true,
.ignore_nan_fp_comparisons = true, .ignore_nan_fp_comparisons = true,
}; } {
if (use_asynchronous_shaders) {
workers = CreateWorkers();
}
} }
ShaderCache::~ShaderCache() = default; ShaderCache::~ShaderCache() = default;
@ -307,29 +319,20 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
} }
shader_cache_filename = transferable_dir / fmt::format("{:016x}.bin", title_id); shader_cache_filename = transferable_dir / fmt::format("{:016x}.bin", title_id);
struct Context { if (!workers) {
explicit Context(Core::Frontend::EmuWindow& emu_window) workers = CreateWorkers();
: gl_context{emu_window.CreateSharedContext()}, scoped{*gl_context} {} }
std::unique_ptr<Core::Frontend::GraphicsContext> gl_context;
Core::Frontend::GraphicsContext::Scoped scoped;
ShaderPools pools;
};
Common::StatefulThreadWorker<Context> workers(
std::max(std::thread::hardware_concurrency(), 2U) - 1, "yuzu:ShaderBuilder",
[this] { return Context{emu_window}; });
struct { struct {
std::mutex mutex; std::mutex mutex;
size_t total{0}; size_t total{};
size_t built{0}; size_t built{};
bool has_loaded{false}; bool has_loaded{};
} state; } state;
const auto load_compute{[&](std::ifstream& file, FileEnvironment env) { const auto load_compute{[&](std::ifstream& file, FileEnvironment env) {
ComputePipelineKey key; ComputePipelineKey key;
file.read(reinterpret_cast<char*>(&key), sizeof(key)); file.read(reinterpret_cast<char*>(&key), sizeof(key));
workers.QueueWork( workers->QueueWork(
[this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { [this, key, env = std::move(env), &state, &callback](Context* ctx) mutable {
ctx->pools.ReleaseContents(); ctx->pools.ReleaseContents();
auto pipeline{CreateComputePipeline(ctx->pools, key, env)}; auto pipeline{CreateComputePipeline(ctx->pools, key, env)};
@ -347,7 +350,7 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) { const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) {
GraphicsPipelineKey key; GraphicsPipelineKey key;
file.read(reinterpret_cast<char*>(&key), sizeof(key)); file.read(reinterpret_cast<char*>(&key), sizeof(key));
workers.QueueWork( workers->QueueWork(
[this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable { [this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable {
boost::container::static_vector<Shader::Environment*, 5> env_ptrs; boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
for (auto& env : envs) { for (auto& env : envs) {
@ -373,7 +376,10 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
state.has_loaded = true; state.has_loaded = true;
lock.unlock(); lock.unlock();
workers.WaitForRequests(); workers->WaitForRequests();
if (!use_asynchronous_shaders) {
workers.reset();
}
} }
GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() {
@ -570,4 +576,11 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(ShaderPools&
return nullptr; return nullptr;
} }
std::unique_ptr<Common::StatefulThreadWorker<ShaderCache::Context>> ShaderCache::CreateWorkers()
const {
return std::make_unique<Common::StatefulThreadWorker<Context>>(
std::max(std::thread::hardware_concurrency(), 2U) - 1, "yuzu:ShaderBuilder",
[this] { return Context{emu_window}; });
}
} // namespace OpenGL } // namespace OpenGL

View file

@ -12,6 +12,7 @@
#include <glad/glad.h> #include <glad/glad.h>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/thread_worker.h"
#include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/basic_block.h"
#include "shader_recompiler/frontend/ir/value.h" #include "shader_recompiler/frontend/ir/value.h"
#include "shader_recompiler/frontend/maxwell/control_flow.h" #include "shader_recompiler/frontend/maxwell/control_flow.h"
@ -44,6 +45,8 @@ struct ShaderPools {
}; };
class ShaderCache : public VideoCommon::ShaderCache { class ShaderCache : public VideoCommon::ShaderCache {
struct Context;
public: public:
explicit ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, explicit ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_,
Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::Engines::Maxwell3D& maxwell3d_,
@ -74,6 +77,8 @@ private:
const ComputePipelineKey& key, const ComputePipelineKey& key,
Shader::Environment& env); Shader::Environment& env);
std::unique_ptr<Common::StatefulThreadWorker<Context>> CreateWorkers() const;
Core::Frontend::EmuWindow& emu_window; Core::Frontend::EmuWindow& emu_window;
const Device& device; const Device& device;
TextureCache& texture_cache; TextureCache& texture_cache;
@ -82,6 +87,7 @@ private:
StateTracker& state_tracker; StateTracker& state_tracker;
GraphicsPipelineKey graphics_key{}; GraphicsPipelineKey graphics_key{};
const bool use_asynchronous_shaders;
ShaderPools main_pools; ShaderPools main_pools;
std::unordered_map<GraphicsPipelineKey, std::unique_ptr<GraphicsPipeline>> graphics_cache; std::unordered_map<GraphicsPipelineKey, std::unique_ptr<GraphicsPipeline>> graphics_cache;
@ -89,6 +95,7 @@ private:
Shader::Profile profile; Shader::Profile profile;
std::filesystem::path shader_cache_filename; std::filesystem::path shader_cache_filename;
std::unique_ptr<Common::StatefulThreadWorker<Context>> workers;
}; };
} // namespace OpenGL } // namespace OpenGL