Add Debug Label Functionality For D3D12/Vk Buffers & Textures
Adds a generic SetDebugName utility for D3D12 and Vulkan. Passes down
debug label set by user for buffers and textures to be labeled by the
appropriate backend method.
Bug: dawn:840
Change-Id: I7158b537a6e37fdf733645e6830dc33833ee683e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/61588
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Brandon Jones (Intel) <brandon1.jones@intel.com>
diff --git a/src/dawn_native/Buffer.cpp b/src/dawn_native/Buffer.cpp
index 3e1b72f..d9ca585 100644
--- a/src/dawn_native/Buffer.cpp
+++ b/src/dawn_native/Buffer.cpp
@@ -128,7 +128,7 @@
// Buffer
BufferBase::BufferBase(DeviceBase* device, const BufferDescriptor* descriptor)
- : ObjectBase(device),
+ : ObjectBase(device, descriptor->label),
mSize(descriptor->size),
mUsage(descriptor->usage),
mState(BufferState::Unmapped) {
diff --git a/src/dawn_native/DawnNative.cpp b/src/dawn_native/DawnNative.cpp
index 1ac8d98..15fd697 100644
--- a/src/dawn_native/DawnNative.cpp
+++ b/src/dawn_native/DawnNative.cpp
@@ -225,4 +225,9 @@
ExternalImageExportInfo::ExternalImageExportInfo(ExternalImageType type) : type(type) {
}
+ const char* GetObjectLabelForTesting(void* objectHandle) {
+ ObjectBase* object = reinterpret_cast<ObjectBase*>(objectHandle);
+ return object->GetLabel().c_str();
+ }
+
} // namespace dawn_native
diff --git a/src/dawn_native/ObjectBase.cpp b/src/dawn_native/ObjectBase.cpp
index 8b4731f..05ba33e 100644
--- a/src/dawn_native/ObjectBase.cpp
+++ b/src/dawn_native/ObjectBase.cpp
@@ -22,10 +22,20 @@
ObjectBase::ObjectBase(DeviceBase* device) : RefCounted(kNotErrorPayload), mDevice(device) {
}
+ ObjectBase::ObjectBase(DeviceBase* device, const char* label) : ObjectBase(device) {
+ if (label) {
+ mLabel = label;
+ }
+ }
+
ObjectBase::ObjectBase(DeviceBase* device, ErrorTag)
: RefCounted(kErrorPayload), mDevice(device) {
}
+ const std::string& ObjectBase::GetLabel() {
+ return mLabel;
+ }
+
DeviceBase* ObjectBase::GetDevice() const {
return mDevice;
}
@@ -34,4 +44,12 @@
return GetRefCountPayload() == kErrorPayload;
}
+ void ObjectBase::APISetLabel(const char* label) {
+ mLabel = label;
+ SetLabelImpl();
+ }
+
+ void ObjectBase::SetLabelImpl() {
+ }
+
} // namespace dawn_native
diff --git a/src/dawn_native/ObjectBase.h b/src/dawn_native/ObjectBase.h
index 544ce1a..41a4dcf 100644
--- a/src/dawn_native/ObjectBase.h
+++ b/src/dawn_native/ObjectBase.h
@@ -17,6 +17,8 @@
#include "common/RefCounted.h"
+#include <string>
+
namespace dawn_native {
class DeviceBase;
@@ -27,15 +29,21 @@
static constexpr ErrorTag kError = {};
ObjectBase(DeviceBase* device);
+ ObjectBase(DeviceBase* device, const char* label);
ObjectBase(DeviceBase* device, ErrorTag tag);
DeviceBase* GetDevice() const;
+ const std::string& GetLabel();
bool IsError() const;
- protected:
- ~ObjectBase() override = default;
+ // Dawn API
+ void APISetLabel(const char* label);
private:
+ virtual void SetLabelImpl();
+
+ // TODO(dawn:840): Optimize memory footprint for objects that don't have labels.
+ std::string mLabel;
DeviceBase* mDevice;
};
diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp
index bf1ccff..1b9a708 100644
--- a/src/dawn_native/Texture.cpp
+++ b/src/dawn_native/Texture.cpp
@@ -433,7 +433,7 @@
TextureBase::TextureBase(DeviceBase* device,
const TextureDescriptor* descriptor,
TextureState state)
- : ObjectBase(device),
+ : ObjectBase(device, descriptor->label),
mDimension(descriptor->dimension),
mFormat(device->GetValidInternalFormat(descriptor->format)),
mSize(descriptor->size),
diff --git a/src/dawn_native/Toggles.cpp b/src/dawn_native/Toggles.cpp
index efd6519..7c40fe7 100644
--- a/src/dawn_native/Toggles.cpp
+++ b/src/dawn_native/Toggles.cpp
@@ -212,6 +212,11 @@
{"disable_symbol_renaming",
"Disables the WGSL symbol renaming so that names are preserved.",
"https://crbug.com/dawn/1016"}},
+ {Toggle::UseUserDefinedLabelsInBackend,
+ {"use_user_defined_labels_in_backend",
+ "Enables calls to SetLabel to be forwarded to backend-specific APIs that label "
+ "objects.",
+ "https://crbug.com/dawn/840"}},
// Dummy comment to separate the }} so it is clearer what to copy-paste to add a toggle.
}};
} // anonymous namespace
diff --git a/src/dawn_native/Toggles.h b/src/dawn_native/Toggles.h
index 9c11400..668086f 100644
--- a/src/dawn_native/Toggles.h
+++ b/src/dawn_native/Toggles.h
@@ -58,6 +58,7 @@
ForceWGSLStep,
DisableWorkgroupInit,
DisableSymbolRenaming,
+ UseUserDefinedLabelsInBackend,
EnumCount,
InvalidEnum = EnumCount,
diff --git a/src/dawn_native/d3d12/BufferD3D12.cpp b/src/dawn_native/d3d12/BufferD3D12.cpp
index 399a02c..67ebc47 100644
--- a/src/dawn_native/d3d12/BufferD3D12.cpp
+++ b/src/dawn_native/d3d12/BufferD3D12.cpp
@@ -24,6 +24,7 @@
#include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/HeapD3D12.h"
#include "dawn_native/d3d12/ResidencyManagerD3D12.h"
+#include "dawn_native/d3d12/UtilsD3D12.h"
namespace dawn_native { namespace d3d12 {
@@ -155,7 +156,7 @@
mResourceAllocation,
ToBackend(GetDevice())->AllocateMemory(heapType, resourceDescriptor, bufferUsage));
- DAWN_TRY(mResourceAllocation.SetDebugName("Dawn_Buffer"));
+ SetLabelImpl();
// The buffers with mappedAtCreation == true will be initialized in
// BufferBase::MapAtCreation().
@@ -446,6 +447,11 @@
return {};
}
+ void Buffer::SetLabelImpl() {
+ SetDebugName(ToBackend(GetDevice()), mResourceAllocation.GetD3D12Resource(), "Dawn_Buffer",
+ GetLabel());
+ }
+
MaybeError Buffer::InitializeToZero(CommandRecordingContext* commandContext) {
ASSERT(GetDevice()->IsToggleEnabled(Toggle::LazyClearResourceOnFirstUse));
ASSERT(!IsDataInitialized());
diff --git a/src/dawn_native/d3d12/BufferD3D12.h b/src/dawn_native/d3d12/BufferD3D12.h
index ed19efa..d6fcbbd 100644
--- a/src/dawn_native/d3d12/BufferD3D12.h
+++ b/src/dawn_native/d3d12/BufferD3D12.h
@@ -48,6 +48,8 @@
uint64_t size);
MaybeError EnsureDataInitializedAsDestination(CommandRecordingContext* commandContext,
const CopyTextureToBufferCmd* copy);
+ // Dawn API
+ void SetLabelImpl() override;
private:
Buffer(Device* device, const BufferDescriptor* descriptor);
diff --git a/src/dawn_native/d3d12/ResourceHeapAllocationD3D12.cpp b/src/dawn_native/d3d12/ResourceHeapAllocationD3D12.cpp
index 10a43d8..c7f8c68 100644
--- a/src/dawn_native/d3d12/ResourceHeapAllocationD3D12.cpp
+++ b/src/dawn_native/d3d12/ResourceHeapAllocationD3D12.cpp
@@ -40,11 +40,4 @@
D3D12_GPU_VIRTUAL_ADDRESS ResourceHeapAllocation::GetGPUPointer() const {
return mResource->GetGPUVirtualAddress();
}
-
- MaybeError ResourceHeapAllocation::SetDebugName(const char* name) {
- DAWN_TRY(CheckHRESULT(
- mResource->SetPrivateData(WKPDID_D3DDebugObjectName, std::strlen(name), name),
- "ID3D12Resource::SetName"));
- return {};
- }
}} // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/ResourceHeapAllocationD3D12.h b/src/dawn_native/d3d12/ResourceHeapAllocationD3D12.h
index 892a72c..7f1fe0a 100644
--- a/src/dawn_native/d3d12/ResourceHeapAllocationD3D12.h
+++ b/src/dawn_native/d3d12/ResourceHeapAllocationD3D12.h
@@ -35,7 +35,6 @@
ResourceHeapAllocation& operator=(const ResourceHeapAllocation&) = default;
void Invalidate() override;
- MaybeError SetDebugName(const char* name);
ID3D12Resource* GetD3D12Resource() const;
D3D12_GPU_VIRTUAL_ADDRESS GetGPUPointer() const;
diff --git a/src/dawn_native/d3d12/StagingBufferD3D12.cpp b/src/dawn_native/d3d12/StagingBufferD3D12.cpp
index 4c1e90b..d35622e 100644
--- a/src/dawn_native/d3d12/StagingBufferD3D12.cpp
+++ b/src/dawn_native/d3d12/StagingBufferD3D12.cpp
@@ -17,6 +17,7 @@
#include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/HeapD3D12.h"
#include "dawn_native/d3d12/ResidencyManagerD3D12.h"
+#include "dawn_native/d3d12/UtilsD3D12.h"
namespace dawn_native { namespace d3d12 {
@@ -47,7 +48,7 @@
DAWN_TRY(mDevice->GetResidencyManager()->LockAllocation(
ToBackend(mUploadHeap.GetResourceHeap())));
- DAWN_TRY(mUploadHeap.SetDebugName("Dawn_StagingBuffer"));
+ SetDebugName(mDevice, GetResource(), "Dawn_StagingBuffer");
return CheckHRESULT(GetResource()->Map(0, nullptr, &mMappedPointer), "ID3D12Resource::Map");
}
diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp
index 4968533..fcabcd0 100644
--- a/src/dawn_native/d3d12/TextureD3D12.cpp
+++ b/src/dawn_native/d3d12/TextureD3D12.cpp
@@ -482,7 +482,7 @@
// memory management.
mResourceAllocation = {info, 0, std::move(d3d12Texture), nullptr};
- DAWN_TRY(mResourceAllocation.SetDebugName("Dawn_ExternalTexture"));
+ SetLabelHelper("Dawn_ExternalTexture");
return {};
}
@@ -521,7 +521,7 @@
->AllocateMemory(D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor,
D3D12_RESOURCE_STATE_COMMON));
- DAWN_TRY(mResourceAllocation.SetDebugName("Dawn_InternalTexture"));
+ SetLabelImpl();
Device* device = ToBackend(GetDevice());
@@ -544,7 +544,8 @@
// memory management.
mResourceAllocation = {info, 0, std::move(d3d12Texture), nullptr};
- DAWN_TRY(mResourceAllocation.SetDebugName("Dawn_SwapChainTexture"));
+ SetLabelHelper("Dawn_SwapChainTexture");
+
return {};
}
@@ -1026,6 +1027,15 @@
return {};
}
+ void Texture::SetLabelHelper(const char* prefix) {
+ SetDebugName(ToBackend(GetDevice()), mResourceAllocation.GetD3D12Resource(), prefix,
+ GetLabel());
+ }
+
+ void Texture::SetLabelImpl() {
+ SetLabelHelper("Dawn_InternalTexture");
+ }
+
void Texture::EnsureSubresourceContentInitialized(CommandRecordingContext* commandContext,
const SubresourceRange& range) {
if (!ToBackend(GetDevice())->IsToggleEnabled(Toggle::LazyClearResourceOnFirstUse)) {
diff --git a/src/dawn_native/d3d12/TextureD3D12.h b/src/dawn_native/d3d12/TextureD3D12.h
index 0c1bb2e..c414a8a 100644
--- a/src/dawn_native/d3d12/TextureD3D12.h
+++ b/src/dawn_native/d3d12/TextureD3D12.h
@@ -98,8 +98,12 @@
bool isSwapChainTexture);
MaybeError InitializeAsSwapChainTexture(ComPtr<ID3D12Resource> d3d12Texture);
+ void SetLabelHelper(const char* prefix);
+
// Dawn API
+ void SetLabelImpl() override;
void DestroyImpl() override;
+
MaybeError ClearTexture(CommandRecordingContext* commandContext,
const SubresourceRange& range,
TextureBase::ClearValue clearValue);
diff --git a/src/dawn_native/d3d12/UtilsD3D12.cpp b/src/dawn_native/d3d12/UtilsD3D12.cpp
index b52dc0b..98f056b 100644
--- a/src/dawn_native/d3d12/UtilsD3D12.cpp
+++ b/src/dawn_native/d3d12/UtilsD3D12.cpp
@@ -18,6 +18,8 @@
#include "dawn_native/Format.h"
#include "dawn_native/d3d12/BufferD3D12.h"
#include "dawn_native/d3d12/CommandRecordingContext.h"
+#include "dawn_native/d3d12/D3D12Error.h"
+#include "dawn_native/d3d12/DeviceD3D12.h"
#include <stringapiset.h>
@@ -370,4 +372,16 @@
}
}
+ void SetDebugName(Device* device, ID3D12Object* object, const char* prefix, std::string label) {
+ if (label.empty() || !device->IsToggleEnabled(Toggle::UseUserDefinedLabelsInBackend)) {
+ object->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(prefix), prefix);
+ return;
+ }
+
+ std::string objectName = prefix;
+ objectName += "_";
+ objectName += label;
+ object->SetPrivateData(WKPDID_D3DDebugObjectName, objectName.length(), objectName.c_str());
+ }
+
}} // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/UtilsD3D12.h b/src/dawn_native/d3d12/UtilsD3D12.h
index fea27d5..2a3f3d5 100644
--- a/src/dawn_native/d3d12/UtilsD3D12.h
+++ b/src/dawn_native/d3d12/UtilsD3D12.h
@@ -81,6 +81,11 @@
Buffer* buffer,
const Extent3D& copySize);
+ void SetDebugName(Device* device,
+ ID3D12Object* object,
+ const char* prefix,
+ std::string label = "");
+
}} // namespace dawn_native::d3d12
#endif // DAWNNATIVE_D3D12_UTILSD3D12_H_
diff --git a/src/dawn_native/vulkan/BufferVk.cpp b/src/dawn_native/vulkan/BufferVk.cpp
index 8139b29..75a32fd 100644
--- a/src/dawn_native/vulkan/BufferVk.cpp
+++ b/src/dawn_native/vulkan/BufferVk.cpp
@@ -19,6 +19,7 @@
#include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/ResourceHeapVk.h"
#include "dawn_native/vulkan/ResourceMemoryAllocatorVk.h"
+#include "dawn_native/vulkan/UtilsVulkan.h"
#include "dawn_native/vulkan/VulkanError.h"
#include <cstring>
@@ -229,6 +230,9 @@
ClearBuffer(recordingContext, 0, clearOffset, clearSize);
}
}
+
+ SetLabelImpl();
+
return {};
}
@@ -374,6 +378,11 @@
}
}
+ void Buffer::SetLabelImpl() {
+ SetDebugName(ToBackend(GetDevice()), VK_OBJECT_TYPE_BUFFER,
+ reinterpret_cast<uint64_t&>(mHandle), "Dawn_Buffer", GetLabel());
+ }
+
void Buffer::InitializeToZero(CommandRecordingContext* recordingContext) {
ASSERT(GetDevice()->IsToggleEnabled(Toggle::LazyClearResourceOnFirstUse));
ASSERT(!IsDataInitialized());
diff --git a/src/dawn_native/vulkan/BufferVk.h b/src/dawn_native/vulkan/BufferVk.h
index 1c40140..3fcab60 100644
--- a/src/dawn_native/vulkan/BufferVk.h
+++ b/src/dawn_native/vulkan/BufferVk.h
@@ -49,6 +49,9 @@
void EnsureDataInitializedAsDestination(CommandRecordingContext* recordingContext,
const CopyTextureToBufferCmd* copy);
+ // Dawn API
+ void SetLabelImpl() override;
+
private:
~Buffer() override;
using BufferBase::BufferBase;
diff --git a/src/dawn_native/vulkan/StagingBufferVk.cpp b/src/dawn_native/vulkan/StagingBufferVk.cpp
index cf3129c..c78f0fc 100644
--- a/src/dawn_native/vulkan/StagingBufferVk.cpp
+++ b/src/dawn_native/vulkan/StagingBufferVk.cpp
@@ -17,6 +17,7 @@
#include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/ResourceHeapVk.h"
#include "dawn_native/vulkan/ResourceMemoryAllocatorVk.h"
+#include "dawn_native/vulkan/UtilsVulkan.h"
#include "dawn_native/vulkan/VulkanError.h"
namespace dawn_native { namespace vulkan {
@@ -57,6 +58,9 @@
return DAWN_INTERNAL_ERROR("Unable to map staging buffer.");
}
+ SetDebugName(mDevice, VK_OBJECT_TYPE_BUFFER, reinterpret_cast<uint64_t&>(mBuffer),
+ "Dawn_StagingBuffer");
+
return {};
}
diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp
index cbb2f2ce..f4be49a 100644
--- a/src/dawn_native/vulkan/TextureVk.cpp
+++ b/src/dawn_native/vulkan/TextureVk.cpp
@@ -577,6 +577,8 @@
GetAllSubresources(), TextureBase::ClearValue::NonZero));
}
+ SetLabelImpl();
+
return {};
}
@@ -611,11 +613,15 @@
baseCreateInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
DAWN_TRY_ASSIGN(mHandle, externalMemoryService->CreateImage(descriptor, baseCreateInfo));
+
+ SetLabelHelper("Dawn_ExternalTexture");
+
return {};
}
void Texture::InitializeForSwapChain(VkImage nativeImage) {
mHandle = nativeImage;
+ SetLabelHelper("Dawn_SwapChainTexture");
}
MaybeError Texture::BindExternalMemory(const ExternalImageDescriptorVk* descriptor,
@@ -720,6 +726,15 @@
DestroyInternal();
}
+ void Texture::SetLabelHelper(const char* prefix) {
+ SetDebugName(ToBackend(GetDevice()), VK_OBJECT_TYPE_IMAGE,
+ reinterpret_cast<uint64_t&>(mHandle), prefix, GetLabel());
+ }
+
+ void Texture::SetLabelImpl() {
+ SetLabelHelper("Dawn_InternalTexture");
+ }
+
void Texture::DestroyImpl() {
if (GetTextureState() == TextureState::OwnedInternal) {
Device* device = ToBackend(GetDevice());
diff --git a/src/dawn_native/vulkan/TextureVk.h b/src/dawn_native/vulkan/TextureVk.h
index e985c55..779d51b 100644
--- a/src/dawn_native/vulkan/TextureVk.h
+++ b/src/dawn_native/vulkan/TextureVk.h
@@ -93,6 +93,11 @@
VkImageLayout* releasedOldLayout,
VkImageLayout* releasedNewLayout);
+ void SetLabelHelper(const char* prefix);
+
+ // Dawn API
+ void SetLabelImpl() override;
+
private:
~Texture() override;
Texture(Device* device, const TextureDescriptor* descriptor, TextureState state);
diff --git a/src/dawn_native/vulkan/UtilsVulkan.cpp b/src/dawn_native/vulkan/UtilsVulkan.cpp
index c6952d4..eb46180 100644
--- a/src/dawn_native/vulkan/UtilsVulkan.cpp
+++ b/src/dawn_native/vulkan/UtilsVulkan.cpp
@@ -17,8 +17,10 @@
#include "common/Assert.h"
#include "dawn_native/EnumMaskIterator.h"
#include "dawn_native/Format.h"
+#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/Forward.h"
#include "dawn_native/vulkan/TextureVk.h"
+#include "dawn_native/vulkan/VulkanError.h"
namespace dawn_native { namespace vulkan {
@@ -162,4 +164,30 @@
return region;
}
+
+ void SetDebugName(Device* device,
+ VkObjectType objectType,
+ uint64_t objectHandle,
+ const char* prefix,
+ std::string label) {
+ if (device->GetGlobalInfo().HasExt(InstanceExt::DebugUtils)) {
+ VkDebugUtilsObjectNameInfoEXT objectNameInfo;
+ objectNameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+ objectNameInfo.pNext = nullptr;
+ objectNameInfo.objectType = objectType;
+ objectNameInfo.objectHandle = objectHandle;
+
+ if (label.empty() || !device->IsToggleEnabled(Toggle::UseUserDefinedLabelsInBackend)) {
+ objectNameInfo.pObjectName = prefix;
+ device->fn.SetDebugUtilsObjectNameEXT(device->GetVkDevice(), &objectNameInfo);
+ return;
+ }
+
+ std::string objectName = prefix;
+ objectName += "_";
+ objectName += label;
+ objectNameInfo.pObjectName = objectName.c_str();
+ device->fn.SetDebugUtilsObjectNameEXT(device->GetVkDevice(), &objectNameInfo);
+ }
+ }
}} // namespace dawn_native::vulkan
diff --git a/src/dawn_native/vulkan/UtilsVulkan.h b/src/dawn_native/vulkan/UtilsVulkan.h
index e57e3f4..23c36a9 100644
--- a/src/dawn_native/vulkan/UtilsVulkan.h
+++ b/src/dawn_native/vulkan/UtilsVulkan.h
@@ -21,6 +21,8 @@
namespace dawn_native { namespace vulkan {
+ class Device;
+
// A Helper type used to build a pNext chain of extension structs.
// Usage is:
// 1) Create instance, passing the address of the first struct in the
@@ -99,6 +101,12 @@
const TextureCopy& textureCopy,
const Extent3D& copySize);
+ void SetDebugName(Device* device,
+ VkObjectType objectType,
+ uint64_t objectHandle,
+ const char* prefix,
+ std::string label = "");
+
}} // namespace dawn_native::vulkan
#endif // DAWNNATIVE_VULKAN_UTILSVULKAN_H_
diff --git a/src/include/dawn_native/DawnNative.h b/src/include/dawn_native/DawnNative.h
index 9baf128..a0a6229 100644
--- a/src/include/dawn_native/DawnNative.h
+++ b/src/include/dawn_native/DawnNative.h
@@ -248,6 +248,8 @@
ExternalImageExportInfo(ExternalImageType type);
};
+ DAWN_NATIVE_EXPORT const char* GetObjectLabelForTesting(void* objectHandle);
+
} // namespace dawn_native
#endif // DAWNNATIVE_DAWNNATIVE_H_
diff --git a/src/tests/BUILD.gn b/src/tests/BUILD.gn
index 3ff1698..8aa80f8 100644
--- a/src/tests/BUILD.gn
+++ b/src/tests/BUILD.gn
@@ -203,6 +203,7 @@
"unittests/validation/GetBindGroupLayoutValidationTests.cpp",
"unittests/validation/IndexBufferValidationTests.cpp",
"unittests/validation/InternalUsageValidationTests.cpp",
+ "unittests/validation/LabelTests.cpp",
"unittests/validation/MinimumBufferSizeValidationTests.cpp",
"unittests/validation/MultipleDeviceTests.cpp",
"unittests/validation/QueryValidationTests.cpp",
diff --git a/src/tests/unittests/validation/LabelTests.cpp b/src/tests/unittests/validation/LabelTests.cpp
new file mode 100644
index 0000000..4cb2a24
--- /dev/null
+++ b/src/tests/unittests/validation/LabelTests.cpp
@@ -0,0 +1,86 @@
+// Copyright 2021 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 WvecANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string>
+#include "tests/unittests/validation/ValidationTest.h"
+
+class LabelTest : public ValidationTest {};
+
+TEST_F(LabelTest, Buffer) {
+ DAWN_SKIP_TEST_IF(UsesWire());
+ std::string label = "test";
+ wgpu::BufferDescriptor descriptor;
+ descriptor.size = 4;
+ descriptor.usage = wgpu::BufferUsage::Uniform;
+
+ // The label should be empty if one was not set.
+ {
+ wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
+ std::string readbackLabel = dawn_native::GetObjectLabelForTesting(buffer.Get());
+ ASSERT_TRUE(readbackLabel.empty());
+ }
+
+ // Test setting a label through API
+ {
+ wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
+ buffer.SetLabel(label.c_str());
+ std::string readbackLabel = dawn_native::GetObjectLabelForTesting(buffer.Get());
+ ASSERT_EQ(label, readbackLabel);
+ }
+
+ // Test setting a label through the descriptor.
+ {
+ descriptor.label = label.c_str();
+ wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
+ std::string readbackLabel = dawn_native::GetObjectLabelForTesting(buffer.Get());
+ ASSERT_EQ(label, readbackLabel);
+ }
+}
+
+TEST_F(LabelTest, Texture) {
+ DAWN_SKIP_TEST_IF(UsesWire());
+ std::string label = "test";
+ wgpu::TextureDescriptor descriptor;
+ descriptor.size.width = 1;
+ descriptor.size.height = 1;
+ descriptor.size.depthOrArrayLayers = 1;
+ descriptor.mipLevelCount = 1;
+ descriptor.sampleCount = 1;
+ descriptor.dimension = wgpu::TextureDimension::e2D;
+ descriptor.format = wgpu::TextureFormat::RGBA8Uint;
+ descriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
+
+ // The label should be empty if one was not set.
+ {
+ wgpu::Texture texture = device.CreateTexture(&descriptor);
+ std::string readbackLabel = dawn_native::GetObjectLabelForTesting(texture.Get());
+ ASSERT_TRUE(readbackLabel.empty());
+ }
+
+ // Test setting a label through API
+ {
+ wgpu::Texture texture = device.CreateTexture(&descriptor);
+ texture.SetLabel(label.c_str());
+ std::string readbackLabel = dawn_native::GetObjectLabelForTesting(texture.Get());
+ ASSERT_EQ(label, readbackLabel);
+ }
+
+ // Test setting a label through the descriptor.
+ {
+ descriptor.label = label.c_str();
+ wgpu::Texture texture = device.CreateTexture(&descriptor);
+ std::string readbackLabel = dawn_native::GetObjectLabelForTesting(texture.Get());
+ ASSERT_EQ(label, readbackLabel);
+ }
+}
\ No newline at end of file