[TEST] Adjustments on the pipeline cache + optimized vertex buffer refinement

This commit is contained in:
CamilleLaVey
2026-08-22 03:34:01 -04:00
parent b0b4817162
commit a6d49872a1
7 changed files with 41 additions and 16 deletions
+7 -5
View File
@@ -811,7 +811,7 @@ void BufferCache<P>::BindHostVertexBuffers() {
if (use_optimized_vertex_buffers) {
auto& flags = maxwell3d->dirty.flags;
const u32 enabled_mask = enabled_vertex_buffers_mask;
bool any_dirty = false;
u32 dirty_mask = 0;
u32 pending_mask = enabled_mask;
while (pending_mask != 0) {
const u32 index = std::countr_zero(pending_mask);
@@ -820,13 +820,15 @@ void BufferCache<P>::BindHostVertexBuffers() {
Buffer& buffer = slot_buffers[binding.buffer_id];
TouchBuffer(buffer, binding.buffer_id);
SynchronizeBuffer(buffer, binding.device_addr, binding.size);
any_dirty |= flags[Dirty::VertexBuffer0 + index];
if (flags[Dirty::VertexBuffer0 + index]) {
dirty_mask |= 1u << index;
}
}
if (enabled_mask == 0 || !any_dirty) {
if (dirty_mask == 0) {
return;
}
const u32 min_index = static_cast<u32>(std::countr_zero(enabled_mask));
const u32 max_index = 32u - static_cast<u32>(std::countl_zero(enabled_mask));
const u32 min_index = static_cast<u32>(std::countr_zero(dirty_mask));
const u32 max_index = 32u - static_cast<u32>(std::countl_zero(dirty_mask));
HostBindings<Buffer> bindings{};
bindings.min_index = min_index;
bindings.max_index = max_index;
@@ -32,6 +32,7 @@ using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET;
using Tegra::Texture::TexturePair;
ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk::PipelineCache& pipeline_cache_,
std::shared_mutex& pipeline_cache_mutex_,
DescriptorPool& descriptor_pool,
GuestDescriptorQueue& guest_descriptor_queue_,
DescriptorBufferRing& descriptor_buffer_ring_,
@@ -40,7 +41,8 @@ ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk
VideoCore::ShaderNotify* shader_notify, const Shader::Info& info_,
vk::ShaderModule spv_module_, u64 shader_hash_)
: device{device_},
pipeline_cache(pipeline_cache_), guest_descriptor_queue{guest_descriptor_queue_},
pipeline_cache(pipeline_cache_), pipeline_cache_mutex(pipeline_cache_mutex_),
guest_descriptor_queue{guest_descriptor_queue_},
descriptor_buffer_ring{descriptor_buffer_ring_}, info{info_},
shader_hash{shader_hash_}, spv_module(std::move(spv_module_)) {
if (shader_notify) {
@@ -111,6 +113,7 @@ ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk
.basePipelineIndex = 0,
};
try {
std::shared_lock cache_lock{pipeline_cache_mutex};
pipeline = device.GetLogical().CreateComputePipeline(compute_ci, *pipeline_cache);
} catch (const vk::Exception& exception) {
LOG_CRITICAL(Render_Vulkan, "Adreno rejected compute shader {:016X}: {}", shader_hash,
@@ -9,6 +9,7 @@
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <shared_mutex>
#include "common/common_types.h"
#include "common/thread_worker.h"
@@ -34,6 +35,7 @@ class Scheduler;
class ComputePipeline {
public:
explicit ComputePipeline(const Device& device, Scheduler& scheduler, vk::PipelineCache& pipeline_cache,
std::shared_mutex& pipeline_cache_mutex,
DescriptorPool& descriptor_pool,
GuestDescriptorQueue& guest_descriptor_queue,
DescriptorBufferRing& descriptor_buffer_ring,
@@ -59,6 +61,7 @@ public:
private:
const Device& device;
vk::PipelineCache& pipeline_cache;
std::shared_mutex& pipeline_cache_mutex;
GuestDescriptorQueue& guest_descriptor_queue;
DescriptorBufferRing& descriptor_buffer_ring;
Shader::Info info;
@@ -251,7 +251,8 @@ ConfigureFuncPtr ConfigureFunc(const std::array<vk::ShaderModule, NUM_STAGES>& m
// TODO(crueter): This is the worst-formatted code I have EVER seen
GraphicsPipeline::GraphicsPipeline(
Scheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_,
vk::PipelineCache& pipeline_cache_, VideoCore::ShaderNotify* shader_notify,
vk::PipelineCache& pipeline_cache_, std::shared_mutex& pipeline_cache_mutex_,
VideoCore::ShaderNotify* shader_notify,
const Device& device_, DescriptorPool& descriptor_pool,
GuestDescriptorQueue& guest_descriptor_queue_, DescriptorBufferRing& descriptor_buffer_ring_,
Common::ThreadWorker* worker_thread,
@@ -259,7 +260,8 @@ GraphicsPipeline::GraphicsPipeline(
const GraphicsPipelineCacheKey& key_, std::array<vk::ShaderModule, NUM_STAGES> stages,
const std::array<const Shader::Info*, NUM_STAGES>& infos)
: key{key_}, device{device_}, texture_cache{texture_cache_}, buffer_cache{buffer_cache_},
pipeline_cache(pipeline_cache_), scheduler{scheduler_},
pipeline_cache(pipeline_cache_), pipeline_cache_mutex(pipeline_cache_mutex_),
scheduler{scheduler_},
guest_descriptor_queue{guest_descriptor_queue_},
descriptor_buffer_ring{descriptor_buffer_ring_}, spv_modules{std::move(stages)} {
if (shader_notify) {
@@ -1081,6 +1083,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT;
}
std::shared_lock cache_lock{pipeline_cache_mutex};
pipeline = device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr,
@@ -11,6 +11,7 @@
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <shared_mutex>
#include <type_traits>
#include <vector>
@@ -78,7 +79,8 @@ class GraphicsPipeline {
public:
explicit GraphicsPipeline(
Scheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache,
vk::PipelineCache& pipeline_cache, VideoCore::ShaderNotify* shader_notify,
vk::PipelineCache& pipeline_cache, std::shared_mutex& pipeline_cache_mutex,
VideoCore::ShaderNotify* shader_notify,
const Device& device, DescriptorPool& descriptor_pool,
GuestDescriptorQueue& guest_descriptor_queue,
DescriptorBufferRing& descriptor_buffer_ring, Common::ThreadWorker* worker_thread,
@@ -151,6 +153,7 @@ private:
TextureCache& texture_cache;
BufferCache& buffer_cache;
vk::PipelineCache& pipeline_cache;
std::shared_mutex& pipeline_cache_mutex;
Scheduler& scheduler;
GuestDescriptorQueue& guest_descriptor_queue;
DescriptorBufferRing& descriptor_buffer_ring;
@@ -553,6 +553,7 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
PipelineCache::~PipelineCache() {
if (use_vulkan_pipeline_cache && !vulkan_pipeline_cache_filename.empty()) {
std::unique_lock lock{vulkan_pipeline_cache_mutex};
SerializeVulkanPipelineCache(vulkan_pipeline_cache_filename, vulkan_pipeline_cache,
CACHE_VERSION);
}
@@ -612,6 +613,7 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
if (use_vulkan_pipeline_cache) {
vulkan_pipeline_cache_filename = base_dir / "vulkan_pipelines.bin";
std::unique_lock lock{vulkan_pipeline_cache_mutex};
vulkan_pipeline_cache =
LoadVulkanPipelineCache(vulkan_pipeline_cache_filename, CACHE_VERSION);
}
@@ -710,6 +712,7 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
workers.WaitForRequests(stop_loading);
if (use_vulkan_pipeline_cache) {
std::unique_lock lock{vulkan_pipeline_cache_mutex};
SerializeVulkanPipelineCache(vulkan_pipeline_cache_filename, vulkan_pipeline_cache,
CACHE_VERSION);
size_t size = 0;
@@ -743,11 +746,14 @@ void PipelineCache::QueueVulkanPipelineCacheFlush() {
pipelines_since_flush = 0;
last_flush = now;
serialization_thread.QueueWork([this] {
SerializeVulkanPipelineCache(vulkan_pipeline_cache_filename, vulkan_pipeline_cache,
CACHE_VERSION);
size_t size = 0;
vulkan_pipeline_cache.Read(&size, nullptr);
last_cache_size.store(size, std::memory_order_relaxed);
{
std::unique_lock lock{vulkan_pipeline_cache_mutex};
SerializeVulkanPipelineCache(vulkan_pipeline_cache_filename, vulkan_pipeline_cache,
CACHE_VERSION);
size_t size = 0;
vulkan_pipeline_cache.Read(&size, nullptr);
last_cache_size.store(size, std::memory_order_relaxed);
}
flush_in_flight.store(false, std::memory_order_release);
});
}
@@ -890,7 +896,8 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
}
Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
return std::make_unique<GraphicsPipeline>(
scheduler, buffer_cache, texture_cache, vulkan_pipeline_cache, &shader_notify, device,
scheduler, buffer_cache, texture_cache, vulkan_pipeline_cache,
vulkan_pipeline_cache_mutex, &shader_notify, device,
descriptor_pool, guest_descriptor_queue, descriptor_buffer_ring, thread_worker, statistics,
render_pass_cache, key, std::move(modules), infos);
@@ -1014,7 +1021,8 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
spv_module.SetObjectNameEXT(name.c_str());
}
Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
return std::make_unique<ComputePipeline>(device, scheduler, vulkan_pipeline_cache, descriptor_pool,
return std::make_unique<ComputePipeline>(device, scheduler, vulkan_pipeline_cache,
vulkan_pipeline_cache_mutex, descriptor_pool,
guest_descriptor_queue, descriptor_buffer_ring,
thread_worker, statistics,
&shader_notify, program.info, std::move(spv_module),
@@ -12,6 +12,8 @@
#include <cstddef>
#include <filesystem>
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <type_traits>
#include <ankerl/unordered_dense.h>
#include <vector>
@@ -175,6 +177,7 @@ private:
std::filesystem::path vulkan_pipeline_cache_filename;
vk::PipelineCache vulkan_pipeline_cache;
std::shared_mutex vulkan_pipeline_cache_mutex;
size_t pipelines_since_flush{};
std::chrono::steady_clock::time_point last_flush{};
std::atomic<size_t> last_cache_size{};