summaryrefslogtreecommitdiff
path: root/drivers/vulkan
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vulkan')
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp76
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h35
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();
};