diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp index efb544589f..a8116c184a 100644 --- a/src/dawn_native/CommandEncoder.cpp +++ b/src/dawn_native/CommandEncoder.cpp @@ -52,10 +52,13 @@ namespace dawn_native { // Compressed Textures will have paddings if their width or height is not a multiple of // 4 at non-zero mipmap levels. - if (Is4x4CompressedFormat(texture->GetFormat())) { + const Format& textureFormat = texture->GetFormat(); + if (textureFormat.isCompressed) { // TODO(jiawei.shao@intel.com): check if there are any overflows. - widthAtLevel = (widthAtLevel + 3) / 4 * 4; - heightAtLevel = (heightAtLevel + 3) / 4 * 4; + uint32_t blockWidth = textureFormat.blockWidth; + uint32_t blockHeight = textureFormat.blockHeight; + widthAtLevel = (widthAtLevel + blockWidth - 1) / blockWidth * blockWidth; + heightAtLevel = (heightAtLevel + blockHeight - 1) / blockHeight * blockHeight; } if (uint64_t(textureCopy.origin.x) + uint64_t(copySize.width) > @@ -107,9 +110,8 @@ namespace dawn_native { return {}; } - MaybeError ValidateTexelBufferOffset(TextureBase* texture, const BufferCopy& bufferCopy) { - uint32_t blockSize = TextureFormatTexelBlockSizeInBytes(texture->GetFormat()); - if (bufferCopy.offset % blockSize != 0) { + MaybeError ValidateTexelBufferOffset(const BufferCopy& bufferCopy, const Format& format) { + if (bufferCopy.offset % format.blockByteSize != 0) { return DAWN_VALIDATION_ERROR( "Buffer offset must be a multiple of the texel or block size"); } @@ -187,10 +189,12 @@ namespace dawn_native { DAWN_TRY(ValidateEntireSubresourceCopied(src, dst, copySize)); } - if (src.texture.Get()->GetFormat() != dst.texture.Get()->GetFormat()) { + if (src.texture.Get()->GetFormat().format != dst.texture.Get()->GetFormat().format) { // Metal requires texture-to-texture copies be the same format return DAWN_VALIDATION_ERROR("Source and destination texture formats must match."); - } else if (TextureFormatHasDepthOrStencil(src.texture.Get()->GetFormat())) { + } + + if (src.texture.Get()->GetFormat().HasDepthOrStencil()) { // D3D12 requires entire subresource to be copied when using CopyTextureRegion is // used with depth/stencil. DAWN_TRY(ValidateEntireSubresourceCopied(src, dst, copySize)); @@ -199,43 +203,38 @@ namespace dawn_native { return {}; } - MaybeError ComputeTextureCopyBufferSize(dawn::TextureFormat textureFormat, + MaybeError ComputeTextureCopyBufferSize(const Format& textureFormat, const Extent3D& copySize, uint32_t rowPitch, uint32_t imageHeight, uint32_t* bufferSize) { DAWN_TRY(ValidateImageHeight(imageHeight, copySize.height)); - uint32_t texelOrBlockSizeInBytes = TextureFormatTexelBlockSizeInBytes(textureFormat); - uint32_t blockWidthInTexels = TextureFormatBlockWidthInTexels(textureFormat); - uint32_t blockHeightInTexels = TextureFormatBlockWidthInTexels(textureFormat); + uint32_t blockByteSize = textureFormat.blockByteSize; + uint32_t blockWidth = textureFormat.blockWidth; + uint32_t blockHeight = textureFormat.blockHeight; // TODO(cwallez@chromium.org): check for overflows - uint32_t slicePitch = rowPitch * imageHeight / blockWidthInTexels; - uint32_t sliceSize = rowPitch * (copySize.height / blockHeightInTexels - 1) + - (copySize.width / blockWidthInTexels) * texelOrBlockSizeInBytes; + uint32_t slicePitch = rowPitch * imageHeight / blockWidth; + uint32_t sliceSize = rowPitch * (copySize.height / blockHeight - 1) + + (copySize.width / blockWidth) * blockByteSize; *bufferSize = (slicePitch * (copySize.depth - 1)) + sliceSize; return {}; } - uint32_t ComputeDefaultRowPitch(TextureBase* texture, uint32_t width) { - const dawn::TextureFormat format = texture->GetFormat(); - uint32_t texelOrBlockSizeInBytes = TextureFormatTexelBlockSizeInBytes(format); - uint32_t blockWidthInTexels = TextureFormatBlockWidthInTexels(format); - return width / blockWidthInTexels * texelOrBlockSizeInBytes; + uint32_t ComputeDefaultRowPitch(const Format& format, uint32_t width) { + return width / format.blockWidth * format.blockByteSize; } - MaybeError ValidateRowPitch(dawn::TextureFormat format, + MaybeError ValidateRowPitch(const Format& format, const Extent3D& copySize, uint32_t rowPitch) { if (rowPitch % kTextureRowPitchAlignment != 0) { return DAWN_VALIDATION_ERROR("Row pitch must be a multiple of 256"); } - uint32_t texelOrBlockSizeInBytes = TextureFormatTexelBlockSizeInBytes(format); - uint32_t blockWidthInTexels = TextureFormatBlockWidthInTexels(format); - if (rowPitch < copySize.width / blockWidthInTexels * texelOrBlockSizeInBytes) { + if (rowPitch < copySize.width / format.blockWidth * format.blockByteSize) { return DAWN_VALIDATION_ERROR( "Row pitch must not be less than the number of bytes per row"); } @@ -243,8 +242,8 @@ namespace dawn_native { return {}; } - MaybeError ValidateImageHeight(dawn::TextureFormat format, uint32_t imageHeight) { - if (imageHeight % TextureFormatBlockHeightInTexels(format) != 0) { + MaybeError ValidateImageHeight(const Format& format, uint32_t imageHeight) { + if (imageHeight % format.blockHeight != 0) { return DAWN_VALIDATION_ERROR( "Image height must be a multiple of compressed texture format block width"); } @@ -252,13 +251,13 @@ namespace dawn_native { return {}; } - MaybeError ValidateImageOrigin(dawn::TextureFormat format, const Origin3D& offset) { - if (offset.x % TextureFormatBlockWidthInTexels(format) != 0) { + MaybeError ValidateImageOrigin(const Format& format, const Origin3D& offset) { + if (offset.x % format.blockWidth != 0) { return DAWN_VALIDATION_ERROR( "Offset.x must be a multiple of compressed texture format block width"); } - if (offset.y % TextureFormatBlockHeightInTexels(format) != 0) { + if (offset.y % format.blockHeight != 0) { return DAWN_VALIDATION_ERROR( "Offset.y must be a multiple of compressed texture format block height"); } @@ -266,13 +265,13 @@ namespace dawn_native { return {}; } - MaybeError ValidateImageCopySize(dawn::TextureFormat format, const Extent3D& extent) { - if (extent.width % TextureFormatBlockWidthInTexels(format) != 0) { + MaybeError ValidateImageCopySize(const Format& format, const Extent3D& extent) { + if (extent.width % format.blockWidth != 0) { return DAWN_VALIDATION_ERROR( "Extent.width must be a multiple of compressed texture format block width"); } - if (extent.height % TextureFormatBlockHeightInTexels(format) != 0) { + if (extent.height % format.blockHeight != 0) { return DAWN_VALIDATION_ERROR( "Extent.height must be a multiple of compressed texture format block height"); } @@ -389,8 +388,9 @@ namespace dawn_native { "The size of the resolve target must be the same as the color attachment"); } - dawn::TextureFormat resolveTargetFormat = colorAttachment->resolveTarget->GetFormat(); - if (resolveTargetFormat != colorAttachment->attachment->GetFormat()) { + dawn::TextureFormat resolveTargetFormat = + colorAttachment->resolveTarget->GetFormat().format; + if (resolveTargetFormat != colorAttachment->attachment->GetFormat().format) { return DAWN_VALIDATION_ERROR( "The format of the resolve target must be the same as the color attachment"); } @@ -409,7 +409,7 @@ namespace dawn_native { DAWN_TRY(device->ValidateObject(colorAttachment->attachment)); const TextureViewBase* attachment = colorAttachment->attachment; - if (!IsColorRenderableTextureFormat(attachment->GetFormat())) { + if (!attachment->GetFormat().IsColor() || !attachment->GetFormat().isRenderable) { return DAWN_VALIDATION_ERROR( "The format of the texture view used as color attachment is not color " "renderable"); @@ -436,7 +436,8 @@ namespace dawn_native { DAWN_TRY(device->ValidateObject(depthStencilAttachment->attachment)); const TextureViewBase* attachment = depthStencilAttachment->attachment; - if (!TextureFormatHasDepthOrStencil(attachment->GetFormat())) { + if (!attachment->GetFormat().HasDepthOrStencil() || + !attachment->GetFormat().isRenderable) { return DAWN_VALIDATION_ERROR( "The format of the texture view used as depth stencil attachment is not a " "depth stencil format"); @@ -783,7 +784,8 @@ namespace dawn_native { copy->destination.level = destination->level; copy->destination.slice = destination->slice; if (source->rowPitch == 0) { - copy->source.rowPitch = ComputeDefaultRowPitch(destination->texture, copySize->width); + copy->source.rowPitch = + ComputeDefaultRowPitch(destination->texture->GetFormat(), copySize->width); } else { copy->source.rowPitch = source->rowPitch; } @@ -819,7 +821,8 @@ namespace dawn_native { copy->destination.buffer = destination->buffer; copy->destination.offset = destination->offset; if (destination->rowPitch == 0) { - copy->destination.rowPitch = ComputeDefaultRowPitch(source->texture, copySize->width); + copy->destination.rowPitch = + ComputeDefaultRowPitch(source->texture->GetFormat(), copySize->width); } else { copy->destination.rowPitch = destination->rowPitch; } @@ -977,8 +980,8 @@ namespace dawn_native { DAWN_TRY(ValidateCopySizeFitsInTexture(copy->destination, copy->copySize)); DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->source, bufferCopySize)); - DAWN_TRY( - ValidateTexelBufferOffset(copy->destination.texture.Get(), copy->source)); + DAWN_TRY(ValidateTexelBufferOffset(copy->source, + copy->destination.texture->GetFormat())); DAWN_TRY(ValidateCanUseAs(copy->source.buffer.Get(), dawn::BufferUsageBit::TransferSrc)); @@ -1011,8 +1014,8 @@ namespace dawn_native { DAWN_TRY(ValidateCopySizeFitsInTexture(copy->source, copy->copySize)); DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->destination, bufferCopySize)); - DAWN_TRY( - ValidateTexelBufferOffset(copy->source.texture.Get(), copy->destination)); + DAWN_TRY(ValidateTexelBufferOffset(copy->destination, + copy->source.texture->GetFormat())); DAWN_TRY(ValidateCanUseAs(copy->source.texture.Get(), dawn::TextureUsageBit::TransferSrc)); diff --git a/src/dawn_native/RenderPipeline.cpp b/src/dawn_native/RenderPipeline.cpp index c4b05126b8..7e85287c1e 100644 --- a/src/dawn_native/RenderPipeline.cpp +++ b/src/dawn_native/RenderPipeline.cpp @@ -124,9 +124,9 @@ namespace dawn_native { DAWN_TRY(ValidateBlendFactor(descriptor->colorBlend.dstFactor)); DAWN_TRY(ValidateColorWriteMask(descriptor->writeMask)); - dawn::TextureFormat format = descriptor->format; - DAWN_TRY(ValidateTextureFormat(format)); - if (!IsColorRenderableTextureFormat(format)) { + Format format; + DAWN_TRY_ASSIGN(format, ConvertFormat(descriptor->format)); + if (!format.IsColor() || !format.isRenderable) { return DAWN_VALIDATION_ERROR("Color format must be color renderable"); } @@ -148,9 +148,9 @@ namespace dawn_native { DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.depthFailOp)); DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.passOp)); - dawn::TextureFormat format = descriptor->format; - DAWN_TRY(ValidateTextureFormat(format)); - if (!IsDepthStencilRenderableTextureFormat(format)) { + Format format; + DAWN_TRY_ASSIGN(format, ConvertFormat(descriptor->format)); + if (!format.HasDepthOrStencil() || !format.isRenderable) { return DAWN_VALIDATION_ERROR( "Depth stencil format must be depth-stencil renderable"); } @@ -503,7 +503,8 @@ namespace dawn_native { } for (uint32_t i : IterateBitSet(mColorAttachmentsSet)) { - if (renderPass->colorAttachments[i].view->GetFormat() != mColorStates[i].format) { + if (renderPass->colorAttachments[i].view->GetFormat().format != + mColorStates[i].format) { return false; } } @@ -513,7 +514,8 @@ namespace dawn_native { } if (mHasDepthStencilAttachment && - (renderPass->depthStencilAttachment.view->GetFormat() != mDepthStencilState.format)) { + (renderPass->depthStencilAttachment.view->GetFormat().format != + mDepthStencilState.format)) { return false; } diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp index e1000d1744..5d0b9651b9 100644 --- a/src/dawn_native/Texture.cpp +++ b/src/dawn_native/Texture.cpp @@ -27,7 +27,7 @@ namespace dawn_native { // TODO(jiawei.shao@intel.com): implement texture view format compatibility rule MaybeError ValidateTextureViewFormatCompatibility(const TextureBase* texture, const TextureViewDescriptor* descriptor) { - if (texture->GetFormat() != descriptor->format) { + if (texture->GetFormat().format != descriptor->format) { return DAWN_VALIDATION_ERROR( "The format of texture view is not compatible to the original texture"); } @@ -86,38 +86,88 @@ namespace dawn_native { } } - bool IsBCFormat(dawn::TextureFormat format) { + // Returns a format with a blockByteSize of 0 for an invalid input format + Format ConvertFormatInternal(dawn::TextureFormat format) { + auto MakeColorFormat = [](dawn::TextureFormat format, bool renderable, + uint32_t byteSize) -> Format { + Format result; + result.format = format; + result.isRenderable = renderable; + result.isCompressed = false; + result.aspect = Format::Aspect::Color; + result.blockByteSize = byteSize; + result.blockWidth = 1; + result.blockHeight = 1; + return result; + }; + + auto MakeDepthStencilFormat = [](dawn::TextureFormat format, Format::Aspect aspect, + uint32_t byteSize) -> Format { + Format result; + result.format = format; + result.isRenderable = true; + result.isCompressed = false; + result.aspect = aspect; + result.blockByteSize = byteSize; + result.blockWidth = 1; + result.blockHeight = 1; + return result; + }; + + auto MakeCompressedFormat = [](dawn::TextureFormat format, uint32_t byteSize, + uint32_t width, uint32_t height) -> Format { + Format result; + result.format = format; + result.isRenderable = false; + result.isCompressed = true; + result.aspect = Format::Aspect::Color; + result.blockByteSize = byteSize; + result.blockWidth = width; + result.blockHeight = height; + return result; + }; + switch (format) { + case dawn::TextureFormat::R8Unorm: + case dawn::TextureFormat::R8Uint: + return MakeColorFormat(format, true, 1); + case dawn::TextureFormat::RG8Unorm: + case dawn::TextureFormat::RG8Uint: + return MakeColorFormat(format, true, 2); + case dawn::TextureFormat::RGBA8Unorm: + case dawn::TextureFormat::RGBA8Uint: + case dawn::TextureFormat::BGRA8Unorm: + return MakeColorFormat(format, true, 4); + case dawn::TextureFormat::Depth24PlusStencil8: + // TODO(cwallez@chromium.org): It isn't clear if this format should be copyable + // because its size isn't well defined, is it 4, 5 or 8? + return MakeDepthStencilFormat(format, Format::Aspect::DepthStencil, 4); case dawn::TextureFormat::BC1RGBAUnorm: case dawn::TextureFormat::BC1RGBAUnormSrgb: + case dawn::TextureFormat::BC4RSnorm: + case dawn::TextureFormat::BC4RUnorm: + return MakeCompressedFormat(format, 8, 4, 4); case dawn::TextureFormat::BC2RGBAUnorm: case dawn::TextureFormat::BC2RGBAUnormSrgb: case dawn::TextureFormat::BC3RGBAUnorm: case dawn::TextureFormat::BC3RGBAUnormSrgb: - case dawn::TextureFormat::BC4RUnorm: - case dawn::TextureFormat::BC4RSnorm: - case dawn::TextureFormat::BC5RGUnorm: case dawn::TextureFormat::BC5RGSnorm: - case dawn::TextureFormat::BC6HRGBUfloat: + case dawn::TextureFormat::BC5RGUnorm: case dawn::TextureFormat::BC6HRGBSfloat: + case dawn::TextureFormat::BC6HRGBUfloat: case dawn::TextureFormat::BC7RGBAUnorm: case dawn::TextureFormat::BC7RGBAUnormSrgb: - return true; + return MakeCompressedFormat(format, 16, 4, 4); + default: - return false; + Format result = {}; + result.blockByteSize = 0; + return result; } } - bool IsCompressedFormat(dawn::TextureFormat format) { - return IsBCFormat(format); - } - - bool IsWritableFormat(dawn::TextureFormat format) { - return !IsBCFormat(format); - } - // TODO(jiawei.shao@intel.com): support more sample count. - MaybeError ValidateSampleCount(const TextureDescriptor* descriptor) { + MaybeError ValidateSampleCount(const TextureDescriptor* descriptor, const Format& format) { if (!IsValidSampleCount(descriptor->sampleCount)) { return DAWN_VALIDATION_ERROR("The sample count of the texture is not supported."); } @@ -134,7 +184,7 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("Multisampled 2D array texture is not supported."); } - if (IsCompressedFormat(descriptor->format)) { + if (format.isCompressed) { return DAWN_VALIDATION_ERROR( "The sample counts of the textures in BC formats must be 1."); } @@ -171,7 +221,7 @@ namespace dawn_native { TextureViewDescriptor MakeDefaultTextureViewDescriptor(const TextureBase* texture) { TextureViewDescriptor descriptor; - descriptor.format = texture->GetFormat(); + descriptor.format = texture->GetFormat().format; descriptor.baseArrayLayer = 0; descriptor.arrayLayerCount = texture->GetArrayLayers(); descriptor.baseMipLevel = 0; @@ -193,7 +243,7 @@ namespace dawn_native { return descriptor; } - MaybeError ValidateTextureSize(const TextureDescriptor* descriptor) { + MaybeError ValidateTextureSize(const TextureDescriptor* descriptor, const Format& format) { ASSERT(descriptor->size.width != 0 && descriptor->size.height != 0); if (Log2(std::max(descriptor->size.width, descriptor->size.height)) + 1 < @@ -201,63 +251,43 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("Texture has too many mip levels"); } - if (Is4x4CompressedFormat(descriptor->format)) { - if (descriptor->size.width % 4 != 0 || descriptor->size.height % 4 != 0) { + if (format.isCompressed && (descriptor->size.width % format.blockWidth != 0 || + descriptor->size.height % format.blockHeight != 0)) { + return DAWN_VALIDATION_ERROR( + "The size of the texture is incompatible with the texture format"); + } + + return {}; + } + + MaybeError ValidateTextureUsage(const TextureDescriptor* descriptor, const Format& format) { + DAWN_TRY(ValidateTextureUsageBit(descriptor->usage)); + if (format.isCompressed) { + constexpr dawn::TextureUsageBit kValidUsage = dawn::TextureUsageBit::Sampled | + dawn::TextureUsageBit::TransferSrc | + dawn::TextureUsageBit::TransferDst; + if (descriptor->usage & (~kValidUsage)) { return DAWN_VALIDATION_ERROR( - "The size of the texture is incompatible with the texture format"); + "Compressed texture format is incompatible with the texture usage"); } } return {}; } + } // anonymous namespace - bool Is4x4CompressedFormat(dawn::TextureFormat format) { - return IsBCFormat(format); - } - - // We treat non-compressed texture formats as the block texture formats in 1x1 blocks. - uint32_t TextureFormatBlockWidthInTexels(dawn::TextureFormat format) { - if (Is4x4CompressedFormat(format)) { - return 4; - } - - return 1; - } - - // We treat non-compressed texture formats as the block texture formats in 1x1 blocks. - uint32_t TextureFormatBlockHeightInTexels(dawn::TextureFormat format) { - if (Is4x4CompressedFormat(format)) { - return 4; - } - - return 1; - } - - MaybeError ValidateTextureUsageBit(const TextureDescriptor* descriptor) { - DAWN_TRY(ValidateTextureUsageBit(descriptor->usage)); - if (!IsWritableFormat(descriptor->format)) { - constexpr dawn::TextureUsageBit kValidUsage = dawn::TextureUsageBit::Sampled | - dawn::TextureUsageBit::TransferSrc | - dawn::TextureUsageBit::TransferDst; - if (descriptor->usage & (~kValidUsage)) { - return DAWN_VALIDATION_ERROR( - "Texture format is incompatible with the texture usage"); - } - } - - return {}; - } - MaybeError ValidateTextureDescriptor(DeviceBase*, const TextureDescriptor* descriptor) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); } - DAWN_TRY(ValidateTextureUsageBit(descriptor)); + Format format; + DAWN_TRY_ASSIGN(format, ConvertFormat(descriptor->format)); + + DAWN_TRY(ValidateTextureUsage(descriptor, format)); DAWN_TRY(ValidateTextureDimension(descriptor->dimension)); - DAWN_TRY(ValidateTextureFormat(descriptor->format)); - DAWN_TRY(ValidateSampleCount(descriptor)); + DAWN_TRY(ValidateSampleCount(descriptor, format)); // TODO(jiawei.shao@intel.com): check stuff based on the dimension if (descriptor->size.width == 0 || descriptor->size.height == 0 || @@ -266,7 +296,7 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("Cannot create an empty texture"); } - DAWN_TRY(ValidateTextureSize(descriptor)); + DAWN_TRY(ValidateTextureSize(descriptor, format)); return {}; } @@ -307,113 +337,6 @@ namespace dawn_native { return {}; } - // We treat non-compressed texture formats as the block texture formats in 1x1 blocks. - uint32_t TextureFormatTexelBlockSizeInBytes(dawn::TextureFormat format) { - switch (format) { - // Non-compressed texture formats - case dawn::TextureFormat::R8Unorm: - case dawn::TextureFormat::R8Uint: - return 1; - case dawn::TextureFormat::RG8Unorm: - case dawn::TextureFormat::RG8Uint: - return 2; - case dawn::TextureFormat::RGBA8Unorm: - case dawn::TextureFormat::RGBA8Uint: - case dawn::TextureFormat::BGRA8Unorm: - return 4; - case dawn::TextureFormat::Depth24PlusStencil8: - return 8; - - // BC formats - case dawn::TextureFormat::BC1RGBAUnorm: - case dawn::TextureFormat::BC1RGBAUnormSrgb: - case dawn::TextureFormat::BC4RSnorm: - case dawn::TextureFormat::BC4RUnorm: - return 8; - case dawn::TextureFormat::BC2RGBAUnorm: - case dawn::TextureFormat::BC2RGBAUnormSrgb: - case dawn::TextureFormat::BC3RGBAUnorm: - case dawn::TextureFormat::BC3RGBAUnormSrgb: - case dawn::TextureFormat::BC5RGSnorm: - case dawn::TextureFormat::BC5RGUnorm: - case dawn::TextureFormat::BC6HRGBSfloat: - case dawn::TextureFormat::BC6HRGBUfloat: - case dawn::TextureFormat::BC7RGBAUnorm: - case dawn::TextureFormat::BC7RGBAUnormSrgb: - return 16; - - default: - UNREACHABLE(); - } - } - - bool TextureFormatHasDepth(dawn::TextureFormat format) { - switch (format) { - case dawn::TextureFormat::Depth24PlusStencil8: - return true; - default: - return false; - } - } - - bool TextureFormatHasStencil(dawn::TextureFormat format) { - switch (format) { - case dawn::TextureFormat::Depth24PlusStencil8: - return true; - default: - return false; - } - } - - bool TextureFormatHasDepthOrStencil(dawn::TextureFormat format) { - switch (format) { - case dawn::TextureFormat::Depth24PlusStencil8: - return true; - default: - return false; - } - } - - bool IsColorRenderableTextureFormat(dawn::TextureFormat format) { - switch (format) { - case dawn::TextureFormat::BGRA8Unorm: - case dawn::TextureFormat::RGBA8Uint: - case dawn::TextureFormat::RGBA8Unorm: - case dawn::TextureFormat::RG8Uint: - case dawn::TextureFormat::RG8Unorm: - case dawn::TextureFormat::R8Uint: - case dawn::TextureFormat::R8Unorm: - return true; - - case dawn::TextureFormat::Depth24PlusStencil8: - return false; - - default: - UNREACHABLE(); - return false; - } - } - - bool IsDepthStencilRenderableTextureFormat(dawn::TextureFormat format) { - switch (format) { - case dawn::TextureFormat::Depth24PlusStencil8: - return true; - - case dawn::TextureFormat::BGRA8Unorm: - case dawn::TextureFormat::RGBA8Uint: - case dawn::TextureFormat::RGBA8Unorm: - case dawn::TextureFormat::RG8Uint: - case dawn::TextureFormat::RG8Unorm: - case dawn::TextureFormat::R8Uint: - case dawn::TextureFormat::R8Unorm: - return false; - - default: - UNREACHABLE(); - return false; - } - } - bool IsValidSampleCount(uint32_t sampleCount) { switch (sampleCount) { case 1: @@ -425,6 +348,36 @@ namespace dawn_native { } } + ResultOrError ConvertFormat(dawn::TextureFormat format) { + Format result = ConvertFormatInternal(format); + if (result.blockByteSize == 0) { + return DAWN_VALIDATION_ERROR("Invalid texture format"); + } + return result; + } + + Format ConvertValidFormat(dawn::TextureFormat format) { + Format result = ConvertFormatInternal(format); + ASSERT(result.blockByteSize != 0); + return result; + } + + bool Format::IsColor() const { + return aspect == Aspect::Color; + } + + bool Format::HasDepth() const { + return aspect == Depth || aspect == DepthStencil; + } + + bool Format::HasStencil() const { + return aspect == Stencil || aspect == DepthStencil; + } + + bool Format::HasDepthOrStencil() const { + return aspect != Color; + } + // TextureBase TextureBase::TextureBase(DeviceBase* device, @@ -432,7 +385,7 @@ namespace dawn_native { TextureState state) : ObjectBase(device), mDimension(descriptor->dimension), - mFormat(descriptor->format), + mFormat(ConvertValidFormat(descriptor->format)), mSize(descriptor->size), mArrayLayerCount(descriptor->arrayLayerCount), mMipLevelCount(descriptor->mipLevelCount), @@ -459,7 +412,7 @@ namespace dawn_native { } // TODO(jiawei.shao@intel.com): return more information about texture format - dawn::TextureFormat TextureBase::GetFormat() const { + const Format& TextureBase::GetFormat() const { ASSERT(!IsError()); return mFormat; } @@ -586,7 +539,7 @@ namespace dawn_native { TextureViewBase::TextureViewBase(TextureBase* texture, const TextureViewDescriptor* descriptor) : ObjectBase(texture->GetDevice()), mTexture(texture), - mFormat(descriptor->format), + mFormat(ConvertValidFormat(descriptor->format)), mBaseMipLevel(descriptor->baseMipLevel), mMipLevelCount(descriptor->mipLevelCount), mBaseArrayLayer(descriptor->baseArrayLayer), @@ -612,7 +565,7 @@ namespace dawn_native { return mTexture.Get(); } - dawn::TextureFormat TextureViewBase::GetFormat() const { + const Format& TextureViewBase::GetFormat() const { ASSERT(!IsError()); return mFormat; } diff --git a/src/dawn_native/Texture.h b/src/dawn_native/Texture.h index db6a3e4f52..ebf3148aa8 100644 --- a/src/dawn_native/Texture.h +++ b/src/dawn_native/Texture.h @@ -29,18 +29,8 @@ namespace dawn_native { const TextureBase* texture, const TextureViewDescriptor* descriptor); - uint32_t TextureFormatTexelBlockSizeInBytes(dawn::TextureFormat format); - bool TextureFormatHasDepth(dawn::TextureFormat format); - bool TextureFormatHasStencil(dawn::TextureFormat format); - bool TextureFormatHasDepthOrStencil(dawn::TextureFormat format); - bool IsColorRenderableTextureFormat(dawn::TextureFormat format); - bool IsDepthStencilRenderableTextureFormat(dawn::TextureFormat format); bool IsValidSampleCount(uint32_t sampleCount); - bool Is4x4CompressedFormat(dawn::TextureFormat format); - uint32_t TextureFormatBlockWidthInTexels(dawn::TextureFormat format); - uint32_t TextureFormatBlockHeightInTexels(dawn::TextureFormat format); - static constexpr dawn::TextureUsageBit kReadOnlyTextureUsages = dawn::TextureUsageBit::TransferSrc | dawn::TextureUsageBit::Sampled | dawn::TextureUsageBit::Present; @@ -49,6 +39,36 @@ namespace dawn_native { dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Storage | dawn::TextureUsageBit::OutputAttachment; + struct Format { + enum Aspect { + Color, + Depth, + Stencil, + DepthStencil, + }; + + dawn::TextureFormat format; + bool isRenderable; + bool isCompressed; + Aspect aspect; + + uint32_t blockByteSize; + uint32_t blockWidth; + uint32_t blockHeight; + + bool IsColor() const; + bool HasDepth() const; + bool HasStencil() const; + bool HasDepthOrStencil() const; + }; + + // Returns the Format corresponding to the dawn::TextureFormat or an error if the format + // isn't valid. + ResultOrError ConvertFormat(dawn::TextureFormat format); + + // Returns the Format corresponding to the dawn::TextureFormat and assumes the format is valid. + Format ConvertValidFormat(dawn::TextureFormat format); + class TextureBase : public ObjectBase { public: enum class TextureState { OwnedInternal, OwnedExternal, Destroyed }; @@ -58,7 +78,7 @@ namespace dawn_native { static TextureBase* MakeError(DeviceBase* device); dawn::TextureDimension GetDimension() const; - dawn::TextureFormat GetFormat() const; + const Format& GetFormat() const; const Extent3D& GetSize() const; uint32_t GetArrayLayers() const; uint32_t GetNumMipLevels() const; @@ -93,7 +113,8 @@ namespace dawn_native { MaybeError ValidateDestroy() const; dawn::TextureDimension mDimension; - dawn::TextureFormat mFormat; + // TODO(cwallez@chromium.org): This should be deduplicated in the Device + Format mFormat; Extent3D mSize; uint32_t mArrayLayerCount; uint32_t mMipLevelCount; @@ -114,7 +135,7 @@ namespace dawn_native { const TextureBase* GetTexture() const; TextureBase* GetTexture(); - dawn::TextureFormat GetFormat() const; + const Format& GetFormat() const; uint32_t GetBaseMipLevel() const; uint32_t GetLevelCount() const; uint32_t GetBaseArrayLayer() const; @@ -125,7 +146,8 @@ namespace dawn_native { Ref mTexture; - dawn::TextureFormat mFormat; + // TODO(cwallez@chromium.org): This should be deduplicated in the Device + Format mFormat; uint32_t mBaseMipLevel; uint32_t mMipLevelCount; uint32_t mBaseArrayLayer; diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index bfdc84aba4..8f404b07ce 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -505,9 +505,8 @@ namespace dawn_native { namespace d3d12 { auto copySplit = ComputeTextureCopySplit( copy->destination.origin, copy->copySize, - static_cast( - TextureFormatTexelBlockSizeInBytes(texture->GetFormat())), - copy->source.offset, copy->source.rowPitch, copy->source.imageHeight); + texture->GetFormat().blockByteSize, copy->source.offset, + copy->source.rowPitch, copy->source.imageHeight); D3D12_TEXTURE_COPY_LOCATION textureLocation = CreateTextureCopyLocationForTexture(*texture, copy->destination.level, @@ -549,9 +548,7 @@ namespace dawn_native { namespace d3d12 { buffer->TransitionUsageNow(commandList, dawn::BufferUsageBit::TransferDst); auto copySplit = ComputeTextureCopySplit( - copy->source.origin, copy->copySize, - static_cast( - TextureFormatTexelBlockSizeInBytes(texture->GetFormat())), + copy->source.origin, copy->copySize, texture->GetFormat().blockByteSize, copy->destination.offset, copy->destination.rowPitch, copy->destination.imageHeight); @@ -749,9 +746,9 @@ namespace dawn_native { namespace d3d12 { Texture* texture = ToBackend(renderPass->depthStencilAttachment.view->GetTexture()); // Load op - depth/stencil - bool doDepthClear = TextureFormatHasDepth(texture->GetFormat()) && + bool doDepthClear = texture->GetFormat().HasDepth() && (attachmentInfo.depthLoadOp == dawn::LoadOp::Clear); - bool doStencilClear = TextureFormatHasStencil(texture->GetFormat()) && + bool doStencilClear = texture->GetFormat().HasStencil() && (attachmentInfo.stencilLoadOp == dawn::LoadOp::Clear); D3D12_CLEAR_FLAGS clearFlags = {}; diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp index d119d73d4b..d698c89bd4 100644 --- a/src/dawn_native/d3d12/TextureD3D12.cpp +++ b/src/dawn_native/d3d12/TextureD3D12.cpp @@ -21,8 +21,7 @@ namespace dawn_native { namespace d3d12 { namespace { - D3D12_RESOURCE_STATES D3D12TextureUsage(dawn::TextureUsageBit usage, - dawn::TextureFormat format) { + D3D12_RESOURCE_STATES D3D12TextureUsage(dawn::TextureUsageBit usage, const Format& format) { D3D12_RESOURCE_STATES resourceState = D3D12_RESOURCE_STATE_COMMON; // Present is an exclusive flag. @@ -44,7 +43,7 @@ namespace dawn_native { namespace d3d12 { resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS; } if (usage & dawn::TextureUsageBit::OutputAttachment) { - if (TextureFormatHasDepth(format) || TextureFormatHasStencil(format)) { + if (format.HasDepthOrStencil()) { resourceState |= D3D12_RESOURCE_STATE_DEPTH_WRITE; } else { resourceState |= D3D12_RESOURCE_STATE_RENDER_TARGET; @@ -55,7 +54,7 @@ namespace dawn_native { namespace d3d12 { } D3D12_RESOURCE_FLAGS D3D12ResourceFlags(dawn::TextureUsageBit usage, - dawn::TextureFormat format, + const Format& format, bool isMultisampledTexture) { D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE; @@ -68,7 +67,7 @@ namespace dawn_native { namespace d3d12 { // https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_resource // _desc if ((usage & dawn::TextureUsageBit::OutputAttachment) || isMultisampledTexture) { - if (TextureFormatHasDepth(format) || TextureFormatHasStencil(format)) { + if (format.HasDepthOrStencil()) { flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; } else { flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; @@ -126,7 +125,7 @@ namespace dawn_native { namespace d3d12 { resourceDescriptor.DepthOrArraySize = GetDepthOrArraySize(); resourceDescriptor.MipLevels = static_cast(GetNumMipLevels()); - resourceDescriptor.Format = D3D12TextureFormat(GetFormat()); + resourceDescriptor.Format = D3D12TextureFormat(GetFormat().format); resourceDescriptor.SampleDesc.Count = descriptor->sampleCount; // TODO(bryan.bernhart@intel.com): investigate how to specify standard MSAA sample pattern. resourceDescriptor.SampleDesc.Quality = 0; @@ -225,7 +224,7 @@ namespace dawn_native { namespace d3d12 { } DXGI_FORMAT Texture::GetD3D12Format() const { - return D3D12TextureFormat(GetFormat()); + return D3D12TextureFormat(GetFormat().format); } ID3D12Resource* Texture::GetD3D12Resource() const { @@ -329,7 +328,7 @@ namespace dawn_native { namespace d3d12 { } DXGI_FORMAT TextureView::GetD3D12Format() const { - return D3D12TextureFormat(GetFormat()); + return D3D12TextureFormat(GetFormat().format); } const D3D12_SHADER_RESOURCE_VIEW_DESC& TextureView::GetSRVDescriptor() const { diff --git a/src/dawn_native/metal/CommandBufferMTL.mm b/src/dawn_native/metal/CommandBufferMTL.mm index 20ff0a96f9..ac4bafe053 100644 --- a/src/dawn_native/metal/CommandBufferMTL.mm +++ b/src/dawn_native/metal/CommandBufferMTL.mm @@ -89,9 +89,9 @@ namespace dawn_native { namespace metal { // TODO(jiawei.shao@intel.com): support rendering into a layer of a texture. id texture = ToBackend(attachmentInfo.view->GetTexture())->GetMTLTexture(); - dawn::TextureFormat format = attachmentInfo.view->GetTexture()->GetFormat(); + const Format& format = attachmentInfo.view->GetTexture()->GetFormat(); - if (TextureFormatHasDepth(format)) { + if (format.HasDepth()) { descriptor.depthAttachment.texture = texture; descriptor.depthAttachment.storeAction = MTLStoreActionStore; @@ -103,7 +103,7 @@ namespace dawn_native { namespace metal { } } - if (TextureFormatHasStencil(format)) { + if (format.HasStencil()) { descriptor.stencilAttachment.texture = texture; descriptor.stencilAttachment.storeAction = MTLStoreActionStore; @@ -453,8 +453,7 @@ namespace dawn_native { namespace metal { // Doing the last row copy with the exact number of bytes in last row. // Like copy to a 1D texture to workaround the issue. - uint32_t lastRowDataSize = - copySize.width * TextureFormatTexelBlockSizeInBytes(texture->GetFormat()); + uint32_t lastRowDataSize = copySize.width * texture->GetFormat().blockByteSize; [encoders.blit copyFromBuffer:buffer->GetMTLBuffer() @@ -567,8 +566,7 @@ namespace dawn_native { namespace metal { // Doing the last row copy with the exact number of bytes in last row. // Like copy from a 1D texture to workaround the issue. - uint32_t lastRowDataSize = - copySize.width * TextureFormatTexelBlockSizeInBytes(texture->GetFormat()); + uint32_t lastRowDataSize = copySize.width * texture->GetFormat().blockByteSize; [encoders.blit copyFromTexture:texture->GetMTLTexture() diff --git a/src/dawn_native/metal/TextureMTL.mm b/src/dawn_native/metal/TextureMTL.mm index 8c2d90f83d..6a2d12fb55 100644 --- a/src/dawn_native/metal/TextureMTL.mm +++ b/src/dawn_native/metal/TextureMTL.mm @@ -82,7 +82,7 @@ namespace dawn_native { namespace metal { bool RequiresCreatingNewTextureView(const TextureBase* texture, const TextureViewDescriptor* textureViewDescriptor) { - if (texture->GetFormat() != textureViewDescriptor->format) { + if (texture->GetFormat().format != textureViewDescriptor->format) { return true; } diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp index 702d5f3619..92209f6cce 100644 --- a/src/dawn_native/opengl/CommandBufferGL.cpp +++ b/src/dawn_native/opengl/CommandBufferGL.cpp @@ -389,9 +389,8 @@ namespace dawn_native { namespace opengl { gl.ActiveTexture(GL_TEXTURE0); gl.BindTexture(target, texture->GetHandle()); - gl.PixelStorei( - GL_UNPACK_ROW_LENGTH, - src.rowPitch / TextureFormatTexelBlockSizeInBytes(texture->GetFormat())); + gl.PixelStorei(GL_UNPACK_ROW_LENGTH, + src.rowPitch / texture->GetFormat().blockByteSize); gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, src.imageHeight); switch (texture->GetDimension()) { case dawn::TextureDimension::e2D: @@ -452,9 +451,8 @@ namespace dawn_native { namespace opengl { } gl.BindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle()); - gl.PixelStorei( - GL_PACK_ROW_LENGTH, - dst.rowPitch / TextureFormatTexelBlockSizeInBytes(texture->GetFormat())); + gl.PixelStorei(GL_PACK_ROW_LENGTH, + dst.rowPitch / texture->GetFormat().blockByteSize); gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, dst.imageHeight); ASSERT(copySize.depth == 1 && src.origin.z == 0); void* offset = reinterpret_cast(static_cast(dst.offset)); @@ -582,7 +580,7 @@ namespace dawn_native { namespace opengl { // TODO(kainino@chromium.org): the color clears (later in // this function) may be undefined for non-normalized integer formats. - dawn::TextureFormat format = textureView->GetTexture()->GetFormat(); + dawn::TextureFormat format = textureView->GetTexture()->GetFormat().format; ASSERT(format == dawn::TextureFormat::RGBA8Unorm || format == dawn::TextureFormat::RG8Unorm || format == dawn::TextureFormat::R8Unorm || @@ -593,20 +591,25 @@ namespace dawn_native { namespace opengl { if (renderPass->hasDepthStencilAttachment) { TextureViewBase* textureView = renderPass->depthStencilAttachment.view.Get(); GLuint texture = ToBackend(textureView->GetTexture())->GetHandle(); - dawn::TextureFormat format = textureView->GetTexture()->GetFormat(); + const Format& format = textureView->GetTexture()->GetFormat(); // Attach depth/stencil buffer. GLenum glAttachment = 0; // TODO(kainino@chromium.org): it may be valid to just always use // GL_DEPTH_STENCIL_ATTACHMENT here. - if (TextureFormatHasDepth(format)) { - if (TextureFormatHasStencil(format)) { - glAttachment = GL_DEPTH_STENCIL_ATTACHMENT; - } else { + switch (format.aspect) { + case Format::Aspect::Depth: glAttachment = GL_DEPTH_ATTACHMENT; - } - } else { - glAttachment = GL_STENCIL_ATTACHMENT; + break; + case Format::Aspect::Stencil: + glAttachment = GL_STENCIL_ATTACHMENT; + break; + case Format::Aspect::DepthStencil: + glAttachment = GL_DEPTH_STENCIL_ATTACHMENT; + break; + default: + UNREACHABLE(); + break; } GLenum target = ToBackend(textureView->GetTexture())->GetGLTarget(); @@ -614,7 +617,7 @@ namespace dawn_native { namespace opengl { // TODO(kainino@chromium.org): the depth/stencil clears (later in // this function) may be undefined for other texture formats. - ASSERT(format == dawn::TextureFormat::Depth24PlusStencil8); + ASSERT(format.format == dawn::TextureFormat::Depth24PlusStencil8); } } @@ -639,20 +642,19 @@ namespace dawn_native { namespace opengl { if (renderPass->hasDepthStencilAttachment) { const auto& attachmentInfo = renderPass->depthStencilAttachment; - dawn::TextureFormat attachmentFormat = - attachmentInfo.view->GetTexture()->GetFormat(); + const Format& attachmentFormat = attachmentInfo.view->GetTexture()->GetFormat(); // Load op - depth/stencil - bool doDepthClear = TextureFormatHasDepth(attachmentFormat) && + bool doDepthClear = attachmentFormat.HasDepth() && (attachmentInfo.depthLoadOp == dawn::LoadOp::Clear); - bool doStencilClear = TextureFormatHasStencil(attachmentFormat) && + bool doStencilClear = attachmentFormat.HasStencil() && (attachmentInfo.stencilLoadOp == dawn::LoadOp::Clear); if (doDepthClear) { gl.DepthMask(GL_TRUE); } if (doStencilClear) { - gl.StencilMask(GetStencilMaskFromStencilFormat(attachmentFormat)); + gl.StencilMask(GetStencilMaskFromStencilFormat(attachmentFormat.format)); } if (doDepthClear && doStencilClear) { diff --git a/src/dawn_native/opengl/TextureGL.cpp b/src/dawn_native/opengl/TextureGL.cpp index 76914dcdd2..3c5f01d8e6 100644 --- a/src/dawn_native/opengl/TextureGL.cpp +++ b/src/dawn_native/opengl/TextureGL.cpp @@ -102,7 +102,7 @@ namespace dawn_native { namespace opengl { bool RequiresCreatingNewTextureView(const TextureBase* texture, const TextureViewDescriptor* textureViewDescriptor) { - if (texture->GetFormat() != textureViewDescriptor->format) { + if (texture->GetFormat().format != textureViewDescriptor->format) { return true; } @@ -139,7 +139,7 @@ namespace dawn_native { namespace opengl { uint32_t arrayLayers = GetArrayLayers(); uint32_t sampleCount = GetSampleCount(); - auto formatInfo = GetGLFormatInfo(GetFormat()); + auto formatInfo = GetGLFormatInfo(GetFormat().format); gl.BindTexture(mTarget, mHandle); @@ -171,7 +171,7 @@ namespace dawn_native { namespace opengl { if (GetDevice()->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) { static constexpr uint32_t MAX_TEXEL_SIZE = 16; - ASSERT(TextureFormatTexelBlockSizeInBytes(GetFormat()) <= MAX_TEXEL_SIZE); + ASSERT(GetFormat().blockByteSize <= MAX_TEXEL_SIZE); GLubyte clearColor[MAX_TEXEL_SIZE]; std::fill(clearColor, clearColor + MAX_TEXEL_SIZE, 255); @@ -208,7 +208,7 @@ namespace dawn_native { namespace opengl { } TextureFormatInfo Texture::GetGLFormat() const { - return GetGLFormatInfo(GetFormat()); + return GetGLFormatInfo(GetFormat().format); } // TextureView diff --git a/src/dawn_native/vulkan/CommandBufferVk.cpp b/src/dawn_native/vulkan/CommandBufferVk.cpp index f200e2b110..7fdb225f89 100644 --- a/src/dawn_native/vulkan/CommandBufferVk.cpp +++ b/src/dawn_native/vulkan/CommandBufferVk.cpp @@ -50,8 +50,7 @@ namespace dawn_native { namespace vulkan { region.bufferOffset = bufferCopy.offset; // In Vulkan the row length is in texels while it is in bytes for Dawn - region.bufferRowLength = - bufferCopy.rowPitch / TextureFormatTexelBlockSizeInBytes(texture->GetFormat()); + region.bufferRowLength = bufferCopy.rowPitch / texture->GetFormat().blockByteSize; region.bufferImageHeight = bufferCopy.imageHeight; region.imageSubresource.aspectMask = texture->GetVkAspectMask(); @@ -190,12 +189,13 @@ namespace dawn_native { namespace vulkan { default: { UNREACHABLE(); } break; } - query.SetColor(i, attachmentInfo.view->GetFormat(), loadOp, hasResolveTarget); + query.SetColor(i, attachmentInfo.view->GetFormat().format, loadOp, + hasResolveTarget); } if (renderPass->hasDepthStencilAttachment) { auto& attachmentInfo = renderPass->depthStencilAttachment; - query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat(), + query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat().format, attachmentInfo.depthLoadOp, attachmentInfo.stencilLoadOp); if (attachmentInfo.depthLoadOp == dawn::LoadOp::Load || attachmentInfo.stencilLoadOp == dawn::LoadOp::Load) { diff --git a/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp b/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp index bfcde4ce80..95b53e5485 100644 --- a/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp +++ b/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp @@ -92,8 +92,8 @@ namespace dawn_native { namespace vulkan { createInfo.imageExtent.width = width; createInfo.imageExtent.height = height; createInfo.imageArrayLayers = 1; - createInfo.imageUsage = - VulkanImageUsage(static_cast(usage), mConfig.format); + createInfo.imageUsage = VulkanImageUsage(static_cast(usage), + ConvertValidFormat(mConfig.format)); createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; createInfo.queueFamilyIndexCount = 0; createInfo.pQueueFamilyIndices = nullptr; diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp index cbd7644531..dbf94618ba 100644 --- a/src/dawn_native/vulkan/TextureVk.cpp +++ b/src/dawn_native/vulkan/TextureVk.cpp @@ -51,7 +51,7 @@ namespace dawn_native { namespace vulkan { } // Computes which vulkan access type could be required for the given Dawn usage. - VkAccessFlags VulkanAccessFlags(dawn::TextureUsageBit usage, dawn::TextureFormat format) { + VkAccessFlags VulkanAccessFlags(dawn::TextureUsageBit usage, const Format& format) { VkAccessFlags flags = 0; if (usage & dawn::TextureUsageBit::TransferSrc) { @@ -67,7 +67,7 @@ namespace dawn_native { namespace vulkan { flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; } if (usage & dawn::TextureUsageBit::OutputAttachment) { - if (TextureFormatHasDepthOrStencil(format)) { + if (format.HasDepthOrStencil()) { flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; } else { @@ -88,7 +88,7 @@ namespace dawn_native { namespace vulkan { } // Chooses which Vulkan image layout should be used for the given Dawn usage - VkImageLayout VulkanImageLayout(dawn::TextureUsageBit usage, dawn::TextureFormat format) { + VkImageLayout VulkanImageLayout(dawn::TextureUsageBit usage, const Format& format) { if (usage == dawn::TextureUsageBit::None) { return VK_IMAGE_LAYOUT_UNDEFINED; } @@ -114,7 +114,7 @@ namespace dawn_native { namespace vulkan { case dawn::TextureUsageBit::Storage: return VK_IMAGE_LAYOUT_GENERAL; case dawn::TextureUsageBit::OutputAttachment: - if (TextureFormatHasDepthOrStencil(format)) { + if (format.HasDepthOrStencil()) { return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; } else { return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; @@ -128,7 +128,7 @@ namespace dawn_native { namespace vulkan { // Computes which Vulkan pipeline stage can access a texture in the given Dawn usage VkPipelineStageFlags VulkanPipelineStage(dawn::TextureUsageBit usage, - dawn::TextureFormat format) { + const Format& format) { VkPipelineStageFlags flags = 0; if (usage == dawn::TextureUsageBit::None) { @@ -145,7 +145,7 @@ namespace dawn_native { namespace vulkan { VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; } if (usage & dawn::TextureUsageBit::OutputAttachment) { - if (TextureFormatHasDepthOrStencil(format)) { + if (format.HasDepthOrStencil()) { flags |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; // TODO(cwallez@chromium.org): This is missing the stage where the depth and @@ -170,22 +170,20 @@ namespace dawn_native { namespace vulkan { } // Computes which Vulkan texture aspects are relevant for the given Dawn format - VkImageAspectFlags VulkanAspectMask(dawn::TextureFormat format) { - bool isDepth = TextureFormatHasDepth(format); - bool isStencil = TextureFormatHasStencil(format); - - VkImageAspectFlags flags = 0; - if (isDepth) { - flags |= VK_IMAGE_ASPECT_DEPTH_BIT; + VkImageAspectFlags VulkanAspectMask(const Format& format) { + switch (format.aspect) { + case Format::Aspect::Color: + return VK_IMAGE_ASPECT_COLOR_BIT; + case Format::Aspect::Depth: + return VK_IMAGE_ASPECT_DEPTH_BIT; + case Format::Aspect::Stencil: + return VK_IMAGE_ASPECT_STENCIL_BIT; + case Format::Aspect::DepthStencil: + return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + default: + UNREACHABLE(); + return 0; } - if (isStencil) { - flags |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - - if (flags != 0) { - return flags; - } - return VK_IMAGE_ASPECT_COLOR_BIT; } VkExtent3D VulkanExtent3D(const Extent3D& extent) { @@ -236,7 +234,7 @@ namespace dawn_native { namespace vulkan { // Converts the Dawn usage flags to Vulkan usage flags. Also needs the format to choose // between color and depth attachment usages. - VkImageUsageFlags VulkanImageUsage(dawn::TextureUsageBit usage, dawn::TextureFormat format) { + VkImageUsageFlags VulkanImageUsage(dawn::TextureUsageBit usage, const Format& format) { VkImageUsageFlags flags = 0; if (usage & dawn::TextureUsageBit::TransferSrc) { @@ -252,7 +250,7 @@ namespace dawn_native { namespace vulkan { flags |= VK_IMAGE_USAGE_STORAGE_BIT; } if (usage & dawn::TextureUsageBit::OutputAttachment) { - if (TextureFormatHasDepthOrStencil(format)) { + if (format.HasDepthOrStencil()) { flags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; } else { flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; @@ -283,7 +281,7 @@ namespace dawn_native { namespace vulkan { createInfo.pNext = nullptr; createInfo.flags = 0; createInfo.imageType = VulkanImageType(GetDimension()); - createInfo.format = VulkanImageFormat(GetFormat()); + createInfo.format = VulkanImageFormat(GetFormat().format); createInfo.extent = VulkanExtent3D(GetSize()); createInfo.mipLevels = GetNumMipLevels(); createInfo.arrayLayers = GetArrayLayers(); @@ -334,7 +332,7 @@ namespace dawn_native { namespace vulkan { TransitionUsageNow(ToBackend(GetDevice())->GetPendingCommandBuffer(), dawn::TextureUsageBit::TransferDst); - if (TextureFormatHasDepthOrStencil(GetFormat())) { + if (GetFormat().HasDepthOrStencil()) { VkClearDepthStencilValue clear_color[1]; clear_color[0].depth = 1.0f; clear_color[0].stencil = 1u; @@ -396,7 +394,7 @@ namespace dawn_native { namespace vulkan { return; } - dawn::TextureFormat format = GetFormat(); + const Format& format = GetFormat(); VkPipelineStageFlags srcStages = VulkanPipelineStage(mLastUsage, format); VkPipelineStageFlags dstStages = VulkanPipelineStage(usage, format); @@ -439,7 +437,7 @@ namespace dawn_native { namespace vulkan { range.layerCount = layerCount; TransitionUsageNow(commands, dawn::TextureUsageBit::TransferDst); - if (TextureFormatHasDepthOrStencil(GetFormat())) { + if (GetFormat().HasDepthOrStencil()) { VkClearDepthStencilValue clear_color[1]; clear_color[0].depth = 0.0f; clear_color[0].stencil = 0u; @@ -490,7 +488,7 @@ namespace dawn_native { namespace vulkan { createInfo.format = VulkanImageFormat(descriptor->format); createInfo.components = VkComponentMapping{VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}; - createInfo.subresourceRange.aspectMask = VulkanAspectMask(descriptor->format); + createInfo.subresourceRange.aspectMask = VulkanAspectMask(GetFormat()); createInfo.subresourceRange.baseMipLevel = descriptor->baseMipLevel; createInfo.subresourceRange.levelCount = descriptor->mipLevelCount; createInfo.subresourceRange.baseArrayLayer = descriptor->baseArrayLayer; diff --git a/src/dawn_native/vulkan/TextureVk.h b/src/dawn_native/vulkan/TextureVk.h index decc997568..41cdf6d30a 100644 --- a/src/dawn_native/vulkan/TextureVk.h +++ b/src/dawn_native/vulkan/TextureVk.h @@ -23,7 +23,7 @@ namespace dawn_native { namespace vulkan { VkFormat VulkanImageFormat(dawn::TextureFormat format); - VkImageUsageFlags VulkanImageUsage(dawn::TextureUsageBit usage, dawn::TextureFormat format); + VkImageUsageFlags VulkanImageUsage(dawn::TextureUsageBit usage, const Format& format); VkSampleCountFlagBits VulkanSampleCount(uint32_t sampleCount); class Texture : public TextureBase {