From 1188f285b73a387eae4a3c3d4ca04a5b932b1994 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Thu, 30 Jul 2026 18:57:15 -0400 Subject: [PATCH] Pipeline Creation Feedback impl --- .../renderer_vulkan/vk_buffer_cache.cpp | 6 +++++ .../renderer_vulkan/vk_buffer_cache.h | 5 ++++ .../renderer_vulkan/vk_compute_pipeline.cpp | 18 +++++++++++++- .../renderer_vulkan/vk_graphics_pipeline.cpp | 24 ++++++++++++++++++- src/video_core/vulkan_common/vulkan_device.h | 5 ++++ 5 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 49a2eaf3a3..ac98483d3d 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -69,6 +69,9 @@ vk::Buffer CreateBuffer(const Device& device, const MemoryAllocator& memory_allo if (device.IsExtConditionalRendering()) { flags |= VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT; } + if (device.IsBufferDeviceAddressSupported()) { + flags |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + } const VkBufferCreateInfo buffer_ci = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, @@ -100,6 +103,9 @@ Buffer::Buffer(BufferCacheRuntime& runtime, DAddr cpu_addr_, u64 size_bytes_) if (runtime.device.HasDebuggingToolAttached()) { buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str()); } + if (device->IsBufferDeviceAddressSupported()) { + device_address = device->GetLogical().GetBufferDeviceAddress(*buffer); + } } void Buffer::MarkUsage(u64 offset, u64 size) noexcept { diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index ed45aa7125..22ee0311b0 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -39,6 +39,10 @@ public: return *buffer; } + [[nodiscard]] VkDeviceAddress DeviceAddress() const noexcept { + return device_address; + } + [[nodiscard]] bool IsRegionUsed(u64 offset, u64 size) const noexcept { return tracker.IsUsed(offset, size); } @@ -70,6 +74,7 @@ private: vk::Buffer buffer; std::vector views; VideoCommon::UsageTracker tracker; + VkDeviceAddress device_address{}; u64 last_usage_tick{}; bool is_null{}; }; diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 006bfc0a09..5661e83813 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp @@ -69,9 +69,17 @@ ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk if (device.IsKhrPipelineExecutablePropertiesEnabled() && Settings::values.renderer_debug.GetValue()) { flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; } + VkPipelineCreationFeedback creation_feedback{}; + const VkPipelineCreationFeedbackCreateInfo feedback_ci{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO, + .pNext = nullptr, + .pPipelineCreationFeedback = &creation_feedback, + .pipelineStageCreationFeedbackCount = 0, + .pPipelineStageCreationFeedbacks = nullptr, + }; const VkComputePipelineCreateInfo compute_ci{ .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = device.IsExtPipelineCreationFeedbackSupported() ? &feedback_ci : nullptr, .flags = flags, .stage{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, @@ -101,6 +109,14 @@ ComputePipeline::ComputePipeline(const Device& device_, Scheduler& scheduler, vk return; } + if ((creation_feedback.flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT) != 0) { + const bool cache_hit = + (creation_feedback.flags & + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT) != 0; + LOG_DEBUG(Render_Vulkan, "Compute pipeline {:016X} cache_hit={} duration={}us", + shader_hash, cache_hit, creation_feedback.duration / 1000); + } + // Log compute pipeline creation if (GPU::Logging::IsActive()) { GPU::Logging::GPULogger::GetInstance().LogPipelineStateChange( diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 3fdf0851c7..2508cbde9d 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -1056,9 +1056,23 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { .stencilAttachmentFormat = stencil_attachment_format, }; + VkPipelineCreationFeedback creation_feedback{}; + const VkPipelineCreationFeedbackCreateInfo feedback_ci{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO, + .pNext = device.IsKhrDynamicRenderingSupported() ? &rendering_ci : nullptr, + .pPipelineCreationFeedback = &creation_feedback, + .pipelineStageCreationFeedbackCount = 0, + .pPipelineStageCreationFeedbacks = nullptr, + }; + const void* const create_next = + device.IsExtPipelineCreationFeedbackSupported() + ? static_cast(&feedback_ci) + : (device.IsKhrDynamicRenderingSupported() ? static_cast(&rendering_ci) + : nullptr); + pipeline = device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = device.IsKhrDynamicRenderingSupported() ? &rendering_ci : nullptr, + .pNext = create_next, .flags = flags, .stageCount = static_cast(shader_stages.size()), .pStages = shader_stages.data(), @@ -1078,6 +1092,14 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { .basePipelineIndex = 0, }, *pipeline_cache); + if ((creation_feedback.flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT) != 0) { + const bool cache_hit = + (creation_feedback.flags & + VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT) != 0; + LOG_DEBUG(Render_Vulkan, "Graphics pipeline {:016X} cache_hit={} duration={}us", + key.Hash(), cache_hit, creation_feedback.duration / 1000); + } + // Log graphics pipeline creation if (GPU::Logging::IsActive()) { const std::string pipeline_info = fmt::format( diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index e9cb5f7b24..2b37ceceb7 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -88,6 +88,7 @@ VK_DEFINE_HANDLE(VmaAllocator) EXTENSION(EXT, CONSERVATIVE_RASTERIZATION, conservative_rasterization) \ EXTENSION(EXT, DEPTH_RANGE_UNRESTRICTED, depth_range_unrestricted) \ EXTENSION(EXT, MEMORY_BUDGET, memory_budget) \ + EXTENSION(EXT, PIPELINE_CREATION_FEEDBACK, pipeline_creation_feedback) \ EXTENSION(EXT, ROBUSTNESS_2, robustness_2) \ EXTENSION(EXT, SAMPLER_FILTER_MINMAX, sampler_filter_minmax) \ EXTENSION(EXT, SHADER_STENCIL_EXPORT, shader_stencil_export) \ @@ -484,6 +485,10 @@ FN_MAX_LIMIT_LIST } /// Returns true if the device supports descriptor buffers. + bool IsExtPipelineCreationFeedbackSupported() const { + return extensions.pipeline_creation_feedback; + } + bool IsExtDescriptorBufferSupported() const { return extensions.descriptor_buffer; }