Improve validation errors in Texture
Updates all validation messages in Texture.cpp to give them better contextual information. Bug: dawn:563 Change-Id: Ibae48b6842c80253c82b63989d08dac95c4b5759 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/65602 Commit-Queue: Brandon Jones <bajones@chromium.org> Commit-Queue: Austin Eng <enga@chromium.org> Auto-Submit: Brandon Jones <bajones@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
2bf51560eb
commit
2f1d02b94b
|
@ -1439,7 +1439,8 @@ namespace dawn_native {
|
||||||
ResultOrError<Ref<TextureBase>> DeviceBase::CreateTexture(const TextureDescriptor* descriptor) {
|
ResultOrError<Ref<TextureBase>> DeviceBase::CreateTexture(const TextureDescriptor* descriptor) {
|
||||||
DAWN_TRY(ValidateIsAlive());
|
DAWN_TRY(ValidateIsAlive());
|
||||||
if (IsValidationEnabled()) {
|
if (IsValidationEnabled()) {
|
||||||
DAWN_TRY(ValidateTextureDescriptor(this, descriptor));
|
DAWN_TRY_CONTEXT(ValidateTextureDescriptor(this, descriptor), "validating %s.",
|
||||||
|
descriptor);
|
||||||
}
|
}
|
||||||
return CreateTextureImpl(descriptor);
|
return CreateTextureImpl(descriptor);
|
||||||
}
|
}
|
||||||
|
@ -1451,7 +1452,8 @@ namespace dawn_native {
|
||||||
DAWN_TRY(ValidateObject(texture));
|
DAWN_TRY(ValidateObject(texture));
|
||||||
TextureViewDescriptor desc = GetTextureViewDescriptorWithDefaults(texture, descriptor);
|
TextureViewDescriptor desc = GetTextureViewDescriptorWithDefaults(texture, descriptor);
|
||||||
if (IsValidationEnabled()) {
|
if (IsValidationEnabled()) {
|
||||||
DAWN_TRY(ValidateTextureViewDescriptor(this, texture, &desc));
|
DAWN_TRY_CONTEXT(ValidateTextureViewDescriptor(this, texture, &desc),
|
||||||
|
"validating %s against %s.", &desc, texture);
|
||||||
}
|
}
|
||||||
return CreateTextureViewImpl(texture, &desc);
|
return CreateTextureViewImpl(texture, &desc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,59 +90,42 @@ namespace dawn_native {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsTextureSizeValidForTextureViewDimension(
|
|
||||||
wgpu::TextureViewDimension textureViewDimension,
|
|
||||||
const Extent3D& textureSize) {
|
|
||||||
switch (textureViewDimension) {
|
|
||||||
case wgpu::TextureViewDimension::Cube:
|
|
||||||
case wgpu::TextureViewDimension::CubeArray:
|
|
||||||
return textureSize.width == textureSize.height;
|
|
||||||
case wgpu::TextureViewDimension::e2D:
|
|
||||||
case wgpu::TextureViewDimension::e2DArray:
|
|
||||||
case wgpu::TextureViewDimension::e3D:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case wgpu::TextureViewDimension::e1D:
|
|
||||||
case wgpu::TextureViewDimension::Undefined:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError ValidateSampleCount(const TextureDescriptor* descriptor,
|
MaybeError ValidateSampleCount(const TextureDescriptor* descriptor,
|
||||||
wgpu::TextureUsage usage,
|
wgpu::TextureUsage usage,
|
||||||
const Format* format) {
|
const Format* format) {
|
||||||
if (!IsValidSampleCount(descriptor->sampleCount)) {
|
DAWN_INVALID_IF(!IsValidSampleCount(descriptor->sampleCount),
|
||||||
return DAWN_VALIDATION_ERROR("The sample count of the texture is not supported.");
|
"The sample count (%u) of the texture is not supported.",
|
||||||
}
|
descriptor->sampleCount);
|
||||||
|
|
||||||
if (descriptor->sampleCount > 1) {
|
if (descriptor->sampleCount > 1) {
|
||||||
if (descriptor->mipLevelCount > 1) {
|
DAWN_INVALID_IF(descriptor->mipLevelCount > 1,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"The mip level count (%u) of a multisampled texture is not 1.",
|
||||||
"The mipmap level count of a multisampled texture must be 1.");
|
descriptor->mipLevelCount);
|
||||||
}
|
|
||||||
|
|
||||||
// Multisampled 1D and 3D textures are not supported in D3D12/Metal/Vulkan.
|
// Multisampled 1D and 3D textures are not supported in D3D12/Metal/Vulkan.
|
||||||
// Multisampled 2D array texture is not supported because on Metal it requires the
|
// Multisampled 2D array texture is not supported because on Metal it requires the
|
||||||
// version of macOS be greater than 10.14.
|
// version of macOS be greater than 10.14.
|
||||||
if (descriptor->dimension != wgpu::TextureDimension::e2D ||
|
DAWN_INVALID_IF(descriptor->dimension != wgpu::TextureDimension::e2D,
|
||||||
descriptor->size.depthOrArrayLayers > 1) {
|
"The dimension (%s) of a multisampled texture is not 2D.",
|
||||||
return DAWN_VALIDATION_ERROR("Multisampled texture must be 2D with depth=1");
|
descriptor->dimension);
|
||||||
}
|
|
||||||
|
DAWN_INVALID_IF(descriptor->size.depthOrArrayLayers > 1,
|
||||||
|
"The depthOrArrayLayers (%u) of a multisampled texture is not 1.",
|
||||||
|
descriptor->size.depthOrArrayLayers);
|
||||||
|
|
||||||
// If a format can support multisample, it must be renderable. Because Vulkan
|
// If a format can support multisample, it must be renderable. Because Vulkan
|
||||||
// requires that if the format is not color-renderable or depth/stencil renderable,
|
// requires that if the format is not color-renderable or depth/stencil renderable,
|
||||||
// sampleCount must be 1.
|
// sampleCount must be 1.
|
||||||
if (!format->isRenderable) {
|
DAWN_INVALID_IF(!format->isRenderable,
|
||||||
return DAWN_VALIDATION_ERROR("This format cannot support multisample.");
|
"The texture format (%s) does not support multisampling.",
|
||||||
}
|
format->format);
|
||||||
|
|
||||||
// Compressed formats are not renderable. They cannot support multisample.
|
// Compressed formats are not renderable. They cannot support multisample.
|
||||||
ASSERT(!format->isCompressed);
|
ASSERT(!format->isCompressed);
|
||||||
|
|
||||||
if (usage & wgpu::TextureUsage::StorageBinding) {
|
DAWN_INVALID_IF(usage & wgpu::TextureUsage::StorageBinding,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"The sample count (%u) of a storage textures is not 1.",
|
||||||
"The sample counts of the storage textures must be 1.");
|
descriptor->sampleCount);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -151,24 +134,40 @@ namespace dawn_native {
|
||||||
MaybeError ValidateTextureViewDimensionCompatibility(
|
MaybeError ValidateTextureViewDimensionCompatibility(
|
||||||
const TextureBase* texture,
|
const TextureBase* texture,
|
||||||
const TextureViewDescriptor* descriptor) {
|
const TextureViewDescriptor* descriptor) {
|
||||||
if (!IsArrayLayerValidForTextureViewDimension(descriptor->dimension,
|
DAWN_INVALID_IF(
|
||||||
descriptor->arrayLayerCount)) {
|
!IsArrayLayerValidForTextureViewDimension(descriptor->dimension,
|
||||||
return DAWN_VALIDATION_ERROR(
|
descriptor->arrayLayerCount),
|
||||||
"The dimension of the texture view is not compatible with the layer count");
|
"The dimension (%s) of the texture view is not compatible with the layer count "
|
||||||
}
|
"(%u) of %s.",
|
||||||
|
descriptor->dimension, descriptor->arrayLayerCount, texture);
|
||||||
|
|
||||||
if (!IsTextureViewDimensionCompatibleWithTextureDimension(descriptor->dimension,
|
DAWN_INVALID_IF(
|
||||||
texture->GetDimension())) {
|
!IsTextureViewDimensionCompatibleWithTextureDimension(descriptor->dimension,
|
||||||
return DAWN_VALIDATION_ERROR(
|
texture->GetDimension()),
|
||||||
"The dimension of the texture view is not compatible with the dimension of the"
|
"The dimension (%s) of the texture view is not compatible with the dimension (%s) "
|
||||||
"original texture");
|
"of %s.",
|
||||||
}
|
descriptor->dimension, texture->GetDimension(), texture);
|
||||||
|
|
||||||
if (!IsTextureSizeValidForTextureViewDimension(descriptor->dimension,
|
switch (descriptor->dimension) {
|
||||||
texture->GetSize())) {
|
case wgpu::TextureViewDimension::Cube:
|
||||||
return DAWN_VALIDATION_ERROR(
|
case wgpu::TextureViewDimension::CubeArray:
|
||||||
"The dimension of the texture view is not compatible with the size of the"
|
DAWN_INVALID_IF(
|
||||||
"original texture");
|
texture->GetSize().width != texture->GetSize().height,
|
||||||
|
"A %s texture view is not compatible with %s because the texture's width "
|
||||||
|
"(%u) and height (%u) are not equal.",
|
||||||
|
descriptor->dimension, texture, texture->GetSize().width,
|
||||||
|
texture->GetSize().height);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wgpu::TextureViewDimension::e2D:
|
||||||
|
case wgpu::TextureViewDimension::e2DArray:
|
||||||
|
case wgpu::TextureViewDimension::e3D:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wgpu::TextureViewDimension::e1D:
|
||||||
|
case wgpu::TextureViewDimension::Undefined:
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -192,11 +191,11 @@ namespace dawn_native {
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
if (descriptor->size.width > maxExtent.width ||
|
DAWN_INVALID_IF(descriptor->size.width > maxExtent.width ||
|
||||||
descriptor->size.height > maxExtent.height ||
|
descriptor->size.height > maxExtent.height ||
|
||||||
descriptor->size.depthOrArrayLayers > maxExtent.depthOrArrayLayers) {
|
descriptor->size.depthOrArrayLayers > maxExtent.depthOrArrayLayers,
|
||||||
return DAWN_VALIDATION_ERROR("Texture dimension (width, height or depth) exceeded");
|
"Texture size (%s) exceeded maximum texture size (%s).",
|
||||||
}
|
&descriptor->size, &maxExtent);
|
||||||
|
|
||||||
uint32_t maxMippedDimension = descriptor->size.width;
|
uint32_t maxMippedDimension = descriptor->size.width;
|
||||||
if (descriptor->dimension != wgpu::TextureDimension::e1D) {
|
if (descriptor->dimension != wgpu::TextureDimension::e1D) {
|
||||||
|
@ -206,19 +205,22 @@ namespace dawn_native {
|
||||||
maxMippedDimension =
|
maxMippedDimension =
|
||||||
std::max(maxMippedDimension, descriptor->size.depthOrArrayLayers);
|
std::max(maxMippedDimension, descriptor->size.depthOrArrayLayers);
|
||||||
}
|
}
|
||||||
if (Log2(maxMippedDimension) + 1 < descriptor->mipLevelCount) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR("Texture has too many mip levels");
|
Log2(maxMippedDimension) + 1 < descriptor->mipLevelCount,
|
||||||
}
|
"Texture mip level count (%u) exceeds the maximum (%u) for its size (%s).",
|
||||||
|
descriptor->mipLevelCount, Log2(maxMippedDimension) + 1, &descriptor->size);
|
||||||
|
|
||||||
ASSERT(descriptor->mipLevelCount <= kMaxTexture2DMipLevels);
|
ASSERT(descriptor->mipLevelCount <= kMaxTexture2DMipLevels);
|
||||||
|
|
||||||
if (format->isCompressed) {
|
if (format->isCompressed) {
|
||||||
const TexelBlockInfo& blockInfo =
|
const TexelBlockInfo& blockInfo =
|
||||||
format->GetAspectInfo(wgpu::TextureAspect::All).block;
|
format->GetAspectInfo(wgpu::TextureAspect::All).block;
|
||||||
if (descriptor->size.width % blockInfo.width != 0 ||
|
DAWN_INVALID_IF(
|
||||||
descriptor->size.height % blockInfo.height != 0) {
|
descriptor->size.width % blockInfo.width != 0 ||
|
||||||
return DAWN_VALIDATION_ERROR(
|
descriptor->size.height % blockInfo.height != 0,
|
||||||
"The size of the texture is incompatible with the texture format");
|
"The size (%s) of the texture is not a multiple of the block width (%u) and "
|
||||||
}
|
"height (%u) of the texture format (%s).",
|
||||||
|
&descriptor->size, blockInfo.width, blockInfo.height, format->format);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -232,25 +234,28 @@ namespace dawn_native {
|
||||||
constexpr wgpu::TextureUsage kValidCompressedUsages =
|
constexpr wgpu::TextureUsage kValidCompressedUsages =
|
||||||
wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc |
|
wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc |
|
||||||
wgpu::TextureUsage::CopyDst;
|
wgpu::TextureUsage::CopyDst;
|
||||||
if (format->isCompressed && !IsSubset(usage, kValidCompressedUsages)) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR(
|
format->isCompressed && !IsSubset(usage, kValidCompressedUsages),
|
||||||
"Compressed texture format is incompatible with the texture usage");
|
"The texture usage (%s) is incompatible with the compressed texture format (%s).",
|
||||||
}
|
usage, format->format);
|
||||||
|
|
||||||
if (!format->isRenderable && (usage & wgpu::TextureUsage::RenderAttachment)) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR(
|
!format->isRenderable && (usage & wgpu::TextureUsage::RenderAttachment),
|
||||||
"Non-renderable format used with RenderAttachment usage");
|
"The texture usage (%s) includes %s, which is incompatible with the non-renderable "
|
||||||
}
|
"format (%s).",
|
||||||
|
usage, wgpu::TextureUsage::RenderAttachment, format->format);
|
||||||
|
|
||||||
if (!format->supportsStorageUsage && (usage & wgpu::TextureUsage::StorageBinding)) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR("Format cannot be used in storage textures");
|
!format->supportsStorageUsage && (usage & wgpu::TextureUsage::StorageBinding),
|
||||||
}
|
"The texture usage (%s) includes %s, which is incompatible with the format (%s).",
|
||||||
|
usage, wgpu::TextureUsage::StorageBinding, format->format);
|
||||||
|
|
||||||
constexpr wgpu::TextureUsage kValidMultiPlanarUsages =
|
constexpr wgpu::TextureUsage kValidMultiPlanarUsages =
|
||||||
wgpu::TextureUsage::TextureBinding;
|
wgpu::TextureUsage::TextureBinding;
|
||||||
if (format->IsMultiPlanar() && !IsSubset(usage, kValidMultiPlanarUsages)) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR("Multi-planar format doesn't have valid usage.");
|
format->IsMultiPlanar() && !IsSubset(usage, kValidMultiPlanarUsages),
|
||||||
}
|
"The texture usage (%s) is incompatible with the multi-planar format (%s).", usage,
|
||||||
|
format->format);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -265,14 +270,12 @@ namespace dawn_native {
|
||||||
const DawnTextureInternalUsageDescriptor* internalUsageDesc = nullptr;
|
const DawnTextureInternalUsageDescriptor* internalUsageDesc = nullptr;
|
||||||
FindInChain(descriptor->nextInChain, &internalUsageDesc);
|
FindInChain(descriptor->nextInChain, &internalUsageDesc);
|
||||||
|
|
||||||
if (descriptor->dimension == wgpu::TextureDimension::e1D) {
|
DAWN_INVALID_IF(descriptor->dimension == wgpu::TextureDimension::e1D,
|
||||||
return DAWN_VALIDATION_ERROR("1D textures aren't supported (yet).");
|
"1D textures aren't supported (yet).");
|
||||||
}
|
|
||||||
|
|
||||||
if (internalUsageDesc != nullptr &&
|
DAWN_INVALID_IF(internalUsageDesc != nullptr &&
|
||||||
!device->IsExtensionEnabled(Extension::DawnInternalUsages)) {
|
!device->IsExtensionEnabled(Extension::DawnInternalUsages),
|
||||||
return DAWN_VALIDATION_ERROR("The dawn-internal-usages feature is not enabled");
|
"The dawn-internal-usages feature is not enabled");
|
||||||
}
|
|
||||||
|
|
||||||
const Format* format;
|
const Format* format;
|
||||||
DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format));
|
DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format));
|
||||||
|
@ -286,42 +289,42 @@ namespace dawn_native {
|
||||||
DAWN_TRY(ValidateTextureDimension(descriptor->dimension));
|
DAWN_TRY(ValidateTextureDimension(descriptor->dimension));
|
||||||
DAWN_TRY(ValidateSampleCount(descriptor, usage, format));
|
DAWN_TRY(ValidateSampleCount(descriptor, usage, format));
|
||||||
|
|
||||||
if (descriptor->size.width == 0 || descriptor->size.height == 0 ||
|
DAWN_INVALID_IF(descriptor->size.width == 0 || descriptor->size.height == 0 ||
|
||||||
descriptor->size.depthOrArrayLayers == 0 || descriptor->mipLevelCount == 0) {
|
descriptor->size.depthOrArrayLayers == 0 ||
|
||||||
return DAWN_VALIDATION_ERROR("Cannot create an empty texture");
|
descriptor->mipLevelCount == 0,
|
||||||
}
|
"The texture size (%s) or mipLevelCount (%u) is empty.", &descriptor->size,
|
||||||
|
descriptor->mipLevelCount);
|
||||||
|
|
||||||
if (descriptor->dimension != wgpu::TextureDimension::e2D && format->isCompressed) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR("Compressed texture must be 2D");
|
descriptor->dimension != wgpu::TextureDimension::e2D && format->isCompressed,
|
||||||
}
|
"The dimension (%s) of a texture with a compressed format (%s) is not 2D.",
|
||||||
|
descriptor->dimension, format->format);
|
||||||
|
|
||||||
// Depth/stencil formats are valid for 2D textures only. Metal has this limit. And D3D12
|
// Depth/stencil formats are valid for 2D textures only. Metal has this limit. And D3D12
|
||||||
// doesn't support depth/stencil formats on 3D textures.
|
// doesn't support depth/stencil formats on 3D textures.
|
||||||
if (descriptor->dimension != wgpu::TextureDimension::e2D &&
|
DAWN_INVALID_IF(
|
||||||
(format->aspects & (Aspect::Depth | Aspect::Stencil)) != 0) {
|
descriptor->dimension != wgpu::TextureDimension::e2D &&
|
||||||
return DAWN_VALIDATION_ERROR("Depth/stencil formats are valid for 2D textures only");
|
(format->aspects & (Aspect::Depth | Aspect::Stencil)) != 0,
|
||||||
}
|
"The dimension (%s) of a texture with a depth/stencil format (%s) is not 2D.",
|
||||||
|
descriptor->dimension, format->format);
|
||||||
|
|
||||||
DAWN_TRY(ValidateTextureSize(descriptor, format));
|
DAWN_TRY(ValidateTextureSize(descriptor, format));
|
||||||
|
|
||||||
if (device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs) && format->HasStencil() &&
|
// TODO(crbug.com/dawn/838): Implement a workaround for this issue.
|
||||||
descriptor->mipLevelCount > 1 &&
|
// Readbacks from the non-zero mip of a stencil texture may contain garbage data.
|
||||||
device->GetAdapter()->GetBackendType() == wgpu::BackendType::Metal) {
|
DAWN_INVALID_IF(
|
||||||
// TODO(crbug.com/dawn/838): Implement a workaround for this issue.
|
device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs) && format->HasStencil() &&
|
||||||
// Readbacks from the non-zero mip of a stencil texture may contain
|
descriptor->mipLevelCount > 1 &&
|
||||||
// garbage data.
|
device->GetAdapter()->GetBackendType() == wgpu::BackendType::Metal,
|
||||||
return DAWN_VALIDATION_ERROR(
|
"https://crbug.com/dawn/838: Stencil textures with more than one mip level are "
|
||||||
"crbug.com/dawn/838: Stencil textures with more than one mip level are "
|
"disabled on Metal.");
|
||||||
"disabled on Metal.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device->IsToggleEnabled(Toggle::DisableR8RG8Mipmaps) && descriptor->mipLevelCount > 1 &&
|
DAWN_INVALID_IF(
|
||||||
(descriptor->format == wgpu::TextureFormat::R8Unorm ||
|
device->IsToggleEnabled(Toggle::DisableR8RG8Mipmaps) && descriptor->mipLevelCount > 1 &&
|
||||||
descriptor->format == wgpu::TextureFormat::RG8Unorm)) {
|
(descriptor->format == wgpu::TextureFormat::R8Unorm ||
|
||||||
return DAWN_VALIDATION_ERROR(
|
descriptor->format == wgpu::TextureFormat::RG8Unorm),
|
||||||
"https://crbug.com/dawn/1071: r8unorm and rg8unorm textures with more than one mip "
|
"https://crbug.com/dawn/1071: r8unorm and rg8unorm textures with more than one mip "
|
||||||
"level are disabled on Metal.");
|
"level are disabled on Metal.");
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -329,39 +332,41 @@ namespace dawn_native {
|
||||||
MaybeError ValidateTextureViewDescriptor(const DeviceBase* device,
|
MaybeError ValidateTextureViewDescriptor(const DeviceBase* device,
|
||||||
const TextureBase* texture,
|
const TextureBase* texture,
|
||||||
const TextureViewDescriptor* descriptor) {
|
const TextureViewDescriptor* descriptor) {
|
||||||
if (descriptor->nextInChain != nullptr) {
|
DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr.");
|
||||||
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parent texture should have been already validated.
|
// Parent texture should have been already validated.
|
||||||
ASSERT(texture);
|
ASSERT(texture);
|
||||||
ASSERT(!texture->IsError());
|
ASSERT(!texture->IsError());
|
||||||
|
|
||||||
DAWN_TRY(ValidateTextureViewDimension(descriptor->dimension));
|
DAWN_TRY(ValidateTextureViewDimension(descriptor->dimension));
|
||||||
if (descriptor->dimension == wgpu::TextureViewDimension::e1D) {
|
DAWN_INVALID_IF(descriptor->dimension == wgpu::TextureViewDimension::e1D,
|
||||||
return DAWN_VALIDATION_ERROR("1D texture views aren't supported (yet).");
|
"1D texture views aren't supported (yet).");
|
||||||
}
|
|
||||||
|
|
||||||
DAWN_TRY(ValidateTextureFormat(descriptor->format));
|
DAWN_TRY(ValidateTextureFormat(descriptor->format));
|
||||||
|
|
||||||
DAWN_TRY(ValidateTextureAspect(descriptor->aspect));
|
DAWN_TRY(ValidateTextureAspect(descriptor->aspect));
|
||||||
if (SelectFormatAspects(texture->GetFormat(), descriptor->aspect) == Aspect::None) {
|
DAWN_INVALID_IF(
|
||||||
return DAWN_VALIDATION_ERROR("Texture does not have selected aspect for texture view.");
|
SelectFormatAspects(texture->GetFormat(), descriptor->aspect) == Aspect::None,
|
||||||
}
|
"Texture format (%s) does not have the texture view's selected aspect (%s).",
|
||||||
|
texture->GetFormat().format, descriptor->aspect);
|
||||||
|
|
||||||
if (descriptor->arrayLayerCount == 0 || descriptor->mipLevelCount == 0) {
|
DAWN_INVALID_IF(descriptor->arrayLayerCount == 0 || descriptor->mipLevelCount == 0,
|
||||||
return DAWN_VALIDATION_ERROR("Cannot create an empty texture view");
|
"The texture view's arrayLayerCount (%u) or mipLevelCount (%u) is zero.",
|
||||||
}
|
descriptor->arrayLayerCount, descriptor->mipLevelCount);
|
||||||
|
|
||||||
if (uint64_t(descriptor->baseArrayLayer) + uint64_t(descriptor->arrayLayerCount) >
|
DAWN_INVALID_IF(
|
||||||
uint64_t(texture->GetArrayLayers())) {
|
uint64_t(descriptor->baseArrayLayer) + uint64_t(descriptor->arrayLayerCount) >
|
||||||
return DAWN_VALIDATION_ERROR("Texture view array-layer out of range");
|
uint64_t(texture->GetArrayLayers()),
|
||||||
}
|
"Texture view array layer range (baseArrayLayer: %u, arrayLayerCount: %u) exceeds the "
|
||||||
|
"texture's array layer count (%u).",
|
||||||
|
descriptor->baseArrayLayer, descriptor->arrayLayerCount, texture->GetArrayLayers());
|
||||||
|
|
||||||
if (uint64_t(descriptor->baseMipLevel) + uint64_t(descriptor->mipLevelCount) >
|
DAWN_INVALID_IF(
|
||||||
uint64_t(texture->GetNumMipLevels())) {
|
uint64_t(descriptor->baseMipLevel) + uint64_t(descriptor->mipLevelCount) >
|
||||||
return DAWN_VALIDATION_ERROR("Texture view mip-level out of range");
|
uint64_t(texture->GetNumMipLevels()),
|
||||||
}
|
"Texture view mip level range (baseMipLevel: %u, mipLevelCount: %u) exceeds the "
|
||||||
|
"texture's mip level count (%u).",
|
||||||
|
descriptor->baseMipLevel, descriptor->mipLevelCount, texture->GetNumMipLevels());
|
||||||
|
|
||||||
DAWN_TRY(ValidateTextureViewFormatCompatibility(texture, descriptor));
|
DAWN_TRY(ValidateTextureViewFormatCompatibility(texture, descriptor));
|
||||||
DAWN_TRY(ValidateTextureViewDimensionCompatibility(texture, descriptor));
|
DAWN_TRY(ValidateTextureViewDimensionCompatibility(texture, descriptor));
|
||||||
|
@ -596,9 +601,8 @@ namespace dawn_native {
|
||||||
|
|
||||||
MaybeError TextureBase::ValidateCanUseInSubmitNow() const {
|
MaybeError TextureBase::ValidateCanUseInSubmitNow() const {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
if (mState == TextureState::Destroyed) {
|
DAWN_INVALID_IF(mState == TextureState::Destroyed, "Destroyed texture %s used in a submit.",
|
||||||
return DAWN_VALIDATION_ERROR("Destroyed texture used in a submit");
|
this);
|
||||||
}
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,14 +663,15 @@ namespace dawn_native {
|
||||||
DeviceBase* device = GetDevice();
|
DeviceBase* device = GetDevice();
|
||||||
|
|
||||||
Ref<TextureViewBase> result;
|
Ref<TextureViewBase> result;
|
||||||
if (device->ConsumedError(device->CreateTextureView(this, descriptor), &result)) {
|
if (device->ConsumedError(device->CreateTextureView(this, descriptor), &result,
|
||||||
|
"calling %s.CreateView(%s).", this, descriptor)) {
|
||||||
return TextureViewBase::MakeError(device);
|
return TextureViewBase::MakeError(device);
|
||||||
}
|
}
|
||||||
return result.Detach();
|
return result.Detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBase::APIDestroy() {
|
void TextureBase::APIDestroy() {
|
||||||
if (GetDevice()->ConsumedError(ValidateDestroy())) {
|
if (GetDevice()->ConsumedError(ValidateDestroy(), "calling %s.Destroy().", this)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
|
|
Loading…
Reference in New Issue