// Copyright 2022 Simon Boyé #include #include #include namespace vk { Fence::Fence() noexcept { } Fence::Fence(Context& context, VkFenceCreateFlags flags) : m_context(&context) { assert(m_context); VkFenceCreateInfo create_info { .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .flags = flags, }; if(vkCreateFence( context.device(), &create_info, nullptr, &m_fence ) != VK_SUCCESS) throw std::runtime_error("failed to create fence"); } Fence::Fence(Fence&& other) noexcept { swap(*this, other); } Fence::~Fence() noexcept { if(!is_null()) destroy(); } Fence& Fence::operator=(Fence&& other) noexcept { swap(*this, other); if(other) other.destroy(); return *this; } VkResult Fence::get_status() const { assert(m_context); assert(!is_null()); VkResult result = vkGetFenceStatus( m_context->device(), m_fence ); if(result < 0) throw std::runtime_error("failed to get fence status"); return result; } void Fence::reset() { assert(m_context); assert(!is_null()); if(vkResetFences( m_context->device(), 1, &m_fence ) != VK_SUCCESS) throw std::runtime_error("failed to reset fence"); } void Fence::wait(uint64_t timeout) const { assert(m_context); assert(!is_null()); wait_for_fences( m_context->device(), ArrayView(1, const_cast(&m_fence)), true, timeout ); } void Fence::destroy() noexcept { assert(!is_null()); assert(m_context); vkDestroyFence( m_context->device(), m_fence, nullptr ); m_fence = nullptr; } void wait_for_fences(VkDevice device, ArrayView fences, bool wait_all, uint64_t timeout) { assert(fences.is_dense()); if(fences.size() == 0) return; if(vkWaitForFences( device, fences.size(), fences.data(), wait_all, timeout ) != VK_SUCCESS) throw std::runtime_error("failed to wait for fences"); } }