Add a usage parameter to TextureView creation.
This allows views to use a subset of usages from the source texture's
usages and use formats that may not be compatible with all of the
source textures usages.
Roll third_party/gpuweb/ 2dc56f297..010f5c9dd (5 commits):
https://github.com/gpuweb/gpuweb/compare/2dc56f29788a...010f5c9ddfd2
Bug: 363903526
Change-Id: I4d59907a976063b01a992776a20eeeaf326856ad
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/206115
Commit-Queue: Geoff Lang <geofflang@google.com>
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/DEPS b/DEPS
index 3f9ce3b..af420a1 100644
--- a/DEPS
+++ b/DEPS
@@ -375,7 +375,7 @@
'condition': 'dawn_node',
},
'third_party/gpuweb': {
- 'url': '{github_git}/gpuweb/gpuweb.git@2dc56f29788a2b8087ef0de87379c0b40a6f2dd5',
+ 'url': '{github_git}/gpuweb/gpuweb.git@010f5c9ddfd21bc963025979d08eb7489058c1c7',
'condition': 'dawn_node',
},
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index 8d20970..063eefa 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -4625,7 +4625,8 @@
{"name": "mip level count", "type": "uint32_t", "default": "WGPU_MIP_LEVEL_COUNT_UNDEFINED"},
{"name": "base array layer", "type": "uint32_t", "default": "0"},
{"name": "array layer count", "type": "uint32_t", "default": "WGPU_ARRAY_LAYER_COUNT_UNDEFINED"},
- {"name": "aspect", "type": "texture aspect", "default": "all"}
+ {"name": "aspect", "type": "texture aspect", "default": "all"},
+ {"name": "usage", "type": "texture usage", "default": "none"}
]
},
"texture view": {
diff --git a/src/dawn/native/BindGroup.cpp b/src/dawn/native/BindGroup.cpp
index b397bf4..c6438e9 100644
--- a/src/dawn/native/BindGroup.cpp
+++ b/src/dawn/native/BindGroup.cpp
@@ -166,7 +166,7 @@
static_cast<SharedTextureMemoryContents*>(texture->GetSharedResourceMemoryContents())
->GetExternalFormatSupportedSampleTypes();
}
- DAWN_TRY(ValidateCanUseAs(texture, wgpu::TextureUsage::TextureBinding, mode));
+ DAWN_TRY(ValidateCanUseAs(view, wgpu::TextureUsage::TextureBinding, mode));
DAWN_INVALID_IF(texture->IsMultisampledTexture() != layout.multisampled,
"Sample count (%u) of %s doesn't match expectation (multisampled: %d).",
@@ -210,7 +210,7 @@
TextureViewBase* view = entry.textureView;
TextureBase* texture = view->GetTexture();
- DAWN_TRY(ValidateCanUseAs(texture, wgpu::TextureUsage::StorageBinding, mode));
+ DAWN_TRY(ValidateCanUseAs(view, wgpu::TextureUsage::StorageBinding, mode));
DAWN_ASSERT(!texture->IsMultisampledTexture());
diff --git a/src/dawn/native/CommandEncoder.cpp b/src/dawn/native/CommandEncoder.cpp
index 0cb5762..27f8be5 100644
--- a/src/dawn/native/CommandEncoder.cpp
+++ b/src/dawn/native/CommandEncoder.cpp
@@ -386,8 +386,8 @@
const TextureViewBase* resolveTarget = colorAttachment.resolveTarget;
const TextureViewBase* attachment = colorAttachment.view;
DAWN_TRY(device->ValidateObject(colorAttachment.resolveTarget));
- DAWN_TRY(ValidateCanUseAs(colorAttachment.resolveTarget->GetTexture(),
- wgpu::TextureUsage::RenderAttachment, usageValidationMode));
+ DAWN_TRY(ValidateCanUseAs(colorAttachment.resolveTarget, wgpu::TextureUsage::RenderAttachment,
+ usageValidationMode));
DAWN_INVALID_IF(!attachment->GetTexture()->IsMultisampledTexture(),
"Cannot set %s as a resolve target when the color attachment %s has a sample "
@@ -503,12 +503,12 @@
!colorAttachment.resolveTarget->IsError());
DAWN_ASSERT(colorAttachment.view->GetFormat().supportsResolveTarget);
- DAWN_INVALID_IF((colorAttachment.resolveTarget->GetTexture()->GetUsage() &
- wgpu::TextureUsage::TextureBinding) == 0,
- "Resolve target %s was not created with %s usage, which is required for "
- "%s.",
- colorAttachment.resolveTarget, wgpu::TextureUsage::TextureBinding,
- wgpu::LoadOp::ExpandResolveTexture);
+ DAWN_INVALID_IF(
+ (colorAttachment.resolveTarget->GetUsage() & wgpu::TextureUsage::TextureBinding) == 0,
+ "Resolve target %s was not created with %s usage, which is required for "
+ "%s.",
+ colorAttachment.resolveTarget, wgpu::TextureUsage::TextureBinding,
+ wgpu::LoadOp::ExpandResolveTexture);
// TODO(42240662): multiplanar textures are not supported as resolve target.
// The RenderPassValidationState currently rejects such usage.
@@ -529,8 +529,8 @@
}
DAWN_TRY(device->ValidateObject(attachment));
- DAWN_TRY(ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment,
- usageValidationMode));
+ DAWN_TRY(
+ ValidateCanUseAs(attachment, wgpu::TextureUsage::RenderAttachment, usageValidationMode));
UnpackedPtr<RenderPassColorAttachment> unpacked;
DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(&colorAttachment));
@@ -558,16 +558,16 @@
DAWN_TRY(ValidateStoreOp(colorAttachment.storeOp));
DAWN_INVALID_IF(colorAttachment.loadOp == wgpu::LoadOp::Undefined, "loadOp must be set.");
DAWN_INVALID_IF(colorAttachment.storeOp == wgpu::StoreOp::Undefined, "storeOp must be set.");
- if (attachment->GetTexture()->GetUsage() & wgpu::TextureUsage::TransientAttachment) {
+ if (attachment->GetUsage() & wgpu::TextureUsage::TransientAttachment) {
DAWN_INVALID_IF(colorAttachment.loadOp != wgpu::LoadOp::Clear &&
colorAttachment.loadOp != wgpu::LoadOp::ExpandResolveTexture,
"The color attachment %s has the load op set to %s while its usage (%s) "
"has the transient attachment bit set.",
- attachment, colorAttachment.loadOp, attachment->GetTexture()->GetUsage());
+ attachment, colorAttachment.loadOp, attachment->GetUsage());
DAWN_INVALID_IF(colorAttachment.storeOp != wgpu::StoreOp::Discard,
"The color attachment %s has the store op set to %s while its usage (%s) "
"has the transient attachment bit set.",
- attachment, wgpu::StoreOp::Store, attachment->GetTexture()->GetUsage());
+ attachment, wgpu::StoreOp::Store, attachment->GetUsage());
}
const dawn::native::Color& clearValue = colorAttachment.clearValue;
@@ -612,8 +612,8 @@
TextureViewBase* attachment = depthStencilAttachment->view;
DAWN_TRY(device->ValidateObject(attachment));
- DAWN_TRY(ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment,
- usageValidationMode));
+ DAWN_TRY(
+ ValidateCanUseAs(attachment, wgpu::TextureUsage::RenderAttachment, usageValidationMode));
// DS attachments must encompass all aspects of the texture, so we first check that this is
// true, which means that in the rest of the function we can assume that the view's format is
@@ -712,8 +712,8 @@
// Validate the attachment can be used as a storage attachment.
DAWN_TRY(device->ValidateObject(attachment.storage));
- DAWN_TRY(ValidateCanUseAs(attachment.storage->GetTexture(),
- wgpu::TextureUsage::StorageAttachment, usageValidationMode));
+ DAWN_TRY(ValidateCanUseAs(attachment.storage, wgpu::TextureUsage::StorageAttachment,
+ usageValidationMode));
DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment.storage));
// Validate the load/storeOp and the clearValue.
diff --git a/src/dawn/native/CommandValidation.cpp b/src/dawn/native/CommandValidation.cpp
index 7bd537a..ccdc97bc 100644
--- a/src/dawn/native/CommandValidation.cpp
+++ b/src/dawn/native/CommandValidation.cpp
@@ -648,6 +648,25 @@
return {};
}
+MaybeError ValidateCanUseAs(const TextureViewBase* textureView,
+ wgpu::TextureUsage usage,
+ UsageValidationMode mode) {
+ DAWN_ASSERT(wgpu::HasZeroOrOneBits(usage));
+ DAWN_ASSERT(IsSubset(usage, kTextureViewOnlyUsages));
+ switch (mode) {
+ case UsageValidationMode::Default:
+ DAWN_INVALID_IF(!(textureView->GetUsage() & usage), "%s usage (%s) doesn't include %s.",
+ textureView, textureView->GetUsage(), usage);
+ break;
+ case UsageValidationMode::Internal:
+ DAWN_INVALID_IF(!(textureView->GetInternalUsage() & usage),
+ "%s internal usage (%s) doesn't include %s.", textureView,
+ textureView->GetInternalUsage(), usage);
+ break;
+ }
+ return {};
+}
+
MaybeError ValidateCanUseAs(const BufferBase* buffer, wgpu::BufferUsage usage) {
DAWN_ASSERT(wgpu::HasZeroOrOneBits(usage));
DAWN_INVALID_IF(!(buffer->GetUsage() & usage), "%s usage (%s) doesn't include %s.", buffer,
diff --git a/src/dawn/native/CommandValidation.h b/src/dawn/native/CommandValidation.h
index 36e737f..f9c2dbd 100644
--- a/src/dawn/native/CommandValidation.h
+++ b/src/dawn/native/CommandValidation.h
@@ -110,7 +110,10 @@
const ImageCopyTexture& dst,
const Extent3D& copySize);
-MaybeError ValidateCanUseAs(const TextureBase* texture,
+MaybeError ValidateCanUseAs(const TextureBase* textureView,
+ wgpu::TextureUsage usage,
+ UsageValidationMode mode);
+MaybeError ValidateCanUseAs(const TextureViewBase* textureView,
wgpu::TextureUsage usage,
UsageValidationMode mode);
MaybeError ValidateCanUseAs(const BufferBase* buffer, wgpu::BufferUsage usage);
diff --git a/src/dawn/native/ExternalTexture.cpp b/src/dawn/native/ExternalTexture.cpp
index 7249bc5..d916af5 100644
--- a/src/dawn/native/ExternalTexture.cpp
+++ b/src/dawn/native/ExternalTexture.cpp
@@ -42,9 +42,9 @@
MaybeError ValidateExternalTexturePlane(const TextureViewBase* textureView) {
DAWN_INVALID_IF(
- (textureView->GetTexture()->GetUsage() & wgpu::TextureUsage::TextureBinding) == 0,
+ (textureView->GetUsage() & wgpu::TextureUsage::TextureBinding) == 0,
"The external texture plane (%s) usage (%s) doesn't include the required usage (%s)",
- textureView, textureView->GetTexture()->GetUsage(), wgpu::TextureUsage::TextureBinding);
+ textureView, textureView->GetUsage(), wgpu::TextureUsage::TextureBinding);
DAWN_INVALID_IF(textureView->GetDimension() != wgpu::TextureViewDimension::e2D,
"The external texture plane (%s) dimension (%s) is not 2D.", textureView,
diff --git a/src/dawn/native/Texture.cpp b/src/dawn/native/Texture.cpp
index 8d929f5..2138d65 100644
--- a/src/dawn/native/Texture.cpp
+++ b/src/dawn/native/Texture.cpp
@@ -347,7 +347,7 @@
}
MaybeError ValidateTextureUsage(const DeviceBase* device,
- const TextureDescriptor* descriptor,
+ wgpu::TextureDimension textureDimension,
wgpu::TextureUsage usage,
const Format* format,
std::optional<wgpu::TextureUsage> allowedSharedTextureMemoryUsage) {
@@ -369,11 +369,11 @@
"format (%s).",
usage, wgpu::TextureUsage::RenderAttachment, format->format);
- DAWN_INVALID_IF(descriptor->dimension == wgpu::TextureDimension::e1D &&
+ DAWN_INVALID_IF(textureDimension == wgpu::TextureDimension::e1D &&
(usage & wgpu::TextureUsage::RenderAttachment),
"The texture usage (%s) includes %s, which is incompatible with the texture "
"dimension (%s).",
- usage, wgpu::TextureUsage::RenderAttachment, descriptor->dimension);
+ usage, wgpu::TextureUsage::RenderAttachment, textureDimension);
DAWN_INVALID_IF(
!format->supportsStorageUsage && (usage & wgpu::TextureUsage::StorageBinding),
@@ -427,6 +427,27 @@
return {};
}
+wgpu::TextureUsage GetTextureViewUsage(wgpu::TextureUsage sourceTextureUsage,
+ wgpu::TextureUsage requestedViewUsage) {
+ // If a view's requested usage is None, inherit usage from the source texture.
+ return (requestedViewUsage != wgpu::TextureUsage::None) ? requestedViewUsage
+ : sourceTextureUsage;
+}
+
+MaybeError ValidateTextureViewUsage(const DeviceBase* device,
+ const TextureBase* texture,
+ wgpu::TextureUsage usage,
+ const Format* format) {
+ wgpu::TextureUsage inheritedUsage = GetTextureViewUsage(texture->GetUsage(), usage);
+ DAWN_INVALID_IF(!IsSubset(inheritedUsage, texture->GetUsage()),
+ "The texture view usage (%s) is not a subset of the texture usage (%s).",
+ inheritedUsage, texture->GetUsage());
+
+ DAWN_TRY(ValidateTextureUsage(device, texture->GetDimension(), inheritedUsage, format, {}));
+
+ return {};
+}
+
// We need to add an internal RenderAttachment usage to some textures that has CopyDst usage as we
// apply a workaround that writes to them with a render pipeline.
bool CopyDstNeedsInternalRenderAttachmentUsage(const DeviceBase* device, const Format& format) {
@@ -516,6 +537,49 @@
}
}
+wgpu::TextureUsage AddInternalUsages(const DeviceBase* device,
+ wgpu::TextureUsage usage,
+ const Format& format,
+ uint32_t sampleCount,
+ uint32_t mipLevelCount,
+ uint32_t arrayLayerCount) {
+ wgpu::TextureUsage internalUsage = usage;
+
+ // dawn:1569: If a texture with multiple array layers or mip levels is specified as a
+ // texture attachment when this toggle is active, it needs to be given CopySrc | CopyDst usage
+ // internally.
+ bool applyAlwaysResolveIntoZeroLevelAndLayerToggle =
+ device->IsToggleEnabled(Toggle::AlwaysResolveIntoZeroLevelAndLayer) &&
+ (arrayLayerCount > 1 || mipLevelCount > 1) &&
+ (internalUsage & wgpu::TextureUsage::RenderAttachment);
+ if (applyAlwaysResolveIntoZeroLevelAndLayerToggle) {
+ internalUsage |= wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
+ }
+
+ if (internalUsage & wgpu::TextureUsage::CopyDst) {
+ if (CopyDstNeedsInternalRenderAttachmentUsage(device, format)) {
+ internalUsage |= wgpu::TextureUsage::RenderAttachment;
+ }
+ }
+ if (internalUsage & wgpu::TextureUsage::CopySrc) {
+ if (CopySrcNeedsInternalTextureBindingUsage(device, format)) {
+ internalUsage |= wgpu::TextureUsage::TextureBinding;
+ }
+ }
+ if (internalUsage & wgpu::TextureUsage::StorageBinding) {
+ internalUsage |= kReadOnlyStorageTexture | kWriteOnlyStorageTexture;
+ }
+
+ bool supportsMSAAPartialResolve = device->HasFeature(Feature::DawnPartialLoadResolveTexture) &&
+ sampleCount > 1 &&
+ (usage & wgpu::TextureUsage::RenderAttachment);
+ if (supportsMSAAPartialResolve) {
+ internalUsage |= wgpu::TextureUsage::TextureBinding;
+ }
+
+ return internalUsage;
+}
+
} // anonymous namespace
MaybeError ValidateTextureDescriptor(
@@ -563,7 +627,7 @@
"validating viewFormats[%u]", i);
}
- DAWN_TRY(ValidateTextureUsage(device, *descriptor, usage, format,
+ DAWN_TRY(ValidateTextureUsage(device, descriptor->dimension, usage, format,
std::move(allowedSharedTextureMemoryUsage)));
DAWN_TRY(ValidateTextureDimension(descriptor->dimension));
if (device->IsCompatibilityMode()) {
@@ -618,6 +682,8 @@
const Format* viewFormat;
DAWN_TRY_ASSIGN(viewFormat, device->GetInternalFormat(descriptor->format));
+ DAWN_TRY(ValidateTextureViewUsage(device, texture, descriptor->usage, viewFormat));
+
const auto aspect = SelectFormatAspects(format, descriptor->aspect);
DAWN_INVALID_IF(aspect == Aspect::None,
"Texture format (%s) does not have the texture view's selected aspect (%s).",
@@ -782,37 +848,8 @@
}
GetObjectTrackingList()->Track(this);
- // dawn:1569: If a texture with multiple array layers or mip levels is specified as a
- // texture attachment when this toggle is active, it needs to be given CopySrc | CopyDst usage
- // internally.
- bool applyAlwaysResolveIntoZeroLevelAndLayerToggle =
- device->IsToggleEnabled(Toggle::AlwaysResolveIntoZeroLevelAndLayer) &&
- (GetArrayLayers() > 1 || GetNumMipLevels() > 1) &&
- (GetInternalUsage() & wgpu::TextureUsage::RenderAttachment);
- if (applyAlwaysResolveIntoZeroLevelAndLayerToggle) {
- AddInternalUsage(wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst);
- }
-
- if (mInternalUsage & wgpu::TextureUsage::CopyDst) {
- if (CopyDstNeedsInternalRenderAttachmentUsage(device, *mFormat)) {
- AddInternalUsage(wgpu::TextureUsage::RenderAttachment);
- }
- }
- if (mInternalUsage & wgpu::TextureUsage::CopySrc) {
- if (CopySrcNeedsInternalTextureBindingUsage(device, *mFormat)) {
- AddInternalUsage(wgpu::TextureUsage::TextureBinding);
- }
- }
- if (mInternalUsage & wgpu::TextureUsage::StorageBinding) {
- AddInternalUsage(kReadOnlyStorageTexture | kWriteOnlyStorageTexture);
- }
-
- bool supportsMSAAPartialResolve = device->HasFeature(Feature::DawnPartialLoadResolveTexture) &&
- GetSampleCount() > 1 &&
- (GetUsage() & wgpu::TextureUsage::RenderAttachment);
- if (supportsMSAAPartialResolve) {
- AddInternalUsage(wgpu::TextureUsage::TextureBinding);
- }
+ mInternalUsage = AddInternalUsages(device, mInternalUsage, *mFormat, GetSampleCount(),
+ GetNumMipLevels(), GetArrayLayers());
}
TextureBase::~TextureBase() = default;
@@ -1304,7 +1341,15 @@
mDimension(descriptor->dimension),
mRange({ConvertViewAspect(*mFormat, descriptor->aspect),
{descriptor->baseArrayLayer, descriptor->arrayLayerCount},
- {descriptor->baseMipLevel, descriptor->mipLevelCount}}) {
+ {descriptor->baseMipLevel, descriptor->mipLevelCount}}),
+ mUsage(GetTextureViewUsage(texture->GetUsage(), descriptor->usage)),
+ mInternalUsage(
+ AddInternalUsages(GetDevice(),
+ GetTextureViewUsage(texture->GetInternalUsage(), descriptor->usage),
+ *mFormat,
+ texture->GetSampleCount(),
+ texture->GetNumMipLevels(),
+ texture->GetArrayLayers())) {
GetObjectTrackingList()->Track(this);
}
@@ -1396,6 +1441,16 @@
return GetTexture()->GetMipLevelSingleSubresourceVirtualSize(GetBaseMipLevel(), GetAspects());
}
+wgpu::TextureUsage TextureViewBase::GetUsage() const {
+ DAWN_ASSERT(!IsError());
+ return mUsage;
+}
+
+wgpu::TextureUsage TextureViewBase::GetInternalUsage() const {
+ DAWN_ASSERT(!IsError());
+ return mInternalUsage;
+}
+
ApiObjectList* TextureViewBase::GetObjectTrackingList() {
if (mTexture != nullptr) {
return mTexture->GetViewTrackingList();
diff --git a/src/dawn/native/Texture.h b/src/dawn/native/Texture.h
index caad0e2..e43602c 100644
--- a/src/dawn/native/Texture.h
+++ b/src/dawn/native/Texture.h
@@ -79,6 +79,11 @@
wgpu::TextureUsage::TextureBinding | kReadOnlyStorageTexture |
wgpu::TextureUsage::StorageBinding | kWriteOnlyStorageTexture;
+// Usages that are used to validate operations that act on texture views.
+static constexpr wgpu::TextureUsage kTextureViewOnlyUsages =
+ kShaderTextureUsages | kResolveTextureLoadAndStoreUsages |
+ wgpu::TextureUsage::TransientAttachment | wgpu::TextureUsage::StorageAttachment;
+
class TextureBase : public SharedResource {
public:
enum class ClearValue { Zero, NonZero };
@@ -243,6 +248,12 @@
// Returns the size of the texture's subresource at this view's base mip level and aspect.
Extent3D GetSingleSubresourceVirtualSize() const;
+ // |GetUsage| returns the usage with which the texture view was created using the base WebGPU
+ // API. The dawn-internal-usages extension may add additional usages. |GetInternalUsage|
+ // returns the union of base usage and the usages added by the extension.
+ wgpu::TextureUsage GetUsage() const;
+ wgpu::TextureUsage GetInternalUsage() const;
+
protected:
void DestroyImpl() override;
@@ -256,6 +267,8 @@
const raw_ref<const Format> mFormat;
wgpu::TextureViewDimension mDimension;
SubresourceRange mRange;
+ const wgpu::TextureUsage mUsage = wgpu::TextureUsage::None;
+ const wgpu::TextureUsage mInternalUsage = wgpu::TextureUsage::None;
};
} // namespace dawn::native
diff --git a/src/dawn/native/metal/TextureMTL.mm b/src/dawn/native/metal/TextureMTL.mm
index 4397701..9df2144 100644
--- a/src/dawn/native/metal/TextureMTL.mm
+++ b/src/dawn/native/metal/TextureMTL.mm
@@ -103,13 +103,14 @@
bool RequiresCreatingNewTextureView(
const TextureBase* texture,
+ wgpu::TextureUsage internalViewUsage,
const UnpackedPtr<TextureViewDescriptor>& textureViewDescriptor) {
constexpr wgpu::TextureUsage kShaderUsageNeedsView =
wgpu::TextureUsage::StorageBinding | wgpu::TextureUsage::TextureBinding;
constexpr wgpu::TextureUsage kUsageNeedsView = kShaderUsageNeedsView |
wgpu::TextureUsage::RenderAttachment |
wgpu::TextureUsage::StorageAttachment;
- if ((texture->GetInternalUsage() & kUsageNeedsView) == 0) {
+ if ((internalViewUsage & kUsageNeedsView) == 0) {
return false;
}
@@ -789,7 +790,7 @@
Aspect aspect = SelectFormatAspects(texture->GetFormat(), descriptor->aspect);
id<MTLTexture> mtlTexture = texture->GetMTLTexture(aspect);
- bool needsNewView = RequiresCreatingNewTextureView(texture, descriptor);
+ bool needsNewView = RequiresCreatingNewTextureView(texture, GetInternalUsage(), descriptor);
if (device->IsToggleEnabled(Toggle::MetalUseCombinedDepthStencilFormatForStencil8) &&
GetTexture()->GetFormat().format == wgpu::TextureFormat::Stencil8) {
// If MetalUseCombinedDepthStencilFormatForStencil8 is true and the format is Stencil8,
@@ -850,7 +851,7 @@
}
TextureView::AttachmentInfo TextureView::GetAttachmentInfo() const {
- DAWN_ASSERT(GetTexture()->GetInternalUsage() &
+ DAWN_ASSERT(GetInternalUsage() &
(wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::StorageAttachment));
// Use our own view if the formats do not match.
// If the formats do not match, format reinterpretation will be required.
diff --git a/src/dawn/native/vulkan/TextureVk.cpp b/src/dawn/native/vulkan/TextureVk.cpp
index 6c12824..006cd51 100644
--- a/src/dawn/native/vulkan/TextureVk.cpp
+++ b/src/dawn/native/vulkan/TextureVk.cpp
@@ -1607,6 +1607,7 @@
viewDesc.mipLevelCount = 1u;
viewDesc.baseArrayLayer = layer;
viewDesc.arrayLayerCount = 1u;
+ viewDesc.usage = wgpu::TextureUsage::RenderAttachment;
ColorAttachmentIndex ca0(uint8_t(0));
DAWN_TRY_ASSIGN(beginCmd.colorAttachments[ca0].view,
@@ -1781,8 +1782,7 @@
}
MaybeError TextureView::Initialize(const UnpackedPtr<TextureViewDescriptor>& descriptor) {
- if ((GetTexture()->GetInternalUsage() &
- ~(wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst)) == 0) {
+ if ((GetInternalUsage() & ~(wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst)) == 0) {
// If the texture view has no other usage than CopySrc and CopyDst, then it can't
// actually be used as a render pass attachment or sampled/storage texture. The Vulkan
// validation errors warn if you create such a vkImageView, so return early.
@@ -1797,15 +1797,9 @@
Device* device = ToBackend(GetTexture()->GetDevice());
VkImageViewCreateInfo createInfo = GetCreateInfo(descriptor->format, descriptor->dimension);
- // Remove StorageBinding usage if the format doesn't support it.
- wgpu::TextureUsage usage = GetTexture()->GetInternalUsage();
- if (!GetFormat().supportsStorageUsage) {
- usage &= ~wgpu::TextureUsage::StorageBinding;
- }
-
VkImageViewUsageCreateInfo usageInfo = {};
usageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO;
- usageInfo.usage = VulkanImageUsage(device, usage, GetFormat());
+ usageInfo.usage = VulkanImageUsage(device, GetInternalUsage(), GetFormat());
createInfo.pNext = &usageInfo;
VkSamplerYcbcrConversionInfo samplerYCbCrInfo = {};
diff --git a/src/dawn/node/binding/GPUTexture.cpp b/src/dawn/node/binding/GPUTexture.cpp
index d2668f8..c13586b 100644
--- a/src/dawn/node/binding/GPUTexture.cpp
+++ b/src/dawn/node/binding/GPUTexture.cpp
@@ -62,7 +62,9 @@
!conv(desc.arrayLayerCount, descriptor.arrayLayerCount) || //
!conv(desc.format, descriptor.format) || //
!conv(desc.dimension, descriptor.dimension) || //
- !conv(desc.aspect, descriptor.aspect) || !conv(desc.label, descriptor.label)) {
+ !conv(desc.aspect, descriptor.aspect) || //
+ !conv(desc.label, descriptor.label) || //
+ !conv(desc.usage, descriptor.usage)) {
return {};
}
return interop::GPUTextureView::Create<GPUTextureView>(env, desc, texture_.CreateView(&desc));
diff --git a/src/dawn/tests/end2end/TextureViewTests.cpp b/src/dawn/tests/end2end/TextureViewTests.cpp
index af00dab..7b3878a 100644
--- a/src/dawn/tests/end2end/TextureViewTests.cpp
+++ b/src/dawn/tests/end2end/TextureViewTests.cpp
@@ -166,6 +166,7 @@
mDefaultTextureViewDescriptor.mipLevelCount = mipLevelCount;
mDefaultTextureViewDescriptor.baseArrayLayer = 0;
mDefaultTextureViewDescriptor.arrayLayerCount = arrayLayerCount;
+ mDefaultTextureViewDescriptor.usage = kUsage;
// Create a texture with pixel = (0, 0, 0, level * 10 + layer + 1) at level `level` and
// layer `layer`.
diff --git a/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp b/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
index eb59fa3..e3032a3 100644
--- a/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/BindGroupValidationTests.cpp
@@ -460,10 +460,30 @@
utils::MakeBindGroup(device, layout, {{0, mSampledTextureView}});
// Make an render attachment texture and try to set it for a SampledTexture binding
- wgpu::Texture outputTexture =
- CreateTexture(wgpu::TextureUsage::RenderAttachment, wgpu::TextureFormat::RGBA8Unorm, 1);
- wgpu::TextureView outputTextureView = outputTexture.CreateView();
- ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, outputTextureView}}));
+ {
+ wgpu::Texture outputTexture =
+ CreateTexture(wgpu::TextureUsage::RenderAttachment, wgpu::TextureFormat::RGBA8Unorm, 1);
+ wgpu::TextureView outputTextureView = outputTexture.CreateView();
+ ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, outputTextureView}}));
+ }
+
+ // Make a sampled/render attachment texture and a view without sampling and attempt to bind it
+ {
+ wgpu::Texture outputTexture =
+ CreateTexture(wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding,
+ wgpu::TextureFormat::RGBA8Unorm, 1);
+ wgpu::TextureViewDescriptor viewDescriptor;
+ viewDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
+ viewDescriptor.dimension = wgpu::TextureViewDimension::e2D;
+ viewDescriptor.baseMipLevel = 0;
+ viewDescriptor.mipLevelCount = 1;
+ viewDescriptor.baseArrayLayer = 0;
+ viewDescriptor.arrayLayerCount = 1;
+ viewDescriptor.usage = wgpu::TextureUsage::RenderAttachment;
+
+ wgpu::TextureView outputTextureView = outputTexture.CreateView(&viewDescriptor);
+ ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, outputTextureView}}));
+ }
}
// Check that a storage texture binding must have the correct usage
diff --git a/src/dawn/tests/unittests/validation/TextureViewValidationTests.cpp b/src/dawn/tests/unittests/validation/TextureViewValidationTests.cpp
index f56277d..8f1fa64 100644
--- a/src/dawn/tests/unittests/validation/TextureViewValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/TextureViewValidationTests.cpp
@@ -945,6 +945,59 @@
ASSERT_DEVICE_ERROR(utils::MakeBindGroup(device, layout, {{0, view}}));
}
+// Tests that texture view usage is validated for the texture view format and is compatible with the
+// source texture usages
+TEST_F(TextureViewValidationTest, Usage) {
+ wgpu::TextureFormat viewFormats[] = {wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureFormat::RGBA8UnormSrgb};
+
+ wgpu::TextureDescriptor textureDescriptor;
+ textureDescriptor.dimension = wgpu::TextureDimension::e2D;
+ textureDescriptor.size.width = kWidth;
+ textureDescriptor.size.height = kHeight;
+ textureDescriptor.sampleCount = 1;
+ textureDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
+ textureDescriptor.mipLevelCount = 1;
+ textureDescriptor.usage = wgpu::TextureUsage::TextureBinding |
+ wgpu::TextureUsage::RenderAttachment |
+ wgpu::TextureUsage::StorageBinding;
+ textureDescriptor.viewFormats = viewFormats;
+ textureDescriptor.viewFormatCount = 2;
+ wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
+
+ wgpu::TextureViewDescriptor base2DTextureViewDescriptor;
+ base2DTextureViewDescriptor.format = kDefaultTextureFormat;
+ base2DTextureViewDescriptor.dimension = wgpu::TextureViewDimension::e2D;
+ base2DTextureViewDescriptor.baseMipLevel = 0;
+ base2DTextureViewDescriptor.mipLevelCount = 1;
+ base2DTextureViewDescriptor.baseArrayLayer = 0;
+ base2DTextureViewDescriptor.arrayLayerCount = 1;
+
+ // It is an error to request a usage outside of the source texture's usage
+ {
+ wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
+ descriptor.usage |= wgpu::TextureUsage::CopyDst;
+ ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
+ }
+
+ // It is an error to create a view with RGBA8UnormSrgb and default usage which includes
+ // StorageBinding
+ {
+ wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
+ descriptor.format = wgpu::TextureFormat::RGBA8UnormSrgb;
+ ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor));
+ }
+
+ // A view can be created for RGBA8UnormSrgb with a compatible subset of usages
+ {
+ wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor;
+ descriptor.format = wgpu::TextureFormat::RGBA8UnormSrgb;
+ descriptor.usage =
+ wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment;
+ texture.CreateView(&descriptor);
+ }
+}
+
class D32S8TextureViewValidationTests : public ValidationTest {
protected:
std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
diff --git a/third_party/gpuweb b/third_party/gpuweb
index 2dc56f2..010f5c9 160000
--- a/third_party/gpuweb
+++ b/third_party/gpuweb
@@ -1 +1 @@
-Subproject commit 2dc56f29788a2b8087ef0de87379c0b40a6f2dd5
+Subproject commit 010f5c9ddfd21bc963025979d08eb7489058c1c7