diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index 930cc768e..0fcdc7016 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -32,7 +32,6 @@ set(MagnumVk_SRCS Extensions.cpp Handle.cpp Instance.cpp - Memory.cpp Result.cpp Shader.cpp Version.cpp @@ -48,7 +47,8 @@ set(MagnumVk_GracefulAssert_SRCS Enums.cpp ExtensionProperties.cpp Image.cpp - LayerProperties.cpp) + LayerProperties.cpp + Memory.cpp) set(MagnumVk_HEADERS Assert.h diff --git a/src/Magnum/Vk/Memory.cpp b/src/Magnum/Vk/Memory.cpp index 2d0f32254..4356a283d 100644 --- a/src/Magnum/Vk/Memory.cpp +++ b/src/Magnum/Vk/Memory.cpp @@ -46,6 +46,11 @@ MemoryRequirements::MemoryRequirements(const VkMemoryRequirements2& requirements member instead of doing a copy */ _requirements(requirements) {} +UnsignedLong MemoryRequirements::alignedSize(const UnsignedLong alignment) const { + CORRADE_ASSERT(alignment, "Vk::MemoryRequirements::alignedSize(): alignment can't be zero", {}); + return ((_requirements.memoryRequirements.size + alignment - 1)/alignment)*alignment; +} + MemoryAllocateInfo::MemoryAllocateInfo(UnsignedLong size, UnsignedInt memory): _info{} { _info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; _info.allocationSize = size; diff --git a/src/Magnum/Vk/Memory.h b/src/Magnum/Vk/Memory.h index d52a2230f..ae82909cd 100644 --- a/src/Magnum/Vk/Memory.h +++ b/src/Magnum/Vk/Memory.h @@ -161,16 +161,35 @@ class MAGNUM_VK_EXPORT MemoryRequirements { /** @overload */ const VkMemoryRequirements2* operator->() const { return &_requirements; } - /** @brief Required memory size */ + /** + * @brief Required memory size + * + * @see @ref alignedSize() + */ UnsignedLong size() const { return _requirements.memoryRequirements.size; } - /** @brief Required memory alignment */ + /** + * @brief Required memory alignment + * + * @see @ref alignedSize() + */ UnsignedLong alignment() const { return _requirements.memoryRequirements.alignment; } + /** + * @brief Required memory size rounded up for given alignment + * + * Pads @ref size() with given alignment requirements. For example, a + * 13765-byte buffer aligned to 4 kB would be 16384 bytes. See the + * @ref Memory class for more information and example usage. + * + * The alignment is expected to be non-zero. + */ + UnsignedLong alignedSize(UnsignedLong alignment) const; + /** @brief Bits indicating which memory */ UnsignedInt memories() const { return _requirements.memoryRequirements.memoryTypeBits; diff --git a/src/Magnum/Vk/Test/CMakeLists.txt b/src/Magnum/Vk/Test/CMakeLists.txt index 06a8efb5e..dd753028d 100644 --- a/src/Magnum/Vk/Test/CMakeLists.txt +++ b/src/Magnum/Vk/Test/CMakeLists.txt @@ -37,7 +37,7 @@ corrade_add_test(VkImageTest ImageTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkInstanceTest InstanceTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkIntegrationTest IntegrationTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkLayerPropertiesTest LayerPropertiesTest.cpp LIBRARIES MagnumVk) -corrade_add_test(VkMemoryTest MemoryTest.cpp LIBRARIES MagnumVk) +corrade_add_test(VkMemoryTest MemoryTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkResultTest ResultTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkShaderTest ShaderTest.cpp LIBRARIES MagnumVk) diff --git a/src/Magnum/Vk/Test/MemoryTest.cpp b/src/Magnum/Vk/Test/MemoryTest.cpp index 010df0b1e..209d10478 100644 --- a/src/Magnum/Vk/Test/MemoryTest.cpp +++ b/src/Magnum/Vk/Test/MemoryTest.cpp @@ -37,6 +37,9 @@ struct MemoryTest: TestSuite::Tester { void requirementsConstructNoInit(); void requirementsConstructFromVk(); + void requirementsAlignedSize(); + void requirementsAlignedSizeZeroAlignement(); + void allocateInfoConstruct(); void allocateInfoConstructNoInit(); void allocateInfoConstructFromVk(); @@ -52,6 +55,9 @@ MemoryTest::MemoryTest() { addTests({&MemoryTest::requirementsConstructNoInit, &MemoryTest::requirementsConstructFromVk, + &MemoryTest::requirementsAlignedSize, + &MemoryTest::requirementsAlignedSizeZeroAlignement, + &MemoryTest::allocateInfoConstruct, &MemoryTest::allocateInfoConstructNoInit, &MemoryTest::allocateInfoConstructFromVk, @@ -83,6 +89,36 @@ void MemoryTest::requirementsConstructFromVk() { CORRADE_COMPARE(requirements->sType, VK_STRUCTURE_TYPE_APPLICATION_INFO); } +void MemoryTest::requirementsAlignedSize() { + /* Creating from a raw Vulkan structure because there's no other way */ + VkMemoryRequirements2 vkRequirements{}; + vkRequirements.memoryRequirements.size = 13765; + CORRADE_COMPARE(MemoryRequirements{vkRequirements}.alignedSize(4096), 16384); + + vkRequirements.memoryRequirements.size = 16383; + CORRADE_COMPARE(MemoryRequirements{vkRequirements}.alignedSize(4096), 16384); + + vkRequirements.memoryRequirements.size = 16384; + CORRADE_COMPARE(MemoryRequirements{vkRequirements}.alignedSize(4096), 16384); + + vkRequirements.memoryRequirements.size = 0; + CORRADE_COMPARE(MemoryRequirements{vkRequirements}.alignedSize(4096), 0); +} + +void MemoryTest::requirementsAlignedSizeZeroAlignement() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + VkMemoryRequirements2 vkRequirements{}; + vkRequirements.memoryRequirements.size = 16384; + + std::ostringstream out; + Error redirectError{&out}; + MemoryRequirements{vkRequirements}.alignedSize(0); + CORRADE_COMPARE(out.str(), "Vk::MemoryRequirements::alignedSize(): alignment can't be zero\n"); +} + void MemoryTest::allocateInfoConstruct() { MemoryAllocateInfo info{65536, 1}; CORRADE_COMPARE(info->allocationSize, 65536);