From 7a7ae5defe9bfe36040509149aeb8d555fdefb1a Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 20 Aug 2024 11:27:33 +0200 Subject: [PATCH] Vulkan: Occlusion Queries Implements occlusion queries using VkQueryPools. Pull Request: https://projects.blender.org/blender/blender/pulls/123883 --- source/blender/gpu/CMakeLists.txt | 3 + .../render_graph/nodes/vk_begin_query_node.hh | 68 ++++++++++++ .../render_graph/nodes/vk_end_query_node.hh | 67 ++++++++++++ .../vulkan/render_graph/nodes/vk_node_info.hh | 12 +++ .../nodes/vk_reset_query_pool_node.hh | 68 ++++++++++++ .../tests/vk_render_graph_test_types.hh | 11 ++ .../render_graph/vk_command_buffer_wrapper.cc | 19 ++++ .../render_graph/vk_command_buffer_wrapper.hh | 13 +++ .../vulkan/render_graph/vk_render_graph.hh | 3 + .../render_graph/vk_render_graph_node.hh | 18 ++++ source/blender/gpu/vulkan/vk_common.cc | 10 ++ source/blender/gpu/vulkan/vk_common.hh | 2 + source/blender/gpu/vulkan/vk_query.cc | 102 ++++++++++++++++-- source/blender/gpu/vulkan/vk_query.hh | 15 +++ 14 files changed, 404 insertions(+), 7 deletions(-) create mode 100644 source/blender/gpu/vulkan/render_graph/nodes/vk_begin_query_node.hh create mode 100644 source/blender/gpu/vulkan/render_graph/nodes/vk_end_query_node.hh create mode 100644 source/blender/gpu/vulkan/render_graph/nodes/vk_reset_query_pool_node.hh diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 34e69669b85..f29c49addd5 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -267,6 +267,7 @@ set(VULKAN_SRC vulkan/vk_pixel_buffer.hh vulkan/vk_push_constants.hh vulkan/vk_query.hh + vulkan/render_graph/nodes/vk_begin_query_node.hh vulkan/render_graph/nodes/vk_begin_rendering_node.hh vulkan/render_graph/nodes/vk_blit_image_node.hh vulkan/render_graph/nodes/vk_clear_attachments_node.hh @@ -282,10 +283,12 @@ set(VULKAN_SRC vulkan/render_graph/nodes/vk_draw_indexed_node.hh vulkan/render_graph/nodes/vk_draw_indirect_node.hh vulkan/render_graph/nodes/vk_draw_node.hh + vulkan/render_graph/nodes/vk_end_query_node.hh vulkan/render_graph/nodes/vk_end_rendering_node.hh vulkan/render_graph/nodes/vk_fill_buffer_node.hh vulkan/render_graph/nodes/vk_node_info.hh vulkan/render_graph/nodes/vk_pipeline_data.hh + vulkan/render_graph/nodes/vk_reset_query_pool_node.hh vulkan/render_graph/nodes/vk_synchronization_node.hh vulkan/render_graph/nodes/vk_update_mipmaps_node.hh vulkan/render_graph/vk_command_buffer_wrapper.hh diff --git a/source/blender/gpu/vulkan/render_graph/nodes/vk_begin_query_node.hh b/source/blender/gpu/vulkan/render_graph/nodes/vk_begin_query_node.hh new file mode 100644 index 00000000000..91c3be1ced7 --- /dev/null +++ b/source/blender/gpu/vulkan/render_graph/nodes/vk_begin_query_node.hh @@ -0,0 +1,68 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "vk_node_info.hh" + +namespace blender::gpu::render_graph { + +/** + * Information stored inside the render graph node. See `VKRenderGraphNode`. + */ +struct VKBeginQueryData { + VkQueryPool vk_query_pool; + uint32_t query_index; + VkQueryControlFlags vk_query_control_flags; +}; + +/** + * Begin query + * + * - Contains logic to copy relevant data to the VKRenderGraphNode. + * - Determine read/write resource dependencies. + * - Add commands to a command builder. + */ +class VKBeginQueryNode : public VKNodeInfo { + public: + /** + * Update the node data with the data inside create_info. + * + * Has been implemented as a template to ensure all node specific data + * (`VK*Data`/`VK*CreateInfo`) types can be included in the same header file as the logic. The + * actual node data (`VKRenderGraphNode` includes all header files.) + */ + template void set_node_data(Node &node, const CreateInfo &create_info) + { + node.begin_query = create_info; + } + + /** + * Extract read/write resource dependencies from `create_info` and add them to `node_links`. + */ + void build_links(VKResourceStateTracker & /*resources*/, + VKRenderGraphNodeLinks & /*node_links*/, + const CreateInfo & /*create_info*/) override + { + } + + /** + * Build the commands and add them to the command_buffer. + */ + void build_commands(VKCommandBufferInterface &command_buffer, + Data &data, + VKBoundPipelines & /*r_bound_pipelines*/) override + { + command_buffer.begin_query(data.vk_query_pool, data.query_index, data.vk_query_control_flags); + } +}; +} // namespace blender::gpu::render_graph diff --git a/source/blender/gpu/vulkan/render_graph/nodes/vk_end_query_node.hh b/source/blender/gpu/vulkan/render_graph/nodes/vk_end_query_node.hh new file mode 100644 index 00000000000..d02726ea928 --- /dev/null +++ b/source/blender/gpu/vulkan/render_graph/nodes/vk_end_query_node.hh @@ -0,0 +1,67 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "vk_node_info.hh" + +namespace blender::gpu::render_graph { + +/** + * Information stored inside the render graph node. See `VKRenderGraphNode`. + */ +struct VKEndQueryData { + VkQueryPool vk_query_pool; + uint32_t query_index; +}; + +/** + * End Query Node + * + * - Contains logic to copy relevant data to the VKRenderGraphNode. + * - Determine read/write resource dependencies. + * - Add commands to a command builder. + */ +class VKEndQueryNode : public VKNodeInfo { + public: + /** + * Update the node data with the data inside create_info. + * + * Has been implemented as a template to ensure all node specific data + * (`VK*Data`/`VK*CreateInfo`) types can be included in the same header file as the logic. The + * actual node data (`VKRenderGraphNode` includes all header files.) + */ + template void set_node_data(Node &node, const CreateInfo &create_info) + { + node.end_query = create_info; + } + + /** + * Extract read/write resource dependencies from `create_info` and add them to `node_links`. + */ + void build_links(VKResourceStateTracker & /*resources*/, + VKRenderGraphNodeLinks & /*node_links*/, + const CreateInfo & /*create_info*/) override + { + } + + /** + * Build the commands and add them to the command_buffer. + */ + void build_commands(VKCommandBufferInterface &command_buffer, + Data &data, + VKBoundPipelines & /*r_bound_pipelines*/) override + { + command_buffer.end_query(data.vk_query_pool, data.query_index); + } +}; +} // namespace blender::gpu::render_graph diff --git a/source/blender/gpu/vulkan/render_graph/nodes/vk_node_info.hh b/source/blender/gpu/vulkan/render_graph/nodes/vk_node_info.hh index 90ffd365467..0ae1fdae8b2 100644 --- a/source/blender/gpu/vulkan/render_graph/nodes/vk_node_info.hh +++ b/source/blender/gpu/vulkan/render_graph/nodes/vk_node_info.hh @@ -21,6 +21,7 @@ namespace blender::gpu::render_graph { */ enum class VKNodeType { UNUSED, + BEGIN_QUERY, BEGIN_RENDERING, BLIT_IMAGE, CLEAR_ATTACHMENTS, @@ -36,8 +37,10 @@ enum class VKNodeType { DRAW_INDEXED, DRAW_INDEXED_INDIRECT, DRAW_INDIRECT, + END_QUERY, END_RENDERING, FILL_BUFFER, + RESET_QUERY_POOL, SYNCHRONIZATION, UPDATE_MIPMAPS, }; @@ -48,9 +51,15 @@ BLI_INLINE std::ostream &operator<<(std::ostream &os, const VKNodeType node_type case VKNodeType::UNUSED: os << "UNUSED"; break; + case VKNodeType::BEGIN_QUERY: + os << "BEGIN_QUERY"; + break; case VKNodeType::BEGIN_RENDERING: os << "BEGIN_RENDERING"; break; + case VKNodeType::END_QUERY: + os << "END_QUERY"; + break; case VKNodeType::END_RENDERING: os << "END_RENDERING"; break; @@ -99,6 +108,9 @@ BLI_INLINE std::ostream &operator<<(std::ostream &os, const VKNodeType node_type case VKNodeType::DRAW_INDIRECT: os << "DRAW_INDIRECT"; break; + case VKNodeType::RESET_QUERY_POOL: + os << "RESET_QUERY_POOL"; + break; case VKNodeType::SYNCHRONIZATION: os << "SYNCHRONIZATION"; break; diff --git a/source/blender/gpu/vulkan/render_graph/nodes/vk_reset_query_pool_node.hh b/source/blender/gpu/vulkan/render_graph/nodes/vk_reset_query_pool_node.hh new file mode 100644 index 00000000000..0c0d47ca703 --- /dev/null +++ b/source/blender/gpu/vulkan/render_graph/nodes/vk_reset_query_pool_node.hh @@ -0,0 +1,68 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "vk_node_info.hh" + +namespace blender::gpu::render_graph { + +/** + * Information stored inside the render graph node. See `VKRenderGraphNode`. + */ +struct VKResetQueryPoolData { + VkQueryPool vk_query_pool; + uint32_t first_query; + uint32_t query_count; +}; + +/** + * Reset query pool. + * + * - Contains logic to copy relevant data to the VKRenderGraphNode. + * - Determine read/write resource dependencies. + * - Add commands to a command builder. + */ +class VKResetQueryPoolNode : public VKNodeInfo { + public: + /** + * Update the node data with the data inside create_info. + * + * Has been implemented as a template to ensure all node specific data + * (`VK*Data`/`VK*CreateInfo`) types can be included in the same header file as the logic. The + * actual node data (`VKRenderGraphNode` includes all header files.) + */ + template void set_node_data(Node &node, const CreateInfo &create_info) + { + node.reset_query_pool = create_info; + } + + /** + * Extract read/write resource dependencies from `create_info` and add them to `node_links`. + */ + void build_links(VKResourceStateTracker & /*resources*/, + VKRenderGraphNodeLinks & /*node_links*/, + const CreateInfo & /*create_info*/) override + { + } + + /** + * Build the commands and add them to the command_buffer. + */ + void build_commands(VKCommandBufferInterface &command_buffer, + Data &data, + VKBoundPipelines & /*r_bound_pipelines*/) override + { + command_buffer.reset_query_pool(data.vk_query_pool, data.first_query, data.query_count); + } +}; +} // namespace blender::gpu::render_graph diff --git a/source/blender/gpu/vulkan/render_graph/tests/vk_render_graph_test_types.hh b/source/blender/gpu/vulkan/render_graph/tests/vk_render_graph_test_types.hh index 556e3d375bf..3b2eb5b0921 100644 --- a/source/blender/gpu/vulkan/render_graph/tests/vk_render_graph_test_types.hh +++ b/source/blender/gpu/vulkan/render_graph/tests/vk_render_graph_test_types.hh @@ -421,6 +421,17 @@ class CommandBufferLog : public VKCommandBufferInterface { log_.append(ss.str()); } + void begin_query(VkQueryPool /*vk_query_pool*/, + uint32_t /*query_index*/, + VkQueryControlFlags /*vk_query_control_flags*/) override + { + } + void end_query(VkQueryPool /*vk_query_pool*/, uint32_t /*query_index*/) override {} + void reset_query_pool(VkQueryPool /*vk_query_pool*/, + uint32_t /*first_query*/, + uint32_t /*query_count*/) override + { + } void begin_debug_utils_label(const VkDebugUtilsLabelEXT * /*vk_debug_utils_label*/) override {} void end_debug_utils_label() override {} }; diff --git a/source/blender/gpu/vulkan/render_graph/vk_command_buffer_wrapper.cc b/source/blender/gpu/vulkan/render_graph/vk_command_buffer_wrapper.cc index 59e46b283a6..2b5372afa0d 100644 --- a/source/blender/gpu/vulkan/render_graph/vk_command_buffer_wrapper.cc +++ b/source/blender/gpu/vulkan/render_graph/vk_command_buffer_wrapper.cc @@ -332,6 +332,25 @@ void VKCommandBufferWrapper::end_rendering() device.functions.vkCmdEndRendering(vk_command_buffer_); } +void VKCommandBufferWrapper::begin_query(VkQueryPool vk_query_pool, + uint32_t query_index, + VkQueryControlFlags vk_query_control_flags) +{ + vkCmdBeginQuery(vk_command_buffer_, vk_query_pool, query_index, vk_query_control_flags); +} + +void VKCommandBufferWrapper::end_query(VkQueryPool vk_query_pool, uint32_t query_index) +{ + vkCmdEndQuery(vk_command_buffer_, vk_query_pool, query_index); +} + +void VKCommandBufferWrapper::reset_query_pool(VkQueryPool vk_query_pool, + uint32_t first_query, + uint32_t query_count) +{ + vkCmdResetQueryPool(vk_command_buffer_, vk_query_pool, first_query, query_count); +} + void VKCommandBufferWrapper::begin_debug_utils_label( const VkDebugUtilsLabelEXT *vk_debug_utils_label) { diff --git a/source/blender/gpu/vulkan/render_graph/vk_command_buffer_wrapper.hh b/source/blender/gpu/vulkan/render_graph/vk_command_buffer_wrapper.hh index d23d652f830..712fe99d65c 100644 --- a/source/blender/gpu/vulkan/render_graph/vk_command_buffer_wrapper.hh +++ b/source/blender/gpu/vulkan/render_graph/vk_command_buffer_wrapper.hh @@ -114,6 +114,14 @@ class VKCommandBufferInterface { uint32_t offset, uint32_t size, const void *p_values) = 0; + virtual void begin_query(VkQueryPool vk_query_pool, + uint32_t query_index, + VkQueryControlFlags vk_query_control_flags) = 0; + virtual void end_query(VkQueryPool vk_query_pool, uint32_t query_index) = 0; + virtual void reset_query_pool(VkQueryPool vk_query_pool, + uint32_t first_query, + uint32_t query_count) = 0; + /* VK_KHR_dynamic_rendering */ virtual void begin_rendering(const VkRenderingInfo *p_rendering_info) = 0; virtual void end_rendering() = 0; @@ -234,6 +242,11 @@ class VKCommandBufferWrapper : public VKCommandBufferInterface { uint32_t offset, uint32_t size, const void *p_values) override; + void begin_query(VkQueryPool vk_query_pool, + uint32_t query_index, + VkQueryControlFlags vk_query_control_flags) override; + void end_query(VkQueryPool vk_query_pool, uint32_t query_index) override; + void reset_query_pool(VkQueryPool, uint32_t first_query, uint32_t query_count) override; void begin_rendering(const VkRenderingInfo *p_rendering_info) override; void end_rendering() override; void begin_debug_utils_label(const VkDebugUtilsLabelEXT *vk_debug_utils_label) override; diff --git a/source/blender/gpu/vulkan/render_graph/vk_render_graph.hh b/source/blender/gpu/vulkan/render_graph/vk_render_graph.hh index cbb23e09654..d2b29cc06b0 100644 --- a/source/blender/gpu/vulkan/render_graph/vk_render_graph.hh +++ b/source/blender/gpu/vulkan/render_graph/vk_render_graph.hh @@ -177,7 +177,9 @@ class VKRenderGraph : public NonCopyable { { \ add_node(create_info); \ } + ADD_NODE(VKBeginQueryNode) ADD_NODE(VKBeginRenderingNode) + ADD_NODE(VKEndQueryNode) ADD_NODE(VKEndRenderingNode) ADD_NODE(VKClearAttachmentsNode) ADD_NODE(VKClearColorImageNode) @@ -194,6 +196,7 @@ class VKRenderGraph : public NonCopyable { ADD_NODE(VKDrawIndexedNode) ADD_NODE(VKDrawIndexedIndirectNode) ADD_NODE(VKDrawIndirectNode) + ADD_NODE(VKResetQueryPoolNode) ADD_NODE(VKUpdateMipmapsNode) #undef ADD_NODE diff --git a/source/blender/gpu/vulkan/render_graph/vk_render_graph_node.hh b/source/blender/gpu/vulkan/render_graph/vk_render_graph_node.hh index 526833e7ddb..9d7eed35049 100644 --- a/source/blender/gpu/vulkan/render_graph/vk_render_graph_node.hh +++ b/source/blender/gpu/vulkan/render_graph/vk_render_graph_node.hh @@ -8,6 +8,7 @@ #pragma once +#include "nodes/vk_begin_query_node.hh" #include "nodes/vk_begin_rendering_node.hh" #include "nodes/vk_blit_image_node.hh" #include "nodes/vk_clear_attachments_node.hh" @@ -23,8 +24,10 @@ #include "nodes/vk_draw_indexed_node.hh" #include "nodes/vk_draw_indirect_node.hh" #include "nodes/vk_draw_node.hh" +#include "nodes/vk_end_query_node.hh" #include "nodes/vk_end_rendering_node.hh" #include "nodes/vk_fill_buffer_node.hh" +#include "nodes/vk_reset_query_pool_node.hh" #include "nodes/vk_synchronization_node.hh" #include "nodes/vk_update_mipmaps_node.hh" @@ -45,6 +48,7 @@ using NodeHandle = uint64_t; struct VKRenderGraphNode { VKNodeType type; union { + VKBeginQueryNode::Data begin_query; VKBeginRenderingNode::Data begin_rendering; VKBlitImageNode::Data blit_image; VKClearAttachmentsNode::Data clear_attachments; @@ -60,8 +64,10 @@ struct VKRenderGraphNode { VKDrawIndexedNode::Data draw_indexed; VKDrawIndexedIndirectNode::Data draw_indexed_indirect; VKDrawIndirectNode::Data draw_indirect; + VKEndQueryNode::Data end_query; VKEndRenderingNode::Data end_rendering; VKFillBufferNode::Data fill_buffer; + VKResetQueryPoolNode::Data reset_query_pool; VKSynchronizationNode::Data synchronization; VKUpdateMipmapsNode::Data update_mipmaps; }; @@ -110,6 +116,8 @@ struct VKRenderGraphNode { switch (type) { case VKNodeType::UNUSED: return VK_PIPELINE_STAGE_NONE; + case VKNodeType::BEGIN_QUERY: + return VKBeginQueryNode::pipeline_stage; case VKNodeType::BEGIN_RENDERING: return VKBeginRenderingNode::pipeline_stage; case VKNodeType::CLEAR_ATTACHMENTS: @@ -118,6 +126,8 @@ struct VKRenderGraphNode { return VKClearColorImageNode::pipeline_stage; case VKNodeType::CLEAR_DEPTH_STENCIL_IMAGE: return VKClearDepthStencilImageNode::pipeline_stage; + case VKNodeType::END_QUERY: + return VKEndQueryNode::pipeline_stage; case VKNodeType::END_RENDERING: return VKEndRenderingNode::pipeline_stage; case VKNodeType::FILL_BUFFER: @@ -144,6 +154,8 @@ struct VKRenderGraphNode { return VKDrawIndexedIndirectNode::pipeline_stage; case VKNodeType::DRAW_INDIRECT: return VKDrawIndirectNode::pipeline_stage; + case VKNodeType::RESET_QUERY_POOL: + return VKResetQueryPoolNode::pipeline_stage; case VKNodeType::SYNCHRONIZATION: return VKSynchronizationNode::pipeline_stage; case VKNodeType::UPDATE_MIPMAPS: @@ -173,12 +185,14 @@ struct VKRenderGraphNode { break; \ } + BUILD_COMMANDS(VKNodeType::BEGIN_QUERY, VKBeginQueryNode, begin_query) BUILD_COMMANDS(VKNodeType::BEGIN_RENDERING, VKBeginRenderingNode, begin_rendering) BUILD_COMMANDS(VKNodeType::CLEAR_ATTACHMENTS, VKClearAttachmentsNode, clear_attachments) BUILD_COMMANDS(VKNodeType::CLEAR_COLOR_IMAGE, VKClearColorImageNode, clear_color_image) BUILD_COMMANDS(VKNodeType::CLEAR_DEPTH_STENCIL_IMAGE, VKClearDepthStencilImageNode, clear_depth_stencil_image) + BUILD_COMMANDS(VKNodeType::END_QUERY, VKEndQueryNode, end_query) BUILD_COMMANDS(VKNodeType::END_RENDERING, VKEndRenderingNode, end_rendering) BUILD_COMMANDS(VKNodeType::FILL_BUFFER, VKFillBufferNode, fill_buffer) BUILD_COMMANDS(VKNodeType::COPY_BUFFER, VKCopyBufferNode, copy_buffer) @@ -188,6 +202,7 @@ struct VKRenderGraphNode { BUILD_COMMANDS( VKNodeType::COPY_IMAGE_TO_BUFFER, VKCopyImageToBufferNode, copy_image_to_buffer) BUILD_COMMANDS(VKNodeType::BLIT_IMAGE, VKBlitImageNode, blit_image) + BUILD_COMMANDS(VKNodeType::RESET_QUERY_POOL, VKResetQueryPoolNode, reset_query_pool) BUILD_COMMANDS(VKNodeType::SYNCHRONIZATION, VKSynchronizationNode, synchronization) BUILD_COMMANDS(VKNodeType::UPDATE_MIPMAPS, VKUpdateMipmapsNode, update_mipmaps) BUILD_COMMANDS(VKNodeType::DISPATCH, VKDispatchNode, dispatch) @@ -225,10 +240,12 @@ struct VKRenderGraphNode { #undef FREE_DATA case VKNodeType::UNUSED: + case VKNodeType::BEGIN_QUERY: case VKNodeType::BEGIN_RENDERING: case VKNodeType::CLEAR_ATTACHMENTS: case VKNodeType::CLEAR_COLOR_IMAGE: case VKNodeType::CLEAR_DEPTH_STENCIL_IMAGE: + case VKNodeType::END_QUERY: case VKNodeType::END_RENDERING: case VKNodeType::FILL_BUFFER: case VKNodeType::COPY_BUFFER: @@ -236,6 +253,7 @@ struct VKRenderGraphNode { case VKNodeType::COPY_IMAGE_TO_BUFFER: case VKNodeType::COPY_BUFFER_TO_IMAGE: case VKNodeType::BLIT_IMAGE: + case VKNodeType::RESET_QUERY_POOL: case VKNodeType::SYNCHRONIZATION: case VKNodeType::UPDATE_MIPMAPS: break; diff --git a/source/blender/gpu/vulkan/vk_common.cc b/source/blender/gpu/vulkan/vk_common.cc index ac44726de56..b7655c0355d 100644 --- a/source/blender/gpu/vulkan/vk_common.cc +++ b/source/blender/gpu/vulkan/vk_common.cc @@ -669,6 +669,16 @@ VkFormat to_vk_format(const shader::Type type) return VK_FORMAT_R32G32B32A32_SFLOAT; } +VkQueryType to_vk_query_type(const GPUQueryType query_type) +{ + switch (query_type) { + case GPU_QUERY_OCCLUSION: + return VK_QUERY_TYPE_OCCLUSION; + } + BLI_assert_unreachable(); + return VK_QUERY_TYPE_OCCLUSION; +} + VkImageType to_vk_image_type(const eGPUTextureType type) { /* See diff --git a/source/blender/gpu/vulkan/vk_common.hh b/source/blender/gpu/vulkan/vk_common.hh index 7d6a79186d7..1d5bb8dd911 100644 --- a/source/blender/gpu/vulkan/vk_common.hh +++ b/source/blender/gpu/vulkan/vk_common.hh @@ -19,6 +19,7 @@ #include "vk_mem_alloc.h" #include "GPU_index_buffer.hh" +#include "gpu_query.hh" #include "gpu_shader_create_info.hh" #include "gpu_texture_private.hh" @@ -52,6 +53,7 @@ VkFormat to_vk_format(const GPUVertCompType type, const uint32_t size, const GPUVertFetchMode fetch_mode); VkFormat to_vk_format(const shader::Type type); +VkQueryType to_vk_query_type(const GPUQueryType query_type); VkComponentSwizzle to_vk_component_swizzle(const char swizzle); VkImageViewType to_vk_image_view_type(const eGPUTextureType type, diff --git a/source/blender/gpu/vulkan/vk_query.cc b/source/blender/gpu/vulkan/vk_query.cc index 8331959914a..9eb829dffc8 100644 --- a/source/blender/gpu/vulkan/vk_query.cc +++ b/source/blender/gpu/vulkan/vk_query.cc @@ -7,28 +7,116 @@ */ #include "vk_query.hh" -#include "vk_common.hh" +#include "vk_backend.hh" +#include "vk_context.hh" +#include "vk_memory.hh" + +#include "GPU_debug.hh" namespace blender::gpu { -void VKQueryPool::init(GPUQueryType /*type*/) +VKQueryPool::~VKQueryPool() { - NOT_YET_IMPLEMENTED + VKBackend &backend = VKBackend::get(); + const VKDevice &device = backend.device; + VK_ALLOCATION_CALLBACKS; + + while (!vk_query_pools_.is_empty()) { + VkQueryPool vk_query_pool = vk_query_pools_.pop_last(); + vkDestroyQueryPool(device.vk_handle(), vk_query_pool, vk_allocation_callbacks); + } +} + +uint32_t VKQueryPool::query_index_in_pool() const +{ + return queries_issued_ - (vk_query_pools_.size() - 1) * query_chunk_len_; +} + +void VKQueryPool::init(GPUQueryType type) +{ + BLI_assert(vk_query_pools_.is_empty()); + queries_issued_ = 0; + vk_query_type_ = to_vk_query_type(type); } void VKQueryPool::begin_query() { - NOT_YET_IMPLEMENTED + VKBackend &backend = VKBackend::get(); + const VKDevice &device = backend.device; + + uint32_t pool_index = queries_issued_ / query_chunk_len_; + bool is_new_pool = (queries_issued_ % query_chunk_len_) == 0; + + if (pool_index == vk_query_pools_.size()) { + BLI_assert(is_new_pool); + VK_ALLOCATION_CALLBACKS; + + VkQueryPoolCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; + create_info.queryType = vk_query_type_; + create_info.queryCount = query_chunk_len_; + + VkQueryPool vk_query_pool = VK_NULL_HANDLE; + vkCreateQueryPool(device.vk_handle(), &create_info, vk_allocation_callbacks, &vk_query_pool); + vk_query_pools_.append(vk_query_pool); + } + BLI_assert(pool_index < vk_query_pools_.size()); + + /* When using a new query pool make sure to reset it before first usage. */ + VKContext &context = *VKContext::get(); + VkQueryPool vk_query_pool = vk_query_pools_[pool_index]; + if (is_new_pool) { + render_graph::VKResetQueryPoolNode::Data reset_query_pool = {}; + reset_query_pool.vk_query_pool = vk_query_pool; + reset_query_pool.first_query = 0; + reset_query_pool.query_count = query_chunk_len_; + context.render_graph.add_node(reset_query_pool); + } + + render_graph::VKBeginQueryNode::Data begin_query = {}; + begin_query.vk_query_pool = vk_query_pool; + begin_query.query_index = query_index_in_pool(); + context.render_graph.add_node(begin_query); } void VKQueryPool::end_query() { - NOT_YET_IMPLEMENTED + VKContext &context = *VKContext::get(); + render_graph::VKEndQueryNode::Data end_query = {}; + end_query.vk_query_pool = vk_query_pools_.last(); + end_query.query_index = query_index_in_pool(); + context.render_graph.add_node(end_query); + queries_issued_ += 1; } -void VKQueryPool::get_occlusion_result(MutableSpan /*r_values*/) +void VKQueryPool::get_occlusion_result(MutableSpan r_values) { - NOT_YET_IMPLEMENTED + VKContext &context = *VKContext::get(); + /* During selection the frame buffer is still rendering. It needs to finish the render scope to + * ensure the END_RENDERING node */ + context.rendering_end(); + context.render_graph.submit(); + + int queries_left = queries_issued_; + int pool_index = 0; + VKBackend &backend = VKBackend::get(); + const VKDevice &device = backend.device; + while (queries_left) { + VkQueryPool vk_query_pool = vk_query_pools_[pool_index]; + uint32_t *r_values_chunk = &r_values[pool_index * query_chunk_len_]; + uint32_t values_chunk_size = min_ii(queries_left, query_chunk_len_); + vkGetQueryPoolResults(device.vk_handle(), + vk_query_pool, + 0, + values_chunk_size, + values_chunk_size * sizeof(uint32_t), + r_values_chunk, + sizeof(uint32_t), + VK_QUERY_RESULT_WAIT_BIT); + + queries_left = max_ii(queries_left - query_chunk_len_, 0); + pool_index += 1; + } } } // namespace blender::gpu diff --git a/source/blender/gpu/vulkan/vk_query.hh b/source/blender/gpu/vulkan/vk_query.hh index 8ab849810ed..25bc2a886aa 100644 --- a/source/blender/gpu/vulkan/vk_query.hh +++ b/source/blender/gpu/vulkan/vk_query.hh @@ -8,16 +8,31 @@ #pragma once +#include "BLI_vector.hh" + #include "gpu_query.hh" +#include "vk_common.hh" + namespace blender::gpu { class VKQueryPool : public QueryPool { + const uint32_t query_chunk_len_ = 256; + Vector vk_query_pools_; + VkQueryType vk_query_type_; + uint32_t queries_issued_ = 0; + + protected: + ~VKQueryPool(); + public: void init(GPUQueryType type) override; void begin_query() override; void end_query() override; void get_occlusion_result(MutableSpan r_values) override; + + private: + uint32_t query_index_in_pool() const; }; } // namespace blender::gpu