Browse Source

Vk: fence status, reset and wait.

I was hesitating a bit with the <chrono> include but I can't think of
anything better right now. It's "only" 4k lines on C++11 (and I bet most
of it is <type_traits>), so should be fine.
pull/491/head
Vladimír Vondruš 5 years ago
parent
commit
32cc6ed69d
  1. 6
      doc/vulkan-mapping.dox
  2. 17
      src/Magnum/Vk/Fence.cpp
  3. 53
      src/Magnum/Vk/Fence.h
  4. 6
      src/Magnum/Vk/FenceCreateInfo.h
  5. 49
      src/Magnum/Vk/Test/FenceVkTest.cpp

6
doc/vulkan-mapping.dox

@ -220,7 +220,7 @@ Vulkan function | Matching API
@fn_vk{GetDeviceProcAddr} | @ref Device constructor
@fn_vk{GetDeviceQueue}, \n @fn_vk{GetDeviceQueue2} @m_class{m-label m-flat m-success} **1.1** | @ref Device constructor
@fn_vk{GetEventStatus} | |
@fn_vk{GetFenceStatus} | |
@fn_vk{GetFenceStatus} | @ref Fence::status()
@fn_vk{GetImageMemoryRequirements}, \n @fn_vk{GetImageMemoryRequirements2} @m_class{m-label m-flat m-success} **KHR, 1.1** | @ref Image::memoryRequirements()
@fn_vk{GetImageSparseMemoryRequirements}, \n @fn_vk{GetImageSparseMemoryRequirements2} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@fn_vk{GetImageSubresourceLayout} | |
@ -281,7 +281,7 @@ Vulkan function | Matching API
@fn_vk{ResetCommandBuffer} | @ref CommandBuffer::reset()
@fn_vk{ResetCommandPool} | @ref CommandPool::reset()
@fn_vk{ResetDescriptorPool} | |
@fn_vk{ResetFences} | |
@fn_vk{ResetFences} | @ref Fence::reset()
@fn_vk{ResetQueryPool} @m_class{m-label m-flat m-success} **EXT, 1.2** | |
@subsection vulkan-mapping-functions-s S
@ -319,7 +319,7 @@ Vulkan function | Matching API
Vulkan function | Matching API
--------------------------------------- | ------------
@fn_vk{WaitForFences} | |
@fn_vk{WaitForFences} | @ref Fence::wait()
@fn_vk{WriteAccelerationStructuresPropertiesKHR} @m_class{m-label m-flat m-warning} **KHR** | |
@section vulkan-mapping-structures Structures

17
src/Magnum/Vk/Fence.cpp

@ -28,6 +28,7 @@
#include "Magnum/Vk/Assert.h"
#include "Magnum/Vk/Device.h"
#include "Magnum/Vk/Result.h"
namespace Magnum { namespace Vk {
@ -76,6 +77,22 @@ Fence& Fence::operator=(Fence&& other) noexcept {
return *this;
}
bool Fence::status() {
return MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(NotReady, (**_device).GetFenceStatus(*_device, _handle)) == Result::Success;
}
void Fence::reset() {
MAGNUM_VK_INTERNAL_ASSERT_SUCCESS((**_device).ResetFences(*_device, 1, &_handle));
}
bool Fence::wait(const std::chrono::nanoseconds timeout) {
return MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(Timeout, (**_device).WaitForFences(*_device, 1, &_handle, true, timeout.count())) == Result::Success;
}
void Fence::wait() {
CORRADE_INTERNAL_ASSERT_OUTPUT(wait(std::chrono::nanoseconds{~std::uint64_t{}}));
}
VkFence Fence::release() {
const VkFence handle = _handle;
_handle = {};

53
src/Magnum/Vk/Fence.h

@ -30,6 +30,8 @@
* @m_since_latest
*/
#include <chrono>
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/Vk/Handle.h"
@ -53,6 +55,13 @@ the @p info parameter at its default. If you want to pass additional parameters
to it, include the @ref FenceCreateInfo class as usual:
@snippet MagnumVk.cpp Fence-creation
@section Vk-Fence-usage Basic usage
By default a fence is created unsignaled. It can be created in a signaled state
using @ref FenceCreateInfo::Flag::Signaled and its signaled state reset back
via @ref reset(). Fence status can be queried immediately via @ref status() and
waited on using @ref wait().
*/
class MAGNUM_VK_EXPORT Fence {
public:
@ -122,6 +131,50 @@ class MAGNUM_VK_EXPORT Fence {
/** @brief Handle flags */
HandleFlags handleFlags() const { return _flags; }
/**
* @brief Reset the fence
*
* Sets the state of a fence to unsignaled from the host.
* @see @fn_vk_keyword{ResetFences}
* @todo batch version (needs `DynamicArray<N, VkFence>` to avoid an
* allocation)
*/
void reset();
/**
* @brief Fence status
*
* Returns @cpp true @ce if the fence is signaled and @cpp false @ce
* if unsignaled.
* @see @fn_vk_keyword{GetFenceStatus}
*/
bool status();
/**
* @brief Wait for the fence to become signaled
*
* Blocks until the fence becomes signaled or @p timeout is elapsed,
* whichever happens sooner, returning @cpp true @ce is the fence
* became signaled. If the fence is already signaled, the function
* returns immediately, if the timeout happens before the fence
* becomes signaled, @cpp false @ce is returned.
*
* Calling this function with zero @p timeout is equivalent to calling
* @ref status().
* @see @fn_vk_keyword{WaitForFences}
* @todo batch version (needs DynamicArray<N, VkFence> to avoid an
* allocation), expose `waitAll`
*/
bool wait(std::chrono::nanoseconds timeout);
/**
* @brief Wait indefinitely for the fence to become signaled
*
* Equivalent to calling @ref wait(std::chrono::nanoseconds) with the
* largest representable 64-bit value.
*/
void wait();
/**
* @brief Release the underlying Vulkan fence
*

6
src/Magnum/Vk/FenceCreateInfo.h

@ -58,7 +58,11 @@ class MAGNUM_VK_EXPORT FenceCreateInfo {
* @m_enum_values_as_keywords
*/
enum class Flag: UnsignedInt {
/** Create the fence in a signaled state */
/**
* Create the fence in a signaled state.
*
* @ref Fence::status(), @ref Fence::reset()
*/
Signaled = VK_FENCE_CREATE_SIGNALED_BIT
};

49
src/Magnum/Vk/Test/FenceVkTest.cpp

@ -38,13 +38,25 @@ struct FenceVkTest: VulkanTester {
void constructMove();
void wrap();
void status();
void reset();
void wait100ms();
void wait();
};
FenceVkTest::FenceVkTest() {
addTests({&FenceVkTest::construct,
&FenceVkTest::constructMove,
&FenceVkTest::wrap});
&FenceVkTest::wrap,
&FenceVkTest::status,
&FenceVkTest::reset});
addBenchmarks({&FenceVkTest::wait100ms}, 1);
addTests({&FenceVkTest::wait});
}
void FenceVkTest::construct() {
@ -93,6 +105,41 @@ void FenceVkTest::wrap() {
device()->DestroyFence(device(), fence, nullptr);
}
void FenceVkTest::status() {
Fence a{device()};
CORRADE_VERIFY(!a.status());
Fence b{device(), FenceCreateInfo{FenceCreateInfo::Flag::Signaled}};
CORRADE_VERIFY(b.status());
}
void FenceVkTest::reset() {
Fence a{device(), FenceCreateInfo{FenceCreateInfo::Flag::Signaled}};
CORRADE_VERIFY(a.status());
a.reset();
CORRADE_VERIFY(!a.status());
}
void FenceVkTest::wait100ms() {
Fence a{device()};
CORRADE_VERIFY(!a.status());
/* A benchmark so we have at least some verification we're not terribly off
with the units */
CORRADE_BENCHMARK(1)
CORRADE_VERIFY(!a.wait(std::chrono::milliseconds{100}));
CORRADE_VERIFY(!a.status());
}
void FenceVkTest::wait() {
Fence a{device(), FenceCreateInfo{FenceCreateInfo::Flag::Signaled}};
CORRADE_VERIFY(a.status());
a.wait();
CORRADE_VERIFY(a.status());
}
}}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::FenceVkTest)

Loading…
Cancel
Save