Add internal usage for copyTextureForBrowser
Add an internal usage option for copyTextureForBrowserOption
allowing internal calls from call to use canvas context
texture as source/destination.
Bug: chromium:1331139
Change-Id: Ida8421b3962a6434e8ef57c581c7a2e1d607954c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/94985
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Shrek Shao <shrekshao@google.com>
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/dawn.json b/dawn.json
index ec3cb28..1fa746a 100644
--- a/dawn.json
+++ b/dawn.json
@@ -922,7 +922,8 @@
"length": 9, "optional": true},
{"name": "dst transfer function parameters", "type": "float", "annotation": "const*",
"length": 7, "optional": true},
- {"name": "dst alpha mode", "type": "alpha mode", "default": "unpremultiplied"}
+ {"name": "dst alpha mode", "type": "alpha mode", "default": "unpremultiplied"},
+ {"name": "internal usage", "type": "bool", "default": "false"}
]
},
"create compute pipeline async callback": {
diff --git a/src/dawn/native/BUILD.gn b/src/dawn/native/BUILD.gn
index 81110b5..e6cbc4d 100644
--- a/src/dawn/native/BUILD.gn
+++ b/src/dawn/native/BUILD.gn
@@ -330,6 +330,7 @@
"ToBackend.h",
"Toggles.cpp",
"Toggles.h",
+ "UsageValidationMode.h",
"VertexFormat.cpp",
"VertexFormat.h",
"dawn_platform.h",
diff --git a/src/dawn/native/BindGroup.cpp b/src/dawn/native/BindGroup.cpp
index 0d3af77..c5e0afc 100644
--- a/src/dawn/native/BindGroup.cpp
+++ b/src/dawn/native/BindGroup.cpp
@@ -20,12 +20,14 @@
#include "dawn/native/BindGroupLayout.h"
#include "dawn/native/Buffer.h"
#include "dawn/native/ChainUtils_autogen.h"
+#include "dawn/native/CommandValidation.h"
#include "dawn/native/Device.h"
#include "dawn/native/ExternalTexture.h"
#include "dawn/native/ObjectBase.h"
#include "dawn/native/ObjectType_autogen.h"
#include "dawn/native/Sampler.h"
#include "dawn/native/Texture.h"
+#include "dawn/native/utils/WGPUHelpers.h"
namespace dawn::native {
@@ -114,7 +116,8 @@
MaybeError ValidateTextureBinding(DeviceBase* device,
const BindGroupEntry& entry,
- const BindingInfo& bindingInfo) {
+ const BindingInfo& bindingInfo,
+ UsageValidationMode mode) {
DAWN_INVALID_IF(entry.textureView == nullptr, "Binding entry textureView not set.");
DAWN_INVALID_IF(entry.sampler != nullptr || entry.buffer != nullptr,
@@ -136,9 +139,7 @@
texture->GetFormat().GetAspectInfo(aspect).supportedSampleTypes;
SampleTypeBit requiredType = SampleTypeToSampleTypeBit(bindingInfo.texture.sampleType);
- DAWN_INVALID_IF(!(texture->GetUsage() & wgpu::TextureUsage::TextureBinding),
- "Usage (%s) of %s doesn't include TextureUsage::TextureBinding.",
- texture->GetUsage(), texture);
+ DAWN_TRY(ValidateCanUseAs(texture, wgpu::TextureUsage::TextureBinding, mode));
DAWN_INVALID_IF(texture->IsMultisampledTexture() != bindingInfo.texture.multisampled,
"Sample count (%u) of %s doesn't match expectation (multisampled: %d).",
@@ -157,9 +158,7 @@
break;
}
case BindingInfoType::StorageTexture: {
- DAWN_INVALID_IF(!(texture->GetUsage() & wgpu::TextureUsage::StorageBinding),
- "Usage (%s) of %s doesn't include TextureUsage::StorageBinding.",
- texture->GetUsage(), texture);
+ DAWN_TRY(ValidateCanUseAs(texture, wgpu::TextureUsage::StorageBinding, mode));
ASSERT(!texture->IsMultisampledTexture());
@@ -253,7 +252,9 @@
} // anonymous namespace
-MaybeError ValidateBindGroupDescriptor(DeviceBase* device, const BindGroupDescriptor* descriptor) {
+MaybeError ValidateBindGroupDescriptor(DeviceBase* device,
+ const BindGroupDescriptor* descriptor,
+ UsageValidationMode mode) {
DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr.");
DAWN_TRY(device->ValidateObject(descriptor->layout));
@@ -314,6 +315,7 @@
// Perform binding-type specific validation.
switch (bindingInfo.bindingType) {
case BindingInfoType::Buffer:
+ // TODO(dawn:1485): Validate buffer binding with usage validation mode.
DAWN_TRY_CONTEXT(ValidateBufferBinding(device, entry, bindingInfo),
"validating entries[%u] as a Buffer."
"\nExpected entry layout: %s",
@@ -321,7 +323,7 @@
break;
case BindingInfoType::Texture:
case BindingInfoType::StorageTexture:
- DAWN_TRY_CONTEXT(ValidateTextureBinding(device, entry, bindingInfo),
+ DAWN_TRY_CONTEXT(ValidateTextureBinding(device, entry, bindingInfo, mode),
"validating entries[%u] as a Texture."
"\nExpected entry layout: %s",
i, bindingInfo);
diff --git a/src/dawn/native/BindGroup.h b/src/dawn/native/BindGroup.h
index 236e4fb..34c122b 100644
--- a/src/dawn/native/BindGroup.h
+++ b/src/dawn/native/BindGroup.h
@@ -24,6 +24,7 @@
#include "dawn/native/Error.h"
#include "dawn/native/Forward.h"
#include "dawn/native/ObjectBase.h"
+#include "dawn/native/UsageValidationMode.h"
#include "dawn/native/dawn_platform.h"
@@ -31,7 +32,9 @@
class DeviceBase;
-MaybeError ValidateBindGroupDescriptor(DeviceBase* device, const BindGroupDescriptor* descriptor);
+MaybeError ValidateBindGroupDescriptor(DeviceBase* device,
+ const BindGroupDescriptor* descriptor,
+ UsageValidationMode mode);
struct BufferBinding {
BufferBase* buffer;
diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt
index 9eecfc5..9cf3b68 100644
--- a/src/dawn/native/CMakeLists.txt
+++ b/src/dawn/native/CMakeLists.txt
@@ -187,6 +187,7 @@
"ToBackend.h"
"Toggles.cpp"
"Toggles.h"
+ "UsageValidationMode.h"
"VertexFormat.cpp"
"VertexFormat.h"
"dawn_platform.h"
diff --git a/src/dawn/native/CommandValidation.cpp b/src/dawn/native/CommandValidation.cpp
index 723f658..d0bdb0c 100644
--- a/src/dawn/native/CommandValidation.cpp
+++ b/src/dawn/native/CommandValidation.cpp
@@ -471,7 +471,6 @@
texture->GetInternalUsage(), usage);
break;
}
-
return {};
}
diff --git a/src/dawn/native/CommandValidation.h b/src/dawn/native/CommandValidation.h
index ede6b31..bf4e8aa 100644
--- a/src/dawn/native/CommandValidation.h
+++ b/src/dawn/native/CommandValidation.h
@@ -20,6 +20,7 @@
#include "dawn/native/CommandAllocator.h"
#include "dawn/native/Error.h"
#include "dawn/native/Texture.h"
+#include "dawn/native/UsageValidationMode.h"
namespace dawn::native {
@@ -82,11 +83,6 @@
const ImageCopyTexture& dst,
const Extent3D& copySize);
-enum class UsageValidationMode {
- Default,
- Internal,
-};
-
MaybeError ValidateCanUseAs(const TextureBase* texture,
wgpu::TextureUsage usage,
UsageValidationMode mode);
diff --git a/src/dawn/native/ComputePassEncoder.cpp b/src/dawn/native/ComputePassEncoder.cpp
index a7f9ef5..30fa36b 100644
--- a/src/dawn/native/ComputePassEncoder.cpp
+++ b/src/dawn/native/ComputePassEncoder.cpp
@@ -306,7 +306,8 @@
{1, indirectBuffer, clientIndirectBindingOffset,
clientIndirectBindingSize},
{2, validatedIndirectBuffer, 0, scratchBufferSize},
- }));
+ },
+ UsageValidationMode::Internal));
// Issue commands to validate the indirect buffer.
APISetPipeline(validationPipeline.Get());
diff --git a/src/dawn/native/CopyTextureForBrowserHelper.cpp b/src/dawn/native/CopyTextureForBrowserHelper.cpp
index 48cf6e6..112eb0f 100644
--- a/src/dawn/native/CopyTextureForBrowserHelper.cpp
+++ b/src/dawn/native/CopyTextureForBrowserHelper.cpp
@@ -354,15 +354,15 @@
"not 1.",
source->texture->GetSampleCount(), destination->texture->GetSampleCount());
- DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc,
- UsageValidationMode::Default));
- DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::TextureBinding,
- UsageValidationMode::Default));
-
- DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst,
- UsageValidationMode::Default));
- DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::RenderAttachment,
- UsageValidationMode::Default));
+ DAWN_INVALID_IF(
+ options->internalUsage && !device->IsFeatureEnabled(Feature::DawnInternalUsages),
+ "The internalUsage is true while the dawn-internal-usages feature is not enabled.");
+ UsageValidationMode mode =
+ options->internalUsage ? UsageValidationMode::Internal : UsageValidationMode::Default;
+ DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc, mode));
+ DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::TextureBinding, mode));
+ DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst, mode));
+ DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::RenderAttachment, mode));
DAWN_TRY(ValidateCopyTextureFormatConversion(source->texture->GetFormat().format,
destination->texture->GetFormat().format));
@@ -546,14 +546,22 @@
device->CreateTextureView(source->texture, &srcTextureViewDesc));
// Create bind group after all binding entries are set.
+ UsageValidationMode mode =
+ options->internalUsage ? UsageValidationMode::Internal : UsageValidationMode::Default;
Ref<BindGroupBase> bindGroup;
- DAWN_TRY_ASSIGN(bindGroup,
- utils::MakeBindGroup(device, layout,
- {{0, uniformBuffer}, {1, sampler}, {2, srcTextureView}}));
+ DAWN_TRY_ASSIGN(bindGroup, utils::MakeBindGroup(
+ device, layout,
+ {{0, uniformBuffer}, {1, sampler}, {2, srcTextureView}}, mode));
// Create command encoder.
+ CommandEncoderDescriptor commandEncoderDesc;
+ DawnEncoderInternalUsageDescriptor internalUsageDesc;
+ if (options->internalUsage) {
+ internalUsageDesc.useInternalUsages = true;
+ commandEncoderDesc.nextInChain = &internalUsageDesc;
+ }
Ref<CommandEncoder> encoder;
- DAWN_TRY_ASSIGN(encoder, device->CreateCommandEncoder());
+ DAWN_TRY_ASSIGN(encoder, device->CreateCommandEncoder(&commandEncoderDesc));
// Prepare dst texture view as color Attachment.
TextureViewDescriptor dstTextureViewDesc;
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index 82fb66c..e15bee0 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -1407,12 +1407,12 @@
// Implementation details of object creation
-ResultOrError<Ref<BindGroupBase>> DeviceBase::CreateBindGroup(
- const BindGroupDescriptor* descriptor) {
+ResultOrError<Ref<BindGroupBase>> DeviceBase::CreateBindGroup(const BindGroupDescriptor* descriptor,
+ UsageValidationMode mode) {
DAWN_TRY(ValidateIsAlive());
if (IsValidationEnabled()) {
- DAWN_TRY_CONTEXT(ValidateBindGroupDescriptor(this, descriptor), "validating %s against %s",
- descriptor, descriptor->layout);
+ DAWN_TRY_CONTEXT(ValidateBindGroupDescriptor(this, descriptor, mode),
+ "validating %s against %s", descriptor, descriptor->layout);
}
return CreateBindGroupImpl(descriptor);
}
diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h
index e9fab16..10f9087 100644
--- a/src/dawn/native/Device.h
+++ b/src/dawn/native/Device.h
@@ -35,6 +35,7 @@
#include "dawn/native/RefCountedWithExternalCount.h"
#include "dawn/native/StagingBuffer.h"
#include "dawn/native/Toggles.h"
+#include "dawn/native/UsageValidationMode.h"
#include "dawn/native/DawnNative.h"
#include "dawn/native/dawn_platform.h"
@@ -203,7 +204,9 @@
Ref<PipelineCacheBase> GetOrCreatePipelineCache(const CacheKey& key);
// Object creation methods that be used in a reentrant manner.
- ResultOrError<Ref<BindGroupBase>> CreateBindGroup(const BindGroupDescriptor* descriptor);
+ ResultOrError<Ref<BindGroupBase>> CreateBindGroup(
+ const BindGroupDescriptor* descriptor,
+ UsageValidationMode mode = UsageValidationMode::Default);
ResultOrError<Ref<BindGroupLayoutBase>> CreateBindGroupLayout(
const BindGroupLayoutDescriptor* descriptor,
bool allowInternalBinding = false);
diff --git a/src/dawn/native/QueryHelper.cpp b/src/dawn/native/QueryHelper.cpp
index 7832cb3..d8f6481 100644
--- a/src/dawn/native/QueryHelper.cpp
+++ b/src/dawn/native/QueryHelper.cpp
@@ -199,7 +199,8 @@
Ref<BindGroupBase> bindGroup;
DAWN_TRY_ASSIGN(
bindGroup,
- utils::MakeBindGroup(device, layout, {{0, timestamps}, {1, availability}, {2, params}}));
+ utils::MakeBindGroup(device, layout, {{0, timestamps}, {1, availability}, {2, params}},
+ UsageValidationMode::Internal));
// Create compute encoder and issue dispatch.
Ref<ComputePassEncoder> pass = encoder->BeginComputePass();
diff --git a/src/dawn/native/Texture.cpp b/src/dawn/native/Texture.cpp
index 7b1526a..3580ca7 100644
--- a/src/dawn/native/Texture.cpp
+++ b/src/dawn/native/Texture.cpp
@@ -340,7 +340,7 @@
DAWN_INVALID_IF(
internalUsageDesc != nullptr && !device->IsFeatureEnabled(Feature::DawnInternalUsages),
- "The dawn-internal-usages feature is not enabled");
+ "The internalUsageDesc is not empty while the dawn-internal-usages feature is not enabled");
const Format* format;
DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format));
diff --git a/src/dawn/native/UsageValidationMode.h b/src/dawn/native/UsageValidationMode.h
new file mode 100644
index 0000000..2228bb4
--- /dev/null
+++ b/src/dawn/native/UsageValidationMode.h
@@ -0,0 +1,27 @@
+// Copyright 2022 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.
+
+#ifndef SRC_DAWN_NATIVE_USAGEVALIDATIONMODE_H_
+#define SRC_DAWN_NATIVE_USAGEVALIDATIONMODE_H_
+
+namespace dawn::native {
+
+enum class UsageValidationMode {
+ Default,
+ Internal,
+};
+
+} // namespace dawn::native
+
+#endif // SRC_DAWN_NATIVE_USAGEVALIDATIONMODE_H_
diff --git a/src/dawn/native/utils/WGPUHelpers.cpp b/src/dawn/native/utils/WGPUHelpers.cpp
index 722476e..2a7a5e0 100644
--- a/src/dawn/native/utils/WGPUHelpers.cpp
+++ b/src/dawn/native/utils/WGPUHelpers.cpp
@@ -165,7 +165,8 @@
ResultOrError<Ref<BindGroupBase>> MakeBindGroup(
DeviceBase* device,
const Ref<BindGroupLayoutBase>& layout,
- std::initializer_list<BindingInitializationHelper> entriesInitializer) {
+ std::initializer_list<BindingInitializationHelper> entriesInitializer,
+ UsageValidationMode mode) {
std::vector<BindGroupEntry> entries;
for (const BindingInitializationHelper& helper : entriesInitializer) {
entries.push_back(helper.GetAsBinding());
@@ -176,7 +177,7 @@
descriptor.entryCount = entries.size();
descriptor.entries = entries.data();
- return device->CreateBindGroup(&descriptor);
+ return device->CreateBindGroup(&descriptor, mode);
}
const char* GetLabelForTrace(const char* label) {
diff --git a/src/dawn/native/utils/WGPUHelpers.h b/src/dawn/native/utils/WGPUHelpers.h
index 9eab990..45cfa46 100644
--- a/src/dawn/native/utils/WGPUHelpers.h
+++ b/src/dawn/native/utils/WGPUHelpers.h
@@ -21,6 +21,7 @@
#include "dawn/common/RefCounted.h"
#include "dawn/native/Error.h"
+#include "dawn/native/UsageValidationMode.h"
#include "dawn/native/dawn_platform.h"
namespace dawn::native::utils {
@@ -110,10 +111,12 @@
uint64_t size = 0;
};
+// This helper is only used inside dawn native.
ResultOrError<Ref<BindGroupBase>> MakeBindGroup(
DeviceBase* device,
const Ref<BindGroupLayoutBase>& layout,
- std::initializer_list<BindingInitializationHelper> entriesInitializer);
+ std::initializer_list<BindingInitializationHelper> entriesInitializer,
+ UsageValidationMode mode);
const char* GetLabelForTrace(const char* label);
diff --git a/src/dawn/tests/unittests/validation/CopyTextureForBrowserTests.cpp b/src/dawn/tests/unittests/validation/CopyTextureForBrowserTests.cpp
index 5a4e1ec..06c1b3d 100644
--- a/src/dawn/tests/unittests/validation/CopyTextureForBrowserTests.cpp
+++ b/src/dawn/tests/unittests/validation/CopyTextureForBrowserTests.cpp
@@ -22,14 +22,17 @@
class CopyTextureForBrowserTest : public ValidationTest {
protected:
- wgpu::Texture Create2DTexture(uint32_t width,
- uint32_t height,
- uint32_t mipLevelCount,
- uint32_t arrayLayerCount,
- wgpu::TextureFormat format,
- wgpu::TextureUsage usage,
- uint32_t sampleCount = 1) {
+ wgpu::Texture Create2DTexture(
+ uint32_t width,
+ uint32_t height,
+ uint32_t mipLevelCount,
+ uint32_t arrayLayerCount,
+ wgpu::TextureFormat format,
+ wgpu::TextureUsage usage,
+ uint32_t sampleCount = 1,
+ const wgpu::DawnTextureInternalUsageDescriptor* internalDesc = nullptr) {
wgpu::TextureDescriptor descriptor;
+ descriptor.nextInChain = internalDesc;
descriptor.dimension = wgpu::TextureDimension::e2D;
descriptor.size.width = width;
descriptor.size.height = height;
@@ -67,6 +70,17 @@
}
};
+class CopyTextureForBrowserInternalUsageTest : public CopyTextureForBrowserTest {
+ protected:
+ WGPUDevice CreateTestDevice(dawn::native::Adapter dawnAdapter) override {
+ wgpu::DeviceDescriptor descriptor;
+ wgpu::FeatureName feature = wgpu::FeatureName::DawnInternalUsages;
+ descriptor.requiredFeatures = &feature;
+ descriptor.requiredFeaturesCount = 1;
+ return dawnAdapter.CreateDevice(&descriptor);
+ }
+};
+
// Tests should be Success
TEST_F(CopyTextureForBrowserTest, Success) {
wgpu::Texture source =
@@ -434,3 +448,54 @@
{0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, options);
}
}
+
+// Test that the internal usage can only be set to true when the device internal usage feature is
+// enabled
+TEST_F(CopyTextureForBrowserTest, InternalUsage) {
+ wgpu::DawnTextureInternalUsageDescriptor internalDesc = {};
+ internalDesc.internalUsage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding;
+
+ // Validation should fail because internal descriptor is not empty.
+ ASSERT_DEVICE_ERROR(Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopySrc, 1, &internalDesc));
+
+ wgpu::Texture source =
+ Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
+
+ wgpu::Texture destination =
+ Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
+
+ // Validation should fail because of device internal usage feature is missing when internal
+ // usage option is on
+ wgpu::CopyTextureForBrowserOptions options = {};
+ options.internalUsage = true;
+ TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
+ {0, 0, 0}, {16, 16, 1}, wgpu::TextureAspect::All, options);
+}
+
+// Test that the internal usages are taken into account when interalUsage = true
+TEST_F(CopyTextureForBrowserInternalUsageTest, InternalUsage) {
+ wgpu::DawnTextureInternalUsageDescriptor internalDesc1 = {};
+ internalDesc1.internalUsage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding;
+
+ wgpu::Texture source = Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopySrc, 1, &internalDesc1);
+
+ wgpu::DawnTextureInternalUsageDescriptor internalDesc2 = {};
+ internalDesc2.internalUsage =
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment;
+ wgpu::Texture destination = Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst, 1, &internalDesc2);
+
+ // Without internal usage option should fail usage validation
+ TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
+ {0, 0, 0}, {16, 16, 1});
+
+ // With internal usage option should pass usage validation
+ wgpu::CopyTextureForBrowserOptions options = {};
+ options.internalUsage = true;
+ TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
+ {0, 0, 0}, {16, 16, 1}, wgpu::TextureAspect::All, options);
+}