summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrChat <arkolbed@gmail.com>2018-02-20 21:25:51 -0600
committerDrChat <arkolbed@gmail.com>2018-02-20 21:25:51 -0600
commit1a263f14a2dfcd3c56c170a7d95cabaa880b77a2 (patch)
tree6fe788629c148d268ca4b86c6575fb42873c1ce5
parent2a908eb86de6dea40828e0e43560adc9dd97db6f (diff)
[Vulkan] Hash and track vertex descriptor sets (similar to texture cache)crash_dumps
-rw-r--r--src/xenia/gpu/vulkan/buffer_cache.cc44
-rw-r--r--src/xenia/gpu/vulkan/buffer_cache.h11
2 files changed, 53 insertions, 2 deletions
diff --git a/src/xenia/gpu/vulkan/buffer_cache.cc b/src/xenia/gpu/vulkan/buffer_cache.cc
index 46d6da8e8..2008f4cea 100644
--- a/src/xenia/gpu/vulkan/buffer_cache.cc
+++ b/src/xenia/gpu/vulkan/buffer_cache.cc
@@ -543,9 +543,46 @@ std::pair<VkBuffer, VkDeviceSize> BufferCache::UploadVertexBuffer(
return {transient_buffer_->gpu_buffer(), offset + source_offset};
}
+void BufferCache::HashVertexBindings(
+ XXH64_state_t* hash_state,
+ const std::vector<Shader::VertexBinding>& vertex_bindings) {
+ auto& regs = *register_file_;
+ for (const auto& vertex_binding : vertex_bindings) {
+ int r = XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 +
+ (vertex_binding.fetch_constant / 3) * 6;
+ const auto group = reinterpret_cast<xe_gpu_fetch_group_t*>(&regs.values[r]);
+ const xe_gpu_vertex_fetch_t* fetch = nullptr;
+ switch (vertex_binding.fetch_constant % 3) {
+ case 0:
+ fetch = &group->vertex_fetch_0;
+ break;
+ case 1:
+ fetch = &group->vertex_fetch_1;
+ break;
+ case 2:
+ fetch = &group->vertex_fetch_2;
+ break;
+ }
+
+ XXH64_update(hash_state, fetch, sizeof(fetch));
+ }
+}
+
VkDescriptorSet BufferCache::PrepareVertexSet(
VkCommandBuffer command_buffer, VkFence fence,
- std::vector<Shader::VertexBinding> vertex_bindings) {
+ const std::vector<Shader::VertexBinding>& vertex_bindings) {
+ // (quickly) Generate a hash.
+ XXH64_state_t hash_state;
+ XXH64_reset(&hash_state, 0);
+
+ // (quickly) Generate a hash.
+ HashVertexBindings(&hash_state, vertex_bindings);
+ uint64_t hash = XXH64_digest(&hash_state);
+ for (auto it = vertex_sets_.find(hash); it != vertex_sets_.end(); ++it) {
+ // TODO(DrChat): We need to compare the bindings and ensure they're equal.
+ return it->second;
+ }
+
if (!vertex_descriptor_pool_->has_open_batch()) {
vertex_descriptor_pool_->BeginBatch(fence);
}
@@ -621,6 +658,7 @@ VkDescriptorSet BufferCache::PrepareVertexSet(
}
vkUpdateDescriptorSets(*device_, 1, &descriptor_write, 0, nullptr);
+ vertex_sets_[hash] = set;
return set;
}
@@ -718,6 +756,10 @@ void BufferCache::ClearCache() { transient_cache_.clear(); }
void BufferCache::Scavenge() {
transient_cache_.clear();
transient_buffer_->Scavenge();
+
+ // TODO(DrChat): These could persist across frames, we just need a smart way
+ // to delete unused ones.
+ vertex_sets_.clear();
if (vertex_descriptor_pool_->has_open_batch()) {
vertex_descriptor_pool_->EndBatch();
}
diff --git a/src/xenia/gpu/vulkan/buffer_cache.h b/src/xenia/gpu/vulkan/buffer_cache.h
index b39a67b52..67f964353 100644
--- a/src/xenia/gpu/vulkan/buffer_cache.h
+++ b/src/xenia/gpu/vulkan/buffer_cache.h
@@ -20,8 +20,10 @@
#include "xenia/ui/vulkan/vulkan_device.h"
#include "third_party/vulkan/vk_mem_alloc.h"
+#include "third_party/xxhash/xxhash.h"
#include <map>
+#include <unordered_map>
namespace xe {
namespace gpu {
@@ -89,7 +91,7 @@ class BufferCache {
// Prepares and returns a vertex descriptor set.
VkDescriptorSet PrepareVertexSet(
VkCommandBuffer setup_buffer, VkFence fence,
- std::vector<Shader::VertexBinding> vertex_bindings);
+ const std::vector<Shader::VertexBinding>& vertex_bindings);
// Flushes all pending data to the GPU.
// Until this is called the GPU is not guaranteed to see any data.
@@ -124,6 +126,10 @@ class BufferCache {
VkResult CreateConstantDescriptorSet();
void FreeConstantDescriptorSet();
+ void HashVertexBindings(
+ XXH64_state_t* hash_state,
+ const std::vector<Shader::VertexBinding>& vertex_bindings);
+
// Allocates a block of memory in the transient buffer.
// When memory is not available fences are checked and space is reclaimed.
// Returns VK_WHOLE_SIZE if requested amount of memory is not available.
@@ -155,6 +161,9 @@ class BufferCache {
std::unique_ptr<ui::vulkan::DescriptorPool> vertex_descriptor_pool_ = nullptr;
VkDescriptorSetLayout vertex_descriptor_set_layout_ = nullptr;
+ // Current frame vertex sets.
+ std::unordered_map<uint64_t, VkDescriptorSet> vertex_sets_;
+
// Descriptor set used to hold vertex/pixel shader float constants
VkDescriptorPool constant_descriptor_pool_ = nullptr;
VkDescriptorSetLayout constant_descriptor_set_layout_ = nullptr;