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>
This commit is contained in:
shrekshao 2022-07-11 18:11:14 +00:00 committed by Shrek Shao
parent e629aee91a
commit c6cbcdb05b
17 changed files with 160 additions and 48 deletions

View File

@ -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": {

View File

@ -330,6 +330,7 @@ source_set("sources") {
"ToBackend.h",
"Toggles.cpp",
"Toggles.h",
"UsageValidationMode.h",
"VertexFormat.cpp",
"VertexFormat.h",
"dawn_platform.h",

View File

@ -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 ValidateBufferBinding(const DeviceBase* device,
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 @@ MaybeError ValidateTextureBinding(DeviceBase* device,
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 @@ MaybeError ValidateTextureBinding(DeviceBase* device,
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 @@ MaybeError ValidateExternalTextureBinding(
} // 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 @@ MaybeError ValidateBindGroupDescriptor(DeviceBase* device, const BindGroupDescri
// 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 @@ MaybeError ValidateBindGroupDescriptor(DeviceBase* device, const BindGroupDescri
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);

View File

@ -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 @@ namespace dawn::native {
class DeviceBase;
MaybeError ValidateBindGroupDescriptor(DeviceBase* device, const BindGroupDescriptor* descriptor);
MaybeError ValidateBindGroupDescriptor(DeviceBase* device,
const BindGroupDescriptor* descriptor,
UsageValidationMode mode);
struct BufferBinding {
BufferBase* buffer;

View File

@ -187,6 +187,7 @@ target_sources(dawn_native PRIVATE
"ToBackend.h"
"Toggles.cpp"
"Toggles.h"
"UsageValidationMode.h"
"VertexFormat.cpp"
"VertexFormat.h"
"dawn_platform.h"

View File

@ -471,7 +471,6 @@ MaybeError ValidateCanUseAs(const TextureBase* texture,
texture->GetInternalUsage(), usage);
break;
}
return {};
}

View File

@ -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 @@ MaybeError ValidateTextureToTextureCopyRestrictions(const ImageCopyTexture& src,
const ImageCopyTexture& dst,
const Extent3D& copySize);
enum class UsageValidationMode {
Default,
Internal,
};
MaybeError ValidateCanUseAs(const TextureBase* texture,
wgpu::TextureUsage usage,
UsageValidationMode mode);

View File

@ -306,7 +306,8 @@ ComputePassEncoder::TransformIndirectDispatchBuffer(Ref<BufferBase> indirectBuff
{1, indirectBuffer, clientIndirectBindingOffset,
clientIndirectBindingSize},
{2, validatedIndirectBuffer, 0, scratchBufferSize},
}));
},
UsageValidationMode::Internal));
// Issue commands to validate the indirect buffer.
APISetPipeline(validationPipeline.Get());

View File

@ -354,15 +354,15 @@ MaybeError ValidateCopyTextureForBrowser(DeviceBase* device,
"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 @@ MaybeError DoCopyTextureForBrowser(DeviceBase* device,
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;

View File

@ -1407,12 +1407,12 @@ QueueBase* DeviceBase::GetQueue() const {
// 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);
}

View File

@ -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 @@ class DeviceBase : public RefCountedWithExternalCount {
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);

View File

@ -199,7 +199,8 @@ MaybeError EncodeConvertTimestampsToNanoseconds(CommandEncoder* encoder,
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();

View File

@ -340,7 +340,7 @@ MaybeError ValidateTextureDescriptor(const DeviceBase* device,
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));

View File

@ -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_

View File

@ -165,7 +165,8 @@ BindGroupEntry BindingInitializationHelper::GetAsBinding() const {
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 @@ ResultOrError<Ref<BindGroupBase>> MakeBindGroup(
descriptor.entryCount = entries.size();
descriptor.entries = entries.data();
return device->CreateBindGroup(&descriptor);
return device->CreateBindGroup(&descriptor, mode);
}
const char* GetLabelForTrace(const char* label) {

View File

@ -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 @@ struct BindingInitializationHelper {
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);

View File

@ -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 CopyTextureForBrowserTest : public ValidationTest {
}
};
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 @@ TEST_F(CopyTextureForBrowserTest, ColorSpaceConversion_TextureAlphaState) {
{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);
}