[vulkan] Added dirty tracking in PushDescriptor
This commit is contained in:
parent
5aa9ed4dc0
commit
a711a4e6ab
|
|
@ -5,6 +5,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <span>
|
||||
|
||||
|
|
@ -308,6 +309,37 @@ void GraphicsPipeline::AddTransition(GraphicsPipeline* transition) {
|
|||
transitions.push_back(transition);
|
||||
}
|
||||
|
||||
bool GraphicsPipeline::UpdateDescriptorDirtyMask(const DescriptorUpdateEntry* data, size_t count) {
|
||||
if (count == 0) {
|
||||
descriptor_dirty_mask.clear();
|
||||
last_descriptor_data.clear();
|
||||
last_descriptor_count = 0;
|
||||
return false;
|
||||
}
|
||||
const size_t word_count = (count + 63) / 64;
|
||||
descriptor_dirty_mask.assign(word_count, 0);
|
||||
|
||||
if (last_descriptor_count != count || last_descriptor_data.size() != count) {
|
||||
last_descriptor_data.assign(data, data + count);
|
||||
last_descriptor_count = count;
|
||||
std::fill(descriptor_dirty_mask.begin(), descriptor_dirty_mask.end(), ~0ULL);
|
||||
if ((count % 64) != 0) {
|
||||
descriptor_dirty_mask.back() = (1ULL << (count % 64)) - 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool any_dirty = false;
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
if (std::memcmp(&last_descriptor_data[i], &data[i], sizeof(DescriptorUpdateEntry)) != 0) {
|
||||
last_descriptor_data[i] = data[i];
|
||||
descriptor_dirty_mask[i / 64] |= (1ULL << (i % 64));
|
||||
any_dirty = true;
|
||||
}
|
||||
}
|
||||
return any_dirty;
|
||||
}
|
||||
|
||||
template <typename Spec>
|
||||
bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
||||
std::array<VideoCommon::ImageViewInOut, MAX_IMAGE_ELEMENTS> views;
|
||||
|
|
@ -524,9 +556,22 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
|
|||
GPU::Logging::GPULogger::GetInstance().LogPipelineBind(false, pipeline_info);
|
||||
}
|
||||
|
||||
const void* const descriptor_data{guest_descriptor_queue.UpdateData()};
|
||||
const DescriptorUpdateEntry* const descriptor_data{guest_descriptor_queue.UpdateData()};
|
||||
const size_t descriptor_count = guest_descriptor_queue.UpdateCount();
|
||||
const bool has_descriptor_layout = descriptor_set_layout != nullptr;
|
||||
const bool descriptors_dirty = has_descriptor_layout &&
|
||||
UpdateDescriptorDirtyMask(descriptor_data, descriptor_count);
|
||||
VkDescriptorSet descriptor_set = last_descriptor_set;
|
||||
if (has_descriptor_layout && !uses_push_descriptor) {
|
||||
if (descriptors_dirty || descriptor_set == VK_NULL_HANDLE) {
|
||||
descriptor_set = descriptor_allocator.Commit();
|
||||
const vk::Device& dev{device.GetLogical()};
|
||||
dev.UpdateDescriptorSet(descriptor_set, *descriptor_update_template, descriptor_data);
|
||||
last_descriptor_set = descriptor_set;
|
||||
}
|
||||
}
|
||||
scheduler.Record([this, descriptor_data, bind_pipeline, rescaling_data = rescaling.Data(),
|
||||
is_rescaling, update_rescaling,
|
||||
is_rescaling, update_rescaling, descriptors_dirty, descriptor_set,
|
||||
uses_render_area = render_area.uses_render_area,
|
||||
render_area_data = render_area.words](vk::CommandBuffer cmdbuf) {
|
||||
if (bind_pipeline) {
|
||||
|
|
@ -551,12 +596,12 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
|
|||
return;
|
||||
}
|
||||
if (uses_push_descriptor) {
|
||||
if (!descriptors_dirty) {
|
||||
return;
|
||||
}
|
||||
cmdbuf.PushDescriptorSetWithTemplateKHR(*descriptor_update_template, *pipeline_layout,
|
||||
0, descriptor_data);
|
||||
} 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,
|
||||
descriptor_set, nullptr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
|
|
@ -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 {
|
||||
|
|
@ -168,6 +170,13 @@ private:
|
|||
vk::DescriptorUpdateTemplate descriptor_update_template;
|
||||
vk::Pipeline pipeline;
|
||||
|
||||
bool UpdateDescriptorDirtyMask(const DescriptorUpdateEntry* data, size_t count);
|
||||
|
||||
std::vector<DescriptorUpdateEntry> last_descriptor_data;
|
||||
std::vector<u64> descriptor_dirty_mask;
|
||||
size_t last_descriptor_count{};
|
||||
VkDescriptorSet last_descriptor_set{VK_NULL_HANDLE};
|
||||
|
||||
std::condition_variable build_condvar;
|
||||
std::mutex build_mutex;
|
||||
std::atomic_bool is_built{false};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -47,32 +50,44 @@ public:
|
|||
return upload_start;
|
||||
}
|
||||
|
||||
size_t UpdateCount() const noexcept {
|
||||
return static_cast<size_t>(payload_cursor - upload_start);
|
||||
}
|
||||
|
||||
void AddSampledImage(VkImageView image_view, VkSampler sampler) {
|
||||
*(payload_cursor++) = VkDescriptorImageInfo{
|
||||
DescriptorUpdateEntry entry{};
|
||||
entry.image = VkDescriptorImageInfo{
|
||||
.sampler = sampler,
|
||||
.imageView = image_view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
};
|
||||
*(payload_cursor++) = entry;
|
||||
}
|
||||
|
||||
void AddImage(VkImageView image_view) {
|
||||
*(payload_cursor++) = VkDescriptorImageInfo{
|
||||
DescriptorUpdateEntry entry{};
|
||||
entry.image = VkDescriptorImageInfo{
|
||||
.sampler = VK_NULL_HANDLE,
|
||||
.imageView = image_view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
};
|
||||
*(payload_cursor++) = entry;
|
||||
}
|
||||
|
||||
void AddBuffer(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size) {
|
||||
*(payload_cursor++) = VkDescriptorBufferInfo{
|
||||
DescriptorUpdateEntry entry{};
|
||||
entry.buffer = VkDescriptorBufferInfo{
|
||||
.buffer = buffer,
|
||||
.offset = offset,
|
||||
.range = size,
|
||||
};
|
||||
*(payload_cursor++) = entry;
|
||||
}
|
||||
|
||||
void AddTexelBuffer(VkBufferView texel_buffer) {
|
||||
*(payload_cursor++) = texel_buffer;
|
||||
DescriptorUpdateEntry entry{};
|
||||
entry.texel_buffer = texel_buffer;
|
||||
*(payload_cursor++) = entry;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
Loading…
Reference in New Issue