Created
February 17, 2019 15:53
-
-
Save grondag/c1aa6af7c0815c3b00771e73293b2f15 to your computer and use it in GitHub Desktop.
Benchmark: vertex attribute access patterns
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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