diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index f18a149cd4..72c38fb95d 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -215,23 +215,23 @@ namespace dawn::native::d3d12 { DAWN_TRY_ASSIGN(tempBufferBase, device->CreateBuffer(&tempBufferDescriptor)); Ref 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; } diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp index 7a72f6e3e8..2a403ce474 100644 --- a/src/dawn_native/d3d12/DeviceD3D12.cpp +++ b/src/dawn_native/d3d12/DeviceD3D12.cpp @@ -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 {}; } diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp index d958daf830..f269e59c21 100644 --- a/src/dawn_native/d3d12/TextureD3D12.cpp +++ b/src/dawn_native/d3d12/TextureD3D12.cpp @@ -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); } } } diff --git a/src/dawn_native/d3d12/UtilsD3D12.cpp b/src/dawn_native/d3d12/UtilsD3D12.cpp index 04be72b1fd..ae451df0f7 100644 --- a/src/dawn_native/d3d12/UtilsD3D12.cpp +++ b/src/dawn_native/d3d12/UtilsD3D12.cpp @@ -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 - 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) { diff --git a/src/dawn_native/d3d12/UtilsD3D12.h b/src/dawn_native/d3d12/UtilsD3D12.h index dcfb5ae83a..ab724ae94b 100644 --- a/src/dawn_native/d3d12/UtilsD3D12.h +++ b/src/dawn_native/d3d12/UtilsD3D12.h @@ -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,