mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-16 00:17:03 +00:00
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:
committed by
Tint LUCI CQ
parent
59f1e8d06c
commit
bee5fa6881
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"))},
|
||||
|
||||
Reference in New Issue
Block a user