Skip to content

Instantly share code, notes, and snippets.

@grondag
Created February 17, 2019 15:53
Show Gist options
  • Save grondag/c1aa6af7c0815c3b00771e73293b2f15 to your computer and use it in GitHub Desktop.
Save grondag/c1aa6af7c0815c3b00771e73293b2f15 to your computer and use it in GitHub Desktop.
Benchmark: vertex attribute access patterns
Benchmark Mode Cnt Score Error Units
VertexAccess.testQuadIndexed thrpt 25 1792.170 ± 35.819 ops/s
VertexAccess.testVertexDirect thrpt 25 1854.714 ± 7.662 ops/s
VertexAccess.testVertexIndexed thrpt 25 1847.824 ± 26.582 ops/s
public class VertexAccess {
class Quad {
static final int VERTEX_STRIDE = 16;
static final int QUAD_STRIDE = VERTEX_STRIDE * 4;
static final int TEX_START = 4;
static final int TEX_STRIDE = 3;
final Vertex[] vertex = new Vertex[4];
int[] data;
int baseIndex;
Quad(int[] data, int baseIndex) {
this.data = data;
this.baseIndex = baseIndex;
for(int i = 0; i < 4; i++) {
vertex[i] = new Vertex(i);
}
}
Vertex vertex(int i) {
return vertex[i];
}
float x(int i) {
return Float.intBitsToFloat(data[baseIndex + i * VERTEX_STRIDE]);
}
Quad x(int i, float x) {
data[baseIndex + i * VERTEX_STRIDE] = Float.floatToRawIntBits(x);
return this;
}
float y(int i) {
return Float.intBitsToFloat(data[baseIndex + i * VERTEX_STRIDE + 1]);
}
Quad y(int i, float y) {
data[baseIndex + i * VERTEX_STRIDE + 1] = Float.floatToRawIntBits(y);
return this;
}
float z(int i) {
return Float.intBitsToFloat(data[baseIndex + i * VERTEX_STRIDE + 2]);
}
Quad z(int i, float z) {
data[baseIndex + i * VERTEX_STRIDE + 2] = Float.floatToRawIntBits(z);
return this;
}
int color(int i, int j) {
return data[baseIndex + i * VERTEX_STRIDE + TEX_START + j * TEX_STRIDE];
}
Quad color(int i, int j, int c) {
data[baseIndex + i * VERTEX_STRIDE + TEX_START + j * TEX_STRIDE] = c;
return this;
}
float u(int i, int j) {
return Float.intBitsToFloat(data[baseIndex + i * VERTEX_STRIDE + TEX_START + j * TEX_STRIDE + 1]);
}
Quad u(int i, int j, float u) {
data[baseIndex + i * VERTEX_STRIDE + TEX_START + j * TEX_STRIDE + 1] = Float.floatToRawIntBits(u);
return this;
}
float v(int i, int j) {
return Float.intBitsToFloat(data[baseIndex + i * VERTEX_STRIDE + TEX_START + j * TEX_STRIDE + 2]);
}
Quad v(int i, int j, float v) {
data[baseIndex + i * VERTEX_STRIDE + TEX_START + j * TEX_STRIDE + 2] = Float.floatToRawIntBits(v);
return this;
}
class Vertex {
private final int texBase;
private final int xOffset;
private final int yOffset;
private final int zOffset;
private final int colorOffset1;
private final int uOffset1;
private final int vOffset1;
private final int colorOffset2;
private final int uOffset2;
private final int vOffset2;
private final int colorOffset3;
private final int uOffset3;
private final int vOffset3;
Vertex(int index) {
int baseIndex = index * VERTEX_STRIDE;
texBase = baseIndex + TEX_START;
xOffset = baseIndex++;
yOffset = baseIndex++;
zOffset = baseIndex++;
colorOffset1 = baseIndex++;
uOffset1 = baseIndex++;
vOffset1 = baseIndex++;
colorOffset2 = baseIndex++;
uOffset2 = baseIndex++;
vOffset2 = baseIndex++;
colorOffset3 = baseIndex++;
uOffset3 = baseIndex++;
vOffset3 = baseIndex++;
}
float x() {
return Float.intBitsToFloat(data[baseIndex + xOffset]);
}
Vertex x(float x) {
data[baseIndex + xOffset] = Float.floatToRawIntBits(x);
return this;
}
float y() {
return Float.intBitsToFloat(data[baseIndex + yOffset]);
}
Vertex y(float y) {
data[baseIndex + yOffset] = Float.floatToRawIntBits(y);
return this;
}
float z() {
return Float.intBitsToFloat(data[baseIndex + zOffset]);
}
Vertex z(float z) {
data[baseIndex + zOffset] = Float.floatToRawIntBits(z);
return this;
}
int color(int j) {
return data[baseIndex + texBase + j * TEX_STRIDE];
}
Vertex color(int j, int c) {
data[baseIndex + texBase + j * TEX_STRIDE] = c;
return this;
}
float u(int j) {
return Float.intBitsToFloat(data[baseIndex + texBase + j * TEX_STRIDE + 1]);
}
Vertex u(int j, float u) {
data[baseIndex + texBase + j * TEX_STRIDE + 1] = Float.floatToRawIntBits(u);
return this;
}
float v(int j) {
return Float.intBitsToFloat(data[baseIndex + texBase + j * TEX_STRIDE + 2]);
}
Vertex v(int j, float v) {
data[baseIndex + texBase + j * TEX_STRIDE + 2] = Float.floatToRawIntBits(v);
return this;
}
int color1() {
return data[baseIndex + colorOffset1];
}
Vertex color1(int c) {
data[baseIndex + colorOffset1] = c;
return this;
}
float u1() {
return Float.intBitsToFloat(data[baseIndex + uOffset1]);
}
Vertex u1(float u) {
data[baseIndex + uOffset1] = Float.floatToRawIntBits(u);
return this;
}
float v1() {
return Float.intBitsToFloat(data[baseIndex + + vOffset1]);
}
Vertex v1(float v) {
data[baseIndex + vOffset1] = Float.floatToRawIntBits(v);
return this;
}
int color2() {
return data[baseIndex + colorOffset2];
}
Vertex color2(int c) {
data[baseIndex + colorOffset2] = c;
return this;
}
float u2() {
return Float.intBitsToFloat(data[baseIndex + uOffset2]);
}
Vertex u2(float u) {
data[baseIndex + uOffset2] = Float.floatToRawIntBits(u);
return this;
}
float v2() {
return Float.intBitsToFloat(data[baseIndex + + vOffset2]);
}
Vertex v2(float v) {
data[baseIndex + vOffset2] = Float.floatToRawIntBits(v);
return this;
}
int color3() {
return data[baseIndex + colorOffset3];
}
Vertex color3(int c) {
data[baseIndex + colorOffset3] = c;
return this;
}
float u3() {
return Float.intBitsToFloat(data[baseIndex + uOffset3]);
}
Vertex u3(float u) {
data[baseIndex + uOffset3] = Float.floatToRawIntBits(u);
return this;
}
float v3() {
return Float.intBitsToFloat(data[baseIndex + + vOffset3]);
}
Vertex v3(float v) {
data[baseIndex + vOffset3] = Float.floatToRawIntBits(v);
return this;
}
}
}
@Benchmark
public void testVertexDirect() {
int[] data = new int[Quad.QUAD_STRIDE * 1000];
Quad q = new Quad(data, 0);
Random r = new Random();
for(int i = 0; i < 1000; i++) {
q.baseIndex = i * Quad.QUAD_STRIDE;
for(int j = 0; j < 4; j++) {
Vertex vt = q.vertex(j);
vt.x(r.nextFloat()).x(vt.x() + .1f).y(r.nextFloat()).x(vt.y() + .1f).z(r.nextFloat()).z(vt.z() + .1f);
vt.color1(r.nextInt());
vt.color2(r.nextInt());
vt.color3(r.nextInt());
vt.color1(vt.color1() | 0xFF000000);
vt.color2(vt.color2() | 0x00FFFFFF);
vt.color3(vt.color3() & 0x00FFFFFF);
vt.u1(r.nextFloat());
vt.u2(r.nextFloat());
vt.u3(r.nextFloat());
vt.u1(vt.u1() * 0.8f);
vt.u2(vt.u2() + 0.5f);
vt.u3(1 - vt.u3());
vt.v1(r.nextFloat());
vt.v2(r.nextFloat());
vt.v3(r.nextFloat());
vt.v1(vt.v1() * 0.8f);
vt.v2(vt.v2() + 0.5f);
vt.v3(1 - vt.v3());
}
}
}
@Benchmark
public void testVertexIndexed() {
int[] data = new int[Quad.QUAD_STRIDE * 1000];
Quad q = new Quad(data, 0);
Random r = new Random();
for(int i = 0; i < 1000; i++) {
q.baseIndex = i * Quad.QUAD_STRIDE;
for(int j = 0; j < 4; j++) {
Vertex vt = q.vertex(j);
vt.x(r.nextFloat()).x(vt.x() + .1f).y(r.nextFloat()).x(vt.y() + .1f).z(r.nextFloat()).z(vt.z() + .1f);
vt.color(0, r.nextInt());
vt.color(1, r.nextInt());
vt.color(2, r.nextInt());
vt.color(0, vt.color(0) | 0xFF000000);
vt.color(1, vt.color(1) | 0x00FFFFFF);
vt.color(2, vt.color(2) & 0x00FFFFFF);
vt.u(0, r.nextFloat());
vt.u(1, r.nextFloat());
vt.u(2, r.nextFloat());
vt.u(0, vt.u(0) * 0.8f);
vt.u(1, vt.u(1) + 0.5f);
vt.u(2, 1 - vt.u(2));
vt.v(0, r.nextFloat());
vt.v(1, r.nextFloat());
vt.v(2, r.nextFloat());
vt.v(0, vt.v(0) * 0.8f);
vt.v(1, vt.v(1) + 0.5f);
vt.v(2, 1 - vt.v(2));
}
}
}
@Benchmark
public void testQuadIndexed() {
int[] data = new int[Quad.QUAD_STRIDE * 1000];
Quad q = new Quad(data, 0);
Random r = new Random();
for(int i = 0; i < 1000; i++) {
q.baseIndex = i * Quad.QUAD_STRIDE;
for(int j = 0; j < 4; j++) {
q.x(j, r.nextFloat()).x(j, q.x(j) + .1f).y(j, r.nextFloat()).x(j, q.y(j) + .1f).z(j, r.nextFloat()).z(j, q.z(j) + .1f);
q.color(j, 0, r.nextInt());
q.color(j, 1, r.nextInt());
q.color(j, 2, r.nextInt());
q.color(j, 0, q.color(j, 0) | 0xFF000000);
q.color(j, 1, q.color(j, 1) | 0x00FFFFFF);
q.color(j, 2, q.color(j, 2) & 0x00FFFFFF);
q.u(j, 0, r.nextFloat());
q.u(j, 1, r.nextFloat());
q.u(j, 2, r.nextFloat());
q.u(j, 0, q.u(j, 0) * 0.8f);
q.u(j, 1, q.u(j, 1) + 0.5f);
q.u(j, 2, 1 - q.u(j, 2));
q.v(j, 0, r.nextFloat());
q.v(j, 1, r.nextFloat());
q.v(j, 2, r.nextFloat());
q.v(j, 0, q.v(j, 0) * 0.8f);
q.v(j, 1, q.v(j, 1) + 0.5f);
q.v(j, 2, 1 - q.v(j, 2));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment