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>
This commit is contained in:
parent
ddca7bc855
commit
aa9475e973
11
dawn.json
11
dawn.json
|
@ -2369,7 +2369,8 @@
|
||||||
{"value": 11, "name": "surface descriptor from windows swap chain panel", "tags": ["dawn"]},
|
{"value": 11, "name": "surface descriptor from windows swap chain panel", "tags": ["dawn"]},
|
||||||
{"value": 1000, "name": "dawn texture internal usage descriptor", "tags": ["dawn"]},
|
{"value": 1000, "name": "dawn texture internal usage descriptor", "tags": ["dawn"]},
|
||||||
{"value": 1001, "name": "primitive depth clamping state", "tags": ["dawn", "emscripten"]},
|
{"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": {
|
"texture": {
|
||||||
|
@ -2733,5 +2734,13 @@
|
||||||
"members": [
|
"members": [
|
||||||
{"name": "internal usage", "type": "texture usage", "default": "none"}
|
{"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"}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
# Dawn Internal Usages
|
# 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 = {};
|
wgpu::DawnTextureInternalUsageDescriptor internalDesc = {};
|
||||||
internalDesc.internalUsage = wgpu::TextureUsage::CopySrc;
|
internalDesc.internalUsage = wgpu::TextureUsage::CopySrc;
|
||||||
|
|
||||||
|
@ -14,5 +13,26 @@ wgpu::TextureDescriptor desc = {};
|
||||||
// set properties of desc.
|
// set properties of desc.
|
||||||
desc.nextInChain = &internalDesc;
|
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`.
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "common/Math.h"
|
#include "common/Math.h"
|
||||||
#include "dawn_native/BindGroup.h"
|
#include "dawn_native/BindGroup.h"
|
||||||
#include "dawn_native/Buffer.h"
|
#include "dawn_native/Buffer.h"
|
||||||
|
#include "dawn_native/ChainUtils_autogen.h"
|
||||||
#include "dawn_native/CommandBuffer.h"
|
#include "dawn_native/CommandBuffer.h"
|
||||||
#include "dawn_native/CommandBufferStateTracker.h"
|
#include "dawn_native/CommandBufferStateTracker.h"
|
||||||
#include "dawn_native/CommandValidation.h"
|
#include "dawn_native/CommandValidation.h"
|
||||||
|
@ -159,7 +160,8 @@ namespace dawn::native {
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ValidateResolveTarget(const DeviceBase* device,
|
MaybeError ValidateResolveTarget(const DeviceBase* device,
|
||||||
const RenderPassColorAttachment& colorAttachment) {
|
const RenderPassColorAttachment& colorAttachment,
|
||||||
|
UsageValidationMode usageValidationMode) {
|
||||||
if (colorAttachment.resolveTarget == nullptr) {
|
if (colorAttachment.resolveTarget == nullptr) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -168,7 +170,7 @@ namespace dawn::native {
|
||||||
const TextureViewBase* attachment = colorAttachment.view;
|
const TextureViewBase* attachment = colorAttachment.view;
|
||||||
DAWN_TRY(device->ValidateObject(colorAttachment.resolveTarget));
|
DAWN_TRY(device->ValidateObject(colorAttachment.resolveTarget));
|
||||||
DAWN_TRY(ValidateCanUseAs(colorAttachment.resolveTarget->GetTexture(),
|
DAWN_TRY(ValidateCanUseAs(colorAttachment.resolveTarget->GetTexture(),
|
||||||
wgpu::TextureUsage::RenderAttachment));
|
wgpu::TextureUsage::RenderAttachment, usageValidationMode));
|
||||||
|
|
||||||
DAWN_INVALID_IF(
|
DAWN_INVALID_IF(
|
||||||
!attachment->GetTexture()->IsMultisampledTexture(),
|
!attachment->GetTexture()->IsMultisampledTexture(),
|
||||||
|
@ -216,11 +218,12 @@ namespace dawn::native {
|
||||||
const RenderPassColorAttachment& colorAttachment,
|
const RenderPassColorAttachment& colorAttachment,
|
||||||
uint32_t* width,
|
uint32_t* width,
|
||||||
uint32_t* height,
|
uint32_t* height,
|
||||||
uint32_t* sampleCount) {
|
uint32_t* sampleCount,
|
||||||
|
UsageValidationMode usageValidationMode) {
|
||||||
TextureViewBase* attachment = colorAttachment.view;
|
TextureViewBase* attachment = colorAttachment.view;
|
||||||
DAWN_TRY(device->ValidateObject(attachment));
|
DAWN_TRY(device->ValidateObject(attachment));
|
||||||
DAWN_TRY(
|
DAWN_TRY(ValidateCanUseAs(attachment->GetTexture(),
|
||||||
ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment));
|
wgpu::TextureUsage::RenderAttachment, usageValidationMode));
|
||||||
|
|
||||||
DAWN_INVALID_IF(!(attachment->GetAspects() & Aspect::Color) ||
|
DAWN_INVALID_IF(!(attachment->GetAspects() & Aspect::Color) ||
|
||||||
!attachment->GetFormat().isRenderable,
|
!attachment->GetFormat().isRenderable,
|
||||||
|
@ -241,7 +244,7 @@ namespace dawn::native {
|
||||||
|
|
||||||
DAWN_TRY(ValidateOrSetColorAttachmentSampleCount(attachment, sampleCount));
|
DAWN_TRY(ValidateOrSetColorAttachmentSampleCount(attachment, sampleCount));
|
||||||
|
|
||||||
DAWN_TRY(ValidateResolveTarget(device, colorAttachment));
|
DAWN_TRY(ValidateResolveTarget(device, colorAttachment, usageValidationMode));
|
||||||
|
|
||||||
DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment));
|
DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment));
|
||||||
DAWN_TRY(ValidateOrSetAttachmentSize(attachment, width, height));
|
DAWN_TRY(ValidateOrSetAttachmentSize(attachment, width, height));
|
||||||
|
@ -254,13 +257,14 @@ namespace dawn::native {
|
||||||
const RenderPassDepthStencilAttachment* depthStencilAttachment,
|
const RenderPassDepthStencilAttachment* depthStencilAttachment,
|
||||||
uint32_t* width,
|
uint32_t* width,
|
||||||
uint32_t* height,
|
uint32_t* height,
|
||||||
uint32_t* sampleCount) {
|
uint32_t* sampleCount,
|
||||||
|
UsageValidationMode usageValidationMode) {
|
||||||
DAWN_ASSERT(depthStencilAttachment != nullptr);
|
DAWN_ASSERT(depthStencilAttachment != nullptr);
|
||||||
|
|
||||||
TextureViewBase* attachment = depthStencilAttachment->view;
|
TextureViewBase* attachment = depthStencilAttachment->view;
|
||||||
DAWN_TRY(device->ValidateObject(attachment));
|
DAWN_TRY(device->ValidateObject(attachment));
|
||||||
DAWN_TRY(
|
DAWN_TRY(ValidateCanUseAs(attachment->GetTexture(),
|
||||||
ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment));
|
wgpu::TextureUsage::RenderAttachment, usageValidationMode));
|
||||||
|
|
||||||
const Format& format = attachment->GetFormat();
|
const Format& format = attachment->GetFormat();
|
||||||
DAWN_INVALID_IF(
|
DAWN_INVALID_IF(
|
||||||
|
@ -333,24 +337,25 @@ namespace dawn::native {
|
||||||
const RenderPassDescriptor* descriptor,
|
const RenderPassDescriptor* descriptor,
|
||||||
uint32_t* width,
|
uint32_t* width,
|
||||||
uint32_t* height,
|
uint32_t* height,
|
||||||
uint32_t* sampleCount) {
|
uint32_t* sampleCount,
|
||||||
|
UsageValidationMode usageValidationMode) {
|
||||||
DAWN_INVALID_IF(
|
DAWN_INVALID_IF(
|
||||||
descriptor->colorAttachmentCount > kMaxColorAttachments,
|
descriptor->colorAttachmentCount > kMaxColorAttachments,
|
||||||
"Color attachment count (%u) exceeds the maximum number of color attachments (%u).",
|
"Color attachment count (%u) exceeds the maximum number of color attachments (%u).",
|
||||||
descriptor->colorAttachmentCount, kMaxColorAttachments);
|
descriptor->colorAttachmentCount, kMaxColorAttachments);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) {
|
for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) {
|
||||||
DAWN_TRY_CONTEXT(
|
DAWN_TRY_CONTEXT(ValidateRenderPassColorAttachment(
|
||||||
ValidateRenderPassColorAttachment(device, descriptor->colorAttachments[i],
|
device, descriptor->colorAttachments[i], width, height,
|
||||||
width, height, sampleCount),
|
sampleCount, usageValidationMode),
|
||||||
"validating colorAttachments[%u].", i);
|
"validating colorAttachments[%u].", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor->depthStencilAttachment != nullptr) {
|
if (descriptor->depthStencilAttachment != nullptr) {
|
||||||
DAWN_TRY_CONTEXT(
|
DAWN_TRY_CONTEXT(ValidateRenderPassDepthStencilAttachment(
|
||||||
ValidateRenderPassDepthStencilAttachment(
|
device, descriptor->depthStencilAttachment, width, height,
|
||||||
device, descriptor->depthStencilAttachment, width, height, sampleCount),
|
sampleCount, usageValidationMode),
|
||||||
"validating depthStencilAttachment.");
|
"validating depthStencilAttachment.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor->occlusionQuerySet != nullptr) {
|
if (descriptor->occlusionQuerySet != nullptr) {
|
||||||
|
@ -468,9 +473,50 @@ namespace dawn::native {
|
||||||
|
|
||||||
} // namespace
|
} // 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)
|
CommandEncoder::CommandEncoder(DeviceBase* device, const CommandEncoderDescriptor* descriptor)
|
||||||
: ApiObjectBase(device, descriptor->label), mEncodingContext(device, this) {
|
: ApiObjectBase(device, descriptor->label), mEncodingContext(device, this) {
|
||||||
TrackInDevice();
|
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 {
|
ObjectType CommandEncoder::GetType() const {
|
||||||
|
@ -554,7 +600,7 @@ namespace dawn::native {
|
||||||
uint32_t sampleCount = 0;
|
uint32_t sampleCount = 0;
|
||||||
|
|
||||||
DAWN_TRY(ValidateRenderPassDescriptor(device, descriptor, &width, &height,
|
DAWN_TRY(ValidateRenderPassDescriptor(device, descriptor, &width, &height,
|
||||||
&sampleCount));
|
&sampleCount, mUsageValidationMode));
|
||||||
|
|
||||||
ASSERT(width > 0 && height > 0 && sampleCount > 0);
|
ASSERT(width > 0 && height > 0 && sampleCount > 0);
|
||||||
|
|
||||||
|
@ -703,7 +749,8 @@ namespace dawn::native {
|
||||||
|
|
||||||
DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize));
|
DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize));
|
||||||
DAWN_TRY_CONTEXT(
|
DAWN_TRY_CONTEXT(
|
||||||
ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst),
|
ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst,
|
||||||
|
mUsageValidationMode),
|
||||||
"validating destination %s usage.", destination->texture);
|
"validating destination %s usage.", destination->texture);
|
||||||
DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(destination->texture));
|
DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(destination->texture));
|
||||||
|
|
||||||
|
@ -757,7 +804,8 @@ namespace dawn::native {
|
||||||
[&](CommandAllocator* allocator) -> MaybeError {
|
[&](CommandAllocator* allocator) -> MaybeError {
|
||||||
if (GetDevice()->IsValidationEnabled()) {
|
if (GetDevice()->IsValidationEnabled()) {
|
||||||
DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *source, *copySize));
|
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);
|
"validating source %s usage.", source->texture);
|
||||||
DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(source->texture));
|
DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(source->texture));
|
||||||
DAWN_TRY(ValidateTextureDepthStencilToBufferCopyRestrictions(*source));
|
DAWN_TRY(ValidateTextureDepthStencilToBufferCopyRestrictions(*source));
|
||||||
|
@ -846,14 +894,15 @@ namespace dawn::native {
|
||||||
// For internal usages (CopyToCopyInternal) we don't care if the user has added
|
// 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.
|
// CopySrc as a usage for this texture, but we will always add it internally.
|
||||||
if (Internal) {
|
if (Internal) {
|
||||||
DAWN_TRY(
|
DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc,
|
||||||
ValidateInternalCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
|
UsageValidationMode::Internal));
|
||||||
DAWN_TRY(ValidateInternalCanUseAs(destination->texture,
|
DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst,
|
||||||
wgpu::TextureUsage::CopyDst));
|
UsageValidationMode::Internal));
|
||||||
} else {
|
} else {
|
||||||
DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
|
DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc,
|
||||||
DAWN_TRY(
|
mUsageValidationMode));
|
||||||
ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst));
|
DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst,
|
||||||
|
mUsageValidationMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
mTopLevelTextures.insert(source->texture);
|
mTopLevelTextures.insert(source->texture);
|
||||||
|
|
|
@ -26,9 +26,16 @@
|
||||||
|
|
||||||
namespace dawn::native {
|
namespace dawn::native {
|
||||||
|
|
||||||
|
enum class UsageValidationMode;
|
||||||
|
|
||||||
|
MaybeError ValidateCommandEncoderDescriptor(const DeviceBase* device,
|
||||||
|
const CommandEncoderDescriptor* descriptor);
|
||||||
|
|
||||||
class CommandEncoder final : public ApiObjectBase {
|
class CommandEncoder final : public ApiObjectBase {
|
||||||
public:
|
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;
|
ObjectType GetType() const override;
|
||||||
|
|
||||||
|
@ -80,6 +87,9 @@ namespace dawn::native {
|
||||||
CommandBufferBase* APIFinish(const CommandBufferDescriptor* descriptor = nullptr);
|
CommandBufferBase* APIFinish(const CommandBufferDescriptor* descriptor = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CommandEncoder(DeviceBase* device, const CommandEncoderDescriptor* descriptor);
|
||||||
|
CommandEncoder(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||||
|
|
||||||
void DestroyImpl() override;
|
void DestroyImpl() override;
|
||||||
ResultOrError<Ref<CommandBufferBase>> FinishInternal(
|
ResultOrError<Ref<CommandBufferBase>> FinishInternal(
|
||||||
const CommandBufferDescriptor* descriptor);
|
const CommandBufferDescriptor* descriptor);
|
||||||
|
@ -100,6 +110,8 @@ namespace dawn::native {
|
||||||
std::set<QuerySetBase*> mUsedQuerySets;
|
std::set<QuerySetBase*> mUsedQuerySets;
|
||||||
|
|
||||||
uint64_t mDebugGroupStackSize = 0;
|
uint64_t mDebugGroupStackSize = 0;
|
||||||
|
|
||||||
|
UsageValidationMode mUsageValidationMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn::native
|
} // namespace dawn::native
|
||||||
|
|
|
@ -447,19 +447,21 @@ namespace dawn::native {
|
||||||
return ValidateTextureToTextureCopyCommonRestrictions(src, dst, copySize);
|
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));
|
ASSERT(wgpu::HasZeroOrOneBits(usage));
|
||||||
DAWN_INVALID_IF(!(texture->GetUsage() & usage), "%s usage (%s) doesn't include %s.",
|
switch (mode) {
|
||||||
texture, texture->GetUsage(), usage);
|
case UsageValidationMode::Default:
|
||||||
|
DAWN_INVALID_IF(!(texture->GetUsage() & usage), "%s usage (%s) doesn't include %s.",
|
||||||
return {};
|
texture, texture->GetUsage(), usage);
|
||||||
}
|
break;
|
||||||
|
case UsageValidationMode::Internal:
|
||||||
MaybeError ValidateInternalCanUseAs(const TextureBase* texture, wgpu::TextureUsage usage) {
|
DAWN_INVALID_IF(!(texture->GetInternalUsage() & usage),
|
||||||
ASSERT(wgpu::HasZeroOrOneBits(usage));
|
"%s internal usage (%s) doesn't include %s.", texture,
|
||||||
DAWN_INVALID_IF(!(texture->GetInternalUsage() & usage),
|
texture->GetInternalUsage(), usage);
|
||||||
"%s internal usage (%s) doesn't include %s.", texture,
|
break;
|
||||||
texture->GetInternalUsage(), usage);
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -468,7 +470,6 @@ namespace dawn::native {
|
||||||
ASSERT(wgpu::HasZeroOrOneBits(usage));
|
ASSERT(wgpu::HasZeroOrOneBits(usage));
|
||||||
DAWN_INVALID_IF(!(buffer->GetUsage() & usage), "%s usage (%s) doesn't include %s.", buffer,
|
DAWN_INVALID_IF(!(buffer->GetUsage() & usage), "%s usage (%s) doesn't include %s.", buffer,
|
||||||
buffer->GetUsage(), usage);
|
buffer->GetUsage(), usage);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,10 +73,14 @@ namespace dawn::native {
|
||||||
const ImageCopyTexture& dst,
|
const ImageCopyTexture& dst,
|
||||||
const Extent3D& copySize);
|
const Extent3D& copySize);
|
||||||
|
|
||||||
MaybeError ValidateCanUseAs(const TextureBase* texture, wgpu::TextureUsage usage);
|
enum class UsageValidationMode {
|
||||||
|
Default,
|
||||||
MaybeError ValidateInternalCanUseAs(const TextureBase* texture, wgpu::TextureUsage usage);
|
Internal,
|
||||||
|
};
|
||||||
|
|
||||||
|
MaybeError ValidateCanUseAs(const TextureBase* texture,
|
||||||
|
wgpu::TextureUsage usage,
|
||||||
|
UsageValidationMode mode);
|
||||||
MaybeError ValidateCanUseAs(const BufferBase* buffer, wgpu::BufferUsage usage);
|
MaybeError ValidateCanUseAs(const BufferBase* buffer, wgpu::BufferUsage usage);
|
||||||
|
|
||||||
} // namespace dawn::native
|
} // namespace dawn::native
|
||||||
|
|
|
@ -350,11 +350,15 @@ namespace dawn::native {
|
||||||
"not 1.",
|
"not 1.",
|
||||||
source->texture->GetSampleCount(), destination->texture->GetSampleCount());
|
source->texture->GetSampleCount(), destination->texture->GetSampleCount());
|
||||||
|
|
||||||
DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
|
DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc,
|
||||||
DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::TextureBinding));
|
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::CopyDst,
|
||||||
DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::RenderAttachment));
|
UsageValidationMode::Default));
|
||||||
|
DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::RenderAttachment,
|
||||||
|
UsageValidationMode::Default));
|
||||||
|
|
||||||
DAWN_TRY(ValidateCopyTextureFormatConversion(source->texture->GetFormat().format,
|
DAWN_TRY(ValidateCopyTextureFormatConversion(source->texture->GetFormat().format,
|
||||||
destination->texture->GetFormat().format));
|
destination->texture->GetFormat().format));
|
||||||
|
|
|
@ -953,7 +953,13 @@ namespace dawn::native {
|
||||||
if (descriptor == nullptr) {
|
if (descriptor == nullptr) {
|
||||||
descriptor = &defaultDescriptor;
|
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(
|
ComputePipelineBase* DeviceBase::APICreateComputePipeline(
|
||||||
const ComputePipelineDescriptor* descriptor) {
|
const ComputePipelineDescriptor* descriptor) {
|
||||||
|
@ -1313,6 +1319,15 @@ namespace dawn::native {
|
||||||
return AddOrGetCachedComputePipeline(std::move(uninitializedComputePipeline));
|
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(
|
MaybeError DeviceBase::CreateComputePipelineAsync(
|
||||||
const ComputePipelineDescriptor* descriptor,
|
const ComputePipelineDescriptor* descriptor,
|
||||||
WGPUCreateComputePipelineAsyncCallback callback,
|
WGPUCreateComputePipelineAsyncCallback callback,
|
||||||
|
|
|
@ -198,6 +198,8 @@ namespace dawn::native {
|
||||||
const BindGroupLayoutDescriptor* descriptor,
|
const BindGroupLayoutDescriptor* descriptor,
|
||||||
bool allowInternalBinding = false);
|
bool allowInternalBinding = false);
|
||||||
ResultOrError<Ref<BufferBase>> CreateBuffer(const BufferDescriptor* descriptor);
|
ResultOrError<Ref<BufferBase>> CreateBuffer(const BufferDescriptor* descriptor);
|
||||||
|
ResultOrError<Ref<CommandEncoder>> CreateCommandEncoder(
|
||||||
|
const CommandEncoderDescriptor* descriptor);
|
||||||
ResultOrError<Ref<ComputePipelineBase>> CreateComputePipeline(
|
ResultOrError<Ref<ComputePipelineBase>> CreateComputePipeline(
|
||||||
const ComputePipelineDescriptor* descriptor);
|
const ComputePipelineDescriptor* descriptor);
|
||||||
MaybeError CreateComputePipelineAsync(
|
MaybeError CreateComputePipelineAsync(
|
||||||
|
|
|
@ -16,10 +16,11 @@
|
||||||
|
|
||||||
#include "utils/WGPUHelpers.h"
|
#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 that using DawnTextureInternalUsageDescriptor is an error if DawnInternalUsages is not
|
||||||
TEST_F(TextureInternalUsageValidationDisabledTest, RequiresFeature) {
|
// enabled
|
||||||
|
TEST_F(InternalUsageValidationDisabledTest, TextureDescriptorRequiresFeature) {
|
||||||
wgpu::TextureDescriptor textureDesc = {};
|
wgpu::TextureDescriptor textureDesc = {};
|
||||||
textureDesc.size = {1, 1};
|
textureDesc.size = {1, 1};
|
||||||
textureDesc.usage = wgpu::TextureUsage::CopySrc;
|
textureDesc.usage = wgpu::TextureUsage::CopySrc;
|
||||||
|
@ -42,6 +43,26 @@ TEST_F(TextureInternalUsageValidationDisabledTest, RequiresFeature) {
|
||||||
ASSERT_DEVICE_ERROR(device.CreateTexture(&textureDesc));
|
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 {
|
class TextureInternalUsageValidationTest : public ValidationTest {
|
||||||
WGPUDevice CreateTestDevice() override {
|
WGPUDevice CreateTestDevice() override {
|
||||||
wgpu::DeviceDescriptor descriptor;
|
wgpu::DeviceDescriptor descriptor;
|
||||||
|
@ -117,7 +138,7 @@ TEST_F(TextureInternalUsageValidationTest, UsageValidation) {
|
||||||
// Test that internal usage does not add to the validated usage
|
// Test that internal usage does not add to the validated usage
|
||||||
// for command encoding
|
// for command encoding
|
||||||
// This test also test the internal copy
|
// This test also test the internal copy
|
||||||
TEST_F(TextureInternalUsageValidationTest, CommandValidation) {
|
TEST_F(TextureInternalUsageValidationTest, DeprecatedCommandValidation) {
|
||||||
wgpu::TextureDescriptor textureDesc = {};
|
wgpu::TextureDescriptor textureDesc = {};
|
||||||
textureDesc.size = {1, 1};
|
textureDesc.size = {1, 1};
|
||||||
textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
textureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
@ -182,3 +203,96 @@ TEST_F(TextureInternalUsageValidationTest, CommandValidation) {
|
||||||
encoder.Finish();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue