Support 1D texture copies.

- WriteBuffer to 1D textures
 - copyBufferToTexture to 1D textures
 - copyTextureToBuffer from 1D textures
 - copyTextureToTexture with 1D textures

Test coverage will be provided by the CTS. At the time this
commit is up for review, the validation tests have been change
to test 1D texture copies comprehensively, except for copies
between 1D textures and textures of other dimensions.

Bug: dawn:814
Change-Id: I91a278d9c113a06a108fecb124aa21fea5e691b3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/64544
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2022-02-01 15:32:32 +00:00 committed by Dawn LUCI CQ
parent e59b4b4c57
commit 38b188ce61
13 changed files with 105 additions and 70 deletions

View File

@ -76,28 +76,29 @@ namespace dawn::native {
const uint32_t mipLevel) {
Extent3D extent = texture->GetMipLevelPhysicalSize(mipLevel);
ASSERT(texture->GetDimension() != wgpu::TextureDimension::e1D);
switch (texture->GetDimension()) {
case wgpu::TextureDimension::e1D:
return extent.width == copySize.width;
case wgpu::TextureDimension::e2D:
return extent.width == copySize.width && extent.height == copySize.height;
case wgpu::TextureDimension::e3D:
return extent.width == copySize.width && extent.height == copySize.height &&
extent.depthOrArrayLayers == copySize.depthOrArrayLayers;
default:
UNREACHABLE();
}
}
SubresourceRange GetSubresourcesAffectedByCopy(const TextureCopy& copy,
const Extent3D& copySize) {
switch (copy.texture->GetDimension()) {
case wgpu::TextureDimension::e1D:
ASSERT(copy.origin.z == 0 && copySize.depthOrArrayLayers == 1);
ASSERT(copy.mipLevel == 0);
return {copy.aspect, {0, 1}, {0, 1}};
case wgpu::TextureDimension::e2D:
return {
copy.aspect, {copy.origin.z, copySize.depthOrArrayLayers}, {copy.mipLevel, 1}};
case wgpu::TextureDimension::e3D:
return {copy.aspect, {0, 1}, {copy.mipLevel, 1}};
default:
UNREACHABLE();
}
}

View File

@ -268,12 +268,6 @@ namespace dawn::native {
const TextureBase* texture = textureCopy.texture;
DAWN_TRY(device->ValidateObject(texture));
// TODO(https://crbug.com/dawn/814): Disallow 1D texture copies until they are implemented.
DAWN_INVALID_IF(texture->GetDimension() == wgpu::TextureDimension::e1D,
"%s is used in a copy and has dimension %s. Copies with %s aren't "
"implemented (yet) and are disallowed. See https://crbug.com/dawn/814.",
texture, wgpu::TextureDimension::e1D, wgpu::TextureDimension::e1D);
DAWN_INVALID_IF(textureCopy.mipLevel >= texture->GetNumMipLevels(),
"MipLevel (%u) is greater than the number of mip levels (%u) in %s.",
textureCopy.mipLevel, texture->GetNumMipLevels(), texture);
@ -306,8 +300,6 @@ namespace dawn::native {
const Extent3D& copySize) {
const TextureBase* texture = textureCopy.texture;
ASSERT(texture->GetDimension() != wgpu::TextureDimension::e1D);
// Validation for the copy being in-bounds:
Extent3D mipSize = texture->GetMipLevelPhysicalSize(textureCopy.mipLevel);
// For 1D/2D textures, include the array layer as depth so it can be checked with other
@ -420,14 +412,29 @@ namespace dawn::native {
"(%s).",
dst.texture, dst.aspect, format.format);
if (src.texture == dst.texture && src.mipLevel == dst.mipLevel) {
wgpu::TextureDimension dimension = src.texture->GetDimension();
ASSERT(dimension != wgpu::TextureDimension::e1D);
DAWN_INVALID_IF(
(dimension == wgpu::TextureDimension::e2D &&
IsRangeOverlapped(src.origin.z, dst.origin.z, copySize.depthOrArrayLayers)) ||
dimension == wgpu::TextureDimension::e3D,
"Cannot copy between overlapping subresources of %s.", src.texture);
if (src.texture == dst.texture) {
switch (src.texture->GetDimension()) {
case wgpu::TextureDimension::e1D:
ASSERT(src.mipLevel == 0 && src.origin.z == 0 && dst.origin.z == 0);
return DAWN_FORMAT_VALIDATION_ERROR("Copy is from %s to itself.", src.texture);
case wgpu::TextureDimension::e2D:
DAWN_INVALID_IF(src.mipLevel == dst.mipLevel &&
IsRangeOverlapped(src.origin.z, dst.origin.z,
copySize.depthOrArrayLayers),
"Copy source and destination are overlapping layer ranges "
"([%u, %u) and [%u, %u)) of %s mip level %u",
src.origin.z, src.origin.z + copySize.depthOrArrayLayers,
dst.origin.z, dst.origin.z + copySize.depthOrArrayLayers,
src.texture, src.mipLevel);
break;
case wgpu::TextureDimension::e3D:
DAWN_INVALID_IF(src.mipLevel == dst.mipLevel,
"Copy is from %s mip level %u to itself.", src.texture,
src.mipLevel);
break;
}
}
return {};

View File

@ -538,7 +538,6 @@ namespace dawn::native {
}
uint32_t TextureBase::GetHeight() const {
ASSERT(!IsError());
ASSERT(mDimension != wgpu::TextureDimension::e1D);
return mSize.height;
}
uint32_t TextureBase::GetDepth() const {

View File

@ -745,7 +745,6 @@ namespace dawn::native::d3d12 {
DAWN_TRY(buffer->EnsureDataInitialized(commandContext));
ASSERT(texture->GetDimension() != wgpu::TextureDimension::e1D);
SubresourceRange subresources =
GetSubresourcesAffectedByCopy(copy->destination, copy->copySize);
@ -778,7 +777,6 @@ namespace dawn::native::d3d12 {
DAWN_TRY(buffer->EnsureDataInitializedAsDestination(commandContext, copy));
ASSERT(texture->GetDimension() != wgpu::TextureDimension::e1D);
SubresourceRange subresources =
GetSubresourcesAffectedByCopy(copy->source, copy->copySize);
@ -862,9 +860,6 @@ namespace dawn::native::d3d12 {
&sourceRegion);
}
} else {
// TODO(crbug.com/dawn/814): support copying with 1D.
ASSERT(source->GetDimension() != wgpu::TextureDimension::e1D &&
destination->GetDimension() != wgpu::TextureDimension::e1D);
const dawn::native::Extent3D copyExtentOneSlice = {
copy->copySize.width, copy->copySize.height, 1u};
@ -873,27 +868,29 @@ namespace dawn::native::d3d12 {
uint32_t sourceLayer = 0;
uint32_t sourceZ = 0;
switch (source->GetDimension()) {
case wgpu::TextureDimension::e1D:
ASSERT(copy->source.origin.z == 0);
break;
case wgpu::TextureDimension::e2D:
sourceLayer = copy->source.origin.z + z;
break;
case wgpu::TextureDimension::e3D:
sourceZ = copy->source.origin.z + z;
break;
case wgpu::TextureDimension::e1D:
UNREACHABLE();
}
uint32_t destinationLayer = 0;
uint32_t destinationZ = 0;
switch (destination->GetDimension()) {
case wgpu::TextureDimension::e1D:
ASSERT(copy->destination.origin.z == 0);
break;
case wgpu::TextureDimension::e2D:
destinationLayer = copy->destination.origin.z + z;
break;
case wgpu::TextureDimension::e3D:
destinationZ = copy->destination.origin.z + z;
break;
case wgpu::TextureDimension::e1D:
UNREACHABLE();
}
D3D12_TEXTURE_COPY_LOCATION srcLocation =
ComputeTextureCopyLocationForTexture(

View File

@ -499,7 +499,6 @@ namespace dawn::native::d3d12 {
CommandRecordingContext* commandContext;
DAWN_TRY_ASSIGN(commandContext, GetPendingCommandContext());
Texture* texture = ToBackend(dst->texture.Get());
ASSERT(texture->GetDimension() != wgpu::TextureDimension::e1D);
SubresourceRange range = GetSubresourcesAffectedByCopy(*dst, copySizePixels);

View File

@ -869,8 +869,6 @@ namespace dawn::native::d3d12 {
const ExecutionSerial pendingCommandSerial =
ToBackend(GetDevice())->GetPendingCommandSerial();
ASSERT(GetDimension() != wgpu::TextureDimension::e1D);
mSubresourceStateAndDecay.Update(
range, [&](const SubresourceRange& updateRange, StateAndDecay* state) {
TransitionSubresourceRange(barriers, updateRange, state, newState,
@ -892,8 +890,6 @@ namespace dawn::native::d3d12 {
const ExecutionSerial pendingCommandSerial =
ToBackend(GetDevice())->GetPendingCommandSerial();
// TODO(crbug.com/dawn/814): support 1D textures.
ASSERT(GetDimension() != wgpu::TextureDimension::e1D);
mSubresourceStateAndDecay.Merge(textureUsages, [&](const SubresourceRange& mergeRange,
StateAndDecay* state,

View File

@ -245,7 +245,15 @@ namespace dawn::native::d3d12 {
switch (texture->GetDimension()) {
case wgpu::TextureDimension::e1D: {
UNREACHABLE();
// 1D textures copy splits are a subset of the single-layer 2D texture copy splits,
// at least while 1D textures can only have a single array layer.
ASSERT(texture->GetArrayLayers() == 1);
TextureCopySubresource copyRegions = Compute2DTextureCopySubresource(
textureCopy.origin, copySize, blockInfo, offset, bytesPerRow);
RecordBufferTextureCopyFromSplits(direction, commandList, copyRegions,
bufferResource, 0, bytesPerRow, texture,
textureCopy.mipLevel, 0, textureCopy.aspect);
break;
}
@ -259,7 +267,7 @@ namespace dawn::native::d3d12 {
case wgpu::TextureDimension::e3D: {
// See comments in Compute3DTextureCopySplits() for more details.
const TextureCopySubresource copyRegions = Compute3DTextureCopySplits(
TextureCopySubresource copyRegions = Compute3DTextureCopySplits(
textureCopy.origin, copySize, blockInfo, offset, bytesPerRow, rowsPerImage);
RecordBufferTextureCopyFromSplits(direction, commandList, copyRegions,

View File

@ -614,6 +614,20 @@ namespace dawn::native::metal {
for (const auto& copyInfo : splitCopies) {
uint64_t bufferOffset = copyInfo.bufferOffset;
switch (texture->GetDimension()) {
case wgpu::TextureDimension::e1D: {
[commandContext->EnsureBlit()
copyFromBuffer:mtlBuffer
sourceOffset:bufferOffset
sourceBytesPerRow:copyInfo.bytesPerRow
sourceBytesPerImage:copyInfo.bytesPerImage
sourceSize:MTLSizeMake(copyInfo.copyExtent.width, 1, 1)
toTexture:texture->GetMTLTexture()
destinationSlice:0
destinationLevel:mipLevel
destinationOrigin:MTLOriginMake(copyInfo.textureOrigin.x, 0, 0)
options:blitOption];
break;
}
case wgpu::TextureDimension::e2D: {
const MTLOrigin textureOrigin =
MTLOriginMake(copyInfo.textureOrigin.x, copyInfo.textureOrigin.y, 0);
@ -655,8 +669,6 @@ namespace dawn::native::metal {
options:blitOption];
break;
}
case wgpu::TextureDimension::e1D:
UNREACHABLE();
}
}
}
@ -797,6 +809,23 @@ namespace dawn::native::metal {
uint64_t bufferOffset = copyInfo.bufferOffset;
switch (texture->GetDimension()) {
case wgpu::TextureDimension::e1D: {
[commandContext->EnsureBlit()
copyFromTexture:texture->GetMTLTexture()
sourceSlice:0
sourceLevel:src.mipLevel
sourceOrigin:MTLOriginMake(copyInfo.textureOrigin.x,
0, 0)
sourceSize:MTLSizeMake(copyInfo.copyExtent.width,
1, 1)
toBuffer:buffer->GetMTLBuffer()
destinationOffset:bufferOffset
destinationBytesPerRow:copyInfo.bytesPerRow
destinationBytesPerImage:copyInfo.bytesPerImage
options:blitOption];
break;
}
case wgpu::TextureDimension::e2D: {
const MTLOrigin textureOrigin = MTLOriginMake(
copyInfo.textureOrigin.x, copyInfo.textureOrigin.y, 0);
@ -841,8 +870,6 @@ namespace dawn::native::metal {
options:blitOption];
break;
}
case wgpu::TextureDimension::e1D:
UNREACHABLE();
}
}
break;
@ -865,10 +892,6 @@ namespace dawn::native::metal {
EnsureDestinationTextureInitialized(commandContext, dstTexture,
copy->destination, copy->copySize);
// TODO(crbug.com/dawn/814): support copies with 1D textures.
ASSERT(srcTexture->GetDimension() != wgpu::TextureDimension::e1D &&
dstTexture->GetDimension() != wgpu::TextureDimension::e1D);
const MTLSize sizeOneSlice =
MTLSizeMake(copy->copySize.width, copy->copySize.height, 1);
@ -892,7 +915,7 @@ namespace dawn::native::metal {
destinationZPtr = &destinationOriginZ;
}
// TODO(crbug.com/dawn/782): Do a single T2T copy if both are 3D.
// TODO(crbug.com/dawn/782): Do a single T2T copy if both are 1D or 3D.
for (uint32_t z = 0; z < copy->copySize.depthOrArrayLayers; ++z) {
*sourceZPtr = copy->source.origin.z + z;
*destinationZPtr = copy->destination.origin.z + z;

View File

@ -84,8 +84,6 @@ namespace dawn::native::metal {
const Extent3D clampedCopyExtent =
texture->ClampToMipLevelVirtualSize(mipLevel, origin, copyExtent);
ASSERT(texture->GetDimension() != wgpu::TextureDimension::e1D);
// Check whether buffer size is big enough.
bool needWorkaround =
bufferSize - bufferOffset < bytesPerImage * copyExtent.depthOrArrayLayers;

View File

@ -82,6 +82,11 @@ namespace dawn::native::vulkan {
region.srcOffset.x = srcCopy.origin.x;
region.srcOffset.y = srcCopy.origin.y;
switch (srcTexture->GetDimension()) {
case wgpu::TextureDimension::e1D:
region.srcSubresource.baseArrayLayer = 0;
region.srcSubresource.layerCount = 1;
region.srcOffset.z = 0;
break;
case wgpu::TextureDimension::e2D:
region.srcSubresource.baseArrayLayer = srcCopy.origin.z;
region.srcSubresource.layerCount = copySize.depthOrArrayLayers;
@ -93,14 +98,16 @@ namespace dawn::native::vulkan {
region.srcSubresource.layerCount = 1;
region.srcOffset.z = srcCopy.origin.z;
break;
case wgpu::TextureDimension::e1D:
// TODO(crbug.com/dawn/814): support 1D textures
UNREACHABLE();
}
region.dstOffset.x = dstCopy.origin.x;
region.dstOffset.y = dstCopy.origin.y;
switch (dstTexture->GetDimension()) {
case wgpu::TextureDimension::e1D:
region.dstSubresource.baseArrayLayer = 0;
region.dstSubresource.layerCount = 1;
region.dstOffset.z = 0;
break;
case wgpu::TextureDimension::e2D:
region.dstSubresource.baseArrayLayer = dstCopy.origin.z;
region.dstSubresource.layerCount = copySize.depthOrArrayLayers;
@ -112,9 +119,6 @@ namespace dawn::native::vulkan {
region.dstSubresource.layerCount = 1;
region.dstOffset.z = dstCopy.origin.z;
break;
case wgpu::TextureDimension::e1D:
// TODO(crbug.com/dawn/814): support 1D textures
UNREACHABLE();
}
ASSERT(HasSameTextureCopyExtent(srcCopy, dstCopy, copySize));
@ -564,7 +568,6 @@ namespace dawn::native::vulkan {
ComputeBufferImageCopyRegion(src, dst, copy->copySize);
VkImageSubresourceLayers subresource = region.imageSubresource;
ASSERT(dst.texture->GetDimension() != wgpu::TextureDimension::e1D);
SubresourceRange range =
GetSubresourcesAffectedByCopy(copy->destination, copy->copySize);
@ -607,7 +610,6 @@ namespace dawn::native::vulkan {
VkBufferImageCopy region =
ComputeBufferImageCopyRegion(dst, src, copy->copySize);
ASSERT(src.texture->GetDimension() != wgpu::TextureDimension::e1D);
SubresourceRange range =
GetSubresourcesAffectedByCopy(copy->source, copy->copySize);

View File

@ -689,7 +689,6 @@ namespace dawn::native::vulkan {
VkBufferImageCopy region = ComputeBufferImageCopyRegion(src, *dst, copySizePixels);
VkImageSubresourceLayers subresource = region.imageSubresource;
ASSERT(dst->texture->GetDimension() != wgpu::TextureDimension::e1D);
SubresourceRange range = GetSubresourcesAffectedByCopy(*dst, copySizePixels);
if (IsCompleteSubresourceCopiedTo(dst->texture.Get(), copySizePixels,

View File

@ -1042,9 +1042,6 @@ namespace dawn::native::vulkan {
wgpu::TextureUsage allUsages = wgpu::TextureUsage::None;
wgpu::TextureUsage allLastUsages = wgpu::TextureUsage::None;
// TODO(crbug.com/dawn/814): support 1D textures.
ASSERT(GetDimension() != wgpu::TextureDimension::e1D);
mSubresourceLastUsages->Merge(
subresourceUsages, [&](const SubresourceRange& range, wgpu::TextureUsage* lastUsage,
const wgpu::TextureUsage& newUsage) {

View File

@ -136,11 +136,24 @@ namespace dawn::native::vulkan {
region.imageSubresource.mipLevel = textureCopy.mipLevel;
switch (textureCopy.texture->GetDimension()) {
case wgpu::TextureDimension::e1D:
ASSERT(textureCopy.origin.z == 0 && copySize.depthOrArrayLayers == 1);
region.imageOffset.x = textureCopy.origin.x;
region.imageOffset.y = 0;
region.imageOffset.z = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
ASSERT(!textureCopy.texture->GetFormat().isCompressed);
region.imageExtent.width = copySize.width;
region.imageExtent.height = 1;
region.imageExtent.depth = 1;
break;
case wgpu::TextureDimension::e2D: {
region.imageOffset.x = textureCopy.origin.x;
region.imageOffset.y = textureCopy.origin.y;
region.imageOffset.z = 0;
region.imageSubresource.baseArrayLayer = textureCopy.origin.z;
region.imageSubresource.layerCount = copySize.depthOrArrayLayers;
@ -155,19 +168,15 @@ namespace dawn::native::vulkan {
region.imageOffset.x = textureCopy.origin.x;
region.imageOffset.y = textureCopy.origin.y;
region.imageOffset.z = textureCopy.origin.z;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
Extent3D imageExtent = ComputeTextureCopyExtent(textureCopy, copySize);
region.imageExtent.width = imageExtent.width;
region.imageExtent.height = imageExtent.height;
region.imageExtent.depth = imageExtent.depthOrArrayLayers;
ASSERT(!textureCopy.texture->GetFormat().isCompressed);
region.imageExtent.width = copySize.width;
region.imageExtent.height = copySize.height;
region.imageExtent.depth = copySize.depthOrArrayLayers;
break;
}
case wgpu::TextureDimension::e1D:
UNREACHABLE();
}
return region;