diff options
author | Juan Linietsky <reduzio@gmail.com> | 2019-09-20 17:58:06 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2020-02-11 12:01:26 +0100 |
commit | 123ee5995c989d7c2f0bb320fe94ef1702a48c13 (patch) | |
tree | 97855b3218f56dcaaeb5e737bf1a919f28ac36db /drivers | |
parent | dc32083681a770e9d7e332c5beed30b52c793752 (diff) |
Visual GPU profiler and related profiling support in Vulkan.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/vulkan/rendering_device_vulkan.cpp | 76 | ||||
-rw-r--r-- | drivers/vulkan/rendering_device_vulkan.h | 35 |
2 files changed, 111 insertions, 0 deletions
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 09b0f7113e..dd638bb7ba 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -31,6 +31,7 @@ #include "rendering_device_vulkan.h" #include "core/hashfuncs.h" #include "core/os/file_access.h" +#include "core/os/os.h" #include "core/project_settings.h" #include "drivers/vulkan/vulkan_context.h" #include "thirdparty/spirv-reflect/spirv_reflect.h" @@ -6167,6 +6168,20 @@ void RenderingDeviceVulkan::advance_frame() { staging_buffer_current = (staging_buffer_current + 1) % staging_buffer_blocks.size(); staging_buffer_used = false; } + + if (frames[frame].timestamp_count) { + vkGetQueryPoolResults(device, frames[frame].timestamp_pool, 0, frames[frame].timestamp_count, sizeof(uint64_t) * max_timestamp_query_elements, frames[frame].timestamp_result_values, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT); + SWAP(frames[frame].timestamp_names, frames[frame].timestamp_result_names); + SWAP(frames[frame].timestamp_cpu_values, frames[frame].timestamp_cpu_result_values); + } + + frames[frame].timestamp_result_count = frames[frame].timestamp_count; + frames[frame].timestamp_count = 0; + frames[frame].index = Engine::get_singleton()->get_frames_drawn(); +} + +uint32_t RenderingDeviceVulkan::get_frame_delay() const { + return frame_count; } void RenderingDeviceVulkan::_flush(bool p_current_frame) { @@ -6209,6 +6224,7 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context) { device = p_context->get_device(); frame_count = p_context->get_swapchain_image_count() + 1; //always need one extra to ensure it's unused at any time, without having to use a fence for this. limits = p_context->get_device_limits(); + max_timestamp_query_elements = 256; { //initialize allocator @@ -6224,6 +6240,8 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context) { //create setup and frame buffers for (int i = 0; i < frame_count; i++) { + frames[i].index = 0; + { //create command pool, one per frame is recommended VkCommandPoolCreateInfo cmd_pool_info; cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; @@ -6251,6 +6269,27 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context) { err = vkAllocateCommandBuffers(device, &cmdbuf, &frames[i].draw_command_buffer); ERR_CONTINUE(err); } + + { + //create query pool + VkQueryPoolCreateInfo query_pool_create_info; + query_pool_create_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + query_pool_create_info.flags = 0; + query_pool_create_info.pNext = NULL; + query_pool_create_info.queryType = VK_QUERY_TYPE_TIMESTAMP; + query_pool_create_info.queryCount = max_timestamp_query_elements; + query_pool_create_info.pipelineStatistics = 0; + + vkCreateQueryPool(device, &query_pool_create_info, NULL, &frames[i].timestamp_pool); + + frames[i].timestamp_names = memnew_arr(String, max_timestamp_query_elements); + frames[i].timestamp_cpu_values = memnew_arr(uint64_t, max_timestamp_query_elements); + frames[i].timestamp_count = 0; + frames[i].timestamp_result_names = memnew_arr(String, max_timestamp_query_elements); + frames[i].timestamp_cpu_result_values = memnew_arr(uint64_t, max_timestamp_query_elements); + frames[i].timestamp_result_values = memnew_arr(uint64_t, max_timestamp_query_elements); + frames[i].timestamp_result_count = 0; + } } { @@ -6319,6 +6358,37 @@ void RenderingDeviceVulkan::_free_rids(T &p_owner, const char *p_type) { } } +void RenderingDeviceVulkan::capture_timestamp(const String &p_name, bool p_sync_to_draw) { + + ERR_FAIL_COND(frames[frame].timestamp_count >= max_timestamp_query_elements); + + vkCmdWriteTimestamp(p_sync_to_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, frames[frame].timestamp_pool, frames[frame].timestamp_count); + frames[frame].timestamp_names[frames[frame].timestamp_count] = p_name; + frames[frame].timestamp_cpu_values[frames[frame].timestamp_count] = OS::get_singleton()->get_ticks_usec(); + frames[frame].timestamp_count++; +} + +uint32_t RenderingDeviceVulkan::get_captured_timestamps_count() const { + return frames[frame].timestamp_result_count; +} + +uint64_t RenderingDeviceVulkan::get_captured_timestamps_frame() const { + return frames[frame].index; +} + +uint64_t RenderingDeviceVulkan::get_captured_timestamp_gpu_time(uint32_t p_index) const { + ERR_FAIL_INDEX_V(p_index, frames[frame].timestamp_result_count, 0); + return frames[frame].timestamp_result_values[p_index]; +} +uint64_t RenderingDeviceVulkan::get_captured_timestamp_cpu_time(uint32_t p_index) const { + ERR_FAIL_INDEX_V(p_index, frames[frame].timestamp_result_count, 0); + return frames[frame].timestamp_cpu_result_values[p_index]; +} +String RenderingDeviceVulkan::get_captured_timestamp_name(uint32_t p_index) const { + ERR_FAIL_INDEX_V(p_index, frames[frame].timestamp_result_count, String()); + return frames[frame].timestamp_result_names[p_index]; +} + int RenderingDeviceVulkan::limit_get(Limit p_limit) { switch (p_limit) { case LIMIT_MAX_BOUND_UNIFORM_SETS: return limits.maxBoundDescriptorSets; @@ -6400,6 +6470,12 @@ void RenderingDeviceVulkan::finalize() { int f = (frame + i) % frame_count; _free_pending_resources(f); vkDestroyCommandPool(device, frames[i].command_pool, NULL); + vkDestroyQueryPool(device, frames[i].timestamp_pool, NULL); + memdelete_arr(frames[i].timestamp_names); + memdelete_arr(frames[i].timestamp_cpu_values); + memdelete_arr(frames[i].timestamp_result_names); + memdelete_arr(frames[i].timestamp_result_values); + memdelete_arr(frames[i].timestamp_cpu_result_values); } for (int i = 0; i < split_draw_list_allocators.size(); i++) { diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index c4e5b789bd..be776bd6e2 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -828,8 +828,26 @@ class RenderingDeviceVulkan : public RenderingDevice { VkCommandPool command_pool; VkCommandBuffer setup_command_buffer; //used at the begining of every frame for set-up VkCommandBuffer draw_command_buffer; //used at the begining of every frame for set-up + + struct Timestamp { + String description; + uint64_t value; + }; + + VkQueryPool timestamp_pool; + + String *timestamp_names; + uint64_t *timestamp_cpu_values; + uint32_t timestamp_count; + String *timestamp_result_names; + uint64_t *timestamp_cpu_result_values; + uint64_t *timestamp_result_values; + uint32_t timestamp_result_count; + uint64_t index; }; + uint32_t max_timestamp_query_elements; + Frame *frames; //frames available, they are cycled (usually 3) int frame; //current frame int frame_count; //total amount of frames @@ -958,6 +976,21 @@ public: virtual void free(RID p_id); + /****************/ + /**** Timing ****/ + /****************/ + + virtual void capture_timestamp(const String &p_name, bool p_sync_to_draw); + virtual uint32_t get_captured_timestamps_count() const; + virtual uint64_t get_captured_timestamps_frame() const; + virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const; + virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const; + virtual String get_captured_timestamp_name(uint32_t p_index) const; + + /****************/ + /**** Limits ****/ + /****************/ + virtual int limit_get(Limit p_limit); virtual void prepare_screen_for_drawing(); @@ -967,6 +1000,8 @@ public: virtual void finalize_frame(); virtual void advance_frame(); + virtual uint32_t get_frame_delay() const; + RenderingDeviceVulkan(); }; |