From 2d8ba5fac68fb85a46700543ac39b549f57ad760 Mon Sep 17 00:00:00 2001 From: Corentin Wallez Date: Fri, 12 Jul 2019 07:13:41 +0000 Subject: [PATCH] Add rendering tests for all color formats BUG=dawn:128 Change-Id: I32cab39e77847388a7736a51532a1b5c24a0fde7 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8684 Reviewed-by: Austin Eng Reviewed-by: Jiawei Shao Commit-Queue: Corentin Wallez --- src/common/Math.cpp | 4 + src/common/Math.h | 1 + src/tests/end2end/TextureFormatTests.cpp | 268 +++++++++++++++-------- src/tests/unittests/MathTests.cpp | 14 ++ 4 files changed, 197 insertions(+), 90 deletions(-) diff --git a/src/common/Math.cpp b/src/common/Math.cpp index a096bead4d..4077bdb900 100644 --- a/src/common/Math.cpp +++ b/src/common/Math.cpp @@ -109,6 +109,10 @@ uint16_t Float32ToFloat16(float fp32) { } } +bool IsFloat16NaN(uint16_t fp16) { + return (fp16 & 0x7FFF) > 0x7C00; +} + // Based on the Khronos Data Format Specification 1.2 Section 13.3 sRGB transfer functions float SRGBToLinear(float srgb) { // sRGB is always used in unsigned normalized formats so clamp to [0.0, 1.0] diff --git a/src/common/Math.h b/src/common/Math.h index 56aa5ed5dc..d52252ebba 100644 --- a/src/common/Math.h +++ b/src/common/Math.h @@ -51,6 +51,7 @@ destType BitCast(const sourceType& source) { } uint16_t Float32ToFloat16(float fp32); +bool IsFloat16NaN(uint16_t fp16); float SRGBToLinear(float srgb); diff --git a/src/tests/end2end/TextureFormatTests.cpp b/src/tests/end2end/TextureFormatTests.cpp index b32206d6df..d56f1d7ab5 100644 --- a/src/tests/end2end/TextureFormatTests.cpp +++ b/src/tests/end2end/TextureFormatTests.cpp @@ -71,6 +71,44 @@ class ExpectFloatWithTolerance : public detail::Expectation { float mTolerance; }; +// An expectation for float16 buffers that can correctly compare NaNs (all NaNs are equivalent). +class ExpectFloat16 : public detail::Expectation { + public: + ExpectFloat16(std::vector expected) : mExpected(std::move(expected)) { + } + + testing::AssertionResult Check(const void* data, size_t size) override { + ASSERT(size == sizeof(uint16_t) * mExpected.size()); + + const uint16_t* actual = static_cast(data); + + for (size_t i = 0; i < mExpected.size(); ++i) { + uint16_t expectedValue = mExpected[i]; + uint16_t actualValue = actual[i]; + + if (!Floats16Match(expectedValue, actualValue)) { + testing::AssertionResult result = testing::AssertionFailure() + << "Expected data[" << i << "] to be " + << expectedValue << ", actual " << actualValue + << std::endl; + return result; + } + } + return testing::AssertionSuccess(); + } + + private: + bool Floats16Match(float expected, float actual) { + if (IsFloat16NaN(expected)) { + return IsFloat16NaN(actual); + } + + return expected == actual; + } + + std::vector mExpected; +}; + class TextureFormatTest : public DawnTest { protected: void SetUp() { @@ -97,9 +135,9 @@ class TextureFormatTest : public DawnTest { uint32_t componentCount; }; - // Returns a texture format that can be used to contain the interpreted value of the format in - // formatInfo. - dawn::TextureFormat GetComponentFormat(FormatTestInfo formatInfo) { + // Returns a reprensentation of a format that can be used to contain the "uncompressed" values + // of the format. That the equivalent format with all channels 32bit-sized. + FormatTestInfo GetUncompressedFormatInfo(FormatTestInfo formatInfo) { std::array floatFormats = { dawn::TextureFormat::R32Float, dawn::TextureFormat::RG32Float, @@ -118,24 +156,32 @@ class TextureFormatTest : public DawnTest { dawn::TextureFormat::RGBA32Uint, dawn::TextureFormat::RGBA32Uint, }; + std::array componentCounts = {1, 2, 4, 4}; ASSERT(formatInfo.componentCount > 0 && formatInfo.componentCount <= 4); + dawn::TextureFormat format; switch (formatInfo.type) { case Float: - return floatFormats[formatInfo.componentCount - 1]; + format = floatFormats[formatInfo.componentCount - 1]; + break; case Sint: - return sintFormats[formatInfo.componentCount - 1]; + format = sintFormats[formatInfo.componentCount - 1]; + break; case Uint: - return uintFormats[formatInfo.componentCount - 1]; + format = uintFormats[formatInfo.componentCount - 1]; + break; default: UNREACHABLE(); - return dawn::TextureFormat::R32Float; } + + uint32_t componentCount = componentCounts[formatInfo.componentCount - 1]; + return {format, 4 * componentCount, formatInfo.type, componentCount}; } // Return a pipeline that can be used in a full-texture draw to sample from the texture in the // bindgroup and output its decompressed values to the render target. - dawn::RenderPipeline CreateSamplePipeline(FormatTestInfo formatInfo) { + dawn::RenderPipeline CreateSamplePipeline(FormatTestInfo sampleFormatInfo, + FormatTestInfo renderFormatInfo) { utils::ComboRenderPipelineDescriptor desc(device); dawn::ShaderModule vsModule = @@ -152,7 +198,7 @@ class TextureFormatTest : public DawnTest { // Compute the prefix needed for GLSL types that handle our texture's data. const char* prefix = nullptr; - switch (formatInfo.type) { + switch (sampleFormatInfo.type) { case Float: prefix = ""; break; @@ -184,66 +230,63 @@ class TextureFormatTest : public DawnTest { desc.cVertexStage.module = vsModule; desc.cFragmentStage.module = fsModule; desc.layout = utils::MakeBasicPipelineLayout(device, &mSampleBGL); - desc.cColorStates[0]->format = GetComponentFormat(formatInfo); + desc.cColorStates[0]->format = renderFormatInfo.format; return device.CreateRenderPipeline(&desc); } - // The sampling test uploads the textureData in a texture with the formatInfo.format format and - // the samples from it, then checks that the sampled values correspond to expectedRenderData. - void DoSampleTest(FormatTestInfo formatInfo, - const void* textureData, - size_t textureDataSize, + // The sampling test uploads the sample data in a texture with the sampleFormatInfo.format. + // It then samples from it and renders the results in a texture with the + // renderFormatInfo.format format. Finally it checks that the data rendered matches + // expectedRenderData, using the cutom expectation if present. + void DoSampleTest(FormatTestInfo sampleFormatInfo, + const void* sampleData, + size_t sampleDataSize, + FormatTestInfo renderFormatInfo, const void* expectedRenderData, size_t expectedRenderDataSize, - float floatTolerance) { + detail::Expectation* customExpectation) { // The input data should contain an exact number of texels - ASSERT(textureDataSize % formatInfo.texelByteSize == 0); - uint32_t width = textureDataSize / formatInfo.texelByteSize; + ASSERT(sampleDataSize % sampleFormatInfo.texelByteSize == 0); + uint32_t width = sampleDataSize / sampleFormatInfo.texelByteSize; // The input data must be a multiple of 4 byte in length for setSubData - ASSERT(textureDataSize % 4 == 0); + ASSERT(sampleDataSize % 4 == 0); + ASSERT(expectedRenderDataSize % 4 == 0); // Create the texture we will sample from - dawn::TextureDescriptor textureDesc; - textureDesc.usage = dawn::TextureUsageBit::CopyDst | dawn::TextureUsageBit::Sampled; - textureDesc.dimension = dawn::TextureDimension::e2D; - textureDesc.size = {width, 1, 1}; - textureDesc.arrayLayerCount = 1; - textureDesc.format = formatInfo.format; - textureDesc.mipLevelCount = 1; - textureDesc.sampleCount = 1; + dawn::TextureDescriptor sampleTextureDesc; + sampleTextureDesc.usage = dawn::TextureUsageBit::CopyDst | dawn::TextureUsageBit::Sampled; + sampleTextureDesc.size = {width, 1, 1}; + sampleTextureDesc.format = sampleFormatInfo.format; + dawn::Texture sampleTexture = device.CreateTexture(&sampleTextureDesc); - dawn::Texture texture = device.CreateTexture(&textureDesc); - - dawn::Buffer uploadBuffer = utils::CreateBufferFromData( - device, textureData, textureDataSize, dawn::BufferUsageBit::CopySrc); + dawn::Buffer uploadBuffer = utils::CreateBufferFromData(device, sampleData, sampleDataSize, + dawn::BufferUsageBit::CopySrc); // Create the texture that we will render results to + ASSERT(expectedRenderDataSize == width * renderFormatInfo.texelByteSize); + dawn::TextureDescriptor renderTargetDesc; renderTargetDesc.usage = dawn::TextureUsageBit::CopySrc | dawn::TextureUsageBit::OutputAttachment; - renderTargetDesc.dimension = dawn::TextureDimension::e2D; renderTargetDesc.size = {width, 1, 1}; - renderTargetDesc.arrayLayerCount = 1; - renderTargetDesc.format = GetComponentFormat(formatInfo); - renderTargetDesc.mipLevelCount = 1; - renderTargetDesc.sampleCount = 1; + renderTargetDesc.format = renderFormatInfo.format; dawn::Texture renderTarget = device.CreateTexture(&renderTargetDesc); // Create the readback buffer for the data in renderTarget dawn::BufferDescriptor readbackBufferDesc; readbackBufferDesc.usage = dawn::BufferUsageBit::CopyDst | dawn::BufferUsageBit::CopySrc; - readbackBufferDesc.size = 4 * width * formatInfo.componentCount; + readbackBufferDesc.size = 4 * width * sampleFormatInfo.componentCount; dawn::Buffer readbackBuffer = device.CreateBuffer(&readbackBufferDesc); // Prepare objects needed to sample from texture in the renderpass - dawn::RenderPipeline pipeline = CreateSamplePipeline(formatInfo); + dawn::RenderPipeline pipeline = CreateSamplePipeline(sampleFormatInfo, renderFormatInfo); dawn::SamplerDescriptor samplerDesc = utils::GetDefaultSamplerDescriptor(); dawn::Sampler sampler = device.CreateSampler(&samplerDesc); dawn::BindGroup bindGroup = utils::MakeBindGroup( - device, mSampleBGL, {{0, sampler}, {1, texture.CreateDefaultView()}}); + device, mSampleBGL, {{0, sampler}, {1, sampleTexture.CreateDefaultView()}}); // Encode commands for the test that fill texture, sample it to render to renderTarget then // copy renderTarget in a buffer so we can read it easily. @@ -252,7 +295,7 @@ class TextureFormatTest : public DawnTest { { dawn::BufferCopyView bufferView = utils::CreateBufferCopyView(uploadBuffer, 0, 256, 0); dawn::TextureCopyView textureView = - utils::CreateTextureCopyView(texture, 0, 0, {0, 0, 0}); + utils::CreateTextureCopyView(sampleTexture, 0, 0, {0, 0, 0}); dawn::Extent3D extent{width, 1, 1}; encoder.CopyBufferToTexture(&bufferView, &textureView, &extent); } @@ -278,12 +321,9 @@ class TextureFormatTest : public DawnTest { // For floats use a special expectation that understands how to compare NaNs and support a // tolerance. - if (formatInfo.type == Float) { - const float* expectedFloats = static_cast(expectedRenderData); - std::vector expectedVector( - expectedFloats, expectedFloats + expectedRenderDataSize / sizeof(float)); + if (customExpectation != nullptr) { AddBufferExpectation(__FILE__, __LINE__, readbackBuffer, 0, expectedRenderDataSize, - new ExpectFloatWithTolerance(expectedVector, floatTolerance)); + customExpectation); } else { EXPECT_BUFFER_U32_RANGE_EQ(static_cast(expectedRenderData), readbackBuffer, 0, @@ -291,14 +331,38 @@ class TextureFormatTest : public DawnTest { } } + // Helper functions used to run tests that convert the typeful test objects to typeless void* + template - void DoSampleTest(FormatTestInfo formatInfo, - const std::vector& textureData, - const std::vector& expectedRenderData, - float floatTolerance = 0.0f) { + void DoFormatSamplingTest(FormatTestInfo formatInfo, + const std::vector& textureData, + const std::vector& expectedRenderData, + detail::Expectation* customExpectation = nullptr) { + FormatTestInfo renderFormatInfo = GetUncompressedFormatInfo(formatInfo); DoSampleTest(formatInfo, textureData.data(), textureData.size() * sizeof(TextureData), - expectedRenderData.data(), expectedRenderData.size() * sizeof(RenderData), - floatTolerance); + renderFormatInfo, expectedRenderData.data(), + expectedRenderData.size() * sizeof(RenderData), customExpectation); + } + + template + void DoFloatFormatSamplingTest(FormatTestInfo formatInfo, + const std::vector& textureData, + const std::vector& expectedRenderData, + float floatTolerance = 0.0f) { + // Use a special expectation that understands how to compare NaNs and supports a tolerance. + DoFormatSamplingTest(formatInfo, textureData, expectedRenderData, + new ExpectFloatWithTolerance(expectedRenderData, floatTolerance)); + } + + template + void DoFormatRenderingTest(FormatTestInfo formatInfo, + const std::vector& textureData, + const std::vector& expectedRenderData, + detail::Expectation* customExpectation = nullptr) { + FormatTestInfo sampleFormatInfo = GetUncompressedFormatInfo(formatInfo); + DoSampleTest(sampleFormatInfo, textureData.data(), textureData.size() * sizeof(TextureData), + formatInfo, expectedRenderData.data(), + expectedRenderData.size() * sizeof(RenderData), customExpectation); } // Below are helper functions for types that are very similar to one another so the logic is @@ -312,9 +376,10 @@ class TextureFormatTest : public DawnTest { T maxValue = std::numeric_limits::max(); std::vector textureData = {0, 1, maxValue, maxValue}; - std::vector expectedData = {0.0f, 1.0f / maxValue, 1.0f, 1.0f}; + std::vector uncompressedData = {0.0f, 1.0f / maxValue, 1.0f, 1.0f}; - DoSampleTest(formatInfo, textureData, expectedData); + DoFormatSamplingTest(formatInfo, textureData, uncompressedData); + DoFormatRenderingTest(formatInfo, uncompressedData, textureData); } template @@ -326,9 +391,14 @@ class TextureFormatTest : public DawnTest { T maxValue = std::numeric_limits::max(); T minValue = std::numeric_limits::min(); std::vector textureData = {0, 1, maxValue, minValue}; - std::vector expectedData = {0.0f, 1.0f / maxValue, 1.0f, -1.0f}; + std::vector uncompressedData = {0.0f, 1.0f / maxValue, 1.0f, -1.0f}; - DoSampleTest(formatInfo, textureData, expectedData, 0.0001f / maxValue); + DoFloatFormatSamplingTest(formatInfo, textureData, uncompressedData, 0.0001f / maxValue); + + // It is not possible to render minValue because -1.0f is the minimum and corresponds to + // -maxValue (minValue is - maxValue -1) + textureData[3] = -maxValue; + DoFormatRenderingTest(formatInfo, uncompressedData, textureData); } template @@ -339,9 +409,10 @@ class TextureFormatTest : public DawnTest { T maxValue = std::numeric_limits::max(); std::vector textureData = {0, 1, maxValue, maxValue}; - std::vector expectedData = {0, 1, maxValue, maxValue}; + std::vector uncompressedData = {0, 1, maxValue, maxValue}; - DoSampleTest(formatInfo, textureData, expectedData); + DoFormatSamplingTest(formatInfo, textureData, uncompressedData); + DoFormatRenderingTest(formatInfo, uncompressedData, textureData); } template @@ -353,9 +424,10 @@ class TextureFormatTest : public DawnTest { T maxValue = std::numeric_limits::max(); T minValue = std::numeric_limits::min(); std::vector textureData = {0, 1, maxValue, minValue}; - std::vector expectedData = {0, 1, maxValue, minValue}; + std::vector uncompressedData = {0, 1, maxValue, minValue}; - DoSampleTest(formatInfo, textureData, expectedData); + DoFormatSamplingTest(formatInfo, textureData, uncompressedData); + DoFormatRenderingTest(formatInfo, uncompressedData, textureData); } void DoFloat32Test(FormatTestInfo formatInfo) { @@ -365,21 +437,26 @@ class TextureFormatTest : public DawnTest { std::vector textureData = {+0.0f, -0.0f, 1.0f, 1.0e-29f, 1.0e29, NAN, INFINITY, -INFINITY}; - DoSampleTest(formatInfo, textureData, textureData); + DoFloatFormatSamplingTest(formatInfo, textureData, textureData); + DoFormatRenderingTest(formatInfo, textureData, textureData); } void DoFloat16Test(FormatTestInfo formatInfo) { ASSERT(sizeof(int16_t) * formatInfo.componentCount == formatInfo.texelByteSize); ASSERT(formatInfo.type == Float); - std::vector expectedData = {+0.0f, -0.0f, 1.0f, 1.0e-4f, - 1.0e4f, NAN, INFINITY, -INFINITY}; + std::vector uncompressedData = {+0.0f, -0.0f, 1.0f, 1.01e-4f, + 1.0e4f, NAN, INFINITY, -INFINITY}; std::vector textureData; - for (float value : expectedData) { + for (float value : uncompressedData) { textureData.push_back(Float32ToFloat16(value)); } - DoSampleTest(formatInfo, textureData, expectedData, 1.0e-5); + DoFloatFormatSamplingTest(formatInfo, textureData, uncompressedData, 1.0e-5); + + // Use a special expectation that knows that all Float16 NaNs are equivalent. + DoFormatRenderingTest(formatInfo, uncompressedData, textureData, + new ExpectFloat16(textureData)); } private: @@ -420,8 +497,11 @@ TEST_P(TextureFormatTest, RGBA16Unorm) { TEST_P(TextureFormatTest, BGRA8Unorm) { uint8_t maxValue = std::numeric_limits::max(); std::vector textureData = {maxValue, 1, 0, maxValue}; - std::vector expectedData = {0.0f, 1.0f / maxValue, 1.0f, 1.0f}; - DoSampleTest({dawn::TextureFormat::BGRA8Unorm, 4, Float, 4}, textureData, expectedData); + std::vector uncompressedData = {0.0f, 1.0f / maxValue, 1.0f, 1.0f}; + DoFormatSamplingTest({dawn::TextureFormat::BGRA8Unorm, 4, Float, 4}, textureData, + uncompressedData); + DoFormatRenderingTest({dawn::TextureFormat::BGRA8Unorm, 4, Float, 4}, uncompressedData, + textureData); } // Test the R8Snorm format @@ -579,36 +659,40 @@ TEST_P(TextureFormatTest, RGBA8UnormSrgb) { uint8_t maxValue = std::numeric_limits::max(); std::vector textureData = {0, 1, maxValue, 64, 35, 68, 152, 168}; - std::vector expectedData; + std::vector uncompressedData; for (size_t i = 0; i < textureData.size(); i += 4) { - expectedData.push_back(SRGBToLinear(textureData[i + 0] / float(maxValue))); - expectedData.push_back(SRGBToLinear(textureData[i + 1] / float(maxValue))); - expectedData.push_back(SRGBToLinear(textureData[i + 2] / float(maxValue))); + uncompressedData.push_back(SRGBToLinear(textureData[i + 0] / float(maxValue))); + uncompressedData.push_back(SRGBToLinear(textureData[i + 1] / float(maxValue))); + uncompressedData.push_back(SRGBToLinear(textureData[i + 2] / float(maxValue))); // Alpha is linear for sRGB formats - expectedData.push_back(textureData[i + 3] / float(maxValue)); + uncompressedData.push_back(textureData[i + 3] / float(maxValue)); } - DoSampleTest({dawn::TextureFormat::RGBA8UnormSrgb, 4, Float, 4}, textureData, expectedData, - 1.0e-3); + DoFloatFormatSamplingTest({dawn::TextureFormat::RGBA8UnormSrgb, 4, Float, 4}, textureData, + uncompressedData, 1.0e-3); + DoFormatRenderingTest({dawn::TextureFormat::RGBA8UnormSrgb, 4, Float, 4}, uncompressedData, + textureData); } -// Test the BGRA8Unorm format +// Test the BGRA8UnormSrgb format TEST_P(TextureFormatTest, BGRA8UnormSrgb) { uint8_t maxValue = std::numeric_limits::max(); std::vector textureData = {0, 1, maxValue, 64, 35, 68, 152, 168}; - std::vector expectedData; + std::vector uncompressedData; for (size_t i = 0; i < textureData.size(); i += 4) { // Note that R and B are swapped - expectedData.push_back(SRGBToLinear(textureData[i + 2] / float(maxValue))); - expectedData.push_back(SRGBToLinear(textureData[i + 1] / float(maxValue))); - expectedData.push_back(SRGBToLinear(textureData[i + 0] / float(maxValue))); + uncompressedData.push_back(SRGBToLinear(textureData[i + 2] / float(maxValue))); + uncompressedData.push_back(SRGBToLinear(textureData[i + 1] / float(maxValue))); + uncompressedData.push_back(SRGBToLinear(textureData[i + 0] / float(maxValue))); // Alpha is linear for sRGB formats - expectedData.push_back(textureData[i + 3] / float(maxValue)); + uncompressedData.push_back(textureData[i + 3] / float(maxValue)); } - DoSampleTest({dawn::TextureFormat::BGRA8UnormSrgb, 4, Float, 4}, textureData, expectedData, - 1.0e-3); + DoFloatFormatSamplingTest({dawn::TextureFormat::BGRA8UnormSrgb, 4, Float, 4}, textureData, + uncompressedData, 1.0e-3); + DoFormatRenderingTest({dawn::TextureFormat::BGRA8UnormSrgb, 4, Float, 4}, uncompressedData, + textureData); } // Test the RGB10A2Unorm format @@ -622,18 +706,20 @@ TEST_P(TextureFormatTest, RGB10A2Unorm) { }; std::vector textureData = {MakeRGB10A2(0, 0, 0, 0), MakeRGB10A2(1023, 1023, 1023, 1), - MakeRGB10A2(243, 578, 765, 2), MakeRGB10A2(0, 0, 0, 3)}; + MakeRGB10A2(243, 576, 765, 2), MakeRGB10A2(0, 0, 0, 3)}; // clang-format off - std::vector expectedData = { - 0.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1 / 3.0f, + std::vector uncompressedData = { + 0.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1 / 3.0f, 243 / 1023.0f, 576 / 1023.0f, 765 / 1023.0f, 2 / 3.0f, - 0.0f, 0.0f, 0.0f, 1.0f + 0.0f, 0.0f, 0.0f, 1.0f }; // clang-format on - DoSampleTest({dawn::TextureFormat::RGB10A2Unorm, 4, Float, 4}, textureData, expectedData, - 2.0e-3); + DoFloatFormatSamplingTest({dawn::TextureFormat::RGB10A2Unorm, 4, Float, 4}, textureData, + uncompressedData, 1.0e-5); + DoFormatRenderingTest({dawn::TextureFormat::RGB10A2Unorm, 4, Float, 4}, uncompressedData, + textureData); } // Test the RG11B10Float format @@ -667,7 +753,7 @@ TEST_P(TextureFormatTest, RG11B10Float) { // This is one of the only 3-channel formats, so we don't have specific testing for them. Alpha // should slways be sampled as 1 // clang-format off - std::vector expectedData = { + std::vector uncompressedData = { 0.0f, INFINITY, NAN, 1.0f, INFINITY, NAN, 1.0f, 1.0f, NAN, 1.0f, 0.0f, 1.0f, @@ -675,7 +761,9 @@ TEST_P(TextureFormatTest, RG11B10Float) { }; // clang-format on - DoSampleTest({dawn::TextureFormat::RG11B10Float, 4, Float, 4}, textureData, expectedData); + DoFloatFormatSamplingTest({dawn::TextureFormat::RG11B10Float, 4, Float, 4}, textureData, + uncompressedData); + // This format is not renderable. } // TODO(cwallez@chromium.org): Add tests for depth-stencil formats when we know if they are copyable diff --git a/src/tests/unittests/MathTests.cpp b/src/tests/unittests/MathTests.cpp index 01a16a428a..70f300f10f 100644 --- a/src/tests/unittests/MathTests.cpp +++ b/src/tests/unittests/MathTests.cpp @@ -151,6 +151,20 @@ TEST(Math, Float32ToFloat16) { ASSERT_EQ(Float32ToFloat16(1.0f), 0x3C00); } +// Tests for IsFloat16NaN +TEST(Math, IsFloat16NaN) { + ASSERT_FALSE(IsFloat16NaN(0u)); + ASSERT_FALSE(IsFloat16NaN(0u)); + ASSERT_FALSE(IsFloat16NaN(Float32ToFloat16(1.0f))); + ASSERT_FALSE(IsFloat16NaN(Float32ToFloat16(INFINITY))); + ASSERT_FALSE(IsFloat16NaN(Float32ToFloat16(-INFINITY))); + + ASSERT_TRUE(IsFloat16NaN(Float32ToFloat16(INFINITY) + 1)); + ASSERT_TRUE(IsFloat16NaN(Float32ToFloat16(-INFINITY) + 1)); + ASSERT_TRUE(IsFloat16NaN(0x7FFF)); + ASSERT_TRUE(IsFloat16NaN(0xFFFF)); +} + // Tests for SRGBToLinear TEST(Math, SRGBToLinear) { ASSERT_EQ(SRGBToLinear(0.0f), 0.0f);