summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/shader/const_buffer_locker.cpp152
-rw-r--r--src/video_core/shader/const_buffer_locker.h76
2 files changed, 76 insertions, 152 deletions
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 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <algorithm>
8#include <memory>
7#include "common/assert.h" 9#include "common/assert.h"
8#include "common/common_types.h" 10#include "common/common_types.h"
9#include "video_core/engines/maxwell_3d.h" 11#include "video_core/engines/maxwell_3d.h"
@@ -11,140 +13,92 @@
11 13
12namespace VideoCommon::Shader { 14namespace VideoCommon::Shader {
13 15
16using Tegra::Engines::SamplerDescriptor;
17
14ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage) 18ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage)
15 : engine{nullptr}, shader_stage{shader_stage} {} 19 : stage{shader_stage} {}
16 20
17ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage, 21ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage,
18 Tegra::Engines::ConstBufferEngineInterface& engine) 22 Tegra::Engines::ConstBufferEngineInterface& engine)
19 : engine{&engine}, shader_stage{shader_stage} {} 23 : stage{shader_stage}, engine{&engine} {}
20
21bool ConstBufferLocker::IsEngineSet() const {
22 return engine != nullptr;
23}
24
25void ConstBufferLocker::SetEngine(Tegra::Engines::ConstBufferEngineInterface& engine_) {
26 engine = &engine_;
27}
28 24
29std::optional<u32> ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) { 25std::optional<u32> ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) {
30 if (!keys) {
31 keys = std::make_shared<KeyMap>();
32 }
33 auto& key_map = *keys;
34 const std::pair<u32, u32> key = {buffer, offset}; 26 const std::pair<u32, u32> key = {buffer, offset};
35 const auto iter = key_map.find(key); 27 const auto iter = keys.find(key);
36 if (iter != key_map.end()) { 28 if (iter != keys.end()) {
37 return {iter->second}; 29 return iter->second;
38 } 30 }
39 if (!IsEngineSet()) { 31 if (!engine) {
40 return {}; 32 return {};
41 } 33 }
42 const u32 value = engine->AccessConstBuffer32(shader_stage, buffer, offset); 34 const u32 value = engine->AccessConstBuffer32(stage, buffer, offset);
43 key_map.emplace(key, value); 35 keys.emplace(key, value);
44 return {value}; 36 return value;
45} 37}
46 38
47std::optional<Tegra::Engines::SamplerDescriptor> ConstBufferLocker::ObtainBoundSampler(u32 offset) { 39std::optional<SamplerDescriptor> ConstBufferLocker::ObtainBoundSampler(u32 offset) {
48 if (!bound_samplers) {
49 bound_samplers = std::make_shared<BoundSamplerMap>();
50 }
51 auto& key_map = *bound_samplers;
52 const u32 key = offset; 40 const u32 key = offset;
53 const auto iter = key_map.find(key); 41 const auto iter = bound_samplers.find(key);
54 if (iter != key_map.end()) { 42 if (iter != bound_samplers.end()) {
55 return {iter->second}; 43 return iter->second;
56 } 44 }
57 if (!IsEngineSet()) { 45 if (!engine) {
58 return {}; 46 return {};
59 } 47 }
60 const Tegra::Engines::SamplerDescriptor value = 48 const SamplerDescriptor value = engine->AccessBoundSampler(stage, offset);
61 engine->AccessBoundSampler(shader_stage, offset); 49 bound_samplers.emplace(key, value);
62 key_map.emplace(key, value); 50 return value;
63 return {value};
64} 51}
65 52
66std::optional<Tegra::Engines::SamplerDescriptor> ConstBufferLocker::ObtainBindlessSampler( 53std::optional<Tegra::Engines::SamplerDescriptor> ConstBufferLocker::ObtainBindlessSampler(
67 u32 buffer, u32 offset) { 54 u32 buffer, u32 offset) {
68 if (!bindless_samplers) { 55 const std::pair key = {buffer, offset};
69 bindless_samplers = std::make_shared<BindlessSamplerMap>(); 56 const auto iter = bindless_samplers.find(key);
70 } 57 if (iter != bindless_samplers.end()) {
71 auto& key_map = *bindless_samplers; 58 return iter->second;
72 const std::pair<u32, u32> key = {buffer, offset};
73 const auto iter = key_map.find(key);
74 if (iter != key_map.end()) {
75 return {iter->second};
76 } 59 }
77 if (!IsEngineSet()) { 60 if (!engine) {
78 return {}; 61 return {};
79 } 62 }
80 const Tegra::Engines::SamplerDescriptor value = 63 const SamplerDescriptor value = engine->AccessBindlessSampler(stage, buffer, offset);
81 engine->AccessBindlessSampler(shader_stage, buffer, offset); 64 bindless_samplers.emplace(key, value);
82 key_map.emplace(key, value); 65 return value;
83 return {value};
84} 66}
85 67
86void ConstBufferLocker::InsertKey(u32 buffer, u32 offset, u32 value) { 68void ConstBufferLocker::InsertKey(u32 buffer, u32 offset, u32 value) {
87 if (!keys) { 69 keys.insert_or_assign({buffer, offset}, value);
88 keys = std::make_shared<KeyMap>();
89 }
90 const std::pair<u32, u32> key = {buffer, offset};
91 (*keys)[key] = value;
92} 70}
93 71
94void ConstBufferLocker::InsertBoundSampler(u32 offset, Tegra::Engines::SamplerDescriptor sampler) { 72void ConstBufferLocker::InsertBoundSampler(u32 offset, SamplerDescriptor sampler) {
95 if (!bound_samplers) { 73 bound_samplers.insert_or_assign(offset, sampler);
96 bound_samplers = std::make_shared<BoundSamplerMap>();
97 }
98 (*bound_samplers)[offset] = sampler;
99} 74}
100 75
101void ConstBufferLocker::InsertBindlessSampler(u32 buffer, u32 offset, 76void ConstBufferLocker::InsertBindlessSampler(u32 buffer, u32 offset, SamplerDescriptor sampler) {
102 Tegra::Engines::SamplerDescriptor sampler) { 77 bindless_samplers.insert_or_assign({buffer, offset}, sampler);
103 if (!bindless_samplers) {
104 bindless_samplers = std::make_shared<BindlessSamplerMap>();
105 }
106 const std::pair<u32, u32> key = {buffer, offset};
107 (*bindless_samplers)[key] = sampler;
108} 78}
109 79
110bool ConstBufferLocker::IsConsistent() const { 80bool ConstBufferLocker::IsConsistent() const {
111 if (!IsEngineSet()) { 81 if (!engine) {
112 return false; 82 return false;
113 } 83 }
114 if (keys) { 84 return std::all_of(keys.begin(), keys.end(),
115 for (const auto& key_val : *keys) { 85 [](const auto& key) {
116 const std::pair<u32, u32> key = key_val.first; 86 const auto [value, other_value] = key.first;
117 const u32 value = key_val.second; 87 return value == other_value;
118 const u32 other_value = 88 }) &&
119 engine->AccessConstBuffer32(shader_stage, key.first, key.second); 89 std::all_of(bound_samplers.begin(), bound_samplers.end(),
120 if (other_value != value) { 90 [this](const auto& sampler) {
121 return false; 91 const auto [key, value] = sampler;
122 } 92 const auto other_value = engine->AccessBoundSampler(stage, key);
123 } 93 return value.raw == other_value.raw;
124 } 94 }) &&
125 if (bound_samplers) { 95 std::all_of(
126 for (const auto& sampler_val : *bound_samplers) { 96 bindless_samplers.begin(), bindless_samplers.end(), [this](const auto& sampler) {
127 const u32 key = sampler_val.first; 97 const auto [cbuf, offset] = sampler.first;
128 const Tegra::Engines::SamplerDescriptor value = sampler_val.second; 98 const auto value = sampler.second;
129 const Tegra::Engines::SamplerDescriptor other_value = 99 const auto other_value = engine->AccessBindlessSampler(stage, cbuf, offset);
130 engine->AccessBoundSampler(shader_stage, key); 100 return value.raw == other_value.raw;
131 if (other_value.raw != value.raw) { 101 });
132 return false;
133 }
134 }
135 }
136 if (bindless_samplers) {
137 for (const auto& sampler_val : *bindless_samplers) {
138 const std::pair<u32, u32> key = sampler_val.first;
139 const Tegra::Engines::SamplerDescriptor value = sampler_val.second;
140 const Tegra::Engines::SamplerDescriptor other_value =
141 engine->AccessBindlessSampler(shader_stage, key.first, key.second);
142 if (other_value.raw != value.raw) {
143 return false;
144 }
145 }
146 }
147 return true;
148} 102}
149 103
150} // namespace VideoCommon::Shader 104} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/const_buffer_locker.h b/src/video_core/shader/const_buffer_locker.h
index 54459977f..417d5a16f 100644
--- a/src/video_core/shader/const_buffer_locker.h
+++ b/src/video_core/shader/const_buffer_locker.h
@@ -23,78 +23,48 @@ public:
23 explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage, 23 explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage,
24 Tegra::Engines::ConstBufferEngineInterface& engine); 24 Tegra::Engines::ConstBufferEngineInterface& engine);
25 25
26 // Checks if an engine is setup, it may be possible that during disk shader 26 /// Retrieves a key from the locker, if it's registered, it will give the registered value, if
27 // cache run, the engines have not been created yet. 27 /// not it will obtain it from maxwell3d and register it.
28 bool IsEngineSet() const;
29
30 // Use this to set/change the engine used for this shader.
31 void SetEngine(Tegra::Engines::ConstBufferEngineInterface& engine);
32
33 // Retrieves a key from the locker, if it's registered, it will give the
34 // registered value, if not it will obtain it from maxwell3d and register it.
35 std::optional<u32> ObtainKey(u32 buffer, u32 offset); 28 std::optional<u32> ObtainKey(u32 buffer, u32 offset);
36 29
37 std::optional<Tegra::Engines::SamplerDescriptor> ObtainBoundSampler(u32 offset); 30 std::optional<Tegra::Engines::SamplerDescriptor> ObtainBoundSampler(u32 offset);
38 31
39 std::optional<Tegra::Engines::SamplerDescriptor> ObtainBindlessSampler(u32 buffer, u32 offset); 32 std::optional<Tegra::Engines::SamplerDescriptor> ObtainBindlessSampler(u32 buffer, u32 offset);
40 33
41 // Manually inserts a key. 34 /// Inserts a key.
42 void InsertKey(u32 buffer, u32 offset, u32 value); 35 void InsertKey(u32 buffer, u32 offset, u32 value);
43 36
37 /// Inserts a bound sampler key.
44 void InsertBoundSampler(u32 offset, Tegra::Engines::SamplerDescriptor sampler); 38 void InsertBoundSampler(u32 offset, Tegra::Engines::SamplerDescriptor sampler);
45 39
40 /// Inserts a bindless sampler key.
46 void InsertBindlessSampler(u32 buffer, u32 offset, Tegra::Engines::SamplerDescriptor sampler); 41 void InsertBindlessSampler(u32 buffer, u32 offset, Tegra::Engines::SamplerDescriptor sampler);
47 42
48 // Retrieves the number of keys registered. 43 /// Checks keys and samplers against engine's current const buffers. Returns true if they are
49 std::size_t NumKeys() const { 44 /// the same value, false otherwise;
50 if (!keys) { 45 bool IsConsistent() const;
51 return 0;
52 }
53 return keys->size();
54 }
55
56 std::size_t NumBoundSamplers() const {
57 if (!bound_samplers) {
58 return 0;
59 }
60 return bound_samplers->size();
61 }
62
63 std::size_t NumBindlessSamplers() const {
64 if (!bindless_samplers) {
65 return 0;
66 }
67 return bindless_samplers->size();
68 }
69 46
70 // Gives an accessor to the key's database. 47 /// Gives an getter to the const buffer keys in the database.
71 // Pre: NumKeys > 0 48 const KeyMap& GetKeys() const {
72 const KeyMap& AccessKeys() const { 49 return keys;
73 return *keys;
74 } 50 }
75 51
76 // Gives an accessor to the sampler's database. 52 /// Gets samplers database.
77 // Pre: NumBindlessSamplers > 0 53 const BoundSamplerMap& GetBoundSamplers() const {
78 const BoundSamplerMap& AccessBoundSamplers() const { 54 return bound_samplers;
79 return *bound_samplers;
80 } 55 }
81 56
82 // Gives an accessor to the sampler's database. 57 /// Gets bindless samplers database.
83 // Pre: NumBindlessSamplers > 0 58 const BindlessSamplerMap& GetBindlessSamplers() const {
84 const BindlessSamplerMap& AccessBindlessSamplers() const { 59 return bindless_samplers;
85 return *bindless_samplers;
86 } 60 }
87 61
88 // Checks keys & samplers against engine's current const buffers. Returns true if they
89 // are the same value, false otherwise;
90 bool IsConsistent() const;
91
92private: 62private:
93 Tegra::Engines::ConstBufferEngineInterface* engine; 63 const Tegra::Engines::ShaderType stage;
94 Tegra::Engines::ShaderType shader_stage; 64 Tegra::Engines::ConstBufferEngineInterface* engine = nullptr;
95 // All containers are lazy initialized as most shaders don't use them. 65 KeyMap keys;
96 std::shared_ptr<KeyMap> keys{}; 66 BoundSamplerMap bound_samplers;
97 std::shared_ptr<BoundSamplerMap> bound_samplers{}; 67 BindlessSamplerMap bindless_samplers;
98 std::shared_ptr<BindlessSamplerMap> bindless_samplers{};
99}; 68};
69
100} // namespace VideoCommon::Shader 70} // namespace VideoCommon::Shader