Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions tools/opacitymapfuzz.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include "../src/meshoptimizer.h"

#include <fuzzer/FuzzedDataProvider.h>
#include <vector>
#include <string.h>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider fdp(data, size);

uint32_t vertex_count = fdp.ConsumeIntegralInRange<uint32_t>(1, 1024);
uint32_t index_count = fdp.ConsumeIntegralInRange<uint32_t>(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<float> vertex_uvs(vertex_count * 2);
for (size_t i = 0; i < vertex_uvs.size(); ++i) {
vertex_uvs[i] = fdp.ConsumeFloatingPoint<float>();
}

std::vector<uint32_t> indices(index_count);
for (size_t i = 0; i < index_count; ++i) {
indices[i] = fdp.ConsumeIntegralInRange<uint32_t>(0, vertex_count - 1);
}

uint32_t texture_width = fdp.ConsumeIntegralInRange<uint32_t>(1, 512);
uint32_t texture_height = fdp.ConsumeIntegralInRange<uint32_t>(1, 512);
int max_level = fdp.ConsumeIntegralInRange<int>(0, 4);
float target_edge = fdp.ConsumeFloatingPointInRange<float>(0.0f, 10.0f);

size_t triangle_count = index_count / 3;
std::vector<unsigned char> levels(triangle_count);
std::vector<unsigned int> sources(triangle_count);
std::vector<int> 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<unsigned char> 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<unsigned char> omm_data(total_omm_size);
std::vector<unsigned int> 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;
}
71 changes: 71 additions & 0 deletions tools/optimizefuzz.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "../src/meshoptimizer.h"

#include <fuzzer/FuzzedDataProvider.h>
#include <vector>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider fdp(data, size);

uint32_t vertex_count = fdp.ConsumeIntegralInRange<uint32_t>(1, 1024);
uint32_t index_count = fdp.ConsumeIntegralInRange<uint32_t>(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<float> vertex_positions(vertex_count * 3);
for (size_t i = 0; i < vertex_positions.size(); ++i) {
vertex_positions[i] = fdp.ConsumeFloatingPoint<float>();
}

std::vector<uint32_t> indices(index_count);
for (size_t i = 0; i < indices.size(); ++i) {
indices[i] = fdp.ConsumeIntegralInRange<uint32_t>(0, vertex_count - 1);
}

std::vector<uint32_t> 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<float>(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<float> 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<uint32_t>();
std::vector<uint32_t> strip(meshopt_stripifyBound(index_count));
size_t strip_size = meshopt_stripify(strip.data(), indices.data(), index_count, vertex_count, restart_index);

std::vector<uint32_t> unstrip(meshopt_unstripifyBound(strip_size));
meshopt_unstripify(unstrip.data(), strip.data(), strip_size, restart_index);
}

if (fdp.ConsumeBool()) {
std::vector<float> normals(vertex_count * 3);
std::vector<float> uvs(vertex_count * 2);
std::vector<float> tangents(index_count * 4);
for (size_t i = 0; i < normals.size(); ++i) normals[i] = fdp.ConsumeFloatingPoint<float>();
for (size_t i = 0; i < uvs.size(); ++i) uvs[i] = fdp.ConsumeFloatingPoint<float>();
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<unsigned int> remap(vertex_count);
meshopt_generateVertexRemap(remap.data(), indices.data(), index_count, vertex_positions.data(), vertex_count, 3 * sizeof(float));
}

return 0;
}
Loading