class new in Git master
#include <Magnum/Vk/Image.h>
Image Image.
Wraps a VkImage and its memory.
Image creation
Pass one of the ImageCreateInfo subclasses depending on desired image type with desired usage, format, size and other propoerties to the Image constructor together with specifying MemoryFlags for memory allocation.
#include <Magnum/Vk/ImageCreateInfo.h> … Vk::Image image{device, Vk::ImageCreateInfo2D{ Vk::ImageUsage::Sampled, PixelFormat::RGBA8Srgb, {1024, 1024}, 1 }, Vk::MemoryFlag::DeviceLocal};
With an Image ready, you may want to proceed to ImageView creation.
Custom memory allocation
Using Image(Device&, const ImageCreateInfo&, NoAllocateT), the image will be created without any memory attached. Image memory requirements can be subsequently queried using memoryRequirements() and an allocated memory bound with bindMemory(). See Memory for further details about memory allocation.
Vk::Image image{device, Vk::ImageCreateInfo2D{ Vk::ImageUsage::Sampled, PixelFormat::RGBA8Srgb, {1024, 1024}, 1 }, NoAllocate}; Vk::MemoryRequirements requirements = image.memoryRequirements(); Vk::Memory memory{device, Vk::MemoryAllocateInfo{ requirements.size(), device.properties().pickMemory(Vk::MemoryFlag::DeviceLocal, requirements.memories()) }}; image.bindMemory(memory, 0);
Using bindDedicatedMemory() instead of bindMemory() will transfer ownership of the Memory to the image instance, making it subsequently available through dedicatedMemory(). This matches current behavior of the Image(Device&, const ImageCreateInfo&, MemoryFlags) constructor shown above, except that you have more control over choosing and allocating the memory.
Image usage
Clearing image data
Usually an image is cleared implicitly at the start of a render pass using AttachmentLoadOperation::
Vk::Image image{device, Vk::ImageCreateInfo2D{ Vk::ImageUsage::TransferDestination|…, Vk::PixelFormat::RGBA8Srgb, … }, …}; … cmd.pipelineBarrier(Vk::PipelineStage::TopOfPipe, Vk::PipelineStage::Transfer, { /* Transition the image to a layout required by the clear operation */ {Vk::Accesses{}, Vk::Access::TransferWrite, Vk::ImageLayout::Undefined, Vk::ImageLayout::TransferDestination, image} }) .clearColorImage(image, Vk::ImageLayout::TransferDestination, 0x1f1f1f_srgbf);
Copying image data
The most common image copy operation is uploading texture data from a host-visible buffer to a device-local image. This is the preferred workflow over using a host-visible linear image directly, since linear images are poorly supported, have suboptimal access performance, and host-visible memory usually isn't the fastest for device access. Similarly, for downloading a rendered framebuffer back to the host it's recommended to linearize to a buffer instead of rendering to a linear image, which isn't widely supported.
The copy is done using CommandBuffer::
Vk::Buffer input{device, Vk::BufferCreateInfo{ Vk::BufferUsage::TransferSource, 256*256*4 … }, Vk::MemoryFlag::HostVisible}; Vk::Image texture{device, Vk::ImageCreateInfo2D{ Vk::ImageUsage::TransferDestination|Vk::ImageUsage::Sampled, Vk::PixelFormat::RGBA8Srgb, {256, 256}, … }, Vk::MemoryFlag::DeviceLocal}; … cmd.pipelineBarrier(Vk::PipelineStage::TopOfPipe, Vk::PipelineStage::Transfer, { /* Transition the image to a layout required by the copy operation */ {Vk::Accesses{}, Vk::Access::TransferWrite, Vk::ImageLayout::Undefined, Vk::ImageLayout::TransferDestination, texture} }) .copyBufferToImage({input, texture, Vk::ImageLayout::TransferDestination, { /* Copy the whole buffer to the first level of the image */ Vk::BufferImageCopy2D{0, Vk::ImageAspect::Color, 0, {{}, {256, 256}}} }}) .pipelineBarrier(Vk::PipelineStage::Transfer, Vk::PipelineStage::FragmentShader, { /* Make the image memory available for fragment shader sampling */ {Vk::Access::TransferWrite, Vk::Access::ShaderRead, Vk::ImageLayout::TransferDestination, Vk::ImageLayout::ShaderReadOnly, texture} });
Alternatively you can use CopyBufferToImageInfo1D / CopyImageToBufferInfo1D, CopyBufferToImageInfo2D / CopyImageToBufferInfo2D etc., as both CopyBufferToImageInfo / CopyImageToBufferInfo and BufferImageCopy (sub)classes have implicit constructors. This can be handy when uploading multiple regions — for example uploading all mip levels of an image at the same time:
cmd.copyBufferToImage(Vk::CopyBufferToImageInfo2D{ input, texture, Vk::ImageLayout::Undefined, { /* Assuming mip levels are tightly packed after each other */ { 0, Vk::ImageAspect::Color, 0, {{}, {256, 256}}}, {262144, Vk::ImageAspect::Color, 1, {{}, {128, 128}}}, {327680, Vk::ImageAspect::Color, 2, {{}, { 64, 64}}}, … } });
Image/image copy is possible as well and is done using CommandBuffer::
Vk::Image a{device, Vk::ImageCreateInfo2D{ Vk::ImageUsage::TransferSource|…, Vk::PixelFormat::RGBA8Srgb, {256, 256}, … }, …}; Vk::Image b{device, Vk::ImageCreateInfo2D{ Vk::ImageUsage::TransferDestination|…, Vk::PixelFormat::RGBA8Srgb, {256, 256}, … }, …}; … cmd.pipelineBarrier(Vk::PipelineStage::TopOfPipe, Vk::PipelineStage::Transfer, { /* Transfer both images to a layout required by the copy operation */ {Vk::Accesses{}, Vk::Access::TransferRead, Vk::ImageLayout::…, Vk::ImageLayout::TransferSource, a}, {Vk::Accesses{}, Vk::Access::TransferWrite, Vk::ImageLayout::Undefined, Vk::ImageLayout::TransferDestination, b} }) .copyImage({a, Vk::ImageLayout::TransferSource, b, Vk::ImageLayout::TransferDestination, { /* Copy the whole first layer/level between the images */ {Vk::ImageAspect::Color, 0, 0, 1, {}, 0, 0, 1, {}, {256, 256, 1}} }});
Public static functions
- static auto wrap(Device& device, VkImage handle, PixelFormat format, HandleFlags flags = {}) -> Image
- Wrap existing Vulkan handle.
-
static auto wrap(Device& device,
VkImage handle,
Magnum::
PixelFormat format, HandleFlags flags = {}) -> Image -
static auto wrap(Device& device,
VkImage handle,
Magnum::
CompressedPixelFormat format, HandleFlags flags = {}) -> Image
Constructors, destructors, conversion operators
- Image(Device& device, const ImageCreateInfo& info, NoAllocateT) explicit
- Construct an image without allocating.
- Image(Device& device, const ImageCreateInfo& info, MemoryFlags memoryFlags) explicit
- Construct an image.
- Image(NoCreateT) explicit
- Construct without creating the image.
- Image(const Image&) deleted
- Copying is not allowed.
- Image(Image&& other) noexcept
- Move constructor.
- ~Image()
- Destructor.
- operator VkImage()
Public functions
- auto operator=(const Image&) -> Image& deleted
- Copying is not allowed.
- auto operator=(Image&& other) -> Image& noexcept
- Move assignment.
- auto handle() -> VkImage
- Underlying VkImage handle.
- auto handleFlags() const -> HandleFlags
- Handle flags.
- auto format() const -> PixelFormat
- Image format.
- auto memoryRequirements() const -> MemoryRequirements
- Image memory requirements.
- void bindMemory(Memory& memory, UnsignedLong offset)
- Bind image memory.
- void bindDedicatedMemory(Memory&& memory)
- Bind a dedicated image memory.
- auto hasDedicatedMemory() const -> bool
- Whether the image has a dedicated memory.
- auto dedicatedMemory() -> Memory&
- Dedicated image memory.
- auto release() -> VkImage
- Release the underlying Vulkan image.
Function documentation
static Image Magnum:: Vk:: Image:: wrap(Device& device,
VkImage handle,
PixelFormat format,
HandleFlags flags = {})
Wrap existing Vulkan handle.
Parameters | |
---|---|
device | Vulkan device the image is created on |
handle | The VkImage handle |
format | Image format. Available through format() afterwards. |
flags | Handle flags |
The handle
is expected to be originating from device
. The format
parameter is used for convenience ImageView creation. If it's unknown, use a PixelFormat{}
— you will then be able to only create image views by passing a concrete format to ImageViewCreateInfo.
Unlike an image created using a constructor, the Vulkan image is by default not deleted on destruction, use flags
for different behavior.
static Image Magnum:: Vk:: Image:: wrap(Device& device,
VkImage handle,
Magnum:: PixelFormat format,
HandleFlags flags = {})
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
static Image Magnum:: Vk:: Image:: wrap(Device& device,
VkImage handle,
Magnum:: CompressedPixelFormat format,
HandleFlags flags = {})
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
Magnum:: Vk:: Image:: Image(Device& device,
const ImageCreateInfo& info,
NoAllocateT) explicit
Construct an image without allocating.
Parameters | |
---|---|
device | Vulkan device to create the image on |
info | Image creation info |
Use memoryRequirements(), Memory and bindMemory() to bind a memory (sub)allocation to the image.
Magnum:: Vk:: Image:: Image(Device& device,
const ImageCreateInfo& info,
MemoryFlags memoryFlags) explicit
Construct an image.
Parameters | |
---|---|
device | Vulkan device to create the image on |
info | Image creation info |
memoryFlags | Memory allocation flags |
Compared to Image(Device&, const ImageCreateInfo&, NoAllocateT) allocates a memory satisfying memoryFlags
as well.
Magnum:: Vk:: Image:: ~Image()
Destructor.
Destroys associated VkImage handle, unless the instance was created using wrap() without HandleFlag::
Magnum:: Vk:: Image:: operator VkImage()
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
MemoryRequirements Magnum:: Vk:: Image:: memoryRequirements() const
Image memory requirements.
void Magnum:: Vk:: Image:: bindMemory(Memory& memory,
UnsignedLong offset)
Bind image memory.
Assumes that memory
type, the amount of memory
at offset
and offset
alignment corresponds to image memory requirements.
void Magnum:: Vk:: Image:: bindDedicatedMemory(Memory&& memory)
Bind a dedicated image memory.
Equivalent to bindMemory() with offset
set to 0
, with the additional effect that memory
ownership transfers to the image and is then available through dedicatedMemory().
bool Magnum:: Vk:: Image:: hasDedicatedMemory() const
Whether the image has a dedicated memory.
Returns true
if the image memory was bound using bindDedicatedMemory(), false
otherwise.
Memory& Magnum:: Vk:: Image:: dedicatedMemory()
Dedicated image memory.
Expects that the image has a dedicated memory.
VkImage Magnum:: Vk:: Image:: release()
Release the underlying Vulkan image.
Releases ownership of the Vulkan image and returns its handle so vkDestroyImage() is not called on destruction. The internal state is then equivalent to moved-from state.