diff --git a/Common/GPU/Vulkan/VulkanFrameData.h b/Common/GPU/Vulkan/VulkanFrameData.h index 0085c3ed96..346f15c782 100644 --- a/Common/GPU/Vulkan/VulkanFrameData.h +++ b/Common/GPU/Vulkan/VulkanFrameData.h @@ -29,6 +29,9 @@ struct QueueProfileContext { double cpuEndTime; double descWriteTime; int descriptorsWritten; +#ifdef _DEBUG + int commandCounts[11]; +#endif }; class VKRFramebuffer; diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index 4f97b25434..12c2ac5ee0 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -350,7 +350,6 @@ void VulkanQueueRunner::RunSteps(std::vector &steps, int curFrame, Fr for (size_t i = 0; i < steps.size(); i++) { const VKRStep &step = *steps[i]; - if (emitLabels) { VkDebugUtilsLabelEXT labelInfo{ VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT }; char temp[128]; @@ -394,7 +393,7 @@ void VulkanQueueRunner::RunSteps(std::vector &steps, int curFrame, Fr vkCmdBeginDebugUtilsLabelEXT(cmd, &labelInfo); } } - PerformRenderPass(step, cmd, curFrame); + PerformRenderPass(step, cmd, curFrame, frameData.profile); break; case VKRStepType::COPY: PerformCopy(step, cmd); @@ -1101,7 +1100,7 @@ void TransitionFromOptimal(VkCommandBuffer cmd, VkImage colorImage, VkImageLayou } } -void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer cmd, int curFrame) { +void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer cmd, int curFrame, QueueProfileContext &profile) { for (size_t i = 0; i < step.preTransitions.size(); i++) { const TransitionRequest &iter = step.preTransitions[i]; if (iter.aspect == VK_IMAGE_ASPECT_COLOR_BIT && iter.fb->color.layout != iter.targetLayout) { @@ -1210,6 +1209,13 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c for (size_t i = 0; i < commands.size(); i++) { const VkRenderData &c = commands[i]; +#ifdef _DEBUG + if (profile.enabled) { + if ((size_t)step.stepType < ARRAY_SIZE(profile.commandCounts)) { + profile.commandCounts[(size_t)c.cmd]++; + } + } +#endif switch (c.cmd) { case VKRRenderCommand::REMOVED: break; @@ -2088,3 +2094,24 @@ bool VulkanQueueRunner::CopyReadbackBuffer(FrameData &frameData, VKRFramebuffer vmaUnmapMemory(vulkan_->Allocator(), readback->allocation); return true; } + +const char *VKRRenderCommandToString(VKRRenderCommand cmd) { + const char * const str[] = { + "REMOVED", + "BIND_GRAPHICS_PIPELINE", // async + "STENCIL", + "BLEND", + "VIEWPORT", + "SCISSOR", + "CLEAR", + "DRAW", + "DRAW_INDEXED", + "PUSH_CONSTANTS", + "DEBUG_ANNOTATION", + }; + if ((int)cmd < ARRAY_SIZE(str)) { + return str[(int)cmd]; + } else { + return "N/A"; + } +} diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.h b/Common/GPU/Vulkan/VulkanQueueRunner.h index a7676c4660..590e821432 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.h +++ b/Common/GPU/Vulkan/VulkanQueueRunner.h @@ -280,7 +280,7 @@ private: bool InitDepthStencilBuffer(VkCommandBuffer cmd); // Used for non-buffered rendering. VKRRenderPass *PerformBindFramebufferAsRenderTarget(const VKRStep &pass, VkCommandBuffer cmd); - void PerformRenderPass(const VKRStep &pass, VkCommandBuffer cmd, int curFrame); + void PerformRenderPass(const VKRStep &pass, VkCommandBuffer cmd, int curFrame, QueueProfileContext &profile); void PerformCopy(const VKRStep &pass, VkCommandBuffer cmd); void PerformBlit(const VKRStep &pass, VkCommandBuffer cmd); void PerformReadback(const VKRStep &pass, VkCommandBuffer cmd, FrameData &frameData); @@ -346,3 +346,5 @@ private: }; DepthBufferInfo depth_; }; + +const char *VKRRenderCommandToString(VKRRenderCommand cmd); diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 9a4f4e1aa6..8b031ce8c9 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -723,6 +723,17 @@ void VulkanRenderManager::BeginFrame(bool enableProfiling, bool enableLogProfile str << line; frameData.profile.profileSummary = str.str(); } + +#ifdef _DEBUG + std::string cmdString; + for (int i = 0; i < ARRAY_SIZE(frameData.profile.commandCounts); i++) { + if (frameData.profile.commandCounts[i] > 0) { + cmdString += StringFromFormat("%s: %d\n", VKRRenderCommandToString((VKRRenderCommand)i), frameData.profile.commandCounts[i]); + } + } + memset(frameData.profile.commandCounts, 0, sizeof(frameData.profile.commandCounts)); + frameData.profile.profileSummary += cmdString; +#endif } frameData.profile.descriptorsWritten = 0;