#ifndef LAYER_CONTEXT_HH_ #define LAYER_CONTEXT_HH_ #include #include #include #include "context.hh" #include "device_context.hh" #include "instance_context.hh" #include "physical_device_context.hh" #include "queue_context.hh" // The purpose of this file is to provide a definition for the highest level // entry point struct of our vulkan state. // // All Context structs have deleted copy/move constructors. This is because we // want to be extremely explicit with how/when we delete things, and this allows // us to use destructors for cleanup without much worry about weird copies // floating around. Most contexts will probably live inside std::unique_ptr's as // a result so they can be used in standard containers. namespace low_latency { // All these templates do is make it so we can go from some DispatchableType // to their respective context's with nice syntax. template concept DispatchableType = std::same_as, VkInstance> || std::same_as, VkPhysicalDevice> || std::same_as, VkDevice> || std::same_as, VkQueue>; template struct context_for_t; template <> struct context_for_t { using context = InstanceContext; }; template <> struct context_for_t { using context = PhysicalDeviceContext; }; template <> struct context_for_t { using context = DeviceContext; }; template <> struct context_for_t { using context = QueueContext; }; template using dispatch_context_t = typename context_for_t::context; struct LayerContext final : public Context { public: std::mutex mutex; std::unordered_map> contexts; public: LayerContext(); virtual ~LayerContext(); public: template static void* get_key(const DT& dt) { return reinterpret_cast(dt); } template std::shared_ptr> get_context(const DT& dt) { const auto key = get_key(dt); const auto lock = std::scoped_lock(this->mutex); const auto it = this->contexts.find(key); assert(it != std::end(this->contexts)); using context_t = dispatch_context_t
; const auto ptr = std::dynamic_pointer_cast(it->second); assert(ptr); return ptr; } }; }; // namespace low_latency #endif