diff options
| author | 2021-04-01 09:21:53 +0200 | |
|---|---|---|
| committer | 2021-07-22 21:51:25 -0400 | |
| commit | 12f5f320985824d1ebad587ebecb0f8406143ebc (patch) | |
| tree | cce9a7c14619350d578a262a6a23da6b0c9461d6 /src/shader_recompiler | |
| parent | shader: Implement ViewportIndex (diff) | |
| download | yuzu-12f5f320985824d1ebad587ebecb0f8406143ebc.tar.gz yuzu-12f5f320985824d1ebad587ebecb0f8406143ebc.tar.xz yuzu-12f5f320985824d1ebad587ebecb0f8406143ebc.zip | |
shader: Mark SSBOs as written when they are
Diffstat (limited to 'src/shader_recompiler')
| -rw-r--r-- | src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp | 31 | ||||
| -rw-r--r-- | src/shader_recompiler/shader_info.h | 1 |
2 files changed, 30 insertions, 2 deletions
diff --git a/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp b/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp index 1faa1ec88..d4bae249b 100644 --- a/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp +++ b/src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <compare> | 6 | #include <compare> |
| 7 | #include <optional> | 7 | #include <optional> |
| 8 | #include <ranges> | 8 | #include <ranges> |
| 9 | #include <map> | ||
| 9 | 10 | ||
| 10 | #include <boost/container/flat_set.hpp> | 11 | #include <boost/container/flat_set.hpp> |
| 11 | #include <boost/container/small_vector.hpp> | 12 | #include <boost/container/small_vector.hpp> |
| @@ -45,6 +46,7 @@ using StorageBufferSet = | |||
| 45 | using StorageInstVector = boost::container::small_vector<StorageInst, 24>; | 46 | using StorageInstVector = boost::container::small_vector<StorageInst, 24>; |
| 46 | using VisitedBlocks = boost::container::flat_set<IR::Block*, std::less<IR::Block*>, | 47 | using VisitedBlocks = boost::container::flat_set<IR::Block*, std::less<IR::Block*>, |
| 47 | boost::container::small_vector<IR::Block*, 4>>; | 48 | boost::container::small_vector<IR::Block*, 4>>; |
| 49 | using StorageWritesMap = std::map<StorageBufferAddr, bool>; | ||
| 48 | 50 | ||
| 49 | /// Returns true when the instruction is a global memory instruction | 51 | /// Returns true when the instruction is a global memory instruction |
| 50 | bool IsGlobalMemory(const IR::Inst& inst) { | 52 | bool IsGlobalMemory(const IR::Inst& inst) { |
| @@ -69,6 +71,22 @@ bool IsGlobalMemory(const IR::Inst& inst) { | |||
| 69 | } | 71 | } |
| 70 | } | 72 | } |
| 71 | 73 | ||
| 74 | /// Returns true when the instruction is a global memory instruction | ||
| 75 | bool IsGlobalMemoryWrite(const IR::Inst& inst) { | ||
| 76 | switch (inst.Opcode()) { | ||
| 77 | case IR::Opcode::WriteGlobalS8: | ||
| 78 | case IR::Opcode::WriteGlobalU8: | ||
| 79 | case IR::Opcode::WriteGlobalS16: | ||
| 80 | case IR::Opcode::WriteGlobalU16: | ||
| 81 | case IR::Opcode::WriteGlobal32: | ||
| 82 | case IR::Opcode::WriteGlobal64: | ||
| 83 | case IR::Opcode::WriteGlobal128: | ||
| 84 | return true; | ||
| 85 | default: | ||
| 86 | return false; | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 72 | /// Converts a global memory opcode to its storage buffer equivalent | 90 | /// Converts a global memory opcode to its storage buffer equivalent |
| 73 | IR::Opcode GlobalToStorage(IR::Opcode opcode) { | 91 | IR::Opcode GlobalToStorage(IR::Opcode opcode) { |
| 74 | switch (opcode) { | 92 | switch (opcode) { |
| @@ -248,7 +266,7 @@ std::optional<StorageBufferAddr> Track(IR::Block* block, const IR::Value& value, | |||
| 248 | 266 | ||
| 249 | /// Collects the storage buffer used by a global memory instruction and the instruction itself | 267 | /// Collects the storage buffer used by a global memory instruction and the instruction itself |
| 250 | void CollectStorageBuffers(IR::Block& block, IR::Inst& inst, StorageBufferSet& storage_buffer_set, | 268 | void CollectStorageBuffers(IR::Block& block, IR::Inst& inst, StorageBufferSet& storage_buffer_set, |
| 251 | StorageInstVector& to_replace) { | 269 | StorageInstVector& to_replace, StorageWritesMap& writes_map) { |
| 252 | // NVN puts storage buffers in a specific range, we have to bias towards these addresses to | 270 | // NVN puts storage buffers in a specific range, we have to bias towards these addresses to |
| 253 | // avoid getting false positives | 271 | // avoid getting false positives |
| 254 | static constexpr Bias nvn_bias{ | 272 | static constexpr Bias nvn_bias{ |
| @@ -277,6 +295,13 @@ void CollectStorageBuffers(IR::Block& block, IR::Inst& inst, StorageBufferSet& s | |||
| 277 | } | 295 | } |
| 278 | } | 296 | } |
| 279 | // Collect storage buffer and the instruction | 297 | // Collect storage buffer and the instruction |
| 298 | const bool is_a_write = IsGlobalMemoryWrite(inst); | ||
| 299 | auto it = writes_map.find(*storage_buffer); | ||
| 300 | if (it == writes_map.end()) { | ||
| 301 | writes_map[*storage_buffer] = is_a_write; | ||
| 302 | } else { | ||
| 303 | it->second = it->second || is_a_write; | ||
| 304 | } | ||
| 280 | storage_buffer_set.insert(*storage_buffer); | 305 | storage_buffer_set.insert(*storage_buffer); |
| 281 | to_replace.push_back(StorageInst{ | 306 | to_replace.push_back(StorageInst{ |
| 282 | .storage_buffer{*storage_buffer}, | 307 | .storage_buffer{*storage_buffer}, |
| @@ -350,13 +375,14 @@ void Replace(IR::Block& block, IR::Inst& inst, const IR::U32& storage_index, | |||
| 350 | void GlobalMemoryToStorageBufferPass(IR::Program& program) { | 375 | void GlobalMemoryToStorageBufferPass(IR::Program& program) { |
| 351 | StorageBufferSet storage_buffers; | 376 | StorageBufferSet storage_buffers; |
| 352 | StorageInstVector to_replace; | 377 | StorageInstVector to_replace; |
| 378 | StorageWritesMap writes_map; | ||
| 353 | 379 | ||
| 354 | for (IR::Block* const block : program.post_order_blocks) { | 380 | for (IR::Block* const block : program.post_order_blocks) { |
| 355 | for (IR::Inst& inst : block->Instructions()) { | 381 | for (IR::Inst& inst : block->Instructions()) { |
| 356 | if (!IsGlobalMemory(inst)) { | 382 | if (!IsGlobalMemory(inst)) { |
| 357 | continue; | 383 | continue; |
| 358 | } | 384 | } |
| 359 | CollectStorageBuffers(*block, inst, storage_buffers, to_replace); | 385 | CollectStorageBuffers(*block, inst, storage_buffers, to_replace, writes_map); |
| 360 | } | 386 | } |
| 361 | } | 387 | } |
| 362 | Info& info{program.info}; | 388 | Info& info{program.info}; |
| @@ -366,6 +392,7 @@ void GlobalMemoryToStorageBufferPass(IR::Program& program) { | |||
| 366 | .cbuf_index{storage_buffer.index}, | 392 | .cbuf_index{storage_buffer.index}, |
| 367 | .cbuf_offset{storage_buffer.offset}, | 393 | .cbuf_offset{storage_buffer.offset}, |
| 368 | .count{1}, | 394 | .count{1}, |
| 395 | .is_written{writes_map[storage_buffer]}, | ||
| 369 | }); | 396 | }); |
| 370 | ++storage_index; | 397 | ++storage_index; |
| 371 | } | 398 | } |
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index a5bff40bb..d4d039eaf 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h | |||
| @@ -59,6 +59,7 @@ struct StorageBufferDescriptor { | |||
| 59 | u32 cbuf_index; | 59 | u32 cbuf_index; |
| 60 | u32 cbuf_offset; | 60 | u32 cbuf_offset; |
| 61 | u32 count; | 61 | u32 count; |
| 62 | bool is_written; | ||
| 62 | }; | 63 | }; |
| 63 | 64 | ||
| 64 | struct Info { | 65 | struct Info { |