Add unit test verifying float encoding of uniforms.

This test verifies that float scalars and vectors can be added as
uniforms. In Metal, this is a particularly interesting challenge because
we represent half values as 16-bit floats.

Change-Id: I4ce2280a61afee905ac5980792b6dbe6e4be572f
Bug: skia:13478
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/554344
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
John Stiles 2022-06-30 09:33:32 -04:00 committed by SkCQ
parent 91c25e9b05
commit eb35a3783e
2 changed files with 104 additions and 2 deletions

View File

@ -162,6 +162,60 @@ static constexpr bool SkSLTypeIsIntegralType(SkSLType type) {
SkUNREACHABLE;
}
/** Is the shading language type full precision? */
static constexpr bool SkSLTypeIsFullPrecisionNumericType(SkSLType type) {
switch (type) {
// Half-precision types:
case SkSLType::kShort:
case SkSLType::kShort2:
case SkSLType::kShort3:
case SkSLType::kShort4:
case SkSLType::kUShort:
case SkSLType::kUShort2:
case SkSLType::kUShort3:
case SkSLType::kUShort4:
case SkSLType::kHalf:
case SkSLType::kHalf2:
case SkSLType::kHalf3:
case SkSLType::kHalf4:
case SkSLType::kHalf2x2:
case SkSLType::kHalf3x3:
case SkSLType::kHalf4x4:
// Non-numeric types:
case SkSLType::kVoid:
case SkSLType::kTexture2DSampler:
case SkSLType::kTextureExternalSampler:
case SkSLType::kTexture2DRectSampler:
case SkSLType::kTexture2D:
case SkSLType::kSampler:
case SkSLType::kInput:
case SkSLType::kBool:
case SkSLType::kBool2:
case SkSLType::kBool3:
case SkSLType::kBool4:
return false;
// Full-precision numeric types:
case SkSLType::kInt:
case SkSLType::kInt2:
case SkSLType::kInt3:
case SkSLType::kInt4:
case SkSLType::kUInt:
case SkSLType::kUInt2:
case SkSLType::kUInt3:
case SkSLType::kUInt4:
case SkSLType::kFloat:
case SkSLType::kFloat2:
case SkSLType::kFloat3:
case SkSLType::kFloat4:
case SkSLType::kFloat2x2:
case SkSLType::kFloat3x3:
case SkSLType::kFloat4x4:
return true;
}
SkUNREACHABLE;
}
/**
* Is the shading language type supported as a uniform (ie, does it have a corresponding set
* function on GrGLSLProgramDataManager)?

View File

@ -5,6 +5,8 @@
* found in the LICENSE file.
*/
#include "include/private/SkHalf.h"
#include "src/core/SkPipelineData.h"
#include "src/core/SkSLTypeShared.h"
#include "src/core/SkUniform.h"
#include "src/gpu/graphite/UniformManager.h"
@ -29,7 +31,15 @@ static constexpr SkSLType kTypes[] = {
SkSLType::kHalf2x2, SkSLType::kHalf3x3, SkSLType::kHalf4x4,
};
static constexpr uint8_t kZeroData[64] = {};
static constexpr float kFloats[16] = { 1.0f, 2.0f, 3.0f, 4.0f,
5.0f, 6.0f, 7.0f, 8.0f,
9.0f, 10.0f, 11.0f, 12.0f,
13.0f, 14.0f, 15.0f, 16.0f };
static constexpr SkHalf kHalfs[16] = { 0x3C00, 0x4000, 0x4200, 0x4400,
0x4500, 0x4600, 0x4700, 0x4800,
0x4880, 0x4900, 0x4980, 0x4A00,
0x4A80, 0x4B00, 0x4B80, 0x4C00 };
DEF_TEST(UniformManagerCheckSingleUniform, r) {
// Verify that the uniform manager can hold all the basic uniform types, in every layout.
@ -39,9 +49,47 @@ DEF_TEST(UniformManagerCheckSingleUniform, r) {
for (SkSLType type : kTypes) {
const SkUniform expectations[] = {{"uniform", type}};
mgr.setExpectedUniforms(SkSpan(expectations));
mgr.write(type, 1, kZeroData);
mgr.write(type, 1, kFloats);
REPORTER_ASSERT(r, mgr.size() > 0);
mgr.reset();
}
}
}
DEF_TEST(UniformManagerCheckFloatEncoding, r) {
// Verify that the uniform manager encodes float data properly.
for (Layout layout : kLayouts) {
UniformManager mgr(layout);
for (SkSLType type : kTypes) {
// Only test scalar and vector floats. (Matrices can introduce padding between values.)
int vecLength = SkSLTypeVecLength(type);
if (!SkSLTypeIsFloatType(type) || vecLength < 0) {
continue;
}
// Write our uniform float scalar/vector.
const SkUniform expectations[] = {{"uniform", type}};
mgr.setExpectedUniforms(SkSpan(expectations));
mgr.write(type, 1, kFloats);
// Read back the uniform data.
SkUniformDataBlock uniformData = mgr.peekData();
if (layout == Layout::kMetal && !SkSLTypeIsFullPrecisionNumericType(type)) {
// Metal should encode half-precision float uniforms in 16-bit floats.
REPORTER_ASSERT(r, uniformData.size() >= vecLength * sizeof(SkHalf));
REPORTER_ASSERT(r, 0 == memcmp(kHalfs, uniformData.data(),
vecLength * sizeof(SkHalf)),
"Layout:%d Type:%d encoding failed", (int)layout, (int)type);
} else {
// Other layouts should always encode float uniforms in full precision.
REPORTER_ASSERT(r, uniformData.size() >= vecLength * sizeof(float));
REPORTER_ASSERT(r, 0 == memcmp(kFloats, uniformData.data(),
vecLength * sizeof(float)),
"Layout:%d Type:%d encoding failed", (int)layout, (int)type);
}
mgr.reset();
}
}
}