Browse Source

Vk: querying image memory requirements.

pull/234/head
Vladimír Vondruš 6 years ago
parent
commit
19c9243d3b
  1. 3
      doc/vulkan-mapping.dox
  2. 4
      src/Magnum/Vk/DeviceProperties.h
  3. 23
      src/Magnum/Vk/Image.cpp
  4. 16
      src/Magnum/Vk/Image.h
  5. 10
      src/Magnum/Vk/Implementation/DeviceState.cpp
  6. 2
      src/Magnum/Vk/Implementation/DeviceState.h
  7. 11
      src/Magnum/Vk/Memory.cpp
  8. 67
      src/Magnum/Vk/Memory.h
  9. 19
      src/Magnum/Vk/Test/ImageVkTest.cpp
  10. 28
      src/Magnum/Vk/Test/MemoryTest.cpp
  11. 1
      src/Magnum/Vk/Vk.h

3
doc/vulkan-mapping.dox

@ -197,7 +197,7 @@ Vulkan function | Matching API
@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{GetImageMemoryRequirements}, \n @fn_vk{GetImageMemoryRequirements2} @m_class{m-label m-flat m-success} **KHR, 1.1** | |
@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} | |
@fn_vk{GetInstanceProcAddr} | @ref Instance constructor
@ -329,6 +329,7 @@ Vulkan structure | Matching API
Vulkan structure | Matching API
--------------------------------------- | ------------
@type_vk{ImageCreateInfo} | @ref ImageCreateInfo
@type_vk{ImageMemoryRequirementsInfo} | not exposed, internal to @ref Image::memoryRequirements()
@type_vk{InstanceCreateInfo} | @ref InstanceCreateInfo
*/

4
src/Magnum/Vk/DeviceProperties.h

@ -434,8 +434,8 @@ class MAGNUM_VK_EXPORT DeviceProperties {
* should be considered etc.). Expected to have at least one bit
* of the first @ref memoryCount() bits set, otherwise the
* function will always fail. Defaults to all bits set, meaning
* all memory types are considered. Corresponds to the
* `memoryTypeBits` field of @type_vk{MemoryRequirements}.
* all memory types are considered. Corresponds to
* @ref MemoryRequirements::memories().
*
* Queries memory properties using @ref memoryProperties() and out of
* memory types set in @p memoryBits tries to find one that contains

23
src/Magnum/Vk/Image.cpp

@ -28,7 +28,9 @@
#include "Magnum/Vk/Device.h"
#include "Magnum/Vk/Handle.h"
#include "Magnum/Vk/Integration.h"
#include "Magnum/Vk/Memory.h"
#include "Magnum/Vk/Result.h"
#include "Magnum/Vk/Implementation/DeviceState.h"
namespace Magnum { namespace Vk {
@ -96,10 +98,31 @@ Image& Image::operator=(Image&& other) noexcept {
return *this;
}
MemoryRequirements Image::memoryRequirements() const {
MemoryRequirements requirements;
VkImageMemoryRequirementsInfo2 info{};
info.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
info.image = _handle;
_device->state().getImageMemoryRequirementsImplementation(*_device, info, requirements);
return requirements;
}
VkImage Image::release() {
const VkImage handle = _handle;
_handle = {};
return handle;
}
void Image::getMemoryRequirementsImplementationDefault(Device& device, const VkImageMemoryRequirementsInfo2& info, VkMemoryRequirements2& requirements) {
device->GetImageMemoryRequirements(device, info.image, &requirements.memoryRequirements);
}
void Image::getMemoryRequirementsImplementationKHR(Device& device, const VkImageMemoryRequirementsInfo2& info, VkMemoryRequirements2& requirements) {
device->GetImageMemoryRequirements2KHR(device, &info, &requirements);
}
void Image::getMemoryRequirementsImplementation11(Device& device, const VkImageMemoryRequirementsInfo2& info, VkMemoryRequirements2& requirements) {
device->GetImageMemoryRequirements2(device, &info, &requirements);
}
}}

16
src/Magnum/Vk/Image.h

@ -41,6 +41,8 @@
namespace Magnum { namespace Vk {
namespace Implementation { struct DeviceState; }
/**
@brief Image usage
@m_since_latest
@ -395,6 +397,14 @@ class MAGNUM_VK_EXPORT Image {
/** @brief Handle flags */
HandleFlags handleFlags() const { return _flags; }
/**
* @brief Image memory requirements
*
* @see @fn_vk_keyword{GetImageMemoryRequirements2},
* @fn_vk_keyword{GetImageMemoryRequirements}
*/
MemoryRequirements memoryRequirements() const;
/**
* @brief Release the underlying Vulkan image
*
@ -406,6 +416,12 @@ class MAGNUM_VK_EXPORT Image {
VkImage release();
private:
friend Implementation::DeviceState;
MAGNUM_VK_LOCAL static void getMemoryRequirementsImplementationDefault(Device& device, const VkImageMemoryRequirementsInfo2& info, VkMemoryRequirements2& requirements);
MAGNUM_VK_LOCAL static void getMemoryRequirementsImplementationKHR(Device& device, const VkImageMemoryRequirementsInfo2& info, VkMemoryRequirements2& requirements);
MAGNUM_VK_LOCAL static void getMemoryRequirementsImplementation11(Device& device, const VkImageMemoryRequirementsInfo2& info, VkMemoryRequirements2& requirements);
/* Can't be a reference because of the NoCreate constructor */
Device* _device;

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

@ -26,6 +26,8 @@
#include "DeviceState.h"
#include "Magnum/Vk/Device.h"
#include "Magnum/Vk/Extensions.h"
#include "Magnum/Vk/Image.h"
#include "Magnum/Vk/Version.h"
namespace Magnum { namespace Vk { namespace Implementation {
@ -36,6 +38,14 @@ DeviceState::DeviceState(Device& device) {
} else {
getDeviceQueueImplementation = &Device::getQueueImplementationDefault;
}
if(device.isVersionSupported(Version::Vk11)) {
getImageMemoryRequirementsImplementation = &Image::getMemoryRequirementsImplementation11;
} else if(device.isExtensionEnabled<Extensions::KHR::get_memory_requirements2>()) {
getImageMemoryRequirementsImplementation = &Image::getMemoryRequirementsImplementationKHR;
} else {
getImageMemoryRequirementsImplementation = &Image::getMemoryRequirementsImplementationDefault;
}
}
}}}

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

@ -34,6 +34,8 @@ struct DeviceState {
explicit DeviceState(Device& instance);
void(*getDeviceQueueImplementation)(Device&, const VkDeviceQueueInfo2&, VkQueue&);
/** @todo put this eventually into a dedicated image state struct? */
void(*getImageMemoryRequirementsImplementation)(Device&, const VkImageMemoryRequirementsInfo2&, VkMemoryRequirements2&);
};
}}}

11
src/Magnum/Vk/Memory.cpp

@ -30,6 +30,17 @@
namespace Magnum { namespace Vk {
MemoryRequirements::MemoryRequirements(): _requirements{} {
_requirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
}
MemoryRequirements::MemoryRequirements(NoInitT) noexcept {}
MemoryRequirements::MemoryRequirements(const VkMemoryRequirements2& requirements):
/* Can't use {} with GCC 4.8 here because it tries to initialize the first
member instead of doing a copy */
_requirements(requirements) {}
Debug& operator<<(Debug& debug, const MemoryFlag value) {
debug << "Vk::MemoryFlag" << Debug::nospace;

67
src/Magnum/Vk/Memory.h

@ -26,12 +26,14 @@
*/
/** @file
* @brief Enum @ref Magnum::Vk::MemoryFlag, enum set @ref Magnum::Vk::MemoryFlags
* @brief Class @ref Magnum::Vk::MemoryRequirements, enum @ref Magnum::Vk::MemoryFlag, enum set @ref Magnum::Vk::MemoryFlags
*/
#include <Corrade/Containers/EnumSet.h>
#include "Magnum/Magnum.h"
#include "Magnum/Tags.h"
#include "Magnum/Vk/Vk.h"
#include "Magnum/Vk/Vulkan.h"
#include "Magnum/Vk/visibility.h"
@ -109,6 +111,69 @@ CORRADE_ENUMSET_OPERATORS(MemoryFlags)
*/
MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, MemoryFlags value);
/**
@brief Device memory requirements
@m_since_latest
Wraps a @type_vk_keyword{MemoryRequirements2}. Not constructible directly,
returned from @ref Image::memoryRequirements().
@see @ref DeviceProperties::pickMemory()
*/
class MAGNUM_VK_EXPORT MemoryRequirements {
public:
/**
* @brief Construct without initializing the contents
*
* Note that not even the `sType` field is set --- the structure has to
* be fully initialized afterwards in order to be usable.
*/
explicit MemoryRequirements(NoInitT) noexcept;
/**
* @brief Construct from existing data
*
* Copies the existing values verbatim, pointers are kept unchanged
* without taking over the ownership. Modifying the newly created
* instance will not modify the original data nor the pointed-to data.
*/
explicit MemoryRequirements(const VkMemoryRequirements2& requirements);
/** @brief Underlying @type_vk{MemoryRequirements} structure */
VkMemoryRequirements2& requirements() { return _requirements; }
/** @overload */
const VkMemoryRequirements2& requirements() const { return _requirements; }
/** @overload */
operator VkMemoryRequirements2&() { return _requirements; }
/** @overload */
operator const VkMemoryRequirements2&() const { return _requirements; }
/** @overload */
VkMemoryRequirements2* operator->() { return &_requirements; }
/** @overload */
const VkMemoryRequirements2* operator->() const { return &_requirements; }
/** @brief Required memory size */
UnsignedLong size() const {
return _requirements.memoryRequirements.size;
}
/** @brief Required memory alignment */
UnsignedLong alignment() const {
return _requirements.memoryRequirements.alignment;
}
/** @brief Bits indicating which memory */
UnsignedInt memories() const {
return _requirements.memoryRequirements.memoryTypeBits;
}
private:
friend Image;
explicit MemoryRequirements();
VkMemoryRequirements2 _requirements;
};
}}
#endif

19
src/Magnum/Vk/Test/ImageVkTest.cpp

@ -23,8 +23,9 @@
DEALINGS IN THE SOFTWARE.
*/
#include "Magnum/Vk/Image.h"
#include "Magnum/Vk/Handle.h"
#include "Magnum/Vk/Image.h"
#include "Magnum/Vk/Memory.h"
#include "Magnum/Vk/Result.h"
#include "Magnum/Vk/VulkanTester.h"
@ -43,6 +44,8 @@ struct ImageVkTest: VulkanTester {
void constructMove();
void wrap();
void memoryRequirements();
};
ImageVkTest::ImageVkTest() {
@ -55,7 +58,9 @@ ImageVkTest::ImageVkTest() {
&ImageVkTest::constructCubeMapArray,
&ImageVkTest::constructMove,
&ImageVkTest::wrap});
&ImageVkTest::wrap,
&ImageVkTest::memoryRequirements});
}
void ImageVkTest::construct1D() {
@ -180,6 +185,16 @@ void ImageVkTest::wrap() {
device()->DestroyImage(device(), image, nullptr);
}
void ImageVkTest::memoryRequirements() {
/* Use linear tiling for a deterministic memory size */
ImageCreateInfo2D info{ImageUsage::Sampled, VK_FORMAT_R8G8B8A8_UNORM, {128, 64}, 1};
info->tiling = VK_IMAGE_TILING_LINEAR;
Image image{device(), info, NoAllocate};
MemoryRequirements requirements = image.memoryRequirements();
CORRADE_COMPARE(requirements.size(), 128*64*4);
}
}}}}
CORRADE_TEST_MAIN(Magnum::Vk::Test::ImageVkTest)

28
src/Magnum/Vk/Test/MemoryTest.cpp

@ -34,15 +34,41 @@ namespace Magnum { namespace Vk { namespace Test { namespace {
struct MemoryTest: TestSuite::Tester {
explicit MemoryTest();
void requirementsConstructNoInit();
void requirementsConstructFromVk();
void debugMemoryFlag();
void debugMemoryFlags();
};
MemoryTest::MemoryTest() {
addTests({&MemoryTest::debugMemoryFlag,
addTests({&MemoryTest::requirementsConstructNoInit,
&MemoryTest::requirementsConstructFromVk,
&MemoryTest::debugMemoryFlag,
&MemoryTest::debugMemoryFlags});
}
void MemoryTest::requirementsConstructNoInit() {
MemoryRequirements requirements{NoInit};
requirements->sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
new(&requirements) MemoryRequirements{NoInit};
CORRADE_COMPARE(requirements->sType, VK_STRUCTURE_TYPE_APPLICATION_INFO);
CORRADE_VERIFY((std::is_nothrow_constructible<MemoryRequirements, NoInitT>::value));
/* Implicit construction is not allowed */
CORRADE_VERIFY(!(std::is_convertible<NoInitT, MemoryRequirements>::value));
}
void MemoryTest::requirementsConstructFromVk() {
VkMemoryRequirements2 vkRequirements;
vkRequirements.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
MemoryRequirements requirements{vkRequirements};
CORRADE_COMPARE(requirements->sType, VK_STRUCTURE_TYPE_APPLICATION_INFO);
}
void MemoryTest::debugMemoryFlag() {
std::ostringstream out;
Debug{&out} << MemoryFlag::HostCached << MemoryFlag(0xdeadcafe);

1
src/Magnum/Vk/Vk.h

@ -52,6 +52,7 @@ class InstanceCreateInfo;
class InstanceExtension;
class InstanceExtensionProperties;
class LayerProperties;
class MemoryRequirements;
enum class MemoryFlag: UnsignedInt;
typedef Containers::EnumSet<MemoryFlag> MemoryFlags;
enum class MemoryHeapFlag: UnsignedInt;

Loading…
Cancel
Save