dawn-cmake/src/writer/wgsl/generator_impl_literal_test.cc
Ben Clayton e1f30f1049 writer: Add TextBuffer to TextGenerator
And migrate the WGSL writer over to the new APIs.

TextBuffer allows text to be written to different buffers.
Helps with the complexities around for loops.

Bug: tint:952
Change-Id: I094a726254f2a97b5830a8d6e07af7649c91e083
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56771
Reviewed-by: David Neto <dneto@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
2021-07-02 22:17:25 +00:00

134 lines
5.2 KiB
C++

// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cstring>
#include "src/ast/override_decoration.h"
#include "src/writer/wgsl/test_helper.h"
namespace tint {
namespace writer {
namespace wgsl {
namespace {
// Makes an IEEE 754 binary32 floating point number with
// - 0 sign if sign is 0, 1 otherwise
// - 'exponent_bits' is placed in the exponent space.
// So, the exponent bias must already be included.
float MakeFloat(int sign, int biased_exponent, int mantissa) {
const uint32_t sign_bit = sign ? 0x80000000u : 0u;
// The binary32 exponent is 8 bits, just below the sign.
const uint32_t exponent_bits = (biased_exponent & 0xffu) << 23;
// The mantissa is the bottom 23 bits.
const uint32_t mantissa_bits = (mantissa & 0x7fffffu);
uint32_t bits = sign_bit | exponent_bits | mantissa_bits;
float result = 0.0f;
static_assert(sizeof(result) == sizeof(bits),
"expected float and uint32_t to be the same size");
std::memcpy(&result, &bits, sizeof(bits));
return result;
}
struct FloatData {
float value;
std::string expected;
};
inline std::ostream& operator<<(std::ostream& out, FloatData data) {
out << "{" << data.value << "," << data.expected << "}";
return out;
}
using WgslGenerator_FloatLiteralTest = TestParamHelper<FloatData>;
TEST_P(WgslGenerator_FloatLiteralTest, Emit) {
auto* v = Expr(GetParam().value);
SetResolveOnBuild(false);
GeneratorImpl& gen = Build();
std::stringstream out;
ASSERT_TRUE(gen.EmitScalarConstructor(out, v)) << gen.error();
EXPECT_EQ(out.str(), GetParam().expected);
}
INSTANTIATE_TEST_SUITE_P(Zero,
WgslGenerator_FloatLiteralTest,
::testing::ValuesIn(std::vector<FloatData>{
{0.0f, "0.0"},
{MakeFloat(0, 0, 0), "0.0"},
{MakeFloat(1, 0, 0), "-0.0"}}));
INSTANTIATE_TEST_SUITE_P(Normal,
WgslGenerator_FloatLiteralTest,
::testing::ValuesIn(std::vector<FloatData>{
{1.0f, "1.0"},
{-1.0f, "-1.0"},
{101.375, "101.375"}}));
INSTANTIATE_TEST_SUITE_P(
Subnormal,
WgslGenerator_FloatLiteralTest,
::testing::ValuesIn(std::vector<FloatData>{
{MakeFloat(0, 0, 1), "0x1p-149"}, // Smallest
{MakeFloat(1, 0, 1), "-0x1p-149"},
{MakeFloat(0, 0, 2), "0x1p-148"},
{MakeFloat(1, 0, 2), "-0x1p-148"},
{MakeFloat(0, 0, 0x7fffff), "0x1.fffffcp-127"}, // Largest
{MakeFloat(1, 0, 0x7fffff), "-0x1.fffffcp-127"}, // Largest
{MakeFloat(0, 0, 0xcafebe), "0x1.2bfaf8p-127"}, // Scattered bits
{MakeFloat(1, 0, 0xcafebe), "-0x1.2bfaf8p-127"}, // Scattered bits
{MakeFloat(0, 0, 0xaaaaa), "0x1.55554p-130"}, // Scattered bits
{MakeFloat(1, 0, 0xaaaaa), "-0x1.55554p-130"}, // Scattered bits
}));
INSTANTIATE_TEST_SUITE_P(Infinity,
WgslGenerator_FloatLiteralTest,
::testing::ValuesIn(std::vector<FloatData>{
{MakeFloat(0, 255, 0), "0x1p+128"},
{MakeFloat(1, 255, 0), "-0x1p+128"}}));
INSTANTIATE_TEST_SUITE_P(
// TODO(dneto): It's unclear how Infinity and NaN should be handled.
// https://github.com/gpuweb/gpuweb/issues/1769
// This test fails on Windows x86-64 because the machine sets the high
// mantissa bit on NaNs.
DISABLED_NaN,
// In the NaN case, the top bit in the mantissa is often used to encode
// whether the NaN is signalling or quiet, but no agreement between
// different machine architectures on whether 1 means signalling or
// if 1 means quiet.
WgslGenerator_FloatLiteralTest,
::testing::ValuesIn(std::vector<FloatData>{
// LSB only. Smallest mantissa.
{MakeFloat(0, 255, 1), "0x1.000002p+128"}, // Smallest mantissa
{MakeFloat(1, 255, 1), "-0x1.000002p+128"},
// MSB only.
{MakeFloat(0, 255, 0x400000), "0x1.8p+128"},
{MakeFloat(1, 255, 0x400000), "-0x1.8p+128"},
// All 1s in the mantissa.
{MakeFloat(0, 255, 0x7fffff), "0x1.fffffep+128"},
{MakeFloat(1, 255, 0x7fffff), "-0x1.fffffep+128"},
// Scattered bits, with 0 in top mantissa bit.
{MakeFloat(0, 255, 0x20101f), "0x1.40203ep+128"},
{MakeFloat(1, 255, 0x20101f), "-0x1.40203ep+128"},
// Scattered bits, with 1 in top mantissa bit.
{MakeFloat(0, 255, 0x40101f), "0x1.80203ep+128"},
{MakeFloat(1, 255, 0x40101f), "-0x1.80203ep+128"}}));
} // namespace
} // namespace wgsl
} // namespace writer
} // namespace tint