mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 18:59:21 +00:00
Support BC5 formats on Metal
This patch adds the support of BC5 formats on Metal and the related dawn_end2end_tests to verify Dawn works correctly when (bufferSize - bufferOffset < bytesPerImage * copyExtent.depth), which is the special case of buffer-to-texture and texture-to-buffer copies on Metal. BUG=dawn:42 TEST=dawn_end2end_tests Change-Id: I27c384d0d8d2bb908f1ad15c2451fd23c1313598 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8720 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
committed by
Commit Bot service account
parent
4b90c47ce0
commit
ea2d558479
@@ -314,6 +314,7 @@ namespace dawn_native { namespace metal {
|
||||
TextureBufferCopySplit ComputeTextureBufferCopySplit(Origin3D origin,
|
||||
Extent3D copyExtent,
|
||||
Format textureFormat,
|
||||
Extent3D virtualSizeAtLevel,
|
||||
uint64_t bufferSize,
|
||||
uint64_t bufferOffset,
|
||||
uint32_t rowPitch,
|
||||
@@ -323,9 +324,10 @@ namespace dawn_native { namespace metal {
|
||||
// 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
|
||||
// data for the whole copy. Instead of looking at the position of the last texel in the
|
||||
// buffer, it computes the volume of the 3D box with rowPitch * imageHeight *
|
||||
// copySize.depth. For example considering the pixel buffer below where in memory, each
|
||||
// row data (D) of the texture is followed by some padding data (P):
|
||||
// buffer, it computes the volume of the 3D box with rowPitch * (imageHeight /
|
||||
// format.blockHeight) * copySize.depth. For example considering the pixel buffer below
|
||||
// where in memory, each row data (D) of the texture is followed by some padding data
|
||||
// (P):
|
||||
// |DDDDDDD|PP|
|
||||
// |DDDDDDD|PP|
|
||||
// |DDDDDDD|PP|
|
||||
@@ -336,7 +338,21 @@ namespace dawn_native { namespace metal {
|
||||
|
||||
// We work around this limitation by detecting when Metal would complain and copy the
|
||||
// last image and row separately using tight sourceBytesPerRow or sourceBytesPerImage.
|
||||
uint32_t bytesPerImage = rowPitch * imageHeight;
|
||||
uint32_t rowPitchCountPerImage = imageHeight / textureFormat.blockHeight;
|
||||
uint32_t bytesPerImage = rowPitch * rowPitchCountPerImage;
|
||||
|
||||
// Metal validation layer requires that if the texture's pixel format is a compressed
|
||||
// format, the sourceSize must be a multiple of the pixel format's block size or be
|
||||
// clamped to the edge of the texture if the block extends outside the bounds of a
|
||||
// texture.
|
||||
uint32_t clampedCopyExtentWidth =
|
||||
(origin.x + copyExtent.width > virtualSizeAtLevel.width)
|
||||
? (virtualSizeAtLevel.width - origin.x)
|
||||
: copyExtent.width;
|
||||
uint32_t clampedCopyExtentHeight =
|
||||
(origin.y + copyExtent.height > virtualSizeAtLevel.height)
|
||||
? (virtualSizeAtLevel.height - origin.y)
|
||||
: copyExtent.height;
|
||||
|
||||
// Check whether buffer size is big enough.
|
||||
bool needWorkaround = bufferSize - bufferOffset < bytesPerImage * copyExtent.depth;
|
||||
@@ -347,7 +363,7 @@ namespace dawn_native { namespace metal {
|
||||
copy.copies[0].bytesPerImage = bytesPerImage;
|
||||
copy.copies[0].textureOrigin = MTLOriginMake(origin.x, origin.y, origin.z);
|
||||
copy.copies[0].copyExtent =
|
||||
MTLSizeMake(copyExtent.width, copyExtent.height, copyExtent.depth);
|
||||
MTLSizeMake(clampedCopyExtentWidth, clampedCopyExtentHeight, copyExtent.depth);
|
||||
return copy;
|
||||
}
|
||||
|
||||
@@ -359,8 +375,8 @@ namespace dawn_native { namespace metal {
|
||||
copy.copies[copy.count].bytesPerRow = rowPitch;
|
||||
copy.copies[copy.count].bytesPerImage = bytesPerImage;
|
||||
copy.copies[copy.count].textureOrigin = MTLOriginMake(origin.x, origin.y, origin.z);
|
||||
copy.copies[copy.count].copyExtent =
|
||||
MTLSizeMake(copyExtent.width, copyExtent.height, copyExtent.depth - 1);
|
||||
copy.copies[copy.count].copyExtent = MTLSizeMake(
|
||||
clampedCopyExtentWidth, clampedCopyExtentHeight, copyExtent.depth - 1);
|
||||
|
||||
++copy.count;
|
||||
|
||||
@@ -369,30 +385,40 @@ namespace dawn_native { namespace metal {
|
||||
}
|
||||
|
||||
// Doing all the copy in last image except the last row.
|
||||
if (copyExtent.height > 1) {
|
||||
uint32_t copyBlockRowCount = copyExtent.height / textureFormat.blockHeight;
|
||||
if (copyBlockRowCount > 1) {
|
||||
copy.copies[copy.count].bufferOffset = currentOffset;
|
||||
copy.copies[copy.count].bytesPerRow = rowPitch;
|
||||
copy.copies[copy.count].bytesPerImage = rowPitch * (imageHeight - 1);
|
||||
copy.copies[copy.count].bytesPerImage = rowPitch * (copyBlockRowCount - 1);
|
||||
copy.copies[copy.count].textureOrigin =
|
||||
MTLOriginMake(origin.x, origin.y, origin.z + copyExtent.depth - 1);
|
||||
copy.copies[copy.count].copyExtent =
|
||||
MTLSizeMake(copyExtent.width, copyExtent.height - 1, 1);
|
||||
|
||||
ASSERT(copyExtent.height - textureFormat.blockHeight < virtualSizeAtLevel.height);
|
||||
copy.copies[copy.count].copyExtent = MTLSizeMake(
|
||||
clampedCopyExtentWidth, copyExtent.height - textureFormat.blockHeight, 1);
|
||||
|
||||
++copy.count;
|
||||
|
||||
// Update offset to copy to the last row.
|
||||
currentOffset += (copyExtent.height - 1) * rowPitch;
|
||||
currentOffset += (copyBlockRowCount - 1) * rowPitch;
|
||||
}
|
||||
|
||||
// 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 * textureFormat.blockByteSize;
|
||||
uint32_t lastRowDataSize =
|
||||
(copyExtent.width / textureFormat.blockWidth) * textureFormat.blockByteSize;
|
||||
uint32_t lastRowCopyExtentHeight =
|
||||
textureFormat.blockHeight + clampedCopyExtentHeight - copyExtent.height;
|
||||
ASSERT(lastRowCopyExtentHeight <= textureFormat.blockHeight);
|
||||
|
||||
copy.copies[copy.count].bufferOffset = currentOffset;
|
||||
copy.copies[copy.count].bytesPerRow = lastRowDataSize;
|
||||
copy.copies[copy.count].bytesPerImage = lastRowDataSize;
|
||||
copy.copies[copy.count].textureOrigin = MTLOriginMake(
|
||||
origin.x, origin.y + copyExtent.height - 1, origin.z + copyExtent.depth - 1);
|
||||
copy.copies[copy.count].copyExtent = MTLSizeMake(copyExtent.width, 1, 1);
|
||||
copy.copies[copy.count].textureOrigin =
|
||||
MTLOriginMake(origin.x, origin.y + copyExtent.height - textureFormat.blockHeight,
|
||||
origin.z + copyExtent.depth - 1);
|
||||
copy.copies[copy.count].copyExtent =
|
||||
MTLSizeMake(clampedCopyExtentWidth, lastRowCopyExtentHeight, 1);
|
||||
++copy.count;
|
||||
|
||||
return copy;
|
||||
@@ -446,9 +472,10 @@ namespace dawn_native { namespace metal {
|
||||
Buffer* buffer = ToBackend(src.buffer.Get());
|
||||
Texture* texture = ToBackend(dst.texture.Get());
|
||||
|
||||
Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(dst.mipLevel);
|
||||
TextureBufferCopySplit splittedCopies = ComputeTextureBufferCopySplit(
|
||||
dst.origin, copySize, texture->GetFormat(), buffer->GetSize(), src.offset,
|
||||
src.rowPitch, src.imageHeight);
|
||||
dst.origin, copySize, texture->GetFormat(), virtualSizeAtLevel,
|
||||
buffer->GetSize(), src.offset, src.rowPitch, src.imageHeight);
|
||||
|
||||
encoders.EnsureBlit(commandBuffer);
|
||||
for (uint32_t i = 0; i < splittedCopies.count; ++i) {
|
||||
@@ -473,9 +500,10 @@ namespace dawn_native { namespace metal {
|
||||
Texture* texture = ToBackend(src.texture.Get());
|
||||
Buffer* buffer = ToBackend(dst.buffer.Get());
|
||||
|
||||
Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(src.mipLevel);
|
||||
TextureBufferCopySplit splittedCopies = ComputeTextureBufferCopySplit(
|
||||
src.origin, copySize, texture->GetFormat(), buffer->GetSize(), dst.offset,
|
||||
dst.rowPitch, dst.imageHeight);
|
||||
src.origin, copySize, texture->GetFormat(), virtualSizeAtLevel,
|
||||
buffer->GetSize(), dst.offset, dst.rowPitch, dst.imageHeight);
|
||||
|
||||
encoders.EnsureBlit(commandBuffer);
|
||||
for (uint32_t i = 0; i < splittedCopies.count; ++i) {
|
||||
|
||||
@@ -215,6 +215,12 @@ namespace dawn_native { namespace metal {
|
||||
case dawn::TextureFormat::Depth24PlusStencil8:
|
||||
return MTLPixelFormatDepth32Float_Stencil8;
|
||||
|
||||
// TODO(jiawei.shao@intel.com): support all BC formats
|
||||
case dawn::TextureFormat::BC5RGSnorm:
|
||||
return MTLPixelFormatBC5_RGSnorm;
|
||||
case dawn::TextureFormat::BC5RGUnorm:
|
||||
return MTLPixelFormatBC5_RGUnorm;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user