Implementing Shader Perf Benchmark as a fractal.
And tuned some other benchmarks.
Change-Id: I290540c3580fb7d8ab2b4577e00a1dd1a2ec55b4
diff --git a/suite/pts/deviceTests/opengl/jni/GLUtils.cpp b/suite/pts/deviceTests/opengl/jni/GLUtils.cpp
index f62f5b8..9e75f2c 100644
--- a/suite/pts/deviceTests/opengl/jni/GLUtils.cpp
+++ b/suite/pts/deviceTests/opengl/jni/GLUtils.cpp
@@ -15,6 +15,10 @@
#include <GLUtils.h>
#include <stdlib.h>
+#define LOG_TAG "PTS_OPENGL"
+#define LOG_NDEBUG 0
+#include "utils/Log.h"
+
// Loads the given source code as a shader of the given type.
static GLuint loadShader(GLenum shaderType, const char** source) {
GLuint shader = glCreateShader(shaderType);
@@ -24,6 +28,14 @@
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
+ GLint infoLen = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen > 0) {
+ char* infoLog = (char*) malloc(sizeof(char) * infoLen);
+ glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
+ ALOGE("Error compiling shader:\n%s\n", infoLog);
+ free(infoLog);
+ }
glDeleteShader(shader);
shader = 0;
}
@@ -38,29 +50,29 @@
return 0;
}
- GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, fragmentSource);
- if (!pixelShader) {
+ GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentSource);
+ if (!fragmentShader) {
return 0;
}
GLuint program = glCreateProgram();
if (program) {
- bool success = true;
glAttachShader(program, vertexShader);
- if (GLenum(GL_NO_ERROR) != glGetError()) {
- success = false;
- }
- glAttachShader(program, pixelShader);
- if (GLenum(GL_NO_ERROR) != glGetError()) {
- success = false;
- }
+ glAttachShader(program, fragmentShader);
- GLint linkStatus = GL_FALSE;
- if (success) {
- glLinkProgram(program);
- glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
- }
- if (linkStatus != GL_TRUE || !success) {
+ GLint linkStatus;
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+
+ if (!linkStatus) {
+ GLint infoLen = 0;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen > 0) {
+ char* infoLog = (char*) malloc(sizeof(char) * infoLen);
+ glGetProgramInfoLog(program, infoLen, NULL, infoLog);
+ ALOGE("Error linking program:\n%s\n", infoLog);
+ free(infoLog);
+ }
glDeleteProgram(program);
program = 0;
}
diff --git a/suite/pts/deviceTests/opengl/jni/fullpipeline/FullPipelineRenderer.cpp b/suite/pts/deviceTests/opengl/jni/fullpipeline/FullPipelineRenderer.cpp
index c2ffecc..4cab669 100644
--- a/suite/pts/deviceTests/opengl/jni/fullpipeline/FullPipelineRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/fullpipeline/FullPipelineRenderer.cpp
@@ -115,7 +115,7 @@
// Position the eye in front of the origin.
float eyeX = 0.0f;
float eyeY = 0.0f;
- float eyeZ = 2.0f;
+ float eyeZ = 1.5f;
// We are looking at the origin
float centerX = 0.0f;
@@ -138,7 +138,7 @@
float bottom = -1.0f;
float top = 1.0f;
float near = 1.0f;
- float far = 3.0f;
+ float far = 2.0f;
mProjectionMatrix = Matrix::newFrustum(left, right, bottom, top, near, far);
diff --git a/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.cpp b/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.cpp
index a3fea22..6d98c9a 100644
--- a/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.cpp
@@ -14,10 +14,14 @@
#include "ShaderPerfRenderer.h"
#include <GLUtils.h>
+#include <math.h>
+
#define LOG_TAG "PTS_OPENGL"
#define LOG_NDEBUG 0
#include "utils/Log.h"
+static const float GOLDEN_RATIO = (1.0 + sqrt(5.0)) / 2.0;
+
static const int SP_NUM_VERTICES = 6;
static const float SP_VERTICES[SP_NUM_VERTICES * 3] = {
@@ -28,19 +32,66 @@
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f };
-static const char* SP_VERTEX = "attribute vec4 a_Position;"
- "varying vec4 v_Position;"
- "void main() {"
- " v_Position = a_Position;"
- " gl_Position = a_Position;"
- "}";
+static const float SP_TEX_COORDS[SP_NUM_VERTICES * 2] = {
+ 1.0f, 1.0f,
+ 0.0f, 1.0f,
+ 0.0f, 0.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 1.0f };
-// TODO At the moment this a very simple shader. Later on this will get more complex.
-static const char* SP_FRAGMENT = "precision mediump float;"
- "varying vec4 v_Position;"
- "void main() {"
- " gl_FragColor = v_Position;"
- "}";
+static const char* SP_VERTEX =
+ "attribute vec4 a_Position;"
+ "attribute vec2 a_TexCoord;"
+ "varying vec2 v_TexCoord;"
+ "void main() {"
+ " v_TexCoord = a_TexCoord;"
+ " gl_Position = a_Position;"
+ "}";
+
+static const char* SP_FRAGMENT_1 =
+ "precision mediump float;"
+ "uniform vec2 u_Seed;"
+ "uniform sampler2D u_Texture;"
+ "varying vec2 v_TexCoord;"
+ "void main() {"
+ " int count = ";
+
+//Add workload here
+
+static const char* SP_FRAGMENT_2 =
+ " * 5;"//workload * 5 (5 is a balanced number, bigger = more work)
+ " vec2 z;"
+ " z.x = 3.0 * (v_TexCoord.x - 0.5);"
+ " z.y = 2.0 * (v_TexCoord.y - 0.5);"
+ " float u = 0.0;"
+ " for (int i = 0; i < count; i++) {"
+ " float x = (z.x * z.x - z.y * z.y) + u_Seed.x;"
+ " float y = (z.y * z.x + z.x * z.y) + u_Seed.y;"
+ " if (((x * x + y * y) > 4.0) && (u == 0.0)) {"
+ " u = float(i) / float(count);"
+ " }"
+ " z.x = x;"
+ " z.y = y;"
+ " }"
+ " gl_FragColor = texture2D(u_Texture, vec2(u, 0.0));"
+ "}";
+
+// Copies the source array from 0 up to and including the '\0' character to the
+// destination array starting from the given start position. Unlike strcpy, this
+// returns the number of characters which were copied.
+static int charCopy(const char* source, char* dest, int destStart) {
+ int srcAddr = 0;
+ int destAddr = destStart;
+ char current;
+ do {
+ current = source[srcAddr];
+ dest[destAddr] = current;
+ srcAddr++;
+ destAddr++;
+ } while (current != '\0');
+ return destAddr - destStart;
+}
ShaderPerfRenderer::ShaderPerfRenderer(ANativeWindow* window, bool offscreen, int workload) :
Renderer(window, offscreen, workload) {
@@ -50,12 +101,49 @@
if (!Renderer::setUp()) {
return false;
}
+
+ const int MAX_FRAGMENT_SHADER_SIZE = 1000;
+ char* spFragment = new char[MAX_FRAGMENT_SHADER_SIZE];
+ // Add the first part.
+ int index = charCopy(SP_FRAGMENT_1, spFragment, 0);
+ // Add the count, overwriting the '\0' added by charCopy.
+ spFragment[index - 1] = (char) (((int) '0') + mWorkload);
+ // Add the second part.
+ index += charCopy(SP_FRAGMENT_2, spFragment, index);
// Create program.
- mProgramId = GLUtils::createProgram(&SP_VERTEX, &SP_FRAGMENT);
+ mProgramId = GLUtils::createProgram(&SP_VERTEX, const_cast<const char**>(&spFragment));
+ delete[] spFragment;
if (mProgramId == 0)
return false;
// Bind attributes.
+ mTextureUniformHandle = glGetUniformLocation(mProgramId, "u_Texture");
+ mSeedUniformHandle = glGetUniformLocation(mProgramId, "u_Seed");
mPositionHandle = glGetAttribLocation(mProgramId, "a_Position");
+ mTexCoordHandle = glGetAttribLocation(mProgramId, "a_TexCoord");
+
+ const int SIZE = 256;
+ uint32_t* m = new uint32_t[SIZE];
+ if (m != NULL) {
+ uint32_t* d = m;
+ for (int i = 0; i < SIZE; i++) {
+ *d = 0xff000000 | ((i & 0xff) << 16);
+ d++;
+ }
+ glGenTextures(1, &mTextureId);
+ glBindTexture(GL_TEXTURE_2D, mTextureId);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SIZE, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, m);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ }
+ delete[] m;
+
+ GLuint err = glGetError();
+ if (err != GL_NO_ERROR) {
+ ALOGV("GLError %d", err);
+ return false;
+ }
+
return true;
}
@@ -64,15 +152,26 @@
glBindFramebuffer(GL_FRAMEBUFFER, mFboId);
}
glUseProgram(mProgramId);
- // Set the background clear color to black.
+ // Set the background clear color.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
// No culling of back faces
glDisable(GL_CULL_FACE);
+ // Bind the texture.
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, mTextureId);
+ glUniform1i(mTextureUniformHandle, 0);
+
+ // Bind the seed.
+ glUniform2f(mSeedUniformHandle, GOLDEN_RATIO - 2.0f, GOLDEN_RATIO - 1.0f);
+
+ // Bind the vertices.
glEnableVertexAttribArray(mPositionHandle);
+ glEnableVertexAttribArray(mTexCoordHandle);
glVertexAttribPointer(mPositionHandle, 3, GL_FLOAT, false, 0, SP_VERTICES);
+ glVertexAttribPointer(mTexCoordHandle, 2, GL_FLOAT, false, 0, SP_TEX_COORDS);
glDrawArrays(GL_TRIANGLES, 0, SP_NUM_VERTICES);
diff --git a/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.h b/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.h
index 22e0420..4460174 100644
--- a/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.h
+++ b/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.h
@@ -23,7 +23,11 @@
bool setUp();
bool draw();
private:
+ GLuint mTextureId;
+ GLuint mTextureUniformHandle;
GLuint mPositionHandle;
+ GLuint mTexCoordHandle;
+ GLuint mSeedUniformHandle;
};
#endif
diff --git a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java
index b1c9112..0eab7cd 100644
--- a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java
+++ b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java
@@ -67,16 +67,14 @@
* Runs the shader performance test offscreen.
*/
public void testShaderPerfOffscreen() throws Exception {
- // TODO(stuartscott): Not yet implemented
- // runBenchmark(Benchmark.ShaderPerf, true, 500, 8, 1000000);
+ runBenchmark(Benchmark.ShaderPerf, true, 500, 8, 1000000);
}
/**
* Runs the shader performance test onscreen.
*/
public void testShaderPerfOnscreen() throws Exception {
- // TODO(stuartscott): Not yet implemented
- // runBenchmark(Benchmark.ShaderPerf, false, 500, 8, 1000000);
+ runBenchmark(Benchmark.ShaderPerf, false, 500, 8, 1000000);
}
/**