/* Copyright (c) 2017-2026 Hans-Kristian Arntzen * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #include namespace Granite { class FileMapping; } namespace Vulkan { class CommandBuffer; class Buffer; } namespace Vulkan { // MESHLET1 format. namespace Meshlet { static constexpr unsigned MaxStreams = 8; static constexpr unsigned MaxElements = 32; static constexpr unsigned ChunkFactor = 256 / MaxElements; struct Stream { union { uint32_t base_value[2]; struct { uint32_t prim_count; uint32_t vert_count; } counts; } u; uint32_t bits; uint32_t offset_in_words; }; static_assert(sizeof(Stream) == 16, "Unexpected Stream size."); struct RuntimeHeaderEncoded { uint32_t stream_offset; }; struct RuntimeHeaderDecoded { uint32_t primitive_offset; uint32_t vertex_offset; uint32_t primitive_count; uint32_t vertex_count; }; struct RuntimeHeaderDecodedMDI { uint32_t indexCount; uint32_t firstIndex; int32_t vertexOffset; }; struct Bound { float center[3]; float radius; float cone_axis_cutoff[4]; }; enum class StreamType { Primitive = 0, // RGB8_UINT (fixed 5-bit encoding, fixed base value of 0) Position, // RGB16_SINT * 2^aux NormalTangentOct8, // Octahedron encoding in RG8, BA8 for tangent. Following uvec4 encodes 1-bit sign. UV, // (0.5 * (R16G16_SINT * 2^aux) + 0.5 BoneIndices, // RGBA8_UINT BoneWeights, // RGBA8_UNORM }; enum class MeshStyle : uint32_t { Wireframe = 0, // Primitive + Position Textured, // Untextured + TangentOct8 + UV Skinned // Textured + Bone* }; struct FormatHeader { MeshStyle style; uint32_t stream_count; uint32_t meshlet_count; uint32_t payload_size_words; }; using PayloadWord = uint32_t; struct MeshView { const FormatHeader *format_header; const Bound *bounds; const Bound *bounds_256; const Stream *streams; const PayloadWord *payload; uint32_t total_primitives; uint32_t total_vertices; uint32_t num_bounds; uint32_t num_bounds_256; }; static const char magic[8] = { 'M', 'E', 'S', 'H', 'L', 'E', 'T', '4' }; MeshView create_mesh_view(const Granite::FileMapping &mapping); enum DecodeModeFlagBits : uint32_t { DECODE_MODE_UNROLLED_MESH = 1 << 0, DECODE_MODE_INDEX_16 = 1 << 1, }; using DecodeModeFlags = uint32_t; enum class RuntimeStyle { MDI, Meshlet }; struct DecodeInfo { const Vulkan::Buffer *ibo, *streams[3], *indirect, *payload; DecodeModeFlags flags; MeshStyle target_style; RuntimeStyle runtime_style; struct { uint32_t primitive_offset; uint32_t vertex_offset; } push; uint32_t indirect_offset; }; bool decode_mesh(Vulkan::CommandBuffer &cmd, const DecodeInfo &decode_info, const MeshView &view); } }