Improve validation errors in CommandEncoder
Updates all validation messages in CommandEncoder.cpp to give them better contextual information. Bug: dawn:563 Change-Id: I0aa2063c4805225a5124fdd07e350ee1a74a5f3c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/65609 Commit-Queue: Brandon Jones <bajones@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
b4d59c83ee
commit
da1a78db3b
|
@ -46,25 +46,21 @@ namespace dawn_native {
|
||||||
uint64_t srcOffset,
|
uint64_t srcOffset,
|
||||||
uint64_t dstOffset) {
|
uint64_t dstOffset) {
|
||||||
// Copy size must be a multiple of 4 bytes on macOS.
|
// Copy size must be a multiple of 4 bytes on macOS.
|
||||||
if (dataSize % 4 != 0) {
|
DAWN_INVALID_IF(dataSize % 4 != 0, "Copy size (%u) is not a multiple of 4.", dataSize);
|
||||||
return DAWN_VALIDATION_ERROR("Copy size must be a multiple of 4 bytes");
|
|
||||||
}
|
|
||||||
|
|
||||||
// SourceOffset and destinationOffset must be multiples of 4 bytes on macOS.
|
// SourceOffset and destinationOffset must be multiples of 4 bytes on macOS.
|
||||||
if (srcOffset % 4 != 0 || dstOffset % 4 != 0) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR(
|
srcOffset % 4 != 0 || dstOffset % 4 != 0,
|
||||||
"Source offset and destination offset must be multiples of 4 bytes");
|
"Source offset (%u) or destination offset (%u) is not a multiple of 4 bytes,",
|
||||||
}
|
srcOffset, dstOffset);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ValidateTextureSampleCountInBufferCopyCommands(const TextureBase* texture) {
|
MaybeError ValidateTextureSampleCountInBufferCopyCommands(const TextureBase* texture) {
|
||||||
if (texture->GetSampleCount() > 1) {
|
DAWN_INVALID_IF(texture->GetSampleCount() > 1,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"%s sample count (%u) is not 1 when copying to or from a buffer.",
|
||||||
"The sample count of textures must be 1 when copying between buffers and "
|
texture, texture->GetSampleCount());
|
||||||
"textures");
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -74,15 +70,13 @@ namespace dawn_native {
|
||||||
const bool hasDepthOrStencil) {
|
const bool hasDepthOrStencil) {
|
||||||
if (hasDepthOrStencil) {
|
if (hasDepthOrStencil) {
|
||||||
// For depth-stencil texture, buffer offset must be a multiple of 4.
|
// For depth-stencil texture, buffer offset must be a multiple of 4.
|
||||||
if (layout.offset % 4 != 0) {
|
DAWN_INVALID_IF(layout.offset % 4 != 0,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"Offset (%u) is not a multiple of 4 for depth/stencil texture.",
|
||||||
"offset must be a multiple of 4 for depth/stencil texture.");
|
layout.offset);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (layout.offset % blockInfo.byteSize != 0) {
|
DAWN_INVALID_IF(layout.offset % blockInfo.byteSize != 0,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"Offset (%u) is not a multiple of the texel block byte size (%u).",
|
||||||
"offset must be a multiple of the texel block byte size.");
|
layout.offset, blockInfo.byteSize);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -95,9 +89,10 @@ namespace dawn_native {
|
||||||
switch (src.texture->GetFormat().format) {
|
switch (src.texture->GetFormat().format) {
|
||||||
case wgpu::TextureFormat::Depth24Plus:
|
case wgpu::TextureFormat::Depth24Plus:
|
||||||
case wgpu::TextureFormat::Depth24PlusStencil8:
|
case wgpu::TextureFormat::Depth24PlusStencil8:
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_FORMAT_VALIDATION_ERROR(
|
||||||
"The depth aspect of depth24plus texture cannot be selected in a "
|
"The depth aspect of %s format %s cannot be selected in a texture to "
|
||||||
"texture to buffer copy");
|
"buffer copy.",
|
||||||
|
src.texture, src.texture->GetFormat().format);
|
||||||
case wgpu::TextureFormat::Depth32Float:
|
case wgpu::TextureFormat::Depth32Float:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -111,17 +106,13 @@ namespace dawn_native {
|
||||||
|
|
||||||
MaybeError ValidateAttachmentArrayLayersAndLevelCount(const TextureViewBase* attachment) {
|
MaybeError ValidateAttachmentArrayLayersAndLevelCount(const TextureViewBase* attachment) {
|
||||||
// Currently we do not support layered rendering.
|
// Currently we do not support layered rendering.
|
||||||
if (attachment->GetLayerCount() > 1) {
|
DAWN_INVALID_IF(attachment->GetLayerCount() > 1,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"The layer count (%u) of %s used as attachment is greater than 1.",
|
||||||
"The layer count of the texture view used as attachment cannot be greater than "
|
attachment->GetLayerCount(), attachment);
|
||||||
"1");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attachment->GetLevelCount() > 1) {
|
DAWN_INVALID_IF(attachment->GetLevelCount() > 1,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"The mip level count (%u) of %s used as attachment is greater than 1.",
|
||||||
"The mipmap level count of the texture view used as attachment cannot be "
|
attachment->GetLevelCount(), attachment);
|
||||||
"greater than 1");
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -137,8 +128,12 @@ namespace dawn_native {
|
||||||
*width = attachmentSize.width;
|
*width = attachmentSize.width;
|
||||||
*height = attachmentSize.height;
|
*height = attachmentSize.height;
|
||||||
DAWN_ASSERT(*width != 0 && *height != 0);
|
DAWN_ASSERT(*width != 0 && *height != 0);
|
||||||
} else if (*width != attachmentSize.width || *height != attachmentSize.height) {
|
} else {
|
||||||
return DAWN_VALIDATION_ERROR("Attachment size mismatch");
|
DAWN_INVALID_IF(
|
||||||
|
*width != attachmentSize.width || *height != attachmentSize.height,
|
||||||
|
"Attachment %s size (width: %u, height: %u) does not match the size of the "
|
||||||
|
"other attachments (width: %u, height: %u).",
|
||||||
|
attachment, attachmentSize.width, attachmentSize.height, *width, *height);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -149,8 +144,12 @@ namespace dawn_native {
|
||||||
if (*sampleCount == 0) {
|
if (*sampleCount == 0) {
|
||||||
*sampleCount = colorAttachment->GetTexture()->GetSampleCount();
|
*sampleCount = colorAttachment->GetTexture()->GetSampleCount();
|
||||||
DAWN_ASSERT(*sampleCount != 0);
|
DAWN_ASSERT(*sampleCount != 0);
|
||||||
} else if (*sampleCount != colorAttachment->GetTexture()->GetSampleCount()) {
|
} else {
|
||||||
return DAWN_VALIDATION_ERROR("Color attachment sample counts mismatch");
|
DAWN_INVALID_IF(
|
||||||
|
*sampleCount != colorAttachment->GetTexture()->GetSampleCount(),
|
||||||
|
"Color attachment %s sample count (%u) does not match the sample count of the "
|
||||||
|
"other attachments (%u).",
|
||||||
|
colorAttachment, colorAttachment->GetTexture()->GetSampleCount(), *sampleCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -168,40 +167,43 @@ namespace dawn_native {
|
||||||
DAWN_TRY(ValidateCanUseAs(colorAttachment.resolveTarget->GetTexture(),
|
DAWN_TRY(ValidateCanUseAs(colorAttachment.resolveTarget->GetTexture(),
|
||||||
wgpu::TextureUsage::RenderAttachment));
|
wgpu::TextureUsage::RenderAttachment));
|
||||||
|
|
||||||
if (!attachment->GetTexture()->IsMultisampledTexture()) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR(
|
!attachment->GetTexture()->IsMultisampledTexture(),
|
||||||
"Cannot set resolve target when the sample count of the color attachment is 1");
|
"Cannot set %s as a resolve target when the color attachment %s has a sample "
|
||||||
}
|
"count of 1.",
|
||||||
|
resolveTarget, attachment);
|
||||||
|
|
||||||
if (resolveTarget->GetTexture()->IsMultisampledTexture()) {
|
DAWN_INVALID_IF(resolveTarget->GetTexture()->IsMultisampledTexture(),
|
||||||
return DAWN_VALIDATION_ERROR("Cannot use multisampled texture as resolve target");
|
"Cannot use %s as resolve target. Sample count (%u) is greater than 1.",
|
||||||
}
|
resolveTarget, resolveTarget->GetTexture()->GetSampleCount());
|
||||||
|
|
||||||
if (resolveTarget->GetLayerCount() > 1) {
|
DAWN_INVALID_IF(resolveTarget->GetLayerCount() > 1,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"The resolve target %s array layer count (%u) is not 1.", resolveTarget,
|
||||||
"The array layer count of the resolve target must be 1");
|
resolveTarget->GetLayerCount());
|
||||||
}
|
|
||||||
|
|
||||||
if (resolveTarget->GetLevelCount() > 1) {
|
DAWN_INVALID_IF(resolveTarget->GetLevelCount() > 1,
|
||||||
return DAWN_VALIDATION_ERROR("The mip level count of the resolve target must be 1");
|
"The resolve target %s mip level count (%u) is not 1.", resolveTarget,
|
||||||
}
|
resolveTarget->GetLevelCount());
|
||||||
|
|
||||||
const Extent3D& colorTextureSize =
|
const Extent3D& colorTextureSize =
|
||||||
attachment->GetTexture()->GetMipLevelVirtualSize(attachment->GetBaseMipLevel());
|
attachment->GetTexture()->GetMipLevelVirtualSize(attachment->GetBaseMipLevel());
|
||||||
const Extent3D& resolveTextureSize =
|
const Extent3D& resolveTextureSize =
|
||||||
resolveTarget->GetTexture()->GetMipLevelVirtualSize(
|
resolveTarget->GetTexture()->GetMipLevelVirtualSize(
|
||||||
resolveTarget->GetBaseMipLevel());
|
resolveTarget->GetBaseMipLevel());
|
||||||
if (colorTextureSize.width != resolveTextureSize.width ||
|
DAWN_INVALID_IF(
|
||||||
colorTextureSize.height != resolveTextureSize.height) {
|
colorTextureSize.width != resolveTextureSize.width ||
|
||||||
return DAWN_VALIDATION_ERROR(
|
colorTextureSize.height != resolveTextureSize.height,
|
||||||
"The size of the resolve target must be the same as the color attachment");
|
"The Resolve target %s size (width: %u, height: %u) does not match the color "
|
||||||
}
|
"attachment %s size (width: %u, height: %u).",
|
||||||
|
resolveTarget, resolveTextureSize.width, resolveTextureSize.height, attachment,
|
||||||
|
colorTextureSize.width, colorTextureSize.height);
|
||||||
|
|
||||||
wgpu::TextureFormat resolveTargetFormat = resolveTarget->GetFormat().format;
|
wgpu::TextureFormat resolveTargetFormat = resolveTarget->GetFormat().format;
|
||||||
if (resolveTargetFormat != attachment->GetFormat().format) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR(
|
resolveTargetFormat != attachment->GetFormat().format,
|
||||||
"The format of the resolve target must be the same as the color attachment");
|
"The resolve target %s format (%s) does not match the color attachment %s format "
|
||||||
}
|
"(%s).",
|
||||||
|
resolveTarget, resolveTargetFormat, attachment, attachment->GetFormat().format);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -217,23 +219,21 @@ namespace dawn_native {
|
||||||
DAWN_TRY(
|
DAWN_TRY(
|
||||||
ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment));
|
ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment));
|
||||||
|
|
||||||
if (!(attachment->GetAspects() & Aspect::Color) ||
|
DAWN_INVALID_IF(!(attachment->GetAspects() & Aspect::Color) ||
|
||||||
!attachment->GetFormat().isRenderable) {
|
!attachment->GetFormat().isRenderable,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"The color attachment %s format (%s) is not color renderable.",
|
||||||
"The format of the texture view used as color attachment is not color "
|
attachment, attachment->GetFormat().format);
|
||||||
"renderable");
|
|
||||||
}
|
|
||||||
|
|
||||||
DAWN_TRY(ValidateLoadOp(colorAttachment.loadOp));
|
DAWN_TRY(ValidateLoadOp(colorAttachment.loadOp));
|
||||||
DAWN_TRY(ValidateStoreOp(colorAttachment.storeOp));
|
DAWN_TRY(ValidateStoreOp(colorAttachment.storeOp));
|
||||||
|
|
||||||
if (colorAttachment.loadOp == wgpu::LoadOp::Clear) {
|
if (colorAttachment.loadOp == wgpu::LoadOp::Clear) {
|
||||||
if (std::isnan(colorAttachment.clearColor.r) ||
|
DAWN_INVALID_IF(std::isnan(colorAttachment.clearColor.r) ||
|
||||||
std::isnan(colorAttachment.clearColor.g) ||
|
std::isnan(colorAttachment.clearColor.g) ||
|
||||||
std::isnan(colorAttachment.clearColor.b) ||
|
std::isnan(colorAttachment.clearColor.b) ||
|
||||||
std::isnan(colorAttachment.clearColor.a)) {
|
std::isnan(colorAttachment.clearColor.a),
|
||||||
return DAWN_VALIDATION_ERROR("Color clear value cannot contain NaN");
|
"Color clear value (%s) contain a NaN.",
|
||||||
}
|
&colorAttachment.clearColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_TRY(ValidateOrSetColorAttachmentSampleCount(attachment, sampleCount));
|
DAWN_TRY(ValidateOrSetColorAttachmentSampleCount(attachment, sampleCount));
|
||||||
|
@ -260,64 +260,62 @@ namespace dawn_native {
|
||||||
ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment));
|
ValidateCanUseAs(attachment->GetTexture(), wgpu::TextureUsage::RenderAttachment));
|
||||||
|
|
||||||
const Format& format = attachment->GetFormat();
|
const Format& format = attachment->GetFormat();
|
||||||
if (!format.HasDepthOrStencil()) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR(
|
!format.HasDepthOrStencil(),
|
||||||
"The format of the texture view used as depth stencil attachment is not a "
|
"The depth stencil attachment %s format (%s) is not a depth stencil format.",
|
||||||
"depth stencil format");
|
attachment, format.format);
|
||||||
}
|
|
||||||
if (!format.isRenderable) {
|
DAWN_INVALID_IF(!format.isRenderable,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"The depth stencil attachment %s format (%s) is not renderable.",
|
||||||
"The format of the texture view used as depth stencil attachment is not "
|
attachment, format.format);
|
||||||
"renderable");
|
|
||||||
}
|
DAWN_INVALID_IF(attachment->GetAspects() != format.aspects,
|
||||||
if (attachment->GetAspects() != format.aspects) {
|
"The depth stencil attachment %s must encompass all aspects.",
|
||||||
// TODO(https://crbug.com/dawn/812): Investigate if this limitation should be added
|
attachment);
|
||||||
// to the WebGPU spec of lifted from Dawn.
|
|
||||||
return DAWN_VALIDATION_ERROR(
|
|
||||||
"The texture view used as depth stencil view must encompass all aspects");
|
|
||||||
}
|
|
||||||
|
|
||||||
DAWN_TRY(ValidateLoadOp(depthStencilAttachment->depthLoadOp));
|
DAWN_TRY(ValidateLoadOp(depthStencilAttachment->depthLoadOp));
|
||||||
DAWN_TRY(ValidateLoadOp(depthStencilAttachment->stencilLoadOp));
|
DAWN_TRY(ValidateLoadOp(depthStencilAttachment->stencilLoadOp));
|
||||||
DAWN_TRY(ValidateStoreOp(depthStencilAttachment->depthStoreOp));
|
DAWN_TRY(ValidateStoreOp(depthStencilAttachment->depthStoreOp));
|
||||||
DAWN_TRY(ValidateStoreOp(depthStencilAttachment->stencilStoreOp));
|
DAWN_TRY(ValidateStoreOp(depthStencilAttachment->stencilStoreOp));
|
||||||
|
|
||||||
if (attachment->GetAspects() == (Aspect::Depth | Aspect::Stencil) &&
|
DAWN_INVALID_IF(
|
||||||
depthStencilAttachment->depthReadOnly != depthStencilAttachment->stencilReadOnly) {
|
attachment->GetAspects() == (Aspect::Depth | Aspect::Stencil) &&
|
||||||
return DAWN_VALIDATION_ERROR(
|
depthStencilAttachment->depthReadOnly !=
|
||||||
"depthReadOnly and stencilReadOnly must be the same when texture aspect is "
|
depthStencilAttachment->stencilReadOnly,
|
||||||
"'all'");
|
"depthReadOnly (%u) and stencilReadOnly (%u) must be the same when texture aspect "
|
||||||
}
|
"is 'all'.",
|
||||||
|
depthStencilAttachment->depthReadOnly, depthStencilAttachment->stencilReadOnly);
|
||||||
|
|
||||||
if (depthStencilAttachment->depthReadOnly &&
|
DAWN_INVALID_IF(
|
||||||
(depthStencilAttachment->depthLoadOp != wgpu::LoadOp::Load ||
|
depthStencilAttachment->depthReadOnly &&
|
||||||
depthStencilAttachment->depthStoreOp != wgpu::StoreOp::Store)) {
|
(depthStencilAttachment->depthLoadOp != wgpu::LoadOp::Load ||
|
||||||
return DAWN_VALIDATION_ERROR(
|
depthStencilAttachment->depthStoreOp != wgpu::StoreOp::Store),
|
||||||
"depthLoadOp must be load and depthStoreOp must be store when depthReadOnly "
|
"depthLoadOp (%s) is not %s or depthStoreOp (%s) is not %s when depthReadOnly "
|
||||||
"is true.");
|
"is true.",
|
||||||
}
|
depthStencilAttachment->depthLoadOp, wgpu::LoadOp::Load,
|
||||||
|
depthStencilAttachment->depthStoreOp, wgpu::StoreOp::Store);
|
||||||
|
|
||||||
if (depthStencilAttachment->stencilReadOnly &&
|
DAWN_INVALID_IF(depthStencilAttachment->stencilReadOnly &&
|
||||||
(depthStencilAttachment->stencilLoadOp != wgpu::LoadOp::Load ||
|
(depthStencilAttachment->stencilLoadOp != wgpu::LoadOp::Load ||
|
||||||
depthStencilAttachment->stencilStoreOp != wgpu::StoreOp::Store)) {
|
depthStencilAttachment->stencilStoreOp != wgpu::StoreOp::Store),
|
||||||
return DAWN_VALIDATION_ERROR(
|
"stencilLoadOp (%s) is not %s or stencilStoreOp (%s) is not %s when "
|
||||||
"stencilLoadOp must be load and stencilStoreOp must be store when "
|
"stencilReadOnly is true.",
|
||||||
"stencilReadOnly "
|
depthStencilAttachment->stencilLoadOp, wgpu::LoadOp::Load,
|
||||||
"is true.");
|
depthStencilAttachment->stencilStoreOp, wgpu::StoreOp::Store);
|
||||||
}
|
|
||||||
|
|
||||||
if (depthStencilAttachment->depthLoadOp == wgpu::LoadOp::Clear &&
|
DAWN_INVALID_IF(depthStencilAttachment->depthLoadOp == wgpu::LoadOp::Clear &&
|
||||||
std::isnan(depthStencilAttachment->clearDepth)) {
|
std::isnan(depthStencilAttachment->clearDepth),
|
||||||
return DAWN_VALIDATION_ERROR("Depth clear value cannot be NaN");
|
"Depth clear value is NaN.");
|
||||||
}
|
|
||||||
|
|
||||||
// *sampleCount == 0 must only happen when there is no color attachment. In that case we
|
// *sampleCount == 0 must only happen when there is no color attachment. In that case we
|
||||||
// do not need to validate the sample count of the depth stencil attachment.
|
// do not need to validate the sample count of the depth stencil attachment.
|
||||||
const uint32_t depthStencilSampleCount = attachment->GetTexture()->GetSampleCount();
|
const uint32_t depthStencilSampleCount = attachment->GetTexture()->GetSampleCount();
|
||||||
if (*sampleCount != 0) {
|
if (*sampleCount != 0) {
|
||||||
if (depthStencilSampleCount != *sampleCount) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR("Depth stencil attachment sample counts mismatch");
|
depthStencilSampleCount != *sampleCount,
|
||||||
}
|
"The depth stencil attachment %s sample count (%u) does not match the sample "
|
||||||
|
"count of the other attachments (%u).",
|
||||||
|
attachment, depthStencilSampleCount, *sampleCount);
|
||||||
} else {
|
} else {
|
||||||
*sampleCount = depthStencilSampleCount;
|
*sampleCount = depthStencilSampleCount;
|
||||||
}
|
}
|
||||||
|
@ -333,32 +331,37 @@ namespace dawn_native {
|
||||||
uint32_t* width,
|
uint32_t* width,
|
||||||
uint32_t* height,
|
uint32_t* height,
|
||||||
uint32_t* sampleCount) {
|
uint32_t* sampleCount) {
|
||||||
if (descriptor->colorAttachmentCount > kMaxColorAttachments) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR("Setting color attachments out of bounds");
|
descriptor->colorAttachmentCount > kMaxColorAttachments,
|
||||||
}
|
"Color attachment count (%u) exceeds the maximum number of color attachments (%u).",
|
||||||
|
descriptor->colorAttachmentCount, kMaxColorAttachments);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) {
|
for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) {
|
||||||
DAWN_TRY(ValidateRenderPassColorAttachment(device, descriptor->colorAttachments[i],
|
DAWN_TRY_CONTEXT(
|
||||||
width, height, sampleCount));
|
ValidateRenderPassColorAttachment(device, descriptor->colorAttachments[i],
|
||||||
|
width, height, sampleCount),
|
||||||
|
"validating colorAttachments[%u].", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor->depthStencilAttachment != nullptr) {
|
if (descriptor->depthStencilAttachment != nullptr) {
|
||||||
DAWN_TRY(ValidateRenderPassDepthStencilAttachment(
|
DAWN_TRY_CONTEXT(
|
||||||
device, descriptor->depthStencilAttachment, width, height, sampleCount));
|
ValidateRenderPassDepthStencilAttachment(
|
||||||
|
device, descriptor->depthStencilAttachment, width, height, sampleCount),
|
||||||
|
"validating depthStencilAttachment.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor->occlusionQuerySet != nullptr) {
|
if (descriptor->occlusionQuerySet != nullptr) {
|
||||||
DAWN_TRY(device->ValidateObject(descriptor->occlusionQuerySet));
|
DAWN_TRY(device->ValidateObject(descriptor->occlusionQuerySet));
|
||||||
|
|
||||||
if (descriptor->occlusionQuerySet->GetQueryType() != wgpu::QueryType::Occlusion) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR("The type of query set must be Occlusion");
|
descriptor->occlusionQuerySet->GetQueryType() != wgpu::QueryType::Occlusion,
|
||||||
}
|
"The occlusionQuerySet %s type (%s) is not %s.", descriptor->occlusionQuerySet,
|
||||||
|
descriptor->occlusionQuerySet->GetQueryType(), wgpu::QueryType::Occlusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor->colorAttachmentCount == 0 &&
|
DAWN_INVALID_IF(descriptor->colorAttachmentCount == 0 &&
|
||||||
descriptor->depthStencilAttachment == nullptr) {
|
descriptor->depthStencilAttachment == nullptr,
|
||||||
return DAWN_VALIDATION_ERROR("Cannot use render pass with no attachments.");
|
"Render pass has no attachments.");
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -373,21 +376,19 @@ namespace dawn_native {
|
||||||
uint32_t queryCount,
|
uint32_t queryCount,
|
||||||
const BufferBase* destination,
|
const BufferBase* destination,
|
||||||
uint64_t destinationOffset) {
|
uint64_t destinationOffset) {
|
||||||
if (firstQuery >= querySet->GetQueryCount()) {
|
DAWN_INVALID_IF(firstQuery >= querySet->GetQueryCount(),
|
||||||
return DAWN_VALIDATION_ERROR("Query index out of bounds");
|
"First query (%u) exceeds the number of queries (%u) in %s.",
|
||||||
}
|
firstQuery, querySet->GetQueryCount(), querySet);
|
||||||
|
|
||||||
if (queryCount > querySet->GetQueryCount() - firstQuery) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR(
|
queryCount > querySet->GetQueryCount() - firstQuery,
|
||||||
"The sum of firstQuery and queryCount exceeds the number of queries in query "
|
"The query range (firstQuery: %u, queryCount: %u) exceeds the number of queries "
|
||||||
"set");
|
"(%u) in %s.",
|
||||||
}
|
firstQuery, queryCount, querySet->GetQueryCount(), querySet);
|
||||||
|
|
||||||
if (destinationOffset % 256 != 0) {
|
DAWN_INVALID_IF(destinationOffset % 256 != 0,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"The destination buffer %s offset (%u) is not a multiple of 256.",
|
||||||
"The alignment offset into the destination buffer must be a multiple of 256 "
|
destination, destinationOffset);
|
||||||
"bytes");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t bufferSize = destination->GetSize();
|
uint64_t bufferSize = destination->GetSize();
|
||||||
// The destination buffer must have enough storage, from destination offset, to contain
|
// The destination buffer must have enough storage, from destination offset, to contain
|
||||||
|
@ -395,9 +396,11 @@ namespace dawn_native {
|
||||||
bool fitsInBuffer = destinationOffset <= bufferSize &&
|
bool fitsInBuffer = destinationOffset <= bufferSize &&
|
||||||
(static_cast<uint64_t>(queryCount) * sizeof(uint64_t) <=
|
(static_cast<uint64_t>(queryCount) * sizeof(uint64_t) <=
|
||||||
(bufferSize - destinationOffset));
|
(bufferSize - destinationOffset));
|
||||||
if (!fitsInBuffer) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR("The resolved query data would overflow the buffer");
|
!fitsInBuffer,
|
||||||
}
|
"The resolved %s data size (%u) would not fit in %s with size %u at the offset %u.",
|
||||||
|
querySet, static_cast<uint64_t>(queryCount) * sizeof(uint64_t), destination,
|
||||||
|
bufferSize, destinationOffset);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -588,11 +591,10 @@ namespace dawn_native {
|
||||||
if (IsReadOnlyDepthStencilAttachment(descriptor->depthStencilAttachment)) {
|
if (IsReadOnlyDepthStencilAttachment(descriptor->depthStencilAttachment)) {
|
||||||
// TODO(dawn:485): Readonly depth/stencil attachment is not fully
|
// TODO(dawn:485): Readonly depth/stencil attachment is not fully
|
||||||
// implemented. Disallow it as unsafe until the implementaion is completed.
|
// implemented. Disallow it as unsafe until the implementaion is completed.
|
||||||
if (device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs)) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR(
|
device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs),
|
||||||
"Readonly depth/stencil attachment is disallowed because it's not "
|
"Readonly depth/stencil attachment is disallowed because it's not "
|
||||||
"fully implemented");
|
"fully implemented");
|
||||||
}
|
|
||||||
|
|
||||||
usageTracker.TextureViewUsedAs(view, kReadOnlyRenderAttachment);
|
usageTracker.TextureViewUsedAs(view, kReadOnlyRenderAttachment);
|
||||||
} else {
|
} else {
|
||||||
|
@ -632,17 +634,20 @@ namespace dawn_native {
|
||||||
DAWN_TRY(GetDevice()->ValidateObject(source));
|
DAWN_TRY(GetDevice()->ValidateObject(source));
|
||||||
DAWN_TRY(GetDevice()->ValidateObject(destination));
|
DAWN_TRY(GetDevice()->ValidateObject(destination));
|
||||||
|
|
||||||
if (source == destination) {
|
DAWN_INVALID_IF(source == destination,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"Source and destination are the same buffer (%s).", source);
|
||||||
"Source and destination cannot be the same buffer.");
|
|
||||||
}
|
|
||||||
|
|
||||||
DAWN_TRY(ValidateCopySizeFitsInBuffer(source, sourceOffset, size));
|
DAWN_TRY_CONTEXT(ValidateCopySizeFitsInBuffer(source, sourceOffset, size),
|
||||||
DAWN_TRY(ValidateCopySizeFitsInBuffer(destination, destinationOffset, size));
|
"validating source %s copy size.", source);
|
||||||
|
DAWN_TRY_CONTEXT(
|
||||||
|
ValidateCopySizeFitsInBuffer(destination, destinationOffset, size),
|
||||||
|
"validating destination %s copy size.", destination);
|
||||||
DAWN_TRY(ValidateB2BCopyAlignment(size, sourceOffset, destinationOffset));
|
DAWN_TRY(ValidateB2BCopyAlignment(size, sourceOffset, destinationOffset));
|
||||||
|
|
||||||
DAWN_TRY(ValidateCanUseAs(source, wgpu::BufferUsage::CopySrc));
|
DAWN_TRY_CONTEXT(ValidateCanUseAs(source, wgpu::BufferUsage::CopySrc),
|
||||||
DAWN_TRY(ValidateCanUseAs(destination, wgpu::BufferUsage::CopyDst));
|
"validating source %s usage.", source);
|
||||||
|
DAWN_TRY_CONTEXT(ValidateCanUseAs(destination, wgpu::BufferUsage::CopyDst),
|
||||||
|
"validating destination %s usage.", destination);
|
||||||
|
|
||||||
mTopLevelBuffers.insert(source);
|
mTopLevelBuffers.insert(source);
|
||||||
mTopLevelBuffers.insert(destination);
|
mTopLevelBuffers.insert(destination);
|
||||||
|
@ -670,10 +675,13 @@ namespace dawn_native {
|
||||||
[&](CommandAllocator* allocator) -> MaybeError {
|
[&](CommandAllocator* allocator) -> MaybeError {
|
||||||
if (GetDevice()->IsValidationEnabled()) {
|
if (GetDevice()->IsValidationEnabled()) {
|
||||||
DAWN_TRY(ValidateImageCopyBuffer(GetDevice(), *source));
|
DAWN_TRY(ValidateImageCopyBuffer(GetDevice(), *source));
|
||||||
DAWN_TRY(ValidateCanUseAs(source->buffer, wgpu::BufferUsage::CopySrc));
|
DAWN_TRY_CONTEXT(ValidateCanUseAs(source->buffer, wgpu::BufferUsage::CopySrc),
|
||||||
|
"validating source %s usage.", source->buffer);
|
||||||
|
|
||||||
DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize));
|
DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize));
|
||||||
DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst));
|
DAWN_TRY_CONTEXT(
|
||||||
|
ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst),
|
||||||
|
"validating destination %s usage.", destination->texture);
|
||||||
DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(destination->texture));
|
DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(destination->texture));
|
||||||
|
|
||||||
DAWN_TRY(ValidateLinearToDepthStencilCopyRestrictions(*destination));
|
DAWN_TRY(ValidateLinearToDepthStencilCopyRestrictions(*destination));
|
||||||
|
@ -726,12 +734,15 @@ 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(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
|
DAWN_TRY_CONTEXT(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc),
|
||||||
|
"validating source %s usage.", source->texture);
|
||||||
DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(source->texture));
|
DAWN_TRY(ValidateTextureSampleCountInBufferCopyCommands(source->texture));
|
||||||
DAWN_TRY(ValidateTextureDepthStencilToBufferCopyRestrictions(*source));
|
DAWN_TRY(ValidateTextureDepthStencilToBufferCopyRestrictions(*source));
|
||||||
|
|
||||||
DAWN_TRY(ValidateImageCopyBuffer(GetDevice(), *destination));
|
DAWN_TRY(ValidateImageCopyBuffer(GetDevice(), *destination));
|
||||||
DAWN_TRY(ValidateCanUseAs(destination->buffer, wgpu::BufferUsage::CopyDst));
|
DAWN_TRY_CONTEXT(
|
||||||
|
ValidateCanUseAs(destination->buffer, wgpu::BufferUsage::CopyDst),
|
||||||
|
"validating destination %s usage.", destination->buffer);
|
||||||
|
|
||||||
// We validate texture copy range before validating linear texture data,
|
// We validate texture copy range before validating linear texture data,
|
||||||
// because in the latter we divide copyExtent.width by blockWidth and
|
// because in the latter we divide copyExtent.width by blockWidth and
|
||||||
|
@ -796,14 +807,18 @@ namespace dawn_native {
|
||||||
DAWN_TRY(GetDevice()->ValidateObject(source->texture));
|
DAWN_TRY(GetDevice()->ValidateObject(source->texture));
|
||||||
DAWN_TRY(GetDevice()->ValidateObject(destination->texture));
|
DAWN_TRY(GetDevice()->ValidateObject(destination->texture));
|
||||||
|
|
||||||
DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *source, *copySize));
|
DAWN_TRY_CONTEXT(ValidateImageCopyTexture(GetDevice(), *source, *copySize),
|
||||||
DAWN_TRY(ValidateImageCopyTexture(GetDevice(), *destination, *copySize));
|
"validating source %s.", source->texture);
|
||||||
|
DAWN_TRY_CONTEXT(ValidateImageCopyTexture(GetDevice(), *destination, *copySize),
|
||||||
|
"validating destination %s.", destination->texture);
|
||||||
|
|
||||||
DAWN_TRY(
|
DAWN_TRY(
|
||||||
ValidateTextureToTextureCopyRestrictions(*source, *destination, *copySize));
|
ValidateTextureToTextureCopyRestrictions(*source, *destination, *copySize));
|
||||||
|
|
||||||
DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *source, *copySize));
|
DAWN_TRY_CONTEXT(ValidateTextureCopyRange(GetDevice(), *source, *copySize),
|
||||||
DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *destination, *copySize));
|
"validating source %s copy range.", source->texture);
|
||||||
|
DAWN_TRY_CONTEXT(ValidateTextureCopyRange(GetDevice(), *destination, *copySize),
|
||||||
|
"validating source %s copy range.", destination->texture);
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -868,10 +883,10 @@ namespace dawn_native {
|
||||||
this,
|
this,
|
||||||
[&](CommandAllocator* allocator) -> MaybeError {
|
[&](CommandAllocator* allocator) -> MaybeError {
|
||||||
if (GetDevice()->IsValidationEnabled()) {
|
if (GetDevice()->IsValidationEnabled()) {
|
||||||
if (mDebugGroupStackSize == 0) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR(
|
mDebugGroupStackSize == 0,
|
||||||
"Pop must be balanced by a corresponding Push.");
|
"Every call to PopDebugGroup must be balanced by a corresponding call to "
|
||||||
}
|
"PushDebugGroup.");
|
||||||
}
|
}
|
||||||
allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup);
|
allocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup);
|
||||||
mDebugGroupStackSize--;
|
mDebugGroupStackSize--;
|
||||||
|
@ -1032,18 +1047,22 @@ namespace dawn_native {
|
||||||
DAWN_TRY(GetDevice()->ValidateObject(this));
|
DAWN_TRY(GetDevice()->ValidateObject(this));
|
||||||
|
|
||||||
for (const RenderPassResourceUsage& passUsage : mEncodingContext.GetRenderPassUsages()) {
|
for (const RenderPassResourceUsage& passUsage : mEncodingContext.GetRenderPassUsages()) {
|
||||||
DAWN_TRY(ValidateSyncScopeResourceUsage(passUsage));
|
DAWN_TRY_CONTEXT(ValidateSyncScopeResourceUsage(passUsage),
|
||||||
|
"validating render pass usage.");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const ComputePassResourceUsage& passUsage : mEncodingContext.GetComputePassUsages()) {
|
for (const ComputePassResourceUsage& passUsage : mEncodingContext.GetComputePassUsages()) {
|
||||||
for (const SyncScopeResourceUsage& scope : passUsage.dispatchUsages) {
|
for (const SyncScopeResourceUsage& scope : passUsage.dispatchUsages) {
|
||||||
DAWN_TRY(ValidateSyncScopeResourceUsage(scope));
|
DAWN_TRY_CONTEXT(ValidateSyncScopeResourceUsage(scope),
|
||||||
|
"validating compute pass usage.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDebugGroupStackSize != 0) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR("Each Push must be balanced by a corresponding Pop.");
|
mDebugGroupStackSize != 0,
|
||||||
}
|
"PushDebugGroup called %u time(s) without a corresponding PopDebugGroup prior to "
|
||||||
|
"calling Finish.",
|
||||||
|
mDebugGroupStackSize);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue