CopyTextureForBrowser: Support flipY option

This CL enable CopyTextureForBrowser to accept options. The first
supported option is flipY, which can be implemented through scale and
offset uniforms.

BUG=dawn:465

Change-Id: Ia90153ee63a50e0e40beb1c13c63764d19a0b809
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/34402
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Yan, Shaobo 2020-12-02 08:13:09 +00:00 committed by Commit Bot service account
parent 6f5151f657
commit bb913a94da
6 changed files with 133 additions and 41 deletions

View File

@ -507,6 +507,13 @@
{"name": "compute stage", "type": "programmable stage descriptor"} {"name": "compute stage", "type": "programmable stage descriptor"}
] ]
}, },
"copy texture for browser options": {
"category": "structure",
"extensible": true,
"members": [
{"name": "flipY", "type": "bool", "default": "false"}
]
},
"create ready compute pipeline callback": { "create ready compute pipeline callback": {
"category": "callback", "category": "callback",
"args": [ "args": [
@ -1044,10 +1051,12 @@
}, },
{ {
"name": "copy texture for browser", "name": "copy texture for browser",
"extensible": true,
"args": [ "args": [
{"name": "source", "type": "texture copy view", "annotation": "const*"}, {"name": "source", "type": "texture copy view", "annotation": "const*"},
{"name": "destination", "type": "texture copy view", "annotation": "const*"}, {"name": "destination", "type": "texture copy view", "annotation": "const*"},
{"name": "copy size", "type": "extent 3D", "annotation": "const*"} {"name": "copy size", "type": "extent 3D", "annotation": "const*"},
{"name": "options", "type": "copy texture for browser options", "annotation": "const*"}
] ]
} }
] ]

View File

@ -93,6 +93,16 @@ namespace dawn_native {
return {}; return {};
} }
MaybeError ValidateCopyTextureForBrowserOptions(
const CopyTextureForBrowserOptions* options) {
if (options->nextInChain != nullptr) {
return DAWN_VALIDATION_ERROR(
"CopyTextureForBrowserOptions: nextInChain must be nullptr");
}
return {};
}
RenderPipelineBase* GetOrCreateCopyTextureForBrowserPipeline(DeviceBase* device) { RenderPipelineBase* GetOrCreateCopyTextureForBrowserPipeline(DeviceBase* device) {
InternalPipelineStore* store = device->GetInternalPipelineStore(); InternalPipelineStore* store = device->GetInternalPipelineStore();
@ -162,7 +172,8 @@ namespace dawn_native {
MaybeError ValidateCopyTextureForBrowser(DeviceBase* device, MaybeError ValidateCopyTextureForBrowser(DeviceBase* device,
const TextureCopyView* source, const TextureCopyView* source,
const TextureCopyView* destination, const TextureCopyView* destination,
const Extent3D* copySize) { const Extent3D* copySize,
const CopyTextureForBrowserOptions* options) {
DAWN_TRY(device->ValidateObject(source->texture)); DAWN_TRY(device->ValidateObject(source->texture));
DAWN_TRY(device->ValidateObject(destination->texture)); DAWN_TRY(device->ValidateObject(destination->texture));
@ -180,6 +191,8 @@ namespace dawn_native {
DAWN_TRY(ValidateCopyTextureFormatConversion(source->texture->GetFormat().format, DAWN_TRY(ValidateCopyTextureFormatConversion(source->texture->GetFormat().format,
destination->texture->GetFormat().format)); destination->texture->GetFormat().format));
DAWN_TRY(ValidateCopyTextureForBrowserOptions(options));
// TODO(shaobo.yan@intel.com): Support the simplest case for now that source and destination // TODO(shaobo.yan@intel.com): Support the simplest case for now that source and destination
// texture has the same size and do full texture blit. Will address sub texture blit in // texture has the same size and do full texture blit. Will address sub texture blit in
// future and remove these validations. // future and remove these validations.
@ -197,7 +210,8 @@ namespace dawn_native {
MaybeError DoCopyTextureForBrowser(DeviceBase* device, MaybeError DoCopyTextureForBrowser(DeviceBase* device,
const TextureCopyView* source, const TextureCopyView* source,
const TextureCopyView* destination, const TextureCopyView* destination,
const Extent3D* copySize) { const Extent3D* copySize,
const CopyTextureForBrowserOptions* options) {
// TODO(shaobo.yan@intel.com): In D3D12 and Vulkan, compatible texture format can directly // TODO(shaobo.yan@intel.com): In D3D12 and Vulkan, compatible texture format can directly
// copy to each other. This can be a potential fast path. // copy to each other. This can be a potential fast path.
RenderPipelineBase* pipeline = GetOrCreateCopyTextureForBrowserPipeline(device); RenderPipelineBase* pipeline = GetOrCreateCopyTextureForBrowserPipeline(device);
@ -213,20 +227,24 @@ namespace dawn_native {
bgDesc.entries = bindGroupEntries; bgDesc.entries = bindGroupEntries;
// Prepare binding 0 resource: uniform buffer. // Prepare binding 0 resource: uniform buffer.
// TODO(shaobo.yan@intel.com): Will use scale vector and offset vector to replace the float uniformData[] = {
// 4x4 rotation matrix here.
const float rotationMatrix[] = {
1.0, 1.0, // scale 1.0, 1.0, // scale
0.0, 0.0 // offset 0.0, 0.0 // offset
}; };
BufferDescriptor rotationUniformDesc = {}; // Handle flipY.
rotationUniformDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform; if (options && options->flipY) {
rotationUniformDesc.size = sizeof(rotationMatrix); uniformData[1] *= -1.0;
Ref<BufferBase> rotationUniform = AcquireRef(device->CreateBuffer(&rotationUniformDesc)); uniformData[3] += 1.0;
}
device->GetDefaultQueue()->WriteBuffer(rotationUniform.Get(), 0, rotationMatrix, BufferDescriptor uniformDesc = {};
sizeof(rotationMatrix)); uniformDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform;
uniformDesc.size = sizeof(uniformData);
Ref<BufferBase> uniformBuffer = AcquireRef(device->CreateBuffer(&uniformDesc));
device->GetDefaultQueue()->WriteBuffer(uniformBuffer.Get(), 0, uniformData,
sizeof(uniformData));
// Prepare binding 1 resource: sampler // Prepare binding 1 resource: sampler
// Use default configuration, filterMode set to Nearest for min and mag. // Use default configuration, filterMode set to Nearest for min and mag.
@ -242,8 +260,8 @@ namespace dawn_native {
// Set bind group entries. // Set bind group entries.
bindGroupEntries[0].binding = 0; bindGroupEntries[0].binding = 0;
bindGroupEntries[0].buffer = rotationUniform.Get(); bindGroupEntries[0].buffer = uniformBuffer.Get();
bindGroupEntries[0].size = sizeof(rotationMatrix); bindGroupEntries[0].size = sizeof(uniformData);
bindGroupEntries[1].binding = 1; bindGroupEntries[1].binding = 1;
bindGroupEntries[1].sampler = sampler.Get(); bindGroupEntries[1].sampler = sampler.Get();
bindGroupEntries[2].binding = 2; bindGroupEntries[2].binding = 2;

View File

@ -22,16 +22,19 @@ namespace dawn_native {
class DeviceBase; class DeviceBase;
struct Extent3D; struct Extent3D;
struct TextureCopyView; struct TextureCopyView;
struct CopyTextureForBrowserOptions;
MaybeError ValidateCopyTextureForBrowser(DeviceBase* device, MaybeError ValidateCopyTextureForBrowser(DeviceBase* device,
const TextureCopyView* source, const TextureCopyView* source,
const TextureCopyView* destination, const TextureCopyView* destination,
const Extent3D* copySize); const Extent3D* copySize,
const CopyTextureForBrowserOptions* options);
MaybeError DoCopyTextureForBrowser(DeviceBase* device, MaybeError DoCopyTextureForBrowser(DeviceBase* device,
const TextureCopyView* source, const TextureCopyView* source,
const TextureCopyView* destination, const TextureCopyView* destination,
const Extent3D* copySize); const Extent3D* copySize,
const CopyTextureForBrowserOptions* options);
} // namespace dawn_native } // namespace dawn_native

View File

@ -312,18 +312,23 @@ namespace dawn_native {
void QueueBase::CopyTextureForBrowser(const TextureCopyView* source, void QueueBase::CopyTextureForBrowser(const TextureCopyView* source,
const TextureCopyView* destination, const TextureCopyView* destination,
const Extent3D* copySize) { const Extent3D* copySize,
GetDevice()->ConsumedError(CopyTextureForBrowserInternal(source, destination, copySize)); const CopyTextureForBrowserOptions* options) {
GetDevice()->ConsumedError(
CopyTextureForBrowserInternal(source, destination, copySize, options));
} }
MaybeError QueueBase::CopyTextureForBrowserInternal(const TextureCopyView* source, MaybeError QueueBase::CopyTextureForBrowserInternal(
const TextureCopyView* destination, const TextureCopyView* source,
const Extent3D* copySize) { const TextureCopyView* destination,
const Extent3D* copySize,
const CopyTextureForBrowserOptions* options) {
if (GetDevice()->IsValidationEnabled()) { if (GetDevice()->IsValidationEnabled()) {
DAWN_TRY(ValidateCopyTextureForBrowser(GetDevice(), source, destination, copySize)); DAWN_TRY(
ValidateCopyTextureForBrowser(GetDevice(), source, destination, copySize, options));
} }
return DoCopyTextureForBrowser(GetDevice(), source, destination, copySize); return DoCopyTextureForBrowser(GetDevice(), source, destination, copySize, options);
} }
MaybeError QueueBase::ValidateSubmit(uint32_t commandCount, MaybeError QueueBase::ValidateSubmit(uint32_t commandCount,

View File

@ -47,7 +47,8 @@ namespace dawn_native {
const Extent3D* writeSize); const Extent3D* writeSize);
void CopyTextureForBrowser(const TextureCopyView* source, void CopyTextureForBrowser(const TextureCopyView* source,
const TextureCopyView* destination, const TextureCopyView* destination,
const Extent3D* copySize); const Extent3D* copySize,
const CopyTextureForBrowserOptions* options);
void TrackTask(std::unique_ptr<TaskInFlight> task, ExecutionSerial serial); void TrackTask(std::unique_ptr<TaskInFlight> task, ExecutionSerial serial);
void Tick(ExecutionSerial finishedSerial); void Tick(ExecutionSerial finishedSerial);
@ -68,7 +69,8 @@ namespace dawn_native {
const Extent3D* writeSize); const Extent3D* writeSize);
MaybeError CopyTextureForBrowserInternal(const TextureCopyView* source, MaybeError CopyTextureForBrowserInternal(const TextureCopyView* source,
const TextureCopyView* destination, const TextureCopyView* destination,
const Extent3D* copySize); const Extent3D* copySize,
const CopyTextureForBrowserOptions* options);
virtual MaybeError SubmitImpl(uint32_t commandCount, virtual MaybeError SubmitImpl(uint32_t commandCount,
CommandBufferBase* const* commands) = 0; CommandBufferBase* const* commands) = 0;

View File

@ -53,11 +53,15 @@ class CopyTextureForBrowserTests : public DawnTest {
uint32_t height, uint32_t height,
uint32_t srcTexelsPerRow, uint32_t srcTexelsPerRow,
RGBA8* dstData, RGBA8* dstData,
uint32_t dstTexelsPerRow) { uint32_t dstTexelsPerRow,
for (unsigned int y = 0; y < height; ++y) { const wgpu::CopyTextureForBrowserOptions* options) {
for (unsigned int x = 0; x < width; ++x) { bool isFlipY = options != nullptr && options->flipY;
unsigned int src = x + y * srcTexelsPerRow; for (uint32_t y = 0; y < height; ++y) {
unsigned int dst = x + y * dstTexelsPerRow; for (uint32_t x = 0; x < width; ++x) {
uint32_t srcYIndex =
isFlipY ? (height - y - 1) * srcTexelsPerRow : y * srcTexelsPerRow;
uint32_t src = x + srcYIndex;
uint32_t dst = x + y * dstTexelsPerRow;
dstData[dst] = srcData[src]; dstData[dst] = srcData[src];
} }
} }
@ -65,7 +69,8 @@ class CopyTextureForBrowserTests : public DawnTest {
void DoTest(const TextureSpec& srcSpec, void DoTest(const TextureSpec& srcSpec,
const TextureSpec& dstSpec, const TextureSpec& dstSpec,
const wgpu::Extent3D& copySize) { const wgpu::Extent3D& copySize,
const wgpu::CopyTextureForBrowserOptions* options) {
wgpu::TextureDescriptor srcDescriptor; wgpu::TextureDescriptor srcDescriptor;
srcDescriptor.size = srcSpec.textureSize; srcDescriptor.size = srcSpec.textureSize;
srcDescriptor.format = kTextureFormat; srcDescriptor.format = kTextureFormat;
@ -119,7 +124,7 @@ class CopyTextureForBrowserTests : public DawnTest {
// Perform a copy here for testing. // Perform a copy here for testing.
device.GetDefaultQueue().CopyTextureForBrowser(&srcTextureCopyView, &dstTextureCopyView, device.GetDefaultQueue().CopyTextureForBrowser(&srcTextureCopyView, &dstTextureCopyView,
&copySize); &copySize, options);
// Texels in single slice. // Texels in single slice.
const uint32_t texelCountInCopyRegion = utils::GetTexelCountInCopyRegion( const uint32_t texelCountInCopyRegion = utils::GetTexelCountInCopyRegion(
@ -134,7 +139,7 @@ class CopyTextureForBrowserTests : public DawnTest {
(srcSpec.copyOrigin.x + srcSpec.copyOrigin.y * copyLayout.texelBlocksPerRow); (srcSpec.copyOrigin.x + srcSpec.copyOrigin.y * copyLayout.texelBlocksPerRow);
PackTextureData(&textureArrayCopyData[expectedTexelArrayDataStartIndex], copySize.width, PackTextureData(&textureArrayCopyData[expectedTexelArrayDataStartIndex], copySize.width,
copySize.height, copyLayout.texelBlocksPerRow, expected.data(), copySize.height, copyLayout.texelBlocksPerRow, expected.data(),
copySize.width); copySize.width, options);
EXPECT_TEXTURE_RGBA8_EQ(expected.data(), dstTexture, dstSpec.copyOrigin.x, EXPECT_TEXTURE_RGBA8_EQ(expected.data(), dstTexture, dstSpec.copyOrigin.x,
dstSpec.copyOrigin.y, copySize.width, copySize.height, dstSpec.copyOrigin.y, copySize.width, copySize.height,
@ -160,7 +165,7 @@ TEST_P(CopyTextureForBrowserTests, PassthroughCopy) {
// Tests skip due to crbug.com/dawn/592. // Tests skip due to crbug.com/dawn/592.
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled()); DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
// OpenGL tests fails due to 'WriteTexture' unimplemented. // OpenGL tests fails because 'WriteTexture' is unimplemented.
// Related bug : crbug.com/dawn/483 // Related bug : crbug.com/dawn/483
DAWN_SKIP_TEST_IF(IsOpenGL()); DAWN_SKIP_TEST_IF(IsOpenGL());
DAWN_SKIP_TEST_IF(IsOpenGLES()); DAWN_SKIP_TEST_IF(IsOpenGLES());
@ -172,14 +177,16 @@ TEST_P(CopyTextureForBrowserTests, PassthroughCopy) {
textureSpec.copyOrigin = {0, 0, 0}; textureSpec.copyOrigin = {0, 0, 0};
textureSpec.level = 0; textureSpec.level = 0;
textureSpec.textureSize = {kWidth, kHeight, 1}; textureSpec.textureSize = {kWidth, kHeight, 1};
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
wgpu::CopyTextureForBrowserOptions options = {};
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1}, &options);
} }
TEST_P(CopyTextureForBrowserTests, VerifyCopyOnXDirection) { TEST_P(CopyTextureForBrowserTests, VerifyCopyOnXDirection) {
// Tests skip due to crbug.com/dawn/592. // Tests skip due to crbug.com/dawn/592.
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled()); DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
// OpenGL tests fails due to 'WriteTexture' unimplemented. // OpenGL tests fails because 'WriteTexture' is unimplemented.
// Related bug : crbug.com/dawn/483 // Related bug : crbug.com/dawn/483
DAWN_SKIP_TEST_IF(IsOpenGL()); DAWN_SKIP_TEST_IF(IsOpenGL());
DAWN_SKIP_TEST_IF(IsOpenGLES()); DAWN_SKIP_TEST_IF(IsOpenGLES());
@ -191,14 +198,16 @@ TEST_P(CopyTextureForBrowserTests, VerifyCopyOnXDirection) {
textureSpec.copyOrigin = {0, 0, 0}; textureSpec.copyOrigin = {0, 0, 0};
textureSpec.level = 0; textureSpec.level = 0;
textureSpec.textureSize = {kWidth, kHeight, 1}; textureSpec.textureSize = {kWidth, kHeight, 1};
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
wgpu::CopyTextureForBrowserOptions options = {};
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1}, &options);
} }
TEST_P(CopyTextureForBrowserTests, VerifyCopyOnYDirection) { TEST_P(CopyTextureForBrowserTests, VerifyCopyOnYDirection) {
// Tests skip due to crbug.com/dawn/592. // Tests skip due to crbug.com/dawn/592.
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled()); DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
// OpenGL tests fails due to 'WriteTexture' unimplemented. // OpenGL tests fails because 'WriteTexture' is unimplemented.
// Related bug : crbug.com/dawn/483 // Related bug : crbug.com/dawn/483
DAWN_SKIP_TEST_IF(IsOpenGL()); DAWN_SKIP_TEST_IF(IsOpenGL());
DAWN_SKIP_TEST_IF(IsOpenGLES()); DAWN_SKIP_TEST_IF(IsOpenGLES());
@ -210,14 +219,16 @@ TEST_P(CopyTextureForBrowserTests, VerifyCopyOnYDirection) {
textureSpec.copyOrigin = {0, 0, 0}; textureSpec.copyOrigin = {0, 0, 0};
textureSpec.level = 0; textureSpec.level = 0;
textureSpec.textureSize = {kWidth, kHeight, 1}; textureSpec.textureSize = {kWidth, kHeight, 1};
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
wgpu::CopyTextureForBrowserOptions options = {};
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1}, &options);
} }
TEST_P(CopyTextureForBrowserTests, VerifyCopyFromLargeTexture) { TEST_P(CopyTextureForBrowserTests, VerifyCopyFromLargeTexture) {
// Tests skip due to crbug.com/dawn/592. // Tests skip due to crbug.com/dawn/592.
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled()); DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
// OpenGL tests fails due to 'WriteTexture' unimplemented. // OpenGL tests fails because 'WriteTexture' is unimplemented.
// Related bug : crbug.com/dawn/483 // Related bug : crbug.com/dawn/483
DAWN_SKIP_TEST_IF(IsOpenGL()); DAWN_SKIP_TEST_IF(IsOpenGL());
DAWN_SKIP_TEST_IF(IsOpenGLES()); DAWN_SKIP_TEST_IF(IsOpenGLES());
@ -229,7 +240,51 @@ TEST_P(CopyTextureForBrowserTests, VerifyCopyFromLargeTexture) {
textureSpec.copyOrigin = {0, 0, 0}; textureSpec.copyOrigin = {0, 0, 0};
textureSpec.level = 0; textureSpec.level = 0;
textureSpec.textureSize = {kWidth, kHeight, 1}; textureSpec.textureSize = {kWidth, kHeight, 1};
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1});
wgpu::CopyTextureForBrowserOptions options = {};
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1}, &options);
}
TEST_P(CopyTextureForBrowserTests, VerifyFlipY) {
// Tests skip due to crbug.com/dawn/592.
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
// OpenGL tests fails because 'WriteTexture' is unimplemented.
// Related bug : crbug.com/dawn/483
DAWN_SKIP_TEST_IF(IsOpenGL());
constexpr uint32_t kWidth = 901;
constexpr uint32_t kHeight = 1001;
TextureSpec textureSpec;
textureSpec.copyOrigin = {0, 0, 0};
textureSpec.level = 0;
textureSpec.textureSize = {kWidth, kHeight, 1};
wgpu::CopyTextureForBrowserOptions options = {};
options.flipY = true;
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1}, &options);
}
TEST_P(CopyTextureForBrowserTests, VerifyFlipYInSlimTexture) {
// Tests skip due to crbug.com/dawn/592.
DAWN_SKIP_TEST_IF(IsD3D12() && IsBackendValidationEnabled());
// OpenGL tests fails because 'WriteTexture' is unimplemented.
// Related bug : crbug.com/dawn/483
DAWN_SKIP_TEST_IF(IsOpenGL());
constexpr uint32_t kWidth = 1;
constexpr uint32_t kHeight = 1001;
TextureSpec textureSpec;
textureSpec.copyOrigin = {0, 0, 0};
textureSpec.level = 0;
textureSpec.textureSize = {kWidth, kHeight, 1};
wgpu::CopyTextureForBrowserOptions options = {};
options.flipY = true;
DoTest(textureSpec, textureSpec, {kWidth, kHeight, 1}, &options);
} }
DAWN_INSTANTIATE_TEST(CopyTextureForBrowserTests, DAWN_INSTANTIATE_TEST(CopyTextureForBrowserTests,