class new in Git master
#include <Magnum/Vk/Mesh.h>
Mesh Mesh.
Connects MeshLayout with concrete vertex/index Buffer instances and manages related information such as vertex or instance count.
Populating a mesh
Continuing from the mesh layout setup, the Mesh gets concrete buffers bound using addVertexBuffer() and vertex count specified with setCount():
Vk::MeshLayout meshLayout{MeshPrimitive::Triangles}; meshLayout .addBinding(Binding, 8*sizeof(Float)) .addAttribute(PositionLocation, Binding, VertexFormat::Vector3, 0) .addAttribute(TextureLocation, Binding, VertexFormat::Vector2, 3*sizeof(Float)) .addAttribute(NormalLocation, Binding, VertexFormat::Vector3, 5*sizeof(Float)); Vk::Buffer vertices{…, Vk::BufferCreateInfo{ Vk::BufferUsage::VertexBuffer, vertexCount*8*sizeof(Float) }, …}; … Vk::Mesh mesh{meshLayout}; mesh.addVertexBuffer(Binding, vertices, 0) .setCount(vertexCount);
For an indexed mesh, the index buffer can be specified via setIndexBuffer(). With an index buffer present, setCount() then describes count of indices, instead of vertices:
Vk::Buffer indices{…, Vk::BufferCreateInfo{ Vk::BufferUsage::IndexBuffer, indexCount*sizeof(UnsignedShort) }, …}; … mesh.setIndexBuffer(indices, 0, MeshIndexType::UnsignedShort) .setCount(indexCount);
Transferring buffer and layout ownership
To simplify resource management, it's possible to have the Buffer instances owned by the Mesh, as well as the MeshLayout, either using std::
Vk::Buffer buffer{…, Vk::BufferCreateInfo{ Vk::BufferUsage::VertexBuffer|Vk::BufferUsage::IndexBuffer, … }, …}; … Vk::Mesh mesh{Vk::MeshLayout{MeshPrimitive::Triangles} .addBinding(…) … }; mesh.addVertexBuffer(…, buffer, …) .setIndexBuffer(std::move(buffer), …) .setCount(…);
Drawing a mesh
Assuming a rasterization pipeline with the same MeshLayout was bound, a mesh can be then drawn using CommandBuffer::
Vk::Mesh mesh{…}; Vk::Pipeline pipeline{…, Vk::RasterizationPipelineCreateInfo{ …, mesh.layout(), … }… }; … cmd.bindPipeline(pipeline) .draw(mesh);
Dynamic pipeline state
Both the MeshPrimitive set in MeshLayout constructor and binding stride set in MeshLayout::
Taking this to the extreme, with these two dynamic states and a dedicated binding for each attribute you can make the pipeline accept basically any mesh as long as just the attribute locations and types are the same — offsets and strided of particular attributes are then fully dynamic.
/* Use zero stride and zero offsets, as the stride gets specified dynamically and offsets specified in concrete buffer bindings instead */ Vk::MeshLayout dynamicMeshLayout{MeshPrimitive::Triangles}; dynamicMeshLayout .addBinding(0, 0) .addBinding(1, 0) .addBinding(2, 0) .addAttribute(PositionLocation, 0, VertexFormat::Vector3, 0) .addAttribute(TextureLocation, 1, VertexFormat::Vector2, 0) .addAttribute(NormalLocation, 2, VertexFormat::Vector3, 0); Vk::Pipeline pipeline{…, Vk::RasterizationPipelineCreateInfo{ …, dynamicMeshLayout, …} /* Enable dynamic primitive and stride */ .setDynamicStates(Vk::DynamicRasterizationState::MeshPrimitive| Vk::DynamicRasterizationState::VertexInputBindingStride) … }; Vk::Buffer vertices{…}; Vk::Mesh mesh{Vk::MeshLayout{MeshPrimitive::Triangles} /* Or TriangleStrip etc */ /* Concrete stride */ .addBinding(0, 8*sizeof(Float)) .addBinding(1, 8*sizeof(Float)) .addBinding(2, 8*sizeof(Float)) /* Rest the same as in the dynamicMeshLayout */ .addAttribute(PositionLocation, 0, VertexFormat::Vector3, 0) .addAttribute(TextureLocation, 1, VertexFormat::Vector2, 0) .addAttribute(NormalLocation, 2, VertexFormat::Vector3, 0) }; /* Bind the same buffer to three different bindings, with concrete offsets */ mesh.addVertexBuffer(0, vertices, 0) .addVertexBuffer(1, vertices, 3*sizeof(Float)) .addVertexBuffer(2, vertices, 5*sizeof(Float)) .setCount(…); cmd.bindPipeline(pipeline) /* Updates the dynamic primitive and stride as needed by the mesh */ .draw(mesh);
Constructors, destructors, conversion operators
- Mesh(const MeshLayout& layout) explicit
- Construct with a reference to external MeshLayout.
- Mesh(MeshLayout&& layout) explicit
- Construct with taking over MeshLayout ownership.
- Mesh(const Mesh&) deleted
- Copying is not allowed.
- Mesh(Mesh&&) noexcept
- Move constructor.
- ~Mesh()
- Destructor.
Public functions
- auto operator=(const Mesh&) -> Mesh& deleted
- Copying is not allowed.
- auto operator=(Mesh&&) -> Mesh& noexcept
- Move assignment.
- auto count() const -> UnsignedInt
- Vertex/index count.
- auto setCount(UnsignedInt count) -> Mesh&
- Set vertex/index count.
- auto vertexOffset() const -> UnsignedInt
- Vertex offset.
- auto setVertexOffset(UnsignedInt offset) -> Mesh&
- Set vertex offset.
- auto indexOffset() const -> UnsignedInt
- Index offset.
- auto setIndexOffset(UnsignedInt offset) -> Mesh&
- Set index offset.
- auto instanceCount() const -> UnsignedInt
- Instance count.
- auto setInstanceCount(UnsignedInt count) -> Mesh&
- Set instance count.
- auto instanceOffset() const -> UnsignedInt
- Instance offset.
- auto setInstanceOffset(UnsignedInt offset) -> Mesh&
- Set instance offset.
- auto addVertexBuffer(UnsignedInt binding, VkBuffer buffer, UnsignedLong offset) -> Mesh&
- Add a vertex buffer.
- auto addVertexBuffer(UnsignedInt binding, Buffer&& buffer, UnsignedLong offset) -> Mesh&
- Add a vertex buffer and take over its ownership.
- auto setIndexBuffer(VkBuffer buffer, UnsignedLong offset, MeshIndexType indexType) -> Mesh&
- Set an index buffer.
-
auto setIndexBuffer(VkBuffer buffer,
UnsignedLong offset,
Magnum::
MeshIndexType indexType) -> Mesh& - Set an index buffer with a generic index type.
- auto setIndexBuffer(Buffer&& buffer, UnsignedLong offset, MeshIndexType indexType) -> Mesh&
- Set an index buffer and take over its ownership.
-
auto setIndexBuffer(Buffer&& buffer,
UnsignedLong offset,
Magnum::
MeshIndexType indexType) -> Mesh& - Set an index buffer with a generic index type and take over its ownership.
- auto layout() const -> const MeshLayout&
- Layout of this mesh.
-
auto vertexBuffers() -> Containers::
ArrayView<const VkBuffer> - Vertex buffers.
-
auto vertexBufferOffsets() const -> Containers::
ArrayView<const UnsignedLong> - Vertex buffer offsets.
-
auto vertexBufferStrides() const -> Containers::
ArrayView<const UnsignedLong> - Vertex buffer strides.
- auto isIndexed() const -> bool
- Whether the mesh is indexed.
- auto indexBuffer() -> VkBuffer
- Index buffer.
- auto indexBufferOffset() const -> UnsignedLong
- Index buffer offset.
- auto indexType() const -> MeshIndexType
- Index type.
Function documentation
Magnum:: Vk:: Mesh:: Mesh(const MeshLayout& layout) explicit
Construct with a reference to external MeshLayout.
Assumes layout
stays in scope for the whole lifetime of the Mesh instance.
Magnum:: Vk:: Mesh:: ~Mesh()
Destructor.
If any buffers were added using addVertexBuffer(UnsignedInt, Buffer&&, UnsignedLong) or setIndexBuffer(Buffer&&, UnsignedLong, MeshIndexType), their owned instanced are destructed at this point.
Mesh& Magnum:: Vk:: Mesh:: setCount(UnsignedInt count)
Set vertex/index count.
Returns | Reference to self (for method chaining) |
---|
If the mesh is indexed, the value is treated as index count, otherwise the value is vertex count. If set to 0
, no draw commands are issued when calling CommandBuffer::
Mesh& Magnum:: Vk:: Mesh:: setVertexOffset(UnsignedInt offset)
Set vertex offset.
Returns | Reference to self (for method chaining) |
---|
For non-indexed meshes specifies the first vertex that will be drawn, for indexed meshes specifies the offset added to each index. Default is 0
.
Mesh& Magnum:: Vk:: Mesh:: setIndexOffset(UnsignedInt offset)
Set index offset.
Returns | Reference to self (for method chaining) |
---|
Expects that the mesh is indexed. Specifies the first index that will be drawn. Default is 0
.
Mesh& Magnum:: Vk:: Mesh:: setInstanceCount(UnsignedInt count)
Set instance count.
Returns | Reference to self (for method chaining) |
---|
If set to 0
, no draw commands are issued when calling CommandBuffer::1
.
Mesh& Magnum:: Vk:: Mesh:: setInstanceOffset(UnsignedInt offset)
Set instance offset.
Returns | Reference to self (for method chaining) |
---|
Specifies the first instance that will be drawn. Default is 0
.
Mesh& Magnum:: Vk:: Mesh:: addVertexBuffer(UnsignedInt binding,
VkBuffer buffer,
UnsignedLong offset)
Add a vertex buffer.
Parameters | |
---|---|
binding | Binding corresponding to a particular MeshLayout:: |
buffer | A Buffer instance or a raw Vulkan buffer handle. Expected to have been created with BufferUsage:: |
offset | Offset into the buffer, in bytes |
Returns | Reference to self (for method chaining) |
Mesh& Magnum:: Vk:: Mesh:: addVertexBuffer(UnsignedInt binding,
Buffer&& buffer,
UnsignedLong offset)
Add a vertex buffer and take over its ownership.
Returns | Reference to self (for method chaining) |
---|
Compared to addVertexBuffer(UnsignedInt, VkBuffer, UnsignedLong) the buffer
instance ownership is transferred to the class and thus doesn't have to be managed separately.
Mesh& Magnum:: Vk:: Mesh:: setIndexBuffer(VkBuffer buffer,
UnsignedLong offset,
MeshIndexType indexType)
Set an index buffer.
Parameters | |
---|---|
buffer | A Buffer instance or a raw Vulkan buffer handle. Expected to have been created with BufferUsage:: |
offset | Offset into the buffer, in bytes |
indexType | Index type |
Returns | Reference to self (for method chaining) |
Mesh& Magnum:: Vk:: Mesh:: setIndexBuffer(VkBuffer buffer,
UnsignedLong offset,
Magnum:: MeshIndexType indexType)
Set an index buffer with a generic index type.
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. Note that implementation-specific values are passed as-is with meshIndexTypeUnwrap(). It's the user responsibility to ensure an implementation-specific actually represents a valid Vulkan index type.
Mesh& Magnum:: Vk:: Mesh:: setIndexBuffer(Buffer&& buffer,
UnsignedLong offset,
MeshIndexType indexType)
Set an index buffer and take over its ownership.
Returns | Reference to self (for method chaining) |
---|
Compared to setIndexBuffer(VkBuffer, UnsignedLong, MeshIndexType) the buffer
instance ownership is transferred to the class and thus doesn't have to be managed separately.
Mesh& Magnum:: Vk:: Mesh:: setIndexBuffer(Buffer&& buffer,
UnsignedLong offset,
Magnum:: MeshIndexType indexType)
Set an index buffer with a generic index type and take over its ownership.
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. Note that implementation-specific values are passed as-is with meshIndexTypeUnwrap(). It's the user responsibility to ensure an implementation-specific actually represents a valid Vulkan index type.
Containers:: ArrayView<const VkBuffer> Magnum:: Vk:: Mesh:: vertexBuffers()
Vertex buffers.
Has the same length as the vertex buffer binding array in layout(), the buffers correspond to binding IDs at the same index.
Containers:: ArrayView<const UnsignedLong> Magnum:: Vk:: Mesh:: vertexBufferOffsets() const
Vertex buffer offsets.
Has the same length as the vertex buffer binding array in layout(), offsets correspond to vertexBuffers() at the same index.
Containers:: ArrayView<const UnsignedLong> Magnum:: Vk:: Mesh:: vertexBufferStrides() const
Vertex buffer strides.
Has the same length as the vertex buffer binding array in layout(). The strides are the same as strides in the layout at the same index, but here in a form that's usable by vkCmdBindVertexBuffers2() if DynamicRasterizationState::
bool Magnum:: Vk:: Mesh:: isIndexed() const
Whether the mesh is indexed.
The mesh is considered indexed if setIndexBuffer() was called.
UnsignedLong Magnum:: Vk:: Mesh:: indexBufferOffset() const
Index buffer offset.
Expects that the mesh is indexed.