spirv-reader: polyfill scalar refract
Compute it in 2 dimensions, with a 0-valued y component, then extract the x component of that result. Fixed: tint:974 Change-Id: Ie23668d3403e68be14f34da9540f27f6f3c3aca2 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/58782 Auto-Submit: David Neto <dneto@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: James Price <jrprice@google.com> Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
parent
0c3ddc9649
commit
94a5fd476e
|
@ -3989,6 +3989,37 @@ TypedExpression FunctionEmitter::EmitGlslStd450ExtInst(
|
||||||
create<ast::ScalarConstructorExpression>(
|
create<ast::ScalarConstructorExpression>(
|
||||||
Source{}, create<ast::FloatLiteral>(Source{}, 1.0f))};
|
Source{}, create<ast::FloatLiteral>(Source{}, 1.0f))};
|
||||||
}
|
}
|
||||||
|
if ((ext_opcode == GLSLstd450Refract) && result_type->IsScalar()) {
|
||||||
|
// WGSL does not have scalar form of the refract builtin.
|
||||||
|
// It's a complicated expression. Implement it by /computing it in two
|
||||||
|
// dimensions, but with a 0-valued y component in both the incident and
|
||||||
|
// normal vectors, then take the x component of that result.
|
||||||
|
auto incident = MakeOperand(inst, 2);
|
||||||
|
auto normal = MakeOperand(inst, 3);
|
||||||
|
auto eta = MakeOperand(inst, 4);
|
||||||
|
TINT_ASSERT(Reader, incident.type->Is<F32>());
|
||||||
|
TINT_ASSERT(Reader, normal.type->Is<F32>());
|
||||||
|
TINT_ASSERT(Reader, eta.type->Is<F32>());
|
||||||
|
if (!success()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const Type* f32 = eta.type;
|
||||||
|
const Type* vec2 = ty_.Vector(f32, 2);
|
||||||
|
return {
|
||||||
|
f32,
|
||||||
|
builder_.MemberAccessor(
|
||||||
|
builder_.Call(
|
||||||
|
Source{}, "refract",
|
||||||
|
ast::ExpressionList{
|
||||||
|
builder_.Construct(vec2->Build(builder_),
|
||||||
|
ast::ExpressionList{
|
||||||
|
incident.expr, builder_.Expr(0.0f)}),
|
||||||
|
builder_.Construct(
|
||||||
|
vec2->Build(builder_),
|
||||||
|
ast::ExpressionList{normal.expr, builder_.Expr(0.0f)}),
|
||||||
|
eta.expr}),
|
||||||
|
"x")};
|
||||||
|
}
|
||||||
|
|
||||||
const auto name = GetGlslStd450FuncName(ext_opcode);
|
const auto name = GetGlslStd450FuncName(ext_opcode);
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
|
|
|
@ -53,6 +53,7 @@ std::string Preamble() {
|
||||||
OpName %v3f1 "v3f1"
|
OpName %v3f1 "v3f1"
|
||||||
OpName %v3f2 "v3f2"
|
OpName %v3f2 "v3f2"
|
||||||
OpName %v4f1 "v4f1"
|
OpName %v4f1 "v4f1"
|
||||||
|
OpName %v4f2 "v4f2"
|
||||||
|
|
||||||
%void = OpTypeVoid
|
%void = OpTypeVoid
|
||||||
%voidfn = OpTypeFunction %void
|
%voidfn = OpTypeFunction %void
|
||||||
|
@ -123,6 +124,7 @@ std::string Preamble() {
|
||||||
%v3f2 = OpCopyObject %v3float %v3float_60_70_50
|
%v3f2 = OpCopyObject %v3float %v3float_60_70_50
|
||||||
|
|
||||||
%v4f1 = OpCopyObject %v4float %v4float_50_50_50_50
|
%v4f1 = OpCopyObject %v4float %v4float_50_50_50_50
|
||||||
|
%v4f2 = OpCopyObject %v4float %v4f1
|
||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1746,6 +1748,78 @@ INSTANTIATE_TEST_SUITE_P(Samples,
|
||||||
{"UnpackUnorm2x16", "unpack2x16unorm", 2},
|
{"UnpackUnorm2x16", "unpack2x16unorm", 2},
|
||||||
{"UnpackHalf2x16", "unpack2x16float", 2}}));
|
{"UnpackHalf2x16", "unpack2x16float", 2}}));
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GlslStd450_Refract_Scalar) {
|
||||||
|
const auto assembly = Preamble() + R"(
|
||||||
|
%1 = OpExtInst %float %glsl Refract %f1 %f2 %f3
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
auto fe = p->function_emitter(100);
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(p->builder(), fe.ast_body());
|
||||||
|
const auto* expected = R"(VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
undefined
|
||||||
|
__f32
|
||||||
|
{
|
||||||
|
MemberAccessor[not set]{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{refract}
|
||||||
|
(
|
||||||
|
TypeConstructor[not set]{
|
||||||
|
__vec_2__f32
|
||||||
|
Identifier[not set]{f1}
|
||||||
|
ScalarConstructor[not set]{0.000000}
|
||||||
|
}
|
||||||
|
TypeConstructor[not set]{
|
||||||
|
__vec_2__f32
|
||||||
|
Identifier[not set]{f2}
|
||||||
|
ScalarConstructor[not set]{0.000000}
|
||||||
|
}
|
||||||
|
Identifier[not set]{f3}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Identifier[not set]{x}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
|
||||||
|
EXPECT_THAT(body, HasSubstr(expected)) << body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GlslStd450_Refract_Vector) {
|
||||||
|
const auto assembly = Preamble() + R"(
|
||||||
|
%1 = OpExtInst %v2float %glsl Refract %v2f1 %v2f2 %f3
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||||
|
auto fe = p->function_emitter(100);
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body = ToString(p->builder(), fe.ast_body());
|
||||||
|
const auto* expected = R"(VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
undefined
|
||||||
|
__vec_2__f32
|
||||||
|
{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{refract}
|
||||||
|
(
|
||||||
|
Identifier[not set]{v2f1}
|
||||||
|
Identifier[not set]{v2f2}
|
||||||
|
Identifier[not set]{f3}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
|
||||||
|
EXPECT_THAT(body, HasSubstr(expected));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace reader
|
} // namespace reader
|
||||||
|
|
Loading…
Reference in New Issue