mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-01 04:01:26 +00:00
Change-Id: Ia80b1bed84aa7d16421d432d5da861e55175b335 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/85841 Commit-Queue: Brandon Jones <bajones@chromium.org> Auto-Submit: Brandon Jones <bajones@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: James Price <jrprice@google.com>
1167 lines
51 KiB
C++
1167 lines
51 KiB
C++
// Copyright 2020 The Dawn 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 "dawn/tests/DawnTest.h"
|
|
|
|
#include "dawn/common/Constants.h"
|
|
#include "dawn/common/Math.h"
|
|
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
|
|
#include "dawn/utils/TestUtils.h"
|
|
#include "dawn/utils/TextureUtils.h"
|
|
#include "dawn/utils/WGPUHelpers.h"
|
|
|
|
namespace {
|
|
static constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::RGBA8Unorm;
|
|
|
|
// Set default texture size to single line texture for color conversion tests.
|
|
static constexpr uint64_t kDefaultTextureWidth = 10;
|
|
static constexpr uint64_t kDefaultTextureHeight = 1;
|
|
|
|
enum class ColorSpace : uint32_t {
|
|
SRGB = 0x00,
|
|
DisplayP3 = 0x01,
|
|
};
|
|
|
|
using SrcFormat = wgpu::TextureFormat;
|
|
using DstFormat = wgpu::TextureFormat;
|
|
using SrcOrigin = wgpu::Origin3D;
|
|
using DstOrigin = wgpu::Origin3D;
|
|
using CopySize = wgpu::Extent3D;
|
|
using FlipY = bool;
|
|
using SrcColorSpace = ColorSpace;
|
|
using DstColorSpace = ColorSpace;
|
|
using SrcAlphaMode = wgpu::AlphaMode;
|
|
using DstAlphaMode = wgpu::AlphaMode;
|
|
|
|
std::ostream& operator<<(std::ostream& o, wgpu::Origin3D origin) {
|
|
o << origin.x << ", " << origin.y << ", " << origin.z;
|
|
return o;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& o, wgpu::Extent3D copySize) {
|
|
o << copySize.width << ", " << copySize.height << ", " << copySize.depthOrArrayLayers;
|
|
return o;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& o, ColorSpace space) {
|
|
o << static_cast<uint32_t>(space);
|
|
return o;
|
|
}
|
|
|
|
DAWN_TEST_PARAM_STRUCT(AlphaTestParams, SrcAlphaMode, DstAlphaMode);
|
|
DAWN_TEST_PARAM_STRUCT(FormatTestParams, SrcFormat, DstFormat);
|
|
DAWN_TEST_PARAM_STRUCT(SubRectTestParams, SrcOrigin, DstOrigin, CopySize, FlipY);
|
|
DAWN_TEST_PARAM_STRUCT(ColorSpaceTestParams,
|
|
DstFormat,
|
|
SrcColorSpace,
|
|
DstColorSpace,
|
|
SrcAlphaMode,
|
|
DstAlphaMode);
|
|
|
|
// Color Space table
|
|
struct ColorSpaceInfo {
|
|
ColorSpace index;
|
|
std::array<float, 9> toXYZD50; // 3x3 row major transform matrix
|
|
std::array<float, 9> fromXYZD50; // inverse transform matrix of toXYZD50, precomputed
|
|
std::array<float, 7> gammaDecodingParams; // Follow { A, B, G, E, epsilon, C, F } order
|
|
std::array<float, 7> gammaEncodingParams; // inverse op of decoding, precomputed
|
|
bool isNonLinear;
|
|
bool isExtended; // For extended color space.
|
|
};
|
|
static constexpr size_t kSupportedColorSpaceCount = 2;
|
|
static constexpr std::array<ColorSpaceInfo, kSupportedColorSpaceCount> ColorSpaceTable = {{
|
|
// sRGB,
|
|
// Got primary attributes from https://drafts.csswg.org/css-color/#predefined-sRGB
|
|
// Use matrices from
|
|
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html#WSMatrices
|
|
// Get gamma-linear conversion params from https://en.wikipedia.org/wiki/SRGB with some
|
|
// mathematics.
|
|
{
|
|
//
|
|
ColorSpace::SRGB,
|
|
{{
|
|
//
|
|
0.4360747, 0.3850649, 0.1430804, //
|
|
0.2225045, 0.7168786, 0.0606169, //
|
|
0.0139322, 0.0971045, 0.7141733 //
|
|
}},
|
|
|
|
{{
|
|
//
|
|
3.1338561, -1.6168667, -0.4906146, //
|
|
-0.9787684, 1.9161415, 0.0334540, //
|
|
0.0719453, -0.2289914, 1.4052427 //
|
|
}},
|
|
|
|
// {G, A, B, C, D, E, F, }
|
|
{{2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 4.045e-02, 0.0, 0.0}},
|
|
|
|
{{1.0 / 2.4, 1.13711 /*pow(1.055, 2.4)*/, 0.0, 12.92f, 3.1308e-03, -0.055, 0.0}},
|
|
|
|
true,
|
|
true //
|
|
},
|
|
|
|
// Display P3, got primary attributes from
|
|
// https://www.w3.org/TR/css-color-4/#valdef-color-display-p3
|
|
// Use equations found in
|
|
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html,
|
|
// Use Bradford method to do D65 to D50 transform.
|
|
// Get matrices with help of http://www.russellcottrell.com/photo/matrixCalculator.htm
|
|
// Gamma-linear conversion params is the same as Srgb.
|
|
{
|
|
//
|
|
ColorSpace::DisplayP3,
|
|
{{
|
|
//
|
|
0.5151114, 0.2919612, 0.1571274, //
|
|
0.2411865, 0.6922440, 0.0665695, //
|
|
-0.0010491, 0.0418832, 0.7842659 //
|
|
}},
|
|
|
|
{{
|
|
//
|
|
2.4039872, -0.9898498, -0.3976181, //
|
|
-0.8422138, 1.7988188, 0.0160511, //
|
|
0.0481937, -0.0973889, 1.2736887 //
|
|
}},
|
|
|
|
// {G, A, B, C, D, E, F, }
|
|
{{2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 4.045e-02, 0.0, 0.0}},
|
|
|
|
{{1.0 / 2.4, 1.13711 /*pow(1.055, 2.4)*/, 0.0, 12.92f, 3.1308e-03, -0.055, 0.0}},
|
|
|
|
true,
|
|
false //
|
|
}
|
|
//
|
|
}};
|
|
} // anonymous namespace
|
|
|
|
template <typename Parent>
|
|
class CopyTextureForBrowserTests : public Parent {
|
|
protected:
|
|
struct TextureSpec {
|
|
wgpu::Origin3D copyOrigin = {};
|
|
wgpu::Extent3D textureSize = {kDefaultTextureWidth, kDefaultTextureHeight};
|
|
uint32_t level = 0;
|
|
wgpu::TextureFormat format = kTextureFormat;
|
|
};
|
|
|
|
enum class TextureCopyRole {
|
|
SOURCE,
|
|
DEST,
|
|
};
|
|
|
|
// Source texture contains red pixels and dst texture contains green pixels at start.
|
|
static std::vector<RGBA8> GetTextureData(
|
|
const utils::TextureDataCopyLayout& layout,
|
|
TextureCopyRole textureRole,
|
|
wgpu::AlphaMode srcAlphaMode = wgpu::AlphaMode::Premultiplied,
|
|
wgpu::AlphaMode dstAlphaMode = wgpu::AlphaMode::Unpremultiplied) {
|
|
std::array<uint8_t, 4> alpha = {0, 102, 153, 255}; // 0.0, 0.4, 0.6, 1.0
|
|
std::vector<RGBA8> textureData(layout.texelBlockCount);
|
|
for (uint32_t layer = 0; layer < layout.mipSize.depthOrArrayLayers; ++layer) {
|
|
const uint32_t sliceOffset = layout.texelBlocksPerImage * layer;
|
|
for (uint32_t y = 0; y < layout.mipSize.height; ++y) {
|
|
const uint32_t rowOffset = layout.texelBlocksPerRow * y;
|
|
for (uint32_t x = 0; x < layout.mipSize.width; ++x) {
|
|
// Source textures will have variable pixel data to cover cases like
|
|
// flipY.
|
|
if (textureRole == TextureCopyRole::SOURCE) {
|
|
if (srcAlphaMode != dstAlphaMode) {
|
|
if (dstAlphaMode == wgpu::AlphaMode::Premultiplied) {
|
|
// For premultiply alpha test cases, we expect each channel in dst
|
|
// texture will equal to the alpha channel value.
|
|
ASSERT(srcAlphaMode == wgpu::AlphaMode::Unpremultiplied);
|
|
textureData[sliceOffset + rowOffset + x] = RGBA8(
|
|
static_cast<uint8_t>(255), static_cast<uint8_t>(255),
|
|
static_cast<uint8_t>(255), static_cast<uint8_t>(alpha[x % 4]));
|
|
} else {
|
|
// For unpremultiply alpha test cases, we expect each channel in dst
|
|
// texture will equal to 1.0.
|
|
ASSERT(srcAlphaMode == wgpu::AlphaMode::Premultiplied);
|
|
textureData[sliceOffset + rowOffset + x] =
|
|
RGBA8(static_cast<uint8_t>(alpha[x % 4]),
|
|
static_cast<uint8_t>(alpha[x % 4]),
|
|
static_cast<uint8_t>(alpha[x % 4]),
|
|
static_cast<uint8_t>(alpha[x % 4]));
|
|
}
|
|
|
|
} else {
|
|
textureData[sliceOffset + rowOffset + x] =
|
|
RGBA8(static_cast<uint8_t>((x + layer * x) % 256),
|
|
static_cast<uint8_t>((y + layer * y) % 256),
|
|
static_cast<uint8_t>(x % 256), static_cast<uint8_t>(x % 256));
|
|
}
|
|
} else { // Dst textures will have be init as `green` to ensure subrect
|
|
// copy not cross bound.
|
|
textureData[sliceOffset + rowOffset + x] =
|
|
RGBA8(static_cast<uint8_t>(0), static_cast<uint8_t>(255),
|
|
static_cast<uint8_t>(0), static_cast<uint8_t>(255));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return textureData;
|
|
}
|
|
|
|
void SetUp() override {
|
|
Parent::SetUp();
|
|
pipeline = MakeTestPipeline();
|
|
|
|
uint32_t uniformBufferData[] = {
|
|
0, // copy have flipY option
|
|
4, // channelCount
|
|
0,
|
|
0, // uvec2, subrect copy src origin
|
|
0,
|
|
0, // uvec2, subrect copy dst origin
|
|
0,
|
|
0, // uvec2, subrect copy size
|
|
0, // srcAlphaMode, wgpu::AlphaMode::Premultiplied
|
|
0 // dstAlphaMode, wgpu::AlphaMode::Premultiplied
|
|
};
|
|
|
|
wgpu::BufferDescriptor uniformBufferDesc = {};
|
|
uniformBufferDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform;
|
|
uniformBufferDesc.size = sizeof(uniformBufferData);
|
|
uniformBuffer = this->device.CreateBuffer(&uniformBufferDesc);
|
|
}
|
|
|
|
// Do the bit-by-bit comparison between the source and destination texture with GPU (compute
|
|
// shader) instead of CPU after executing CopyTextureForBrowser() to avoid the errors caused by
|
|
// comparing a value generated on CPU to the one generated on GPU.
|
|
wgpu::ComputePipeline MakeTestPipeline() {
|
|
wgpu::ShaderModule csModule = utils::CreateShaderModule(this->device, R"(
|
|
struct Uniforms {
|
|
dstTextureFlipY : u32,
|
|
channelCount : u32,
|
|
srcCopyOrigin : vec2<u32>,
|
|
dstCopyOrigin : vec2<u32>,
|
|
copySize : vec2<u32>,
|
|
srcAlphaMode : u32,
|
|
dstAlphaMode : u32,
|
|
}
|
|
struct OutputBuf {
|
|
result : array<u32>
|
|
}
|
|
@group(0) @binding(0) var src : texture_2d<f32>;
|
|
@group(0) @binding(1) var dst : texture_2d<f32>;
|
|
@group(0) @binding(2) var<storage, read_write> output : OutputBuf;
|
|
@group(0) @binding(3) var<uniform> uniforms : Uniforms;
|
|
fn aboutEqual(value : f32, expect : f32) -> bool {
|
|
// The value diff should be smaller than the hard coded tolerance.
|
|
return abs(value - expect) < 0.01;
|
|
}
|
|
@stage(compute) @workgroup_size(1, 1, 1)
|
|
fn main(@builtin(global_invocation_id) GlobalInvocationID : vec3<u32>) {
|
|
let srcSize = textureDimensions(src);
|
|
let dstSize = textureDimensions(dst);
|
|
let dstTexCoord = vec2<u32>(GlobalInvocationID.xy);
|
|
let nonCoveredColor = vec4<f32>(0.0, 1.0, 0.0, 1.0); // should be green
|
|
|
|
var success : bool = true;
|
|
if (dstTexCoord.x < uniforms.dstCopyOrigin.x ||
|
|
dstTexCoord.y < uniforms.dstCopyOrigin.y ||
|
|
dstTexCoord.x >= uniforms.dstCopyOrigin.x + uniforms.copySize.x ||
|
|
dstTexCoord.y >= uniforms.dstCopyOrigin.y + uniforms.copySize.y) {
|
|
success = success &&
|
|
all(textureLoad(dst, vec2<i32>(dstTexCoord), 0) == nonCoveredColor);
|
|
} else {
|
|
// Calculate source texture coord.
|
|
var srcTexCoord = dstTexCoord - uniforms.dstCopyOrigin +
|
|
uniforms.srcCopyOrigin;
|
|
// Note that |flipY| equals flip src texture firstly and then do copy from src
|
|
// subrect to dst subrect. This helps on blink part to handle some input texture
|
|
// which is flipped and need to unpack flip during the copy.
|
|
// We need to calculate the expect y coord based on this rule.
|
|
if (uniforms.dstTextureFlipY == 1u) {
|
|
srcTexCoord.y = u32(srcSize.y) - srcTexCoord.y - 1u;
|
|
}
|
|
|
|
var srcColor = textureLoad(src, vec2<i32>(srcTexCoord), 0);
|
|
var dstColor = textureLoad(dst, vec2<i32>(dstTexCoord), 0);
|
|
|
|
// Expect the dst texture channels should be all equal to alpha value
|
|
// after premultiply.
|
|
let premultiplied = 0u;
|
|
let unpremultiplied = 1u;
|
|
if (uniforms.srcAlphaMode != uniforms.dstAlphaMode) {
|
|
if (uniforms.dstAlphaMode == premultiplied) {
|
|
// srcAlphaMode == unpremultiplied
|
|
srcColor = vec4<f32>(srcColor.rgb * srcColor.a, srcColor.a);
|
|
}
|
|
|
|
if (uniforms.dstAlphaMode == unpremultiplied) {
|
|
// srcAlphaMode == premultiplied
|
|
if (srcColor.a != 0.0) {
|
|
srcColor = vec4<f32>(srcColor.rgb / srcColor.a, srcColor.a);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Not use loop and variable index format to workaround
|
|
// crbug.com/tint/638.
|
|
switch(uniforms.channelCount) {
|
|
case 1u: {
|
|
success = success && aboutEqual(dstColor.r, srcColor.r);
|
|
break;
|
|
}
|
|
case 2u: {
|
|
success = success &&
|
|
aboutEqual(dstColor.r, srcColor.r) &&
|
|
aboutEqual(dstColor.g, srcColor.g);
|
|
break;
|
|
}
|
|
case 4u: {
|
|
success = success &&
|
|
aboutEqual(dstColor.r, srcColor.r) &&
|
|
aboutEqual(dstColor.g, srcColor.g) &&
|
|
aboutEqual(dstColor.b, srcColor.b) &&
|
|
aboutEqual(dstColor.a, srcColor.a);
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
let outputIndex = GlobalInvocationID.y * u32(dstSize.x) + GlobalInvocationID.x;
|
|
if (success) {
|
|
output.result[outputIndex] = 1u;
|
|
} else {
|
|
output.result[outputIndex] = 0u;
|
|
}
|
|
}
|
|
)");
|
|
|
|
wgpu::ComputePipelineDescriptor csDesc;
|
|
csDesc.compute.module = csModule;
|
|
csDesc.compute.entryPoint = "main";
|
|
|
|
return this->device.CreateComputePipeline(&csDesc);
|
|
}
|
|
static uint32_t GetTextureFormatComponentCount(wgpu::TextureFormat format) {
|
|
switch (format) {
|
|
case wgpu::TextureFormat::RGBA8Unorm:
|
|
case wgpu::TextureFormat::RGBA8UnormSrgb:
|
|
case wgpu::TextureFormat::BGRA8Unorm:
|
|
case wgpu::TextureFormat::BGRA8UnormSrgb:
|
|
case wgpu::TextureFormat::RGB10A2Unorm:
|
|
case wgpu::TextureFormat::RGBA16Float:
|
|
case wgpu::TextureFormat::RGBA32Float:
|
|
return 4;
|
|
case wgpu::TextureFormat::RG8Unorm:
|
|
case wgpu::TextureFormat::RG16Float:
|
|
case wgpu::TextureFormat::RG32Float:
|
|
return 2;
|
|
case wgpu::TextureFormat::R8Unorm:
|
|
case wgpu::TextureFormat::R16Float:
|
|
case wgpu::TextureFormat::R32Float:
|
|
return 1;
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
}
|
|
|
|
wgpu::Texture CreateTexture(const TextureSpec& spec, wgpu::TextureUsage usage) {
|
|
// Create and initialize src texture.
|
|
wgpu::TextureDescriptor descriptor;
|
|
descriptor.size = spec.textureSize;
|
|
descriptor.format = spec.format;
|
|
descriptor.mipLevelCount = spec.level + 1;
|
|
descriptor.usage = usage;
|
|
wgpu::Texture texture = this->device.CreateTexture(&descriptor);
|
|
return texture;
|
|
}
|
|
|
|
wgpu::Texture CreateAndInitTexture(const TextureSpec& spec,
|
|
wgpu::TextureUsage usage,
|
|
utils::TextureDataCopyLayout copyLayout,
|
|
void const* init,
|
|
uint32_t initBytes) {
|
|
wgpu::Texture texture = CreateTexture(spec, usage);
|
|
|
|
wgpu::ImageCopyTexture imageTextureInit =
|
|
utils::CreateImageCopyTexture(texture, spec.level, {0, 0});
|
|
|
|
wgpu::TextureDataLayout textureDataLayout;
|
|
textureDataLayout.offset = 0;
|
|
textureDataLayout.bytesPerRow = copyLayout.bytesPerRow;
|
|
textureDataLayout.rowsPerImage = copyLayout.rowsPerImage;
|
|
|
|
this->device.GetQueue().WriteTexture(&imageTextureInit, init, initBytes, &textureDataLayout,
|
|
©Layout.mipSize);
|
|
return texture;
|
|
}
|
|
|
|
void RunCopyExternalImageToTexture(const TextureSpec& srcSpec,
|
|
wgpu::Texture srcTexture,
|
|
const TextureSpec& dstSpec,
|
|
wgpu::Texture dstTexture,
|
|
const wgpu::Extent3D& copySize,
|
|
const wgpu::CopyTextureForBrowserOptions options) {
|
|
wgpu::ImageCopyTexture srcImageCopyTexture =
|
|
utils::CreateImageCopyTexture(srcTexture, srcSpec.level, srcSpec.copyOrigin);
|
|
wgpu::ImageCopyTexture dstImageCopyTexture =
|
|
utils::CreateImageCopyTexture(dstTexture, dstSpec.level, dstSpec.copyOrigin);
|
|
this->device.GetQueue().CopyTextureForBrowser(&srcImageCopyTexture, &dstImageCopyTexture,
|
|
©Size, &options);
|
|
}
|
|
|
|
void CheckResultInBuiltInComputePipeline(const TextureSpec& srcSpec,
|
|
wgpu::Texture srcTexture,
|
|
const TextureSpec& dstSpec,
|
|
wgpu::Texture dstTexture,
|
|
const wgpu::Extent3D& copySize,
|
|
const wgpu::CopyTextureForBrowserOptions options) {
|
|
// Update uniform buffer based on test config
|
|
uint32_t uniformBufferData[] = {
|
|
options.flipY, // copy have flipY option
|
|
GetTextureFormatComponentCount(dstSpec.format), // channelCount
|
|
srcSpec.copyOrigin.x,
|
|
srcSpec.copyOrigin.y, // src texture copy origin
|
|
dstSpec.copyOrigin.x,
|
|
dstSpec.copyOrigin.y, // dst texture copy origin
|
|
copySize.width,
|
|
copySize.height, // copy size
|
|
static_cast<uint32_t>(options.srcAlphaMode),
|
|
static_cast<uint32_t>(options.dstAlphaMode)};
|
|
|
|
this->device.GetQueue().WriteBuffer(uniformBuffer, 0, uniformBufferData,
|
|
sizeof(uniformBufferData));
|
|
|
|
// Create output buffer to store result
|
|
wgpu::BufferDescriptor outputDesc;
|
|
outputDesc.size = dstSpec.textureSize.width * dstSpec.textureSize.height * sizeof(uint32_t);
|
|
outputDesc.usage =
|
|
wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
|
wgpu::Buffer outputBuffer = this->device.CreateBuffer(&outputDesc);
|
|
|
|
// Create texture views for test.
|
|
wgpu::TextureViewDescriptor srcTextureViewDesc = {};
|
|
srcTextureViewDesc.baseMipLevel = srcSpec.level;
|
|
wgpu::TextureView srcTextureView = srcTexture.CreateView(&srcTextureViewDesc);
|
|
|
|
wgpu::TextureViewDescriptor dstTextureViewDesc = {};
|
|
dstTextureViewDesc.baseMipLevel = dstSpec.level;
|
|
wgpu::TextureView dstTextureView = dstTexture.CreateView(&dstTextureViewDesc);
|
|
|
|
// Create bind group based on the config.
|
|
wgpu::BindGroup bindGroup = utils::MakeBindGroup(
|
|
this->device, pipeline.GetBindGroupLayout(0),
|
|
{{0, srcTextureView}, {1, dstTextureView}, {2, outputBuffer}, {3, uniformBuffer}});
|
|
|
|
// Start a pipeline to check pixel value in bit form.
|
|
wgpu::CommandEncoder testEncoder = this->device.CreateCommandEncoder();
|
|
|
|
wgpu::CommandBuffer testCommands;
|
|
{
|
|
wgpu::CommandEncoder encoder = this->device.CreateCommandEncoder();
|
|
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
|
pass.SetPipeline(pipeline);
|
|
pass.SetBindGroup(0, bindGroup);
|
|
pass.Dispatch(dstSpec.textureSize.width,
|
|
dstSpec.textureSize.height); // Verify dst texture content
|
|
pass.End();
|
|
|
|
testCommands = encoder.Finish();
|
|
}
|
|
this->device.GetQueue().Submit(1, &testCommands);
|
|
|
|
std::vector<uint32_t> expectResult(dstSpec.textureSize.width * dstSpec.textureSize.height,
|
|
1);
|
|
EXPECT_BUFFER_U32_RANGE_EQ(expectResult.data(), outputBuffer, 0,
|
|
dstSpec.textureSize.width * dstSpec.textureSize.height);
|
|
}
|
|
|
|
void DoTest(const TextureSpec& srcSpec,
|
|
const TextureSpec& dstSpec,
|
|
const wgpu::Extent3D& copySize = {kDefaultTextureWidth, kDefaultTextureHeight},
|
|
const wgpu::CopyTextureForBrowserOptions options = {}) {
|
|
// Create and initialize src texture.
|
|
const utils::TextureDataCopyLayout srcCopyLayout =
|
|
utils::GetTextureDataCopyLayoutForTextureAtLevel(
|
|
kTextureFormat,
|
|
{srcSpec.textureSize.width, srcSpec.textureSize.height,
|
|
copySize.depthOrArrayLayers},
|
|
srcSpec.level);
|
|
|
|
std::vector<RGBA8> srcTextureArrayCopyData = GetTextureData(
|
|
srcCopyLayout, TextureCopyRole::SOURCE, options.srcAlphaMode, options.dstAlphaMode);
|
|
|
|
wgpu::TextureUsage srcUsage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
|
|
wgpu::TextureUsage::TextureBinding;
|
|
wgpu::Texture srcTexture =
|
|
CreateAndInitTexture(srcSpec, srcUsage, srcCopyLayout, srcTextureArrayCopyData.data(),
|
|
srcTextureArrayCopyData.size() * sizeof(RGBA8));
|
|
|
|
bool testSubRectCopy = srcSpec.copyOrigin.x > 0 || srcSpec.copyOrigin.y > 0 ||
|
|
dstSpec.copyOrigin.x > 0 || dstSpec.copyOrigin.y > 0 ||
|
|
srcSpec.textureSize.width > copySize.width ||
|
|
srcSpec.textureSize.height > copySize.height ||
|
|
dstSpec.textureSize.width > copySize.width ||
|
|
dstSpec.textureSize.height > copySize.height;
|
|
|
|
// Create and init dst texture.
|
|
wgpu::Texture dstTexture;
|
|
wgpu::TextureUsage dstUsage =
|
|
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::TextureBinding |
|
|
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
|
|
|
|
if (testSubRectCopy) {
|
|
// For subrect copy tests, dst texture use kTextureFormat always.
|
|
const utils::TextureDataCopyLayout dstCopyLayout =
|
|
utils::GetTextureDataCopyLayoutForTextureAtLevel(
|
|
kTextureFormat,
|
|
{dstSpec.textureSize.width, dstSpec.textureSize.height,
|
|
copySize.depthOrArrayLayers},
|
|
dstSpec.level);
|
|
|
|
const std::vector<RGBA8> dstTextureArrayCopyData =
|
|
GetTextureData(dstCopyLayout, TextureCopyRole::DEST);
|
|
dstTexture = CreateAndInitTexture(dstSpec, dstUsage, dstCopyLayout,
|
|
dstTextureArrayCopyData.data(),
|
|
dstTextureArrayCopyData.size() * sizeof(RGBA8));
|
|
} else {
|
|
dstTexture = CreateTexture(dstSpec, dstUsage);
|
|
}
|
|
|
|
// Perform the texture to texture copy
|
|
RunCopyExternalImageToTexture(srcSpec, srcTexture, dstSpec, dstTexture, copySize, options);
|
|
|
|
// Check Result
|
|
CheckResultInBuiltInComputePipeline(srcSpec, srcTexture, dstSpec, dstTexture, copySize,
|
|
options);
|
|
}
|
|
|
|
wgpu::Buffer uniformBuffer;
|
|
wgpu::ComputePipeline pipeline;
|
|
};
|
|
|
|
class CopyTextureForBrowser_Basic : public CopyTextureForBrowserTests<DawnTest> {
|
|
protected:
|
|
void DoBasicCopyTest(const wgpu::Extent3D& copySize,
|
|
const wgpu::CopyTextureForBrowserOptions options = {}) {
|
|
TextureSpec textureSpec;
|
|
textureSpec.textureSize = copySize;
|
|
|
|
DoTest(textureSpec, textureSpec, copySize, options);
|
|
}
|
|
};
|
|
|
|
class CopyTextureForBrowser_Formats
|
|
: public CopyTextureForBrowserTests<DawnTestWithParams<FormatTestParams>> {
|
|
protected:
|
|
bool IsDstFormatSrgbFormats() {
|
|
return GetParam().mDstFormat == wgpu::TextureFormat::RGBA8UnormSrgb ||
|
|
GetParam().mDstFormat == wgpu::TextureFormat::BGRA8UnormSrgb;
|
|
}
|
|
|
|
wgpu::TextureFormat GetNonSrgbFormat(wgpu::TextureFormat format) {
|
|
switch (format) {
|
|
case wgpu::TextureFormat::RGBA8UnormSrgb:
|
|
return wgpu::TextureFormat::RGBA8Unorm;
|
|
case wgpu::TextureFormat::BGRA8UnormSrgb:
|
|
return wgpu::TextureFormat::BGRA8Unorm;
|
|
default:
|
|
return format;
|
|
}
|
|
}
|
|
|
|
void DoColorConversionTest() {
|
|
TextureSpec srcTextureSpec;
|
|
srcTextureSpec.format = GetParam().mSrcFormat;
|
|
|
|
TextureSpec dstTextureSpec;
|
|
dstTextureSpec.format = GetParam().mDstFormat;
|
|
|
|
wgpu::Extent3D copySize = {kDefaultTextureWidth, kDefaultTextureHeight};
|
|
wgpu::CopyTextureForBrowserOptions options = {};
|
|
|
|
// Create and init source texture.
|
|
// This fixed source texture data is for color conversion tests.
|
|
// The source data can fill a texture in default width and height.
|
|
std::vector<RGBA8> srcTextureArrayCopyData{
|
|
// Take RGBA8Unorm as example:
|
|
// R channel has different values
|
|
RGBA8(0, 255, 255, 255), // r = 0.0
|
|
RGBA8(102, 255, 255, 255), // r = 0.4
|
|
RGBA8(153, 255, 255, 255), // r = 0.6
|
|
|
|
// G channel has different values
|
|
RGBA8(255, 0, 255, 255), // g = 0.0
|
|
RGBA8(255, 102, 255, 255), // g = 0.4
|
|
RGBA8(255, 153, 255, 255), // g = 0.6
|
|
|
|
// B channel has different values
|
|
RGBA8(255, 255, 0, 255), // b = 0.0
|
|
RGBA8(255, 255, 102, 255), // b = 0.4
|
|
RGBA8(255, 255, 153, 255), // b = 0.6
|
|
|
|
// A channel set to 0
|
|
RGBA8(255, 255, 255, 0) // a = 0
|
|
};
|
|
|
|
const utils::TextureDataCopyLayout srcCopyLayout =
|
|
utils::GetTextureDataCopyLayoutForTextureAtLevel(
|
|
kTextureFormat,
|
|
{srcTextureSpec.textureSize.width, srcTextureSpec.textureSize.height,
|
|
copySize.depthOrArrayLayers},
|
|
srcTextureSpec.level);
|
|
|
|
wgpu::TextureUsage srcUsage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
|
|
wgpu::TextureUsage::TextureBinding;
|
|
wgpu::Texture srcTexture = CreateAndInitTexture(
|
|
srcTextureSpec, srcUsage, srcCopyLayout, srcTextureArrayCopyData.data(),
|
|
srcTextureArrayCopyData.size() * sizeof(RGBA8));
|
|
|
|
// Create dst texture.
|
|
wgpu::Texture dstTexture = CreateTexture(
|
|
dstTextureSpec, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::TextureBinding |
|
|
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);
|
|
|
|
// Perform the texture to texture copy
|
|
RunCopyExternalImageToTexture(srcTextureSpec, srcTexture, dstTextureSpec, dstTexture,
|
|
copySize, options);
|
|
|
|
wgpu::Texture result;
|
|
TextureSpec resultSpec = dstTextureSpec;
|
|
|
|
// To construct the expected value for the case that dst texture is srgb format,
|
|
// we need to ensure it is byte level equal to the comparable non-srgb format texture.
|
|
// We schedule an copy from srgb texture to non-srgb texture which keeps the bytes
|
|
// same and bypass the sampler to do gamma correction when comparing the expected values
|
|
// in compute shader.
|
|
if (IsDstFormatSrgbFormats()) {
|
|
resultSpec.format = GetNonSrgbFormat(dstTextureSpec.format);
|
|
wgpu::Texture intermediateTexture = CreateTexture(
|
|
resultSpec, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::TextureBinding |
|
|
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);
|
|
|
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
|
|
|
// Perform the texture to texture copy
|
|
wgpu::ImageCopyTexture dstImageCopyTexture =
|
|
utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0});
|
|
wgpu::ImageCopyTexture intermediateImageCopyTexture =
|
|
utils::CreateImageCopyTexture(intermediateTexture, 0, {0, 0, 0});
|
|
|
|
encoder.CopyTextureToTexture(&dstImageCopyTexture, &intermediateImageCopyTexture,
|
|
&(dstTextureSpec.textureSize));
|
|
wgpu::CommandBuffer commands = encoder.Finish();
|
|
queue.Submit(1, &commands);
|
|
|
|
result = intermediateTexture;
|
|
} else {
|
|
result = dstTexture;
|
|
}
|
|
|
|
// Check Result
|
|
CheckResultInBuiltInComputePipeline(srcTextureSpec, srcTexture, resultSpec, result,
|
|
copySize, options);
|
|
}
|
|
};
|
|
|
|
class CopyTextureForBrowser_SubRects
|
|
: public CopyTextureForBrowserTests<DawnTestWithParams<SubRectTestParams>> {
|
|
protected:
|
|
void DoCopySubRectTest() {
|
|
TextureSpec srcTextureSpec;
|
|
srcTextureSpec.copyOrigin = GetParam().mSrcOrigin;
|
|
srcTextureSpec.textureSize = {6, 7};
|
|
|
|
TextureSpec dstTextureSpec;
|
|
dstTextureSpec.copyOrigin = GetParam().mDstOrigin;
|
|
dstTextureSpec.textureSize = {8, 5};
|
|
wgpu::CopyTextureForBrowserOptions options = {};
|
|
options.flipY = GetParam().mFlipY;
|
|
|
|
wgpu::Extent3D copySize = GetParam().mCopySize;
|
|
|
|
DoTest(srcTextureSpec, dstTextureSpec, copySize, options);
|
|
}
|
|
};
|
|
|
|
class CopyTextureForBrowser_AlphaMode
|
|
: public CopyTextureForBrowserTests<DawnTestWithParams<AlphaTestParams>> {
|
|
protected:
|
|
void DoAlphaModeTest() {
|
|
constexpr uint32_t kWidth = 10;
|
|
constexpr uint32_t kHeight = 10;
|
|
|
|
TextureSpec textureSpec;
|
|
textureSpec.textureSize = {kWidth, kHeight};
|
|
|
|
wgpu::CopyTextureForBrowserOptions options = {};
|
|
options.srcAlphaMode = GetParam().mSrcAlphaMode;
|
|
options.dstAlphaMode = GetParam().mDstAlphaMode;
|
|
|
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight}, options);
|
|
}
|
|
};
|
|
|
|
class CopyTextureForBrowser_ColorSpace
|
|
: public CopyTextureForBrowserTests<DawnTestWithParams<ColorSpaceTestParams>> {
|
|
protected:
|
|
const ColorSpaceInfo& GetColorSpaceInfo(ColorSpace colorSpace) {
|
|
uint32_t index = static_cast<uint32_t>(colorSpace);
|
|
ASSERT(index < ColorSpaceTable.size());
|
|
ASSERT(ColorSpaceTable[index].index == colorSpace);
|
|
return ColorSpaceTable[index];
|
|
}
|
|
|
|
std::array<float, 9> GetConversionMatrix(ColorSpace src, ColorSpace dst) {
|
|
const ColorSpaceInfo& srcColorSpace = GetColorSpaceInfo(src);
|
|
const ColorSpaceInfo& dstColorSpace = GetColorSpaceInfo(dst);
|
|
|
|
const std::array<float, 9> toXYZD50 = srcColorSpace.toXYZD50;
|
|
const std::array<float, 9> fromXYZD50 = dstColorSpace.fromXYZD50;
|
|
|
|
// Fuse the transform matrix. The color space transformation equation is:
|
|
// Pixels = fromXYZD50 * toXYZD50 * Pixels.
|
|
// Calculate fromXYZD50 * toXYZD50 to simplify
|
|
// Add a padding in each row for Mat3x3 in wgsl uniform(mat3x3, Align(16), Size(48)).
|
|
std::array<float, 9> fuseMatrix = {};
|
|
|
|
// Mat3x3 * Mat3x3
|
|
for (uint32_t row = 0; row < 3; ++row) {
|
|
for (uint32_t col = 0; col < 3; ++col) {
|
|
// Transpose the matrix from row major to column major for wgsl.
|
|
fuseMatrix[col * 3 + row] = fromXYZD50[row * 3 + 0] * toXYZD50[col] +
|
|
fromXYZD50[row * 3 + 1] * toXYZD50[3 + col] +
|
|
fromXYZD50[row * 3 + 2] * toXYZD50[3 * 2 + col];
|
|
}
|
|
}
|
|
|
|
return fuseMatrix;
|
|
}
|
|
|
|
// TODO(crbug.com/dawn/1140): Generate source data automatically.
|
|
std::vector<RGBA8> GetSourceData(wgpu::AlphaMode srcTextureAlphaMode) {
|
|
if (srcTextureAlphaMode == wgpu::AlphaMode::Premultiplied) {
|
|
return std::vector<RGBA8>{
|
|
RGBA8(0, 102, 102, 102), // a = 0.4
|
|
RGBA8(102, 0, 0, 102), // a = 0.4
|
|
RGBA8(153, 0, 0, 153), // a = 0.6
|
|
RGBA8(255, 0, 0, 255), // a = 1.0
|
|
|
|
RGBA8(153, 0, 153, 153), // a = 0.6
|
|
RGBA8(0, 102, 0, 102), // a = 0.4
|
|
RGBA8(0, 153, 0, 153), // a = 0.6
|
|
RGBA8(0, 255, 0, 255), // a = 1.0
|
|
|
|
RGBA8(255, 255, 0, 255), // a = 1.0
|
|
RGBA8(0, 0, 102, 102), // a = 0.4
|
|
RGBA8(0, 0, 153, 153), // a = 0.6
|
|
RGBA8(0, 0, 255, 255), // a = 1.0
|
|
};
|
|
}
|
|
|
|
return std::vector<RGBA8>{
|
|
// Take RGBA8Unorm as example:
|
|
// R channel has different values
|
|
RGBA8(0, 255, 255, 255), // r = 0.0
|
|
RGBA8(102, 0, 0, 255), // r = 0.4
|
|
RGBA8(153, 0, 0, 255), // r = 0.6
|
|
RGBA8(255, 0, 0, 255), // r = 1.0
|
|
|
|
// G channel has different values
|
|
RGBA8(255, 0, 255, 255), // g = 0.0
|
|
RGBA8(0, 102, 0, 255), // g = 0.4
|
|
RGBA8(0, 153, 0, 255), // g = 0.6
|
|
RGBA8(0, 255, 0, 255), // g = 1.0
|
|
|
|
// B channel has different values
|
|
RGBA8(255, 255, 0, 255), // b = 0.0
|
|
RGBA8(0, 0, 102, 255), // b = 0.4
|
|
RGBA8(0, 0, 153, 255), // b = 0.6
|
|
RGBA8(0, 0, 255, 255), // b = 1.0
|
|
};
|
|
}
|
|
|
|
// TODO(crbug.com/dawn/1140): Current expected values are from ColorSync utils
|
|
// tool on Mac. Should implement CPU or compute shader algorithm to do color
|
|
// conversion and use the result as expected data.
|
|
std::vector<float> GetExpectedData(ColorSpace srcColorSpace,
|
|
ColorSpace dstColorSpace,
|
|
wgpu::AlphaMode srcTextureAlphaMode,
|
|
wgpu::AlphaMode dstTextureAlphaMode) {
|
|
if (srcTextureAlphaMode == wgpu::AlphaMode::Premultiplied) {
|
|
return GetExpectedDataForPremultipliedSource(srcColorSpace, dstColorSpace,
|
|
dstTextureAlphaMode);
|
|
}
|
|
|
|
return GetExpectedDataForSeperateSource(srcColorSpace, dstColorSpace);
|
|
}
|
|
|
|
std::vector<float> GeneratePremultipliedResult(std::vector<float> result) {
|
|
// Four channels per pixel
|
|
for (uint32_t i = 0; i < result.size(); i += 4) {
|
|
result[i] *= result[i + 3];
|
|
result[i + 1] *= result[i + 3];
|
|
result[i + 2] *= result[i + 3];
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
std::vector<float> GetExpectedDataForPremultipliedSource(ColorSpace srcColorSpace,
|
|
ColorSpace dstColorSpace,
|
|
wgpu::AlphaMode dstTextureAlphaMode) {
|
|
if (srcColorSpace == dstColorSpace) {
|
|
std::vector<float> expected = {
|
|
0.0, 1.0, 1.0, 0.4, //
|
|
1.0, 0.0, 0.0, 0.4, //
|
|
1.0, 0.0, 0.0, 0.6, //
|
|
1.0, 0.0, 0.0, 1.0, //
|
|
|
|
1.0, 0.0, 1.0, 0.6, //
|
|
0.0, 1.0, 0.0, 0.4, //
|
|
0.0, 1.0, 0.0, 0.6, //
|
|
0.0, 1.0, 0.0, 1.0, //
|
|
|
|
1.0, 1.0, 0.0, 1.0, //
|
|
0.0, 0.0, 1.0, 0.4, //
|
|
0.0, 0.0, 1.0, 0.6, //
|
|
0.0, 0.0, 1.0, 1.0, //
|
|
};
|
|
|
|
return dstTextureAlphaMode == wgpu::AlphaMode::Premultiplied
|
|
? GeneratePremultipliedResult(expected)
|
|
: expected;
|
|
}
|
|
|
|
switch (srcColorSpace) {
|
|
case ColorSpace::DisplayP3: {
|
|
switch (dstColorSpace) {
|
|
case ColorSpace::SRGB: {
|
|
std::vector<float> expected = {
|
|
-0.5118, 1.0183, 1.0085, 0.4, //
|
|
1.093, -0.2267, -0.1501, 0.4, //
|
|
1.093, -0.2267, -0.1501, 0.6, //
|
|
1.093, -0.2267, -0.1501, 1.0, //
|
|
|
|
1.093, -0.2266, 1.0337, 0.6, //
|
|
-0.5118, 1.0183, -0.3107, 0.4, //
|
|
-0.5118, 1.0183, -0.3107, 0.6, //
|
|
-0.5118, 1.0183, -0.3107, 1.0, //
|
|
|
|
0.9999, 1.0001, -0.3462, 1.0, //
|
|
0.0002, 0.0004, 1.0419, 0.4, //
|
|
0.0002, 0.0004, 1.0419, 0.6, //
|
|
0.0002, 0.0004, 1.0419, 1.0, //
|
|
};
|
|
|
|
return dstTextureAlphaMode == wgpu::AlphaMode::Premultiplied
|
|
? GeneratePremultipliedResult(expected)
|
|
: expected;
|
|
}
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
UNREACHABLE();
|
|
}
|
|
|
|
std::vector<float> GetExpectedDataForSeperateSource(ColorSpace srcColorSpace,
|
|
ColorSpace dstColorSpace) {
|
|
if (srcColorSpace == dstColorSpace) {
|
|
return std::vector<float>{
|
|
0.0, 1.0, 1.0, 1.0, //
|
|
0.4, 0.0, 0.0, 1.0, //
|
|
0.6, 0.0, 0.0, 1.0, //
|
|
1.0, 0.0, 0.0, 1.0, //
|
|
|
|
1.0, 0.0, 1.0, 1.0, //
|
|
0.0, 0.4, 0.0, 1.0, //
|
|
0.0, 0.6, 0.0, 1.0, //
|
|
0.0, 1.0, 0.0, 1.0, //
|
|
|
|
1.0, 1.0, 0.0, 1.0, //
|
|
0.0, 0.0, 0.4, 1.0, //
|
|
0.0, 0.0, 0.6, 1.0, //
|
|
0.0, 0.0, 1.0, 1.0, //
|
|
};
|
|
}
|
|
|
|
switch (srcColorSpace) {
|
|
case ColorSpace::DisplayP3: {
|
|
switch (dstColorSpace) {
|
|
case ColorSpace::SRGB: {
|
|
return std::vector<float>{
|
|
-0.5118, 1.0183, 1.0085, 1.0, //
|
|
0.4401, -0.0665, -0.0337, 1.0, //
|
|
0.6578, -0.1199, -0.0723, 1.0, //
|
|
1.093, -0.2267, -0.1501, 1.0, //
|
|
|
|
1.093, -0.2266, 1.0337, 1.0, //
|
|
-0.1894, 0.4079, -0.1027, 1.0, //
|
|
-0.2969, 0.6114, -0.1720, 1.0, //
|
|
-0.5118, 1.0183, -0.3107, 1.0, //
|
|
|
|
0.9999, 1.0001, -0.3462, 1.0, //
|
|
0.0000, 0.0001, 0.4181, 1.0, //
|
|
0.0001, 0.0001, 0.6260, 1.0, //
|
|
0.0002, 0.0004, 1.0419, 1.0, //
|
|
};
|
|
}
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
UNREACHABLE();
|
|
}
|
|
|
|
void DoColorSpaceConversionTest() {
|
|
constexpr uint32_t kWidth = 12;
|
|
constexpr uint32_t kHeight = 1;
|
|
|
|
TextureSpec srcTextureSpec;
|
|
srcTextureSpec.textureSize = {kWidth, kHeight};
|
|
|
|
TextureSpec dstTextureSpec;
|
|
dstTextureSpec.textureSize = {kWidth, kHeight};
|
|
dstTextureSpec.format = GetParam().mDstFormat;
|
|
|
|
ColorSpace srcColorSpace = GetParam().mSrcColorSpace;
|
|
ColorSpace dstColorSpace = GetParam().mDstColorSpace;
|
|
|
|
ColorSpaceInfo srcColorSpaceInfo = GetColorSpaceInfo(srcColorSpace);
|
|
ColorSpaceInfo dstColorSpaceInfo = GetColorSpaceInfo(dstColorSpace);
|
|
|
|
std::array<float, 9> matrix = GetConversionMatrix(srcColorSpace, dstColorSpace);
|
|
|
|
wgpu::CopyTextureForBrowserOptions options = {};
|
|
options.needsColorSpaceConversion = srcColorSpace != dstColorSpace;
|
|
options.srcAlphaMode = GetParam().mSrcAlphaMode;
|
|
options.srcTransferFunctionParameters = srcColorSpaceInfo.gammaDecodingParams.data();
|
|
options.conversionMatrix = matrix.data();
|
|
options.dstTransferFunctionParameters = dstColorSpaceInfo.gammaEncodingParams.data();
|
|
options.dstAlphaMode = GetParam().mDstAlphaMode;
|
|
|
|
std::vector<RGBA8> sourceTextureData = GetSourceData(options.srcAlphaMode);
|
|
const wgpu::Extent3D& copySize = {kWidth, kHeight};
|
|
|
|
const utils::TextureDataCopyLayout srcCopyLayout =
|
|
utils::GetTextureDataCopyLayoutForTextureAtLevel(
|
|
kTextureFormat,
|
|
{srcTextureSpec.textureSize.width, srcTextureSpec.textureSize.height},
|
|
srcTextureSpec.level);
|
|
|
|
wgpu::TextureUsage srcUsage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
|
|
wgpu::TextureUsage::TextureBinding;
|
|
wgpu::Texture srcTexture = this->CreateAndInitTexture(
|
|
srcTextureSpec, srcUsage, srcCopyLayout, sourceTextureData.data(),
|
|
sourceTextureData.size() * sizeof(RGBA8));
|
|
|
|
// Create dst texture.
|
|
wgpu::Texture dstTexture = this->CreateTexture(
|
|
dstTextureSpec, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::TextureBinding |
|
|
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);
|
|
|
|
// Perform the texture to texture copy
|
|
this->RunCopyExternalImageToTexture(srcTextureSpec, srcTexture, dstTextureSpec, dstTexture,
|
|
copySize, options);
|
|
|
|
std::vector<float> expectedData = GetExpectedData(
|
|
srcColorSpace, dstColorSpace, options.srcAlphaMode, options.dstAlphaMode);
|
|
|
|
// The value provided by Apple's ColorSync Utility.
|
|
float tolerance = 0.001;
|
|
if (dstTextureSpec.format == wgpu::TextureFormat::RGBA16Float) {
|
|
EXPECT_TEXTURE_FLOAT16_EQ(expectedData.data(), dstTexture, {0, 0}, {kWidth, kHeight},
|
|
dstTextureSpec.format, tolerance);
|
|
} else {
|
|
EXPECT_TEXTURE_EQ(expectedData.data(), dstTexture, {0, 0}, {kWidth, kHeight},
|
|
dstTextureSpec.format, tolerance);
|
|
}
|
|
}
|
|
};
|
|
|
|
// Verify CopyTextureForBrowserTests works with internal pipeline.
|
|
// The case do copy without any transform.
|
|
TEST_P(CopyTextureForBrowser_Basic, PassthroughCopy) {
|
|
// TODO(crbug.com/dawn/1232): Program link error on OpenGLES backend
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux());
|
|
|
|
DoBasicCopyTest({10, 1});
|
|
}
|
|
|
|
TEST_P(CopyTextureForBrowser_Basic, VerifyCopyOnXDirection) {
|
|
// TODO(crbug.com/dawn/1232): Program link error on OpenGLES backend
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux());
|
|
|
|
DoBasicCopyTest({1000, 1});
|
|
}
|
|
|
|
TEST_P(CopyTextureForBrowser_Basic, VerifyCopyOnYDirection) {
|
|
// TODO(crbug.com/dawn/1232): Program link error on OpenGLES backend
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux());
|
|
|
|
DoBasicCopyTest({1, 1000});
|
|
}
|
|
|
|
TEST_P(CopyTextureForBrowser_Basic, VerifyCopyFromLargeTexture) {
|
|
// TODO(crbug.com/dawn/1232): Program link error on OpenGLES backend
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux());
|
|
|
|
// TODO(crbug.com/dawn/1070): Flaky VK_DEVICE_LOST
|
|
DAWN_SUPPRESS_TEST_IF(IsWindows() && IsVulkan() && IsIntel());
|
|
|
|
DoBasicCopyTest({899, 999});
|
|
}
|
|
|
|
TEST_P(CopyTextureForBrowser_Basic, VerifyFlipY) {
|
|
// TODO(crbug.com/dawn/1232): Program link error on OpenGLES backend
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux());
|
|
|
|
wgpu::CopyTextureForBrowserOptions options = {};
|
|
options.flipY = true;
|
|
|
|
DoBasicCopyTest({901, 1001}, options);
|
|
}
|
|
|
|
TEST_P(CopyTextureForBrowser_Basic, VerifyFlipYInSlimTexture) {
|
|
// TODO(crbug.com/dawn/1232): Program link error on OpenGLES backend
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux());
|
|
|
|
wgpu::CopyTextureForBrowserOptions options = {};
|
|
options.flipY = true;
|
|
|
|
DoBasicCopyTest({1, 1001}, options);
|
|
}
|
|
|
|
DAWN_INSTANTIATE_TEST(CopyTextureForBrowser_Basic,
|
|
D3D12Backend(),
|
|
MetalBackend(),
|
|
OpenGLBackend(),
|
|
OpenGLESBackend(),
|
|
VulkanBackend());
|
|
|
|
// Verify |CopyTextureForBrowser| doing color conversion correctly when
|
|
// the source texture is RGBA8Unorm format.
|
|
TEST_P(CopyTextureForBrowser_Formats, ColorConversion) {
|
|
// Skip OpenGLES backend because it fails on using RGBA8Unorm as
|
|
// source texture format.
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux());
|
|
|
|
// Skip OpenGL backend on linux because it fails on using *-srgb format as
|
|
// dst texture format
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux() && IsDstFormatSrgbFormats());
|
|
|
|
DoColorConversionTest();
|
|
}
|
|
|
|
DAWN_INSTANTIATE_TEST_P(
|
|
CopyTextureForBrowser_Formats,
|
|
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(), VulkanBackend()},
|
|
std::vector<wgpu::TextureFormat>({wgpu::TextureFormat::RGBA8Unorm,
|
|
wgpu::TextureFormat::BGRA8Unorm}),
|
|
std::vector<wgpu::TextureFormat>(
|
|
{wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::R16Float, wgpu::TextureFormat::R32Float,
|
|
wgpu::TextureFormat::RG8Unorm, wgpu::TextureFormat::RG16Float,
|
|
wgpu::TextureFormat::RG32Float, wgpu::TextureFormat::RGBA8Unorm,
|
|
wgpu::TextureFormat::RGBA8UnormSrgb, wgpu::TextureFormat::BGRA8Unorm,
|
|
wgpu::TextureFormat::BGRA8UnormSrgb, wgpu::TextureFormat::RGB10A2Unorm,
|
|
wgpu::TextureFormat::RGBA16Float, wgpu::TextureFormat::RGBA32Float}));
|
|
|
|
// Verify |CopyTextureForBrowser| doing subrect copy.
|
|
// Source texture is a full red texture and dst texture is a full
|
|
// green texture originally. After the subrect copy, affected part
|
|
// in dst texture should be red and other part should remain green.
|
|
TEST_P(CopyTextureForBrowser_SubRects, CopySubRect) {
|
|
// TODO(crbug.com/dawn/1232): Program link error on OpenGLES backend
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux());
|
|
|
|
// Tests skip due to crbug.com/dawn/592.
|
|
DAWN_SUPPRESS_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
|
|
|
|
// Tests skip due to crbug.com/dawn/1104.
|
|
DAWN_SUPPRESS_TEST_IF(IsWARP());
|
|
|
|
DoCopySubRectTest();
|
|
}
|
|
|
|
DAWN_INSTANTIATE_TEST_P(CopyTextureForBrowser_SubRects,
|
|
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
|
|
VulkanBackend()},
|
|
std::vector<wgpu::Origin3D>({{1, 1}, {1, 2}, {2, 1}}),
|
|
std::vector<wgpu::Origin3D>({{1, 1}, {1, 2}, {2, 1}}),
|
|
std::vector<wgpu::Extent3D>({{1, 1}, {2, 1}, {1, 2}, {2, 2}}),
|
|
std::vector<bool>({true, false}));
|
|
|
|
// Verify |CopyTextureForBrowser| doing alpha changes.
|
|
// Test srcAlphaMode and dstAlphaMode: Premultiplied, Unpremultiplied.
|
|
TEST_P(CopyTextureForBrowser_AlphaMode, alphaMode) {
|
|
// Skip OpenGLES backend because it fails on using RGBA8Unorm as
|
|
// source texture format.
|
|
// TODO(crbug.com/dawn/1232): Program link error on OpenGLES backend
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux());
|
|
|
|
// Tests skip due to crbug.com/dawn/1104.
|
|
DAWN_SUPPRESS_TEST_IF(IsWARP());
|
|
|
|
DoAlphaModeTest();
|
|
}
|
|
|
|
DAWN_INSTANTIATE_TEST_P(CopyTextureForBrowser_AlphaMode,
|
|
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
|
|
VulkanBackend()},
|
|
std::vector<wgpu::AlphaMode>({wgpu::AlphaMode::Premultiplied,
|
|
wgpu::AlphaMode::Unpremultiplied}),
|
|
std::vector<wgpu::AlphaMode>({wgpu::AlphaMode::Premultiplied,
|
|
wgpu::AlphaMode::Unpremultiplied}));
|
|
|
|
// Verify |CopyTextureForBrowser| doing color space conversion.
|
|
TEST_P(CopyTextureForBrowser_ColorSpace, colorSpaceConversion) {
|
|
// TODO(crbug.com/dawn/1232): Program link error on OpenGLES backend
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
|
|
DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux());
|
|
|
|
// Tests skip due to crbug.com/dawn/1104.
|
|
DAWN_SUPPRESS_TEST_IF(IsWARP());
|
|
|
|
DoColorSpaceConversionTest();
|
|
}
|
|
|
|
DAWN_INSTANTIATE_TEST_P(CopyTextureForBrowser_ColorSpace,
|
|
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
|
|
VulkanBackend()},
|
|
std::vector<wgpu::TextureFormat>({wgpu::TextureFormat::RGBA16Float,
|
|
wgpu::TextureFormat::RGBA32Float}),
|
|
std::vector<ColorSpace>({ColorSpace::SRGB, ColorSpace::DisplayP3}),
|
|
std::vector<ColorSpace>({ColorSpace::SRGB}),
|
|
std::vector<wgpu::AlphaMode>({wgpu::AlphaMode::Premultiplied,
|
|
wgpu::AlphaMode::Unpremultiplied}),
|
|
std::vector<wgpu::AlphaMode>({wgpu::AlphaMode::Premultiplied,
|
|
wgpu::AlphaMode::Unpremultiplied}));
|