Implement Queue::WriteTexture in D3D12
Bug: dawn:483
Change-Id: I9e5f54abc6675acbb11a021a3d38aea7195017c5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/26320
Commit-Queue: Natasha Lee <natlee@microsoft.com>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_native/Queue.cpp b/src/dawn_native/Queue.cpp
index 3afc185..403e022 100644
--- a/src/dawn_native/Queue.cpp
+++ b/src/dawn_native/Queue.cpp
@@ -158,14 +158,13 @@
return {};
}
- return WriteTextureImpl(destination, data, dataSize, dataLayout, writeSize);
+ return WriteTextureImpl(*destination, data, *dataLayout, *writeSize);
}
- MaybeError QueueBase::WriteTextureImpl(const TextureCopyView* destination,
+ MaybeError QueueBase::WriteTextureImpl(const TextureCopyView& destination,
const void* data,
- size_t dataSize,
- const TextureDataLayout* dataLayout,
- const Extent3D* writeSize) {
+ const TextureDataLayout& dataLayout,
+ const Extent3D& writeSize) {
// TODO(tommek@google.com): This should be implemented.
return {};
}
diff --git a/src/dawn_native/Queue.h b/src/dawn_native/Queue.h
index aad5175..441fa1b 100644
--- a/src/dawn_native/Queue.h
+++ b/src/dawn_native/Queue.h
@@ -58,11 +58,10 @@
uint64_t bufferOffset,
const void* data,
size_t size);
- virtual MaybeError WriteTextureImpl(const TextureCopyView* destination,
+ virtual MaybeError WriteTextureImpl(const TextureCopyView& destination,
const void* data,
- size_t dataSize,
- const TextureDataLayout* dataLayout,
- const Extent3D* writeSize);
+ const TextureDataLayout& dataLayout,
+ const Extent3D& writeSize);
MaybeError ValidateSubmit(uint32_t commandCount, CommandBufferBase* const* commands) const;
MaybeError ValidateSignal(const Fence* fence, uint64_t signalValue) const;
diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
index c58f150..8fd4a5a 100644
--- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp
+++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
@@ -95,39 +95,6 @@
copySize.depth == srcSize.depth;
}
- void RecordCopyBufferToTextureFromTextureCopySplit(ID3D12GraphicsCommandList* commandList,
- const Texture2DCopySplit& baseCopySplit,
- Buffer* buffer,
- uint64_t baseOffset,
- uint64_t bufferBytesPerRow,
- Texture* texture,
- uint32_t textureMiplevel,
- uint32_t textureSlice,
- Aspect aspect) {
- const D3D12_TEXTURE_COPY_LOCATION textureLocation =
- ComputeTextureCopyLocationForTexture(texture, textureMiplevel, textureSlice,
- aspect);
-
- const uint64_t offset = baseCopySplit.offset + baseOffset;
-
- for (uint32_t i = 0; i < baseCopySplit.count; ++i) {
- const Texture2DCopySplit::CopyInfo& info = baseCopySplit.copies[i];
-
- // TODO(jiawei.shao@intel.com): pre-compute bufferLocation and sourceRegion as
- // members in Texture2DCopySplit::CopyInfo.
- const D3D12_TEXTURE_COPY_LOCATION bufferLocation =
- ComputeBufferLocationForCopyTextureRegion(texture, buffer->GetD3D12Resource(),
- info.bufferSize, offset,
- bufferBytesPerRow);
- const D3D12_BOX sourceRegion =
- ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
-
- commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
- info.textureOffset.y, info.textureOffset.z,
- &bufferLocation, &sourceRegion);
- }
- }
-
void RecordCopyTextureToBufferFromTextureCopySplit(ID3D12GraphicsCommandList* commandList,
const Texture2DCopySplit& baseCopySplit,
Buffer* buffer,
@@ -713,41 +680,11 @@
texture->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopyDst,
subresources);
- // See comments in ComputeTextureCopySplits() for more details.
- const TextureCopySplits copySplits = ComputeTextureCopySplits(
- copy->destination.origin, copy->copySize, texture->GetFormat(),
- copy->source.offset, copy->source.bytesPerRow, copy->source.rowsPerImage);
-
- const uint64_t bytesPerSlice =
- copy->source.bytesPerRow *
- (copy->source.rowsPerImage / texture->GetFormat().blockHeight);
-
- // copySplits.copies2D[1] is always calculated for the second copy slice with
- // extra "bytesPerSlice" copy offset compared with the first copy slice. So
- // here we use an array bufferOffsetsForNextSlice to record the extra offsets
- // for each copy slice: bufferOffsetsForNextSlice[0] is the extra offset for
- // the next copy slice that uses copySplits.copies2D[0], and
- // bufferOffsetsForNextSlice[1] is the extra offset for the next copy slice
- // that uses copySplits.copies2D[1].
- std::array<uint64_t, TextureCopySplits::kMaxTextureCopySplits>
- bufferOffsetsForNextSlice = {{0u, 0u}};
- for (uint32_t copySlice = 0; copySlice < copy->copySize.depth; ++copySlice) {
- const uint32_t splitIndex = copySlice % copySplits.copies2D.size();
-
- const Texture2DCopySplit& copySplitPerLayerBase =
- copySplits.copies2D[splitIndex];
- const uint64_t bufferOffsetForNextSlice =
- bufferOffsetsForNextSlice[splitIndex];
- const uint32_t copyTextureLayer = copySlice + copy->destination.origin.z;
-
- RecordCopyBufferToTextureFromTextureCopySplit(
- commandList, copySplitPerLayerBase, buffer, bufferOffsetForNextSlice,
- copy->source.bytesPerRow, texture, copy->destination.mipLevel,
- copyTextureLayer, subresources.aspects);
-
- bufferOffsetsForNextSlice[splitIndex] +=
- bytesPerSlice * copySplits.copies2D.size();
- }
+ // compute the copySplits and record the CopyTextureRegion commands
+ CopyBufferToTextureWithCopySplit(
+ commandContext, copy->destination, copy->copySize, texture,
+ buffer->GetD3D12Resource(), copy->source.offset, copy->source.bytesPerRow,
+ copy->source.rowsPerImage, subresources.aspects);
break;
}
diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp
index 7b73ccf..2e2e60e 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn_native/d3d12/DeviceD3D12.cpp
@@ -42,6 +42,7 @@
#include "dawn_native/d3d12/StagingDescriptorAllocatorD3D12.h"
#include "dawn_native/d3d12/SwapChainD3D12.h"
#include "dawn_native/d3d12/TextureD3D12.h"
+#include "dawn_native/d3d12/UtilsD3D12.h"
#include <sstream>
@@ -364,6 +365,33 @@
sourceOffset, size);
}
+ MaybeError Device::CopyFromStagingToTexture(const StagingBufferBase* source,
+ const TextureDataLayout& src,
+ TextureCopy* dst,
+ const Extent3D& copySizePixels) {
+ CommandRecordingContext* commandContext;
+ DAWN_TRY_ASSIGN(commandContext, GetPendingCommandContext());
+ Texture* texture = ToBackend(dst->texture.Get());
+ ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
+
+ SubresourceRange range = GetSubresourcesAffectedByCopy(*dst, copySizePixels);
+
+ if (IsCompleteSubresourceCopiedTo(texture, copySizePixels, dst->mipLevel)) {
+ texture->SetIsSubresourceContentInitialized(true, range);
+ } else {
+ texture->EnsureSubresourceContentInitialized(commandContext, range);
+ }
+
+ texture->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopyDst, range);
+
+ // compute the copySplits and record the CopyTextureRegion commands
+ CopyBufferToTextureWithCopySplit(commandContext, *dst, copySizePixels, texture,
+ ToBackend(source)->GetResource(), src.offset,
+ src.bytesPerRow, src.rowsPerImage, range.aspects);
+
+ return {};
+ }
+
void Device::DeallocateMemory(ResourceHeapAllocation& allocation) {
mResourceAllocatorManager->DeallocateMemory(allocation);
}
diff --git a/src/dawn_native/d3d12/DeviceD3D12.h b/src/dawn_native/d3d12/DeviceD3D12.h
index d4cb081..3ab0393 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.h
+++ b/src/dawn_native/d3d12/DeviceD3D12.h
@@ -20,6 +20,7 @@
#include "common/Constants.h"
#include "common/SerialQueue.h"
#include "dawn_native/BindingInfo.h"
+#include "dawn_native/Commands.h"
#include "dawn_native/Device.h"
#include "dawn_native/d3d12/CommandRecordingContext.h"
#include "dawn_native/d3d12/D3D12Info.h"
@@ -99,6 +100,11 @@
uint64_t destinationOffset,
uint64_t size);
+ MaybeError CopyFromStagingToTexture(const StagingBufferBase* source,
+ const TextureDataLayout& src,
+ TextureCopy* dst,
+ const Extent3D& copySizePixels);
+
ResultOrError<ResourceHeapAllocation> AllocateMemory(
D3D12_HEAP_TYPE heapType,
const D3D12_RESOURCE_DESC& resourceDescriptor,
diff --git a/src/dawn_native/d3d12/QueueD3D12.cpp b/src/dawn_native/d3d12/QueueD3D12.cpp
index 710e41f..c880892 100644
--- a/src/dawn_native/d3d12/QueueD3D12.cpp
+++ b/src/dawn_native/d3d12/QueueD3D12.cpp
@@ -14,6 +14,11 @@
#include "dawn_native/d3d12/QueueD3D12.h"
+#include "common/Math.h"
+#include "dawn_native/Buffer.h"
+#include "dawn_native/CommandValidation.h"
+#include "dawn_native/Commands.h"
+#include "dawn_native/DynamicUploader.h"
#include "dawn_native/d3d12/CommandBufferD3D12.h"
#include "dawn_native/d3d12/D3D12Error.h"
#include "dawn_native/d3d12/DeviceD3D12.h"
@@ -22,6 +27,46 @@
namespace dawn_native { namespace d3d12 {
+ namespace {
+ ResultOrError<UploadHandle> UploadTextureDataAligningBytesPerRow(
+ DeviceBase* device,
+ const void* data,
+ uint32_t alignedBytesPerRow,
+ uint32_t optimallyAlignedBytesPerRow,
+ uint32_t alignedRowsPerImage,
+ const TextureDataLayout& dataLayout,
+ const Format& textureFormat,
+ const Extent3D& writeSizePixel) {
+ uint32_t newDataSizeBytes = ComputeRequiredBytesInCopy(
+ textureFormat, writeSizePixel, optimallyAlignedBytesPerRow, alignedRowsPerImage);
+
+ UploadHandle uploadHandle;
+ DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
+ newDataSizeBytes, device->GetPendingCommandSerial()));
+ ASSERT(uploadHandle.mappedBuffer != nullptr);
+
+ uint8_t* dstPointer = static_cast<uint8_t*>(uploadHandle.mappedBuffer);
+ const uint8_t* srcPointer = static_cast<const uint8_t*>(data);
+ srcPointer += dataLayout.offset;
+
+ uint32_t alignedRowsPerImageInBlock = alignedRowsPerImage / textureFormat.blockHeight;
+ uint32_t dataRowsPerImageInBlock = dataLayout.rowsPerImage / textureFormat.blockHeight;
+ if (dataRowsPerImageInBlock == 0) {
+ dataRowsPerImageInBlock = writeSizePixel.height / textureFormat.blockHeight;
+ }
+
+ ASSERT(dataRowsPerImageInBlock >= alignedRowsPerImageInBlock);
+ uint64_t imageAdditionalStride =
+ dataLayout.bytesPerRow * (dataRowsPerImageInBlock - alignedRowsPerImageInBlock);
+
+ CopyTextureData(dstPointer, srcPointer, writeSizePixel.depth,
+ alignedRowsPerImageInBlock, imageAdditionalStride, alignedBytesPerRow,
+ optimallyAlignedBytesPerRow, dataLayout.bytesPerRow);
+
+ return uploadHandle;
+ }
+ } // namespace
+
Queue::Queue(Device* device) : QueueBase(device) {
}
@@ -47,4 +92,43 @@
return {};
}
+ MaybeError Queue::WriteTextureImpl(const TextureCopyView& destination,
+ const void* data,
+ const TextureDataLayout& dataLayout,
+ const Extent3D& writeSizePixel) {
+ const TexelBlockInfo& blockInfo =
+ destination.texture->GetFormat().GetTexelBlockInfo(destination.aspect);
+
+ // 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.
+ uint32_t alignedBytesPerRow =
+ (writeSizePixel.width) / blockInfo.blockWidth * blockInfo.blockByteSize;
+ uint32_t alignedRowsPerImage = writeSizePixel.height;
+ uint32_t optimallyAlignedBytesPerRow =
+ Align(alignedBytesPerRow, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+
+ UploadHandle uploadHandle;
+ DAWN_TRY_ASSIGN(
+ uploadHandle,
+ UploadTextureDataAligningBytesPerRow(
+ GetDevice(), data, alignedBytesPerRow, optimallyAlignedBytesPerRow,
+ alignedRowsPerImage, dataLayout, destination.texture->GetFormat(), writeSizePixel));
+
+ TextureDataLayout passDataLayout = dataLayout;
+ passDataLayout.offset = uploadHandle.startOffset;
+ passDataLayout.bytesPerRow = optimallyAlignedBytesPerRow;
+ passDataLayout.rowsPerImage = alignedRowsPerImage;
+
+ TextureCopy textureCopy;
+ textureCopy.texture = destination.texture;
+ textureCopy.mipLevel = destination.mipLevel;
+ textureCopy.origin = destination.origin;
+ textureCopy.aspect = ConvertAspect(destination.texture->GetFormat(), destination.aspect);
+
+ return ToBackend(GetDevice())
+ ->CopyFromStagingToTexture(uploadHandle.stagingBuffer, passDataLayout, &textureCopy,
+ writeSizePixel);
+ }
+
}} // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/QueueD3D12.h b/src/dawn_native/d3d12/QueueD3D12.h
index f211d0b..6b23a45 100644
--- a/src/dawn_native/d3d12/QueueD3D12.h
+++ b/src/dawn_native/d3d12/QueueD3D12.h
@@ -31,6 +31,10 @@
private:
MaybeError SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override;
+ MaybeError WriteTextureImpl(const TextureCopyView& destination,
+ const void* data,
+ const TextureDataLayout& dataLayout,
+ const Extent3D& writeSizePixel) override;
};
}} // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/UtilsD3D12.cpp b/src/dawn_native/d3d12/UtilsD3D12.cpp
index 97de204..6a3b4bc 100644
--- a/src/dawn_native/d3d12/UtilsD3D12.cpp
+++ b/src/dawn_native/d3d12/UtilsD3D12.cpp
@@ -15,6 +15,9 @@
#include "dawn_native/d3d12/UtilsD3D12.h"
#include "common/Assert.h"
+#include "dawn_native/Format.h"
+#include "dawn_native/d3d12/BufferD3D12.h"
+#include "dawn_native/d3d12/CommandRecordingContext.h"
#include <stringapiset.h>
@@ -65,7 +68,7 @@
D3D12_TEXTURE_COPY_LOCATION ComputeTextureCopyLocationForTexture(const Texture* texture,
uint32_t level,
uint32_t slice,
- Aspect aspect) {
+ const Aspect& aspect) {
D3D12_TEXTURE_COPY_LOCATION copyLocation;
copyLocation.pResource = texture->GetD3D12Resource();
copyLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
@@ -136,4 +139,78 @@
}
}
+ void RecordCopyBufferToTextureFromTextureCopySplit(ID3D12GraphicsCommandList* commandList,
+ const Texture2DCopySplit& baseCopySplit,
+ ID3D12Resource* bufferResource,
+ uint64_t baseOffsetBytes,
+ uint64_t bufferBytesPerRow,
+ Texture* texture,
+ uint32_t textureMiplevel,
+ uint32_t textureSlice,
+ const Aspect& aspect) {
+ const D3D12_TEXTURE_COPY_LOCATION textureLocation =
+ ComputeTextureCopyLocationForTexture(texture, textureMiplevel, textureSlice, aspect);
+
+ const uint64_t offsetBytes = baseCopySplit.offset + baseOffsetBytes;
+
+ for (uint32_t i = 0; i < baseCopySplit.count; ++i) {
+ const Texture2DCopySplit::CopyInfo& info = baseCopySplit.copies[i];
+
+ // TODO(jiawei.shao@intel.com): pre-compute bufferLocation and sourceRegion as
+ // members in Texture2DCopySplit::CopyInfo.
+ const D3D12_TEXTURE_COPY_LOCATION bufferLocation =
+ ComputeBufferLocationForCopyTextureRegion(texture, bufferResource, info.bufferSize,
+ offsetBytes, bufferBytesPerRow);
+ const D3D12_BOX sourceRegion =
+ ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
+
+ commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
+ info.textureOffset.y, info.textureOffset.z,
+ &bufferLocation, &sourceRegion);
+ }
+ }
+
+ void CopyBufferToTextureWithCopySplit(CommandRecordingContext* commandContext,
+ const TextureCopy& textureCopy,
+ const Extent3D& copySize,
+ Texture* texture,
+ ID3D12Resource* bufferResource,
+ const uint64_t offsetBytes,
+ const uint32_t bytesPerRow,
+ const uint32_t rowsPerImage,
+ const Aspect& aspects) {
+ // See comments in ComputeTextureCopySplits() for more details.
+ const TextureCopySplits copySplits =
+ ComputeTextureCopySplits(textureCopy.origin, copySize, texture->GetFormat(),
+ offsetBytes, bytesPerRow, rowsPerImage);
+
+ const uint64_t bytesPerSlice =
+ bytesPerRow * (rowsPerImage / texture->GetFormat().blockHeight);
+
+ // copySplits.copies2D[1] is always calculated for the second copy slice with
+ // extra "bytesPerSlice" copy offset compared with the first copy slice. So
+ // here we use an array bufferOffsetsForNextSlice to record the extra offsets
+ // for each copy slice: bufferOffsetsForNextSlice[0] is the extra offset for
+ // the next copy slice that uses copySplits.copies2D[0], and
+ // bufferOffsetsForNextSlice[1] is the extra offset for the next copy slice
+ // that uses copySplits.copies2D[1].
+ std::array<uint64_t, TextureCopySplits::kMaxTextureCopySplits> bufferOffsetsForNextSlice = {
+ {0u, 0u}};
+
+ for (uint32_t copySlice = 0; copySlice < copySize.depth; ++copySlice) {
+ const uint32_t splitIndex = copySlice % copySplits.copies2D.size();
+
+ const Texture2DCopySplit& copySplitPerLayerBase = copySplits.copies2D[splitIndex];
+ const uint64_t bufferOffsetForNextSlice = bufferOffsetsForNextSlice[splitIndex];
+ const uint32_t copyTextureLayer = copySlice + textureCopy.origin.z;
+
+ RecordCopyBufferToTextureFromTextureCopySplit(
+ commandContext->GetCommandList(), copySplitPerLayerBase, bufferResource,
+ bufferOffsetForNextSlice, bytesPerRow, texture, textureCopy.mipLevel,
+ copyTextureLayer, aspects);
+
+ bufferOffsetsForNextSlice[splitIndex] += bytesPerSlice * copySplits.copies2D.size();
+ }
+ }
+
}} // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/UtilsD3D12.h b/src/dawn_native/d3d12/UtilsD3D12.h
index 97bf74c..ad47570 100644
--- a/src/dawn_native/d3d12/UtilsD3D12.h
+++ b/src/dawn_native/d3d12/UtilsD3D12.h
@@ -15,6 +15,7 @@
#ifndef DAWNNATIVE_D3D12_UTILSD3D12_H_
#define DAWNNATIVE_D3D12_UTILSD3D12_H_
+#include "dawn_native/Commands.h"
#include "dawn_native/d3d12/BufferD3D12.h"
#include "dawn_native/d3d12/TextureCopySplitter.h"
#include "dawn_native/d3d12/TextureD3D12.h"
@@ -30,7 +31,7 @@
D3D12_TEXTURE_COPY_LOCATION ComputeTextureCopyLocationForTexture(const Texture* texture,
uint32_t level,
uint32_t slice,
- Aspect aspect);
+ const Aspect& aspect);
D3D12_TEXTURE_COPY_LOCATION ComputeBufferLocationForCopyTextureRegion(
const Texture* texture,
@@ -42,6 +43,26 @@
bool IsTypeless(DXGI_FORMAT format);
+ void RecordCopyBufferToTextureFromTextureCopySplit(ID3D12GraphicsCommandList* commandList,
+ const Texture2DCopySplit& baseCopySplit,
+ Buffer* buffer,
+ uint64_t baseOffset,
+ uint64_t bufferBytesPerRow,
+ Texture* texture,
+ uint32_t textureMiplevel,
+ uint32_t textureSlice,
+ const Aspect& aspect);
+
+ void CopyBufferToTextureWithCopySplit(CommandRecordingContext* commandContext,
+ const TextureCopy& textureCopy,
+ const Extent3D& copySize,
+ Texture* texture,
+ ID3D12Resource* bufferResource,
+ const uint64_t offset,
+ const uint32_t bytesPerRow,
+ const uint32_t rowsPerImage,
+ const Aspect& aspect);
+
}} // namespace dawn_native::d3d12
#endif // DAWNNATIVE_D3D12_UTILSD3D12_H_
diff --git a/src/dawn_native/metal/DeviceMTL.h b/src/dawn_native/metal/DeviceMTL.h
index 87a697b..8c4bc49 100644
--- a/src/dawn_native/metal/DeviceMTL.h
+++ b/src/dawn_native/metal/DeviceMTL.h
@@ -67,7 +67,7 @@
MaybeError CopyFromStagingToTexture(StagingBufferBase* source,
const TextureDataLayout& dataLayout,
TextureCopy* dst,
- const Extent3D copySize);
+ const Extent3D& copySizePixels);
private:
Device(AdapterBase* adapter, id<MTLDevice> mtlDevice, const DeviceDescriptor* descriptor);
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index fb7fdc3..79b4f81 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -271,7 +271,7 @@
MaybeError Device::CopyFromStagingToTexture(StagingBufferBase* source,
const TextureDataLayout& dataLayout,
TextureCopy* dst,
- const Extent3D copySize) {
+ const Extent3D& copySizePixels) {
Texture* texture = ToBackend(dst->texture.Get());
// This function assumes data is perfectly aligned. Otherwise, it might be necessary
@@ -280,19 +280,19 @@
uint32_t blockSize = blockInfo.blockByteSize;
uint32_t blockWidth = blockInfo.blockWidth;
uint32_t blockHeight = blockInfo.blockHeight;
- ASSERT(dataLayout.rowsPerImage == (copySize.height));
- ASSERT(dataLayout.bytesPerRow == (copySize.width) / blockWidth * blockSize);
+ ASSERT(dataLayout.rowsPerImage == (copySizePixels.height));
+ ASSERT(dataLayout.bytesPerRow == (copySizePixels.width) / blockWidth * blockSize);
- EnsureDestinationTextureInitialized(texture, *dst, copySize);
+ EnsureDestinationTextureInitialized(texture, *dst, copySizePixels);
// 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.
const Extent3D clampedSize =
- texture->ClampToMipLevelVirtualSize(dst->mipLevel, dst->origin, copySize);
+ texture->ClampToMipLevelVirtualSize(dst->mipLevel, dst->origin, copySizePixels);
const uint32_t copyBaseLayer = dst->origin.z;
- const uint32_t copyLayerCount = copySize.depth;
+ const uint32_t copyLayerCount = copySizePixels.depth;
const uint64_t bytesPerImage =
dataLayout.rowsPerImage * dataLayout.bytesPerRow / blockHeight;
diff --git a/src/dawn_native/metal/QueueMTL.h b/src/dawn_native/metal/QueueMTL.h
index bda47eb..55915c2 100644
--- a/src/dawn_native/metal/QueueMTL.h
+++ b/src/dawn_native/metal/QueueMTL.h
@@ -28,11 +28,10 @@
private:
MaybeError SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override;
- MaybeError WriteTextureImpl(const TextureCopyView* destination,
+ MaybeError WriteTextureImpl(const TextureCopyView& destination,
const void* data,
- size_t dataSize,
- const TextureDataLayout* dataLayout,
- const Extent3D* writeSize) override;
+ const TextureDataLayout& dataLayout,
+ const Extent3D& writeSizePixel) override;
};
}} // namespace dawn_native::metal
diff --git a/src/dawn_native/metal/QueueMTL.mm b/src/dawn_native/metal/QueueMTL.mm
index 237750c..44cbb0f 100644
--- a/src/dawn_native/metal/QueueMTL.mm
+++ b/src/dawn_native/metal/QueueMTL.mm
@@ -29,37 +29,36 @@
ResultOrError<UploadHandle> UploadTextureDataAligningBytesPerRow(
DeviceBase* device,
const void* data,
- size_t dataSize,
uint32_t alignedBytesPerRow,
uint32_t alignedRowsPerImage,
- const TextureDataLayout* dataLayout,
+ const TextureDataLayout& dataLayout,
const TexelBlockInfo& blockInfo,
- const Extent3D* writeSize) {
- uint32_t newDataSize = ComputeRequiredBytesInCopy(
- blockInfo, *writeSize, alignedBytesPerRow, alignedRowsPerImage);
+ const Extent3D& writeSizePixel) {
+ uint32_t newDataSizeBytes = ComputeRequiredBytesInCopy(
+ blockInfo, writeSizePixel, alignedBytesPerRow, alignedRowsPerImage);
UploadHandle uploadHandle;
DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
- newDataSize, device->GetPendingCommandSerial()));
+ newDataSizeBytes, device->GetPendingCommandSerial()));
ASSERT(uploadHandle.mappedBuffer != nullptr);
uint8_t* dstPointer = static_cast<uint8_t*>(uploadHandle.mappedBuffer);
const uint8_t* srcPointer = static_cast<const uint8_t*>(data);
- srcPointer += dataLayout->offset;
+ srcPointer += dataLayout.offset;
uint32_t alignedRowsPerImageInBlock = alignedRowsPerImage / blockInfo.blockHeight;
- uint32_t dataRowsPerImageInBlock = dataLayout->rowsPerImage / blockInfo.blockHeight;
+ uint32_t dataRowsPerImageInBlock = dataLayout.rowsPerImage / blockInfo.blockHeight;
if (dataRowsPerImageInBlock == 0) {
- dataRowsPerImageInBlock = writeSize->height / blockInfo.blockHeight;
+ dataRowsPerImageInBlock = writeSizePixel.height / blockInfo.blockHeight;
}
ASSERT(dataRowsPerImageInBlock >= alignedRowsPerImageInBlock);
uint64_t imageAdditionalStride =
- dataLayout->bytesPerRow * (dataRowsPerImageInBlock - alignedRowsPerImageInBlock);
+ dataLayout.bytesPerRow * (dataRowsPerImageInBlock - alignedRowsPerImageInBlock);
- CopyTextureData(dstPointer, srcPointer, writeSize->depth, alignedRowsPerImageInBlock,
- imageAdditionalStride, alignedBytesPerRow, alignedBytesPerRow,
- dataLayout->bytesPerRow);
+ CopyTextureData(dstPointer, srcPointer, writeSizePixel.depth,
+ alignedRowsPerImageInBlock, imageAdditionalStride, alignedBytesPerRow,
+ alignedBytesPerRow, dataLayout.bytesPerRow);
return uploadHandle;
}
@@ -86,40 +85,40 @@
// We don't write from the CPU to the texture directly which can be done in Metal using the
// replaceRegion function, because the function requires a non-private storage mode and Dawn
// sets the private storage mode by default for all textures except IOSurfaces on macOS.
- MaybeError Queue::WriteTextureImpl(const TextureCopyView* destination,
+ MaybeError Queue::WriteTextureImpl(const TextureCopyView& destination,
const void* data,
- size_t dataSize,
- const TextureDataLayout* dataLayout,
- const Extent3D* writeSize) {
+ const TextureDataLayout& dataLayout,
+ const Extent3D& writeSizePixel) {
const TexelBlockInfo& blockInfo =
- destination->texture->GetFormat().GetTexelBlockInfo(destination->aspect);
+ destination.texture->GetFormat().GetTexelBlockInfo(destination.aspect);
// We are only copying the part of the data that will appear in the texture.
- // Note that validating texture copy range ensures that writeSize->width and
- // writeSize->height are multiples of blockWidth and blockHeight respectively.
+ // Note that validating texture copy range ensures that writeSizePixel->width and
+ // writeSizePixel->height are multiples of blockWidth and blockHeight respectively.
uint32_t alignedBytesPerRow =
- (writeSize->width) / blockInfo.blockWidth * blockInfo.blockByteSize;
- uint32_t alignedRowsPerImage = writeSize->height;
+ (writeSizePixel.width) / blockInfo.blockWidth * blockInfo.blockByteSize;
+ uint32_t alignedRowsPerImage = writeSizePixel.height;
UploadHandle uploadHandle;
- DAWN_TRY_ASSIGN(uploadHandle, UploadTextureDataAligningBytesPerRow(
- GetDevice(), data, dataSize, alignedBytesPerRow,
- alignedRowsPerImage, dataLayout, blockInfo, writeSize));
+ DAWN_TRY_ASSIGN(uploadHandle,
+ UploadTextureDataAligningBytesPerRow(GetDevice(), data, alignedBytesPerRow,
+ alignedRowsPerImage, dataLayout,
+ blockInfo, writeSizePixel));
- TextureDataLayout passDataLayout = *dataLayout;
+ TextureDataLayout passDataLayout = dataLayout;
passDataLayout.offset = uploadHandle.startOffset;
passDataLayout.bytesPerRow = alignedBytesPerRow;
passDataLayout.rowsPerImage = alignedRowsPerImage;
TextureCopy textureCopy;
- textureCopy.texture = destination->texture;
- textureCopy.mipLevel = destination->mipLevel;
- textureCopy.origin = destination->origin;
- textureCopy.aspect = ConvertAspect(destination->texture->GetFormat(), destination->aspect);
+ textureCopy.texture = destination.texture;
+ textureCopy.mipLevel = destination.mipLevel;
+ textureCopy.origin = destination.origin;
+ textureCopy.aspect = ConvertAspect(destination.texture->GetFormat(), destination.aspect);
return ToBackend(GetDevice())
->CopyFromStagingToTexture(uploadHandle.stagingBuffer, passDataLayout, &textureCopy,
- *writeSize);
+ writeSizePixel);
}
}} // namespace dawn_native::metal
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index f6afcfd..1b5e197 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -617,20 +617,21 @@
MaybeError Device::CopyFromStagingToTexture(StagingBufferBase* source,
const TextureDataLayout& src,
TextureCopy* dst,
- const Extent3D copySize) {
+ const Extent3D& copySizePixels) {
// There is no need of a barrier to make host writes available and visible to the copy
// operation for HOST_COHERENT memory. The Vulkan spec for vkQueueSubmit describes that it
// does an implicit availability, visibility and domain operation.
CommandRecordingContext* recordingContext = GetPendingRecordingContext();
- VkBufferImageCopy region = ComputeBufferImageCopyRegion(src, *dst, copySize);
+ VkBufferImageCopy region = ComputeBufferImageCopyRegion(src, *dst, copySizePixels);
VkImageSubresourceLayers subresource = region.imageSubresource;
ASSERT(dst->texture->GetDimension() == wgpu::TextureDimension::e2D);
- SubresourceRange range = GetSubresourcesAffectedByCopy(*dst, copySize);
+ SubresourceRange range = GetSubresourcesAffectedByCopy(*dst, copySizePixels);
- if (IsCompleteSubresourceCopiedTo(dst->texture.Get(), copySize, subresource.mipLevel)) {
+ if (IsCompleteSubresourceCopiedTo(dst->texture.Get(), copySizePixels,
+ subresource.mipLevel)) {
// Since texture has been overwritten, it has been "initialized"
dst->texture->SetIsSubresourceContentInitialized(true, range);
} else {
diff --git a/src/dawn_native/vulkan/DeviceVk.h b/src/dawn_native/vulkan/DeviceVk.h
index 851a1e7..89ec1ea 100644
--- a/src/dawn_native/vulkan/DeviceVk.h
+++ b/src/dawn_native/vulkan/DeviceVk.h
@@ -91,7 +91,7 @@
MaybeError CopyFromStagingToTexture(StagingBufferBase* source,
const TextureDataLayout& src,
TextureCopy* dst,
- const Extent3D copySize);
+ const Extent3D& copySizePixels);
ResultOrError<ResourceMemoryAllocation> AllocateMemory(VkMemoryRequirements requirements,
bool mappable);
diff --git a/src/dawn_native/vulkan/QueueVk.cpp b/src/dawn_native/vulkan/QueueVk.cpp
index 227ccb4..3842652 100644
--- a/src/dawn_native/vulkan/QueueVk.cpp
+++ b/src/dawn_native/vulkan/QueueVk.cpp
@@ -31,15 +31,14 @@
ResultOrError<UploadHandle> UploadTextureDataAligningBytesPerRow(
DeviceBase* device,
const void* data,
- size_t dataSize,
uint32_t alignedBytesPerRow,
uint32_t optimallyAlignedBytesPerRow,
uint32_t alignedRowsPerImage,
- const TextureDataLayout* dataLayout,
+ const TextureDataLayout& dataLayout,
const TexelBlockInfo& blockInfo,
- const Extent3D* writeSize) {
- uint32_t newDataSize = ComputeRequiredBytesInCopy(
- blockInfo, *writeSize, optimallyAlignedBytesPerRow, alignedRowsPerImage);
+ const Extent3D& writeSizePixel) {
+ uint32_t newDataSizeBytes = ComputeRequiredBytesInCopy(
+ blockInfo, writeSizePixel, optimallyAlignedBytesPerRow, alignedRowsPerImage);
uint64_t optimalOffsetAlignment =
ToBackend(device)
@@ -48,18 +47,18 @@
UploadHandle uploadHandle;
DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
- newDataSize + optimalOffsetAlignment - 1,
+ newDataSizeBytes + optimalOffsetAlignment - 1,
device->GetPendingCommandSerial()));
ASSERT(uploadHandle.mappedBuffer != nullptr);
uint8_t* dstPointer = static_cast<uint8_t*>(uploadHandle.mappedBuffer);
const uint8_t* srcPointer = static_cast<const uint8_t*>(data);
- srcPointer += dataLayout->offset;
+ srcPointer += dataLayout.offset;
uint32_t alignedRowsPerImageInBlock = alignedRowsPerImage / blockInfo.blockHeight;
- uint32_t dataRowsPerImageInBlock = dataLayout->rowsPerImage / blockInfo.blockHeight;
+ uint32_t dataRowsPerImageInBlock = dataLayout.rowsPerImage / blockInfo.blockHeight;
if (dataRowsPerImageInBlock == 0) {
- dataRowsPerImageInBlock = writeSize->height / blockInfo.blockHeight;
+ dataRowsPerImageInBlock = writeSizePixel.height / blockInfo.blockHeight;
}
uint64_t additionalOffset =
@@ -69,11 +68,11 @@
ASSERT(dataRowsPerImageInBlock >= alignedRowsPerImageInBlock);
uint64_t imageAdditionalStride =
- dataLayout->bytesPerRow * (dataRowsPerImageInBlock - alignedRowsPerImageInBlock);
+ dataLayout.bytesPerRow * (dataRowsPerImageInBlock - alignedRowsPerImageInBlock);
- CopyTextureData(dstPointer, srcPointer, writeSize->depth, alignedRowsPerImageInBlock,
- imageAdditionalStride, alignedBytesPerRow, optimallyAlignedBytesPerRow,
- dataLayout->bytesPerRow);
+ CopyTextureData(dstPointer, srcPointer, writeSizePixel.depth,
+ alignedRowsPerImageInBlock, imageAdditionalStride, alignedBytesPerRow,
+ optimallyAlignedBytesPerRow, dataLayout.bytesPerRow);
return uploadHandle;
}
@@ -105,20 +104,19 @@
return {};
}
- MaybeError Queue::WriteTextureImpl(const TextureCopyView* destination,
+ MaybeError Queue::WriteTextureImpl(const TextureCopyView& destination,
const void* data,
- size_t dataSize,
- const TextureDataLayout* dataLayout,
- const Extent3D* writeSize) {
+ const TextureDataLayout& dataLayout,
+ const Extent3D& writeSizePixel) {
const TexelBlockInfo& blockInfo =
- destination->texture->GetFormat().GetTexelBlockInfo(destination->aspect);
+ destination.texture->GetFormat().GetTexelBlockInfo(destination.aspect);
// We are only copying the part of the data that will appear in the texture.
- // Note that validating texture copy range ensures that writeSize->width and
- // writeSize->height are multiples of blockWidth and blockHeight respectively.
+ // Note that validating texture copy range ensures that writeSizePixel->width and
+ // writeSizePixel->height are multiples of blockWidth and blockHeight respectively.
uint32_t alignedBytesPerRow =
- (writeSize->width) / blockInfo.blockWidth * blockInfo.blockByteSize;
- uint32_t alignedRowsPerImage = writeSize->height;
+ (writeSizePixel.width) / blockInfo.blockWidth * blockInfo.blockByteSize;
+ uint32_t alignedRowsPerImage = writeSizePixel.height;
uint32_t optimalBytesPerRowAlignment =
ToBackend(GetDevice())
@@ -128,24 +126,24 @@
Align(alignedBytesPerRow, optimalBytesPerRowAlignment);
UploadHandle uploadHandle;
- DAWN_TRY_ASSIGN(uploadHandle, UploadTextureDataAligningBytesPerRow(
- GetDevice(), data, dataSize, alignedBytesPerRow,
- optimallyAlignedBytesPerRow, alignedRowsPerImage,
- dataLayout, blockInfo, writeSize));
+ DAWN_TRY_ASSIGN(uploadHandle,
+ UploadTextureDataAligningBytesPerRow(
+ GetDevice(), data, alignedBytesPerRow, optimallyAlignedBytesPerRow,
+ alignedRowsPerImage, dataLayout, blockInfo, writeSizePixel));
- TextureDataLayout passDataLayout = *dataLayout;
+ TextureDataLayout passDataLayout = dataLayout;
passDataLayout.offset = uploadHandle.startOffset;
passDataLayout.bytesPerRow = optimallyAlignedBytesPerRow;
passDataLayout.rowsPerImage = alignedRowsPerImage;
TextureCopy textureCopy;
- textureCopy.texture = destination->texture;
- textureCopy.mipLevel = destination->mipLevel;
- textureCopy.origin = destination->origin;
- textureCopy.aspect = ConvertAspect(destination->texture->GetFormat(), destination->aspect);
+ textureCopy.texture = destination.texture;
+ textureCopy.mipLevel = destination.mipLevel;
+ textureCopy.origin = destination.origin;
+ textureCopy.aspect = ConvertAspect(destination.texture->GetFormat(), destination.aspect);
return ToBackend(GetDevice())
->CopyFromStagingToTexture(uploadHandle.stagingBuffer, passDataLayout, &textureCopy,
- *writeSize);
+ writeSizePixel);
}
}} // namespace dawn_native::vulkan
diff --git a/src/dawn_native/vulkan/QueueVk.h b/src/dawn_native/vulkan/QueueVk.h
index bcfdbda..34a0e6a 100644
--- a/src/dawn_native/vulkan/QueueVk.h
+++ b/src/dawn_native/vulkan/QueueVk.h
@@ -31,11 +31,10 @@
using QueueBase::QueueBase;
MaybeError SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override;
- MaybeError WriteTextureImpl(const TextureCopyView* destination,
+ MaybeError WriteTextureImpl(const TextureCopyView& destination,
const void* data,
- size_t dataSize,
- const TextureDataLayout* dataLayout,
- const Extent3D* writeSize) override;
+ const TextureDataLayout& dataLayout,
+ const Extent3D& writeSizePixel) override;
};
}} // namespace dawn_native::vulkan
diff --git a/src/tests/end2end/CompressedTextureFormatTests.cpp b/src/tests/end2end/CompressedTextureFormatTests.cpp
index 2054dfa..a6ae419 100644
--- a/src/tests/end2end/CompressedTextureFormatTests.cpp
+++ b/src/tests/end2end/CompressedTextureFormatTests.cpp
@@ -1179,4 +1179,7 @@
}
}
-DAWN_INSTANTIATE_TEST(CompressedTextureWriteTextureTest, MetalBackend(), VulkanBackend());
\ No newline at end of file
+DAWN_INSTANTIATE_TEST(CompressedTextureWriteTextureTest,
+ MetalBackend(),
+ VulkanBackend(),
+ D3D12Backend());
\ No newline at end of file
diff --git a/src/tests/end2end/QueueTests.cpp b/src/tests/end2end/QueueTests.cpp
index edf9ccf..2ac7c8c 100644
--- a/src/tests/end2end/QueueTests.cpp
+++ b/src/tests/end2end/QueueTests.cpp
@@ -522,4 +522,4 @@
}
}
-DAWN_INSTANTIATE_TEST(QueueWriteTextureTests, MetalBackend(), VulkanBackend());
+DAWN_INSTANTIATE_TEST(QueueWriteTextureTests, MetalBackend(), VulkanBackend(), D3D12Backend());
diff --git a/src/tests/end2end/TextureZeroInitTests.cpp b/src/tests/end2end/TextureZeroInitTests.cpp
index b4646f5..7289757 100644
--- a/src/tests/end2end/TextureZeroInitTests.cpp
+++ b/src/tests/end2end/TextureZeroInitTests.cpp
@@ -1382,7 +1382,7 @@
// In this test WriteTexture fully overwrites a texture
TEST_P(TextureZeroInitTest, WriteWholeTexture) {
// TODO(dawn:483): Remove this condition after implementing WriteTexture in those backends.
- DAWN_SKIP_TEST_IF(IsOpenGL() || IsD3D12());
+ DAWN_SKIP_TEST_IF(IsOpenGL());
wgpu::TextureDescriptor descriptor = CreateTextureDescriptor(
1, 1, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc, kColorFormat);
@@ -1417,7 +1417,7 @@
// half.
TEST_P(TextureZeroInitTest, WriteTextureHalf) {
// TODO(dawn:483): Remove this condition after implementing WriteTexture in those backends.
- DAWN_SKIP_TEST_IF(IsOpenGL() || IsD3D12());
+ DAWN_SKIP_TEST_IF(IsOpenGL());
wgpu::TextureDescriptor descriptor = CreateTextureDescriptor(
4, 1,
@@ -1457,7 +1457,7 @@
// is needed for neither the subresources involved in the write nor the other subresources.
TEST_P(TextureZeroInitTest, WriteWholeTextureArray) {
// TODO(dawn:483): Remove this condition after implementing WriteTexture in those backends.
- DAWN_SKIP_TEST_IF(IsOpenGL() || IsD3D12());
+ DAWN_SKIP_TEST_IF(IsOpenGL());
wgpu::TextureDescriptor descriptor = CreateTextureDescriptor(
1, 6, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc, kColorFormat);
@@ -1500,7 +1500,7 @@
// half.
TEST_P(TextureZeroInitTest, WriteTextureArrayHalf) {
// TODO(dawn:483): Remove this condition after implementing WriteTexture in those backends.
- DAWN_SKIP_TEST_IF(IsOpenGL() || IsD3D12());
+ DAWN_SKIP_TEST_IF(IsOpenGL());
wgpu::TextureDescriptor descriptor = CreateTextureDescriptor(
4, 6,
@@ -1547,7 +1547,7 @@
// In this test WriteTexture fully overwrites a texture at mip level.
TEST_P(TextureZeroInitTest, WriteWholeTextureAtMipLevel) {
// TODO(dawn:483): Remove this condition after implementing WriteTexture in those backends.
- DAWN_SKIP_TEST_IF(IsOpenGL() || IsD3D12());
+ DAWN_SKIP_TEST_IF(IsOpenGL());
wgpu::TextureDescriptor descriptor = CreateTextureDescriptor(
4, 1, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc, kColorFormat);
@@ -1586,7 +1586,7 @@
// other half.
TEST_P(TextureZeroInitTest, WriteTextureHalfAtMipLevel) {
// TODO(dawn:483): Remove this condition after implementing WriteTexture in those backends.
- DAWN_SKIP_TEST_IF(IsOpenGL() || IsD3D12());
+ DAWN_SKIP_TEST_IF(IsOpenGL());
wgpu::TextureDescriptor descriptor = CreateTextureDescriptor(
4, 1,