CopyTextureForBrowser: Use large triangle to avoid arithmetic precision
In previous internal shader, we draw a just fit-in rectangle to do the copy. But there is arithmetic precision issues in border pixels when copy from a large texture. ANGLE handle the same issue by drawing a large triangle. Dawn adopte the same idea here BUG=dawn:465 Change-Id: I2366e28b1e96e7a33116a170023a5138d8c9f770 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/33900 Reviewed-by: Shaobo Yan <shaobo.yan@intel.com> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Shaobo Yan <shaobo.yan@intel.com>
This commit is contained in:
parent
d1b65e0d32
commit
a827aa2c29
|
@ -32,50 +32,42 @@
|
||||||
|
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
namespace {
|
namespace {
|
||||||
|
// TODO(shaobo.yan@intel.com) : Support premultiplay-alpha, flipY.
|
||||||
// TODO(shaobo.yan@intel.com): Use ANGLE's strategy(render a large triangle) to handle
|
|
||||||
// transform and border interop issue.
|
|
||||||
static const char sCopyTextureForBrowserVertex[] = R"(
|
static const char sCopyTextureForBrowserVertex[] = R"(
|
||||||
[[block]] struct Uniforms {
|
[[block]] struct Uniforms {
|
||||||
[[offset(0)]] rotation : mat4x4<f32>;
|
[[offset(0)]] u_scale : vec2<f32>;
|
||||||
|
[[offset(8)]] u_offset : vec2<f32>;
|
||||||
};
|
};
|
||||||
const pos : array<vec2<f32>, 6> = array<vec2<f32>, 6>(
|
const texcoord : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
|
||||||
vec2<f32>(1.0, 1.0),
|
vec2<f32>(-0.5, 0.0),
|
||||||
vec2<f32>(1.0, -1.0),
|
vec2<f32>( 1.5, 0.0),
|
||||||
vec2<f32>(-1.0, -1.0),
|
vec2<f32>( 0.5, 2.0));
|
||||||
vec2<f32>(1.0, 1.0),
|
[[location(0)]] var<out> v_texcoord: vec2<f32>;
|
||||||
vec2<f32>(-1.0, -1.0),
|
|
||||||
vec2<f32>(-1.0, 1.0));
|
|
||||||
|
|
||||||
const texUV : array<vec2<f32>, 6> = array<vec2<f32>, 6>(
|
|
||||||
vec2<f32>(1.0, 0.0),
|
|
||||||
vec2<f32>(1.0, 1.0),
|
|
||||||
vec2<f32>(0.0, 1.0),
|
|
||||||
vec2<f32>(1.0, 0.0),
|
|
||||||
vec2<f32>(0.0, 1.0),
|
|
||||||
vec2<f32>(0.0, 0.0));
|
|
||||||
|
|
||||||
[[location(0)]] var<out> texCoord: vec2<f32>;
|
|
||||||
[[builtin(position)]] var<out> Position : vec4<f32>;
|
[[builtin(position)]] var<out> Position : vec4<f32>;
|
||||||
[[builtin(vertex_idx)]] var<in> VertexIndex : u32;
|
[[builtin(vertex_idx)]] var<in> VertexIndex : u32;
|
||||||
[[binding(0), set(0)]] var<uniform> uniforms : Uniforms;
|
[[binding(0), set(0)]] var<uniform> uniforms : Uniforms;
|
||||||
[[stage(vertex)]]
|
[[stage(vertex)]] fn main() -> void {
|
||||||
fn main() -> void {
|
Position = vec4<f32>((texcoord[VertexIndex] * 2.0 - vec2<f32>(1.0, 1.0)), 0.0, 1.0);
|
||||||
Position = uniforms.rotation * vec4<f32>(pos[VertexIndex], 0.0, 1.0);
|
|
||||||
texCoord = texUV[VertexIndex];
|
# Texture coordinate takes top-left as origin point. We need to map the
|
||||||
return;
|
# texture to triangle carefully.
|
||||||
|
v_texcoord = (texcoord[VertexIndex] * vec2<f32>(1.0, -1.0) + vec2<f32>(0.0, 1.0)) *
|
||||||
|
uniforms.u_scale + uniforms.u_offset;
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
static const char sPassthrough2D4ChannelFrag[] = R"(
|
static const char sPassthrough2D4ChannelFrag[] = R"(
|
||||||
[[binding(1), set(0)]] var<uniform_constant> mySampler: sampler;
|
[[binding(1), set(0)]] var<uniform_constant> mySampler: sampler;
|
||||||
[[binding(2), set(0)]] var<uniform_constant> myTexture: texture_sampled_2d<f32>;
|
[[binding(2), set(0)]] var<uniform_constant> myTexture: texture_sampled_2d<f32>;
|
||||||
[[location(0)]] var<in> texCoord : vec2<f32>;
|
[[location(0)]] var<in> v_texcoord : vec2<f32>;
|
||||||
[[location(0)]] var<out> rgbaColor : vec4<f32>;
|
[[location(0)]] var<out> rgbaColor : vec4<f32>;
|
||||||
[[stage(fragment)]]
|
[[stage(fragment)]] fn main() -> void {
|
||||||
fn main() -> void {
|
# Clamp the texcoord and discard the out-of-bound pixels.
|
||||||
rgbaColor = textureSample(myTexture, mySampler, texCoord);
|
var clampedTexcoord : vec2<f32> =
|
||||||
return;
|
clamp(v_texcoord, vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0));
|
||||||
|
if (all(clampedTexcoord == v_texcoord)) {
|
||||||
|
rgbaColor = textureSample(myTexture, mySampler, v_texcoord);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
|
@ -224,10 +216,8 @@ namespace dawn_native {
|
||||||
// TODO(shaobo.yan@intel.com): Will use scale vector and offset vector to replace the
|
// TODO(shaobo.yan@intel.com): Will use scale vector and offset vector to replace the
|
||||||
// 4x4 rotation matrix here.
|
// 4x4 rotation matrix here.
|
||||||
const float rotationMatrix[] = {
|
const float rotationMatrix[] = {
|
||||||
1.0, 0.0, 0.0, 0.0, //
|
1.0, 1.0, // scale
|
||||||
0.0, 1.0, 0.0, 0.0, //
|
0.0, 0.0 // offset
|
||||||
0.0, 0.0, 1.0, 0.0, //
|
|
||||||
0.0, 0.0, 0.0, 1.0, //
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BufferDescriptor rotationUniformDesc = {};
|
BufferDescriptor rotationUniformDesc = {};
|
||||||
|
@ -290,7 +280,7 @@ namespace dawn_native {
|
||||||
// the copy from src texture to dst texture with transformation.
|
// the copy from src texture to dst texture with transformation.
|
||||||
passEncoder->SetPipeline(pipeline);
|
passEncoder->SetPipeline(pipeline);
|
||||||
passEncoder->SetBindGroup(0, bindGroup.Get());
|
passEncoder->SetBindGroup(0, bindGroup.Get());
|
||||||
passEncoder->Draw(6);
|
passEncoder->Draw(3);
|
||||||
passEncoder->EndPass();
|
passEncoder->EndPass();
|
||||||
|
|
||||||
// Finsh encoding.
|
// Finsh encoding.
|
||||||
|
|
|
@ -176,6 +176,66 @@ TEST_P(CopyTextureForBrowserTests, PassthroughCopy) {
|
||||||
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(CopyTextureForBrowserTests, VerifyCopyOnXDirection) {
|
||||||
|
// These tests fails due to crbug.com/tint/63.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
DAWN_SKIP_TEST_IF(IsVulkan());
|
||||||
|
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
|
||||||
|
|
||||||
|
// OpenGL tests fails due to 'WriteTexture' unimplemented.
|
||||||
|
// Related bug : crbug.com/dawn/483
|
||||||
|
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||||
|
|
||||||
|
constexpr uint32_t kWidth = 1000;
|
||||||
|
constexpr uint32_t kHeight = 1;
|
||||||
|
|
||||||
|
TextureSpec textureSpec;
|
||||||
|
textureSpec.copyOrigin = {0, 0, 0};
|
||||||
|
textureSpec.level = 0;
|
||||||
|
textureSpec.textureSize = {kWidth, kHeight, 1};
|
||||||
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(CopyTextureForBrowserTests, VerifyCopyOnYDirection) {
|
||||||
|
// These tests fails due to crbug.com/tint/63.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
DAWN_SKIP_TEST_IF(IsVulkan());
|
||||||
|
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
|
||||||
|
|
||||||
|
// OpenGL tests fails due to 'WriteTexture' unimplemented.
|
||||||
|
// Related bug : crbug.com/dawn/483
|
||||||
|
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||||
|
|
||||||
|
constexpr uint32_t kWidth = 1;
|
||||||
|
constexpr uint32_t kHeight = 1000;
|
||||||
|
|
||||||
|
TextureSpec textureSpec;
|
||||||
|
textureSpec.copyOrigin = {0, 0, 0};
|
||||||
|
textureSpec.level = 0;
|
||||||
|
textureSpec.textureSize = {kWidth, kHeight, 1};
|
||||||
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(CopyTextureForBrowserTests, VerifyCopyFromLargeTexture) {
|
||||||
|
// These tests fails due to crbug.com/tint/63.
|
||||||
|
DAWN_SKIP_TEST_IF(IsSwiftshader());
|
||||||
|
DAWN_SKIP_TEST_IF(IsVulkan());
|
||||||
|
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
|
||||||
|
|
||||||
|
// OpenGL tests fails due to 'WriteTexture' unimplemented.
|
||||||
|
// Related bug : crbug.com/dawn/483
|
||||||
|
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||||
|
|
||||||
|
constexpr uint32_t kWidth = 899;
|
||||||
|
constexpr uint32_t kHeight = 999;
|
||||||
|
|
||||||
|
TextureSpec textureSpec;
|
||||||
|
textureSpec.copyOrigin = {0, 0, 0};
|
||||||
|
textureSpec.level = 0;
|
||||||
|
textureSpec.textureSize = {kWidth, kHeight, 1};
|
||||||
|
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(CopyTextureForBrowserTests,
|
DAWN_INSTANTIATE_TEST(CopyTextureForBrowserTests,
|
||||||
D3D12Backend(),
|
D3D12Backend(),
|
||||||
MetalBackend(),
|
MetalBackend(),
|
||||||
|
|
Loading…
Reference in New Issue