Improve validation messages for surface/swap chain
Updates validation messages with more contextual information in: - ChainUtils.h - Device.cpp - SpirvValidation.cpp - Surface.cpp - SwapChain.cpp Bug: dawn:563 Change-Id: I486512791caaf1acf4607539aa5ad11daf1ab9be Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/67140 Commit-Queue: Brandon Jones <bajones@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
853c61d0a6
commit
7dc906a4c9
|
@ -36,9 +36,8 @@ namespace dawn_native {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
MaybeError ValidateSingleSTypeInner(const ChainedStruct* chain, T sType) {
|
MaybeError ValidateSingleSTypeInner(const ChainedStruct* chain, T sType) {
|
||||||
if (chain->sType != sType) {
|
DAWN_INVALID_IF(chain->sType != sType,
|
||||||
return DAWN_VALIDATION_ERROR("Unsupported sType");
|
"Unsupported sType (%s). Expected (%s)", chain->sType, sType);
|
||||||
}
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +56,8 @@ namespace dawn_native {
|
||||||
if (chain == nullptr) {
|
if (chain == nullptr) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (chain->nextInChain != nullptr) {
|
DAWN_INVALID_IF(chain->nextInChain != nullptr,
|
||||||
return DAWN_VALIDATION_ERROR("Chain can only contain a single chained struct");
|
"Chain can only contain a single chained struct.");
|
||||||
}
|
|
||||||
return ValidateSingleSTypeInner(chain, sType);
|
return ValidateSingleSTypeInner(chain, sType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,9 +68,8 @@ namespace dawn_native {
|
||||||
if (chain == nullptr) {
|
if (chain == nullptr) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (chain->nextInChain != nullptr) {
|
DAWN_INVALID_IF(chain->nextInChain != nullptr,
|
||||||
return DAWN_VALIDATION_ERROR("Chain can only contain a single chained struct");
|
"Chain can only contain a single chained struct.");
|
||||||
}
|
|
||||||
return ValidateSingleSTypeInner(chain, sType, sTypes...);
|
return ValidateSingleSTypeInner(chain, sType, sTypes...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1444,7 +1444,8 @@ namespace dawn_native {
|
||||||
const SwapChainDescriptor* descriptor) {
|
const SwapChainDescriptor* descriptor) {
|
||||||
DAWN_TRY(ValidateIsAlive());
|
DAWN_TRY(ValidateIsAlive());
|
||||||
if (IsValidationEnabled()) {
|
if (IsValidationEnabled()) {
|
||||||
DAWN_TRY(ValidateSwapChainDescriptor(this, surface, descriptor));
|
DAWN_TRY_CONTEXT(ValidateSwapChainDescriptor(this, surface, descriptor),
|
||||||
|
"validating %s", descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(dawn:269): Remove this code path once implementation-based swapchains are removed.
|
// TODO(dawn:269): Remove this code path once implementation-based swapchains are removed.
|
||||||
|
|
|
@ -65,10 +65,8 @@ namespace dawn_native {
|
||||||
device->EmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str());
|
device->EmitLog(WGPULoggingType_Info, dumpedMsg.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!valid) {
|
DAWN_INVALID_IF(!valid,
|
||||||
return DAWN_VALIDATION_ERROR(
|
|
||||||
"Produced invalid SPIRV. Please file a bug at https://crbug.com/tint.");
|
"Produced invalid SPIRV. Please file a bug at https://crbug.com/tint.");
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,9 +36,9 @@ namespace dawn_native {
|
||||||
|
|
||||||
MaybeError ValidateSurfaceDescriptor(const InstanceBase* instance,
|
MaybeError ValidateSurfaceDescriptor(const InstanceBase* instance,
|
||||||
const SurfaceDescriptor* descriptor) {
|
const SurfaceDescriptor* descriptor) {
|
||||||
if (descriptor->nextInChain == nullptr) {
|
DAWN_INVALID_IF(descriptor->nextInChain == nullptr,
|
||||||
return DAWN_VALIDATION_ERROR("Surface cannot be created with just the base descriptor");
|
"Surface cannot be created with %s. nextInChain is not specified.",
|
||||||
}
|
descriptor);
|
||||||
|
|
||||||
DAWN_TRY(ValidateSingleSType(descriptor->nextInChain,
|
DAWN_TRY(ValidateSingleSType(descriptor->nextInChain,
|
||||||
wgpu::SType::SurfaceDescriptorFromMetalLayer,
|
wgpu::SType::SurfaceDescriptorFromMetalLayer,
|
||||||
|
@ -52,9 +52,8 @@ namespace dawn_native {
|
||||||
FindInChain(descriptor->nextInChain, &metalDesc);
|
FindInChain(descriptor->nextInChain, &metalDesc);
|
||||||
if (metalDesc) {
|
if (metalDesc) {
|
||||||
// Check that the layer is a CAMetalLayer (or a derived class).
|
// Check that the layer is a CAMetalLayer (or a derived class).
|
||||||
if (!InheritsFromCAMetalLayer(metalDesc->layer)) {
|
DAWN_INVALID_IF(!InheritsFromCAMetalLayer(metalDesc->layer),
|
||||||
return DAWN_VALIDATION_ERROR("layer must be a CAMetalLayer");
|
"Layer must be a CAMetalLayer");
|
||||||
}
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
#endif // defined(DAWN_ENABLE_BACKEND_METAL)
|
#endif // defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
@ -64,9 +63,7 @@ namespace dawn_native {
|
||||||
const SurfaceDescriptorFromWindowsHWND* hwndDesc = nullptr;
|
const SurfaceDescriptorFromWindowsHWND* hwndDesc = nullptr;
|
||||||
FindInChain(descriptor->nextInChain, &hwndDesc);
|
FindInChain(descriptor->nextInChain, &hwndDesc);
|
||||||
if (hwndDesc) {
|
if (hwndDesc) {
|
||||||
if (IsWindow(static_cast<HWND>(hwndDesc->hwnd)) == 0) {
|
DAWN_INVALID_IF(IsWindow(static_cast<HWND>(hwndDesc->hwnd)) == 0, "Invalid HWND");
|
||||||
return DAWN_VALIDATION_ERROR("Invalid HWND");
|
|
||||||
}
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
# endif // defined(DAWN_PLATFORM_WIN32)
|
# endif // defined(DAWN_PLATFORM_WIN32)
|
||||||
|
@ -75,11 +72,10 @@ namespace dawn_native {
|
||||||
if (coreWindowDesc) {
|
if (coreWindowDesc) {
|
||||||
// Validate the coreWindow by query for ICoreWindow interface
|
// Validate the coreWindow by query for ICoreWindow interface
|
||||||
ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow;
|
ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow;
|
||||||
if (coreWindowDesc->coreWindow == nullptr ||
|
DAWN_INVALID_IF(coreWindowDesc->coreWindow == nullptr ||
|
||||||
FAILED(static_cast<IUnknown*>(coreWindowDesc->coreWindow)
|
FAILED(static_cast<IUnknown*>(coreWindowDesc->coreWindow)
|
||||||
->QueryInterface(IID_PPV_ARGS(&coreWindow)))) {
|
->QueryInterface(IID_PPV_ARGS(&coreWindow))),
|
||||||
return DAWN_VALIDATION_ERROR("Invalid CoreWindow");
|
"Invalid CoreWindow");
|
||||||
}
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const SurfaceDescriptorFromWindowsSwapChainPanel* swapChainPanelDesc = nullptr;
|
const SurfaceDescriptorFromWindowsSwapChainPanel* swapChainPanelDesc = nullptr;
|
||||||
|
@ -87,11 +83,10 @@ namespace dawn_native {
|
||||||
if (swapChainPanelDesc) {
|
if (swapChainPanelDesc) {
|
||||||
// Validate the swapChainPanel by querying for ISwapChainPanel interface
|
// Validate the swapChainPanel by querying for ISwapChainPanel interface
|
||||||
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
|
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
|
||||||
if (swapChainPanelDesc->swapChainPanel == nullptr ||
|
DAWN_INVALID_IF(swapChainPanelDesc->swapChainPanel == nullptr ||
|
||||||
FAILED(static_cast<IUnknown*>(swapChainPanelDesc->swapChainPanel)
|
FAILED(static_cast<IUnknown*>(swapChainPanelDesc->swapChainPanel)
|
||||||
->QueryInterface(IID_PPV_ARGS(&swapChainPanel)))) {
|
->QueryInterface(IID_PPV_ARGS(&swapChainPanel))),
|
||||||
return DAWN_VALIDATION_ERROR("Invalid SwapChainPanel");
|
"Invalid SwapChainPanel");
|
||||||
}
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
#endif // defined(DAWN_PLATFORM_WINDOWS)
|
#endif // defined(DAWN_PLATFORM_WINDOWS)
|
||||||
|
@ -111,14 +106,13 @@ namespace dawn_native {
|
||||||
xDesc->window, &attributes);
|
xDesc->window, &attributes);
|
||||||
XSetErrorHandler(oldErrorHandler);
|
XSetErrorHandler(oldErrorHandler);
|
||||||
|
|
||||||
if (status == 0) {
|
DAWN_INVALID_IF(status == 0, "Invalid X Window");
|
||||||
return DAWN_VALIDATION_ERROR("Invalid X Window");
|
|
||||||
}
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
#endif // defined(DAWN_USE_X11)
|
#endif // defined(DAWN_USE_X11)
|
||||||
|
|
||||||
return DAWN_VALIDATION_ERROR("Unsupported sType");
|
return DAWN_FORMAT_VALIDATION_ERROR("Unsupported sType (%s)",
|
||||||
|
descriptor->nextInChain->sType);
|
||||||
}
|
}
|
||||||
|
|
||||||
Surface::Surface(InstanceBase* instance, const SurfaceDescriptor* descriptor)
|
Surface::Surface(InstanceBase* instance, const SurfaceDescriptor* descriptor)
|
||||||
|
|
|
@ -36,16 +36,19 @@ namespace dawn_native {
|
||||||
wgpu::TextureUsage allowedUsage,
|
wgpu::TextureUsage allowedUsage,
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
uint32_t height) override {
|
uint32_t height) override {
|
||||||
GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("error swapchain"));
|
GetDevice()->ConsumedError(
|
||||||
|
DAWN_FORMAT_VALIDATION_ERROR("%s is an error swapchain.", this));
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureViewBase* APIGetCurrentTextureView() override {
|
TextureViewBase* APIGetCurrentTextureView() override {
|
||||||
GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("error swapchain"));
|
GetDevice()->ConsumedError(
|
||||||
|
DAWN_FORMAT_VALIDATION_ERROR("%s is an error swapchain.", this));
|
||||||
return TextureViewBase::MakeError(GetDevice());
|
return TextureViewBase::MakeError(GetDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
void APIPresent() override {
|
void APIPresent() override {
|
||||||
GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR("error swapchain"));
|
GetDevice()->ConsumedError(
|
||||||
|
DAWN_FORMAT_VALIDATION_ERROR("%s is an error swapchain.", this));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,45 +58,43 @@ namespace dawn_native {
|
||||||
const Surface* surface,
|
const Surface* surface,
|
||||||
const SwapChainDescriptor* descriptor) {
|
const SwapChainDescriptor* descriptor) {
|
||||||
if (descriptor->implementation != 0) {
|
if (descriptor->implementation != 0) {
|
||||||
if (surface != nullptr) {
|
DAWN_INVALID_IF(surface != nullptr,
|
||||||
return DAWN_VALIDATION_ERROR(
|
|
||||||
"Exactly one of surface or implementation must be set");
|
"Exactly one of surface or implementation must be set");
|
||||||
}
|
|
||||||
|
|
||||||
DawnSwapChainImplementation* impl =
|
DawnSwapChainImplementation* impl =
|
||||||
reinterpret_cast<DawnSwapChainImplementation*>(descriptor->implementation);
|
reinterpret_cast<DawnSwapChainImplementation*>(descriptor->implementation);
|
||||||
|
|
||||||
if (!impl->Init || !impl->Destroy || !impl->Configure || !impl->GetNextTexture ||
|
DAWN_INVALID_IF(!impl->Init || !impl->Destroy || !impl->Configure ||
|
||||||
!impl->Present) {
|
!impl->GetNextTexture || !impl->Present,
|
||||||
return DAWN_VALIDATION_ERROR("Implementation is incomplete");
|
"Implementation is incomplete");
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (surface == nullptr) {
|
DAWN_INVALID_IF(surface == nullptr,
|
||||||
return DAWN_VALIDATION_ERROR(
|
|
||||||
"At least one of surface or implementation must be set");
|
"At least one of surface or implementation must be set");
|
||||||
}
|
|
||||||
|
|
||||||
DAWN_TRY(ValidatePresentMode(descriptor->presentMode));
|
DAWN_TRY(ValidatePresentMode(descriptor->presentMode));
|
||||||
|
|
||||||
// TODO(crbug.com/dawn/160): Lift this restriction once
|
// TODO(crbug.com/dawn/160): Lift this restriction once
|
||||||
// wgpu::Instance::GetPreferredSurfaceFormat is implemented.
|
// wgpu::Instance::GetPreferredSurfaceFormat is implemented.
|
||||||
if (descriptor->format != wgpu::TextureFormat::BGRA8Unorm) {
|
DAWN_INVALID_IF(descriptor->format != wgpu::TextureFormat::BGRA8Unorm,
|
||||||
return DAWN_VALIDATION_ERROR("Format must (currently) be BGRA8Unorm");
|
"Format (%s) is not %s, which is (currently) the only accepted format.",
|
||||||
}
|
descriptor->format, wgpu::TextureFormat::BGRA8Unorm);
|
||||||
|
|
||||||
if (descriptor->usage != wgpu::TextureUsage::RenderAttachment) {
|
DAWN_INVALID_IF(descriptor->usage != wgpu::TextureUsage::RenderAttachment,
|
||||||
return DAWN_VALIDATION_ERROR("Usage must (currently) be RenderAttachment");
|
"Usage (%s) is not %s, which is (currently) the only accepted usage.",
|
||||||
}
|
descriptor->usage, wgpu::TextureUsage::RenderAttachment);
|
||||||
|
|
||||||
if (descriptor->width == 0 || descriptor->height == 0) {
|
DAWN_INVALID_IF(descriptor->width == 0 || descriptor->height == 0,
|
||||||
return DAWN_VALIDATION_ERROR("Swapchain size can't be empty");
|
"Swap Chain size (width: %u, height: %u) is empty.", descriptor->width,
|
||||||
}
|
descriptor->height);
|
||||||
|
|
||||||
if (descriptor->width > device->GetLimits().v1.maxTextureDimension2D ||
|
DAWN_INVALID_IF(
|
||||||
descriptor->height > device->GetLimits().v1.maxTextureDimension2D) {
|
descriptor->width > device->GetLimits().v1.maxTextureDimension2D ||
|
||||||
return DAWN_VALIDATION_ERROR("Swapchain size too big");
|
descriptor->height > device->GetLimits().v1.maxTextureDimension2D,
|
||||||
}
|
"Swap Chain size (width: %u, height: %u) is greater than the maximum 2D texture "
|
||||||
|
"size (width: %u, height: %u).",
|
||||||
|
descriptor->width, descriptor->height, device->GetLimits().v1.maxTextureDimension2D,
|
||||||
|
device->GetLimits().v1.maxTextureDimension2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -230,9 +231,9 @@ namespace dawn_native {
|
||||||
DAWN_TRY(ValidateTextureUsage(allowedUsage));
|
DAWN_TRY(ValidateTextureUsage(allowedUsage));
|
||||||
DAWN_TRY(ValidateTextureFormat(format));
|
DAWN_TRY(ValidateTextureFormat(format));
|
||||||
|
|
||||||
if (width == 0 || height == 0) {
|
DAWN_INVALID_IF(width == 0 || height == 0,
|
||||||
return DAWN_VALIDATION_ERROR("Swap chain cannot be configured to zero size");
|
"Configuration size (width: %u, height: %u) for %s is empty.", width,
|
||||||
}
|
height, this);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -241,10 +242,9 @@ namespace dawn_native {
|
||||||
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
||||||
DAWN_TRY(GetDevice()->ValidateObject(this));
|
DAWN_TRY(GetDevice()->ValidateObject(this));
|
||||||
|
|
||||||
if (mWidth == 0) {
|
|
||||||
// If width is 0, it implies swap chain has never been configured
|
// If width is 0, it implies swap chain has never been configured
|
||||||
return DAWN_VALIDATION_ERROR("Swap chain needs to be configured before GetNextTexture");
|
DAWN_INVALID_IF(mWidth == 0, "%s was not configured prior to calling GetNextTexture.",
|
||||||
}
|
this);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -253,10 +253,10 @@ namespace dawn_native {
|
||||||
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
||||||
DAWN_TRY(GetDevice()->ValidateObject(this));
|
DAWN_TRY(GetDevice()->ValidateObject(this));
|
||||||
|
|
||||||
if (mCurrentTextureView == nullptr) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR(
|
mCurrentTextureView == nullptr,
|
||||||
"Cannot call present without a GetCurrentTextureView call for this frame");
|
"GetCurrentTextureView was not called on %s this frame prior to calling Present.",
|
||||||
}
|
this);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -302,7 +302,7 @@ namespace dawn_native {
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
uint32_t height) {
|
uint32_t height) {
|
||||||
GetDevice()->ConsumedError(
|
GetDevice()->ConsumedError(
|
||||||
DAWN_VALIDATION_ERROR("Configure is invalid for surface-based swapchains"));
|
DAWN_FORMAT_VALIDATION_ERROR("Configure is invalid for surface-based swapchains."));
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureViewBase* NewSwapChainBase::APIGetCurrentTextureView() {
|
TextureViewBase* NewSwapChainBase::APIGetCurrentTextureView() {
|
||||||
|
@ -386,13 +386,12 @@ namespace dawn_native {
|
||||||
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
||||||
DAWN_TRY(GetDevice()->ValidateObject(this));
|
DAWN_TRY(GetDevice()->ValidateObject(this));
|
||||||
|
|
||||||
if (!mAttached) {
|
DAWN_INVALID_IF(!mAttached, "Cannot call Present called on detached %s.", this);
|
||||||
return DAWN_VALIDATION_ERROR("Presenting on detached swapchain");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCurrentTextureView == nullptr) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR("Presenting without prior GetCurrentTextureView");
|
mCurrentTextureView == nullptr,
|
||||||
}
|
"GetCurrentTextureView was not called on %s this frame prior to calling Present.",
|
||||||
|
this);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -401,9 +400,7 @@ namespace dawn_native {
|
||||||
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
DAWN_TRY(GetDevice()->ValidateIsAlive());
|
||||||
DAWN_TRY(GetDevice()->ValidateObject(this));
|
DAWN_TRY(GetDevice()->ValidateObject(this));
|
||||||
|
|
||||||
if (!mAttached) {
|
DAWN_INVALID_IF(!mAttached, "Cannot call GetCurrentTextureView on detached %s.", this);
|
||||||
return DAWN_VALIDATION_ERROR("Getting view on detached swapchain");
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue