Add WGPUDawnEncoderInternalUsageDescriptor
This descriptor, when chained on WGPUCommandEncoderDescriptor makes
internal usages visible to validation.
This CL is to help implement WebGPU Swiftshader support in Chrome.
Bug: chromium:1266550
Change-Id: I7253fe45003e9ad5ac4d8ddd2d4782989e9b5c27
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/76440
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/dawn.json b/dawn.json
index e7e5b61..40c8cf7 100644
--- a/dawn.json
+++ b/dawn.json
@@ -2369,7 +2369,8 @@
{"value": 11, "name": "surface descriptor from windows swap chain panel", "tags": ["dawn"]},
{"value": 1000, "name": "dawn texture internal usage descriptor", "tags": ["dawn"]},
{"value": 1001, "name": "primitive depth clamping state", "tags": ["dawn", "emscripten"]},
- {"value": 1002, "name": "dawn toggles device descriptor", "tags": ["dawn", "native"]}
+ {"value": 1002, "name": "dawn toggles device descriptor", "tags": ["dawn", "native"]},
+ {"value": 1003, "name": "dawn encoder internal usage descriptor", "tags": ["dawn"]}
]
},
"texture": {
@@ -2733,5 +2734,13 @@
"members": [
{"name": "internal usage", "type": "texture usage", "default": "none"}
]
+ },
+ "dawn encoder internal usage descriptor": {
+ "category": "structure",
+ "chained": "in",
+ "tags": ["dawn"],
+ "members": [
+ {"name": "use internal usages", "type": "bool", "default": "false"}
+ ]
}
}
diff --git a/docs/features/dawn_internal_usages.md b/docs/features/dawn_internal_usages.md
index ec06637..521a3ac 100644
--- a/docs/features/dawn_internal_usages.md
+++ b/docs/features/dawn_internal_usages.md
@@ -1,12 +1,11 @@
# Dawn Internal Usages
-The `dawn-internal-usages` feature allows adding additional usage which affects how a texture is allocated, but does not affect frontend validation.
+The `dawn-internal-usages` feature allows adding additional usage which affects how a texture is allocated, but does not affect normal frontend validation.
-One use case for this is so that Chromium can use an internal copyTextureToTexture command to implement copies from a WebGPU texture-backed canvas to other Web platform primitives when the swapchain texture was not explicitly created with CopySrc usage in Javascript.
+Adds `WGPUDawnTextureInternalUsageDescriptor` for specifying additional internal usages to create a texture with.
+Example Usage:
```
-Usage:
-
wgpu::DawnTextureInternalUsageDescriptor internalDesc = {};
internalDesc.internalUsage = wgpu::TextureUsage::CopySrc;
@@ -14,5 +13,26 @@
// set properties of desc.
desc.nextInChain = &internalDesc;
-device.createTexture(&desc);
+device.CreateTexture(&desc);
```
+
+Adds `WGPUDawnEncoderInternalUsageDescriptor` which may be chained on `WGPUCommandEncoderDescriptor`. Setting `WGPUDawnEncoderInternalUsageDescriptor::useInternalUsages` to `true` means that internal resource usages will be visible during validation. ex.) A texture that has `WGPUTextureUsage_CopySrc` in `WGPUDawnEncoderInternalUsageDescriptor::internalUsage`, but not in `WGPUTextureDescriptor::usage` may be used as the source of a copy command.
+
+
+Example Usage:
+```
+wgpu::DawnEncoderInternalUsageDescriptor internalEncoderDesc = { true };
+wgpu::CommandEncoderDescriptor encoderDesc = {};
+encoderDesc.nextInChain = &internalEncoderDesc;
+
+wgpu::CommandEncoder encoder = device.CreateCommandEncoder(&encoderDesc);
+
+// This will be valid
+wgpu::ImageCopyTexture src = {};
+src.texture = texture;
+encoder.CopyTextureToBuffer(&src, ...);
+```
+
+One use case for this is so that Chromium can use an internal copyTextureToTexture command to implement copies from a WebGPU texture-backed canvas to other Web platform primitives when the swapchain texture was not explicitly created with CopySrc usage in Javascript.
+
+Note: copyTextureToTextureInternal will be removed in favor of `WGPUDawnEncoderInternalUsageDescriptor`.
diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp
index d781962..0001555 100644
--- a/src/dawn_native/CommandEncoder.cpp
+++ b/src/dawn_native/CommandEncoder.cpp
@@ -18,6 +18,7 @@
#include "common/Math.h"
#include "dawn_native/BindGroup.h"
#include "dawn_native/Buffer.h"
+#include "dawn_native/ChainUtils_autogen.h"
#include "dawn_native/CommandBuffer.h"
#include "dawn_native/CommandBufferStateTracker.h"
#include "dawn_native/CommandValidation.h"
@@ -159,7 +160,8 @@
}
MaybeError ValidateResolveTarget(const DeviceBase* device,
- const RenderPassColorAttachment& colorAttachment) {
+ const RenderPassColorAttachment& colorAttachment,
+ UsageValidationMode usageValidationMode) {
if (colorAttachment.resolveTarget == nullptr) {
return {};
}
@@ -168,7 +170,7 @@
const TextureViewBase* attachment = colorAttachment.view;
DAWN_TRY(device->ValidateObject(colorAttachment.resolveTarget));
DAWN_TRY(ValidateCanUseAs(colorAttachment.resolveTarget->GetTexture(),
- wgpu::TextureUsage::RenderAttachment));
+ wgpu::TextureUsage::RenderAttachment, usageValidationMode));
DAWN_INVALID_IF(
!attachment->GetTexture()->IsMultisampledTexture(),
@@ -216,11 +218,12 @@
const RenderPassColorAttachment& colorAttachment,
uint32_t* width,
uint32_t* height,
- uint32_t* sampleCount) {
+ uint32_t* sampleCount,
+ UsageValidationMode usageValidationMode) {
TextureViewBase* attachment = colorAttachment.view;
DAWN_TRY(device->ValidateObject(attachment));
- DAWN_TRY(
- ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment));
+ DAWN_TRY(ValidateCanUseAs(attachment->GetTexture(),
+ wgpu::TextureUsage::RenderAttachment, usageValidationMode));
DAWN_INVALID_IF(!(attachment->GetAspects() & Aspect::Color) ||
!attachment->GetFormat().isRenderable,
@@ -241,7 +244,7 @@
DAWN_TRY(ValidateOrSetColorAttachmentSampleCount(attachment, sampleCount));
- DAWN_TRY(ValidateResolveTarget(device, colorAttachment));
+ DAWN_TRY(ValidateResolveTarget(device, colorAttachment, usageValidationMode));
DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment));
DAWN_TRY(ValidateOrSetAttachmentSize(attachment, width, height));
@@ -254,13 +257,14 @@
const RenderPassDepthStencilAttachment* depthStencilAttachment,
uint32_t* width,
uint32_t* height,
- uint32_t* sampleCount) {
+ uint32_t* sampleCount,
+ UsageValidationMode usageValidationMode) {
DAWN_ASSERT(depthStencilAttachment != nullptr);
TextureViewBase* attachment = depthStencilAttachment->view;
DAWN_TRY(device->ValidateObject(attachment));
- DAWN_TRY(
- ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment));
+ DAWN_TRY(ValidateCanUseAs(attachment->GetTexture(),
+ wgpu::TextureUsage::RenderAttachment, usageValidationMode));
const Format& format = attachment->GetFormat();
DAWN_INVALID_IF(
@@ -333,24 +337,25 @@
const RenderPassDescriptor* descriptor,
uint32_t* width,
uint32_t* height,
- uint32_t* sampleCount) {
+ uint32_t* sampleCount,
+ UsageValidationMode usageValidationMode) {
DAWN_INVALID_IF(
descriptor->colorAttachmentCount > kMaxColorAttachments,
"Color attachment count (%u) exceeds the maximum number of color attachments (%u).",
descriptor->colorAttachmentCount, kMaxColorAttachments);
for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) {
- DAWN_TRY_CONTEXT(
- ValidateRenderPassColorAttachment(device, descriptor->colorAttachments[i],
- width, height, sampleCount),
- "validating colorAttachments[%u].", i);
+ DAWN_TRY_CONTEXT(ValidateRenderPassColorAttachment(
+ device, descriptor->colorAttachments[i], width, height,
+ sampleCount, usageValidationMode),
+ "validating colorAttachments[%u].", i);
}
if (descriptor->depthStencilAttachment != nullptr) {
- DAWN_TRY_CONTEXT(
- ValidateRenderPassDepthStencilAttachment(
- device, descriptor->depthStencilAttachment, width, height, sampleCount),
- "validating depthStencilAttachment.");
+ DAWN_TRY_CONTEXT(ValidateRenderPassDepthStencilAttachment(
+ device, descriptor->depthStencilAttachment, width, height,
+ sampleCount, usageValidationMode),
+ "validating depthStencilAttachment.");
}
if (descriptor->occlusionQuerySet != nullptr) {
@@ -468,9 +473,50 @@
} // namespace
+ MaybeError ValidateCommandEncoderDescriptor(const DeviceBase* device,
+ const CommandEncoderDescriptor* descriptor) {
+ DAWN_TRY(ValidateSingleSType(descriptor->nextInChain,
+ wgpu::SType::DawnEncoderInternalUsageDescriptor));
+
+ const DawnEncoderInternalUsageDescriptor* internalUsageDesc = nullptr;
+ FindInChain(descriptor->nextInChain, &internalUsageDesc);
+
+ DAWN_INVALID_IF(internalUsageDesc != nullptr &&
+ !device->APIHasFeature(wgpu::FeatureName::DawnInternalUsages),
+ "%s is not available.", wgpu::FeatureName::DawnInternalUsages);
+ return {};
+ }
+
+ // static
+ Ref<CommandEncoder> CommandEncoder::Create(DeviceBase* device,
+ const CommandEncoderDescriptor* descriptor) {
+ return AcquireRef(new CommandEncoder(device, descriptor));
+ }
+
+ // static
+ CommandEncoder* CommandEncoder::MakeError(DeviceBase* device) {
+ return new CommandEncoder(device, ObjectBase::kError);
+ }
+
CommandEncoder::CommandEncoder(DeviceBase* device, const CommandEncoderDescriptor* descriptor)
: ApiObjectBase(device, descriptor->label), mEncodingContext(device, this) {
TrackInDevice();
+
+ const DawnEncoderInternalUsageDescriptor* internalUsageDesc = nullptr;
+ FindInChain(descriptor->nextInChain, &internalUsageDesc);
+
+ if (internalUsageDesc != nullptr && internalUsageDesc->useInternalUsages) {
+ mUsageValidationMode = UsageValidationMode::Internal;
+ } else {
+ mUsageValidationMode = UsageValidationMode::Default;
+ }
+ }
+
+ CommandEncoder::CommandEncoder(DeviceBase* device, ObjectBase::ErrorTag tag)
+ : ApiObjectBase(device, tag),
+ mEncodingContext(device, this),
+ mUsageValidationMode(UsageValidationMode::Default) {
+ mEncodingContext.HandleError(DAWN_FORMAT_VALIDATION_ERROR("%s is invalid.", this));
}
ObjectType CommandEncoder::GetType() const {
@@ -554,7 +600,7 @@
uint32_t sampleCount = 0;
DAWN_TRY(ValidateRenderPassDescriptor(device, descriptor, &width, &height,
- &sampleCount));
+ &sampleCount, mUsageValidationMode));
ASSERT(width > 0 && height > 0 && sampleCount > 0);
@@ -703,7 +749,8 @@
DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize));
DAWN_TRY_CONTEXT(
- ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst),
+ ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst,
+ mUsageValidationMode),
"validating destination %s usage.", destination->texture);
DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(destination->texture));
@@ -757,7 +804,8 @@
[&](CommandAllocator* allocator) -> MaybeError {
if (GetDevice()->IsValidationEnabled()) {
DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *source, *copySize));
- DAWN_TRY_CONTEXT(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc),
+ DAWN_TRY_CONTEXT(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc,
+ mUsageValidationMode),
"validating source %s usage.", source->texture);
DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(source->texture));
DAWN_TRY(ValidateTextureDepthStencilToBufferCopyRestrictions(*source));
@@ -846,14 +894,15 @@
// For internal usages (CopyToCopyInternal) we don't care if the user has added
// CopySrc as a usage for this texture, but we will always add it internally.
if (Internal) {
- DAWN_TRY(
- ValidateInternalCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
- DAWN_TRY(ValidateInternalCanUseAs(destination->texture,
- wgpu::TextureUsage::CopyDst));
+ DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc,
+ UsageValidationMode::Internal));
+ DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst,
+ UsageValidationMode::Internal));
} else {
- DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
- DAWN_TRY(
- ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst));
+ DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc,
+ mUsageValidationMode));
+ DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst,
+ mUsageValidationMode));
}
mTopLevelTextures.insert(source->texture);
diff --git a/src/dawn_native/CommandEncoder.h b/src/dawn_native/CommandEncoder.h
index e773ed2..14f81ed 100644
--- a/src/dawn_native/CommandEncoder.h
+++ b/src/dawn_native/CommandEncoder.h
@@ -26,9 +26,16 @@
namespace dawn::native {
+ enum class UsageValidationMode;
+
+ MaybeError ValidateCommandEncoderDescriptor(const DeviceBase* device,
+ const CommandEncoderDescriptor* descriptor);
+
class CommandEncoder final : public ApiObjectBase {
public:
- CommandEncoder(DeviceBase* device, const CommandEncoderDescriptor* descriptor);
+ static Ref<CommandEncoder> Create(DeviceBase* device,
+ const CommandEncoderDescriptor* descriptor);
+ static CommandEncoder* MakeError(DeviceBase* device);
ObjectType GetType() const override;
@@ -80,6 +87,9 @@
CommandBufferBase* APIFinish(const CommandBufferDescriptor* descriptor = nullptr);
private:
+ CommandEncoder(DeviceBase* device, const CommandEncoderDescriptor* descriptor);
+ CommandEncoder(DeviceBase* device, ObjectBase::ErrorTag tag);
+
void DestroyImpl() override;
ResultOrError<Ref<CommandBufferBase>> FinishInternal(
const CommandBufferDescriptor* descriptor);
@@ -100,6 +110,8 @@
std::set<QuerySetBase*> mUsedQuerySets;
uint64_t mDebugGroupStackSize = 0;
+
+ UsageValidationMode mUsageValidationMode;
};
} // namespace dawn::native
diff --git a/src/dawn_native/CommandValidation.cpp b/src/dawn_native/CommandValidation.cpp
index 1e307e5..d3474f4 100644
--- a/src/dawn_native/CommandValidation.cpp
+++ b/src/dawn_native/CommandValidation.cpp
@@ -447,19 +447,21 @@
return ValidateTextureToTextureCopyCommonRestrictions(src, dst, copySize);
}
- MaybeError ValidateCanUseAs(const TextureBase* texture, wgpu::TextureUsage usage) {
+ MaybeError ValidateCanUseAs(const TextureBase* texture,
+ wgpu::TextureUsage usage,
+ UsageValidationMode mode) {
ASSERT(wgpu::HasZeroOrOneBits(usage));
- DAWN_INVALID_IF(!(texture->GetUsage() & usage), "%s usage (%s) doesn't include %s.",
- texture, texture->GetUsage(), usage);
-
- return {};
- }
-
- MaybeError ValidateInternalCanUseAs(const TextureBase* texture, wgpu::TextureUsage usage) {
- ASSERT(wgpu::HasZeroOrOneBits(usage));
- DAWN_INVALID_IF(!(texture->GetInternalUsage() & usage),
- "%s internal usage (%s) doesn't include %s.", texture,
- texture->GetInternalUsage(), usage);
+ switch (mode) {
+ case UsageValidationMode::Default:
+ DAWN_INVALID_IF(!(texture->GetUsage() & usage), "%s usage (%s) doesn't include %s.",
+ texture, texture->GetUsage(), usage);
+ break;
+ case UsageValidationMode::Internal:
+ DAWN_INVALID_IF(!(texture->GetInternalUsage() & usage),
+ "%s internal usage (%s) doesn't include %s.", texture,
+ texture->GetInternalUsage(), usage);
+ break;
+ }
return {};
}
@@ -468,7 +470,6 @@
ASSERT(wgpu::HasZeroOrOneBits(usage));
DAWN_INVALID_IF(!(buffer->GetUsage() & usage), "%s usage (%s) doesn't include %s.", buffer,
buffer->GetUsage(), usage);
-
return {};
}
diff --git a/src/dawn_native/CommandValidation.h b/src/dawn_native/CommandValidation.h
index 92b61e6..b17a003 100644
--- a/src/dawn_native/CommandValidation.h
+++ b/src/dawn_native/CommandValidation.h
@@ -73,10 +73,14 @@
const ImageCopyTexture& dst,
const Extent3D& copySize);
- MaybeError ValidateCanUseAs(const TextureBase* texture, wgpu::TextureUsage usage);
+ enum class UsageValidationMode {
+ Default,
+ Internal,
+ };
- MaybeError ValidateInternalCanUseAs(const TextureBase* texture, wgpu::TextureUsage usage);
-
+ MaybeError ValidateCanUseAs(const TextureBase* texture,
+ wgpu::TextureUsage usage,
+ UsageValidationMode mode);
MaybeError ValidateCanUseAs(const BufferBase* buffer, wgpu::BufferUsage usage);
} // namespace dawn::native
diff --git a/src/dawn_native/CopyTextureForBrowserHelper.cpp b/src/dawn_native/CopyTextureForBrowserHelper.cpp
index 6cfd74c..2ccaf66 100644
--- a/src/dawn_native/CopyTextureForBrowserHelper.cpp
+++ b/src/dawn_native/CopyTextureForBrowserHelper.cpp
@@ -350,11 +350,15 @@
"not 1.",
source->texture->GetSampleCount(), destination->texture->GetSampleCount());
- DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
- DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::TextureBinding));
+ 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));
- DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::RenderAttachment));
+ DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst,
+ UsageValidationMode::Default));
+ DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::RenderAttachment,
+ UsageValidationMode::Default));
DAWN_TRY(ValidateCopyTextureFormatConversion(source->texture->GetFormat().format,
destination->texture->GetFormat().format));
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index 1775574..cdd7197 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -953,7 +953,13 @@
if (descriptor == nullptr) {
descriptor = &defaultDescriptor;
}
- return new CommandEncoder(this, descriptor);
+
+ Ref<CommandEncoder> result;
+ if (ConsumedError(CreateCommandEncoder(descriptor), &result,
+ "calling %s.CreateCommandEncoder(%s).", this, descriptor)) {
+ return CommandEncoder::MakeError(this);
+ }
+ return result.Detach();
}
ComputePipelineBase* DeviceBase::APICreateComputePipeline(
const ComputePipelineDescriptor* descriptor) {
@@ -1313,6 +1319,15 @@
return AddOrGetCachedComputePipeline(std::move(uninitializedComputePipeline));
}
+ ResultOrError<Ref<CommandEncoder>> DeviceBase::CreateCommandEncoder(
+ const CommandEncoderDescriptor* descriptor) {
+ DAWN_TRY(ValidateIsAlive());
+ if (IsValidationEnabled()) {
+ DAWN_TRY(ValidateCommandEncoderDescriptor(this, descriptor));
+ }
+ return CommandEncoder::Create(this, descriptor);
+ }
+
MaybeError DeviceBase::CreateComputePipelineAsync(
const ComputePipelineDescriptor* descriptor,
WGPUCreateComputePipelineAsyncCallback callback,
diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h
index 89ddcf5..75e293f 100644
--- a/src/dawn_native/Device.h
+++ b/src/dawn_native/Device.h
@@ -198,6 +198,8 @@
const BindGroupLayoutDescriptor* descriptor,
bool allowInternalBinding = false);
ResultOrError<Ref<BufferBase>> CreateBuffer(const BufferDescriptor* descriptor);
+ ResultOrError<Ref<CommandEncoder>> CreateCommandEncoder(
+ const CommandEncoderDescriptor* descriptor);
ResultOrError<Ref<ComputePipelineBase>> CreateComputePipeline(
const ComputePipelineDescriptor* descriptor);
MaybeError CreateComputePipelineAsync(
diff --git a/src/tests/unittests/validation/InternalUsageValidationTests.cpp b/src/tests/unittests/validation/InternalUsageValidationTests.cpp
index 49ebc24..d175276 100644
--- a/src/tests/unittests/validation/InternalUsageValidationTests.cpp
+++ b/src/tests/unittests/validation/InternalUsageValidationTests.cpp
@@ -16,10 +16,11 @@
#include "utils/WGPUHelpers.h"
-class TextureInternalUsageValidationDisabledTest : public ValidationTest {};
+class InternalUsageValidationDisabledTest : public ValidationTest {};
-// Test that using the feature is an error if it is not enabled
-TEST_F(TextureInternalUsageValidationDisabledTest, RequiresFeature) {
+// Test that using DawnTextureInternalUsageDescriptor is an error if DawnInternalUsages is not
+// enabled
+TEST_F(InternalUsageValidationDisabledTest, TextureDescriptorRequiresFeature) {
wgpu::TextureDescriptor textureDesc = {};
textureDesc.size = {1, 1};
textureDesc.usage = wgpu::TextureUsage::CopySrc;
@@ -42,6 +43,26 @@
ASSERT_DEVICE_ERROR(device.CreateTexture(&textureDesc));
}
+// Test that using DawnEncoderInternalUsageDescriptor is an error if DawnInternalUsages is not
+// enabled
+TEST_F(InternalUsageValidationDisabledTest, CommandEncoderDescriptorRequiresFeature) {
+ wgpu::CommandEncoderDescriptor encoderDesc = {};
+
+ // Control case: Normal encoder creation works
+ device.CreateCommandEncoder(&encoderDesc);
+
+ wgpu::DawnEncoderInternalUsageDescriptor internalDesc = {};
+ encoderDesc.nextInChain = &internalDesc;
+
+ // Error with chained DawnEncoderInternalUsageDescriptor.
+ ASSERT_DEVICE_ERROR(wgpu::CommandEncoder encoder = device.CreateCommandEncoder(&encoderDesc));
+
+ // Check that the encoder records that it is invalid, and not any other errors.
+ encoder.InjectValidationError("injected error");
+ ASSERT_DEVICE_ERROR(encoder.Finish(),
+ testing::HasSubstr("[Invalid CommandEncoder] is invalid"));
+}
+
class TextureInternalUsageValidationTest : public ValidationTest {
WGPUDevice CreateTestDevice() override {
wgpu::DeviceDescriptor descriptor;
@@ -117,7 +138,7 @@
// Test that internal usage does not add to the validated usage
// for command encoding
// This test also test the internal copy
-TEST_F(TextureInternalUsageValidationTest, CommandValidation) {
+TEST_F(TextureInternalUsageValidationTest, DeprecatedCommandValidation) {
wgpu::TextureDescriptor textureDesc = {};
textureDesc.size = {1, 1};
textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
@@ -182,3 +203,96 @@
encoder.Finish();
}
}
+
+TEST_F(TextureInternalUsageValidationTest, CommandValidation) {
+ wgpu::TextureDescriptor textureDesc = {};
+ textureDesc.size = {1, 1};
+ textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
+
+ textureDesc.usage = wgpu::TextureUsage::CopyDst;
+ wgpu::Texture dst = device.CreateTexture(&textureDesc);
+
+ textureDesc.usage = wgpu::TextureUsage::CopySrc;
+ wgpu::Texture src = device.CreateTexture(&textureDesc);
+
+ textureDesc.usage = wgpu::TextureUsage::None;
+
+ wgpu::DawnTextureInternalUsageDescriptor internalDesc = {};
+ textureDesc.nextInChain = &internalDesc;
+ internalDesc.internalUsage = wgpu::TextureUsage::CopySrc;
+
+ wgpu::Texture srcInternal = device.CreateTexture(&textureDesc);
+
+ // Control: src -> dst
+ {
+ wgpu::ImageCopyTexture srcImageCopyTexture = utils::CreateImageCopyTexture(src, 0, {0, 0});
+ wgpu::ImageCopyTexture dstImageCopyTexture = utils::CreateImageCopyTexture(dst, 0, {0, 0});
+ wgpu::Extent3D extent3D = {1, 1};
+
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+ encoder.CopyTextureToTexture(&srcImageCopyTexture, &dstImageCopyTexture, &extent3D);
+ encoder.Finish();
+ }
+
+ // Invalid: src internal -> dst
+ {
+ wgpu::ImageCopyTexture srcImageCopyTexture =
+ utils::CreateImageCopyTexture(srcInternal, 0, {0, 0});
+ wgpu::ImageCopyTexture dstImageCopyTexture = utils::CreateImageCopyTexture(dst, 0, {0, 0});
+ wgpu::Extent3D extent3D = {1, 1};
+
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
+ encoder.CopyTextureToTexture(&srcImageCopyTexture, &dstImageCopyTexture, &extent3D);
+ ASSERT_DEVICE_ERROR(encoder.Finish());
+ }
+
+ // Invalid: src internal -> dst, with internal descriptor, but useInternalUsages set to false.
+ {
+ wgpu::ImageCopyTexture srcImageCopyTexture =
+ utils::CreateImageCopyTexture(srcInternal, 0, {0, 0});
+ wgpu::ImageCopyTexture dstImageCopyTexture = utils::CreateImageCopyTexture(dst, 0, {0, 0});
+ wgpu::Extent3D extent3D = {1, 1};
+
+ wgpu::CommandEncoderDescriptor encoderDesc = {};
+ wgpu::DawnEncoderInternalUsageDescriptor internalDesc = {};
+ internalDesc.useInternalUsages = false;
+ encoderDesc.nextInChain = &internalDesc;
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder(&encoderDesc);
+
+ encoder.CopyTextureToTexture(&srcImageCopyTexture, &dstImageCopyTexture, &extent3D);
+ ASSERT_DEVICE_ERROR(encoder.Finish());
+ }
+
+ // Control with internal copy: src -> dst
+ {
+ wgpu::ImageCopyTexture srcImageCopyTexture = utils::CreateImageCopyTexture(src, 0, {0, 0});
+ wgpu::ImageCopyTexture dstImageCopyTexture = utils::CreateImageCopyTexture(dst, 0, {0, 0});
+ wgpu::Extent3D extent3D = {1, 1};
+
+ wgpu::CommandEncoderDescriptor encoderDesc = {};
+ wgpu::DawnEncoderInternalUsageDescriptor internalDesc = {};
+ internalDesc.useInternalUsages = true;
+ encoderDesc.nextInChain = &internalDesc;
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder(&encoderDesc);
+
+ encoder.CopyTextureToTexture(&srcImageCopyTexture, &dstImageCopyTexture, &extent3D);
+ encoder.Finish();
+ }
+
+ // Valid with internal copy: src internal -> dst
+ {
+ wgpu::ImageCopyTexture srcImageCopyTexture =
+ utils::CreateImageCopyTexture(srcInternal, 0, {0, 0});
+ wgpu::ImageCopyTexture dstImageCopyTexture = utils::CreateImageCopyTexture(dst, 0, {0, 0});
+ wgpu::Extent3D extent3D = {1, 1};
+
+ wgpu::CommandEncoderDescriptor encoderDesc = {};
+ wgpu::DawnEncoderInternalUsageDescriptor internalDesc = {};
+ internalDesc.useInternalUsages = true;
+ encoderDesc.nextInChain = &internalDesc;
+ wgpu::CommandEncoder encoder = device.CreateCommandEncoder(&encoderDesc);
+
+ encoder.CopyTextureToTexture(&srcImageCopyTexture, &dstImageCopyTexture, &extent3D);
+ encoder.Finish();
+ }
+}