Skip to content

Instantly share code, notes, and snippets.

@zeux
zeux / meshoptimizer-c99.diff
Created June 19, 2018 14:02
Experimental change to convert meshoptimizer code from C++03 to C99, to measure compile time & size impact of C++ on a largely-C-codebase.
diff --git a/src/indexcodec.cpp b/src/indexcodec.cpp
index 4ab92cb..18ccd43 100644
--- a/src/indexcodec.cpp
+++ b/src/indexcodec.cpp
@@ -7,9 +7,6 @@
// This work is based on:
// Fabian Giesen. Simple lossless index buffer compression & follow-up. 2013
// Conor Stokes. Vertex Cache Optimised Index Buffer Compression. 2014
-namespace meshopt
-{
@zeux
zeux / vertexcodec-comparison.txt
Last active May 23, 2019 16:45
Comparison of vertexcodec/indexcodec from meshoptimizer with Google Draco
Using fixed-point encoding for position (14 bits per component) and texture coordinates (12 bits per component), with 32-bit index buffer
and this vertex format:
// 12 bytes
struct PackedVertexOct
{
unsigned short px, py, pz;
unsigned char nu, nv; // octahedron encoded normal, aliases .pw
unsigned short tx, ty;
};
@zeux
zeux / cone-culling-experiments.log
Last active February 19, 2024 08:38
Comparison of backface culling efficiency for cluster cone culling with 64-triangle clusters and triangle mask culling (6 64-bit masks per cluster).
Algorithms used for Cone* preprocess the mesh in some way, then split sequentially into 64-triangle clusters:
ConeBase: optimize mesh for transform cache
ConeSort: split mesh into large planar connected clusters, bin clusters into 6 buckets by cardinal axes, optimize each bucket for transform cache
ConeAcmr: optimize mesh for transform cache, split sequentially into variable length clusters that are relatively planar, sort clusters by avg normal
ConeCash: optimize mesh for transform cache, picking triangles that reduce ACMR but prioritizing those that keep current cluster planar
MaskBase: split sequentially into 64-triangle clusters, store a 64-bit conservative triangle mask for 6 frustums (cube faces)
ManyConeN: split sequentially into 64-triangle clusters, store N (up to 4) cones for each cluster and a cone id per triangle (2 bit)
Note that all Cone* solutions get significantly worse results with 128 or 256 triangle clusters; it doesn't matter much for Mask.
The biggest challenge with Cone* algorithms is t
@zeux
zeux / decodebytes.cpp
Created April 13, 2018 03:47
Decoding a format where we first have 16 k-bit values (for k=1,2,4,8), and then have up to 16 8-bit values for "outliers" which are selected based on whether a k-bit value was equal to (1<<k)-1
static unsigned char kDecodeBytesGroupShuffle[256][8];
static unsigned char kDecodeBytesGroupCount[256];
static bool gDecodeBytesGroupInitialized;
static void decodeBytesGroupBuildTables()
{
if (gDecodeBytesGroupInitialized)
return;
for (int mask = 0; mask < 256; ++mask)
@zeux
zeux / rngshuf.cpp
Last active March 25, 2018 15:29
This is a response to https://lemire.me/blog/2018/03/24/when-shuffling-large-arrays-how-much-time-can-be-attributed-to-random-number-generation/; the results of that benchmark looked off to me so I reimplemented this in C++ and re-measured it.
// On a Core i7-8650U running at 2.1 GHz, I get the following numbers:
// /mnt/c/work $ g++ -O2 rngshuf.cpp && ./a.out
// shuf 2.195379 s, gen 0.338417 s, shuf-gen 2.731224 s, fwd shuf 2.227119 s
// shuf 2.167099 s, gen 0.122208 s, shuf-gen 2.870520 s, fwd shuf 2.314143 s
// shuf 2.269147 s, gen 0.122214 s, shuf-gen 2.845593 s, fwd shuf 2.367242 s
// shuf 2.270375 s, gen 0.122476 s, shuf-gen 2.867398 s, fwd shuf 2.314249 s
// shuf 2.258742 s, gen 0.120076 s, shuf-gen 2.863602 s, fwd shuf 2.328118 s
// shuf 2.265792 s, gen 0.126285 s, shuf-gen 2.923946 s, fwd shuf 2.356490 s
// shuf 2.264414 s, gen 0.122542 s, shuf-gen 2.880007 s, fwd shuf 2.365302 s
@zeux
zeux / vulkan-dispatch.c
Created March 17, 2018 20:02
This is how vkCmdDraw looks when you use vulkan-1.dll on Windows (call esi is the only "important" instruction here - it calls the driver). Omitted are also DLL thunks that go before this function, adding two more jmps.
LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
uint32_t firstVertex, uint32_t firstInstance) {
0F9EEE00 55 push ebp
0F9EEE01 8B EC mov ebp,esp
0F9EEE03 51 push ecx
0F9EEE04 A1 34 E0 A6 0F mov eax,dword ptr [__security_cookie (0FA6E034h)]
0F9EEE09 33 C5 xor eax,ebp
0F9EEE0B 89 45 FC mov dword ptr [ebp-4],eax
const VkLayerDispatchTable *disp;
@zeux
zeux / disjoint.cpp
Last active February 2, 2018 05:26
void transpose(disjoint Matrix4& target, const disjoint Matrix4& source)
{
for (int i = 0; i < 4; ++i) for (int j = 0; j < 4; ++j) target.m[i][j] = source.m[j][i];
}
// this is a safe overload
void transpose(Matrix4& target, const Matrix4& source)
{
Matrix4 temp;
for (int i = 0; i < 4; ++i) for (int j = 0; j < 4; ++j) temp.m[i][j] = source.m[j][i];

State of Roblox graphics API across all platforms, with percentage deltas since EOY 2017. Updated December 17 2018

Windows

API Share
Direct3D 11+ 80% (+3%)
Direct3D 10.1 10% (-1%)
Direct3D 10.0 8% (-1%)
Direct3D 9 2% (-1%)
.SUFFIXES:
MAKEFLAGS+=-r
config=release
BUILD=build/$(config)
SOURCES=$(wildcard src/*.cpp demo/*.c demo/*.cpp)
OBJECTS=$(SOURCES:%=$(BUILD)/%.o)
@zeux
zeux / format.cpp
Last active November 14, 2025 11:08
C++ format library proof of concept - focus here is on minimal header so that compilation time is not affected. Implementation is very bare bones.
#include "format.h"
namespace fmt {
static void format_bool(std::string& result, bool value)
{
result += value ? "true" : "false";
}
static void format_char(std::string& result, char value)