query_pool.cpp

cross platform rendering playground

src/backend/vulkan/query_pool.cpp

3.67 KB
#include <volk.h>

#include "backend/vulkan/debug.h"
#include "backend/vulkan/utils.h"
#include "backend/vulkan/vk_api.h"
#include "backend/vulkan/vk_conversion.h"

namespace rhi {
using namespace vk;

bool create_query_pool(Device &device, const QueryPoolDesc &desc, QueryPool &pool) {
    if (desc.queryType == QueryType::TIMESTAMP || desc.queryType == QueryType::TIMESTAMP_COPY_QUEUE) {
        pool._type = VK_QUERY_TYPE_TIMESTAMP;
    } else if (desc.queryType == QueryType::OCCLUSION) {
        pool._type = VK_QUERY_TYPE_OCCLUSION;
    } else if (desc.queryType == QueryType::PIPELINE_STATISTICS) {
        pool._type = VK_QUERY_TYPE_PIPELINE_STATISTICS;
    } else if (desc.queryType == QueryType::ACCELERATION_STRUCTURE_SIZE) {
        pool._type = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR;
    } else if (desc.queryType == QueryType::ACCELERATION_STRUCTURE_COMPACTED_SIZE) {
        pool._type = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR;
    } else if (desc.queryType == QueryType::MICROMAP_COMPACTED_SIZE) {
        pool._type = VK_QUERY_TYPE_MICROMAP_COMPACTED_SIZE_EXT;
    } else {
        return false;
    }

    VkQueryPipelineStatisticFlags pipeline_statistics =
        VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT |
        VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT |
        VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT |
        VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT |
        VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT |
        VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT | VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT |
        VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT |
        VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT |
        VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT |
        VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT;

    // if (m_Device.GetDesc().features.meshShader)
    //     pipelineStatistics |= VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT |
    //     VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT;

    VkQueryPoolCreateInfo pool_info = {
        VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
        nullptr,
        (VkQueryPoolCreateFlags)0,
        (VkQueryType)pool._type,
        desc.capacity,
        pipeline_statistics
    };

    VkQueryPool vk_pool;
    VK_CHECK(vkCreateQueryPool(device.logical, &pool_info, nullptr, &vk_pool));
    pool._handle = vk_pool;
    pool.desc = desc;
    if (!desc.name.empty()) {
        VK_NAME_EX(device, vk_pool, desc.name.c_str());
    }
    return true;
}

void reset_query_pool(CmdBuffer &cmd, QueryPool &queryPool, u32 offset, u32 count) {
    vkCmdResetQueryPool(cmd.handle, queryPool._handle, offset, count);
}

void write_timestamp(CmdBuffer &cmd, QueryPool &queryPool, u32 queryIndex, rhi::PipelineStages stage) {
    vkCmdWriteTimestamp(cmd.handle, static_cast<VkPipelineStageFlagBits>(stage), queryPool._handle, queryIndex);
}

void destroy_query_pool(Device &device, QueryPool &queryPool) {
    vkDestroyQueryPool(device.logical, queryPool._handle, nullptr);
}

bool query_pool_results(
    Device &device,
    const QueryPool &pool,
    u32 first_query,
    u32 query_count,
    u64 *out,
    usize data_size_bytes,
    usize stride_bytes,
    bool with_availability
) {
    VkQueryResultFlags flags = VK_QUERY_RESULT_64_BIT;
    if (with_availability) {
        flags |= VK_QUERY_RESULT_WITH_AVAILABILITY_BIT;
    }
    VkResult res = vkGetQueryPoolResults(
        device.logical, pool._handle, first_query, query_count, data_size_bytes, out, stride_bytes, flags
    );
    return res == VK_SUCCESS;
}

} // namespace rhi