Browse Source

Vk: binding Buffer memory.

Again basically the same as with Image.
pull/234/head
Vladimír Vondruš 6 years ago
parent
commit
086f531f17
  1. 47
      src/Magnum/Vk/Buffer.cpp
  2. 45
      src/Magnum/Vk/Buffer.h
  3. 2
      src/Magnum/Vk/CMakeLists.txt
  4. 3
      src/Magnum/Vk/Implementation/DeviceState.cpp
  5. 1
      src/Magnum/Vk/Implementation/DeviceState.h
  6. 22
      src/Magnum/Vk/Test/BufferTest.cpp
  7. 57
      src/Magnum/Vk/Test/BufferVkTest.cpp
  8. 2
      src/Magnum/Vk/Test/CMakeLists.txt

47
src/Magnum/Vk/Buffer.cpp

@ -28,7 +28,6 @@
#include "Magnum/Vk/Assert.h"
#include "Magnum/Vk/Device.h"
#include "Magnum/Vk/Handle.h"
#include "Magnum/Vk/Memory.h"
#include "Magnum/Vk/Implementation/DeviceState.h"
namespace Magnum { namespace Vk {
@ -58,13 +57,13 @@ Buffer Buffer::wrap(Device& device, const VkBuffer handle, const HandleFlags fla
return out;
}
Buffer::Buffer(Device& device, const BufferCreateInfo& info, NoAllocateT): _device{&device}, _flags{HandleFlag::DestroyOnDestruction} {
Buffer::Buffer(Device& device, const BufferCreateInfo& info, NoAllocateT): _device{&device}, _flags{HandleFlag::DestroyOnDestruction}, _dedicatedMemory{NoCreate} {
MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(device->CreateBuffer(device, info, nullptr, &_handle));
}
Buffer::Buffer(NoCreateT): _device{}, _handle{} {}
Buffer::Buffer(NoCreateT): _device{}, _handle{}, _dedicatedMemory{NoCreate} {}
Buffer::Buffer(Buffer&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags} {
Buffer::Buffer(Buffer&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags}, _dedicatedMemory{std::move(other._dedicatedMemory)} {
other._handle = {};
}
@ -78,6 +77,7 @@ Buffer& Buffer::operator=(Buffer&& other) noexcept {
swap(other._device, _device);
swap(other._handle, _handle);
swap(other._flags, _flags);
swap(other._dedicatedMemory, _dedicatedMemory);
return *this;
}
@ -90,6 +90,32 @@ MemoryRequirements Buffer::memoryRequirements() const {
return requirements;
}
void Buffer::bindMemory(Memory& memory, const UnsignedLong offset) {
VkBindBufferMemoryInfo info{};
info.sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO;
info.buffer = _handle;
info.memory = memory;
info.memoryOffset = offset;
_device->state().bindBufferMemoryImplementation(*_device, 1, &info);
}
void Buffer::bindDedicatedMemory(Memory&& memory) {
bindMemory(memory, 0);
_dedicatedMemory = std::move(memory);
}
bool Buffer::hasDedicatedMemory() const {
/* Sigh. Though better than needing to have `const handle()` overloads
returning `const VkDeviceMemory_T*` */
return const_cast<Buffer&>(*this)._dedicatedMemory.handle();
}
Memory& Buffer::dedicatedMemory() {
CORRADE_ASSERT(_dedicatedMemory.handle(),
"Vk::Buffer::dedicatedMemory(): buffer doesn't have a dedicated memory", _dedicatedMemory);
return _dedicatedMemory;
}
VkBuffer Buffer::release() {
const VkBuffer handle = _handle;
_handle = {};
@ -108,4 +134,17 @@ void Buffer::getMemoryRequirementsImplementation11(Device& device, const VkBuffe
device->GetBufferMemoryRequirements2(device, &info, &requirements);
}
void Buffer::bindMemoryImplementationDefault(Device& device, UnsignedInt count, const VkBindBufferMemoryInfo* const infos) {
for(std::size_t i = 0; i != count; ++i)
device->BindBufferMemory(device, infos[i].buffer, infos[i].memory, infos[i].memoryOffset);
}
void Buffer::bindMemoryImplementationKHR(Device& device, UnsignedInt count, const VkBindBufferMemoryInfo* const infos) {
device->BindBufferMemory2KHR(device, count, infos);
}
void Buffer::bindMemoryImplementation11(Device& device, UnsignedInt count, const VkBindBufferMemoryInfo* const infos) {
device->BindBufferMemory2(device, count, infos);
}
}}

45
src/Magnum/Vk/Buffer.h

@ -34,6 +34,7 @@
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/Vk/Memory.h"
#include "Magnum/Vk/Vk.h"
#include "Magnum/Vk/Vulkan.h"
#include "Magnum/Vk/visibility.h"
@ -227,11 +228,48 @@ class MAGNUM_VK_EXPORT Buffer {
/**
* @brief Buffer memory requirements
*
* @see @fn_vk_keyword{GetBufferMemoryRequirements2},
* @see @ref bindMemory(), @fn_vk_keyword{GetBufferMemoryRequirements2},
* @fn_vk_keyword{GetBufferMemoryRequirements}
*/
MemoryRequirements memoryRequirements() const;
/**
* @brief Bind buffer memory
*
* Assumes that @p memory type, the amount of @p memory at @p offset
* and @p offset alignment corresponds to buffer memory requirements.
* @see @ref memoryRequirements(), @ref bindDedicatedMemory(),
* @fn_vk_keyword{BindBufferMemory2},
* @fn_vk_keyword{BindBufferMemory}
*/
void bindMemory(Memory& memory, UnsignedLong offset);
/**
* @brief Bind a dedicated buffer memory
*
* Equivalent to @ref bindMemory() with @p offset set to @cpp 0 @ce,
* with the additional effect that @p memory ownership transfers to the
* buffer and is then available through @ref dedicatedMemory().
*/
void bindDedicatedMemory(Memory&& memory);
/**
* @brief Whether the buffer has a dedicated memory
*
* Returns @cpp true @ce if the buffer memory was bound using
* @ref bindDedicatedMemory(), @cpp false @ce otherwise.
* @see @ref dedicatedMemory()
*/
bool hasDedicatedMemory() const;
/**
* @brief Dedicated buffer memory
*
* Expects that the buffer has a dedicated memory.
* @see @ref hasDedicatedMemory()
*/
Memory& dedicatedMemory();
/**
* @brief Release the underlying Vulkan buffer
*
@ -249,11 +287,16 @@ class MAGNUM_VK_EXPORT Buffer {
MAGNUM_VK_LOCAL static void getMemoryRequirementsImplementationKHR(Device& device, const VkBufferMemoryRequirementsInfo2& info, VkMemoryRequirements2& requirements);
MAGNUM_VK_LOCAL static void getMemoryRequirementsImplementation11(Device& device, const VkBufferMemoryRequirementsInfo2& info, VkMemoryRequirements2& requirements);
MAGNUM_VK_LOCAL static void bindMemoryImplementationDefault(Device& device, UnsignedInt count, const VkBindBufferMemoryInfo* infos);
MAGNUM_VK_LOCAL static void bindMemoryImplementationKHR(Device& device, UnsignedInt count, const VkBindBufferMemoryInfo* infos);
MAGNUM_VK_LOCAL static void bindMemoryImplementation11(Device& device, UnsignedInt count, const VkBindBufferMemoryInfo* infos);
/* Can't be a reference because of the NoCreate constructor */
Device* _device;
VkBuffer _handle;
HandleFlags _flags;
Memory _dedicatedMemory;
};
}}

2
src/Magnum/Vk/CMakeLists.txt

@ -27,7 +27,6 @@
find_package(Vulkan REQUIRED)
set(MagnumVk_SRCS
Buffer.cpp
CommandBuffer.cpp
CommandPool.cpp
Extensions.cpp
@ -42,6 +41,7 @@ set(MagnumVk_SRCS
Implementation/InstanceState.cpp)
set(MagnumVk_GracefulAssert_SRCS
Buffer.cpp
Device.cpp
DeviceProperties.cpp
Enums.cpp

3
src/Magnum/Vk/Implementation/DeviceState.cpp

@ -53,10 +53,13 @@ DeviceState::DeviceState(Device& device) {
if(device.isVersionSupported(Version::Vk11)) {
bindImageMemoryImplementation = &Image::bindMemoryImplementation11;
bindBufferMemoryImplementation = &Buffer::bindMemoryImplementation11;
} else if(device.isExtensionEnabled<Extensions::KHR::bind_memory2>()) {
bindImageMemoryImplementation = &Image::bindMemoryImplementationKHR;
bindBufferMemoryImplementation = &Buffer::bindMemoryImplementationKHR;
} else {
bindImageMemoryImplementation = &Image::bindMemoryImplementationDefault;
bindBufferMemoryImplementation = &Buffer::bindMemoryImplementationDefault;
}
}

1
src/Magnum/Vk/Implementation/DeviceState.h

@ -37,6 +37,7 @@ struct DeviceState {
/** @todo put this eventually into a dedicated buffer / image state struct? */
void(*getBufferMemoryRequirementsImplementation)(Device&, const VkBufferMemoryRequirementsInfo2&, VkMemoryRequirements2&);
void(*getImageMemoryRequirementsImplementation)(Device&, const VkImageMemoryRequirementsInfo2&, VkMemoryRequirements2&);
void(*bindBufferMemoryImplementation)(Device&, UnsignedInt, const VkBindBufferMemoryInfo*);
void(*bindImageMemoryImplementation)(Device&, UnsignedInt, const VkBindImageMemoryInfo*);
};

22
src/Magnum/Vk/Test/BufferTest.cpp

@ -24,7 +24,9 @@
*/
#include <new>
#include <sstream>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/Utility/DebugStl.h>
#include "Magnum/Vk/Buffer.h"
@ -39,6 +41,8 @@ struct BufferTest: TestSuite::Tester {
void constructNoCreate();
void constructCopy();
void dedicatedMemoryNotDedicated();
};
BufferTest::BufferTest() {
@ -47,7 +51,9 @@ BufferTest::BufferTest() {
&BufferTest::createInfoConstructFromVk,
&BufferTest::constructNoCreate,
&BufferTest::constructCopy});
&BufferTest::constructCopy,
&BufferTest::dedicatedMemoryNotDedicated});
}
void BufferTest::createInfoConstruct() {
@ -93,6 +99,20 @@ void BufferTest::constructCopy() {
CORRADE_VERIFY(!(std::is_assignable<Buffer, const Buffer&>{}));
}
void BufferTest::dedicatedMemoryNotDedicated() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
Buffer buffer{NoCreate};
CORRADE_VERIFY(!buffer.hasDedicatedMemory());
std::ostringstream out;
Error redirectError{&out};
buffer.dedicatedMemory();
CORRADE_COMPARE(out.str(), "Vk::Buffer::dedicatedMemory(): buffer doesn't have a dedicated memory\n");
}
}}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::BufferTest)

57
src/Magnum/Vk/Test/BufferVkTest.cpp

@ -23,7 +23,10 @@
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/TestSuite/Compare/Numeric.h>
#include "Magnum/Vk/Buffer.h"
#include "Magnum/Vk/DeviceProperties.h"
#include "Magnum/Vk/Handle.h"
#include "Magnum/Vk/Memory.h"
#include "Magnum/Vk/Result.h"
@ -40,6 +43,9 @@ struct BufferVkTest: VulkanTester {
void wrap();
void memoryRequirements();
void bindMemory();
void bindDedicatedMemory();
};
BufferVkTest::BufferVkTest() {
@ -48,7 +54,10 @@ BufferVkTest::BufferVkTest() {
&BufferVkTest::wrap,
&BufferVkTest::memoryRequirements});
&BufferVkTest::memoryRequirements,
&BufferVkTest::bindMemory,
&BufferVkTest::bindDedicatedMemory});
}
void BufferVkTest::construct() {
@ -66,17 +75,29 @@ void BufferVkTest::constructMove() {
Buffer a{device(), BufferCreateInfo{BufferUsage::StorageBuffer, 1024}, NoAllocate};
VkBuffer handle = a.handle();
/* Verify that also the dedicated memory gets moved */
MemoryRequirements requirements = a.memoryRequirements();
a.bindDedicatedMemory(Vk::Memory{device(), Vk::MemoryAllocateInfo{requirements.size(),
device().properties().pickMemory(Vk::MemoryFlag::DeviceLocal, requirements.memories())}});
VkDeviceMemory memoryHandle = a.dedicatedMemory().handle();
Buffer b = std::move(a);
CORRADE_VERIFY(!a.handle());
CORRADE_VERIFY(!a.hasDedicatedMemory());
CORRADE_COMPARE(b.handle(), handle);
CORRADE_COMPARE(b.handleFlags(), HandleFlag::DestroyOnDestruction);
CORRADE_VERIFY(b.hasDedicatedMemory());
CORRADE_COMPARE(b.dedicatedMemory().handle(), memoryHandle);
Buffer c{NoCreate};
c = std::move(b);
CORRADE_VERIFY(!b.handle());
CORRADE_VERIFY(!b.hasDedicatedMemory());
CORRADE_COMPARE(b.handleFlags(), HandleFlags{});
CORRADE_COMPARE(c.handle(), handle);
CORRADE_COMPARE(c.handleFlags(), HandleFlag::DestroyOnDestruction);
CORRADE_VERIFY(c.hasDedicatedMemory());
CORRADE_COMPARE(c.dedicatedMemory().handle(), memoryHandle);
CORRADE_VERIFY(std::is_nothrow_move_constructible<Buffer>::value);
CORRADE_VERIFY(std::is_nothrow_move_assignable<Buffer>::value);
@ -104,6 +125,40 @@ void BufferVkTest::memoryRequirements() {
CORRADE_COMPARE(requirements.size(), 16384);
}
void BufferVkTest::bindMemory() {
Buffer buffer{device(), BufferCreateInfo{BufferUsage::StorageBuffer, 16384}, NoAllocate};
MemoryRequirements requirements = buffer.memoryRequirements();
/* Similarly to the Image bindMemory() test, use a 128 kB offset */
constexpr UnsignedLong offset = 128*1024;
CORRADE_COMPARE_AS(offset, requirements.alignment(),
TestSuite::Compare::Divisible);
Vk::Memory memory{device(), Vk::MemoryAllocateInfo{
requirements.size() + offset,
device().properties().pickMemory(Vk::MemoryFlag::DeviceLocal, requirements.memories())}};
buffer.bindMemory(memory, offset);
CORRADE_VERIFY(!buffer.hasDedicatedMemory());
}
void BufferVkTest::bindDedicatedMemory() {
Buffer buffer{device(), BufferCreateInfo{BufferUsage::StorageBuffer, 16384}, NoAllocate};
MemoryRequirements requirements = buffer.memoryRequirements();
/** @todo expand once KHR_dedicated_allocation is implemented */
Vk::Memory memory{device(), Vk::MemoryAllocateInfo{
requirements.size(),
device().properties().pickMemory(Vk::MemoryFlag::DeviceLocal, requirements.memories())}};
VkDeviceMemory handle = memory.handle();
CORRADE_VERIFY(handle);
buffer.bindDedicatedMemory(std::move(memory));
CORRADE_VERIFY(buffer.hasDedicatedMemory());
CORRADE_COMPARE(buffer.dedicatedMemory().handle(), handle);
}
}}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::BufferVkTest)

2
src/Magnum/Vk/Test/CMakeLists.txt

@ -24,7 +24,7 @@
# DEALINGS IN THE SOFTWARE.
#
corrade_add_test(VkBufferTest BufferTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkBufferTest BufferTest.cpp LIBRARIES MagnumVkTestLib)
corrade_add_test(VkCommandBufferTest CommandBufferTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkCommandPoolTest CommandPoolTest.cpp LIBRARIES MagnumVk)
corrade_add_test(VkDeviceTest DeviceTest.cpp LIBRARIES MagnumVk)

Loading…
Cancel
Save