D3D12: Unify both buffer<->texture copy paths.

The two paths were duplicated with extremely similar code.
Unifying them will help implement the buffer<->1D texture
copies by having a single place to change.

Bug: dawn:814
Change-Id: Id574bf62fc85e5e72ab54ba5066e52ff37000e87
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/78723
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2022-02-01 11:04:53 +00:00 committed by Dawn LUCI CQ
parent 0cb5c0edeb
commit 9dfcc20750
5 changed files with 119 additions and 225 deletions

View File

@ -215,23 +215,23 @@ namespace dawn::native::d3d12 {
DAWN_TRY_ASSIGN(tempBufferBase, device->CreateBuffer(&tempBufferDescriptor));
Ref<Buffer> tempBuffer = ToBackend(std::move(tempBufferBase));
// Copy from source texture into tempBuffer
Texture* srcTexture = ToBackend(srcCopy.texture).Get();
tempBuffer->TrackUsageAndTransitionNow(recordingContext, wgpu::BufferUsage::CopyDst);
BufferCopy bufferCopy;
bufferCopy.buffer = tempBuffer;
bufferCopy.offset = 0;
bufferCopy.bytesPerRow = bytesPerRow;
bufferCopy.rowsPerImage = rowsPerImage;
RecordCopyTextureToBuffer(recordingContext->GetCommandList(), srcCopy, bufferCopy,
srcTexture, tempBuffer.Get(), copySize);
// Copy from source texture into tempBuffer
tempBuffer->TrackUsageAndTransitionNow(recordingContext, wgpu::BufferUsage::CopyDst);
RecordBufferTextureCopy(BufferTextureCopyDirection::T2B,
recordingContext->GetCommandList(), bufferCopy, srcCopy,
copySize);
// Copy from tempBuffer into destination texture
tempBuffer->TrackUsageAndTransitionNow(recordingContext, wgpu::BufferUsage::CopySrc);
Texture* dstTexture = ToBackend(dstCopy.texture).Get();
RecordCopyBufferToTexture(recordingContext, dstCopy, tempBuffer->GetD3D12Resource(), 0,
bytesPerRow, rowsPerImage, copySize, dstTexture,
dstCopy.aspect);
RecordBufferTextureCopy(BufferTextureCopyDirection::B2T,
recordingContext->GetCommandList(), bufferCopy, dstCopy,
copySize);
// Save tempBuffer into recordingContext
recordingContext->AddToTempBuffers(std::move(tempBuffer));
@ -760,10 +760,8 @@ namespace dawn::native::d3d12 {
texture->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopyDst,
subresources);
RecordCopyBufferToTexture(commandContext, copy->destination,
buffer->GetD3D12Resource(), copy->source.offset,
copy->source.bytesPerRow, copy->source.rowsPerImage,
copy->copySize, texture, subresources.aspects);
RecordBufferTextureCopy(BufferTextureCopyDirection::B2T, commandList,
copy->source, copy->destination, copy->copySize);
break;
}
@ -790,8 +788,8 @@ namespace dawn::native::d3d12 {
subresources);
buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst);
RecordCopyTextureToBuffer(commandList, copy->source, copy->destination, texture,
buffer, copy->copySize);
RecordBufferTextureCopy(BufferTextureCopyDirection::T2B, commandList,
copy->destination, copy->source, copy->copySize);
break;
}

View File

@ -511,9 +511,10 @@ namespace dawn::native::d3d12 {
texture->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopyDst, range);
RecordCopyBufferToTexture(commandContext, *dst, ToBackend(source)->GetResource(),
src.offset, src.bytesPerRow, src.rowsPerImage, copySizePixels,
texture, range.aspects);
RecordBufferTextureCopyWithBufferHandle(
BufferTextureCopyDirection::B2T, commandContext->GetCommandList(),
ToBackend(source)->GetResource(), src.offset, src.bytesPerRow, src.rowsPerImage, *dst,
copySizePixels);
return {};
}

View File

@ -1101,9 +1101,6 @@ namespace dawn::native::d3d12 {
// compute d3d12 texture copy locations for texture and buffer
Extent3D copySize = GetMipLevelPhysicalSize(level);
TextureCopySubresource copySplit = Compute2DTextureCopySubresource(
{0, 0, 0}, copySize, blockInfo, uploadHandle.startOffset, bytesPerRow);
for (uint32_t layer = range.baseArrayLayer;
layer < range.baseArrayLayer + range.layerCount; ++layer) {
if (clearValue == TextureBase::ClearValue::Zero &&
@ -1113,10 +1110,16 @@ namespace dawn::native::d3d12 {
continue;
}
RecordCopyBufferToTextureFromTextureCopySplit(
commandList, copySplit,
ToBackend(uploadHandle.stagingBuffer)->GetResource(), 0, bytesPerRow,
this, level, layer, aspect);
TextureCopy textureCopy;
textureCopy.texture = this;
textureCopy.origin = {0, 0, layer};
textureCopy.mipLevel = level;
textureCopy.aspect = aspect;
RecordBufferTextureCopyWithBufferHandle(
BufferTextureCopyDirection::B2T, commandList,
ToBackend(uploadHandle.stagingBuffer)->GetResource(),
uploadHandle.startOffset, bytesPerRow, GetHeight(), textureCopy,
copySize);
}
}
}

View File

@ -144,16 +144,17 @@ namespace dawn::native::d3d12 {
}
}
void RecordCopyBufferToTextureFromTextureCopySplit(ID3D12GraphicsCommandList* commandList,
const TextureCopySubresource& baseCopySplit,
ID3D12Resource* bufferResource,
uint64_t baseOffset,
uint64_t bufferBytesPerRow,
Texture* texture,
uint32_t textureMiplevel,
uint32_t textureLayer,
Aspect aspect) {
ASSERT(HasOneBit(aspect));
void RecordBufferTextureCopyFromSplits(BufferTextureCopyDirection direction,
ID3D12GraphicsCommandList* commandList,
const TextureCopySubresource& baseCopySplit,
ID3D12Resource* bufferResource,
uint64_t baseOffset,
uint64_t bufferBytesPerRow,
TextureBase* textureBase,
uint32_t textureMiplevel,
uint32_t textureLayer,
Aspect aspect) {
Texture* texture = ToBackend(textureBase);
const D3D12_TEXTURE_COPY_LOCATION textureLocation =
ComputeTextureCopyLocationForTexture(texture, textureMiplevel, textureLayer, aspect);
@ -166,27 +167,35 @@ namespace dawn::native::d3d12 {
const D3D12_TEXTURE_COPY_LOCATION bufferLocation =
ComputeBufferLocationForCopyTextureRegion(texture, bufferResource, info.bufferSize,
offsetBytes, bufferBytesPerRow, aspect);
const D3D12_BOX sourceRegion =
ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
if (direction == BufferTextureCopyDirection::B2T) {
const D3D12_BOX sourceRegion =
ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
info.textureOffset.y, info.textureOffset.z,
&bufferLocation, &sourceRegion);
commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
info.textureOffset.y, info.textureOffset.z,
&bufferLocation, &sourceRegion);
} else {
ASSERT(direction == BufferTextureCopyDirection::T2B);
const D3D12_BOX sourceRegion =
ComputeD3D12BoxFromOffsetAndSize(info.textureOffset, info.copySize);
commandList->CopyTextureRegion(&bufferLocation, info.bufferOffset.x,
info.bufferOffset.y, info.bufferOffset.z,
&textureLocation, &sourceRegion);
}
}
}
void CopyBufferTo2DTextureWithCopySplit(CommandRecordingContext* commandContext,
const TextureCopy& textureCopy,
void Record2DBufferTextureCopyWithSplit(BufferTextureCopyDirection direction,
ID3D12GraphicsCommandList* commandList,
ID3D12Resource* bufferResource,
const uint64_t offset,
const uint32_t bytesPerRow,
const uint32_t rowsPerImage,
const Extent3D& copySize,
Texture* texture,
Aspect aspect) {
ASSERT(HasOneBit(aspect));
const TextureCopy& textureCopy,
const TexelBlockInfo& blockInfo,
const Extent3D& copySize) {
// See comments in Compute2DTextureCopySplits() for more details.
const TexelBlockInfo& blockInfo = texture->GetFormat().GetAspectInfo(aspect).block;
const TextureCopySplits copySplits = Compute2DTextureCopySplits(
textureCopy.origin, copySize, blockInfo, offset, bytesPerRow, rowsPerImage);
@ -210,166 +219,66 @@ namespace dawn::native::d3d12 {
const uint64_t bufferOffsetForNextLayer = bufferOffsetsForNextLayer[splitIndex];
const uint32_t copyTextureLayer = copyLayer + textureCopy.origin.z;
RecordCopyBufferToTextureFromTextureCopySplit(
commandContext->GetCommandList(), copySplitPerLayerBase, bufferResource,
bufferOffsetForNextLayer, bytesPerRow, texture, textureCopy.mipLevel,
copyTextureLayer, aspect);
RecordBufferTextureCopyFromSplits(direction, commandList, copySplitPerLayerBase,
bufferResource, bufferOffsetForNextLayer, bytesPerRow,
textureCopy.texture.Get(), textureCopy.mipLevel,
copyTextureLayer, textureCopy.aspect);
bufferOffsetsForNextLayer[splitIndex] +=
bytesPerLayer * copySplits.copySubresources.size();
}
}
void CopyBufferTo3DTexture(CommandRecordingContext* commandContext,
const TextureCopy& textureCopy,
ID3D12Resource* bufferResource,
const uint64_t offset,
const uint32_t bytesPerRow,
const uint32_t rowsPerImage,
const Extent3D& copySize,
Texture* texture,
Aspect aspect) {
ASSERT(HasOneBit(aspect));
// See comments in Compute3DTextureCopySplits() for more details.
const TexelBlockInfo& blockInfo = texture->GetFormat().GetAspectInfo(aspect).block;
const TextureCopySubresource copyRegions = Compute3DTextureCopySplits(
textureCopy.origin, copySize, blockInfo, offset, bytesPerRow, rowsPerImage);
RecordCopyBufferToTextureFromTextureCopySplit(commandContext->GetCommandList(), copyRegions,
bufferResource, 0, bytesPerRow, texture,
textureCopy.mipLevel, 0, aspect);
}
void RecordCopyBufferToTexture(CommandRecordingContext* commandContext,
const TextureCopy& textureCopy,
ID3D12Resource* bufferResource,
const uint64_t offset,
const uint32_t bytesPerRow,
const uint32_t rowsPerImage,
const Extent3D& copySize,
Texture* texture,
Aspect aspect) {
// Record the CopyTextureRegion commands for 3D textures. Multiple depths of 3D
// textures can be copied in one shot and copySplits are not needed.
if (texture->GetDimension() == wgpu::TextureDimension::e3D) {
CopyBufferTo3DTexture(commandContext, textureCopy, bufferResource, offset, bytesPerRow,
rowsPerImage, copySize, texture, aspect);
} else {
// Compute the copySplits and record the CopyTextureRegion commands for 2D
// textures.
CopyBufferTo2DTextureWithCopySplit(commandContext, textureCopy, bufferResource, offset,
bytesPerRow, rowsPerImage, copySize, texture,
aspect);
}
}
void RecordCopyTextureToBufferFromTextureCopySplit(ID3D12GraphicsCommandList* commandList,
const TextureCopySubresource& baseCopySplit,
Buffer* buffer,
uint64_t baseOffset,
uint64_t bufferBytesPerRow,
Texture* texture,
uint32_t textureMiplevel,
uint32_t textureLayer,
Aspect aspect) {
const D3D12_TEXTURE_COPY_LOCATION textureLocation =
ComputeTextureCopyLocationForTexture(texture, textureMiplevel, textureLayer, aspect);
for (uint32_t i = 0; i < baseCopySplit.count; ++i) {
const TextureCopySubresource::CopyInfo& info = baseCopySplit.copies[i];
// TODO(jiawei.shao@intel.com): pre-compute bufferLocation and sourceRegion as
// members in TextureCopySubresource::CopyInfo.
const uint64_t offsetBytes = info.alignedOffset + baseOffset;
const D3D12_TEXTURE_COPY_LOCATION bufferLocation =
ComputeBufferLocationForCopyTextureRegion(texture, buffer->GetD3D12Resource(),
info.bufferSize, offsetBytes,
bufferBytesPerRow, aspect);
const D3D12_BOX sourceRegion =
ComputeD3D12BoxFromOffsetAndSize(info.textureOffset, info.copySize);
commandList->CopyTextureRegion(&bufferLocation, info.bufferOffset.x,
info.bufferOffset.y, info.bufferOffset.z,
&textureLocation, &sourceRegion);
}
}
void Copy2DTextureToBufferWithCopySplit(ID3D12GraphicsCommandList* commandList,
const TextureCopy& textureCopy,
const BufferCopy& bufferCopy,
Texture* texture,
Buffer* buffer,
const Extent3D& copySize) {
void RecordBufferTextureCopyWithBufferHandle(BufferTextureCopyDirection direction,
ID3D12GraphicsCommandList* commandList,
ID3D12Resource* bufferResource,
const uint64_t offset,
const uint32_t bytesPerRow,
const uint32_t rowsPerImage,
const TextureCopy& textureCopy,
const Extent3D& copySize) {
ASSERT(HasOneBit(textureCopy.aspect));
TextureBase* texture = textureCopy.texture.Get();
const TexelBlockInfo& blockInfo =
texture->GetFormat().GetAspectInfo(textureCopy.aspect).block;
// See comments around Compute2DTextureCopySplits() for more details.
const TextureCopySplits copySplits =
Compute2DTextureCopySplits(textureCopy.origin, copySize, blockInfo, bufferCopy.offset,
bufferCopy.bytesPerRow, bufferCopy.rowsPerImage);
switch (texture->GetDimension()) {
case wgpu::TextureDimension::e1D: {
UNREACHABLE();
break;
}
const uint64_t bytesPerLayer = bufferCopy.bytesPerRow * bufferCopy.rowsPerImage;
// Record the CopyTextureRegion commands for 2D textures, with special handling of array
// layers since each require their own set of copies.
case wgpu::TextureDimension::e2D:
Record2DBufferTextureCopyWithSplit(direction, commandList, bufferResource, offset,
bytesPerRow, rowsPerImage, textureCopy,
blockInfo, copySize);
break;
// copySplits.copySubresources[1] is always calculated for the second copy layer with
// extra "bytesPerLayer" copy offset compared with the first copy layer. So
// here we use an array bufferOffsetsForNextLayer to record the extra offsets
// for each copy layer: bufferOffsetsForNextLayer[0] is the extra offset for
// the next copy layer that uses copySplits.copySubresources[0], and
// bufferOffsetsForNextLayer[1] is the extra offset for the next copy layer
// that uses copySplits.copySubresources[1].
std::array<uint64_t, TextureCopySplits::kMaxTextureCopySubresources>
bufferOffsetsForNextLayer = {{0u, 0u}};
for (uint32_t copyLayer = 0; copyLayer < copySize.depthOrArrayLayers; ++copyLayer) {
const uint32_t splitIndex = copyLayer % copySplits.copySubresources.size();
case wgpu::TextureDimension::e3D: {
// See comments in Compute3DTextureCopySplits() for more details.
const TextureCopySubresource copyRegions = Compute3DTextureCopySplits(
textureCopy.origin, copySize, blockInfo, offset, bytesPerRow, rowsPerImage);
const TextureCopySubresource& copySplitPerLayerBase =
copySplits.copySubresources[splitIndex];
const uint64_t bufferOffsetForNextLayer = bufferOffsetsForNextLayer[splitIndex];
const uint32_t copyTextureLayer = copyLayer + textureCopy.origin.z;
RecordCopyTextureToBufferFromTextureCopySplit(
commandList, copySplitPerLayerBase, buffer, bufferOffsetForNextLayer,
bufferCopy.bytesPerRow, texture, textureCopy.mipLevel, copyTextureLayer,
textureCopy.aspect);
bufferOffsetsForNextLayer[splitIndex] +=
bytesPerLayer * copySplits.copySubresources.size();
RecordBufferTextureCopyFromSplits(direction, commandList, copyRegions,
bufferResource, 0, bytesPerRow, texture,
textureCopy.mipLevel, 0, textureCopy.aspect);
break;
}
}
}
void Copy3DTextureToBuffer(ID3D12GraphicsCommandList* commandList,
const TextureCopy& textureCopy,
const BufferCopy& bufferCopy,
Texture* texture,
Buffer* buffer,
const Extent3D& copySize) {
ASSERT(HasOneBit(textureCopy.aspect));
const TexelBlockInfo& blockInfo =
texture->GetFormat().GetAspectInfo(textureCopy.aspect).block;
// See comments around Compute3DTextureCopySplits() for more details.
const TextureCopySubresource copyRegions =
Compute3DTextureCopySplits(textureCopy.origin, copySize, blockInfo, bufferCopy.offset,
bufferCopy.bytesPerRow, bufferCopy.rowsPerImage);
RecordCopyTextureToBufferFromTextureCopySplit(commandList, copyRegions, buffer, 0,
bufferCopy.bytesPerRow, texture,
textureCopy.mipLevel, 0, textureCopy.aspect);
}
void RecordCopyTextureToBuffer(ID3D12GraphicsCommandList* commandList,
const TextureCopy& textureCopy,
const BufferCopy& bufferCopy,
Texture* texture,
Buffer* buffer,
const Extent3D& copySize) {
if (texture->GetDimension() == wgpu::TextureDimension::e3D) {
Copy3DTextureToBuffer(commandList, textureCopy, bufferCopy, texture, buffer, copySize);
} else {
Copy2DTextureToBufferWithCopySplit(commandList, textureCopy, bufferCopy, texture,
buffer, copySize);
}
void RecordBufferTextureCopy(BufferTextureCopyDirection direction,
ID3D12GraphicsCommandList* commandList,
const BufferCopy& bufferCopy,
const TextureCopy& textureCopy,
const Extent3D& copySize) {
RecordBufferTextureCopyWithBufferHandle(direction, commandList,
ToBackend(bufferCopy.buffer)->GetD3D12Resource(),
bufferCopy.offset, bufferCopy.bytesPerRow,
bufferCopy.rowsPerImage, textureCopy, copySize);
}
void SetDebugName(Device* device, ID3D12Object* object, const char* prefix, std::string label) {

View File

@ -44,42 +44,25 @@ namespace dawn::native::d3d12 {
bool IsTypeless(DXGI_FORMAT format);
void RecordCopyBufferToTextureFromTextureCopySplit(ID3D12GraphicsCommandList* commandList,
const TextureCopySubresource& baseCopySplit,
ID3D12Resource* bufferResource,
uint64_t baseOffset,
uint64_t bufferBytesPerRow,
Texture* texture,
uint32_t textureMiplevel,
uint32_t textureLayer,
Aspect aspect);
enum class BufferTextureCopyDirection {
B2T,
T2B,
};
void RecordCopyBufferToTexture(CommandRecordingContext* commandContext,
const TextureCopy& textureCopy,
ID3D12Resource* bufferResource,
const uint64_t offset,
const uint32_t bytesPerRow,
const uint32_t rowsPerImage,
const Extent3D& copySize,
Texture* texture,
Aspect aspect);
void RecordBufferTextureCopyWithBufferHandle(BufferTextureCopyDirection direction,
ID3D12GraphicsCommandList* commandList,
ID3D12Resource* bufferResource,
const uint64_t offset,
const uint32_t bytesPerRow,
const uint32_t rowsPerImage,
const TextureCopy& textureCopy,
const Extent3D& copySize);
void RecordCopyTextureToBufferFromTextureCopySplit(ID3D12GraphicsCommandList* commandList,
const TextureCopySubresource& baseCopySplit,
Buffer* buffer,
uint64_t baseOffset,
uint64_t bufferBytesPerRow,
Texture* texture,
uint32_t textureMiplevel,
uint32_t textureLayer,
Aspect aspect);
void RecordCopyTextureToBuffer(ID3D12GraphicsCommandList* commandList,
const TextureCopy& textureCopy,
const BufferCopy& bufferCopy,
Texture* texture,
Buffer* buffer,
const Extent3D& copySize);
void RecordBufferTextureCopy(BufferTextureCopyDirection direction,
ID3D12GraphicsCommandList* commandList,
const BufferCopy& bufferCopy,
const TextureCopy& textureCopy,
const Extent3D& copySize);
void SetDebugName(Device* device,
ID3D12Object* object,