Skip to content

Commit

Permalink
Clarified the documentation and parameter description of the meshlet'…
Browse files Browse the repository at this point in the history
…s convert_for_gpu_usage.
  • Loading branch information
johannesugb committed May 31, 2023
1 parent 4c6e8c9 commit f5d5b0e
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 43 deletions.
88 changes: 61 additions & 27 deletions auto_vk_toolkit/include/meshlet_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,14 +236,23 @@ namespace avk

/** Converts meshlets into a GPU usable representation.
* @param aMeshlets The meshlets to convert
* @tparam T Either meshlet_gpu_data or meshlet_indirect_gpu_data. If the indirect representation is used, the meshlet data will also be returned.
* The meshlet data contains the vertex indices from [mDataOffset] to [mDataOffset + mVertexCount].
* It also contains the indices into the vertex indices, four uint8 packed into a single uint32,
* from [mDataOffset + mVertexCount] to [mDataOffset + mVertexCount + (mIndexCount+3)/4]
* @tparam T Either meshlet_gpu_data or meshlet_redirected_gpu_data.
* - meshlet_gpu_data => The output will be one vector of meshlet_gpu_data elements, and the
* second tuple element will be empty.
* - meshlet_redirected_gpu_data => Two vectors are returned: Firstly, a vector of meshlet_redirected_gpu_data elements
* which contains index offsets, and for the second tuple element a vector of meshlet indices is returned.
* Attention: The vector of indices contains two different regions:
* 1) The meshlet data contains the vertex indices from [mDataOffset .. mDataOffset+mVertexCount).
* 2) The indices into the vertex indices, where groups of four uint8_t values are packed into a single uint32_t value.
* Region 2 is stored in [mDataOffset+mVertexCount .. mDataOffset+mVertexCount+(mIndexCount+3)/4)
* The advantage of the non-redirected representation is easier handling, while the index data must be copied.
* The advantage of the redirected representation can be more compressed data, while there is another indirection.
* @tparam NV The number of vertices
* @tparam NI The number of indices
* @returns A Tuple of the converted meshlets into the provided type and the optional meshlet data when the indirect representation
* is used.
* @returns A Tuple of the following structure:
* <0>: The input meshlets, converted into the provided output meshlet type.
* If T is meshlet_redirected_gpu_data, it will contain offsets into the second tuple element:
* <1>: Meshlet indices data, if the redirected representation is used. (For more details, see description of T.)
*/
template <typename T, size_t NV, size_t NI>
std::tuple<std::vector<T>, std::optional<std::vector<uint32_t>>> convert_for_gpu_usage(const std::vector<meshlet>& aMeshlets)
Expand Down Expand Up @@ -285,13 +294,21 @@ namespace avk

/** Converts meshlets into a GPU usable representation.
* @param aMeshlets The meshlets to convert
* @tparam T Either meshlet_gpu_data or meshlet_indirect_gpu_data. If the indirect representation is used, the meshlet data will also be returned.
* The meshlet data contains the vertex indices from [mDataOffset] to [mDataOffset + mVertexCount].
* It also contains the indices into the vertex indices, four uint8 packed into a single uint32,
* from [mDataOffset + mVertexCount] to [mDataOffset + mVertexCount + (mIndexCount+3)/4]
* T must provide static members ::sNumVertices and ::sNumIndices
* @returns A Tuple of the converted meshlets into the provided type and the optional meshlet data when the indirect representation
* is used.
* @tparam T Either meshlet_gpu_data or meshlet_redirected_gpu_data.
* - meshlet_gpu_data => The output will be one vector of meshlet_gpu_data elements, and the
* second tuple element will be empty.
* - meshlet_redirected_gpu_data => Two vectors are returned: Firstly, a vector of meshlet_redirected_gpu_data elements
* which contains index offsets, and for the second tuple element a vector of meshlet indices is returned.
* Attention: The vector of indices contains two different regions:
* 1) The meshlet data contains the vertex indices from [mDataOffset .. mDataOffset+mVertexCount).
* 2) The indices into the vertex indices, where groups of four uint8_t values are packed into a single uint32_t value.
* Region 2 is stored in [mDataOffset+mVertexCount .. mDataOffset+mVertexCount+(mIndexCount+3)/4)
* The advantage of the non-redirected representation is easier handling, while the index data must be copied.
* The advantage of the redirected representation can be more compressed data, while there is another indirection.
* @returns A Tuple of the following structure:
* <0>: The input meshlets, converted into the provided output meshlet type.
* If T is meshlet_redirected_gpu_data, it will contain offsets into the second tuple element:
* <1>: Meshlet indices data, if the redirected representation is used. (For more details, see description of T.)
*/
template <typename T> requires has_static_num_vertices_and_num_indices<T>
std::tuple<std::vector<T>, std::optional<std::vector<uint32_t>>> convert_for_gpu_usage(const std::vector<meshlet>& aMeshlets)
Expand All @@ -302,14 +319,23 @@ namespace avk
/** Converts meshlets into a GPU usable representation.
* @param aSerializer The serializer for the meshlet gpu data.
* @param aMeshlets The meshlets to convert
* @tparam T Either meshlet_gpu_data or meshlet_indirect_gpu_data. If the indirect representation is used, the meshlet data will also be returned.
* The meshlet data contains the vertex indices from [mDataOffset] to [mDataOffset + mVertexCount].
* It also contains the indices into the vertex indices, four uint8 packed into a single uint32,
* from [mDataOffset + mVertexCount] to [mDataOffset + mVertexCount + (mIndexCount+3)/4]
* @tparam T Either meshlet_gpu_data or meshlet_redirected_gpu_data.
* - meshlet_gpu_data => The output will be one vector of meshlet_gpu_data elements, and the
* second tuple element will be empty.
* - meshlet_redirected_gpu_data => Two vectors are returned: Firstly, a vector of meshlet_redirected_gpu_data elements
* which contains index offsets, and for the second tuple element a vector of meshlet indices is returned.
* Attention: The vector of indices contains two different regions:
* 1) The meshlet data contains the vertex indices from [mDataOffset .. mDataOffset+mVertexCount).
* 2) The indices into the vertex indices, where groups of four uint8_t values are packed into a single uint32_t value.
* Region 2 is stored in [mDataOffset+mVertexCount .. mDataOffset+mVertexCount+(mIndexCount+3)/4)
* The advantage of the non-redirected representation is easier handling, while the index data must be copied.
* The advantage of the redirected representation can be more compressed data, while there is another indirection.
* @tparam NV The number of vertices
* @tparam NI The number of indices
* @returns A Tuple of the converted meshlets into the provided type and the optional meshlet data when the indirect representation
* is used.
* @tparam NI The number of indices
* @returns A Tuple of the following structure:
* <0>: The input meshlets, converted into the provided output meshlet type.
* If T is meshlet_redirected_gpu_data, it will contain offsets into the second tuple element:
* <1>: Meshlet indices data, if the redirected representation is used. (For more details, see description of T.)
*/
template <typename T, size_t NV, size_t NI>
std::tuple<std::vector<T>, std::optional<std::vector<uint32_t>>> convert_for_gpu_usage_cached(serializer& aSerializer, const std::vector<meshlet>& aMeshlets)
Expand Down Expand Up @@ -341,13 +367,21 @@ namespace avk
/** Converts meshlets into a GPU usable representation.
* @param aSerializer The serializer for the meshlet gpu data.
* @param aMeshlets The meshlets to convert
* @tparam T Either meshlet_gpu_data or meshlet_indirect_gpu_data. If the indirect representation is used, the meshlet data will also be returned.
* The meshlet data contains the vertex indices from [mDataOffset] to [mDataOffset + mVertexCount].
* It also contains the indices into the vertex indices, four uint8 packed into a single uint32,
* from [mDataOffset + mVertexCount] to [mDataOffset + mVertexCount + (mIndexCount+3)/4].
* T must provide static members ::sNumVertices and ::sNumIndices
* @returns A Tuple of the converted meshlets into the provided type and the optional meshlet data when the indirect representation
* is used.
* @tparam T Either meshlet_gpu_data or meshlet_redirected_gpu_data.
* - meshlet_gpu_data => The output will be one vector of meshlet_gpu_data elements, and the
* second tuple element will be empty.
* - meshlet_redirected_gpu_data => Two vectors are returned: Firstly, a vector of meshlet_redirected_gpu_data elements
* which contains index offsets, and for the second tuple element a vector of meshlet indices is returned.
* Attention: The vector of indices contains two different regions:
* 1) The meshlet data contains the vertex indices from [mDataOffset .. mDataOffset+mVertexCount).
* 2) The indices into the vertex indices, where groups of four uint8_t values are packed into a single uint32_t value.
* Region 2 is stored in [mDataOffset+mVertexCount .. mDataOffset+mVertexCount+(mIndexCount+3)/4)
* The advantage of the non-redirected representation is easier handling, while the index data must be copied.
* The advantage of the redirected representation can be more compressed data, while there is another indirection.
* @returns A Tuple of the following structure:
* <0>: The input meshlets, converted into the provided output meshlet type.
* If T is meshlet_redirected_gpu_data, it will contain offsets into the second tuple element:
* <1>: Meshlet indices data, if the redirected representation is used. (For more details, see description of T.)
*/
template <typename T> requires has_static_num_vertices_and_num_indices<T>
std::tuple<std::vector<T>, std::optional<std::vector<uint32_t>>> convert_for_gpu_usage_cached(serializer& aSerializer, const std::vector<meshlet>& aMeshlets)
Expand Down
2 changes: 2 additions & 0 deletions examples/skinned_meshlets/shaders/meshlet.mesh
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ void main()
uint modelIdx = meshletsBuffer.mValues[meshletIndex].mModelIndex;
uint texelBufferIndex = meshletsBuffer.mValues[meshletIndex].mTexelBufferIndex;
#if USE_REDIRECTED_GPU_DATA
// Note: There is another set of indices contained in the indicesBuffers, which starts at an offset of vertexCount.
// For more details, see meshlet_helpers.hpp!
uint indexOffset = uint(meshletsBuffer.mValues[meshletIndex].mGeometry.mDataOffset + vertexCount);
#endif

Expand Down
10 changes: 6 additions & 4 deletions examples/skinned_meshlets/shaders/meshlet.nv.mesh
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ void main()
uint modelIdx = meshletsBuffer.mValues[meshletIndex].mModelIndex;
uint texelBufferIndex = meshletsBuffer.mValues[meshletIndex].mTexelBufferIndex;
#if USE_REDIRECTED_GPU_DATA
// Note: There is another set of indices contained in the indicesBuffers, which starts at an offset of vertexCount.
// For more details, see meshlet_helpers.hpp!
uint indexOffset = uint(meshletsBuffer.mValues[meshletIndex].mGeometry.mDataOffset + vertexCount);
#endif

Expand All @@ -120,7 +122,7 @@ void main()
{
// Get the vertex index:
#if !USE_REDIRECTED_GPU_DATA
uint vi = meshletsBuffer.values[meshletIndex].mGeometry.mVertices[i];
uint vi = meshletsBuffer.mValues[meshletIndex].mGeometry.mVertices[i];
#else
uint vi = uint(indicesBuffers[texelBufferIndex].mIndices[int(meshletsBuffer.mValues[meshletIndex].mGeometry.mDataOffset + i)]);
#endif
Expand Down Expand Up @@ -177,9 +179,9 @@ void main()
// Write for each triangle, also note the NUM_MESH_SHADER_INVOCATIONS stepping
for (uint i = invocationId; i < triangleCount; i += NUM_MESH_SHADER_INVOCATIONS)
{
gl_PrimitiveIndicesNV[i*3 + 0] = uint(meshletsBuffer.values[meshletIndex].mGeometry.mIndices[i * 3 + 0]);
gl_PrimitiveIndicesNV[i*3 + 1] = uint(meshletsBuffer.values[meshletIndex].mGeometry.mIndices[i * 3 + 1]);
gl_PrimitiveIndicesNV[i*3 + 2] = uint(meshletsBuffer.values[meshletIndex].mGeometry.mIndices[i * 3 + 2]);
gl_PrimitiveIndicesNV[i*3 + 0] = uint(meshletsBuffer.mValues[meshletIndex].mGeometry.mIndices[i * 3 + 0]);
gl_PrimitiveIndicesNV[i*3 + 1] = uint(meshletsBuffer.mValues[meshletIndex].mGeometry.mIndices[i * 3 + 1]);
gl_PrimitiveIndicesNV[i*3 + 2] = uint(meshletsBuffer.mValues[meshletIndex].mGeometry.mIndices[i * 3 + 2]);
}
#else // USE_REDIRECTED_GPU_DATA
// Here we have the indices packed into an uint, so we can write each of the uints at once:
Expand Down
24 changes: 12 additions & 12 deletions examples/skinned_meshlets/source/skinned_meshlets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class skinned_meshlets_app : public avk::invokee
avk::buffer mBoneIndicesBuffer;
avk::buffer mBoneWeightsBuffer;
#if USE_REDIRECTED_GPU_DATA
avk::buffer mMeshletDataBuffer;
avk::buffer mIndicesDataBuffer;
#endif

glm::mat4 mModelMatrix;
Expand All @@ -62,7 +62,7 @@ class skinned_meshlets_app : public avk::invokee
std::vector<glm::uvec4> mBoneIndices;
std::vector<glm::vec4> mBoneWeights;
#if USE_REDIRECTED_GPU_DATA
std::vector<uint32_t> mMeshletData;
std::vector<uint32_t> mIndicesData;
#endif

glm::mat4 mModelMatrix;
Expand Down Expand Up @@ -149,9 +149,9 @@ class skinned_meshlets_app : public avk::invokee
);

#if USE_REDIRECTED_GPU_DATA
drawCall.mMeshletDataBuffer = avk::context().create_buffer(avk::memory_usage::device, {},
avk::vertex_buffer_meta::create_from_data(drawCallData.mMeshletData),
avk::storage_buffer_meta::create_from_data(drawCallData.mMeshletData)
drawCall.mIndicesDataBuffer = avk::context().create_buffer(avk::memory_usage::device, {},
avk::vertex_buffer_meta::create_from_data(drawCallData.mIndicesData),
avk::storage_buffer_meta::create_from_data(drawCallData.mIndicesData)
);
#endif

Expand All @@ -174,7 +174,7 @@ class skinned_meshlets_app : public avk::invokee
drawCall.mBoneIndicesBuffer->fill(drawCallData.mBoneIndices.data(), 0),
drawCall.mBoneWeightsBuffer->fill(drawCallData.mBoneWeights.data(), 0)
#if USE_REDIRECTED_GPU_DATA
, drawCall.mMeshletDataBuffer->fill(drawCallData.mMeshletData.data(), 0)
, drawCall.mIndicesDataBuffer->fill(drawCallData.mIndicesData.data(), 0)
#endif
}, *mQueue)->wait_until_signalled();

Expand All @@ -183,7 +183,7 @@ class skinned_meshlets_app : public avk::invokee
mNormalBuffers.push_back(avk::context().create_buffer_view(drawCall.mNormalsBuffer));
mTexCoordsBuffers.push_back(avk::context().create_buffer_view(drawCall.mTexCoordsBuffer));
#if USE_REDIRECTED_GPU_DATA
mMeshletDataBuffers.push_back(drawCall.mMeshletDataBuffer);
mIndicesDataBuffers.push_back(drawCall.mIndicesDataBuffer);
#endif
mBoneIndicesBuffers.push_back(avk::context().create_buffer_view(drawCall.mBoneIndicesBuffer));
mBoneWeightsBuffers.push_back(avk::context().create_buffer_view(drawCall.mBoneWeightsBuffer));
Expand Down Expand Up @@ -290,11 +290,11 @@ class skinned_meshlets_app : public avk::invokee
#else
#if USE_CACHE
avk::serializer serializer("redirected_meshlets-" + meshname + "-" + std::to_string(mpos) + ".cache");
auto [gpuMeshlets, generatedMeshletData] = avk::convert_for_gpu_usage_cached<avk::meshlet_redirected_gpu_data, sNumVertices, sNumIndices>(serializer, cpuMeshlets);
auto [gpuMeshlets, gpuIndicesData] = avk::convert_for_gpu_usage_cached<avk::meshlet_redirected_gpu_data, sNumVertices, sNumIndices>(serializer, cpuMeshlets);
#else
auto [gpuMeshlets, generatedMeshletData] = avk::convert_for_gpu_usage<avk::meshlet_redirected_gpu_data, sNumVertices, sNumIndices>(cpuMeshlets);
#endif
drawCallData.mMeshletData = std::move(generatedMeshletData.value());
drawCallData.mIndicesData = std::move(gpuIndicesData.value());
#endif

// fill our own meshlets with the loaded/generated data
Expand Down Expand Up @@ -417,7 +417,7 @@ class skinned_meshlets_app : public avk::invokee
avk::descriptor_binding(3, 2, avk::as_uniform_texel_buffer_views(mNormalBuffers)),
avk::descriptor_binding(3, 3, avk::as_uniform_texel_buffer_views(mTexCoordsBuffers)),
#if USE_REDIRECTED_GPU_DATA
avk::descriptor_binding(3, 4, avk::as_storage_buffers(mMeshletDataBuffers)),
avk::descriptor_binding(3, 4, avk::as_storage_buffers(mIndicesDataBuffers)),
#endif
avk::descriptor_binding(3, 5, avk::as_uniform_texel_buffer_views(mBoneIndicesBuffers)),
avk::descriptor_binding(3, 6, avk::as_uniform_texel_buffer_views(mBoneWeightsBuffers)),
Expand Down Expand Up @@ -610,7 +610,7 @@ class skinned_meshlets_app : public avk::invokee
descriptor_binding(3, 2, as_uniform_texel_buffer_views(mNormalBuffers)),
descriptor_binding(3, 3, as_uniform_texel_buffer_views(mTexCoordsBuffers)),
#if USE_REDIRECTED_GPU_DATA
descriptor_binding(3, 4, avk::as_storage_buffers(mMeshletDataBuffers)),
descriptor_binding(3, 4, avk::as_storage_buffers(mIndicesDataBuffers)),
#endif
descriptor_binding(3, 5, as_uniform_texel_buffer_views(mBoneIndicesBuffers)),
descriptor_binding(3, 6, as_uniform_texel_buffer_views(mBoneWeightsBuffers)),
Expand Down Expand Up @@ -670,7 +670,7 @@ class skinned_meshlets_app : public avk::invokee
std::vector<avk::buffer_view> mBoneWeightsBuffers;
std::vector<avk::buffer_view> mBoneIndicesBuffers;
#if USE_REDIRECTED_GPU_DATA
std::vector<avk::buffer> mMeshletDataBuffers;
std::vector<avk::buffer> mIndicesDataBuffers;
#endif

bool mHighlightMeshlets = false;
Expand Down

0 comments on commit f5d5b0e

Please sign in to comment.