spirv-reader: polyfill scalar reflect
Fixed: tint:1018 Change-Id: I60916d6c4ac4ae8c1a88763c12acf83d19bb2e68 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/58821 Commit-Queue: David Neto <dneto@google.com> Auto-Submit: David Neto <dneto@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@chromium.org>
This commit is contained in:
parent
70eb1d3573
commit
f7d0c1cbfe
|
@ -3996,6 +3996,7 @@ TypedExpression FunctionEmitter::EmitGlslStd450ExtInst(
|
||||||
// WGSL does not have scalar form of the normalize builtin.
|
// WGSL does not have scalar form of the normalize builtin.
|
||||||
// The answer would be 1 anyway, so return that directly.
|
// The answer would be 1 anyway, so return that directly.
|
||||||
return {ty_.F32(), builder_.Expr(1.0f)};
|
return {ty_.F32(), builder_.Expr(1.0f)};
|
||||||
|
|
||||||
case GLSLstd450FaceForward: {
|
case GLSLstd450FaceForward: {
|
||||||
// If dot(Nref, Incident) < 0, the result is Normal, otherwise -Normal.
|
// If dot(Nref, Incident) < 0, the result is Normal, otherwise -Normal.
|
||||||
// Also: select(-normal,normal, Incident*Nref < 0)
|
// Also: select(-normal,normal, Incident*Nref < 0)
|
||||||
|
@ -4021,6 +4022,21 @@ TypedExpression FunctionEmitter::EmitGlslStd450ExtInst(
|
||||||
builder_.Expr(0.0f))})};
|
builder_.Expr(0.0f))})};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case GLSLstd450Reflect: {
|
||||||
|
// Compute Incident - 2 * Normal * Normal * Incident
|
||||||
|
auto incident = MakeOperand(inst, 2);
|
||||||
|
auto normal = MakeOperand(inst, 3);
|
||||||
|
TINT_ASSERT(Reader, incident.type->Is<F32>());
|
||||||
|
TINT_ASSERT(Reader, normal.type->Is<F32>());
|
||||||
|
return {
|
||||||
|
ty_.F32(),
|
||||||
|
builder_.Sub(
|
||||||
|
incident.expr,
|
||||||
|
builder_.Mul(2.0f, builder_.Mul(normal.expr,
|
||||||
|
builder_.Mul(normal.expr,
|
||||||
|
incident.expr))))};
|
||||||
|
}
|
||||||
|
|
||||||
case GLSLstd450Refract: {
|
case GLSLstd450Refract: {
|
||||||
// It's a complicated expression. Compute it in two dimensions, but
|
// It's a complicated expression. Compute it in two dimensions, but
|
||||||
// with a 0-valued y component in both the incident and normal vectors,
|
// with a 0-valued y component in both the incident and normal vectors,
|
||||||
|
@ -4701,6 +4717,10 @@ void FunctionEmitter::FindValuesNeedingNamedOrHoistedDefinition() {
|
||||||
// The "normal" operand expression is used twice in code generation.
|
// The "normal" operand expression is used twice in code generation.
|
||||||
require_named_const_def(inst, 2);
|
require_named_const_def(inst, 2);
|
||||||
break;
|
break;
|
||||||
|
case GLSLstd450Reflect:
|
||||||
|
require_named_const_def(inst, 2); // Incident
|
||||||
|
require_named_const_def(inst, 3); // Normal
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -717,7 +717,6 @@ INSTANTIATE_TEST_SUITE_P(Samples,
|
||||||
{"FMax", "max"}, // WGSL max promises more for NaN
|
{"FMax", "max"}, // WGSL max promises more for NaN
|
||||||
{"FMin", "min"}, // WGSL min promises more for NaN
|
{"FMin", "min"}, // WGSL min promises more for NaN
|
||||||
{"Pow", "pow"},
|
{"Pow", "pow"},
|
||||||
{"Reflect", "reflect"},
|
|
||||||
{"Step", "step"},
|
{"Step", "step"},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1913,6 +1912,145 @@ TEST_F(SpvParserTest, GlslStd450_FaceForward_Vector) {
|
||||||
EXPECT_THAT(body, HasSubstr(expected));
|
EXPECT_THAT(body, HasSubstr(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GlslStd450_Reflect_Scalar) {
|
||||||
|
const auto assembly = Preamble() + R"(
|
||||||
|
%98 = OpFAdd %float %f1 %f1 ; has only one use
|
||||||
|
%99 = OpFAdd %float %f2 %f2 ; has only one use
|
||||||
|
%1 = OpExtInst %float %glsl Reflect %98 %99
|
||||||
|
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());
|
||||||
|
// The %99 sum only has one use. Ensure it is evaluated only once by
|
||||||
|
// making a let-declaration for it, since it is the normal operand to
|
||||||
|
// the builtin function, and code generation uses it twice.
|
||||||
|
const auto* expected = R"(VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_98
|
||||||
|
none
|
||||||
|
undefined
|
||||||
|
__f32
|
||||||
|
{
|
||||||
|
Binary[not set]{
|
||||||
|
Identifier[not set]{f1}
|
||||||
|
add
|
||||||
|
Identifier[not set]{f1}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_99
|
||||||
|
none
|
||||||
|
undefined
|
||||||
|
__f32
|
||||||
|
{
|
||||||
|
Binary[not set]{
|
||||||
|
Identifier[not set]{f2}
|
||||||
|
add
|
||||||
|
Identifier[not set]{f2}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
undefined
|
||||||
|
__f32
|
||||||
|
{
|
||||||
|
Binary[not set]{
|
||||||
|
Identifier[not set]{x_98}
|
||||||
|
subtract
|
||||||
|
Binary[not set]{
|
||||||
|
ScalarConstructor[not set]{2.000000}
|
||||||
|
multiply
|
||||||
|
Binary[not set]{
|
||||||
|
Identifier[not set]{x_99}
|
||||||
|
multiply
|
||||||
|
Binary[not set]{
|
||||||
|
Identifier[not set]{x_99}
|
||||||
|
multiply
|
||||||
|
Identifier[not set]{x_98}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
|
||||||
|
EXPECT_THAT(body, HasSubstr(expected)) << body;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, GlslStd450_Reflect_Vector) {
|
||||||
|
const auto assembly = Preamble() + R"(
|
||||||
|
%98 = OpFAdd %v2float %v2f1 %v2f1
|
||||||
|
%99 = OpFAdd %v2float %v2f2 %v2f2
|
||||||
|
%1 = OpExtInst %v2float %glsl Reflect %98 %99
|
||||||
|
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"(VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_98
|
||||||
|
none
|
||||||
|
undefined
|
||||||
|
__vec_2__f32
|
||||||
|
{
|
||||||
|
Binary[not set]{
|
||||||
|
Identifier[not set]{v2f1}
|
||||||
|
add
|
||||||
|
Identifier[not set]{v2f1}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_99
|
||||||
|
none
|
||||||
|
undefined
|
||||||
|
__vec_2__f32
|
||||||
|
{
|
||||||
|
Binary[not set]{
|
||||||
|
Identifier[not set]{v2f2}
|
||||||
|
add
|
||||||
|
Identifier[not set]{v2f2}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
undefined
|
||||||
|
__vec_2__f32
|
||||||
|
{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{reflect}
|
||||||
|
(
|
||||||
|
Identifier[not set]{x_98}
|
||||||
|
Identifier[not set]{x_99}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
|
||||||
|
EXPECT_THAT(body, HasSubstr(expected)) << body;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace reader
|
} // namespace reader
|
||||||
|
|
|
@ -21,7 +21,9 @@ void main_1() {
|
||||||
m24 = float2x2(float2(x_40, x_42), float2((x_44 * 1.0f), x_47));
|
m24 = float2x2(float2(x_40, x_42), float2((x_44 * 1.0f), x_47));
|
||||||
a = m24[0u].x;
|
a = m24[0u].x;
|
||||||
v2 = float2(asfloat(0x7fc00000u), 1.0f);
|
v2 = float2(asfloat(0x7fc00000u), 1.0f);
|
||||||
v3 = reflect(v2, float2(a, 1.0f));
|
const float2 x_53 = v2;
|
||||||
|
const float2 x_55 = float2(a, 1.0f);
|
||||||
|
v3 = reflect(x_53, x_55);
|
||||||
const uint scalar_offset_3 = ((16u * uint(0))) / 4;
|
const uint scalar_offset_3 = ((16u * uint(0))) / 4;
|
||||||
const float x_58 = asfloat(x_6[scalar_offset_3 / 4][scalar_offset_3 % 4]);
|
const float x_58 = asfloat(x_6[scalar_offset_3 / 4][scalar_offset_3 % 4]);
|
||||||
const float2 x_59 = v3;
|
const float2 x_59 = v3;
|
||||||
|
|
|
@ -36,7 +36,8 @@ void main_1(constant buf0& x_6, constant buf1& x_8, thread float4* const tint_sy
|
||||||
v2 = float2(NAN, 1.0f);
|
v2 = float2(NAN, 1.0f);
|
||||||
float2 const x_53 = v2;
|
float2 const x_53 = v2;
|
||||||
float const x_54 = a;
|
float const x_54 = a;
|
||||||
v3 = reflect(x_53, float2(x_54, 1.0f));
|
float2 const x_55 = float2(x_54, 1.0f);
|
||||||
|
v3 = reflect(x_53, x_55);
|
||||||
float const x_58 = x_6.x_GLF_uniform_float_values.arr[0].el;
|
float const x_58 = x_6.x_GLF_uniform_float_values.arr[0].el;
|
||||||
float2 const x_59 = v3;
|
float2 const x_59 = v3;
|
||||||
float const x_61 = x_6.x_GLF_uniform_float_values.arr[0].el;
|
float const x_61 = x_6.x_GLF_uniform_float_values.arr[0].el;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
; Bound: 98
|
; Bound: 98
|
||||||
; Schema: 0
|
; Schema: 0
|
||||||
OpCapability Shader
|
OpCapability Shader
|
||||||
%58 = OpExtInstImport "GLSL.std.450"
|
%59 = OpExtInstImport "GLSL.std.450"
|
||||||
OpMemoryModel Logical GLSL450
|
OpMemoryModel Logical GLSL450
|
||||||
OpEntryPoint Fragment %main "main" %tint_symbol_1
|
OpEntryPoint Fragment %main "main" %tint_symbol_1
|
||||||
OpExecutionMode %main OriginUpperLeft
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
@ -104,9 +104,9 @@
|
||||||
OpStore %v2 %54
|
OpStore %v2 %54
|
||||||
%55 = OpLoad %v2float %v2
|
%55 = OpLoad %v2float %v2
|
||||||
%56 = OpLoad %float %a
|
%56 = OpLoad %float %a
|
||||||
%59 = OpCompositeConstruct %v2float %56 %float_1
|
%57 = OpCompositeConstruct %v2float %56 %float_1
|
||||||
%57 = OpExtInst %v2float %58 Reflect %55 %59
|
%58 = OpExtInst %v2float %59 Reflect %55 %57
|
||||||
OpStore %v3 %57
|
OpStore %v3 %58
|
||||||
%60 = OpAccessChain %_ptr_Uniform_float %x_6 %uint_0 %int_0
|
%60 = OpAccessChain %_ptr_Uniform_float %x_6 %uint_0 %int_0
|
||||||
%61 = OpLoad %float %60
|
%61 = OpLoad %float %60
|
||||||
%62 = OpLoad %v2float %v3
|
%62 = OpLoad %v2float %v3
|
||||||
|
|
|
@ -31,7 +31,8 @@ fn main_1() {
|
||||||
v2 = vec2<f32>(-0x1.8p+128, 1.0);
|
v2 = vec2<f32>(-0x1.8p+128, 1.0);
|
||||||
let x_53 : vec2<f32> = v2;
|
let x_53 : vec2<f32> = v2;
|
||||||
let x_54 : f32 = a;
|
let x_54 : f32 = a;
|
||||||
v3 = reflect(x_53, vec2<f32>(x_54, 1.0));
|
let x_55 : vec2<f32> = vec2<f32>(x_54, 1.0);
|
||||||
|
v3 = reflect(x_53, x_55);
|
||||||
let x_58 : f32 = x_6.x_GLF_uniform_float_values[0];
|
let x_58 : f32 = x_6.x_GLF_uniform_float_values[0];
|
||||||
let x_59 : vec2<f32> = v3;
|
let x_59 : vec2<f32> = v3;
|
||||||
let x_61 : f32 = x_6.x_GLF_uniform_float_values[0];
|
let x_61 : f32 = x_6.x_GLF_uniform_float_values[0];
|
||||||
|
|
Loading…
Reference in New Issue