summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFernandoS27 <fsahmkow27@gmail.com>2021-04-01 09:21:53 +0200
committerameerj <52414509+ameerj@users.noreply.github.com>2021-07-23 03:51:25 +0200
commit12f5f320985824d1ebad587ebecb0f8406143ebc (patch)
treecce9a7c14619350d578a262a6a23da6b0c9461d6
parentshader: Implement ViewportIndex (diff)
downloadyuzu-12f5f320985824d1ebad587ebecb0f8406143ebc.tar
yuzu-12f5f320985824d1ebad587ebecb0f8406143ebc.tar.gz
yuzu-12f5f320985824d1ebad587ebecb0f8406143ebc.tar.bz2
yuzu-12f5f320985824d1ebad587ebecb0f8406143ebc.tar.lz
yuzu-12f5f320985824d1ebad587ebecb0f8406143ebc.tar.xz
yuzu-12f5f320985824d1ebad587ebecb0f8406143ebc.tar.zst
yuzu-12f5f320985824d1ebad587ebecb0f8406143ebc.zip
-rw-r--r--src/shader_recompiler/ir_opt/global_memory_to_storage_buffer_pass.cpp31
-rw-r--r--src/shader_recompiler/shader_info.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp2
4 files changed, 32 insertions, 4 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 @@
#include <compare>
#include <optional>
#include <ranges>
+#include <map>
#include <boost/container/flat_set.hpp>
#include <boost/container/small_vector.hpp>
@@ -45,6 +46,7 @@ using StorageBufferSet =
using StorageInstVector = boost::container::small_vector<StorageInst, 24>;
using VisitedBlocks = boost::container::flat_set<IR::Block*, std::less<IR::Block*>,
boost::container::small_vector<IR::Block*, 4>>;
+using StorageWritesMap = std::map<StorageBufferAddr, bool>;
/// Returns true when the instruction is a global memory instruction
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
IR::Opcode GlobalToStorage(IR::Opcode 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
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
// avoid getting false positives
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
+ 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);
to_replace.push_back(StorageInst{
.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) {
StorageBufferSet storage_buffers;
StorageInstVector to_replace;
+ StorageWritesMap writes_map;
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
if (!IsGlobalMemory(inst)) {
continue;
}
- CollectStorageBuffers(*block, inst, storage_buffers, to_replace);
+ CollectStorageBuffers(*block, inst, storage_buffers, to_replace, writes_map);
}
}
Info& info{program.info};
@@ -366,6 +392,7 @@ void GlobalMemoryToStorageBufferPass(IR::Program& program) {
.cbuf_index{storage_buffer.index},
.cbuf_offset{storage_buffer.offset},
.count{1},
+ .is_written{writes_map[storage_buffer]},
});
++storage_index;
}
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 {
u32 cbuf_index;
u32 cbuf_offset;
u32 count;
+ bool is_written;
};
struct Info {
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index fb19bb4b9..6707842ab 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -75,7 +75,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
size_t ssbo_index{};
for (const auto& desc : info.storage_buffers_descriptors) {
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;
}
buffer_cache.UpdateComputeBuffers();
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index d17b79e02..e8c3a5624 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -163,7 +163,7 @@ void GraphicsPipeline::Configure(bool is_indexed) {
for (const auto& desc : info.storage_buffers_descriptors) {
ASSERT(desc.count == 1);
buffer_cache.BindGraphicsStorageBuffer(stage, index, desc.cbuf_index, desc.cbuf_offset,
- true);
+ desc.is_written);
++index;
}
const auto& cbufs{maxwell3d.state.shader_stages[stage].const_buffers};