Commit b783fbc7 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: Fix matrix uniforms

A piece of code shared with d3d was used to implement this feature. However, we store the uniform data transposed and row-major in d3d to accomodate the fact that matrix indexing in HLSL is the opposite of GLSL (mat[row][col] in HLSL as opposed to mat[col][row] in GLSL). There were two functions that copied the source matrix fields either as column-major or source-major (corresponding to `transpose` false or true respectively in glUniformMatrix*) into a row-major destination. These functions are refactored into one, which copies from any-major source to any-major destination. The HLSL backend uses the "to row-major" variant and the Vulkan backend uses the "to column-major" variant. Bug: angleproject:3198 Change-Id: I7254da4fbe6916af78c5906abcb82ca01674ab9f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1607541 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent f7033c55
......@@ -2602,16 +2602,13 @@ void ProgramD3D::setUniformMatrixfvInternal(GLint location,
unsigned int arrayElementOffset = uniformLocation.arrayIndex;
unsigned int elementCount = targetUniform->getArraySizeProduct();
// Internally store matrices as transposed versions to accomodate HLSL matrix indexing
transpose = !transpose;
for (gl::ShaderType shaderType : gl::AllShaderTypes())
{
if (targetUniform->mShaderData[shaderType])
{
if (SetFloatUniformMatrix<cols, rows>(arrayElementOffset, elementCount, countIn,
transpose, value,
targetUniform->mShaderData[shaderType]))
if (SetFloatUniformMatrixHLSL<cols, rows>(arrayElementOffset, elementCount, countIn,
transpose, value,
targetUniform->mShaderData[shaderType]))
{
mShaderUniformsDirty.set(shaderType);
}
......
......@@ -98,64 +98,75 @@ void WriteFloatColor(const gl::ColorF &color,
colorWriteFunction(reinterpret_cast<const uint8_t *>(&color), destPixelData);
}
template <typename T, int cols, int rows>
bool TransposeExpandMatrix(T *target, const GLfloat *value)
template <int cols, int rows>
int GetFlattenedIndex(bool isColumnMajor, int col, int row)
{
constexpr int targetWidth = 4;
constexpr int targetHeight = rows;
constexpr int srcWidth = rows;
constexpr int srcHeight = cols;
if (isColumnMajor)
{
return col * rows + row;
}
else
{
return row * cols + col;
}
}
constexpr int copyWidth = std::min(targetHeight, srcWidth);
constexpr int copyHeight = std::min(targetWidth, srcHeight);
template <typename T, int colsSrc, int rowsSrc, bool IsDstColumnMajor, int colsDst, int rowsDst>
bool ExpandMatrix(T *target, const GLfloat *value, bool isSrcColumnMajor)
{
static_assert(colsSrc <= colsDst && rowsSrc <= rowsDst, "Can only expand!");
T staging[targetWidth * targetHeight] = {0};
constexpr int kDstFlatSize = colsDst * rowsDst;
T staging[kDstFlatSize] = {0};
for (int x = 0; x < copyWidth; x++)
for (int r = 0; r < rowsSrc; r++)
{
for (int y = 0; y < copyHeight; y++)
for (int c = 0; c < colsSrc; c++)
{
staging[x * targetWidth + y] = static_cast<T>(value[y * srcWidth + x]);
int srcIndex = GetFlattenedIndex<colsSrc, rowsSrc>(isSrcColumnMajor, c, r);
int dstIndex = GetFlattenedIndex<colsDst, rowsDst>(IsDstColumnMajor, c, r);
staging[dstIndex] = static_cast<T>(value[srcIndex]);
}
}
if (memcmp(target, staging, targetWidth * targetHeight * sizeof(T)) == 0)
if (memcmp(target, staging, kDstFlatSize * sizeof(T)) == 0)
{
return false;
}
memcpy(target, staging, targetWidth * targetHeight * sizeof(T));
memcpy(target, staging, kDstFlatSize * sizeof(T));
return true;
}
template <typename T, int cols, int rows>
bool ExpandMatrix(T *target, const GLfloat *value)
template <int colsSrc, int rowsSrc, bool IsDstColumnMajor, int colsDst, int rowsDst>
bool SetFloatUniformMatrix(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
uint8_t *targetData)
{
constexpr int kTargetWidth = 4;
constexpr int kTargetHeight = rows;
constexpr int kSrcWidth = cols;
constexpr int kSrcHeight = rows;
constexpr int kCopyWidth = std::min(kTargetWidth, kSrcWidth);
constexpr int kCopyHeight = std::min(kTargetHeight, kSrcHeight);
unsigned int count =
std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
T staging[kTargetWidth * kTargetHeight] = {0};
const unsigned int targetMatrixStride = colsDst * rowsDst;
GLfloat *target = reinterpret_cast<GLfloat *>(
targetData + arrayElementOffset * sizeof(GLfloat) * targetMatrixStride);
for (int y = 0; y < kCopyHeight; y++)
{
for (int x = 0; x < kCopyWidth; x++)
{
staging[y * kTargetWidth + x] = static_cast<T>(value[y * kSrcWidth + x]);
}
}
bool dirty = false;
if (memcmp(target, staging, kTargetWidth * kTargetHeight * sizeof(T)) == 0)
for (unsigned int i = 0; i < count; i++)
{
return false;
const bool isSrcColumnMajor = !transpose;
dirty = ExpandMatrix<GLfloat, colsSrc, rowsSrc, IsDstColumnMajor, colsDst, rowsDst>(
target, value, isSrcColumnMajor) ||
dirty;
target += targetMatrixStride;
value += colsSrc * rowsSrc;
}
memcpy(target, staging, kTargetWidth * kTargetHeight * sizeof(T));
return true;
return dirty;
}
} // anonymous namespace
......@@ -471,54 +482,57 @@ angle::Result IncompleteTextureSet::getIncompleteTexture(
return angle::Result::Continue;
}
#define ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(cols, rows) \
template bool SetFloatUniformMatrix<cols, rows>(unsigned int, unsigned int, GLsizei, \
GLboolean, const GLfloat *, uint8_t *)
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(2, 2);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(3, 3);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(4, 4);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(2, 3);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(3, 2);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(2, 4);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(4, 2);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(3, 4);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(4, 3);
#define ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \
template bool SetFloatUniformMatrix##api<cols, rows>(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, 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, 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, 3, 4);
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, 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, 3, 2);
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, 4, 3);
#undef ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC
template <int cols, int rows>
bool SetFloatUniformMatrix(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
uint8_t *targetData)
bool SetFloatUniformMatrixGLSL(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
uint8_t *targetData)
{
unsigned int count =
std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
const unsigned int targetMatrixStride = (4 * rows);
GLfloat *target = reinterpret_cast<GLfloat *>(
targetData + arrayElementOffset * sizeof(GLfloat) * targetMatrixStride);
bool dirty = false;
for (unsigned int i = 0; i < count; i++)
{
if (transpose == GL_FALSE)
{
dirty = ExpandMatrix<GLfloat, cols, rows>(target, value) || dirty;
}
else
{
dirty = TransposeExpandMatrix<GLfloat, cols, rows>(target, value) || dirty;
}
target += targetMatrixStride;
value += cols * 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,
countIn, transpose, value, targetData);
}
return dirty;
template <int cols, int rows>
bool SetFloatUniformMatrixHLSL(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
uint8_t *targetData)
{
// Internally store matrices as row-major to accomodate HLSL matrix indexing. Each row is
// padded to 4 columns.
return SetFloatUniformMatrix<cols, rows, false, 4, rows>(arrayElementOffset, elementCount,
countIn, transpose, value, targetData);
}
template void GetMatrixUniform<GLint>(GLenum, GLint *, const GLint *, bool);
......
......@@ -257,14 +257,22 @@ class IncompleteTextureSet final : angle::NonCopyable
gl::TextureMap mIncompleteTextures;
};
// Helpers to set a matrix uniform value based on GLSL or HLSL semantics.
// The return value indicate if the data was updated or not.
template <int cols, int rows>
bool SetFloatUniformMatrix(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
uint8_t *targetData);
bool SetFloatUniformMatrixGLSL(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
uint8_t *targetData);
template <int cols, int rows>
bool SetFloatUniformMatrixHLSL(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
uint8_t *targetData);
// Helper method to de-tranpose a matrix uniform for an API query.
void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose);
......
......@@ -663,7 +663,7 @@ void ProgramVk::setUniformMatrixfv(GLint location,
continue;
}
bool updated = SetFloatUniformMatrix<cols, rows>(
bool updated = SetFloatUniformMatrixGLSL<cols, rows>(
locationInfo.arrayIndex, linkedUniform.getArraySizeProduct(), count, transpose, value,
uniformBlock.uniformData.data() + layoutInfo.offset);
......
......@@ -611,12 +611,6 @@
// Shader support:
3219 VULKAN : dEQP-GLES3.functional.negative_api.shader.link_program = FAIL
3219 VULKAN : dEQP-GLES3.functional.negative_api.shader.use_program = FAIL
3219 VULKAN : dEQP-GLES3.functional.shaders.linkage.varying.basic_types.mat* = SKIP
3219 VULKAN : dEQP-GLES3.functional.shaders.linkage.varying.struct.mat* = SKIP
3219 VULKAN : dEQP-GLES3.functional.shaders.conversions.scalar_to_matrix.* = SKIP
3219 VULKAN : dEQP-GLES3.functional.shaders.conversions.matrix* = SKIP
3219 VULKAN : dEQP-GLES3.functional.shaders.functions.datatypes.mat* = SKIP
3219 VULKAN : dEQP-GLES3.functional.shaders.matrix.* = SKIP
3443 VULKAN : dEQP-GLES3.functional.ubo.random.basic_arrays.10 = FAIL
// New vertex attribute formats:
......
......@@ -687,9 +687,6 @@ class UniformTestES3 : public ANGLETest
// Test queries for transposed arrays of non-square matrix uniforms.
TEST_P(UniformTestES3, TransposedMatrixArrayUniformStateQuery)
{
// TODO(syoussefi): Bug in glGetUniformfv. http://anglebug.com/3387
ANGLE_SKIP_TEST_IF(IsVulkan());
constexpr char kFS[] =
"#version 300 es\n"
"precision mediump float;\n"
......@@ -1246,9 +1243,6 @@ TEST_P(UniformTestES3, StructWithNonSquareMatrixAndBool)
// Test that matrix uniform upload is correct.
TEST_P(UniformTestES3, MatrixUniformUpload)
{
// TODO(syoussefi): Bug in matrix uniform handling. http://anglebug.com/3198
ANGLE_SKIP_TEST_IF(IsVulkan());
constexpr size_t kMinDims = 2;
constexpr size_t kMaxDims = 4;
......@@ -1280,6 +1274,9 @@ TEST_P(UniformTestES3, MatrixUniformUpload)
"out highp vec4 colorOut;\n"
"uniform mat"
<< cols << 'x' << rows
<< " unused;\n"
"uniform mat"
<< cols << 'x' << rows
<< " m;\n"
"void main()\n"
"{\n"
......
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