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:
parent
e896a0da66
commit
2d8ba5fac6
|
@ -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]
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue