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 <enga@chromium.org>
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2019-07-12 07:13:41 +00:00 committed by Commit Bot service account
parent e896a0da66
commit 2d8ba5fac6
4 changed files with 197 additions and 90 deletions

View File

@ -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 // Based on the Khronos Data Format Specification 1.2 Section 13.3 sRGB transfer functions
float SRGBToLinear(float srgb) { float SRGBToLinear(float srgb) {
// sRGB is always used in unsigned normalized formats so clamp to [0.0, 1.0] // sRGB is always used in unsigned normalized formats so clamp to [0.0, 1.0]

View File

@ -51,6 +51,7 @@ destType BitCast(const sourceType& source) {
} }
uint16_t Float32ToFloat16(float fp32); uint16_t Float32ToFloat16(float fp32);
bool IsFloat16NaN(uint16_t fp16);
float SRGBToLinear(float srgb); float SRGBToLinear(float srgb);

View File

@ -71,6 +71,44 @@ class ExpectFloatWithTolerance : public detail::Expectation {
float mTolerance; 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<uint16_t> 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<const uint16_t*>(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<uint16_t> mExpected;
};
class TextureFormatTest : public DawnTest { class TextureFormatTest : public DawnTest {
protected: protected:
void SetUp() { void SetUp() {
@ -97,9 +135,9 @@ class TextureFormatTest : public DawnTest {
uint32_t componentCount; uint32_t componentCount;
}; };
// Returns a texture format that can be used to contain the interpreted value of the format in // Returns a reprensentation of a format that can be used to contain the "uncompressed" values
// formatInfo. // of the format. That the equivalent format with all channels 32bit-sized.
dawn::TextureFormat GetComponentFormat(FormatTestInfo formatInfo) { FormatTestInfo GetUncompressedFormatInfo(FormatTestInfo formatInfo) {
std::array<dawn::TextureFormat, 4> floatFormats = { std::array<dawn::TextureFormat, 4> floatFormats = {
dawn::TextureFormat::R32Float, dawn::TextureFormat::R32Float,
dawn::TextureFormat::RG32Float, dawn::TextureFormat::RG32Float,
@ -118,24 +156,32 @@ class TextureFormatTest : public DawnTest {
dawn::TextureFormat::RGBA32Uint, dawn::TextureFormat::RGBA32Uint,
dawn::TextureFormat::RGBA32Uint, dawn::TextureFormat::RGBA32Uint,
}; };
std::array<uint32_t, 4> componentCounts = {1, 2, 4, 4};
ASSERT(formatInfo.componentCount > 0 && formatInfo.componentCount <= 4); ASSERT(formatInfo.componentCount > 0 && formatInfo.componentCount <= 4);
dawn::TextureFormat format;
switch (formatInfo.type) { switch (formatInfo.type) {
case Float: case Float:
return floatFormats[formatInfo.componentCount - 1]; format = floatFormats[formatInfo.componentCount - 1];
break;
case Sint: case Sint:
return sintFormats[formatInfo.componentCount - 1]; format = sintFormats[formatInfo.componentCount - 1];
break;
case Uint: case Uint:
return uintFormats[formatInfo.componentCount - 1]; format = uintFormats[formatInfo.componentCount - 1];
break;
default: default:
UNREACHABLE(); 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 // 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. // 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); utils::ComboRenderPipelineDescriptor desc(device);
dawn::ShaderModule vsModule = dawn::ShaderModule vsModule =
@ -152,7 +198,7 @@ class TextureFormatTest : public DawnTest {
// Compute the prefix needed for GLSL types that handle our texture's data. // Compute the prefix needed for GLSL types that handle our texture's data.
const char* prefix = nullptr; const char* prefix = nullptr;
switch (formatInfo.type) { switch (sampleFormatInfo.type) {
case Float: case Float:
prefix = ""; prefix = "";
break; break;
@ -184,66 +230,63 @@ class TextureFormatTest : public DawnTest {
desc.cVertexStage.module = vsModule; desc.cVertexStage.module = vsModule;
desc.cFragmentStage.module = fsModule; desc.cFragmentStage.module = fsModule;
desc.layout = utils::MakeBasicPipelineLayout(device, &mSampleBGL); desc.layout = utils::MakeBasicPipelineLayout(device, &mSampleBGL);
desc.cColorStates[0]->format = GetComponentFormat(formatInfo); desc.cColorStates[0]->format = renderFormatInfo.format;
return device.CreateRenderPipeline(&desc); return device.CreateRenderPipeline(&desc);
} }
// The sampling test uploads the textureData in a texture with the formatInfo.format format and // The sampling test uploads the sample data in a texture with the sampleFormatInfo.format.
// the samples from it, then checks that the sampled values correspond to expectedRenderData. // It then samples from it and renders the results in a texture with the
void DoSampleTest(FormatTestInfo formatInfo, // renderFormatInfo.format format. Finally it checks that the data rendered matches
const void* textureData, // expectedRenderData, using the cutom expectation if present.
size_t textureDataSize, void DoSampleTest(FormatTestInfo sampleFormatInfo,
const void* sampleData,
size_t sampleDataSize,
FormatTestInfo renderFormatInfo,
const void* expectedRenderData, const void* expectedRenderData,
size_t expectedRenderDataSize, size_t expectedRenderDataSize,
float floatTolerance) { detail::Expectation* customExpectation) {
// The input data should contain an exact number of texels // The input data should contain an exact number of texels
ASSERT(textureDataSize % formatInfo.texelByteSize == 0); ASSERT(sampleDataSize % sampleFormatInfo.texelByteSize == 0);
uint32_t width = textureDataSize / formatInfo.texelByteSize; uint32_t width = sampleDataSize / sampleFormatInfo.texelByteSize;
// The input data must be a multiple of 4 byte in length for setSubData // 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 // Create the texture we will sample from
dawn::TextureDescriptor textureDesc; dawn::TextureDescriptor sampleTextureDesc;
textureDesc.usage = dawn::TextureUsageBit::CopyDst | dawn::TextureUsageBit::Sampled; sampleTextureDesc.usage = dawn::TextureUsageBit::CopyDst | dawn::TextureUsageBit::Sampled;
textureDesc.dimension = dawn::TextureDimension::e2D; sampleTextureDesc.size = {width, 1, 1};
textureDesc.size = {width, 1, 1}; sampleTextureDesc.format = sampleFormatInfo.format;
textureDesc.arrayLayerCount = 1; dawn::Texture sampleTexture = device.CreateTexture(&sampleTextureDesc);
textureDesc.format = formatInfo.format;
textureDesc.mipLevelCount = 1;
textureDesc.sampleCount = 1;
dawn::Texture texture = device.CreateTexture(&textureDesc); dawn::Buffer uploadBuffer = utils::CreateBufferFromData(device, sampleData, sampleDataSize,
dawn::BufferUsageBit::CopySrc);
dawn::Buffer uploadBuffer = utils::CreateBufferFromData(
device, textureData, textureDataSize, dawn::BufferUsageBit::CopySrc);
// Create the texture that we will render results to // Create the texture that we will render results to
ASSERT(expectedRenderDataSize == width * renderFormatInfo.texelByteSize);
dawn::TextureDescriptor renderTargetDesc; dawn::TextureDescriptor renderTargetDesc;
renderTargetDesc.usage = renderTargetDesc.usage =
dawn::TextureUsageBit::CopySrc | dawn::TextureUsageBit::OutputAttachment; dawn::TextureUsageBit::CopySrc | dawn::TextureUsageBit::OutputAttachment;
renderTargetDesc.dimension = dawn::TextureDimension::e2D;
renderTargetDesc.size = {width, 1, 1}; renderTargetDesc.size = {width, 1, 1};
renderTargetDesc.arrayLayerCount = 1; renderTargetDesc.format = renderFormatInfo.format;
renderTargetDesc.format = GetComponentFormat(formatInfo);
renderTargetDesc.mipLevelCount = 1;
renderTargetDesc.sampleCount = 1;
dawn::Texture renderTarget = device.CreateTexture(&renderTargetDesc); dawn::Texture renderTarget = device.CreateTexture(&renderTargetDesc);
// Create the readback buffer for the data in renderTarget // Create the readback buffer for the data in renderTarget
dawn::BufferDescriptor readbackBufferDesc; dawn::BufferDescriptor readbackBufferDesc;
readbackBufferDesc.usage = dawn::BufferUsageBit::CopyDst | dawn::BufferUsageBit::CopySrc; 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); dawn::Buffer readbackBuffer = device.CreateBuffer(&readbackBufferDesc);
// Prepare objects needed to sample from texture in the renderpass // 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::SamplerDescriptor samplerDesc = utils::GetDefaultSamplerDescriptor();
dawn::Sampler sampler = device.CreateSampler(&samplerDesc); dawn::Sampler sampler = device.CreateSampler(&samplerDesc);
dawn::BindGroup bindGroup = utils::MakeBindGroup( 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 // 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. // 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::BufferCopyView bufferView = utils::CreateBufferCopyView(uploadBuffer, 0, 256, 0);
dawn::TextureCopyView textureView = 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}; dawn::Extent3D extent{width, 1, 1};
encoder.CopyBufferToTexture(&bufferView, &textureView, &extent); 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 // For floats use a special expectation that understands how to compare NaNs and support a
// tolerance. // tolerance.
if (formatInfo.type == Float) { if (customExpectation != nullptr) {
const float* expectedFloats = static_cast<const float*>(expectedRenderData);
std::vector<float> expectedVector(
expectedFloats, expectedFloats + expectedRenderDataSize / sizeof(float));
AddBufferExpectation(__FILE__, __LINE__, readbackBuffer, 0, expectedRenderDataSize, AddBufferExpectation(__FILE__, __LINE__, readbackBuffer, 0, expectedRenderDataSize,
new ExpectFloatWithTolerance(expectedVector, floatTolerance)); customExpectation);
} else { } else {
EXPECT_BUFFER_U32_RANGE_EQ(static_cast<const uint32_t*>(expectedRenderData), EXPECT_BUFFER_U32_RANGE_EQ(static_cast<const uint32_t*>(expectedRenderData),
readbackBuffer, 0, 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 <typename TextureData, typename RenderData> template <typename TextureData, typename RenderData>
void DoSampleTest(FormatTestInfo formatInfo, void DoFormatSamplingTest(FormatTestInfo formatInfo,
const std::vector<TextureData>& textureData, const std::vector<TextureData>& textureData,
const std::vector<RenderData>& expectedRenderData, const std::vector<RenderData>& expectedRenderData,
float floatTolerance = 0.0f) { detail::Expectation* customExpectation = nullptr) {
FormatTestInfo renderFormatInfo = GetUncompressedFormatInfo(formatInfo);
DoSampleTest(formatInfo, textureData.data(), textureData.size() * sizeof(TextureData), DoSampleTest(formatInfo, textureData.data(), textureData.size() * sizeof(TextureData),
expectedRenderData.data(), expectedRenderData.size() * sizeof(RenderData), renderFormatInfo, expectedRenderData.data(),
floatTolerance); expectedRenderData.size() * sizeof(RenderData), customExpectation);
}
template <typename TextureData>
void DoFloatFormatSamplingTest(FormatTestInfo formatInfo,
const std::vector<TextureData>& textureData,
const std::vector<float>& 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 <typename TextureData, typename RenderData>
void DoFormatRenderingTest(FormatTestInfo formatInfo,
const std::vector<TextureData>& textureData,
const std::vector<RenderData>& 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 // 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<T>::max(); T maxValue = std::numeric_limits<T>::max();
std::vector<T> textureData = {0, 1, maxValue, maxValue}; std::vector<T> textureData = {0, 1, maxValue, maxValue};
std::vector<float> expectedData = {0.0f, 1.0f / maxValue, 1.0f, 1.0f}; std::vector<float> uncompressedData = {0.0f, 1.0f / maxValue, 1.0f, 1.0f};
DoSampleTest(formatInfo, textureData, expectedData); DoFormatSamplingTest(formatInfo, textureData, uncompressedData);
DoFormatRenderingTest(formatInfo, uncompressedData, textureData);
} }
template <typename T> template <typename T>
@ -326,9 +391,14 @@ class TextureFormatTest : public DawnTest {
T maxValue = std::numeric_limits<T>::max(); T maxValue = std::numeric_limits<T>::max();
T minValue = std::numeric_limits<T>::min(); T minValue = std::numeric_limits<T>::min();
std::vector<T> textureData = {0, 1, maxValue, minValue}; std::vector<T> textureData = {0, 1, maxValue, minValue};
std::vector<float> expectedData = {0.0f, 1.0f / maxValue, 1.0f, -1.0f}; std::vector<float> 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 <typename T> template <typename T>
@ -339,9 +409,10 @@ class TextureFormatTest : public DawnTest {
T maxValue = std::numeric_limits<T>::max(); T maxValue = std::numeric_limits<T>::max();
std::vector<T> textureData = {0, 1, maxValue, maxValue}; std::vector<T> textureData = {0, 1, maxValue, maxValue};
std::vector<uint32_t> expectedData = {0, 1, maxValue, maxValue}; std::vector<uint32_t> uncompressedData = {0, 1, maxValue, maxValue};
DoSampleTest(formatInfo, textureData, expectedData); DoFormatSamplingTest(formatInfo, textureData, uncompressedData);
DoFormatRenderingTest(formatInfo, uncompressedData, textureData);
} }
template <typename T> template <typename T>
@ -353,9 +424,10 @@ class TextureFormatTest : public DawnTest {
T maxValue = std::numeric_limits<T>::max(); T maxValue = std::numeric_limits<T>::max();
T minValue = std::numeric_limits<T>::min(); T minValue = std::numeric_limits<T>::min();
std::vector<T> textureData = {0, 1, maxValue, minValue}; std::vector<T> textureData = {0, 1, maxValue, minValue};
std::vector<int32_t> expectedData = {0, 1, maxValue, minValue}; std::vector<int32_t> uncompressedData = {0, 1, maxValue, minValue};
DoSampleTest(formatInfo, textureData, expectedData); DoFormatSamplingTest(formatInfo, textureData, uncompressedData);
DoFormatRenderingTest(formatInfo, uncompressedData, textureData);
} }
void DoFloat32Test(FormatTestInfo formatInfo) { void DoFloat32Test(FormatTestInfo formatInfo) {
@ -365,21 +437,26 @@ class TextureFormatTest : public DawnTest {
std::vector<float> textureData = {+0.0f, -0.0f, 1.0f, 1.0e-29f, std::vector<float> textureData = {+0.0f, -0.0f, 1.0f, 1.0e-29f,
1.0e29, NAN, INFINITY, -INFINITY}; 1.0e29, NAN, INFINITY, -INFINITY};
DoSampleTest(formatInfo, textureData, textureData); DoFloatFormatSamplingTest(formatInfo, textureData, textureData);
DoFormatRenderingTest(formatInfo, textureData, textureData);
} }
void DoFloat16Test(FormatTestInfo formatInfo) { void DoFloat16Test(FormatTestInfo formatInfo) {
ASSERT(sizeof(int16_t) * formatInfo.componentCount == formatInfo.texelByteSize); ASSERT(sizeof(int16_t) * formatInfo.componentCount == formatInfo.texelByteSize);
ASSERT(formatInfo.type == Float); ASSERT(formatInfo.type == Float);
std::vector<float> expectedData = {+0.0f, -0.0f, 1.0f, 1.0e-4f, std::vector<float> uncompressedData = {+0.0f, -0.0f, 1.0f, 1.01e-4f,
1.0e4f, NAN, INFINITY, -INFINITY}; 1.0e4f, NAN, INFINITY, -INFINITY};
std::vector<uint16_t> textureData; std::vector<uint16_t> textureData;
for (float value : expectedData) { for (float value : uncompressedData) {
textureData.push_back(Float32ToFloat16(value)); 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: private:
@ -420,8 +497,11 @@ TEST_P(TextureFormatTest, RGBA16Unorm) {
TEST_P(TextureFormatTest, BGRA8Unorm) { TEST_P(TextureFormatTest, BGRA8Unorm) {
uint8_t maxValue = std::numeric_limits<uint8_t>::max(); uint8_t maxValue = std::numeric_limits<uint8_t>::max();
std::vector<uint8_t> textureData = {maxValue, 1, 0, maxValue}; std::vector<uint8_t> textureData = {maxValue, 1, 0, maxValue};
std::vector<float> expectedData = {0.0f, 1.0f / maxValue, 1.0f, 1.0f}; std::vector<float> uncompressedData = {0.0f, 1.0f / maxValue, 1.0f, 1.0f};
DoSampleTest({dawn::TextureFormat::BGRA8Unorm, 4, Float, 4}, textureData, expectedData); DoFormatSamplingTest({dawn::TextureFormat::BGRA8Unorm, 4, Float, 4}, textureData,
uncompressedData);
DoFormatRenderingTest({dawn::TextureFormat::BGRA8Unorm, 4, Float, 4}, uncompressedData,
textureData);
} }
// Test the R8Snorm format // Test the R8Snorm format
@ -579,36 +659,40 @@ TEST_P(TextureFormatTest, RGBA8UnormSrgb) {
uint8_t maxValue = std::numeric_limits<uint8_t>::max(); uint8_t maxValue = std::numeric_limits<uint8_t>::max();
std::vector<uint8_t> textureData = {0, 1, maxValue, 64, 35, 68, 152, 168}; std::vector<uint8_t> textureData = {0, 1, maxValue, 64, 35, 68, 152, 168};
std::vector<float> expectedData; std::vector<float> uncompressedData;
for (size_t i = 0; i < textureData.size(); i += 4) { for (size_t i = 0; i < textureData.size(); i += 4) {
expectedData.push_back(SRGBToLinear(textureData[i + 0] / float(maxValue))); uncompressedData.push_back(SRGBToLinear(textureData[i + 0] / float(maxValue)));
expectedData.push_back(SRGBToLinear(textureData[i + 1] / float(maxValue))); uncompressedData.push_back(SRGBToLinear(textureData[i + 1] / float(maxValue)));
expectedData.push_back(SRGBToLinear(textureData[i + 2] / float(maxValue))); uncompressedData.push_back(SRGBToLinear(textureData[i + 2] / float(maxValue)));
// Alpha is linear for sRGB formats // 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, DoFloatFormatSamplingTest({dawn::TextureFormat::RGBA8UnormSrgb, 4, Float, 4}, textureData,
1.0e-3); 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) { TEST_P(TextureFormatTest, BGRA8UnormSrgb) {
uint8_t maxValue = std::numeric_limits<uint8_t>::max(); uint8_t maxValue = std::numeric_limits<uint8_t>::max();
std::vector<uint8_t> textureData = {0, 1, maxValue, 64, 35, 68, 152, 168}; std::vector<uint8_t> textureData = {0, 1, maxValue, 64, 35, 68, 152, 168};
std::vector<float> expectedData; std::vector<float> uncompressedData;
for (size_t i = 0; i < textureData.size(); i += 4) { for (size_t i = 0; i < textureData.size(); i += 4) {
// Note that R and B are swapped // Note that R and B are swapped
expectedData.push_back(SRGBToLinear(textureData[i + 2] / float(maxValue))); uncompressedData.push_back(SRGBToLinear(textureData[i + 2] / float(maxValue)));
expectedData.push_back(SRGBToLinear(textureData[i + 1] / float(maxValue))); uncompressedData.push_back(SRGBToLinear(textureData[i + 1] / float(maxValue)));
expectedData.push_back(SRGBToLinear(textureData[i + 0] / float(maxValue))); uncompressedData.push_back(SRGBToLinear(textureData[i + 0] / float(maxValue)));
// Alpha is linear for sRGB formats // 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, DoFloatFormatSamplingTest({dawn::TextureFormat::BGRA8UnormSrgb, 4, Float, 4}, textureData,
1.0e-3); uncompressedData, 1.0e-3);
DoFormatRenderingTest({dawn::TextureFormat::BGRA8UnormSrgb, 4, Float, 4}, uncompressedData,
textureData);
} }
// Test the RGB10A2Unorm format // Test the RGB10A2Unorm format
@ -622,18 +706,20 @@ TEST_P(TextureFormatTest, RGB10A2Unorm) {
}; };
std::vector<uint32_t> textureData = {MakeRGB10A2(0, 0, 0, 0), MakeRGB10A2(1023, 1023, 1023, 1), std::vector<uint32_t> 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 // clang-format off
std::vector<float> expectedData = { std::vector<float> uncompressedData = {
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1 / 3.0f, 1.0f, 1.0f, 1.0f, 1 / 3.0f,
243 / 1023.0f, 576 / 1023.0f, 765 / 1023.0f, 2 / 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 // clang-format on
DoSampleTest({dawn::TextureFormat::RGB10A2Unorm, 4, Float, 4}, textureData, expectedData, DoFloatFormatSamplingTest({dawn::TextureFormat::RGB10A2Unorm, 4, Float, 4}, textureData,
2.0e-3); uncompressedData, 1.0e-5);
DoFormatRenderingTest({dawn::TextureFormat::RGB10A2Unorm, 4, Float, 4}, uncompressedData,
textureData);
} }
// Test the RG11B10Float format // 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 // 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 // should slways be sampled as 1
// clang-format off // clang-format off
std::vector<float> expectedData = { std::vector<float> uncompressedData = {
0.0f, INFINITY, NAN, 1.0f, 0.0f, INFINITY, NAN, 1.0f,
INFINITY, NAN, 1.0f, 1.0f, INFINITY, NAN, 1.0f, 1.0f,
NAN, 1.0f, 0.0f, 1.0f, NAN, 1.0f, 0.0f, 1.0f,
@ -675,7 +761,9 @@ TEST_P(TextureFormatTest, RG11B10Float) {
}; };
// clang-format on // 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 // TODO(cwallez@chromium.org): Add tests for depth-stencil formats when we know if they are copyable

View File

@ -151,6 +151,20 @@ TEST(Math, Float32ToFloat16) {
ASSERT_EQ(Float32ToFloat16(1.0f), 0x3C00); 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 // Tests for SRGBToLinear
TEST(Math, SRGBToLinear) { TEST(Math, SRGBToLinear) {
ASSERT_EQ(SRGBToLinear(0.0f), 0.0f); ASSERT_EQ(SRGBToLinear(0.0f), 0.0f);