Commit ec30d78d by Jiacheng Lu Committed by Commit Bot

Optimize uniform matrix update

1. Add a fast matrix update function to do a single memcpy for uniform matrix assignment with same layout. It benefits row-4 no-transpose GLSL matrix and col-4 transpose HLSL matrix. 2. Make boolean IsColumnMajor to be a template parameter in generate uniform matrix updating, which gets rid of the conditional branch in loop and has better performance. 3. Add e2e test of uploading multiple 3x4 GLSL matrices at the same time, which adds coverage to this CL. Bug: angleproject:3632 Change-Id: Id1701ef6fbf63ea4b9884254d93ea8eacfe4e16a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1688274 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 69194e5f
...@@ -2602,9 +2602,9 @@ void ProgramD3D::setUniformMatrixfvInternal(GLint location, ...@@ -2602,9 +2602,9 @@ void ProgramD3D::setUniformMatrixfvInternal(GLint location,
{ {
if (targetUniform->mShaderData[shaderType]) if (targetUniform->mShaderData[shaderType])
{ {
if (SetFloatUniformMatrixHLSL<cols, rows>(arrayElementOffset, elementCount, countIn, if (SetFloatUniformMatrixHLSL<cols, rows>::Run(arrayElementOffset, elementCount,
transpose, value, countIn, transpose, value,
targetUniform->mShaderData[shaderType])) targetUniform->mShaderData[shaderType]))
{ {
mShaderUniformsDirty.set(shaderType); mShaderUniformsDirty.set(shaderType);
} }
......
...@@ -101,10 +101,10 @@ void WriteFloatColor(const gl::ColorF &color, ...@@ -101,10 +101,10 @@ void WriteFloatColor(const gl::ColorF &color,
colorWriteFunction(reinterpret_cast<const uint8_t *>(&color), destPixelData); colorWriteFunction(reinterpret_cast<const uint8_t *>(&color), destPixelData);
} }
template <int cols, int rows> template <int cols, int rows, bool IsColumnMajor>
int GetFlattenedIndex(bool isColumnMajor, int col, int row) inline int GetFlattenedIndex(int col, int row)
{ {
if (isColumnMajor) if (IsColumnMajor)
{ {
return col * rows + row; return col * rows + row;
} }
...@@ -114,8 +114,14 @@ int GetFlattenedIndex(bool isColumnMajor, int col, int row) ...@@ -114,8 +114,14 @@ int GetFlattenedIndex(bool isColumnMajor, int col, int row)
} }
} }
template <typename T, int colsSrc, int rowsSrc, bool IsDstColumnMajor, int colsDst, int rowsDst> template <typename T,
bool ExpandMatrix(T *target, const GLfloat *value, bool isSrcColumnMajor) bool IsSrcColumnMajor,
int colsSrc,
int rowsSrc,
bool IsDstColumnMajor,
int colsDst,
int rowsDst>
bool ExpandMatrix(T *target, const GLfloat *value)
{ {
static_assert(colsSrc <= colsDst && rowsSrc <= rowsDst, "Can only expand!"); static_assert(colsSrc <= colsDst && rowsSrc <= rowsDst, "Can only expand!");
...@@ -126,8 +132,8 @@ bool ExpandMatrix(T *target, const GLfloat *value, bool isSrcColumnMajor) ...@@ -126,8 +132,8 @@ bool ExpandMatrix(T *target, const GLfloat *value, bool isSrcColumnMajor)
{ {
for (int c = 0; c < colsSrc; c++) for (int c = 0; c < colsSrc; c++)
{ {
int srcIndex = GetFlattenedIndex<colsSrc, rowsSrc>(isSrcColumnMajor, c, r); int srcIndex = GetFlattenedIndex<colsSrc, rowsSrc, IsSrcColumnMajor>(c, r);
int dstIndex = GetFlattenedIndex<colsDst, rowsDst>(IsDstColumnMajor, c, r); int dstIndex = GetFlattenedIndex<colsDst, rowsDst, IsDstColumnMajor>(c, r);
staging[dstIndex] = static_cast<T>(value[srcIndex]); staging[dstIndex] = static_cast<T>(value[srcIndex]);
} }
...@@ -142,11 +148,15 @@ bool ExpandMatrix(T *target, const GLfloat *value, bool isSrcColumnMajor) ...@@ -142,11 +148,15 @@ bool ExpandMatrix(T *target, const GLfloat *value, bool isSrcColumnMajor)
return true; return true;
} }
template <int colsSrc, int rowsSrc, bool IsDstColumnMajor, int colsDst, int rowsDst> template <bool IsSrcColumMajor,
int colsSrc,
int rowsSrc,
bool IsDstColumnMajor,
int colsDst,
int rowsDst>
bool SetFloatUniformMatrix(unsigned int arrayElementOffset, bool SetFloatUniformMatrix(unsigned int arrayElementOffset,
unsigned int elementCount, unsigned int elementCount,
GLsizei countIn, GLsizei countIn,
GLboolean transpose,
const GLfloat *value, const GLfloat *value,
uint8_t *targetData) uint8_t *targetData)
{ {
...@@ -161,16 +171,39 @@ bool SetFloatUniformMatrix(unsigned int arrayElementOffset, ...@@ -161,16 +171,39 @@ bool SetFloatUniformMatrix(unsigned int arrayElementOffset,
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
const bool isSrcColumnMajor = !transpose; dirty = ExpandMatrix<GLfloat, IsSrcColumMajor, colsSrc, rowsSrc, IsDstColumnMajor, colsDst,
dirty = ExpandMatrix<GLfloat, colsSrc, rowsSrc, IsDstColumnMajor, colsDst, rowsDst>( rowsDst>(target, value) ||
target, value, isSrcColumnMajor) ||
dirty; dirty;
target += targetMatrixStride; target += targetMatrixStride;
value += colsSrc * rowsSrc; value += colsSrc * rowsSrc;
} }
return dirty; return dirty;
} }
bool SetFloatUniformMatrixFast(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
size_t matrixSize,
const GLfloat *value,
uint8_t *targetData)
{
const unsigned int count =
std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
const uint8_t *valueData = reinterpret_cast<const uint8_t *>(value);
targetData = targetData + arrayElementOffset * matrixSize;
if (memcmp(targetData, valueData, matrixSize * count) == 0)
{
return false;
}
memcpy(targetData, valueData, matrixSize * count);
return true;
}
} // anonymous namespace } // anonymous namespace
PackPixelsParams::PackPixelsParams() PackPixelsParams::PackPixelsParams()
...@@ -485,57 +518,161 @@ angle::Result IncompleteTextureSet::getIncompleteTexture( ...@@ -485,57 +518,161 @@ angle::Result IncompleteTextureSet::getIncompleteTexture(
return angle::Result::Continue; return angle::Result::Continue;
} }
#define ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \ #define ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \
template bool SetFloatUniformMatrix##api<cols, rows>(unsigned int, unsigned int, GLsizei, \ template bool SetFloatUniformMatrix##api<cols, rows>::Run( \
GLboolean, const GLfloat *, uint8_t *) unsigned int, unsigned int, GLsizei, GLboolean, const GLfloat *, uint8_t *)
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 2); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 2);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 3); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 3);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 4);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 3); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 3);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 2); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 2);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 4);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 2); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 2);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 4);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 3); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 3);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 2); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 2);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 3); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 3);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 4);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 3); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 3);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 2); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 2);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 4); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 4);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 2);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 4); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 4);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 3);
#undef ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC #undef ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC
#define ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \
template bool SetFloatUniformMatrix##api<cols, 4>::Run(unsigned int, unsigned int, GLsizei, \
GLboolean, const GLfloat *, uint8_t *)
template <int cols>
struct SetFloatUniformMatrixGLSL<cols, 4>
{
static bool Run(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
uint8_t *targetData);
};
ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 4);
ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 4);
ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 4);
#undef ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC
#define ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \
template bool SetFloatUniformMatrix##api<4, rows>::Run(unsigned int, unsigned int, GLsizei, \
GLboolean, const GLfloat *, uint8_t *)
template <int rows>
struct SetFloatUniformMatrixHLSL<4, rows>
{
static bool Run(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
uint8_t *targetData);
};
ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 2);
ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 3);
ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 4);
#undef ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC
template <int cols>
bool SetFloatUniformMatrixGLSL<cols, 4>::Run(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
uint8_t *targetData)
{
const bool isSrcColumnMajor = !transpose;
if (isSrcColumnMajor)
{
// Both src and dst matrixs are has same layout,
// a single memcpy updates all the matrices
constexpr size_t srcMatrixSize = sizeof(GLfloat) * cols * 4;
return SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize,
value, targetData);
}
else
{
// fallback to general cases
return SetFloatUniformMatrix<false, cols, 4, true, cols, 4>(
arrayElementOffset, elementCount, countIn, value, targetData);
}
}
template <int cols, int rows> template <int cols, int rows>
bool SetFloatUniformMatrixGLSL(unsigned int arrayElementOffset, bool SetFloatUniformMatrixGLSL<cols, rows>::Run(unsigned int arrayElementOffset,
unsigned int elementCount, unsigned int elementCount,
GLsizei countIn, GLsizei countIn,
GLboolean transpose, GLboolean transpose,
const GLfloat *value, const GLfloat *value,
uint8_t *targetData) uint8_t *targetData)
{ {
const bool isSrcColumnMajor = !transpose;
// GLSL expects matrix uniforms to be column-major, and each column is padded to 4 rows. // GLSL expects matrix uniforms to be column-major, and each column is padded to 4 rows.
return SetFloatUniformMatrix<cols, rows, true, cols, 4>(arrayElementOffset, elementCount, if (isSrcColumnMajor)
countIn, transpose, value, targetData); {
return SetFloatUniformMatrix<true, cols, rows, true, cols, 4>(
arrayElementOffset, elementCount, countIn, value, targetData);
}
else
{
return SetFloatUniformMatrix<false, cols, rows, true, cols, 4>(
arrayElementOffset, elementCount, countIn, value, targetData);
}
} }
template <int cols, int rows> template <int rows>
bool SetFloatUniformMatrixHLSL(unsigned int arrayElementOffset, bool SetFloatUniformMatrixHLSL<4, rows>::Run(unsigned int arrayElementOffset,
unsigned int elementCount, unsigned int elementCount,
GLsizei countIn, GLsizei countIn,
GLboolean transpose, GLboolean transpose,
const GLfloat *value, const GLfloat *value,
uint8_t *targetData) uint8_t *targetData)
{ {
const bool isSrcColumnMajor = !transpose;
if (!isSrcColumnMajor)
{
// Both src and dst matrixs are has same layout,
// a single memcpy updates all the matrices
constexpr size_t srcMatrixSize = sizeof(GLfloat) * 4 * rows;
return SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize,
value, targetData);
}
else
{
// fallback to general cases
return SetFloatUniformMatrix<true, 4, rows, false, 4, rows>(
arrayElementOffset, elementCount, countIn, value, targetData);
}
}
template <int cols, int rows>
bool SetFloatUniformMatrixHLSL<cols, rows>::Run(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
uint8_t *targetData)
{
const bool isSrcColumnMajor = !transpose;
// Internally store matrices as row-major to accomodate HLSL matrix indexing. Each row is // Internally store matrices as row-major to accomodate HLSL matrix indexing. Each row is
// padded to 4 columns. // padded to 4 columns.
return SetFloatUniformMatrix<cols, rows, false, 4, rows>(arrayElementOffset, elementCount, if (!isSrcColumnMajor)
countIn, transpose, value, targetData); {
return SetFloatUniformMatrix<false, cols, rows, false, 4, rows>(
arrayElementOffset, elementCount, countIn, value, targetData);
}
else
{
return SetFloatUniformMatrix<true, cols, rows, false, 4, rows>(
arrayElementOffset, elementCount, countIn, value, targetData);
}
} }
template void GetMatrixUniform<GLint>(GLenum, GLint *, const GLint *, bool); template void GetMatrixUniform<GLint>(GLenum, GLint *, const GLint *, bool);
......
...@@ -267,19 +267,26 @@ class IncompleteTextureSet final : angle::NonCopyable ...@@ -267,19 +267,26 @@ class IncompleteTextureSet final : angle::NonCopyable
// Helpers to set a matrix uniform value based on GLSL or HLSL semantics. // Helpers to set a matrix uniform value based on GLSL or HLSL semantics.
// The return value indicate if the data was updated or not. // The return value indicate if the data was updated or not.
template <int cols, int rows> template <int cols, int rows>
bool SetFloatUniformMatrixGLSL(unsigned int arrayElementOffset, struct SetFloatUniformMatrixGLSL
unsigned int elementCount, {
GLsizei countIn, static bool Run(unsigned int arrayElementOffset,
GLboolean transpose, unsigned int elementCount,
const GLfloat *value, GLsizei countIn,
uint8_t *targetData); GLboolean transpose,
const GLfloat *value,
uint8_t *targetData);
};
template <int cols, int rows> template <int cols, int rows>
bool SetFloatUniformMatrixHLSL(unsigned int arrayElementOffset, struct SetFloatUniformMatrixHLSL
unsigned int elementCount, {
GLsizei countIn, static bool Run(unsigned int arrayElementOffset,
GLboolean transpose, unsigned int elementCount,
const GLfloat *value, GLsizei countIn,
uint8_t *targetData); GLboolean transpose,
const GLfloat *value,
uint8_t *targetData);
};
// Helper method to de-tranpose a matrix uniform for an API query. // Helper method to de-tranpose a matrix uniform for an API query.
void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose); void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose);
......
...@@ -783,7 +783,7 @@ void ProgramVk::setUniformMatrixfv(GLint location, ...@@ -783,7 +783,7 @@ void ProgramVk::setUniformMatrixfv(GLint location,
continue; continue;
} }
bool updated = SetFloatUniformMatrixGLSL<cols, rows>( bool updated = SetFloatUniformMatrixGLSL<cols, rows>::Run(
locationInfo.arrayIndex, linkedUniform.getArraySizeProduct(), count, transpose, value, locationInfo.arrayIndex, linkedUniform.getArraySizeProduct(), count, transpose, value,
uniformBlock.uniformData.data() + layoutInfo.offset); uniformBlock.uniformData.data() + layoutInfo.offset);
......
...@@ -684,6 +684,60 @@ class UniformTestES3 : public ANGLETest ...@@ -684,6 +684,60 @@ class UniformTestES3 : public ANGLETest
GLuint mProgram; GLuint mProgram;
}; };
// Test that we can get and set an array of matrices uniform.
TEST_P(UniformTestES3, MatrixArrayUniformStateQuery)
{
constexpr char kFragShader[] =
"#version 300 es\n"
"precision mediump float;\n"
"uniform mat3x4 uniMat3x4[5];\n"
"out vec4 fragColor;\n"
"void main() {\n"
" fragColor = vec4(uniMat3x4[0]);\n"
" fragColor += vec4(uniMat3x4[1]);\n"
" fragColor += vec4(uniMat3x4[2]);\n"
" fragColor += vec4(uniMat3x4[3]);\n"
" fragColor += vec4(uniMat3x4[4]);\n"
"}\n";
constexpr unsigned int kArrayCount = 5;
constexpr unsigned int kMatrixStride = 3 * 4;
mProgram = CompileProgram(essl3_shaders::vs::Zero(), kFragShader);
ASSERT_NE(mProgram, 0u);
glUseProgram(mProgram);
GLfloat expected[kArrayCount][kMatrixStride] = {
{0.6f, -0.4f, 0.6f, 0.9f, -0.6f, 0.3f, -0.3f, -0.1f, -0.4f, -0.3f, 0.7f, 0.1f},
{-0.4f, -0.4f, -0.5f, -0.7f, 0.1f, -0.5f, 0.0f, -0.9f, -0.4f, 0.8f, -0.6f, 0.9f},
{0.4f, 0.1f, -0.9f, 1.0f, -0.8f, 0.4f, -0.2f, 0.4f, -0.0f, 0.2f, 0.9f, -0.3f},
{0.5f, 0.7f, -0.0f, 1.0f, 0.7f, 0.7f, 0.7f, -0.7f, -0.8f, 0.6f, 0.5f, -0.2f},
{-1.0f, 0.8f, 1.0f, -0.4f, 0.7f, 0.5f, 0.5f, 0.8f, 0.6f, 0.1f, 0.4f, -0.9f}};
GLint baseLocation = glGetUniformLocation(mProgram, "uniMat3x4");
ASSERT_NE(-1, baseLocation);
glUniformMatrix3x4fv(baseLocation, kArrayCount, GL_FALSE, &expected[0][0]);
for (size_t i = 0; i < kArrayCount; i++)
{
std::stringstream nameStr;
nameStr << "uniMat3x4[" << i << "]";
std::string name = nameStr.str();
GLint location = glGetUniformLocation(mProgram, name.c_str());
ASSERT_GL_NO_ERROR();
ASSERT_NE(-1, location);
std::vector<GLfloat> results(12, 0);
glGetUniformfv(mProgram, location, results.data());
ASSERT_GL_NO_ERROR();
for (size_t compIdx = 0; compIdx < kMatrixStride; compIdx++)
{
EXPECT_EQ(results[compIdx], expected[i][compIdx]);
}
}
}
// Test queries for transposed arrays of non-square matrix uniforms. // Test queries for transposed arrays of non-square matrix uniforms.
TEST_P(UniformTestES3, TransposedMatrixArrayUniformStateQuery) TEST_P(UniformTestES3, TransposedMatrixArrayUniformStateQuery)
{ {
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <random> #include <random>
#include <sstream> #include <sstream>
#include "common/debug.h"
#include "util/Matrix.h" #include "util/Matrix.h"
#include "util/shader_utils.h" #include "util/shader_utils.h"
...@@ -34,7 +35,9 @@ enum DataMode ...@@ -34,7 +35,9 @@ enum DataMode
enum DataType enum DataType
{ {
VEC4, VEC4,
MAT4, MAT3x3,
MAT3x4,
MAT4x4,
}; };
// Determines if we state change the program between draws. // Determines if we state change the program between draws.
...@@ -45,6 +48,12 @@ enum ProgramMode ...@@ -45,6 +48,12 @@ enum ProgramMode
MULTIPLE, MULTIPLE,
}; };
enum MatrixLayout
{
TRANSPOSE,
NO_TRANSPOSE,
};
struct UniformsParams final : public RenderTestParams struct UniformsParams final : public RenderTestParams
{ {
UniformsParams() UniformsParams()
...@@ -52,7 +61,7 @@ struct UniformsParams final : public RenderTestParams ...@@ -52,7 +61,7 @@ struct UniformsParams final : public RenderTestParams
iterationsPerStep = kIterationsPerStep; iterationsPerStep = kIterationsPerStep;
// Common default params // Common default params
majorVersion = 2; majorVersion = 3;
minorVersion = 0; minorVersion = 0;
windowWidth = 720; windowWidth = 720;
windowHeight = 720; windowHeight = 720;
...@@ -62,9 +71,10 @@ struct UniformsParams final : public RenderTestParams ...@@ -62,9 +71,10 @@ struct UniformsParams final : public RenderTestParams
size_t numVertexUniforms = 200; size_t numVertexUniforms = 200;
size_t numFragmentUniforms = 200; size_t numFragmentUniforms = 200;
DataType dataType = DataType::VEC4; DataType dataType = DataType::VEC4;
DataMode dataMode = DataMode::REPEAT; DataMode dataMode = DataMode::REPEAT;
ProgramMode programMode = ProgramMode::SINGLE; MatrixLayout matrixLayout = MatrixLayout::NO_TRANSPOSE;
ProgramMode programMode = ProgramMode::SINGLE;
}; };
std::ostream &operator<<(std::ostream &os, const UniformsParams &params) std::ostream &operator<<(std::ostream &os, const UniformsParams &params)
...@@ -88,9 +98,22 @@ std::string UniformsParams::suffix() const ...@@ -88,9 +98,22 @@ std::string UniformsParams::suffix() const
{ {
strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_vec4"; strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_vec4";
} }
else if (dataType == DataType::MAT3x3)
{
strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_mat3x3";
}
else if (dataType == DataType::MAT3x4)
{
strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_mat3x4";
}
else else
{ {
strstr << "_matrix"; strstr << "_" << (numVertexUniforms + numFragmentUniforms) << "_mat4x4";
}
if (matrixLayout == MatrixLayout::TRANSPOSE)
{
strstr << "_transpose";
} }
if (programMode == ProgramMode::MULTIPLE) if (programMode == ProgramMode::MULTIPLE)
...@@ -162,12 +185,33 @@ void UniformsBenchmark::initializeBenchmark() ...@@ -162,12 +185,33 @@ void UniformsBenchmark::initializeBenchmark()
glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVertexUniformVectors); glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVertexUniformVectors);
glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxFragmentUniformVectors); glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxFragmentUniformVectors);
bool isMatrix = params.dataType == DataType::MAT4; GLint vectorCountPerUniform;
bool isMatrix;
switch (params.dataType)
{
case DataType::MAT3x3:
vectorCountPerUniform = 3;
isMatrix = true;
break;
case DataType::MAT3x4:
// depends on transpose, conservatively set to 4
vectorCountPerUniform = 4;
isMatrix = true;
break;
case DataType::MAT4x4:
vectorCountPerUniform = 4;
isMatrix = true;
break;
default:
vectorCountPerUniform = 1;
isMatrix = false;
break;
}
GLint numVertexUniformVectors = GLint numVertexUniformVectors =
static_cast<GLint>(params.numVertexUniforms) * (isMatrix ? 4 : 1); static_cast<GLint>(params.numVertexUniforms) * vectorCountPerUniform;
GLint numFragmentUniformVectors = GLint numFragmentUniformVectors =
static_cast<GLint>(params.numFragmentUniforms) * (isMatrix ? 4 : 1); static_cast<GLint>(params.numFragmentUniforms) * vectorCountPerUniform;
if (numVertexUniformVectors > maxVertexUniformVectors) if (numVertexUniformVectors > maxVertexUniformVectors)
{ {
...@@ -219,20 +263,39 @@ std::string GetUniformLocationName(size_t idx, bool vertexShader) ...@@ -219,20 +263,39 @@ std::string GetUniformLocationName(size_t idx, bool vertexShader)
void UniformsBenchmark::initShaders() void UniformsBenchmark::initShaders()
{ {
const auto &params = GetParam(); const auto &params = GetParam();
bool isMatrix = (params.dataType == DataType::MAT4);
std::stringstream vstrstr; const std::string kUniformVarPlaceHolder = "%s";
vstrstr << "precision mediump float;\n"; std::string typeString;
std::string typeString = isMatrix ? "mat4" : "vec4"; std::string uniformOperationTemplate;
std::string constVector = "const vec4 one = vec4(1, 1, 1, 1);\n"; switch (params.dataType)
vstrstr << "attribute vec4 pos;\n";
if (isMatrix)
{ {
vstrstr << constVector; case DataType::VEC4:
typeString = "vec4";
uniformOperationTemplate = kUniformVarPlaceHolder;
break;
case DataType::MAT3x3:
typeString = "mat3";
uniformOperationTemplate =
"mat4(" + kUniformVarPlaceHolder + ") * vec4(1.0, 1.0, 1.0, 1.0)";
break;
case DataType::MAT3x4:
typeString = "mat3x4";
uniformOperationTemplate =
"mat4(" + kUniformVarPlaceHolder + ") * vec4(1.0, 1.0, 1.0, 1.0)";
break;
case DataType::MAT4x4:
typeString = "mat4";
uniformOperationTemplate = kUniformVarPlaceHolder + "* vec4(1.0, 1.0, 1.0, 1.0)";
break;
default:
UNREACHABLE();
} }
std::stringstream vstrstr;
vstrstr << "#version 300 es\n";
vstrstr << "precision mediump float;\n";
vstrstr << "in vec4 pos;\n";
for (size_t i = 0; i < params.numVertexUniforms; i++) for (size_t i = 0; i < params.numVertexUniforms; i++)
{ {
vstrstr << "uniform " << typeString << " " << GetUniformLocationName(i, true) << ";\n"; vstrstr << "uniform " << typeString << " " << GetUniformLocationName(i, true) << ";\n";
...@@ -243,22 +306,21 @@ void UniformsBenchmark::initShaders() ...@@ -243,22 +306,21 @@ void UniformsBenchmark::initShaders()
" gl_Position = pos;\n"; " gl_Position = pos;\n";
for (size_t i = 0; i < params.numVertexUniforms; i++) for (size_t i = 0; i < params.numVertexUniforms; i++)
{ {
vstrstr << " gl_Position += " << GetUniformLocationName(i, true); std::string uniformOperation = uniformOperationTemplate;
if (isMatrix) std::size_t pos = uniformOperation.find(kUniformVarPlaceHolder);
{ ASSERT(pos != std::string::npos);
vstrstr << " * one"; uniformOperation.replace(pos, kUniformVarPlaceHolder.size(),
} GetUniformLocationName(i, true));
vstrstr << " gl_Position += ";
vstrstr << uniformOperation;
vstrstr << ";\n"; vstrstr << ";\n";
} }
vstrstr << "}"; vstrstr << "}";
std::stringstream fstrstr; std::stringstream fstrstr;
fstrstr << "#version 300 es\n";
fstrstr << "precision mediump float;\n"; fstrstr << "precision mediump float;\n";
fstrstr << "out vec4 fragColor;\n";
if (isMatrix)
{
fstrstr << constVector;
}
for (size_t i = 0; i < params.numFragmentUniforms; i++) for (size_t i = 0; i < params.numFragmentUniforms; i++)
{ {
...@@ -266,14 +328,16 @@ void UniformsBenchmark::initShaders() ...@@ -266,14 +328,16 @@ void UniformsBenchmark::initShaders()
} }
fstrstr << "void main()\n" fstrstr << "void main()\n"
"{\n" "{\n"
" gl_FragColor = vec4(0, 0, 0, 0);\n"; " fragColor = vec4(0, 0, 0, 0);\n";
for (size_t i = 0; i < params.numFragmentUniforms; i++) for (size_t i = 0; i < params.numFragmentUniforms; i++)
{ {
fstrstr << " gl_FragColor += " << GetUniformLocationName(i, false); std::string uniformOperation = uniformOperationTemplate;
if (isMatrix) std::size_t pos = uniformOperation.find(kUniformVarPlaceHolder);
{ ASSERT(pos != std::string::npos);
fstrstr << " * one"; uniformOperation.replace(pos, kUniformVarPlaceHolder.size(),
} GetUniformLocationName(i, false));
fstrstr << " fragColor += ";
fstrstr << uniformOperation;
fstrstr << ";\n"; fstrstr << ";\n";
} }
fstrstr << "}"; fstrstr << "}";
...@@ -339,32 +403,63 @@ void UniformsBenchmark::drawBenchmark() ...@@ -339,32 +403,63 @@ void UniformsBenchmark::drawBenchmark()
{ {
const auto &params = GetParam(); const auto &params = GetParam();
if (params.dataType == DataType::MAT4) GLboolean transpose = static_cast<GLboolean>(params.matrixLayout == MatrixLayout::TRANSPOSE);
{
auto setFunc = [](const std::vector<GLuint> &locations, const MatrixData &matrixData,
size_t uniform, size_t frameIndex) {
glUniformMatrix4fv(locations[uniform], 1, GL_FALSE,
matrixData[frameIndex][uniform].data);
};
drawLoop<false>(setFunc); switch (params.dataType)
}
else
{ {
auto setFunc = [](const std::vector<GLuint> &locations, const MatrixData &matrixData, case DataType::MAT4x4:
size_t uniform, size_t frameIndex) { {
float value = static_cast<float>(uniform); auto setFunc = [=](const std::vector<GLuint> &locations, const MatrixData &matrixData,
glUniform4f(locations[uniform], value, value, value, value); size_t uniform, size_t frameIndex) {
}; glUniformMatrix4fv(locations[uniform], 1, transpose,
matrixData[frameIndex][uniform].data);
};
if (params.programMode == ProgramMode::MULTIPLE) drawLoop<false>(setFunc);
break;
}
case DataType::MAT3x4:
{ {
drawLoop<true>(setFunc); auto setFunc = [=](const std::vector<GLuint> &locations, const MatrixData &matrixData,
size_t uniform, size_t frameIndex) {
glUniformMatrix3x4fv(locations[uniform], 1, transpose,
matrixData[frameIndex][uniform].data);
};
drawLoop<false>(setFunc);
break;
} }
else case DataType::MAT3x3:
{ {
auto setFunc = [=](const std::vector<GLuint> &locations, const MatrixData &matrixData,
size_t uniform, size_t frameIndex) {
glUniformMatrix3fv(locations[uniform], 1, transpose,
matrixData[frameIndex][uniform].data);
};
drawLoop<false>(setFunc); drawLoop<false>(setFunc);
break;
} }
case DataType::VEC4:
{
auto setFunc = [](const std::vector<GLuint> &locations, const MatrixData &matrixData,
size_t uniform, size_t frameIndex) {
float value = static_cast<float>(uniform);
glUniform4f(locations[uniform], value, value, value, value);
};
if (params.programMode == ProgramMode::MULTIPLE)
{
drawLoop<true>(setFunc);
}
else
{
drawLoop<false>(setFunc);
}
break;
}
default:
UNREACHABLE();
} }
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
...@@ -383,12 +478,16 @@ UniformsParams VectorUniforms(const EGLPlatformParameters &egl, ...@@ -383,12 +478,16 @@ UniformsParams VectorUniforms(const EGLPlatformParameters &egl,
return params; return params;
} }
UniformsParams MatrixUniforms(const EGLPlatformParameters &egl, DataMode dataMode) UniformsParams MatrixUniforms(const EGLPlatformParameters &egl,
DataMode dataMode,
DataType dataType,
MatrixLayout matrixLayout)
{ {
UniformsParams params; UniformsParams params;
params.eglParameters = egl; params.eglParameters = egl;
params.dataType = DataType::MAT4; params.dataType = dataType;
params.dataMode = dataMode; params.dataMode = dataMode;
params.matrixLayout = matrixLayout;
// Reduce the number of uniforms to fit within smaller upper limits on some configs. // Reduce the number of uniforms to fit within smaller upper limits on some configs.
params.numVertexUniforms = 55; params.numVertexUniforms = 55;
...@@ -404,14 +503,27 @@ TEST_P(UniformsBenchmark, Run) ...@@ -404,14 +503,27 @@ TEST_P(UniformsBenchmark, Run)
run(); run();
} }
ANGLE_INSTANTIATE_TEST(UniformsBenchmark, ANGLE_INSTANTIATE_TEST(
VectorUniforms(D3D9(), DataMode::UPDATE), UniformsBenchmark,
VectorUniforms(D3D11(), DataMode::REPEAT), VectorUniforms(D3D11(), DataMode::REPEAT),
VectorUniforms(D3D11(), DataMode::UPDATE), VectorUniforms(D3D11(), DataMode::UPDATE),
VectorUniforms(D3D11_NULL(), DataMode::UPDATE), VectorUniforms(D3D11_NULL(), DataMode::UPDATE),
VectorUniforms(OPENGL_OR_GLES(), DataMode::UPDATE), VectorUniforms(OPENGL_OR_GLES(), DataMode::UPDATE),
VectorUniforms(OPENGL_OR_GLES(), DataMode::REPEAT), VectorUniforms(OPENGL_OR_GLES(), DataMode::REPEAT),
VectorUniforms(OPENGL_OR_GLES_NULL(), DataMode::UPDATE), VectorUniforms(OPENGL_OR_GLES_NULL(), DataMode::UPDATE),
MatrixUniforms(D3D11(), DataMode::UPDATE), MatrixUniforms(D3D11(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),
MatrixUniforms(OPENGL_OR_GLES(), DataMode::UPDATE), MatrixUniforms(OPENGL_OR_GLES(),
VectorUniforms(D3D11_NULL(), DataMode::REPEAT, ProgramMode::MULTIPLE)); DataMode::UPDATE,
DataType::MAT4x4,
MatrixLayout::NO_TRANSPOSE),
MatrixUniforms(VULKAN_NULL(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),
MatrixUniforms(VULKAN_NULL(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::TRANSPOSE),
MatrixUniforms(VULKAN_NULL(), DataMode::REPEAT, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),
MatrixUniforms(VULKAN_NULL(), DataMode::UPDATE, DataType::MAT3x4, MatrixLayout::NO_TRANSPOSE),
MatrixUniforms(VULKAN_NULL(), DataMode::UPDATE, DataType::MAT3x3, MatrixLayout::TRANSPOSE),
MatrixUniforms(VULKAN_NULL(), DataMode::REPEAT, DataType::MAT3x3, MatrixLayout::TRANSPOSE),
MatrixUniforms(VULKAN(), DataMode::UPDATE, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),
MatrixUniforms(VULKAN(), DataMode::REPEAT, DataType::MAT4x4, MatrixLayout::NO_TRANSPOSE),
MatrixUniforms(VULKAN(), DataMode::UPDATE, DataType::MAT3x3, MatrixLayout::NO_TRANSPOSE),
MatrixUniforms(VULKAN(), DataMode::REPEAT, DataType::MAT3x3, MatrixLayout::NO_TRANSPOSE),
VectorUniforms(D3D11_NULL(), DataMode::REPEAT, ProgramMode::MULTIPLE));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment