mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-11 22:32:29 +00:00
Cut per-draw descriptor set work
Only query the timeline semaphore when no set looks free, and skip the update plus rebind when the payload matches the previous draw.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <span>
|
||||
|
||||
@@ -568,8 +569,19 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
|
||||
}
|
||||
|
||||
const void* const descriptor_data{guest_descriptor_queue.UpdateData()};
|
||||
scheduler.Record([this, descriptor_data, bind_pipeline, rescaling_data = rescaling.Data(),
|
||||
is_rescaling, update_rescaling,
|
||||
bool update_descriptors = true;
|
||||
if (descriptor_set_layout && !uses_push_descriptor) {
|
||||
const auto* const entries = static_cast<const DescriptorUpdateEntry*>(descriptor_data);
|
||||
update_descriptors =
|
||||
bind_pipeline || last_descriptor_payload.size() != num_descriptor_entries ||
|
||||
std::memcmp(last_descriptor_payload.data(), entries,
|
||||
num_descriptor_entries * sizeof(DescriptorUpdateEntry)) != 0;
|
||||
if (update_descriptors) {
|
||||
last_descriptor_payload.assign(entries, entries + num_descriptor_entries);
|
||||
}
|
||||
}
|
||||
scheduler.Record([this, descriptor_data, bind_pipeline, update_descriptors,
|
||||
rescaling_data = rescaling.Data(), is_rescaling, update_rescaling,
|
||||
uses_render_area = render_area.uses_render_area,
|
||||
render_area_data = render_area.words](vk::CommandBuffer cmdbuf) {
|
||||
if (bind_pipeline) {
|
||||
@@ -599,7 +611,7 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
|
||||
if (uses_push_descriptor) {
|
||||
cmdbuf.PushDescriptorSetWithTemplateKHR(*descriptor_update_template, *pipeline_layout,
|
||||
0, descriptor_data);
|
||||
} else {
|
||||
} else if (update_descriptors) {
|
||||
const VkDescriptorSet descriptor_set{descriptor_allocator.Commit()};
|
||||
const vk::Device& dev{device.GetLogical()};
|
||||
dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "common/thread_worker.h"
|
||||
#include "shader_recompiler/shader_info.h"
|
||||
@@ -20,6 +21,7 @@
|
||||
#include "video_core/renderer_vulkan/vk_buffer_cache.h"
|
||||
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
|
||||
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
||||
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
|
||||
namespace VideoCore {
|
||||
@@ -170,6 +172,8 @@ private:
|
||||
vk::DescriptorUpdateTemplate descriptor_update_template;
|
||||
vk::Pipeline pipeline;
|
||||
|
||||
std::vector<DescriptorUpdateEntry> last_descriptor_payload;
|
||||
|
||||
std::condition_variable build_condvar;
|
||||
std::mutex build_mutex;
|
||||
std::atomic_bool is_built{false};
|
||||
|
||||
@@ -12,10 +12,7 @@ ResourcePool::ResourcePool(MasterSemaphore& master_semaphore_, size_t grow_step_
|
||||
: master_semaphore{&master_semaphore_}, grow_step{grow_step_} {}
|
||||
|
||||
size_t ResourcePool::CommitResource() {
|
||||
// Refresh semaphore to query updated results
|
||||
master_semaphore->Refresh();
|
||||
const u64 gpu_tick = master_semaphore->KnownGpuTick();
|
||||
const auto search = [this, gpu_tick](size_t begin, size_t end) -> std::optional<size_t> {
|
||||
const auto search = [this](size_t begin, size_t end, u64 gpu_tick) -> std::optional<size_t> {
|
||||
for (size_t iterator = begin; iterator < end; ++iterator) {
|
||||
if (gpu_tick >= ticks[iterator]) {
|
||||
ticks[iterator] = master_semaphore->CurrentTick();
|
||||
@@ -24,11 +21,17 @@ size_t ResourcePool::CommitResource() {
|
||||
}
|
||||
return std::nullopt;
|
||||
};
|
||||
// Try to find a free resource from the hinted position to the end.
|
||||
std::optional<size_t> found = search(hint_iterator, ticks.size());
|
||||
const auto find_free = [&](u64 gpu_tick) -> std::optional<size_t> {
|
||||
std::optional<size_t> result = search(hint_iterator, ticks.size(), gpu_tick);
|
||||
if (!result) {
|
||||
result = search(0, hint_iterator, gpu_tick);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
std::optional<size_t> found = find_free(master_semaphore->KnownGpuTick());
|
||||
if (!found) {
|
||||
// Search from beginning to the hinted position.
|
||||
found = search(0, hint_iterator);
|
||||
master_semaphore->Refresh();
|
||||
found = find_free(master_semaphore->KnownGpuTick());
|
||||
if (!found) {
|
||||
// Both searches failed, the pool is full; handle it.
|
||||
const size_t free_resource = ManageOverflow();
|
||||
|
||||
Reference in New Issue
Block a user