aboutsummaryrefslogtreecommitdiff
path: root/src/device_context.cc
blob: 4b39210f9efdc9f663ba45e7824d080cfaa14f3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "device_context.hh"
#include "queue_context.hh"

#include <utility>

namespace low_latency {

DeviceContext::DeviceContext(InstanceContext& parent_instance,
                             PhysicalDeviceContext& parent_physical_device,
                             const VkDevice& device,
                             const PFN_vkSetDeviceLoaderData& sdld,
                             VkuDeviceDispatchTable&& vtable)
    : instance(parent_instance), physical_device(parent_physical_device),
      device(device), sdld(sdld), vtable(std::move(vtable)), clock(*this) {}

DeviceContext::~DeviceContext() {
    // We will let the destructor handle clearing here, but they should be
    // unique by now (ie, removed from the layer's context map).
    for (const auto& [queue, queue_context] : this->queues) {
        assert(queue_context.unique());
    }
}

void DeviceContext::notify_acquire(const VkSwapchainKHR& swapchain,
                                   const std::uint32_t& image_index,
                                   const VkSemaphore& signal_semaphore) {

    const auto it = this->swapchain_signals.try_emplace(swapchain).first;

    // Doesn't matter if it was already there, overwrite it.
    it->second.insert_or_assign(image_index, signal_semaphore);
}

DeviceContext::Clock::Clock(const DeviceContext& context) {

    const auto infos = std::vector<VkCalibratedTimestampInfoKHR>{
        {VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT, nullptr,
         VK_TIME_DOMAIN_DEVICE_EXT},
        {VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT, nullptr,
         VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT}};

    auto device_host = std::array<std::uint64_t, 2>{};

    const auto steady_before = std::chrono::steady_clock::now();
    context.vtable.GetCalibratedTimestampsKHR(
        context.device, 2, std::data(infos), std::data(device_host),
        &this->error_bound);
    const auto steady_after = std::chrono::steady_clock::now();

    this->cpu_time = steady_before + (steady_after - steady_before) / 2;
    this->device_ticks = device_host[0];
    this->host_ns = device_host[1];

    // Might need to get physical limits again?
    this->ticks_per_ns =
        context.physical_device.properties->limits.timestampPeriod;
}

DeviceContext::Clock::time_point_t
DeviceContext::Clock::ticks_to_time(const std::uint64_t& ticks) const {
    /*
    struct timespec tv;
    clock_gettime(CLOCK_MONOTONIC, &tv);
    return tv.tv_nsec + tv.tv_sec*1000000000ull;
    */

    auto a = this->device_ticks;
    auto b = ticks;

    const auto was_before = a > b;
    if (was_before) { // it's happened before
        std::swap(a, b);
    }
    const auto nsec = std::chrono::nanoseconds((b - a) * this->ticks_per_ns);
    return this->cpu_time + (was_before ? -nsec : nsec);
}

void DeviceContext::calibrate_timestamps() { this->clock = Clock{*this}; }

} // namespace low_latency