[Vulkan] Phase 1: Descriptor Set caching
This commit is contained in:
parent
f6d99e5032
commit
0b4102c4bd
6 changed files with 58 additions and 11 deletions
|
@ -96,9 +96,30 @@ VkDescriptorSet DescriptorAllocator::Commit() {
|
||||||
const size_t index = CommitResource();
|
const size_t index = CommitResource();
|
||||||
return sets[index / SETS_GROW_RATE][index % SETS_GROW_RATE];
|
return sets[index / SETS_GROW_RATE][index % SETS_GROW_RATE];
|
||||||
}
|
}
|
||||||
|
VkDescriptorSet DescriptorAllocator::CommitWithTracking(u64 current_frame, const void* descriptor_data) {
|
||||||
|
const size_t index = CommitResource();
|
||||||
|
const size_t group = index / SETS_GROW_RATE;
|
||||||
|
const size_t slot = index % SETS_GROW_RATE;
|
||||||
|
set_states[group][slot].set = sets[group][slot];
|
||||||
|
set_states[group][slot].last_update_frame = current_frame;
|
||||||
|
set_states[group][slot].last_data_ptr = descriptor_data;
|
||||||
|
return set_states[group][slot].set;
|
||||||
|
}
|
||||||
|
bool DescriptorAllocator::NeedsUpdate(VkDescriptorSet set, u64 current_frame, const void* descriptor_data) const {
|
||||||
|
for (const auto& group : set_states) {
|
||||||
|
for (const auto& st : group) {
|
||||||
|
if (st.set == set) {
|
||||||
|
// Update if pointer changed or the set hasn't been updated this frame
|
||||||
|
return st.last_data_ptr != descriptor_data || st.last_update_frame != current_frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
void DescriptorAllocator::Allocate(size_t begin, size_t end) {
|
void DescriptorAllocator::Allocate(size_t begin, size_t end) {
|
||||||
sets.push_back(AllocateDescriptors(end - begin));
|
const size_t count = end - begin;
|
||||||
|
sets.push_back(AllocateDescriptors(count));
|
||||||
|
set_states.emplace_back(count); // create parallel state storage
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) {
|
vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "common/common_types.h"
|
||||||
#include "shader_recompiler/shader_info.h"
|
#include "shader_recompiler/shader_info.h"
|
||||||
#include "video_core/renderer_vulkan/vk_resource_pool.h"
|
#include "video_core/renderer_vulkan/vk_resource_pool.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
@ -44,7 +44,15 @@ public:
|
||||||
DescriptorAllocator(const DescriptorAllocator&) = delete;
|
DescriptorAllocator(const DescriptorAllocator&) = delete;
|
||||||
|
|
||||||
VkDescriptorSet Commit();
|
VkDescriptorSet Commit();
|
||||||
|
// commit + remember when/with what we last updated this set
|
||||||
|
struct DescriptorSetState {
|
||||||
|
VkDescriptorSet set = VK_NULL_HANDLE;
|
||||||
|
u64 last_update_frame = 0;
|
||||||
|
const void* last_data_ptr = nullptr; // fast pointer compare
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDescriptorSet CommitWithTracking(u64 current_frame, const void* descriptor_data);
|
||||||
|
bool NeedsUpdate(VkDescriptorSet set, u64 current_frame, const void* descriptor_data) const;
|
||||||
private:
|
private:
|
||||||
explicit DescriptorAllocator(const Device& device_, MasterSemaphore& master_semaphore_,
|
explicit DescriptorAllocator(const Device& device_, MasterSemaphore& master_semaphore_,
|
||||||
DescriptorBank& bank_, VkDescriptorSetLayout layout_);
|
DescriptorBank& bank_, VkDescriptorSetLayout layout_);
|
||||||
|
@ -58,6 +66,7 @@ private:
|
||||||
VkDescriptorSetLayout layout{};
|
VkDescriptorSetLayout layout{};
|
||||||
|
|
||||||
std::vector<vk::DescriptorSets> sets;
|
std::vector<vk::DescriptorSets> sets;
|
||||||
|
std::vector<std::vector<DescriptorSetState>> set_states;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DescriptorPool {
|
class DescriptorPool {
|
||||||
|
|
|
@ -513,7 +513,25 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
|
||||||
const bool update_rescaling{scheduler.UpdateRescaling(is_rescaling)};
|
const bool update_rescaling{scheduler.UpdateRescaling(is_rescaling)};
|
||||||
const bool bind_pipeline{scheduler.UpdateGraphicsPipeline(this)};
|
const bool bind_pipeline{scheduler.UpdateGraphicsPipeline(this)};
|
||||||
const void* const descriptor_data{guest_descriptor_queue.UpdateData()};
|
const void* const descriptor_data{guest_descriptor_queue.UpdateData()};
|
||||||
scheduler.Record([this, descriptor_data, bind_pipeline, rescaling_data = rescaling.Data(),
|
|
||||||
|
// allocate/bind descriptor set and only update if needed
|
||||||
|
VkDescriptorSet descriptor_set = VK_NULL_HANDLE;
|
||||||
|
bool needs_update = false;
|
||||||
|
if (descriptor_set_layout) {
|
||||||
|
if (uses_push_descriptor) {
|
||||||
|
// handled below via push descriptor
|
||||||
|
} else {
|
||||||
|
descriptor_set = descriptor_allocator.CommitWithTracking(current_frame_number, descriptor_data);
|
||||||
|
needs_update = descriptor_allocator.NeedsUpdate(descriptor_set, current_frame_number, descriptor_data);
|
||||||
|
if (needs_update) {
|
||||||
|
const vk::Device& dev{device.GetLogical()};
|
||||||
|
dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduler.Record([this, descriptor_data, descriptor_set, bind_pipeline, rescaling_data = rescaling.Data(),
|
||||||
is_rescaling, update_rescaling,
|
is_rescaling, update_rescaling,
|
||||||
uses_render_area = render_area.uses_render_area,
|
uses_render_area = render_area.uses_render_area,
|
||||||
render_area_data = render_area.words](vk::CommandBuffer cmdbuf) {
|
render_area_data = render_area.words](vk::CommandBuffer cmdbuf) {
|
||||||
|
@ -539,12 +557,8 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (uses_push_descriptor) {
|
if (uses_push_descriptor) {
|
||||||
cmdbuf.PushDescriptorSetWithTemplateKHR(*descriptor_update_template, *pipeline_layout,
|
cmdbuf.PushDescriptorSetWithTemplateKHR(*descriptor_update_template, *pipeline_layout, 0, descriptor_data);
|
||||||
0, descriptor_data);
|
|
||||||
} else {
|
} else {
|
||||||
const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()};
|
|
||||||
const vk::Device& dev{device.GetLogical()};
|
|
||||||
dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data);
|
|
||||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline_layout, 0,
|
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline_layout, 0,
|
||||||
descriptor_set, nullptr);
|
descriptor_set, nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ public:
|
||||||
maxwell3d = maxwell3d_;
|
maxwell3d = maxwell3d_;
|
||||||
gpu_memory = gpu_memory_;
|
gpu_memory = gpu_memory_;
|
||||||
}
|
}
|
||||||
|
void SetFrameNumber(u64 frame) { current_frame_number = frame; }
|
||||||
private:
|
private:
|
||||||
template <typename Spec>
|
template <typename Spec>
|
||||||
bool ConfigureImpl(bool is_indexed);
|
bool ConfigureImpl(bool is_indexed);
|
||||||
|
@ -160,6 +160,7 @@ private:
|
||||||
std::mutex build_mutex;
|
std::mutex build_mutex;
|
||||||
std::atomic_bool is_built{false};
|
std::atomic_bool is_built{false};
|
||||||
bool uses_push_descriptor{false};
|
bool uses_push_descriptor{false};
|
||||||
|
u64 current_frame_number{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -217,6 +217,7 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
|
||||||
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
|
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
|
||||||
// update engine as channel may be different.
|
// update engine as channel may be different.
|
||||||
pipeline->SetEngine(maxwell3d, gpu_memory);
|
pipeline->SetEngine(maxwell3d, gpu_memory);
|
||||||
|
pipeline->SetFrameNumber(current_frame_number);
|
||||||
if (!pipeline->Configure(is_indexed))
|
if (!pipeline->Configure(is_indexed))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -759,6 +760,7 @@ void RasterizerVulkan::FlushCommands() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::TickFrame() {
|
void RasterizerVulkan::TickFrame() {
|
||||||
|
current_frame_number++;
|
||||||
draw_counter = 0;
|
draw_counter = 0;
|
||||||
guest_descriptor_queue.TickFrame();
|
guest_descriptor_queue.TickFrame();
|
||||||
compute_pass_descriptor_queue.TickFrame();
|
compute_pass_descriptor_queue.TickFrame();
|
||||||
|
|
|
@ -160,7 +160,7 @@ private:
|
||||||
void UpdateDynamicStates();
|
void UpdateDynamicStates();
|
||||||
|
|
||||||
void HandleTransformFeedback();
|
void HandleTransformFeedback();
|
||||||
|
u64 current_frame_number{0};
|
||||||
void UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs);
|
void UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||||
void UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs);
|
void UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||||
void UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs);
|
void UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue