aboutsummaryrefslogtreecommitdiff
path: root/src/layer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/layer.cc')
-rw-r--r--src/layer.cc320
1 files changed, 142 insertions, 178 deletions
diff --git a/src/layer.cc b/src/layer.cc
index 94b4969..5e652f0 100644
--- a/src/layer.cc
+++ b/src/layer.cc
@@ -1,6 +1,10 @@
#include "layer.hh"
+#include <iostream>
+#include <string_view>
+#include <unordered_map>
#include <utility>
+
#include <vulkan/utility/vk_dispatch_table.h>
#include <vulkan/vk_layer.h>
#include <vulkan/vk_platform.h>
@@ -8,37 +12,18 @@
#include <vulkan/vulkan.hpp>
#include <vulkan/vulkan_core.h>
-#include <deque>
-#include <iostream>
-#include <mutex>
-#include <string_view>
-#include <unordered_map>
-#include <unordered_set>
-
+#include "device_context.hh"
+#include "instance_context.hh"
+#include "layer_context.hh"
#include "queue_context.hh"
-#include "timestamp_pool.hh"
namespace low_latency {
-// Global mutex for layer data.
-static auto mutex = std::mutex{};
-
-// Mappings for device instances.
-static std::unordered_map<VkPhysicalDevice, VkInstance> device_instances;
-static std::unordered_map<void*, VkuInstanceDispatchTable> instance_vtables;
-static std::unordered_map<void*, VkuDeviceDispatchTable> device_vtables;
+namespace {
-static std::uint64_t current_frame = 0;
-static std::unordered_map<VkQueue, QueueContext> queue_contexts;
+LayerContext layer_context;
-template <typename T>
-concept DispatchableType =
- std::same_as<std::remove_cvref_t<T>, VkInstance> ||
- std::same_as<std::remove_cvref_t<T>, VkDevice> ||
- std::same_as<std::remove_cvref_t<T>, VkPhysicalDevice>;
-template <DispatchableType T> void* get_key(const T& inst) {
- return *reinterpret_cast<void**>(inst);
-}
+} // namespace
template <typename T, typename sType>
static T* get_link_info(const void* const head, const sType& stype) {
@@ -92,23 +77,24 @@ CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
return result;
}
- const auto lock = std::scoped_lock{mutex};
- instance_vtables.emplace(
- get_key(*pInstance),
- VkuInstanceDispatchTable{
- .DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
- gipa(*pInstance, "vkDestroyInstance")),
- .EnumeratePhysicalDevices =
- reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(
- gipa(*pInstance, "vkEnumeratePhysicalDevices")),
- .GetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
- gipa(*pInstance, "vkGetInstanceProcAddr")),
- .EnumerateDeviceExtensionProperties =
- reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
- gipa(*pInstance, "vkEnumerateDeviceExtensionProperties")),
- }
+ const auto key = layer_context.get_key(*pInstance);
+ auto vtable = VkuInstanceDispatchTable{
+ .DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
+ gipa(*pInstance, "vkDestroyInstance")),
+ .EnumeratePhysicalDevices =
+ reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(
+ gipa(*pInstance, "vkEnumeratePhysicalDevices")),
+ .GetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
+ gipa(*pInstance, "vkGetInstanceProcAddr")),
+ .EnumerateDeviceExtensionProperties =
+ reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
+ gipa(*pInstance, "vkEnumerateDeviceExtensionProperties")),
+ };
- );
+ const auto lock = std::scoped_lock{layer_context.mutex};
+ assert(!layer_context.contexts.contains(key));
+ layer_context.contexts.try_emplace(
+ key, std::make_unique<InstanceContext>(*pInstance, std::move(vtable)));
return VK_SUCCESS;
}
@@ -116,34 +102,11 @@ CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
static VKAPI_ATTR void VKAPI_CALL
DestroyInstance(VkInstance instance, const VkAllocationCallbacks* allocator) {
- const auto lock = std::scoped_lock{mutex};
+ const auto lock = std::scoped_lock{layer_context.mutex};
- const auto key = get_key(instance);
- assert(instance_vtables.contains(key));
- instance_vtables.erase(key);
-}
-
-static VKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDevices(
- VkInstance instance, std::uint32_t* count, VkPhysicalDevice* devices) {
-
- const auto lock = std::scoped_lock{mutex};
-
- const auto it = instance_vtables.find(get_key(instance));
- assert(it != std::end(instance_vtables));
- const auto& vtable = it->second;
-
- if (const auto result =
- vtable.EnumeratePhysicalDevices(instance, count, devices);
- !devices || result != VK_SUCCESS) {
-
- return result;
- }
-
- for (auto i = std::uint32_t{0}; i < *count; ++i) {
- device_instances.emplace(devices[i], instance);
- }
-
- return VK_SUCCESS;
+ const auto key = layer_context.get_key(instance);
+ assert(layer_context.contexts.contains(key));
+ layer_context.contexts.erase(key);
}
static VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(
@@ -163,16 +126,17 @@ static VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(
}
create_info->u.pLayerInfo = create_info->u.pLayerInfo->pNext;
- const auto lock = std::scoped_lock{mutex};
+ const auto lock = std::scoped_lock{layer_context.mutex};
+
+ auto& context = layer_context.get_context<InstanceContext>(physical_device);
const auto next_extensions =
[&]() -> std::optional<std::vector<const char*>> {
const auto supported_extensions =
[&]() -> std::optional<std::vector<VkExtensionProperties>> {
const auto enumerate_device_extensions =
- reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
- gipa(device_instances[physical_device],
- "vkEnumerateDeviceExtensionProperties"));
+ reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(gipa(
+ context.instance, "vkEnumerateDeviceExtensionProperties"));
if (!enumerate_device_extensions) {
return std::nullopt;
}
@@ -257,67 +221,75 @@ static VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(
return result;
}
- device_vtables.emplace(
- get_key(*pDevice),
- VkuDeviceDispatchTable{
- .GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
- gdpa(*pDevice, "vkGetDeviceProcAddr")),
- .DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
- gdpa(*pDevice, "vkDestroyDevice")),
- .GetDeviceQueue = reinterpret_cast<PFN_vkGetDeviceQueue>(
- gdpa(*pDevice, "vkGetDeviceQueue")),
- .QueueSubmit = reinterpret_cast<PFN_vkQueueSubmit>(
- gdpa(*pDevice, "vkQueueSubmit")),
- .CreateSemaphore = reinterpret_cast<PFN_vkCreateSemaphore>(
- gdpa(*pDevice, "vkCreateSemaphore")),
- .CreateQueryPool = reinterpret_cast<PFN_vkCreateQueryPool>(
- gdpa(*pDevice, "vkCreateQueryPool")),
- .GetQueryPoolResults = reinterpret_cast<PFN_vkGetQueryPoolResults>(
- gdpa(*pDevice, "vkGetQueryPoolResults")),
- .CreateCommandPool = reinterpret_cast<PFN_vkCreateCommandPool>(
- gdpa(*pDevice, "vkCreateCommandPool")),
- .AllocateCommandBuffers =
- reinterpret_cast<PFN_vkAllocateCommandBuffers>(
- gdpa(*pDevice, "vkAllocateCommandBuffers")),
- .BeginCommandBuffer = reinterpret_cast<PFN_vkBeginCommandBuffer>(
- gdpa(*pDevice, "vkBeginCommandBuffer")),
- .EndCommandBuffer = reinterpret_cast<PFN_vkEndCommandBuffer>(
- gdpa(*pDevice, "vkEndCommandBuffer")),
- .ResetCommandBuffer = reinterpret_cast<PFN_vkResetCommandBuffer>(
- gdpa(*pDevice, "vkResetCommandBuffer")),
- .CmdDraw =
- reinterpret_cast<PFN_vkCmdDraw>(gdpa(*pDevice, "vkCmdDraw")),
- .CmdDrawIndexed = reinterpret_cast<PFN_vkCmdDrawIndexed>(
- gdpa(*pDevice, "vkCmdDrawIndexed")),
- .CmdResetQueryPool = reinterpret_cast<PFN_vkCmdResetQueryPool>(
- gdpa(*pDevice, "vkCmdResetQueryPool")),
- .GetDeviceQueue2 = reinterpret_cast<PFN_vkGetDeviceQueue2>(
- gdpa(*pDevice, "vkGetDeviceQueue2")),
- .QueueSubmit2 = reinterpret_cast<PFN_vkQueueSubmit2>(
- gdpa(*pDevice, "vkQueueSubmit2")),
- .QueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(
- gdpa(*pDevice, "vkQueuePresentKHR")),
- .GetSemaphoreCounterValueKHR =
- reinterpret_cast<PFN_vkGetSemaphoreCounterValueKHR>(
- gdpa(*pDevice, "vkGetSemaphoreCounterValueKHR")),
- .CmdWriteTimestamp2KHR =
- reinterpret_cast<PFN_vkCmdWriteTimestamp2KHR>(
- gdpa(*pDevice, "vkCmdWriteTimestamp2KHR")),
- .QueueSubmit2KHR = reinterpret_cast<PFN_vkQueueSubmit2KHR>(
- gdpa(*pDevice, "vkQueueSubmit2KHR")),
-
- });
+ auto vtable = VkuDeviceDispatchTable{
+ .GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
+ gdpa(*pDevice, "vkGetDeviceProcAddr")),
+ .DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
+ gdpa(*pDevice, "vkDestroyDevice")),
+ .GetDeviceQueue = reinterpret_cast<PFN_vkGetDeviceQueue>(
+ gdpa(*pDevice, "vkGetDeviceQueue")),
+ .QueueSubmit = reinterpret_cast<PFN_vkQueueSubmit>(
+ gdpa(*pDevice, "vkQueueSubmit")),
+ .CreateSemaphore = reinterpret_cast<PFN_vkCreateSemaphore>(
+ gdpa(*pDevice, "vkCreateSemaphore")),
+ .DestroySemaphore = reinterpret_cast<PFN_vkDestroySemaphore>(
+ gdpa(*pDevice, "vkDestroySemaphore")),
+ .CreateQueryPool = reinterpret_cast<PFN_vkCreateQueryPool>(
+ gdpa(*pDevice, "vkCreateQueryPool")),
+ .DestroyQueryPool = reinterpret_cast<PFN_vkDestroyQueryPool>(
+ gdpa(*pDevice, "vkDestroyQueryPool")),
+ .GetQueryPoolResults = reinterpret_cast<PFN_vkGetQueryPoolResults>(
+ gdpa(*pDevice, "vkGetQueryPoolResults")),
+ .CreateCommandPool = reinterpret_cast<PFN_vkCreateCommandPool>(
+ gdpa(*pDevice, "vkCreateCommandPool")),
+ .DestroyCommandPool = reinterpret_cast<PFN_vkDestroyCommandPool>(
+ gdpa(*pDevice, "vkDestroyCommandPool")),
+ .AllocateCommandBuffers =
+ reinterpret_cast<PFN_vkAllocateCommandBuffers>(
+ gdpa(*pDevice, "vkAllocateCommandBuffers")),
+ .FreeCommandBuffers = reinterpret_cast<PFN_vkFreeCommandBuffers>(
+ gdpa(*pDevice, "vkFreeCommandBuffers")),
+ .BeginCommandBuffer = reinterpret_cast<PFN_vkBeginCommandBuffer>(
+ gdpa(*pDevice, "vkBeginCommandBuffer")),
+ .EndCommandBuffer = reinterpret_cast<PFN_vkEndCommandBuffer>(
+ gdpa(*pDevice, "vkEndCommandBuffer")),
+ .ResetCommandBuffer = reinterpret_cast<PFN_vkResetCommandBuffer>(
+ gdpa(*pDevice, "vkResetCommandBuffer")),
+ .CmdDraw = reinterpret_cast<PFN_vkCmdDraw>(gdpa(*pDevice, "vkCmdDraw")),
+ .CmdDrawIndexed = reinterpret_cast<PFN_vkCmdDrawIndexed>(
+ gdpa(*pDevice, "vkCmdDrawIndexed")),
+ .CmdResetQueryPool = reinterpret_cast<PFN_vkCmdResetQueryPool>(
+ gdpa(*pDevice, "vkCmdResetQueryPool")),
+ .GetDeviceQueue2 = reinterpret_cast<PFN_vkGetDeviceQueue2>(
+ gdpa(*pDevice, "vkGetDeviceQueue2")),
+ .QueueSubmit2 = reinterpret_cast<PFN_vkQueueSubmit2>(
+ gdpa(*pDevice, "vkQueueSubmit2")),
+ .QueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(
+ gdpa(*pDevice, "vkQueuePresentKHR")),
+ .GetSemaphoreCounterValueKHR =
+ reinterpret_cast<PFN_vkGetSemaphoreCounterValueKHR>(
+ gdpa(*pDevice, "vkGetSemaphoreCounterValueKHR")),
+ .CmdWriteTimestamp2KHR = reinterpret_cast<PFN_vkCmdWriteTimestamp2KHR>(
+ gdpa(*pDevice, "vkCmdWriteTimestamp2KHR")),
+ .QueueSubmit2KHR = reinterpret_cast<PFN_vkQueueSubmit2KHR>(
+ gdpa(*pDevice, "vkQueueSubmit2KHR")),
+ };
+
+ const auto key = layer_context.get_key(*pDevice);
+ assert(!layer_context.contexts.contains(key));
+ layer_context.contexts.try_emplace(
+ key,
+ std::make_unique<DeviceContext>(context, *pDevice, std::move(vtable)));
return VK_SUCCESS;
}
static VKAPI_ATTR void VKAPI_CALL
DestroyDevice(VkDevice device, const VkAllocationCallbacks* allocator) {
-
- const auto lock = std::scoped_lock{mutex};
- const auto key = get_key(device);
- assert(device_vtables.contains(key));
- device_vtables.erase(key);
+ const auto lock = std::scoped_lock{layer_context.mutex};
+ const auto key = layer_context.get_key(device);
+ assert(layer_context.contexts.contains(key));
+ layer_context.contexts.erase(key);
}
// Small amount of duplication, we can't assume gdq2 is available apparently.
@@ -325,37 +297,40 @@ static VKAPI_ATTR void VKAPI_CALL
GetDeviceQueue(VkDevice device, std::uint32_t queue_family_index,
std::uint32_t queue_index, VkQueue* queue) {
- const auto lock = std::scoped_lock{mutex};
- const auto& vtable = device_vtables[get_key(device)];
+ const auto lock = std::scoped_lock{layer_context.mutex};
+
+ auto& device_context = layer_context.get_context<DeviceContext>(device);
- vtable.GetDeviceQueue(device, queue_family_index, queue_index, queue);
+ device_context.vtable.GetDeviceQueue(device, queue_family_index,
+ queue_index, queue);
if (!queue || !*queue) {
return;
}
+ auto& queue_contexts = device_context.queue_contexts;
if (!queue_contexts.contains(*queue)) {
- queue_contexts.emplace(
- std::piecewise_construct, std::forward_as_tuple(*queue),
- std::forward_as_tuple(device, *queue, queue_family_index, vtable));
+ queue_contexts.try_emplace(
+ *queue, std::make_unique<QueueContext>(device_context, *queue,
+ queue_family_index));
}
}
static VKAPI_ATTR void VKAPI_CALL GetDeviceQueue2(
VkDevice device, const VkDeviceQueueInfo2* info, VkQueue* queue) {
- const auto lock = std::scoped_lock{mutex};
- const auto& vtable = device_vtables[get_key(device)];
+ const auto lock = std::scoped_lock{layer_context.mutex};
+ auto& device_context = layer_context.get_context<DeviceContext>(device);
- vtable.GetDeviceQueue2(device, info, queue);
+ device_context.vtable.GetDeviceQueue2(device, info, queue);
if (!queue || !*queue) {
return;
}
+ auto& queue_contexts = device_context.queue_contexts;
if (!queue_contexts.contains(*queue)) {
- queue_contexts.emplace(
- std::piecewise_construct, std::forward_as_tuple(*queue),
- std::forward_as_tuple(device, *queue, info->queueFamilyIndex,
- vtable));
+ queue_contexts.try_emplace(
+ *queue, std::make_unique<QueueContext>(device_context, *queue,
+ info->queueFamilyIndex));
}
}
@@ -363,14 +338,10 @@ static VKAPI_ATTR VkResult VKAPI_CALL
vkQueueSubmit(VkQueue queue, std::uint32_t submit_count,
const VkSubmitInfo* submit_info, VkFence fence) {
- const auto lock = std::scoped_lock{mutex};
+ const auto lock = std::scoped_lock{layer_context.mutex};
- auto& queue_context = [&]() -> auto& {
- const auto& queue_context_it = queue_contexts.find(queue);
- assert(queue_context_it != std::end(queue_contexts));
- return queue_context_it->second;
- }();
- const auto& vtable = device_vtables[get_key(queue_context.device)];
+ auto& queue_context = layer_context.get_context<QueueContext>(queue);
+ const auto& vtable = queue_context.device_context.vtable;
if (!submit_count) { // no-op submit we shouldn't worry about
return vtable.QueueSubmit(queue, submit_count, submit_info, fence);
@@ -380,7 +351,7 @@ vkQueueSubmit(VkQueue queue, std::uint32_t submit_count,
auto next_submit_infos = std::vector<VkSubmitInfo>{};
next_submit_infos.reserve(submit_count + 2);
- auto timestamp_handle = queue_context.timestamp_pool.acquire();
+ auto timestamp_handle = queue_context.timestamp_pool->acquire();
timestamp_handle->setup_command_buffers(vtable);
const auto& [head_cb, tail_cb] = timestamp_handle->command_buffers;
@@ -403,7 +374,7 @@ vkQueueSubmit(VkQueue queue, std::uint32_t submit_count,
next_submit_infos[1].pWaitSemaphores = nullptr;
next_submit_infos[1].waitSemaphoreCount = 0u;
- const auto TODO_next = std::uint64_t{current_frame + 1};
+ const auto TODO_next = std::uint64_t{layer_context.current_frame + 1};
const auto tail_tssi = VkTimelineSemaphoreSubmitInfo{
.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR,
.signalSemaphoreValueCount = 1,
@@ -434,13 +405,9 @@ static VKAPI_ATTR VkResult VKAPI_CALL
vkQueueSubmit2(VkQueue queue, std::uint32_t submit_count,
const VkSubmitInfo2* submit_infos, VkFence fence) {
- const auto lock = std::scoped_lock{mutex};
- auto& queue_context = [&]() -> auto& {
- const auto& queue_context_it = queue_contexts.find(queue);
- assert(queue_context_it != std::end(queue_contexts));
- return queue_context_it->second;
- }();
- const auto& vtable = device_vtables[get_key(queue_context.device)];
+ const auto lock = std::scoped_lock{layer_context.mutex};
+ auto& queue_context = layer_context.get_context<QueueContext>(queue);
+ const auto& vtable = queue_context.device_context.vtable;
if (!submit_count) { // another no-op submit
return vtable.QueueSubmit2(queue, submit_count, submit_infos, fence);
@@ -449,7 +416,7 @@ vkQueueSubmit2(VkQueue queue, std::uint32_t submit_count,
auto next_submit_infos = std::vector<VkSubmitInfo2>();
next_submit_infos.reserve(submit_count + 2);
- auto timestamp_handle = queue_context.timestamp_pool.acquire();
+ auto timestamp_handle = queue_context.timestamp_pool->acquire();
timestamp_handle->setup_command_buffers(vtable);
const auto& [head_cb, tail_cb] = timestamp_handle->command_buffers;
@@ -500,13 +467,9 @@ vkQueueSubmit2KHR(VkQueue queue, std::uint32_t submit_count,
static VKAPI_ATTR VkResult VKAPI_CALL
vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
- const auto lock = std::scoped_lock{mutex};
- auto& queue_context = [&]() -> auto& {
- const auto& queue_context_it = queue_contexts.find(queue);
- assert(queue_context_it != std::end(queue_contexts));
- return queue_context_it->second;
- }();
- const auto& vtable = device_vtables[get_key(queue_context.device)];
+ const auto lock = std::scoped_lock{layer_context.mutex};
+ auto& queue_context = layer_context.get_context<QueueContext>(queue);
+ const auto& vtable = queue_context.device_context.vtable;
if (const auto res = vtable.QueuePresentKHR(queue, present_info);
res != VK_SUCCESS) {
@@ -517,23 +480,24 @@ vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
std::cout << "queuePresentKHR called for queue " << queue << '\n';
// Update all of our information about this queue's timestamp pool!
- queue_context.timestamp_pool.poll();
+ queue_context.timestamp_pool->poll();
// While we might be submitting on this queue, let's see what our timeline
// semaphore says we're at.
uint64_t value = 0;
if (const auto res = vtable.GetSemaphoreCounterValueKHR(
- queue_context.device, queue_context.semaphore, &value);
+ queue_context.device_context.device, queue_context.semaphore,
+ &value);
res != VK_SUCCESS) {
return res;
}
- std::cout << " frame_index: " << current_frame << '\n';
+ std::cout << " frame_index: " << layer_context.current_frame << '\n';
std::cout << " semaphore: " << value << '\n';
std::cout << " queue: " << queue << '\n';
- ++current_frame;
+ ++layer_context.current_frame;
return VK_SUCCESS;
}
@@ -548,10 +512,6 @@ static const auto instance_functions =
reinterpret_cast<PFN_vkVoidFunction>(low_latency::CreateInstance)},
{"vkDestroyInstance",
reinterpret_cast<PFN_vkVoidFunction>(low_latency::DestroyInstance)},
-
- {"vkEnumeratePhysicalDevices",
- reinterpret_cast<PFN_vkVoidFunction>(
- low_latency::EnumeratePhysicalDevices)},
};
static const auto device_functions =
@@ -587,9 +547,11 @@ LowLatency_GetDeviceProcAddr(VkDevice device, const char* const pName) {
return it->second;
}
- const auto lock = std::scoped_lock{low_latency::mutex};
- return low_latency::device_vtables[low_latency::get_key(device)]
- .GetDeviceProcAddr(device, pName);
+ const auto lock = std::scoped_lock{low_latency::layer_context.mutex};
+
+ using namespace low_latency;
+ const auto& context = layer_context.get_context<DeviceContext>(device);
+ return context.vtable.GetDeviceProcAddr(device, pName);
}
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
@@ -602,7 +564,9 @@ LowLatency_GetInstanceProcAddr(VkInstance instance, const char* const pName) {
}
}
- const auto lock = std::scoped_lock{low_latency::mutex};
- return low_latency::instance_vtables[low_latency::get_key(instance)]
- .GetInstanceProcAddr(instance, pName);
+ const auto lock = std::scoped_lock{low_latency::layer_context.mutex};
+
+ using namespace low_latency;
+ const auto& context = layer_context.get_context<InstanceContext>(instance);
+ return context.vtable.GetInstanceProcAddr(instance, pName);
} \ No newline at end of file