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, ...@@ -2602,16 +2602,13 @@ void ProgramD3D::setUniformMatrixfvInternal(GLint location,
unsigned int arrayElementOffset = uniformLocation.arrayIndex; unsigned int arrayElementOffset = uniformLocation.arrayIndex;
unsigned int elementCount = targetUniform->getArraySizeProduct(); unsigned int elementCount = targetUniform->getArraySizeProduct();
// Internally store matrices as transposed versions to accomodate HLSL matrix indexing
transpose = !transpose;
for (gl::ShaderType shaderType : gl::AllShaderTypes()) for (gl::ShaderType shaderType : gl::AllShaderTypes())
{ {
if (targetUniform->mShaderData[shaderType]) if (targetUniform->mShaderData[shaderType])
{ {
if (SetFloatUniformMatrix<cols, rows>(arrayElementOffset, elementCount, countIn, if (SetFloatUniformMatrixHLSL<cols, rows>(arrayElementOffset, elementCount, countIn,
transpose, value, transpose, value,
targetUniform->mShaderData[shaderType])) targetUniform->mShaderData[shaderType]))
{ {
mShaderUniformsDirty.set(shaderType); mShaderUniformsDirty.set(shaderType);
} }
......
...@@ -98,64 +98,75 @@ void WriteFloatColor(const gl::ColorF &color, ...@@ -98,64 +98,75 @@ void WriteFloatColor(const gl::ColorF &color,
colorWriteFunction(reinterpret_cast<const uint8_t *>(&color), destPixelData); colorWriteFunction(reinterpret_cast<const uint8_t *>(&color), destPixelData);
} }
template <typename T, int cols, int rows> template <int cols, int rows>
bool TransposeExpandMatrix(T *target, const GLfloat *value) int GetFlattenedIndex(bool isColumnMajor, int col, int row)
{ {
constexpr int targetWidth = 4; if (isColumnMajor)
constexpr int targetHeight = rows; {
constexpr int srcWidth = rows; return col * rows + row;
constexpr int srcHeight = cols; }
else
{
return row * cols + col;
}
}
constexpr int copyWidth = std::min(targetHeight, srcWidth); template <typename T, int colsSrc, int rowsSrc, bool IsDstColumnMajor, int colsDst, int rowsDst>
constexpr int copyHeight = std::min(targetWidth, srcHeight); 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; return false;
} }
memcpy(target, staging, targetWidth * targetHeight * sizeof(T)); memcpy(target, staging, kDstFlatSize * sizeof(T));
return true; return true;
} }
template <typename T, int cols, int rows> template <int colsSrc, int rowsSrc, bool IsDstColumnMajor, int colsDst, int rowsDst>
bool ExpandMatrix(T *target, const GLfloat *value) bool SetFloatUniformMatrix(unsigned int arrayElementOffset,
unsigned int elementCount,
GLsizei countIn,
GLboolean transpose,
const GLfloat *value,
uint8_t *targetData)
{ {
constexpr int kTargetWidth = 4; unsigned int count =
constexpr int kTargetHeight = rows; std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
constexpr int kSrcWidth = cols;
constexpr int kSrcHeight = rows;
constexpr int kCopyWidth = std::min(kTargetWidth, kSrcWidth);
constexpr int kCopyHeight = std::min(kTargetHeight, kSrcHeight);
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++) bool dirty = false;
{
for (int x = 0; x < kCopyWidth; x++)
{
staging[y * kTargetWidth + x] = static_cast<T>(value[y * kSrcWidth + x]);
}
}
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 dirty;
return true;
} }
} // anonymous namespace } // anonymous namespace
...@@ -471,54 +482,57 @@ angle::Result IncompleteTextureSet::getIncompleteTexture( ...@@ -471,54 +482,57 @@ angle::Result IncompleteTextureSet::getIncompleteTexture(
return angle::Result::Continue; return angle::Result::Continue;
} }
#define ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(cols, rows) \ #define ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \
template bool SetFloatUniformMatrix<cols, rows>(unsigned int, unsigned int, GLsizei, \ template bool SetFloatUniformMatrix##api<cols, rows>(unsigned int, unsigned int, GLsizei, \
GLboolean, const GLfloat *, uint8_t *) GLboolean, const GLfloat *, uint8_t *)
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(2, 2); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 2);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(3, 3); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 3);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(4, 4); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 4);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(2, 3); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 3);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(3, 2); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 2);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(2, 4); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 4);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(4, 2); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 2);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(3, 4); ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 4);
ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(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, 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 #undef ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC
template <int cols, int rows> template <int cols, int rows>
bool SetFloatUniformMatrix(unsigned int arrayElementOffset, bool SetFloatUniformMatrixGLSL(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)
{ {
unsigned int count = // GLSL expects matrix uniforms to be column-major, and each column is padded to 4 rows.
std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn)); return SetFloatUniformMatrix<cols, rows, true, cols, 4>(arrayElementOffset, elementCount,
countIn, transpose, value, targetData);
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;
}
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); template void GetMatrixUniform<GLint>(GLenum, GLint *, const GLint *, bool);
......
...@@ -257,14 +257,22 @@ class IncompleteTextureSet final : angle::NonCopyable ...@@ -257,14 +257,22 @@ class IncompleteTextureSet final : angle::NonCopyable
gl::TextureMap mIncompleteTextures; 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. // The return value indicate if the data was updated or not.
template <int cols, int rows> template <int cols, int rows>
bool SetFloatUniformMatrix(unsigned int arrayElementOffset, bool SetFloatUniformMatrixGLSL(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);
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. // 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);
......
...@@ -663,7 +663,7 @@ void ProgramVk::setUniformMatrixfv(GLint location, ...@@ -663,7 +663,7 @@ void ProgramVk::setUniformMatrixfv(GLint location,
continue; continue;
} }
bool updated = SetFloatUniformMatrix<cols, rows>( bool updated = SetFloatUniformMatrixGLSL<cols, rows>(
locationInfo.arrayIndex, linkedUniform.getArraySizeProduct(), count, transpose, value, locationInfo.arrayIndex, linkedUniform.getArraySizeProduct(), count, transpose, value,
uniformBlock.uniformData.data() + layoutInfo.offset); uniformBlock.uniformData.data() + layoutInfo.offset);
......
...@@ -611,12 +611,6 @@ ...@@ -611,12 +611,6 @@
// Shader support: // Shader support:
3219 VULKAN : dEQP-GLES3.functional.negative_api.shader.link_program = FAIL 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.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 3443 VULKAN : dEQP-GLES3.functional.ubo.random.basic_arrays.10 = FAIL
// New vertex attribute formats: // New vertex attribute formats:
......
...@@ -687,9 +687,6 @@ class UniformTestES3 : public ANGLETest ...@@ -687,9 +687,6 @@ class UniformTestES3 : public ANGLETest
// 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)
{ {
// TODO(syoussefi): Bug in glGetUniformfv. http://anglebug.com/3387
ANGLE_SKIP_TEST_IF(IsVulkan());
constexpr char kFS[] = constexpr char kFS[] =
"#version 300 es\n" "#version 300 es\n"
"precision mediump float;\n" "precision mediump float;\n"
...@@ -1246,9 +1243,6 @@ TEST_P(UniformTestES3, StructWithNonSquareMatrixAndBool) ...@@ -1246,9 +1243,6 @@ TEST_P(UniformTestES3, StructWithNonSquareMatrixAndBool)
// Test that matrix uniform upload is correct. // Test that matrix uniform upload is correct.
TEST_P(UniformTestES3, MatrixUniformUpload) 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 kMinDims = 2;
constexpr size_t kMaxDims = 4; constexpr size_t kMaxDims = 4;
...@@ -1280,6 +1274,9 @@ TEST_P(UniformTestES3, MatrixUniformUpload) ...@@ -1280,6 +1274,9 @@ TEST_P(UniformTestES3, MatrixUniformUpload)
"out highp vec4 colorOut;\n" "out highp vec4 colorOut;\n"
"uniform mat" "uniform mat"
<< cols << 'x' << rows << cols << 'x' << rows
<< " unused;\n"
"uniform mat"
<< cols << 'x' << rows
<< " m;\n" << " m;\n"
"void main()\n" "void main()\n"
"{\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