GLSL: implement pack/unpack builtins.

Bug: tint:1428
Change-Id: Ic1db31feb6c6da4a98f6a37b40c77be887662825
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/82200
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Stephen White
2022-02-28 21:19:02 +00:00
committed by Tint LUCI CQ
parent 59f1e8d06c
commit bee5fa6881
44 changed files with 191 additions and 1216 deletions

View File

@@ -679,12 +679,6 @@ bool GeneratorImpl::EmitBuiltinCall(std::ostream& out,
if (builtin->Type() == sem::BuiltinType::kFma && version_.IsES()) {
return EmitEmulatedFMA(out, expr);
}
if (builtin->IsDataPacking()) {
return EmitDataPackingCall(out, expr, builtin);
}
if (builtin->IsDataUnpacking()) {
return EmitDataUnpackingCall(out, expr, builtin);
}
if (builtin->IsBarrier()) {
return EmitBarrierCall(out, builtin);
}
@@ -1222,142 +1216,6 @@ bool GeneratorImpl::EmitRadiansCall(std::ostream& out,
});
}
bool GeneratorImpl::EmitDataPackingCall(std::ostream& out,
const ast::CallExpression* expr,
const sem::Builtin* builtin) {
return CallBuiltinHelper(
out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) {
uint32_t dims = 2;
bool is_signed = false;
uint32_t scale = 65535;
if (builtin->Type() == sem::BuiltinType::kPack4x8snorm ||
builtin->Type() == sem::BuiltinType::kPack4x8unorm) {
dims = 4;
scale = 255;
}
if (builtin->Type() == sem::BuiltinType::kPack4x8snorm ||
builtin->Type() == sem::BuiltinType::kPack2x16snorm) {
is_signed = true;
scale = (scale - 1) / 2;
}
switch (builtin->Type()) {
case sem::BuiltinType::kPack4x8snorm:
case sem::BuiltinType::kPack4x8unorm:
case sem::BuiltinType::kPack2x16snorm:
case sem::BuiltinType::kPack2x16unorm: {
{
auto l = line(b);
l << (is_signed ? "" : "u") << "int" << dims
<< " i = " << (is_signed ? "" : "u") << "int" << dims
<< "(round(clamp(" << params[0] << ", "
<< (is_signed ? "-1.0" : "0.0") << ", 1.0) * " << scale
<< ".0))";
if (is_signed) {
l << " & " << (dims == 4 ? "0xff" : "0xffff");
}
l << ";";
}
{
auto l = line(b);
l << "return ";
if (is_signed) {
l << "asuint";
}
l << "(i.x | i.y << " << (32 / dims);
if (dims == 4) {
l << " | i.z << 16 | i.w << 24";
}
l << ");";
}
break;
}
case sem::BuiltinType::kPack2x16float: {
line(b) << "uint2 i = f32tof16(" << params[0] << ");";
line(b) << "return i.x | (i.y << 16);";
break;
}
default:
diagnostics_.add_error(
diag::System::Writer,
"Internal error: unhandled data packing builtin");
return false;
}
return true;
});
}
bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out,
const ast::CallExpression* expr,
const sem::Builtin* builtin) {
return CallBuiltinHelper(
out, expr, builtin,
[&](TextBuffer* b, const std::vector<std::string>& params) {
uint32_t dims = 2;
bool is_signed = false;
uint32_t scale = 65535;
if (builtin->Type() == sem::BuiltinType::kUnpack4x8snorm ||
builtin->Type() == sem::BuiltinType::kUnpack4x8unorm) {
dims = 4;
scale = 255;
}
if (builtin->Type() == sem::BuiltinType::kUnpack4x8snorm ||
builtin->Type() == sem::BuiltinType::kUnpack2x16snorm) {
is_signed = true;
scale = (scale - 1) / 2;
}
switch (builtin->Type()) {
case sem::BuiltinType::kUnpack4x8snorm:
case sem::BuiltinType::kUnpack2x16snorm: {
line(b) << "int j = int(" << params[0] << ");";
{ // Perform sign extension on the converted values.
auto l = line(b);
l << "int" << dims << " i = int" << dims << "(";
if (dims == 2) {
l << "j << 16, j) >> 16";
} else {
l << "j << 24, j << 16, j << 8, j) >> 24";
}
l << ";";
}
line(b) << "return clamp(float" << dims << "(i) / " << scale
<< ".0, " << (is_signed ? "-1.0" : "0.0") << ", 1.0);";
break;
}
case sem::BuiltinType::kUnpack4x8unorm:
case sem::BuiltinType::kUnpack2x16unorm: {
line(b) << "uint j = " << params[0] << ";";
{
auto l = line(b);
l << "uint" << dims << " i = uint" << dims << "(";
l << "j & " << (dims == 2 ? "0xffff" : "0xff") << ", ";
if (dims == 4) {
l << "(j >> " << (32 / dims)
<< ") & 0xff, (j >> 16) & 0xff, j >> 24";
} else {
l << "j >> " << (32 / dims);
}
l << ");";
}
line(b) << "return float" << dims << "(i) / " << scale << ".0;";
break;
}
case sem::BuiltinType::kUnpack2x16float:
line(b) << "uint i = " << params[0] << ";";
line(b) << "return f16tof32(uint2(i & 0xffff, i >> 16));";
break;
default:
diagnostics_.add_error(
diag::System::Writer,
"Internal error: unhandled data packing builtin");
return false;
}
return true;
});
}
bool GeneratorImpl::EmitBarrierCall(std::ostream& out,
const sem::Builtin* builtin) {
// TODO(crbug.com/tint/661): Combine sequential barriers to a single
@@ -1721,10 +1579,30 @@ std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
return "isnan";
case sem::BuiltinType::kMix:
return "mix";
case sem::BuiltinType::kPack2x16float:
return "packHalf2x16";
case sem::BuiltinType::kPack2x16snorm:
return "packSnorm2x16";
case sem::BuiltinType::kPack2x16unorm:
return "packUnorm2x16";
case sem::BuiltinType::kPack4x8snorm:
return "packSnorm4x8";
case sem::BuiltinType::kPack4x8unorm:
return "packUnorm4x8";
case sem::BuiltinType::kReverseBits:
return "bitfieldReverse";
case sem::BuiltinType::kSmoothStep:
return "smoothstep";
case sem::BuiltinType::kUnpack2x16float:
return "unpackHalf2x16";
case sem::BuiltinType::kUnpack2x16snorm:
return "unpackSnorm2x16";
case sem::BuiltinType::kUnpack2x16unorm:
return "unpackUnorm2x16";
case sem::BuiltinType::kUnpack4x8snorm:
return "unpackSnorm4x8";
case sem::BuiltinType::kUnpack4x8unorm:
return "unpackUnorm4x8";
default:
diagnostics_.add_error(
diag::System::Writer,

View File

@@ -253,22 +253,6 @@ class GeneratorImpl : public TextGenerator {
bool EmitRadiansCall(std::ostream& out,
const ast::CallExpression* expr,
const sem::Builtin* builtin);
/// Handles generating a call to data packing builtin
/// @param out the output of the expression stream
/// @param expr the call expression
/// @param builtin the semantic information for the texture builtin
/// @returns true if the call expression is emitted
bool EmitDataPackingCall(std::ostream& out,
const ast::CallExpression* expr,
const sem::Builtin* builtin);
/// Handles generating a call to data unpacking builtin
/// @param out the output of the expression stream
/// @param expr the call expression
/// @param builtin the semantic information for the texture builtin
/// @returns true if the call expression is emitted
bool EmitDataUnpackingCall(std::ostream& out,
const ast::CallExpression* expr,
const sem::Builtin* builtin);
/// Handles a case statement
/// @param stmt the statement
/// @returns true if the statement was emitted successfully

View File

@@ -652,20 +652,22 @@ void main() {
)");
}
#if 0
TEST_F(GlslGeneratorImplTest_Builtin, Pack4x8Snorm) {
auto* call = Call("pack4x8snorm", "p1");
Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate);
WrapInFunction(CallStmt(call));
GeneratorImpl& gen = Build();
gen.increment_indent();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_THAT(gen.result(), HasSubstr("ivec4 tint_tmp = ivec4(round(clamp(p1, "
"-1.0, 1.0) * 127.0)) & 0xff;"));
EXPECT_THAT(out.str(), HasSubstr("asuint(tint_tmp.x | tint_tmp.y << 8 | "
"tint_tmp.z << 16 | tint_tmp.w << 24)"));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
vec4 p1 = vec4(0.0f, 0.0f, 0.0f, 0.0f);
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void test_function() {
packSnorm4x8(p1);
return;
}
)");
}
TEST_F(GlslGeneratorImplTest_Builtin, Pack4x8Unorm) {
@@ -674,13 +676,16 @@ TEST_F(GlslGeneratorImplTest_Builtin, Pack4x8Unorm) {
WrapInFunction(CallStmt(call));
GeneratorImpl& gen = Build();
gen.increment_indent();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_THAT(gen.result(), HasSubstr("uvec4 tint_tmp = uvec4(round(clamp(p1, "
"0.0, 1.0) * 255.0));"));
EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 8 | "
"tint_tmp.z << 16 | tint_tmp.w << 24)"));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
vec4 p1 = vec4(0.0f, 0.0f, 0.0f, 0.0f);
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void test_function() {
packUnorm4x8(p1);
return;
}
)");
}
TEST_F(GlslGeneratorImplTest_Builtin, Pack2x16Snorm) {
@@ -689,12 +694,16 @@ TEST_F(GlslGeneratorImplTest_Builtin, Pack2x16Snorm) {
WrapInFunction(CallStmt(call));
GeneratorImpl& gen = Build();
gen.increment_indent();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_THAT(gen.result(), HasSubstr("int2 tint_tmp = int2(round(clamp(p1, "
"-1.0, 1.0) * 32767.0)) & 0xffff;"));
EXPECT_THAT(out.str(), HasSubstr("asuint(tint_tmp.x | tint_tmp.y << 16)"));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
vec2 p1 = vec2(0.0f, 0.0f);
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void test_function() {
packSnorm2x16(p1);
return;
}
)");
}
TEST_F(GlslGeneratorImplTest_Builtin, Pack2x16Unorm) {
@@ -703,12 +712,16 @@ TEST_F(GlslGeneratorImplTest_Builtin, Pack2x16Unorm) {
WrapInFunction(CallStmt(call));
GeneratorImpl& gen = Build();
gen.increment_indent();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_THAT(gen.result(), HasSubstr("uint2 tint_tmp = uint2(round(clamp(p1, "
"0.0, 1.0) * 65535.0));"));
EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)"));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
vec2 p1 = vec2(0.0f, 0.0f);
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void test_function() {
packUnorm2x16(p1);
return;
}
)");
}
TEST_F(GlslGeneratorImplTest_Builtin, Pack2x16Float) {
@@ -717,11 +730,16 @@ TEST_F(GlslGeneratorImplTest_Builtin, Pack2x16Float) {
WrapInFunction(CallStmt(call));
GeneratorImpl& gen = Build();
gen.increment_indent();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_THAT(gen.result(), HasSubstr("uint2 tint_tmp = f32tof16(p1);"));
EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)"));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
vec2 p1 = vec2(0.0f, 0.0f);
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void test_function() {
packHalf2x16(p1);
return;
}
)");
}
TEST_F(GlslGeneratorImplTest_Builtin, Unpack4x8Snorm) {
@@ -730,15 +748,16 @@ TEST_F(GlslGeneratorImplTest_Builtin, Unpack4x8Snorm) {
WrapInFunction(CallStmt(call));
GeneratorImpl& gen = Build();
gen.increment_indent();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_THAT(gen.result(), HasSubstr("int tint_tmp_1 = int(p1);"));
EXPECT_THAT(gen.result(),
HasSubstr("ivec4 tint_tmp = ivec4(tint_tmp_1 << 24, tint_tmp_1 "
"<< 16, tint_tmp_1 << 8, tint_tmp_1) >> 24;"));
EXPECT_THAT(out.str(),
HasSubstr("clamp(float4(tint_tmp) / 127.0, -1.0, 1.0)"));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
uint p1 = 0u;
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void test_function() {
unpackSnorm4x8(p1);
return;
}
)");
}
TEST_F(GlslGeneratorImplTest_Builtin, Unpack4x8Unorm) {
@@ -747,15 +766,16 @@ TEST_F(GlslGeneratorImplTest_Builtin, Unpack4x8Unorm) {
WrapInFunction(CallStmt(call));
GeneratorImpl& gen = Build();
gen.increment_indent();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_THAT(gen.result(), HasSubstr("uint tint_tmp_1 = p1;"));
EXPECT_THAT(
gen.result(),
HasSubstr("uvec4 tint_tmp = uvec4(tint_tmp_1 & 0xff, (tint_tmp_1 >> "
"8) & 0xff, (tint_tmp_1 >> 16) & 0xff, tint_tmp_1 >> 24);"));
EXPECT_THAT(out.str(), HasSubstr("float4(tint_tmp) / 255.0"));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
uint p1 = 0u;
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void test_function() {
unpackUnorm4x8(p1);
return;
}
)");
}
TEST_F(GlslGeneratorImplTest_Builtin, Unpack2x16Snorm) {
@@ -764,15 +784,16 @@ TEST_F(GlslGeneratorImplTest_Builtin, Unpack2x16Snorm) {
WrapInFunction(CallStmt(call));
GeneratorImpl& gen = Build();
gen.increment_indent();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_THAT(gen.result(), HasSubstr("int tint_tmp_1 = int(p1);"));
EXPECT_THAT(
gen.result(),
HasSubstr("int2 tint_tmp = int2(tint_tmp_1 << 16, tint_tmp_1) >> 16;"));
EXPECT_THAT(out.str(),
HasSubstr("clamp(float2(tint_tmp) / 32767.0, -1.0, 1.0)"));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
uint p1 = 0u;
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void test_function() {
unpackSnorm2x16(p1);
return;
}
)");
}
TEST_F(GlslGeneratorImplTest_Builtin, Unpack2x16Unorm) {
@@ -781,14 +802,16 @@ TEST_F(GlslGeneratorImplTest_Builtin, Unpack2x16Unorm) {
WrapInFunction(CallStmt(call));
GeneratorImpl& gen = Build();
gen.increment_indent();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_THAT(gen.result(), HasSubstr("uint tint_tmp_1 = p1;"));
EXPECT_THAT(gen.result(),
HasSubstr("uint2 tint_tmp = uint2(tint_tmp_1 & 0xffff, "
"tint_tmp_1 >> 16);"));
EXPECT_THAT(out.str(), HasSubstr("float2(tint_tmp) / 65535.0"));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
uint p1 = 0u;
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void test_function() {
unpackUnorm2x16(p1);
return;
}
)");
}
TEST_F(GlslGeneratorImplTest_Builtin, Unpack2x16Float) {
@@ -797,15 +820,17 @@ TEST_F(GlslGeneratorImplTest_Builtin, Unpack2x16Float) {
WrapInFunction(CallStmt(call));
GeneratorImpl& gen = Build();
gen.increment_indent();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_THAT(gen.result(), HasSubstr("uint tint_tmp = p1;"));
EXPECT_THAT(out.str(),
HasSubstr("f16tof32(uint2(tint_tmp & 0xffff, tint_tmp >> 16))"));
}
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
#endif
uint p1 = 0u;
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void test_function() {
unpackHalf2x16(p1);
return;
}
)");
}
TEST_F(GlslGeneratorImplTest_Builtin, StorageBarrier) {
Func("main", {}, ty.void_(), {CallStmt(Call("storageBarrier"))},