2
1
Fork 0
mirror of https://github.com/yuzu-emu/yuzu.git synced 2024-07-04 23:31:19 +01:00

shader: Mark SSBOs as written when they are

This commit is contained in:
FernandoS27 2021-04-01 09:21:53 +02:00 committed by ameerj
parent d819ba4489
commit 12f5f32098
4 changed files with 32 additions and 4 deletions

View file

@ -6,6 +6,7 @@
#include <compare> #include <compare>
#include <optional> #include <optional>
#include <ranges> #include <ranges>
#include <map>
#include <boost/container/flat_set.hpp> #include <boost/container/flat_set.hpp>
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
@ -45,6 +46,7 @@ using StorageBufferSet =
using StorageInstVector = boost::container::small_vector<StorageInst, 24>; using StorageInstVector = boost::container::small_vector<StorageInst, 24>;
using VisitedBlocks = boost::container::flat_set<IR::Block*, std::less<IR::Block*>, using VisitedBlocks = boost::container::flat_set<IR::Block*, std::less<IR::Block*>,
boost::container::small_vector<IR::Block*, 4>>; boost::container::small_vector<IR::Block*, 4>>;
using StorageWritesMap = std::map<StorageBufferAddr, bool>;
/// Returns true when the instruction is a global memory instruction /// Returns true when the instruction is a global memory instruction
bool IsGlobalMemory(const IR::Inst& inst) { bool IsGlobalMemory(const IR::Inst& inst) {
@ -69,6 +71,22 @@ bool IsGlobalMemory(const IR::Inst& inst) {
} }
} }
/// Returns true when the instruction is a global memory instruction
bool IsGlobalMemoryWrite(const IR::Inst& inst) {
switch (inst.Opcode()) {
case IR::Opcode::WriteGlobalS8:
case IR::Opcode::WriteGlobalU8:
case IR::Opcode::WriteGlobalS16:
case IR::Opcode::WriteGlobalU16:
case IR::Opcode::WriteGlobal32:
case IR::Opcode::WriteGlobal64:
case IR::Opcode::WriteGlobal128:
return true;
default:
return false;
}
}
/// Converts a global memory opcode to its storage buffer equivalent /// Converts a global memory opcode to its storage buffer equivalent
IR::Opcode GlobalToStorage(IR::Opcode opcode) { IR::Opcode GlobalToStorage(IR::Opcode opcode) {
switch (opcode) { switch (opcode) {
@ -248,7 +266,7 @@ std::optional<StorageBufferAddr> Track(IR::Block* block, const IR::Value& value,
/// Collects the storage buffer used by a global memory instruction and the instruction itself /// Collects the storage buffer used by a global memory instruction and the instruction itself
void CollectStorageBuffers(IR::Block& block, IR::Inst& inst, StorageBufferSet& storage_buffer_set, void CollectStorageBuffers(IR::Block& block, IR::Inst& inst, StorageBufferSet& storage_buffer_set,
StorageInstVector& to_replace) { StorageInstVector& to_replace, StorageWritesMap& writes_map) {
// NVN puts storage buffers in a specific range, we have to bias towards these addresses to // NVN puts storage buffers in a specific range, we have to bias towards these addresses to
// avoid getting false positives // avoid getting false positives
static constexpr Bias nvn_bias{ static constexpr Bias nvn_bias{
@ -277,6 +295,13 @@ void CollectStorageBuffers(IR::Block& block, IR::Inst& inst, StorageBufferSet& s
} }
} }
// Collect storage buffer and the instruction // Collect storage buffer and the instruction
const bool is_a_write = IsGlobalMemoryWrite(inst);
auto it = writes_map.find(*storage_buffer);
if (it == writes_map.end()) {
writes_map[*storage_buffer] = is_a_write;
} else {
it->second = it->second || is_a_write;
}
storage_buffer_set.insert(*storage_buffer); storage_buffer_set.insert(*storage_buffer);
to_replace.push_back(StorageInst{ to_replace.push_back(StorageInst{
.storage_buffer{*storage_buffer}, .storage_buffer{*storage_buffer},
@ -350,13 +375,14 @@ void Replace(IR::Block& block, IR::Inst& inst, const IR::U32& storage_index,
void GlobalMemoryToStorageBufferPass(IR::Program& program) { void GlobalMemoryToStorageBufferPass(IR::Program& program) {
StorageBufferSet storage_buffers; StorageBufferSet storage_buffers;
StorageInstVector to_replace; StorageInstVector to_replace;
StorageWritesMap writes_map;
for (IR::Block* const block : program.post_order_blocks) { for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) { for (IR::Inst& inst : block->Instructions()) {
if (!IsGlobalMemory(inst)) { if (!IsGlobalMemory(inst)) {
continue; continue;
} }
CollectStorageBuffers(*block, inst, storage_buffers, to_replace); CollectStorageBuffers(*block, inst, storage_buffers, to_replace, writes_map);
} }
} }
Info& info{program.info}; Info& info{program.info};
@ -366,6 +392,7 @@ void GlobalMemoryToStorageBufferPass(IR::Program& program) {
.cbuf_index{storage_buffer.index}, .cbuf_index{storage_buffer.index},
.cbuf_offset{storage_buffer.offset}, .cbuf_offset{storage_buffer.offset},
.count{1}, .count{1},
.is_written{writes_map[storage_buffer]},
}); });
++storage_index; ++storage_index;
} }

View file

@ -59,6 +59,7 @@ struct StorageBufferDescriptor {
u32 cbuf_index; u32 cbuf_index;
u32 cbuf_offset; u32 cbuf_offset;
u32 count; u32 count;
bool is_written;
}; };
struct Info { struct Info {

View file

@ -75,7 +75,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
size_t ssbo_index{}; size_t ssbo_index{};
for (const auto& desc : info.storage_buffers_descriptors) { for (const auto& desc : info.storage_buffers_descriptors) {
ASSERT(desc.count == 1); ASSERT(desc.count == 1);
buffer_cache.BindComputeStorageBuffer(ssbo_index, desc.cbuf_index, desc.cbuf_offset, true); buffer_cache.BindComputeStorageBuffer(ssbo_index, desc.cbuf_index, desc.cbuf_offset, desc.is_written);
++ssbo_index; ++ssbo_index;
} }
buffer_cache.UpdateComputeBuffers(); buffer_cache.UpdateComputeBuffers();

View file

@ -163,7 +163,7 @@ void GraphicsPipeline::Configure(bool is_indexed) {
for (const auto& desc : info.storage_buffers_descriptors) { for (const auto& desc : info.storage_buffers_descriptors) {
ASSERT(desc.count == 1); ASSERT(desc.count == 1);
buffer_cache.BindGraphicsStorageBuffer(stage, index, desc.cbuf_index, desc.cbuf_offset, buffer_cache.BindGraphicsStorageBuffer(stage, index, desc.cbuf_index, desc.cbuf_offset,
true); desc.is_written);
++index; ++index;
} }
const auto& cbufs{maxwell3d.state.shader_stages[stage].const_buffers}; const auto& cbufs{maxwell3d.state.shader_stages[stage].const_buffers};