summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-09-26 00:23:08 -0300
committerGravatar FernandoS272019-10-25 09:01:32 -0400
commit78f3e8a75792c976eb5bfa6df4c020d898642684 (patch)
tree4c7103c396f180654850362c89d01b46358e58cb
parentgl_shader_disk_cache: Store and load fast BRX (diff)
downloadyuzu-78f3e8a75792c976eb5bfa6df4c020d898642684.tar.gz
yuzu-78f3e8a75792c976eb5bfa6df4c020d898642684.tar.xz
yuzu-78f3e8a75792c976eb5bfa6df4c020d898642684.zip
gl_shader_cache: Implement locker variants invalidation
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp102
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h15
-rw-r--r--src/video_core/shader/const_buffer_locker.cpp28
-rw-r--r--src/video_core/shader/const_buffer_locker.h3
4 files changed, 104 insertions, 44 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 7e7aea15f..f1b89165d 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -225,6 +225,34 @@ std::string GetShaderId(u64 unique_identifier, ProgramType program_type) {
225 return fmt::format("{}{:016X}", GetProgramTypeName(program_type), unique_identifier); 225 return fmt::format("{}{:016X}", GetProgramTypeName(program_type), unique_identifier);
226} 226}
227 227
228Tegra::Engines::ConstBufferEngineInterface& GetConstBufferEngineInterface(
229 Core::System& system, ProgramType program_type) {
230 if (program_type == ProgramType::Compute) {
231 return system.GPU().KeplerCompute();
232 } else {
233 return system.GPU().Maxwell3D();
234 }
235}
236
237std::unique_ptr<ConstBufferLocker> MakeLocker(Core::System& system, ProgramType program_type) {
238 return std::make_unique<ConstBufferLocker>(GetEnginesShaderType(program_type),
239 GetConstBufferEngineInterface(system, program_type));
240}
241
242void FillLocker(ConstBufferLocker& locker, const ShaderDiskCacheUsage& usage) {
243 for (const auto& key : usage.keys) {
244 const auto [buffer, offset] = key.first;
245 locker.InsertKey(buffer, offset, key.second);
246 }
247 for (const auto& [offset, sampler] : usage.bound_samplers) {
248 locker.InsertBoundSampler(offset, sampler);
249 }
250 for (const auto& [key, sampler] : usage.bindless_samplers) {
251 const auto [buffer, offset] = key;
252 locker.InsertBindlessSampler(buffer, offset, sampler);
253 }
254}
255
228CachedProgram BuildShader(const Device& device, u64 unique_identifier, ProgramType program_type, 256CachedProgram BuildShader(const Device& device, u64 unique_identifier, ProgramType program_type,
229 const ProgramCode& program_code, const ProgramCode& program_code_b, 257 const ProgramCode& program_code, const ProgramCode& program_code_b,
230 const ProgramVariant& variant, ConstBufferLocker& locker, 258 const ProgramVariant& variant, ConstBufferLocker& locker,
@@ -336,11 +364,27 @@ CachedShader::CachedShader(const ShaderParameters& params, ProgramType program_t
336 disk_cache{params.disk_cache}, device{params.device}, cpu_addr{params.cpu_addr}, 364 disk_cache{params.disk_cache}, device{params.device}, cpu_addr{params.cpu_addr},
337 unique_identifier{params.unique_identifier}, program_type{program_type}, entries{entries}, 365 unique_identifier{params.unique_identifier}, program_type{program_type}, entries{entries},
338 program_code{std::move(program_code)}, program_code_b{std::move(program_code_b)} { 366 program_code{std::move(program_code)}, program_code_b{std::move(program_code_b)} {
339 if (params.precompiled_variants) { 367 if (!params.precompiled_variants) {
340 for (const auto& pair : *params.precompiled_variants) { 368 return;
341 const auto& variant = pair->first.variant; 369 }
342 programs.emplace(variant, pair->second); 370 for (const auto& pair : *params.precompiled_variants) {
371 auto locker = MakeLocker(system, program_type);
372 const auto& usage = pair->first;
373 FillLocker(*locker, usage);
374
375 std::unique_ptr<LockerVariant>* locker_variant = nullptr;
376 const auto it =
377 std::find_if(locker_variants.begin(), locker_variants.end(), [&](const auto& variant) {
378 return variant->locker->HasEqualKeys(*locker);
379 });
380 if (it == locker_variants.end()) {
381 locker_variant = &locker_variants.emplace_back();
382 *locker_variant = std::make_unique<LockerVariant>();
383 locker_variant->get()->locker = std::move(locker);
384 } else {
385 locker_variant = &*it;
343 } 386 }
387 locker_variant->get()->programs.emplace(usage.variant, pair->second);
344 } 388 }
345} 389}
346 390
@@ -380,19 +424,14 @@ Shader CachedShader::CreateFromCache(const ShaderParameters& params,
380} 424}
381 425
382std::tuple<GLuint, BaseBindings> CachedShader::GetProgramHandle(const ProgramVariant& variant) { 426std::tuple<GLuint, BaseBindings> CachedShader::GetProgramHandle(const ProgramVariant& variant) {
383 const auto [entry, is_cache_miss] = programs.try_emplace(variant); 427 UpdateVariant();
428
429 const auto [entry, is_cache_miss] = curr_variant->programs.try_emplace(variant);
384 auto& program = entry->second; 430 auto& program = entry->second;
385 if (is_cache_miss) { 431 if (is_cache_miss) {
386 Tegra::Engines::ConstBufferEngineInterface* engine = nullptr;
387 if (program_type == ProgramType::Compute) {
388 engine = &system.GPU().KeplerCompute();
389 } else {
390 engine = &system.GPU().Maxwell3D();
391 }
392 ConstBufferLocker locker(GetEnginesShaderType(program_type), *engine);
393 program = BuildShader(device, unique_identifier, program_type, program_code, program_code_b, 432 program = BuildShader(device, unique_identifier, program_type, program_code, program_code_b,
394 variant, locker); 433 variant, *curr_variant->locker);
395 disk_cache.SaveUsage(GetUsage(variant, locker)); 434 disk_cache.SaveUsage(GetUsage(variant, *curr_variant->locker));
396 435
397 LabelGLObject(GL_PROGRAM, program->handle, cpu_addr); 436 LabelGLObject(GL_PROGRAM, program->handle, cpu_addr);
398 } 437 }
@@ -408,6 +447,25 @@ std::tuple<GLuint, BaseBindings> CachedShader::GetProgramHandle(const ProgramVar
408 return {program->handle, base_bindings}; 447 return {program->handle, base_bindings};
409} 448}
410 449
450void CachedShader::UpdateVariant() {
451 if (curr_variant && !curr_variant->locker->IsConsistent()) {
452 curr_variant = nullptr;
453 }
454 if (!curr_variant) {
455 for (auto& variant : locker_variants) {
456 if (variant->locker->IsConsistent()) {
457 curr_variant = variant.get();
458 }
459 }
460 }
461 if (!curr_variant) {
462 auto& new_variant = locker_variants.emplace_back();
463 new_variant = std::make_unique<LockerVariant>();
464 new_variant->locker = MakeLocker(system, program_type);
465 curr_variant = new_variant.get();
466 }
467}
468
411ShaderDiskCacheUsage CachedShader::GetUsage(const ProgramVariant& variant, 469ShaderDiskCacheUsage CachedShader::GetUsage(const ProgramVariant& variant,
412 const ConstBufferLocker& locker) const { 470 const ConstBufferLocker& locker) const {
413 ShaderDiskCacheUsage usage; 471 ShaderDiskCacheUsage usage;
@@ -475,21 +533,11 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
475 } 533 }
476 } 534 }
477 if (!shader) { 535 if (!shader) {
478 ConstBufferLocker locker(GetEnginesShaderType(unspecialized.program_type)); 536 auto locker{MakeLocker(system, unspecialized.program_type)};
479 for (const auto& key : usage.keys) { 537 FillLocker(*locker, usage);
480 const auto [buffer, offset] = key.first;
481 locker.InsertKey(buffer, offset, key.second);
482 }
483 for (const auto& [offset, sampler] : usage.bound_samplers) {
484 locker.InsertBoundSampler(offset, sampler);
485 }
486 for (const auto& [key, sampler] : usage.bindless_samplers) {
487 const auto [buffer, offset] = key;
488 locker.InsertBindlessSampler(buffer, offset, sampler);
489 }
490 shader = BuildShader(device, usage.unique_identifier, unspecialized.program_type, 538 shader = BuildShader(device, usage.unique_identifier, unspecialized.program_type,
491 unspecialized.code, unspecialized.code_b, usage.variant, 539 unspecialized.code, unspecialized.code_b, usage.variant,
492 locker, true); 540 *locker, true);
493 } 541 }
494 542
495 std::scoped_lock lock{mutex}; 543 std::scoped_lock lock{mutex};
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index 2935e6831..6bd7c9cf1 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -21,6 +21,7 @@
21#include "video_core/renderer_opengl/gl_resource_manager.h" 21#include "video_core/renderer_opengl/gl_resource_manager.h"
22#include "video_core/renderer_opengl/gl_shader_decompiler.h" 22#include "video_core/renderer_opengl/gl_shader_decompiler.h"
23#include "video_core/renderer_opengl/gl_shader_disk_cache.h" 23#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
24#include "video_core/shader/const_buffer_locker.h"
24#include "video_core/shader/shader_ir.h" 25#include "video_core/shader/shader_ir.h"
25 26
26namespace Core { 27namespace Core {
@@ -31,10 +32,6 @@ namespace Core::Frontend {
31class EmuWindow; 32class EmuWindow;
32} 33}
33 34
34namespace VideoCommon::Shader {
35class ConstBufferLocker;
36}
37
38namespace OpenGL { 35namespace OpenGL {
39 36
40class CachedShader; 37class CachedShader;
@@ -92,10 +89,17 @@ public:
92 std::tuple<GLuint, BaseBindings> GetProgramHandle(const ProgramVariant& variant); 89 std::tuple<GLuint, BaseBindings> GetProgramHandle(const ProgramVariant& variant);
93 90
94private: 91private:
92 struct LockerVariant {
93 std::unique_ptr<VideoCommon::Shader::ConstBufferLocker> locker;
94 std::unordered_map<ProgramVariant, CachedProgram> programs;
95 };
96
95 explicit CachedShader(const ShaderParameters& params, ProgramType program_type, 97 explicit CachedShader(const ShaderParameters& params, ProgramType program_type,
96 GLShader::ShaderEntries entries, ProgramCode program_code, 98 GLShader::ShaderEntries entries, ProgramCode program_code,
97 ProgramCode program_code_b); 99 ProgramCode program_code_b);
98 100
101 void UpdateVariant();
102
99 ShaderDiskCacheUsage GetUsage(const ProgramVariant& variant, 103 ShaderDiskCacheUsage GetUsage(const ProgramVariant& variant,
100 const VideoCommon::Shader::ConstBufferLocker& locker) const; 104 const VideoCommon::Shader::ConstBufferLocker& locker) const;
101 105
@@ -113,7 +117,8 @@ private:
113 ProgramCode program_code; 117 ProgramCode program_code;
114 ProgramCode program_code_b; 118 ProgramCode program_code_b;
115 119
116 std::unordered_map<ProgramVariant, CachedProgram> programs; 120 LockerVariant* curr_variant = nullptr;
121 std::vector<std::unique_ptr<LockerVariant>> locker_variants;
117}; 122};
118 123
119class ShaderCacheOpenGL final : public RasterizerCache<Shader> { 124class ShaderCacheOpenGL final : public RasterizerCache<Shader> {
diff --git a/src/video_core/shader/const_buffer_locker.cpp b/src/video_core/shader/const_buffer_locker.cpp
index fda9e3c38..592bbf657 100644
--- a/src/video_core/shader/const_buffer_locker.cpp
+++ b/src/video_core/shader/const_buffer_locker.cpp
@@ -82,23 +82,27 @@ bool ConstBufferLocker::IsConsistent() const {
82 return false; 82 return false;
83 } 83 }
84 return std::all_of(keys.begin(), keys.end(), 84 return std::all_of(keys.begin(), keys.end(),
85 [](const auto& key) { 85 [this](const auto& pair) {
86 const auto [value, other_value] = key.first; 86 const auto [cbuf, offset] = pair.first;
87 return value == other_value; 87 const auto value = pair.second;
88 return value == engine->AccessConstBuffer32(stage, cbuf, offset);
88 }) && 89 }) &&
89 std::all_of(bound_samplers.begin(), bound_samplers.end(), 90 std::all_of(bound_samplers.begin(), bound_samplers.end(),
90 [this](const auto& sampler) { 91 [this](const auto& sampler) {
91 const auto [key, value] = sampler; 92 const auto [key, value] = sampler;
92 const auto other_value = engine->AccessBoundSampler(stage, key); 93 return value == engine->AccessBoundSampler(stage, key);
93 return value == other_value;
94 }) && 94 }) &&
95 std::all_of( 95 std::all_of(bindless_samplers.begin(), bindless_samplers.end(),
96 bindless_samplers.begin(), bindless_samplers.end(), [this](const auto& sampler) { 96 [this](const auto& sampler) {
97 const auto [cbuf, offset] = sampler.first; 97 const auto [cbuf, offset] = sampler.first;
98 const auto value = sampler.second; 98 const auto value = sampler.second;
99 const auto other_value = engine->AccessBindlessSampler(stage, cbuf, offset); 99 return value == engine->AccessBindlessSampler(stage, cbuf, offset);
100 return value == other_value; 100 });
101 }); 101}
102
103bool ConstBufferLocker::HasEqualKeys(const ConstBufferLocker& rhs) const {
104 return keys == rhs.keys && bound_samplers == rhs.bound_samplers &&
105 bindless_samplers == rhs.bindless_samplers;
102} 106}
103 107
104} // namespace VideoCommon::Shader 108} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/const_buffer_locker.h b/src/video_core/shader/const_buffer_locker.h
index 417d5a16f..966537fd6 100644
--- a/src/video_core/shader/const_buffer_locker.h
+++ b/src/video_core/shader/const_buffer_locker.h
@@ -44,6 +44,9 @@ public:
44 /// the same value, false otherwise; 44 /// the same value, false otherwise;
45 bool IsConsistent() const; 45 bool IsConsistent() const;
46 46
47 /// Returns true if the keys are equal to the other ones in the locker.
48 bool HasEqualKeys(const ConstBufferLocker& rhs) const;
49
47 /// Gives an getter to the const buffer keys in the database. 50 /// Gives an getter to the const buffer keys in the database.
48 const KeyMap& GetKeys() const { 51 const KeyMap& GetKeys() const {
49 return keys; 52 return keys;