From 1a58f45d76fe7756dd365e099d1536da769c1eab Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 23 Sep 2019 14:02:02 -0400 Subject: VideoCore: Unify const buffer accessing along engines and provide ConstBufferLocker class to shaders. --- src/video_core/shader/const_buffer_locker.cpp | 72 +++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/video_core/shader/const_buffer_locker.cpp (limited to 'src/video_core/shader/const_buffer_locker.cpp') diff --git a/src/video_core/shader/const_buffer_locker.cpp b/src/video_core/shader/const_buffer_locker.cpp new file mode 100644 index 000000000..6a9e0ed5e --- /dev/null +++ b/src/video_core/shader/const_buffer_locker.cpp @@ -0,0 +1,72 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/assert.h" +#include "common/common_types.h" +#include "video_core/engines/maxwell_3d.h" +#include "video_core/shader/const_buffer_locker.h" + +namespace VideoCommon::Shader { + +ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage) + : engine{nullptr}, shader_stage{shader_stage} {} + +ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage, + Tegra::Engines::ConstBufferEngineInterface* engine) + : engine{engine}, shader_stage{shader_stage} {} + +bool ConstBufferLocker::IsEngineSet() const { + return engine != nullptr; +} + +void ConstBufferLocker::SetEngine(Tegra::Engines::ConstBufferEngineInterface* engine_) { + engine = engine_; +} + +std::optional ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) { + const std::pair key = {buffer, offset}; + const auto iter = keys.find(key); + if (iter != keys.end()) { + return {iter->second}; + } + if (!IsEngineSet()) { + return {}; + } + const u32 value = engine->AccessConstBuffer32(shader_stage, buffer, offset); + keys.emplace(key, value); + return {value}; +} + +void ConstBufferLocker::InsertKey(u32 buffer, u32 offset, u32 value) { + const std::pair key = {buffer, offset}; + keys[key] = value; +} + +u32 ConstBufferLocker::NumKeys() const { + return keys.size(); +} + +const std::unordered_map, u32, Common::PairHash>& +ConstBufferLocker::AccessKeys() const { + return keys; +} + +bool ConstBufferLocker::AreKeysConsistant() const { + if (!IsEngineSet()) { + return false; + } + for (const auto& key_val : keys) { + const std::pair key = key_val.first; + const u32 value = key_val.second; + const u32 other_value = engine->AccessConstBuffer32(shader_stage, key.first, key.second); + if (other_value != value) { + return false; + } + } + return true; +} + +} // namespace VideoCommon::Shader -- cgit v1.2.3 From 33fcec3502f5dd5a99b7a8337128b7c99bfba908 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 25 Sep 2019 09:53:18 -0400 Subject: Shader_IR: allow lookup of texture samplers within the shader_ir for instructions that don't provide it --- src/video_core/shader/const_buffer_locker.cpp | 110 ++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 16 deletions(-) (limited to 'src/video_core/shader/const_buffer_locker.cpp') diff --git a/src/video_core/shader/const_buffer_locker.cpp b/src/video_core/shader/const_buffer_locker.cpp index 6a9e0ed5e..4f5de8ae9 100644 --- a/src/video_core/shader/const_buffer_locker.cpp +++ b/src/video_core/shader/const_buffer_locker.cpp @@ -27,43 +27,121 @@ void ConstBufferLocker::SetEngine(Tegra::Engines::ConstBufferEngineInterface* en } std::optional ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) { + if (!keys) { + keys = std::make_shared(); + } + auto& key_map = *keys; const std::pair key = {buffer, offset}; - const auto iter = keys.find(key); - if (iter != keys.end()) { + const auto iter = key_map.find(key); + if (iter != key_map.end()) { return {iter->second}; } if (!IsEngineSet()) { return {}; } const u32 value = engine->AccessConstBuffer32(shader_stage, buffer, offset); - keys.emplace(key, value); + key_map.emplace(key, value); + return {value}; +} + +std::optional ConstBufferLocker::ObtainBoundSampler(u32 offset) { + if (!bound_samplers) { + bound_samplers = std::make_shared(); + } + auto& key_map = *bound_samplers; + const u32 key = offset; + const auto iter = key_map.find(key); + if (iter != key_map.end()) { + return {iter->second}; + } + if (!IsEngineSet()) { + return {}; + } + const Tegra::Engines::SamplerDescriptor value = + engine->AccessBoundSampler(shader_stage, offset); + key_map.emplace(key, value); + return {value}; +} + +std::optional ConstBufferLocker::ObtainBindlessSampler( + u32 buffer, u32 offset) { + if (!bindless_samplers) { + bindless_samplers = std::make_shared(); + } + auto& key_map = *bindless_samplers; + const std::pair key = {buffer, offset}; + const auto iter = key_map.find(key); + if (iter != key_map.end()) { + return {iter->second}; + } + if (!IsEngineSet()) { + return {}; + } + const Tegra::Engines::SamplerDescriptor value = + engine->AccessBindlessSampler(shader_stage, buffer, offset); + key_map.emplace(key, value); return {value}; } void ConstBufferLocker::InsertKey(u32 buffer, u32 offset, u32 value) { + if (!keys) { + keys = std::make_shared(); + } const std::pair key = {buffer, offset}; - keys[key] = value; + (*keys)[key] = value; } -u32 ConstBufferLocker::NumKeys() const { - return keys.size(); +void ConstBufferLocker::InsertBoundSampler(u32 offset, Tegra::Engines::SamplerDescriptor sampler) { + if (!bound_samplers) { + bound_samplers = std::make_shared(); + } + (*bound_samplers)[offset] = sampler; } -const std::unordered_map, u32, Common::PairHash>& -ConstBufferLocker::AccessKeys() const { - return keys; +void ConstBufferLocker::InsertBindlessSampler(u32 buffer, u32 offset, + Tegra::Engines::SamplerDescriptor sampler) { + if (!bindless_samplers) { + bindless_samplers = std::make_shared(); + } + const std::pair key = {buffer, offset}; + (*bindless_samplers)[key] = sampler; } -bool ConstBufferLocker::AreKeysConsistant() const { +bool ConstBufferLocker::IsConsistant() const { if (!IsEngineSet()) { return false; } - for (const auto& key_val : keys) { - const std::pair key = key_val.first; - const u32 value = key_val.second; - const u32 other_value = engine->AccessConstBuffer32(shader_stage, key.first, key.second); - if (other_value != value) { - return false; + if (keys) { + for (const auto& key_val : *keys) { + const std::pair key = key_val.first; + const u32 value = key_val.second; + const u32 other_value = + engine->AccessConstBuffer32(shader_stage, key.first, key.second); + if (other_value != value) { + return false; + } + } + } + if (bound_samplers) { + for (const auto& sampler_val : *bound_samplers) { + const u32 key = sampler_val.first; + const Tegra::Engines::SamplerDescriptor value = sampler_val.second; + const Tegra::Engines::SamplerDescriptor other_value = + engine->AccessBoundSampler(shader_stage, key); + if (other_value.raw != value.raw) { + return false; + } + } + } + if (bindless_samplers) { + for (const auto& sampler_val : *bindless_samplers) { + const std::pair key = sampler_val.first; + const Tegra::Engines::SamplerDescriptor value = sampler_val.second; + const Tegra::Engines::SamplerDescriptor other_value = + engine->AccessBindlessSampler(shader_stage, key.first, key.second); + if (other_value.raw != value.raw) { + return false; + } } } return true; -- cgit v1.2.3 From a05120ec0b8b1827ebeffd4e78a553f7886fa178 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 25 Sep 2019 15:03:13 -0400 Subject: Shader_IR: Correct typo in Consistent method. --- src/video_core/shader/const_buffer_locker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/video_core/shader/const_buffer_locker.cpp') diff --git a/src/video_core/shader/const_buffer_locker.cpp b/src/video_core/shader/const_buffer_locker.cpp index 4f5de8ae9..9d23bcecf 100644 --- a/src/video_core/shader/const_buffer_locker.cpp +++ b/src/video_core/shader/const_buffer_locker.cpp @@ -107,7 +107,7 @@ void ConstBufferLocker::InsertBindlessSampler(u32 buffer, u32 offset, (*bindless_samplers)[key] = sampler; } -bool ConstBufferLocker::IsConsistant() const { +bool ConstBufferLocker::IsConsistent() const { if (!IsEngineSet()) { return false; } -- cgit v1.2.3 From 7b81ba4d8a9805f808fcc60a0905ac74d293b2ee Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 24 Sep 2019 23:34:18 -0300 Subject: gl_shader_decompiler: Move entries to a separate function --- src/video_core/shader/const_buffer_locker.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/video_core/shader/const_buffer_locker.cpp') diff --git a/src/video_core/shader/const_buffer_locker.cpp b/src/video_core/shader/const_buffer_locker.cpp index 9d23bcecf..37a0968a1 100644 --- a/src/video_core/shader/const_buffer_locker.cpp +++ b/src/video_core/shader/const_buffer_locker.cpp @@ -15,15 +15,15 @@ ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage) : engine{nullptr}, shader_stage{shader_stage} {} ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage, - Tegra::Engines::ConstBufferEngineInterface* engine) - : engine{engine}, shader_stage{shader_stage} {} + Tegra::Engines::ConstBufferEngineInterface& engine) + : engine{&engine}, shader_stage{shader_stage} {} bool ConstBufferLocker::IsEngineSet() const { return engine != nullptr; } -void ConstBufferLocker::SetEngine(Tegra::Engines::ConstBufferEngineInterface* engine_) { - engine = engine_; +void ConstBufferLocker::SetEngine(Tegra::Engines::ConstBufferEngineInterface& engine_) { + engine = &engine_; } std::optional ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) { -- cgit v1.2.3 From fa2c297f3eddc718123767142dbc296270f58f7a Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 25 Sep 2019 19:19:41 -0300 Subject: const_buffer_locker: Minor style changes --- src/video_core/shader/const_buffer_locker.cpp | 152 +++++++++----------------- 1 file changed, 53 insertions(+), 99 deletions(-) (limited to 'src/video_core/shader/const_buffer_locker.cpp') diff --git a/src/video_core/shader/const_buffer_locker.cpp b/src/video_core/shader/const_buffer_locker.cpp index 37a0968a1..ebeba102d 100644 --- a/src/video_core/shader/const_buffer_locker.cpp +++ b/src/video_core/shader/const_buffer_locker.cpp @@ -4,6 +4,8 @@ #pragma once +#include +#include #include "common/assert.h" #include "common/common_types.h" #include "video_core/engines/maxwell_3d.h" @@ -11,140 +13,92 @@ namespace VideoCommon::Shader { +using Tegra::Engines::SamplerDescriptor; + ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage) - : engine{nullptr}, shader_stage{shader_stage} {} + : stage{shader_stage} {} ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage, Tegra::Engines::ConstBufferEngineInterface& engine) - : engine{&engine}, shader_stage{shader_stage} {} - -bool ConstBufferLocker::IsEngineSet() const { - return engine != nullptr; -} - -void ConstBufferLocker::SetEngine(Tegra::Engines::ConstBufferEngineInterface& engine_) { - engine = &engine_; -} + : stage{shader_stage}, engine{&engine} {} std::optional ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) { - if (!keys) { - keys = std::make_shared(); - } - auto& key_map = *keys; const std::pair key = {buffer, offset}; - const auto iter = key_map.find(key); - if (iter != key_map.end()) { - return {iter->second}; + const auto iter = keys.find(key); + if (iter != keys.end()) { + return iter->second; } - if (!IsEngineSet()) { + if (!engine) { return {}; } - const u32 value = engine->AccessConstBuffer32(shader_stage, buffer, offset); - key_map.emplace(key, value); - return {value}; + const u32 value = engine->AccessConstBuffer32(stage, buffer, offset); + keys.emplace(key, value); + return value; } -std::optional ConstBufferLocker::ObtainBoundSampler(u32 offset) { - if (!bound_samplers) { - bound_samplers = std::make_shared(); - } - auto& key_map = *bound_samplers; +std::optional ConstBufferLocker::ObtainBoundSampler(u32 offset) { const u32 key = offset; - const auto iter = key_map.find(key); - if (iter != key_map.end()) { - return {iter->second}; + const auto iter = bound_samplers.find(key); + if (iter != bound_samplers.end()) { + return iter->second; } - if (!IsEngineSet()) { + if (!engine) { return {}; } - const Tegra::Engines::SamplerDescriptor value = - engine->AccessBoundSampler(shader_stage, offset); - key_map.emplace(key, value); - return {value}; + const SamplerDescriptor value = engine->AccessBoundSampler(stage, offset); + bound_samplers.emplace(key, value); + return value; } std::optional ConstBufferLocker::ObtainBindlessSampler( u32 buffer, u32 offset) { - if (!bindless_samplers) { - bindless_samplers = std::make_shared(); - } - auto& key_map = *bindless_samplers; - const std::pair key = {buffer, offset}; - const auto iter = key_map.find(key); - if (iter != key_map.end()) { - return {iter->second}; + const std::pair key = {buffer, offset}; + const auto iter = bindless_samplers.find(key); + if (iter != bindless_samplers.end()) { + return iter->second; } - if (!IsEngineSet()) { + if (!engine) { return {}; } - const Tegra::Engines::SamplerDescriptor value = - engine->AccessBindlessSampler(shader_stage, buffer, offset); - key_map.emplace(key, value); - return {value}; + const SamplerDescriptor value = engine->AccessBindlessSampler(stage, buffer, offset); + bindless_samplers.emplace(key, value); + return value; } void ConstBufferLocker::InsertKey(u32 buffer, u32 offset, u32 value) { - if (!keys) { - keys = std::make_shared(); - } - const std::pair key = {buffer, offset}; - (*keys)[key] = value; + keys.insert_or_assign({buffer, offset}, value); } -void ConstBufferLocker::InsertBoundSampler(u32 offset, Tegra::Engines::SamplerDescriptor sampler) { - if (!bound_samplers) { - bound_samplers = std::make_shared(); - } - (*bound_samplers)[offset] = sampler; +void ConstBufferLocker::InsertBoundSampler(u32 offset, SamplerDescriptor sampler) { + bound_samplers.insert_or_assign(offset, sampler); } -void ConstBufferLocker::InsertBindlessSampler(u32 buffer, u32 offset, - Tegra::Engines::SamplerDescriptor sampler) { - if (!bindless_samplers) { - bindless_samplers = std::make_shared(); - } - const std::pair key = {buffer, offset}; - (*bindless_samplers)[key] = sampler; +void ConstBufferLocker::InsertBindlessSampler(u32 buffer, u32 offset, SamplerDescriptor sampler) { + bindless_samplers.insert_or_assign({buffer, offset}, sampler); } bool ConstBufferLocker::IsConsistent() const { - if (!IsEngineSet()) { + if (!engine) { return false; } - if (keys) { - for (const auto& key_val : *keys) { - const std::pair key = key_val.first; - const u32 value = key_val.second; - const u32 other_value = - engine->AccessConstBuffer32(shader_stage, key.first, key.second); - if (other_value != value) { - return false; - } - } - } - if (bound_samplers) { - for (const auto& sampler_val : *bound_samplers) { - const u32 key = sampler_val.first; - const Tegra::Engines::SamplerDescriptor value = sampler_val.second; - const Tegra::Engines::SamplerDescriptor other_value = - engine->AccessBoundSampler(shader_stage, key); - if (other_value.raw != value.raw) { - return false; - } - } - } - if (bindless_samplers) { - for (const auto& sampler_val : *bindless_samplers) { - const std::pair key = sampler_val.first; - const Tegra::Engines::SamplerDescriptor value = sampler_val.second; - const Tegra::Engines::SamplerDescriptor other_value = - engine->AccessBindlessSampler(shader_stage, key.first, key.second); - if (other_value.raw != value.raw) { - return false; - } - } - } - return true; + return std::all_of(keys.begin(), keys.end(), + [](const auto& key) { + const auto [value, other_value] = key.first; + return value == other_value; + }) && + std::all_of(bound_samplers.begin(), bound_samplers.end(), + [this](const auto& sampler) { + const auto [key, value] = sampler; + const auto other_value = engine->AccessBoundSampler(stage, key); + return value.raw == other_value.raw; + }) && + std::all_of( + bindless_samplers.begin(), bindless_samplers.end(), [this](const auto& sampler) { + const auto [cbuf, offset] = sampler.first; + const auto value = sampler.second; + const auto other_value = engine->AccessBindlessSampler(stage, cbuf, offset); + return value.raw == other_value.raw; + }); } } // namespace VideoCommon::Shader -- cgit v1.2.3 From ec85648af3316d5e43c7b57fca55d0dad3d03f96 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 25 Sep 2019 21:46:34 -0300 Subject: gl_shader_disk_cache: Store and load fast BRX --- src/video_core/shader/const_buffer_locker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/video_core/shader/const_buffer_locker.cpp') diff --git a/src/video_core/shader/const_buffer_locker.cpp b/src/video_core/shader/const_buffer_locker.cpp index ebeba102d..fda9e3c38 100644 --- a/src/video_core/shader/const_buffer_locker.cpp +++ b/src/video_core/shader/const_buffer_locker.cpp @@ -90,14 +90,14 @@ bool ConstBufferLocker::IsConsistent() const { [this](const auto& sampler) { const auto [key, value] = sampler; const auto other_value = engine->AccessBoundSampler(stage, key); - return value.raw == other_value.raw; + return value == other_value; }) && std::all_of( bindless_samplers.begin(), bindless_samplers.end(), [this](const auto& sampler) { const auto [cbuf, offset] = sampler.first; const auto value = sampler.second; const auto other_value = engine->AccessBindlessSampler(stage, cbuf, offset); - return value.raw == other_value.raw; + return value == other_value; }); } -- cgit v1.2.3 From 78f3e8a75792c976eb5bfa6df4c020d898642684 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 26 Sep 2019 00:23:08 -0300 Subject: gl_shader_cache: Implement locker variants invalidation --- src/video_core/shader/const_buffer_locker.cpp | 28 +++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'src/video_core/shader/const_buffer_locker.cpp') 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 { return false; } return std::all_of(keys.begin(), keys.end(), - [](const auto& key) { - const auto [value, other_value] = key.first; - return value == other_value; + [this](const auto& pair) { + const auto [cbuf, offset] = pair.first; + const auto value = pair.second; + return value == engine->AccessConstBuffer32(stage, cbuf, offset); }) && std::all_of(bound_samplers.begin(), bound_samplers.end(), [this](const auto& sampler) { const auto [key, value] = sampler; - const auto other_value = engine->AccessBoundSampler(stage, key); - return value == other_value; + return value == engine->AccessBoundSampler(stage, key); }) && - std::all_of( - bindless_samplers.begin(), bindless_samplers.end(), [this](const auto& sampler) { - const auto [cbuf, offset] = sampler.first; - const auto value = sampler.second; - const auto other_value = engine->AccessBindlessSampler(stage, cbuf, offset); - return value == other_value; - }); + std::all_of(bindless_samplers.begin(), bindless_samplers.end(), + [this](const auto& sampler) { + const auto [cbuf, offset] = sampler.first; + const auto value = sampler.second; + return value == engine->AccessBindlessSampler(stage, cbuf, offset); + }); +} + +bool ConstBufferLocker::HasEqualKeys(const ConstBufferLocker& rhs) const { + return keys == rhs.keys && bound_samplers == rhs.bound_samplers && + bindless_samplers == rhs.bindless_samplers; } } // namespace VideoCommon::Shader -- cgit v1.2.3 From be856a38d6b0c7c90c861baf3204ac48a108f3d2 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 17 Oct 2019 10:35:16 -0400 Subject: Shader_IR: Address Feedback. --- src/video_core/shader/const_buffer_locker.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/video_core/shader/const_buffer_locker.cpp') diff --git a/src/video_core/shader/const_buffer_locker.cpp b/src/video_core/shader/const_buffer_locker.cpp index 592bbf657..fe467608e 100644 --- a/src/video_core/shader/const_buffer_locker.cpp +++ b/src/video_core/shader/const_buffer_locker.cpp @@ -22,6 +22,8 @@ ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage, Tegra::Engines::ConstBufferEngineInterface& engine) : stage{shader_stage}, engine{&engine} {} +ConstBufferLocker::~ConstBufferLocker() = default; + std::optional ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) { const std::pair key = {buffer, offset}; const auto iter = keys.find(key); @@ -29,7 +31,7 @@ std::optional ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) { return iter->second; } if (!engine) { - return {}; + return std::nullopt; } const u32 value = engine->AccessConstBuffer32(stage, buffer, offset); keys.emplace(key, value); @@ -43,7 +45,7 @@ std::optional ConstBufferLocker::ObtainBoundSampler(u32 offse return iter->second; } if (!engine) { - return {}; + return std::nullopt; } const SamplerDescriptor value = engine->AccessBoundSampler(stage, offset); bound_samplers.emplace(key, value); @@ -58,7 +60,7 @@ std::optional ConstBufferLocker::ObtainBindle return iter->second; } if (!engine) { - return {}; + return std::nullopt; } const SamplerDescriptor value = engine->AccessBindlessSampler(stage, buffer, offset); bindless_samplers.emplace(key, value); -- cgit v1.2.3