From 6298d2b70cb67bb929f7817f2186f618ec8f1ca1 Mon Sep 17 00:00:00 2001 From: Corentin Wallez Date: Thu, 15 Oct 2020 09:05:03 +0000 Subject: [PATCH] Format: Move the TexelBlockInfo inside an AspectInfo. In follow up CLs additional will be added to the AspectInfo, like the supported component types. Also simplify the logic for GetTexelInfo since all aspects are the first aspects, except stencil which is always stencil8. Bug: dawn:517 Change-Id: Iebbcb8a7f8fa2c4b7b06f65d6e4e8917c0a85366 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/30100 Commit-Queue: Corentin Wallez Reviewed-by: Austin Eng --- src/dawn_native/CommandBuffer.cpp | 6 +- src/dawn_native/CommandEncoder.cpp | 19 ++-- src/dawn_native/CommandValidation.cpp | 53 +++++------ src/dawn_native/Format.cpp | 90 ++++++------------- src/dawn_native/Format.h | 21 +++-- src/dawn_native/Queue.cpp | 20 ++--- src/dawn_native/Texture.cpp | 22 ++--- src/dawn_native/d3d12/CommandBufferD3D12.cpp | 2 +- src/dawn_native/d3d12/TextureCopySplitter.cpp | 21 ++--- src/dawn_native/d3d12/TextureD3D12.cpp | 13 ++- src/dawn_native/d3d12/UtilsD3D12.cpp | 2 +- src/dawn_native/metal/DeviceMTL.mm | 10 +-- src/dawn_native/metal/TextureMTL.mm | 10 +-- src/dawn_native/metal/UtilsMetal.mm | 21 +++-- src/dawn_native/opengl/CommandBufferGL.cpp | 27 +++--- src/dawn_native/opengl/TextureGL.cpp | 21 +++-- src/dawn_native/vulkan/CommandBufferVk.cpp | 15 ++-- src/dawn_native/vulkan/UtilsVulkan.cpp | 9 +- src/tests/unittests/d3d12/CopySplitTests.cpp | 6 +- 19 files changed, 174 insertions(+), 214 deletions(-) diff --git a/src/dawn_native/CommandBuffer.cpp b/src/dawn_native/CommandBuffer.cpp index fb6089e5d3..f5deec1b0b 100644 --- a/src/dawn_native/CommandBuffer.cpp +++ b/src/dawn_native/CommandBuffer.cpp @@ -168,15 +168,15 @@ namespace dawn_native { const TextureBase* texture = copy->source.texture.Get(); const TexelBlockInfo& blockInfo = - texture->GetFormat().GetTexelBlockInfo(copy->source.aspect); - const uint64_t heightInBlocks = copy->copySize.height / blockInfo.blockHeight; + texture->GetFormat().GetAspectInfo(copy->source.aspect).block; + const uint64_t heightInBlocks = copy->copySize.height / blockInfo.height; if (copy->destination.rowsPerImage > heightInBlocks) { return false; } const uint64_t copyTextureDataSizePerRow = - copy->copySize.width / blockInfo.blockWidth * blockInfo.blockByteSize; + copy->copySize.width / blockInfo.width * blockInfo.byteSize; if (copy->destination.bytesPerRow > copyTextureDataSizePerRow) { return false; } diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp index ec4a0e21cb..ac356258e1 100644 --- a/src/dawn_native/CommandEncoder.cpp +++ b/src/dawn_native/CommandEncoder.cpp @@ -650,7 +650,7 @@ namespace dawn_native { DAWN_TRY(ValidateTextureCopyRange(*destination, *copySize)); } const TexelBlockInfo& blockInfo = - destination->texture->GetFormat().GetTexelBlockInfo(destination->aspect); + destination->texture->GetFormat().GetAspectInfo(destination->aspect).block; if (GetDevice()->IsValidationEnabled()) { DAWN_TRY(ValidateLinearTextureData(source->layout, source->buffer->GetSize(), blockInfo, *copySize)); @@ -662,15 +662,15 @@ namespace dawn_native { // Compute default value for rowsPerImage uint32_t defaultedRowsPerImage = source->layout.rowsPerImage; if (defaultedRowsPerImage == 0) { - ASSERT(copySize->height % blockInfo.blockHeight == 0); - defaultedRowsPerImage = copySize->height / blockInfo.blockHeight; + ASSERT(copySize->height % blockInfo.height == 0); + defaultedRowsPerImage = copySize->height / blockInfo.height; } // In the case of one row copy bytesPerRow might not contain enough bytes uint32_t bytesPerRow = source->layout.bytesPerRow; if (copySize->height <= 1 && copySize->depth <= 1) { bytesPerRow = - Align(copySize->width * blockInfo.blockByteSize, kTextureBytesPerRowAlignment); + Align(copySize->width * blockInfo.byteSize, kTextureBytesPerRowAlignment); } // Skip noop copies. @@ -714,11 +714,10 @@ namespace dawn_native { DAWN_TRY(ValidateTextureCopyRange(*source, *copySize)); } const TexelBlockInfo& blockInfo = - source->texture->GetFormat().GetTexelBlockInfo(source->aspect); + source->texture->GetFormat().GetAspectInfo(source->aspect).block; if (GetDevice()->IsValidationEnabled()) { DAWN_TRY(ValidateLinearTextureData( - destination->layout, destination->buffer->GetSize(), - source->texture->GetFormat().GetTexelBlockInfo(source->aspect), *copySize)); + destination->layout, destination->buffer->GetSize(), blockInfo, *copySize)); mTopLevelTextures.insert(source->texture); mTopLevelBuffers.insert(destination->buffer); @@ -727,15 +726,15 @@ namespace dawn_native { // Compute default value for rowsPerImage uint32_t defaultedRowsPerImage = destination->layout.rowsPerImage; if (defaultedRowsPerImage == 0) { - ASSERT(copySize->height % blockInfo.blockHeight == 0); - defaultedRowsPerImage = copySize->height / blockInfo.blockHeight; + ASSERT(copySize->height % blockInfo.height == 0); + defaultedRowsPerImage = copySize->height / blockInfo.height; } // In the case of one row copy bytesPerRow might not contain enough bytes uint32_t bytesPerRow = destination->layout.bytesPerRow; if (copySize->height <= 1 && copySize->depth <= 1) { bytesPerRow = - Align(copySize->width * blockInfo.blockByteSize, kTextureBytesPerRowAlignment); + Align(copySize->width * blockInfo.byteSize, kTextureBytesPerRowAlignment); } // Skip noop copies. diff --git a/src/dawn_native/CommandValidation.cpp b/src/dawn_native/CommandValidation.cpp index 8b99e0f4b5..348d445f79 100644 --- a/src/dawn_native/CommandValidation.cpp +++ b/src/dawn_native/CommandValidation.cpp @@ -374,8 +374,8 @@ namespace dawn_native { const Extent3D& copySize, uint32_t bytesPerRow, uint32_t rowsPerImage) { - ASSERT(copySize.height % blockInfo.blockHeight == 0); - uint32_t heightInBlocks = copySize.height / blockInfo.blockHeight; + ASSERT(copySize.height % blockInfo.height == 0); + uint32_t heightInBlocks = copySize.height / blockInfo.height; // Default value for rowsPerImage if (rowsPerImage == 0) { @@ -384,7 +384,7 @@ namespace dawn_native { ASSERT(rowsPerImage >= heightInBlocks); if (copySize.height > 1 || copySize.depth > 1) { - ASSERT(bytesPerRow >= copySize.width / blockInfo.blockWidth * blockInfo.blockByteSize); + ASSERT(bytesPerRow >= copySize.width / blockInfo.width * blockInfo.byteSize); } if (copySize.width == 0 || copySize.height == 0 || copySize.depth == 0) { @@ -400,7 +400,7 @@ namespace dawn_native { // bytesPerImage. Otherwise the result is a multiplication of two uint32_t numbers. uint64_t bytesInLastSlice = uint64_t(bytesPerRow) * (heightInBlocks - 1) + - (uint64_t(copySize.width) / blockInfo.blockWidth * blockInfo.blockByteSize); + (uint64_t(copySize.width) / blockInfo.width * blockInfo.byteSize); // This error cannot be thrown for copySize.depth = 1. // For copySize.depth > 1 we know that: @@ -430,14 +430,13 @@ namespace dawn_native { const TexelBlockInfo& blockInfo, const Extent3D& copyExtent) { // Validation for the texel block alignments: - if (layout.offset % blockInfo.blockByteSize != 0) { + if (layout.offset % blockInfo.byteSize != 0) { return DAWN_VALIDATION_ERROR("Offset must be a multiple of the texel or block size"); } // Validation for other members in layout: if ((copyExtent.height > 1 || copyExtent.depth > 1) && - layout.bytesPerRow < - copyExtent.width / blockInfo.blockWidth * blockInfo.blockByteSize) { + layout.bytesPerRow < copyExtent.width / blockInfo.width * blockInfo.byteSize) { return DAWN_VALIDATION_ERROR( "bytesPerRow must not be less than the number of bytes per row"); } @@ -445,8 +444,8 @@ namespace dawn_native { // TODO(tommek@google.com): to match the spec there should be another condition here // on rowsPerImage >= copyExtent.height if copyExtent.depth > 1. - ASSERT(copyExtent.height % blockInfo.blockHeight == 0); - uint32_t heightInBlocks = copyExtent.height / blockInfo.blockHeight; + ASSERT(copyExtent.height % blockInfo.height == 0); + uint32_t heightInBlocks = copyExtent.height / blockInfo.height; // Validation for the copy being in-bounds: if (layout.rowsPerImage != 0 && layout.rowsPerImage < heightInBlocks) { @@ -551,24 +550,26 @@ namespace dawn_native { } // Validation for the texel block alignments: - const TexelBlockInfo& blockInfo = - textureCopy.texture->GetFormat().GetTexelBlockInfo(textureCopy.aspect); - if (textureCopy.origin.x % blockInfo.blockWidth != 0) { - return DAWN_VALIDATION_ERROR( - "Offset.x must be a multiple of compressed texture format block width"); - } - if (textureCopy.origin.y % blockInfo.blockHeight != 0) { - return DAWN_VALIDATION_ERROR( - "Offset.y must be a multiple of compressed texture format block height"); - } - if (copySize.width % blockInfo.blockWidth != 0) { - return DAWN_VALIDATION_ERROR( - "copySize.width must be a multiple of compressed texture format block width"); - } + const Format& format = textureCopy.texture->GetFormat(); + if (format.isCompressed) { + const TexelBlockInfo& blockInfo = format.GetAspectInfo(textureCopy.aspect).block; + if (textureCopy.origin.x % blockInfo.width != 0) { + return DAWN_VALIDATION_ERROR( + "Offset.x must be a multiple of compressed texture format block width"); + } + if (textureCopy.origin.y % blockInfo.height != 0) { + return DAWN_VALIDATION_ERROR( + "Offset.y must be a multiple of compressed texture format block height"); + } + if (copySize.width % blockInfo.width != 0) { + return DAWN_VALIDATION_ERROR( + "copySize.width must be a multiple of compressed texture format block width"); + } - if (copySize.height % blockInfo.blockHeight != 0) { - return DAWN_VALIDATION_ERROR( - "copySize.height must be a multiple of compressed texture format block height"); + if (copySize.height % blockInfo.height != 0) { + return DAWN_VALIDATION_ERROR( + "copySize.height must be a multiple of compressed texture format block height"); + } } return {}; diff --git a/src/dawn_native/Format.cpp b/src/dawn_native/Format.cpp index cda4394b63..a3fd34a4fe 100644 --- a/src/dawn_native/Format.cpp +++ b/src/dawn_native/Format.cpp @@ -22,6 +22,12 @@ namespace dawn_native { + namespace { + + static const AspectInfo kStencil8AspectInfo = {{1, 1, 1}}; + + } + // Format // static @@ -78,62 +84,20 @@ namespace dawn_native { return componentType == type; } - TexelBlockInfo Format::GetTexelBlockInfo(wgpu::TextureAspect aspect) const { - switch (aspect) { - case wgpu::TextureAspect::All: - return blockInfo; - - case wgpu::TextureAspect::DepthOnly: - ASSERT(HasDepth()); - switch (format) { - case wgpu::TextureFormat::Depth32Float: - return blockInfo; - default: - UNREACHABLE(); - break; - } - break; - - case wgpu::TextureAspect::StencilOnly: - ASSERT(HasStencil()); - switch (format) { - case wgpu::TextureFormat::Depth24PlusStencil8: - return {1, 1, 1}; - default: - UNREACHABLE(); - break; - } - break; - } + const AspectInfo& Format::GetAspectInfo(wgpu::TextureAspect aspect) const { + return GetAspectInfo(ConvertAspect(*this, aspect)); } - TexelBlockInfo Format::GetTexelBlockInfo(Aspect aspect) const { + const AspectInfo& Format::GetAspectInfo(Aspect aspect) const { ASSERT(HasOneBit(aspect)); ASSERT(aspects & aspect); - switch (aspect) { - case Aspect::Color: - ASSERT(aspects == aspect); - return blockInfo; - case Aspect::Depth: - switch (format) { - case wgpu::TextureFormat::Depth32Float: - return blockInfo; - default: - UNREACHABLE(); - break; - } - case Aspect::Stencil: - switch (format) { - case wgpu::TextureFormat::Depth24PlusStencil8: - return {1, 1, 1}; - default: - UNREACHABLE(); - break; - } - break; - case Aspect::None: - UNREACHABLE(); + // The stencil aspect is the only aspect that's not the first aspect. Since it is alwaus the + // same aspect information, special case it to return a constant AspectInfo. + if (aspect == Aspect::Stencil) { + return kStencil8AspectInfo; + } else { + return firstAspect; } } @@ -182,9 +146,9 @@ namespace dawn_native { internalFormat.supportsStorageUsage = supportsStorageUsage; internalFormat.aspects = Aspect::Color; internalFormat.type = type; - internalFormat.blockInfo.blockByteSize = byteSize; - internalFormat.blockInfo.blockWidth = 1; - internalFormat.blockInfo.blockHeight = 1; + internalFormat.firstAspect.block.byteSize = byteSize; + internalFormat.firstAspect.block.width = 1; + internalFormat.firstAspect.block.height = 1; AddFormat(internalFormat); }; @@ -198,9 +162,9 @@ namespace dawn_native { internalFormat.supportsStorageUsage = false; internalFormat.aspects = aspects; internalFormat.type = Type::Other; - internalFormat.blockInfo.blockByteSize = byteSize; - internalFormat.blockInfo.blockWidth = 1; - internalFormat.blockInfo.blockHeight = 1; + internalFormat.firstAspect.block.byteSize = byteSize; + internalFormat.firstAspect.block.width = 1; + internalFormat.firstAspect.block.height = 1; AddFormat(internalFormat); }; @@ -214,9 +178,9 @@ namespace dawn_native { internalFormat.supportsStorageUsage = false; internalFormat.aspects = Aspect::Depth; internalFormat.type = type; - internalFormat.blockInfo.blockByteSize = byteSize; - internalFormat.blockInfo.blockWidth = 1; - internalFormat.blockInfo.blockHeight = 1; + internalFormat.firstAspect.block.byteSize = byteSize; + internalFormat.firstAspect.block.width = 1; + internalFormat.firstAspect.block.height = 1; AddFormat(internalFormat); }; @@ -230,9 +194,9 @@ namespace dawn_native { internalFormat.supportsStorageUsage = false; internalFormat.aspects = Aspect::Color; internalFormat.type = Type::Float; - internalFormat.blockInfo.blockByteSize = byteSize; - internalFormat.blockInfo.blockWidth = width; - internalFormat.blockInfo.blockHeight = height; + internalFormat.firstAspect.block.byteSize = byteSize; + internalFormat.firstAspect.block.width = width; + internalFormat.firstAspect.block.height = height; AddFormat(internalFormat); }; diff --git a/src/dawn_native/Format.h b/src/dawn_native/Format.h index 63c450e3b7..3052f679be 100644 --- a/src/dawn_native/Format.h +++ b/src/dawn_native/Format.h @@ -18,9 +18,8 @@ #include "dawn_native/dawn_platform.h" #include "common/ityp_bitset.h" -#include "dawn_native/Error.h" - #include "dawn_native/EnumClassBitmasks.h" +#include "dawn_native/Error.h" #include @@ -30,9 +29,13 @@ namespace dawn_native { class DeviceBase; struct TexelBlockInfo { - uint32_t blockByteSize; - uint32_t blockWidth; - uint32_t blockHeight; + uint32_t byteSize; + uint32_t width; + uint32_t height; + }; + + struct AspectInfo { + TexelBlockInfo block; }; // The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the @@ -69,15 +72,17 @@ namespace dawn_native { bool HasDepthOrStencil() const; bool HasComponentType(Type componentType) const; - TexelBlockInfo GetTexelBlockInfo(wgpu::TextureAspect aspect) const; - TexelBlockInfo GetTexelBlockInfo(Aspect aspect) const; + const AspectInfo& GetAspectInfo(wgpu::TextureAspect aspect) const; + const AspectInfo& GetAspectInfo(Aspect aspect) const; // The index of the format in the list of all known formats: a unique number for each format // in [0, kKnownFormatCount) size_t GetIndex() const; private: - TexelBlockInfo blockInfo; + // The most common aspect: the color aspect for color texture, the depth aspect for + // depth[-stencil] textures. + AspectInfo firstAspect; friend FormatTable BuildFormatTable(const DeviceBase* device); }; diff --git a/src/dawn_native/Queue.cpp b/src/dawn_native/Queue.cpp index 13bf177402..ed6cbab4cd 100644 --- a/src/dawn_native/Queue.cpp +++ b/src/dawn_native/Queue.cpp @@ -88,11 +88,11 @@ namespace dawn_native { uint64_t optimalOffsetAlignment = device->GetOptimalBufferToTextureCopyOffsetAlignment(); ASSERT(IsPowerOfTwo(optimalOffsetAlignment)); - ASSERT(IsPowerOfTwo(blockInfo.blockByteSize)); + ASSERT(IsPowerOfTwo(blockInfo.byteSize)); // We need the offset to be aligned to both optimalOffsetAlignment and blockByteSize, // since both of them are powers of two, we only need to align to the max value. uint64_t offsetAlignment = - std::max(optimalOffsetAlignment, uint64_t(blockInfo.blockByteSize)); + std::max(optimalOffsetAlignment, uint64_t(blockInfo.byteSize)); UploadHandle uploadHandle; DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate( @@ -106,7 +106,7 @@ namespace dawn_native { uint32_t dataRowsPerImage = dataLayout.rowsPerImage; if (dataRowsPerImage == 0) { - dataRowsPerImage = writeSizePixel.height / blockInfo.blockHeight; + dataRowsPerImage = writeSizePixel.height / blockInfo.height; } ASSERT(dataRowsPerImage >= alignedRowsPerImage); @@ -266,16 +266,15 @@ namespace dawn_native { const TextureDataLayout& dataLayout, const Extent3D& writeSizePixel) { const TexelBlockInfo& blockInfo = - destination.texture->GetFormat().GetTexelBlockInfo(destination.aspect); + destination.texture->GetFormat().GetAspectInfo(destination.aspect).block; // We are only copying the part of the data that will appear in the texture. // Note that validating texture copy range ensures that writeSizePixel->width and // writeSizePixel->height are multiples of blockWidth and blockHeight respectively. - ASSERT(writeSizePixel.width % blockInfo.blockWidth == 0); - ASSERT(writeSizePixel.height % blockInfo.blockHeight == 0); - uint32_t alignedBytesPerRow = - writeSizePixel.width / blockInfo.blockWidth * blockInfo.blockByteSize; - uint32_t alignedRowsPerImage = writeSizePixel.height / blockInfo.blockHeight; + ASSERT(writeSizePixel.width % blockInfo.width == 0); + ASSERT(writeSizePixel.height % blockInfo.height == 0); + uint32_t alignedBytesPerRow = writeSizePixel.width / blockInfo.width * blockInfo.byteSize; + uint32_t alignedRowsPerImage = writeSizePixel.height / blockInfo.height; uint32_t optimalBytesPerRowAlignment = GetDevice()->GetOptimalBytesPerRowAlignment(); uint32_t optimallyAlignedBytesPerRow = @@ -418,7 +417,8 @@ namespace dawn_native { DAWN_TRY(ValidateTextureCopyRange(*destination, *writeSize)); DAWN_TRY(ValidateLinearTextureData( *dataLayout, dataSize, - destination->texture->GetFormat().GetTexelBlockInfo(destination->aspect), *writeSize)); + destination->texture->GetFormat().GetAspectInfo(destination->aspect).block, + *writeSize)); DAWN_TRY(destination->texture->ValidateCanUseInSubmitNow()); diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp index 98e9abdc9d..263a7ee7ea 100644 --- a/src/dawn_native/Texture.cpp +++ b/src/dawn_native/Texture.cpp @@ -165,11 +165,14 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("Texture has too many mip levels"); } - const TexelBlockInfo& blockInfo = format->GetTexelBlockInfo(wgpu::TextureAspect::All); - if (format->isCompressed && (descriptor->size.width % blockInfo.blockWidth != 0 || - descriptor->size.height % blockInfo.blockHeight != 0)) { - return DAWN_VALIDATION_ERROR( - "The size of the texture is incompatible with the texture format"); + if (format->isCompressed) { + const TexelBlockInfo& blockInfo = + format->GetAspectInfo(wgpu::TextureAspect::All).block; + if (descriptor->size.width % blockInfo.width != 0 || + descriptor->size.height % blockInfo.height != 0) { + return DAWN_VALIDATION_ERROR( + "The size of the texture is incompatible with the texture format"); + } } if (descriptor->dimension == wgpu::TextureDimension::e2D && @@ -558,11 +561,10 @@ namespace dawn_native { // 4 at non-zero mipmap levels. if (mFormat.isCompressed) { // TODO(jiawei.shao@intel.com): check if there are any overflows. - const TexelBlockInfo& blockInfo = mFormat.GetTexelBlockInfo(wgpu::TextureAspect::All); - uint32_t blockWidth = blockInfo.blockWidth; - uint32_t blockHeight = blockInfo.blockHeight; - extent.width = (extent.width + blockWidth - 1) / blockWidth * blockWidth; - extent.height = (extent.height + blockHeight - 1) / blockHeight * blockHeight; + const TexelBlockInfo& blockInfo = mFormat.GetAspectInfo(wgpu::TextureAspect::All).block; + extent.width = (extent.width + blockInfo.width - 1) / blockInfo.width * blockInfo.width; + extent.height = + (extent.height + blockInfo.height - 1) / blockInfo.height * blockInfo.height; } return extent; diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index d0b077713b..5b36200e85 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -770,7 +770,7 @@ namespace dawn_native { namespace d3d12 { buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst); const TexelBlockInfo& blockInfo = - texture->GetFormat().GetTexelBlockInfo(copy->source.aspect); + texture->GetFormat().GetAspectInfo(copy->source.aspect).block; // See comments around ComputeTextureCopySplits() for more details. const TextureCopySplits copySplits = ComputeTextureCopySplits( diff --git a/src/dawn_native/d3d12/TextureCopySplitter.cpp b/src/dawn_native/d3d12/TextureCopySplitter.cpp index 2a445a8535..d326489a56 100644 --- a/src/dawn_native/d3d12/TextureCopySplitter.cpp +++ b/src/dawn_native/d3d12/TextureCopySplitter.cpp @@ -32,8 +32,8 @@ namespace dawn_native { namespace d3d12 { uint32_t byteOffsetY = offset % slicePitch; uint32_t byteOffsetZ = offset - byteOffsetY; - return {byteOffsetX / blockInfo.blockByteSize * blockInfo.blockWidth, - byteOffsetY / bytesPerRow * blockInfo.blockHeight, byteOffsetZ / slicePitch}; + return {byteOffsetX / blockInfo.byteSize * blockInfo.width, + byteOffsetY / bytesPerRow * blockInfo.height, byteOffsetZ / slicePitch}; } } // namespace @@ -45,7 +45,7 @@ namespace dawn_native { namespace d3d12 { uint32_t rowsPerImage) { Texture2DCopySplit copy; - ASSERT(bytesPerRow % blockInfo.blockByteSize == 0); + ASSERT(bytesPerRow % blockInfo.byteSize == 0); uint64_t alignedOffset = offset & ~static_cast(D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT - 1); @@ -75,11 +75,9 @@ namespace dawn_native { namespace d3d12 { Origin3D texelOffset = ComputeTexelOffsets( blockInfo, static_cast(offset - alignedOffset), bytesPerRow, slicePitch); - uint32_t copyBytesPerRowPitch = - copySize.width / blockInfo.blockWidth * blockInfo.blockByteSize; - uint32_t byteOffsetInRowPitch = - texelOffset.x / blockInfo.blockWidth * blockInfo.blockByteSize; - uint32_t rowsPerImageInTexels = rowsPerImage * blockInfo.blockHeight; + uint32_t copyBytesPerRowPitch = copySize.width / blockInfo.width * blockInfo.byteSize; + uint32_t byteOffsetInRowPitch = texelOffset.x / blockInfo.width * blockInfo.byteSize; + uint32_t rowsPerImageInTexels = rowsPerImage * blockInfo.height; if (copyBytesPerRowPitch + byteOffsetInRowPitch <= bytesPerRow) { // The region's rows fit inside the bytes per row. In this case, extend the width of the // PlacedFootprint and copy the buffer with an offset location @@ -157,7 +155,7 @@ namespace dawn_native { namespace d3d12 { copy.copies[0].textureOffset = origin; ASSERT(bytesPerRow > byteOffsetInRowPitch); - uint32_t texelsPerRow = bytesPerRow / blockInfo.blockByteSize * blockInfo.blockWidth; + uint32_t texelsPerRow = bytesPerRow / blockInfo.byteSize * blockInfo.width; copy.copies[0].copySize.width = texelsPerRow - texelOffset.x; copy.copies[0].copySize.height = copySize.height; copy.copies[0].copySize.depth = copySize.depth; @@ -177,11 +175,10 @@ namespace dawn_native { namespace d3d12 { copy.copies[1].copySize.depth = copySize.depth; copy.copies[1].bufferOffset.x = 0; - copy.copies[1].bufferOffset.y = texelOffset.y + blockInfo.blockHeight; + copy.copies[1].bufferOffset.y = texelOffset.y + blockInfo.height; copy.copies[1].bufferOffset.z = texelOffset.z; copy.copies[1].bufferSize.width = copy.copies[1].copySize.width; - copy.copies[1].bufferSize.height = - rowsPerImageInTexels + texelOffset.y + blockInfo.blockHeight; + copy.copies[1].bufferSize.height = rowsPerImageInTexels + texelOffset.y + blockInfo.height; copy.copies[1].bufferSize.depth = copySize.depth + texelOffset.z; return copy; diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp index e5cc5054fa..e1eac4e26d 100644 --- a/src/dawn_native/d3d12/TextureD3D12.cpp +++ b/src/dawn_native/d3d12/TextureD3D12.cpp @@ -947,12 +947,11 @@ namespace dawn_native { namespace d3d12 { TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_COPY_DEST, range); for (Aspect aspect : IterateEnumMask(range.aspects)) { - const TexelBlockInfo& blockInfo = GetFormat().GetTexelBlockInfo(aspect); + const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(aspect).block; - uint32_t bytesPerRow = - Align((GetWidth() / blockInfo.blockWidth) * blockInfo.blockByteSize, - kTextureBytesPerRowAlignment); - uint64_t bufferSize64 = bytesPerRow * (GetHeight() / blockInfo.blockHeight); + uint32_t bytesPerRow = Align((GetWidth() / blockInfo.width) * blockInfo.byteSize, + kTextureBytesPerRowAlignment); + uint64_t bufferSize64 = bytesPerRow * (GetHeight() / blockInfo.height); if (bufferSize64 > std::numeric_limits::max()) { return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer."); } @@ -962,7 +961,7 @@ namespace dawn_native { namespace d3d12 { UploadHandle uploadHandle; DAWN_TRY_ASSIGN(uploadHandle, uploader->Allocate(bufferSize, device->GetPendingCommandSerial(), - blockInfo.blockByteSize)); + blockInfo.byteSize)); memset(uploadHandle.mappedBuffer, clearColor, bufferSize); for (uint32_t level = range.baseMipLevel; @@ -970,7 +969,7 @@ namespace dawn_native { namespace d3d12 { // compute d3d12 texture copy locations for texture and buffer Extent3D copySize = GetMipLevelVirtualSize(level); - uint32_t rowsPerImage = GetHeight() / blockInfo.blockHeight; + uint32_t rowsPerImage = GetHeight() / blockInfo.height; Texture2DCopySplit copySplit = ComputeTextureCopySplit( {0, 0, 0}, copySize, blockInfo, uploadHandle.startOffset, bytesPerRow, rowsPerImage); diff --git a/src/dawn_native/d3d12/UtilsD3D12.cpp b/src/dawn_native/d3d12/UtilsD3D12.cpp index 436076bbab..fa950b58a6 100644 --- a/src/dawn_native/d3d12/UtilsD3D12.cpp +++ b/src/dawn_native/d3d12/UtilsD3D12.cpp @@ -185,7 +185,7 @@ namespace dawn_native { namespace d3d12 { Aspect aspect) { ASSERT(HasOneBit(aspect)); // See comments in ComputeTextureCopySplits() for more details. - const TexelBlockInfo& blockInfo = texture->GetFormat().GetTexelBlockInfo(aspect); + const TexelBlockInfo& blockInfo = texture->GetFormat().GetAspectInfo(aspect).block; const TextureCopySplits copySplits = ComputeTextureCopySplits( textureCopy.origin, copySize, blockInfo, offsetBytes, bytesPerRow, rowsPerImage); diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm index 9c28c50aee..d449ab50c5 100644 --- a/src/dawn_native/metal/DeviceMTL.mm +++ b/src/dawn_native/metal/DeviceMTL.mm @@ -297,12 +297,10 @@ namespace dawn_native { namespace metal { // This function assumes data is perfectly aligned. Otherwise, it might be necessary // to split copying to several stages: see ComputeTextureBufferCopySplit. - const TexelBlockInfo& blockInfo = texture->GetFormat().GetTexelBlockInfo(dst->aspect); - uint32_t blockSize = blockInfo.blockByteSize; - uint32_t blockWidth = blockInfo.blockWidth; - uint32_t blockHeight = blockInfo.blockHeight; - ASSERT(dataLayout.rowsPerImage == copySizePixels.height / blockHeight); - ASSERT(dataLayout.bytesPerRow == copySizePixels.width / blockWidth * blockSize); + const TexelBlockInfo& blockInfo = texture->GetFormat().GetAspectInfo(dst->aspect).block; + ASSERT(dataLayout.rowsPerImage == copySizePixels.height / blockInfo.height); + ASSERT(dataLayout.bytesPerRow == + copySizePixels.width / blockInfo.width * blockInfo.byteSize); EnsureDestinationTextureInitialized(texture, *dst, copySizePixels); diff --git a/src/dawn_native/metal/TextureMTL.mm b/src/dawn_native/metal/TextureMTL.mm index d47dda0623..2e2f34f16b 100644 --- a/src/dawn_native/metal/TextureMTL.mm +++ b/src/dawn_native/metal/TextureMTL.mm @@ -491,16 +491,16 @@ namespace dawn_native { namespace metal { // Compute the buffer size big enough to fill the largest mip. Extent3D largestMipSize = GetMipLevelVirtualSize(range.baseMipLevel); const TexelBlockInfo& blockInfo = - GetFormat().GetTexelBlockInfo(wgpu::TextureAspect::All); + GetFormat().GetAspectInfo(wgpu::TextureAspect::All).block; // Metal validation layers: sourceBytesPerRow must be at least 64. - uint32_t largestMipBytesPerRow = std::max( - (largestMipSize.width / blockInfo.blockWidth) * blockInfo.blockByteSize, 64u); + uint32_t largestMipBytesPerRow = + std::max((largestMipSize.width / blockInfo.width) * blockInfo.byteSize, 64u); // Metal validation layers: sourceBytesPerImage must be at least 512. uint64_t largestMipBytesPerImage = std::max(static_cast(largestMipBytesPerRow) * - (largestMipSize.height / blockInfo.blockHeight), + (largestMipSize.height / blockInfo.height), 512llu); // TODO(enga): Multiply by largestMipSize.depth and do a larger 3D copy to clear a whole @@ -515,7 +515,7 @@ namespace dawn_native { namespace metal { UploadHandle uploadHandle; DAWN_TRY_ASSIGN(uploadHandle, uploader->Allocate(bufferSize, device->GetPendingCommandSerial(), - blockInfo.blockByteSize)); + blockInfo.byteSize)); memset(uploadHandle.mappedBuffer, clearColor, bufferSize); id encoder = commandContext->EnsureBlit(); diff --git a/src/dawn_native/metal/UtilsMetal.mm b/src/dawn_native/metal/UtilsMetal.mm index 93082c4c19..689204e7ea 100644 --- a/src/dawn_native/metal/UtilsMetal.mm +++ b/src/dawn_native/metal/UtilsMetal.mm @@ -54,7 +54,7 @@ namespace dawn_native { namespace metal { Aspect aspect) { TextureBufferCopySplit copy; const Format textureFormat = texture->GetFormat(); - const TexelBlockInfo& blockInfo = textureFormat.GetTexelBlockInfo(aspect); + const TexelBlockInfo& blockInfo = textureFormat.GetAspectInfo(aspect).block; // When copying textures from/to an unpacked buffer, the Metal validation layer doesn't // compute the correct range when checking if the buffer is big enough to contain the @@ -115,7 +115,7 @@ namespace dawn_native { namespace metal { } // Doing all the copy in last image except the last row. - uint32_t copyBlockRowCount = copyExtent.height / blockInfo.blockHeight; + uint32_t copyBlockRowCount = copyExtent.height / blockInfo.height; if (copyBlockRowCount > 1) { copy.copies[copy.count].bufferOffset = currentOffset; copy.copies[copy.count].bytesPerRow = bytesPerRow; @@ -123,10 +123,10 @@ namespace dawn_native { namespace metal { copy.copies[copy.count].textureOrigin = {origin.x, origin.y, origin.z + copyExtent.depth - 1}; - ASSERT(copyExtent.height - blockInfo.blockHeight < + ASSERT(copyExtent.height - blockInfo.height < texture->GetMipLevelVirtualSize(mipLevel).height); copy.copies[copy.count].copyExtent = {clampedCopyExtent.width, - copyExtent.height - blockInfo.blockHeight, 1}; + copyExtent.height - blockInfo.height, 1}; ++copy.count; @@ -136,18 +136,17 @@ namespace dawn_native { namespace metal { // Doing the last row copy with the exact number of bytes in last row. // Workaround this issue in a way just like the copy to a 1D texture. - uint32_t lastRowDataSize = - (copyExtent.width / blockInfo.blockWidth) * blockInfo.blockByteSize; + uint32_t lastRowDataSize = (copyExtent.width / blockInfo.width) * blockInfo.byteSize; uint32_t lastRowCopyExtentHeight = - blockInfo.blockHeight + clampedCopyExtent.height - copyExtent.height; - ASSERT(lastRowCopyExtentHeight <= blockInfo.blockHeight); + blockInfo.height + clampedCopyExtent.height - copyExtent.height; + ASSERT(lastRowCopyExtentHeight <= blockInfo.height); copy.copies[copy.count].bufferOffset = currentOffset; copy.copies[copy.count].bytesPerRow = lastRowDataSize; copy.copies[copy.count].bytesPerImage = lastRowDataSize; - copy.copies[copy.count].textureOrigin = { - origin.x, origin.y + copyExtent.height - blockInfo.blockHeight, - origin.z + copyExtent.depth - 1}; + copy.copies[copy.count].textureOrigin = {origin.x, + origin.y + copyExtent.height - blockInfo.height, + origin.z + copyExtent.depth - 1}; copy.copies[copy.count].copyExtent = {clampedCopyExtent.width, lastRowCopyExtentHeight, 1}; ++copy.count; diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp index 0db0083d5f..141ae67ea2 100644 --- a/src/dawn_native/opengl/CommandBufferGL.cpp +++ b/src/dawn_native/opengl/CommandBufferGL.cpp @@ -531,22 +531,21 @@ namespace dawn_native { namespace opengl { gl.BindTexture(target, texture->GetHandle()); const Format& formatInfo = texture->GetFormat(); - const TexelBlockInfo& blockInfo = formatInfo.GetTexelBlockInfo(dst.aspect); - gl.PixelStorei(GL_UNPACK_ROW_LENGTH, src.bytesPerRow / blockInfo.blockByteSize * - blockInfo.blockWidth); - gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, - src.rowsPerImage * blockInfo.blockHeight); + const TexelBlockInfo& blockInfo = formatInfo.GetAspectInfo(dst.aspect).block; + gl.PixelStorei(GL_UNPACK_ROW_LENGTH, + src.bytesPerRow / blockInfo.byteSize * blockInfo.width); + gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, src.rowsPerImage * blockInfo.height); if (formatInfo.isCompressed) { - gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE, blockInfo.blockByteSize); - gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, blockInfo.blockWidth); - gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT, blockInfo.blockHeight); + gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE, blockInfo.byteSize); + gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, blockInfo.width); + gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT, blockInfo.height); gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_DEPTH, 1); ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D); - uint64_t copyDataSize = (copySize.width / blockInfo.blockWidth) * - (copySize.height / blockInfo.blockHeight) * - blockInfo.blockByteSize * copySize.depth; + uint64_t copyDataSize = (copySize.width / blockInfo.width) * + (copySize.height / blockInfo.height) * + blockInfo.byteSize * copySize.depth; Extent3D copyExtent = ComputeTextureCopyExtent(dst, copySize); if (texture->GetArrayLayers() > 1) { @@ -624,11 +623,11 @@ namespace dawn_native { namespace opengl { gl.GenFramebuffers(1, &readFBO); gl.BindFramebuffer(GL_READ_FRAMEBUFFER, readFBO); - const TexelBlockInfo& blockInfo = formatInfo.GetTexelBlockInfo(src.aspect); + const TexelBlockInfo& blockInfo = formatInfo.GetAspectInfo(src.aspect).block; gl.BindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle()); - gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, dst.rowsPerImage * blockInfo.blockHeight); - gl.PixelStorei(GL_PACK_ROW_LENGTH, dst.bytesPerRow / blockInfo.blockByteSize); + gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, dst.rowsPerImage * blockInfo.height); + gl.PixelStorei(GL_PACK_ROW_LENGTH, dst.bytesPerRow / blockInfo.byteSize); GLenum glAttachment; GLenum glFormat; diff --git a/src/dawn_native/opengl/TextureGL.cpp b/src/dawn_native/opengl/TextureGL.cpp index 97d877ce5e..1185dc94e7 100644 --- a/src/dawn_native/opengl/TextureGL.cpp +++ b/src/dawn_native/opengl/TextureGL.cpp @@ -294,8 +294,8 @@ namespace dawn_native { namespace opengl { ASSERT(range.aspects == Aspect::Color); static constexpr uint32_t MAX_TEXEL_SIZE = 16; - const TexelBlockInfo& blockInfo = GetFormat().GetTexelBlockInfo(Aspect::Color); - ASSERT(blockInfo.blockByteSize <= MAX_TEXEL_SIZE); + const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(Aspect::Color).block; + ASSERT(blockInfo.byteSize <= MAX_TEXEL_SIZE); std::array clearColorData; clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 255; @@ -324,20 +324,19 @@ namespace dawn_native { namespace opengl { ASSERT(range.aspects == Aspect::Color); // create temp buffer with clear color to copy to the texture image - const TexelBlockInfo& blockInfo = GetFormat().GetTexelBlockInfo(Aspect::Color); - ASSERT(kTextureBytesPerRowAlignment % blockInfo.blockByteSize == 0); - uint32_t bytesPerRow = - Align((GetWidth() / blockInfo.blockWidth) * blockInfo.blockByteSize, - kTextureBytesPerRowAlignment); + const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(Aspect::Color).block; + ASSERT(kTextureBytesPerRowAlignment % blockInfo.byteSize == 0); + uint32_t bytesPerRow = Align((GetWidth() / blockInfo.width) * blockInfo.byteSize, + kTextureBytesPerRowAlignment); // Make sure that we are not rounding - ASSERT(bytesPerRow % blockInfo.blockByteSize == 0); - ASSERT(GetHeight() % blockInfo.blockHeight == 0); + ASSERT(bytesPerRow % blockInfo.byteSize == 0); + ASSERT(GetHeight() % blockInfo.height == 0); dawn_native::BufferDescriptor descriptor = {}; descriptor.mappedAtCreation = true; descriptor.usage = wgpu::BufferUsage::CopySrc; - descriptor.size = bytesPerRow * (GetHeight() / blockInfo.blockHeight); + descriptor.size = bytesPerRow * (GetHeight() / blockInfo.height); if (descriptor.size > std::numeric_limits::max()) { return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer."); } @@ -353,7 +352,7 @@ namespace dawn_native { namespace opengl { // Bind buffer and texture, and make the buffer to texture copy gl.PixelStorei(GL_UNPACK_ROW_LENGTH, - (bytesPerRow / blockInfo.blockByteSize) * blockInfo.blockWidth); + (bytesPerRow / blockInfo.byteSize) * blockInfo.width); gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount; ++level) { diff --git a/src/dawn_native/vulkan/CommandBufferVk.cpp b/src/dawn_native/vulkan/CommandBufferVk.cpp index 42e5278060..73a2f970f5 100644 --- a/src/dawn_native/vulkan/CommandBufferVk.cpp +++ b/src/dawn_native/vulkan/CommandBufferVk.cpp @@ -436,15 +436,15 @@ namespace dawn_native { namespace vulkan { ASSERT(srcCopy.texture->GetFormat().format == dstCopy.texture->GetFormat().format); ASSERT(srcCopy.aspect == dstCopy.aspect); dawn_native::Format format = srcCopy.texture->GetFormat(); - const TexelBlockInfo& blockInfo = format.GetTexelBlockInfo(srcCopy.aspect); - ASSERT(copySize.width % blockInfo.blockWidth == 0); - uint32_t widthInBlocks = copySize.width / blockInfo.blockWidth; - ASSERT(copySize.height % blockInfo.blockHeight == 0); - uint32_t heightInBlocks = copySize.height / blockInfo.blockHeight; + const TexelBlockInfo& blockInfo = format.GetAspectInfo(srcCopy.aspect).block; + ASSERT(copySize.width % blockInfo.width == 0); + uint32_t widthInBlocks = copySize.width / blockInfo.width; + ASSERT(copySize.height % blockInfo.height == 0); + uint32_t heightInBlocks = copySize.height / blockInfo.height; // Create the temporary buffer. Note that We don't need to respect WebGPU's 256 alignment // because it isn't a hard constraint in Vulkan. - uint64_t tempBufferSize = widthInBlocks * heightInBlocks * blockInfo.blockByteSize; + uint64_t tempBufferSize = widthInBlocks * heightInBlocks * blockInfo.byteSize; BufferDescriptor tempBufferDescriptor; tempBufferDescriptor.size = tempBufferSize; tempBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst; @@ -456,8 +456,7 @@ namespace dawn_native { namespace vulkan { tempBufferCopy.buffer = tempBuffer.Get(); tempBufferCopy.rowsPerImage = heightInBlocks; tempBufferCopy.offset = 0; - tempBufferCopy.bytesPerRow = - copySize.width / blockInfo.blockWidth * blockInfo.blockByteSize; + tempBufferCopy.bytesPerRow = copySize.width / blockInfo.width * blockInfo.byteSize; VkCommandBuffer commands = recordingContext->commandBuffer; VkImage srcImage = ToBackend(srcCopy.texture)->GetHandle(); diff --git a/src/dawn_native/vulkan/UtilsVulkan.cpp b/src/dawn_native/vulkan/UtilsVulkan.cpp index 967d2a74ec..a78bfef100 100644 --- a/src/dawn_native/vulkan/UtilsVulkan.cpp +++ b/src/dawn_native/vulkan/UtilsVulkan.cpp @@ -108,11 +108,10 @@ namespace dawn_native { namespace vulkan { region.bufferOffset = dataLayout.offset; // In Vulkan the row length is in texels while it is in bytes for Dawn const TexelBlockInfo& blockInfo = - texture->GetFormat().GetTexelBlockInfo(textureCopy.aspect); - ASSERT(dataLayout.bytesPerRow % blockInfo.blockByteSize == 0); - region.bufferRowLength = - dataLayout.bytesPerRow / blockInfo.blockByteSize * blockInfo.blockWidth; - region.bufferImageHeight = dataLayout.rowsPerImage * blockInfo.blockHeight; + texture->GetFormat().GetAspectInfo(textureCopy.aspect).block; + ASSERT(dataLayout.bytesPerRow % blockInfo.byteSize == 0); + region.bufferRowLength = dataLayout.bytesPerRow / blockInfo.byteSize * blockInfo.width; + region.bufferImageHeight = dataLayout.rowsPerImage * blockInfo.height; region.imageSubresource.aspectMask = VulkanAspectMask(textureCopy.aspect); region.imageSubresource.mipLevel = textureCopy.mipLevel; diff --git a/src/tests/unittests/d3d12/CopySplitTests.cpp b/src/tests/unittests/d3d12/CopySplitTests.cpp index 71b165d572..4b444b30e1 100644 --- a/src/tests/unittests/d3d12/CopySplitTests.cpp +++ b/src/tests/unittests/d3d12/CopySplitTests.cpp @@ -291,9 +291,9 @@ class CopySplitTest : public testing::Test { ASSERT(textureSpec.width % textureSpec.blockWidth == 0 && textureSpec.height % textureSpec.blockHeight == 0); dawn_native::TexelBlockInfo blockInfo = {}; - blockInfo.blockWidth = textureSpec.blockWidth; - blockInfo.blockHeight = textureSpec.blockHeight; - blockInfo.blockByteSize = textureSpec.texelBlockSizeInBytes; + blockInfo.width = textureSpec.blockWidth; + blockInfo.height = textureSpec.blockHeight; + blockInfo.byteSize = textureSpec.texelBlockSizeInBytes; Texture2DCopySplit copySplit = ComputeTextureCopySplit( {textureSpec.x, textureSpec.y, textureSpec.z}, {textureSpec.width, textureSpec.height, textureSpec.depth}, blockInfo,