diff --git a/tools/opacitymapfuzz.cpp b/tools/opacitymapfuzz.cpp new file mode 100644 index 000000000..25df76ff1 --- /dev/null +++ b/tools/opacitymapfuzz.cpp @@ -0,0 +1,74 @@ +#include "../src/meshoptimizer.h" + +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FuzzedDataProvider fdp(data, size); + + uint32_t vertex_count = fdp.ConsumeIntegralInRange(1, 1024); + uint32_t index_count = fdp.ConsumeIntegralInRange(3, 3072); + index_count = (index_count / 3) * 3; + + if (fdp.remaining_bytes() < (vertex_count * 2 * sizeof(float) + index_count * sizeof(uint32_t))) { + return 0; + } + + std::vector vertex_uvs(vertex_count * 2); + for (size_t i = 0; i < vertex_uvs.size(); ++i) { + vertex_uvs[i] = fdp.ConsumeFloatingPoint(); + } + + std::vector indices(index_count); + for (size_t i = 0; i < index_count; ++i) { + indices[i] = fdp.ConsumeIntegralInRange(0, vertex_count - 1); + } + + uint32_t texture_width = fdp.ConsumeIntegralInRange(1, 512); + uint32_t texture_height = fdp.ConsumeIntegralInRange(1, 512); + int max_level = fdp.ConsumeIntegralInRange(0, 4); + float target_edge = fdp.ConsumeFloatingPointInRange(0.0f, 10.0f); + + size_t triangle_count = index_count / 3; + std::vector levels(triangle_count); + std::vector sources(triangle_count); + std::vector omm_indices(triangle_count); + + size_t omm_count = meshopt_opacityMapMeasure(levels.data(), sources.data(), omm_indices.data(), indices.data(), index_count, vertex_uvs.data(), vertex_count, 2 * sizeof(float), texture_width, texture_height, max_level, target_edge); + + if (omm_count > 0 && fdp.remaining_bytes() > 0) { + int states = fdp.ConsumeBool() ? 2 : 4; + + // Rasterize some maps + std::vector texture_data(texture_width * texture_height, 128); + size_t total_omm_size = 0; + for (size_t i = 0; i < omm_count; ++i) { + total_omm_size += meshopt_opacityMapEntrySize(levels[i], states); + } + + if (total_omm_size < 1000000) { // Limit memory usage + std::vector omm_data(total_omm_size); + std::vector offsets(omm_count); + size_t current_offset = 0; + + for (size_t i = 0; i < omm_count; ++i) { + offsets[i] = (unsigned int)current_offset; + + unsigned int tri_idx = sources[i]; + float uv0[2] = {vertex_uvs[indices[tri_idx * 3 + 0] * 2 + 0], vertex_uvs[indices[tri_idx * 3 + 0] * 2 + 1]}; + float uv1[2] = {vertex_uvs[indices[tri_idx * 3 + 1] * 2 + 0], vertex_uvs[indices[tri_idx * 3 + 1] * 2 + 1]}; + float uv2[2] = {vertex_uvs[indices[tri_idx * 3 + 2] * 2 + 0], vertex_uvs[indices[tri_idx * 3 + 2] * 2 + 1]}; + + meshopt_opacityMapRasterize(omm_data.data() + current_offset, levels[i], states, uv0, uv1, uv2, texture_data.data(), 1, texture_width, texture_width, texture_height); + + current_offset += meshopt_opacityMapEntrySize(levels[i], states); + } + + // Compact + meshopt_opacityMapCompact(omm_data.data(), total_omm_size, levels.data(), offsets.data(), omm_count, omm_indices.data(), triangle_count, states); + } + } + + return 0; +} diff --git a/tools/optimizefuzz.cpp b/tools/optimizefuzz.cpp new file mode 100644 index 000000000..c04ed9fbf --- /dev/null +++ b/tools/optimizefuzz.cpp @@ -0,0 +1,71 @@ +#include "../src/meshoptimizer.h" + +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FuzzedDataProvider fdp(data, size); + + uint32_t vertex_count = fdp.ConsumeIntegralInRange(1, 1024); + uint32_t index_count = fdp.ConsumeIntegralInRange(1, 3072); + index_count = (index_count / 3) * 3; + + if (fdp.remaining_bytes() < (vertex_count * 3 * sizeof(float) + index_count * sizeof(uint32_t))) { + return 0; + } + + std::vector vertex_positions(vertex_count * 3); + for (size_t i = 0; i < vertex_positions.size(); ++i) { + vertex_positions[i] = fdp.ConsumeFloatingPoint(); + } + + std::vector indices(index_count); + for (size_t i = 0; i < indices.size(); ++i) { + indices[i] = fdp.ConsumeIntegralInRange(0, vertex_count - 1); + } + + std::vector destination(index_count); + + // Vertex cache optimization + meshopt_optimizeVertexCache(destination.data(), indices.data(), index_count, vertex_count); + meshopt_optimizeVertexCacheFifo(destination.data(), indices.data(), index_count, vertex_count, 16); + meshopt_optimizeVertexCacheStrip(destination.data(), indices.data(), index_count, vertex_count); + + // Overdraw optimization + float threshold = fdp.ConsumeFloatingPointInRange(1.0f, 1.1f); + meshopt_optimizeOverdraw(destination.data(), indices.data(), index_count, vertex_positions.data(), vertex_count, 3 * sizeof(float), threshold); + + // Vertex fetch optimization + std::vector vertices_dest(vertex_count * 3); + meshopt_optimizeVertexFetch(vertices_dest.data(), indices.data(), index_count, vertex_positions.data(), vertex_count, 3 * sizeof(float)); + + // Overdraw/Coverage Analysis + meshopt_analyzeOverdraw(indices.data(), index_count, vertex_positions.data(), vertex_count, 3 * sizeof(float)); + meshopt_analyzeCoverage(indices.data(), index_count, vertex_positions.data(), vertex_count, 3 * sizeof(float)); + + // Stripifier + if (fdp.ConsumeBool()) { + uint32_t restart_index = fdp.ConsumeIntegral(); + std::vector strip(meshopt_stripifyBound(index_count)); + size_t strip_size = meshopt_stripify(strip.data(), indices.data(), index_count, vertex_count, restart_index); + + std::vector unstrip(meshopt_unstripifyBound(strip_size)); + meshopt_unstripify(unstrip.data(), strip.data(), strip_size, restart_index); + } + + if (fdp.ConsumeBool()) { + std::vector normals(vertex_count * 3); + std::vector uvs(vertex_count * 2); + std::vector tangents(index_count * 4); + for (size_t i = 0; i < normals.size(); ++i) normals[i] = fdp.ConsumeFloatingPoint(); + for (size_t i = 0; i < uvs.size(); ++i) uvs[i] = fdp.ConsumeFloatingPoint(); + meshopt_generateTangents(tangents.data(), indices.data(), index_count, vertex_positions.data(), vertex_count, 3 * sizeof(float), normals.data(), 3 * sizeof(float), uvs.data(), 2 * sizeof(float), 0); + } + + if (fdp.ConsumeBool()) { + std::vector remap(vertex_count); + meshopt_generateVertexRemap(remap.data(), indices.data(), index_count, vertex_positions.data(), vertex_count, 3 * sizeof(float)); + } + + return 0; +}