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,